aabd143b6a1f6891866c18c1bdf264a6b5326435
[efi/edk2/.git] / edk2 / BaseTools / 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,SMM_CORE,\n\\r
203                         PEI_CORE, PEIM, DXE_CORE, DXE_DRIVER, UEFI_APPLICATION,\n\\r
204                         SEC, 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        Strip off the relocation info from 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                         Guid is used to specify hii package list 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 \r
1370 EFI_IMAGE_OPTIONAL_HEADER_UNION *\r
1371 GetPeCoffHeader (\r
1372   void *Data\r
1373   )\r
1374 {\r
1375   EFI_IMAGE_DOS_HEADER             *DosHdr;\r
1376   EFI_IMAGE_OPTIONAL_HEADER_UNION  *PeHdr;\r
1377 \r
1378   //\r
1379   // Read the dos & pe hdrs of the image\r
1380   //\r
1381   DosHdr = (EFI_IMAGE_DOS_HEADER *)Data;\r
1382   if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {\r
1383     // NO DOS header, check for PE/COFF header\r
1384     PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(Data);\r
1385     if (PeHdr->Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) {\r
1386       return NULL;\r
1387     }\r
1388   } else {\r
1389 \r
1390     PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(((UINT8 *)Data) + DosHdr->e_lfanew);\r
1391     if (PeHdr->Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) {\r
1392       return NULL;\r
1393     }\r
1394   }\r
1395   \r
1396   return PeHdr;\r
1397 }\r
1398 \r
1399 void\r
1400 PeCoffConvertImageToXip (\r
1401   UINT8  **FileBuffer,\r
1402   UINT32 *FileLength\r
1403   )\r
1404 {\r
1405   EFI_IMAGE_OPTIONAL_HEADER_UNION  *PeHdr;\r
1406   EFI_IMAGE_OPTIONAL_HEADER_UNION  *NewPeHdr;\r
1407   EFI_IMAGE_SECTION_HEADER         *SectionHeader;\r
1408   UINTN                            TotalNecessaryFileSize;\r
1409   UINTN                            SectionSize;\r
1410   UINT8                            *XipFile;\r
1411   UINT32                           XipLength;\r
1412   UINTN                            Index;\r
1413   UINTN                            FirstSectionOffset;\r
1414   BOOLEAN                          ConversionNeeded;\r
1415 \r
1416   PeHdr = GetPeCoffHeader ((void *) *FileBuffer);\r
1417   if (PeHdr == NULL) {\r
1418     return;\r
1419   }\r
1420   \r
1421   if (PeHdr->Pe32.OptionalHeader.SectionAlignment != PeHdr->Pe32.OptionalHeader.FileAlignment) {\r
1422     //\r
1423     // The only reason to expand zero fill sections is to make them compatible with XIP images.\r
1424     // If SectionAlignment is not equal to FileAlginment then it is not an XIP type image.\r
1425     //\r
1426     return;\r
1427   }\r
1428 \r
1429   //\r
1430   // Calculate size of XIP file, and determine if the conversion is needed.\r
1431   //\r
1432   ConversionNeeded = FALSE;\r
1433   XipLength = 0;\r
1434   FirstSectionOffset = *FileLength;\r
1435   TotalNecessaryFileSize = 0;\r
1436   SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);\r
1437   for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) {\r
1438     SectionSize = MAX (SectionHeader->Misc.VirtualSize, SectionHeader->SizeOfRawData);\r
1439     TotalNecessaryFileSize += SectionSize;\r
1440     if (SectionSize > 0) {\r
1441       FirstSectionOffset = MIN (FirstSectionOffset, SectionHeader->VirtualAddress);\r
1442       XipLength = MAX (XipLength, SectionHeader->VirtualAddress + SectionSize);\r
1443       if (SectionHeader->VirtualAddress != SectionHeader->PointerToRawData) {\r
1444         ConversionNeeded = TRUE;\r
1445       }\r
1446     }\r
1447     if (SectionHeader->Misc.VirtualSize > SectionHeader->SizeOfRawData) {\r
1448       ConversionNeeded = TRUE;\r
1449     }\r
1450   }\r
1451 \r
1452   if (FirstSectionOffset < PeHdr->Pe32.OptionalHeader.SizeOfHeaders) {\r
1453     //\r
1454     // If one of the sections should be loaded to an offset overlapping with\r
1455     // the executable header, then it cannot be made into an XIP image.\r
1456     //\r
1457     VerboseMsg ("PE/COFF conversion to XIP is impossible due to overlap");\r
1458     VerboseMsg ("of section data with the executable header.");\r
1459     return;\r
1460   }\r
1461 \r
1462   if (FirstSectionOffset == *FileLength) {\r
1463     //\r
1464     // If we never found a section with a non-zero size, then we\r
1465     // skip the conversion.\r
1466     //\r
1467     return;\r
1468   }\r
1469 \r
1470   TotalNecessaryFileSize += FirstSectionOffset;\r
1471 \r
1472   if (!ConversionNeeded) {\r
1473     return;\r
1474   }\r
1475 \r
1476   if (XipLength > (2 * TotalNecessaryFileSize)) {\r
1477     VerboseMsg ("PE/COFF conversion to XIP appears to be larger than necessary.");\r
1478     VerboseMsg ("The image linking process may have left unused memory ranges.");\r
1479   }\r
1480 \r
1481   if (PeHdr->Pe32.FileHeader.PointerToSymbolTable != 0) {\r
1482     //\r
1483     // This field is obsolete and should be zero\r
1484     //\r
1485     PeHdr->Pe32.FileHeader.PointerToSymbolTable = 0;\r
1486   }\r
1487 \r
1488   //\r
1489   // Allocate the extra space that we need to grow the image\r
1490   //\r
1491   XipFile = malloc (XipLength);\r
1492   memset (XipFile, 0, XipLength);\r
1493 \r
1494   //\r
1495   // Copy the file headers\r
1496   //\r
1497   memcpy (XipFile, *FileBuffer, PeHdr->Pe32.OptionalHeader.SizeOfHeaders);\r
1498 \r
1499   NewPeHdr = GetPeCoffHeader ((void *)XipFile);\r
1500   if (NewPeHdr == NULL) {\r
1501     free (XipFile);\r
1502     return;\r
1503   }\r
1504 \r
1505   //\r
1506   // Copy the section data over to the appropriate XIP offsets\r
1507   //\r
1508   SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(NewPeHdr->Pe32.OptionalHeader) + NewPeHdr->Pe32.FileHeader.SizeOfOptionalHeader);\r
1509   for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) {\r
1510     if (SectionHeader->SizeOfRawData > 0) {\r
1511       memcpy (\r
1512         XipFile + SectionHeader->VirtualAddress,\r
1513         *FileBuffer + SectionHeader->PointerToRawData,\r
1514         SectionHeader->SizeOfRawData\r
1515         );\r
1516     }\r
1517     SectionHeader->SizeOfRawData = SectionHeader->Misc.VirtualSize;\r
1518     SectionHeader->PointerToRawData = SectionHeader->VirtualAddress;\r
1519   }\r
1520 \r
1521   free (*FileBuffer);\r
1522   *FileLength = XipLength;\r
1523   *FileBuffer = XipFile;\r
1524 }\r
1525 \r
1526 UINT8 *\r
1527 CreateHiiResouceSectionHeader (\r
1528   UINT32 *pSectionHeaderSize, \r
1529   UINT32 HiiDataSize\r
1530   )\r
1531 /*++\r
1532 \r
1533 Routine Description:\r
1534 \r
1535   Create COFF resource section header\r
1536 \r
1537 Arguments:\r
1538 \r
1539   pSectionHeaderSize - Pointer to section header size.\r
1540   HiiDataSize        - Size of the total HII data in section.\r
1541 \r
1542 Returns:\r
1543   The created section header buffer.\r
1544 \r
1545 --*/\r
1546 {\r
1547   UINT32  HiiSectionHeaderSize;\r
1548   UINT32  HiiSectionOffset;\r
1549   UINT8   *HiiSectionHeader;\r
1550   EFI_IMAGE_RESOURCE_DIRECTORY        *ResourceDirectory;\r
1551   EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY  *TypeResourceDirectoryEntry;\r
1552   EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY  *NameResourceDirectoryEntry;\r
1553   EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY  *LanguageResourceDirectoryEntry;\r
1554   EFI_IMAGE_RESOURCE_DIRECTORY_STRING *ResourceDirectoryString;\r
1555   EFI_IMAGE_RESOURCE_DATA_ENTRY       *ResourceDataEntry;\r
1556 \r
1557   //\r
1558   // Calculate the total size for the resource header (include Type, Name and Language)\r
1559   // then allocate memory for the resource header.\r
1560   //\r
1561   HiiSectionHeaderSize = 3 * (sizeof (EFI_IMAGE_RESOURCE_DIRECTORY) + sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY)) \r
1562                           + 3 * (sizeof (UINT16) + 3 * sizeof (CHAR16)) \r
1563                           + sizeof (EFI_IMAGE_RESOURCE_DATA_ENTRY);\r
1564   HiiSectionHeader = malloc (HiiSectionHeaderSize);\r
1565   memset (HiiSectionHeader, 0, HiiSectionHeaderSize);\r
1566 \r
1567   HiiSectionOffset = 0;\r
1568   //\r
1569   // Create Type entry \r
1570   //\r
1571   ResourceDirectory = (EFI_IMAGE_RESOURCE_DIRECTORY *) (HiiSectionHeader + HiiSectionOffset);\r
1572   HiiSectionOffset += sizeof (EFI_IMAGE_RESOURCE_DIRECTORY);\r
1573   ResourceDirectory->NumberOfNamedEntries = 1;\r
1574   TypeResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *) (HiiSectionHeader + HiiSectionOffset);\r
1575   HiiSectionOffset += sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY);\r
1576   TypeResourceDirectoryEntry->u1.s.NameIsString      = 1;\r
1577   TypeResourceDirectoryEntry->u2.s.DataIsDirectory   = 1;\r
1578   TypeResourceDirectoryEntry->u2.s.OffsetToDirectory = HiiSectionOffset;\r
1579   //\r
1580   // Create Name entry\r
1581   //\r
1582   ResourceDirectory = (EFI_IMAGE_RESOURCE_DIRECTORY *) (HiiSectionHeader + HiiSectionOffset);\r
1583   HiiSectionOffset += sizeof (EFI_IMAGE_RESOURCE_DIRECTORY);\r
1584   ResourceDirectory->NumberOfNamedEntries = 1;\r
1585   NameResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *) (HiiSectionHeader + HiiSectionOffset);\r
1586   HiiSectionOffset += sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY);\r
1587   NameResourceDirectoryEntry->u1.s.NameIsString      = 1;\r
1588   NameResourceDirectoryEntry->u2.s.DataIsDirectory   = 1;\r
1589   NameResourceDirectoryEntry->u2.s.OffsetToDirectory = HiiSectionOffset;\r
1590   //\r
1591   // Create Language entry\r
1592   //\r
1593   ResourceDirectory = (EFI_IMAGE_RESOURCE_DIRECTORY *) (HiiSectionHeader + HiiSectionOffset);\r
1594   HiiSectionOffset += sizeof (EFI_IMAGE_RESOURCE_DIRECTORY);\r
1595   ResourceDirectory->NumberOfNamedEntries = 1;\r
1596   LanguageResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *) (HiiSectionHeader + HiiSectionOffset);\r
1597   HiiSectionOffset += sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY);\r
1598   LanguageResourceDirectoryEntry->u1.s.NameIsString = 1;\r
1599   //\r
1600   // Create string entry for Type\r
1601   //\r
1602   TypeResourceDirectoryEntry->u1.s.NameOffset = HiiSectionOffset;\r
1603   ResourceDirectoryString = (EFI_IMAGE_RESOURCE_DIRECTORY_STRING *) (HiiSectionHeader + HiiSectionOffset);\r
1604   ResourceDirectoryString->Length = 3;\r
1605   ResourceDirectoryString->String[0] = L'H';\r
1606   ResourceDirectoryString->String[1] = L'I';\r
1607   ResourceDirectoryString->String[2] = L'I';\r
1608   HiiSectionOffset = HiiSectionOffset + sizeof (ResourceDirectoryString->Length) + ResourceDirectoryString->Length * sizeof (ResourceDirectoryString->String[0]);\r
1609   //\r
1610   // Create string entry for Name\r
1611   //\r
1612   NameResourceDirectoryEntry->u1.s.NameOffset = HiiSectionOffset;\r
1613   ResourceDirectoryString = (EFI_IMAGE_RESOURCE_DIRECTORY_STRING *) (HiiSectionHeader + HiiSectionOffset);\r
1614   ResourceDirectoryString->Length = 3;\r
1615   ResourceDirectoryString->String[0] = L'E';\r
1616   ResourceDirectoryString->String[1] = L'F';\r
1617   ResourceDirectoryString->String[2] = L'I';\r
1618   HiiSectionOffset = HiiSectionOffset + sizeof (ResourceDirectoryString->Length) + ResourceDirectoryString->Length * sizeof (ResourceDirectoryString->String[0]);\r
1619   //\r
1620   // Create string entry for Language\r
1621   //\r
1622   LanguageResourceDirectoryEntry->u1.s.NameOffset = HiiSectionOffset;\r
1623   ResourceDirectoryString = (EFI_IMAGE_RESOURCE_DIRECTORY_STRING *) (HiiSectionHeader + HiiSectionOffset);\r
1624   ResourceDirectoryString->Length = 3;\r
1625   ResourceDirectoryString->String[0] = L'B';\r
1626   ResourceDirectoryString->String[1] = L'I';\r
1627   ResourceDirectoryString->String[2] = L'N';\r
1628   HiiSectionOffset = HiiSectionOffset + sizeof (ResourceDirectoryString->Length) + ResourceDirectoryString->Length * sizeof (ResourceDirectoryString->String[0]);\r
1629   //\r
1630   // Create Leaf data\r
1631   //\r
1632   LanguageResourceDirectoryEntry->u2.OffsetToData = HiiSectionOffset;\r
1633   ResourceDataEntry = (EFI_IMAGE_RESOURCE_DATA_ENTRY *) (HiiSectionHeader + HiiSectionOffset);\r
1634   HiiSectionOffset += sizeof (EFI_IMAGE_RESOURCE_DATA_ENTRY);\r
1635   ResourceDataEntry->OffsetToData = HiiSectionOffset;\r
1636   ResourceDataEntry->Size = HiiDataSize;\r
1637 \r
1638   *pSectionHeaderSize = HiiSectionHeaderSize;\r
1639   return HiiSectionHeader;\r
1640 }\r
1641 \r
1642 int\r
1643 main (\r
1644   int  argc,\r
1645   char *argv[]\r
1646   )\r
1647 /*++\r
1648 \r
1649 Routine Description:\r
1650 \r
1651   Main function.\r
1652 \r
1653 Arguments:\r
1654 \r
1655   argc - Number of command line parameters.\r
1656   argv - Array of pointers to command line parameter strings.\r
1657 \r
1658 Returns:\r
1659   STATUS_SUCCESS - Utility exits successfully.\r
1660   STATUS_ERROR   - Some error occurred during execution.\r
1661 \r
1662 --*/\r
1663 {\r
1664   UINT32                           Type;\r
1665   UINT32                           InputFileNum;\r
1666   CHAR8                            **InputFileName;\r
1667   char                             *OutImageName;\r
1668   char                             *ModuleType;\r
1669   CHAR8                            *TimeStamp;\r
1670   UINT32                           OutImageType;\r
1671   FILE                             *fpIn;\r
1672   FILE                             *fpOut;\r
1673   FILE                             *fpInOut;\r
1674   UINT32                           Data;\r
1675   UINT32                           *DataPointer;\r
1676   UINT32                           *OldDataPointer;\r
1677   UINT32                           CheckSum;\r
1678   UINT32                           Index;\r
1679   UINT32                           Index1;\r
1680   UINT32                           Index2;\r
1681   UINT64                           Temp64;\r
1682   UINT32                           MciAlignment;\r
1683   UINT8                            MciPadValue;\r
1684   UINT32                           AllignedRelocSize;\r
1685   UINT8                            *FileBuffer;\r
1686   UINT32                           FileLength;\r
1687   UINT8                            *OutputFileBuffer;\r
1688   UINT32                           OutputFileLength;\r
1689   RUNTIME_FUNCTION                 *RuntimeFunction;\r
1690   UNWIND_INFO                      *UnwindInfo;\r
1691   STATUS                           Status;\r
1692   BOOLEAN                          ReplaceFlag;\r
1693   BOOLEAN                          KeepExceptionTableFlag;\r
1694   BOOLEAN                          KeepZeroPendingFlag;\r
1695   UINT64                           LogLevel;\r
1696   EFI_TE_IMAGE_HEADER              TEImageHeader;\r
1697   EFI_TE_IMAGE_HEADER              *TeHdr;\r
1698   EFI_IMAGE_SECTION_HEADER         *SectionHeader;\r
1699   EFI_IMAGE_DOS_HEADER             *DosHdr;\r
1700   EFI_IMAGE_OPTIONAL_HEADER_UNION  *PeHdr;\r
1701   EFI_IMAGE_OPTIONAL_HEADER32      *Optional32;\r
1702   EFI_IMAGE_OPTIONAL_HEADER64      *Optional64;\r
1703   EFI_IMAGE_DOS_HEADER             BackupDosHdr;\r
1704   MICROCODE_IMAGE_HEADER           *MciHeader;\r
1705   UINT8                            *HiiPackageListBuffer;\r
1706   UINT8                            *HiiPackageDataPointer;\r
1707   EFI_GUID                         HiiPackageListGuid;\r
1708   EFI_HII_PACKAGE_LIST_HEADER      HiiPackageListHeader;\r
1709   EFI_HII_PACKAGE_HEADER           HiiPackageHeader;\r
1710   EFI_IFR_FORM_SET                 IfrFormSet;\r
1711   UINT8                            NumberOfFormPacakge;\r
1712   EFI_HII_PACKAGE_HEADER           EndPackage;\r
1713   UINT32                           HiiSectionHeaderSize;\r
1714   UINT8                            *HiiSectionHeader;\r
1715 \r
1716   SetUtilityName (UTILITY_NAME);\r
1717 \r
1718   //\r
1719   // Assign to fix compile warning\r
1720   //\r
1721   InputFileNum      = 0;\r
1722   InputFileName     = NULL;\r
1723   mInImageName      = NULL;\r
1724   OutImageName      = NULL;\r
1725   ModuleType        = NULL;\r
1726   OutImageType      = FW_DUMMY_IMAGE;\r
1727   Type              = 0;\r
1728   Status            = STATUS_SUCCESS;\r
1729   FileBuffer        = NULL;\r
1730   fpIn              = NULL;\r
1731   fpOut             = NULL;\r
1732   fpInOut           = NULL;\r
1733   TimeStamp         = NULL;\r
1734   MciAlignment      = DEFAULT_MC_ALIGNMENT;\r
1735   MciPadValue       = DEFAULT_MC_PAD_BYTE_VALUE;\r
1736   FileLength        = 0;\r
1737   MciHeader         = NULL;\r
1738   CheckSum          = 0;\r
1739   ReplaceFlag       = FALSE;\r
1740   LogLevel          = 0;\r
1741   OutputFileBuffer  = NULL;\r
1742   OutputFileLength  = 0;\r
1743   Optional32        = NULL;\r
1744   Optional64        = NULL;\r
1745   KeepExceptionTableFlag = FALSE;\r
1746   KeepZeroPendingFlag    = FALSE;\r
1747   NumberOfFormPacakge    = 0;\r
1748   HiiPackageListBuffer   = NULL;\r
1749   HiiPackageDataPointer  = NULL;\r
1750   EndPackage.Length      = sizeof (EFI_HII_PACKAGE_HEADER);\r
1751   EndPackage.Type        = EFI_HII_PACKAGE_END;\r
1752   memset (&HiiPackageListGuid, 0, sizeof (HiiPackageListGuid));\r
1753   HiiSectionHeaderSize   = 0;\r
1754   HiiSectionHeader       = NULL;\r
1755 \r
1756   if (argc == 1) {\r
1757     Error (NULL, 0, 1001, "Missing options", "No input options.");\r
1758     Usage ();\r
1759     return STATUS_ERROR;\r
1760   }\r
1761 \r
1762   argc --;\r
1763   argv ++;\r
1764 \r
1765   if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) {\r
1766     Version ();\r
1767     Usage ();\r
1768     return STATUS_SUCCESS;\r
1769   }\r
1770 \r
1771   if (stricmp (argv[0], "--version") == 0) {\r
1772     Version ();\r
1773     return STATUS_SUCCESS;\r
1774   }\r
1775 \r
1776   while (argc > 0) {\r
1777     if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--outputfile") == 0)) {\r
1778       if (argv[1] == NULL || argv[1][0] == '-') {\r
1779         Error (NULL, 0, 1003, "Invalid option value", "Output file name is missing for -o option");\r
1780         goto Finish;\r
1781       }\r
1782       OutImageName = argv[1];\r
1783       argc -= 2;\r
1784       argv += 2;\r
1785       continue;\r
1786     }\r
1787 \r
1788     if ((stricmp (argv[0], "-e") == 0) || (stricmp (argv[0], "--efiImage") == 0)) {\r
1789       if (argv[1] == NULL || argv[1][0] == '-') {\r
1790         Error (NULL, 0, 1003, "Invalid option value", "Module Type is missing for -o option");\r
1791         goto Finish;\r
1792       }\r
1793       ModuleType = argv[1];\r
1794       if (OutImageType != FW_TE_IMAGE) {\r
1795         OutImageType = FW_EFI_IMAGE;\r
1796       }\r
1797       argc -= 2;\r
1798       argv += 2;\r
1799       continue;\r
1800     }\r
1801 \r
1802     if ((stricmp (argv[0], "-l") == 0) || (stricmp (argv[0], "--stripped") == 0)) {\r
1803       OutImageType = FW_RELOC_STRIPEED_IMAGE;\r
1804       argc --;\r
1805       argv ++;\r
1806       continue;\r
1807     }\r
1808 \r
1809     if ((stricmp (argv[0], "-c") == 0) || (stricmp (argv[0], "--acpi") == 0)) {\r
1810       OutImageType = FW_ACPI_IMAGE;\r
1811       argc --;\r
1812       argv ++;\r
1813       continue;\r
1814     }\r
1815 \r
1816     if ((stricmp (argv[0], "-t") == 0) || (stricmp (argv[0], "--terse") == 0)) {\r
1817       OutImageType = FW_TE_IMAGE;\r
1818       argc --;\r
1819       argv ++;\r
1820       continue;\r
1821     }\r
1822 \r
1823     if ((stricmp (argv[0], "-u") == 0) || (stricmp (argv[0], "--dump") == 0)) {\r
1824       OutImageType = DUMP_TE_HEADER;\r
1825       argc --;\r
1826       argv ++;\r
1827       continue;\r
1828     }\r
1829 \r
1830     if ((stricmp (argv[0], "-b") == 0) || (stricmp (argv[0], "--exe2bin") == 0)) {\r
1831       OutImageType = FW_BIN_IMAGE;\r
1832       argc --;\r
1833       argv ++;\r
1834       continue;\r
1835     }\r
1836 \r
1837     if ((stricmp (argv[0], "-z") == 0) || (stricmp (argv[0], "--zero") == 0)) {\r
1838       OutImageType = FW_ZERO_DEBUG_IMAGE;\r
1839       argc --;\r
1840       argv ++;\r
1841       continue;\r
1842     }\r
1843 \r
1844     if ((stricmp (argv[0], "-s") == 0) || (stricmp (argv[0], "--stamp") == 0)) {\r
1845       OutImageType = FW_SET_STAMP_IMAGE;\r
1846       if (argv[1] == NULL || argv[1][0] == '-') {\r
1847         Error (NULL, 0, 1003, "Invalid option value", "time stamp is missing for -s option");\r
1848         goto Finish;\r
1849       }\r
1850       TimeStamp = argv[1];\r
1851       argc -= 2;\r
1852       argv += 2;\r
1853       continue;\r
1854     }\r
1855 \r
1856     if ((stricmp (argv[0], "-r") == 0) || (stricmp (argv[0], "--replace") == 0)) {\r
1857       ReplaceFlag = TRUE;\r
1858       argc --;\r
1859       argv ++;\r
1860       continue;\r
1861     }\r
1862 \r
1863     if (stricmp (argv[0], "--keepexceptiontable") == 0) {\r
1864       KeepExceptionTableFlag = TRUE;\r
1865       argc --;\r
1866       argv ++;\r
1867       continue;\r
1868     }\r
1869 \r
1870     if (stricmp (argv[0], "--keepzeropending") == 0) {\r
1871       KeepZeroPendingFlag = TRUE;\r
1872       argc --;\r
1873       argv ++;\r
1874       continue;\r
1875     }\r
1876 \r
1877     if ((stricmp (argv[0], "-m") == 0) || (stricmp (argv[0], "--mcifile") == 0)) {\r
1878       OutImageType = FW_MCI_IMAGE;\r
1879       argc --;\r
1880       argv ++;\r
1881       continue;\r
1882     }\r
1883 \r
1884     if ((stricmp (argv[0], "-j") == 0) || (stricmp (argv[0], "--join") == 0)) {\r
1885       OutImageType = FW_MERGE_IMAGE;\r
1886       argc --;\r
1887       argv ++;\r
1888       continue;\r
1889     }\r
1890 \r
1891     if ((stricmp (argv[0], "-a") == 0) || (stricmp (argv[0], "--align") == 0)) {\r
1892       if (AsciiStringToUint64 (argv[1], FALSE, &Temp64) != EFI_SUCCESS) {\r
1893         Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
1894         goto Finish;\r
1895       }\r
1896       MciAlignment = (UINT32) Temp64;\r
1897       argc -= 2;\r
1898       argv += 2;\r
1899       continue;\r
1900     }\r
1901 \r
1902     if ((stricmp (argv[0], "-p") == 0) || (stricmp (argv[0], "--pad") == 0)) {\r
1903       if (AsciiStringToUint64 (argv[1], FALSE, &Temp64) != EFI_SUCCESS) {\r
1904         Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
1905         goto Finish;\r
1906       }\r
1907       MciPadValue = (UINT8) Temp64;\r
1908       argc -= 2;\r
1909       argv += 2;\r
1910       continue;\r
1911     }\r
1912 \r
1913     if ((stricmp (argv[0], "-v") == 0) || (stricmp (argv[0], "--verbose") == 0)) {\r
1914       SetPrintLevel (VERBOSE_LOG_LEVEL);\r
1915       VerboseMsg ("Verbose output Mode Set!");\r
1916       argc --;\r
1917       argv ++;\r
1918       continue;\r
1919     }\r
1920 \r
1921     if ((stricmp (argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) {\r
1922       SetPrintLevel (KEY_LOG_LEVEL);\r
1923       KeyMsg ("Quiet output Mode Set!");\r
1924       argc --;\r
1925       argv ++;\r
1926       continue;\r
1927     }\r
1928 \r
1929     if ((stricmp (argv[0], "-d") == 0) || (stricmp (argv[0], "--debug") == 0)) {\r
1930       Status = AsciiStringToUint64 (argv[1], FALSE, &LogLevel);\r
1931       if (EFI_ERROR (Status)) {\r
1932         Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
1933         goto Finish;\r
1934       }\r
1935       if (LogLevel > 9) {\r
1936         Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0-9, currnt input level is %d", (int) LogLevel);\r
1937         goto Finish;\r
1938       }\r
1939       SetPrintLevel (LogLevel);\r
1940       DebugMsg (NULL, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv[1]);\r
1941       argc -= 2;\r
1942       argv += 2;\r
1943       continue;\r
1944     }\r
1945     \r
1946     if ((stricmp (argv[0], "-g") == 0) || (stricmp (argv[0], "--hiiguid") == 0)) {\r
1947       Status = StringToGuid (argv[1], &HiiPackageListGuid);\r
1948       if (EFI_ERROR (Status)) {\r
1949         Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
1950         goto Finish;\r
1951       }\r
1952       argc -= 2;\r
1953       argv += 2;\r
1954       continue;\r
1955     }\r
1956 \r
1957     if (stricmp (argv[0], "--hiipackage") == 0) {\r
1958       OutImageType = FW_HII_PACKAGE_LIST_RCIMAGE;\r
1959       argc --;\r
1960       argv ++;\r
1961       continue;\r
1962     }\r
1963 \r
1964     if (stricmp (argv[0], "--hiibinpackage") == 0) {\r
1965       OutImageType = FW_HII_PACKAGE_LIST_BINIMAGE;\r
1966       argc --;\r
1967       argv ++;\r
1968       continue;\r
1969     }\r
1970 \r
1971     if (argv[0][0] == '-') {\r
1972       Error (NULL, 0, 1000, "Unknown option", argv[0]);\r
1973       goto Finish;\r
1974     }\r
1975     //\r
1976     // Get Input file name\r
1977     //\r
1978     if ((InputFileNum == 0) && (InputFileName == NULL)) {\r
1979       InputFileName = (CHAR8 **) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *));\r
1980       if (InputFileName == NULL) {\r
1981         Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
1982         goto Finish;\r
1983       }\r
1984 \r
1985       memset (InputFileName, 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));\r
1986     } else if (InputFileNum % MAXIMUM_INPUT_FILE_NUM == 0) {\r
1987       //\r
1988       // InputFileName buffer too small, need to realloc\r
1989       //\r
1990       InputFileName = (CHAR8 **) realloc (\r
1991                                   InputFileName,\r
1992                                   (InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (CHAR8 *)\r
1993                                   );\r
1994 \r
1995       if (InputFileName == NULL) {\r
1996         Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
1997         goto Finish;\r
1998       }\r
1999 \r
2000       memset (&(InputFileName[InputFileNum]), 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));\r
2001     }\r
2002 \r
2003     InputFileName [InputFileNum ++] = argv[0];\r
2004     argc --;\r
2005     argv ++;\r
2006   }\r
2007 \r
2008   VerboseMsg ("%s tool start.", UTILITY_NAME);\r
2009 \r
2010   if (OutImageType == FW_DUMMY_IMAGE) {\r
2011     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
2012     if (ReplaceFlag) {\r
2013       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
2014     }\r
2015     goto Finish;\r
2016   }\r
2017 \r
2018   //\r
2019   // check input files\r
2020   //\r
2021   if (InputFileNum == 0) {\r
2022     Error (NULL, 0, 1001, "Missing option", "Input files");\r
2023     goto Finish;\r
2024   }\r
2025 \r
2026   //\r
2027   // Combine MciBinary files to one file\r
2028   //\r
2029   if ((OutImageType == FW_MERGE_IMAGE) && ReplaceFlag) {\r
2030     Error (NULL, 0, 1002, "Conflicting option", "-r replace option cannot be used with -j merge files option.");\r
2031     goto Finish;\r
2032   }\r
2033 \r
2034   //\r
2035   // Combine HiiBinary packages to a single package list\r
2036   //\r
2037   if ((OutImageType == FW_HII_PACKAGE_LIST_RCIMAGE) && ReplaceFlag) {\r
2038     Error (NULL, 0, 1002, "Conflicting option", "-r replace option cannot be used with --hiipackage merge files option.");\r
2039     goto Finish;\r
2040   }\r
2041 \r
2042   if ((OutImageType == FW_HII_PACKAGE_LIST_BINIMAGE) && ReplaceFlag) {\r
2043     Error (NULL, 0, 1002, "Conflicting option", "-r replace option cannot be used with --hiibinpackage merge files option.");\r
2044     goto Finish;\r
2045   }\r
2046 \r
2047   //\r
2048   // Input image file\r
2049   //\r
2050   mInImageName = InputFileName [InputFileNum - 1];\r
2051   VerboseMsg ("the input file name is %s", mInImageName);\r
2052 \r
2053   //\r
2054   // Action will be taken for the input file.\r
2055   //\r
2056   switch (OutImageType) {\r
2057   case FW_EFI_IMAGE:\r
2058     VerboseMsg ("Create efi image on module type %s based on the input PE image.", ModuleType);\r
2059     break;\r
2060   case FW_TE_IMAGE:\r
2061     VerboseMsg ("Create Te Image based on the input PE image.");\r
2062     break;\r
2063   case FW_ACPI_IMAGE:\r
2064     VerboseMsg ("Get acpi table data from the input PE image.");\r
2065     break;\r
2066   case FW_RELOC_STRIPEED_IMAGE:\r
2067     VerboseMsg ("Remove relocation section from Pe or Te image.");\r
2068     break;\r
2069   case FW_BIN_IMAGE:\r
2070     VerboseMsg ("Convert the input EXE to the output BIN file.");\r
2071     break;\r
2072   case FW_ZERO_DEBUG_IMAGE:\r
2073     VerboseMsg ("Zero the Debug Data Fields and Time Stamp in input PE image.");\r
2074     break;\r
2075   case FW_SET_STAMP_IMAGE:\r
2076     VerboseMsg ("Set new time stamp %s in the input PE image.", TimeStamp);\r
2077     break;\r
2078   case DUMP_TE_HEADER:\r
2079     VerboseMsg ("Dump the TE header information of the input TE image.");\r
2080     break;\r
2081   case FW_MCI_IMAGE:\r
2082     VerboseMsg ("Conver input MicroCode.txt file to MicroCode.bin file.");\r
2083     break;\r
2084   case FW_MERGE_IMAGE:\r
2085     VerboseMsg ("Combine the input multi microcode bin files to one bin file.");\r
2086     break;\r
2087   case FW_HII_PACKAGE_LIST_RCIMAGE:\r
2088     VerboseMsg ("Combine the input multi hii bin packages to one text pacakge list RC file.");\r
2089     break;\r
2090   case FW_HII_PACKAGE_LIST_BINIMAGE:\r
2091     VerboseMsg ("Combine the input multi hii bin packages to one binary pacakge list file.");\r
2092     break;\r
2093   default:\r
2094     break;\r
2095   }\r
2096 \r
2097   if (ReplaceFlag) {\r
2098     VerboseMsg ("Overwrite the input file with the output content.");\r
2099   }\r
2100 \r
2101   //\r
2102   // Open output file and Write image into the output file.\r
2103   //\r
2104   if (OutImageName != NULL) {\r
2105     fpOut = fopen (OutImageName, "rb");\r
2106     if (fpOut != NULL) {\r
2107       OutputFileLength = _filelength (fileno (fpOut));\r
2108       OutputFileBuffer = malloc (OutputFileLength);\r
2109       if (OutputFileBuffer == NULL) {\r
2110         Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
2111         fclose (fpOut);\r
2112         fpOut = NULL;\r
2113         goto Finish;\r
2114       }\r
2115       fread (OutputFileBuffer, 1, OutputFileLength, fpOut);\r
2116       fclose (fpOut);\r
2117     }\r
2118     fpOut = fopen (OutImageName, "wb");\r
2119     if (!fpOut) {\r
2120       Error (NULL, 0, 0001, "Error opening output file", OutImageName);\r
2121       goto Finish;\r
2122     }\r
2123     VerboseMsg ("Output file name is %s", OutImageName);\r
2124   } else if (!ReplaceFlag) {\r
2125     if (OutImageType == DUMP_TE_HEADER) {\r
2126       fpOut = stdout;\r
2127     } else {\r
2128       Error (NULL, 0, 1001, "Missing option", "output file");\r
2129       goto Finish;\r
2130     }\r
2131   }\r
2132 \r
2133   //\r
2134   // Combine multi binary HII package files.\r
2135   //\r
2136   if (OutImageType == FW_HII_PACKAGE_LIST_RCIMAGE || OutImageType == FW_HII_PACKAGE_LIST_BINIMAGE) {\r
2137     //\r
2138     // Get hii package list lenght\r
2139     //\r
2140     HiiPackageListHeader.PackageLength = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
2141     for (Index = 0; Index < InputFileNum; Index ++) {\r
2142       fpIn = fopen (InputFileName [Index], "rb");\r
2143       if (!fpIn) {\r
2144         Error (NULL, 0, 0001, "Error opening file", InputFileName [Index]);\r
2145         goto Finish;\r
2146       }\r
2147       FileLength = _filelength (fileno (fpIn));\r
2148       fread (&HiiPackageHeader, 1, sizeof (HiiPackageHeader), fpIn);\r
2149       if (HiiPackageHeader.Type == EFI_HII_PACKAGE_FORM) {\r
2150         if (HiiPackageHeader.Length != FileLength) {\r
2151           Error (NULL, 0, 3000, "Invalid", "The wrong package size is in HII package file %s", InputFileName [Index]);\r
2152           fclose (fpIn);\r
2153           goto Finish;\r
2154         }\r
2155         if (memcmp (&HiiPackageListGuid, &mZeroGuid, sizeof (EFI_GUID)) == 0) {\r
2156           fread (&IfrFormSet, 1, sizeof (IfrFormSet), fpIn);\r
2157           memcpy (&HiiPackageListGuid, &IfrFormSet.Guid, sizeof (EFI_GUID));\r
2158         }\r
2159         NumberOfFormPacakge ++;\r
2160       }\r
2161       HiiPackageListHeader.PackageLength += FileLength;\r
2162       fclose (fpIn);\r
2163     }\r
2164     HiiPackageListHeader.PackageLength += sizeof (EndPackage);\r
2165     //\r
2166     // Check whether hii packages are valid\r
2167     //\r
2168     if (NumberOfFormPacakge > 1) {\r
2169       Error (NULL, 0, 3000, "Invalid", "The input hii packages contains more than one hii form package");\r
2170       goto Finish;\r
2171     }\r
2172     if (memcmp (&HiiPackageListGuid, &mZeroGuid, sizeof (EFI_GUID)) == 0) {\r
2173       Error (NULL, 0, 3000, "Invalid", "HII pacakge list guid is not specified!");\r
2174       goto Finish;\r
2175     }\r
2176     memcpy (&HiiPackageListHeader.PackageListGuid, &HiiPackageListGuid, sizeof (EFI_GUID));\r
2177     //\r
2178     // read hii packages\r
2179     //\r
2180     HiiPackageListBuffer = malloc (HiiPackageListHeader.PackageLength);\r
2181     if (HiiPackageListBuffer == NULL) {\r
2182       Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
2183       goto Finish;\r
2184     }\r
2185     memcpy (HiiPackageListBuffer, &HiiPackageListHeader, sizeof (HiiPackageListHeader));\r
2186     HiiPackageDataPointer = HiiPackageListBuffer + sizeof (HiiPackageListHeader);\r
2187     for (Index = 0; Index < InputFileNum; Index ++) {\r
2188       fpIn = fopen (InputFileName [Index], "rb");\r
2189       if (!fpIn) {\r
2190         Error (NULL, 0, 0001, "Error opening file", InputFileName [Index]);\r
2191         free (HiiPackageListBuffer);\r
2192         goto Finish;\r
2193       }\r
2194 \r
2195       FileLength = _filelength (fileno (fpIn));\r
2196       fread (HiiPackageDataPointer, 1, FileLength, fpIn);\r
2197       fclose (fpIn);\r
2198       HiiPackageDataPointer = HiiPackageDataPointer + FileLength;\r
2199     }\r
2200     memcpy (HiiPackageDataPointer, &EndPackage, sizeof (EndPackage));\r
2201 \r
2202     //\r
2203     // write the hii package into the binary package list file with the resource section header\r
2204     //\r
2205     if (OutImageType == FW_HII_PACKAGE_LIST_BINIMAGE) {\r
2206       //\r
2207       // Create the resource section header\r
2208       //\r
2209       HiiSectionHeader = CreateHiiResouceSectionHeader (&HiiSectionHeaderSize, HiiPackageListHeader.PackageLength);\r
2210       //\r
2211       // Wrtie section header and HiiData into File.\r
2212       //\r
2213       fwrite (HiiSectionHeader, 1, HiiSectionHeaderSize, fpOut);\r
2214       fwrite (HiiPackageListBuffer, 1, HiiPackageListHeader.PackageLength, fpOut);\r
2215       //\r
2216       // Free allocated resources.\r
2217       //\r
2218       free (HiiSectionHeader);\r
2219       free (HiiPackageListBuffer);\r
2220       //\r
2221       // Done successfully\r
2222       //\r
2223       goto Finish;\r
2224     }\r
2225 \r
2226     //\r
2227     // write the hii package into the text package list rc file.\r
2228     //\r
2229     if (OutImageType == FW_HII_PACKAGE_LIST_RCIMAGE) {\r
2230       for (Index = 0; gHiiPackageRCFileHeader[Index] != NULL; Index++) {\r
2231         fprintf (fpOut, "%s\n", gHiiPackageRCFileHeader[Index]);\r
2232       }\r
2233       fprintf (fpOut, "\n%d %s\n{", HII_RESOURCE_SECTION_INDEX, HII_RESOURCE_SECTION_NAME);\r
2234 \r
2235       HiiPackageDataPointer = HiiPackageListBuffer;\r
2236       for (Index = 0; Index + 2 < HiiPackageListHeader.PackageLength; Index += 2) {\r
2237         if (Index % 16 == 0) {\r
2238           fprintf (fpOut, "\n ");\r
2239         }\r
2240         fprintf (fpOut, " 0x%04X,", *(UINT16 *) HiiPackageDataPointer);\r
2241         HiiPackageDataPointer += 2;\r
2242       }\r
2243       \r
2244       if (Index % 16 == 0) {\r
2245         fprintf (fpOut, "\n ");\r
2246       }\r
2247       if ((Index + 2) == HiiPackageListHeader.PackageLength) {\r
2248         fprintf (fpOut, " 0x%04X\n}\n", *(UINT16 *) HiiPackageDataPointer);\r
2249       }\r
2250       if ((Index + 1) == HiiPackageListHeader.PackageLength) {\r
2251         fprintf (fpOut, " 0x%04X\n}\n", *(UINT8 *) HiiPackageDataPointer);\r
2252       }\r
2253       free (HiiPackageListBuffer);\r
2254       //\r
2255       // Done successfully\r
2256       //\r
2257       goto Finish;\r
2258     }\r
2259   }\r
2260 \r
2261   //\r
2262   // Combine MciBinary files to one file\r
2263   //\r
2264   if (OutImageType == FW_MERGE_IMAGE) {\r
2265     for (Index = 0; Index < InputFileNum; Index ++) {\r
2266       fpIn = fopen (InputFileName [Index], "rb");\r
2267       if (!fpIn) {\r
2268         Error (NULL, 0, 0001, "Error opening file", InputFileName [Index]);\r
2269         goto Finish;\r
2270       }\r
2271 \r
2272       FileLength = _filelength (fileno (fpIn));\r
2273       FileBuffer = malloc (FileLength);\r
2274       if (FileBuffer == NULL) {\r
2275         Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
2276         fclose (fpIn);\r
2277         goto Finish;\r
2278       }\r
2279 \r
2280       fread (FileBuffer, 1, FileLength, fpIn);\r
2281       fclose (fpIn);\r
2282       //\r
2283       // write input file to out file\r
2284       //\r
2285       fwrite (FileBuffer, 1, FileLength, fpOut);\r
2286       //\r
2287       // write pad value to out file.\r
2288       //\r
2289       while (FileLength ++ % MciAlignment != 0) {\r
2290         fwrite (&MciPadValue, 1, 1, fpOut);\r
2291       }\r
2292       //\r
2293       // free allocated memory space\r
2294       //\r
2295       free (FileBuffer);\r
2296       FileBuffer = NULL;\r
2297     }\r
2298     //\r
2299     // Done successfully\r
2300     //\r
2301     goto Finish;\r
2302   }\r
2303 \r
2304   //\r
2305   // Convert MicroCode.txt file to MicroCode.bin file\r
2306   //\r
2307   if (OutImageType == FW_MCI_IMAGE) {\r
2308     fpIn = fopen (mInImageName, "r");\r
2309     if (!fpIn) {\r
2310       Error (NULL, 0, 0001, "Error opening file", mInImageName);\r
2311       goto Finish;\r
2312     }\r
2313 \r
2314     //\r
2315     // The first pass is to determine\r
2316     // how much data is in the file so we can allocate a working buffer.\r
2317     //\r
2318     FileLength = 0;\r
2319     do {\r
2320       Status = MicrocodeReadData (fpIn, &Data);\r
2321       if (Status == STATUS_SUCCESS) {\r
2322         FileLength += sizeof (Data);\r
2323       }\r
2324       if (Status == STATUS_IGNORE) {\r
2325         Status = STATUS_SUCCESS;\r
2326       }\r
2327     } while (Status == STATUS_SUCCESS);\r
2328     //\r
2329     // Error if no data.\r
2330     //\r
2331     if (FileLength == 0) {\r
2332       Error (NULL, 0, 3000, "Invalid", "no parseable data found in file %s", mInImageName);\r
2333       goto Finish;\r
2334     }\r
2335     if (FileLength < sizeof (MICROCODE_IMAGE_HEADER)) {\r
2336       Error (NULL, 0, 3000, "Invalid", "amount of parseable data in %s is insufficient to contain a microcode header", mInImageName);\r
2337       goto Finish;\r
2338     }\r
2339 \r
2340     //\r
2341     // Allocate a buffer for the data\r
2342     //\r
2343     FileBuffer = malloc (FileLength);\r
2344     if (FileBuffer == NULL) {\r
2345       Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
2346       goto Finish;\r
2347     }\r
2348     //\r
2349     // Re-read the file, storing the data into our buffer\r
2350     //\r
2351     fseek (fpIn, 0, SEEK_SET);\r
2352     DataPointer = (UINT32 *) FileBuffer;\r
2353     OldDataPointer = DataPointer;\r
2354     do {\r
2355       OldDataPointer = DataPointer;\r
2356       Status = MicrocodeReadData (fpIn, DataPointer++);\r
2357       if (Status == STATUS_IGNORE) {\r
2358         DataPointer = OldDataPointer;\r
2359         Status = STATUS_SUCCESS;\r
2360       }\r
2361     } while (Status == STATUS_SUCCESS);\r
2362     //\r
2363     // close input file after read data\r
2364     //\r
2365     fclose (fpIn);\r
2366 \r
2367     //\r
2368     // Can't do much checking on the header because, per the spec, the\r
2369     // DataSize field may be 0, which means DataSize = 2000 and TotalSize = 2K,\r
2370     // and the TotalSize field is invalid (actually missing). Thus we can't\r
2371     // even verify the Reserved fields are 0.\r
2372     //\r
2373     MciHeader = (MICROCODE_IMAGE_HEADER *) FileBuffer;\r
2374     if (MciHeader->DataSize == 0) {\r
2375       Index = 2048;\r
2376     } else {\r
2377       Index = MciHeader->TotalSize;\r
2378     }\r
2379 \r
2380     if (Index != FileLength) {\r
2381       Error (NULL, 0, 3000, "Invalid", "file length of %s (0x%x) does not equal expected TotalSize: 0x%04X.", mInImageName, (unsigned) FileLength, (unsigned) Index);\r
2382       goto Finish;\r
2383     }\r
2384 \r
2385     //\r
2386     // Checksum the contents\r
2387     //\r
2388     DataPointer = (UINT32 *) FileBuffer;\r
2389     CheckSum  = 0;\r
2390     Index     = 0;\r
2391     while (Index < FileLength) {\r
2392       CheckSum    += *DataPointer;\r
2393       DataPointer ++;\r
2394       Index       += sizeof (*DataPointer);\r
2395     }\r
2396     if (CheckSum != 0) {\r
2397       Error (NULL, 0, 3000, "Invalid", "checksum (0x%x) failed on file %s.", (unsigned) CheckSum, mInImageName);\r
2398       goto Finish;\r
2399     }\r
2400     //\r
2401     // Open the output file and write the buffer contents\r
2402     //\r
2403     if (fpOut != NULL) {\r
2404       if (fwrite (FileBuffer, FileLength, 1, fpOut) != 1) {\r
2405         Error (NULL, 0, 0002, "Error writing file", OutImageName);\r
2406         goto Finish;\r
2407       }\r
2408     }\r
2409 \r
2410     if (ReplaceFlag) {\r
2411       fpInOut = fopen (mInImageName, "wb");\r
2412       if (fpInOut != NULL) {\r
2413         Error (NULL, 0, 0001, "Error opening file", mInImageName);\r
2414         goto Finish;\r
2415       }\r
2416       if (fwrite (FileBuffer, FileLength, 1, fpInOut) != 1) {\r
2417         Error (NULL, 0, 0002, "Error writing file", mInImageName);\r
2418         goto Finish;\r
2419       }\r
2420     }\r
2421     VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength);\r
2422     //\r
2423     //  Convert Mci.TXT to Mci.bin file successfully\r
2424     //\r
2425     goto Finish;\r
2426   }\r
2427 \r
2428   //\r
2429   // Open input file and read file data into file buffer.\r
2430   //\r
2431   fpIn = fopen (mInImageName, "rb");\r
2432   if (!fpIn) {\r
2433     Error (NULL, 0, 0001, "Error opening file", mInImageName);\r
2434     goto Finish;\r
2435   }\r
2436 \r
2437   FileLength = _filelength (fileno (fpIn));\r
2438   FileBuffer = malloc (FileLength);\r
2439   if (FileBuffer == NULL) {\r
2440     Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
2441     fclose (fpIn);\r
2442     goto Finish;\r
2443   }\r
2444 \r
2445   fread (FileBuffer, 1, FileLength, fpIn);\r
2446   fclose (fpIn);\r
2447 \r
2448   DebugMsg (NULL, 0, 9, "input file info", "the input file size is %u bytes", (unsigned) FileLength);\r
2449 \r
2450   //\r
2451   // Replace file\r
2452   //\r
2453   if (ReplaceFlag) {\r
2454     fpInOut = fopen (mInImageName, "wb");\r
2455     if (!fpInOut) {\r
2456       Error (NULL, 0, 0001, "Error opening file", mInImageName);\r
2457       goto Finish;\r
2458     }\r
2459   }\r
2460   //\r
2461   // Dump TeImage Header into output file.\r
2462   //\r
2463   if (OutImageType == DUMP_TE_HEADER) {\r
2464     memcpy (&TEImageHeader, FileBuffer, sizeof (TEImageHeader));\r
2465     if (TEImageHeader.Signature != EFI_TE_IMAGE_HEADER_SIGNATURE) {\r
2466       Error (NULL, 0, 3000, "Invalid", "TE header signature of file %s is not correct.", mInImageName);\r
2467       goto Finish;\r
2468     }\r
2469     if (fpInOut != NULL) {\r
2470       fprintf (fpInOut, "Dump of file %s\n\n", mInImageName);\r
2471       fprintf (fpInOut, "TE IMAGE HEADER VALUES\n");\r
2472       fprintf (fpInOut, "%17X machine\n", TEImageHeader.Machine);\r
2473       fprintf (fpInOut, "%17X number of sections\n", TEImageHeader.NumberOfSections);\r
2474       fprintf (fpInOut, "%17X subsystems\n", TEImageHeader.Subsystem);\r
2475       fprintf (fpInOut, "%17X stripped size\n", TEImageHeader.StrippedSize);\r
2476       fprintf (fpInOut, "%17X entry point\n", (unsigned) TEImageHeader.AddressOfEntryPoint);\r
2477       fprintf (fpInOut, "%17X base of code\n", (unsigned) TEImageHeader.BaseOfCode);\r
2478       fprintf (fpInOut, "%17llX image base\n", (unsigned long long)TEImageHeader.ImageBase);\r
2479       fprintf (fpInOut, "%17X [%8X] RVA [size] of Base Relocation Directory\n", (unsigned) TEImageHeader.DataDirectory[0].VirtualAddress, (unsigned) TEImageHeader.DataDirectory[0].Size);\r
2480       fprintf (fpInOut, "%17X [%8X] RVA [size] of Debug Directory\n", (unsigned) TEImageHeader.DataDirectory[1].VirtualAddress, (unsigned) TEImageHeader.DataDirectory[1].Size);\r
2481     }\r
2482 \r
2483     if (fpOut != NULL) {\r
2484       fprintf (fpOut, "Dump of file %s\n\n", mInImageName);\r
2485       fprintf (fpOut, "TE IMAGE HEADER VALUES\n");\r
2486       fprintf (fpOut, "%17X machine\n", TEImageHeader.Machine);\r
2487       fprintf (fpOut, "%17X number of sections\n", TEImageHeader.NumberOfSections);\r
2488       fprintf (fpOut, "%17X subsystems\n", TEImageHeader.Subsystem);\r
2489       fprintf (fpOut, "%17X stripped size\n", TEImageHeader.StrippedSize);\r
2490       fprintf (fpOut, "%17X entry point\n", (unsigned) TEImageHeader.AddressOfEntryPoint);\r
2491       fprintf (fpOut, "%17X base of code\n", (unsigned) TEImageHeader.BaseOfCode);\r
2492       fprintf (fpOut, "%17llX image base\n", (unsigned long long)TEImageHeader.ImageBase);\r
2493       fprintf (fpOut, "%17X [%8X] RVA [size] of Base Relocation Directory\n", (unsigned) TEImageHeader.DataDirectory[0].VirtualAddress, (unsigned) TEImageHeader.DataDirectory[0].Size);\r
2494       fprintf (fpOut, "%17X [%8X] RVA [size] of Debug Directory\n", (unsigned) TEImageHeader.DataDirectory[1].VirtualAddress, (unsigned) TEImageHeader.DataDirectory[1].Size);\r
2495     }\r
2496     goto Finish;\r
2497   }\r
2498 \r
2499   //\r
2500   // Following code to convert dll to efi image or te image.\r
2501   // Get new image type\r
2502   //\r
2503   if ((OutImageType == FW_EFI_IMAGE) || (OutImageType == FW_TE_IMAGE)) {\r
2504     if (ModuleType == NULL) {\r
2505       if (OutImageType == FW_EFI_IMAGE) {\r
2506         Error (NULL, 0, 1001, "Missing option", "EFI_FILETYPE");\r
2507         goto Finish;\r
2508       } else if (OutImageType == FW_TE_IMAGE) {\r
2509         //\r
2510         // Default TE Image Type is Boot service driver\r
2511         //\r
2512         Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER;\r
2513         VerboseMsg ("Efi Image subsystem type is efi boot service driver.");\r
2514       }\r
2515     } else {\r
2516       if (stricmp (ModuleType, "BASE") == 0 ||\r
2517           stricmp (ModuleType, "SEC") == 0 ||\r
2518           stricmp (ModuleType, "SECURITY_CORE") == 0 ||\r
2519           stricmp (ModuleType, "PEI_CORE") == 0 ||\r
2520           stricmp (ModuleType, "PEIM") == 0 ||\r
2521           stricmp (ModuleType, "COMBINED_PEIM_DRIVER") == 0 ||\r
2522           stricmp (ModuleType, "PIC_PEIM") == 0 ||\r
2523           stricmp (ModuleType, "RELOCATABLE_PEIM") == 0 ||\r
2524           stricmp (ModuleType, "DXE_CORE") == 0 ||\r
2525           stricmp (ModuleType, "BS_DRIVER") == 0  ||\r
2526           stricmp (ModuleType, "DXE_DRIVER") == 0 ||\r
2527           stricmp (ModuleType, "DXE_SMM_DRIVER") == 0  ||\r
2528           stricmp (ModuleType, "UEFI_DRIVER") == 0 ||\r
2529           stricmp (ModuleType, "SMM_CORE") == 0) {\r
2530         Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER;\r
2531         VerboseMsg ("Efi Image subsystem type is efi boot service driver.");\r
2532 \r
2533       } else if (stricmp (ModuleType, "UEFI_APPLICATION") == 0 ||\r
2534                  stricmp (ModuleType, "APPLICATION") == 0) {\r
2535         Type = EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION;\r
2536         VerboseMsg ("Efi Image subsystem type is efi application.");\r
2537 \r
2538       } else if (stricmp (ModuleType, "DXE_RUNTIME_DRIVER") == 0 ||\r
2539                  stricmp (ModuleType, "RT_DRIVER") == 0) {\r
2540         Type = EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER;\r
2541         VerboseMsg ("Efi Image subsystem type is efi runtime driver.");\r
2542 \r
2543       } else if (stricmp (ModuleType, "DXE_SAL_DRIVER") == 0 ||\r
2544                  stricmp (ModuleType, "SAL_RT_DRIVER") == 0) {\r
2545         Type = EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER;\r
2546         VerboseMsg ("Efi Image subsystem type is efi sal runtime driver.");\r
2547 \r
2548       } else {\r
2549         Error (NULL, 0, 1003, "Invalid option value", "EFI_FILETYPE = %s", ModuleType);\r
2550         goto Finish;\r
2551       }\r
2552     }\r
2553   }\r
2554 \r
2555   //\r
2556   // Convert EFL image to PeImage\r
2557   //\r
2558   if (IsElfHeader(FileBuffer)) {\r
2559     VerboseMsg ("Convert the input ELF Image to Pe Image");\r
2560     ConvertElf(&FileBuffer, &FileLength);\r
2561   }\r
2562  \r
2563   //\r
2564   // Make sure File Offsets and Virtual Offsets are the same in the image so it is XIP\r
2565   // XIP == eXecute In Place\r
2566   //\r
2567   PeCoffConvertImageToXip (&FileBuffer, &FileLength);\r
2568 \r
2569   //\r
2570   // Remove reloc section from PE or TE image\r
2571   //\r
2572   if (OutImageType == FW_RELOC_STRIPEED_IMAGE) {\r
2573     //\r
2574     // Check TeImage\r
2575     //\r
2576     TeHdr = (EFI_TE_IMAGE_HEADER *) FileBuffer;\r
2577     if (TeHdr->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {\r
2578       SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (TeHdr + 1);\r
2579       for (Index = 0; Index < TeHdr->NumberOfSections; Index ++, SectionHeader ++) {\r
2580         if (strcmp ((char *)SectionHeader->Name, ".reloc") == 0) {\r
2581           //\r
2582           // Check the reloc section is in the end of image.\r
2583           //\r
2584           if ((SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData) ==\r
2585             (FileLength + TeHdr->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER))) {\r
2586             //\r
2587             // Remove .reloc section and update TeImage Header\r
2588             //\r
2589             FileLength = FileLength - SectionHeader->SizeOfRawData;\r
2590             SectionHeader->SizeOfRawData = 0;\r
2591             SectionHeader->Misc.VirtualSize = 0;\r
2592             TeHdr->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = 0;\r
2593             TeHdr->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size           = 0;\r
2594             break;\r
2595           }\r
2596         }\r
2597       }\r
2598     } else {\r
2599       //\r
2600       // Check PE Image\r
2601       //\r
2602       DosHdr = (EFI_IMAGE_DOS_HEADER *) FileBuffer;\r
2603       if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {\r
2604         PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer);\r
2605         if (PeHdr->Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) {\r
2606           Error (NULL, 0, 3000, "Invalid", "TE and DOS header signatures were not found in %s image.", mInImageName);\r
2607           goto Finish;\r
2608         }\r
2609         DosHdr = NULL;\r
2610       } else {\r
2611         PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer + DosHdr->e_lfanew);\r
2612         if (PeHdr->Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) {\r
2613           Error (NULL, 0, 3000, "Invalid", "PE header signature was not found in %s image.", mInImageName);\r
2614           goto Finish;\r
2615         }\r
2616       }\r
2617       SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);\r
2618       for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) {\r
2619         if (strcmp ((char *)SectionHeader->Name, ".reloc") == 0) {\r
2620           //\r
2621           // Check the reloc section is in the end of image.\r
2622           //\r
2623           if ((SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData) == FileLength) {\r
2624             //\r
2625             // Remove .reloc section and update PeImage Header\r
2626             //\r
2627             FileLength = FileLength - SectionHeader->SizeOfRawData;\r
2628 \r
2629             PeHdr->Pe32.FileHeader.Characteristics |= EFI_IMAGE_FILE_RELOCS_STRIPPED;\r
2630             if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
2631               Optional32 = (EFI_IMAGE_OPTIONAL_HEADER32 *)&PeHdr->Pe32.OptionalHeader;\r
2632               Optional32->SizeOfImage -= SectionHeader->SizeOfRawData;\r
2633               Optional32->SizeOfInitializedData -= SectionHeader->SizeOfRawData;\r
2634               if (Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {\r
2635                 Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = 0;\r
2636                 Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = 0;\r
2637               }\r
2638             }\r
2639             if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
2640               Optional64 = (EFI_IMAGE_OPTIONAL_HEADER64 *)&PeHdr->Pe32.OptionalHeader;\r
2641               Optional64->SizeOfImage -= SectionHeader->SizeOfRawData;\r
2642               Optional64->SizeOfInitializedData -= SectionHeader->SizeOfRawData;\r
2643               if (Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {\r
2644                 Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = 0;\r
2645                 Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = 0;\r
2646               }\r
2647             }\r
2648             SectionHeader->Misc.VirtualSize = 0;\r
2649             SectionHeader->SizeOfRawData = 0;\r
2650             break;\r
2651           }\r
2652         }\r
2653       }\r
2654     }\r
2655     //\r
2656     // Write file\r
2657     //\r
2658     goto WriteFile;\r
2659   }\r
2660   //\r
2661   // Read the dos & pe hdrs of the image\r
2662   //\r
2663   DosHdr = (EFI_IMAGE_DOS_HEADER *)FileBuffer;\r
2664   if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {\r
2665     // NO DOS header, check for PE/COFF header\r
2666     PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer);\r
2667     if (PeHdr->Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) {\r
2668       Error (NULL, 0, 3000, "Invalid", "DOS header signature was not found in %s image.", mInImageName);\r
2669       goto Finish;\r
2670     }\r
2671     DosHdr = NULL;\r
2672   } else {\r
2673 \r
2674     PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer + DosHdr->e_lfanew);\r
2675     if (PeHdr->Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) {\r
2676       Error (NULL, 0, 3000, "Invalid", "PE header signature was not found in %s image.", mInImageName);\r
2677       goto Finish;\r
2678     }\r
2679   }\r
2680   \r
2681   if (PeHdr->Pe32.FileHeader.Machine == IMAGE_FILE_MACHINE_ARM) {\r
2682     // Some tools kick out IMAGE_FILE_MACHINE_ARM (0x1c0) vs IMAGE_FILE_MACHINE_ARMT (0x1c2)\r
2683     // so patch back to the offical UEFI value.\r
2684     PeHdr->Pe32.FileHeader.Machine = IMAGE_FILE_MACHINE_ARMT;\r
2685   }\r
2686 \r
2687   //\r
2688   // Extract bin data from Pe image.\r
2689   //\r
2690   if (OutImageType == FW_BIN_IMAGE) {\r
2691     if (FileLength < PeHdr->Pe32.OptionalHeader.SizeOfHeaders) {\r
2692       Error (NULL, 0, 3000, "Invalid", "FileSize of %s is not a legal size.", mInImageName);\r
2693       goto Finish;\r
2694     }\r
2695     //\r
2696     // Output bin data from exe file\r
2697     //\r
2698     if (fpOut != NULL) {\r
2699       fwrite (FileBuffer + PeHdr->Pe32.OptionalHeader.SizeOfHeaders, 1, FileLength - PeHdr->Pe32.OptionalHeader.SizeOfHeaders, fpOut);\r
2700     }\r
2701     if (fpInOut != NULL) {\r
2702       fwrite (FileBuffer + PeHdr->Pe32.OptionalHeader.SizeOfHeaders, 1, FileLength - PeHdr->Pe32.OptionalHeader.SizeOfHeaders, fpInOut);\r
2703     }\r
2704     VerboseMsg ("the size of output file is %u bytes", (unsigned) (FileLength - PeHdr->Pe32.OptionalHeader.SizeOfHeaders));\r
2705     goto Finish;\r
2706   }\r
2707 \r
2708   //\r
2709   // Zero Debug Information of Pe Image\r
2710   //\r
2711   if (OutImageType == FW_ZERO_DEBUG_IMAGE) {\r
2712     Status = ZeroDebugData (FileBuffer, TRUE);\r
2713     if (EFI_ERROR (Status)) {\r
2714       Error (NULL, 0, 3000, "Invalid", "Zero DebugData Error status is 0x%x", (int) Status);\r
2715       goto Finish;\r
2716     }\r
2717 \r
2718     if (fpOut != NULL) {\r
2719       fwrite (FileBuffer, 1, FileLength, fpOut);\r
2720     }\r
2721     if (fpInOut != NULL) {\r
2722       fwrite (FileBuffer, 1, FileLength, fpInOut);\r
2723     }\r
2724     VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength);\r
2725     goto Finish;\r
2726   }\r
2727 \r
2728   //\r
2729   // Set Time Stamp of Pe Image\r
2730   //\r
2731   if (OutImageType == FW_SET_STAMP_IMAGE) {\r
2732     Status = SetStamp (FileBuffer, TimeStamp);\r
2733     if (EFI_ERROR (Status)) {\r
2734       goto Finish;\r
2735     }\r
2736 \r
2737     if (fpOut != NULL) {\r
2738       fwrite (FileBuffer, 1, FileLength, fpOut);\r
2739     }\r
2740     if (fpInOut != NULL) {\r
2741       fwrite (FileBuffer, 1, FileLength, fpInOut);\r
2742     }\r
2743     VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength);\r
2744     goto Finish;\r
2745   }\r
2746 \r
2747   //\r
2748   // Extract acpi data from pe image.\r
2749   //\r
2750   if (OutImageType == FW_ACPI_IMAGE) {\r
2751     SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);\r
2752     for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) {\r
2753       if (strcmp ((char *)SectionHeader->Name, ".data") == 0 || strcmp ((char *)SectionHeader->Name, ".sdata") == 0) {\r
2754         //\r
2755         // Check Acpi Table\r
2756         //\r
2757         if (SectionHeader->Misc.VirtualSize < SectionHeader->SizeOfRawData) {\r
2758           FileLength = SectionHeader->Misc.VirtualSize;\r
2759         } else {\r
2760           FileLength = SectionHeader->SizeOfRawData;\r
2761         }\r
2762 \r
2763         if (CheckAcpiTable (FileBuffer + SectionHeader->PointerToRawData, FileLength) != STATUS_SUCCESS) {\r
2764           Error (NULL, 0, 3000, "Invalid", "ACPI table check failed in %s.", mInImageName);\r
2765           goto Finish;\r
2766         }\r
2767 \r
2768         //\r
2769         // Output Apci data to file\r
2770         //\r
2771         if (fpOut != NULL) {\r
2772           fwrite (FileBuffer + SectionHeader->PointerToRawData, 1, FileLength, fpOut);\r
2773         }\r
2774         if (fpInOut != NULL) {\r
2775           fwrite (FileBuffer + SectionHeader->PointerToRawData, 1, FileLength, fpInOut);\r
2776         }\r
2777         VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength);\r
2778         goto Finish;\r
2779       }\r
2780     }\r
2781     Error (NULL, 0, 3000, "Invalid", "failed to get ACPI table from %s.", mInImageName);\r
2782     goto Finish;\r
2783   }\r
2784   //\r
2785   // Zero all unused fields of the DOS header\r
2786   //\r
2787   if (DosHdr != NULL) {\r
2788     memcpy (&BackupDosHdr, DosHdr, sizeof (EFI_IMAGE_DOS_HEADER));\r
2789     memset (DosHdr, 0, sizeof (EFI_IMAGE_DOS_HEADER));\r
2790     DosHdr->e_magic  = BackupDosHdr.e_magic;\r
2791     DosHdr->e_lfanew = BackupDosHdr.e_lfanew;\r
2792   \r
2793     for (Index = sizeof (EFI_IMAGE_DOS_HEADER); Index < (UINT32 ) DosHdr->e_lfanew; Index++) {\r
2794       FileBuffer[Index] = (UINT8) DosHdr->e_cp;\r
2795     }\r
2796   }\r
2797 \r
2798   //\r
2799   // Initialize TeImage Header\r
2800   //\r
2801   memset (&TEImageHeader, 0, sizeof (EFI_TE_IMAGE_HEADER));\r
2802   TEImageHeader.Signature        = EFI_TE_IMAGE_HEADER_SIGNATURE;\r
2803   TEImageHeader.Machine          = PeHdr->Pe32.FileHeader.Machine;\r
2804   TEImageHeader.NumberOfSections = (UINT8) PeHdr->Pe32.FileHeader.NumberOfSections;\r
2805   TEImageHeader.StrippedSize     = (UINT16) ((UINTN) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader) - (UINTN) FileBuffer);\r
2806   TEImageHeader.Subsystem        = (UINT8) Type;\r
2807   \r
2808   //\r
2809   // Patch the PE header\r
2810   //\r
2811   PeHdr->Pe32.OptionalHeader.Subsystem = (UINT16) Type;\r
2812 \r
2813   if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
2814     Optional32 = (EFI_IMAGE_OPTIONAL_HEADER32 *)&PeHdr->Pe32.OptionalHeader;\r
2815     Optional32->MajorLinkerVersion          = 0;\r
2816     Optional32->MinorLinkerVersion          = 0;\r
2817     Optional32->MajorOperatingSystemVersion = 0;\r
2818     Optional32->MinorOperatingSystemVersion = 0;\r
2819     Optional32->MajorImageVersion           = 0;\r
2820     Optional32->MinorImageVersion           = 0;\r
2821     Optional32->MajorSubsystemVersion       = 0;\r
2822     Optional32->MinorSubsystemVersion       = 0;\r
2823     Optional32->Win32VersionValue           = 0;\r
2824     Optional32->CheckSum                    = 0;\r
2825     Optional32->SizeOfStackReserve = 0;\r
2826     Optional32->SizeOfStackCommit  = 0;\r
2827     Optional32->SizeOfHeapReserve  = 0;\r
2828     Optional32->SizeOfHeapCommit   = 0;\r
2829 \r
2830     TEImageHeader.AddressOfEntryPoint = Optional32->AddressOfEntryPoint;\r
2831     TEImageHeader.BaseOfCode          = Optional32->BaseOfCode;\r
2832     TEImageHeader.ImageBase           = (UINT64) (Optional32->ImageBase);\r
2833 \r
2834     if (Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {\r
2835       TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;\r
2836       TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;\r
2837     }\r
2838 \r
2839     if (Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {\r
2840       TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;\r
2841       TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size;\r
2842     }\r
2843 \r
2844     //\r
2845     // Zero .pdata section data.\r
2846     //\r
2847     if (!KeepExceptionTableFlag && Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION &&\r
2848         Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress != 0 &&\r
2849         Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size != 0) {\r
2850       SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);\r
2851       for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++, SectionHeader++) {\r
2852         if (SectionHeader->VirtualAddress == Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress) {\r
2853           //\r
2854           // Zero .pdata Section data\r
2855           //\r
2856           memset (FileBuffer + SectionHeader->PointerToRawData, 0, SectionHeader->SizeOfRawData);\r
2857           //\r
2858           // Zero .pdata Section header name\r
2859           //\r
2860           memset (SectionHeader->Name, 0, sizeof (SectionHeader->Name));\r
2861           //\r
2862           // Zero Execption Table\r
2863           //\r
2864           Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress = 0;\r
2865           Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size           = 0;\r
2866           DebugMsg (NULL, 0, 9, "Zero the .pdata section for PE image", NULL);\r
2867           break;\r
2868         }\r
2869       }\r
2870     }\r
2871 \r
2872     //\r
2873     // Strip zero padding at the end of the .reloc section\r
2874     //\r
2875     if (!KeepZeroPendingFlag && Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {\r
2876       if (Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size != 0) {\r
2877         SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);\r
2878         for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++, SectionHeader++) {\r
2879           //\r
2880           // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory\r
2881           //\r
2882           if (SectionHeader->VirtualAddress == Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress) {\r
2883             SectionHeader->Misc.VirtualSize = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;\r
2884             AllignedRelocSize = (Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size + Optional32->FileAlignment - 1) & (~(Optional32->FileAlignment - 1));\r
2885             //\r
2886             // Check to see if there is zero padding at the end of the base relocations\r
2887             //\r
2888             if (AllignedRelocSize < SectionHeader->SizeOfRawData) {\r
2889               //\r
2890               // Check to see if the base relocations are at the end of the file\r
2891               //\r
2892               if (SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData == Optional32->SizeOfImage) {\r
2893                 //\r
2894                 // All the required conditions are met to strip the zero padding of the end of the base relocations section\r
2895                 //\r
2896                 Optional32->SizeOfImage -= (SectionHeader->SizeOfRawData - AllignedRelocSize);\r
2897                 Optional32->SizeOfInitializedData -= (SectionHeader->SizeOfRawData - AllignedRelocSize);\r
2898                 SectionHeader->SizeOfRawData = AllignedRelocSize;\r
2899                 FileLength = Optional32->SizeOfImage;\r
2900                 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
2901               }\r
2902             }\r
2903           }\r
2904         }\r
2905       }\r
2906     }\r
2907   } else if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
2908     Optional64 = (EFI_IMAGE_OPTIONAL_HEADER64 *)&PeHdr->Pe32.OptionalHeader;\r
2909     Optional64->MajorLinkerVersion          = 0;\r
2910     Optional64->MinorLinkerVersion          = 0;\r
2911     Optional64->MajorOperatingSystemVersion = 0;\r
2912     Optional64->MinorOperatingSystemVersion = 0;\r
2913     Optional64->MajorImageVersion           = 0;\r
2914     Optional64->MinorImageVersion           = 0;\r
2915     Optional64->MajorSubsystemVersion       = 0;\r
2916     Optional64->MinorSubsystemVersion       = 0;\r
2917     Optional64->Win32VersionValue           = 0;\r
2918     Optional64->CheckSum                    = 0;\r
2919     Optional64->SizeOfStackReserve = 0;\r
2920     Optional64->SizeOfStackCommit  = 0;\r
2921     Optional64->SizeOfHeapReserve  = 0;\r
2922     Optional64->SizeOfHeapCommit   = 0;\r
2923 \r
2924     TEImageHeader.AddressOfEntryPoint = Optional64->AddressOfEntryPoint;\r
2925     TEImageHeader.BaseOfCode          = Optional64->BaseOfCode;\r
2926     TEImageHeader.ImageBase           = (UINT64) (Optional64->ImageBase);\r
2927 \r
2928     if (Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {\r
2929       TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;\r
2930       TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;\r
2931     }\r
2932 \r
2933     if (Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {\r
2934       TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;\r
2935       TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size;\r
2936     }\r
2937 \r
2938     //\r
2939     // Zero the .pdata section for X64 machine and don't check the Debug Directory is empty\r
2940     // For Itaninum and X64 Image, remove .pdata section.\r
2941     //\r
2942     if ((!KeepExceptionTableFlag && PeHdr->Pe32.FileHeader.Machine == IMAGE_FILE_MACHINE_X64) || PeHdr->Pe32.FileHeader.Machine == IMAGE_FILE_MACHINE_IA64) {\r
2943       if (Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION &&\r
2944           Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress != 0 &&\r
2945           Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size != 0) {\r
2946         SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);\r
2947         for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++, SectionHeader++) {\r
2948           if (SectionHeader->VirtualAddress == Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress) {\r
2949             //\r
2950             // Zero .pdata Section header name\r
2951             //\r
2952             memset (SectionHeader->Name, 0, sizeof (SectionHeader->Name));\r
2953 \r
2954             RuntimeFunction = (RUNTIME_FUNCTION *)(FileBuffer + SectionHeader->PointerToRawData);\r
2955             for (Index1 = 0; Index1 < Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size / sizeof (RUNTIME_FUNCTION); Index1++, RuntimeFunction++) {\r
2956               SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);\r
2957               for (Index2 = 0; Index2 < PeHdr->Pe32.FileHeader.NumberOfSections; Index2++, SectionHeader++) {\r
2958                 if (RuntimeFunction->UnwindInfoAddress >= SectionHeader->VirtualAddress && RuntimeFunction->UnwindInfoAddress < (SectionHeader->VirtualAddress + SectionHeader->SizeOfRawData)) {\r
2959                   UnwindInfo = (UNWIND_INFO *)(FileBuffer + SectionHeader->PointerToRawData + (RuntimeFunction->UnwindInfoAddress - SectionHeader->VirtualAddress));\r
2960                   if (UnwindInfo->Version == 1) {\r
2961                     memset (UnwindInfo + 1, 0, UnwindInfo->CountOfUnwindCodes * sizeof (UINT16));\r
2962                     memset (UnwindInfo, 0, sizeof (UNWIND_INFO));\r
2963                   }\r
2964                   break;\r
2965                 }\r
2966               }\r
2967               memset (RuntimeFunction, 0, sizeof (RUNTIME_FUNCTION));\r
2968             }\r
2969             //\r
2970             // Zero Execption Table\r
2971             //\r
2972             Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size = 0;\r
2973             Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress = 0;\r
2974             DebugMsg (NULL, 0, 9, "Zero the .pdata section if the machine type is X64 for PE32+ image", NULL);\r
2975             break;\r
2976           }\r
2977         }\r
2978       }\r
2979     }\r
2980 \r
2981     //\r
2982     // Strip zero padding at the end of the .reloc section\r
2983     //\r
2984     if (!KeepZeroPendingFlag && Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {\r
2985       if (Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size != 0) {\r
2986         SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);\r
2987         for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++, SectionHeader++) {\r
2988           //\r
2989           // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory\r
2990           //\r
2991           if (SectionHeader->VirtualAddress == Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress) {\r
2992             SectionHeader->Misc.VirtualSize = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;\r
2993             AllignedRelocSize = (Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size + Optional64->FileAlignment - 1) & (~(Optional64->FileAlignment - 1));\r
2994             //\r
2995             // Check to see if there is zero padding at the end of the base relocations\r
2996             //\r
2997             if (AllignedRelocSize < SectionHeader->SizeOfRawData) {\r
2998               //\r
2999               // Check to see if the base relocations are at the end of the file\r
3000               //\r
3001               if (SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData == Optional64->SizeOfImage) {\r
3002                 //\r
3003                 // All the required conditions are met to strip the zero padding of the end of the base relocations section\r
3004                 //\r
3005                 Optional64->SizeOfImage -= (SectionHeader->SizeOfRawData - AllignedRelocSize);\r
3006                 Optional64->SizeOfInitializedData -= (SectionHeader->SizeOfRawData - AllignedRelocSize);\r
3007                 SectionHeader->SizeOfRawData = AllignedRelocSize;\r
3008                 FileLength = Optional64->SizeOfImage;\r
3009                 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
3010               }\r
3011             }\r
3012           }\r
3013         }\r
3014       }\r
3015     }\r
3016   } else {\r
3017     Error (NULL, 0, 3000, "Invalid", "Magic 0x%x of PeImage %s is unknown.", PeHdr->Pe32.OptionalHeader.Magic, mInImageName);\r
3018     goto Finish;\r
3019   }\r
3020   \r
3021   if (((PeHdr->Pe32.FileHeader.Characteristics & EFI_IMAGE_FILE_RELOCS_STRIPPED) == 0) && \\r
3022     (TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress == 0) && \\r
3023     (TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size == 0)) {\r
3024     //\r
3025     // PeImage can be loaded into memory, but it has no relocation section. \r
3026     // Fix TeImage Header to set VA of relocation data directory to not zero, the size is still zero.\r
3027     //\r
3028     if (Optional32 != NULL) {\r
3029       TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = Optional32->SizeOfImage - sizeof (EFI_IMAGE_BASE_RELOCATION);\r
3030     } else if (Optional64 != NULL) {\r
3031       TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = Optional64->SizeOfImage - sizeof (EFI_IMAGE_BASE_RELOCATION);\r
3032     }\r
3033   }\r
3034 \r
3035   //\r
3036   // Fill HII section data\r
3037   //\r
3038   SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);\r
3039   for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++) {\r
3040     if (stricmp ((char *)SectionHeader[Index].Name, ".hii") == 0) {\r
3041       //\r
3042       // Update resource section header offset\r
3043       //\r
3044       SetHiiResourceHeader ((UINT8*) FileBuffer + SectionHeader[Index].PointerToRawData, SectionHeader[Index].VirtualAddress);\r
3045       //\r
3046       // Update resource section name\r
3047       //\r
3048       strcpy((char *) SectionHeader[Index].Name, ".rsrc");\r
3049       //\r
3050       // Update resource data directory.\r
3051       //\r
3052       if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
3053         Optional32 = (EFI_IMAGE_OPTIONAL_HEADER32 *)&PeHdr->Pe32.OptionalHeader;\r
3054         Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = SectionHeader[Index].VirtualAddress;\r
3055         Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = SectionHeader[Index].Misc.VirtualSize;\r
3056       } else if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
3057         Optional64 = (EFI_IMAGE_OPTIONAL_HEADER64 *)&PeHdr->Pe32.OptionalHeader;\r
3058         Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = SectionHeader[Index].VirtualAddress;\r
3059         Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = SectionHeader[Index].Misc.VirtualSize;\r
3060       }\r
3061       break;\r
3062     }\r
3063   }\r
3064 \r
3065   //\r
3066   // Zero ExceptionTable Xdata\r
3067   //\r
3068   if (!KeepExceptionTableFlag) {\r
3069     SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);\r
3070     for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++) {\r
3071       if (stricmp ((char *)SectionHeader[Index].Name, ".xdata") == 0) {\r
3072         //\r
3073         // zero .xdata section\r
3074         //\r
3075         memset (FileBuffer + SectionHeader[Index].PointerToRawData, 0, SectionHeader[Index].SizeOfRawData);\r
3076         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
3077         break;\r
3078       }\r
3079     }\r
3080   }\r
3081 \r
3082   //\r
3083   // Zero Time/Data field\r
3084   //\r
3085   ZeroDebugData (FileBuffer, FALSE);\r
3086 \r
3087   if (OutImageType == FW_TE_IMAGE) {\r
3088     if ((PeHdr->Pe32.FileHeader.NumberOfSections &~0xFF) || (Type &~0xFF)) {\r
3089       //\r
3090       // Pack the subsystem and NumberOfSections into 1 byte. Make sure they fit both.\r
3091       //\r
3092       Error (NULL, 0, 3000, "Invalid", "Image's subsystem or NumberOfSections of PeImage %s cannot be packed into 1 byte.", mInImageName);\r
3093       goto Finish;\r
3094     }\r
3095 \r
3096     if ((PeHdr->Pe32.OptionalHeader.SectionAlignment != PeHdr->Pe32.OptionalHeader.FileAlignment)) {\r
3097       //\r
3098       // TeImage has the same section alignment and file alignment.\r
3099       //\r
3100       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
3101       goto Finish;\r
3102     }\r
3103 \r
3104     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
3105               TEImageHeader.Machine, TEImageHeader.NumberOfSections, TEImageHeader.StrippedSize, (unsigned) TEImageHeader.AddressOfEntryPoint, (unsigned) TEImageHeader.BaseOfCode, (unsigned long long) TEImageHeader.ImageBase);\r
3106     //\r
3107     // Update Image to TeImage\r
3108     //\r
3109     if (fpOut != NULL) {\r
3110       fwrite (&TEImageHeader, 1, sizeof (EFI_TE_IMAGE_HEADER), fpOut);\r
3111       fwrite (FileBuffer + TEImageHeader.StrippedSize, 1, FileLength - TEImageHeader.StrippedSize, fpOut);\r
3112     }\r
3113     if (fpInOut != NULL) {\r
3114       fwrite (&TEImageHeader, 1, sizeof (EFI_TE_IMAGE_HEADER), fpInOut);\r
3115       fwrite (FileBuffer + TEImageHeader.StrippedSize, 1, FileLength - TEImageHeader.StrippedSize, fpInOut);\r
3116     }\r
3117     VerboseMsg ("the size of output file is %u bytes", (unsigned) (FileLength - TEImageHeader.StrippedSize));\r
3118     goto Finish;\r
3119   }\r
3120 WriteFile:\r
3121   //\r
3122   // Update Image to EfiImage\r
3123   //\r
3124   if (fpOut != NULL) {\r
3125     fwrite (FileBuffer, 1, FileLength, fpOut);\r
3126   }\r
3127   if (fpInOut != NULL) {\r
3128     fwrite (FileBuffer, 1, FileLength, fpInOut);\r
3129   }\r
3130   VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength);\r
3131 \r
3132 Finish:\r
3133   if (fpInOut != NULL) {\r
3134     if (GetUtilityStatus () != STATUS_SUCCESS) {\r
3135       //\r
3136       // when file updates failed, original file is still recoveried.\r
3137       //\r
3138       fwrite (FileBuffer, 1, FileLength, fpInOut);\r
3139     }\r
3140     //\r
3141     // Write converted data into fpInOut file and close input file.\r
3142     //\r
3143     fclose (fpInOut);\r
3144   }\r
3145 \r
3146   if (FileBuffer != NULL) {\r
3147     free (FileBuffer);\r
3148   }\r
3149 \r
3150   if (InputFileName != NULL) {\r
3151     free (InputFileName);\r
3152   }\r
3153 \r
3154   if (fpOut != NULL) {\r
3155     //\r
3156     // Write converted data into fpOut file and close output file.\r
3157     //\r
3158     fclose (fpOut);\r
3159     if (GetUtilityStatus () != STATUS_SUCCESS) {\r
3160       if (OutputFileBuffer == NULL) {\r
3161         remove (OutImageName);\r
3162       } else {\r
3163         fpOut = fopen (OutImageName, "wb");\r
3164         fwrite (OutputFileBuffer, 1, OutputFileLength, fpOut);\r
3165         fclose (fpOut);\r
3166         free (OutputFileBuffer);\r
3167       }\r
3168     }\r
3169   }\r
3170 \r
3171   VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME, GetUtilityStatus ());\r
3172 \r
3173   return GetUtilityStatus ();\r
3174 }\r
3175 \r
3176 STATIC\r
3177 EFI_STATUS\r
3178 ZeroDebugData (\r
3179   IN OUT UINT8   *FileBuffer,\r
3180   BOOLEAN        ZeroDebugFlag\r
3181   )\r
3182 /*++\r
3183 \r
3184 Routine Description:\r
3185 \r
3186   Zero debug information in PeImage.\r
3187 \r
3188 Arguments:\r
3189 \r
3190   FileBuffer    - Pointer to PeImage.\r
3191   ZeroDebugFlag - TRUE to zero Debug information, FALSE to only zero time/stamp\r
3192 \r
3193 Returns:\r
3194 \r
3195   EFI_ABORTED   - PeImage is invalid.\r
3196   EFI_SUCCESS   - Zero debug data successfully.\r
3197 \r
3198 --*/\r
3199 {\r
3200   UINT32                           Index;\r
3201   UINT32                           DebugDirectoryEntryRva;\r
3202   UINT32                           DebugDirectoryEntryFileOffset;\r
3203   UINT32                           ExportDirectoryEntryRva;\r
3204   UINT32                           ExportDirectoryEntryFileOffset;\r
3205   UINT32                           ResourceDirectoryEntryRva;\r
3206   UINT32                           ResourceDirectoryEntryFileOffset;\r
3207   EFI_IMAGE_DOS_HEADER            *DosHdr;\r
3208   EFI_IMAGE_FILE_HEADER           *FileHdr;\r
3209   EFI_IMAGE_OPTIONAL_HEADER32     *Optional32Hdr;\r
3210   EFI_IMAGE_OPTIONAL_HEADER64     *Optional64Hdr;\r
3211   EFI_IMAGE_SECTION_HEADER        *SectionHeader;\r
3212   EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *DebugEntry;\r
3213   UINT32                          *NewTimeStamp;  \r
3214 \r
3215   //\r
3216   // Init variable.\r
3217   //\r
3218   DebugDirectoryEntryRva           = 0;\r
3219   ExportDirectoryEntryRva          = 0;\r
3220   ResourceDirectoryEntryRva        = 0;\r
3221   DebugDirectoryEntryFileOffset    = 0;\r
3222   ExportDirectoryEntryFileOffset   = 0;\r
3223   ResourceDirectoryEntryFileOffset = 0;\r
3224   DosHdr   = (EFI_IMAGE_DOS_HEADER *)  FileBuffer;\r
3225   FileHdr  = (EFI_IMAGE_FILE_HEADER *) (FileBuffer + DosHdr->e_lfanew + sizeof (UINT32));\r
3226 \r
3227 \r
3228   DosHdr = (EFI_IMAGE_DOS_HEADER *)FileBuffer;\r
3229   if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {\r
3230     // NO DOS header, must start with PE/COFF header\r
3231     FileHdr  = (EFI_IMAGE_FILE_HEADER *)(FileBuffer + sizeof (UINT32));\r
3232   } else {\r
3233     FileHdr  = (EFI_IMAGE_FILE_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof (UINT32));\r
3234   }\r
3235 \r
3236   //\r
3237   // Get Debug, Export and Resource EntryTable RVA address.\r
3238   // Resource Directory entry need to review.\r
3239   //\r
3240   if (FileHdr->Machine == EFI_IMAGE_MACHINE_IA32) {\r
3241     Optional32Hdr = (EFI_IMAGE_OPTIONAL_HEADER32 *) ((UINT8*) FileHdr + sizeof (EFI_IMAGE_FILE_HEADER));\r
3242     SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) Optional32Hdr +  FileHdr->SizeOfOptionalHeader);\r
3243     if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXPORT && \\r
3244         Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].Size != 0) {\r
3245       ExportDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;\r
3246     }\r
3247     if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE && \\r
3248         Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size != 0) {\r
3249       ResourceDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;\r
3250     }\r
3251     if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG && \\r
3252         Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) {\r
3253       DebugDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;\r
3254       if (ZeroDebugFlag) {\r
3255         Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = 0;\r
3256         Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = 0;\r
3257       }\r
3258     }\r
3259   } else {\r
3260     Optional64Hdr = (EFI_IMAGE_OPTIONAL_HEADER64 *) ((UINT8*) FileHdr + sizeof (EFI_IMAGE_FILE_HEADER));\r
3261     SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) Optional64Hdr +  FileHdr->SizeOfOptionalHeader);\r
3262     if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXPORT && \\r
3263         Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].Size != 0) {\r
3264       ExportDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;\r
3265     }\r
3266     if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE && \\r
3267         Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size != 0) {\r
3268       ResourceDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;\r
3269     }\r
3270     if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG && \\r
3271         Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) {\r
3272       DebugDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;\r
3273       if (ZeroDebugFlag) {\r
3274         Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = 0;\r
3275         Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = 0;\r
3276       }\r
3277     }\r
3278   }\r
3279 \r
3280   //\r
3281   // Get DirectoryEntryTable file offset.\r
3282   //\r
3283   for (Index = 0; Index < FileHdr->NumberOfSections; Index ++, SectionHeader ++) {\r
3284     if (DebugDirectoryEntryRva >= SectionHeader->VirtualAddress &&\r
3285         DebugDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) {\r
3286         DebugDirectoryEntryFileOffset =\r
3287         DebugDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData;\r
3288     }\r
3289     if (ExportDirectoryEntryRva >= SectionHeader->VirtualAddress &&\r
3290         ExportDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) {\r
3291         ExportDirectoryEntryFileOffset =\r
3292         ExportDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData;\r
3293     }\r
3294     if (ResourceDirectoryEntryRva >= SectionHeader->VirtualAddress &&\r
3295         ResourceDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) {\r
3296         ResourceDirectoryEntryFileOffset =\r
3297         ResourceDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData;\r
3298     }\r
3299   }\r
3300 \r
3301   //\r
3302   //Zero Debug Data and TimeStamp\r
3303   //\r
3304   FileHdr->TimeDateStamp = 0;\r
3305 \r
3306   if (ExportDirectoryEntryFileOffset != 0) {\r
3307     NewTimeStamp  = (UINT32 *) (FileBuffer + ExportDirectoryEntryFileOffset + sizeof (UINT32));\r
3308     *NewTimeStamp = 0;\r
3309   }\r
3310 \r
3311   if (ResourceDirectoryEntryFileOffset != 0) {\r
3312     NewTimeStamp  = (UINT32 *) (FileBuffer + ResourceDirectoryEntryFileOffset + sizeof (UINT32));\r
3313     *NewTimeStamp = 0;\r
3314   }\r
3315 \r
3316   if (DebugDirectoryEntryFileOffset != 0) {\r
3317     DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) (FileBuffer + DebugDirectoryEntryFileOffset);\r
3318     DebugEntry->TimeDateStamp = 0;\r
3319     if (ZeroDebugFlag) {\r
3320       memset (FileBuffer + DebugEntry->FileOffset, 0, DebugEntry->SizeOfData);\r
3321       memset (DebugEntry, 0, sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY));\r
3322     }\r
3323   }\r
3324 \r
3325   return EFI_SUCCESS;\r
3326 }\r
3327 \r
3328 STATIC\r
3329 EFI_STATUS\r
3330 SetStamp (\r
3331   IN OUT UINT8  *FileBuffer,\r
3332   IN     CHAR8  *TimeStamp\r
3333   )\r
3334 /*++\r
3335 \r
3336 Routine Description:\r
3337 \r
3338   Set new time stamp into PeImage FileHdr and Directory table:\r
3339   Debug, Export and Resource.\r
3340 \r
3341 Arguments:\r
3342 \r
3343   FileBuffer    - Pointer to PeImage.\r
3344   TimeStamp     - Time stamp string.\r
3345 \r
3346 Returns:\r
3347 \r
3348   EFI_INVALID_PARAMETER   - TimeStamp format is not recognized.\r
3349   EFI_SUCCESS             - Set new time stamp in this image successfully.\r
3350 \r
3351 --*/\r
3352 {\r
3353   struct tm                       stime;\r
3354   struct tm                       *ptime;\r
3355   time_t                          newtime;\r
3356   UINT32                          Index;\r
3357   UINT32                          DebugDirectoryEntryRva;\r
3358   UINT32                          DebugDirectoryEntryFileOffset;\r
3359   UINT32                          ExportDirectoryEntryRva;\r
3360   UINT32                          ExportDirectoryEntryFileOffset;\r
3361   UINT32                          ResourceDirectoryEntryRva;\r
3362   UINT32                          ResourceDirectoryEntryFileOffset;\r
3363   EFI_IMAGE_DOS_HEADER            *DosHdr;\r
3364   EFI_IMAGE_FILE_HEADER           *FileHdr;\r
3365   EFI_IMAGE_OPTIONAL_HEADER32     *Optional32Hdr;\r
3366   EFI_IMAGE_OPTIONAL_HEADER64     *Optional64Hdr;\r
3367   EFI_IMAGE_SECTION_HEADER        *SectionHeader;\r
3368   UINT32                          *NewTimeStamp;\r
3369   \r
3370   //\r
3371   // Init variable.\r
3372   //\r
3373   DebugDirectoryEntryRva           = 0;\r
3374   DebugDirectoryEntryFileOffset    = 0;\r
3375   ExportDirectoryEntryRva          = 0;\r
3376   ExportDirectoryEntryFileOffset   = 0;\r
3377   ResourceDirectoryEntryRva        = 0;\r
3378   ResourceDirectoryEntryFileOffset = 0;\r
3379   //\r
3380   // Get time and date that will be set.\r
3381   //\r
3382   if (TimeStamp == NULL) {\r
3383     Error (NULL, 0, 3000, "Invalid", "TimeStamp cannot be NULL.");\r
3384     return EFI_INVALID_PARAMETER;\r
3385   }\r
3386   //\r
3387   // compare the value with "NOW", if yes, current system time is set.\r
3388   //\r
3389   if (stricmp (TimeStamp, "NOW") == 0) {\r
3390     //\r
3391     // get system current time and date\r
3392     //\r
3393     time (&newtime);\r
3394   } else {\r
3395     //\r
3396     // Check Time Format strictly yyyy-mm-dd 00:00:00\r
3397     //\r
3398     for (Index = 0; TimeStamp[Index] != '\0' && Index < 20; Index ++) {\r
3399       if (Index == 4 || Index == 7) {\r
3400         if (TimeStamp[Index] == '-') {\r
3401           continue;\r
3402         }\r
3403       } else if (Index == 13 || Index == 16) {\r
3404         if (TimeStamp[Index] == ':') {\r
3405           continue;\r
3406         }\r
3407       } else if (Index == 10 && TimeStamp[Index] == ' ') {\r
3408         continue;\r
3409       } else if ((TimeStamp[Index] < '0') || (TimeStamp[Index] > '9')) {\r
3410         break;\r
3411       }\r
3412     }\r
3413 \r
3414     if (Index < 19 || TimeStamp[19] != '\0') {\r
3415       Error (NULL, 0, 1003, "Invalid&n