[efi] Write out PE header only after writing sections

Hybrid bzImage and UEFI binaries (such as wimboot) include a bzImage
header within a section starting at offset zero, with the PE header
effectively occupying unused space within this section.

Allow for this by treating a section placed at offset zero as hidden,
and by deferring the writing of the PE header until after the output
sections have been written.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
pull/1082/head
Michael Brown 2023-11-22 15:38:22 +00:00
parent b30a0987e2
commit cc858acd32
1 changed files with 28 additions and 22 deletions

View File

@ -642,6 +642,8 @@ static struct pe_section * process_section ( struct elf_file *elf,
if ( shdr->sh_type == SHT_PROGBITS ) {
if ( opts->hybrid ) {
new->hdr.PointerToRawData = elf_lma ( elf, shdr, name );
if ( new->hdr.PointerToRawData == 0 )
new->hidden = 1;
} else {
new->hdr.PointerToRawData = PTRD_AUTO;
}
@ -1024,28 +1026,6 @@ static void write_pe_file ( struct pe_header *pe_header,
section->fixup ( section );
}
/* Write file header */
if ( fwrite ( pe_header,
( offsetof ( typeof ( *pe_header ), nt.OptionalHeader ) +
pe_header->nt.FileHeader.SizeOfOptionalHeader ),
1, pe ) != 1 ) {
perror ( "Could not write PE header" );
exit ( 1 );
}
/* Write section headers */
for ( section = pe_sections ; section ; section = section->next ) {
if ( section->hidden )
continue;
if ( fwrite ( &section->hdr, sizeof ( section->hdr ),
1, pe ) != 1 ) {
perror ( "Could not write section header" );
exit ( 1 );
}
count++;
}
assert ( count == pe_header->nt.FileHeader.NumberOfSections );
/* Write sections */
for ( section = pe_sections ; section ; section = section->next ) {
if ( section->hdr.PointerToRawData & ( EFI_FILE_ALIGN - 1 ) ) {
@ -1069,6 +1049,32 @@ static void write_pe_file ( struct pe_header *pe_header,
exit ( 1 );
}
}
/* Write file header */
if ( fseek ( pe, 0, SEEK_SET ) != 0 ) {
eprintf ( "Could not rewind: %s\n", strerror ( errno ) );
exit ( 1 );
}
if ( fwrite ( pe_header,
( offsetof ( typeof ( *pe_header ), nt.OptionalHeader ) +
pe_header->nt.FileHeader.SizeOfOptionalHeader ),
1, pe ) != 1 ) {
perror ( "Could not write PE header" );
exit ( 1 );
}
/* Write section headers */
for ( section = pe_sections ; section ; section = section->next ) {
if ( section->hidden )
continue;
if ( fwrite ( &section->hdr, sizeof ( section->hdr ),
1, pe ) != 1 ) {
perror ( "Could not write section header" );
exit ( 1 );
}
count++;
}
assert ( count == pe_header->nt.FileHeader.NumberOfSections );
}
/**