aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2016-08-28 19:43:25 +0200
committerMatthias Schiffer <mschiffer@universe-factory.net>2016-08-28 19:59:21 +0200
commita4fc62bc0ea4010ddbfbd738453c9db70988a57c (patch)
tree472623ad959248d115b1fde72b876fc9a3b5bcce
parent02e3c718e9ad0c14aa3cf359ba2a4763e81df805 (diff)
downloadupstream-a4fc62bc0ea4010ddbfbd738453c9db70988a57c.tar.gz
upstream-a4fc62bc0ea4010ddbfbd738453c9db70988a57c.tar.bz2
upstream-a4fc62bc0ea4010ddbfbd738453c9db70988a57c.zip
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>
-rw-r--r--tools/firmware-utils/src/mktplinkfw.c69
1 files 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 &regions[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");