From 0b333eb093e198e7c4febb65a63465bc94b71770 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Fri, 2 Apr 2021 16:31:43 +0200 Subject: [PATCH] firmware-utils: bcm4908img: support extracting image data MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit It's useful for upgrading cferom, firmware, etc. Signed-off-by: Rafał Miłecki (cherry picked from commit 9c039d56a154bb416492bf5657093576d50cc220) --- tools/firmware-utils/src/bcm4908img.c | 87 +++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/tools/firmware-utils/src/bcm4908img.c b/tools/firmware-utils/src/bcm4908img.c index b04916443b..7e9cba299d 100644 --- a/tools/firmware-utils/src/bcm4908img.c +++ b/tools/firmware-utils/src/bcm4908img.c @@ -469,6 +469,86 @@ out: return err; } +/************************************************** + * Extract + **************************************************/ + +static int bcm4908img_extract(int argc, char **argv) { + struct bcm4908img_info info; + const char *pathname = NULL; + uint8_t buf[1024]; + const char *type; + size_t offset; + size_t length; + size_t bytes; + FILE *fp; + int c; + int err = 0; + + while ((c = getopt(argc, argv, "i:t:")) != -1) { + switch (c) { + case 'i': + pathname = optarg; + break; + case 't': + type = optarg; + break; + } + } + + fp = bcm4908img_open(pathname, "r"); + if (!fp) { + fprintf(stderr, "Failed to open BCM4908 image\n"); + err = -EACCES; + goto err_out; + } + + err = bcm4908img_parse(fp, &info); + if (err) { + fprintf(stderr, "Failed to parse BCM4908 image\n"); + goto err_close; + } + + if (!strcmp(type, "cferom")) { + offset = 0; + length = info.cferom_size; + if (!length) { + err = -ENOENT; + fprintf(stderr, "This BCM4908 image doesn't contain cferom\n"); + goto err_close; + } + } else if (!strcmp(type, "firmware")) { + offset = info.vendor_header_size + info.cferom_size; + length = info.file_size - offset - sizeof(struct bcm4908img_tail); + } else { + err = -EINVAL; + fprintf(stderr, "Unsupported extract type: %s\n", type); + goto err_close; + } + + if (!length) { + err = -EINVAL; + fprintf(stderr, "No data to extract specified\n"); + goto err_close; + } + + fseek(fp, offset, SEEK_SET); + while (length && (bytes = fread(buf, 1, bcm4908img_min(sizeof(buf), length), fp)) > 0) { + fwrite(buf, bytes, 1, stdout); + length -= bytes; + } + if (length) { + err = -EIO; + fprintf(stderr, "Failed to read last %zd B of data\n", length); + goto err_close; + } + +err_close: + bcm4908img_close(fp); +err_out: + return err; +} + /************************************************** * Start **************************************************/ @@ -485,6 +565,11 @@ static void usage() { printf("\t-f file\t\t\t\tadd data from specified file\n"); printf("\t-a alignment\t\t\tpad image with zeros to specified alignment\n"); printf("\t-A offset\t\t\t\tappend zeros until reaching specified offset\n"); + printf("\n"); + printf("Extracting from a BCM4908 image:\n"); + printf("\tbcm4908img extract \n"); + printf("\t-i \t\t\t\tinput BCM490 image\n"); + printf("\t-t \t\t\t\tone of: cferom, bootfs, rootfs, firmware\n"); } int main(int argc, char **argv) { @@ -494,6 +579,8 @@ int main(int argc, char **argv) { return bcm4908img_info(argc, argv); else if (!strcmp(argv[1], "create")) return bcm4908img_create(argc, argv); + else if (!strcmp(argv[1], "extract")) + return bcm4908img_extract(argc, argv); } usage(); -- 2.30.2