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