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>
(cherry picked from commit e33957c241)
			
			
This commit is contained in:
		| @@ -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); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Rafał Miłecki
					Rafał Miłecki