Browse Source

[util] Allow Option::ROM to access multiple ROM images

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 12 years ago
parent
commit
f2e5f8813e
3 changed files with 129 additions and 53 deletions
  1. 70
    4
      src/util/Option/ROM.pm
  2. 53
    47
      src/util/disrom.pl
  3. 6
    2
      src/util/fixrom.pl

+ 70
- 4
src/util/Option/ROM.pm View File

@@ -169,9 +169,11 @@ use Exporter 'import';
169 169
 
170 170
 use constant ROM_SIGNATURE => 0xaa55;
171 171
 use constant PCI_SIGNATURE => 'PCIR';
172
+use constant PCI_LAST_IMAGE => 0x80;
172 173
 use constant PNP_SIGNATURE => '$PnP';
173 174
 
174
-our @EXPORT_OK = qw ( ROM_SIGNATURE PCI_SIGNATURE PNP_SIGNATURE );
175
+our @EXPORT_OK = qw ( ROM_SIGNATURE PCI_SIGNATURE PCI_LAST_IMAGE
176
+		      PNP_SIGNATURE );
175 177
 our %EXPORT_TAGS = ( all => [ @EXPORT_OK ] );
176 178
 
177 179
 use constant JMP_SHORT => 0xeb;
@@ -241,6 +243,53 @@ sub new {
241 243
 
242 244
 =pod
243 245
 
246
+=item C<< set ( $data ) >>
247
+
248
+Set option ROM contents.
249
+
250
+=cut
251
+
252
+sub set {
253
+  my $hash = shift;
254
+  my $self = tied(%$hash);
255
+  my $data = shift;
256
+
257
+  # Store data
258
+  $self->{data} = \$data;
259
+
260
+  # Split out any data belonging to the next image
261
+  delete $self->{next_image};
262
+  my $length = ( $hash->{length} * 512 );
263
+  my $pci_header = $hash->pci_header();
264
+  if ( ( $length < length $data ) &&
265
+       ( defined $pci_header ) &&
266
+       ( ! ( $pci_header->{last_image} & PCI_LAST_IMAGE ) ) ) {
267
+    my $remainder = substr ( $data, $length );
268
+    $data = substr ( $data, 0, $length );
269
+    $self->{next_image} = new Option::ROM;
270
+    $self->{next_image}->set ( $remainder );
271
+  }
272
+}
273
+
274
+=pod
275
+
276
+=item C<< get () >>
277
+
278
+Get option ROM contents.
279
+
280
+=cut
281
+
282
+sub get {
283
+  my $hash = shift;
284
+  my $self = tied(%$hash);
285
+
286
+  my $data = ${$self->{data}};
287
+  $data .= $self->{next_image}->get() if $self->{next_image};
288
+  return $data;
289
+}
290
+
291
+=pod
292
+
244 293
 =item C<< load ( $filename ) >>
245 294
 
246 295
 Load option ROM contents from the file C<$filename>.
@@ -256,8 +305,8 @@ sub load {
256 305
 
257 306
   open my $fh, "<$filename"
258 307
       or croak "Cannot open $filename for reading: $!";
259
-  read $fh, my $data, ( 128 * 1024 ); # 128kB is theoretical max size
260
-  $self->{data} = \$data;
308
+  read $fh, my $data, -s $fh;
309
+  $hash->set ( $data );
261 310
   close $fh;
262 311
 }
263 312
 
@@ -279,7 +328,8 @@ sub save {
279 328
 
280 329
   open my $fh, ">$filename"
281 330
       or croak "Cannot open $filename for writing: $!";
282
-  print $fh ${$self->{data}};
331
+  my $data = $hash->get();
332
+  print $fh $data;
283 333
   close $fh;
284 334
 }
285 335
 
@@ -339,6 +389,22 @@ sub pnp_header {
339 389
 
340 390
 =pod
341 391
 
392
+=item C<< next_image () >>
393
+
394
+Return a C<Option::ROM> object representing the next image within the
395
+ROM, if present.
396
+
397
+=cut
398
+
399
+sub next_image {
400
+  my $hash = shift;
401
+  my $self = tied(%$hash);
402
+
403
+  return $self->{next_image};
404
+}
405
+
406
+=pod
407
+
342 408
 =item C<< checksum () >>
343 409
 
344 410
 Calculate the byte checksum of the ROM.

+ 53
- 47
src/util/disrom.pl View File

@@ -27,55 +27,61 @@ my $romfile = shift || "-";
27 27
 my $rom = new Option::ROM;
28 28
 $rom->load ( $romfile );
29 29
 
30
-die "Not an option ROM image\n"
31
-    unless $rom->{signature} == ROM_SIGNATURE;
30
+do {
32 31
 
33
-my $romlength = ( $rom->{length} * 512 );
34
-my $filelength = $rom->length;
35
-die "ROM image truncated (is $filelength, should be $romlength)\n"
36
-    if $filelength < $romlength;
32
+  die "Not an option ROM image\n"
33
+      unless $rom->{signature} == ROM_SIGNATURE;
37 34
 
38
-printf "ROM header:\n\n";
39
-printf "  %-16s 0x%02x (%d)\n", "Length:", $rom->{length}, ( $rom->{length} * 512 );
40
-printf "  %-16s 0x%02x (%s0x%02x)\n", "Checksum:", $rom->{checksum},
41
-       ( ( $rom->checksum == 0 ) ? "" : "INCORRECT: " ), $rom->checksum;
42
-printf "  %-16s 0x%04x\n", "Init:", $rom->{init};
43
-printf "  %-16s 0x%04x\n", "UNDI header:", $rom->{undi_header};
44
-printf "  %-16s 0x%04x\n", "PCI header:", $rom->{pci_header};
45
-printf "  %-16s 0x%04x\n", "PnP header:", $rom->{pnp_header};
46
-printf "\n";
35
+  my $romlength = ( $rom->{length} * 512 );
36
+  my $filelength = $rom->length;
37
+  die "ROM image truncated (is $filelength, should be $romlength)\n"
38
+      if $filelength < $romlength;
47 39
 
48
-my $pci = $rom->pci_header();
49
-if ( $pci ) {
50
-  printf "PCI header:\n\n";
51
-  printf "  %-16s %s\n", "Signature:", $pci->{signature};
52
-  printf "  %-16s 0x%04x\n", "Vendor ID:", $pci->{vendor_id};
53
-  printf "  %-16s 0x%04x\n", "Device ID:", $pci->{device_id};
54
-  printf "  %-16s 0x%02x%02x%02x\n", "Device class:",
55
-	 $pci->{base_class}, $pci->{sub_class}, $pci->{prog_intf};
56
-  printf "  %-16s 0x%04x (%d)\n", "Image length:",
57
-	 $pci->{image_length}, ( $pci->{image_length} * 512 );
58
-  printf "  %-16s 0x%04x (%d)\n", "Runtime length:",
59
-	 $pci->{runtime_length}, ( $pci->{runtime_length} * 512 );
60
-  if ( exists $pci->{conf_header} ) {
61
-    printf "  %-16s 0x%04x\n", "Config header:", $pci->{conf_header};
62
-    printf "  %-16s 0x%04x\n", "CLP entry:", $pci->{clp_entry};
63
-  }
40
+  printf "ROM header:\n\n";
41
+  printf "  %-16s 0x%02x (%d)\n", "Length:",
42
+	 $rom->{length}, ( $rom->{length} * 512 );
43
+  printf "  %-16s 0x%02x (%s0x%02x)\n", "Checksum:", $rom->{checksum},
44
+	 ( ( $rom->checksum == 0 ) ? "" : "INCORRECT: " ), $rom->checksum;
45
+  printf "  %-16s 0x%04x\n", "Init:", $rom->{init};
46
+  printf "  %-16s 0x%04x\n", "UNDI header:", $rom->{undi_header};
47
+  printf "  %-16s 0x%04x\n", "PCI header:", $rom->{pci_header};
48
+  printf "  %-16s 0x%04x\n", "PnP header:", $rom->{pnp_header};
64 49
   printf "\n";
65
-}
66 50
 
67
-my $pnp = $rom->pnp_header();
68
-if ( $pnp ) {
69
-  printf "PnP header:\n\n";
70
-  printf "  %-16s %s\n", "Signature:", $pnp->{signature};
71
-  printf "  %-16s 0x%02x (%s0x%02x)\n", "Checksum:", $pnp->{checksum},
72
-	 ( ( $pnp->checksum == 0 ) ? "" : "INCORRECT: " ), $pnp->checksum;
73
-  printf "  %-16s 0x%04x \"%s\"\n", "Manufacturer:",
74
-	 $pnp->{manufacturer}, $pnp->manufacturer;
75
-  printf "  %-16s 0x%04x \"%s\"\n", "Product:",
76
-	 $pnp->{product}, $pnp->product;
77
-  printf "  %-16s 0x%04x\n", "BCV:", $pnp->{bcv};
78
-  printf "  %-16s 0x%04x\n", "BDV:", $pnp->{bdv};
79
-  printf "  %-16s 0x%04x\n", "BEV:", $pnp->{bev};
80
-  printf "\n";
81
-}
51
+  my $pci = $rom->pci_header();
52
+  if ( $pci ) {
53
+    printf "PCI header:\n\n";
54
+    printf "  %-16s %s\n", "Signature:", $pci->{signature};
55
+    printf "  %-16s 0x%04x\n", "Vendor ID:", $pci->{vendor_id};
56
+    printf "  %-16s 0x%04x\n", "Device ID:", $pci->{device_id};
57
+    printf "  %-16s 0x%02x%02x%02x\n", "Device class:",
58
+	   $pci->{base_class}, $pci->{sub_class}, $pci->{prog_intf};
59
+    printf "  %-16s 0x%04x (%d)\n", "Image length:",
60
+	   $pci->{image_length}, ( $pci->{image_length} * 512 );
61
+    printf "  %-16s 0x%04x (%d)\n", "Runtime length:",
62
+	   $pci->{runtime_length}, ( $pci->{runtime_length} * 512 );
63
+    printf "  %-16s 0x%02x\n", "Code type:", $pci->{code_type};
64
+    if ( exists $pci->{conf_header} ) {
65
+      printf "  %-16s 0x%04x\n", "Config header:", $pci->{conf_header};
66
+      printf "  %-16s 0x%04x\n", "CLP entry:", $pci->{clp_entry};
67
+    }
68
+    printf "\n";
69
+  }
70
+
71
+  my $pnp = $rom->pnp_header();
72
+  if ( $pnp ) {
73
+    printf "PnP header:\n\n";
74
+    printf "  %-16s %s\n", "Signature:", $pnp->{signature};
75
+    printf "  %-16s 0x%02x (%s0x%02x)\n", "Checksum:", $pnp->{checksum},
76
+	   ( ( $pnp->checksum == 0 ) ? "" : "INCORRECT: " ), $pnp->checksum;
77
+    printf "  %-16s 0x%04x \"%s\"\n", "Manufacturer:",
78
+	   $pnp->{manufacturer}, $pnp->manufacturer;
79
+    printf "  %-16s 0x%04x \"%s\"\n", "Product:",
80
+	   $pnp->{product}, $pnp->product;
81
+    printf "  %-16s 0x%04x\n", "BCV:", $pnp->{bcv};
82
+    printf "  %-16s 0x%04x\n", "BDV:", $pnp->{bdv};
83
+    printf "  %-16s 0x%04x\n", "BEV:", $pnp->{bev};
84
+    printf "\n";
85
+  }
86
+
87
+} while ( $rom = $rom->next_image );

+ 6
- 2
src/util/fixrom.pl View File

@@ -28,7 +28,11 @@ my @romfiles = @ARGV;
28 28
 foreach my $romfile ( @romfiles ) {
29 29
   my $rom = new Option::ROM;
30 30
   $rom->load ( $romfile );
31
-  $rom->pnp_header->fix_checksum() if $rom->pnp_header;
32
-  $rom->fix_checksum();
31
+  my $image = $rom;
32
+  while ( $image ) {
33
+    $image->pnp_header->fix_checksum() if $image->pnp_header;
34
+    $image->fix_checksum();
35
+    $image = $image->next_image();
36
+  }
33 37
   $rom->save ( $romfile );
34 38
 }

Loading…
Cancel
Save