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