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