Browse Source

[efi] Use elf2efi utility in place of efilink

elf2efi converts a suitable ELF executable (containing relocation
information, and with appropriate virtual addresses) into an EFI
executable.  It is less tightly coupled with the gPXE build process
and, in particular, does not require the use of a hand-crafted PE
image header in efiprefix.S.

elf2efi correctly handles .bss sections, which significantly reduces
the size of the gPXE EFI executable.
tags/v0.9.7
Michael Brown 15 years ago
parent
commit
314779eb36

+ 2
- 1
src/Makefile View File

@@ -37,7 +37,8 @@ SYMCHECK	:= $(PERL) ./util/symcheck.pl
37 37
 SORTOBJDUMP	:= $(PERL) ./util/sortobjdump.pl
38 38
 NRV2B		:= ./util/nrv2b
39 39
 ZBIN		:= ./util/zbin
40
-EFILINK		:= ./util/efilink
40
+ELF2EFI32	:= ./util/elf2efi32
41
+ELF2EFI64	:= ./util/elf2efi64
41 42
 DOXYGEN		:= doxygen
42 43
 
43 44
 ###############################################################################

+ 9
- 4
src/Makefile.housekeeping View File

@@ -703,12 +703,17 @@ CLEANUP += $(ZBIN)
703 703
 
704 704
 ###############################################################################
705 705
 #
706
-# The EFI custom linker
706
+# The EFI image converter
707 707
 #
708
-$(EFILINK) : util/efilink.c $(MAKEDEPS)
708
+$(ELF2EFI32) : util/elf2efi.c $(MAKEDEPS)
709 709
 	$(QM)$(ECHO) "  [HOSTCC] $@"
710
-	$(Q)$(HOST_CC) -O2 -o $@ $< -lbfd -liberty
711
-CLEANUP += $(EFILINK)
710
+	$(Q)$(HOST_CC) -DMDE_CPU_IA32 -O2 -o $@ $< -lbfd -liberty
711
+CLEANUP += $(ELF2EFI32)
712
+
713
+$(ELF2EFI64) : util/elf2efi.c $(MAKEDEPS)
714
+	$(QM)$(ECHO) "  [HOSTCC] $@"
715
+	$(Q)$(HOST_CC) -DMDE_CPU_X64 -O2 -o $@ $< -lbfd -liberty
716
+CLEANUP += $(ELF2EFI64)
712 717
 
713 718
 ###############################################################################
714 719
 #

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

@@ -2,11 +2,11 @@
2 2
 
3 3
 # The EFI linker script
4 4
 #
5
-LDSCRIPT	= arch/i386/scripts/efi.lds
5
+LDSCRIPT	= arch/x86/scripts/efi.lds
6 6
 
7
-# Use a relocatable link; we perform final relocations in the efilink utility.
7
+# Retain relocation information for elf2efi
8 8
 #
9
-LDFLAGS		+= -r -d -S
9
+LDFLAGS		+= -q -S
10 10
 
11 11
 # Media types.
12 12
 #
@@ -14,12 +14,6 @@ NON_AUTO_MEDIA	+= efi
14 14
 
15 15
 # Rule for building EFI files
16 16
 #
17
-$(BIN)/%.efi.tmp-reloc : $(BIN)/%.efi.tmp $(EFILINK)
18
-	$(QM)$(ECHO) "  [EFILINK] $@"
19
-	$(Q)# Check for unresolved symbols
20
-	$(Q)$(LD) -e 0 --no-warn-mismatch -o /dev/null $<
21
-	$(Q)$(EFILINK) $< $@
22
-
23
-$(BIN)/%.efi : $(BIN)/%.efi.tmp-reloc
17
+$(BIN)/%.efi : $(BIN)/%.efi.tmp $(ELF2EFI32)
24 18
 	$(QM)$(ECHO) "  [FINISH] $@"
25
-	$(Q)$(OBJCOPY) -Obinary $< $@
19
+	$(Q)$(ELF2EFI32) $< $@

+ 0
- 175
src/arch/i386/prefix/efiprefix.S View File

@@ -1,175 +0,0 @@
1
-	.text
2
-	.code32
3
-	.arch i386
4
-	.section ".prefix", "a", @progbits
5
-	.org 0x00
6
-
7
-	/* DOS (.com) header
8
-	 *
9
-	 * EFI executables seem to leave most of this empty
10
-	 */
11
-mzhdr:
12
-	.ascii	"MZ"		/* Magic number */
13
-	.word	0		/* Bytes on last page of file */
14
-	.word	0		/* Pages in file */
15
-	.word	0		/* Relocations */
16
-	.word	0		/* Size of header in paragraphs */
17
-	.word	0		/* Minimum extra paragraphs needed */
18
-	.word	0		/* Maximum extra paragraphs needed */
19
-	.word	0		/* Initial (relative) SS value */
20
-	.word	0		/* Initial SP value */
21
-	.word	0		/* "Checksum" */
22
-	.word	0		/* Initial IP value */
23
-	.word	0		/* Initial (relative) CS value */
24
-	.word	0		/* File address of relocation table */
25
-	.word	0		/* Ovesrlay number */
26
-	.word	0, 0, 0, 0	/* Reserved words */
27
-	.word	0		/* OEM identifier (for e_oeminfo) */
28
-	.word	0		/* OEM information; e_oemid specific */
29
-	.word	0, 0, 0, 0, 0	/* Reserved words */
30
-	.word	0, 0, 0, 0, 0	/* Reserved words */
31
-	.long	pehdr_lma	/* File address of new exe header */
32
-	.size	mzhdr, . - mzhdr
33
-
34
-	/* PE header */
35
-	.org	0xc0 /* For compatibility with MS toolchain */
36
-pehdr:
37
-	.ascii	"PE\0\0"	/* Magic number */
38
-	.word	0x014c		/* CPU architecture: i386 */
39
-	.word	num_pe_sections	/* Number of sections */
40
-	.long	0x10d1a884	/* Timestamp */
41
-	.long	0		/* Symbol table */
42
-	.long	0		/* Number of symbols */
43
-	.word	opthdr_size	/* Size of optional header */
44
-	.word	0x2102		/* Characteristics */
45
-	.size	pehdr, . - pehdr
46
-	.equ	pehdr_lma, pehdr - mzhdr
47
-
48
-	/* "Optional" header */
49
-opthdr:
50
-	.word	0x010b		/* Magic number */
51
-	.byte	0		/* Linker major version number */
52
-	.byte	0		/* Linker minor version number */
53
-	.long	_text_filesz	/* Size of text section */
54
-	.long	_data_filesz	/* Size of data section */
55
-	.long	_bss_filesz	/* Size of bss section */
56
-	.long	efi_entry_lma	/* Entry point */
57
-	.long	_text_lma	/* Text section start RVA */
58
-	.long	_data_lma	/* Data section start RVA */
59
-	.long	0		/* Image base address */
60
-	.long	_max_align	/* Section alignment */
61
-	.long	_max_align	/* File alignment */
62
-	.word	0		/* Operating system major version number */
63
-	.word	0		/* Operating system minor version number */
64
-	.word	0		/* Image major version number */
65
-	.word	0		/* Image minor version number */
66
-	.word	0		/* Subsystem major version number */
67
-	.word	0		/* Subsystem minor version number */
68
-	.long	0		/* Reserved */
69
-	.long	_filesz		/* Total image size */
70
-	.long	_prefix_filesz	/* Total header size */
71
-	.long	0		/* "Checksum" */
72
-	.word	0x0a		/* Subsystem: EFI */
73
-	.word	0		/* DLL characteristics */
74
-	.long	0		/* Size of stack reserve */
75
-	.long	0		/* Size of stack commit */
76
-	.long	0		/* Size of heap reserve */
77
-	.long	0		/* Size of heap commit */
78
-	.long	0		/* Loader flags */
79
-	.long	16		/* Number of data directory entries */
80
-	.long	0, 0		/* Export directory */
81
-	.long	0, 0		/* Import directory */
82
-	.long	0, 0		/* Resource directory */
83
-	.long	0, 0		/* Exception directory */
84
-	.long	0, 0		/* Security directory */
85
-	.long	_reloc_lma, _reloc_filesz /* Base relocation directory */
86
-	.long	debugdir_lma, debugdir_size /* Debug directory */
87
-	.long	0, 0		/* Description directory */
88
-	.long	0, 0		/* Special directory */
89
-	.long	0, 0		/* Thread storage directory */
90
-	.long	0, 0		/* Load configuration directory */
91
-	.long	0, 0		/* Bound import directory */
92
-	.long	0, 0		/* Import address table directory */
93
-	.long	0, 0		/* Delay import directory */
94
-	.long	0, 0		/* Reserved */
95
-	.long	0, 0		/* Reserved */
96
-	.size	opthdr, . - opthdr
97
-	.equ	opthdr_size, . - opthdr
98
-
99
-	/* PE sections */
100
-pe_sections:
101
-text_section:
102
-	.asciz	".text"		/* Section name */
103
-	.align	8
104
-	.long	_text_filesz	/* Section size */
105
-	.long	_text_lma	/* Relative Virtual Address */
106
-	.long	_text_filesz	/* Section size (rounded up) */
107
-	.long	_text_lma	/* Pointer to raw data */
108
-	.long	0		/* Link-time relocations */
109
-	.long	0		/* Line numbers */
110
-	.word	0		/* Number of link-time relocations */
111
-	.word	0		/* Number of line numbers */
112
-	.long	0x68000020	/* Characteristics */
113
-rodata_section:
114
-	.asciz	".rodata"	/* Section name */
115
-	.align	8
116
-	.long	_rodata_filesz	/* Section size */
117
-	.long	_rodata_lma	/* Relative Virtual Address */
118
-	.long	_rodata_filesz	/* Section size (rounded up) */
119
-	.long	_rodata_lma	/* Pointer to raw data */
120
-	.long	0		/* Link-time relocations */
121
-	.long	0		/* Line numbers */
122
-	.word	0		/* Number of link-time relocations */
123
-	.word	0		/* Number of line numbers */
124
-	.long	0x48000040	/* Characteristics */
125
-data_section:
126
-	.asciz	".data"		/* Section name */
127
-	.align	8
128
-	.long	_data_filesz	/* Section size */
129
-	.long	_data_lma	/* Relative Virtual Address */
130
-	.long	_data_filesz	/* Section size (rounded up) */
131
-	.long	_data_lma	/* Pointer to raw data */
132
-	.long	0		/* Link-time relocations */
133
-	.long	0		/* Line numbers */
134
-	.word	0		/* Number of link-time relocations */
135
-	.word	0		/* Number of line numbers */
136
-	.long	0xc8000040	/* Characteristics */
137
-reloc_section:
138
-	.asciz	".reloc"	/* Section name */
139
-	.align	8
140
-	.long	_reloc_filesz	/* Section size */
141
-	.long	_reloc_lma	/* Relative Virtual Address */
142
-	.long	_reloc_filesz	/* Section size (rounded up) */
143
-	.long	_reloc_lma	/* Pointer to raw data */
144
-	.long	0		/* Link-time relocations */
145
-	.long	0		/* Line numbers */
146
-	.word	0		/* Number of link-time relocations */
147
-	.word	0		/* Number of line numbers */
148
-	.long	0x42000040	/* Characteristics */
149
-
150
-pe_sections_end:
151
-	.size	pe_sections, . - pe_sections
152
-	.equ	num_pe_sections, ( ( . - pe_sections ) / 0x28 )
153
-
154
-	/* Debug directory */
155
-	.section ".rodata"
156
-	.globl	debugdir
157
-debugdir:
158
-	.long	0		/* Characteristics */
159
-	.long	0x10d1a884	/* Timestamp */
160
-	.word	0		/* Major version */
161
-	.word	0		/* Minor version */
162
-	.long	0x02		/* RSDS? */
163
-	.long	codeview_rsds_size /* Size of data */
164
-	.long	codeview_rsds_lma /* RVA */
165
-	.long	codeview_rsds_lma /* File offset */
166
-	.size	debugdir, . - debugdir
167
-	.equ	debugdir_size, . - debugdir
168
-	/* Codeview structure */
169
-	.globl	codeview_rsds
170
-codeview_rsds:
171
-	.ascii	"RSDS"		/* Magic number */
172
-	.long	0, 0, 0, 0, 0	/* Unused by EFI */
173
-	.asciz	"efiprefix.pdb"
174
-	.size	codeview_rsds, . - codeview_rsds
175
-	.equ	codeview_rsds_size, . - codeview_rsds

