64128698c2d311ed81942abdc7547b6b7b674b21
[people/mcb30/gpxe.git] / src / util / disrom.pl
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);