diff options
author | Amaury Pouly <pamaury@rockbox.org> | 2011-10-23 17:43:52 +0000 |
---|---|---|
committer | Amaury Pouly <pamaury@rockbox.org> | 2011-10-23 17:43:52 +0000 |
commit | b93e15c404cda96397ba2b98e49359a81d34c957 (patch) | |
tree | c01fa91dad56a1b51b4f448835de4465ab1cc265 /utils | |
parent | 94c573f3eca59347cd397d6b68159997bb674246 (diff) | |
download | rockbox-b93e15c404cda96397ba2b98e49359a81d34c957.tar.gz rockbox-b93e15c404cda96397ba2b98e49359a81d34c957.zip |
sbtools: fix sbtoelf to support NOP, add alignment support to elftosb
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30832 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'utils')
-rw-r--r-- | utils/sbtools/elftosb.c | 84 | ||||
-rw-r--r-- | utils/sbtools/sbtoelf.c | 20 |
2 files changed, 94 insertions, 10 deletions
diff --git a/utils/sbtools/elftosb.c b/utils/sbtools/elftosb.c index f78c6cf64b..986376179a 100644 --- a/utils/sbtools/elftosb.c +++ b/utils/sbtools/elftosb.c | |||
@@ -203,6 +203,7 @@ struct sb_section_t | |||
203 | uint32_t identifier; | 203 | uint32_t identifier; |
204 | bool is_data; | 204 | bool is_data; |
205 | bool is_cleartext; | 205 | bool is_cleartext; |
206 | uint32_t alignment; | ||
206 | // data sections are handled as a single SB_INST_DATA virtual instruction | 207 | // data sections are handled as a single SB_INST_DATA virtual instruction |
207 | int nr_insts; | 208 | int nr_insts; |
208 | struct sb_inst_t *insts; | 209 | struct sb_inst_t *insts; |
@@ -333,6 +334,7 @@ static struct sb_file_t *apply_cmd_file(struct cmd_file_t *cmd_file) | |||
333 | /* options */ | 334 | /* options */ |
334 | do | 335 | do |
335 | { | 336 | { |
337 | /* cleartext */ | ||
336 | struct cmd_option_t *opt = db_find_option_by_id(csec->opt_list, "cleartext"); | 338 | struct cmd_option_t *opt = db_find_option_by_id(csec->opt_list, "cleartext"); |
337 | if(opt != NULL) | 339 | if(opt != NULL) |
338 | { | 340 | { |
@@ -342,6 +344,23 @@ static struct sb_file_t *apply_cmd_file(struct cmd_file_t *cmd_file) | |||
342 | bug("Cleartext section attribute must be 0 or 1\n"); | 344 | bug("Cleartext section attribute must be 0 or 1\n"); |
343 | sec->is_cleartext = opt->val; | 345 | sec->is_cleartext = opt->val; |
344 | } | 346 | } |
347 | /* alignment */ | ||
348 | opt = db_find_option_by_id(csec->opt_list, "alignment"); | ||
349 | if(opt != NULL) | ||
350 | { | ||
351 | if(opt->is_string) | ||
352 | bug("Cleartext section attribute must be an integer\n"); | ||
353 | // n is a power of 2 iff n & (n - 1) = 0 | ||
354 | // alignement cannot be lower than block size | ||
355 | if((opt->val & (opt->val - 1)) != 0) | ||
356 | bug("Cleartext section attribute must be a power of two\n"); | ||
357 | if(opt->val < BLOCK_SIZE) | ||
358 | sec->alignment = BLOCK_SIZE; | ||
359 | else | ||
360 | sec->alignment = opt->val; | ||
361 | } | ||
362 | else | ||
363 | sec->alignment = BLOCK_SIZE; | ||
345 | }while(0); | 364 | }while(0); |
346 | 365 | ||
347 | if(csec->is_data) | 366 | if(csec->is_data) |
@@ -469,6 +488,16 @@ static struct sb_file_t *apply_cmd_file(struct cmd_file_t *cmd_file) | |||
469 | * SB file production | 488 | * SB file production |
470 | */ | 489 | */ |
471 | 490 | ||
491 | /* helper function to augment an array, free old array */ | ||
492 | void *augment_array(void *arr, size_t elem_sz, size_t cnt, void *aug, size_t aug_cnt) | ||
493 | { | ||
494 | void *p = xmalloc(elem_sz * (cnt + aug_cnt)); | ||
495 | memcpy(p, arr, elem_sz * cnt); | ||
496 | memcpy(p + elem_sz * cnt, aug, elem_sz * aug_cnt); | ||
497 | free(arr); | ||
498 | return p; | ||
499 | } | ||
500 | |||
472 | static void fill_gaps(struct sb_file_t *sb) | 501 | static void fill_gaps(struct sb_file_t *sb) |
473 | { | 502 | { |
474 | for(int i = 0; i < sb->nr_sections; i++) | 503 | for(int i = 0; i < sb->nr_sections; i++) |
@@ -501,6 +530,11 @@ static void compute_sb_offsets(struct sb_file_t *sb) | |||
501 | { | 530 | { |
502 | /* each section has a preliminary TAG command */ | 531 | /* each section has a preliminary TAG command */ |
503 | sb->image_size += sizeof(struct sb_instruction_tag_t) / BLOCK_SIZE; | 532 | sb->image_size += sizeof(struct sb_instruction_tag_t) / BLOCK_SIZE; |
533 | /* we might need to pad the section so compute next alignment */ | ||
534 | uint32_t alignment = BLOCK_SIZE; | ||
535 | if((i + 1) < sb->nr_sections) | ||
536 | alignment = sb->sections[i + 1].alignment; | ||
537 | alignment /= BLOCK_SIZE; /* alignment in block sizes */ | ||
504 | 538 | ||
505 | struct sb_section_t *sec = &sb->sections[i]; | 539 | struct sb_section_t *sec = &sb->sections[i]; |
506 | 540 | ||
@@ -561,6 +595,50 @@ static void compute_sb_offsets(struct sb_file_t *sb) | |||
561 | else | 595 | else |
562 | bug("die on inst %d\n", inst->inst); | 596 | bug("die on inst %d\n", inst->inst); |
563 | } | 597 | } |
598 | /* we need to make sure next section starts on the right alignment. | ||
599 | * Since each section starts with a boot tag, we thus need to ensure | ||
600 | * that this sections ends at adress X such that X+BLOCK_SIZE is | ||
601 | * a multiple of the alignment. | ||
602 | * For data sections, we just add random data, otherwise we add nops */ | ||
603 | uint32_t missing_sz = alignment - ((sb->image_size + 1) % alignment); | ||
604 | if(missing_sz != alignment) | ||
605 | { | ||
606 | struct sb_inst_t *aug_insts; | ||
607 | int nr_aug_insts = 0; | ||
608 | |||
609 | if(sb->sections[i].is_data) | ||
610 | { | ||
611 | nr_aug_insts = 1; | ||
612 | aug_insts = malloc(sizeof(struct sb_inst_t)); | ||
613 | memset(aug_insts, 0, sizeof(struct sb_inst_t)); | ||
614 | aug_insts[0].inst = SB_INST_DATA; | ||
615 | aug_insts[0].size = missing_sz * BLOCK_SIZE; | ||
616 | aug_insts[0].data = xmalloc(missing_sz * BLOCK_SIZE); | ||
617 | generate_random_data(aug_insts[0].data, missing_sz * BLOCK_SIZE); | ||
618 | if(g_debug) | ||
619 | printf(" DATA | size=0x%08x\n", aug_insts[0].size); | ||
620 | } | ||
621 | else | ||
622 | { | ||
623 | nr_aug_insts = missing_sz; | ||
624 | aug_insts = malloc(sizeof(struct sb_inst_t) * nr_aug_insts); | ||
625 | memset(aug_insts, 0, sizeof(struct sb_inst_t) * nr_aug_insts); | ||
626 | for(int j = 0; j < nr_aug_insts; j++) | ||
627 | { | ||
628 | aug_insts[j].inst = SB_INST_NOP; | ||
629 | if(g_debug) | ||
630 | printf(" NOOP\n"); | ||
631 | } | ||
632 | } | ||
633 | |||
634 | sb->sections[i].insts = augment_array(sb->sections[i].insts, sizeof(struct sb_inst_t), | ||
635 | sb->sections[i].nr_insts, aug_insts, nr_aug_insts); | ||
636 | sb->sections[i].nr_insts += nr_aug_insts; | ||
637 | |||
638 | /* augment image and section size */ | ||
639 | sb->image_size += missing_sz; | ||
640 | sec->sec_size += missing_sz; | ||
641 | } | ||
564 | } | 642 | } |
565 | /* final signature */ | 643 | /* final signature */ |
566 | sb->image_size += 2; | 644 | sb->image_size += 2; |
@@ -679,6 +757,8 @@ void produce_sb_instruction(struct sb_inst_t *inst, | |||
679 | case SB_INST_MODE: | 757 | case SB_INST_MODE: |
680 | cmd->data = inst->addr; | 758 | cmd->data = inst->addr; |
681 | break; | 759 | break; |
760 | case SB_INST_NOP: | ||
761 | break; | ||
682 | default: | 762 | default: |
683 | bug("die\n"); | 763 | bug("die\n"); |
684 | } | 764 | } |
@@ -799,11 +879,11 @@ void usage(void) | |||
799 | { | 879 | { |
800 | printf("Usage: elftosb [options | file]...\n"); | 880 | printf("Usage: elftosb [options | file]...\n"); |
801 | printf("Options:\n"); | 881 | printf("Options:\n"); |
802 | printf(" -?/--help:\t\tDisplay this message\n"); | 882 | printf(" -?/--help\tDisplay this message\n"); |
803 | printf(" -o <file>\tSet output file\n"); | 883 | printf(" -o <file>\tSet output file\n"); |
804 | printf(" -c <file>\tSet command file\n"); | 884 | printf(" -c <file>\tSet command file\n"); |
805 | printf(" -d/--debug\tEnable debug output\n"); | 885 | printf(" -d/--debug\tEnable debug output\n"); |
806 | printf(" -k <file>\t\tAdd key file\n"); | 886 | printf(" -k <file>\tAdd key file\n"); |
807 | printf(" -z\t\tAdd zero key\n"); | 887 | printf(" -z\t\tAdd zero key\n"); |
808 | exit(1); | 888 | exit(1); |
809 | } | 889 | } |
diff --git a/utils/sbtools/sbtoelf.c b/utils/sbtools/sbtoelf.c index 9a06eade79..4878c73faf 100644 --- a/utils/sbtools/sbtoelf.c +++ b/utils/sbtools/sbtoelf.c | |||
@@ -260,8 +260,6 @@ static void extract_section(int data_sec, char name[5], byte *buf, int size, con | |||
260 | &buf[pos + sizeof(struct sb_instruction_load_t)]); | 260 | &buf[pos + sizeof(struct sb_instruction_load_t)]); |
261 | 261 | ||
262 | pos += load->len + sizeof(struct sb_instruction_load_t); | 262 | pos += load->len + sizeof(struct sb_instruction_load_t); |
263 | // unsure about rounding | ||
264 | pos = ROUND_UP(pos, 16); | ||
265 | } | 263 | } |
266 | else if(hdr->opcode == SB_INST_FILL) | 264 | else if(hdr->opcode == SB_INST_FILL) |
267 | { | 265 | { |
@@ -283,8 +281,6 @@ static void extract_section(int data_sec, char name[5], byte *buf, int size, con | |||
283 | elf_add_fill_section(&elf, fill->addr, fill->len, fill->pattern); | 281 | elf_add_fill_section(&elf, fill->addr, fill->len, fill->pattern); |
284 | 282 | ||
285 | pos += sizeof(struct sb_instruction_fill_t); | 283 | pos += sizeof(struct sb_instruction_fill_t); |
286 | // fixme: useless as pos is a multiple of 16 and fill struct is 4-bytes wide ? | ||
287 | pos = ROUND_UP(pos, 16); | ||
288 | } | 284 | } |
289 | else if(hdr->opcode == SB_INST_CALL || | 285 | else if(hdr->opcode == SB_INST_CALL || |
290 | hdr->opcode == SB_INST_JUMP) | 286 | hdr->opcode == SB_INST_JUMP) |
@@ -311,8 +307,6 @@ static void extract_section(int data_sec, char name[5], byte *buf, int size, con | |||
311 | elf_init(&elf); | 307 | elf_init(&elf); |
312 | 308 | ||
313 | pos += sizeof(struct sb_instruction_call_t); | 309 | pos += sizeof(struct sb_instruction_call_t); |
314 | // fixme: useless as pos is a multiple of 16 and call struct is 4-bytes wide ? | ||
315 | pos = ROUND_UP(pos, 16); | ||
316 | } | 310 | } |
317 | else if(hdr->opcode == SB_INST_MODE) | 311 | else if(hdr->opcode == SB_INST_MODE) |
318 | { | 312 | { |
@@ -325,12 +319,20 @@ static void extract_section(int data_sec, char name[5], byte *buf, int size, con | |||
325 | color(OFF); | 319 | color(OFF); |
326 | pos += sizeof(struct sb_instruction_mode_t); | 320 | pos += sizeof(struct sb_instruction_mode_t); |
327 | } | 321 | } |
322 | else if(hdr->opcode == SB_INST_NOP) | ||
323 | { | ||
324 | color(RED); | ||
325 | printf("NOOP\n"); | ||
326 | pos += sizeof(struct sb_instruction_mode_t); | ||
327 | } | ||
328 | else | 328 | else |
329 | { | 329 | { |
330 | color(RED); | 330 | color(RED); |
331 | printf("Unknown instruction %d at address 0x%08lx\n", hdr->opcode, (unsigned long)pos); | 331 | printf("Unknown instruction %d at address 0x%08lx\n", hdr->opcode, (unsigned long)pos); |
332 | break; | 332 | break; |
333 | } | 333 | } |
334 | |||
335 | pos = ROUND_UP(pos, BLOCK_SIZE); | ||
334 | } | 336 | } |
335 | 337 | ||
336 | if(!elf_is_empty(&elf)) | 338 | if(!elf_is_empty(&elf)) |
@@ -609,7 +611,7 @@ static void extract(unsigned long filesize) | |||
609 | const char *indent = " "; | 611 | const char *indent = " "; |
610 | while(true) | 612 | while(true) |
611 | { | 613 | { |
612 | byte cmd[16]; | 614 | byte cmd[BLOCK_SIZE]; |
613 | if(sb_header->nr_keys > 0) | 615 | if(sb_header->nr_keys > 0) |
614 | cbc_mac(g_buf + offset, cmd, 1, real_key, iv, &iv, 0); | 616 | cbc_mac(g_buf + offset, cmd, 1, real_key, iv, &iv, 0); |
615 | else | 617 | else |
@@ -620,7 +622,7 @@ static void extract(unsigned long filesize) | |||
620 | if(checksum != hdr->checksum) | 622 | if(checksum != hdr->checksum) |
621 | { | 623 | { |
622 | color(GREY); | 624 | color(GREY); |
623 | printf("[Bad checksum]"); | 625 | printf("[Bad checksum']"); |
624 | } | 626 | } |
625 | 627 | ||
626 | if(hdr->opcode == SB_INST_NOP) | 628 | if(hdr->opcode == SB_INST_NOP) |
@@ -628,6 +630,8 @@ static void extract(unsigned long filesize) | |||
628 | color(RED); | 630 | color(RED); |
629 | printf("NOOP\n"); | 631 | printf("NOOP\n"); |
630 | offset += BLOCK_SIZE; | 632 | offset += BLOCK_SIZE; |
633 | /* restart with IV */ | ||
634 | memcpy(iv, g_buf, 16); | ||
631 | } | 635 | } |
632 | else if(hdr->opcode == SB_INST_TAG) | 636 | else if(hdr->opcode == SB_INST_TAG) |
633 | { | 637 | { |