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 15 years ago
parent
commit
765efac771

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

1
 # -*- makefile -*- : Force emacs to use Makefile mode
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

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

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
  *
5
  *
6
  */
6
  */
7
 
7
 
8
-EXTERN ( _start )
9
 ENTRY ( _start )
8
 ENTRY ( _start )
10
 
9
 
11
 SECTIONS {
10
 SECTIONS {

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

4
 #
4
 #
5
 CFLAGS		+= -mno-red-zone
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
 extern const char * efi_strerror ( EFI_STATUS efirc );
126
 extern const char * efi_strerror ( EFI_STATUS efirc );
127
 extern EFI_STATUS efi_init ( EFI_HANDLE image_handle,
127
 extern EFI_STATUS efi_init ( EFI_HANDLE image_handle,
128
 			     EFI_SYSTEM_TABLE *systab );
128
 			     EFI_SYSTEM_TABLE *systab );
129
+extern int efi_snp_install ( void );
129
 
130
 
130
 #endif /* _EFI_H */
131
 #endif /* _EFI_H */

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

25
 #include <unistd.h>
25
 #include <unistd.h>
26
 #include <errno.h>
26
 #include <errno.h>
27
 #include <assert.h>
27
 #include <assert.h>
28
+#include <getopt.h>
28
 #include <bfd.h>
29
 #include <bfd.h>
29
 
30
 
30
 /* Include the EFI PE image header file */
31
 /* Include the EFI PE image header file */
69
 #define  BIT31    0x80000000
70
 #define  BIT31    0x80000000
70
 #include "../include/gpxe/efi/IndustryStandard/PeImage.h"
71
 #include "../include/gpxe/efi/IndustryStandard/PeImage.h"
71
 
72
 
73
+#define eprintf(...) fprintf ( stderr, __VA_ARGS__ )
74
+
72
 #define EFI_FILE_ALIGN 0x20
75
 #define EFI_FILE_ALIGN 0x20
73
 
76
 
74
 struct pe_section {
77
 struct pe_section {
127
 			.FileAlignment = EFI_FILE_ALIGN,
130
 			.FileAlignment = EFI_FILE_ALIGN,
128
 			.SizeOfImage = sizeof ( efi_pe_header ),
131
 			.SizeOfImage = sizeof ( efi_pe_header ),
129
 			.SizeOfHeaders = sizeof ( efi_pe_header ),
132
 			.SizeOfHeaders = sizeof ( efi_pe_header ),
130
-			.Subsystem = EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION,
131
 			.NumberOfRvaAndSizes =
133
 			.NumberOfRvaAndSizes =
132
 				EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES,
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
  * Allocate memory
145
  * Allocate memory
139
  *
146
  *
145
 
152
 
146
 	ptr = malloc ( len );
153
 	ptr = malloc ( len );
147
 	if ( ! ptr ) {
154
 	if ( ! ptr ) {
148
-		fprintf ( stderr, "Could not allocate %zd bytes\n", len );
155
+		eprintf ( "Could not allocate %zd bytes\n", len );
149
 		exit ( 1 );
156
 		exit ( 1 );
150
 	}
157
 	}
151
 
158
 
190
 		reloc |= 0x2000;
197
 		reloc |= 0x2000;
191
 		break;
198
 		break;
192
 	default:
199
 	default:
193
-		fprintf ( stderr, "Unsupported relocation size %zd\n", size );
200
+		eprintf ( "Unsupported relocation size %zd\n", size );
194
 		exit ( 1 );
201
 		exit ( 1 );
195
 	}
202
 	}
196
 
203
 
271
 	/* Open the file */
278
 	/* Open the file */
272
 	bfd = bfd_openr ( filename, NULL );
279
 	bfd = bfd_openr ( filename, NULL );
273
 	if ( ! bfd ) {
280
 	if ( ! bfd ) {
274
-		fprintf ( stderr, "Cannot open %s: ", filename );
281
+		eprintf ( "Cannot open %s: ", filename );
275
 		bfd_perror ( NULL );
282
 		bfd_perror ( NULL );
276
 		exit ( 1 );
283
 		exit ( 1 );
277
 	}
284
 	}
280
 	 * we get a segfault from later BFD calls.
287
 	 * we get a segfault from later BFD calls.
281
 	 */
288
 	 */
282
 	if ( bfd_check_format ( bfd, bfd_object ) < 0 ) {
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
 		exit ( 1 );
291
 		exit ( 1 );
285
 	}
292
 	}
286
 
293
 
442
 	if ( flags & SEC_LOAD ) {
449
 	if ( flags & SEC_LOAD ) {
443
 		if ( ! bfd_get_section_contents ( bfd, section, new->contents,
450
 		if ( ! bfd_get_section_contents ( bfd, section, new->contents,
444
 						  0, section_memsz ) ) {
451
 						  0, section_memsz ) ) {
445
-			fprintf ( stderr, "Cannot read section %s: ",
446
-				  section->name );
452
+			eprintf ( "Cannot read section %s: ", section->name );
447
 			bfd_perror ( NULL );
453
 			bfd_perror ( NULL );
448
 			exit ( 1 );
454
 			exit ( 1 );
449
 		}
455
 		}
518
 		 * remain unaltered when the object is loaded.
524
 		 * remain unaltered when the object is loaded.
519
 		 */
525
 		 */
520
 	} else {
526
 	} else {
521
-		fprintf ( stderr, "Unrecognised relocation type %s\n",
522
-			  howto->name );
527
+		eprintf ( "Unrecognised relocation type %s\n", howto->name );
523
 		exit ( 1 );
528
 		exit ( 1 );
524
 	}
529
 	}
525
 }
