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