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