Update GenFw and GenFv tool to support more features based on base tools spec.
[people/mcb30/basetools.git] / Source / C / GenFw / GenFw.c
1 /*++\r
2 \r
3 Copyright (c) 2004 - 2007, 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 image type\r
19 \r
20 --*/\r
21 \r
22 #include "WinNtInclude.h"\r
23 \r
24 //\r
25 // List of OS and CPU which support ELF to PE conversion\r
26 //\r
27 #if defined(linux)
28 #if defined (__i386__) || defined(__x86_64__)
29 #define HAVE_ELF
30 #endif
31 #endif
32
33 #ifndef __GNUC__\r
34 #include <windows.h>\r
35 #endif\r
36 #include <stdio.h>\r
37 #include <stdlib.h>\r
38 #include <string.h>\r
39 #include <time.h>\r
40
41 #ifdef HAVE_ELF
42 #include <elf.h>
43 #endif
44 \r
45 #include <Common/UefiBaseTypes.h>\r
46 #include <Common/EfiImage.h>\r
47 \r
48 #include "CommonLib.h"\r
49 #include "EfiUtilityMsgs.c"\r
50 \r
51 //\r
52 // Acpi Table definition\r
53 //\r
54 #include "Acpi.h"\r
55 #include "Acpi1_0.h"\r
56 #include "Acpi2_0.h"\r
57 #include "Acpi3_0.h"\r
58 #include "MemoryMappedConfigurationSpaceAccessTable.h"\r
59 \r
60 //\r
61 // Version of this utility\r
62 //\r
63 #define UTILITY_NAME "GenFw"\r
64 #define UTILITY_MAJOR_VERSION 1\r
65 #define UTILITY_MINOR_VERSION 0\r
66 \r
67 UINT8 *InImageName;\r
68 \r
69 #define FW_DUMMY_IMAGE       0\r
70 #define FW_EFI_IMAGE         1\r
71 #define FW_TE_IMAGE          2\r
72 #define FW_ACPI_IMAGE        3\r
73 #define FW_BIN_IMAGE         4\r
74 #define FW_ZERO_DEBUG_IMAGE  5\r
75 #define FW_SET_STAMP_IMAGE   6\r
76 \r
77 #define DUMP_TE_HEADER       0x11\r
78 #define FW_REPLACE_IMAGE     0x100\r
79 \r
80  \r
81 #define MAX_STRING_LENGTH 100\r
82 \r
83 STATIC\r
84 EFI_STATUS\r
85 ZeroDebugData (\r
86   IN OUT UINT8   *FileBuffer\r
87   );\r
88 \r
89 STATIC \r
90 EFI_STATUS\r
91 SetStamp (\r
92   IN OUT UINT8  *FileBuffer, \r
93   IN     CHAR8  *TimeStamp\r
94   );\r
95 \r
96 static\r
97 VOID\r
98 Version (\r
99   VOID\r
100   )\r
101 {\r
102   printf ("%s v%d.%d -EDK Utility mainly for Converting a pe32+ image to an FW image type.\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION);\r
103   printf ("Copyright (c) 2007 Intel Corporation. All rights reserved.\n");\r
104 }\r
105 \r
106 STATIC\r
107 VOID\r
108 Usage (\r
109   VOID\r
110   )\r
111 {\r
112   Version();\r
113   printf ("\nUsage: " UTILITY_NAME " [inputfilename]\n\\r
114         -o, --outputfile [FileName]\n\\r
115         -e, --efiImage <BASE|SEC|PEI_CORE|PEIM|DXE_CORE|DXE_DRIVER|\n\\r
116                         DXE_RUNTIME_DRIVER|DXE_SAL_DRIVER|DXE_SMM_DRIVER|\n\\r
117                         UEFI_DRIVER|UEFI_APPLICATION|SECURITY_CORE|\n\\r
118                         COMBINED_PEIM_DRIVER|PIC_PEIM|RELOCATABLE_PEIM|\n\\r
119                         BS_DRIVER|RT_DRIVER|SAL_RT_DRIVER|APPLICATION>\n\\r
120         -c, --acpi\n\\r
121         -t, --terse\n\\r
122         -u, --dump\n\\r
123         -z, --zero\n\\r
124         -b, --exe2bin\n\\r
125         -r, --replace\n\\r
126         -s, --stamp [time-data] <NOW|\"####-##-## ##:##:##\">\n\\r
127         -h, --help\n\\r
128         -V, --version\n");\r
129 }\r
130 \r
131 static\r
132 STATUS\r
133 CheckAcpiTable (\r
134   VOID      *AcpiTable,\r
135   UINT32    Length\r
136   )\r
137 /*++\r
138 \r
139 Routine Description:\r
140   \r
141   Check Acpi Table \r
142 \r
143 Arguments:\r
144 \r
145   AcpiTable     Buffer for AcpiSection\r
146   Length        AcpiSection Length\r
147 \r
148 Returns:\r
149 \r
150   0             success\r
151   non-zero      otherwise\r
152 \r
153 --*/\r
154 {\r
155   EFI_ACPI_DESCRIPTION_HEADER                   *AcpiHeader;\r
156   EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE  *Facs;\r
157   UINT32                                        ExpectedLength;\r
158 \r
159   AcpiHeader = (EFI_ACPI_DESCRIPTION_HEADER *)AcpiTable;\r
160 \r
161   //\r
162   // Generic check for AcpiTable length.\r
163   //\r
164   if (AcpiHeader->Length > Length) {\r
165     Error (NULL, 0, 0, "CheckAcpiTable", "failed to pass AcpiTable Length check");\r
166     return STATUS_ERROR;\r
167   }\r
168 \r
169   //\r
170   // Currently, we only check must-have tables: FADT, FACS, DSDT,\r
171   // and some important tables: MADT, MCFG.\r
172   //\r
173   switch (AcpiHeader->Signature) {\r
174 \r
175   //\r
176   // "FACP" Fixed ACPI Description Table\r
177   //\r
178   case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE:\r
179     switch (AcpiHeader->Revision) {\r
180     case EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION:\r
181       ExpectedLength = sizeof(EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE);\r
182       break;\r
183     case EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION:\r
184       ExpectedLength = sizeof(EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE);\r
185       break;\r
186     case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION:\r
187       ExpectedLength = sizeof(EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE);\r
188       break;\r
189     default:\r
190       Error (NULL, 0, 0, "CheckAcpiTable", "failed to pass FACP revision check");\r
191       return STATUS_ERROR;\r
192     }\r
193     if (ExpectedLength != AcpiHeader->Length) {\r
194       Error (NULL, 0, 0, "CheckAcpiTable", "failed to pass FACP Length check");\r
195       return STATUS_ERROR;\r
196     }\r
197     break;\r
198 \r
199   //\r
200   // "FACS" Firmware ACPI Control Structure\r
201   //\r
202   case EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE:\r
203     Facs = (EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *)AcpiTable;\r
204     if ((Facs->Version != 0) &&\r
205         (Facs->Version != EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION) &&\r
206         (Facs->Version != EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION)){\r
207       Error (NULL, 0, 0, "CheckAcpiTable", "failed to pass FACS version check");\r
208       return STATUS_ERROR;\r
209     }\r
210     if ((Facs->Length != sizeof(EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE)) &&\r
211         (Facs->Length != sizeof(EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE)) &&\r
212         (Facs->Length != sizeof(EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE))) {\r
213       Error (NULL, 0, 0, "CheckAcpiTable", "failed to pass FACS Length check");\r
214       return STATUS_ERROR;\r
215     }\r
216     break;\r
217 \r
218   //\r
219   // "DSDT" Differentiated System Description Table\r
220   //\r
221   case EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:\r
222     if (AcpiHeader->Revision > EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_REVISION) {\r
223       Error (NULL, 0, 0, "CheckAcpiTable", "failed to pass DSDT revision check");\r
224       return STATUS_ERROR;\r
225     }\r
226     if (AcpiHeader->Length <= sizeof(EFI_ACPI_DESCRIPTION_HEADER)) {\r
227       Error (NULL, 0, 0, "CheckAcpiTable", "failed to pass DSDT Length check");\r
228       return STATUS_ERROR;\r
229     }\r
230     break;\r
231 \r
232   //\r
233   // "APIC" Multiple APIC Description Table\r
234   //\r
235   case EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE:\r
236     if ((AcpiHeader->Revision != EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION) &&\r
237         (AcpiHeader->Revision != EFI_ACPI_2_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION) &&\r
238         (AcpiHeader->Revision != EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION)) {\r
239       Error (NULL, 0, 0, "CheckAcpiTable", "failed to pass APIC revision check");\r
240       return STATUS_ERROR;\r
241     }\r
242     if (AcpiHeader->Length <= sizeof(EFI_ACPI_DESCRIPTION_HEADER) + sizeof(UINT32) + sizeof(UINT32)) {\r
243       Error (NULL, 0, 0, "CheckAcpiTable", "failed to pass APIC Length check");\r
244       return STATUS_ERROR;\r
245     }\r
246     break;\r
247 \r
248   //\r
249   // "MCFG" PCI Express Memory Mapped Configuration Space Base Address Description Table\r
250   //\r
251   case EFI_ACPI_3_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE:\r
252     if (AcpiHeader->Revision != EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION) {\r
253       Error (NULL, 0, 0, "CheckAcpiTable", "failed to pass MCFG revision check");\r
254       return STATUS_ERROR;\r
255     }\r
256     if (AcpiHeader->Length <= sizeof(EFI_ACPI_DESCRIPTION_HEADER) + sizeof(UINT64)) {\r
257       Error (NULL, 0, 0, "CheckAcpiTable", "failed to pass MCFG Length check");\r
258       return STATUS_ERROR;\r
259     }\r
260     break;\r
261 \r
262   //\r
263   // Other table pass check\r
264   //\r
265   default:\r
266     break;\r
267   }\r
268 \r
269   return STATUS_SUCCESS;\r
270 }\r
271 \r
272 static\r
273 STATUS\r
274 FCopyFile (\r
275   FILE    *in,\r
276   FILE    *out\r
277   )\r
278 {\r
279   UINT32  filesize;\r
280   UINT32  offset;\r
281   UINT32  length;\r
282   UINT8 Buffer[8 * 1024];\r
283 \r
284   fseek (in, 0, SEEK_END);\r
285   filesize = ftell (in);\r
286 \r
287   fseek (in, 0, SEEK_SET);\r
288   fseek (out, 0, SEEK_SET);\r
289 \r
290   offset = 0;\r
291   while (offset < filesize) {\r
292     length = sizeof (Buffer);\r
293     if (filesize - offset < length) {\r
294       length = filesize - offset;\r
295     }\r
296 \r
297     fread (Buffer, length, 1, in);\r
298     fwrite (Buffer, length, 1, out);\r
299     offset += length;\r
300   }\r
301 \r
302   if ((UINT32 ) ftell (out) != filesize) {\r
303     Error (NULL, 0, 0, "write error", NULL);\r
304     return STATUS_ERROR;\r
305   }\r
306 \r
307   return STATUS_SUCCESS;\r
308 }\r
309 \r
310 #ifdef HAVE_ELF
311 INTN
312 IsElfHeader(
313   UINT8  *FileBuffer
314 )
315 {
316   return (FileBuffer[EI_MAG0] == ELFMAG0
317     && FileBuffer[EI_MAG1] == ELFMAG1
318     && FileBuffer[EI_MAG2] == ELFMAG2
319     && FileBuffer[EI_MAG3] == ELFMAG3);
320 }
321
322 typedef Elf32_Shdr Elf_Shdr;
323 typedef Elf32_Ehdr Elf_Ehdr;
324 typedef Elf32_Rel Elf_Rel;
325 typedef Elf32_Sym Elf_Sym;
326 #define ELFCLASS ELFCLASS32
327 #define ELF_R_TYPE(r) ELF32_R_TYPE(r)
328 #define ELF_R_SYM(r) ELF32_R_SYM(r)
329
330 //
331 // Well known ELF structures.
332 //
333 Elf_Ehdr *Ehdr;
334 Elf_Shdr *ShdrBase;
335
336 //
337 // PE section alignment.
338 //
339 const UINT32 CoffAlignment = 0x20;
340 const UINT32 CoffNbrSections = 4;
341
342 //
343 // Current offset in coff file.
344 //
345 UINT32 CoffOffset;
346
347 //
348 // Result Coff file in memory.
349 //
350 UINT8 *CoffFile;
351
352 //
353 // Offset in Coff file of headers and sections.
354 //
355 UINT32 NtHdrOffset;
356 UINT32 TableOffset;
357 UINT32 TextOffset;
358 UINT32 DataOffset;
359 UINT32 RelocOffset;
360
361 //
362 // ELF sections to offset in Coff file.
363 //
364 UINT32 *CoffSectionsOffset;
365
366 EFI_IMAGE_BASE_RELOCATION *CoffBaseRel;
367 UINT16 *CoffEntryRel;
368
369 UINT32
370 CoffAlign(
371   UINT32 Offset
372   )
373 {
374   return (Offset + CoffAlignment - 1) & ~(CoffAlignment - 1);
375 }
376
377 Elf_Shdr *
378 GetShdrByIndex(
379   UINT32 Num
380   )
381 {
382   if (Num >= Ehdr->e_shnum)
383     return NULL;
384   return (Elf_Shdr*)((UINT8*)ShdrBase + Num * Ehdr->e_shentsize);
385 }
386
387 INTN
388 CheckElfHeader(
389   VOID
390   )
391 {\r
392   //
393   // Note: Magic has already been tested.
394   //
395   if (Ehdr->e_ident[EI_CLASS] != ELFCLASS)
396     return 0;
397   if (Ehdr->e_ident[EI_DATA] != ELFDATA2LSB)
398     return 0;
399   if (Ehdr->e_type != ET_EXEC)
400     return 0;
401   if (Ehdr->e_machine != EM_386)
402     return 0;
403   if (Ehdr->e_version != EV_CURRENT)
404     return 0;
405 \r
406   //\r
407   // Find the section header table\r
408   // 
409   ShdrBase = (Elf_Shdr *)((UINT8 *)Ehdr + Ehdr->e_shoff);
410
411   CoffSectionsOffset = (UINT32 *)malloc(Ehdr->e_shnum * sizeof (UINT32));\r
412
413   memset(CoffSectionsOffset, 0, Ehdr->e_shnum * sizeof(UINT32));\r
414   return 1;
415 }
416
417 int
418 IsTextShdr(
419   Elf_Shdr *Shdr
420   )
421 {
422   return (Shdr->sh_flags & (SHF_WRITE | SHF_ALLOC)) == SHF_ALLOC;
423 }
424 \r
425 int
426 IsDataShdr(
427   Elf_Shdr *Shdr
428   )
429 {
430   return (Shdr->sh_flags & (SHF_WRITE | SHF_ALLOC)) == (SHF_ALLOC | SHF_WRITE);
431 }
432
433 void
434 CreateSectionHeader(
435   const char *Name,
436   UINT32     Offset,
437   UINT32     Size,
438   UINT32     Flags
439   )
440 {
441   EFI_IMAGE_SECTION_HEADER *Hdr;
442   Hdr = (EFI_IMAGE_SECTION_HEADER*)(CoffFile + TableOffset);
443
444   strcpy(Hdr->Name, Name);
445   Hdr->Misc.VirtualSize = Size;
446   Hdr->VirtualAddress = Offset;
447   Hdr->SizeOfRawData = Size;
448   Hdr->PointerToRawData = Offset;
449   Hdr->PointerToRelocations = 0;
450   Hdr->PointerToLinenumbers = 0;
451   Hdr->NumberOfRelocations = 0;
452   Hdr->NumberOfLinenumbers = 0;
453   Hdr->Characteristics = Flags;
454
455   TableOffset += sizeof (EFI_IMAGE_SECTION_HEADER);
456 }
457
458 void
459 ScanSections(
460   VOID
461   )
462 {
463   UINT32 i;
464   EFI_IMAGE_DOS_HEADER *DosHdr;
465   EFI_IMAGE_NT_HEADERS *NtHdr;
466   UINT32 CoffEntry = 0;
467
468   CoffOffset = 0;
469
470   //
471   // Coff file start with a DOS header.
472   //
473   CoffOffset = sizeof(EFI_IMAGE_DOS_HEADER) + 0x40;
474   NtHdrOffset = CoffOffset;
475   CoffOffset += sizeof(EFI_IMAGE_NT_HEADERS);
476   TableOffset = CoffOffset;
477   CoffOffset += CoffNbrSections * sizeof(EFI_IMAGE_SECTION_HEADER);
478
479   //
480   // First text sections.
481   //
482   CoffOffset = CoffAlign(CoffOffset);
483   TextOffset = CoffOffset;
484   for (i = 0; i < Ehdr->e_shnum; i++) {
485     Elf_Shdr *shdr = GetShdrByIndex(i);
486     if (IsTextShdr(shdr)) {\r
487       //\r
488       // Align the coff offset to meet with the alignment requirement of section\r
489       // itself.\r
490       // \r
491       if ((shdr->sh_addralign != 0) && (shdr->sh_addralign != 1)) {\r
492         CoffOffset = (CoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1);\r
493       }\r
494 \r
495       /* Relocate entry.  */
496       if ((Ehdr->e_entry >= shdr->sh_addr) && \r
497           (Ehdr->e_entry < shdr->sh_addr + shdr->sh_size)) {
498         CoffEntry = CoffOffset + Ehdr->e_entry - shdr->sh_addr;
499       }
500       CoffSectionsOffset[i] = CoffOffset;\r
501       CoffOffset += shdr->sh_size;
502     }\r
503   }\r
504   CoffOffset = CoffAlign(CoffOffset);
505 \r
506   //
507   //  Then data sections.
508   //
509   DataOffset = CoffOffset;
510   for (i = 0; i < Ehdr->e_shnum; i++) {
511     Elf_Shdr *shdr = GetShdrByIndex(i);
512     if (IsDataShdr(shdr)) {\r
513       //\r
514       // Align the coff offset to meet with the alignment requirement of section\r
515       // itself.\r
516       // \r
517       if ((shdr->sh_addralign != 0) && (shdr->sh_addralign != 1)) {\r
518         CoffOffset = (CoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1);\r
519       }
520      \r
521       CoffSectionsOffset[i] = CoffOffset;
522       CoffOffset += shdr->sh_size;
523     }
524   }
525   CoffOffset = CoffAlign(CoffOffset);
526
527   RelocOffset = CoffOffset;  
528
529   //
530   // Allocate base Coff file.  Will be expanded later for relocations. 
531   //
532   CoffFile = (UINT8 *)malloc(CoffOffset);
533   memset(CoffFile, 0, CoffOffset);
534
535   //
536   // Fill headers.
537   //
538   DosHdr = (EFI_IMAGE_DOS_HEADER *)CoffFile;
539   DosHdr->e_magic = EFI_IMAGE_DOS_SIGNATURE;
540   DosHdr->e_lfanew = NtHdrOffset;
541
542   NtHdr = (EFI_IMAGE_NT_HEADERS*)(CoffFile + NtHdrOffset);
543
544   NtHdr->Signature = EFI_IMAGE_NT_SIGNATURE;
545
546   NtHdr->FileHeader.Machine = EFI_IMAGE_MACHINE_IA32;
547   NtHdr->FileHeader.NumberOfSections = CoffNbrSections;
548   NtHdr->FileHeader.TimeDateStamp = time(NULL);
549   NtHdr->FileHeader.PointerToSymbolTable = 0;
550   NtHdr->FileHeader.NumberOfSymbols = 0;
551   NtHdr->FileHeader.SizeOfOptionalHeader = sizeof(NtHdr->OptionalHeader);
552   NtHdr->FileHeader.Characteristics = EFI_IMAGE_FILE_EXECUTABLE_IMAGE
553     | EFI_IMAGE_FILE_LINE_NUMS_STRIPPED
554     | EFI_IMAGE_FILE_LOCAL_SYMS_STRIPPED
555     | EFI_IMAGE_FILE_32BIT_MACHINE;
556   
557   NtHdr->OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC;
558   NtHdr->OptionalHeader.SizeOfCode = DataOffset - TextOffset;
559   NtHdr->OptionalHeader.SizeOfInitializedData = RelocOffset - DataOffset;
560   NtHdr->OptionalHeader.SizeOfUninitializedData = 0;
561   NtHdr->OptionalHeader.AddressOfEntryPoint = CoffEntry;
562   NtHdr->OptionalHeader.BaseOfCode = TextOffset;
563
564   NtHdr->OptionalHeader.BaseOfData = DataOffset;
565   NtHdr->OptionalHeader.ImageBase = 0;
566   NtHdr->OptionalHeader.SectionAlignment = CoffAlignment;
567   NtHdr->OptionalHeader.FileAlignment = CoffAlignment;
568   NtHdr->OptionalHeader.SizeOfImage = 0;
569
570   NtHdr->OptionalHeader.SizeOfHeaders = TextOffset;
571   NtHdr->OptionalHeader.NumberOfRvaAndSizes = EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES;
572
573   //
574   // Section headers.
575   //
576   CreateSectionHeader (".text", TextOffset, DataOffset - TextOffset,
577            EFI_IMAGE_SCN_CNT_CODE
578            | EFI_IMAGE_SCN_MEM_EXECUTE
579            | EFI_IMAGE_SCN_MEM_READ);
580   CreateSectionHeader (".data", DataOffset, RelocOffset - DataOffset,
581            EFI_IMAGE_SCN_CNT_INITIALIZED_DATA
582            | EFI_IMAGE_SCN_MEM_WRITE
583            | EFI_IMAGE_SCN_MEM_READ);
584 }
585
586 void
587 WriteSections(
588   int   (*Filter)(Elf_Shdr *)
589   )
590 {
591   UINT32 Idx;
592
593   //
594   // First: copy sections.
595   //
596   for (Idx = 0; Idx < Ehdr->e_shnum; Idx++) {
597     Elf_Shdr *Shdr = GetShdrByIndex(Idx);
598     if ((*Filter)(Shdr)) {
599       switch (Shdr->sh_type) {
600       case SHT_PROGBITS:
601   /* Copy.  */
602   memcpy(CoffFile + CoffSectionsOffset[Idx],
603          (UINT8*)Ehdr + Shdr->sh_offset,
604          Shdr->sh_size);
605   break;
606       case SHT_NOBITS:
607   memset(CoffFile + CoffSectionsOffset[Idx], 0, Shdr->sh_size);
608   break;
609       default:
610   Error (NULL, 0, 0, InImageName, "unhandle section type %x",
611          (UINTN)Shdr->sh_type);
612       }
613     }
614   }
615
616   //
617   // Second: apply relocations.
618   //
619   for (Idx = 0; Idx < Ehdr->e_shnum; Idx++) {
620     Elf_Shdr *RelShdr = GetShdrByIndex(Idx);
621     if (RelShdr->sh_type != SHT_REL)
622       continue;
623     Elf_Shdr *SecShdr = GetShdrByIndex(RelShdr->sh_info);
624     UINT32 SecOffset = CoffSectionsOffset[RelShdr->sh_info];
625     if (RelShdr->sh_type == SHT_REL && (*Filter)(SecShdr)) {
626       UINT32 RelIdx;
627       Elf_Shdr *SymtabShdr = GetShdrByIndex(RelShdr->sh_link);
628       UINT8 *Symtab = (UINT8*)Ehdr + SymtabShdr->sh_offset;
629
630       for (RelIdx = 0; RelIdx < RelShdr->sh_size; RelIdx += RelShdr->sh_entsize) {
631   Elf_Rel *Rel = (Elf_Rel *)((UINT8*)Ehdr + RelShdr->sh_offset + RelIdx);
632   Elf_Sym *Sym = (Elf_Sym *)
633     (Symtab + ELF_R_SYM(Rel->r_info) * SymtabShdr->sh_entsize);
634   Elf_Shdr *SymShdr;
635   UINT8 *Targ;
636
637   if (Sym->st_shndx == SHN_UNDEF
638       || Sym->st_shndx == SHN_ABS
639       || Sym->st_shndx > Ehdr->e_shnum) {
640     Error (NULL, 0, 0, InImageName, "bad symbol definition");
641   }
642   SymShdr = GetShdrByIndex(Sym->st_shndx);
643
644   //
645   // Note: r_offset in a memory address.
646   //  Convert it to a pointer in the coff file.
647   //
648   Targ = CoffFile + SecOffset + (Rel->r_offset - SecShdr->sh_addr);
649
650   switch (ELF_R_TYPE(Rel->r_info)) {
651   case R_386_NONE:
652     break;
653   case R_386_32:
654     //
655     // Absolute relocation.
656     //
657     *(UINT32 *)Targ = *(UINT32 *)Targ - SymShdr->sh_addr
658       + CoffSectionsOffset[Sym->st_shndx];
659     break;
660   case R_386_PC32:
661     //
662     // Relative relocation: Symbol - Ip + Addend
663     //
664     *(UINT32 *)Targ = *(UINT32 *)Targ
665       + (CoffSectionsOffset[Sym->st_shndx] - SymShdr->sh_addr)
666       - (SecOffset - SecShdr->sh_addr);
667     break;
668   default:
669     Error (NULL, 0, 0, InImageName, "unhandled relocation type %x",
670      ELF_R_TYPE(Rel->r_info));
671   }
672       }
673     }
674   }
675 }
676
677 void
678 CoffAddFixupEntry(
679   UINT16 Val
680   )
681 {
682   *CoffEntryRel = Val;
683   CoffEntryRel++;
684   CoffBaseRel->SizeOfBlock += 2;
685   CoffOffset += 2;
686 }
687
688 void
689 CoffAddFixup(
690   UINT32 Offset,
691   UINT8  Type
692   )
693 {
694   if (CoffBaseRel == NULL
695       || CoffBaseRel->VirtualAddress != (Offset & ~0xfff)) {
696     if (CoffBaseRel != NULL) {
697       //
698       // Add a null entry (is it required ?)
699       //
700       CoffAddFixupEntry (0);
701       //
702       // Pad for alignment.
703       //
704       if (CoffOffset % 4 != 0)
705   CoffAddFixupEntry (0);
706     }
707       
708     CoffFile = realloc
709       (CoffFile,
710        CoffOffset + sizeof(EFI_IMAGE_BASE_RELOCATION) + 2*0x1000);
711     memset(CoffFile + CoffOffset, 0,
712      sizeof(EFI_IMAGE_BASE_RELOCATION) + 2*0x1000);
713
714     CoffBaseRel = (EFI_IMAGE_BASE_RELOCATION*)(CoffFile + CoffOffset);
715     CoffBaseRel->VirtualAddress = Offset & ~0xfff;
716     CoffBaseRel->SizeOfBlock = sizeof(EFI_IMAGE_BASE_RELOCATION);
717
718     CoffEntryRel = (UINT16 *)(CoffBaseRel + 1);
719     CoffOffset += sizeof(EFI_IMAGE_BASE_RELOCATION);
720   }
721
722   //
723   // Fill the entry.
724   //
725   CoffAddFixupEntry((Type << 12) | (Offset & 0xfff));
726 }
727
728 void
729 WriteRelocations(
730   VOID
731   )
732 {
733   UINT32 Idx;
734   EFI_IMAGE_NT_HEADERS *NtHdr;
735   EFI_IMAGE_DATA_DIRECTORY *Dir;
736
737   for (Idx = 0; Idx < Ehdr->e_shnum; Idx++) {
738     Elf_Shdr *RelShdr = GetShdrByIndex(Idx);
739     if (RelShdr->sh_type == SHT_REL) {
740       Elf_Shdr *SecShdr = GetShdrByIndex(RelShdr->sh_info);
741       if (IsTextShdr(SecShdr) || IsDataShdr(SecShdr)) {
742   UINT32 RelIdx;
743   for (RelIdx = 0; RelIdx < RelShdr->sh_size; RelIdx += RelShdr->sh_entsize) {
744     Elf_Rel *Rel = (Elf_Rel *)
745       ((UINT8*)Ehdr + RelShdr->sh_offset + RelIdx);
746     switch (ELF_R_TYPE(Rel->r_info)) {
747     case R_386_NONE:
748     case R_386_PC32:
749       break;
750     case R_386_32:
751       CoffAddFixup(CoffSectionsOffset[RelShdr->sh_info]
752        + (Rel->r_offset - SecShdr->sh_addr),
753        EFI_IMAGE_REL_BASED_HIGHLOW);
754       break;
755     default:
756       Error (NULL, 0, 0, InImageName, "unhandled relocation type %x",
757        ELF_R_TYPE(Rel->r_info));
758     }
759   }
760       }
761     }
762   }
763
764   //
765   // Pad by adding empty entries. 
766   //
767   while (CoffOffset & (CoffAlignment - 1)) {
768     CoffAddFixupEntry(0);
769   }
770
771   CreateSectionHeader (".reloc", RelocOffset, CoffOffset - RelocOffset,
772            EFI_IMAGE_SCN_CNT_INITIALIZED_DATA
773            | EFI_IMAGE_SCN_MEM_DISCARDABLE
774            | EFI_IMAGE_SCN_MEM_READ);
775
776   NtHdr = (EFI_IMAGE_NT_HEADERS *)(CoffFile + NtHdrOffset);
777   Dir = &NtHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];
778   Dir->VirtualAddress = RelocOffset;
779   Dir->Size = CoffOffset - RelocOffset;
780 }
781
782 void
783 WriteDebug(
784   VOID
785   )
786 {
787   UINT32 Len = strlen(InImageName) + 1;
788   UINT32 DebugOffset = CoffOffset;
789   EFI_IMAGE_NT_HEADERS *NtHdr;
790   EFI_IMAGE_DATA_DIRECTORY *DataDir;
791   EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *Dir;
792   EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY *Nb10;
793
794   CoffOffset += sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY)
795     + sizeof(EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY)
796     + Len;
797   CoffOffset = CoffAlign(CoffOffset);
798
799   CoffFile = realloc
800     (CoffFile, CoffOffset);
801   memset(CoffFile + DebugOffset, 0, CoffOffset - DebugOffset);
802   
803   Dir = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY*)(CoffFile + DebugOffset);
804   Dir->Type = EFI_IMAGE_DEBUG_TYPE_CODEVIEW;
805   Dir->SizeOfData = sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY) + Len;
806   Dir->RVA = DebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);
807   Dir->FileOffset = DebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);
808   
809   Nb10 = (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY*)(Dir + 1);
810   Nb10->Signature = CODEVIEW_SIGNATURE_NB10;
811   strcpy ((UINT8 *)(Nb10 + 1), InImageName);
812
813   CreateSectionHeader (".debug", DebugOffset, CoffOffset - DebugOffset,
814            EFI_IMAGE_SCN_CNT_INITIALIZED_DATA
815            | EFI_IMAGE_SCN_MEM_DISCARDABLE
816            | EFI_IMAGE_SCN_MEM_READ);
817
818   NtHdr = (EFI_IMAGE_NT_HEADERS *)(CoffFile + NtHdrOffset);
819   DataDir = &NtHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG];
820   DataDir->VirtualAddress = DebugOffset;
821   DataDir->Size = CoffOffset - DebugOffset;
822 }
823
824 void
825 ConvertElf (
826   UINT8  **FileBuffer,
827   UINTN *FileLength
828   )
829 {
830   EFI_IMAGE_NT_HEADERS *NtHdr;
831
832   //
833   // Check header, read section table.
834   //
835   Ehdr = (Elf32_Ehdr*)*FileBuffer;
836   if (!CheckElfHeader())
837     return;
838
839   //
840   // Compute sections new address.
841   //
842   ScanSections();
843
844   //
845   // Write and relocate sections.
846   //
847   WriteSections(IsTextShdr);
848   WriteSections(IsDataShdr);
849
850   //
851   // Translate and write relocations.
852   //
853   WriteRelocations();
854
855   //
856   // Write debug info.
857   //
858   WriteDebug();
859
860   NtHdr = (EFI_IMAGE_NT_HEADERS *)(CoffFile + NtHdrOffset);
861   NtHdr->OptionalHeader.SizeOfImage = CoffOffset;
862
863   //
864   // Replace.
865   //
866   free(*FileBuffer);
867   *FileBuffer = CoffFile;
868   *FileLength = CoffOffset;
869 }
870 #endif // HAVE_ELF
871
872 int\r
873 main (\r
874   int  argc,\r
875   char *argv[]\r
876   )\r
877 /*++\r
878 \r
879 Routine Description:\r
880 \r
881   Main function.\r
882 \r
883 Arguments:\r
884 \r
885   argc - Number of command line parameters.\r
886   argv - Array of pointers to command line parameter strings.\r
887 \r
888 Returns:\r
889   STATUS_SUCCESS - Utility exits successfully.\r
890   STATUS_ERROR   - Some error occurred during execution.\r
891 \r
892 --*/\r
893 {\r
894   UINT32            Type;\r
895   UINT8             *OutImageName;\r
896   UINT8             *ModuleType;\r
897   CHAR8             *TimeStamp;\r
898   CHAR8             FileName[MAX_STRING_LENGTH];\r
899   UINT32            OutImageType;\r
900   FILE              *fpIn;\r
901   FILE              *fpOut;\r
902   FILE              *fpInOut;\r
903   UINT32            Index;\r
904   UINT32            Index1;\r
905   UINT32            Index2;\r
906   UINTN             AllignedRelocSize;\r
907   UINT8             *FileBuffer;\r
908   UINTN             FileLength;\r
909   RUNTIME_FUNCTION  *RuntimeFunction;\r
910   UNWIND_INFO       *UnwindInfo;\r
911   STATUS            Status;\r
912 \r
913   EFI_TE_IMAGE_HEADER          TEImageHeader;\r
914   EFI_IMAGE_SECTION_HEADER     *SectionHeader;\r
915   EFI_IMAGE_DOS_HEADER         *DosHdr;\r
916   EFI_IMAGE_NT_HEADERS         *PeHdr;\r
917   EFI_IMAGE_OPTIONAL_HEADER32  *Optional32;\r
918   EFI_IMAGE_OPTIONAL_HEADER64  *Optional64;\r
919   EFI_IMAGE_DOS_HEADER         BackupDosHdr;\r
920 \r
921 \r
922   SetUtilityName (UTILITY_NAME);\r
923 \r
924   //\r
925   // Assign to fix compile warning\r
926   //\r
927   InImageName       = NULL;\r
928   OutImageName      = NULL;\r
929   ModuleType        = NULL;\r
930   OutImageType      = FW_DUMMY_IMAGE;\r
931   Type              = 0;\r
932   Status            = STATUS_SUCCESS;\r
933   FileBuffer        = NULL;\r
934   fpIn              = NULL;\r
935   fpOut             = NULL;\r
936   fpInOut           = NULL;\r
937   TimeStamp         = NULL;\r
938 \r
939   if (argc == 1) {\r
940     Usage();\r
941     return STATUS_ERROR;\r
942   }\r
943   \r
944   argc --;\r
945   argv ++;  \r
946 \r
947   if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) {\r
948     Usage();\r
949     return STATUS_ERROR;    \r
950   }\r
951 \r
952   if ((stricmp (argv[0], "-v") == 0) || (stricmp (argv[0], "--version") == 0)) {\r
953     Version();\r
954     return STATUS_ERROR;    \r
955   }\r
956   \r
957   while (argc > 0) {\r
958     if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--outputfile") == 0)) {\r
959       OutImageName = argv[1];\r
960       argc -= 2;\r
961       argv += 2;\r
962       continue; \r
963     }\r
964 \r
965     if ((stricmp (argv[0], "-e") == 0) || (stricmp (argv[0], "--efiImage") == 0)) {\r
966       ModuleType   = argv[1];\r
967       if (OutImageType == FW_DUMMY_IMAGE) {\r
968         OutImageType = FW_EFI_IMAGE;\r
969       }\r
970       argc -= 2;\r
971       argv += 2;\r
972       continue;\r
973     }\r
974 \r
975     if ((stricmp (argv[0], "-c") == 0) || (stricmp (argv[0], "--acpi") == 0)) {\r
976       OutImageType = FW_ACPI_IMAGE;\r
977       argc --;\r
978       argv ++;\r
979       continue;\r
980     }\r
981 \r
982     if ((stricmp (argv[0], "-t") == 0) || (stricmp (argv[0], "--terse") == 0)) {\r
983       OutImageType = FW_TE_IMAGE;\r
984       argc --;\r
985       argv ++;\r
986       continue;\r
987     }\r
988 \r
989     if ((stricmp (argv[0], "-u") == 0) || (stricmp (argv[0], "--dump") == 0)) {\r
990       OutImageType = DUMP_TE_HEADER;\r
991       argc --;\r
992       argv ++;\r
993       continue;\r
994     }\r
995 \r
996     if ((stricmp (argv[0], "-b") == 0) || (stricmp (argv[0], "--exe2bin") == 0)) {\r
997       OutImageType = FW_BIN_IMAGE;\r
998       argc --;\r
999       argv ++;\r
1000       continue;\r
1001     }\r
1002 \r
1003     if ((stricmp (argv[0], "-z") == 0) || (stricmp (argv[0], "--zero") == 0)) {\r
1004       OutImageType = FW_ZERO_DEBUG_IMAGE;\r
1005       argc --;\r
1006       argv ++;\r
1007       continue;\r
1008     }\r
1009 \r
1010     if ((stricmp (argv[0], "-s") == 0) || (stricmp (argv[0], "--stamp") == 0)) {\r
1011       OutImageType = FW_SET_STAMP_IMAGE;\r
1012       TimeStamp    = argv[1];\r
1013       argc -= 2;\r
1014       argv += 2;\r
1015       continue;\r
1016     }\r
1017 \r
1018     if ((stricmp (argv[0], "-r") == 0) || (stricmp (argv[0], "--replace") == 0)) {\r
1019       OutImageType |= FW_REPLACE_IMAGE;\r
1020       argc --;\r
1021       argv ++;\r
1022       continue;\r
1023     }\r
1024 \r
1025     InImageName = argv[0];\r
1026     argc --;\r
1027     argv ++;\r
1028   }\r
1029   \r
1030   if (OutImageType == FW_DUMMY_IMAGE) {\r
1031     Error (NULL, 0, 0, NULL, "No action specified, such as -e, -c or -t\n");\r
1032     Usage ();\r
1033     return STATUS_ERROR;    \r
1034   }\r
1035 \r
1036 \r
1037   //\r
1038   // get InImageName from stdin\r
1039   //\r
1040   if (InImageName == NULL) {\r
1041     fscanf (stdin, "%s", FileName);\r
1042     InImageName = (UINT8 *) FileName;\r
1043   }\r
1044 \r
1045   //\r
1046   // Open input file and read file data into file buffer.\r
1047   //\r
1048   fpIn = fopen (InImageName, "rb");\r
1049   if (!fpIn) {\r
1050     Error (NULL, 0, 0, InImageName, "failed to open input file for reading");\r
1051     goto Finish;\r
1052   }\r
1053 \r
1054   FileLength = _filelength (fileno (fpIn));\r
1055   FileBuffer = malloc (FileLength);\r
1056   if (FileBuffer == NULL) {\r
1057     Error (NULL, 0, 0, NULL, "can't allocate enough memory space");\r
1058     fclose (fpIn);\r
1059     goto Finish;\r
1060   }\r
1061   \r
1062   fread (FileBuffer, 1, FileLength, fpIn);\r
1063   fclose (fpIn);\r
1064 \r
1065   //\r
1066   // Open output file and Write image into the output file.\r
1067   // if OutImageName == NULL, output data to stdout.\r
1068   //\r
1069   if (OutImageName == NULL) {\r
1070     if ((OutImageType & FW_REPLACE_IMAGE) != 0) {\r
1071       fpOut = fopen (InImageName, "wb");\r
1072       if (!fpOut) {\r
1073         Error (NULL, 0, 0, InImageName, "could not open input file for modify");\r
1074         goto Finish;\r
1075       }\r
1076       OutImageType = OutImageType & ~FW_REPLACE_IMAGE;\r
1077     } else {\r
1078       // binary stream can't be output to string strem stdout\r
1079       // because 0x0A can be auto converted to 0x0D 0x0A.\r
1080       fpOut = stdout;\r
1081     } \r
1082   } else {\r
1083     fpOut = fopen (OutImageName, "wb");\r
1084     if (!fpOut) {\r
1085       Error (NULL, 0, 0, OutImageName, "could not open output file for writing");\r
1086       goto Finish;\r
1087     }\r
1088     if ((OutImageType & FW_REPLACE_IMAGE) != 0) {\r
1089       fpInOut = fopen (InImageName, "wb");\r
1090       if (!fpInOut) {\r
1091         Error (NULL, 0, 0, InImageName, "could not open input file for modify");\r
1092         goto Finish;\r
1093       }\r
1094       OutImageType = OutImageType & ~FW_REPLACE_IMAGE;\r
1095     }\r
1096   }
1097 \r
1098   //\r
1099   // Following code to convert dll to efi image or te image.\r
1100   // Get new image type\r
1101   //\r
1102   if ((OutImageType == FW_EFI_IMAGE) || (OutImageType == FW_TE_IMAGE)) {\r
1103     if (ModuleType == NULL) {\r
1104       Error (NULL, 0, 0, NULL, "No ModuleType specified, such as PEIM, DXE_DRIVER\n");\r
1105       Usage ();\r
1106       goto Finish;\r
1107     }\r
1108     \r
1109     if (stricmp (ModuleType, "BASE") == 0 ||\r
1110         stricmp (ModuleType, "SEC") == 0 ||\r
1111         stricmp (ModuleType, "SECURITY_CORE") == 0 ||\r
1112         stricmp (ModuleType, "PEI_CORE") == 0 ||\r
1113         stricmp (ModuleType, "PEIM") == 0 ||\r
1114         stricmp (ModuleType, "COMBINED_PEIM_DRIVER") == 0 ||\r
1115         stricmp (ModuleType, "PIC_PEIM") == 0 ||\r
1116         stricmp (ModuleType, "RELOCATABLE_PEIM") == 0 ||\r
1117         stricmp (ModuleType, "DXE_CORE") == 0 ||\r
1118         stricmp (ModuleType, "BS_DRIVER") == 0  ||\r
1119         stricmp (ModuleType, "DXE_DRIVER") == 0 ||\r
1120         stricmp (ModuleType, "DXE_SMM_DRIVER") == 0  ||\r
1121         stricmp (ModuleType, "UEFI_DRIVER") == 0) {\r
1122       Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER;\r
1123   \r
1124     } else if (stricmp (ModuleType, "UEFI_APPLICATION") == 0 || \r
1125                stricmp (ModuleType, "APPLICATION") == 0) {\r
1126       Type = EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION;\r
1127   \r
1128     } else if (stricmp (ModuleType, "DXE_RUNTIME_DRIVER") == 0 || \r
1129                stricmp (ModuleType, "RT_DRIVER") == 0) {\r
1130       Type = EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER;\r
1131   \r
1132     } else if (stricmp (ModuleType, "DXE_SAL_DRIVER") == 0 || \r
1133                stricmp (ModuleType, "SAL_RT_DRIVER") == 0) {\r
1134       Type = EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER;\r
1135   \r
1136     } else {\r
1137       Error (NULL, 0, 0, ModuleType, "%s is not one valid Module type.\n");\r
1138       Usage ();\r
1139       goto Finish;\r
1140     }\r
1141   }\r
1142  \r
1143   //\r
1144   // Dump TeImage Header into output file.\r
1145   //\r
1146   if (OutImageType == DUMP_TE_HEADER) {\r
1147     memcpy (&TEImageHeader, FileBuffer, sizeof (TEImageHeader));\r
1148     if (TEImageHeader.Signature != EFI_TE_IMAGE_HEADER_SIGNATURE) {\r
1149       Error (NULL, 0, 0, InImageName, "TE header signature is not correct");\r
1150       goto Finish;      \r
1151     }\r
1152     fprintf (fpOut, "Dump of file %s\n\n", InImageName);\r
1153     fprintf (fpOut, "TE IMAGE HEADER VALUES\n");\r
1154     fprintf (fpOut, "%17X machine\n", TEImageHeader.Machine);\r
1155     fprintf (fpOut, "%17X number of sections\n", TEImageHeader.NumberOfSections);\r
1156     fprintf (fpOut, "%17X subsystems\n", TEImageHeader.Subsystem);\r
1157     fprintf (fpOut, "%17X stripped size\n", TEImageHeader.StrippedSize);\r
1158     fprintf (fpOut, "%17X entry point\n", TEImageHeader.AddressOfEntryPoint);\r
1159     fprintf (fpOut, "%17X base of code\n", TEImageHeader.BaseOfCode);\r
1160     fprintf (fpOut, "%17X image base\n", TEImageHeader.ImageBase);\r
1161     fprintf (fpOut, "%17X [%8X] RVA [size] of Base Relocation Directory\n", TEImageHeader.DataDirectory[0].VirtualAddress, TEImageHeader.DataDirectory[0].Size);\r
1162     fprintf (fpOut, "%17X [%8X] RVA [size] of Debug Directory\n", TEImageHeader.DataDirectory[1].VirtualAddress, TEImageHeader.DataDirectory[1].Size);\r
1163     goto Finish;\r
1164   }\r
1165 \r
1166   //\r
1167   // Convert EFL image to PeImage\r
1168   //\r
1169 #ifdef HAVE_ELF
1170   if (IsElfHeader(FileBuffer)) {
1171     ConvertElf(&FileBuffer, &FileLength);
1172   }
1173 #endif\r
1174 \r
1175   //\r
1176   // Read the dos & pe hdrs of the image\r
1177   //\r
1178   DosHdr = (EFI_IMAGE_DOS_HEADER *)FileBuffer;\r
1179   if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {\r
1180     Error (NULL, 0, 0, InImageName, "DOS header signature not found in source image");\r
1181     goto Finish;\r
1182   }\r
1183 \r
1184   PeHdr = (EFI_IMAGE_NT_HEADERS *)(FileBuffer + DosHdr->e_lfanew);\r
1185   if (PeHdr->Signature != EFI_IMAGE_NT_SIGNATURE) {\r
1186     Error (NULL, 0, 0, InImageName, "PE header signature not found in source image");\r
1187     goto Finish;\r
1188   }\r
1189   \r
1190   //\r
1191   // Extract bin data from Pe image.\r
1192   //\r
1193   if (OutImageType == FW_BIN_IMAGE) {\r
1194     if (FileLength < PeHdr->OptionalHeader.SizeOfHeaders) {\r
1195       Error (NULL, 0, 0, InImageName, "FileSize is not a legal size.");\r
1196       goto Finish;\r
1197     }\r
1198     //\r
1199     // Output bin data from exe file\r
1200     //\r
1201     fwrite (FileBuffer + PeHdr->OptionalHeader.SizeOfHeaders, 1, FileLength - PeHdr->OptionalHeader.SizeOfHeaders, fpOut);\r
1202     if (fpInOut != NULL) {\r
1203       fwrite (FileBuffer + PeHdr->OptionalHeader.SizeOfHeaders, 1, FileLength - PeHdr->OptionalHeader.SizeOfHeaders, fpInOut);\r
1204     }\r
1205     goto Finish;\r
1206   }\r
1207 \r
1208   //\r
1209   // Zero Debug Information of Pe Image\r
1210   //\r
1211   if (OutImageType == FW_ZERO_DEBUG_IMAGE) {\r
1212     Status = ZeroDebugData (FileBuffer);\r
1213     if (EFI_ERROR (Status)) {\r
1214       goto Finish;\r
1215     }\r
1216 \r
1217     fwrite (FileBuffer, 1, FileLength, fpOut);\r
1218     if (fpInOut != NULL) {\r
1219       fwrite (FileBuffer, 1, FileLength, fpInOut);\r
1220     }\r
1221     goto Finish; \r
1222   }\r
1223 \r
1224   //\r
1225   // Set Time Stamp of Pe Image\r
1226   //\r
1227   if (OutImageType == FW_SET_STAMP_IMAGE) {\r
1228     Status = SetStamp (FileBuffer, TimeStamp);\r
1229     if (EFI_ERROR (Status)) {\r
1230       goto Finish;\r
1231     }\r
1232 \r
1233     fwrite (FileBuffer, 1, FileLength, fpOut);\r
1234     if (fpInOut != NULL) {\r
1235       fwrite (FileBuffer, 1, FileLength, fpInOut);\r
1236     }\r
1237     goto Finish;\r
1238   }\r
1239 \r
1240   //\r
1241   // Extract acpi data from pe image.\r
1242   //\r
1243   if (OutImageType == FW_ACPI_IMAGE) {\r
1244     SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->OptionalHeader) + PeHdr->FileHeader.SizeOfOptionalHeader); \r
1245     for (Index = 0; Index < PeHdr->FileHeader.NumberOfSections; Index ++, SectionHeader ++) {\r
1246       if (strcmp (SectionHeader->Name, ".data") == 0 || strcmp (SectionHeader->Name, ".sdata") == 0) {\r
1247         //\r
1248         // Check Acpi Table\r
1249         //\r
1250         if (SectionHeader->Misc.VirtualSize < SectionHeader->SizeOfRawData) {\r
1251           FileLength = SectionHeader->Misc.VirtualSize;\r
1252         } else {\r
1253           FileLength = SectionHeader->SizeOfRawData;\r
1254         }\r
1255 \r
1256         if (CheckAcpiTable (FileBuffer + SectionHeader->PointerToRawData, FileLength) != STATUS_SUCCESS) {\r
1257           Error (NULL, 0, 0, InImageName, "failed to check ACPI table");\r
1258           goto Finish;\r
1259         }\r
1260         \r
1261         //\r
1262         // Output Apci data to file\r
1263         //\r
1264         fwrite (FileBuffer + SectionHeader->PointerToRawData, 1, FileLength, fpOut);\r
1265         if (fpInOut != NULL) {\r
1266           fwrite (FileBuffer + SectionHeader->PointerToRawData, 1, FileLength, fpInOut);\r
1267         }\r
1268         goto Finish;\r
1269       }\r
1270     }\r
1271     Error (NULL, 0, 0, InImageName, "failed to get ACPI table");\r
1272     goto Finish;\r
1273   }\r
1274   //\r
1275   // Zero all unused fields of the DOS header\r
1276   //\r
1277   memcpy (&BackupDosHdr, DosHdr, sizeof (EFI_IMAGE_DOS_HEADER));\r
1278   memset (DosHdr, 0, sizeof (EFI_IMAGE_DOS_HEADER));\r
1279   DosHdr->e_magic  = BackupDosHdr.e_magic;\r
1280   DosHdr->e_lfanew = BackupDosHdr.e_lfanew;\r
1281 \r
1282   for (Index = sizeof (EFI_IMAGE_DOS_HEADER); Index < (UINT32 ) DosHdr->e_lfanew; Index++) {\r
1283     FileBuffer[Index] = DosHdr->e_cp;\r
1284   }\r
1285   \r
1286   //\r
1287   // Initialize TeImage Header\r
1288   //\r
1289   memset (&TEImageHeader, 0, sizeof (EFI_TE_IMAGE_HEADER));\r
1290   TEImageHeader.Signature        = EFI_TE_IMAGE_HEADER_SIGNATURE;\r
1291   TEImageHeader.Machine          = PeHdr->FileHeader.Machine;\r
1292   TEImageHeader.NumberOfSections = (UINT8) PeHdr->FileHeader.NumberOfSections;\r
1293   TEImageHeader.StrippedSize     = (UINT16) ((UINTN) ((UINT8 *) &(PeHdr->OptionalHeader) + PeHdr->FileHeader.SizeOfOptionalHeader) - (UINTN) FileBuffer);\r
1294   TEImageHeader.Subsystem        = (UINT8) Type;\r
1295 \r
1296   //\r
1297   // Patch the PE header\r
1298   //\r
1299   PeHdr->OptionalHeader.Subsystem = (UINT16) Type;\r
1300 \r
1301   if (PeHdr->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
1302     Optional32 = (EFI_IMAGE_OPTIONAL_HEADER32 *)&PeHdr->OptionalHeader;\r
1303     Optional32->MajorLinkerVersion          = 0;\r
1304     Optional32->MinorLinkerVersion          = 0;\r
1305     Optional32->MajorOperatingSystemVersion = 0;\r
1306     Optional32->MinorOperatingSystemVersion = 0;\r
1307     Optional32->MajorImageVersion           = 0;\r
1308     Optional32->MinorImageVersion           = 0;\r
1309     Optional32->MajorSubsystemVersion       = 0;\r
1310     Optional32->MinorSubsystemVersion       = 0;\r
1311     Optional32->Win32VersionValue           = 0;\r
1312     Optional32->CheckSum                    = 0;\r
1313     Optional32->SizeOfStackReserve = 0;\r
1314     Optional32->SizeOfStackCommit  = 0;\r
1315     Optional32->SizeOfHeapReserve  = 0;\r
1316     Optional32->SizeOfHeapCommit   = 0;\r
1317     \r
1318     TEImageHeader.AddressOfEntryPoint = Optional32->AddressOfEntryPoint;\r
1319     TEImageHeader.BaseOfCode          = Optional32->BaseOfCode;\r
1320     TEImageHeader.ImageBase           = (UINT64) (Optional32->ImageBase);\r
1321 \r
1322     if (Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {\r
1323       TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;\r
1324       TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;\r
1325     }\r
1326 \r
1327     if (Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {\r
1328       TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;\r
1329       TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size;\r
1330     }\r
1331 \r
1332     //\r
1333     // Strip zero padding at the end of the .reloc section \r
1334     //\r
1335     if (Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {\r
1336       if (Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size != 0) {\r
1337         SectionHeader = (EFI_IMAGE_SECTION_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof(UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + PeHdr->FileHeader.SizeOfOptionalHeader);\r
1338         for (Index = 0; Index < PeHdr->FileHeader.NumberOfSections; Index++, SectionHeader++) {\r
1339           //\r
1340           // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory\r
1341           //\r
1342           if (SectionHeader->VirtualAddress == Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress) {\r
1343             SectionHeader->Misc.VirtualSize = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;\r
1344             AllignedRelocSize = (Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size + Optional32->FileAlignment - 1) & (~(Optional32->FileAlignment - 1));\r
1345             //\r
1346             // Check to see if there is zero padding at the end of the base relocations\r
1347             //\r
1348             if (AllignedRelocSize < SectionHeader->SizeOfRawData) {\r
1349               //\r
1350               // Check to see if the base relocations are at the end of the file\r
1351               //\r
1352               if (SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData == Optional32->SizeOfImage) {\r
1353                 //\r
1354                 // All the required conditions are met to strip the zero padding of the end of the base relocations section\r
1355                 //\r
1356                 Optional32->SizeOfImage -= (SectionHeader->SizeOfRawData - AllignedRelocSize);\r
1357                 Optional32->SizeOfInitializedData -= (SectionHeader->SizeOfRawData - AllignedRelocSize);\r
1358                 SectionHeader->SizeOfRawData = AllignedRelocSize;\r
1359                 FileLength = Optional32->SizeOfImage;\r
1360               }\r
1361             }\r
1362           }\r
1363         }\r
1364       }\r
1365     }\r
1366   } \r
1367 \r
1368   if (PeHdr->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
1369     Optional64 = (EFI_IMAGE_OPTIONAL_HEADER64 *)&PeHdr->OptionalHeader;\r
1370     Optional64->MajorLinkerVersion          = 0;\r
1371     Optional64->MinorLinkerVersion          = 0;\r
1372     Optional64->MajorOperatingSystemVersion = 0;\r
1373     Optional64->MinorOperatingSystemVersion = 0;\r
1374     Optional64->MajorImageVersion           = 0;\r
1375     Optional64->MinorImageVersion           = 0;\r
1376     Optional64->MajorSubsystemVersion       = 0;\r
1377     Optional64->MinorSubsystemVersion       = 0;\r
1378     Optional64->Win32VersionValue           = 0;\r
1379     Optional64->CheckSum                    = 0;\r
1380     Optional64->SizeOfStackReserve = 0;\r
1381     Optional64->SizeOfStackCommit  = 0;\r
1382     Optional64->SizeOfHeapReserve  = 0;\r
1383     Optional64->SizeOfHeapCommit   = 0;\r
1384 \r
1385     TEImageHeader.AddressOfEntryPoint = Optional64->AddressOfEntryPoint;\r
1386     TEImageHeader.BaseOfCode          = Optional64->BaseOfCode;\r
1387     TEImageHeader.ImageBase           = (UINT64) (Optional64->ImageBase);\r
1388 \r
1389     if (Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {\r
1390       TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;\r
1391       TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;\r
1392     }\r
1393 \r
1394     if (Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {\r
1395       TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;\r
1396       TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size;\r
1397     }\r
1398 \r
1399     //\r
1400     // Zero the .pdata section if the machine type is X64 and the Debug Directory is empty\r
1401     //\r
1402     if (PeHdr->FileHeader.Machine == IMAGE_FILE_MACHINE_X64) { // X64\r
1403       if (Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION) {\r
1404         if (Optional64->NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_DEBUG || (Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG && Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size == 0)) {\r
1405           SectionHeader = (EFI_IMAGE_SECTION_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof(UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + PeHdr->FileHeader.SizeOfOptionalHeader);\r
1406           for (Index = 0; Index < PeHdr->FileHeader.NumberOfSections; Index++, SectionHeader++) {\r
1407             if (SectionHeader->VirtualAddress == Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress) {\r
1408               RuntimeFunction = (RUNTIME_FUNCTION *)(FileBuffer + SectionHeader->PointerToRawData);\r
1409               for (Index1 = 0; Index1 < Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size / sizeof (RUNTIME_FUNCTION); Index1++, RuntimeFunction++) {\r
1410                 SectionHeader = (EFI_IMAGE_SECTION_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof(UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + PeHdr->FileHeader.SizeOfOptionalHeader);\r
1411                 for (Index2 = 0; Index2 < PeHdr->FileHeader.NumberOfSections; Index2++, SectionHeader++) {\r
1412                   if (RuntimeFunction->UnwindInfoAddress > SectionHeader->VirtualAddress && RuntimeFunction->UnwindInfoAddress < (SectionHeader->VirtualAddress + SectionHeader->SizeOfRawData)) {\r
1413                     UnwindInfo = (UNWIND_INFO *)(FileBuffer + SectionHeader->PointerToRawData + (RuntimeFunction->UnwindInfoAddress - SectionHeader->VirtualAddress));\r
1414                     if (UnwindInfo->Version == 1) {\r
1415                       memset (UnwindInfo + 1, 0, UnwindInfo->CountOfUnwindCodes * sizeof (UINT16));\r
1416                       memset (UnwindInfo, 0, sizeof (UNWIND_INFO));\r
1417                     }\r
1418                   }\r
1419                 }\r
1420                 memset (RuntimeFunction, 0, sizeof (RUNTIME_FUNCTION));\r
1421               }\r
1422 \r
1423               break;\r
1424             }\r
1425           }\r
1426           Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size = 0;\r
1427           Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress = 0;\r
1428         }\r
1429       }\r
1430     }\r
1431 \r
1432     //\r
1433     // Strip zero padding at the end of the .reloc section \r
1434     //\r
1435     if (Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {\r
1436       if (Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size != 0) {\r
1437         SectionHeader = (EFI_IMAGE_SECTION_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof(UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + PeHdr->FileHeader.SizeOfOptionalHeader);\r
1438         for (Index = 0; Index < PeHdr->FileHeader.NumberOfSections; Index++, SectionHeader++) {\r
1439           //\r
1440           // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory\r
1441           //\r
1442           if (SectionHeader->VirtualAddress == Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress) {\r
1443             SectionHeader->Misc.VirtualSize = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;\r
1444             AllignedRelocSize = (Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size + Optional64->FileAlignment - 1) & (~(Optional64->FileAlignment - 1));\r
1445             //\r
1446             // Check to see if there is zero padding at the end of the base relocations\r
1447             //\r
1448             if (AllignedRelocSize < SectionHeader->SizeOfRawData) {\r
1449               //\r
1450               // Check to see if the base relocations are at the end of the file\r
1451               //\r
1452               if (SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData == Optional64->SizeOfImage) {\r
1453                 //\r
1454                 // All the required conditions are met to strip the zero padding of the end of the base relocations section\r
1455                 //\r
1456                 Optional64->SizeOfImage -= (SectionHeader->SizeOfRawData - AllignedRelocSize);\r
1457                 Optional64->SizeOfInitializedData -= (SectionHeader->SizeOfRawData - AllignedRelocSize);\r
1458                 SectionHeader->SizeOfRawData = AllignedRelocSize;\r
1459                 FileLength = Optional64->SizeOfImage;\r
1460               }\r
1461             }\r
1462           }\r
1463         }\r
1464       }\r
1465     }\r
1466   }\r
1467 \r
1468   if (OutImageType == FW_TE_IMAGE) {\r
1469     if ((PeHdr->FileHeader.NumberOfSections &~0xFF) || (Type &~0xFF)) {\r
1470       //\r
1471       // Pack the subsystem and NumberOfSections into 1 byte. Make sure they fit both.\r
1472       //\r
1473       Error (NULL, 0, 0, InImageName, "image subsystem or NumberOfSections cannot be packed into 1 byte");\r
1474       goto Finish;\r
1475     }\r
1476 \r
1477     if ((PeHdr->OptionalHeader.SectionAlignment != PeHdr->OptionalHeader.FileAlignment)) {\r
1478       //\r
1479       // TeImage has the same section alignment and file alignment.\r
1480       //\r
1481       Error (NULL, 0, 0, InImageName, "Section-Alignment and File-Alignment does not match for TeImage");\r
1482       goto Finish;\r
1483     }\r
1484 \r
1485     //\r
1486     // Update Image to TeImage\r
1487     //\r
1488     fwrite (&TEImageHeader, 1, sizeof (EFI_TE_IMAGE_HEADER), fpOut);\r
1489     fwrite (FileBuffer + TEImageHeader.StrippedSize, 1, FileLength - TEImageHeader.StrippedSize, fpOut);\r
1490     if (fpInOut != NULL) {\r
1491       fwrite (&TEImageHeader, 1, sizeof (EFI_TE_IMAGE_HEADER), fpOut);\r
1492       fwrite (FileBuffer + TEImageHeader.StrippedSize, 1, FileLength - TEImageHeader.StrippedSize, fpOut);\r
1493     }\r
1494     goto Finish;\r
1495   }\r
1496   \r
1497   //\r
1498   // Update Image to EfiImage\r
1499   //\r
1500   fwrite (FileBuffer, 1, FileLength, fpOut);\r
1501   if (fpInOut != NULL) {\r
1502     fwrite (FileBuffer, 1, FileLength, fpInOut);\r
1503   }\r
1504 \r
1505 Finish:\r
1506   if (FileBuffer != NULL) {\r
1507     free (FileBuffer);\r
1508   }\r
1509 \r
1510   if (fpOut != NULL) {\r
1511     //\r
1512     // Write converted data into fpOut file and close output file.\r
1513     //\r
1514     fclose (fpOut);\r
1515   }\r
1516 \r
1517   if (fpInOut != NULL) {\r
1518     //\r
1519     // Write converted data into fpInOut file and close input file.\r
1520     //\r
1521     fclose (fpInOut);\r
1522   }\r
1523 \r
1524   return GetUtilityStatus ();\r
1525 }\r
1526 \r
1527 STATIC\r
1528 EFI_STATUS\r
1529 ZeroDebugData (\r
1530   IN OUT UINT8   *FileBuffer\r
1531   )\r
1532 {\r
1533   UINTN                           Index;\r
1534   UINTN                           DebugDirectoryEntryRva;\r
1535   UINTN                           DebugDirectoryEntryFileOffset;\r
1536   EFI_IMAGE_DOS_HEADER            *DosHdr;\r
1537   EFI_IMAGE_FILE_HEADER           *FileHdr;\r
1538   EFI_IMAGE_OPTIONAL_HEADER32     *Optional32Hdr;\r
1539   EFI_IMAGE_OPTIONAL_HEADER64     *Optional64Hdr;\r
1540   EFI_IMAGE_SECTION_HEADER        *SectionHeader;\r
1541   EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *DebugEntry;\r
1542    \r
1543   DosHdr   = (EFI_IMAGE_DOS_HEADER *)  FileBuffer;\r
1544   FileHdr  = (EFI_IMAGE_FILE_HEADER *) (FileBuffer + DosHdr->e_lfanew + sizeof (UINT32));\r
1545   DebugDirectoryEntryRva = 0;\r
1546 \r
1547   //\r
1548   // Get DebugEntryTable RVA address.\r
1549   //\r
1550   if (FileHdr->Machine == EFI_IMAGE_MACHINE_IA32) {\r
1551     Optional32Hdr = (EFI_IMAGE_OPTIONAL_HEADER32 *) ((UINT8*) FileHdr + sizeof (EFI_IMAGE_FILE_HEADER));\r
1552     SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) Optional32Hdr +  FileHdr->SizeOfOptionalHeader);\r
1553     if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG && \\r
1554         Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) {\r
1555       DebugDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;\r
1556     } else {\r
1557       //\r
1558       // No Debug Data, nothing to do.\r
1559       //\r
1560       return EFI_SUCCESS;\r
1561     }\r
1562   } else {\r
1563     Optional64Hdr = (EFI_IMAGE_OPTIONAL_HEADER64 *) ((UINT8*) FileHdr + sizeof (EFI_IMAGE_FILE_HEADER));\r
1564     SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) Optional64Hdr +  FileHdr->SizeOfOptionalHeader);\r
1565     if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG && \\r
1566         Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) {\r
1567       DebugDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;\r
1568     } else {\r
1569       //\r
1570       // No Debug Data, nothing to do.\r
1571       //\r
1572       return EFI_SUCCESS;\r
1573     }\r
1574   }\r
1575   \r
1576   //\r
1577   // Get DebugEntryTable file offset.\r
1578   //\r
1579   for (Index = 0; Index < FileHdr->NumberOfSections; Index ++, SectionHeader ++) {\r
1580     if (DebugDirectoryEntryRva >= SectionHeader->VirtualAddress &&\r
1581         DebugDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) {\r
1582         DebugDirectoryEntryFileOffset =\r
1583         DebugDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData;\r
1584       break;\r
1585     }\r
1586   }\r
1587   \r
1588   if (Index >= FileHdr->NumberOfSections) {\r
1589     Error (NULL, 0, 0, NULL, "Invalid PeImage.");\r
1590     return EFI_ABORTED;\r
1591   }\r
1592   \r
1593   //\r
1594   // Zero Debug Data and TimeStamp\r
1595   //\r
1596   DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) (FileBuffer + DebugDirectoryEntryFileOffset);\r
1597   DebugEntry->TimeDateStamp = 0;\r
1598   memset (FileBuffer + DebugEntry->FileOffset, 0, DebugEntry->SizeOfData);\r
1599   \r
1600   return EFI_SUCCESS;\r
1601 }\r
1602 \r
1603 STATIC \r
1604 EFI_STATUS\r
1605 SetStamp (\r
1606   IN OUT UINT8  *FileBuffer, \r
1607   IN     CHAR8  *TimeStamp\r
1608   )\r
1609 {\r
1610   struct tm stime;\r
1611   time_t    newtime;\r
1612   UINTN                           Index;\r
1613   UINTN                           DebugDirectoryEntryRva;\r
1614   UINTN                           DebugDirectoryEntryFileOffset;\r
1615   UINTN                           ExportDirectoryEntryRva;\r
1616   UINTN                           ExportDirectoryEntryFileOffset;\r
1617   UINTN                           ResourceDirectoryEntryRva;\r
1618   UINTN                           ResourceDirectoryEntryFileOffset;\r
1619   EFI_IMAGE_DOS_HEADER            *DosHdr;\r
1620   EFI_IMAGE_FILE_HEADER           *FileHdr;\r
1621   EFI_IMAGE_OPTIONAL_HEADER32     *Optional32Hdr;\r
1622   EFI_IMAGE_OPTIONAL_HEADER64     *Optional64Hdr;\r
1623   EFI_IMAGE_SECTION_HEADER        *SectionHeader;\r
1624   UINT32                          *NewTimeStamp;\r
1625   \r
1626   //\r
1627   // Init variable.\r
1628   //  \r
1629   DebugDirectoryEntryRva    = 0;\r
1630   ExportDirectoryEntryRva   = 0;\r
1631   ResourceDirectoryEntryRva = 0;\r
1632 \r
1633   //\r
1634   // Get time and date that will be set.\r
1635   //\r
1636   \r
1637   //\r
1638   // compare the value with "NOW", if yes, current system time is set.\r
1639   //\r
1640   if (stricmp (TimeStamp, "NOW") == 0) {\r
1641     //\r
1642     // get system current time and date\r
1643     //\r
1644     time (&newtime);\r
1645   } else {\r
1646     //\r
1647     // get the date and time from TimeStamp\r
1648     //\r
1649     if (sscanf (TimeStamp, "%d-%d-%d %d:%d:%d",\r
1650             &stime.tm_year,\r
1651             &stime.tm_mon,\r
1652             &stime.tm_mday,\r
1653             &stime.tm_hour,\r
1654             &stime.tm_min,\r
1655             &stime.tm_sec\r
1656             ) != 6) {\r
1657       Error (NULL, 0, 0, TimeStamp, "Invaild date or time!");\r
1658       return EFI_INVALID_PARAMETER;\r
1659     }\r
1660 \r
1661     //\r
1662     // in struct, Month (0 - 11; Jan = 0). So decrease 1 from it\r
1663     //\r
1664     stime.tm_mon -= 1;\r
1665   \r
1666     //\r
1667     // in struct, Year (current year minus 1900)\r
1668     // and only the dates can be handled from Jan 1, 1970 to Jan 18, 2038\r
1669     //\r
1670     //\r
1671     // convert 0 -> 100 (2000), 1 -> 101 (2001), ..., 38 -> 138 (2038)\r
1672     //\r
1673     if (stime.tm_year <= 38) {\r
1674       stime.tm_year += 100;\r
1675     } else if (stime.tm_year >= 1970) {\r
1676       //\r
1677       // convert 1970 -> 70, 2000 -> 100, ...\r
1678       //\r
1679       stime.tm_year -= 1900;\r
1680     }\r
1681 \r
1682     //\r
1683     // convert the date and time to time_t format\r
1684     //\r
1685     newtime = mktime (&stime);\r
1686     if (newtime == (time_t) - 1) {\r
1687       Error (NULL, 0, 0, TimeStamp, "Invaild date or time!");\r
1688       return EFI_INVALID_PARAMETER;\r
1689     }\r
1690   }\r
1691   \r
1692   //\r
1693   // Set new time and data into PeImage.\r
1694   //\r
1695   DosHdr   = (EFI_IMAGE_DOS_HEADER *)  FileBuffer;\r
1696   FileHdr  = (EFI_IMAGE_FILE_HEADER *) (FileBuffer + DosHdr->e_lfanew + sizeof (UINT32));\r
1697   \r
1698   //\r
1699   // Get Debug, Export and Resource EntryTable RVA address.\r
1700   // Resource Directory entry need to review.\r
1701   //\r
1702   if (FileHdr->Machine == EFI_IMAGE_MACHINE_IA32) {\r
1703     Optional32Hdr = (EFI_IMAGE_OPTIONAL_HEADER32 *) ((UINT8*) FileHdr + sizeof (EFI_IMAGE_FILE_HEADER));\r
1704     SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) Optional32Hdr +  FileHdr->SizeOfOptionalHeader);\r
1705     if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXPORT && \\r
1706         Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].Size != 0) {\r
1707       ExportDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;\r
1708     }\r
1709     if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE && \\r
1710         Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size != 0) {\r
1711       ResourceDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;\r
1712     }\r
1713     if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG && \\r
1714         Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) {\r
1715       DebugDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;\r
1716     }\r
1717   } else {\r
1718     Optional64Hdr = (EFI_IMAGE_OPTIONAL_HEADER64 *) ((UINT8*) FileHdr + sizeof (EFI_IMAGE_FILE_HEADER));\r
1719     SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) Optional64Hdr +  FileHdr->SizeOfOptionalHeader);\r
1720     if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXPORT && \\r
1721         Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].Size != 0) {\r
1722       ExportDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;\r
1723     }\r
1724     if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE && \\r
1725         Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size != 0) {\r
1726       ResourceDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;\r
1727     }\r
1728     if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG && \\r
1729         Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) {\r
1730       DebugDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;\r
1731     }\r
1732   }\r
1733 \r
1734   //\r
1735   // Get DirectoryEntryTable file offset.\r
1736   //\r
1737   for (Index = 0; Index < FileHdr->NumberOfSections; Index ++, SectionHeader ++) {\r
1738     if (DebugDirectoryEntryRva >= SectionHeader->VirtualAddress &&\r
1739         DebugDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) {\r
1740         DebugDirectoryEntryFileOffset =\r
1741         DebugDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData;\r
1742     }\r
1743     if (ExportDirectoryEntryRva >= SectionHeader->VirtualAddress &&\r
1744         ExportDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) {\r
1745         ExportDirectoryEntryFileOffset =\r
1746         ExportDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData;\r
1747     }\r
1748     if (ResourceDirectoryEntryRva >= SectionHeader->VirtualAddress &&\r
1749         ResourceDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) {\r
1750         ResourceDirectoryEntryFileOffset =\r
1751         ResourceDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData;\r
1752     }\r
1753   }\r
1754   \r
1755   //\r
1756   // Set new stamp\r
1757   //\r
1758   FileHdr->TimeDateStamp = (UINT32) newtime;\r
1759 \r
1760   if (ExportDirectoryEntryRva != 0) {\r
1761     NewTimeStamp  = (UINT32 *) (FileBuffer + ExportDirectoryEntryFileOffset + sizeof (UINT32));\r
1762     *NewTimeStamp = (UINT32) newtime;\r
1763   }\r
1764 \r
1765   if (ResourceDirectoryEntryRva != 0) {\r
1766     NewTimeStamp  = (UINT32 *) (FileBuffer + ResourceDirectoryEntryFileOffset + sizeof (UINT32));\r
1767     *NewTimeStamp = (UINT32) newtime;\r
1768   }\r
1769 \r
1770   if (DebugDirectoryEntryRva != 0) {\r
1771     NewTimeStamp  = (UINT32 *) (FileBuffer + DebugDirectoryEntryFileOffset + sizeof (UINT32));\r
1772     *NewTimeStamp = (UINT32) newtime;\r
1773   }\r
1774   \r
1775   return EFI_SUCCESS;\r
1776 }