diff options
Diffstat (limited to 'utils')
-rw-r--r-- | utils/rknanoutils/rkboottool/rkboottool.c | 141 |
1 files changed, 107 insertions, 34 deletions
diff --git a/utils/rknanoutils/rkboottool/rkboottool.c b/utils/rknanoutils/rkboottool/rkboottool.c index bfa7ebe291..d131d9701c 100644 --- a/utils/rknanoutils/rkboottool/rkboottool.c +++ b/utils/rknanoutils/rkboottool/rkboottool.c | |||
@@ -284,7 +284,7 @@ struct rknano_stage_header_t | |||
284 | 284 | ||
285 | /* | 285 | /* |
286 | * The [code_pa,code_pa+code_sz[ and [data_pa,data_pa+data_sz[ ranges | 286 | * The [code_pa,code_pa+code_sz[ and [data_pa,data_pa+data_sz[ ranges |
287 | * are consitent: they never overlap and have no gaps and fill the | 287 | * are consistent: they never overlap and have no gaps and fill the |
288 | * entire space. Furthermore they match the code sequences so it's | 288 | * entire space. Furthermore they match the code sequences so it's |
289 | * reasonable to assume these fields are correct. | 289 | * reasonable to assume these fields are correct. |
290 | * The other fields are still quite unsure. */ | 290 | * The other fields are still quite unsure. */ |
@@ -411,12 +411,16 @@ struct rknano_boot_desc_t | |||
411 | struct rknano_boot_header_t | 411 | struct rknano_boot_header_t |
412 | { | 412 | { |
413 | char magic[MAGIC_BOOT_SIZE]; | 413 | char magic[MAGIC_BOOT_SIZE]; |
414 | uint16_t field_4; | 414 | uint16_t hdr_size; |
415 | uint32_t field_6; | 415 | uint32_t version; |
416 | uint32_t field_A; | 416 | uint32_t unk; |
417 | uint16_t field_E; | 417 | uint16_t year; |
418 | uint8_t field_10[5]; | 418 | uint8_t month; |
419 | uint32_t field_15; | 419 | uint8_t day; |
420 | uint8_t hour; | ||
421 | uint8_t minute; | ||
422 | uint8_t second; | ||
423 | uint32_t chip; | ||
420 | struct rknano_boot_desc_t desc_1; | 424 | struct rknano_boot_desc_t desc_1; |
421 | struct rknano_boot_desc_t desc_2; | 425 | struct rknano_boot_desc_t desc_2; |
422 | struct rknano_boot_desc_t desc_4; | 426 | struct rknano_boot_desc_t desc_4; |
@@ -564,8 +568,6 @@ static int do_boot_desc(uint8_t *buf, unsigned long size, | |||
564 | 568 | ||
565 | static int do_boot_image(uint8_t *buf, unsigned long size) | 569 | static int do_boot_image(uint8_t *buf, unsigned long size) |
566 | { | 570 | { |
567 | if(sizeof(struct rknano_boot_header_t) != 0x38) | ||
568 | printf("aie"); | ||
569 | if(size < sizeof(struct rknano_boot_header_t)) | 571 | if(size < sizeof(struct rknano_boot_header_t)) |
570 | return 1; | 572 | return 1; |
571 | struct rknano_boot_header_t *hdr = (void *)buf; | 573 | struct rknano_boot_header_t *hdr = (void *)buf; |
@@ -579,16 +581,29 @@ static int do_boot_image(uint8_t *buf, unsigned long size) | |||
579 | cprintf(RED, "OK\n"); | 581 | cprintf(RED, "OK\n"); |
580 | else | 582 | else |
581 | cprintf(RED, "Mismatch\n"); | 583 | cprintf(RED, "Mismatch\n"); |
584 | |||
585 | cprintf(GREEN, " Header Size: "); | ||
586 | cprintf(YELLOW, "%#x ", hdr->hdr_size); | ||
587 | if(hdr->hdr_size >= sizeof(struct rknano_boot_header_t)) | ||
588 | cprintf(RED, "OK\n"); | ||
589 | else | ||
590 | cprintf(RED, "Mismatch\n"); | ||
591 | |||
582 | #define print(str, name) cprintf(GREEN, " "str": ");cprintf(YELLOW, "%#x\n", (unsigned)hdr->name) | 592 | #define print(str, name) cprintf(GREEN, " "str": ");cprintf(YELLOW, "%#x\n", (unsigned)hdr->name) |
583 | #define print_arr(str, name, sz) \ | 593 | #define print_arr(str, name, sz) \ |
584 | cprintf(GREEN, " "str":");for(int i = 0; i < sz; i++)cprintf(YELLOW, " %#x", (unsigned)hdr->name[i]);printf("\n") | 594 | cprintf(GREEN, " "str":");for(int i = 0; i < sz; i++)cprintf(YELLOW, " %#x", (unsigned)hdr->name[i]);printf("\n") |
585 | 595 | ||
586 | print("field_4", field_4); | 596 | cprintf(GREEN, " Version: "); |
587 | print("field_6", field_6); | 597 | cprintf(YELLOW, "%x.%x.%x\n", (hdr->version >> 24) & 0xff, |
588 | print("field_A", field_A); | 598 | (hdr->version >> 16) & 0xff, hdr->version & 0xffff); |
589 | print("field_E", field_E); | 599 | |
590 | print_arr("field_10", field_10, 5); | 600 | cprintf(GREEN, " Date: "); |
591 | print("field_15", field_15); | 601 | cprintf(YELLOW, "%d/%d/%d %02d:%02d:%02d\n", hdr->day, hdr->month, hdr->year, |
602 | hdr->hour, hdr->minute, hdr->second); | ||
603 | |||
604 | cprintf(GREEN, " Chip: "); | ||
605 | cprintf(YELLOW, "%#x\n", hdr->chip); | ||
606 | |||
592 | print_arr("field_2A", field_2B, 9); | 607 | print_arr("field_2A", field_2B, 9); |
593 | print("field_34", field_34); | 608 | print("field_34", field_34); |
594 | 609 | ||
@@ -623,21 +638,22 @@ struct rkfw_header_t | |||
623 | { | 638 | { |
624 | char magic[MAGIC_RKFW_SIZE]; | 639 | char magic[MAGIC_RKFW_SIZE]; |
625 | uint16_t hdr_size; // UNSURE | 640 | uint16_t hdr_size; // UNSURE |
626 | uint32_t field_6; | 641 | uint32_t version; |
627 | uint32_t field_A; | 642 | uint32_t code; |
628 | uint16_t field_E; | 643 | uint16_t year; |
629 | uint8_t field_10[5]; | 644 | uint8_t month; |
630 | uint32_t field_15; | 645 | uint8_t day; |
646 | uint8_t hour; | ||
647 | uint8_t minute; | ||
648 | uint8_t second; | ||
649 | uint32_t chip; | ||
631 | rkfw_blob_t loader; | 650 | rkfw_blob_t loader; |
632 | rkfw_blob_t update; | 651 | rkfw_blob_t update; |
633 | uint8_t pad[60]; | 652 | uint8_t pad[61]; |
634 | uint8_t field_65; | ||
635 | } __attribute__((packed)); | 653 | } __attribute__((packed)); |
636 | 654 | ||
637 | static int do_rkfw_image(uint8_t *buf, unsigned long size) | 655 | static int do_rkfw_image(uint8_t *buf, unsigned long size) |
638 | { | 656 | { |
639 | if(sizeof(struct rkfw_header_t) != 0x66) | ||
640 | printf("aie"); | ||
641 | if(size < sizeof(struct rkfw_header_t)) | 657 | if(size < sizeof(struct rkfw_header_t)) |
642 | return 1; | 658 | return 1; |
643 | struct rkfw_header_t *hdr = (void *)buf; | 659 | struct rkfw_header_t *hdr = (void *)buf; |
@@ -652,6 +668,26 @@ static int do_rkfw_image(uint8_t *buf, unsigned long size) | |||
652 | else | 668 | else |
653 | cprintf(RED, "Mismatch\n"); | 669 | cprintf(RED, "Mismatch\n"); |
654 | 670 | ||
671 | cprintf(GREEN, " Header size: "); | ||
672 | cprintf(YELLOW, " %#x ", hdr->hdr_size); | ||
673 | if(hdr->hdr_size == sizeof(struct rkfw_header_t)) | ||
674 | cprintf(RED, "OK\n"); | ||
675 | else | ||
676 | cprintf(RED, "Mismatch\n"); | ||
677 | cprintf(GREEN, " Version: "); | ||
678 | cprintf(YELLOW, "%x.%x.%x\n", (hdr->version >> 24) & 0xff, | ||
679 | (hdr->version >> 16) & 0xff, hdr->version & 0xffff); | ||
680 | |||
681 | cprintf(GREEN, " Code: "); | ||
682 | cprintf(YELLOW, "%#x\n", hdr->code); | ||
683 | |||
684 | cprintf(GREEN, " Date: "); | ||
685 | cprintf(YELLOW, "%d/%d/%d %02d:%02d:%02d\n", hdr->day, hdr->month, hdr->year, | ||
686 | hdr->hour, hdr->minute, hdr->second); | ||
687 | |||
688 | cprintf(GREEN, " Chip: "); | ||
689 | cprintf(YELLOW, "%#x\n", hdr->chip); | ||
690 | |||
655 | cprintf(GREEN, " Loader: "); | 691 | cprintf(GREEN, " Loader: "); |
656 | print_blob_interval(&hdr->loader); | 692 | print_blob_interval(&hdr->loader); |
657 | cprintf(OFF, "\n"); | 693 | cprintf(OFF, "\n"); |
@@ -662,14 +698,42 @@ static int do_rkfw_image(uint8_t *buf, unsigned long size) | |||
662 | cprintf(OFF, "\n"); | 698 | cprintf(OFF, "\n"); |
663 | save_blob(&hdr->update, buf, size, "update", 0, NO_ENC); | 699 | save_blob(&hdr->update, buf, size, "update", 0, NO_ENC); |
664 | 700 | ||
665 | print("hdr_size", hdr_size); | 701 | print_arr("pad", pad, 61); |
666 | print("field_6", field_6); | 702 | |
667 | print("field_A", field_A); | 703 | return 0; |
668 | print("field_E", field_E); | 704 | } |
669 | print_arr("field_10", field_10, 5); | 705 | |
670 | print("field_15", field_15); | 706 | static int do_rkencode_image(uint8_t *buf, unsigned long size) |
671 | print_arr("pad", pad, 60); | 707 | { |
672 | print("field_65", field_65); | 708 | void *ptr = malloc(size); |
709 | int len = size; | ||
710 | uint8_t *buff_ptr = buf; | ||
711 | uint8_t *out_ptr = ptr; | ||
712 | int enc_mode = PAGE_ENC; | ||
713 | if(enc_mode == PAGE_ENC) | ||
714 | { | ||
715 | while(len >= 0x200) | ||
716 | { | ||
717 | encode_page(buff_ptr, out_ptr, 0x200); | ||
718 | buff_ptr += 0x200; | ||
719 | out_ptr += 0x200; | ||
720 | len -= 0x200; | ||
721 | } | ||
722 | } | ||
723 | encode_page(buff_ptr, out_ptr, len); | ||
724 | |||
725 | if(g_out_prefix) | ||
726 | { | ||
727 | FILE *f = fopen(g_out_prefix, "wb"); | ||
728 | if(f) | ||
729 | { | ||
730 | fwrite(buff_ptr, 1, size, f); | ||
731 | fclose(f); | ||
732 | } | ||
733 | else | ||
734 | printf("Cannot open output file: %m\n"); | ||
735 | } | ||
736 | free(ptr); | ||
673 | 737 | ||
674 | return 0; | 738 | return 0; |
675 | } | 739 | } |
@@ -682,6 +746,7 @@ static void usage(void) | |||
682 | printf(" --rknanofw\tUnpack a regular RknanoFW file\n"); | 746 | printf(" --rknanofw\tUnpack a regular RknanoFW file\n"); |
683 | printf(" --rkboot\tUnpack a BOOT file\n"); | 747 | printf(" --rkboot\tUnpack a BOOT file\n"); |
684 | printf(" --rknanostage\tUnpack a RknanoFW stage file\n"); | 748 | printf(" --rknanostage\tUnpack a RknanoFW stage file\n"); |
749 | printf(" --rkencode\tEncode a raw file\n"); | ||
685 | printf(" -o <prefix>\tSet output prefix\n"); | 750 | printf(" -o <prefix>\tSet output prefix\n"); |
686 | printf("The default is to try to guess the format.\n"); | 751 | printf("The default is to try to guess the format.\n"); |
687 | printf("If several formats are specified, all are tried.\n"); | 752 | printf("If several formats are specified, all are tried.\n"); |
@@ -694,6 +759,7 @@ int main(int argc, char **argv) | |||
694 | bool try_rkfw = false; | 759 | bool try_rkfw = false; |
695 | bool try_boot = false; | 760 | bool try_boot = false; |
696 | bool try_nanostage = false; | 761 | bool try_nanostage = false; |
762 | bool try_rkencode = false; | ||
697 | 763 | ||
698 | while(1) | 764 | while(1) |
699 | { | 765 | { |
@@ -704,12 +770,13 @@ int main(int argc, char **argv) | |||
704 | {"rkfw", no_argument, 0, '9'}, | 770 | {"rkfw", no_argument, 0, '9'}, |
705 | {"rknanofw", no_argument, 0, 'n'}, | 771 | {"rknanofw", no_argument, 0, 'n'}, |
706 | {"rknanostage", no_argument, 0, 's'}, | 772 | {"rknanostage", no_argument, 0, 's'}, |
773 | {"rkencode", no_argument, 0, 'e'}, | ||
707 | {"rkboot", no_argument, 0, 'b'}, | 774 | {"rkboot", no_argument, 0, 'b'}, |
708 | {"no-color", no_argument, 0, 'c'}, | 775 | {"no-color", no_argument, 0, 'c'}, |
709 | {0, 0, 0, 0} | 776 | {0, 0, 0, 0} |
710 | }; | 777 | }; |
711 | 778 | ||
712 | int c = getopt_long(argc, argv, "?d9nscbo:", long_options, NULL); | 779 | int c = getopt_long(argc, argv, "?d9nscbeo:", long_options, NULL); |
713 | if(c == -1) | 780 | if(c == -1) |
714 | break; | 781 | break; |
715 | switch(c) | 782 | switch(c) |
@@ -740,7 +807,11 @@ int main(int argc, char **argv) | |||
740 | case 's': | 807 | case 's': |
741 | try_nanostage = true; | 808 | try_nanostage = true; |
742 | break; | 809 | break; |
810 | case 'e': | ||
811 | try_rkencode = true; | ||
812 | break; | ||
743 | default: | 813 | default: |
814 | printf("Invalid argument '%c'\n", c); | ||
744 | abort(); | 815 | abort(); |
745 | } | 816 | } |
746 | } | 817 | } |
@@ -751,7 +822,7 @@ int main(int argc, char **argv) | |||
751 | return 1; | 822 | return 1; |
752 | } | 823 | } |
753 | 824 | ||
754 | if(!try_nanostage && !try_rkfw && !try_nanofw && !try_boot) | 825 | if(!try_nanostage && !try_rkfw && !try_nanofw && !try_boot && !try_rkencode) |
755 | try_nanostage = try_rkfw = try_nanofw = try_boot = true; | 826 | try_nanostage = try_rkfw = try_nanofw = try_boot = true; |
756 | 827 | ||
757 | FILE *fin = fopen(argv[optind], "r"); | 828 | FILE *fin = fopen(argv[optind], "r"); |
@@ -787,6 +858,8 @@ int main(int argc, char **argv) | |||
787 | goto Lsuccess; | 858 | goto Lsuccess; |
788 | if(try_nanostage && !do_nanostage_image(buf, size)) | 859 | if(try_nanostage && !do_nanostage_image(buf, size)) |
789 | goto Lsuccess; | 860 | goto Lsuccess; |
861 | if(try_rkencode && !do_rkencode_image(buf, size)) | ||
862 | goto Lsuccess; | ||
790 | cprintf(GREY, "No valid format found!\n"); | 863 | cprintf(GREY, "No valid format found!\n"); |
791 | Lsuccess: | 864 | Lsuccess: |
792 | free(buf); | 865 | free(buf); |