[openwrt/openwrt] firmware-utils: bcm4908img: replace size with offset

LEDE Commits lede-commits at lists.infradead.org
Thu Apr 8 12:40:58 BST 2021


rmilecki pushed a commit to openwrt/openwrt.git, branch openwrt-21.02:
https://git.openwrt.org/cbf8ac82c6e4aea62510ffe10dee85eb8a79e2fb

commit cbf8ac82c6e4aea62510ffe10dee85eb8a79e2fb
Author: Rafał Miłecki <rafal at milecki.pl>
AuthorDate: Tue Apr 6 01:06:52 2021 +0200

    firmware-utils: bcm4908img: replace size with offset
    
    It's much easier to operate on BCM4908 image data with absolute offset
    of each section stored. It doesn't require summing sizes over and over.
    
    Signed-off-by: Rafał Miłecki <rafal at milecki.pl>
    (cherry picked from commit 5314cab729b743d3b8b08db4e01c3095017f4e68)
---
 tools/firmware-utils/src/bcm4908img.c | 55 ++++++++++++++++++++++-------------
 1 file changed, 35 insertions(+), 20 deletions(-)

diff --git a/tools/firmware-utils/src/bcm4908img.c b/tools/firmware-utils/src/bcm4908img.c
index 536056d42a..ac76bd1c61 100644
--- a/tools/firmware-utils/src/bcm4908img.c
+++ b/tools/firmware-utils/src/bcm4908img.c
@@ -64,11 +64,21 @@ struct bcm4908img_tail {
 	uint32_t flags;
 };
 
-/* Info about BCM4908 image */
+/**
+ * struct bcm4908img_info - info about BCM4908 image
+ *
+ * Standard BCM4908 image consists of:
+ * 1. (Optional) vedor header
+ * 2. (Optional) cferom
+ * 3. bootfs  ─┐
+ * 4. padding  ├─ firmware
+ * 5. rootfs  ─┘
+ * 6. BCM4908 tail
+ */
 struct bcm4908img_info {
 	size_t file_size;
-	size_t vendor_header_size;	/* Vendor header size */
-	size_t cferom_size;
+	size_t cferom_offset;
+	size_t bootfs_offset;
 	uint32_t crc32;			/* Calculated checksum */
 	struct bcm4908img_tail tail;
 };
@@ -200,10 +210,11 @@ static int bcm4908img_calc_crc32(FILE *fp, struct bcm4908img_info *info) {
 	size_t length;
 	size_t bytes;
 
-	fseek(fp, info->vendor_header_size, SEEK_SET);
+	/* Start with cferom (or bootfs) - skip vendor header */
+	fseek(fp, info->cferom_offset, SEEK_SET);
 
 	info->crc32 = 0xffffffff;
-	length = info->file_size - info->vendor_header_size - sizeof(struct bcm4908img_tail);
+	length = info->file_size - info->cferom_offset - sizeof(struct bcm4908img_tail);
 	while (length && (bytes = fread(buf, 1, bcm4908img_min(sizeof(buf), length), fp)) > 0) {
 		info->crc32 = bcm4908img_crc32(info->crc32, buf, bytes);
 		length -= bytes;
@@ -263,14 +274,16 @@ static int bcm4908img_parse(FILE *fp, struct bcm4908img_info *info) {
 	}
 	chk = (void *)buf;
 	if (be32_to_cpu(chk->magic) == 0x2a23245e)
-		info->vendor_header_size = be32_to_cpu(chk->header_len);
+		info->cferom_offset = be32_to_cpu(chk->header_len);
 
-	/* Sizes */
+	/* Offsets */
 
-	for (; info->vendor_header_size + info->cferom_size <= info->file_size; info->cferom_size += 0x20000) {
-		if (fseek(fp, info->vendor_header_size + info->cferom_size, SEEK_SET)) {
+	for (info->bootfs_offset = info->cferom_offset;
+	     info->bootfs_offset < info->file_size;
+	     info->bootfs_offset += 0x20000) {
+		if (fseek(fp, info->bootfs_offset, SEEK_SET)) {
 			err = -errno;
-			fprintf(stderr, "Failed to fseek to the 0x%zx\n", info->cferom_size);
+			fprintf(stderr, "Failed to fseek to the 0x%zx\n", info->bootfs_offset);
 			return err;
 		}
 		if (fread(&tmp16, 1, sizeof(tmp16), fp) != sizeof(tmp16)) {
@@ -280,17 +293,18 @@ static int bcm4908img_parse(FILE *fp, struct bcm4908img_info *info) {
 		if (be16_to_cpu(tmp16) == 0x8519)
 			break;
 	}
-	if (info->vendor_header_size + info->cferom_size >= info->file_size) {
-		fprintf(stderr, "Failed to find cferom size (no bootfs found)\n");
+	if (info->bootfs_offset >= info->file_size) {
+		fprintf(stderr, "Failed to find bootfs offset\n");
 		return -EPROTO;
 	}
 
 	/* CRC32 */
 
-	fseek(fp, info->vendor_header_size, SEEK_SET);
+	/* Start with cferom (or bootfs) - skip vendor header */
+	fseek(fp, info->cferom_offset, SEEK_SET);
 
 	info->crc32 = 0xffffffff;
-	length = info->file_size - info->vendor_header_size - sizeof(*tail);
+	length = info->file_size - info->cferom_offset - sizeof(*tail);
 	while (length && (bytes = fread(buf, 1, bcm4908img_min(sizeof(buf), length), fp)) > 0) {
 		info->crc32 = bcm4908img_crc32(info->crc32, buf, bytes);
 		length -= bytes;
@@ -349,8 +363,9 @@ static int bcm4908img_info(int argc, char **argv) {
 		goto err_close;
 	}
 
-	printf("Vendor header length:\t%zu\n", info.vendor_header_size);
-	printf("cferom size:\t0x%zx\n", info.cferom_size);
+	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("Checksum:\t0x%08x\n", info.crc32);
 
 err_close:
@@ -537,14 +552,14 @@ static int bcm4908img_extract(int argc, char **argv) {
 
 	if (!strcmp(type, "cferom")) {
 		offset = 0;
-		length = info.cferom_size;
+		length = info.bootfs_offset - offset;
 		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;
+		offset = info.bootfs_offset;
 		length = info.file_size - offset - sizeof(struct bcm4908img_tail);
 	} else {
 		err = -EINVAL;
@@ -648,7 +663,7 @@ static int bcm4908img_bootfs_ls(FILE *fp, struct bcm4908img_info *info) {
 	size_t bytes;
 	int err = 0;
 
-	for (offset = info->vendor_header_size + info->cferom_size; ; offset += (je32_to_cpu(node.totlen) + 0x03) & ~0x03) {
+	for (offset = info->bootfs_offset; ; offset += (je32_to_cpu(node.totlen) + 0x03) & ~0x03) {
 		char name[FILENAME_MAX + 1];
 
 		if (fseek(fp, offset, SEEK_SET)) {
@@ -719,7 +734,7 @@ static int bcm4908img_bootfs_mv(FILE *fp, struct bcm4908img_info *info, int argc
 		return -EINVAL;
 	}
 
-	for (offset = info->vendor_header_size + info->cferom_size; ; offset += (je32_to_cpu(node.totlen) + 0x03) & ~0x03) {
+	for (offset = info->bootfs_offset; ; offset += (je32_to_cpu(node.totlen) + 0x03) & ~0x03) {
 		char name[FILENAME_MAX];
 		uint32_t crc32;
 



More information about the lede-commits mailing list