diff options
| author | Simon Rettberg | 2019-02-15 10:38:39 +0100 |
|---|---|---|
| committer | Simon Rettberg | 2019-02-15 10:38:39 +0100 |
| commit | 893714cfea74a68b5637f1d9866d1b8d8973cf94 (patch) | |
| tree | 0bc3209f0dc939a4dab61218c9af71f904bb17e5 /src | |
| parent | [efi] Add support for console --update in efifb mode (diff) | |
| parent | [init] Show startup and shutdown function names in debug messages (diff) | |
| download | ipxe-893714cfea74a68b5637f1d9866d1b8d8973cf94.tar.gz ipxe-893714cfea74a68b5637f1d9866d1b8d8973cf94.tar.xz ipxe-893714cfea74a68b5637f1d9866d1b8d8973cf94.zip | |
Merge branch 'master' into openslx
Diffstat (limited to 'src')
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 ); } |
