mirror of
https://github.com/ipxe/ipxe
synced 2025-12-20 20:10:18 +03:00
[util] Add Option::ROM library and rewrite disrom.pl to use it.
The Option::ROM module provides an easy way to read and edit fields within option ROM headers.
This commit is contained in:
@@ -1,114 +1,75 @@
|
||||
#!/usr/bin/perl -w
|
||||
#
|
||||
# Program to display key information about a boot ROM
|
||||
# including PCI and PnP structures
|
||||
# Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
#
|
||||
# GPL, Ken Yap 2001
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 2 of the
|
||||
# License, or any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
use bytes;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
sub getid ($)
|
||||
{
|
||||
my ($offset) = @_;
|
||||
use FindBin;
|
||||
use lib "$FindBin::Bin";
|
||||
use Option::ROM qw ( :all );
|
||||
|
||||
return '' if ($offset == 0 or $offset > $len);
|
||||
my ($string) = unpack('Z32', substr($data, $offset, 32));
|
||||
return ($string);
|
||||
my $romfile = shift || "-";
|
||||
my $rom = new Option::ROM;
|
||||
$rom->load ( $romfile );
|
||||
|
||||
die "Not an option ROM image\n"
|
||||
unless $rom->{signature} == ROM_SIGNATURE;
|
||||
|
||||
my $romlength = ( $rom->{length} * 512 );
|
||||
my $filelength = $rom->length;
|
||||
die "ROM image truncated (is $filelength, should be $romlength)\n"
|
||||
if $filelength < $romlength;
|
||||
|
||||
printf "ROM header:\n\n";
|
||||
printf " Length:\t0x%02x (%d)\n", $rom->{length}, ( $rom->{length} * 512 );
|
||||
printf " Checksum:\t0x%02x (0x%02x)\n", $rom->{checksum}, $rom->checksum;
|
||||
printf " UNDI header:\t0x%04x\n", $rom->{undi_header};
|
||||
printf " PCI header:\t0x%04x\n", $rom->{pci_header};
|
||||
printf " PnP header:\t0x%04x\n", $rom->{pnp_header};
|
||||
printf "\n";
|
||||
|
||||
my $pci = $rom->pci_header();
|
||||
if ( $pci ) {
|
||||
printf "PCI header:\n\n";
|
||||
printf " Signature:\t%s\n", $pci->{signature};
|
||||
printf " Vendor id:\t0x%04x\n", $pci->{vendor_id};
|
||||
printf " Device id:\t0x%04x\n", $pci->{device_id};
|
||||
printf " Device class:\t0x%02x%02x%02x\n",
|
||||
$pci->{base_class}, $pci->{sub_class}, $pci->{prog_intf};
|
||||
printf " Image length:\t0x%04x (%d)\n",
|
||||
$pci->{image_length}, ( $pci->{image_length} * 512 );
|
||||
printf " Runtime length:\t0x%04x (%d)\n",
|
||||
$pci->{runtime_length}, ( $pci->{runtime_length} * 512 );
|
||||
printf " Config header:\t0x%04x\n", $pci->{conf_header};
|
||||
printf " CLP entry:\t0x%04x\n", $pci->{clp_entry};
|
||||
printf "\n";
|
||||
}
|
||||
|
||||
sub dispci
|
||||
{
|
||||
my ($pcidata) = substr($data, $pci, 0x18);
|
||||
my ($dummy, $vendorid, $deviceid, $vpd, $pcilen, $pcirev,
|
||||
$class1, $class2, $class3, $imglen, $coderev, $codetype,
|
||||
$indicator) = unpack('a4v4C4v2C2', $pcidata);
|
||||
$imglen *= 512;
|
||||
my $vendorstr = sprintf('%#04x', $vendorid);
|
||||
my $devicestr = sprintf('%#04x', $deviceid);
|
||||
my $coderevstr = sprintf('%#04x', $coderev);
|
||||
print <<EOF;
|
||||
PCI structure:
|
||||
|
||||
Vital product data: $vpd
|
||||
Vendor ID: $vendorstr
|
||||
Device ID: $devicestr
|
||||
Device base type: $class1
|
||||
Device sub type: $class2
|
||||
Device interface type: $class3
|
||||
Image length: $imglen
|
||||
Code revision: $coderevstr
|
||||
Code type: $codetype
|
||||
Indicator: $indicator
|
||||
|
||||
EOF
|
||||
my $pnp = $rom->pnp_header();
|
||||
if ( $pnp ) {
|
||||
printf "PnP header:\n\n";
|
||||
printf " Signature:\t%s\n", $pnp->{signature};
|
||||
printf " Checksum:\t0x%02x (0x%02x)\n", $pnp->{checksum}, $pnp->checksum;
|
||||
printf " Manufacturer:\t0x%04x \"%s\"\n",
|
||||
$pnp->{manufacturer}, $pnp->manufacturer;
|
||||
printf " Product:\t0x%04x \"%s\"\n", $pnp->{product}, $pnp->product;
|
||||
printf " BCV:\t\t0x%04x\n", $pnp->{bcv};
|
||||
printf " BDV:\t\t0x%04x\n", $pnp->{bdv};
|
||||
printf " BEV:\t\t0x%04x\n", $pnp->{bev};
|
||||
printf "\n";
|
||||
}
|
||||
|
||||
sub dispnp
|
||||
{
|
||||
my ($pnpdata) = substr($data, $pnp, 0x20);
|
||||
my ($dummy1, $pnprev, $pnplen, $nextpnp, $dummy2,
|
||||
$pnpcsum, $deviceid, $mfrid, $productid,
|
||||
$class1, $class2, $class3, $indicator,
|
||||
$bcv, $dv, $bev, $dummy, $sri) = unpack('a4C2vC2a4v2C4v5', $pnpdata);
|
||||
print <<EOF;
|
||||
PnP structure:
|
||||
|
||||
EOF
|
||||
print 'Vendor: ', &getid($mfrid), "\n";
|
||||
print 'Device: ', &getid($productid), "\n";
|
||||
my $indicatorstr = sprintf('%#02x', $indicator);
|
||||
my $bcvstr = sprintf('%#04x', $bcv);
|
||||
my $dvstr = sprintf('%#04x', $dv);
|
||||
my $bevstr = sprintf('%#04x', $bev);
|
||||
my $sristr = sprintf('%#04x', $sri);
|
||||
my $checksum = unpack('%8C*', $pnpdata);
|
||||
print <<EOF;
|
||||
Device base type: $class1
|
||||
Device sub type: $class2
|
||||
Device interface type: $class3
|
||||
Device indicator: $indicatorstr
|
||||
Boot connection vector: $bcvstr
|
||||
Disconnect vector: $dvstr
|
||||
Bootstrap entry vector: $bevstr
|
||||
Static resource information vector: $sristr
|
||||
Checksum: $checksum
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
sub pcipnp
|
||||
{
|
||||
($pci, $pnp) = unpack('v2', substr($data, 0x18, 4));
|
||||
if ($pci >= $len or $pnp >= $len) {
|
||||
print "$file: Not a PCI PnP ROM image\n";
|
||||
return;
|
||||
}
|
||||
if (substr($data, $pci, 4) ne 'PCIR' or substr($data, $pnp, 4) ne '$PnP') {
|
||||
print "$file: No PCI and PNP structures, not a PCI PNP ROM image\n";
|
||||
return;
|
||||
}
|
||||
&dispci();
|
||||
&dispnp();
|
||||
}
|
||||
|
||||
$file = $#ARGV >= 0 ? $ARGV[0] : '-';
|
||||
open(F, "$file") or die "$file: $!\n";
|
||||
binmode(F);
|
||||
# Handle up to 64kB ROM images
|
||||
$len = read(F, $data, 64*1024);
|
||||
close(F);
|
||||
defined($len) or die "$file: $!\n";
|
||||
substr($data, 0, 2) eq "\x55\xAA" or die "$file: Not a boot ROM image\n";
|
||||
my ($codelen) = unpack('C', substr($data, 2, 1));
|
||||
$codelen *= 512;
|
||||
if ($codelen < $len) {
|
||||
my $pad = $len - $codelen;
|
||||
print "Image is $codelen bytes and has $pad bytes of padding following\n";
|
||||
$data = substr($data, 0, $codelen);
|
||||
} elsif ($codelen > $len) {
|
||||
print "Image should be $codelen bytes but is truncated to $len bytes\n";}
|
||||
&pcipnp();
|
||||
($csum) = unpack('%8C*', $data);
|
||||
print "ROM checksum: $csum \n";
|
||||
exit(0);
|
||||
|
||||
Reference in New Issue
Block a user