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;
};
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;
}
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)) {
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;
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:
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;
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)) {
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;