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