From fff6443b5bf62f70b44ce5270129e8ecd7b9a25c Mon Sep 17 00:00:00 2001 From: Jo-Philipp Wich Date: Wed, 24 Aug 2016 19:42:19 +0200 Subject: [PATCH] firmware-utils/tplink-safeloader: refactor code for further board support In order to make it easier to add new boards in the future, refactor the code to describe the image layouts of supported boards in a struct array and alter the image generation routines to figure out the sysupgrade partitions automatically. Signed-off-by: Jo-Philipp Wich --- tools/firmware-utils/src/tplink-safeloader.c | 566 +++++++++---------- 1 file changed, 265 insertions(+), 301 deletions(-) diff --git a/tools/firmware-utils/src/tplink-safeloader.c b/tools/firmware-utils/src/tplink-safeloader.c index 7fb5e89530..7a5990cc9b 100644 --- a/tools/firmware-utils/src/tplink-safeloader.c +++ b/tools/firmware-utils/src/tplink-safeloader.c @@ -53,6 +53,8 @@ #define ALIGN(x,a) ({ typeof(a) __a = (a); (((x) + __a - 1) & ~(__a - 1)); }) +#define MAX_PARTITIONS 32 + /** An image partition table entry */ struct image_partition_entry { const char *name; @@ -67,12 +69,15 @@ struct flash_partition_entry { uint32_t size; }; +/** Firmware layout description */ struct device_info { + const char *id; const char *vendor; const char *support_list; char support_trail; - const struct flash_partition_entry *partitions; - void *(*generate_sysupgrade_image)(const struct flash_partition_entry *flash_parts, const struct image_partition_entry *image_parts, size_t *len); + const struct flash_partition_entry partitions[MAX_PARTITIONS+1]; + const char *first_sysupgrade_partition; + const char *last_sysupgrade_partition; }; /** The content of the soft-version structure */ @@ -109,156 +114,189 @@ static const uint8_t md5_salt[16] = { }; -/** Vendor information for CPE210/220/510/520 */ -static const char cpe510_vendor[] = "CPE510(TP-LINK|UN|N300-5):1.0\r\n"; - -/** Vendor information for C2600 */ -static const char c2600_vendor[] = ""; - -/** Vendor information for EAP120 */ -static const char eap120_vendor[] = "EAP120(TP-LINK|UN|N300-2):1.0\r\n"; - -/** - The flash partition table for CPE210/220/510/520; - it is the same as the one used by the stock images. -*/ -static const struct flash_partition_entry cpe510_partitions[] = { - {"fs-uboot", 0x00000, 0x20000}, - {"partition-table", 0x20000, 0x02000}, - {"default-mac", 0x30000, 0x00020}, - {"product-info", 0x31100, 0x00100}, - {"signature", 0x32000, 0x00400}, - {"os-image", 0x40000, 0x170000}, - {"soft-version", 0x1b0000, 0x00100}, - {"support-list", 0x1b1000, 0x00400}, - {"file-system", 0x1c0000, 0x600000}, - {"user-config", 0x7c0000, 0x10000}, - {"default-config", 0x7d0000, 0x10000}, - {"log", 0x7e0000, 0x10000}, - {"radio", 0x7f0000, 0x10000}, - {NULL, 0, 0} +/** Firmware layout table */ +static struct device_info boards[] = { + /** Firmware layout for the CPE210/220 */ + { + .id = "CPE210", + .vendor = "CPE510(TP-LINK|UN|N300-5):1.0\r\n", + .support_list = + "SupportList:\r\n" + "CPE210(TP-LINK|UN|N300-2):1.0\r\n" + "CPE210(TP-LINK|UN|N300-2):1.1\r\n" + "CPE210(TP-LINK|US|N300-2):1.1\r\n" + "CPE210(TP-LINK|EU|N300-2):1.1\r\n" + "CPE220(TP-LINK|UN|N300-2):1.1\r\n" + "CPE220(TP-LINK|US|N300-2):1.1\r\n" + "CPE220(TP-LINK|EU|N300-2):1.1\r\n", + .support_trail = '\xff', + + .partitions = { + {"fs-uboot", 0x00000, 0x20000}, + {"partition-table", 0x20000, 0x02000}, + {"default-mac", 0x30000, 0x00020}, + {"product-info", 0x31100, 0x00100}, + {"signature", 0x32000, 0x00400}, + {"os-image", 0x40000, 0x170000}, + {"soft-version", 0x1b0000, 0x00100}, + {"support-list", 0x1b1000, 0x00400}, + {"file-system", 0x1c0000, 0x600000}, + {"user-config", 0x7c0000, 0x10000}, + {"default-config", 0x7d0000, 0x10000}, + {"log", 0x7e0000, 0x10000}, + {"radio", 0x7f0000, 0x10000}, + {NULL, 0, 0} + }, + + .first_sysupgrade_partition = "os-image", + .last_sysupgrade_partition = "file-system", + }, + + /** Firmware layout for the CPE510/520 */ + { + .id = "CPE510", + .vendor = "CPE510(TP-LINK|UN|N300-5):1.0\r\n", + .support_list = + "SupportList:\r\n" + "CPE510(TP-LINK|UN|N300-5):1.0\r\n" + "CPE510(TP-LINK|UN|N300-5):1.1\r\n" + "CPE510(TP-LINK|UN|N300-5):1.1\r\n" + "CPE510(TP-LINK|US|N300-5):1.1\r\n" + "CPE510(TP-LINK|EU|N300-5):1.1\r\n" + "CPE520(TP-LINK|UN|N300-5):1.1\r\n" + "CPE520(TP-LINK|US|N300-5):1.1\r\n" + "CPE520(TP-LINK|EU|N300-5):1.1\r\n", + .support_trail = '\xff', + + .partitions = { + {"fs-uboot", 0x00000, 0x20000}, + {"partition-table", 0x20000, 0x02000}, + {"default-mac", 0x30000, 0x00020}, + {"product-info", 0x31100, 0x00100}, + {"signature", 0x32000, 0x00400}, + {"os-image", 0x40000, 0x170000}, + {"soft-version", 0x1b0000, 0x00100}, + {"support-list", 0x1b1000, 0x00400}, + {"file-system", 0x1c0000, 0x600000}, + {"user-config", 0x7c0000, 0x10000}, + {"default-config", 0x7d0000, 0x10000}, + {"log", 0x7e0000, 0x10000}, + {"radio", 0x7f0000, 0x10000}, + {NULL, 0, 0} + }, + + .first_sysupgrade_partition = "os-image", + .last_sysupgrade_partition = "file-system", + }, + + /** Firmware layout for the C2600 */ + { + .id = "C2600", + .vendor = "", + .support_list = + "SupportList:\r\n" + "{product_name:Archer C2600,product_ver:1.0.0,special_id:00000000}\r\n", + .support_trail = '\x00', + + .partitions = { + {"SBL1", 0x00000, 0x20000}, + {"MIBIB", 0x20000, 0x20000}, + {"SBL2", 0x40000, 0x20000}, + {"SBL3", 0x60000, 0x30000}, + {"DDRCONFIG", 0x90000, 0x10000}, + {"SSD", 0xa0000, 0x10000}, + {"TZ", 0xb0000, 0x30000}, + {"RPM", 0xe0000, 0x20000}, + {"fs-uboot", 0x100000, 0x70000}, + {"uboot-env", 0x170000, 0x40000}, + {"radio", 0x1b0000, 0x40000}, + {"os-image", 0x1f0000, 0x200000}, + {"file-system", 0x3f0000, 0x1b00000}, + {"default-mac", 0x1ef0000, 0x00200}, + {"pin", 0x1ef0200, 0x00200}, + {"product-info", 0x1ef0400, 0x0fc00}, + {"partition-table", 0x1f00000, 0x10000}, + {"soft-version", 0x1f10000, 0x10000}, + {"support-list", 0x1f20000, 0x10000}, + {"profile", 0x1f30000, 0x10000}, + {"default-config", 0x1f40000, 0x10000}, + {"user-config", 0x1f50000, 0x40000}, + {"qos-db", 0x1f90000, 0x40000}, + {"usb-config", 0x1fd0000, 0x10000}, + {"log", 0x1fe0000, 0x20000}, + {NULL, 0, 0} + }, + + .first_sysupgrade_partition = "os-image", + .last_sysupgrade_partition = "file-system" + }, + + /** Firmware layout for the C9 */ + { + .id = "ARCHERC9", + .vendor = "", + .support_list = + "SupportList:\n" + "{product_name:ArcherC9," + "product_ver:1.0.0," + "special_id:00000000}\n", + .support_trail = '\x00', + + .partitions = { + {"fs-uboot", 0x00000, 0x40000}, + {"os-image", 0x40000, 0x200000}, + {"file-system", 0x240000, 0xc00000}, + {"default-mac", 0xe40000, 0x00200}, + {"pin", 0xe40200, 0x00200}, + {"product-info", 0xe40400, 0x00200}, + {"partition-table", 0xe50000, 0x10000}, + {"soft-version", 0xe60000, 0x00200}, + {"support-list", 0xe61000, 0x0f000}, + {"profile", 0xe70000, 0x10000}, + {"default-config", 0xe80000, 0x10000}, + {"user-config", 0xe90000, 0x50000}, + {"log", 0xee0000, 0x100000}, + {"radio_bk", 0xfe0000, 0x10000}, + {"radio", 0xff0000, 0x10000}, + {NULL, 0, 0} + }, + + .first_sysupgrade_partition = "os-image", + .last_sysupgrade_partition = "file-system" + }, + + /** Firmware layout for the EAP120 */ + { + .id = "EAP120", + .vendor = "EAP120(TP-LINK|UN|N300-2):1.0\r\n", + .support_list = + "SupportList:\r\n" + "EAP120(TP-LINK|UN|N300-2):1.0\r\n", + .support_trail = '\xff', + + .partitions = { + {"fs-uboot", 0x00000, 0x20000}, + {"partition-table", 0x20000, 0x02000}, + {"default-mac", 0x30000, 0x00020}, + {"support-list", 0x31000, 0x00100}, + {"product-info", 0x31100, 0x00100}, + {"soft-version", 0x32000, 0x00100}, + {"os-image", 0x40000, 0x180000}, + {"file-system", 0x1c0000, 0x600000}, + {"user-config", 0x7c0000, 0x10000}, + {"backup-config", 0x7d0000, 0x10000}, + {"log", 0x7e0000, 0x10000}, + {"radio", 0x7f0000, 0x10000}, + {NULL, 0, 0} + }, + + .first_sysupgrade_partition = "os-image", + .last_sysupgrade_partition = "file-system" + }, + + {} }; -/** - The flash partition table for C2600; - it is the same as the one used by the stock images. -*/ -static const struct flash_partition_entry c2600_partitions[] = { - {"SBL1", 0x00000, 0x20000}, - {"MIBIB", 0x20000, 0x20000}, - {"SBL2", 0x40000, 0x20000}, - {"SBL3", 0x60000, 0x30000}, - {"DDRCONFIG", 0x90000, 0x10000}, - {"SSD", 0xa0000, 0x10000}, - {"TZ", 0xb0000, 0x30000}, - {"RPM", 0xe0000, 0x20000}, - {"fs-uboot", 0x100000, 0x70000}, - {"uboot-env", 0x170000, 0x40000}, - {"radio", 0x1b0000, 0x40000}, - {"os-image", 0x1f0000, 0x200000}, - {"file-system", 0x3f0000, 0x1b00000}, - {"default-mac", 0x1ef0000, 0x00200}, - {"pin", 0x1ef0200, 0x00200}, - {"product-info", 0x1ef0400, 0x0fc00}, - {"partition-table", 0x1f00000, 0x10000}, - {"soft-version", 0x1f10000, 0x10000}, - {"support-list", 0x1f20000, 0x10000}, - {"profile", 0x1f30000, 0x10000}, - {"default-config", 0x1f40000, 0x10000}, - {"user-config", 0x1f50000, 0x40000}, - {"qos-db", 0x1f90000, 0x40000}, - {"usb-config", 0x1fd0000, 0x10000}, - {"log", 0x1fe0000, 0x20000}, - {NULL, 0, 0} -}; - -static const struct flash_partition_entry c5_partitions[] = { - {"fs-uboot", 0x00000, 0x40000}, - {"os-image", 0x40000, 0x200000}, - {"file-system", 0x240000, 0xc00000}, - {"default-mac", 0xe40000, 0x00200}, - {"pin", 0xe40200, 0x00200}, - {"product-info", 0xe40400, 0x00200}, - {"partition-table", 0xe50000, 0x10000}, - {"soft-version", 0xe60000, 0x00200}, - {"support-list", 0xe61000, 0x0f000}, - {"profile", 0xe70000, 0x10000}, - {"default-config", 0xe80000, 0x10000}, - {"user-config", 0xe90000, 0x50000}, - {"log", 0xee0000, 0x100000}, - {"radio_bk", 0xfe0000, 0x10000}, - {"radio", 0xff0000, 0x10000}, - {NULL, 0, 0} -}; - -/** The flash partition table for EAP120; - it is the same as the one used by the stock images. -*/ -static const struct flash_partition_entry eap120_partitions[] = { - {"fs-uboot", 0x00000, 0x20000}, - {"partition-table", 0x20000, 0x02000}, - {"default-mac", 0x30000, 0x00020}, - {"support-list", 0x31000, 0x00100}, - {"product-info", 0x31100, 0x00100}, - {"soft-version", 0x32000, 0x00100}, - {"os-image", 0x40000, 0x180000}, - {"file-system", 0x1c0000, 0x600000}, - {"user-config", 0x7c0000, 0x10000}, - {"backup-config", 0x7d0000, 0x10000}, - {"log", 0x7e0000, 0x10000}, - {"radio", 0x7f0000, 0x10000}, - {NULL, 0, 0} -}; - -/** - The support list for CPE210/220 -*/ -static const char cpe210_support_list[] = - "SupportList:\r\n" - "CPE210(TP-LINK|UN|N300-2):1.0\r\n" - "CPE210(TP-LINK|UN|N300-2):1.1\r\n" - "CPE210(TP-LINK|US|N300-2):1.1\r\n" - "CPE210(TP-LINK|EU|N300-2):1.1\r\n" - "CPE220(TP-LINK|UN|N300-2):1.1\r\n" - "CPE220(TP-LINK|US|N300-2):1.1\r\n" - "CPE220(TP-LINK|EU|N300-2):1.1\r\n" - ; - -/** - The support list for CPE210/220/510/520 -*/ -static const char cpe510_support_list[] = - "SupportList:\r\n" - "CPE510(TP-LINK|UN|N300-5):1.0\r\n" - "CPE510(TP-LINK|UN|N300-5):1.1\r\n" - "CPE510(TP-LINK|UN|N300-5):1.1\r\n" - "CPE510(TP-LINK|US|N300-5):1.1\r\n" - "CPE510(TP-LINK|EU|N300-5):1.1\r\n" - "CPE520(TP-LINK|UN|N300-5):1.1\r\n" - "CPE520(TP-LINK|US|N300-5):1.1\r\n" - "CPE520(TP-LINK|EU|N300-5):1.1\r\n" - ; - -/** - The support list for C2600 -*/ -static const char c2600_support_list[] = - "SupportList:\r\n" - "{product_name:Archer C2600,product_ver:1.0.0,special_id:00000000}\r\n"; - -static const char c9_support_list[] = - "SupportList:\n" - "{product_name:ArcherC9," - "product_ver:1.0.0," - "special_id:00000000}\n"; - -/** - The support list for EAP120 -*/ -static const char eap120_support_list[] = - "SupportList:\r\n" - "EAP120(TP-LINK|UN|N300-2):1.0\r\n"; - #define error(_ret, _errno, _str, ...) \ do { \ fprintf(stderr, _str ": %s\n", ## __VA_ARGS__, \ @@ -358,7 +396,7 @@ static struct image_partition_entry make_soft_version(uint32_t rev) { } /** Generates the support-list partition */ -static struct image_partition_entry make_support_list(struct device_info *info) { +static struct image_partition_entry make_support_list(const struct device_info *info) { size_t len = strlen(info->support_list); struct image_partition_entry entry = alloc_image_partition("support-list", len + 9); @@ -431,12 +469,22 @@ static struct image_partition_entry read_file(const char *part_name, const char I think partition-table must be the first partition in the firmware image. */ -static void put_partitions(uint8_t *buffer, const struct image_partition_entry *parts) { - size_t i; +static void put_partitions(uint8_t *buffer, const struct flash_partition_entry *flash_parts, const struct image_partition_entry *parts) { + size_t i, j; char *image_pt = (char *)buffer, *end = image_pt + 0x800; size_t base = 0x800; for (i = 0; parts[i].name; i++) { + for (j = 0; flash_parts[j].name; j++) { + if (!strcmp(flash_parts[j].name, parts[i].name)) { + if (parts[i].size > flash_parts[j].size) + error(1, 0, "%s partition too big (more than %u bytes)", flash_parts[j].name, (unsigned)flash_parts[j].size); + break; + } + } + + assert(flash_parts[j].name); + memcpy(buffer + base, parts[i].data, parts[i].size); size_t len = end-image_pt; @@ -477,7 +525,7 @@ static void put_md5(uint8_t *md5, uint8_t *buffer, unsigned int len) { 1014-1813 Image partition table (2048 bytes, padded with 0xff) 1814-xxxx Firmware partitions */ -static void * generate_factory_image(const char *vendor, const struct image_partition_entry *parts, size_t *len) { +static void * generate_factory_image(const struct device_info *info, const struct image_partition_entry *parts, size_t *len) { *len = 0x1814; size_t i; @@ -491,13 +539,13 @@ static void * generate_factory_image(const char *vendor, const struct image_part memset(image, 0xff, *len); put32(image, *len); - if (vendor) { - size_t vendor_len = strlen(vendor); + if (info->vendor) { + size_t vendor_len = strlen(info->vendor); put32(image+0x14, vendor_len); - memcpy(image+0x18, vendor, vendor_len); + memcpy(image+0x18, info->vendor, vendor_len); } - put_partitions(image + 0x1014, parts); + put_partitions(image + 0x1014, info->partitions, parts); put_md5(image+0x04, image+0x14, *len-0x14); return image; @@ -510,67 +558,39 @@ static void * generate_factory_image(const char *vendor, const struct image_part should be generalized when TP-LINK starts building its safeloader into hardware with different flash layouts. */ -static void * generate_sysupgrade_image(const struct flash_partition_entry *flash_parts, const struct image_partition_entry *image_parts, size_t *len) { - const struct flash_partition_entry *flash_os_image = &flash_parts[5]; - const struct flash_partition_entry *flash_soft_version = &flash_parts[6]; - const struct flash_partition_entry *flash_support_list = &flash_parts[7]; - const struct flash_partition_entry *flash_file_system = &flash_parts[8]; - - const struct image_partition_entry *image_os_image = &image_parts[3]; - const struct image_partition_entry *image_soft_version = &image_parts[1]; - const struct image_partition_entry *image_support_list = &image_parts[2]; - const struct image_partition_entry *image_file_system = &image_parts[4]; - - assert(strcmp(flash_os_image->name, "os-image") == 0); - assert(strcmp(flash_soft_version->name, "soft-version") == 0); - assert(strcmp(flash_support_list->name, "support-list") == 0); - assert(strcmp(flash_file_system->name, "file-system") == 0); - - assert(strcmp(image_os_image->name, "os-image") == 0); - assert(strcmp(image_soft_version->name, "soft-version") == 0); - assert(strcmp(image_support_list->name, "support-list") == 0); - assert(strcmp(image_file_system->name, "file-system") == 0); - - if (image_os_image->size > flash_os_image->size) - error(1, 0, "kernel image too big (more than %u bytes)", (unsigned)flash_os_image->size); - if (image_file_system->size > flash_file_system->size) - error(1, 0, "rootfs image too big (more than %u bytes)", (unsigned)flash_file_system->size); - - *len = flash_file_system->base - flash_os_image->base + image_file_system->size; - - uint8_t *image = malloc(*len); - if (!image) - error(1, errno, "malloc"); - - memset(image, 0xff, *len); - - memcpy(image, image_os_image->data, image_os_image->size); - memcpy(image + flash_soft_version->base - flash_os_image->base, image_soft_version->data, image_soft_version->size); - memcpy(image + flash_support_list->base - flash_os_image->base, image_support_list->data, image_support_list->size); - memcpy(image + flash_file_system->base - flash_os_image->base, image_file_system->data, image_file_system->size); - - return image; -} - -static void * generate_sysupgrade_image_c2600(const struct flash_partition_entry *flash_parts, const struct image_partition_entry *image_parts, size_t *len) { - const struct flash_partition_entry *flash_os_image = &flash_parts[11]; - const struct flash_partition_entry *flash_file_system = &flash_parts[12]; - - const struct image_partition_entry *image_os_image = &image_parts[3]; - const struct image_partition_entry *image_file_system = &image_parts[4]; +static void * generate_sysupgrade_image(const struct device_info *info, const struct image_partition_entry *image_parts, size_t *len) { + size_t i, j; + size_t flash_first_partition_index = 0; + size_t flash_last_partition_index = 0; + const struct flash_partition_entry *flash_first_partition = NULL; + const struct flash_partition_entry *flash_last_partition = NULL; + const struct image_partition_entry *image_last_partition = NULL; + + /** Find first and last partitions */ + for (i = 0; info->partitions[i].name; i++) { + if (!strcmp(info->partitions[i].name, info->first_sysupgrade_partition)) { + flash_first_partition = &info->partitions[i]; + flash_first_partition_index = i; + } else if (!strcmp(info->partitions[i].name, info->last_sysupgrade_partition)) { + flash_last_partition = &info->partitions[i]; + flash_last_partition_index = i; + } + } - assert(strcmp(flash_os_image->name, "os-image") == 0); - assert(strcmp(flash_file_system->name, "file-system") == 0); + assert(flash_first_partition && flash_last_partition); + assert(flash_first_partition_index < flash_last_partition_index); - assert(strcmp(image_os_image->name, "os-image") == 0); - assert(strcmp(image_file_system->name, "file-system") == 0); + /** Find last partition from image to calculate needed size */ + for (i = 0; image_parts[i].name; i++) { + if (!strcmp(image_parts[i].name, info->last_sysupgrade_partition)) { + image_last_partition = &image_parts[i]; + break; + } + } - if (image_os_image->size > flash_os_image->size) - error(1, 0, "kernel image too big (more than %u bytes)", (unsigned)flash_os_image->size); - if (image_file_system->size > flash_file_system->size) - error(1, 0, "rootfs image too big (more than %u bytes)", (unsigned)flash_file_system->size); + assert(image_last_partition); - *len = flash_file_system->base - flash_os_image->base + image_file_system->size; + *len = flash_last_partition->base - flash_first_partition->base + image_last_partition->size; uint8_t *image = malloc(*len); if (!image) @@ -578,89 +598,30 @@ static void * generate_sysupgrade_image_c2600(const struct flash_partition_entry memset(image, 0xff, *len); - memcpy(image, image_os_image->data, image_os_image->size); - memcpy(image + flash_file_system->base - flash_os_image->base, image_file_system->data, image_file_system->size); - - return image; -} -static void *generate_sysupgrade_image_eap120(const struct flash_partition_entry *flash_parts, const struct image_partition_entry *image_parts, size_t *len) -{ - const struct flash_partition_entry *flash_os_image = &flash_parts[6]; - const struct flash_partition_entry *flash_file_system = &flash_parts[7]; - - const struct image_partition_entry *image_os_image = &image_parts[3]; - const struct image_partition_entry *image_file_system = &image_parts[4]; - - assert(strcmp(flash_os_image->name, "os-image") == 0); - assert(strcmp(flash_file_system->name, "file-system") == 0); - - assert(strcmp(image_os_image->name, "os-image") == 0); - assert(strcmp(image_file_system->name, "file-system") == 0); - - if (image_os_image->size > flash_os_image->size) - error(1, 0, "kernel image too big (more than %u bytes)", (unsigned)flash_os_image->size); - if (image_file_system->size > flash_file_system->size) - error(1, 0, "rootfs image too big (more than %u bytes)", (unsigned)flash_file_system->size); - - *len = flash_file_system->base - flash_os_image->base + image_file_system->size; - - uint8_t *image = malloc(*len); - if (!image) - error(1, errno, "malloc"); + for (i = flash_first_partition_index; i <= flash_last_partition_index; i++) { + for (j = 0; image_parts[j].name; j++) { + if (!strcmp(info->partitions[i].name, image_parts[j].name)) { + if (image_parts[j].size > info->partitions[i].size) + error(1, 0, "%s partition too big (more than %u bytes)", info->partitions[i].name, (unsigned)info->partitions[i].size); + memcpy(image + info->partitions[i].base - flash_first_partition->base, image_parts[j].data, image_parts[j].size); + break; + } - memset(image, 0xff, *len); - memcpy(image, image_os_image->data, image_os_image->size); - memcpy(image + flash_file_system->base - flash_os_image->base, image_file_system->data, image_file_system->size); + assert(image_parts[j].name); + } + } return image; } -struct device_info cpe210_info = { - .vendor = cpe510_vendor, - .support_list = cpe210_support_list, - .support_trail = '\xff', - .partitions = cpe510_partitions, - .generate_sysupgrade_image = &generate_sysupgrade_image, -}; - -struct device_info cpe510_info = { - .vendor = cpe510_vendor, - .support_list = cpe510_support_list, - .support_trail = '\xff', - .partitions = cpe510_partitions, - .generate_sysupgrade_image = &generate_sysupgrade_image, -}; - -struct device_info c2600_info = { - .vendor = c2600_vendor, - .support_list = c2600_support_list, - .support_trail = '\x00', - .partitions = c2600_partitions, - .generate_sysupgrade_image = &generate_sysupgrade_image_c2600, -}; - -struct device_info e9_info = { - .vendor = c2600_vendor, - .support_list = c9_support_list, - .support_trail = '\x00', - .partitions = c5_partitions, -}; - -struct device_info eap120_info = { - .vendor = eap120_vendor, - .support_list = eap120_support_list, - .support_trail = '\xff', - .partitions = eap120_partitions, - .generate_sysupgrade_image = &generate_sysupgrade_image_eap120, -}; - +/** Generates an image according to a given layout and writes it to a file */ static void build_image(const char *output, const char *kernel_image, const char *rootfs_image, uint32_t rev, bool add_jffs2_eof, bool sysupgrade, - struct device_info *info) { + const struct device_info *info) { struct image_partition_entry parts[6] = {}; parts[0] = make_partition_table(info->partitions); @@ -672,9 +633,9 @@ static void build_image(const char *output, size_t len; void *image; if (sysupgrade) - image = info->generate_sysupgrade_image(info->partitions, parts, &len); + image = generate_sysupgrade_image(info, parts, &len); else - image = generate_factory_image(info->vendor, parts, &len); + image = generate_factory_image(info, parts, &len); FILE *file = fopen(output, "wb"); if (!file) @@ -711,11 +672,22 @@ static void usage(const char *argv0) { }; +static const struct device_info *find_board(const char *id) +{ + struct device_info *board = NULL; + + for (board = boards; board->id != NULL; board++) + if (strcasecmp(id, board->id) == 0) + return board; + + return NULL; +} + int main(int argc, char *argv[]) { const char *board = NULL, *kernel_image = NULL, *rootfs_image = NULL, *output = NULL; bool add_jffs2_eof = false, sysupgrade = false; unsigned rev = 0; - struct device_info *info; + const struct device_info *info; while (true) { int c; @@ -772,17 +744,9 @@ int main(int argc, char *argv[]) { if (!output) error(1, 0, "no output filename has been specified"); - if (strcmp(board, "CPE210") == 0) - info = &cpe210_info; - else if (strcmp(board, "CPE510") == 0) - info = &cpe510_info; - else if (strcmp(board, "C2600") == 0) - info = &c2600_info; - else if (strcmp(board, "EAP120") == 0) - info = &eap120_info; - else if (strcmp(board, "ARCHERC9") == 0) - info = &e9_info; - else + info = find_board(board); + + if (info == NULL) error(1, 0, "unsupported board %s", board); build_image(output, kernel_image, rootfs_image, rev, add_jffs2_eof, sysupgrade, info);