#!/usr/bin/perl use warnings; use strict; undef $/; my $rom = <>; my $base = 0xFFFFFFFF - length($rom) + 1; printf "ROM len: %08x\n", length($rom); printf "ROM base: %08x\n", $base; sub uint32 { my $offset = shift; return unpack("V", substr($rom, $offset - $base, 4)); } sub uint64 { my $offset = shift; return unpack("Q", substr($rom, $offset - $base, 8)); } # Assume the ROM is mapped to the top of 4GB my $fit_ptr = uint32(0xFFFFFFC0); my $fit_offset = $fit_ptr - $base; printf "FIT pointer: %08x (offset %08x)\n", $fit_ptr, $fit_offset; die "FIT pointer out of range?\n" if $fit_offset >= length($rom); my $fit = substr($rom, $fit_ptr - $base, 8); printf "Signature: '%s'\n", $fit; die "Bad signature?\n" unless $fit eq '_FIT_ '; my $entries = uint32($fit_ptr + 0x8); my %entry_types = ( 0x00 => "Header", 0x01 => "Microcode", 0x02 => "Startup ACM", 0x07 => "BIOS Startup Module", 0x08 => "TPM Policy", 0x09 => "BIOS Policy", 0x0A => "TXT Policy", 0x0B => "Key Manifest", 0x0C => "Boot Policy Manifest", 0x10 => "CSE Secure Boot", 0x2D => "TXTSX Policy", 0x2F => "JMP Debug Policy", 0x7F => "SKIP", ); for my $i (1..$entries-1) { my ($address, $len, $ver, $type, $csum) = unpack( "QVSCC", substr($rom, $fit_ptr - $base + $i*0x10, 0x10)); printf "%d: address %08x @ %08x: ver %04x type %s (0x%02x)\n", $i, $address, $len, $ver, $entry_types{$type} || "Unknown", $type, ; }