Add more usage description for -r option in order to avoid confuse.
[people/mcb30/basetools.git] / Source / C / GenFw / GenFw.c
1 /*++\r
2 \r
3 Copyright (c) 2004 - 2007, 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 image type\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)\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   Error (NULL, 0, 3000, "Invalid", "%s unhandled section type %x.", mInImageName, (UINTN)Shdr->sh_type);\r
701       }\r
702     }\r
703   }\r
704 \r
705   //\r
706   // Second: apply relocations.\r
707   //\r
708   for (Idx = 0; Idx < Ehdr->e_shnum; Idx++) {\r
709     Elf_Shdr *RelShdr = GetShdrByIndex(Idx);\r
710     if (RelShdr->sh_type != SHT_REL)\r
711       continue;\r
712     Elf_Shdr *SecShdr = GetShdrByIndex(RelShdr->sh_info);\r
713     UINT32 SecOffset = CoffSectionsOffset[RelShdr->sh_info];\r
714     if (RelShdr->sh_type == SHT_REL && (*Filter)(SecShdr)) {\r
715       UINT32 RelIdx;\r
716       Elf_Shdr *SymtabShdr = GetShdrByIndex(RelShdr->sh_link);\r
717       UINT8 *Symtab = (UINT8*)Ehdr + SymtabShdr->sh_offset;\r
718 \r
719       for (RelIdx = 0; RelIdx < RelShdr->sh_size; RelIdx += RelShdr->sh_entsize) {\r
720   Elf_Rel *Rel = (Elf_Rel *)((UINT8*)Ehdr + RelShdr->sh_offset + RelIdx);\r
721   Elf_Sym *Sym = (Elf_Sym *)\r
722     (Symtab + ELF_R_SYM(Rel->r_info) * SymtabShdr->sh_entsize);\r
723   Elf_Shdr *SymShdr;\r
724   UINT8 *Targ;\r
725 \r
726   if (Sym->st_shndx == SHN_UNDEF\r
727       || Sym->st_shndx == SHN_ABS\r
728       || Sym->st_shndx > Ehdr->e_shnum) {\r
729     Error (NULL, 0, 3000, "Invalid", "%s bad symbol definition.", mInImageName);\r
730   }\r
731   SymShdr = GetShdrByIndex(Sym->st_shndx);\r
732 \r
733   //\r
734   // Note: r_offset in a memory address.\r
735   //  Convert it to a pointer in the coff file.\r
736   //\r
737   Targ = CoffFile + SecOffset + (Rel->r_offset - SecShdr->sh_addr);\r
738 \r
739   switch (ELF_R_TYPE(Rel->r_info)) {\r
740   case R_386_NONE:\r
741     break;\r
742   case R_386_32:\r
743     //\r
744     // Absolute relocation.\r
745     //\r
746     *(UINT32 *)Targ = *(UINT32 *)Targ - SymShdr->sh_addr\r
747       + CoffSectionsOffset[Sym->st_shndx];\r
748     break;\r
749   case R_386_PC32:\r
750     //\r
751     // Relative relocation: Symbol - Ip + Addend\r
752     //\r
753     *(UINT32 *)Targ = *(UINT32 *)Targ\r
754       + (CoffSectionsOffset[Sym->st_shndx] - SymShdr->sh_addr)\r
755       - (SecOffset - SecShdr->sh_addr);\r
756     break;\r
757   default:\r
758     Error (NULL, 0, 3000, "Invalid", "%s unhandled section type %x.", mInImageName, ELF_R_TYPE(Rel->r_info));\r
759   }\r
760       }\r
761     }\r
762   }\r
763 }\r
764 \r
765 VOID\r
766 CoffAddFixupEntry(\r
767   UINT16 Val\r
768   )\r
769 {\r
770   *CoffEntryRel = Val;\r
771   CoffEntryRel++;\r
772   CoffBaseRel->SizeOfBlock += 2;\r
773   CoffOffset += 2;\r
774 }\r
775 \r
776 VOID\r
777 CoffAddFixup(\r
778   UINT32 Offset,\r
779   UINT8  Type\r
780   )\r
781 {\r
782   if (CoffBaseRel == NULL\r
783       || CoffBaseRel->VirtualAddress != (Offset & ~0xfff)) {\r
784     if (CoffBaseRel != NULL) {\r
785       //\r
786       // Add a null entry (is it required ?)\r
787       //\r
788       CoffAddFixupEntry (0);\r
789       //\r
790       // Pad for alignment.\r
791       //\r
792       if (CoffOffset % 4 != 0)\r
793   CoffAddFixupEntry (0);\r
794     }\r
795       \r
796     CoffFile = realloc\r
797       (CoffFile,\r
798        CoffOffset + sizeof(EFI_IMAGE_BASE_RELOCATION) + 2*0x1000);\r
799     memset(CoffFile + CoffOffset, 0,\r
800      sizeof(EFI_IMAGE_BASE_RELOCATION) + 2*0x1000);\r
801 \r
802     CoffBaseRel = (EFI_IMAGE_BASE_RELOCATION*)(CoffFile + CoffOffset);\r
803     CoffBaseRel->VirtualAddress = Offset & ~0xfff;\r
804     CoffBaseRel->SizeOfBlock = sizeof(EFI_IMAGE_BASE_RELOCATION);\r
805 \r
806     CoffEntryRel = (UINT16 *)(CoffBaseRel + 1);\r
807     CoffOffset += sizeof(EFI_IMAGE_BASE_RELOCATION);\r
808   }\r
809 \r
810   //\r
811   // Fill the entry.\r
812   //\r
813   CoffAddFixupEntry((Type << 12) | (Offset & 0xfff));\r
814 }\r
815 \r
816 VOID\r
817 WriteRelocations(\r
818   VOID\r
819   )\r
820 {\r
821   UINT32 Idx;\r
822   EFI_IMAGE_NT_HEADERS *NtHdr;\r
823   EFI_IMAGE_DATA_DIRECTORY *Dir;\r
824 \r
825   for (Idx = 0; Idx < Ehdr->e_shnum; Idx++) {\r
826     Elf_Shdr *RelShdr = GetShdrByIndex(Idx);\r
827     if (RelShdr->sh_type == SHT_REL) {\r
828       Elf_Shdr *SecShdr = GetShdrByIndex(RelShdr->sh_info);\r
829       if (IsTextShdr(SecShdr) || IsDataShdr(SecShdr)) {\r
830   UINT32 RelIdx;\r
831   for (RelIdx = 0; RelIdx < RelShdr->sh_size; RelIdx += RelShdr->sh_entsize) {\r
832     Elf_Rel *Rel = (Elf_Rel *)\r
833       ((UINT8*)Ehdr + RelShdr->sh_offset + RelIdx);\r
834     switch (ELF_R_TYPE(Rel->r_info)) {\r
835     case R_386_NONE:\r
836     case R_386_PC32:\r
837       break;\r
838     case R_386_32:\r
839       CoffAddFixup(CoffSectionsOffset[RelShdr->sh_info]\r
840        + (Rel->r_offset - SecShdr->sh_addr),\r
841        EFI_IMAGE_REL_BASED_HIGHLOW);\r
842       break;\r
843     default:\r
844       Error (NULL, 0, 3000, "Invalid", "%s unhandled section type %x.", mInImageName, ELF_R_TYPE(Rel->r_info));\r
845     }\r
846   }\r
847       }\r
848     }\r
849   }\r
850 \r
851   //\r
852   // Pad by adding empty entries. \r
853   //\r
854   while (CoffOffset & (CoffAlignment - 1)) {\r
855     CoffAddFixupEntry(0);\r
856   }\r
857 \r
858   CreateSectionHeader (".reloc", RelocOffset, CoffOffset - RelocOffset,\r
859            EFI_IMAGE_SCN_CNT_INITIALIZED_DATA\r
860            | EFI_IMAGE_SCN_MEM_DISCARDABLE\r
861            | EFI_IMAGE_SCN_MEM_READ);\r
862 \r
863   NtHdr = (EFI_IMAGE_NT_HEADERS *)(CoffFile + NtHdrOffset);\r
864   Dir = &NtHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];\r
865   Dir->VirtualAddress = RelocOffset;\r
866   Dir->Size = CoffOffset - RelocOffset;\r
867 }\r
868 \r
869 VOID\r
870 WriteDebug(\r
871   VOID\r
872   )\r
873 {\r
874   UINT32 Len = strlen(mInImageName) + 1;\r
875   UINT32 DebugOffset = CoffOffset;\r
876   EFI_IMAGE_NT_HEADERS *NtHdr;\r
877   EFI_IMAGE_DATA_DIRECTORY *DataDir;\r
878   EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *Dir;\r
879   EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY *Nb10;\r
880 \r
881   CoffOffset += sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY)\r
882     + sizeof(EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY)\r
883     + Len;\r
884   CoffOffset = CoffAlign(CoffOffset);\r
885 \r
886   CoffFile = realloc\r
887     (CoffFile, CoffOffset);\r
888   memset(CoffFile + DebugOffset, 0, CoffOffset - DebugOffset);\r
889   \r
890   Dir = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY*)(CoffFile + DebugOffset);\r
891   Dir->Type = EFI_IMAGE_DEBUG_TYPE_CODEVIEW;\r
892   Dir->SizeOfData = sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY) + Len;\r
893   Dir->RVA = DebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);\r
894   Dir->FileOffset = DebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);\r
895   \r
896   Nb10 = (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY*)(Dir + 1);\r
897   Nb10->Signature = CODEVIEW_SIGNATURE_NB10;\r
898   strcpy ((UINT8 *)(Nb10 + 1), mInImageName);\r
899 \r
900   CreateSectionHeader (".debug", DebugOffset, CoffOffset - DebugOffset,\r
901            EFI_IMAGE_SCN_CNT_INITIALIZED_DATA\r
902            | EFI_IMAGE_SCN_MEM_DISCARDABLE\r
903            | EFI_IMAGE_SCN_MEM_READ);\r
904 \r
905   NtHdr = (EFI_IMAGE_NT_HEADERS *)(CoffFile + NtHdrOffset);\r
906   DataDir = &NtHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG];\r
907   DataDir->VirtualAddress = DebugOffset;\r
908   DataDir->Size = CoffOffset - DebugOffset;\r
909 }\r
910 \r
911 VOID\r
912 ConvertElf (\r
913   UINT8  **FileBuffer,\r
914   UINTN *FileLength\r
915   )\r
916 {\r
917   EFI_IMAGE_NT_HEADERS *NtHdr;\r
918 \r
919   //\r
920   // Check header, read section table.\r
921   //\r
922   Ehdr = (Elf32_Ehdr*)*FileBuffer;\r
923   if (!CheckElfHeader())\r
924     return;\r
925 \r
926   VerboseMsg ("Check Efl Image Header");\r
927   //\r
928   // Compute sections new address.\r
929   //\r
930   ScanSections();\r
931   \r
932   VerboseMsg ("Compute sections new address.");\r
933 \r
934   //\r
935   // Write and relocate sections.\r
936   //\r
937   WriteSections(IsTextShdr);\r
938   WriteSections(IsDataShdr);\r
939   VerboseMsg ("Write and relocate sections.");\r
940 \r
941   //\r
942   // Translate and write relocations.\r
943   //\r
944   WriteRelocations();\r
945   VerboseMsg ("Translate and write relocations.");\r
946 \r
947   //\r
948   // Write debug info.\r
949   //\r
950   WriteDebug();\r
951   VerboseMsg ("Write debug info.");\r
952 \r
953   NtHdr = (EFI_IMAGE_NT_HEADERS *)(CoffFile + NtHdrOffset);\r
954   NtHdr->OptionalHeader.SizeOfImage = CoffOffset;\r
955 \r
956   //\r
957   // Replace.\r
958   //\r
959   free(*FileBuffer);\r
960   *FileBuffer = CoffFile;\r
961   *FileLength = CoffOffset;\r
962   \r
963   //\r
964   // Free memory space\r
965   //\r
966   if (CoffSectionsOffset != NULL) {\r
967     free (CoffSectionsOffset);\r
968   }\r
969 }\r
970 #endif // HAVE_ELF\r
971 \r
972 int\r
973 main (\r
974   int  argc,\r
975   char *argv[]\r
976   )\r
977 /*++\r
978 \r
979 Routine Description:\r
980 \r
981   Main function.\r
982 \r
983 Arguments:\r
984 \r
985   argc - Number of command line parameters.\r
986   argv - Array of pointers to command line parameter strings.\r
987 \r
988 Returns:\r
989   STATUS_SUCCESS - Utility exits successfully.\r
990   STATUS_ERROR   - Some error occurred during execution.\r
991 \r
992 --*/\r
993 {\r
994   UINT32            Type;\r
995   UINT32            InputFileNum;\r
996   CHAR8             **InputFileName;\r
997   UINT8             *OutImageName;\r
998   UINT8             *ModuleType;\r
999   CHAR8             *TimeStamp;\r
1000   CHAR8             FileName[_MAX_PATH];\r
1001   UINT32            OutImageType;\r
1002   FILE              *fpIn;\r
1003   FILE              *fpOut;\r
1004   FILE              *fpInOut;\r
1005   UINTN             Data;\r
1006   UINTN             *DataPointer;\r
1007   UINTN             *OldDataPointer;\r
1008   UINTN             CheckSum;\r
1009   UINT32            Index;\r
1010   UINT32            Index1;\r
1011   UINT32            Index2;\r
1012   UINT64            Temp64;\r
1013   UINT32            MciAlignment;\r
1014   UINT8             MciPadValue;\r
1015   UINT32            AllignedRelocSize;\r
1016   UINT8             *FileBuffer;\r
1017   UINT32            FileLength;\r
1018   RUNTIME_FUNCTION  *RuntimeFunction;\r
1019   UNWIND_INFO       *UnwindInfo;\r
1020   STATUS            Status;\r
1021   BOOLEAN           ReplaceFlag;\r
1022   BOOLEAN           KeepExceptionTableFlag;\r
1023   BOOLEAN           KeepZeroPendingFlag;\r
1024   UINT64            LogLevel;\r
1025   EFI_TE_IMAGE_HEADER          TEImageHeader;\r
1026   EFI_TE_IMAGE_HEADER          *TeHdr;\r
1027   EFI_IMAGE_SECTION_HEADER     *SectionHeader;\r
1028   EFI_IMAGE_DOS_HEADER         *DosHdr;\r
1029   EFI_IMAGE_NT_HEADERS         *PeHdr;\r
1030   EFI_IMAGE_OPTIONAL_HEADER32  *Optional32;\r
1031   EFI_IMAGE_OPTIONAL_HEADER64  *Optional64;\r
1032   EFI_IMAGE_DOS_HEADER         BackupDosHdr;\r
1033   MICROCODE_IMAGE_HEADER       *MciHeader; \r
1034 \r
1035   SetUtilityName (UTILITY_NAME);\r
1036 \r
1037   //\r
1038   // Assign to fix compile warning\r
1039   //\r
1040   InputFileNum      = 0; \r
1041   InputFileName     = NULL;\r
1042   mInImageName       = NULL;\r
1043   OutImageName      = NULL;\r
1044   ModuleType        = NULL;\r
1045   OutImageType      = FW_DUMMY_IMAGE;\r
1046   Type              = 0;\r
1047   Status            = STATUS_SUCCESS;\r
1048   FileBuffer        = NULL;\r
1049   fpIn              = NULL;\r
1050   fpOut             = NULL;\r
1051   fpInOut           = NULL;\r
1052   TimeStamp         = NULL;\r
1053   MciAlignment      = DEFAULT_MC_ALIGNMENT;\r
1054   MciPadValue       = DEFAULT_MC_PAD_BYTE_VALUE;\r
1055   FileLength        = 0;\r
1056   MciHeader         = NULL;\r
1057   CheckSum          = 0;\r
1058   ReplaceFlag       = FALSE;\r
1059   LogLevel          = 0;\r
1060   KeepExceptionTableFlag = FALSE;\r
1061   KeepZeroPendingFlag    = FALSE;\r
1062 \r
1063   if (argc == 1) {\r
1064     Error (NULL, 0, 1001, "Missing options", "No input options.");\r
1065     Usage ();\r
1066     return STATUS_ERROR;\r
1067   }\r
1068   \r
1069   argc --;\r
1070   argv ++;  \r
1071 \r
1072   if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) {\r
1073     Version ();\r
1074     Usage ();\r
1075     return STATUS_SUCCESS;    \r
1076   }\r
1077 \r
1078   if (stricmp (argv[0], "--version") == 0) {\r
1079     Version ();\r
1080     return STATUS_SUCCESS;\r
1081   }\r
1082 \r
1083   while (argc > 0) {\r
1084     if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--outputfile") == 0)) {\r
1085       OutImageName = argv[1];\r
1086       if (OutImageName == NULL) {\r
1087         Error (NULL, 0, 1003, "Invalid option value", "Output file name can't be NULL");\r
1088         goto Finish;\r
1089       }\r
1090       argc -= 2;\r
1091       argv += 2;\r
1092       continue; \r
1093     }\r
1094 \r
1095     if ((stricmp (argv[0], "-e") == 0) || (stricmp (argv[0], "--efiImage") == 0)) {\r
1096       ModuleType   = argv[1];\r
1097       if (ModuleType == NULL) {\r
1098         Error (NULL, 0, 1003, "Invalid option value", "Module Type can't be NULL");\r
1099         goto Finish;        \r
1100       }\r
1101       if (OutImageType != FW_TE_IMAGE) {\r
1102         OutImageType = FW_EFI_IMAGE;\r
1103       }\r
1104       argc -= 2;\r
1105       argv += 2;\r
1106       continue;\r
1107     }\r
1108 \r
1109     if ((stricmp (argv[0], "-l") == 0) || (stricmp (argv[0], "--stripped") == 0)) {\r
1110       OutImageType = FW_RELOC_STRIPEED_IMAGE;\r
1111       argc --;\r
1112       argv ++;\r
1113       continue;\r
1114     }\r
1115 \r
1116     if ((stricmp (argv[0], "-c") == 0) || (stricmp (argv[0], "--acpi") == 0)) {\r
1117       OutImageType = FW_ACPI_IMAGE;\r
1118       argc --;\r
1119       argv ++;\r
1120       continue;\r
1121     }\r
1122 \r
1123     if ((stricmp (argv[0], "-t") == 0) || (stricmp (argv[0], "--terse") == 0)) {\r
1124       OutImageType = FW_TE_IMAGE;\r
1125       argc --;\r
1126       argv ++;\r
1127       continue;\r
1128     }\r
1129 \r
1130     if ((stricmp (argv[0], "-u") == 0) || (stricmp (argv[0], "--dump") == 0)) {\r
1131       OutImageType = DUMP_TE_HEADER;\r
1132       argc --;\r
1133       argv ++;\r
1134       continue;\r
1135     }\r
1136 \r
1137     if ((stricmp (argv[0], "-b") == 0) || (stricmp (argv[0], "--exe2bin") == 0)) {\r
1138       OutImageType = FW_BIN_IMAGE;\r
1139       argc --;\r
1140       argv ++;\r
1141       continue;\r
1142     }\r
1143 \r
1144     if ((stricmp (argv[0], "-z") == 0) || (stricmp (argv[0], "--zero") == 0)) {\r
1145       OutImageType = FW_ZERO_DEBUG_IMAGE;\r
1146       argc --;\r
1147       argv ++;\r
1148       continue;\r
1149     }\r
1150 \r
1151     if ((stricmp (argv[0], "-s") == 0) || (stricmp (argv[0], "--stamp") == 0)) {\r
1152       OutImageType = FW_SET_STAMP_IMAGE;\r
1153       TimeStamp    = argv[1];\r
1154       argc -= 2;\r
1155       argv += 2;\r
1156       continue;\r
1157     }\r
1158 \r
1159     if ((stricmp (argv[0], "-r") == 0) || (stricmp (argv[0], "--replace") == 0)) {\r
1160       ReplaceFlag = TRUE;\r
1161       argc --;\r
1162       argv ++;\r
1163       continue;\r
1164     }\r
1165 \r
1166     if (stricmp (argv[0], "--keepexceptiontable") == 0) {\r
1167       KeepExceptionTableFlag = TRUE;\r
1168       argc --;\r
1169       argv ++;\r
1170       continue;\r
1171     }\r
1172 \r
1173     if (stricmp (argv[0], "--keepzeropending") == 0) {\r
1174       KeepZeroPendingFlag = TRUE;\r
1175       argc --;\r
1176       argv ++;\r
1177       continue;\r
1178     }\r
1179 \r
1180     if ((stricmp (argv[0], "-m") == 0) || (stricmp (argv[0], "--mcifile") == 0)) {\r
1181       OutImageType = FW_MCI_IMAGE;\r
1182       argc --;\r
1183       argv ++;\r
1184       continue;\r
1185     }\r
1186 \r
1187     if ((stricmp (argv[0], "-j") == 0) || (stricmp (argv[0], "--join") == 0)) {\r
1188       OutImageType = FW_MERGE_IMAGE;\r
1189       argc --;\r
1190       argv ++;\r
1191       continue;\r
1192     }\r
1193 \r
1194     if ((stricmp (argv[0], "-a") == 0) || (stricmp (argv[0], "--align") == 0)) {\r
1195       if (AsciiStringToUint64 (argv[1], FALSE, &Temp64) != EFI_SUCCESS) {\r
1196         Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
1197         goto Finish;\r
1198       }\r
1199       MciAlignment = (UINT32) Temp64;\r
1200       argc -= 2;\r
1201       argv += 2;\r
1202       continue;\r
1203     }\r
1204 \r
1205     if ((stricmp (argv[0], "-p") == 0) || (stricmp (argv[0], "--pad") == 0)) {\r
1206       if (AsciiStringToUint64 (argv[1], FALSE, &Temp64) != EFI_SUCCESS) {\r
1207         Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
1208         goto Finish;\r
1209       }\r
1210       MciPadValue = (UINT8) Temp64;\r
1211       argc -= 2;\r
1212       argv += 2;\r
1213       continue;\r
1214     }\r
1215 \r
1216     if ((stricmp (argv[0], "-v") == 0) || (stricmp (argv[0], "--verbose") == 0)) {\r
1217       SetPrintLevel (VERBOSE_LOG_LEVEL);\r
1218       VerboseMsg ("Verbose output Mode Set!");\r
1219       argc --;\r
1220       argv ++;\r
1221       continue;\r
1222     }\r
1223 \r
1224     if ((stricmp (argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) {\r
1225       SetPrintLevel (KEY_LOG_LEVEL);\r
1226       KeyMsg ("Quiet output Mode Set!");\r
1227       argc --;\r
1228       argv ++;\r
1229       continue;\r
1230     }\r
1231 \r
1232     if ((stricmp (argv[0], "-d") == 0) || (stricmp (argv[0], "--debug") == 0)) {\r
1233       Status = AsciiStringToUint64 (argv[1], FALSE, &LogLevel);\r
1234       if (EFI_ERROR (Status)) {\r
1235         Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
1236         goto Finish;\r
1237       }\r
1238       if (LogLevel > 9) {\r
1239         Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0-9, currnt input level is %d", LogLevel);\r
1240         goto Finish;\r
1241       }\r
1242       SetPrintLevel (LogLevel);\r
1243       DebugMsg (NULL, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv[1]);\r
1244       argc -= 2;\r
1245       argv += 2;\r
1246       continue;\r
1247     }\r
1248 \r
1249     //\r
1250     // Get Input file name\r
1251     //\r
1252     if ((InputFileNum == 0) && (InputFileName == NULL)) {\r
1253       InputFileName = (CHAR8 **) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *));\r
1254       if (InputFileName == NULL) {\r
1255         Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
1256         return EFI_OUT_OF_RESOURCES;\r
1257       }\r
1258 \r
1259       memset (InputFileName, 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));\r
1260     } else if (InputFileNum % MAXIMUM_INPUT_FILE_NUM == 0) {\r
1261       //\r
1262       // InputFileName buffer too small, need to realloc\r
1263       //\r
1264       InputFileName = (CHAR8 **) realloc (\r
1265                                   InputFileName,\r
1266                                   (InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (CHAR8 *)\r
1267                                   );\r
1268 \r
1269       if (InputFileName == NULL) {\r
1270         Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
1271         return EFI_OUT_OF_RESOURCES;\r
1272       }\r
1273 \r
1274       memset (&(InputFileName[InputFileNum]), 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));\r
1275     }\r
1276 \r
1277     InputFileName [InputFileNum ++] = argv[0];\r
1278     argc --;\r
1279     argv ++;\r
1280   }\r
1281   \r
1282   VerboseMsg ("%s tool start.", UTILITY_NAME);\r
1283 \r
1284   if (OutImageType == FW_DUMMY_IMAGE) {\r
1285     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
1286     if (ReplaceFlag) {\r
1287       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
1288     }\r
1289     goto Finish;\r
1290   }\r
1291 \r
1292   //\r
1293   // check input files\r
1294   //\r
1295   if (InputFileNum == 0) {\r
1296     Error (NULL, 0, 1001, "Missing option", "Input files");\r
1297     goto Finish;\r
1298   }\r
1299 \r
1300   //\r
1301   // Combine MciBinary files to one file\r
1302   //\r
1303   if ((OutImageType == FW_MERGE_IMAGE) && ReplaceFlag) {\r
1304     Error (NULL, 0, 1002, "Conflicting option", "-r replace option cannot be used with -j merge files option.");\r
1305     goto Finish;\r
1306   }\r
1307    \r
1308   //\r
1309   // Input image file\r
1310   //\r
1311   mInImageName = InputFileName [InputFileNum - 1];\r
1312   VerboseMsg ("the input file name is %s", mInImageName);\r
1313   \r
1314   //\r
1315   // Action will be taken for the input file.\r
1316   //\r
1317   switch (OutImageType) {\r
1318   case FW_EFI_IMAGE:\r
1319     VerboseMsg ("Create efi image on module type %s based on the input PE image.", ModuleType);\r
1320     break;\r
1321   case FW_TE_IMAGE:\r
1322     VerboseMsg ("Create Te Image based on the input PE image.");\r
1323     break;\r
1324   case FW_ACPI_IMAGE:\r
1325     VerboseMsg ("Get acpi table data from the input PE image.");\r
1326     break;\r
1327   case FW_RELOC_STRIPEED_IMAGE:\r
1328     VerboseMsg ("Remove relocation section from Pe or Te image.");\r
1329     break;\r
1330   case FW_BIN_IMAGE:\r
1331     VerboseMsg ("Convert the input EXE to the output BIN file.");\r
1332     break;\r
1333   case FW_ZERO_DEBUG_IMAGE:\r
1334     VerboseMsg ("Zero the Debug Data Fields in input PE image.");\r
1335     break;\r
1336   case FW_SET_STAMP_IMAGE:\r
1337     VerboseMsg ("Set new time stamp %s in the input PE image.", TimeStamp);\r
1338     break;\r
1339   case DUMP_TE_HEADER:\r
1340     VerboseMsg ("Dump the TE header information of the input TE image.");\r
1341     break;\r
1342   case FW_MCI_IMAGE:\r
1343     VerboseMsg ("Conver input MicroCode.txt file to MicroCode.bin file.");\r
1344     break;\r
1345   case FW_MERGE_IMAGE:\r
1346     VerboseMsg ("Combine the input multi microcode bin files to one bin file.");\r
1347     break;\r
1348   default:\r
1349     break;\r
1350   }\r
1351   \r
1352   if (ReplaceFlag) {\r
1353     VerboseMsg ("Overwrite the input file with the output content.");\r
1354   }\r
1355 \r
1356   //\r
1357   // Open output file and Write image into the output file.\r
1358   //\r
1359   if (OutImageName != NULL) {\r
1360     fpOut = fopen (OutImageName, "wb");\r
1361     if (!fpOut) {\r
1362       Error (NULL, 0, 0001, "Error opening file", OutImageName);\r
1363       goto Finish;\r
1364     }\r
1365     VerboseMsg ("Output file name is %s", OutImageName);\r
1366   } else if (!ReplaceFlag) {\r
1367     if (OutImageType == DUMP_TE_HEADER) {\r
1368       fpOut = stdout;\r
1369     } else {\r
1370       Error (NULL, 0, 1001, "Missing option", "output file");\r
1371       goto Finish;\r
1372     }\r
1373   }\r
1374 \r
1375   //\r
1376   // Combine MciBinary files to one file\r
1377   //\r
1378   if (OutImageType == FW_MERGE_IMAGE) {\r
1379     for (Index = 0; Index < InputFileNum; Index ++) {\r
1380       fpIn = fopen (InputFileName [Index], "rb");\r
1381       if (!fpIn) {\r
1382         Error (NULL, 0, 0001, "Error opening file", InputFileName [Index]);\r
1383         goto Finish;\r
1384       }\r
1385     \r
1386       FileLength = _filelength (fileno (fpIn));\r
1387       FileBuffer = malloc (FileLength);\r
1388       if (FileBuffer == NULL) {\r
1389         Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
1390         fclose (fpIn);\r
1391         goto Finish;\r
1392       }\r
1393       \r
1394       fread (FileBuffer, 1, FileLength, fpIn);\r
1395       fclose (fpIn);\r
1396       //\r
1397       // write input file to out file\r
1398       //\r
1399       fwrite (FileBuffer, 1, FileLength, fpOut);\r
1400       //\r
1401       // write pad value to out file.\r
1402       //\r
1403       while (FileLength ++ % MciAlignment != 0) {\r
1404         fwrite (&MciPadValue, 1, 1, fpOut);\r
1405       }\r
1406       //\r
1407       // free allocated memory space\r
1408       //\r
1409       free (FileBuffer);\r
1410       FileBuffer = NULL;\r
1411     }\r
1412     // \r
1413     // Done successfully\r
1414     //\r
1415     goto Finish;\r
1416   }\r
1417 \r
1418   //\r
1419   // Convert MicroCode.txt file to MicroCode.bin file\r
1420   //\r
1421   if (OutImageType == FW_MCI_IMAGE) {\r
1422     fpIn = fopen (mInImageName, "r");\r
1423     if (!fpIn) {\r
1424       Error (NULL, 0, 0001, "Error opening file", mInImageName);\r
1425       goto Finish;\r
1426     }\r
1427     \r
1428     //\r
1429     // The first pass is to determine \r
1430     // how much data is in the file so we can allocate a working buffer. \r
1431     //\r
1432     FileLength = 0;\r
1433     do {\r
1434       Status = MicrocodeReadData (fpIn, &Data);\r
1435       if (Status == STATUS_SUCCESS) {\r
1436         FileLength += sizeof (Data);\r
1437       }\r
1438       if (Status == STATUS_IGNORE) {\r
1439         Status = STATUS_SUCCESS;\r
1440       }\r
1441     } while (Status == STATUS_SUCCESS);\r
1442     //\r
1443     // Error if no data.\r
1444     //\r
1445     if (FileLength == 0) {\r
1446       Error (NULL, 0, 3000, "Invalid", "no parseable data found in file %s", mInImageName);\r
1447       goto Finish;\r
1448     }\r
1449     if (FileLength < sizeof (MICROCODE_IMAGE_HEADER)) {\r
1450       Error (NULL, 0, 3000, "Invalid", "amount of parseable data in %s is insufficient to contain a microcode header", mInImageName);\r
1451       goto Finish;\r
1452     }\r
1453 \r
1454     //\r
1455     // Allocate a buffer for the data\r
1456     //\r
1457     FileBuffer = malloc (FileLength);\r
1458     if (FileBuffer == NULL) {\r
1459       Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
1460       goto Finish;\r
1461     }\r
1462     //\r
1463     // Re-read the file, storing the data into our buffer\r
1464     //\r
1465     fseek (fpIn, 0, SEEK_SET);\r
1466     DataPointer = (UINTN *) FileBuffer;\r
1467     OldDataPointer = DataPointer;\r
1468     do {\r
1469       OldDataPointer = DataPointer;\r
1470       Status = MicrocodeReadData (fpIn, DataPointer++);\r
1471       if (Status == STATUS_IGNORE) {\r
1472         DataPointer = OldDataPointer;\r
1473         Status = STATUS_SUCCESS;\r
1474       }\r
1475     } while (Status == STATUS_SUCCESS);\r
1476     //\r
1477     // close input file after read data\r
1478     //\r
1479     fclose (fpIn);\r
1480 \r
1481     //\r
1482     // Can't do much checking on the header because, per the spec, the\r
1483     // DataSize field may be 0, which means DataSize = 2000 and TotalSize = 2K,\r
1484     // and the TotalSize field is invalid (actually missing). Thus we can't\r
1485     // even verify the Reserved fields are 0.\r
1486     //\r
1487     MciHeader = (MICROCODE_IMAGE_HEADER *) FileBuffer;\r
1488     if (MciHeader->DataSize == 0) {\r
1489       Index = 2048;\r
1490     } else {\r
1491       Index = MciHeader->TotalSize;\r
1492     }\r
1493 \r
1494     if (Index != FileLength) {\r
1495       Error (NULL, 0, 3000, "Invalid", "file length of %s (0x%x) does not equal expected TotalSize: 0x%04X.", mInImageName, FileLength, Index);\r
1496       goto Finish;\r
1497     }\r
1498 \r
1499     //\r
1500     // Checksum the contents\r
1501     //\r
1502     DataPointer = (UINTN *) FileBuffer;\r
1503     CheckSum  = 0;\r
1504     Index     = 0;\r
1505     while (Index < FileLength) {\r
1506       CheckSum    += *DataPointer;\r
1507       DataPointer ++;\r
1508       Index       += sizeof (UINTN);\r
1509     }\r
1510     if (CheckSum != 0) {\r
1511       Error (NULL, 0, 3000, "Invalid", "checksum (0x%x) failed on file %s.", CheckSum, mInImageName);\r
1512       goto Finish;\r
1513     }\r
1514     //\r
1515     // Open the output file and write the buffer contents\r
1516     //\r
1517     if (fpOut != NULL) {\r
1518       if (fwrite (FileBuffer, FileLength, 1, fpOut) != 1) {\r
1519         Error (NULL, 0, 0002, "Error writing file", OutImageName);\r
1520         goto Finish;\r
1521       }\r
1522     }\r
1523     \r
1524     if (ReplaceFlag) {\r
1525       fpInOut = fopen (mInImageName, "wb");\r
1526       if (fpInOut != NULL) {\r
1527         Error (NULL, 0, 0001, "Error opening file", mInImageName);\r
1528         goto Finish;\r
1529       }\r
1530       if (fwrite (FileBuffer, FileLength, 1, fpInOut) != 1) {\r
1531         Error (NULL, 0, 0002, "Error writing file", mInImageName);\r
1532         goto Finish;\r
1533       }\r
1534     }\r
1535     VerboseMsg ("the size of output file is %d bytes", FileLength);\r
1536     //\r
1537     //  Convert Mci.TXT to Mci.bin file successfully\r
1538     //\r
1539     goto Finish;\r
1540   }\r
1541 \r
1542   //\r
1543   // Open input file and read file data into file buffer.\r
1544   //\r
1545   fpIn = fopen (mInImageName, "rb");\r
1546   if (!fpIn) {\r
1547     Error (NULL, 0, 0001, "Error opening file", mInImageName);\r
1548     goto Finish;\r
1549   }\r
1550 \r
1551   FileLength = _filelength (fileno (fpIn));\r
1552   FileBuffer = malloc (FileLength);\r
1553   if (FileBuffer == NULL) {\r
1554     Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
1555     fclose (fpIn);\r
1556     goto Finish;\r
1557   }\r
1558   \r
1559   fread (FileBuffer, 1, FileLength, fpIn);\r
1560   fclose (fpIn);\r
1561   \r
1562   DebugMsg (NULL, 0, 9, "input file info", "the input file size is %d bytes", FileLength);\r
1563   \r
1564   //\r
1565   // Replace file\r
1566   //\r
1567   if (ReplaceFlag) {\r
1568     fpInOut = fopen (mInImageName, "wb");\r
1569     if (!fpInOut) {\r
1570       Error (NULL, 0, 0001, "Error opening file", mInImageName);\r
1571       goto Finish;\r
1572     }\r
1573   }\r
1574   //\r
1575   // Dump TeImage Header into output file.\r
1576   //\r
1577   if (OutImageType == DUMP_TE_HEADER) {\r
1578     memcpy (&TEImageHeader, FileBuffer, sizeof (TEImageHeader));\r
1579     if (TEImageHeader.Signature != EFI_TE_IMAGE_HEADER_SIGNATURE) {\r
1580       Error (NULL, 0, 3000, "Invalid", "TE header signature of file %s is not correct.", mInImageName);\r
1581       goto Finish;      \r
1582     }\r
1583     if (fpInOut != NULL) {\r
1584       fprintf (fpInOut, "Dump of file %s\n\n", mInImageName);\r
1585       fprintf (fpInOut, "TE IMAGE HEADER VALUES\n");\r
1586       fprintf (fpInOut, "%17X machine\n", TEImageHeader.Machine);\r
1587       fprintf (fpInOut, "%17X number of sections\n", TEImageHeader.NumberOfSections);\r
1588       fprintf (fpInOut, "%17X subsystems\n", TEImageHeader.Subsystem);\r
1589       fprintf (fpInOut, "%17X stripped size\n", TEImageHeader.StrippedSize);\r
1590       fprintf (fpInOut, "%17X entry point\n", TEImageHeader.AddressOfEntryPoint);\r
1591       fprintf (fpInOut, "%17X base of code\n", TEImageHeader.BaseOfCode);\r
1592       fprintf (fpInOut, "%17X image base\n", TEImageHeader.ImageBase);\r
1593       fprintf (fpInOut, "%17X [%8X] RVA [size] of Base Relocation Directory\n", TEImageHeader.DataDirectory[0].VirtualAddress, TEImageHeader.DataDirectory[0].Size);\r
1594       fprintf (fpInOut, "%17X [%8X] RVA [size] of Debug Directory\n", TEImageHeader.DataDirectory[1].VirtualAddress, TEImageHeader.DataDirectory[1].Size);\r
1595     }\r
1596 \r
1597     if (fpOut != NULL) {\r
1598       fprintf (fpOut, "Dump of file %s\n\n", mInImageName);\r
1599       fprintf (fpOut, "TE IMAGE HEADER VALUES\n");\r
1600       fprintf (fpOut, "%17X machine\n", TEImageHeader.Machine);\r
1601       fprintf (fpOut, "%17X number of sections\n", TEImageHeader.NumberOfSections);\r
1602       fprintf (fpOut, "%17X subsystems\n", TEImageHeader.Subsystem);\r
1603       fprintf (fpOut, "%17X stripped size\n", TEImageHeader.StrippedSize);\r
1604       fprintf (fpOut, "%17X entry point\n", TEImageHeader.AddressOfEntryPoint);\r
1605       fprintf (fpOut, "%17X base of code\n", TEImageHeader.BaseOfCode);\r
1606       fprintf (fpOut, "%17X image base\n", TEImageHeader.ImageBase);\r
1607       fprintf (fpOut, "%17X [%8X] RVA [size] of Base Relocation Directory\n", TEImageHeader.DataDirectory[0].VirtualAddress, TEImageHeader.DataDirectory[0].Size);\r
1608       fprintf (fpOut, "%17X [%8X] RVA [size] of Debug Directory\n", TEImageHeader.DataDirectory[1].VirtualAddress, TEImageHeader.DataDirectory[1].Size);\r
1609     }\r
1610     goto Finish;\r
1611   }\r
1612 \r
1613   //\r
1614   // Following code to convert dll to efi image or te image.\r
1615   // Get new image type\r
1616   //\r
1617   if ((OutImageType == FW_EFI_IMAGE) || (OutImageType == FW_TE_IMAGE)) {\r
1618     if (ModuleType == NULL) {\r
1619       if (OutImageType == FW_EFI_IMAGE) {\r
1620         Error (NULL, 0, 1001, "Missing option", "EFI_FILETYPE");\r
1621         goto Finish;\r
1622       } else if (OutImageType == FW_TE_IMAGE) {\r
1623         //\r
1624         // Default TE Image Type is Boot service driver\r
1625         //\r
1626         Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER;\r
1627         VerboseMsg ("Efi Image subsystem type is efi boot service driver.");\r
1628       }\r
1629     } else {\r
1630       if (stricmp (ModuleType, "BASE") == 0 ||\r
1631           stricmp (ModuleType, "SEC") == 0 ||\r
1632           stricmp (ModuleType, "SECURITY_CORE") == 0 ||\r
1633           stricmp (ModuleType, "PEI_CORE") == 0 ||\r
1634           stricmp (ModuleType, "PEIM") == 0 ||\r
1635           stricmp (ModuleType, "COMBINED_PEIM_DRIVER") == 0 ||\r
1636           stricmp (ModuleType, "PIC_PEIM") == 0 ||\r
1637           stricmp (ModuleType, "RELOCATABLE_PEIM") == 0 ||\r
1638           stricmp (ModuleType, "DXE_CORE") == 0 ||\r
1639           stricmp (ModuleType, "BS_DRIVER") == 0  ||\r
1640           stricmp (ModuleType, "DXE_DRIVER") == 0 ||\r
1641           stricmp (ModuleType, "DXE_SMM_DRIVER") == 0  ||\r
1642           stricmp (ModuleType, "UEFI_DRIVER") == 0) {\r
1643         Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER;\r
1644         VerboseMsg ("Efi Image subsystem type is efi boot service driver.");\r
1645     \r
1646       } else if (stricmp (ModuleType, "UEFI_APPLICATION") == 0 || \r
1647                  stricmp (ModuleType, "APPLICATION") == 0) {\r
1648         Type = EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION;\r
1649         VerboseMsg ("Efi Image subsystem type is efi application.");\r
1650     \r
1651       } else if (stricmp (ModuleType, "DXE_RUNTIME_DRIVER") == 0 || \r
1652                  stricmp (ModuleType, "RT_DRIVER") == 0) {\r
1653         Type = EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER;\r
1654         VerboseMsg ("Efi Image subsystem type is efi runtime driver.");\r
1655     \r
1656       } else if (stricmp (ModuleType, "DXE_SAL_DRIVER") == 0 || \r
1657                  stricmp (ModuleType, "SAL_RT_DRIVER") == 0) {\r
1658         Type = EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER;\r
1659         VerboseMsg ("Efi Image subsystem type is efi sal runtime driver.");\r
1660     \r
1661       } else {\r
1662         Error (NULL, 0, 1003, "Invalid option value", "EFI_FILETYPE = %s", ModuleType);\r
1663         goto Finish;\r
1664       }\r
1665     }\r
1666   }\r
1667 \r
1668   //\r
1669   // Convert EFL image to PeImage\r
1670   //\r
1671 #ifdef HAVE_ELF\r
1672   if (IsElfHeader(FileBuffer)) {\r
1673     VerboseMsg ("Convert the input ELF Image to Pe Image");\r
1674     ConvertElf(&FileBuffer, &FileLength);\r
1675   }\r
1676 #endif\r
1677   \r
1678   //\r
1679   // Remove reloc section from PE or TE image\r
1680   //\r
1681   if (OutImageType == FW_RELOC_STRIPEED_IMAGE) {\r
1682     //\r
1683     // Check TeImage\r
1684     //\r
1685     TeHdr = (EFI_TE_IMAGE_HEADER *) FileBuffer;\r
1686     if (TeHdr->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {\r
1687       SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (TeHdr + 1);\r
1688       for (Index = 0; Index < TeHdr->NumberOfSections; Index ++, SectionHeader ++) {\r
1689         if (strcmp (SectionHeader->Name, ".reloc") == 0) {\r
1690           //\r
1691           // Check the reloc section is in the end of image.\r
1692           //\r
1693           if ((SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData) == \r
1694             (FileLength + TeHdr->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER))) {\r
1695             //\r
1696             // Remove .reloc section and update TeImage Header\r
1697             //\r
1698             FileLength = FileLength - SectionHeader->SizeOfRawData;\r
1699             SectionHeader->SizeOfRawData = 0;\r
1700             SectionHeader->Misc.VirtualSize = 0;\r
1701             TeHdr->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = 0;\r
1702             TeHdr->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size           = 0;\r
1703             break;\r
1704           }\r
1705         }\r
1706       }\r
1707     } else {\r
1708       //\r
1709       // Check PE Image\r
1710       //\r
1711       DosHdr = (EFI_IMAGE_DOS_HEADER *) FileBuffer;\r
1712       if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {\r
1713         Error (NULL, 0, 3000, "Invalid", "TE and DOS header signatures were not found in %s image.", mInImageName);\r
1714         goto Finish;\r
1715       }\r
1716       PeHdr = (EFI_IMAGE_NT_HEADERS *)(FileBuffer + DosHdr->e_lfanew);\r
1717       if (PeHdr->Signature != EFI_IMAGE_NT_SIGNATURE) {\r
1718         Error (NULL, 0, 3000, "Invalid", "PE header signature was not found in %s image.", mInImageName);\r
1719         goto Finish;\r
1720       }\r
1721       SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->OptionalHeader) + PeHdr->FileHeader.SizeOfOptionalHeader);\r
1722       for (Index = 0; Index < PeHdr->FileHeader.NumberOfSections; Index ++, SectionHeader ++) {\r
1723         if (strcmp (SectionHeader->Name, ".reloc") == 0) {\r
1724           //\r
1725           // Check the reloc section is in the end of image.\r
1726           //\r
1727           if ((SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData) == FileLength) {\r
1728             //\r
1729             // Remove .reloc section and update PeImage Header\r
1730             //\r
1731             FileLength = FileLength - SectionHeader->SizeOfRawData;\r
1732 \r
1733             PeHdr->FileHeader.Characteristics |= EFI_IMAGE_FILE_RELOCS_STRIPPED;\r
1734             if (PeHdr->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
1735               Optional32 = (EFI_IMAGE_OPTIONAL_HEADER32 *)&PeHdr->OptionalHeader;\r
1736               Optional32->SizeOfImage -= SectionHeader->SizeOfRawData;\r
1737               Optional32->SizeOfInitializedData -= SectionHeader->SizeOfRawData;\r
1738               if (Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {\r
1739                 Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = 0;\r
1740                 Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = 0;\r
1741               }\r
1742             }\r
1743             if (PeHdr->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
1744               Optional64 = (EFI_IMAGE_OPTIONAL_HEADER64 *)&PeHdr->OptionalHeader;\r
1745               Optional64->SizeOfImage -= SectionHeader->SizeOfRawData;\r
1746               Optional64->SizeOfInitializedData -= SectionHeader->SizeOfRawData;\r
1747               if (Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {\r
1748                 Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = 0;\r
1749                 Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = 0;\r
1750               }\r
1751             }\r
1752             SectionHeader->Misc.VirtualSize = 0;\r
1753             SectionHeader->SizeOfRawData = 0;\r
1754             break;\r
1755           }\r
1756         }\r
1757       }\r
1758     }\r
1759     //\r
1760     // Write file\r
1761     //\r
1762     goto WriteFile;\r
1763   }\r
1764   //\r
1765   // Read the dos & pe hdrs of the image\r
1766   //\r
1767   DosHdr = (EFI_IMAGE_DOS_HEADER *)FileBuffer;\r
1768   if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {\r
1769     Error (NULL, 0, 3000, "Invalid", "DOS header signature was not found in %s image.", mInImageName);\r
1770     goto Finish;\r
1771   }\r
1772 \r
1773   PeHdr = (EFI_IMAGE_NT_HEADERS *)(FileBuffer + DosHdr->e_lfanew);\r
1774   if (PeHdr->Signature != EFI_IMAGE_NT_SIGNATURE) {\r
1775     Error (NULL, 0, 3000, "Invalid", "PE header signature was not found in %s image.", mInImageName);\r
1776     goto Finish;\r
1777   }\r
1778   \r
1779   //\r
1780   // Extract bin data from Pe image.\r
1781   //\r
1782   if (OutImageType == FW_BIN_IMAGE) {\r
1783     if (FileLength < PeHdr->OptionalHeader.SizeOfHeaders) {\r
1784       Error (NULL, 0, 3000, "Invalid", "FileSize of %s is not a legal size.", mInImageName);\r
1785       goto Finish;\r
1786     }\r
1787     //\r
1788     // Output bin data from exe file\r
1789     //\r
1790     if (fpOut != NULL) {\r
1791       fwrite (FileBuffer + PeHdr->OptionalHeader.SizeOfHeaders, 1, FileLength - PeHdr->OptionalHeader.SizeOfHeaders, fpOut);\r
1792     }\r
1793     if (fpInOut != NULL) {\r
1794       fwrite (FileBuffer + PeHdr->OptionalHeader.SizeOfHeaders, 1, FileLength - PeHdr->OptionalHeader.SizeOfHeaders, fpInOut);\r
1795     }\r
1796     VerboseMsg ("the size of output file is %d bytes", FileLength - PeHdr->OptionalHeader.SizeOfHeaders);\r
1797     goto Finish;\r
1798   }\r
1799 \r
1800   //\r
1801   // Zero Debug Information of Pe Image\r
1802   //\r
1803   if (OutImageType == FW_ZERO_DEBUG_IMAGE) {\r
1804     Status = ZeroDebugData (FileBuffer);\r
1805     if (EFI_ERROR (Status)) {\r
1806       Error (NULL, 0, 3000, "Invalid", "Zero DebugData Error status is 0x%lx", (UINTN) Status);\r
1807       goto Finish;\r
1808     }\r
1809     \r
1810     if (fpOut != NULL) {\r
1811       fwrite (FileBuffer, 1, FileLength, fpOut);\r
1812     }\r
1813     if (fpInOut != NULL) {\r
1814       fwrite (FileBuffer, 1, FileLength, fpInOut);\r
1815     }\r
1816     VerboseMsg ("the size of output file is %d bytes", FileLength);\r
1817     goto Finish; \r
1818   }\r
1819 \r
1820   //\r
1821   // Set Time Stamp of Pe Image\r
1822   //\r
1823   if (OutImageType == FW_SET_STAMP_IMAGE) {\r
1824     Status = SetStamp (FileBuffer, TimeStamp);\r
1825     if (EFI_ERROR (Status)) {\r
1826       Error (NULL, 0, 3000, "Invalid", "SetStamp Error status is 0x%lx", (UINTN) Status);\r
1827       goto Finish;\r
1828     }\r
1829     \r
1830     if (fpOut != NULL) {\r
1831       fwrite (FileBuffer, 1, FileLength, fpOut);  \r
1832     }\r
1833     if (fpInOut != NULL) {\r
1834       fwrite (FileBuffer, 1, FileLength, fpInOut);\r
1835     }\r
1836     VerboseMsg ("the size of output file is %d bytes", FileLength);\r
1837     goto Finish;\r
1838   }\r
1839 \r
1840   //\r
1841   // Extract acpi data from pe image.\r
1842   //\r
1843   if (OutImageType == FW_ACPI_IMAGE) {\r
1844     SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->OptionalHeader) + PeHdr->FileHeader.SizeOfOptionalHeader); \r
1845     for (Index = 0; Index < PeHdr->FileHeader.NumberOfSections; Index ++, SectionHeader ++) {\r
1846       if (strcmp (SectionHeader->Name, ".data") == 0 || strcmp (SectionHeader->Name, ".sdata") == 0) {\r
1847         //\r
1848         // Check Acpi Table\r
1849         //\r
1850         if (SectionHeader->Misc.VirtualSize < SectionHeader->SizeOfRawData) {\r
1851           FileLength = SectionHeader->Misc.VirtualSize;\r
1852         } else {\r
1853           FileLength = SectionHeader->SizeOfRawData;\r
1854         }\r
1855 \r
1856         if (CheckAcpiTable (FileBuffer + SectionHeader->PointerToRawData, FileLength) != STATUS_SUCCESS) {\r
1857           Error (NULL, 0, 3000, "Invalid", "ACPI table check failed in %s.", mInImageName);\r
1858           goto Finish;\r
1859         }\r
1860         \r
1861         //\r
1862         // Output Apci data to file\r
1863         //\r
1864         if (fpOut != NULL) {\r
1865           fwrite (FileBuffer + SectionHeader->PointerToRawData, 1, FileLength, fpOut);\r
1866         }\r
1867         if (fpInOut != NULL) {\r
1868           fwrite (FileBuffer + SectionHeader->PointerToRawData, 1, FileLength, fpInOut);\r
1869         }\r
1870         VerboseMsg ("the size of output file is %d bytes", FileLength);\r
1871         goto Finish;\r
1872       }\r
1873     }\r
1874     Error (NULL, 0, 3000, "Invalid", "failed to get ACPI table from %s.", mInImageName);\r
1875     goto Finish;\r
1876   }\r
1877   //\r
1878   // Zero all unused fields of the DOS header\r
1879   //\r
1880   memcpy (&BackupDosHdr, DosHdr, sizeof (EFI_IMAGE_DOS_HEADER));\r
1881   memset (DosHdr, 0, sizeof (EFI_IMAGE_DOS_HEADER));\r
1882   DosHdr->e_magic  = BackupDosHdr.e_magic;\r
1883   DosHdr->e_lfanew = BackupDosHdr.e_lfanew;\r
1884 \r
1885   for (Index = sizeof (EFI_IMAGE_DOS_HEADER); Index < (UINT32 ) DosHdr->e_lfanew; Index++) {\r
1886     FileBuffer[Index] = DosHdr->e_cp;\r
1887   }\r
1888   \r
1889   //\r
1890   // Initialize TeImage Header\r
1891   //\r
1892   memset (&TEImageHeader, 0, sizeof (EFI_TE_IMAGE_HEADER));\r
1893   TEImageHeader.Signature        = EFI_TE_IMAGE_HEADER_SIGNATURE;\r
1894   TEImageHeader.Machine          = PeHdr->FileHeader.Machine;\r
1895   TEImageHeader.NumberOfSections = (UINT8) PeHdr->FileHeader.NumberOfSections;\r
1896   TEImageHeader.StrippedSize     = (UINT16) ((UINTN) ((UINT8 *) &(PeHdr->OptionalHeader) + PeHdr->FileHeader.SizeOfOptionalHeader) - (UINTN) FileBuffer);\r
1897   TEImageHeader.Subsystem        = (UINT8) Type;\r
1898 \r
1899   //\r
1900   // Patch the PE header\r
1901   //\r
1902   PeHdr->OptionalHeader.Subsystem = (UINT16) Type;\r
1903 \r
1904   if (PeHdr->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
1905     Optional32 = (EFI_IMAGE_OPTIONAL_HEADER32 *)&PeHdr->OptionalHeader;\r
1906     Optional32->MajorLinkerVersion          = 0;\r
1907     Optional32->MinorLinkerVersion          = 0;\r
1908     Optional32->MajorOperatingSystemVersion = 0;\r
1909     Optional32->MinorOperatingSystemVersion = 0;\r
1910     Optional32->MajorImageVersion           = 0;\r
1911     Optional32->MinorImageVersion           = 0;\r
1912     Optional32->MajorSubsystemVersion       = 0;\r
1913     Optional32->MinorSubsystemVersion       = 0;\r
1914     Optional32->Win32VersionValue           = 0;\r
1915     Optional32->CheckSum                    = 0;\r
1916     Optional32->SizeOfStackReserve = 0;\r
1917     Optional32->SizeOfStackCommit  = 0;\r
1918     Optional32->SizeOfHeapReserve  = 0;\r
1919     Optional32->SizeOfHeapCommit   = 0;\r
1920     \r
1921     TEImageHeader.AddressOfEntryPoint = Optional32->AddressOfEntryPoint;\r
1922     TEImageHeader.BaseOfCode          = Optional32->BaseOfCode;\r
1923     TEImageHeader.ImageBase           = (UINT64) (Optional32->ImageBase);\r
1924 \r
1925     if (Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {\r
1926       TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;\r
1927       TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;\r
1928     }\r
1929 \r
1930     if (Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {\r
1931       TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;\r
1932       TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size;\r
1933     }\r
1934 \r
1935     //\r
1936     // Zero .pdata section data.\r
1937     //\r
1938     if (!KeepExceptionTableFlag && Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION &&\r
1939         Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress != 0 && \r
1940         Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size != 0) {\r
1941       SectionHeader = (EFI_IMAGE_SECTION_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof(UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + PeHdr->FileHeader.SizeOfOptionalHeader);\r
1942       for (Index = 0; Index < PeHdr->FileHeader.NumberOfSections; Index++, SectionHeader++) {\r
1943         if (SectionHeader->VirtualAddress == Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress) {\r
1944           //\r
1945           // Zero .pdata Section data\r
1946           //\r
1947           memset (FileBuffer + SectionHeader->PointerToRawData, 0, SectionHeader->SizeOfRawData);\r
1948           //\r
1949           // Zero .pdata Section header name\r
1950           //\r
1951           memset (SectionHeader->Name, 0, sizeof (SectionHeader->Name));\r
1952           //\r
1953           // Zero Execption Table\r
1954           //\r
1955           Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress = 0;\r
1956           Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size           = 0;\r
1957           DebugMsg (NULL, 0, 9, "Zero the .pdata section for PE image", NULL);\r
1958           break;\r
1959         }\r
1960       }\r
1961     }\r
1962 \r
1963     //\r
1964     // Strip zero padding at the end of the .reloc section \r
1965     //\r
1966     if (!KeepZeroPendingFlag && Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {\r
1967       if (Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size != 0) {\r
1968         SectionHeader = (EFI_IMAGE_SECTION_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof(UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + PeHdr->FileHeader.SizeOfOptionalHeader);\r
1969         for (Index = 0; Index < PeHdr->FileHeader.NumberOfSections; Index++, SectionHeader++) {\r
1970           //\r
1971           // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory\r
1972           //\r
1973           if (SectionHeader->VirtualAddress == Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress) {\r
1974             SectionHeader->Misc.VirtualSize = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;\r
1975             AllignedRelocSize = (Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size + Optional32->FileAlignment - 1) & (~(Optional32->FileAlignment - 1));\r
1976             //\r
1977             // Check to see if there is zero padding at the end of the base relocations\r
1978             //\r
1979             if (AllignedRelocSize < SectionHeader->SizeOfRawData) {\r
1980               //\r
1981               // Check to see if the base relocations are at the end of the file\r
1982               //\r
1983               if (SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData == Optional32->SizeOfImage) {\r
1984                 //\r
1985                 // All the required conditions are met to strip the zero padding of the end of the base relocations section\r
1986                 //\r
1987                 Optional32->SizeOfImage -= (SectionHeader->SizeOfRawData - AllignedRelocSize);\r
1988                 Optional32->SizeOfInitializedData -= (SectionHeader->SizeOfRawData - AllignedRelocSize);\r
1989                 SectionHeader->SizeOfRawData = AllignedRelocSize;\r
1990                 FileLength = Optional32->SizeOfImage;\r
1991                 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
1992               }\r
1993             }\r
1994           }\r
1995         }\r
1996       }\r
1997     }\r
1998   } else if (PeHdr->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
1999     Optional64 = (EFI_IMAGE_OPTIONAL_HEADER64 *)&PeHdr->OptionalHeader;\r
2000     Optional64->MajorLinkerVersion          = 0;\r
2001     Optional64->MinorLinkerVersion          = 0;\r
2002     Optional64->MajorOperatingSystemVersion = 0;\r
2003     Optional64->MinorOperatingSystemVersion = 0;\r
2004     Optional64->MajorImageVersion           = 0;\r
2005     Optional64->MinorImageVersion           = 0;\r
2006     Optional64->MajorSubsystemVersion       = 0;\r
2007     Optional64->MinorSubsystemVersion       = 0;\r
2008     Optional64->Win32VersionValue           = 0;\r
2009     Optional64->CheckSum                    = 0;\r
2010     Optional64->SizeOfStackReserve = 0;\r
2011     Optional64->SizeOfStackCommit  = 0;\r
2012     Optional64->SizeOfHeapReserve  = 0;\r
2013     Optional64->SizeOfHeapCommit   = 0;\r
2014 \r
2015     TEImageHeader.AddressOfEntryPoint = Optional64->AddressOfEntryPoint;\r
2016     TEImageHeader.BaseOfCode          = Optional64->BaseOfCode;\r
2017     TEImageHeader.ImageBase           = (UINT64) (Optional64->ImageBase);\r
2018 \r
2019     if (Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {\r
2020       TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;\r
2021       TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;\r
2022     }\r
2023 \r
2024     if (Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {\r
2025       TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;\r
2026       TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size;\r
2027     }\r
2028 \r
2029     //\r
2030     // Zero the .pdata section for X64 machine and don't check the Debug Directory is empty\r
2031     // For Itaninum and X64 Image, remove .pdata section.\r
2032     //\r
2033     if (!KeepExceptionTableFlag && PeHdr->FileHeader.Machine == IMAGE_FILE_MACHINE_X64 || PeHdr->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64) {\r
2034       if (Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION &&\r
2035           Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress != 0 && \r
2036           Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size != 0) {\r
2037         //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
2038         SectionHeader = (EFI_IMAGE_SECTION_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof(UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + PeHdr->FileHeader.SizeOfOptionalHeader);\r
2039         for (Index = 0; Index < PeHdr->FileHeader.NumberOfSections; Index++, SectionHeader++) {\r
2040           if (SectionHeader->VirtualAddress == Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress) {\r
2041             //\r
2042             // Zero .pdata Section header name\r
2043             //\r
2044             memset (SectionHeader->Name, 0, sizeof (SectionHeader->Name));\r
2045 \r
2046             RuntimeFunction = (RUNTIME_FUNCTION *)(FileBuffer + SectionHeader->PointerToRawData);\r
2047             for (Index1 = 0; Index1 < Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size / sizeof (RUNTIME_FUNCTION); Index1++, RuntimeFunction++) {\r
2048               SectionHeader = (EFI_IMAGE_SECTION_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof(UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + PeHdr->FileHeader.SizeOfOptionalHeader);\r
2049               for (Index2 = 0; Index2 < PeHdr->FileHeader.NumberOfSections; Index2++, SectionHeader++) {\r
2050                 if (RuntimeFunction->UnwindInfoAddress > SectionHeader->VirtualAddress && RuntimeFunction->UnwindInfoAddress < (SectionHeader->VirtualAddress + SectionHeader->SizeOfRawData)) {\r
2051                   UnwindInfo = (UNWIND_INFO *)(FileBuffer + SectionHeader->PointerToRawData + (RuntimeFunction->UnwindInfoAddress - SectionHeader->VirtualAddress));\r
2052                   if (UnwindInfo->Version == 1) {\r
2053                     memset (UnwindInfo + 1, 0, UnwindInfo->CountOfUnwindCodes * sizeof (UINT16));\r
2054                     memset (UnwindInfo, 0, sizeof (UNWIND_INFO));\r
2055                   }\r
2056                 }\r
2057               }\r
2058               memset (RuntimeFunction, 0, sizeof (RUNTIME_FUNCTION));\r
2059             }\r
2060             //\r
2061             // Zero Execption Table\r
2062             //\r
2063             Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size = 0;\r
2064             Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress = 0;\r
2065             DebugMsg (NULL, 0, 9, "Zero the .pdata section if the machine type is X64 for PE32+ image", NULL);\r
2066             break;\r
2067           }\r
2068         }\r
2069       }\r
2070     }\r
2071 \r
2072     //\r
2073     // Strip zero padding at the end of the .reloc section \r
2074     //\r
2075     if (!KeepZeroPendingFlag && Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {\r
2076       if (Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size != 0) {\r
2077         SectionHeader = (EFI_IMAGE_SECTION_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof(UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + PeHdr->FileHeader.SizeOfOptionalHeader);\r
2078         for (Index = 0; Index < PeHdr->FileHeader.NumberOfSections; Index++, SectionHeader++) {\r
2079           //\r
2080           // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory\r
2081           //\r
2082           if (SectionHeader->VirtualAddress == Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress) {\r
2083             SectionHeader->Misc.VirtualSize = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;\r
2084             AllignedRelocSize = (Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size + Optional64->FileAlignment - 1) & (~(Optional64->FileAlignment - 1));\r
2085             //\r
2086             // Check to see if there is zero padding at the end of the base relocations\r
2087             //\r
2088             if (AllignedRelocSize < SectionHeader->SizeOfRawData) {\r
2089               //\r
2090               // Check to see if the base relocations are at the end of the file\r
2091               //\r
2092               if (SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData == Optional64->SizeOfImage) {\r
2093                 //\r
2094                 // All the required conditions are met to strip the zero padding of the end of the base relocations section\r
2095                 //\r
2096                 Optional64->SizeOfImage -= (SectionHeader->SizeOfRawData - AllignedRelocSize);\r
2097                 Optional64->SizeOfInitializedData -= (SectionHeader->SizeOfRawData - AllignedRelocSize);\r
2098                 SectionHeader->SizeOfRawData = AllignedRelocSize;\r
2099                 FileLength = Optional64->SizeOfImage;\r
2100                 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
2101               }\r
2102             }\r
2103           }\r
2104         }\r
2105       }\r
2106     }\r
2107   } else {\r
2108     Error (NULL, 0, 3000, "Invalid", "Magic 0x%x of PeImage %s is unknown.", PeHdr->OptionalHeader.Magic, mInImageName);\r
2109     goto Finish;\r
2110   }\r
2111 \r
2112   if (OutImageType == FW_TE_IMAGE) {\r
2113     if ((PeHdr->FileHeader.NumberOfSections &~0xFF) || (Type &~0xFF)) {\r
2114       //\r
2115       // Pack the subsystem and NumberOfSections into 1 byte. Make sure they fit both.\r
2116       //\r
2117       Error (NULL, 0, 3000, "Invalid", "Image's subsystem or NumberOfSections of PeImage %s cannot be packed into 1 byte.", mInImageName);\r
2118       goto Finish;\r
2119     }\r
2120 \r
2121     if ((PeHdr->OptionalHeader.SectionAlignment != PeHdr->OptionalHeader.FileAlignment)) {\r
2122       //\r
2123       // TeImage has the same section alignment and file alignment.\r
2124       //\r
2125       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
2126       goto Finish;\r
2127     }\r
2128     \r
2129     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
2130               TEImageHeader.Machine, TEImageHeader.NumberOfSections, TEImageHeader.StrippedSize, TEImageHeader.AddressOfEntryPoint, TEImageHeader.BaseOfCode, TEImageHeader.ImageBase);\r
2131     //\r
2132     // Update Image to TeImage\r
2133     //\r
2134     if (fpOut != NULL) {\r
2135       fwrite (&TEImageHeader, 1, sizeof (EFI_TE_IMAGE_HEADER), fpOut);\r
2136       fwrite (FileBuffer + TEImageHeader.StrippedSize, 1, FileLength - TEImageHeader.StrippedSize, fpOut);\r
2137     }\r
2138     if (fpInOut != NULL) {\r
2139       fwrite (&TEImageHeader, 1, sizeof (EFI_TE_IMAGE_HEADER), fpInOut);\r
2140       fwrite (FileBuffer + TEImageHeader.StrippedSize, 1, FileLength - TEImageHeader.StrippedSize, fpInOut);\r
2141     }\r
2142     VerboseMsg ("the size of output file is %d bytes", FileLength - TEImageHeader.StrippedSize);\r
2143     goto Finish;\r
2144   }\r
2145 WriteFile:\r
2146   //\r
2147   // Update Image to EfiImage\r
2148   //\r
2149   if (fpOut != NULL) {\r
2150     fwrite (FileBuffer, 1, FileLength, fpOut);\r
2151   }\r
2152   if (fpInOut != NULL) {\r
2153     fwrite (FileBuffer, 1, FileLength, fpInOut);\r
2154   }\r
2155   VerboseMsg ("the size of output file is %d bytes", FileLength);\r
2156 \r
2157 Finish:\r
2158   if (fpInOut != NULL) {\r
2159     if (GetUtilityStatus () != STATUS_SUCCESS) {\r
2160       //\r
2161       // when file updates failed, original file is still recoveried.\r
2162       //\r
2163       fwrite (FileBuffer, 1, FileLength, fpInOut);\r
2164     }\r
2165     //\r
2166     // Write converted data into fpInOut file and close input file.\r
2167     //\r
2168     fclose (fpInOut);\r
2169   }\r
2170 \r
2171   if (FileBuffer != NULL) {\r
2172     free (FileBuffer);\r
2173   }\r
2174   \r
2175   if (InputFileName != NULL) {\r
2176     free (InputFileName);\r
2177   }\r
2178 \r
2179   if (fpOut != NULL) {\r
2180     //\r
2181     // Write converted data into fpOut file and close output file.\r
2182     //\r
2183     fclose (fpOut);\r
2184   }\r
2185  \r
2186   VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME, GetUtilityStatus ());\r
2187   \r
2188   return GetUtilityStatus ();\r
2189 }\r
2190 \r
2191 STATIC\r
2192 EFI_STATUS\r
2193 ZeroDebugData (\r
2194   IN OUT UINT8   *FileBuffer\r
2195   )\r
2196 /*++\r
2197 \r
2198 Routine Description:\r
2199 \r
2200   Zero debug information in PeImage.\r
2201 \r
2202 Arguments:\r
2203 \r
2204   FileBuffer    - Pointer to PeImage.\r
2205 \r
2206 Returns:\r
2207 \r
2208   EFI_ABORTED   - PeImage is invalid.\r
2209   EFI_SUCCESS   - Zero debug data successfully.\r
2210 \r
2211 --*/\r
2212 {\r
2213   UINTN                           Index;\r
2214   UINTN                           DebugDirectoryEntryRva;\r
2215   UINTN                           DebugDirectoryEntryFileOffset;\r
2216   EFI_IMAGE_DOS_HEADER            *DosHdr;\r
2217   EFI_IMAGE_FILE_HEADER           *FileHdr;\r
2218   EFI_IMAGE_OPTIONAL_HEADER32     *Optional32Hdr;\r
2219   EFI_IMAGE_OPTIONAL_HEADER64     *Optional64Hdr;\r
2220   EFI_IMAGE_SECTION_HEADER        *SectionHeader;\r
2221   EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *DebugEntry;\r
2222    \r
2223   DosHdr   = (EFI_IMAGE_DOS_HEADER *)  FileBuffer;\r
2224   FileHdr  = (EFI_IMAGE_FILE_HEADER *) (FileBuffer + DosHdr->e_lfanew + sizeof (UINT32));\r
2225   DebugDirectoryEntryRva = 0;\r
2226 \r
2227   //\r
2228   // Get DebugEntryTable RVA address.\r
2229   //\r
2230   if (FileHdr->Machine == EFI_IMAGE_MACHINE_IA32) {\r
2231     Optional32Hdr = (EFI_IMAGE_OPTIONAL_HEADER32 *) ((UINT8*) FileHdr + sizeof (EFI_IMAGE_FILE_HEADER));\r
2232     SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) Optional32Hdr +  FileHdr->SizeOfOptionalHeader);\r
2233     if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG && \\r
2234         Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) {\r
2235       DebugDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;\r
2236     } else {\r
2237       //\r
2238       // No Debug Data, nothing to do.\r
2239       //\r
2240       return EFI_SUCCESS;\r
2241     }\r
2242   } else {\r
2243     Optional64Hdr = (EFI_IMAGE_OPTIONAL_HEADER64 *) ((UINT8*) FileHdr + sizeof (EFI_IMAGE_FILE_HEADER));\r
2244     SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) Optional64Hdr +  FileHdr->SizeOfOptionalHeader);\r
2245     if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG && \\r
2246         Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) {\r
2247       DebugDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;\r
2248     } else {\r
2249       //\r
2250       // No Debug Data, nothing to do.\r
2251       //\r
2252       return EFI_SUCCESS;\r
2253     }\r
2254   }\r
2255   \r
2256   //\r
2257   // Get DebugEntryTable file offset.\r
2258   //\r
2259   for (Index = 0; Index < FileHdr->NumberOfSections; Index ++, SectionHeader ++) {\r
2260     if (DebugDirectoryEntryRva >= SectionHeader->VirtualAddress &&\r
2261         DebugDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) {\r
2262         DebugDirectoryEntryFileOffset =\r
2263         DebugDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData;\r
2264       break;\r
2265     }\r
2266   }\r
2267   \r
2268   if (Index >= FileHdr->NumberOfSections) {\r
2269     Error (NULL, 0, 3000, "Invalid", "PeImage");\r
2270     return EFI_ABORTED;\r
2271   }\r
2272   \r
2273   //\r
2274   // Zero Debug Data and TimeStamp\r
2275   //\r
2276   DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) (FileBuffer + DebugDirectoryEntryFileOffset);\r
2277   DebugEntry->TimeDateStamp = 0;\r
2278   memset (FileBuffer + DebugEntry->FileOffset, 0, DebugEntry->SizeOfData);\r
2279   \r
2280   return EFI_SUCCESS;\r
2281 }\r
2282 \r
2283 STATIC \r
2284 EFI_STATUS\r
2285 SetStamp (\r
2286   IN OUT UINT8  *FileBuffer, \r
2287   IN     CHAR8  *TimeStamp\r
2288   )\r
2289 /*++\r
2290 \r
2291 Routine Description:\r
2292 \r
2293   Set new time stamp into PeImage FileHdr and Directory table: \r
2294   Debug, Export and Resource.\r
2295 \r
2296 Arguments:\r
2297 \r
2298   FileBuffer    - Pointer to PeImage.\r
2299   TimeStamp     - Time stamp string.\r
2300 \r
2301 Returns:\r
2302 \r
2303   EFI_INVALID_PARAMETER   - TimeStamp format is not recognized.\r
2304   EFI_SUCCESS             - Set new time stamp in this image successfully.\r
2305 \r
2306 --*/\r
2307 {\r
2308   struct tm                       stime;\r
2309   struct tm                       *ptime;\r
2310   time_t                          newtime;\r
2311   UINTN                           Index;\r
2312   UINTN                           DebugDirectoryEntryRva;\r
2313   UINTN                           DebugDirectoryEntryFileOffset;\r
2314   UINTN                           ExportDirectoryEntryRva;\r
2315   UINTN                           ExportDirectoryEntryFileOffset;\r
2316   UINTN                           ResourceDirectoryEntryRva;\r
2317   UINTN                           ResourceDirectoryEntryFileOffset;\r
2318   EFI_IMAGE_DOS_HEADER            *DosHdr;\r
2319   EFI_IMAGE_FILE_HEADER           *FileHdr;\r
2320   EFI_IMAGE_OPTIONAL_HEADER32     *Optional32Hdr;\r
2321   EFI_IMAGE_OPTIONAL_HEADER64     *Optional64Hdr;\r
2322   EFI_IMAGE_SECTION_HEADER        *SectionHeader;\r
2323   UINT32                          *NewTimeStamp;\r
2324   \r
2325   //\r
2326   // Init variable.\r
2327   //  \r
2328   DebugDirectoryEntryRva    = 0;\r
2329   ExportDirectoryEntryRva   = 0;\r
2330   ResourceDirectoryEntryRva = 0;\r
2331 \r
2332   //\r
2333   // Get time and date that will be set.\r
2334   //\r
2335   if (TimeStamp == NULL) {\r
2336     Error (NULL, 0, 3000, "Invalid", "TimeStamp cannot be NULL.");\r
2337     return EFI_INVALID_PARAMETER;\r
2338   }\r
2339   //\r
2340   // compare the value with "NOW", if yes, current system time is set.\r
2341   //\r
2342   if (stricmp (TimeStamp, "NOW") == 0) {\r
2343     //\r
2344     // get system current time and date\r
2345     //\r
2346     time (&newtime);\r
2347   } else {\r
2348     //\r
2349     // get the date and time from TimeStamp\r
2350     //\r
2351     if (sscanf (TimeStamp, "%d-%d-%d %d:%d:%d",\r
2352             &stime.tm_year,\r
2353             &stime.tm_mon,\r
2354             &stime.tm_mday,\r
2355             &stime.tm_hour,\r
2356             &stime.tm_min,\r
2357             &stime.tm_sec\r
2358             ) != 6) {\r
2359       Error (NULL, 0, 3000, "Invalid", "%s Invalid or unsupported datetime!", TimeStamp);\r
2360       return EFI_INVALID_PARAMETER;\r
2361     }\r
2362 \r
2363     //\r
2364     // in struct, Month (0 - 11; Jan = 0). So decrease 1 from it\r
2365     //\r
2366     if (stime.tm_mon <= 0 || stime.tm_mday <=0) {\r
2367       Error (NULL, 0, 3000, "Invalid", "%s Invalid date!", TimeStamp);\r
2368       return EFI_INVALID_PARAMETER;      \r
2369     }\r
2370     stime.tm_mon -= 1;\r
2371   \r
2372     //\r
2373     // in struct, Year (current year minus 1900)\r
2374     // and only the dates can be handled from Jan 1, 1970 to Jan 18, 2038\r
2375     //\r
2376     //\r
2377     // convert 0 -> 100 (2000), 1 -> 101 (2001), ..., 38 -> 138 (2038)\r
2378     //\r
2379     if (stime.tm_year >= 1970 && stime.tm_year <= 2038) {\r
2380       //\r
2381       // convert 1970 -> 70, 2000 -> 100, ...\r
2382       //\r
2383       stime.tm_year -= 1900;\r
2384     } else {\r
2385       Error (NULL, 0, 3000, "Invalid", "%s Invalid or unsupported datetime!", TimeStamp);\r
2386       return EFI_INVALID_PARAMETER;\r
2387     }\r
2388 \r
2389     //\r
2390     // convert the date and time to time_t format\r
2391     //\r
2392     newtime = mktime (&stime);\r
2393     if (newtime == (time_t) - 1) {\r
2394       Error (NULL, 0, 3000, "Invalid", "%s Invalid or unsupported datetime!", TimeStamp);\r
2395       return EFI_INVALID_PARAMETER;\r
2396     }\r
2397   }\r
2398   \r
2399   ptime = localtime (&newtime);\r
2400   DebugMsg (NULL, 0, 9, "New Image Time Stamp", "%04d-%02d-%02d %02d:%02d:%02d",\r
2401             ptime->tm_year + 1900, ptime->tm_mon + 1, ptime->tm_mday, ptime->tm_hour, ptime->tm_min, ptime->tm_sec); \r
2402   //\r
2403   // Set new time and data into PeImage.\r
2404   //\r
2405   DosHdr   = (EFI_IMAGE_DOS_HEADER *)  FileBuffer;\r
2406   FileHdr  = (EFI_IMAGE_FILE_HEADER *) (FileBuffer + DosHdr->e_lfanew + sizeof (UINT32));\r
2407   \r
2408   //\r
2409   // Get Debug, Export and Resource EntryTable RVA address.\r
2410   // Resource Directory entry need to review.\r
2411   //\r
2412   if (FileHdr->Machine == EFI_IMAGE_MACHINE_IA32) {\r
2413     Optional32Hdr = (EFI_IMAGE_OPTIONAL_HEADER32 *) ((UINT8*) FileHdr + sizeof (EFI_IMAGE_FILE_HEADER));\r
2414     SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) Optional32Hdr +  FileHdr->SizeOfOptionalHeader);\r
2415     if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXPORT && \\r
2416         Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].Size != 0) {\r
2417       ExportDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;\r
2418     }\r
2419     if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE && \\r
2420         Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size != 0) {\r
2421       ResourceDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;\r
2422     }\r
2423     if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG && \\r
2424         Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) {\r
2425       DebugDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;\r
2426     }\r
2427   } else {\r
2428     Optional64Hdr = (EFI_IMAGE_OPTIONAL_HEADER64 *) ((UINT8*) FileHdr + sizeof (EFI_IMAGE_FILE_HEADER));\r
2429     SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) Optional64Hdr +  FileHdr->SizeOfOptionalHeader);\r
2430     if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXPORT && \\r
2431         Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].Size != 0) {\r
2432       ExportDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;\r
2433     }\r
2434     if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE && \\r
2435         Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size != 0) {\r
2436       ResourceDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;\r
2437     }\r
2438     if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG && \\r
2439         Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) {\r
2440       DebugDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;\r
2441     }\r
2442   }\r
2443 \r
2444   //\r
2445   // Get DirectoryEntryTable file offset.\r
2446   //\r
2447   for (Index = 0; Index < FileHdr->NumberOfSections; Index ++, SectionHeader ++) {\r
2448     if (DebugDirectoryEntryRva >= SectionHeader->VirtualAddress &&\r
2449         DebugDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) {\r
2450         DebugDirectoryEntryFileOffset =\r
2451         DebugDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData;\r
2452     }\r
2453     if (ExportDirectoryEntryRva >= SectionHeader->VirtualAddress &&\r
2454         ExportDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) {\r
2455         ExportDirectoryEntryFileOffset =\r
2456         ExportDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData;\r
2457     }\r
2458     if (ResourceDirectoryEntryRva >= SectionHeader->VirtualAddress &&\r
2459         ResourceDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) {\r
2460         ResourceDirectoryEntryFileOffset =\r
2461         ResourceDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData;\r
2462     }\r
2463   }\r
2464   \r
2465   //\r
2466   // Set new stamp\r
2467   //\r
2468   FileHdr->TimeDateStamp = (UINT32) newtime;\r
2469 \r
2470   if (ExportDirectoryEntryRva != 0) {\r
2471     NewTimeStamp  = (UINT32 *) (FileBuffer + ExportDirectoryEntryFileOffset + sizeof (UINT32));\r
2472     *NewTimeStamp = (UINT32) newtime;\r
2473   }\r
2474 \r
2475   if (ResourceDirectoryEntryRva != 0) {\r
2476     NewTimeStamp  = (UINT32 *) (FileBuffer + ResourceDirectoryEntryFileOffset + sizeof (UINT32));\r
2477     *NewTimeStamp = (UINT32) newtime;\r
2478   }\r
2479 \r
2480   if (DebugDirectoryEntryRva != 0) {\r
2481     NewTimeStamp  = (UINT32 *) (FileBuffer + DebugDirectoryEntryFileOffset + sizeof (UINT32));\r
2482     *NewTimeStamp = (UINT32) newtime;\r
2483   }\r
2484   \r
2485   return EFI_SUCCESS;\r
2486 }\r
2487 \r
2488 STATIC\r
2489 STATUS\r
2490 MicrocodeReadData (\r
2491   FILE          *InFptr,\r
2492   UINTN         *Data\r
2493   )\r
2494 /*++\r
2495 \r
2496 Routine Description:\r
2497   Read a 32-bit microcode data value from a text file and convert to raw binary form.\r
2498 \r
2499 Arguments:\r
2500   InFptr    - file pointer to input text file\r
2501   Data      - pointer to where to return the data parsed\r
2502 \r
2503 Returns:\r
2504   STATUS_SUCCESS    - no errors or warnings, Data contains valid information\r
2505   STATUS_ERROR      - errors were encountered\r
2506 \r
2507 --*/\r
2508 {\r
2509   CHAR8  Line[MAX_LINE_LEN];\r
2510   CHAR8  *cptr;\r
2511   UINT8  ctr;\r
2512 \r
2513   Line[MAX_LINE_LEN - 1]  = 0;\r
2514   while (1) {\r
2515     if (fgets (Line, MAX_LINE_LEN, InFptr) == NULL) {\r
2516       return STATUS_ERROR;\r
2517     }\r
2518     //\r
2519     // If it was a binary file, then it may have overwritten our null terminator\r
2520     //\r
2521     if (Line[MAX_LINE_LEN - 1] != 0) {\r
2522       return STATUS_ERROR;\r
2523     }\r
2524     \r
2525     //\r
2526     // strip space\r
2527     // \r
2528     for (cptr = Line; *cptr && isspace(*cptr); cptr++) {\r
2529     }\r
2530     \r
2531     // Skip Blank Lines and Comment Lines\r
2532     if ((strlen(cptr) != 0) && (*cptr != ';')) {\r
2533       break;\r
2534     }\r
2535   }\r
2536 \r
2537   // Look for\r
2538   // dd 000000001h ; comment\r
2539   // dd XXXXXXXX\r
2540   // DD  XXXXXXXXX\r
2541   //  DD XXXXXXXXX\r
2542   //\r
2543   if ((tolower(cptr[0]) == 'd') && (tolower(cptr[1]) == 'd') && isspace (cptr[2])) {\r
2544     //\r
2545     // Skip blanks and look for a hex digit\r
2546     //\r
2547     cptr += 3;\r
2548     for (; *cptr && isspace(*cptr); cptr++) {\r
2549     }\r
2550     if (isxdigit (*cptr)) {\r
2551       if (sscanf (cptr, "%X", Data) != 1) {\r
2552         return STATUS_ERROR;\r
2553       }\r
2554     }\r
2555     return STATUS_SUCCESS;\r
2556   }\r
2557 \r
2558   return STATUS_ERROR;\r
2559 }\r