/** @file\r
+The tool dumps the contents of a firmware volume\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
#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
#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
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
CHAR8* mUtilityFilename = NULL;\r
\r
+BOOLEAN EnableHash = FALSE;\r
+CHAR8 *OpenSslPath = NULL;\r
+\r
EFI_STATUS\r
ParseGuidBaseNameFile (\r
CHAR8 *FileName\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
+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
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
\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 (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
//\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
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
\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
//\r
// 0x02\r
//\r
- "EFI_SECTION_GUID_DEFINED", \r
+ "EFI_SECTION_GUID_DEFINED",\r
//\r
// 0x03\r
//\r
//\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
\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
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
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
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
-#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
+ HeaderSize = FvBufGetFfsHeaderSize(FileHeader);\r
if (ErasePolarity) {\r
- memset (&BlankHeader, -1, sizeof (EFI_FFS_FILE_HEADER));\r
+ memset (&BlankHeader, -1, HeaderSize);\r
} else {\r
- memset (&BlankHeader, 0, sizeof (EFI_FFS_FILE_HEADER));\r
+ memset (&BlankHeader, 0, HeaderSize);\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
// 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
\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
//\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
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
- 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
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
return EFI_ABORTED;\r
}\r
}\r
- #endif \r
+ #endif\r
break;\r
\r
default:\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
// 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
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
\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_SECTION_TYPE Type;\r
UINT8 *Ptr;\r
UINT32 SectionLength;\r
+ UINT32 SectionHeaderLen;\r
CHAR8 *SectionName;\r
EFI_STATUS Status;\r
UINT32 ParsedLength;\r
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
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
- 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
- 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
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
- 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
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
- 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
\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
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
- PrintGuid (&((EFI_GUID_DEFINED_SECTION *) Ptr)->SectionDefinitionGuid);\r
+ PrintGuid (EfiGuid);\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
- &((EFI_GUID_DEFINED_SECTION *) Ptr)->SectionDefinitionGuid\r
+ EfiGuid\r
);\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
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
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
// 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
// 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
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
{\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
\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
- 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