Browse Source

[romprefix] Report a pessimistic runtime size estimate

PCI3.0 allows us to report a "runtime size" which can be smaller than
the actual ROM size.  On systems that support PMM our runtime size
will be small (~2.5kB), which helps to conserve the limited option ROM
space.  However, there is no guarantee that the PMM allocation will
succeed, and so we need to report the worst-case runtime size in the
PCI header.

Move the "shrunk ROM size" field from the PCI header to a new "iPXE
ROM header", allowing it to be accessed by ROM-manipulation utilities
such as disrom.pl.

Reported-by: Anton D. Kachalov <mouse@yandex-team.ru>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 12 years ago
parent
commit
5de45cd3da
4 changed files with 111 additions and 6 deletions
  1. 23
    5
      src/arch/i386/prefix/romprefix.S
  2. 76
    1
      src/util/Option/ROM.pm
  3. 11
    0
      src/util/disrom.pl
  4. 1
    0
      src/util/fixrom.pl

+ 23
- 5
src/arch/i386/prefix/romprefix.S View File

@@ -63,6 +63,8 @@ romheader_size:	.byte 0			/* Size in 512-byte blocks */
63 63
 	jmp	init			/* Initialisation vector */
64 64
 checksum:
65 65
 	.byte	0
66
+	.org	0x10
67
+	.word	ipxeheader
66 68
 	.org	0x16
67 69
 	.word	undiheader
68 70
 	.org	0x18
@@ -78,9 +80,6 @@ checksum:
78 80
 	.long	0
79 81
 	.previous
80 82
 
81
-build_id:
82
-	.long	_build_id		/* Randomly-generated build ID */
83
-
84 83
 pciheader:
85 84
 	.ascii	"PCIR"			/* Signature */
86 85
 	.word	pci_vendor_id		/* Vendor identification */ 
@@ -106,7 +105,7 @@ pciheader_runtime_length:
106 105
 	.long	pciheader_image_length
107 106
 	.long	512
108 107
 	.long	0
109
-	.ascii	"ADHW"
108
+	.ascii	ZINFO_TYPE_ADxW
110 109
 	.long	pciheader_runtime_length
111 110
 	.long	512
112 111
 	.long	0
@@ -175,6 +174,25 @@ undiheader:
175 174
 	.equ undiheader_len, . - undiheader
176 175
 	.size undiheader, . - undiheader
177 176
 
177
+ipxeheader:
178
+	.ascii	"iPXE"			/* Signature */
179
+	.byte	ipxeheader_len		/* Length of structure */
180
+	.byte	0			/* Checksum */
181
+shrunk_rom_size:
182
+	.byte	0			/* Shrunk size (in 512-byte blocks) */
183
+	.byte	0			/* Reserved */
184
+build_id:
185
+	.long	_build_id		/* Randomly-generated build ID */
186
+	.equ ipxeheader_len, . - ipxeheader
187
+	.size ipxeheader, . - ipxeheader
188
+
189
+	.section ".zinfo.fixup", "a", @progbits	/* Compressor fixups */
190
+	.ascii	"ADHB"
191
+	.long	shrunk_rom_size
192
+	.long	512
193
+	.long	0
194
+	.previous
195
+
178 196
 /* Initialisation (called once during POST)
179 197
  *
180 198
  * Determine whether or not this is a PnP system via a signature
@@ -354,7 +372,7 @@ pmm_scan:
354 372
 	addr32 rep movsl	/* PMM presence implies flat real mode */
355 373
 	popw	%es
356 374
 	/* Shrink ROM */
357
-	movw	pciheader_runtime_length, %ax
375
+	movb	shrunk_rom_size, %al
358 376
 	movb	%al, romheader_size
