From a4fc62bc0ea4010ddbfbd738453c9db70988a57c Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Sun, 28 Aug 2016 19:43:25 +0200 Subject: [PATCH] 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 --- tools/firmware-utils/src/mktplinkfw.c | 69 ++++++++++++++------------- 1 file changed, 37 insertions(+), 32 deletions(-) diff --git a/tools/firmware-utils/src/mktplinkfw.c b/tools/firmware-utils/src/mktplinkfw.c index 7127932d71..34e6546a2d 100644 --- a/tools/firmware-utils/src/mktplinkfw.c +++ b/tools/firmware-utils/src/mktplinkfw.c @@ -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"); -- 2.30.2