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