]>
Commit | Line | Data |
---|---|---|
1 | /*++\r | |
2 | \r | |
3 | Copyright (c) 2004, Intel Corporation \r | |
4 | All rights reserved. This program and the accompanying materials \r | |
5 | are licensed and made available under the terms and conditions of the BSD License \r | |
6 | which accompanies this distribution. The full text of the license may be found at \r | |
7 | http://opensource.org/licenses/bsd-license.php \r | |
8 | \r | |
9 | THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r | |
10 | WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r | |
11 | \r | |
12 | Module Name:\r | |
13 | \r | |
14 | fwimage.c\r | |
15 | \r | |
16 | Abstract:\r | |
17 | \r | |
18 | Converts a pe32+ image to an FW image type\r | |
19 | \r | |
20 | --*/\r | |
21 | \r | |
22 | #include "WinNtInclude.h"\r | |
23 | \r | |
24 | //\r | |
25 | // List of OS and CPU which support ELF to PE conversion\r | |
26 | //\r | |
27 | #if defined(linux) | |
28 | #if defined(i386) | |
29 | #define HAVE_ELF | |
30 | #endif | |
31 | #endif | |
32 | ||
33 | #ifndef __GNUC__\r | |
34 | #include <windows.h>\r | |
35 | #endif\r | |
36 | #include <stdio.h>\r | |
37 | #include <stdlib.h>\r | |
38 | #include <string.h>\r | |
39 | #include <time.h>\r | |
40 | ||
41 | #ifdef HAVE_ELF | |
42 | #include <elf.h> | |
43 | #endif | |
44 | \r | |
45 | #include <Common/UefiBaseTypes.h>\r | |
46 | #include <Common/EfiImage.h>\r | |
47 | \r | |
48 | #include "CommonLib.h"\r | |
49 | #include "EfiUtilityMsgs.c"\r | |
50 | \r | |
51 | //\r | |
52 | // Version of this utility\r | |
53 | //\r | |
54 | #define UTILITY_NAME "FwImage"\r | |
55 | #define UTILITY_MAJOR_VERSION 1\r | |
56 | #define UTILITY_MINOR_VERSION 0\r | |
57 | \r | |
58 | #ifdef __GNUC__\r | |
59 | typedef unsigned long ULONG;\r | |
60 | typedef unsigned char UCHAR;\r | |
61 | typedef unsigned char *PUCHAR;\r | |
62 | typedef unsigned short USHORT;\r | |
63 | #endif\r | |
64 | \r | |
65 | PUCHAR InImageName;\r | |
66 | \r | |
67 | static\r | |
68 | void\r | |
69 | Version (\r | |
70 | VOID\r | |
71 | )\r | |
72 | {\r | |
73 | printf ("%s v%d.%d -EDK Utility for Converting a pe32+ image to an FW image type.\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION);\r | |
74 | printf ("Copyright (c) 1999-2006 Intel Corporation. All rights reserved.\n");\r | |
75 | }\r | |
76 | \r | |
77 | \r | |
78 | VOID\r | |
79 | Usage (\r | |
80 | VOID\r | |
81 | )\r | |
82 | {\r | |
83 | Version();\r | |
84 | printf ("\nUsage: " UTILITY_NAME " {-t time-date} {-h|--help|-?|/?|-V|--version} \n\\r | |
85 | [BASE|SEC|PEI_CORE|PEIM|DXE_CORE|DXE_DRIVER|DXE_RUNTIME_DRIVER|\n\\r | |
86 | DXE_SAL_DRIVER|DXE_SMM_DRIVER|TOOL|UEFI_DRIVER|UEFI_APPLICATION|\n\\r | |
87 | USER_DEFINED] peimage [outimage]\n");\r | |
88 | }\r | |
89 | \r | |
90 | static\r | |
91 | STATUS\r | |
92 | FCopyFile (\r | |
93 | FILE *in,\r | |
94 | FILE *out\r | |
95 | )\r | |
96 | {\r | |
97 | ULONG filesize;\r | |
98 | ULONG offset;\r | |
99 | ULONG length;\r | |
100 | UCHAR Buffer[8 * 1024];\r | |
101 | \r | |
102 | fseek (in, 0, SEEK_END);\r | |
103 | filesize = ftell (in);\r | |
104 | \r | |
105 | fseek (in, 0, SEEK_SET);\r | |
106 | fseek (out, 0, SEEK_SET);\r | |
107 | \r | |
108 | offset = 0;\r | |
109 | while (offset < filesize) {\r | |
110 | length = sizeof (Buffer);\r | |
111 | if (filesize - offset < length) {\r | |
112 | length = filesize - offset;\r | |
113 | }\r | |
114 | \r | |
115 | fread (Buffer, length, 1, in);\r | |
116 | fwrite (Buffer, length, 1, out);\r | |
117 | offset += length;\r | |
118 | }\r | |
119 | \r | |
120 | if ((ULONG) ftell (out) != filesize) {\r | |
121 | Error (NULL, 0, 0, "write error", NULL);\r | |
122 | return STATUS_ERROR;\r | |
123 | }\r | |
124 | \r | |
125 | return STATUS_SUCCESS;\r | |
126 | }\r | |
127 | \r | |
128 | static\r | |
129 | STATUS\r | |
130 | FReadFile (\r | |
131 | FILE *in,\r | |
132 | VOID **Buffer,\r | |
133 | UINTN *Length\r | |
134 | )\r | |
135 | {\r | |
136 | fseek (in, 0, SEEK_END);\r | |
137 | *Length = ftell (in);\r | |
138 | *Buffer = malloc (*Length);\r | |
139 | fseek (in, 0, SEEK_SET);\r | |
140 | fread (*Buffer, *Length, 1, in);\r | |
141 | return STATUS_SUCCESS;\r | |
142 | }\r | |
143 | \r | |
144 | static\r | |
145 | STATUS\r | |
146 | FWriteFile (\r | |
147 | FILE *out,\r | |
148 | VOID *Buffer,\r | |
149 | UINTN Length\r | |
150 | )\r | |
151 | {\r | |
152 | fseek (out, 0, SEEK_SET);\r | |
153 | fwrite (Buffer, Length, 1, out);\r | |
154 | if ((ULONG) ftell (out) != Length) {\r | |
155 | Error (NULL, 0, 0, "write error", NULL);\r | |
156 | return STATUS_ERROR;\r | |
157 | }\r | |
158 | free (Buffer);\r | |
159 | return STATUS_SUCCESS;\r | |
160 | }\r | |
161 | \r | |
162 | #ifdef HAVE_ELF | |
163 | INTN | |
164 | IsElfHeader( | |
165 | UINT8 *FileBuffer | |
166 | ) | |
167 | { | |
168 | return (FileBuffer[EI_MAG0] == ELFMAG0 | |
169 | && FileBuffer[EI_MAG1] == ELFMAG1 | |
170 | && FileBuffer[EI_MAG2] == ELFMAG2 | |
171 | && FileBuffer[EI_MAG3] == ELFMAG3); | |
172 | } | |
173 | ||
174 | typedef Elf32_Shdr Elf_Shdr; | |
175 | typedef Elf32_Ehdr Elf_Ehdr; | |
176 | typedef Elf32_Rel Elf_Rel; | |
177 | typedef Elf32_Sym Elf_Sym; | |
178 | #define ELFCLASS ELFCLASS32 | |
179 | #define ELF_R_TYPE(r) ELF32_R_TYPE(r) | |
180 | #define ELF_R_SYM(r) ELF32_R_SYM(r) | |
181 | ||
182 | // | |
183 | // Well known ELF structures. | |
184 | // | |
185 | Elf_Ehdr *Ehdr; | |
186 | Elf_Shdr *ShdrBase; | |
187 | ||
188 | // | |
189 | // PE section alignment. | |
190 | // | |
191 | const UINT32 CoffAlignment = 0x20; | |
192 | const UINT32 CoffNbrSections = 4; | |
193 | ||
194 | // | |
195 | // Current offset in coff file. | |
196 | // | |
197 | UINT32 CoffOffset; | |
198 | ||
199 | // | |
200 | // Result Coff file in memory. | |
201 | // | |
202 | UINT8 *CoffFile; | |
203 | ||
204 | // | |
205 | // Offset in Coff file of headers and sections. | |
206 | // | |
207 | UINT32 NtHdrOffset; | |
208 | UINT32 TableOffset; | |
209 | UINT32 TextOffset; | |
210 | UINT32 DataOffset; | |
211 | UINT32 RelocOffset; | |
212 | ||
213 | // | |
214 | // ELF sections to offset in Coff file. | |
215 | // | |
216 | UINT32 *CoffSectionsOffset; | |
217 | ||
218 | EFI_IMAGE_BASE_RELOCATION *CoffBaseRel; | |
219 | UINT16 *CoffEntryRel; | |
220 | ||
221 | UINT32 | |
222 | CoffAlign( | |
223 | UINT32 Offset | |
224 | ) | |
225 | { | |
226 | return (Offset + CoffAlignment - 1) & ~(CoffAlignment - 1); | |
227 | } | |
228 | ||
229 | Elf_Shdr * | |
230 | GetShdrByIndex( | |
231 | UINT32 Num | |
232 | ) | |
233 | { | |
234 | if (Num >= Ehdr->e_shnum) | |
235 | return NULL; | |
236 | return (Elf_Shdr*)((UINT8*)ShdrBase + Num * Ehdr->e_shentsize); | |
237 | } | |
238 | ||
239 | INTN | |
240 | CheckElfHeader( | |
241 | VOID | |
242 | ) | |
243 | { | |
244 | // | |
245 | // Note: Magic has already been tested. | |
246 | // | |
247 | if (Ehdr->e_ident[EI_CLASS] != ELFCLASS) | |
248 | return 0; | |
249 | if (Ehdr->e_ident[EI_DATA] != ELFDATA2LSB) | |
250 | return 0; | |
251 | if (Ehdr->e_type != ET_EXEC) | |
252 | return 0; | |
253 | if (Ehdr->e_machine != EM_386) | |
254 | return 0; | |
255 | if (Ehdr->e_version != EV_CURRENT) | |
256 | return 0; | |
257 | ||
258 | ShdrBase = (Elf_Shdr *)((UINT8 *)Ehdr + Ehdr->e_shoff); | |
259 | ||
260 | CoffSectionsOffset = (UINT32 *)malloc(Ehdr->e_shnum * sizeof (UINT32)); | |
261 | memset(CoffSectionsOffset, 0, Ehdr->e_shnum * sizeof(UINT32)); | |
262 | return 1; | |
263 | } | |
264 | ||
265 | int | |
266 | IsTextShdr( | |
267 | Elf_Shdr *Shdr | |
268 | ) | |
269 | { | |
270 | return (Shdr->sh_flags & (SHF_WRITE | SHF_ALLOC)) == SHF_ALLOC; | |
271 | } | |
272 | ||
273 | int | |
274 | IsDataShdr( | |
275 | Elf_Shdr *Shdr | |
276 | ) | |
277 | { | |
278 | return (Shdr->sh_flags & (SHF_WRITE | SHF_ALLOC)) == (SHF_ALLOC | SHF_WRITE); | |
279 | } | |
280 | ||
281 | void | |
282 | CreateSectionHeader( | |
283 | const char *Name, | |
284 | UINT32 Offset, | |
285 | UINT32 Size, | |
286 | UINT32 Flags | |
287 | ) | |
288 | { | |
289 | EFI_IMAGE_SECTION_HEADER *Hdr; | |
290 | Hdr = (EFI_IMAGE_SECTION_HEADER*)(CoffFile + TableOffset); | |
291 | ||
292 | strcpy(Hdr->Name, Name); | |
293 | Hdr->Misc.VirtualSize = Size; | |
294 | Hdr->VirtualAddress = Offset; | |
295 | Hdr->SizeOfRawData = Size; | |
296 | Hdr->PointerToRawData = Offset; | |
297 | Hdr->PointerToRelocations = 0; | |
298 | Hdr->PointerToLinenumbers = 0; | |
299 | Hdr->NumberOfRelocations = 0; | |
300 | Hdr->NumberOfLinenumbers = 0; | |
301 | Hdr->Characteristics = Flags; | |
302 | ||
303 | TableOffset += sizeof (EFI_IMAGE_SECTION_HEADER); | |
304 | } | |
305 | ||
306 | void | |
307 | ScanSections( | |
308 | VOID | |
309 | ) | |
310 | { | |
311 | UINT32 i; | |
312 | EFI_IMAGE_DOS_HEADER *DosHdr; | |
313 | EFI_IMAGE_NT_HEADERS *NtHdr; | |
314 | UINT32 CoffEntry = 0; | |
315 | ||
316 | CoffOffset = 0; | |
317 | ||
318 | // | |
319 | // Coff file start with a DOS header. | |
320 | // | |
321 | CoffOffset = sizeof(EFI_IMAGE_DOS_HEADER) + 0x40; | |
322 | NtHdrOffset = CoffOffset; | |
323 | CoffOffset += sizeof(EFI_IMAGE_NT_HEADERS); | |
324 | TableOffset = CoffOffset; | |
325 | CoffOffset += CoffNbrSections * sizeof(EFI_IMAGE_SECTION_HEADER); | |
326 | ||
327 | // | |
328 | // First text sections. | |
329 | // | |
330 | CoffOffset = CoffAlign(CoffOffset); | |
331 | TextOffset = CoffOffset; | |
332 | for (i = 0; i < Ehdr->e_shnum; i++) { | |
333 | Elf_Shdr *shdr = GetShdrByIndex(i); | |
334 | if (IsTextShdr(shdr)) { | |
335 | /* Relocate entry. */ | |
336 | if (Ehdr->e_entry >= shdr->sh_addr | |
337 | && Ehdr->e_entry < shdr->sh_addr + shdr->sh_size) { | |
338 | CoffEntry = CoffOffset + Ehdr->e_entry - shdr->sh_addr; | |
339 | } | |
340 | CoffSectionsOffset[i] = CoffOffset; | |
341 | CoffOffset += shdr->sh_size; | |
342 | } | |
343 | } | |
344 | CoffOffset = CoffAlign(CoffOffset); | |
345 | ||
346 | // | |
347 | // Then data sections. | |
348 | // | |
349 | DataOffset = CoffOffset; | |
350 | for (i = 0; i < Ehdr->e_shnum; i++) { | |
351 | Elf_Shdr *shdr = GetShdrByIndex(i); | |
352 | if (IsDataShdr(shdr)) { | |
353 | CoffSectionsOffset[i] = CoffOffset; | |
354 | CoffOffset += shdr->sh_size; | |
355 | } | |
356 | } | |
357 | CoffOffset = CoffAlign(CoffOffset); | |
358 | ||
359 | RelocOffset = CoffOffset; | |
360 | ||
361 | // | |
362 | // Allocate base Coff file. Will be expanded later for relocations. | |
363 | // | |
364 | CoffFile = (UINT8 *)malloc(CoffOffset); | |
365 | memset(CoffFile, 0, CoffOffset); | |
366 | ||
367 | // | |
368 | // Fill headers. | |
369 | // | |
370 | DosHdr = (EFI_IMAGE_DOS_HEADER *)CoffFile; | |
371 | DosHdr->e_magic = EFI_IMAGE_DOS_SIGNATURE; | |
372 | DosHdr->e_lfanew = NtHdrOffset; | |
373 | ||
374 | NtHdr = (EFI_IMAGE_NT_HEADERS*)(CoffFile + NtHdrOffset); | |
375 | ||
376 | NtHdr->Signature = EFI_IMAGE_NT_SIGNATURE; | |
377 | ||
378 | NtHdr->FileHeader.Machine = EFI_IMAGE_MACHINE_IA32; | |
379 | NtHdr->FileHeader.NumberOfSections = CoffNbrSections; | |
380 | NtHdr->FileHeader.TimeDateStamp = time(NULL); | |
381 | NtHdr->FileHeader.PointerToSymbolTable = 0; | |
382 | NtHdr->FileHeader.NumberOfSymbols = 0; | |
383 | NtHdr->FileHeader.SizeOfOptionalHeader = sizeof(NtHdr->OptionalHeader); | |
384 | NtHdr->FileHeader.Characteristics = EFI_IMAGE_FILE_EXECUTABLE_IMAGE | |
385 | | EFI_IMAGE_FILE_LINE_NUMS_STRIPPED | |
386 | | EFI_IMAGE_FILE_LOCAL_SYMS_STRIPPED | |
387 | | EFI_IMAGE_FILE_32BIT_MACHINE; | |
388 | ||
389 | NtHdr->OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC; | |
390 | NtHdr->OptionalHeader.SizeOfCode = DataOffset - TextOffset; | |
391 | NtHdr->OptionalHeader.SizeOfInitializedData = RelocOffset - DataOffset; | |
392 | NtHdr->OptionalHeader.SizeOfUninitializedData = 0; | |
393 | NtHdr->OptionalHeader.AddressOfEntryPoint = CoffEntry; | |
394 | NtHdr->OptionalHeader.BaseOfCode = TextOffset; | |
395 | ||
396 | NtHdr->OptionalHeader.BaseOfData = DataOffset; | |
397 | NtHdr->OptionalHeader.ImageBase = 0; | |
398 | NtHdr->OptionalHeader.SectionAlignment = CoffAlignment; | |
399 | NtHdr->OptionalHeader.FileAlignment = CoffAlignment; | |
400 | NtHdr->OptionalHeader.SizeOfImage = 0; | |
401 | ||
402 | NtHdr->OptionalHeader.SizeOfHeaders = TextOffset; | |
403 | NtHdr->OptionalHeader.NumberOfRvaAndSizes = EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES; | |
404 | ||
405 | // | |
406 | // Section headers. | |
407 | // | |
408 | CreateSectionHeader (".text", TextOffset, DataOffset - TextOffset, | |
409 | EFI_IMAGE_SCN_CNT_CODE | |
410 | | EFI_IMAGE_SCN_MEM_EXECUTE | |
411 | | EFI_IMAGE_SCN_MEM_READ); | |
412 | CreateSectionHeader (".data", DataOffset, RelocOffset - DataOffset, | |
413 | EFI_IMAGE_SCN_CNT_INITIALIZED_DATA | |
414 | | EFI_IMAGE_SCN_MEM_WRITE | |
415 | | EFI_IMAGE_SCN_MEM_READ); | |
416 | } | |
417 | ||
418 | void | |
419 | WriteSections( | |
420 | int (*Filter)(Elf_Shdr *) | |
421 | ) | |
422 | { | |
423 | UINT32 Idx; | |
424 | ||
425 | // | |
426 | // First: copy sections. | |
427 | // | |
428 | for (Idx = 0; Idx < Ehdr->e_shnum; Idx++) { | |
429 | Elf_Shdr *Shdr = GetShdrByIndex(Idx); | |
430 | if ((*Filter)(Shdr)) { | |
431 | switch (Shdr->sh_type) { | |
432 | case SHT_PROGBITS: | |
433 | /* Copy. */ | |
434 | memcpy(CoffFile + CoffSectionsOffset[Idx], | |
435 | (UINT8*)Ehdr + Shdr->sh_offset, | |
436 | Shdr->sh_size); | |
437 | break; | |
438 | case SHT_NOBITS: | |
439 | memset(CoffFile + CoffSectionsOffset[Idx], 0, Shdr->sh_size); | |
440 | break; | |
441 | default: | |
442 | Error (NULL, 0, 0, InImageName, "unhandle section type %x", | |
443 | (UINTN)Shdr->sh_type); | |
444 | } | |
445 | } | |
446 | } | |
447 | ||
448 | // | |
449 | // Second: apply relocations. | |
450 | // | |
451 | for (Idx = 0; Idx < Ehdr->e_shnum; Idx++) { | |
452 | Elf_Shdr *RelShdr = GetShdrByIndex(Idx); | |
453 | if (RelShdr->sh_type != SHT_REL) | |
454 | continue; | |
455 | Elf_Shdr *SecShdr = GetShdrByIndex(RelShdr->sh_info); | |
456 | UINT32 SecOffset = CoffSectionsOffset[RelShdr->sh_info]; | |
457 | if (RelShdr->sh_type == SHT_REL && (*Filter)(SecShdr)) { | |
458 | UINT32 RelIdx; | |
459 | Elf_Shdr *SymtabShdr = GetShdrByIndex(RelShdr->sh_link); | |
460 | UINT8 *Symtab = (UINT8*)Ehdr + SymtabShdr->sh_offset; | |
461 | ||
462 | for (RelIdx = 0; RelIdx < RelShdr->sh_size; RelIdx += RelShdr->sh_entsize) { | |
463 | Elf_Rel *Rel = (Elf_Rel *)((UINT8*)Ehdr + RelShdr->sh_offset + RelIdx); | |
464 | Elf_Sym *Sym = (Elf_Sym *) | |
465 | (Symtab + ELF_R_SYM(Rel->r_info) * SymtabShdr->sh_entsize); | |
466 | Elf_Shdr *SymShdr; | |
467 | UINT8 *Targ; | |
468 | ||
469 | if (Sym->st_shndx == SHN_UNDEF | |
470 | || Sym->st_shndx == SHN_ABS | |
471 | || Sym->st_shndx > Ehdr->e_shnum) { | |
472 | Error (NULL, 0, 0, InImageName, "bad symbol definition"); | |
473 | } | |
474 | SymShdr = GetShdrByIndex(Sym->st_shndx); | |
475 | ||
476 | // | |
477 | // Note: r_offset in a memory address. | |
478 | // Convert it to a pointer in the coff file. | |
479 | // | |
480 | Targ = CoffFile + SecOffset + (Rel->r_offset - SecShdr->sh_addr); | |
481 | ||
482 | switch (ELF_R_TYPE(Rel->r_info)) { | |
483 | case R_386_NONE: | |
484 | break; | |
485 | case R_386_32: | |
486 | // | |
487 | // Absolute relocation. | |
488 | // | |
489 | *(UINT32 *)Targ = *(UINT32 *)Targ - SymShdr->sh_addr | |
490 | + CoffSectionsOffset[Sym->st_shndx]; | |
491 | break; | |
492 | case R_386_PC32: | |
493 | // | |
494 | // Relative relocation: Symbol - Ip + Addend | |
495 | // | |
496 | *(UINT32 *)Targ = *(UINT32 *)Targ | |
497 | + (CoffSectionsOffset[Sym->st_shndx] - SymShdr->sh_addr) | |
498 | - (SecOffset - SecShdr->sh_addr); | |
499 | break; | |
500 | default: | |
501 | Error (NULL, 0, 0, InImageName, "unhandled relocation type %x", | |
502 | ELF_R_TYPE(Rel->r_info)); | |
503 | } | |
504 | } | |
505 | } | |
506 | } | |
507 | } | |
508 | ||
509 | void | |
510 | CoffAddFixupEntry( | |
511 | UINT16 Val | |
512 | ) | |
513 | { | |
514 | *CoffEntryRel = Val; | |
515 | CoffEntryRel++; | |
516 | CoffBaseRel->SizeOfBlock += 2; | |
517 | CoffOffset += 2; | |
518 | } | |
519 | ||
520 | void | |
521 | CoffAddFixup( | |
522 | UINT32 Offset, | |
523 | UINT8 Type | |
524 | ) | |
525 | { | |
526 | if (CoffBaseRel == NULL | |
527 | || CoffBaseRel->VirtualAddress != (Offset & ~0xfff)) { | |
528 | if (CoffBaseRel != NULL) { | |
529 | // | |
530 | // Add a null entry (is it required ?) | |
531 | // | |
532 | CoffAddFixupEntry (0); | |
533 | // | |
534 | // Pad for alignment. | |
535 | // | |
536 | if (CoffOffset % 4 != 0) | |
537 | CoffAddFixupEntry (0); | |
538 | } | |
539 | ||
540 | CoffFile = realloc | |
541 | (CoffFile, | |
542 | CoffOffset + sizeof(EFI_IMAGE_BASE_RELOCATION) + 2*0x1000); | |
543 | memset(CoffFile + CoffOffset, 0, | |
544 | sizeof(EFI_IMAGE_BASE_RELOCATION) + 2*0x1000); | |
545 | ||
546 | CoffBaseRel = (EFI_IMAGE_BASE_RELOCATION*)(CoffFile + CoffOffset); | |
547 | CoffBaseRel->VirtualAddress = Offset & ~0xfff; | |
548 | CoffBaseRel->SizeOfBlock = sizeof(EFI_IMAGE_BASE_RELOCATION); | |
549 | ||
550 | CoffEntryRel = (UINT16 *)(CoffBaseRel + 1); | |
551 | CoffOffset += sizeof(EFI_IMAGE_BASE_RELOCATION); | |
552 | } | |
553 | ||
554 | // | |
555 | // Fill the entry. | |
556 | // | |
557 | CoffAddFixupEntry((Type << 12) | (Offset & 0xfff)); | |
558 | } | |
559 | ||
560 | void | |
561 | WriteRelocations( | |
562 | VOID | |
563 | ) | |
564 | { | |
565 | UINT32 Idx; | |
566 | EFI_IMAGE_NT_HEADERS *NtHdr; | |
567 | EFI_IMAGE_DATA_DIRECTORY *Dir; | |
568 | ||
569 | for (Idx = 0; Idx < Ehdr->e_shnum; Idx++) { | |
570 | Elf_Shdr *RelShdr = GetShdrByIndex(Idx); | |
571 | if (RelShdr->sh_type == SHT_REL) { | |
572 | Elf_Shdr *SecShdr = GetShdrByIndex(RelShdr->sh_info); | |
573 | if (IsTextShdr(SecShdr) || IsDataShdr(SecShdr)) { | |
574 | UINT32 RelIdx; | |
575 | for (RelIdx = 0; RelIdx < RelShdr->sh_size; RelIdx += RelShdr->sh_entsize) { | |
576 | Elf_Rel *Rel = (Elf_Rel *) | |
577 | ((UINT8*)Ehdr + RelShdr->sh_offset + RelIdx); | |
578 | switch (ELF_R_TYPE(Rel->r_info)) { | |
579 | case R_386_NONE: | |
580 | case R_386_PC32: | |
581 | break; | |
582 | case R_386_32: | |
583 | CoffAddFixup(CoffSectionsOffset[RelShdr->sh_info] | |
584 | + (Rel->r_offset - SecShdr->sh_addr), | |
585 | EFI_IMAGE_REL_BASED_HIGHLOW); | |
586 | break; | |
587 | default: | |
588 | Error (NULL, 0, 0, InImageName, "unhandled relocation type %x", | |
589 | ELF_R_TYPE(Rel->r_info)); | |
590 | } | |
591 | } | |
592 | } | |
593 | } | |
594 | } | |
595 | ||
596 | // | |
597 | // Pad by adding empty entries. | |
598 | // | |
599 | while (CoffOffset & (CoffAlignment - 1)) { | |
600 | CoffAddFixupEntry(0); | |
601 | } | |
602 | ||
603 | CreateSectionHeader (".reloc", RelocOffset, CoffOffset - RelocOffset, | |
604 | EFI_IMAGE_SCN_CNT_INITIALIZED_DATA | |
605 | | EFI_IMAGE_SCN_MEM_DISCARDABLE | |
606 | | EFI_IMAGE_SCN_MEM_READ); | |
607 | ||
608 | NtHdr = (EFI_IMAGE_NT_HEADERS *)(CoffFile + NtHdrOffset); | |
609 | Dir = &NtHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC]; | |
610 | Dir->VirtualAddress = RelocOffset; | |
611 | Dir->Size = CoffOffset - RelocOffset; | |
612 | } | |
613 | ||
614 | void | |
615 | WriteDebug( | |
616 | VOID | |
617 | ) | |
618 | { | |
619 | UINT32 Len = strlen(InImageName) + 1; | |
620 | UINT32 DebugOffset = CoffOffset; | |
621 | EFI_IMAGE_NT_HEADERS *NtHdr; | |
622 | EFI_IMAGE_DATA_DIRECTORY *DataDir; | |
623 | EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *Dir; | |
624 | EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY *Nb10; | |
625 | ||
626 | CoffOffset += sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY) | |
627 | + sizeof(EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY) | |
628 | + Len; | |
629 | CoffOffset = CoffAlign(CoffOffset); | |
630 | ||
631 | CoffFile = realloc | |
632 | (CoffFile, CoffOffset); | |
633 | memset(CoffFile + DebugOffset, 0, CoffOffset - DebugOffset); | |
634 | ||
635 | Dir = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY*)(CoffFile + DebugOffset); | |
636 | Dir->Type = EFI_IMAGE_DEBUG_TYPE_CODEVIEW; | |
637 | Dir->SizeOfData = sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY) + Len; | |
638 | Dir->RVA = DebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY); | |
639 | Dir->FileOffset = DebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY); | |
640 | ||
641 | Nb10 = (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY*)(Dir + 1); | |
642 | Nb10->Signature = CODEVIEW_SIGNATURE_NB10; | |
643 | strcpy ((PUCHAR)(Nb10 + 1), InImageName); | |
644 | ||
645 | CreateSectionHeader (".debug", DebugOffset, CoffOffset - DebugOffset, | |
646 | EFI_IMAGE_SCN_CNT_INITIALIZED_DATA | |
647 | | EFI_IMAGE_SCN_MEM_DISCARDABLE | |
648 | | EFI_IMAGE_SCN_MEM_READ); | |
649 | ||
650 | NtHdr = (EFI_IMAGE_NT_HEADERS *)(CoffFile + NtHdrOffset); | |
651 | DataDir = &NtHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]; | |
652 | DataDir->VirtualAddress = DebugOffset; | |
653 | DataDir->Size = CoffOffset - DebugOffset; | |
654 | } | |
655 | ||
656 | void | |
657 | ConvertElf ( | |
658 | UINT8 **FileBuffer, | |
659 | UINTN *FileLength | |
660 | ) | |
661 | { | |
662 | EFI_IMAGE_NT_HEADERS *NtHdr; | |
663 | ||
664 | // | |
665 | // Check header, read section table. | |
666 | // | |
667 | Ehdr = (Elf32_Ehdr*)*FileBuffer; | |
668 | if (!CheckElfHeader()) | |
669 | return; | |
670 | ||
671 | // | |
672 | // Compute sections new address. | |
673 | // | |
674 | ScanSections(); | |
675 | ||
676 | // | |
677 | // Write and relocate sections. | |
678 | // | |
679 | WriteSections(IsTextShdr); | |
680 | WriteSections(IsDataShdr); | |
681 | ||
682 | // | |
683 | // Translate and write relocations. | |
684 | // | |
685 | WriteRelocations(); | |
686 | ||
687 | // | |
688 | // Write debug info. | |
689 | // | |
690 | WriteDebug(); | |
691 | ||
692 | NtHdr = (EFI_IMAGE_NT_HEADERS *)(CoffFile + NtHdrOffset); | |
693 | NtHdr->OptionalHeader.SizeOfImage = CoffOffset; | |
694 | ||
695 | // | |
696 | // Replace. | |
697 | // | |
698 | free(*FileBuffer); | |
699 | *FileBuffer = CoffFile; | |
700 | *FileLength = CoffOffset; | |
701 | } | |
702 | #endif // HAVE_ELF | |
703 | ||
704 | int\r | |
705 | main (\r | |
706 | int argc,\r | |
707 | char *argv[]\r | |
708 | )\r | |
709 | /*++\r | |
710 | \r | |
711 | Routine Description:\r | |
712 | \r | |
713 | Main function.\r | |
714 | \r | |
715 | Arguments:\r | |
716 | \r | |
717 | argc - Number of command line parameters.\r | |
718 | argv - Array of pointers to command line parameter strings.\r | |
719 | \r | |
720 | Returns:\r | |
721 | STATUS_SUCCESS - Utility exits successfully.\r | |
722 | STATUS_ERROR - Some error occurred during execution.\r | |
723 | \r | |
724 | --*/\r | |
725 | {\r | |
726 | ULONG Type;\r | |
727 | PUCHAR Ext;\r | |
728 | PUCHAR p;\r | |
729 | PUCHAR pe;\r | |
730 | PUCHAR OutImageName;\r | |
731 | UCHAR outname[500];\r | |
732 | FILE *fpIn;\r | |
733 | FILE *fpOut;\r | |
734 | VOID *ZeroBuffer;\r | |
735 | EFI_IMAGE_DOS_HEADER *DosHdr;\r | |
736 | EFI_IMAGE_NT_HEADERS *PeHdr;\r | |
737 | EFI_IMAGE_OPTIONAL_HEADER32 *Optional32;\r | |
738 | EFI_IMAGE_OPTIONAL_HEADER64 *Optional64;\r | |
739 | time_t TimeStamp;\r | |
740 | struct tm TimeStruct;\r | |
741 | EFI_IMAGE_DOS_HEADER BackupDosHdr;\r | |
742 | ULONG Index;\r | |
743 | ULONG Index1;\r | |
744 | ULONG Index2;\r | |
745 | ULONG Index3;\r | |
746 | BOOLEAN TimeStampPresent;\r | |
747 | UINTN AllignedRelocSize;\r | |
748 | UINTN Delta;\r | |
749 | EFI_IMAGE_SECTION_HEADER *SectionHeader;\r | |
750 | UINT8 *FileBuffer;\r | |
751 | UINTN FileLength;\r | |
752 | RUNTIME_FUNCTION *RuntimeFunction;\r | |
753 | UNWIND_INFO *UnwindInfo;\r | |
754 | \r | |
755 | SetUtilityName (UTILITY_NAME);\r | |
756 | //\r | |
757 | // Assign to fix compile warning\r | |
758 | //\r | |
759 | OutImageName = NULL;\r | |
760 | Type = 0;\r | |
761 | Ext = 0;\r | |
762 | TimeStamp = 0;\r | |
763 | TimeStampPresent = FALSE;\r | |
764 | \r | |
765 | if (argc < 1) {\r | |
766 | Usage();\r | |
767 | return STATUS_ERROR;\r | |
768 | }\r | |
769 | \r | |
770 | if ((strcmp(argv[1], "-h") == 0) || (strcmp(argv[1], "--help") == 0) ||\r | |
771 | (strcmp(argv[1], "-?") == 0) || (strcmp(argv[1], "/?") == 0)) {\r | |
772 | Usage();\r | |
773 | return STATUS_ERROR;\r | |
774 | }\r | |
775 | \r | |
776 | if ((strcmp(argv[1], "-V") == 0) || (strcmp(argv[1], "--version") == 0)) {\r | |
777 | Version();\r | |
778 | return STATUS_ERROR;\r | |
779 | }\r | |
780 | \r | |
781 | //\r | |
782 | // Look for -t time-date option first. If the time is "0", then\r | |
783 | // skip it.\r | |
784 | //\r | |
785 | if ((argc > 2) && !strcmp (argv[1], "-t")) {\r | |
786 | TimeStampPresent = TRUE;\r | |
787 | if (strcmp (argv[2], "0") != 0) {\r | |
788 | //\r | |
789 | // Convert the string to a value\r | |
790 | //\r | |
791 | memset ((char *) &TimeStruct, 0, sizeof (TimeStruct));\r | |
792 | if (sscanf(\r | |
793 | argv[2], "%d/%d/%d,%d:%d:%d",\r | |
794 | &TimeStruct.tm_mon, /* months since January - [0,11] */\r | |
795 | &TimeStruct.tm_mday, /* day of the month - [1,31] */\r | |
796 | &TimeStruct.tm_year, /* years since 1900 */\r | |
797 | &TimeStruct.tm_hour, /* hours since midnight - [0,23] */\r | |
798 | &TimeStruct.tm_min, /* minutes after the hour - [0,59] */\r | |
799 | &TimeStruct.tm_sec /* seconds after the minute - [0,59] */\r | |
800 | ) != 6) {\r | |
801 | Error (NULL, 0, 0, argv[2], "failed to convert to mm/dd/yyyy,hh:mm:ss format");\r | |
802 | return STATUS_ERROR;\r | |
803 | }\r | |
804 | //\r | |
805 | // Now fixup some of the fields\r | |
806 | //\r | |
807 | TimeStruct.tm_mon--;\r | |
808 | TimeStruct.tm_year -= 1900;\r | |
809 | //\r | |
810 | // Sanity-check values?\r | |
811 | // Convert\r | |
812 | //\r | |
813 | TimeStamp = mktime (&TimeStruct);\r | |
814 | if (TimeStamp == (time_t) - 1) {\r | |
815 | Error (NULL, 0, 0, argv[2], "failed to convert time");\r | |
816 | return STATUS_ERROR;\r | |
817 | }\r | |
818 | }\r | |
819 | //\r | |
820 | // Skip over the args\r | |
821 | //\r | |
822 | argc -= 2;\r | |
823 | argv += 2;\r | |
824 | }\r | |
825 | //\r | |
826 | // Check for enough args\r | |
827 | //\r | |
828 | if (argc < 3) {\r | |
829 | Usage ();\r | |
830 | return STATUS_ERROR;\r | |
831 | }\r | |
832 | \r | |
833 | InImageName = argv[2];\r | |
834 | \r | |
835 | if (argc == 4) {\r | |
836 | OutImageName = argv[3];\r | |
837 | }\r | |
838 | //\r | |
839 | // Get new image type\r | |
840 | //\r | |
841 | p = argv[1];\r | |
842 | if (*p == '/' || *p == '\\') {\r | |
843 | p += 1;\r | |
844 | }\r | |
845 | \r | |
846 | if (stricmp (p, "app") == 0 || stricmp (p, "UEFI_APPLICATION") == 0) {\r | |
847 | Type = EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION;\r | |
848 | Ext = ".efi";\r | |
849 | \r | |
850 | } else if (stricmp (p, "bsdrv") == 0 || stricmp (p, "DXE_DRIVER") == 0) {\r | |
851 | Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER;\r | |
852 | Ext = ".efi";\r | |
853 | \r | |
854 | } else if (stricmp (p, "rtdrv") == 0 || stricmp (p, "DXE_RUNTIME_DRIVER") == 0) {\r | |
855 | Type = EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER;\r | |
856 | Ext = ".efi";\r | |
857 | \r | |
858 | } else if (stricmp (p, "rtdrv") == 0 || stricmp (p, "DXE_SAL_DRIVER") == 0) {\r | |
859 | Type = EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER;\r | |
860 | Ext = ".efi";\r | |
861 | } else if (stricmp (p, "SEC") == 0) {\r | |
862 | Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER;\r | |
863 | Ext = ".sec";\r | |
864 | } else if (stricmp (p, "peim") == 0 ||\r | |
865 | stricmp (p, "BASE") == 0 ||\r | |
866 | stricmp (p, "PEI_CORE") == 0 ||\r | |
867 | stricmp (p, "PEIM") == 0 ||\r | |
868 | stricmp (p, "DXE_SMM_DRIVER") == 0 ||\r | |
869 | stricmp (p, "TOOL") == 0 ||\r | |
870 | stricmp (p, "UEFI_APPLICATION") == 0 ||\r | |
871 | stricmp (p, "USER_DEFINED") == 0 ||\r | |
872 | stricmp (p, "UEFI_DRIVER") == 0 ||\r | |
873 | stricmp (p, "DXE_CORE") == 0\r | |
874 | ) {\r | |
875 | Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER;\r | |
876 | Ext = ".pei";\r | |
877 | } else {\r | |
878 | printf ("%s", p);\r | |
879 | Usage ();\r | |
880 | return STATUS_ERROR;\r | |
881 | }\r | |
882 | //\r | |
883 | // open source file\r | |
884 | //\r | |
885 | fpIn = fopen (InImageName, "rb");\r | |
886 | if (!fpIn) {\r | |
887 | Error (NULL, 0, 0, InImageName, "failed to open input file for reading");\r | |
888 | return STATUS_ERROR;\r | |
889 | }\r | |
890 | \r | |
891 | FReadFile (fpIn, (VOID **)&FileBuffer, &FileLength);\r | |
892 | \r | |
893 | #ifdef HAVE_ELF | |
894 | if (IsElfHeader(FileBuffer)) { | |
895 | ConvertElf(&FileBuffer, &FileLength); | |
896 | } | |
897 | #endif | |
898 | //\r | |
899 | // Read the dos & pe hdrs of the image\r | |
900 | //\r | |
901 | DosHdr = (EFI_IMAGE_DOS_HEADER *)FileBuffer;\r | |
902 | if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {\r | |
903 | Error (NULL, 0, 0, InImageName, "DOS header signature not found in source image");\r | |
904 | fclose (fpIn);\r | |
905 | return STATUS_ERROR;\r | |
906 | }\r | |
907 | \r | |
908 | PeHdr = (EFI_IMAGE_NT_HEADERS *)(FileBuffer + DosHdr->e_lfanew);\r | |
909 | if (PeHdr->Signature != EFI_IMAGE_NT_SIGNATURE) {\r | |
910 | Error (NULL, 0, 0, InImageName, "PE header signature not found in source image");\r | |
911 | fclose (fpIn);\r | |
912 | return STATUS_ERROR;\r | |
913 | }\r | |
914 | \r | |
915 | //\r | |
916 | // open output file\r | |
917 | //\r | |
918 | strcpy (outname, InImageName);\r | |
919 | pe = NULL;\r | |
920 | for (p = outname; *p; p++) {\r | |
921 | if (*p == '.') {\r | |
922 | pe = p;\r | |
923 | }\r | |
924 | }\r | |
925 | \r | |
926 | if (!pe) {\r | |
927 | pe = p;\r | |
928 | }\r | |
929 | \r | |
930 | strcpy (pe, Ext);\r | |
931 | \r | |
932 | if (!OutImageName) {\r | |
933 | OutImageName = outname;\r | |
934 | }\r | |
935 | \r | |
936 | fpOut = fopen (OutImageName, "w+b");\r | |
937 | if (!fpOut) {\r | |
938 | Error (NULL, 0, 0, OutImageName, "could not open output file for writing");\r | |
939 | fclose (fpIn);\r | |
940 | return STATUS_ERROR;\r | |
941 | }\r | |
942 | \r | |
943 | //\r | |
944 | // Zero all unused fields of the DOS header\r | |
945 | //\r | |
946 | memcpy (&BackupDosHdr, DosHdr, sizeof (EFI_IMAGE_DOS_HEADER));\r | |
947 | memset (DosHdr, 0, sizeof (EFI_IMAGE_DOS_HEADER));\r | |
948 | DosHdr->e_magic = BackupDosHdr.e_magic;\r | |
949 | DosHdr->e_lfanew = BackupDosHdr.e_lfanew;\r | |
950 | \r | |
951 | for (Index = sizeof (EFI_IMAGE_DOS_HEADER); Index < (ULONG) DosHdr->e_lfanew; Index++) {\r | |
952 | FileBuffer[Index] = DosHdr->e_cp;\r | |
953 | }\r | |
954 | \r | |
955 | //\r | |
956 | // Patch the PE header\r | |
957 | //\r | |
958 | PeHdr->OptionalHeader.Subsystem = (USHORT) Type;\r | |
959 | if (TimeStampPresent) {\r | |
960 | PeHdr->FileHeader.TimeDateStamp = (UINT32) TimeStamp;\r | |
961 | }\r | |
962 | \r | |
963 | if (PeHdr->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r | |
964 | Optional32 = (EFI_IMAGE_OPTIONAL_HEADER32 *)&PeHdr->OptionalHeader;\r | |
965 | Optional32->MajorLinkerVersion = 0;\r | |
966 | Optional32->MinorLinkerVersion = 0;\r | |
967 | Optional32->MajorOperatingSystemVersion = 0;\r | |
968 | Optional32->MinorOperatingSystemVersion = 0;\r | |
969 | Optional32->MajorImageVersion = 0;\r | |
970 | Optional32->MinorImageVersion = 0;\r | |
971 | Optional32->MajorSubsystemVersion = 0;\r | |
972 | Optional32->MinorSubsystemVersion = 0;\r | |
973 | Optional32->Win32VersionValue = 0;\r | |
974 | Optional32->CheckSum = 0;\r | |
975 | Optional32->SizeOfStackReserve = 0;\r | |
976 | Optional32->SizeOfStackCommit = 0;\r | |
977 | Optional32->SizeOfHeapReserve = 0;\r | |
978 | Optional32->SizeOfHeapCommit = 0;\r | |
979 | \r | |
980 | //\r | |
981 | // Strip zero padding at the end of the .reloc section \r | |
982 | //\r | |
983 | if (Optional32->NumberOfRvaAndSizes >= 6) {\r | |
984 | if (Optional32->DataDirectory[5].Size != 0) {\r | |
985 | SectionHeader = (EFI_IMAGE_SECTION_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof(UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + PeHdr->FileHeader.SizeOfOptionalHeader);\r | |
986 | for (Index = 0; Index < PeHdr->FileHeader.NumberOfSections; Index++, SectionHeader++) {\r | |
987 | //\r | |
988 | // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory\r | |
989 | //\r | |
990 | if (SectionHeader->VirtualAddress == Optional32->DataDirectory[5].VirtualAddress) {\r | |
991 | SectionHeader->Misc.VirtualSize = Optional32->DataDirectory[5].Size;\r | |
992 | AllignedRelocSize = (Optional32->DataDirectory[5].Size + Optional32->FileAlignment - 1) & (~(Optional32->FileAlignment - 1));\r | |
993 | //\r | |
994 | // Check to see if there is zero padding at the end of the base relocations\r | |
995 | //\r | |
996 | if (AllignedRelocSize < SectionHeader->SizeOfRawData) {\r | |
997 | //\r | |
998 | // Check to see if the base relocations are at the end of the file\r | |
999 | //\r | |
1000 | if (SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData == Optional32->SizeOfImage) {\r | |
1001 | //\r | |
1002 | // All the required conditions are met to strip the zero padding of the end of the base relocations section\r | |
1003 | //\r | |
1004 | Optional32->SizeOfImage -= (SectionHeader->SizeOfRawData - AllignedRelocSize);\r | |
1005 | Optional32->SizeOfInitializedData -= (SectionHeader->SizeOfRawData - AllignedRelocSize);\r | |
1006 | SectionHeader->SizeOfRawData = AllignedRelocSize;\r | |
1007 | FileLength = Optional32->SizeOfImage;\r | |
1008 | }\r | |
1009 | }\r | |
1010 | }\r | |
1011 | }\r | |
1012 | }\r | |
1013 | }\r | |
1014 | } \r | |
1015 | if (PeHdr->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r | |
1016 | Optional64 = (EFI_IMAGE_OPTIONAL_HEADER64 *)&PeHdr->OptionalHeader;\r | |
1017 | Optional64->MajorLinkerVersion = 0;\r | |
1018 | Optional64->MinorLinkerVersion = 0;\r | |
1019 | Optional64->MajorOperatingSystemVersion = 0;\r | |
1020 | Optional64->MinorOperatingSystemVersion = 0;\r | |
1021 | Optional64->MajorImageVersion = 0;\r | |
1022 | Optional64->MinorImageVersion = 0;\r | |
1023 | Optional64->MajorSubsystemVersion = 0;\r | |
1024 | Optional64->MinorSubsystemVersion = 0;\r | |
1025 | Optional64->Win32VersionValue = 0;\r | |
1026 | Optional64->CheckSum = 0;\r | |
1027 | Optional64->SizeOfStackReserve = 0;\r | |
1028 | Optional64->SizeOfStackCommit = 0;\r | |
1029 | Optional64->SizeOfHeapReserve = 0;\r | |
1030 | Optional64->SizeOfHeapCommit = 0;\r | |
1031 | \r | |
1032 | //\r | |
1033 | // Zero the .pdata section if the machine type is X64 and the Debug Directory is empty\r | |
1034 | //\r | |
1035 | if (PeHdr->FileHeader.Machine == 0x8664) { // X64\r | |
1036 | if (Optional64->NumberOfRvaAndSizes >= 4) {\r | |
1037 | if (Optional64->NumberOfRvaAndSizes < 7 || (Optional64->NumberOfRvaAndSizes >= 7 && Optional64->DataDirectory[6].Size == 0)) {\r | |
1038 | SectionHeader = (EFI_IMAGE_SECTION_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof(UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + PeHdr->FileHeader.SizeOfOptionalHeader);\r | |
1039 | for (Index = 0; Index < PeHdr->FileHeader.NumberOfSections; Index++, SectionHeader++) {\r | |
1040 | if (SectionHeader->VirtualAddress == Optional64->DataDirectory[3].VirtualAddress) {\r | |
1041 | RuntimeFunction = (RUNTIME_FUNCTION *)(FileBuffer + SectionHeader->PointerToRawData);\r | |
1042 | for (Index1 = 0; Index1 < Optional64->DataDirectory[3].Size / sizeof (RUNTIME_FUNCTION); Index1++, RuntimeFunction++) {\r | |
1043 | SectionHeader = (EFI_IMAGE_SECTION_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof(UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + PeHdr->FileHeader.SizeOfOptionalHeader);\r | |
1044 | for (Index2 = 0; Index2 < PeHdr->FileHeader.NumberOfSections; Index2++, SectionHeader++) {\r | |
1045 | if (RuntimeFunction->UnwindInfoAddress > SectionHeader->VirtualAddress && RuntimeFunction->UnwindInfoAddress < (SectionHeader->VirtualAddress + SectionHeader->SizeOfRawData)) {\r | |
1046 | UnwindInfo = (UNWIND_INFO *)(FileBuffer + SectionHeader->PointerToRawData + (RuntimeFunction->UnwindInfoAddress - SectionHeader->VirtualAddress));\r | |
1047 | if (UnwindInfo->Version == 1) {\r | |
1048 | memset (UnwindInfo + 1, 0, UnwindInfo->CountOfUnwindCodes * sizeof (UINT16));\r | |
1049 | memset (UnwindInfo, 0, sizeof (UNWIND_INFO));\r | |
1050 | }\r | |
1051 | }\r | |
1052 | }\r | |
1053 | memset (RuntimeFunction, 0, sizeof (RUNTIME_FUNCTION));\r | |
1054 | }\r | |
1055 | \r | |
1056 | break;\r | |
1057 | }\r | |
1058 | }\r | |
1059 | Optional64->DataDirectory[3].Size = 0;\r | |
1060 | Optional64->DataDirectory[3].VirtualAddress = 0;\r | |
1061 | }\r | |
1062 | }\r | |
1063 | }\r | |
1064 | \r | |
1065 | //\r | |
1066 | // Strip zero padding at the end of the .reloc section \r | |
1067 | //\r | |
1068 | if (Optional64->NumberOfRvaAndSizes >= 6) {\r | |
1069 | if (Optional64->DataDirectory[5].Size != 0) {\r | |
1070 | SectionHeader = (EFI_IMAGE_SECTION_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof(UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + PeHdr->FileHeader.SizeOfOptionalHeader);\r | |
1071 | for (Index = 0; Index < PeHdr->FileHeader.NumberOfSections; Index++, SectionHeader++) {\r | |
1072 | //\r | |
1073 | // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory\r | |
1074 | //\r | |
1075 | if (SectionHeader->VirtualAddress == Optional64->DataDirectory[5].VirtualAddress) {\r | |
1076 | SectionHeader->Misc.VirtualSize = Optional64->DataDirectory[5].Size;\r | |
1077 | AllignedRelocSize = (Optional64->DataDirectory[5].Size + Optional64->FileAlignment - 1) & (~(Optional64->FileAlignment - 1));\r | |
1078 | //\r | |
1079 | // Check to see if there is zero padding at the end of the base relocations\r | |
1080 | //\r | |
1081 | if (AllignedRelocSize < SectionHeader->SizeOfRawData) {\r | |
1082 | //\r | |
1083 | // Check to see if the base relocations are at the end of the file\r | |
1084 | //\r | |
1085 | if (SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData == Optional64->SizeOfImage) {\r | |
1086 | //\r | |
1087 | // All the required conditions are met to strip the zero padding of the end of the base relocations section\r | |
1088 | //\r | |
1089 | Optional64->SizeOfImage -= (SectionHeader->SizeOfRawData - AllignedRelocSize);\r | |
1090 | Optional64->SizeOfInitializedData -= (SectionHeader->SizeOfRawData - AllignedRelocSize);\r | |
1091 | SectionHeader->SizeOfRawData = AllignedRelocSize;\r | |
1092 | FileLength = Optional64->SizeOfImage;\r | |
1093 | }\r | |
1094 | }\r | |
1095 | }\r | |
1096 | }\r | |
1097 | }\r | |
1098 | }\r | |
1099 | }\r | |
1100 | \r | |
1101 | FWriteFile (fpOut, FileBuffer, FileLength);\r | |
1102 | \r | |
1103 | //\r | |
1104 | // Done\r | |
1105 | //\r | |
1106 | fclose (fpIn);\r | |
1107 | fclose (fpOut);\r | |
1108 | //\r | |
1109 | // printf ("Created %s\n", OutImageName);\r | |
1110 | //\r | |
1111 | return STATUS_SUCCESS;\r | |
1112 | }\r |