]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[efi] Write out PE header only after writing sections
authorMichael Brown <mcb30@ipxe.org>
Wed, 22 Nov 2023 15:38:22 +0000 (15:38 +0000)
committerMichael Brown <mcb30@ipxe.org>
Thu, 23 Nov 2023 13:37:47 +0000 (13:37 +0000)
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>
src/util/elf2efi.c

index 682580f44a9e4ac7494d7dcda0d1ce8d95c49493..a8074915a21e4e86593a7c1d96ee50c299e9eb63 100644 (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 );
 }
 
 /**