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