Ticket #7525: 7525-mktplinkfw_enhancements_2.diff

File 7525-mktplinkfw_enhancements_2.diff, 11.3 KB (added by Pieter "Fate" Hollants <pieter@…>, 6 years ago)

Revised version of patch adapted to OpenWrt coding style and some smaller changes (fixes, wording)

  • tools/firmware-utils/src/mktplinkfw.c

     
    9393static char *board_id; 
    9494static struct board_info *board; 
    9595static struct file_info kernel_info; 
     96static uint32_t kernel_la = 0; 
     97static uint32_t kernel_ep = 0; 
    9698static struct file_info rootfs_info; 
     99static uint32_t rootfs_ofs = 0; 
    97100static struct file_info boot_info; 
    98101static int combined; 
    99102static int strip_padding; 
    100103 
     104static struct file_info inspect_info; 
     105static int extract = 0; 
     106 
    101107char md5salt_normal[MD5SUM_LEN] = { 
    102108        0xdc, 0xd7, 0x3a, 0xa5, 0xc3, 0x95, 0x98, 0xfb, 
    103109        0xdd, 0xf9, 0xe7, 0xf4, 0x0e, 0xae, 0x47, 0x38, 
     
    214220        return ret; 
    215221} 
    216222 
     223static struct board_info *find_board_by_hwid(uint32_t hw_id) 
     224{ 
     225        struct board_info *board; 
     226 
     227        for (board = boards; board->id != NULL; board++) { 
     228                if (hw_id == board->hw_id) 
     229                        return board; 
     230        }; 
     231 
     232        return NULL; 
     233} 
     234 
     235 
    217236static void usage(int status) 
    218237{ 
    219238        FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout; 
     
    225244"Options:\n" 
    226245"  -B <board>      create image for the board specified with <board>\n" 
    227246"  -c              use combined kernel image\n" 
     247"  -E <ep>         overwrite kernel entry point with <ep> (hexval prefixed with 0x)\n" 
     248"  -L <la>         overwrite kernel load address with <la> (hexval prefixed with 0x)\n" 
    228249"  -k <file>       read kernel image from the file <file>\n" 
    229250"  -r <file>       read rootfs image from the file <file>\n" 
     251"  -R <offset>     overwrite rootfs offset with <offset> (hexval prefixed with 0x)\n" 
    230252"  -o <file>       write output to the file <file>\n" 
    231253"  -s              strip padding from the end of the image\n" 
    232254"  -N <vendor>     set image vendor to <vendor>\n" 
    233255"  -V <version>    set image version to <version>\n" 
     256"  -i <file>       inspect given firmware file <file>\n" 
     257"  -x              extract kernel and rootfs while inspecting (requires -i)\n" 
    234258"  -h              show this screen\n" 
    235259        ); 
    236260 
     
    294318{ 
    295319        int ret; 
    296320 
     321        if (inspect_info.file_name) { 
     322                ret = get_file_stat(&inspect_info); 
     323                if (ret) 
     324                        return ret; 
     325 
     326                return 0; 
     327        } else if (extract) { 
     328                ERR("no firmware for inspection specified"); 
     329                return -1; 
     330        } 
     331 
    297332        if (board_id == NULL) { 
    298333                ERR("no board specified"); 
    299334                return -1; 
     
    304339                ERR("unknown/unsupported board id \"%s\"", board_id); 
    305340                return -1; 
    306341        } 
     342        if (!kernel_la) 
     343                kernel_la = board->kernel_la; 
     344        if (!kernel_ep) 
     345                kernel_ep = board->kernel_ep; 
     346        if (!rootfs_ofs) 
     347                rootfs_ofs = board->rootfs_ofs; 
    307348 
    308349        if (kernel_info.file_name == NULL) { 
    309350                ERR("no kernel image specified"); 
     
    322363                } 
    323364        } else { 
    324365                if (kernel_info.file_size > 
    325                     board->rootfs_ofs - sizeof(struct fw_header)) { 
     366                    rootfs_ofs - sizeof(struct fw_header)) { 
    326367                        ERR("kernel image is too big"); 
    327368                        return -1; 
    328369                } 
     
    336377                        return ret; 
    337378 
    338379                if (rootfs_info.file_size > 
    339                     (board->fw_max_len - board->rootfs_ofs)) { 
     380                    (board->fw_max_len - rootfs_ofs)) { 
    340381                        ERR("rootfs image is too big"); 
    341382                        return -1; 
    342383                } 
     
    367408        else 
    368409                memcpy(hdr->md5sum1, md5salt_boot, sizeof(hdr->md5sum1)); 
    369410 
    370         hdr->kernel_la = HOST_TO_BE32(board->kernel_la); 
    371         hdr->kernel_ep = HOST_TO_BE32(board->kernel_ep); 
     411        hdr->kernel_la = HOST_TO_BE32(kernel_la); 
     412        hdr->kernel_ep = HOST_TO_BE32(kernel_ep); 
    372413        hdr->fw_length = HOST_TO_BE32(board->fw_max_len); 
    373414        hdr->kernel_ofs = HOST_TO_BE32(sizeof(struct fw_header)); 
    374415        hdr->kernel_len = HOST_TO_BE32(kernel_info.file_size); 
    375416        if (!combined) { 
    376                 hdr->rootfs_ofs = HOST_TO_BE32(board->rootfs_ofs); 
     417                hdr->rootfs_ofs = HOST_TO_BE32(rootfs_ofs); 
    377418                hdr->rootfs_len = HOST_TO_BE32(rootfs_info.file_size); 
    378419        } 
    379420 
     
    437478        writelen = kernel_info.file_size; 
    438479 
    439480        if (!combined) { 
    440                 p = buf + board->rootfs_ofs; 
     481                p = buf + rootfs_ofs; 
    441482                ret = read_to_buf(&rootfs_info, p); 
    442483                if (ret) 
    443484                        goto out_free_buf; 
    444485 
    445                 writelen = board->rootfs_ofs + rootfs_info.file_size; 
     486                writelen = rootfs_ofs + rootfs_info.file_size; 
    446487        } 
    447488 
    448489        if (!strip_padding) 
     
    461502        return ret; 
    462503} 
    463504 
     505/* Helper functions to inspect_fw() representing different output formats */ 
     506static inline void inspect_fw_pstr(char *label, char *str) 
     507{ 
     508        printf("%-23s: %s\n", label, str); 
     509} 
     510 
     511static inline void inspect_fw_phex(char *label, uint32_t val) 
     512{ 
     513        printf("%-23s: 0x%08x\n", label, val); 
     514} 
     515 
     516static inline void inspect_fw_phexpost(char *label, 
     517                                       uint32_t val, char *post) 
     518{ 
     519        printf("%-23s: 0x%08x (%s)\n", label, val, post); 
     520} 
     521 
     522static inline void inspect_fw_phexdef(char *label, 
     523                                      uint32_t val, uint32_t defval) 
     524{ 
     525        printf("%-23s: 0x%08x                  ", label, val); 
     526 
     527        if (val == defval) 
     528                printf("(== OpenWrt default)\n"); 
     529        else 
     530                printf("(OpenWrt default: 0x%08x)\n", defval); 
     531} 
     532 
     533static inline void inspect_fw_phexexp(char *label, 
     534                                      uint32_t val, uint32_t expval) 
     535{ 
     536        printf("%-23s: 0x%08x ", label, val); 
     537 
     538        if (val == expval) 
     539                printf("(ok)\n"); 
     540        else 
     541                printf("(expected: 0x%08x)\n", expval); 
     542} 
     543 
     544static inline void inspect_fw_phexdec(char *label, uint32_t val) 
     545{ 
     546        printf("%-23s: 0x%08x / %8u bytes\n", label, val, val); 
     547} 
     548 
     549static inline void inspect_fw_phexdecdef(char *label, 
     550                                         uint32_t val, uint32_t defval) 
     551{ 
     552        printf("%-23s: 0x%08x / %8u bytes ", label, val, val); 
     553 
     554        if (val == defval) 
     555                printf("(== OpenWrt default)\n"); 
     556        else 
     557                printf("(OpenWrt default: 0x%08x)\n", defval); 
     558} 
     559 
     560static inline void inspect_fw_pmd5sum(char *label, uint8_t *val, char *text) 
     561{ 
     562        int i; 
     563 
     564        printf("%-23s:", label); 
     565        for (i=0; i<MD5SUM_LEN; i++) 
     566                printf(" %02x", val[i]); 
     567        printf(" %s\n", text); 
     568} 
     569 
     570static int inspect_fw(void) 
     571{ 
     572        char *buf; 
     573        struct fw_header *hdr; 
     574        uint8_t md5sum[MD5SUM_LEN]; 
     575        struct board_info *board; 
     576        int ret = EXIT_FAILURE; 
     577 
     578        buf = malloc(inspect_info.file_size); 
     579        if (!buf) { 
     580                ERR("no memory for buffer!\n"); 
     581                goto out; 
     582        } 
     583 
     584        ret = read_to_buf(&inspect_info, buf); 
     585        if (ret) 
     586                goto out_free_buf; 
     587        hdr = (struct fw_header *)buf; 
     588 
     589        inspect_fw_pstr("File name", inspect_info.file_name); 
     590        inspect_fw_phexdec("File size", inspect_info.file_size); 
     591 
     592        if (BE32_TO_HOST(hdr->version) != HEADER_VERSION_V1) { 
     593                ERR("file does not seem to have V1 header!\n"); 
     594                goto out_free_buf; 
     595        } 
     596 
     597        inspect_fw_phexdec("Version 1 Header size", sizeof(struct fw_header)); 
     598 
     599        if (BE32_TO_HOST(hdr->unk1) != 0) 
     600                inspect_fw_phexdec("Unknown value 1", hdr->unk1); 
     601 
     602        memcpy(md5sum, hdr->md5sum1, sizeof(md5sum)); 
     603        if (BE32_TO_HOST(hdr->boot_len) == 0) 
     604                memcpy(hdr->md5sum1, md5salt_normal, sizeof(md5sum)); 
     605        else 
     606                memcpy(hdr->md5sum1, md5salt_boot, sizeof(md5sum)); 
     607        get_md5(buf, inspect_info.file_size, hdr->md5sum1); 
     608 
     609        if (memcmp(md5sum, hdr->md5sum1, sizeof(md5sum))) { 
     610                inspect_fw_pmd5sum("Header MD5Sum1", md5sum, "(*ERROR*)"); 
     611                inspect_fw_pmd5sum("          --> expected", hdr->md5sum1, ""); 
     612        } else { 
     613                inspect_fw_pmd5sum("Header MD5Sum1", md5sum, "(ok)"); 
     614        } 
     615        if (BE32_TO_HOST(hdr->unk2) != 0) 
     616                inspect_fw_phexdec("Unknown value 2", hdr->unk2); 
     617        inspect_fw_pmd5sum("Header MD5Sum2", hdr->md5sum2, 
     618                           "(purpose yet unknown, unchecked here)"); 
     619        if (BE32_TO_HOST(hdr->unk3) != 0) 
     620                inspect_fw_phexdec("Unknown value 3", hdr->unk3); 
     621 
     622        printf("\n"); 
     623 
     624        inspect_fw_pstr("Vendor name", hdr->vendor_name); 
     625        inspect_fw_pstr("Firmware version", hdr->fw_version); 
     626        board = find_board_by_hwid(BE32_TO_HOST(hdr->hw_id)); 
     627        if (board) { 
     628                inspect_fw_phexpost("Hardware ID", 
     629                                    BE32_TO_HOST(hdr->hw_id), board->id); 
     630                inspect_fw_phexexp("Hardware Revision", 
     631                                   BE32_TO_HOST(hdr->hw_rev), board->hw_rev); 
     632        } else { 
     633                inspect_fw_phexpost("Hardware ID", 
     634                                    BE32_TO_HOST(hdr->hw_id), "unknown"); 
     635                inspect_fw_phex("Hardware Revision", 
     636                                BE32_TO_HOST(hdr->hw_rev)); 
     637        } 
     638 
     639        printf("\n"); 
     640 
     641        inspect_fw_phexdec("Kernel data offset", 
     642                           BE32_TO_HOST(hdr->kernel_ofs)); 
     643        inspect_fw_phexdec("Kernel data length", 
     644                           BE32_TO_HOST(hdr->kernel_len)); 
     645        if (board) { 
     646                inspect_fw_phexdef("Kernel load address", 
     647                                   BE32_TO_HOST(hdr->kernel_la), 
     648                                   board->kernel_la); 
     649                inspect_fw_phexdef("Kernel entry point", 
     650                                   BE32_TO_HOST(hdr->kernel_ep), 
     651                                   board->kernel_ep); 
     652                inspect_fw_phexdecdef("Rootfs data offset", 
     653                                      BE32_TO_HOST(hdr->rootfs_ofs), 
     654                                      board->rootfs_ofs); 
     655        } else { 
     656                inspect_fw_phex("Kernel load address", 
     657                                BE32_TO_HOST(hdr->kernel_la)); 
     658                inspect_fw_phex("Kernel entry point", 
     659                                BE32_TO_HOST(hdr->kernel_ep)); 
     660                inspect_fw_phexdec("Rootfs data offset", 
     661                                   BE32_TO_HOST(hdr->rootfs_ofs)); 
     662        } 
     663        inspect_fw_phexdec("Rootfs data length", 
     664                           BE32_TO_HOST(hdr->rootfs_len)); 
     665        inspect_fw_phexdec("Boot loader data offset", 
     666                           BE32_TO_HOST(hdr->boot_ofs)); 
     667        inspect_fw_phexdec("Boot loader data length", 
     668                           BE32_TO_HOST(hdr->boot_len)); 
     669        inspect_fw_phexdec("Total firmware length", 
     670                           BE32_TO_HOST(hdr->fw_length)); 
     671 
     672        if (extract) { 
     673                FILE *fp; 
     674                char *filename; 
     675 
     676                printf("\n"); 
     677 
     678                filename = malloc(strlen(inspect_info.file_name) + 8); 
     679                sprintf(filename, "%s-kernel", inspect_info.file_name); 
     680                printf("Extracting kernel to \"%s\"...\n", filename); 
     681                fp = fopen(filename, "w"); 
     682                if (fp) { 
     683                        if (!fwrite(buf + BE32_TO_HOST(hdr->kernel_ofs), 
     684                                    BE32_TO_HOST(hdr->kernel_len), 1, fp)) { 
     685                                ERR("error in fwrite(): %s", strerror(errno)); 
     686                        } 
     687                        fclose(fp); 
     688                } else { 
     689                        ERR("error in fopen(): %s", strerror(errno)); 
     690                } 
     691                free(filename); 
     692 
     693                filename = malloc(strlen(inspect_info.file_name) + 8); 
     694                sprintf(filename, "%s-rootfs", inspect_info.file_name); 
     695                printf("Extracting rootfs to \"%s\"...\n", filename); 
     696                fp = fopen(filename, "w"); 
     697                if (fp) { 
     698                        if (!fwrite(buf + BE32_TO_HOST(hdr->rootfs_ofs), 
     699                                    BE32_TO_HOST(hdr->rootfs_len), 1, fp)) { 
     700                                ERR("error in fwrite(): %s", strerror(errno)); 
     701                        } 
     702                        fclose(fp); 
     703                } else { 
     704                        ERR("error in fopen(): %s", strerror(errno)); 
     705                } 
     706                free(filename); 
     707        } 
     708 
     709 out_free_buf: 
     710        free(buf); 
     711 out: 
     712        return ret; 
     713} 
     714 
    464715int main(int argc, char *argv[]) 
    465716{ 
    466717        int ret = EXIT_FAILURE; 
     
    473724        while ( 1 ) { 
    474725                int c; 
    475726 
    476                 c = getopt(argc, argv, "B:V:N:ck:r:o:hs"); 
     727                c = getopt(argc, argv, "B:E:L:V:N:ci:k:r:R:o:xhs"); 
    477728                if (c == -1) 
    478729                        break; 
    479730 
     
    481732                case 'B': 
    482733                        board_id = optarg; 
    483734                        break; 
     735                case 'E': 
     736                        sscanf(optarg, "0x%x", &kernel_ep); 
     737                        break; 
     738                case 'L': 
     739                        sscanf(optarg, "0x%x", &kernel_la); 
     740                        break; 
    484741                case 'V': 
    485742                        version = optarg; 
    486743                        break; 
     
    496753                case 'r': 
    497754                        rootfs_info.file_name = optarg; 
    498755                        break; 
     756                case 'R': 
     757                        sscanf(optarg, "0x%x", &rootfs_ofs); 
     758                        break; 
    499759                case 'o': 
    500760                        ofname = optarg; 
    501761                        break; 
    502762                case 's': 
    503763                        strip_padding = 1; 
    504764                        break; 
     765                case 'i': 
     766                        inspect_info.file_name = optarg; 
     767                        break; 
     768                case 'x': 
     769                        extract = 1; 
     770                        break; 
    505771                case 'h': 
    506772                        usage(EXIT_SUCCESS); 
    507773                        break; 
     
    515781        if (ret) 
    516782                goto out; 
    517783 
    518         ret = build_fw(); 
     784        if (!inspect_info.file_name) 
     785                ret = build_fw(); 
     786        else 
     787                ret = inspect_fw(); 
    519788 
    520789 out: 
    521790        return ret;