diff options
Diffstat (limited to 'utils/sbtools/elftosb.c')
-rw-r--r-- | utils/sbtools/elftosb.c | 84 |
1 files changed, 82 insertions, 2 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 | } |