]> git.proxmox.com Git - mirror_edk2.git/blobdiff - BaseTools/Source/C/VolInfo/VolInfo.c
BaseTools/GenVtf & VolInfo: Fix build fail for 'snprintf' not defined
[mirror_edk2.git] / BaseTools / Source / C / VolInfo / VolInfo.c
index 4fb634fe099b0205eddd90fe9595cc8f916f8bbf..2647cbb73a176c04b605f52ab661df272fa29438 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
 The tool dumps the contents of a firmware volume\r
 \r
-Copyright (c) 1999 - 2016, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 1999 - 2017, 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
@@ -19,6 +19,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <assert.h>\r
 #ifdef __GNUC__\r
 #include <unistd.h>\r
+#else\r
+#include <direct.h>\r
 #endif\r
 \r
 #include <FvLib.h>\r
@@ -40,6 +42,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include "ParseGuidedSectionTools.h"\r
 #include "StringFuncs.h"\r
 #include "ParseInf.h"\r
+#include "PeCoffLib.h"\r
 \r
 //\r
 // Utility global variables\r
@@ -47,8 +50,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 \r
 EFI_GUID  gEfiCrc32GuidedSectionExtractionProtocolGuid = EFI_CRC32_GUIDED_SECTION_EXTRACTION_PROTOCOL_GUID;\r
 \r
-#define UTILITY_MAJOR_VERSION      1
-#define UTILITY_MINOR_VERSION      0
+#define UTILITY_MAJOR_VERSION      1\r
+#define UTILITY_MINOR_VERSION      0\r
 \r
 #define UTILITY_NAME         "VolInfo"\r
 \r
@@ -74,6 +77,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
@@ -130,11 +136,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
@@ -165,16 +237,18 @@ Returns:
   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 Version %d.%d Build %s\n",
+  printf ("%s Version %d.%d Build %s\n",\r
     UTILITY_NAME,\r
     UTILITY_MAJOR_VERSION,\r
     UTILITY_MINOR_VERSION,\r
-    __BUILD_VERSION
+    __BUILD_VERSION\r
     );\r
 \r
   if (argc == 1) {\r
@@ -242,6 +316,36 @@ Returns:
       argv += 2;\r
       continue;\r
     }\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
+        OpenSslPath = malloc(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
@@ -1234,6 +1338,276 @@ 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) && (ImgHdr->Pe32.FileHeader.Machine != IMAGE_FILE_MACHINE_IA64)) {\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
+  DefaultPathLen = strlen(DefaultPath);\r
+  strcpy(NewPath, DefaultPath);\r
+  UINT64 Index = 0;\r
+  for (; Index < DefaultPathLen; 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
+  return EFI_SUCCESS;\r
+}\r
+\r
 EFI_STATUS\r
 ParseSection (\r
   IN UINT8  *SectionBuffer,\r
@@ -1284,14 +1658,19 @@ 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
 \r
   ParsedLength = 0;\r
+  ToolInputFileName = NULL;\r
+  ToolOutputFileName = NULL;\r
+\r
   while (ParsedLength < BufferLength) {\r
     Ptr           = SectionBuffer + ParsedLength;\r
 \r
@@ -1315,20 +1694,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
-      printf ("  String: %ls\n", (CHAR16 *) &((EFI_USER_INTERFACE_SECTION *) Ptr)->FileNameString);\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
@@ -1404,8 +1857,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
@@ -1481,20 +1940,40 @@ Returns:
         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
@@ -1520,6 +1999,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
@@ -1762,6 +2242,7 @@ 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 (LongFilePath (FileName), "r")) == NULL) {\r
@@ -1769,17 +2250,28 @@ Returns:
     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
@@ -1886,7 +2378,7 @@ Returns:
   //\r
   // Copyright declaration\r
   // \r
-  fprintf (stdout, "Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.\n\n");
+  fprintf (stdout, "Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.\n\n");\r
   fprintf (stdout, "  Display Tiano Firmware Volume FFS image information\n\n");\r
 \r
   //\r
@@ -1911,6 +2403,8 @@ Returns:
   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