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