summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--BaseTools/Source/C/VolInfo/VolInfo.c375
1 files changed, 374 insertions, 1 deletions
diff --git a/BaseTools/Source/C/VolInfo/VolInfo.c b/BaseTools/Source/C/VolInfo/VolInfo.c
index 84bfa69ea2..5c4a5036c2 100644
--- a/BaseTools/Source/C/VolInfo/VolInfo.c
+++ b/BaseTools/Source/C/VolInfo/VolInfo.c
@@ -19,6 +19,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <assert.h>
#ifdef __GNUC__
#include <unistd.h>
+#else
+#include <direct.h>
#endif
#include <FvLib.h>
@@ -40,6 +42,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include "ParseGuidedSectionTools.h"
#include "StringFuncs.h"
#include "ParseInf.h"
+#include "PeCoffLib.h"
//
// Utility global variables
@@ -74,6 +77,9 @@ EFI_HANDLE mParsedGuidedSectionTools = NULL;
CHAR8* mUtilityFilename = NULL;
+BOOLEAN EnableHash = FALSE;
+CHAR8 *OpenSslPath = NULL;
+
EFI_STATUS
ParseGuidBaseNameFile (
CHAR8 *FileName
@@ -130,6 +136,13 @@ LoadGuidedSectionToolsTxt (
IN CHAR8* FirmwareVolumeFilename
);
+EFI_STATUS
+CombinePath (
+ IN CHAR8* DefaultPath,
+ IN CHAR8* AppendPath,
+ OUT CHAR8* NewPath
+);
+
void
Usage (
VOID
@@ -165,6 +178,8 @@ Returns:
int Offset;
BOOLEAN ErasePolarity;
UINT64 LogLevel;
+ CHAR8 *OpenSslEnv;
+ CHAR8 *OpenSslCommand;
SetUtilityName (UTILITY_NAME);
//
@@ -242,6 +257,24 @@ Returns:
argv += 2;
continue;
}
+ if ((stricmp (argv[0], "--hash") == 0)) {
+ EnableHash = TRUE;
+ OpenSslCommand = "openssl";
+ OpenSslEnv = getenv("OPENSSL_PATH");
+ if (OpenSslEnv == NULL) {
+ OpenSslPath = OpenSslCommand;
+ } else {
+ OpenSslPath = malloc(strlen(OpenSslEnv)+strlen(OpenSslCommand)+1);
+ CombinePath(OpenSslEnv, OpenSslCommand, OpenSslPath);
+ }
+ if (OpenSslPath == NULL){
+ Error (NULL, 0, 3000, "Open SSL command not available. Please verify PATH or set OPENSSL_PATH.", NULL);
+ return GetUtilityStatus ();
+ }
+ argc --;
+ argv ++;
+ continue;
+ }
if ((stricmp (argv[0], "-v") == 0) || (stricmp (argv[0], "--verbose") == 0)) {
SetPrintLevel (VERBOSE_LOG_LEVEL);
@@ -1235,6 +1268,283 @@ Returns:
}
EFI_STATUS
+RebaseImageRead (
+ IN VOID *FileHandle,
+ IN UINTN FileOffset,
+ IN OUT UINT32 *ReadSize,
+ OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
+
+Arguments:
+
+ FileHandle - The handle to the PE/COFF file
+
+ FileOffset - The offset, in bytes, into the file to read
+
+ ReadSize - The number of bytes to read from the file starting at FileOffset
+
+ Buffer - A pointer to the buffer to read the data into.
+
+Returns:
+
+ EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
+
+--*/
+{
+ CHAR8 *Destination8;
+ CHAR8 *Source8;
+ UINT32 Length;
+
+ Destination8 = Buffer;
+ Source8 = (CHAR8 *) ((UINTN) FileHandle + FileOffset);
+ Length = *ReadSize;
+ while (Length--) {
+ *(Destination8++) = *(Source8++);
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+SetAddressToSectionHeader (
+ IN CHAR8 *FileName,
+ IN OUT UINT8 *FileBuffer,
+ IN UINT64 NewPe32BaseAddress
+ )
+/*++
+
+Routine Description:
+
+ Set new base address into the section header of PeImage
+
+Arguments:
+
+ FileName - Name of file
+ FileBuffer - Pointer to PeImage.
+ NewPe32BaseAddress - New Base Address for PE image.
+
+Returns:
+
+ EFI_SUCCESS Set new base address into this image successfully.
+
+--*/
+{
+ EFI_STATUS Status;
+ PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
+ UINTN Index;
+ EFI_IMAGE_OPTIONAL_HEADER_UNION *ImgHdr;
+ EFI_IMAGE_SECTION_HEADER *SectionHeader;
+
+ //
+ // Initialize context
+ //
+ memset (&ImageContext, 0, sizeof (ImageContext));
+ ImageContext.Handle = (VOID *) FileBuffer;
+ ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) RebaseImageRead;
+ Status = PeCoffLoaderGetImageInfo (&ImageContext);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 3000, "Invalid", "The input PeImage %s is not valid", FileName);
+ return Status;
+ }
+
+ if (ImageContext.RelocationsStripped) {
+ Error (NULL, 0, 3000, "Invalid", "The input PeImage %s has no relocation to be fixed up", FileName);
+ return Status;
+ }
+
+ //
+ // Get PeHeader pointer
+ //
+ ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer + ImageContext.PeCoffHeaderOffset);
+
+ //
+ // Get section header list
+ //
+ SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (
+ (UINTN) ImgHdr +
+ sizeof (UINT32) +
+ sizeof (EFI_IMAGE_FILE_HEADER) +
+ ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader
+ );
+
+ //
+ // Set base address into the first section header that doesn't point to code section.
+ //
+ for (Index = 0; Index < ImgHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) {
+ if ((SectionHeader->Characteristics & EFI_IMAGE_SCN_CNT_CODE) == 0) {
+ *(UINT64 *) &SectionHeader->PointerToRelocations = NewPe32BaseAddress;
+ break;
+ }
+ }
+
+ //
+ // No available section header is found.
+ //
+ if (Index == ImgHdr->Pe32.FileHeader.NumberOfSections) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // BaseAddress is set to section header.
+ //
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+RebaseImage (
+ IN CHAR8 *FileName,
+ IN OUT UINT8 *FileBuffer,
+ IN UINT64 NewPe32BaseAddress
+ )
+/*++
+
+Routine Description:
+
+ Set new base address into PeImage, and fix up PeImage based on new address.
+
+Arguments:
+
+ FileName - Name of file
+ FileBuffer - Pointer to PeImage.
+ NewPe32BaseAddress - New Base Address for PE image.
+
+Returns:
+
+ EFI_INVALID_PARAMETER - BaseAddress is not valid.
+ EFI_SUCCESS - Update PeImage is correctly.
+
+--*/
+{
+ EFI_STATUS Status;
+ PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
+ UINTN Index;
+ EFI_IMAGE_OPTIONAL_HEADER_UNION *ImgHdr;
+ UINT8 *MemoryImagePointer;
+ EFI_IMAGE_SECTION_HEADER *SectionHeader;
+
+ //
+ // Initialize context
+ //
+ memset (&ImageContext, 0, sizeof (ImageContext));
+ ImageContext.Handle = (VOID *) FileBuffer;
+ ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) RebaseImageRead;
+ Status = PeCoffLoaderGetImageInfo (&ImageContext);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 3000, "Invalid", "The input PeImage %s is not valid", FileName);
+ return Status;
+ }
+
+ if (ImageContext.RelocationsStripped) {
+ Error (NULL, 0, 3000, "Invalid", "The input PeImage %s has no relocation to be fixed up", FileName);
+ return Status;
+ }
+
+ //
+ // Get PeHeader pointer
+ //
+ ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer + ImageContext.PeCoffHeaderOffset);
+
+ //
+ // Load and Relocate Image Data
+ //
+ MemoryImagePointer = (UINT8 *) malloc ((UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment);
+ if (MemoryImagePointer == NULL) {
+ Error (NULL, 0, 4001, "Resource", "memory cannot be allocated on rebase of %s", FileName);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ memset ((VOID *) MemoryImagePointer, 0, (UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment);
+ ImageContext.ImageAddress = ((UINTN) MemoryImagePointer + ImageContext.SectionAlignment - 1) & (~((INT64)ImageContext.SectionAlignment - 1));
+
+ Status = PeCoffLoaderLoadImage (&ImageContext);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 3000, "Invalid", "LocateImage() call failed on rebase of %s", FileName);
+ free ((VOID *) MemoryImagePointer);
+ return Status;
+ }
+
+ ImageContext.DestinationAddress = NewPe32BaseAddress;
+ Status = PeCoffLoaderRelocateImage (&ImageContext);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 3000, "Invalid", "RelocateImage() call failed on rebase of %s", FileName);
+ free ((VOID *) MemoryImagePointer);
+ return Status;
+ }
+
+ //
+ // Copy Relocated data to raw image file.
+ //
+ SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (
+ (UINTN) ImgHdr +
+ sizeof (UINT32) +
+ sizeof (EFI_IMAGE_FILE_HEADER) +
+ ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader
+ );
+
+ for (Index = 0; Index < ImgHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) {
+ CopyMem (
+ FileBuffer + SectionHeader->PointerToRawData,
+ (VOID*) (UINTN) (ImageContext.ImageAddress + SectionHeader->VirtualAddress),
+ SectionHeader->SizeOfRawData
+ );
+ }
+
+ free ((VOID *) MemoryImagePointer);
+
+ //
+ // Update Image Base Address
+ //
+ if ((ImgHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) && (ImgHdr->Pe32.FileHeader.Machine != IMAGE_FILE_MACHINE_IA64)) {
+ ImgHdr->Pe32.OptionalHeader.ImageBase = (UINT32) NewPe32BaseAddress;
+ } else if (ImgHdr->Pe32Plus.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
+ ImgHdr->Pe32Plus.OptionalHeader.ImageBase = NewPe32BaseAddress;
+ } else {
+ Error (NULL, 0, 3000, "Invalid", "unknown PE magic signature %X in PE32 image %s",
+ ImgHdr->Pe32.OptionalHeader.Magic,
+ FileName
+ );
+ return EFI_ABORTED;
+ }
+
+ //
+ // Set new base address into section header
+ //
+ Status = SetAddressToSectionHeader (FileName, FileBuffer, NewPe32BaseAddress);
+
+ return Status;
+}
+
+EFI_STATUS
+CombinePath (
+ IN CHAR8* DefaultPath,
+ IN CHAR8* AppendPath,
+ OUT CHAR8* NewPath
+)
+{
+ UINT32 DefaultPathLen;
+ DefaultPathLen = strlen(DefaultPath);
+ strcpy(NewPath, DefaultPath);
+ UINT64 Index = 0;
+ for (; Index < DefaultPathLen; Index ++) {
+ if (NewPath[Index] == '\\' || NewPath[Index] == '/') {
+ if (NewPath[Index + 1] != '\0') {
+ NewPath[Index] = '/';
+ }
+ }
+ }
+ if (NewPath[Index -1] != '/') {
+ NewPath[Index] = '/';
+ NewPath[Index + 1] = '\0';
+ }
+ strcat(NewPath, AppendPath);
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
ParseSection (
IN UINT8 *SectionBuffer,
IN UINT32 BufferLength
@@ -1290,8 +1600,13 @@ Returns:
UINT16 DataOffset;
UINT16 Attributes;
UINT32 RealHdrLen;
+ CHAR8 *ToolInputFileName;
+ CHAR8 *ToolOutputFileName;
ParsedLength = 0;
+ ToolInputFileName = NULL;
+ ToolOutputFileName = NULL;
+
while (ParsedLength < BufferLength) {
Ptr = SectionBuffer + ParsedLength;
@@ -1321,12 +1636,68 @@ Returns:
switch (Type) {
case EFI_SECTION_RAW:
- case EFI_SECTION_PE32:
case EFI_SECTION_PIC:
case EFI_SECTION_TE:
// default is no more information
break;
+ case EFI_SECTION_PE32:
+ if (EnableHash) {
+ ToolInputFileName = "edk2Temp_InputEfi.tmp";
+ ToolOutputFileName = "edk2Temp_OutputHash.tmp";
+ RebaseImage(ToolInputFileName, (UINT8*)Ptr + SectionHeaderLen, 0);
+ PutFileImage (
+ ToolInputFileName,
+ (CHAR8*)Ptr + SectionHeaderLen,
+ SectionLength - SectionHeaderLen
+ );
+
+ SystemCommandFormatString = "%s sha1 -out %s %s";
+ SystemCommand = malloc (
+ strlen (SystemCommandFormatString) +
+ strlen (OpenSslPath) +
+ strlen (ToolInputFileName) +
+ strlen (ToolOutputFileName) +
+ 1
+ );
+ sprintf (
+ SystemCommand,
+ SystemCommandFormatString,
+ OpenSslPath,
+ ToolOutputFileName,
+ ToolInputFileName
+ );
+
+ if (system (SystemCommand) != EFI_SUCCESS) {
+ Error (NULL, 0, 3000, "Open SSL command not available. Please verify PATH or set OPENSSL_PATH.", NULL);
+ }
+ else {
+ FILE *fp;
+ CHAR8 *StrLine;
+ CHAR8 *NewStr;
+ UINT32 nFileLen;
+ if((fp = fopen(ToolOutputFileName,"r")) == NULL) {
+ Error (NULL, 0, 0004, "Hash the PE32 image failed.", NULL);
+ }
+ else {
+ fseek(fp,0,SEEK_SET);
+ fseek(fp,0,SEEK_END);
+ nFileLen = ftell(fp);
+ fseek(fp,0,SEEK_SET);
+ StrLine = malloc(nFileLen);
+ fgets(StrLine, nFileLen, fp);
+ NewStr = strrchr (StrLine, '=');
+ printf (" SHA1: %s\n", NewStr + 1);
+ free (StrLine);
+ }
+ fclose(fp);
+ }
+ remove(ToolInputFileName);
+ remove(ToolOutputFileName);
+ free (SystemCommand);
+ }
+ break;
+
case EFI_SECTION_USER_INTERFACE:
printf (" String: %ls\n", (CHAR16 *) &((EFI_USER_INTERFACE_SECTION *) Ptr)->FileNameString);
break;
@@ -1911,6 +2282,8 @@ Returns:
fprintf (stdout, " -f OFFSET, --offset OFFSET\n\
The offset from the start of the input file to start \n\
processing an FV\n");
+ fprintf (stdout, " --hash\n\
+ Generate HASH value of the entire PE image\n");
fprintf (stdout, " --sfo\n\
Reserved for future use\n");
}