diff options
author | H. Peter Anvin <hpa@zytor.com> | 2008-09-07 22:41:29 -0700 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2008-09-07 22:41:29 -0700 |
commit | c14f98ab23dbc912aa9db26d86434a4d2bd80a5f (patch) | |
tree | a0b1d6fd48ad30f8af19a88d11a8f4e61cebf52f /gpxe/src/util | |
parent | 3506d7fb195922b04c941650b1512440bdcc89e4 (diff) | |
download | syslinux-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.pm | 46 | ||||
-rwxr-xr-x | gpxe/src/util/disrom.pl | 162 | ||||
-rw-r--r-- | gpxe/src/util/mergerom.pl | 28 | ||||
-rw-r--r-- | gpxe/src/util/zbin.c | 3 |
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; } |