mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2026-01-09 17:11:42 +00:00
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:
20
system/cbootimage/GNUmakefile
Normal file
20
system/cbootimage/GNUmakefile
Normal 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
330
system/cbootimage/aes_ref.c
Normal 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));
|
||||
}
|
||||
258
system/cbootimage/cbootimage.c
Normal file
258
system/cbootimage/cbootimage.c
Normal 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;
|
||||
}
|
||||
141
system/cbootimage/cbootimage.h
Normal file
141
system/cbootimage/cbootimage.h
Normal 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
303
system/cbootimage/crypto.c
Normal 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;
|
||||
}
|
||||
|
||||
50
system/cbootimage/crypto.h
Normal file
50
system/cbootimage/crypto.h
Normal 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 */
|
||||
1027
system/cbootimage/data_layout.c
Normal file
1027
system/cbootimage/data_layout.c
Normal file
File diff suppressed because it is too large
Load Diff
56
system/cbootimage/data_layout.h
Normal file
56
system/cbootimage/data_layout.h
Normal 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 */
|
||||
37
system/cbootimage/nvaes_ref.h
Normal file
37
system/cbootimage/nvaes_ref.h
Normal 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
|
||||
126
system/cbootimage/nvbctlib.h
Normal file
126
system/cbootimage/nvbctlib.h
Normal 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 */
|
||||
282
system/cbootimage/nvbctlib_ap20.c
Normal file
282
system/cbootimage/nvbctlib_ap20.c
Normal 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;
|
||||
}
|
||||
151
system/cbootimage/nvboot_bct.h
Normal file
151
system/cbootimage/nvboot_bct.h
Normal 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
527
system/cbootimage/parse.c
Normal 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
74
system/cbootimage/parse.h
Normal 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
306
system/cbootimage/set.c
Normal 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
81
system/cbootimage/set.h
Normal 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 */
|
||||
Reference in New Issue
Block a user