tegra tools: add the cbootimage for google request

cbootimage is a tool used to combine binary .bct, bootloader
and google's component to a spi rom image file.

Change-Id: I25b6fee13d7449fc83ec3802b79cbbbcaae54494
This commit is contained in:
Peer Chen
2011-01-18 21:34:18 -05:00
committed by Allen Martin
commit 8d782eec33
16 changed files with 3769 additions and 0 deletions

View File

@@ -0,0 +1,20 @@
C_FILES :=
C_FILES += nvbctlib_ap20.c
C_FILES += cbootimage.c
C_FILES += data_layout.c
C_FILES += parse.c
C_FILES += set.c
C_FILES += crypto.c
C_FILES += aes_ref.c
OBJS := $(patsubst %.c,%.o,$(notdir $(C_FILES)))
TARGET = cbootimage
CC = gcc
CFLAGS=-Wall -O
$(TARGET):$(OBJS)
$(CC) -o $(TARGET) $(OBJS) $(CFLAGS)
clean:
rm -rf *.o $(TARGET)

330
system/cbootimage/aes_ref.c Normal file
View File

@@ -0,0 +1,330 @@
/*
* (C) Copyright 2011
* NVIDIA Corporation <www.nvidia.com>
*
* 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
*/
/* advanced encryption standard
* author: karl malbrain, malbrain@yahoo.com
*/
/*
This work, including the source code, documentation
and related data, is placed into the public domain.
The orginal author is Karl Malbrain.
THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY
OF ANY KIND, NOT EVEN THE IMPLIED WARRANTY OF
MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE,
ASSUMES _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE
RESULTING FROM THE USE, MODIFICATION, OR
REDISTRIBUTION OF THIS SOFTWARE.
*/
/*
* Modifications by NVIDIA:
* - Created nvaes_ref.h header.
* - Replaced type definitions with NVIDIA standard types.
* - Removed unneeded code that turns this source file into an executable.
* - Created function prototypes for some of the functions.
* - Reformatted the code to conform to coding conventions.
*/
#include "nvaes_ref.h"
static void shift_rows(u_int8_t *state);
static void mix_sub_columns(u_int8_t *state);
static void add_round_key(u_int32_t *state, u_int32_t *key);
static u_int8_t s_Sbox[256] =
{ /* forward s-box */
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5,
0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc,
0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a,
0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b,
0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85,
0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17,
0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88,
0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9,
0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6,
0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94,
0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68,
0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
};
/* combined Xtimes2[Sbox[]] */
static u_int8_t s_Xtime2Sbox[256] =
{
0xc6, 0xf8, 0xee, 0xf6, 0xff, 0xd6, 0xde, 0x91,
0x60, 0x02, 0xce, 0x56, 0xe7, 0xb5, 0x4d, 0xec,
0x8f, 0x1f, 0x89, 0xfa, 0xef, 0xb2, 0x8e, 0xfb,
0x41, 0xb3, 0x5f, 0x45, 0x23, 0x53, 0xe4, 0x9b,
0x75, 0xe1, 0x3d, 0x4c, 0x6c, 0x7e, 0xf5, 0x83,
0x68, 0x51, 0xd1, 0xf9, 0xe2, 0xab, 0x62, 0x2a,
0x08, 0x95, 0x46, 0x9d, 0x30, 0x37, 0x0a, 0x2f,
0x0e, 0x24, 0x1b, 0xdf, 0xcd, 0x4e, 0x7f, 0xea,
0x12, 0x1d, 0x58, 0x34, 0x36, 0xdc, 0xb4, 0x5b,
0xa4, 0x76, 0xb7, 0x7d, 0x52, 0xdd, 0x5e, 0x13,
0xa6, 0xb9, 0x00, 0xc1, 0x40, 0xe3, 0x79, 0xb6,
0xd4, 0x8d, 0x67, 0x72, 0x94, 0x98, 0xb0, 0x85,
0xbb, 0xc5, 0x4f, 0xed, 0x86, 0x9a, 0x66, 0x11,
0x8a, 0xe9, 0x04, 0xfe, 0xa0, 0x78, 0x25, 0x4b,
0xa2, 0x5d, 0x80, 0x05, 0x3f, 0x21, 0x70, 0xf1,
0x63, 0x77, 0xaf, 0x42, 0x20, 0xe5, 0xfd, 0xbf,
0x81, 0x18, 0x26, 0xc3, 0xbe, 0x35, 0x88, 0x2e,
0x93, 0x55, 0xfc, 0x7a, 0xc8, 0xba, 0x32, 0xe6,
0xc0, 0x19, 0x9e, 0xa3, 0x44, 0x54, 0x3b, 0x0b,
0x8c, 0xc7, 0x6b, 0x28, 0xa7, 0xbc, 0x16, 0xad,
0xdb, 0x64, 0x74, 0x14, 0x92, 0x0c, 0x48, 0xb8,
0x9f, 0xbd, 0x43, 0xc4, 0x39, 0x31, 0xd3, 0xf2,
0xd5, 0x8b, 0x6e, 0xda, 0x01, 0xb1, 0x9c, 0x49,
0xd8, 0xac, 0xf3, 0xcf, 0xca, 0xf4, 0x47, 0x10,
0x6f, 0xf0, 0x4a, 0x5c, 0x38, 0x57, 0x73, 0x97,
0xcb, 0xa1, 0xe8, 0x3e, 0x96, 0x61, 0x0d, 0x0f,
0xe0, 0x7c, 0x71, 0xcc, 0x90, 0x06, 0xf7, 0x1c,
0xc2, 0x6a, 0xae, 0x69, 0x17, 0x99, 0x3a, 0x27,
0xd9, 0xeb, 0x2b, 0x22, 0xd2, 0xa9, 0x07, 0x33,
0x2d, 0x3c, 0x15, 0xc9, 0x87, 0xaa, 0x50, 0xa5,
0x03, 0x59, 0x09, 0x1a, 0x65, 0xd7, 0x84, 0xd0,
0x82, 0x29, 0x5a, 0x1e, 0x7b, 0xa8, 0x6d, 0x2c
};
/* combined Xtimes3[Sbox[]] */
static u_int8_t s_Xtime3Sbox[256] =
{
0xa5, 0x84, 0x99, 0x8d, 0x0d, 0xbd, 0xb1, 0x54,
0x50, 0x03, 0xa9, 0x7d, 0x19, 0x62, 0xe6, 0x9a,
0x45, 0x9d, 0x40, 0x87, 0x15, 0xeb, 0xc9, 0x0b,
0xec, 0x67, 0xfd, 0xea, 0xbf, 0xf7, 0x96, 0x5b,
0xc2, 0x1c, 0xae, 0x6a, 0x5a, 0x41, 0x02, 0x4f,
0x5c, 0xf4, 0x34, 0x08, 0x93, 0x73, 0x53, 0x3f,
0x0c, 0x52, 0x65, 0x5e, 0x28, 0xa1, 0x0f, 0xb5,
0x09, 0x36, 0x9b, 0x3d, 0x26, 0x69, 0xcd, 0x9f,
0x1b, 0x9e, 0x74, 0x2e, 0x2d, 0xb2, 0xee, 0xfb,
0xf6, 0x4d, 0x61, 0xce, 0x7b, 0x3e, 0x71, 0x97,
0xf5, 0x68, 0x00, 0x2c, 0x60, 0x1f, 0xc8, 0xed,
0xbe, 0x46, 0xd9, 0x4b, 0xde, 0xd4, 0xe8, 0x4a,
0x6b, 0x2a, 0xe5, 0x16, 0xc5, 0xd7, 0x55, 0x94,
0xcf, 0x10, 0x06, 0x81, 0xf0, 0x44, 0xba, 0xe3,
0xf3, 0xfe, 0xc0, 0x8a, 0xad, 0xbc, 0x48, 0x04,
0xdf, 0xc1, 0x75, 0x63, 0x30, 0x1a, 0x0e, 0x6d,
0x4c, 0x14, 0x35, 0x2f, 0xe1, 0xa2, 0xcc, 0x39,
0x57, 0xf2, 0x82, 0x47, 0xac, 0xe7, 0x2b, 0x95,
0xa0, 0x98, 0xd1, 0x7f, 0x66, 0x7e, 0xab, 0x83,
0xca, 0x29, 0xd3, 0x3c, 0x79, 0xe2, 0x1d, 0x76,
0x3b, 0x56, 0x4e, 0x1e, 0xdb, 0x0a, 0x6c, 0xe4,
0x5d, 0x6e, 0xef, 0xa6, 0xa8, 0xa4, 0x37, 0x8b,
0x32, 0x43, 0x59, 0xb7, 0x8c, 0x64, 0xd2, 0xe0,
0xb4, 0xfa, 0x07, 0x25, 0xaf, 0x8e, 0xe9, 0x18,
0xd5, 0x88, 0x6f, 0x72, 0x24, 0xf1, 0xc7, 0x51,
0x23, 0x7c, 0x9c, 0x21, 0xdd, 0xdc, 0x86, 0x85,
0x90, 0x42, 0xc4, 0xaa, 0xd8, 0x05, 0x01, 0x12,
0xa3, 0x5f, 0xf9, 0xd0, 0x91, 0x58, 0x27, 0xb9,
0x38, 0x13, 0xb3, 0x33, 0xbb, 0x70, 0x89, 0xa7,
0xb6, 0x22, 0x92, 0x20, 0x49, 0xff, 0x78, 0x7a,
0x8f, 0xf8, 0x80, 0x17, 0xda, 0x31, 0xc6, 0xb8,
0xc3, 0xb0, 0x77, 0x11, 0xcb, 0xfc, 0xd6, 0x3a
};
/* exchanges columns in each of 4 rows
* row0 - unchanged, row1- shifted left 1,
* row2 - shifted left 2 and row3 - shifted left 3
*/
static void
shift_rows(u_int8_t *state)
{
u_int8_t tmp;
/* just substitute row 0 */
state[ 0] = s_Sbox[state[ 0]];
state[ 4] = s_Sbox[state[ 4]];
state[ 8] = s_Sbox[state[ 8]];
state[12] = s_Sbox[state[12]];
/* rotate row 1 */
tmp = s_Sbox[state[ 1]];
state[ 1] = s_Sbox[state[ 5]];
state[ 5] = s_Sbox[state[ 9]];
state[ 9] = s_Sbox[state[13]];
state[13] = tmp;
/* rotate row 2 */
tmp = s_Sbox[state[ 2]];
state[ 2] = s_Sbox[state[10]];
state[10] = tmp;
tmp = s_Sbox[state[ 6]];
state[ 6] = s_Sbox[state[14]];
state[14] = tmp;
/* rotate row 3 */
tmp = s_Sbox[state[15]];
state[15] = s_Sbox[state[11]];
state[11] = s_Sbox[state[ 7]];
state[ 7] = s_Sbox[state[ 3]];
state[ 3] = tmp;
}
/* recombine and mix each row in a column */
static void
mix_sub_columns(u_int8_t *state)
{
u_int8_t tmp[4 * NVAES_STATECOLS];
/* mixing column 0 */
tmp[ 0] = s_Xtime2Sbox[state[ 0]] ^ s_Xtime3Sbox[state[ 5]] ^
s_Sbox[state[10]] ^ s_Sbox[state[15]];
tmp[ 1] = s_Sbox[state[ 0]] ^ s_Xtime2Sbox[state[ 5]] ^
s_Xtime3Sbox[state[10]] ^ s_Sbox[state[15]];
tmp[ 2] = s_Sbox[state[ 0]] ^ s_Sbox[state[ 5]] ^
s_Xtime2Sbox[state[10]] ^ s_Xtime3Sbox[state[15]];
tmp[ 3] = s_Xtime3Sbox[state[ 0]] ^ s_Sbox[state[ 5]] ^
s_Sbox[state[10]] ^ s_Xtime2Sbox[state[15]];
/* mixing column 1 */
tmp[ 4] = s_Xtime2Sbox[state[ 4]] ^ s_Xtime3Sbox[state[ 9]] ^
s_Sbox[state[14]] ^ s_Sbox[state[ 3]];
tmp[ 5] = s_Sbox[state[ 4]] ^ s_Xtime2Sbox[state[ 9]] ^
s_Xtime3Sbox[state[14]] ^ s_Sbox[state[ 3]];
tmp[ 6] = s_Sbox[state[ 4]] ^ s_Sbox[state[ 9]] ^
s_Xtime2Sbox[state[14]] ^ s_Xtime3Sbox[state[ 3]];
tmp[ 7] = s_Xtime3Sbox[state[ 4]] ^ s_Sbox[state[ 9]] ^
s_Sbox[state[14]] ^ s_Xtime2Sbox[state[ 3]];
/* mixing column 2 */
tmp[ 8] = s_Xtime2Sbox[state[ 8]] ^ s_Xtime3Sbox[state[13]] ^
s_Sbox[state[ 2]] ^ s_Sbox[state[ 7]];
tmp[ 9] = s_Sbox[state[ 8]] ^ s_Xtime2Sbox[state[13]] ^
s_Xtime3Sbox[state[ 2]] ^ s_Sbox[state[ 7]];
tmp[10] = s_Sbox[state[ 8]] ^ s_Sbox[state[13]] ^
s_Xtime2Sbox[state[ 2]] ^ s_Xtime3Sbox[state[ 7]];
tmp[11] = s_Xtime3Sbox[state[ 8]] ^ s_Sbox[state[13]] ^
s_Sbox[state[ 2]] ^ s_Xtime2Sbox[state[ 7]];
/* mixing column 3 */
tmp[12] = s_Xtime2Sbox[state[12]] ^ s_Xtime3Sbox[state[ 1]] ^
s_Sbox[state[ 6]] ^ s_Sbox[state[11]];
tmp[13] = s_Sbox[state[12]] ^ s_Xtime2Sbox[state[ 1]] ^
s_Xtime3Sbox[state[ 6]] ^ s_Sbox[state[11]];
tmp[14] = s_Sbox[state[12]] ^ s_Sbox[state[ 1]] ^
s_Xtime2Sbox[state[ 6]] ^ s_Xtime3Sbox[state[11]];
tmp[15] = s_Xtime3Sbox[state[12]] ^ s_Sbox[state[ 1]] ^
s_Sbox[state[ 6]] ^ s_Xtime2Sbox[state[11]];
memcpy (state, tmp, sizeof(tmp));
}
/* encrypt/decrypt columns of the key
* n.b. you can replace this with
* byte-wise xor if you wish.
*/
static void
add_round_key(u_int32_t *state, u_int32_t *key)
{
int idx;
for (idx = 0; idx < 4; idx++)
state[idx] ^= key[idx];
}
static u_int8_t s_Rcon[11] =
{
0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36
};
/* produce NVAES_STATECOLS bytes for each round */
void
nv_aes_expand_key(u_int8_t *key, u_int8_t *expkey)
{
u_int8_t tmp0, tmp1, tmp2, tmp3, tmp4;
u_int32_t idx;
memcpy(expkey, key, NVAES_KEYCOLS * 4);
for (idx = NVAES_KEYCOLS;
idx < NVAES_STATECOLS * (NVAES_ROUNDS + 1);
idx++) {
tmp0 = expkey[4*idx - 4];
tmp1 = expkey[4*idx - 3];
tmp2 = expkey[4*idx - 2];
tmp3 = expkey[4*idx - 1];
if (!(idx % NVAES_KEYCOLS)) {
tmp4 = tmp3;
tmp3 = s_Sbox[tmp0];
tmp0 = s_Sbox[tmp1] ^ s_Rcon[idx/NVAES_KEYCOLS];
tmp1 = s_Sbox[tmp2];
tmp2 = s_Sbox[tmp4];
} else if (NVAES_KEYCOLS > 6 && idx % NVAES_KEYCOLS == 4 ) {
tmp0 = s_Sbox[tmp0];
tmp1 = s_Sbox[tmp1];
tmp2 = s_Sbox[tmp2];
tmp3 = s_Sbox[tmp3];
}
expkey[4*idx+0] = expkey[4*idx - 4*NVAES_KEYCOLS + 0] ^ tmp0;
expkey[4*idx+1] = expkey[4*idx - 4*NVAES_KEYCOLS + 1] ^ tmp1;
expkey[4*idx+2] = expkey[4*idx - 4*NVAES_KEYCOLS + 2] ^ tmp2;
expkey[4*idx+3] = expkey[4*idx - 4*NVAES_KEYCOLS + 3] ^ tmp3;
}
}
/* encrypt one 128 bit block */
void
nv_aes_encrypt(u_int8_t *in, u_int8_t *expkey, u_int8_t *out)
{
u_int8_t state[NVAES_STATECOLS * 4];
u_int32_t round;
memcpy(state, in, NVAES_STATECOLS * 4);
add_round_key((u_int32_t *)state, (u_int32_t *)expkey);
for (round = 1; round < NVAES_ROUNDS + 1; round++) {
if (round < NVAES_ROUNDS)
mix_sub_columns (state);
else
shift_rows (state);
add_round_key((u_int32_t *)state, (u_int32_t *)expkey +
round * NVAES_STATECOLS);
}
memcpy(out, state, sizeof(state));
}

