[prev in list] [next in list] [prev in thread] [next in thread] 

List:       rockbox-cvs
Subject:    sbtools: now generate a db file along with with elf/rsrc files
From:       gerrit () rockbox ! org
Date:       2013-08-21 22:59:53
Message-ID: 201308212259.r7LMxrBI006788 () giant ! haxx ! se
[Download RAW message or body]

commit 81f97f67e2638623abe3ba4094bffea563832355
Author: Amaury Pouly <amaury.pouly@gmail.com>
Date:   Thu Aug 22 00:58:19 2013 +0200

    sbtools: now generate a db file along with with elf/rsrc files
    
    Now always generate a "make.db" file which aims at being the exact
    representation of the file, ie running sbtoelf and elftosb using
    the generated command file should produce the exact same file
    (except for the random paddings). We still miss the support
    for some option parsing to achieve that though.
    
    Change-Id: Ib7d6b241f7855fd35225df8ab8e0711f69d9ee5a

diff --git a/utils/imxtools/sbtools/Makefile b/utils/imxtools/sbtools/Makefile
index eab5b8d..13b0a12 100644
--- a/utils/imxtools/sbtools/Makefile
+++ b/utils/imxtools/sbtools/Makefile
@@ -10,7 +10,7 @@ all: $(BINS)
 %.o: %.c
 	$(CC) $(CFLAGS) -c -o $@ $<
 
-sbtoelf: sbtoelf.o crc.o crypto.o aes128.o sha1.o xorcrypt.o elf.o misc.o sb.o sb1.o
+sbtoelf: sbtoelf.o crc.o crypto.o aes128.o sha1.o xorcrypt.o dbparser.o elf.o misc.o \
sb.o sb1.o  $(LD) -o $@ $^ $(LDFLAGS)
 
 elftosb: elftosb.o crc.o crypto.o aes128.o sha1.o elf.o dbparser.o misc.o sb.o
diff --git a/utils/imxtools/sbtools/dbparser.c b/utils/imxtools/sbtools/dbparser.c
index 37f812d..414b771 100644
--- a/utils/imxtools/sbtools/dbparser.c
+++ b/utils/imxtools/sbtools/dbparser.c
@@ -316,6 +316,84 @@ static void log_lexem(struct lexem_t *lexem)
 }
 #endif
 
+struct cmd_option_t *db_add_opt(struct cmd_option_t **opt, const char *identifier, \
bool is_str) +{
+    while(*opt)
+        opt = &(*opt)->next;
+    *opt = xmalloc(sizeof(struct cmd_option_t));
+    memset(*opt, 0, sizeof(struct cmd_option_t));
+    (*opt)->name = strdup(identifier);
+    (*opt)->is_string = is_str;
+    return *opt;
+}
+
+void db_add_str_opt(struct cmd_option_t **opt, const char *name, const char *value)
+{
+    db_add_opt(opt, name, true)->str = strdup(value);
+}
+
+void db_add_int_opt(struct cmd_option_t **opt, const char *name, uint32_t value)
+{
+    db_add_opt(opt, name, false)->val = value;
+}
+
+static struct cmd_source_t *db_add_src(struct cmd_source_t **src, const char \
*identifier, bool is_extern) +{
+    while(*src)
+        src = &(*src)->next;
+    *src = xmalloc(sizeof(struct cmd_source_t));
+    memset(*src, 0, sizeof(struct cmd_source_t));
+    (*src)->identifier = strdup(identifier);
+    (*src)->is_extern = is_extern;
+    return *src;
+}
+
+void db_add_source(struct cmd_file_t *cmd_file, const char *identifier, const char \
*filename) +{
+    db_add_src(&cmd_file->source_list, identifier, false)->filename = \
strdup(filename); +}
+
+void db_add_extern_source(struct cmd_file_t *cmd_file, const char *identifier, int \
extern_nr) +{
+    db_add_src(&cmd_file->source_list, identifier, false)->extern_nr = extern_nr;
+}
+
+static struct cmd_inst_t *db_add_inst(struct cmd_inst_t **list, enum cmd_inst_type_t \
type, +    uint32_t argument)
+{
+    while(*list)
+        list = &(*list)->next;
+    *list = xmalloc(sizeof(struct cmd_inst_t));
+    memset(*list, 0, sizeof(struct cmd_inst_t));
+    (*list)->type = type;
+    (*list)->argument = argument;
+    return *list;
+}
+
+void db_add_inst_id(struct cmd_section_t *cmd_section, enum cmd_inst_type_t type,
+    const char *identifier, uint32_t argument)
+{
+    db_add_inst(&cmd_section->inst_list, type, argument)->identifier = \
strdup(identifier); +}
+
+void db_add_inst_addr(struct cmd_section_t *cmd_section, enum cmd_inst_type_t type,
+    uint32_t addr, uint32_t argument)
+{
+    db_add_inst(&cmd_section->inst_list, type, argument)->addr = addr;
+}
+
+struct cmd_section_t *db_add_section(struct cmd_file_t *cmd_file, uint32_t \
identifier, bool data) +{
+    struct cmd_section_t **prev = &cmd_file->section_list;
+    while(*prev)
+        prev = &(*prev)->next;
+    *prev = xmalloc(sizeof(struct cmd_section_t));
+    memset(*prev, 0, sizeof(struct cmd_section_t));
+    (*prev)->identifier = identifier;
+    (*prev)->is_data = data;
+    return *prev;
+}
+
 struct cmd_source_t *db_find_source_by_id(struct cmd_file_t *cmd_file, const char \
*id)  {
     struct cmd_source_t *src = cmd_file->source_list;
@@ -381,6 +459,26 @@ bool db_parse_sb_version(struct sb_version_t *ver, char *str)
         ver->revision != INVALID_SB_SUBVERSION;
 }
 
