Browse Source

[efi] Allow for .efidrv images as well as .efi images

Merge in the changes that allow for building EFI driver images (that
can be loaded using the EFI shell's "load" command) as well as EFI
applications.
tags/v0.9.7
Michael Brown 16 years ago
parent
commit
765efac771

+ 5
- 14
src/arch/i386/Makefile.efi View File

@@ -1,19 +1,10 @@
1 1
 # -*- makefile -*- : Force emacs to use Makefile mode
2 2
 
3
-# The EFI linker script
3
+# Specify EFI image builder
4 4
 #
5
-LDSCRIPT	= arch/x86/scripts/efi.lds
5
+ELF2EFI		= $(ELF2EFI32)
6 6
 
7
-# Retain relocation information for elf2efi
7
+# Include generic EFI Makefile
8 8
 #
9
-LDFLAGS		+= -q -S
10
-
11
-# Media types.
12
-#
13
-NON_AUTO_MEDIA	+= efi
14
-
15
-# Rule for building EFI files
16
-#
17
-$(BIN)/%.efi : $(BIN)/%.efi.tmp $(ELF2EFI32)
18
-	$(QM)$(ECHO) "  [FINISH] $@"
19
-	$(Q)$(ELF2EFI32) $< $@
9
+MAKEDEPS	+= arch/x86/Makefile.efi
10
+include arch/x86/Makefile.efi

+ 24
- 0
src/arch/x86/Makefile.efi View File

@@ -0,0 +1,24 @@
1
+# -*- makefile -*- : Force emacs to use Makefile mode
2
+
3
+# The EFI linker script
4
+#
5
+LDSCRIPT	= arch/x86/scripts/efi.lds
6
+
7
+# Retain relocation information for elf2efi
8
+#
9
+LDFLAGS		+= -q -S
10
+
11
+# Media types.
12
+#
13
+NON_AUTO_MEDIA	+= efi
14
+NON_AUTO_MEDIA	+= efidrv
15
+
16
+# Rules for building EFI files
17
+#
18
+$(BIN)/%.efi : $(BIN)/%.efi.tmp $(ELF2EFI)
19
+	$(QM)$(ECHO) "  [FINISH] $@"
20
+	$(Q)$(ELF2EFI) --subsystem=10 $< $@
21
+
22
+$(BIN)/%.efidrv : $(BIN)/%.efidrv.tmp $(ELF2EFI)
23
+	$(QM)$(ECHO) "  [FINISH] $@"
24
+	$(Q)$(ELF2EFI) --subsystem=11 $< $@

+ 44
- 0
src/arch/x86/prefix/efidrvprefix.c View File

@@ -0,0 +1,44 @@
1
+/*
2
+ * Copyright (C) 2009 Michael Brown <mbrown@fensystems.co.uk>.
3
+ *
4
+ * This program is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU General Public License as
6
+ * published by the Free Software Foundation; either version 2 of the
7
+ * License, or any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful, but
10
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
+ * General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
+ */
18
+
19
+#include <stdlib.h>
20
+#include <gpxe/init.h>
21
+#include <gpxe/efi/efi.h>
22
+
23
+/**
24
+ * EFI entry point
25
+ *
26
+ * @v image_handle	Image handle
27
+ * @v systab		System table
28
+ * @ret efirc		EFI return status code
29
+ */
30
+EFI_STATUS EFIAPI _start ( EFI_HANDLE image_handle,
31
+			   EFI_SYSTEM_TABLE *systab ) {
32
+	EFI_STATUS efirc;
33
+
34
+	/* Initialise EFI environment */
35
+	if ( ( efirc = efi_init ( image_handle, systab ) ) != 0 )
36
+		return efirc;
37
+
38
+	/* Initialise gPXE environment */
39
+	initialise();
40
+	startup();
41
+
42
+	/* Install SNP driver and return */
43
+	return RC_TO_EFIRC ( efi_snp_install () );
44
+}

+ 0
- 1
src/arch/x86/scripts/efi.lds View File

@@ -5,7 +5,6 @@
5 5
  *
6 6
  */
7 7
 
8
-EXTERN ( _start )
9 8
 ENTRY ( _start )
10 9
 
11 10
 SECTIONS {

+ 5
- 14
src/arch/x86_64/Makefile.efi View File

@@ -4,20 +4,11 @@
4 4
 #
5 5
 CFLAGS		+= -mno-red-zone
6 6
 
7
-# The EFI linker script
7
+# Specify EFI image builder
8 8
 #
9
-LDSCRIPT	= arch/x86/scripts/efi.lds
9
+ELF2EFI		= $(ELF2EFI64)
10 10
 
11
-# Retain relocation information for elf2efi
11
+# Include generic EFI Makefile
12 12
 #
13
-LDFLAGS		+= -q -S
14
-
15
-# Media types.
16
-#
17
-NON_AUTO_MEDIA	+= efi
18
-
19
-# Rule for building EFI files
20
-#
21
-$(BIN)/%.efi : $(BIN)/%.efi.tmp $(ELF2EFI64)
22
-	$(QM)$(ECHO) "  [FINISH] $@"
23
-	$(Q)$(ELF2EFI64) $< $@
13
+MAKEDEPS	+= arch/x86/Makefile.efi
14
+include arch/x86/Makefile.efi

+ 1
- 0
src/include/gpxe/efi/efi.h View File

@@ -126,5 +126,6 @@ extern EFI_SYSTEM_TABLE *efi_systab;
126 126
 extern const char * efi_strerror ( EFI_STATUS efirc );
127 127
 extern EFI_STATUS efi_init ( EFI_HANDLE image_handle,
128 128
 			     EFI_SYSTEM_TABLE *systab );
129
+extern int efi_snp_install ( void );
129 130
 
130 131
 #endif /* _EFI_H */

+ 93
- 14
src/util/elf2efi.c View File

@@ -25,6 +25,7 @@
25 25
 #include <unistd.h>
26 26
 #include <errno.h>
27 27
 #include <assert.h>
28
+#include <getopt.h>
28 29
 #include <bfd.h>
29 30
 
30 31
 /* Include the EFI PE image header file */
@@ -69,6 +70,8 @@ typedef uint64_t UINT64;
69 70
 #define  BIT31    0x80000000
70 71
 #include "../include/gpxe/efi/IndustryStandard/PeImage.h"
71 72
 
73
+#define eprintf(...) fprintf ( stderr, __VA_ARGS__ )
74
+
72 75
 #define EFI_FILE_ALIGN 0x20
73 76
 
74 77
 struct pe_section {
@@ -127,13 +130,17 @@ static struct pe_header efi_pe_header = {
127 130
 			.FileAlignment = EFI_FILE_ALIGN,
128 131
 			.SizeOfImage = sizeof ( efi_pe_header ),
129 132
 			.SizeOfHeaders = sizeof ( efi_pe_header ),
130
-			.Subsystem = EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION,
131 133
 			.NumberOfRvaAndSizes =
132 134
 				EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES,
133 135
 		},
134 136
 	},
135 137
 };
136 138
 
139
+/** Command-line options */
140
+struct options {
141
+	unsigned int subsystem;
142
+};
143
+
137 144
 /**
138 145
  * Allocate memory
139 146
  *
@@ -145,7 +152,7 @@ static void * xmalloc ( size_t len ) {
145 152
 
146 153
 	ptr = malloc ( len );
147 154
 	if ( ! ptr ) {
148
-		fprintf ( stderr, "Could not allocate %zd bytes\n", len );
155
+		eprintf ( "Could not allocate %zd bytes\n", len );
149 156
 		exit ( 1 );
150 157
 	}
151 158
 
@@ -190,7 +197,7 @@ static void generate_pe_reloc ( struct pe_relocs **pe_reltab,
190 197
 		reloc |= 0x2000;
191 198
 		break;
192 199
 	default:
193
-		fprintf ( stderr, "Unsupported relocation size %zd\n", size );
200
+		eprintf ( "Unsupported relocation size %zd\n", size );
194 201
 		exit ( 1 );
195 202
 	}
196 203
 
@@ -271,7 +278,7 @@ static bfd * open_input_bfd ( const char *filename ) {
271 278
 	/* Open the file */
272 279
 	bfd = bfd_openr ( filename, NULL );
273 280
 	if ( ! bfd ) {
274
-		fprintf ( stderr, "Cannot open %s: ", filename );
281
+		eprintf ( "Cannot open %s: ", filename );
275 282
 		bfd_perror ( NULL );
276 283
 		exit ( 1 );
277 284
 	}
@@ -280,7 +287,7 @@ static bfd * open_input_bfd ( const char *filename ) {
280 287
 	 * we get a segfault from later BFD calls.
281 288
 	 */
282 289
 	if ( bfd_check_format ( bfd, bfd_object ) < 0 ) {
283
-		fprintf ( stderr, "%s is not an object file\n", filename );
290
+		eprintf ( "%s is not an object file\n", filename );
284 291
 		exit ( 1 );
285 292
 	}
286 293
 
@@ -442,8 +449,7 @@ static struct pe_section * process_section ( bfd *bfd,
442 449
 	if ( flags & SEC_LOAD ) {
443 450
 		if ( ! bfd_get_section_contents ( bfd, section, new->contents,
444 451
 						  0, section_memsz ) ) {
445
-			fprintf ( stderr, "Cannot read section %s: ",
446
-				  section->name );
452
+			eprintf ( "Cannot read section %s: ", section->name );
447 453
 			bfd_perror ( NULL );
448 454
 			exit ( 1 );
449 455
 		}
@@ -518,8 +524,7 @@ static void process_reloc ( bfd *bfd, asection *section, arelent *rel,
518 524
 		 * remain unaltered when the object is loaded.
519 525
 		 */
520 526
 	} else {
521
-		fprintf ( stderr, "Unrecognised relocation type %s\n",
522
-			  howto->name );
527
+		eprintf ( "Unrecognised relocation type %s\n", howto->name );
523 528
 		exit ( 1 );
524 529
 	}
525 530
 }
@@ -670,7 +675,7 @@ static void write_pe_file ( struct pe_header *pe_header,
670 675
 	for ( section = pe_sections ; section ; section = section->next ) {
671 676
 		if ( fseek ( pe, section->hdr.PointerToRawData,
672 677
 			     SEEK_SET ) != 0 ) {
673
-			fprintf ( stderr, "Could not seek to %lx: %s\n",
678
+			eprintf ( "Could not seek to %lx: %s\n",
674 679
 				  section->hdr.PointerToRawData,
675 680
 				  strerror ( errno ) );
676 681
 			exit ( 1 );
@@ -678,7 +683,7 @@ static void write_pe_file ( struct pe_header *pe_header,
678 683
 		if ( section->hdr.SizeOfRawData &&
679 684
 		     ( fwrite ( section->contents, section->hdr.SizeOfRawData,
680 685
 				1, pe ) != 1 ) ) {
681
-			fprintf ( stderr, "Could not write section %.8s: %s\n",
686
+			eprintf ( "Could not write section %.8s: %s\n",
682 687
 				  section->hdr.Name, strerror ( errno ) );
683 688
 			exit ( 1 );
684 689
 		}
@@ -691,7 +696,8 @@ static void write_pe_file ( struct pe_header *pe_header,
691 696
  * @v elf_name		ELF file name
692 697
  * @v pe_name		PE file name
693 698
  */
694
-static void elf2pe ( const char *elf_name, const char *pe_name ) {
699
+static void elf2pe ( const char *elf_name, const char *pe_name,
700
+		     struct options *opts ) {
695 701
 	bfd *bfd;
696 702
 	asymbol **symtab;
697 703
 	asection *section;
@@ -711,6 +717,7 @@ static void elf2pe ( const char *elf_name, const char *pe_name ) {
711 717
 	memcpy ( &pe_header, &efi_pe_header, sizeof ( pe_header ) );
712 718
 	pe_header.nt.OptionalHeader.AddressOfEntryPoint =
713 719
 		bfd_get_start_address ( bfd );
720
+	pe_header.nt.OptionalHeader.Subsystem = opts->subsystem;
714 721
 
715 722
 	/* For each input section, build an output section and create
716 723
 	 * the appropriate relocation records
@@ -742,7 +749,7 @@ static void elf2pe ( const char *elf_name, const char *pe_name ) {
742 749
 	/* Write out PE file */
743 750
 	pe = fopen ( pe_name, "w" );
744 751
 	if ( ! pe ) {
745
-		fprintf ( stderr, "Could not open %s for writing: %s\n",
752
+		eprintf ( "Could not open %s for writing: %s\n",
746 753
 			  pe_name, strerror ( errno ) );
747 754
 		exit ( 1 );
748 755
 	}
@@ -753,12 +760,84 @@ static void elf2pe ( const char *elf_name, const char *pe_name ) {
753 760
 	bfd_close ( bfd );
754 761
 }
755 762
 
763
+/**
764
+ * Print help
765
+ *
766
+ * @v program_name	Program name
767
+ */
768
+static void print_help ( const char *program_name ) {
769
+	eprintf ( "Syntax: %s [--subsystem=<number>] infile outfile\n",
770
+		  program_name );
771
+}
772
+
773
+/**
774
+ * Parse command-line options
775
+ *
776
+ * @v argc		Argument count
777
+ * @v argv		Argument list
778
+ * @v opts		Options structure to populate
779
+ */
780
+static int parse_options ( const int argc, char **argv,
781
+			   struct options *opts ) {
782
+	char *end;
783
+	int c;
784
+
785
+	while (1) {
786
+		int option_index = 0;
787
+		static struct option long_options[] = {
788
+			{ "subsystem", required_argument, NULL, 's' },
789
+			{ "help", 0, NULL, 'h' },
790
+			{ 0, 0, 0, 0 }
791
+		};
792
+
793
+		if ( ( c = getopt_long ( argc, argv, "s:h",
794
+					 long_options,
795
+					 &option_index ) ) == -1 ) {
796
+			break;
797
+		}
798
+
799
+		switch ( c ) {
800
+		case 's':
801
+			opts->subsystem = strtoul ( optarg, &end, 0 );
802
+			if ( *end ) {
803
+				eprintf ( "Invalid subsytem \"%s\"\n",
804
+					  optarg );
805
+				exit ( 2 );
806
+			}
807
+			break;
808
+		case 'h':
809
+			print_help ( argv[0] );
810
+			exit ( 0 );
811
+		case '?':
812
+		default:
813
+			exit ( 2 );
814
+		}
815
+	}
816
+	return optind;
817
+}
818
+
756 819
 int main ( int argc, char **argv ) {
820
+	struct options opts = {
821
+		.subsystem = EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION,
822
+	};
823
+	unsigned int infile_index;
824
+	const char *infile;
825
+	const char *outfile;
757 826
 
758 827
 	/* Initialise libbfd */
759 828
 	bfd_init();
760 829
 
761
-	elf2pe ( argv[1], argv[2] );
830
+	/* Parse command-line arguments */
831
+	infile_index = parse_options ( argc, argv, &opts );
832
+	if ( argc != ( infile_index + 2 ) ) {
833
+		print_help ( argv[0] );
834
+		exit ( 2 );
835
+	}
836
+	infile = argv[infile_index];
837
+	outfile = argv[infile_index + 1];
838
+
839
+	/* Convert file */
840
+	elf2pe ( infile, outfile, &opts );
762 841
 
763 842
 	return 0;
764 843
 }

Loading…
Cancel
Save