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