Browse Source

[util] Allow Option::ROM to understand and modify initialisation entry point

Add support for manipulating the jump instruction that forms the
option ROM initialisation entry point, so that mergerom.pl can treat
it just like other entry points.

Add support for merging the initialisation entry point (and IBM BOFM
table) to mergerom.pl; this is another slightly icky but unfortunately
necessary GPL vs. NDA workaround.  When mergerom.pl replaces an entry
point in the original ROM, it now fills in the corresponding entry
point in the merged ROM with the original value; this allows (for
example) a merged initialisation entry point to do some processing and
then jump back to the original entry point.
tags/v0.9.4
Michael Brown 16 years ago
parent
commit
23bca8f9d8
3 changed files with 66 additions and 7 deletions
  1. 42
    2
      src/util/Option/ROM.pm
  2. 1
    0
      src/util/disrom.pl
  3. 23
    5
      src/util/mergerom.pl

+ 42
- 2
src/util/Option/ROM.pm View File

73
   my $raw = substr ( ${$self->{data}},
73
   my $raw = substr ( ${$self->{data}},
74
 		     ( $self->{offset} + $self->{fields}->{$key}->{offset} ),
74
 		     ( $self->{offset} + $self->{fields}->{$key}->{offset} ),
75
 		     $self->{fields}->{$key}->{length} );
75
 		     $self->{fields}->{$key}->{length} );
76
-  return unpack ( $self->{fields}->{$key}->{pack}, $raw );
76
+  my $unpack = ( ref $self->{fields}->{$key}->{unpack} ?
77
+		 $self->{fields}->{$key}->{unpack} :
78
+		 sub { unpack ( $self->{fields}->{$key}->{pack}, shift ); } );
79
+  return &$unpack ( $raw );
77
 }
80
 }
78
 
81
 