530
 }
670
 	for ( section = pe_sections ; section ; section = section->next ) {
675
 	for ( section = pe_sections ; section ; section = section->next ) {
671
 		if ( fseek ( pe, section->hdr.PointerToRawData,
676
 		if ( fseek ( pe, section->hdr.PointerToRawData,
672
 			     SEEK_SET ) != 0 ) {
677
 			     SEEK_SET ) != 0 ) {
673
-			fprintf ( stderr, "Could not seek to %lx: %s\n",
678
+			eprintf ( "Could not seek to %lx: %s\n",
674
 				  section->hdr.PointerToRawData,
679
 				  section->hdr.PointerToRawData,
675
 				  strerror ( errno ) );
680
 				  strerror ( errno ) );
676
 			exit ( 1 );
681
 			exit ( 1 );
678
 		if ( section->hdr.SizeOfRawData &&
683
 		if ( section->hdr.SizeOfRawData &&
679
 		     ( fwrite ( section->contents, section->hdr.SizeOfRawData,
684
 		     ( fwrite ( section->contents, section->hdr.SizeOfRawData,
680
 				1, pe ) != 1 ) ) {
685
 				1, pe ) != 1 ) ) {
681
-			fprintf ( stderr, "Could not write section %.8s: %s\n",
686
+			eprintf ( "Could not write section %.8s: %s\n",
682
 				  section->hdr.Name, strerror ( errno ) );
687
 				  section->hdr.Name, strerror ( errno ) );
683
 			exit ( 1 );
688
 			exit ( 1 );
684
 		}
689
 		}
691
  * @v elf_name		ELF file name
696
  * @v elf_name		ELF file name
692
  * @v pe_name		PE file name
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
 	bfd *bfd;
701
 	bfd *bfd;
696
 	asymbol **symtab;
702
 	asymbol **symtab;
697
 	asection *section;
703
 	asection *section;
711
 	memcpy ( &pe_header, &efi_pe_header, sizeof ( pe_header ) );
717
 	memcpy ( &pe_header, &efi_pe_header, sizeof ( pe_header ) );
712
 	pe_header.nt.OptionalHeader.AddressOfEntryPoint =
718
 	pe_header.nt.OptionalHeader.AddressOfEntryPoint =
713
 		bfd_get_start_address ( bfd );
719
 		bfd_get_start_address ( bfd );
720
+	pe_header.nt.OptionalHeader.Subsystem = opts->subsystem;
714
 
721
 
715
 	/* For each input section, build an output section and create
722
 	/* For each input section, build an output section and create
716
 	 * the appropriate relocation records
723
 	 * the appropriate relocation records
742
 	/* Write out PE file */
749
 	/* Write out PE file */
743
 	pe = fopen ( pe_name, "w" );
750
 	pe = fopen ( pe_name, "w" );
744
 	if ( ! pe ) {
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
 			  pe_name, strerror ( errno ) );
753
 			  pe_name, strerror ( errno ) );
747
 		exit ( 1 );
754
 		exit ( 1 );
748
 	}
755
 	}
753
 	bfd_close ( bfd );
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
 int main ( int argc, char **argv ) {
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
 	/* Initialise libbfd */
827
 	/* Initialise libbfd */
759
 	bfd_init();
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
 	return 0;
842
 	return 0;
764
 }
843
 }

Loading…
Cancel
Save