311 lines
7.7 KiB
C
311 lines
7.7 KiB
C
/*
|
|
* 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,
|
|
* version 2, as published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
* See file CREDITS for list of people who contributed to this
|
|
* project.
|
|
*/
|
|
|
|
/*
|
|
* 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 parsing functions.
|
|
*/
|
|
#define DEFAULT() \
|
|
default: \
|
|
printf("Unexpected token %d at line %d\n", \
|
|
token, __LINE__); \
|
|
return 1
|
|
|
|
int
|
|
read_from_image(char *filename,
|
|
uint32_t offset,
|
|
uint32_t max_size,
|
|
uint8_t **image,
|
|
uint32_t *actual_size,
|
|
file_type f_type)
|
|
{
|
|
int result = 0; /* 0 = success, 1 = failure */
|
|
FILE *fp;
|
|
struct stat stats;
|
|
|
|
fp = fopen(filename, "rb");
|
|
if (fp == NULL) {
|
|
result = 1;
|
|
return result;
|
|
}
|
|
|
|
if (fseek(fp, offset, SEEK_SET) == -1) {
|
|
printf("Error: Couldn't seek to %s(%d)\n", filename, offset);
|
|
result = 1;
|
|
goto cleanup;
|
|
}
|
|
|
|
if (stat(filename, &stats) != 0) {
|
|
printf("Error: Unable to query info on bootloader path %s\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 = (uint32_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;
|
|
goto cleanup;
|
|
}
|
|
|
|
memset(*image, 0, *actual_size);
|
|
|
|
if (fread(*image, 1, (size_t)(*actual_size), fp) !=
|
|
(size_t)(*actual_size)) {
|
|
result = 1;
|
|
free(*image);
|
|
goto cleanup;
|
|
}
|
|
|
|
cleanup:
|
|
fclose(fp);
|
|
return result;
|
|
}
|
|
|
|
/*
|
|
* Processes commands to set a bootloader.
|
|
*
|
|
* @param context The main context pointer
|
|
* @param filename The file name of bootloader
|
|
* @param load_addr The load address value for bootloader
|
|
* @param entry_point The entry point value for bootloader
|
|
* @return 0 and 1 for success and failure
|
|
*/
|
|
int
|
|
set_bootloader(build_image_context *context,
|
|
char *filename,
|
|
uint32_t load_addr,
|
|
uint32_t entry_point)
|
|
{
|
|
context->newbl_filename = filename;
|
|
context->newbl_load_addr = load_addr;
|
|
context->newbl_entry_point = entry_point;
|
|
return update_bl(context);
|
|
}
|
|
|
|
/*
|
|
* Processes commands to set a MTS image.
|
|
*
|
|
* @param context The main context pointer
|
|
* @param filename The file name of MTS image
|
|
* @param load_addr The load address value for MTS image
|
|
* @param entry_point The entry point value for MTS image
|
|
* @return 0 and 1 for success and failure
|
|
*/
|
|
int
|
|
set_mts_image(build_image_context *context,
|
|
char *filename,
|
|
uint32_t load_addr,
|
|
uint32_t entry_point)
|
|
{
|
|
context->mts_filename = filename;
|
|
context->mts_load_addr = load_addr;
|
|
context->mts_entry_point = entry_point;
|
|
return update_mts_image(context);
|
|
}
|
|
|
|
int
|
|
set_rsa_param(build_image_context *context, parse_token token,
|
|
char *filename)
|
|
{
|
|
int result;
|
|
uint8_t *rsa_storage; /* Holds the rsa param after reading */
|
|
int32_t size; /* Bytes to read */
|
|
uint32_t actual_size; /* In bytes */
|
|
|
|
if ((size = g_soc_config->get_value_size(token)) <= 0) {
|
|
printf("Error: Unsupported token %d for value size.\n", token);
|
|
exit(1);
|
|
}
|
|
|
|
/* Read the image into memory. */
|
|
result = read_from_image(filename,
|
|
0,
|
|
(uint32_t)size,
|
|
&rsa_storage,
|
|
&actual_size,
|
|
file_type_bin);
|
|
|
|
if (result) {
|
|
printf("Error reading file %s.\n", filename);
|
|
exit(1);
|
|
}
|
|
|
|
if (actual_size != size) {
|
|
printf("Error: invalid size, file %s.\n", filename);
|
|
exit(1);
|
|
}
|
|
|
|
if (enable_debug)
|
|
printf("Updating token %d with file %s\n", (int)token, filename);
|
|
|
|
/* set to appropriate bct field */
|
|
result = g_soc_config->set_value(token,
|
|
rsa_storage, context->bct);
|
|
|
|
free(rsa_storage);
|
|
return result;
|
|
}
|
|
|
|
#define DEFAULT() \
|
|
default: \
|
|
printf("Unexpected token %d at line %d\n", \
|
|
token, __LINE__); \
|
|
return 1
|
|
|
|
/*
|
|
* General handler for setting values in config files.
|
|
*
|
|
* @param context The main context pointer
|
|
* @param token The parse token value
|
|
* @param value The pointer of value to set
|
|
* @return 0 for success
|
|
*/
|
|
int context_set_value(build_image_context *context,
|
|
parse_token token,
|
|
void *value)
|
|
{
|
|
assert(context != NULL);
|
|
|
|
switch (token) {
|
|
case token_attribute:
|
|
context->newbl_attr = *((uint32_t *)value);
|
|
break;
|
|
|
|
case token_block_size:
|
|
context->block_size = *((uint32_t *)value);
|
|
context->block_size_log2 = log2(*((uint32_t *)value));
|
|
|
|
if (context->memory != NULL) {
|
|
printf("Error: Too late to change block size.\n");
|
|
return 1;
|
|
}
|
|
|
|
if (context->block_size != (uint32_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);
|
|
g_soc_config->set_value(token_block_size_log2,
|
|
&(context->block_size_log2), context->bct);
|
|
break;
|
|
|
|
case token_partition_size:
|
|
if (context->memory != NULL) {
|
|
printf("Error: Too late to change block size.\n");
|
|
return 1;
|
|
}
|
|
|
|
context->partition_size= *((uint32_t *)value);
|
|
g_soc_config->set_value(token_partition_size,
|
|
value, context->bct);
|
|
break;
|
|
|
|
case token_page_size:
|
|
context->page_size = *((uint32_t *)value);
|
|
context->page_size_log2 = log2(*((uint32_t *)value));
|
|
|
|
if (context->page_size != (uint32_t)(1 << context->page_size_log2)) {
|
|
printf("Error: Page size must be a power of 2.\n");
|
|
return 1;
|
|
}
|
|
context->pages_per_blk= 1 << (context->block_size_log2-
|
|
context->page_size_log2);
|
|
|
|
g_soc_config->set_value(token_page_size_log2,
|
|
&(context->page_size_log2), context->bct);
|
|
break;
|
|
case token_redundancy:
|
|
context->redundancy = *((uint32_t *)value);
|
|
break;
|
|
|
|
case token_version:
|
|
context->version = *((uint32_t *)value);
|
|
break;
|
|
|
|
case token_bct_copy:
|
|
context->bct_copy = *((uint32_t *)value);
|
|
break;
|
|
|
|
case token_odm_data:
|
|
context->odm_data = *((uint32_t *)value);
|
|
break;
|
|
|
|
case token_pre_bct_pad_blocks:
|
|
if (context->bct_init) {
|
|
printf("Error: Too late to pre-BCT pad.\n");
|
|
return 1;
|
|
}
|
|
context->pre_bct_pad_blocks = *((uint32_t *)value);
|
|
break;
|
|
|
|
case token_secure_jtag_control:
|
|
context->secure_jtag_control = *((uint32_t *)value);
|
|
g_soc_config->set_value(token_secure_jtag_control,
|
|
value, context->bct);
|
|
break;
|
|
|
|
case token_secure_debug_control:
|
|
context->secure_debug_control = *((uint32_t *)value);
|
|
g_soc_config->set_value(token_secure_debug_control,
|
|
value, context->bct);
|
|
break;
|
|
|
|
case token_unique_chip_id:
|
|
memcpy(context->unique_chip_id, value, 16);
|
|
g_soc_config->set_value(token_unique_chip_id,
|
|
value, context->bct);
|
|
break;
|
|
|
|
DEFAULT();
|
|
}
|
|
|
|
return 0;
|
|
}
|