1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org>
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>
14 #include <unistd.h> /* for unlink() */
16 #include <getopt.h> /* for getopt() */
23 #include <arpa/inet.h>
24 #include <netinet/in.h>
26 #include "mktplinkfw-lib.h"
30 extern char *progname
;
31 extern uint32_t kernel_len
;
32 extern struct file_info kernel_info
;
33 extern struct file_info rootfs_info
;
34 extern struct flash_layout
*layout
;
35 extern uint32_t rootfs_ofs
;
36 extern uint32_t rootfs_align
;
38 extern int strip_padding
;
39 extern int add_jffs2_eof
;
41 static unsigned char jffs2_eof_mark
[4] = {0xde, 0xad, 0xc0, 0xde};
43 void fill_header(char *buf
, int len
);
45 struct flash_layout
*find_layout(struct flash_layout
*layouts
, const char *id
)
47 struct flash_layout
*ret
;
48 struct flash_layout
*l
;
51 for (l
= layouts
; l
->id
!= NULL
; l
++){
52 if (strcasecmp(id
, l
->id
) == 0) {
61 void get_md5(const char *data
, int size
, uint8_t *md5
)
66 MD5_Update(&ctx
, data
, size
);
70 int get_file_stat(struct file_info
*fdata
)
75 if (fdata
->file_name
== NULL
)
78 res
= stat(fdata
->file_name
, &st
);
80 ERRS("stat failed on %s", fdata
->file_name
);
84 fdata
->file_size
= st
.st_size
;
88 int read_to_buf(const struct file_info
*fdata
, char *buf
)
91 int ret
= EXIT_FAILURE
;
93 f
= fopen(fdata
->file_name
, "r");
95 ERRS("could not open \"%s\" for reading", fdata
->file_name
);
100 fread(buf
, fdata
->file_size
, 1, f
);
102 ERRS("unable to read from file \"%s\"", fdata
->file_name
);
114 static int pad_jffs2(char *buf
, int currlen
, int maxlen
)
120 pad_mask
= (4 * 1024) | (64 * 1024); /* EOF at 4KB and at 64KB */
121 while ((len
< maxlen
) && (pad_mask
!= 0)) {
125 for (i
= 10; i
< 32; i
++) {
131 len
= ALIGN(len
, mask
);
133 for (i
= 10; i
< 32; i
++) {
135 if ((len
& (mask
- 1)) == 0)
139 for (i
= 0; i
< sizeof(jffs2_eof_mark
); i
++)
140 buf
[len
+ i
] = jffs2_eof_mark
[i
];
142 len
+= sizeof(jffs2_eof_mark
);
148 int write_fw(const char *ofname
, const char *data
, int len
)
151 int ret
= EXIT_FAILURE
;
153 f
= fopen(ofname
, "w");
155 ERRS("could not open \"%s\" for writing", ofname
);
160 fwrite(data
, len
, 1, f
);
162 ERRS("unable to write output file");
166 DBG("firmware file \"%s\" completed", ofname
);
173 if (ret
!= EXIT_SUCCESS
) {
180 /* Helper functions to inspect_fw() representing different output formats */
181 inline void inspect_fw_pstr(const char *label
, const char *str
)
183 printf("%-23s: %s\n", label
, str
);
186 inline void inspect_fw_phex(const char *label
, uint32_t val
)
188 printf("%-23s: 0x%08x\n", label
, val
);
191 inline void inspect_fw_phexdec(const char *label
, uint32_t val
)
193 printf("%-23s: 0x%08x / %8u bytes\n", label
, val
, val
);
196 inline void inspect_fw_pmd5sum(const char *label
, const uint8_t *val
, const char *text
)
200 printf("%-23s:", label
);
201 for (i
=0; i
<MD5SUM_LEN
; i
++)
202 printf(" %02x", val
[i
]);
203 printf(" %s\n", text
);
206 // header_size = sizeof(struct fw_header)
207 int build_fw(size_t header_size
)
212 int ret
= EXIT_FAILURE
;
215 writelen
= header_size
+ kernel_len
;
220 buflen
= layout
->fw_max_len
;
222 buf
= malloc(buflen
);
224 ERR("no memory for buffer\n");
228 memset(buf
, 0xff, buflen
);
229 p
= buf
+ header_size
;
230 ret
= read_to_buf(&kernel_info
, p
);
235 p
= buf
+ rootfs_ofs
;
237 ret
= read_to_buf(&rootfs_info
, p
);
241 writelen
= rootfs_ofs
+ rootfs_info
.file_size
;
244 writelen
= pad_jffs2(buf
, writelen
, layout
->fw_max_len
);
250 fill_header(buf
, writelen
);
251 ret
= write_fw(ofname
, buf
, writelen
);