diff options
author | Amaury Pouly <pamaury@rockbox.org> | 2011-04-17 22:30:09 +0000 |
---|---|---|
committer | Amaury Pouly <pamaury@rockbox.org> | 2011-04-17 22:30:09 +0000 |
commit | b2c59541b47e98fe69ab973ca4ab2688d70aac23 (patch) | |
tree | bb2384b6c844ce9f77ccc2227920a053b5ee33cd /utils/sbtools/elftosb.c | |
parent | e3fe3956f6c9c244ccbc57d1ddce7b2202b373f4 (diff) | |
download | rockbox-b2c59541b47e98fe69ab973ca4ab2688d70aac23.tar.gz rockbox-b2c59541b47e98fe69ab973ca4ab2688d70aac23.zip |
sbtoelf: fix to handle unencrypted files (minor tweak)
elftosb: properly generate sb file (encryption not implemented yet)
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@29742 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'utils/sbtools/elftosb.c')
-rw-r--r-- | utils/sbtools/elftosb.c | 204 |
1 files changed, 192 insertions, 12 deletions
diff --git a/utils/sbtools/elftosb.c b/utils/sbtools/elftosb.c index 275f21724d..28717fddd9 100644 --- a/utils/sbtools/elftosb.c +++ b/utils/sbtools/elftosb.c | |||
@@ -42,10 +42,23 @@ | |||
42 | 42 | ||
43 | bool g_debug = false; | 43 | bool g_debug = false; |
44 | 44 | ||
45 | #define ROUND_UP(val, round) ((((val) + (round) - 1) / (round)) * (round)) | ||
46 | |||
45 | /** | 47 | /** |
46 | * Misc | 48 | * Misc |
47 | */ | 49 | */ |
48 | 50 | ||
51 | void generate_random_data(void *buf, size_t sz) | ||
52 | { | ||
53 | static int rand_fd = -1; | ||
54 | if(rand_fd == -1) | ||
55 | rand_fd = open("/dev/urandom", O_RDONLY); | ||
56 | if(rand_fd == -1) | ||
57 | bugp("failed to open /dev/urandom"); | ||
58 | if(read(rand_fd, buf, sz) != (ssize_t)sz) | ||
59 | bugp("failed to read /dev/urandom"); | ||
60 | } | ||
61 | |||
49 | void *xmalloc(size_t s) /* malloc helper, used in elf.c */ | 62 | void *xmalloc(size_t s) /* malloc helper, used in elf.c */ |
50 | { | 63 | { |
51 | void * r = malloc(s); | 64 | void * r = malloc(s); |
@@ -316,6 +329,7 @@ static void next_lexem(char **ptr, char *end, struct lexem_t *lexem) | |||
316 | #undef ret_simple | 329 | #undef ret_simple |
317 | } | 330 | } |
318 | 331 | ||
332 | #if 0 | ||
319 | static void log_lexem(struct lexem_t *lexem) | 333 | static void log_lexem(struct lexem_t *lexem) |
320 | { | 334 | { |
321 | switch(lexem->type) | 335 | switch(lexem->type) |
@@ -333,6 +347,7 @@ static void log_lexem(struct lexem_t *lexem) | |||
333 | default: printf("<unk>"); | 347 | default: printf("<unk>"); |
334 | } | 348 | } |
335 | } | 349 | } |
350 | #endif | ||
336 | 351 | ||
337 | static struct cmd_source_t *find_source_by_id(struct cmd_file_t *cmd_file, const char *id) | 352 | static struct cmd_source_t *find_source_by_id(struct cmd_file_t *cmd_file, const char *id) |
338 | { | 353 | { |
@@ -495,6 +510,9 @@ struct sb_inst_t | |||
495 | uint32_t pattern; | 510 | uint32_t pattern; |
496 | uint32_t addr; | 511 | uint32_t addr; |
497 | // </union> | 512 | // </union> |
513 | /* for production use */ | ||
514 | uint32_t padding_size; | ||
515 | uint8_t *padding; | ||
498 | }; | 516 | }; |
499 | 517 | ||
500 | struct sb_section_t | 518 | struct sb_section_t |
@@ -504,6 +522,7 @@ struct sb_section_t | |||
504 | struct sb_inst_t *insts; | 522 | struct sb_inst_t *insts; |
505 | /* for production use */ | 523 | /* for production use */ |
506 | uint32_t file_offset; /* in blocks */ | 524 | uint32_t file_offset; /* in blocks */ |
525 | uint32_t sec_size; /* in blocks */ | ||
507 | }; | 526 | }; |
508 | 527 | ||
509 | struct sb_file_t | 528 | struct sb_file_t |
@@ -637,6 +656,24 @@ static struct sb_file_t *apply_cmd_file(struct cmd_file_t *cmd_file) | |||
637 | * Sb file production | 656 | * Sb file production |
638 | */ | 657 | */ |
639 | 658 | ||
659 | static void fill_gaps(struct sb_file_t *sb) | ||
660 | { | ||
661 | for(int i = 0; i < sb->nr_sections; i++) | ||
662 | { | ||
663 | struct sb_section_t *sec = &sb->sections[i]; | ||
664 | for(int j = 0; j < sec->nr_insts; j++) | ||
665 | { | ||
666 | struct sb_inst_t *inst = &sec->insts[j]; | ||
667 | if(inst->inst != SB_INST_LOAD) | ||
668 | continue; | ||
669 | inst->padding_size = ROUND_UP(inst->size, BLOCK_SIZE) - inst->size; | ||
670 | /* emulate elftosb2 behaviour: generate 15 bytes (that's a safe maximum) */ | ||
671 | inst->padding = xmalloc(15); | ||
672 | generate_random_data(inst->padding, 15); | ||
673 | } | ||
674 | } | ||
675 | } | ||
676 | |||
640 | static void compute_sb_offsets(struct sb_file_t *sb) | 677 | static void compute_sb_offsets(struct sb_file_t *sb) |
641 | { | 678 | { |
642 | sb->image_size = 0; | 679 | sb->image_size = 0; |
@@ -663,6 +700,7 @@ static void compute_sb_offsets(struct sb_file_t *sb) | |||
663 | printf("%s | addr=0x%08x | arg=0x%08x\n", | 700 | printf("%s | addr=0x%08x | arg=0x%08x\n", |
664 | inst->inst == SB_INST_CALL ? "CALL" : "JUMP", inst->addr, 0); | 701 | inst->inst == SB_INST_CALL ? "CALL" : "JUMP", inst->addr, 0); |
665 | sb->image_size += sizeof(struct sb_instruction_call_t) / BLOCK_SIZE; | 702 | sb->image_size += sizeof(struct sb_instruction_call_t) / BLOCK_SIZE; |
703 | sec->sec_size += sizeof(struct sb_instruction_call_t) / BLOCK_SIZE; | ||
666 | } | 704 | } |
667 | else if(inst->inst == SB_INST_FILL) | 705 | else if(inst->inst == SB_INST_FILL) |
668 | { | 706 | { |
@@ -670,6 +708,7 @@ static void compute_sb_offsets(struct sb_file_t *sb) | |||
670 | printf("FILL | addr=0x%08x | len=0x%08x | pattern=0x%08x\n", | 708 | printf("FILL | addr=0x%08x | len=0x%08x | pattern=0x%08x\n", |
671 | inst->addr, inst->size, inst->pattern); | 709 | inst->addr, inst->size, inst->pattern); |
672 | sb->image_size += sizeof(struct sb_instruction_fill_t) / BLOCK_SIZE; | 710 | sb->image_size += sizeof(struct sb_instruction_fill_t) / BLOCK_SIZE; |
711 | sec->sec_size += sizeof(struct sb_instruction_fill_t) / BLOCK_SIZE; | ||
673 | } | 712 | } |
674 | else if(inst->inst == SB_INST_LOAD) | 713 | else if(inst->inst == SB_INST_LOAD) |
675 | { | 714 | { |
@@ -677,8 +716,10 @@ static void compute_sb_offsets(struct sb_file_t *sb) | |||
677 | printf("LOAD | addr=0x%08x | len=0x%08x\n", inst->addr, inst->size); | 716 | printf("LOAD | addr=0x%08x | len=0x%08x\n", inst->addr, inst->size); |
678 | /* load header */ | 717 | /* load header */ |
679 | sb->image_size += sizeof(struct sb_instruction_load_t) / BLOCK_SIZE; | 718 | sb->image_size += sizeof(struct sb_instruction_load_t) / BLOCK_SIZE; |
719 | sec->sec_size += sizeof(struct sb_instruction_load_t) / BLOCK_SIZE; | ||
680 | /* data + alignment */ | 720 | /* data + alignment */ |
681 | sb->image_size += (inst->size + BLOCK_SIZE - 1) / BLOCK_SIZE; | 721 | sb->image_size += (inst->size + inst->padding_size) / BLOCK_SIZE; |
722 | sec->sec_size += (inst->size + inst->padding_size) / BLOCK_SIZE; | ||
682 | } | 723 | } |
683 | } | 724 | } |
684 | } | 725 | } |
@@ -686,8 +727,27 @@ static void compute_sb_offsets(struct sb_file_t *sb) | |||
686 | sb->image_size += 2; | 727 | sb->image_size += 2; |
687 | } | 728 | } |
688 | 729 | ||
730 | static uint64_t generate_timestamp() | ||
731 | { | ||
732 | struct tm tm_base = {0, 0, 0, 1, 0, 100, 0, 0, 1, 0, NULL}; /* 2000/1/1 0:00:00 */ | ||
733 | time_t t = time(NULL) - mktime(&tm_base); | ||
734 | return (uint64_t)t * 1000000L; | ||
735 | } | ||
736 | |||
737 | void generate_version(struct sb_version_t *ver) | ||
738 | { | ||
739 | ver->major = 0x999; | ||
740 | ver->pad0 = 0; | ||
741 | ver->minor = 0x999; | ||
742 | ver->pad1 = 0; | ||
743 | ver->revision = 0x999; | ||
744 | ver->pad2 = 0; | ||
745 | } | ||
746 | |||
689 | static void produce_sb_header(struct sb_file_t *sb, struct sb_header_t *sb_hdr) | 747 | static void produce_sb_header(struct sb_file_t *sb, struct sb_header_t *sb_hdr) |
690 | { | 748 | { |
749 | struct sha_1_params_t sha_1_params; | ||
750 | |||
691 | sb_hdr->signature[0] = 'S'; | 751 | sb_hdr->signature[0] = 'S'; |
692 | sb_hdr->signature[1] = 'T'; | 752 | sb_hdr->signature[1] = 'T'; |
693 | sb_hdr->signature[2] = 'M'; | 753 | sb_hdr->signature[2] = 'M'; |
@@ -696,6 +756,83 @@ static void produce_sb_header(struct sb_file_t *sb, struct sb_header_t *sb_hdr) | |||
696 | sb_hdr->minor_ver = IMAGE_MINOR_VERSION; | 756 | sb_hdr->minor_ver = IMAGE_MINOR_VERSION; |
697 | sb_hdr->flags = 0; | 757 | sb_hdr->flags = 0; |
698 | sb_hdr->image_size = sb->image_size; | 758 | sb_hdr->image_size = sb->image_size; |
759 | sb_hdr->header_size = sizeof(struct sb_header_t) / BLOCK_SIZE; | ||
760 | sb_hdr->first_boot_sec_id = sb->sections[0].identifier; | ||
761 | sb_hdr->nr_keys = g_nr_keys; | ||
762 | sb_hdr->nr_sections = sb->nr_sections; | ||
763 | sb_hdr->sec_hdr_size = sizeof(struct sb_section_header_t) / BLOCK_SIZE; | ||
764 | sb_hdr->key_dict_off = sb_hdr->header_size + | ||
765 | sb_hdr->sec_hdr_size * sb_hdr->nr_sections; | ||
766 | sb_hdr->first_boot_tag_off = sb_hdr->key_dict_off + | ||
767 | sizeof(struct sb_key_dictionary_entry_t) * sb_hdr->nr_keys / BLOCK_SIZE; | ||
768 | generate_random_data(sb_hdr->rand_pad0, sizeof(sb_hdr->rand_pad0)); | ||
769 | generate_random_data(sb_hdr->rand_pad1, sizeof(sb_hdr->rand_pad1)); | ||
770 | sb_hdr->timestamp = generate_timestamp(); | ||
771 | generate_version(&sb_hdr->product_ver); | ||
772 | generate_version(&sb_hdr->component_ver); | ||
773 | sb_hdr->drive_tag = 0; | ||
774 | |||
775 | sha_1_init(&sha_1_params); | ||
776 | sha_1_update(&sha_1_params, &sb_hdr->signature[0], | ||
777 | sizeof(struct sb_header_t) - sizeof(sb_hdr->sha1_header)); | ||
778 | sha_1_finish(&sha_1_params); | ||
779 | sha_1_output(&sha_1_params, sb_hdr->sha1_header); | ||
780 | } | ||
781 | |||
782 | static void produce_sb_section_header(struct sb_section_t *sec, | ||
783 | struct sb_section_header_t *sec_hdr) | ||
784 | { | ||
785 | sec_hdr->identifier = sec->identifier; | ||
786 | sec_hdr->offset = sec->file_offset; | ||
787 | sec_hdr->size = sec->sec_size; | ||
788 | sec_hdr->flags = SECTION_BOOTABLE; | ||
789 | } | ||
790 | |||
791 | static uint8_t instruction_checksum(struct sb_instruction_header_t *hdr) | ||
792 | { | ||
793 | uint8_t sum = 90; | ||
794 | byte *ptr = (byte *)hdr; | ||
795 | for(int i = 1; i < 16; i++) | ||
796 | sum += ptr[i]; | ||
797 | return sum; | ||
798 | } | ||
799 | |||
800 | static void produce_section_tag_cmd(struct sb_section_t *sec, | ||
801 | struct sb_instruction_tag_t *tag, bool is_last) | ||
802 | { | ||
803 | tag->hdr.opcode = SB_INST_TAG; | ||
804 | tag->hdr.flags = is_last ? SB_INST_LAST_TAG : 0; | ||
805 | tag->identifier = sec->identifier; | ||
806 | tag->len = sec->sec_size; | ||
807 | tag->flags = SECTION_BOOTABLE; | ||
808 | tag->hdr.checksum = instruction_checksum(&tag->hdr); | ||
809 | } | ||
810 | |||
811 | void produce_sb_instruction(struct sb_inst_t *inst, | ||
812 | struct sb_instruction_common_t *cmd) | ||
813 | { | ||
814 | cmd->hdr.flags = 0; | ||
815 | cmd->hdr.opcode = inst->inst; | ||
816 | cmd->addr = inst->addr; | ||
817 | cmd->len = inst->size; | ||
818 | switch(inst->inst) | ||
819 | { | ||
820 | case SB_INST_CALL: | ||
821 | case SB_INST_JUMP: | ||
822 | cmd->len = 0; | ||
823 | cmd->data = 0; | ||
824 | break; | ||
825 | case SB_INST_FILL: | ||
826 | cmd->data = inst->pattern; | ||
827 | break; | ||
828 | case SB_INST_LOAD: | ||
829 | cmd->data = crc_continue(crc(inst->data, inst->size), | ||
830 | inst->padding, inst->padding_size); | ||
831 | break; | ||
832 | default: | ||
833 | break; | ||
834 | } | ||
835 | cmd->hdr.checksum = instruction_checksum(&cmd->hdr); | ||
699 | } | 836 | } |
700 | 837 | ||
701 | static void produce_sb_file(struct sb_file_t *sb, const char *filename) | 838 | static void produce_sb_file(struct sb_file_t *sb, const char *filename) |
@@ -705,25 +842,68 @@ static void produce_sb_file(struct sb_file_t *sb, const char *filename) | |||
705 | if(fd < 0) | 842 | if(fd < 0) |
706 | bugp("cannot open output file"); | 843 | bugp("cannot open output file"); |
707 | 844 | ||
845 | byte real_key[16]; | ||
846 | |||
847 | fill_gaps(sb); | ||
708 | compute_sb_offsets(sb); | 848 | compute_sb_offsets(sb); |
709 | 849 | ||
850 | generate_random_data(real_key, sizeof(real_key)); | ||
851 | |||
852 | /* global SHA-1 */ | ||
853 | struct sha_1_params_t file_sha1; | ||
854 | sha_1_init(&file_sha1); | ||
855 | /* produce and write header */ | ||
710 | struct sb_header_t sb_hdr; | 856 | struct sb_header_t sb_hdr; |
711 | produce_sb_header(sb, &sb_hdr); | 857 | produce_sb_header(sb, &sb_hdr); |
858 | sha_1_update(&file_sha1, (byte *)&sb_hdr, sizeof(sb_hdr)); | ||
859 | write(fd, &sb_hdr, sizeof(sb_hdr)); | ||
860 | |||
861 | /* produce and write section headers */ | ||
862 | for(int i = 0; i < sb_hdr.nr_sections; i++) | ||
863 | { | ||
864 | struct sb_section_header_t sb_sec_hdr; | ||
865 | produce_sb_section_header(&sb->sections[i], &sb_sec_hdr); | ||
866 | sha_1_update(&file_sha1, (byte *)&sb_sec_hdr, sizeof(sb_sec_hdr)); | ||
867 | write(fd, &sb_sec_hdr, sizeof(sb_sec_hdr)); | ||
868 | } | ||
869 | /* produce key dictionary */ | ||
870 | /* produce sections data */ | ||
871 | for(int i = 0; i< sb_hdr.nr_sections; i++) | ||
872 | { | ||
873 | /* produce tag command */ | ||
874 | struct sb_instruction_tag_t tag_cmd; | ||
875 | produce_section_tag_cmd(&sb->sections[i], &tag_cmd, (i + 1) == sb_hdr.nr_sections); | ||
876 | sha_1_update(&file_sha1, (byte *)&tag_cmd, sizeof(tag_cmd)); | ||
877 | write(fd, &tag_cmd, sizeof(tag_cmd)); | ||
878 | /* produce other commands */ | ||
879 | for(int j = 0; j < sb->sections[i].nr_insts; j++) | ||
880 | { | ||
881 | struct sb_inst_t *inst = &sb->sections[i].insts[j]; | ||
882 | /* command */ | ||
883 | struct sb_instruction_common_t cmd; | ||
884 | produce_sb_instruction(inst, &cmd); | ||
885 | sha_1_update(&file_sha1, (byte *)&cmd, sizeof(cmd)); | ||
886 | write(fd, &cmd, sizeof(cmd)); | ||
887 | /* data */ | ||
888 | if(inst->inst == SB_INST_LOAD) | ||
889 | { | ||
890 | sha_1_update(&file_sha1, inst->data, inst->size); | ||
891 | write(fd, inst->data, inst->size); | ||
892 | sha_1_update(&file_sha1, inst->padding, inst->padding_size); | ||
893 | write(fd, inst->padding, inst->padding_size); | ||
894 | } | ||
895 | } | ||
896 | } | ||
897 | /* write file SHA-1 */ | ||
898 | byte final_sig[32]; | ||
899 | sha_1_finish(&file_sha1); | ||
900 | sha_1_output(&file_sha1, final_sig); | ||
901 | generate_random_data(final_sig + 20, 12); | ||
902 | write(fd, final_sig, 32); | ||
712 | 903 | ||
713 | close(fd); | 904 | close(fd); |
714 | } | 905 | } |
715 | 906 | ||
716 | #define ROUND_UP(val, round) ((((val) + (round) - 1) / (round)) * (round)) | ||
717 | |||
718 | static uint8_t instruction_checksum(struct sb_instruction_header_t *hdr) | ||
719 | { | ||
720 | uint8_t sum = 90; | ||
721 | byte *ptr = (byte *)hdr; | ||
722 | for(int i = 1; i < 16; i++) | ||
723 | sum += ptr[i]; | ||
724 | return sum; | ||
725 | } | ||
726 | |||
727 | int main(int argc, const char **argv) | 907 | int main(int argc, const char **argv) |
728 | { | 908 | { |
729 | if(argc != 4) | 909 | if(argc != 4) |