summaryrefslogtreecommitdiff
path: root/utils/sbtools/elftosb.c
diff options
context:
space:
mode:
Diffstat (limited to 'utils/sbtools/elftosb.c')
-rw-r--r--utils/sbtools/elftosb.c215
1 files changed, 204 insertions, 11 deletions
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 @@
31#include <string.h> 31#include <string.h>
32#include <ctype.h> 32#include <ctype.h>
33#include <time.h> 33#include <time.h>
34#include <stdarg.h>
34 35
35#include "crypto.h" 36#include "crypto.h"
36#include "elf.h" 37#include "elf.h"
@@ -39,6 +40,12 @@
39#define bug(...) do { fprintf(stderr,"ERROR: "__VA_ARGS__); exit(1); } while(0) 40#define bug(...) do { fprintf(stderr,"ERROR: "__VA_ARGS__); exit(1); } while(0)
40#define bugp(a) do { perror("ERROR: "a); exit(1); } while(0) 41#define bugp(a) do { perror("ERROR: "a); exit(1); } while(0)
41 42
43bool g_debug = false;
44
45/**
46 * Misc
47 */
48
42void *xmalloc(size_t s) /* malloc helper, used in elf.c */ 49void *xmalloc(size_t s) /* malloc helper, used in elf.c */
43{ 50{
44 void * r = malloc(s); 51 void * r = malloc(s);
@@ -67,6 +74,10 @@ static int convxdigit(char digit, byte *val)
67 return 1; 74 return 1;
68} 75}
69 76
77/**
78 * Key file parsing
79 */
80
70typedef byte (*key_array_t)[16]; 81typedef byte (*key_array_t)[16];
71 82
72static key_array_t read_keys(const char *key_file, int *num_keys) 83static 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)
117 return keys; 128 return keys;
118} 129}
119 130
131/**
132 * Command file parsing
133 */
134
120struct cmd_source_t 135struct cmd_source_t
121{ 136{
122 char *identifier; 137 char *identifier;
123 char *filename; 138 char *filename;
124 struct cmd_source_t *next; 139 struct cmd_source_t *next;
140 /* for later use */
141 bool elf_loaded;
142 struct elf_params_t elf;
125}; 143};
126 144
127enum cmd_inst_type_t 145enum cmd_inst_type_t
@@ -142,6 +160,7 @@ struct cmd_section_t
142{ 160{
143 uint32_t identifier; 161 uint32_t identifier;
144 struct cmd_inst_t *inst_list; 162 struct cmd_inst_t *inst_list;
163 struct cmd_section_t *next;
145}; 164};
146 165
147struct cmd_file_t 166struct cmd_file_t
@@ -171,7 +190,7 @@ struct lexem_t
171 uint32_t num; 190 uint32_t num;
172}; 191};
173 192
174void __parse_string(char **ptr, char *end, void *user, void (*emit_fn)(void *user, char c)) 193static void __parse_string(char **ptr, char *end, void *user, void (*emit_fn)(void *user, char c))
175{ 194{
176 while(*ptr != end) 195 while(*ptr != end)
177 { 196 {
@@ -196,19 +215,19 @@ void __parse_string(char **ptr, char *end, void *user, void (*emit_fn)(void *use
196 (*ptr)++; 215 (*ptr)++;
197} 216}
198 217
199void __parse_string_emit(void *user, char c) 218static void __parse_string_emit(void *user, char c)
200{ 219{
201 char **pstr = (char **)user; 220 char **pstr = (char **)user;
202 *(*pstr)++ = c; 221 *(*pstr)++ = c;
203} 222}
204 223
205void __parse_string_count(void *user, char c) 224static void __parse_string_count(void *user, char c)
206{ 225{
207 (void) c; 226 (void) c;
208 (*(int *)user)++; 227 (*(int *)user)++;
209} 228}
210 229
211void parse_string(char **ptr, char *end, struct lexem_t *lexem) 230static void parse_string(char **ptr, char *end, struct lexem_t *lexem)
212{ 231{
213 /* skip " */ 232 /* skip " */
214 (*ptr)++; 233 (*ptr)++;
@@ -224,7 +243,7 @@ void parse_string(char **ptr, char *end, struct lexem_t *lexem)
224 __parse_string(ptr, end, (void *)&pstr, __parse_string_emit); 243 __parse_string(ptr, end, (void *)&pstr, __parse_string_emit);
225} 244}
226 245
227void parse_number(char **ptr, char *end, struct lexem_t *lexem) 246static void parse_number(char **ptr, char *end, struct lexem_t *lexem)
228{ 247{
229 int base = 10; 248 int base = 10;
230 if(**ptr == '0' && (*ptr) + 1 != end && (*ptr)[1] == 'x') 249 if(**ptr == '0' && (*ptr) + 1 != end && (*ptr)[1] == 'x')
@@ -247,7 +266,7 @@ void parse_number(char **ptr, char *end, struct lexem_t *lexem)
247 } 266 }
248} 267}
249 268
250void parse_identifier(char **ptr, char *end, struct lexem_t *lexem) 269static void parse_identifier(char **ptr, char *end, struct lexem_t *lexem)
251{ 270{
252 /* remember position */ 271 /* remember position */
253 char *old = *ptr; 272 char *old = *ptr;
@@ -260,7 +279,7 @@ void parse_identifier(char **ptr, char *end, struct lexem_t *lexem)
260 memcpy(lexem->str, old, len); 279 memcpy(lexem->str, old, len);
261} 280}
262 281
263void next_lexem(char **ptr, char *end, struct lexem_t *lexem) 282static void next_lexem(char **ptr, char *end, struct lexem_t *lexem)
264{ 283{
265 #define ret_simple(t, advance) ({(*ptr) += advance; lexem->type = t; return;}) 284 #define ret_simple(t, advance) ({(*ptr) += advance; lexem->type = t; return;})
266 while(true) 285 while(true)
@@ -294,7 +313,7 @@ void next_lexem(char **ptr, char *end, struct lexem_t *lexem)
294 #undef ret_simple 313 #undef ret_simple
295} 314}
296 315
297void log_lexem(struct lexem_t *lexem) 316static void log_lexem(struct lexem_t *lexem)
298{ 317{
299 switch(lexem->type) 318 switch(lexem->type)
300 { 319 {
@@ -312,19 +331,19 @@ void log_lexem(struct lexem_t *lexem)
312 } 331 }
313} 332}
314 333
315char *find_source_by_id(struct cmd_file_t *cmd_file, const char *id) 334static struct cmd_source_t *find_source_by_id(struct cmd_file_t *cmd_file, const char *id)
316{ 335{
317 struct cmd_source_t *src = cmd_file->source_list; 336 struct cmd_source_t *src = cmd_file->source_list;
318 while(src) 337 while(src)
319 { 338 {
320 if(strcmp(src->identifier, id) == 0) 339 if(strcmp(src->identifier, id) == 0)
321 return src->filename; 340 return src;
322 src = src->next; 341 src = src->next;
323 } 342 }
324 return NULL; 343 return NULL;
325} 344}
326 345
327struct cmd_file_t *read_command_file(const char *file) 346static struct cmd_file_t *read_command_file(const char *file)
328{ 347{
329 int size; 348 int size;
330 struct stat st; 349 struct stat st;
@@ -380,6 +399,7 @@ struct cmd_file_t *read_command_file(const char *file)
380 } 399 }
381 400
382 /* sections */ 401 /* sections */
402 struct cmd_section_t *end_sec = NULL;
383 while(true) 403 while(true)
384 { 404 {
385 struct cmd_section_t *sec = xmalloc(sizeof(struct cmd_section_t)); 405 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)
442 end_list = inst; 462 end_list = inst;
443 } 463 }
444 } 464 }
465
466 if(end_sec == NULL)
467 {
468 cmd_file->section_list = sec;
469 end_sec = sec;
470 }
471 else
472 {
473 end_sec->next = sec;
474 end_sec = sec;
475 }
445 } 476 }
446 #undef next 477 #undef next
447 478
448 return cmd_file; 479 return cmd_file;
449} 480}
450 481
482/**
483 * command file to sb conversion
484 */
485
486struct sb_inst_t
487{
488 uint8_t inst; /* SB_INST_* */
489 uint32_t size;
490 // <union>
491 void *data;
492 uint32_t pattern;
493 uint32_t addr;
494 // </union>
495};
496
497struct sb_section_t
498{
499 uint32_t identifier;
500 int nr_insts;
501 struct sb_inst_t *insts;
502};
503
504struct sb_file_t
505{
506 int nr_sections;
507 struct sb_section_t *sections;
508};
509
510static bool elf_read(void *user, uint32_t addr, void *buf, size_t count)
511{
512 if(lseek(*(int *)user, addr, SEEK_SET) == (off_t)-1)
513 return false;
514 return read(*(int *)user, buf, count) == (ssize_t)count;
515}
516
517static void elf_printf(void *user, bool error, const char *fmt, ...)
518{
519 if(!g_debug && !error)
520 return;
521 (void) user;
522 va_list args;
523 va_start(args, fmt);
524 vprintf(fmt, args);
525 va_end(args);
526}
527
528static void load_elf_by_id(struct cmd_file_t *cmd_file, const char *id)
529{
530 struct cmd_source_t *src = find_source_by_id(cmd_file, id);
531 if(src == NULL)
532 bug("undefined reference to source '%s'\n", id);
533 /* avoid reloading */
534 if(src->elf_loaded)
535 return;
536 int fd = open(src->filename, O_RDONLY);
537 if(fd < 0)
538 bug("cannot open '%s' (id '%s')\n", src->filename, id);
539 elf_init(&src->elf);
540 src->elf_loaded = elf_read_file(&src->elf, elf_read, elf_printf, &fd);
541 close(fd);
542 if(!src->elf_loaded)
543 bug("error loading elf file '%s' (id '%s')\n", src->filename, id);
544}
545
546static struct sb_file_t *apply_cmd_file(struct cmd_file_t *cmd_file)
547{
548 struct sb_file_t *sb = xmalloc(sizeof(struct sb_file_t));
549 memset(sb, 0, sizeof(struct sb_file_t));
550 /* count sections */
551 struct cmd_section_t *csec = cmd_file->section_list;
552 while(csec)
553 {
554 sb->nr_sections++;
555 csec = csec->next;
556 }
557
558 sb->sections = xmalloc(sb->nr_sections * sizeof(struct sb_section_t));
559 memset(sb->sections, 0, sb->nr_sections * sizeof(struct sb_section_t));
560 /* flatten sections */
561 csec = cmd_file->section_list;
562 for(int i = 0; i < sb->nr_sections; i++, csec = csec->next)
563 {
564 struct sb_section_t *sec = &sb->sections[i];
565 sec->identifier = csec->identifier;
566 /* count instructions */
567 struct cmd_inst_t *cinst = csec->inst_list;
568 while(cinst)
569 {
570 load_elf_by_id(cmd_file, cinst->identifier);
571 struct elf_params_t *elf = &find_source_by_id(cmd_file, cinst->identifier)->elf;
572
573 if(cinst->type == CMD_LOAD)
574 sec->nr_insts += elf_get_nr_sections(elf);
575 else if(cinst->type == CMD_JUMP || cinst->type == CMD_LOAD)
576 {
577 if(!elf_get_start_addr(elf, NULL))
578 bug("cannot jump/call '%s' because it has no starting point !", cinst->identifier);
579 sec->nr_insts++;
580 }
581
582 cinst = cinst->next;
583 }
584
585 sec->insts = xmalloc(sec->nr_insts * sizeof(struct sb_inst_t));
586 memset(sec->insts, 0, sec->nr_insts * sizeof(struct sb_inst_t));
587 /* flatten */
588 int idx = 0;
589 cinst = csec->inst_list;
590 while(cinst)
591 {
592 struct elf_params_t *elf = &find_source_by_id(cmd_file, cinst->identifier)->elf;
593
594 if(cinst->type == CMD_LOAD)
595 {
596 struct elf_section_t *esec = elf->first_section;
597 while(esec)
598 {
599 if(esec->type == EST_LOAD)
600 {
601 sec->insts[idx].inst = SB_INST_LOAD;
602 sec->insts[idx].addr = esec->addr;
603 sec->insts[idx].size = esec->size;
604 sec->insts[idx++].data = esec->section;
605 if(g_debug)
606 printf("LOAD | addr=0x%08x | len=0x%08x | crc=0x%08x\n",
607 esec->addr, esec->size, 0);
608 }
609 else if(esec->type == EST_FILL)
610 {
611 sec->insts[idx].inst = SB_INST_FILL;
612 sec->insts[idx].addr = esec->addr;
613 sec->insts[idx].size = esec->size;
614 sec->insts[idx++].pattern = esec->pattern;
615 if(g_debug)
616 printf("FILL | addr=0x%08x | len=0x%08x | pattern=0x%08x\n",
617 esec->addr, esec->size, esec->pattern);
618 }
619 esec = esec->next;
620 }
621 }
622 else if(cinst->type == CMD_JUMP || cinst->type == CMD_LOAD)
623 {
624 sec->insts[idx].inst = (cinst->type == CMD_JUMP) ? SB_INST_JUMP : SB_INST_CALL;
625 sec->insts[idx++].addr = elf->start_addr;
626 if(g_debug)
627 printf("%s | addr=0x%08x | arg=0x%08x\n",
628 (cinst->type == CMD_JUMP) ? "JUMP" : "CALL",
629 elf->start_addr, 0);
630 }
631
632 cinst = cinst->next;
633 }
634 }
635
636 return sb;
637}
638
639/**
640 * Sb file production
641 */
642
451#define ROUND_UP(val, round) ((((val) + (round) - 1) / (round)) * (round)) 643#define ROUND_UP(val, round) ((((val) + (round) - 1) / (round)) * (round))
452 644
453static uint8_t instruction_checksum(struct sb_instruction_header_t *hdr) 645static uint8_t instruction_checksum(struct sb_instruction_header_t *hdr)
@@ -467,6 +659,7 @@ int main(int argc, const char **argv)
467 int nr_keys; 659 int nr_keys;
468 key_array_t key_array = read_keys(argv[2], &nr_keys); 660 key_array_t key_array = read_keys(argv[2], &nr_keys);
469 struct cmd_file_t *cmd_file = read_command_file(argv[1]); 661 struct cmd_file_t *cmd_file = read_command_file(argv[1]);
662 struct sb_file_t *sb_file = apply_cmd_file(cmd_file);
470 663
471 return 0; 664 return 0;
472} 665}