diff --git a/tools/firmware-utils/src/tplink-safeloader.c b/tools/firmware-utils/src/tplink-safeloader.c index c7942d1ef6..fe57905fac 100644 --- a/tools/firmware-utils/src/tplink-safeloader.c +++ b/tools/firmware-utils/src/tplink-safeloader.c @@ -65,7 +65,7 @@ struct image_partition_entry { /** A flash partition table entry */ struct flash_partition_entry { - const char *name; + char *name; uint32_t base; uint32_t size; }; @@ -77,7 +77,7 @@ struct device_info { const char *support_list; char support_trail; const char *soft_ver; - const struct flash_partition_entry partitions[MAX_PARTITIONS+1]; + struct flash_partition_entry partitions[MAX_PARTITIONS+1]; const char *first_sysupgrade_partition; const char *last_sysupgrade_partition; }; @@ -1223,7 +1223,7 @@ static struct image_partition_entry make_soft_version_from_string(const char *so } /** Generates the support-list partition */ -static struct image_partition_entry make_support_list(const struct device_info *info) { +static struct image_partition_entry make_support_list(struct device_info *info) { size_t len = strlen(info->support_list); struct image_partition_entry entry = alloc_image_partition("support-list", len + 9); @@ -1236,7 +1236,7 @@ static struct image_partition_entry make_support_list(const struct device_info * } /** Creates a new image partition with an arbitrary name from a file */ -static struct image_partition_entry read_file(const char *part_name, const char *filename, bool add_jffs2_eof) { +static struct image_partition_entry read_file(const char *part_name, const char *filename, bool add_jffs2_eof, struct flash_partition_entry *file_system_partition) { struct stat statbuf; if (stat(filename, &statbuf) < 0) @@ -1245,7 +1245,10 @@ static struct image_partition_entry read_file(const char *part_name, const char size_t len = statbuf.st_size; if (add_jffs2_eof) - len = ALIGN(len, 0x10000) + sizeof(jffs2_eof_mark); + if (file_system_partition) + len = ALIGN(len + file_system_partition->base, 0x10000) + sizeof(jffs2_eof_mark) - file_system_partition->base; + else + len = ALIGN(len, 0x10000) + sizeof(jffs2_eof_mark); struct image_partition_entry entry = alloc_image_partition(part_name, len); @@ -1361,7 +1364,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 struct device_info *info, const struct image_partition_entry *parts, size_t *len) { +static void * generate_factory_image(struct device_info *info, const struct image_partition_entry *parts, size_t *len) { *len = 0x1814; size_t i; @@ -1394,7 +1397,7 @@ static void * generate_factory_image(const struct device_info *info, const struc should be generalized when TP-LINK starts building its safeloader into hardware with different flash layouts. */ -static void * generate_sysupgrade_image(const struct device_info *info, const struct image_partition_entry *image_parts, size_t *len) { +static void * generate_sysupgrade_image(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; @@ -1457,10 +1460,53 @@ static void build_image(const char *output, uint32_t rev, bool add_jffs2_eof, bool sysupgrade, - const struct device_info *info) { + struct device_info *info) { + + size_t i; struct image_partition_entry parts[7] = {}; + struct flash_partition_entry *firmware_partition = NULL; + struct flash_partition_entry *os_image_partition = NULL; + struct flash_partition_entry *file_system_partition = NULL; + size_t firmware_partition_index = 0; + + for (i = 0; info->partitions[i].name; i++) { + if (!strcmp(info->partitions[i].name, "firmware")) + { + firmware_partition = &info->partitions[i]; + firmware_partition_index = i; + } + } + + if (firmware_partition) + { + os_image_partition = &info->partitions[firmware_partition_index]; + file_system_partition = &info->partitions[firmware_partition_index + 1]; + + struct stat kernel; + if (stat(kernel_image, &kernel) < 0) + error(1, errno, "unable to stat file `%s'", kernel_image); + + if (kernel.st_size > firmware_partition->size) + error(1, 0, "kernel overflowed firmware partition\n"); + + for (i = MAX_PARTITIONS-1; i >= firmware_partition_index + 1; i--) + info->partitions[i+1] = info->partitions[i]; + + file_system_partition->name = "file-system"; + file_system_partition->base = firmware_partition->base + kernel.st_size; + + /* Align partition start to erase blocks for factory images only */ + if (!sysupgrade) + file_system_partition->base = ALIGN(firmware_partition->base + kernel.st_size, 0x10000); + + file_system_partition->size = firmware_partition->size - file_system_partition->base; + + os_image_partition->name = "os-image"; + os_image_partition->size = kernel.st_size; + } + parts[0] = make_partition_table(info->partitions); if (info->soft_ver) parts[1] = make_soft_version_from_string(info->soft_ver); @@ -1468,8 +1514,8 @@ static void build_image(const char *output, parts[1] = make_soft_version(rev); parts[2] = make_support_list(info); - parts[3] = read_file("os-image", kernel_image, false); - parts[4] = read_file("file-system", rootfs_image, add_jffs2_eof); + parts[3] = read_file("os-image", kernel_image, false, NULL); + parts[4] = read_file("file-system", rootfs_image, add_jffs2_eof, file_system_partition); /* Some devices need the extra-para partition to accept the firmware */ if (strcasecmp(info->id, "ARCHER-C25-V1") == 0 || @@ -1500,7 +1546,6 @@ static void build_image(const char *output, free(image); - size_t i; for (i = 0; parts[i].name; i++) free_image_partition(parts[i]); } @@ -1530,7 +1575,7 @@ static void usage(const char *argv0) { }; -static const struct device_info *find_board(const char *id) +static struct device_info *find_board(const char *id) { struct device_info *board = NULL; @@ -1860,7 +1905,7 @@ int main(int argc, char *argv[]) { const char *extract_image = NULL, *output_directory = NULL, *convert_image = NULL; bool add_jffs2_eof = false, sysupgrade = false; unsigned rev = 0; - const struct device_info *info; + struct device_info *info; set_source_date_epoch(); while (true) {