aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorRafał Miłecki <rafal@milecki.pl>2021-04-05 19:30:06 +0200
committerRafał Miłecki <rafal@milecki.pl>2021-04-07 00:21:40 +0200
commite33957c241abf8f0dbf5f3713058d126fb4599b4 (patch)
treed7332ba725321cf586200029bd8e93d0e3a138b3 /tools
parent5314cab729b743d3b8b08db4e01c3095017f4e68 (diff)
downloadupstream-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')
-rw-r--r--tools/firmware-utils/src/bcm4908img.c35
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);