]> git.proxmox.com Git - mirror_edk2.git/blobdiff - BaseTools/Source/C/VolInfo/VolInfo.c
BaseTools: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / BaseTools / Source / C / VolInfo / VolInfo.c
index 0f54c2a42963c19bc9102e4b8bca68ca320e51de..d8216c61e88bd0235721b4a9cea3a4dcb4cddbe8 100644 (file)
@@ -1,21 +1,8 @@
 /** @file\r
 /** @file\r
+The tool dumps the contents of a firmware volume\r
 \r
 \r
-Copyright (c) 1999 - 2011, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution.  The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-Module Name:\r
-\r
-  VolInfo.c\r
-\r
-Abstract:\r
-\r
-  The tool dumps the contents of a firmware volume\r
+Copyright (c) 1999 - 2018, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
 \r
 **/\r
 \r
@@ -24,6 +11,11 @@ Abstract:
 #include <string.h>\r
 #include <ctype.h>\r
 #include <assert.h>\r
 #include <string.h>\r
 #include <ctype.h>\r
 #include <assert.h>\r
+#ifdef __GNUC__\r
+#include <unistd.h>\r
+#else\r
+#include <direct.h>\r
+#endif\r
 \r
 #include <FvLib.h>\r
 #include <Common/UefiBaseTypes.h>\r
 \r
 #include <FvLib.h>\r
 #include <Common/UefiBaseTypes.h>\r
@@ -43,6 +35,8 @@ Abstract:
 #include "OsPath.h"\r
 #include "ParseGuidedSectionTools.h"\r
 #include "StringFuncs.h"\r
 #include "OsPath.h"\r
 #include "ParseGuidedSectionTools.h"\r
 #include "StringFuncs.h"\r
+#include "ParseInf.h"\r
+#include "PeCoffLib.h"\r
 \r
 //\r
 // Utility global variables\r
 \r
 //\r
 // Utility global variables\r
@@ -50,8 +44,8 @@ Abstract:
 \r
 EFI_GUID  gEfiCrc32GuidedSectionExtractionProtocolGuid = EFI_CRC32_GUIDED_SECTION_EXTRACTION_PROTOCOL_GUID;\r
 \r
 \r
 EFI_GUID  gEfiCrc32GuidedSectionExtractionProtocolGuid = EFI_CRC32_GUIDED_SECTION_EXTRACTION_PROTOCOL_GUID;\r
 \r
-#define UTILITY_MAJOR_VERSION      0\r
-#define UTILITY_MINOR_VERSION      82\r
+#define UTILITY_MAJOR_VERSION      1\r
+#define UTILITY_MINOR_VERSION      0\r
 \r
 #define UTILITY_NAME         "VolInfo"\r
 \r
 \r
 #define UTILITY_NAME         "VolInfo"\r
 \r
@@ -77,6 +71,9 @@ EFI_HANDLE mParsedGuidedSectionTools = NULL;
 \r
 CHAR8* mUtilityFilename = NULL;\r
 \r
 \r
 CHAR8* mUtilityFilename = NULL;\r
 \r
