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