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