+/**************************************************
+ * Existing firmware parser
+ **************************************************/
+
+static int bcm4908img_parse(FILE *fp, struct bcm4908img_info *info) {
+ struct bcm4908img_tail *tail = &info->tail;
+ struct stat st;
+ uint8_t buf[1024];
+ size_t length;
+ size_t bytes;
+ int err = 0;
+
+ memset(info, 0, sizeof(*info));
+
+ /* File size */
+
+ if (fstat(fileno(fp), &st)) {
+ err = -errno;
+ fprintf(stderr, "Failed to fstat: %d\n", err);
+ return err;
+ }
+ info->file_size = st.st_size;
+
+ /* CRC32 */
+
+ fseek(fp, prefix_len, SEEK_SET);
+
+ info->crc32 = 0xffffffff;
+ length = info->file_size - prefix_len - sizeof(*tail) - suffix_len;
+ while (length && (bytes = fread(buf, 1, bcm4908img_min(sizeof(buf), length), fp)) > 0) {
+ info->crc32 = bcm4908img_crc32(info->crc32, buf, bytes);
+ length -= bytes;
+ }
+ if (length) {
+ fprintf(stderr, "Failed to read last %zd B of data\n", length);
+ return -EIO;
+ }
+
+ /* Tail */
+
+ if (fread(tail, 1, sizeof(*tail), fp) != sizeof(*tail)) {
+ fprintf(stderr, "Failed to read BCM4908 image tail\n");
+ return -EIO;
+ }
+
+ /* Standard validation */
+
+ if (info->crc32 != le32_to_cpu(tail->crc32)) {
+ fprintf(stderr, "Invalid data crc32: 0x%08x instead of 0x%08x\n", info->crc32, le32_to_cpu(tail->crc32));
+ return -EPROTO;
+ }
+
+ return 0;
+}
+