1 | #!/usr/bin/perl -w
|
---|
2 | #
|
---|
3 | # Program to display key information about a boot ROM
|
---|
4 | # including PCI and PnP structures
|
---|
5 | #
|
---|
6 | # GPL, Ken Yap 2001
|
---|
7 | #
|
---|
8 |
|
---|
9 | use bytes;
|
---|
10 |
|
---|
11 | sub getid ($)
|
---|
12 | {
|
---|
13 | my ($offset) = @_;
|
---|
14 |
|
---|
15 | return '' if ($offset == 0 or $offset > $len);
|
---|
16 | my ($string) = unpack('Z32', substr($data, $offset, 32));
|
---|
17 | return ($string);
|
---|
18 | }
|
---|
19 |
|
---|
20 | sub dispci
|
---|
21 | {
|
---|
22 | my ($pcidata) = substr($data, $pci, 0x18);
|
---|
23 | my ($dummy, $vendorid, $deviceid, $vpd, $pcilen, $pcirev,
|
---|
24 | $class1, $class2, $class3, $imglen, $coderev, $codetype,
|
---|
25 | $indicator) = unpack('a4v4C4v2C2', $pcidata);
|
---|
26 | $imglen *= 512;
|
---|
27 | my $vendorstr = sprintf('%#04x', $vendorid);
|
---|
28 | my $devicestr = sprintf('%#04x', $deviceid);
|
---|
29 | my $coderevstr = sprintf('%#04x', $coderev);
|
---|
30 | print <<EOF;
|
---|
31 | PCI structure:
|
---|
32 |
|
---|
33 | Vital product data: $vpd
|
---|
34 | Vendor ID: $vendorstr
|
---|
35 | Device ID: $devicestr
|
---|
36 | Device base type: $class1
|
---|
37 | Device sub type: $class2
|
---|
38 | Device interface type: $class3
|
---|
39 | Image length: $imglen
|
---|
40 | Code revision: $coderevstr
|
---|
41 | Code type: $codetype
|
---|
42 | Indicator: $indicator
|
---|
43 |
|
---|
44 | EOF
|
---|
45 | }
|
---|
46 |
|
---|
47 | sub dispnp
|
---|
48 | {
|
---|
49 | my ($pnpdata) = substr($data, $pnp, 0x20);
|
---|
50 | my ($dummy1, $pnprev, $pnplen, $nextpnp, $dummy2,
|
---|
51 | $pnpcsum, $deviceid, $mfrid, $productid,
|
---|
52 | $class1, $class2, $class3, $indicator,
|
---|
53 | $bcv, $dv, $bev, $dummy, $sri) = unpack('a4C2vC2a4v2C4v5', $pnpdata);
|
---|
54 | print <<EOF;
|
---|
55 | PnP structure:
|
---|
56 |
|
---|
57 | EOF
|
---|
58 | print 'Vendor: ', &getid($mfrid), "\n";
|
---|
59 | print 'Device: ', &getid($productid), "\n";
|
---|
60 | my $indicatorstr = sprintf('%#02x', $indicator);
|
---|
61 | my $bcvstr = sprintf('%#04x', $bcv);
|
---|
62 | my $dvstr = sprintf('%#04x', $dv);
|
---|
63 | my $bevstr = sprintf('%#04x', $bev);
|
---|
64 | my $sristr = sprintf('%#04x', $sri);
|
---|
65 | my $checksum = unpack('%8C*', $pnpdata);
|
---|
66 | print <<EOF;
|
---|
67 | Device base type: $class1
|
---|
68 | Device sub type: $class2
|
---|
69 | Device interface type: $class3
|
---|
70 | Device indicator: $indicatorstr
|
---|
71 | Boot connection vector: $bcvstr
|
---|
72 | Disconnect vector: $dvstr
|
---|
73 | Bootstrap entry vector: $bevstr
|
---|
74 | Static resource information vector: $sristr
|
---|
75 | Checksum: $checksum
|
---|
76 |
|
---|
77 | EOF
|
---|
78 | }
|
---|
79 |
|
---|
80 | sub pcipnp
|
---|
81 | {
|
---|
82 | ($pci, $pnp) = unpack('v2', substr($data, 0x18, 4));
|
---|
83 | if ($pci >= $len or $pnp >= $len) {
|
---|
84 | print "$file: Not a PCI PnP ROM image\n";
|
---|
85 | return;
|
---|
86 | }
|
---|
87 | if (substr($data, $pci, 4) ne 'PCIR' or substr($data, $pnp, 4) ne '$PnP') {
|
---|
88 | print "$file: No PCI and PNP structures, not a PCI PNP ROM image\n";
|
---|
89 | return;
|
---|
90 | }
|
---|
91 | &dispci();
|
---|
92 | &dispnp();
|
---|
93 | }
|
---|
94 |
|
---|
95 | $file = $#ARGV >= 0 ? $ARGV[0] : '-';
|
---|
96 | open(F, "$file") or die "$file: $!\n";
|
---|
97 | binmode(F);
|
---|
98 | # Handle up to 64kB ROM images
|
---|
99 | $len = read(F, $data, 64*1024);
|
---|
100 | close(F);
|
---|
101 | defined($len) or die "$file: $!\n";
|
---|
102 | substr($data, 0, 2) eq "\x55\xAA" or die "$file: Not a boot ROM image\n";
|
---|
103 | my ($codelen) = unpack('C', substr($data, 2, 1));
|
---|
104 | $codelen *= 512;
|
---|
105 | if ($codelen < $len) {
|
---|
106 | my $pad = $len - $codelen;
|
---|
107 | print "Image is $codelen bytes and has $pad bytes of padding following\n";
|
---|
108 | $data = substr($data, 0, $codelen);
|
---|
109 | } elsif ($codelen > $len) {
|
---|
110 | print "Image should be $codelen bytes but is truncated to $len bytes\n";}
|
---|
111 | &pcipnp();
|
---|
112 | ($csum) = unpack('%8C*', $data);
|
---|
113 | print "ROM checksum: $csum \n";
|
---|
114 | exit(0);
|
---|