diff options
Diffstat (limited to 'src/data_layout.c')
-rw-r--r-- | src/data_layout.c | 394 |
1 files changed, 255 insertions, 139 deletions
diff --git a/src/data_layout.c b/src/data_layout.c index 73663be..01f00ab 100644 --- a/src/data_layout.c +++ b/src/data_layout.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2012-2014, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -75,7 +75,7 @@ set_bl_data(build_image_context *context, u_int32_t start_page, u_int32_t length); -static int write_bootloaders(build_image_context *context); +static int write_image(build_image_context *context, file_type image_type); static void find_new_bct_blk(build_image_context *context); static int finish_update(build_image_context *context); @@ -306,25 +306,76 @@ fail: return err; } -#define SET_BL_FIELD(instance, field, value) \ -do { \ - g_soc_config->setbl_param(instance, \ - token_bl_##field, \ - &(value), \ - context->bct); \ +#define SET_BL_FIELD(instance, field, value) \ +do { \ + g_soc_config->setbl_param(instance, \ + token_bl_##field, \ + &(value), \ + context->bct); \ } while (0); -#define GET_BL_FIELD(instance, field, ptr) \ -g_soc_config->getbl_param(instance, \ - token_bl_##field, \ - ptr, \ - context->bct); +#define GET_BL_FIELD(instance, field, ptr) \ +g_soc_config->getbl_param(instance, \ + token_bl_##field, \ + ptr, \ + context->bct); + +#define COPY_BL_FIELD(from, to, field) \ +do { \ + u_int32_t v; \ + GET_BL_FIELD(from, field, &v); \ + SET_BL_FIELD(to, field, v); \ +} while (0); + +#define SET_MTS_FIELD(instance, field, value) \ +do { \ + g_soc_config->set_mts_info(context, \ + instance, \ + token_mts_info_##field, \ + value); \ +} while (0); + +#define GET_MTS_FIELD(instance, field, ptr) \ +g_soc_config->get_mts_info(context, \ + instance, \ + token_mts_info_##field, \ + ptr); + +#define COPY_MTS_FIELD(from, to, field) \ +do { \ + u_int32_t v; \ + GET_MTS_FIELD(from, field, &v); \ + SET_MTS_FIELD(to, field, v); \ +} while (0); + +#define SET_FIELD(is_bl, instance, field, value)\ +do { \ + if (is_bl) { \ + SET_BL_FIELD(instance, field,value); \ + } \ + else { \ + SET_MTS_FIELD(instance, field, value); \ + } \ +} while (0); -#define COPY_BL_FIELD(from, to, field) \ -do { \ - u_int32_t v; \ - GET_BL_FIELD(from, field, &v); \ - SET_BL_FIELD(to, field, v); \ +#define GET_FIELD(is_bl, instance, field, ptr) \ +do { \ + if (is_bl) { \ + GET_BL_FIELD(instance, field, ptr); \ + } \ + else { \ + GET_MTS_FIELD(instance, field, ptr); \ + } \ +} while (0); + +#define COPY_FIELD(is_bl, from, to, field) \ +do { \ + if (is_bl) { \ + COPY_BL_FIELD(from, to, field); \ + } \ + else { \ + COPY_MTS_FIELD(from, to, field); \ + } \ } while (0); static void @@ -345,130 +396,170 @@ set_bl_data(build_image_context *context, SET_BL_FIELD(instance, attribute, context->newbl_attr); } +static void +set_mts_data(build_image_context *context, + u_int32_t instance, + u_int32_t start_blk, + u_int32_t start_page, + u_int32_t length) +{ + assert(context); + + SET_MTS_FIELD(instance, version, context->version); + SET_MTS_FIELD(instance, start_blk, start_blk); + SET_MTS_FIELD(instance, start_page, start_page); + SET_MTS_FIELD(instance, length, length); + SET_MTS_FIELD(instance, load_addr, context->mts_load_addr); + SET_MTS_FIELD(instance, entry_point, context->mts_entry_point); + SET_MTS_FIELD(instance, attribute, context->mts_attr); +} + +#define SET_DATA(is_bl, context, instance, start_blk, start_page, length) \ +do { \ + if (is_bl) \ + set_bl_data(context, instance, start_blk, start_page, length); \ + else \ + set_mts_data(context, instance, start_blk, start_page, length); \ +} while (0); + /* - * Load the bootloader image then update it with the information - * from config file. - * In the interest of expediency, all BL's allocated from bottom to top start - * at page 0 of a block, and all BL's allocated from top to bottom end at - * the end of a block. + * Load the image then update it with the information from config file. + * In the interest of expediency, all image's allocated from bottom to top + * start at page 0 of a block, and all image's allocated from top to bottom + * end at the end of a block. * - * @param context The main context pointer + * @param context The main context pointer + * @param image_type The image type. Can be file_type_bl or file_type_mts + * only right now * @return 0 for success */ static int -write_bootloaders(build_image_context *context) +write_image(build_image_context *context, file_type image_type) { - u_int32_t i; - u_int32_t j; - u_int32_t bl_instance; - u_int32_t bl_move_count = 0; - u_int32_t bl_move_remaining; + u_int32_t i, j; + u_int32_t image_instance; + u_int32_t image_move_count = 0; + u_int32_t image_move_remaining; u_int32_t current_blk; u_int32_t current_page; - u_int32_t pages_in_bl; - u_int32_t bootloader_used; - u_int8_t *bl_storage; /* Holds the Bl after reading */ - u_int8_t *buffer; /* Holds the Bl for writing */ - u_int8_t *src; /* Scans through the Bl during writing */ - u_int32_t bl_actual_size; /* In bytes */ + u_int32_t pages_in_image; + u_int32_t image_used; + u_int8_t *image_storage; /* Holds the image after reading */ + u_int8_t *buffer; /* Holds the image for writing */ + u_int8_t *src; /* Scans through the image during writing */ + u_int32_t image_actual_size; /* In bytes */ u_int32_t pagesremaining; u_int32_t virtual_blk; u_int32_t pages_per_blk; - u_int32_t bl_0_version; - u_int32_t bl_used; + u_int32_t image_version; u_int8_t *hash_buffer; u_int32_t hash_size; - u_int32_t bootloaders_max; - file_type bl_filetype = file_type_bl; - int err = 0; + u_int32_t image_max; + parse_token token; + int err = 0, is_bl; assert(context); + /* Only support bootloader and mts image right now */ + if (image_type == file_type_bl) { + is_bl = 1; + } + else if (image_type == file_type_mts) { + is_bl = 0; + } + else { + printf("Not supported image type!\n"); + return -EINVAL; + } + pages_per_blk = 1 << (context->block_size_log2 - context->page_size_log2); g_soc_config->get_value(token_hash_size, &hash_size, context->bct); - g_soc_config->get_value(token_bootloaders_max, - &bootloaders_max, context->bct); + token = is_bl ? token_bootloaders_max : token_mts_max; + g_soc_config->get_value(token, &image_max, context->bct); hash_buffer = calloc(1, hash_size); if (hash_buffer == NULL) return -ENOMEM; if (enable_debug) { - printf("write_bootloaders()\n"); + printf("writing %s\n", is_bl ? "bootloader" : "mts image"); printf(" redundancy = %d\n", context->redundancy); } - /* Make room for the Bl(s) in the BCT. */ + /* Make room for the image in the BCT. */ /* Determine how many to move. - * Note that this code will count Bl[0] only if there is already - * a BL in the device. + * Note that this code will count Mts[0] only if there is already + * a mts in the device. */ - GET_BL_FIELD(0, version, &bl_0_version); - g_soc_config->get_value(token_bootloader_used, - &bl_used, context->bct); - for (bl_instance = 0; bl_instance < bl_used; bl_instance++) { - u_int32_t bl_version; - GET_BL_FIELD(bl_instance, version, &bl_version); - if (bl_version == bl_0_version) - bl_move_count++; + GET_FIELD(is_bl, 0, version, &image_version); + token = is_bl ? token_bootloader_used : token_mts_used; + g_soc_config->get_value(token, &image_used, context->bct); + for (image_instance = 0; image_instance < image_used; image_instance++) { + u_int32_t tmp; + GET_FIELD(is_bl, image_instance, version, &tmp); + if (tmp == image_version) + image_move_count++; } - /* Adjust the move count, if needed, to avoid overflowing the BL table. + /* Adjust the move count, if needed, to avoid overflowing the mts table. * This can happen due to too much redundancy. */ - bl_move_count = MIN(bl_move_count, - bootloaders_max - context->redundancy); + image_move_count = MIN(image_move_count, image_max - context->redundancy); - /* Move the Bl entries down. */ - bl_move_remaining = bl_move_count; - while (bl_move_remaining > 0) { - u_int32_t inst_from = bl_move_remaining - 1; + /* Move the mts entries down. */ + image_move_remaining = image_move_count; + while (image_move_remaining > 0) { + u_int32_t inst_from = image_move_remaining - 1; u_int32_t inst_to = - bl_move_remaining + context->redundancy - 1; - - COPY_BL_FIELD(inst_from, inst_to, version); - COPY_BL_FIELD(inst_from, inst_to, start_blk); - COPY_BL_FIELD(inst_from, inst_to, start_page); - COPY_BL_FIELD(inst_from, inst_to, length); - COPY_BL_FIELD(inst_from, inst_to, load_addr); - COPY_BL_FIELD(inst_from, inst_to, entry_point); - COPY_BL_FIELD(inst_from, inst_to, attribute); - - g_soc_config->getbl_param(inst_from, - token_bl_crypto_hash, - (u_int32_t*)hash_buffer, - context->bct); - g_soc_config->setbl_param(inst_to, - token_bl_crypto_hash, - (u_int32_t*)hash_buffer, - context->bct); - bl_move_remaining--; + image_move_remaining + context->redundancy - 1; + + COPY_FIELD(is_bl, inst_from, inst_to, version); + COPY_FIELD(is_bl, inst_from, inst_to, start_blk); + COPY_FIELD(is_bl, inst_from, inst_to, start_page); + COPY_FIELD(is_bl, inst_from, inst_to, length); + COPY_FIELD(is_bl, inst_from, inst_to, load_addr); + COPY_FIELD(is_bl, inst_from, inst_to, entry_point); + COPY_FIELD(is_bl, inst_from, inst_to, attribute); + + if (is_bl) { + g_soc_config->getbl_param(inst_from, + token_bl_crypto_hash, + (u_int32_t*)hash_buffer, + context->bct); + g_soc_config->setbl_param(inst_to, + token_bl_crypto_hash, + (u_int32_t*)hash_buffer, + context->bct); + } + + image_move_remaining--; } - /* Read the BL into memory. */ - if (read_from_image(context->newbl_filename, + /* Read the image into memory. */ + if (read_from_image( + is_bl ? context->newbl_filename : context->mts_filename, 0, - MAX_BOOTLOADER_SIZE, - &bl_storage, - &bl_actual_size, - bl_filetype) == 1) { - printf("Error reading Bootloader %s.\n", - context->newbl_filename); + is_bl ? MAX_BOOTLOADER_SIZE : MAX_MTS_SIZE, + &image_storage, + &image_actual_size, + image_type) == 1) { + printf("Error reading image %s.\n", + is_bl ? context->newbl_filename : context->mts_filename); exit(1); } - pages_in_bl = iceil_log2(bl_actual_size, context->page_size_log2); + pages_in_image = iceil_log2(image_actual_size, context->page_size_log2); current_blk = context->next_bct_blk; current_page = 0; - for (bl_instance = 0; bl_instance < context->redundancy; - bl_instance++) { + for (image_instance = 0; image_instance < context->redundancy; + image_instance++) { - pagesremaining = pages_in_bl; + pagesremaining = pages_in_image; /* Advance to the next block if needed. */ if (current_page > 0) { current_blk++; @@ -482,11 +573,12 @@ write_bootloaders(build_image_context *context) * bad blocks. */ if (virtual_blk == 0) { - set_bl_data(context, - bl_instance, + SET_DATA(is_bl, + context, + image_instance, current_blk, current_page, - bl_actual_size); + image_actual_size); } if (pagesremaining > pages_per_blk) { @@ -501,31 +593,37 @@ write_bootloaders(build_image_context *context) } /* Scan forwards to write each copy. */ - for (bl_instance = 0; bl_instance < context->redundancy; - bl_instance++) { + for (image_instance = 0; image_instance < context->redundancy; + image_instance++) { /* Create a local copy of the BCT data */ - buffer = malloc(pages_in_bl * context->page_size); + buffer = malloc(pages_in_image * context->page_size); if (buffer == NULL) return -ENOMEM; - memset(buffer, 0, pages_in_bl * context->page_size); - memcpy(buffer, bl_storage, bl_actual_size); - insert_padding(buffer, bl_actual_size); + memset(buffer, 0, pages_in_image * context->page_size); + memcpy(buffer, image_storage, image_actual_size); - pagesremaining = pages_in_bl; + insert_padding(buffer, image_actual_size); - GET_BL_FIELD(bl_instance, start_blk, ¤t_blk); - GET_BL_FIELD(bl_instance, start_page, ¤t_page); + pagesremaining = pages_in_image; - /* Encrypt and compute hash */ - sign_data_block(buffer, - bl_actual_size, - hash_buffer); - g_soc_config->setbl_param(bl_instance, - token_bl_crypto_hash, - (u_int32_t*)hash_buffer, - context->bct); + if (is_bl) { + GET_BL_FIELD(image_instance, start_blk, ¤t_blk); + GET_BL_FIELD(image_instance, start_page, ¤t_page); + + /* Encrypt and compute hash */ + sign_data_block(buffer, + image_actual_size, + hash_buffer); + g_soc_config->setbl_param(image_instance, + token_bl_crypto_hash, + (u_int32_t*)hash_buffer, + context->bct); + } + + GET_FIELD(is_bl, image_instance, start_blk, ¤t_blk); + GET_FIELD(is_bl, image_instance, start_page, ¤t_page); /* Write the BCT data to the storage device, * picking up ECC errors @@ -558,13 +656,12 @@ write_bootloaders(build_image_context *context) free(buffer); } - bootloader_used = context->redundancy + bl_move_count; - g_soc_config->set_value(token_bootloader_used, - &bootloader_used, - context->bct); + image_used = context->redundancy + image_move_count; + token = is_bl ? token_bootloader_used : token_mts_used; + g_soc_config->set_value(token, &image_used, context->bct); if (enable_debug) { - for (i = 0; i < bootloaders_max; i++) { + for (i = 0; i < image_max; i++) { u_int32_t version; u_int32_t start_blk; u_int32_t start_page; @@ -572,15 +669,16 @@ write_bootloaders(build_image_context *context) u_int32_t load_addr; u_int32_t entry_point; - GET_BL_FIELD(i, version, &version); - GET_BL_FIELD(i, start_blk, &start_blk); - GET_BL_FIELD(i, start_page, &start_page); - GET_BL_FIELD(i, length, &length); - GET_BL_FIELD(i, load_addr, &load_addr); - GET_BL_FIELD(i, entry_point, &entry_point); + GET_FIELD(is_bl, i, version, &version); + GET_FIELD(is_bl, i, start_blk, &start_blk); + GET_FIELD(is_bl, i, start_page, &start_page); + GET_FIELD(is_bl, i, length, &length); + GET_FIELD(is_bl, i, load_addr, &load_addr); + GET_FIELD(is_bl, i, entry_point, &entry_point); - printf("%sBL[%d]: %d %04d %04d %04d 0x%08x 0x%08x k=", - i < bl_used ? " " : "**", + printf("%s%s[%d]: %d %04d %04d %04d 0x%08x 0x%08x\n", + i < image_used ? " " : "**", + is_bl ? "BL" : "MTS", i, version, start_blk, @@ -588,28 +686,29 @@ write_bootloaders(build_image_context *context) length, load_addr, entry_point); - - g_soc_config->getbl_param(i, - token_bl_crypto_hash, - (u_int32_t*)hash_buffer, - context->bct); - for (j = 0; j < hash_size / 4; j++) { - printf("%08x", - *((u_int32_t*)(hash_buffer + 4*j))); + if (is_bl) { + g_soc_config->getbl_param(i, + token_bl_crypto_hash, + (u_int32_t*)hash_buffer, + context->bct); + for (j = 0; j < hash_size / 4; j++) { + printf("%08x", + *((u_int32_t*)(hash_buffer + 4*j))); + } + printf("\n"); } - printf("\n"); } } - free(bl_storage); + free(image_storage); free(hash_buffer); return 0; fail: /* Cleanup. */ free(buffer); - free(bl_storage); + free(image_storage); free(hash_buffer); - printf("Write bootloader failed, error: %d.\n", err); + printf("Write image failed, error: %d.\n", err); return err; } @@ -825,7 +924,22 @@ update_bl(build_image_context *context) if (begin_update(context) != 0) return 1; - if (write_bootloaders(context) != 0) + if (write_image(context, file_type_bl) != 0) + return 1; + if (finish_update(context) != 0) + return 1; + return 0; +} + +int +update_mts_image(build_image_context *context) +{ + if (enable_debug) + printf("**update_mts()\n"); + + if (begin_update(context) != 0) + return 1; + if (write_image(context, file_type_mts) != 0) return 1; if (finish_update(context) != 0) return 1; @@ -918,6 +1032,8 @@ int data_is_valid_bct(build_image_context *context) return 1; if (if_bct_is_t124_get_soc_config(context, &g_soc_config)) return 1; + if (if_bct_is_t132_get_soc_config(context, &g_soc_config)) + return 1; return 0; } |