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