| /** @file | |
| The tool dumps the contents of a firmware volume | |
| Copyright (c) 1999 - 2016, Intel Corporation. All rights reserved.<BR> | |
| This program and the accompanying materials | |
| are licensed and made available under the terms and conditions of the BSD License | |
| which accompanies this distribution. The full text of the license may be found at | |
| http://opensource.org/licenses/bsd-license.php | |
| THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, | |
| WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. | |
| **/ | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <string.h> | |
| #include <ctype.h> | |
| #include <assert.h> | |
| #ifdef __GNUC__ | |
| #include <unistd.h> | |
| #else | |
| #include <direct.h> | |
| #endif | |
| #include <FvLib.h> | |
| #include <Common/UefiBaseTypes.h> | |
| #include <Common/UefiCapsule.h> | |
| #include <Common/PiFirmwareFile.h> | |
| #include <Common/PiFirmwareVolume.h> | |
| #include <Guid/PiFirmwareFileSystem.h> | |
| #include <IndustryStandard/PeImage.h> | |
| #include <Protocol/GuidedSectionExtraction.h> | |
| #include "Compress.h" | |
| #include "Decompress.h" | |
| #include "VolInfo.h" | |
| #include "CommonLib.h" | |
| #include "EfiUtilityMsgs.h" | |
| #include "FirmwareVolumeBufferLib.h" | |
| #include "OsPath.h" | |
| #include "ParseGuidedSectionTools.h" | |
| #include "StringFuncs.h" | |
| #include "ParseInf.h" | |
| #include "PeCoffLib.h" | |
| // | |
| // Utility global variables | |
| // | |
| EFI_GUID gEfiCrc32GuidedSectionExtractionProtocolGuid = EFI_CRC32_GUIDED_SECTION_EXTRACTION_PROTOCOL_GUID; | |
| #define UTILITY_MAJOR_VERSION 1 | |
| #define UTILITY_MINOR_VERSION 0 | |
| #define UTILITY_NAME "VolInfo" | |
| #define EFI_SECTION_ERROR EFIERR (100) | |
| #define MAX_BASENAME_LEN 60 // not good to hardcode, but let's be reasonable | |
| // | |
| // Structure to keep a list of guid-to-basenames | |
| // | |
| typedef struct _GUID_TO_BASENAME { | |
| struct _GUID_TO_BASENAME *Next; | |
| INT8 Guid[PRINTED_GUID_BUFFER_SIZE]; | |
| INT8 BaseName[MAX_BASENAME_LEN]; | |
| } GUID_TO_BASENAME; | |
| static GUID_TO_BASENAME *mGuidBaseNameList = NULL; | |
| // | |
| // Store GUIDed Section guid->tool mapping | |
| // | |
| EFI_HANDLE mParsedGuidedSectionTools = NULL; | |
| CHAR8* mUtilityFilename = NULL; | |
| BOOLEAN EnableHash = FALSE; | |
| CHAR8 *OpenSslPath = NULL; | |
| EFI_STATUS | |
| ParseGuidBaseNameFile ( | |
| CHAR8 *FileName | |
| ); | |
| EFI_STATUS | |
| FreeGuidBaseNameList ( | |
| VOID | |
| ); | |
| EFI_STATUS | |
| PrintGuidName ( | |
| IN UINT8 *GuidStr | |
| ); | |
| EFI_STATUS | |
| ParseSection ( | |
| IN UINT8 *SectionBuffer, | |
| IN UINT32 BufferLength | |
| ); | |
| EFI_STATUS | |
| DumpDepexSection ( | |
| IN UINT8 *Ptr, | |
| IN UINT32 SectionLength | |
| ); | |
| STATIC | |
| EFI_STATUS | |
| ReadHeader ( | |
| IN FILE *InputFile, | |
| OUT UINT32 *FvSize, | |
| OUT BOOLEAN *ErasePolarity | |
| ); | |
| STATIC | |
| EFI_STATUS | |
| PrintFileInfo ( | |
| EFI_FIRMWARE_VOLUME_HEADER *FvImage, | |
| EFI_FFS_FILE_HEADER *FileHeader, | |
| BOOLEAN ErasePolarity | |
| ); | |
| static | |
| EFI_STATUS | |
| PrintFvInfo ( | |
| IN VOID *Fv, | |
| IN BOOLEAN IsChildFv | |
| ); | |
| static | |
| VOID | |
| LoadGuidedSectionToolsTxt ( | |
| IN CHAR8* FirmwareVolumeFilename | |
| ); | |
| EFI_STATUS | |
| CombinePath ( | |
| IN CHAR8* DefaultPath, | |
| IN CHAR8* AppendPath, | |
| OUT CHAR8* NewPath | |
| ); | |
| void | |
| Usage ( | |
| VOID | |
| ); | |
| int | |
| main ( | |
| int argc, | |
| char *argv[] | |
| ) | |
| /*++ | |
| Routine Description: | |
| GC_TODO: Add function description | |
| Arguments: | |
| argc - GC_TODO: add argument description | |
| ] - GC_TODO: add argument description | |
| Returns: | |
| GC_TODO: add return values | |
| --*/ | |
| { | |
| FILE *InputFile; | |
| int BytesRead; | |
| EFI_FIRMWARE_VOLUME_HEADER *FvImage; | |
| UINT32 FvSize; | |
| EFI_STATUS Status; | |
| int Offset; | |
| BOOLEAN ErasePolarity; | |
| UINT64 LogLevel; | |
| CHAR8 *OpenSslEnv; | |
| CHAR8 *OpenSslCommand; | |
| SetUtilityName (UTILITY_NAME); | |
| // | |
| // Print utility header | |
| // | |
| printf ("%s Version %d.%d Build %s\n", | |
| UTILITY_NAME, | |
| UTILITY_MAJOR_VERSION, | |
| UTILITY_MINOR_VERSION, | |
| __BUILD_VERSION | |
| ); | |
| if (argc == 1) { | |
| Usage (); | |
| return -1; | |
| } | |
| argc--; | |
| argv++; | |
| LogLevel = 0; | |
| Offset = 0; | |
| // | |
| // Look for help options | |
| // | |
| if ((strcmp(argv[0], "-h") == 0) || (strcmp(argv[0], "--help") == 0) || | |
| (strcmp(argv[0], "-?") == 0) || (strcmp(argv[0], "/?") == 0)) { | |
| Usage(); | |
| return STATUS_SUCCESS; | |
| } | |
| // | |
| // Version has already be printed, so just return success | |
| // | |
| if (strcmp(argv[0], "--version") == 0) { | |
| return STATUS_SUCCESS; | |
| } | |
| // | |
| // If they specified -x xref guid/basename cross-reference files, process it. | |
| // This will print the basename beside each file guid. To use it, specify | |
| // -x xref_filename to processdsc, then use xref_filename as a parameter | |
| // here. | |
| // | |
| while (argc > 0) { | |
| if ((strcmp(argv[0], "-x") == 0) || (strcmp(argv[0], "--xref") == 0)) { | |
| ParseGuidBaseNameFile (argv[1]); | |
| printf("ParseGuidBaseNameFile: %s\n", argv[1]); | |
| argc -= 2; | |
| argv += 2; | |
| continue; | |
| } | |
| if (strcmp(argv[0], "--offset") == 0) { | |
| // | |
| // Hex or decimal? | |
| // | |
| if ((argv[1][0] == '0') && (tolower ((int)argv[1][1]) == 'x')) { | |
| if (sscanf (argv[1], "%x", &Offset) != 1) { | |
| Error (NULL, 0, 1003, "Invalid option value", "Offset = %s", argv[1]); | |
| return GetUtilityStatus (); | |
| } | |
| } else { | |
| if (sscanf (argv[1], "%d", &Offset) != 1) { | |
| Error (NULL, 0, 1003, "Invalid option value", "Offset = %s", argv[1]); | |
| return GetUtilityStatus (); | |
| } | |
| // | |
| // See if they said something like "64K" | |
| // | |
| if (tolower ((int)argv[1][strlen (argv[1]) - 1]) == 'k') { | |
| Offset *= 1024; | |
| } | |
| } | |
| argc -= 2; | |
| 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); | |
| argc --; | |
| argv ++; | |
| continue; | |
| } | |
| if ((stricmp (argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) { | |
| SetPrintLevel (KEY_LOG_LEVEL); | |
| argc --; | |
| argv ++; | |
| continue; | |
| } | |
| if ((stricmp (argv[0], "-d") == 0) || (stricmp (argv[0], "--debug") == 0)) { | |
| Status = AsciiStringToUint64 (argv[1], FALSE, &LogLevel); | |
| if (EFI_ERROR (Status)) { | |
| Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]); | |
| return -1; | |
| } | |
| if (LogLevel > 9) { | |
| Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0-9, current input level is %d", (int) LogLevel); | |
| return -1; | |
| } | |
| SetPrintLevel (LogLevel); | |
| DebugMsg (NULL, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv[1]); | |
| argc -= 2; | |
| argv += 2; | |
| continue; | |
| } | |
| mUtilityFilename = argv[0]; | |
| argc --; | |
| argv ++; | |
| } | |
| // | |
| // Open the file containing the FV | |
| // | |
| if (mUtilityFilename == NULL) { | |
| Error (NULL, 0, 1001, "Missing option", "Input files are not specified"); | |
| return GetUtilityStatus (); | |
| } | |
| InputFile = fopen (LongFilePath (mUtilityFilename), "rb"); | |
| if (InputFile == NULL) { | |
| Error (NULL, 0, 0001, "Error opening the input file", mUtilityFilename); | |
| return GetUtilityStatus (); | |
| } | |
| // | |
| // Skip over pad bytes if specified. This is used if they prepend 0xff | |
| // data to the FV image binary. | |
| // | |
| if (Offset != 0) { | |
| fseek (InputFile, Offset, SEEK_SET); | |
| } | |
| // | |
| // Determine size of FV | |
| // | |
| Status = ReadHeader (InputFile, &FvSize, &ErasePolarity); | |
| if (EFI_ERROR (Status)) { | |
| Error (NULL, 0, 0003, "error parsing FV image", "%s Header is invalid", mUtilityFilename); | |
| fclose (InputFile); | |
| return GetUtilityStatus (); | |
| } | |
| // | |
| // Allocate a buffer for the FV image | |
| // | |
| FvImage = malloc (FvSize); | |
| if (FvImage == NULL) { | |
| Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL); | |
| fclose (InputFile); | |
| return GetUtilityStatus (); | |
| } | |
| // | |
| // Seek to the start of the image, then read the entire FV to the buffer | |
| // | |
| fseek (InputFile, Offset, SEEK_SET); | |
| BytesRead = fread (FvImage, 1, FvSize, InputFile); | |
| fclose (InputFile); | |
| if ((unsigned int) BytesRead != FvSize) { | |
| Error (NULL, 0, 0004, "error reading FvImage from", mUtilityFilename); | |
| free (FvImage); | |
| return GetUtilityStatus (); | |
| } | |
| LoadGuidedSectionToolsTxt (mUtilityFilename); | |
| PrintFvInfo (FvImage, FALSE); | |
| // | |
| // Clean up | |
| // | |
| free (FvImage); | |
| FreeGuidBaseNameList (); | |
| return GetUtilityStatus (); | |
| } | |
| static | |
| EFI_STATUS | |
| PrintFvInfo ( | |
| IN VOID *Fv, | |
| IN BOOLEAN IsChildFv | |
| ) | |
| /*++ | |
| Routine Description: | |
| GC_TODO: Add function description | |
| Arguments: | |
| Fv - Firmware Volume to print information about | |
| IsChildFv - Flag specifies whether the input FV is a child FV. | |
| Returns: | |
| EFI_STATUS | |
| --*/ | |
| { | |
| EFI_STATUS Status; | |
| UINTN NumberOfFiles; | |
| BOOLEAN ErasePolarity; | |
| UINTN FvSize; | |
| EFI_FFS_FILE_HEADER *CurrentFile; | |
| UINTN Key; | |
| Status = FvBufGetSize (Fv, &FvSize); | |
| NumberOfFiles = 0; | |
| ErasePolarity = | |
| (((EFI_FIRMWARE_VOLUME_HEADER*)Fv)->Attributes & EFI_FVB2_ERASE_POLARITY) ? | |
| TRUE : FALSE; | |
| // | |
| // Get the first file | |
| // | |
| Key = 0; | |
| Status = FvBufFindNextFile (Fv, &Key, (VOID **) &CurrentFile); | |
| if (EFI_ERROR (Status)) { | |
| Error (NULL, 0, 0003, "error parsing FV image", "cannot find the first file in the FV image"); | |
| return GetUtilityStatus (); | |
| } | |
| // | |
| // Display information about files found | |
| // | |
| while (CurrentFile != NULL) { | |
| // | |
| // Increment the number of files counter | |
| // | |
| NumberOfFiles++; | |
| // | |
| // Display info about this file | |
| // | |
| Status = PrintFileInfo (Fv, CurrentFile, ErasePolarity); | |
| if (EFI_ERROR (Status)) { | |
| Error (NULL, 0, 0003, "error parsing FV image", "failed to parse a file in the FV"); | |
| return GetUtilityStatus (); | |
| } | |
| // | |
| // Get the next file | |
| // | |
| Status = FvBufFindNextFile (Fv, &Key, (VOID **) &CurrentFile); | |
| if (Status == EFI_NOT_FOUND) { | |
| CurrentFile = NULL; | |
| } else if (EFI_ERROR (Status)) { | |
| Error (NULL, 0, 0003, "error parsing FV image", "cannot find the next file in the FV image"); | |
| return GetUtilityStatus (); | |
| } | |
| } | |
| if (IsChildFv) { | |
| printf ("There are a total of %d files in the child FV\n", (int) NumberOfFiles); | |
| } else { | |
| printf ("There are a total of %d files in this FV\n", (int) NumberOfFiles); | |
| } | |
| return EFI_SUCCESS; | |
| } | |
| UINT32 | |
| GetOccupiedSize ( | |
| IN UINT32 ActualSize, | |
| IN UINT32 Alignment | |
| ) | |
| /*++ | |
| Routine Description: | |
| This function returns the next larger size that meets the alignment | |
| requirement specified. | |
| Arguments: | |
| ActualSize The size. | |
| Alignment The desired alignment. | |
| Returns: | |
| EFI_SUCCESS Function completed successfully. | |
| EFI_ABORTED The function encountered an error. | |
| --*/ | |
| { | |
| UINT32 OccupiedSize; | |
| OccupiedSize = ActualSize; | |
| while ((OccupiedSize & (Alignment - 1)) != 0) { | |
| OccupiedSize++; | |
| } | |
| return OccupiedSize; | |
| } | |
| static | |
| CHAR8 * | |
| SectionNameToStr ( | |
| IN EFI_SECTION_TYPE Type | |
| ) | |
| /*++ | |
| Routine Description: | |
| Converts EFI Section names to Strings | |
| Arguments: | |
| Type - The EFI Section type | |
| Returns: | |
| CHAR8* - Pointer to the String containing the section name. | |
| --*/ | |
| { | |
| CHAR8 *SectionStr; | |
| CHAR8 *SectionTypeStringTable[] = { | |
| // | |
| // 0X00 | |
| // | |
| "EFI_SECTION_ALL", | |
| // | |
| // 0x01 | |
| // | |
| "EFI_SECTION_COMPRESSION", | |
| // | |
| // 0x02 | |
| // | |
| "EFI_SECTION_GUID_DEFINED", | |
| // | |
| // 0x03 | |
| // | |
| "Unknown section type - Reserved 0x03", | |
| // | |
| // 0x04 | |
| // | |
| "Unknown section type - Reserved 0x04", | |
| // | |
| // 0x05 | |
| // | |
| "Unknown section type - Reserved 0x05", | |
| // | |
| // 0x06 | |
| // | |
| "Unknown section type - Reserved 0x06", | |
| // | |
| // 0x07 | |
| // | |
| "Unknown section type - Reserved 0x07", | |
| // | |
| // 0x08 | |
| // | |
| "Unknown section type - Reserved 0x08", | |
| // | |
| // 0x09 | |
| // | |
| "Unknown section type - Reserved 0x09", | |
| // | |
| // 0x0A | |
| // | |
| "Unknown section type - Reserved 0x0A", | |
| // | |
| // 0x0B | |
| // | |
| "Unknown section type - Reserved 0x0B", | |
| // | |
| // 0x0C | |
| // | |
| "Unknown section type - Reserved 0x0C", | |
| // | |
| // 0x0D | |
| // | |
| "Unknown section type - Reserved 0x0D", | |
| // | |
| // 0x0E | |
| // | |
| "Unknown section type - Reserved 0x0E", | |
| // | |
| // 0x0F | |
| // | |
| "Unknown section type - Reserved 0x0E", | |
| // | |
| // 0x10 | |
| // | |
| "EFI_SECTION_PE32", | |
| // | |
| // 0x11 | |
| // | |
| "EFI_SECTION_PIC", | |
| // | |
| // 0x12 | |
| // | |
| "EFI_SECTION_TE", | |
| // | |
| // 0x13 | |
| // | |
| "EFI_SECTION_DXE_DEPEX", | |
| // | |
| // 0x14 | |
| // | |
| "EFI_SECTION_VERSION", | |
| // | |
| // 0x15 | |
| // | |
| "EFI_SECTION_USER_INTERFACE", | |
| // | |
| // 0x16 | |
| // | |
| "EFI_SECTION_COMPATIBILITY16", | |
| // | |
| // 0x17 | |
| // | |
| "EFI_SECTION_FIRMWARE_VOLUME_IMAGE ", | |
| // | |
| // 0x18 | |
| // | |
| "EFI_SECTION_FREEFORM_SUBTYPE_GUID ", | |
| // | |
| // 0x19 | |
| // | |
| "EFI_SECTION_RAW", | |
| // | |
| // 0x1A | |
| // | |
| "Unknown section type - 0x1A", | |
| // | |
| // 0x1B | |
| // | |
| "EFI_SECTION_PEI_DEPEX", | |
| // | |
| // 0x1C | |
| // | |
| "EFI_SECTION_SMM_DEPEX", | |
| // | |
| // 0x1C+ | |
| // | |
| "Unknown section type - Reserved - beyond last defined section" | |
| }; | |
| if (Type > EFI_SECTION_LAST_SECTION_TYPE) { | |
| Type = EFI_SECTION_LAST_SECTION_TYPE + 1; | |
| } | |
| SectionStr = malloc (100); | |
| if (SectionStr == NULL) { | |
| printf ("Error: Out of memory resources.\n"); | |
| return SectionStr; | |
| } | |
| strcpy (SectionStr, SectionTypeStringTable[Type]); | |
| return SectionStr; | |
| } | |
| STATIC | |
| EFI_STATUS | |
| ReadHeader ( | |
| IN FILE *InputFile, | |
| OUT UINT32 *FvSize, | |
| OUT BOOLEAN *ErasePolarity | |
| ) | |
| /*++ | |
| Routine Description: | |
| This function determines the size of the FV and the erase polarity. The | |
| erase polarity is the FALSE value for file state. | |
| Arguments: | |
| InputFile The file that contains the FV image. | |
| FvSize The size of the FV. | |
| ErasePolarity The FV erase polarity. | |
| Returns: | |
| EFI_SUCCESS Function completed successfully. | |
| EFI_INVALID_PARAMETER A required parameter was NULL or is out of range. | |
| EFI_ABORTED The function encountered an error. | |
| --*/ | |
| { | |
| EFI_FIRMWARE_VOLUME_HEADER VolumeHeader; | |
| EFI_FV_BLOCK_MAP_ENTRY BlockMap; | |
| UINTN Signature[2]; | |
| UINTN BytesRead; | |
| UINT32 Size; | |
| BytesRead = 0; | |
| Size = 0; | |
| // | |
| // Check input parameters | |
| // | |
| if (InputFile == NULL || FvSize == NULL || ErasePolarity == NULL) { | |
| Error (__FILE__, __LINE__, 0, "application error", "invalid parameter to function"); | |
| return EFI_INVALID_PARAMETER; | |
| } | |
| // | |
| // Read the header | |
| // | |
| fread (&VolumeHeader, sizeof (EFI_FIRMWARE_VOLUME_HEADER) - sizeof (EFI_FV_BLOCK_MAP_ENTRY), 1, InputFile); | |
| BytesRead = sizeof (EFI_FIRMWARE_VOLUME_HEADER) - sizeof (EFI_FV_BLOCK_MAP_ENTRY); | |
| Signature[0] = VolumeHeader.Signature; | |
| Signature[1] = 0; | |
| // | |
| // Print FV header information | |
| // | |
| printf ("Signature: %s (%X)\n", (char *) Signature, (unsigned) VolumeHeader.Signature); | |
| printf ("Attributes: %X\n", (unsigned) VolumeHeader.Attributes); | |
| if (VolumeHeader.Attributes & EFI_FVB2_READ_DISABLED_CAP) { | |
| printf (" EFI_FVB2_READ_DISABLED_CAP\n"); | |
| } | |
| if (VolumeHeader.Attributes & EFI_FVB2_READ_ENABLED_CAP) { | |
| printf (" EFI_FVB2_READ_ENABLED_CAP\n"); | |
| } | |
| if (VolumeHeader.Attributes & EFI_FVB2_READ_STATUS) { | |
| printf (" EFI_FVB2_READ_STATUS\n"); | |
| } | |
| if (VolumeHeader.Attributes & EFI_FVB2_WRITE_DISABLED_CAP) { | |
| printf (" EFI_FVB2_WRITE_DISABLED_CAP\n"); | |
| } | |
| if (VolumeHeader.Attributes & EFI_FVB2_WRITE_ENABLED_CAP) { | |
| printf (" EFI_FVB2_WRITE_ENABLED_CAP\n"); | |
| } | |
| if (VolumeHeader.Attributes & EFI_FVB2_WRITE_STATUS) { | |
| printf (" EFI_FVB2_WRITE_STATUS\n"); | |
| } | |
| if (VolumeHeader.Attributes & EFI_FVB2_LOCK_CAP) { | |
| printf (" EFI_FVB2_LOCK_CAP\n"); | |
| } | |
| if (VolumeHeader.Attributes & EFI_FVB2_LOCK_STATUS) { | |
| printf (" EFI_FVB2_LOCK_STATUS\n"); | |
| } | |
| if (VolumeHeader.Attributes & EFI_FVB2_STICKY_WRITE) { | |
| printf (" EFI_FVB2_STICKY_WRITE\n"); | |
| } | |
| if (VolumeHeader.Attributes & EFI_FVB2_MEMORY_MAPPED) { | |
| printf (" EFI_FVB2_MEMORY_MAPPED\n"); | |
| } | |
| if (VolumeHeader.Attributes & EFI_FVB2_ERASE_POLARITY) { | |
| printf (" EFI_FVB2_ERASE_POLARITY\n"); | |
| *ErasePolarity = TRUE; | |
| } | |
| #if (PI_SPECIFICATION_VERSION < 0x00010000) | |
| if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT) { | |
| printf (" EFI_FVB2_ALIGNMENT\n"); | |
| } | |
| if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_2) { | |
| printf (" EFI_FVB2_ALIGNMENT_2\n"); | |
| } | |
| if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_4) { | |
| printf (" EFI_FVB2_ALIGNMENT_4\n"); | |
| } | |
| if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_8) { | |
| printf (" EFI_FVB2_ALIGNMENT_8\n"); | |
| } | |
| if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_16) { | |
| printf (" EFI_FVB2_ALIGNMENT_16\n"); | |
| } | |
| if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_32) { | |
| printf (" EFI_FVB2_ALIGNMENT_32\n"); | |
| } | |
| if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_64) { | |
| printf (" EFI_FVB2_ALIGNMENT_64\n"); | |
| } | |
| if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_128) { | |
| printf (" EFI_FVB2_ALIGNMENT_128\n"); | |
| } | |
| if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_256) { | |
| printf (" EFI_FVB2_ALIGNMENT_256\n"); | |
| } | |
| if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_512) { | |
| printf (" EFI_FVB2_ALIGNMENT_512\n"); | |
| } | |
| if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_1K) { | |
| printf (" EFI_FVB2_ALIGNMENT_1K\n"); | |
| } | |
| if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_2K) { | |
| printf (" EFI_FVB2_ALIGNMENT_2K\n"); | |
| } | |
| if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_4K) { | |
| printf (" EFI_FVB2_ALIGNMENT_4K\n"); | |
| } | |
| if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_8K) { | |
| printf (" EFI_FVB2_ALIGNMENT_8K\n"); | |
| } | |
| if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_16K) { | |
| printf (" EFI_FVB2_ALIGNMENT_16K\n"); | |
| } | |
| if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_32K) { | |
| printf (" EFI_FVB2_ALIGNMENT_32K\n"); | |
| } | |
| if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_64K) { | |
| printf (" EFI_FVB2_ALIGNMENT_64K\n"); | |
| } | |
| #else | |
| if (VolumeHeader.Attributes & EFI_FVB2_READ_LOCK_CAP) { | |
| printf (" EFI_FVB2_READ_LOCK_CAP\n"); | |
| } | |
| if (VolumeHeader.Attributes & EFI_FVB2_READ_LOCK_STATUS) { | |
| printf (" EFI_FVB2_READ_LOCK_STATUS\n"); | |
| } | |
| if (VolumeHeader.Attributes & EFI_FVB2_WRITE_LOCK_CAP) { | |
| printf (" EFI_FVB2_WRITE_LOCK_CAP\n"); | |
| } | |
| if (VolumeHeader.Attributes & EFI_FVB2_WRITE_LOCK_STATUS) { | |
| printf (" EFI_FVB2_WRITE_LOCK_STATUS\n"); | |
| } | |
| if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_1) { | |
| printf (" EFI_FVB2_ALIGNMENT_1\n"); | |
| } | |
| if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_2) { | |
| printf (" EFI_FVB2_ALIGNMENT_2\n"); | |
| } | |
| if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_4) { | |
| printf (" EFI_FVB2_ALIGNMENT_4\n"); | |
| } | |
| if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_8) { | |
| printf (" EFI_FVB2_ALIGNMENT_8\n"); | |
| } | |
| if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_16) { | |
| printf (" EFI_FVB2_ALIGNMENT_16\n"); | |
| } | |
| if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_32) { | |
| printf (" EFI_FVB2_ALIGNMENT_32\n"); | |
| } | |
| if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_64) { | |
| printf (" EFI_FVB2_ALIGNMENT_64\n"); | |
| } | |
| if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_128) { | |
| printf (" EFI_FVB2_ALIGNMENT_128\n"); | |
| } | |
| if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_256) { | |
| printf (" EFI_FVB2_ALIGNMENT_256\n"); | |
| } | |
| if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_512) { | |
| printf (" EFI_FVB2_ALIGNMENT_512\n"); | |
| } | |
| if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_1K) { | |
| printf (" EFI_FVB2_ALIGNMENT_1K\n"); | |
| } | |
| if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_2K) { | |
| printf (" EFI_FVB2_ALIGNMENT_2K\n"); | |
| } | |
| if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_4K) { | |
| printf (" EFI_FVB2_ALIGNMENT_4K\n"); | |
| } | |
| if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_8K) { | |
| printf (" EFI_FVB2_ALIGNMENT_8K\n"); | |
| } | |
| if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_16K) { | |
| printf (" EFI_FVB2_ALIGNMENT_16K\n"); | |
| } | |
| if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_32K) { | |
| printf (" EFI_FVB2_ALIGNMENT_32K\n"); | |
| } | |
| if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_64K) { | |
| printf (" EFI_FVB2_ALIGNMENT_64K\n"); | |
| } | |
| if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_128K) { | |
| printf (" EFI_FVB2_ALIGNMENT_128K\n"); | |
| } | |
| if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_256K) { | |
| printf (" EFI_FVB2_ALIGNMENT_256K\n"); | |
| } | |
| if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_512K) { | |
| printf (" EFI_FVB2_ALIGNMENT_512K\n"); | |
| } | |
| if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_1M) { | |
| printf (" EFI_FVB2_ALIGNMENT_1M\n"); | |
| } | |
| if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_2M) { | |
| printf (" EFI_FVB2_ALIGNMENT_2M\n"); | |
| } | |
| if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_4M) { | |
| printf (" EFI_FVB2_ALIGNMENT_4M\n"); | |
| } | |
| if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_8M) { | |
| printf (" EFI_FVB2_ALIGNMENT_8M\n"); | |
| } | |
| if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_16M) { | |
| printf (" EFI_FVB2_ALIGNMENT_16M\n"); | |
| } | |
| if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_32M) { | |
| printf (" EFI_FVB2_ALIGNMENT_32M\n"); | |
| } | |
| if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_64M) { | |
| printf (" EFI_FVB2_ALIGNMENT_64M\n"); | |
| } | |
| if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_128M) { | |
| printf (" EFI_FVB2_ALIGNMENT_128M\n"); | |
| } | |
| if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_64M) { | |
| printf (" EFI_FVB2_ALIGNMENT_64M\n"); | |
| } | |
| if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_128M) { | |
| printf (" EFI_FVB2_ALIGNMENT_128M\n"); | |
| } | |
| if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_256M) { | |
| printf (" EFI_FVB2_ALIGNMENT_256M\n"); | |
| } | |
| if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_512M) { | |
| printf (" EFI_FVB2_ALIGNMENT_512M\n"); | |
| } | |
| if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_1G) { | |
| printf (" EFI_FVB2_ALIGNMENT_1G\n"); | |
| } | |
| if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_2G) { | |
| printf (" EFI_FVB2_ALIGNMENT_2G\n"); | |
| } | |
| #endif | |
| printf ("Header Length: 0x%08X\n", VolumeHeader.HeaderLength); | |
| printf ("File System ID: "); | |
| PrintGuid (&VolumeHeader.FileSystemGuid); | |
| // | |
| // printf ("\n"); | |
| // | |
| printf ("Revision: 0x%04X\n", VolumeHeader.Revision); | |
| do { | |
| fread (&BlockMap, sizeof (EFI_FV_BLOCK_MAP_ENTRY), 1, InputFile); | |
| BytesRead += sizeof (EFI_FV_BLOCK_MAP_ENTRY); | |
| if (BlockMap.NumBlocks != 0) { | |
| printf ("Number of Blocks: 0x%08X\n", (unsigned) BlockMap.NumBlocks); | |
| printf ("Block Length: 0x%08X\n", (unsigned) BlockMap.Length); | |
| Size += BlockMap.NumBlocks * BlockMap.Length; | |
| } | |
| } while (!(BlockMap.NumBlocks == 0 && BlockMap.Length == 0)); | |
| if (BytesRead != VolumeHeader.HeaderLength) { | |
| printf ("ERROR: Header length not consistent with Block Maps!\n"); | |
| return EFI_ABORTED; | |
| } | |
| if (VolumeHeader.FvLength != Size) { | |
| printf ("ERROR: Volume Size not consistant with Block Maps!\n"); | |
| return EFI_ABORTED; | |
| } | |
| printf ("Total Volume Size: 0x%08X\n", (unsigned) Size); | |
| *FvSize = Size; | |
| // | |
| // rewind (InputFile); | |
| // | |
| return EFI_SUCCESS; | |
| } | |
| STATIC | |
| EFI_STATUS | |
| PrintFileInfo ( | |
| EFI_FIRMWARE_VOLUME_HEADER *FvImage, | |
| EFI_FFS_FILE_HEADER *FileHeader, | |
| BOOLEAN ErasePolarity | |
| ) | |
| /*++ | |
| Routine Description: | |
| GC_TODO: Add function description | |
| Arguments: | |
| FvImage - GC_TODO: add argument description | |
| FileHeader - GC_TODO: add argument description | |
| ErasePolarity - GC_TODO: add argument description | |
| Returns: | |
| EFI_SUCCESS - GC_TODO: Add description for return value | |
| EFI_ABORTED - GC_TODO: Add description for return value | |
| --*/ | |
| { | |
| UINT32 FileLength; | |
| UINT8 FileState; | |
| UINT8 Checksum; | |
| EFI_FFS_FILE_HEADER2 BlankHeader; | |
| EFI_STATUS Status; | |
| UINT8 GuidBuffer[PRINTED_GUID_BUFFER_SIZE]; | |
| UINT32 HeaderSize; | |
| #if (PI_SPECIFICATION_VERSION < 0x00010000) | |
| UINT16 *Tail; | |
| #endif | |
| // | |
| // Check if we have free space | |
| // | |
| HeaderSize = FvBufGetFfsHeaderSize(FileHeader); | |
| if (ErasePolarity) { | |
| memset (&BlankHeader, -1, HeaderSize); | |
| } else { | |
| memset (&BlankHeader, 0, HeaderSize); | |
| } | |
| if (memcmp (&BlankHeader, FileHeader, HeaderSize) == 0) { | |
| return EFI_SUCCESS; | |
| } | |
| // | |
| // Print file information. | |
| // | |
| printf ("============================================================\n"); | |
| printf ("File Name: "); | |
| PrintGuidToBuffer (&FileHeader->Name, GuidBuffer, sizeof (GuidBuffer), TRUE); | |
| printf ("%s ", GuidBuffer); | |
| PrintGuidName (GuidBuffer); | |
| printf ("\n"); | |
| // | |
| // PrintGuid (&FileHeader->Name); | |
| // printf ("\n"); | |
| // | |
| FileLength = FvBufGetFfsFileSize (FileHeader); | |
| printf ("File Offset: 0x%08X\n", (unsigned) ((UINTN) FileHeader - (UINTN) FvImage)); | |
| printf ("File Length: 0x%08X\n", (unsigned) FileLength); | |
| printf ("File Attributes: 0x%02X\n", FileHeader->Attributes); | |
| printf ("File State: 0x%02X\n", FileHeader->State); | |
| // | |
| // Print file state | |
| // | |
| FileState = GetFileState (ErasePolarity, FileHeader); | |
| switch (FileState) { | |
| case EFI_FILE_HEADER_CONSTRUCTION: | |
| printf (" EFI_FILE_HEADER_CONSTRUCTION\n"); | |
| return EFI_SUCCESS; | |
| case EFI_FILE_HEADER_INVALID: | |
| printf (" EFI_FILE_HEADER_INVALID\n"); | |
| return EFI_SUCCESS; | |
| case EFI_FILE_HEADER_VALID: | |
| printf (" EFI_FILE_HEADER_VALID\n"); | |
| Checksum = CalculateSum8 ((UINT8 *) FileHeader, HeaderSize); | |
| Checksum = (UINT8) (Checksum - FileHeader->IntegrityCheck.Checksum.File); | |
| Checksum = (UINT8) (Checksum - FileHeader->State); | |
| if (Checksum != 0) { | |
| printf ("ERROR: Header checksum invalid.\n"); | |
| return EFI_ABORTED; | |
| } | |
| return EFI_SUCCESS; | |
| case EFI_FILE_DELETED: | |
| printf (" EFI_FILE_DELETED\n"); | |
| case EFI_FILE_MARKED_FOR_UPDATE: | |
| printf (" EFI_FILE_MARKED_FOR_UPDATE\n"); | |
| case EFI_FILE_DATA_VALID: | |
| printf (" EFI_FILE_DATA_VALID\n"); | |
| // | |
| // Calculate header checksum | |
| // | |
| Checksum = CalculateSum8 ((UINT8 *) FileHeader, HeaderSize); | |
| Checksum = (UINT8) (Checksum - FileHeader->IntegrityCheck.Checksum.File); | |
| Checksum = (UINT8) (Checksum - FileHeader->State); | |
| if (Checksum != 0) { | |
| Error (NULL, 0, 0003, "error parsing FFS file", "FFS file with Guid %s has invalid header checksum", GuidBuffer); | |
| return EFI_ABORTED; | |
| } | |
| FileLength = FvBufGetFfsFileSize (FileHeader); | |
| if (FileHeader->Attributes & FFS_ATTRIB_CHECKSUM) { | |
| // | |
| // Calculate file checksum | |
| // | |
| Checksum = CalculateSum8 ((UINT8 *)FileHeader + HeaderSize, FileLength - HeaderSize); | |
| Checksum = Checksum + FileHeader->IntegrityCheck.Checksum.File; | |
| if (Checksum != 0) { | |
| Error (NULL, 0, 0003, "error parsing FFS file", "FFS file with Guid %s has invalid file checksum", GuidBuffer); | |
| return EFI_ABORTED; | |
| } | |
| } else { | |
| if (FileHeader->IntegrityCheck.Checksum.File != FFS_FIXED_CHECKSUM) { | |
| Error (NULL, 0, 0003, "error parsing FFS file", "FFS file with Guid %s has invalid header checksum -- not set to fixed value of 0xAA", GuidBuffer); | |
| return EFI_ABORTED; | |
| } | |
| } | |
| #if (PI_SPECIFICATION_VERSION < 0x00010000) | |
| // | |
| // Verify tail if present | |
| // | |
| if (FileHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT) { | |
| // | |
| // Verify tail is complement of integrity check field in the header. | |
| // | |
| Tail = (UINT16 *) ((UINTN) FileHeader + GetLength (FileHeader->Size) - sizeof (EFI_FFS_INTEGRITY_CHECK)); | |
| if (FileHeader->IntegrityCheck.TailReference != (UINT16)~(*Tail)) { | |
| Error (NULL, 0, 0003, "error parsing FFS file", \ | |
| "FFS file with Guid %s failed in the integrity check, tail is not the complement of the header field", GuidBuffer); | |
| return EFI_ABORTED; | |
| } | |
| } | |
| #endif | |
| break; | |
| default: | |
| Error (NULL, 0, 0003, "error parsing FFS file", "FFS file with Guid %s has the invalid/unrecognized file state bits", GuidBuffer); | |
| return EFI_ABORTED; | |
| } | |
| printf ("File Type: 0x%02X ", FileHeader->Type); | |
| switch (FileHeader->Type) { | |
| case EFI_FV_FILETYPE_RAW: | |
| printf ("EFI_FV_FILETYPE_RAW\n"); | |
| break; | |
| case EFI_FV_FILETYPE_FREEFORM: | |
| printf ("EFI_FV_FILETYPE_FREEFORM\n"); | |
| break; | |
| case EFI_FV_FILETYPE_SECURITY_CORE: | |
| printf ("EFI_FV_FILETYPE_SECURITY_CORE\n"); | |
| break; | |
| case EFI_FV_FILETYPE_PEI_CORE: | |
| printf ("EFI_FV_FILETYPE_PEI_CORE\n"); | |
| break; | |
| case EFI_FV_FILETYPE_DXE_CORE: | |
| printf ("EFI_FV_FILETYPE_DXE_CORE\n"); | |
| break; | |
| case EFI_FV_FILETYPE_PEIM: | |
| printf ("EFI_FV_FILETYPE_PEIM\n"); | |
| break; | |
| case EFI_FV_FILETYPE_DRIVER: | |
| printf ("EFI_FV_FILETYPE_DRIVER\n"); | |
| break; | |
| case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER: | |
| printf ("EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER\n"); | |
| break; | |
| case EFI_FV_FILETYPE_APPLICATION: | |
| printf ("EFI_FV_FILETYPE_APPLICATION\n"); | |
| break; | |
| case EFI_FV_FILETYPE_SMM: | |
| printf ("EFI_FV_FILETYPE_SMM\n"); | |
| break; | |
| case EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE: | |
| printf ("EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE\n"); | |
| break; | |
| case EFI_FV_FILETYPE_COMBINED_SMM_DXE: | |
| printf ("EFI_FV_FILETYPE_COMBINED_SMM_DXE\n"); | |
| break; | |
| case EFI_FV_FILETYPE_SMM_CORE: | |
| printf ("EFI_FV_FILETYPE_SMM_CORE\n"); | |
| break; | |
| case EFI_FV_FILETYPE_FFS_PAD: | |
| printf ("EFI_FV_FILETYPE_FFS_PAD\n"); | |
| break; | |
| default: | |
| printf ("\nERROR: Unrecognized file type %X.\n", FileHeader->Type); | |
| return EFI_ABORTED; | |
| break; | |
| } | |
| switch (FileHeader->Type) { | |
| case EFI_FV_FILETYPE_ALL: | |
| case EFI_FV_FILETYPE_RAW: | |
| case EFI_FV_FILETYPE_FFS_PAD: | |
| break; | |
| default: | |
| // | |
| // All other files have sections | |
| // | |
| Status = ParseSection ( | |
| (UINT8 *) ((UINTN) FileHeader + HeaderSize), | |
| FvBufGetFfsFileSize (FileHeader) - HeaderSize | |
| ); | |
| if (EFI_ERROR (Status)) { | |
| // | |
| // printf ("ERROR: Parsing the FFS file.\n"); | |
| // | |
| return EFI_ABORTED; | |
| } | |
| break; | |
| } | |
| return EFI_SUCCESS; | |
| } | |
| 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; | |
| } | |
| } | |
| // | |
| // 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 | |
| ) | |
| /*++ | |
| Routine Description: | |
| Parses EFI Sections | |
| Arguments: | |
| SectionBuffer - Buffer containing the section to parse. | |
| BufferLength - Length of SectionBuffer | |
| Returns: | |
| EFI_SECTION_ERROR - Problem with section parsing. | |
| (a) compression errors | |
| (b) unrecognized section | |
| EFI_UNSUPPORTED - Do not know how to parse the section. | |
| EFI_SUCCESS - Section successfully parsed. | |
| EFI_OUT_OF_RESOURCES - Memory allocation failed. | |
| --*/ | |
| { | |
| EFI_SECTION_TYPE Type; | |
| UINT8 *Ptr; | |
| UINT32 SectionLength; | |
| UINT32 SectionHeaderLen; | |
| CHAR8 *SectionName; | |
| EFI_STATUS Status; | |
| UINT32 ParsedLength; | |
| UINT8 *CompressedBuffer; | |
| UINT32 CompressedLength; | |
| UINT8 *UncompressedBuffer; | |
| UINT32 UncompressedLength; | |
| UINT8 *ToolOutputBuffer; | |
| UINT32 ToolOutputLength; | |
| UINT8 CompressionType; | |
| UINT32 DstSize; | |
| UINT32 ScratchSize; | |
| UINT8 *ScratchBuffer; | |
| DECOMPRESS_FUNCTION DecompressFunction; | |
| GETINFO_FUNCTION GetInfoFunction; | |
| // CHAR16 *name; | |
| CHAR8 *ExtractionTool; | |
| CHAR8 *ToolInputFile; | |
| CHAR8 *ToolOutputFile; | |
| CHAR8 *SystemCommandFormatString; | |
| CHAR8 *SystemCommand; | |
| EFI_GUID *EfiGuid; | |
| UINT16 DataOffset; | |
| UINT16 Attributes; | |
| UINT32 RealHdrLen; | |
| CHAR8 *ToolInputFileName; | |
| CHAR8 *ToolOutputFileName; | |
| ParsedLength = 0; | |
| ToolInputFileName = NULL; | |
| ToolOutputFileName = NULL; | |
| while (ParsedLength < BufferLength) { | |
| Ptr = SectionBuffer + ParsedLength; | |
| SectionLength = GetLength (((EFI_COMMON_SECTION_HEADER *) Ptr)->Size); | |
| Type = ((EFI_COMMON_SECTION_HEADER *) Ptr)->Type; | |
| // | |
| // This is sort of an odd check, but is necessary because FFS files are | |
| // padded to a QWORD boundary, meaning there is potentially a whole section | |
| // header worth of 0xFF bytes. | |
| // | |
| if (SectionLength == 0xffffff && Type == 0xff) { | |
| ParsedLength += 4; | |
| continue; | |
| } | |
| // | |
| // Get real section file size | |
| // | |
| SectionLength = GetSectionFileLength ((EFI_COMMON_SECTION_HEADER *) Ptr); | |
| SectionHeaderLen = GetSectionHeaderLength((EFI_COMMON_SECTION_HEADER *)Ptr); | |
| SectionName = SectionNameToStr (Type); | |
| printf ("------------------------------------------------------------\n"); | |
| printf (" Type: %s\n Size: 0x%08X\n", SectionName, (unsigned) SectionLength); | |
| free (SectionName); | |
| switch (Type) { | |
| case EFI_SECTION_RAW: | |
| 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; | |
| case EFI_SECTION_FIRMWARE_VOLUME_IMAGE: | |
| Status = PrintFvInfo (Ptr + SectionHeaderLen, TRUE); | |
| if (EFI_ERROR (Status)) { | |
| Error (NULL, 0, 0003, "printing of FV section contents failed", NULL); | |
| return EFI_SECTION_ERROR; | |
| } | |
| break; | |
| case EFI_SECTION_COMPATIBILITY16: | |
| case EFI_SECTION_FREEFORM_SUBTYPE_GUID: | |
| // | |
| // Section does not contain any further header information. | |
| // | |
| break; | |
| case EFI_SECTION_PEI_DEPEX: | |
| case EFI_SECTION_DXE_DEPEX: | |
| case EFI_SECTION_SMM_DEPEX: | |
| DumpDepexSection (Ptr, SectionLength); | |
| break; | |
| case EFI_SECTION_VERSION: | |
| printf (" Build Number: 0x%02X\n", *(UINT16 *)(Ptr + SectionHeaderLen)); | |
| printf (" Version Strg: %s\n", (char*) (Ptr + SectionHeaderLen + sizeof (UINT16))); | |
| break; | |
| case EFI_SECTION_COMPRESSION: | |
| UncompressedBuffer = NULL; | |
| if (SectionHeaderLen == sizeof (EFI_COMMON_SECTION_HEADER)) { | |
| RealHdrLen = sizeof(EFI_COMPRESSION_SECTION); | |
| UncompressedLength = ((EFI_COMPRESSION_SECTION *)Ptr)->UncompressedLength; | |
| CompressionType = ((EFI_COMPRESSION_SECTION *)Ptr)->CompressionType; | |
| } else { | |
| RealHdrLen = sizeof(EFI_COMPRESSION_SECTION2); | |
| UncompressedLength = ((EFI_COMPRESSION_SECTION2 *)Ptr)->UncompressedLength; | |
| CompressionType = ((EFI_COMPRESSION_SECTION2 *)Ptr)->CompressionType; | |
| } | |
| CompressedLength = SectionLength - RealHdrLen; | |
| printf (" Uncompressed Length: 0x%08X\n", (unsigned) UncompressedLength); | |
| if (CompressionType == EFI_NOT_COMPRESSED) { | |
| printf (" Compression Type: EFI_NOT_COMPRESSED\n"); | |
| if (CompressedLength != UncompressedLength) { | |
| Error ( | |
| NULL, | |
| 0, | |
| 0, | |
| "file is not compressed, but the compressed length does not match the uncompressed length", | |
| NULL | |
| ); | |
| return EFI_SECTION_ERROR; | |
| } | |
| UncompressedBuffer = Ptr + RealHdrLen; | |
| } else if (CompressionType == EFI_STANDARD_COMPRESSION) { | |
| GetInfoFunction = EfiGetInfo; | |
| DecompressFunction = EfiDecompress; | |
| printf (" Compression Type: EFI_STANDARD_COMPRESSION\n"); | |
| CompressedBuffer = Ptr + RealHdrLen; | |
| Status = GetInfoFunction (CompressedBuffer, CompressedLength, &DstSize, &ScratchSize); | |
| if (EFI_ERROR (Status)) { | |
| Error (NULL, 0, 0003, "error getting compression info from compression section", NULL); | |
| return EFI_SECTION_ERROR; | |
| } | |
| if (DstSize != UncompressedLength) { | |
| Error (NULL, 0, 0003, "compression error in the compression section", NULL); | |
| return EFI_SECTION_ERROR; | |
| } | |
| ScratchBuffer = malloc (ScratchSize); | |
| UncompressedBuffer = malloc (UncompressedLength); | |
| if ((ScratchBuffer == NULL) || (UncompressedBuffer == NULL)) { | |
| return EFI_OUT_OF_RESOURCES; | |
| } | |
| Status = DecompressFunction ( | |
| CompressedBuffer, | |
| CompressedLength, | |
| UncompressedBuffer, | |
| UncompressedLength, | |
| ScratchBuffer, | |
| ScratchSize | |
| ); | |
| free (ScratchBuffer); | |
| if (EFI_ERROR (Status)) { | |
| Error (NULL, 0, 0003, "decompress failed", NULL); | |
| free (UncompressedBuffer); | |
| return EFI_SECTION_ERROR; | |
| } | |
| } else { | |
| Error (NULL, 0, 0003, "unrecognized compression type", "type 0x%X", CompressionType); | |
| return EFI_SECTION_ERROR; | |
| } | |
| Status = ParseSection (UncompressedBuffer, UncompressedLength); | |
| if (CompressionType == EFI_STANDARD_COMPRESSION) { | |
| // | |
| // We need to deallocate Buffer | |
| // | |
| free (UncompressedBuffer); | |
| } | |
| if (EFI_ERROR (Status)) { | |
| Error (NULL, 0, 0003, "failed to parse section", NULL); | |
| return EFI_SECTION_ERROR; | |
| } | |
| break; | |
| case EFI_SECTION_GUID_DEFINED: | |
| if (SectionHeaderLen == sizeof(EFI_COMMON_SECTION_HEADER)) { | |
| EfiGuid = &((EFI_GUID_DEFINED_SECTION *) Ptr)->SectionDefinitionGuid; | |
| DataOffset = ((EFI_GUID_DEFINED_SECTION *) Ptr)->DataOffset; | |
| Attributes = ((EFI_GUID_DEFINED_SECTION *) Ptr)->Attributes; | |
| } else { | |
| EfiGuid = &((EFI_GUID_DEFINED_SECTION2 *) Ptr)->SectionDefinitionGuid; | |
| DataOffset = ((EFI_GUID_DEFINED_SECTION2 *) Ptr)->DataOffset; | |
| Attributes = ((EFI_GUID_DEFINED_SECTION2 *) Ptr)->Attributes; | |
| } | |
| printf (" SectionDefinitionGuid: "); | |
| PrintGuid (EfiGuid); | |
| printf ("\n"); | |
| printf (" DataOffset: 0x%04X\n", (unsigned) DataOffset); | |
| printf (" Attributes: 0x%04X\n", (unsigned) Attributes); | |
| ExtractionTool = | |
| LookupGuidedSectionToolPath ( | |
| mParsedGuidedSectionTools, | |
| EfiGuid | |
| ); | |
| if (ExtractionTool != NULL) { | |
| #ifndef __GNUC__ | |
| ToolInputFile = CloneString (tmpnam (NULL)); | |
| ToolOutputFile = CloneString (tmpnam (NULL)); | |
| #else | |
| char tmp1[] = "/tmp/fileXXXXXX"; | |
| char tmp2[] = "/tmp/fileXXXXXX"; | |
| int fd1; | |
| int fd2; | |
| fd1 = mkstemp(tmp1); | |
| fd2 = mkstemp(tmp2); | |
| ToolInputFile = CloneString(tmp1); | |
| ToolOutputFile = CloneString(tmp2); | |
| close(fd1); | |
| close(fd2); | |
| #endif | |
| // | |
| // Construction 'system' command string | |
| // | |
| SystemCommandFormatString = "%s -d -o %s %s"; | |
| SystemCommand = malloc ( | |
| strlen (SystemCommandFormatString) + | |
| strlen (ExtractionTool) + | |
| strlen (ToolInputFile) + | |
| strlen (ToolOutputFile) + | |
| 1 | |
| ); | |
| sprintf ( | |
| SystemCommand, | |
| SystemCommandFormatString, | |
| ExtractionTool, | |
| ToolOutputFile, | |
| ToolInputFile | |
| ); | |
| free (ExtractionTool); | |
| Status = | |
| PutFileImage ( | |
| ToolInputFile, | |
| (CHAR8*) SectionBuffer + DataOffset, | |
| BufferLength - DataOffset | |
| ); | |
| system (SystemCommand); | |
| remove (ToolInputFile); | |
| free (ToolInputFile); | |
| Status = | |
| GetFileImage ( | |
| ToolOutputFile, | |
| (CHAR8 **)&ToolOutputBuffer, | |
| &ToolOutputLength | |
| ); | |
| remove (ToolOutputFile); | |
| free (ToolOutputFile); | |
| if (EFI_ERROR (Status)) { | |
| Error (NULL, 0, 0004, "unable to read decoded GUIDED section", NULL); | |
| return EFI_SECTION_ERROR; | |
| } | |
| Status = ParseSection ( | |
| ToolOutputBuffer, | |
| ToolOutputLength | |
| ); | |
| if (EFI_ERROR (Status)) { | |
| Error (NULL, 0, 0003, "parse of decoded GUIDED section failed", NULL); | |
| return EFI_SECTION_ERROR; | |
| } | |
| // | |
| // Check for CRC32 sections which we can handle internally if needed. | |
| // | |
| } else if (!CompareGuid ( | |
| EfiGuid, | |
| &gEfiCrc32GuidedSectionExtractionProtocolGuid | |
| ) | |
| ) { | |
| // | |
| // CRC32 guided section | |
| // | |
| Status = ParseSection ( | |
| SectionBuffer + DataOffset, | |
| BufferLength - DataOffset | |
| ); | |
| if (EFI_ERROR (Status)) { | |
| Error (NULL, 0, 0003, "parse of CRC32 GUIDED section failed", NULL); | |
| return EFI_SECTION_ERROR; | |
| } | |
| } else { | |
| // | |
| // We don't know how to parse it now. | |
| // | |
| Error (NULL, 0, 0003, "Error parsing section", \ | |
| "EFI_SECTION_GUID_DEFINED cannot be parsed at this time. Tool to decode this section should have been defined in GuidedSectionTools.txt (built in the FV directory)."); | |
| return EFI_UNSUPPORTED; | |
| } | |
| break; | |
| default: | |
| // | |
| // Unknown section, return error | |
| // | |
| Error (NULL, 0, 0003, "unrecognized section type found", "section type = 0x%X", Type); | |
| return EFI_SECTION_ERROR; | |
| } | |
| ParsedLength += SectionLength; | |
| // | |
| // We make then next section begin on a 4-byte boundary | |
| // | |
| ParsedLength = GetOccupiedSize (ParsedLength, 4); | |
| } | |
| if (ParsedLength < BufferLength) { | |
| Error (NULL, 0, 0003, "sections do not completely fill the sectioned buffer being parsed", NULL); | |
| return EFI_SECTION_ERROR; | |
| } | |
| return EFI_SUCCESS; | |
| } | |
| EFI_STATUS | |
| DumpDepexSection ( | |
| IN UINT8 *Ptr, | |
| IN UINT32 SectionLength | |
| ) | |
| /*++ | |
| Routine Description: | |
| GC_TODO: Add function description | |
| Arguments: | |
| Ptr - GC_TODO: add argument description | |
| SectionLength - GC_TODO: add argument description | |
| Returns: | |
| EFI_SUCCESS - GC_TODO: Add description for return value | |
| --*/ | |
| { | |
| UINT8 GuidBuffer[PRINTED_GUID_BUFFER_SIZE]; | |
| // | |
| // Need at least a section header + data | |
| // | |
| if (SectionLength <= sizeof (EFI_COMMON_SECTION_HEADER)) { | |
| return EFI_SUCCESS; | |
| } | |
| Ptr += GetSectionHeaderLength((EFI_COMMON_SECTION_HEADER *)Ptr); | |
| SectionLength -= GetSectionHeaderLength((EFI_COMMON_SECTION_HEADER *)Ptr); | |
| while (SectionLength > 0) { | |
| printf (" "); | |
| switch (*Ptr) { | |
| case EFI_DEP_BEFORE: | |
| printf ("BEFORE\n"); | |
| Ptr++; | |
| SectionLength--; | |
| break; | |
| case EFI_DEP_AFTER: | |
| printf ("AFTER\n"); | |
| Ptr++; | |
| SectionLength--; | |
| break; | |
| case EFI_DEP_PUSH: | |
| printf ("PUSH\n "); | |
| PrintGuidToBuffer ((EFI_GUID *) (Ptr + 1), GuidBuffer, sizeof (GuidBuffer), TRUE); | |
| printf ("%s ", GuidBuffer); | |
| PrintGuidName (GuidBuffer); | |
| printf ("\n"); | |
| // | |
| // PrintGuid ((EFI_GUID *)(Ptr + 1)); | |
| // | |
| Ptr += 17; | |
| SectionLength -= 17; | |
| break; | |
| case EFI_DEP_AND: | |
| printf ("AND\n"); | |
| Ptr++; | |
| SectionLength--; | |
| break; | |
| case EFI_DEP_OR: | |
| printf ("OR\n"); | |
| Ptr++; | |
| SectionLength--; | |
| break; | |
| case EFI_DEP_NOT: | |
| printf ("NOT\n"); | |
| Ptr++; | |
| SectionLength--; | |
| break; | |
| case EFI_DEP_TRUE: | |
| printf ("TRUE\n"); | |
| Ptr++; | |
| SectionLength--; | |
| break; | |
| case EFI_DEP_FALSE: | |
| printf ("FALSE\n"); | |
| Ptr++; | |
| SectionLength--; | |
| break; | |
| case EFI_DEP_END: | |
| printf ("END DEPEX\n"); | |
| Ptr++; | |
| SectionLength--; | |
| break; | |
| case EFI_DEP_SOR: | |
| printf ("SOR\n"); | |
| Ptr++; | |
| SectionLength--; | |
| break; | |
| default: | |
| printf ("Unrecognized byte in depex: 0x%X\n", *Ptr); | |
| return EFI_SUCCESS; | |
| } | |
| } | |
| return EFI_SUCCESS; | |
| } | |
| EFI_STATUS | |
| PrintGuidName ( | |
| IN UINT8 *GuidStr | |
| ) | |
| /*++ | |
| Routine Description: | |
| GC_TODO: Add function description | |
| Arguments: | |
| GuidStr - GC_TODO: add argument description | |
| Returns: | |
| EFI_SUCCESS - GC_TODO: Add description for return value | |
| EFI_INVALID_PARAMETER - GC_TODO: Add description for return value | |
| --*/ | |
| { | |
| GUID_TO_BASENAME *GPtr; | |
| // | |
| // If we have a list of guid-to-basenames, then go through the list to | |
| // look for a guid string match. If found, print the basename to stdout, | |
| // otherwise return a failure. | |
| // | |
| GPtr = mGuidBaseNameList; | |
| while (GPtr != NULL) { | |
| if (_stricmp ((CHAR8*) GuidStr, (CHAR8*) GPtr->Guid) == 0) { | |
| printf ("%s", GPtr->BaseName); | |
| return EFI_SUCCESS; | |
| } | |
| GPtr = GPtr->Next; | |
| } | |
| return EFI_INVALID_PARAMETER; | |
| } | |
| EFI_STATUS | |
| ParseGuidBaseNameFile ( | |
| CHAR8 *FileName | |
| ) | |
| /*++ | |
| Routine Description: | |
| GC_TODO: Add function description | |
| Arguments: | |
| FileName - GC_TODO: add argument description | |
| Returns: | |
| EFI_DEVICE_ERROR - GC_TODO: Add description for return value | |
| EFI_OUT_OF_RESOURCES - GC_TODO: Add description for return value | |
| EFI_SUCCESS - GC_TODO: Add description for return value | |
| --*/ | |
| { | |
| FILE *Fptr; | |
| CHAR8 Line[MAX_LINE_LEN]; | |
| GUID_TO_BASENAME *GPtr; | |
| if ((Fptr = fopen (LongFilePath (FileName), "r")) == NULL) { | |
| printf ("ERROR: Failed to open input cross-reference file '%s'\n", FileName); | |
| return EFI_DEVICE_ERROR; | |
| } | |
| while (fgets (Line, sizeof (Line), Fptr) != NULL) { | |
| // | |
| // Allocate space for another guid/basename element | |
| // | |
| GPtr = malloc (sizeof (GUID_TO_BASENAME)); | |
| if (GPtr == NULL) { | |
| return EFI_OUT_OF_RESOURCES; | |
| } | |
| memset ((char *) GPtr, 0, sizeof (GUID_TO_BASENAME)); | |
| if (sscanf (Line, "%s %s", GPtr->Guid, GPtr->BaseName) == 2) { | |
| GPtr->Next = mGuidBaseNameList; | |
| mGuidBaseNameList = GPtr; | |
| } else { | |
| // | |
| // Some sort of error. Just continue. | |
| // | |
| free (GPtr); | |
| } | |
| } | |
| fclose (Fptr); | |
| return EFI_SUCCESS; | |
| } | |
| EFI_STATUS | |
| FreeGuidBaseNameList ( | |
| VOID | |
| ) | |
| /*++ | |
| Routine Description: | |
| GC_TODO: Add function description | |
| Arguments: | |
| None | |
| Returns: | |
| EFI_SUCCESS - GC_TODO: Add description for return value | |
| --*/ | |
| { | |
| GUID_TO_BASENAME *Next; | |
| while (mGuidBaseNameList != NULL) { | |
| Next = mGuidBaseNameList->Next; | |
| free (mGuidBaseNameList); | |
| mGuidBaseNameList = Next; | |
| } | |
| return EFI_SUCCESS; | |
| } | |
| static | |
| VOID | |
| LoadGuidedSectionToolsTxt ( | |
| IN CHAR8* FirmwareVolumeFilename | |
| ) | |
| { | |
| CHAR8* PeerFilename; | |
| CHAR8* Places[] = { | |
| NULL, | |
| //NULL, | |
| }; | |
| UINTN Index; | |
| Places[0] = FirmwareVolumeFilename; | |
| //Places[1] = mUtilityFilename; | |
| mParsedGuidedSectionTools = NULL; | |
| for (Index = 0; Index < (sizeof(Places)/sizeof(Places[0])); Index++) { | |
| PeerFilename = OsPathPeerFilePath (Places[Index], "GuidedSectionTools.txt"); | |
| //printf("Loading %s...\n", PeerFilename); | |
| if (OsPathExists (PeerFilename)) { | |
| mParsedGuidedSectionTools = ParseGuidedSectionToolsFile (PeerFilename); | |
| } | |
| free (PeerFilename); | |
| if (mParsedGuidedSectionTools != NULL) { | |
| return; | |
| } | |
| } | |
| } | |
| void | |
| Usage ( | |
| VOID | |
| ) | |
| /*++ | |
| Routine Description: | |
| GC_TODO: Add function description | |
| Arguments: | |
| None | |
| Returns: | |
| GC_TODO: add return values | |
| --*/ | |
| { | |
| // | |
| // Summary usage | |
| // | |
| fprintf (stdout, "Usage: %s [options] <input_file>\n\n", UTILITY_NAME); | |
| // | |
| // Copyright declaration | |
| // | |
| fprintf (stdout, "Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.\n\n"); | |
| fprintf (stdout, " Display Tiano Firmware Volume FFS image information\n\n"); | |
| // | |
| // Details Option | |
| // | |
| fprintf (stdout, "optional arguments:\n"); | |
| fprintf (stdout, " -h, --help\n\ | |
| Show this help message and exit\n"); | |
| fprintf (stdout, " --version\n\ | |
| Show program's version number and exit\n"); | |
| fprintf (stdout, " -d [DEBUG], --debug [DEBUG]\n\ | |
| Output DEBUG statements, where DEBUG_LEVEL is 0 (min) - 9 (max)\n"); | |
| fprintf (stdout, " -v, --verbose\n\ | |
| Print informational statements\n"); | |
| fprintf (stdout, " -q, --quiet\n\ | |
| Returns the exit code, error messages will be displayed\n"); | |
| fprintf (stdout, " -s, --silent\n\ | |
| Returns only the exit code; informational and error\n\ | |
| messages are not displayed\n"); | |
| fprintf (stdout, " -x XREF_FILENAME, --xref XREF_FILENAME\n\ | |
| Parse the basename to file-guid cross reference file(s)\n"); | |
| 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"); | |
| } | |