Home | History | Annotate | Download | only in VolInfo
      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