summaryrefslogtreecommitdiff
path: root/gpxe/src/util/elf2efi.c
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2016-02-09 18:08:47 -0800
committerH. Peter Anvin <hpa@zytor.com>2016-02-09 18:08:47 -0800
commitf2f897a1762fab84d2905f32b1c15dd7b42abb56 (patch)
treea38f51d3f1fcbf44afddb4736d549c12eaf491be /gpxe/src/util/elf2efi.c
parent72d2959272b4616f17a97667e6dfa9d06bf109a3 (diff)
downloadsyslinux-f2f897a1762fab84d2905f32b1c15dd7b42abb56.tar.gz
gpxe: delete long since obsolete snapshot of gPXE
gPXE has been deprecated in favor of iPXE for many, many years now. It is much better than users get it directly from the iPXE project, since we should no longer need any special modifications for Syslinux use. Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Diffstat (limited to 'gpxe/src/util/elf2efi.c')
-rw-r--r--gpxe/src/util/elf2efi.c808
1 files changed, 0 insertions, 808 deletions
diff --git a/gpxe/src/util/elf2efi.c b/gpxe/src/util/elf2efi.c
deleted file mode 100644
index bb766bd3..00000000
--- a/gpxe/src/util/elf2efi.c
+++ /dev/null
@@ -1,808 +0,0 @@
-/*
- * Copyright (C) 2009 Michael Brown <mbrown@fensystems.co.uk>.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#define _GNU_SOURCE
-#include <stdint.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-#include <assert.h>
-#include <getopt.h>
-#include <bfd.h>
-#include <gpxe/efi/efi.h>
-#include <gpxe/efi/IndustryStandard/PeImage.h>
-#include <libgen.h>
-
-#define eprintf(...) fprintf ( stderr, __VA_ARGS__ )
-
-#define EFI_FILE_ALIGN 0x20
-
-struct pe_section {
- struct pe_section *next;
- EFI_IMAGE_SECTION_HEADER hdr;
- uint8_t contents[0];
-};
-
-struct pe_relocs {
- struct pe_relocs *next;
- unsigned long start_rva;
- unsigned int used_relocs;
- unsigned int total_relocs;
- uint16_t *relocs;
-};
-
-struct pe_header {
- EFI_IMAGE_DOS_HEADER dos;
- uint8_t padding[128];
-#if defined(MDE_CPU_IA32)
- EFI_IMAGE_NT_HEADERS32 nt;
-#elif defined(MDE_CPU_X64)
- EFI_IMAGE_NT_HEADERS64 nt;
-#endif
-};
-
-static struct pe_header efi_pe_header = {
- .dos = {
- .e_magic = EFI_IMAGE_DOS_SIGNATURE,
- .e_lfanew = offsetof ( typeof ( efi_pe_header ), nt ),
- },
- .nt = {
- .Signature = EFI_IMAGE_NT_SIGNATURE,
- .FileHeader = {
-#if defined(MDE_CPU_IA32)
- .Machine = EFI_IMAGE_MACHINE_IA32,
-#elif defined(MDE_CPU_X64)
- .Machine = EFI_IMAGE_MACHINE_X64,
-#endif
- .TimeDateStamp = 0x10d1a884,
- .SizeOfOptionalHeader =
- sizeof ( efi_pe_header.nt.OptionalHeader ),
- .Characteristics = ( EFI_IMAGE_FILE_DLL |
-#if defined(MDE_CPU_IA32)
- EFI_IMAGE_FILE_32BIT_MACHINE |
-#endif
- EFI_IMAGE_FILE_EXECUTABLE_IMAGE ),
- },
- .OptionalHeader = {
-#if defined(MDE_CPU_IA32)
- .Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC,
-#elif defined(MDE_CPU_X64)
- .Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC,
-#endif
- .SectionAlignment = EFI_FILE_ALIGN,
- .FileAlignment = EFI_FILE_ALIGN,
- .SizeOfImage = sizeof ( efi_pe_header ),
- .SizeOfHeaders = sizeof ( efi_pe_header ),
- .NumberOfRvaAndSizes =
- EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES,
- },
- },
-};
-
-/** Command-line options */
-struct options {
- unsigned int subsystem;
-};
-
-/**
- * Allocate memory
- *
- * @v len Length of memory to allocate
- * @ret ptr Pointer to allocated memory
- */
-static void * xmalloc ( size_t len ) {
- void *ptr;
-
- ptr = malloc ( len );
- if ( ! ptr ) {
- eprintf ( "Could not allocate %zd bytes\n", len );
- exit ( 1 );
- }
-
- return ptr;
-}
-
-/**
- * Align section within PE file
- *
- * @v offset Unaligned offset
- * @ret aligned_offset Aligned offset
- */
-static unsigned long efi_file_align ( unsigned long offset ) {
- return ( ( offset + EFI_FILE_ALIGN - 1 ) & ~( EFI_FILE_ALIGN - 1 ) );
-}
-
-/**
- * Generate entry in PE relocation table
- *
- * @v pe_reltab PE relocation table
- * @v rva RVA
- * @v size Size of relocation entry
- */
-static void generate_pe_reloc ( struct pe_relocs **pe_reltab,
- unsigned long rva, size_t size ) {
- unsigned long start_rva;
- uint16_t reloc;
- struct pe_relocs *pe_rel;
- uint16_t *relocs;
-
- /* Construct */
- start_rva = ( rva & ~0xfff );
- reloc = ( rva & 0xfff );
- switch ( size ) {
- case 8:
- reloc |= 0xa000;
- break;
- case 4:
- reloc |= 0x3000;
- break;
- case 2:
- reloc |= 0x2000;
- break;
- default:
- eprintf ( "Unsupported relocation size %zd\n", size );
- exit ( 1 );
- }
-
- /* Locate or create PE relocation table */
- for ( pe_rel = *pe_reltab ; pe_rel ; pe_rel = pe_rel->next ) {
- if ( pe_rel->start_rva == start_rva )
- break;
- }
- if ( ! pe_rel ) {
- pe_rel = xmalloc ( sizeof ( *pe_rel ) );
- memset ( pe_rel, 0, sizeof ( *pe_rel ) );
- pe_rel->next = *pe_reltab;
- *pe_reltab = pe_rel;
- pe_rel->start_rva = start_rva;
- }
-
- /* Expand relocation list if necessary */
- if ( pe_rel->used_relocs < pe_rel->total_relocs ) {
- relocs = pe_rel->relocs;
- } else {
- pe_rel->total_relocs = ( pe_rel->total_relocs ?
- ( pe_rel->total_relocs * 2 ) : 256 );
- relocs = xmalloc ( pe_rel->total_relocs *
- sizeof ( pe_rel->relocs[0] ) );
- memset ( relocs, 0,
- pe_rel->total_relocs * sizeof ( pe_rel->relocs[0] ) );
- memcpy ( relocs, pe_rel->relocs,
- pe_rel->used_relocs * sizeof ( pe_rel->relocs[0] ) );
- free ( pe_rel->relocs );
- pe_rel->relocs = relocs;
- }
-
- /* Store relocation */
- pe_rel->relocs[ pe_rel->used_relocs++ ] = reloc;
-}
-
-/**
- * Calculate size of binary PE relocation table
- *
- * @v pe_reltab PE relocation table
- * @v buffer Buffer to contain binary table, or NULL
- * @ret size Size of binary table
- */
-static size_t output_pe_reltab ( struct pe_relocs *pe_reltab,
- void *buffer ) {
- struct pe_relocs *pe_rel;
- unsigned int num_relocs;
- size_t size;
- size_t total_size = 0;
-
- for ( pe_rel = pe_reltab ; pe_rel ; pe_rel = pe_rel->next ) {
- num_relocs = ( ( pe_rel->used_relocs + 1 ) & ~1 );
- size = ( sizeof ( uint32_t ) /* VirtualAddress */ +
- sizeof ( uint32_t ) /* SizeOfBlock */ +
- ( num_relocs * sizeof ( uint16_t ) ) );
- if ( buffer ) {
- *( (uint32_t *) ( buffer + total_size + 0 ) )
- = pe_rel->start_rva;
- *( (uint32_t *) ( buffer + total_size + 4 ) ) = size;
- memcpy ( ( buffer + total_size + 8 ), pe_rel->relocs,
- ( num_relocs * sizeof ( uint16_t ) ) );
- }
- total_size += size;
- }
-
- return total_size;
-}
-
-/**
- * Open input BFD file
- *
- * @v filename File name
- * @ret ibfd BFD file
- */
-static bfd * open_input_bfd ( const char *filename ) {
- bfd *bfd;
-
- /* Open the file */
- bfd = bfd_openr ( filename, NULL );
- if ( ! bfd ) {
- eprintf ( "Cannot open %s: ", filename );
- bfd_perror ( NULL );
- exit ( 1 );
- }
-
- /* The call to bfd_check_format() must be present, otherwise
- * we get a segfault from later BFD calls.
- */
- if ( bfd_check_format ( bfd, bfd_object ) < 0 ) {
- eprintf ( "%s is not an object file\n", filename );
- exit ( 1 );
- }
-
- return bfd;
-}
-
-/**
- * Read symbol table
- *
- * @v bfd BFD file
- */
-static asymbol ** read_symtab ( bfd *bfd ) {
- long symtab_size;
- asymbol **symtab;
- long symcount;
-
- /* Get symbol table size */
- symtab_size = bfd_get_symtab_upper_bound ( bfd );
- if ( symtab_size < 0 ) {
- bfd_perror ( "Could not get symbol table upper bound" );
- exit ( 1 );
- }
-
- /* Allocate and read symbol table */
- symtab = xmalloc ( symtab_size );
- symcount = bfd_canonicalize_symtab ( bfd, symtab );
- if ( symcount < 0 ) {
- bfd_perror ( "Cannot read symbol table" );
- exit ( 1 );
- }
-
- return symtab;
-}
-
-/**
- * Read relocation table
- *
- * @v bfd BFD file
- * @v symtab Symbol table
- * @v section Section
- * @v symtab Symbol table
- * @ret reltab Relocation table
- */
-static arelent ** read_reltab ( bfd *bfd, asymbol **symtab,
- asection *section ) {
- long reltab_size;
- arelent **reltab;
- long numrels;
-
- /* Get relocation table size */
- reltab_size = bfd_get_reloc_upper_bound ( bfd, section );
- if ( reltab_size < 0 ) {
- bfd_perror ( "Could not get relocation table upper bound" );
- exit ( 1 );
- }
-
- /* Allocate and read relocation table */
- reltab = xmalloc ( reltab_size );
- numrels = bfd_canonicalize_reloc ( bfd, section, reltab, symtab );
- if ( numrels < 0 ) {
- bfd_perror ( "Cannot read relocation table" );
- exit ( 1 );
- }
-
- return reltab;
-}
-
-/**
- * Process section
- *
- * @v bfd BFD file
- * @v pe_header PE file header
- * @v section Section
- * @ret new New PE section
- */
-static struct pe_section * process_section ( bfd *bfd,
- struct pe_header *pe_header,
- asection *section ) {
- struct pe_section *new;
- size_t section_memsz;
- size_t section_filesz;
- unsigned long flags = bfd_get_section_flags ( bfd, section );
- unsigned long code_start;
- unsigned long code_end;
- unsigned long data_start;
- unsigned long data_mid;
- unsigned long data_end;
- unsigned long start;
- unsigned long end;
- unsigned long *applicable_start;
- unsigned long *applicable_end;
-
- /* Extract current RVA limits from file header */
- code_start = pe_header->nt.OptionalHeader.BaseOfCode;
- code_end = ( code_start + pe_header->nt.OptionalHeader.SizeOfCode );
-#if defined(MDE_CPU_IA32)
- data_start = pe_header->nt.OptionalHeader.BaseOfData;
-#elif defined(MDE_CPU_X64)
- data_start = code_end;
-#endif
- data_mid = ( data_start +
- pe_header->nt.OptionalHeader.SizeOfInitializedData );
- data_end = ( data_mid +
- pe_header->nt.OptionalHeader.SizeOfUninitializedData );
-
- /* Allocate PE section */
- section_memsz = bfd_section_size ( bfd, section );
- section_filesz = ( ( flags & SEC_LOAD ) ?
- efi_file_align ( section_memsz ) : 0 );
- new = xmalloc ( sizeof ( *new ) + section_filesz );
- memset ( new, 0, sizeof ( *new ) + section_filesz );
-
- /* Fill in section header details */
- strncpy ( ( char * ) new->hdr.Name, section->name,
- sizeof ( new->hdr.Name ) );
- new->hdr.Misc.VirtualSize = section_memsz;
- new->hdr.VirtualAddress = bfd_get_section_vma ( bfd, section );
- new->hdr.SizeOfRawData = section_filesz;
-
- /* Fill in section characteristics and update RVA limits */
- if ( flags & SEC_CODE ) {
- /* .text-type section */
- new->hdr.Characteristics =
- ( EFI_IMAGE_SCN_CNT_CODE |
- EFI_IMAGE_SCN_MEM_NOT_PAGED |
- EFI_IMAGE_SCN_MEM_EXECUTE |
- EFI_IMAGE_SCN_MEM_READ );
- applicable_start = &code_start;
- applicable_end = &code_end;
- } else if ( flags & SEC_DATA ) {
- /* .data-type section */
- new->hdr.Characteristics =
- ( EFI_IMAGE_SCN_CNT_INITIALIZED_DATA |
- EFI_IMAGE_SCN_MEM_NOT_PAGED |
- EFI_IMAGE_SCN_MEM_READ |
- EFI_IMAGE_SCN_MEM_WRITE );
- applicable_start = &data_start;
- applicable_end = &data_mid;
- } else if ( flags & SEC_READONLY ) {
- /* .rodata-type section */
- new->hdr.Characteristics =
- ( EFI_IMAGE_SCN_CNT_INITIALIZED_DATA |
- EFI_IMAGE_SCN_MEM_NOT_PAGED |
- EFI_IMAGE_SCN_MEM_READ );
- applicable_start = &data_start;
- applicable_end = &data_mid;
- } else if ( ! ( flags & SEC_LOAD ) ) {
- /* .bss-type section */
- new->hdr.Characteristics =
- ( EFI_IMAGE_SCN_CNT_UNINITIALIZED_DATA |
- EFI_IMAGE_SCN_MEM_NOT_PAGED |
- EFI_IMAGE_SCN_MEM_READ |
- EFI_IMAGE_SCN_MEM_WRITE );
- applicable_start = &data_mid;
- applicable_end = &data_end;
- }
-
- /* Copy in section contents */
- if ( flags & SEC_LOAD ) {
- if ( ! bfd_get_section_contents ( bfd, section, new->contents,
- 0, section_memsz ) ) {
- eprintf ( "Cannot read section %s: ", section->name );
- bfd_perror ( NULL );
- exit ( 1 );
- }
- }
-
- /* Update RVA limits */
- start = new->hdr.VirtualAddress;
- end = ( start + new->hdr.Misc.VirtualSize );
- if ( ( ! *applicable_start ) || ( *applicable_start >= start ) )
- *applicable_start = start;
- if ( *applicable_end < end )
- *applicable_end = end;
- if ( data_start < code_end )
- data_start = code_end;
- if ( data_mid < data_start )
- data_mid = data_start;
- if ( data_end < data_mid )
- data_end = data_mid;
-
- /* Write RVA limits back to file header */
- pe_header->nt.OptionalHeader.BaseOfCode = code_start;
- pe_header->nt.OptionalHeader.SizeOfCode = ( code_end - code_start );
-#if defined(MDE_CPU_IA32)
- pe_header->nt.OptionalHeader.BaseOfData = data_start;
-#endif
- pe_header->nt.OptionalHeader.SizeOfInitializedData =
- ( data_mid - data_start );
- pe_header->nt.OptionalHeader.SizeOfUninitializedData =
- ( data_end - data_mid );
-
- /* Update remaining file header fields */
- pe_header->nt.FileHeader.NumberOfSections++;
- pe_header->nt.OptionalHeader.SizeOfHeaders += sizeof ( new->hdr );
- pe_header->nt.OptionalHeader.SizeOfImage =
- efi_file_align ( data_end );
-
- return new;
-}
-
-/**
- * Process relocation record
- *
- * @v bfd BFD file
- * @v section Section
- * @v rel Relocation entry
- * @v pe_reltab PE relocation table to fill in
- */
-static void process_reloc ( bfd *bfd, asection *section, arelent *rel,
- struct pe_relocs **pe_reltab ) {
- reloc_howto_type *howto = rel->howto;
- asymbol *sym = *(rel->sym_ptr_ptr);
- unsigned long offset = ( bfd_get_section_vma ( bfd, section ) +
- rel->address );
-
- if ( bfd_is_abs_section ( sym->section ) ) {
- /* Skip absolute symbols; the symbol value won't
- * change when the object is loaded.
- */
- } else if ( strcmp ( howto->name, "R_X86_64_64" ) == 0 ) {
- /* Generate an 8-byte PE relocation */
- generate_pe_reloc ( pe_reltab, offset, 8 );
- } else if ( ( strcmp ( howto->name, "R_386_32" ) == 0 ) ||
- ( strcmp ( howto->name, "R_X86_64_32" ) == 0 ) ) {
- /* Generate a 4-byte PE relocation */
- generate_pe_reloc ( pe_reltab, offset, 4 );
- } else if ( strcmp ( howto->name, "R_386_16" ) == 0 ) {
- /* Generate a 2-byte PE relocation */
- generate_pe_reloc ( pe_reltab, offset, 2 );
- } else if ( ( strcmp ( howto->name, "R_386_PC32" ) == 0 ) ||
- ( strcmp ( howto->name, "R_X86_64_PC32" ) == 0 ) ) {
- /* Skip PC-relative relocations; all relative offsets
- * remain unaltered when the object is loaded.
- */
- } else {
- eprintf ( "Unrecognised relocation type %s\n", howto->name );
- exit ( 1 );
- }
-}
-
-/**
- * Create relocations section
- *
- * @v pe_header PE file header
- * @v pe_reltab PE relocation table
- * @ret section Relocation section
- */
-static struct pe_section *
-create_reloc_section ( struct pe_header *pe_header,
- struct pe_relocs *pe_reltab ) {
- struct pe_section *reloc;
- size_t section_memsz;
- size_t section_filesz;
- EFI_IMAGE_DATA_DIRECTORY *relocdir;
-
- /* Allocate PE section */
- section_memsz = output_pe_reltab ( pe_reltab, NULL );
- section_filesz = efi_file_align ( section_memsz );
- reloc = xmalloc ( sizeof ( *reloc ) + section_filesz );
- memset ( reloc, 0, sizeof ( *reloc ) + section_filesz );
-
- /* Fill in section header details */
- strncpy ( ( char * ) reloc->hdr.Name, ".reloc",
- sizeof ( reloc->hdr.Name ) );
- reloc->hdr.Misc.VirtualSize = section_memsz;
- reloc->hdr.VirtualAddress = pe_header->nt.OptionalHeader.SizeOfImage;
- reloc->hdr.SizeOfRawData = section_filesz;
- reloc->hdr.Characteristics = ( EFI_IMAGE_SCN_CNT_INITIALIZED_DATA |
- EFI_IMAGE_SCN_MEM_NOT_PAGED |
- EFI_IMAGE_SCN_MEM_READ );
-
- /* Copy in section contents */
- output_pe_reltab ( pe_reltab, reloc->contents );
-
- /* Update file header details */
- pe_header->nt.FileHeader.NumberOfSections++;
- pe_header->nt.OptionalHeader.SizeOfHeaders += sizeof ( reloc->hdr );
- pe_header->nt.OptionalHeader.SizeOfImage += section_filesz;
- relocdir = &(pe_header->nt.OptionalHeader.DataDirectory
- [EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC]);
- relocdir->VirtualAddress = reloc->hdr.VirtualAddress;
- relocdir->Size = reloc->hdr.Misc.VirtualSize;
-
- return reloc;
-}
-
-/**
- * Create debug section
- *
- * @v pe_header PE file header
- * @ret section Debug section
- */
-static struct pe_section *
-create_debug_section ( struct pe_header *pe_header, const char *filename ) {
- struct pe_section *debug;
- size_t section_memsz;
- size_t section_filesz;
- EFI_IMAGE_DATA_DIRECTORY *debugdir;
- struct {
- EFI_IMAGE_DEBUG_DIRECTORY_ENTRY debug;
- EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY rsds;
- char name[ strlen ( filename ) + 1 ];
- } *contents;
-
- /* Allocate PE section */
- section_memsz = sizeof ( *contents );
- section_filesz = efi_file_align ( section_memsz );
- debug = xmalloc ( sizeof ( *debug ) + section_filesz );
- memset ( debug, 0, sizeof ( *debug ) + section_filesz );
- contents = ( void * ) debug->contents;
-
- /* Fill in section header details */
- strncpy ( ( char * ) debug->hdr.Name, ".debug",
- sizeof ( debug->hdr.Name ) );
- debug->hdr.Misc.VirtualSize = section_memsz;
- debug->hdr.VirtualAddress = pe_header->nt.OptionalHeader.SizeOfImage;
- debug->hdr.SizeOfRawData = section_filesz;
- debug->hdr.Characteristics = ( EFI_IMAGE_SCN_CNT_INITIALIZED_DATA |
- EFI_IMAGE_SCN_MEM_NOT_PAGED |
- EFI_IMAGE_SCN_MEM_READ );
-
- /* Create section contents */
- contents->debug.TimeDateStamp = 0x10d1a884;
- contents->debug.Type = EFI_IMAGE_DEBUG_TYPE_CODEVIEW;
- contents->debug.SizeOfData =
- ( sizeof ( *contents ) - sizeof ( contents->debug ) );
- contents->debug.RVA = ( debug->hdr.VirtualAddress +
- offsetof ( typeof ( *contents ), rsds ) );
- contents->rsds.Signature = CODEVIEW_SIGNATURE_RSDS;
- snprintf ( contents->name, sizeof ( contents->name ), "%s",
- filename );
-
- /* Update file header details */
- pe_header->nt.FileHeader.NumberOfSections++;
- pe_header->nt.OptionalHeader.SizeOfHeaders += sizeof ( debug->hdr );
- pe_header->nt.OptionalHeader.SizeOfImage += section_filesz;
- debugdir = &(pe_header->nt.OptionalHeader.DataDirectory
- [EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);
- debugdir->VirtualAddress = debug->hdr.VirtualAddress;
- debugdir->Size = debug->hdr.Misc.VirtualSize;
-
- return debug;
-}
-
-/**
- * Write out PE file
- *
- * @v pe_header PE file header
- * @v pe_sections List of PE sections
- * @v pe Output file
- */
-static void write_pe_file ( struct pe_header *pe_header,
- struct pe_section *pe_sections,
- FILE *pe ) {
- struct pe_section *section;
- unsigned long fpos = 0;
-
- /* Assign raw data pointers */
- fpos = efi_file_align ( pe_header->nt.OptionalHeader.SizeOfHeaders );
- for ( section = pe_sections ; section ; section = section->next ) {
- if ( section->hdr.SizeOfRawData ) {
- section->hdr.PointerToRawData = fpos;
- fpos += section->hdr.SizeOfRawData;
- fpos = efi_file_align ( fpos );
- }
- }
-
- /* Write file header */
- if ( fwrite ( pe_header, sizeof ( *pe_header ), 1, pe ) != 1 ) {
- perror ( "Could not write PE header" );
- exit ( 1 );
- }
-
- /* Write section headers */
- for ( section = pe_sections ; section ; section = section->next ) {
- if ( fwrite ( &section->hdr, sizeof ( section->hdr ),
- 1, pe ) != 1 ) {
- perror ( "Could not write section header" );
- exit ( 1 );
- }
- }
-
- /* Write sections */
- for ( section = pe_sections ; section ; section = section->next ) {
- if ( fseek ( pe, section->hdr.PointerToRawData,
- SEEK_SET ) != 0 ) {
- eprintf ( "Could not seek to %lx: %s\n",
- section->hdr.PointerToRawData,
- strerror ( errno ) );
- exit ( 1 );
- }
- if ( section->hdr.SizeOfRawData &&
- ( fwrite ( section->contents, section->hdr.SizeOfRawData,
- 1, pe ) != 1 ) ) {
- eprintf ( "Could not write section %.8s: %s\n",
- section->hdr.Name, strerror ( errno ) );
- exit ( 1 );
- }
- }
-}
-
-/**
- * Convert ELF to PE
- *
- * @v elf_name ELF file name
- * @v pe_name PE file name
- */
-static void elf2pe ( const char *elf_name, const char *pe_name,
- struct options *opts ) {
- char pe_name_tmp[ strlen ( pe_name ) + 1 ];
- bfd *bfd;
- asymbol **symtab;
- asection *section;
- arelent **reltab;
- arelent **rel;
- struct pe_relocs *pe_reltab = NULL;
- struct pe_section *pe_sections = NULL;
- struct pe_section **next_pe_section = &pe_sections;
- struct pe_header pe_header;
- FILE *pe;
-
- /* Create a modifiable copy of the PE name */
- memcpy ( pe_name_tmp, pe_name, sizeof ( pe_name_tmp ) );
-
- /* Open the file */
- bfd = open_input_bfd ( elf_name );
- symtab = read_symtab ( bfd );
-
- /* Initialise the PE header */
- memcpy ( &pe_header, &efi_pe_header, sizeof ( pe_header ) );
- pe_header.nt.OptionalHeader.AddressOfEntryPoint =
- bfd_get_start_address ( bfd );
- pe_header.nt.OptionalHeader.Subsystem = opts->subsystem;
-
- /* For each input section, build an output section and create
- * the appropriate relocation records
- */
- for ( section = bfd->sections ; section ; section = section->next ) {
- /* Discard non-allocatable sections */
- if ( ! ( bfd_get_section_flags ( bfd, section ) & SEC_ALLOC ) )
- continue;
- /* Create output section */
- *(next_pe_section) = process_section ( bfd, &pe_header,
- section );
- next_pe_section = &(*next_pe_section)->next;
- /* Add relocations from this section */
- reltab = read_reltab ( bfd, symtab, section );
- for ( rel = reltab ; *rel ; rel++ )
- process_reloc ( bfd, section, *rel, &pe_reltab );
- free ( reltab );
- }
-
- /* Create the .reloc section */
- *(next_pe_section) = create_reloc_section ( &pe_header, pe_reltab );
- next_pe_section = &(*next_pe_section)->next;
-
- /* Create the .reloc section */
- *(next_pe_section) = create_debug_section ( &pe_header,
- basename ( pe_name_tmp ) );
- next_pe_section = &(*next_pe_section)->next;
-
- /* Write out PE file */
- pe = fopen ( pe_name, "w" );
- if ( ! pe ) {
- eprintf ( "Could not open %s for writing: %s\n",
- pe_name, strerror ( errno ) );
- exit ( 1 );
- }
- write_pe_file ( &pe_header, pe_sections, pe );
- fclose ( pe );
-
- /* Close BFD file */
- bfd_close ( bfd );
-}
-
-/**
- * Print help
- *
- * @v program_name Program name
- */
-static void print_help ( const char *program_name ) {
- eprintf ( "Syntax: %s [--subsystem=<number>] infile outfile\n",
- program_name );
-}
-
-/**
- * Parse command-line options
- *
- * @v argc Argument count
- * @v argv Argument list
- * @v opts Options structure to populate
- */
-static int parse_options ( const int argc, char **argv,
- struct options *opts ) {
- char *end;
- int c;
-
- while (1) {
- int option_index = 0;
- static struct option long_options[] = {
- { "subsystem", required_argument, NULL, 's' },
- { "help", 0, NULL, 'h' },
- { 0, 0, 0, 0 }
- };
-
- if ( ( c = getopt_long ( argc, argv, "s:h",
- long_options,
- &option_index ) ) == -1 ) {
- break;
- }
-
- switch ( c ) {
- case 's':
- opts->subsystem = strtoul ( optarg, &end, 0 );
- if ( *end ) {
- eprintf ( "Invalid subsytem \"%s\"\n",
- optarg );
- exit ( 2 );
- }
- break;
- case 'h':
- print_help ( argv[0] );
- exit ( 0 );
- case '?':
- default:
- exit ( 2 );
- }
- }
- return optind;
-}
-
-int main ( int argc, char **argv ) {
- struct options opts = {
- .subsystem = EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION,
- };
- unsigned int infile_index;
- const char *infile;
- const char *outfile;
-
- /* Initialise libbfd */
- bfd_init();
-
- /* Parse command-line arguments */
- infile_index = parse_options ( argc, argv, &opts );
- if ( argc != ( infile_index + 2 ) ) {
- print_help ( argv[0] );
- exit ( 2 );
- }
- infile = argv[infile_index];
- outfile = argv[infile_index + 1];
-
- /* Convert file */
- elf2pe ( infile, outfile, &opts );
-
- return 0;
-}