View File

@@ -0,0 +1,258 @@
/**
* 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
*/
/*
* cbootimage.c - Implementation of the cbootimage tool.
*/
#include "cbootimage.h"
#include "nvbctlib.h"
#include "crypto.h"
#include "data_layout.h"
#include "parse.h"
#include "set.h"
/*
* Global data
*/
int enable_debug = 0;
static int help_only = 0; // Only print help & exit
/*
* Function prototypes
*/
int main(int argc, char *argv[]);
static int
query_alloc(build_image_context *context,
nvbct_lib_id size_id,
u_int8_t **dst)
{
u_int32_t size;
/* Note: 3rd argument not used in this particular query. */
if (context->bctlib.get_value(size_id,
&size, context->bct) != 0)
return -ENODATA;
*dst = malloc(size);
if (*dst == NULL)
return -ENOMEM;
memset(*dst, 0, size);
return 0;
}
static void
cleanup_context(build_image_context *context)
{
destroy_block_list(context->memory);
destroy_addon_list(context->addon_tbl.addon_item_list);
free(context->bct);
}
static int
init_context(build_image_context *context)
{
int e = 0;
/* Set defaults */
context->memory = new_block_list();
context->journal_blk = 1; /* Default to 1st block */
/* Allocate space for the bct.
* Note that this is different from the old code which pointed directly
* into a memory image.
*/
e = query_alloc(context, nvbct_lib_id_bct_size, &(context->bct));
if (e != 0)
goto fail;
context_set_value(context, token_page_size, 2048);
context_set_value(context, token_redundancy, 1);
context_set_value(context, token_version, 1);
return 0;
fail:
cleanup_context(context);
return e;
}
int
write_image_file(build_image_context *context)
{
assert(context != NULL);
return write_block_raw(context);
}
static void
usage(void)
{
printf("Usage: cbootimage [options] configfile imagename\n");
printf(" options:\n");
printf(" -h, --help, -? Display this message.\n");
printf(" -d, --debug Output debugging information.\n");
printf(" configfile File with configuration information\n");
printf(" imagename Output image name\n");
}
static int
process_command_line(int argc, char *argv[], build_image_context *context)
{
int arg = 1;
while (arg < argc) {
/* Process the next argument. */
if (!strcmp(argv[arg], "-h") ||
!strcmp(argv[arg], "--help") ||
!strcmp(argv[arg], "-?")) {
help_only = 1;
usage();
return 0;
} else if (!strcmp(argv[arg], "-d") ||
!strcmp(argv[arg], "--debug")) {
enable_debug = 1;
arg++;
} else if (argv[arg][0] == '-') {
printf("Illegal option %s\n", argv[arg]);
usage();
return -EINVAL;
}
else
break; /* Finished with options */
}
/* Handle file specification errors. */
switch (argc - arg) {
case 0:
printf("Missing configuration and image file names.\n");
usage();
return -EINVAL;
case 1:
printf("Missing configuration or image file name.\n");
usage();
return -EINVAL;
case 2:
/* Correct args, so break from the switch statement. */
break;
default:
printf("Too many arguments.\n");
usage();
return -EINVAL;
}
/* Open the configuration file. */
context->config_file = fopen(argv[arg], "r");
if (context->config_file == NULL) {
printf("Error opening config file.\n");
return -ENODATA;
}
/* Record the output filename */
context->image_filename = argv[arg + 1];
/* Set up the Nvbctlib function pointers. */
nvbct_lib_get_fns(&(context->bctlib));
return 0;
}
int
main(int argc, char *argv[])
{
int e = 0;
build_image_context context;
u_int32_t data = 0;
memset(&context, 0, sizeof(build_image_context));
/* Process command line arguments. */
if (process_command_line(argc, argv, &context) != 0)
return -EINVAL;
if (help_only)
return 1;
e = init_context(&context);
if (e != 0) {
printf("context initialization failed. Aborting.\n");
return e;
}
if (enable_debug) {
/* Debugging information... */
e = context.bctlib.get_value(nvbct_lib_id_bct_size,
&data, context.bct);
printf("bct size: %d\n", e == 0 ? data : -1);
}
/* Open the raw output file. */
context.raw_file = fopen(context.image_filename,
"w+");
if (context.raw_file == NULL) {
printf("Error opening raw file %s.\n",
context.image_filename);
goto fail;
}
/* Parse & process the contents of the config file. */
process_config_file(&context);
/* Update the bct file */
/* Update the add on file */
e = update_addon_item(&context);
if ( e!= 0) {
printf("Write addon item failed, error: %d.\n", e);
goto fail;
}
/* Peform final signing & encryption of bct. */
e = sign_bct(&context, context.bct);
if (e != 0) {
printf("Signing BCT failed, error: %d.\n", e);
goto fail;
}
/* Write the image file. */
/* The image hasn't been written yet. */
if (write_image_file(&context) != 0)
printf("Error writing image file.\n");
else
printf("Image file %s has been successfully generated!\n",
context.image_filename);
fail:
/* Close the file(s). */
if (context.raw_file)
fclose(context.raw_file);
/* Clean up memory. */
cleanup_context(&context);
return e;
}

