From c4cb4cca47091978be0c557bcc0b2fbdca7c3b61 Mon Sep 17 00:00:00 2001 From: Amaury Pouly Date: Sun, 17 Apr 2011 15:49:58 +0000 Subject: sbtools: move internal elf definition to elf.c, implement elf reading sbtoelf: generate a correct section name for undef and string table sections elftosb: static'ify functions, add cmd file to sb file conversion git-svn-id: svn://svn.rockbox.org/rockbox/trunk@29738 a1c6a512-1295-4272-9138-f99709370657 --- utils/sbtools/elf.c | 240 +++++++++++++++++++++++++++++++++++++++++++++++- utils/sbtools/elf.h | 141 ++-------------------------- utils/sbtools/elftosb.c | 215 ++++++++++++++++++++++++++++++++++++++++--- utils/sbtools/sbtoelf.c | 2 +- 4 files changed, 449 insertions(+), 149 deletions(-) (limited to 'utils') diff --git a/utils/sbtools/elf.c b/utils/sbtools/elf.c index f146bcc111..4b95025d8f 100644 --- a/utils/sbtools/elf.c +++ b/utils/sbtools/elf.c @@ -1,5 +1,135 @@ #include "elf.h" +/** + * Definitions + * taken from elf.h linux header + * based on ELF specification + * based on ARM ELF specification + */ +typedef uint16_t Elf32_Half; + +typedef uint32_t Elf32_Word; +typedef int32_t Elf32_Sword; +typedef uint32_t Elf32_Addr; +typedef uint32_t Elf32_Off; +typedef uint16_t Elf32_Section; + +#define EI_NIDENT 16 + +typedef struct +{ + unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ + Elf32_Half e_type; /* Object file type */ + Elf32_Half e_machine; /* Architecture */ + Elf32_Word e_version; /* Object file version */ + Elf32_Addr e_entry; /* Entry point virtual address */ + Elf32_Off e_phoff; /* Program header table file offset */ + Elf32_Off e_shoff; /* Section header table file offset */ + Elf32_Word e_flags; /* Processor-specific flags */ + Elf32_Half e_ehsize; /* ELF header size in bytes */ + Elf32_Half e_phentsize; /* Program header table entry size */ + Elf32_Half e_phnum; /* Program header table entry count */ + Elf32_Half e_shentsize; /* Section header table entry size */ + Elf32_Half e_shnum; /* Section header table entry count */ + Elf32_Half e_shstrndx; /* Section header string table index */ +}Elf32_Ehdr; + +#define EI_MAG0 0 /* File identification byte 0 index */ +#define ELFMAG0 0x7f /* Magic number byte 0 */ + +#define EI_MAG1 1 /* File identification byte 1 index */ +#define ELFMAG1 'E' /* Magic number byte 1 */ + +#define EI_MAG2 2 /* File identification byte 2 index */ +#define ELFMAG2 'L' /* Magic number byte 2 */ + +#define EI_MAG3 3 /* File identification byte 3 index */ +#define ELFMAG3 'F' /* Magic number byte 3 */ + +#define EI_CLASS 4 /* File class byte index */ +#define ELFCLASS32 1 /* 32-bit objects */ + +#define EI_DATA 5 /* Data encoding byte index */ +#define ELFDATA2LSB 1 /* 2's complement, little endian */ + +#define EI_VERSION 6 /* File version byte index, Value must be EV_CURRENT */ + +#define EI_OSABI 7 /* OS ABI identification */ +#define ELFOSABI_NONE 0 /* UNIX System V ABI */ +#define ELFOSABI_ARM_AEABI 64 /* ARM EABI */ +#define ELFOSABI_ARM 97 /* ARM */ + +#define EI_ABIVERSION 8 /* ABI version */ + +#define EI_PAD 9 /* Byte index of padding bytes */ + +#define ET_EXEC 2 /* Executable file */ + +#define EM_ARM 40 /* ARM */ + +#define EV_CURRENT 1 /* Current version */ + +#define EF_ARM_HASENTRY 0x00000002 + +#define SHN_UNDEF 0 /* Undefined section */ + +typedef struct +{ + Elf32_Word sh_name; /* Section name (string tbl index) */ + Elf32_Word sh_type; /* Section type */ + Elf32_Word sh_flags; /* Section flags */ + Elf32_Addr sh_addr; /* Section virtual addr at execution */ + Elf32_Off sh_offset; /* Section file offset */ + Elf32_Word sh_size; /* Section size in bytes */ + Elf32_Word sh_link; /* Link to another section */ + Elf32_Word sh_info; /* Additional section information */ + Elf32_Word sh_addralign; /* Section alignment */ + Elf32_Word sh_entsize; /* Entry size if section holds table */ +}Elf32_Shdr; + +#define SHT_NULL 0 /* Section header table entry unused */ +#define SHT_PROGBITS 1 /* Program data */ +#define SHT_SYMTAB 2 /* Symbol table */ +#define SHT_STRTAB 3 /* String table */ +#define SHT_RELA 4 /* Relocation entries with addends */ +#define SHT_HASH 5 /* Symbol hash table */ +#define SHT_DYNAMIC 6 /* Dynamic linking information */ +#define SHT_NOTE 7 /* Notes */ +#define SHT_NOBITS 8 /* Program space with no data (bss) */ +#define SHT_REL 9 /* Relocation entries, no addends */ +#define SHT_SHLIB 10 /* Reserved */ +#define SHT_DYNSYM 11 /* Dynamic linker symbol table */ +#define SHT_INIT_ARRAY 14 /* Array of constructors */ +#define SHT_FINI_ARRAY 15 /* Array of destructors */ +#define SHT_PREINIT_ARRAY 16 /* Array of pre-constructors */ +#define SHT_GROUP 17 /* Section group */ +#define SHT_SYMTAB_SHNDX 18 /* Extended section indeces */ +#define SHT_NUM 19 /* Number of defined types. */ + +#define SHF_WRITE (1 << 0) /* Writable */ +#define SHF_ALLOC (1 << 1) /* Occupies memory during execution */ +#define SHF_EXECINSTR (1 << 2) /* Executable */ +#define SHF_MERGE (1 << 4) /* Might be merged */ +#define SHF_STRINGS (1 << 5) /* Contains nul-terminated strings */ + +typedef struct +{ + Elf32_Word p_type; /* Segment type */ + Elf32_Off p_offset; /* Segment file offset */ + Elf32_Addr p_vaddr; /* Segment virtual address */ + Elf32_Addr p_paddr; /* Segment physical address */ + Elf32_Word p_filesz; /* Segment size in file */ + Elf32_Word p_memsz; /* Segment size in memory */ + Elf32_Word p_flags; /* Segment flags */ + Elf32_Word p_align; /* Segment alignment */ +}Elf32_Phdr; + +#define PT_LOAD 1 /* Loadable program segment */ + +#define PF_X (1 << 0) /* Segment is executable */ +#define PF_W (1 << 1) /* Segment is writable */ +#define PF_R (1 << 2) /* Segment is readable */ + void elf_init(struct elf_params_t *params) { params->has_start_addr = false; @@ -54,7 +184,7 @@ void elf_add_fill_section(struct elf_params_t *params, sec->pattern = pattern; } -void elf_output(struct elf_params_t *params, elf_write_fn_t write, void *user) +void elf_write_file(struct elf_params_t *params, elf_write_fn_t write, void *user) { Elf32_Ehdr ehdr; uint32_t phnum = 0; @@ -64,9 +194,11 @@ void elf_output(struct elf_params_t *params, elf_write_fn_t write, void *user) Elf32_Shdr shdr; memset(&ehdr, 0, EI_NIDENT); - uint32_t bss_strtbl = 0; + uint32_t bss_strtbl = 1; uint32_t text_strtbl = bss_strtbl + strlen(".bss") + 1; - uint32_t strtbl_size = text_strtbl + strlen(".text") + 1; + uint32_t shstrtab_strtbl = text_strtbl + strlen(".text") + 1; + uint32_t strtbl_size = shstrtab_strtbl + strlen(".shstrtab") + 1; + while(sec) { @@ -182,7 +314,7 @@ void elf_output(struct elf_params_t *params, elf_write_fn_t write, void *user) } { - shdr.sh_name = bss_strtbl; + shdr.sh_name = shstrtab_strtbl; shdr.sh_type = SHT_STRTAB; shdr.sh_flags = 0; shdr.sh_addr = 0; @@ -206,7 +338,86 @@ void elf_output(struct elf_params_t *params, elf_write_fn_t write, void *user) sec = sec->next; } - write(user, strtbl_offset + data_offset, ".bss\0.text\0", strtbl_size); + write(user, strtbl_offset + data_offset, "\0.bss\0.text\0.shstrtab\0", strtbl_size); +} + +bool elf_read_file(struct elf_params_t *params, elf_read_fn_t read, + elf_printf_fn_t printf, void *user) +{ + #define error_printf(...) ({printf(user, true, __VA_ARGS__); return false;}) + /* read header */ + Elf32_Ehdr ehdr; + if(!read(user, 0, &ehdr, sizeof(ehdr))) + { + printf(user, true, "error reading elf header\n"); + return false; + } + /* basic checks */ + if(ehdr.e_ident[EI_MAG0] != ELFMAG0 || ehdr.e_ident[EI_MAG1] != ELFMAG1 || + ehdr.e_ident[EI_MAG2] != ELFMAG2 || ehdr.e_ident[EI_MAG3] != ELFMAG3) + error_printf("invalid elf header\n"); + if(ehdr.e_ident[EI_CLASS] != ELFCLASS32) + error_printf("invalid elf class: must be a 32-bit object\n"); + if(ehdr.e_ident[EI_DATA] != ELFDATA2LSB) + error_printf("invalid elf data encoding: must be 32-bit lsb\n"); + if(ehdr.e_ident[EI_VERSION] != EV_CURRENT) + error_printf("invalid elf version"); + if(ehdr.e_type != ET_EXEC) + error_printf("invalid elf file: must be an executable file\n"); + if(ehdr.e_machine != EM_ARM) + error_printf("invalid elf file: must target an arm machine\n"); + if(ehdr.e_ehsize != sizeof(ehdr)) + error_printf("invalid elf file: size header mismatch\n"); + if(ehdr.e_phentsize != sizeof(Elf32_Phdr)) + error_printf("invalid elf file: program header size mismatch\n"); + if(ehdr.e_shentsize != sizeof(Elf32_Shdr)) + error_printf("invalid elf file: section header size mismatch\n"); + if(ehdr.e_flags & EF_ARM_HASENTRY) + elf_set_start_addr(params, ehdr.e_entry); + + char *strtab = NULL; + { + Elf32_Shdr shstrtab; + if(read(user, ehdr.e_shoff + ehdr.e_shstrndx * ehdr.e_shentsize, + &shstrtab, sizeof(shstrtab))) + { + strtab = xmalloc(shstrtab.sh_size); + if(!read(user, shstrtab.sh_offset, strtab, shstrtab.sh_size)) + { + free(strtab); + strtab = NULL; + } + } + } + /* run through sections */ + printf(user, false, "ELF file:\n"); + for(int i = 1; i< ehdr.e_shnum; i++) + { + uint32_t off = ehdr.e_shoff + i * ehdr.e_shentsize; + Elf32_Shdr shdr; + memset(&shdr, 0, sizeof(shdr)); + if(!read(user, off, &shdr, sizeof(shdr))) + error_printf("error reading elf section header"); + + if(shdr.sh_type == SHT_PROGBITS && shdr.sh_flags & SHF_ALLOC) + { + void *data = xmalloc(shdr.sh_size); + if(!read(user, shdr.sh_offset, data, shdr.sh_size)) + error_printf("error read self section data"); + elf_add_load_section(params, shdr.sh_addr, shdr.sh_size, data); + + printf(user, false, "create load segment for %s\n", &strtab[shdr.sh_name]); + } + else if(shdr.sh_type == SHT_NOBITS && shdr.sh_flags & SHF_ALLOC) + { + elf_add_fill_section(params, shdr.sh_addr, shdr.sh_size, 0); + printf(user, false, "create fill segment for %s\n", &strtab[shdr.sh_name]); + } + else + printf(user, false, "filter out %s\n", &strtab[shdr.sh_name], shdr.sh_type); + + } + return true; } bool elf_is_empty(struct elf_params_t *params) @@ -220,6 +431,25 @@ void elf_set_start_addr(struct elf_params_t *params, uint32_t addr) params->start_addr = addr; } +bool elf_get_start_addr(struct elf_params_t *params, uint32_t *addr) +{ + if(params->has_start_addr && addr != NULL) + *addr = params->start_addr; + return params->has_start_addr; +} + +int elf_get_nr_sections(struct elf_params_t *params) +{ + int nr = 0; + struct elf_section_t *sec = params->first_section; + while(sec) + { + nr++; + sec = sec->next; + } + return nr; +} + void elf_release(struct elf_params_t *params) { struct elf_section_t *sec, *next_sec; diff --git a/utils/sbtools/elf.h b/utils/sbtools/elf.h index d2bf210c5c..b145bfffc5 100644 --- a/utils/sbtools/elf.h +++ b/utils/sbtools/elf.h @@ -5,136 +5,6 @@ #include #include -/** - * Definitions - * taken from elf.h linux header - * based on ELF specification - * based on ARM ELF specification - */ -typedef uint16_t Elf32_Half; - -typedef uint32_t Elf32_Word; -typedef int32_t Elf32_Sword; -typedef uint32_t Elf32_Addr; -typedef uint32_t Elf32_Off; -typedef uint16_t Elf32_Section; - -#define EI_NIDENT 16 - -typedef struct -{ - unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ - Elf32_Half e_type; /* Object file type */ - Elf32_Half e_machine; /* Architecture */ - Elf32_Word e_version; /* Object file version */ - Elf32_Addr e_entry; /* Entry point virtual address */ - Elf32_Off e_phoff; /* Program header table file offset */ - Elf32_Off e_shoff; /* Section header table file offset */ - Elf32_Word e_flags; /* Processor-specific flags */ - Elf32_Half e_ehsize; /* ELF header size in bytes */ - Elf32_Half e_phentsize; /* Program header table entry size */ - Elf32_Half e_phnum; /* Program header table entry count */ - Elf32_Half e_shentsize; /* Section header table entry size */ - Elf32_Half e_shnum; /* Section header table entry count */ - Elf32_Half e_shstrndx; /* Section header string table index */ -}Elf32_Ehdr; - -#define EI_MAG0 0 /* File identification byte 0 index */ -#define ELFMAG0 0x7f /* Magic number byte 0 */ - -#define EI_MAG1 1 /* File identification byte 1 index */ -#define ELFMAG1 'E' /* Magic number byte 1 */ - -#define EI_MAG2 2 /* File identification byte 2 index */ -#define ELFMAG2 'L' /* Magic number byte 2 */ - -#define EI_MAG3 3 /* File identification byte 3 index */ -#define ELFMAG3 'F' /* Magic number byte 3 */ - -#define EI_CLASS 4 /* File class byte index */ -#define ELFCLASS32 1 /* 32-bit objects */ - -#define EI_DATA 5 /* Data encoding byte index */ -#define ELFDATA2LSB 1 /* 2's complement, little endian */ - -#define EI_VERSION 6 /* File version byte index, Value must be EV_CURRENT */ - -#define EI_OSABI 7 /* OS ABI identification */ -#define ELFOSABI_NONE 0 /* UNIX System V ABI */ -#define ELFOSABI_ARM_AEABI 64 /* ARM EABI */ -#define ELFOSABI_ARM 97 /* ARM */ - -#define EI_ABIVERSION 8 /* ABI version */ - -#define EI_PAD 9 /* Byte index of padding bytes */ - -#define ET_EXEC 2 /* Executable file */ - -#define EM_ARM 40 /* ARM */ - -#define EV_CURRENT 1 /* Current version */ - -#define EF_ARM_HASENTRY 0x00000002 - -#define SHN_UNDEF 0 /* Undefined section */ - -typedef struct -{ - Elf32_Word sh_name; /* Section name (string tbl index) */ - Elf32_Word sh_type; /* Section type */ - Elf32_Word sh_flags; /* Section flags */ - Elf32_Addr sh_addr; /* Section virtual addr at execution */ - Elf32_Off sh_offset; /* Section file offset */ - Elf32_Word sh_size; /* Section size in bytes */ - Elf32_Word sh_link; /* Link to another section */ - Elf32_Word sh_info; /* Additional section information */ - Elf32_Word sh_addralign; /* Section alignment */ - Elf32_Word sh_entsize; /* Entry size if section holds table */ -}Elf32_Shdr; - -#define SHT_NULL 0 /* Section header table entry unused */ -#define SHT_PROGBITS 1 /* Program data */ -#define SHT_SYMTAB 2 /* Symbol table */ -#define SHT_STRTAB 3 /* String table */ -#define SHT_RELA 4 /* Relocation entries with addends */ -#define SHT_HASH 5 /* Symbol hash table */ -#define SHT_DYNAMIC 6 /* Dynamic linking information */ -#define SHT_NOTE 7 /* Notes */ -#define SHT_NOBITS 8 /* Program space with no data (bss) */ -#define SHT_REL 9 /* Relocation entries, no addends */ -#define SHT_SHLIB 10 /* Reserved */ -#define SHT_DYNSYM 11 /* Dynamic linker symbol table */ -#define SHT_INIT_ARRAY 14 /* Array of constructors */ -#define SHT_FINI_ARRAY 15 /* Array of destructors */ -#define SHT_PREINIT_ARRAY 16 /* Array of pre-constructors */ -#define SHT_GROUP 17 /* Section group */ -#define SHT_SYMTAB_SHNDX 18 /* Extended section indeces */ -#define SHT_NUM 19 /* Number of defined types. */ - -#define SHF_WRITE (1 << 0) /* Writable */ -#define SHF_ALLOC (1 << 1) /* Occupies memory during execution */ -#define SHF_EXECINSTR (1 << 2) /* Executable */ -#define SHF_MERGE (1 << 4) /* Might be merged */ -#define SHF_STRINGS (1 << 5) /* Contains nul-terminated strings */ - -typedef struct -{ - Elf32_Word p_type; /* Segment type */ - Elf32_Off p_offset; /* Segment file offset */ - Elf32_Addr p_vaddr; /* Segment virtual address */ - Elf32_Addr p_paddr; /* Segment physical address */ - Elf32_Word p_filesz; /* Segment size in file */ - Elf32_Word p_memsz; /* Segment size in memory */ - Elf32_Word p_flags; /* Segment flags */ - Elf32_Word p_align; /* Segment alignment */ -}Elf32_Phdr; - -#define PT_LOAD 1 /* Loadable program segment */ - -#define PF_X (1 << 0) /* Segment is executable */ -#define PF_W (1 << 1) /* Segment is writable */ -#define PF_R (1 << 2) /* Segment is readable */ - /** * API */ @@ -154,7 +24,7 @@ struct elf_section_t uint32_t pattern; /* */ struct elf_section_t *next; - /* Internal to elf_output */ + /* Internal to elf_write_file */ uint32_t offset; }; @@ -166,14 +36,21 @@ struct elf_params_t struct elf_section_t *last_section; }; +typedef bool (*elf_read_fn_t)(void *user, uint32_t addr, void *buf, size_t count); +/* write function manages it's own error state */ typedef void (*elf_write_fn_t)(void *user, uint32_t addr, const void *buf, size_t count); +typedef void (*elf_printf_fn_t)(void *user, bool error, const char *fmt, ...); void elf_init(struct elf_params_t *params); void elf_add_load_section(struct elf_params_t *params, uint32_t load_addr, uint32_t size, const void *section); void elf_add_fill_section(struct elf_params_t *params, uint32_t fill_addr, uint32_t size, uint32_t pattern); -void elf_output(struct elf_params_t *params, elf_write_fn_t write, void *user); +void elf_write_file(struct elf_params_t *params, elf_write_fn_t write, void *user); +bool elf_read_file(struct elf_params_t *params, elf_read_fn_t read, elf_printf_fn_t printf, + void *user); bool elf_is_empty(struct elf_params_t *params); void elf_set_start_addr(struct elf_params_t *params, uint32_t addr); +bool elf_get_start_addr(struct elf_params_t *params, uint32_t *addr); +int elf_get_nr_sections(struct elf_params_t *params); void elf_release(struct elf_params_t *params); diff --git a/utils/sbtools/elftosb.c b/utils/sbtools/elftosb.c index 73768dd9a3..c4887ab47a 100644 --- a/utils/sbtools/elftosb.c +++ b/utils/sbtools/elftosb.c @@ -31,6 +31,7 @@ #include #include #include +#include #include "crypto.h" #include "elf.h" @@ -39,6 +40,12 @@ #define bug(...) do { fprintf(stderr,"ERROR: "__VA_ARGS__); exit(1); } while(0) #define bugp(a) do { perror("ERROR: "a); exit(1); } while(0) +bool g_debug = false; + +/** + * Misc + */ + void *xmalloc(size_t s) /* malloc helper, used in elf.c */ { void * r = malloc(s); @@ -67,6 +74,10 @@ static int convxdigit(char digit, byte *val) return 1; } +/** + * Key file parsing + */ + typedef byte (*key_array_t)[16]; static key_array_t read_keys(const char *key_file, int *num_keys) @@ -117,11 +128,18 @@ static key_array_t read_keys(const char *key_file, int *num_keys) return keys; } +/** + * Command file parsing + */ + struct cmd_source_t { char *identifier; char *filename; struct cmd_source_t *next; + /* for later use */ + bool elf_loaded; + struct elf_params_t elf; }; enum cmd_inst_type_t @@ -142,6 +160,7 @@ struct cmd_section_t { uint32_t identifier; struct cmd_inst_t *inst_list; + struct cmd_section_t *next; }; struct cmd_file_t @@ -171,7 +190,7 @@ struct lexem_t uint32_t num; }; -void __parse_string(char **ptr, char *end, void *user, void (*emit_fn)(void *user, char c)) +static void __parse_string(char **ptr, char *end, void *user, void (*emit_fn)(void *user, char c)) { while(*ptr != end) { @@ -196,19 +215,19 @@ void __parse_string(char **ptr, char *end, void *user, void (*emit_fn)(void *use (*ptr)++; } -void __parse_string_emit(void *user, char c) +static void __parse_string_emit(void *user, char c) { char **pstr = (char **)user; *(*pstr)++ = c; } -void __parse_string_count(void *user, char c) +static void __parse_string_count(void *user, char c) { (void) c; (*(int *)user)++; } -void parse_string(char **ptr, char *end, struct lexem_t *lexem) +static void parse_string(char **ptr, char *end, struct lexem_t *lexem) { /* skip " */ (*ptr)++; @@ -224,7 +243,7 @@ void parse_string(char **ptr, char *end, struct lexem_t *lexem) __parse_string(ptr, end, (void *)&pstr, __parse_string_emit); } -void parse_number(char **ptr, char *end, struct lexem_t *lexem) +static void parse_number(char **ptr, char *end, struct lexem_t *lexem) { int base = 10; if(**ptr == '0' && (*ptr) + 1 != end && (*ptr)[1] == 'x') @@ -247,7 +266,7 @@ void parse_number(char **ptr, char *end, struct lexem_t *lexem) } } -void parse_identifier(char **ptr, char *end, struct lexem_t *lexem) +static void parse_identifier(char **ptr, char *end, struct lexem_t *lexem) { /* remember position */ char *old = *ptr; @@ -260,7 +279,7 @@ void parse_identifier(char **ptr, char *end, struct lexem_t *lexem) memcpy(lexem->str, old, len); } -void next_lexem(char **ptr, char *end, struct lexem_t *lexem) +static void next_lexem(char **ptr, char *end, struct lexem_t *lexem) { #define ret_simple(t, advance) ({(*ptr) += advance; lexem->type = t; return;}) while(true) @@ -294,7 +313,7 @@ void next_lexem(char **ptr, char *end, struct lexem_t *lexem) #undef ret_simple } -void log_lexem(struct lexem_t *lexem) +static void log_lexem(struct lexem_t *lexem) { switch(lexem->type) { @@ -312,19 +331,19 @@ void log_lexem(struct lexem_t *lexem) } } -char *find_source_by_id(struct cmd_file_t *cmd_file, const char *id) +static struct cmd_source_t *find_source_by_id(struct cmd_file_t *cmd_file, const char *id) { struct cmd_source_t *src = cmd_file->source_list; while(src) { if(strcmp(src->identifier, id) == 0) - return src->filename; + return src; src = src->next; } return NULL; } -struct cmd_file_t *read_command_file(const char *file) +static struct cmd_file_t *read_command_file(const char *file) { int size; struct stat st; @@ -380,6 +399,7 @@ struct cmd_file_t *read_command_file(const char *file) } /* sections */ + struct cmd_section_t *end_sec = NULL; while(true) { struct cmd_section_t *sec = xmalloc(sizeof(struct cmd_section_t)); @@ -442,12 +462,184 @@ struct cmd_file_t *read_command_file(const char *file) end_list = inst; } } + + if(end_sec == NULL) + { + cmd_file->section_list = sec; + end_sec = sec; + } + else + { + end_sec->next = sec; + end_sec = sec; + } } #undef next return cmd_file; } +/** + * command file to sb conversion + */ + +struct sb_inst_t +{ + uint8_t inst; /* SB_INST_* */ + uint32_t size; + // + void *data; + uint32_t pattern; + uint32_t addr; + // +}; + +struct sb_section_t +{ + uint32_t identifier; + int nr_insts; + struct sb_inst_t *insts; +}; + +struct sb_file_t +{ + int nr_sections; + struct sb_section_t *sections; +}; + +static bool elf_read(void *user, uint32_t addr, void *buf, size_t count) +{ + if(lseek(*(int *)user, addr, SEEK_SET) == (off_t)-1) + return false; + return read(*(int *)user, buf, count) == (ssize_t)count; +} + +static void elf_printf(void *user, bool error, const char *fmt, ...) +{ + if(!g_debug && !error) + return; + (void) user; + va_list args; + va_start(args, fmt); + vprintf(fmt, args); + va_end(args); +} + +static void load_elf_by_id(struct cmd_file_t *cmd_file, const char *id) +{ + struct cmd_source_t *src = find_source_by_id(cmd_file, id); + if(src == NULL) + bug("undefined reference to source '%s'\n", id); + /* avoid reloading */ + if(src->elf_loaded) + return; + int fd = open(src->filename, O_RDONLY); + if(fd < 0) + bug("cannot open '%s' (id '%s')\n", src->filename, id); + elf_init(&src->elf); + src->elf_loaded = elf_read_file(&src->elf, elf_read, elf_printf, &fd); + close(fd); + if(!src->elf_loaded) + bug("error loading elf file '%s' (id '%s')\n", src->filename, id); +} + +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)); + /* count sections */ + struct cmd_section_t *csec = cmd_file->section_list; + while(csec) + { + sb->nr_sections++; + csec = csec->next; + } + + sb->sections = xmalloc(sb->nr_sections * sizeof(struct sb_section_t)); + memset(sb->sections, 0, sb->nr_sections * sizeof(struct sb_section_t)); + /* flatten sections */ + csec = cmd_file->section_list; + for(int i = 0; i < sb->nr_sections; i++, csec = csec->next) + { + struct sb_section_t *sec = &sb->sections[i]; + sec->identifier = csec->identifier; + /* count instructions */ + struct cmd_inst_t *cinst = csec->inst_list; + while(cinst) + { + load_elf_by_id(cmd_file, cinst->identifier); + struct elf_params_t *elf = &find_source_by_id(cmd_file, cinst->identifier)->elf; + + if(cinst->type == CMD_LOAD) + sec->nr_insts += elf_get_nr_sections(elf); + else if(cinst->type == CMD_JUMP || cinst->type == CMD_LOAD) + { + if(!elf_get_start_addr(elf, NULL)) + bug("cannot jump/call '%s' because it has no starting point !", cinst->identifier); + sec->nr_insts++; + } + + cinst = cinst->next; + } + + sec->insts = xmalloc(sec->nr_insts * sizeof(struct sb_inst_t)); + memset(sec->insts, 0, sec->nr_insts * sizeof(struct sb_inst_t)); + /* flatten */ + int idx = 0; + cinst = csec->inst_list; + while(cinst) + { + struct elf_params_t *elf = &find_source_by_id(cmd_file, cinst->identifier)->elf; + + if(cinst->type == CMD_LOAD) + { + struct elf_section_t *esec = elf->first_section; + while(esec) + { + if(esec->type == EST_LOAD) + { + 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; + if(g_debug) + printf("LOAD | addr=0x%08x | len=0x%08x | crc=0x%08x\n", + esec->addr, esec->size, 0); + } + else if(esec->type == EST_FILL) + { + sec->insts[idx].inst = SB_INST_FILL; + sec->insts[idx].addr = esec->addr; + sec->insts[idx].size = esec->size; + sec->insts[idx++].pattern = esec->pattern; + if(g_debug) + printf("FILL | addr=0x%08x | len=0x%08x | pattern=0x%08x\n", + esec->addr, esec->size, esec->pattern); + } + esec = esec->next; + } + } + else if(cinst->type == CMD_JUMP || cinst->type == CMD_LOAD) + { + sec->insts[idx].inst = (cinst->type == CMD_JUMP) ? SB_INST_JUMP : SB_INST_CALL; + sec->insts[idx++].addr = elf->start_addr; + if(g_debug) + printf("%s | addr=0x%08x | arg=0x%08x\n", + (cinst->type == CMD_JUMP) ? "JUMP" : "CALL", + elf->start_addr, 0); + } + + cinst = cinst->next; + } + } + + return sb; +} + +/** + * Sb file production + */ + #define ROUND_UP(val, round) ((((val) + (round) - 1) / (round)) * (round)) static uint8_t instruction_checksum(struct sb_instruction_header_t *hdr) @@ -467,6 +659,7 @@ int main(int argc, const char **argv) int nr_keys; key_array_t key_array = read_keys(argv[2], &nr_keys); struct cmd_file_t *cmd_file = read_command_file(argv[1]); + struct sb_file_t *sb_file = apply_cmd_file(cmd_file); return 0; } diff --git a/utils/sbtools/sbtoelf.c b/utils/sbtools/sbtoelf.c index 3eb168ddd1..3a3d9a7bb7 100644 --- a/utils/sbtools/sbtoelf.c +++ b/utils/sbtools/sbtoelf.c @@ -183,7 +183,7 @@ static void extract_elf_section(struct elf_params_t *elf, int count, const char if(fd == NULL) return ; - elf_output(elf, elf_write, fd); + elf_write_file(elf, elf_write, fd); fclose(fd); } -- cgit v1.2.3