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