View File

@@ -0,0 +1,141 @@
/**
* 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
*/
/*
* cbootimage.h - Definitions for the cbootimage code.
*/
#ifndef INCLUDED_BUILDIMAGE_H
#define INCLUDED_BUILDIMAGE_H
#include "nvboot_bct.h"
#include "nvbctlib.h"
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <errno.h>
#define NVBOOT_AES_BLOCK_SIZE_LOG2 4
#define KEY_LENGTH (128/8)
#define MAX_BUFFER 200
#define MAX_STR_LEN 20
#define MAX_BOOTLOADER_SIZE (16 * 1024 * 1024)
/*
* Enumerations
*/
typedef enum
{
file_type_bl = 0,
file_type_bct,
file_type_addon
} file_type;
/*
* Structures
*/
typedef struct item_rec
{
u_int8_t unique_name[4];
u_int32_t Location;
u_int32_t size;
u_int32_t attribute;
u_int32_t reserve[4];
u_int32_t item_checksum[4];
}item;
typedef struct addon_item_rec
{
struct item_rec item;
char addon_filename[MAX_BUFFER];
int item_index;
struct addon_item_rec *next;
}addon_item;
typedef struct table_rec
{
u_int8_t magic_id[8];
u_int32_t table_checksum[4];
u_int32_t table_size;
}table;
typedef struct addon_table_rec
{
struct table_rec table;
u_int8_t addon_item_no;
struct addon_item_rec *addon_item_list;
}addon_table;
typedef struct build_image_context_rec
{
FILE *config_file;
char *image_filename;
FILE *raw_file;
nvbct_lib_fns bctlib;
u_int32_t block_size;
u_int32_t block_size_log2;
u_int32_t page_size;
u_int32_t page_size_log2;
u_int32_t pages_per_blk;
u_int32_t partition_size;
u_int32_t redundancy;
u_int32_t version;
/* Allocation data. */
struct blk_data_rec *memory; /* Representation of memory */
/* block number for the (first) journal block */
u_int32_t journal_blk;
char *newbl_filename;
u_int32_t newbl_load_addr;
u_int32_t newbl_entry_point;
u_int32_t newbl_attr;
u_int8_t *bct;
struct addon_table_rec addon_tbl;
char *bct_filename;
u_int32_t last_bl_blk;
u_int32_t addon_tbl_blk;
} build_image_context;
/* Function prototypes */
int write_image_file(build_image_context *context);
/* Global data */
extern int enable_debug;
/* Useful macros */
#define GET_VALUE(id, ptr) \
(void)context->bctlib.get_value(nvbct_lib_id_##id, \
ptr, \
context->bct);
#define SET_VALUE(id, value) \
(void)context->bctlib.set_value(nvbct_lib_id_##id, \
value, \
context->bct);
#endif /* #ifndef INCLUDED_BUILDIMAGE_H */

