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