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