+ 0
- 180
src/arch/i386/scripts/efi.lds View File

@@ -1,180 +0,0 @@
1
-/* -*- sh -*- */
2
-
3
-/*
4
- * Linker script for EFI images
5
- *
6
- */
7
-
8
-EXTERN ( efi_entry )
9
-
10
-SECTIONS {
11
-
12
-    /* The file starts at a virtual address of zero, and sections are
13
-     * contiguous.  Each section is aligned to at least _max_align,
14
-     * which defaults to 32.  Load addresses are equal to virtual
15
-     * addresses.
16
-     */
17
-
18
-    . = 0;
19
-    PROVIDE ( _max_align = 32 );
20
-
21
-    /*
22
-     * The prefix
23
-     *
24
-     */
25
-
26
-    .prefix : {
27
-	_prefix = .;
28
-	*(.prefix)
29
-	*(.prefix.*)
30
-	_mprefix = .;
31
-    } .bss.prefix (NOLOAD) : {
32
-	_eprefix = .;
33
-    }
34
-    _prefix_filesz	= ABSOLUTE ( _mprefix - _prefix );
35
-    _prefix_memsz	= ABSOLUTE ( _eprefix - _prefix );
36
-
37
-    /*
38
-     * The text section
39
-     *
40
-     */
41
-
42
-    . = ALIGN ( _max_align );
43
-    .text : {
44
-	_text = .;
45
-	*(.text)
46
-	*(.text.*)
47
-	_mtext = .;
48
-    } .bss.text (NOLOAD) : {
49
-	_etext = .;
50
-    }
51
-    _text_filesz	= ABSOLUTE ( _mtext - _text );
52
-    _text_memsz		= ABSOLUTE ( _etext - _text );
53
-
54
-    /*
55
-     * The rodata section
56
-     *
57
-     */
58
-
59
-    . = ALIGN ( _max_align );
60
-    .rodata : {
61
-	_rodata = .;
62
-	*(.rodata)
63
-	*(.rodata.*)
64
-	_mrodata = .;
65
-    } .bss.rodata (NOLOAD) : {
66
-	_erodata = .;
67
-    }
68
-    _rodata_filesz	= ABSOLUTE ( _mrodata - _rodata );
69
-    _rodata_memsz	= ABSOLUTE ( _erodata - _rodata );
70
-
71
-    /*
72
-     * The data section
73
-     *
74
-     */
75
-
76
-    . = ALIGN ( _max_align );
77
-    .data : {
78
-	_data = .;
79
-	*(.data)
80
-	*(.data.*)
81
-	*(SORT(.tbl.*))		/* Various tables.  See include/tables.h */
82
-	/* EFI seems to not support proper bss sections */
83
-	*(.bss)
84
-	*(.bss.*)
85
-	*(COMMON)
86
-	*(.stack)
87
-	*(.stack.*)
88
-	_mdata = .;
89
-    } .bss.data (NOLOAD) : {
90
-	_edata = .;
91
-    }
92
-    _data_filesz	= ABSOLUTE ( _mdata - _data );
93
-    _data_memsz		= ABSOLUTE ( _edata - _data );
94
-
95
-    /*
96
-     * The bss section
97
-     *
98
-     */
99
-
100
-    . = ALIGN ( _max_align );
101
-    .bss : { 
102
-	_bss = .;
103
-	/* EFI seems to not support proper bss sections */
104
-	_mbss = .;
105
-    } .bss.bss (NOLOAD) : {
106
-	_ebss = .;
107
-    }
108
-    _bss_filesz		= ABSOLUTE ( _mbss - _bss );
109
-    _bss_memsz		= ABSOLUTE ( _ebss - _bss );
110
-
111
-    /*
112
-     * The reloc section
113
-     *
114
-     */
115
-
116
-    . = ALIGN ( _max_align );
117
-    .reloc : {
118
-	_reloc = .;
119
-	/* Provide some dummy contents to force ld to include this
120
-	 * section.  It will be created by the efilink utility.
121
-	 */
122
-	. += 1;
123
-	_mreloc = .;
124
-    } .bss.reloc (NOLOAD) : {
125
-	_ereloc = .;
126
-    }
127
-    _reloc_filesz	= ABSOLUTE ( _mreloc - _reloc );
128
-    _reloc_memsz	= ABSOLUTE ( _ereloc - _reloc );
129
-
130
-    _filesz		= ABSOLUTE ( . );
131
-
132
-    /*
133
-     * Weak symbols that need zero values if not otherwise defined
134
-     *
135
-     */
136
-
137
-    .weak 0x0 : {
138
-	_weak = .;
139
-	*(.weak)
140
-	_eweak = .;
141
-    }
142
-    _assert = ASSERT ( ( _weak == _eweak ), ".weak is non-zero length" );
143
-
144
-    /*
145
-     * Dispose of the comment and note sections to make the link map
146
-     * easier to read
147
-     *
148
-     */
149
-
150
-    /DISCARD/ : {
151
-	*(.comment)
152
-	*(.comment.*)
153
-	*(.note)
154
-	*(.note.*)
155
-	*(.eh_frame)
156
-	*(.eh_frame.*)
157
-	*(.rel)
158
-	*(.rel.*)
159
-    }
160
-
161
-    /*
162
-     * Load address calculations.
163
-     *
164
-     */
165
-
166
-    _prefix_lma		= ABSOLUTE ( _prefix );
167
-    _text_lma		= ABSOLUTE ( _text );
168
-    _rodata_lma		= ABSOLUTE ( _rodata );
169
-    _data_lma		= ABSOLUTE ( _data );
170
-    _bss_lma		= ABSOLUTE ( _bss );
171
-    _reloc_lma		= ABSOLUTE ( _reloc );
172
-
173
-    /*
174
-     * Load addresses required by the prefix
175
-     *
176
-     */
177
-    efi_entry_lma	= ABSOLUTE ( efi_entry );
178
-    debugdir_lma	= ABSOLUTE ( debugdir );
179
-    codeview_rsds_lma	= ABSOLUTE ( codeview_rsds );
180
-}

+ 1
- 0
src/arch/x86/Makefile View File

@@ -6,3 +6,4 @@ CFLAGS		+= -Iarch/x86/include
6 6
 #
7 7
 SRCDIRS		+= arch/x86/core
8 8
 SRCDIRS 	+= arch/x86/interface/efi
9
+SRCDIRS 	+= arch/x86/prefix

+ 39
- 0
src/arch/x86/prefix/efiprefix.c View File

@@ -0,0 +1,39 @@
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/efi/efi.h>
21
+
22
+/**
23
+ * EFI entry point
24
+ *
25
+ * @v image_handle	Image handle
26
+ * @v systab		System table
27
+ * @ret efirc		EFI return status code
28
+ */
29
+EFI_STATUS EFIAPI _start ( EFI_HANDLE image_handle,
30
+			   EFI_SYSTEM_TABLE *systab ) {
31
+	EFI_STATUS efirc;
32
+
33
+	/* Initialise EFI environment */
34
+	if ( ( efirc = efi_init ( image_handle, systab ) ) != 0 )
35
+		return efirc;
36
+
37
+	/* Call to main() */
38
+	return RC_TO_EFIRC ( main () );
39
+}

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

@@ -0,0 +1,106 @@
1
+/* -*- sh -*- */
2
+
3
+/*
4
+ * Linker script for EFI images
5
+ *
6
+ */
7
+
8
+EXTERN ( _start )
9
+ENTRY ( _start )
10
+
11
+SECTIONS {
12
+
13
+    /* The file starts at a virtual address of zero, and sections are
14
+     * contiguous.  Each section is aligned to at least _max_align,
15
+     * which defaults to 32.  Load addresses are equal to virtual
16
+     * addresses.
17
+     */
18
+
19
+    _max_align = 32;
20
+
21
+    /* Allow plenty of space for file headers */
22
+    . = 0x1000;
23
+
24
+    /*
25
+     * The text section
26
+     *
27
+     */
28
+
29
+    . = ALIGN ( _max_align );
30
+    .text : {
31
+	_text = .;
32
+	*(.text)
33
+	*(.text.*)
34
+	_etext = .;
35
+    }
36
+
37
+    /*
38
+     * The rodata section
39
+     *
40
+     */
41
+
42
+    . = ALIGN ( _max_align );
43
+    .rodata : {
44
+	_rodata = .;
45
+	*(.rodata)
46
+	*(.rodata.*)
47
+	_erodata = .;
48
+    }
49
+
50
+    /*
51
+     * The data section
52
+     *
53
+     */
54
+
55
+    . = ALIGN ( _max_align );
56
+    .data : {
57
+	_data = .;
58
+	*(.data)
59
+	*(.data.*)
60
+	*(SORT(.tbl.*))		/* Various tables.  See include/tables.h */
61
+	_edata = .;
62
+    }
63
+
64
+    /*
65
+     * The bss section
66
+     *
67
+     */
68
+
69
+    . = ALIGN ( _max_align );
70
+    .bss : {
71
+	_bss = .;
72
+	*(.bss)
73
+	*(.bss.*)
74
+	*(COMMON)
75
+	_ebss = .;
76
+    }
77
+
78
+    /*
79
+     * Weak symbols that need zero values if not otherwise defined
80
+     *
81
+     */
82
+
83
+    .weak 0x0 : {
84
+	_weak = .;
85
+	*(.weak)
86
+	_eweak = .;
87
+    }
88
+    _assert = ASSERT ( ( _weak == _eweak ), ".weak is non-zero length" );
89
+
90
+    /*
91
+     * Dispose of the comment and note sections to make the link map
92
+     * easier to read
93
+     *
94
+     */
95
+
96
+    /DISCARD/ : {
97
+	*(.comment)
98
+	*(.comment.*)
99
+	*(.note)
100
+	*(.note.*)
101
+	*(.eh_frame)
102
+	*(.eh_frame.*)
103
+	*(.rel)
104
+	*(.rel.*)
105
+    }
106
+}

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

@@ -6,11 +6,11 @@ CFLAGS		+= -mno-red-zone
6 6
 
7 7
 # The EFI linker script
8 8
 #
9
-LDSCRIPT	= arch/x86_64/scripts/efi.lds
9
+LDSCRIPT	= arch/x86/scripts/efi.lds
10 10
 
11
-# Use a relocatable link; we perform final relocations in the efilink utility.
11
+# Retain relocation information for elf2efi
12 12
 #
13
-LDFLAGS		+= -r -d -S
13
+LDFLAGS		+= -q -S
14 14
 
15 15
 # Media types.
16 16
 #
@@ -18,12 +18,6 @@ NON_AUTO_MEDIA	+= efi
18 18
 
19 19
 # Rule for building EFI files
20 20
 #
21
-$(BIN)/%.efi.tmp-reloc : $(BIN)/%.efi.tmp $(EFILINK)
22
-	$(QM)$(ECHO) "  [EFILINK] $@"
23
-	$(Q)# Check for unresolved symbols
24
-	$(Q)$(LD) -e 0 --no-warn-mismatch -o /dev/null $<
25
-	$(Q)$(EFILINK) $< $@
26
-
27
-$(BIN)/%.efi : $(BIN)/%.efi.tmp-reloc
21
+$(BIN)/%.efi : $(BIN)/%.efi.tmp $(ELF2EFI64)
28 22
 	$(QM)$(ECHO) "  [FINISH] $@"
