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