2 * Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org>
4 * This tool was based on:
5 * TP-Link WR941 V2 firmware checksum fixing tool.
6 * Copyright (C) 2008,2009 Wang Jian <lark@linux.net.cn>
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License version 2 as published
10 * by the Free Software Foundation.
18 #include <unistd.h> /* for unlink() */
20 #include <getopt.h> /* for getopt() */
27 #include <arpa/inet.h>
28 #include <netinet/in.h>
30 #include "mktplinkfw-lib.h"
34 extern char *progname;
35 extern uint32_t kernel_len;
36 extern struct file_info kernel_info;
37 extern struct file_info rootfs_info;
38 extern struct flash_layout *layout;
39 extern uint32_t rootfs_ofs;
40 extern uint32_t rootfs_align;
42 extern int strip_padding;
43 extern int add_jffs2_eof;
45 static unsigned char jffs2_eof_mark[4] = {0xde, 0xad, 0xc0, 0xde};
47 void fill_header(char *buf, int len);
49 struct flash_layout *find_layout(struct flash_layout *layouts, const char *id)
51 struct flash_layout *ret;
52 struct flash_layout *l;
55 for (l = layouts; l->id != NULL; l++){
56 if (strcasecmp(id, l->id) == 0) {
65 void get_md5(const char *data, int size, uint8_t *md5)
70 MD5_Update(&ctx, data, size);
74 int get_file_stat(struct file_info *fdata)
79 if (fdata->file_name == NULL)
82 res = stat(fdata->file_name, &st);
84 ERRS("stat failed on %s", fdata->file_name);
88 fdata->file_size = st.st_size;
92 int read_to_buf(const struct file_info *fdata, char *buf)
95 int ret = EXIT_FAILURE;
97 f = fopen(fdata->file_name, "r");
99 ERRS("could not open \"%s\" for reading", fdata->file_name);
104 fread(buf, fdata->file_size, 1, f);
106 ERRS("unable to read from file \"%s\"", fdata->file_name);
118 static int pad_jffs2(char *buf, int currlen, int maxlen)
124 pad_mask = (4 * 1024) | (64 * 1024); /* EOF at 4KB and at 64KB */
125 while ((len < maxlen) && (pad_mask != 0)) {
129 for (i = 10; i < 32; i++) {
135 len = ALIGN(len, mask);
137 for (i = 10; i < 32; i++) {
139 if ((len & (mask - 1)) == 0)
143 for (i = 0; i < sizeof(jffs2_eof_mark); i++)
144 buf[len + i] = jffs2_eof_mark[i];
146 len += sizeof(jffs2_eof_mark);
152 int write_fw(const char *ofname, const char *data, int len)
155 int ret = EXIT_FAILURE;
157 f = fopen(ofname, "w");
159 ERRS("could not open \"%s\" for writing", ofname);
164 fwrite(data, len, 1, f);
166 ERRS("unable to write output file");
170 DBG("firmware file \"%s\" completed", ofname);
177 if (ret != EXIT_SUCCESS) {
184 /* Helper functions to inspect_fw() representing different output formats */
185 inline void inspect_fw_pstr(const char *label, const char *str)
187 printf("%-23s: %s\n", label, str);
190 inline void inspect_fw_phex(const char *label, uint32_t val)
192 printf("%-23s: 0x%08x\n", label, val);
195 inline void inspect_fw_phexdec(const char *label, uint32_t val)
197 printf("%-23s: 0x%08x / %8u bytes\n", label, val, val);
200 inline void inspect_fw_pmd5sum(const char *label, const uint8_t *val, const char *text)
204 printf("%-23s:", label);
205 for (i=0; i<MD5SUM_LEN; i++)
206 printf(" %02x", val[i]);
207 printf(" %s\n", text);
210 // header_size = sizeof(struct fw_header)
211 int build_fw(size_t header_size)
216 int ret = EXIT_FAILURE;
219 writelen = header_size + kernel_len;
224 buflen = layout->fw_max_len;
226 buf = malloc(buflen);
228 ERR("no memory for buffer\n");
232 memset(buf, 0xff, buflen);
233 p = buf + header_size;
234 ret = read_to_buf(&kernel_info, p);
239 p = buf + rootfs_ofs;
241 ret = read_to_buf(&rootfs_info, p);
245 writelen = rootfs_ofs + rootfs_info.file_size;
248 writelen = pad_jffs2(buf, writelen, layout->fw_max_len);
254 fill_header(buf, writelen);
255 ret = write_fw(ofname, buf, writelen);