e29fcb2b83247caad235939085617b1f4e1f38d2
[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 action specified; specify -e, -c or -t!");\r
1286     goto Finish;\r
1287   }\r
1288 \r
1289   //\r
1290   // check input files\r
1291   //\r
1292   if (InputFileNum == 0) {\r
1293     Error (NULL, 0, 1001, "Missing option", "Input files");\r
1294     goto Finish;\r
1295   }\r
1296 \r
1297   //\r
1298   // Combine MciBinary files to one file\r
1299   //\r
1300   if ((OutImageType == FW_MERGE_IMAGE) && ReplaceFlag) {\r
1301     Error (NULL, 0, 1002, "Conflicting option", "-r replace option cannot be used with -j merge files option.");\r
1302     goto Finish;\r
1303   }\r
1304    \r
1305   //\r
1306   // Input image file\r
1307   //\r
1308   mInImageName = InputFileName [InputFileNum - 1];\r
1309   VerboseMsg ("the input file name is %s", mInImageName);\r
1310   \r
1311   //\r
1312   // Action will be taken for the input file.\r
1313   //\r
1314   switch (OutImageType) {\r
1315   case FW_EFI_IMAGE:\r
1316     VerboseMsg ("Create efi image on module type %s based on the input PE image.", ModuleType);\r
1317     break;\r
1318   case FW_TE_IMAGE:\r
1319     VerboseMsg ("Create Te Image based on the input PE image.");\r
1320     break;\r
1321   case FW_ACPI_IMAGE:\r
1322     VerboseMsg ("Get acpi table data from the input PE image.");\r
1323     break;\r
1324   case FW_RELOC_STRIPEED_IMAGE:\r
1325     VerboseMsg ("Remove relocation section from Pe or Te image.");\r
1326     break;\r
1327   case FW_BIN_IMAGE:\r
1328     VerboseMsg ("Convert the input EXE to the output BIN file.");\r
1329     break;\r
1330   case FW_ZERO_DEBUG_IMAGE:\r
1331     VerboseMsg ("Zero the Debug Data Fields in input PE image.");\r
1332     break;\r
1333   case FW_SET_STAMP_IMAGE:\r
1334     VerboseMsg ("Set new time stamp %s in the input PE image.", TimeStamp);\r
1335     break;\r
1336   case DUMP_TE_HEADER:\r
1337     VerboseMsg ("Dump the TE header information of the input TE image.");\r
1338     break;\r
1339   case FW_MCI_IMAGE:\r
1340     VerboseMsg ("Conver input MicroCode.txt file to MicroCode.bin file.");\r
1341     break;\r
1342   case FW_MERGE_IMAGE:\r
1343     VerboseMsg ("Combine the input multi microcode bin files to one bin file.");\r
1344     break;\r
1345   default:\r
1346     break;\r
1347   }\r
1348   \r
1349   if (ReplaceFlag) {\r
1350     VerboseMsg ("Overwrite the input file with the output content.");\r
1351   }\r
1352 \r
1353   //\r
1354   // Open output file and Write image into the output file.\r
1355   //\r
1356   if (OutImageName != NULL) {\r
1357     fpOut = fopen (OutImageName, "wb");\r
1358     if (!fpOut) {\r
1359       Error (NULL, 0, 0001, "Error opening file", OutImageName);\r
1360       goto Finish;\r
1361     }\r
1362     VerboseMsg ("Output file name is %s", OutImageName);\r
1363   } else if (!ReplaceFlag) {\r
1364     if (OutImageType == DUMP_TE_HEADER) {\r
1365       fpOut = stdout;\r
1366     } else {\r
1367       Error (NULL, 0, 1001, "Missing option", "output file");\r
1368       goto Finish;\r
1369     }\r
1370   }\r
1371 \r
1372   //\r
1373   // Combine MciBinary files to one file\r
1374   //\r
1375   if (OutImageType == FW_MERGE_IMAGE) {\r
1376     for (Index = 0; Index < InputFileNum; Index ++) {\r
1377       fpIn = fopen (InputFileName [Index], "rb");\r
1378       if (!fpIn) {\r
1379         Error (NULL, 0, 0001, "Error opening file", InputFileName [Index]);\r
1380         goto Finish;\r
1381       }\r
1382     \r
1383       FileLength = _filelength (fileno (fpIn));\r
1384       FileBuffer = malloc (FileLength);\r
1385       if (FileBuffer == NULL) {\r
1386         Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
1387         fclose (fpIn);\r
1388         goto Finish;\r
1389       }\r
1390       \r
1391       fread (FileBuffer, 1, FileLength, fpIn);\r
1392       fclose (fpIn);\r
1393       //\r
1394       // write input file to out file\r
1395       //\r
1396       fwrite (FileBuffer, 1, FileLength, fpOut);\r
1397       //\r
1398       // write pad value to out file.\r
1399       //\r
1400       while (FileLength ++ % MciAlignment != 0) {\r
1401         fwrite (&MciPadValue, 1, 1, fpOut);\r
1402       }\r
1403       //\r
1404       // free allocated memory space\r
1405       //\r
1406       free (FileBuffer);\r
1407       FileBuffer = NULL;\r
1408     }\r
1409     // \r
1410     // Done successfully\r
1411     //\r
1412     goto Finish;\r
1413   }\r
1414 \r
1415   //\r
1416   // Convert MicroCode.txt file to MicroCode.bin file\r
1417   //\r
1418   if (OutImageType == FW_MCI_IMAGE) {\r
1419     fpIn = fopen (mInImageName, "r");\r
1420     if (!fpIn) {\r
1421       Error (NULL, 0, 0001, "Error opening file", mInImageName);\r
1422       goto Finish;\r
1423     }\r
1424     \r
1425     //\r
1426     // The first pass is to determine \r
1427     // how much data is in the file so we can allocate a working buffer. \r
1428     //\r
1429     FileLength = 0;\r
1430     do {\r
1431       Status = MicrocodeReadData (fpIn, &Data);\r
1432       if (Status == STATUS_SUCCESS) {\r
1433         FileLength += sizeof (Data);\r
1434       }\r
1435       if (Status == STATUS_IGNORE) {\r
1436         Status = STATUS_SUCCESS;\r
1437       }\r
1438     } while (Status == STATUS_SUCCESS);\r
1439     //\r
1440     // Error if no data.\r
1441     //\r
1442     if (FileLength == 0) {\r
1443       Error (NULL, 0, 3000, "Invalid", "no parseable data found in file %s", mInImageName);\r
1444       goto Finish;\r
1445     }\r
1446     if (FileLength < sizeof (MICROCODE_IMAGE_HEADER)) {\r
1447       Error (NULL, 0, 3000, "Invalid", "amount of parseable data in %s is insufficient to contain a microcode header", mInImageName);\r
1448       goto Finish;\r
1449     }\r
1450 \r
1451     //\r
1452     // Allocate a buffer for the data\r
1453     //\r
1454     FileBuffer = malloc (FileLength);\r
1455     if (FileBuffer == NULL) {\r
1456       Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
1457       goto Finish;\r
1458     }\r
1459     //\r
1460     // Re-read the file, storing the data into our buffer\r
1461     //\r
1462     fseek (fpIn, 0, SEEK_SET);\r
1463     DataPointer = (UINTN *) FileBuffer;\r
1464     OldDataPointer = DataPointer;\r
1465     do {\r
1466       OldDataPointer = DataPointer;\r
1467       Status = MicrocodeReadData (fpIn, DataPointer++);\r
1468       if (Status == STATUS_IGNORE) {\r
1469         DataPointer = OldDataPointer;\r
1470         Status = STATUS_SUCCESS;\r
1471       }\r
1472     } while (Status == STATUS_SUCCESS);\r
1473     //\r
1474     // close input file after read data\r
1475     //\r
1476     fclose (fpIn);\r
1477 \r
1478     //\r
1479     // Can't do much checking on the header because, per the spec, the\r
1480     // DataSize field may be 0, which means DataSize = 2000 and TotalSize = 2K,\r
1481     // and the TotalSize field is invalid (actually missing). Thus we can't\r
1482     // even verify the Reserved fields are 0.\r
1483     //\r
1484     MciHeader = (MICROCODE_IMAGE_HEADER *) FileBuffer;\r
1485     if (MciHeader->DataSize == 0) {\r
1486       Index = 2048;\r
1487     } else {\r
1488       Index = MciHeader->TotalSize;\r
1489     }\r
1490 \r
1491     if (Index != FileLength) {\r
1492       Error (NULL, 0, 3000, "Invalid", "file length of %s (0x%x) does not equal expected TotalSize: 0x%04X.", mInImageName, FileLength, Index);\r
1493       goto Finish;\r
1494     }\r
1495 \r
1496     //\r
1497     // Checksum the contents\r
1498     //\r
1499     DataPointer = (UINTN *) FileBuffer;\r
1500     CheckSum  = 0;\r
1501     Index     = 0;\r
1502     while (Index < FileLength) {\r
1503       CheckSum    += *DataPointer;\r
1504       DataPointer ++;\r
1505       Index       += sizeof (UINTN);\r
1506     }\r
1507     if (CheckSum != 0) {\r
1508       Error (NULL, 0, 3000, "Invalid", "checksum (0x%x) failed on file %s.", CheckSum, mInImageName);\r
1509       goto Finish;\r
1510     }\r
1511     //\r
1512     // Open the output file and write the buffer contents\r
1513     //\r
1514     if (fpOut != NULL) {\r
1515       if (fwrite (FileBuffer, FileLength, 1, fpOut) != 1) {\r
1516         Error (NULL, 0, 0002, "Error writing file", OutImageName);\r
1517         goto Finish;\r
1518       }\r
1519     }\r
1520     \r
1521     if (ReplaceFlag) {\r
1522       fpInOut = fopen (mInImageName, "wb");\r
1523       if (fpInOut != NULL) {\r
1524         Error (NULL, 0, 0001, "Error opening file", mInImageName);\r
1525         goto Finish;\r
1526       }\r
1527       if (fwrite (FileBuffer, FileLength, 1, fpInOut) != 1) {\r
1528         Error (NULL, 0, 0002, "Error writing file", mInImageName);\r
1529         goto Finish;\r
1530       }\r
1531     }\r
1532     VerboseMsg ("the size of output file is %d bytes", FileLength);\r
1533     //\r
1534     //  Convert Mci.TXT to Mci.bin file successfully\r
1535     //\r
1536     goto Finish;\r
1537   }\r
1538 \r
1539   //\r
1540   // Open input file and read file data into file buffer.\r
1541   //\r
1542   fpIn = fopen (mInImageName, "rb");\r
1543   if (!fpIn) {\r
1544     Error (NULL, 0, 0001, "Error opening file", mInImageName);\r
1545     goto Finish;\r
1546   }\r
1547 \r
1548   FileLength = _filelength (fileno (fpIn));\r
1549   FileBuffer = malloc (FileLength);\r
1550   if (FileBuffer == NULL) {\r
1551     Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
1552     fclose (fpIn);\r
1553     goto Finish;\r
1554   }\r
1555   \r
1556   fread (FileBuffer, 1, FileLength, fpIn);\r
1557   fclose (fpIn);\r
1558   \r
1559   DebugMsg (NULL, 0, 9, "input file info", "the input file size is %d bytes", FileLength);\r
1560   \r
1561   //\r
1562   // Replace file\r
1563   //\r
1564   if (ReplaceFlag) {\r
1565     fpInOut = fopen (mInImageName, "wb");\r
1566     if (!fpInOut) {\r
1567       Error (NULL, 0, 0001, "Error opening file", mInImageName);\r
1568       goto Finish;\r
1569     }\r
1570   }\r
1571   //\r
1572   // Dump TeImage Header into output file.\r
1573   //\r
1574   if (OutImageType == DUMP_TE_HEADER) {\r
1575     memcpy (&TEImageHeader, FileBuffer, sizeof (TEImageHeader));\r
1576     if (TEImageHeader.Signature != EFI_TE_IMAGE_HEADER_SIGNATURE) {\r
1577       Error (NULL, 0, 3000, "Invalid", "TE header signature of file %s is not correct.", mInImageName);\r
1578       goto Finish;      \r
1579     }\r
1580     if (fpInOut != NULL) {\r
1581       fprintf (fpInOut, "Dump of file %s\n\n", mInImageName);\r
1582       fprintf (fpInOut, "TE IMAGE HEADER VALUES\n");\r
1583       fprintf (fpInOut, "%17X machine\n", TEImageHeader.Machine);\r
1584       fprintf (fpInOut, "%17X number of sections\n", TEImageHeader.NumberOfSections);\r
1585       fprintf (fpInOut, "%17X subsystems\n", TEImageHeader.Subsystem);\r
1586       fprintf (fpInOut, "%17X stripped size\n", TEImageHeader.StrippedSize);\r
1587       fprintf (fpInOut, "%17X entry point\n", TEImageHeader.AddressOfEntryPoint);\r
1588       fprintf (fpInOut, "%17X base of code\n", TEImageHeader.BaseOfCode);\r
1589       fprintf (fpInOut, "%17X image base\n", TEImageHeader.ImageBase);\r
1590       fprintf (fpInOut, "%17X [%8X] RVA [size] of Base Relocation Directory\n", TEImageHeader.DataDirectory[0].VirtualAddress, TEImageHeader.DataDirectory[0].Size);\r
1591       fprintf (fpInOut, "%17X [%8X] RVA [size] of Debug Directory\n", TEImageHeader.DataDirectory[1].VirtualAddress, TEImageHeader.DataDirectory[1].Size);\r
1592     }\r
1593 \r
1594     if (fpOut != NULL) {\r
1595       fprintf (fpOut, "Dump of file %s\n\n", mInImageName);\r
1596       fprintf (fpOut, "TE IMAGE HEADER VALUES\n");\r
1597       fprintf (fpOut, "%17X machine\n", TEImageHeader.Machine);\r
1598       fprintf (fpOut, "%17X number of sections\n", TEImageHeader.NumberOfSections);\r
1599       fprintf (fpOut, "%17X subsystems\n", TEImageHeader.Subsystem);\r
1600       fprintf (fpOut, "%17X stripped size\n", TEImageHeader.StrippedSize);\r
1601       fprintf (fpOut, "%17X entry point\n", TEImageHeader.AddressOfEntryPoint);\r
1602       fprintf (fpOut, "%17X base of code\n", TEImageHeader.BaseOfCode);\r
1603       fprintf (fpOut, "%17X image base\n", TEImageHeader.ImageBase);\r
1604       fprintf (fpOut, "%17X [%8X] RVA [size] of Base Relocation Directory\n", TEImageHeader.DataDirectory[0].VirtualAddress, TEImageHeader.DataDirectory[0].Size);\r
1605       fprintf (fpOut, "%17X [%8X] RVA [size] of Debug Directory\n", TEImageHeader.DataDirectory[1].VirtualAddress, TEImageHeader.DataDirectory[1].Size);\r
1606     }\r
1607     goto Finish;\r
1608   }\r
1609 \r
1610   //\r
1611   // Following code to convert dll to efi image or te image.\r
1612   // Get new image type\r
1613   //\r
1614   if ((OutImageType == FW_EFI_IMAGE) || (OutImageType == FW_TE_IMAGE)) {\r
1615     if (ModuleType == NULL) {\r
1616       if (OutImageType == FW_EFI_IMAGE) {\r
1617         Error (NULL, 0, 1001, "Missing option", "EFI_FILETYPE");\r
1618         goto Finish;\r
1619       } else if (OutImageType == FW_TE_IMAGE) {\r
1620         //\r
1621         // Default TE Image Type is Boot service driver\r
1622         //\r
1623         Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER;\r
1624         VerboseMsg ("Efi Image subsystem type is efi boot service driver.");\r
1625       }\r
1626     } else {\r
1627       if (stricmp (ModuleType, "BASE") == 0 ||\r
1628           stricmp (ModuleType, "SEC") == 0 ||\r
1629           stricmp (ModuleType, "SECURITY_CORE") == 0 ||\r
1630           stricmp (ModuleType, "PEI_CORE") == 0 ||\r
1631           stricmp (ModuleType, "PEIM") == 0 ||\r
1632           stricmp (ModuleType, "COMBINED_PEIM_DRIVER") == 0 ||\r
1633           stricmp (ModuleType, "PIC_PEIM") == 0 ||\r
1634           stricmp (ModuleType, "RELOCATABLE_PEIM") == 0 ||\r
1635           stricmp (ModuleType, "DXE_CORE") == 0 ||\r
1636           stricmp (ModuleType, "BS_DRIVER") == 0  ||\r
1637           stricmp (ModuleType, "DXE_DRIVER") == 0 ||\r
1638           stricmp (ModuleType, "DXE_SMM_DRIVER") == 0  ||\r
1639           stricmp (ModuleType, "UEFI_DRIVER") == 0) {\r
1640         Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER;\r
1641         VerboseMsg ("Efi Image subsystem type is efi boot service driver.");\r
1642     \r
1643       } else if (stricmp (ModuleType, "UEFI_APPLICATION") == 0 || \r
1644                  stricmp (ModuleType, "APPLICATION") == 0) {\r
1645         Type = EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION;\r
1646         VerboseMsg ("Efi Image subsystem type is efi application.");\r
1647     \r
1648       } else if (stricmp (ModuleType, "DXE_RUNTIME_DRIVER") == 0 || \r
1649                  stricmp (ModuleType, "RT_DRIVER") == 0) {\r
1650         Type = EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER;\r
1651         VerboseMsg ("Efi Image subsystem type is efi runtime driver.");\r
1652     \r
1653       } else if (stricmp (ModuleType, "DXE_SAL_DRIVER") == 0 || \r
1654                  stricmp (ModuleType, "SAL_RT_DRIVER") == 0) {\r
1655         Type = EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER;\r
1656         VerboseMsg ("Efi Image subsystem type is efi sal runtime driver.");\r
1657     \r
1658       } else {\r
1659         Error (NULL, 0, 1003, "Invalid option value", "EFI_FILETYPE = %s", ModuleType);\r
1660         goto Finish;\r
1661       }\r
1662     }\r
1663   }\r
1664 \r
1665   //\r
1666   // Convert EFL image to PeImage\r
1667   //\r
1668 #ifdef HAVE_ELF\r
1669   if (IsElfHeader(FileBuffer)) {\r
1670     VerboseMsg ("Convert the input ELF Image to Pe Image");\r
1671     ConvertElf(&FileBuffer, &FileLength);\r
1672   }\r
1673 #endif\r
1674   \r
1675   //\r
1676   // Remove reloc section from PE or TE image\r
1677   //\r
1678   if (OutImageType == FW_RELOC_STRIPEED_IMAGE) {\r
1679     //\r
1680     // Check TeImage\r
1681     //\r
1682     TeHdr = (EFI_TE_IMAGE_HEADER *) FileBuffer;\r
1683     if (TeHdr->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {\r
1684       SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (TeHdr + 1);\r
1685       for (Index = 0; Index < TeHdr->NumberOfSections; Index ++, SectionHeader ++) {\r
1686         if (strcmp (SectionHeader->Name, ".reloc") == 0) {\r
1687           //\r
1688           // Check the reloc section is in the end of image.\r
1689           //\r
1690           if ((SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData) == \r
1691             (FileLength + TeHdr->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER))) {\r
1692             //\r
1693             // Remove .reloc section and update TeImage Header\r
1694             //\r
1695             FileLength = FileLength - SectionHeader->SizeOfRawData;\r
1696             SectionHeader->SizeOfRawData = 0;\r
1697             SectionHeader->Misc.VirtualSize = 0;\r
1698             TeHdr->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = 0;\r
1699             TeHdr->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size           = 0;\r
1700             break;\r
1701           }\r
1702         }\r
1703       }\r
1704     } else {\r
1705       //\r
1706       // Check PE Image\r
1707       //\r
1708       DosHdr = (EFI_IMAGE_DOS_HEADER *) FileBuffer;\r
1709       if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {\r
1710         Error (NULL, 0, 3000, "Invalid", "TE and DOS header signatures were not found in %s image.", mInImageName);\r
1711         goto Finish;\r
1712       }\r
1713       PeHdr = (EFI_IMAGE_NT_HEADERS *)(FileBuffer + DosHdr->e_lfanew);\r
1714       if (PeHdr->Signature != EFI_IMAGE_NT_SIGNATURE) {\r
1715         Error (NULL, 0, 3000, "Invalid", "PE header signature was not found in %s image.", mInImageName);\r
1716         goto Finish;\r
1717       }\r
1718       SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->OptionalHeader) + PeHdr->FileHeader.SizeOfOptionalHeader);\r
1719       for (Index = 0; Index < PeHdr->FileHeader.NumberOfSections; Index ++, SectionHeader ++) {\r
1720         if (strcmp (SectionHeader->Name, ".reloc") == 0) {\r
1721           //\r
1722           // Check the reloc section is in the end of image.\r
1723           //\r
1724           if ((SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData) == FileLength) {\r
1725             //\r
1726             // Remove .reloc section and update PeImage Header\r
1727             //\r
1728             FileLength = FileLength - SectionHeader->SizeOfRawData;\r
1729 \r
1730             PeHdr->FileHeader.Characteristics |= EFI_IMAGE_FILE_RELOCS_STRIPPED;\r
1731             if (PeHdr->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
1732               Optional32 = (EFI_IMAGE_OPTIONAL_HEADER32 *)&PeHdr->OptionalHeader;\r
1733               Optional32->SizeOfImage -= SectionHeader->SizeOfRawData;\r
1734               Optional32->SizeOfInitializedData -= SectionHeader->SizeOfRawData;\r
1735               if (Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {\r
1736                 Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = 0;\r
1737                 Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = 0;\r
1738               }\r
1739             }\r
1740             if (PeHdr->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
1741               Optional64 = (EFI_IMAGE_OPTIONAL_HEADER64 *)&PeHdr->OptionalHeader;\r
1742               Optional64->SizeOfImage -= SectionHeader->SizeOfRawData;\r
1743               Optional64->SizeOfInitializedData -= SectionHeader->SizeOfRawData;\r
1744               if (Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {\r
1745                 Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = 0;\r
1746                 Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = 0;\r
1747               }\r
1748             }\r
1749             SectionHeader->Misc.VirtualSize = 0;\r
1750             SectionHeader->SizeOfRawData = 0;\r
1751             break;\r
1752           }\r
1753         }\r
1754       }\r
1755     }\r
1756     //\r
1757     // Write file\r
1758     //\r
1759     goto WriteFile;\r
1760   }\r
1761   //\r
1762   // Read the dos & pe hdrs of the image\r
1763   //\r
1764   DosHdr = (EFI_IMAGE_DOS_HEADER *)FileBuffer;\r
1765   if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {\r
1766     Error (NULL, 0, 3000, "Invalid", "DOS header signature was not found in %s image.", mInImageName);\r
1767     goto Finish;\r
1768   }\r
1769 \r
1770   PeHdr = (EFI_IMAGE_NT_HEADERS *)(FileBuffer + DosHdr->e_lfanew);\r
1771   if (PeHdr->Signature != EFI_IMAGE_NT_SIGNATURE) {\r
1772     Error (NULL, 0, 3000, "Invalid", "PE header signature was not found in %s image.", mInImageName);\r
1773     goto Finish;\r
1774   }\r
1775   \r
1776   //\r
1777   // Extract bin data from Pe image.\r
1778   //\r
1779   if (OutImageType == FW_BIN_IMAGE) {\r
1780     if (FileLength < PeHdr->OptionalHeader.SizeOfHeaders) {\r
1781       Error (NULL, 0, 3000, "Invalid", "FileSize of %s is not a legal size.", mInImageName);\r
1782       goto Finish;\r
1783     }\r
1784     //\r
1785     // Output bin data from exe file\r
1786     //\r
1787     if (fpOut != NULL) {\r
1788       fwrite (FileBuffer + PeHdr->OptionalHeader.SizeOfHeaders, 1, FileLength - PeHdr->OptionalHeader.SizeOfHeaders, fpOut);\r
1789     }\r
1790     if (fpInOut != NULL) {\r
1791       fwrite (FileBuffer + PeHdr->OptionalHeader.SizeOfHeaders, 1, FileLength - PeHdr->OptionalHeader.SizeOfHeaders, fpInOut);\r
1792     }\r
1793     VerboseMsg ("the size of output file is %d bytes", FileLength - PeHdr->OptionalHeader.SizeOfHeaders);\r
1794     goto Finish;\r
1795   }\r
1796 \r
1797   //\r
1798   // Zero Debug Information of Pe Image\r
1799   //\r
1800   if (OutImageType == FW_ZERO_DEBUG_IMAGE) {\r
1801     Status = ZeroDebugData (FileBuffer);\r
1802     if (EFI_ERROR (Status)) {\r
1803       Error (NULL, 0, 3000, "Invalid", "Zero DebugData Error status is 0x%lx", (UINTN) Status);\r
1804       goto Finish;\r
1805     }\r
1806     \r
1807     if (fpOut != NULL) {\r
1808       fwrite (FileBuffer, 1, FileLength, fpOut);\r
1809     }\r
1810     if (fpInOut != NULL) {\r
1811       fwrite (FileBuffer, 1, FileLength, fpInOut);\r
1812     }\r
1813     VerboseMsg ("the size of output file is %d bytes", FileLength);\r
1814     goto Finish; \r
1815   }\r
1816 \r
1817   //\r
1818   // Set Time Stamp of Pe Image\r
1819   //\r
1820   if (OutImageType == FW_SET_STAMP_IMAGE) {\r
1821     Status = SetStamp (FileBuffer, TimeStamp);\r
1822     if (EFI_ERROR (Status)) {\r
1823       Error (NULL, 0, 3000, "Invalid", "SetStamp Error status is 0x%lx", (UINTN) Status);\r
1824       goto Finish;\r
1825     }\r
1826     \r
1827     if (fpOut != NULL) {\r
1828       fwrite (FileBuffer, 1, FileLength, fpOut);  \r
1829     }\r
1830     if (fpInOut != NULL) {\r
1831       fwrite (FileBuffer, 1, FileLength, fpInOut);\r
1832     }\r
1833     VerboseMsg ("the size of output file is %d bytes", FileLength);\r
1834     goto Finish;\r
1835   }\r
1836 \r
1837   //\r
1838   // Extract acpi data from pe image.\r
1839   //\r
1840   if (OutImageType == FW_ACPI_IMAGE) {\r
1841     SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->OptionalHeader) + PeHdr->FileHeader.SizeOfOptionalHeader); \r
1842     for (Index = 0; Index < PeHdr->FileHeader.NumberOfSections; Index ++, SectionHeader ++) {\r
1843       if (strcmp (SectionHeader->Name, ".data") == 0 || strcmp (SectionHeader->Name, ".sdata") == 0) {\r
1844         //\r
1845         // Check Acpi Table\r
1846         //\r
1847         if (SectionHeader->Misc.VirtualSize < SectionHeader->SizeOfRawData) {\r
1848           FileLength = SectionHeader->Misc.VirtualSize;\r
1849         } else {\r
1850           FileLength = SectionHeader->SizeOfRawData;\r
1851         }\r
1852 \r
1853         if (CheckAcpiTable (FileBuffer + SectionHeader->PointerToRawData, FileLength) != STATUS_SUCCESS) {\r
1854           Error (NULL, 0, 3000, "Invalid", "ACPI table check failed in %s.", mInImageName);\r
1855           goto Finish;\r
1856         }\r
1857         \r
1858         //\r
1859         // Output Apci data to file\r
1860         //\r
1861         if (fpOut != NULL) {\r
1862           fwrite (FileBuffer + SectionHeader->PointerToRawData, 1, FileLength, fpOut);\r
1863         }\r
1864         if (fpInOut != NULL) {\r
1865           fwrite (FileBuffer + SectionHeader->PointerToRawData, 1, FileLength, fpInOut);\r
1866         }\r
1867         VerboseMsg ("the size of output file is %d bytes", FileLength);\r
1868         goto Finish;\r
1869       }\r
1870     }\r
1871     Error (NULL, 0, 3000, "Invalid", "failed to get ACPI table from %s.", mInImageName);\r
1872     goto Finish;\r
1873   }\r
1874   //\r
1875   // Zero all unused fields of the DOS header\r
1876   //\r
1877   memcpy (&BackupDosHdr, DosHdr, sizeof (EFI_IMAGE_DOS_HEADER));\r
1878   memset (DosHdr, 0, sizeof (EFI_IMAGE_DOS_HEADER));\r
1879   DosHdr->e_magic  = BackupDosHdr.e_magic;\r
1880   DosHdr->e_lfanew = BackupDosHdr.e_lfanew;\r
1881 \r
1882   for (Index = sizeof (EFI_IMAGE_DOS_HEADER); Index < (UINT32 ) DosHdr->e_lfanew; Index++) {\r
1883     FileBuffer[Index] = DosHdr->e_cp;\r
1884   }\r
1885   \r
1886   //\r
1887   // Initialize TeImage Header\r
1888   //\r
1889   memset (&TEImageHeader, 0, sizeof (EFI_TE_IMAGE_HEADER));\r
1890   TEImageHeader.Signature        = EFI_TE_IMAGE_HEADER_SIGNATURE;\r
1891   TEImageHeader.Machine          = PeHdr->FileHeader.Machine;\r
1892   TEImageHeader.NumberOfSections = (UINT8) PeHdr->FileHeader.NumberOfSections;\r
1893   TEImageHeader.StrippedSize     = (UINT16) ((UINTN) ((UINT8 *) &(PeHdr->OptionalHeader) + PeHdr->FileHeader.SizeOfOptionalHeader) - (UINTN) FileBuffer);\r
1894   TEImageHeader.Subsystem        = (UINT8) Type;\r
1895 \r
1896   //\r
1897   // Patch the PE header\r
1898   //\r
1899   PeHdr->OptionalHeader.Subsystem = (UINT16) Type;\r
1900 \r
1901   if (PeHdr->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
1902     Optional32 = (EFI_IMAGE_OPTIONAL_HEADER32 *)&PeHdr->OptionalHeader;\r
1903     Optional32->MajorLinkerVersion          = 0;\r
1904     Optional32->MinorLinkerVersion          = 0;\r
1905     Optional32->MajorOperatingSystemVersion = 0;\r
1906     Optional32->MinorOperatingSystemVersion = 0;\r
1907     Optional32->MajorImageVersion           = 0;\r
1908     Optional32->MinorImageVersion           = 0;\r
1909     Optional32->MajorSubsystemVersion       = 0;\r
1910     Optional32->MinorSubsystemVersion       = 0;\r
1911     Optional32->Win32VersionValue           = 0;\r
1912     Optional32->CheckSum                    = 0;\r
1913     Optional32->SizeOfStackReserve = 0;\r
1914     Optional32->SizeOfStackCommit  = 0;\r
1915     Optional32->SizeOfHeapReserve  = 0;\r
1916     Optional32->SizeOfHeapCommit   = 0;\r
1917     \r
1918     TEImageHeader.AddressOfEntryPoint = Optional32->AddressOfEntryPoint;\r
1919     TEImageHeader.BaseOfCode          = Optional32->BaseOfCode;\r
1920     TEImageHeader.ImageBase           = (UINT64) (Optional32->ImageBase);\r
1921 \r
1922     if (Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {\r
1923       TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;\r
1924       TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;\r
1925     }\r
1926 \r
1927     if (Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {\r
1928       TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;\r
1929       TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size;\r
1930     }\r
1931 \r
1932     //\r
1933     // Zero .pdata section data.\r
1934     //\r
1935     if (!KeepExceptionTableFlag && Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION &&\r
1936         Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress != 0 && \r
1937         Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size != 0) {\r
1938       SectionHeader = (EFI_IMAGE_SECTION_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof(UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + PeHdr->FileHeader.SizeOfOptionalHeader);\r
1939       for (Index = 0; Index < PeHdr->FileHeader.NumberOfSections; Index++, SectionHeader++) {\r
1940         if (SectionHeader->VirtualAddress == Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress) {\r
1941           //\r
1942           // Zero .pdata Section data\r
1943           //\r
1944           memset (FileBuffer + SectionHeader->PointerToRawData, 0, SectionHeader->SizeOfRawData);\r
1945           //\r
1946           // Zero .pdata Section header name\r
1947           //\r
1948           memset (SectionHeader->Name, 0, sizeof (SectionHeader->Name));\r
1949           //\r
1950           // Zero Execption Table\r
1951           //\r
1952           Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress = 0;\r
1953           Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size           = 0;\r
1954           DebugMsg (NULL, 0, 9, "Zero the .pdata section for PE image", NULL);\r
1955           break;\r
1956         }\r
1957       }\r
1958     }\r
1959 \r
1960     //\r
1961     // Strip zero padding at the end of the .reloc section \r
1962     //\r
1963     if (!KeepZeroPendingFlag && Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {\r
1964       if (Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size != 0) {\r
1965         SectionHeader = (EFI_IMAGE_SECTION_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof(UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + PeHdr->FileHeader.SizeOfOptionalHeader);\r
1966         for (Index = 0; Index < PeHdr->FileHeader.NumberOfSections; Index++, SectionHeader++) {\r
1967           //\r
1968           // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory\r
1969           //\r
1970           if (SectionHeader->VirtualAddress == Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress) {\r
1971             SectionHeader->Misc.VirtualSize = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;\r
1972             AllignedRelocSize = (Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size + Optional32->FileAlignment - 1) & (~(Optional32->FileAlignment - 1));\r
1973             //\r
1974             // Check to see if there is zero padding at the end of the base relocations\r
1975             //\r
1976             if (AllignedRelocSize < SectionHeader->SizeOfRawData) {\r
1977               //\r
1978               // Check to see if the base relocations are at the end of the file\r
1979               //\r
1980               if (SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData == Optional32->SizeOfImage) {\r
1981                 //\r
1982                 // All the required conditions are met to strip the zero padding of the end of the base relocations section\r
1983                 //\r
1984                 Optional32->SizeOfImage -= (SectionHeader->SizeOfRawData - AllignedRelocSize);\r
1985                 Optional32->SizeOfInitializedData -= (SectionHeader->SizeOfRawData - AllignedRelocSize);\r
1986                 SectionHeader->SizeOfRawData = AllignedRelocSize;\r
1987                 FileLength = Optional32->SizeOfImage;\r
1988                 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
1989               }\r
1990             }\r
1991           }\r
1992         }\r
1993       }\r
1994     }\r
1995   } else if (PeHdr->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
1996     Optional64 = (EFI_IMAGE_OPTIONAL_HEADER64 *)&PeHdr->OptionalHeader;\r
1997     Optional64->MajorLinkerVersion          = 0;\r
1998     Optional64->MinorLinkerVersion          = 0;\r
1999     Optional64->MajorOperatingSystemVersion = 0;\r
2000     Optional64->MinorOperatingSystemVersion = 0;\r
2001     Optional64->MajorImageVersion           = 0;\r
2002     Optional64->MinorImageVersion           = 0;\r
2003     Optional64->MajorSubsystemVersion       = 0;\r
2004     Optional64->MinorSubsystemVersion       = 0;\r
2005     Optional64->Win32VersionValue           = 0;\r
2006     Optional64->CheckSum                    = 0;\r
2007     Optional64->SizeOfStackReserve = 0;\r
2008     Optional64->SizeOfStackCommit  = 0;\r
2009     Optional64->SizeOfHeapReserve  = 0;\r
2010     Optional64->SizeOfHeapCommit   = 0;\r
2011 \r
2012     TEImageHeader.AddressOfEntryPoint = Optional64->AddressOfEntryPoint;\r
2013     TEImageHeader.BaseOfCode          = Optional64->BaseOfCode;\r
2014     TEImageHeader.ImageBase           = (UINT64) (Optional64->ImageBase);\r
2015 \r
2016     if (Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {\r
2017       TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;\r
2018       TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;\r
2019     }\r
2020 \r
2021     if (Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {\r
2022       TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;\r
2023       TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size;\r
2024     }\r
2025 \r
2026     //\r
2027     // Zero the .pdata section for X64 machine and don't check the Debug Directory is empty\r
2028     // For Itaninum and X64 Image, remove .pdata section.\r
2029     //\r
2030     if (!KeepExceptionTableFlag && PeHdr->FileHeader.Machine == IMAGE_FILE_MACHINE_X64 || PeHdr->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64) {\r
2031       if (Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION &&\r
2032           Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress != 0 && \r
2033           Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size != 0) {\r
2034         //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
2035         SectionHeader = (EFI_IMAGE_SECTION_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof(UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + PeHdr->FileHeader.SizeOfOptionalHeader);\r
2036         for (Index = 0; Index < PeHdr->FileHeader.NumberOfSections; Index++, SectionHeader++) {\r
2037           if (SectionHeader->VirtualAddress == Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress) {\r
2038             //\r
2039             // Zero .pdata Section header name\r
2040             //\r
2041             memset (SectionHeader->Name, 0, sizeof (SectionHeader->Name));\r
2042 \r
2043             RuntimeFunction = (RUNTIME_FUNCTION *)(FileBuffer + SectionHeader->PointerToRawData);\r
2044             for (Index1 = 0; Index1 < Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size / sizeof (RUNTIME_FUNCTION); Index1++, RuntimeFunction++) {\r
2045               SectionHeader = (EFI_IMAGE_SECTION_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof(UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + PeHdr->FileHeader.SizeOfOptionalHeader);\r
2046               for (Index2 = 0; Index2 < PeHdr->FileHeader.NumberOfSections; Index2++, SectionHeader++) {\r
2047                 if (RuntimeFunction->UnwindInfoAddress > SectionHeader->VirtualAddress && RuntimeFunction->UnwindInfoAddress < (SectionHeader->VirtualAddress + SectionHeader->SizeOfRawData)) {\r
2048                   UnwindInfo = (UNWIND_INFO *)(FileBuffer + SectionHeader->PointerToRawData + (RuntimeFunction->UnwindInfoAddress - SectionHeader->VirtualAddress));\r
2049                   if (UnwindInfo->Version == 1) {\r
2050                     memset (UnwindInfo + 1, 0, UnwindInfo->CountOfUnwindCodes * sizeof (UINT16));\r
2051                     memset (UnwindInfo, 0, sizeof (UNWIND_INFO));\r
2052                   }\r
2053                 }\r
2054               }\r
2055               memset (RuntimeFunction, 0, sizeof (RUNTIME_FUNCTION));\r
2056             }\r
2057             //\r
2058             // Zero Execption Table\r
2059             //\r
2060             Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size = 0;\r
2061             Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress = 0;\r
2062             DebugMsg (NULL, 0, 9, "Zero the .pdata section if the machine type is X64 for PE32+ image", NULL);\r
2063             break;\r
2064           }\r
2065         }\r
2066       }\r
2067     }\r
2068 \r
2069     //\r
2070     // Strip zero padding at the end of the .reloc section \r
2071     //\r
2072     if (!KeepZeroPendingFlag && Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {\r
2073       if (Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size != 0) {\r
2074         SectionHeader = (EFI_IMAGE_SECTION_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof(UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + PeHdr->FileHeader.SizeOfOptionalHeader);\r
2075         for (Index = 0; Index < PeHdr->FileHeader.NumberOfSections; Index++, SectionHeader++) {\r
2076           //\r
2077           // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory\r
2078           //\r
2079           if (SectionHeader->VirtualAddress == Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress) {\r
2080             SectionHeader->Misc.VirtualSize = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;\r
2081             AllignedRelocSize = (Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size + Optional64->FileAlignment - 1) & (~(Optional64->FileAlignment - 1));\r
2082             //\r
2083             // Check to see if there is zero padding at the end of the base relocations\r
2084             //\r
2085             if (AllignedRelocSize < SectionHeader->SizeOfRawData) {\r
2086               //\r
2087               // Check to see if the base relocations are at the end of the file\r
2088               //\r
2089               if (SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData == Optional64->SizeOfImage) {\r
2090                 //\r
2091                 // All the required conditions are met to strip the zero padding of the end of the base relocations section\r
2092                 //\r
2093                 Optional64->SizeOfImage -= (SectionHeader->SizeOfRawData - AllignedRelocSize);\r
2094                 Optional64->SizeOfInitializedData -= (SectionHeader->SizeOfRawData - AllignedRelocSize);\r
2095                 SectionHeader->SizeOfRawData = AllignedRelocSize;\r
2096                 FileLength = Optional64->SizeOfImage;\r
2097                 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
2098               }\r
2099             }\r
2100           }\r
2101         }\r
2102       }\r
2103     }\r
2104   } else {\r
2105     Error (NULL, 0, 3000, "Invalid", "Magic 0x%x of PeImage %s is unknown.", PeHdr->OptionalHeader.Magic, mInImageName);\r
2106     goto Finish;\r
2107   }\r
2108 \r
2109   if (OutImageType == FW_TE_IMAGE) {\r
2110     if ((PeHdr->FileHeader.NumberOfSections &~0xFF) || (Type &~0xFF)) {\r
2111       //\r
2112       // Pack the subsystem and NumberOfSections into 1 byte. Make sure they fit both.\r
2113       //\r
2114       Error (NULL, 0, 3000, "Invalid", "Image's subsystem or NumberOfSections of PeImage %s cannot be packed into 1 byte.", mInImageName);\r
2115       goto Finish;\r
2116     }\r
2117 \r
2118     if ((PeHdr->OptionalHeader.SectionAlignment != PeHdr->OptionalHeader.FileAlignment)) {\r
2119       //\r
2120       // TeImage has the same section alignment and file alignment.\r
2121       //\r
2122       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
2123       goto Finish;\r
2124     }\r
2125     \r
2126     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
2127               TEImageHeader.Machine, TEImageHeader.NumberOfSections, TEImageHeader.StrippedSize, TEImageHeader.AddressOfEntryPoint, TEImageHeader.BaseOfCode, TEImageHeader.ImageBase);\r
2128     //\r
2129     // Update Image to TeImage\r
2130     //\r
2131     if (fpOut != NULL) {\r
2132       fwrite (&TEImageHeader, 1, sizeof (EFI_TE_IMAGE_HEADER), fpOut);\r
2133       fwrite (FileBuffer + TEImageHeader.StrippedSize, 1, FileLength - TEImageHeader.StrippedSize, fpOut);\r
2134     }\r
2135     if (fpInOut != NULL) {\r
2136       fwrite (&TEImageHeader, 1, sizeof (EFI_TE_IMAGE_HEADER), fpInOut);\r
2137       fwrite (FileBuffer + TEImageHeader.StrippedSize, 1, FileLength - TEImageHeader.StrippedSize, fpInOut);\r
2138     }\r
2139     VerboseMsg ("the size of output file is %d bytes", FileLength - TEImageHeader.StrippedSize);\r
2140     goto Finish;\r
2141   }\r
2142 WriteFile:\r
2143   //\r
2144   // Update Image to EfiImage\r
2145   //\r
2146   if (fpOut != NULL) {\r
2147     fwrite (FileBuffer, 1, FileLength, fpOut);\r
2148   }\r
2149   if (fpInOut != NULL) {\r
2150     fwrite (FileBuffer, 1, FileLength, fpInOut);\r
2151   }\r
2152   VerboseMsg ("the size of output file is %d bytes", FileLength);\r
2153 \r
2154 Finish:\r
2155   if (fpInOut != NULL) {\r
2156     if (GetUtilityStatus () != STATUS_SUCCESS) {\r
2157       //\r
2158       // when file updates failed, original file is still recoveried.\r
2159       //\r
2160       fwrite (FileBuffer, 1, FileLength, fpInOut);\r
2161     }\r
2162     //\r
2163     // Write converted data into fpInOut file and close input file.\r
2164     //\r
2165     fclose (fpInOut);\r
2166   }\r
2167 \r
2168   if (FileBuffer != NULL) {\r
2169     free (FileBuffer);\r
2170   }\r
2171   \r
2172   if (InputFileName != NULL) {\r
2173     free (InputFileName);\r
2174   }\r
2175 \r
2176   if (fpOut != NULL) {\r
2177     //\r
2178     // Write converted data into fpOut file and close output file.\r
2179     //\r
2180     fclose (fpOut);\r
2181   }\r
2182  \r
2183   VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME, GetUtilityStatus ());\r
2184   \r
2185   return GetUtilityStatus ();\r
2186 }\r
2187 \r
2188 STATIC\r
2189 EFI_STATUS\r
2190 ZeroDebugData (\r
2191   IN OUT UINT8   *FileBuffer\r
2192   )\r
2193 /*++\r
2194 \r
2195 Routine Description:\r
2196 \r
2197   Zero debug information in PeImage.\r
2198 \r
2199 Arguments:\r
2200 \r
2201   FileBuffer    - Pointer to PeImage.\r
2202 \r
2203 Returns:\r
2204 \r
2205   EFI_ABORTED   - PeImage is invalid.\r
2206   EFI_SUCCESS   - Zero debug data successfully.\r
2207 \r
2208 --*/\r
2209 {\r
2210   UINTN                           Index;\r
2211   UINTN                           DebugDirectoryEntryRva;\r
2212   UINTN                           DebugDirectoryEntryFileOffset;\r
2213   EFI_IMAGE_DOS_HEADER            *DosHdr;\r
2214   EFI_IMAGE_FILE_HEADER           *FileHdr;\r
2215   EFI_IMAGE_OPTIONAL_HEADER32     *Optional32Hdr;\r
2216   EFI_IMAGE_OPTIONAL_HEADER64     *Optional64Hdr;\r
2217   EFI_IMAGE_SECTION_HEADER        *SectionHeader;\r
2218   EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *DebugEntry;\r
2219    \r
2220   DosHdr   = (EFI_IMAGE_DOS_HEADER *)  FileBuffer;\r
2221   FileHdr  = (EFI_IMAGE_FILE_HEADER *) (FileBuffer + DosHdr->e_lfanew + sizeof (UINT32));\r
2222   DebugDirectoryEntryRva = 0;\r
2223 \r
2224   //\r
2225   // Get DebugEntryTable RVA address.\r
2226   //\r
2227   if (FileHdr->Machine == EFI_IMAGE_MACHINE_IA32) {\r
2228     Optional32Hdr = (EFI_IMAGE_OPTIONAL_HEADER32 *) ((UINT8*) FileHdr + sizeof (EFI_IMAGE_FILE_HEADER));\r
2229     SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) Optional32Hdr +  FileHdr->SizeOfOptionalHeader);\r
2230     if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG && \\r
2231         Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) {\r
2232       DebugDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;\r
2233     } else {\r
2234       //\r
2235       // No Debug Data, nothing to do.\r
2236       //\r
2237       return EFI_SUCCESS;\r
2238     }\r
2239   } else {\r
2240     Optional64Hdr = (EFI_IMAGE_OPTIONAL_HEADER64 *) ((UINT8*) FileHdr + sizeof (EFI_IMAGE_FILE_HEADER));\r
2241     SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) Optional64Hdr +  FileHdr->SizeOfOptionalHeader);\r
2242     if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG && \\r
2243         Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) {\r
2244       DebugDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;\r
2245     } else {\r
2246       //\r
2247       // No Debug Data, nothing to do.\r
2248       //\r
2249       return EFI_SUCCESS;\r
2250     }\r
2251   }\r
2252   \r
2253   //\r
2254   // Get DebugEntryTable file offset.\r
2255   //\r
2256   for (Index = 0; Index < FileHdr->NumberOfSections; Index ++, SectionHeader ++) {\r
2257     if (DebugDirectoryEntryRva >= SectionHeader->VirtualAddress &&\r
2258         DebugDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) {\r
2259         DebugDirectoryEntryFileOffset =\r
2260         DebugDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData;\r
2261       break;\r
2262     }\r
2263   }\r
2264   \r
2265   if (Index >= FileHdr->NumberOfSections) {\r
2266     Error (NULL, 0, 3000, "Invalid", "PeImage");\r
2267     return EFI_ABORTED;\r
2268   }\r
2269   \r
2270   //\r
2271   // Zero Debug Data and TimeStamp\r
2272   //\r
2273   DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) (FileBuffer + DebugDirectoryEntryFileOffset);\r
2274   DebugEntry->TimeDateStamp = 0;\r
2275   memset (FileBuffer + DebugEntry->FileOffset, 0, DebugEntry->SizeOfData);\r
2276   \r
2277   return EFI_SUCCESS;\r
2278 }\r
2279 \r
2280 STATIC \r
2281 EFI_STATUS\r
2282 SetStamp (\r
2283   IN OUT UINT8  *FileBuffer, \r
2284   IN     CHAR8  *TimeStamp\r
2285   )\r
2286 /*++\r
2287 \r
2288 Routine Description:\r
2289 \r
2290   Set new time stamp into PeImage FileHdr and Directory table: \r
2291   Debug, Export and Resource.\r
2292 \r
2293 Arguments:\r
2294 \r
2295   FileBuffer    - Pointer to PeImage.\r
2296   TimeStamp     - Time stamp string.\r
2297 \r
2298 Returns:\r
2299 \r
2300   EFI_INVALID_PARAMETER   - TimeStamp format is not recognized.\r
2301   EFI_SUCCESS             - Set new time stamp in this image successfully.\r
2302 \r
2303 --*/\r
2304 {\r
2305   struct tm                       stime;\r
2306   struct tm                       *ptime;\r
2307   time_t                          newtime;\r
2308   UINTN                           Index;\r
2309   UINTN                           DebugDirectoryEntryRva;\r
2310   UINTN                           DebugDirectoryEntryFileOffset;\r
2311   UINTN                           ExportDirectoryEntryRva;\r
2312   UINTN                           ExportDirectoryEntryFileOffset;\r
2313   UINTN                           ResourceDirectoryEntryRva;\r
2314   UINTN                           ResourceDirectoryEntryFileOffset;\r
2315   EFI_IMAGE_DOS_HEADER            *DosHdr;\r
2316   EFI_IMAGE_FILE_HEADER           *FileHdr;\r
2317   EFI_IMAGE_OPTIONAL_HEADER32     *Optional32Hdr;\r
2318   EFI_IMAGE_OPTIONAL_HEADER64     *Optional64Hdr;\r
2319   EFI_IMAGE_SECTION_HEADER        *SectionHeader;\r
2320   UINT32                          *NewTimeStamp;\r
2321   \r
2322   //\r
2323   // Init variable.\r
2324   //  \r
2325   DebugDirectoryEntryRva    = 0;\r
2326   ExportDirectoryEntryRva   = 0;\r
2327   ResourceDirectoryEntryRva = 0;\r
2328 \r
2329   //\r
2330   // Get time and date that will be set.\r
2331   //\r
2332   if (TimeStamp == NULL) {\r
2333     Error (NULL, 0, 3000, "Invalid", "TimeStamp cannot be NULL.");\r
2334     return EFI_INVALID_PARAMETER;\r
2335   }\r
2336   //\r
2337   // compare the value with "NOW", if yes, current system time is set.\r
2338   //\r
2339   if (stricmp (TimeStamp, "NOW") == 0) {\r
2340     //\r
2341     // get system current time and date\r
2342     //\r
2343     time (&newtime);\r
2344   } else {\r
2345     //\r
2346     // get the date and time from TimeStamp\r
2347     //\r
2348     if (sscanf (TimeStamp, "%d-%d-%d %d:%d:%d",\r
2349             &stime.tm_year,\r
2350             &stime.tm_mon,\r
2351             &stime.tm_mday,\r
2352             &stime.tm_hour,\r
2353             &stime.tm_min,\r
2354             &stime.tm_sec\r
2355             ) != 6) {\r
2356       Error (NULL, 0, 3000, "Invalid", "%s Invalid or unsupported datetime!", TimeStamp);\r
2357       return EFI_INVALID_PARAMETER;\r
2358     }\r
2359 \r
2360     //\r
2361     // in struct, Month (0 - 11; Jan = 0). So decrease 1 from it\r
2362     //\r
2363     if (stime.tm_mon <= 0 || stime.tm_mday <=0) {\r
2364       Error (NULL, 0, 3000, "Invalid", "%s Invalid date!", TimeStamp);\r
2365       return EFI_INVALID_PARAMETER;      \r
2366     }\r
2367     stime.tm_mon -= 1;\r
2368   \r
2369     //\r
2370     // in struct, Year (current year minus 1900)\r
2371     // and only the dates can be handled from Jan 1, 1970 to Jan 18, 2038\r
2372     //\r
2373     //\r
2374     // convert 0 -> 100 (2000), 1 -> 101 (2001), ..., 38 -> 138 (2038)\r
2375     //\r
2376     if (stime.tm_year >= 1970 && stime.tm_year <= 2038) {\r
2377       //\r
2378       // convert 1970 -> 70, 2000 -> 100, ...\r
2379       //\r
2380       stime.tm_year -= 1900;\r
2381     } else {\r
2382       Error (NULL, 0, 3000, "Invalid", "%s Invalid or unsupported datetime!", TimeStamp);\r
2383       return EFI_INVALID_PARAMETER;\r
2384     }\r
2385 \r
2386     //\r
2387     // convert the date and time to time_t format\r
2388     //\r
2389     newtime = mktime (&stime);\r
2390     if (newtime == (time_t) - 1) {\r
2391       Error (NULL, 0, 3000, "Invalid", "%s Invalid or unsupported datetime!", TimeStamp);\r
2392       return EFI_INVALID_PARAMETER;\r
2393     }\r
2394   }\r
2395   \r
2396   ptime = localtime (&newtime);\r
2397   DebugMsg (NULL, 0, 9, "New Image Time Stamp", "%04d-%02d-%02d %02d:%02d:%02d",\r
2398             ptime->tm_year + 1900, ptime->tm_mon + 1, ptime->tm_mday, ptime->tm_hour, ptime->tm_min, ptime->tm_sec); \r
2399   //\r
2400   // Set new time and data into PeImage.\r
2401   //\r
2402   DosHdr   = (EFI_IMAGE_DOS_HEADER *)  FileBuffer;\r
2403   FileHdr  = (EFI_IMAGE_FILE_HEADER *) (FileBuffer + DosHdr->e_lfanew + sizeof (UINT32));\r
2404   \r
2405   //\r
2406   // Get Debug, Export and Resource EntryTable RVA address.\r
2407   // Resource Directory entry need to review.\r
2408   //\r
2409   if (FileHdr->Machine == EFI_IMAGE_MACHINE_IA32) {\r
2410     Optional32Hdr = (EFI_IMAGE_OPTIONAL_HEADER32 *) ((UINT8*) FileHdr + sizeof (EFI_IMAGE_FILE_HEADER));\r
2411     SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) Optional32Hdr +  FileHdr->SizeOfOptionalHeader);\r
2412     if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXPORT && \\r
2413         Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].Size != 0) {\r
2414       ExportDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;\r
2415     }\r
2416     if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE && \\r
2417         Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size != 0) {\r
2418       ResourceDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;\r
2419     }\r
2420     if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG && \\r
2421         Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) {\r
2422       DebugDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;\r
2423     }\r
2424   } else {\r
2425     Optional64Hdr = (EFI_IMAGE_OPTIONAL_HEADER64 *) ((UINT8*) FileHdr + sizeof (EFI_IMAGE_FILE_HEADER));\r
2426     SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) Optional64Hdr +  FileHdr->SizeOfOptionalHeader);\r
2427     if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXPORT && \\r
2428         Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].Size != 0) {\r
2429       ExportDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;\r
2430     }\r
2431     if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE && \\r
2432         Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size != 0) {\r
2433       ResourceDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;\r
2434     }\r
2435     if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG && \\r
2436         Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) {\r
2437       DebugDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;\r
2438     }\r
2439   }\r
2440 \r
2441   //\r
2442   // Get DirectoryEntryTable file offset.\r
2443   //\r
2444   for (Index = 0; Index < FileHdr->NumberOfSections; Index ++, SectionHeader ++) {\r
2445     if (DebugDirectoryEntryRva >= SectionHeader->VirtualAddress &&\r
2446         DebugDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) {\r
2447         DebugDirectoryEntryFileOffset =\r
2448         DebugDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData;\r
2449     }\r
2450     if (ExportDirectoryEntryRva >= SectionHeader->VirtualAddress &&\r
2451         ExportDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) {\r
2452         ExportDirectoryEntryFileOffset =\r
2453         ExportDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData;\r
2454     }\r
2455     if (ResourceDirectoryEntryRva >= SectionHeader->VirtualAddress &&\r
2456         ResourceDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) {\r
2457         ResourceDirectoryEntryFileOffset =\r
2458         ResourceDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData;\r
2459     }\r
2460   }\r
2461   \r
2462   //\r
2463   // Set new stamp\r
2464   //\r
2465   FileHdr->TimeDateStamp = (UINT32) newtime;\r
2466 \r
2467   if (ExportDirectoryEntryRva != 0) {\r
2468     NewTimeStamp  = (UINT32 *) (FileBuffer + ExportDirectoryEntryFileOffset + sizeof (UINT32));\r
2469     *NewTimeStamp = (UINT32) newtime;\r
2470   }\r
2471 \r
2472   if (ResourceDirectoryEntryRva != 0) {\r
2473     NewTimeStamp  = (UINT32 *) (FileBuffer + ResourceDirectoryEntryFileOffset + sizeof (UINT32));\r
2474     *NewTimeStamp = (UINT32) newtime;\r
2475   }\r
2476 \r
2477   if (DebugDirectoryEntryRva != 0) {\r
2478     NewTimeStamp  = (UINT32 *) (FileBuffer + DebugDirectoryEntryFileOffset + sizeof (UINT32));\r
2479     *NewTimeStamp = (UINT32) newtime;\r
2480   }\r
2481   \r
2482   return EFI_SUCCESS;\r
2483 }\r
2484 \r
2485 STATIC\r
2486 STATUS\r
2487 MicrocodeReadData (\r
2488   FILE          *InFptr,\r
2489   UINTN         *Data\r
2490   )\r
2491 /*++\r
2492 \r
2493 Routine Description:\r
2494   Read a 32-bit microcode data value from a text file and convert to raw binary form.\r
2495 \r
2496 Arguments:\r
2497   InFptr    - file pointer to input text file\r
2498   Data      - pointer to where to return the data parsed\r
2499 \r
2500 Returns:\r
2501   STATUS_SUCCESS    - no errors or warnings, Data contains valid information\r
2502   STATUS_ERROR      - errors were encountered\r
2503 \r
2504 --*/\r
2505 {\r
2506   CHAR8  Line[MAX_LINE_LEN];\r
2507   CHAR8  *cptr;\r
2508   UINT8  ctr;\r
2509 \r
2510   Line[MAX_LINE_LEN - 1]  = 0;\r
2511   while (1) {\r
2512     if (fgets (Line, MAX_LINE_LEN, InFptr) == NULL) {\r
2513       return STATUS_ERROR;\r
2514     }\r
2515     //\r
2516     // If it was a binary file, then it may have overwritten our null terminator\r
2517     //\r
2518     if (Line[MAX_LINE_LEN - 1] != 0) {\r
2519       return STATUS_ERROR;\r
2520     }\r
2521     \r
2522     //\r
2523     // strip space\r
2524     // \r
2525     for (cptr = Line; *cptr && isspace(*cptr); cptr++) {\r
2526     }\r
2527     \r
2528     // Skip Blank Lines and Comment Lines\r
2529     if ((strlen(cptr) != 0) && (*cptr != ';')) {\r
2530       break;\r
2531     }\r
2532   }\r
2533 \r
2534   // Look for\r
2535   // dd 000000001h ; comment\r
2536   // dd XXXXXXXX\r
2537   // DD  XXXXXXXXX\r
2538   //  DD XXXXXXXXX\r
2539   //\r
2540   if ((tolower(cptr[0]) == 'd') && (tolower(cptr[1]) == 'd') && isspace (cptr[2])) {\r
2541     //\r
2542     // Skip blanks and look for a hex digit\r
2543     //\r
2544     cptr += 3;\r
2545     for (; *cptr && isspace(*cptr); cptr++) {\r
2546     }\r
2547     if (isxdigit (*cptr)) {\r
2548       if (sscanf (cptr, "%X", Data) != 1) {\r
2549         return STATUS_ERROR;\r
2550       }\r
2551     }\r
2552     return STATUS_SUCCESS;\r
2553   }\r
2554 \r
2555   return STATUS_ERROR;\r
2556 }\r