1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org> 4 * 5 * This tool was based on: 6 * TP-Link WR941 V2 firmware checksum fixing tool. 7 * Copyright (C) 2008,2009 Wang Jian <lark@linux.net.cn> 8 */ 9 10 #include <stdio.h> 11 #include <stdlib.h> 12 #include <stdint.h> 13 #include <string.h> 14 #include <byteswap.h> 15 #include <unistd.h> /* for unlink() */ 16 #include <libgen.h> 17 #include <getopt.h> /* for getopt() */ 18 #include <stdarg.h> 19 #include <errno.h> 20 #include <stdbool.h> 21 #include <endian.h> 22 #include <sys/stat.h> 23 24 #include <arpa/inet.h> 25 #include <netinet/in.h> 26 27 #include "md5.h" 28 #include "mktplinkfw-lib.h" 29 30 struct fw_header { 31 uint32_t version; /* 0x00: header version */ 32 char fw_version[48]; /* 0x04: fw version string */ 33 uint32_t hw_id; /* 0x34: hardware id */ 34 uint32_t hw_rev; /* 0x38: FIXME: hardware revision? */ 35 uint32_t hw_ver_add; /* 0x3c: additional hardware version */ 36 uint8_t md5sum1[MD5SUM_LEN]; /* 0x40 */ 37 uint32_t unk2; /* 0x50: 0x00000000 */ 38 uint8_t md5sum2[MD5SUM_LEN]; /* 0x54 */ 39 uint32_t unk3; /* 0x64: 0xffffffff */ 40 41 uint32_t kernel_la; /* 0x68: kernel load address */ 42 uint32_t kernel_ep; /* 0x6c: kernel entry point */ 43 uint32_t fw_length; /* 0x70: total length of the image */ 44 uint32_t kernel_ofs; /* 0x74: kernel data offset */ 45 uint32_t kernel_len; /* 0x78: kernel data length */ 46 uint32_t rootfs_ofs; /* 0x7c: rootfs data offset */ 47 uint32_t rootfs_len; /* 0x80: rootfs data length */ 48 uint32_t boot_ofs; /* 0x84: bootloader offset */ 49 uint32_t boot_len; /* 0x88: bootloader length */ 50 uint16_t unk4; /* 0x8c: 0x55aa */ 51 uint8_t sver_hi; /* 0x8e */ 52 uint8_t sver_lo; /* 0x8f */ 53 uint8_t unk5; /* 0x90: magic: 0xa5 */ 54 uint8_t ver_hi; /* 0x91 */ 55 uint8_t ver_mid; /* 0x92 */ 56 uint8_t ver_lo; /* 0x93 */ 57 uint8_t pad[364]; 58 } __attribute__ ((packed)); 59 60 #define FLAG_LE_KERNEL_LA_EP 0x00000001 /* Little-endian used for kernel load address & entry point */ 61 62 struct board_info { 63 char *id; 64 uint32_t hw_id; 65 uint32_t hw_rev; 66 uint32_t hw_ver_add; 67 char *layout_id; 68 uint32_t hdr_ver; 69 uint32_t flags; 70 }; 71 72 /* 73 * Globals 74 */ 75 char *ofname; 76 char *progname; 77 static char *vendor = "TP-LINK Technologies"; 78 static char *version = "ver. 1.0"; 79 static char *fw_ver = "0.0.0"; 80 static char *sver = "1.0"; 81 static uint32_t hdr_ver = 2; 82 83 static struct board_info custom_board; 84 85 static struct board_info *board; 86 static char *layout_id; 87 struct flash_layout *layout; 88 static char *opt_hw_id; 89 static char *opt_hw_rev; 90 static char *opt_hw_ver_add; 91 static int fw_ver_lo; 92 static int fw_ver_mid; 93 static int fw_ver_hi; 94 static int sver_lo; 95 static int sver_hi; 96 struct file_info kernel_info; 97 static uint32_t kernel_la = 0; 98 static uint32_t kernel_ep = 0; 99 uint32_t kernel_len = 0; 100 struct file_info rootfs_info; 101 uint32_t rootfs_ofs = 0; 102 uint32_t rootfs_align; 103 static struct file_info boot_info = { 0 }; 104 int combined; 105 int strip_padding; 106 int add_jffs2_eof; 107 108 static struct file_info inspect_info; 109 static int extract = 0; 110 111 char md5salt_normal[MD5SUM_LEN] = { 112 0xdc, 0xd7, 0x3a, 0xa5, 0xc3, 0x95, 0x98, 0xfb, 113 0xdc, 0xf9, 0xe7, 0xf4, 0x0e, 0xae, 0x47, 0x37, 114 }; 115 116 char md5salt_boot[MD5SUM_LEN] = { 117 0x8c, 0xef, 0x33, 0x5f, 0xd5, 0xc5, 0xce, 0xfa, 118 0xac, 0x9c, 0x28, 0xda, 0xb2, 0xe9, 0x0f, 0x42, 119 }; 120 121 static struct flash_layout layouts[] = { 122 { 123 .id = "4Mmtk", 124 .fw_max_len = 0x3c0000, 125 .kernel_la = 0x80000000, 126 .kernel_ep = 0x80000000, 127 .rootfs_ofs = 0x140000, 128 }, { 129 .id = "4MLmtk", 130 .fw_max_len = 0x3d0000, 131 .kernel_la = 0x80000000, 132 .kernel_ep = 0x80000000, 133 .rootfs_ofs = 0x140000, 134 }, { 135 .id = "8Mltq", 136 .fw_max_len = 0x7a0000, 137 .kernel_la = 0x80002000, 138 .kernel_ep = 0x80002000, 139 .rootfs_ofs = 0x140000, 140 }, { 141 .id = "16Mltq", 142 .fw_max_len = 0xf90000, 143 .kernel_la = 0x80002000, 144 .kernel_ep = 0x800061b0, 145 .rootfs_ofs = 0x140000, 146 }, { 147 .id = "8Mmtk", 148 .fw_max_len = 0x7a0000, 149 .kernel_la = 0x80000000, 150 .kernel_ep = 0x80000000, 151 .rootfs_ofs = 0x140000, 152 }, { 153 .id = "8MSUmtk", /* Split U-Boot OS */ 154 .fw_max_len = 0x770000, 155 .kernel_la = 0x80000000, 156 .kernel_ep = 0x80000000, 157 .rootfs_ofs = 0x140000, 158 }, { 159 .id = "8MLmtk", 160 .fw_max_len = 0x7b0000, 161 .kernel_la = 0x80000000, 162 .kernel_ep = 0x80000000, 163 .rootfs_ofs = 0x140000, 164 }, { 165 .id = "8Mqca", 166 .fw_max_len = 0x7a0000, 167 .kernel_la = 0x80060000, 168 .kernel_ep = 0x80060000, 169 .rootfs_ofs = 0x140000, 170 }, { 171 .id = "16Mqca", 172 .fw_max_len = 0xf90000, 173 .kernel_la = 0x80060000, 174 .kernel_ep = 0x80060000, 175 .rootfs_ofs = 0x140000, 176 }, { 177 /* terminating entry */ 178 } 179 }; 180 181 static void usage(int status) 182 { 183 FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout; 184 185 fprintf(stream, "Usage: %s [OPTIONS...]\n", progname); 186 fprintf(stream, 187 "\n" 188 "Options:\n" 189 " -c use combined kernel image\n" 190 " -e swap endianness in kernel load address and entry point\n" 191 " -E <ep> overwrite kernel entry point with <ep> (hexval prefixed with 0x)\n" 192 " -L <la> overwrite kernel load address with <la> (hexval prefixed with 0x)\n" 193 " -H <hwid> use hardware id specified with <hwid>\n" 194 " -W <hwrev> use hardware revision specified with <hwrev>\n" 195 " -w <hwveradd> use additional hardware version specified with <hwveradd>\n" 196 " -F <id> use flash layout specified with <id>\n" 197 " -k <file> read kernel image from the file <file>\n" 198 " -r <file> read rootfs image from the file <file>\n" 199 " -b <file> read bootloader image from the file <file>\n" 200 " -a <align> align the rootfs start on an <align> bytes boundary\n" 201 " -R <offset> overwrite rootfs offset with <offset> (hexval prefixed with 0x)\n" 202 " -o <file> write output to the file <file>\n" 203 " -s strip padding from the end of the image\n" 204 " -j add jffs2 end-of-filesystem markers\n" 205 " -N <vendor> set image vendor to <vendor>\n" 206 " -T <version> set header version to <version>\n" 207 " -V <version> set image version to <version>\n" 208 " -v <version> set firmware version to <version>\n" 209 " -y <version> set secondary version to <version>\n" 210 " -i <file> inspect given firmware file <file>\n" 211 " -x extract bootloader, kernel and rootfs while inspecting (requires -i)\n" 212 " -h show this screen\n" 213 ); 214 215 exit(status); 216 } 217 218 static int check_options(void) 219 { 220 int ret; 221 int exceed_bytes; 222 223 if (inspect_info.file_name) { 224 ret = get_file_stat(&inspect_info); 225 if (ret) 226 return ret; 227 228 return 0; 229 } else if (extract) { 230 ERR("no firmware for inspection specified"); 231 return -1; 232 } 233 234 if (opt_hw_id == NULL) { 235 ERR("hardware id must be specified"); 236 return -1; 237 } 238 239 board = &custom_board; 240 241 if (layout_id == NULL) { 242 ERR("flash layout is not specified"); 243 return -1; 244 } 245 246 board->hw_id = strtoul(opt_hw_id, NULL, 0); 247 248 board->hw_rev = 1; 249 board->hw_ver_add = 0; 250 251 if (opt_hw_rev) 252 board->hw_rev = strtoul(opt_hw_rev, NULL, 0); 253 if (opt_hw_ver_add) 254 board->hw_ver_add = strtoul(opt_hw_ver_add, NULL, 0); 255 256 layout = find_layout(layouts, layout_id); 257 if (layout == NULL) { 258 ERR("unknown flash layout \"%s\"", layout_id); 259 return -1; 260 } 261 262 if (!kernel_la) 263 kernel_la = layout->kernel_la; 264 if (!kernel_ep) 265 kernel_ep = layout->kernel_ep; 266 if (!rootfs_ofs) 267 rootfs_ofs = layout->rootfs_ofs; 268 269 /* check bootloader */ 270 ret = get_file_stat(&boot_info); 271 if (ret) { 272 ERR("Can not load bootloader image."); 273 return ret; 274 } 275 276 if (boot_info.file_size > 2 * 64 * 1024) { 277 /* the offset in fill_header is hardcoded to 128k */ 278 ERR("Bootloader image is bigger than 128k."); 279 return -1; 280 } 281 282 if (kernel_info.file_name == NULL) { 283 ERR("no kernel image specified"); 284 return -1; 285 } 286 ret = get_file_stat(&kernel_info); 287 if (ret) 288 return ret; 289 290 kernel_len = kernel_info.file_size; 291 292 if (combined) { 293 if (kernel_info.file_size > 294 layout->fw_max_len - sizeof(struct fw_header)) { 295 ERR("kernel image is too big"); 296 return -1; 297 } 298 } else { 299 if (rootfs_info.file_name == NULL) { 300 ERR("no rootfs image specified"); 301 return -1; 302 } 303 304 ret = get_file_stat(&rootfs_info); 305 if (ret) 306 return ret; 307 308 if (rootfs_align) { 309 kernel_len += sizeof(struct fw_header); 310 rootfs_ofs = ALIGN(kernel_len, rootfs_align); 311 kernel_len -= sizeof(struct fw_header); 312 313 DBG("rootfs offset aligned to 0x%u", rootfs_ofs); 314 315 exceed_bytes = (kernel_len + rootfs_info.file_size) - 316 (layout->fw_max_len - sizeof(struct fw_header)); 317 if (exceed_bytes > 0) { 318 ERR("images are too big by %i bytes", exceed_bytes); 319 return -1; 320 } 321 } else { 322 exceed_bytes = kernel_info.file_size - 323 (rootfs_ofs - sizeof(struct fw_header)); 324 if (exceed_bytes > 0) { 325 ERR("images are too big by %i bytes", exceed_bytes); 326 return -1; 327 } 328 329 exceed_bytes = rootfs_info.file_size - 330 (layout->fw_max_len - rootfs_ofs); 331 if (exceed_bytes > 0) { 332 ERR("images are too big by %i bytes", exceed_bytes); 333 return -1; 334 } 335 } 336 } 337 338 if (ofname == NULL) { 339 ERR("no output file specified"); 340 return -1; 341 } 342 343 ret = sscanf(fw_ver, "%d.%d.%d", &fw_ver_hi, &fw_ver_mid, &fw_ver_lo); 344 if (ret != 3) { 345 ERR("invalid firmware version '%s'", fw_ver); 346 return -1; 347 } 348 349 ret = sscanf(sver, "%d.%d", &sver_hi, &sver_lo); 350 if (ret != 2) { 351 ERR("invalid secondary version '%s'", sver); 352 return -1; 353 } 354 355 return 0; 356 } 357 358 void fill_header_bootloader(char *buf, int len, int with_bootloader) 359 { 360 struct fw_header *hdr = (struct fw_header *)buf; 361 unsigned ver_len; 362 unsigned int offset = 0; 363 364 if (with_bootloader) { 365 /* ensure the bootloader is padded to 64k */ 366 offset = boot_info.file_size & (64 * 1024); 367 if (offset < boot_info.file_size) 368 offset += 64 * 1024; 369 370 offset += sizeof(struct fw_header); 371 } 372 373 memset(hdr, '\xff', sizeof(struct fw_header)); 374 375 hdr->version = htonl(bswap_32(hdr_ver)); 376 ver_len = strlen(version); 377 if (ver_len > (sizeof(hdr->fw_version) - 1)) 378 ver_len = sizeof(hdr->fw_version) - 1; 379 380 memcpy(hdr->fw_version, version, ver_len); 381 hdr->fw_version[ver_len] = 0; 382 383 hdr->hw_id = htonl(board->hw_id); 384 hdr->hw_rev = htonl(board->hw_rev); 385 hdr->hw_ver_add = htonl(board->hw_ver_add); 386 387 if (boot_info.file_size == 0 || !with_bootloader) { 388 memcpy(hdr->md5sum1, md5salt_normal, sizeof(hdr->md5sum1)); 389 hdr->boot_ofs = htonl(0); 390 hdr->boot_len = htonl(0); 391 } else { 392 memcpy(hdr->md5sum1, md5salt_boot, sizeof(hdr->md5sum1)); 393 hdr->boot_ofs = htonl(0); 394 hdr->boot_len = htonl(boot_info.file_size); 395 } 396 397 hdr->kernel_la = htonl(kernel_la); 398 hdr->kernel_ep = htonl(kernel_ep); 399 hdr->fw_length = htonl(layout->fw_max_len + offset); 400 hdr->kernel_ofs = htonl(sizeof(struct fw_header) + offset); 401 hdr->kernel_len = htonl(kernel_len); 402 if (!combined) { 403 /* even the bootloader doesnt increased the root_ofs. Unsure if this parser 404 * always ignores the rootfs or only in the 841v13 405 */ 406 hdr->rootfs_ofs = htonl(rootfs_ofs); 407 hdr->rootfs_len = htonl(rootfs_info.file_size); 408 } 409 410 hdr->unk2 = htonl(0); 411 hdr->unk3 = htonl(0xffffffff); 412 hdr->unk4 = htons(0x55aa); 413 hdr->unk5 = 0xa5; 414 415 hdr->sver_hi = sver_hi; 416 hdr->sver_lo = sver_lo; 417 418 hdr->ver_hi = fw_ver_hi; 419 hdr->ver_mid = fw_ver_mid; 420 hdr->ver_lo = fw_ver_lo; 421 422 if (board->flags & FLAG_LE_KERNEL_LA_EP) { 423 hdr->kernel_la = bswap_32(hdr->kernel_la); 424 hdr->kernel_ep = bswap_32(hdr->kernel_ep); 425 } 426 427 get_md5(buf, len, hdr->md5sum1); 428 } 429 430 /* fill_header get called by mktplinkfw_lib to fill the header in front of the kernel. */ 431 void fill_header(char *buf, int len) { 432 fill_header_bootloader(buf, len, 0); 433 } 434 435 static int inspect_fw(void) 436 { 437 char *buf; 438 struct fw_header *hdr; 439 uint8_t md5sum[MD5SUM_LEN]; 440 struct board_info *board; 441 int ret = EXIT_FAILURE; 442 443 buf = malloc(inspect_info.file_size); 444 if (!buf) { 445 ERR("no memory for buffer!\n"); 446 goto out; 447 } 448 449 ret = read_to_buf(&inspect_info, buf); 450 if (ret) 451 goto out_free_buf; 452 hdr = (struct fw_header *)buf; 453 454 board = &custom_board; 455 456 if (board->flags & FLAG_LE_KERNEL_LA_EP) { 457 hdr->kernel_la = bswap_32(hdr->kernel_la); 458 hdr->kernel_ep = bswap_32(hdr->kernel_ep); 459 } 460 461 inspect_fw_pstr("File name", inspect_info.file_name); 462 inspect_fw_phexdec("File size", inspect_info.file_size); 463 464 switch(bswap_32(ntohl(hdr->version))) { 465 case 2: 466 case 3: 467 break; 468 default: 469 ERR("file does not seem to have V2/V3 header!\n"); 470 goto out_free_buf; 471 } 472 473 inspect_fw_phexdec("Version 2 Header size", sizeof(struct fw_header)); 474 475 memcpy(md5sum, hdr->md5sum1, sizeof(md5sum)); 476 if (ntohl(hdr->boot_len) == 0) 477 memcpy(hdr->md5sum1, md5salt_normal, sizeof(md5sum)); 478 else 479 memcpy(hdr->md5sum1, md5salt_boot, sizeof(md5sum)); 480 get_md5(buf, inspect_info.file_size, hdr->md5sum1); 481 482 if (memcmp(md5sum, hdr->md5sum1, sizeof(md5sum))) { 483 inspect_fw_pmd5sum("Header MD5Sum1", md5sum, "(*ERROR*)"); 484 inspect_fw_pmd5sum(" --> expected", hdr->md5sum1, ""); 485 } else { 486 inspect_fw_pmd5sum("Header MD5Sum1", md5sum, "(ok)"); 487 } 488 if (ntohl(hdr->unk2) != 0) 489 inspect_fw_phexdec("Unknown value 2", hdr->unk2); 490 inspect_fw_pmd5sum("Header MD5Sum2", hdr->md5sum2, 491 "(purpose yet unknown, unchecked here)"); 492 493 if (ntohl(hdr->unk3) != 0xffffffff) 494 inspect_fw_phexdec("Unknown value 3", hdr->unk3); 495 496 if (ntohs(hdr->unk4) != 0x55aa) 497 inspect_fw_phexdec("Unknown value 4", hdr->unk4); 498 499 if (hdr->unk5 != 0xa5) 500 inspect_fw_phexdec("Unknown value 5", hdr->unk5); 501 502 printf("\n"); 503 504 inspect_fw_pstr("Firmware version", hdr->fw_version); 505 inspect_fw_phex("Hardware ID", ntohl(hdr->hw_id)); 506 inspect_fw_phex("Hardware Revision", 507 ntohl(hdr->hw_rev)); 508 inspect_fw_phex("Additional HW Version", 509 ntohl(hdr->hw_ver_add)); 510 511 printf("%-23s: %d.%d.%d-%d.%d\n", "Software version", 512 hdr->ver_hi, hdr->ver_mid, hdr->ver_lo, 513 hdr->sver_hi, hdr->sver_lo); 514 515 printf("\n"); 516 517 inspect_fw_phexdec("Kernel data offset", 518 ntohl(hdr->kernel_ofs)); 519 inspect_fw_phexdec("Kernel data length", 520 ntohl(hdr->kernel_len)); 521 inspect_fw_phex("Kernel load address", 522 ntohl(hdr->kernel_la)); 523 inspect_fw_phex("Kernel entry point", 524 ntohl(hdr->kernel_ep)); 525 inspect_fw_phexdec("Rootfs data offset", 526 ntohl(hdr->rootfs_ofs)); 527 inspect_fw_phexdec("Rootfs data length", 528 ntohl(hdr->rootfs_len)); 529 inspect_fw_phexdec("Boot loader data offset", 530 ntohl(hdr->boot_ofs)); 531 inspect_fw_phexdec("Boot loader data length", 532 ntohl(hdr->boot_len)); 533 inspect_fw_phexdec("Total firmware length", 534 ntohl(hdr->fw_length)); 535 536 if (extract) { 537 FILE *fp; 538 char *filename; 539 540 printf("\n"); 541 542 if (hdr->boot_len) { 543 filename = malloc(strlen(inspect_info.file_name) + 8); 544 sprintf(filename, "%s-bootloader", inspect_info.file_name); 545 printf("Extracting bootloader to \"%s\"...\n", filename); 546 fp = fopen(filename, "w"); 547 if (fp) { 548 if (!fwrite(buf + sizeof(struct fw_header) + ntohl(hdr->boot_ofs), 549 ntohl(hdr->boot_len), 1, fp)) { 550 ERR("error in fwrite(): %s", strerror(errno)); 551 } 552 fclose(fp); 553 } else { 554 ERR("error in fopen(): %s", strerror(errno)); 555 } 556 free(filename); 557 } 558 559 filename = malloc(strlen(inspect_info.file_name) + 8); 560 sprintf(filename, "%s-kernel", inspect_info.file_name); 561 printf("Extracting kernel to \"%s\"...\n", filename); 562 fp = fopen(filename, "w"); 563 if (fp) { 564 if (!fwrite(buf + ntohl(hdr->kernel_ofs), 565 ntohl(hdr->kernel_len), 1, fp)) { 566 ERR("error in fwrite(): %s", strerror(errno)); 567 } 568 fclose(fp); 569 } else { 570 ERR("error in fopen(): %s", strerror(errno)); 571 } 572 free(filename); 573 574 filename = malloc(strlen(inspect_info.file_name) + 8); 575 sprintf(filename, "%s-rootfs", inspect_info.file_name); 576 printf("Extracting rootfs to \"%s\"...\n", filename); 577 fp = fopen(filename, "w"); 578 if (fp) { 579 if (!fwrite(buf + ntohl(hdr->rootfs_ofs), 580 ntohl(hdr->rootfs_len), 1, fp)) { 581 ERR("error in fwrite(): %s", strerror(errno)); 582 } 583 fclose(fp); 584 } else { 585 ERR("error in fopen(): %s", strerror(errno)); 586 } 587 free(filename); 588 } 589 590 out_free_buf: 591 free(buf); 592 out: 593 return ret; 594 } 595 596 /* prepend a second image header and the bootloader. 597 * 598 * |------------| 599 * |image header| 600 * |------------| 601 * |bootloader | 602 * |------------| 603 * |optional pad| 604 * |------------| 605 * |image header| 606 * |------------| 607 * |kernel image| 608 * |------------| 609 * |rootfs image| 610 * |------------| 611 * 612 * The padding is optional. The second image header should begin a 64k boundary. 613 */ 614 int prepend_bootloader() { 615 unsigned int buflen = 0; 616 int ret = 0, bootloader_padded = 0; 617 char *buf = 0, *p = 0; 618 struct file_info image; 619 620 /* calculate blocks to ensure padding */ 621 bootloader_padded = boot_info.file_size & (64 * 1024); 622 if (bootloader_padded < boot_info.file_size) 623 bootloader_padded += 64 * 1024; 624 625 image.file_name = ofname; 626 ret = get_file_stat(&image); 627 if (ret) { 628 ERR("Can not load the output image"); 629 return ret; 630 } 631 632 buflen = image.file_size + bootloader_padded + sizeof(struct fw_header); 633 buf = malloc(buflen); 634 if (buf == NULL) { 635 ERR("Can not allocate buffer %d bytes", buflen); 636 return -1; 637 } 638 memset(buf, 0xff, buflen); 639 640 /* load old image */ 641 p = buf + bootloader_padded + sizeof(struct fw_header); 642 ret = read_to_buf(&image, p); 643 if (ret) { 644 ERR("Can not read output image"); 645 goto out_free_buf; 646 } 647 648 p = buf + sizeof(struct fw_header); 649 ret = read_to_buf(&boot_info, p); 650 651 fill_header_bootloader(buf, buflen, 1); 652 653 ret = write_fw(ofname, buf, buflen); 654 if (ret) 655 goto out_free_buf; 656 657 ret = EXIT_SUCCESS; 658 659 out_free_buf: 660 free(buf); 661 662 return ret; 663 } 664 665 int main(int argc, char *argv[]) 666 { 667 int ret = EXIT_FAILURE; 668 669 progname = basename(argv[0]); 670 671 while ( 1 ) { 672 int c; 673 674 c = getopt(argc, argv, "a:b:H:E:F:L:V:N:W:w:ci:k:r:R:o:xhsjv:y:T:e"); 675 if (c == -1) 676 break; 677 678 switch (c) { 679 case 'a': 680 sscanf(optarg, "0x%x", &rootfs_align); 681 break; 682 case 'b': 683 boot_info.file_name = optarg; 684 break; 685 case 'H': 686 opt_hw_id = optarg; 687 break; 688 case 'E': 689 sscanf(optarg, "0x%x", &kernel_ep); 690 break; 691 case 'F': 692 layout_id = optarg; 693 break; 694 case 'W': 695 opt_hw_rev = optarg; 696 break; 697 case 'w': 698 opt_hw_ver_add = optarg; 699 break; 700 case 'L': 701 sscanf(optarg, "0x%x", &kernel_la); 702 break; 703 case 'V': 704 version = optarg; 705 break; 706 case 'v': 707 fw_ver = optarg; 708 break; 709 case 'y': 710 sver = optarg; 711 break; 712 case 'N': 713 vendor = optarg; 714 break; 715 case 'c': 716 combined++; 717 break; 718 case 'k': 719 kernel_info.file_name = optarg; 720 break; 721 case 'r': 722 rootfs_info.file_name = optarg; 723 break; 724 case 'R': 725 sscanf(optarg, "0x%x", &rootfs_ofs); 726 break; 727 case 'o': 728 ofname = optarg; 729 break; 730 case 's': 731 strip_padding = 1; 732 break; 733 case 'i': 734 inspect_info.file_name = optarg; 735 break; 736 case 'j': 737 add_jffs2_eof = 1; 738 break; 739 case 'x': 740 extract = 1; 741 break; 742 case 'T': 743 hdr_ver = atoi(optarg); 744 break; 745 case 'e': 746 custom_board.flags = FLAG_LE_KERNEL_LA_EP; 747 break; 748 case 'h': 749 usage(EXIT_SUCCESS); 750 break; 751 default: 752 usage(EXIT_FAILURE); 753 break; 754 } 755 } 756 757 ret = check_options(); 758 if (ret) 759 goto out; 760 761 if (!inspect_info.file_name) { 762 ret = build_fw(sizeof(struct fw_header)); 763 if (ret == 0 && boot_info.file_size > 0) 764 ret = prepend_bootloader(); 765 } 766 else 767 ret = inspect_fw(); 768 769 out: 770 return ret; 771 } 772
This page was automatically generated by LXR 0.3.1. • OpenWrt