Remove the specific SHT_GNU_HASH for some version unix OS.
[people/mcb30/basetools.git] / Source / C / GenFw / GenFw.c
1 /** @file\r
2 \r
3 Copyright (c) 2004 - 2008, Intel Corporation                                                         \r
4 All rights reserved. This program and the accompanying materials                          \r
5 are licensed and made available under the terms and conditions of the BSD License         \r
6 which accompanies this distribution.  The full text of the license may be found at        \r
7 http://opensource.org/licenses/bsd-license.php                                            \r
8                                                                                           \r
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
11 \r
12 Module Name:\r
13 \r
14     GenFw.c\r
15 \r
16 Abstract:\r
17 \r
18     Converts a pe32+ image to an FW, Te image type, or other specific image. \r
19 \r
20 **/\r
21 \r
22 #include "WinNtInclude.h"\r
23 \r
24 //\r
25 // List of OS and CPU which support ELF to PE conversion\r
26 //\r
27 #if defined(linux)\r
28 #if defined (__i386__) || defined(__x86_64__)\r
29 #define HAVE_ELF\r
30 #endif\r
31 #endif\r
32 \r
33 #ifndef __GNUC__\r
34 #include <windows.h>\r
35 #endif\r
36 #include <stdio.h>\r
37 #include <stdlib.h>\r
38 #include <string.h>\r
39 #include <time.h>\r
40 \r
41 #ifdef HAVE_ELF\r
42 #include <elf.h>\r
43 #endif\r
44 \r
45 #include <Common/UefiBaseTypes.h>\r
46 #include <IndustryStandard/PeImage.h>\r
47 \r
48 //\r
49 // Acpi Table definition\r
50 //\r
51 #include <IndustryStandard/Acpi.h>\r
52 #include <IndustryStandard/Acpi1_0.h>\r
53 #include <IndustryStandard/Acpi2_0.h>\r
54 #include <IndustryStandard/Acpi3_0.h>\r
55 #include <IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h>\r
56 \r
57 #include "CommonLib.h"\r
58 #include "EfiUtilityMsgs.h"\r
59 \r
60 //\r
61 // Version of this utility\r
62 //\r
63 #define UTILITY_NAME "GenFw"\r
64 #define UTILITY_MAJOR_VERSION 0\r
65 #define UTILITY_MINOR_VERSION 2\r
66 \r
67 //\r
68 // Action for this tool.\r
69 //\r
70 #define FW_DUMMY_IMAGE       0\r
71 #define FW_EFI_IMAGE         1\r
72 #define FW_TE_IMAGE          2\r
73 #define FW_ACPI_IMAGE        3\r
74 #define FW_BIN_IMAGE         4\r
75 #define FW_ZERO_DEBUG_IMAGE  5\r
76 #define FW_SET_STAMP_IMAGE   6\r
77 #define FW_MCI_IMAGE         7\r
78 #define FW_MERGE_IMAGE       8\r
79 #define FW_RELOC_STRIPEED_IMAGE 9\r
80 \r
81 #define DUMP_TE_HEADER       0x11\r
82 \r
83 #define DEFAULT_MC_PAD_BYTE_VALUE  0xFF\r
84 #define DEFAULT_MC_ALIGNMENT       16\r
85 \r
86 #ifndef _MAX_PATH\r
87 #define _MAX_PATH 500\r
88 #endif\r
89 \r
90 #define STATUS_IGNORE        0xA\r
91 //\r
92 // Structure definition for a microcode header\r
93 //\r
94 typedef struct {\r
95   UINTN  HeaderVersion;\r
96   UINTN  PatchId;\r
97   UINTN  Date;\r
98   UINTN  CpuId;\r
99   UINTN  Checksum;\r
100   UINTN  LoaderVersion;\r
101   UINTN  PlatformId;\r
102   UINTN  DataSize;   // if 0, then TotalSize = 2048, and TotalSize field is invalid\r
103   UINTN  TotalSize;  // number of bytes\r
104   UINTN  Reserved[3];\r
105 } MICROCODE_IMAGE_HEADER;\r
106 \r
107 STATIC CHAR8 *mInImageName;\r
108 \r
109 STATIC\r
110 EFI_STATUS\r
111 ZeroDebugData (\r
112   IN OUT UINT8   *FileBuffer\r
113   );\r
114 \r
115 STATIC \r
116 EFI_STATUS\r
117 SetStamp (\r
118   IN OUT UINT8  *FileBuffer, \r
119   IN     CHAR8  *TimeStamp\r
120   );\r
121 \r
122 STATIC \r
123 STATUS\r
124 MicrocodeReadData (\r
125   FILE          *InFptr,\r
126   UINTN         *Data\r
127   );\r
128 \r
129 STATIC\r
130 VOID\r
131 Version (\r
132   VOID\r
133   )\r
134 /*++\r
135 \r
136 Routine Description:\r
137 \r
138   Print out version information for this utility.\r
139 \r
140 Arguments:\r
141 \r
142   None\r
143   \r
144 Returns:\r
145 \r
146   None\r
147   \r
148 --*/ \r
149 {\r
150   fprintf (stdout, "%s Version %d.%d\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION);\r
151 }\r
152 \r
153 STATIC\r
154 VOID\r
155 Usage (\r
156   VOID\r
157   )\r
158 /*++\r
159 \r
160 Routine Description:\r
161 \r
162   Print Help message.\r
163 \r
164 Arguments:\r
165 \r
166   VOID\r
167 \r
168 Returns:\r
169 \r
170   None\r
171 \r
172 --*/\r
173 {\r
174   //\r
175   // Summary usage\r
176   //\r
177   fprintf (stdout, "\nUsage: %s [options] <input_file>\n\n", UTILITY_NAME);\r
178   \r
179   //\r
180   // Copyright declaration\r
181   // \r
182   fprintf (stdout, "Copyright (c) 2007, Intel Corporation. All rights reserved.\n\n");\r
183 \r
184   //\r
185   // Details Option\r
186   //\r
187   fprintf (stdout, "Options:\n");\r
188   fprintf (stdout, "  -o FileName, --outputfile FileName\n\\r
189                         File will be created to store the ouput content.\n");\r
190   fprintf (stdout, "  -e EFI_FILETYPE, --efiImage EFI_FILETYPE\n\\r
191                         Create Efi Image. EFI_FILETYPE is one of BASE, SEC,\n\\r
192                         PEI_CORE, PEIM, DXE_CORE, DXE_RUNTIME_DRIVER,\n\\r
193                         DXE_SAL_DRIVER, UEFI_DRIVER, UEFI_APPLICATION, \n\\r
194                         DXE_SMM_DRIVER, SECURITY_CORE, COMBINED_PEIM_DRIVER, \n\\r
195                         PIC_PEIM, RELOCATABLE_PEIM, BS_DRIVER, RT_DRIVER,\n\\r
196                         APPLICATION, SAL_RT_DRIVER to support all module types\n");\r
197   fprintf (stdout, "  -c, --acpi            Create Acpi table.\n");\r
198   fprintf (stdout, "  -t, --terse           Create Te Image.\n");\r
199   fprintf (stdout, "  -u, --dump            Dump TeImage Header.\n");\r
200   fprintf (stdout, "  -z, --zero            Zero the Debug Data Fields in the PE input image file.\n");\r
201   fprintf (stdout, "  -b, --exe2bin         Convert the input EXE to the output BIN file.\n");\r
202   fprintf (stdout, "  -l, --stripped        Relocation info stripped from the input PE or TE image.\n");\r
203   fprintf (stdout, "  -r, --replace         Overwrite the input file with the output content.\n");\r
204   fprintf (stdout, "  -s timedate, --stamp timedate\n\\r
205                         timedate format is \"yyyy-mm-dd 00:00:00\". if timedata \n\\r
206                         is set to NOW, current system time is used. The support\n\\r
207                         date scope is 1970-1-1 0:0:0 ~ 2038-1-19 3:14:07\n");\r
208   fprintf (stdout, "  -m, --mcifile         Convert input microcode txt file to microcode bin file.\n");\r
209   fprintf (stdout, "  -j, --join            Combine multi microcode bin files to one file.\n");\r
210   fprintf (stdout, "  --keepexceptiontable  Don't clear exception table.\n");\r
211   fprintf (stdout, "  --keepzeropending     Don't strip zero pending of .reloc.\n");\r
212   fprintf (stdout, "  -a NUM, --align NUM   NUM is one HEX or DEC format alignment value.\n");\r
213   fprintf (stdout, "  -p NUM, --pad NUM     NUM is one HEX or DEC format padding value.\n");\r
214   fprintf (stdout, "  -v, --verbose         Turn on verbose output with informational messages.\n");\r
215   fprintf (stdout, "  -q, --quiet           Disable all messages except key message and fatal error\n");\r
216   fprintf (stdout, "  -d, --debug level     Enable debug messages, at input debug level.\n");\r
217   fprintf (stdout, "  --version             Show program's version number and exit\n");\r
218   fprintf (stdout, "  -h, --help            Show this help message and exit\n");\r
219 }\r
220 \r
221 STATIC\r
222 STATUS\r
223 CheckAcpiTable (\r
224   VOID      *AcpiTable,\r
225   UINT32    Length\r
226   )\r
227 /*++\r
228 \r
229 Routine Description:\r
230   \r
231   Check Acpi Table \r
232 \r
233 Arguments:\r
234 \r
235   AcpiTable     Buffer for AcpiSection\r
236   Length        AcpiSection Length\r
237 \r
238 Returns:\r
239 \r
240   0             success\r
241   non-zero      otherwise\r
242 \r
243 --*/\r
244 {\r
245   EFI_ACPI_DESCRIPTION_HEADER                   *AcpiHeader;\r
246   EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE  *Facs;\r
247   UINT32                                        ExpectedLength;\r
248 \r
249   AcpiHeader = (EFI_ACPI_DESCRIPTION_HEADER *)AcpiTable;\r
250 \r
251   //\r
252   // Generic check for AcpiTable length.\r
253   //\r
254   if (AcpiHeader->Length > Length) {\r
255     Error (NULL, 0, 3000, "Invalid", "AcpiTable length check failed.", NULL);\r
256     return STATUS_ERROR;\r
257   }\r
258 \r
259   //\r
260   // Currently, we only check must-have tables: FADT, FACS, DSDT,\r
261   // and some important tables: MADT, MCFG.\r
262   //\r
263   switch (AcpiHeader->Signature) {\r
264 \r
265   //\r
266   // "FACP" Fixed ACPI Description Table\r
267   //\r
268   case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE:\r
269     switch (AcpiHeader->Revision) {\r
270     case EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION:\r
271       ExpectedLength = sizeof(EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE);\r
272       break;\r
273     case EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION:\r
274       ExpectedLength = sizeof(EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE);\r
275       break;\r
276     case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION:\r
277       ExpectedLength = sizeof(EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE);\r
278       break;\r
279     default:\r
280       Error (NULL, 0, 3000, "Invalid", "FACP revision check failed.");\r
281       return STATUS_ERROR;\r
282     }\r
283     if (ExpectedLength != AcpiHeader->Length) {\r
284       Error (NULL, 0, 3000, "Invalid", "FACP length check failed.");\r
285       return STATUS_ERROR;\r
286     }\r
287     break;\r
288 \r
289   //\r
290   // "FACS" Firmware ACPI Control Structure\r
291   //\r
292   case EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE:\r
293     Facs = (EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *)AcpiTable;\r
294     if ((Facs->Version != 0) &&\r
295         (Facs->Version != EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION) &&\r
296         (Facs->Version != EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION)){\r
297       Error (NULL, 0, 3000, "Invalid", "FACS version check failed.");\r
298       return STATUS_ERROR;\r
299     }\r
300     if ((Facs->Length != sizeof(EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE)) &&\r
301         (Facs->Length != sizeof(EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE)) &&\r
302         (Facs->Length != sizeof(EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE))) {\r
303       Error (NULL, 0, 3000, "Invalid", "FACS length check failed.");\r
304       return STATUS_ERROR;\r
305     }\r
306     break;\r
307 \r
308   //\r
309   // "DSDT" Differentiated System Description Table\r
310   //\r
311   case EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:\r
312     if (AcpiHeader->Revision > EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_REVISION) {\r
313       Error (NULL, 0, 3000, "Invalid", "DSDT revision check failed.");\r
314       return STATUS_ERROR;\r
315     }\r
316     if (AcpiHeader->Length <= sizeof(EFI_ACPI_DESCRIPTION_HEADER)) {\r
317       Error (NULL, 0, 3000, "Invalid", "DSDT length check failed.");\r
318       return STATUS_ERROR;\r
319     }\r
320     break;\r
321 \r
322   //\r
323   // "APIC" Multiple APIC Description Table\r
324   //\r
325   case EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE:\r
326     if ((AcpiHeader->Revision != EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION) &&\r
327         (AcpiHeader->Revision != EFI_ACPI_2_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION) &&\r
328         (AcpiHeader->Revision != EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION)) {\r
329       Error (NULL, 0, 3000, "Invalid", "APIC revision check failed.");\r
330       return STATUS_ERROR;\r
331     }\r
332     if (AcpiHeader->Length <= sizeof(EFI_ACPI_DESCRIPTION_HEADER) + sizeof(UINT32) + sizeof(UINT32)) {\r
333       Error (NULL, 0, 3000, "Invalid", "APIC length check failed.");\r
334       return STATUS_ERROR;\r
335     }\r
336     break;\r
337 \r
338   //\r
339   // "MCFG" PCI Express Memory Mapped Configuration Space Base Address Description Table\r
340   //\r
341   case EFI_ACPI_3_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE:\r
342     if (AcpiHeader->Revision != EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION) {\r
343       Error (NULL, 0, 3000, "Invalid", "MCFG revision check failed.");\r
344       return STATUS_ERROR;\r
345     }\r
346     if (AcpiHeader->Length <= sizeof(EFI_ACPI_DESCRIPTION_HEADER) + sizeof(UINT64)) {\r
347       Error (NULL, 0, 3000, "Invalid", "MCFG length check failed.");\r
348       return STATUS_ERROR;\r
349     }\r
350     break;\r
351 \r
352   //\r
353   // Other table pass check\r
354   //\r
355   default:\r
356     break;\r
357   }\r
358 \r
359   return STATUS_SUCCESS;\r
360 }\r
361 \r
362 STATIC\r
363 STATUS\r
364 FCopyFile (\r
365   FILE    *in,\r
366   FILE    *out\r
367   )\r
368 {\r
369   UINT32  filesize;\r
370   UINT32  offset;\r
371   UINT32  length;\r
372   UINT8 Buffer[8 * 1024];\r
373 \r
374   fseek (in, 0, SEEK_END);\r
375   filesize = ftell (in);\r
376 \r
377   fseek (in, 0, SEEK_SET);\r
378   fseek (out, 0, SEEK_SET);\r
379 \r
380   offset = 0;\r
381   while (offset < filesize) {\r
382     length = sizeof (Buffer);\r
383     if (filesize - offset < length) {\r
384       length = filesize - offset;\r
385     }\r
386 \r
387     fread (Buffer, length, 1, in);\r
388     fwrite (Buffer, length, 1, out);\r
389     offset += length;\r
390   }\r
391 \r
392   if ((UINT32 ) ftell (out) != filesize) {\r
393     Error (NULL, 0, 0002, "Error writing file", NULL);\r
394     return STATUS_ERROR;\r
395   }\r
396 \r
397   return STATUS_SUCCESS;\r
398 }\r
399 \r
400 #ifdef HAVE_ELF\r
401 INTN\r
402 IsElfHeader(\r
403   UINT8  *FileBuffer\r
404 )\r
405 {\r
406   return (FileBuffer[EI_MAG0] == ELFMAG0\r
407     && FileBuffer[EI_MAG1] == ELFMAG1\r
408     && FileBuffer[EI_MAG2] == ELFMAG2\r
409     && FileBuffer[EI_MAG3] == ELFMAG3);\r
410 }\r
411 \r
412 typedef Elf32_Shdr Elf_Shdr;\r
413 typedef Elf32_Ehdr Elf_Ehdr;\r
414 typedef Elf32_Rel Elf_Rel;\r
415 typedef Elf32_Sym Elf_Sym;\r
416 #define ELFCLASS ELFCLASS32\r
417 #define ELF_R_TYPE(r) ELF32_R_TYPE(r)\r
418 #define ELF_R_SYM(r) ELF32_R_SYM(r)\r
419 \r
420 //\r
421 // Well known ELF structures.\r
422 //\r
423 Elf_Ehdr *Ehdr;\r
424 Elf_Shdr *ShdrBase;\r
425 \r
426 //\r
427 // PE section alignment.\r
428 //\r
429 const UINT32 CoffAlignment = 0x20;\r
430 const UINT32 CoffNbrSections = 4;\r
431 \r
432 //\r
433 // Current offset in coff file.\r
434 //\r
435 UINT32 CoffOffset;\r
436 \r
437 //\r
438 // Result Coff file in memory.\r
439 //\r
440 UINT8 *CoffFile = NULL;\r
441 //\r
442 // ELF sections to offset in Coff file.\r
443 //\r
444 UINT32 *CoffSectionsOffset = NULL;\r
445 \r
446 //\r
447 // Offset in Coff file of headers and sections.\r
448 //\r
449 UINT32 NtHdrOffset;\r
450 UINT32 TableOffset;\r
451 UINT32 TextOffset;\r
452 UINT32 DataOffset;\r
453 UINT32 RelocOffset;\r
454 \r
455 EFI_IMAGE_BASE_RELOCATION *CoffBaseRel;\r
456 UINT16 *CoffEntryRel;\r
457 \r
458 UINT32\r
459 CoffAlign(\r
460   UINT32 Offset\r
461   )\r
462 {\r
463   return (Offset + CoffAlignment - 1) & ~(CoffAlignment - 1);\r
464 }\r
465 \r
466 Elf_Shdr *\r
467 GetShdrByIndex(\r
468   UINT32 Num\r
469   )\r
470 {\r
471   if (Num >= Ehdr->e_shnum)\r
472     return NULL;\r
473   return (Elf_Shdr*)((UINT8*)ShdrBase + Num * Ehdr->e_shentsize);\r
474 }\r
475 \r
476 INTN\r
477 CheckElfHeader(\r
478   VOID\r
479   )\r
480 {\r
481   //\r
482   // Note: Magic has already been tested.\r
483   //\r
484   if (Ehdr->e_ident[EI_CLASS] != ELFCLASS)\r
485     return 0;\r
486   if (Ehdr->e_ident[EI_DATA] != ELFDATA2LSB)\r
487     return 0;\r
488   if ((Ehdr->e_type != ET_EXEC) && (Ehdr->e_type != ET_DYN))\r
489     return 0;\r
490   if (Ehdr->e_machine != EM_386)\r
491     return 0;\r
492   if (Ehdr->e_version != EV_CURRENT)\r
493     return 0;\r
494 \r
495   //\r
496   // Find the section header table\r
497   // \r
498   ShdrBase = (Elf_Shdr *)((UINT8 *)Ehdr + Ehdr->e_shoff);\r
499 \r
500   CoffSectionsOffset = (UINT32 *)malloc(Ehdr->e_shnum * sizeof (UINT32));\r
501 \r
502   memset(CoffSectionsOffset, 0, Ehdr->e_shnum * sizeof(UINT32));\r
503   return 1;\r
504 }\r
505 \r
506 int\r
507 IsTextShdr(\r
508   Elf_Shdr *Shdr\r
509   )\r
510 {\r
511   return (Shdr->sh_flags & (SHF_WRITE | SHF_ALLOC)) == SHF_ALLOC;\r
512 }\r
513 \r
514 int\r
515 IsDataShdr(\r
516   Elf_Shdr *Shdr\r
517   )\r
518 {\r
519   return (Shdr->sh_flags & (SHF_WRITE | SHF_ALLOC)) == (SHF_ALLOC | SHF_WRITE);\r
520 }\r
521 \r
522 VOID\r
523 CreateSectionHeader(\r
524   const CHAR8 *Name,\r
525   UINT32      Offset,\r
526   UINT32      Size,\r
527   UINT32      Flags\r
528   )\r
529 {\r
530   EFI_IMAGE_SECTION_HEADER *Hdr;\r
531   Hdr = (EFI_IMAGE_SECTION_HEADER*)(CoffFile + TableOffset);\r
532 \r
533   strcpy(Hdr->Name, Name);\r
534   Hdr->Misc.VirtualSize = Size;\r
535   Hdr->VirtualAddress = Offset;\r
536   Hdr->SizeOfRawData = Size;\r
537   Hdr->PointerToRawData = Offset;\r
538   Hdr->PointerToRelocations = 0;\r
539   Hdr->PointerToLinenumbers = 0;\r
540   Hdr->NumberOfRelocations = 0;\r
541   Hdr->NumberOfLinenumbers = 0;\r
542   Hdr->Characteristics = Flags;\r
543 \r
544   TableOffset += sizeof (EFI_IMAGE_SECTION_HEADER);\r
545 }\r
546 \r
547 VOID\r
548 ScanSections(\r
549   VOID\r
550   )\r
551 {\r
552   UINT32 i;\r
553   EFI_IMAGE_DOS_HEADER *DosHdr;\r
554   EFI_IMAGE_NT_HEADERS *NtHdr;\r
555   UINT32 CoffEntry = 0;\r
556 \r
557   CoffOffset = 0;\r
558 \r
559   //\r
560   // Coff file start with a DOS header.\r
561   //\r
562   CoffOffset = sizeof(EFI_IMAGE_DOS_HEADER) + 0x40;\r
563   NtHdrOffset = CoffOffset;\r
564   CoffOffset += sizeof(EFI_IMAGE_NT_HEADERS);\r
565   TableOffset = CoffOffset;\r
566   CoffOffset += CoffNbrSections * sizeof(EFI_IMAGE_SECTION_HEADER);\r
567 \r
568   //\r
569   // First text sections.\r
570   //\r
571   CoffOffset = CoffAlign(CoffOffset);\r
572   TextOffset = CoffOffset;\r
573   for (i = 0; i < Ehdr->e_shnum; i++) {\r
574     Elf_Shdr *shdr = GetShdrByIndex(i);\r
575     if (IsTextShdr(shdr)) {\r
576       //\r
577       // Align the coff offset to meet with the alignment requirement of section\r
578       // itself.\r
579       // \r
580       if ((shdr->sh_addralign != 0) && (shdr->sh_addralign != 1)) {\r
581         CoffOffset = (CoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1);\r
582       }\r
583 \r
584       /* Relocate entry.  */\r
585       if ((Ehdr->e_entry >= shdr->sh_addr) && \r
586           (Ehdr->e_entry < shdr->sh_addr + shdr->sh_size)) {\r
587         CoffEntry = CoffOffset + Ehdr->e_entry - shdr->sh_addr;\r
588       }\r
589       CoffSectionsOffset[i] = CoffOffset;\r
590       CoffOffset += shdr->sh_size;\r
591     }\r
592   }\r
593   CoffOffset = CoffAlign(CoffOffset);\r
594 \r
595   //\r
596   //  Then data sections.\r
597   //\r
598   DataOffset = CoffOffset;\r
599   for (i = 0; i < Ehdr->e_shnum; i++) {\r
600     Elf_Shdr *shdr = GetShdrByIndex(i);\r
601     if (IsDataShdr(shdr)) {\r
602       //\r
603       // Align the coff offset to meet with the alignment requirement of section\r
604       // itself.\r
605       // \r
606       if ((shdr->sh_addralign != 0) && (shdr->sh_addralign != 1)) {\r
607         CoffOffset = (CoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1);\r
608       }\r
609      \r
610       CoffSectionsOffset[i] = CoffOffset;\r
611       CoffOffset += shdr->sh_size;\r
612     }\r
613   }\r
614   CoffOffset = CoffAlign(CoffOffset);\r
615 \r
616   RelocOffset = CoffOffset;  \r
617 \r
618   //\r
619   // Allocate base Coff file.  Will be expanded later for relocations. \r
620   //\r
621   CoffFile = (UINT8 *)malloc(CoffOffset);\r
622   memset(CoffFile, 0, CoffOffset);\r
623 \r
624   //\r
625   // Fill headers.\r
626   //\r
627   DosHdr = (EFI_IMAGE_DOS_HEADER *)CoffFile;\r
628   DosHdr->e_magic = EFI_IMAGE_DOS_SIGNATURE;\r
629   DosHdr->e_lfanew = NtHdrOffset;\r
630 \r
631   NtHdr = (EFI_IMAGE_NT_HEADERS*)(CoffFile + NtHdrOffset);\r
632 \r
633   NtHdr->Signature = EFI_IMAGE_NT_SIGNATURE;\r
634 \r
635   NtHdr->FileHeader.Machine = EFI_IMAGE_MACHINE_IA32;\r
636   NtHdr->FileHeader.NumberOfSections = CoffNbrSections;\r
637   NtHdr->FileHeader.TimeDateStamp = time(NULL);\r
638   NtHdr->FileHeader.PointerToSymbolTable = 0;\r
639   NtHdr->FileHeader.NumberOfSymbols = 0;\r
640   NtHdr->FileHeader.SizeOfOptionalHeader = sizeof(NtHdr->OptionalHeader);\r
641   NtHdr->FileHeader.Characteristics = EFI_IMAGE_FILE_EXECUTABLE_IMAGE\r
642     | EFI_IMAGE_FILE_LINE_NUMS_STRIPPED\r
643     | EFI_IMAGE_FILE_LOCAL_SYMS_STRIPPED\r
644     | EFI_IMAGE_FILE_32BIT_MACHINE;\r
645   \r
646   NtHdr->OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC;\r
647   NtHdr->OptionalHeader.SizeOfCode = DataOffset - TextOffset;\r
648   NtHdr->OptionalHeader.SizeOfInitializedData = RelocOffset - DataOffset;\r
649   NtHdr->OptionalHeader.SizeOfUninitializedData = 0;\r
650   NtHdr->OptionalHeader.AddressOfEntryPoint = CoffEntry;\r
651 \r
652   NtHdr->OptionalHeader.BaseOfCode = TextOffset;\r
653 \r
654   NtHdr->OptionalHeader.BaseOfData = DataOffset;\r
655   NtHdr->OptionalHeader.ImageBase = 0;\r
656   NtHdr->OptionalHeader.SectionAlignment = CoffAlignment;\r
657   NtHdr->OptionalHeader.FileAlignment = CoffAlignment;\r
658   NtHdr->OptionalHeader.SizeOfImage = 0;\r
659 \r
660   NtHdr->OptionalHeader.SizeOfHeaders = TextOffset;\r
661   NtHdr->OptionalHeader.NumberOfRvaAndSizes = EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES;\r
662 \r
663   //\r
664   // Section headers.\r
665   //\r
666   CreateSectionHeader (".text", TextOffset, DataOffset - TextOffset,\r
667            EFI_IMAGE_SCN_CNT_CODE\r
668            | EFI_IMAGE_SCN_MEM_EXECUTE\r
669            | EFI_IMAGE_SCN_MEM_READ);\r
670   CreateSectionHeader (".data", DataOffset, RelocOffset - DataOffset,\r
671            EFI_IMAGE_SCN_CNT_INITIALIZED_DATA\r
672            | EFI_IMAGE_SCN_MEM_WRITE\r
673            | EFI_IMAGE_SCN_MEM_READ);\r
674 }\r
675 \r
676 VOID\r
677 WriteSections(\r
678   int   (*Filter)(Elf_Shdr *)\r
679   )\r
680 {\r
681   UINT32 Idx;\r
682 \r
683   //\r
684   // First: copy sections.\r
685   //\r
686   for (Idx = 0; Idx < Ehdr->e_shnum; Idx++) {\r
687     Elf_Shdr *Shdr = GetShdrByIndex(Idx);\r
688     if ((*Filter)(Shdr)) {\r
689       switch (Shdr->sh_type) {\r
690       case SHT_PROGBITS:\r
691   /* Copy.  */\r
692   memcpy(CoffFile + CoffSectionsOffset[Idx],\r
693          (UINT8*)Ehdr + Shdr->sh_offset,\r
694          Shdr->sh_size);\r
695   break;\r
696       case SHT_NOBITS:\r
697   memset(CoffFile + CoffSectionsOffset[Idx], 0, Shdr->sh_size);\r
698   break;\r
699       default:\r
700   //\r
701   //  Ignore for unkown section type.\r
702   //    \r
703   VerboseMsg ("%s unknown section type %x. We directly copy this section into Coff file", mInImageName, (UINTN)Shdr->sh_type);\r
704   break;\r
705      }\r
706     }\r
707   }\r
708 \r
709   //\r
710   // Second: apply relocations.\r
711   //\r
712   for (Idx = 0; Idx < Ehdr->e_shnum; Idx++) {\r
713     Elf_Shdr *RelShdr = GetShdrByIndex(Idx);\r
714     if (RelShdr->sh_type != SHT_REL)\r
715       continue;\r
716     Elf_Shdr *SecShdr = GetShdrByIndex(RelShdr->sh_info);\r
717     UINT32 SecOffset = CoffSectionsOffset[RelShdr->sh_info];\r
718     if (RelShdr->sh_type == SHT_REL && (*Filter)(SecShdr)) {\r
719       UINT32 RelIdx;\r
720       Elf_Shdr *SymtabShdr = GetShdrByIndex(RelShdr->sh_link);\r
721       UINT8 *Symtab = (UINT8*)Ehdr + SymtabShdr->sh_offset;\r
722 \r
723       for (RelIdx = 0; RelIdx < RelShdr->sh_size; RelIdx += RelShdr->sh_entsize) {\r
724   Elf_Rel *Rel = (Elf_Rel *)((UINT8*)Ehdr + RelShdr->sh_offset + RelIdx);\r
725   Elf_Sym *Sym = (Elf_Sym *)\r
726     (Symtab + ELF_R_SYM(Rel->r_info) * SymtabShdr->sh_entsize);\r
727   Elf_Shdr *SymShdr;\r
728   UINT8 *Targ;\r
729 \r
730   if (Sym->st_shndx == SHN_UNDEF\r
731       || Sym->st_shndx == SHN_ABS\r
732       || Sym->st_shndx > Ehdr->e_shnum) {\r
733     Error (NULL, 0, 3000, "Invalid", "%s bad symbol definition.", mInImageName);\r
734   }\r
735   SymShdr = GetShdrByIndex(Sym->st_shndx);\r
736 \r
737   //\r
738   // Note: r_offset in a memory address.\r
739   //  Convert it to a pointer in the coff file.\r
740   //\r
741   Targ = CoffFile + SecOffset + (Rel->r_offset - SecShdr->sh_addr);\r
742 \r
743   switch (ELF_R_TYPE(Rel->r_info)) {\r
744   case R_386_NONE:\r
745     break;\r
746   case R_386_32:\r
747     //\r
748     // Absolute relocation.\r
749     //\r
750     *(UINT32 *)Targ = *(UINT32 *)Targ - SymShdr->sh_addr\r
751       + CoffSectionsOffset[Sym->st_shndx];\r
752     break;\r
753   case R_386_PC32:\r
754     //\r
755     // Relative relocation: Symbol - Ip + Addend\r
756     //\r
757     *(UINT32 *)Targ = *(UINT32 *)Targ\r
758       + (CoffSectionsOffset[Sym->st_shndx] - SymShdr->sh_addr)\r
759       - (SecOffset - SecShdr->sh_addr);\r
760     break;\r
761   default:\r
762     Error (NULL, 0, 3000, "Invalid", "%s unhandled section type %x.", mInImageName, ELF_R_TYPE(Rel->r_info));\r
763   }\r
764       }\r
765     }\r
766   }\r
767 }\r
768 \r
769 VOID\r
770 CoffAddFixupEntry(\r
771   UINT16 Val\r
772   )\r
773 {\r
774   *CoffEntryRel = Val;\r
775   CoffEntryRel++;\r
776   CoffBaseRel->SizeOfBlock += 2;\r
777   CoffOffset += 2;\r
778 }\r
779 \r
780 VOID\r
781 CoffAddFixup(\r
782   UINT32 Offset,\r
783   UINT8  Type\r
784   )\r
785 {\r
786   if (CoffBaseRel == NULL\r
787       || CoffBaseRel->VirtualAddress != (Offset & ~0xfff)) {\r
788     if (CoffBaseRel != NULL) {\r
789       //\r
790       // Add a null entry (is it required ?)\r
791       //\r
792       CoffAddFixupEntry (0);\r
793       //\r
794       // Pad for alignment.\r
795       //\r
796       if (CoffOffset % 4 != 0)\r
797   CoffAddFixupEntry (0);\r
798     }\r
799       \r
800     CoffFile = realloc\r
801       (CoffFile,\r
802        CoffOffset + sizeof(EFI_IMAGE_BASE_RELOCATION) + 2*0x1000);\r
803     memset(CoffFile + CoffOffset, 0,\r
804      sizeof(EFI_IMAGE_BASE_RELOCATION) + 2*0x1000);\r
805 \r
806     CoffBaseRel = (EFI_IMAGE_BASE_RELOCATION*)(CoffFile + CoffOffset);\r
807     CoffBaseRel->VirtualAddress = Offset & ~0xfff;\r
808     CoffBaseRel->SizeOfBlock = sizeof(EFI_IMAGE_BASE_RELOCATION);\r
809 \r
810     CoffEntryRel = (UINT16 *)(CoffBaseRel + 1);\r
811     CoffOffset += sizeof(EFI_IMAGE_BASE_RELOCATION);\r
812   }\r
813 \r
814   //\r
815   // Fill the entry.\r
816   //\r
817   CoffAddFixupEntry((Type << 12) | (Offset & 0xfff));\r
818 }\r
819 \r
820 VOID\r
821 WriteRelocations(\r
822   VOID\r
823   )\r
824 {\r
825   UINT32 Idx;\r
826   EFI_IMAGE_NT_HEADERS *NtHdr;\r
827   EFI_IMAGE_DATA_DIRECTORY *Dir;\r
828 \r
829   for (Idx = 0; Idx < Ehdr->e_shnum; Idx++) {\r
830     Elf_Shdr *RelShdr = GetShdrByIndex(Idx);\r
831     if (RelShdr->sh_type == SHT_REL) {\r
832       Elf_Shdr *SecShdr = GetShdrByIndex(RelShdr->sh_info);\r
833       if (IsTextShdr(SecShdr) || IsDataShdr(SecShdr)) {\r
834   UINT32 RelIdx;\r
835   for (RelIdx = 0; RelIdx < RelShdr->sh_size; RelIdx += RelShdr->sh_entsize) {\r
836     Elf_Rel *Rel = (Elf_Rel *)\r
837       ((UINT8*)Ehdr + RelShdr->sh_offset + RelIdx);\r
838     switch (ELF_R_TYPE(Rel->r_info)) {\r
839     case R_386_NONE:\r
840     case R_386_PC32:\r
841       break;\r
842     case R_386_32:\r
843       CoffAddFixup(CoffSectionsOffset[RelShdr->sh_info]\r
844        + (Rel->r_offset - SecShdr->sh_addr),\r
845        EFI_IMAGE_REL_BASED_HIGHLOW);\r
846       break;\r
847     default:\r
848       Error (NULL, 0, 3000, "Invalid", "%s unhandled section type %x.", mInImageName, ELF_R_TYPE(Rel->r_info));\r
849     }\r
850   }\r
851       }\r
852     }\r
853   }\r
854 \r
855   //\r
856   // Pad by adding empty entries. \r
857   //\r
858   while (CoffOffset & (CoffAlignment - 1)) {\r
859     CoffAddFixupEntry(0);\r
860   }\r
861 \r
862   CreateSectionHeader (".reloc", RelocOffset, CoffOffset - RelocOffset,\r
863            EFI_IMAGE_SCN_CNT_INITIALIZED_DATA\r
864            | EFI_IMAGE_SCN_MEM_DISCARDABLE\r
865            | EFI_IMAGE_SCN_MEM_READ);\r
866 \r
867   NtHdr = (EFI_IMAGE_NT_HEADERS *)(CoffFile + NtHdrOffset);\r
868   Dir = &NtHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];\r
869   Dir->VirtualAddress = RelocOffset;\r
870   Dir->Size = CoffOffset - RelocOffset;\r
871 }\r
872 \r
873 VOID\r
874 WriteDebug(\r
875   VOID\r
876   )\r
877 {\r
878   UINT32 Len = strlen(mInImageName) + 1;\r
879   UINT32 DebugOffset = CoffOffset;\r
880   EFI_IMAGE_NT_HEADERS *NtHdr;\r
881   EFI_IMAGE_DATA_DIRECTORY *DataDir;\r
882   EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *Dir;\r
883   EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY *Nb10;\r
884 \r
885   CoffOffset += sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY)\r
886     + sizeof(EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY)\r
887     + Len;\r
888   CoffOffset = CoffAlign(CoffOffset);\r
889 \r
890   CoffFile = realloc\r
891     (CoffFile, CoffOffset);\r
892   memset(CoffFile + DebugOffset, 0, CoffOffset - DebugOffset);\r
893   \r
894   Dir = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY*)(CoffFile + DebugOffset);\r
895   Dir->Type = EFI_IMAGE_DEBUG_TYPE_CODEVIEW;\r
896   Dir->SizeOfData = sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY) + Len;\r
897   Dir->RVA = DebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);\r
898   Dir->FileOffset = DebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);\r
899   \r
900   Nb10 = (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY*)(Dir + 1);\r
901   Nb10->Signature = CODEVIEW_SIGNATURE_NB10;\r
902   strcpy ((UINT8 *)(Nb10 + 1), mInImageName);\r
903 \r
904   CreateSectionHeader (".debug", DebugOffset, CoffOffset - DebugOffset,\r
905            EFI_IMAGE_SCN_CNT_INITIALIZED_DATA\r
906            | EFI_IMAGE_SCN_MEM_DISCARDABLE\r
907            | EFI_IMAGE_SCN_MEM_READ);\r
908 \r
909   NtHdr = (EFI_IMAGE_NT_HEADERS *)(CoffFile + NtHdrOffset);\r
910   DataDir = &NtHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG];\r
911   DataDir->VirtualAddress = DebugOffset;\r
912   DataDir->Size = CoffOffset - DebugOffset;\r
913 }\r
914 \r
915 VOID\r
916 ConvertElf (\r
917   UINT8  **FileBuffer,\r
918   UINTN *FileLength\r
919   )\r
920 {\r
921   EFI_IMAGE_NT_HEADERS *NtHdr;\r
922 \r
923   //\r
924   // Check header, read section table.\r
925   //\r
926   Ehdr = (Elf32_Ehdr*)*FileBuffer;\r
927   if (!CheckElfHeader())\r
928     return;\r
929 \r
930   VerboseMsg ("Check Efl Image Header");\r
931   //\r
932   // Compute sections new address.\r
933   //\r
934   ScanSections();\r
935   \r
936   VerboseMsg ("Compute sections new address.");\r
937 \r
938   //\r
939   // Write and relocate sections.\r
940   //\r
941   WriteSections(IsTextShdr);\r
942   WriteSections(IsDataShdr);\r
943   VerboseMsg ("Write and relocate sections.");\r
944 \r
945   //\r
946   // Translate and write relocations.\r
947   //\r
948   WriteRelocations();\r
949   VerboseMsg ("Translate and write relocations.");\r
950 \r
951   //\r
952   // Write debug info.\r
953   //\r
954   WriteDebug();\r
955   VerboseMsg ("Write debug info.");\r
956 \r
957   NtHdr = (EFI_IMAGE_NT_HEADERS *)(CoffFile + NtHdrOffset);\r
958   NtHdr->OptionalHeader.SizeOfImage = CoffOffset;\r
959 \r
960   //\r
961   // Replace.\r
962   //\r
963   free(*FileBuffer);\r
964   *FileBuffer = CoffFile;\r
965   *FileLength = CoffOffset;\r
966   \r
967   //\r
968   // Free memory space\r
969   //\r
970   if (CoffSectionsOffset != NULL) {\r
971     free (CoffSectionsOffset);\r
972   }\r
973 }\r
974 #endif // HAVE_ELF\r
975 \r
976 int\r
977 main (\r
978   int  argc,\r
979   char *argv[]\r
980   )\r
981 /*++\r
982 \r
983 Routine Description:\r
984 \r
985   Main function.\r
986 \r
987 Arguments:\r
988 \r
989   argc - Number of command line parameters.\r
990   argv - Array of pointers to command line parameter strings.\r
991 \r
992 Returns:\r
993   STATUS_SUCCESS - Utility exits successfully.\r
994   STATUS_ERROR   - Some error occurred during execution.\r
995 \r
996 --*/\r
997 {\r
998   UINT32            Type;\r
999   UINT32            InputFileNum;\r
1000   CHAR8             **InputFileName;\r
1001   UINT8             *OutImageName;\r
1002   UINT8             *ModuleType;\r
1003   CHAR8             *TimeStamp;\r
1004   CHAR8             FileName[_MAX_PATH];\r
1005   UINT32            OutImageType;\r
1006   FILE              *fpIn;\r
1007   FILE              *fpOut;\r
1008   FILE              *fpInOut;\r
1009   UINTN             Data;\r
1010   UINTN             *DataPointer;\r
1011   UINTN             *OldDataPointer;\r
1012   UINTN             CheckSum;\r
1013   UINT32            Index;\r
1014   UINT32            Index1;\r
1015   UINT32            Index2;\r
1016   UINT64            Temp64;\r
1017   UINT32            MciAlignment;\r
1018   UINT8             MciPadValue;\r
1019   UINT32            AllignedRelocSize;\r
1020   UINT8             *FileBuffer;\r
1021   UINT32            FileLength;\r
1022   RUNTIME_FUNCTION  *RuntimeFunction;\r
1023   UNWIND_INFO       *UnwindInfo;\r
1024   STATUS            Status;\r
1025   BOOLEAN           ReplaceFlag;\r
1026   BOOLEAN           KeepExceptionTableFlag;\r
1027   BOOLEAN           KeepZeroPendingFlag;\r
1028   UINT64            LogLevel;\r
1029   EFI_TE_IMAGE_HEADER          TEImageHeader;\r
1030   EFI_TE_IMAGE_HEADER          *TeHdr;\r
1031   EFI_IMAGE_SECTION_HEADER     *SectionHeader;\r
1032   EFI_IMAGE_DOS_HEADER         *DosHdr;\r
1033   EFI_IMAGE_NT_HEADERS         *PeHdr;\r
1034   EFI_IMAGE_OPTIONAL_HEADER32  *Optional32;\r
1035   EFI_IMAGE_OPTIONAL_HEADER64  *Optional64;\r
1036   EFI_IMAGE_DOS_HEADER         BackupDosHdr;\r
1037   MICROCODE_IMAGE_HEADER       *MciHeader; \r
1038 \r
1039   SetUtilityName (UTILITY_NAME);\r
1040 \r
1041   //\r
1042   // Assign to fix compile warning\r
1043   //\r
1044   InputFileNum      = 0; \r
1045   InputFileName     = NULL;\r
1046   mInImageName       = NULL;\r
1047   OutImageName      = NULL;\r
1048   ModuleType        = NULL;\r
1049   OutImageType      = FW_DUMMY_IMAGE;\r
1050   Type              = 0;\r
1051   Status            = STATUS_SUCCESS;\r
1052   FileBuffer        = NULL;\r
1053   fpIn              = NULL;\r
1054   fpOut             = NULL;\r
1055   fpInOut           = NULL;\r
1056   TimeStamp         = NULL;\r
1057   MciAlignment      = DEFAULT_MC_ALIGNMENT;\r
1058   MciPadValue       = DEFAULT_MC_PAD_BYTE_VALUE;\r
1059   FileLength        = 0;\r
1060   MciHeader         = NULL;\r
1061   CheckSum          = 0;\r
1062   ReplaceFlag       = FALSE;\r
1063   LogLevel          = 0;\r
1064   KeepExceptionTableFlag = FALSE;\r
1065   KeepZeroPendingFlag    = FALSE;\r
1066 \r
1067   if (argc == 1) {\r
1068     Error (NULL, 0, 1001, "Missing options", "No input options.");\r
1069     Usage ();\r
1070     return STATUS_ERROR;\r
1071   }\r
1072   \r
1073   argc --;\r
1074   argv ++;  \r
1075 \r
1076   if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) {\r
1077     Version ();\r
1078     Usage ();\r
1079     return STATUS_SUCCESS;    \r
1080   }\r
1081 \r
1082   if (stricmp (argv[0], "--version") == 0) {\r
1083     Version ();\r
1084     return STATUS_SUCCESS;\r
1085   }\r
1086 \r
1087   while (argc > 0) {\r
1088     if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--outputfile") == 0)) {\r
1089       OutImageName = argv[1];\r
1090       if (OutImageName == NULL) {\r
1091         Error (NULL, 0, 1003, "Invalid option value", "Output file name can't be NULL");\r
1092         goto Finish;\r
1093       }\r
1094       argc -= 2;\r
1095       argv += 2;\r
1096       continue; \r
1097     }\r
1098 \r
1099     if ((stricmp (argv[0], "-e") == 0) || (stricmp (argv[0], "--efiImage") == 0)) {\r
1100       ModuleType   = argv[1];\r
1101       if (ModuleType == NULL) {\r
1102         Error (NULL, 0, 1003, "Invalid option value", "Module Type can't be NULL");\r
1103         goto Finish;        \r
1104       }\r
1105       if (OutImageType != FW_TE_IMAGE) {\r
1106         OutImageType = FW_EFI_IMAGE;\r
1107       }\r
1108       argc -= 2;\r
1109       argv += 2;\r
1110       continue;\r
1111     }\r
1112 \r
1113     if ((stricmp (argv[0], "-l") == 0) || (stricmp (argv[0], "--stripped") == 0)) {\r
1114       OutImageType = FW_RELOC_STRIPEED_IMAGE;\r
1115       argc --;\r
1116       argv ++;\r
1117       continue;\r
1118     }\r
1119 \r
1120     if ((stricmp (argv[0], "-c") == 0) || (stricmp (argv[0], "--acpi") == 0)) {\r
1121       OutImageType = FW_ACPI_IMAGE;\r
1122       argc --;\r
1123       argv ++;\r
1124       continue;\r
1125     }\r
1126 \r
1127     if ((stricmp (argv[0], "-t") == 0) || (stricmp (argv[0], "--terse") == 0)) {\r
1128       OutImageType = FW_TE_IMAGE;\r
1129       argc --;\r
1130       argv ++;\r
1131       continue;\r
1132     }\r
1133 \r
1134     if ((stricmp (argv[0], "-u") == 0) || (stricmp (argv[0], "--dump") == 0)) {\r
1135       OutImageType = DUMP_TE_HEADER;\r
1136       argc --;\r
1137       argv ++;\r
1138       continue;\r
1139     }\r
1140 \r
1141     if ((stricmp (argv[0], "-b") == 0) || (stricmp (argv[0], "--exe2bin") == 0)) {\r
1142       OutImageType = FW_BIN_IMAGE;\r
1143       argc --;\r
1144       argv ++;\r
1145       continue;\r
1146     }\r
1147 \r
1148     if ((stricmp (argv[0], "-z") == 0) || (stricmp (argv[0], "--zero") == 0)) {\r
1149       OutImageType = FW_ZERO_DEBUG_IMAGE;\r
1150       argc --;\r
1151       argv ++;\r
1152       continue;\r
1153     }\r
1154 \r
1155     if ((stricmp (argv[0], "-s") == 0) || (stricmp (argv[0], "--stamp") == 0)) {\r
1156       OutImageType = FW_SET_STAMP_IMAGE;\r
1157       TimeStamp    = argv[1];\r
1158       argc -= 2;\r
1159       argv += 2;\r
1160       continue;\r
1161     }\r
1162 \r
1163     if ((stricmp (argv[0], "-r") == 0) || (stricmp (argv[0], "--replace") == 0)) {\r
1164       ReplaceFlag = TRUE;\r
1165       argc --;\r
1166       argv ++;\r
1167       continue;\r
1168     }\r
1169 \r
1170     if (stricmp (argv[0], "--keepexceptiontable") == 0) {\r
1171       KeepExceptionTableFlag = TRUE;\r
1172       argc --;\r
1173       argv ++;\r
1174       continue;\r
1175     }\r
1176 \r
1177     if (stricmp (argv[0], "--keepzeropending") == 0) {\r
1178       KeepZeroPendingFlag = TRUE;\r
1179       argc --;\r
1180       argv ++;\r
1181       continue;\r
1182     }\r
1183 \r
1184     if ((stricmp (argv[0], "-m") == 0) || (stricmp (argv[0], "--mcifile") == 0)) {\r
1185       OutImageType = FW_MCI_IMAGE;\r
1186       argc --;\r
1187       argv ++;\r
1188       continue;\r
1189     }\r
1190 \r
1191     if ((stricmp (argv[0], "-j") == 0) || (stricmp (argv[0], "--join") == 0)) {\r
1192       OutImageType = FW_MERGE_IMAGE;\r
1193       argc --;\r
1194       argv ++;\r
1195       continue;\r
1196     }\r
1197 \r
1198     if ((stricmp (argv[0], "-a") == 0) || (stricmp (argv[0], "--align") == 0)) {\r
1199       if (AsciiStringToUint64 (argv[1], FALSE, &Temp64) != EFI_SUCCESS) {\r
1200         Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
1201         goto Finish;\r
1202       }\r
1203       MciAlignment = (UINT32) Temp64;\r
1204       argc -= 2;\r
1205       argv += 2;\r
1206       continue;\r
1207     }\r
1208 \r
1209     if ((stricmp (argv[0], "-p") == 0) || (stricmp (argv[0], "--pad") == 0)) {\r
1210       if (AsciiStringToUint64 (argv[1], FALSE, &Temp64) != EFI_SUCCESS) {\r
1211         Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
1212         goto Finish;\r
1213       }\r
1214       MciPadValue = (UINT8) Temp64;\r
1215       argc -= 2;\r
1216       argv += 2;\r
1217       continue;\r
1218     }\r
1219 \r
1220     if ((stricmp (argv[0], "-v") == 0) || (stricmp (argv[0], "--verbose") == 0)) {\r
1221       SetPrintLevel (VERBOSE_LOG_LEVEL);\r
1222       VerboseMsg ("Verbose output Mode Set!");\r
1223       argc --;\r
1224       argv ++;\r
1225       continue;\r
1226     }\r
1227 \r
1228     if ((stricmp (argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) {\r
1229       SetPrintLevel (KEY_LOG_LEVEL);\r
1230       KeyMsg ("Quiet output Mode Set!");\r
1231       argc --;\r
1232       argv ++;\r
1233       continue;\r
1234     }\r
1235 \r
1236     if ((stricmp (argv[0], "-d") == 0) || (stricmp (argv[0], "--debug") == 0)) {\r
1237       Status = AsciiStringToUint64 (argv[1], FALSE, &LogLevel);\r
1238       if (EFI_ERROR (Status)) {\r
1239         Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
1240         goto Finish;\r
1241       }\r
1242       if (LogLevel > 9) {\r
1243         Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0-9, currnt input level is %d", LogLevel);\r
1244         goto Finish;\r
1245       }\r
1246       SetPrintLevel (LogLevel);\r
1247       DebugMsg (NULL, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv[1]);\r
1248       argc -= 2;\r
1249       argv += 2;\r
1250       continue;\r
1251     }\r
1252 \r
1253     //\r
1254     // Get Input file name\r
1255     //\r
1256     if ((InputFileNum == 0) && (InputFileName == NULL)) {\r
1257       InputFileName = (CHAR8 **) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *));\r
1258       if (InputFileName == NULL) {\r
1259         Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
1260         return EFI_OUT_OF_RESOURCES;\r
1261       }\r
1262 \r
1263       memset (InputFileName, 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));\r
1264     } else if (InputFileNum % MAXIMUM_INPUT_FILE_NUM == 0) {\r
1265       //\r
1266       // InputFileName buffer too small, need to realloc\r
1267       //\r
1268       InputFileName = (CHAR8 **) realloc (\r
1269                                   InputFileName,\r
1270                                   (InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (CHAR8 *)\r
1271                                   );\r
1272 \r
1273       if (InputFileName == NULL) {\r
1274         Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
1275         return EFI_OUT_OF_RESOURCES;\r
1276       }\r
1277 \r
1278       memset (&(InputFileName[InputFileNum]), 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));\r
1279     }\r
1280 \r
1281     InputFileName [InputFileNum ++] = argv[0];\r
1282     argc --;\r
1283     argv ++;\r
1284   }\r
1285   \r
1286   VerboseMsg ("%s tool start.", UTILITY_NAME);\r
1287 \r
1288   if (OutImageType == FW_DUMMY_IMAGE) {\r
1289     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!");\r
1290     if (ReplaceFlag) {\r
1291       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.");\r
1292     }\r
1293     goto Finish;\r
1294   }\r
1295 \r
1296   //\r
1297   // check input files\r
1298   //\r
1299   if (InputFileNum == 0) {\r
1300     Error (NULL, 0, 1001, "Missing option", "Input files");\r
1301     goto Finish;\r
1302   }\r
1303 \r
1304   //\r
1305   // Combine MciBinary files to one file\r
1306   //\r
1307   if ((OutImageType == FW_MERGE_IMAGE) && ReplaceFlag) {\r
1308     Error (NULL, 0, 1002, "Conflicting option", "-r replace option cannot be used with -j merge files option.");\r
1309     goto Finish;\r
1310   }\r
1311    \r
1312   //\r
1313   // Input image file\r
1314   //\r
1315   mInImageName = InputFileName [InputFileNum - 1];\r
1316   VerboseMsg ("the input file name is %s", mInImageName);\r
1317   \r
1318   //\r
1319   // Action will be taken for the input file.\r
1320   //\r
1321   switch (OutImageType) {\r
1322   case FW_EFI_IMAGE:\r
1323     VerboseMsg ("Create efi image on module type %s based on the input PE image.", ModuleType);\r
1324     break;\r
1325   case FW_TE_IMAGE:\r
1326     VerboseMsg ("Create Te Image based on the input PE image.");\r
1327     break;\r
1328   case FW_ACPI_IMAGE:\r
1329     VerboseMsg ("Get acpi table data from the input PE image.");\r
1330     break;\r
1331   case FW_RELOC_STRIPEED_IMAGE:\r
1332     VerboseMsg ("Remove relocation section from Pe or Te image.");\r
1333     break;\r
1334   case FW_BIN_IMAGE:\r
1335     VerboseMsg ("Convert the input EXE to the output BIN file.");\r
1336     break;\r
1337   case FW_ZERO_DEBUG_IMAGE:\r
1338     VerboseMsg ("Zero the Debug Data Fields in input PE image.");\r
1339     break;\r
1340   case FW_SET_STAMP_IMAGE:\r
1341     VerboseMsg ("Set new time stamp %s in the input PE image.", TimeStamp);\r
1342     break;\r
1343   case DUMP_TE_HEADER:\r
1344     VerboseMsg ("Dump the TE header information of the input TE image.");\r
1345     break;\r
1346   case FW_MCI_IMAGE:\r
1347     VerboseMsg ("Conver input MicroCode.txt file to MicroCode.bin file.");\r
1348     break;\r
1349   case FW_MERGE_IMAGE:\r
1350     VerboseMsg ("Combine the input multi microcode bin files to one bin file.");\r
1351     break;\r
1352   default:\r
1353     break;\r
1354   }\r
1355   \r
1356   if (ReplaceFlag) {\r
1357     VerboseMsg ("Overwrite the input file with the output content.");\r
1358   }\r
1359 \r
1360   //\r
1361   // Open output file and Write image into the output file.\r
1362   //\r
1363   if (OutImageName != NULL) {\r
1364     fpOut = fopen (OutImageName, "wb");\r
1365     if (!fpOut) {\r
1366       Error (NULL, 0, 0001, "Error opening file", OutImageName);\r
1367       goto Finish;\r
1368     }\r
1369     VerboseMsg ("Output file name is %s", OutImageName);\r
1370   } else if (!ReplaceFlag) {\r
1371     if (OutImageType == DUMP_TE_HEADER) {\r
1372       fpOut = stdout;\r
1373     } else {\r
1374       Error (NULL, 0, 1001, "Missing option", "output file");\r
1375       goto Finish;\r
1376     }\r
1377   }\r
1378 \r
1379   //\r
1380   // Combine MciBinary files to one file\r
1381   //\r
1382   if (OutImageType == FW_MERGE_IMAGE) {\r
1383     for (Index = 0; Index < InputFileNum; Index ++) {\r
1384       fpIn = fopen (InputFileName [Index], "rb");\r
1385       if (!fpIn) {\r
1386         Error (NULL, 0, 0001, "Error opening file", InputFileName [Index]);\r
1387         goto Finish;\r
1388       }\r
1389     \r
1390       FileLength = _filelength (fileno (fpIn));\r
1391       FileBuffer = malloc (FileLength);\r
1392       if (FileBuffer == NULL) {\r
1393         Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
1394         fclose (fpIn);\r
1395         goto Finish;\r
1396       }\r
1397       \r
1398       fread (FileBuffer, 1, FileLength, fpIn);\r
1399       fclose (fpIn);\r
1400       //\r
1401       // write input file to out file\r
1402       //\r
1403       fwrite (FileBuffer, 1, FileLength, fpOut);\r
1404       //\r
1405       // write pad value to out file.\r
1406       //\r
1407       while (FileLength ++ % MciAlignment != 0) {\r
1408         fwrite (&MciPadValue, 1, 1, fpOut);\r
1409       }\r
1410       //\r
1411       // free allocated memory space\r
1412       //\r
1413       free (FileBuffer);\r
1414       FileBuffer = NULL;\r
1415     }\r
1416     // \r
1417     // Done successfully\r
1418     //\r
1419     goto Finish;\r
1420   }\r
1421 \r
1422   //\r
1423   // Convert MicroCode.txt file to MicroCode.bin file\r
1424   //\r
1425   if (OutImageType == FW_MCI_IMAGE) {\r
1426     fpIn = fopen (mInImageName, "r");\r
1427     if (!fpIn) {\r
1428       Error (NULL, 0, 0001, "Error opening file", mInImageName);\r
1429       goto Finish;\r
1430     }\r
1431     \r
1432     //\r
1433     // The first pass is to determine \r
1434     // how much data is in the file so we can allocate a working buffer. \r
1435     //\r
1436     FileLength = 0;\r
1437     do {\r
1438       Status = MicrocodeReadData (fpIn, &Data);\r
1439       if (Status == STATUS_SUCCESS) {\r
1440         FileLength += sizeof (Data);\r
1441       }\r
1442       if (Status == STATUS_IGNORE) {\r
1443         Status = STATUS_SUCCESS;\r
1444       }\r
1445     } while (Status == STATUS_SUCCESS);\r
1446     //\r
1447     // Error if no data.\r
1448     //\r
1449     if (FileLength == 0) {\r
1450       Error (NULL, 0, 3000, "Invalid", "no parseable data found in file %s", mInImageName);\r
1451       goto Finish;\r
1452     }\r
1453     if (FileLength < sizeof (MICROCODE_IMAGE_HEADER)) {\r
1454       Error (NULL, 0, 3000, "Invalid", "amount of parseable data in %s is insufficient to contain a microcode header", mInImageName);\r
1455       goto Finish;\r
1456     }\r
1457 \r
1458     //\r
1459     // Allocate a buffer for the data\r
1460     //\r
1461     FileBuffer = malloc (FileLength);\r
1462     if (FileBuffer == NULL) {\r
1463       Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
1464       goto Finish;\r
1465     }\r
1466     //\r
1467     // Re-read the file, storing the data into our buffer\r
1468     //\r
1469     fseek (fpIn, 0, SEEK_SET);\r
1470     DataPointer = (UINTN *) FileBuffer;\r
1471     OldDataPointer = DataPointer;\r
1472     do {\r
1473       OldDataPointer = DataPointer;\r
1474       Status = MicrocodeReadData (fpIn, DataPointer++);\r
1475       if (Status == STATUS_IGNORE) {\r
1476         DataPointer = OldDataPointer;\r
1477         Status = STATUS_SUCCESS;\r
1478       }\r
1479     } while (Status == STATUS_SUCCESS);\r
1480     //\r
1481     // close input file after read data\r
1482     //\r
1483     fclose (fpIn);\r
1484 \r
1485     //\r
1486     // Can't do much checking on the header because, per the spec, the\r
1487     // DataSize field may be 0, which means DataSize = 2000 and TotalSize = 2K,\r
1488     // and the TotalSize field is invalid (actually missing). Thus we can't\r
1489     // even verify the Reserved fields are 0.\r
1490     //\r
1491     MciHeader = (MICROCODE_IMAGE_HEADER *) FileBuffer;\r
1492     if (MciHeader->DataSize == 0) {\r
1493       Index = 2048;\r
1494     } else {\r
1495       Index = MciHeader->TotalSize;\r
1496     }\r
1497 \r
1498     if (Index != FileLength) {\r
1499       Error (NULL, 0, 3000, "Invalid", "file length of %s (0x%x) does not equal expected TotalSize: 0x%04X.", mInImageName, FileLength, Index);\r
1500       goto Finish;\r
1501     }\r
1502 \r
1503     //\r
1504     // Checksum the contents\r
1505     //\r
1506     DataPointer = (UINTN *) FileBuffer;\r
1507     CheckSum  = 0;\r
1508     Index     = 0;\r
1509     while (Index < FileLength) {\r
1510       CheckSum    += *DataPointer;\r
1511       DataPointer ++;\r
1512       Index       += sizeof (UINTN);\r
1513     }\r
1514     if (CheckSum != 0) {\r
1515       Error (NULL, 0, 3000, "Invalid", "checksum (0x%x) failed on file %s.", CheckSum, mInImageName);\r
1516       goto Finish;\r
1517     }\r
1518     //\r
1519     // Open the output file and write the buffer contents\r
1520     //\r
1521     if (fpOut != NULL) {\r
1522       if (fwrite (FileBuffer, FileLength, 1, fpOut) != 1) {\r
1523         Error (NULL, 0, 0002, "Error writing file", OutImageName);\r
1524         goto Finish;\r
1525       }\r
1526     }\r
1527     \r
1528     if (ReplaceFlag) {\r
1529       fpInOut = fopen (mInImageName, "wb");\r
1530       if (fpInOut != NULL) {\r
1531         Error (NULL, 0, 0001, "Error opening file", mInImageName);\r
1532         goto Finish;\r
1533       }\r
1534       if (fwrite (FileBuffer, FileLength, 1, fpInOut) != 1) {\r
1535         Error (NULL, 0, 0002, "Error writing file", mInImageName);\r
1536         goto Finish;\r
1537       }\r
1538     }\r
1539     VerboseMsg ("the size of output file is %d bytes", FileLength);\r
1540     //\r
1541     //  Convert Mci.TXT to Mci.bin file successfully\r
1542     //\r
1543     goto Finish;\r
1544   }\r
1545 \r
1546   //\r
1547   // Open input file and read file data into file buffer.\r
1548   //\r
1549   fpIn = fopen (mInImageName, "rb");\r
1550   if (!fpIn) {\r
1551     Error (NULL, 0, 0001, "Error opening file", mInImageName);\r
1552     goto Finish;\r
1553   }\r
1554 \r
1555   FileLength = _filelength (fileno (fpIn));\r
1556   FileBuffer = malloc (FileLength);\r
1557   if (FileBuffer == NULL) {\r
1558     Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
1559     fclose (fpIn);\r
1560     goto Finish;\r
1561   }\r
1562   \r
1563   fread (FileBuffer, 1, FileLength, fpIn);\r
1564   fclose (fpIn);\r
1565   \r
1566   DebugMsg (NULL, 0, 9, "input file info", "the input file size is %d bytes", FileLength);\r
1567   \r
1568   //\r
1569   // Replace file\r
1570   //\r
1571   if (ReplaceFlag) {\r
1572     fpInOut = fopen (mInImageName, "wb");\r
1573     if (!fpInOut) {\r
1574       Error (NULL, 0, 0001, "Error opening file", mInImageName);\r
1575       goto Finish;\r
1576     }\r
1577   }\r
1578   //\r
1579   // Dump TeImage Header into output file.\r
1580   //\r
1581   if (OutImageType == DUMP_TE_HEADER) {\r
1582     memcpy (&TEImageHeader, FileBuffer, sizeof (TEImageHeader));\r
1583     if (TEImageHeader.Signature != EFI_TE_IMAGE_HEADER_SIGNATURE) {\r
1584       Error (NULL, 0, 3000, "Invalid", "TE header signature of file %s is not correct.", mInImageName);\r
1585       goto Finish;      \r
1586     }\r
1587     if (fpInOut != NULL) {\r
1588       fprintf (fpInOut, "Dump of file %s\n\n", mInImageName);\r
1589       fprintf (fpInOut, "TE IMAGE HEADER VALUES\n");\r
1590       fprintf (fpInOut, "%17X machine\n", TEImageHeader.Machine);\r
1591       fprintf (fpInOut, "%17X number of sections\n", TEImageHeader.NumberOfSections);\r
1592       fprintf (fpInOut, "%17X subsystems\n", TEImageHeader.Subsystem);\r
1593       fprintf (fpInOut, "%17X stripped size\n", TEImageHeader.StrippedSize);\r
1594       fprintf (fpInOut, "%17X entry point\n", TEImageHeader.AddressOfEntryPoint);\r
1595       fprintf (fpInOut, "%17X base of code\n", TEImageHeader.BaseOfCode);\r
1596       fprintf (fpInOut, "%17X image base\n", TEImageHeader.ImageBase);\r
1597       fprintf (fpInOut, "%17X [%8X] RVA [size] of Base Relocation Directory\n", TEImageHeader.DataDirectory[0].VirtualAddress, TEImageHeader.DataDirectory[0].Size);\r
1598       fprintf (fpInOut, "%17X [%8X] RVA [size] of Debug Directory\n", TEImageHeader.DataDirectory[1].VirtualAddress, TEImageHeader.DataDirectory[1].Size);\r
1599     }\r
1600 \r
1601     if (fpOut != NULL) {\r
1602       fprintf (fpOut, "Dump of file %s\n\n", mInImageName);\r
1603       fprintf (fpOut, "TE IMAGE HEADER VALUES\n");\r
1604       fprintf (fpOut, "%17X machine\n", TEImageHeader.Machine);\r
1605       fprintf (fpOut, "%17X number of sections\n", TEImageHeader.NumberOfSections);\r
1606       fprintf (fpOut, "%17X subsystems\n", TEImageHeader.Subsystem);\r
1607       fprintf (fpOut, "%17X stripped size\n", TEImageHeader.StrippedSize);\r
1608       fprintf (fpOut, "%17X entry point\n", TEImageHeader.AddressOfEntryPoint);\r
1609       fprintf (fpOut, "%17X base of code\n", TEImageHeader.BaseOfCode);\r
1610       fprintf (fpOut, "%17X image base\n", TEImageHeader.ImageBase);\r
1611       fprintf (fpOut, "%17X [%8X] RVA [size] of Base Relocation Directory\n", TEImageHeader.DataDirectory[0].VirtualAddress, TEImageHeader.DataDirectory[0].Size);\r
1612       fprintf (fpOut, "%17X [%8X] RVA [size] of Debug Directory\n", TEImageHeader.DataDirectory[1].VirtualAddress, TEImageHeader.DataDirectory[1].Size);\r
1613     }\r
1614     goto Finish;\r
1615   }\r
1616 \r
1617   //\r
1618   // Following code to convert dll to efi image or te image.\r
1619   // Get new image type\r
1620   //\r
1621   if ((OutImageType == FW_EFI_IMAGE) || (OutImageType == FW_TE_IMAGE)) {\r
1622     if (ModuleType == NULL) {\r
1623       if (OutImageType == FW_EFI_IMAGE) {\r
1624         Error (NULL, 0, 1001, "Missing option", "EFI_FILETYPE");\r
1625         goto Finish;\r
1626       } else if (OutImageType == FW_TE_IMAGE) {\r
1627         //\r
1628         // Default TE Image Type is Boot service driver\r
1629         //\r
1630         Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER;\r
1631         VerboseMsg ("Efi Image subsystem type is efi boot service driver.");\r
1632       }\r
1633     } else {\r
1634       if (stricmp (ModuleType, "BASE") == 0 ||\r
1635           stricmp (ModuleType, "SEC") == 0 ||\r
1636           stricmp (ModuleType, "SECURITY_CORE") == 0 ||\r
1637           stricmp (ModuleType, "PEI_CORE") == 0 ||\r
1638           stricmp (ModuleType, "PEIM") == 0 ||\r
1639           stricmp (ModuleType, "COMBINED_PEIM_DRIVER") == 0 ||\r
1640           stricmp (ModuleType, "PIC_PEIM") == 0 ||\r
1641           stricmp (ModuleType, "RELOCATABLE_PEIM") == 0 ||\r
1642           stricmp (ModuleType, "DXE_CORE") == 0 ||\r
1643           stricmp (ModuleType, "BS_DRIVER") == 0  ||\r
1644           stricmp (ModuleType, "DXE_DRIVER") == 0 ||\r
1645           stricmp (ModuleType, "DXE_SMM_DRIVER") == 0  ||\r
1646           stricmp (ModuleType, "UEFI_DRIVER") == 0) {\r
1647         Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER;\r
1648         VerboseMsg ("Efi Image subsystem type is efi boot service driver.");\r
1649     \r
1650       } else if (stricmp (ModuleType, "UEFI_APPLICATION") == 0 || \r
1651                  stricmp (ModuleType, "APPLICATION") == 0) {\r
1652         Type = EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION;\r
1653         VerboseMsg ("Efi Image subsystem type is efi application.");\r
1654     \r
1655       } else if (stricmp (ModuleType, "DXE_RUNTIME_DRIVER") == 0 || \r
1656                  stricmp (ModuleType, "RT_DRIVER") == 0) {\r
1657         Type = EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER;\r
1658         VerboseMsg ("Efi Image subsystem type is efi runtime driver.");\r
1659     \r
1660       } else if (stricmp (ModuleType, "DXE_SAL_DRIVER") == 0 || \r
1661                  stricmp (ModuleType, "SAL_RT_DRIVER") == 0) {\r
1662         Type = EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER;\r
1663         VerboseMsg ("Efi Image subsystem type is efi sal runtime driver.");\r
1664     \r
1665       } else {\r
1666         Error (NULL, 0, 1003, "Invalid option value", "EFI_FILETYPE = %s", ModuleType);\r
1667         goto Finish;\r
1668       }\r
1669     }\r
1670   }\r
1671 \r
1672   //\r
1673   // Convert EFL image to PeImage\r
1674   //\r
1675 #ifdef HAVE_ELF\r
1676   if (IsElfHeader(FileBuffer)) {\r
1677     VerboseMsg ("Convert the input ELF Image to Pe Image");\r
1678     ConvertElf(&FileBuffer, &FileLength);\r
1679   }\r
1680 #endif\r
1681   \r
1682   //\r
1683   // Remove reloc section from PE or TE image\r
1684   //\r
1685   if (OutImageType == FW_RELOC_STRIPEED_IMAGE) {\r
1686     //\r
1687     // Check TeImage\r
1688     //\r
1689     TeHdr = (EFI_TE_IMAGE_HEADER *) FileBuffer;\r
1690     if (TeHdr->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {\r
1691       SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (TeHdr + 1);\r
1692       for (Index = 0; Index < TeHdr->NumberOfSections; Index ++, SectionHeader ++) {\r
1693         if (strcmp (SectionHeader->Name, ".reloc") == 0) {\r
1694           //\r
1695           // Check the reloc section is in the end of image.\r
1696           //\r
1697           if ((SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData) == \r
1698             (FileLength + TeHdr->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER))) {\r
1699             //\r
1700             // Remove .reloc section and update TeImage Header\r
1701             //\r
1702             FileLength = FileLength - SectionHeader->SizeOfRawData;\r
1703             SectionHeader->SizeOfRawData = 0;\r
1704             SectionHeader->Misc.VirtualSize = 0;\r
1705             TeHdr->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = 0;\r
1706             TeHdr->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size           = 0;\r
1707             break;\r
1708           }\r
1709         }\r
1710       }\r
1711     } else {\r
1712       //\r
1713       // Check PE Image\r
1714       //\r
1715       DosHdr = (EFI_IMAGE_DOS_HEADER *) FileBuffer;\r
1716       if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {\r
1717         Error (NULL, 0, 3000, "Invalid", "TE and DOS header signatures were not found in %s image.", mInImageName);\r
1718         goto Finish;\r
1719       }\r
1720       PeHdr = (EFI_IMAGE_NT_HEADERS *)(FileBuffer + DosHdr->e_lfanew);\r
1721       if (PeHdr->Signature != EFI_IMAGE_NT_SIGNATURE) {\r
1722         Error (NULL, 0, 3000, "Invalid", "PE header signature was not found in %s image.", mInImageName);\r
1723         goto Finish;\r
1724       }\r
1725       SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->OptionalHeader) + PeHdr->FileHeader.SizeOfOptionalHeader);\r
1726       for (Index = 0; Index < PeHdr->FileHeader.NumberOfSections; Index ++, SectionHeader ++) {\r
1727         if (strcmp (SectionHeader->Name, ".reloc") == 0) {\r
1728           //\r
1729           // Check the reloc section is in the end of image.\r
1730           //\r
1731           if ((SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData) == FileLength) {\r
1732             //\r
1733             // Remove .reloc section and update PeImage Header\r
1734             //\r
1735             FileLength = FileLength - SectionHeader->SizeOfRawData;\r
1736 \r
1737             PeHdr->FileHeader.Characteristics |= EFI_IMAGE_FILE_RELOCS_STRIPPED;\r
1738             if (PeHdr->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
1739               Optional32 = (EFI_IMAGE_OPTIONAL_HEADER32 *)&PeHdr->OptionalHeader;\r
1740               Optional32->SizeOfImage -= SectionHeader->SizeOfRawData;\r
1741               Optional32->SizeOfInitializedData -= SectionHeader->SizeOfRawData;\r
1742               if (Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {\r
1743                 Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = 0;\r
1744                 Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = 0;\r
1745               }\r
1746             }\r
1747             if (PeHdr->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
1748               Optional64 = (EFI_IMAGE_OPTIONAL_HEADER64 *)&PeHdr->OptionalHeader;\r
1749               Optional64->SizeOfImage -= SectionHeader->SizeOfRawData;\r
1750               Optional64->SizeOfInitializedData -= SectionHeader->SizeOfRawData;\r
1751               if (Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {\r
1752                 Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = 0;\r
1753                 Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = 0;\r
1754               }\r
1755             }\r
1756             SectionHeader->Misc.VirtualSize = 0;\r
1757             SectionHeader->SizeOfRawData = 0;\r
1758             break;\r
1759           }\r
1760         }\r
1761       }\r
1762     }\r
1763     //\r
1764     // Write file\r
1765     //\r
1766     goto WriteFile;\r
1767   }\r
1768   //\r
1769   // Read the dos & pe hdrs of the image\r
1770   //\r
1771   DosHdr = (EFI_IMAGE_DOS_HEADER *)FileBuffer;\r
1772   if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {\r
1773     Error (NULL, 0, 3000, "Invalid", "DOS header signature was not found in %s image.", mInImageName);\r
1774     goto Finish;\r
1775   }\r
1776 \r
1777   PeHdr = (EFI_IMAGE_NT_HEADERS *)(FileBuffer + DosHdr->e_lfanew);\r
1778   if (PeHdr->Signature != EFI_IMAGE_NT_SIGNATURE) {\r
1779     Error (NULL, 0, 3000, "Invalid", "PE header signature was not found in %s image.", mInImageName);\r
1780     goto Finish;\r
1781   }\r
1782   \r
1783   //\r
1784   // Extract bin data from Pe image.\r
1785   //\r
1786   if (OutImageType == FW_BIN_IMAGE) {\r
1787     if (FileLength < PeHdr->OptionalHeader.SizeOfHeaders) {\r
1788       Error (NULL, 0, 3000, "Invalid", "FileSize of %s is not a legal size.", mInImageName);\r
1789       goto Finish;\r
1790     }\r
1791     //\r
1792     // Output bin data from exe file\r
1793     //\r
1794     if (fpOut != NULL) {\r
1795       fwrite (FileBuffer + PeHdr->OptionalHeader.SizeOfHeaders, 1, FileLength - PeHdr->OptionalHeader.SizeOfHeaders, fpOut);\r
1796     }\r
1797     if (fpInOut != NULL) {\r
1798       fwrite (FileBuffer + PeHdr->OptionalHeader.SizeOfHeaders, 1, FileLength - PeHdr->OptionalHeader.SizeOfHeaders, fpInOut);\r
1799     }\r
1800     VerboseMsg ("the size of output file is %d bytes", FileLength - PeHdr->OptionalHeader.SizeOfHeaders);\r
1801     goto Finish;\r
1802   }\r
1803 \r
1804   //\r
1805   // Zero Debug Information of Pe Image\r
1806   //\r
1807   if (OutImageType == FW_ZERO_DEBUG_IMAGE) {\r
1808     Status = ZeroDebugData (FileBuffer);\r
1809     if (EFI_ERROR (Status)) {\r
1810       Error (NULL, 0, 3000, "Invalid", "Zero DebugData Error status is 0x%lx", (UINTN) Status);\r
1811       goto Finish;\r
1812     }\r
1813     \r
1814     if (fpOut != NULL) {\r
1815       fwrite (FileBuffer, 1, FileLength, fpOut);\r
1816     }\r
1817     if (fpInOut != NULL) {\r
1818       fwrite (FileBuffer, 1, FileLength, fpInOut);\r
1819     }\r
1820     VerboseMsg ("the size of output file is %d bytes", FileLength);\r
1821     goto Finish; \r
1822   }\r
1823 \r
1824   //\r
1825   // Set Time Stamp of Pe Image\r
1826   //\r
1827   if (OutImageType == FW_SET_STAMP_IMAGE) {\r
1828     Status = SetStamp (FileBuffer, TimeStamp);\r
1829     if (EFI_ERROR (Status)) {\r
1830       Error (NULL, 0, 3000, "Invalid", "SetStamp Error status is 0x%lx", (UINTN) Status);\r
1831       goto Finish;\r
1832     }\r
1833     \r
1834     if (fpOut != NULL) {\r
1835       fwrite (FileBuffer, 1, FileLength, fpOut);  \r
1836     }\r
1837     if (fpInOut != NULL) {\r
1838       fwrite (FileBuffer, 1, FileLength, fpInOut);\r
1839     }\r
1840     VerboseMsg ("the size of output file is %d bytes", FileLength);\r
1841     goto Finish;\r
1842   }\r
1843 \r
1844   //\r
1845   // Extract acpi data from pe image.\r
1846   //\r
1847   if (OutImageType == FW_ACPI_IMAGE) {\r
1848     SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->OptionalHeader) + PeHdr->FileHeader.SizeOfOptionalHeader); \r
1849     for (Index = 0; Index < PeHdr->FileHeader.NumberOfSections; Index ++, SectionHeader ++) {\r
1850       if (strcmp (SectionHeader->Name, ".data") == 0 || strcmp (SectionHeader->Name, ".sdata") == 0) {\r
1851         //\r
1852         // Check Acpi Table\r
1853         //\r
1854         if (SectionHeader->Misc.VirtualSize < SectionHeader->SizeOfRawData) {\r
1855           FileLength = SectionHeader->Misc.VirtualSize;\r
1856         } else {\r
1857           FileLength = SectionHeader->SizeOfRawData;\r
1858         }\r
1859 \r
1860         if (CheckAcpiTable (FileBuffer + SectionHeader->PointerToRawData, FileLength) != STATUS_SUCCESS) {\r
1861           Error (NULL, 0, 3000, "Invalid", "ACPI table check failed in %s.", mInImageName);\r
1862           goto Finish;\r
1863         }\r
1864         \r
1865         //\r
1866         // Output Apci data to file\r
1867         //\r
1868         if (fpOut != NULL) {\r
1869           fwrite (FileBuffer + SectionHeader->PointerToRawData, 1, FileLength, fpOut);\r
1870         }\r
1871         if (fpInOut != NULL) {\r
1872           fwrite (FileBuffer + SectionHeader->PointerToRawData, 1, FileLength, fpInOut);\r
1873         }\r
1874         VerboseMsg ("the size of output file is %d bytes", FileLength);\r
1875         goto Finish;\r
1876       }\r
1877     }\r
1878     Error (NULL, 0, 3000, "Invalid", "failed to get ACPI table from %s.", mInImageName);\r
1879     goto Finish;\r
1880   }\r
1881   //\r
1882   // Zero all unused fields of the DOS header\r
1883   //\r
1884   memcpy (&BackupDosHdr, DosHdr, sizeof (EFI_IMAGE_DOS_HEADER));\r
1885   memset (DosHdr, 0, sizeof (EFI_IMAGE_DOS_HEADER));\r
1886   DosHdr->e_magic  = BackupDosHdr.e_magic;\r
1887   DosHdr->e_lfanew = BackupDosHdr.e_lfanew;\r
1888 \r
1889   for (Index = sizeof (EFI_IMAGE_DOS_HEADER); Index < (UINT32 ) DosHdr->e_lfanew; Index++) {\r
1890     FileBuffer[Index] = DosHdr->e_cp;\r
1891   }\r
1892   \r
1893   //\r
1894   // Initialize TeImage Header\r
1895   //\r
1896   memset (&TEImageHeader, 0, sizeof (EFI_TE_IMAGE_HEADER));\r
1897   TEImageHeader.Signature        = EFI_TE_IMAGE_HEADER_SIGNATURE;\r
1898   TEImageHeader.Machine          = PeHdr->FileHeader.Machine;\r
1899   TEImageHeader.NumberOfSections = (UINT8) PeHdr->FileHeader.NumberOfSections;\r
1900   TEImageHeader.StrippedSize     = (UINT16) ((UINTN) ((UINT8 *) &(PeHdr->OptionalHeader) + PeHdr->FileHeader.SizeOfOptionalHeader) - (UINTN) FileBuffer);\r
1901   TEImageHeader.Subsystem        = (UINT8) Type;\r
1902 \r
1903   //\r
1904   // Patch the PE header\r
1905   //\r
1906   PeHdr->OptionalHeader.Subsystem = (UINT16) Type;\r
1907 \r
1908   if (PeHdr->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
1909     Optional32 = (EFI_IMAGE_OPTIONAL_HEADER32 *)&PeHdr->OptionalHeader;\r
1910     Optional32->MajorLinkerVersion          = 0;\r
1911     Optional32->MinorLinkerVersion          = 0;\r
1912     Optional32->MajorOperatingSystemVersion = 0;\r
1913     Optional32->MinorOperatingSystemVersion = 0;\r
1914     Optional32->MajorImageVersion           = 0;\r
1915     Optional32->MinorImageVersion           = 0;\r
1916     Optional32->MajorSubsystemVersion       = 0;\r
1917     Optional32->MinorSubsystemVersion       = 0;\r
1918     Optional32->Win32VersionValue           = 0;\r
1919     Optional32->CheckSum                    = 0;\r
1920     Optional32->SizeOfStackReserve = 0;\r
1921     Optional32->SizeOfStackCommit  = 0;\r
1922     Optional32->SizeOfHeapReserve  = 0;\r
1923     Optional32->SizeOfHeapCommit   = 0;\r
1924     \r
1925     TEImageHeader.AddressOfEntryPoint = Optional32->AddressOfEntryPoint;\r
1926     TEImageHeader.BaseOfCode          = Optional32->BaseOfCode;\r
1927     TEImageHeader.ImageBase           = (UINT64) (Optional32->ImageBase);\r
1928 \r
1929     if (Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {\r
1930       TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;\r
1931       TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;\r
1932     }\r
1933 \r
1934     if (Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {\r
1935       TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;\r
1936       TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size;\r
1937     }\r
1938 \r
1939     //\r
1940     // Zero .pdata section data.\r
1941     //\r
1942     if (!KeepExceptionTableFlag && Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION &&\r
1943         Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress != 0 && \r
1944         Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size != 0) {\r
1945       SectionHeader = (EFI_IMAGE_SECTION_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof(UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + PeHdr->FileHeader.SizeOfOptionalHeader);\r
1946       for (Index = 0; Index < PeHdr->FileHeader.NumberOfSections; Index++, SectionHeader++) {\r
1947         if (SectionHeader->VirtualAddress == Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress) {\r
1948           //\r
1949           // Zero .pdata Section data\r
1950           //\r
1951           memset (FileBuffer + SectionHeader->PointerToRawData, 0, SectionHeader->SizeOfRawData);\r
1952           //\r
1953           // Zero .pdata Section header name\r
1954           //\r
1955           memset (SectionHeader->Name, 0, sizeof (SectionHeader->Name));\r
1956           //\r
1957           // Zero Execption Table\r
1958           //\r
1959           Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress = 0;\r
1960           Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size           = 0;\r
1961           DebugMsg (NULL, 0, 9, "Zero the .pdata section for PE image", NULL);\r
1962           break;\r
1963         }\r
1964       }\r
1965     }\r
1966 \r
1967     //\r
1968     // Strip zero padding at the end of the .reloc section \r
1969     //\r
1970     if (!KeepZeroPendingFlag && Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {\r
1971       if (Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size != 0) {\r
1972         SectionHeader = (EFI_IMAGE_SECTION_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof(UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + PeHdr->FileHeader.SizeOfOptionalHeader);\r
1973         for (Index = 0; Index < PeHdr->FileHeader.NumberOfSections; Index++, SectionHeader++) {\r
1974           //\r
1975           // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory\r
1976           //\r
1977           if (SectionHeader->VirtualAddress == Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress) {\r
1978             SectionHeader->Misc.VirtualSize = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;\r
1979             AllignedRelocSize = (Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size + Optional32->FileAlignment - 1) & (~(Optional32->FileAlignment - 1));\r
1980             //\r
1981             // Check to see if there is zero padding at the end of the base relocations\r
1982             //\r
1983             if (AllignedRelocSize < SectionHeader->SizeOfRawData) {\r
1984               //\r
1985               // Check to see if the base relocations are at the end of the file\r
1986               //\r
1987               if (SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData == Optional32->SizeOfImage) {\r
1988                 //\r
1989                 // All the required conditions are met to strip the zero padding of the end of the base relocations section\r
1990                 //\r
1991                 Optional32->SizeOfImage -= (SectionHeader->SizeOfRawData - AllignedRelocSize);\r
1992                 Optional32->SizeOfInitializedData -= (SectionHeader->SizeOfRawData - AllignedRelocSize);\r
1993                 SectionHeader->SizeOfRawData = AllignedRelocSize;\r
1994                 FileLength = Optional32->SizeOfImage;\r
1995                 DebugMsg (NULL, 0, 9, "Remove the zero padding bytes at the end of the base relocations", "The size of padding bytes is %d", SectionHeader->SizeOfRawData - AllignedRelocSize);\r
1996               }\r
1997             }\r
1998           }\r
1999         }\r
2000       }\r
2001     }\r
2002   } else if (PeHdr->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
2003     Optional64 = (EFI_IMAGE_OPTIONAL_HEADER64 *)&PeHdr->OptionalHeader;\r
2004     Optional64->MajorLinkerVersion          = 0;\r
2005     Optional64->MinorLinkerVersion          = 0;\r
2006     Optional64->MajorOperatingSystemVersion = 0;\r
2007     Optional64->MinorOperatingSystemVersion = 0;\r
2008     Optional64->MajorImageVersion           = 0;\r
2009     Optional64->MinorImageVersion           = 0;\r
2010     Optional64->MajorSubsystemVersion       = 0;\r
2011     Optional64->MinorSubsystemVersion       = 0;\r
2012     Optional64->Win32VersionValue           = 0;\r
2013     Optional64->CheckSum                    = 0;\r
2014     Optional64->SizeOfStackReserve = 0;\r
2015     Optional64->SizeOfStackCommit  = 0;\r
2016     Optional64->SizeOfHeapReserve  = 0;\r
2017     Optional64->SizeOfHeapCommit   = 0;\r
2018 \r
2019     TEImageHeader.AddressOfEntryPoint = Optional64->AddressOfEntryPoint;\r
2020     TEImageHeader.BaseOfCode          = Optional64->BaseOfCode;\r
2021     TEImageHeader.ImageBase           = (UINT64) (Optional64->ImageBase);\r
2022 \r
2023     if (Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {\r
2024       TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;\r
2025       TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;\r
2026     }\r
2027 \r
2028     if (Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {\r
2029       TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;\r
2030       TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size;\r
2031     }\r
2032 \r
2033     //\r
2034     // Zero the .pdata section for X64 machine and don't check the Debug Directory is empty\r
2035     // For Itaninum and X64 Image, remove .pdata section.\r
2036     //\r
2037     if (!KeepExceptionTableFlag && PeHdr->FileHeader.Machine == IMAGE_FILE_MACHINE_X64 || PeHdr->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64) {\r
2038       if (Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION &&\r
2039           Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress != 0 && \r
2040           Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size != 0) {\r
2041         //if (Optional64->NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_DEBUG || (Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG && Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size == 0)) {\r
2042         SectionHeader = (EFI_IMAGE_SECTION_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof(UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + PeHdr->FileHeader.SizeOfOptionalHeader);\r
2043         for (Index = 0; Index < PeHdr->FileHeader.NumberOfSections; Index++, SectionHeader++) {\r
2044           if (SectionHeader->VirtualAddress == Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress) {\r
2045             //\r
2046             // Zero .pdata Section header name\r
2047             //\r
2048             memset (SectionHeader->Name, 0, sizeof (SectionHeader->Name));\r
2049 \r
2050             RuntimeFunction = (RUNTIME_FUNCTION *)(FileBuffer + SectionHeader->PointerToRawData);\r
2051             for (Index1 = 0; Index1 < Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size / sizeof (RUNTIME_FUNCTION); Index1++, RuntimeFunction++) {\r
2052               SectionHeader = (EFI_IMAGE_SECTION_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof(UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + PeHdr->FileHeader.SizeOfOptionalHeader);\r
2053               for (Index2 = 0; Index2 < PeHdr->FileHeader.NumberOfSections; Index2++, SectionHeader++) {\r
2054                 if (RuntimeFunction->UnwindInfoAddress > SectionHeader->VirtualAddress && RuntimeFunction->UnwindInfoAddress < (SectionHeader->VirtualAddress + SectionHeader->SizeOfRawData)) {\r
2055                   UnwindInfo = (UNWIND_INFO *)(FileBuffer + SectionHeader->PointerToRawData + (RuntimeFunction->UnwindInfoAddress - SectionHeader->VirtualAddress));\r
2056                   if (UnwindInfo->Version == 1) {\r
2057                     memset (UnwindInfo + 1, 0, UnwindInfo->CountOfUnwindCodes * sizeof (UINT16));\r
2058                     memset (UnwindInfo, 0, sizeof (UNWIND_INFO));\r
2059                   }\r
2060                 }\r
2061               }\r
2062               memset (RuntimeFunction, 0, sizeof (RUNTIME_FUNCTION));\r
2063             }\r
2064             //\r
2065             // Zero Execption Table\r
2066             //\r
2067             Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size = 0;\r
2068             Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress = 0;\r
2069             DebugMsg (NULL, 0, 9, "Zero the .pdata section if the machine type is X64 for PE32+ image", NULL);\r
2070             break;\r
2071           }\r
2072         }\r
2073       }\r
2074     }\r
2075 \r
2076     //\r
2077     // Strip zero padding at the end of the .reloc section \r
2078     //\r
2079     if (!KeepZeroPendingFlag && Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {\r
2080       if (Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size != 0) {\r
2081         SectionHeader = (EFI_IMAGE_SECTION_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof(UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + PeHdr->FileHeader.SizeOfOptionalHeader);\r
2082         for (Index = 0; Index < PeHdr->FileHeader.NumberOfSections; Index++, SectionHeader++) {\r
2083           //\r
2084           // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory\r
2085           //\r
2086           if (SectionHeader->VirtualAddress == Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress) {\r
2087             SectionHeader->Misc.VirtualSize = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;\r
2088             AllignedRelocSize = (Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size + Optional64->FileAlignment - 1) & (~(Optional64->FileAlignment - 1));\r
2089             //\r
2090             // Check to see if there is zero padding at the end of the base relocations\r
2091             //\r
2092             if (AllignedRelocSize < SectionHeader->SizeOfRawData) {\r
2093               //\r
2094               // Check to see if the base relocations are at the end of the file\r
2095               //\r
2096               if (SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData == Optional64->SizeOfImage) {\r
2097                 //\r
2098                 // All the required conditions are met to strip the zero padding of the end of the base relocations section\r
2099                 //\r
2100                 Optional64->SizeOfImage -= (SectionHeader->SizeOfRawData - AllignedRelocSize);\r
2101                 Optional64->SizeOfInitializedData -= (SectionHeader->SizeOfRawData - AllignedRelocSize);\r
2102                 SectionHeader->SizeOfRawData = AllignedRelocSize;\r
2103                 FileLength = Optional64->SizeOfImage;\r
2104                 DebugMsg (NULL, 0, 9, "Remove the zero padding bytes at the end of the base relocations", "The size of padding bytes is %d", SectionHeader->SizeOfRawData - AllignedRelocSize);\r
2105               }\r
2106             }\r
2107           }\r
2108         }\r
2109       }\r
2110     }\r
2111   } else {\r
2112     Error (NULL, 0, 3000, "Invalid", "Magic 0x%x of PeImage %s is unknown.", PeHdr->OptionalHeader.Magic, mInImageName);\r
2113     goto Finish;\r
2114   }\r
2115 \r
2116   if (OutImageType == FW_TE_IMAGE) {\r
2117     if ((PeHdr->FileHeader.NumberOfSections &~0xFF) || (Type &~0xFF)) {\r
2118       //\r
2119       // Pack the subsystem and NumberOfSections into 1 byte. Make sure they fit both.\r
2120       //\r
2121       Error (NULL, 0, 3000, "Invalid", "Image's subsystem or NumberOfSections of PeImage %s cannot be packed into 1 byte.", mInImageName);\r
2122       goto Finish;\r
2123     }\r
2124 \r
2125     if ((PeHdr->OptionalHeader.SectionAlignment != PeHdr->OptionalHeader.FileAlignment)) {\r
2126       //\r
2127       // TeImage has the same section alignment and file alignment.\r
2128       //\r
2129       Error (NULL, 0, 3000, "Invalid", "Section-Alignment and File-Alignment of PeImage %s do not match, they must be equal for a TeImage.", mInImageName);\r
2130       goto Finish;\r
2131     }\r
2132     \r
2133     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 %X", \r
2134               TEImageHeader.Machine, TEImageHeader.NumberOfSections, TEImageHeader.StrippedSize, TEImageHeader.AddressOfEntryPoint, TEImageHeader.BaseOfCode, TEImageHeader.ImageBase);\r
2135     //\r
2136     // Update Image to TeImage\r
2137     //\r
2138     if (fpOut != NULL) {\r
2139       fwrite (&TEImageHeader, 1, sizeof (EFI_TE_IMAGE_HEADER), fpOut);\r
2140       fwrite (FileBuffer + TEImageHeader.StrippedSize, 1, FileLength - TEImageHeader.StrippedSize, fpOut);\r
2141     }\r
2142     if (fpInOut != NULL) {\r
2143       fwrite (&TEImageHeader, 1, sizeof (EFI_TE_IMAGE_HEADER), fpInOut);\r
2144       fwrite (FileBuffer + TEImageHeader.StrippedSize, 1, FileLength - TEImageHeader.StrippedSize, fpInOut);\r
2145     }\r
2146     VerboseMsg ("the size of output file is %d bytes", FileLength - TEImageHeader.StrippedSize);\r
2147     goto Finish;\r
2148   }\r
2149 WriteFile:\r
2150   //\r
2151   // Update Image to EfiImage\r
2152   //\r
2153   if (fpOut != NULL) {\r
2154     fwrite (FileBuffer, 1, FileLength, fpOut);\r
2155   }\r
2156   if (fpInOut != NULL) {\r
2157     fwrite (FileBuffer, 1, FileLength, fpInOut);\r
2158   }\r
2159   VerboseMsg ("the size of output file is %d bytes", FileLength);\r
2160 \r
2161 Finish:\r
2162   if (fpInOut != NULL) {\r
2163     if (GetUtilityStatus () != STATUS_SUCCESS) {\r
2164       //\r
2165       // when file updates failed, original file is still recoveried.\r
2166       //\r
2167       fwrite (FileBuffer, 1, FileLength, fpInOut);\r
2168     }\r
2169     //\r
2170     // Write converted data into fpInOut file and close input file.\r
2171     //\r
2172     fclose (fpInOut);\r
2173   }\r
2174 \r
2175   if (FileBuffer != NULL) {\r
2176     free (FileBuffer);\r
2177   }\r
2178   \r
2179   if (InputFileName != NULL) {\r
2180     free (InputFileName);\r
2181   }\r
2182 \r
2183   if (fpOut != NULL) {\r
2184     //\r
2185     // Write converted data into fpOut file and close output file.\r
2186     //\r
2187     fclose (fpOut);\r
2188   }\r
2189  \r
2190   VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME, GetUtilityStatus ());\r
2191   \r
2192   return GetUtilityStatus ();\r
2193 }\r
2194 \r
2195 STATIC\r
2196 EFI_STATUS\r
2197 ZeroDebugData (\r
2198   IN OUT UINT8   *FileBuffer\r
2199   )\r
2200 /*++\r
2201 \r
2202 Routine Description:\r
2203 \r
2204   Zero debug information in PeImage.\r
2205 \r
2206 Arguments:\r
2207 \r
2208   FileBuffer    - Pointer to PeImage.\r
2209 \r
2210 Returns:\r
2211 \r
2212   EFI_ABORTED   - PeImage is invalid.\r
2213   EFI_SUCCESS   - Zero debug data successfully.\r
2214 \r
2215 --*/\r
2216 {\r
2217   UINTN                           Index;\r
2218   UINTN                           DebugDirectoryEntryRva;\r
2219   UINTN                           DebugDirectoryEntryFileOffset;\r
2220   EFI_IMAGE_DOS_HEADER            *DosHdr;\r
2221   EFI_IMAGE_FILE_HEADER           *FileHdr;\r
2222   EFI_IMAGE_OPTIONAL_HEADER32     *Optional32Hdr;\r
2223   EFI_IMAGE_OPTIONAL_HEADER64     *Optional64Hdr;\r
2224   EFI_IMAGE_SECTION_HEADER        *SectionHeader;\r
2225   EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *DebugEntry;\r
2226    \r
2227   DosHdr   = (EFI_IMAGE_DOS_HEADER *)  FileBuffer;\r
2228   FileHdr  = (EFI_IMAGE_FILE_HEADER *) (FileBuffer + DosHdr->e_lfanew + sizeof (UINT32));\r
2229   DebugDirectoryEntryRva = 0;\r
2230 \r
2231   //\r
2232   // Get DebugEntryTable RVA address.\r
2233   //\r
2234   if (FileHdr->Machine == EFI_IMAGE_MACHINE_IA32) {\r
2235     Optional32Hdr = (EFI_IMAGE_OPTIONAL_HEADER32 *) ((UINT8*) FileHdr + sizeof (EFI_IMAGE_FILE_HEADER));\r
2236     SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) Optional32Hdr +  FileHdr->SizeOfOptionalHeader);\r
2237     if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG && \\r
2238         Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) {\r
2239       DebugDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;\r
2240     } else {\r
2241       //\r
2242       // No Debug Data, nothing to do.\r
2243       //\r
2244       return EFI_SUCCESS;\r
2245     }\r
2246   } else {\r
2247     Optional64Hdr = (EFI_IMAGE_OPTIONAL_HEADER64 *) ((UINT8*) FileHdr + sizeof (EFI_IMAGE_FILE_HEADER));\r
2248     SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) Optional64Hdr +  FileHdr->SizeOfOptionalHeader);\r
2249     if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG && \\r
2250         Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) {\r
2251       DebugDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;\r
2252     } else {\r
2253       //\r
2254       // No Debug Data, nothing to do.\r
2255       //\r
2256       return EFI_SUCCESS;\r
2257     }\r
2258   }\r
2259   \r
2260   //\r
2261   // Get DebugEntryTable file offset.\r
2262   //\r
2263   for (Index = 0; Index < FileHdr->NumberOfSections; Index ++, SectionHeader ++) {\r
2264     if (DebugDirectoryEntryRva >= SectionHeader->VirtualAddress &&\r
2265         DebugDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) {\r
2266         DebugDirectoryEntryFileOffset =\r
2267         DebugDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData;\r
2268       break;\r
2269     }\r
2270   }\r
2271   \r
2272   if (Index >= FileHdr->NumberOfSections) {\r
2273     Error (NULL, 0, 3000, "Invalid", "PeImage");\r
2274     return EFI_ABORTED;\r
2275   }\r
2276   \r
2277   //\r
2278   // Zero Debug Data and TimeStamp\r
2279   //\r
2280   DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) (FileBuffer + DebugDirectoryEntryFileOffset);\r
2281   DebugEntry->TimeDateStamp = 0;\r
2282   memset (FileBuffer + DebugEntry->FileOffset, 0, DebugEntry->SizeOfData);\r
2283   \r
2284   return EFI_SUCCESS;\r
2285 }\r
2286 \r
2287 STATIC \r
2288 EFI_STATUS\r
2289 SetStamp (\r
2290   IN OUT UINT8  *FileBuffer, \r
2291   IN     CHAR8  *TimeStamp\r
2292   )\r
2293 /*++\r
2294 \r
2295 Routine Description:\r
2296 \r
2297   Set new time stamp into PeImage FileHdr and Directory table: \r
2298   Debug, Export and Resource.\r
2299 \r
2300 Arguments:\r
2301 \r
2302   FileBuffer    - Pointer to PeImage.\r
2303   TimeStamp     - Time stamp string.\r
2304 \r
2305 Returns:\r
2306 \r
2307   EFI_INVALID_PARAMETER   - TimeStamp format is not recognized.\r
2308   EFI_SUCCESS             - Set new time stamp in this image successfully.\r
2309 \r
2310 --*/\r
2311 {\r
2312   struct tm                       stime;\r
2313   struct tm                       *ptime;\r
2314   time_t                          newtime;\r
2315   UINTN                           Index;\r
2316   UINTN                           DebugDirectoryEntryRva;\r
2317   UINTN                           DebugDirectoryEntryFileOffset;\r
2318   UINTN                           ExportDirectoryEntryRva;\r
2319   UINTN                           ExportDirectoryEntryFileOffset;\r
2320   UINTN                           ResourceDirectoryEntryRva;\r
2321   UINTN                           ResourceDirectoryEntryFileOffset;\r
2322   EFI_IMAGE_DOS_HEADER            *DosHdr;\r
2323   EFI_IMAGE_FILE_HEADER           *FileHdr;\r
2324   EFI_IMAGE_OPTIONAL_HEADER32     *Optional32Hdr;\r
2325   EFI_IMAGE_OPTIONAL_HEADER64     *Optional64Hdr;\r
2326   EFI_IMAGE_SECTION_HEADER        *SectionHeader;\r
2327   UINT32                          *NewTimeStamp;\r
2328   \r
2329   //\r
2330   // Init variable.\r
2331   //  \r
2332   DebugDirectoryEntryRva    = 0;\r
2333   ExportDirectoryEntryRva   = 0;\r
2334   ResourceDirectoryEntryRva = 0;\r
2335 \r
2336   //\r
2337   // Get time and date that will be set.\r
2338   //\r
2339   if (TimeStamp == NULL) {\r
2340     Error (NULL, 0, 3000, "Invalid", "TimeStamp cannot be NULL.");\r
2341     return EFI_INVALID_PARAMETER;\r
2342   }\r
2343   //\r
2344   // compare the value with "NOW", if yes, current system time is set.\r
2345   //\r
2346   if (stricmp (TimeStamp, "NOW") == 0) {\r
2347     //\r
2348     // get system current time and date\r
2349     //\r
2350     time (&newtime);\r
2351   } else {\r
2352     //\r
2353     // get the date and time from TimeStamp\r
2354     //\r
2355     if (sscanf (TimeStamp, "%d-%d-%d %d:%d:%d",\r
2356             &stime.tm_year,\r
2357             &stime.tm_mon,\r
2358             &stime.tm_mday,\r
2359             &stime.tm_hour,\r
2360             &stime.tm_min,\r
2361             &stime.tm_sec\r
2362             ) != 6) {\r
2363       Error (NULL, 0, 3000, "Invalid", "%s Invalid or unsupported datetime!", TimeStamp);\r
2364       return EFI_INVALID_PARAMETER;\r
2365     }\r
2366 \r
2367     //\r
2368     // in struct, Month (0 - 11; Jan = 0). So decrease 1 from it\r
2369     //\r
2370     if (stime.tm_mon <= 0 || stime.tm_mday <=0) {\r
2371       Error (NULL, 0, 3000, "Invalid", "%s Invalid date!", TimeStamp);\r
2372       return EFI_INVALID_PARAMETER;      \r
2373     }\r
2374     stime.tm_mon -= 1;\r
2375   \r
2376     //\r
2377     // in struct, Year (current year minus 1900)\r
2378     // and only the dates can be handled from Jan 1, 1970 to Jan 18, 2038\r
2379     //\r
2380     //\r
2381     // convert 0 -> 100 (2000), 1 -> 101 (2001), ..., 38 -> 138 (2038)\r
2382     //\r
2383     if (stime.tm_year >= 1970 && stime.tm_year <= 2038) {\r
2384       //\r
2385       // convert 1970 -> 70, 2000 -> 100, ...\r
2386       //\r
2387       stime.tm_year -= 1900;\r
2388     } else {\r
2389       Error (NULL, 0, 3000, "Invalid", "%s Invalid or unsupported datetime!", TimeStamp);\r
2390       return EFI_INVALID_PARAMETER;\r
2391     }\r
2392 \r
2393     //\r
2394     // convert the date and time to time_t format\r
2395     //\r
2396     newtime = mktime (&stime);\r
2397     if (newtime == (time_t) - 1) {\r
2398       Error (NULL, 0, 3000, "Invalid", "%s Invalid or unsupported datetime!", TimeStamp);\r
2399       return EFI_INVALID_PARAMETER;\r
2400     }\r
2401   }\r
2402   \r
2403   ptime = localtime (&newtime);\r
2404   DebugMsg (NULL, 0, 9, "New Image Time Stamp", "%04d-%02d-%02d %02d:%02d:%02d",\r
2405             ptime->tm_year + 1900, ptime->tm_mon + 1, ptime->tm_mday, ptime->tm_hour, ptime->tm_min, ptime->tm_sec); \r
2406   //\r
2407   // Set new time and data into PeImage.\r
2408   //\r
2409   DosHdr   = (EFI_IMAGE_DOS_HEADER *)  FileBuffer;\r
2410   FileHdr  = (EFI_IMAGE_FILE_HEADER *) (FileBuffer + DosHdr->e_lfanew + sizeof (UINT32));\r
2411   \r
2412   //\r
2413   // Get Debug, Export and Resource EntryTable RVA address.\r
2414   // Resource Directory entry need to review.\r
2415   //\r
2416   if (FileHdr->Machine == EFI_IMAGE_MACHINE_IA32) {\r
2417     Optional32Hdr = (EFI_IMAGE_OPTIONAL_HEADER32 *) ((UINT8*) FileHdr + sizeof (EFI_IMAGE_FILE_HEADER));\r
2418     SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) Optional32Hdr +  FileHdr->SizeOfOptionalHeader);\r
2419     if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXPORT && \\r
2420         Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].Size != 0) {\r
2421       ExportDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;\r
2422     }\r
2423     if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE && \\r
2424         Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size != 0) {\r
2425       ResourceDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;\r
2426     }\r
2427     if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG && \\r
2428         Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) {\r
2429       DebugDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;\r
2430     }\r
2431   } else {\r
2432     Optional64Hdr = (EFI_IMAGE_OPTIONAL_HEADER64 *) ((UINT8*) FileHdr + sizeof (EFI_IMAGE_FILE_HEADER));\r
2433     SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) Optional64Hdr +  FileHdr->SizeOfOptionalHeader);\r
2434     if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXPORT && \\r
2435         Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].Size != 0) {\r
2436       ExportDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;\r
2437     }\r
2438     if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE && \\r
2439         Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size != 0) {\r
2440       ResourceDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;\r
2441     }\r
2442     if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG && \\r
2443         Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) {\r
2444       DebugDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;\r
2445     }\r
2446   }\r
2447 \r
2448   //\r
2449   // Get DirectoryEntryTable file offset.\r
2450   //\r
2451   for (Index = 0; Index < FileHdr->NumberOfSections; Index ++, SectionHeader ++) {\r
2452     if (DebugDirectoryEntryRva >= SectionHeader->VirtualAddress &&\r
2453         DebugDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) {\r
2454         DebugDirectoryEntryFileOffset =\r
2455         DebugDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData;\r
2456     }\r
2457     if (ExportDirectoryEntryRva >= SectionHeader->VirtualAddress &&\r
2458         ExportDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) {\r
2459         ExportDirectoryEntryFileOffset =\r
2460         ExportDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData;\r
2461     }\r
2462     if (ResourceDirectoryEntryRva >= SectionHeader->VirtualAddress &&\r
2463         ResourceDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) {\r
2464         ResourceDirectoryEntryFileOffset =\r
2465         ResourceDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData;\r
2466     }\r
2467   }\r
2468   \r
2469   //\r
2470   // Set new stamp\r
2471   //\r
2472   FileHdr->TimeDateStamp = (UINT32) newtime;\r
2473 \r
2474   if (ExportDirectoryEntryRva != 0) {\r
2475     NewTimeStamp  = (UINT32 *) (FileBuffer + ExportDirectoryEntryFileOffset + sizeof (UINT32));\r
2476     *NewTimeStamp = (UINT32) newtime;\r
2477   }\r
2478 \r
2479   if (ResourceDirectoryEntryRva != 0) {\r
2480     NewTimeStamp  = (UINT32 *) (FileBuffer + ResourceDirectoryEntryFileOffset + sizeof (UINT32));\r
2481     *NewTimeStamp = (UINT32) newtime;\r
2482   }\r
2483 \r
2484   if (DebugDirectoryEntryRva != 0) {\r
2485     NewTimeStamp  = (UINT32 *) (FileBuffer + DebugDirectoryEntryFileOffset + sizeof (UINT32));\r
2486     *NewTimeStamp = (UINT32) newtime;\r
2487   }\r
2488   \r
2489   return EFI_SUCCESS;\r
2490 }\r
2491 \r
2492 STATIC\r
2493 STATUS\r
2494 MicrocodeReadData (\r
2495   FILE          *InFptr,\r
2496   UINTN         *Data\r
2497   )\r
2498 /*++\r
2499 \r
2500 Routine Description:\r
2501   Read a 32-bit microcode data value from a text file and convert to raw binary form.\r
2502 \r
2503 Arguments:\r
2504   InFptr    - file pointer to input text file\r
2505   Data      - pointer to where to return the data parsed\r
2506 \r
2507 Returns:\r
2508   STATUS_SUCCESS    - no errors or warnings, Data contains valid information\r
2509   STATUS_ERROR      - errors were encountered\r
2510 \r
2511 --*/\r
2512 {\r
2513   CHAR8  Line[MAX_LINE_LEN];\r
2514   CHAR8  *cptr;\r
2515   UINT8  ctr;\r
2516 \r
2517   Line[MAX_LINE_LEN - 1]  = 0;\r
2518   while (1) {\r
2519     if (fgets (Line, MAX_LINE_LEN, InFptr) == NULL) {\r
2520       return STATUS_ERROR;\r
2521     }\r
2522     //\r
2523     // If it was a binary file, then it may have overwritten our null terminator\r
2524     //\r
2525     if (Line[MAX_LINE_LEN - 1] != 0) {\r
2526       return STATUS_ERROR;\r
2527     }\r
2528     \r
2529     //\r
2530     // strip space\r
2531     // \r
2532     for (cptr = Line; *cptr && isspace(*cptr); cptr++) {\r
2533     }\r
2534     \r
2535     // Skip Blank Lines and Comment Lines\r
2536     if ((strlen(cptr) != 0) && (*cptr != ';')) {\r
2537       break;\r
2538     }\r
2539   }\r
2540 \r
2541   // Look for\r
2542   // dd 000000001h ; comment\r
2543   // dd XXXXXXXX\r
2544   // DD  XXXXXXXXX\r
2545   //  DD XXXXXXXXX\r
2546   //\r
2547   if ((tolower(cptr[0]) == 'd') && (tolower(cptr[1]) == 'd') && isspace (cptr[2])) {\r
2548     //\r
2549     // Skip blanks and look for a hex digit\r
2550     //\r
2551     cptr += 3;\r
2552     for (; *cptr && isspace(*cptr); cptr++) {\r
2553     }\r
2554     if (isxdigit (*cptr)) {\r
2555       if (sscanf (cptr, "%X", Data) != 1) {\r
2556         return STATUS_ERROR;\r
2557       }\r
2558     }\r
2559     return STATUS_SUCCESS;\r
2560   }\r
2561 \r
2562   return STATUS_ERROR;\r
2563 }\r