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