aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorRafał Miłecki <rafal@milecki.pl>2021-04-02 16:31:43 +0200
committerRafał Miłecki <rafal@milecki.pl>2021-04-05 10:05:25 +0200
commit9c039d56a154bb416492bf5657093576d50cc220 (patch)
tree070b7781af84d378b0987c2a603a27da28b76a21 /tools
parent6af45b842bd22633fa3ccd57edaf073a759525bb (diff)
downloadupstream-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.c87
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();