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