From 133f4c47baef6002b2ccb4904a035cda2303c6e5 Mon Sep 17 00:00:00 2001 From: Christian Hesse Date: Sat, 25 Aug 2018 13:53:08 +0200 Subject: [build] Handle R_X86_64_PLT32 from binutils 2.31 Starting from binutils 2.31.0 (commit bd7ab16b) x86-64 assembler generates R_X86_64_PLT32 instead of R_X86_64_PC32. Acked-by: John Jolly Signed-off-by: Michael Brown --- src/util/elf2efi.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') 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 ) : -- cgit v1.2.3-55-g7522 From ba0d5aa993df4bad28b2a6a36c10b43c7e5c33f2 Mon Sep 17 00:00:00 2001 From: Petr Borsodi Date: Tue, 15 Jan 2019 13:06:19 +0000 Subject: [pci] Correct invalid base-class/sub-class/prog-if order in PCIR PCI Configuration Space contains fields prog-if at the offset 0x09, sub-class at the offset 0x0a and base-class at the offset 0x0b (it respects little endian). PCIR structure uses these fields in the same order. Signed-off-by: Michael Brown --- src/arch/x86/prefix/mromprefix.S | 2 +- src/arch/x86/prefix/romprefix.S | 2 +- src/util/Option/ROM.pm | 4 ++-- src/util/efirom.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src') 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/util/Option/ROM.pm b/src/util/Option/ROM.pm index 232cf16b8..48d92dda0 100644 --- a/src/util/Option/ROM.pm +++ b/src/util/Option/ROM.pm @@ -508,9 +508,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" }, 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? */ -- cgit v1.2.3-55-g7522 From e226fecd1b602ece7f4f208042f3e87ca540b297 Mon Sep 17 00:00:00 2001 From: Ignat Korchagin Date: Fri, 4 Jan 2019 19:20:28 +0000 Subject: [efi] Fix error handling path in efi_snp_probe Current (simplified): 1. InstallMultipleProtocolInterfaces if err goto err_install_protocol_interface; 2. OpenProtocol(efi_nii_protocol_guid) if err goto err_open_nii; 3. OpenProtocol(efi_nii31_protocol_guid) if err goto err_open_nii31; 4. efi_child_add if err goto err_efi_child_add; ... err_efi_child_add: CloseProtocol(efi_nii_protocol_guid) <= should be efi_nii31_protocol_guid err_open_nii: <= should be err_open_nii31 CloseProtocol(efi_nii31_protocol_guid) <= should be efi_nii_protocol_guid err_open_nii31: <= should be err_open_nii UninstallMultipleProtocolInterfaces Signed-off-by: Ignat Korchagin Signed-off-by: Michael Brown --- src/interface/efi/efi_snp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') 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, -- cgit v1.2.3-55-g7522 From 3946aa9bac1b4a784924fab1693bfebfdd357438 Mon Sep 17 00:00:00 2001 From: Aaron Young Date: Wed, 9 Jan 2019 11:35:39 -0800 Subject: [libc] Fix strcmp()/strncmp() to return proper values Fix strcmp() and strncmp() to return proper standard positive/negative values for unequal strings. Current implementation is backwards (i.e. the functions are returning negative when should be positive and vice-versa). Currently all consumers of these functions only check the return value for ==0 or !=0 and so we can safely change the implementation without breaking things. Signed-off-by: Aaron Young Modified-by: Michael Brown Signed-off-by: Michael Brown --- src/core/string.c | 6 +++--- src/tests/string_test.c | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'src') 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/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 ); -- cgit v1.2.3-55-g7522 From 956f6a7227b62ce98d7840439af17bbca04f0c86 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 21 Jan 2019 11:17:04 +0000 Subject: [zbin] Fix compiler warning with GCC 9 GCC 9 warns that abs() may truncate its signed long argument. Fix by using labs() instead. Reported-by: Martin Liška Signed-off-by: Michael Brown --- src/util/zbin.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src') 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 ); } -- cgit v1.2.3-55-g7522 From 3f4c179a149c4feb3f0ea777aeddffa06bed0a27 Mon Sep 17 00:00:00 2001 From: Petr Borsodi Date: Wed, 16 Jan 2019 17:37:57 +0100 Subject: [util] Improve processing of ROM images in Option::ROM The Option::ROM module now compares the Code Type in the PCIR header to 0x00 (PC-AT) in order to check the presence of other header types (PnP, UNDI, iPXE, etc). The validity of these headers are checked not only by offset, but by range and signature checks also. The image checksum and initial size also depends on Code Type. Signed-off-by: Michael Brown --- src/util/Option/ROM.pm | 137 +++++++++++++++++++++++++++++++++++++------------ src/util/disrom.pl | 12 +++-- 2 files changed, 110 insertions(+), 39 deletions(-) (limited to 'src') diff --git a/src/util/Option/ROM.pm b/src/util/Option/ROM.pm index 48d92dda0..7bbd69866 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,11 @@ 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'; our @EXPORT_OK = qw ( ROM_SIGNATURE PCI_SIGNATURE PCI_LAST_IMAGE - PNP_SIGNATURE IPXE_SIGNATURE ); + PNP_SIGNATURE UNDI_SIGNATURE IPXE_SIGNATURE ); our %EXPORT_TAGS = ( all => [ @EXPORT_OK ] ); use constant JMP_SHORT => 0xeb; @@ -210,10 +213,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 +240,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 +271,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 +281,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 +296,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 +334,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 +359,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 +394,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 +413,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 +432,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 +451,9 @@ 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 @@ -475,9 +500,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 +534,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 => { @@ -522,11 +564,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 +612,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 +635,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 +699,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 +725,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 +767,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 +786,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; diff --git a/src/util/disrom.pl b/src/util/disrom.pl index 920a86b24..71eee5902 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,15 +39,16 @@ 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 $pci = $rom->pci_header(); -- cgit v1.2.3-55-g7522 From de4565cbe76ea9f7913a01f331be3ee901bb6e17 Mon Sep 17 00:00:00 2001 From: Petr Borsodi Date: Wed, 16 Jan 2019 17:37:58 +0100 Subject: [util] Add support for EFI ROM images The Option::ROM module recognizes and checks EFI header of image. The disrom.pl utility dumps this header if is present. Signed-off-by: Michael Brown --- src/util/Option/ROM.pm | 66 +++++++++++++++++++++++++++++++++++++++++++++++++- src/util/disrom.pl | 13 ++++++++++ 2 files changed, 78 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/util/Option/ROM.pm b/src/util/Option/ROM.pm index 7bbd69866..51831adf9 100644 --- a/src/util/Option/ROM.pm +++ b/src/util/Option/ROM.pm @@ -176,9 +176,10 @@ 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 UNDI_SIGNATURE IPXE_SIGNATURE ); + PNP_SIGNATURE UNDI_SIGNATURE IPXE_SIGNATURE EFI_SIGNATURE ); our %EXPORT_TAGS = ( all => [ @EXPORT_OK ] ); use constant JMP_SHORT => 0xeb; @@ -458,6 +459,25 @@ sub ipxe_header { =pod +=item C<< efi_header () >> + +Return a C 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 + =item C<< next_image () >> Return a C object representing the next image within the @@ -813,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 71eee5902..6b2b30738 100755 --- a/src/util/disrom.pl +++ b/src/util/disrom.pl @@ -51,6 +51,19 @@ do { 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"; -- cgit v1.2.3-55-g7522 From 36a4c85f911c85f5ab183331ff74d125f9a9ed32 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 25 Jan 2019 14:53:43 +0000 Subject: [init] Show startup and shutdown function names in debug messages Signed-off-by: Michael Brown --- src/arch/x86/core/cachedhcp.c | 1 + src/arch/x86/core/runtime.c | 1 + src/arch/x86/drivers/net/undionly.c | 1 + src/arch/x86/image/initrd.c | 1 + src/arch/x86/interface/pcbios/bios_console.c | 1 + src/arch/x86/interface/pcbios/hidemem.c | 1 + src/core/device.c | 1 + src/core/init.c | 15 +++++++++++++-- src/core/malloc.c | 1 + src/core/serial.c | 1 + src/crypto/rbg.c | 1 + src/crypto/rootcert.c | 1 + src/drivers/usb/ehci.c | 1 + src/drivers/usb/xhci.c | 1 + src/hci/linux_args.c | 1 + src/include/ipxe/init.h | 1 + src/interface/efi/efi_timer.c | 1 + src/interface/linux/linux_console.c | 1 + src/net/tcp.c | 1 + 19 files changed, 31 insertions(+), 2 deletions(-) (limited to 'src') 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/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/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_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, }; -- cgit v1.2.3-55-g7522