mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-12-27 02:04:55 +00:00
Add update BCT configs feature
This feature reads the BCT data from BCT or BCT with bootloader appended binary, updates the BCT data based on config file, then writes to new image file. Signed-off-by: Penny Chiu <pchiu@nvidia.com> Signed-off-by: Stephen Warren <swarren@nvidia.com>
This commit is contained in:
committed by
Stephen Warren
parent
5f0b21a2b6
commit
ef386340a6
103
src/cbootimage.c
103
src/cbootimage.c
@@ -49,6 +49,7 @@ struct option cbootcmd[] = {
|
||||
{"tegra", 1, NULL, 't'},
|
||||
{"odmdata", 1, NULL, 'o'},
|
||||
{"soc", 1, NULL, 's'},
|
||||
{"update", 0, NULL, 'u'},
|
||||
{0, 0, 0, 0},
|
||||
};
|
||||
|
||||
@@ -63,7 +64,7 @@ write_image_file(build_image_context *context)
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
printf("Usage: cbootimage [options] configfile imagename\n");
|
||||
printf("Usage: cbootimage [options] configfile [inputimage] outputimage\n");
|
||||
printf(" options:\n");
|
||||
printf(" -h, --help, -? Display this message.\n");
|
||||
printf(" -d, --debug Output debugging information.\n");
|
||||
@@ -75,18 +76,23 @@ usage(void)
|
||||
printf(" -s|--soc tegraNN Select target device. Must be one of:\n");
|
||||
printf(" tegra20, tegra30, tegra114, tegra124.\n");
|
||||
printf(" Default: tegra20.\n");
|
||||
printf(" -u|--update Copy input image data and update bct\n");
|
||||
printf(" configs into new image file.\n");
|
||||
printf(" This feature is only for tegra114/124.\n");
|
||||
printf(" configfile File with configuration information\n");
|
||||
printf(" imagename Output image name\n");
|
||||
printf(" inputimage Input image name. This is required\n");
|
||||
printf(" if -u|--update option is used.\n");
|
||||
printf(" outputimage Output image name\n");
|
||||
}
|
||||
|
||||
static int
|
||||
process_command_line(int argc, char *argv[], build_image_context *context)
|
||||
{
|
||||
int c;
|
||||
int c, num_filenames = 2;
|
||||
|
||||
context->generate_bct = 0;
|
||||
|
||||
while ((c = getopt_long(argc, argv, "hdg:t:o:s:", cbootcmd, NULL)) != -1) {
|
||||
while ((c = getopt_long(argc, argv, "hdg:t:o:s:u", cbootcmd, NULL)) != -1) {
|
||||
switch (c) {
|
||||
case 'h':
|
||||
help_only = 1;
|
||||
@@ -131,10 +137,14 @@ process_command_line(int argc, char *argv[], build_image_context *context)
|
||||
case 'o':
|
||||
context->odm_data = strtoul(optarg, NULL, 16);
|
||||
break;
|
||||
case 'u':
|
||||
context->update_image = 1;
|
||||
num_filenames = 3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (argc - optind != 2) {
|
||||
if (argc - optind != num_filenames) {
|
||||
printf("Missing configuration and/or image file name.\n");
|
||||
usage();
|
||||
return -EINVAL;
|
||||
@@ -145,14 +155,26 @@ process_command_line(int argc, char *argv[], build_image_context *context)
|
||||
t20_get_soc_config(context, &g_soc_config);
|
||||
|
||||
/* Open the configuration file. */
|
||||
context->config_file = fopen(argv[optind], "r");
|
||||
context->config_file = fopen(argv[optind++], "r");
|
||||
if (context->config_file == NULL) {
|
||||
printf("Error opening config file.\n");
|
||||
return -ENODATA;
|
||||
}
|
||||
|
||||
/* Record the input image filename if update_image is necessary */
|
||||
if (context->update_image)
|
||||
{
|
||||
if (context->boot_data_version != BOOTDATA_VERSION_T114 &&
|
||||
context->boot_data_version != BOOTDATA_VERSION_T124) {
|
||||
printf("Update image feature is only for Tegra114 and Tegra124.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
context->input_image_filename = argv[optind++];
|
||||
}
|
||||
|
||||
/* Record the output filename */
|
||||
context->image_filename = argv[optind + 1];
|
||||
context->output_image_filename = argv[optind++];
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -190,18 +212,69 @@ main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
/* Open the raw output file. */
|
||||
context.raw_file = fopen(context.image_filename,
|
||||
"w+");
|
||||
context.raw_file = fopen(context.output_image_filename, "w+");
|
||||
if (context.raw_file == NULL) {
|
||||
printf("Error opening raw file %s.\n",
|
||||
context.image_filename);
|
||||
context.output_image_filename);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* first, if we aren't generating the bct, read in config file */
|
||||
if (context.generate_bct == 0) {
|
||||
process_config_file(&context, 1);
|
||||
/* Read the bct data from image if bct configs needs to be updated */
|
||||
if (context.update_image) {
|
||||
u_int32_t offset = 0, bct_size, actual_size;
|
||||
u_int8_t *data_block;
|
||||
struct stat stats;
|
||||
|
||||
if (stat(context.input_image_filename, &stats) != 0) {
|
||||
printf("Error: Unable to query info on input file path %s\n",
|
||||
context.input_image_filename);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Get BCT_SIZE from input image file */
|
||||
bct_size = get_bct_size_from_image(&context);
|
||||
if (!bct_size) {
|
||||
printf("Error: Invalid input image file %s\n",
|
||||
context.input_image_filename);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
while (stats.st_size > offset) {
|
||||
/* Read a block of data into memory */
|
||||
if (read_from_image(context.input_image_filename, offset, bct_size,
|
||||
&data_block, &actual_size, file_type_bct)) {
|
||||
printf("Error reading image file %s.\n", context.input_image_filename);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Check if memory data is valid BCT */
|
||||
context.bct = data_block;
|
||||
if (data_is_valid_bct(&context)) {
|
||||
fseek(context.config_file, 0, SEEK_SET);
|
||||
process_config_file(&context, 0);
|
||||
e = sign_bct(&context, context.bct);
|
||||
if (e != 0) {
|
||||
printf("Signing BCT failed, error: %d.\n", e);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
/* Write the block of data to file */
|
||||
if (actual_size != write_data_block(context.raw_file, offset, actual_size, data_block)) {
|
||||
printf("Error writing image file %s.\n", context.output_image_filename);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
offset += bct_size;
|
||||
}
|
||||
|
||||
printf("Image file %s has been successfully generated!\n",
|
||||
context.output_image_filename);
|
||||
goto fail;
|
||||
}
|
||||
/* If we aren't generating the bct, read in config file */
|
||||
else if (context.generate_bct == 0)
|
||||
process_config_file(&context, 1);
|
||||
/* Generate the new bct file */
|
||||
else {
|
||||
/* Initialize the bct memory */
|
||||
@@ -218,7 +291,7 @@ main(int argc, char *argv[])
|
||||
fwrite(context.bct, 1, context.bct_size,
|
||||
context.raw_file);
|
||||
printf("New BCT file %s has been successfully generated!\n",
|
||||
context.image_filename);
|
||||
context.output_image_filename);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@@ -234,7 +307,7 @@ main(int argc, char *argv[])
|
||||
printf("Error writing image file.\n");
|
||||
else
|
||||
printf("Image file %s has been successfully generated!\n",
|
||||
context.image_filename);
|
||||
context.output_image_filename);
|
||||
|
||||
fail:
|
||||
/* Close the file(s). */
|
||||
|
||||
@@ -45,6 +45,8 @@
|
||||
#define BOOTDATA_VERSION_T114 NVBOOT_BOOTDATA_VERSION(0x35, 0x1)
|
||||
#define BOOTDATA_VERSION_T124 NVBOOT_BOOTDATA_VERSION(0x40, 0x1)
|
||||
|
||||
#define NVBOOT_CONFIG_TABLE_SIZE_MAX 8192
|
||||
|
||||
/*
|
||||
* Enumerations
|
||||
*/
|
||||
@@ -61,7 +63,8 @@ typedef enum
|
||||
typedef struct build_image_context_rec
|
||||
{
|
||||
FILE *config_file;
|
||||
char *image_filename;
|
||||
char *output_image_filename;
|
||||
char *input_image_filename;
|
||||
FILE *raw_file;
|
||||
u_int32_t block_size;
|
||||
u_int32_t block_size_log2;
|
||||
@@ -99,6 +102,7 @@ typedef struct build_image_context_rec
|
||||
u_int32_t odm_data; /* The odm data value */
|
||||
u_int8_t unique_chip_id[16]; /* The unique chip uid */
|
||||
u_int8_t secure_jtag_control; /* The flag for enabling jtag control */
|
||||
u_int8_t update_image; /* The flag for updating image */
|
||||
} build_image_context;
|
||||
|
||||
/* Function prototypes */
|
||||
|
||||
@@ -451,6 +451,8 @@ write_bootloaders(build_image_context *context)
|
||||
|
||||
/* Read the BL into memory. */
|
||||
if (read_from_image(context->newbl_filename,
|
||||
0,
|
||||
MAX_BOOTLOADER_SIZE,
|
||||
&bl_storage,
|
||||
&bl_actual_size,
|
||||
bl_filetype) == 1) {
|
||||
@@ -670,12 +672,15 @@ read_bct_file(struct build_image_context_rec *context)
|
||||
int err = 0;
|
||||
|
||||
if (read_from_image(context->bct_filename,
|
||||
&bct_storage,
|
||||
&bct_actual_size,
|
||||
bct_filetype) == 1) {
|
||||
0,
|
||||
NVBOOT_CONFIG_TABLE_SIZE_MAX,
|
||||
&bct_storage,
|
||||
&bct_actual_size,
|
||||
bct_filetype) == 1) {
|
||||
printf("Error reading bct file %s.\n", context->bct_filename);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
context->bct_size = bct_actual_size;
|
||||
if (context->bct_init != 1)
|
||||
err = init_bct(context);
|
||||
@@ -686,18 +691,12 @@ read_bct_file(struct build_image_context_rec *context)
|
||||
memcpy(context->bct, bct_storage, context->bct_size);
|
||||
free(bct_storage);
|
||||
|
||||
/* get proper soc_config pointer by polling each supported chip */
|
||||
if (if_bct_is_t20_get_soc_config(context, &g_soc_config))
|
||||
return 0;
|
||||
if (if_bct_is_t30_get_soc_config(context, &g_soc_config))
|
||||
return 0;
|
||||
if (if_bct_is_t114_get_soc_config(context, &g_soc_config))
|
||||
return 0;
|
||||
if (if_bct_is_t124_get_soc_config(context, &g_soc_config))
|
||||
return 0;
|
||||
if (!data_is_valid_bct(context))
|
||||
return ENODATA;
|
||||
|
||||
return ENODATA;
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Update the next_bct_blk and make it point to the next
|
||||
* new blank block according to bct_copy given.
|
||||
@@ -898,3 +897,50 @@ write_block_raw(build_image_context *context)
|
||||
free(empty_blk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int write_data_block(FILE *fp, u_int32_t offset, u_int32_t size, u_int8_t *buffer)
|
||||
{
|
||||
if (fseek(fp, offset, 0))
|
||||
return -1;
|
||||
|
||||
return fwrite(buffer, 1, size, fp);
|
||||
}
|
||||
|
||||
int data_is_valid_bct(build_image_context *context)
|
||||
{
|
||||
/* get proper soc_config pointer by polling each supported chip */
|
||||
if (if_bct_is_t20_get_soc_config(context, &g_soc_config))
|
||||
return 1;
|
||||
if (if_bct_is_t30_get_soc_config(context, &g_soc_config))
|
||||
return 1;
|
||||
if (if_bct_is_t114_get_soc_config(context, &g_soc_config))
|
||||
return 1;
|
||||
if (if_bct_is_t124_get_soc_config(context, &g_soc_config))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int get_bct_size_from_image(build_image_context *context)
|
||||
{
|
||||
u_int8_t buffer[NVBOOT_CONFIG_TABLE_SIZE_MAX];
|
||||
u_int32_t bct_size = 0;
|
||||
FILE *fp;
|
||||
|
||||
fp = fopen(context->input_image_filename, "r");
|
||||
if (!fp)
|
||||
return ENODATA;
|
||||
|
||||
if (!fread(buffer, 1, NVBOOT_CONFIG_TABLE_SIZE_MAX, fp)) {
|
||||
fclose(fp);
|
||||
return ENODATA;
|
||||
}
|
||||
|
||||
context->bct = buffer;
|
||||
if (data_is_valid_bct(context) && g_soc_config->get_bct_size)
|
||||
bct_size = g_soc_config->get_bct_size();
|
||||
|
||||
fclose(fp);
|
||||
context->bct = 0;
|
||||
return bct_size;
|
||||
}
|
||||
|
||||
@@ -49,6 +49,15 @@ init_bct(struct build_image_context_rec *context);
|
||||
int
|
||||
write_block_raw(struct build_image_context_rec *context);
|
||||
|
||||
int
|
||||
write_data_block(FILE *fp, u_int32_t offset, u_int32_t size, u_int8_t *buffer);
|
||||
|
||||
int
|
||||
data_is_valid_bct(build_image_context *context);
|
||||
|
||||
int
|
||||
get_bct_size_from_image(build_image_context *context);
|
||||
|
||||
int
|
||||
begin_update(build_image_context *context);
|
||||
|
||||
|
||||
@@ -752,6 +752,13 @@ typedef struct cbootimage_soc_config_rec {
|
||||
u_int32_t length,
|
||||
u_int8_t *bct);
|
||||
|
||||
/*
|
||||
* Get the BCT structure size
|
||||
*
|
||||
* @return BCT size
|
||||
*/
|
||||
int (*get_bct_size)();
|
||||
|
||||
/*
|
||||
* Check if the token is supported to dump
|
||||
*
|
||||
|
||||
28
src/set.c
28
src/set.c
@@ -43,6 +43,8 @@
|
||||
|
||||
int
|
||||
read_from_image(char *filename,
|
||||
u_int32_t offset,
|
||||
u_int32_t max_size,
|
||||
u_int8_t **image,
|
||||
u_int32_t *actual_size,
|
||||
file_type f_type)
|
||||
@@ -57,6 +59,8 @@ read_from_image(char *filename,
|
||||
return result;
|
||||
}
|
||||
|
||||
fseek(fp, offset, SEEK_SET);
|
||||
|
||||
if (stat(filename, &stats) != 0) {
|
||||
printf("Error: Unable to query info on bootloader path %s\n",
|
||||
filename);
|
||||
@@ -64,14 +68,21 @@ read_from_image(char *filename,
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
*actual_size = (u_int32_t)stats.st_size;
|
||||
|
||||
if (f_type == file_type_bl && *actual_size > MAX_BOOTLOADER_SIZE) {
|
||||
printf("Error: Bootloader file %s is too large.\n",
|
||||
filename);
|
||||
result = 1;
|
||||
goto cleanup;
|
||||
if (f_type == file_type_bl) {
|
||||
if ((stats.st_size - offset) > max_size) {
|
||||
printf("Error: Bootloader file %s is too large.\n",
|
||||
filename);
|
||||
result = 1;
|
||||
goto cleanup;
|
||||
}
|
||||
*actual_size = (u_int32_t)stats.st_size;
|
||||
} else {
|
||||
if ((stats.st_size - offset) < max_size)
|
||||
*actual_size = stats.st_size - offset;
|
||||
else
|
||||
*actual_size = max_size;
|
||||
}
|
||||
|
||||
*image = malloc(*actual_size);
|
||||
if (*image == NULL) {
|
||||
result = 1;
|
||||
@@ -80,7 +91,8 @@ read_from_image(char *filename,
|
||||
|
||||
memset(*image, 0, *actual_size);
|
||||
|
||||
if (fread(*image, 1, (size_t)stats.st_size, fp) != stats.st_size) {
|
||||
if (fread(*image, 1, (size_t)(*actual_size), fp) !=
|
||||
(size_t)(*actual_size)) {
|
||||
result = 1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
@@ -42,6 +42,8 @@ context_set_value(build_image_context *context,
|
||||
|
||||
int
|
||||
read_from_image(char *filename,
|
||||
u_int32_t offset,
|
||||
u_int32_t max_size,
|
||||
u_int8_t **Image,
|
||||
u_int32_t *actual_size,
|
||||
file_type f_type);
|
||||
|
||||
@@ -1064,6 +1064,11 @@ t114_bct_set_data(parse_token id,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int t114_get_bct_size()
|
||||
{
|
||||
return sizeof(nvboot_config_table);
|
||||
}
|
||||
|
||||
int t114_bct_token_supported(parse_token token)
|
||||
{
|
||||
int index;
|
||||
@@ -1108,6 +1113,7 @@ cbootimage_soc_config tegra114_config = {
|
||||
.set_value = t114_bct_set_value,
|
||||
.get_value = t114_bct_get_value,
|
||||
.set_data = t114_bct_set_data,
|
||||
.get_bct_size = t114_get_bct_size,
|
||||
.token_supported = t114_bct_token_supported,
|
||||
|
||||
.devtype_table = s_devtype_table_t114,
|
||||
|
||||
@@ -1077,6 +1077,11 @@ t124_bct_set_data(parse_token id,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int t124_get_bct_size()
|
||||
{
|
||||
return sizeof(nvboot_config_table);
|
||||
}
|
||||
|
||||
int t124_bct_token_supported(parse_token token)
|
||||
{
|
||||
int index;
|
||||
@@ -1121,6 +1126,7 @@ cbootimage_soc_config tegra124_config = {
|
||||
.set_value = t124_bct_set_value,
|
||||
.get_value = t124_bct_get_value,
|
||||
.set_data = t124_bct_set_data,
|
||||
.get_bct_size = t124_get_bct_size,
|
||||
.token_supported = t124_bct_token_supported,
|
||||
|
||||
.devtype_table = s_devtype_table_t124,
|
||||
|
||||
@@ -645,6 +645,11 @@ t20_bct_set_data(parse_token id,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int t20_get_bct_size()
|
||||
{
|
||||
return sizeof(nvboot_config_table);
|
||||
}
|
||||
|
||||
int t20_bct_token_supported(parse_token token)
|
||||
{
|
||||
int index;
|
||||
@@ -689,6 +694,7 @@ cbootimage_soc_config tegra20_config = {
|
||||
.set_value = t20_bct_set_value,
|
||||
.get_value = t20_bct_get_value,
|
||||
.set_data = t20_bct_set_data,
|
||||
.get_bct_size = t20_get_bct_size,
|
||||
.token_supported = t20_bct_token_supported,
|
||||
|
||||
.devtype_table = s_devtype_table_t20,
|
||||
|
||||
@@ -852,6 +852,11 @@ t30_bct_set_data(parse_token id,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int t30_get_bct_size()
|
||||
{
|
||||
return sizeof(nvboot_config_table);
|
||||
}
|
||||
|
||||
int t30_bct_token_supported(parse_token token)
|
||||
{
|
||||
int index;
|
||||
@@ -896,6 +901,7 @@ cbootimage_soc_config tegra30_config = {
|
||||
.set_value = t30_bct_set_value,
|
||||
.get_value = t30_bct_get_value,
|
||||
.set_data = t30_bct_set_data,
|
||||
.get_bct_size = t30_get_bct_size,
|
||||
.token_supported = t30_bct_token_supported,
|
||||
|
||||
.devtype_table = s_devtype_table_t30,
|
||||
|
||||
Reference in New Issue
Block a user