+static bool db_generate_sb_subversion(uint16_t subver, char *str)
+{
+    str[0] = '0' + ((subver >> 8) & 0xf);
+    str[1] = '0' + ((subver >> 4) & 0xf);
+    str[2] = '0' + (subver & 0xf);
+    return true;
+}
+
+bool db_generate_sb_version(struct sb_version_t *ver, char *str, int size)
+{
+    if(size < 12)
+        return false;
+    str[3] = '.';
+    str[7] = '.';
+    str[11] = 0;
+    return db_generate_sb_subversion(ver->major, str) &&
+        db_generate_sb_subversion(ver->minor, str + 4) &&
+        db_generate_sb_subversion(ver->revision, str + 8);
+}
+
 #undef parse_error
 #define parse_error(lexem, ...) \
     do { fprintf(stderr, "%s:%d: ", lexem.file, lexem.line); \
@@ -815,6 +913,134 @@ void db_free_option_list(struct cmd_option_t *opt_list)
     }
 }
 
+static bool db_generate_options(FILE *f, const char *secname, struct cmd_option_t \
*list) +{
+    fprintf(f, "%s\n", secname);
+    fprintf(f, "{\n");
+    while(list)
+    {
+        fprintf(f, "    %s = ", list->name);
+        if(list->is_string)
+            fprintf(f, "\"%s\";\n", list->str); // FIXME handle escape
+        else
+            fprintf(f, "0x%x;\n", list->val);
+        list = list->next;
+    }
+    fprintf(f, "}\n");
+    return true;
+}
+
+static bool db_generate_section_options(FILE *f, struct cmd_option_t *list)
+{
+    bool first = true;
+    while(list)
+    {
+        fprintf(f, "%c %s = ", first ? ';' : ',', list->name);
+        if(list->is_string)
+            fprintf(f, "\"%s\"", list->str); // FIXME handle escape
+        else
+            fprintf(f, "0x%x", list->val);
+        first = false;
+        list = list->next;
+    }
+    return true;
+}
+
+static bool db_generate_sources(FILE *f, struct cmd_source_t *list)
+{
+    fprintf(f, "sources\n"),
+    fprintf(f, "{\n");
+    while(list)
+    {
+        fprintf(f, "    %s = ", list->identifier);
+        if(list->is_extern)
+            fprintf(f, "extern(%d);\n", list->extern_nr);
+        else
+            fprintf(f, "\"%s\";\n", list->filename); // FIXME handle escape
+        list = list->next;
+    }
+    fprintf(f, "}\n");
+    return true;
+}
+
+static bool db_generate_section(FILE *f, struct cmd_section_t *section)
+{
+    fprintf(f, "section(%#x", section->identifier);
+    db_generate_section_options(f, section->opt_list);
+    if(section->is_data)
+    {
+        fprintf(f, ") <= %s;\n", section->source_id);
+        return true;
+    }
+    fprintf(f, ")\n{\n");
+    struct cmd_inst_t *inst = section->inst_list;
+    while(inst)
+    {
+        fprintf(f, "    ");
+        switch(inst->type)
+        {
+            case CMD_LOAD:
+                fprintf(f, "load %s;\n", inst->identifier);
+                break;
+            case CMD_LOAD_AT:
+                fprintf(f, "load %s > %#x;\n", inst->identifier, inst->addr);
+                break;
+            case CMD_CALL:
+                fprintf(f, "call %s(%#x);\n", inst->identifier, inst->argument);
+                break;
+            case CMD_CALL_AT:
+                fprintf(f, "call %#x(%#x);\n", inst->addr, inst->argument);
+                break;
+            case CMD_JUMP:
+                fprintf(f, "jump %s(%#x);\n", inst->identifier, inst->argument);
+                break;
+            case CMD_JUMP_AT:
+                fprintf(f, "jump %#x(%#x);\n", inst->addr, inst->argument);
+                break;
+            case CMD_MODE:
+                fprintf(f, "mode %#x;\n", inst->argument);
+                break;
+            default:
+                bug("die");
+        }
+        inst = inst->next;
+    }
+    fprintf(f, "}\n");
+    return true;
+}
+
+static bool db_generate_sections(FILE *f, struct cmd_section_t *section)
+{
+    while(section)
+        if(!db_generate_section(f, section))
+            return false;
+        else
+            section = section->next;
+    return true;
+}
+
+bool db_generate_file(struct cmd_file_t *file, const char *filename, void *user, \
db_color_printf printf) +{
+    FILE *f = fopen(filename, "w");
+    if(f == NULL)
+        return printf(user, true, GREY, "Cannot open '%s' for writing: %m\n", \
filename), false; +    if(!db_generate_options(f, "constants", file->constant_list))
+        goto Lerr;
+    if(!db_generate_options(f, "options", file->opt_list))
+        goto Lerr;
+    if(!db_generate_sources(f, file->source_list))
+        goto Lerr;
+    if(!db_generate_sections(f, file->section_list))
+        goto Lerr;
+
+    fclose(f);
+    return true;
+
+    Lerr:
+    fclose(f);
+    return false;
+}
+
 void db_free(struct cmd_file_t *file)
 {
     db_free_option_list(file->opt_list);
diff --git a/utils/imxtools/sbtools/dbparser.h b/utils/imxtools/sbtools/dbparser.h
index 4a36861..b99eae9 100644
--- a/utils/imxtools/sbtools/dbparser.h
+++ b/utils/imxtools/sbtools/dbparser.h
@@ -107,12 +107,29 @@ struct cmd_file_t
     struct cmd_section_t *section_list;
 };
 