303
system/cbootimage/crypto.c Normal file
View File

@@ -0,0 +1,303 @@
/*
* (C) Copyright 2011
* NVIDIA Corporation <www.nvidia.com>
*
* 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
*/
/*
* crypto.c - Cryptography support
*/
#include "crypto.h"
#include "nvaes_ref.h"
#include <stdio.h>
/* Local function declarations */
static void
apply_cbc_chain_data(u_int8_t *cbc_chain_data,
u_int8_t *src,
u_int8_t *dst);
static void
generate_key_schedule(u_int8_t *key, u_int8_t *key_schedule);
static void
encrypt_object( u_int8_t *key_schedule,
u_int8_t *src,
u_int8_t *dst,
u_int32_t num_aes_blocks);
static int
encrypt_and_sign(u_int8_t *key,
u_int8_t *src,
u_int32_t length,
u_int8_t *sig_dst);
u_int8_t enable_debug_crypto = 0;
/* Implementation */
static u_int8_t zero_key[16] = { 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0 };
static void
print_vector(char *name, u_int32_t num_bytes, u_int8_t *data)
{
u_int32_t i;
printf("%s [%d] @0x%08x", name, num_bytes, (u_int32_t)data);
for (i=0; i<num_bytes; i++) {
if ( i % 16 == 0 )
printf(" = ");
printf("%02x", data[i]);
if ( (i+1) % 16 != 0 )
printf(" ");
}
printf("\n");
}
static void
apply_cbc_chain_data(u_int8_t *cbc_chain_data,
u_int8_t *src,
u_int8_t *dst)
{
int i;
for (i = 0; i < 16; i++) {
*dst++ = *src++ ^ *cbc_chain_data++;
}
}
static void
generate_key_schedule(u_int8_t *key, u_int8_t *key_schedule)
{
/*
* The only need for a key is for signing/checksum purposes, so
* expand a key of 0's.
*/
nv_aes_expand_key(zero_key, key_schedule);
}
static void
encrypt_object(u_int8_t *key_schedule,
u_int8_t *src,
u_int8_t *dst,
u_int32_t num_aes_blocks)
{
u_int32_t i;
u_int8_t *cbc_chain_data;
u_int8_t tmp_data[KEY_LENGTH];
cbc_chain_data = zero_key; /* Convenient array of 0's for IV */
for (i = 0; i < num_aes_blocks; i++) {
if (enable_debug_crypto) {
printf("encrypt_object: block %d of %d\n", i,
num_aes_blocks);
print_vector("AES Src", KEY_LENGTH, src);
}
/* Apply the chain data */
apply_cbc_chain_data(cbc_chain_data, src, tmp_data);
if (enable_debug_crypto)
print_vector("AES Xor", KEY_LENGTH,
tmp_data);
/* encrypt the AES block */
nv_aes_encrypt(tmp_data, key_schedule, dst);
if (enable_debug_crypto)
print_vector("AES Dst", KEY_LENGTH, dst);
/* Update pointers for next loop. */
cbc_chain_data = dst;
src += KEY_LENGTH;
dst += KEY_LENGTH;
}
}
static void
left_shift_vector(u_int8_t *in,
u_int8_t *out,
u_int32_t size)
{
u_int32_t i;
u_int8_t carry = 0;
for (i=0; i<size; i++) {
u_int32_t j = size-1-i;
out[j] = (in[j] << 1) | carry;
carry = in[j] >> 7; /* get most significant bit */
}
}
static void
sign_objext(
u_int8_t *key,
u_int8_t *key_schedule,
u_int8_t *src,
u_int8_t *dst,
u_int32_t num_aes_blocks)
{
u_int32_t i;
u_int8_t *cbc_chain_data;
u_int8_t l[KEY_LENGTH];
u_int8_t k1[KEY_LENGTH];
u_int8_t tmp_data[KEY_LENGTH];
cbc_chain_data = zero_key; /* Convenient array of 0's for IV */
/* compute k1 constant needed by AES-CMAC calculation */
for (i=0; i<KEY_LENGTH; i++)
tmp_data[i] = 0;
encrypt_object(key_schedule, tmp_data, l, 1);
if (enable_debug_crypto)
print_vector("AES(key, nonce)", KEY_LENGTH, l);
left_shift_vector(l, k1, sizeof(l));
if (enable_debug_crypto)
print_vector("L", KEY_LENGTH, l);
if ( (l[0] >> 7) != 0 ) /* get MSB of L */
k1[KEY_LENGTH-1] ^= AES_CMAC_CONST_RB;
if (enable_debug_crypto)
print_vector("K1", KEY_LENGTH, k1);
/* compute the AES-CMAC value */
for (i = 0; i < num_aes_blocks; i++) {
/* Apply the chain data */
apply_cbc_chain_data(cbc_chain_data, src, tmp_data);
/* for the final block, XOR k1 into the IV */
if ( i == num_aes_blocks-1 )
apply_cbc_chain_data(tmp_data, k1, tmp_data);
/* encrypt the AES block */
nv_aes_encrypt(tmp_data, key_schedule, (u_int8_t*)dst);
if (enable_debug_crypto) {
printf("sign_objext: block %d of %d\n", i,
num_aes_blocks);
print_vector("AES-CMAC Src", KEY_LENGTH, src);
print_vector("AES-CMAC Xor", KEY_LENGTH, tmp_data);
print_vector("AES-CMAC Dst",
KEY_LENGTH,
(u_int8_t*)dst);
}
/* Update pointers for next loop. */
cbc_chain_data = (u_int8_t*)dst;
src += KEY_LENGTH;
}
if (enable_debug_crypto)
print_vector("AES-CMAC Hash", KEY_LENGTH, (u_int8_t*)dst);
}
static int
encrypt_and_sign(u_int8_t *key,
u_int8_t *src,
u_int32_t length,
u_int8_t *sig_dst)
{
u_int32_t num_aes_blocks;
u_int8_t key_schedule[4*NVAES_STATECOLS*(NVAES_ROUNDS+1)];
if (enable_debug_crypto) {
printf("encrypt_and_sign: length = %d\n", length);
print_vector("AES key", KEY_LENGTH, key);
}
generate_key_schedule(key, key_schedule);
num_aes_blocks = ICEIL(length, KEY_LENGTH);
if (enable_debug_crypto)
printf("encrypt_and_sign: begin signing\n");
/* encrypt the data, overwriting the result in signature. */
sign_objext(key, key_schedule, src, sig_dst, num_aes_blocks);
if (enable_debug_crypto)
printf("encrypt_and_sign: end signing\n");
return 0;
}
int
sign_data_block(u_int8_t *source,
u_int32_t length,
u_int8_t *signature)
{
return encrypt_and_sign(zero_key,
source,
length,
signature);
}
int
sign_bct(build_image_context *context,
u_int8_t *bct)
{
u_int32_t Offset;
u_int32_t length;
u_int32_t hash_size;
u_int8_t *hash_buffer = NULL;
int e = 0;
assert(bct != NULL);
if (context->bctlib.get_value(nvbct_lib_id_hash_size,
&hash_size,
bct) != 0)
return -ENODATA;
if (context->bctlib.get_value(nvbct_lib_id_crypto_offset,
&Offset,
bct) != 0)
return -ENODATA;
if (context->bctlib.get_value(nvbct_lib_id_crypto_length,
&length,
bct) != 0)
return -ENODATA;
hash_buffer = malloc(hash_size);
if (hash_buffer == NULL)
return -ENOMEM;
e = sign_data_block(bct + Offset, length, hash_buffer);
if (e != 0)
goto fail;
e = context->bctlib.set_data(nvbct_lib_id_crypto_hash,
hash_buffer,
hash_size,
bct);
if (e != 0)
goto fail;
fail:
free(hash_buffer);
return e;
}

