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