| /** @file |
| |
| Copyright (c) 1999 - 2011, 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. |
| |
| Module Name: |
| |
| VolInfo.c |
| |
| Abstract: |
| |
| The tool dumps the contents of a firmware volume |
| |
| **/ |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <ctype.h> |
| #include <assert.h> |
| |
| #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" |
| |
| // |
| // Utility global variables |
| // |
| |
| EFI_GUID gEfiCrc32GuidedSectionExtractionProtocolGuid = EFI_CRC32_GUIDED_SECTION_EXTRACTION_PROTOCOL_GUID; |
| |
| #define UTILITY_MAJOR_VERSION 0 |
| #define UTILITY_MINOR_VERSION 82 |
| |
| #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; |
| |
| 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 |
| ); |
| |
| 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; |
| |
| SetUtilityName (UTILITY_NAME); |
| // |
| // Print utility header |
| // |
| printf ("%s Tiano Firmware Volume FFS image info. Version %d.%d %s, %s\n", |
| UTILITY_NAME, |
| UTILITY_MAJOR_VERSION, |
| UTILITY_MINOR_VERSION, |
| __BUILD_VERSION, |
| __DATE__ |
| ); |
| |
| // |
| // Save, and then skip filename arg |
| // |
| mUtilityFilename = argv[0]; |
| argc--; |
| argv++; |
| |
| Offset = 0; |
| |
| // |
| // 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 > 2) { |
| if ((strcmp(argv[0], "-x") == 0) || (strcmp(argv[0], "--xref") == 0)) { |
| ParseGuidBaseNameFile (argv[1]); |
| printf("ParseGuidBaseNameFile: %s\n", argv[1]); |
| argc -= 2; |
| argv += 2; |
| } else 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; |
| } else { |
| Usage (); |
| return -1; |
| } |
| } |
| // |
| // Check for proper number of arguments |
| // |
| if (argc != 1) { |
| Usage (); |
| return -1; |
| } |
| // |
| // 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_ERROR; |
| } |
| |
| // |
| // Open the file containing the FV |
| // |
| InputFile = fopen (argv[0], "rb"); |
| if (InputFile == NULL) { |
| Error (NULL, 0, 0001, "Error opening the input file", argv[0]); |
| 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", argv[0]); |
| 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", argv[0]); |
| free (FvImage); |
| return GetUtilityStatus (); |
| } |
| |
| LoadGuidedSectionToolsTxt (argv[0]); |
| |
| 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_HEADER BlankHeader; |
| EFI_STATUS Status; |
| UINT8 GuidBuffer[PRINTED_GUID_BUFFER_SIZE]; |
| #if (PI_SPECIFICATION_VERSION < 0x00010000) |
| UINT16 *Tail; |
| #endif |
| // |
| // Check if we have free space |
| // |
| if (ErasePolarity) { |
| memset (&BlankHeader, -1, sizeof (EFI_FFS_FILE_HEADER)); |
| } else { |
| memset (&BlankHeader, 0, sizeof (EFI_FFS_FILE_HEADER)); |
| } |
| |
| if (memcmp (&BlankHeader, FileHeader, sizeof (EFI_FFS_FILE_HEADER)) == 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 = GetLength (FileHeader->Size); |
| 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, sizeof (EFI_FFS_FILE_HEADER)); |
| 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, sizeof (EFI_FFS_FILE_HEADER)); |
| 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 = GetLength (FileHeader->Size); |
| |
| if (FileHeader->Attributes & FFS_ATTRIB_CHECKSUM) { |
| // |
| // Calculate file checksum |
| // |
| Checksum = CalculateSum8 ((UINT8 *) (FileHeader + 1), FileLength - sizeof (EFI_FFS_FILE_HEADER)); |
| 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 + sizeof (EFI_FFS_FILE_HEADER)), |
| GetLength (FileHeader->Size) - sizeof (EFI_FFS_FILE_HEADER) |
| ); |
| if (EFI_ERROR (Status)) { |
| // |
| // printf ("ERROR: Parsing the FFS file.\n"); |
| // |
| return EFI_ABORTED; |
| } |
| break; |
| } |
| |
| 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; |
| 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; |
| |
| ParsedLength = 0; |
| 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; |
| } |
| |
| 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_PE32: |
| case EFI_SECTION_PIC: |
| case EFI_SECTION_TE: |
| // default is no more information |
| break; |
| |
| case EFI_SECTION_USER_INTERFACE: |
| // name = &((EFI_USER_INTERFACE_SECTION *) Ptr)->FileNameString; |
| // printf (" String: %s\n", &name); |
| break; |
| |
| case EFI_SECTION_FIRMWARE_VOLUME_IMAGE: |
| Status = PrintFvInfo (((EFI_FIRMWARE_VOLUME_IMAGE_SECTION*)Ptr) + 1, 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", ((EFI_VERSION_SECTION *) Ptr)->BuildNumber); |
| printf (" Version Strg: %s\n", (char*) ((EFI_VERSION_SECTION *) Ptr)->VersionString); |
| break; |
| |
| case EFI_SECTION_COMPRESSION: |
| UncompressedBuffer = NULL; |
| CompressedLength = SectionLength - sizeof (EFI_COMPRESSION_SECTION); |
| UncompressedLength = ((EFI_COMPRESSION_SECTION *) Ptr)->UncompressedLength; |
| CompressionType = ((EFI_COMPRESSION_SECTION *) Ptr)->CompressionType; |
| 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 + sizeof (EFI_COMPRESSION_SECTION); |
| } else if (CompressionType == EFI_STANDARD_COMPRESSION) { |
| GetInfoFunction = EfiGetInfo; |
| DecompressFunction = EfiDecompress; |
| printf (" Compression Type: EFI_STANDARD_COMPRESSION\n"); |
| |
| CompressedBuffer = Ptr + sizeof (EFI_COMPRESSION_SECTION); |
| |
| 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: |
| printf (" SectionDefinitionGuid: "); |
| PrintGuid (&((EFI_GUID_DEFINED_SECTION *) Ptr)->SectionDefinitionGuid); |
| printf ("\n"); |
| printf (" DataOffset: 0x%04X\n", (unsigned) ((EFI_GUID_DEFINED_SECTION *) Ptr)->DataOffset); |
| printf (" Attributes: 0x%04X\n", (unsigned) ((EFI_GUID_DEFINED_SECTION *) Ptr)->Attributes); |
| |
| ExtractionTool = |
| LookupGuidedSectionToolPath ( |
| mParsedGuidedSectionTools, |
| &((EFI_GUID_DEFINED_SECTION *) Ptr)->SectionDefinitionGuid |
| ); |
| |
| if (ExtractionTool != NULL) { |
| |
| ToolInputFile = CloneString (tmpnam (NULL)); |
| ToolOutputFile = CloneString (tmpnam (NULL)); |
| |
| // |
| // 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 + ((EFI_GUID_DEFINED_SECTION *) Ptr)->DataOffset, |
| BufferLength - ((EFI_GUID_DEFINED_SECTION *) Ptr)->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 ( |
| &((EFI_GUID_DEFINED_SECTION *) Ptr)->SectionDefinitionGuid, |
| &gEfiCrc32GuidedSectionExtractionProtocolGuid |
| ) |
| ) { |
| // |
| // CRC32 guided section |
| // |
| Status = ParseSection ( |
| SectionBuffer + ((EFI_GUID_DEFINED_SECTION *) Ptr)->DataOffset, |
| BufferLength - ((EFI_GUID_DEFINED_SECTION *) Ptr)->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 += sizeof (EFI_COMMON_SECTION_HEADER); |
| SectionLength -= sizeof (EFI_COMMON_SECTION_HEADER); |
| 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 (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 - 2010, Intel Corporation. All rights reserved.\n\n"); |
| |
| // |
| // Details Option |
| // |
| fprintf (stdout, "Options:\n"); |
| fprintf (stdout, " -x xref, --xref xref\n\ |
| Parse basename to file-guid cross reference file(s).\n"); |
| fprintf (stdout, " --offset offset\n\ |
| Offset of file to start processing FV at.\n"); |
| fprintf (stdout, " -h, --help\n\ |
| Show this help message and exit.\n"); |
| |
| } |
| |