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