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