View File

@@ -0,0 +1,50 @@
/**
* 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
*/
/*
* crypto.h - Definitions for the crypto support.
*/
#ifndef INCLUDED_CRYPTO_H_N
#define INCLUDED_CRYPTO_H_N
#include "cbootimage.h"
/* lengths, in bytes */
#define KEY_LENGTH (128/8)
#define ICEIL(a, b) (((a) + (b) - 1)/(b))
#define AES_CMAC_CONST_RB 0x87 // from RFC 4493, Figure 2.2
/* Function prototypes */
int
sign_bct(build_image_context *context,
u_int8_t *bct);
int
sign_data_block(u_int8_t *source,
u_int32_t length,
u_int8_t *signature);
#endif /* #ifndef INCLUDED_CRYPTO_H */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,56 @@
/**
* 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
*/
/*
* data_layout.h - Definitions for the cbootimage data layout code.
*/
#ifndef INCLUDED_DATA_LAYOUT_H
#define INCLUDED_DATA_LAYOUT_H
#include "cbootimage.h"
/* Foward declarations */
struct build_image_context_rec;
typedef struct blk_data_rec *blk_data_handle;
blk_data_handle new_block_list(void);
void destroy_block_list(blk_data_handle);
void destroy_addon_list(struct addon_item_rec *addon_list);
int
update_bl(struct build_image_context_rec *context);
void
update_context(struct build_image_context_rec *context);
void
read_bct_file(struct build_image_context_rec *context);
int
update_addon_item(struct build_image_context_rec *context);
int
write_block_raw(struct build_image_context_rec *context);
#endif /* #ifndef INCLUDED_DATA_LAYOUT_H */

View File

@@ -0,0 +1,37 @@
/*
* 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
*/
#include "cbootimage.h"
#include "string.h"
#ifndef INCLUDED_NVAES_REF_H
#define INCLUDED_NVAES_REF_H
#define NVAES_STATECOLS 4
#define NVAES_KEYCOLS 4
#define NVAES_ROUNDS 10
void nv_aes_expand_key(u_int8_t *key, u_int8_t *expkey);
void nv_aes_encrypt(u_int8_t *in,
u_int8_t *expkey,
u_int8_t *out);
#endif // INCLUDED_NVAES_REF_H

View File

@@ -0,0 +1,126 @@
/**
* 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
*/
/*
* nvbctlib is a library for accessing data in BCTs from different versions
* of the BootROM. This provides a means for one utility program to
* reference data which is stored differently by different versions of chips,
* often with the same header file names.
*
* In essence, nvbctlib.h defines an API for selecting chip versions and
* accessing BCT data, and a separate source file wraps the API implementation
* around the header files that are unique to a chip version.
*/
#ifndef INCLUDED_NVBCTLIB_H
#define INCLUDED_NVBCTLIB_H
#include <sys/types.h>
/*
* nvbct_lib_id defines tokens used for querying or setting values within, or
* about, the BCT. These are used to identify values within structures,
* sizes and other properties of structures, and values for enumerated
* constants.
*/
typedef enum {
nvbct_lib_id_none = 0,
nvbct_lib_id_crypto_hash,
nvbct_lib_id_random_aes_blk,
nvbct_lib_id_boot_data_version,
nvbct_lib_id_block_size_log2,
nvbct_lib_id_page_size_log2,
nvbct_lib_id_partition_size,
nvbct_lib_id_bootloader_used,
nvbct_lib_id_bootloaders_max,
nvbct_lib_id_reserved,
nvbct_lib_id_reserved_size,
nvbct_lib_id_reserved_offset,
nvbct_lib_id_bct_size,
nvbct_lib_id_hash_size,
nvbct_lib_id_crypto_offset,
nvbct_lib_id_crypto_length,
nvbct_lib_id_max_bct_search_blks,
nvbct_lib_id_bl_version,
nvbct_lib_id_bl_start_blk,
nvbct_lib_id_bl_start_page,
nvbct_lib_id_bl_length,
nvbct_lib_id_bl_load_addr,
nvbct_lib_id_bl_entry_point,
nvbct_lib_id_bl_attribute,
nvbct_lib_id_bl_crypto_hash,
nvbct_lib_id_max,
nvbct_lib_id_force32 = 0x7fffffff
} nvbct_lib_id;
typedef int (*nvbct_lib_get_bl_param)(u_int32_t set,
nvbct_lib_id id,
u_int32_t *data,
u_int8_t *bct);
typedef int (*nvbct_lib_set_bl_param)(u_int32_t set,
nvbct_lib_id id,
u_int32_t *data,
u_int8_t *bct);
typedef int (*nvbct_lib_get_value)(nvbct_lib_id id,
u_int32_t *data,
u_int8_t *bct);
typedef int (*nvbct_lib_set_value)(nvbct_lib_id id,
u_int32_t data,
u_int8_t *bct);
/*
* Note: On input, *length is the size of data. On output, *length is the
* actual size used.
*/
typedef int (*nvbct_lib_get_data)(nvbct_lib_id id,
u_int8_t *data,
u_int32_t *length,
u_int8_t *bct);
typedef int (*nvbct_lib_set_data)(nvbct_lib_id id,
u_int8_t *data,
u_int32_t length,
u_int8_t *bct);
/*
* Structure of function pointers used to access a specific BCT variant.
*/
typedef struct nvbct_lib_fns_rec
{
nvbct_lib_get_value get_value;
nvbct_lib_set_value set_value;
nvbct_lib_get_data get_data;
nvbct_lib_set_data set_data;
nvbct_lib_get_bl_param getbl_param;
nvbct_lib_set_bl_param setbl_param;
} nvbct_lib_fns;
void nvbct_lib_get_fns(nvbct_lib_fns *fns);
#endif /* #ifndef INCLUDED_NVBCTLIB_H */

View File

