mkrasimage: fix segmentation fault

This commit is contained in:
CN_SZTL 2020-03-02 17:53:40 +08:00
parent 6d0259e28e
commit 25cc297914
No known key found for this signature in database
GPG Key ID: 6850B6345C862176
4 changed files with 336 additions and 9 deletions

View File

@ -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)

View File

@ -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 <byteswap.h>
#include <endian.h>
#include <errno.h>
#include <libgen.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#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 <file> 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 <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 <file> 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 <file>\n");
printf("\n");
printf("Create new Luxul firmware:\n");
printf("\tlxlfw create <file> [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;
}

View File

@ -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();
}

View File

@ -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",