From 25cc2979142153211e74ad874ef404e5d010eea9 Mon Sep 17 00:00:00 2001 From: CN_SZTL Date: Mon, 2 Mar 2020 17:53:40 +0800 Subject: [PATCH] mkrasimage: fix segmentation fault --- tools/firmware-utils/Makefile | 1 + tools/firmware-utils/src/lxlfw.c | 282 +++++++++++++++++++ tools/firmware-utils/src/mkrasimage.c | 19 +- tools/firmware-utils/src/tplink-safeloader.c | 43 +++ 4 files changed, 336 insertions(+), 9 deletions(-) create mode 100644 tools/firmware-utils/src/lxlfw.c diff --git a/tools/firmware-utils/Makefile b/tools/firmware-utils/Makefile index 2d2c96ce0a..97c89eec27 100644 --- a/tools/firmware-utils/Makefile +++ b/tools/firmware-utils/Makefile @@ -25,6 +25,7 @@ define Host/Compile mkdir -p $(HOST_BUILD_DIR)/bin $(call cc,addpattern) $(call cc,asustrx) + $(call cc,lxlfw) $(call cc,trx) $(call cc,otrx) $(call cc,motorola-bin) diff --git a/tools/firmware-utils/src/lxlfw.c b/tools/firmware-utils/src/lxlfw.c new file mode 100644 index 0000000000..15678b8736 --- /dev/null +++ b/tools/firmware-utils/src/lxlfw.c @@ -0,0 +1,282 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +/* + * Luxul's firmware container format + * + * Copyright 2020 Legrand AV Inc. + */ + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if __BYTE_ORDER == __BIG_ENDIAN +#define cpu_to_le32(x) bswap_32(x) +#define cpu_to_le16(x) bswap_16(x) +#define le32_to_cpu(x) bswap_32(x) +#define le16_to_cpu(x) bswap_16(x) +#elif __BYTE_ORDER == __LITTLE_ENDIAN +#define cpu_to_le32(x) (x) +#define cpu_to_le16(x) (x) +#define le32_to_cpu(x) (x) +#define le16_to_cpu(x) (x) +#endif + +#define min(a, b) \ + ({ \ + __typeof__ (a) _a = (a); \ + __typeof__ (b) _b = (b); \ + _a < _b ? _a : _b; \ + }) + +#define max(a, b) \ + ({ \ + __typeof__ (a) _a = (a); \ + __typeof__ (b) _b = (b); \ + _a > _b ? _a : _b; \ + }) + +#define LXL_FLAGS_VENDOR_LUXUL 0x00000001 + +struct lxl_hdr { + char magic[4]; /* "LXL#" */ + uint32_t version; + uint32_t hdr_len; + uint8_t v0_end[0]; + /* Version: 1+ */ + uint32_t flags; + char board[16]; + uint8_t v1_end[0]; + /* Version: 2+ */ + uint8_t release[4]; + uint8_t v2_end[0]; +} __packed; + +static uint32_t lxlfw_hdr_len(uint32_t version) +{ + switch (version) { + case 0: + return offsetof(struct lxl_hdr, v0_end); + case 1: + return offsetof(struct lxl_hdr, v1_end); + case 2: + return offsetof(struct lxl_hdr, v2_end); + default: + fprintf(stderr, "Unsupported version %d\n", version); + return 0; + } +} + +/************************************************** + * Info + **************************************************/ + +static int lxlfw_info(int argc, char **argv) { + struct lxl_hdr hdr; + uint32_t version; + uint32_t hdr_len; + char board[17]; + size_t bytes; + int err = 0; + FILE *lxl; + int flags; + + if (argc < 3) { + fprintf(stderr, "Missing argument\n"); + err = -EINVAL; + goto out; + } + + lxl = fopen(argv[2], "r"); + if (!lxl) { + fprintf(stderr, "Could not open \"%s\" file\n", argv[2]); + err = -ENOENT; + goto out; + } + + bytes = fread(&hdr, 1, sizeof(hdr), lxl); + if (bytes < offsetof(struct lxl_hdr, v0_end)) { + fprintf(stderr, "Input file too small to use Luxul format\n"); + err = -ENXIO; + goto err_close; + } + + if (memcmp(hdr.magic, "LXL#", 4)) { + fprintf(stderr, "File does not use Luxul's format\n"); + err = -EINVAL; + goto err_close; + } + + version = le32_to_cpu(hdr.version); + hdr_len = lxlfw_hdr_len(version); + if (bytes < hdr_len) { + fprintf(stderr, "Input file too small for header version %d\n", version); + err = -ENXIO; + goto err_close; + } + + printf("Format version:\t%d\n", version); + printf("Header length:\t%d\n", le32_to_cpu(hdr.hdr_len)); + if (version >= 1) { + printf("Flags:\t\t"); + flags = le32_to_cpu(hdr.flags); + if (flags & LXL_FLAGS_VENDOR_LUXUL) + printf("VENDOR_LUXUL "); + printf("\n"); + memcpy(board, hdr.board, sizeof(hdr.board)); + board[16] = '\0'; + printf("Board:\t\t%s\n", board); + } + if (version >= 2) { + printf("Release:\t"); + if (hdr.release[0] || hdr.release[1] || hdr.release[2] || hdr.release[3]) { + printf("%hu.%hu.%hu", hdr.release[0], hdr.release[1], hdr.release[2]); + if (hdr.release[3]) + printf(".%hu", hdr.release[3]); + } + printf("\n"); + } + +err_close: + fclose(lxl); +out: + return err; +} + +/************************************************** + * Create + **************************************************/ + +static int lxlfw_create(int argc, char **argv) { + struct lxl_hdr hdr = { + .magic = { 'L', 'X', 'L', '#' }, + }; + char *in_path = NULL; + uint32_t version = 0; + uint32_t hdr_len; + ssize_t bytes; + char buf[512]; + int err = 0; + FILE *lxl; + FILE *in; + int c; + + if (argc < 3) { + fprintf(stderr, "Missing argument\n"); + err = -EINVAL; + goto out; + } + + optind = 3; + while ((c = getopt(argc, argv, "i:lb:r:")) != -1) { + switch (c) { + case 'i': + in_path = optarg; + break; + case 'l': + hdr.flags |= cpu_to_le32(LXL_FLAGS_VENDOR_LUXUL); + version = max(version, 1); + break; + case 'b': + memcpy(hdr.board, optarg, strlen(optarg) > 16 ? 16 : strlen(optarg)); + version = max(version, 1); + break; + case 'r': + if (sscanf(optarg, "%hhu.%hhu.%hhu.%hhu", &hdr.release[0], &hdr.release[1], &hdr.release[2], &hdr.release[3]) < 1) { + fprintf(stderr, "Failed to parse release number \"%s\"\n", optarg); + err = -EINVAL; + goto out; + } + version = max(version, 2); + break; + } + } + + hdr.version = cpu_to_le32(version); + hdr_len = lxlfw_hdr_len(version); + if (!hdr_len) { + err = -EINVAL; + goto out; + } + hdr.hdr_len = cpu_to_le32(hdr_len); + + if (!in_path) { + fprintf(stderr, "Missing input file argument\n"); + err = -EINVAL; + goto out; + } + + in = fopen(in_path, "r"); + if (!in) { + fprintf(stderr, "Could not open input file %s\n", in_path); + err = -EIO; + goto out; + } + + lxl = fopen(argv[2], "w+"); + if (!lxl) { + fprintf(stderr, "Could not open \"%s\" file\n", argv[2]); + err = -EIO; + goto err_close_in; + } + + bytes = fwrite(&hdr, 1, hdr_len, lxl); + if (bytes != hdr_len) { + fprintf(stderr, "Could not write Luxul's header\n"); + err = -EIO; + goto err_close_lxl; + } + + while ((bytes = fread(buf, 1, sizeof(buf), in)) > 0) { + if (fwrite(buf, 1, bytes, lxl) != bytes) { + fprintf(stderr, "Could not copy %zu bytes from input file\n", bytes); + err = -EIO; + goto err_close_lxl; + } + } + +err_close_lxl: + fclose(lxl); +err_close_in: + fclose(in); +out: + return err; +} + +/************************************************** + * Start + **************************************************/ + +static void usage() { + printf("Usage:\n"); + printf("\n"); + printf("Get info about Luxul firmware:\n"); + printf("\tlxlfw info \n"); + printf("\n"); + printf("Create new Luxul firmware:\n"); + printf("\tlxlfw create [options]\n"); + printf("\t-i file\t\t\t\tinput file for Luxul's firmware container\n"); + printf("\t-l\t\t\t\tmark firmware as created by Luxul company (DON'T USE)\n"); + printf("\t-b board\t\t\tboard (device) name\n"); + printf("\t-r release\t\t\trelease number (e.g. 5.1.0, 7.1.0.2)\n"); +} + +int main(int argc, char **argv) { + if (argc > 1) { + if (!strcmp(argv[1], "info")) + return lxlfw_info(argc, argv); + else if (!strcmp(argv[1], "create")) + return lxlfw_create(argc, argv); + } + + usage(); + return 0; +} diff --git a/tools/firmware-utils/src/mkrasimage.c b/tools/firmware-utils/src/mkrasimage.c index cff3a533d1..d8cec527fb 100644 --- a/tools/firmware-utils/src/mkrasimage.c +++ b/tools/firmware-utils/src/mkrasimage.c @@ -317,6 +317,16 @@ int build_image() map_file(&kernel); map_file(&rootfs); + /* As ZyXEL Web-GUI only accept images with a rootfs equal or larger than the first firmware shipped + * for the device, we need to pad rootfs partition to this size. To perform further calculations, we + * decide the size of this part here. In case the rootfs we want to integrate in our image is larger, + * take it's size, otherwise the supplied size. + * + * Be careful! We rely on assertion of correct size to be performed beforehand. It is unknown if images + * with a to large rootfs are accepted or not. + */ + rootfs_out.size = rootfs_size < rootfs.size ? rootfs.size : rootfs_size; + /* * Allocate memory and copy input rootfs for temporary output rootfs. * This is important as we have to generate the rootfs checksum over the @@ -451,14 +461,5 @@ int main(int argc, char *argv[]) if (ret) usage(EXIT_FAILURE); - /* As ZyXEL Web-GUI only accept images with a rootfs equal or larger than the first firmware shipped - * for the device, we need to pad rootfs partition to this size. To perform further calculations, we - * decide the size of this part here. In case the rootfs we want to integrate in our image is larger, - * take it's size, otherwise the supplied size. - * - * Be careful! We rely on assertion of correct size to be performed beforehand. It is unknown if images - * with a to large rootfs are accepted or not. - */ - rootfs_out.size = rootfs_size < rootfs.size ? rootfs.size : rootfs_size; return build_image(); } diff --git a/tools/firmware-utils/src/tplink-safeloader.c b/tools/firmware-utils/src/tplink-safeloader.c index 43c4bafe00..0359c9f614 100644 --- a/tools/firmware-utils/src/tplink-safeloader.c +++ b/tools/firmware-utils/src/tplink-safeloader.c @@ -1436,6 +1436,49 @@ static struct device_info boards[] = { .last_sysupgrade_partition = "file-system", }, + /** Firmware layout for the RE200 v2 */ + { + .id = "RE200-V2", + .vendor = "", + .support_list = + "SupportList:\n" + "{product_name:RE200,product_ver:2.0.0,special_id:00000000}\n" + "{product_name:RE200,product_ver:2.0.0,special_id:41520000}\n" + "{product_name:RE200,product_ver:2.0.0,special_id:41550000}\n" + "{product_name:RE200,product_ver:2.0.0,special_id:42520000}\n" + "{product_name:RE200,product_ver:2.0.0,special_id:43410000}\n" + "{product_name:RE200,product_ver:2.0.0,special_id:45530000}\n" + "{product_name:RE200,product_ver:2.0.0,special_id:45550000}\n" + "{product_name:RE200,product_ver:2.0.0,special_id:49440000}\n" + "{product_name:RE200,product_ver:2.0.0,special_id:4a500000}\n" + "{product_name:RE200,product_ver:2.0.0,special_id:4b520000}\n" + "{product_name:RE200,product_ver:2.0.0,special_id:52550000}\n" + "{product_name:RE200,product_ver:2.0.0,special_id:54570000}\n" + "{product_name:RE200,product_ver:2.0.0,special_id:55530000}\n", + .support_trail = '\x00', + .soft_ver = NULL, + + .partitions = { + {"fs-uboot", 0x00000, 0x20000}, + {"firmware", 0x20000, 0x7a0000}, + {"partition-table", 0x7c0000, 0x02000}, + {"default-mac", 0x7c2000, 0x00020}, + {"pin", 0x7c2100, 0x00020}, + {"product-info", 0x7c3100, 0x01000}, + {"soft-version", 0x7c4200, 0x01000}, + {"support-list", 0x7c5200, 0x01000}, + {"profile", 0x7c6200, 0x08000}, + {"config-info", 0x7ce200, 0x00400}, + {"user-config", 0x7d0000, 0x10000}, + {"default-config", 0x7e0000, 0x10000}, + {"radio", 0x7f0000, 0x10000}, + {NULL, 0, 0} + }, + + .first_sysupgrade_partition = "os-image", + .last_sysupgrade_partition = "file-system" + }, + /** Firmware layout for the RE305 v1 */ { .id = "RE305-V1",