summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAmaury Pouly <pamaury@rockbox.org>2011-11-06 01:49:13 +0000
committerAmaury Pouly <pamaury@rockbox.org>2011-11-06 01:49:13 +0000
commit5827937270bac874ae9e04679b3130fef9e306c4 (patch)
tree51bc262dedecdb7620300b46f23005c4b0eed311
parent33d6bd61b51178b42a07a97118a689d849666331 (diff)
sbtools: rename to imxtools, move imx_hid_recovery to imxtools/sbloader, fix tools to correctly handle/free memory, properly return error codes
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30907 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--utils/imx_hid_recovery/Makefile15
-rw-r--r--utils/imxtools/Makefile (renamed from utils/sbtools/Makefile)8
-rw-r--r--utils/imxtools/README (renamed from utils/sbtools/README)0
-rw-r--r--utils/imxtools/aes128.c (renamed from utils/sbtools/aes128.c)0
-rw-r--r--utils/imxtools/crc.c (renamed from utils/sbtools/crc.c)0
-rw-r--r--utils/imxtools/crypto.c (renamed from utils/sbtools/crypto.c)0
-rw-r--r--utils/imxtools/crypto.h (renamed from utils/sbtools/crypto.h)1
-rw-r--r--utils/imxtools/dbparser.c (renamed from utils/sbtools/dbparser.c)164
-rw-r--r--utils/imxtools/dbparser.h (renamed from utils/sbtools/dbparser.h)4
-rw-r--r--utils/imxtools/elf.c (renamed from utils/sbtools/elf.c)21
-rw-r--r--utils/imxtools/elf.h (renamed from utils/sbtools/elf.h)0
-rw-r--r--utils/imxtools/elftosb.c (renamed from utils/sbtools/elftosb.c)24
-rw-r--r--utils/imxtools/fuze+_key_file.txt (renamed from utils/sbtools/fuze+_key_file.txt)0
-rw-r--r--utils/imxtools/misc.c (renamed from utils/sbtools/misc.c)14
-rw-r--r--utils/imxtools/misc.h (renamed from utils/sbtools/misc.h)2
-rw-r--r--utils/imxtools/sb.c (renamed from utils/sbtools/sb.c)285
-rw-r--r--utils/imxtools/sb.h (renamed from utils/sbtools/sb.h)26
-rw-r--r--utils/imxtools/sbloader.c (renamed from utils/imx_hid_recovery/imx_hid_recovery.c)0
-rw-r--r--utils/imxtools/sbtoelf.c (renamed from utils/sbtools/sbtoelf.c)18
-rw-r--r--utils/imxtools/sha1.c (renamed from utils/sbtools/sha1.c)0
20 files changed, 388 insertions, 194 deletions
diff --git a/utils/imx_hid_recovery/Makefile b/utils/imx_hid_recovery/Makefile
deleted file mode 100644
index 24d0b8e3d3..0000000000
--- a/utils/imx_hid_recovery/Makefile
+++ /dev/null
@@ -1,15 +0,0 @@
-CC=gcc
-LD=gcc
-
-all: imx_hid_recovery
-
-imx_hid_recovery.o: imx_hid_recovery.c
- $(CC) -c -Wall -O2 -std=c99 `pkg-config --cflags libusb-1.0` -o $@ $<
-
-imx_hid_recovery: imx_hid_recovery.o
- $(LD) -o $@ $< `pkg-config --libs libusb-1.0`
-
-clean:
- rm -rf imx_hid_recovery.o
-
-
diff --git a/utils/sbtools/Makefile b/utils/imxtools/Makefile
index 69e63c9ac2..7a09d86d24 100644
--- a/utils/sbtools/Makefile
+++ b/utils/imxtools/Makefile
@@ -3,8 +3,9 @@ CC=gcc
LD=gcc
CFLAGS=-g -std=c99 -W -Wall `pkg-config --cflags libusb-1.0` $(DEFINES)
LDFLAGS=`pkg-config --libs libusb-1.0`
+BINS=elftosb sbtoelf sbloader
-all: elftosb sbtoelf
+all: $(BINS)
%.o: %.c
$(CC) $(CFLAGS) -c -o $@ $<
@@ -15,8 +16,11 @@ sbtoelf: sbtoelf.o crc.o crypto.o aes128.o sha1.o elf.o misc.o sb.o
elftosb: elftosb.o crc.o crypto.o aes128.o sha1.o elf.o dbparser.o misc.o sb.o
$(LD) -o $@ $^ $(LDFLAGS)
+sbloader: sbloader.o
+ $(LD) -o $@ $^ $(LDFLAGS)
+
clean:
rm -fr *.o
veryclean:
- rm -rf sbtoelf elftosb
+ rm -rf $(BINS)
diff --git a/utils/sbtools/README b/utils/imxtools/README
index 8bf6fd5f8e..8bf6fd5f8e 100644
--- a/utils/sbtools/README
+++ b/utils/imxtools/README
diff --git a/utils/sbtools/aes128.c b/utils/imxtools/aes128.c
index 5870813db8..5870813db8 100644
--- a/utils/sbtools/aes128.c
+++ b/utils/imxtools/aes128.c
diff --git a/utils/sbtools/crc.c b/utils/imxtools/crc.c
index eaf257ddfe..eaf257ddfe 100644
--- a/utils/sbtools/crc.c
+++ b/utils/imxtools/crc.c
diff --git a/utils/sbtools/crypto.c b/utils/imxtools/crypto.c
index d4afc6c816..d4afc6c816 100644
--- a/utils/sbtools/crypto.c
+++ b/utils/imxtools/crypto.c
diff --git a/utils/sbtools/crypto.h b/utils/imxtools/crypto.h
index 51f44406db..452db6a28d 100644
--- a/utils/sbtools/crypto.h
+++ b/utils/imxtools/crypto.h
@@ -63,6 +63,7 @@ void crypto_setup(enum crypto_method_t method, void *param);
#define CRYPTO_ERROR_DEVREJECT -5 /* device rejected cypto operation */
#define CRYPTO_ERROR_DEVSILENT -6 /* device did not notify completion */
#define CRYPTO_ERROR_DEVERR -7 /* device did something wrong (like return too small buffer) */
+#define CRYPTO_NUM_ERRORS 8
/* return 0 on success, <0 on error */
int crypto_apply(
byte *in_data, /* Input data */
diff --git a/utils/sbtools/dbparser.c b/utils/imxtools/dbparser.c
index 3cd0652d49..b2027e5ad7 100644
--- a/utils/sbtools/dbparser.c
+++ b/utils/imxtools/dbparser.c
@@ -19,6 +19,7 @@
*
****************************************************************************/
+#define _POSIX_C_SOURCE 200809L /* for strdup */
#include <stdio.h>
#include <ctype.h>
#include <stdint.h>
@@ -48,6 +49,7 @@ enum lexem_type_t
struct lexem_t
{
enum lexem_type_t type;
+ /* if str is not NULL, it must be a malloc'd pointer */
char *str;
uint32_t num;
int line;
@@ -390,8 +392,15 @@ struct lex_ctx_t
struct lexem_t lexem;
};
-static inline void next(struct lex_ctx_t *ctx)
+/* When lexems hold strings (like identifier), it might be useful to steal
+ * the pointer and don't clean the lexem but in other case, one don't want
+ * to keep the pointer to the string and just want to release the memory.
+ * Thus clean_lexem should be true except when one keeps a pointer */
+static inline void next(struct lex_ctx_t *ctx, bool clean_lexem)
{
+ if(clean_lexem)
+ free(ctx->lexem.str);
+ memset(&ctx->lexem, 0, sizeof(struct lexem_t));
next_lexem(&ctx->ctx, &ctx->lexem);
}
@@ -411,7 +420,7 @@ static uint32_t parse_term_expr(struct lex_ctx_t *ctx, struct cmd_option_t *cons
}
else
parse_error(ctx->lexem, "Number or constant identifier expected\n");
- next(ctx);
+ next(ctx, true);
return ret;
}
@@ -420,7 +429,7 @@ static uint32_t parse_shift_expr(struct lex_ctx_t *ctx, struct cmd_option_t *con
uint32_t v = parse_term_expr(ctx, const_list);
while(ctx->lexem.type == LEX_LSHIFT)
{
- next(ctx);
+ next(ctx, true);
v <<= parse_term_expr(ctx, const_list);
}
return v;
@@ -431,7 +440,7 @@ static uint32_t parse_or_expr(struct lex_ctx_t *ctx, struct cmd_option_t *const_
uint32_t v = parse_shift_expr(ctx, const_list);
while(ctx->lexem.type == LEX_OR)
{
- next(ctx);
+ next(ctx, true);
v |= parse_shift_expr(ctx, const_list);
}
return v;
@@ -470,7 +479,7 @@ struct cmd_file_t *db_parse_file(const char *file)
{
struct cmd_option_t *opt = xmalloc(sizeof(struct cmd_option_t));
memset(opt, 0, sizeof(struct cmd_option_t));
- opt->name = init_const_name[i];
+ opt->name = strdup(init_const_name[i]);
opt->is_string = false;
opt->val = init_const_value[i];
opt->next = cmd_file->constant_list;
@@ -483,14 +492,14 @@ struct cmd_file_t *db_parse_file(const char *file)
lctx.ctx.begin = buf;
lctx.ctx.ptr = buf;
lctx.ctx.end = buf + size;
- #define next() next(&lctx)
+ #define next(clean_lexem) next(&lctx, clean_lexem)
#define lexem lctx.lexem
/* init lexer */
- next();
+ next(false); /* don't clean init lexem because it doesn't exist */
/* constants ? */
if(lexem.type == LEX_IDENTIFIER && !strcmp(lexem.str, "constants"))
{
- next();
+ next(true);
if(lexem.type != LEX_LBRACE)
parse_error(lexem, "'{' expected after 'constants'\n");
@@ -498,16 +507,16 @@ struct cmd_file_t *db_parse_file(const char *file)
{
struct cmd_option_t *opt = xmalloc(sizeof(struct cmd_option_t));
memset(opt, 0, sizeof(struct cmd_option_t));
- next();
+ next(true);
if(lexem.type == LEX_RBRACE)
break;
if(lexem.type != LEX_IDENTIFIER)
parse_error(lexem, "Identifier expected in constants\n");
opt->name = lexem.str;
- next();
+ next(false); /* lexem string is kept as option name */
if(lexem.type != LEX_EQUAL)
parse_error(lexem, "'=' expected after identifier\n");
- next();
+ next(true);
opt->is_string = false;
opt->val = parse_intexpr(&lctx, cmd_file->constant_list);
opt->next = cmd_file->constant_list;
@@ -515,34 +524,34 @@ struct cmd_file_t *db_parse_file(const char *file)
if(lexem.type != LEX_SEMICOLON)
parse_error(lexem, "';' expected after string\n");
}
- next();
+ next(true);
}
/* options ? */
if(lexem.type == LEX_IDENTIFIER && !strcmp(lexem.str, "options"))
{
- next();
+ next(true);
if(lexem.type != LEX_LBRACE)
parse_error(lexem, "'{' expected after 'options'\n");
while(true)
{
- struct cmd_option_t *opt = xmalloc(sizeof(struct cmd_option_t));
- memset(opt, 0, sizeof(struct cmd_option_t));
- next();
+ next(true);
if(lexem.type == LEX_RBRACE)
break;
+ struct cmd_option_t *opt = xmalloc(sizeof(struct cmd_option_t));
+ memset(opt, 0, sizeof(struct cmd_option_t));
if(lexem.type != LEX_IDENTIFIER)
parse_error(lexem, "Identifier expected in options\n");
opt->name = lexem.str;
- next();
+ next(false); /* lexem string is kept as option name */
if(lexem.type != LEX_EQUAL)
parse_error(lexem, "'=' expected after identifier\n");
- next();
+ next(true);
if(lexem.type == LEX_STRING)
{
opt->is_string = true;
opt->str = lexem.str;
- next();
+ next(false); /* lexem string is kept as option name */
}
else
{
@@ -554,18 +563,18 @@ struct cmd_file_t *db_parse_file(const char *file)
if(lexem.type != LEX_SEMICOLON)
parse_error(lexem, "';' expected after string\n");
}
- next();
+ next(true);
}
/* sources */
if(lexem.type != LEX_IDENTIFIER || strcmp(lexem.str, "sources"))
parse_error(lexem, "'sources' expected\n");
- next();
+ next(true);
if(lexem.type != LEX_LBRACE)
parse_error(lexem, "'{' expected after 'sources'\n");
while(true)
{
- next();
+ next(true);
if(lexem.type == LEX_RBRACE)
break;
struct cmd_source_t *src = xmalloc(sizeof(struct cmd_source_t));
@@ -573,28 +582,28 @@ struct cmd_file_t *db_parse_file(const char *file)
if(lexem.type != LEX_IDENTIFIER)
parse_error(lexem, "identifier expected in sources\n");
src->identifier = lexem.str;
- next();
+ next(false); /* lexem string is kept as source name */
if(lexem.type != LEX_EQUAL)
parse_error(lexem, "'=' expected after identifier\n");
- next();
+ next(true);
if(lexem.type == LEX_STRING)
{
src->is_extern = false;
src->filename = lexem.str;
- next();
+ next(false); /* lexem string is kept as file name */
}
else if(lexem.type == LEX_IDENTIFIER && !strcmp(lexem.str, "extern"))
{
src->is_extern = true;
- src->filename = "<extern>";
- next();
+ src->filename = strdup("<extern>"); /* duplicate because it will be free'd */
+ next(true);
if(lexem.type != LEX_LPAREN)
parse_error(lexem, "'(' expected after 'extern'\n");
- next();
+ next(true);
src->extern_nr = parse_intexpr(&lctx, cmd_file->constant_list);
if(lexem.type != LEX_RPAREN)
parse_error(lexem, "')' expected\n");
- next();
+ next(true);
}
else
parse_error(lexem, "String or 'extern' expected after '='\n");
@@ -612,18 +621,18 @@ struct cmd_file_t *db_parse_file(const char *file)
struct cmd_section_t *end_sec = NULL;
while(true)
{
+ next(true);
+ if(lexem.type == LEX_EOF)
+ break;
struct cmd_section_t *sec = xmalloc(sizeof(struct cmd_section_t));
struct cmd_inst_t *end_list = NULL;
memset(sec, 0, sizeof(struct cmd_section_t));
- next();
- if(lexem.type == LEX_EOF)
- break;
if(lexem.type != LEX_IDENTIFIER || strcmp(lexem.str, "section") != 0)
parse_error(lexem, "'section' expected\n");
- next();
+ next(true);
if(lexem.type != LEX_LPAREN)
parse_error(lexem, "'(' expected after 'section'\n");
- next();
+ next(true);
/* can be any number */
sec->identifier = parse_intexpr(&lctx, cmd_file->constant_list);
/* options ? */
@@ -631,21 +640,21 @@ struct cmd_file_t *db_parse_file(const char *file)
{
do
{
- next();
+ next(true);
struct cmd_option_t *opt = xmalloc(sizeof(struct cmd_option_t));
memset(opt, 0, sizeof(struct cmd_option_t));
if(lexem.type != LEX_IDENTIFIER)
parse_error(lexem, "Identifier expected for section option\n");
opt->name = lexem.str;
- next();
+ next(false); /* lexem string is kept as option name */
if(lexem.type != LEX_EQUAL)
parse_error(lexem, "'=' expected after option identifier\n");
- next();
+ next(true);
if(lexem.type == LEX_STRING)
{
opt->is_string = true;
opt->str = lexem.str;
- next();
+ next(false); /* lexem string is kept as option string */
}
else
{
@@ -658,18 +667,18 @@ struct cmd_file_t *db_parse_file(const char *file)
}
if(lexem.type != LEX_RPAREN)
parse_error(lexem, "')' expected after section identifier\n");
- next();
+ next(true);
if(lexem.type == LEX_LBRACE)
{
sec->is_data = false;
/* commands */
while(true)
{
- struct cmd_inst_t *inst = xmalloc(sizeof(struct cmd_inst_t));
- memset(inst, 0, sizeof(struct cmd_inst_t));
- next();
+ next(true);
if(lexem.type == LEX_RBRACE)
break;
+ struct cmd_inst_t *inst = xmalloc(sizeof(struct cmd_inst_t));
+ memset(inst, 0, sizeof(struct cmd_inst_t));
if(lexem.type != LEX_IDENTIFIER)
parse_error(lexem, "Instruction expected in section\n");
if(strcmp(lexem.str, "load") == 0)
@@ -682,7 +691,7 @@ struct cmd_file_t *db_parse_file(const char *file)
inst->type = CMD_MODE;
else
parse_error(lexem, "Instruction expected in section\n");
- next();
+ next(true);
if(inst->type == CMD_LOAD)
{
@@ -691,12 +700,12 @@ struct cmd_file_t *db_parse_file(const char *file)
inst->identifier = lexem.str;
if(db_find_source_by_id(cmd_file, inst->identifier) == NULL)
parse_error(lexem, "Undefined reference to source '%s'\n", inst->identifier);
- next();
+ next(false); /* lexem string kept as identifier */
if(lexem.type == LEX_RANGLE)
{
// load at
inst->type = CMD_LOAD_AT;
- next();
+ next(true);
inst->addr = parse_intexpr(&lctx, cmd_file->constant_list);
}
if(lexem.type != LEX_SEMICOLON)
@@ -709,7 +718,7 @@ struct cmd_file_t *db_parse_file(const char *file)
inst->identifier = lexem.str;
if(db_find_source_by_id(cmd_file, inst->identifier) == NULL)
parse_error(lexem, "Undefined reference to source '%s'\n", inst->identifier);
- next();
+ next(false); /* lexem string kept as identifier */
}
else
{
@@ -719,11 +728,11 @@ struct cmd_file_t *db_parse_file(const char *file)
if(lexem.type == LEX_LPAREN)
{
- next();
+ next(true);
inst->argument = parse_intexpr(&lctx, cmd_file->constant_list);
if(lexem.type != LEX_RPAREN)
parse_error(lexem, "Expected closing brace\n");
- next();
+ next(true);
}
if(lexem.type != LEX_SEMICOLON)
parse_error(lexem, "';' expected after command\n");
@@ -751,11 +760,11 @@ struct cmd_file_t *db_parse_file(const char *file)
else if(lexem.type == LEX_LE)
{
sec->is_data = true;
- next();
+ next(true);
if(lexem.type != LEX_IDENTIFIER)
parse_error(lexem, "Identifier expected after '<='\n");
sec->source_id = lexem.str;
- next();
+ next(false); /* lexem string is kept as source id */
if(lexem.type != LEX_SEMICOLON)
parse_error(lexem, "';' expected after identifier\n");
}
@@ -776,6 +785,7 @@ struct cmd_file_t *db_parse_file(const char *file)
#undef lexem
#undef next
+ free(buf);
return cmd_file;
}
@@ -783,3 +793,57 @@ void db_generate_default_sb_version(struct sb_version_t *ver)
{
ver->major = ver->minor = ver->revision = 0x999;
}
+
+void db_free_option_list(struct cmd_option_t *opt_list)
+{
+ while(opt_list)
+ {
+ struct cmd_option_t *next = opt_list->next;
+ fflush(stdout);
+ free(opt_list->name);
+ free(opt_list->str);
+ free(opt_list);
+ opt_list = next;
+ }
+}
+
+void db_free(struct cmd_file_t *file)
+{
+ db_free_option_list(file->opt_list);
+ db_free_option_list(file->constant_list);
+ struct cmd_source_t *src = file->source_list;
+ while(src)
+ {
+ struct cmd_source_t *next = src->next;
+ free(src->identifier);
+ fflush(stdout);
+ free(src->filename);
+ if(src->loaded)
+ {
+ if(src->type == CMD_SRC_BIN)
+ free(src->bin.data);
+ if(src->type == CMD_SRC_ELF)
+ elf_release(&src->elf);
+ }
+ free(src);
+ src = next;
+ }
+ struct cmd_section_t *sec = file->section_list;
+ while(sec)
+ {
+ struct cmd_section_t *next = sec->next;
+ db_free_option_list(sec->opt_list);
+ free(sec->source_id);
+ struct cmd_inst_t *inst = sec->inst_list;
+ while(inst)
+ {
+ struct cmd_inst_t *next = inst->next;
+ free(inst->identifier);
+ free(inst);
+ inst = next;
+ }
+ free(sec);
+ sec = next;
+ }
+ free(file);
+}
diff --git a/utils/sbtools/dbparser.h b/utils/imxtools/dbparser.h
index cfb1a692fa..4a36861583 100644
--- a/utils/sbtools/dbparser.h
+++ b/utils/imxtools/dbparser.h
@@ -102,7 +102,7 @@ struct cmd_section_t
struct cmd_file_t
{
struct cmd_option_t *opt_list;
- struct cmd_option_t *constant_list; /* constant all always integers */
+ struct cmd_option_t *constant_list; /* constant are always integers */
struct cmd_source_t *source_list;
struct cmd_section_t *section_list;
};
@@ -112,5 +112,7 @@ struct cmd_option_t *db_find_option_by_id(struct cmd_option_t *opt, const char *
bool db_parse_sb_version(struct sb_version_t *ver, char *str);
void db_generate_default_sb_version(struct sb_version_t *ver);
struct cmd_file_t *db_parse_file(const char *file);
+void db_free_option_list(struct cmd_option_t *opt_list);
+void db_free(struct cmd_file_t *file);
#endif /* __DBPARSER__ */
diff --git a/utils/sbtools/elf.c b/utils/imxtools/elf.c
index 91b5d74848..481ab98dd6 100644
--- a/utils/sbtools/elf.c
+++ b/utils/imxtools/elf.c
@@ -153,10 +153,7 @@ typedef struct
void elf_init(struct elf_params_t *params)
{
- params->has_start_addr = false;
- params->start_addr = 0;
- params->first_section = NULL;
- params->last_section = NULL;
+ memset(params, 0, sizeof(struct elf_params_t));
}
extern void *xmalloc(size_t s);
@@ -463,6 +460,7 @@ bool elf_read_file(struct elf_params_t *params, elf_read_fn_t read,
if(!read(user, shdr.sh_offset, data, shdr.sh_size))
error_printf("error read self section data\n");
elf_add_load_section(params, shdr.sh_addr, shdr.sh_size, data);
+ free(data);
if(strtab)
printf(user, false, "create load segment for %s\n", &strtab[shdr.sh_name]);
@@ -480,6 +478,7 @@ bool elf_read_file(struct elf_params_t *params, elf_read_fn_t read,
}
}
+ free(strtab);
/* run through segments */
for(int i = 1; i < ehdr.e_phnum; i++)
{
@@ -557,16 +556,20 @@ int elf_get_nr_sections(struct elf_params_t *params)
void elf_release(struct elf_params_t *params)
{
- struct elf_section_t *sec, *next_sec;
- sec = params->first_section;
+ struct elf_section_t *sec = params->first_section;
while(sec)
{
- next_sec = sec->next;
+ struct elf_section_t *next_sec = sec->next;
if(sec->type == EST_LOAD)
free(sec->section);
free(sec);
sec = next_sec;
}
- params->first_section = NULL;
- params->last_section = NULL;
+ struct elf_segment_t *seg = params->first_segment;
+ while(seg)
+ {
+ struct elf_segment_t *next_seg = seg->next;
+ free(seg);
+ seg = next_seg;
+ }
}
diff --git a/utils/sbtools/elf.h b/utils/imxtools/elf.h
index 2166833276..2166833276 100644
--- a/utils/sbtools/elf.h
+++ b/utils/imxtools/elf.h
diff --git a/utils/sbtools/elftosb.c b/utils/imxtools/elftosb.c
index b8d68b82e7..2f8700551f 100644
--- a/utils/sbtools/elftosb.c
+++ b/utils/imxtools/elftosb.c
@@ -20,6 +20,7 @@
****************************************************************************/
#define _ISOC99_SOURCE
+#define _POSIX_C_SOURCE 200809L /* for strdup */
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
@@ -77,7 +78,9 @@ static void resolve_extern(struct cmd_source_t *src)
src->is_extern = false;
if(src->extern_nr < 0 || src->extern_nr >= g_extern_count)
bug("There aren't enough file on command file to resolve extern(%d)\n", src->extern_nr);
- src->filename = g_extern[src->extern_nr];
+ /* first free the old src->filename content */
+ free(src->filename);
+ src->filename = strdup(g_extern[src->extern_nr]);
}
static void load_elf_by_id(struct cmd_file_t *cmd_file, const char *id)
@@ -206,7 +209,7 @@ static struct sb_file_t *apply_cmd_file(struct cmd_file_t *cmd_file)
sec->insts[0].inst = SB_INST_DATA;
sec->insts[0].size = bin->size;
- sec->insts[0].data = bin->data;
+ sec->insts[0].data = memdup(bin->data, bin->size);
}
else
{
@@ -266,7 +269,7 @@ static struct sb_file_t *apply_cmd_file(struct cmd_file_t *cmd_file)
sec->insts[idx].inst = SB_INST_LOAD;
sec->insts[idx].addr = esec->addr;
sec->insts[idx].size = esec->size;
- sec->insts[idx++].data = esec->section;
+ sec->insts[idx++].data = memdup(esec->section, esec->size);
}
else if(esec->type == EST_FILL)
{
@@ -296,7 +299,7 @@ static struct sb_file_t *apply_cmd_file(struct cmd_file_t *cmd_file)
struct bin_param_t *bin = &db_find_source_by_id(cmd_file, cinst->identifier)->bin;
sec->insts[idx].inst = SB_INST_LOAD;
sec->insts[idx].addr = cinst->addr;
- sec->insts[idx].data = bin->data;
+ sec->insts[idx].data = memdup(bin->data, bin->size);
sec->insts[idx++].size = bin->size;
}
else if(cinst->type == CMD_MODE)
@@ -431,11 +434,18 @@ int main(int argc, char **argv)
struct cmd_file_t *cmd_file = db_parse_file(cmd_filename);
struct sb_file_t *sb_file = apply_cmd_file(cmd_file);
+ db_free(cmd_file);
if(real_key.method == CRYPTO_KEY)
- sb_file->real_key = &real_key.u.key;
+ {
+ sb_file->override_real_key = true;
+ memcpy(sb_file->real_key, real_key.u.key, 16);
+ }
if(crypto_iv.method == CRYPTO_KEY)
- sb_file->crypto_iv = &crypto_iv.u.key;
+ {
+ sb_file->override_crypto_iv = true;
+ memcpy(sb_file->crypto_iv, crypto_iv.u.key, 16);
+ }
/* fill with default parameters since there is no command file support for them */
sb_file->drive_tag = 0;
@@ -444,6 +454,8 @@ int main(int argc, char **argv)
sb_file->minor_version = 1;
sb_write_file(sb_file, output_filename);
+ sb_free(sb_file);
+ clear_keys();
return 0;
}
diff --git a/utils/sbtools/fuze+_key_file.txt b/utils/imxtools/fuze+_key_file.txt
index a965e715f7..a965e715f7 100644
--- a/utils/sbtools/fuze+_key_file.txt
+++ b/utils/imxtools/fuze+_key_file.txt
diff --git a/utils/sbtools/misc.c b/utils/imxtools/misc.c
index 4eeda4ef33..8d7cea89d7 100644
--- a/utils/sbtools/misc.c
+++ b/utils/imxtools/misc.c
@@ -29,6 +29,14 @@ bool g_debug = false;
/**
* Misc
*/
+
+void *memdup(void *p, size_t len)
+{
+ void *cpy = xmalloc(len);
+ memcpy(cpy, p, len);
+ return cpy;
+}
+
void generate_random_data(void *buf, size_t sz)
{
FILE *rand_fd = fopen("/dev/urandom", "rb");
@@ -144,6 +152,12 @@ void add_keys(key_array_t ka, int kac)
g_nr_keys += kac;
}
+void clear_keys()
+{
+ free(g_key_array);
+ g_nr_keys = 0;
+}
+
void add_keys_from_file(const char *key_file)
{
int size;
diff --git a/utils/sbtools/misc.h b/utils/imxtools/misc.h
index 9f14497680..b0b7dfeba6 100644
--- a/utils/sbtools/misc.h
+++ b/utils/imxtools/misc.h
@@ -38,6 +38,7 @@ typedef struct crypto_key_t *key_array_t;
int g_nr_keys;
key_array_t g_key_array;
+void *memdup(void *p, size_t len);
void *augment_array(void *arr, size_t elem_sz, size_t cnt, void *aug, size_t aug_cnt);
void generate_random_data(void *buf, size_t sz);
void *xmalloc(size_t s);
@@ -47,6 +48,7 @@ void add_keys(key_array_t ka, int kac);
bool parse_key(char **str, struct crypto_key_t *key);
void add_keys_from_file(const char *key_file);
void print_key(struct crypto_key_t *key, bool newline);
+void clear_keys();
typedef char color_t[];
diff --git a/utils/sbtools/sb.c b/utils/imxtools/sb.c
index d620c00f42..44db56b7d1 100644
--- a/utils/sbtools/sb.c
+++ b/utils/imxtools/sb.c
@@ -138,7 +138,7 @@ static void compute_sb_offsets(struct sb_file_t *sb)
if(sb->sections[i].is_data)
{
nr_aug_insts = 1;
- aug_insts = malloc(sizeof(struct sb_inst_t));
+ aug_insts = xmalloc(sizeof(struct sb_inst_t));
memset(aug_insts, 0, sizeof(struct sb_inst_t));
aug_insts[0].inst = SB_INST_DATA;
aug_insts[0].size = missing_sz * BLOCK_SIZE;
@@ -150,7 +150,7 @@ static void compute_sb_offsets(struct sb_file_t *sb)
else
{
nr_aug_insts = missing_sz;
- aug_insts = malloc(sizeof(struct sb_inst_t) * nr_aug_insts);
+ aug_insts = xmalloc(sizeof(struct sb_inst_t) * nr_aug_insts);
memset(aug_insts, 0, sizeof(struct sb_inst_t) * nr_aug_insts);
for(int j = 0; j < nr_aug_insts; j++)
{
@@ -163,6 +163,7 @@ static void compute_sb_offsets(struct sb_file_t *sb)
sb->sections[i].insts = augment_array(sb->sections[i].insts, sizeof(struct sb_inst_t),
sb->sections[i].nr_insts, aug_insts, nr_aug_insts);
sb->sections[i].nr_insts += nr_aug_insts;
+ free(aug_insts);
/* augment image and section size */
sb->image_size += missing_sz;
@@ -299,12 +300,8 @@ void produce_sb_instruction(struct sb_inst_t *inst,
cmd->hdr.checksum = instruction_checksum(&cmd->hdr);
}
-void sb_write_file(struct sb_file_t *sb, const char *filename)
+enum sb_error_t sb_write_file(struct sb_file_t *sb, const char *filename)
{
- FILE *fd = fopen(filename, "wb");
- if(fd == NULL)
- bugp("cannot open output file");
-
struct crypto_key_t real_key;
real_key.method = CRYPTO_KEY;
byte crypto_iv[16];
@@ -324,8 +321,13 @@ void sb_write_file(struct sb_file_t *sb, const char *filename)
/* produce and write header */
struct sb_header_t sb_hdr;
produce_sb_header(sb, &sb_hdr);
+ /* allocate image */
+ byte *buf = xmalloc(sb_hdr.image_size * BLOCK_SIZE);
+ byte *buf_p = buf;
+ #define write(p, sz) do { memcpy(buf_p, p, sz); buf_p += sz; } while(0)
+
sha_1_update(&file_sha1, (byte *)&sb_hdr, sizeof(sb_hdr));
- fwrite(&sb_hdr, 1, sizeof(sb_hdr), fd);
+ write(&sb_hdr, sizeof(sb_hdr));
memcpy(crypto_iv, &sb_hdr, 16);
@@ -340,7 +342,7 @@ void sb_write_file(struct sb_file_t *sb, const char *filename)
struct sb_section_header_t sb_sec_hdr;
produce_sb_section_header(&sb->sections[i], &sb_sec_hdr);
sha_1_update(&file_sha1, (byte *)&sb_sec_hdr, sizeof(sb_sec_hdr));
- fwrite(&sb_sec_hdr, 1, sizeof(sb_sec_hdr), fd);
+ write(&sb_sec_hdr, sizeof(sb_sec_hdr));
/* update CBC-MACs */
for(int j = 0; j < g_nr_keys; j++)
crypto_cbc((byte *)&sb_sec_hdr, NULL, sizeof(sb_sec_hdr) / BLOCK_SIZE,
@@ -354,16 +356,18 @@ void sb_write_file(struct sb_file_t *sb, const char *filename)
crypto_cbc(real_key.u.key, entry.key, 1, &g_key_array[i],
crypto_iv, NULL, 1);
- fwrite(&entry, 1, sizeof(entry), fd);
+ write(&entry, sizeof(entry));
sha_1_update(&file_sha1, (byte *)&entry, sizeof(entry));
}
+ free(cbc_macs);
+
/* HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK */
/* Image crafting, don't use it unless you understand what you do */
- if(sb->real_key != NULL)
- memcpy(real_key.u.key, *sb->real_key, 16);
- if(sb->crypto_iv != NULL)
- memcpy(crypto_iv, *sb->crypto_iv, 16);
+ if(sb->override_real_key)
+ memcpy(real_key.u.key, sb->real_key, 16);
+ if(sb->override_crypto_iv)
+ memcpy(crypto_iv, sb->crypto_iv, 16);
/* KCAH KCAH KCAH KCAH KCAH KCAH KCAH KCAH KCAH KCAH KCAH KCAH KCAH KCAH */
if(g_debug)
{
@@ -386,7 +390,7 @@ void sb_write_file(struct sb_file_t *sb, const char *filename)
crypto_cbc((byte *)&tag_cmd, (byte *)&tag_cmd, sizeof(tag_cmd) / BLOCK_SIZE,
&real_key, crypto_iv, NULL, 1);
sha_1_update(&file_sha1, (byte *)&tag_cmd, sizeof(tag_cmd));
- fwrite(&tag_cmd, 1, sizeof(tag_cmd), fd);
+ write(&tag_cmd, sizeof(tag_cmd));
/* produce other commands */
byte cur_cbc_mac[16];
memcpy(cur_cbc_mac, crypto_iv, 16);
@@ -402,7 +406,7 @@ void sb_write_file(struct sb_file_t *sb, const char *filename)
crypto_cbc((byte *)&cmd, (byte *)&cmd, sizeof(cmd) / BLOCK_SIZE,
&real_key, cur_cbc_mac, &cur_cbc_mac, 1);
sha_1_update(&file_sha1, (byte *)&cmd, sizeof(cmd));
- fwrite(&cmd, 1, sizeof(cmd), fd);
+ write(&cmd, sizeof(cmd));
}
/* data */
if(inst->inst == SB_INST_LOAD || inst->inst == SB_INST_DATA)
@@ -415,7 +419,7 @@ void sb_write_file(struct sb_file_t *sb, const char *filename)
crypto_cbc(data, data, sz / BLOCK_SIZE,
&real_key, cur_cbc_mac, &cur_cbc_mac, 1);
sha_1_update(&file_sha1, data, sz);
- fwrite(data, 1, sz, fd);
+ write(data, sz);
free(data);
}
}
@@ -427,22 +431,35 @@ void sb_write_file(struct sb_file_t *sb, const char *filename)
generate_random_data(final_sig + 20, 12);
if(g_nr_keys > 0)
crypto_cbc(final_sig, final_sig, 2, &real_key, crypto_iv, NULL, 1);
- fwrite(final_sig, 1, 32, fd);
+ write(final_sig, 32);
+
+ if(buf_p - buf != sb_hdr.image_size * BLOCK_SIZE)
+ bug("SB image buffer was not entirely filled !");
+ FILE *fd = fopen(filename, "wb");
+ if(fd == NULL)
+ return SB_OPEN_ERROR;
+ if(fwrite(buf, sb_hdr.image_size * BLOCK_SIZE, 1, fd) != 1)
+ {
+ free(buf);
+ return SB_WRITE_ERROR;
+ }
fclose(fd);
-}
+ free(buf);
-static void *memdup(void *p, size_t len)
-{
- void *cpy = xmalloc(len);
- memcpy(cpy, p, len);
- return cpy;
+ return SB_SUCCESS;
}
static struct sb_section_t *read_section(bool data_sec, uint32_t id, byte *buf,
- int size, const char *indent, void *u, sb_color_printf cprintf)
+ int size, const char *indent, void *u, sb_color_printf cprintf, enum sb_error_t *err)
{
#define printf(c, ...) cprintf(u, false, c, __VA_ARGS__)
+ #define fatal(e, ...) \
+ do { if(err) *err = e; \
+ cprintf(u, true, GREY, __VA_ARGS__); \
+ sb_free_section(*sec); \
+ free(sec); \
+ return NULL; } while(0)
struct sb_section_t *sec = xmalloc(sizeof(struct sb_section_t));
memset(sec, 0, sizeof(struct sb_section_t));
@@ -474,7 +491,7 @@ static struct sb_section_t *read_section(bool data_sec, uint32_t id, byte *buf,
printf(OFF, "%s", indent);
uint8_t checksum = instruction_checksum(hdr);
if(checksum != hdr->checksum)
- printf(GREY, "[Bad checksum]");
+ fatal(SB_CHECKSUM_ERROR, "Bad instruction checksum");
if(hdr->flags != 0)
{
printf(GREY, "[");
@@ -501,7 +518,10 @@ static struct sb_section_t *read_section(bool data_sec, uint32_t id, byte *buf,
if(load->crc == computed_crc)
printf(RED, " Ok\n");
else
+ {
printf(RED, " Failed (crc=0x%08x)\n", computed_crc);
+ fatal(SB_CHECKSUM_ERROR, "Instruction data crc error\n");
+ }
pos += load->len + sizeof(struct sb_instruction_load_t);
}
@@ -559,7 +579,7 @@ static struct sb_section_t *read_section(bool data_sec, uint32_t id, byte *buf,
}
else
{
- printf(RED, "Unknown instruction %d at address 0x%08lx\n", hdr->opcode, (unsigned long)pos);
+ fatal(SB_FORMAT_ERROR, "Unknown instruction %d at address 0x%08lx\n", hdr->opcode, (unsigned long)pos);
break;
}
@@ -569,6 +589,7 @@ static struct sb_section_t *read_section(bool data_sec, uint32_t id, byte *buf,
return sec;
#undef printf
+ #undef fatal
}
void sb_fill_section_name(char name[5], uint32_t identifier)
@@ -595,25 +616,37 @@ static uint32_t guess_alignment(uint32_t off)
}
struct sb_file_t *sb_read_file(const char *filename, bool raw_mode, void *u,
- sb_color_printf cprintf)
+ sb_color_printf cprintf, enum sb_error_t *err)
{
+ uint8_t *buf = NULL;
+ struct sb_file_t *sb_file = NULL;
+
#define printf(c, ...) cprintf(u, false, c, __VA_ARGS__)
- #define fatal(...) do { cprintf(u, true, GREY, __VA_ARGS__); return NULL; } while(0)
+ #define fatal(e, ...) \
+ do { if(err) *err = e; \
+ cprintf(u, true, GREY, __VA_ARGS__); \
+ free(buf); \
+ sb_free(sb_file); \
+ return NULL; } while(0)
#define print_hex(c, p, len, nl) \
do { printf(c, ""); print_hex(p, len, nl); } while(0)
FILE *f = fopen(filename, "rb");
if(f == NULL)
- fatal("Cannot open file for reading\n");
+ fatal(SB_OPEN_ERROR, "Cannot open file for reading\n");
fseek(f, 0, SEEK_END);
long filesize = ftell(f);
fseek(f, 0, SEEK_SET);
- uint8_t *buf = xmalloc(filesize);
- fread(buf, 1, filesize, f);
+ buf = xmalloc(filesize);
+ if(fread(buf, filesize, 1, f) != 1)
+ {
+ fclose(f);
+ fatal(SB_READ_ERROR, "Cannot read file\n");
+ }
fclose(f);
struct sha_1_params_t sha_1_params;
- struct sb_file_t *sb_file = xmalloc(sizeof(struct sb_file_t));
+ sb_file = xmalloc(sizeof(struct sb_file_t));
memset(sb_file, 0, sizeof(struct sb_file_t));
struct sb_header_t *sb_header = (struct sb_header_t *)buf;
@@ -624,13 +657,13 @@ struct sb_file_t *sb_read_file(const char *filename, bool raw_mode, void *u,
sb_file->first_boot_sec_id = sb_header->first_boot_sec_id;
if(memcmp(sb_header->signature, "STMP", 4) != 0)
- fatal("Bad signature\n");
+ fatal(SB_FORMAT_ERROR, "Bad signature\n");
if(sb_header->image_size * BLOCK_SIZE > filesize)
- fatal("File too small mismatch");
+ fatal(SB_FORMAT_ERROR, "File too small");
if(sb_header->header_size * BLOCK_SIZE != sizeof(struct sb_header_t))
- fatal("Bad header size");
+ fatal(SB_FORMAT_ERROR, "Bad header size");
if(sb_header->sec_hdr_size * BLOCK_SIZE != sizeof(struct sb_section_header_t))
- fatal("Bad section header size");
+ fatal(SB_FORMAT_ERROR, "Bad section header size");
if(filesize > sb_header->image_size * BLOCK_SIZE)
{
@@ -707,86 +740,106 @@ struct sb_file_t *sb_read_file(const char *filename, bool raw_mode, void *u,
/* encryption cbc-mac */
byte real_key[16];
bool valid_key = false; /* false until a matching key was found */
+
if(sb_header->nr_keys > 0)
{
- if(sb_header->nr_keys > g_nr_keys)
- {
- fatal("SB file has %d keys but only %d were specified\n",
- sb_header->nr_keys, g_nr_keys);
- }
- printf(BLUE, "Encryption data\n");
- for(int i = 0; i < sb_header->nr_keys; i++)
+ byte (*cbcmacs)[16] = xmalloc(16 * g_nr_keys);
+ printf(BLUE, "Encryption keys\n");
+ for(int i = 0; i < g_nr_keys; i++)
{
printf(RED, " Key %d: ", i);
printf(YELLOW, "");
print_key(&g_key_array[i], true);
- printf(GREEN, " CBC-MAC of headers: ");
+ printf(GREEN, " CBC-MAC: ");
+ /* check it */
+ byte zero[16];
+ memset(zero, 0, 16);
+ int ret = crypto_cbc(buf, NULL, sb_header->header_size + sb_header->nr_sections,
+ &g_key_array[i], zero, &cbcmacs[i], 1);
+ if(ret != CRYPTO_ERROR_SUCCESS)
+ {
+ free(cbcmacs);
+ fatal(SB_FIRST_CRYPTO_ERROR + ret, "Crypto error: %d", ret);
+ }
+ print_hex(YELLOW, cbcmacs[i], 16, true);
+ }
+ printf(BLUE, "DEK\n");
+ for(int i = 0; i < sb_header->nr_keys; i++)
+ {
+ printf(RED, " Entry %d\n", i);
uint32_t ofs = sizeof(struct sb_header_t)
+ sizeof(struct sb_section_header_t) * sb_header->nr_sections
+ sizeof(struct sb_key_dictionary_entry_t) * i;
struct sb_key_dictionary_entry_t *dict_entry =
(struct sb_key_dictionary_entry_t *)&buf[ofs];
/* cbc mac */
+ printf(GREEN, " Encrypted key: ");
+ print_hex(YELLOW, dict_entry->key, 16, true);
+ printf(GREEN, " CBC-MAC : ");
print_hex(YELLOW, dict_entry->hdr_cbc_mac, 16, false);
/* check it */
- byte computed_cbc_mac[16];
- byte zero[16];
- memset(zero, 0, 16);
- crypto_cbc(buf, NULL, sb_header->header_size + sb_header->nr_sections,
- &g_key_array[i], zero, &computed_cbc_mac, 1);
-
- bool ok = memcmp(dict_entry->hdr_cbc_mac, computed_cbc_mac, 16) == 0;
- if(ok)
- {
- valid_key = true;
- printf(RED, " Ok\n");
- }
- else
- printf(RED, " Failed\n");
-
- printf(GREEN, " Encrypted key : ");
- print_hex(YELLOW, dict_entry->key, 16, true);
- /* decrypt */
- byte decrypted_key[16];
- byte iv[16];
- memcpy(iv, buf, 16); /* uses the first 16-bytes of SHA-1 sig as IV */
- crypto_cbc(dict_entry->key, decrypted_key, 1, &g_key_array[i], iv, NULL, 0);
- printf(GREEN, " Decrypted key : ");
- print_hex(YELLOW, decrypted_key, 16, false);
- /* cross-check or copy */
- if(valid_key && ok)
- memcpy(real_key, decrypted_key, 16);
- else if(valid_key)
+ int idx = 0;
+ while(idx < g_nr_keys && memcmp(dict_entry->hdr_cbc_mac, cbcmacs[idx], 16) != 0)
+ idx++;
+ if(idx != g_nr_keys)
{
- if(memcmp(real_key, decrypted_key, 16) == 0)
- printf(RED, " Cross-Check Ok");
+ printf(RED, " Match\n");
+ /* decrypt */
+ byte decrypted_key[16];
+ byte iv[16];
+ memcpy(iv, buf, 16); /* uses the first 16-bytes of SHA-1 sig as IV */
+ int ret = crypto_cbc(dict_entry->key, decrypted_key, 1, &g_key_array[idx], iv, NULL, 0);
+ if(ret != CRYPTO_ERROR_SUCCESS)
+ {
+ free(cbcmacs);
+ fatal(SB_FIRST_CRYPTO_ERROR + ret, "Crypto error: %d\n", ret);
+ }
+ printf(GREEN, " Decrypted key: ");
+ print_hex(YELLOW, decrypted_key, 16, false);
+ if(valid_key)
+ {
+ if(memcmp(real_key, decrypted_key, 16) == 0)
+ printf(RED, " Cross-Check Ok");
+ else
+ printf(RED, " Cross-Check Failed");
+ }
else
- printf(RED, " Cross-Check Failed");
+ {
+ memcpy(real_key, decrypted_key, 16);
+ valid_key = true;
+ }
+ printf(OFF, "\n");
}
- printf(OFF, "\n");
+ else
+ printf(RED, " Don't Match\n");
}
- }
- if(getenv("SB_REAL_KEY") != 0)
- {
- struct crypto_key_t k;
- char *env = getenv("SB_REAL_KEY");
- if(!parse_key(&env, &k) || *env)
- bug("Invalid SB_REAL_KEY\n");
- memcpy(real_key, k.u.key, 16);
- }
+ free(cbcmacs);
+
+ if(!valid_key)
+ fatal(SB_NO_VALID_KEY, "No valid key found\n");
+
+ if(getenv("SB_REAL_KEY") != 0)
+ {
+ struct crypto_key_t k;
+ char *env = getenv("SB_REAL_KEY");
+ if(!parse_key(&env, &k) || *env)
+ bug("Invalid SB_REAL_KEY\n");
+ memcpy(real_key, k.u.key, 16);
+ }
- printf(RED, " Summary:\n");
- printf(GREEN, " Real key: ");
- print_hex(YELLOW, real_key, 16, true);
- printf(GREEN, " IV : ");
- print_hex(YELLOW, buf, 16, true);
+ printf(RED, " Summary:\n");
+ printf(GREEN, " Real key: ");
+ print_hex(YELLOW, real_key, 16, true);
+ printf(GREEN, " IV : ");
+ print_hex(YELLOW, buf, 16, true);
- sb_file->real_key = xmalloc(16);
- memcpy(*sb_file->real_key, real_key, 16);
- sb_file->crypto_iv = xmalloc(16);
- memcpy(*sb_file->crypto_iv, buf, 16);
+ sb_file->override_real_key = true;
+ memcpy(sb_file->real_key, real_key, 16);
+ sb_file->override_crypto_iv = true;
+ memcpy(sb_file->crypto_iv, buf, 16);
+ }
/* sections */
if(!raw_mode)
@@ -831,7 +884,7 @@ struct sb_file_t *sb_read_file(const char *filename, bool raw_mode, void *u,
memcpy(sec, buf + pos, size);
struct sb_section_t *s = read_section(data_sec, sec_hdr->identifier,
- sec, size, " ", u, cprintf);
+ sec, size, " ", u, cprintf, err);
if(s)
{
s->is_cleartext = !encrypted;
@@ -839,6 +892,8 @@ struct sb_file_t *sb_read_file(const char *filename, bool raw_mode, void *u,
memcpy(&sb_file->sections[i], s, sizeof(struct sb_section_t));
free(s);
}
+ else
+ fatal(*err, "Error reading section\n");
free(sec);
}
@@ -919,7 +974,7 @@ struct sb_file_t *sb_read_file(const char *filename, bool raw_mode, void *u,
memcpy(sec, buf + pos, size);
struct sb_section_t *s = read_section(data_sec, tag->identifier,
- sec, size, " ", u, cprintf);
+ sec, size, " ", u, cprintf, err);
if(s)
{
s->is_cleartext = !encrypted;
@@ -929,6 +984,8 @@ struct sb_file_t *sb_read_file(const char *filename, bool raw_mode, void *u,
s, 1);
free(s);
}
+ else
+ fatal(*err, "Error reading section\n");
free(sec);
/* last one ? */
@@ -938,7 +995,7 @@ struct sb_file_t *sb_read_file(const char *filename, bool raw_mode, void *u,
}
else
{
- printf(RED, "Unknown instruction %d at address 0x%08lx\n", hdr->opcode, (long)offset);
+ fatal(SB_FORMAT_ERROR, "Unknown instruction %d at address 0x%08lx\n", hdr->opcode, (long)offset);
break;
}
}
@@ -970,7 +1027,10 @@ struct sb_file_t *sb_read_file(const char *filename, bool raw_mode, void *u,
if(memcmp(decrypted_block, computed_sha1, 20) == 0)
printf(RED, " Ok\n");
else
+ {
printf(RED, " Failed\n");
+ fatal(SB_CHECKSUM_ERROR, "File SHA-1 error\n");
+ }
free(buf);
return sb_file;
@@ -979,6 +1039,27 @@ struct sb_file_t *sb_read_file(const char *filename, bool raw_mode, void *u,
#undef print_hex
}
+void sb_free_section(struct sb_section_t sec)
+{
+ for(int j = 0; j < sec.nr_insts; j++)
+ {
+ free(sec.insts[j].padding);
+ free(sec.insts[j].data);
+ }
+ free(sec.insts);
+}
+
+void sb_free(struct sb_file_t *file)
+{
+ if(!file) return;
+
+ for(int i = 0; i < file->nr_sections; i++)
+ sb_free_section(file->sections[i]);
+
+ free(file->sections);
+ free(file);
+}
+
void sb_dump(struct sb_file_t *file, void *u, sb_color_printf cprintf)
{
#define printf(c, ...) cprintf(u, false, c, __VA_ARGS__)
@@ -1007,17 +1088,17 @@ void sb_dump(struct sb_file_t *file, void *u, sb_color_printf cprintf)
sb_fill_section_name(name, file->first_boot_sec_id);
printf(TEXT, "%08x (%s)\n", file->first_boot_sec_id, name);
- if(file->real_key)
+ if(file->override_real_key)
{
printf(TREE, "+-");
printf(HEADER, "Real key: ");
- print_hex(TEXT, *file->real_key, 16, true);
+ print_hex(TEXT, file->real_key, 16, true);
}
- if(file->crypto_iv)
+ if(file->override_crypto_iv)
{
printf(TREE, "+-");
printf(HEADER, "IV : ");
- print_hex(TEXT, *file->crypto_iv, 16, true);
+ print_hex(TEXT, file->crypto_iv, 16, true);
}
printf(TREE, "+-");
printf(HEADER, "Product Version: ");
diff --git a/utils/sbtools/sb.h b/utils/imxtools/sb.h
index 39bb8ce59b..ced6481a80 100644
--- a/utils/sbtools/sb.h
+++ b/utils/imxtools/sb.h
@@ -191,9 +191,11 @@ struct sb_section_t
struct sb_file_t
{
/* override real, otherwise it is randomly generated */
- uint8_t (*real_key)[16];
+ bool override_real_key;
+ uint8_t real_key[16];
/* override crypto IV, use with caution ! Use NULL to generate it */
- uint8_t (*crypto_iv)[16];
+ bool override_crypto_iv;
+ uint8_t crypto_iv[16];
int nr_sections;
uint16_t drive_tag;
@@ -207,13 +209,29 @@ struct sb_file_t
uint32_t image_size; /* in blocks */
};
-void sb_write_file(struct sb_file_t *sb, const char *filename);
+enum sb_error_t
+{
+ SB_SUCCESS = 0,
+ SB_ERROR = -1,
+ SB_OPEN_ERROR = -2,
+ SB_READ_ERROR = -3,
+ SB_WRITE_ERROR = -4,
+ SB_FORMAT_ERROR = -5,
+ SB_CHECKSUM_ERROR = -6,
+ SB_NO_VALID_KEY = -7,
+ SB_FIRST_CRYPTO_ERROR = -8,
+ SB_LAST_CRYPTO_ERROR = SB_FIRST_CRYPTO_ERROR - CRYPTO_NUM_ERRORS,
+};
+
+enum sb_error_t sb_write_file(struct sb_file_t *sb, const char *filename);
typedef void (*sb_color_printf)(void *u, bool err, color_t c, const char *f, ...);
struct sb_file_t *sb_read_file(const char *filename, bool raw_mode, void *u,
- sb_color_printf printf);
+ sb_color_printf printf, enum sb_error_t *err);
void sb_fill_section_name(char name[5], uint32_t identifier);
void sb_dump(struct sb_file_t *file, void *u, sb_color_printf printf);
+void sb_free_section(struct sb_section_t file);
+void sb_free(struct sb_file_t *file);
#endif /* __SB_H__ */
diff --git a/utils/imx_hid_recovery/imx_hid_recovery.c b/utils/imxtools/sbloader.c
index ba4645f8ab..ba4645f8ab 100644
--- a/utils/imx_hid_recovery/imx_hid_recovery.c
+++ b/utils/imxtools/sbloader.c
diff --git a/utils/sbtools/sbtoelf.c b/utils/imxtools/sbtoelf.c
index 179f91262f..fda70b1180 100644
--- a/utils/sbtools/sbtoelf.c
+++ b/utils/imxtools/sbtoelf.c
@@ -268,7 +268,15 @@ int main(int argc, char **argv)
const char *sb_filename = argv[optind];
- struct sb_file_t *file = sb_read_file(sb_filename, raw_mode, NULL, sb_printf);
+ enum sb_error_t err;
+ struct sb_file_t *file = sb_read_file(sb_filename, raw_mode, NULL, sb_printf, &err);
+ if(file == NULL)
+ {
+ color(OFF);
+ printf("SB read failed: %d\n", err);
+ return 1;
+ }
+
color(OFF);
if(g_out_prefix)
extract_sb_file(file);
@@ -283,12 +291,12 @@ int main(int argc, char **argv)
/* sb_read_file will fill real key and IV but we don't want to override
* them when looping back otherwise the output will be inconsistent and
* garbage */
- free(file->real_key);
- file->real_key = NULL;
- free(file->crypto_iv);
- file->crypto_iv = NULL;
+ file->override_real_key = false;
+ file->override_crypto_iv = false;
sb_write_file(file, loopback);
}
+ sb_free(file);
+ clear_keys();
return 0;
}
diff --git a/utils/sbtools/sha1.c b/utils/imxtools/sha1.c
index 0ad05bb5cd..0ad05bb5cd 100644
--- a/utils/sbtools/sha1.c
+++ b/utils/imxtools/sha1.c