]> git.proxmox.com Git - mirror_edk2.git/blobdiff - BaseTools/Source/C/VolInfo/VolInfo.c
BaseTools/VolInfo: Correct EFI_SECTION_VERSION display
[mirror_edk2.git] / BaseTools / Source / C / VolInfo / VolInfo.c
index 537cea3cfe56d95656d4c601308f18deb243abff..ed56587058f74319dad55778fe61ef796cf05981 100644 (file)
@@ -1,21 +1,8 @@
 /** @file\r
+The tool dumps the contents of a firmware volume\r
 \r
-Copyright (c) 1999 - 2014, 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
@@ -24,6 +11,11 @@ Abstract:
 #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
@@ -43,6 +35,8 @@ Abstract:
 #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
@@ -50,8 +44,8 @@ Abstract:
 \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
@@ -77,6 +71,9 @@ EFI_HANDLE mParsedGuidedSectionTools = NULL;
 \r
 CHAR8* mUtilityFilename = NULL;\r
 \r
+BOOLEAN EnableHash = FALSE;\r
+CHAR8 *OpenSslPath = NULL;\r
+\r
 EFI_STATUS\r
 ParseGuidBaseNameFile (\r
   CHAR8    *FileName\r
@@ -133,11 +130,77 @@ LoadGuidedSectionToolsTxt (
   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
+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
@@ -167,41 +230,61 @@ Returns:
   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
-  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
-    __BUILD_VERSION,\r
-    __DATE__\r
+    __BUILD_VERSION\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
-\r
+  LogLevel = 0;\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
-  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
-    } else if (strcmp(argv[0], "--offset") == 0) {\r
+      continue;\r
+    }\r
+    if (strcmp(argv[0], "--offset") == 0) {\r
       //\r
       // Hex or decimal?\r
       //\r
@@ -225,33 +308,88 @@ Returns:
 \r
       argc -= 2;\r
       argv += 2;\r
-    } else {\r
-      Usage ();\r
-      return -1;\r
+      continue;\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
-  InputFile = fopen (LongFilePath (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
-    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
@@ -266,7 +404,7 @@ Returns:
   //\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
@@ -286,12 +424,12 @@ Returns:
   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
-  LoadGuidedSectionToolsTxt (argv[0]);\r
+  LoadGuidedSectionToolsTxt (mUtilityFilename);\r
 \r
   PrintFvInfo (FvImage, FALSE);\r
 \r
@@ -397,16 +535,16 @@ GetOccupiedSize (
 \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
-    \r
+\r
 Returns:\r
\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
-    "EFI_SECTION_GUID_DEFINED",    \r
+    "EFI_SECTION_GUID_DEFINED",\r
     //\r
     // 0x03\r
     //\r
@@ -520,11 +658,11 @@ Returns:
     //\r
     // 0x12\r
     //\r
-    "EFI_SECTION_TE",    \r
+    "EFI_SECTION_TE",\r
     //\r
     // 0x13\r
     //\r
-    "EFI_SECTION_DXE_DEPEX", \r
+    "EFI_SECTION_DXE_DEPEX",\r
     //\r
     // 0x14\r
     //\r
@@ -591,7 +729,7 @@ ReadHeader (
 \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
@@ -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
-    \r
+\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
@@ -613,6 +751,7 @@ Returns:
   UINTN                       Signature[2];\r
   UINTN                       BytesRead;\r
   UINT32                      Size;\r
+  size_t                      ReadSize;\r
 \r
   BytesRead = 0;\r
   Size      = 0;\r
@@ -626,7 +765,10 @@ Returns:
   //\r
   // Read the header\r
   //\r
-  fread (&VolumeHeader, sizeof (EFI_FIRMWARE_VOLUME_HEADER) - sizeof (EFI_FV_BLOCK_MAP_ENTRY), 1, InputFile);\r
+  ReadSize = fread (&VolumeHeader, sizeof (EFI_FIRMWARE_VOLUME_HEADER) - sizeof (EFI_FV_BLOCK_MAP_ENTRY), 1, InputFile);\r
+  if (ReadSize != 1) {\r
+    return EFI_ABORTED;\r
+  }\r
   BytesRead     = sizeof (EFI_FIRMWARE_VOLUME_HEADER) - sizeof (EFI_FV_BLOCK_MAP_ENTRY);\r
   Signature[0]  = VolumeHeader.Signature;\r
   Signature[1]  = 0;\r
@@ -750,7 +892,7 @@ Returns:
   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
@@ -769,140 +911,134 @@ Returns:
     printf ("       EFI_FVB2_WRITE_LOCK_STATUS\n");\r
   }\r
 \r
-  if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_1) {\r
+  switch (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT) {\r
+    case EFI_FVB2_ALIGNMENT_1:\r
     printf ("       EFI_FVB2_ALIGNMENT_1\n");\r
-  }\r
-\r
-  if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_2) {\r
-    printf ("        EFI_FVB2_ALIGNMENT_2\n");\r
-  }\r
-\r
-  if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_4) {\r
-    printf ("        EFI_FVB2_ALIGNMENT_4\n");\r
-  }\r
+    break;\r
 \r
-  if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_8) {\r
-    printf ("        EFI_FVB2_ALIGNMENT_8\n");\r
-  }\r
+    case EFI_FVB2_ALIGNMENT_2:\r
+    printf ("       EFI_FVB2_ALIGNMENT_2\n");\r
+    break;\r
 \r
-  if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_16) {\r
-    printf ("        EFI_FVB2_ALIGNMENT_16\n");\r
-  }\r
+    case EFI_FVB2_ALIGNMENT_4:\r
+    printf ("       EFI_FVB2_ALIGNMENT_4\n");\r
+    break;\r
 \r
-  if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_32) {\r
-    printf ("        EFI_FVB2_ALIGNMENT_32\n");\r
-  }\r
+    case EFI_FVB2_ALIGNMENT_8:\r
+    printf ("       EFI_FVB2_ALIGNMENT_8\n");\r
+    break;\r
 \r
-  if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_64) {\r
-    printf ("        EFI_FVB2_ALIGNMENT_64\n");\r
-  }\r
+    case EFI_FVB2_ALIGNMENT_16:\r
+    printf ("       EFI_FVB2_ALIGNMENT_16\n");\r
+    break;\r
 \r
-  if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_128) {\r
-    printf ("        EFI_FVB2_ALIGNMENT_128\n");\r
-  }\r
+    case EFI_FVB2_ALIGNMENT_32:\r
+    printf ("       EFI_FVB2_ALIGNMENT_32\n");\r
+    break;\r
 \r
-  if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_256) {\r
-    printf ("        EFI_FVB2_ALIGNMENT_256\n");\r
-  }\r
+    case EFI_FVB2_ALIGNMENT_64:\r
+    printf ("       EFI_FVB2_ALIGNMENT_64\n");\r
+    break;\r
 \r
-  if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_512) {\r
-    printf ("        EFI_FVB2_ALIGNMENT_512\n");\r
-  }\r
+    case EFI_FVB2_ALIGNMENT_128:\r
+    printf ("       EFI_FVB2_ALIGNMENT_128\n");\r
+    break;\r
 \r
-  if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_1K) {\r
-    printf ("        EFI_FVB2_ALIGNMENT_1K\n");\r
-  }\r
+    case EFI_FVB2_ALIGNMENT_256:\r
+    printf ("       EFI_FVB2_ALIGNMENT_256\n");\r
+    break;\r
 \r
-  if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_2K) {\r
-    printf ("        EFI_FVB2_ALIGNMENT_2K\n");\r
-  }\r
+    case EFI_FVB2_ALIGNMENT_512:\r
+    printf ("       EFI_FVB2_ALIGNMENT_512\n");\r
+    break;\r
 \r
-  if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_4K) {\r
-    printf ("        EFI_FVB2_ALIGNMENT_4K\n");\r
-  }\r
+    case EFI_FVB2_ALIGNMENT_1K:\r
+    printf ("       EFI_FVB2_ALIGNMENT_1K\n");\r
+    break;\r
 \r
-  if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_8K) {\r
-    printf ("        EFI_FVB2_ALIGNMENT_8K\n");\r
-  }\r
+    case EFI_FVB2_ALIGNMENT_2K:\r
+    printf ("       EFI_FVB2_ALIGNMENT_2K\n");\r
+    break;\r
 \r
-  if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_16K) {\r
-    printf ("        EFI_FVB2_ALIGNMENT_16K\n");\r
-  }\r
+    case EFI_FVB2_ALIGNMENT_4K:\r
+    printf ("       EFI_FVB2_ALIGNMENT_4K\n");\r
+    break;\r
 \r
-  if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_32K) {\r
-    printf ("        EFI_FVB2_ALIGNMENT_32K\n");\r
-  }\r
+    case EFI_FVB2_ALIGNMENT_8K:\r
+    printf ("       EFI_FVB2_ALIGNMENT_8K\n");\r
+    break;\r
 \r
-  if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_64K) {\r
-    printf ("        EFI_FVB2_ALIGNMENT_64K\n");\r
-  }\r
+    case EFI_FVB2_ALIGNMENT_16K:\r
+    printf ("       EFI_FVB2_ALIGNMENT_16K\n");\r
+    break;\r
 \r
-  if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_128K) {\r
-    printf ("        EFI_FVB2_ALIGNMENT_128K\n");\r
-  }\r
+    case EFI_FVB2_ALIGNMENT_32K:\r
+    printf ("       EFI_FVB2_ALIGNMENT_32K\n");\r
+    break;\r
 \r
-  if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_256K) {\r
-    printf ("        EFI_FVB2_ALIGNMENT_256K\n");\r
-  }\r
+    case EFI_FVB2_ALIGNMENT_64K:\r
+    printf ("       EFI_FVB2_ALIGNMENT_64K\n");\r
+    break;\r
 \r
-  if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_512K) {\r
-    printf ("        EFI_FVB2_ALIGNMENT_512K\n");\r
-  }\r
+    case EFI_FVB2_ALIGNMENT_128K:\r
+    printf ("       EFI_FVB2_ALIGNMENT_128K\n");\r
+    break;\r
 \r
-  if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_1M) {\r
-    printf ("        EFI_FVB2_ALIGNMENT_1M\n");\r
-  }\r
+    case EFI_FVB2_ALIGNMENT_256K:\r
+    printf ("       EFI_FVB2_ALIGNMENT_256K\n");\r
+    break;\r
 \r
-  if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_2M) {\r
-    printf ("        EFI_FVB2_ALIGNMENT_2M\n");\r
-  }\r
+    case EFI_FVB2_ALIGNMENT_512K:\r
+    printf ("       EFI_FVB2_ALIGNMENT_512K\n");\r
+    break;\r
 \r
-  if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_4M) {\r
-    printf ("        EFI_FVB2_ALIGNMENT_4M\n");\r
-  }\r
+    case EFI_FVB2_ALIGNMENT_1M:\r
+    printf ("       EFI_FVB2_ALIGNMENT_1M\n");\r
+    break;\r
 \r
-  if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_8M) {\r
-    printf ("        EFI_FVB2_ALIGNMENT_8M\n");\r
-  }\r
+    case EFI_FVB2_ALIGNMENT_2M:\r
+    printf ("       EFI_FVB2_ALIGNMENT_2M\n");\r
+    break;\r
 \r
-  if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_16M) {\r
-    printf ("        EFI_FVB2_ALIGNMENT_16M\n");\r
-  }\r
+    case EFI_FVB2_ALIGNMENT_4M:\r
+    printf ("       EFI_FVB2_ALIGNMENT_4M\n");\r
+    break;\r
 \r
-  if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_32M) {\r
-    printf ("        EFI_FVB2_ALIGNMENT_32M\n");\r
-  }\r
+    case EFI_FVB2_ALIGNMENT_8M:\r
+    printf ("       EFI_FVB2_ALIGNMENT_8M\n");\r
+    break;\r
 \r
-  if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_64M) {\r
-    printf ("        EFI_FVB2_ALIGNMENT_64M\n");\r
-  }\r
+    case EFI_FVB2_ALIGNMENT_16M:\r
+    printf ("       EFI_FVB2_ALIGNMENT_16M\n");\r
+    break;\r
 \r
-  if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_128M) {\r
-    printf ("        EFI_FVB2_ALIGNMENT_128M\n");\r
-  }\r
+    case EFI_FVB2_ALIGNMENT_32M:\r
+    printf ("       EFI_FVB2_ALIGNMENT_32M\n");\r
+    break;\r
 \r
-  if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_64M) {\r
-    printf ("        EFI_FVB2_ALIGNMENT_64M\n");\r
-  }\r
+    case EFI_FVB2_ALIGNMENT_64M:\r
+    printf ("       EFI_FVB2_ALIGNMENT_64M\n");\r
+    break;\r
 \r
-  if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_128M) {\r
-    printf ("        EFI_FVB2_ALIGNMENT_128M\n");\r
-  }\r
+    case EFI_FVB2_ALIGNMENT_128M:\r
+    printf ("       EFI_FVB2_ALIGNMENT_128M\n");\r
+    break;\r
 \r
-  if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_256M) {\r
-    printf ("        EFI_FVB2_ALIGNMENT_256M\n");\r
-  }\r
+    case EFI_FVB2_ALIGNMENT_256M:\r
+    printf ("       EFI_FVB2_ALIGNMENT_256M\n");\r
+    break;\r
 \r
-  if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_512M) {\r
-    printf ("        EFI_FVB2_ALIGNMENT_512M\n");\r
-  }\r
+    case EFI_FVB2_ALIGNMENT_512M:\r
+    printf ("       EFI_FVB2_ALIGNMENT_512M\n");\r
+    break;\r
 \r
-  if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_1G) {\r
-    printf ("        EFI_FVB2_ALIGNMENT_1G\n");\r
-  }\r
+    case EFI_FVB2_ALIGNMENT_1G:\r
+    printf ("       EFI_FVB2_ALIGNMENT_1G\n");\r
+    break;\r
 \r
-  if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_2G) {\r
-    printf ("        EFI_FVB2_ALIGNMENT_2G\n");\r
+    case EFI_FVB2_ALIGNMENT_2G:\r
+    printf ("       EFI_FVB2_ALIGNMENT_2G\n");\r
+    break;\r
   }\r
 \r
 #endif\r
@@ -915,7 +1051,10 @@ Returns:
   printf ("Revision:              0x%04X\n", VolumeHeader.Revision);\r
 \r
   do {\r
-    fread (&BlockMap, sizeof (EFI_FV_BLOCK_MAP_ENTRY), 1, InputFile);\r
+    ReadSize = fread (&BlockMap, sizeof (EFI_FV_BLOCK_MAP_ENTRY), 1, InputFile);\r
+    if (ReadSize != 1) {\r
+      return EFI_ABORTED;\r
+    }\r
     BytesRead += sizeof (EFI_FV_BLOCK_MAP_ENTRY);\r
 \r
     if (BlockMap.NumBlocks != 0) {\r
@@ -932,7 +1071,7 @@ Returns:
   }\r
 \r
   if (VolumeHeader.FvLength != Size) {\r
-    printf ("ERROR: Volume Size not consistant with Block Maps!\n");\r
+    printf ("ERROR: Volume Size not consistent with Block Maps!\n");\r
     return EFI_ABORTED;\r
   }\r
 \r
@@ -979,7 +1118,7 @@ Returns:
   EFI_STATUS          Status;\r
   UINT8               GuidBuffer[PRINTED_GUID_BUFFER_SIZE];\r
   UINT32              HeaderSize;\r
-#if (PI_SPECIFICATION_VERSION < 0x00010000) \r
+#if (PI_SPECIFICATION_VERSION < 0x00010000)\r
   UINT16              *Tail;\r
 #endif\r
   //\r
@@ -1081,7 +1220,7 @@ Returns:
         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
@@ -1096,7 +1235,7 @@ Returns:
         return EFI_ABORTED;\r
       }\r
     }\r
- #endif   \r
+ #endif\r
     break;\r
 \r
   default:\r
@@ -1160,6 +1299,14 @@ Returns:
     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
@@ -1197,6 +1344,280 @@ Returns:
   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
@@ -1217,7 +1638,7 @@ Returns:
 \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
@@ -1247,14 +1668,20 @@ Returns:
   CHAR8               *ExtractionTool;\r
   CHAR8               *ToolInputFile;\r
   CHAR8               *ToolOutputFile;\r
-  CHAR8               *SystemCommandFormatString;\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
+  CHAR8               *VersionString;\r
 \r
   ParsedLength = 0;\r
+  ToolInputFileName = NULL;\r
+  ToolOutputFileName = NULL;\r
+\r
   while (ParsedLength < BufferLength) {\r
     Ptr           = SectionBuffer + ParsedLength;\r
 \r
@@ -1278,21 +1705,94 @@ Returns:
     SectionHeaderLen = GetSectionHeaderLength((EFI_COMMON_SECTION_HEADER *)Ptr);\r
 \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
-    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_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
-      // 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
@@ -1317,8 +1817,14 @@ Returns:
       break;\r
 \r
     case EFI_SECTION_VERSION:\r
-      printf ("  Build Number:  0x%02X\n", *(UINT16 *)(Ptr + SectionHeaderLen));\r
-      printf ("  Version Strg:  %s\n", (char*) (Ptr + SectionHeaderLen + sizeof (UINT16)));\r
+      printf ("  Build Number:  0x%04X\n", *(UINT16 *)(Ptr + SectionHeaderLen));\r
+      VersionString = (CHAR8 *) malloc (UnicodeStrLen (((EFI_VERSION_SECTION *) Ptr)->VersionString) + 1);\r
+      if (VersionString == NULL) {\r
+        Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
+        return EFI_OUT_OF_RESOURCES;\r
+      }\r
+      Unicode2AsciiString (((EFI_VERSION_SECTION *) Ptr)->VersionString, VersionString);\r
+      printf ("  Version String:  %s\n", VersionString);\r
       break;\r
 \r
     case EFI_SECTION_COMPRESSION:\r
@@ -1368,8 +1874,14 @@ Returns:
         }\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
-        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
@@ -1429,24 +1941,56 @@ Returns:
           );\r
 \r
       if (ExtractionTool != NULL) {\r
-\r
+       #ifndef __GNUC__\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
-        SystemCommandFormatString = "%s -d -o %s %s";\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
+        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
-          SystemCommandFormatString,\r
+          EXTRACT_COMMAND_FORMAT_STRING,\r
           ExtractionTool,\r
           ToolOutputFile,\r
           ToolInputFile\r
@@ -1472,6 +2016,7 @@ Returns:
             );\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
@@ -1714,24 +2259,36 @@ Returns:
 {\r
   FILE              *Fptr;\r
   CHAR8             Line[MAX_LINE_LEN];\r
+  CHAR8             FormatString[MAX_LINE_LEN];\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
+  //\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
+      fclose (Fptr);\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
@@ -1837,19 +2394,35 @@ Returns:
 \r
   //\r
   // Copyright declaration\r
-  // \r
-  fprintf (stdout, "Copyright (c) 2007 - 2014, 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
-  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
-            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