mirror of https://github.com/ipxe/ipxe.git
[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>pull/598/head
parent
ee3636370d
commit
5de45cd3da
|
@ -63,6 +63,8 @@ romheader_size: .byte 0 /* Size in 512-byte blocks */
|
||||||
jmp init /* Initialisation vector */
|
jmp init /* Initialisation vector */
|
||||||
checksum:
|
checksum:
|
||||||
.byte 0
|
.byte 0
|
||||||
|
.org 0x10
|
||||||
|
.word ipxeheader
|
||||||
.org 0x16
|
.org 0x16
|
||||||
.word undiheader
|
.word undiheader
|
||||||
.org 0x18
|
.org 0x18
|
||||||
|
@ -78,9 +80,6 @@ checksum:
|
||||||
.long 0
|
.long 0
|
||||||
.previous
|
.previous
|
||||||
|
|
||||||
build_id:
|
|
||||||
.long _build_id /* Randomly-generated build ID */
|
|
||||||
|
|
||||||
pciheader:
|
pciheader:
|
||||||
.ascii "PCIR" /* Signature */
|
.ascii "PCIR" /* Signature */
|
||||||
.word pci_vendor_id /* Vendor identification */
|
.word pci_vendor_id /* Vendor identification */
|
||||||
|
@ -106,7 +105,7 @@ pciheader_runtime_length:
|
||||||
.long pciheader_image_length
|
.long pciheader_image_length
|
||||||
.long 512
|
.long 512
|
||||||
.long 0
|
.long 0
|
||||||
.ascii "ADHW"
|
.ascii ZINFO_TYPE_ADxW
|
||||||
.long pciheader_runtime_length
|
.long pciheader_runtime_length
|
||||||
.long 512
|
.long 512
|
||||||
.long 0
|
.long 0
|
||||||
|
@ -175,6 +174,25 @@ undiheader:
|
||||||
.equ undiheader_len, . - undiheader
|
.equ undiheader_len, . - undiheader
|
||||||
.size undiheader, . - 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)
|
/* Initialisation (called once during POST)
|
||||||
*
|
*
|
||||||
* Determine whether or not this is a PnP system via a signature
|
* 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 */
|
addr32 rep movsl /* PMM presence implies flat real mode */
|
||||||
popw %es
|
popw %es
|
||||||
/* Shrink ROM */
|
/* Shrink ROM */
|
||||||
movw pciheader_runtime_length, %ax
|
movb shrunk_rom_size, %al
|
||||||
movb %al, romheader_size
|
movb %al, romheader_size
|
||||||
1: /* Allocate decompression PMM block. Round up the size to the
|
1: /* Allocate decompression PMM block. Round up the size to the
|
||||||
* nearest 128kB and use the size within the PMM handle; this
|
* nearest 128kB and use the size within the PMM handle; this
|
||||||
|
|
|
@ -172,9 +172,10 @@ use constant ROM_SIGNATURE => 0xaa55;
|
||||||
use constant PCI_SIGNATURE => 'PCIR';
|
use constant PCI_SIGNATURE => 'PCIR';
|
||||||
use constant PCI_LAST_IMAGE => 0x80;
|
use constant PCI_LAST_IMAGE => 0x80;
|
||||||
use constant PNP_SIGNATURE => '$PnP';
|
use constant PNP_SIGNATURE => '$PnP';
|
||||||
|
use constant IPXE_SIGNATURE => 'iPXE';
|
||||||
|
|
||||||
our @EXPORT_OK = qw ( ROM_SIGNATURE PCI_SIGNATURE PCI_LAST_IMAGE
|
our @EXPORT_OK = qw ( ROM_SIGNATURE PCI_SIGNATURE PCI_LAST_IMAGE
|
||||||
PNP_SIGNATURE );
|
PNP_SIGNATURE IPXE_SIGNATURE );
|
||||||
our %EXPORT_TAGS = ( all => [ @EXPORT_OK ] );
|
our %EXPORT_TAGS = ( all => [ @EXPORT_OK ] );
|
||||||
|
|
||||||
use constant JMP_SHORT => 0xeb;
|
use constant JMP_SHORT => 0xeb;
|
||||||
|
@ -232,6 +233,7 @@ sub new {
|
||||||
init => { offset => 0x03, length => 0x03,
|
init => { offset => 0x03, length => 0x03,
|
||||||
pack => \&pack_init, unpack => \&unpack_init },
|
pack => \&pack_init, unpack => \&unpack_init },
|
||||||
checksum => { offset => 0x06, length => 0x01, pack => "C" },
|
checksum => { offset => 0x06, length => 0x01, pack => "C" },
|
||||||
|
ipxe_header => { offset => 0x10, length => 0x02, pack => "S" },
|
||||||
bofm_header => { offset => 0x14, length => 0x02, pack => "S" },
|
bofm_header => { offset => 0x14, length => 0x02, pack => "S" },
|
||||||
undi_header => { offset => 0x16, length => 0x02, pack => "S" },
|
undi_header => { offset => 0x16, length => 0x02, pack => "S" },
|
||||||
pci_header => { offset => 0x18, length => 0x02, pack => "S" },
|
pci_header => { offset => 0x18, length => 0x02, pack => "S" },
|
||||||
|
@ -390,6 +392,25 @@ sub pnp_header {
|
||||||
|
|
||||||
=pod
|
=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 () >>
|
=item C<< next_image () >>
|
||||||
|
|
||||||
Return a C<Option::ROM> object representing the next image within the
|
Return a C<Option::ROM> object representing the next image within the
|
||||||
|
@ -566,4 +587,58 @@ sub product {
|
||||||
return unpack ( "Z*", $raw );
|
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;
|
1;
|
||||||
|
|
|
@ -85,4 +85,15 @@ do {
|
||||||
printf "\n";
|
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 );
|
} while ( $rom = $rom->next_image );
|
||||||
|
|
|
@ -32,6 +32,7 @@ foreach my $romfile ( @romfiles ) {
|
||||||
my $image = $rom;
|
my $image = $rom;
|
||||||
while ( $image ) {
|
while ( $image ) {
|
||||||
$image->pnp_header->fix_checksum() if $image->pnp_header;
|
$image->pnp_header->fix_checksum() if $image->pnp_header;
|
||||||
|
$image->ipxe_header->fix_checksum() if $image->ipxe_header;
|
||||||
$image->fix_checksum();
|
$image->fix_checksum();
|
||||||
$image = $image->next_image();
|
$image = $image->next_image();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue