1 /** @file 2 The tool dumps the contents of a firmware volume 3 4 Copyright (c) 1999 - 2016, Intel Corporation. All rights reserved.<BR> 5 This program and the accompanying materials 6 are licensed and made available under the terms and conditions of the BSD License 7 which accompanies this distribution. The full text of the license may be found at 8 http://opensource.org/licenses/bsd-license.php 9 10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 12 13 **/ 14 15 #include <stdio.h> 16 #include <stdlib.h> 17 #include <string.h> 18 #include <ctype.h> 19 #include <assert.h> 20 #ifdef __GNUC__ 21 #include <unistd.h> 22 #else 23 #include <direct.h> 24 #endif 25 26 #include <FvLib.h> 27 #include <Common/UefiBaseTypes.h> 28 #include <Common/UefiCapsule.h> 29 #include <Common/PiFirmwareFile.h> 30 #include <Common/PiFirmwareVolume.h> 31 #include <Guid/PiFirmwareFileSystem.h> 32 #include <IndustryStandard/PeImage.h> 33 #include <Protocol/GuidedSectionExtraction.h> 34 35 #include "Compress.h" 36 #include "Decompress.h" 37 #include "VolInfo.h" 38 #include "CommonLib.h" 39 #include "EfiUtilityMsgs.h" 40 #include "FirmwareVolumeBufferLib.h" 41 #include "OsPath.h" 42 #include "ParseGuidedSectionTools.h" 43 #include "StringFuncs.h" 44 #include "ParseInf.h" 45 #include "PeCoffLib.h" 46 47 // 48 // Utility global variables 49 // 50 51 EFI_GUID gEfiCrc32GuidedSectionExtractionProtocolGuid = EFI_CRC32_GUIDED_SECTION_EXTRACTION_PROTOCOL_GUID; 52 53 #define UTILITY_MAJOR_VERSION 1 54 #define UTILITY_MINOR_VERSION 0 55 56 #define UTILITY_NAME "VolInfo" 57 58 #define EFI_SECTION_ERROR EFIERR (100) 59 60 #define MAX_BASENAME_LEN 60 // not good to hardcode, but let's be reasonable 61 62 // 63 // Structure to keep a list of guid-to-basenames 64 // 65 typedef struct _GUID_TO_BASENAME { 66 struct _GUID_TO_BASENAME *Next; 67 INT8 Guid[PRINTED_GUID_BUFFER_SIZE]; 68 INT8 BaseName[MAX_BASENAME_LEN]; 69 } GUID_TO_BASENAME; 70 71 static GUID_TO_BASENAME *mGuidBaseNameList = NULL; 72 73 // 74 // Store GUIDed Section guid->tool mapping 75 // 76 EFI_HANDLE mParsedGuidedSectionTools = NULL; 77 78 CHAR8* mUtilityFilename = NULL; 79 80 BOOLEAN EnableHash = FALSE; 81 CHAR8 *OpenSslPath = NULL; 82 83 EFI_STATUS 84 ParseGuidBaseNameFile ( 85 CHAR8 *FileName 86 ); 87 88 EFI_STATUS 89 FreeGuidBaseNameList ( 90 VOID 91 ); 92 93 EFI_STATUS 94 PrintGuidName ( 95 IN UINT8 *GuidStr 96 ); 97 98 EFI_STATUS 99 ParseSection ( 100 IN UINT8 *SectionBuffer, 101 IN UINT32 BufferLength 102 ); 103 104 EFI_STATUS 105 DumpDepexSection ( 106 IN UINT8 *Ptr, 107 IN UINT32 SectionLength 108 ); 109 110 STATIC 111 EFI_STATUS 112 ReadHeader ( 113 IN FILE *InputFile, 114 OUT UINT32 *FvSize, 115 OUT BOOLEAN *ErasePolarity 116 ); 117 118 STATIC 119 EFI_STATUS 120 PrintFileInfo ( 121 EFI_FIRMWARE_VOLUME_HEADER *FvImage, 122 EFI_FFS_FILE_HEADER *FileHeader, 123 BOOLEAN ErasePolarity 124 ); 125 126 static 127 EFI_STATUS 128 PrintFvInfo ( 129 IN VOID *Fv, 130 IN BOOLEAN IsChildFv 131 ); 132 133 static 134 VOID 135 LoadGuidedSectionToolsTxt ( 136 IN CHAR8* FirmwareVolumeFilename 137 ); 138 139 EFI_STATUS 140 CombinePath ( 141 IN CHAR8* DefaultPath, 142 IN CHAR8* AppendPath, 143 OUT CHAR8* NewPath 144 ); 145 146 void 147 Usage ( 148 VOID 149 ); 150 151 UINT32 152 UnicodeStrLen ( 153 IN CHAR16 *String 154 ) 155 /*++ 156 157 Routine Description: 158 159 Returns the length of a null-terminated unicode string. 160 161 Arguments: 162 163 String - The pointer to a null-terminated unicode string. 164 165 Returns: 166 167 N/A 168 169 --*/ 170 { 171 UINT32 Length; 172 173 for (Length = 0; *String != L'\0'; String++, Length++) { 174 ; 175 } 176 return Length; 177 } 178 179 VOID 180 Unicode2AsciiString ( 181 IN CHAR16 *Source, 182 OUT CHAR8 *Destination 183 ) 184 /*++ 185 186 Routine Description: 187 188 Convert a null-terminated unicode string to a null-terminated ascii string. 189 190 Arguments: 191 192 Source - The pointer to the null-terminated input unicode string. 193 Destination - The pointer to the null-terminated output ascii string. 194 195 Returns: 196 197 N/A 198 199 --*/ 200 { 201 while (*Source != '\0') { 202 *(Destination++) = (CHAR8) *(Source++); 203 } 204 // 205 // End the ascii with a NULL. 206 // 207 *Destination = '\0'; 208 } 209 210 int 211 main ( 212 int argc, 213 char *argv[] 214 ) 215 /*++ 216 217 Routine Description: 218 219 GC_TODO: Add function description 220 221 Arguments: 222 223 argc - GC_TODO: add argument description 224 ] - GC_TODO: add argument description 225 226 Returns: 227 228 GC_TODO: add return values 229 230 --*/ 231 { 232 FILE *InputFile; 233 int BytesRead; 234 EFI_FIRMWARE_VOLUME_HEADER *FvImage; 235 UINT32 FvSize; 236 EFI_STATUS Status; 237 int Offset; 238 BOOLEAN ErasePolarity; 239 UINT64 LogLevel; 240 CHAR8 *OpenSslEnv; 241 CHAR8 *OpenSslCommand; 242 243 SetUtilityName (UTILITY_NAME); 244 // 245 // Print utility header 246 // 247 printf ("%s Version %d.%d Build %s\n", 248 UTILITY_NAME, 249 UTILITY_MAJOR_VERSION, 250 UTILITY_MINOR_VERSION, 251 __BUILD_VERSION 252 ); 253 254 if (argc == 1) { 255 Usage (); 256 return -1; 257 } 258 259 argc--; 260 argv++; 261 LogLevel = 0; 262 Offset = 0; 263 264 // 265 // Look for help options 266 // 267 if ((strcmp(argv[0], "-h") == 0) || (strcmp(argv[0], "--help") == 0) || 268 (strcmp(argv[0], "-?") == 0) || (strcmp(argv[0], "/?") == 0)) { 269 Usage(); 270 return STATUS_SUCCESS; 271 } 272 // 273 // Version has already be printed, so just return success 274 // 275 if (strcmp(argv[0], "--version") == 0) { 276 return STATUS_SUCCESS; 277 } 278 279 // 280 // If they specified -x xref guid/basename cross-reference files, process it. 281 // This will print the basename beside each file guid. To use it, specify 282 // -x xref_filename to processdsc, then use xref_filename as a parameter 283 // here. 284 // 285 while (argc > 0) { 286 if ((strcmp(argv[0], "-x") == 0) || (strcmp(argv[0], "--xref") == 0)) { 287 ParseGuidBaseNameFile (argv[1]); 288 printf("ParseGuidBaseNameFile: %s\n", argv[1]); 289 argc -= 2; 290 argv += 2; 291 continue; 292 } 293 if (strcmp(argv[0], "--offset") == 0) { 294 // 295 // Hex or decimal? 296 // 297 if ((argv[1][0] == '0') && (tolower ((int)argv[1][1]) == 'x')) { 298 if (sscanf (argv[1], "%x", &Offset) != 1) { 299 Error (NULL, 0, 1003, "Invalid option value", "Offset = %s", argv[1]); 300 return GetUtilityStatus (); 301 } 302 } else { 303 if (sscanf (argv[1], "%d", &Offset) != 1) { 304 Error (NULL, 0, 1003, "Invalid option value", "Offset = %s", argv[1]); 305 return GetUtilityStatus (); 306 } 307 // 308 // See if they said something like "64K" 309 // 310 if (tolower ((int)argv[1][strlen (argv[1]) - 1]) == 'k') { 311 Offset *= 1024; 312 } 313 } 314 315 argc -= 2; 316 argv += 2; 317 continue; 318 } 319 if ((stricmp (argv[0], "--hash") == 0)) { 320 if (EnableHash == TRUE) { 321 // 322 // --hash already given in the option, ignore this one 323 // 324 argc --; 325 argv ++; 326 continue; 327 } 328 EnableHash = TRUE; 329 OpenSslCommand = "openssl"; 330 OpenSslEnv = getenv("OPENSSL_PATH"); 331 if (OpenSslEnv == NULL) { 332 OpenSslPath = OpenSslCommand; 333 } else { 334 OpenSslPath = malloc(strlen(OpenSslEnv)+strlen(OpenSslCommand)+1); 335 if (OpenSslPath == NULL) { 336 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); 337 return GetUtilityStatus (); 338 } 339 CombinePath(OpenSslEnv, OpenSslCommand, OpenSslPath); 340 } 341 if (OpenSslPath == NULL){ 342 Error (NULL, 0, 3000, "Open SSL command not available. Please verify PATH or set OPENSSL_PATH.", NULL); 343 return GetUtilityStatus (); 344 } 345 argc --; 346 argv ++; 347 continue; 348 } 349 350 if ((stricmp (argv[0], "-v") == 0) || (stricmp (argv[0], "--verbose") == 0)) { 351 SetPrintLevel (VERBOSE_LOG_LEVEL); 352 argc --; 353 argv ++; 354 continue; 355 } 356 357 if ((stricmp (argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) { 358 SetPrintLevel (KEY_LOG_LEVEL); 359 argc --; 360 argv ++; 361 continue; 362 } 363 364 if ((stricmp (argv[0], "-d") == 0) || (stricmp (argv[0], "--debug") == 0)) { 365 Status = AsciiStringToUint64 (argv[1], FALSE, &LogLevel); 366 if (EFI_ERROR (Status)) { 367 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]); 368 return -1; 369 } 370 if (LogLevel > 9) { 371 Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0-9, current input level is %d", (int) LogLevel); 372 return -1; 373 } 374 SetPrintLevel (LogLevel); 375 DebugMsg (NULL, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv[1]); 376 argc -= 2; 377 argv += 2; 378 continue; 379 } 380 381 mUtilityFilename = argv[0]; 382 argc --; 383 argv ++; 384 } 385 386 // 387 // Open the file containing the FV 388 // 389 if (mUtilityFilename == NULL) { 390 Error (NULL, 0, 1001, "Missing option", "Input files are not specified"); 391 return GetUtilityStatus (); 392 } 393 InputFile = fopen (LongFilePath (mUtilityFilename), "rb"); 394 if (InputFile == NULL) { 395 Error (NULL, 0, 0001, "Error opening the input file", mUtilityFilename); 396 return GetUtilityStatus (); 397 } 398 // 399 // Skip over pad bytes if specified. This is used if they prepend 0xff 400 // data to the FV image binary. 401 // 402 if (Offset != 0) { 403 fseek (InputFile, Offset, SEEK_SET); 404 } 405 // 406 // Determine size of FV 407 // 408 Status = ReadHeader (InputFile, &FvSize, &ErasePolarity); 409 if (EFI_ERROR (Status)) { 410 Error (NULL, 0, 0003, "error parsing FV image", "%s Header is invalid", mUtilityFilename); 411 fclose (InputFile); 412 return GetUtilityStatus (); 413 } 414 // 415 // Allocate a buffer for the FV image 416 // 417 FvImage = malloc (FvSize); 418 if (FvImage == NULL) { 419 Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL); 420 fclose (InputFile); 421 return GetUtilityStatus (); 422 } 423 // 424 // Seek to the start of the image, then read the entire FV to the buffer 425 // 426 fseek (InputFile, Offset, SEEK_SET); 427 BytesRead = fread (FvImage, 1, FvSize, InputFile); 428 fclose (InputFile); 429 if ((unsigned int) BytesRead != FvSize) { 430 Error (NULL, 0, 0004, "error reading FvImage from", mUtilityFilename); 431 free (FvImage); 432 return GetUtilityStatus (); 433 } 434 435 LoadGuidedSectionToolsTxt (mUtilityFilename); 436 437 PrintFvInfo (FvImage, FALSE); 438 439 // 440 // Clean up 441 // 442 free (FvImage); 443 FreeGuidBaseNameList (); 444 return GetUtilityStatus (); 445 } 446 447 448 static 449 EFI_STATUS 450 PrintFvInfo ( 451 IN VOID *Fv, 452 IN BOOLEAN IsChildFv 453 ) 454 /*++ 455 456 Routine Description: 457 458 GC_TODO: Add function description 459 460 Arguments: 461 462 Fv - Firmware Volume to print information about 463 IsChildFv - Flag specifies whether the input FV is a child FV. 464 465 Returns: 466 467 EFI_STATUS 468 469 --*/ 470 { 471 EFI_STATUS Status; 472 UINTN NumberOfFiles; 473 BOOLEAN ErasePolarity; 474 UINTN FvSize; 475 EFI_FFS_FILE_HEADER *CurrentFile; 476 UINTN Key; 477 478 Status = FvBufGetSize (Fv, &FvSize); 479 480 NumberOfFiles = 0; 481 ErasePolarity = 482 (((EFI_FIRMWARE_VOLUME_HEADER*)Fv)->Attributes & EFI_FVB2_ERASE_POLARITY) ? 483 TRUE : FALSE; 484 485 // 486 // Get the first file 487 // 488 Key = 0; 489 Status = FvBufFindNextFile (Fv, &Key, (VOID **) &CurrentFile); 490 if (EFI_ERROR (Status)) { 491 Error (NULL, 0, 0003, "error parsing FV image", "cannot find the first file in the FV image"); 492 return GetUtilityStatus (); 493 } 494 // 495 // Display information about files found 496 // 497 while (CurrentFile != NULL) { 498 // 499 // Increment the number of files counter 500 // 501 NumberOfFiles++; 502 503 // 504 // Display info about this file 505 // 506 Status = PrintFileInfo (Fv, CurrentFile, ErasePolarity); 507 if (EFI_ERROR (Status)) { 508 Error (NULL, 0, 0003, "error parsing FV image", "failed to parse a file in the FV"); 509 return GetUtilityStatus (); 510 } 511 // 512 // Get the next file 513 // 514 Status = FvBufFindNextFile (Fv, &Key, (VOID **) &CurrentFile); 515 if (Status == EFI_NOT_FOUND) { 516 CurrentFile = NULL; 517 } else if (EFI_ERROR (Status)) { 518 Error (NULL, 0, 0003, "error parsing FV image", "cannot find the next file in the FV image"); 519 return GetUtilityStatus (); 520 } 521 } 522 523 if (IsChildFv) { 524 printf ("There are a total of %d files in the child FV\n", (int) NumberOfFiles); 525 } else { 526 printf ("There are a total of %d files in this FV\n", (int) NumberOfFiles); 527 } 528 529 return EFI_SUCCESS; 530 } 531 532 UINT32 533 GetOccupiedSize ( 534 IN UINT32 ActualSize, 535 IN UINT32 Alignment 536 ) 537 /*++ 538 539 Routine Description: 540 541 This function returns the next larger size that meets the alignment 542 requirement specified. 543 544 Arguments: 545 546 ActualSize The size. 547 Alignment The desired alignment. 548 549 Returns: 550 551 EFI_SUCCESS Function completed successfully. 552 EFI_ABORTED The function encountered an error. 553 554 --*/ 555 { 556 UINT32 OccupiedSize; 557 558 OccupiedSize = ActualSize; 559 while ((OccupiedSize & (Alignment - 1)) != 0) { 560 OccupiedSize++; 561 } 562 563 return OccupiedSize; 564 } 565 566 static 567 CHAR8 * 568 SectionNameToStr ( 569 IN EFI_SECTION_TYPE Type 570 ) 571 /*++ 572 573 Routine Description: 574 575 Converts EFI Section names to Strings 576 577 Arguments: 578 579 Type - The EFI Section type 580 581 Returns: 582 583 CHAR8* - Pointer to the String containing the section name. 584 585 --*/ 586 { 587 CHAR8 *SectionStr; 588 CHAR8 *SectionTypeStringTable[] = { 589 // 590 // 0X00 591 // 592 "EFI_SECTION_ALL", 593 // 594 // 0x01 595 // 596 "EFI_SECTION_COMPRESSION", 597 // 598 // 0x02 599 // 600 "EFI_SECTION_GUID_DEFINED", 601 // 602 // 0x03 603 // 604 "Unknown section type - Reserved 0x03", 605 // 606 // 0x04 607 // 608 "Unknown section type - Reserved 0x04", 609 // 610 // 0x05 611 // 612 "Unknown section type - Reserved 0x05", 613 // 614 // 0x06 615 // 616 "Unknown section type - Reserved 0x06", 617 // 618 // 0x07 619 // 620 "Unknown section type - Reserved 0x07", 621 // 622 // 0x08 623 // 624 "Unknown section type - Reserved 0x08", 625 // 626 // 0x09 627 // 628 "Unknown section type - Reserved 0x09", 629 // 630 // 0x0A 631 // 632 "Unknown section type - Reserved 0x0A", 633 // 634 // 0x0B 635 // 636 "Unknown section type - Reserved 0x0B", 637 // 638 // 0x0C 639 // 640 "Unknown section type - Reserved 0x0C", 641 // 642 // 0x0D 643 // 644 "Unknown section type - Reserved 0x0D", 645 // 646 // 0x0E 647 // 648 "Unknown section type - Reserved 0x0E", 649 // 650 // 0x0F 651 // 652 "Unknown section type - Reserved 0x0E", 653 // 654 // 0x10 655 // 656 "EFI_SECTION_PE32", 657 // 658 // 0x11 659 // 660 "EFI_SECTION_PIC", 661 // 662 // 0x12 663 // 664 "EFI_SECTION_TE", 665 // 666 // 0x13 667 // 668 "EFI_SECTION_DXE_DEPEX", 669 // 670 // 0x14 671 // 672 "EFI_SECTION_VERSION", 673 // 674 // 0x15 675 // 676 "EFI_SECTION_USER_INTERFACE", 677 // 678 // 0x16 679 // 680 "EFI_SECTION_COMPATIBILITY16", 681 // 682 // 0x17 683 // 684 "EFI_SECTION_FIRMWARE_VOLUME_IMAGE ", 685 // 686 // 0x18 687 // 688 "EFI_SECTION_FREEFORM_SUBTYPE_GUID ", 689 // 690 // 0x19 691 // 692 "EFI_SECTION_RAW", 693 // 694 // 0x1A 695 // 696 "Unknown section type - 0x1A", 697 // 698 // 0x1B 699 // 700 "EFI_SECTION_PEI_DEPEX", 701 // 702 // 0x1C 703 // 704 "EFI_SECTION_SMM_DEPEX", 705 // 706 // 0x1C+ 707 // 708 "Unknown section type - Reserved - beyond last defined section" 709 }; 710 711 if (Type > EFI_SECTION_LAST_SECTION_TYPE) { 712 Type = EFI_SECTION_LAST_SECTION_TYPE + 1; 713 } 714 715 SectionStr = malloc (100); 716 if (SectionStr == NULL) { 717 printf ("Error: Out of memory resources.\n"); 718 return SectionStr; 719 } 720 strcpy (SectionStr, SectionTypeStringTable[Type]); 721 return SectionStr; 722 } 723 724 STATIC 725 EFI_STATUS 726 ReadHeader ( 727 IN FILE *InputFile, 728 OUT UINT32 *FvSize, 729 OUT BOOLEAN *ErasePolarity 730 ) 731 /*++ 732 733 Routine Description: 734 735 This function determines the size of the FV and the erase polarity. The 736 erase polarity is the FALSE value for file state. 737 738 Arguments: 739 740 InputFile The file that contains the FV image. 741 FvSize The size of the FV. 742 ErasePolarity The FV erase polarity. 743 744 Returns: 745 746 EFI_SUCCESS Function completed successfully. 747 EFI_INVALID_PARAMETER A required parameter was NULL or is out of range. 748 EFI_ABORTED The function encountered an error. 749 750 --*/ 751 { 752 EFI_FIRMWARE_VOLUME_HEADER VolumeHeader; 753 EFI_FV_BLOCK_MAP_ENTRY BlockMap; 754 UINTN Signature[2]; 755 UINTN BytesRead; 756 UINT32 Size; 757 758 BytesRead = 0; 759 Size = 0; 760 // 761 // Check input parameters 762 // 763 if (InputFile == NULL || FvSize == NULL || ErasePolarity == NULL) { 764 Error (__FILE__, __LINE__, 0, "application error", "invalid parameter to function"); 765 return EFI_INVALID_PARAMETER; 766 } 767 // 768 // Read the header 769 // 770 fread (&VolumeHeader, sizeof (EFI_FIRMWARE_VOLUME_HEADER) - sizeof (EFI_FV_BLOCK_MAP_ENTRY), 1, InputFile); 771 BytesRead = sizeof (EFI_FIRMWARE_VOLUME_HEADER) - sizeof (EFI_FV_BLOCK_MAP_ENTRY); 772 Signature[0] = VolumeHeader.Signature; 773 Signature[1] = 0; 774 775 // 776 // Print FV header information 777 // 778 printf ("Signature: %s (%X)\n", (char *) Signature, (unsigned) VolumeHeader.Signature); 779 printf ("Attributes: %X\n", (unsigned) VolumeHeader.Attributes); 780 781 if (VolumeHeader.Attributes & EFI_FVB2_READ_DISABLED_CAP) { 782 printf (" EFI_FVB2_READ_DISABLED_CAP\n"); 783 } 784 785 if (VolumeHeader.Attributes & EFI_FVB2_READ_ENABLED_CAP) { 786 printf (" EFI_FVB2_READ_ENABLED_CAP\n"); 787 } 788 789 if (VolumeHeader.Attributes & EFI_FVB2_READ_STATUS) { 790 printf (" EFI_FVB2_READ_STATUS\n"); 791 } 792 793 if (VolumeHeader.Attributes & EFI_FVB2_WRITE_DISABLED_CAP) { 794 printf (" EFI_FVB2_WRITE_DISABLED_CAP\n"); 795 } 796 797 if (VolumeHeader.Attributes & EFI_FVB2_WRITE_ENABLED_CAP) { 798 printf (" EFI_FVB2_WRITE_ENABLED_CAP\n"); 799 } 800 801 if (VolumeHeader.Attributes & EFI_FVB2_WRITE_STATUS) { 802 printf (" EFI_FVB2_WRITE_STATUS\n"); 803 } 804 805 if (VolumeHeader.Attributes & EFI_FVB2_LOCK_CAP) { 806 printf (" EFI_FVB2_LOCK_CAP\n"); 807 } 808 809 if (VolumeHeader.Attributes & EFI_FVB2_LOCK_STATUS) { 810 printf (" EFI_FVB2_LOCK_STATUS\n"); 811 } 812 813 if (VolumeHeader.Attributes & EFI_FVB2_STICKY_WRITE) { 814 printf (" EFI_FVB2_STICKY_WRITE\n"); 815 } 816 817 if (VolumeHeader.Attributes & EFI_FVB2_MEMORY_MAPPED) { 818 printf (" EFI_FVB2_MEMORY_MAPPED\n"); 819 } 820 821 if (VolumeHeader.Attributes & EFI_FVB2_ERASE_POLARITY) { 822 printf (" EFI_FVB2_ERASE_POLARITY\n"); 823 *ErasePolarity = TRUE; 824 } 825 826 #if (PI_SPECIFICATION_VERSION < 0x00010000) 827 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT) { 828 printf (" EFI_FVB2_ALIGNMENT\n"); 829 } 830 831 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_2) { 832 printf (" EFI_FVB2_ALIGNMENT_2\n"); 833 } 834 835 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_4) { 836 printf (" EFI_FVB2_ALIGNMENT_4\n"); 837 } 838 839 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_8) { 840 printf (" EFI_FVB2_ALIGNMENT_8\n"); 841 } 842 843 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_16) { 844 printf (" EFI_FVB2_ALIGNMENT_16\n"); 845 } 846 847 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_32) { 848 printf (" EFI_FVB2_ALIGNMENT_32\n"); 849 } 850 851 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_64) { 852 printf (" EFI_FVB2_ALIGNMENT_64\n"); 853 } 854 855 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_128) { 856 printf (" EFI_FVB2_ALIGNMENT_128\n"); 857 } 858 859 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_256) { 860 printf (" EFI_FVB2_ALIGNMENT_256\n"); 861 } 862 863 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_512) { 864 printf (" EFI_FVB2_ALIGNMENT_512\n"); 865 } 866 867 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_1K) { 868 printf (" EFI_FVB2_ALIGNMENT_1K\n"); 869 } 870 871 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_2K) { 872 printf (" EFI_FVB2_ALIGNMENT_2K\n"); 873 } 874 875 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_4K) { 876 printf (" EFI_FVB2_ALIGNMENT_4K\n"); 877 } 878 879 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_8K) { 880 printf (" EFI_FVB2_ALIGNMENT_8K\n"); 881 } 882 883 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_16K) { 884 printf (" EFI_FVB2_ALIGNMENT_16K\n"); 885 } 886 887 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_32K) { 888 printf (" EFI_FVB2_ALIGNMENT_32K\n"); 889 } 890 891 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_64K) { 892 printf (" EFI_FVB2_ALIGNMENT_64K\n"); 893 } 894 895 #else 896 897 if (VolumeHeader.Attributes & EFI_FVB2_READ_LOCK_CAP) { 898 printf (" EFI_FVB2_READ_LOCK_CAP\n"); 899 } 900 901 if (VolumeHeader.Attributes & EFI_FVB2_READ_LOCK_STATUS) { 902 printf (" EFI_FVB2_READ_LOCK_STATUS\n"); 903 } 904 905 if (VolumeHeader.Attributes & EFI_FVB2_WRITE_LOCK_CAP) { 906 printf (" EFI_FVB2_WRITE_LOCK_CAP\n"); 907 } 908 909 if (VolumeHeader.Attributes & EFI_FVB2_WRITE_LOCK_STATUS) { 910 printf (" EFI_FVB2_WRITE_LOCK_STATUS\n"); 911 } 912 913 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_1) { 914 printf (" EFI_FVB2_ALIGNMENT_1\n"); 915 } 916 917 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_2) { 918 printf (" EFI_FVB2_ALIGNMENT_2\n"); 919 } 920 921 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_4) { 922 printf (" EFI_FVB2_ALIGNMENT_4\n"); 923 } 924 925 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_8) { 926 printf (" EFI_FVB2_ALIGNMENT_8\n"); 927 } 928 929 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_16) { 930 printf (" EFI_FVB2_ALIGNMENT_16\n"); 931 } 932 933 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_32) { 934 printf (" EFI_FVB2_ALIGNMENT_32\n"); 935 } 936 937 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_64) { 938 printf (" EFI_FVB2_ALIGNMENT_64\n"); 939 } 940 941 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_128) { 942 printf (" EFI_FVB2_ALIGNMENT_128\n"); 943 } 944 945 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_256) { 946 printf (" EFI_FVB2_ALIGNMENT_256\n"); 947 } 948 949 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_512) { 950 printf (" EFI_FVB2_ALIGNMENT_512\n"); 951 } 952 953 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_1K) { 954 printf (" EFI_FVB2_ALIGNMENT_1K\n"); 955 } 956 957 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_2K) { 958 printf (" EFI_FVB2_ALIGNMENT_2K\n"); 959 } 960 961 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_4K) { 962 printf (" EFI_FVB2_ALIGNMENT_4K\n"); 963 } 964 965 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_8K) { 966 printf (" EFI_FVB2_ALIGNMENT_8K\n"); 967 } 968 969 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_16K) { 970 printf (" EFI_FVB2_ALIGNMENT_16K\n"); 971 } 972 973 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_32K) { 974 printf (" EFI_FVB2_ALIGNMENT_32K\n"); 975 } 976 977 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_64K) { 978 printf (" EFI_FVB2_ALIGNMENT_64K\n"); 979 } 980 981 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_128K) { 982 printf (" EFI_FVB2_ALIGNMENT_128K\n"); 983 } 984 985 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_256K) { 986 printf (" EFI_FVB2_ALIGNMENT_256K\n"); 987 } 988 989 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_512K) { 990 printf (" EFI_FVB2_ALIGNMENT_512K\n"); 991 } 992 993 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_1M) { 994 printf (" EFI_FVB2_ALIGNMENT_1M\n"); 995 } 996 997 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_2M) { 998 printf (" EFI_FVB2_ALIGNMENT_2M\n"); 999 } 1000 1001 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_4M) { 1002 printf (" EFI_FVB2_ALIGNMENT_4M\n"); 1003 } 1004 1005 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_8M) { 1006 printf (" EFI_FVB2_ALIGNMENT_8M\n"); 1007 } 1008 1009 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_16M) { 1010 printf (" EFI_FVB2_ALIGNMENT_16M\n"); 1011 } 1012 1013 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_32M) { 1014 printf (" EFI_FVB2_ALIGNMENT_32M\n"); 1015 } 1016 1017 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_64M) { 1018 printf (" EFI_FVB2_ALIGNMENT_64M\n"); 1019 } 1020 1021 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_128M) { 1022 printf (" EFI_FVB2_ALIGNMENT_128M\n"); 1023 } 1024 1025 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_64M) { 1026 printf (" EFI_FVB2_ALIGNMENT_64M\n"); 1027 } 1028 1029 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_128M) { 1030 printf (" EFI_FVB2_ALIGNMENT_128M\n"); 1031 } 1032 1033 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_256M) { 1034 printf (" EFI_FVB2_ALIGNMENT_256M\n"); 1035 } 1036 1037 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_512M) { 1038 printf (" EFI_FVB2_ALIGNMENT_512M\n"); 1039 } 1040 1041 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_1G) { 1042 printf (" EFI_FVB2_ALIGNMENT_1G\n"); 1043 } 1044 1045 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_2G) { 1046 printf (" EFI_FVB2_ALIGNMENT_2G\n"); 1047 } 1048 1049 #endif 1050 printf ("Header Length: 0x%08X\n", VolumeHeader.HeaderLength); 1051 printf ("File System ID: "); 1052 PrintGuid (&VolumeHeader.FileSystemGuid); 1053 // 1054 // printf ("\n"); 1055 // 1056 printf ("Revision: 0x%04X\n", VolumeHeader.Revision); 1057 1058 do { 1059 fread (&BlockMap, sizeof (EFI_FV_BLOCK_MAP_ENTRY), 1, InputFile); 1060 BytesRead += sizeof (EFI_FV_BLOCK_MAP_ENTRY); 1061 1062 if (BlockMap.NumBlocks != 0) { 1063 printf ("Number of Blocks: 0x%08X\n", (unsigned) BlockMap.NumBlocks); 1064 printf ("Block Length: 0x%08X\n", (unsigned) BlockMap.Length); 1065 Size += BlockMap.NumBlocks * BlockMap.Length; 1066 } 1067 1068 } while (!(BlockMap.NumBlocks == 0 && BlockMap.Length == 0)); 1069 1070 if (BytesRead != VolumeHeader.HeaderLength) { 1071 printf ("ERROR: Header length not consistent with Block Maps!\n"); 1072 return EFI_ABORTED; 1073 } 1074 1075 if (VolumeHeader.FvLength != Size) { 1076 printf ("ERROR: Volume Size not consistant with Block Maps!\n"); 1077 return EFI_ABORTED; 1078 } 1079 1080 printf ("Total Volume Size: 0x%08X\n", (unsigned) Size); 1081 1082 *FvSize = Size; 1083 1084 // 1085 // rewind (InputFile); 1086 // 1087 return EFI_SUCCESS; 1088 } 1089 1090 STATIC 1091 EFI_STATUS 1092 PrintFileInfo ( 1093 EFI_FIRMWARE_VOLUME_HEADER *FvImage, 1094 EFI_FFS_FILE_HEADER *FileHeader, 1095 BOOLEAN ErasePolarity 1096 ) 1097 /*++ 1098 1099 Routine Description: 1100 1101 GC_TODO: Add function description 1102 1103 Arguments: 1104 1105 FvImage - GC_TODO: add argument description 1106 FileHeader - GC_TODO: add argument description 1107 ErasePolarity - GC_TODO: add argument description 1108 1109 Returns: 1110 1111 EFI_SUCCESS - GC_TODO: Add description for return value 1112 EFI_ABORTED - GC_TODO: Add description for return value 1113 1114 --*/ 1115 { 1116 UINT32 FileLength; 1117 UINT8 FileState; 1118 UINT8 Checksum; 1119 EFI_FFS_FILE_HEADER2 BlankHeader; 1120 EFI_STATUS Status; 1121 UINT8 GuidBuffer[PRINTED_GUID_BUFFER_SIZE]; 1122 UINT32 HeaderSize; 1123 #if (PI_SPECIFICATION_VERSION < 0x00010000) 1124 UINT16 *Tail; 1125 #endif 1126 // 1127 // Check if we have free space 1128 // 1129 HeaderSize = FvBufGetFfsHeaderSize(FileHeader); 1130 if (ErasePolarity) { 1131 memset (&BlankHeader, -1, HeaderSize); 1132 } else { 1133 memset (&BlankHeader, 0, HeaderSize); 1134 } 1135 1136 if (memcmp (&BlankHeader, FileHeader, HeaderSize) == 0) { 1137 return EFI_SUCCESS; 1138 } 1139 // 1140 // Print file information. 1141 // 1142 printf ("============================================================\n"); 1143 1144 printf ("File Name: "); 1145 PrintGuidToBuffer (&FileHeader->Name, GuidBuffer, sizeof (GuidBuffer), TRUE); 1146 printf ("%s ", GuidBuffer); 1147 PrintGuidName (GuidBuffer); 1148 printf ("\n"); 1149 1150 // 1151 // PrintGuid (&FileHeader->Name); 1152 // printf ("\n"); 1153 // 1154 FileLength = FvBufGetFfsFileSize (FileHeader); 1155 printf ("File Offset: 0x%08X\n", (unsigned) ((UINTN) FileHeader - (UINTN) FvImage)); 1156 printf ("File Length: 0x%08X\n", (unsigned) FileLength); 1157 printf ("File Attributes: 0x%02X\n", FileHeader->Attributes); 1158 printf ("File State: 0x%02X\n", FileHeader->State); 1159 1160 // 1161 // Print file state 1162 // 1163 FileState = GetFileState (ErasePolarity, FileHeader); 1164 1165 switch (FileState) { 1166 1167 case EFI_FILE_HEADER_CONSTRUCTION: 1168 printf (" EFI_FILE_HEADER_CONSTRUCTION\n"); 1169 return EFI_SUCCESS; 1170 1171 case EFI_FILE_HEADER_INVALID: 1172 printf (" EFI_FILE_HEADER_INVALID\n"); 1173 return EFI_SUCCESS; 1174 1175 case EFI_FILE_HEADER_VALID: 1176 printf (" EFI_FILE_HEADER_VALID\n"); 1177 Checksum = CalculateSum8 ((UINT8 *) FileHeader, HeaderSize); 1178 Checksum = (UINT8) (Checksum - FileHeader->IntegrityCheck.Checksum.File); 1179 Checksum = (UINT8) (Checksum - FileHeader->State); 1180 if (Checksum != 0) { 1181 printf ("ERROR: Header checksum invalid.\n"); 1182 return EFI_ABORTED; 1183 } 1184 1185 return EFI_SUCCESS; 1186 1187 case EFI_FILE_DELETED: 1188 printf (" EFI_FILE_DELETED\n"); 1189 1190 case EFI_FILE_MARKED_FOR_UPDATE: 1191 printf (" EFI_FILE_MARKED_FOR_UPDATE\n"); 1192 1193 case EFI_FILE_DATA_VALID: 1194 printf (" EFI_FILE_DATA_VALID\n"); 1195 1196 // 1197 // Calculate header checksum 1198 // 1199 Checksum = CalculateSum8 ((UINT8 *) FileHeader, HeaderSize); 1200 Checksum = (UINT8) (Checksum - FileHeader->IntegrityCheck.Checksum.File); 1201 Checksum = (UINT8) (Checksum - FileHeader->State); 1202 if (Checksum != 0) { 1203 Error (NULL, 0, 0003, "error parsing FFS file", "FFS file with Guid %s has invalid header checksum", GuidBuffer); 1204 return EFI_ABORTED; 1205 } 1206 1207 FileLength = FvBufGetFfsFileSize (FileHeader); 1208 1209 if (FileHeader->Attributes & FFS_ATTRIB_CHECKSUM) { 1210 // 1211 // Calculate file checksum 1212 // 1213 Checksum = CalculateSum8 ((UINT8 *)FileHeader + HeaderSize, FileLength - HeaderSize); 1214 Checksum = Checksum + FileHeader->IntegrityCheck.Checksum.File; 1215 if (Checksum != 0) { 1216 Error (NULL, 0, 0003, "error parsing FFS file", "FFS file with Guid %s has invalid file checksum", GuidBuffer); 1217 return EFI_ABORTED; 1218 } 1219 } else { 1220 if (FileHeader->IntegrityCheck.Checksum.File != FFS_FIXED_CHECKSUM) { 1221 Error (NULL, 0, 0003, "error parsing FFS file", "FFS file with Guid %s has invalid header checksum -- not set to fixed value of 0xAA", GuidBuffer); 1222 return EFI_ABORTED; 1223 } 1224 } 1225 #if (PI_SPECIFICATION_VERSION < 0x00010000) 1226 // 1227 // Verify tail if present 1228 // 1229 if (FileHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT) { 1230 // 1231 // Verify tail is complement of integrity check field in the header. 1232 // 1233 Tail = (UINT16 *) ((UINTN) FileHeader + GetLength (FileHeader->Size) - sizeof (EFI_FFS_INTEGRITY_CHECK)); 1234 if (FileHeader->IntegrityCheck.TailReference != (UINT16)~(*Tail)) { 1235 Error (NULL, 0, 0003, "error parsing FFS file", \ 1236 "FFS file with Guid %s failed in the integrity check, tail is not the complement of the header field", GuidBuffer); 1237 return EFI_ABORTED; 1238 } 1239 } 1240 #endif 1241 break; 1242 1243 default: 1244 Error (NULL, 0, 0003, "error parsing FFS file", "FFS file with Guid %s has the invalid/unrecognized file state bits", GuidBuffer); 1245 return EFI_ABORTED; 1246 } 1247 1248 printf ("File Type: 0x%02X ", FileHeader->Type); 1249 1250 switch (FileHeader->Type) { 1251 1252 case EFI_FV_FILETYPE_RAW: 1253 printf ("EFI_FV_FILETYPE_RAW\n"); 1254 break; 1255 1256 case EFI_FV_FILETYPE_FREEFORM: 1257 printf ("EFI_FV_FILETYPE_FREEFORM\n"); 1258 break; 1259 1260 case EFI_FV_FILETYPE_SECURITY_CORE: 1261 printf ("EFI_FV_FILETYPE_SECURITY_CORE\n"); 1262 break; 1263 1264 case EFI_FV_FILETYPE_PEI_CORE: 1265 printf ("EFI_FV_FILETYPE_PEI_CORE\n"); 1266 break; 1267 1268 case EFI_FV_FILETYPE_DXE_CORE: 1269 printf ("EFI_FV_FILETYPE_DXE_CORE\n"); 1270 break; 1271 1272 case EFI_FV_FILETYPE_PEIM: 1273 printf ("EFI_FV_FILETYPE_PEIM\n"); 1274 break; 1275 1276 case EFI_FV_FILETYPE_DRIVER: 1277 printf ("EFI_FV_FILETYPE_DRIVER\n"); 1278 break; 1279 1280 case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER: 1281 printf ("EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER\n"); 1282 break; 1283 1284 case EFI_FV_FILETYPE_APPLICATION: 1285 printf ("EFI_FV_FILETYPE_APPLICATION\n"); 1286 break; 1287 1288 case EFI_FV_FILETYPE_SMM: 1289 printf ("EFI_FV_FILETYPE_SMM\n"); 1290 break; 1291 1292 case EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE: 1293 printf ("EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE\n"); 1294 break; 1295 1296 case EFI_FV_FILETYPE_COMBINED_SMM_DXE: 1297 printf ("EFI_FV_FILETYPE_COMBINED_SMM_DXE\n"); 1298 break; 1299 1300 case EFI_FV_FILETYPE_SMM_CORE: 1301 printf ("EFI_FV_FILETYPE_SMM_CORE\n"); 1302 break; 1303 1304 case EFI_FV_FILETYPE_FFS_PAD: 1305 printf ("EFI_FV_FILETYPE_FFS_PAD\n"); 1306 break; 1307 1308 default: 1309 printf ("\nERROR: Unrecognized file type %X.\n", FileHeader->Type); 1310 return EFI_ABORTED; 1311 break; 1312 } 1313 1314 switch (FileHeader->Type) { 1315 1316 case EFI_FV_FILETYPE_ALL: 1317 case EFI_FV_FILETYPE_RAW: 1318 case EFI_FV_FILETYPE_FFS_PAD: 1319 break; 1320 1321 default: 1322 // 1323 // All other files have sections 1324 // 1325 Status = ParseSection ( 1326 (UINT8 *) ((UINTN) FileHeader + HeaderSize), 1327 FvBufGetFfsFileSize (FileHeader) - HeaderSize 1328 ); 1329 if (EFI_ERROR (Status)) { 1330 // 1331 // printf ("ERROR: Parsing the FFS file.\n"); 1332 // 1333 return EFI_ABORTED; 1334 } 1335 break; 1336 } 1337 1338 return EFI_SUCCESS; 1339 } 1340 1341 EFI_STATUS 1342 RebaseImageRead ( 1343 IN VOID *FileHandle, 1344 IN UINTN FileOffset, 1345 IN OUT UINT32 *ReadSize, 1346 OUT VOID *Buffer 1347 ) 1348 /*++ 1349 1350 Routine Description: 1351 1352 Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file 1353 1354 Arguments: 1355 1356 FileHandle - The handle to the PE/COFF file 1357 1358 FileOffset - The offset, in bytes, into the file to read 1359 1360 ReadSize - The number of bytes to read from the file starting at FileOffset 1361 1362 Buffer - A pointer to the buffer to read the data into. 1363 1364 Returns: 1365 1366 EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset 1367 1368 --*/ 1369 { 1370 CHAR8 *Destination8; 1371 CHAR8 *Source8; 1372 UINT32 Length; 1373 1374 Destination8 = Buffer; 1375 Source8 = (CHAR8 *) ((UINTN) FileHandle + FileOffset); 1376 Length = *ReadSize; 1377 while (Length--) { 1378 *(Destination8++) = *(Source8++); 1379 } 1380 1381 return EFI_SUCCESS; 1382 } 1383 1384 EFI_STATUS 1385 SetAddressToSectionHeader ( 1386 IN CHAR8 *FileName, 1387 IN OUT UINT8 *FileBuffer, 1388 IN UINT64 NewPe32BaseAddress 1389 ) 1390 /*++ 1391 1392 Routine Description: 1393 1394 Set new base address into the section header of PeImage 1395 1396 Arguments: 1397 1398 FileName - Name of file 1399 FileBuffer - Pointer to PeImage. 1400 NewPe32BaseAddress - New Base Address for PE image. 1401 1402 Returns: 1403 1404 EFI_SUCCESS Set new base address into this image successfully. 1405 1406 --*/ 1407 { 1408 EFI_STATUS Status; 1409 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; 1410 UINTN Index; 1411 EFI_IMAGE_OPTIONAL_HEADER_UNION *ImgHdr; 1412 EFI_IMAGE_SECTION_HEADER *SectionHeader; 1413 1414 // 1415 // Initialize context 1416 // 1417 memset (&ImageContext, 0, sizeof (ImageContext)); 1418 ImageContext.Handle = (VOID *) FileBuffer; 1419 ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) RebaseImageRead; 1420 Status = PeCoffLoaderGetImageInfo (&ImageContext); 1421 if (EFI_ERROR (Status)) { 1422 Error (NULL, 0, 3000, "Invalid", "The input PeImage %s is not valid", FileName); 1423 return Status; 1424 } 1425 1426 if (ImageContext.RelocationsStripped) { 1427 Error (NULL, 0, 3000, "Invalid", "The input PeImage %s has no relocation to be fixed up", FileName); 1428 return Status; 1429 } 1430 1431 // 1432 // Get PeHeader pointer 1433 // 1434 ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer + ImageContext.PeCoffHeaderOffset); 1435 1436 // 1437 // Get section header list 1438 // 1439 SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ( 1440 (UINTN) ImgHdr + 1441 sizeof (UINT32) + 1442 sizeof (EFI_IMAGE_FILE_HEADER) + 1443 ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader 1444 ); 1445 1446 // 1447 // Set base address into the first section header that doesn't point to code section. 1448 // 1449 for (Index = 0; Index < ImgHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) { 1450 if ((SectionHeader->Characteristics & EFI_IMAGE_SCN_CNT_CODE) == 0) { 1451 *(UINT64 *) &SectionHeader->PointerToRelocations = NewPe32BaseAddress; 1452 break; 1453 } 1454 } 1455 1456 // 1457 // BaseAddress is set to section header. 1458 // 1459 return EFI_SUCCESS; 1460 } 1461 1462 EFI_STATUS 1463 RebaseImage ( 1464 IN CHAR8 *FileName, 1465 IN OUT UINT8 *FileBuffer, 1466 IN UINT64 NewPe32BaseAddress 1467 ) 1468 /*++ 1469 1470 Routine Description: 1471 1472 Set new base address into PeImage, and fix up PeImage based on new address. 1473 1474 Arguments: 1475 1476 FileName - Name of file 1477 FileBuffer - Pointer to PeImage. 1478 NewPe32BaseAddress - New Base Address for PE image. 1479 1480 Returns: 1481 1482 EFI_INVALID_PARAMETER - BaseAddress is not valid. 1483 EFI_SUCCESS - Update PeImage is correctly. 1484 1485 --*/ 1486 { 1487 EFI_STATUS Status; 1488 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; 1489 UINTN Index; 1490 EFI_IMAGE_OPTIONAL_HEADER_UNION *ImgHdr; 1491 UINT8 *MemoryImagePointer; 1492 EFI_IMAGE_SECTION_HEADER *SectionHeader; 1493 1494 // 1495 // Initialize context 1496 // 1497 memset (&ImageContext, 0, sizeof (ImageContext)); 1498 ImageContext.Handle = (VOID *) FileBuffer; 1499 ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) RebaseImageRead; 1500 Status = PeCoffLoaderGetImageInfo (&ImageContext); 1501 if (EFI_ERROR (Status)) { 1502 Error (NULL, 0, 3000, "Invalid", "The input PeImage %s is not valid", FileName); 1503 return Status; 1504 } 1505 1506 if (ImageContext.RelocationsStripped) { 1507 Error (NULL, 0, 3000, "Invalid", "The input PeImage %s has no relocation to be fixed up", FileName); 1508 return Status; 1509 } 1510 1511 // 1512 // Get PeHeader pointer 1513 // 1514 ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer + ImageContext.PeCoffHeaderOffset); 1515 1516 // 1517 // Load and Relocate Image Data 1518 // 1519 MemoryImagePointer = (UINT8 *) malloc ((UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment); 1520 if (MemoryImagePointer == NULL) { 1521 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated on rebase of %s", FileName); 1522 return EFI_OUT_OF_RESOURCES; 1523 } 1524 memset ((VOID *) MemoryImagePointer, 0, (UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment); 1525 ImageContext.ImageAddress = ((UINTN) MemoryImagePointer + ImageContext.SectionAlignment - 1) & (~((INT64)ImageContext.SectionAlignment - 1)); 1526 1527 Status = PeCoffLoaderLoadImage (&ImageContext); 1528 if (EFI_ERROR (Status)) { 1529 Error (NULL, 0, 3000, "Invalid", "LocateImage() call failed on rebase of %s", FileName); 1530 free ((VOID *) MemoryImagePointer); 1531 return Status; 1532 } 1533 1534 ImageContext.DestinationAddress = NewPe32BaseAddress; 1535 Status = PeCoffLoaderRelocateImage (&ImageContext); 1536 if (EFI_ERROR (Status)) { 1537 Error (NULL, 0, 3000, "Invalid", "RelocateImage() call failed on rebase of %s", FileName); 1538 free ((VOID *) MemoryImagePointer); 1539 return Status; 1540 } 1541 1542 // 1543 // Copy Relocated data to raw image file. 1544 // 1545 SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ( 1546 (UINTN) ImgHdr + 1547 sizeof (UINT32) + 1548 sizeof (EFI_IMAGE_FILE_HEADER) + 1549 ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader 1550 ); 1551 1552 for (Index = 0; Index < ImgHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) { 1553 CopyMem ( 1554 FileBuffer + SectionHeader->PointerToRawData, 1555 (VOID*) (UINTN) (ImageContext.ImageAddress + SectionHeader->VirtualAddress), 1556 SectionHeader->SizeOfRawData 1557 ); 1558 } 1559 1560 free ((VOID *) MemoryImagePointer); 1561 1562 // 1563 // Update Image Base Address 1564 // 1565 if ((ImgHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) && (ImgHdr->Pe32.FileHeader.Machine != IMAGE_FILE_MACHINE_IA64)) { 1566 ImgHdr->Pe32.OptionalHeader.ImageBase = (UINT32) NewPe32BaseAddress; 1567 } else if (ImgHdr->Pe32Plus.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) { 1568 ImgHdr->Pe32Plus.OptionalHeader.ImageBase = NewPe32BaseAddress; 1569 } else { 1570 Error (NULL, 0, 3000, "Invalid", "unknown PE magic signature %X in PE32 image %s", 1571 ImgHdr->Pe32.OptionalHeader.Magic, 1572 FileName 1573 ); 1574 return EFI_ABORTED; 1575 } 1576 1577 // 1578 // Set new base address into section header 1579 // 1580 Status = SetAddressToSectionHeader (FileName, FileBuffer, NewPe32BaseAddress); 1581 1582 return Status; 1583 } 1584 1585 EFI_STATUS 1586 CombinePath ( 1587 IN CHAR8* DefaultPath, 1588 IN CHAR8* AppendPath, 1589 OUT CHAR8* NewPath 1590 ) 1591 { 1592 UINT32 DefaultPathLen; 1593 DefaultPathLen = strlen(DefaultPath); 1594 strcpy(NewPath, DefaultPath); 1595 UINT64 Index = 0; 1596 for (; Index < DefaultPathLen; Index ++) { 1597 if (NewPath[Index] == '\\' || NewPath[Index] == '/') { 1598 if (NewPath[Index + 1] != '\0') { 1599 NewPath[Index] = '/'; 1600 } 1601 } 1602 } 1603 if (NewPath[Index -1] != '/') { 1604 NewPath[Index] = '/'; 1605 NewPath[Index + 1] = '\0'; 1606 } 1607 strcat(NewPath, AppendPath); 1608 return EFI_SUCCESS; 1609 } 1610 1611 EFI_STATUS 1612 ParseSection ( 1613 IN UINT8 *SectionBuffer, 1614 IN UINT32 BufferLength 1615 ) 1616 /*++ 1617 1618 Routine Description: 1619 1620 Parses EFI Sections 1621 1622 Arguments: 1623 1624 SectionBuffer - Buffer containing the section to parse. 1625 BufferLength - Length of SectionBuffer 1626 1627 Returns: 1628 1629 EFI_SECTION_ERROR - Problem with section parsing. 1630 (a) compression errors 1631 (b) unrecognized section 1632 EFI_UNSUPPORTED - Do not know how to parse the section. 1633 EFI_SUCCESS - Section successfully parsed. 1634 EFI_OUT_OF_RESOURCES - Memory allocation failed. 1635 1636 --*/ 1637 { 1638 EFI_SECTION_TYPE Type; 1639 UINT8 *Ptr; 1640 UINT32 SectionLength; 1641 UINT32 SectionHeaderLen; 1642 CHAR8 *SectionName; 1643 EFI_STATUS Status; 1644 UINT32 ParsedLength; 1645 UINT8 *CompressedBuffer; 1646 UINT32 CompressedLength; 1647 UINT8 *UncompressedBuffer; 1648 UINT32 UncompressedLength; 1649 UINT8 *ToolOutputBuffer; 1650 UINT32 ToolOutputLength; 1651 UINT8 CompressionType; 1652 UINT32 DstSize; 1653 UINT32 ScratchSize; 1654 UINT8 *ScratchBuffer; 1655 DECOMPRESS_FUNCTION DecompressFunction; 1656 GETINFO_FUNCTION GetInfoFunction; 1657 // CHAR16 *name; 1658 CHAR8 *ExtractionTool; 1659 CHAR8 *ToolInputFile; 1660 CHAR8 *ToolOutputFile; 1661 CHAR8 *SystemCommand; 1662 EFI_GUID *EfiGuid; 1663 UINT16 DataOffset; 1664 UINT16 Attributes; 1665 UINT32 RealHdrLen; 1666 CHAR8 *ToolInputFileName; 1667 CHAR8 *ToolOutputFileName; 1668 CHAR8 *UIFileName; 1669 1670 ParsedLength = 0; 1671 ToolInputFileName = NULL; 1672 ToolOutputFileName = NULL; 1673 1674 while (ParsedLength < BufferLength) { 1675 Ptr = SectionBuffer + ParsedLength; 1676 1677 SectionLength = GetLength (((EFI_COMMON_SECTION_HEADER *) Ptr)->Size); 1678 Type = ((EFI_COMMON_SECTION_HEADER *) Ptr)->Type; 1679 1680 // 1681 // This is sort of an odd check, but is necessary because FFS files are 1682 // padded to a QWORD boundary, meaning there is potentially a whole section 1683 // header worth of 0xFF bytes. 1684 // 1685 if (SectionLength == 0xffffff && Type == 0xff) { 1686 ParsedLength += 4; 1687 continue; 1688 } 1689 1690 // 1691 // Get real section file size 1692 // 1693 SectionLength = GetSectionFileLength ((EFI_COMMON_SECTION_HEADER *) Ptr); 1694 SectionHeaderLen = GetSectionHeaderLength((EFI_COMMON_SECTION_HEADER *)Ptr); 1695 1696 SectionName = SectionNameToStr (Type); 1697 if (SectionName != NULL) { 1698 printf ("------------------------------------------------------------\n"); 1699 printf (" Type: %s\n Size: 0x%08X\n", SectionName, (unsigned) SectionLength); 1700 free (SectionName); 1701 } 1702 1703 switch (Type) { 1704 case EFI_SECTION_RAW: 1705 case EFI_SECTION_PIC: 1706 case EFI_SECTION_TE: 1707 // default is no more information 1708 break; 1709 1710 case EFI_SECTION_PE32: 1711 if (EnableHash) { 1712 ToolInputFileName = "edk2Temp_InputEfi.tmp"; 1713 ToolOutputFileName = "edk2Temp_OutputHash.tmp"; 1714 RebaseImage(ToolInputFileName, (UINT8*)Ptr + SectionHeaderLen, 0); 1715 PutFileImage ( 1716 ToolInputFileName, 1717 (CHAR8*)Ptr + SectionHeaderLen, 1718 SectionLength - SectionHeaderLen 1719 ); 1720 1721 SystemCommand = malloc ( 1722 strlen (OPENSSL_COMMAND_FORMAT_STRING) + 1723 strlen (OpenSslPath) + 1724 strlen (ToolInputFileName) + 1725 strlen (ToolOutputFileName) + 1726 1 1727 ); 1728 if (SystemCommand == NULL) { 1729 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); 1730 return EFI_OUT_OF_RESOURCES; 1731 } 1732 sprintf ( 1733 SystemCommand, 1734 OPENSSL_COMMAND_FORMAT_STRING, 1735 OpenSslPath, 1736 ToolOutputFileName, 1737 ToolInputFileName 1738 ); 1739 1740 if (system (SystemCommand) != EFI_SUCCESS) { 1741 Error (NULL, 0, 3000, "Open SSL command not available. Please verify PATH or set OPENSSL_PATH.", NULL); 1742 } 1743 else { 1744 FILE *fp; 1745 CHAR8 *StrLine; 1746 CHAR8 *NewStr; 1747 UINT32 nFileLen; 1748 if((fp = fopen(ToolOutputFileName,"r")) == NULL) { 1749 Error (NULL, 0, 0004, "Hash the PE32 image failed.", NULL); 1750 } 1751 else { 1752 fseek(fp,0,SEEK_SET); 1753 fseek(fp,0,SEEK_END); 1754 nFileLen = ftell(fp); 1755 fseek(fp,0,SEEK_SET); 1756 StrLine = malloc(nFileLen); 1757 if (StrLine == NULL) { 1758 fclose(fp); 1759 free (SystemCommand); 1760 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); 1761 return EFI_OUT_OF_RESOURCES; 1762 } 1763 fgets(StrLine, nFileLen, fp); 1764 NewStr = strrchr (StrLine, '='); 1765 printf (" SHA1: %s\n", NewStr + 1); 1766 free (StrLine); 1767 fclose(fp); 1768 } 1769 } 1770 remove(ToolInputFileName); 1771 remove(ToolOutputFileName); 1772 free (SystemCommand); 1773 } 1774 break; 1775 1776 case EFI_SECTION_USER_INTERFACE: 1777 UIFileName = (CHAR8 *) malloc (UnicodeStrLen (((EFI_USER_INTERFACE_SECTION *) Ptr)->FileNameString) + 1); 1778 if (UIFileName == NULL) { 1779 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); 1780 return EFI_OUT_OF_RESOURCES; 1781 } 1782 Unicode2AsciiString (((EFI_USER_INTERFACE_SECTION *) Ptr)->FileNameString, UIFileName); 1783 printf (" String: %s\n", UIFileName); 1784 free (UIFileName); 1785 break; 1786 1787 case EFI_SECTION_FIRMWARE_VOLUME_IMAGE: 1788 Status = PrintFvInfo (Ptr + SectionHeaderLen, TRUE); 1789 if (EFI_ERROR (Status)) { 1790 Error (NULL, 0, 0003, "printing of FV section contents failed", NULL); 1791 return EFI_SECTION_ERROR; 1792 } 1793 break; 1794 1795 case EFI_SECTION_COMPATIBILITY16: 1796 case EFI_SECTION_FREEFORM_SUBTYPE_GUID: 1797 // 1798 // Section does not contain any further header information. 1799 // 1800 break; 1801 1802 case EFI_SECTION_PEI_DEPEX: 1803 case EFI_SECTION_DXE_DEPEX: 1804 case EFI_SECTION_SMM_DEPEX: 1805 DumpDepexSection (Ptr, SectionLength); 1806 break; 1807 1808 case EFI_SECTION_VERSION: 1809 printf (" Build Number: 0x%02X\n", *(UINT16 *)(Ptr + SectionHeaderLen)); 1810 printf (" Version Strg: %s\n", (char*) (Ptr + SectionHeaderLen + sizeof (UINT16))); 1811 break; 1812 1813 case EFI_SECTION_COMPRESSION: 1814 UncompressedBuffer = NULL; 1815 if (SectionHeaderLen == sizeof (EFI_COMMON_SECTION_HEADER)) { 1816 RealHdrLen = sizeof(EFI_COMPRESSION_SECTION); 1817 UncompressedLength = ((EFI_COMPRESSION_SECTION *)Ptr)->UncompressedLength; 1818 CompressionType = ((EFI_COMPRESSION_SECTION *)Ptr)->CompressionType; 1819 } else { 1820 RealHdrLen = sizeof(EFI_COMPRESSION_SECTION2); 1821 UncompressedLength = ((EFI_COMPRESSION_SECTION2 *)Ptr)->UncompressedLength; 1822 CompressionType = ((EFI_COMPRESSION_SECTION2 *)Ptr)->CompressionType; 1823 } 1824 CompressedLength = SectionLength - RealHdrLen; 1825 printf (" Uncompressed Length: 0x%08X\n", (unsigned) UncompressedLength); 1826 1827 if (CompressionType == EFI_NOT_COMPRESSED) { 1828 printf (" Compression Type: EFI_NOT_COMPRESSED\n"); 1829 if (CompressedLength != UncompressedLength) { 1830 Error ( 1831 NULL, 1832 0, 1833 0, 1834 "file is not compressed, but the compressed length does not match the uncompressed length", 1835 NULL 1836 ); 1837 return EFI_SECTION_ERROR; 1838 } 1839 1840 UncompressedBuffer = Ptr + RealHdrLen; 1841 } else if (CompressionType == EFI_STANDARD_COMPRESSION) { 1842 GetInfoFunction = EfiGetInfo; 1843 DecompressFunction = EfiDecompress; 1844 printf (" Compression Type: EFI_STANDARD_COMPRESSION\n"); 1845 1846 CompressedBuffer = Ptr + RealHdrLen; 1847 1848 Status = GetInfoFunction (CompressedBuffer, CompressedLength, &DstSize, &ScratchSize); 1849 if (EFI_ERROR (Status)) { 1850 Error (NULL, 0, 0003, "error getting compression info from compression section", NULL); 1851 return EFI_SECTION_ERROR; 1852 } 1853 1854 if (DstSize != UncompressedLength) { 1855 Error (NULL, 0, 0003, "compression error in the compression section", NULL); 1856 return EFI_SECTION_ERROR; 1857 } 1858 1859 ScratchBuffer = malloc (ScratchSize); 1860 if (ScratchBuffer == NULL) { 1861 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); 1862 return EFI_OUT_OF_RESOURCES; 1863 } 1864 UncompressedBuffer = malloc (UncompressedLength); 1865 if (UncompressedBuffer == NULL) { 1866 free (ScratchBuffer); 1867 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); 1868 return EFI_OUT_OF_RESOURCES; 1869 } 1870 Status = DecompressFunction ( 1871 CompressedBuffer, 1872 CompressedLength, 1873 UncompressedBuffer, 1874 UncompressedLength, 1875 ScratchBuffer, 1876 ScratchSize 1877 ); 1878 free (ScratchBuffer); 1879 if (EFI_ERROR (Status)) { 1880 Error (NULL, 0, 0003, "decompress failed", NULL); 1881 free (UncompressedBuffer); 1882 return EFI_SECTION_ERROR; 1883 } 1884 } else { 1885 Error (NULL, 0, 0003, "unrecognized compression type", "type 0x%X", CompressionType); 1886 return EFI_SECTION_ERROR; 1887 } 1888 1889 Status = ParseSection (UncompressedBuffer, UncompressedLength); 1890 1891 if (CompressionType == EFI_STANDARD_COMPRESSION) { 1892 // 1893 // We need to deallocate Buffer 1894 // 1895 free (UncompressedBuffer); 1896 } 1897 1898 if (EFI_ERROR (Status)) { 1899 Error (NULL, 0, 0003, "failed to parse section", NULL); 1900 return EFI_SECTION_ERROR; 1901 } 1902 break; 1903 1904 case EFI_SECTION_GUID_DEFINED: 1905 if (SectionHeaderLen == sizeof(EFI_COMMON_SECTION_HEADER)) { 1906 EfiGuid = &((EFI_GUID_DEFINED_SECTION *) Ptr)->SectionDefinitionGuid; 1907 DataOffset = ((EFI_GUID_DEFINED_SECTION *) Ptr)->DataOffset; 1908 Attributes = ((EFI_GUID_DEFINED_SECTION *) Ptr)->Attributes; 1909 } else { 1910 EfiGuid = &((EFI_GUID_DEFINED_SECTION2 *) Ptr)->SectionDefinitionGuid; 1911 DataOffset = ((EFI_GUID_DEFINED_SECTION2 *) Ptr)->DataOffset; 1912 Attributes = ((EFI_GUID_DEFINED_SECTION2 *) Ptr)->Attributes; 1913 } 1914 printf (" SectionDefinitionGuid: "); 1915 PrintGuid (EfiGuid); 1916 printf ("\n"); 1917 printf (" DataOffset: 0x%04X\n", (unsigned) DataOffset); 1918 printf (" Attributes: 0x%04X\n", (unsigned) Attributes); 1919 1920 ExtractionTool = 1921 LookupGuidedSectionToolPath ( 1922 mParsedGuidedSectionTools, 1923 EfiGuid 1924 ); 1925 1926 if (ExtractionTool != NULL) { 1927 #ifndef __GNUC__ 1928 ToolInputFile = CloneString (tmpnam (NULL)); 1929 ToolOutputFile = CloneString (tmpnam (NULL)); 1930 #else 1931 char tmp1[] = "/tmp/fileXXXXXX"; 1932 char tmp2[] = "/tmp/fileXXXXXX"; 1933 int fd1; 1934 int fd2; 1935 fd1 = mkstemp(tmp1); 1936 fd2 = mkstemp(tmp2); 1937 ToolInputFile = CloneString(tmp1); 1938 ToolOutputFile = CloneString(tmp2); 1939 close(fd1); 1940 close(fd2); 1941 #endif 1942 1943 if ((ToolInputFile == NULL) || (ToolOutputFile == NULL)) { 1944 if (ToolInputFile != NULL) { 1945 free (ToolInputFile); 1946 } 1947 if (ToolOutputFile != NULL) { 1948 free (ToolOutputFile); 1949 } 1950 free (ExtractionTool); 1951 1952 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); 1953 return EFI_OUT_OF_RESOURCES; 1954 } 1955 1956 // 1957 // Construction 'system' command string 1958 // 1959 SystemCommand = malloc ( 1960 strlen (EXTRACT_COMMAND_FORMAT_STRING) + 1961 strlen (ExtractionTool) + 1962 strlen (ToolInputFile) + 1963 strlen (ToolOutputFile) + 1964 1 1965 ); 1966 if (SystemCommand == NULL) { 1967 free (ToolInputFile); 1968 free (ToolOutputFile); 1969 free (ExtractionTool); 1970 1971 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); 1972 return EFI_OUT_OF_RESOURCES; 1973 } 1974 sprintf ( 1975 SystemCommand, 1976 EXTRACT_COMMAND_FORMAT_STRING, 1977 ExtractionTool, 1978 ToolOutputFile, 1979 ToolInputFile 1980 ); 1981 free (ExtractionTool); 1982 1983 Status = 1984 PutFileImage ( 1985 ToolInputFile, 1986 (CHAR8*) SectionBuffer + DataOffset, 1987 BufferLength - DataOffset 1988 ); 1989 1990 system (SystemCommand); 1991 remove (ToolInputFile); 1992 free (ToolInputFile); 1993 1994 Status = 1995 GetFileImage ( 1996 ToolOutputFile, 1997 (CHAR8 **)&ToolOutputBuffer, 1998 &ToolOutputLength 1999 ); 2000 remove (ToolOutputFile); 2001 free (ToolOutputFile); 2002 free (SystemCommand); 2003 if (EFI_ERROR (Status)) { 2004 Error (NULL, 0, 0004, "unable to read decoded GUIDED section", NULL); 2005 return EFI_SECTION_ERROR; 2006 } 2007 2008 Status = ParseSection ( 2009 ToolOutputBuffer, 2010 ToolOutputLength 2011 ); 2012 if (EFI_ERROR (Status)) { 2013 Error (NULL, 0, 0003, "parse of decoded GUIDED section failed", NULL); 2014 return EFI_SECTION_ERROR; 2015 } 2016 2017 // 2018 // Check for CRC32 sections which we can handle internally if needed. 2019 // 2020 } else if (!CompareGuid ( 2021 EfiGuid, 2022 &gEfiCrc32GuidedSectionExtractionProtocolGuid 2023 ) 2024 ) { 2025 // 2026 // CRC32 guided section 2027 // 2028 Status = ParseSection ( 2029 SectionBuffer + DataOffset, 2030 BufferLength - DataOffset 2031 ); 2032 if (EFI_ERROR (Status)) { 2033 Error (NULL, 0, 0003, "parse of CRC32 GUIDED section failed", NULL); 2034 return EFI_SECTION_ERROR; 2035 } 2036 } else { 2037 // 2038 // We don't know how to parse it now. 2039 // 2040 Error (NULL, 0, 0003, "Error parsing section", \ 2041 "EFI_SECTION_GUID_DEFINED cannot be parsed at this time. Tool to decode this section should have been defined in GuidedSectionTools.txt (built in the FV directory)."); 2042 return EFI_UNSUPPORTED; 2043 } 2044 break; 2045 2046 default: 2047 // 2048 // Unknown section, return error 2049 // 2050 Error (NULL, 0, 0003, "unrecognized section type found", "section type = 0x%X", Type); 2051 return EFI_SECTION_ERROR; 2052 } 2053 2054 ParsedLength += SectionLength; 2055 // 2056 // We make then next section begin on a 4-byte boundary 2057 // 2058 ParsedLength = GetOccupiedSize (ParsedLength, 4); 2059 } 2060 2061 if (ParsedLength < BufferLength) { 2062 Error (NULL, 0, 0003, "sections do not completely fill the sectioned buffer being parsed", NULL); 2063 return EFI_SECTION_ERROR; 2064 } 2065 2066 return EFI_SUCCESS; 2067 } 2068 2069 EFI_STATUS 2070 DumpDepexSection ( 2071 IN UINT8 *Ptr, 2072 IN UINT32 SectionLength 2073 ) 2074 /*++ 2075 2076 Routine Description: 2077 2078 GC_TODO: Add function description 2079 2080 Arguments: 2081 2082 Ptr - GC_TODO: add argument description 2083 SectionLength - GC_TODO: add argument description 2084 2085 Returns: 2086 2087 EFI_SUCCESS - GC_TODO: Add description for return value 2088 2089 --*/ 2090 { 2091 UINT8 GuidBuffer[PRINTED_GUID_BUFFER_SIZE]; 2092 2093 // 2094 // Need at least a section header + data 2095 // 2096 if (SectionLength <= sizeof (EFI_COMMON_SECTION_HEADER)) { 2097 return EFI_SUCCESS; 2098 } 2099 2100 Ptr += GetSectionHeaderLength((EFI_COMMON_SECTION_HEADER *)Ptr); 2101 SectionLength -= GetSectionHeaderLength((EFI_COMMON_SECTION_HEADER *)Ptr); 2102 while (SectionLength > 0) { 2103 printf (" "); 2104 switch (*Ptr) { 2105 case EFI_DEP_BEFORE: 2106 printf ("BEFORE\n"); 2107 Ptr++; 2108 SectionLength--; 2109 break; 2110 2111 case EFI_DEP_AFTER: 2112 printf ("AFTER\n"); 2113 Ptr++; 2114 SectionLength--; 2115 break; 2116 2117 case EFI_DEP_PUSH: 2118 printf ("PUSH\n "); 2119 PrintGuidToBuffer ((EFI_GUID *) (Ptr + 1), GuidBuffer, sizeof (GuidBuffer), TRUE); 2120 printf ("%s ", GuidBuffer); 2121 PrintGuidName (GuidBuffer); 2122 printf ("\n"); 2123 // 2124 // PrintGuid ((EFI_GUID *)(Ptr + 1)); 2125 // 2126 Ptr += 17; 2127 SectionLength -= 17; 2128 break; 2129 2130 case EFI_DEP_AND: 2131 printf ("AND\n"); 2132 Ptr++; 2133 SectionLength--; 2134 break; 2135 2136 case EFI_DEP_OR: 2137 printf ("OR\n"); 2138 Ptr++; 2139 SectionLength--; 2140 break; 2141 2142 case EFI_DEP_NOT: 2143 printf ("NOT\n"); 2144 Ptr++; 2145 SectionLength--; 2146 break; 2147 2148 case EFI_DEP_TRUE: 2149 printf ("TRUE\n"); 2150 Ptr++; 2151 SectionLength--; 2152 break; 2153 2154 case EFI_DEP_FALSE: 2155 printf ("FALSE\n"); 2156 Ptr++; 2157 SectionLength--; 2158 break; 2159 2160 case EFI_DEP_END: 2161 printf ("END DEPEX\n"); 2162 Ptr++; 2163 SectionLength--; 2164 break; 2165 2166 case EFI_DEP_SOR: 2167 printf ("SOR\n"); 2168 Ptr++; 2169 SectionLength--; 2170 break; 2171 2172 default: 2173 printf ("Unrecognized byte in depex: 0x%X\n", *Ptr); 2174 return EFI_SUCCESS; 2175 } 2176 } 2177 2178 return EFI_SUCCESS; 2179 } 2180 2181 EFI_STATUS 2182 PrintGuidName ( 2183 IN UINT8 *GuidStr 2184 ) 2185 /*++ 2186 2187 Routine Description: 2188 2189 GC_TODO: Add function description 2190 2191 Arguments: 2192 2193 GuidStr - GC_TODO: add argument description 2194 2195 Returns: 2196 2197 EFI_SUCCESS - GC_TODO: Add description for return value 2198 EFI_INVALID_PARAMETER - GC_TODO: Add description for return value 2199 2200 --*/ 2201 { 2202 GUID_TO_BASENAME *GPtr; 2203 // 2204 // If we have a list of guid-to-basenames, then go through the list to 2205 // look for a guid string match. If found, print the basename to stdout, 2206 // otherwise return a failure. 2207 // 2208 GPtr = mGuidBaseNameList; 2209 while (GPtr != NULL) { 2210 if (_stricmp ((CHAR8*) GuidStr, (CHAR8*) GPtr->Guid) == 0) { 2211 printf ("%s", GPtr->BaseName); 2212 return EFI_SUCCESS; 2213 } 2214 2215 GPtr = GPtr->Next; 2216 } 2217 2218 return EFI_INVALID_PARAMETER; 2219 } 2220 2221 EFI_STATUS 2222 ParseGuidBaseNameFile ( 2223 CHAR8 *FileName 2224 ) 2225 /*++ 2226 2227 Routine Description: 2228 2229 GC_TODO: Add function description 2230 2231 Arguments: 2232 2233 FileName - GC_TODO: add argument description 2234 2235 Returns: 2236 2237 EFI_DEVICE_ERROR - GC_TODO: Add description for return value 2238 EFI_OUT_OF_RESOURCES - GC_TODO: Add description for return value 2239 EFI_SUCCESS - GC_TODO: Add description for return value 2240 2241 --*/ 2242 { 2243 FILE *Fptr; 2244 CHAR8 Line[MAX_LINE_LEN]; 2245 CHAR8 *FormatString; 2246 INTN FormatLength; 2247 GUID_TO_BASENAME *GPtr; 2248 2249 if ((Fptr = fopen (LongFilePath (FileName), "r")) == NULL) { 2250 printf ("ERROR: Failed to open input cross-reference file '%s'\n", FileName); 2251 return EFI_DEVICE_ERROR; 2252 } 2253 2254 // 2255 // Generate the format string for fscanf 2256 // 2257 FormatLength = snprintf ( 2258 NULL, 2259 0, 2260 "%%%us %%%us", 2261 (unsigned) sizeof (GPtr->Guid) - 1, 2262 (unsigned) sizeof (GPtr->BaseName) - 1 2263 ) + 1; 2264 2265 FormatString = (CHAR8 *) malloc (FormatLength); 2266 if (FormatString == NULL) { 2267 fclose (Fptr); 2268 return EFI_OUT_OF_RESOURCES; 2269 } 2270 2271 snprintf ( 2272 FormatString, 2273 FormatLength, 2274 "%%%us %%%us", 2275 (unsigned) sizeof (GPtr->Guid) - 1, 2276 (unsigned) sizeof (GPtr->BaseName) - 1 2277 ); 2278 2279 while (fgets (Line, sizeof (Line), Fptr) != NULL) { 2280 // 2281 // Allocate space for another guid/basename element 2282 // 2283 GPtr = malloc (sizeof (GUID_TO_BASENAME)); 2284 if (GPtr == NULL) { 2285 free (FormatString); 2286 fclose (Fptr); 2287 return EFI_OUT_OF_RESOURCES; 2288 } 2289 2290 memset ((char *) GPtr, 0, sizeof (GUID_TO_BASENAME)); 2291 if (sscanf (Line, FormatString, GPtr->Guid, GPtr->BaseName) == 2) { 2292 GPtr->Next = mGuidBaseNameList; 2293 mGuidBaseNameList = GPtr; 2294 } else { 2295 // 2296 // Some sort of error. Just continue. 2297 // 2298 free (GPtr); 2299 } 2300 } 2301 2302 free (FormatString); 2303 fclose (Fptr); 2304 return EFI_SUCCESS; 2305 } 2306 2307 EFI_STATUS 2308 FreeGuidBaseNameList ( 2309 VOID 2310 ) 2311 /*++ 2312 2313 Routine Description: 2314 2315 GC_TODO: Add function description 2316 2317 Arguments: 2318 2319 None 2320 2321 Returns: 2322 2323 EFI_SUCCESS - GC_TODO: Add description for return value 2324 2325 --*/ 2326 { 2327 GUID_TO_BASENAME *Next; 2328 2329 while (mGuidBaseNameList != NULL) { 2330 Next = mGuidBaseNameList->Next; 2331 free (mGuidBaseNameList); 2332 mGuidBaseNameList = Next; 2333 } 2334 2335 return EFI_SUCCESS; 2336 } 2337 2338 2339 static 2340 VOID 2341 LoadGuidedSectionToolsTxt ( 2342 IN CHAR8* FirmwareVolumeFilename 2343 ) 2344 { 2345 CHAR8* PeerFilename; 2346 CHAR8* Places[] = { 2347 NULL, 2348 //NULL, 2349 }; 2350 UINTN Index; 2351 2352 Places[0] = FirmwareVolumeFilename; 2353 //Places[1] = mUtilityFilename; 2354 2355 mParsedGuidedSectionTools = NULL; 2356 2357 for (Index = 0; Index < (sizeof(Places)/sizeof(Places[0])); Index++) { 2358 PeerFilename = OsPathPeerFilePath (Places[Index], "GuidedSectionTools.txt"); 2359 //printf("Loading %s...\n", PeerFilename); 2360 if (OsPathExists (PeerFilename)) { 2361 mParsedGuidedSectionTools = ParseGuidedSectionToolsFile (PeerFilename); 2362 } 2363 free (PeerFilename); 2364 if (mParsedGuidedSectionTools != NULL) { 2365 return; 2366 } 2367 } 2368 } 2369 2370 2371 void 2372 Usage ( 2373 VOID 2374 ) 2375 /*++ 2376 2377 Routine Description: 2378 2379 GC_TODO: Add function description 2380 2381 Arguments: 2382 2383 None 2384 2385 Returns: 2386 2387 GC_TODO: add return values 2388 2389 --*/ 2390 { 2391 // 2392 // Summary usage 2393 // 2394 fprintf (stdout, "Usage: %s [options] <input_file>\n\n", UTILITY_NAME); 2395 2396 // 2397 // Copyright declaration 2398 // 2399 fprintf (stdout, "Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.\n\n"); 2400 fprintf (stdout, " Display Tiano Firmware Volume FFS image information\n\n"); 2401 2402 // 2403 // Details Option 2404 // 2405 fprintf (stdout, "optional arguments:\n"); 2406 fprintf (stdout, " -h, --help\n\ 2407 Show this help message and exit\n"); 2408 fprintf (stdout, " --version\n\ 2409 Show program's version number and exit\n"); 2410 fprintf (stdout, " -d [DEBUG], --debug [DEBUG]\n\ 2411 Output DEBUG statements, where DEBUG_LEVEL is 0 (min) - 9 (max)\n"); 2412 fprintf (stdout, " -v, --verbose\n\ 2413 Print informational statements\n"); 2414 fprintf (stdout, " -q, --quiet\n\ 2415 Returns the exit code, error messages will be displayed\n"); 2416 fprintf (stdout, " -s, --silent\n\ 2417 Returns only the exit code; informational and error\n\ 2418 messages are not displayed\n"); 2419 fprintf (stdout, " -x XREF_FILENAME, --xref XREF_FILENAME\n\ 2420 Parse the basename to file-guid cross reference file(s)\n"); 2421 fprintf (stdout, " -f OFFSET, --offset OFFSET\n\ 2422 The offset from the start of the input file to start \n\ 2423 processing an FV\n"); 2424 fprintf (stdout, " --hash\n\ 2425 Generate HASH value of the entire PE image\n"); 2426 fprintf (stdout, " --sfo\n\ 2427 Reserved for future use\n"); 2428 } 2429 2430