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