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