• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/firmware-utils/src/mktplinkfw2.c

  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