summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSimon Rettberg2019-02-15 10:38:39 +0100
committerSimon Rettberg2019-02-15 10:38:39 +0100
commit893714cfea74a68b5637f1d9866d1b8d8973cf94 (patch)
tree0bc3209f0dc939a4dab61218c9af71f904bb17e5 /src
parent[efi] Add support for console --update in efifb mode (diff)
parent[init] Show startup and shutdown function names in debug messages (diff)
downloadipxe-893714cfea74a68b5637f1d9866d1b8d8973cf94.tar.gz
ipxe-893714cfea74a68b5637f1d9866d1b8d8973cf94.tar.xz
ipxe-893714cfea74a68b5637f1d9866d1b8d8973cf94.zip
Merge branch 'master' into openslx
Diffstat (limited to 'src')
-rw-r--r--src/arch/x86/core/cachedhcp.c1
-rw-r--r--src/arch/x86/core/runtime.c1
-rw-r--r--src/arch/x86/drivers/net/undionly.c1
-rw-r--r--src/arch/x86/image/initrd.c1
-rw-r--r--src/arch/x86/interface/pcbios/bios_console.c1
-rw-r--r--src/arch/x86/interface/pcbios/hidemem.c1
-rw-r--r--src/arch/x86/prefix/mromprefix.S2
-rw-r--r--src/arch/x86/prefix/romprefix.S2
-rw-r--r--src/core/device.c1
-rw-r--r--src/core/init.c15
-rw-r--r--src/core/malloc.c1
-rw-r--r--src/core/serial.c1
-rw-r--r--src/core/string.c6
-rw-r--r--src/crypto/rbg.c1
-rw-r--r--src/crypto/rootcert.c1
-rw-r--r--src/drivers/usb/ehci.c1
-rw-r--r--src/drivers/usb/xhci.c1
-rw-r--r--src/hci/linux_args.c1
-rw-r--r--src/include/ipxe/init.h1
-rw-r--r--src/interface/efi/efi_snp.c6
-rw-r--r--src/interface/efi/efi_timer.c1
-rw-r--r--src/interface/linux/linux_console.c1
-rw-r--r--src/net/tcp.c1
-rw-r--r--src/tests/string_test.c1
-rw-r--r--src/util/Option/ROM.pm205
-rwxr-xr-xsrc/util/disrom.pl25
-rw-r--r--src/util/efirom.c2
-rw-r--r--src/util/elf2efi.c1
-rw-r--r--src/util/zbin.c12
29 files changed, 237 insertions, 58 deletions
diff --git a/src/arch/x86/core/cachedhcp.c b/src/arch/x86/core/cachedhcp.c
index ff35b9256..dffafe3c9 100644
--- a/src/arch/x86/core/cachedhcp.c
+++ b/src/arch/x86/core/cachedhcp.c
@@ -127,6 +127,7 @@ struct init_fn cachedhcp_init_fn __init_fn ( INIT_NORMAL ) = {
/** Cached DHCPACK startup function */
struct startup_fn cachedhcp_startup_fn __startup_fn ( STARTUP_LATE ) = {
+ .name = "cachedhcp",
.startup = cachedhcp_startup,
};
diff --git a/src/arch/x86/core/runtime.c b/src/arch/x86/core/runtime.c
index d160fee04..f96b23af4 100644
--- a/src/arch/x86/core/runtime.c
+++ b/src/arch/x86/core/runtime.c
@@ -265,5 +265,6 @@ static void runtime_init ( void ) {
/** Command line and initrd initialisation function */
struct startup_fn runtime_startup_fn __startup_fn ( STARTUP_NORMAL ) = {
+ .name = "runtime",
.startup = runtime_init,
};
diff --git a/src/arch/x86/drivers/net/undionly.c b/src/arch/x86/drivers/net/undionly.c
index 9c9ca1274..898372217 100644
--- a/src/arch/x86/drivers/net/undionly.c
+++ b/src/arch/x86/drivers/net/undionly.c
@@ -141,5 +141,6 @@ static void undionly_shutdown ( int booting ) {
}
struct startup_fn startup_undionly __startup_fn ( STARTUP_LATE ) = {
+ .name = "undionly",
.shutdown = undionly_shutdown,
};
diff --git a/src/arch/x86/image/initrd.c b/src/arch/x86/image/initrd.c
index 80c197417..8f6366d3d 100644
--- a/src/arch/x86/image/initrd.c
+++ b/src/arch/x86/image/initrd.c
@@ -300,5 +300,6 @@ static void initrd_startup ( void ) {
/** initrd startup function */
struct startup_fn startup_initrd __startup_fn ( STARTUP_LATE ) = {
+ .name = "initrd",
.startup = initrd_startup,
};
diff --git a/src/arch/x86/interface/pcbios/bios_console.c b/src/arch/x86/interface/pcbios/bios_console.c
index 08fa6d036..52a02fba5 100644
--- a/src/arch/x86/interface/pcbios/bios_console.c
+++ b/src/arch/x86/interface/pcbios/bios_console.c
@@ -547,6 +547,7 @@ static void bios_inject_shutdown ( int booting __unused ) {
/** Keypress injection startup function */
struct startup_fn bios_inject_startup_fn __startup_fn ( STARTUP_NORMAL ) = {
+ .name = "bios_inject",
.startup = bios_inject_startup,
.shutdown = bios_inject_shutdown,
};
diff --git a/src/arch/x86/interface/pcbios/hidemem.c b/src/arch/x86/interface/pcbios/hidemem.c
index a3728123c..1a3022c5d 100644
--- a/src/arch/x86/interface/pcbios/hidemem.c
+++ b/src/arch/x86/interface/pcbios/hidemem.c
@@ -229,6 +229,7 @@ static void unhide_etherboot ( int flags __unused ) {
/** Hide Etherboot startup function */
struct startup_fn hide_etherboot_startup_fn __startup_fn ( STARTUP_EARLY ) = {
+ .name = "hidemem",
.startup = hide_etherboot,
.shutdown = unhide_etherboot,
};
diff --git a/src/arch/x86/prefix/mromprefix.S b/src/arch/x86/prefix/mromprefix.S
index 73a869d90..2b5c6bf64 100644
--- a/src/arch/x86/prefix/mromprefix.S
+++ b/src/arch/x86/prefix/mromprefix.S
@@ -500,7 +500,7 @@ mpciheader:
.word 0x0000 /* Device list pointer */
.word mpciheader_len /* PCI data structure length */
.byte 0x03 /* PCI data structure revision */
- .byte 0x02, 0x00, 0x00 /* Class code */
+ .byte 0x00, 0x00, 0x02 /* Class code */
mpciheader_image_length:
.word 0 /* Image length */
.word 0x0001 /* Revision level */
diff --git a/src/arch/x86/prefix/romprefix.S b/src/arch/x86/prefix/romprefix.S
index 978b07b57..3abef0eaf 100644
--- a/src/arch/x86/prefix/romprefix.S
+++ b/src/arch/x86/prefix/romprefix.S
@@ -96,7 +96,7 @@ pciheader:
.word ( pci_devlist - pciheader ) /* Device list pointer */
.word pciheader_len /* PCI data structure length */
.byte 0x03 /* PCI data structure revision */
- .byte 0x02, 0x00, 0x00 /* Class code */
+ .byte 0x00, 0x00, 0x02 /* Class code */
pciheader_image_length:
.word 0 /* Image length */
.word 0x0001 /* Revision level */
diff --git a/src/core/device.c b/src/core/device.c
index 77d7b719b..efe4eb687 100644
--- a/src/core/device.c
+++ b/src/core/device.c
@@ -111,6 +111,7 @@ static void remove_devices ( int booting __unused ) {
}
struct startup_fn startup_devices __startup_fn ( STARTUP_NORMAL ) = {
+ .name = "devices",
.startup = probe_devices,
.shutdown = remove_devices,
};
diff --git a/src/core/init.c b/src/core/init.c
index d91e44669..c13fd1667 100644
--- a/src/core/init.c
+++ b/src/core/init.c
@@ -36,6 +36,9 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/** "startup() has been called" flag */
static int started = 0;
+/** Colour for debug messages */
+#define colour table_start ( INIT_FNS )
+
/**
* Initialise iPXE
*
@@ -69,11 +72,15 @@ void startup ( void ) {
/* Call registered startup functions */
for_each_table_entry ( startup_fn, STARTUP_FNS ) {
- if ( startup_fn->startup )
+ if ( startup_fn->startup ) {
+ DBGC ( colour, "INIT startup %s...\n",
+ startup_fn->name );
startup_fn->startup();
+ }
}
started = 1;
+ DBGC ( colour, "INIT startup complete\n" );
}
/**
@@ -96,12 +103,16 @@ void shutdown ( int flags ) {
/* Call registered shutdown functions (in reverse order) */
for_each_table_entry_reverse ( startup_fn, STARTUP_FNS ) {
- if ( startup_fn->shutdown )
+ if ( startup_fn->shutdown ) {
+ DBGC ( colour, "INIT shutdown %s...\n",
+ startup_fn->name );
startup_fn->shutdown ( flags );
+ }
}
/* Reset console */
console_reset();
started = 0;
+ DBGC ( colour, "INIT shutdown complete\n" );
}
diff --git a/src/core/malloc.c b/src/core/malloc.c
index 91c8e4d35..0a7843a14 100644
--- a/src/core/malloc.c
+++ b/src/core/malloc.c
@@ -685,6 +685,7 @@ static void shutdown_cache ( int booting __unused ) {
/** Memory allocator shutdown function */
struct startup_fn heap_startup_fn __startup_fn ( STARTUP_EARLY ) = {
+ .name = "heap",
.shutdown = shutdown_cache,
};
diff --git a/src/core/serial.c b/src/core/serial.c
index dd22f6731..bef9ccbab 100644
--- a/src/core/serial.c
+++ b/src/core/serial.c
@@ -181,5 +181,6 @@ struct init_fn serial_console_init_fn __init_fn ( INIT_CONSOLE ) = {
/** Serial console startup function */
struct startup_fn serial_startup_fn __startup_fn ( STARTUP_EARLY ) = {
+ .name = "serial",
.shutdown = serial_shutdown,
};
diff --git a/src/core/string.c b/src/core/string.c
index 5a185e635..5bd9dae8b 100644
--- a/src/core/string.c
+++ b/src/core/string.c
@@ -173,7 +173,7 @@ int strncmp ( const char *first, const char *second, size_t max ) {
int diff;
for ( ; max-- ; first_bytes++, second_bytes++ ) {
- diff = ( *second_bytes - *first_bytes );
+ diff = ( *first_bytes - *second_bytes );
if ( diff )
return diff;
if ( ! *first_bytes )
@@ -195,8 +195,8 @@ int strcasecmp ( const char *first, const char *second ) {
int diff;
for ( ; ; first_bytes++, second_bytes++ ) {
- diff = ( toupper ( *second_bytes ) -
- toupper ( *first_bytes ) );
+ diff = ( toupper ( *first_bytes ) -
+ toupper ( *second_bytes ) );
if ( diff )
return diff;
if ( ! *first_bytes )
diff --git a/src/crypto/rbg.c b/src/crypto/rbg.c
index a5a77e3cd..4b45b3474 100644
--- a/src/crypto/rbg.c
+++ b/src/crypto/rbg.c
@@ -126,6 +126,7 @@ static void rbg_shutdown_fn ( int booting __unused ) {
/** RBG startup table entry */
struct startup_fn startup_rbg __startup_fn ( STARTUP_NORMAL ) = {
+ .name = "rbg",
.startup = rbg_startup_fn,
.shutdown = rbg_shutdown_fn,
};
diff --git a/src/crypto/rootcert.c b/src/crypto/rootcert.c
index f7b9dcfb7..867ff50e8 100644
--- a/src/crypto/rootcert.c
+++ b/src/crypto/rootcert.c
@@ -123,5 +123,6 @@ static void rootcert_init ( void ) {
/** Root certificate initialiser */
struct startup_fn rootcert_startup_fn __startup_fn ( STARTUP_LATE ) = {
+ .name = "rootcert",
.startup = rootcert_init,
};
diff --git a/src/drivers/usb/ehci.c b/src/drivers/usb/ehci.c
index 35cbc8de9..cd3967070 100644
--- a/src/drivers/usb/ehci.c
+++ b/src/drivers/usb/ehci.c
@@ -2098,5 +2098,6 @@ static void ehci_shutdown ( int booting ) {
/** Startup/shutdown function */
struct startup_fn ehci_startup __startup_fn ( STARTUP_LATE ) = {
+ .name = "ehci",
.shutdown = ehci_shutdown,
};
diff --git a/src/drivers/usb/xhci.c b/src/drivers/usb/xhci.c
index ecf8bf4d5..e9a7f4c65 100644
--- a/src/drivers/usb/xhci.c
+++ b/src/drivers/usb/xhci.c
@@ -3363,5 +3363,6 @@ static void xhci_shutdown ( int booting ) {
/** Startup/shutdown function */
struct startup_fn xhci_startup __startup_fn ( STARTUP_LATE ) = {
+ .name = "xhci",
.shutdown = xhci_shutdown,
};
diff --git a/src/hci/linux_args.c b/src/hci/linux_args.c
index 58eeb063e..5f903e3b6 100644
--- a/src/hci/linux_args.c
+++ b/src/hci/linux_args.c
@@ -185,6 +185,7 @@ void linux_args_cleanup(int flags __unused)
}
struct startup_fn startup_linux_args __startup_fn(STARTUP_EARLY) = {
+ .name = "linux_args",
.startup = linux_args_parse,
.shutdown = linux_args_cleanup,
};
diff --git a/src/include/ipxe/init.h b/src/include/ipxe/init.h
index 025cfaf37..32927e3a6 100644
--- a/src/include/ipxe/init.h
+++ b/src/include/ipxe/init.h
@@ -39,6 +39,7 @@ struct init_fn {
* part of the calls to startup() and shutdown().
*/
struct startup_fn {
+ const char *name;
void ( * startup ) ( void );
void ( * shutdown ) ( int booting );
};
diff --git a/src/interface/efi/efi_snp.c b/src/interface/efi/efi_snp.c
index 9c1b14d87..d648700f6 100644
--- a/src/interface/efi/efi_snp.c
+++ b/src/interface/efi/efi_snp.c
@@ -1829,12 +1829,12 @@ static int efi_snp_probe ( struct net_device *netdev ) {
efi_snp_hii_uninstall ( snpdev );
efi_child_del ( efidev->device, snpdev->handle );
err_efi_child_add:
- bs->CloseProtocol ( snpdev->handle, &efi_nii_protocol_guid,
- efi_image_handle, snpdev->handle );
- err_open_nii:
bs->CloseProtocol ( snpdev->handle, &efi_nii31_protocol_guid,
efi_image_handle, snpdev->handle );
err_open_nii31:
+ bs->CloseProtocol ( snpdev->handle, &efi_nii_protocol_guid,
+ efi_image_handle, snpdev->handle );
+ err_open_nii:
bs->UninstallMultipleProtocolInterfaces (
snpdev->handle,
&efi_simple_network_protocol_guid, &snpdev->snp,
diff --git a/src/interface/efi/efi_timer.c b/src/interface/efi/efi_timer.c
index 8fe307ceb..8f40cb81a 100644
--- a/src/interface/efi/efi_timer.c
+++ b/src/interface/efi/efi_timer.c
@@ -212,6 +212,7 @@ static void efi_tick_shutdown ( int booting __unused ) {
/** Timer tick startup function */
struct startup_fn efi_tick_startup_fn __startup_fn ( STARTUP_EARLY ) = {
+ .name = "efi_tick",
.startup = efi_tick_startup,
.shutdown = efi_tick_shutdown,
};
diff --git a/src/interface/linux/linux_console.c b/src/interface/linux/linux_console.c
index 5105eaa94..5294fca79 100644
--- a/src/interface/linux/linux_console.c
+++ b/src/interface/linux/linux_console.c
@@ -150,6 +150,7 @@ static void linux_console_shutdown(int flags __unused)
}
struct startup_fn linux_console_startup_fn __startup_fn(STARTUP_EARLY) = {
+ .name = "linux_console",
.startup = linux_console_startup,
.shutdown = linux_console_shutdown,
};
diff --git a/src/net/tcp.c b/src/net/tcp.c
index cb3b84edd..c445100ad 100644
--- a/src/net/tcp.c
+++ b/src/net/tcp.c
@@ -1654,6 +1654,7 @@ static void tcp_shutdown ( int booting __unused ) {
/** TCP shutdown function */
struct startup_fn tcp_startup_fn __startup_fn ( STARTUP_LATE ) = {
+ .name = "tcp",
.shutdown = tcp_shutdown,
};
diff --git a/src/tests/string_test.c b/src/tests/string_test.c
index 4693b5f65..a66501da3 100644
--- a/src/tests/string_test.c
+++ b/src/tests/string_test.c
@@ -88,6 +88,7 @@ static void string_test_exec ( void ) {
ok ( strcmp ( "Hello", "hello" ) != 0 );
ok ( strcmp ( "Hello", "Hello world!" ) != 0 );
ok ( strcmp ( "Hello world!", "Hello" ) != 0 );
+ ok ( strcmp ( "abc", "def" ) < 0 );
/* Test strncmp() */
ok ( strncmp ( "", "", 0 ) == 0 );
diff --git a/src/util/Option/ROM.pm b/src/util/Option/ROM.pm
index 232cf16b8..51831adf9 100644
--- a/src/util/Option/ROM.pm
+++ b/src/util/Option/ROM.pm
@@ -116,7 +116,9 @@ sub EXISTS {
return ( exists $self->{fields}->{$key} &&
( ( $self->{fields}->{$key}->{offset} +
- $self->{fields}->{$key}->{length} ) <= $self->{length} ) );
+ $self->{fields}->{$key}->{length} ) <= $self->{length} ) &&
+ ( ! defined $self->{fields}->{$key}->{check} ||
+ &{$self->{fields}->{$key}->{check}} ( $self, $key ) ) );
}
sub FIRSTKEY {
@@ -172,10 +174,12 @@ use constant ROM_SIGNATURE => 0xaa55;
use constant PCI_SIGNATURE => 'PCIR';
use constant PCI_LAST_IMAGE => 0x80;
use constant PNP_SIGNATURE => '$PnP';
+use constant UNDI_SIGNATURE => 'UNDI';
use constant IPXE_SIGNATURE => 'iPXE';
+use constant EFI_SIGNATURE => 0x00000ef1;
our @EXPORT_OK = qw ( ROM_SIGNATURE PCI_SIGNATURE PCI_LAST_IMAGE
- PNP_SIGNATURE IPXE_SIGNATURE );
+ PNP_SIGNATURE UNDI_SIGNATURE IPXE_SIGNATURE EFI_SIGNATURE );
our %EXPORT_TAGS = ( all => [ @EXPORT_OK ] );
use constant JMP_SHORT => 0xeb;
@@ -210,10 +214,20 @@ sub unpack_init {
} elsif ( $jump == 0 ) {
return 0;
} else {
- croak "Unrecognised jump instruction in init vector\n";
+ carp "Unrecognised jump instruction in init vector\n";
+ return 0;
}
}
+sub check_pcat_rom {
+ my $self = shift;
+ my $key = shift;
+
+ my $pci = $self->{rom}->pci_header ();
+
+ return ! defined $pci || $pci->{code_type} == 0x00;
+}
+
=pod
=item C<< new () >>
@@ -227,21 +241,29 @@ sub new {
my $hash = {};
tie %$hash, "Option::ROM::Fields", {
+ rom => $hash, # ROM object itself
data => undef,
offset => 0x00,
length => 0x20,
+ file_offset => 0x0,
fields => {
signature => { offset => 0x00, length => 0x02, pack => "S" },
length => { offset => 0x02, length => 0x01, pack => "C" },
# "init" is part of a jump instruction
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" },
+ pack => \&pack_init, unpack => \&unpack_init,
+ check => \&check_pcat_rom },
+ checksum => { offset => 0x06, length => 0x01, pack => "C",
+ check => \&check_pcat_rom },
+ ipxe_header => { offset => 0x10, length => 0x02, pack => "S",
+ check => \&check_pcat_rom },
+ bofm_header => { offset => 0x14, length => 0x02, pack => "S",
+ check => \&check_pcat_rom },
+ undi_header => { offset => 0x16, length => 0x02, pack => "S",
+ check => \&check_pcat_rom },
pci_header => { offset => 0x18, length => 0x02, pack => "S" },
- pnp_header => { offset => 0x1a, length => 0x02, pack => "S" },
+ pnp_header => { offset => 0x1a, length => 0x02, pack => "S",
+ check => \&check_pcat_rom },
},
};
bless $hash, $class;
@@ -250,9 +272,9 @@ sub new {
=pod
-=item C<< set ( $data ) >>
+=item C<< set ( $data [, $file_offset ] ) >>
-Set option ROM contents.
+Set option ROM contents, optionally sets original file offset.
=cut
@@ -260,9 +282,11 @@ sub set {
my $hash = shift;
my $self = tied(%$hash);
my $data = shift;
+ my $file_offset = shift // 0x0;
# Store data
$self->{data} = \$data;
+ $self->{file_offset} = $file_offset;
# Split out any data belonging to the next image
delete $self->{next_image};
@@ -273,7 +297,7 @@ sub set {
my $remainder = substr ( $data, $length );
$data = substr ( $data, 0, $length );
$self->{next_image} = new Option::ROM;
- $self->{next_image}->set ( $remainder );
+ $self->{next_image}->set ( $remainder, $self->{file_offset} + $length );
}
}
@@ -311,6 +335,7 @@ sub load {
open my $fh, "<$filename"
or croak "Cannot open $filename for reading: $!";
+ binmode $fh;
read $fh, my $data, -s $fh;
$hash->set ( $data );
close $fh;
@@ -335,6 +360,7 @@ sub save {
open my $fh, ">$filename"
or croak "Cannot open $filename for writing: $!";
my $data = $hash->get();
+ binmode $fh;
print $fh $data;
close $fh;
}
@@ -369,9 +395,9 @@ sub pci_header {
my $self = tied(%$hash);
my $offset = $hash->{pci_header};
- return undef unless $offset != 0;
+ return undef unless $offset;
- return Option::ROM::PCI->new ( $self->{data}, $offset );
+ return Option::ROM::PCI->new ( $self, $offset );
}
=pod
@@ -388,9 +414,9 @@ sub pnp_header {
my $self = tied(%$hash);
my $offset = $hash->{pnp_header};
- return undef unless $offset != 0;
+ return undef unless $offset;
- return Option::ROM::PnP->new ( $self->{data}, $offset );
+ return Option::ROM::PnP->new ( $self, $offset );
}
=pod
@@ -407,9 +433,9 @@ sub undi_header {
my $self = tied(%$hash);
my $offset = $hash->{undi_header};
- return undef unless $offset != 0;
+ return undef unless $offset;
- return Option::ROM::UNDI->new ( $self->{data}, $offset );
+ return Option::ROM::UNDI->new ( $self, $offset );
}
=pod
@@ -426,9 +452,28 @@ sub ipxe_header {
my $self = tied(%$hash);
my $offset = $hash->{ipxe_header};
- return undef unless $offset != 0;
+ return undef unless $offset;
- return Option::ROM::iPXE->new ( $self->{data}, $offset );
+ return Option::ROM::iPXE->new ( $self, $offset );
+}
+
+=pod
+
+=item C<< efi_header () >>
+
+Return a C<Option::ROM::EFI> object representing the ROM's EFI header,
+if present.
+
+=cut
+
+sub efi_header {
+ my $hash = shift;
+ my $self = tied(%$hash);
+
+ my $pci = $hash->pci_header ();
+ return undef unless defined $pci;
+
+ return Option::ROM::EFI->new ( $self, $pci );
}
=pod
@@ -475,9 +520,25 @@ sub fix_checksum {
my $hash = shift;
my $self = tied(%$hash);
+ return unless ( exists $hash->{checksum} );
$hash->{checksum} = ( ( $hash->{checksum} - $hash->checksum() ) & 0xff );
}
+=pod
+
+=item C<< file_offset () >>
+
+Get file offset of image.
+
+=cut
+
+sub file_offset {
+ my $hash = shift;
+ my $self = tied(%$hash);
+
+ return $self->{file_offset};
+}
+
##############################################################################
#
# Option::ROM::PCI
@@ -493,12 +554,13 @@ use bytes;
sub new {
my $class = shift;
- my $data = shift;
+ my $rom = shift;
my $offset = shift;
my $hash = {};
tie %$hash, "Option::ROM::Fields", {
- data => $data,
+ rom => $rom,
+ data => $rom->{data},
offset => $offset,
length => 0x0c,
fields => {
@@ -508,9 +570,9 @@ sub new {
device_list => { offset => 0x08, length => 0x02, pack => "S" },
struct_length => { offset => 0x0a, length => 0x02, pack => "S" },
struct_revision =>{ offset => 0x0c, length => 0x01, pack => "C" },
- base_class => { offset => 0x0d, length => 0x01, pack => "C" },
+ prog_intf => { offset => 0x0d, length => 0x01, pack => "C" },
sub_class => { offset => 0x0e, length => 0x01, pack => "C" },
- prog_intf => { offset => 0x0f, length => 0x01, pack => "C" },
+ base_class => { offset => 0x0f, length => 0x01, pack => "C" },
image_length => { offset => 0x10, length => 0x02, pack => "S" },
revision => { offset => 0x12, length => 0x02, pack => "S" },
code_type => { offset => 0x14, length => 0x01, pack => "C" },
@@ -522,11 +584,17 @@ sub new {
};
bless $hash, $class;
- # Retrieve true length of structure
my $self = tied ( %$hash );
+ my $length = $rom->{rom}->length ();
+
+ return undef unless ( $offset + $self->{length} <= $length &&
+ $hash->{signature} eq Option::ROM::PCI_SIGNATURE &&
+ $offset + $hash->{struct_length} <= $length );
+
+ # Retrieve true length of structure
$self->{length} = $hash->{struct_length};
- return $hash;
+ return $hash;
}
sub device_list {
@@ -564,12 +632,13 @@ use bytes;
sub new {
my $class = shift;
- my $data = shift;
+ my $rom = shift;
my $offset = shift;
my $hash = {};
tie %$hash, "Option::ROM::Fields", {
- data => $data,
+ rom => $rom,
+ data => $rom->{data},
offset => $offset,
length => 0x06,
fields => {
@@ -586,11 +655,17 @@ sub new {
};
bless $hash, $class;
- # Retrieve true length of structure
my $self = tied ( %$hash );
+ my $length = $rom->{rom}->length ();
+
+ return undef unless ( $offset + $self->{length} <= $length &&
+ $hash->{signature} eq Option::ROM::PNP_SIGNATURE &&
+ $offset + $hash->{struct_length} * 16 <= $length );
+
+ # Retrieve true length of structure
$self->{length} = ( $hash->{struct_length} * 16 );
- return $hash;
+ return $hash;
}
sub checksum {
@@ -644,12 +719,13 @@ use bytes;
sub new {
my $class = shift;
- my $data = shift;
+ my $rom = shift;
my $offset = shift;
my $hash = {};
tie %$hash, "Option::ROM::Fields", {
- data => $data,
+ rom => $rom,
+ data => $rom->{data},
offset => $offset,
length => 0x16,
fields => {
@@ -669,8 +745,14 @@ sub new {
};
bless $hash, $class;
- # Retrieve true length of structure
my $self = tied ( %$hash );
+ my $length = $rom->{rom}->length ();
+
+ return undef unless ( $offset + $self->{length} <= $length &&
+ $hash->{signature} eq Option::ROM::UNDI_SIGNATURE &&
+ $offset + $hash->{struct_length} <= $length );
+
+ # Retrieve true length of structure
$self->{length} = $hash->{struct_length};
return $hash;
@@ -705,12 +787,13 @@ use bytes;
sub new {
my $class = shift;
- my $data = shift;
+ my $rom = shift;
my $offset = shift;
my $hash = {};
tie %$hash, "Option::ROM::Fields", {
- data => $data,
+ rom => $rom,
+ data => $rom->{data},
offset => $offset,
length => 0x06,
fields => {
@@ -723,8 +806,14 @@ sub new {
};
bless $hash, $class;
- # Retrieve true length of structure
my $self = tied ( %$hash );
+ my $length = $rom->{rom}->length ();
+
+ return undef unless ( $offset + $self->{length} <= $length &&
+ $hash->{signature} eq Option::ROM::IPXE_SIGNATURE &&
+ $offset + $hash->{struct_length} <= $length );
+
+ # Retrieve true length of structure
$self->{length} = $hash->{struct_length};
return $hash;
@@ -744,4 +833,48 @@ sub fix_checksum {
$hash->{checksum} = ( ( $hash->{checksum} - $hash->checksum() ) & 0xff );
}
+##############################################################################
+#
+# Option::ROM::EFI
+#
+##############################################################################
+
+package Option::ROM::EFI;
+
+use strict;
+use warnings;
+use Carp;
+use bytes;
+
+sub new {
+ my $class = shift;
+ my $rom = shift;
+ my $pci = shift;
+
+ my $hash = {};
+ tie %$hash, "Option::ROM::Fields", {
+ rom => $rom,
+ data => $rom->{data},
+ offset => 0x00,
+ length => 0x18,
+ fields => {
+ signature => { offset => 0x00, length => 0x02, pack => "S" },
+ init_size => { offset => 0x02, length => 0x02, pack => "S" },
+ efi_signature => { offset => 0x04, length => 0x04, pack => "L" },
+ efi_subsystem => { offset => 0x08, length => 0x02, pack => "S" },
+ efi_machine_type => { offset => 0x0a, length => 0x02, pack => "S" },
+ compression_type => { offset => 0x0c, length => 0x02, pack => "S" },
+ efi_image_offset => { offset => 0x16, length => 0x02, pack => "S" },
+ },
+ };
+ bless $hash, $class;
+
+ my $self = tied ( %$hash );
+
+ return undef unless ( $hash->{efi_signature} == Option::ROM::EFI_SIGNATURE &&
+ $pci->{code_type} == 0x03 );
+
+ return $hash;
+}
+
1;
diff --git a/src/util/disrom.pl b/src/util/disrom.pl
index 920a86b24..6b2b30738 100755
--- a/src/util/disrom.pl
+++ b/src/util/disrom.pl
@@ -28,8 +28,9 @@ my $romfile = shift || "-";
my $rom = new Option::ROM;
$rom->load ( $romfile );
-do {
+my $index = 0;
+do {
die "Not an option ROM image\n"
unless $rom->{signature} == ROM_SIGNATURE;
@@ -38,17 +39,31 @@ do {
die "ROM image truncated (is $filelength, should be $romlength)\n"
if $filelength < $romlength;
+ printf "Index: %d, offset: 0x%08x\n\n", $index++, $rom->file_offset;
printf "ROM header:\n\n";
printf " %-16s 0x%02x (%d)\n", "Length:",
$rom->{length}, ( $rom->{length} * 512 );
printf " %-16s 0x%02x (%s0x%02x)\n", "Checksum:", $rom->{checksum},
- ( ( $rom->checksum == 0 ) ? "" : "INCORRECT: " ), $rom->checksum;
- printf " %-16s 0x%04x\n", "Init:", $rom->{init};
- printf " %-16s 0x%04x\n", "UNDI header:", $rom->{undi_header};
+ ( ( $rom->checksum () == 0 ) ? "" : "INCORRECT: " ), $rom->checksum () if ( exists $rom->{checksum} );
+ printf " %-16s 0x%04x\n", "Init:", $rom->{init} if ( defined $rom->{init} );
+ printf " %-16s 0x%04x\n", "UNDI header:", $rom->{undi_header} if ( exists $rom->{undi_header} );
printf " %-16s 0x%04x\n", "PCI header:", $rom->{pci_header};
- printf " %-16s 0x%04x\n", "PnP header:", $rom->{pnp_header};
+ printf " %-16s 0x%04x\n", "PnP header:", $rom->{pnp_header} if ( exists $rom->{pnp_header} );
printf "\n";
+ my $efi = $rom->efi_header();
+ if ( $efi ) {
+ printf "EFI header:\n\n";
+ printf " %-16s 0x%04x (%d)\n", "Init size:",
+ $efi->{init_size}, ( $efi->{init_size} * 512 );
+ printf " %-16s 0x%08x\n", "EFI Signature:", $efi->{efi_signature};
+ printf " %-16s 0x%04x\n", "EFI Subsystem:", $efi->{efi_subsystem};
+ printf " %-16s 0x%04x\n", "EFI Machine type:", $efi->{efi_machine_type};
+ printf " %-16s 0x%04x\n", "Compression type:", $efi->{compression_type};
+ printf " %-16s 0x%04x\n", "EFI Image offset:", $efi->{efi_image_offset};
+ printf "\n";
+ }
+
my $pci = $rom->pci_header();
if ( $pci ) {
printf "PCI header:\n\n";
diff --git a/src/util/efirom.c b/src/util/efirom.c
index 943a66910..93cd79fe9 100644
--- a/src/util/efirom.c
+++ b/src/util/efirom.c
@@ -149,7 +149,7 @@ static void make_efi_rom ( FILE *pe, FILE *rom, struct options *opts ) {
headers->pci.VendorId = opts->vendor;
headers->pci.DeviceId = opts->device;
headers->pci.Length = sizeof ( headers->pci );
- headers->pci.ClassCode[0] = PCI_CLASS_NETWORK;
+ headers->pci.ClassCode[2] = PCI_CLASS_NETWORK;
headers->pci.ImageLength = ( rom_size / 512 );
headers->pci.CodeType = 0x03; /* No constant in EFI headers? */
headers->pci.Indicator = 0x80; /* No constant in EFI headers? */
diff --git a/src/util/elf2efi.c b/src/util/elf2efi.c
index 6718df777..2c5b9df8a 100644
--- a/src/util/elf2efi.c
+++ b/src/util/elf2efi.c
@@ -636,6 +636,7 @@ static void process_reloc ( struct elf_file *elf, const Elf_Shdr *shdr,
case ELF_MREL ( EM_ARM, R_ARM_THM_JUMP24 ) :
case ELF_MREL ( EM_ARM, R_ARM_V4BX ):
case ELF_MREL ( EM_X86_64, R_X86_64_PC32 ) :
+ case ELF_MREL ( EM_X86_64, R_X86_64_PLT32 ) :
case ELF_MREL ( EM_AARCH64, R_AARCH64_CALL26 ) :
case ELF_MREL ( EM_AARCH64, R_AARCH64_JUMP26 ) :
case ELF_MREL ( EM_AARCH64, R_AARCH64_ADR_PREL_LO21 ) :
diff --git a/src/util/zbin.c b/src/util/zbin.c
index 75fba583f..3a4670b88 100644
--- a/src/util/zbin.c
+++ b/src/util/zbin.c
@@ -386,16 +386,16 @@ static int process_zinfo_add ( struct input_file *input
( ( 1UL << ( 8 * datasize ) ) - 1 ) : ~0UL );
if ( val < 0 ) {
- fprintf ( stderr, "Add %s%#x+%#lx at %#zx %sflows field\n",
- ( ( addend < 0 ) ? "-" : "" ), abs ( addend ), size,
+ fprintf ( stderr, "Add %s%#lx+%#lx at %#zx %sflows field\n",
+ ( ( addend < 0 ) ? "-" : "" ), labs ( addend ), size,
offset, ( ( addend < 0 ) ? "under" : "over" ) );
return -1;
}
if ( val & ~mask ) {
- fprintf ( stderr, "Add %s%#x+%#lx at %#zx overflows %zd-byte "
+ fprintf ( stderr, "Add %s%#lx+%#lx at %#zx overflows %zd-byte "
"field (%d bytes too big)\n",
- ( ( addend < 0 ) ? "-" : "" ), abs ( addend ), size,
+ ( ( addend < 0 ) ? "-" : "" ), labs ( addend ), size,
offset, datasize,
( int )( ( val - mask - 1 ) * add->divisor ) );
return -1;
@@ -414,9 +414,9 @@ static int process_zinfo_add ( struct input_file *input
}
if ( DEBUG ) {
- fprintf ( stderr, "ADDx [%#zx,%#zx) (%s%#x+(%#zx/%#x)) = "
+ fprintf ( stderr, "ADDx [%#zx,%#zx) (%s%#lx+(%#zx/%#x)) = "
"%#lx\n", offset, ( offset + datasize ),
- ( ( addend < 0 ) ? "-" : "" ), abs ( addend ),
+ ( ( addend < 0 ) ? "-" : "" ), labs ( addend ),
len, add->divisor, val );
}