+ inspect_fw_pstr("File name", inspect_info.file_name);
+ inspect_fw_phexdec("File size", inspect_info.file_size);
+
+ if (BE32_TO_HOST(hdr->version) != HEADER_VERSION_V1) {
+ ERR("file does not seem to have V1 header!\n");
+ goto out_free_buf;
+ }
+
+ inspect_fw_phexdec("Version 1 Header size", sizeof(struct fw_header));
+
+ if (BE32_TO_HOST(hdr->unk1) != 0)
+ inspect_fw_phexdec("Unknown value 1", hdr->unk1);
+
+ memcpy(md5sum, hdr->md5sum1, sizeof(md5sum));
+ if (BE32_TO_HOST(hdr->boot_len) == 0)
+ memcpy(hdr->md5sum1, md5salt_normal, sizeof(md5sum));
+ else
+ memcpy(hdr->md5sum1, md5salt_boot, sizeof(md5sum));
+ get_md5(buf, inspect_info.file_size, hdr->md5sum1);
+
+ if (memcmp(md5sum, hdr->md5sum1, sizeof(md5sum))) {
+ inspect_fw_pmd5sum("Header MD5Sum1", md5sum, "(*ERROR*)");
+ inspect_fw_pmd5sum(" --> expected", hdr->md5sum1, "");
+ } else {
+ inspect_fw_pmd5sum("Header MD5Sum1", md5sum, "(ok)");
+ }
+ if (BE32_TO_HOST(hdr->unk2) != 0)
+ inspect_fw_phexdec("Unknown value 2", hdr->unk2);
+ inspect_fw_pmd5sum("Header MD5Sum2", hdr->md5sum2,
+ "(purpose yet unknown, unchecked here)");
+ if (BE32_TO_HOST(hdr->unk3) != 0)
+ inspect_fw_phexdec("Unknown value 3", hdr->unk3);
+
+ printf("\n");
+
+ inspect_fw_pstr("Vendor name", hdr->vendor_name);
+ inspect_fw_pstr("Firmware version", hdr->fw_version);
+ board = find_board_by_hwid(BE32_TO_HOST(hdr->hw_id));
+ if (board) {
+ inspect_fw_phexpost("Hardware ID",
+ BE32_TO_HOST(hdr->hw_id), board->id);
+ inspect_fw_phexexp("Hardware Revision",
+ BE32_TO_HOST(hdr->hw_rev), board->hw_rev);
+ } else {
+ inspect_fw_phexpost("Hardware ID",
+ BE32_TO_HOST(hdr->hw_id), "unknown");
+ inspect_fw_phex("Hardware Revision",
+ BE32_TO_HOST(hdr->hw_rev));
+ }
+
+ printf("\n");
+
+ inspect_fw_phexdec("Kernel data offset",
+ BE32_TO_HOST(hdr->kernel_ofs));
+ inspect_fw_phexdec("Kernel data length",
+ BE32_TO_HOST(hdr->kernel_len));
+ if (board) {
+ inspect_fw_phexdef("Kernel load address",
+ BE32_TO_HOST(hdr->kernel_la),
+ board->kernel_la);
+ inspect_fw_phexdef("Kernel entry point",
+ BE32_TO_HOST(hdr->kernel_ep),
+ board->kernel_ep);
+ inspect_fw_phexdecdef("Rootfs data offset",
+ BE32_TO_HOST(hdr->rootfs_ofs),
+ board->rootfs_ofs);
+ } else {
+ inspect_fw_phex("Kernel load address",
+ BE32_TO_HOST(hdr->kernel_la));
+ inspect_fw_phex("Kernel entry point",
+ BE32_TO_HOST(hdr->kernel_ep));
+ inspect_fw_phexdec("Rootfs data offset",
+ BE32_TO_HOST(hdr->rootfs_ofs));
+ }
+ inspect_fw_phexdec("Rootfs data length",
+ BE32_TO_HOST(hdr->rootfs_len));
+ inspect_fw_phexdec("Boot loader data offset",
+ BE32_TO_HOST(hdr->boot_ofs));
+ inspect_fw_phexdec("Boot loader data length",
+ BE32_TO_HOST(hdr->boot_len));
+ inspect_fw_phexdec("Total firmware length",
+ BE32_TO_HOST(hdr->fw_length));
+
+ if (extract) {
+ FILE *fp;
+ char *filename;
+
+ printf("\n");
+
+ filename = malloc(strlen(inspect_info.file_name) + 8);
+ sprintf(filename, "%s-kernel", inspect_info.file_name);
+ printf("Extracting kernel to \"%s\"...\n", filename);
+ fp = fopen(filename, "w");
+ if (fp) {
+ if (!fwrite(buf + BE32_TO_HOST(hdr->kernel_ofs),
+ BE32_TO_HOST(hdr->kernel_len), 1, fp)) {
+ ERR("error in fwrite(): %s", strerror(errno));
+ }
+ fclose(fp);
+ } else {
+ ERR("error in fopen(): %s", strerror(errno));
+ }
+ free(filename);
+
+ filename = malloc(strlen(inspect_info.file_name) + 8);
+ sprintf(filename, "%s-rootfs", inspect_info.file_name);
+ printf("Extracting rootfs to \"%s\"...\n", filename);
+ fp = fopen(filename, "w");
+ if (fp) {
+ if (!fwrite(buf + BE32_TO_HOST(hdr->rootfs_ofs),
+ BE32_TO_HOST(hdr->rootfs_len), 1, fp)) {
+ ERR("error in fwrite(): %s", strerror(errno));
+ }
+ fclose(fp);
+ } else {
+ ERR("error in fopen(): %s", strerror(errno));
+ }
+ free(filename);
+ }