diff options
author | Amaury Pouly <pamaury@rockbox.org> | 2011-04-17 18:37:30 +0000 |
---|---|---|
committer | Amaury Pouly <pamaury@rockbox.org> | 2011-04-17 18:37:30 +0000 |
commit | e3fe3956f6c9c244ccbc57d1ddce7b2202b373f4 (patch) | |
tree | d7ce4f48d839157888f6f1ce7084e39473e60117 /utils/sbtools/elftosb.c | |
parent | 8bff25945bfceaeace132998aa98f6d1022aa3e9 (diff) | |
download | rockbox-e3fe3956f6c9c244ccbc57d1ddce7b2202b373f4.tar.gz rockbox-e3fe3956f6c9c244ccbc57d1ddce7b2202b373f4.zip |
elftosb: more code toward sb production
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@29741 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'utils/sbtools/elftosb.c')
-rw-r--r-- | utils/sbtools/elftosb.c | 110 |
1 files changed, 95 insertions, 15 deletions
diff --git a/utils/sbtools/elftosb.c b/utils/sbtools/elftosb.c index c4887ab47a..275f21724d 100644 --- a/utils/sbtools/elftosb.c +++ b/utils/sbtools/elftosb.c | |||
@@ -80,6 +80,9 @@ static int convxdigit(char digit, byte *val) | |||
80 | 80 | ||
81 | typedef byte (*key_array_t)[16]; | 81 | typedef byte (*key_array_t)[16]; |
82 | 82 | ||
83 | int g_nr_keys; | ||
84 | key_array_t g_key_array; | ||
85 | |||
83 | static key_array_t read_keys(const char *key_file, int *num_keys) | 86 | static key_array_t read_keys(const char *key_file, int *num_keys) |
84 | { | 87 | { |
85 | int size; | 88 | int size; |
@@ -499,12 +502,16 @@ struct sb_section_t | |||
499 | uint32_t identifier; | 502 | uint32_t identifier; |
500 | int nr_insts; | 503 | int nr_insts; |
501 | struct sb_inst_t *insts; | 504 | struct sb_inst_t *insts; |
505 | /* for production use */ | ||
506 | uint32_t file_offset; /* in blocks */ | ||
502 | }; | 507 | }; |
503 | 508 | ||
504 | struct sb_file_t | 509 | struct sb_file_t |
505 | { | 510 | { |
506 | int nr_sections; | 511 | int nr_sections; |
507 | struct sb_section_t *sections; | 512 | struct sb_section_t *sections; |
513 | /* for production use */ | ||
514 | uint32_t image_size; /* in blocks */ | ||
508 | }; | 515 | }; |
509 | 516 | ||
510 | static bool elf_read(void *user, uint32_t addr, void *buf, size_t count) | 517 | static bool elf_read(void *user, uint32_t addr, void *buf, size_t count) |
@@ -572,7 +579,7 @@ static struct sb_file_t *apply_cmd_file(struct cmd_file_t *cmd_file) | |||
572 | 579 | ||
573 | if(cinst->type == CMD_LOAD) | 580 | if(cinst->type == CMD_LOAD) |
574 | sec->nr_insts += elf_get_nr_sections(elf); | 581 | sec->nr_insts += elf_get_nr_sections(elf); |
575 | else if(cinst->type == CMD_JUMP || cinst->type == CMD_LOAD) | 582 | else if(cinst->type == CMD_JUMP || cinst->type == CMD_CALL) |
576 | { | 583 | { |
577 | if(!elf_get_start_addr(elf, NULL)) | 584 | if(!elf_get_start_addr(elf, NULL)) |
578 | bug("cannot jump/call '%s' because it has no starting point !", cinst->identifier); | 585 | bug("cannot jump/call '%s' because it has no starting point !", cinst->identifier); |
@@ -602,9 +609,6 @@ static struct sb_file_t *apply_cmd_file(struct cmd_file_t *cmd_file) | |||
602 | sec->insts[idx].addr = esec->addr; | 609 | sec->insts[idx].addr = esec->addr; |
603 | sec->insts[idx].size = esec->size; | 610 | sec->insts[idx].size = esec->size; |
604 | sec->insts[idx++].data = esec->section; | 611 | 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 | } | 612 | } |
609 | else if(esec->type == EST_FILL) | 613 | else if(esec->type == EST_FILL) |
610 | { | 614 | { |
@@ -612,21 +616,14 @@ static struct sb_file_t *apply_cmd_file(struct cmd_file_t *cmd_file) | |||
612 | sec->insts[idx].addr = esec->addr; | 616 | sec->insts[idx].addr = esec->addr; |
613 | sec->insts[idx].size = esec->size; | 617 | sec->insts[idx].size = esec->size; |
614 | sec->insts[idx++].pattern = esec->pattern; | 618 | 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 | } |
619 | esec = esec->next; | 620 | esec = esec->next; |
620 | } | 621 | } |
621 | } | 622 | } |
622 | else if(cinst->type == CMD_JUMP || cinst->type == CMD_LOAD) | 623 | else if(cinst->type == CMD_JUMP || cinst->type == CMD_CALL) |
623 | { | 624 | { |
624 | sec->insts[idx].inst = (cinst->type == CMD_JUMP) ? SB_INST_JUMP : SB_INST_CALL; | 625 | sec->insts[idx].inst = (cinst->type == CMD_JUMP) ? SB_INST_JUMP : SB_INST_CALL; |
625 | sec->insts[idx++].addr = elf->start_addr; | 626 | 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 | } | 627 | } |
631 | 628 | ||
632 | cinst = cinst->next; | 629 | cinst = cinst->next; |
@@ -640,6 +637,82 @@ static struct sb_file_t *apply_cmd_file(struct cmd_file_t *cmd_file) | |||
640 | * Sb file production | 637 | * Sb file production |
641 | */ | 638 | */ |
642 | 639 | ||
640 | static void compute_sb_offsets(struct sb_file_t *sb) | ||
641 | { | ||
642 | sb->image_size = 0; | ||
643 | /* sb header */ | ||
644 | sb->image_size += sizeof(struct sb_header_t) / BLOCK_SIZE; | ||
645 | /* sections headers */ | ||
646 | sb->image_size += sb->nr_sections * sizeof(struct sb_section_header_t) / BLOCK_SIZE; | ||
647 | /* key dictionary */ | ||
648 | sb->image_size += g_nr_keys * sizeof(struct sb_key_dictionary_entry_t) / BLOCK_SIZE; | ||
649 | /* sections */ | ||
650 | for(int i = 0; i < sb->nr_sections; i++) | ||
651 | { | ||
652 | /* each section has a preliminary TAG command */ | ||
653 | sb->image_size += sizeof(struct sb_instruction_tag_t) / BLOCK_SIZE; | ||
654 | |||
655 | struct sb_section_t *sec = &sb->sections[i]; | ||
656 | sec->file_offset = sb->image_size; | ||
657 | for(int j = 0; j < sec->nr_insts; j++) | ||
658 | { | ||
659 | struct sb_inst_t *inst = &sec->insts[j]; | ||
660 | if(inst->inst == SB_INST_CALL || inst->inst == SB_INST_JUMP) | ||
661 | { | ||
662 | if(g_debug) | ||
663 | printf("%s | addr=0x%08x | arg=0x%08x\n", | ||
664 | inst->inst == SB_INST_CALL ? "CALL" : "JUMP", inst->addr, 0); | ||
665 | sb->image_size += sizeof(struct sb_instruction_call_t) / BLOCK_SIZE; | ||
666 | } | ||
667 | else if(inst->inst == SB_INST_FILL) | ||
668 | { | ||
669 | if(g_debug) | ||
670 | printf("FILL | addr=0x%08x | len=0x%08x | pattern=0x%08x\n", | ||
671 | inst->addr, inst->size, inst->pattern); | ||
672 | sb->image_size += sizeof(struct sb_instruction_fill_t) / BLOCK_SIZE; | ||
673 | } | ||
674 | else if(inst->inst == SB_INST_LOAD) | ||
675 | { | ||
676 | if(g_debug) | ||
677 | printf("LOAD | addr=0x%08x | len=0x%08x\n", inst->addr, inst->size); | ||
678 | /* load header */ | ||
679 | sb->image_size += sizeof(struct sb_instruction_load_t) / BLOCK_SIZE; | ||
680 | /* data + alignment */ | ||
681 | sb->image_size += (inst->size + BLOCK_SIZE - 1) / BLOCK_SIZE; | ||
682 | } | ||
683 | } | ||
684 | } | ||
685 | /* final signature */ | ||
686 | sb->image_size += 2; | ||
687 | } | ||
688 | |||
689 | static void produce_sb_header(struct sb_file_t *sb, struct sb_header_t *sb_hdr) | ||
690 | { | ||
691 | sb_hdr->signature[0] = 'S'; | ||
692 | sb_hdr->signature[1] = 'T'; | ||
693 | sb_hdr->signature[2] = 'M'; | ||
694 | sb_hdr->signature[3] = 'P'; | ||
695 | sb_hdr->major_ver = IMAGE_MAJOR_VERSION; | ||
696 | sb_hdr->minor_ver = IMAGE_MINOR_VERSION; | ||
697 | sb_hdr->flags = 0; | ||
698 | sb_hdr->image_size = sb->image_size; | ||
699 | } | ||
700 | |||
701 | static void produce_sb_file(struct sb_file_t *sb, const char *filename) | ||
702 | { | ||
703 | int fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, | ||
704 | S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); | ||
705 | if(fd < 0) | ||
706 | bugp("cannot open output file"); | ||
707 | |||
708 | compute_sb_offsets(sb); | ||
709 | |||
710 | struct sb_header_t sb_hdr; | ||
711 | produce_sb_header(sb, &sb_hdr); | ||
712 | |||
713 | close(fd); | ||
714 | } | ||
715 | |||
643 | #define ROUND_UP(val, round) ((((val) + (round) - 1) / (round)) * (round)) | 716 | #define ROUND_UP(val, round) ((((val) + (round) - 1) / (round)) * (round)) |
644 | 717 | ||
645 | static uint8_t instruction_checksum(struct sb_instruction_header_t *hdr) | 718 | static uint8_t instruction_checksum(struct sb_instruction_header_t *hdr) |
@@ -654,12 +727,19 @@ static uint8_t instruction_checksum(struct sb_instruction_header_t *hdr) | |||
654 | int main(int argc, const char **argv) | 727 | int main(int argc, const char **argv) |
655 | { | 728 | { |
656 | if(argc != 4) | 729 | if(argc != 4) |
657 | bug("Usage: %s <cmd file> <key file> <out file>\n",*argv); | 730 | { |
731 | printf("Usage: %s <cmd file> <key file> <out file>\n",*argv); | ||
732 | printf("To enable debug mode, set environement variable SB_DEBUG to YES\n"); | ||
733 | return 1; | ||
734 | } | ||
735 | |||
736 | if(getenv("SB_DEBUG") != NULL && strcmp(getenv("SB_DEBUG"), "YES") == 0) | ||
737 | g_debug = true; | ||
658 | 738 | ||
659 | int nr_keys; | 739 | g_key_array = read_keys(argv[2], &g_nr_keys); |
660 | key_array_t key_array = read_keys(argv[2], &nr_keys); | ||
661 | struct cmd_file_t *cmd_file = read_command_file(argv[1]); | 740 | struct cmd_file_t *cmd_file = read_command_file(argv[1]); |
662 | struct sb_file_t *sb_file = apply_cmd_file(cmd_file); | 741 | struct sb_file_t *sb_file = apply_cmd_file(cmd_file); |
742 | produce_sb_file(sb_file, argv[3]); | ||
663 | 743 | ||
664 | return 0; | 744 | return 0; |
665 | } | 745 | } |