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