@@ -0,0 +1,282 @@
/**
* 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
*/
#include "nvbctlib.h"
#include "nvboot_bct.h"
#include "string.h"
#include "cbootimage.h"
/* nvbctlib_ap20.c: The implementation of the nvbctlib API for AP20. */
/* Definitions that simplify the code which follows. */
#define CASE_GET_BL_PARAM(x) \
case nvbct_lib_id_bl_##x:\
*data = bct_ptr->bootloader[set].x; \
break
#define CASE_SET_BL_PARAM(x) \
case nvbct_lib_id_bl_##x:\
bct_ptr->bootloader[set].x = *data; \
break
#define CASE_GET_NVU32(id) \
case nvbct_lib_id_##id:\
if (bct == NULL) return -ENODATA; \
*data = bct_ptr->id; \
break
#define CASE_GET_CONST(id, val) \
case nvbct_lib_id_##id:\
*data = val; \
break
#define CASE_GET_CONST_PREFIX(id, val_prefix) \
case nvbct_lib_id_##id:\
*data = val_prefix##id; \
break
#define CASE_SET_NVU32(id) \
case nvbct_lib_id_##id:\
bct_ptr->id = data; \
break
#define CASE_GET_DATA(id, size) \
case nvbct_lib_id_##id:\
if (*length < size) return -ENODATA;\
memcpy(data, &(bct_ptr->id), size); \
*length = size;\
break
#define CASE_SET_DATA(id, size) \
case nvbct_lib_id_##id:\
if (length < size) return -ENODATA;\
memcpy(&(bct_ptr->id), data, size); \
break
static int
getbl_param(u_int32_t set,
nvbct_lib_id id,
u_int32_t *data,
u_int8_t *bct)
{
nvboot_config_table *bct_ptr = (nvboot_config_table*)bct;
if (set >= NVBOOT_MAX_BOOTLOADERS)
return -ENODATA;
if (data == NULL || bct == NULL)
return -ENODATA;
switch (id) {
CASE_GET_BL_PARAM(version);
CASE_GET_BL_PARAM(start_blk);
CASE_GET_BL_PARAM(start_page);
CASE_GET_BL_PARAM(length);
CASE_GET_BL_PARAM(load_addr);
CASE_GET_BL_PARAM(entry_point);
CASE_GET_BL_PARAM(attribute);
case nvbct_lib_id_bl_crypto_hash:
memcpy(data,
&(bct_ptr->bootloader[set].crypto_hash),
sizeof(nvboot_hash));
break;
default:
return -ENODATA;
}
return 0;
}
/* Note: The *Data argument is to support hash data. */
static int
setbl_param(u_int32_t set,
nvbct_lib_id id,
u_int32_t *data,
u_int8_t *bct)
{
nvboot_config_table *bct_ptr = (nvboot_config_table*)bct;
if (set >= NVBOOT_MAX_BOOTLOADERS)
return -ENODATA;
if (data == NULL || bct == NULL)
return -ENODATA;
switch (id) {
CASE_SET_BL_PARAM(version);
CASE_SET_BL_PARAM(start_blk);
CASE_SET_BL_PARAM(start_page);
CASE_SET_BL_PARAM(length);
CASE_SET_BL_PARAM(load_addr);
CASE_SET_BL_PARAM(entry_point);
CASE_SET_BL_PARAM(attribute);
case nvbct_lib_id_bl_crypto_hash:
memcpy(&(bct_ptr->bootloader[set].crypto_hash),
data,
sizeof(nvboot_hash));
break;
default:
return -ENODATA;
}
return 0;
}
static int
bct_get_value(nvbct_lib_id id, u_int32_t *data, u_int8_t *bct)
{
nvboot_config_table *bct_ptr = (nvboot_config_table*)bct;
nvboot_config_table samplebct; /* Used for computing offsets. */
/*
* Note: Not all queries require use of the BCT, so testing for a
* valid BCT is distributed within the code.
*/
if (data == NULL)
return -ENODATA;
switch (id) {
/*
* Simple BCT fields
*/
CASE_GET_NVU32(boot_data_version);
CASE_GET_NVU32(block_size_log2);
CASE_GET_NVU32(page_size_log2);
CASE_GET_NVU32(partition_size);
CASE_GET_NVU32(bootloader_used);
/*
* Constants.
*/
CASE_GET_CONST(bootloaders_max, NVBOOT_MAX_BOOTLOADERS);
CASE_GET_CONST(reserved_size, NVBOOT_BCT_RESERVED_SIZE);
case nvbct_lib_id_reserved_offset:
*data = (u_int8_t*)&(samplebct.reserved)
- (u_int8_t*)&samplebct;
break;
case nvbct_lib_id_bct_size:
*data = sizeof(nvboot_config_table);
break;
CASE_GET_CONST(hash_size, sizeof(nvboot_hash));
case nvbct_lib_id_crypto_offset:
/* Offset to region in BCT to encrypt & sign */
*data = (u_int8_t*)&(samplebct.random_aes_blk)
- (u_int8_t*)&samplebct;
break;
case nvbct_lib_id_crypto_length:
/* size of region in BCT to encrypt & sign */
*data = sizeof(nvboot_config_table) - sizeof(nvboot_hash);
break;
CASE_GET_CONST(max_bct_search_blks, NVBOOT_MAX_BCT_SEARCH_BLOCKS);
default:
return -ENODATA;
}
return 0;
}
static int
bct_set_value(nvbct_lib_id id, u_int32_t data, u_int8_t *bct)
{
nvboot_config_table *bct_ptr = (nvboot_config_table*)bct;
if (bct == NULL)
return -ENODATA;
switch (id) {
/*
* Simple BCT fields
*/
CASE_SET_NVU32(boot_data_version);
CASE_SET_NVU32(block_size_log2);
CASE_SET_NVU32(page_size_log2);
CASE_SET_NVU32(partition_size);
CASE_SET_NVU32(bootloader_used);
default:
return -ENODATA;
}
return 0;
}
/*
* Note: On input, *length is the size of Data. On output, *length is the
* actual size used.
*/
static int
bct_get_data(nvbct_lib_id id,
u_int8_t *data,
u_int32_t *length,
u_int8_t *bct)
{
return 0;
}
static int
bct_set_data(nvbct_lib_id id,
u_int8_t *data,
u_int32_t length,
u_int8_t *bct)
{
nvboot_config_table *bct_ptr = (nvboot_config_table*)bct;
if (data == NULL || bct == NULL)
return -ENODATA;
switch (id) {
CASE_SET_DATA(crypto_hash, sizeof(nvboot_hash));
default:
return -ENODATA;
}
return 0;
}
void
nvbct_lib_get_fns(nvbct_lib_fns *fns)
{
fns->get_value = bct_get_value;
fns->set_value = bct_set_value;
fns->get_data = bct_get_data;
fns->set_data = bct_set_data;
fns->getbl_param = getbl_param;
fns->setbl_param = setbl_param;
}

View File

@@ -0,0 +1,151 @@
/**
* 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
*/
#ifndef INCLUDED_NVBOOT_BCT_H
#define INCLUDED_NVBOOT_BCT_H
#include <sys/types.h>
/**
* Defines the number of 32-bit words in the customer_data area of the BCT.
*/
#define NVBOOT_BCT_CUSTOMER_DATA_WORDS 298
/**
* Defines the number of bytes in the customer_data area of the BCT.
*/
#define NVBOOT_BCT_CUSTOMER_DATA_SIZE \
(NVBOOT_BCT_CUSTOMER_DATA_WORDS * 4)
/**
* Defines the number of bytes in the reserved area of the BCT.
*/
#define NVBOOT_BCT_RESERVED_SIZE 3
/**
* Defines the maximum number of bootloader descriptions in the BCT.
*/
#define NVBOOT_MAX_BOOTLOADERS 4
#define NVBOOT_BCT_USED_DATA_SIZE 534
/**
* Defines the number of entries (bits) in the bad block table.
* The consequences of changing its value are as follows. Using P as the
* # of physical blocks in the boot loader and B as the value of this
* constant:
* B > P: There will be unused storage in the bad block table.
* B < P: The virtual block size will be greater than the physical block
* size, so the granularity of the bad block table will be less than
* one bit per physical block.
*
* 4096 bits is enough to represent an 8MiB partition of 2KiB blocks with one
* bit per block (1 virtual block = 1 physical block). This occupies 512 bytes
* of storage.
*/
#define NVBOOT_BAD_BLOCK_TABLE_SIZE 4096
/**
* Defines the maximum number of blocks to search for BCTs.
*
* This value covers the initial block and a set of journal blocks.
*
* Ideally, this number will span several erase units for reliable updates
* and tolerance for blocks to become bad with use. Safe updates require
* a minimum of 2 erase units in which BCTs can appear.
*
* To ensure that the BCT search spans a sufficient range of configurations,
* the search block count has been set to 64. This allows for redundancy with
* a wide range of parts and provides room for greater problems in this
* region of the device.
*/
#define NVBOOT_MAX_BCT_SEARCH_BLOCKS 64
/*
* Defines the CMAC-AES-128 hash length in 32 bit words. (128 bits = 4 words)
*/
enum {NVBOOT_CMAC_AES_HASH_LENGTH = 4};
/**
* Defines the storage for a hash value (128 bits).
*/
typedef struct nvboot_hash_rec
{
u_int32_t hash[NVBOOT_CMAC_AES_HASH_LENGTH];
} nvboot_hash;
/**
* Stores information needed to locate and verify a boot loader.
*
* There is one \c nv_bootloader_info structure for each copy of a BL stored on
* the device.
*/
typedef struct nv_bootloader_info_rec
{
u_int32_t version;
u_int32_t start_blk;
u_int32_t start_page;
u_int32_t length;
u_int32_t load_addr;
u_int32_t entry_point;
u_int32_t attribute;
nvboot_hash crypto_hash;
} nv_bootloader_info;
/**
* Defines the bad block table structure stored in the BCT.
*/
typedef struct nvboot_badblock_table_rec
{
u_int32_t entries_used;
u_int8_t virtual_blk_size_log2;
u_int8_t block_size_log2;
u_int8_t bad_blks[NVBOOT_BAD_BLOCK_TABLE_SIZE / 8];
} nvboot_badblock_table;
/**
* Contains the information needed to load BLs from the secondary boot device.
*
* - Supplying NumParamSets = 0 indicates not to load any of them.
* - Supplying NumDramSets = 0 indicates not to load any of them.
* - The \c random_aes_blk member exists to increase the difficulty of
* key attacks based on knowledge of this structure.
*/
typedef struct nvboot_config_table_rec
{
nvboot_hash crypto_hash;
nvboot_hash random_aes_blk;
u_int32_t boot_data_version;
u_int32_t block_size_log2;
u_int32_t page_size_log2;
u_int32_t partition_size;
u_int32_t bct_used_data[NVBOOT_BCT_USED_DATA_SIZE];
nvboot_badblock_table badblock_table;
u_int32_t bootloader_used;
nv_bootloader_info bootloader[NVBOOT_MAX_BOOTLOADERS];
u_int8_t customer_data[NVBOOT_BCT_CUSTOMER_DATA_SIZE];
u_int8_t enable_fail_back;
u_int8_t reserved[NVBOOT_BCT_RESERVED_SIZE];
} nvboot_config_table;
/** @} */
#endif /* #ifndef INCLUDED_NVBOOT_BCT_H */

