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 = "16MLmtk", 154 .fw_max_len = 0xe90000, 155 .kernel_la = 0x80000000, 156 .kernel_ep = 0x80000000, 157 .rootfs_ofs = 0x140000, 158 }, { 159 .id = "16Mmtk", 160 .fw_max_len = 0xfa0000, 161 .kernel_la = 0x80000000, 162 .kernel_ep = 0x80000000, 163 .rootfs_ofs = 0x140000, 164 }, { 165 .id = "8MSUmtk", /* Split U-Boot OS */ 166 .fw_max_len = 0x770000, 167 .kernel_la = 0x80000000, 168 .kernel_ep = 0x80000000, 169 .rootfs_ofs = 0x140000, 170 }, { 171 .id = "8MLmtk", 172 .fw_max_len = 0x7b0000, 173 .kernel_la = 0x80000000, 174 .kernel_ep = 0x80000000, 175 .rootfs_ofs = 0x140000, 176 }, { 177 .id = "8Mqca", 178 .fw_max_len = 0x7a0000, 179 .kernel_la = 0x80060000, 180 .kernel_ep = 0x80060000, 181 .rootfs_ofs = 0x140000, 182 }, { 183 .id = "16Mqca", 184 .fw_max_len = 0xf90000, 185 .kernel_la = 0x80060000, 186 .kernel_ep = 0x80060000, 187 .rootfs_ofs = 0x140000, 188 }, { 189 /* terminating entry */ 190 } 191 }; 192 193 static void usage(int status) 194 { 195 FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout; 196 197 fprintf(stream, "Usage: %s [OPTIONS...]\n", progname); 198 fprintf(stream, 199 "\n" 200 "Options:\n" 201 " -c use combined kernel image\n" 202 " -e swap endianness in kernel load address and entry point\n" 203 " -E <ep> overwrite kernel entry point with <ep> (hexval prefixed with 0x)\n" 204 " -L <la> overwrite kernel load address with <la> (hexval prefixed with 0x)\n" 205 " -H <hwid> use hardware id specified with <hwid>\n" 206 " -W <hwrev> use hardware revision specified with <hwrev>\n" 207 " -w <hwveradd> use additional hardware version specified with <hwveradd>\n" 208 " -F <id> use flash layout specified with <id>\n" 209 " -k <file> read kernel image from the file <file>\n" 210 " -r <file> read rootfs image from the file <file>\n" 211 " -b <file> read bootloader image from the file <file>\n" 212 " -a <align> align the rootfs start on an <align> bytes boundary\n" 213 " -R <offset> overwrite rootfs offset with <offset> (hexval prefixed with 0x)\n" 214 " -o <file> write output to the file <file>\n" 215 " -s strip padding from the end of the image\n" 216 " -j add jffs2 end-of-filesystem markers\n" 217 " -N <vendor> set image vendor to <vendor>\n" 218 " -T <version> set header version to <version>\n" 219 " -V <version> set image version to <version>\n" 220 " -v <version> set firmware version to <version>\n" 221 " -y <version> set secondary version to <version>\n" 222 " -i <file> inspect given firmware file <file>\n" 223 " -x extract bootloader, kernel and rootfs while inspecting (requires -i)\n" 224 " -h show this screen\n" 225 ); 226 227 exit(status); 228 } 229 230 static int check_options(void) 231 { 232 int ret; 233 int exceed_bytes; 234 235 if (inspect_info.file_name) { 236 ret = get_file_stat(&inspect_info); 237 if (ret) 238 return ret; 239 240 return 0; 241 } else if (extract) { 242 ERR("no firmware for inspection specified"); 243 return -1; 244 } 245 246 if (opt_hw_id == NULL) { 247 ERR("hardware id must be specified"); 248 return -1; 249 } 250 251 board = &custom_board; 252 253 if (layout_id == NULL) { 254 ERR("flash layout is not specified"); 255 return -1; 256 } 257 258 board->hw_id = strtoul(opt_hw_id, NULL, 0); 259 260 board->hw_rev = 1; 261 board->hw_ver_add = 0; 262 263 if (opt_hw_rev) 264 board->hw_rev = strtoul(opt_hw_rev, NULL, 0); 265 if (opt_hw_ver_add) 266 board->hw_ver_add = strtoul(opt_hw_ver_add, NULL, 0); 267 268 layout = find_layout(layouts, layout_id); 269 if (layout == NULL) { 270 ERR("unknown flash layout \"%s\"", layout_id); 271 return -1; 272 } 273 274 if (!kernel_la) 275 kernel_la = layout->kernel_la; 276 if (!kernel_ep) 277 kernel_ep = layout->kernel_ep; 278 if (!rootfs_ofs) 279 rootfs_ofs = layout->rootfs_ofs; 280 281 /* check bootloader */ 282 ret = get_file_stat(&boot_info); 283 if (ret) { 284 ERR("Can not load bootloader image."); 285 return ret; 286 } 287 288 if (boot_info.file_size > 2 * 64 * 1024) { 289 /* the offset in fill_header is hardcoded to 128k */ 290 ERR("Bootloader image is bigger than 128k."); 291 return -1; 292 } 293 294 if (kernel_info.file_name == NULL) { 295 ERR("no kernel image specified"); 296 return -1; 297 } 298 ret = get_file_stat(&kernel_info); 299 if (ret) 300 return ret; 301 302 kernel_len = kernel_info.file_size; 303 304 if (combined) { 305 if (kernel_info.file_size > 306 layout->fw_max_len - sizeof(struct fw_header)) { 307 ERR("kernel image is too big"); 308 return -1; 309 } 310 } else { 311 if (rootfs_info.file_name == NULL) { 312 ERR("no rootfs image specified"); 313 return -1; 314 } 315 316 ret = get_file_stat(&rootfs_info); 317 if (ret) 318 return ret; 319 320 if (rootfs_align) { 321 kernel_len += sizeof(struct fw_header); 322 rootfs_ofs = ALIGN(kernel_len, rootfs_align); 323 kernel_len -= sizeof(struct fw_header); 324 325 DBG("rootfs offset aligned to 0x%u", rootfs_ofs); 326 327 exceed_bytes = (kernel_len + rootfs_info.file_size) - 328 (layout->fw_max_len - sizeof(struct fw_header)); 329 if (exceed_bytes > 0) { 330 ERR("images are too big by %i bytes", exceed_bytes); 331 return -1; 332 } 333 } else { 334 exceed_bytes = kernel_info.file_size - 335 (rootfs_ofs - sizeof(struct fw_header)); 336 if (exceed_bytes > 0) { 337 ERR("images are too big by %i bytes", exceed_bytes); 338 return -1; 339 } 340 341 exceed_bytes = rootfs_info.file_size - 342 (layout->fw_max_len - rootfs_ofs); 343 if (exceed_bytes > 0) { 344 ERR("images are too big by %i bytes", exceed_bytes); 345 return -1; 346 } 347 } 348 } 349 350 if (ofname == NULL) { 351 ERR("no output file specified"); 352 return -1; 353 } 354 355 ret = sscanf(fw_ver, "%d.%d.%d", &fw_ver_hi, &fw_ver_mid, &fw_ver_lo); 356 if (ret != 3) { 357 ERR("invalid firmware version '%s'", fw_ver); 358 return -1; 359 } 360 361 ret = sscanf(sver, "%d.%d", &sver_hi, &sver_lo); 362 if (ret != 2) { 363 ERR("invalid secondary version '%s'", sver); 364 return -1; 365 } 366 367 return 0; 368 } 369 370 void fill_header_bootloader(char *buf, int len, int with_bootloader) 371 { 372 struct fw_header *hdr = (struct fw_header *)buf; 373 unsigned ver_len; 374 unsigned int offset = 0; 375 376 if (with_bootloader) { 377 /* ensure the bootloader is padded to 64k */ 378 offset = boot_info.file_size & (64 * 1024); 379 if (offset < boot_info.file_size) 380 offset += 64 * 1024; 381 382 offset += sizeof(struct fw_header); 383 } 384 385 memset(hdr, '\xff', sizeof(struct fw_header)); 386 387 hdr->version = htonl(bswap_32(hdr_ver)); 388 ver_len = strlen(version); 389 if (ver_len > (sizeof(hdr->fw_version) - 1)) 390 ver_len = sizeof(hdr->fw_version) - 1; 391 392 memcpy(hdr->fw_version, version, ver_len); 393 hdr->fw_version[ver_len] = 0; 394 395 hdr->hw_id = htonl(board->hw_id); 396 hdr->hw_rev = htonl(board->hw_rev); 397 hdr->hw_ver_add = htonl(board->hw_ver_add); 398 399 if (boot_info.file_size == 0 || !with_bootloader) { 400 memcpy(hdr->md5sum1, md5salt_normal, sizeof(hdr->md5sum1)); 401 hdr->boot_ofs = htonl(0); 402 hdr->boot_len = htonl(0); 403 } else { 404 memcpy(hdr->md5sum1, md5salt_boot, sizeof(hdr->md5sum1)); 405 hdr->boot_ofs = htonl(0); 406 hdr->boot_len = htonl(boot_info.file_size); 407 } 408 409 hdr->kernel_la = htonl(kernel_la); 410 hdr->kernel_ep = htonl(kernel_ep); 411 hdr->fw_length = htonl(layout->fw_max_len + offset); 412 hdr->kernel_ofs = htonl(sizeof(struct fw_header) + offset); 413 hdr->kernel_len = htonl(kernel_len); 414 if (!combined) { 415 /* even the bootloader doesnt increased the root_ofs. Unsure if this parser 416 * always ignores the rootfs or only in the 841v13 417 */ 418 hdr->rootfs_ofs = htonl(rootfs_ofs); 419 hdr->rootfs_len = htonl(rootfs_info.file_size); 420 } 421 422 hdr->unk2 = htonl(0); 423 hdr->unk3 = htonl(0xffffffff); 424 hdr->unk4 = htons(0x55aa); 425 hdr->unk5 = 0xa5; 426 427 hdr->sver_hi = sver_hi; 428 hdr->sver_lo = sver_lo; 429 430 hdr->ver_hi = fw_ver_hi; 431 hdr->ver_mid = fw_ver_mid; 432 hdr->ver_lo = fw_ver_lo; 433 434 if (board->flags & FLAG_LE_KERNEL_LA_EP) { 435 hdr->kernel_la = bswap_32(hdr->kernel_la); 436 hdr->kernel_ep = bswap_32(hdr->kernel_ep); 437 } 438 439 get_md5(buf, len, hdr->md5sum1); 440 } 441 442 /* fill_header get called by mktplinkfw_lib to fill the header in front of the kernel. */ 443 void fill_header(char *buf, int len) { 444 fill_header_bootloader(buf, len, 0); 445 } 446 447 static int inspect_fw(void) 448 { 449 char *buf; 450 struct fw_header *hdr; 451 uint8_t md5sum[MD5SUM_LEN]; 452 struct board_info *board; 453 int ret = EXIT_FAILURE; 454 455 buf = malloc(inspect_info.file_size); 456 if (!buf) { 457 ERR("no memory for buffer!\n"); 458 goto out; 459 } 460 461 ret = read_to_buf(&inspect_info, buf); 462 if (ret) 463 goto out_free_buf; 464 hdr = (struct fw_header *)buf; 465 466 board = &custom_board; 467 468 if (board->flags & FLAG_LE_KERNEL_LA_EP) { 469 hdr->kernel_la = bswap_32(hdr->kernel_la); 470 hdr->kernel_ep = bswap_32(hdr->kernel_ep); 471 } 472 473 inspect_fw_pstr("File name", inspect_info.file_name); 474 inspect_fw_phexdec("File size", inspect_info.file_size); 475 476 switch(bswap_32(ntohl(hdr->version))) { 477 case 2: 478 case 3: 479 break; 480 default: 481 ERR("file does not seem to have V2/V3 header!\n"); 482 goto out_free_buf; 483 } 484 485 inspect_fw_phexdec("Version 2 Header size", sizeof(struct fw_header)); 486 487 memcpy(md5sum, hdr->md5sum1, sizeof(md5sum)); 488 if (ntohl(hdr->boot_len) == 0) 489 memcpy(hdr->md5sum1, md5salt_normal, sizeof(md5sum)); 490 else 491 memcpy(hdr->md5sum1, md5salt_boot, sizeof(md5sum)); 492 get_md5(buf, inspect_info.file_size, hdr->md5sum1); 493 494 if (memcmp(md5sum, hdr->md5sum1, sizeof(md5sum))) { 495 inspect_fw_pmd5sum("Header MD5Sum1", md5sum, "(*ERROR*)"); 496 inspect_fw_pmd5sum(" --> expected", hdr->md5sum1, ""); 497 } else { 498 inspect_fw_pmd5sum("Header MD5Sum1", md5sum, "(ok)"); 499 } 500 if (ntohl(hdr->unk2) != 0) 501 inspect_fw_phexdec("Unknown value 2", hdr->unk2); 502 inspect_fw_pmd5sum("Header MD5Sum2", hdr->md5sum2, 503 "(purpose yet unknown, unchecked here)"); 504 505 if (ntohl(hdr->unk3) != 0xffffffff) 506 inspect_fw_phexdec("Unknown value 3", hdr->unk3); 507 508 if (ntohs(hdr->unk4) != 0x55aa) 509 inspect_fw_phexdec("Unknown value 4", hdr->unk4); 510 511 if (hdr->unk5 != 0xa5) 512 inspect_fw_phexdec("Unknown value 5", hdr->unk5); 513 514 printf("\n"); 515 516 inspect_fw_pstr("Firmware version", hdr->fw_version); 517 inspect_fw_phex("Hardware ID", ntohl(hdr->hw_id)); 518 inspect_fw_phex("Hardware Revision", 519 ntohl(hdr->hw_rev)); 520 inspect_fw_phex("Additional HW Version", 521 ntohl(hdr->hw_ver_add)); 522 523 printf("%-23s: %d.%d.%d-%d.%d\n", "Software version", 524 hdr->ver_hi, hdr->ver_mid, hdr->ver_lo, 525 hdr->sver_hi, hdr->sver_lo); 526 527 printf("\n"); 528 529 inspect_fw_phexdec("Kernel data offset", 530 ntohl(hdr->kernel_ofs)); 531 inspect_fw_phexdec("Kernel data length", 532 ntohl(hdr->kernel_len)); 533 inspect_fw_phex("Kernel load address", 534 ntohl(hdr->kernel_la)); 535 inspect_fw_phex("Kernel entry point", 536 ntohl(hdr->kernel_ep)); 537 inspect_fw_phexdec("Rootfs data offset", 538 ntohl(hdr->rootfs_ofs)); 539 inspect_fw_phexdec("Rootfs data length", 540 ntohl(hdr->rootfs_len)); 541 inspect_fw_phexdec("Boot loader data offset", 542 ntohl(hdr->boot_ofs)); 543 inspect_fw_phexdec("Boot loader data length", 544 ntohl(hdr->boot_len)); 545 inspect_fw_phexdec("Total firmware length", 546 ntohl(hdr->fw_length)); 547 548 if (extract) { 549 FILE *fp; 550 char *filename; 551 552 printf("\n"); 553 554 if (hdr->boot_len) { 555 filename = malloc(strlen(inspect_info.file_name) + 8); 556 sprintf(filename, "%s-bootloader", inspect_info.file_name); 557 printf("Extracting bootloader to \"%s\"...\n", filename); 558 fp = fopen(filename, "w"); 559 if (fp) { 560 if (!fwrite(buf + sizeof(struct fw_header) + ntohl(hdr->boot_ofs), 561 ntohl(hdr->boot_len), 1, fp)) { 562 ERR("error in fwrite(): %s", strerror(errno)); 563 } 564 fclose(fp); 565 } else { 566 ERR("error in fopen(): %s", strerror(errno)); 567 } 568 free(filename); 569 } 570 571 filename = malloc(strlen(inspect_info.file_name) + 8); 572 sprintf(filename, "%s-kernel", inspect_info.file_name); 573 printf("Extracting kernel to \"%s\"...\n", filename); 574 fp = fopen(filename, "w"); 575 if (fp) { 576 if (!fwrite(buf + ntohl(hdr->kernel_ofs), 577 ntohl(hdr->kernel_len), 1, fp)) { 578 ERR("error in fwrite(): %s", strerror(errno)); 579 } 580 fclose(fp); 581 } else { 582 ERR("error in fopen(): %s", strerror(errno)); 583 } 584 free(filename); 585 586 filename = malloc(strlen(inspect_info.file_name) + 8); 587 sprintf(filename, "%s-rootfs", inspect_info.file_name); 588 printf("Extracting rootfs to \"%s\"...\n", filename); 589 fp = fopen(filename, "w"); 590 if (fp) { 591 if (!fwrite(buf + ntohl(hdr->rootfs_ofs), 592 ntohl(hdr->rootfs_len), 1, fp)) { 593 ERR("error in fwrite(): %s", strerror(errno)); 594 } 595 fclose(fp); 596 } else { 597 ERR("error in fopen(): %s", strerror(errno)); 598 } 599 free(filename); 600 } 601 602 out_free_buf: 603 free(buf); 604 out: 605 return ret; 606 } 607 608 /* prepend a second image header and the bootloader. 609 * 610 * |------------| 611 * |image header| 612 * |------------| 613 * |bootloader | 614 * |------------| 615 * |optional pad| 616 * |------------| 617 * |image header| 618 * |------------| 619 * |kernel image| 620 * |------------| 621 * |rootfs image| 622 * |------------| 623 * 624 * The padding is optional. The second image header should begin a 64k boundary. 625 */ 626 int prepend_bootloader() { 627 unsigned int buflen = 0; 628 int ret = 0, bootloader_padded = 0; 629 char *buf = 0, *p = 0; 630 struct file_info image; 631 632 /* calculate blocks to ensure padding */ 633 bootloader_padded = boot_info.file_size & (64 * 1024); 634 if (bootloader_padded < boot_info.file_size) 635 bootloader_padded += 64 * 1024; 636 637 image.file_name = ofname; 638 ret = get_file_stat(&image); 639 if (ret) { 640 ERR("Can not load the output image"); 641 return ret; 642 } 643 644 buflen = image.file_size + bootloader_padded + sizeof(struct fw_header); 645 buf = malloc(buflen); 646 if (buf == NULL) { 647 ERR("Can not allocate buffer %d bytes", buflen); 648 return -1; 649 } 650 memset(buf, 0xff, buflen); 651 652 /* load old image */ 653 p = buf + bootloader_padded + sizeof(struct fw_header); 654 ret = read_to_buf(&image, p); 655 if (ret) { 656 ERR("Can not read output image"); 657 goto out_free_buf; 658 } 659 660 p = buf + sizeof(struct fw_header); 661 ret = read_to_buf(&boot_info, p); 662 663 fill_header_bootloader(buf, buflen, 1); 664 665 ret = write_fw(ofname, buf, buflen); 666 if (ret) 667 goto out_free_buf; 668 669 ret = EXIT_SUCCESS; 670 671 out_free_buf: 672 free(buf); 673 674 return ret; 675 } 676 677 int main(int argc, char *argv[]) 678 { 679 int ret = EXIT_FAILURE; 680 681 progname = basename(argv[0]); 682 683 while ( 1 ) { 684 int c; 685 686 c = getopt(argc, argv, "a:b:H:E:F:L:V:N:W:w:ci:k:r:R:o:xhsjv:y:T:e"); 687 if (c == -1) 688 break; 689 690 switch (c) { 691 case 'a': 692 sscanf(optarg, "0x%x", &rootfs_align); 693 break; 694 case 'b': 695 boot_info.file_name = optarg; 696 break; 697 case 'H': 698 opt_hw_id = optarg; 699 break; 700 case 'E': 701 sscanf(optarg, "0x%x", &kernel_ep); 702 break; 703 case 'F': 704 layout_id = optarg; 705 break; 706 case 'W': 707 opt_hw_rev = optarg; 708 break; 709 case 'w': 710 opt_hw_ver_add = optarg; 711 break; 712 case 'L': 713 sscanf(optarg, "0x%x", &kernel_la); 714 break; 715 case 'V': 716 version = optarg; 717 break; 718 case 'v': 719 fw_ver = optarg; 720 break; 721 case 'y': 722 sver = optarg; 723 break; 724 case 'N': 725 vendor = optarg; 726 break; 727 case 'c': 728 combined++; 729 break; 730 case 'k': 731 kernel_info.file_name = optarg; 732 break; 733 case 'r': 734 rootfs_info.file_name = optarg; 735 break; 736 case 'R': 737 sscanf(optarg, "0x%x", &rootfs_ofs); 738 break; 739 case 'o': 740 ofname = optarg; 741 break; 742 case 's': 743 strip_padding = 1; 744 break; 745 case 'i': 746 inspect_info.file_name = optarg; 747 break; 748 case 'j': 749 add_jffs2_eof = 1; 750 break; 751 case 'x': 752 extract = 1; 753 break; 754 case 'T': 755 hdr_ver = atoi(optarg); 756 break; 757 case 'e': 758 custom_board.flags = FLAG_LE_KERNEL_LA_EP; 759 break; 760 case 'h': 761 usage(EXIT_SUCCESS); 762 break; 763 default: 764 usage(EXIT_FAILURE); 765 break; 766 } 767 } 768 769 ret = check_options(); 770 if (ret) 771 goto out; 772 773 if (!inspect_info.file_name) { 774 ret = build_fw(sizeof(struct fw_header)); 775 if (ret == 0 && boot_info.file_size > 0) 776 ret = prepend_bootloader(); 777 } 778 else 779 ret = inspect_fw(); 780 781 out: 782 return ret; 783 } 784
This page was automatically generated by LXR 0.3.1. • OpenWrt