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