527
system/cbootimage/parse.c Normal file
View File

@@ -0,0 +1,527 @@
/**
* 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
*/
/*
* parse.c - Parsing support for the cbootimage tool
*/
/*
* TODO / Notes
* - Add doxygen commentary
* - Do we have endian issues to deal with?
* - Add support for device configuration data
* - Add support for bad blocks
* - Add support for different allocation modes/strategies
* - Add support for multiple BCTs in journal block
* - Add support for other missing features.
*/
#include "parse.h"
#include "cbootimage.h"
#include "data_layout.h"
#include "crypto.h"
#include "set.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.
*/
static char *parse_u32(char *statement, u_int32_t *val);
static char *parse_filename(char *statement, char *name, int chars_remaining);
static int
parse_array(build_image_context *context, parse_token token, char *rest);
static int
parse_bootloader(build_image_context *context, parse_token token, char *rest);
static int
parse_value_u32(build_image_context *context, parse_token token, char *rest);
static int
parse_bct_file(build_image_context *context, parse_token token, char *rest);
static int
parse_addon(build_image_context *context, parse_token token, char *rest);
static char *parse_string(char *statement, char *uname, int chars_remaining);
static char
*parse_end_state(char *statement, char *uname, int chars_remaining);
static int process_statement(build_image_context *context, char *statement);
static parse_item s_top_level_items[] =
{
{ "Bctfile=", token_bct_file, parse_bct_file },
{ "Attribute=", token_attribute, parse_value_u32 },
{ "Attribute[", token_attribute, parse_array },
{ "BootLoader=", token_bootloader, parse_bootloader },
{ "Redundancy=", token_redundancy, parse_value_u32 },
{ "Version=", token_version, parse_value_u32 },
{ "AddOn[", token_addon, parse_addon },
{ NULL, 0, NULL } /* Must be last */
};
/* Macro to simplify parser code a bit. */
#define PARSE_COMMA(x) if (*rest != ',') return (x); rest++
/* This parsing code was initially borrowed from nvcamera_config_parse.c. */
/* Returns the address of the character after the parsed data. */
static char *
parse_u32(char *statement, u_int32_t *val)
{
u_int32_t value = 0;
while (*statement=='0') {
statement++;
}
if (*statement=='x' || *statement=='X') {
statement++;
while (((*statement >= '0') && (*statement <= '9')) ||
((*statement >= 'a') && (*statement <= 'f')) ||
((*statement >= 'A') && (*statement <= 'F'))) {
value *= 16;
if ((*statement >= '0') && (*statement <= '9')) {
value += (*statement - '0');
} else if ((*statement >= 'A') &&
(*statement <= 'F')) {
value += ((*statement - 'A')+10);
} else {
value += ((*statement - 'a')+10);
}
statement++;
}
} else {
while (*statement >= '0' && *statement <= '9') {
value = value*10 + (*statement - '0');
statement++;
}
}
*val = value;
return statement;
}
/* This parsing code was initially borrowed from nvcamera_config_parse.c. */
/* Returns the address of the character after the parsed data. */
static char *
parse_filename(char *statement, char *name, int chars_remaining)
{
while (((*statement >= '0') && (*statement <= '9')) ||
((*statement >= 'a') && (*statement <= 'z')) ||
((*statement >= 'A') && (*statement <= 'Z')) ||
(*statement == '\\') ||
(*statement == '/' ) ||
(*statement == '~' ) ||
(*statement == '_' ) ||
(*statement == '-' ) ||
(*statement == '+' ) ||
(*statement == ':' ) ||
(*statement == '.' )) {
/* Check if the filename buffer is out of space, preserving one
* character to null terminate the string.
*/
chars_remaining--;
if (chars_remaining < 1)
return NULL;
*name++ = *statement++;
}
/* Null terminate the filename. */
*name = '\0';
return statement;
}
/*
* parse_bootloader(): Processes commands to set a bootloader.
*/
static int parse_bootloader(build_image_context *context,
parse_token token,
char *rest)
{
char filename[MAX_BUFFER];
char e_state[MAX_STR_LEN];
u_int32_t load_addr;
u_int32_t entry_point;
assert(context != NULL);
assert(rest != NULL);
/* Parse the file name. */
rest = parse_filename(rest, filename, MAX_BUFFER);
if (rest == NULL)
return 1;
PARSE_COMMA(1);
/* Parse the load address. */
rest = parse_u32(rest, &load_addr);
if (rest == NULL)
return 1;
PARSE_COMMA(1);
/* Parse the entry point. */
rest = parse_u32(rest, &entry_point);
if (rest == NULL)
return 1;
PARSE_COMMA(1);
/* Parse the end state. */
rest = parse_end_state(rest, e_state, MAX_STR_LEN);
if (rest == NULL)
return 1;
if (strncmp(e_state, "Complete", strlen("Complete")))
return 1;
/* Parsing has finished - set the bootloader */
return set_bootloader(context, filename, load_addr, entry_point);
}
/*
* parse_array(): Processes commands to set an array value.
*/
static int
parse_array(build_image_context *context, parse_token token, char *rest)
{
u_int32_t index;
u_int32_t value;
assert(context != NULL);
assert(rest != NULL);
/* Parse the index. */
rest = parse_u32(rest, &index);
if (rest == NULL)
return 1;
/* Parse the closing bracket. */
if (*rest != ']')
return 1;
rest++;
/* Parse the equals sign.*/
if (*rest != '=')
return 1;
rest++;
/* Parse the value based on the field table. */
switch(token) {
case token_attribute:
rest = parse_u32(rest, &value);
break;
default:
/* Unknown token */
return 1;
}
if (rest == NULL)
return 1;
/* Store the result. */
return context_set_array(context, index, token, value);
}
/*
* parse_value_u32(): General handler for setting u_int32_t values in config files.
*/
static int parse_value_u32(build_image_context *context,
parse_token token,
char *rest)
{
u_int32_t value;
assert(context != NULL);
assert(rest != NULL);
rest = parse_u32(rest, &value);
if (rest == NULL)
return 1;
return context_set_value(context, token, value);
}
static int
parse_bct_file(build_image_context *context, parse_token token, char *rest)
{
char filename[MAX_BUFFER];
assert(context != NULL);
assert(rest != NULL);
/* Parse the file name. */
rest = parse_filename(rest, filename, MAX_BUFFER);
if (rest == NULL)
return 1;
/* Parsing has finished - set the bctfile */
context->bct_filename = filename;
/* Read the bct file to buffer */
read_bct_file(context);
return 0;
}
static char *
parse_string(char *statement, char *uname, int chars_remaining)
{
memset(uname, 0, chars_remaining);
while (((*statement >= '0') && (*statement <= '9')) ||
((*statement >= 'A') && (*statement <= 'Z')) ||
((*statement >= 'a') && (*statement <= 'z'))) {
*uname++ = *statement++;
if (--chars_remaining < 0) {
printf("String length beyond the boundary!!!");
return NULL;
}
}
*uname = '\0';
return statement;
}
static char *
parse_end_state(char *statement, char *uname, int chars_remaining)
{
while (((*statement >= 'a') && (*statement <= 'z')) ||
((*statement >= 'A') && (*statement <= 'Z'))) {
*uname++ = *statement++;
if (--chars_remaining < 0)
return NULL;
}
*uname = '\0';
return statement;
}
/* Parse the addon component */
static int
parse_addon(build_image_context *context, parse_token token, char *rest)
{
char filename[MAX_BUFFER];
char u_name[4];
char e_state[MAX_STR_LEN];
u_int32_t index;
u_int32_t item_attr;
u_int32_t others;
char other_str[MAX_STR_LEN];
assert(context != NULL);
assert(rest != NULL);
/* Parse the index. */
rest = parse_u32(rest, &index);
if (rest == NULL)
return 1;
/* Parse the closing bracket. */
if (*rest != ']')
return 1;
rest++;
/* Parse the equals sign.*/
if (*rest != '=')
return 1;
rest++;
rest = parse_filename(rest, filename, MAX_BUFFER);
if (rest == NULL)
return 1;
if (set_addon_filename(context, filename, index) != 0)
return 1;
PARSE_COMMA(1);
rest = parse_string(rest, u_name, 3);
if (rest == NULL) {
printf("Unique name should be 3 characters.\n");
return 1;
}
if (set_unique_name(context, u_name, index) != 0)
return 1;
PARSE_COMMA(1);
rest = parse_u32(rest, &item_attr);
if (rest == NULL)
return 1;
if (set_addon_attr(context, item_attr, index) != 0)
return 1;
PARSE_COMMA(1);
if (*rest == '0' && (*(rest + 1) == 'x' ||*(rest + 1) == 'X')) {
rest = parse_u32(rest, &others);
if (set_other_field(context, NULL, others, index) != 0)
return 1;
} else {
rest = parse_string(rest, other_str, 16);
if (set_other_field(context, other_str, 0, index) != 0)
return 1;
}
if (rest == NULL)
return 1;
PARSE_COMMA(1);
rest = parse_end_state(rest, e_state, MAX_STR_LEN);
if (rest == NULL)
return 1;
if (strncmp(e_state, "Complete", strlen("Complete")))
return 1;
return 0;
}
/* Return 0 on success, 1 on error */
static int
process_statement(build_image_context *context, char *statement)
{
int i;
char *rest;
for (i = 0; s_top_level_items[i].prefix != NULL; i++) {
if (!strncmp(s_top_level_items[i].prefix, statement,
strlen(s_top_level_items[i].prefix))) {
rest = statement + strlen(s_top_level_items[i].prefix);
return s_top_level_items[i].process(context,
s_top_level_items[i].token,
rest);
}
}
/* If this point was reached, there was a processing error. */
return 1;
}
/* Note: Basic parsing borrowed from nvcamera_config.c */
void process_config_file(build_image_context *context)
{
char buffer[MAX_BUFFER];
int space = 0;
char current;
u_int8_t c_eol_comment_start = 0; // True after first slash
u_int8_t comment = 0;
u_int8_t string = 0;
u_int8_t equal_encounter = 0;
assert(context != NULL);
assert(context->config_file != NULL);
while ((current = fgetc(context->config_file)) !=EOF) {
if (space >= (MAX_BUFFER-1)) {
/* if we exceeded the max buffer size, it is likely
due to a missing semi-colon at the end of a line */
printf("Config file parsing error!");
exit(1);
}
/* Handle failure to complete "//" comment token.
Insert the '/' into the busffer and proceed with
processing the current character. */
if (c_eol_comment_start && current != '/') {
c_eol_comment_start = 0;
buffer[space++] = '/';
}
switch (current) {
case '\"': /* " indicates start or end of a string */
if (!comment) {
string ^= 1;
buffer[space++] = current;
}
break;
case ';':
if (!string && !comment) {
buffer[space++] = '\0';
/* Process a statement. */
if (process_statement(context, buffer)) {
goto error;
}
space = 0;
equal_encounter = 0;
} else if (string) {
buffer[space++] = current;
}
break;
case '/':
if (!string && !comment) {
if (c_eol_comment_start) {
/* EOL comment started. */
comment = 1;
c_eol_comment_start = 0;
} else {
/* Potential start of eol comment. */
c_eol_comment_start = 1;
}
} else if (!comment) {
buffer[space++] = current;
}
break;
/* ignore whitespace. uses fallthrough */
case '\n':
case '\r': /* carriage returns end comments */
string = 0;
comment = 0;
c_eol_comment_start = 0;
case ' ':
case '\t':
if (string) {
buffer[space++] = current;
}
break;
case '#':
if (!string) {
comment = 1;
} else {
buffer[space++] = current;
}
break;
default:
if (!comment) {
buffer[space++] = current;
if (current == '=') {
if (!equal_encounter) {
equal_encounter = 1;
} else {
goto error;
}
}
}
break;
}
}
return;
error:
printf("Error parsing: %s\n", buffer);
exit(1);
}

