blob: 70c952233f950a1479bcf304d710ff62f10ae01c [file] [log] [blame]
/**
* Copyright (c) 2011 NVIDIA Corporation. All rights reserved.
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
/*
* set.c - State setting support for the cbootimage tool
*/
#include "set.h"
#include "cbootimage.h"
#include "crypto.h"
#include "data_layout.h"
/*
* Function prototypes
*
* ParseXXX() parses XXX in the input
* SetXXX() sets state based on the parsing results but does not perform
* any parsing of its own
* A ParseXXX() function may call other parse functions and set functions.
* A SetXXX() function may not call any parseing functions.
*/
#define CASE_DEVICE_VALUE(prefix, id) \
case token_##id: \
(void)context->bctlib.setdev_param(index, \
nvbct_lib_id_##prefix##_##id, \
value, \
context->bct); \
break
#define CASE_SDRAM_VALUE(id) \
case token_##id: \
(void)context->bctlib.set_sdram_params(index, \
nvbct_lib_id_sdram_##id, \
value, \
context->bct); \
break
#define DEFAULT() \
default: \
printf("Unexpected token %d at line %d\n", \
token, __LINE__); \
return 1
int
read_from_image(char *filename,
u_int32_t page_size,
u_int8_t **image,
u_int32_t *storage_size,
u_int32_t *actual_size,
file_type f_type)
{
int result = 0; /* 0 = success, 1 = failure */
FILE *fp;
struct stat stats;
fp = fopen(filename, "r");
if (fp == NULL) {
result = 1;
return result;
}
if (stat(filename, &stats) != 0) {
printf("Error: Unable to query info on bootloader path %s\n",
filename);
result = 1;
goto cleanup;
}
*actual_size = (u_int32_t)stats.st_size;
*storage_size =
(u_int32_t)(ICEIL(stats.st_size, page_size) * page_size);
if (f_type == file_type_bl) {
if (stats.st_size > MAX_BOOTLOADER_SIZE) {
printf("Error: Bootloader file %s is too large.\n",
filename);
result = 1;
goto cleanup;
}
/* Workaround for a bug in release 1.0 of the boot rom.
* Any BL whose padded size is an integral multiple of page size
* has its length extended by 16 bytes to bump it to end on a
* partial page.
*/
if ((*storage_size - *actual_size) < 16) {
*actual_size += 16;
*storage_size += page_size;
}
}
*image = malloc(*storage_size);
if (*image == NULL) {
result = 1;
goto cleanup;
}
memset(*image, 0, *storage_size);
if (fread(*image, 1, (size_t)stats.st_size, fp) != stats.st_size) {
result = 1;
goto cleanup;
}
cleanup:
fclose(fp);
return result;
}
/*
* set_bootloader(): Processes commands to set a bootloader.
*/
int
set_bootloader(build_image_context *context,
char *filename,
u_int32_t load_addr,
u_int32_t entry_point)
{
context->newbl_filename = filename;
context->newbl_load_addr = load_addr;
context->newbl_entry_point = entry_point;
return update_bl(context);
}
#define DEFAULT() \
default: \
printf("Unexpected token %d at line %d\n", \
token, __LINE__); \
return 1
/*
* context_set_array(): Sets an array value.
*/
int
context_set_array(build_image_context *context,
u_int32_t index,
parse_token token,
u_int32_t value)
{
assert(context != NULL);
assert(context->bct != NULL);
switch (token) {
case token_attribute:
(void)context->bctlib.setbl_param(index,
nvbct_lib_id_bl_attribute,
&value,
context->bct);
break;
case token_dev_type:
(void)context->bctlib.setdev_param(index,
nvbct_lib_id_dev_type,
value,
context->bct);
break;
DEFAULT();
}
return 0;
}
/*
* context_set_value(): General handler for setting values in config files.
*/
int context_set_value(build_image_context *context,
parse_token token,
u_int32_t value)
{
assert(context != NULL);
switch (token) {
case token_attribute:
context->newbl_attr = value;
break;
case token_block_size:
context->block_size = value;
context->block_size_log2 = log2(value);
if (context->memory != NULL) {
printf("Error: Too late to change block size.\n");
return 1;
}
if (value != (u_int32_t)(1 << context->block_size_log2)) {
printf("Error: Block size must be a power of 2.\n");
return 1;
}
context->pages_per_blk= 1 << (context->block_size_log2-
context->page_size_log2);
SET_VALUE(block_size_log2, context->block_size_log2);
break;
case token_partition_size:
if (context->memory != NULL) {
printf("Error: Too late to change block size.\n");
return 1;
}
context->partition_size= value;
SET_VALUE(partition_size, value);
break;
case token_page_size:
context->page_size = value;
context->page_size_log2 = log2(value);
context->pages_per_blk= 1 << (context->block_size_log2-
context->page_size_log2);
SET_VALUE(page_size_log2, context->page_size_log2);
break;
case token_redundancy:
context->redundancy = value;
break;
case token_version:
context->version = value;
break;
DEFAULT();
}
return 0;
}
int
set_addon_filename(build_image_context *context,
char *filename,
int index)
{
struct addon_item_rec **current;
int i;
current = &(context->addon_tbl.addon_item_list);
for(i = 0; i <= index; i++) {
if (*current == NULL) {
(*current) = malloc(sizeof(struct addon_item_rec));
if (*current == NULL)
return -ENOMEM;
memset((*current), 0, sizeof(struct addon_item_rec));
memcpy((*current)->addon_filename,
filename, MAX_BUFFER);
(*current)->item_index = index;
(*current)->next = NULL;
context->addon_tbl.addon_item_no++;
} else if ((*current)->item_index == index) {
memcpy((*current)->addon_filename,
filename, MAX_BUFFER);
} else
current = &((*current)->next);
}
return 0;
}
int set_addon_attr(build_image_context *context,
u_int32_t file_attr,
int index)
{
struct addon_item_rec **current;
int i;
current = &(context->addon_tbl.addon_item_list);
for(i = 0; i <= index; i++) {
if (*current == NULL) {
(*current) = malloc(sizeof(struct addon_item_rec));
if (*current == NULL)
return -ENOMEM;
memset((*current), 0, sizeof(struct addon_item_rec));
(*current)->item.attribute= file_attr;
(*current)->item_index = index;
(*current)->next = NULL;
context->addon_tbl.addon_item_no++;
} else if ((*current)->item_index == index) {
(*current)->item.attribute= file_attr;
} else
current = &((*current)->next);
}
return 0;
}
int set_unique_name(build_image_context *context, char *uname, int index)
{
struct addon_item_rec **current;
int i;
current = &(context->addon_tbl.addon_item_list);
for(i = 0; i <= index; i++) {
if (*current == NULL) {
(*current) = malloc(sizeof(struct addon_item_rec));
if (*current == NULL)
return -ENOMEM;
memset((*current), 0, sizeof(struct addon_item_rec));
memcpy((*current)->item.unique_name, uname, 4);
(*current)->item_index = index;
(*current)->next = NULL;
context->addon_tbl.addon_item_no++;
} else if ((*current)->item_index == index) {
memcpy((*current)->item.unique_name, uname, 4);
} else
current = &((*current)->next);
}
return 0;
}
int
set_other_field(build_image_context *context,
char *other_str,
int other,
int index)
{
struct addon_item_rec **current;
int i;
current = &(context->addon_tbl.addon_item_list);
for(i = 0; i <= index; i++) {
if (*current == NULL) {
(*current) = malloc(sizeof(struct addon_item_rec));
if (*current == NULL)
return -ENOMEM;
memset((*current), 0, sizeof(struct addon_item_rec));
if (other_str == NULL)
(*current)->item.reserve[0] = other;
else
memcpy((*current)->item.reserve,
other_str, 16);
(*current)->item_index = index;
(*current)->next = NULL;
context->addon_tbl.addon_item_no++;
} else if ((*current)->item_index == index) {
if (other_str == NULL)
(*current)->item.reserve[0] = other;
else
memcpy((*current)->item.reserve,
other_str, 16);
} else
current = &((*current)->next);
}
return 0;
}
static void
update_num_param_sets(build_image_context *context, u_int32_t index)
{
u_int32_t num_params;
GET_VALUE(num_param_sets, &num_params);
num_params = NV_MAX(num_params, index + 1);
SET_VALUE(num_param_sets, num_params);
}
/*
* set_nand_param(): Processes commands to set Nand parameters.
*/
int
set_nand_param(build_image_context *context,
u_int32_t index,
parse_token token,
u_int32_t value)
{
assert(context != NULL);
assert(context->bct != NULL);
update_num_param_sets(context, index);
switch (token) {
CASE_DEVICE_VALUE(nand, clock_divider);
CASE_DEVICE_VALUE(nand, nand_timing);
CASE_DEVICE_VALUE(nand, nand_timing2);
CASE_DEVICE_VALUE(nand, block_size_log2);
CASE_DEVICE_VALUE(nand, page_size_log2);
DEFAULT();
}
return 0;
}
/*
* set_sdmmc_param(): Processes commands to set MoviNand parameters.
*/
int
set_sdmmc_param(build_image_context *context,
u_int32_t index,
parse_token token,
u_int32_t value)
{
assert(context != NULL);
assert(context->bct != NULL);
update_num_param_sets(context, index);
switch (token) {
CASE_DEVICE_VALUE(sdmmc, clock_divider);
CASE_DEVICE_VALUE(sdmmc, data_width);
CASE_DEVICE_VALUE(sdmmc, max_power_class_supported);
DEFAULT();
}
return 0;
}
/*
* set_spiflash_param(): Processes commands to set SpiFlash parameters.
*/
int
set_spiflash_param(build_image_context *context,
u_int32_t index,
parse_token token,
u_int32_t value)
{
assert(context != NULL);
assert(context->bct != NULL);
update_num_param_sets(context, index);
switch (token) {
CASE_DEVICE_VALUE(spiflash, clock_divider);
CASE_DEVICE_VALUE(spiflash, clock_source);
CASE_DEVICE_VALUE(spiflash, read_command_type_fast);
DEFAULT();
}
return 0;
}
int
set_sdram_param(build_image_context *context,
u_int32_t index,
parse_token token,
u_int32_t value)
{
u_int32_t num_sdram_sets;
assert(context != NULL);
assert(context->bct != NULL);
// Update the number of SDRAM parameter sets.
GET_VALUE(num_sdram_sets, &num_sdram_sets);
num_sdram_sets = NV_MAX(num_sdram_sets, index + 1);
SET_VALUE(num_sdram_sets, num_sdram_sets);
switch (token) {
CASE_SDRAM_VALUE(memory_type);
CASE_SDRAM_VALUE(pllm_charge_pump_setup_ctrl);
CASE_SDRAM_VALUE(pllm_loop_filter_setup_ctrl);
CASE_SDRAM_VALUE(pllm_input_divider);
CASE_SDRAM_VALUE(pllm_feedback_divider);
CASE_SDRAM_VALUE(pllm_post_divider);
CASE_SDRAM_VALUE(pllm_stable_time);
CASE_SDRAM_VALUE(emc_clock_divider);
CASE_SDRAM_VALUE(emc_auto_cal_interval);
CASE_SDRAM_VALUE(emc_auto_cal_config);
CASE_SDRAM_VALUE(emc_auto_cal_wait);
CASE_SDRAM_VALUE(emc_pin_program_wait);
CASE_SDRAM_VALUE(emc_rc);
CASE_SDRAM_VALUE(emc_rfc);
CASE_SDRAM_VALUE(emc_ras);
CASE_SDRAM_VALUE(emc_rp);
CASE_SDRAM_VALUE(emc_r2w);
CASE_SDRAM_VALUE(emc_w2r);
CASE_SDRAM_VALUE(emc_r2p);
CASE_SDRAM_VALUE(emc_w2p);
CASE_SDRAM_VALUE(emc_rd_rcd);
CASE_SDRAM_VALUE(emc_wr_rcd);
CASE_SDRAM_VALUE(emc_rrd);
CASE_SDRAM_VALUE(emc_rext);
CASE_SDRAM_VALUE(emc_wdv);
CASE_SDRAM_VALUE(emc_quse);
CASE_SDRAM_VALUE(emc_qrst);
CASE_SDRAM_VALUE(emc_qsafe);
CASE_SDRAM_VALUE(emc_rdv);
CASE_SDRAM_VALUE(emc_refresh);
CASE_SDRAM_VALUE(emc_burst_refresh_num);
CASE_SDRAM_VALUE(emc_pdex2wr);
CASE_SDRAM_VALUE(emc_pdex2rd);
CASE_SDRAM_VALUE(emc_pchg2pden);
CASE_SDRAM_VALUE(emc_act2pden);
CASE_SDRAM_VALUE(emc_ar2pden);
CASE_SDRAM_VALUE(emc_rw2pden);
CASE_SDRAM_VALUE(emc_txsr);
CASE_SDRAM_VALUE(emc_tcke);
CASE_SDRAM_VALUE(emc_tfaw);
CASE_SDRAM_VALUE(emc_trpab);
CASE_SDRAM_VALUE(emc_tclkstable);
CASE_SDRAM_VALUE(emc_tclkstop);
CASE_SDRAM_VALUE(emc_trefbw);
CASE_SDRAM_VALUE(emc_quse_extra);
CASE_SDRAM_VALUE(emc_fbio_cfg1);
CASE_SDRAM_VALUE(emc_fbio_dqsib_dly);
CASE_SDRAM_VALUE(emc_fbio_dqsib_dly_msb);
CASE_SDRAM_VALUE(emc_fbio_quse_dly);
CASE_SDRAM_VALUE(emc_fbio_quse_dly_msb);
CASE_SDRAM_VALUE(emc_fbio_cfg5);
CASE_SDRAM_VALUE(emc_fbio_cfg6);
CASE_SDRAM_VALUE(emc_fbio_spare);
CASE_SDRAM_VALUE(emc_mrs);
CASE_SDRAM_VALUE(emc_emrs);
CASE_SDRAM_VALUE(emc_mrw1);
CASE_SDRAM_VALUE(emc_mrw2);
CASE_SDRAM_VALUE(emc_mrw3);
CASE_SDRAM_VALUE(emc_mrw_reset_command);
CASE_SDRAM_VALUE(emc_mrw_reset_ninit_wait);
CASE_SDRAM_VALUE(emc_adr_cfg);
CASE_SDRAM_VALUE(emc_adr_cfg1);
CASE_SDRAM_VALUE(mc_emem_Cfg);
CASE_SDRAM_VALUE(mc_lowlatency_config);
CASE_SDRAM_VALUE(emc_cfg);
CASE_SDRAM_VALUE(emc_cfg2);
CASE_SDRAM_VALUE(emc_dbg);
CASE_SDRAM_VALUE(ahb_arbitration_xbar_ctrl);
CASE_SDRAM_VALUE(emc_cfg_dig_dll);
CASE_SDRAM_VALUE(emc_dll_xform_dqs);
CASE_SDRAM_VALUE(emc_dll_xform_quse);
CASE_SDRAM_VALUE(warm_boot_wait);
CASE_SDRAM_VALUE(emc_ctt_term_ctrl);
CASE_SDRAM_VALUE(emc_odt_write);
CASE_SDRAM_VALUE(emc_odt_read);
CASE_SDRAM_VALUE(emc_zcal_ref_cnt);
CASE_SDRAM_VALUE(emc_zcal_wait_cnt);
CASE_SDRAM_VALUE(emc_zcal_mrw_cmd);
CASE_SDRAM_VALUE(emc_mrs_reset_dll);
CASE_SDRAM_VALUE(emc_mrw_zq_init_dev0);
CASE_SDRAM_VALUE(emc_mrw_zq_init_dev1);
CASE_SDRAM_VALUE(emc_mrw_zq_init_wait);
CASE_SDRAM_VALUE(emc_mrs_reset_dll_wait);
CASE_SDRAM_VALUE(emc_emrs_emr2);
CASE_SDRAM_VALUE(emc_emrs_emr3);
CASE_SDRAM_VALUE(emc_emrs_ddr2_dll_enable);
CASE_SDRAM_VALUE(emc_mrs_ddr2_dll_reset);
CASE_SDRAM_VALUE(emc_emrs_ddr2_ocd_calib);
CASE_SDRAM_VALUE(emc_ddr2_wait);
CASE_SDRAM_VALUE(emc_cfg_clktrim0);
CASE_SDRAM_VALUE(emc_cfg_clktrim1);
CASE_SDRAM_VALUE(emc_cfg_clktrim2);
CASE_SDRAM_VALUE(pmc_ddr_pwr);
CASE_SDRAM_VALUE(apb_misc_gp_xm2cfga_pad_ctrl);
CASE_SDRAM_VALUE(apb_misc_gp_xm2cfgc_pad_ctrl);
CASE_SDRAM_VALUE(apb_misc_gp_xm2cfgc_pad_ctrl2);
CASE_SDRAM_VALUE(apb_misc_gp_xm2cfgd_pad_ctrl);
CASE_SDRAM_VALUE(apb_misc_gp_xm2cfgd_pad_ctrl2);
CASE_SDRAM_VALUE(apb_misc_gp_xm2clkcfg_Pad_ctrl);
CASE_SDRAM_VALUE(apb_misc_gp_xm2comp_pad_ctrl);
CASE_SDRAM_VALUE(apb_misc_gp_xm2vttgen_pad_ctrl);
DEFAULT();
}
return 0;
}