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