+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_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);
+/* NOTE: db_add_{str_opt,int_opt,source,extern_source} add at the beginning of the \
list */ +void db_add_str_opt(struct cmd_option_t **opt, const char *name, const char \
*str); +void db_add_int_opt(struct cmd_option_t **opt, const char *name, uint32_t \
value); +void db_add_source(struct cmd_file_t *cmd_file, const char *identifier, \
const char *filename); +void db_add_inst_id(struct cmd_section_t *cmd_section, enum \
cmd_inst_type_t type, +    const char *identifier, uint32_t argument);
+void db_add_inst_addr(struct cmd_section_t *cmd_section, enum cmd_inst_type_t type,
+    uint32_t addr, uint32_t argument);
+struct cmd_section_t *db_add_section(struct cmd_file_t *cmd_file, uint32_t \
identifier, bool data); +void db_add_extern_source(struct cmd_file_t *cmd_file, const \
char *identifier, int extern_nr); +bool db_generate_file(struct cmd_file_t *file, \
const char *filename, void *user, db_color_printf printf);  void \
db_free_option_list(struct cmd_option_t *opt_list);  void db_free(struct cmd_file_t \
*file);  
+/* standard implementation: user is unused*/
+void db_std_printf(void *user, bool error, color_t c, const char *fmt, ...);
+
 #endif /* __DBPARSER__ */
diff --git a/utils/imxtools/sbtools/sb.c b/utils/imxtools/sbtools/sb.c
index a642af5..d7d3734 100644
--- a/utils/imxtools/sbtools/sb.c
+++ b/utils/imxtools/sbtools/sb.c
@@ -237,7 +237,10 @@ 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);
 