+BOOLEAN EnableHash = FALSE;\r
+CHAR8 *OpenSslPath = NULL;\r
+\r
 EFI_STATUS\r
 ParseGuidBaseNameFile (\r
   CHAR8    *FileName\r
 EFI_STATUS\r
 ParseGuidBaseNameFile (\r
   CHAR8    *FileName\r
@@ -133,11 +130,77 @@ LoadGuidedSectionToolsTxt (
   IN CHAR8* FirmwareVolumeFilename\r
   );\r
 \r
   IN CHAR8* FirmwareVolumeFilename\r
   );\r
 \r
+EFI_STATUS\r
+CombinePath (\r
+  IN  CHAR8* DefaultPath,\r
+  IN  CHAR8* AppendPath,\r
+  OUT CHAR8* NewPath\r
+);\r
+\r
 void\r
 Usage (\r
   VOID\r
   );\r
 \r
 void\r
 Usage (\r
   VOID\r
   );\r
 \r
+UINT32\r
+UnicodeStrLen (\r
+  IN CHAR16 *String\r
+  )\r
+  /*++\r
+\r
+  Routine Description:\r
+\r
+  Returns the length of a null-terminated unicode string.\r
+\r
+  Arguments:\r
+\r
+    String - The pointer to a null-terminated unicode string.\r
+\r
+  Returns:\r
+\r
+    N/A\r
+\r
+  --*/\r
+{\r
+  UINT32  Length;\r
+\r
+  for (Length = 0; *String != L'\0'; String++, Length++) {\r
+    ;\r
+  }\r
+  return Length;\r
+}\r
+\r
+VOID\r
+Unicode2AsciiString (\r
+  IN  CHAR16 *Source,\r
+  OUT CHAR8  *Destination\r
+  )\r
+  /*++\r
+\r
+  Routine Description:\r
+\r
+  Convert a null-terminated unicode string to a null-terminated ascii string.\r
+\r
+  Arguments:\r
+\r
+    Source      - The pointer to the null-terminated input unicode string.\r
+    Destination - The pointer to the null-terminated output ascii string.\r
+\r
+  Returns:\r
+\r
+    N/A\r
+\r
+  --*/\r
+{\r
+  while (*Source != '\0') {\r
+    *(Destination++) = (CHAR8) *(Source++);\r
+  }\r
+  //\r
+  // End the ascii with a NULL.\r
+  //\r
+  *Destination = '\0';\r
+}\r
+\r
 int\r
 main (\r
   int       argc,\r
 int\r
 main (\r
   int       argc,\r
@@ -167,41 +230,61 @@ Returns:
   EFI_STATUS                  Status;\r
   int                         Offset;\r
   BOOLEAN                     ErasePolarity;\r
   EFI_STATUS                  Status;\r
   int                         Offset;\r
   BOOLEAN                     ErasePolarity;\r
+  UINT64                      LogLevel;\r
+  CHAR8                       *OpenSslEnv;\r
+  CHAR8                       *OpenSslCommand;\r
 \r
   SetUtilityName (UTILITY_NAME);\r
   //\r
   // Print utility header\r
   //\r
 \r
   SetUtilityName (UTILITY_NAME);\r
   //\r
   // Print utility header\r
   //\r
-  printf ("%s Tiano Firmware Volume FFS image info.  Version %d.%d %s, %s\n",\r
+  printf ("%s Version %d.%d Build %s\n",\r
     UTILITY_NAME,\r
     UTILITY_MAJOR_VERSION,\r
     UTILITY_MINOR_VERSION,\r
     UTILITY_NAME,\r
     UTILITY_MAJOR_VERSION,\r
     UTILITY_MINOR_VERSION,\r
-    __BUILD_VERSION,\r
-    __DATE__\r
+    __BUILD_VERSION\r
     );\r
 \r
     );\r
 \r
-  //\r
-  // Save, and then skip filename arg\r
-  //\r
-  mUtilityFilename = argv[0];\r
+  if (argc == 1) {\r
+    Usage ();\r
+    return -1;\r
+  }\r
+\r
   argc--;\r
   argv++;\r
   argc--;\r
   argv++;\r
-\r
+  LogLevel = 0;\r
   Offset = 0;\r
 \r
   Offset = 0;\r
 \r
+  //\r
+  // Look for help options\r
+  //\r
+  if ((strcmp(argv[0], "-h") == 0) || (strcmp(argv[0], "--help") == 0) ||\r
+      (strcmp(argv[0], "-?") == 0) || (strcmp(argv[0], "/?") == 0)) {\r
+    Usage();\r
+    return  STATUS_SUCCESS;\r
+  }\r
+  //\r
+  // Version has already be printed, so just return success\r
+  //\r
+  if (strcmp(argv[0], "--version") == 0) {\r
+    return  STATUS_SUCCESS;\r
+  }\r
+\r
   //\r
   // If they specified -x xref guid/basename cross-reference files, process it.\r
   // This will print the basename beside each file guid. To use it, specify\r
   // -x xref_filename to processdsc, then use xref_filename as a parameter\r
   // here.\r
   //\r
   //\r
   // If they specified -x xref guid/basename cross-reference files, process it.\r
   // This will print the basename beside each file guid. To use it, specify\r
   // -x xref_filename to processdsc, then use xref_filename as a parameter\r
   // here.\r
   //\r
-  while (argc > 2) {\r
+  while (argc > 0) {\r
     if ((strcmp(argv[0], "-x") == 0) || (strcmp(argv[0], "--xref") == 0)) {\r
       ParseGuidBaseNameFile (argv[1]);\r
       printf("ParseGuidBaseNameFile: %s\n", argv[1]);\r
       argc -= 2;\r
       argv += 2;\r
     if ((strcmp(argv[0], "-x") == 0) || (strcmp(argv[0], "--xref") == 0)) {\r
       ParseGuidBaseNameFile (argv[1]);\r
       printf("ParseGuidBaseNameFile: %s\n", argv[1]);\r
       argc -= 2;\r
       argv += 2;\r
-    } else if (strcmp(argv[0], "--offset") == 0) {\r
+      continue;\r
+    }\r
+    if (strcmp(argv[0], "--offset") == 0) {\r
       //\r
       // Hex or decimal?\r
       //\r
       //\r
       // Hex or decimal?\r
       //\r
@@ -225,33 +308,88 @@ Returns:
 \r
       argc -= 2;\r
       argv += 2;\r
 \r
       argc -= 2;\r
       argv += 2;\r
-    } else {\r
-      Usage ();\r
-      return -1;\r
+      continue;\r
     }\r
     }\r
-  }\r
-  //\r
-  // Check for proper number of arguments\r
-  //\r
-  if (argc != 1) {\r
-    Usage ();\r
-    return -1;\r
-  }\r
-  //\r
-  // Look for help options\r
-  //\r
-  if ((strcmp(argv[0], "-h") == 0) || (strcmp(argv[0], "--help") == 0) || \r
-      (strcmp(argv[0], "-?") == 0) || (strcmp(argv[0], "/?") == 0)) {\r
-    Usage();\r
-    return STATUS_ERROR;\r
+    if ((stricmp (argv[0], "--hash") == 0)) {\r
+      if (EnableHash == TRUE) {\r
+        //\r
+        // --hash already given in the option, ignore this one\r
+        //\r
+        argc --;\r
+        argv ++;\r
+        continue;\r
+      }\r
+      EnableHash = TRUE;\r
+      OpenSslCommand = "openssl";\r
+      OpenSslEnv = getenv("OPENSSL_PATH");\r
+      if (OpenSslEnv == NULL) {\r
+        OpenSslPath = OpenSslCommand;\r
+      } else {\r
+        //\r
+        // We add quotes to the Openssl Path in case it has space characters\r
+        //\r
+        OpenSslPath = malloc(2+strlen(OpenSslEnv)+strlen(OpenSslCommand)+1);\r
+        if (OpenSslPath == NULL) {\r
+          Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
+          return GetUtilityStatus ();\r
+        }\r
+        CombinePath(OpenSslEnv, OpenSslCommand, OpenSslPath);\r
+      }\r
+      if (OpenSslPath == NULL){\r
+        Error (NULL, 0, 3000, "Open SSL command not available.  Please verify PATH or set OPENSSL_PATH.", NULL);\r
+        return GetUtilityStatus ();\r
+      }\r
+      argc --;\r
+      argv ++;\r
+      continue;\r
+    }\r
+\r
+    if ((stricmp (argv[0], "-v") == 0) || (stricmp (argv[0], "--verbose") == 0)) {\r
+      SetPrintLevel (VERBOSE_LOG_LEVEL);\r
+      argc --;\r
+      argv ++;\r
+      continue;\r
+    }\r
+\r
+    if ((stricmp (argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) {\r
+      SetPrintLevel (KEY_LOG_LEVEL);\r
+      argc --;\r
+      argv ++;\r
+      continue;\r
+    }\r
+\r
+    if ((stricmp (argv[0], "-d") == 0) || (stricmp (argv[0], "--debug") == 0)) {\r
+      Status = AsciiStringToUint64 (argv[1], FALSE, &LogLevel);\r
+      if (EFI_ERROR (Status)) {\r
+        Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
+        return -1;\r
+      }\r
+      if (LogLevel > 9) {\r
+        Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0-9, current input level is %d", (int) LogLevel);\r
+        return -1;\r
+      }\r
+      SetPrintLevel (LogLevel);\r
+      DebugMsg (NULL, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv[1]);\r
+      argc -= 2;\r
+      argv += 2;\r
+      continue;\r
+    }\r
+\r
+    mUtilityFilename = argv[0];\r
+    argc --;\r
+    argv ++;\r
   }\r
 \r
   //\r
   // Open the file containing the FV\r
   //\r
   }\r
 \r
   //\r
   // Open the file containing the FV\r
   //\r
-  InputFile = fopen (argv[0], "rb");\r
+  if (mUtilityFilename == NULL) {\r
+    Error (NULL, 0, 1001, "Missing option", "Input files are not specified");\r
+    return GetUtilityStatus ();\r
+  }\r
+  InputFile = fopen (LongFilePath (mUtilityFilename), "rb");\r
   if (InputFile == NULL) {\r
   if (InputFile == NULL) {\r
-    Error (NULL, 0, 0001, "Error opening the input file", argv[0]);\r
+    Error (NULL, 0, 0001, "Error opening the input file", mUtilityFilename);\r
     return GetUtilityStatus ();\r
   }\r
   //\r
     return GetUtilityStatus ();\r
   }\r
   //\r
@@ -266,7 +404,7 @@ Returns:
   //\r
   Status = ReadHeader (InputFile, &FvSize, &ErasePolarity);\r
   if (EFI_ERROR (Status)) {\r
   //\r
   Status = ReadHeader (InputFile, &FvSize, &ErasePolarity);\r
   if (EFI_ERROR (Status)) {\r
-    Error (NULL, 0, 0003, "error parsing FV image", "%s Header is invalid", argv[0]);\r
+    Error (NULL, 0, 0003, "error parsing FV image", "%s Header is invalid", mUtilityFilename);\r
     fclose (InputFile);\r
     return GetUtilityStatus ();\r
   }\r
     fclose (InputFile);\r
     return GetUtilityStatus ();\r
   }\r
@@ -286,12 +424,12 @@ Returns:
   BytesRead = fread (FvImage, 1, FvSize, InputFile);\r
   fclose (InputFile);\r
   if ((unsigned int) BytesRead != FvSize) {\r
   BytesRead = fread (FvImage, 1, FvSize, InputFile);\r
   fclose (InputFile);\r
   if ((unsigned int) BytesRead != FvSize) {\r
-    Error (NULL, 0, 0004, "error reading FvImage from", argv[0]);\r
+    Error (NULL, 0, 0004, "error reading FvImage from", mUtilityFilename);\r
     free (FvImage);\r
     return GetUtilityStatus ();\r
   }\r
 \r
     free (FvImage);\r
     return GetUtilityStatus ();\r
   }\r
 \r
-  LoadGuidedSectionToolsTxt (argv[0]);\r
+  LoadGuidedSectionToolsTxt (mUtilityFilename);\r
 \r
   PrintFvInfo (FvImage, FALSE);\r
 \r
 \r
   PrintFvInfo (FvImage, FALSE);\r
 \r
@@ -397,16 +535,16 @@ GetOccupiedSize (
 \r
 Routine Description:\r
 \r
 \r
 Routine Description:\r
 \r
-  This function returns the next larger size that meets the alignment \r
+  This function returns the next larger size that meets the alignment\r
   requirement specified.\r
 \r
 Arguments:\r
 \r
   ActualSize      The size.\r
   Alignment       The desired alignment.\r
   requirement specified.\r
 \r
 Arguments:\r
 \r
   ActualSize      The size.\r
   Alignment       The desired alignment.\r
-    \r
+\r
 Returns:\r
 Returns:\r
\r
+\r
   EFI_SUCCESS             Function completed successfully.\r
   EFI_ABORTED             The function encountered an error.\r
 \r
   EFI_SUCCESS             Function completed successfully.\r
   EFI_ABORTED             The function encountered an error.\r
 \r
@@ -456,7 +594,7 @@ Returns:
     //\r
     // 0x02\r
     //\r
     //\r
     // 0x02\r
     //\r
-    "EFI_SECTION_GUID_DEFINED",    \r
+    "EFI_SECTION_GUID_DEFINED",\r
     //\r
     // 0x03\r
     //\r
     //\r
     // 0x03\r
     //\r
@@ -520,11 +658,11 @@ Returns:
     //\r
     // 0x12\r
     //\r
     //\r
     // 0x12\r
     //\r
-    "EFI_SECTION_TE",    \r
+    "EFI_SECTION_TE",\r
     //\r
     // 0x13\r
     //\r
     //\r
     // 0x13\r
     //\r
-    "EFI_SECTION_DXE_DEPEX", \r
+    "EFI_SECTION_DXE_DEPEX",\r
     //\r
     // 0x14\r
     //\r
     //\r
     // 0x14\r
     //\r
@@ -591,7 +729,7 @@ ReadHeader (
 \r
 Routine Description:\r
 \r
 \r
 Routine Description:\r
 \r
-  This function determines the size of the FV and the erase polarity.  The \r
+  This function determines the size of the FV and the erase polarity.  The\r
   erase polarity is the FALSE value for file state.\r
 \r
 Arguments:\r
   erase polarity is the FALSE value for file state.\r
 \r
 Arguments:\r
@@ -599,9 +737,9 @@ Arguments:
   InputFile       The file that contains the FV image.\r
   FvSize          The size of the FV.\r
   ErasePolarity   The FV erase polarity.\r
   InputFile       The file that contains the FV image.\r
   FvSize          The size of the FV.\r
   ErasePolarity   The FV erase polarity.\r
-    \r
+\r
 Returns:\r
 Returns:\r
\r
+\r
   EFI_SUCCESS             Function completed successfully.\r
   EFI_INVALID_PARAMETER   A required parameter was NULL or is out of range.\r
   EFI_ABORTED             The function encountered an error.\r
   EFI_SUCCESS             Function completed successfully.\r
   EFI_INVALID_PARAMETER   A required parameter was NULL or is out of range.\r
   EFI_ABORTED             The function encountered an error.\r
@@ -750,7 +888,7 @@ Returns:
   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_64K) {\r
     printf ("        EFI_FVB2_ALIGNMENT_64K\n");\r
   }\r
   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_64K) {\r
     printf ("        EFI_FVB2_ALIGNMENT_64K\n");\r
   }\r
-  \r
+\r
 #else\r
 \r
   if (VolumeHeader.Attributes & EFI_FVB2_READ_LOCK_CAP) {\r
 #else\r
 \r
   if (VolumeHeader.Attributes & EFI_FVB2_READ_LOCK_CAP) {\r
@@ -975,22 +1113,24 @@ Returns:
   UINT32              FileLength;\r
   UINT8               FileState;\r
   UINT8               Checksum;\r
   UINT32              FileLength;\r
   UINT8               FileState;\r
   UINT8               Checksum;\r
-  EFI_FFS_FILE_HEADER BlankHeader;\r
+  EFI_FFS_FILE_HEADER2 BlankHeader;\r
   EFI_STATUS          Status;\r
   UINT8               GuidBuffer[PRINTED_GUID_BUFFER_SIZE];\r
   EFI_STATUS          Status;\r
   UINT8               GuidBuffer[PRINTED_GUID_BUFFER_SIZE];\r
-#if (PI_SPECIFICATION_VERSION < 0x00010000) \r
+  UINT32              HeaderSize;\r
+#if (PI_SPECIFICATION_VERSION < 0x00010000)\r
   UINT16              *Tail;\r
 #endif\r
   //\r
   // Check if we have free space\r
   //\r
   UINT16              *Tail;\r
 #endif\r
   //\r
   // Check if we have free space\r
   //\r
+  HeaderSize = FvBufGetFfsHeaderSize(FileHeader);\r
   if (ErasePolarity) {\r
   if (ErasePolarity) {\r
-    memset (&BlankHeader, -1, sizeof (EFI_FFS_FILE_HEADER));\r
+    memset (&BlankHeader, -1, HeaderSize);\r
   } else {\r
   } else {\r
-    memset (&BlankHeader, 0, sizeof (EFI_FFS_FILE_HEADER));\r
+    memset (&BlankHeader, 0, HeaderSize);\r
   }\r
 \r
   }\r
 \r
-  if (memcmp (&BlankHeader, FileHeader, sizeof (EFI_FFS_FILE_HEADER)) == 0) {\r
+  if (memcmp (&BlankHeader, FileHeader, HeaderSize) == 0) {\r
     return EFI_SUCCESS;\r
   }\r
   //\r
     return EFI_SUCCESS;\r
   }\r
   //\r
@@ -1008,7 +1148,7 @@ Returns:
   //  PrintGuid (&FileHeader->Name);\r
   //  printf ("\n");\r
   //\r
   //  PrintGuid (&FileHeader->Name);\r
   //  printf ("\n");\r
   //\r
-  FileLength = GetLength (FileHeader->Size);\r
+  FileLength = FvBufGetFfsFileSize (FileHeader);\r
   printf ("File Offset:      0x%08X\n", (unsigned) ((UINTN) FileHeader - (UINTN) FvImage));\r
   printf ("File Length:      0x%08X\n", (unsigned) FileLength);\r
   printf ("File Attributes:  0x%02X\n", FileHeader->Attributes);\r
   printf ("File Offset:      0x%08X\n", (unsigned) ((UINTN) FileHeader - (UINTN) FvImage));\r
   printf ("File Length:      0x%08X\n", (unsigned) FileLength);\r
   printf ("File Attributes:  0x%02X\n", FileHeader->Attributes);\r
@@ -1031,7 +1171,7 @@ Returns:
 \r
   case EFI_FILE_HEADER_VALID:\r
     printf ("        EFI_FILE_HEADER_VALID\n");\r
 \r
   case EFI_FILE_HEADER_VALID:\r
     printf ("        EFI_FILE_HEADER_VALID\n");\r
-    Checksum  = CalculateSum8 ((UINT8 *) FileHeader, sizeof (EFI_FFS_FILE_HEADER));\r
+    Checksum  = CalculateSum8 ((UINT8 *) FileHeader, HeaderSize);\r
     Checksum  = (UINT8) (Checksum - FileHeader->IntegrityCheck.Checksum.File);\r
     Checksum  = (UINT8) (Checksum - FileHeader->State);\r
     if (Checksum != 0) {\r
     Checksum  = (UINT8) (Checksum - FileHeader->IntegrityCheck.Checksum.File);\r
     Checksum  = (UINT8) (Checksum - FileHeader->State);\r
     if (Checksum != 0) {\r
@@ -1053,7 +1193,7 @@ Returns:
     //\r
     // Calculate header checksum\r
     //\r
     //\r
     // Calculate header checksum\r
     //\r
-    Checksum  = CalculateSum8 ((UINT8 *) FileHeader, sizeof (EFI_FFS_FILE_HEADER));\r
+    Checksum  = CalculateSum8 ((UINT8 *) FileHeader, HeaderSize);\r
     Checksum  = (UINT8) (Checksum - FileHeader->IntegrityCheck.Checksum.File);\r
     Checksum  = (UINT8) (Checksum - FileHeader->State);\r
     if (Checksum != 0) {\r
     Checksum  = (UINT8) (Checksum - FileHeader->IntegrityCheck.Checksum.File);\r
     Checksum  = (UINT8) (Checksum - FileHeader->State);\r
     if (Checksum != 0) {\r
@@ -1061,13 +1201,13 @@ Returns:
       return EFI_ABORTED;\r
     }\r
 \r
       return EFI_ABORTED;\r
     }\r
 \r
-    FileLength = GetLength (FileHeader->Size);\r
+    FileLength = FvBufGetFfsFileSize (FileHeader);\r
 \r
     if (FileHeader->Attributes & FFS_ATTRIB_CHECKSUM) {\r
       //\r
       // Calculate file checksum\r
       //\r
 \r
     if (FileHeader->Attributes & FFS_ATTRIB_CHECKSUM) {\r
       //\r
       // Calculate file checksum\r
       //\r
-      Checksum  = CalculateSum8 ((UINT8 *) (FileHeader + 1), FileLength - sizeof (EFI_FFS_FILE_HEADER));\r
+      Checksum  = CalculateSum8 ((UINT8 *)FileHeader + HeaderSize, FileLength - HeaderSize);\r
       Checksum  = Checksum + FileHeader->IntegrityCheck.Checksum.File;\r
       if (Checksum != 0) {\r
         Error (NULL, 0, 0003, "error parsing FFS file", "FFS file with Guid %s has invalid file checksum", GuidBuffer);\r
       Checksum  = Checksum + FileHeader->IntegrityCheck.Checksum.File;\r
       if (Checksum != 0) {\r
         Error (NULL, 0, 0003, "error parsing FFS file", "FFS file with Guid %s has invalid file checksum", GuidBuffer);\r
@@ -1079,7 +1219,7 @@ Returns:
         return EFI_ABORTED;\r
       }\r
     }\r
         return EFI_ABORTED;\r
       }\r
     }\r
-#if (PI_SPECIFICATION_VERSION < 0x00010000)    \r
+#if (PI_SPECIFICATION_VERSION < 0x00010000)\r
     //\r
     // Verify tail if present\r
     //\r
     //\r
     // Verify tail if present\r
     //\r
@@ -1094,7 +1234,7 @@ Returns:
         return EFI_ABORTED;\r
       }\r
     }\r
         return EFI_ABORTED;\r
       }\r
     }\r
- #endif   \r
+ #endif\r
     break;\r
 \r
   default:\r
     break;\r
 \r
   default:\r
@@ -1158,6 +1298,14 @@ Returns:
     printf ("EFI_FV_FILETYPE_SMM_CORE\n");\r
     break;\r
 \r
     printf ("EFI_FV_FILETYPE_SMM_CORE\n");\r
     break;\r
 \r
+  case EFI_FV_FILETYPE_MM_STANDALONE:\r
+    printf ("EFI_FV_FILETYPE_MM_STANDALONE\n");\r
+    break;\r
+\r
+  case EFI_FV_FILETYPE_MM_CORE_STANDALONE:\r
+    printf ("EFI_FV_FILETYPE_MM_CORE_STANDALONE\n");\r
+    break;\r
+\r
   case EFI_FV_FILETYPE_FFS_PAD:\r
     printf ("EFI_FV_FILETYPE_FFS_PAD\n");\r
     break;\r
   case EFI_FV_FILETYPE_FFS_PAD:\r
     printf ("EFI_FV_FILETYPE_FFS_PAD\n");\r
     break;\r
@@ -1180,8 +1328,8 @@ Returns:
     // All other files have sections\r
     //\r
     Status = ParseSection (\r
     // All other files have sections\r
     //\r
     Status = ParseSection (\r
-              (UINT8 *) ((UINTN) FileHeader + sizeof (EFI_FFS_FILE_HEADER)),\r
-              GetLength (FileHeader->Size) - sizeof (EFI_FFS_FILE_HEADER)\r
+              (UINT8 *) ((UINTN) FileHeader + HeaderSize),\r
+              FvBufGetFfsFileSize (FileHeader) - HeaderSize\r
               );\r
     if (EFI_ERROR (Status)) {\r
       //\r
               );\r
     if (EFI_ERROR (Status)) {\r
       //\r
@@ -1195,6 +1343,280 @@ Returns:
   return EFI_SUCCESS;\r
 }\r
 \r
   return EFI_SUCCESS;\r
 }\r
 \r
+EFI_STATUS\r
+RebaseImageRead (\r
+  IN     VOID    *FileHandle,\r
+  IN     UINTN   FileOffset,\r
+  IN OUT UINT32  *ReadSize,\r
+  OUT    VOID    *Buffer\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file\r
+\r
+Arguments:\r
+\r
+  FileHandle - The handle to the PE/COFF file\r
+\r
+  FileOffset - The offset, in bytes, into the file to read\r
+\r
+  ReadSize   - The number of bytes to read from the file starting at FileOffset\r
+\r
+  Buffer     - A pointer to the buffer to read the data into.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset\r
+\r
+--*/\r
+{\r
+  CHAR8   *Destination8;\r
+  CHAR8   *Source8;\r
+  UINT32  Length;\r
+\r
+  Destination8  = Buffer;\r
+  Source8       = (CHAR8 *) ((UINTN) FileHandle + FileOffset);\r
+  Length        = *ReadSize;\r
+  while (Length--) {\r
+    *(Destination8++) = *(Source8++);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+SetAddressToSectionHeader (\r
+  IN     CHAR8   *FileName,\r
+  IN OUT UINT8   *FileBuffer,\r
+  IN     UINT64  NewPe32BaseAddress\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Set new base address into the section header of PeImage\r
+\r
+Arguments:\r
+\r
+  FileName           - Name of file\r
+  FileBuffer         - Pointer to PeImage.\r
+  NewPe32BaseAddress - New Base Address for PE image.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS          Set new base address into this image successfully.\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                            Status;\r
+  PE_COFF_LOADER_IMAGE_CONTEXT          ImageContext;\r
+  UINTN                                 Index;\r
+  EFI_IMAGE_OPTIONAL_HEADER_UNION       *ImgHdr;\r
+  EFI_IMAGE_SECTION_HEADER              *SectionHeader;\r
+\r
+  //\r
+  // Initialize context\r
+  //\r
+  memset (&ImageContext, 0, sizeof (ImageContext));\r
+  ImageContext.Handle     = (VOID *) FileBuffer;\r
+  ImageContext.ImageRead  = (PE_COFF_LOADER_READ_FILE) RebaseImageRead;\r
+  Status                  = PeCoffLoaderGetImageInfo (&ImageContext);\r
+  if (EFI_ERROR (Status)) {\r
+    Error (NULL, 0, 3000, "Invalid", "The input PeImage %s is not valid", FileName);\r
+    return Status;\r
+  }\r
+\r
+  if (ImageContext.RelocationsStripped) {\r
+    Error (NULL, 0, 3000, "Invalid", "The input PeImage %s has no relocation to be fixed up", FileName);\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Get PeHeader pointer\r
+  //\r
+  ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer + ImageContext.PeCoffHeaderOffset);\r
+\r
+  //\r
+  // Get section header list\r
+  //\r
+  SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (\r
+    (UINTN) ImgHdr +\r
+    sizeof (UINT32) +\r
+    sizeof (EFI_IMAGE_FILE_HEADER) +\r
+    ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader\r
+    );\r
+\r
+  //\r
+  // Set base address into the first section header that doesn't point to code section.\r
+  //\r
+  for (Index = 0; Index < ImgHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) {\r
+    if ((SectionHeader->Characteristics & EFI_IMAGE_SCN_CNT_CODE) == 0) {\r
+      *(UINT64 *) &SectionHeader->PointerToRelocations = NewPe32BaseAddress;\r
+      break;\r
+    }\r
+  }\r
+\r
+  //\r
+  // BaseAddress is set to section header.\r
+  //\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+RebaseImage (\r
+  IN     CHAR8   *FileName,\r
+  IN OUT UINT8   *FileBuffer,\r
+  IN     UINT64  NewPe32BaseAddress\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Set new base address into PeImage, and fix up PeImage based on new address.\r
+\r
+Arguments:\r
+\r
+  FileName           - Name of file\r
+  FileBuffer         - Pointer to PeImage.\r
+  NewPe32BaseAddress - New Base Address for PE image.\r
+\r
+Returns:\r
+\r
+  EFI_INVALID_PARAMETER   - BaseAddress is not valid.\r
+  EFI_SUCCESS             - Update PeImage is correctly.\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                            Status;\r
+  PE_COFF_LOADER_IMAGE_CONTEXT          ImageContext;\r
+  UINTN                                 Index;\r
+  EFI_IMAGE_OPTIONAL_HEADER_UNION       *ImgHdr;\r
+  UINT8                                 *MemoryImagePointer;\r
+  EFI_IMAGE_SECTION_HEADER              *SectionHeader;\r
+\r
+  //\r
+  // Initialize context\r
+  //\r
+  memset (&ImageContext, 0, sizeof (ImageContext));\r
+  ImageContext.Handle     = (VOID *) FileBuffer;\r
+  ImageContext.ImageRead  = (PE_COFF_LOADER_READ_FILE) RebaseImageRead;\r
+  Status                  = PeCoffLoaderGetImageInfo (&ImageContext);\r
+  if (EFI_ERROR (Status)) {\r
+    Error (NULL, 0, 3000, "Invalid", "The input PeImage %s is not valid", FileName);\r
+    return Status;\r
+  }\r
+\r
+  if (ImageContext.RelocationsStripped) {\r
+    Error (NULL, 0, 3000, "Invalid", "The input PeImage %s has no relocation to be fixed up", FileName);\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Get PeHeader pointer\r
+  //\r
+  ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer + ImageContext.PeCoffHeaderOffset);\r
+\r
+  //\r
+  // Load and Relocate Image Data\r
+  //\r
+  MemoryImagePointer = (UINT8 *) malloc ((UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment);\r
+  if (MemoryImagePointer == NULL) {\r
+    Error (NULL, 0, 4001, "Resource", "memory cannot be allocated on rebase of %s", FileName);\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  memset ((VOID *) MemoryImagePointer, 0, (UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment);\r
+  ImageContext.ImageAddress = ((UINTN) MemoryImagePointer + ImageContext.SectionAlignment - 1) & (~((INT64)ImageContext.SectionAlignment - 1));\r
+\r
+  Status =  PeCoffLoaderLoadImage (&ImageContext);\r
+  if (EFI_ERROR (Status)) {\r
+    Error (NULL, 0, 3000, "Invalid", "LocateImage() call failed on rebase of %s", FileName);\r
+    free ((VOID *) MemoryImagePointer);\r
+    return Status;\r
+  }\r
+\r
+  ImageContext.DestinationAddress = NewPe32BaseAddress;\r
+  Status                          = PeCoffLoaderRelocateImage (&ImageContext);\r
+  if (EFI_ERROR (Status)) {\r
+    Error (NULL, 0, 3000, "Invalid", "RelocateImage() call failed on rebase of %s", FileName);\r
+    free ((VOID *) MemoryImagePointer);\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Copy Relocated data to raw image file.\r
+  //\r
+  SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (\r
+    (UINTN) ImgHdr +\r
+    sizeof (UINT32) +\r
+    sizeof (EFI_IMAGE_FILE_HEADER) +\r
+    ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader\r
+    );\r
+\r
+  for (Index = 0; Index < ImgHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) {\r
+    CopyMem (\r
+      FileBuffer + SectionHeader->PointerToRawData,\r
+      (VOID*) (UINTN) (ImageContext.ImageAddress + SectionHeader->VirtualAddress),\r
+      SectionHeader->SizeOfRawData\r
+      );\r
+  }\r
+\r
+  free ((VOID *) MemoryImagePointer);\r
+\r
+  //\r
+  // Update Image Base Address\r
+  //\r
+  if (ImgHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+    ImgHdr->Pe32.OptionalHeader.ImageBase = (UINT32) NewPe32BaseAddress;\r
+  } else if (ImgHdr->Pe32Plus.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
+    ImgHdr->Pe32Plus.OptionalHeader.ImageBase = NewPe32BaseAddress;\r
+  } else {\r
+    Error (NULL, 0, 3000, "Invalid", "unknown PE magic signature %X in PE32 image %s",\r
+      ImgHdr->Pe32.OptionalHeader.Magic,\r
+      FileName\r
+      );\r
+    return EFI_ABORTED;\r
+  }\r
+\r
+  //\r
+  // Set new base address into section header\r
+  //\r
+  Status = SetAddressToSectionHeader (FileName, FileBuffer, NewPe32BaseAddress);\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+CombinePath (\r
+  IN  CHAR8* DefaultPath,\r
+  IN  CHAR8* AppendPath,\r
+  OUT CHAR8* NewPath\r
+)\r
+{\r
+  UINT32 DefaultPathLen;\r
+  UINT64 Index;\r
+  CHAR8  QuotesStr[] = "\"";\r
+  strcpy(NewPath, QuotesStr);\r
+  DefaultPathLen = strlen(DefaultPath);\r
+  strcat(NewPath, DefaultPath);\r
+  Index = 0;\r
+  for (; Index < DefaultPathLen + 1; Index ++) {\r
+    if (NewPath[Index] == '\\' || NewPath[Index] == '/') {\r
+      if (NewPath[Index + 1] != '\0') {\r
+        NewPath[Index] = '/';\r
+      }\r
+    }\r
+  }\r
+  if (NewPath[Index -1] != '/') {\r
+    NewPath[Index] = '/';\r
+    NewPath[Index + 1] = '\0';\r
+  }\r
+  strcat(NewPath, AppendPath);\r
+  strcat(NewPath, QuotesStr);\r
+  return EFI_SUCCESS;\r
+}\r
+\r
 EFI_STATUS\r
 ParseSection (\r
   IN UINT8  *SectionBuffer,\r
 EFI_STATUS\r
 ParseSection (\r
   IN UINT8  *SectionBuffer,\r
@@ -1215,7 +1637,7 @@ Returns:
 \r
   EFI_SECTION_ERROR - Problem with section parsing.\r
                       (a) compression errors\r
 \r
   EFI_SECTION_ERROR - Problem with section parsing.\r
                       (a) compression errors\r
-                      (b) unrecognized section \r
+                      (b) unrecognized section\r
   EFI_UNSUPPORTED - Do not know how to parse the section.\r
   EFI_SUCCESS - Section successfully parsed.\r
   EFI_OUT_OF_RESOURCES - Memory allocation failed.\r
   EFI_UNSUPPORTED - Do not know how to parse the section.\r
   EFI_SUCCESS - Section successfully parsed.\r
   EFI_OUT_OF_RESOURCES - Memory allocation failed.\r
@@ -1225,6 +1647,7 @@ Returns:
   EFI_SECTION_TYPE    Type;\r
   UINT8               *Ptr;\r
   UINT32              SectionLength;\r
   EFI_SECTION_TYPE    Type;\r
   UINT8               *Ptr;\r
   UINT32              SectionLength;\r
+  UINT32              SectionHeaderLen;\r
   CHAR8               *SectionName;\r
   EFI_STATUS          Status;\r
   UINT32              ParsedLength;\r
   CHAR8               *SectionName;\r
   EFI_STATUS          Status;\r
   UINT32              ParsedLength;\r
@@ -1244,10 +1667,19 @@ Returns:
   CHAR8               *ExtractionTool;\r
   CHAR8               *ToolInputFile;\r
   CHAR8               *ToolOutputFile;\r
   CHAR8               *ExtractionTool;\r
   CHAR8               *ToolInputFile;\r
   CHAR8               *ToolOutputFile;\r
-  CHAR8               *SystemCommandFormatString;\r
   CHAR8               *SystemCommand;\r
   CHAR8               *SystemCommand;\r
+  EFI_GUID            *EfiGuid;\r
+  UINT16              DataOffset;\r
+  UINT16              Attributes;\r
+  UINT32              RealHdrLen;\r
+  CHAR8               *ToolInputFileName;\r
+  CHAR8               *ToolOutputFileName;\r
+  CHAR8               *UIFileName;\r
 \r
   ParsedLength = 0;\r
 \r
   ParsedLength = 0;\r
+  ToolInputFileName = NULL;\r
+  ToolOutputFileName = NULL;\r
+\r
   while (ParsedLength < BufferLength) {\r
     Ptr           = SectionBuffer + ParsedLength;\r
 \r
   while (ParsedLength < BufferLength) {\r
     Ptr           = SectionBuffer + ParsedLength;\r
 \r
@@ -1264,26 +1696,105 @@ Returns:
       continue;\r
     }\r
 \r
       continue;\r
     }\r
 \r
+    //\r
+    // Get real section file size\r
+    //\r
+    SectionLength = GetSectionFileLength ((EFI_COMMON_SECTION_HEADER *) Ptr);\r
+    SectionHeaderLen = GetSectionHeaderLength((EFI_COMMON_SECTION_HEADER *)Ptr);\r
+\r
     SectionName = SectionNameToStr (Type);\r
     SectionName = SectionNameToStr (Type);\r
-    printf ("------------------------------------------------------------\n");\r
-    printf ("  Type:  %s\n  Size:  0x%08X\n", SectionName, (unsigned) SectionLength);\r
-    free (SectionName);\r
+    if (SectionName != NULL) {\r
+      printf ("------------------------------------------------------------\n");\r
+      printf ("  Type:  %s\n  Size:  0x%08X\n", SectionName, (unsigned) SectionLength);\r
+      free (SectionName);\r
+    }\r
 \r
     switch (Type) {\r
     case EFI_SECTION_RAW:\r
 \r
     switch (Type) {\r
     case EFI_SECTION_RAW:\r
-    case EFI_SECTION_PE32:\r
     case EFI_SECTION_PIC:\r
     case EFI_SECTION_TE:\r
       // default is no more information\r
       break;\r
 \r
     case EFI_SECTION_PIC:\r
     case EFI_SECTION_TE:\r
       // default is no more information\r
       break;\r
 \r
+    case EFI_SECTION_PE32:\r
+      if (EnableHash) {\r
+        ToolInputFileName  = "edk2Temp_InputEfi.tmp";\r
+        ToolOutputFileName = "edk2Temp_OutputHash.tmp";\r
+        RebaseImage(ToolInputFileName, (UINT8*)Ptr + SectionHeaderLen, 0);\r
+        PutFileImage (\r
+          ToolInputFileName,\r
+          (CHAR8*)Ptr + SectionHeaderLen,\r
+          SectionLength - SectionHeaderLen\r
+          );\r
+\r
+        SystemCommand = malloc (\r
+          strlen (OPENSSL_COMMAND_FORMAT_STRING) +\r
+          strlen (OpenSslPath) +\r
+          strlen (ToolInputFileName) +\r
+          strlen (ToolOutputFileName) +\r
+          1\r
+          );\r
+        if (SystemCommand == NULL) {\r
+          Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
+          return EFI_OUT_OF_RESOURCES;\r
+        }\r
+        sprintf (\r
+          SystemCommand,\r
+          OPENSSL_COMMAND_FORMAT_STRING,\r
+          OpenSslPath,\r
+          ToolOutputFileName,\r
+          ToolInputFileName\r
+          );\r
+\r
+        if (system (SystemCommand) != EFI_SUCCESS) {\r
+          Error (NULL, 0, 3000, "Open SSL command not available.  Please verify PATH or set OPENSSL_PATH.", NULL);\r
+        }\r
+        else {\r
+          FILE *fp;\r
+          CHAR8 *StrLine;\r
+          CHAR8 *NewStr;\r
+          UINT32 nFileLen;\r
+          if((fp = fopen(ToolOutputFileName,"r")) == NULL) {\r
+            Error (NULL, 0, 0004, "Hash the PE32 image failed.", NULL);\r
+          }\r
+          else {\r
+            fseek(fp,0,SEEK_SET);\r
+            fseek(fp,0,SEEK_END);\r
+            nFileLen = ftell(fp);\r
+            fseek(fp,0,SEEK_SET);\r
+            StrLine = malloc(nFileLen);\r
+            if (StrLine == NULL) {\r
+              fclose(fp);\r
+              free (SystemCommand);\r
+              Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
+              return EFI_OUT_OF_RESOURCES;\r
+            }\r
+            fgets(StrLine, nFileLen, fp);\r
+            NewStr = strrchr (StrLine, '=');\r
+            printf ("  SHA1: %s\n", NewStr + 1);\r
+            free (StrLine);\r
+            fclose(fp);\r
+          }\r
+        }\r
+        remove(ToolInputFileName);\r
+        remove(ToolOutputFileName);\r
+        free (SystemCommand);\r
+      }\r
+      break;\r
+\r
     case EFI_SECTION_USER_INTERFACE:\r
     case EFI_SECTION_USER_INTERFACE:\r
-      // name = &((EFI_USER_INTERFACE_SECTION *) Ptr)->FileNameString;\r
-      // printf ("  String: %s\n", &name);\r
+      UIFileName = (CHAR8 *) malloc (UnicodeStrLen (((EFI_USER_INTERFACE_SECTION *) Ptr)->FileNameString) + 1);\r
+      if (UIFileName == NULL) {\r
+        Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
+        return EFI_OUT_OF_RESOURCES;\r
+      }\r
+      Unicode2AsciiString (((EFI_USER_INTERFACE_SECTION *) Ptr)->FileNameString, UIFileName);\r
+      printf ("  String: %s\n", UIFileName);\r
+      free (UIFileName);\r
       break;\r
 \r
     case EFI_SECTION_FIRMWARE_VOLUME_IMAGE:\r
       break;\r
 \r
     case EFI_SECTION_FIRMWARE_VOLUME_IMAGE:\r
-      Status = PrintFvInfo (((EFI_FIRMWARE_VOLUME_IMAGE_SECTION*)Ptr) + 1, TRUE);\r
+      Status = PrintFvInfo (Ptr + SectionHeaderLen, TRUE);\r
       if (EFI_ERROR (Status)) {\r
         Error (NULL, 0, 0003, "printing of FV section contents failed", NULL);\r
         return EFI_SECTION_ERROR;\r
       if (EFI_ERROR (Status)) {\r
         Error (NULL, 0, 0003, "printing of FV section contents failed", NULL);\r
         return EFI_SECTION_ERROR;\r
@@ -1304,15 +1815,22 @@ Returns:
       break;\r
 \r
     case EFI_SECTION_VERSION:\r
       break;\r
 \r
     case EFI_SECTION_VERSION:\r
-      printf ("  Build Number:  0x%02X\n", ((EFI_VERSION_SECTION *) Ptr)->BuildNumber);\r
-      printf ("  Version Strg:  %s\n", (char*) ((EFI_VERSION_SECTION *) Ptr)->VersionString);\r
+      printf ("  Build Number:  0x%02X\n", *(UINT16 *)(Ptr + SectionHeaderLen));\r
+      printf ("  Version Strg:  %s\n", (char*) (Ptr + SectionHeaderLen + sizeof (UINT16)));\r
       break;\r
 \r
     case EFI_SECTION_COMPRESSION:\r
       UncompressedBuffer  = NULL;\r
       break;\r
 \r
     case EFI_SECTION_COMPRESSION:\r
       UncompressedBuffer  = NULL;\r
-      CompressedLength    = SectionLength - sizeof (EFI_COMPRESSION_SECTION);\r
-      UncompressedLength  = ((EFI_COMPRESSION_SECTION *) Ptr)->UncompressedLength;\r
-      CompressionType     = ((EFI_COMPRESSION_SECTION *) Ptr)->CompressionType;\r
+      if (SectionHeaderLen == sizeof (EFI_COMMON_SECTION_HEADER)) {\r
+        RealHdrLen = sizeof(EFI_COMPRESSION_SECTION);\r
+        UncompressedLength  = ((EFI_COMPRESSION_SECTION *)Ptr)->UncompressedLength;\r
+        CompressionType     = ((EFI_COMPRESSION_SECTION *)Ptr)->CompressionType;\r
+      } else {\r
+        RealHdrLen = sizeof(EFI_COMPRESSION_SECTION2);\r
+        UncompressedLength  = ((EFI_COMPRESSION_SECTION2 *)Ptr)->UncompressedLength;\r
+        CompressionType     = ((EFI_COMPRESSION_SECTION2 *)Ptr)->CompressionType;\r
+      }\r
+      CompressedLength    = SectionLength - RealHdrLen;\r
       printf ("  Uncompressed Length:  0x%08X\n", (unsigned) UncompressedLength);\r
 \r
       if (CompressionType == EFI_NOT_COMPRESSED) {\r
       printf ("  Uncompressed Length:  0x%08X\n", (unsigned) UncompressedLength);\r
 \r
       if (CompressionType == EFI_NOT_COMPRESSED) {\r
@@ -1328,13 +1846,13 @@ Returns:
           return EFI_SECTION_ERROR;\r
         }\r
 \r
           return EFI_SECTION_ERROR;\r
         }\r
 \r
-        UncompressedBuffer = Ptr + sizeof (EFI_COMPRESSION_SECTION);\r
+        UncompressedBuffer = Ptr + RealHdrLen;\r
       } else if (CompressionType == EFI_STANDARD_COMPRESSION) {\r
         GetInfoFunction     = EfiGetInfo;\r
         DecompressFunction  = EfiDecompress;\r
         printf ("  Compression Type:  EFI_STANDARD_COMPRESSION\n");\r
 \r
       } else if (CompressionType == EFI_STANDARD_COMPRESSION) {\r
         GetInfoFunction     = EfiGetInfo;\r
         DecompressFunction  = EfiDecompress;\r
         printf ("  Compression Type:  EFI_STANDARD_COMPRESSION\n");\r
 \r
-        CompressedBuffer  = Ptr + sizeof (EFI_COMPRESSION_SECTION);\r
+        CompressedBuffer  = Ptr + RealHdrLen;\r
 \r
         Status            = GetInfoFunction (CompressedBuffer, CompressedLength, &DstSize, &ScratchSize);\r
         if (EFI_ERROR (Status)) {\r
 \r
         Status            = GetInfoFunction (CompressedBuffer, CompressedLength, &DstSize, &ScratchSize);\r
         if (EFI_ERROR (Status)) {\r
@@ -1348,8 +1866,14 @@ Returns:
         }\r
 \r
         ScratchBuffer       = malloc (ScratchSize);\r
         }\r
 \r
         ScratchBuffer       = malloc (ScratchSize);\r
+        if (ScratchBuffer == NULL) {\r
+          Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
+          return EFI_OUT_OF_RESOURCES;\r
+        }\r
         UncompressedBuffer  = malloc (UncompressedLength);\r
         UncompressedBuffer  = malloc (UncompressedLength);\r
-        if ((ScratchBuffer == NULL) || (UncompressedBuffer == NULL)) {\r
+        if (UncompressedBuffer == NULL) {\r
+          free (ScratchBuffer);\r
+          Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
           return EFI_OUT_OF_RESOURCES;\r
         }\r
         Status = DecompressFunction (\r
           return EFI_OUT_OF_RESOURCES;\r
         }\r
         Status = DecompressFunction (\r
@@ -1387,37 +1911,78 @@ Returns:
       break;\r
 \r
     case EFI_SECTION_GUID_DEFINED:\r
       break;\r
 \r
     case EFI_SECTION_GUID_DEFINED:\r
+      if (SectionHeaderLen == sizeof(EFI_COMMON_SECTION_HEADER)) {\r
+        EfiGuid = &((EFI_GUID_DEFINED_SECTION *) Ptr)->SectionDefinitionGuid;\r
+        DataOffset = ((EFI_GUID_DEFINED_SECTION *) Ptr)->DataOffset;\r
+        Attributes = ((EFI_GUID_DEFINED_SECTION *) Ptr)->Attributes;\r
+      } else {\r
+        EfiGuid = &((EFI_GUID_DEFINED_SECTION2 *) Ptr)->SectionDefinitionGuid;\r
+        DataOffset = ((EFI_GUID_DEFINED_SECTION2 *) Ptr)->DataOffset;\r
+        Attributes = ((EFI_GUID_DEFINED_SECTION2 *) Ptr)->Attributes;\r
+      }\r
       printf ("  SectionDefinitionGuid:  ");\r
       printf ("  SectionDefinitionGuid:  ");\r
-      PrintGuid (&((EFI_GUID_DEFINED_SECTION *) Ptr)->SectionDefinitionGuid);\r
+      PrintGuid (EfiGuid);\r
       printf ("\n");\r
       printf ("\n");\r
-      printf ("  DataOffset:             0x%04X\n", (unsigned) ((EFI_GUID_DEFINED_SECTION *) Ptr)->DataOffset);\r
-      printf ("  Attributes:             0x%04X\n", (unsigned) ((EFI_GUID_DEFINED_SECTION *) Ptr)->Attributes);\r
+      printf ("  DataOffset:             0x%04X\n", (unsigned) DataOffset);\r
+      printf ("  Attributes:             0x%04X\n", (unsigned) Attributes);\r
 \r
       ExtractionTool =\r
         LookupGuidedSectionToolPath (\r
           mParsedGuidedSectionTools,\r
 \r
       ExtractionTool =\r
         LookupGuidedSectionToolPath (\r
           mParsedGuidedSectionTools,\r
-          &((EFI_GUID_DEFINED_SECTION *) Ptr)->SectionDefinitionGuid\r
+          EfiGuid\r
           );\r
 \r
       if (ExtractionTool != NULL) {\r
           );\r
 \r
       if (ExtractionTool != NULL) {\r
-\r
+       #ifndef __GNUC__\r
         ToolInputFile = CloneString (tmpnam (NULL));\r
         ToolOutputFile = CloneString (tmpnam (NULL));\r
         ToolInputFile = CloneString (tmpnam (NULL));\r
         ToolOutputFile = CloneString (tmpnam (NULL));\r
+       #else\r
+        char tmp1[] = "/tmp/fileXXXXXX";\r
+        char tmp2[] = "/tmp/fileXXXXXX";\r
+        int fd1;\r
+        int fd2;\r
+        fd1 = mkstemp(tmp1);\r
+        fd2 = mkstemp(tmp2);\r
+        ToolInputFile = CloneString(tmp1);\r
+        ToolOutputFile = CloneString(tmp2);\r
+        close(fd1);\r
+        close(fd2);\r
+       #endif\r
+\r
+        if ((ToolInputFile == NULL) || (ToolOutputFile == NULL)) {\r
+          if (ToolInputFile != NULL) {\r
+            free (ToolInputFile);\r
+          }\r
+          if (ToolOutputFile != NULL) {\r
+            free (ToolOutputFile);\r
+          }\r
+          free (ExtractionTool);\r
+\r
+          Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
+          return EFI_OUT_OF_RESOURCES;\r
+        }\r
 \r
         //\r
         // Construction 'system' command string\r
         //\r
 \r
         //\r
         // Construction 'system' command string\r
         //\r
-        SystemCommandFormatString = "%s -d -o %s %s";\r
         SystemCommand = malloc (\r
         SystemCommand = malloc (\r
-          strlen (SystemCommandFormatString) +\r
+          strlen (EXTRACT_COMMAND_FORMAT_STRING) +\r
           strlen (ExtractionTool) +\r
           strlen (ToolInputFile) +\r
           strlen (ToolOutputFile) +\r
           1\r
           );\r
           strlen (ExtractionTool) +\r
           strlen (ToolInputFile) +\r
           strlen (ToolOutputFile) +\r
           1\r
           );\r
+        if (SystemCommand == NULL) {\r
+          free (ToolInputFile);\r
+          free (ToolOutputFile);\r
+          free (ExtractionTool);\r
+\r
+          Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
+          return EFI_OUT_OF_RESOURCES;\r
+        }\r
         sprintf (\r
           SystemCommand,\r
         sprintf (\r
           SystemCommand,\r
-          SystemCommandFormatString,\r
+          EXTRACT_COMMAND_FORMAT_STRING,\r
           ExtractionTool,\r
           ToolOutputFile,\r
           ToolInputFile\r
           ExtractionTool,\r
           ToolOutputFile,\r
           ToolInputFile\r
@@ -1427,8 +1992,8 @@ Returns:
         Status =\r
           PutFileImage (\r
             ToolInputFile,\r
         Status =\r
           PutFileImage (\r
             ToolInputFile,\r
-            (CHAR8*) SectionBuffer + ((EFI_GUID_DEFINED_SECTION *) Ptr)->DataOffset,\r
-            BufferLength - ((EFI_GUID_DEFINED_SECTION *) Ptr)->DataOffset\r
+            (CHAR8*) SectionBuffer + DataOffset,\r
+            BufferLength - DataOffset\r
             );\r
 \r
         system (SystemCommand);\r
             );\r
 \r
         system (SystemCommand);\r
@@ -1443,6 +2008,7 @@ Returns:
             );\r
         remove (ToolOutputFile);\r
         free (ToolOutputFile);\r
             );\r
         remove (ToolOutputFile);\r
         free (ToolOutputFile);\r
+        free (SystemCommand);\r
         if (EFI_ERROR (Status)) {\r
           Error (NULL, 0, 0004, "unable to read decoded GUIDED section", NULL);\r
           return EFI_SECTION_ERROR;\r
         if (EFI_ERROR (Status)) {\r
           Error (NULL, 0, 0004, "unable to read decoded GUIDED section", NULL);\r
           return EFI_SECTION_ERROR;\r
@@ -1461,7 +2027,7 @@ Returns:
       // Check for CRC32 sections which we can handle internally if needed.\r
       //\r
       } else if (!CompareGuid (\r
       // Check for CRC32 sections which we can handle internally if needed.\r
       //\r
       } else if (!CompareGuid (\r
-                   &((EFI_GUID_DEFINED_SECTION *) Ptr)->SectionDefinitionGuid,\r
+                   EfiGuid,\r
                    &gEfiCrc32GuidedSectionExtractionProtocolGuid\r
                    )\r
           ) {\r
                    &gEfiCrc32GuidedSectionExtractionProtocolGuid\r
                    )\r
           ) {\r
@@ -1469,8 +2035,8 @@ Returns:
         // CRC32 guided section\r
         //\r
         Status = ParseSection (\r
         // CRC32 guided section\r
         //\r
         Status = ParseSection (\r
-                  SectionBuffer + ((EFI_GUID_DEFINED_SECTION *) Ptr)->DataOffset,\r
-                  BufferLength - ((EFI_GUID_DEFINED_SECTION *) Ptr)->DataOffset\r
+                  SectionBuffer + DataOffset,\r
+                  BufferLength - DataOffset\r
                   );\r
         if (EFI_ERROR (Status)) {\r
           Error (NULL, 0, 0003, "parse of CRC32 GUIDED section failed", NULL);\r
                   );\r
         if (EFI_ERROR (Status)) {\r
           Error (NULL, 0, 0003, "parse of CRC32 GUIDED section failed", NULL);\r
@@ -1540,8 +2106,8 @@ Returns:
     return EFI_SUCCESS;\r
   }\r
 \r
     return EFI_SUCCESS;\r
   }\r
 \r
-  Ptr += sizeof (EFI_COMMON_SECTION_HEADER);\r
-  SectionLength -= sizeof (EFI_COMMON_SECTION_HEADER);\r
+  Ptr += GetSectionHeaderLength((EFI_COMMON_SECTION_HEADER *)Ptr);\r
+  SectionLength -= GetSectionHeaderLength((EFI_COMMON_SECTION_HEADER *)Ptr);\r
   while (SectionLength > 0) {\r
     printf ("        ");\r
     switch (*Ptr) {\r
   while (SectionLength > 0) {\r
     printf ("        ");\r
     switch (*Ptr) {\r
@@ -1685,24 +2251,36 @@ Returns:
 {\r
   FILE              *Fptr;\r
   CHAR8             Line[MAX_LINE_LEN];\r
 {\r
   FILE              *Fptr;\r
   CHAR8             Line[MAX_LINE_LEN];\r
+  CHAR8             FormatString[MAX_LINE_LEN];\r
   GUID_TO_BASENAME  *GPtr;\r
 \r
   GUID_TO_BASENAME  *GPtr;\r
 \r
-  if ((Fptr = fopen (FileName, "r")) == NULL) {\r
+  if ((Fptr = fopen (LongFilePath (FileName), "r")) == NULL) {\r
     printf ("ERROR: Failed to open input cross-reference file '%s'\n", FileName);\r
     return EFI_DEVICE_ERROR;\r
   }\r
 \r
     printf ("ERROR: Failed to open input cross-reference file '%s'\n", FileName);\r
     return EFI_DEVICE_ERROR;\r
   }\r
 \r
+  //\r
+  // Generate the format string for fscanf\r
+  //\r
+  sprintf (\r
+    FormatString,\r
+    "%%%us %%%us",\r
+    (unsigned) sizeof (GPtr->Guid) - 1,\r
+    (unsigned) sizeof (GPtr->BaseName) - 1\r
+    );\r
+\r
   while (fgets (Line, sizeof (Line), Fptr) != NULL) {\r
     //\r
     // Allocate space for another guid/basename element\r
     //\r
     GPtr = malloc (sizeof (GUID_TO_BASENAME));\r
     if (GPtr == NULL) {\r
   while (fgets (Line, sizeof (Line), Fptr) != NULL) {\r
     //\r
     // Allocate space for another guid/basename element\r
     //\r
     GPtr = malloc (sizeof (GUID_TO_BASENAME));\r
     if (GPtr == NULL) {\r
+      fclose (Fptr);\r
       return EFI_OUT_OF_RESOURCES;\r
     }\r
 \r
     memset ((char *) GPtr, 0, sizeof (GUID_TO_BASENAME));\r
       return EFI_OUT_OF_RESOURCES;\r
     }\r
 \r
     memset ((char *) GPtr, 0, sizeof (GUID_TO_BASENAME));\r
-    if (sscanf (Line, "%s %s", GPtr->Guid, GPtr->BaseName) == 2) {\r
+    if (sscanf (Line, FormatString, GPtr->Guid, GPtr->BaseName) == 2) {\r
       GPtr->Next        = mGuidBaseNameList;\r
       mGuidBaseNameList = GPtr;\r
     } else {\r
       GPtr->Next        = mGuidBaseNameList;\r
       mGuidBaseNameList = GPtr;\r
     } else {\r
@@ -1808,19 +2386,35 @@ Returns:
 \r
   //\r
   // Copyright declaration\r
 \r
   //\r
   // Copyright declaration\r
-  // \r
-  fprintf (stdout, "Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.\n\n");\r
+  //\r
+  fprintf (stdout, "Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.\n\n");\r
+  fprintf (stdout, "  Display Tiano Firmware Volume FFS image information\n\n");\r
 \r
   //\r
   // Details Option\r
   //\r
 \r
   //\r
   // Details Option\r
   //\r
-  fprintf (stdout, "Options:\n");\r
-  fprintf (stdout, "  -x xref, --xref xref\n\\r
-            Parse basename to file-guid cross reference file(s).\n");\r
-  fprintf (stdout, "  --offset offset\n\\r
-            Offset of file to start processing FV at.\n");\r
+  fprintf (stdout, "optional arguments:\n");\r
   fprintf (stdout, "  -h, --help\n\\r
   fprintf (stdout, "  -h, --help\n\\r
-            Show this help message and exit.\n");\r
-\r
+            Show this help message and exit\n");\r
+  fprintf (stdout, "  --version\n\\r
+           Show program's version number and exit\n");\r
+  fprintf (stdout, "  -d [DEBUG], --debug [DEBUG]\n\\r
+            Output DEBUG statements, where DEBUG_LEVEL is 0 (min) - 9 (max)\n");\r
+  fprintf (stdout, "  -v, --verbose\n\\r
+            Print informational statements\n");\r
+  fprintf (stdout, "  -q, --quiet\n\\r
+            Returns the exit code, error messages will be displayed\n");\r
+  fprintf (stdout, "  -s, --silent\n\\r
+            Returns only the exit code; informational and error\n\\r
+            messages are not displayed\n");\r
+  fprintf (stdout, "  -x XREF_FILENAME, --xref XREF_FILENAME\n\\r
+            Parse the basename to file-guid cross reference file(s)\n");\r
+  fprintf (stdout, "  -f OFFSET, --offset OFFSET\n\\r
+            The offset from the start of the input file to start \n\\r
+            processing an FV\n");\r
+  fprintf (stdout, "  --hash\n\\r
+            Generate HASH value of the entire PE image\n");\r
+  fprintf (stdout, "  --sfo\n\\r
+            Reserved for future use\n");\r
 }\r
 \r
 }\r
 \r