summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--utils/imxtools/sbtools/dbparser.c56
-rw-r--r--utils/imxtools/sbtools/dbparser.h2
-rw-r--r--utils/imxtools/sbtools/elftosb.c82
-rw-r--r--utils/imxtools/sbtools/sb.c42
-rw-r--r--utils/imxtools/sbtools/sb.h9
-rw-r--r--utils/imxtools/sbtools/sbtoelf.c2
6 files changed, 107 insertions, 86 deletions
diff --git a/utils/imxtools/sbtools/dbparser.c b/utils/imxtools/sbtools/dbparser.c
index 6cba91f34b..54939db6d2 100644
--- a/utils/imxtools/sbtools/dbparser.c
+++ b/utils/imxtools/sbtools/dbparser.c
@@ -419,44 +419,29 @@ struct cmd_option_t *db_find_option_by_id(struct cmd_option_t *opt, const char *
#define INVALID_SB_SUBVERSION 0xffff
-static uint16_t parse_sb_subversion(char *str)
+static const char *parse_sb_subversion(const char *str, uint16_t *v)
{
- int len = strlen(str);
- uint16_t n = 0;
- if(len == 0 || len > 4)
- return INVALID_SB_SUBVERSION;
- for(int i = 0; i < len; i++)
- {
- if(!isdigit(str[i]))
- return INVALID_SB_SUBVERSION;
- n = n << 4 | (str[i] - '0');
- }
- return n;
+ int len = 0;
+ *v = 0;
+ while(isdigit(str[len]) && len < 3)
+ *v = (*v) << 4 | (str[len++] - '0');
+ if(len == 0)
+ *v = INVALID_SB_SUBVERSION;
+ return str + len;
}
-bool db_parse_sb_version(struct sb_version_t *ver, char *str)
+bool db_parse_sb_version(struct sb_version_t *ver, const char *str)
{
- int len = strlen(str);
- int cnt = 0;
- int pos[2];
-
- for(int i = 0; i < len; i++)
- {
- if(str[i] != '.')
- continue;
- if(cnt == 2)
- return false;
- pos[cnt++] = i + 1;
- str[i] = 0;
- }
- if(cnt != 2)
+ str = parse_sb_subversion(str, &ver->major);
+ if(ver->major == INVALID_SB_SUBVERSION || *str != '.')
+ return false;
+ str = parse_sb_subversion(str + 1, &ver->minor);
+ if(ver->minor == INVALID_SB_SUBVERSION || *str != '.')
return false;
- ver->major = parse_sb_subversion(str);
- ver->minor = parse_sb_subversion(str + pos[0]);
- ver->revision = parse_sb_subversion(str + pos[1]);
- return ver->major != INVALID_SB_SUBVERSION &&
- ver->minor != INVALID_SB_SUBVERSION &&
- ver->revision != INVALID_SB_SUBVERSION;
+ str = parse_sb_subversion(str + 1, &ver->revision);
+ if(ver->revision == INVALID_SB_SUBVERSION || *str != 0)
+ return false;
+ return true;
}
static bool db_generate_sb_subversion(uint16_t subver, char *str)
@@ -831,11 +816,6 @@ struct cmd_file_t *db_parse_file(const char *file)
return cmd_file;
}
-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)
diff --git a/utils/imxtools/sbtools/dbparser.h b/utils/imxtools/sbtools/dbparser.h
index b99eae9a2b..c55d560df4 100644
--- a/utils/imxtools/sbtools/dbparser.h
+++ b/utils/imxtools/sbtools/dbparser.h
@@ -111,7 +111,7 @@ typedef void (*db_color_printf)(void *u, bool err, color_t c, const char *f, ...
struct cmd_source_t *db_find_source_by_id(struct cmd_file_t *cmd_file, const char *id);
struct cmd_option_t *db_find_option_by_id(struct cmd_option_t *opt, const char *name);
-bool db_parse_sb_version(struct sb_version_t *ver, char *str);
+bool db_parse_sb_version(struct sb_version_t *ver, const char *str);
bool db_generate_sb_version(struct sb_version_t *ver, char *str, int size);
void db_generate_default_sb_version(struct sb_version_t *ver);
struct cmd_file_t *db_parse_file(const char *file);
diff --git a/utils/imxtools/sbtools/elftosb.c b/utils/imxtools/sbtools/elftosb.c
index c904e42f79..b65b65d402 100644
--- a/utils/imxtools/sbtools/elftosb.c
+++ b/utils/imxtools/sbtools/elftosb.c
@@ -118,13 +118,51 @@ static void load_bin_by_id(struct cmd_file_t *cmd_file, const char *id)
src->loaded = true;
}
+static const char *get_str_opt(struct cmd_option_t *opt_list, const char *id, const char *dflt)
+{
+ struct cmd_option_t *opt = db_find_option_by_id(opt_list, id);
+ if(!opt)
+ return dflt;
+ if(!opt->is_string)
+ bug("'%s' option must be a string\n", id);
+ return opt->str;
+}
+
+static uint32_t get_int_opt(struct cmd_option_t *opt_list, const char *id, uint32_t dflt)
+{
+ struct cmd_option_t *opt = db_find_option_by_id(opt_list, id);
+ if(!opt)
+ return dflt;
+ if(opt->is_string)
+ bug("'%s' option must be an integer\n", id);
+ return opt->val;
+}
+
static struct sb_file_t *apply_cmd_file(struct cmd_file_t *cmd_file)
{
struct sb_file_t *sb = xmalloc(sizeof(struct sb_file_t));
memset(sb, 0, sizeof(struct sb_file_t));
-
- db_generate_default_sb_version(&sb->product_ver);
- db_generate_default_sb_version(&sb->component_ver);
+ sb_build_default_image(sb);
+
+ if(db_find_option_by_id(cmd_file->opt_list, "componentVersion") &&
+ !db_parse_sb_version(&sb->component_ver, get_str_opt(cmd_file->opt_list, "componentVersion", "")))
+ bug("Invalid 'componentVersion' format\n");
+ if(db_find_option_by_id(cmd_file->opt_list, "productVersion") &&
+ !db_parse_sb_version(&sb->product_ver, get_str_opt(cmd_file->opt_list, "productVersion", "")))
+ bug("Invalid 'productVersion' format\n");
+ if(db_find_option_by_id(cmd_file->opt_list, "sbMinorVersion"))
+ sb->minor_version = get_int_opt(cmd_file->opt_list, "sbMinorVersion", 0);
+ if(db_find_option_by_id(cmd_file->opt_list, "flags"))
+ sb->flags = get_int_opt(cmd_file->opt_list, "flags", 0);
+ if(db_find_option_by_id(cmd_file->opt_list, "driveTag"))
+ sb->drive_tag = get_int_opt(cmd_file->opt_list, "driveTag", 0);
+ if(db_find_option_by_id(cmd_file->opt_list, "timestampLow"))
+ {
+ if(!db_find_option_by_id(cmd_file->opt_list, "timestampHigh"))
+ bug("Option 'timestampLow' and 'timestampHigh' must both specified\n");
+ sb->timestamp = (uint64_t)get_int_opt(cmd_file->opt_list, "timestampHigh", 0) << 32 |
+ get_int_opt(cmd_file->opt_list, "timestampLow", 0);
+ }
if(g_debug)
printf("Applying command file...\n");
@@ -149,32 +187,16 @@ static struct sb_file_t *apply_cmd_file(struct cmd_file_t *cmd_file)
do
{
/* cleartext */
- struct cmd_option_t *opt = db_find_option_by_id(csec->opt_list, "cleartext");
- if(opt != NULL)
- {
- if(opt->is_string)
- bug("Cleartext section attribute must be an integer\n");
- if(opt->val != 0 && opt->val != 1)
- bug("Cleartext section attribute must be 0 or 1\n");
- sec->is_cleartext = opt->val;
- }
+ sec->is_cleartext = get_int_opt(csec->opt_list, "cleartext", false);
/* alignment */
- opt = db_find_option_by_id(csec->opt_list, "alignment");
- if(opt != NULL)
- {
- if(opt->is_string)
- bug("Cleartext section attribute must be an integer\n");
- // n is a power of 2 iff n & (n - 1) = 0
- // alignement cannot be lower than block size
- if((opt->val & (opt->val - 1)) != 0)
- bug("Cleartext section attribute must be a power of two\n");
- if(opt->val < BLOCK_SIZE)
- sec->alignment = BLOCK_SIZE;
- else
- sec->alignment = opt->val;
- }
- else
+ sec->alignment = get_int_opt(csec->opt_list, "alignment", BLOCK_SIZE);
+ // alignement cannot be lower than block size
+ if((sec->alignment & (sec->alignment - 1)) != 0)
+ bug("Alignment section attribute must be a power of two\n");
+ if(sec->alignment < BLOCK_SIZE)
sec->alignment = BLOCK_SIZE;
+ /* other flags */
+ sec->other_flags = get_int_opt(csec->opt_list, "sectionFlags", 0) & ~SECTION_STD_MASK;
}while(0);
if(csec->is_data)
@@ -424,12 +446,6 @@ int main(int argc, char **argv)
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;
- sb_file->first_boot_sec_id = sb_file->sections[0].identifier;
- sb_file->flags = 0;
- sb_file->minor_version = 1;
-
sb_write_file(sb_file, output_filename, 0, generic_std_printf);
sb_free(sb_file);
clear_keys();
diff --git a/utils/imxtools/sbtools/sb.c b/utils/imxtools/sbtools/sb.c
index d7d3734a91..bea0438cca 100644
--- a/utils/imxtools/sbtools/sb.c
+++ b/utils/imxtools/sbtools/sb.c
@@ -186,7 +186,7 @@ static void compute_sb_offsets(struct sb_file_t *sb, void *u, generic_printf_t c
#undef printf
}
-static uint64_t generate_timestamp()
+uint64_t sb_generate_timestamp(void)
{
struct tm tm_base;
memset(&tm_base, 0, sizeof(tm_base));
@@ -218,11 +218,11 @@ static void produce_sb_header(struct sb_file_t *sb, struct sb_header_t *sb_hdr)
sb_hdr->signature[2] = 'M';
sb_hdr->signature[3] = 'P';
sb_hdr->major_ver = IMAGE_MAJOR_VERSION;
- sb_hdr->minor_ver = IMAGE_MINOR_VERSION;
- sb_hdr->flags = 0;
+ sb_hdr->minor_ver = sb->minor_version;
+ sb_hdr->flags = sb->flags;
sb_hdr->image_size = sb->image_size;
sb_hdr->header_size = sizeof(struct sb_header_t) / BLOCK_SIZE;
- sb_hdr->first_boot_sec_id = sb->first_boot_sec_id;
+ sb_hdr->first_boot_sec_id = sb->sections[0].identifier;
sb_hdr->nr_keys = g_nr_keys;
sb_hdr->nr_sections = sb->nr_sections;
sb_hdr->sec_hdr_size = sizeof(struct sb_section_header_t) / BLOCK_SIZE;
@@ -237,10 +237,7 @@ static void produce_sb_header(struct sb_file_t *sb, struct sb_header_t *sb_hdr)
if(sb->minor_version >= 1)
memcpy(&sb_hdr->rand_pad0[2], "sgtl", 4);
- if(sb->override_timestamp)
- sb_hdr->timestamp = sb->timestamp;
- else
- sb_hdr->timestamp = generate_timestamp();
+ sb_hdr->timestamp = sb->timestamp;
sb_hdr->product_ver = sb->product_ver;
fix_version(&sb_hdr->product_ver);
sb_hdr->component_ver = sb->component_ver;
@@ -261,7 +258,8 @@ static void produce_sb_section_header(struct sb_section_t *sec,
sec_hdr->offset = sec->file_offset;
sec_hdr->size = sec->sec_size;
sec_hdr->flags = (sec->is_data ? 0 : SECTION_BOOTABLE)
- | (sec->is_cleartext ? SECTION_CLEARTEXT : 0);
+ | (sec->is_cleartext ? SECTION_CLEARTEXT : 0)
+ | sec->other_flags;
}
static uint8_t instruction_checksum(struct sb_instruction_header_t *hdr)
@@ -281,7 +279,8 @@ static void produce_section_tag_cmd(struct sb_section_t *sec,
tag->identifier = sec->identifier;
tag->len = sec->sec_size;
tag->flags = (sec->is_data ? 0 : SECTION_BOOTABLE)
- | (sec->is_cleartext ? SECTION_CLEARTEXT : 0);
+ | (sec->is_cleartext ? SECTION_CLEARTEXT : 0)
+ | sec->other_flags;
tag->hdr.checksum = instruction_checksum(&tag->hdr);
}
@@ -333,6 +332,11 @@ enum sb_error_t sb_write_file(struct sb_file_t *sb, const char *filename, void *
memset(cbc_macs[i], 0, 16);
fill_gaps(sb);
+ if(sb->nr_sections == 0 || sb->sections[0].is_data)
+ {
+ cprintf(u, true, GREY, "First section of the image is not bootable, I cannot handle that.\n");
+ return SB_ERROR;
+ }
compute_sb_offsets(sb, u, cprintf);
generate_random_data(real_key.u.key, 16);
@@ -983,6 +987,7 @@ struct sb_file_t *sb_read_memory(void *_buf, size_t filesize, bool raw_mode, voi
sec, size, " ", u, cprintf, err);
if(s)
{
+ s->other_flags = sec_hdr->flags & ~SECTION_STD_MASK;
s->is_cleartext = !encrypted;
s->alignment = guess_alignment(pos);
memcpy(&sb_file->sections[i], s, sizeof(struct sb_section_t));
@@ -1073,6 +1078,7 @@ struct sb_file_t *sb_read_memory(void *_buf, size_t filesize, bool raw_mode, voi
sec, size, " ", u, cprintf, err);
if(s)
{
+ s->other_flags = tag->flags & ~SECTION_STD_MASK;
s->is_cleartext = !encrypted;
s->alignment = guess_alignment(pos);
sb_file->sections = augment_array(sb_file->sections,
@@ -1138,6 +1144,19 @@ struct sb_file_t *sb_read_memory(void *_buf, size_t filesize, bool raw_mode, voi
#undef print_hex
}
+void sb_generate_default_version(struct sb_version_t *ver)
+{
+ ver->major = ver->minor = ver->revision = 0x999;
+}
+
+void sb_build_default_image(struct sb_file_t *sb)
+{
+ sb->minor_version = IMAGE_MINOR_VERSION;
+ sb->timestamp = sb_generate_timestamp();
+ sb_generate_default_version(&sb->product_ver);
+ sb_generate_default_version(&sb->component_ver);
+}
+
void sb_free_instruction(struct sb_inst_t inst)
{
free(inst.padding);
@@ -1246,6 +1265,9 @@ void sb_dump(struct sb_file_t *file, void *u, generic_printf_t cprintf)
printf(HEADER, "Alignment: ");
printf(TEXT, "%d (bytes)\n", sec->alignment);
printf(TREE, "| +-");
+ printf(HEADER, "Other Flags: ");
+ printf(TEXT, "%#x\n", sec->other_flags);
+ printf(TREE, "| +-");
printf(HEADER, "Instructions\n");
for(int j = 0; j < sec->nr_insts; j++)
{
diff --git a/utils/imxtools/sbtools/sb.h b/utils/imxtools/sbtools/sb.h
index aa382fca82..67d0d8c423 100644
--- a/utils/imxtools/sbtools/sb.h
+++ b/utils/imxtools/sbtools/sb.h
@@ -81,6 +81,7 @@ struct sb_key_dictionary_entry_t
#define SECTION_BOOTABLE (1 << 0)
#define SECTION_CLEARTEXT (1 << 1)
+#define SECTION_STD_MASK (3 << 0)
#define SB_INST_NOP 0x0
#define SB_INST_TAG 0x1
@@ -187,6 +188,7 @@ struct sb_section_t
uint32_t identifier;
bool is_data;
bool is_cleartext;
+ uint32_t other_flags;
uint32_t alignment;
// data sections are handled as one or more SB_INST_DATA virtual instruction
int nr_insts;
@@ -204,15 +206,13 @@ struct sb_file_t
/* override crypto IV, use with caution ! Use NULL to generate it */
bool override_crypto_iv;
uint8_t crypto_iv[16];
- /* override timestamp */
- bool override_timestamp;
uint64_t timestamp; /* In microseconds since 2000/1/1 00:00:00 */
+ uint8_t minor_version;
int nr_sections;
uint16_t drive_tag;
uint32_t first_boot_sec_id;
uint16_t flags;
- uint8_t minor_version;
struct sb_section_t *sections;
struct sb_version_t product_ver;
struct sb_version_t component_ver;
@@ -244,6 +244,9 @@ struct sb_file_t *sb_read_file_ex(const char *filename, size_t offset, size_t si
struct sb_file_t *sb_read_memory(void *buffer, size_t size, bool raw_mode, void *u,
generic_printf_t printf, enum sb_error_t *err);
+uint64_t sb_generate_timestamp(void);
+void sb_generate_default_version(struct sb_version_t *ver);
+void sb_build_default_image(struct sb_file_t *file);
void sb_fill_section_name(char name[5], uint32_t identifier);
void sb_dump(struct sb_file_t *file, void *u, generic_printf_t printf);
void sb_free_instruction(struct sb_inst_t inst);
diff --git a/utils/imxtools/sbtools/sbtoelf.c b/utils/imxtools/sbtools/sbtoelf.c
index ed27a53f16..04bde051ad 100644
--- a/utils/imxtools/sbtools/sbtoelf.c
+++ b/utils/imxtools/sbtools/sbtoelf.c
@@ -96,6 +96,7 @@ static void extract_sb_section(struct sb_section_t *sec, struct cmd_file_t *cmd_
struct cmd_section_t *db_sec = db_add_section(cmd_file, sec->identifier, sec->is_data);
db_add_int_opt(&db_sec->opt_list, "alignment", sec->alignment);
db_add_int_opt(&db_sec->opt_list, "cleartext", sec->is_cleartext);
+ db_add_int_opt(&db_sec->opt_list, "sectionFlags", sec->other_flags);
if(sec->is_data)
{
@@ -413,7 +414,6 @@ int main(int argc, char **argv)
* garbage */
file->override_real_key = false;
file->override_crypto_iv = false;
- file->override_timestamp = true;
sb_write_file(file, loopback, 0, generic_std_printf);
}
sb_free(file);