]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[romprefix] Report a pessimistic runtime size estimate
authorMichael Brown <mcb30@ipxe.org>
Mon, 23 Jul 2012 16:41:38 +0000 (17:41 +0100)
committerMichael Brown <mcb30@ipxe.org>
Mon, 23 Jul 2012 16:57:40 +0000 (17:57 +0100)
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>
src/arch/i386/prefix/romprefix.S
src/util/Option/ROM.pm
src/util/disrom.pl
src/util/fixrom.pl

index 2719a70aa2c126d600576256a7e3a8122677ac66..2b4c20b8e83725d93c27ad7114713ea65821bd55 100644 (file)
@@ -63,6 +63,8 @@ romheader_size:       .byte 0                 /* Size in 512-byte blocks */
        jmp     init                    /* Initialisation vector */
 checksum:
        .byte   0
+       .org    0x10
+       .word   ipxeheader
        .org    0x16
        .word   undiheader
        .org    0x18
@@ -78,9 +80,6 @@ checksum:
        .long   0
        .previous
 
-build_id:
-       .long   _build_id               /* Randomly-generated build ID */
-
 pciheader:
        .ascii  "PCIR"                  /* Signature */
        .word   pci_vendor_id           /* Vendor identification */ 
@@ -106,7 +105,7 @@ pciheader_runtime_length:
        .long   pciheader_image_length
        .long   512
        .long   0
-       .ascii  "ADHW"
+       .ascii  ZINFO_TYPE_ADxW
        .long   pciheader_runtime_length
        .long   512
        .long   0
@@ -175,6 +174,25 @@ undiheader:
        .equ undiheader_len, . - undiheader
        .size undiheader, . - undiheader
 
+ipxeheader:
+       .ascii  "iPXE"                  /* Signature */
+       .byte   ipxeheader_len          /* Length of structure */
+       .byte   0                       /* Checksum */
+shrunk_rom_size:
+       .byte   0                       /* Shrunk size (in 512-byte blocks) */
+       .byte   0                       /* Reserved */
+build_id:
+       .long   _build_id               /* Randomly-generated build ID */
+       .equ ipxeheader_len, . - ipxeheader
+       .size ipxeheader, . - ipxeheader
+
+       .section ".zinfo.fixup", "a", @progbits /* Compressor fixups */
+       .ascii  "ADHB"
+       .long   shrunk_rom_size
+       .long   512
+       .long   0
+       .previous
+
 /* Initialisation (called once during POST)
  *
  * Determine whether or not this is a PnP system via a signature
@@ -354,7 +372,7 @@ pmm_scan:
        addr32 rep movsl        /* PMM presence implies flat real mode */
        popw    %es
        /* Shrink ROM */
-       movw    pciheader_runtime_length, %ax
+       movb    shrunk_rom_size, %al
        movb    %al, romheader_size
 1:     /* Allocate decompression PMM block.  Round up the size to the
         * nearest 128kB and use the size within the PMM handle; this
index fdc5e4ae98b6aea228def21561bd0d8533dd9038..82d654261cef891aa120c9532081525f82bad245 100644 (file)
@@ -172,9 +172,10 @@ use constant ROM_SIGNATURE => 0xaa55;
 use constant PCI_SIGNATURE => 'PCIR';
 use constant PCI_LAST_IMAGE => 0x80;
 use constant PNP_SIGNATURE => '$PnP';
+use constant IPXE_SIGNATURE => 'iPXE';
 
 our @EXPORT_OK = qw ( ROM_SIGNATURE PCI_SIGNATURE PCI_LAST_IMAGE
-                     PNP_SIGNATURE );
+                     PNP_SIGNATURE IPXE_SIGNATURE );
 our %EXPORT_TAGS = ( all => [ @EXPORT_OK ] );
 
 use constant JMP_SHORT => 0xeb;
@@ -232,6 +233,7 @@ sub new {
       init =>          { offset => 0x03, length => 0x03,
                          pack => \&pack_init, unpack => \&unpack_init },
       checksum =>      { offset => 0x06, length => 0x01, pack => "C" },
+      ipxe_header =>   { offset => 0x10, length => 0x02, pack => "S" },
       bofm_header =>   { offset => 0x14, length => 0x02, pack => "S" },
       undi_header =>   { offset => 0x16, length => 0x02, pack => "S" },
       pci_header =>    { offset => 0x18, length => 0x02, pack => "S" },
@@ -390,6 +392,25 @@ sub pnp_header {
 
 =pod
 
+=item C<< ipxe_header () >>
+
+Return a C<Option::ROM::iPXE> object representing the ROM's iPXE
+header, if present.
+
+=cut
+
+sub ipxe_header {
+  my $hash = shift;
+  my $self = tied(%$hash);
+
+  my $offset = $hash->{ipxe_header};
+  return undef unless $offset != 0;
+
+  return Option::ROM::iPXE->new ( $self->{data}, $offset );
+}
+
+=pod
+
 =item C<< next_image () >>
 
 Return a C<Option::ROM> object representing the next image within the
@@ -566,4 +587,58 @@ sub product {
   return unpack ( "Z*", $raw );
 }
 
+##############################################################################
+#
+# Option::ROM::iPXE
+#
+##############################################################################
+
+package Option::ROM::iPXE;
+
+use strict;
+use warnings;
+use Carp;
+use bytes;
+
+sub new {
+  my $class = shift;
+  my $data = shift;
+  my $offset = shift;
+
+  my $hash = {};
+  tie %$hash, "Option::ROM::Fields", {
+    data => $data,
+    offset => $offset,
+    length => 0x06,
+    fields => {
+      signature =>     { offset => 0x00, length => 0x04, pack => "a4" },
+      struct_length => { offset => 0x04, length => 0x01, pack => "C" },
+      checksum =>      { offset => 0x05, length => 0x01, pack => "C" },
+      shrunk_length => { offset => 0x06, length => 0x01, pack => "C" },
+      build_id =>      { offset => 0x08, length => 0x04, pack => "L" },
+    },
+  };
+  bless $hash, $class;
+
+  # Retrieve true length of structure
+  my $self = tied ( %$hash );
+  $self->{length} = $hash->{struct_length};
+
+  return $hash;
+}
+
+sub checksum {
+  my $hash = shift;
+  my $self = tied(%$hash);
+
+  return $self->checksum();
+}
+
+sub fix_checksum {
+  my $hash = shift;
+  my $self = tied(%$hash);
+
+  $hash->{checksum} = ( ( $hash->{checksum} - $hash->checksum() ) & 0xff );
+}
+
 1;
index c133c26a87d376ff7cdec178879626e3430eef4c..87138686089d1847ccc9ae03ea1e8f488e82bca9 100755 (executable)
@@ -85,4 +85,15 @@ do {
     printf "\n";
   }
 
+  my $ipxe = $rom->ipxe_header();
+  if ( $ipxe ) {
+    printf "iPXE header:\n\n";
+    printf "  %-16s 0x%02x (%s0x%02x)\n", "Checksum:", $ipxe->{checksum},
+          ( ( $ipxe->checksum == 0 ) ? "" : "INCORRECT: " ), $ipxe->checksum;
+    printf "  %-16s 0x%02x (%d)\n", "Shrunk length:",
+          $ipxe->{shrunk_length}, ( $ipxe->{shrunk_length} * 512 );
+    printf "  %-16s 0x%08x\n", "Build ID:", $ipxe->{build_id};
+    printf "\n";
+  }
+
 } while ( $rom = $rom->next_image );
index c84e2cf2f086bc57add45ea82b8625736a2251f4..8987b5129df83cf6571ade02a6a2d3847a959b8f 100755 (executable)
@@ -32,6 +32,7 @@ foreach my $romfile ( @romfiles ) {
   my $image = $rom;
   while ( $image ) {
     $image->pnp_header->fix_checksum() if $image->pnp_header;
+    $image->ipxe_header->fix_checksum() if $image->ipxe_header;
     $image->fix_checksum();
     $image = $image->next_image();
   }