359 377
 1:	/* Allocate decompression PMM block.  Round up the size to the
360 378
 	 * nearest 128kB and use the size within the PMM handle; this

+ 76
- 1
src/util/Option/ROM.pm View File

@@ -172,9 +172,10 @@ use constant ROM_SIGNATURE => 0xaa55;
172 172
 use constant PCI_SIGNATURE => 'PCIR';
173 173
 use constant PCI_LAST_IMAGE => 0x80;
174 174
 use constant PNP_SIGNATURE => '$PnP';
175
+use constant IPXE_SIGNATURE => 'iPXE';
175 176
 
176 177
 our @EXPORT_OK = qw ( ROM_SIGNATURE PCI_SIGNATURE PCI_LAST_IMAGE
177
-		      PNP_SIGNATURE );
178
+		      PNP_SIGNATURE IPXE_SIGNATURE );
178 179
 our %EXPORT_TAGS = ( all => [ @EXPORT_OK ] );
179 180
 
180 181
 use constant JMP_SHORT => 0xeb;
@@ -232,6 +233,7 @@ sub new {
232 233
       init =>		{ offset => 0x03, length => 0x03,
233 234
 			  pack => \&pack_init, unpack => \&unpack_init },
234 235
       checksum =>	{ offset => 0x06, length => 0x01, pack => "C" },
236
+      ipxe_header =>	{ offset => 0x10, length => 0x02, pack => "S" },
235 237
       bofm_header =>	{ offset => 0x14, length => 0x02, pack => "S" },
236 238
       undi_header =>	{ offset => 0x16, length => 0x02, pack => "S" },
237 239
       pci_header =>	{ offset => 0x18, length => 0x02, pack => "S" },
@@ -390,6 +392,25 @@ sub pnp_header {
390 392
 
391 393
 =pod
392 394
 
395
+=item C<< ipxe_header () >>
396
+
397
+Return a C<Option::ROM::iPXE> object representing the ROM's iPXE
398
+header, if present.
399
+
400
+=cut
401
+
402
+sub ipxe_header {
403
+  my $hash = shift;
404
+  my $self = tied(%$hash);
405
+
406
+  my $offset = $hash->{ipxe_header};
407
+  return undef unless $offset != 0;
408
+
409
+  return Option::ROM::iPXE->new ( $self->{data}, $offset );
410
+}
411
+
412
+=pod
413
+
393 414
 =item C<< next_image () >>
394 415
 
395 416
 Return a C<Option::ROM> object representing the next image within the
@@ -566,4 +587,58 @@ sub product {
566 587
   return unpack ( "Z*", $raw );
567 588
 }
568 589
 
590
+##############################################################################
591
+#
592
+# Option::ROM::iPXE
593
+#
594
+##############################################################################
595
+
596
+package Option::ROM::iPXE;
597
+
598
+use strict;
599
+use warnings;
600
+use Carp;
601
+use bytes;
602
+
603
+sub new {
604
+  my $class = shift;
605
+  my $data = shift;
606
+  my $offset = shift;
607
+
608
+  my $hash = {};
609
+  tie %$hash, "Option::ROM::Fields", {
610
+    data => $data,
611
+    offset => $offset,
612
+    length => 0x06,
613
+    fields => {
614
+      signature =>	{ offset => 0x00, length => 0x04, pack => "a4" },
615
+      struct_length =>	{ offset => 0x04, length => 0x01, pack => "C" },
616
+      checksum =>	{ offset => 0x05, length => 0x01, pack => "C" },
617
+      shrunk_length =>	{ offset => 0x06, length => 0x01, pack => "C" },
618
+      build_id =>	{ offset => 0x08, length => 0x04, pack => "L" },
619
+    },
620
+  };
621
+  bless $hash, $class;
622
+
623
+  # Retrieve true length of structure
624
+  my $self = tied ( %$hash );
625
+  $self->{length} = $hash->{struct_length};
626
+
627
+  return $hash;
628
+}
629
+
630
+sub checksum {
631
+  my $hash = shift;
632
+  my $self = tied(%$hash);
633
+
634
+  return $self->checksum();
635
+}
636
+
637
+sub fix_checksum {
638
+  my $hash = shift;
639
+  my $self = tied(%$hash);
640
+
641
+  $hash->{checksum} = ( ( $hash->{checksum} - $hash->checksum() ) & 0xff );
642
+}
643
+
569 644
 1;

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

@@ -85,4 +85,15 @@ do {
85 85
     printf "\n";
86 86
   }
87 87
 
88
+  my $ipxe = $rom->ipxe_header();
89
+  if ( $ipxe ) {
90
+    printf "iPXE header:\n\n";
91
+    printf "  %-16s 0x%02x (%s0x%02x)\n", "Checksum:", $ipxe->{checksum},
92
+	   ( ( $ipxe->checksum == 0 ) ? "" : "INCORRECT: " ), $ipxe->checksum;
93
+    printf "  %-16s 0x%02x (%d)\n", "Shrunk length:",
94
+	   $ipxe->{shrunk_length}, ( $ipxe->{shrunk_length} * 512 );
95
+    printf "  %-16s 0x%08x\n", "Build ID:", $ipxe->{build_id};
96
+    printf "\n";
97
+  }
98
+
88 99
 } while ( $rom = $rom->next_image );

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

@@ -32,6 +32,7 @@ foreach my $romfile ( @romfiles ) {
32 32
   my $image = $rom;
33 33
   while ( $image ) {
34 34
     $image->pnp_header->fix_checksum() if $image->pnp_header;
35
+    $image->ipxe_header->fix_checksum() if $image->ipxe_header;
35 36
     $image->fix_checksum();
36 37
     $image = $image->next_image();
37 38
   }

Loading…
Cancel
Save