--- /dev/null
+/*
+ * 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.
+ */
+
+#include <stdlib.h>
+#include <gpxe/init.h>
+#include <gpxe/efi/efi.h>
+
+/**
+ * EFI entry point
+ *
+ * @v image_handle Image handle
+ * @v systab System table
+ * @ret efirc EFI return status code
+ */
+EFI_STATUS EFIAPI _start ( EFI_HANDLE image_handle,
+ EFI_SYSTEM_TABLE *systab ) {
+ EFI_STATUS efirc;
+
+ /* Initialise EFI environment */
+ if ( ( efirc = efi_init ( image_handle, systab ) ) != 0 )
+ return efirc;
+
+ /* Initialise gPXE environment */
+ initialise();
+ startup();
+
+ /* Install SNP driver and return */
+ return RC_TO_EFIRC ( efi_snp_install () );
+}
#include <unistd.h>
#include <errno.h>
#include <assert.h>
+#include <getopt.h>
#include <bfd.h>
/* Include the EFI PE image header file */
#define BIT31 0x80000000
#include "../include/gpxe/efi/IndustryStandard/PeImage.h"
+#define eprintf(...) fprintf ( stderr, __VA_ARGS__ )
+
#define EFI_FILE_ALIGN 0x20
struct pe_section {
.FileAlignment = EFI_FILE_ALIGN,
.SizeOfImage = sizeof ( efi_pe_header ),
.SizeOfHeaders = sizeof ( efi_pe_header ),
- .Subsystem = EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION,
.NumberOfRvaAndSizes =
EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES,
},
},
};
+/** Command-line options */
+struct options {
+ unsigned int subsystem;
+};
+
/**
* Allocate memory
*
ptr = malloc ( len );
if ( ! ptr ) {
- fprintf ( stderr, "Could not allocate %zd bytes\n", len );
+ eprintf ( "Could not allocate %zd bytes\n", len );
exit ( 1 );
}
reloc |= 0x2000;
break;
default:
- fprintf ( stderr, "Unsupported relocation size %zd\n", size );
+ eprintf ( "Unsupported relocation size %zd\n", size );
exit ( 1 );
}
/* Open the file */
bfd = bfd_openr ( filename, NULL );
if ( ! bfd ) {
- fprintf ( stderr, "Cannot open %s: ", filename );
+ eprintf ( "Cannot open %s: ", filename );
bfd_perror ( NULL );
exit ( 1 );
}
* we get a segfault from later BFD calls.
*/
if ( bfd_check_format ( bfd, bfd_object ) < 0 ) {
- fprintf ( stderr, "%s is not an object file\n", filename );
+ eprintf ( "%s is not an object file\n", filename );
exit ( 1 );
}
if ( flags & SEC_LOAD ) {
if ( ! bfd_get_section_contents ( bfd, section, new->contents,
0, section_memsz ) ) {
- fprintf ( stderr, "Cannot read section %s: ",
- section->name );
+ eprintf ( "Cannot read section %s: ", section->name );
bfd_perror ( NULL );
exit ( 1 );
}
* remain unaltered when the object is loaded.
*/
} else {
- fprintf ( stderr, "Unrecognised relocation type %s\n",
- howto->name );
+ eprintf ( "Unrecognised relocation type %s\n", howto->name );
exit ( 1 );
}
}
for ( section = pe_sections ; section ; section = section->next ) {
if ( fseek ( pe, section->hdr.PointerToRawData,
SEEK_SET ) != 0 ) {
- fprintf ( stderr, "Could not seek to %lx: %s\n",
+ 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 ) ) {
- fprintf ( stderr, "Could not write section %.8s: %s\n",
+ eprintf ( "Could not write section %.8s: %s\n",
section->hdr.Name, strerror ( errno ) );
exit ( 1 );
}
* @v elf_name ELF file name
* @v pe_name PE file name
*/
-static void elf2pe ( const char *elf_name, const char *pe_name ) {
+static void elf2pe ( const char *elf_name, const char *pe_name,
+ struct options *opts ) {
bfd *bfd;
asymbol **symtab;
asection *section;
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
/* Write out PE file */
pe = fopen ( pe_name, "w" );
if ( ! pe ) {
- fprintf ( stderr, "Could not open %s for writing: %s\n",
+ eprintf ( "Could not open %s for writing: %s\n",
pe_name, strerror ( errno ) );
exit ( 1 );
}
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();
- elf2pe ( argv[1], argv[2] );
+ /* 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;
}