• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2 Converts a pe32+ image to an FW, Te image type, or other specific image.
3 
4 Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution.  The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9 
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 
13 **/
14 
15 #include "WinNtInclude.h"
16 
17 #ifndef __GNUC__
18 #include <windows.h>
19 #include <io.h>
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 #endif
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <time.h>
27 #include <ctype.h>
28 
29 #include <Common/UefiBaseTypes.h>
30 #include <IndustryStandard/PeImage.h>
31 #include <Common/UefiInternalFormRepresentation.h>
32 
33 //
34 // Acpi Table definition
35 //
36 #include <IndustryStandard/Acpi.h>
37 #include <IndustryStandard/Acpi1_0.h>
38 #include <IndustryStandard/Acpi2_0.h>
39 #include <IndustryStandard/Acpi3_0.h>
40 #include <IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h>
41 
42 #include "CommonLib.h"
43 #include "PeCoffLib.h"
44 #include "ParseInf.h"
45 #include "EfiUtilityMsgs.h"
46 
47 #include "GenFw.h"
48 
49 //
50 // Version of this utility
51 //
52 #define UTILITY_NAME "GenFw"
53 #define UTILITY_MAJOR_VERSION 0
54 #define UTILITY_MINOR_VERSION 2
55 
56 #define HII_RESOURCE_SECTION_INDEX  1
57 #define HII_RESOURCE_SECTION_NAME   "HII"
58 
59 #define DEFAULT_MC_PAD_BYTE_VALUE  0xFF
60 #define DEFAULT_MC_ALIGNMENT       16
61 
62 #define STATUS_IGNORE 0xA
63 //
64 // Structure definition for a microcode header
65 //
66 typedef struct {
67   UINT32  HeaderVersion;
68   UINT32  PatchId;
69   UINT32  Date;
70   UINT32  CpuId;
71   UINT32  Checksum;
72   UINT32  LoaderVersion;
73   UINT32  PlatformId;
74   UINT32  DataSize;   // if 0, then TotalSize = 2048, and TotalSize field is invalid
75   UINT32  TotalSize;  // number of bytes
76   UINT32  Reserved[3];
77 } MICROCODE_IMAGE_HEADER;
78 
79 static EFI_GUID mZeroGuid = {0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
80 
81 static const char *gHiiPackageRCFileHeader[] = {
82   "//",
83   "//  DO NOT EDIT -- auto-generated file",
84   "//",
85   NULL
86 };
87 
88 //
89 // Module image information
90 //
91 CHAR8  *mInImageName;
92 UINT32 mImageTimeStamp = 0;
93 UINT32 mImageSize = 0;
94 UINT32 mOutImageType = FW_DUMMY_IMAGE;
95 
96 
97 STATIC
98 EFI_STATUS
99 ZeroDebugData (
100   IN OUT UINT8   *FileBuffer,
101   BOOLEAN        ZeroDebug
102   );
103 
104 STATIC
105 EFI_STATUS
106 SetStamp (
107   IN OUT UINT8  *FileBuffer,
108   IN     CHAR8  *TimeStamp
109   );
110 
111 STATIC
112 STATUS
113 MicrocodeReadData (
114   FILE          *InFptr,
115   UINT32        *Data
116   );
117 
118 STATIC
119 VOID
Version(VOID)120 Version (
121   VOID
122   )
123 /*++
124 
125 Routine Description:
126 
127   Print out version information for this utility.
128 
129 Arguments:
130 
131   None
132 
133 Returns:
134 
135   None
136 
137 --*/
138 {
139   fprintf (stdout, "%s Version %d.%d %s \n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION, __BUILD_VERSION);
140 }
141 
142 STATIC
143 VOID
Usage(VOID)144 Usage (
145   VOID
146   )
147 /*++
148 
149 Routine Description:
150 
151   Print Help message.
152 
153 Arguments:
154 
155   VOID
156 
157 Returns:
158 
159   None
160 
161 --*/
162 {
163   //
164   // Summary usage
165   //
166   fprintf (stdout, "\nUsage: %s [options] <input_file>\n\n", UTILITY_NAME);
167 
168   //
169   // Copyright declaration
170   //
171   fprintf (stdout, "Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved.\n\n");
172 
173   //
174   // Details Option
175   //
176   fprintf (stdout, "Options:\n");
177   fprintf (stdout, "  -o FileName, --outputfile FileName\n\
178                         File will be created to store the ouput content.\n");
179   fprintf (stdout, "  -e EFI_FILETYPE, --efiImage EFI_FILETYPE\n\
180                         Create Efi Image. EFI_FILETYPE is one of BASE,SMM_CORE,\n\
181                         PEI_CORE, PEIM, DXE_CORE, DXE_DRIVER, UEFI_APPLICATION,\n\
182                         SEC, DXE_SAL_DRIVER, UEFI_DRIVER, DXE_RUNTIME_DRIVER,\n\
183                         DXE_SMM_DRIVER, SECURITY_CORE, COMBINED_PEIM_DRIVER,\n\
184                         PIC_PEIM, RELOCATABLE_PEIM, BS_DRIVER, RT_DRIVER,\n\
185                         APPLICATION, SAL_RT_DRIVER to support all module types\n\
186                         It can only be used together with --keepexceptiontable,\n\
187                         --keepzeropending, --keepoptionalheader, -r, -o option.\n\
188                         It is a action option. If it is combined with other action options,\n\
189                         the later input action option will override the previous one.\n");
190   fprintf (stdout, "  -c, --acpi            Create Acpi table.\n\
191                         It can't be combined with other action options\n\
192                         except for -o, -r option. It is a action option.\n\
193                         If it is combined with other action options, the later\n\
194                         input action option will override the previous one.\n");
195   fprintf (stdout, "  -t, --terse           Create Te Image.\n\
196                         It can only be used together with --keepexceptiontable,\n\
197                         --keepzeropending, --keepoptionalheader, -r, -o option.\n\
198                         It is a action option. If it is combined with other action options,\n\
199                         the later input action option will override the previous one.\n");
200   fprintf (stdout, "  -u, --dump            Dump TeImage Header.\n\
201                         It can't be combined with other action options\n\
202                         except for -o, -r option. It is a action option.\n\
203                         If it is combined with other action options, the later\n\
204                         input action option will override the previous one.\n");
205   fprintf (stdout, "  -z, --zero            Zero the Debug Data Fields in the PE input image file.\n\
206                         It also zeros the time stamp fields.\n\
207                         This option can be used to compare the binary efi image.\n\
208                         It can't be combined with other action options\n\
209                         except for -o, -r option. It is a action option.\n\
210                         If it is combined with other action options, the later\n\
211                         input action option will override the previous one.\n");
212   fprintf (stdout, "  -b, --exe2bin         Convert the input EXE to the output BIN file.\n\
213                         It can't be combined with other action options\n\
214                         except for -o, -r option. It is a action option.\n\
215                         If it is combined with other action options, the later\n\
216                         input action option will override the previous one.\n");;
217   fprintf (stdout, "  -l, --stripped        Strip off the relocation info from PE or TE image.\n\
218                         It can't be combined with other action options\n\
219                         except for -o, -r option. It is a action option.\n\
220                         If it is combined with other action options, the later\n\
221                         input action option will override the previous one.\n");
222   fprintf (stdout, "  -s timedate, --stamp timedate\n\
223                         timedate format is \"yyyy-mm-dd 00:00:00\". if timedata \n\
224                         is set to NOW, current system time is used. The support\n\
225                         date scope is 1970-01-01 00+timezone:00:00\n\
226                         ~ 2038-01-19 03+timezone:14:07\n\
227                         The scope is adjusted according to the different zones.\n\
228                         It can't be combined with other action options\n\
229                         except for -o, -r option. It is a action option.\n\
230                         If it is combined with other action options, the later\n\
231                         input action option will override the previous one.\n");
232   fprintf (stdout, "  -m, --mcifile         Convert input microcode txt file to microcode bin file.\n\
233                         It can't be combined with other action options\n\
234                         except for -o option. It is a action option.\n\
235                         If it is combined with other action options, the later\n\
236                         input action option will override the previous one.\n");
237   fprintf (stdout, "  -j, --join            Combine multi microcode bin files to one file.\n\
238                         It can be specified with -a, -p, -o option.\n\
239                         No other options can be combined with it.\n\
240                         If it is combined with other action options, the later\n\
241                         input action option will override the previous one.\n");
242   fprintf (stdout, "  -a NUM, --align NUM   NUM is one HEX or DEC format alignment value.\n\
243                         This option is only used together with -j option.\n");
244   fprintf (stdout, "  -p NUM, --pad NUM     NUM is one HEX or DEC format padding value.\n\
245                         This option is only used together with -j option.\n");
246   fprintf (stdout, "  --keepexceptiontable  Don't clear exception table.\n\
247                         This option can be used together with -e or -t.\n\
248                         It doesn't work for other options.\n");
249   fprintf (stdout, "  --keepoptionalheader  Don't zero PE/COFF optional header fields.\n\
250                         This option can be used together with -e or -t.\n\
251                         It doesn't work for other options.\n");
252   fprintf (stdout, "  --keepzeropending     Don't strip zero pending of .reloc.\n\
253                         This option can be used together with -e or -t.\n\
254                         It doesn't work for other options.\n");
255   fprintf (stdout, "  -r, --replace         Overwrite the input file with the output content.\n\
256                         If more input files are specified,\n\
257                         the last input file will be as the output file.\n");
258   fprintf (stdout, "  -g HiiPackageListGuid, --hiiguid HiiPackageListGuid\n\
259                         Guid is used to specify hii package list guid.\n\
260                         Its format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n\
261                         If not specified, the first Form FormSet guid is used.\n");
262   fprintf (stdout, "  --hiipackage          Combine all input binary hii pacakges into \n\
263                         a single package list as the text resource data(RC).\n\
264                         It can't be combined with other action options\n\
265                         except for -o option. It is a action option.\n\
266                         If it is combined with other action options, the later\n\
267                         input action option will override the previous one.\n");
268   fprintf (stdout, "  --hiibinpackage       Combine all input binary hii pacakges into \n\
269                         a single package list as the binary resource section.\n\
270                         It can't be combined with other action options\n\
271                         except for -o option. It is a action option.\n\
272                         If it is combined with other action options, the later\n\
273                         input action option will override the previous one.\n");
274   fprintf (stdout, "  --rebase NewAddress   Rebase image to new base address. New address \n\
275                         is also set to the first none code section header.\n\
276                         It can't be combined with other action options\n\
277                         except for -o or -r option. It is a action option.\n\
278                         If it is combined with other action options, the later\n\
279                         input action option will override the previous one.\n");
280   fprintf (stdout, "  --address NewAddress  Set new address into the first none code \n\
281                         section header of the input image.\n\
282                         It can't be combined with other action options\n\
283                         except for -o or -r option. It is a action option.\n\
284                         If it is combined with other action options, the later\n\
285                         input action option will override the previous one.\n");
286   fprintf (stdout, "  -v, --verbose         Turn on verbose output with informational messages.\n");
287   fprintf (stdout, "  -q, --quiet           Disable all messages except key message and fatal error\n");
288   fprintf (stdout, "  -d, --debug level     Enable debug messages, at input debug level.\n");
289   fprintf (stdout, "  --version             Show program's version number and exit\n");
290   fprintf (stdout, "  -h, --help            Show this help message and exit\n");
291 }
292 
293 STATIC
294 STATUS
CheckAcpiTable(VOID * AcpiTable,UINT32 Length)295 CheckAcpiTable (
296   VOID      *AcpiTable,
297   UINT32    Length
298   )
299 /*++
300 
301 Routine Description:
302 
303   Check Acpi Table
304 
305 Arguments:
306 
307   AcpiTable     Buffer for AcpiSection
308   Length        AcpiSection Length
309 
310 Returns:
311 
312   0             success
313   non-zero      otherwise
314 
315 --*/
316 {
317   EFI_ACPI_DESCRIPTION_HEADER                   *AcpiHeader;
318   EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE  *Facs;
319   UINT32                                        ExpectedLength;
320 
321   AcpiHeader = (EFI_ACPI_DESCRIPTION_HEADER *)AcpiTable;
322 
323   //
324   // Generic check for AcpiTable length.
325   //
326   if (AcpiHeader->Length > Length) {
327     Error (NULL, 0, 3000, "Invalid", "AcpiTable length check failed.", NULL);
328     return STATUS_ERROR;
329   }
330 
331   //
332   // Currently, we only check must-have tables: FADT, FACS, DSDT,
333   // and some important tables: MADT, MCFG.
334   //
335   switch (AcpiHeader->Signature) {
336 
337   //
338   // "FACP" Fixed ACPI Description Table
339   //
340   case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE:
341     switch (AcpiHeader->Revision) {
342     case EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION:
343       ExpectedLength = sizeof(EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE);
344       break;
345     case EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION:
346       ExpectedLength = sizeof(EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE);
347       break;
348     case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION:
349       ExpectedLength = sizeof(EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE);
350       break;
351     default:
352       if (AcpiHeader->Revision > EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION) {
353         ExpectedLength = AcpiHeader->Length;
354         break;
355       }
356       Error (NULL, 0, 3000, "Invalid", "FACP revision check failed.");
357       return STATUS_ERROR;
358     }
359     if (ExpectedLength != AcpiHeader->Length) {
360       Error (NULL, 0, 3000, "Invalid", "FACP length check failed.");
361       return STATUS_ERROR;
362     }
363     break;
364 
365   //
366   // "FACS" Firmware ACPI Control Structure
367   //
368   case EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE:
369     Facs = (EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *)AcpiTable;
370     if (Facs->Version > EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION) {
371       break;
372     }
373     if ((Facs->Version != EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION) &&
374         (Facs->Version != EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION) &&
375         (Facs->Version != EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION)){
376       Error (NULL, 0, 3000, "Invalid", "FACS version check failed.");
377       return STATUS_ERROR;
378     }
379     if ((Facs->Length != sizeof(EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE)) &&
380         (Facs->Length != sizeof(EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE)) &&
381         (Facs->Length != sizeof(EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE))) {
382       Error (NULL, 0, 3000, "Invalid", "FACS length check failed.");
383       return STATUS_ERROR;
384     }
385     break;
386 
387   //
388   // "DSDT" Differentiated System Description Table
389   //
390   case EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:
391     if (AcpiHeader->Revision > EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_REVISION) {
392       break;
393     }
394     if (AcpiHeader->Length <= sizeof(EFI_ACPI_DESCRIPTION_HEADER)) {
395       Error (NULL, 0, 3000, "Invalid", "DSDT length check failed.");
396       return STATUS_ERROR;
397     }
398     break;
399 
400   //
401   // "APIC" Multiple APIC Description Table
402   //
403   case EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE:
404     if (AcpiHeader->Revision > EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION) {
405       break;
406     }
407     if ((AcpiHeader->Revision != EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION) &&
408         (AcpiHeader->Revision != EFI_ACPI_2_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION) &&
409         (AcpiHeader->Revision != EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION)) {
410       Error (NULL, 0, 3000, "Invalid", "APIC revision check failed.");
411       return STATUS_ERROR;
412     }
413     if (AcpiHeader->Length <= sizeof(EFI_ACPI_DESCRIPTION_HEADER) + sizeof(UINT32) + sizeof(UINT32)) {
414       Error (NULL, 0, 3000, "Invalid", "APIC length check failed.");
415       return STATUS_ERROR;
416     }
417     break;
418 
419   //
420   // "MCFG" PCI Express Memory Mapped Configuration Space Base Address Description Table
421   //
422   case EFI_ACPI_3_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE:
423     if (AcpiHeader->Revision > EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION) {
424       break;
425     }
426     if (AcpiHeader->Revision != EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION) {
427       Error (NULL, 0, 3000, "Invalid", "MCFG revision check failed.");
428       return STATUS_ERROR;
429     }
430     if (AcpiHeader->Length <= sizeof(EFI_ACPI_DESCRIPTION_HEADER) + sizeof(UINT64)) {
431       Error (NULL, 0, 3000, "Invalid", "MCFG length check failed.");
432       return STATUS_ERROR;
433     }
434     break;
435 
436   //
437   // Other table pass check
438   //
439   default:
440     break;
441   }
442 
443   return STATUS_SUCCESS;
444 }
445 
446 VOID
SetHiiResourceHeader(UINT8 * HiiBinData,UINT32 OffsetToFile)447 SetHiiResourceHeader (
448   UINT8   *HiiBinData,
449   UINT32  OffsetToFile
450   )
451 {
452   UINT32  Index;
453   EFI_IMAGE_RESOURCE_DIRECTORY        *ResourceDirectory;
454   EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY  *ResourceDirectoryEntry;
455   EFI_IMAGE_RESOURCE_DIRECTORY_STRING *ResourceDirectoryString;
456   EFI_IMAGE_RESOURCE_DATA_ENTRY       *ResourceDataEntry;
457 
458   //
459   // Fill Resource section entry
460   //
461   ResourceDirectory      = (EFI_IMAGE_RESOURCE_DIRECTORY *) (HiiBinData);
462   ResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *) (ResourceDirectory + 1);
463   for (Index = 0; Index < ResourceDirectory->NumberOfNamedEntries; Index ++) {
464     if (ResourceDirectoryEntry->u1.s.NameIsString) {
465       ResourceDirectoryString = (EFI_IMAGE_RESOURCE_DIRECTORY_STRING *) (HiiBinData + ResourceDirectoryEntry->u1.s.NameOffset);
466 
467       if (ResourceDirectoryString->Length == 3 &&
468           ResourceDirectoryString->String[0] == L'H' &&
469           ResourceDirectoryString->String[1] == L'I' &&
470           ResourceDirectoryString->String[2] == L'I') {
471         //
472         // Resource Type "HII" found
473         //
474         if (ResourceDirectoryEntry->u2.s.DataIsDirectory) {
475           //
476           // Move to next level - resource Name
477           //
478           ResourceDirectory = (EFI_IMAGE_RESOURCE_DIRECTORY *) (HiiBinData + ResourceDirectoryEntry->u2.s.OffsetToDirectory);
479           ResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *) (ResourceDirectory + 1);
480 
481           if (ResourceDirectoryEntry->u2.s.DataIsDirectory) {
482             //
483             // Move to next level - resource Language
484             //
485             ResourceDirectory = (EFI_IMAGE_RESOURCE_DIRECTORY *) (HiiBinData + ResourceDirectoryEntry->u2.s.OffsetToDirectory);
486             ResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *) (ResourceDirectory + 1);
487           }
488         }
489 
490         //
491         // Now it ought to be resource Data and update its OffsetToData value
492         //
493         if (!ResourceDirectoryEntry->u2.s.DataIsDirectory) {
494           ResourceDataEntry = (EFI_IMAGE_RESOURCE_DATA_ENTRY *) (HiiBinData + ResourceDirectoryEntry->u2.OffsetToData);
495           ResourceDataEntry->OffsetToData = ResourceDataEntry->OffsetToData + OffsetToFile;
496           break;
497         }
498       }
499     }
500     ResourceDirectoryEntry++;
501   }
502 
503   return;
504 }
505 
506 EFI_IMAGE_OPTIONAL_HEADER_UNION *
GetPeCoffHeader(void * Data)507 GetPeCoffHeader (
508   void *Data
509   )
510 {
511   EFI_IMAGE_DOS_HEADER             *DosHdr;
512   EFI_IMAGE_OPTIONAL_HEADER_UNION  *PeHdr;
513 
514   //
515   // Read the dos & pe hdrs of the image
516   //
517   DosHdr = (EFI_IMAGE_DOS_HEADER *)Data;
518   if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {
519     // NO DOS header, check for PE/COFF header
520     PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(Data);
521     if (PeHdr->Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) {
522       return NULL;
523     }
524   } else {
525 
526     PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(((UINT8 *)Data) + DosHdr->e_lfanew);
527     if (PeHdr->Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) {
528       return NULL;
529     }
530   }
531 
532   return PeHdr;
533 }
534 
535 void
PeCoffConvertImageToXip(UINT8 ** FileBuffer,UINT32 * FileLength)536 PeCoffConvertImageToXip (
537   UINT8  **FileBuffer,
538   UINT32 *FileLength
539   )
540 {
541   EFI_IMAGE_OPTIONAL_HEADER_UNION  *PeHdr;
542   EFI_IMAGE_OPTIONAL_HEADER_UNION  *NewPeHdr;
543   EFI_IMAGE_SECTION_HEADER         *SectionHeader;
544   UINTN                            TotalNecessaryFileSize;
545   UINTN                            SectionSize;
546   UINT8                            *XipFile;
547   UINT32                           XipLength;
548   UINTN                            Index;
549   UINTN                            FirstSectionOffset;
550   BOOLEAN                          ConversionNeeded;
551 
552   PeHdr = GetPeCoffHeader ((void *) *FileBuffer);
553   if (PeHdr == NULL) {
554     return;
555   }
556 
557   if (PeHdr->Pe32.OptionalHeader.SectionAlignment != PeHdr->Pe32.OptionalHeader.FileAlignment) {
558     //
559     // The only reason to expand zero fill sections is to make them compatible with XIP images.
560     // If SectionAlignment is not equal to FileAlginment then it is not an XIP type image.
561     //
562     return;
563   }
564 
565   //
566   // Calculate size of XIP file, and determine if the conversion is needed.
567   //
568   ConversionNeeded = FALSE;
569   XipLength = 0;
570   FirstSectionOffset = *FileLength;
571   TotalNecessaryFileSize = 0;
572   SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);
573   for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) {
574     SectionSize = MAX (SectionHeader->Misc.VirtualSize, SectionHeader->SizeOfRawData);
575     TotalNecessaryFileSize += SectionSize;
576     if (SectionSize > 0) {
577       FirstSectionOffset = MIN (FirstSectionOffset, SectionHeader->VirtualAddress);
578       XipLength = MAX (XipLength, SectionHeader->VirtualAddress + SectionSize);
579       if (SectionHeader->VirtualAddress != SectionHeader->PointerToRawData) {
580         ConversionNeeded = TRUE;
581       }
582     }
583     if (SectionHeader->Misc.VirtualSize > SectionHeader->SizeOfRawData) {
584       ConversionNeeded = TRUE;
585     }
586   }
587 
588   if (FirstSectionOffset < PeHdr->Pe32.OptionalHeader.SizeOfHeaders) {
589     //
590     // If one of the sections should be loaded to an offset overlapping with
591     // the executable header, then it cannot be made into an XIP image.
592     //
593     VerboseMsg ("PE/COFF conversion to XIP is impossible due to overlap");
594     VerboseMsg ("of section data with the executable header.");
595     return;
596   }
597 
598   if (FirstSectionOffset == *FileLength) {
599     //
600     // If we never found a section with a non-zero size, then we
601     // skip the conversion.
602     //
603     return;
604   }
605 
606   TotalNecessaryFileSize += FirstSectionOffset;
607 
608   if (!ConversionNeeded) {
609     return;
610   }
611 
612   if (XipLength > (2 * TotalNecessaryFileSize)) {
613     VerboseMsg ("PE/COFF conversion to XIP appears to be larger than necessary.");
614     VerboseMsg ("The image linking process may have left unused memory ranges.");
615   }
616 
617   if (PeHdr->Pe32.FileHeader.PointerToSymbolTable != 0) {
618     //
619     // This field is obsolete and should be zero
620     //
621     PeHdr->Pe32.FileHeader.PointerToSymbolTable = 0;
622   }
623 
624   //
625   // Allocate the extra space that we need to grow the image
626   //
627   XipFile = malloc (XipLength);
628   if (XipFile == NULL) {
629     Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
630     return;
631   }
632   memset (XipFile, 0, XipLength);
633 
634   //
635   // Copy the file headers
636   //
637   memcpy (XipFile, *FileBuffer, PeHdr->Pe32.OptionalHeader.SizeOfHeaders);
638 
639   NewPeHdr = GetPeCoffHeader ((void *)XipFile);
640   if (NewPeHdr == NULL) {
641     free (XipFile);
642     return;
643   }
644 
645   //
646   // Copy the section data over to the appropriate XIP offsets
647   //
648   SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(NewPeHdr->Pe32.OptionalHeader) + NewPeHdr->Pe32.FileHeader.SizeOfOptionalHeader);
649   for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) {
650     if (SectionHeader->SizeOfRawData > 0) {
651       memcpy (
652         XipFile + SectionHeader->VirtualAddress,
653         *FileBuffer + SectionHeader->PointerToRawData,
654         SectionHeader->SizeOfRawData
655         );
656     }
657     //
658     // Make the size of raw data in section header alignment.
659     //
660     SectionHeader->SizeOfRawData = (SectionHeader->Misc.VirtualSize + PeHdr->Pe32.OptionalHeader.FileAlignment - 1) & (~(PeHdr->Pe32.OptionalHeader.FileAlignment - 1));
661     SectionHeader->PointerToRawData = SectionHeader->VirtualAddress;
662   }
663 
664   free (*FileBuffer);
665   *FileLength = XipLength;
666   *FileBuffer = XipFile;
667 }
668 
669 UINT8 *
CreateHiiResouceSectionHeader(UINT32 * pSectionHeaderSize,UINT32 HiiDataSize)670 CreateHiiResouceSectionHeader (
671   UINT32 *pSectionHeaderSize,
672   UINT32 HiiDataSize
673   )
674 /*++
675 
676 Routine Description:
677 
678   Create COFF resource section header
679 
680 Arguments:
681 
682   pSectionHeaderSize - Pointer to section header size.
683   HiiDataSize        - Size of the total HII data in section.
684 
685 Returns:
686   The created section header buffer.
687 
688 --*/
689 {
690   UINT32  HiiSectionHeaderSize;
691   UINT32  HiiSectionOffset;
692   UINT8   *HiiSectionHeader;
693   EFI_IMAGE_RESOURCE_DIRECTORY        *ResourceDirectory;
694   EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY  *TypeResourceDirectoryEntry;
695   EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY  *NameResourceDirectoryEntry;
696   EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY  *LanguageResourceDirectoryEntry;
697   EFI_IMAGE_RESOURCE_DIRECTORY_STRING *ResourceDirectoryString;
698   EFI_IMAGE_RESOURCE_DATA_ENTRY       *ResourceDataEntry;
699 
700   //
701   // Calculate the total size for the resource header (include Type, Name and Language)
702   // then allocate memory for the resource header.
703   //
704   HiiSectionHeaderSize = 3 * (sizeof (EFI_IMAGE_RESOURCE_DIRECTORY) + sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY))
705                           + 3 * (sizeof (UINT16) + 3 * sizeof (CHAR16))
706                           + sizeof (EFI_IMAGE_RESOURCE_DATA_ENTRY);
707   HiiSectionHeader = malloc (HiiSectionHeaderSize);
708   if (HiiSectionHeader == NULL) {
709     Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
710     return NULL;
711   }
712   memset (HiiSectionHeader, 0, HiiSectionHeaderSize);
713 
714   HiiSectionOffset = 0;
715   //
716   // Create Type entry
717   //
718   ResourceDirectory = (EFI_IMAGE_RESOURCE_DIRECTORY *) (HiiSectionHeader + HiiSectionOffset);
719   HiiSectionOffset += sizeof (EFI_IMAGE_RESOURCE_DIRECTORY);
720   ResourceDirectory->NumberOfNamedEntries = 1;
721   TypeResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *) (HiiSectionHeader + HiiSectionOffset);
722   HiiSectionOffset += sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY);
723   TypeResourceDirectoryEntry->u1.s.NameIsString      = 1;
724   TypeResourceDirectoryEntry->u2.s.DataIsDirectory   = 1;
725   TypeResourceDirectoryEntry->u2.s.OffsetToDirectory = HiiSectionOffset;
726   //
727   // Create Name entry
728   //
729   ResourceDirectory = (EFI_IMAGE_RESOURCE_DIRECTORY *) (HiiSectionHeader + HiiSectionOffset);
730   HiiSectionOffset += sizeof (EFI_IMAGE_RESOURCE_DIRECTORY);
731   ResourceDirectory->NumberOfNamedEntries = 1;
732   NameResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *) (HiiSectionHeader + HiiSectionOffset);
733   HiiSectionOffset += sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY);
734   NameResourceDirectoryEntry->u1.s.NameIsString      = 1;
735   NameResourceDirectoryEntry->u2.s.DataIsDirectory   = 1;
736   NameResourceDirectoryEntry->u2.s.OffsetToDirectory = HiiSectionOffset;
737   //
738   // Create Language entry
739   //
740   ResourceDirectory = (EFI_IMAGE_RESOURCE_DIRECTORY *) (HiiSectionHeader + HiiSectionOffset);
741   HiiSectionOffset += sizeof (EFI_IMAGE_RESOURCE_DIRECTORY);
742   ResourceDirectory->NumberOfNamedEntries = 1;
743   LanguageResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *) (HiiSectionHeader + HiiSectionOffset);
744   HiiSectionOffset += sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY);
745   LanguageResourceDirectoryEntry->u1.s.NameIsString = 1;
746   //
747   // Create string entry for Type
748   //
749   TypeResourceDirectoryEntry->u1.s.NameOffset = HiiSectionOffset;
750   ResourceDirectoryString = (EFI_IMAGE_RESOURCE_DIRECTORY_STRING *) (HiiSectionHeader + HiiSectionOffset);
751   ResourceDirectoryString->Length = 3;
752   ResourceDirectoryString->String[0] = L'H';
753   ResourceDirectoryString->String[1] = L'I';
754   ResourceDirectoryString->String[2] = L'I';
755   HiiSectionOffset = HiiSectionOffset + sizeof (ResourceDirectoryString->Length) + ResourceDirectoryString->Length * sizeof (ResourceDirectoryString->String[0]);
756   //
757   // Create string entry for Name
758   //
759   NameResourceDirectoryEntry->u1.s.NameOffset = HiiSectionOffset;
760   ResourceDirectoryString = (EFI_IMAGE_RESOURCE_DIRECTORY_STRING *) (HiiSectionHeader + HiiSectionOffset);
761   ResourceDirectoryString->Length = 3;
762   ResourceDirectoryString->String[0] = L'E';
763   ResourceDirectoryString->String[1] = L'F';
764   ResourceDirectoryString->String[2] = L'I';
765   HiiSectionOffset = HiiSectionOffset + sizeof (ResourceDirectoryString->Length) + ResourceDirectoryString->Length * sizeof (ResourceDirectoryString->String[0]);
766   //
767   // Create string entry for Language
768   //
769   LanguageResourceDirectoryEntry->u1.s.NameOffset = HiiSectionOffset;
770   ResourceDirectoryString = (EFI_IMAGE_RESOURCE_DIRECTORY_STRING *) (HiiSectionHeader + HiiSectionOffset);
771   ResourceDirectoryString->Length = 3;
772   ResourceDirectoryString->String[0] = L'B';
773   ResourceDirectoryString->String[1] = L'I';
774   ResourceDirectoryString->String[2] = L'N';
775   HiiSectionOffset = HiiSectionOffset + sizeof (ResourceDirectoryString->Length) + ResourceDirectoryString->Length * sizeof (ResourceDirectoryString->String[0]);
776   //
777   // Create Leaf data
778   //
779   LanguageResourceDirectoryEntry->u2.OffsetToData = HiiSectionOffset;
780   ResourceDataEntry = (EFI_IMAGE_RESOURCE_DATA_ENTRY *) (HiiSectionHeader + HiiSectionOffset);
781   HiiSectionOffset += sizeof (EFI_IMAGE_RESOURCE_DATA_ENTRY);
782   ResourceDataEntry->OffsetToData = HiiSectionOffset;
783   ResourceDataEntry->Size = HiiDataSize;
784 
785   *pSectionHeaderSize = HiiSectionHeaderSize;
786   return HiiSectionHeader;
787 }
788 
789 EFI_STATUS
RebaseImageRead(IN VOID * FileHandle,IN UINTN FileOffset,IN OUT UINT32 * ReadSize,OUT VOID * Buffer)790 RebaseImageRead (
791   IN     VOID    *FileHandle,
792   IN     UINTN   FileOffset,
793   IN OUT UINT32  *ReadSize,
794   OUT    VOID    *Buffer
795   )
796 /*++
797 
798 Routine Description:
799 
800   Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
801 
802 Arguments:
803 
804   FileHandle - The handle to the PE/COFF file
805 
806   FileOffset - The offset, in bytes, into the file to read
807 
808   ReadSize   - The number of bytes to read from the file starting at FileOffset
809 
810   Buffer     - A pointer to the buffer to read the data into.
811 
812 Returns:
813 
814   EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
815 
816 --*/
817 {
818   CHAR8   *Destination8;
819   CHAR8   *Source8;
820   UINT32  Length;
821 
822   Destination8  = Buffer;
823   Source8       = (CHAR8 *) ((UINTN) FileHandle + FileOffset);
824   Length        = *ReadSize;
825   while (Length--) {
826     *(Destination8++) = *(Source8++);
827   }
828 
829   return EFI_SUCCESS;
830 }
831 
832 EFI_STATUS
SetAddressToSectionHeader(IN CHAR8 * FileName,IN OUT UINT8 * FileBuffer,IN UINT64 NewPe32BaseAddress)833 SetAddressToSectionHeader (
834   IN     CHAR8   *FileName,
835   IN OUT UINT8   *FileBuffer,
836   IN     UINT64  NewPe32BaseAddress
837   )
838 /*++
839 
840 Routine Description:
841 
842   Set new base address into the section header of PeImage
843 
844 Arguments:
845 
846   FileName           - Name of file
847   FileBuffer         - Pointer to PeImage.
848   NewPe32BaseAddress - New Base Address for PE image.
849 
850 Returns:
851 
852   EFI_SUCCESS          Set new base address into this image successfully.
853 
854 --*/
855 {
856   EFI_STATUS                            Status;
857   PE_COFF_LOADER_IMAGE_CONTEXT          ImageContext;
858   UINTN                                 Index;
859   EFI_IMAGE_OPTIONAL_HEADER_UNION       *ImgHdr;
860   EFI_IMAGE_SECTION_HEADER              *SectionHeader;
861 
862   //
863   // Initialize context
864   //
865   memset (&ImageContext, 0, sizeof (ImageContext));
866   ImageContext.Handle     = (VOID *) FileBuffer;
867   ImageContext.ImageRead  = (PE_COFF_LOADER_READ_FILE) RebaseImageRead;
868   Status                  = PeCoffLoaderGetImageInfo (&ImageContext);
869   if (EFI_ERROR (Status)) {
870     Error (NULL, 0, 3000, "Invalid", "The input PeImage %s is not valid", FileName);
871     return Status;
872   }
873 
874   if (ImageContext.RelocationsStripped) {
875     Error (NULL, 0, 3000, "Invalid", "The input PeImage %s has no relocation to be fixed up", FileName);
876     return Status;
877   }
878 
879   //
880   // Get PeHeader pointer
881   //
882   ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer + ImageContext.PeCoffHeaderOffset);
883 
884   //
885   // Get section header list
886   //
887   SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (
888     (UINTN) ImgHdr +
889     sizeof (UINT32) +
890     sizeof (EFI_IMAGE_FILE_HEADER) +
891     ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader
892     );
893 
894   //
895   // Set base address into the first section header that doesn't point to code section.
896   //
897   for (Index = 0; Index < ImgHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) {
898     if ((SectionHeader->Characteristics & EFI_IMAGE_SCN_CNT_CODE) == 0) {
899       *(UINT64 *) &SectionHeader->PointerToRelocations = NewPe32BaseAddress;
900       break;
901     }
902   }
903 
904   //
905   // BaseAddress is set to section header.
906   //
907   return EFI_SUCCESS;
908 }
909 
910 EFI_STATUS
RebaseImage(IN CHAR8 * FileName,IN OUT UINT8 * FileBuffer,IN UINT64 NewPe32BaseAddress)911 RebaseImage (
912   IN     CHAR8   *FileName,
913   IN OUT UINT8   *FileBuffer,
914   IN     UINT64  NewPe32BaseAddress
915   )
916 /*++
917 
918 Routine Description:
919 
920   Set new base address into PeImage, and fix up PeImage based on new address.
921 
922 Arguments:
923 
924   FileName           - Name of file
925   FileBuffer         - Pointer to PeImage.
926   NewPe32BaseAddress - New Base Address for PE image.
927 
928 Returns:
929 
930   EFI_INVALID_PARAMETER   - BaseAddress is not valid.
931   EFI_SUCCESS             - Update PeImage is correctly.
932 
933 --*/
934 {
935   EFI_STATUS                            Status;
936   PE_COFF_LOADER_IMAGE_CONTEXT          ImageContext;
937   UINTN                                 Index;
938   EFI_IMAGE_OPTIONAL_HEADER_UNION       *ImgHdr;
939   UINT8                                 *MemoryImagePointer;
940   EFI_IMAGE_SECTION_HEADER              *SectionHeader;
941 
942   //
943   // Initialize context
944   //
945   memset (&ImageContext, 0, sizeof (ImageContext));
946   ImageContext.Handle     = (VOID *) FileBuffer;
947   ImageContext.ImageRead  = (PE_COFF_LOADER_READ_FILE) RebaseImageRead;
948   Status                  = PeCoffLoaderGetImageInfo (&ImageContext);
949   if (EFI_ERROR (Status)) {
950     Error (NULL, 0, 3000, "Invalid", "The input PeImage %s is not valid", FileName);
951     return Status;
952   }
953 
954   if (ImageContext.RelocationsStripped) {
955     Error (NULL, 0, 3000, "Invalid", "The input PeImage %s has no relocation to be fixed up", FileName);
956     return Status;
957   }
958 
959   //
960   // Get PeHeader pointer
961   //
962   ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer + ImageContext.PeCoffHeaderOffset);
963 
964   //
965   // Load and Relocate Image Data
966   //
967   MemoryImagePointer = (UINT8 *) malloc ((UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment);
968   if (MemoryImagePointer == NULL) {
969     Error (NULL, 0, 4001, "Resource", "memory cannot be allocated on rebase of %s", FileName);
970     return EFI_OUT_OF_RESOURCES;
971   }
972   memset ((VOID *) MemoryImagePointer, 0, (UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment);
973   ImageContext.ImageAddress = ((UINTN) MemoryImagePointer + ImageContext.SectionAlignment - 1) & (~((INT64)ImageContext.SectionAlignment - 1));
974 
975   Status =  PeCoffLoaderLoadImage (&ImageContext);
976   if (EFI_ERROR (Status)) {
977     Error (NULL, 0, 3000, "Invalid", "LocateImage() call failed on rebase of %s", FileName);
978     free ((VOID *) MemoryImagePointer);
979     return Status;
980   }
981 
982   ImageContext.DestinationAddress = NewPe32BaseAddress;
983   Status                          = PeCoffLoaderRelocateImage (&ImageContext);
984   if (EFI_ERROR (Status)) {
985     Error (NULL, 0, 3000, "Invalid", "RelocateImage() call failed on rebase of %s", FileName);
986     free ((VOID *) MemoryImagePointer);
987     return Status;
988   }
989 
990   //
991   // Copy Relocated data to raw image file.
992   //
993   SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (
994     (UINTN) ImgHdr +
995     sizeof (UINT32) +
996     sizeof (EFI_IMAGE_FILE_HEADER) +
997     ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader
998     );
999 
1000   for (Index = 0; Index < ImgHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) {
1001     CopyMem (
1002       FileBuffer + SectionHeader->PointerToRawData,
1003       (VOID*) (UINTN) (ImageContext.ImageAddress + SectionHeader->VirtualAddress),
1004       SectionHeader->SizeOfRawData
1005       );
1006   }
1007 
1008   free ((VOID *) MemoryImagePointer);
1009 
1010   //
1011   // Update Image Base Address
1012   //
1013   if ((ImgHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) && (ImgHdr->Pe32.FileHeader.Machine != IMAGE_FILE_MACHINE_IA64)) {
1014     ImgHdr->Pe32.OptionalHeader.ImageBase = (UINT32) NewPe32BaseAddress;
1015   } else if (ImgHdr->Pe32Plus.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
1016     ImgHdr->Pe32Plus.OptionalHeader.ImageBase = NewPe32BaseAddress;
1017   } else {
1018     Error (NULL, 0, 3000, "Invalid", "unknown PE magic signature %X in PE32 image %s",
1019       ImgHdr->Pe32.OptionalHeader.Magic,
1020       FileName
1021       );
1022     return EFI_ABORTED;
1023   }
1024 
1025   //
1026   // Set new base address into section header
1027   //
1028   Status = SetAddressToSectionHeader (FileName, FileBuffer, NewPe32BaseAddress);
1029 
1030   return Status;
1031 }
1032 
1033 int
main(int argc,char * argv[])1034 main (
1035   int  argc,
1036   char *argv[]
1037   )
1038 /*++
1039 
1040 Routine Description:
1041 
1042   Main function.
1043 
1044 Arguments:
1045 
1046   argc - Number of command line parameters.
1047   argv - Array of pointers to command line parameter strings.
1048 
1049 Returns:
1050   STATUS_SUCCESS - Utility exits successfully.
1051   STATUS_ERROR   - Some error occurred during execution.
1052 
1053 --*/
1054 {
1055   UINT32                           Type;
1056   UINT32                           InputFileNum;
1057   CHAR8                            **InputFileName;
1058   char                             *OutImageName;
1059   char                             *ModuleType;
1060   CHAR8                            *TimeStamp;
1061   FILE                             *fpIn;
1062   FILE                             *fpOut;
1063   FILE                             *fpInOut;
1064   UINT32                           Data;
1065   UINT32                           *DataPointer;
1066   UINT32                           *OldDataPointer;
1067   UINT32                           CheckSum;
1068   UINT32                           Index;
1069   UINT32                           Index1;
1070   UINT32                           Index2;
1071   UINT64                           Temp64;
1072   UINT32                           MciAlignment;
1073   UINT8                            MciPadValue;
1074   UINT32                           AllignedRelocSize;
1075   UINT8                            *FileBuffer;
1076   UINT32                           FileLength;
1077   UINT8                            *OutputFileBuffer;
1078   UINT32                           OutputFileLength;
1079   UINT8                            *InputFileBuffer;
1080   UINT32                           InputFileLength;
1081   RUNTIME_FUNCTION                 *RuntimeFunction;
1082   UNWIND_INFO                      *UnwindInfo;
1083   STATUS                           Status;
1084   BOOLEAN                          ReplaceFlag;
1085   BOOLEAN                          KeepExceptionTableFlag;
1086   BOOLEAN                          KeepOptionalHeaderFlag;
1087   BOOLEAN                          KeepZeroPendingFlag;
1088   UINT64                           LogLevel;
1089   EFI_TE_IMAGE_HEADER              TEImageHeader;
1090   EFI_TE_IMAGE_HEADER              *TeHdr;
1091   EFI_IMAGE_SECTION_HEADER         *SectionHeader;
1092   EFI_IMAGE_DOS_HEADER             *DosHdr;
1093   EFI_IMAGE_OPTIONAL_HEADER_UNION  *PeHdr;
1094   EFI_IMAGE_OPTIONAL_HEADER32      *Optional32;
1095   EFI_IMAGE_OPTIONAL_HEADER64      *Optional64;
1096   EFI_IMAGE_DOS_HEADER             BackupDosHdr;
1097   MICROCODE_IMAGE_HEADER           *MciHeader;
1098   UINT8                            *HiiPackageListBuffer;
1099   UINT8                            *HiiPackageDataPointer;
1100   EFI_GUID                         HiiPackageListGuid;
1101   EFI_HII_PACKAGE_LIST_HEADER      HiiPackageListHeader;
1102   EFI_HII_PACKAGE_HEADER           HiiPackageHeader;
1103   EFI_IFR_FORM_SET                 IfrFormSet;
1104   UINT8                            NumberOfFormPackage;
1105   EFI_HII_PACKAGE_HEADER           EndPackage;
1106   UINT32                           HiiSectionHeaderSize;
1107   UINT8                            *HiiSectionHeader;
1108   UINT64                           NewBaseAddress;
1109   BOOLEAN                          NegativeAddr;
1110   FILE                             *ReportFile;
1111   CHAR8                            *ReportFileName;
1112   UINTN                            FileLen;
1113   time_t                           InputFileTime;
1114   time_t                           OutputFileTime;
1115   struct stat                      Stat_Buf;
1116 
1117   SetUtilityName (UTILITY_NAME);
1118 
1119   //
1120   // Assign to fix compile warning
1121   //
1122   FileLen           = 0;
1123   InputFileNum      = 0;
1124   InputFileName     = NULL;
1125   mInImageName      = NULL;
1126   OutImageName      = NULL;
1127   ModuleType        = NULL;
1128   Type              = 0;
1129   Status            = STATUS_SUCCESS;
1130   FileBuffer        = NULL;
1131   fpIn              = NULL;
1132   fpOut             = NULL;
1133   fpInOut           = NULL;
1134   TimeStamp         = NULL;
1135   MciAlignment      = DEFAULT_MC_ALIGNMENT;
1136   MciPadValue       = DEFAULT_MC_PAD_BYTE_VALUE;
1137   FileLength        = 0;
1138   MciHeader         = NULL;
1139   CheckSum          = 0;
1140   ReplaceFlag       = FALSE;
1141   LogLevel          = 0;
1142   OutputFileBuffer  = NULL;
1143   OutputFileLength  = 0;
1144   InputFileBuffer   = NULL;
1145   InputFileLength   = 0;
1146   Optional32        = NULL;
1147   Optional64        = NULL;
1148   KeepExceptionTableFlag = FALSE;
1149   KeepOptionalHeaderFlag = FALSE;
1150   KeepZeroPendingFlag    = FALSE;
1151   NumberOfFormPackage    = 0;
1152   HiiPackageListBuffer   = NULL;
1153   HiiPackageDataPointer  = NULL;
1154   EndPackage.Length      = sizeof (EFI_HII_PACKAGE_HEADER);
1155   EndPackage.Type        = EFI_HII_PACKAGE_END;
1156   memset (&HiiPackageListGuid, 0, sizeof (HiiPackageListGuid));
1157   HiiSectionHeaderSize   = 0;
1158   HiiSectionHeader       = NULL;
1159   NewBaseAddress         = 0;
1160   NegativeAddr           = FALSE;
1161   InputFileTime          = 0;
1162   OutputFileTime         = 0;
1163 
1164   if (argc == 1) {
1165     Error (NULL, 0, 1001, "Missing options", "No input options.");
1166     Usage ();
1167     return STATUS_ERROR;
1168   }
1169 
1170   argc --;
1171   argv ++;
1172 
1173   if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) {
1174     Version ();
1175     Usage ();
1176     return STATUS_SUCCESS;
1177   }
1178 
1179   if (stricmp (argv[0], "--version") == 0) {
1180     Version ();
1181     return STATUS_SUCCESS;
1182   }
1183 
1184   while (argc > 0) {
1185     if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--outputfile") == 0)) {
1186       if (argv[1] == NULL || argv[1][0] == '-') {
1187         Error (NULL, 0, 1003, "Invalid option value", "Output file name is missing for -o option");
1188         goto Finish;
1189       }
1190       OutImageName = argv[1];
1191       argc -= 2;
1192       argv += 2;
1193       continue;
1194     }
1195 
1196     if ((stricmp (argv[0], "-e") == 0) || (stricmp (argv[0], "--efiImage") == 0)) {
1197       if (argv[1] == NULL || argv[1][0] == '-') {
1198         Error (NULL, 0, 1003, "Invalid option value", "Module Type is missing for -o option");
1199         goto Finish;
1200       }
1201       ModuleType = argv[1];
1202       if (mOutImageType != FW_TE_IMAGE) {
1203         mOutImageType = FW_EFI_IMAGE;
1204       }
1205       argc -= 2;
1206       argv += 2;
1207       continue;
1208     }
1209 
1210     if ((stricmp (argv[0], "-l") == 0) || (stricmp (argv[0], "--stripped") == 0)) {
1211       mOutImageType = FW_RELOC_STRIPEED_IMAGE;
1212       argc --;
1213       argv ++;
1214       continue;
1215     }
1216 
1217     if ((stricmp (argv[0], "-c") == 0) || (stricmp (argv[0], "--acpi") == 0)) {
1218       mOutImageType = FW_ACPI_IMAGE;
1219       argc --;
1220       argv ++;
1221       continue;
1222     }
1223 
1224     if ((stricmp (argv[0], "-t") == 0) || (stricmp (argv[0], "--terse") == 0)) {
1225       mOutImageType = FW_TE_IMAGE;
1226       argc --;
1227       argv ++;
1228       continue;
1229     }
1230 
1231     if ((stricmp (argv[0], "-u") == 0) || (stricmp (argv[0], "--dump") == 0)) {
1232       mOutImageType = DUMP_TE_HEADER;
1233       argc --;
1234       argv ++;
1235       continue;
1236     }
1237 
1238     if ((stricmp (argv[0], "-b") == 0) || (stricmp (argv[0], "--exe2bin") == 0)) {
1239       mOutImageType = FW_BIN_IMAGE;
1240       argc --;
1241       argv ++;
1242       continue;
1243     }
1244 
1245     if ((stricmp (argv[0], "-z") == 0) || (stricmp (argv[0], "--zero") == 0)) {
1246       mOutImageType = FW_ZERO_DEBUG_IMAGE;
1247       argc --;
1248       argv ++;
1249       continue;
1250     }
1251 
1252     if ((stricmp (argv[0], "-s") == 0) || (stricmp (argv[0], "--stamp") == 0)) {
1253       mOutImageType = FW_SET_STAMP_IMAGE;
1254       if (argv[1] == NULL || argv[1][0] == '-') {
1255         Error (NULL, 0, 1003, "Invalid option value", "time stamp is missing for -s option");
1256         goto Finish;
1257       }
1258       TimeStamp = argv[1];
1259       argc -= 2;
1260       argv += 2;
1261       continue;
1262     }
1263 
1264     if ((stricmp (argv[0], "-r") == 0) || (stricmp (argv[0], "--replace") == 0)) {
1265       ReplaceFlag = TRUE;
1266       argc --;
1267       argv ++;
1268       continue;
1269     }
1270 
1271     if (stricmp (argv[0], "--keepexceptiontable") == 0) {
1272       KeepExceptionTableFlag = TRUE;
1273       argc --;
1274       argv ++;
1275       continue;
1276     }
1277 
1278     if (stricmp(argv[0], "--keepoptionalheader") == 0) {
1279       KeepOptionalHeaderFlag = TRUE;
1280       argc--;
1281       argv++;
1282       continue;
1283     }
1284 
1285     if (stricmp (argv[0], "--keepzeropending") == 0) {
1286       KeepZeroPendingFlag = TRUE;
1287       argc --;
1288       argv ++;
1289       continue;
1290     }
1291 
1292     if ((stricmp (argv[0], "-m") == 0) || (stricmp (argv[0], "--mcifile") == 0)) {
1293       mOutImageType = FW_MCI_IMAGE;
1294       argc --;
1295       argv ++;
1296       continue;
1297     }
1298 
1299     if ((stricmp (argv[0], "-j") == 0) || (stricmp (argv[0], "--join") == 0)) {
1300       mOutImageType = FW_MERGE_IMAGE;
1301       argc --;
1302       argv ++;
1303       continue;
1304     }
1305 
1306     if ((stricmp (argv[0], "-a") == 0) || (stricmp (argv[0], "--align") == 0)) {
1307       if (AsciiStringToUint64 (argv[1], FALSE, &Temp64) != EFI_SUCCESS) {
1308         Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
1309         goto Finish;
1310       }
1311       MciAlignment = (UINT32) Temp64;
1312       argc -= 2;
1313       argv += 2;
1314       continue;
1315     }
1316 
1317     if ((stricmp (argv[0], "--rebase") == 0)) {
1318       if (argv[1][0] == '-') {
1319         NegativeAddr = TRUE;
1320         Status = AsciiStringToUint64 (argv[1] + 1, FALSE, &Temp64);
1321       } else {
1322         NegativeAddr = FALSE;
1323         Status = AsciiStringToUint64 (argv[1], FALSE, &Temp64);
1324       }
1325       if (Status != EFI_SUCCESS) {
1326         Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
1327         goto Finish;
1328       }
1329       mOutImageType = FW_REBASE_IMAGE;
1330       NewBaseAddress = (UINT64) Temp64;
1331       argc -= 2;
1332       argv += 2;
1333       continue;
1334     }
1335 
1336     if ((stricmp (argv[0], "--address") == 0)) {
1337       if (argv[1][0] == '-') {
1338         NegativeAddr = TRUE;
1339         Status = AsciiStringToUint64 (argv[1] + 1, FALSE, &Temp64);
1340       } else {
1341         NegativeAddr = FALSE;
1342         Status = AsciiStringToUint64 (argv[1], FALSE, &Temp64);
1343       }
1344       if (Status != EFI_SUCCESS) {
1345         Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
1346         goto Finish;
1347       }
1348       mOutImageType = FW_SET_ADDRESS_IMAGE;
1349       NewBaseAddress = (UINT64) Temp64;
1350       argc -= 2;
1351       argv += 2;
1352       continue;
1353     }
1354 
1355     if ((stricmp (argv[0], "-p") == 0) || (stricmp (argv[0], "--pad") == 0)) {
1356       if (AsciiStringToUint64 (argv[1], FALSE, &Temp64) != EFI_SUCCESS) {
1357         Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
1358         goto Finish;
1359       }
1360       MciPadValue = (UINT8) Temp64;
1361       argc -= 2;
1362       argv += 2;
1363       continue;
1364     }
1365 
1366     if ((stricmp (argv[0], "-v") == 0) || (stricmp (argv[0], "--verbose") == 0)) {
1367       SetPrintLevel (VERBOSE_LOG_LEVEL);
1368       VerboseMsg ("Verbose output Mode Set!");
1369       argc --;
1370       argv ++;
1371       continue;
1372     }
1373 
1374     if ((stricmp (argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) {
1375       SetPrintLevel (KEY_LOG_LEVEL);
1376       KeyMsg ("Quiet output Mode Set!");
1377       argc --;
1378       argv ++;
1379       continue;
1380     }
1381 
1382     if ((stricmp (argv[0], "-d") == 0) || (stricmp (argv[0], "--debug") == 0)) {
1383       Status = AsciiStringToUint64 (argv[1], FALSE, &LogLevel);
1384       if (EFI_ERROR (Status)) {
1385         Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
1386         goto Finish;
1387       }
1388       if (LogLevel > 9) {
1389         Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0-9, currnt input level is %d", (int) LogLevel);
1390         goto Finish;
1391       }
1392       SetPrintLevel (LogLevel);
1393       DebugMsg (NULL, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv[1]);
1394       argc -= 2;
1395       argv += 2;
1396       continue;
1397     }
1398 
1399     if ((stricmp (argv[0], "-g") == 0) || (stricmp (argv[0], "--hiiguid") == 0)) {
1400       Status = StringToGuid (argv[1], &HiiPackageListGuid);
1401       if (EFI_ERROR (Status)) {
1402         Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
1403         goto Finish;
1404       }
1405       argc -= 2;
1406       argv += 2;
1407       continue;
1408     }
1409 
1410     if (stricmp (argv[0], "--hiipackage") == 0) {
1411       mOutImageType = FW_HII_PACKAGE_LIST_RCIMAGE;
1412       argc --;
1413       argv ++;
1414       continue;
1415     }
1416 
1417     if (stricmp (argv[0], "--hiibinpackage") == 0) {
1418       mOutImageType = FW_HII_PACKAGE_LIST_BINIMAGE;
1419       argc --;
1420       argv ++;
1421       continue;
1422     }
1423 
1424     if (argv[0][0] == '-') {
1425       Error (NULL, 0, 1000, "Unknown option", argv[0]);
1426       goto Finish;
1427     }
1428     //
1429     // Get Input file name
1430     //
1431     if ((InputFileNum == 0) && (InputFileName == NULL)) {
1432       InputFileName = (CHAR8 **) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *));
1433       if (InputFileName == NULL) {
1434         Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
1435         goto Finish;
1436       }
1437 
1438       memset (InputFileName, 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));
1439     } else if (InputFileNum % MAXIMUM_INPUT_FILE_NUM == 0) {
1440       //
1441       // InputFileName buffer too small, need to realloc
1442       //
1443       InputFileName = (CHAR8 **) realloc (
1444         InputFileName,
1445         (InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (CHAR8 *)
1446         );
1447 
1448       if (InputFileName == NULL) {
1449         Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
1450         goto Finish;
1451       }
1452 
1453       memset (&(InputFileName[InputFileNum]), 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));
1454     }
1455 
1456     InputFileName [InputFileNum ++] = argv[0];
1457     argc --;
1458     argv ++;
1459   }
1460 
1461   VerboseMsg ("%s tool start.", UTILITY_NAME);
1462 
1463   if (mOutImageType == FW_DUMMY_IMAGE) {
1464     Error (NULL, 0, 1001, "Missing option", "No create file action specified; pls specify -e, -c or -t option to create efi image, or acpi table or TeImage!");
1465     if (ReplaceFlag) {
1466       Error (NULL, 0, 1001, "Missing option", "-r option is not supported as the independent option. It can be used together with other create file option specified at the above.");
1467     }
1468     goto Finish;
1469   }
1470 
1471   //
1472   // check input files
1473   //
1474   if (InputFileNum == 0) {
1475     Error (NULL, 0, 1001, "Missing option", "Input files");
1476     goto Finish;
1477   }
1478 
1479   //
1480   // Combine MciBinary files to one file
1481   //
1482   if ((mOutImageType == FW_MERGE_IMAGE) && ReplaceFlag) {
1483     Error (NULL, 0, 1002, "Conflicting option", "-r replace option cannot be used with -j merge files option.");
1484     goto Finish;
1485   }
1486 
1487   //
1488   // Combine HiiBinary packages to a single package list
1489   //
1490   if ((mOutImageType == FW_HII_PACKAGE_LIST_RCIMAGE) && ReplaceFlag) {
1491     Error (NULL, 0, 1002, "Conflicting option", "-r replace option cannot be used with --hiipackage merge files option.");
1492     goto Finish;
1493   }
1494 
1495   if ((mOutImageType == FW_HII_PACKAGE_LIST_BINIMAGE) && ReplaceFlag) {
1496     Error (NULL, 0, 1002, "Conflicting option", "-r replace option cannot be used with --hiibinpackage merge files option.");
1497     goto Finish;
1498   }
1499 
1500   //
1501   // Input image file
1502   //
1503   mInImageName = InputFileName [InputFileNum - 1];
1504   VerboseMsg ("the input file name is %s", mInImageName);
1505 
1506   //
1507   // Action will be taken for the input file.
1508   //
1509   switch (mOutImageType) {
1510   case FW_EFI_IMAGE:
1511     VerboseMsg ("Create efi image on module type %s based on the input PE image.", ModuleType);
1512     break;
1513   case FW_TE_IMAGE:
1514     VerboseMsg ("Create Te Image based on the input PE image.");
1515     break;
1516   case FW_ACPI_IMAGE:
1517     VerboseMsg ("Get acpi table data from the input PE image.");
1518     break;
1519   case FW_RELOC_STRIPEED_IMAGE:
1520     VerboseMsg ("Remove relocation section from Pe or Te image.");
1521     break;
1522   case FW_BIN_IMAGE:
1523     VerboseMsg ("Convert the input EXE to the output BIN file.");
1524     break;
1525   case FW_ZERO_DEBUG_IMAGE:
1526     VerboseMsg ("Zero the Debug Data Fields and Time Stamp in input PE image.");
1527     break;
1528   case FW_SET_STAMP_IMAGE:
1529     VerboseMsg ("Set new time stamp %s in the input PE image.", TimeStamp);
1530     break;
1531   case DUMP_TE_HEADER:
1532     VerboseMsg ("Dump the TE header information of the input TE image.");
1533     break;
1534   case FW_MCI_IMAGE:
1535     VerboseMsg ("Conver input MicroCode.txt file to MicroCode.bin file.");
1536     break;
1537   case FW_MERGE_IMAGE:
1538     VerboseMsg ("Combine the input multi microcode bin files to one bin file.");
1539     break;
1540   case FW_HII_PACKAGE_LIST_RCIMAGE:
1541     VerboseMsg ("Combine the input multi hii bin packages to one text pacakge list RC file.");
1542     break;
1543   case FW_HII_PACKAGE_LIST_BINIMAGE:
1544     VerboseMsg ("Combine the input multi hii bin packages to one binary pacakge list file.");
1545     break;
1546   case FW_REBASE_IMAGE:
1547     VerboseMsg ("Rebase the input image to new base address.");
1548     break;
1549   case FW_SET_ADDRESS_IMAGE:
1550     VerboseMsg ("Set the preferred address into the section header of the input image");
1551     break;
1552   default:
1553     break;
1554   }
1555 
1556   if (ReplaceFlag) {
1557     VerboseMsg ("Overwrite the input file with the output content.");
1558   }
1559 
1560   //
1561   // Open output file and Write image into the output file.
1562   //
1563   if (OutImageName != NULL) {
1564     fpOut = fopen (LongFilePath (OutImageName), "rb");
1565     if (fpOut != NULL) {
1566       //
1567       // Get Output file time stamp
1568       //
1569       fstat(fileno (fpOut), &Stat_Buf);
1570       OutputFileTime = Stat_Buf.st_mtime;
1571       //
1572       // Get Output file data
1573       //
1574       OutputFileLength = _filelength (fileno (fpOut));
1575       OutputFileBuffer = malloc (OutputFileLength);
1576       if (OutputFileBuffer == NULL) {
1577         Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
1578         fclose (fpOut);
1579         fpOut = NULL;
1580         goto Finish;
1581       }
1582       fread (OutputFileBuffer, 1, OutputFileLength, fpOut);
1583       fclose (fpOut);
1584       fpOut = NULL;
1585     }
1586     VerboseMsg ("Output file name is %s", OutImageName);
1587   } else if (!ReplaceFlag && mOutImageType != DUMP_TE_HEADER) {
1588     Error (NULL, 0, 1001, "Missing option", "output file");
1589     goto Finish;
1590   }
1591 
1592   //
1593   // Open input file and read file data into file buffer.
1594   //
1595   fpIn = fopen (LongFilePath (mInImageName), "rb");
1596   if (fpIn == NULL) {
1597     Error (NULL, 0, 0001, "Error opening file", mInImageName);
1598     goto Finish;
1599   }
1600   //
1601   // Get Iutput file time stamp
1602   //
1603   fstat(fileno (fpIn), &Stat_Buf);
1604   InputFileTime = Stat_Buf.st_mtime;
1605   //
1606   // Get Input file data
1607   //
1608   InputFileLength = _filelength (fileno (fpIn));
1609   InputFileBuffer = malloc (InputFileLength);
1610   if (InputFileBuffer == NULL) {
1611     Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
1612     fclose (fpIn);
1613     goto Finish;
1614   }
1615   fread (InputFileBuffer, 1, InputFileLength, fpIn);
1616   fclose (fpIn);
1617   DebugMsg (NULL, 0, 9, "input file info", "the input file size is %u bytes", (unsigned) InputFileLength);
1618 
1619   //
1620   // Combine multi binary HII package files.
1621   //
1622   if (mOutImageType == FW_HII_PACKAGE_LIST_RCIMAGE || mOutImageType == FW_HII_PACKAGE_LIST_BINIMAGE) {
1623     //
1624     // Open output file handle.
1625     //
1626     fpOut = fopen (LongFilePath (OutImageName), "wb");
1627     if (!fpOut) {
1628       Error (NULL, 0, 0001, "Error opening output file", OutImageName);
1629       goto Finish;
1630     }
1631     //
1632     // Get hii package list lenght
1633     //
1634     HiiPackageListHeader.PackageLength = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
1635     for (Index = 0; Index < InputFileNum; Index ++) {
1636       fpIn = fopen (LongFilePath (InputFileName [Index]), "rb");
1637       if (fpIn == NULL) {
1638         Error (NULL, 0, 0001, "Error opening file", InputFileName [Index]);
1639         goto Finish;
1640       }
1641       FileLength = _filelength (fileno (fpIn));
1642       fread (&HiiPackageHeader, 1, sizeof (HiiPackageHeader), fpIn);
1643       if (HiiPackageHeader.Type == EFI_HII_PACKAGE_FORM) {
1644         if (HiiPackageHeader.Length != FileLength) {
1645           Error (NULL, 0, 3000, "Invalid", "The wrong package size is in HII package file %s", InputFileName [Index]);
1646           fclose (fpIn);
1647           goto Finish;
1648         }
1649         if (memcmp (&HiiPackageListGuid, &mZeroGuid, sizeof (EFI_GUID)) == 0) {
1650           fread (&IfrFormSet, 1, sizeof (IfrFormSet), fpIn);
1651           memcpy (&HiiPackageListGuid, &IfrFormSet.Guid, sizeof (EFI_GUID));
1652         }
1653         NumberOfFormPackage ++;
1654       }
1655       HiiPackageListHeader.PackageLength += FileLength;
1656       fclose (fpIn);
1657     }
1658     HiiPackageListHeader.PackageLength += sizeof (EndPackage);
1659     //
1660     // Check whether hii packages are valid
1661     //
1662     if (NumberOfFormPackage > 1) {
1663       Error (NULL, 0, 3000, "Invalid", "The input hii packages contains more than one hii form package");
1664       goto Finish;
1665     }
1666     if (memcmp (&HiiPackageListGuid, &mZeroGuid, sizeof (EFI_GUID)) == 0) {
1667       Error (NULL, 0, 3000, "Invalid", "HII pacakge list guid is not specified!");
1668       goto Finish;
1669     }
1670     memcpy (&HiiPackageListHeader.PackageListGuid, &HiiPackageListGuid, sizeof (EFI_GUID));
1671     //
1672     // read hii packages
1673     //
1674     HiiPackageListBuffer = malloc (HiiPackageListHeader.PackageLength);
1675     if (HiiPackageListBuffer == NULL) {
1676       Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
1677       goto Finish;
1678     }
1679     memcpy (HiiPackageListBuffer, &HiiPackageListHeader, sizeof (HiiPackageListHeader));
1680     HiiPackageDataPointer = HiiPackageListBuffer + sizeof (HiiPackageListHeader);
1681     for (Index = 0; Index < InputFileNum; Index ++) {
1682       fpIn = fopen (LongFilePath (InputFileName [Index]), "rb");
1683       if (fpIn == NULL) {
1684         Error (NULL, 0, 0001, "Error opening file", InputFileName [Index]);
1685         free (HiiPackageListBuffer);
1686         goto Finish;
1687       }
1688 
1689       FileLength = _filelength (fileno (fpIn));
1690       fread (HiiPackageDataPointer, 1, FileLength, fpIn);
1691       fclose (fpIn);
1692       HiiPackageDataPointer = HiiPackageDataPointer + FileLength;
1693     }
1694     memcpy (HiiPackageDataPointer, &EndPackage, sizeof (EndPackage));
1695 
1696     //
1697     // write the hii package into the binary package list file with the resource section header
1698     //
1699     if (mOutImageType == FW_HII_PACKAGE_LIST_BINIMAGE) {
1700       //
1701       // Create the resource section header
1702       //
1703       HiiSectionHeader = CreateHiiResouceSectionHeader (&HiiSectionHeaderSize, HiiPackageListHeader.PackageLength);
1704       if (HiiSectionHeader == NULL) {
1705         free (HiiPackageListBuffer);
1706         goto Finish;
1707       }
1708       //
1709       // Wrtie section header and HiiData into File.
1710       //
1711       fwrite (HiiSectionHeader, 1, HiiSectionHeaderSize, fpOut);
1712       fwrite (HiiPackageListBuffer, 1, HiiPackageListHeader.PackageLength, fpOut);
1713       //
1714       // Free allocated resources.
1715       //
1716       free (HiiSectionHeader);
1717       free (HiiPackageListBuffer);
1718       //
1719       // Done successfully
1720       //
1721       goto Finish;
1722     }
1723 
1724     //
1725     // write the hii package into the text package list rc file.
1726     //
1727     if (mOutImageType == FW_HII_PACKAGE_LIST_RCIMAGE) {
1728       for (Index = 0; gHiiPackageRCFileHeader[Index] != NULL; Index++) {
1729         fprintf (fpOut, "%s\n", gHiiPackageRCFileHeader[Index]);
1730       }
1731       fprintf (fpOut, "\n%d %s\n{", HII_RESOURCE_SECTION_INDEX, HII_RESOURCE_SECTION_NAME);
1732 
1733       HiiPackageDataPointer = HiiPackageListBuffer;
1734       for (Index = 0; Index + 2 < HiiPackageListHeader.PackageLength; Index += 2) {
1735         if (Index % 16 == 0) {
1736           fprintf (fpOut, "\n ");
1737         }
1738         fprintf (fpOut, " 0x%04X,", *(UINT16 *) HiiPackageDataPointer);
1739         HiiPackageDataPointer += 2;
1740       }
1741 
1742       if (Index % 16 == 0) {
1743         fprintf (fpOut, "\n ");
1744       }
1745       if ((Index + 2) == HiiPackageListHeader.PackageLength) {
1746         fprintf (fpOut, " 0x%04X\n}\n", *(UINT16 *) HiiPackageDataPointer);
1747       }
1748       if ((Index + 1) == HiiPackageListHeader.PackageLength) {
1749         fprintf (fpOut, " 0x%04X\n}\n", *(UINT8 *) HiiPackageDataPointer);
1750       }
1751       free (HiiPackageListBuffer);
1752       //
1753       // Done successfully
1754       //
1755       goto Finish;
1756     }
1757   }
1758 
1759   //
1760   // Combine MciBinary files to one file
1761   //
1762   if (mOutImageType == FW_MERGE_IMAGE) {
1763     //
1764     // Open output file handle.
1765     //
1766     fpOut = fopen (LongFilePath (OutImageName), "wb");
1767     if (!fpOut) {
1768       Error (NULL, 0, 0001, "Error opening output file", OutImageName);
1769       goto Finish;
1770     }
1771     for (Index = 0; Index < InputFileNum; Index ++) {
1772       fpIn = fopen (LongFilePath (InputFileName [Index]), "rb");
1773       if (!fpIn) {
1774         Error (NULL, 0, 0001, "Error opening file", InputFileName [Index]);
1775         goto Finish;
1776       }
1777 
1778       FileLength = _filelength (fileno (fpIn));
1779       FileBuffer = malloc (FileLength);
1780       if (FileBuffer == NULL) {
1781         Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
1782         fclose (fpIn);
1783         goto Finish;
1784       }
1785 
1786       fread (FileBuffer, 1, FileLength, fpIn);
1787       fclose (fpIn);
1788       //
1789       // write input file to out file
1790       //
1791       fwrite (FileBuffer, 1, FileLength, fpOut);
1792       //
1793       // write pad value to out file.
1794       //
1795       while (FileLength ++ % MciAlignment != 0) {
1796         fwrite (&MciPadValue, 1, 1, fpOut);
1797       }
1798       //
1799       // free allocated memory space
1800       //
1801       free (FileBuffer);
1802       FileBuffer = NULL;
1803     }
1804     //
1805     // Done successfully
1806     //
1807     goto Finish;
1808   }
1809 
1810   //
1811   // Convert MicroCode.txt file to MicroCode.bin file
1812   //
1813   if (mOutImageType == FW_MCI_IMAGE) {
1814     fpIn = fopen (LongFilePath (mInImageName), "r");
1815     if (fpIn == NULL) {
1816       Error (NULL, 0, 0001, "Error opening file", mInImageName);
1817       goto Finish;
1818     }
1819 
1820     //
1821     // The first pass is to determine
1822     // how much data is in the file so we can allocate a working buffer.
1823     //
1824     FileLength = 0;
1825     do {
1826       Status = MicrocodeReadData (fpIn, &Data);
1827       if (Status == STATUS_SUCCESS) {
1828         FileLength += sizeof (Data);
1829       }
1830       if (Status == STATUS_IGNORE) {
1831         Status = STATUS_SUCCESS;
1832       }
1833     } while (Status == STATUS_SUCCESS);
1834     //
1835     // Error if no data.
1836     //
1837     if (FileLength == 0) {
1838       Error (NULL, 0, 3000, "Invalid", "no parseable data found in file %s", mInImageName);
1839       goto Finish;
1840     }
1841     if (FileLength < sizeof (MICROCODE_IMAGE_HEADER)) {
1842       Error (NULL, 0, 3000, "Invalid", "amount of parseable data in %s is insufficient to contain a microcode header", mInImageName);
1843       goto Finish;
1844     }
1845 
1846     //
1847     // Allocate a buffer for the data
1848     //
1849     FileBuffer = malloc (FileLength);
1850     if (FileBuffer == NULL) {
1851       Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
1852       goto Finish;
1853     }
1854     //
1855     // Re-read the file, storing the data into our buffer
1856     //
1857     fseek (fpIn, 0, SEEK_SET);
1858     DataPointer = (UINT32 *) FileBuffer;
1859     OldDataPointer = DataPointer;
1860     do {
1861       OldDataPointer = DataPointer;
1862       Status = MicrocodeReadData (fpIn, DataPointer++);
1863       if (Status == STATUS_IGNORE) {
1864         DataPointer = OldDataPointer;
1865         Status = STATUS_SUCCESS;
1866       }
1867     } while (Status == STATUS_SUCCESS);
1868     //
1869     // close input file after read data
1870     //
1871     fclose (fpIn);
1872 
1873     //
1874     // Can't do much checking on the header because, per the spec, the
1875     // DataSize field may be 0, which means DataSize = 2000 and TotalSize = 2K,
1876     // and the TotalSize field is invalid (actually missing). Thus we can't
1877     // even verify the Reserved fields are 0.
1878     //
1879     MciHeader = (MICROCODE_IMAGE_HEADER *) FileBuffer;
1880     if (MciHeader->DataSize == 0) {
1881       Index = 2048;
1882     } else {
1883       Index = MciHeader->TotalSize;
1884     }
1885 
1886     if (Index != FileLength) {
1887       Error (NULL, 0, 3000, "Invalid", "file length of %s (0x%x) does not equal expected TotalSize: 0x%04X.", mInImageName, (unsigned) FileLength, (unsigned) Index);
1888       goto Finish;
1889     }
1890 
1891     //
1892     // Checksum the contents
1893     //
1894     DataPointer = (UINT32 *) FileBuffer;
1895     CheckSum  = 0;
1896     Index     = 0;
1897     while (Index < FileLength) {
1898       CheckSum    += *DataPointer;
1899       DataPointer ++;
1900       Index       += sizeof (*DataPointer);
1901     }
1902     if (CheckSum != 0) {
1903       Error (NULL, 0, 3000, "Invalid", "checksum (0x%x) failed on file %s.", (unsigned) CheckSum, mInImageName);
1904       goto Finish;
1905     }
1906     //
1907     // Open the output file and write the buffer contents
1908     //
1909     VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength);
1910     goto WriteFile;
1911   }
1912 
1913   //
1914   // Open input file and read file data into file buffer.
1915   //
1916   FileLength = InputFileLength;
1917   FileBuffer = malloc (FileLength);
1918   if (FileBuffer == NULL) {
1919     Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
1920     goto Finish;
1921   }
1922   memcpy (FileBuffer, InputFileBuffer, InputFileLength);
1923 
1924   //
1925   // Dump TeImage Header into output file.
1926   //
1927   if (mOutImageType == DUMP_TE_HEADER) {
1928     memcpy (&TEImageHeader, FileBuffer, sizeof (TEImageHeader));
1929     if (TEImageHeader.Signature != EFI_TE_IMAGE_HEADER_SIGNATURE) {
1930       Error (NULL, 0, 3000, "Invalid", "TE header signature of file %s is not correct.", mInImageName);
1931       goto Finish;
1932     }
1933     //
1934     // Open the output file handle.
1935     //
1936     if (ReplaceFlag) {
1937       fpInOut = fopen (LongFilePath (mInImageName), "wb");
1938       if (fpInOut == NULL) {
1939         Error (NULL, 0, 0001, "Error opening file", mInImageName);
1940         goto Finish;
1941       }
1942     } else {
1943       if (OutImageName != NULL) {
1944         fpOut = fopen (LongFilePath (OutImageName), "wb");
1945       } else {
1946         fpOut = stdout;
1947       }
1948       if (fpOut == NULL) {
1949         Error (NULL, 0, 0001, "Error opening output file", OutImageName);
1950         goto Finish;
1951       }
1952     }
1953     if (fpInOut != NULL) {
1954       fprintf (fpInOut, "Dump of file %s\n\n", mInImageName);
1955       fprintf (fpInOut, "TE IMAGE HEADER VALUES\n");
1956       fprintf (fpInOut, "%17X machine\n", TEImageHeader.Machine);
1957       fprintf (fpInOut, "%17X number of sections\n", TEImageHeader.NumberOfSections);
1958       fprintf (fpInOut, "%17X subsystems\n", TEImageHeader.Subsystem);
1959       fprintf (fpInOut, "%17X stripped size\n", TEImageHeader.StrippedSize);
1960       fprintf (fpInOut, "%17X entry point\n", (unsigned) TEImageHeader.AddressOfEntryPoint);
1961       fprintf (fpInOut, "%17X base of code\n", (unsigned) TEImageHeader.BaseOfCode);
1962       fprintf (fpInOut, "%17llX image base\n", (unsigned long long)TEImageHeader.ImageBase);
1963       fprintf (fpInOut, "%17X [%8X] RVA [size] of Base Relocation Directory\n", (unsigned) TEImageHeader.DataDirectory[0].VirtualAddress, (unsigned) TEImageHeader.DataDirectory[0].Size);
1964       fprintf (fpInOut, "%17X [%8X] RVA [size] of Debug Directory\n", (unsigned) TEImageHeader.DataDirectory[1].VirtualAddress, (unsigned) TEImageHeader.DataDirectory[1].Size);
1965     }
1966     if (fpOut != NULL) {
1967       fprintf (fpOut, "Dump of file %s\n\n", mInImageName);
1968       fprintf (fpOut, "TE IMAGE HEADER VALUES\n");
1969       fprintf (fpOut, "%17X machine\n", TEImageHeader.Machine);
1970       fprintf (fpOut, "%17X number of sections\n", TEImageHeader.NumberOfSections);
1971       fprintf (fpOut, "%17X subsystems\n", TEImageHeader.Subsystem);
1972       fprintf (fpOut, "%17X stripped size\n", TEImageHeader.StrippedSize);
1973       fprintf (fpOut, "%17X entry point\n", (unsigned) TEImageHeader.AddressOfEntryPoint);
1974       fprintf (fpOut, "%17X base of code\n", (unsigned) TEImageHeader.BaseOfCode);
1975       fprintf (fpOut, "%17llX image base\n", (unsigned long long)TEImageHeader.ImageBase);
1976       fprintf (fpOut, "%17X [%8X] RVA [size] of Base Relocation Directory\n", (unsigned) TEImageHeader.DataDirectory[0].VirtualAddress, (unsigned) TEImageHeader.DataDirectory[0].Size);
1977       fprintf (fpOut, "%17X [%8X] RVA [size] of Debug Directory\n", (unsigned) TEImageHeader.DataDirectory[1].VirtualAddress, (unsigned) TEImageHeader.DataDirectory[1].Size);
1978     }
1979     goto Finish;
1980   }
1981 
1982   //
1983   // Following code to convert dll to efi image or te image.
1984   // Get new image type
1985   //
1986   if ((mOutImageType == FW_EFI_IMAGE) || (mOutImageType == FW_TE_IMAGE)) {
1987     if (ModuleType == NULL) {
1988       if (mOutImageType == FW_EFI_IMAGE) {
1989         Error (NULL, 0, 1001, "Missing option", "EFI_FILETYPE");
1990         goto Finish;
1991       } else if (mOutImageType == FW_TE_IMAGE) {
1992         //
1993         // Default TE Image Type is Boot service driver
1994         //
1995         Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER;
1996         VerboseMsg ("Efi Image subsystem type is efi boot service driver.");
1997       }
1998     } else {
1999       if (stricmp (ModuleType, "BASE") == 0 ||
2000         stricmp (ModuleType, "SEC") == 0 ||
2001         stricmp (ModuleType, "SECURITY_CORE") == 0 ||
2002         stricmp (ModuleType, "PEI_CORE") == 0 ||
2003         stricmp (ModuleType, "PEIM") == 0 ||
2004         stricmp (ModuleType, "COMBINED_PEIM_DRIVER") == 0 ||
2005         stricmp (ModuleType, "PIC_PEIM") == 0 ||
2006         stricmp (ModuleType, "RELOCATABLE_PEIM") == 0 ||
2007         stricmp (ModuleType, "DXE_CORE") == 0 ||
2008         stricmp (ModuleType, "BS_DRIVER") == 0  ||
2009         stricmp (ModuleType, "DXE_DRIVER") == 0 ||
2010         stricmp (ModuleType, "DXE_SMM_DRIVER") == 0  ||
2011         stricmp (ModuleType, "UEFI_DRIVER") == 0 ||
2012         stricmp (ModuleType, "SMM_CORE") == 0) {
2013           Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER;
2014           VerboseMsg ("Efi Image subsystem type is efi boot service driver.");
2015 
2016       } else if (stricmp (ModuleType, "UEFI_APPLICATION") == 0 ||
2017         stricmp (ModuleType, "APPLICATION") == 0) {
2018           Type = EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION;
2019           VerboseMsg ("Efi Image subsystem type is efi application.");
2020 
2021       } else if (stricmp (ModuleType, "DXE_RUNTIME_DRIVER") == 0 ||
2022         stricmp (ModuleType, "RT_DRIVER") == 0) {
2023           Type = EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER;
2024           VerboseMsg ("Efi Image subsystem type is efi runtime driver.");
2025 
2026       } else if (stricmp (ModuleType, "DXE_SAL_DRIVER") == 0 ||
2027         stricmp (ModuleType, "SAL_RT_DRIVER") == 0) {
2028           Type = EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER;
2029           VerboseMsg ("Efi Image subsystem type is efi sal runtime driver.");
2030 
2031       } else {
2032         Error (NULL, 0, 1003, "Invalid option value", "EFI_FILETYPE = %s", ModuleType);
2033         goto Finish;
2034       }
2035     }
2036   }
2037 
2038   //
2039   // Convert ELF image to PeImage
2040   //
2041   if (IsElfHeader(FileBuffer)) {
2042     VerboseMsg ("Convert %s from ELF to PE/COFF.", mInImageName);
2043     if (!ConvertElf(&FileBuffer, &FileLength)) {
2044       Error (NULL, 0, 3000, "Invalid", "Unable to convert %s from ELF to PE/COFF.", mInImageName);
2045       goto Finish;
2046     }
2047   }
2048 
2049   //
2050   // Make sure File Offsets and Virtual Offsets are the same in the image so it is XIP
2051   // XIP == eXecute In Place
2052   //
2053   PeCoffConvertImageToXip (&FileBuffer, &FileLength);
2054 
2055   //
2056   // Remove reloc section from PE or TE image
2057   //
2058   if (mOutImageType == FW_RELOC_STRIPEED_IMAGE) {
2059     //
2060     // Check TeImage
2061     //
2062     TeHdr = (EFI_TE_IMAGE_HEADER *) FileBuffer;
2063     if (TeHdr->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {
2064       SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (TeHdr + 1);
2065       for (Index = 0; Index < TeHdr->NumberOfSections; Index ++, SectionHeader ++) {
2066         if (strcmp ((char *)SectionHeader->Name, ".reloc") == 0) {
2067           //
2068           // Check the reloc section is in the end of image.
2069           //
2070           if ((SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData) ==
2071             (FileLength + TeHdr->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER))) {
2072               //
2073               // Remove .reloc section and update TeImage Header
2074               //
2075               FileLength = FileLength - SectionHeader->SizeOfRawData;
2076               SectionHeader->SizeOfRawData = 0;
2077               SectionHeader->Misc.VirtualSize = 0;
2078               TeHdr->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = 0;
2079               TeHdr->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size           = 0;
2080               break;
2081           }
2082         }
2083       }
2084     } else {
2085       //
2086       // Check PE Image
2087       //
2088       DosHdr = (EFI_IMAGE_DOS_HEADER *) FileBuffer;
2089       if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {
2090         PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer);
2091         if (PeHdr->Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) {
2092           Error (NULL, 0, 3000, "Invalid", "TE and DOS header signatures were not found in %s image.", mInImageName);
2093           goto Finish;
2094         }
2095         DosHdr = NULL;
2096       } else {
2097         PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer + DosHdr->e_lfanew);
2098         if (PeHdr->Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) {
2099           Error (NULL, 0, 3000, "Invalid", "PE header signature was not found in %s image.", mInImageName);
2100           goto Finish;
2101         }
2102       }
2103       SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);
2104       for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) {
2105         if (strcmp ((char *)SectionHeader->Name, ".reloc") == 0) {
2106           //
2107           // Check the reloc section is in the end of image.
2108           //
2109           if ((SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData) == FileLength) {
2110             //
2111             // Remove .reloc section and update PeImage Header
2112             //
2113             FileLength = FileLength - SectionHeader->SizeOfRawData;
2114 
2115             PeHdr->Pe32.FileHeader.Characteristics |= EFI_IMAGE_FILE_RELOCS_STRIPPED;
2116             if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
2117               Optional32 = (EFI_IMAGE_OPTIONAL_HEADER32 *)&PeHdr->Pe32.OptionalHeader;
2118               Optional32->SizeOfImage -= SectionHeader->SizeOfRawData;
2119               Optional32->SizeOfInitializedData -= SectionHeader->SizeOfRawData;
2120               if (Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {
2121                 Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = 0;
2122                 Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = 0;
2123               }
2124             }
2125             if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
2126               Optional64 = (EFI_IMAGE_OPTIONAL_HEADER64 *)&PeHdr->Pe32.OptionalHeader;
2127               Optional64->SizeOfImage -= SectionHeader->SizeOfRawData;
2128               Optional64->SizeOfInitializedData -= SectionHeader->SizeOfRawData;
2129               if (Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {
2130                 Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = 0;
2131                 Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = 0;
2132               }
2133             }
2134             SectionHeader->Misc.VirtualSize = 0;
2135             SectionHeader->SizeOfRawData = 0;
2136             break;
2137           }
2138         }
2139       }
2140     }
2141     //
2142     // Write file
2143     //
2144     goto WriteFile;
2145   }
2146   //
2147   // Read the dos & pe hdrs of the image
2148   //
2149   DosHdr = (EFI_IMAGE_DOS_HEADER *)FileBuffer;
2150   if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {
2151     // NO DOS header, check for PE/COFF header
2152     PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer);
2153     if (PeHdr->Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) {
2154       Error (NULL, 0, 3000, "Invalid", "DOS header signature was not found in %s image.", mInImageName);
2155       goto Finish;
2156     }
2157     DosHdr = NULL;
2158   } else {
2159 
2160     PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer + DosHdr->e_lfanew);
2161     if (PeHdr->Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) {
2162       Error (NULL, 0, 3000, "Invalid", "PE header signature was not found in %s image.", mInImageName);
2163       goto Finish;
2164     }
2165   }
2166 
2167   if (PeHdr->Pe32.FileHeader.Machine == IMAGE_FILE_MACHINE_ARM) {
2168     // Some tools kick out IMAGE_FILE_MACHINE_ARM (0x1c0) vs IMAGE_FILE_MACHINE_ARMT (0x1c2)
2169     // so patch back to the offical UEFI value.
2170     PeHdr->Pe32.FileHeader.Machine = IMAGE_FILE_MACHINE_ARMT;
2171   }
2172 
2173   //
2174   // Set new base address into image
2175   //
2176   if (mOutImageType == FW_REBASE_IMAGE || mOutImageType == FW_SET_ADDRESS_IMAGE) {
2177     if ((PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) && (PeHdr->Pe32.FileHeader.Machine != IMAGE_FILE_MACHINE_IA64)) {
2178       if (NewBaseAddress >= 0x100000000ULL) {
2179         Error (NULL, 0, 3000, "Invalid", "New base address is larger than 4G for 32bit PE image");
2180         goto Finish;
2181       }
2182     }
2183 
2184     if (NegativeAddr) {
2185       //
2186       // Set Base Address to a negative value.
2187       //
2188       NewBaseAddress = (UINT64) (0 - NewBaseAddress);
2189     }
2190     if (mOutImageType == FW_REBASE_IMAGE) {
2191       Status = RebaseImage (mInImageName, FileBuffer, NewBaseAddress);
2192     } else {
2193       Status = SetAddressToSectionHeader (mInImageName, FileBuffer, NewBaseAddress);
2194     }
2195     if (EFI_ERROR (Status)) {
2196       if (NegativeAddr) {
2197         Error (NULL, 0, 3000, "Invalid", "Rebase/Set Image %s to Base address -0x%llx can't success", mInImageName, 0 - NewBaseAddress);
2198       } else {
2199         Error (NULL, 0, 3000, "Invalid", "Rebase/Set Image %s to Base address 0x%llx can't success", mInImageName, NewBaseAddress);
2200       }
2201       goto Finish;
2202     }
2203 
2204     //
2205     // Write file
2206     //
2207     goto WriteFile;
2208   }
2209 
2210   //
2211   // Extract bin data from Pe image.
2212   //
2213   if (mOutImageType == FW_BIN_IMAGE) {
2214     if (FileLength < PeHdr->Pe32.OptionalHeader.SizeOfHeaders) {
2215       Error (NULL, 0, 3000, "Invalid", "FileSize of %s is not a legal size.", mInImageName);
2216       goto Finish;
2217     }
2218     //
2219     // Output bin data from exe file
2220     //
2221     FileLength = FileLength - PeHdr->Pe32.OptionalHeader.SizeOfHeaders;
2222     memmove (FileBuffer, FileBuffer + PeHdr->Pe32.OptionalHeader.SizeOfHeaders, FileLength);
2223     VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength);
2224     goto WriteFile;
2225   }
2226 
2227   //
2228   // Zero Debug Information of Pe Image
2229   //
2230   if (mOutImageType == FW_ZERO_DEBUG_IMAGE) {
2231     Status = ZeroDebugData (FileBuffer, TRUE);
2232     if (EFI_ERROR (Status)) {
2233       Error (NULL, 0, 3000, "Invalid", "Zero DebugData Error status is 0x%x", (int) Status);
2234       goto Finish;
2235     }
2236 
2237     //
2238     // Write the updated Image
2239     //
2240     VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength);
2241     goto WriteFile;
2242   }
2243 
2244   //
2245   // Set Time Stamp of Pe Image
2246   //
2247   if (mOutImageType == FW_SET_STAMP_IMAGE) {
2248     Status = SetStamp (FileBuffer, TimeStamp);
2249     if (EFI_ERROR (Status)) {
2250       goto Finish;
2251     }
2252 
2253     //
2254     // Write the updated Image
2255     //
2256     VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength);
2257     goto WriteFile;
2258   }
2259 
2260   //
2261   // Extract acpi data from pe image.
2262   //
2263   if (mOutImageType == FW_ACPI_IMAGE) {
2264     SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);
2265     for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) {
2266       if (strcmp ((char *)SectionHeader->Name, ".data") == 0 || strcmp ((char *)SectionHeader->Name, ".sdata") == 0) {
2267         //
2268         // Check Acpi Table
2269         //
2270         if (SectionHeader->Misc.VirtualSize < SectionHeader->SizeOfRawData) {
2271           FileLength = SectionHeader->Misc.VirtualSize;
2272         } else {
2273           FileLength = SectionHeader->SizeOfRawData;
2274         }
2275 
2276         if (CheckAcpiTable (FileBuffer + SectionHeader->PointerToRawData, FileLength) != STATUS_SUCCESS) {
2277           Error (NULL, 0, 3000, "Invalid", "ACPI table check failed in %s.", mInImageName);
2278           goto Finish;
2279         }
2280 
2281         //
2282         // Output Apci data to file
2283         //
2284         memmove (FileBuffer, FileBuffer + SectionHeader->PointerToRawData, FileLength);
2285         VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength);
2286         goto WriteFile;
2287       }
2288     }
2289     Error (NULL, 0, 3000, "Invalid", "failed to get ACPI table from %s.", mInImageName);
2290     goto Finish;
2291   }
2292   //
2293   // Zero all unused fields of the DOS header
2294   //
2295   if (DosHdr != NULL) {
2296     memcpy (&BackupDosHdr, DosHdr, sizeof (EFI_IMAGE_DOS_HEADER));
2297     memset (DosHdr, 0, sizeof (EFI_IMAGE_DOS_HEADER));
2298     DosHdr->e_magic  = BackupDosHdr.e_magic;
2299     DosHdr->e_lfanew = BackupDosHdr.e_lfanew;
2300 
2301     for (Index = sizeof (EFI_IMAGE_DOS_HEADER); Index < (UINT32 ) DosHdr->e_lfanew; Index++) {
2302       FileBuffer[Index] = (UINT8) DosHdr->e_cp;
2303     }
2304   }
2305 
2306   //
2307   // Initialize TeImage Header
2308   //
2309   memset (&TEImageHeader, 0, sizeof (EFI_TE_IMAGE_HEADER));
2310   TEImageHeader.Signature        = EFI_TE_IMAGE_HEADER_SIGNATURE;
2311   TEImageHeader.Machine          = PeHdr->Pe32.FileHeader.Machine;
2312   TEImageHeader.NumberOfSections = (UINT8) PeHdr->Pe32.FileHeader.NumberOfSections;
2313   TEImageHeader.StrippedSize     = (UINT16) ((UINTN) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader) - (UINTN) FileBuffer);
2314   TEImageHeader.Subsystem        = (UINT8) Type;
2315 
2316   //
2317   // Patch the PE header
2318   //
2319   PeHdr->Pe32.OptionalHeader.Subsystem = (UINT16) Type;
2320 
2321   if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
2322     Optional32 = (EFI_IMAGE_OPTIONAL_HEADER32 *)&PeHdr->Pe32.OptionalHeader;
2323     if (!KeepOptionalHeaderFlag) {
2324       Optional32->MajorOperatingSystemVersion = 0;
2325       Optional32->MinorOperatingSystemVersion = 0;
2326       Optional32->MajorImageVersion = 0;
2327       Optional32->MinorImageVersion = 0;
2328       Optional32->MajorSubsystemVersion = 0;
2329       Optional32->MinorSubsystemVersion = 0;
2330       Optional32->Win32VersionValue = 0;
2331       Optional32->CheckSum = 0;
2332       Optional32->SizeOfStackReserve = 0;
2333       Optional32->SizeOfStackCommit = 0;
2334       Optional32->SizeOfHeapReserve = 0;
2335       Optional32->SizeOfHeapCommit = 0;
2336     }
2337     TEImageHeader.AddressOfEntryPoint = Optional32->AddressOfEntryPoint;
2338     TEImageHeader.BaseOfCode          = Optional32->BaseOfCode;
2339     TEImageHeader.ImageBase           = (UINT64) (Optional32->ImageBase);
2340 
2341     if (Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {
2342       TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;
2343       TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
2344     }
2345 
2346     if (Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {
2347       TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
2348       TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size;
2349     }
2350 
2351     //
2352     // Zero .pdata section data.
2353     //
2354     if (!KeepExceptionTableFlag && Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION &&
2355       Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress != 0 &&
2356       Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size != 0) {
2357         SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);
2358         for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++, SectionHeader++) {
2359           if (SectionHeader->VirtualAddress == Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress) {
2360             //
2361             // Zero .pdata Section data
2362             //
2363             memset (FileBuffer + SectionHeader->PointerToRawData, 0, SectionHeader->SizeOfRawData);
2364             //
2365             // Zero .pdata Section header name
2366             //
2367             memset (SectionHeader->Name, 0, sizeof (SectionHeader->Name));
2368             //
2369             // Zero Execption Table
2370             //
2371             Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress = 0;
2372             Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size           = 0;
2373             DebugMsg (NULL, 0, 9, "Zero the .pdata section for PE image", NULL);
2374             break;
2375           }
2376         }
2377     }
2378 
2379     //
2380     // Strip zero padding at the end of the .reloc section
2381     //
2382     if (!KeepZeroPendingFlag && Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {
2383       if (Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size != 0) {
2384         SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);
2385         for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++, SectionHeader++) {
2386           //
2387           // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory
2388           //
2389           if (SectionHeader->VirtualAddress == Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress) {
2390             SectionHeader->Misc.VirtualSize = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
2391             AllignedRelocSize = (Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size + Optional32->FileAlignment - 1) & (~(Optional32->FileAlignment - 1));
2392             //
2393             // Check to see if there is zero padding at the end of the base relocations
2394             //
2395             if (AllignedRelocSize < SectionHeader->SizeOfRawData) {
2396               //
2397               // Check to see if the base relocations are at the end of the file
2398               //
2399               if (SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData == Optional32->SizeOfImage) {
2400                 //
2401                 // All the required conditions are met to strip the zero padding of the end of the base relocations section
2402                 //
2403                 Optional32->SizeOfImage -= (SectionHeader->SizeOfRawData - AllignedRelocSize);
2404                 Optional32->SizeOfInitializedData -= (SectionHeader->SizeOfRawData - AllignedRelocSize);
2405                 SectionHeader->SizeOfRawData = AllignedRelocSize;
2406                 FileLength = Optional32->SizeOfImage;
2407                 DebugMsg (NULL, 0, 9, "Remove the zero padding bytes at the end of the base relocations", "The size of padding bytes is %u", (unsigned) (SectionHeader->SizeOfRawData - AllignedRelocSize));
2408               }
2409             }
2410           }
2411         }
2412       }
2413     }
2414   } else if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
2415     Optional64 = (EFI_IMAGE_OPTIONAL_HEADER64 *)&PeHdr->Pe32.OptionalHeader;
2416     if (!KeepOptionalHeaderFlag) {
2417       Optional64->MajorOperatingSystemVersion = 0;
2418       Optional64->MinorOperatingSystemVersion = 0;
2419       Optional64->MajorImageVersion = 0;
2420       Optional64->MinorImageVersion = 0;
2421       Optional64->MajorSubsystemVersion = 0;
2422       Optional64->MinorSubsystemVersion = 0;
2423       Optional64->Win32VersionValue = 0;
2424       Optional64->CheckSum = 0;
2425       Optional64->SizeOfStackReserve = 0;
2426       Optional64->SizeOfStackCommit = 0;
2427       Optional64->SizeOfHeapReserve = 0;
2428       Optional64->SizeOfHeapCommit = 0;
2429     }
2430     TEImageHeader.AddressOfEntryPoint = Optional64->AddressOfEntryPoint;
2431     TEImageHeader.BaseOfCode          = Optional64->BaseOfCode;
2432     TEImageHeader.ImageBase           = (UINT64) (Optional64->ImageBase);
2433 
2434     if (Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {
2435       TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;
2436       TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
2437     }
2438 
2439     if (Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {
2440       TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
2441       TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size;
2442     }
2443 
2444     //
2445     // Zero the .pdata section for X64 machine and don't check the Debug Directory is empty
2446     // For Itaninum and X64 Image, remove .pdata section.
2447     //
2448     if ((!KeepExceptionTableFlag && PeHdr->Pe32.FileHeader.Machine == IMAGE_FILE_MACHINE_X64) || PeHdr->Pe32.FileHeader.Machine == IMAGE_FILE_MACHINE_IA64) {
2449       if (Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION &&
2450         Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress != 0 &&
2451         Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size != 0) {
2452           SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);
2453           for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++, SectionHeader++) {
2454             if (SectionHeader->VirtualAddress == Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress) {
2455               //
2456               // Zero .pdata Section header name
2457               //
2458               memset (SectionHeader->Name, 0, sizeof (SectionHeader->Name));
2459 
2460               RuntimeFunction = (RUNTIME_FUNCTION *)(FileBuffer + SectionHeader->PointerToRawData);
2461               for (Index1 = 0; Index1 < Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size / sizeof (RUNTIME_FUNCTION); Index1++, RuntimeFunction++) {
2462                 SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);
2463                 for (Index2 = 0; Index2 < PeHdr->Pe32.FileHeader.NumberOfSections; Index2++, SectionHeader++) {
2464                   if (RuntimeFunction->UnwindInfoAddress >= SectionHeader->VirtualAddress && RuntimeFunction->UnwindInfoAddress < (SectionHeader->VirtualAddress + SectionHeader->SizeOfRawData)) {
2465                     UnwindInfo = (UNWIND_INFO *)(FileBuffer + SectionHeader->PointerToRawData + (RuntimeFunction->UnwindInfoAddress - SectionHeader->VirtualAddress));
2466                     if (UnwindInfo->Version == 1) {
2467                       memset (UnwindInfo + 1, 0, UnwindInfo->CountOfUnwindCodes * sizeof (UINT16));
2468                       memset (UnwindInfo, 0, sizeof (UNWIND_INFO));
2469                     }
2470                     break;
2471                   }
2472                 }
2473                 memset (RuntimeFunction, 0, sizeof (RUNTIME_FUNCTION));
2474               }
2475               //
2476               // Zero Execption Table
2477               //
2478               Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size = 0;
2479               Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress = 0;
2480               DebugMsg (NULL, 0, 9, "Zero the .pdata section if the machine type is X64 for PE32+ image", NULL);
2481               break;
2482             }
2483           }
2484       }
2485     }
2486 
2487     //
2488     // Strip zero padding at the end of the .reloc section
2489     //
2490     if (!KeepZeroPendingFlag && Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {
2491       if (Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size != 0) {
2492         SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);
2493         for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++, SectionHeader++) {
2494           //
2495           // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory
2496           //
2497           if (SectionHeader->VirtualAddress == Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress) {
2498             SectionHeader->Misc.VirtualSize = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
2499             AllignedRelocSize = (Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size + Optional64->FileAlignment - 1) & (~(Optional64->FileAlignment - 1));
2500             //
2501             // Check to see if there is zero padding at the end of the base relocations
2502             //
2503             if (AllignedRelocSize < SectionHeader->SizeOfRawData) {
2504               //
2505               // Check to see if the base relocations are at the end of the file
2506               //
2507               if (SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData == Optional64->SizeOfImage) {
2508                 //
2509                 // All the required conditions are met to strip the zero padding of the end of the base relocations section
2510                 //
2511                 Optional64->SizeOfImage -= (SectionHeader->SizeOfRawData - AllignedRelocSize);
2512                 Optional64->SizeOfInitializedData -= (SectionHeader->SizeOfRawData - AllignedRelocSize);
2513                 SectionHeader->SizeOfRawData = AllignedRelocSize;
2514                 FileLength = Optional64->SizeOfImage;
2515                 DebugMsg (NULL, 0, 9, "Remove the zero padding bytes at the end of the base relocations", "The size of padding bytes is %u", (unsigned) (SectionHeader->SizeOfRawData - AllignedRelocSize));
2516               }
2517             }
2518           }
2519         }
2520       }
2521     }
2522   } else {
2523     Error (NULL, 0, 3000, "Invalid", "Magic 0x%x of PeImage %s is unknown.", PeHdr->Pe32.OptionalHeader.Magic, mInImageName);
2524     goto Finish;
2525   }
2526 
2527   if (((PeHdr->Pe32.FileHeader.Characteristics & EFI_IMAGE_FILE_RELOCS_STRIPPED) == 0) && \
2528     (TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress == 0) && \
2529     (TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size == 0)) {
2530       //
2531       // PeImage can be loaded into memory, but it has no relocation section.
2532       // Fix TeImage Header to set VA of relocation data directory to not zero, the size is still zero.
2533       //
2534       if (Optional32 != NULL) {
2535         TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = Optional32->SizeOfImage - sizeof (EFI_IMAGE_BASE_RELOCATION);
2536       } else if (Optional64 != NULL) {
2537         TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = Optional64->SizeOfImage - sizeof (EFI_IMAGE_BASE_RELOCATION);
2538       }
2539   }
2540 
2541   //
2542   // Fill HII section data
2543   //
2544   SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);
2545   for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++) {
2546     if (stricmp ((char *)SectionHeader[Index].Name, ".hii") == 0) {
2547       //
2548       // Update resource section header offset
2549       //
2550       SetHiiResourceHeader ((UINT8*) FileBuffer + SectionHeader[Index].PointerToRawData, SectionHeader[Index].VirtualAddress);
2551       //
2552       // Update resource section name
2553       //
2554       strcpy((char *) SectionHeader[Index].Name, ".rsrc");
2555       //
2556       // Update resource data directory.
2557       //
2558       if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
2559         Optional32 = (EFI_IMAGE_OPTIONAL_HEADER32 *)&PeHdr->Pe32.OptionalHeader;
2560         Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = SectionHeader[Index].VirtualAddress;
2561         Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = SectionHeader[Index].Misc.VirtualSize;
2562       } else if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
2563         Optional64 = (EFI_IMAGE_OPTIONAL_HEADER64 *)&PeHdr->Pe32.OptionalHeader;
2564         Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = SectionHeader[Index].VirtualAddress;
2565         Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = SectionHeader[Index].Misc.VirtualSize;
2566       }
2567       break;
2568     }
2569   }
2570 
2571   //
2572   // Zero ExceptionTable Xdata
2573   //
2574   if (!KeepExceptionTableFlag) {
2575     SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);
2576     for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++) {
2577       if (stricmp ((char *)SectionHeader[Index].Name, ".xdata") == 0) {
2578         //
2579         // zero .xdata section
2580         //
2581         memset (FileBuffer + SectionHeader[Index].PointerToRawData, 0, SectionHeader[Index].SizeOfRawData);
2582         DebugMsg (NULL, 0, 9, NULL, "Zero the .xdata section for PE image at Offset 0x%x and Length 0x%x", (unsigned) SectionHeader[Index].PointerToRawData, (unsigned) SectionHeader[Index].SizeOfRawData);
2583         break;
2584       }
2585     }
2586   }
2587 
2588   //
2589   // Zero Time/Data field
2590   //
2591   ZeroDebugData (FileBuffer, FALSE);
2592 
2593   if (mOutImageType == FW_TE_IMAGE) {
2594     if ((PeHdr->Pe32.FileHeader.NumberOfSections &~0xFF) || (Type &~0xFF)) {
2595       //
2596       // Pack the subsystem and NumberOfSections into 1 byte. Make sure they fit both.
2597       //
2598       Error (NULL, 0, 3000, "Invalid", "Image's subsystem or NumberOfSections of PeImage %s cannot be packed into 1 byte.", mInImageName);
2599       goto Finish;
2600     }
2601 
2602     if ((PeHdr->Pe32.OptionalHeader.SectionAlignment != PeHdr->Pe32.OptionalHeader.FileAlignment)) {
2603       //
2604       // TeImage has the same section alignment and file alignment.
2605       //
2606       Error (NULL, 0, 3000, "Invalid", "Section-Alignment and File-Alignment of PeImage %s do not match, they must be equal for a TeImage.", mInImageName);
2607       goto Finish;
2608     }
2609 
2610     DebugMsg (NULL, 0, 9, "TeImage Header Info", "Machine type is %X, Number of sections is %X, Stripped size is %X, EntryPoint is %X, BaseOfCode is %X, ImageBase is %llX",
2611       TEImageHeader.Machine, TEImageHeader.NumberOfSections, TEImageHeader.StrippedSize, (unsigned) TEImageHeader.AddressOfEntryPoint, (unsigned) TEImageHeader.BaseOfCode, (unsigned long long) TEImageHeader.ImageBase);
2612     //
2613     // Update Image to TeImage
2614     //
2615     FileLength = FileLength - TEImageHeader.StrippedSize;
2616     memmove (FileBuffer + sizeof (EFI_TE_IMAGE_HEADER), FileBuffer + TEImageHeader.StrippedSize, FileLength);
2617     FileLength = FileLength + sizeof (EFI_TE_IMAGE_HEADER);
2618     memcpy (FileBuffer, &TEImageHeader, sizeof (EFI_TE_IMAGE_HEADER));
2619     VerboseMsg ("the size of output file is %u bytes", (unsigned) (FileLength));
2620   } else {
2621 
2622     //
2623     // Following codes are to fix the objcopy's issue:
2624     // objcopy in binutil 2.50.18 will set PE image's charactices to "RELOC_STRIPPED" if image has no ".reloc" section
2625     // It cause issue for EFI image which has no ".reloc" sections.
2626     // Following codes will be removed when objcopy in binutil fix this problem for PE image.
2627     //
2628     if ((PeHdr->Pe32.FileHeader.Characteristics & EFI_IMAGE_FILE_RELOCS_STRIPPED) != 0) {
2629       if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
2630         Optional32 = (EFI_IMAGE_OPTIONAL_HEADER32 *)&PeHdr->Pe32.OptionalHeader;
2631         if (Optional32->ImageBase == 0) {
2632           PeHdr->Pe32.FileHeader.Characteristics &= ~EFI_IMAGE_FILE_RELOCS_STRIPPED;
2633         }
2634       } else if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
2635         Optional64 = (EFI_IMAGE_OPTIONAL_HEADER64 *)&PeHdr->Pe32.OptionalHeader;
2636         if (Optional64->ImageBase == 0) {
2637           PeHdr->Pe32.FileHeader.Characteristics &= ~EFI_IMAGE_FILE_RELOCS_STRIPPED;
2638         }
2639       }
2640     }
2641   }
2642 
2643 WriteFile:
2644   //
2645   // Update Image to EfiImage or TE image
2646   //
2647   if (ReplaceFlag) {
2648     if ((FileLength != InputFileLength) || (memcmp (FileBuffer, InputFileBuffer, FileLength) != 0)) {
2649       //
2650       // Update File when File is changed.
2651       //
2652       fpInOut = fopen (LongFilePath (mInImageName), "wb");
2653       if (fpInOut == NULL) {
2654         Error (NULL, 0, 0001, "Error opening file", mInImageName);
2655         goto Finish;
2656       }
2657       fwrite (FileBuffer, 1, FileLength, fpInOut);
2658       VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength);
2659     }
2660   } else {
2661     if ((OutputFileTime < InputFileTime) || (FileLength != OutputFileLength) || (memcmp (FileBuffer, OutputFileBuffer, FileLength) != 0)) {
2662       //
2663       // Update File when File is changed or File is old.
2664       //
2665       fpOut = fopen (LongFilePath (OutImageName), "wb");
2666       if (fpOut == NULL) {
2667         Error (NULL, 0, 0001, "Error opening output file", OutImageName);
2668         goto Finish;
2669       }
2670       fwrite (FileBuffer, 1, FileLength, fpOut);
2671       VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength);
2672     }
2673   }
2674   mImageSize = FileLength;
2675 
2676 Finish:
2677   if (fpInOut != NULL) {
2678     if (GetUtilityStatus () != STATUS_SUCCESS) {
2679       //
2680       // when file updates failed, original file is still recovered.
2681       //
2682       fwrite (InputFileBuffer, 1, InputFileLength, fpInOut);
2683     }
2684     //
2685     // Write converted data into fpInOut file and close input file.
2686     //
2687     fclose (fpInOut);
2688   }
2689 
2690   if (FileBuffer != NULL) {
2691     free (FileBuffer);
2692   }
2693 
2694   if (InputFileName != NULL) {
2695     free (InputFileName);
2696   }
2697 
2698   if (fpOut != NULL) {
2699     //
2700     // Write converted data into fpOut file and close output file.
2701     //
2702     fclose (fpOut);
2703     if (GetUtilityStatus () != STATUS_SUCCESS) {
2704       if (OutputFileBuffer == NULL) {
2705         remove (OutImageName);
2706       } else {
2707         fpOut = fopen (LongFilePath (OutImageName), "wb");
2708         fwrite (OutputFileBuffer, 1, OutputFileLength, fpOut);
2709         fclose (fpOut);
2710       }
2711     }
2712   }
2713 
2714   if (InputFileBuffer != NULL) {
2715     free (InputFileBuffer);
2716   }
2717 
2718   if (OutputFileBuffer != NULL) {
2719     free (OutputFileBuffer);
2720   }
2721 
2722   //
2723   // Write module size and time stamp to report file.
2724   //
2725   if (OutImageName != NULL) {
2726     FileLen = strlen (OutImageName);
2727   }
2728   if (FileLen >= 4 && strcmp (OutImageName + (FileLen - 4), ".efi") == 0) {
2729     ReportFileName = (CHAR8 *) malloc (FileLen + 1);
2730     if (ReportFileName != NULL) {
2731       strcpy (ReportFileName, OutImageName);
2732       strcpy (ReportFileName + (FileLen - 4), ".txt");
2733       ReportFile = fopen (LongFilePath (ReportFileName), "w+");
2734       if (ReportFile != NULL) {
2735         fprintf (ReportFile, "MODULE_SIZE = %u\n", (unsigned) mImageSize);
2736         fprintf (ReportFile, "TIME_STAMP = %u\n", (unsigned) mImageTimeStamp);
2737         fclose(ReportFile);
2738       }
2739       free (ReportFileName);
2740     }
2741   }
2742   VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME, GetUtilityStatus ());
2743 
2744   return GetUtilityStatus ();
2745 }
2746 
2747 STATIC
2748 EFI_STATUS
ZeroDebugData(IN OUT UINT8 * FileBuffer,BOOLEAN ZeroDebugFlag)2749 ZeroDebugData (
2750   IN OUT UINT8   *FileBuffer,
2751   BOOLEAN        ZeroDebugFlag
2752   )
2753 /*++
2754 
2755 Routine Description:
2756 
2757   Zero debug information in PeImage.
2758 
2759 Arguments:
2760 
2761   FileBuffer    - Pointer to PeImage.
2762   ZeroDebugFlag - TRUE to zero Debug information, FALSE to only zero time/stamp
2763 
2764 Returns:
2765 
2766   EFI_ABORTED   - PeImage is invalid.
2767   EFI_SUCCESS   - Zero debug data successfully.
2768 
2769 --*/
2770 {
2771   UINT32                           Index;
2772   UINT32                           DebugDirectoryEntryRva;
2773   UINT32                           DebugDirectoryEntryFileOffset;
2774   UINT32                           ExportDirectoryEntryRva;
2775   UINT32                           ExportDirectoryEntryFileOffset;
2776   UINT32                           ResourceDirectoryEntryRva;
2777   UINT32                           ResourceDirectoryEntryFileOffset;
2778   EFI_IMAGE_DOS_HEADER            *DosHdr;
2779   EFI_IMAGE_FILE_HEADER           *FileHdr;
2780   EFI_IMAGE_OPTIONAL_HEADER32     *Optional32Hdr;
2781   EFI_IMAGE_OPTIONAL_HEADER64     *Optional64Hdr;
2782   EFI_IMAGE_SECTION_HEADER        *SectionHeader;
2783   EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *DebugEntry;
2784   UINT32                          *NewTimeStamp;
2785 
2786   //
2787   // Init variable.
2788   //
2789   DebugDirectoryEntryRva           = 0;
2790   ExportDirectoryEntryRva          = 0;
2791   ResourceDirectoryEntryRva        = 0;
2792   DebugDirectoryEntryFileOffset    = 0;
2793   ExportDirectoryEntryFileOffset   = 0;
2794   ResourceDirectoryEntryFileOffset = 0;
2795   DosHdr   = (EFI_IMAGE_DOS_HEADER *)  FileBuffer;
2796   FileHdr  = (EFI_IMAGE_FILE_HEADER *) (FileBuffer + DosHdr->e_lfanew + sizeof (UINT32));
2797 
2798 
2799   DosHdr = (EFI_IMAGE_DOS_HEADER *)FileBuffer;
2800   if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {
2801     // NO DOS header, must start with PE/COFF header
2802     FileHdr  = (EFI_IMAGE_FILE_HEADER *)(FileBuffer + sizeof (UINT32));
2803   } else {
2804     FileHdr  = (EFI_IMAGE_FILE_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof (UINT32));
2805   }
2806 
2807   //
2808   // Get Debug, Export and Resource EntryTable RVA address.
2809   // Resource Directory entry need to review.
2810   //
2811   Optional32Hdr = (EFI_IMAGE_OPTIONAL_HEADER32 *) ((UINT8*) FileHdr + sizeof (EFI_IMAGE_FILE_HEADER));
2812   if (Optional32Hdr->Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
2813     SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) Optional32Hdr +  FileHdr->SizeOfOptionalHeader);
2814     if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXPORT && \
2815         Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].Size != 0) {
2816       ExportDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
2817     }
2818     if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE && \
2819         Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size != 0) {
2820       ResourceDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;
2821     }
2822     if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG && \
2823         Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) {
2824       DebugDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
2825       if (ZeroDebugFlag) {
2826         Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = 0;
2827         Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = 0;
2828       }
2829     }
2830   } else {
2831     Optional64Hdr = (EFI_IMAGE_OPTIONAL_HEADER64 *) ((UINT8*) FileHdr + sizeof (EFI_IMAGE_FILE_HEADER));
2832     SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) Optional64Hdr +  FileHdr->SizeOfOptionalHeader);
2833     if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXPORT && \
2834         Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].Size != 0) {
2835       ExportDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
2836     }
2837     if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE && \
2838         Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size != 0) {
2839       ResourceDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;
2840     }
2841     if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG && \
2842         Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) {
2843       DebugDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
2844       if (ZeroDebugFlag) {
2845         Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = 0;
2846         Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = 0;
2847       }
2848     }
2849   }
2850 
2851   //
2852   // Get DirectoryEntryTable file offset.
2853   //
2854   for (Index = 0; Index < FileHdr->NumberOfSections; Index ++, SectionHeader ++) {
2855     if (DebugDirectoryEntryRva >= SectionHeader->VirtualAddress &&
2856         DebugDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) {
2857         DebugDirectoryEntryFileOffset =
2858         DebugDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData;
2859     }
2860     if (ExportDirectoryEntryRva >= SectionHeader->VirtualAddress &&
2861         ExportDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) {
2862         ExportDirectoryEntryFileOffset =
2863         ExportDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData;
2864     }
2865     if (ResourceDirectoryEntryRva >= SectionHeader->VirtualAddress &&
2866         ResourceDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) {
2867         ResourceDirectoryEntryFileOffset =
2868         ResourceDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData;
2869     }
2870   }
2871 
2872   //
2873   //Zero Debug Data and TimeStamp
2874   //
2875   FileHdr->TimeDateStamp = 0;
2876   mImageTimeStamp = 0;
2877   if (ExportDirectoryEntryFileOffset != 0) {
2878     NewTimeStamp  = (UINT32 *) (FileBuffer + ExportDirectoryEntryFileOffset + sizeof (UINT32));
2879     *NewTimeStamp = 0;
2880   }
2881 
2882   if (ResourceDirectoryEntryFileOffset != 0) {
2883     NewTimeStamp  = (UINT32 *) (FileBuffer + ResourceDirectoryEntryFileOffset + sizeof (UINT32));
2884     *NewTimeStamp = 0;
2885   }
2886 
2887   if (DebugDirectoryEntryFileOffset != 0) {
2888     DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) (FileBuffer + DebugDirectoryEntryFileOffset);
2889     DebugEntry->TimeDateStamp = 0;
2890     mImageTimeStamp = 0;
2891     if (ZeroDebugFlag) {
2892       memset (FileBuffer + DebugEntry->FileOffset, 0, DebugEntry->SizeOfData);
2893       memset (DebugEntry, 0, sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY));
2894     }
2895   }
2896 
2897   return EFI_SUCCESS;
2898 }
2899 
2900 STATIC
2901 EFI_STATUS
SetStamp(IN OUT UINT8 * FileBuffer,IN CHAR8 * TimeStamp)2902 SetStamp (
2903   IN OUT UINT8  *FileBuffer,
2904   IN     CHAR8  *TimeStamp
2905   )
2906 /*++
2907 
2908 Routine Description:
2909 
2910   Set new time stamp into PeImage FileHdr and Directory table:
2911   Debug, Export and Resource.
2912 
2913 Arguments:
2914 
2915   FileBuffer    - Pointer to PeImage.
2916   TimeStamp     - Time stamp string.
2917 
2918 Returns:
2919 
2920   EFI_INVALID_PARAMETER   - TimeStamp format is not recognized.
2921   EFI_SUCCESS             - Set new time stamp in this image successfully.
2922 
2923 --*/
2924 {
2925   struct tm                       stime;
2926   struct tm                       *ptime;
2927   time_t                          newtime;
2928   UINT32                          Index;
2929   UINT32                          DebugDirectoryEntryRva;
2930   UINT32                          DebugDirectoryEntryFileOffset;
2931   UINT32                          ExportDirectoryEntryRva;
2932   UINT32                          ExportDirectoryEntryFileOffset;
2933   UINT32                          ResourceDirectoryEntryRva;
2934   UINT32                          ResourceDirectoryEntryFileOffset;
2935   EFI_IMAGE_DOS_HEADER            *DosHdr;
2936   EFI_IMAGE_FILE_HEADER           *FileHdr;
2937   EFI_IMAGE_OPTIONAL_HEADER32     *Optional32Hdr;
2938   EFI_IMAGE_OPTIONAL_HEADER64     *Optional64Hdr;
2939   EFI_IMAGE_SECTION_HEADER        *SectionHeader;
2940   UINT32                          *NewTimeStamp;
2941 
2942   //
2943   // Init variable.
2944   //
2945   DebugDirectoryEntryRva           = 0;
2946   DebugDirectoryEntryFileOffset    = 0;
2947   ExportDirectoryEntryRva          = 0;
2948   ExportDirectoryEntryFileOffset   = 0;
2949   ResourceDirectoryEntryRva        = 0;
2950   ResourceDirectoryEntryFileOffset = 0;
2951   //
2952   // Get time and date that will be set.
2953   //
2954   if (TimeStamp == NULL) {
2955     Error (NULL, 0, 3000, "Invalid", "TimeStamp cannot be NULL.");
2956     return EFI_INVALID_PARAMETER;
2957   }
2958   //
2959   // compare the value with "NOW", if yes, current system time is set.
2960   //
2961   if (stricmp (TimeStamp, "NOW") == 0) {
2962     //
2963     // get system current time and date
2964     //
2965     time (&newtime);
2966   } else {
2967     //
2968     // Check Time Format strictly yyyy-mm-dd 00:00:00
2969     //
2970     for (Index = 0; TimeStamp[Index] != '\0' && Index < 20; Index ++) {
2971       if (Index == 4 || Index == 7) {
2972         if (TimeStamp[Index] == '-') {
2973           continue;
2974         }
2975       } else if (Index == 13 || Index == 16) {
2976         if (TimeStamp[Index] == ':') {
2977           continue;
2978         }
2979       } else if (Index == 10 && TimeStamp[Index] == ' ') {
2980         continue;
2981       } else if ((TimeStamp[Index] < '0') || (TimeStamp[Index] > '9')) {
2982         break;
2983       }
2984     }
2985 
2986     if (Index < 19 || TimeStamp[19] != '\0') {
2987       Error (NULL, 0, 1003, "Invalid option value", "Incorrect Time \"%s\"\n  Correct Format \"yyyy-mm-dd 00:00:00\"", TimeStamp);
2988       return EFI_INVALID_PARAMETER;
2989     }
2990 
2991     //
2992     // get the date and time from TimeStamp
2993     //
2994     if (sscanf (TimeStamp, "%d-%d-%d %d:%d:%d",
2995             &stime.tm_year,
2996             &stime.tm_mon,
2997             &stime.tm_mday,
2998             &stime.tm_hour,
2999             &stime.tm_min,
3000             &stime.tm_sec
3001             ) != 6) {
3002       Error (NULL, 0, 1003, "Invalid option value", "Incorrect Tiem \"%s\"\n  Correct Format \"yyyy-mm-dd 00:00:00\"", TimeStamp);
3003       return EFI_INVALID_PARAMETER;
3004     }
3005 
3006     //
3007     // in struct, Month (0 - 11; Jan = 0). So decrease 1 from it
3008     //
3009     if (stime.tm_mon <= 0 || stime.tm_mday <=0) {
3010       Error (NULL, 0, 3000, "Invalid", "%s Invalid date!", TimeStamp);
3011       return EFI_INVALID_PARAMETER;
3012     }
3013     stime.tm_mon -= 1;
3014 
3015     //
3016     // in struct, Year (current year minus 1900)
3017     // and only the dates can be handled from Jan 1, 1970 to Jan 18, 2038
3018     //
3019     //
3020     // convert 0 -> 100 (2000), 1 -> 101 (2001), ..., 38 -> 138 (2038)
3021     //
3022     if (stime.tm_year >= 1970 && stime.tm_year <= 2038) {
3023       //
3024       // convert 1970 -> 70, 2000 -> 100, ...
3025       //
3026       stime.tm_year -= 1900;
3027     } else {
3028       Error (NULL, 0, 3000, "Invalid", "%s Invalid or unsupported datetime!", TimeStamp);
3029       return EFI_INVALID_PARAMETER;
3030     }
3031 
3032     //
3033     // convert the date and time to time_t format
3034     //
3035     newtime = mktime (&stime);
3036     if (newtime == (time_t) - 1) {
3037       Error (NULL, 0, 3000, "Invalid", "%s Invalid or unsupported datetime!", TimeStamp);
3038       return EFI_INVALID_PARAMETER;
3039     }
3040   }
3041 
3042   ptime = localtime (&newtime);
3043   if (ptime != NULL) {
3044     DebugMsg (NULL, 0, 9, "New Image Time Stamp", "%04d-%02d-%02d %02d:%02d:%02d",
3045               ptime->tm_year + 1900, ptime->tm_mon + 1, ptime->tm_mday, ptime->tm_hour, ptime->tm_min, ptime->tm_sec);
3046   }
3047   //
3048   // Set new time and data into PeImage.
3049   //
3050   DosHdr = (EFI_IMAGE_DOS_HEADER *)FileBuffer;
3051   if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {
3052     // NO DOS header, must start with PE/COFF header
3053     FileHdr  = (EFI_IMAGE_FILE_HEADER *)(FileBuffer + sizeof (UINT32));
3054   } else {
3055     FileHdr  = (EFI_IMAGE_FILE_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof (UINT32));
3056   }
3057 
3058   //
3059   // Get Debug, Export and Resource EntryTable RVA address.
3060   // Resource Directory entry need to review.
3061   //
3062   if (FileHdr->Machine == EFI_IMAGE_MACHINE_IA32) {
3063     Optional32Hdr = (EFI_IMAGE_OPTIONAL_HEADER32 *) ((UINT8*) FileHdr + sizeof (EFI_IMAGE_FILE_HEADER));
3064     SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) Optional32Hdr +  FileHdr->SizeOfOptionalHeader);
3065     if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXPORT && \
3066         Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].Size != 0) {
3067       ExportDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
3068     }
3069     if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE && \
3070         Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size != 0) {
3071       ResourceDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;
3072     }
3073     if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG && \
3074         Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) {
3075       DebugDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
3076     }
3077   } else {
3078     Optional64Hdr = (EFI_IMAGE_OPTIONAL_HEADER64 *) ((UINT8*) FileHdr + sizeof (EFI_IMAGE_FILE_HEADER));
3079     SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) Optional64Hdr +  FileHdr->SizeOfOptionalHeader);
3080     if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXPORT && \
3081         Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].Size != 0) {
3082       ExportDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
3083     }
3084     if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE && \
3085         Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size != 0) {
3086       ResourceDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;
3087     }
3088     if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG && \
3089         Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) {
3090       DebugDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
3091     }
3092   }
3093 
3094   //
3095   // Get DirectoryEntryTable file offset.
3096   //
3097   for (Index = 0; Index < FileHdr->NumberOfSections; Index ++, SectionHeader ++) {
3098     if (DebugDirectoryEntryRva >= SectionHeader->VirtualAddress &&
3099         DebugDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) {
3100         DebugDirectoryEntryFileOffset =
3101         DebugDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData;
3102     }
3103     if (ExportDirectoryEntryRva >= SectionHeader->VirtualAddress &&
3104         ExportDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) {
3105         ExportDirectoryEntryFileOffset =
3106         ExportDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData;
3107     }
3108     if (ResourceDirectoryEntryRva >= SectionHeader->VirtualAddress &&
3109         ResourceDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) {
3110         ResourceDirectoryEntryFileOffset =
3111         ResourceDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData;
3112     }
3113   }
3114 
3115   //
3116   // Set new stamp
3117   //
3118   FileHdr->TimeDateStamp = (UINT32) newtime;
3119   mImageTimeStamp = (UINT32) newtime;
3120   if (ExportDirectoryEntryRva != 0) {
3121     NewTimeStamp  = (UINT32 *) (FileBuffer + ExportDirectoryEntryFileOffset + sizeof (UINT32));
3122     *NewTimeStamp = (UINT32) newtime;
3123   }
3124 
3125   if (ResourceDirectoryEntryRva != 0) {
3126     NewTimeStamp  = (UINT32 *) (FileBuffer + ResourceDirectoryEntryFileOffset + sizeof (UINT32));
3127     *NewTimeStamp = (UINT32) newtime;
3128   }
3129 
3130   if (DebugDirectoryEntryRva != 0) {
3131     NewTimeStamp  = (UINT32 *) (FileBuffer + DebugDirectoryEntryFileOffset + sizeof (UINT32));
3132     *NewTimeStamp = (UINT32) newtime;
3133   }
3134 
3135   return EFI_SUCCESS;
3136 }
3137 
3138 STATIC
3139 STATUS
MicrocodeReadData(FILE * InFptr,UINT32 * Data)3140 MicrocodeReadData (
3141   FILE          *InFptr,
3142   UINT32        *Data
3143   )
3144 /*++
3145 
3146 Routine Description:
3147   Read a 32-bit microcode data value from a text file and convert to raw binary form.
3148 
3149 Arguments:
3150   InFptr    - file pointer to input text file
3151   Data      - pointer to where to return the data parsed
3152 
3153 Returns:
3154   STATUS_SUCCESS    - no errors or warnings, Data contains valid information
3155   STATUS_ERROR      - errors were encountered
3156 
3157 --*/
3158 {
3159   CHAR8  Line[MAX_LINE_LEN];
3160   CHAR8  *cptr;
3161   int    ScannedData = 0;
3162 
3163   Line[MAX_LINE_LEN - 1]  = 0;
3164   while (1) {
3165     if (fgets (Line, MAX_LINE_LEN, InFptr) == NULL) {
3166       return STATUS_ERROR;
3167     }
3168     //
3169     // If it was a binary file, then it may have overwritten our null terminator
3170     //
3171     if (Line[MAX_LINE_LEN - 1] != 0) {
3172       return STATUS_ERROR;
3173     }
3174 
3175     //
3176     // strip space
3177     //
3178     for (cptr = Line; *cptr && isspace((int)*cptr); cptr++) {
3179     }
3180 
3181     // Skip Blank Lines and Comment Lines
3182     if ((strlen(cptr) != 0) && (*cptr != ';')) {
3183       break;
3184     }
3185   }
3186 
3187   // Look for
3188   // dd 000000001h ; comment
3189   // dd XXXXXXXX
3190   // DD  XXXXXXXXX
3191   //  DD XXXXXXXXX
3192   //
3193   if ((tolower((int)cptr[0]) == 'd') && (tolower((int)cptr[1]) == 'd') && isspace ((int)cptr[2])) {
3194     //
3195     // Skip blanks and look for a hex digit
3196     //
3197     cptr += 3;
3198     for (; *cptr && isspace((int)*cptr); cptr++) {
3199     }
3200     if (isxdigit ((int)*cptr)) {
3201       if (sscanf (cptr, "%X", &ScannedData) != 1) {
3202         return STATUS_ERROR;
3203       }
3204     }
3205     *Data = (UINT32) ScannedData;
3206     return STATUS_SUCCESS;
3207   }
3208 
3209   return STATUS_ERROR;
3210 }
3211