29
-	$(Q)$(OBJCOPY) -Obinary $< $@
23
+	$(Q)$(ELF2EFI64) $< $@

+ 0
- 174
src/arch/x86_64/prefix/efiprefix.S View File

@@ -1,174 +0,0 @@
1
-	.text
2
-	.code32
3
-	.arch i386
4
-	.section ".prefix", "a", @progbits
5
-	.org 0x00
6
-
7
-	/* DOS (.com) header
8
-	 *
9
-	 * EFI executables seem to leave most of this empty
10
-	 */
11
-mzhdr:
12
-	.ascii	"MZ"		/* Magic number */
13
-	.word	0		/* Bytes on last page of file */
14
-	.word	0		/* Pages in file */
15
-	.word	0		/* Relocations */
16
-	.word	0		/* Size of header in paragraphs */
17
-	.word	0		/* Minimum extra paragraphs needed */
18
-	.word	0		/* Maximum extra paragraphs needed */
19
-	.word	0		/* Initial (relative) SS value */
20
-	.word	0		/* Initial SP value */
21
-	.word	0		/* "Checksum" */
22
-	.word	0		/* Initial IP value */
23
-	.word	0		/* Initial (relative) CS value */
24
-	.word	0		/* File address of relocation table */
25
-	.word	0		/* Ovesrlay number */
26
-	.word	0, 0, 0, 0	/* Reserved words */
27
-	.word	0		/* OEM identifier (for e_oeminfo) */
28
-	.word	0		/* OEM information; e_oemid specific */
29
-	.word	0, 0, 0, 0, 0	/* Reserved words */
30
-	.word	0, 0, 0, 0, 0	/* Reserved words */
31
-	.long	pehdr_lma	/* File address of new exe header */
32
-	.size	mzhdr, . - mzhdr
33
-
34
-	/* PE header */
35
-	.org	0xc0 /* For compatibility with MS toolchain */
36
-pehdr:
37
-	.ascii	"PE\0\0"	/* Magic number */
38
-	.word	0x8664		/* CPU architecture: x86_64 */
39
-	.word	num_pe_sections	/* Number of sections */
40
-	.long	0x10d1a884	/* Timestamp */
41
-	.long	0		/* Symbol table */
42
-	.long	0		/* Number of symbols */
43
-	.word	opthdr_size	/* Size of optional header */
44
-	.word	0x2002		/* Characteristics */
45
-	.size	pehdr, . - pehdr
46
-	.equ	pehdr_lma, pehdr - mzhdr
47
-
48
-	/* "Optional" header */
49
-opthdr:
50
-	.word	0x020b		/* Magic number */
51
-	.byte	0		/* Linker major version number */
52
-	.byte	0		/* Linker minor version number */
53
-	.long	_text_filesz	/* Size of text section */
54
-	.long	_data_filesz	/* Size of data section */
55
-	.long	_bss_filesz	/* Size of bss section */
56
-	.long	efi_entry_lma	/* Entry point */
57
-	.long	_text_lma	/* Text section start RVA */
58
-	.quad	0		/* Image base address */
59
-	.long	_max_align	/* Section alignment */
60
-	.long	_max_align	/* File alignment */
61
-	.word	0		/* Operating system major version number */
62
-	.word	0		/* Operating system minor version number */
63
-	.word	0		/* Image major version number */
64
-	.word	0		/* Image minor version number */
65
-	.word	0		/* Subsystem major version number */
66
-	.word	0		/* Subsystem minor version number */
67
-	.long	0		/* Reserved */
68
-	.long	_filesz		/* Total image size */
69
-	.long	_prefix_filesz	/* Total header size */
70
-	.long	0		/* "Checksum" */
71
-	.word	0x0a		/* Subsystem: EFI */
72
-	.word	0		/* DLL characteristics */
73
-	.quad	0		/* Size of stack reserve */
74
-	.quad	0		/* Size of stack commit */
75
-	.quad	0		/* Size of heap reserve */
76
-	.quad	0		/* Size of heap commit */
77
-	.long	0		/* Loader flags */
78
-	.long	16		/* Number of data directory entries */
79
-	.long	0, 0		/* Export directory */
80
-	.long	0, 0		/* Import directory */
81
-	.long	0, 0		/* Resource directory */
82
-	.long	0, 0		/* Exception directory */
83
-	.long	0, 0		/* Security directory */
84
-	.long	_reloc_lma, _reloc_filesz /* Base relocation directory */
85
-	.long	debugdir_lma, debugdir_size /* Debug directory */
86
-	.long	0, 0		/* Description directory */
87
-	.long	0, 0		/* Special directory */
88
-	.long	0, 0		/* Thread storage directory */
89
-	.long	0, 0		/* Load configuration directory */
90
-	.long	0, 0		/* Bound import directory */
91
-	.long	0, 0		/* Import address table directory */
92
-	.long	0, 0		/* Delay import directory */
93
-	.long	0, 0		/* Reserved */
94
-	.long	0, 0		/* Reserved */
95
-	.size	opthdr, . - opthdr
96
-	.equ	opthdr_size, . - opthdr
97
-
98
-	/* PE sections */
99
-pe_sections:
100
-text_section:
101
-	.asciz	".text"		/* Section name */
102
-	.align	8
103
-	.long	_text_filesz	/* Section size */
104
-	.long	_text_lma	/* Relative Virtual Address */
105
-	.long	_text_filesz	/* Section size (rounded up) */
106
-	.long	_text_lma	/* Pointer to raw data */
107
-	.long	0		/* Link-time relocations */
108
-	.long	0		/* Line numbers */
109
-	.word	0		/* Number of link-time relocations */
110
-	.word	0		/* Number of line numbers */
111
-	.long	0x68000020	/* Characteristics */
112
-rodata_section:
113
-	.asciz	".rodata"	/* Section name */
114
-	.align	8
115
-	.long	_rodata_filesz	/* Section size */
116
-	.long	_rodata_lma	/* Relative Virtual Address */
117
-	.long	_rodata_filesz	/* Section size (rounded up) */
118
-	.long	_rodata_lma	/* Pointer to raw data */
119
-	.long	0		/* Link-time relocations */
120
-	.long	0		/* Line numbers */
121
-	.word	0		/* Number of link-time relocations */
122
-	.word	0		/* Number of line numbers */
123
-	.long	0x48000040	/* Characteristics */
124
-data_section:
125
-	.asciz	".data"		/* Section name */
126
-	.align	8
127
-	.long	_data_filesz	/* Section size */
128
-	.long	_data_lma	/* Relative Virtual Address */
129
-	.long	_data_filesz	/* Section size (rounded up) */
130
-	.long	_data_lma	/* Pointer to raw data */
131
-	.long	0		/* Link-time relocations */
132
-	.long	0		/* Line numbers */
133
-	.word	0		/* Number of link-time relocations */
134
-	.word	0		/* Number of line numbers */
135
-	.long	0xc8000040	/* Characteristics */
136
-reloc_section:
137
-	.asciz	".reloc"	/* Section name */
138
-	.align	8
139
-	.long	_reloc_filesz	/* Section size */
140
-	.long	_reloc_lma	/* Relative Virtual Address */
141
-	.long	_reloc_filesz	/* Section size (rounded up) */
142
-	.long	_reloc_lma	/* Pointer to raw data */
143
-	.long	0		/* Link-time relocations */
144
-	.long	0		/* Line numbers */
145
-	.word	0		/* Number of link-time relocations */
146
-	.word	0		/* Number of line numbers */
147
-	.long	0x42000040	/* Characteristics */
148
-
149
-pe_sections_end:
150
-	.size	pe_sections, . - pe_sections
151
-	.equ	num_pe_sections, ( ( . - pe_sections ) / 0x28 )
152
-
153
-	/* Debug directory */
154
-	.section ".rodata"
155
-	.globl	debugdir
156
-debugdir:
157
-	.long	0		/* Characteristics */
158
-	.long	0x10d1a884	/* Timestamp */
159
-	.word	0		/* Major version */
160
-	.word	0		/* Minor version */
161
-	.long	0x02		/* RSDS? */
162
-	.long	codeview_rsds_size /* Size of data */
163
-	.long	codeview_rsds_lma /* RVA */
164
-	.long	codeview_rsds_lma /* File offset */
165
-	.size	debugdir, . - debugdir
166
-	.equ	debugdir_size, . - debugdir
167
-	/* Codeview structure */
168
-	.globl	codeview_rsds
169
-codeview_rsds:
170
-	.ascii	"RSDS"		/* Magic number */
171
-	.long	0, 0, 0, 0, 0	/* Unused by EFI */
172
-	.asciz	"efiprefix.pdb"
173
-	.size	codeview_rsds, . - codeview_rsds
174
-	.equ	codeview_rsds_size, . - codeview_rsds

+ 0
- 180
src/arch/x86_64/scripts/efi.lds View File