74
system/cbootimage/parse.h Normal file
View File

@@ -0,0 +1,74 @@
/**
* 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
*/
/*
* parse.h - Definitions for the cbootimage parsing code.
*/
/*
* TODO / Notes
* - Add doxygen commentary
*/
#ifndef INCLUDED_PARSE_H
#define INCLUDED_PARSE_H
#include "cbootimage.h"
/*
* Enums
*/
typedef enum
{
token_none = 0,
token_attribute,
token_bootloader,
token_page_size,
token_redundancy,
token_version,
token_bct_file,
token_addon,
token_force32 = 0x7fffffff
} parse_token;
/* Forward declarations */
typedef int (*process_function)(build_image_context *context,
parse_token token,
char *Remiainder);
typedef struct
{
char *prefix;
parse_token token;
process_function process;
} parse_item;
/*
* Function prototypes
*/
void process_config_file(build_image_context *context);
#endif /* #ifndef INCLUDED_PARSE_H */

306
system/cbootimage/set.c Normal file
View File

@@ -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;
}

81
system/cbootimage/set.h Normal file
View File

@@ -0,0 +1,81 @@
/**
* 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.h - Definitions for the cbootimage state setting code.
*/
#ifndef INCLUDED_SET_H
#define INCLUDED_SET_H
#include "cbootimage.h"
#include "parse.h"
#include "string.h"
#include "sys/stat.h"
int
context_set_array(build_image_context *context,
u_int32_t index,
parse_token token,
u_int32_t value);
int
set_bootloader(build_image_context *context,
char *filename,
u_int32_t load_addr,
u_int32_t entry_point);
int
context_set_value(build_image_context *context,
parse_token token,
u_int32_t value);
int
set_addon_filename(build_image_context *context,
char *filename,
int index);
int
set_addon_attr(build_image_context *context,
u_int32_t file_attr,
int index);
int
set_unique_name(build_image_context *context,
char *uname,
int index);
int
set_other_field(build_image_context *context,
char *other_str,
int other,
int index);
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);
#endif /* #ifndef INCLUDED_SET_H */