e72f05286969297f84d45990160be97621d4707f
[efi/basetools/.git] / Source / C / GenFw / GenFw.c
1 /** @file\r
2 \r
3 Copyright (c) 2004 - 2009, Intel Corporation\r
4 All rights reserved. This program and the accompanying materials\r
5 are licensed and made available under the terms and conditions of the BSD License\r
6 which accompanies this distribution.  The full text of the license may be found at\r
7 http://opensource.org/licenses/bsd-license.php\r
8 \r
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
11 \r
12 Module Name:\r
13 \r
14     GenFw.c\r
15 \r
16 Abstract:\r
17 \r
18     Converts a pe32+ image to an FW, Te image type, or other specific image.\r
19 \r
20 **/\r
21 \r
22 #include "WinNtInclude.h"\r
23 \r
24 #ifndef __GNUC__\r
25 #include <windows.h>\r
26 #include <io.h>\r
27 #endif\r
28 #include <stdio.h>\r
29 #include <stdlib.h>\r
30 #include <string.h>\r
31 #include <time.h>\r
32 #include <ctype.h>\r
33 \r
34 #include <Common/UefiBaseTypes.h>\r
35 #include <IndustryStandard/PeImage.h>\r
36 #include <Common/UefiInternalFormRepresentation.h>\r
37 \r
38 //\r
39 // Acpi Table definition\r
40 //\r
41 #include <IndustryStandard/Acpi.h>\r
42 #include <IndustryStandard/Acpi1_0.h>\r
43 #include <IndustryStandard/Acpi2_0.h>\r
44 #include <IndustryStandard/Acpi3_0.h>\r
45 #include <IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h>\r
46 \r
47 #include "CommonLib.h"\r
48 #include "PeCoffLib.h"\r
49 #include "ParseInf.h"\r
50 #include "EfiUtilityMsgs.h"\r
51 \r
52 #include "elf_common.h"\r
53 #include "elf32.h"\r
54 #include "elf64.h"\r
55 \r
56 \r
57 //\r
58 // Version of this utility\r
59 //\r
60 #define UTILITY_NAME "GenFw"\r
61 #define UTILITY_MAJOR_VERSION 0\r
62 #define UTILITY_MINOR_VERSION 2\r
63 \r
64 #define HII_RESOURCE_SECTION_INDEX  1\r
65 #define HII_RESOURCE_SECTION_NAME   "HII"\r
66 //\r
67 // Action for this tool.\r
68 //\r
69 #define FW_DUMMY_IMAGE       0\r
70 #define FW_EFI_IMAGE         1\r
71 #define FW_TE_IMAGE          2\r
72 #define FW_ACPI_IMAGE        3\r
73 #define FW_BIN_IMAGE         4\r
74 #define FW_ZERO_DEBUG_IMAGE  5\r
75 #define FW_SET_STAMP_IMAGE   6\r
76 #define FW_MCI_IMAGE         7\r
77 #define FW_MERGE_IMAGE       8\r
78 #define FW_RELOC_STRIPEED_IMAGE 9\r
79 #define FW_HII_PACKAGE_LIST_RCIMAGE 10\r
80 \r
81 #define DUMP_TE_HEADER       0x11\r
82 \r
83 #define DEFAULT_MC_PAD_BYTE_VALUE  0xFF\r
84 #define DEFAULT_MC_ALIGNMENT       16\r
85 \r
86 #ifndef _MAX_PATH\r
87 #define _MAX_PATH 500\r
88 #endif\r
89 \r
90 #define STATUS_IGNORE        0xA\r
91 //\r
92 // Structure definition for a microcode header\r
93 //\r
94 typedef struct {\r
95   UINT32  HeaderVersion;\r
96   UINT32  PatchId;\r
97   UINT32  Date;\r
98   UINT32  CpuId;\r
99   UINT32  Checksum;\r
100   UINT32  LoaderVersion;\r
101   UINT32  PlatformId;\r
102   UINT32  DataSize;   // if 0, then TotalSize = 2048, and TotalSize field is invalid\r
103   UINT32  TotalSize;  // number of bytes\r
104   UINT32  Reserved[3];\r
105 } MICROCODE_IMAGE_HEADER;\r
106 \r
107 static EFI_GUID mZeroGuid = {0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};\r
108 \r
109 static const char *gHiiPackageRCFileHeader[] = {\r
110   "//",\r
111   "//  DO NOT EDIT -- auto-generated file",\r
112   "//",\r
113   NULL\r
114 };\r
115 \r
116 STATIC CHAR8 *mInImageName;\r
117 \r
118 STATIC\r
119 EFI_STATUS\r
120 ZeroDebugData (\r
121   IN OUT UINT8   *FileBuffer,\r
122   BOOLEAN        ZeroDebug\r
123   );\r
124 \r
125 STATIC\r
126 EFI_STATUS\r
127 SetStamp (\r
128   IN OUT UINT8  *FileBuffer,\r
129   IN     CHAR8  *TimeStamp\r
130   );\r
131 \r
132 STATIC\r
133 STATUS\r
134 MicrocodeReadData (\r
135   FILE          *InFptr,\r
136   UINT32        *Data\r
137   );\r
138 \r
139 STATIC\r
140 VOID\r
141 Version (\r
142   VOID\r
143   )\r
144 /*++\r
145 \r
146 Routine Description:\r
147 \r
148   Print out version information for this utility.\r
149 \r
150 Arguments:\r
151 \r
152   None\r
153 \r
154 Returns:\r
155 \r
156   None\r
157 \r
158 --*/\r
159 {\r
160   fprintf (stdout, "%s Version %d.%d\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION);\r
161 }\r
162 \r
163 STATIC\r
164 VOID\r
165 Usage (\r
166   VOID\r
167   )\r
168 /*++\r
169 \r
170 Routine Description:\r
171 \r
172   Print Help message.\r
173 \r
174 Arguments:\r
175 \r
176   VOID\r
177 \r
178 Returns:\r
179 \r
180   None\r
181 \r
182 --*/\r
183 {\r
184   //\r
185   // Summary usage\r
186   //\r
187   fprintf (stdout, "\nUsage: %s [options] <input_file>\n\n", UTILITY_NAME);\r
188 \r
189   //\r
190   // Copyright declaration\r
191   //\r
192   fprintf (stdout, "Copyright (c) 2007, Intel Corporation. All rights reserved.\n\n");\r
193 \r
194   //\r
195   // Details Option\r
196   //\r
197   fprintf (stdout, "Options:\n");\r
198   fprintf (stdout, "  -o FileName, --outputfile FileName\n\\r
199                         File will be created to store the ouput content.\n");\r
200   fprintf (stdout, "  -e EFI_FILETYPE, --efiImage EFI_FILETYPE\n\\r
201                         Create Efi Image. EFI_FILETYPE is one of BASE, SEC,\n\\r
202                         PEI_CORE, PEIM, DXE_CORE, DXE_DRIVER, UEFI_APPLICATION,\n\\r
203                         DXE_SAL_DRIVER, UEFI_DRIVER, DXE_RUNTIME_DRIVER, \n\\r
204                         DXE_SMM_DRIVER, SECURITY_CORE, COMBINED_PEIM_DRIVER, \n\\r
205                         PIC_PEIM, RELOCATABLE_PEIM, BS_DRIVER, RT_DRIVER,\n\\r
206                         APPLICATION, SAL_RT_DRIVER to support all module types\n\\r
207                         It can only be used together with --keepexceptiontable,\n\\r
208                         --keepzeropending, -r, -o option.It is a action option.\n\\r
209                         If it is combined with other action options, the later\n\\r
210                         input action option will override the previous one.\n");\r
211   fprintf (stdout, "  -c, --acpi            Create Acpi table.\n\\r
212                         It can't be combined with other action options\n\\r
213                         except for -o, -r option. It is a action option.\n\\r
214                         If it is combined with other action options, the later\n\\r
215                         input action option will override the previous one.\n");\r
216   fprintf (stdout, "  -t, --terse           Create Te Image.\n\\r
217                         It can only be used together with --keepexceptiontable,\n\\r
218                         --keepzeropending, -r, -o option.It is a action option.\n\\r
219                         If it is combined with other action options, the later\n\\r
220                         input action option will override the previous one.\n");\r
221   fprintf (stdout, "  -u, --dump            Dump TeImage Header.\n\\r
222                         It can't be combined with other action options\n\\r
223                         except for -o, -r option. It is a action option.\n\\r
224                         If it is combined with other action options, the later\n\\r
225                         input action option will override the previous one.\n");\r
226   fprintf (stdout, "  -z, --zero            Zero the Debug Data Fields in the PE input image file.\n\\r
227                         It also zeros the time stamp fields.\n\\r
228                         This option can be used to compare the binary efi image.\n\\r
229                         It can't be combined with other action options\n\\r
230                         except for -o, -r option. It is a action option.\n\\r
231                         If it is combined with other action options, the later\n\\r
232                         input action option will override the previous one.\n");\r
233   fprintf (stdout, "  -b, --exe2bin         Convert the input EXE to the output BIN file.\n\\r
234                         It can't be combined with other action options\n\\r
235                         except for -o, -r option. It is a action option.\n\\r
236                         If it is combined with other action options, the later\n\\r
237                         input action option will override the previous one.\n");;\r
238   fprintf (stdout, "  -l, --stripped        Relocation info stripped from the input PE or TE image.\n\\r
239                         It can't be combined with other action options\n\\r
240                         except for -o, -r option. It is a action option.\n\\r
241                         If it is combined with other action options, the later\n\\r
242                         input action option will override the previous one.\n");\r
243   fprintf (stdout, "  -s timedate, --stamp timedate\n\\r
244                         timedate format is \"yyyy-mm-dd 00:00:00\". if timedata \n\\r
245                         is set to NOW, current system time is used. The support\n\\r
246                         date scope is 1970-1-1 8:0:0 ~ 2038-1-19 3:14:07\n\\r
247                         It can't be combined with other action options\n\\r
248                         except for -o, -r option. It is a action option.\n\\r
249                         If it is combined with other action options, the later\n\\r
250                         input action option will override the previous one.\n");\r
251   fprintf (stdout, "  -m, --mcifile         Convert input microcode txt file to microcode bin file.\n\\r
252                         It can't be combined with other action options\n\\r
253                         except for -o option. It is a action option.\n\\r
254                         If it is combined with other action options, the later\n\\r
255                         input action option will override the previous one.\n");\r
256   fprintf (stdout, "  -j, --join            Combine multi microcode bin files to one file.\n\\r
257                         It can be specified with -a, -p, -o option.\n\\r
258                         No other options can be combined with it.\n\\r
259                         If it is combined with other action options, the later\n\\r
260                         input action option will override the previous one.\n");\r
261   fprintf (stdout, "  -a NUM, --align NUM   NUM is one HEX or DEC format alignment value.\n\\r
262                         This option is only used together with -j option.\n");  \r
263   fprintf (stdout, "  -p NUM, --pad NUM     NUM is one HEX or DEC format padding value.\n\\r
264                         This option is only used together with -j option.\n");\r
265   fprintf (stdout, "  --keepexceptiontable  Don't clear exception table.\n\\r
266                         This option can be used together with -e or -t.\n\\r
267                         It doesn't work for other options.\n");\r
268   fprintf (stdout, "  --keepzeropending     Don't strip zero pending of .reloc.\n\\r
269                         This option can be used together with -e or -t.\n\\r
270                         It doesn't work for other options.\n");\r
271   fprintf (stdout, "  -r, --replace         Overwrite the input file with the output content.\n\\r
272                         If more input files are specified,\n\\r
273                         the last input file will be as the output file.\n");\r
274   fprintf (stdout, "  -g HiiPackageListGuid, --hiiguid HiiPackageListGuid\n\\r
275                         HiiListPackageGuidGuid is from the module guid.\n\\r
276                         Its format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n\\r
277                         If not specified, the first Form FormSet guid is used.\n");\r
278   fprintf (stdout, "  --hiipackage          Combine all input binary hii pacakges into \n\\r
279                         a single package list as the text resource data(RC).\n\\r
280                         It can't be combined with other action options\n\\r
281                         except for -o option. It is a action option.\n\\r
282                         If it is combined with other action options, the later\n\\r
283                         input action option will override the previous one.\n");\r
284   fprintf (stdout, "  -v, --verbose         Turn on verbose output with informational messages.\n");\r
285   fprintf (stdout, "  -q, --quiet           Disable all messages except key message and fatal error\n");\r
286   fprintf (stdout, "  -d, --debug level     Enable debug messages, at input debug level.\n");\r
287   fprintf (stdout, "  --version             Show program's version number and exit\n");\r
288   fprintf (stdout, "  -h, --help            Show this help message and exit\n");\r
289 }\r
290 \r
291 STATIC\r
292 STATUS\r
293 CheckAcpiTable (\r
294   VOID      *AcpiTable,\r
295   UINT32    Length\r
296   )\r
297 /*++\r
298 \r
299 Routine Description:\r
300 \r
301   Check Acpi Table\r
302 \r
303 Arguments:\r
304 \r
305   AcpiTable     Buffer for AcpiSection\r
306   Length        AcpiSection Length\r
307 \r
308 Returns:\r
309 \r
310   0             success\r
311   non-zero      otherwise\r
312 \r
313 --*/\r
314 {\r
315   EFI_ACPI_DESCRIPTION_HEADER                   *AcpiHeader;\r
316   EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE  *Facs;\r
317   UINT32                                        ExpectedLength;\r
318 \r
319   AcpiHeader = (EFI_ACPI_DESCRIPTION_HEADER *)AcpiTable;\r
320 \r
321   //\r
322   // Generic check for AcpiTable length.\r
323   //\r
324   if (AcpiHeader->Length > Length) {\r
325     Error (NULL, 0, 3000, "Invalid", "AcpiTable length check failed.", NULL);\r
326     return STATUS_ERROR;\r
327   }\r
328 \r
329   //\r
330   // Currently, we only check must-have tables: FADT, FACS, DSDT,\r
331   // and some important tables: MADT, MCFG.\r
332   //\r
333   switch (AcpiHeader->Signature) {\r
334 \r
335   //\r
336   // "FACP" Fixed ACPI Description Table\r
337   //\r
338   case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE:\r
339     switch (AcpiHeader->Revision) {\r
340     case EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION:\r
341       ExpectedLength = sizeof(EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE);\r
342       break;\r
343     case EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION:\r
344       ExpectedLength = sizeof(EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE);\r
345       break;\r
346     case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION:\r
347       ExpectedLength = sizeof(EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE);\r
348       break;\r
349     default:\r
350       if (AcpiHeader->Revision > EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION) {\r
351         ExpectedLength = AcpiHeader->Length;\r
352         break;\r
353       }\r
354       Error (NULL, 0, 3000, "Invalid", "FACP revision check failed.");\r
355       return STATUS_ERROR;\r
356     }\r
357     if (ExpectedLength != AcpiHeader->Length) {\r
358       Error (NULL, 0, 3000, "Invalid", "FACP length check failed.");\r
359       return STATUS_ERROR;\r
360     }\r
361     break;\r
362 \r
363   //\r
364   // "FACS" Firmware ACPI Control Structure\r
365   //\r
366   case EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE:\r
367     Facs = (EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *)AcpiTable;\r
368     if (Facs->Version > EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION) {\r
369       break;\r
370     }\r
371     if ((Facs->Version != EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION) &&\r
372         (Facs->Version != EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION) &&\r
373         (Facs->Version != EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION)){\r
374       Error (NULL, 0, 3000, "Invalid", "FACS version check failed.");\r
375       return STATUS_ERROR;\r
376     }\r
377     if ((Facs->Length != sizeof(EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE)) &&\r
378         (Facs->Length != sizeof(EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE)) &&\r
379         (Facs->Length != sizeof(EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE))) {\r
380       Error (NULL, 0, 3000, "Invalid", "FACS length check failed.");\r
381       return STATUS_ERROR;\r
382     }\r
383     break;\r
384 \r
385   //\r
386   // "DSDT" Differentiated System Description Table\r
387   //\r
388   case EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:\r
389     if (AcpiHeader->Revision > EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_REVISION) {\r
390       break;\r
391     }\r
392     if (AcpiHeader->Length <= sizeof(EFI_ACPI_DESCRIPTION_HEADER)) {\r
393       Error (NULL, 0, 3000, "Invalid", "DSDT length check failed.");\r
394       return STATUS_ERROR;\r
395     }\r
396     break;\r
397 \r
398   //\r
399   // "APIC" Multiple APIC Description Table\r
400   //\r
401   case EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE:\r
402     if (AcpiHeader->Revision > EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION) {\r
403       break;\r
404     }\r
405     if ((AcpiHeader->Revision != EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION) &&\r
406         (AcpiHeader->Revision != EFI_ACPI_2_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION) &&\r
407         (AcpiHeader->Revision != EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION)) {\r
408       Error (NULL, 0, 3000, "Invalid", "APIC revision check failed.");\r
409       return STATUS_ERROR;\r
410     }\r
411     if (AcpiHeader->Length <= sizeof(EFI_ACPI_DESCRIPTION_HEADER) + sizeof(UINT32) + sizeof(UINT32)) {\r
412       Error (NULL, 0, 3000, "Invalid", "APIC length check failed.");\r
413       return STATUS_ERROR;\r
414     }\r
415     break;\r
416 \r
417   //\r
418   // "MCFG" PCI Express Memory Mapped Configuration Space Base Address Description Table\r
419   //\r
420   case EFI_ACPI_3_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE:\r
421     if (AcpiHeader->Revision > EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION) {\r
422       break;\r
423     }\r
424     if (AcpiHeader->Revision != EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION) {\r
425       Error (NULL, 0, 3000, "Invalid", "MCFG revision check failed.");\r
426       return STATUS_ERROR;\r
427     }\r
428     if (AcpiHeader->Length <= sizeof(EFI_ACPI_DESCRIPTION_HEADER) + sizeof(UINT64)) {\r
429       Error (NULL, 0, 3000, "Invalid", "MCFG length check failed.");\r
430       return STATUS_ERROR;\r
431     }\r
432     break;\r
433 \r
434   //\r
435   // Other table pass check\r
436   //\r
437   default:\r
438     break;\r
439   }\r
440 \r
441   return STATUS_SUCCESS;\r
442 }\r
443 \r
444 \r
445 INTN\r
446 IsElfHeader(\r
447   UINT8  *FileBuffer\r
448 )\r
449 {\r
450   return (FileBuffer[EI_MAG0] == ELFMAG0\r
451     && FileBuffer[EI_MAG1] == ELFMAG1\r
452     && FileBuffer[EI_MAG2] == ELFMAG2\r
453     && FileBuffer[EI_MAG3] == ELFMAG3);\r
454 }\r
455 \r
456 typedef Elf32_Shdr Elf_Shdr;\r
457 typedef Elf32_Ehdr Elf_Ehdr;\r
458 typedef Elf32_Rel Elf_Rel;\r
459 typedef Elf32_Sym Elf_Sym;\r
460 typedef Elf32_Phdr Elf_Phdr;\r
461 typedef Elf32_Dyn Elf_Dyn;\r
462 \r
463 #define ELFCLASS ELFCLASS32\r
464 #define ELF_R_TYPE(r) ELF32_R_TYPE(r)\r
465 #define ELF_R_SYM(r) ELF32_R_SYM(r)\r
466 #define ELF_HII_SECTION_NAME ".hii"\r
467 //\r
468 // Well known ELF structures.\r
469 //\r
470 Elf_Ehdr *Ehdr;\r
471 Elf_Shdr *ShdrBase;\r
472 Elf_Phdr *gPhdrBase;\r
473 \r
474 //\r
475 // PE section alignment.\r
476 //\r
477 const UINT32 CoffAlignment = 0x20;\r
478 const UINT16 CoffNbrSections = 5;\r
479 \r
480 //\r
481 // Current offset in coff file.\r
482 //\r
483 UINT32 CoffOffset;\r
484 \r
485 //\r
486 // Result Coff file in memory.\r
487 //\r
488 UINT8 *CoffFile = NULL;\r
489 //\r
490 // ELF sections to offset in Coff file.\r
491 //\r
492 UINT32 *CoffSectionsOffset = NULL;\r
493 \r
494 //\r
495 // Offset in Coff file of headers and sections.\r
496 //\r
497 UINT32 NtHdrOffset;\r
498 UINT32 TableOffset;\r
499 UINT32 TextOffset;\r
500 UINT32 DataOffset;\r
501 UINT32 HiiRsrcOffset;\r
502 UINT32 RelocOffset;\r
503 \r
504 //\r
505 // HiiBinData\r
506 //\r
507 UINT8* HiiBinData = NULL;\r
508 UINT32 HiiBinSize = 0;\r
509 \r
510 EFI_IMAGE_BASE_RELOCATION *CoffBaseRel;\r
511 UINT16 *CoffEntryRel;\r
512 \r
513 UINT32\r
514 CoffAlign(\r
515   UINT32 Offset\r
516   )\r
517 {\r
518   return (Offset + CoffAlignment - 1) & ~(CoffAlignment - 1);\r
519 }\r
520 \r
521 Elf_Shdr *\r
522 GetShdrByIndex(\r
523   UINT32 Num\r
524   )\r
525 {\r
526   if (Num >= Ehdr->e_shnum)\r
527     return NULL;\r
528   return (Elf_Shdr*)((UINT8*)ShdrBase + Num * Ehdr->e_shentsize);\r
529 }\r
530 \r
531 INTN\r
532 CheckElfHeader(\r
533   VOID\r
534   )\r
535 {\r
536   //\r
537   // Note: Magic has already been tested.\r
538   //\r
539   if (Ehdr->e_ident[EI_CLASS] != ELFCLASS) {\r
540     Error (NULL, 0, 3000, "Unsupported", "%s needs to be ported for 64-bit ELF.", mInImageName);\r
541     return 0;\r
542   }\r
543   if (Ehdr->e_ident[EI_DATA] != ELFDATA2LSB) {\r
544     Error (NULL, 0, 3000, "Unsupported", "ELF EI_DATA not ELFDATA2LSB");\r
545     return 0;\r
546   }\r
547   if ((Ehdr->e_type != ET_EXEC) && (Ehdr->e_type != ET_DYN)) {\r
548     Error (NULL, 0, 3000, "Unsupported", "ELF e_type not ET_EXEC or ET_DYN");\r
549     return 0;\r
550   }\r
551   if (!((Ehdr->e_machine == EM_386) || (Ehdr->e_machine == EM_ARM))) { \r
552     Error (NULL, 0, 3000, "Unsupported", "ELF e_machine not EM_386 or EM_ARM");\r
553     return 0;\r
554   }\r
555   if (Ehdr->e_version != EV_CURRENT) {\r
556     Error (NULL, 0, 3000, "Unsupported", "ELF e_version (%u) not EV_CURRENT (%d)", (unsigned) Ehdr->e_version, EV_CURRENT);\r
557     return 0;\r
558   }\r
559 \r
560   //\r
561   // Find the section header table\r
562   //\r
563   ShdrBase  = (Elf_Shdr *)((UINT8 *)Ehdr + Ehdr->e_shoff);\r
564   gPhdrBase = (Elf_Phdr *)((UINT8 *)Ehdr + Ehdr->e_phoff);\r
565 \r
566   CoffSectionsOffset = (UINT32 *)malloc(Ehdr->e_shnum * sizeof (UINT32));\r
567 \r
568   memset(CoffSectionsOffset, 0, Ehdr->e_shnum * sizeof(UINT32));\r
569   return 1;\r
570 }\r
571 \r
572 int\r
573 IsTextShdr(\r
574   Elf_Shdr *Shdr\r
575   )\r
576 {\r
577   return (Shdr->sh_flags & (SHF_WRITE | SHF_ALLOC)) == SHF_ALLOC;\r
578 }\r
579 \r
580 int\r
581 IsHiiRsrcShdr(\r
582   Elf_Shdr *Shdr\r
583   )\r
584 {\r
585   Elf_Shdr *Namedr = GetShdrByIndex(Ehdr->e_shstrndx);\r
586 \r
587   if (strcmp((CHAR8*)Ehdr + Namedr->sh_offset + Shdr->sh_name, ELF_HII_SECTION_NAME) == 0) {\r
588     return 1;\r
589   }\r
590 \r
591   return 0;\r
592 }\r
593 \r
594 int\r
595 IsDataShdr(\r
596   Elf_Shdr *Shdr\r
597   )\r
598 {\r
599   if (IsHiiRsrcShdr(Shdr)) {\r
600     return 0;\r
601   }\r
602   return (Shdr->sh_flags & (SHF_WRITE | SHF_ALLOC)) == (SHF_ALLOC | SHF_WRITE);\r
603 }\r
604 \r
605 VOID\r
606 CreateSectionHeader(\r
607   const CHAR8 *Name,\r
608   UINT32      Offset,\r
609   UINT32      Size,\r
610   UINT32      Flags\r
611   )\r
612 {\r
613   EFI_IMAGE_SECTION_HEADER *Hdr;\r
614   Hdr = (EFI_IMAGE_SECTION_HEADER*)(CoffFile + TableOffset);\r
615 \r
616   strcpy((char *)Hdr->Name, Name);\r
617   Hdr->Misc.VirtualSize = Size;\r
618   Hdr->VirtualAddress = Offset;\r
619   Hdr->SizeOfRawData = Size;\r
620   Hdr->PointerToRawData = Offset;\r
621   Hdr->PointerToRelocations = 0;\r
622   Hdr->PointerToLinenumbers = 0;\r
623   Hdr->NumberOfRelocations = 0;\r
624   Hdr->NumberOfLinenumbers = 0;\r
625   Hdr->Characteristics = Flags;\r
626 \r
627   TableOffset += sizeof (EFI_IMAGE_SECTION_HEADER);\r
628 }\r
629 \r
630 VOID\r
631 GetBinaryHiiData (\r
632   CHAR8   *RcString,\r
633   UINT32  Size,\r
634   UINT32  OffsetToFile\r
635   )\r
636 {\r
637   unsigned  Data16;\r
638   UINT32  HiiBinOffset;\r
639   UINT32  Index;\r
640   EFI_IMAGE_RESOURCE_DIRECTORY        *ResourceDirectory;\r
641   EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY  *ResourceDirectoryEntry;\r
642   EFI_IMAGE_RESOURCE_DIRECTORY_STRING *ResourceDirectoryString;\r
643   EFI_IMAGE_RESOURCE_DATA_ENTRY       *ResourceDataEntry;\r
644 \r
645   Index = 0;\r
646   while (Index < Size && *RcString != '\0' && *RcString != '{') {\r
647     RcString ++;\r
648     Index ++;\r
649   }\r
650   \r
651   if (*RcString == '\0' || Index == Size) {\r
652     return;\r
653   }\r
654   \r
655   //\r
656   // Skip '{' character\r
657   // Skip space and ',' character\r
658   //\r
659   RcString ++;\r
660   Index ++;\r
661   while (Index < Size && *RcString != '\0' && (isspace (*RcString) || *RcString == ',')){\r
662     RcString ++;\r
663     Index ++;\r
664   }\r
665 \r
666   //\r
667   // '}' end character\r
668   //\r
669   if (*RcString == '}' || Index == Size) {\r
670     return;\r
671   }\r
672 \r
673   HiiBinOffset = 0;\r
674   HiiBinSize   = 0x1000;\r
675   HiiBinData   = (UINT8 *) malloc (HiiBinSize);\r
676   if (HiiBinData == NULL) {\r
677     return;\r
678   }\r
679   memset (HiiBinData, 0, HiiBinSize);\r
680   //\r
681   // Fill Resource section entry\r
682   //\r
683   ResourceDirectory = (EFI_IMAGE_RESOURCE_DIRECTORY *) (HiiBinData + HiiBinOffset);\r
684   HiiBinOffset += sizeof (EFI_IMAGE_RESOURCE_DIRECTORY);\r
685   ResourceDirectory->NumberOfNamedEntries = 1;\r
686 \r
687   ResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *) (HiiBinData + HiiBinOffset);\r
688   HiiBinOffset += sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY);\r
689   ResourceDirectoryEntry->u1.s.NameIsString = 1;\r
690   ResourceDirectoryEntry->u1.s.NameOffset   = HiiBinOffset;\r
691 \r
692   ResourceDirectoryString = (EFI_IMAGE_RESOURCE_DIRECTORY_STRING *) (HiiBinData + HiiBinOffset);\r
693   ResourceDirectoryString->Length = 3;\r
694   ResourceDirectoryString->String[0] =L'H';\r
695   ResourceDirectoryString->String[1] =L'I';\r
696   ResourceDirectoryString->String[2] =L'I';\r
697   HiiBinOffset = HiiBinOffset + sizeof (ResourceDirectoryString->Length) + ResourceDirectoryString->Length * sizeof (ResourceDirectoryString->String[0]);\r
698 \r
699   ResourceDirectoryEntry->u2.OffsetToData = HiiBinOffset;\r
700   ResourceDataEntry = (EFI_IMAGE_RESOURCE_DATA_ENTRY *) (HiiBinData + HiiBinOffset);\r
701   HiiBinOffset += sizeof (EFI_IMAGE_RESOURCE_DATA_ENTRY);\r
702   ResourceDataEntry->OffsetToData = OffsetToFile + HiiBinOffset;\r
703 \r
704   while (sscanf (RcString, "0x%X", &Data16) != EOF) {\r
705     //\r
706     // Convert the string data to the binary data.\r
707     //\r
708     *(UINT16 *)(HiiBinData + HiiBinOffset) = (UINT16) Data16;\r
709     HiiBinOffset += 2;\r
710     //\r
711     // Jump to the next data.\r
712     //\r
713     RcString = RcString + 2 + 4;\r
714     Index    = Index + 2 + 4;\r
715     //\r
716     // Skip space and ',' character\r
717     //\r
718     while (Index < Size && *RcString != '\0' && (isspace (*RcString) || *RcString == ',')){\r
719       RcString ++;\r
720       Index ++;\r
721     }\r
722     //\r
723     // '}' end character\r
724     //\r
725     if (*RcString == '}'|| Index == Size) {\r
726       break;\r
727     }\r
728     //\r
729     // Check BinBuffer size\r
730     //\r
731     if (HiiBinOffset >= HiiBinSize) {\r
732       HiiBinSize += 0x1000;\r
733       HiiBinData = (UINT8 *) realloc (HiiBinData, HiiBinSize);\r
734       //\r
735       // Memory allocation is failure.\r
736       //\r
737       if (HiiBinData == NULL) {\r
738         HiiBinSize = 0;\r
739         break;\r
740       }\r
741     }\r
742   }\r
743 \r
744   if (HiiBinData != NULL) {\r
745     HiiBinSize = HiiBinOffset;\r
746     ResourceDataEntry->Size = HiiBinSize + OffsetToFile - ResourceDataEntry->OffsetToData;\r
747   }\r
748   \r
749   return;\r
750 }\r
751 \r
752 VOID\r
753 ScanSections(\r
754   VOID\r
755   )\r
756 {\r
757   UINT32                          i;\r
758   EFI_IMAGE_DOS_HEADER            *DosHdr;\r
759   EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr;\r
760   UINT32                          CoffEntry;\r
761 \r
762   CoffEntry = 0;\r
763   CoffOffset = 0;\r
764 \r
765   //\r
766   // Coff file start with a DOS header.\r
767   //\r
768   CoffOffset = sizeof(EFI_IMAGE_DOS_HEADER) + 0x40;\r
769   NtHdrOffset = CoffOffset;\r
770   switch (Ehdr->e_machine) {\r
771   case EM_386:\r
772   case EM_ARM:\r
773     CoffOffset += sizeof (EFI_IMAGE_NT_HEADERS32);\r
774         break;\r
775   case EM_X86_64:\r
776   case EM_IA_64:\r
777     CoffOffset += sizeof (EFI_IMAGE_NT_HEADERS64);\r
778         break;\r
779   default:\r
780     VerboseMsg ("%s unknown e_machine type. Assume IA-32", (UINTN)Ehdr->e_machine);\r
781     CoffOffset += sizeof (EFI_IMAGE_NT_HEADERS32);\r
782         break;\r
783   }\r
784 \r
785   TableOffset = CoffOffset;\r
786   CoffOffset += CoffNbrSections * sizeof(EFI_IMAGE_SECTION_HEADER);\r
787 \r
788   //\r
789   // First text sections.\r
790   //\r
791   CoffOffset = CoffAlign(CoffOffset);\r
792   TextOffset = CoffOffset;\r
793   for (i = 0; i < Ehdr->e_shnum; i++) {\r
794     Elf_Shdr *shdr = GetShdrByIndex(i);\r
795     if (IsTextShdr(shdr)) {\r
796       if ((shdr->sh_addralign != 0) && (shdr->sh_addralign != 1)) {\r
797         // the alignment field is valid\r
798         if ((shdr->sh_addr & (shdr->sh_addralign - 1)) == 0) {\r
799           // if the section address is aligned we must align PE/COFF \r
800           CoffOffset = (CoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1);\r
801         } else if ((shdr->sh_addr % shdr->sh_addralign) != (CoffOffset % shdr->sh_addralign)) {\r
802           // ARM RVCT tools have behavior outside of the ELF specification to try \r
803           // and make images smaller.  If sh_addr is not aligned to sh_addralign \r
804           // then the section needs to preserve sh_addr MOD sh_addralign. \r
805           // Normally doing nothing here works great.\r
806           Error (NULL, 0, 3000, "Invalid", "Unsupported section alignment.");\r
807         }\r
808       }\r
809       \r
810       /* Relocate entry.  */\r
811       if ((Ehdr->e_entry >= shdr->sh_addr) &&\r
812           (Ehdr->e_entry < shdr->sh_addr + shdr->sh_size)) {\r
813         CoffEntry = CoffOffset + Ehdr->e_entry - shdr->sh_addr;\r
814       }\r
815       CoffSectionsOffset[i] = CoffOffset;\r
816       CoffOffset += shdr->sh_size;\r
817     }\r
818   }\r
819 \r
820   if (Ehdr->e_machine != EM_ARM) {\r
821     CoffOffset = CoffAlign(CoffOffset);\r
822   }\r
823 \r
824   //\r
825   //  Then data sections.\r
826   //\r
827   DataOffset = CoffOffset;\r
828   for (i = 0; i < Ehdr->e_shnum; i++) {\r
829     Elf_Shdr *shdr = GetShdrByIndex(i);\r
830     if (IsDataShdr(shdr)) {\r
831       if ((shdr->sh_addralign != 0) && (shdr->sh_addralign != 1)) {\r
832         // the alignment field is valid\r
833         if ((shdr->sh_addr & (shdr->sh_addralign - 1)) == 0) {\r
834           // if the section address is aligned we must align PE/COFF \r
835           CoffOffset = (CoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1);\r
836         } else if ((shdr->sh_addr % shdr->sh_addralign) != (CoffOffset % shdr->sh_addralign)) {\r
837           // ARM RVCT tools have behavior outside of the ELF specification to try \r
838           // and make images smaller.  If sh_addr is not aligned to sh_addralign \r
839           // then the section needs to preserve sh_addr MOD sh_addralign. \r
840           // Normally doing nothing here works great.\r
841           Error (NULL, 0, 3000, "Invalid", "Unsupported section alignment.");\r
842         }\r
843       }\r
844       CoffSectionsOffset[i] = CoffOffset;\r
845       CoffOffset += shdr->sh_size;\r
846     }\r
847   }\r
848   CoffOffset = CoffAlign(CoffOffset);\r
849 \r
850   //\r
851   //  The HII resource sections.\r
852   //\r
853   HiiRsrcOffset = CoffOffset;\r
854   for (i = 0; i < Ehdr->e_shnum; i++) {\r
855     Elf_Shdr *shdr = GetShdrByIndex(i);\r
856     if (IsHiiRsrcShdr(shdr)) {\r
857       if ((shdr->sh_addralign != 0) && (shdr->sh_addralign != 1)) {\r
858         // the alignment field is valid\r
859         if ((shdr->sh_addr & (shdr->sh_addralign - 1)) == 0) {\r
860           // if the section address is aligned we must align PE/COFF \r
861           CoffOffset = (CoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1);\r
862         } else if ((shdr->sh_addr % shdr->sh_addralign) != (CoffOffset % shdr->sh_addralign)) {\r
863           // ARM RVCT tools have behavior outside of the ELF specification to try \r
864           // and make images smaller.  If sh_addr is not aligned to sh_addralign \r
865           // then the section needs to preserve sh_addr MOD sh_addralign. \r
866           // Normally doing nothing here works great.\r
867           Error (NULL, 0, 3000, "Invalid", "Unsupported section alignment.");\r
868         }\r
869       }\r
870       GetBinaryHiiData ((CHAR8*)Ehdr + shdr->sh_offset, shdr->sh_size, HiiRsrcOffset);\r
871       if (HiiBinSize != 0) {\r
872         CoffOffset += HiiBinSize;\r
873         CoffOffset = CoffAlign(CoffOffset);\r
874       }\r
875       break;\r
876     }\r
877   }\r
878 \r
879   RelocOffset = CoffOffset;\r
880 \r
881   //\r
882   // Allocate base Coff file.  Will be expanded later for relocations.\r
883   //\r
884   CoffFile = (UINT8 *)malloc(CoffOffset);\r
885   memset(CoffFile, 0, CoffOffset);\r
886 \r
887   //\r
888   // Fill headers.\r
889   //\r
890   DosHdr = (EFI_IMAGE_DOS_HEADER *)CoffFile;\r
891   DosHdr->e_magic = EFI_IMAGE_DOS_SIGNATURE;\r
892   DosHdr->e_lfanew = NtHdrOffset;\r
893 \r
894   NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION*)(CoffFile + NtHdrOffset);\r
895 \r
896   NtHdr->Pe32.Signature = EFI_IMAGE_NT_SIGNATURE;\r
897 \r
898   switch (Ehdr->e_machine) {\r
899   case EM_386:\r
900     NtHdr->Pe32.FileHeader.Machine = EFI_IMAGE_MACHINE_IA32;\r
901     NtHdr->Pe32.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC;\r
902     break;\r
903   case EM_X86_64:\r
904     NtHdr->Pe32.FileHeader.Machine = EFI_IMAGE_MACHINE_X64;\r
905     NtHdr->Pe32.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;\r
906     break;\r
907   case EM_IA_64:\r
908     NtHdr->Pe32.FileHeader.Machine = EFI_IMAGE_MACHINE_IPF;\r
909     NtHdr->Pe32.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;\r
910     break;\r
911   case EM_ARM:\r
912     NtHdr->Pe32.FileHeader.Machine = EFI_IMAGE_MACHINE_ARMT;\r
913     NtHdr->Pe32.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC;\r
914     break;\r
915   default:\r
916     VerboseMsg ("%s unknown e_machine type. Assume IA-32", (UINTN)Ehdr->e_machine);\r
917     NtHdr->Pe32.FileHeader.Machine = EFI_IMAGE_MACHINE_IA32;\r
918     NtHdr->Pe32.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC;\r
919   }\r
920 \r
921   NtHdr->Pe32.FileHeader.NumberOfSections = CoffNbrSections;\r
922   NtHdr->Pe32.FileHeader.TimeDateStamp = (UINT32) time(NULL);\r
923   NtHdr->Pe32.FileHeader.PointerToSymbolTable = 0;\r
924   NtHdr->Pe32.FileHeader.NumberOfSymbols = 0;\r
925   NtHdr->Pe32.FileHeader.SizeOfOptionalHeader = sizeof(NtHdr->Pe32.OptionalHeader);\r
926   NtHdr->Pe32.FileHeader.Characteristics = EFI_IMAGE_FILE_EXECUTABLE_IMAGE\r
927     | EFI_IMAGE_FILE_LINE_NUMS_STRIPPED\r
928     | EFI_IMAGE_FILE_LOCAL_SYMS_STRIPPED\r
929     | EFI_IMAGE_FILE_32BIT_MACHINE;\r
930 \r
931   NtHdr->Pe32.OptionalHeader.SizeOfCode = DataOffset - TextOffset;\r
932   NtHdr->Pe32.OptionalHeader.SizeOfInitializedData = RelocOffset - DataOffset;\r
933   NtHdr->Pe32.OptionalHeader.SizeOfUninitializedData = 0;\r
934   NtHdr->Pe32.OptionalHeader.AddressOfEntryPoint = CoffEntry;\r
935 \r
936   NtHdr->Pe32.OptionalHeader.BaseOfCode = TextOffset;\r
937 \r
938   NtHdr->Pe32.OptionalHeader.BaseOfData = DataOffset;\r
939   NtHdr->Pe32.OptionalHeader.ImageBase = 0;\r
940   NtHdr->Pe32.OptionalHeader.SectionAlignment = CoffAlignment;\r
941   NtHdr->Pe32.OptionalHeader.FileAlignment = CoffAlignment;\r
942   NtHdr->Pe32.OptionalHeader.SizeOfImage = 0;\r
943 \r
944   NtHdr->Pe32.OptionalHeader.SizeOfHeaders = TextOffset;\r
945   NtHdr->Pe32.OptionalHeader.NumberOfRvaAndSizes = EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES;\r
946 \r
947   //\r
948   // Section headers.\r
949   //\r
950   if ((DataOffset - TextOffset) > 0) {\r
951     CreateSectionHeader (".text", TextOffset, DataOffset - TextOffset,\r
952             EFI_IMAGE_SCN_CNT_CODE\r
953             | EFI_IMAGE_SCN_MEM_EXECUTE\r
954             | EFI_IMAGE_SCN_MEM_READ);\r
955   } else {\r
956     // Don't make a section of size 0. \r
957     NtHdr->Pe32.FileHeader.NumberOfSections--;\r
958   }\r
959 \r
960   if ((HiiRsrcOffset - DataOffset) > 0) {\r
961     CreateSectionHeader (".data", DataOffset, HiiRsrcOffset - DataOffset,\r
962             EFI_IMAGE_SCN_CNT_INITIALIZED_DATA\r
963             | EFI_IMAGE_SCN_MEM_WRITE\r
964             | EFI_IMAGE_SCN_MEM_READ);\r
965   } else {\r
966     // Don't make a section of size 0. \r
967     NtHdr->Pe32.FileHeader.NumberOfSections--;\r
968   }\r
969 \r
970   if ((RelocOffset - HiiRsrcOffset) > 0) {\r
971     CreateSectionHeader (".rsrc", HiiRsrcOffset, RelocOffset - HiiRsrcOffset,\r
972             EFI_IMAGE_SCN_CNT_INITIALIZED_DATA\r
973             | EFI_IMAGE_SCN_MEM_READ);\r
974 \r
975     NtHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = HiiBinSize;\r
976     NtHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = HiiRsrcOffset;\r
977 \r
978     memcpy(CoffFile + HiiRsrcOffset, HiiBinData, HiiBinSize);\r
979     free (HiiBinData);\r
980     HiiBinData = NULL;\r
981     HiiBinSize = 0;\r
982   } else {\r
983     // Don't make a section of size 0. \r
984     NtHdr->Pe32.FileHeader.NumberOfSections--;\r
985   }\r
986 \r
987 }\r
988 \r
989 VOID\r
990 WriteSections(\r
991   int   (*Filter)(Elf_Shdr *)\r
992   )\r
993 {\r
994   UINT32      Idx;\r
995   Elf_Shdr  *SecShdr;\r
996   UINT32      SecOffset;\r
997 \r
998   //\r
999   // First: copy sections.\r
1000   //\r
1001   for (Idx = 0; Idx < Ehdr->e_shnum; Idx++) {\r
1002     Elf_Shdr *Shdr = GetShdrByIndex(Idx);\r
1003     if ((*Filter)(Shdr)) {\r
1004       switch (Shdr->sh_type) {\r
1005       case SHT_PROGBITS:\r
1006         /* Copy.  */\r
1007         memcpy(CoffFile + CoffSectionsOffset[Idx],\r
1008               (UINT8*)Ehdr + Shdr->sh_offset,\r
1009               Shdr->sh_size);\r
1010         break;\r
1011       \r
1012       case SHT_NOBITS:\r
1013         memset(CoffFile + CoffSectionsOffset[Idx], 0, Shdr->sh_size);\r
1014         break;\r
1015       \r
1016       default:\r
1017         //\r
1018         //  Ignore for unkown section type.\r
1019         //\r
1020         VerboseMsg ("%s unknown section type %x. We directly copy this section into Coff file", mInImageName, (unsigned)Shdr->sh_type);\r
1021         break;\r
1022       }\r
1023     }\r
1024   }\r
1025 \r
1026   //\r
1027   // Second: apply relocations.\r
1028   //\r
1029   for (Idx = 0; Idx < Ehdr->e_shnum; Idx++) {\r
1030     Elf_Shdr *RelShdr = GetShdrByIndex(Idx);\r
1031     if (RelShdr->sh_type != SHT_REL)\r
1032       continue;\r
1033     SecShdr = GetShdrByIndex(RelShdr->sh_info);\r
1034     SecOffset = CoffSectionsOffset[RelShdr->sh_info];\r
1035     if (RelShdr->sh_type == SHT_REL && (*Filter)(SecShdr)) {\r
1036       UINT32 RelIdx;\r
1037       Elf_Shdr *SymtabShdr = GetShdrByIndex(RelShdr->sh_link);\r
1038       UINT8 *Symtab = (UINT8*)Ehdr + SymtabShdr->sh_offset;\r
1039 \r
1040       for (RelIdx = 0; RelIdx < RelShdr->sh_size; RelIdx += RelShdr->sh_entsize) {\r
1041         Elf_Rel *Rel = (Elf_Rel *)((UINT8*)Ehdr + RelShdr->sh_offset + RelIdx);\r
1042         Elf_Sym *Sym = (Elf_Sym *)(Symtab + ELF_R_SYM(Rel->r_info) * SymtabShdr->sh_entsize);\r
1043         Elf_Shdr *SymShdr;\r
1044         UINT8 *Targ;\r
1045 \r
1046         if (Sym->st_shndx == SHN_UNDEF\r
1047             || Sym->st_shndx == SHN_ABS\r
1048             || Sym->st_shndx > Ehdr->e_shnum) {\r
1049           Error (NULL, 0, 3000, "Invalid", "%s bad symbol definition.", mInImageName);\r
1050         }\r
1051         SymShdr = GetShdrByIndex(Sym->st_shndx);\r
1052 \r
1053         //\r
1054         // Note: r_offset in a memory address.\r
1055         //  Convert it to a pointer in the coff file.\r
1056         //\r
1057         Targ = CoffFile + SecOffset + (Rel->r_offset - SecShdr->sh_addr);\r
1058 \r
1059         if (Ehdr->e_machine == EM_386) {\r
1060           switch (ELF_R_TYPE(Rel->r_info)) {\r
1061           case R_386_NONE:\r
1062             break;\r
1063           case R_386_32:\r
1064             //\r
1065             // Absolute relocation.\r
1066             //\r
1067             *(UINT32 *)Targ = *(UINT32 *)Targ - SymShdr->sh_addr\r
1068               + CoffSectionsOffset[Sym->st_shndx];\r
1069             break;\r
1070           case R_386_PC32:\r
1071             //\r
1072             // Relative relocation: Symbol - Ip + Addend\r
1073             //\r
1074             *(UINT32 *)Targ = *(UINT32 *)Targ\r
1075               + (CoffSectionsOffset[Sym->st_shndx] - SymShdr->sh_addr)\r
1076               - (SecOffset - SecShdr->sh_addr);\r
1077             break;\r
1078           default:\r
1079             Error (NULL, 0, 3000, "Invalid", "%s unhandled section type %x.", mInImageName, (unsigned) ELF_R_TYPE(Rel->r_info));\r
1080           }\r
1081         } else if (Ehdr->e_machine == EM_ARM) {\r
1082           switch (ELF32_R_TYPE(Rel->r_info)) {\r
1083           case R_ARM_RBASE:   // No relocation - no action required\r
1084           case R_ARM_PC24:    // PC-relative relocations don't require modification\r
1085           case R_ARM_XPC25:   // PC-relative relocations don't require modification\r
1086             break;\r
1087           case R_ARM_ABS32:\r
1088           case R_ARM_RABS32:\r
1089             //\r
1090             // Absolute relocation.\r
1091             //\r
1092             *(UINT32 *)Targ = *(UINT32 *)Targ - SymShdr->sh_addr + CoffSectionsOffset[Sym->st_shndx];\r
1093             break;\r
1094           default:\r
1095             Error (NULL, 0, 3000, "Invalid", "%s unhandled section type %x.", mInImageName, (unsigned) ELF32_R_TYPE(Rel->r_info));\r
1096           }\r
1097         }\r
1098       }\r
1099     }\r
1100   }\r
1101 }\r
1102 \r
1103 VOID\r
1104 CoffAddFixupEntry(\r
1105   UINT16 Val\r
1106   )\r
1107 {\r
1108   *CoffEntryRel = Val;\r
1109   CoffEntryRel++;\r
1110   CoffBaseRel->SizeOfBlock += 2;\r
1111   CoffOffset += 2;\r
1112 }\r
1113 \r
1114 VOID\r
1115 CoffAddFixup(\r
1116   UINT32 Offset,\r
1117   UINT8  Type\r
1118   )\r
1119 {\r
1120   if (CoffBaseRel == NULL\r
1121       || CoffBaseRel->VirtualAddress != (Offset & ~0xfff)) {\r
1122     if (CoffBaseRel != NULL) {\r
1123       //\r
1124       // Add a null entry (is it required ?)\r
1125       //\r
1126       CoffAddFixupEntry (0);\r
1127       //\r
1128       // Pad for alignment.\r
1129       //\r
1130       if (CoffOffset % 4 != 0)\r
1131         CoffAddFixupEntry (0);\r
1132     }\r
1133 \r
1134     CoffFile = realloc\r
1135       (CoffFile,\r
1136        CoffOffset + sizeof(EFI_IMAGE_BASE_RELOCATION) + 2*0x1000);\r
1137     memset(CoffFile + CoffOffset, 0,\r
1138      sizeof(EFI_IMAGE_BASE_RELOCATION) + 2*0x1000);\r
1139 \r
1140     CoffBaseRel = (EFI_IMAGE_BASE_RELOCATION*)(CoffFile + CoffOffset);\r
1141     CoffBaseRel->VirtualAddress = Offset & ~0xfff;\r
1142     CoffBaseRel->SizeOfBlock = sizeof(EFI_IMAGE_BASE_RELOCATION);\r
1143 \r
1144     CoffEntryRel = (UINT16 *)(CoffBaseRel + 1);\r
1145     CoffOffset += sizeof(EFI_IMAGE_BASE_RELOCATION);\r
1146   }\r
1147 \r
1148   //\r
1149   // Fill the entry.\r
1150   //\r
1151   CoffAddFixupEntry((UINT16) ((Type << 12) | (Offset & 0xfff)));\r
1152 }\r
1153 \r
1154 \r
1155 Elf_Phdr *\r
1156 GetPhdrByIndex (\r
1157   UINT32 num\r
1158   )\r
1159 {\r
1160   if (num >= Ehdr->e_phnum) {\r
1161     return NULL;\r
1162   }\r
1163   \r
1164   return (Elf32_Phdr *)((UINT8*)gPhdrBase + num * Ehdr->e_phentsize);\r
1165 }\r
1166 \r
1167 \r
1168 VOID\r
1169 WriteRelocations(\r
1170   VOID\r
1171   )\r
1172 {\r
1173   UINT32                           Index;\r
1174   EFI_IMAGE_OPTIONAL_HEADER_UNION  *NtHdr;\r
1175   EFI_IMAGE_DATA_DIRECTORY         *Dir;\r
1176   BOOLEAN                          FoundRelocations;\r
1177   Elf_Dyn                          *Dyn;\r
1178   Elf_Rel                          *Rel;\r
1179   UINTN                            RelElementSize;\r
1180   UINTN                            RelSize;\r
1181   UINTN                            RelOffset;\r
1182   UINTN                            K;\r
1183   UINT8                            *Targ;\r
1184   Elf32_Phdr                       *DynamicSegment;\r
1185   Elf32_Phdr                       *TargetSegment;\r
1186 \r
1187   for (Index = 0, FoundRelocations = FALSE; Index < Ehdr->e_shnum; Index++) {\r
1188     Elf_Shdr *RelShdr = GetShdrByIndex(Index);\r
1189     if (RelShdr->sh_type == SHT_REL) {\r
1190       Elf_Shdr *SecShdr = GetShdrByIndex(RelShdr->sh_info);\r
1191       if (IsTextShdr(SecShdr) || IsDataShdr(SecShdr)) {\r
1192         UINT32 RelIdx;\r
1193         FoundRelocations = TRUE;\r
1194         for (RelIdx = 0; RelIdx < RelShdr->sh_size; RelIdx += RelShdr->sh_entsize) {\r
1195           Elf_Rel *Rel = (Elf_Rel *)\r
1196             ((UINT8*)Ehdr + RelShdr->sh_offset + RelIdx);\r
1197           \r
1198           if (Ehdr->e_machine == EM_386) { \r
1199             switch (ELF_R_TYPE(Rel->r_info)) {\r
1200             case R_386_NONE:\r
1201             case R_386_PC32:\r
1202               break;\r
1203             case R_386_32:\r
1204               CoffAddFixup(CoffSectionsOffset[RelShdr->sh_info]\r
1205               + (Rel->r_offset - SecShdr->sh_addr),\r
1206               EFI_IMAGE_REL_BASED_HIGHLOW);\r
1207               break;\r
1208             default:\r
1209               Error (NULL, 0, 3000, "Invalid", "%s unhandled section type %x.", mInImageName, (unsigned) ELF_R_TYPE(Rel->r_info));\r
1210             }\r
1211           } else if (Ehdr->e_machine == EM_ARM) {\r
1212             switch (ELF32_R_TYPE(Rel->r_info)) {\r
1213             case R_ARM_RBASE:\r
1214             case R_ARM_PC24:\r
1215             case R_ARM_XPC25:\r
1216               break;\r
1217             case R_ARM_ABS32:\r
1218             case R_ARM_RABS32:\r
1219               CoffAddFixup (\r
1220                 CoffSectionsOffset[RelShdr->sh_info]\r
1221                 + (Rel->r_offset - SecShdr->sh_addr),\r
1222                 EFI_IMAGE_REL_BASED_HIGHLOW\r
1223                 );\r
1224               break;\r
1225             default:\r
1226               Error (NULL, 0, 3000, "Invalid", "%s unhandled section type %x.", mInImageName, (unsigned) ELF32_R_TYPE(Rel->r_info));\r
1227             }\r
1228           } else {\r
1229             Error (NULL, 0, 3000, "Not Supported", "This tool does not support relocations for ELF with e_machine %u (processor type).", (unsigned) Ehdr->e_machine);\r
1230           }\r
1231         }\r
1232       }\r
1233     }\r
1234   }\r
1235 \r
1236   if (!FoundRelocations && (Ehdr->e_machine == EM_ARM)) {\r
1237     /* Try again, but look for PT_DYNAMIC instead of SHT_REL */\r
1238 \r
1239     for (Index = 0; Index < Ehdr->e_phnum; Index++) {\r
1240       RelElementSize = 0;\r
1241       RelSize = 0;\r
1242       RelOffset = 0;\r
1243 \r
1244       DynamicSegment = GetPhdrByIndex (Index);\r
1245 \r
1246       if (DynamicSegment->p_type == PT_DYNAMIC) {\r
1247         Dyn = (Elf32_Dyn *) ((UINT8 *)Ehdr + DynamicSegment->p_offset);\r
1248 \r
1249         while (Dyn->d_tag != DT_NULL) {\r
1250           switch (Dyn->d_tag) {\r
1251             case  DT_REL:\r
1252               RelOffset = Dyn->d_un.d_val;\r
1253               break;\r
1254 \r
1255             case  DT_RELSZ:\r
1256               RelSize = Dyn->d_un.d_val;\r
1257               break;\r
1258 \r
1259             case  DT_RELENT:\r
1260               RelElementSize = Dyn->d_un.d_val;\r
1261               break;\r
1262           }\r
1263           Dyn++;\r
1264         }\r
1265         if (( RelOffset == 0 ) || ( RelSize == 0 ) || ( RelElementSize == 0 )) {\r
1266           Error (NULL, 0, 3000, "Invalid", "%s bad ARM dynamic relocations.", mInImageName);\r
1267         }\r
1268 \r
1269         for (K = 0; K < RelSize; K += RelElementSize) {\r
1270 \r
1271           Rel = (Elf32_Rel *) ((UINT8 *) Ehdr + DynamicSegment->p_offset + RelOffset + K);\r
1272 \r
1273           switch (ELF32_R_TYPE (Rel->r_info)) {\r
1274           case  R_ARM_RBASE:\r
1275             break;\r
1276           case  R_ARM_RABS32:\r
1277             TargetSegment = GetPhdrByIndex (ELF32_R_SYM (Rel->r_info) - 1);\r
1278 \r
1279             // Note: r_offset in a memory address.  Convert it to a pointer in the coff file.\r
1280             Targ = CoffFile + CoffSectionsOffset[ ELF32_R_SYM( Rel->r_info ) ] + Rel->r_offset - TargetSegment->p_vaddr;\r
1281 \r
1282             *(UINT32 *)Targ = *(UINT32 *)Targ + CoffSectionsOffset [ELF32_R_SYM( Rel->r_info )];\r
1283 \r
1284             CoffAddFixup (CoffSectionsOffset[ELF32_R_SYM (Rel->r_info)] + (Rel->r_offset - TargetSegment->p_vaddr), EFI_IMAGE_REL_BASED_HIGHLOW);\r
1285             break;\r
1286           default:\r
1287             Error (NULL, 0, 3000, "Invalid", "%s bad ARM dynamic relocations, unkown type.", mInImageName);\r
1288           }\r
1289         }\r
1290         break;\r
1291       }\r
1292     }\r
1293   }\r
1294 \r
1295   //\r
1296   // Pad by adding empty entries.\r
1297   //\r
1298   while (CoffOffset & (CoffAlignment - 1)) {\r
1299     CoffAddFixupEntry(0);\r
1300   }\r
1301 \r
1302 \r
1303   NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(CoffFile + NtHdrOffset);\r
1304   Dir = &NtHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];\r
1305   Dir->Size = CoffOffset - RelocOffset;\r
1306   if (Dir->Size == 0) {\r
1307     // If no relocations, null out the directory entry and don't add the .reloc section\r
1308     Dir->VirtualAddress = 0;\r
1309     NtHdr->Pe32.FileHeader.NumberOfSections--;\r
1310   } else {\r
1311     Dir->VirtualAddress = RelocOffset;\r
1312     CreateSectionHeader (".reloc", RelocOffset, CoffOffset - RelocOffset,\r
1313             EFI_IMAGE_SCN_CNT_INITIALIZED_DATA\r
1314             | EFI_IMAGE_SCN_MEM_DISCARDABLE\r
1315             | EFI_IMAGE_SCN_MEM_READ);\r
1316   }\r
1317 \r
1318 }\r
1319 \r
1320 VOID\r
1321 WriteDebug(\r
1322   VOID\r
1323   )\r
1324 {\r
1325   UINT32                              Len;\r
1326   UINT32                              DebugOffset;\r
1327   EFI_IMAGE_OPTIONAL_HEADER_UNION     *NtHdr;\r
1328   EFI_IMAGE_DATA_DIRECTORY            *DataDir;\r
1329   EFI_IMAGE_DEBUG_DIRECTORY_ENTRY     *Dir;\r
1330   EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY *Nb10;\r
1331 \r
1332   Len = strlen(mInImageName) + 1;\r
1333   DebugOffset = CoffOffset;\r
1334 \r
1335   CoffOffset += sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY)\r
1336     + sizeof(EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY)\r
1337     + Len;\r
1338   CoffOffset = CoffAlign(CoffOffset);\r
1339 \r
1340   CoffFile = realloc(CoffFile, CoffOffset);\r
1341   memset(CoffFile + DebugOffset, 0, CoffOffset - DebugOffset);\r
1342 \r
1343   Dir = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY*)(CoffFile + DebugOffset);\r
1344   Dir->Type = EFI_IMAGE_DEBUG_TYPE_CODEVIEW;\r
1345   Dir->SizeOfData = sizeof(EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY) + Len;\r
1346   Dir->RVA = DebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);\r
1347   Dir->FileOffset = DebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);\r
1348 \r
1349   Nb10 = (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY*)(Dir + 1);\r
1350   Nb10->Signature = CODEVIEW_SIGNATURE_NB10;\r
1351   strcpy ((char *)(Nb10 + 1), mInImageName);\r
1352 \r
1353 \r
1354   NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(CoffFile + NtHdrOffset);\r
1355   DataDir = &NtHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG];\r
1356   DataDir->VirtualAddress = DebugOffset;\r
1357   DataDir->Size = CoffOffset - DebugOffset;\r
1358   if (DataDir->Size == 0) {\r
1359     // If no debug, null out the directory entry and don't add the .debug section\r
1360     DataDir->VirtualAddress = 0;\r
1361     NtHdr->Pe32.FileHeader.NumberOfSections--;\r
1362   } else {\r
1363     DataDir->VirtualAddress = DebugOffset;\r
1364     CreateSectionHeader (".debug", DebugOffset, CoffOffset - DebugOffset,\r
1365             EFI_IMAGE_SCN_CNT_INITIALIZED_DATA\r
1366             | EFI_IMAGE_SCN_MEM_DISCARDABLE\r
1367             | EFI_IMAGE_SCN_MEM_READ);\r
1368 \r
1369   }\r
1370 }\r
1371 \r
1372 VOID\r
1373 ConvertElf (\r
1374   UINT8  **FileBuffer,\r
1375   UINT32 *FileLength\r
1376   )\r
1377 {\r
1378   EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr;\r
1379 \r
1380   //\r
1381   // Check header, read section table.\r
1382   //\r
1383   Ehdr = (Elf32_Ehdr*)*FileBuffer;\r
1384   if (!CheckElfHeader())\r
1385     return;\r
1386 \r
1387   VerboseMsg ("Check Efl Image Header");\r
1388   //\r
1389   // Compute sections new address.\r
1390   //\r
1391   \r
1392   ScanSections();\r
1393 \r
1394   VerboseMsg ("Compute sections new address.");\r
1395 \r
1396   //\r
1397   // Write and relocate sections.\r
1398   //\r
1399   WriteSections(IsTextShdr);\r
1400   WriteSections(IsDataShdr);\r
1401   VerboseMsg ("Write and relocate sections.");\r
1402 \r
1403   //\r
1404   // Translate and write relocations.\r
1405   //\r
1406   WriteRelocations();\r
1407   VerboseMsg ("Translate and write relocations.");\r
1408 \r
1409   //\r
1410   // Write debug info.\r
1411   //\r
1412   WriteDebug();\r
1413   VerboseMsg ("Write debug info.");\r
1414 \r
1415   NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(CoffFile + NtHdrOffset);\r
1416   NtHdr->Pe32.OptionalHeader.SizeOfImage = CoffOffset;\r
1417 \r
1418   //\r
1419   // Replace.\r
1420   //\r
1421   free(*FileBuffer);\r
1422   *FileBuffer = CoffFile;\r
1423   *FileLength = CoffOffset;\r
1424 \r
1425   //\r
1426   // Free memory space\r
1427   //\r
1428   if (CoffSectionsOffset != NULL) {\r
1429     free (CoffSectionsOffset);\r
1430   }\r
1431 }\r
1432 \r
1433 int\r
1434 main (\r
1435   int  argc,\r
1436   char *argv[]\r
1437   )\r
1438 /*++\r
1439 \r
1440 Routine Description:\r
1441 \r
1442   Main function.\r
1443 \r
1444 Arguments:\r
1445 \r
1446   argc - Number of command line parameters.\r
1447   argv - Array of pointers to command line parameter strings.\r
1448 \r
1449 Returns:\r
1450   STATUS_SUCCESS - Utility exits successfully.\r
1451   STATUS_ERROR   - Some error occurred during execution.\r
1452 \r
1453 --*/\r
1454 {\r
1455   UINT32                           Type;\r
1456   UINT32                           InputFileNum;\r
1457   CHAR8                            **InputFileName;\r
1458   char                             *OutImageName;\r
1459   char                             *ModuleType;\r
1460   CHAR8                            *TimeStamp;\r
1461   UINT32                           OutImageType;\r
1462   FILE                             *fpIn;\r
1463   FILE                             *fpOut;\r
1464   FILE                             *fpInOut;\r
1465   UINT32                           Data;\r
1466   UINT32                           *DataPointer;\r
1467   UINT32                           *OldDataPointer;\r
1468   UINT32                           CheckSum;\r
1469   UINT32                           Index;\r
1470   UINT32                           Index1;\r
1471   UINT32                           Index2;\r
1472   UINT64                           Temp64;\r
1473   UINT32                           MciAlignment;\r
1474   UINT8                            MciPadValue;\r
1475   UINT32                           AllignedRelocSize;\r
1476   UINT8                            *FileBuffer;\r
1477   UINT32                           FileLength;\r
1478   UINT8                            *OutputFileBuffer;\r
1479   UINT32                           OutputFileLength;\r
1480   RUNTIME_FUNCTION                 *RuntimeFunction;\r
1481   UNWIND_INFO                      *UnwindInfo;\r
1482   STATUS                           Status;\r
1483   BOOLEAN                          ReplaceFlag;\r
1484   BOOLEAN                          KeepExceptionTableFlag;\r
1485   BOOLEAN                          KeepZeroPendingFlag;\r
1486   UINT64                           LogLevel;\r
1487   EFI_TE_IMAGE_HEADER              TEImageHeader;\r
1488   EFI_TE_IMAGE_HEADER              *TeHdr;\r
1489   EFI_IMAGE_SECTION_HEADER         *SectionHeader;\r
1490   EFI_IMAGE_DOS_HEADER             *DosHdr;\r
1491   EFI_IMAGE_OPTIONAL_HEADER_UNION  *PeHdr;\r
1492   EFI_IMAGE_OPTIONAL_HEADER32      *Optional32;\r
1493   EFI_IMAGE_OPTIONAL_HEADER64      *Optional64;\r
1494   EFI_IMAGE_DOS_HEADER             BackupDosHdr;\r
1495   MICROCODE_IMAGE_HEADER           *MciHeader;\r
1496   UINT8                            *HiiPackageListBuffer;\r
1497   UINT8                            *HiiPackageDataPointer;\r
1498   EFI_GUID                         HiiPackageListGuid;\r
1499   EFI_HII_PACKAGE_LIST_HEADER      HiiPackageListHeader;\r
1500   EFI_HII_PACKAGE_HEADER           HiiPackageHeader;\r
1501   EFI_IFR_FORM_SET                 IfrFormSet;\r
1502   UINT8                            NumberOfFormPacakge;\r
1503   EFI_HII_PACKAGE_HEADER           EndPackage;\r
1504 \r
1505   SetUtilityName (UTILITY_NAME);\r
1506 \r
1507   //\r
1508   // Assign to fix compile warning\r
1509   //\r
1510   InputFileNum      = 0;\r
1511   InputFileName     = NULL;\r
1512   mInImageName      = NULL;\r
1513   OutImageName      = NULL;\r
1514   ModuleType        = NULL;\r
1515   OutImageType      = FW_DUMMY_IMAGE;\r
1516   Type              = 0;\r
1517   Status            = STATUS_SUCCESS;\r
1518   FileBuffer        = NULL;\r
1519   fpIn              = NULL;\r
1520   fpOut             = NULL;\r
1521   fpInOut           = NULL;\r
1522   TimeStamp         = NULL;\r
1523   MciAlignment      = DEFAULT_MC_ALIGNMENT;\r
1524   MciPadValue       = DEFAULT_MC_PAD_BYTE_VALUE;\r
1525   FileLength        = 0;\r
1526   MciHeader         = NULL;\r
1527   CheckSum          = 0;\r
1528   ReplaceFlag       = FALSE;\r
1529   LogLevel          = 0;\r
1530   OutputFileBuffer  = NULL;\r
1531   OutputFileLength  = 0;\r
1532   Optional32        = NULL;\r
1533   Optional64        = NULL;\r
1534   KeepExceptionTableFlag = FALSE;\r
1535   KeepZeroPendingFlag    = FALSE;\r
1536   NumberOfFormPacakge    = 0;\r
1537   HiiPackageListBuffer   = NULL;\r
1538   HiiPackageDataPointer  = NULL;\r
1539   EndPackage.Length      = sizeof (EFI_HII_PACKAGE_HEADER);\r
1540   EndPackage.Type        = EFI_HII_PACKAGE_END;\r
1541   memset (&HiiPackageListGuid, 0, sizeof (HiiPackageListGuid));\r
1542 \r
1543   if (argc == 1) {\r
1544     Error (NULL, 0, 1001, "Missing options", "No input options.");\r
1545     Usage ();\r
1546     return STATUS_ERROR;\r
1547   }\r
1548 \r
1549   argc --;\r
1550   argv ++;\r
1551 \r
1552   if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) {\r
1553     Version ();\r
1554     Usage ();\r
1555     return STATUS_SUCCESS;\r
1556   }\r
1557 \r
1558   if (stricmp (argv[0], "--version") == 0) {\r
1559     Version ();\r
1560     return STATUS_SUCCESS;\r
1561   }\r
1562 \r
1563   while (argc > 0) {\r
1564     if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--outputfile") == 0)) {\r
1565       if (argv[1] == NULL || argv[1][0] == '-') {\r
1566         Error (NULL, 0, 1003, "Invalid option value", "Output file name is missing for -o option");\r
1567         goto Finish;\r
1568       }\r
1569       OutImageName = argv[1];\r
1570       argc -= 2;\r
1571       argv += 2;\r
1572       continue;\r
1573     }\r
1574 \r
1575     if ((stricmp (argv[0], "-e") == 0) || (stricmp (argv[0], "--efiImage") == 0)) {\r
1576       if (argv[1] == NULL || argv[1][0] == '-') {\r
1577         Error (NULL, 0, 1003, "Invalid option value", "Module Type is missing for -o option");\r
1578         goto Finish;\r
1579       }\r
1580       ModuleType = argv[1];\r
1581       if (OutImageType != FW_TE_IMAGE) {\r
1582         OutImageType = FW_EFI_IMAGE;\r
1583       }\r
1584       argc -= 2;\r
1585       argv += 2;\r
1586       continue;\r
1587     }\r
1588 \r
1589     if ((stricmp (argv[0], "-l") == 0) || (stricmp (argv[0], "--stripped") == 0)) {\r
1590       OutImageType = FW_RELOC_STRIPEED_IMAGE;\r
1591       argc --;\r
1592       argv ++;\r
1593       continue;\r
1594     }\r
1595 \r
1596     if ((stricmp (argv[0], "-c") == 0) || (stricmp (argv[0], "--acpi") == 0)) {\r
1597       OutImageType = FW_ACPI_IMAGE;\r
1598       argc --;\r
1599       argv ++;\r
1600       continue;\r
1601     }\r
1602 \r
1603     if ((stricmp (argv[0], "-t") == 0) || (stricmp (argv[0], "--terse") == 0)) {\r
1604       OutImageType = FW_TE_IMAGE;\r
1605       argc --;\r
1606       argv ++;\r
1607       continue;\r
1608     }\r
1609 \r
1610     if ((stricmp (argv[0], "-u") == 0) || (stricmp (argv[0], "--dump") == 0)) {\r
1611       OutImageType = DUMP_TE_HEADER;\r
1612       argc --;\r
1613       argv ++;\r
1614       continue;\r
1615     }\r
1616 \r
1617     if ((stricmp (argv[0], "-b") == 0) || (stricmp (argv[0], "--exe2bin") == 0)) {\r
1618       OutImageType = FW_BIN_IMAGE;\r
1619       argc --;\r
1620       argv ++;\r
1621       continue;\r
1622     }\r
1623 \r
1624     if ((stricmp (argv[0], "-z") == 0) || (stricmp (argv[0], "--zero") == 0)) {\r
1625       OutImageType = FW_ZERO_DEBUG_IMAGE;\r
1626       argc --;\r
1627       argv ++;\r
1628       continue;\r
1629     }\r
1630 \r
1631     if ((stricmp (argv[0], "-s") == 0) || (stricmp (argv[0], "--stamp") == 0)) {\r
1632       OutImageType = FW_SET_STAMP_IMAGE;\r
1633       if (argv[1] == NULL || argv[1][0] == '-') {\r
1634         Error (NULL, 0, 1003, "Invalid option value", "time stamp is missing for -s option");\r
1635         goto Finish;\r
1636       }\r
1637       TimeStamp = argv[1];\r
1638       argc -= 2;\r
1639       argv += 2;\r
1640       continue;\r
1641     }\r
1642 \r
1643     if ((stricmp (argv[0], "-r") == 0) || (stricmp (argv[0], "--replace") == 0)) {\r
1644       ReplaceFlag = TRUE;\r
1645       argc --;\r
1646       argv ++;\r
1647       continue;\r
1648     }\r
1649 \r
1650     if (stricmp (argv[0], "--keepexceptiontable") == 0) {\r
1651       KeepExceptionTableFlag = TRUE;\r
1652       argc --;\r
1653       argv ++;\r
1654       continue;\r
1655     }\r
1656 \r
1657     if (stricmp (argv[0], "--keepzeropending") == 0) {\r
1658       KeepZeroPendingFlag = TRUE;\r
1659       argc --;\r
1660       argv ++;\r
1661       continue;\r
1662     }\r
1663 \r
1664     if ((stricmp (argv[0], "-m") == 0) || (stricmp (argv[0], "--mcifile") == 0)) {\r
1665       OutImageType = FW_MCI_IMAGE;\r
1666       argc --;\r
1667       argv ++;\r
1668       continue;\r
1669     }\r
1670 \r
1671     if ((stricmp (argv[0], "-j") == 0) || (stricmp (argv[0], "--join") == 0)) {\r
1672       OutImageType = FW_MERGE_IMAGE;\r
1673       argc --;\r
1674       argv ++;\r
1675       continue;\r
1676     }\r
1677 \r
1678     if ((stricmp (argv[0], "-a") == 0) || (stricmp (argv[0], "--align") == 0)) {\r
1679       if (AsciiStringToUint64 (argv[1], FALSE, &Temp64) != EFI_SUCCESS) {\r
1680         Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
1681         goto Finish;\r
1682       }\r
1683       MciAlignment = (UINT32) Temp64;\r
1684       argc -= 2;\r
1685       argv += 2;\r
1686       continue;\r
1687     }\r
1688 \r
1689     if ((stricmp (argv[0], "-p") == 0) || (stricmp (argv[0], "--pad") == 0)) {\r
1690       if (AsciiStringToUint64 (argv[1], FALSE, &Temp64) != EFI_SUCCESS) {\r
1691         Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
1692         goto Finish;\r
1693       }\r
1694       MciPadValue = (UINT8) Temp64;\r
1695       argc -= 2;\r
1696       argv += 2;\r
1697       continue;\r
1698     }\r
1699 \r
1700     if ((stricmp (argv[0], "-v") == 0) || (stricmp (argv[0], "--verbose") == 0)) {\r
1701       SetPrintLevel (VERBOSE_LOG_LEVEL);\r
1702       VerboseMsg ("Verbose output Mode Set!");\r
1703       argc --;\r
1704       argv ++;\r
1705       continue;\r
1706     }\r
1707 \r
1708     if ((stricmp (argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) {\r
1709       SetPrintLevel (KEY_LOG_LEVEL);\r
1710       KeyMsg ("Quiet output Mode Set!");\r
1711       argc --;\r
1712       argv ++;\r
1713       continue;\r
1714     }\r
1715 \r
1716     if ((stricmp (argv[0], "-d") == 0) || (stricmp (argv[0], "--debug") == 0)) {\r
1717       Status = AsciiStringToUint64 (argv[1], FALSE, &LogLevel);\r
1718       if (EFI_ERROR (Status)) {\r
1719         Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
1720         goto Finish;\r
1721       }\r
1722       if (LogLevel > 9) {\r
1723         Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0-9, currnt input level is %d", (int) LogLevel);\r
1724         goto Finish;\r
1725       }\r
1726       SetPrintLevel (LogLevel);\r
1727       DebugMsg (NULL, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv[1]);\r
1728       argc -= 2;\r
1729       argv += 2;\r
1730       continue;\r
1731     }\r
1732     \r
1733     if ((stricmp (argv[0], "-g") == 0) || (stricmp (argv[0], "--hiiguid") == 0)) {\r
1734       Status = StringToGuid (argv[1], &HiiPackageListGuid);\r
1735       if (EFI_ERROR (Status)) {\r
1736         Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
1737         goto Finish;\r
1738       }\r
1739       argc -= 2;\r
1740       argv += 2;\r
1741       continue;\r
1742     }\r
1743 \r
1744     if (stricmp (argv[0], "--hiipackage") == 0) {\r
1745       OutImageType = FW_HII_PACKAGE_LIST_RCIMAGE;\r
1746       argc --;\r
1747       argv ++;\r
1748       continue;\r
1749     }\r
1750 \r
1751     if (argv[0][0] == '-') {\r
1752       Error (NULL, 0, 1000, "Unknown option", argv[0]);\r
1753       goto Finish;\r
1754     }\r
1755     //\r
1756     // Get Input file name\r
1757     //\r
1758     if ((InputFileNum == 0) && (InputFileName == NULL)) {\r
1759       InputFileName = (CHAR8 **) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *));\r
1760       if (InputFileName == NULL) {\r
1761         Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
1762         goto Finish;\r
1763       }\r
1764 \r
1765       memset (InputFileName, 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));\r
1766     } else if (InputFileNum % MAXIMUM_INPUT_FILE_NUM == 0) {\r
1767       //\r
1768       // InputFileName buffer too small, need to realloc\r
1769       //\r
1770       InputFileName = (CHAR8 **) realloc (\r
1771                                   InputFileName,\r
1772                                   (InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (CHAR8 *)\r
1773                                   );\r
1774 \r
1775       if (InputFileName == NULL) {\r
1776         Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
1777         goto Finish;\r
1778       }\r
1779 \r
1780       memset (&(InputFileName[InputFileNum]), 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));\r
1781     }\r
1782 \r
1783     InputFileName [InputFileNum ++] = argv[0];\r
1784     argc --;\r
1785     argv ++;\r
1786   }\r
1787 \r
1788   VerboseMsg ("%s tool start.", UTILITY_NAME);\r
1789 \r
1790   if (OutImageType == FW_DUMMY_IMAGE) {\r
1791     Error (NULL, 0, 1001, "Missing option", "No create file action specified; pls specify -e, -c or -t option to create efi image, or acpi table or TeImage!");\r
1792     if (ReplaceFlag) {\r
1793       Error (NULL, 0, 1001, "Missing option", "-r option is not supported as the independent option. It can be used together with other create file option specified at the above.");\r
1794     }\r
1795     goto Finish;\r
1796   }\r
1797 \r
1798   //\r
1799   // check input files\r
1800   //\r
1801   if (InputFileNum == 0) {\r
1802     Error (NULL, 0, 1001, "Missing option", "Input files");\r
1803     goto Finish;\r
1804   }\r
1805 \r
1806   //\r
1807   // Combine MciBinary files to one file\r
1808   //\r
1809   if ((OutImageType == FW_MERGE_IMAGE) && ReplaceFlag) {\r
1810     Error (NULL, 0, 1002, "Conflicting option", "-r replace option cannot be used with -j merge files option.");\r
1811     goto Finish;\r
1812   }\r
1813 \r
1814   //\r
1815   // Combine HiiBinary packages to a single package list\r
1816   //\r
1817   if ((OutImageType == FW_HII_PACKAGE_LIST_RCIMAGE) && ReplaceFlag) {\r
1818     Error (NULL, 0, 1002, "Conflicting option", "-r replace option cannot be used with --hiipackage merge files option.");\r
1819     goto Finish;\r
1820   }\r
1821 \r
1822   //\r
1823   // Input image file\r
1824   //\r
1825   mInImageName = InputFileName [InputFileNum - 1];\r
1826   VerboseMsg ("the input file name is %s", mInImageName);\r
1827 \r
1828   //\r
1829   // Action will be taken for the input file.\r
1830   //\r
1831   switch (OutImageType) {\r
1832   case FW_EFI_IMAGE:\r
1833     VerboseMsg ("Create efi image on module type %s based on the input PE image.", ModuleType);\r
1834     break;\r
1835   case FW_TE_IMAGE:\r
1836     VerboseMsg ("Create Te Image based on the input PE image.");\r
1837     break;\r
1838   case FW_ACPI_IMAGE:\r
1839     VerboseMsg ("Get acpi table data from the input PE image.");\r
1840     break;\r
1841   case FW_RELOC_STRIPEED_IMAGE:\r
1842     VerboseMsg ("Remove relocation section from Pe or Te image.");\r
1843     break;\r
1844   case FW_BIN_IMAGE:\r
1845     VerboseMsg ("Convert the input EXE to the output BIN file.");\r
1846     break;\r
1847   case FW_ZERO_DEBUG_IMAGE:\r
1848     VerboseMsg ("Zero the Debug Data Fields and Time Stamp in input PE image.");\r
1849     break;\r
1850   case FW_SET_STAMP_IMAGE:\r
1851     VerboseMsg ("Set new time stamp %s in the input PE image.", TimeStamp);\r
1852     break;\r
1853   case DUMP_TE_HEADER:\r
1854     VerboseMsg ("Dump the TE header information of the input TE image.");\r
1855     break;\r
1856   case FW_MCI_IMAGE:\r
1857     VerboseMsg ("Conver input MicroCode.txt file to MicroCode.bin file.");\r
1858     break;\r
1859   case FW_MERGE_IMAGE:\r
1860     VerboseMsg ("Combine the input multi microcode bin files to one bin file.");\r
1861     break;\r
1862   case FW_HII_PACKAGE_LIST_RCIMAGE:\r
1863     VerboseMsg ("Combine the input multi hii bin packages to one text pacakge list RC file.");\r
1864     break;\r
1865   default:\r
1866     break;\r
1867   }\r
1868 \r
1869   if (ReplaceFlag) {\r
1870     VerboseMsg ("Overwrite the input file with the output content.");\r
1871   }\r
1872 \r
1873   //\r
1874   // Open output file and Write image into the output file.\r
1875   //\r
1876   if (OutImageName != NULL) {\r
1877     fpOut = fopen (OutImageName, "rb");\r
1878     if (fpOut != NULL) {\r
1879       OutputFileLength = _filelength (fileno (fpOut));\r
1880       OutputFileBuffer = malloc (OutputFileLength);\r
1881       if (OutputFileBuffer == NULL) {\r
1882         Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
1883         fclose (fpOut);\r
1884         fpOut = NULL;\r
1885         goto Finish;\r
1886       }\r
1887       fread (OutputFileBuffer, 1, OutputFileLength, fpOut);\r
1888       fclose (fpOut);\r
1889     }\r
1890     fpOut = fopen (OutImageName, "wb");\r
1891     if (!fpOut) {\r
1892       Error (NULL, 0, 0001, "Error opening output file", OutImageName);\r
1893       goto Finish;\r
1894     }\r
1895     VerboseMsg ("Output file name is %s", OutImageName);\r
1896   } else if (!ReplaceFlag) {\r
1897     if (OutImageType == DUMP_TE_HEADER) {\r
1898       fpOut = stdout;\r
1899     } else {\r
1900       Error (NULL, 0, 1001, "Missing option", "output file");\r
1901       goto Finish;\r
1902     }\r
1903   }\r
1904 \r
1905   //\r
1906   // Combine multi binary HII package files to a single text package list RC file.\r
1907   //\r
1908   if (OutImageType == FW_HII_PACKAGE_LIST_RCIMAGE) {\r
1909     //\r
1910     // Get hii package list lenght\r
1911     //\r
1912     HiiPackageListHeader.PackageLength = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
1913     for (Index = 0; Index < InputFileNum; Index ++) {\r
1914       fpIn = fopen (InputFileName [Index], "rb");\r
1915       if (!fpIn) {\r
1916         Error (NULL, 0, 0001, "Error opening file", InputFileName [Index]);\r
1917         goto Finish;\r
1918       }\r
1919       FileLength = _filelength (fileno (fpIn));\r
1920       fread (&HiiPackageHeader, 1, sizeof (HiiPackageHeader), fpIn);\r
1921       if (HiiPackageHeader.Type == EFI_HII_PACKAGE_FORM) {\r
1922         if (HiiPackageHeader.Length != FileLength) {\r
1923           Error (NULL, 0, 3000, "Invalid", "The wrong package size is in HII package file %s", InputFileName [Index]);\r
1924           fclose (fpIn);\r
1925           goto Finish;\r
1926         }\r
1927         if (memcmp (&HiiPackageListGuid, &mZeroGuid, sizeof (EFI_GUID)) == 0) {\r
1928           fread (&IfrFormSet, 1, sizeof (IfrFormSet), fpIn);\r
1929           memcpy (&HiiPackageListGuid, &IfrFormSet.Guid, sizeof (EFI_GUID));\r
1930         }\r
1931         NumberOfFormPacakge ++;\r
1932       }\r
1933       HiiPackageListHeader.PackageLength += FileLength;\r
1934       fclose (fpIn);\r
1935     }\r
1936     HiiPackageListHeader.PackageLength += sizeof (EndPackage);\r
1937     //\r
1938     // Check whether hii packages are valid\r
1939     //\r
1940     if (NumberOfFormPacakge > 1) {\r
1941       Error (NULL, 0, 3000, "Invalid", "The input hii packages contains more than one hii form package");\r
1942       goto Finish;\r
1943     }\r
1944     if (memcmp (&HiiPackageListGuid, &mZeroGuid, sizeof (EFI_GUID)) == 0) {\r
1945       Error (NULL, 0, 3000, "Invalid", "HII pacakge list guid is not specified!");\r
1946       goto Finish;\r
1947     }\r
1948     memcpy (&HiiPackageListHeader.PackageListGuid, &HiiPackageListGuid, sizeof (EFI_GUID));\r
1949     //\r
1950     // read hii packages\r
1951     //\r
1952     HiiPackageListBuffer = malloc (HiiPackageListHeader.PackageLength);\r
1953     if (HiiPackageListBuffer == NULL) {\r
1954       Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
1955       goto Finish;\r
1956     }\r
1957     memcpy (HiiPackageListBuffer, &HiiPackageListHeader, sizeof (HiiPackageListHeader));\r
1958     HiiPackageDataPointer = HiiPackageListBuffer + sizeof (HiiPackageListHeader);\r
1959     for (Index = 0; Index < InputFileNum; Index ++) {\r
1960       fpIn = fopen (InputFileName [Index], "rb");\r
1961       if (!fpIn) {\r
1962         Error (NULL, 0, 0001, "Error opening file", InputFileName [Index]);\r
1963         free (HiiPackageListBuffer);\r
1964         goto Finish;\r
1965       }\r
1966 \r
1967       FileLength = _filelength (fileno (fpIn));\r
1968       fread (HiiPackageDataPointer, 1, FileLength, fpIn);\r
1969       fclose (fpIn);\r
1970       HiiPackageDataPointer = HiiPackageDataPointer + FileLength;\r
1971     }\r
1972     memcpy (HiiPackageDataPointer, &EndPackage, sizeof (EndPackage));\r
1973     //\r
1974     // write the hii package into the text package list rc file.\r
1975     //\r
1976     for (Index = 0; gHiiPackageRCFileHeader[Index] != NULL; Index++) {\r
1977       fprintf (fpOut, "%s\n", gHiiPackageRCFileHeader[Index]);\r
1978     }\r
1979     fprintf (fpOut, "\n%d %s\n{", HII_RESOURCE_SECTION_INDEX, HII_RESOURCE_SECTION_NAME);\r
1980 \r
1981     HiiPackageDataPointer = HiiPackageListBuffer;\r
1982     for (Index = 0; Index + 2 < HiiPackageListHeader.PackageLength; Index += 2) {\r
1983       if (Index % 16 == 0) {\r
1984         fprintf (fpOut, "\n ");\r
1985       }\r
1986       fprintf (fpOut, " 0x%04X,", *(UINT16 *) HiiPackageDataPointer);\r
1987       HiiPackageDataPointer += 2;\r
1988     }\r
1989     \r
1990     if (Index % 16 == 0) {\r
1991       fprintf (fpOut, "\n ");\r
1992     }\r
1993     if ((Index + 2) == HiiPackageListHeader.PackageLength) {\r
1994       fprintf (fpOut, " 0x%04X\n}\n", *(UINT16 *) HiiPackageDataPointer);\r
1995     }\r
1996     if ((Index + 1) == HiiPackageListHeader.PackageLength) {\r
1997       fprintf (fpOut, " 0x%04X\n}\n", *(UINT8 *) HiiPackageDataPointer);\r
1998     }\r
1999     free (HiiPackageListBuffer);\r
2000     //\r
2001     // Done successfully\r
2002     //\r
2003     goto Finish;\r
2004   }\r
2005 \r
2006   //\r
2007   // Combine MciBinary files to one file\r
2008   //\r
2009   if (OutImageType == FW_MERGE_IMAGE) {\r
2010     for (Index = 0; Index < InputFileNum; Index ++) {\r
2011       fpIn = fopen (InputFileName [Index], "rb");\r
2012       if (!fpIn) {\r
2013         Error (NULL, 0, 0001, "Error opening file", InputFileName [Index]);\r
2014         goto Finish;\r
2015       }\r
2016 \r
2017       FileLength = _filelength (fileno (fpIn));\r
2018       FileBuffer = malloc (FileLength);\r
2019       if (FileBuffer == NULL) {\r
2020         Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
2021         fclose (fpIn);\r
2022         goto Finish;\r
2023       }\r
2024 \r
2025       fread (FileBuffer, 1, FileLength, fpIn);\r
2026       fclose (fpIn);\r
2027       //\r
2028       // write input file to out file\r
2029       //\r
2030       fwrite (FileBuffer, 1, FileLength, fpOut);\r
2031       //\r
2032       // write pad value to out file.\r
2033       //\r
2034       while (FileLength ++ % MciAlignment != 0) {\r
2035         fwrite (&MciPadValue, 1, 1, fpOut);\r
2036       }\r
2037       //\r
2038       // free allocated memory space\r
2039       //\r
2040       free (FileBuffer);\r
2041       FileBuffer = NULL;\r
2042     }\r
2043     //\r
2044     // Done successfully\r
2045     //\r
2046     goto Finish;\r
2047   }\r
2048 \r
2049   //\r
2050   // Convert MicroCode.txt file to MicroCode.bin file\r
2051   //\r
2052   if (OutImageType == FW_MCI_IMAGE) {\r
2053     fpIn = fopen (mInImageName, "r");\r
2054     if (!fpIn) {\r
2055       Error (NULL, 0, 0001, "Error opening file", mInImageName);\r
2056       goto Finish;\r
2057     }\r
2058 \r
2059     //\r
2060     // The first pass is to determine\r
2061     // how much data is in the file so we can allocate a working buffer.\r
2062     //\r
2063     FileLength = 0;\r
2064     do {\r
2065       Status = MicrocodeReadData (fpIn, &Data);\r
2066       if (Status == STATUS_SUCCESS) {\r
2067         FileLength += sizeof (Data);\r
2068       }\r
2069       if (Status == STATUS_IGNORE) {\r
2070         Status = STATUS_SUCCESS;\r
2071       }\r
2072     } while (Status == STATUS_SUCCESS);\r
2073     //\r
2074     // Error if no data.\r
2075     //\r
2076     if (FileLength == 0) {\r
2077       Error (NULL, 0, 3000, "Invalid", "no parseable data found in file %s", mInImageName);\r
2078       goto Finish;\r
2079     }\r
2080     if (FileLength < sizeof (MICROCODE_IMAGE_HEADER)) {\r
2081       Error (NULL, 0, 3000, "Invalid", "amount of parseable data in %s is insufficient to contain a microcode header", mInImageName);\r
2082       goto Finish;\r
2083     }\r
2084 \r
2085     //\r
2086     // Allocate a buffer for the data\r
2087     //\r
2088     FileBuffer = malloc (FileLength);\r
2089     if (FileBuffer == NULL) {\r
2090       Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
2091       goto Finish;\r
2092     }\r
2093     //\r
2094     // Re-read the file, storing the data into our buffer\r
2095     //\r
2096     fseek (fpIn, 0, SEEK_SET);\r
2097     DataPointer = (UINT32 *) FileBuffer;\r
2098     OldDataPointer = DataPointer;\r
2099     do {\r
2100       OldDataPointer = DataPointer;\r
2101       Status = MicrocodeReadData (fpIn, DataPointer++);\r
2102       if (Status == STATUS_IGNORE) {\r
2103         DataPointer = OldDataPointer;\r
2104         Status = STATUS_SUCCESS;\r
2105       }\r
2106     } while (Status == STATUS_SUCCESS);\r
2107     //\r
2108     // close input file after read data\r
2109     //\r
2110     fclose (fpIn);\r
2111 \r
2112     //\r
2113     // Can't do much checking on the header because, per the spec, the\r
2114     // DataSize field may be 0, which means DataSize = 2000 and TotalSize = 2K,\r
2115     // and the TotalSize field is invalid (actually missing). Thus we can't\r
2116     // even verify the Reserved fields are 0.\r
2117     //\r
2118     MciHeader = (MICROCODE_IMAGE_HEADER *) FileBuffer;\r
2119     if (MciHeader->DataSize == 0) {\r
2120       Index = 2048;\r
2121     } else {\r
2122       Index = MciHeader->TotalSize;\r
2123     }\r
2124 \r
2125     if (Index != FileLength) {\r
2126       Error (NULL, 0, 3000, "Invalid", "file length of %s (0x%x) does not equal expected TotalSize: 0x%04X.", mInImageName, (unsigned) FileLength, (unsigned) Index);\r
2127       goto Finish;\r
2128     }\r
2129 \r
2130     //\r
2131     // Checksum the contents\r
2132     //\r
2133     DataPointer = (UINT32 *) FileBuffer;\r
2134     CheckSum  = 0;\r
2135     Index     = 0;\r
2136     while (Index < FileLength) {\r
2137       CheckSum    += *DataPointer;\r
2138       DataPointer ++;\r
2139       Index       += sizeof (*DataPointer);\r
2140     }\r
2141     if (CheckSum != 0) {\r
2142       Error (NULL, 0, 3000, "Invalid", "checksum (0x%x) failed on file %s.", (unsigned) CheckSum, mInImageName);\r
2143       goto Finish;\r
2144     }\r
2145     //\r
2146     // Open the output file and write the buffer contents\r
2147     //\r
2148     if (fpOut != NULL) {\r
2149       if (fwrite (FileBuffer, FileLength, 1, fpOut) != 1) {\r
2150         Error (NULL, 0, 0002, "Error writing file", OutImageName);\r
2151         goto Finish;\r
2152       }\r
2153     }\r
2154 \r
2155     if (ReplaceFlag) {\r
2156       fpInOut = fopen (mInImageName, "wb");\r
2157       if (fpInOut != NULL) {\r
2158         Error (NULL, 0, 0001, "Error opening file", mInImageName);\r
2159         goto Finish;\r
2160       }\r
2161       if (fwrite (FileBuffer, FileLength, 1, fpInOut) != 1) {\r
2162         Error (NULL, 0, 0002, "Error writing file", mInImageName);\r
2163         goto Finish;\r
2164       }\r
2165     }\r
2166     VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength);\r
2167     //\r
2168     //  Convert Mci.TXT to Mci.bin file successfully\r
2169     //\r
2170     goto Finish;\r
2171   }\r
2172 \r
2173   //\r
2174   // Open input file and read file data into file buffer.\r
2175   //\r
2176   fpIn = fopen (mInImageName, "rb");\r
2177   if (!fpIn) {\r
2178     Error (NULL, 0, 0001, "Error opening file", mInImageName);\r
2179     goto Finish;\r
2180   }\r
2181 \r
2182   FileLength = _filelength (fileno (fpIn));\r
2183   FileBuffer = malloc (FileLength);\r
2184   if (FileBuffer == NULL) {\r
2185     Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
2186     fclose (fpIn);\r
2187     goto Finish;\r
2188   }\r
2189 \r
2190   fread (FileBuffer, 1, FileLength, fpIn);\r
2191   fclose (fpIn);\r
2192 \r
2193   DebugMsg (NULL, 0, 9, "input file info", "the input file size is %u bytes", (unsigned) FileLength);\r
2194 \r
2195   //\r
2196   // Replace file\r
2197   //\r
2198   if (ReplaceFlag) {\r
2199     fpInOut = fopen (mInImageName, "wb");\r
2200     if (!fpInOut) {\r
2201       Error (NULL, 0, 0001, "Error opening file", mInImageName);\r
2202       goto Finish;\r
2203     }\r
2204   }\r
2205   //\r
2206   // Dump TeImage Header into output file.\r
2207   //\r
2208   if (OutImageType == DUMP_TE_HEADER) {\r
2209     memcpy (&TEImageHeader, FileBuffer, sizeof (TEImageHeader));\r
2210     if (TEImageHeader.Signature != EFI_TE_IMAGE_HEADER_SIGNATURE) {\r
2211       Error (NULL, 0, 3000, "Invalid", "TE header signature of file %s is not correct.", mInImageName);\r
2212       goto Finish;\r
2213     }\r
2214     if (fpInOut != NULL) {\r
2215       fprintf (fpInOut, "Dump of file %s\n\n", mInImageName);\r
2216       fprintf (fpInOut, "TE IMAGE HEADER VALUES\n");\r
2217       fprintf (fpInOut, "%17X machine\n", TEImageHeader.Machine);\r
2218       fprintf (fpInOut, "%17X number of sections\n", TEImageHeader.NumberOfSections);\r
2219       fprintf (fpInOut, "%17X subsystems\n", TEImageHeader.Subsystem);\r
2220       fprintf (fpInOut, "%17X stripped size\n", TEImageHeader.StrippedSize);\r
2221       fprintf (fpInOut, "%17X entry point\n", (unsigned) TEImageHeader.AddressOfEntryPoint);\r
2222       fprintf (fpInOut, "%17X base of code\n", (unsigned) TEImageHeader.BaseOfCode);\r
2223       fprintf (fpInOut, "%17llX image base\n", (unsigned long long)TEImageHeader.ImageBase);\r
2224       fprintf (fpInOut, "%17X [%8X] RVA [size] of Base Relocation Directory\n", (unsigned) TEImageHeader.DataDirectory[0].VirtualAddress, (unsigned) TEImageHeader.DataDirectory[0].Size);\r
2225       fprintf (fpInOut, "%17X [%8X] RVA [size] of Debug Directory\n", (unsigned) TEImageHeader.DataDirectory[1].VirtualAddress, (unsigned) TEImageHeader.DataDirectory[1].Size);\r
2226     }\r
2227 \r
2228     if (fpOut != NULL) {\r
2229       fprintf (fpOut, "Dump of file %s\n\n", mInImageName);\r
2230       fprintf (fpOut, "TE IMAGE HEADER VALUES\n");\r
2231       fprintf (fpOut, "%17X machine\n", TEImageHeader.Machine);\r
2232       fprintf (fpOut, "%17X number of sections\n", TEImageHeader.NumberOfSections);\r
2233       fprintf (fpOut, "%17X subsystems\n", TEImageHeader.Subsystem);\r
2234       fprintf (fpOut, "%17X stripped size\n", TEImageHeader.StrippedSize);\r
2235       fprintf (fpOut, "%17X entry point\n", (unsigned) TEImageHeader.AddressOfEntryPoint);\r
2236       fprintf (fpOut, "%17X base of code\n", (unsigned) TEImageHeader.BaseOfCode);\r
2237       fprintf (fpOut, "%17llX image base\n", (unsigned long long)TEImageHeader.ImageBase);\r
2238       fprintf (fpOut, "%17X [%8X] RVA [size] of Base Relocation Directory\n", (unsigned) TEImageHeader.DataDirectory[0].VirtualAddress, (unsigned) TEImageHeader.DataDirectory[0].Size);\r
2239       fprintf (fpOut, "%17X [%8X] RVA [size] of Debug Directory\n", (unsigned) TEImageHeader.DataDirectory[1].VirtualAddress, (unsigned) TEImageHeader.DataDirectory[1].Size);\r
2240     }\r
2241     goto Finish;\r
2242   }\r
2243 \r
2244   //\r
2245   // Following code to convert dll to efi image or te image.\r
2246   // Get new image type\r
2247   //\r
2248   if ((OutImageType == FW_EFI_IMAGE) || (OutImageType == FW_TE_IMAGE)) {\r
2249     if (ModuleType == NULL) {\r
2250       if (OutImageType == FW_EFI_IMAGE) {\r
2251         Error (NULL, 0, 1001, "Missing option", "EFI_FILETYPE");\r
2252         goto Finish;\r
2253       } else if (OutImageType == FW_TE_IMAGE) {\r
2254         //\r
2255         // Default TE Image Type is Boot service driver\r
2256         //\r
2257         Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER;\r
2258         VerboseMsg ("Efi Image subsystem type is efi boot service driver.");\r
2259       }\r
2260     } else {\r
2261       if (stricmp (ModuleType, "BASE") == 0 ||\r
2262           stricmp (ModuleType, "SEC") == 0 ||\r
2263           stricmp (ModuleType, "SECURITY_CORE") == 0 ||\r
2264           stricmp (ModuleType, "PEI_CORE") == 0 ||\r
2265           stricmp (ModuleType, "PEIM") == 0 ||\r
2266           stricmp (ModuleType, "COMBINED_PEIM_DRIVER") == 0 ||\r
2267           stricmp (ModuleType, "PIC_PEIM") == 0 ||\r
2268           stricmp (ModuleType, "RELOCATABLE_PEIM") == 0 ||\r
2269           stricmp (ModuleType, "DXE_CORE") == 0 ||\r
2270           stricmp (ModuleType, "BS_DRIVER") == 0  ||\r
2271           stricmp (ModuleType, "DXE_DRIVER") == 0 ||\r
2272           stricmp (ModuleType, "DXE_SMM_DRIVER") == 0  ||\r
2273           stricmp (ModuleType, "UEFI_DRIVER") == 0 ||\r
2274           stricmp (ModuleType, "SMM_DRIVER") == 0 ||\r
2275           stricmp (ModuleType, "SMM_CORE") == 0) {\r
2276         Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER;\r
2277         VerboseMsg ("Efi Image subsystem type is efi boot service driver.");\r
2278 \r
2279       } else if (stricmp (ModuleType, "UEFI_APPLICATION") == 0 ||\r
2280                  stricmp (ModuleType, "APPLICATION") == 0) {\r
2281         Type = EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION;\r
2282         VerboseMsg ("Efi Image subsystem type is efi application.");\r
2283 \r
2284       } else if (stricmp (ModuleType, "DXE_RUNTIME_DRIVER") == 0 ||\r
2285                  stricmp (ModuleType, "RT_DRIVER") == 0) {\r
2286         Type = EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER;\r
2287         VerboseMsg ("Efi Image subsystem type is efi runtime driver.");\r
2288 \r
2289       } else if (stricmp (ModuleType, "DXE_SAL_DRIVER") == 0 ||\r
2290                  stricmp (ModuleType, "SAL_RT_DRIVER") == 0) {\r
2291         Type = EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER;\r
2292         VerboseMsg ("Efi Image subsystem type is efi sal runtime driver.");\r
2293 \r
2294       } else {\r
2295         Error (NULL, 0, 1003, "Invalid option value", "EFI_FILETYPE = %s", ModuleType);\r
2296         goto Finish;\r
2297       }\r
2298     }\r
2299   }\r
2300 \r
2301   //\r
2302   // Convert EFL image to PeImage\r
2303   //\r
2304   if (IsElfHeader(FileBuffer)) {\r
2305     VerboseMsg ("Convert the input ELF Image to Pe Image");\r
2306     ConvertElf(&FileBuffer, &FileLength);\r
2307   }\r
2308 \r
2309   //\r
2310   // Remove reloc section from PE or TE image\r
2311   //\r
2312   if (OutImageType == FW_RELOC_STRIPEED_IMAGE) {\r
2313     //\r
2314     // Check TeImage\r
2315     //\r
2316     TeHdr = (EFI_TE_IMAGE_HEADER *) FileBuffer;\r
2317     if (TeHdr->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {\r
2318       SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (TeHdr + 1);\r
2319       for (Index = 0; Index < TeHdr->NumberOfSections; Index ++, SectionHeader ++) {\r
2320         if (strcmp ((char *)SectionHeader->Name, ".reloc") == 0) {\r
2321           //\r
2322           // Check the reloc section is in the end of image.\r
2323           //\r
2324           if ((SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData) ==\r
2325             (FileLength + TeHdr->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER))) {\r
2326             //\r
2327             // Remove .reloc section and update TeImage Header\r
2328             //\r
2329             FileLength = FileLength - SectionHeader->SizeOfRawData;\r
2330             SectionHeader->SizeOfRawData = 0;\r
2331             SectionHeader->Misc.VirtualSize = 0;\r
2332             TeHdr->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = 0;\r
2333             TeHdr->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size           = 0;\r
2334             break;\r
2335           }\r
2336         }\r
2337       }\r
2338     } else {\r
2339       //\r
2340       // Check PE Image\r
2341       //\r
2342       DosHdr = (EFI_IMAGE_DOS_HEADER *) FileBuffer;\r
2343       if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {\r
2344         PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer);\r
2345         if (PeHdr->Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) {\r
2346           Error (NULL, 0, 3000, "Invalid", "TE and DOS header signatures were not found in %s image.", mInImageName);\r
2347           goto Finish;\r
2348         }\r
2349         DosHdr = NULL;\r
2350       } else {\r
2351         PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer + DosHdr->e_lfanew);\r
2352         if (PeHdr->Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) {\r
2353           Error (NULL, 0, 3000, "Invalid", "PE header signature was not found in %s image.", mInImageName);\r
2354           goto Finish;\r
2355         }\r
2356       }\r
2357       SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);\r
2358       for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) {\r
2359         if (strcmp ((char *)SectionHeader->Name, ".reloc") == 0) {\r
2360           //\r
2361           // Check the reloc section is in the end of image.\r
2362           //\r
2363           if ((SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData) == FileLength) {\r
2364             //\r
2365             // Remove .reloc section and update PeImage Header\r
2366             //\r
2367             FileLength = FileLength - SectionHeader->SizeOfRawData;\r
2368 \r
2369             PeHdr->Pe32.FileHeader.Characteristics |= EFI_IMAGE_FILE_RELOCS_STRIPPED;\r
2370             if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
2371               Optional32 = (EFI_IMAGE_OPTIONAL_HEADER32 *)&PeHdr->Pe32.OptionalHeader;\r
2372               Optional32->SizeOfImage -= SectionHeader->SizeOfRawData;\r
2373               Optional32->SizeOfInitializedData -= SectionHeader->SizeOfRawData;\r
2374               if (Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {\r
2375                 Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = 0;\r
2376                 Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = 0;\r
2377               }\r
2378             }\r
2379             if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
2380               Optional64 = (EFI_IMAGE_OPTIONAL_HEADER64 *)&PeHdr->Pe32.OptionalHeader;\r
2381               Optional64->SizeOfImage -= SectionHeader->SizeOfRawData;\r
2382               Optional64->SizeOfInitializedData -= SectionHeader->SizeOfRawData;\r
2383               if (Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {\r
2384                 Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = 0;\r
2385                 Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = 0;\r
2386               }\r
2387             }\r
2388             SectionHeader->Misc.VirtualSize = 0;\r
2389             SectionHeader->SizeOfRawData = 0;\r
2390             break;\r
2391           }\r
2392         }\r
2393       }\r
2394     }\r
2395     //\r
2396     // Write file\r
2397     //\r
2398     goto WriteFile;\r
2399   }\r
2400   //\r
2401   // Read the dos & pe hdrs of the image\r
2402   //\r
2403   DosHdr = (EFI_IMAGE_DOS_HEADER *)FileBuffer;\r
2404   if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {\r
2405     // NO DOS header, check for PE/COFF header\r
2406     PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer);\r
2407     if (PeHdr->Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) {\r
2408       Error (NULL, 0, 3000, "Invalid", "DOS header signature was not found in %s image.", mInImageName);\r
2409       goto Finish;\r
2410     }\r
2411     DosHdr = NULL;\r
2412   } else {\r
2413 \r
2414     PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer + DosHdr->e_lfanew);\r
2415     if (PeHdr->Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) {\r
2416       Error (NULL, 0, 3000, "Invalid", "PE header signature was not found in %s image.", mInImageName);\r
2417       goto Finish;\r
2418     }\r
2419   }\r
2420   \r
2421   if (PeHdr->Pe32.FileHeader.Machine == IMAGE_FILE_MACHINE_ARM) {\r
2422     // Some tools kick out IMAGE_FILE_MACHINE_ARM (0x1c0) vs IMAGE_FILE_MACHINE_ARMT (0x1c2)\r
2423     // so patch back to the offical UEFI value.\r
2424     PeHdr->Pe32.FileHeader.Machine = IMAGE_FILE_MACHINE_ARMT;\r
2425   }\r
2426 \r
2427   //\r
2428   // Extract bin data from Pe image.\r
2429   //\r
2430   if (OutImageType == FW_BIN_IMAGE) {\r
2431     if (FileLength < PeHdr->Pe32.OptionalHeader.SizeOfHeaders) {\r
2432       Error (NULL, 0, 3000, "Invalid", "FileSize of %s is not a legal size.", mInImageName);\r
2433       goto Finish;\r
2434     }\r
2435     //\r
2436     // Output bin data from exe file\r
2437     //\r
2438     if (fpOut != NULL) {\r
2439       fwrite (FileBuffer + PeHdr->Pe32.OptionalHeader.SizeOfHeaders, 1, FileLength - PeHdr->Pe32.OptionalHeader.SizeOfHeaders, fpOut);\r
2440     }\r
2441     if (fpInOut != NULL) {\r
2442       fwrite (FileBuffer + PeHdr->Pe32.OptionalHeader.SizeOfHeaders, 1, FileLength - PeHdr->Pe32.OptionalHeader.SizeOfHeaders, fpInOut);\r
2443     }\r
2444     VerboseMsg ("the size of output file is %u bytes", (unsigned) (FileLength - PeHdr->Pe32.OptionalHeader.SizeOfHeaders));\r
2445     goto Finish;\r
2446   }\r
2447 \r
2448   //\r
2449   // Zero Debug Information of Pe Image\r
2450   //\r
2451   if (OutImageType == FW_ZERO_DEBUG_IMAGE) {\r
2452     Status = ZeroDebugData (FileBuffer, TRUE);\r
2453     if (EFI_ERROR (Status)) {\r
2454       Error (NULL, 0, 3000, "Invalid", "Zero DebugData Error status is 0x%x", (int) Status);\r
2455       goto Finish;\r
2456     }\r
2457 \r
2458     if (fpOut != NULL) {\r
2459       fwrite (FileBuffer, 1, FileLength, fpOut);\r
2460     }\r
2461     if (fpInOut != NULL) {\r
2462       fwrite (FileBuffer, 1, FileLength, fpInOut);\r
2463     }\r
2464     VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength);\r
2465     goto Finish;\r
2466   }\r
2467 \r
2468   //\r
2469   // Set Time Stamp of Pe Image\r
2470   //\r
2471   if (OutImageType == FW_SET_STAMP_IMAGE) {\r
2472     Status = SetStamp (FileBuffer, TimeStamp);\r
2473     if (EFI_ERROR (Status)) {\r
2474       goto Finish;\r
2475     }\r
2476 \r
2477     if (fpOut != NULL) {\r
2478       fwrite (FileBuffer, 1, FileLength, fpOut);\r
2479     }\r
2480     if (fpInOut != NULL) {\r
2481       fwrite (FileBuffer, 1, FileLength, fpInOut);\r
2482     }\r
2483     VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength);\r
2484     goto Finish;\r
2485   }\r
2486 \r
2487   //\r
2488   // Extract acpi data from pe image.\r
2489   //\r
2490   if (OutImageType == FW_ACPI_IMAGE) {\r
2491     SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);\r
2492     for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) {\r
2493       if (strcmp ((char *)SectionHeader->Name, ".data") == 0 || strcmp ((char *)SectionHeader->Name, ".sdata") == 0) {\r
2494         //\r
2495         // Check Acpi Table\r
2496         //\r
2497         if (SectionHeader->Misc.VirtualSize < SectionHeader->SizeOfRawData) {\r
2498           FileLength = SectionHeader->Misc.VirtualSize;\r
2499         } else {\r
2500           FileLength = SectionHeader->SizeOfRawData;\r
2501         }\r
2502 \r
2503         if (CheckAcpiTable (FileBuffer + SectionHeader->PointerToRawData, FileLength) != STATUS_SUCCESS) {\r
2504           Error (NULL, 0, 3000, "Invalid", "ACPI table check failed in %s.", mInImageName);\r
2505           goto Finish;\r
2506         }\r
2507 \r
2508         //\r
2509         // Output Apci data to file\r
2510         //\r
2511         if (fpOut != NULL) {\r
2512           fwrite (FileBuffer + SectionHeader->PointerToRawData, 1, FileLength, fpOut);\r
2513         }\r
2514         if (fpInOut != NULL) {\r
2515           fwrite (FileBuffer + SectionHeader->PointerToRawData, 1, FileLength, fpInOut);\r
2516         }\r
2517         VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength);\r
2518         goto Finish;\r
2519       }\r
2520     }\r
2521     Error (NULL, 0, 3000, "Invalid", "failed to get ACPI table from %s.", mInImageName);\r
2522     goto Finish;\r
2523   }\r
2524   //\r
2525   // Zero all unused fields of the DOS header\r
2526   //\r
2527   if (DosHdr != NULL) {\r
2528     memcpy (&BackupDosHdr, DosHdr, sizeof (EFI_IMAGE_DOS_HEADER));\r
2529     memset (DosHdr, 0, sizeof (EFI_IMAGE_DOS_HEADER));\r
2530     DosHdr->e_magic  = BackupDosHdr.e_magic;\r
2531     DosHdr->e_lfanew = BackupDosHdr.e_lfanew;\r
2532   \r
2533     for (Index = sizeof (EFI_IMAGE_DOS_HEADER); Index < (UINT32 ) DosHdr->e_lfanew; Index++) {\r
2534       FileBuffer[Index] = (UINT8) DosHdr->e_cp;\r
2535     }\r
2536   }\r
2537 \r
2538   //\r
2539   // Initialize TeImage Header\r
2540   //\r
2541   memset (&TEImageHeader, 0, sizeof (EFI_TE_IMAGE_HEADER));\r
2542   TEImageHeader.Signature        = EFI_TE_IMAGE_HEADER_SIGNATURE;\r
2543   TEImageHeader.Machine          = PeHdr->Pe32.FileHeader.Machine;\r
2544   TEImageHeader.NumberOfSections = (UINT8) PeHdr->Pe32.FileHeader.NumberOfSections;\r
2545   TEImageHeader.StrippedSize     = (UINT16) ((UINTN) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader) - (UINTN) FileBuffer);\r
2546   TEImageHeader.Subsystem        = (UINT8) Type;\r
2547   \r
2548   //\r
2549   // Patch the PE header\r
2550   //\r
2551   PeHdr->Pe32.OptionalHeader.Subsystem = (UINT16) Type;\r
2552 \r
2553   if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
2554     Optional32 = (EFI_IMAGE_OPTIONAL_HEADER32 *)&PeHdr->Pe32.OptionalHeader;\r
2555     Optional32->MajorLinkerVersion          = 0;\r
2556     Optional32->MinorLinkerVersion          = 0;\r
2557     Optional32->MajorOperatingSystemVersion = 0;\r
2558     Optional32->MinorOperatingSystemVersion = 0;\r
2559     Optional32->MajorImageVersion           = 0;\r
2560     Optional32->MinorImageVersion           = 0;\r
2561     Optional32->MajorSubsystemVersion       = 0;\r
2562     Optional32->MinorSubsystemVersion       = 0;\r
2563     Optional32->Win32VersionValue           = 0;\r
2564     Optional32->CheckSum                    = 0;\r
2565     Optional32->SizeOfStackReserve = 0;\r
2566     Optional32->SizeOfStackCommit  = 0;\r
2567     Optional32->SizeOfHeapReserve  = 0;\r
2568     Optional32->SizeOfHeapCommit   = 0;\r
2569 \r
2570     TEImageHeader.AddressOfEntryPoint = Optional32->AddressOfEntryPoint;\r
2571     TEImageHeader.BaseOfCode          = Optional32->BaseOfCode;\r
2572     TEImageHeader.ImageBase           = (UINT64) (Optional32->ImageBase);\r
2573 \r
2574     if (Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {\r
2575       TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;\r
2576       TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;\r
2577     }\r
2578 \r
2579     if (Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {\r
2580       TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;\r
2581       TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size;\r
2582     }\r
2583 \r
2584     //\r
2585     // Zero .pdata section data.\r
2586     //\r
2587     if (!KeepExceptionTableFlag && Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION &&\r
2588         Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress != 0 &&\r
2589         Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size != 0) {\r
2590       SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);\r
2591       for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++, SectionHeader++) {\r
2592         if (SectionHeader->VirtualAddress == Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress) {\r
2593           //\r
2594           // Zero .pdata Section data\r
2595           //\r
2596           memset (FileBuffer + SectionHeader->PointerToRawData, 0, SectionHeader->SizeOfRawData);\r
2597           //\r
2598           // Zero .pdata Section header name\r
2599           //\r
2600           memset (SectionHeader->Name, 0, sizeof (SectionHeader->Name));\r
2601           //\r
2602           // Zero Execption Table\r
2603           //\r
2604           Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress = 0;\r
2605           Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size           = 0;\r
2606           DebugMsg (NULL, 0, 9, "Zero the .pdata section for PE image", NULL);\r
2607           break;\r
2608         }\r
2609       }\r
2610     }\r
2611 \r
2612     //\r
2613     // Strip zero padding at the end of the .reloc section\r
2614     //\r
2615     if (!KeepZeroPendingFlag && Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {\r
2616       if (Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size != 0) {\r
2617         SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);\r
2618         for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++, SectionHeader++) {\r
2619           //\r
2620           // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory\r
2621           //\r
2622           if (SectionHeader->VirtualAddress == Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress) {\r
2623             SectionHeader->Misc.VirtualSize = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;\r
2624             AllignedRelocSize = (Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size + Optional32->FileAlignment - 1) & (~(Optional32->FileAlignment - 1));\r
2625             //\r
2626             // Check to see if there is zero padding at the end of the base relocations\r
2627             //\r
2628             if (AllignedRelocSize < SectionHeader->SizeOfRawData) {\r
2629               //\r
2630               // Check to see if the base relocations are at the end of the file\r
2631               //\r
2632               if (SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData == Optional32->SizeOfImage) {\r
2633                 //\r
2634                 // All the required conditions are met to strip the zero padding of the end of the base relocations section\r
2635                 //\r
2636                 Optional32->SizeOfImage -= (SectionHeader->SizeOfRawData - AllignedRelocSize);\r
2637                 Optional32->SizeOfInitializedData -= (SectionHeader->SizeOfRawData - AllignedRelocSize);\r
2638                 SectionHeader->SizeOfRawData = AllignedRelocSize;\r
2639                 FileLength = Optional32->SizeOfImage;\r
2640                 DebugMsg (NULL, 0, 9, "Remove the zero padding bytes at the end of the base relocations", "The size of padding bytes is %u", (unsigned) (SectionHeader->SizeOfRawData - AllignedRelocSize));\r
2641               }\r
2642             }\r
2643           }\r
2644         }\r
2645       }\r
2646     }\r
2647   } else if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
2648     Optional64 = (EFI_IMAGE_OPTIONAL_HEADER64 *)&PeHdr->Pe32.OptionalHeader;\r
2649     Optional64->MajorLinkerVersion          = 0;\r
2650     Optional64->MinorLinkerVersion          = 0;\r
2651     Optional64->MajorOperatingSystemVersion = 0;\r
2652     Optional64->MinorOperatingSystemVersion = 0;\r
2653     Optional64->MajorImageVersion           = 0;\r
2654     Optional64->MinorImageVersion           = 0;\r
2655     Optional64->MajorSubsystemVersion       = 0;\r
2656     Optional64->MinorSubsystemVersion       = 0;\r
2657     Optional64->Win32VersionValue           = 0;\r
2658     Optional64->CheckSum                    = 0;\r
2659     Optional64->SizeOfStackReserve = 0;\r
2660     Optional64->SizeOfStackCommit  = 0;\r
2661     Optional64->SizeOfHeapReserve  = 0;\r
2662     Optional64->SizeOfHeapCommit   = 0;\r
2663 \r
2664     TEImageHeader.AddressOfEntryPoint = Optional64->AddressOfEntryPoint;\r
2665     TEImageHeader.BaseOfCode          = Optional64->BaseOfCode;\r
2666     TEImageHeader.ImageBase           = (UINT64) (Optional64->ImageBase);\r
2667 \r
2668     if (Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {\r
2669       TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;\r
2670       TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;\r
2671     }\r
2672 \r
2673     if (Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {\r
2674       TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;\r
2675       TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size;\r
2676     }\r
2677 \r
2678     //\r
2679     // Zero the .pdata section for X64 machine and don't check the Debug Directory is empty\r
2680     // For Itaninum and X64 Image, remove .pdata section.\r
2681     //\r
2682     if ((!KeepExceptionTableFlag && PeHdr->Pe32.FileHeader.Machine == IMAGE_FILE_MACHINE_X64) || PeHdr->Pe32.FileHeader.Machine == IMAGE_FILE_MACHINE_IA64) {\r
2683       if (Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION &&\r
2684           Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress != 0 &&\r
2685           Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size != 0) {\r
2686         SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);\r
2687         for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++, SectionHeader++) {\r
2688           if (SectionHeader->VirtualAddress == Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress) {\r
2689             //\r
2690             // Zero .pdata Section header name\r
2691             //\r
2692             memset (SectionHeader->Name, 0, sizeof (SectionHeader->Name));\r
2693 \r
2694             RuntimeFunction = (RUNTIME_FUNCTION *)(FileBuffer + SectionHeader->PointerToRawData);\r
2695             for (Index1 = 0; Index1 < Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size / sizeof (RUNTIME_FUNCTION); Index1++, RuntimeFunction++) {\r
2696               SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);\r
2697               for (Index2 = 0; Index2 < PeHdr->Pe32.FileHeader.NumberOfSections; Index2++, SectionHeader++) {\r
2698                 if (RuntimeFunction->UnwindInfoAddress >= SectionHeader->VirtualAddress && RuntimeFunction->UnwindInfoAddress < (SectionHeader->VirtualAddress + SectionHeader->SizeOfRawData)) {\r
2699                   UnwindInfo = (UNWIND_INFO *)(FileBuffer + SectionHeader->PointerToRawData + (RuntimeFunction->UnwindInfoAddress - SectionHeader->VirtualAddress));\r
2700                   if (UnwindInfo->Version == 1) {\r
2701                     memset (UnwindInfo + 1, 0, UnwindInfo->CountOfUnwindCodes * sizeof (UINT16));\r
2702                     memset (UnwindInfo, 0, sizeof (UNWIND_INFO));\r
2703                   }\r
2704                   break;\r
2705                 }\r
2706               }\r
2707               memset (RuntimeFunction, 0, sizeof (RUNTIME_FUNCTION));\r
2708             }\r
2709             //\r
2710             // Zero Execption Table\r
2711             //\r
2712             Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size = 0;\r
2713             Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress = 0;\r
2714             DebugMsg (NULL, 0, 9, "Zero the .pdata section if the machine type is X64 for PE32+ image", NULL);\r
2715             break;\r
2716           }\r
2717         }\r
2718       }\r
2719     }\r
2720 \r
2721     //\r
2722     // Strip zero padding at the end of the .reloc section\r
2723     //\r
2724     if (!KeepZeroPendingFlag && Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {\r
2725       if (Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size != 0) {\r
2726         SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);\r
2727         for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++, SectionHeader++) {\r
2728           //\r
2729           // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory\r
2730           //\r
2731           if (SectionHeader->VirtualAddress == Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress) {\r
2732             SectionHeader->Misc.VirtualSize = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;\r
2733             AllignedRelocSize = (Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size + Optional64->FileAlignment - 1) & (~(Optional64->FileAlignment - 1));\r
2734             //\r
2735             // Check to see if there is zero padding at the end of the base relocations\r
2736             //\r
2737             if (AllignedRelocSize < SectionHeader->SizeOfRawData) {\r
2738               //\r
2739               // Check to see if the base relocations are at the end of the file\r
2740               //\r
2741               if (SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData == Optional64->SizeOfImage) {\r
2742                 //\r
2743                 // All the required conditions are met to strip the zero padding of the end of the base relocations section\r
2744                 //\r
2745                 Optional64->SizeOfImage -= (SectionHeader->SizeOfRawData - AllignedRelocSize);\r
2746                 Optional64->SizeOfInitializedData -= (SectionHeader->SizeOfRawData - AllignedRelocSize);\r
2747                 SectionHeader->SizeOfRawData = AllignedRelocSize;\r
2748                 FileLength = Optional64->SizeOfImage;\r
2749                 DebugMsg (NULL, 0, 9, "Remove the zero padding bytes at the end of the base relocations", "The size of padding bytes is %u", (unsigned) (SectionHeader->SizeOfRawData - AllignedRelocSize));\r
2750               }\r
2751             }\r
2752           }\r
2753         }\r
2754       }\r
2755     }\r
2756   } else {\r
2757     Error (NULL, 0, 3000, "Invalid", "Magic 0x%x of PeImage %s is unknown.", PeHdr->Pe32.OptionalHeader.Magic, mInImageName);\r
2758     goto Finish;\r
2759   }\r
2760   \r
2761   if (((PeHdr->Pe32.FileHeader.Characteristics & EFI_IMAGE_FILE_RELOCS_STRIPPED) == 0) && \\r
2762     (TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress == 0) && \\r
2763     (TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size == 0)) {\r
2764     //\r
2765     // PeImage can be loaded into memory, but it has no relocation section. \r
2766     // Fix TeImage Header to set VA of relocation data directory to not zero, the size is still zero.\r
2767     //\r
2768     if (Optional32 != NULL) {\r
2769       TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = Optional32->SizeOfImage - sizeof (EFI_IMAGE_BASE_RELOCATION);\r
2770     } else if (Optional64 != NULL) {\r
2771       TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = Optional64->SizeOfImage - sizeof (EFI_IMAGE_BASE_RELOCATION);\r
2772     }\r
2773   }\r
2774    \r
2775   //\r
2776   // Zero ExceptionTable Xdata\r
2777   //\r
2778   if (!KeepExceptionTableFlag) {\r
2779     SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);\r
2780     for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++) {\r
2781       if (stricmp ((char *)SectionHeader[Index].Name, ".xdata") == 0) {\r
2782         //\r
2783         // zero .xdata section\r
2784         //\r
2785         memset (FileBuffer + SectionHeader[Index].PointerToRawData, 0, SectionHeader[Index].SizeOfRawData);\r
2786         DebugMsg (NULL, 0, 9, NULL, "Zero the .xdata section for PE image at Offset 0x%x and Length 0x%x", (unsigned) SectionHeader[Index].PointerToRawData, (unsigned) SectionHeader[Index].SizeOfRawData);\r
2787         break;\r
2788       }\r
2789     }\r
2790   }\r
2791 \r
2792   //\r
2793   // Zero Time/Data field\r
2794   //\r
2795   ZeroDebugData (FileBuffer, FALSE);\r
2796 \r
2797   if (OutImageType == FW_TE_IMAGE) {\r
2798     if ((PeHdr->Pe32.FileHeader.NumberOfSections &~0xFF) || (Type &~0xFF)) {\r
2799       //\r
2800       // Pack the subsystem and NumberOfSections into 1 byte. Make sure they fit both.\r
2801       //\r
2802       Error (NULL, 0, 3000, "Invalid", "Image's subsystem or NumberOfSections of PeImage %s cannot be packed into 1 byte.", mInImageName);\r
2803       goto Finish;\r
2804     }\r
2805 \r
2806     if ((PeHdr->Pe32.OptionalHeader.SectionAlignment != PeHdr->Pe32.OptionalHeader.FileAlignment)) {\r
2807       //\r
2808       // TeImage has the same section alignment and file alignment.\r
2809       //\r
2810       Error (NULL, 0, 3000, "Invalid", "Section-Alignment and File-Alignment of PeImage %s do not match, they must be equal for a TeImage.", mInImageName);\r
2811       goto Finish;\r
2812     }\r
2813 \r
2814     DebugMsg (NULL, 0, 9, "TeImage Header Info", "Machine type is %X, Number of sections is %X, Stripped size is %X, EntryPoint is %X, BaseOfCode is %X, ImageBase is %llX",\r
2815               TEImageHeader.Machine, TEImageHeader.NumberOfSections, TEImageHeader.StrippedSize, (unsigned) TEImageHeader.AddressOfEntryPoint, (unsigned) TEImageHeader.BaseOfCode, (unsigned long long) TEImageHeader.ImageBase);\r
2816     //\r
2817     // Update Image to TeImage\r
2818     //\r
2819     if (fpOut != NULL) {\r
2820       fwrite (&TEImageHeader, 1, sizeof (EFI_TE_IMAGE_HEADER), fpOut);\r
2821       fwrite (FileBuffer + TEImageHeader.StrippedSize, 1, FileLength - TEImageHeader.StrippedSize, fpOut);\r
2822     }\r
2823     if (fpInOut != NULL) {\r
2824       fwrite (&TEImageHeader, 1, sizeof (EFI_TE_IMAGE_HEADER), fpInOut);\r
2825       fwrite (FileBuffer + TEImageHeader.StrippedSize, 1, FileLength - TEImageHeader.StrippedSize, fpInOut);\r
2826     }\r
2827     VerboseMsg ("the size of output file is %u bytes", (unsigned) (FileLength - TEImageHeader.StrippedSize));\r
2828     goto Finish;\r
2829   }\r
2830 WriteFile:\r
2831   //\r
2832   // Update Image to EfiImage\r
2833   //\r
2834   if (fpOut != NULL) {\r
2835     fwrite (FileBuffer, 1, FileLength, fpOut);\r
2836   }\r
2837   if (fpInOut != NULL) {\r
2838     fwrite (FileBuffer, 1, FileLength, fpInOut);\r
2839   }\r
2840   VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength);\r
2841 \r
2842 Finish:\r
2843   if (fpInOut != NULL) {\r
2844     if (GetUtilityStatus () != STATUS_SUCCESS) {\r
2845       //\r
2846       // when file updates failed, original file is still recoveried.\r
2847       //\r
2848       fwrite (FileBuffer, 1, FileLength, fpInOut);\r
2849     }\r
2850     //\r
2851     // Write converted data into fpInOut file and close input file.\r
2852     //\r
2853     fclose (fpInOut);\r
2854   }\r
2855 \r
2856   if (FileBuffer != NULL) {\r
2857     free (FileBuffer);\r
2858   }\r
2859 \r
2860   if (InputFileName != NULL) {\r
2861     free (InputFileName);\r
2862   }\r
2863 \r
2864   if (fpOut != NULL) {\r
2865     //\r
2866     // Write converted data into fpOut file and close output file.\r
2867     //\r
2868     fclose (fpOut);\r
2869     if (GetUtilityStatus () != STATUS_SUCCESS) {\r
2870       if (OutputFileBuffer == NULL) {\r
2871         remove (OutImageName);\r
2872       } else {\r
2873         fpOut = fopen (OutImageName, "wb");\r
2874         fwrite (OutputFileBuffer, 1, OutputFileLength, fpOut);\r
2875         fclose (fpOut);\r
2876         free (OutputFileBuffer);\r
2877       }\r
2878     }\r
2879   }\r
2880 \r
2881   VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME, GetUtilityStatus ());\r
2882 \r
2883   return GetUtilityStatus ();\r
2884 }\r
2885 \r
2886 STATIC\r
2887 EFI_STATUS\r
2888 ZeroDebugData (\r
2889   IN OUT UINT8   *FileBuffer,\r
2890   BOOLEAN        ZeroDebugFlag\r
2891   )\r
2892 /*++\r
2893 \r
2894 Routine Description:\r
2895 \r
2896   Zero debug information in PeImage.\r
2897 \r
2898 Arguments:\r
2899 \r
2900   FileBuffer    - Pointer to PeImage.\r
2901   ZeroDebugFlag - TRUE to zero Debug information, FALSE to only zero time/stamp\r
2902 \r
2903 Returns:\r
2904 \r
2905   EFI_ABORTED   - PeImage is invalid.\r
2906   EFI_SUCCESS   - Zero debug data successfully.\r
2907 \r
2908 --*/\r
2909 {\r
2910   UINT32                           Index;\r
2911   UINT32                           DebugDirectoryEntryRva;\r
2912   UINT32                           DebugDirectoryEntryFileOffset;\r
2913   UINT32                           ExportDirectoryEntryRva;\r
2914   UINT32                           ExportDirectoryEntryFileOffset;\r
2915   UINT32                           ResourceDirectoryEntryRva;\r
2916   UINT32                           ResourceDirectoryEntryFileOffset;\r
2917   EFI_IMAGE_DOS_HEADER            *DosHdr;\r
2918   EFI_IMAGE_FILE_HEADER           *FileHdr;\r
2919   EFI_IMAGE_OPTIONAL_HEADER32     *Optional32Hdr;\r
2920   EFI_IMAGE_OPTIONAL_HEADER64     *Optional64Hdr;\r
2921   EFI_IMAGE_SECTION_HEADER        *SectionHeader;\r
2922   EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *DebugEntry;\r
2923   UINT32                          *NewTimeStamp;  \r
2924 \r
2925   //\r
2926   // Init variable.\r
2927   //\r
2928   DebugDirectoryEntryRva           = 0;\r
2929   ExportDirectoryEntryRva          = 0;\r
2930   ResourceDirectoryEntryRva        = 0;\r
2931   DebugDirectoryEntryFileOffset    = 0;\r
2932   ExportDirectoryEntryFileOffset   = 0;\r
2933   ResourceDirectoryEntryFileOffset = 0;\r
2934   DosHdr   = (EFI_IMAGE_DOS_HEADER *)  FileBuffer;\r
2935   FileHdr  = (EFI_IMAGE_FILE_HEADER *) (FileBuffer + DosHdr->e_lfanew + sizeof (UINT32));\r
2936 \r
2937 \r
2938   DosHdr = (EFI_IMAGE_DOS_HEADER *)FileBuffer;\r
2939   if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {\r
2940     // NO DOS header, must start with PE/COFF header\r
2941     FileHdr  = (EFI_IMAGE_FILE_HEADER *)(FileBuffer + sizeof (UINT32));\r
2942   } else {\r
2943     FileHdr  = (EFI_IMAGE_FILE_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof (UINT32));\r
2944   }\r
2945 \r
2946   //\r
2947   // Get Debug, Export and Resource EntryTable RVA address.\r
2948   // Resource Directory entry need to review.\r
2949   //\r
2950   if (FileHdr->Machine == EFI_IMAGE_MACHINE_IA32) {\r
2951     Optional32Hdr = (EFI_IMAGE_OPTIONAL_HEADER32 *) ((UINT8*) FileHdr + sizeof (EFI_IMAGE_FILE_HEADER));\r
2952     SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) Optional32Hdr +  FileHdr->SizeOfOptionalHeader);\r
2953     if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXPORT && \\r
2954         Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].Size != 0) {\r
2955       ExportDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;\r
2956     }\r
2957     if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE && \\r
2958         Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size != 0) {\r
2959       ResourceDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;\r
2960     }\r
2961     if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG && \\r
2962         Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) {\r
2963       DebugDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;\r
2964       if (ZeroDebugFlag) {\r
2965         Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = 0;\r
2966         Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = 0;\r
2967       }\r
2968     }\r
2969   } else {\r
2970     Optional64Hdr = (EFI_IMAGE_OPTIONAL_HEADER64 *) ((UINT8*) FileHdr + sizeof (EFI_IMAGE_FILE_HEADER));\r
2971     SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) Optional64Hdr +  FileHdr->SizeOfOptionalHeader);\r
2972     if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXPORT && \\r
2973         Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].Size != 0) {\r
2974       ExportDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;\r
2975     }\r
2976     if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE && \\r
2977         Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size != 0) {\r
2978       ResourceDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;\r
2979     }\r
2980     if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG && \\r
2981         Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) {\r
2982       DebugDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;\r
2983       if (ZeroDebugFlag) {\r
2984         Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = 0;\r
2985         Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = 0;\r
2986       }\r
2987     }\r
2988   }\r
2989 \r
2990   //\r
2991   // Get DirectoryEntryTable file offset.\r
2992   //\r
2993   for (Index = 0; Index < FileHdr->NumberOfSections; Index ++, SectionHeader ++) {\r
2994     if (DebugDirectoryEntryRva >= SectionHeader->VirtualAddress &&\r
2995         DebugDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) {\r
2996         DebugDirectoryEntryFileOffset =\r
2997         DebugDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData;\r
2998     }\r
2999     if (ExportDirectoryEntryRva >= SectionHeader->VirtualAddress &&\r
3000         ExportDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) {\r
3001         ExportDirectoryEntryFileOffset =\r
3002         ExportDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData;\r
3003     }\r
3004     if (ResourceDirectoryEntryRva >= SectionHeader->VirtualAddress &&\r
3005         ResourceDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) {\r
3006         ResourceDirectoryEntryFileOffset =\r
3007         ResourceDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData;\r
3008     }\r
3009   }\r
3010 \r
3011   //\r
3012   //Zero Debug Data and TimeStamp\r
3013   //\r
3014   FileHdr->TimeDateStamp = 0;\r
3015 \r
3016   if (ExportDirectoryEntryFileOffset != 0) {\r
3017     NewTimeStamp  = (UINT32 *) (FileBuffer + ExportDirectoryEntryFileOffset + sizeof (UINT32));\r
3018     *NewTimeStamp = 0;\r
3019   }\r
3020 \r
3021   if (ResourceDirectoryEntryFileOffset != 0) {\r
3022     NewTimeStamp  = (UINT32 *) (FileBuffer + ResourceDirectoryEntryFileOffset + sizeof (UINT32));\r
3023     *NewTimeStamp = 0;\r
3024   }\r
3025 \r
3026   if (DebugDirectoryEntryFileOffset != 0) {\r
3027     DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) (FileBuffer + DebugDirectoryEntryFileOffset);\r
3028     DebugEntry->TimeDateStamp = 0;\r
3029     if (ZeroDebugFlag) {\r
3030       memset (FileBuffer + DebugEntry->FileOffset, 0, DebugEntry->SizeOfData);\r
3031       memset (DebugEntry, 0, sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY));\r
3032     }\r
3033   }\r
3034 \r
3035   return EFI_SUCCESS;\r
3036 }\r
3037 \r
3038 STATIC\r
3039 EFI_STATUS\r
3040 SetStamp (\r
3041   IN OUT UINT8  *FileBuffer,\r
3042   IN     CHAR8  *TimeStamp\r
3043   )\r
3044 /*++\r
3045 \r
3046 Routine Description:\r
3047 \r
3048   Set new time stamp into PeImage FileHdr and Directory table:\r
3049   Debug, Export and Resource.\r
3050 \r
3051 Arguments:\r
3052 \r
3053   FileBuffer    - Pointer to PeImage.\r
3054   TimeStamp     - Time stamp string.\r
3055 \r
3056 Returns:\r
3057 \r
3058   EFI_INVALID_PARAMETER   - TimeStamp format is not recognized.\r
3059   EFI_SUCCESS             - Set new time stamp in this image successfully.\r
3060 \r
3061 --*/\r
3062 {\r
3063   struct tm                       stime;\r
3064   struct tm                       *ptime;\r
3065   time_t                          newtime;\r
3066   UINT32                          Index;\r
3067   UINT32                          DebugDirectoryEntryRva;\r
3068   UINT32                          DebugDirectoryEntryFileOffset;\r
3069   UINT32                          ExportDirectoryEntryRva;\r
3070   UINT32                          ExportDirectoryEntryFileOffset;\r
3071   UINT32                          ResourceDirectoryEntryRva;\r
3072   UINT32                          ResourceDirectoryEntryFileOffset;\r
3073   EFI_IMAGE_DOS_HEADER            *DosHdr;\r
3074   EFI_IMAGE_FILE_HEADER           *FileHdr;\r
3075   EFI_IMAGE_OPTIONAL_HEADER32     *Optional32Hdr;\r
3076   EFI_IMAGE_OPTIONAL_HEADER64     *Optional64Hdr;\r
3077   EFI_IMAGE_SECTION_HEADER        *SectionHeader;\r
3078   UINT32                          *NewTimeStamp;\r
3079   \r
3080   //\r
3081   // Init variable.\r
3082   //\r
3083   DebugDirectoryEntryRva           = 0;\r
3084   DebugDirectoryEntryFileOffset    = 0;\r
3085   ExportDirectoryEntryRva          = 0;\r
3086   ExportDirectoryEntryFileOffset   = 0;\r
3087   ResourceDirectoryEntryRva        = 0;\r
3088   ResourceDirectoryEntryFileOffset = 0;\r
3089   //\r
3090   // Get time and date that will be set.\r
3091   //\r
3092   if (TimeStamp == NULL) {\r
3093     Error (NULL, 0, 3000, "Invalid", "TimeStamp cannot be NULL.");\r
3094     return EFI_INVALID_PARAMETER;\r
3095   }\r
3096   //\r
3097   // compare the value with "NOW", if yes, current system time is set.\r
3098   //\r
3099   if (stricmp (TimeStamp, "NOW") == 0) {\r
3100     //\r
3101     // get system current time and date\r
3102     //\r
3103     time (&newtime);\r
3104   } else {\r
3105     //\r
3106     // Check Time Format strictly yyyy-mm-dd 00:00:00\r
3107     //\r
3108     for (Index = 0; TimeStamp[Index] != '\0' && Index < 20; Index ++) {\r
3109       if (Index == 4 || Index == 7) {\r
3110         if (TimeStamp[Index] == '-') {\r
3111           continue;\r
3112         }\r
3113       } else if (Index == 13 || Index == 16) {\r
3114         if (TimeStamp[Index] == ':') {\r
3115           continue;\r
3116         }\r
3117       } else if (Index == 10 && TimeStamp[Index] == ' ') {\r
3118         continue;\r
3119       } else if ((TimeStamp[Index] < '0') || (TimeStamp[Index] > '9')) {\r
3120         break;\r
3121       }\r
3122     }\r
3123 \r
3124     if (Index < 19 || TimeStamp[19] != '\0') {\r
3125       Error (NULL, 0, 1003, "Invalid option value", "Incorrect Time \"%s\"\n  Correct Format \"yyyy-mm-dd 00:00:00\"", TimeStamp);\r
3126       return EFI_INVALID_PARAMETER;\r
3127     }\r
3128 \r
3129     //\r
3130     // get the date and time from TimeStamp\r
3131     //\r
3132     if (sscanf (TimeStamp, "%d-%d-%d %d:%d:%d",\r
3133             &stime.tm_year,\r
3134             &stime.tm_mon,\r
3135             &stime.tm_mday,\r
3136             &stime.tm_hour,\r
3137             &stime.tm_min,\r
3138             &stime.tm_sec\r
3139             ) != 6) {\r
3140       Error (NULL, 0, 1003, "Invalid option value", "Incorrect Tiem \"%s\"\n  Correct Format \"yyyy-mm-dd 00:00:00\"", TimeStamp);\r
3141       return EFI_INVALID_PARAMETER;\r
3142     }\r
3143 \r
3144     //\r
3145     // in struct, Month (0 - 11; Jan = 0). So decrease 1 from it\r
3146     //\r
3147     if (stime.tm_mon <= 0 || stime.tm_mday <=0) {\r
3148       Error (NULL, 0, 3000, "Invalid", "%s Invalid date!", TimeStamp);\r
3149       return EFI_INVALID_PARAMETER;\r
3150     }\r
3151     stime.tm_mon -= 1;\r
3152 \r
3153     //\r
3154     // in struct, Year (current year minus 1900)\r
3155     // and only the dates can be handled from Jan 1, 1970 to Jan 18, 2038\r
3156     //\r
3157     //\r
3158     // convert 0 -> 100 (2000), 1 -> 101 (2001), ..., 38 -> 138 (2038)\r
3159     //\r
3160     if (stime.tm_year >= 1970 && stime.tm_year <= 2038) {\r
3161       //\r
3162       // convert 1970 -> 70, 2000 -> 100, ...\r
3163       //\r
3164       stime.tm_year -= 1900;\r
3165     } else {\r
3166       Error (NULL, 0, 3000, "Invalid", "%s Invalid or unsupported datetime!", TimeStamp);\r
3167       return EFI_INVALID_PARAMETER;\r
3168     }\r
3169 \r
3170     //\r
3171     // convert the date and time to time_t format\r
3172     //\r
3173     newtime = mktime (&stime);\r
3174     if (newtime == (time_t) - 1) {\r
3175       Error (NULL, 0, 3000, "Invalid", "%s Invalid or unsupported datetime!", TimeStamp);\r
3176       return EFI_INVALID_PARAMETER;\r
3177     }\r
3178   }\r
3179 \r
3180   ptime = localtime (&newtime);\r
3181   DebugMsg (NULL, 0, 9, "New Image Time Stamp", "%04d-%02d-%02d %02d:%02d:%02d",\r
3182             ptime->tm_year + 1900, ptime->tm_mon + 1, ptime->tm_mday, ptime->tm_hour, ptime->tm_min, ptime->tm_sec);\r
3183   //\r
3184   // Set new time and data into PeImage.\r
3185   //\r
3186   DosHdr = (EFI_IMAGE_DOS_HEADER *)FileBuffer;\r
3187   if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {\r
3188     // NO DOS header, must start with PE/COFF header\r
3189     FileHdr  = (EFI_IMAGE_FILE_HEADER *)(FileBuffer + sizeof (UINT32));\r
3190   } else {\r
3191     FileHdr  = (EFI_IMAGE_FILE_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof (UINT32));\r
3192   }\r
3193 \r
3194   //\r
3195   // Get Debug, Export and Resource EntryTable RVA address.\r
3196   // Resource Directory entry need to review.\r
3197   //\r
3198   if (FileHdr->Machine == EFI_IMAGE_MACHINE_IA32) {\r
3199     Optional32Hdr = (EFI_IMAGE_OPTIONAL_HEADER32 *) ((UINT8*) FileHdr + sizeof (EFI_IMAGE_FILE_HEADER));\r
3200     SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) Optional32Hdr +  FileHdr->SizeOfOptionalHeader);\r
3201     if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXPORT && \\r
3202         Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].Size != 0) {\r
3203       ExportDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;\r
3204     }\r
3205     if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE && \\r
3206         Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size != 0) {\r
3207       ResourceDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;\r
3208     }\r
3209     if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG && \\r
3210         Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) {\r
3211       DebugDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;\r
3212     }\r
3213   } else {\r
3214     Optional64Hdr = (EFI_IMAGE_OPTIONAL_HEADER64 *) ((UINT8*) FileHdr + sizeof (EFI_IMAGE_FILE_HEADER));\r
3215     SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) Optional64Hdr +  FileHdr->SizeOfOptionalHeader);\r
3216     if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXPORT && \\r
3217         Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].Size != 0) {\r
3218       ExportDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;\r
3219     }\r
3220     if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE && \\r
3221         Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size != 0) {\r
3222       ResourceDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;\r
3223     }\r
3224     if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG && \\r
3225         Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) {\r
3226       DebugDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;\r
3227     }\r
3228   }\r
3229 \r
3230   //\r
3231   // Get DirectoryEntryTable file offset.\r
3232   //\r
3233   for (Index = 0; Index < FileHdr->NumberOfSections; Index ++, SectionHeader ++) {\r
3234     if (DebugDirectoryEntryRva >= SectionHeader->VirtualAddress &&\r
3235         DebugDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) {\r
3236         DebugDirectoryEntryFileOffset =\r
3237         DebugDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData;\r
3238     }\r
3239     if (ExportDirectoryEntryRva >= SectionHeader->VirtualAddress &&\r
3240         ExportDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) {\r
3241         ExportDirectoryEntryFileOffset =\r
3242         ExportDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData;\r
3243     }\r
3244     if (ResourceDirectoryEntryRva >= SectionHeader->VirtualAddress &&\r
3245         ResourceDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) {\r
3246         ResourceDirectoryEntryFileOffset =\r
3247         ResourceDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData;\r
3248     }\r
3249   }\r
3250 \r
3251   //\r
3252   // Set new stamp\r
3253   //\r
3254   FileHdr->TimeDateStamp = (UINT32) newtime;\r
3255 \r
3256   if (ExportDirectoryEntryRva != 0) {\r
3257     NewTimeStamp  = (UINT32 *) (FileBuffer + ExportDirectoryEntryFileOffset + sizeof (UINT32));\r
3258     *NewTimeStamp = (UINT32) newtime;\r
3259   }\r
3260 \r
3261   if (ResourceDirectoryEntryRva != 0) {\r
3262     NewTimeStamp  = (UINT32 *) (FileBuffer + ResourceDirectoryEntryFileOffset + sizeof (UINT32));\r
3263     *NewTimeStamp = (UINT32) newtime;\r
3264   }\r
3265 \r
3266   if (DebugDirectoryEntryRva != 0) {\r
3267     NewTimeStamp  = (UINT32 *) (FileBuffer + DebugDirectoryEntryFileOffset + sizeof (UINT32));\r
3268     *NewTimeStamp = (UINT32) newtime;\r
3269   }\r
3270 \r
3271   return EFI_SUCCESS;\r
3272 }\r
3273 \r
3274 STATIC\r
3275 STATUS\r
3276 MicrocodeReadData (\r
3277   FILE          *InFptr,\r
3278   UINT32        *Data\r
3279   )\r
3280 /*++\r
3281 \r
3282 Routine Description:\r
3283   Read a 32-bit microcode data value from a text file and convert to raw binary form.\r
3284 \r
3285 Arguments:\r
3286   InFptr    - file pointer to input text file\r
3287   Data      - pointer to where to return the data parsed\r
3288 \r
3289 Returns:\r
3290   STATUS_SUCCESS    - no errors or warnings, Data contains valid information\r
3291   STATUS_ERROR      - errors were encountered\r
3292 \r
3293 --*/\r
3294 {\r
3295   CHAR8  Line[MAX_LINE_LEN];\r
3296   CHAR8  *cptr;\r
3297   unsigned ScannedData = 0;\r
3298 \r
3299   Line[MAX_LINE_LEN - 1]  = 0;\r
3300   while (1) {\r
3301     if (fgets (Line, MAX_LINE_LEN, InFptr) == NULL) {\r
3302       return STATUS_ERROR;\r
3303     }\r
3304     //\r
3305     // If it was a binary file, then it may have overwritten our null terminator\r
3306     //\r
3307     if (Line[MAX_LINE_LEN - 1] != 0) {\r
3308       return STATUS_ERROR;\r
3309     }\r
3310 \r
3311     //\r
3312     // strip space\r
3313     //\r
3314     for (cptr = Line; *cptr && isspace(*cptr); cptr++) {\r
3315     }\r
3316 \r
3317     // Skip Blank Lines and Comment Lines\r
3318     if ((strlen(cptr) != 0) && (*cptr != ';')) {\r
3319       break;\r
3320     }\r
3321   }\r
3322 \r
3323   // Look for\r
3324   // dd 000000001h ; comment\r
3325   // dd XXXXXXXX\r
3326   // DD  XXXXXXXXX\r
3327   //  DD XXXXXXXXX\r
3328   //\r
3329   if ((tolower(cptr[0]) == 'd') && (tolower(cptr[1]) == 'd') && isspace (cptr[2])) {\r
3330     //\r
3331     // Skip blanks and look for a hex digit\r
3332     //\r
3333     cptr += 3;\r
3334     for (; *cptr && isspace(*cptr); cptr++) {\r
3335     }\r
3336     if (isxdigit (*cptr)) {\r
3337       if (sscanf (cptr, "%X", &ScannedData) != 1) {\r
3338         return STATUS_ERROR;\r
3339       }\r
3340     }\r
3341     *Data = (UINT32) ScannedData;\r
3342     return STATUS_SUCCESS;\r
3343   }\r
3344 \r
3345   return STATUS_ERROR;\r
3346 }\r