summaryrefslogtreecommitdiffstats
path: root/src/util
diff options
context:
space:
mode:
Diffstat (limited to 'src/util')
-rw-r--r--src/util/Option/ROM.pm44
-rwxr-xr-xsrc/util/disrom.pl1
-rwxr-xr-xsrc/util/mergerom.pl28
3 files changed, 66 insertions, 7 deletions
diff --git a/src/util/Option/ROM.pm b/src/util/Option/ROM.pm
index f5c33f8a2..7a1bb8838 100644
--- a/src/util/Option/ROM.pm
+++ b/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,36 @@ 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, my $offset ) = unpack ( "CS", $instr );
+ if ( $jump == JMP_SHORT ) {
+ return ( $offset + 5 );
+ } elsif ( $jump == JMP_NEAR ) {
+ return ( $offset + 6 );
+ } elsif ( $jump == 0 ) {
+ return 0;
+ } else {
+ croak "Unrecognised jump instruction in init vector\n";
+ }
+}
+
=pod
=item C<< new () >>
@@ -187,7 +223,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/src/util/disrom.pl b/src/util/disrom.pl
index c472037af..80ac4af8f 100755
--- a/src/util/disrom.pl
+++ b/src/util/disrom.pl
@@ -38,6 +38,7 @@ die "ROM image truncated (is $filelength, should be $romlength)\n"
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};
diff --git a/src/util/mergerom.pl b/src/util/mergerom.pl
index ce1befb7f..f9c52502d 100755
--- a/src/util/mergerom.pl
+++ b/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