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.c204
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
43bool g_debug = false; 43bool 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
51void 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
49void *xmalloc(size_t s) /* malloc helper, used in elf.c */ 62void *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
319static void log_lexem(struct lexem_t *lexem) 333static 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
337static struct cmd_source_t *find_source_by_id(struct cmd_file_t *cmd_file, const char *id) 352static 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
500struct sb_section_t 518struct 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
509struct sb_file_t 528struct 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
659static 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
640static void compute_sb_offsets(struct sb_file_t *sb) 677static 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
730static 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
737void 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
689static void produce_sb_header(struct sb_file_t *sb, struct sb_header_t *sb_hdr) 747static 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
782static 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
791static 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
800static 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
811void 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
701static void produce_sb_file(struct sb_file_t *sb, const char *filename) 838static 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
718static 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
727int main(int argc, const char **argv) 907int main(int argc, const char **argv)
728{ 908{
729 if(argc != 4) 909 if(argc != 4)