mirror of https://github.com/acidanthera/audk.git
1819 lines
44 KiB
C
1819 lines
44 KiB
C
/** @file
|
|
|
|
Copyright (c) 1999 - 2010, Intel Corporation
|
|
All rights reserved. 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
|
|
);
|
|
|
|
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\n",
|
|
UTILITY_NAME,
|
|
UTILITY_MAJOR_VERSION,
|
|
UTILITY_MINOR_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);
|
|
|
|
//
|
|
// Clean up
|
|
//
|
|
free (FvImage);
|
|
FreeGuidBaseNameList ();
|
|
return GetUtilityStatus ();
|
|
}
|
|
|
|
|
|
static
|
|
EFI_STATUS
|
|
PrintFvInfo (
|
|
IN VOID *Fv
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
GC_TODO: Add function description
|
|
|
|
Arguments:
|
|
|
|
Fv - Firmware Volume to print information about
|
|
|
|
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 ();
|
|
}
|
|
}
|
|
|
|
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_ALIGNMNET_512K) {
|
|
printf (" EFI_FVB2_ALIGNMNET_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);
|
|
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");
|
|
|
|
}
|
|
|