diff options
author | Rafał Miłecki <rafal@milecki.pl> | 2021-04-02 16:31:43 +0200 |
---|---|---|
committer | Rafał Miłecki <rafal@milecki.pl> | 2021-04-05 10:05:25 +0200 |
commit | 9c039d56a154bb416492bf5657093576d50cc220 (patch) | |
tree | 070b7781af84d378b0987c2a603a27da28b76a21 /tools | |
parent | 6af45b842bd22633fa3ccd57edaf073a759525bb (diff) | |
download | upstream-9c039d56a154bb416492bf5657093576d50cc220.tar.gz upstream-9c039d56a154bb416492bf5657093576d50cc220.tar.bz2 upstream-9c039d56a154bb416492bf5657093576d50cc220.zip |
firmware-utils: bcm4908img: support extracting image data
It's useful for upgrading cferom, firmware, etc.
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/firmware-utils/src/bcm4908img.c | 87 |
1 files changed, 87 insertions, 0 deletions
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 @@ -470,6 +470,86 @@ out: } /************************************************** + * 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 <options>\n"); + printf("\t-i <file>\t\t\t\tinput BCM490 image\n"); + printf("\t-t <type>\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(); |