#define ALIGN(x,a) ({ typeof(a) __a = (a); (((x) + __a - 1) & ~(__a - 1)); })
#define HEADER_VERSION_V1 0x01000000
-#define HEADER_VERSION_V2 0x02000000
+#define HWID_GL_INET_V1 0x08000001
+#define HWID_GS_OOLITE_V1 0x3C000101
#define HWID_TL_MR10U_V1 0x00100101
+#define HWID_TL_MR13U_V1 0x00130101
#define HWID_TL_MR3020_V1 0x30200001
#define HWID_TL_MR3220_V1 0x32200001
#define HWID_TL_MR3220_V2 0x32200002
#define HWID_TL_WA801ND_V1 0x08010001
#define HWID_TL_WA830RE_V1 0x08300010
#define HWID_TL_WA830RE_V2 0x08300002
+#define HWID_TL_WA801ND_V2 0x08010002
#define HWID_TL_WA901ND_V1 0x09010001
#define HWID_TL_WA901ND_V2 0x09010002
+#define HWID_TL_WDR4300_V1_IL 0x43008001
#define HWID_TL_WDR4900_V1 0x49000001
#define HWID_TL_WR703N_V1 0x07030101
#define HWID_TL_WR720N_V3 0x07200103
#define HWID_TL_WR941ND_V2 0x09410002
#define HWID_TL_WR941ND_V4 0x09410004
#define HWID_TL_WR1043ND_V1 0x10430001
+#define HWID_TL_WR1043ND_V2 0x10430002
#define HWID_TL_WR1041N_V2 0x10410002
#define HWID_TL_WR2543N_V1 0x25430001
uint8_t pad[354];
} __attribute__ ((packed));
-struct fw_header_v2 {
- uint32_t version; /* header version */
- char fw_version[48];
- uint32_t hw_id; /* hardware id */
- uint32_t hw_rev; /* hardware revision */
- uint32_t unk1;
- uint8_t md5sum1[MD5SUM_LEN];
- uint32_t unk2;
- uint8_t md5sum2[MD5SUM_LEN];
- uint32_t unk3;
- uint32_t kernel_la; /* kernel load address */
- uint32_t kernel_ep; /* kernel entry point */
- uint32_t fw_length; /* total length of the firmware */
- uint32_t kernel_ofs; /* kernel data offset */
- uint32_t kernel_len; /* kernel data length */
- uint32_t rootfs_ofs; /* rootfs data offset */
- uint32_t rootfs_len; /* rootfs data length */
- uint32_t boot_ofs; /* bootloader data offset */
- uint32_t boot_len; /* bootloader data length */
- uint16_t ver_hi;
- uint16_t ver_mid;
- uint16_t ver_lo;
- uint8_t pad[366];
-} __attribute__ ((packed));
-
struct flash_layout {
char *id;
uint32_t fw_max_len;
uint32_t hw_id;
uint32_t hw_rev;
char *layout_id;
- uint32_t hdr_version
};
/*
static int strip_padding;
static int add_jffs2_eof;
static unsigned char jffs2_eof_mark[4] = {0xde, 0xad, 0xc0, 0xde};
+static uint32_t fw_max_len;
+static uint32_t reserved_space;
static struct file_info inspect_info;
static int extract = 0;
.kernel_la = 0x80060000,
.kernel_ep = 0x80060000,
.rootfs_ofs = 0x100000,
+ }, {
+ .id = "16M",
+ .fw_max_len = 0xf80000,
+ .kernel_la = 0x80060000,
+ .kernel_ep = 0x80060000,
+ .rootfs_ofs = 0x140000,
+ }, {
+ .id = "16Mlzma",
+ .fw_max_len = 0xf80000,
+ .kernel_la = 0x80060000,
+ .kernel_ep = 0x80060000,
+ .rootfs_ofs = 0x100000,
}, {
.id = "16Mppc",
.fw_max_len = 0xf80000,
.hw_id = HWID_TL_MR10U_V1,
.hw_rev = 1,
.layout_id = "4Mlzma",
+ }, {
+ .id = "TL-MR13Uv1",
+ .hw_id = HWID_TL_MR13U_V1,
+ .hw_rev = 1,
+ .layout_id = "4Mlzma",
}, {
.id = "TL-MR3020v1",
.hw_id = HWID_TL_MR3020_V1,
.hw_id = HWID_TL_WA830RE_V2,
.hw_rev = 1,
.layout_id = "4M",
+ }, {
+ .id = "TL-WA801NDv2",
+ .hw_id = HWID_TL_WA801ND_V2,
+ .hw_rev = 1,
+ .layout_id = "4Mlzma",
}, {
.id = "TL-WA901NDv1",
.hw_id = HWID_TL_WA901ND_V1,
.hw_id = HWID_TL_WA901ND_V2,
.hw_rev = 1,
.layout_id = "4M",
+ }, {
+ .id = "TL-WDR4300v1",
+ .hw_id = HWID_TL_WDR4300_V1_IL,
+ .hw_rev = 1,
+ .layout_id = "8Mlzma",
}, {
.id = "TL-WDR4900v1",
.hw_id = HWID_TL_WDR4900_V1,
.hw_id = HWID_TL_WR1043ND_V1,
.hw_rev = 1,
.layout_id = "8M",
+ }, {
+ .id = "TL-WR1043NDv2",
+ .hw_id = HWID_TL_WR1043ND_V2,
+ .hw_rev = 1,
+ .layout_id = "8Mlzma",
}, {
.id = "TL-WR2543Nv1",
.hw_id = HWID_TL_WR2543N_V1,
.hw_id = HWID_TL_WR720N_V3,
.hw_rev = 1,
.layout_id = "4Mlzma",
+ }, {
+ .id = "GL-INETv1",
+ .hw_id = HWID_GL_INET_V1,
+ .hw_rev = 1,
+ .layout_id = "8Mlzma",
+ }, {
+ .id = "GS-OOLITEv1",
+ .hw_id = HWID_GS_OOLITE_V1,
+ .hw_rev = 1,
+ .layout_id = "16Mlzma",
}, {
/* terminating entry */
}
" -v <version> set firmware version to <version>\n"
" -i <file> inspect given firmware file <file>\n"
" -x extract kernel and rootfs while inspecting (requires -i)\n"
+" -X <size> reserve <size> bytes in the firmware image (hexval prefixed with 0x)\n"
" -h show this screen\n"
);
if (!rootfs_ofs)
rootfs_ofs = layout->rootfs_ofs;
+ if (reserved_space > layout->fw_max_len) {
+ ERR("reserved space is not valid");
+ return -1;
+ }
+
+ fw_max_len = layout->fw_max_len - reserved_space;
+
if (kernel_info.file_name == NULL) {
ERR("no kernel image specified");
return -1;
if (combined) {
if (kernel_info.file_size >
- layout->fw_max_len - sizeof(struct fw_header)) {
+ fw_max_len - sizeof(struct fw_header)) {
ERR("kernel image is too big");
return -1;
}
DBG("kernel length aligned to %u", kernel_len);
if (kernel_len + rootfs_info.file_size >
- layout->fw_max_len - sizeof(struct fw_header)) {
+ fw_max_len - sizeof(struct fw_header)) {
ERR("images are too big");
return -1;
}
}
if (rootfs_info.file_size >
- (layout->fw_max_len - rootfs_ofs)) {
+ (fw_max_len - rootfs_ofs)) {
ERR("rootfs image is too big");
return -1;
}
get_md5(buf, len, hdr->md5sum1);
}
-static void fill_header_v2(char *buf, int len)
-{
- struct fw_header_v2 *hdr = (struct fw_header_v2 *)buf;
-
- memset(hdr, 0, sizeof(struct fw_header_v2));
-
- hdr->version = htonl(HEADER_VERSION_V2);
- memset(hdr->fw_version, 0xff, sizeof(hdr->fw_version));
- strncpy(hdr->fw_version, version, strlen(version));
- hdr->hw_id = htonl(hw_id);
- hdr->hw_rev = htonl(hw_rev);
-
- if (boot_info.file_size == 0)
- memcpy(hdr->md5sum1, md5salt_normal, sizeof(hdr->md5sum1));
- else
- memcpy(hdr->md5sum1, md5salt_boot, sizeof(hdr->md5sum1));
-
- hdr->kernel_la = htonl(kernel_la);
- hdr->kernel_ep = htonl(kernel_ep);
- hdr->fw_length = htonl(layout->fw_max_len);
- hdr->kernel_ofs = htonl(sizeof(struct fw_header_v2));
- hdr->kernel_len = htonl(kernel_len);
- if (!combined) {
- hdr->rootfs_ofs = htonl(rootfs_ofs);
- hdr->rootfs_len = htonl(rootfs_info.file_size);
- }
-
- hdr->ver_hi = htons(fw_ver_hi);
- hdr->ver_mid = htons(fw_ver_mid);
- hdr->ver_lo = htons(fw_ver_lo);
-
- get_md5(buf, len, hdr->md5sum1);
-}
-
static int pad_jffs2(char *buf, int currlen)
{
int len;
char *p;
int ret = EXIT_FAILURE;
int writelen = 0;
- int hdr_len;
- if (board->hdr_version == HEADER_VERSION_V2)
- hdr_len = sizeof(struct fw_header_v2);
- else
- hdr_len = sizeof(struct fw_header);
buflen = layout->fw_max_len;
}
memset(buf, 0xff, buflen);
- p = buf + hdr_len;
+ p = buf + sizeof(struct fw_header);
ret = read_to_buf(&kernel_info, p);
if (ret)
goto out_free_buf;
- writelen = hdr_len + kernel_len;
+ writelen = sizeof(struct fw_header) + kernel_len;
if (!combined) {
if (rootfs_align)
if (!strip_padding)
writelen = buflen;
- if (board->hdr_version == HEADER_VERSION_V2)
- fill_header_v2(buf, writelen);
- else
- fill_header(buf, writelen);
+ fill_header(buf, writelen);
ret = write_fw(buf, writelen);
if (ret)
goto out_free_buf;
while ( 1 ) {
int c;
- c = getopt(argc, argv, "a:B:H:E:F:L:V:N:W:ci:k:r:R:o:xhsjv:");
+ c = getopt(argc, argv, "a:B:H:E:F:L:V:N:W:ci:k:r:R:o:xX:hsjv:");
if (c == -1)
break;
case 'h':
usage(EXIT_SUCCESS);
break;
+ case 'X':
+ sscanf(optarg, "0x%x", &reserved_space);
+ break;
default:
usage(EXIT_FAILURE);
break;