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 <[email protected]>
---
 src/cbootimage.c  | 91 ++++++++++++++++++++++++++++++++++++++++++++++---------
 src/cbootimage.h  | 10 +++++-
 src/data_layout.c | 86 +++++++++++++++++++++++++++++++++++++++++++---------
 src/data_layout.h |  9 ++++++
 src/set.c         | 28 ++++++++++++-----
 src/set.h         |  2 ++
 6 files changed, 188 insertions(+), 38 deletions(-)

diff --git a/src/cbootimage.c b/src/cbootimage.c
index 1332c5f..7477414 100644
--- a/src/cbootimage.c
+++ b/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,22 @@ 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("    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 +136,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 +154,18 @@ 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)
+               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 +203,66 @@ 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 */
+                       write_data_block(context.raw_file, offset, actual_size, 
data_block);
+
+                       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 +279,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 +295,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). */
diff --git a/src/cbootimage.h b/src/cbootimage.h
index 252c41e..121bc95 100644
--- a/src/cbootimage.h
+++ b/src/cbootimage.h
@@ -44,6 +44,12 @@
 #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
+#define NVBOOT_CONFIG_TABLE_SIZE_T20 4080
+#define NVBOOT_CONFIG_TABLE_SIZE_T30 6128
+#define NVBOOT_CONFIG_TABLE_SIZE_T114 8192
+#define NVBOOT_CONFIG_TABLE_SIZE_T124 8192
+
 /*
  * Enumerations
  */
@@ -60,7 +66,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;
@@ -98,6 +105,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 */
diff --git a/src/data_layout.c b/src/data_layout.c
index 0a64ec2..a7a89fc 100644
--- a/src/data_layout.c
+++ b/src/data_layout.c
@@ -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) {
@@ -665,17 +667,20 @@ int
 read_bct_file(struct build_image_context_rec *context)
 {
        u_int8_t  *bct_storage; /* Holds the Bl after reading */
-       u_int32_t  bct_actual_size; /* In bytes */
+       u_int32_t bct_actual_size; /* In bytes */
        file_type bct_filetype = file_type_bct;
        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,62 @@ 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;
+
+       fwrite(buffer, 1, size, fp);
+       return 0;
+}
+
+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)) {
+               context->bct = buffer;
+               if (data_is_valid_bct(context)) {
+                       switch (context->boot_data_version) {
+                       case BOOTDATA_VERSION_T20:
+                               bct_size = NVBOOT_CONFIG_TABLE_SIZE_T20;
+                               break;
+                       case BOOTDATA_VERSION_T30:
+                               bct_size = NVBOOT_CONFIG_TABLE_SIZE_T30;
+                               break;
+                       case BOOTDATA_VERSION_T114:
+                               bct_size = NVBOOT_CONFIG_TABLE_SIZE_T114;
+                               break;
+                       case BOOTDATA_VERSION_T124:
+                               bct_size = NVBOOT_CONFIG_TABLE_SIZE_T124;
+                               break;
+                       }
+               }
+       }
+       fclose(fp);
+
+       context->bct = 0;
+       return bct_size;
+}
diff --git a/src/data_layout.h b/src/data_layout.h
index 9ee8267..12da165 100644
--- a/src/data_layout.h
+++ b/src/data_layout.h
@@ -50,6 +50,15 @@ 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);
 
 #endif /* #ifndef INCLUDED_DATA_LAYOUT_H */
diff --git a/src/set.c b/src/set.c
index 4a78b71..46dcfdc 100644
--- a/src/set.c
+++ b/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;
        }
diff --git a/src/set.h b/src/set.h
index 754ed7a..97ecc76 100644
--- a/src/set.h
+++ b/src/set.h
@@ -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);
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-tegra" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to