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