diff options
Diffstat (limited to 'system/cbootimage/set.c')
-rw-r--r-- | system/cbootimage/set.c | 306 |
1 files changed, 306 insertions, 0 deletions
diff --git a/system/cbootimage/set.c b/system/cbootimage/set.c new file mode 100644 index 0000000..14fe214 --- /dev/null +++ b/system/cbootimage/set.c @@ -0,0 +1,306 @@ +/** + * 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. + */ + +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; + + 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_page_size: + context->page_size = value; + 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; + +} + |