]> git.proxmox.com Git - mirror_edk2.git/blame - EdkCompatibilityPkg/Sample/Tools/Source/FwImage/fwimage.c
Sync all bug fixes between EDK1.04 and EDK1.06 into EdkCompatibilityPkg.
[mirror_edk2.git] / EdkCompatibilityPkg / Sample / Tools / Source / FwImage / fwimage.c
CommitLineData
3eb9473e 1/*++\r
2\r
3e99020d 3Copyright (c) 2004 - 2010, Intel Corporation. All rights reserved.<BR>\r
4b1e1121 4This program and the accompanying materials \r
3eb9473e 5are licensed and made available under the terms and conditions of the BSD License \r
6which accompanies this distribution. The full text of the license may be found at \r
7http://opensource.org/licenses/bsd-license.php \r
8 \r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
11\r
12Module Name:\r
13\r
14 fwimage.c\r
15\r
16Abstract:\r
17\r
18 Converts a pe32/pe32+ image to an FW image type\r
19\r
20--*/\r
21\r
22#include <windows.h>\r
23#include <stdio.h>\r
24#include <stdlib.h>\r
25#include <string.h>\r
26#include <time.h>\r
27\r
28#include "TianoCommon.h"\r
29#include "EfiImage.h"\r
30#include "EfiUtilityMsgs.c"\r
31\r
3e99020d
LG
32#define UTILITY_NAME "FwImage"\r
33#define UTILITY_VERSION "v1.0"\r
3eb9473e 34\r
35typedef union {\r
36 IMAGE_NT_HEADERS32 PeHeader32;\r
37 IMAGE_NT_HEADERS64 PeHeader64;\r
38} PE_HEADER;\r
39\r
40VOID\r
41Usage (\r
42 VOID\r
43 )\r
44{\r
3e99020d
LG
45 int Index;\r
46 const char *Str[] = {\r
47 UTILITY_NAME" "UTILITY_VERSION" - Intel Firmware Image Utility",\r
48 " Copyright (C), 2004 - 2008 Intel Corporation",\r
49\r
50#if ( defined(UTILITY_BUILD) && defined(UTILITY_VENDOR) )\r
51 " Built from "UTILITY_BUILD", project of "UTILITY_VENDOR,\r
52#endif\r
53\r
54 "",\r
55 "Usage:",\r
56 " "UTILITY_NAME" [OPTION]... FWTYPE SOURCE [DEST]",\r
57 "Description:",\r
58 " Converts a pe32/pe32+ SOURCE to DEST with FWTYPE image type.",\r
59 "Options:",\r
60 " FWTYPE Can be one of APPLICATION, BS_DRIVER, RT_DRIVER, SAL_RT_DRIVER,",\r
61 " COMBINED_PEIM_DRIVER, SECURITY_CORE, PEI_CORE, PE32_PEIM and",\r
62 " RELOCATABLE_PEIM",\r
63 " -t time-date Add Time Stamp for output image",\r
64 " -e Not clear ExceptionTable for output image",\r
65 " -r Not strip zero pending of .reloc for output image",\r
66 NULL\r
67 };\r
68\r
69 for (Index = 0; Str[Index] != NULL; Index++) {\r
70 fprintf (stdout, "%s\n", Str[Index]);\r
71 } \r
3eb9473e 72}\r
73\r
74static\r
75STATUS\r
76FReadFile (\r
77 FILE *in,\r
78 VOID **Buffer,\r
79 UINTN *Length\r
80 )\r
81{\r
82 fseek (in, 0, SEEK_END);\r
83 *Length = ftell (in);\r
84 *Buffer = malloc (*Length);\r
85 fseek (in, 0, SEEK_SET);\r
86 fread (*Buffer, *Length, 1, in);\r
87 return STATUS_SUCCESS;\r
88}\r
89\r
90static\r
91STATUS\r
92FWriteFile (\r
93 FILE *out,\r
94 VOID *Buffer,\r
95 UINTN Length\r
96 )\r
97{\r
98 fseek (out, 0, SEEK_SET);\r
99 fwrite (Buffer, Length, 1, out);\r
100 if ((ULONG) ftell (out) != Length) {\r
101 Error (NULL, 0, 0, "write error", NULL);\r
102 return STATUS_ERROR;\r
103 }\r
104 free (Buffer);\r
105 return STATUS_SUCCESS;\r
106}\r
107\r
108VOID\r
109ZeroExceptionTable (\r
110 IN UINT8 *FileBuffer,\r
111 IN EFI_IMAGE_DOS_HEADER *DosHdr,\r
112 IN PE_HEADER *PeHdr\r
113 )\r
114{\r
115 UINT32 PdataSize;\r
116 UINT32 PdataOffset;\r
117 UINT32 PdataRVASize;\r
118 UINT32 PdataRVA;\r
119 UINT32 SectionOffset;\r
120 UINT16 SectionNumber;\r
121 UINT32 SectionNameSize;\r
122 EFI_IMAGE_SECTION_HEADER *Section;\r
123\r
124 PdataSize = 0;\r
125 PdataOffset = 0;\r
126 PdataRVASize = 0;\r
127 PdataRVA = 0;\r
128 SectionOffset = 0;\r
129\r
130 //\r
131 // Search .pdata section\r
132 //\r
133 if (PeHdr->PeHeader32.OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
134 if ((PeHdr->PeHeader32.OptionalHeader.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_EXCEPTION) &&\r
135 (PeHdr->PeHeader32.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress != 0) &&\r
136 (PeHdr->PeHeader32.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size != 0)) {\r
137\r
138 PdataRVA = PeHdr->PeHeader32.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress;\r
139 PdataRVASize = PeHdr->PeHeader32.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size;\r
140\r
141 PeHdr->PeHeader32.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress = 0;\r
142 PeHdr->PeHeader32.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size = 0;\r
143\r
144 SectionOffset = sizeof(PeHdr->PeHeader32);\r
145 }\r
146 } else {\r
147 if ((PeHdr->PeHeader64.OptionalHeader.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_EXCEPTION) &&\r
148 (PeHdr->PeHeader64.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress != 0) &&\r
149 (PeHdr->PeHeader64.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size != 0)) {\r
150\r
151 PdataRVA = PeHdr->PeHeader64.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress;\r
152 PdataRVASize = PeHdr->PeHeader64.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size;\r
153\r
154 PeHdr->PeHeader64.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress = 0;\r
155 PeHdr->PeHeader64.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size = 0;\r
156\r
157 SectionOffset = sizeof(PeHdr->PeHeader64);\r
158 }\r
159 }\r
160\r
161 if ((PdataRVASize != 0) && (PdataRVA != 0)) {\r
162\r
163 SectionNumber = PeHdr->PeHeader32.FileHeader.NumberOfSections;\r
164 SectionNameSize = sizeof(Section->Name);\r
165 while (SectionNumber > 0) {\r
166 Section = (EFI_IMAGE_SECTION_HEADER *) &FileBuffer[DosHdr->e_lfanew + SectionOffset];\r
167 if (strcmp (Section->Name, ".pdata") == 0) {\r
168 //\r
169 // Zero .pdata Section Header Name\r
170 //\r
171 memset (\r
172 FileBuffer + DosHdr->e_lfanew + SectionOffset,\r
173 0,\r
174 SectionNameSize);\r
175\r
176 //\r
177 // Zero .pdata Secton raw data\r
178 //\r
179 PdataOffset = Section->PointerToRawData;\r
180 PdataSize = Section->SizeOfRawData;\r
181 memset (FileBuffer + PdataOffset, 0, PdataSize);\r
182 break;\r
183 }\r
184 SectionNumber--;\r
185 SectionOffset += sizeof(EFI_IMAGE_SECTION_HEADER);\r
186 }\r
187 }\r
188 \r
189 return ;\r
190}\r
191\r
192VOID\r
193StripZeroPendingReloc (\r
194 IN UINT8 *FileBuffer,\r
195 IN OUT UINTN *FileLength,\r
196 IN EFI_IMAGE_DOS_HEADER *DosHdr,\r
197 IN PE_HEADER *PeHdr\r
198 )\r
199{\r
200 EFI_IMAGE_OPTIONAL_HEADER32 *Optional32;\r
201 EFI_IMAGE_OPTIONAL_HEADER64 *Optional64;\r
202 EFI_IMAGE_SECTION_HEADER *SectionHeader;\r
203 UINTN AllignedRelocSize;\r
204 UINTN Index;\r
205\r
206 if (PeHdr->PeHeader32.OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
207 Optional32 = (EFI_IMAGE_OPTIONAL_HEADER32 *)&PeHdr->PeHeader32.OptionalHeader;\r
208 if ((Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) &&\r
209 (Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size != 0)) {\r
210 SectionHeader = (EFI_IMAGE_SECTION_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof(UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + PeHdr->PeHeader32.FileHeader.SizeOfOptionalHeader);\r
211 for (Index = 0; Index < PeHdr->PeHeader32.FileHeader.NumberOfSections; Index++, SectionHeader++) {\r
212 //\r
213 // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory\r
214 //\r
215 if (strcmp (SectionHeader->Name, ".reloc") == 0) {\r
216 SectionHeader->Misc.VirtualSize = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;\r
217\r
218 AllignedRelocSize = (Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size +\r
219 Optional32->FileAlignment - 1) & (~(Optional32->FileAlignment - 1));\r
220 //\r
221 // Check to see if there is zero padding at the end of the base relocations\r
222 //\r
223 if (AllignedRelocSize < SectionHeader->SizeOfRawData) {\r
224 //\r
225 // Check to see if the base relocations are at the end of the file\r
226 //\r
227 if (SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData == Optional32->SizeOfImage) {\r
228 //\r
229 // All the required conditions are met to strip the zero padding of the end of the base relocations section\r
230 //\r
231 Optional32->SizeOfImage -= (SectionHeader->SizeOfRawData - AllignedRelocSize);\r
232 Optional32->SizeOfInitializedData -= (SectionHeader->SizeOfRawData - AllignedRelocSize);\r
233 SectionHeader->SizeOfRawData = AllignedRelocSize;\r
234 *FileLength = Optional32->SizeOfImage;\r
235 }\r
236 }\r
237 }\r
238 }\r
239 }\r
240 } else {\r
241 Optional64 = (EFI_IMAGE_OPTIONAL_HEADER64 *)&PeHdr->PeHeader64.OptionalHeader;\r
242 if ((Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) &&\r
243 (Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size != 0)) {\r
244 SectionHeader = (EFI_IMAGE_SECTION_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof(UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + PeHdr->PeHeader64.FileHeader.SizeOfOptionalHeader);\r
245 for (Index = 0; Index < PeHdr->PeHeader64.FileHeader.NumberOfSections; Index++, SectionHeader++) {\r
246 //\r
247 // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory\r
248 //\r
249 if (strcmp (SectionHeader->Name, ".reloc") == 0) {\r
250 SectionHeader->Misc.VirtualSize = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;\r
251\r
252 AllignedRelocSize = (Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size +\r
253 Optional64->FileAlignment - 1) & (~(Optional64->FileAlignment - 1));\r
254 //\r
255 // Check to see if there is zero padding at the end of the base relocations\r
256 //\r
257 if (AllignedRelocSize < SectionHeader->SizeOfRawData) {\r
258 //\r
259 // Check to see if the base relocations are at the end of the file\r
260 //\r
261 if (SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData == Optional64->SizeOfImage) {\r
262 //\r
263 // All the required conditions are met to strip the zero padding of the end of the base relocations section\r
264 //\r
265 Optional64->SizeOfImage -= (SectionHeader->SizeOfRawData - AllignedRelocSize);\r
266 Optional64->SizeOfInitializedData -= (SectionHeader->SizeOfRawData - AllignedRelocSize);\r
267 SectionHeader->SizeOfRawData = AllignedRelocSize;\r
268 *FileLength = Optional64->SizeOfImage;\r
269 }\r
270 }\r
271 }\r
272 }\r
273 }\r
274 }\r
275}\r
276\r
277int\r
278main (\r
279 int argc,\r
280 char *argv[]\r
281 )\r
282/*++\r
283\r
284Routine Description:\r
285\r
286 Main function.\r
287\r
288Arguments:\r
289\r
290 argc - Number of command line parameters.\r
291 argv - Array of pointers to command line parameter strings.\r
292\r
293Returns:\r
294\r
295 STATUS_SUCCESS - Utility exits successfully.\r
296 STATUS_ERROR - Some error occurred during execution.\r
297\r
298--*/\r
299{\r
300 ULONG Type;\r
301 PUCHAR Ext;\r
302 PUCHAR p;\r
303 PUCHAR pe;\r
304 PUCHAR OutImageName;\r
305 UCHAR outname[500];\r
306 FILE *fpIn;\r
307 FILE *fpOut;\r
308 EFI_IMAGE_DOS_HEADER *DosHdr;\r
309 PE_HEADER *PeHdr;\r
310 time_t TimeStamp;\r
311 struct tm TimeStruct;\r
312 EFI_IMAGE_DOS_HEADER BackupDosHdr;\r
313 ULONG Index;\r
314 BOOLEAN TimeStampPresent;\r
315 BOOLEAN NeedClearExceptionTable;\r
316 BOOLEAN NeedStripZeroPendingReloc;\r
317 UINT8 *FileBuffer;\r
318 UINTN FileLength;\r
319 EFI_IMAGE_OPTIONAL_HEADER32 *Optional32;\r
320 EFI_IMAGE_OPTIONAL_HEADER64 *Optional64;\r
321\r
322 SetUtilityName (UTILITY_NAME);\r
323 //\r
324 // Assign to fix compile warning\r
325 //\r
326 OutImageName = NULL;\r
327 Type = 0;\r
328 Ext = 0;\r
329 TimeStamp = 0;\r
330 TimeStampPresent = FALSE;\r
331\r
332 NeedClearExceptionTable = TRUE;\r
333 NeedStripZeroPendingReloc = TRUE;\r
334\r
335 //\r
336 // Look for -t time-date option first. If the time is "0", then\r
337 // skip it.\r
338 //\r
339 if ((argc > 2) && !strcmp (argv[1], "-t")) {\r
340 TimeStampPresent = TRUE;\r
341 if (strcmp (argv[2], "0") != 0) {\r
342 //\r
343 // Convert the string to a value\r
344 //\r
345 memset ((char *) &TimeStruct, 0, sizeof (TimeStruct));\r
346 if (sscanf(\r
347 argv[2], "%d/%d/%d,%d:%d:%d",\r
348 &TimeStruct.tm_mon, /* months since January - [0,11] */\r
349 &TimeStruct.tm_mday, /* day of the month - [1,31] */\r
350 &TimeStruct.tm_year, /* years since 1900 */\r
351 &TimeStruct.tm_hour, /* hours since midnight - [0,23] */\r
352 &TimeStruct.tm_min, /* minutes after the hour - [0,59] */\r
353 &TimeStruct.tm_sec /* seconds after the minute - [0,59] */\r
354 ) != 6) {\r
355 Error (NULL, 0, 0, argv[2], "failed to convert to mm/dd/yyyy,hh:mm:ss format");\r
356 return STATUS_ERROR;\r
357 }\r
358 //\r
359 // Now fixup some of the fields\r
360 //\r
361 TimeStruct.tm_mon--;\r
362 TimeStruct.tm_year -= 1900;\r
363 //\r
364 // Sanity-check values?\r
365 // Convert\r
366 //\r
367 TimeStamp = mktime (&TimeStruct);\r
368 if (TimeStamp == (time_t) - 1) {\r
369 Error (NULL, 0, 0, argv[2], "failed to convert time");\r
370 return STATUS_ERROR;\r
371 }\r
372 }\r
373 //\r
374 // Skip over the args\r
375 //\r
376 argc -= 2;\r
377 argv += 2;\r
378 }\r
379\r
380 //\r
381 // Look for -e option.\r
382 //\r
383 if ((argc > 1) && !strcmp (argv[1], "-e")) {\r
384 NeedClearExceptionTable = FALSE;\r
385 //\r
386 // Skip over the args\r
387 //\r
388 argc -= 1;\r
389 argv += 1;\r
390 }\r
391\r
392 //\r
393 // Look for -r option\r
394 //\r
395 if ((argc > 1) && !strcmp (argv[1], "-r")) {\r
396 NeedStripZeroPendingReloc = FALSE;\r
397 //\r
398 // Skip over the args\r
399 //\r
400 argc -= 1;\r
401 argv += 1;\r
402 }\r
403\r
404 //\r
405 // Check for enough args\r
406 //\r
407 if (argc < 3) {\r
408 Usage ();\r
409 return STATUS_ERROR;\r
410 }\r
411\r
412 if (argc == 4) {\r
413 OutImageName = argv[3];\r
414 }\r
415 //\r
416 // Get new image type\r
417 //\r
418 p = argv[1];\r
419 if (*p == '/' || *p == '\\') {\r
420 p += 1;\r
421 }\r
422\r
423 if (_stricmp (p, "app") == 0 || _stricmp (p, "APPLICATION") == 0) {\r
424 Type = EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION;\r
425 Ext = ".efi";\r
426\r
427 } else if (_stricmp (p, "bsdrv") == 0 || _stricmp (p, "BS_DRIVER") == 0) {\r
428 Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER;\r
429 Ext = ".efi";\r
430\r
431 } else if (_stricmp (p, "rtdrv") == 0 || _stricmp (p, "RT_DRIVER") == 0) {\r
432 Type = EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER;\r
433 Ext = ".efi";\r
434\r
435 } else if (_stricmp (p, "rtdrv") == 0 || _stricmp (p, "SAL_RT_DRIVER") == 0) {\r
436 Type = EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER;\r
437 Ext = ".efi";\r
438 } else if (_stricmp (p, "SECURITY_CORE") == 0) {\r
439 Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER;\r
440 Ext = ".sec";\r
441 } else if (_stricmp (p, "peim") == 0 ||\r
442 _stricmp (p, "PEI_CORE") == 0 ||\r
443 _stricmp (p, "PE32_PEIM") == 0 ||\r
444 _stricmp (p, "RELOCATABLE_PEIM") == 0 ||\r
445 _stricmp (p, "combined_peim_driver") == 0\r
446 ) {\r
447 Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER;\r
448 Ext = ".pei";\r
449 } else {\r
450 Usage ();\r
451 return STATUS_ERROR;\r
452 }\r
453 //\r
454 // open source file\r
455 //\r
456 fpIn = fopen (argv[2], "rb");\r
457 if (!fpIn) {\r
458 Error (NULL, 0, 0, argv[2], "failed to open input file for reading");\r
459 return STATUS_ERROR;\r
460 }\r
461 FReadFile (fpIn, (VOID **)&FileBuffer, &FileLength);\r
462 //\r
463 // Read the dos & pe hdrs of the image\r
464 //\r
465 DosHdr = (EFI_IMAGE_DOS_HEADER *) FileBuffer;\r
466 if (DosHdr->e_magic != IMAGE_DOS_SIGNATURE) {\r
467 Error (NULL, 0, 0, argv[2], "DOS header signature not found in source image");\r
468 fclose (fpIn);\r
469 return STATUS_ERROR;\r
470 }\r
471\r
472 PeHdr = (PE_HEADER *)(FileBuffer + DosHdr->e_lfanew);\r
473 if (PeHdr->PeHeader32.Signature != IMAGE_NT_SIGNATURE) {\r
474 Error (NULL, 0, 0, argv[2], "PE header signature not found in source image");\r
475 fclose (fpIn);\r
476 return STATUS_ERROR;\r
477 }\r
478 //\r
479 // open output file\r
480 //\r
481 strcpy (outname, argv[2]);\r
482 pe = NULL;\r
483 for (p = outname; *p; p++) {\r
484 if (*p == '.') {\r
485 pe = p;\r
486 }\r
487 }\r
488\r
489 if (!pe) {\r
490 pe = p;\r
491 }\r
492\r
493 strcpy (pe, Ext);\r
494\r
495 if (!OutImageName) {\r
496 OutImageName = outname;\r
497 }\r
498\r
499 fpOut = fopen (OutImageName, "w+b");\r
500 if (!fpOut) {\r
501 Error (NULL, 0, 0, OutImageName, "could not open output file for writing");\r
502 fclose (fpIn);\r
503 return STATUS_ERROR;\r
504 }\r
505 //\r
506 // Zero all unused fields of the DOS header\r
507 //\r
508 memcpy (&BackupDosHdr, DosHdr, sizeof (EFI_IMAGE_DOS_HEADER));\r
509 memset (DosHdr, 0, sizeof (EFI_IMAGE_DOS_HEADER));\r
510 DosHdr->e_magic = BackupDosHdr.e_magic;\r
511 DosHdr->e_lfanew = BackupDosHdr.e_lfanew;\r
512\r
513 for (Index = sizeof (EFI_IMAGE_DOS_HEADER); Index < (ULONG) DosHdr->e_lfanew; Index++) {\r
514 FileBuffer[Index] = (UINT8) DosHdr->e_cp;\r
515 }\r
516 \r
517 //\r
518 // Modify some fields in the PE header\r
519 //\r
520\r
521 //\r
522 // TimeDateStamp's offset is fixed for PE32/32+\r
523 //\r
524 if (TimeStampPresent) {\r
525 PeHdr->PeHeader32.FileHeader.TimeDateStamp = (UINT32) TimeStamp;\r
526 }\r
527\r
528 //\r
529 // PE32/32+ has different optional header layout\r
530 // Determine format is PE32 or PE32+ before modification\r
531 //\r
532 if (PeHdr->PeHeader32.OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
533 //\r
534 // PE32 image\r
535 //\r
536 Optional32 = (EFI_IMAGE_OPTIONAL_HEADER32 *)&PeHdr->PeHeader32.OptionalHeader;\r
537\r
538 Optional32->MajorLinkerVersion = 0;\r
539 Optional32->MinorLinkerVersion = 0;\r
540 Optional32->MajorOperatingSystemVersion = 0;\r
541 Optional32->MinorOperatingSystemVersion = 0;\r
542 Optional32->MajorImageVersion = 0;\r
543 Optional32->MinorImageVersion = 0;\r
544 Optional32->MajorSubsystemVersion = 0;\r
545 Optional32->MinorSubsystemVersion = 0;\r
546 Optional32->Win32VersionValue = 0;\r
547 Optional32->CheckSum = 0;\r
548 Optional32->SizeOfStackReserve = 0;\r
549 Optional32->SizeOfStackCommit = 0;\r
550 Optional32->SizeOfHeapReserve = 0;\r
551 Optional32->SizeOfHeapCommit = 0;\r
552 Optional32->Subsystem = (USHORT) Type;\r
553\r
554 //\r
555 // Strip zero padding at the end of the .reloc section \r
556 //\r
557 if (NeedStripZeroPendingReloc) {\r
558 StripZeroPendingReloc (FileBuffer, &FileLength, DosHdr, PeHdr);\r
559 }\r
560 } else if (PeHdr->PeHeader32.OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
561 //\r
562 // PE32+ image\r
563 //\r
564 Optional64 = (EFI_IMAGE_OPTIONAL_HEADER64 *)&PeHdr->PeHeader64.OptionalHeader;\r
565\r
566 Optional64->MajorLinkerVersion = 0;\r
567 Optional64->MinorLinkerVersion = 0;\r
568 Optional64->MajorOperatingSystemVersion = 0;\r
569 Optional64->MinorOperatingSystemVersion = 0;\r
570 Optional64->MajorImageVersion = 0;\r
571 Optional64->MinorImageVersion = 0;\r
572 Optional64->MajorSubsystemVersion = 0;\r
573 Optional64->MinorSubsystemVersion = 0;\r
574 Optional64->Win32VersionValue = 0;\r
575 Optional64->CheckSum = 0;\r
576 Optional64->SizeOfStackReserve = 0;\r
577 Optional64->SizeOfStackCommit = 0;\r
578 Optional64->SizeOfHeapReserve = 0;\r
579 Optional64->SizeOfHeapCommit = 0;\r
580 Optional64->Subsystem = (USHORT) Type;\r
581\r
582 //\r
583 // Strip zero padding at the end of the .reloc section \r
584 //\r
585 if (NeedStripZeroPendingReloc) {\r
586 StripZeroPendingReloc (FileBuffer, &FileLength, DosHdr, PeHdr);\r
587 }\r
588 } else {\r
589 Error (NULL, 0, 0, argv[2], "Unsupported PE image");\r
590 fclose (fpIn);\r
591 fclose (fpOut);\r
592 return STATUS_ERROR;\r
593 }\r
594\r
595 //\r
596 // Zero PDATA section for smaller binary size after compression\r
597 //\r
598 if (NeedClearExceptionTable) {\r
599 ZeroExceptionTable (FileBuffer, DosHdr, PeHdr);\r
600 }\r
601\r
602 FWriteFile (fpOut, FileBuffer, FileLength);\r
603\r
604 //\r
605 // Done\r
606 //\r
607 fclose (fpIn);\r
608 fclose (fpOut);\r
609\r
610 return STATUS_SUCCESS;\r
611}\r