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