-    sb_hdr->timestamp = generate_timestamp();
+    if(sb->override_timestamp)
+        sb_hdr->timestamp = sb->timestamp;
+    else
+        sb_hdr->timestamp = generate_timestamp();
     sb_hdr->product_ver = sb->product_ver;
     fix_version(&sb_hdr->product_ver);
     sb_hdr->component_ver = sb->component_ver;
@@ -789,6 +792,7 @@ struct sb_file_t *sb_read_memory(void *_buf, size_t filesize, \
bool raw_mode, voi  struct tm *time = gmtime(&seconds);
     printf(GREEN, "  Creation date/time = ");
     printf(YELLOW, "%s", asctime(time));
+    sb_file->timestamp = sb_header->timestamp;
 
     struct sb_version_t product_ver = sb_header->product_ver;
     fix_version(&product_ver);
@@ -1186,6 +1190,23 @@ void sb_dump(struct sb_file_t *file, void *u, generic_printf_t \
cprintf)  char name[5];
     sb_fill_section_name(name, file->first_boot_sec_id);
     printf(TEXT, "%08x (%s)\n", file->first_boot_sec_id, name);
+    printf(TREE, "+-");
+    printf(HEADER, "Timestamp: ");
+    printf(TEXT, "%#llx", file->timestamp);
+    {
+        uint64_t micros = file->timestamp;
+        time_t seconds = (micros / (uint64_t)1000000L);
+        struct tm tm_base;
+        memset(&tm_base, 0, sizeof(tm_base));
+        /* 2000/1/1 0:00:00 */
+        tm_base.tm_mday = 1;
+        tm_base.tm_year = 100;
+        seconds += mktime(&tm_base);
+        struct tm *time = gmtime(&seconds);
+        char *str = asctime(time);
+        str[strlen(str) - 1] = 0;
+        printf(TEXT2, " (%s)\n", str);
+    }
 
     if(file->override_real_key)
     {
diff --git a/utils/imxtools/sbtools/sb.h b/utils/imxtools/sbtools/sb.h
index 4f725da..aa382fc 100644
--- a/utils/imxtools/sbtools/sb.h
+++ b/utils/imxtools/sbtools/sb.h
@@ -204,6 +204,9 @@ 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 */
 
     int nr_sections;
     uint16_t drive_tag;
diff --git a/utils/imxtools/sbtools/sbtoelf.c b/utils/imxtools/sbtools/sbtoelf.c
index 640a241..ed27a53 100644
--- a/utils/imxtools/sbtools/sbtoelf.c
+++ b/utils/imxtools/sbtools/sbtoelf.c
@@ -43,6 +43,7 @@
 #include "sb.h"
 #include "sb1.h"
 #include "misc.h"
+#include "dbparser.h"
 
 /* all blocks are sized as a multiple of 0x1ff */
 #define PAD_TO_BOUNDARY(x) (((x) + 0x1ff) & ~0x1ff)
@@ -61,12 +62,21 @@
 static char *g_out_prefix;
 static bool g_elf_simplify = true;
 
-static void extract_elf_section(struct elf_params_t *elf, int count, uint32_t id)
+static void extract_elf_section(struct elf_params_t *elf, int count, uint32_t id,
+    struct cmd_file_t *cmd_file, struct cmd_section_t *section, bool is_call, \
uint32_t arg)  {
     char name[5];
+    char fileid[16];
     char *filename = xmalloc(strlen(g_out_prefix) + 32);
     sb_fill_section_name(name, id);
+    sb_fill_section_name(fileid, id);
+    sprintf(fileid + strlen(fileid), "%d", count);
     sprintf(filename, "%s%s.%d.elf", g_out_prefix, name, count);
+    db_add_source(cmd_file, fileid, filename + strlen(g_out_prefix));
+    db_add_inst_id(section, CMD_LOAD, fileid, 0);
+    if(elf_get_start_addr(elf, NULL))
+        db_add_inst_id(section, is_call ? CMD_CALL : CMD_JUMP, fileid, arg);
+
     if(g_debug)
         printf("Write boot section %s to %s\n", name, filename);
 
@@ -81,14 +91,21 @@ static void extract_elf_section(struct elf_params_t *elf, int \
count, uint32_t id  fclose(fd);
 }
 
-static void extract_sb_section(struct sb_section_t *sec)
+static void extract_sb_section(struct sb_section_t *sec, struct cmd_file_t \
*cmd_file)  {
+    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);
+
     if(sec->is_data)
     {
         char sec_name[5];
         char *filename = xmalloc(strlen(g_out_prefix) + 32);
         sb_fill_section_name(sec_name, sec->identifier);
         sprintf(filename, "%s%s.bin", g_out_prefix, sec_name);
+        db_add_source(cmd_file, sec_name, filename + strlen(g_out_prefix));
+        db_sec->source_id = strdup(sec_name);
+
         FILE *fd = fopen(filename, "wb");
         if(fd == NULL)
             bugp("Cannot open %s for writing\n", filename);
@@ -116,7 +133,7 @@ static void extract_sb_section(struct sb_section_t *sec)
         switch(inst->inst)
         {
             case SB_INST_LOAD:
-                sprintf(secname, ".text%d", text_idx++);
+                sprintf(secname, ".text%d", text_idx);
                 elf_add_load_section(&elf, inst->addr, inst->size, inst->data, \
secname);  break;
             case SB_INST_FILL:
@@ -126,7 +143,8 @@ static void extract_sb_section(struct sb_section_t *sec)
             case SB_INST_CALL:
             case SB_INST_JUMP:
                 elf_set_start_addr(&elf, inst->addr);
-                extract_elf_section(&elf, elf_count++, sec->identifier);
+                extract_elf_section(&elf, elf_count++, sec->identifier, cmd_file, \
db_sec, +                    inst->inst == SB_INST_CALL, inst->argument);
                 elf_release(&elf);
                 elf_init(&elf);
                 bss_idx = text_idx = 0;
@@ -138,20 +156,40 @@ static void extract_sb_section(struct sb_section_t *sec)
     }
 
     if(!elf_is_empty(&elf))
-        extract_elf_section(&elf, elf_count, sec->identifier);
+        extract_elf_section(&elf, elf_count, sec->identifier, cmd_file, db_sec, \
false, 0);  elf_release(&elf);
 }
 
 static void extract_sb_file(struct sb_file_t *file)
 {
+    char buffer[64];
+    struct cmd_file_t *cmd_file = xmalloc(sizeof(struct cmd_file_t));
+    memset(cmd_file, 0, sizeof(struct cmd_file_t));
+    db_generate_sb_version(&file->product_ver, buffer, sizeof(buffer));
+    db_add_str_opt(&cmd_file->opt_list, "productVersion", buffer);
+    db_generate_sb_version(&file->component_ver, buffer, sizeof(buffer));
+    db_add_str_opt(&cmd_file->opt_list, "componentVersion", buffer);
+    db_add_int_opt(&cmd_file->opt_list, "driveTag", file->drive_tag);
+    db_add_int_opt(&cmd_file->opt_list, "flags", file->flags);
+    db_add_int_opt(&cmd_file->opt_list, "timestampLow", file->timestamp & \
0xffffffff); +    db_add_int_opt(&cmd_file->opt_list, "timestampHigh", \
file->timestamp >> 32); +    db_add_int_opt(&cmd_file->opt_list, "sbMinorVersion", \
file->minor_version); +
     for(int i = 0; i < file->nr_sections; i++)
-        extract_sb_section(&file->sections[i]);
+        extract_sb_section(&file->sections[i], cmd_file);
+
+    char *filename = xmalloc(strlen(g_out_prefix) + 32);
+    sprintf(filename, "%smake.db", g_out_prefix);
+    if(g_debug)
+        printf("Write command file to %s\n", filename);
+    db_generate_file(cmd_file, filename, NULL, generic_std_printf);
+    db_free(cmd_file);
 }
 
 static void extract_elf(struct elf_params_t *elf, int count)
 {
     char *filename = xmalloc(strlen(g_out_prefix) + 32);
-    sprintf(filename, "%s.%d.elf", g_out_prefix, count);
+    sprintf(filename, "%s%d.elf", g_out_prefix, count);
     if(g_debug)
         printf("Write boot content to %s\n", filename);
 
@@ -375,6 +413,7 @@ 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);
_______________________________________________
rockbox-cvs mailing list
rockbox-cvs@cool.haxx.se
http://cool.haxx.se/cgi-bin/mailman/listinfo/rockbox-cvs


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic