]>
Commit | Line | Data |
---|---|---|
878ddf1f | 1 | /*++\r |
2 | \r | |
18998564 | 3 | Copyright (c) 2004 - 2007, Intel Corporation \r |
878ddf1f | 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 | |
ce53a8c3 | 22 | #include "WinNtInclude.h"\r |
23 | \r | |
8ba7afaf | 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 | ||
878ddf1f | 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 | |
8ba7afaf | 40 | |
41 | #ifdef HAVE_ELF | |
42 | #include <elf.h> | |
43 | #endif | |
878ddf1f | 44 | \r |
ce53a8c3 | 45 | #include <Common/UefiBaseTypes.h>\r |
46 | #include <Common/EfiImage.h>\r | |
47 | \r | |
48 | #include "CommonLib.h"\r | |
49 | #include "EfiUtilityMsgs.c"\r | |
878ddf1f | 50 | \r |
f091efb3 | 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 | |
878ddf1f | 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 | |
8ba7afaf | 65 | PUCHAR InImageName;\r |
66 | \r | |
f091efb3 | 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 | |
878ddf1f | 78 | VOID\r |
79 | Usage (\r | |
80 | VOID\r | |
81 | )\r | |
82 | {\r | |
f091efb3 | 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 | |
8ba7afaf | 87 | USER_DEFINED] peimage [outimage]\n");\r |
878ddf1f | 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 | |
3edf127e | 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 | |
8ba7afaf | 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 | ) | |
18998564 | 243 | {\r |
8ba7afaf | 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; | |
18998564 | 257 | \r |
258 | //\r | |
259 | // Find the section header table\r | |
260 | // | |
8ba7afaf | 261 | ShdrBase = (Elf_Shdr *)((UINT8 *)Ehdr + Ehdr->e_shoff); |
262 | ||
18998564 | 263 | CoffSectionsOffset = (UINT32 *)malloc(Ehdr->e_shnum * sizeof (UINT32));\r |
264 | ||
265 | memset(CoffSectionsOffset, 0, Ehdr->e_shnum * sizeof(UINT32));\r | |
8ba7afaf | 266 | return 1; |
267 | } | |
268 | ||
269 | int | |
270 | IsTextShdr( | |
271 | Elf_Shdr *Shdr | |
272 | ) | |
273 | { | |
274 | return (Shdr->sh_flags & (SHF_WRITE | SHF_ALLOC)) == SHF_ALLOC; | |
275 | } | |
18998564 | 276 | \r |
8ba7afaf | 277 | int |
278 | IsDataShdr( | |
279 | Elf_Shdr *Shdr | |
280 | ) | |
281 | { | |
282 | return (Shdr->sh_flags & (SHF_WRITE | SHF_ALLOC)) == (SHF_ALLOC | SHF_WRITE); | |
283 | } | |
284 | ||
285 | void | |
286 | CreateSectionHeader( | |
287 | const char *Name, | |
288 | UINT32 Offset, | |
289 | UINT32 Size, | |
290 | UINT32 Flags | |
291 | ) | |
292 | { | |
293 | EFI_IMAGE_SECTION_HEADER *Hdr; | |
294 | Hdr = (EFI_IMAGE_SECTION_HEADER*)(CoffFile + TableOffset); | |
295 | ||
296 | strcpy(Hdr->Name, Name); | |
297 | Hdr->Misc.VirtualSize = Size; | |
298 | Hdr->VirtualAddress = Offset; | |
299 | Hdr->SizeOfRawData = Size; | |
300 | Hdr->PointerToRawData = Offset; | |
301 | Hdr->PointerToRelocations = 0; | |
302 | Hdr->PointerToLinenumbers = 0; | |
303 | Hdr->NumberOfRelocations = 0; | |
304 | Hdr->NumberOfLinenumbers = 0; | |
305 | Hdr->Characteristics = Flags; | |
306 | ||
307 | TableOffset += sizeof (EFI_IMAGE_SECTION_HEADER); | |
308 | } | |
309 | ||
310 | void | |
311 | ScanSections( | |
312 | VOID | |
313 | ) | |
314 | { | |
315 | UINT32 i; | |
316 | EFI_IMAGE_DOS_HEADER *DosHdr; | |
317 | EFI_IMAGE_NT_HEADERS *NtHdr; | |
318 | UINT32 CoffEntry = 0; | |
319 | ||
320 | CoffOffset = 0; | |
321 | ||
322 | // | |
323 | // Coff file start with a DOS header. | |
324 | // | |
325 | CoffOffset = sizeof(EFI_IMAGE_DOS_HEADER) + 0x40; | |
326 | NtHdrOffset = CoffOffset; | |
327 | CoffOffset += sizeof(EFI_IMAGE_NT_HEADERS); | |
328 | TableOffset = CoffOffset; | |
329 | CoffOffset += CoffNbrSections * sizeof(EFI_IMAGE_SECTION_HEADER); | |
330 | ||
331 | // | |
332 | // First text sections. | |
333 | // | |
334 | CoffOffset = CoffAlign(CoffOffset); | |
335 | TextOffset = CoffOffset; | |
336 | for (i = 0; i < Ehdr->e_shnum; i++) { | |
337 | Elf_Shdr *shdr = GetShdrByIndex(i); | |
18998564 | 338 | if (IsTextShdr(shdr)) {\r |
339 | //\r | |
1d6992b9 | 340 | // Align the coff offset to meet with the alignment requirement of section\r |
341 | // itself.\r | |
18998564 | 342 | // \r |
343 | CoffOffset = (CoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1);\r | |
1d6992b9 | 344 | \r |
8ba7afaf | 345 | /* Relocate entry. */ |
18998564 | 346 | if ((Ehdr->e_entry >= shdr->sh_addr) && \r |
347 | (Ehdr->e_entry < shdr->sh_addr + shdr->sh_size)) { | |
348 | CoffEntry = CoffOffset + Ehdr->e_entry - shdr->sh_addr; | |
8ba7afaf | 349 | } |
18998564 | 350 | CoffSectionsOffset[i] = CoffOffset;\r |
8ba7afaf | 351 | CoffOffset += shdr->sh_size; |
18998564 | 352 | }\r |
353 | }\r | |
8ba7afaf | 354 | CoffOffset = CoffAlign(CoffOffset); |
18998564 | 355 | \r |
8ba7afaf | 356 | // |
357 | // Then data sections. | |
358 | // | |
359 | DataOffset = CoffOffset; | |
360 | for (i = 0; i < Ehdr->e_shnum; i++) { | |
361 | Elf_Shdr *shdr = GetShdrByIndex(i); | |
1d6992b9 | 362 | if (IsDataShdr(shdr)) {\r |
363 | //\r | |
364 | // Align the coff offset to meet with the alignment requirement of section\r | |
365 | // itself.\r | |
366 | // \r | |
367 | CoffOffset = (CoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1);\r | |
368 | ||
8ba7afaf | 369 | CoffSectionsOffset[i] = CoffOffset; |
370 | CoffOffset += shdr->sh_size; | |
371 | } | |
372 | } | |
373 | CoffOffset = CoffAlign(CoffOffset); | |
374 | ||
375 | RelocOffset = CoffOffset; | |
376 | ||
377 | // | |
378 | // Allocate base Coff file. Will be expanded later for relocations. | |
379 | // | |
380 | CoffFile = (UINT8 *)malloc(CoffOffset); | |
381 | memset(CoffFile, 0, CoffOffset); | |
382 | ||
383 | // | |
384 | // Fill headers. | |
385 | // | |
386 | DosHdr = (EFI_IMAGE_DOS_HEADER *)CoffFile; | |
387 | DosHdr->e_magic = EFI_IMAGE_DOS_SIGNATURE; | |
388 | DosHdr->e_lfanew = NtHdrOffset; | |
389 | ||
390 | NtHdr = (EFI_IMAGE_NT_HEADERS*)(CoffFile + NtHdrOffset); | |
391 | ||
392 | NtHdr->Signature = EFI_IMAGE_NT_SIGNATURE; | |
393 | ||
394 | NtHdr->FileHeader.Machine = EFI_IMAGE_MACHINE_IA32; | |
395 | NtHdr->FileHeader.NumberOfSections = CoffNbrSections; | |
396 | NtHdr->FileHeader.TimeDateStamp = time(NULL); | |
397 | NtHdr->FileHeader.PointerToSymbolTable = 0; | |
398 | NtHdr->FileHeader.NumberOfSymbols = 0; | |
399 | NtHdr->FileHeader.SizeOfOptionalHeader = sizeof(NtHdr->OptionalHeader); | |
400 | NtHdr->FileHeader.Characteristics = EFI_IMAGE_FILE_EXECUTABLE_IMAGE | |
401 | | EFI_IMAGE_FILE_LINE_NUMS_STRIPPED | |
402 | | EFI_IMAGE_FILE_LOCAL_SYMS_STRIPPED | |
403 | | EFI_IMAGE_FILE_32BIT_MACHINE; | |
404 | ||
405 | NtHdr->OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC; | |
406 | NtHdr->OptionalHeader.SizeOfCode = DataOffset - TextOffset; | |
407 | NtHdr->OptionalHeader.SizeOfInitializedData = RelocOffset - DataOffset; | |
408 | NtHdr->OptionalHeader.SizeOfUninitializedData = 0; | |
409 | NtHdr->OptionalHeader.AddressOfEntryPoint = CoffEntry; | |
410 | NtHdr->OptionalHeader.BaseOfCode = TextOffset; | |
411 | ||
412 | NtHdr->OptionalHeader.BaseOfData = DataOffset; | |
413 | NtHdr->OptionalHeader.ImageBase = 0; | |
414 | NtHdr->OptionalHeader.SectionAlignment = CoffAlignment; | |
415 | NtHdr->OptionalHeader.FileAlignment = CoffAlignment; | |
416 | NtHdr->OptionalHeader.SizeOfImage = 0; | |
417 | ||
418 | NtHdr->OptionalHeader.SizeOfHeaders = TextOffset; | |
419 | NtHdr->OptionalHeader.NumberOfRvaAndSizes = EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES; | |
420 | ||
421 | // | |
422 | // Section headers. | |
423 | // | |
424 | CreateSectionHeader (".text", TextOffset, DataOffset - TextOffset, | |
425 | EFI_IMAGE_SCN_CNT_CODE | |
426 | | EFI_IMAGE_SCN_MEM_EXECUTE | |
427 | | EFI_IMAGE_SCN_MEM_READ); | |
428 | CreateSectionHeader (".data", DataOffset, RelocOffset - DataOffset, | |
429 | EFI_IMAGE_SCN_CNT_INITIALIZED_DATA | |
430 | | EFI_IMAGE_SCN_MEM_WRITE | |
431 | | EFI_IMAGE_SCN_MEM_READ); | |
432 | } | |
433 | ||
434 | void | |
435 | WriteSections( | |
436 | int (*Filter)(Elf_Shdr *) | |
437 | ) | |
438 | { | |
439 | UINT32 Idx; | |
440 | ||
441 | // | |
442 | // First: copy sections. | |
443 | // | |
444 | for (Idx = 0; Idx < Ehdr->e_shnum; Idx++) { | |
445 | Elf_Shdr *Shdr = GetShdrByIndex(Idx); | |
446 | if ((*Filter)(Shdr)) { | |
447 | switch (Shdr->sh_type) { | |
448 | case SHT_PROGBITS: | |
449 | /* Copy. */ | |
450 | memcpy(CoffFile + CoffSectionsOffset[Idx], | |
451 | (UINT8*)Ehdr + Shdr->sh_offset, | |
452 | Shdr->sh_size); | |
453 | break; | |
454 | case SHT_NOBITS: | |
455 | memset(CoffFile + CoffSectionsOffset[Idx], 0, Shdr->sh_size); | |
456 | break; | |
457 | default: | |
458 | Error (NULL, 0, 0, InImageName, "unhandle section type %x", | |
459 | (UINTN)Shdr->sh_type); | |
460 | } | |
461 | } | |
462 | } | |
463 | ||
464 | // | |
465 | // Second: apply relocations. | |
466 | // | |
467 | for (Idx = 0; Idx < Ehdr->e_shnum; Idx++) { | |
468 | Elf_Shdr *RelShdr = GetShdrByIndex(Idx); | |
469 | if (RelShdr->sh_type != SHT_REL) | |
470 | continue; | |
471 | Elf_Shdr *SecShdr = GetShdrByIndex(RelShdr->sh_info); | |
472 | UINT32 SecOffset = CoffSectionsOffset[RelShdr->sh_info]; | |
473 | if (RelShdr->sh_type == SHT_REL && (*Filter)(SecShdr)) { | |
474 | UINT32 RelIdx; | |
475 | Elf_Shdr *SymtabShdr = GetShdrByIndex(RelShdr->sh_link); | |
476 | UINT8 *Symtab = (UINT8*)Ehdr + SymtabShdr->sh_offset; | |
477 | ||
478 | for (RelIdx = 0; RelIdx < RelShdr->sh_size; RelIdx += RelShdr->sh_entsize) { | |
479 | Elf_Rel *Rel = (Elf_Rel *)((UINT8*)Ehdr + RelShdr->sh_offset + RelIdx); | |
480 | Elf_Sym *Sym = (Elf_Sym *) | |
481 | (Symtab + ELF_R_SYM(Rel->r_info) * SymtabShdr->sh_entsize); | |
482 | Elf_Shdr *SymShdr; | |
483 | UINT8 *Targ; | |
484 | ||
485 | if (Sym->st_shndx == SHN_UNDEF | |
486 | || Sym->st_shndx == SHN_ABS | |
487 | || Sym->st_shndx > Ehdr->e_shnum) { | |
488 | Error (NULL, 0, 0, InImageName, "bad symbol definition"); | |
489 | } | |
490 | SymShdr = GetShdrByIndex(Sym->st_shndx); | |
491 | ||
492 | // | |
493 | // Note: r_offset in a memory address. | |
494 | // Convert it to a pointer in the coff file. | |
495 | // | |
496 | Targ = CoffFile + SecOffset + (Rel->r_offset - SecShdr->sh_addr); | |
497 | ||
498 | switch (ELF_R_TYPE(Rel->r_info)) { | |
499 | case R_386_NONE: | |
500 | break; | |
501 | case R_386_32: | |
502 | // | |
503 | // Absolute relocation. | |
504 | // | |
505 | *(UINT32 *)Targ = *(UINT32 *)Targ - SymShdr->sh_addr | |
506 | + CoffSectionsOffset[Sym->st_shndx]; | |
507 | break; | |
508 | case R_386_PC32: | |
509 | // | |
510 | // Relative relocation: Symbol - Ip + Addend | |
511 | // | |
512 | *(UINT32 *)Targ = *(UINT32 *)Targ | |
513 | + (CoffSectionsOffset[Sym->st_shndx] - SymShdr->sh_addr) | |
514 | - (SecOffset - SecShdr->sh_addr); | |
515 | break; | |
516 | default: | |
517 | Error (NULL, 0, 0, InImageName, "unhandled relocation type %x", | |
518 | ELF_R_TYPE(Rel->r_info)); | |
519 | } | |
520 | } | |
521 | } | |
522 | } | |
523 | } | |
524 | ||
525 | void | |
526 | CoffAddFixupEntry( | |
527 | UINT16 Val | |
528 | ) | |
529 | { | |
530 | *CoffEntryRel = Val; | |
531 | CoffEntryRel++; | |
532 | CoffBaseRel->SizeOfBlock += 2; | |
533 | CoffOffset += 2; | |
534 | } | |
535 | ||
536 | void | |
537 | CoffAddFixup( | |
538 | UINT32 Offset, | |
539 | UINT8 Type | |
540 | ) | |
541 | { | |
542 | if (CoffBaseRel == NULL | |
543 | || CoffBaseRel->VirtualAddress != (Offset & ~0xfff)) { | |
544 | if (CoffBaseRel != NULL) { | |
545 | // | |
546 | // Add a null entry (is it required ?) | |
547 | // | |
548 | CoffAddFixupEntry (0); | |
549 | // | |
550 | // Pad for alignment. | |
551 | // | |
552 | if (CoffOffset % 4 != 0) | |
553 | CoffAddFixupEntry (0); | |
554 | } | |
555 | ||
556 | CoffFile = realloc | |
557 | (CoffFile, | |
558 | CoffOffset + sizeof(EFI_IMAGE_BASE_RELOCATION) + 2*0x1000); | |
559 | memset(CoffFile + CoffOffset, 0, | |
560 | sizeof(EFI_IMAGE_BASE_RELOCATION) + 2*0x1000); | |
561 | ||
562 | CoffBaseRel = (EFI_IMAGE_BASE_RELOCATION*)(CoffFile + CoffOffset); | |
563 | CoffBaseRel->VirtualAddress = Offset & ~0xfff; | |
564 | CoffBaseRel->SizeOfBlock = sizeof(EFI_IMAGE_BASE_RELOCATION); | |
565 | ||
566 | CoffEntryRel = (UINT16 *)(CoffBaseRel + 1); | |
567 | CoffOffset += sizeof(EFI_IMAGE_BASE_RELOCATION); | |
568 | } | |
569 | ||
570 | // | |
571 | // Fill the entry. | |
572 | // | |
573 | CoffAddFixupEntry((Type << 12) | (Offset & 0xfff)); | |
574 | } | |
575 | ||
576 | void | |
577 | WriteRelocations( | |
578 | VOID | |
579 | ) | |
580 | { | |
581 | UINT32 Idx; | |
582 | EFI_IMAGE_NT_HEADERS *NtHdr; | |
583 | EFI_IMAGE_DATA_DIRECTORY *Dir; | |
584 | ||
585 | for (Idx = 0; Idx < Ehdr->e_shnum; Idx++) { | |
586 | Elf_Shdr *RelShdr = GetShdrByIndex(Idx); | |
587 | if (RelShdr->sh_type == SHT_REL) { | |
588 | Elf_Shdr *SecShdr = GetShdrByIndex(RelShdr->sh_info); | |
589 | if (IsTextShdr(SecShdr) || IsDataShdr(SecShdr)) { | |
590 | UINT32 RelIdx; | |
591 | for (RelIdx = 0; RelIdx < RelShdr->sh_size; RelIdx += RelShdr->sh_entsize) { | |
592 | Elf_Rel *Rel = (Elf_Rel *) | |
593 | ((UINT8*)Ehdr + RelShdr->sh_offset + RelIdx); | |
594 | switch (ELF_R_TYPE(Rel->r_info)) { | |
595 | case R_386_NONE: | |
596 | case R_386_PC32: | |
597 | break; | |
598 | case R_386_32: | |
599 | CoffAddFixup(CoffSectionsOffset[RelShdr->sh_info] | |
600 | + (Rel->r_offset - SecShdr->sh_addr), | |
601 | EFI_IMAGE_REL_BASED_HIGHLOW); | |
602 | break; | |
603 | default: | |
604 | Error (NULL, 0, 0, InImageName, "unhandled relocation type %x", | |
605 | ELF_R_TYPE(Rel->r_info)); | |
606 | } | |
607 | } | |
608 | } | |
609 | } | |
610 | } | |
611 | ||
612 | // | |
613 | // Pad by adding empty entries. | |
614 | // | |
615 | while (CoffOffset & (CoffAlignment - 1)) { | |
616 | CoffAddFixupEntry(0); | |
617 | } | |
618 | ||
619 | CreateSectionHeader (".reloc", RelocOffset, CoffOffset - RelocOffset, | |
620 | EFI_IMAGE_SCN_CNT_INITIALIZED_DATA | |
621 | | EFI_IMAGE_SCN_MEM_DISCARDABLE | |
622 | | EFI_IMAGE_SCN_MEM_READ); | |
623 | ||
624 | NtHdr = (EFI_IMAGE_NT_HEADERS *)(CoffFile + NtHdrOffset); | |
625 | Dir = &NtHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC]; | |
626 | Dir->VirtualAddress = RelocOffset; | |
627 | Dir->Size = CoffOffset - RelocOffset; | |
628 | } | |
629 | ||
630 | void | |
631 | WriteDebug( | |
632 | VOID | |
633 | ) | |
634 | { | |
635 | UINT32 Len = strlen(InImageName) + 1; | |
636 | UINT32 DebugOffset = CoffOffset; | |
637 | EFI_IMAGE_NT_HEADERS *NtHdr; | |
638 | EFI_IMAGE_DATA_DIRECTORY *DataDir; | |
639 | EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *Dir; | |
640 | EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY *Nb10; | |
641 | ||
642 | CoffOffset += sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY) | |
643 | + sizeof(EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY) | |
644 | + Len; | |
645 | CoffOffset = CoffAlign(CoffOffset); | |
646 | ||
647 | CoffFile = realloc | |
648 | (CoffFile, CoffOffset); | |
649 | memset(CoffFile + DebugOffset, 0, CoffOffset - DebugOffset); | |
650 | ||
651 | Dir = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY*)(CoffFile + DebugOffset); | |
652 | Dir->Type = EFI_IMAGE_DEBUG_TYPE_CODEVIEW; | |
653 | Dir->SizeOfData = sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY) + Len; | |
654 | Dir->RVA = DebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY); | |
655 | Dir->FileOffset = DebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY); | |
656 | ||
657 | Nb10 = (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY*)(Dir + 1); | |
658 | Nb10->Signature = CODEVIEW_SIGNATURE_NB10; | |
659 | strcpy ((PUCHAR)(Nb10 + 1), InImageName); | |
660 | ||
661 | CreateSectionHeader (".debug", DebugOffset, CoffOffset - DebugOffset, | |
662 | EFI_IMAGE_SCN_CNT_INITIALIZED_DATA | |
663 | | EFI_IMAGE_SCN_MEM_DISCARDABLE | |
664 | | EFI_IMAGE_SCN_MEM_READ); | |
665 | ||
666 | NtHdr = (EFI_IMAGE_NT_HEADERS *)(CoffFile + NtHdrOffset); | |
667 | DataDir = &NtHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]; | |
668 | DataDir->VirtualAddress = DebugOffset; | |
669 | DataDir->Size = CoffOffset - DebugOffset; | |
670 | } | |
671 | ||
672 | void | |
673 | ConvertElf ( | |
674 | UINT8 **FileBuffer, | |
675 | UINTN *FileLength | |
676 | ) | |
677 | { | |
678 | EFI_IMAGE_NT_HEADERS *NtHdr; | |
679 | ||
680 | // | |
681 | // Check header, read section table. | |
682 | // | |
683 | Ehdr = (Elf32_Ehdr*)*FileBuffer; | |
684 | if (!CheckElfHeader()) | |
685 | return; | |
686 | ||
687 | // | |
688 | // Compute sections new address. | |
689 | // | |
690 | ScanSections(); | |
691 | ||
692 | // | |
693 | // Write and relocate sections. | |
694 | // | |
695 | WriteSections(IsTextShdr); | |
696 | WriteSections(IsDataShdr); | |
697 | ||
698 | // | |
699 | // Translate and write relocations. | |
700 | // | |
701 | WriteRelocations(); | |
702 | ||
703 | // | |
704 | // Write debug info. | |
705 | // | |
706 | WriteDebug(); | |
707 | ||
708 | NtHdr = (EFI_IMAGE_NT_HEADERS *)(CoffFile + NtHdrOffset); | |
709 | NtHdr->OptionalHeader.SizeOfImage = CoffOffset; | |
710 | ||
711 | // | |
712 | // Replace. | |
713 | // | |
714 | free(*FileBuffer); | |
715 | *FileBuffer = CoffFile; | |
716 | *FileLength = CoffOffset; | |
717 | } | |
718 | #endif // HAVE_ELF | |
719 | ||
878ddf1f | 720 | int\r |
721 | main (\r | |
722 | int argc,\r | |
723 | char *argv[]\r | |
724 | )\r | |
725 | /*++\r | |
726 | \r | |
727 | Routine Description:\r | |
728 | \r | |
729 | Main function.\r | |
730 | \r | |
731 | Arguments:\r | |
732 | \r | |
733 | argc - Number of command line parameters.\r | |
734 | argv - Array of pointers to command line parameter strings.\r | |
735 | \r | |
736 | Returns:\r | |
737 | STATUS_SUCCESS - Utility exits successfully.\r | |
738 | STATUS_ERROR - Some error occurred during execution.\r | |
739 | \r | |
740 | --*/\r | |
741 | {\r | |
742 | ULONG Type;\r | |
743 | PUCHAR Ext;\r | |
744 | PUCHAR p;\r | |
745 | PUCHAR pe;\r | |
746 | PUCHAR OutImageName;\r | |
747 | UCHAR outname[500];\r | |
748 | FILE *fpIn;\r | |
749 | FILE *fpOut;\r | |
3edf127e | 750 | VOID *ZeroBuffer;\r |
751 | EFI_IMAGE_DOS_HEADER *DosHdr;\r | |
752 | EFI_IMAGE_NT_HEADERS *PeHdr;\r | |
753 | EFI_IMAGE_OPTIONAL_HEADER32 *Optional32;\r | |
754 | EFI_IMAGE_OPTIONAL_HEADER64 *Optional64;\r | |
878ddf1f | 755 | time_t TimeStamp;\r |
756 | struct tm TimeStruct;\r | |
757 | EFI_IMAGE_DOS_HEADER BackupDosHdr;\r | |
758 | ULONG Index;\r | |
3edf127e | 759 | ULONG Index1;\r |
307fd197 | 760 | ULONG Index2;\r |
761 | ULONG Index3;\r | |
878ddf1f | 762 | BOOLEAN TimeStampPresent;\r |
0411bcaf | 763 | UINTN AllignedRelocSize;\r |
3edf127e | 764 | UINTN Delta;\r |
765 | EFI_IMAGE_SECTION_HEADER *SectionHeader;\r | |
766 | UINT8 *FileBuffer;\r | |
767 | UINTN FileLength;\r | |
307fd197 | 768 | RUNTIME_FUNCTION *RuntimeFunction;\r |
769 | UNWIND_INFO *UnwindInfo;\r | |
878ddf1f | 770 | \r |
771 | SetUtilityName (UTILITY_NAME);\r | |
772 | //\r | |
773 | // Assign to fix compile warning\r | |
774 | //\r | |
775 | OutImageName = NULL;\r | |
776 | Type = 0;\r | |
777 | Ext = 0;\r | |
778 | TimeStamp = 0;\r | |
779 | TimeStampPresent = FALSE;\r | |
780 | \r | |
db608e6b | 781 | if (argc == 1) {\r |
f091efb3 | 782 | Usage();\r |
783 | return STATUS_ERROR;\r | |
784 | }\r | |
785 | \r | |
786 | if ((strcmp(argv[1], "-h") == 0) || (strcmp(argv[1], "--help") == 0) ||\r | |
787 | (strcmp(argv[1], "-?") == 0) || (strcmp(argv[1], "/?") == 0)) {\r | |
788 | Usage();\r | |
789 | return STATUS_ERROR;\r | |
790 | }\r | |
791 | \r | |
792 | if ((strcmp(argv[1], "-V") == 0) || (strcmp(argv[1], "--version") == 0)) {\r | |
793 | Version();\r | |
794 | return STATUS_ERROR;\r | |
795 | }\r | |
796 | \r | |
878ddf1f | 797 | //\r |
798 | // Look for -t time-date option first. If the time is "0", then\r | |
799 | // skip it.\r | |
800 | //\r | |
801 | if ((argc > 2) && !strcmp (argv[1], "-t")) {\r | |
802 | TimeStampPresent = TRUE;\r | |
803 | if (strcmp (argv[2], "0") != 0) {\r | |
804 | //\r | |
805 | // Convert the string to a value\r | |
806 | //\r | |
807 | memset ((char *) &TimeStruct, 0, sizeof (TimeStruct));\r | |
808 | if (sscanf(\r | |
809 | argv[2], "%d/%d/%d,%d:%d:%d",\r | |
810 | &TimeStruct.tm_mon, /* months since January - [0,11] */\r | |
811 | &TimeStruct.tm_mday, /* day of the month - [1,31] */\r | |
812 | &TimeStruct.tm_year, /* years since 1900 */\r | |
813 | &TimeStruct.tm_hour, /* hours since midnight - [0,23] */\r | |
814 | &TimeStruct.tm_min, /* minutes after the hour - [0,59] */\r | |
815 | &TimeStruct.tm_sec /* seconds after the minute - [0,59] */\r | |
816 | ) != 6) {\r | |
817 | Error (NULL, 0, 0, argv[2], "failed to convert to mm/dd/yyyy,hh:mm:ss format");\r | |
818 | return STATUS_ERROR;\r | |
819 | }\r | |
820 | //\r | |
821 | // Now fixup some of the fields\r | |
822 | //\r | |
823 | TimeStruct.tm_mon--;\r | |
824 | TimeStruct.tm_year -= 1900;\r | |
825 | //\r | |
826 | // Sanity-check values?\r | |
827 | // Convert\r | |
828 | //\r | |
829 | TimeStamp = mktime (&TimeStruct);\r | |
830 | if (TimeStamp == (time_t) - 1) {\r | |
831 | Error (NULL, 0, 0, argv[2], "failed to convert time");\r | |
832 | return STATUS_ERROR;\r | |
833 | }\r | |
834 | }\r | |
835 | //\r | |
836 | // Skip over the args\r | |
837 | //\r | |
838 | argc -= 2;\r | |
839 | argv += 2;\r | |
840 | }\r | |
841 | //\r | |
842 | // Check for enough args\r | |
843 | //\r | |
844 | if (argc < 3) {\r | |
845 | Usage ();\r | |
846 | return STATUS_ERROR;\r | |
847 | }\r | |
848 | \r | |
8ba7afaf | 849 | InImageName = argv[2];\r |
850 | \r | |
878ddf1f | 851 | if (argc == 4) {\r |
852 | OutImageName = argv[3];\r | |
853 | }\r | |
854 | //\r | |
855 | // Get new image type\r | |
856 | //\r | |
857 | p = argv[1];\r | |
858 | if (*p == '/' || *p == '\\') {\r | |
859 | p += 1;\r | |
860 | }\r | |
861 | \r | |
8a286638 | 862 | if (stricmp (p, "app") == 0 || stricmp (p, "UEFI_APPLICATION") == 0) {\r |
878ddf1f | 863 | Type = EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION;\r |
864 | Ext = ".efi";\r | |
865 | \r | |
8a286638 | 866 | } else if (stricmp (p, "bsdrv") == 0 || stricmp (p, "DXE_DRIVER") == 0) {\r |
878ddf1f | 867 | Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER;\r |
868 | Ext = ".efi";\r | |
869 | \r | |
8a286638 | 870 | } else if (stricmp (p, "rtdrv") == 0 || stricmp (p, "DXE_RUNTIME_DRIVER") == 0) {\r |
878ddf1f | 871 | Type = EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER;\r |
872 | Ext = ".efi";\r | |
873 | \r | |
8a286638 | 874 | } else if (stricmp (p, "rtdrv") == 0 || stricmp (p, "DXE_SAL_DRIVER") == 0) {\r |
878ddf1f | 875 | Type = EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER;\r |
876 | Ext = ".efi";\r | |
8a286638 | 877 | } else if (stricmp (p, "SEC") == 0) {\r |
878ddf1f | 878 | Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER;\r |
879 | Ext = ".sec";\r | |
880 | } else if (stricmp (p, "peim") == 0 ||\r | |
8a286638 | 881 | stricmp (p, "BASE") == 0 ||\r |
878ddf1f | 882 | stricmp (p, "PEI_CORE") == 0 ||\r |
8a286638 | 883 | stricmp (p, "PEIM") == 0 ||\r |
884 | stricmp (p, "DXE_SMM_DRIVER") == 0 ||\r | |
885 | stricmp (p, "TOOL") == 0 ||\r | |
886 | stricmp (p, "UEFI_APPLICATION") == 0 ||\r | |
887 | stricmp (p, "USER_DEFINED") == 0 ||\r | |
888 | stricmp (p, "UEFI_DRIVER") == 0 ||\r | |
889 | stricmp (p, "DXE_CORE") == 0\r | |
878ddf1f | 890 | ) {\r |
891 | Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER;\r | |
892 | Ext = ".pei";\r | |
893 | } else {\r | |
8a286638 | 894 | printf ("%s", p);\r |
878ddf1f | 895 | Usage ();\r |
896 | return STATUS_ERROR;\r | |
897 | }\r | |
898 | //\r | |
899 | // open source file\r | |
900 | //\r | |
8ba7afaf | 901 | fpIn = fopen (InImageName, "rb");\r |
878ddf1f | 902 | if (!fpIn) {\r |
8ba7afaf | 903 | Error (NULL, 0, 0, InImageName, "failed to open input file for reading");\r |
878ddf1f | 904 | return STATUS_ERROR;\r |
905 | }\r | |
3edf127e | 906 | \r |
907 | FReadFile (fpIn, (VOID **)&FileBuffer, &FileLength);\r | |
908 | \r | |
8ba7afaf | 909 | #ifdef HAVE_ELF |
910 | if (IsElfHeader(FileBuffer)) { | |
911 | ConvertElf(&FileBuffer, &FileLength); | |
912 | } | |
913 | #endif | |
878ddf1f | 914 | //\r |
915 | // Read the dos & pe hdrs of the image\r | |
916 | //\r | |
3edf127e | 917 | DosHdr = (EFI_IMAGE_DOS_HEADER *)FileBuffer;\r |
918 | if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {\r | |
8ba7afaf | 919 | Error (NULL, 0, 0, InImageName, "DOS header signature not found in source image");\r |
878ddf1f | 920 | fclose (fpIn);\r |
921 | return STATUS_ERROR;\r | |
922 | }\r | |
923 | \r | |
3edf127e | 924 | PeHdr = (EFI_IMAGE_NT_HEADERS *)(FileBuffer + DosHdr->e_lfanew);\r |
925 | if (PeHdr->Signature != EFI_IMAGE_NT_SIGNATURE) {\r | |
8ba7afaf | 926 | Error (NULL, 0, 0, InImageName, "PE header signature not found in source image");\r |
878ddf1f | 927 | fclose (fpIn);\r |
928 | return STATUS_ERROR;\r | |
929 | }\r | |
3edf127e | 930 | \r |
878ddf1f | 931 | //\r |
932 | // open output file\r | |
933 | //\r | |
8ba7afaf | 934 | strcpy (outname, InImageName);\r |
878ddf1f | 935 | pe = NULL;\r |
936 | for (p = outname; *p; p++) {\r | |
937 | if (*p == '.') {\r | |
938 | pe = p;\r | |
939 | }\r | |
940 | }\r | |
941 | \r | |
942 | if (!pe) {\r | |
943 | pe = p;\r | |
944 | }\r | |
945 | \r | |
946 | strcpy (pe, Ext);\r | |
947 | \r | |
948 | if (!OutImageName) {\r | |
949 | OutImageName = outname;\r | |
950 | }\r | |
951 | \r | |
952 | fpOut = fopen (OutImageName, "w+b");\r | |
953 | if (!fpOut) {\r | |
954 | Error (NULL, 0, 0, OutImageName, "could not open output file for writing");\r | |
955 | fclose (fpIn);\r | |
956 | return STATUS_ERROR;\r | |
957 | }\r | |
3edf127e | 958 | \r |
878ddf1f | 959 | //\r |
960 | // Zero all unused fields of the DOS header\r | |
961 | //\r | |
3edf127e | 962 | memcpy (&BackupDosHdr, DosHdr, sizeof (EFI_IMAGE_DOS_HEADER));\r |
963 | memset (DosHdr, 0, sizeof (EFI_IMAGE_DOS_HEADER));\r | |
964 | DosHdr->e_magic = BackupDosHdr.e_magic;\r | |
965 | DosHdr->e_lfanew = BackupDosHdr.e_lfanew;\r | |
966 | \r | |
967 | for (Index = sizeof (EFI_IMAGE_DOS_HEADER); Index < (ULONG) DosHdr->e_lfanew; Index++) {\r | |
968 | FileBuffer[Index] = DosHdr->e_cp;\r | |
878ddf1f | 969 | }\r |
3edf127e | 970 | \r |
878ddf1f | 971 | //\r |
8ba7afaf | 972 | // Patch the PE header\r |
878ddf1f | 973 | //\r |
3edf127e | 974 | PeHdr->OptionalHeader.Subsystem = (USHORT) Type;\r |
878ddf1f | 975 | if (TimeStampPresent) {\r |
3edf127e | 976 | PeHdr->FileHeader.TimeDateStamp = (UINT32) TimeStamp;\r |
977 | }\r | |
978 | \r | |
3edf127e | 979 | if (PeHdr->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r |
980 | Optional32 = (EFI_IMAGE_OPTIONAL_HEADER32 *)&PeHdr->OptionalHeader;\r | |
981 | Optional32->MajorLinkerVersion = 0;\r | |
982 | Optional32->MinorLinkerVersion = 0;\r | |
983 | Optional32->MajorOperatingSystemVersion = 0;\r | |
984 | Optional32->MinorOperatingSystemVersion = 0;\r | |
985 | Optional32->MajorImageVersion = 0;\r | |
986 | Optional32->MinorImageVersion = 0;\r | |
987 | Optional32->MajorSubsystemVersion = 0;\r | |
988 | Optional32->MinorSubsystemVersion = 0;\r | |
989 | Optional32->Win32VersionValue = 0;\r | |
990 | Optional32->CheckSum = 0;\r | |
991 | Optional32->SizeOfStackReserve = 0;\r | |
992 | Optional32->SizeOfStackCommit = 0;\r | |
993 | Optional32->SizeOfHeapReserve = 0;\r | |
994 | Optional32->SizeOfHeapCommit = 0;\r | |
995 | \r | |
3edf127e | 996 | //\r |
997 | // Strip zero padding at the end of the .reloc section \r | |
998 | //\r | |
999 | if (Optional32->NumberOfRvaAndSizes >= 6) {\r | |
1000 | if (Optional32->DataDirectory[5].Size != 0) {\r | |
1001 | SectionHeader = (EFI_IMAGE_SECTION_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof(UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + PeHdr->FileHeader.SizeOfOptionalHeader);\r | |
1002 | for (Index = 0; Index < PeHdr->FileHeader.NumberOfSections; Index++, SectionHeader++) {\r | |
0411bcaf | 1003 | //\r |
1004 | // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory\r | |
1005 | //\r | |
3edf127e | 1006 | if (SectionHeader->VirtualAddress == Optional32->DataDirectory[5].VirtualAddress) {\r |
0411bcaf | 1007 | SectionHeader->Misc.VirtualSize = Optional32->DataDirectory[5].Size;\r |
1008 | AllignedRelocSize = (Optional32->DataDirectory[5].Size + Optional32->FileAlignment - 1) & (~(Optional32->FileAlignment - 1));\r | |
1009 | //\r | |
1010 | // Check to see if there is zero padding at the end of the base relocations\r | |
1011 | //\r | |
1012 | if (AllignedRelocSize < SectionHeader->SizeOfRawData) {\r | |
1013 | //\r | |
1014 | // Check to see if the base relocations are at the end of the file\r | |
1015 | //\r | |
1016 | if (SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData == Optional32->SizeOfImage) {\r | |
1017 | //\r | |
1018 | // All the required conditions are met to strip the zero padding of the end of the base relocations section\r | |
1019 | //\r | |
1020 | Optional32->SizeOfImage -= (SectionHeader->SizeOfRawData - AllignedRelocSize);\r | |
1021 | Optional32->SizeOfInitializedData -= (SectionHeader->SizeOfRawData - AllignedRelocSize);\r | |
1022 | SectionHeader->SizeOfRawData = AllignedRelocSize;\r | |
1023 | FileLength = Optional32->SizeOfImage;\r | |
1024 | }\r | |
1025 | }\r | |
3edf127e | 1026 | }\r |
1027 | }\r | |
1028 | }\r | |
1029 | }\r | |
1030 | } \r | |
1031 | if (PeHdr->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r | |
1032 | Optional64 = (EFI_IMAGE_OPTIONAL_HEADER64 *)&PeHdr->OptionalHeader;\r | |
1033 | Optional64->MajorLinkerVersion = 0;\r | |
1034 | Optional64->MinorLinkerVersion = 0;\r | |
1035 | Optional64->MajorOperatingSystemVersion = 0;\r | |
1036 | Optional64->MinorOperatingSystemVersion = 0;\r | |
1037 | Optional64->MajorImageVersion = 0;\r | |
1038 | Optional64->MinorImageVersion = 0;\r | |
1039 | Optional64->MajorSubsystemVersion = 0;\r | |
1040 | Optional64->MinorSubsystemVersion = 0;\r | |
1041 | Optional64->Win32VersionValue = 0;\r | |
1042 | Optional64->CheckSum = 0;\r | |
1043 | Optional64->SizeOfStackReserve = 0;\r | |
1044 | Optional64->SizeOfStackCommit = 0;\r | |
1045 | Optional64->SizeOfHeapReserve = 0;\r | |
1046 | Optional64->SizeOfHeapCommit = 0;\r | |
1047 | \r | |
1048 | //\r | |
1049 | // Zero the .pdata section if the machine type is X64 and the Debug Directory is empty\r | |
1050 | //\r | |
1051 | if (PeHdr->FileHeader.Machine == 0x8664) { // X64\r | |
1052 | if (Optional64->NumberOfRvaAndSizes >= 4) {\r | |
1053 | if (Optional64->NumberOfRvaAndSizes < 7 || (Optional64->NumberOfRvaAndSizes >= 7 && Optional64->DataDirectory[6].Size == 0)) {\r | |
1054 | SectionHeader = (EFI_IMAGE_SECTION_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof(UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + PeHdr->FileHeader.SizeOfOptionalHeader);\r | |
1055 | for (Index = 0; Index < PeHdr->FileHeader.NumberOfSections; Index++, SectionHeader++) {\r | |
1056 | if (SectionHeader->VirtualAddress == Optional64->DataDirectory[3].VirtualAddress) {\r | |
307fd197 | 1057 | RuntimeFunction = (RUNTIME_FUNCTION *)(FileBuffer + SectionHeader->PointerToRawData);\r |
1058 | for (Index1 = 0; Index1 < Optional64->DataDirectory[3].Size / sizeof (RUNTIME_FUNCTION); Index1++, RuntimeFunction++) {\r | |
1059 | SectionHeader = (EFI_IMAGE_SECTION_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof(UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + PeHdr->FileHeader.SizeOfOptionalHeader);\r | |
1060 | for (Index2 = 0; Index2 < PeHdr->FileHeader.NumberOfSections; Index2++, SectionHeader++) {\r | |
1061 | if (RuntimeFunction->UnwindInfoAddress > SectionHeader->VirtualAddress && RuntimeFunction->UnwindInfoAddress < (SectionHeader->VirtualAddress + SectionHeader->SizeOfRawData)) {\r | |
1062 | UnwindInfo = (UNWIND_INFO *)(FileBuffer + SectionHeader->PointerToRawData + (RuntimeFunction->UnwindInfoAddress - SectionHeader->VirtualAddress));\r | |
1063 | if (UnwindInfo->Version == 1) {\r | |
1064 | memset (UnwindInfo + 1, 0, UnwindInfo->CountOfUnwindCodes * sizeof (UINT16));\r | |
1065 | memset (UnwindInfo, 0, sizeof (UNWIND_INFO));\r | |
1066 | }\r | |
1067 | }\r | |
1068 | }\r | |
1069 | memset (RuntimeFunction, 0, sizeof (RUNTIME_FUNCTION));\r | |
3edf127e | 1070 | }\r |
d9e0f88e | 1071 | \r |
1072 | break;\r | |
3edf127e | 1073 | }\r |
1074 | }\r | |
1075 | Optional64->DataDirectory[3].Size = 0;\r | |
1076 | Optional64->DataDirectory[3].VirtualAddress = 0;\r | |
1077 | }\r | |
1078 | }\r | |
1079 | }\r | |
1080 | \r | |
1081 | //\r | |
1082 | // Strip zero padding at the end of the .reloc section \r | |
1083 | //\r | |
1084 | if (Optional64->NumberOfRvaAndSizes >= 6) {\r | |
1085 | if (Optional64->DataDirectory[5].Size != 0) {\r | |
1086 | SectionHeader = (EFI_IMAGE_SECTION_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof(UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + PeHdr->FileHeader.SizeOfOptionalHeader);\r | |
1087 | for (Index = 0; Index < PeHdr->FileHeader.NumberOfSections; Index++, SectionHeader++) {\r | |
0411bcaf | 1088 | //\r |
1089 | // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory\r | |
1090 | //\r | |
3edf127e | 1091 | if (SectionHeader->VirtualAddress == Optional64->DataDirectory[5].VirtualAddress) {\r |
0411bcaf | 1092 | SectionHeader->Misc.VirtualSize = Optional64->DataDirectory[5].Size;\r |
1093 | AllignedRelocSize = (Optional64->DataDirectory[5].Size + Optional64->FileAlignment - 1) & (~(Optional64->FileAlignment - 1));\r | |
1094 | //\r | |
1095 | // Check to see if there is zero padding at the end of the base relocations\r | |
1096 | //\r | |
1097 | if (AllignedRelocSize < SectionHeader->SizeOfRawData) {\r | |
1098 | //\r | |
1099 | // Check to see if the base relocations are at the end of the file\r | |
1100 | //\r | |
1101 | if (SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData == Optional64->SizeOfImage) {\r | |
1102 | //\r | |
1103 | // All the required conditions are met to strip the zero padding of the end of the base relocations section\r | |
1104 | //\r | |
1105 | Optional64->SizeOfImage -= (SectionHeader->SizeOfRawData - AllignedRelocSize);\r | |
1106 | Optional64->SizeOfInitializedData -= (SectionHeader->SizeOfRawData - AllignedRelocSize);\r | |
1107 | SectionHeader->SizeOfRawData = AllignedRelocSize;\r | |
1108 | FileLength = Optional64->SizeOfImage;\r | |
1109 | }\r | |
1110 | }\r | |
3edf127e | 1111 | }\r |
1112 | }\r | |
1113 | }\r | |
1114 | }\r | |
1115 | }\r | |
1116 | \r | |
3edf127e | 1117 | FWriteFile (fpOut, FileBuffer, FileLength);\r |
878ddf1f | 1118 | \r |
1119 | //\r | |
1120 | // Done\r | |
1121 | //\r | |
1122 | fclose (fpIn);\r | |
1123 | fclose (fpOut);\r | |
1124 | //\r | |
1125 | // printf ("Created %s\n", OutImageName);\r | |
1126 | //\r | |
1127 | return STATUS_SUCCESS;\r | |
1128 | }\r |