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