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