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