79
 sub STORE {
82
 sub STORE {
82
   my $value = shift;
85
   my $value = shift;
83
 
86
 
84
   croak "Nonexistent field \"$key\"" unless $self->EXISTS ( $key );
87
   croak "Nonexistent field \"$key\"" unless $self->EXISTS ( $key );
85
-  my $raw = pack ( $self->{fields}->{$key}->{pack}, $value );
88
+  my $pack = ( ref $self->{fields}->{$key}->{pack} ?
89
+	       $self->{fields}->{$key}->{pack} :
90
+	       sub { pack ( $self->{fields}->{$key}->{pack}, shift ); } );
91
+  my $raw = &$pack ( $value );
86
   substr ( ${$self->{data}},
92
   substr ( ${$self->{data}},
87
 	   ( $self->{offset} + $self->{fields}->{$key}->{offset} ),
93
 	   ( $self->{offset} + $self->{fields}->{$key}->{offset} ),
88
 	   $self->{fields}->{$key}->{length} ) = $raw;
94
 	   $self->{fields}->{$key}->{length} ) = $raw;
168
 our @EXPORT_OK = qw ( ROM_SIGNATURE PCI_SIGNATURE PNP_SIGNATURE );
174
 our @EXPORT_OK = qw ( ROM_SIGNATURE PCI_SIGNATURE PNP_SIGNATURE );
169
 our %EXPORT_TAGS = ( all => [ @EXPORT_OK ] );
175
 our %EXPORT_TAGS = ( all => [ @EXPORT_OK ] );
170
 
176
 
177
+use constant JMP_SHORT => 0xeb;
178
+use constant JMP_NEAR => 0xe9;
179
+
180
+sub pack_init {
181
+  my $dest = shift;
182
+
183
+  # Always create a near jump; it's simpler
184
+  if ( $dest ) {
185
+    return pack ( "CS", JMP_NEAR, ( $dest - 6 ) );
186
+  } else {
187
+    return pack ( "CS", 0, 0 );
188
+  }
189
+}
190
+
191
+sub unpack_init {
192
+  my $instr = shift;
193
+
194
+  # Accept both short and near jumps
195
+  ( my $jump, my $offset ) = unpack ( "CS", $instr );
196
+  if ( $jump == JMP_SHORT ) {
197
+    return ( $offset + 5 );
198
+  } elsif ( $jump == JMP_NEAR ) {
199
+    return ( $offset + 6 );
200
+  } elsif ( $jump == 0 ) {
201
+    return 0;
202
+  } else {
203
+    croak "Unrecognised jump instruction in init vector\n";
204
+  }
205
+}
206
+
171
 =pod
207
 =pod
172
 
208
 
173
 =item C<< new () >>
209
 =item C<< new () >>
187
     fields => {
223
     fields => {
188
       signature =>	{ offset => 0x00, length => 0x02, pack => "S" },
224
       signature =>	{ offset => 0x00, length => 0x02, pack => "S" },
189
       length =>		{ offset => 0x02, length => 0x01, pack => "C" },
225
       length =>		{ offset => 0x02, length => 0x01, pack => "C" },
226
+      # "init" is part of a jump instruction
227
+      init =>		{ offset => 0x03, length => 0x03,
228
+			  pack => \&pack_init, unpack => \&unpack_init },
190
       checksum =>	{ offset => 0x06, length => 0x01, pack => "C" },
229
       checksum =>	{ offset => 0x06, length => 0x01, pack => "C" },
230
+      bofm_header =>	{ offset => 0x14, length => 0x02, pack => "S" },
191
       undi_header =>	{ offset => 0x16, length => 0x02, pack => "S" },
231
       undi_header =>	{ offset => 0x16, length => 0x02, pack => "S" },
192
       pci_header =>	{ offset => 0x18, length => 0x02, pack => "S" },
232
       pci_header =>	{ offset => 0x18, length => 0x02, pack => "S" },
193
       pnp_header =>	{ offset => 0x1a, length => 0x02, pack => "S" },
233
       pnp_header =>	{ offset => 0x1a, length => 0x02, pack => "S" },

+ 1
- 0
src/util/disrom.pl View File

38
 printf "ROM header:\n\n";
38
 printf "ROM header:\n\n";
39
 printf "  Length:\t0x%02x (%d)\n", $rom->{length}, ( $rom->{length} * 512 );
39
 printf "  Length:\t0x%02x (%d)\n", $rom->{length}, ( $rom->{length} * 512 );
40
 printf "  Checksum:\t0x%02x (0x%02x)\n", $rom->{checksum}, $rom->checksum;
40
 printf "  Checksum:\t0x%02x (0x%02x)\n", $rom->{checksum}, $rom->checksum;
41
+printf "  Init:\t\t0x%04x\n", $rom->{init};
41
 printf "  UNDI header:\t0x%04x\n", $rom->{undi_header};
42
 printf "  UNDI header:\t0x%04x\n", $rom->{undi_header};
42
 printf "  PCI header:\t0x%04x\n", $rom->{pci_header};
43
 printf "  PCI header:\t0x%04x\n", $rom->{pci_header};
43
 printf "  PnP header:\t0x%04x\n", $rom->{pnp_header};
44
 printf "  PnP header:\t0x%04x\n", $rom->{pnp_header};

+ 23
- 5
src/util/mergerom.pl View File

23
 use lib "$FindBin::Bin";
23
 use lib "$FindBin::Bin";
24
 use Option::ROM qw ( :all );
24
 use Option::ROM qw ( :all );
25
 
25
 
26
+sub merge_entry_points {
27
+  my $baserom_entry = \shift;
28
+  my $rom_entry = \shift;
29
+  my $offset = shift;
30
+
31
+  if ( $$rom_entry ) {
32
+    my $old_entry = $$baserom_entry;
33
+    $$baserom_entry = ( $offset + $$rom_entry );
34
+    $$rom_entry = $old_entry;
35
+  }
36
+}
37
+
26
 my @romfiles = @ARGV;
38
 my @romfiles = @ARGV;
27
 my @roms = map { my $rom = new Option::ROM; $rom->load($_); $rom } @romfiles;
39
 my @roms = map { my $rom = new Option::ROM; $rom->load($_); $rom } @romfiles;
28
 
40
 
34
   # Update base length
46
   # Update base length
35
   $baserom->{length} += $rom->{length};
47
   $baserom->{length} += $rom->{length};
36
 
48
 
49
+  # Merge initialisation entry point
50
+  merge_entry_points ( $baserom->{init}, $rom->{init}, $offset );
51
+
52
+  # Merge BOFM header
53
+  merge_entry_points ( $baserom->{bofm_header}, $rom->{bofm_header}, $offset );
54
+
37
   # Update PCI header, if present in both
55
   # Update PCI header, if present in both
38
   my $baserom_pci = $baserom->pci_header;
56
   my $baserom_pci = $baserom->pci_header;
39
   my $rom_pci = $rom->pci_header;
57
   my $rom_pci = $rom->pci_header;
52
     # Merge CLP entry point
70
     # Merge CLP entry point
53
     if ( exists ( $baserom_pci->{clp_entry} ) &&
71
     if ( exists ( $baserom_pci->{clp_entry} ) &&
54
 	 exists ( $rom_pci->{clp_entry} ) ) {
72
 	 exists ( $rom_pci->{clp_entry} ) ) {
55
-      $baserom_pci->{clp_entry} = ( $offset + $rom_pci->{clp_entry} )
56
-	  if $rom_pci->{clp_entry};
73
+      merge_entry_points ( $baserom_pci->{clp_entry}, $rom_pci->{clp_entry},
74
+			   $offset );
57
     }
75
     }
58
   }
76
   }
59
 
77
 
61
   my $baserom_pnp = $baserom->pnp_header;
79
   my $baserom_pnp = $baserom->pnp_header;
62
   my $rom_pnp = $rom->pnp_header;
80
   my $rom_pnp = $rom->pnp_header;
63
   if ( $baserom_pnp && $rom_pnp ) {
81
   if ( $baserom_pnp && $rom_pnp ) {
64
-    $baserom_pnp->{bcv} = ( $offset + $rom_pnp->{bcv} ) if $rom_pnp->{bcv};
65
-    $baserom_pnp->{bdv} = ( $offset + $rom_pnp->{bdv} ) if $rom_pnp->{bdv};
66
-    $baserom_pnp->{bev} = ( $offset + $rom_pnp->{bev} ) if $rom_pnp->{bev};
82
+    merge_entry_points ( $baserom_pnp->{bcv}, $rom_pnp->{bcv}, $offset );
83
+    merge_entry_points ( $baserom_pnp->{bdv}, $rom_pnp->{bdv}, $offset );
84
+    merge_entry_points ( $baserom_pnp->{bev}, $rom_pnp->{bev}, $offset );
67
   }
85
   }
68
 
86
 
69
   # Fix checksum for this ROM segment
87
   # Fix checksum for this ROM segment

Loading…
Cancel
Save