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