@@ -1,180 +0,0 @@
1
-/* -*- sh -*- */
2
-
3
-/*
4
- * Linker script for EFI images
5
- *
6
- */
7
-
8
-EXTERN ( efi_entry )
9
-
10
-SECTIONS {
11
-
12
-    /* The file starts at a virtual address of zero, and sections are
13
-     * contiguous.  Each section is aligned to at least _max_align,
14
-     * which defaults to 32.  Load addresses are equal to virtual
15
-     * addresses.
16
-     */
17
-
18
-    . = 0;
19
-    _max_align = 32;
20
-
21
-    /*
22
-     * The prefix
23
-     *
24
-     */
25
-
26
-    .prefix : {
27
-	_prefix = .;
28
-	*(.prefix)
29
-	*(.prefix.*)
30
-	_mprefix = .;
31
-    } .bss.prefix (NOLOAD) : {
32
-	_eprefix = .;
33
-    }
34
-    _prefix_filesz	= ABSOLUTE ( _mprefix - _prefix );
35
-    _prefix_memsz	= ABSOLUTE ( _eprefix - _prefix );
36
-
37
-    /*
38
-     * The text section
39
-     *
40
-     */
41
-
42
-    . = ALIGN ( _max_align );
43
-    .text : {
44
-	_text = .;
45
-	*(.text)
46
-	*(.text.*)
47
-	_mtext = .;
48
-    } .bss.text (NOLOAD) : {
49
-	_etext = .;
50
-    }
51
-    _text_filesz	= ABSOLUTE ( _mtext - _text );
52
-    _text_memsz		= ABSOLUTE ( _etext - _text );
53
-
54
-    /*
55
-     * The rodata section
56
-     *
57
-     */
58
-
59
-    . = ALIGN ( _max_align );
60
-    .rodata : {
61
-	_rodata = .;
62
-	*(.rodata)
63
-	*(.rodata.*)
64
-	_mrodata = .;
65
-    } .bss.rodata (NOLOAD) : {
66
-	_erodata = .;
67
-    }
68
-    _rodata_filesz	= ABSOLUTE ( _mrodata - _rodata );
69
-    _rodata_memsz	= ABSOLUTE ( _erodata - _rodata );
70
-
71
-    /*
72
-     * The data section
73
-     *
74
-     */
75
-
76
-    . = ALIGN ( _max_align );
77
-    .data : {
78
-	_data = .;
79
-	*(.data)
80
-	*(.data.*)
81
-	*(SORT(.tbl.*))		/* Various tables.  See include/tables.h */
82
-	/* EFI seems to not support proper bss sections */
83
-	*(.bss)
84
-	*(.bss.*)
85
-	*(COMMON)
86
-	*(.stack)
87
-	*(.stack.*)
88
-	_mdata = .;
89
-    } .bss.data (NOLOAD) : {
90
-	_edata = .;
91
-    }
92
-    _data_filesz	= ABSOLUTE ( _mdata - _data );
93
-    _data_memsz		= ABSOLUTE ( _edata - _data );
94
-
95
-    /*
96
-     * The bss section
97
-     *
98
-     */
99
-
100
-    . = ALIGN ( _max_align );
101
-    .bss : {
102
-	_bss = .;
103
-	/* EFI seems to not support proper bss sections */
104
-	_mbss = .;
105
-    } .bss.bss (NOLOAD) : {
106
-	_ebss = .;
107
-    }
108
-    _bss_filesz		= ABSOLUTE ( _mbss - _bss );
109
-    _bss_memsz		= ABSOLUTE ( _ebss - _bss );
110
-
111
-    /*
112
-     * The reloc section
113
-     *
114
-     */
115
-
116
-    . = ALIGN ( _max_align );
117
-    .reloc : {
118
-	_reloc = .;
119
-	/* Provide some dummy contents to force ld to include this
120
-	 * section.  It will be created by the efilink utility.
121
-	 */
122
-	BYTE(0);
123
-	_mreloc = .;
124
-    } .bss.reloc (NOLOAD) : {
125
-	_ereloc = .;
126
-    }
127
-    _reloc_filesz	= ABSOLUTE ( _mreloc - _reloc );
128
-    _reloc_memsz	= ABSOLUTE ( _ereloc - _reloc );
129
-
130
-    _filesz		= ABSOLUTE ( . );
131
-
132
-    /*
133
-     * Weak symbols that need zero values if not otherwise defined
134
-     *
135
-     */
136
-
137
-    .weak 0x0 : {
138
-	_weak = .;
139
-	*(.weak)
140
-	_eweak = .;
141
-    }
142
-    _assert = ASSERT ( ( _weak == _eweak ), ".weak is non-zero length" );
143
-
144
-    /*
145
-     * Dispose of the comment and note sections to make the link map
146
-     * easier to read
147
-     *
148
-     */
149
-
150
-    /DISCARD/ : {
151
-	*(.comment)
152
-	*(.comment.*)
153
-	*(.note)
154
-	*(.note.*)
155
-	*(.eh_frame)
156
-	*(.eh_frame.*)
157
-	*(.rel)
158
-	*(.rel.*)
159
-    }
160
-
161
-    /*
162
-     * Load address calculations.
163
-     *
164
-     */
165
-
166
-    _prefix_lma		= ABSOLUTE ( _prefix );
167
-    _text_lma		= ABSOLUTE ( _text );
168
-    _rodata_lma		= ABSOLUTE ( _rodata );
169
-    _data_lma		= ABSOLUTE ( _data );
170
-    _bss_lma		= ABSOLUTE ( _bss );
171
-    _reloc_lma		= ABSOLUTE ( _reloc );
172
-
173
-    /*
174
-     * Load addresses required by the prefix
175
-     *
176
-     */
177
-    efi_entry_lma	= ABSOLUTE ( efi_entry );
178
-    debugdir_lma	= ABSOLUTE ( debugdir );
179
-    codeview_rsds_lma	= ABSOLUTE ( codeview_rsds );
180
-}

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

@@ -124,5 +124,7 @@ extern EFI_HANDLE efi_image_handle;
124 124
 extern EFI_SYSTEM_TABLE *efi_systab;
125 125
 
126 126
 extern const char * efi_strerror ( EFI_STATUS efirc );
127
+extern EFI_STATUS efi_init ( EFI_HANDLE image_handle,
128
+			     EFI_SYSTEM_TABLE *systab );
127 129
 
128 130
 #endif /* _EFI_H */

src/interface/efi/efi_entry.c → src/interface/efi/efi_init.c View File

@@ -16,7 +16,6 @@
16 16
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 17
  */
18 18
 
19
-#include <stdlib.h>
20 19
 #include <string.h>
21 20
 #include <gpxe/efi/efi.h>
22 21
 #include <gpxe/uuid.h>
@@ -58,14 +57,14 @@ static void * efi_find_table ( EFI_GUID *guid ) {
58 57
 }
59 58
 
60 59
 /**
61
- * EFI entry point
60
+ * Initialise EFI environment
62 61
  *
63 62
  * @v image_handle	Image handle
64 63
  * @v systab		System table
65 64
  * @ret efirc		EFI return status code
66 65
  */
67
-EFI_STATUS EFIAPI efi_entry ( EFI_HANDLE image_handle,
68
-			      EFI_SYSTEM_TABLE *systab ) {
66
+EFI_STATUS efi_init ( EFI_HANDLE image_handle,
67
+		      EFI_SYSTEM_TABLE *systab ) {
69 68
 	EFI_BOOT_SERVICES *bs;
70 69
 	struct efi_protocol *prot;
71 70
 	struct efi_config_table *tab;
@@ -119,6 +118,5 @@ EFI_STATUS EFIAPI efi_entry ( EFI_HANDLE image_handle,
119 118
 		}
120 119
 	}
121 120
 
122
-	/* Call to main() */
123
-	return RC_TO_EFIRC ( main () );
121
+	return 0;
124 122
 }

+ 2
- 1
src/util/.gitignore View File

@@ -2,4 +2,5 @@ nrv2b
2 2
 zbin
3 3
 hijack
4 4
 prototester
5
-efilink
5
+elf2efi32
6
+elf2efi64

+ 0
- 515
src/util/efilink.c View File

@@ -1,515 +0,0 @@
1
-#include <stdint.h>
2
-#include <stdio.h>
3
-#include <stdlib.h>
4
-#include <string.h>
5
-#include <unistd.h>
6
-#include <errno.h>
7
-#include <bfd.h>
8
-
9
-struct bfd_file {
10
-	bfd *bfd;
11
-	asymbol **symtab;
12
-	long symcount;
13
-};
14
-
15
-struct pe_relocs {
16
-	struct pe_relocs *next;
17
-	unsigned long start_rva;
18
-	unsigned int used_relocs;
19
-	unsigned int total_relocs;
20
-	uint16_t *relocs;
21
-};
22
-
23
-/**
24
- * Allocate memory
25
- *
26
- * @v len		Length of memory to allocate
27
- * @ret ptr		Pointer to allocated memory
28
- */
29
-static void * xmalloc ( size_t len ) {
30
-	void *ptr;
31
-
32
-	ptr = malloc ( len );
33
-	if ( ! ptr ) {
34
-		fprintf ( stderr, "Could not allocate %zd bytes\n", len );
35
-		exit ( 1 );
36
-	}
37
-
38
-	return ptr;
39
-}
40
-
41
-/**
42
- * Generate entry in PE relocation table
43
- *
44
- * @v pe_reltab		PE relocation table
45
- * @v rva		RVA
46
- * @v size		Size of relocation entry
47
- */
48
-static void generate_pe_reloc ( struct pe_relocs **pe_reltab,
49
-				unsigned long rva, size_t size ) {
50
-	unsigned long start_rva;
51
-	uint16_t reloc;
52
-	struct pe_relocs *pe_rel;
53
-	uint16_t *relocs;
54
-
55
-	/* Construct */
56
-	start_rva = ( rva & ~0xfff );
57
-	reloc = ( rva & 0xfff );
58
-	switch ( size ) {
59
-	case 8:
60
-		reloc |= 0xa000;
61
-		break;
62
-	case 4:
63
-		reloc |= 0x3000;
64
-		break;
65
-	case 2:
66
-		reloc |= 0x2000;
67
-		break;
68
-	default:
69
-		fprintf ( stderr, "Unsupported relocation size %zd\n", size );
70
-		exit ( 1 );
71
-	}
72
-
73
-	/* Locate or create PE relocation table */
74
-	for ( pe_rel = *pe_reltab ; pe_rel ; pe_rel = pe_rel->next ) {
75
-		if ( pe_rel->start_rva == start_rva )
76
-			break;
77
-	}
78
-	if ( ! pe_rel ) {
79
-		pe_rel = xmalloc ( sizeof ( *pe_rel ) );
80
-		memset ( pe_rel, 0, sizeof ( *pe_rel ) );
81
-		pe_rel->next = *pe_reltab;
82
-		*pe_reltab = pe_rel;
83
-		pe_rel->start_rva = start_rva;
84
-	}
85
-
86
-	/* Expand relocation list if necessary */
87
-	if ( pe_rel->used_relocs < pe_rel->total_relocs ) {
88
-		relocs = pe_rel->relocs;
89
-	} else {
90
-		pe_rel->total_relocs = ( pe_rel->total_relocs ?
91
-					 ( pe_rel->total_relocs * 2 ) : 256 );
92
-		relocs = xmalloc ( pe_rel->total_relocs *
93
-				   sizeof ( pe_rel->relocs[0] ) );
94
-		memset ( relocs, 0,
95
-			 pe_rel->total_relocs * sizeof ( pe_rel->relocs[0] ) );
96
-		memcpy ( relocs, pe_rel->relocs,
97
-			 pe_rel->used_relocs * sizeof ( pe_rel->relocs[0] ) );
98
-		free ( pe_rel->relocs );
99
-		pe_rel->relocs = relocs;
100
-	}
101
-
102
-	/* Store relocation */
103
-	pe_rel->relocs[ pe_rel->used_relocs++ ] = reloc;
104
-}
105
-
106
-/**
107
- * Calculate size of binary PE relocation table
108
- *
109
- * @v pe_reltab		PE relocation table
110
- * @v buffer		Buffer to contain binary table, or NULL
111
- * @ret size		Size of binary table
112
- */
113
-static size_t output_pe_reltab ( struct pe_relocs *pe_reltab,
114
-				 void *buffer ) {
115
-	struct pe_relocs *pe_rel;
116
-	unsigned int num_relocs;
117
-	size_t size;
118
-	size_t total_size = 0;
119
-
120
-	for ( pe_rel = pe_reltab ; pe_rel ; pe_rel = pe_rel->next ) {
121
-		num_relocs = ( ( pe_rel->used_relocs + 1 ) & ~1 );
122
-		size = ( sizeof ( uint32_t ) /* VirtualAddress */ +
123
-			 sizeof ( uint32_t ) /* SizeOfBlock */ +
124
-			 ( num_relocs * sizeof ( uint16_t ) ) );
125
-		if ( buffer ) {
126
-			*( (uint32_t *) ( buffer + total_size + 0 ) )
127
-				= pe_rel->start_rva;
128
-			*( (uint32_t *) ( buffer + total_size + 4 ) ) = size;
129
-			memcpy ( ( buffer + total_size + 8 ), pe_rel->relocs,
130
-				 ( num_relocs * sizeof ( uint16_t ) ) );
131
-		}
132
-		total_size += size;
133
-	}
134
-
135
-	return total_size;
136
-}
137
-
138
-/**
139
- * Read symbol table
140
- *
141
- * @v bfd		BFD file
142
- */
143
-static void read_symtab ( struct bfd_file *bfd ) {
144
-	long symtab_size;
145
-
146
-	/* Get symbol table size */
147
-	symtab_size = bfd_get_symtab_upper_bound ( bfd->bfd );
148
-	if ( symtab_size < 0 ) {
149
-		bfd_perror ( "Could not get symbol table upper bound" );
150
-		exit ( 1 );
151
-	}
152
-
153
-	/* Allocate and read symbol table */
154
-	bfd->symtab = xmalloc ( symtab_size );
155
-	bfd->symcount = bfd_canonicalize_symtab ( bfd->bfd, bfd->symtab );
156
-	if ( bfd->symcount < 0 ) {
157
-		bfd_perror ( "Cannot read symbol table" );
158
-		exit ( 1 );
159
-	}
160
-}
161
-
162
-/**
163
- * Read relocation table
164
- *
165
- * @v bfd		BFD file
166
- * @v section		Section
167
- * @v symtab		Symbol table
168
- * @ret reltab		Relocation table
169
- */
170
-static arelent ** read_reltab ( struct bfd_file *bfd, asection *section ) {
171
-	long reltab_size;
172
-	arelent **reltab;
173
-	long numrels;
174
-
175
-	/* Get relocation table size */
176
-	reltab_size = bfd_get_reloc_upper_bound ( bfd->bfd, section );
177
-	if ( reltab_size < 0 ) {
178
-		bfd_perror ( "Could not get relocation table upper bound" );
179
-		exit ( 1 );
180
-	}
181
-
182
-	/* Allocate and read relocation table */
183
-	reltab = xmalloc ( reltab_size );
184
-	numrels = bfd_canonicalize_reloc ( bfd->bfd, section, reltab,
185
-					   bfd->symtab );
186
-	if ( numrels < 0 ) {
187
-		bfd_perror ( "Cannot read relocation table" );
188
-		exit ( 1 );
189
-	}
190
-
191
-	return reltab;
192
-}
193
-
194
-
195
-/**
196
- * Open input BFD file
197
- *
198
- * @v filename		File name
199
- * @ret ibfd		BFD file
200
- */
201
-static struct bfd_file * open_input_bfd ( const char *filename ) {
202
-	struct bfd_file *ibfd;
203
-
204
-	/* Create BFD file */
205
-	ibfd = xmalloc ( sizeof ( *ibfd ) );
206
-	memset ( ibfd, 0, sizeof ( *ibfd ) );
207
-
208
-	/* Open the file */
209
-	ibfd->bfd = bfd_openr ( filename, NULL );
210
-	if ( ! ibfd->bfd ) {
211
-		fprintf ( stderr, "Cannot open %s: ", filename );
212
-		bfd_perror ( NULL );
213
-		exit ( 1 );
214
-	}
215
-
216
-	/* The call to bfd_check_format() must be present, otherwise
217
-	 * we get a segfault from later BFD calls.
218
-	 */
219
-	if ( bfd_check_format ( ibfd->bfd, bfd_object ) < 0 ) {
220
-		fprintf ( stderr, "%s is not an object file\n", filename );
221
-		exit ( 1 );
222
-	}
223
-
224
-	/* Read symbols and relocation entries */
225
-	read_symtab ( ibfd );
226
-
227
-	return ibfd;
228
-}
229
-
230
-/**
231
- * Open output BFD file
232
- *
233
- * @v filename		File name
234
- * @v ibfd		Input BFD file
235
- * @ret obfd		BFD file
236
- */
237
-static struct bfd_file * open_output_bfd ( const char *filename,
238
-					   struct bfd_file *ibfd ) {
239
-	struct bfd_file *obfd;
240
-	asection *isection;
241
-	asection *osection;
242
-
243
-	/*
244
-	 * Most of this code is based on what objcopy.c does.
245
-	 *
246
-	 */
247
-
248
-	/* Create BFD file */
249
-	obfd = xmalloc ( sizeof ( *obfd ) );
250
-	memset ( obfd, 0, sizeof ( *obfd ) );
251
-
252
-	/* Open the file */
253
-	obfd->bfd = bfd_openw ( filename, ibfd->bfd->xvec->name );
254
-	if ( ! obfd->bfd ) {
255
-		fprintf ( stderr, "Cannot open %s: ", filename );
256
-		bfd_perror ( NULL );
257
-		exit ( 1 );
258
-	}
259
-
260
-	/* Copy per-file data */
261
-	if ( ! bfd_set_arch_mach ( obfd->bfd, bfd_get_arch ( ibfd->bfd ),
262
-				   bfd_get_mach ( ibfd->bfd ) ) ) {
263
-		bfd_perror ( "Cannot copy architecture" );
264
-		exit ( 1 );
265
-	}
266
-	if ( ! bfd_set_format ( obfd->bfd, bfd_get_format ( ibfd->bfd ) ) ) {
267
-		bfd_perror ( "Cannot copy format" );
268
-		exit ( 1 );
269
-	}
270
-	if ( ! bfd_copy_private_header_data ( ibfd->bfd, obfd->bfd ) ) {
271
-		bfd_perror ( "Cannot copy private header data" );
272
-		exit ( 1 );
273
-	}
274
-
275
-	/* Create sections */
276
-	for ( isection = ibfd->bfd->sections ; isection ;
277
-	      isection = isection->next ) {
278
-		osection = bfd_make_section_anyway ( obfd->bfd,
279
-						     isection->name );
280
-		if ( ! osection ) {
281
-			bfd_perror ( "Cannot create section" );
282
-			exit ( 1 );
283
-		}
284
-		if ( ! bfd_set_section_flags ( obfd->bfd, osection,
285
-					       isection->flags ) ) {
286
-			bfd_perror ( "Cannot copy section flags" );
287
-			exit ( 1 );
288
-		}
289
-		if ( ! bfd_set_section_size ( obfd->bfd, osection,
290
-				 bfd_section_size ( ibfd->bfd, isection ) ) ) {
291
-			bfd_perror ( "Cannot copy section size" );
292
-			exit ( 1 );
293
-		}
294
-		if ( ! bfd_set_section_vma ( obfd->bfd, osection,
295
-				  bfd_section_vma ( ibfd->bfd, isection ) ) ) {
296
-			bfd_perror ( "Cannot copy section VMA" );
297
-			exit ( 1 );
298
-		}
299
-		osection->lma = bfd_section_lma ( ibfd->bfd, isection );
300
-		if ( ! bfd_set_section_alignment ( obfd->bfd, osection,
301
-			    bfd_section_alignment ( ibfd->bfd, isection ) ) ) {
302
-			bfd_perror ( "Cannot copy section alignment" );
303
-			exit ( 1 );
304
-		}
305
-		osection->entsize = isection->entsize;
306
-		isection->output_section = osection;
307
-		isection->output_offset = 0;
308
-		if ( ! bfd_copy_private_section_data ( ibfd->bfd, isection,
309
-						       obfd->bfd, osection ) ){
310
-			bfd_perror ( "Cannot copy section private data" );
311
-			exit ( 1 );
312
-		}
313
-	}
314
-
315
-	/* Copy symbol table */
316
-	bfd_set_symtab ( obfd->bfd, ibfd->symtab, ibfd->symcount );
317
-	obfd->symtab = ibfd->symtab;
318
-
319
-	return obfd;
320
-}
321
-
322
-/**
323
- * Copy section from input BFD file to output BFD file
324
- *
325
- * @v obfd		Output BFD file
326
- * @v ibfd		Input BFD file
327
- * @v section		Section
328
- */
329
-static void copy_bfd_section ( struct bfd_file *obfd, struct bfd_file *ibfd,
330
-			       asection *isection ) {
331
-	size_t size;
332
-	void *buf;
333
-	arelent **reltab;
334
-	arelent **rel;
335
-	char *errmsg;
336
-
337
-	/* Read in original section */
338
-	size = bfd_section_size ( ibfd->bfd, isection );
339
-	if ( ! size )
340
-		return;
341
-	buf = xmalloc ( size );
342
-	if ( ( ! bfd_get_section_contents ( ibfd->bfd, isection,
343
-					    buf, 0, size ) ) ) {
344
-		fprintf ( stderr, "Cannot read section %s: ", isection->name );
345
-		bfd_perror ( NULL );
346
-		exit ( 1 );
347
-	}
348
-
349
-	/* Perform relocations.  We do this here, rather than letting
350
-	 * ld do it for us when creating the input ELF file, so that
351
-	 * we can change symbol values as a result of having created
352
-	 * the .reloc section.
353
-	 */
354
-	reltab = read_reltab ( ibfd, isection );
355
-	for ( rel = reltab ; *rel ; rel++ ) {
356
-		bfd_perform_relocation ( ibfd->bfd, *rel, buf, isection,
357
-					 NULL, &errmsg );
358
-	}
359
-	free ( reltab );
360
-
361
-	/* Write out modified section */
362
-	if ( ( ! bfd_set_section_contents ( obfd->bfd,
363
-					    isection->output_section,
364
-					    buf, 0, size ) ) ) {
365
-		fprintf ( stderr, "Cannot write section %s: ",
366
-			  isection->output_section->name );
367
-		bfd_perror ( NULL );
368
-		exit ( 1 );
369
-	}
370
-
371
-	free ( buf );
372
-}
373
-
374
-/**
375
- * Process relocation record
376
- *
377
- * @v section		Section
378
- * @v rel		Relocation entry
379
- * @v pe_reltab		PE relocation table to fill in
380
- */
381
-static void process_reloc ( asection *section, arelent *rel,
382
-			    struct pe_relocs **pe_reltab ) {
383
-	reloc_howto_type *howto = rel->howto;
384
-	asymbol *sym = *(rel->sym_ptr_ptr);
385
-	unsigned long offset = ( section->lma + rel->address );
386
-
387
-	if ( bfd_is_abs_section ( sym->section ) ) {
388
-		/* Skip absolute symbols; the symbol value won't
389
-		 * change when the object is loaded.
390
-		 */
391
-	} else if ( strcmp ( howto->name, "R_X86_64_64" ) == 0 ) {
392
-		/* Generate an 8-byte PE relocation */
393
-		generate_pe_reloc ( pe_reltab, offset, 8 );
394
-	} else if ( ( strcmp ( howto->name, "R_386_32" ) == 0 ) ||
395
-		    ( strcmp ( howto->name, "R_X86_64_32" ) == 0 ) ) {
396
-		/* Generate a 4-byte PE relocation */
397
-		generate_pe_reloc ( pe_reltab, offset, 4 );
398
-	} else if ( strcmp ( howto->name, "R_386_16" ) == 0 ) {
399
-		/* Generate a 2-byte PE relocation */
400
-		generate_pe_reloc ( pe_reltab, offset, 2 );
401
-	} else if ( ( strcmp ( howto->name, "R_386_PC32" ) == 0 ) ||
402
-		    ( strcmp ( howto->name, "R_X86_64_PC32" ) == 0 ) ) {
403
-		/* Skip PC-relative relocations; all relative offsets
404
-		 * remain unaltered when the object is loaded.
405
-		 */
406
-	} else {
407
-		fprintf ( stderr, "Unrecognised relocation type %s\n",
408
-			  howto->name );
409
-		exit ( 1 );
410
-	}
411
-}
412
-
413
-/**
414
- * Create .reloc section
415
- *
416
- * obfd			Output BFD file
417
- * section		.reloc section in output file
418
- * pe_reltab		PE relocation table
419
- */
420
-static void create_reloc_section ( struct bfd_file *obfd, asection *section,
421
-				   struct pe_relocs *pe_reltab ) {
422
-	size_t raw_size;
423
-	size_t size;
424
-	size_t old_size;
425
-	void *buf;
426
-	asymbol **sym;
427
-
428
-	/* Build binary PE relocation table */
429
-	raw_size = output_pe_reltab ( pe_reltab, NULL );
430
-	size = ( ( raw_size + 31 ) & ~31 );
431
-	buf = xmalloc ( size );
432
-	memset ( buf, 0, size );
433
-	output_pe_reltab ( pe_reltab, buf );
434
-
435
-	/* Write .reloc section */
436
-	old_size = bfd_section_size ( obfd->bfd, section );
437
-	if ( ! bfd_set_section_size ( obfd->bfd, section, size ) ) {
438
-		bfd_perror ( "Cannot resize .reloc section" );
439
-		exit ( 1 );
440
-	}
441
-	if ( ! bfd_set_section_contents ( obfd->bfd, section,
442
-					  buf, 0, size ) ) {
443
-		bfd_perror ( "Cannot set .reloc section contents" );
444
-		exit ( 1 );
445
-	}
446
-
447
-	/* Update symbols pertaining to the relocation directory */
448
-	for ( sym = obfd->symtab ; *sym ; sym++ ) {
449
-		if ( strcmp ( (*sym)->name, "_reloc_memsz" ) == 0 ) {
450
-			(*sym)->value = size;
451
-		} else if ( strcmp ( (*sym)->name, "_reloc_filesz" ) == 0 ){
452
-			(*sym)->value = raw_size;
453
-		} else if ( strcmp ( (*sym)->name, "_filesz" ) == 0 ) {
454
-			(*sym)->value += ( size - old_size );
455
-		}
456
-	}
457
-}
458
-
459
-int main ( int argc, const char *argv[] ) {
460
-	const char *iname;
461
-	const char *oname;
462
-	struct bfd_file *ibfd;
463
-	struct bfd_file *obfd;
464
-	asection *section;
465
-	arelent **reltab;
466
-	arelent **rel;
467
-	struct pe_relocs *pe_reltab = NULL;
468
-	asection *reloc_section;
469
-
470
-	/* Initialise libbfd */
471
-	bfd_init();
472
-
473
-	/* Identify intput and output files */
474
-	if ( argc != 3 ) {
475
-		fprintf ( stderr, "Syntax: %s infile outfile\n", argv[0] );
476
-		exit ( 1 );
477
-	}
478
-	iname = argv[1];
479
-	oname = argv[2];
480
-
481
-	/* Open BFD files */
482
-	ibfd = open_input_bfd ( iname );
483
-	obfd = open_output_bfd ( oname, ibfd );
484
-
485
-	/* Process relocations in all sections */
486
-	for ( section = ibfd->bfd->sections ; section ;
487
-	      section = section->next ) {
488
-		reltab = read_reltab ( ibfd, section );
489
-		for ( rel = reltab ; *rel ; rel++ ) {
490
-			process_reloc ( section, *rel, &pe_reltab );
491
-		}
492
-		free ( reltab );
493
-	}
494
-
495
-	/* Create modified .reloc section */
496
-	reloc_section = bfd_get_section_by_name ( obfd->bfd, ".reloc" );
497
-	if ( ! reloc_section ) {
498
-		fprintf ( stderr, "Cannot find .reloc section\n" );
499
-		exit ( 1 );
500
-	}
501
-	create_reloc_section ( obfd, reloc_section, pe_reltab );
502
-
503
-	/* Copy other section contents */
504
-	for ( section = ibfd->bfd->sections ; section ;
505
-	      section = section->next ) {
506
-		if ( section->output_section != reloc_section )
507
-			copy_bfd_section ( obfd, ibfd, section );
508
-	}
509
-
510
-	/* Write out files and clean up */
511
-	bfd_close ( obfd->bfd );
512
-	bfd_close ( ibfd->bfd );
513
-
514
-	return 0;
515
-}

+ 764
- 0
src/util/elf2efi.c View File

@@ -0,0 +1,764 @@
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
+#define _GNU_SOURCE
20
+#include <stdint.h>
21
+#include <stddef.h>
22
+#include <stdlib.h>
23
+#include <stdio.h>
24
+#include <string.h>
25
+#include <unistd.h>
26
+#include <errno.h>
27
+#include <assert.h>
28
+#include <bfd.h>
29
+
30
+/* Include the EFI PE image header file */
31
+typedef uint8_t UINT8;
32
+typedef uint16_t UINT16;
33
+typedef uint32_t UINT32;
34
+typedef uint64_t UINT64;
35
+#define SIGNATURE_16( a, b ) ( (a) | ( (b) << 8 ) )
36
+#define SIGNATURE_32( a, b, c, d ) \
37
+	( (a) | ( (b) << 8 ) | ( (c) << 16 ) | ( (d) << 24 ) )
38
+#define  BIT0     0x00000001
39
+#define  BIT1     0x00000002
40
+#define  BIT2     0x00000004
41
+#define  BIT3     0x00000008
42
+#define  BIT4     0x00000010
43
+#define  BIT5     0x00000020
44
+#define  BIT6     0x00000040
45
+#define  BIT7     0x00000080
46
+#define  BIT8     0x00000100
47
+#define  BIT9     0x00000200
48
+#define  BIT10    0x00000400
49
+#define  BIT11    0x00000800
50
+#define  BIT12    0x00001000
51
+#define  BIT13    0x00002000
52
+#define  BIT14    0x00004000
53
+#define  BIT15    0x00008000
54
+#define  BIT16    0x00010000
55
+#define  BIT17    0x00020000
56
+#define  BIT18    0x00040000
57
+#define  BIT19    0x00080000
58
+#define  BIT20    0x00100000
59
+#define  BIT21    0x00200000
60
+#define  BIT22    0x00400000
61
+#define  BIT23    0x00800000
62
+#define  BIT24    0x01000000
63
+#define  BIT25    0x02000000
64
+#define  BIT26    0x04000000
65
+#define  BIT27    0x08000000
66
+#define  BIT28    0x10000000
67
+#define  BIT29    0x20000000
68
+#define  BIT30    0x40000000
69
+#define  BIT31    0x80000000
70
+#include "../include/gpxe/efi/IndustryStandard/PeImage.h"
71
+
72
+#define EFI_FILE_ALIGN 0x20
73
+
74
+struct pe_section {
75
+	struct pe_section *next;
76
+	EFI_IMAGE_SECTION_HEADER hdr;
77
+	uint8_t contents[0];
78
+};
79
+
80
+struct pe_relocs {
81
+	struct pe_relocs *next;
82
+	unsigned long start_rva;
83
+	unsigned int used_relocs;
84
+	unsigned int total_relocs;
85
+	uint16_t *relocs;
86
+};
87
+
88
+struct pe_header {
89
+	EFI_IMAGE_DOS_HEADER dos;
90
+	uint8_t padding[128];
91
+#if defined(MDE_CPU_IA32)
92
+	EFI_IMAGE_NT_HEADERS32 nt;
93
+#elif defined(MDE_CPU_X64)
94
+	EFI_IMAGE_NT_HEADERS64 nt;
95
+#endif
96
+};
97
+
98
+static struct pe_header efi_pe_header = {
99
+	.dos = {
100
+		.e_magic = EFI_IMAGE_DOS_SIGNATURE,
101
+		.e_lfanew = offsetof ( typeof ( efi_pe_header ), nt ),
102
+	},
103
+	.nt = {
104
+		.Signature = EFI_IMAGE_NT_SIGNATURE,
105
+		.FileHeader = {
106
+#if defined(MDE_CPU_IA32)
107
+			.Machine = EFI_IMAGE_MACHINE_IA32,
108
+#elif defined(MDE_CPU_X64)
109
+			.Machine = EFI_IMAGE_MACHINE_X64,
110
+#endif
111
+			.TimeDateStamp = 0x10d1a884,
112
+			.SizeOfOptionalHeader =
113
+				sizeof ( efi_pe_header.nt.OptionalHeader ),
114
+			.Characteristics = ( EFI_IMAGE_FILE_DLL |
115
+#if defined(MDE_CPU_IA32)
116
+					     EFI_IMAGE_FILE_32BIT_MACHINE |
117
+#endif
118
+					     EFI_IMAGE_FILE_EXECUTABLE_IMAGE ),
119
+		},
120
+		.OptionalHeader = {
121
+#if defined(MDE_CPU_IA32)
122
+			.Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC,
123
+#elif defined(MDE_CPU_X64)
124
+			.Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC,
125
+#endif
126
+			.SectionAlignment = EFI_FILE_ALIGN,
127
+			.FileAlignment = EFI_FILE_ALIGN,
128
+			.SizeOfImage = sizeof ( efi_pe_header ),
129
+			.SizeOfHeaders = sizeof ( efi_pe_header ),
130
+			.Subsystem = EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION,
131
+			.NumberOfRvaAndSizes =
132
+				EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES,
133
+		},
134
+	},
135
+};
136
+
137
+/**
138
+ * Allocate memory
139
+ *
140
+ * @v len		Length of memory to allocate
141
+ * @ret ptr		Pointer to allocated memory
142
+ */
143
+static void * xmalloc ( size_t len ) {
144
+	void *ptr;
145
+
146
+	ptr = malloc ( len );
147
+	if ( ! ptr ) {
148
+		fprintf ( stderr, "Could not allocate %zd bytes\n", len );
149
+		exit ( 1 );
150
+	}
151
+
152
+	return ptr;
153
+}
154
+
155
+/**
156
+ * Align section within PE file
157
+ *
158
+ * @v offset		Unaligned offset
159
+ * @ret aligned_offset	Aligned offset
160
+ */
161
+static unsigned long efi_file_align ( unsigned long offset ) {
162
+	return ( ( offset + EFI_FILE_ALIGN - 1 ) & ~( EFI_FILE_ALIGN - 1 ) );
163
+}
164
+
165
+/**
166
+ * Generate entry in PE relocation table
167
+ *
168
+ * @v pe_reltab		PE relocation table
169
+ * @v rva		RVA
170
+ * @v size		Size of relocation entry
171
+ */
172
+static void generate_pe_reloc ( struct pe_relocs **pe_reltab,
173
+				unsigned long rva, size_t size ) {
174
+	unsigned long start_rva;
175
+	uint16_t reloc;
176
+	struct pe_relocs *pe_rel;
177
+	uint16_t *relocs;
178
+
179
+	/* Construct */
180
+	start_rva = ( rva & ~0xfff );
181
+	reloc = ( rva & 0xfff );
182
+	switch ( size ) {
183
+	case 8:
184
+		reloc |= 0xa000;
185
+		break;
186
+	case 4:
187
+		reloc |= 0x3000;
188
+		break;
189
+	case 2:
190
+		reloc |= 0x2000;
191
+		break;
192
+	default:
193
+		fprintf ( stderr, "Unsupported relocation size %zd\n", size );
194
+		exit ( 1 );
195
+	}
196
+
197
+	/* Locate or create PE relocation table */
198
+	for ( pe_rel = *pe_reltab ; pe_rel ; pe_rel = pe_rel->next ) {
199
+		if ( pe_rel->start_rva == start_rva )
200
+			break;
201
+	}
202
+	if ( ! pe_rel ) {
203
+		pe_rel = xmalloc ( sizeof ( *pe_rel ) );
204
+		memset ( pe_rel, 0, sizeof ( *pe_rel ) );
205
+		pe_rel->next = *pe_reltab;
206
+		*pe_reltab = pe_rel;
207
+		pe_rel->start_rva = start_rva;
208
+	}
209
+
210
+	/* Expand relocation list if necessary */
211
+	if ( pe_rel->used_relocs < pe_rel->total_relocs ) {
212
+		relocs = pe_rel->relocs;
213
+	} else {
214
+		pe_rel->total_relocs = ( pe_rel->total_relocs ?
215
+					 ( pe_rel->total_relocs * 2 ) : 256 );
216
+		relocs = xmalloc ( pe_rel->total_relocs *
217
+				   sizeof ( pe_rel->relocs[0] ) );
218
+		memset ( relocs, 0,
219
+			 pe_rel->total_relocs * sizeof ( pe_rel->relocs[0] ) );
220
+		memcpy ( relocs, pe_rel->relocs,
221
+			 pe_rel->used_relocs * sizeof ( pe_rel->relocs[0] ) );
222
+		free ( pe_rel->relocs );
223
+		pe_rel->relocs = relocs;
224
+	}
225
+
226
+	/* Store relocation */
227
+	pe_rel->relocs[ pe_rel->used_relocs++ ] = reloc;
228
+}
229
+
230
+/**
231
+ * Calculate size of binary PE relocation table
232
+ *
233
+ * @v pe_reltab		PE relocation table
234
+ * @v buffer		Buffer to contain binary table, or NULL
235
+ * @ret size		Size of binary table
236
+ */
237
+static size_t output_pe_reltab ( struct pe_relocs *pe_reltab,
238
+				 void *buffer ) {
239
+	struct pe_relocs *pe_rel;
240
+	unsigned int num_relocs;
241
+	size_t size;
242
+	size_t total_size = 0;
243
+
244
+	for ( pe_rel = pe_reltab ; pe_rel ; pe_rel = pe_rel->next ) {
245
+		num_relocs = ( ( pe_rel->used_relocs + 1 ) & ~1 );
246
+		size = ( sizeof ( uint32_t ) /* VirtualAddress */ +
247
+			 sizeof ( uint32_t ) /* SizeOfBlock */ +
248
+			 ( num_relocs * sizeof ( uint16_t ) ) );
249
+		if ( buffer ) {
250
+			*( (uint32_t *) ( buffer + total_size + 0 ) )
251
+				= pe_rel->start_rva;
252
+			*( (uint32_t *) ( buffer + total_size + 4 ) ) = size;
253
+			memcpy ( ( buffer + total_size + 8 ), pe_rel->relocs,
254
+				 ( num_relocs * sizeof ( uint16_t ) ) );
255
+		}
256
+		total_size += size;
257
+	}
258
+
259
+	return total_size;
260
+}
261
+
262
+/**
263
+ * Open input BFD file
264
+ *
265
+ * @v filename		File name
266
+ * @ret ibfd		BFD file
267
+ */
268
+static bfd * open_input_bfd ( const char *filename ) {
269
+	bfd *bfd;
270
+
271
+	/* Open the file */
272
+	bfd = bfd_openr ( filename, NULL );
273
+	if ( ! bfd ) {
274
+		fprintf ( stderr, "Cannot open %s: ", filename );
275
+		bfd_perror ( NULL );
276
+		exit ( 1 );
277
+	}
278
+
279
+	/* The call to bfd_check_format() must be present, otherwise
280
+	 * we get a segfault from later BFD calls.
281
+	 */
282
+	if ( bfd_check_format ( bfd, bfd_object ) < 0 ) {
283
+		fprintf ( stderr, "%s is not an object file\n", filename );
284
+		exit ( 1 );
285
+	}
286
+
287
+	return bfd;
288
+}
289
+
290
+/**
291
+ * Read symbol table
292
+ *
293
+ * @v bfd		BFD file
294
+ */
295
+static asymbol ** read_symtab ( bfd *bfd ) {
296
+	long symtab_size;
297
+	asymbol **symtab;
298
+	long symcount;
299
+
300
+	/* Get symbol table size */
301
+	symtab_size = bfd_get_symtab_upper_bound ( bfd );
302
+	if ( symtab_size < 0 ) {
303
+		bfd_perror ( "Could not get symbol table upper bound" );
304
+		exit ( 1 );
305
+	}
306
+
307
+	/* Allocate and read symbol table */
308
+	symtab = xmalloc ( symtab_size );
309
+	symcount = bfd_canonicalize_symtab ( bfd, symtab );
310
+	if ( symcount < 0 ) {
311
+		bfd_perror ( "Cannot read symbol table" );
312
+		exit ( 1 );
313
+	}
314
+
315
+	return symtab;
316
+}
317
+
318
+/**
319
+ * Read relocation table
320
+ *
321
+ * @v bfd		BFD file
322
+ * @v symtab		Symbol table
323
+ * @v section		Section
324
+ * @v symtab		Symbol table
325
+ * @ret reltab		Relocation table
326
+ */
327
+static arelent ** read_reltab ( bfd *bfd, asymbol **symtab,
328
+				asection *section ) {
329
+	long reltab_size;
330
+	arelent **reltab;
331
+	long numrels;
332
+
333
+	/* Get relocation table size */
334
+	reltab_size = bfd_get_reloc_upper_bound ( bfd, section );
335
+	if ( reltab_size < 0 ) {
336
+		bfd_perror ( "Could not get relocation table upper bound" );
337
+		exit ( 1 );
338
+	}
339
+
340
+	/* Allocate and read relocation table */
341
+	reltab = xmalloc ( reltab_size );
342
+	numrels = bfd_canonicalize_reloc ( bfd, section, reltab, symtab );
343
+	if ( numrels < 0 ) {
344
+		bfd_perror ( "Cannot read relocation table" );
345
+		exit ( 1 );
346
+	}
347
+
348
+	return reltab;
349
+}
350
+
351
+/**
352
+ * Process section
353
+ *
354
+ * @v bfd		BFD file
355
+ * @v pe_header		PE file header
356
+ * @v section		Section
357
+ * @ret new		New PE section
358
+ */
359
+static struct pe_section * process_section ( bfd *bfd,
360
+					     struct pe_header *pe_header,
361
+					     asection *section ) {
362
+	struct pe_section *new;
363
+	size_t section_memsz;
364
+	size_t section_filesz;
365
+	unsigned long flags = bfd_get_section_flags ( bfd, section );
366
+	unsigned long code_start;
367
+	unsigned long code_end;
368
+	unsigned long data_start;
369
+	unsigned long data_mid;
370
+	unsigned long data_end;
371
+	unsigned long start;
372
+	unsigned long end;
373
+	unsigned long *applicable_start;
374
+	unsigned long *applicable_end;
375
+
376
+	/* Extract current RVA limits from file header */
377
+	code_start = pe_header->nt.OptionalHeader.BaseOfCode;
378
+	code_end = ( code_start + pe_header->nt.OptionalHeader.SizeOfCode );
379
+#if defined(MDE_CPU_IA32)
380
+	data_start = pe_header->nt.OptionalHeader.BaseOfData;
381
+#elif defined(MDE_CPU_X64)
382
+	data_start = code_end;
383
+#endif
384
+	data_mid = ( data_start +
385
+		     pe_header->nt.OptionalHeader.SizeOfInitializedData );
386
+	data_end = ( data_mid +
387
+		     pe_header->nt.OptionalHeader.SizeOfUninitializedData );
388
+
389
+	/* Allocate PE section */
390
+	section_memsz = bfd_section_size ( bfd, section );
391
+	section_filesz = ( ( flags & SEC_LOAD ) ?
392
+			   efi_file_align ( section_memsz ) : 0 );
393
+	new = xmalloc ( sizeof ( *new ) + section_filesz );
394
+	memset ( new, 0, sizeof ( *new ) + section_filesz );
395
+
396
+	/* Fill in section header details */
397
+	strncpy ( ( char * ) new->hdr.Name, section->name,
398
+		  sizeof ( new->hdr.Name ) );
399
+	new->hdr.Misc.VirtualSize = section_memsz;
400
+	new->hdr.VirtualAddress = bfd_get_section_vma ( bfd, section );
401
+	new->hdr.SizeOfRawData = section_filesz;
402
+
403
+	/* Fill in section characteristics and update RVA limits */
404
+	if ( flags & SEC_CODE ) {
405
+		/* .text-type section */
406
+		new->hdr.Characteristics =
407
+			( EFI_IMAGE_SCN_CNT_CODE |
408
+			  EFI_IMAGE_SCN_MEM_NOT_PAGED |
409
+			  EFI_IMAGE_SCN_MEM_EXECUTE |
410
+			  EFI_IMAGE_SCN_MEM_READ );
411
+		applicable_start = &code_start;
412
+		applicable_end = &code_end;
413
+	} else if ( flags & SEC_DATA ) {
414
+		/* .data-type section */
415
+		new->hdr.Characteristics =
416
+			( EFI_IMAGE_SCN_CNT_INITIALIZED_DATA |
417
+			  EFI_IMAGE_SCN_MEM_NOT_PAGED |
418
+			  EFI_IMAGE_SCN_MEM_READ |
419
+			  EFI_IMAGE_SCN_MEM_WRITE );
420
+		applicable_start = &data_start;
421
+		applicable_end = &data_mid;
422
+	} else if ( flags & SEC_READONLY ) {
423
+		/* .rodata-type section */
424
+		new->hdr.Characteristics =
425
+			( EFI_IMAGE_SCN_CNT_INITIALIZED_DATA |
426
+			  EFI_IMAGE_SCN_MEM_NOT_PAGED |
427
+			  EFI_IMAGE_SCN_MEM_READ );
428
+		applicable_start = &data_start;
429
+		applicable_end = &data_mid;
430
+	} else if ( ! ( flags & SEC_LOAD ) ) {
431
+		/* .bss-type section */
432
+		new->hdr.Characteristics =
433
+			( EFI_IMAGE_SCN_CNT_UNINITIALIZED_DATA |
434
+			  EFI_IMAGE_SCN_MEM_NOT_PAGED |
435
+			  EFI_IMAGE_SCN_MEM_READ |
436
+			  EFI_IMAGE_SCN_MEM_WRITE );
437
+		applicable_start = &data_mid;
438
+		applicable_end = &data_end;
439
+	}
440
+
441
+	/* Copy in section contents */
442
+	if ( flags & SEC_LOAD ) {
443
+		if ( ! bfd_get_section_contents ( bfd, section, new->contents,
444
+						  0, section_memsz ) ) {
445
+			fprintf ( stderr, "Cannot read section %s: ",
446
+				  section->name );
447
+			bfd_perror ( NULL );
448
+			exit ( 1 );
449
+		}
450
+	}
451
+
452
+	/* Update RVA limits */
453
+	start = new->hdr.VirtualAddress;
454
+	end = ( start + new->hdr.Misc.VirtualSize );
455
+	if ( ( ! *applicable_start ) || ( *applicable_start >= start ) )
456
+		*applicable_start = start;
457
+	if ( *applicable_end < end )
458
+		*applicable_end = end;
459
+	if ( data_start < code_end )
460
+		data_start = code_end;
461
+	if ( data_mid < data_start )
462
+		data_mid = data_start;
463
+	if ( data_end < data_mid )
464
+		data_end = data_mid;
465
+
466
+	/* Write RVA limits back to file header */
467
+	pe_header->nt.OptionalHeader.BaseOfCode = code_start;
468
+	pe_header->nt.OptionalHeader.SizeOfCode = ( code_end - code_start );
469
+#if defined(MDE_CPU_IA32)
470
+	pe_header->nt.OptionalHeader.BaseOfData = data_start;
471
+#endif
472
+	pe_header->nt.OptionalHeader.SizeOfInitializedData =
473
+		( data_mid - data_start );
474
+	pe_header->nt.OptionalHeader.SizeOfUninitializedData =
475
+		( data_end - data_mid );
476
+
477
+	/* Update remaining file header fields */
478
+	pe_header->nt.FileHeader.NumberOfSections++;
479
+	pe_header->nt.OptionalHeader.SizeOfHeaders += sizeof ( new->hdr );
480
+	pe_header->nt.OptionalHeader.SizeOfImage =
481
+		efi_file_align ( data_end );
482
+
483
+	return new;
484
+}
485
+
486
+/**
487
+ * Process relocation record
488
+ *
489
+ * @v bfd		BFD file
490
+ * @v section		Section
491
+ * @v rel		Relocation entry
492
+ * @v pe_reltab		PE relocation table to fill in
493
+ */
494
+static void process_reloc ( bfd *bfd, asection *section, arelent *rel,
495
+			    struct pe_relocs **pe_reltab ) {
496
+	reloc_howto_type *howto = rel->howto;
497
+	asymbol *sym = *(rel->sym_ptr_ptr);
498
+	unsigned long offset = ( bfd_get_section_vma ( bfd, section ) +
499
+				 rel->address );
500
+
501
+	if ( bfd_is_abs_section ( sym->section ) ) {
502
+		/* Skip absolute symbols; the symbol value won't
503
+		 * change when the object is loaded.
504
+		 */
505
+	} else if ( strcmp ( howto->name, "R_X86_64_64" ) == 0 ) {
506
+		/* Generate an 8-byte PE relocation */
507
+		generate_pe_reloc ( pe_reltab, offset, 8 );
508
+	} else if ( ( strcmp ( howto->name, "R_386_32" ) == 0 ) ||
509
+		    ( strcmp ( howto->name, "R_X86_64_32" ) == 0 ) ) {
510
+		/* Generate a 4-byte PE relocation */
511
+		generate_pe_reloc ( pe_reltab, offset, 4 );
512
+	} else if ( strcmp ( howto->name, "R_386_16" ) == 0 ) {
513
+		/* Generate a 2-byte PE relocation */
514
+		generate_pe_reloc ( pe_reltab, offset, 2 );
515
+	} else if ( ( strcmp ( howto->name, "R_386_PC32" ) == 0 ) ||
516
+		    ( strcmp ( howto->name, "R_X86_64_PC32" ) == 0 ) ) {
517
+		/* Skip PC-relative relocations; all relative offsets
518
+		 * remain unaltered when the object is loaded.
519
+		 */
520
+	} else {
521
+		fprintf ( stderr, "Unrecognised relocation type %s\n",
522
+			  howto->name );
523
+		exit ( 1 );
524
+	}
525
+}
526
+
527
+/**
528
+ * Create relocations section
529
+ *
530
+ * @v pe_header		PE file header
531
+ * @v pe_reltab		PE relocation table
532
+ * @ret section		Relocation section
533
+ */
534
+static struct pe_section *
535
+create_reloc_section ( struct pe_header *pe_header,
536
+		       struct pe_relocs *pe_reltab ) {
537
+	struct pe_section *reloc;
538
+	size_t section_memsz;
539
+	size_t section_filesz;
540
+	EFI_IMAGE_DATA_DIRECTORY *relocdir;
541
+
542
+	/* Allocate PE section */
543
+	section_memsz = output_pe_reltab ( pe_reltab, NULL );
544
+	section_filesz = efi_file_align ( section_memsz );
545
+	reloc = xmalloc ( sizeof ( *reloc ) + section_filesz );
546
+	memset ( reloc, 0, sizeof ( *reloc ) + section_filesz );
547
+
548
+	/* Fill in section header details */
549
+	strncpy ( ( char * ) reloc->hdr.Name, ".reloc",
550
+		  sizeof ( reloc->hdr.Name ) );
551
+	reloc->hdr.Misc.VirtualSize = section_memsz;
552
+	reloc->hdr.VirtualAddress = pe_header->nt.OptionalHeader.SizeOfImage;
553
+	reloc->hdr.SizeOfRawData = section_filesz;
554
+	reloc->hdr.Characteristics = ( EFI_IMAGE_SCN_CNT_INITIALIZED_DATA |
555
+				       EFI_IMAGE_SCN_MEM_NOT_PAGED |
556
+				       EFI_IMAGE_SCN_MEM_READ );
557
+
558
+	/* Copy in section contents */
559
+	output_pe_reltab ( pe_reltab, reloc->contents );
560
+
561
+	/* Update file header details */
562
+	pe_header->nt.FileHeader.NumberOfSections++;
563
+	pe_header->nt.OptionalHeader.SizeOfHeaders += sizeof ( reloc->hdr );
564
+	pe_header->nt.OptionalHeader.SizeOfImage += section_filesz;
565
+	relocdir = &(pe_header->nt.OptionalHeader.DataDirectory
566
+		     [EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC]);
567
+	relocdir->VirtualAddress = reloc->hdr.VirtualAddress;
568
+	relocdir->Size = reloc->hdr.Misc.VirtualSize;
569
+
570
+	return reloc;
571
+}
572
+
573
+/**
574
+ * Create debug section
575
+ *
576
+ * @v pe_header		PE file header
577
+ * @ret section		Debug section
578
+ */
579
+static struct pe_section *
580
+create_debug_section ( struct pe_header *pe_header, const char *filename ) {
581
+	struct pe_section *debug;
582
+	size_t section_memsz;
583
+	size_t section_filesz;
584
+	EFI_IMAGE_DATA_DIRECTORY *debugdir;
585
+	struct {
586
+		EFI_IMAGE_DEBUG_DIRECTORY_ENTRY debug;
587
+		EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY rsds;
588
+		char name[ strlen ( filename ) + 1 ];
589
+	} *contents;
590
+
591
+	/* Allocate PE section */
592
+	section_memsz = sizeof ( *contents );
593
+	section_filesz = efi_file_align ( section_memsz );
594
+	debug = xmalloc ( sizeof ( *debug ) + section_filesz );
595
+	memset ( debug, 0, sizeof ( *debug ) + section_filesz );
596
+	contents = ( void * ) debug->contents;
597
+
598
+	/* Fill in section header details */
599
+	strncpy ( ( char * ) debug->hdr.Name, ".debug",
600
+		  sizeof ( debug->hdr.Name ) );
601
+	debug->hdr.Misc.VirtualSize = section_memsz;
602
+	debug->hdr.VirtualAddress = pe_header->nt.OptionalHeader.SizeOfImage;
603
+	debug->hdr.SizeOfRawData = section_filesz;
604
+	debug->hdr.Characteristics = ( EFI_IMAGE_SCN_CNT_INITIALIZED_DATA |
605
+				       EFI_IMAGE_SCN_MEM_NOT_PAGED |
606
+				       EFI_IMAGE_SCN_MEM_READ );
607
+
608
+	/* Create section contents */
609
+	contents->debug.TimeDateStamp = 0x10d1a884;
610
+	contents->debug.Type = EFI_IMAGE_DEBUG_TYPE_CODEVIEW;
611
+	contents->debug.SizeOfData =
612
+		( sizeof ( *contents ) - sizeof ( contents->debug ) );
613
+	contents->debug.RVA = ( debug->hdr.VirtualAddress +
614
+				offsetof ( typeof ( *contents ), rsds ) );
615
+	contents->rsds.Signature = CODEVIEW_SIGNATURE_RSDS;
616
+	snprintf ( contents->name, sizeof ( contents->name ), "%s",
617
+		   filename );
618
+
619
+	/* Update file header details */
620
+	pe_header->nt.FileHeader.NumberOfSections++;
621
+	pe_header->nt.OptionalHeader.SizeOfHeaders += sizeof ( debug->hdr );
622
+	pe_header->nt.OptionalHeader.SizeOfImage += section_filesz;
623
+	debugdir = &(pe_header->nt.OptionalHeader.DataDirectory
624
+		     [EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);
625
+	debugdir->VirtualAddress = debug->hdr.VirtualAddress;
626
+	debugdir->Size = debug->hdr.Misc.VirtualSize;
627
+
628
+	return debug;
629
+}
630
+
631
+/**
632
+ * Write out PE file
633
+ *
634
+ * @v pe_header		PE file header
635
+ * @v pe_sections	List of PE sections
636
+ * @v pe		Output file
637
+ */
638
+static void write_pe_file ( struct pe_header *pe_header,
639
+			    struct pe_section *pe_sections,
640
+			    FILE *pe ) {
641
+	struct pe_section *section;
642
+	unsigned long fpos = 0;
643
+
644
+	/* Assign raw data pointers */
645
+	fpos = efi_file_align ( pe_header->nt.OptionalHeader.SizeOfHeaders );
646
+	for ( section = pe_sections ; section ; section = section->next ) {
647
+		if ( section->hdr.SizeOfRawData ) {
648
+			section->hdr.PointerToRawData = fpos;
649
+			fpos += section->hdr.SizeOfRawData;
650
+			fpos = efi_file_align ( fpos );
651
+		}
652
+	}
653
+
654
+	/* Write file header */
655
+	if ( fwrite ( pe_header, sizeof ( *pe_header ), 1, pe ) != 1 ) {
656
+		perror ( "Could not write PE header" );
657
+		exit ( 1 );
658
+	}
659
+
660
+	/* Write section headers */
661
+	for ( section = pe_sections ; section ; section = section->next ) {
662
+		if ( fwrite ( &section->hdr, sizeof ( section->hdr ),
663
+			      1, pe ) != 1 ) {
664
+			perror ( "Could not write section header" );
665
+			exit ( 1 );
666
+		}
667
+	}
668
+
669
+	/* Write sections */
670
+	for ( section = pe_sections ; section ; section = section->next ) {
671
+		if ( fseek ( pe, section->hdr.PointerToRawData,
672
+			     SEEK_SET ) != 0 ) {
673
+			fprintf ( stderr, "Could not seek to %lx: %s\n",
674
+				  section->hdr.PointerToRawData,
675
+				  strerror ( errno ) );
676
+			exit ( 1 );
677
+		}
678
+		if ( section->hdr.SizeOfRawData &&
679
+		     ( fwrite ( section->contents, section->hdr.SizeOfRawData,
680
+				1, pe ) != 1 ) ) {
681
+			fprintf ( stderr, "Could not write section %.8s: %s\n",
682
+				  section->hdr.Name, strerror ( errno ) );
683
+			exit ( 1 );
684
+		}
685
+	}
686
+}
687
+
688
+/**
689
+ * Convert ELF to PE
690
+ *
691
+ * @v elf_name		ELF file name
692
+ * @v pe_name		PE file name
693
+ */
694
+static void elf2pe ( const char *elf_name, const char *pe_name ) {
695
+	bfd *bfd;
696
+	asymbol **symtab;
697
+	asection *section;
698
+	arelent **reltab;
699
+	arelent **rel;
700
+	struct pe_relocs *pe_reltab = NULL;
701
+	struct pe_section *pe_sections = NULL;
702
+	struct pe_section **next_pe_section = &pe_sections;
703
+	struct pe_header pe_header;
704
+	FILE *pe;
705
+
706
+	/* Open the file */
707
+	bfd = open_input_bfd ( elf_name );
708
+	symtab = read_symtab ( bfd );
709
+
710
+	/* Initialise the PE header */
711
+	memcpy ( &pe_header, &efi_pe_header, sizeof ( pe_header ) );
712
+	pe_header.nt.OptionalHeader.AddressOfEntryPoint =
713
+		bfd_get_start_address ( bfd );
714
+
715
+	/* For each input section, build an output section and create
716
+	 * the appropriate relocation records
717
+	 */
718
+	for ( section = bfd->sections ; section ; section = section->next ) {
719
+		/* Discard non-allocatable sections */
720
+		if ( ! ( bfd_get_section_flags ( bfd, section ) & SEC_ALLOC ) )
721
+			continue;
722
+		/* Create output section */
723
+		*(next_pe_section) = process_section ( bfd, &pe_header,
724
+						       section );
725
+		next_pe_section = &(*next_pe_section)->next;
726
+		/* Add relocations from this section */
727
+		reltab = read_reltab ( bfd, symtab, section );
728
+		for ( rel = reltab ; *rel ; rel++ )
729
+			process_reloc ( bfd, section, *rel, &pe_reltab );
730
+		free ( reltab );
731
+	}
732
+
733
+	/* Create the .reloc section */
734
+	*(next_pe_section) = create_reloc_section ( &pe_header, pe_reltab );
735
+	next_pe_section = &(*next_pe_section)->next;
736
+
737
+	/* Create the .reloc section */
738
+	*(next_pe_section) = create_debug_section ( &pe_header,
739
+						    basename ( pe_name ) );
740
+	next_pe_section = &(*next_pe_section)->next;
741
+
742
+	/* Write out PE file */
743
+	pe = fopen ( pe_name, "w" );
744
+	if ( ! pe ) {
745
+		fprintf ( stderr, "Could not open %s for writing: %s\n",
746
+			  pe_name, strerror ( errno ) );
747
+		exit ( 1 );
748
+	}
749
+	write_pe_file ( &pe_header, pe_sections, pe );
750
+	fclose ( pe );
751
+
752
+	/* Close BFD file */
753
+	bfd_close ( bfd );
754
+}
755
+
756
+int main ( int argc, char **argv ) {
757
+
758
+	/* Initialise libbfd */
759
+	bfd_init();
760
+
761
+	elf2pe ( argv[1], argv[2] );
762
+
763
+	return 0;
764
+}

Loading…
Cancel
Save