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