firmware-utils: mktplinkfw: add support for TP-Link's new region codes
TP-Link has changed the way the region is stored in the firmware header, and now provides US- and EU-specific images for the Archer C7. Adding the new region codes is necessary to make LEDE/OpenWrt flashable on devices with the new stock firmwares again. Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>
This commit is contained in:
parent
02e3c718e9
commit
a4fc62bc0e
1 changed files with 37 additions and 32 deletions
|
@ -46,7 +46,7 @@ struct fw_header {
|
||||||
char fw_version[36];
|
char fw_version[36];
|
||||||
uint32_t hw_id; /* hardware id */
|
uint32_t hw_id; /* hardware id */
|
||||||
uint32_t hw_rev; /* hardware revision */
|
uint32_t hw_rev; /* hardware revision */
|
||||||
uint32_t region; /* region code */
|
uint32_t region_code; /* region code */
|
||||||
uint8_t md5sum1[MD5SUM_LEN];
|
uint8_t md5sum1[MD5SUM_LEN];
|
||||||
uint32_t unk2;
|
uint32_t unk2;
|
||||||
uint8_t md5sum2[MD5SUM_LEN];
|
uint8_t md5sum2[MD5SUM_LEN];
|
||||||
|
@ -63,7 +63,10 @@ struct fw_header {
|
||||||
uint16_t ver_hi;
|
uint16_t ver_hi;
|
||||||
uint16_t ver_mid;
|
uint16_t ver_mid;
|
||||||
uint16_t ver_lo;
|
uint16_t ver_lo;
|
||||||
uint8_t pad[354];
|
uint8_t pad[130];
|
||||||
|
char region_str1[32];
|
||||||
|
char region_str2[32];
|
||||||
|
uint8_t pad2[160];
|
||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
struct flash_layout {
|
struct flash_layout {
|
||||||
|
@ -74,6 +77,12 @@ struct flash_layout {
|
||||||
uint32_t rootfs_ofs;
|
uint32_t rootfs_ofs;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct fw_region {
|
||||||
|
char name[4];
|
||||||
|
uint32_t code;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Globals
|
* Globals
|
||||||
*/
|
*/
|
||||||
|
@ -92,7 +101,7 @@ static char *opt_hw_rev;
|
||||||
static uint32_t hw_rev;
|
static uint32_t hw_rev;
|
||||||
static uint32_t opt_hdr_ver = 1;
|
static uint32_t opt_hdr_ver = 1;
|
||||||
static char *country;
|
static char *country;
|
||||||
static uint32_t region;
|
static const struct fw_region *region;
|
||||||
static int fw_ver_lo;
|
static int fw_ver_lo;
|
||||||
static int fw_ver_mid;
|
static int fw_ver_mid;
|
||||||
static int fw_ver_hi;
|
static int fw_ver_hi;
|
||||||
|
@ -173,9 +182,10 @@ static struct flash_layout layouts[] = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *const regions[] = {
|
static const struct fw_region regions[] = {
|
||||||
"UN", /* universal */
|
/* Default region (universal) uses code 0 as well */
|
||||||
"US",
|
{"US", 1},
|
||||||
|
{"EU", 0},
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -214,22 +224,15 @@ static struct flash_layout *find_layout(const char *id)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t find_region(const char *country) {
|
static const struct fw_region * find_region(const char *country) {
|
||||||
uint32_t i;
|
size_t i;
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(regions); i++) {
|
for (i = 0; i < ARRAY_SIZE(regions); i++) {
|
||||||
if (strcasecmp(regions[i], country) == 0)
|
if (strcasecmp(regions[i].name, country) == 0)
|
||||||
return i;
|
return ®ions[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return NULL;
|
||||||
}
|
|
||||||
|
|
||||||
static const char * get_region_country(uint32_t region) {
|
|
||||||
if (region < ARRAY_SIZE(regions))
|
|
||||||
return regions[region];
|
|
||||||
else
|
|
||||||
return "unknown";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void usage(int status)
|
static void usage(int status)
|
||||||
|
@ -353,15 +356,11 @@ static int check_options(void)
|
||||||
|
|
||||||
if (country) {
|
if (country) {
|
||||||
region = find_region(country);
|
region = find_region(country);
|
||||||
if (region == (uint32_t)-1) {
|
if (!region) {
|
||||||
char *end;
|
|
||||||
region = strtoul(country, &end, 0);
|
|
||||||
if (*end) {
|
|
||||||
ERR("unknown region code \"%s\"", country);
|
ERR("unknown region code \"%s\"", country);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
layout = find_layout(layout_id);
|
layout = find_layout(layout_id);
|
||||||
if (layout == NULL) {
|
if (layout == NULL) {
|
||||||
|
@ -476,7 +475,6 @@ static void fill_header(char *buf, int len)
|
||||||
strncpy(hdr->fw_version, version, sizeof(hdr->fw_version));
|
strncpy(hdr->fw_version, version, sizeof(hdr->fw_version));
|
||||||
hdr->hw_id = htonl(hw_id);
|
hdr->hw_id = htonl(hw_id);
|
||||||
hdr->hw_rev = htonl(hw_rev);
|
hdr->hw_rev = htonl(hw_rev);
|
||||||
hdr->region = htonl(region);
|
|
||||||
|
|
||||||
if (boot_info.file_size == 0)
|
if (boot_info.file_size == 0)
|
||||||
memcpy(hdr->md5sum1, md5salt_normal, sizeof(hdr->md5sum1));
|
memcpy(hdr->md5sum1, md5salt_normal, sizeof(hdr->md5sum1));
|
||||||
|
@ -497,6 +495,18 @@ static void fill_header(char *buf, int len)
|
||||||
hdr->ver_mid = htons(fw_ver_mid);
|
hdr->ver_mid = htons(fw_ver_mid);
|
||||||
hdr->ver_lo = htons(fw_ver_lo);
|
hdr->ver_lo = htons(fw_ver_lo);
|
||||||
|
|
||||||
|
if (region) {
|
||||||
|
hdr->region_code = htonl(region->code);
|
||||||
|
snprintf(
|
||||||
|
hdr->region_str1, sizeof(hdr->region_str1), "00000000;%02X%02X%02X%02X;",
|
||||||
|
region->name[0], region->name[1], region->name[2], region->name[3]
|
||||||
|
);
|
||||||
|
snprintf(
|
||||||
|
hdr->region_str2, sizeof(hdr->region_str2), "%02X%02X%02X%02X",
|
||||||
|
region->name[0], region->name[1], region->name[2], region->name[3]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
get_md5(buf, len, hdr->md5sum1);
|
get_md5(buf, len, hdr->md5sum1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -636,11 +646,6 @@ static inline void inspect_fw_phex(const char *label, uint32_t val)
|
||||||
printf("%-23s: 0x%08x\n", label, val);
|
printf("%-23s: 0x%08x\n", label, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void inspect_fw_phexpost(const char *label, uint32_t val, const char *post)
|
|
||||||
{
|
|
||||||
printf("%-23s: 0x%08x (%s)\n", label, val, post);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void inspect_fw_phexdec(const char *label, uint32_t val)
|
static inline void inspect_fw_phexdec(const char *label, uint32_t val)
|
||||||
{
|
{
|
||||||
printf("%-23s: 0x%08x / %8u bytes\n", label, val, val);
|
printf("%-23s: 0x%08x / %8u bytes\n", label, val, val);
|
||||||
|
@ -711,7 +716,7 @@ static int inspect_fw(void)
|
||||||
inspect_fw_pstr("Firmware version", hdr->fw_version);
|
inspect_fw_pstr("Firmware version", hdr->fw_version);
|
||||||
inspect_fw_phex("Hardware ID", ntohl(hdr->hw_id));
|
inspect_fw_phex("Hardware ID", ntohl(hdr->hw_id));
|
||||||
inspect_fw_phex("Hardware Revision", ntohl(hdr->hw_rev));
|
inspect_fw_phex("Hardware Revision", ntohl(hdr->hw_rev));
|
||||||
inspect_fw_phexpost("Region code", ntohl(hdr->region), get_region_country(ntohl(hdr->region)));
|
inspect_fw_phex("Region code", ntohl(hdr->region_code));
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue