1 | /** @file
|
---|
2 | Elf convert solution
|
---|
3 |
|
---|
4 | Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>
|
---|
5 |
|
---|
6 | SPDX-License-Identifier: BSD-2-Clause-Patent
|
---|
7 |
|
---|
8 | **/
|
---|
9 |
|
---|
10 | #ifndef __GNUC__
|
---|
11 | #define RUNTIME_FUNCTION _WINNT_DUP_RUNTIME_FUNCTION
|
---|
12 | #include <windows.h>
|
---|
13 | #undef RUNTIME_FUNCTION
|
---|
14 | #include <io.h>
|
---|
15 | #endif
|
---|
16 | #include <stdio.h>
|
---|
17 | #include <stdlib.h>
|
---|
18 | #include <string.h>
|
---|
19 | #include <time.h>
|
---|
20 | #include <ctype.h>
|
---|
21 | #include <assert.h>
|
---|
22 |
|
---|
23 | #include <Common/UefiBaseTypes.h>
|
---|
24 | #include <IndustryStandard/PeImage.h>
|
---|
25 |
|
---|
26 | #include "EfiUtilityMsgs.h"
|
---|
27 |
|
---|
28 | #include "GenFw.h"
|
---|
29 | #include "ElfConvert.h"
|
---|
30 | #include "Elf32Convert.h"
|
---|
31 | #include "Elf64Convert.h"
|
---|
32 |
|
---|
33 | //
|
---|
34 | // Result Coff file in memory.
|
---|
35 | //
|
---|
36 | UINT8 *mCoffFile = NULL;
|
---|
37 |
|
---|
38 | //
|
---|
39 | // COFF relocation data
|
---|
40 | //
|
---|
41 | EFI_IMAGE_BASE_RELOCATION *mCoffBaseRel;
|
---|
42 | UINT16 *mCoffEntryRel;
|
---|
43 |
|
---|
44 | //
|
---|
45 | // Current offset in coff file.
|
---|
46 | //
|
---|
47 | UINT32 mCoffOffset;
|
---|
48 |
|
---|
49 | //
|
---|
50 | // Offset in Coff file of headers and sections.
|
---|
51 | //
|
---|
52 | UINT32 mTableOffset;
|
---|
53 |
|
---|
54 | //
|
---|
55 | //mFileBufferSize
|
---|
56 | //
|
---|
57 | UINT32 mFileBufferSize;
|
---|
58 |
|
---|
59 | //
|
---|
60 | //*****************************************************************************
|
---|
61 | // Common ELF Functions
|
---|
62 | //*****************************************************************************
|
---|
63 | //
|
---|
64 |
|
---|
65 | VOID
|
---|
66 | CoffAddFixupEntry(
|
---|
67 | UINT16 Val
|
---|
68 | )
|
---|
69 | {
|
---|
70 | *mCoffEntryRel = Val;
|
---|
71 | mCoffEntryRel++;
|
---|
72 | mCoffBaseRel->SizeOfBlock += 2;
|
---|
73 | mCoffOffset += 2;
|
---|
74 | }
|
---|
75 |
|
---|
76 | VOID
|
---|
77 | CoffAddFixup(
|
---|
78 | UINT32 Offset,
|
---|
79 | UINT8 Type
|
---|
80 | )
|
---|
81 | {
|
---|
82 | if (mCoffBaseRel == NULL
|
---|
83 | || mCoffBaseRel->VirtualAddress != (Offset & ~0xfff)) {
|
---|
84 | if (mCoffBaseRel != NULL) {
|
---|
85 | //
|
---|
86 | // Add a null entry (is it required ?)
|
---|
87 | //
|
---|
88 | CoffAddFixupEntry (0);
|
---|
89 |
|
---|
90 | //
|
---|
91 | // Pad for alignment.
|
---|
92 | //
|
---|
93 | if (mCoffOffset % 4 != 0)
|
---|
94 | CoffAddFixupEntry (0);
|
---|
95 | }
|
---|
96 |
|
---|
97 | mCoffFile = realloc (
|
---|
98 | mCoffFile,
|
---|
99 | mCoffOffset + sizeof(EFI_IMAGE_BASE_RELOCATION) + 2 * MAX_COFF_ALIGNMENT
|
---|
100 | );
|
---|
101 | if (mCoffFile == NULL) {
|
---|
102 | Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
|
---|
103 | }
|
---|
104 | assert (mCoffFile != NULL);
|
---|
105 | memset (
|
---|
106 | mCoffFile + mCoffOffset, 0,
|
---|
107 | sizeof(EFI_IMAGE_BASE_RELOCATION) + 2 * MAX_COFF_ALIGNMENT
|
---|
108 | );
|
---|
109 |
|
---|
110 | mCoffBaseRel = (EFI_IMAGE_BASE_RELOCATION*)(mCoffFile + mCoffOffset);
|
---|
111 | mCoffBaseRel->VirtualAddress = Offset & ~0xfff;
|
---|
112 | mCoffBaseRel->SizeOfBlock = sizeof(EFI_IMAGE_BASE_RELOCATION);
|
---|
113 |
|
---|
114 | mCoffEntryRel = (UINT16 *)(mCoffBaseRel + 1);
|
---|
115 | mCoffOffset += sizeof(EFI_IMAGE_BASE_RELOCATION);
|
---|
116 | }
|
---|
117 |
|
---|
118 | //
|
---|
119 | // Fill the entry.
|
---|
120 | //
|
---|
121 | CoffAddFixupEntry((UINT16) ((Type << 12) | (Offset & 0xfff)));
|
---|
122 | }
|
---|
123 |
|
---|
124 | VOID
|
---|
125 | CreateSectionHeader (
|
---|
126 | const CHAR8 *Name,
|
---|
127 | UINT32 Offset,
|
---|
128 | UINT32 Size,
|
---|
129 | UINT32 Flags
|
---|
130 | )
|
---|
131 | {
|
---|
132 | EFI_IMAGE_SECTION_HEADER *Hdr;
|
---|
133 | Hdr = (EFI_IMAGE_SECTION_HEADER*)(mCoffFile + mTableOffset);
|
---|
134 |
|
---|
135 | strcpy((char *)Hdr->Name, Name);
|
---|
136 | Hdr->Misc.VirtualSize = Size;
|
---|
137 | Hdr->VirtualAddress = Offset;
|
---|
138 | Hdr->SizeOfRawData = Size;
|
---|
139 | Hdr->PointerToRawData = Offset;
|
---|
140 | Hdr->PointerToRelocations = 0;
|
---|
141 | Hdr->PointerToLinenumbers = 0;
|
---|
142 | Hdr->NumberOfRelocations = 0;
|
---|
143 | Hdr->NumberOfLinenumbers = 0;
|
---|
144 | Hdr->Characteristics = Flags;
|
---|
145 |
|
---|
146 | mTableOffset += sizeof (EFI_IMAGE_SECTION_HEADER);
|
---|
147 | }
|
---|
148 |
|
---|
149 | //
|
---|
150 | //*****************************************************************************
|
---|
151 | // Functions called from GenFw main code.
|
---|
152 | //*****************************************************************************
|
---|
153 | //
|
---|
154 |
|
---|
155 | INTN
|
---|
156 | IsElfHeader (
|
---|
157 | UINT8 *FileBuffer
|
---|
158 | )
|
---|
159 | {
|
---|
160 | return (FileBuffer[EI_MAG0] == ELFMAG0 &&
|
---|
161 | FileBuffer[EI_MAG1] == ELFMAG1 &&
|
---|
162 | FileBuffer[EI_MAG2] == ELFMAG2 &&
|
---|
163 | FileBuffer[EI_MAG3] == ELFMAG3);
|
---|
164 | }
|
---|
165 |
|
---|
166 | BOOLEAN
|
---|
167 | ConvertElf (
|
---|
168 | UINT8 **FileBuffer,
|
---|
169 | UINT32 *FileLength
|
---|
170 | )
|
---|
171 | {
|
---|
172 | ELF_FUNCTION_TABLE ElfFunctions;
|
---|
173 | UINT8 EiClass;
|
---|
174 |
|
---|
175 | mFileBufferSize = *FileLength;
|
---|
176 | //
|
---|
177 | // Determine ELF type and set function table pointer correctly.
|
---|
178 | //
|
---|
179 | VerboseMsg ("Check Elf Image Header");
|
---|
180 | EiClass = (*FileBuffer)[EI_CLASS];
|
---|
181 | if (EiClass == ELFCLASS32) {
|
---|
182 | if (!InitializeElf32 (*FileBuffer, &ElfFunctions)) {
|
---|
183 | return FALSE;
|
---|
184 | }
|
---|
185 | } else if (EiClass == ELFCLASS64) {
|
---|
186 | if (!InitializeElf64 (*FileBuffer, &ElfFunctions)) {
|
---|
187 | return FALSE;
|
---|
188 | }
|
---|
189 | } else {
|
---|
190 | Error (NULL, 0, 3000, "Unsupported", "ELF EI_CLASS not supported.");
|
---|
191 | return FALSE;
|
---|
192 | }
|
---|
193 |
|
---|
194 | //
|
---|
195 | // Compute sections new address.
|
---|
196 | //
|
---|
197 | VerboseMsg ("Compute sections new address.");
|
---|
198 | ElfFunctions.ScanSections ();
|
---|
199 |
|
---|
200 | //
|
---|
201 | // Write and relocate sections.
|
---|
202 | //
|
---|
203 | VerboseMsg ("Write and relocate sections.");
|
---|
204 | if (!ElfFunctions.WriteSections (SECTION_TEXT)) {
|
---|
205 | return FALSE;
|
---|
206 | }
|
---|
207 | if (!ElfFunctions.WriteSections (SECTION_DATA)) {
|
---|
208 | return FALSE;
|
---|
209 | }
|
---|
210 | if (!ElfFunctions.WriteSections (SECTION_HII)) {
|
---|
211 | return FALSE;
|
---|
212 | }
|
---|
213 |
|
---|
214 | //
|
---|
215 | // Translate and write relocations.
|
---|
216 | //
|
---|
217 | VerboseMsg ("Translate and write relocations.");
|
---|
218 | ElfFunctions.WriteRelocations ();
|
---|
219 |
|
---|
220 | //
|
---|
221 | // Write debug info.
|
---|
222 | //
|
---|
223 | VerboseMsg ("Write debug info.");
|
---|
224 | ElfFunctions.WriteDebug ();
|
---|
225 |
|
---|
226 | //
|
---|
227 | // For PRM Driver to Write export info.
|
---|
228 | //
|
---|
229 | if (mExportFlag) {
|
---|
230 | VerboseMsg ("Write export info.");
|
---|
231 | ElfFunctions.WriteExport ();
|
---|
232 | }
|
---|
233 |
|
---|
234 | //
|
---|
235 | // Make sure image size is correct before returning the new image.
|
---|
236 | //
|
---|
237 | VerboseMsg ("Set image size.");
|
---|
238 | ElfFunctions.SetImageSize ();
|
---|
239 |
|
---|
240 | //
|
---|
241 | // Replace.
|
---|
242 | //
|
---|
243 | free (*FileBuffer);
|
---|
244 | *FileBuffer = mCoffFile;
|
---|
245 | *FileLength = mCoffOffset;
|
---|
246 |
|
---|
247 | //
|
---|
248 | // Free resources used by ELF functions.
|
---|
249 | //
|
---|
250 | ElfFunctions.CleanUp ();
|
---|
251 |
|
---|
252 | return TRUE;
|
---|
253 | }
|
---|