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