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