summaryrefslogtreecommitdiff
path: root/gpxe/src/util
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2008-09-07 22:41:29 -0700
committerH. Peter Anvin <hpa@zytor.com>2008-09-07 22:41:29 -0700
commitc14f98ab23dbc912aa9db26d86434a4d2bd80a5f (patch)
treea0b1d6fd48ad30f8af19a88d11a8f4e61cebf52f /gpxe/src/util
parent3506d7fb195922b04c941650b1512440bdcc89e4 (diff)
downloadsyslinux-c14f98ab23dbc912aa9db26d86434a4d2bd80a5f.tar.gz
gPXE: update gPXE to current git
Update gPXE to current git. gpxe-for-syslinux e3ef2094cfa26f874c5f8dbd687eb311830efcf0 gpxe main tree 8223084afc206000312611a3fcfa30a28500d1a3
Diffstat (limited to 'gpxe/src/util')
-rw-r--r--gpxe/src/util/Option/ROM.pm46
-rwxr-xr-xgpxe/src/util/disrom.pl162
-rw-r--r--gpxe/src/util/mergerom.pl28
-rw-r--r--gpxe/src/util/zbin.c3
4 files changed, 131 insertions, 108 deletions
diff --git a/gpxe/src/util/Option/ROM.pm b/gpxe/src/util/Option/ROM.pm
index f5c33f8a..a86d3262 100644
--- a/gpxe/src/util/Option/ROM.pm
+++ b/gpxe/src/util/Option/ROM.pm
@@ -73,7 +73,10 @@ sub FETCH {
my $raw = substr ( ${$self->{data}},
( $self->{offset} + $self->{fields}->{$key}->{offset} ),
$self->{fields}->{$key}->{length} );
- return unpack ( $self->{fields}->{$key}->{pack}, $raw );
+ my $unpack = ( ref $self->{fields}->{$key}->{unpack} ?
+ $self->{fields}->{$key}->{unpack} :
+ sub { unpack ( $self->{fields}->{$key}->{pack}, shift ); } );
+ return &$unpack ( $raw );
}
sub STORE {
@@ -82,7 +85,10 @@ sub STORE {
my $value = shift;
croak "Nonexistent field \"$key\"" unless $self->EXISTS ( $key );
- my $raw = pack ( $self->{fields}->{$key}->{pack}, $value );
+ my $pack = ( ref $self->{fields}->{$key}->{pack} ?
+ $self->{fields}->{$key}->{pack} :
+ sub { pack ( $self->{fields}->{$key}->{pack}, shift ); } );
+ my $raw = &$pack ( $value );
substr ( ${$self->{data}},
( $self->{offset} + $self->{fields}->{$key}->{offset} ),
$self->{fields}->{$key}->{length} ) = $raw;
@@ -168,6 +174,38 @@ use constant PNP_SIGNATURE => '$PnP';
our @EXPORT_OK = qw ( ROM_SIGNATURE PCI_SIGNATURE PNP_SIGNATURE );
our %EXPORT_TAGS = ( all => [ @EXPORT_OK ] );
+use constant JMP_SHORT => 0xeb;
+use constant JMP_NEAR => 0xe9;
+
+sub pack_init {
+ my $dest = shift;
+
+ # Always create a near jump; it's simpler
+ if ( $dest ) {
+ return pack ( "CS", JMP_NEAR, ( $dest - 6 ) );
+ } else {
+ return pack ( "CS", 0, 0 );
+ }
+}
+
+sub unpack_init {
+ my $instr = shift;
+
+ # Accept both short and near jumps
+ my $jump = unpack ( "C", $instr );
+ if ( $jump == JMP_SHORT ) {
+ my $offset = unpack ( "xC", $instr );
+ return ( $offset + 5 );
+ } elsif ( $jump == JMP_NEAR ) {
+ my $offset = unpack ( "xS", $instr );
+ return ( $offset + 6 );
+ } elsif ( $jump == 0 ) {
+ return 0;
+ } else {
+ croak "Unrecognised jump instruction in init vector\n";
+ }
+}
+
=pod
=item C<< new () >>
@@ -187,7 +225,11 @@ sub new {
fields => {
signature => { offset => 0x00, length => 0x02, pack => "S" },
length => { offset => 0x02, length => 0x01, pack => "C" },
+ # "init" is part of a jump instruction
+ init => { offset => 0x03, length => 0x03,
+ pack => \&pack_init, unpack => \&unpack_init },
checksum => { offset => 0x06, length => 0x01, pack => "C" },
+ bofm_header => { offset => 0x14, length => 0x02, pack => "S" },
undi_header => { offset => 0x16, length => 0x02, pack => "S" },
pci_header => { offset => 0x18, length => 0x02, pack => "S" },
pnp_header => { offset => 0x1a, length => 0x02, pack => "S" },
diff --git a/gpxe/src/util/disrom.pl b/gpxe/src/util/disrom.pl
index 64128698..80ac4af8 100755
--- a/gpxe/src/util/disrom.pl
+++ b/gpxe/src/util/disrom.pl
@@ -1,114 +1,76 @@
#!/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;
-
-sub getid ($)
-{
- my ($offset) = @_;
-
- return '' if ($offset == 0 or $offset > $len);
- my ($string) = unpack('Z32', substr($data, $offset, 32));
- return ($string);
-}
+use strict;
+use warnings;
-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:
+use FindBin;
+use lib "$FindBin::Bin";
+use Option::ROM qw ( :all );
-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
+my $romfile = shift || "-";
+my $rom = new Option::ROM;
+$rom->load ( $romfile );
-EOF
-}
+die "Not an option ROM image\n"
+ unless $rom->{signature} == ROM_SIGNATURE;
-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:
+my $romlength = ( $rom->{length} * 512 );
+my $filelength = $rom->length;
+die "ROM image truncated (is $filelength, should be $romlength)\n"
+ if $filelength < $romlength;
-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
+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 " Init:\t\t0x%04x\n", $rom->{init};
+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";
-EOF
+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 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();
+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";
}
-
-$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);
diff --git a/gpxe/src/util/mergerom.pl b/gpxe/src/util/mergerom.pl
index ce1befb7..f9c52502 100644
--- a/gpxe/src/util/mergerom.pl
+++ b/gpxe/src/util/mergerom.pl
@@ -23,6 +23,18 @@ use FindBin;
use lib "$FindBin::Bin";
use Option::ROM qw ( :all );
+sub merge_entry_points {
+ my $baserom_entry = \shift;
+ my $rom_entry = \shift;
+ my $offset = shift;
+
+ if ( $$rom_entry ) {
+ my $old_entry = $$baserom_entry;
+ $$baserom_entry = ( $offset + $$rom_entry );
+ $$rom_entry = $old_entry;
+ }
+}
+
my @romfiles = @ARGV;
my @roms = map { my $rom = new Option::ROM; $rom->load($_); $rom } @romfiles;
@@ -34,6 +46,12 @@ foreach my $rom ( @roms ) {
# Update base length
$baserom->{length} += $rom->{length};
+ # Merge initialisation entry point
+ merge_entry_points ( $baserom->{init}, $rom->{init}, $offset );
+
+ # Merge BOFM header
+ merge_entry_points ( $baserom->{bofm_header}, $rom->{bofm_header}, $offset );
+
# Update PCI header, if present in both
my $baserom_pci = $baserom->pci_header;
my $rom_pci = $rom->pci_header;
@@ -52,8 +70,8 @@ foreach my $rom ( @roms ) {
# Merge CLP entry point
if ( exists ( $baserom_pci->{clp_entry} ) &&
exists ( $rom_pci->{clp_entry} ) ) {
- $baserom_pci->{clp_entry} = ( $offset + $rom_pci->{clp_entry} )
- if $rom_pci->{clp_entry};
+ merge_entry_points ( $baserom_pci->{clp_entry}, $rom_pci->{clp_entry},
+ $offset );
}
}
@@ -61,9 +79,9 @@ foreach my $rom ( @roms ) {
my $baserom_pnp = $baserom->pnp_header;
my $rom_pnp = $rom->pnp_header;
if ( $baserom_pnp && $rom_pnp ) {
- $baserom_pnp->{bcv} = ( $offset + $rom_pnp->{bcv} ) if $rom_pnp->{bcv};
- $baserom_pnp->{bdv} = ( $offset + $rom_pnp->{bdv} ) if $rom_pnp->{bdv};
- $baserom_pnp->{bev} = ( $offset + $rom_pnp->{bev} ) if $rom_pnp->{bev};
+ merge_entry_points ( $baserom_pnp->{bcv}, $rom_pnp->{bcv}, $offset );
+ merge_entry_points ( $baserom_pnp->{bdv}, $rom_pnp->{bdv}, $offset );
+ merge_entry_points ( $baserom_pnp->{bev}, $rom_pnp->{bev}, $offset );
}
# Fix checksum for this ROM segment
diff --git a/gpxe/src/util/zbin.c b/gpxe/src/util/zbin.c
index f47fa36b..b24f401e 100644
--- a/gpxe/src/util/zbin.c
+++ b/gpxe/src/util/zbin.c
@@ -90,7 +90,8 @@ static int read_file ( const char *filename, void **buf, size_t *len ) {
return 0;
err:
- fclose ( file );
+ if ( file )
+ fclose ( file );
return -1;
}