diff options
author | Rafał Miłecki <rafal@milecki.pl> | 2021-04-05 19:30:06 +0200 |
---|---|---|
committer | Rafał Miłecki <rafal@milecki.pl> | 2021-04-07 00:21:40 +0200 |
commit | e33957c241abf8f0dbf5f3713058d126fb4599b4 (patch) | |
tree | d7332ba725321cf586200029bd8e93d0e3a138b3 /tools/firmware-utils | |
parent | 5314cab729b743d3b8b08db4e01c3095017f4e68 (diff) | |
download | upstream-e33957c241abf8f0dbf5f3713058d126fb4599b4.tar.gz upstream-e33957c241abf8f0dbf5f3713058d126fb4599b4.tar.bz2 upstream-e33957c241abf8f0dbf5f3713058d126fb4599b4.zip |
firmware-utils: bcm4908img: support extracting bootfs & rootfs
It's required for upgrading firmware using single partitions instead of
just blindly writing whole image.
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
Diffstat (limited to 'tools/firmware-utils')
-rw-r--r-- | tools/firmware-utils/src/bcm4908img.c | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/tools/firmware-utils/src/bcm4908img.c b/tools/firmware-utils/src/bcm4908img.c index ac76bd1c61..51c06041d6 100644 --- a/tools/firmware-utils/src/bcm4908img.c +++ b/tools/firmware-utils/src/bcm4908img.c @@ -54,6 +54,8 @@ #define WFI_FLAG_HAS_PMC 0x1 #define WFI_FLAG_SUPPORTS_BTRM 0x2 +#define UBI_EC_HDR_MAGIC 0x55424923 + static int debug; struct bcm4908img_tail { @@ -79,6 +81,7 @@ struct bcm4908img_info { size_t file_size; size_t cferom_offset; size_t bootfs_offset; + size_t rootfs_offset; uint32_t crc32; /* Calculated checksum */ struct bcm4908img_tail tail; }; @@ -298,6 +301,31 @@ static int bcm4908img_parse(FILE *fp, struct bcm4908img_info *info) { return -EPROTO; } + for (info->rootfs_offset = info->bootfs_offset; + info->rootfs_offset < info->file_size; + info->rootfs_offset += 0x20000) { + uint32_t magic; + + if (fseek(fp, info->rootfs_offset, SEEK_SET)) { + err = -errno; + fprintf(stderr, "Failed to fseek: %d\n", err); + return err; + } + + bytes = fread(&magic, 1, sizeof(magic), fp); + if (bytes != sizeof(magic)) { + fprintf(stderr, "Failed to read %zu bytes\n", sizeof(magic)); + return -EIO; + } + + if (be32_to_cpu(magic) == UBI_EC_HDR_MAGIC) + break; + } + if (info->rootfs_offset >= info->file_size) { + fprintf(stderr, "Failed to find rootfs offset\n"); + return -EPROTO; + } + /* CRC32 */ /* Start with cferom (or bootfs) - skip vendor header */ @@ -366,6 +394,7 @@ static int bcm4908img_info(int argc, char **argv) { if (info.bootfs_offset != info.cferom_offset) printf("cferom offset:\t%zu\n", info.cferom_offset); printf("bootfs offset:\t0x%zx\n", info.bootfs_offset); + printf("rootfs offset:\t0x%zx\n", info.rootfs_offset); printf("Checksum:\t0x%08x\n", info.crc32); err_close: @@ -558,6 +587,12 @@ static int bcm4908img_extract(int argc, char **argv) { fprintf(stderr, "This BCM4908 image doesn't contain cferom\n"); goto err_close; } + } else if (!strcmp(type, "bootfs")) { + offset = info.bootfs_offset; + length = info.rootfs_offset - offset; + } else if (!strcmp(type, "rootfs")) { + offset = info.rootfs_offset; + length = info.file_size - offset - sizeof(struct bcm4908img_tail); } else if (!strcmp(type, "firmware")) { offset = info.bootfs_offset; length = info.file_size - offset - sizeof(struct bcm4908img_tail); |