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];
|
||||
uint32_t hw_id; /* hardware id */
|
||||
uint32_t hw_rev; /* hardware revision */
|
||||
uint32_t region; /* region code */
|
||||
uint32_t region_code; /* region code */
|
||||
uint8_t md5sum1[MD5SUM_LEN];
|
||||
uint32_t unk2;
|
||||
uint8_t md5sum2[MD5SUM_LEN];
|
||||
|
@ -63,7 +63,10 @@ struct fw_header {
|
|||
uint16_t ver_hi;
|
||||
uint16_t ver_mid;
|
||||
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));
|
||||
|
||||
struct flash_layout {
|
||||
|
@ -74,6 +77,12 @@ struct flash_layout {
|
|||
uint32_t rootfs_ofs;
|
||||
};
|
||||
|
||||
struct fw_region {
|
||||
char name[4];
|
||||
uint32_t code;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Globals
|
||||
*/
|
||||
|
@ -92,7 +101,7 @@ static char *opt_hw_rev;
|
|||
static uint32_t hw_rev;
|
||||
static uint32_t opt_hdr_ver = 1;
|
||||
static char *country;
|
||||
static uint32_t region;
|
||||
static const struct fw_region *region;
|
||||
static int fw_ver_lo;
|
||||
static int fw_ver_mid;
|
||||
static int fw_ver_hi;
|
||||
|
@ -173,9 +182,10 @@ static struct flash_layout layouts[] = {
|
|||
}
|
||||
};
|
||||
|
||||
static const char *const regions[] = {
|
||||
"UN", /* universal */
|
||||
"US",
|
||||
static const struct fw_region regions[] = {
|
||||
/* Default region (universal) uses code 0 as well */
|
||||
{"US", 1},
|
||||
{"EU", 0},
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -214,22 +224,15 @@ static struct flash_layout *find_layout(const char *id)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static uint32_t find_region(const char *country) {
|
||||
uint32_t i;
|
||||
static const struct fw_region * find_region(const char *country) {
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(regions); i++) {
|
||||
if (strcasecmp(regions[i], country) == 0)
|
||||
return i;
|
||||
if (strcasecmp(regions[i].name, country) == 0)
|
||||
return ®ions[i];
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static const char * get_region_country(uint32_t region) {
|
||||
if (region < ARRAY_SIZE(regions))
|
||||
return regions[region];
|
||||
else
|
||||
return "unknown";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void usage(int status)
|
||||
|
@ -353,13 +356,9 @@ static int check_options(void)
|
|||
|
||||
if (country) {
|
||||
region = find_region(country);
|
||||
if (region == (uint32_t)-1) {
|
||||
char *end;
|
||||
region = strtoul(country, &end, 0);
|
||||
if (*end) {
|
||||
ERR("unknown region code \"%s\"", country);
|
||||
return -1;
|
||||
}
|
||||
if (!region) {
|
||||
ERR("unknown region code \"%s\"", country);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -476,7 +475,6 @@ static void fill_header(char *buf, int len)
|
|||
strncpy(hdr->fw_version, version, sizeof(hdr->fw_version));
|
||||
hdr->hw_id = htonl(hw_id);
|
||||
hdr->hw_rev = htonl(hw_rev);
|
||||
hdr->region = htonl(region);
|
||||
|
||||
if (boot_info.file_size == 0)
|
||||
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_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);
|
||||
}
|
||||
|
||||
|
@ -636,11 +646,6 @@ static inline void inspect_fw_phex(const char *label, uint32_t 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)
|
||||
{
|
||||
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_phex("Hardware ID", ntohl(hdr->hw_id));
|
||||
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");
|
||||
|
||||
|
|
Loading…
Reference in a new issue