audk/BaseTools/Source/C/FMMT/FmmtLib.c
Shenglei Zhang 080981d72d BaseTools/FMMT: Add a tool FMMT
FMMT is a tool to enable removal, addition and replacement of
FFS files in FD image binaries.
https://bugzilla.tianocore.org/show_bug.cgi?id=1847

Cc: Bob Feng <bob.c.feng@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Signed-off-by: Shenglei Zhang <shenglei.zhang@intel.com>
Reviewed-by: Bob Feng <bob.c.feng@intel.com>
2019-07-04 11:34:57 +08:00

5052 lines
164 KiB
C

/** @file
Library to parse and generate FV image.
Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include "FirmwareModuleManagement.h"
#define EFI_TEST_FFS_ATTRIBUTES_BIT(FvbAttributes, TestAttributes, Bit) \
( \
(BOOLEAN) ( \
(FvbAttributes & EFI_FVB2_ERASE_POLARITY) ? (((~TestAttributes) & Bit) == Bit) : ((TestAttributes & Bit) == Bit) \
) \
)
CHAR8 mFirmwareFileSystem2Guid[16] = {0x78, 0xE5, 0x8C, 0x8C, 0x3D, 0x8A, 0x1C, 0x4F, 0x99, 0x35, 0x89, 0x61, 0x85, 0xC3, 0x2D, 0xD3};
CHAR8 mFirmwareFileSystem3Guid[16] = {0x7A, 0xC0, 0x73, 0x54, 0xCB, 0x3D, 0xCA, 0x4D, 0xBD, 0x6F, 0x1E, 0x96, 0x89, 0xE7, 0x34, 0x9A };
EFI_GUID mEfiCrc32GuidedSectionExtractionProtocolGuid = EFI_CRC32_GUIDED_SECTION_EXTRACTION_PROTOCOL_GUID;
extern CHAR8* mGuidToolDefinition;
static CHAR8 *mSectionTypeName[] = {
NULL, // 0x00 - reserved
"EFI_SECTION_COMPRESSION", // 0x01
"EFI_SECTION_GUID_DEFINED", // 0x02
NULL, // 0x03 - reserved
NULL, // 0x04 - reserved
NULL, // 0x05 - reserved
NULL, // 0x06 - reserved
NULL, // 0x07 - reserved
NULL, // 0x08 - reserved
NULL, // 0x09 - reserved
NULL, // 0x0A - reserved
NULL, // 0x0B - reserved
NULL, // 0x0C - reserved
NULL, // 0x0D - reserved
NULL, // 0x0E - reserved
NULL, // 0x0F - reserved
"EFI_SECTION_PE32", // 0x10
"EFI_SECTION_PIC", // 0x11
"EFI_SECTION_TE", // 0x12
"EFI_SECTION_DXE_DEPEX", // 0x13
"EFI_SECTION_VERSION", // 0x14
"EFI_SECTION_USER_INTERFACE", // 0x15
"EFI_SECTION_COMPATIBILITY16", // 0x16
"EFI_SECTION_FIRMWARE_VOLUME_IMAGE", // 0x17
"EFI_SECTION_FREEFORM_SUBTYPE_GUID", // 0x18
"EFI_SECTION_RAW", // 0x19
NULL, // 0x1A
"EFI_SECTION_PEI_DEPEX", // 0x1B
"EFI_SECTION_SMM_DEPEX" // 0x1C
};
static CHAR8 *mFfsFileType[] = {
NULL, // 0x00
"EFI_FV_FILETYPE_RAW", // 0x01
"EFI_FV_FILETYPE_FREEFORM", // 0x02
"EFI_FV_FILETYPE_SECURITY_CORE", // 0x03
"EFI_FV_FILETYPE_PEI_CORE", // 0x04
"EFI_FV_FILETYPE_DXE_CORE", // 0x05
"EFI_FV_FILETYPE_PEIM", // 0x06
"EFI_FV_FILETYPE_DRIVER", // 0x07
"EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER", // 0x08
"EFI_FV_FILETYPE_APPLICATION", // 0x09
"EFI_FV_FILETYPE_SMM", // 0x0A
"EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE",// 0x0B
"EFI_FV_FILETYPE_COMBINED_SMM_DXE", // 0x0C
"EFI_FV_FILETYPE_SMM_CORE" // 0x0D
};
static CHAR8 *mGuidSectionAttr[] = {
"NONE", // 0x00
"PROCESSING_REQUIRED", // 0x01
"AUTH_STATUS_VALID" // 0x02
};
static EFI_GUID mFvUiGuid = {
0xA67DF1FA, 0x8DE8, 0x4E98, {
0xAF, 0x09, 0x4B, 0xDF, 0x2E, 0xFF, 0xBC, 0x7C
}
};
/**
Generate the unique template filename.
**/
CHAR8 *
GenTempFile (
VOID
)
{
CHAR8 *TemString;
TemString = NULL;
#ifndef __GNUC__
TemString = CloneString (tmpnam (NULL));
#else
CHAR8 tmp[] = "/tmp/fileXXXXXX";
UINTN Fdtmp;
Fdtmp = mkstemp(tmp);
TemString = CloneString(tmp);
close(Fdtmp);
#endif
return TemString;
}
static
EFI_STATUS
LibExtractFvUiName(CONST EFI_FIRMWARE_VOLUME_EXT_HEADER *FvExtHeader, CHAR8 **FvUiName)
{
UINT8 *ExtEnd;
UINT32 ExtDataSize;
EFI_FIRMWARE_VOLUME_EXT_ENTRY *ExtEntry;
EFI_FIRMWARE_VOLUME_EXT_ENTRY_GUID_TYPE *GuidEntry;
ExtEnd = (UINT8 *)FvExtHeader + FvExtHeader->ExtHeaderSize;
ExtEntry = (EFI_FIRMWARE_VOLUME_EXT_ENTRY *)(FvExtHeader + 1);
while ((UINT8 *)ExtEntry < ExtEnd) {
//
// GUID type EXT
//
if (ExtEntry->ExtEntryType == 0x0002) {
GuidEntry = (EFI_FIRMWARE_VOLUME_EXT_ENTRY_GUID_TYPE *)ExtEntry;
if (memcmp(&GuidEntry->FormatType, &mFvUiGuid, sizeof(EFI_GUID)) == 0) {
ExtDataSize = ExtEntry->ExtEntrySize - (sizeof(EFI_GUID)+sizeof(*ExtEntry));
*FvUiName = malloc(ExtDataSize + 1);
if (*FvUiName != NULL) {
memcpy(*FvUiName, (UINT8 *)GuidEntry + sizeof(EFI_GUID)+sizeof(*ExtEntry), ExtDataSize);
(*FvUiName)[ExtDataSize] = '\0';
return EFI_SUCCESS;
}
}
}
ExtEntry = (EFI_FIRMWARE_VOLUME_EXT_ENTRY *)((UINT8 *)ExtEntry + ExtEntry->ExtEntrySize);
}
return EFI_NOT_FOUND;
}
FV_INFORMATION *
LibInitializeFvStruct (
FV_INFORMATION *Fv
)
{
UINT32 Index;
if (Fv == NULL) {
return NULL;
}
for (Index = 0; Index < MAX_NUMBER_OF_FILES_IN_FV; Index ++) {
memset (Fv->FfsAttuibutes[Index].FfsName, '\0', _MAX_PATH);
memset (Fv->FfsAttuibutes[Index].UiName, '\0', _MAX_PATH);
memset (&Fv->FfsAttuibutes[Index].GuidName, '\0', sizeof(EFI_GUID));
Fv->FfsAttuibutes[Index].UiNameSize = 0;
Fv->FfsAttuibutes[Index].IsLeaf = TRUE;
Fv->FfsAttuibutes[Index].Level = 0xFF;
Fv->FfsAttuibutes[Index].TotalSectionNum = 0;
Fv->FfsAttuibutes[Index].Depex = NULL;
Fv->FfsAttuibutes[Index].DepexLen = 0;
Fv->FfsAttuibutes[Index].IsHandle = FALSE;
Fv->FfsAttuibutes[Index].IsFvStart = FALSE;
Fv->FfsAttuibutes[Index].IsFvEnd = FALSE;
}
Fv->EncapData = NULL;
Fv->FvNext = NULL;
Fv->ChildFvFFS = NULL;
Fv->FvLevel = 0;
Fv->MulFvLevel = 1;
strcpy(Fv->AlignmentStr,"8");
return Fv;
}
EFI_STATUS
LibFindFvInFd (
IN FILE *InputFile,
IN OUT FIRMWARE_DEVICE **FdData
)
{
FIRMWARE_DEVICE *LocalFdData;
UINT16 Index;
CHAR8 Ffs2Guid[16];
CHAR8 SignatureCheck[5] = "";
CHAR8 Signature[5] = "_FVH";
FV_INFORMATION *CurrentFv;
FV_INFORMATION *NewFoundFv;
BOOLEAN FirstMatch;
UINT32 FdSize;
UINT16 FvCount;
UINT8 *FdBuffer;
UINT8 *FdBufferEnd;
UINT8 *FdBufferOri;
EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
CurrentFv = NULL;
NewFoundFv = NULL;
FdBuffer = NULL;
FdBufferOri = NULL;
FirstMatch = TRUE;
Index = 0;
FdSize = 0;
FvCount = 0;
LocalFdData = NULL;
if (InputFile == NULL) {
Error ("FMMT", 0, 0001, "Error opening the input file", "");
return EFI_ABORTED;
}
//
// Find each FVs in the FD
//
fseek(InputFile,0,SEEK_SET);
fseek(InputFile,0,SEEK_END);
FdSize = ftell(InputFile);
fseek(InputFile,0,SEEK_SET);
//
// Create an FD structure to store useful information.
//
LocalFdData = (FIRMWARE_DEVICE *) malloc (sizeof (FIRMWARE_DEVICE));
if (LocalFdData == NULL) {
Error ("FMMT", 0, 0002, "Error searching FVs in the input fd", "Allocate memory error");
return EFI_OUT_OF_RESOURCES;
}
LocalFdData->Fv = (FV_INFORMATION *) malloc (sizeof (FV_INFORMATION));
if (LocalFdData->Fv == NULL) {
Error ("FMMT", 0, 0002, "Error searching FVs in the input fd", "Allocate memory error");
free (LocalFdData);
return EFI_OUT_OF_RESOURCES;
}
LibInitializeFvStruct (LocalFdData->Fv);
//
// Readout the FD file data to buffer.
//
FdBuffer = malloc (FdSize);
if (FdBuffer == NULL) {
Error ("FMMT", 0, 0002, "Error searching FVs in the input fd", "Allocate memory error");
free (LocalFdData->Fv);
free (LocalFdData);
return EFI_OUT_OF_RESOURCES;
}
if (fread (FdBuffer, 1, FdSize, InputFile) != FdSize) {
Error ("FMMT", 0, 0002, "Error searching FVs in the input fd", "Read FD file error!");
free (LocalFdData->Fv);
free (LocalFdData);
free (FdBuffer);
return EFI_ABORTED;
}
FdBufferOri = FdBuffer;
FdBufferEnd = FdBuffer + FdSize;
while (FdBuffer <= FdBufferEnd - sizeof (EFI_FIRMWARE_VOLUME_HEADER)) {
FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) FdBuffer;
//
// Copy 4 bytes of fd data to check the _FVH signature
//
memcpy (SignatureCheck, &FvHeader->Signature, 4);
if (strncmp(SignatureCheck, Signature, 4) == 0){
//
// Still need to determine the FileSystemGuid in EFI_FIRMWARE_VOLUME_HEADER equal to
// EFI_FIRMWARE_FILE_SYSTEM2_GUID or EFI_FIRMWARE_FILE_SYSTEM3_GUID.
// Turn back 28 bytes to find the GUID.
//
memcpy (Ffs2Guid, &FvHeader->FileSystemGuid, 16);
//
// Compare GUID.
//
for (Index = 0; Index < 16; Index ++) {
if (Ffs2Guid[Index] != mFirmwareFileSystem2Guid[Index]) {
break;
}
}
if (Index != 16) {
for (Index = 0; Index < 16; Index ++) {
if (Ffs2Guid[Index] != mFirmwareFileSystem3Guid[Index]) {
break;
}
}
}
//
// Here we found an FV.
//
if ((Index == 16) && ((FdBuffer + FvHeader->FvLength) <= FdBufferEnd)) {
if (FirstMatch) {
LocalFdData->Fv->ImageAddress = (UINTN)((UINT8 *)FdBuffer - (UINT8 *)FdBufferOri);
CurrentFv = LocalFdData->Fv;
CurrentFv->FvNext = NULL;
//
// Store the FV name by found sequence
//
sprintf(CurrentFv->FvName, "FV%d", FvCount);
FirstMatch = FALSE;
} else {
NewFoundFv = (FV_INFORMATION *) malloc (sizeof (FV_INFORMATION));
if (NewFoundFv == NULL) {
Error ("FMMT", 0, 0002, "Error searching FVs in the input fd", "Allocate memory error");
free (LocalFdData->Fv);
free (LocalFdData);
free (FdBuffer);
return EFI_OUT_OF_RESOURCES;
}
LibInitializeFvStruct (NewFoundFv);
//
// Need to turn back 0x2c bytes
//
NewFoundFv->ImageAddress = (UINTN)((UINT8 *)FdBuffer - (UINT8 *)FdBufferOri);
//
// Store the FV name by found sequence
//
sprintf(NewFoundFv->FvName, "FV%d", FvCount);
//
// Value it to NULL for found FV usage.
//
NewFoundFv->FvNext = NULL;
CurrentFv->FvNext = NewFoundFv;
//
// Make the CurrentFv point to next FV.
//
CurrentFv = CurrentFv->FvNext;
}
FvCount ++;
FdBuffer = FdBuffer + FvHeader->FvLength;
} else {
FdBuffer ++;
}
} else {
FdBuffer ++;
}
}
LocalFdData->Size = FdSize;
*FdData = LocalFdData;
free (FdBufferOri);
return EFI_SUCCESS;
}
UINTN
GetFreeOffset (
IN VOID *InputFv
)
{
UINTN FreeOffset;
UINTN Offset;
EFI_STATUS Status;
EFI_FFS_FILE_HEADER2 *CurrentFile;
Offset = 0;
CurrentFile = NULL;
FreeOffset = 0;
do {
FreeOffset = (UINTN)ALIGN_POINTER(Offset, 8);
Status = FvBufFindNextFile(InputFv, &Offset, (VOID **)&CurrentFile);
if (Status == EFI_NOT_FOUND) {
CurrentFile = NULL;
break;
}
else if (EFI_ERROR(Status)) {
return Status;
}
} while (CurrentFile != NULL);
return FreeOffset;
}
/*
Construct a set of blank chars based on the number.
@param[in] Count The number of blank chars.
@return A string contained the blank chars.
*/
CHAR8 *
LibConstructBlankChar (
IN UINT8 Count
)
{
CHAR8 *RetStr;
UINT8 Index;
Index = 0;
RetStr = NULL;
RetStr = (CHAR8 *) malloc (Count +1);
if (RetStr == NULL) {
Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);
return NULL;
}
memset (RetStr , '\0', Count + 1);
for (Index=0; Index <= Count -1; Index ++) {
RetStr[Index] = ' ';
}
return RetStr;
}
/**
This function determines the size of the FV and the erase polarity. The
erase polarity is the FALSE value for file state.
@param[in ] InputFile The file that contains the FV image.
@param[out] FvSize The size of the FV.
@param[out] ErasePolarity The FV erase polarity.
@return EFI_SUCCESS Function completed successfully.
@return EFI_INVALID_PARAMETER A required parameter was NULL or is out of range.
@return EFI_ABORTED The function encountered an error.
**/
EFI_STATUS
LibReadFvHeader (
IN VOID *InputFv,
IN BOOLEAN ViewFlag,
IN UINT8 FvLevel,
IN UINT8 FvCount,
IN CHAR8 *FvName
)
{
EFI_FIRMWARE_VOLUME_HEADER *VolumeHeader;
CHAR8 *BlankSpace;
CHAR8 *FvUiName;
EFI_FIRMWARE_VOLUME_EXT_HEADER *FvExtHeader;
BlankSpace = NULL;
FvUiName = NULL;
//
// Check input parameters
//
if (InputFv == NULL) {
Error (__FILE__, __LINE__, 0, "FMMT application error", "invalid parameter to function");
return EFI_INVALID_PARAMETER;
}
//
// Read the header
//
VolumeHeader = (EFI_FIRMWARE_VOLUME_HEADER *) InputFv;
BlankSpace = LibConstructBlankChar((FvLevel)*2);
if (BlankSpace == NULL) {
Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);
return EFI_OUT_OF_RESOURCES;
}
if (ViewFlag) {
if ((FvLevel -1) == 0) {
printf ("\n%s :\n", FvName);
} else {
printf ("%sChild FV named FV%d of %s\n", BlankSpace, FvCount, FvName);
}
}
//
// Print FV header information
//
if (ViewFlag) {
printf ("\n%sAttributes: %X\n", BlankSpace, (unsigned) VolumeHeader->Attributes);
printf ("%sTotal Volume Size: 0x%08X\n", BlankSpace, (unsigned) VolumeHeader->FvLength);
printf ("%sFree Volume Size: 0x%08X\n", BlankSpace, (unsigned) (VolumeHeader->FvLength - GetFreeOffset(InputFv)));
}
if (ViewFlag && VolumeHeader->ExtHeaderOffset != 0) {
FvExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *)((UINT8 *)VolumeHeader + VolumeHeader->ExtHeaderOffset);
printf("%sFvNameGuid: %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X\n",
BlankSpace,
FvExtHeader->FvName.Data1,
FvExtHeader->FvName.Data2,
FvExtHeader->FvName.Data3,
FvExtHeader->FvName.Data4[0],
FvExtHeader->FvName.Data4[1],
FvExtHeader->FvName.Data4[2],
FvExtHeader->FvName.Data4[3],
FvExtHeader->FvName.Data4[4],
FvExtHeader->FvName.Data4[5],
FvExtHeader->FvName.Data4[6],
FvExtHeader->FvName.Data4[7]);
LibExtractFvUiName(FvExtHeader, &FvUiName);
if (FvUiName != NULL && FvLevel == 1) {
printf("%sFV UI Name: %s\n\n", BlankSpace, FvUiName);
}
free(FvUiName);
}
free (BlankSpace);
return EFI_SUCCESS;
}
/*
Get size info from FV file.
@param[in]
@param[out]
@retval
*/
EFI_STATUS
LibGetFvSize (
IN FILE *InputFile,
OUT UINT32 *FvSize
)
{
UINTN BytesRead;
UINT32 Size;
EFI_FV_BLOCK_MAP_ENTRY BlockMap;
BytesRead = 0;
Size = 0;
if (InputFile == NULL || FvSize == NULL) {
Error (__FILE__, __LINE__, 0, "FMMT application error", "invalid parameter to function");
return EFI_INVALID_PARAMETER;
}
fseek (InputFile, sizeof (EFI_FIRMWARE_VOLUME_HEADER) - sizeof (EFI_FV_BLOCK_MAP_ENTRY), SEEK_CUR);
do {
fread (&BlockMap, sizeof (EFI_FV_BLOCK_MAP_ENTRY), 1, InputFile);
BytesRead += sizeof (EFI_FV_BLOCK_MAP_ENTRY);
if (BlockMap.NumBlocks != 0) {
Size += BlockMap.NumBlocks * BlockMap.Length;
}
} while (!(BlockMap.NumBlocks == 0 && BlockMap.Length == 0));
*FvSize = Size;
return EFI_SUCCESS;
}
/**
Clears out all files from the Fv buffer in memory
@param[in] Fv - Address of the Fv in memory
@return EFI_STATUS
**/
EFI_STATUS
FvBufGetSize (
IN VOID *Fv,
OUT UINTN *Size
)
{
EFI_FIRMWARE_VOLUME_HEADER *hdr;
EFI_FV_BLOCK_MAP_ENTRY *blk;
*Size = 0;
hdr = (EFI_FIRMWARE_VOLUME_HEADER*)Fv;
blk = hdr->BlockMap;
while (blk->Length != 0 || blk->NumBlocks != 0) {
*Size = *Size + (blk->Length * blk->NumBlocks);
if (*Size >= 0x40000000) {
//
// If size is greater than 1GB, then assume it is corrupted
//
return EFI_VOLUME_CORRUPTED;
}
blk++;
}
if (*Size == 0) {
//
// If size is 0, then assume the volume is corrupted
//
return EFI_VOLUME_CORRUPTED;
}
return EFI_SUCCESS;
}
/*
Generate the leaf FFS files.
*/
EFI_STATUS
LibGenFfsFile (
EFI_FFS_FILE_HEADER2 *CurrentFile,
FV_INFORMATION *CurrentFv,
CHAR8 *FvName,
UINT8 Level,
UINT32 *FfsCount,
BOOLEAN ErasePolarity
)
{
UINT32 FfsFileSize;
CHAR8 *FfsFileName;
FILE *FfsFile;
CHAR8 *TempDir;
FfsFileSize = 0;
FfsFileName = NULL;
FfsFile = NULL;
TempDir = NULL;
TempDir = getcwd (NULL, _MAX_PATH);
if (strlen (TempDir) + strlen(OS_SEP_STR) + strlen (TEMP_DIR_NAME) > _MAX_PATH - 1) {
Error("FMMT", 0, 1001, "The directory is too long.", "");
return EFI_ABORTED;
}
strncat (TempDir, OS_SEP_STR, _MAX_PATH - strlen(TempDir) - 1);
strncat (TempDir, TEMP_DIR_NAME, _MAX_PATH - strlen(TempDir) - 1);
mkdir(TempDir, S_IRWXU | S_IRWXG | S_IRWXO);
FfsFileName = (CHAR8 *) malloc (_MAX_PATH);
if (FfsFileName == NULL) {
Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);
return EFI_ABORTED;
}
memset (FfsFileName, '\0', _MAX_PATH);
FfsFileSize = GetFfsFileLength ((EFI_FFS_FILE_HEADER *) CurrentFile);
sprintf (
(CHAR8 *)FfsFileName,
"%s%cNum%d-%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X-Level%d",
TempDir,
OS_SEP,
*FfsCount,
(unsigned) CurrentFile->Name.Data1,
CurrentFile->Name.Data2,
CurrentFile->Name.Data3,
CurrentFile->Name.Data4[0],
CurrentFile->Name.Data4[1],
CurrentFile->Name.Data4[2],
CurrentFile->Name.Data4[3],
CurrentFile->Name.Data4[4],
CurrentFile->Name.Data4[5],
CurrentFile->Name.Data4[6],
CurrentFile->Name.Data4[7],
Level
);
memcpy (CurrentFv->FfsAttuibutes[*FfsCount].FfsName, FfsFileName, strlen(FfsFileName));
memcpy (&CurrentFv->FfsAttuibutes[*FfsCount].GuidName, &CurrentFile->Name, sizeof(EFI_GUID));
//
// Update current FFS files file state.
//
if (ErasePolarity) {
CurrentFile->State = (UINT8)~(CurrentFile->State);
}
FfsFile = fopen (FfsFileName, "wb+");
if (FfsFile == NULL) {
Error ("FMMT", 0, 0003, "error writing FFS file", "cannot Create a new ffs file.");
free(FfsFileName);
return EFI_ABORTED;
}
if (fwrite (CurrentFile, 1, FfsFileSize, FfsFile) != FfsFileSize) {
Error ("FMMT", 0, 0004, "error writing FFS file", "cannot Create a new ffs file.");
fclose(FfsFile);
free(FfsFileName);
return EFI_ABORTED;
}
fclose(FfsFile);
free(FfsFileName);
FfsFileName = NULL;
CurrentFv->FfsNumbers = *FfsCount;
*FfsCount += 1;
if (ErasePolarity) {
CurrentFile->State = (UINT8)~(CurrentFile->State);
}
return EFI_SUCCESS;
}
VOID
Unicode2AsciiString (
IN CHAR16 *Source,
OUT CHAR8 *Destination
)
/*++
Routine Description:
Convert a null-terminated unicode string to a null-terminated ascii string.
Arguments:
Source - The pointer to the null-terminated input unicode string.
Destination - The pointer to the null-terminated output ascii string.
Returns:
N/A
--*/
{
while (*Source != '\0') {
*(Destination++) = (CHAR8) *(Source++);
}
//
// End the ascii with a NULL.
//
*Destination = '\0';
}
/**
Parses EFI Sections, if the view flag turn on, then will collect FFS section information
and extract FFS files.
@param[in] SectionBuffer - Buffer containing the section to parse.
@param[in] BufferLength - Length of SectionBuffer
@param[in, out] CurrentFv
@param[in] FvName
@param[in] CurrentFile
@param[in] Level
@param[in, out] FfsCount
@param[in] ViewFlag
@param[in] ErasePolarity
@retval EFI_SECTION_ERROR - Problem with section parsing.
(a) compression errors
(b) unrecognized section
@retval EFI_UNSUPPORTED - Do not know how to parse the section.
@retval EFI_SUCCESS - Section successfully parsed.
@retval EFI_OUT_OF_RESOURCES - Memory allocation failed.
--*/
EFI_STATUS
LibParseSection (
UINT8 *SectionBuffer,
UINT32 BufferLength,
FV_INFORMATION *CurrentFv,
CHAR8 *FvName,
EFI_FFS_FILE_HEADER2 *CurrentFile,
UINT8 Level,
ENCAP_INFO_DATA **CurrentFvEncapData,
UINT8 FfsLevel,
UINT32 *FfsCount,
UINT8 *FvCount,
BOOLEAN ViewFlag,
BOOLEAN ErasePolarity,
BOOLEAN *IsFfsGenerated
)
{
UINT32 ParsedLength;
UINT8 *Ptr;
UINT32 SectionLength;
UINT32 UiSectionLength;
EFI_SECTION_TYPE Type;
EFI_STATUS Status;
CHAR8 *ExtractionTool;
CHAR8 *ToolInputFile;
CHAR8 *ToolOutputFile;
CHAR8 *SystemCommandFormatString;
CHAR8 *SystemCommand;
UINT8 *ToolOutputBuffer;
UINT32 ToolOutputLength;
CHAR16 *UIName;
UINT32 UINameSize;
BOOLEAN HasDepexSection;
UINT32 NumberOfSections;
ENCAP_INFO_DATA *LocalEncapData;
ENCAP_INFO_DATA *LocalEncapDataTemp;
CHAR8 *BlankChar;
UINT8 *UncompressedBuffer;
UINT32 UncompressedLength;
UINT8 *CompressedBuffer;
UINT32 CompressedLength;
UINT8 CompressionType;
DECOMPRESS_FUNCTION DecompressFunction;
GETINFO_FUNCTION GetInfoFunction;
UINT32 DstSize;
UINT32 ScratchSize;
UINT8 *ScratchBuffer;
BOOLEAN EncapDataNeedUpdata;
CHAR8 *TempDir;
CHAR8 *ToolInputFileFullName;
CHAR8 *ToolOutputFileFullName;
UINT8 LargeHeaderOffset;
UINT16 GuidAttr;
UINT16 DataOffset;
CHAR8 *UIFileName;
CHAR8 *ToolInputFileName;
CHAR8 *ToolOutputFileName;
DataOffset = 0;
GuidAttr = 0;
ParsedLength = 0;
ToolOutputLength = 0;
UINameSize = 0;
NumberOfSections = 0;
UncompressedLength = 0;
CompressedLength = 0;
CompressionType = 0;
DstSize = 0;
ScratchSize = 0;
Ptr = NULL;
ExtractionTool = NULL;
ToolInputFile = NULL;
ToolOutputFile = NULL;
SystemCommand = NULL;
SystemCommandFormatString = NULL;
ToolOutputBuffer = NULL;
UIName = NULL;
LocalEncapData = NULL;
LocalEncapDataTemp = NULL;
BlankChar = NULL;
UncompressedBuffer = NULL;
CompressedBuffer = NULL;
ScratchBuffer = NULL;
TempDir = NULL;
ToolInputFileFullName = NULL;
ToolOutputFileFullName = NULL;
ToolInputFileName = NULL;
ToolOutputFileFullName = NULL;
HasDepexSection = FALSE;
EncapDataNeedUpdata = TRUE;
LargeHeaderOffset = 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;
}
//
//If Size is 0xFFFFFF then ExtendedSize contains the size of the section.
//
if (SectionLength == 0xffffff) {
SectionLength = ((EFI_COMMON_SECTION_HEADER2 *) Ptr)->ExtendedSize;
LargeHeaderOffset = sizeof (EFI_COMMON_SECTION_HEADER2) - sizeof (EFI_COMMON_SECTION_HEADER);
}
switch (Type) {
case EFI_SECTION_FIRMWARE_VOLUME_IMAGE:
EncapDataNeedUpdata = TRUE;
Level ++;
NumberOfSections ++;
CurrentFv->FfsAttuibutes[*FfsCount].IsLeaf = FALSE;
CurrentFv->FfsAttuibutes[*FfsCount].IsFvStart = TRUE;
//
// Put in encapsulate data information.
//
LocalEncapData = *CurrentFvEncapData;
if (LocalEncapData->NextNode != NULL) {
LocalEncapData = LocalEncapData->NextNode;
while (LocalEncapData->RightNode != NULL) {
LocalEncapData = LocalEncapData->RightNode;
}
}
if (EncapDataNeedUpdata) {
//
// Put in this is an FFS with FV section
//
//
// Construct the new ENCAP_DATA
//
LocalEncapData->NextNode = (ENCAP_INFO_DATA *) malloc (sizeof (ENCAP_INFO_DATA));
if (LocalEncapData->NextNode == NULL) {
Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);
return EFI_ABORTED;
}
LocalEncapData = LocalEncapData->NextNode;
LocalEncapData->Level = Level;
LocalEncapData->Type = FMMT_ENCAP_TREE_FV_SECTION;
//
// We don't need additional data for encapsulate this FFS but type.
//
LocalEncapData->Data = NULL;
LocalEncapData->FvExtHeader = NULL;
LocalEncapData->NextNode = NULL;
LocalEncapData->RightNode = NULL;
LocalEncapData->Depex = NULL;
LocalEncapData->DepexLen = 0;
LocalEncapData->UiNameSize = 0;
LocalEncapData->FvId = *FvCount;
}
//
//save parent level FFS file's GUID name
//
LocalEncapDataTemp = CurrentFv->EncapData;
while (LocalEncapDataTemp->NextNode != NULL) {
if (LocalEncapDataTemp->Level == FfsLevel) {
while (LocalEncapDataTemp->RightNode != NULL) {
LocalEncapDataTemp = LocalEncapDataTemp->RightNode;
}
if (LocalEncapDataTemp != NULL && LocalEncapDataTemp->FvExtHeader == NULL) {
LocalEncapDataTemp->FvExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *)malloc(sizeof(EFI_FIRMWARE_VOLUME_EXT_HEADER));
if (LocalEncapDataTemp->FvExtHeader == NULL) {
Error(NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);
return EFI_ABORTED;
}
if (*FfsCount >= 1) {
if ((memcmp(&CurrentFv->FfsAttuibutes[*FfsCount - 1].GuidName, &(LocalEncapDataTemp->FvExtHeader->FvName), sizeof(EFI_GUID)) == 0)) {
memcpy(LocalEncapDataTemp->UiName, CurrentFv->FfsAttuibutes[*FfsCount - 1].UiName, _MAX_PATH);
LocalEncapDataTemp->UiNameSize = CurrentFv->FfsAttuibutes[*FfsCount - 1].UiNameSize;
LocalEncapDataTemp->DepexLen = CurrentFv->FfsAttuibutes[*FfsCount - 1].DepexLen;
LocalEncapDataTemp->Depex = malloc (LocalEncapDataTemp->DepexLen);
if (LocalEncapDataTemp->Depex == NULL) {
Error(NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);
return EFI_ABORTED;
}
memcpy(LocalEncapDataTemp->Depex, CurrentFv->FfsAttuibutes[*FfsCount - 1].Depex, LocalEncapDataTemp->DepexLen);
}
}
}
break;
}
LocalEncapDataTemp = LocalEncapDataTemp->NextNode;
}
Status = LibGetFvInfo ((UINT8*)((EFI_FIRMWARE_VOLUME_IMAGE_SECTION*)Ptr + 1) + LargeHeaderOffset, CurrentFv, FvName, Level, &LocalEncapData, FfsCount, FvCount, ViewFlag, TRUE);
if (EFI_ERROR (Status)) {
Error ("FMMT", 0, 0003, "printing of FV section contents failed", NULL);
return EFI_SECTION_ERROR;
}
if (*FfsCount >= 1) {
CurrentFv->FfsAttuibutes[*FfsCount -1].IsFvEnd = TRUE;
}
break;
case EFI_SECTION_COMPRESSION:
Level ++;
NumberOfSections ++;
EncapDataNeedUpdata = TRUE;
//
// Put in encapsulate data information.
//
LocalEncapData = *CurrentFvEncapData;
if (LocalEncapData->NextNode != NULL) {
EncapDataNeedUpdata = FALSE;
while (LocalEncapData->RightNode != NULL) {
LocalEncapData = LocalEncapData->RightNode;
}
}
if (EncapDataNeedUpdata) {
//
// Put in this is an FFS with FV section
//
//
// Construct the new ENCAP_DATA
//
LocalEncapData->NextNode = (ENCAP_INFO_DATA *) malloc (sizeof (ENCAP_INFO_DATA));
if (LocalEncapData->NextNode == NULL) {
Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);
return EFI_ABORTED;
}
LocalEncapData = LocalEncapData->NextNode;
LocalEncapData->Level = Level;
LocalEncapData->Type = FMMT_ENCAP_TREE_COMPRESS_SECTION;
//
// Store the compress type
//
LocalEncapData->Data = malloc (sizeof (UINT8));
if (LocalEncapData->Data == NULL) {
Error ("FMMT", 0, 0003, "Allocate memory failed", NULL);
return EFI_OUT_OF_RESOURCES;
}
*(UINT8 *)LocalEncapData->Data = ((EFI_COMPRESSION_SECTION *) (Ptr + LargeHeaderOffset))->CompressionType;
LocalEncapData->FvExtHeader = NULL;
LocalEncapData->NextNode = NULL;
LocalEncapData->RightNode = NULL;
} else {
LocalEncapData->RightNode = (ENCAP_INFO_DATA *) malloc (sizeof (ENCAP_INFO_DATA));
if (LocalEncapData->RightNode == NULL) {
Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);
return EFI_ABORTED;
}
LocalEncapData = LocalEncapData->RightNode;
LocalEncapData->Level = Level;
LocalEncapData->Type = FMMT_ENCAP_TREE_COMPRESS_SECTION;
//
// Store the compress type
//
LocalEncapData->Data = malloc (sizeof (UINT8));
if (LocalEncapData->Data == NULL) {
Error ("FMMT", 0, 0003, "Allocate memory failed", NULL);
return EFI_OUT_OF_RESOURCES;
}
*(UINT8 *)LocalEncapData->Data = ((EFI_COMPRESSION_SECTION *) (Ptr + LargeHeaderOffset))->CompressionType;
LocalEncapData->FvExtHeader = NULL;
LocalEncapData->NextNode = NULL;
LocalEncapData->RightNode = NULL;
}
//
// Process compressed section
//
CurrentFv->FfsAttuibutes[*FfsCount].IsLeaf = FALSE;
UncompressedBuffer = NULL;
CompressedLength = SectionLength - sizeof (EFI_COMPRESSION_SECTION) - LargeHeaderOffset;
UncompressedLength = ((EFI_COMPRESSION_SECTION *) (Ptr + LargeHeaderOffset))->UncompressedLength;
CompressionType = ((EFI_COMPRESSION_SECTION *) (Ptr + LargeHeaderOffset))->CompressionType;
if (CompressionType == EFI_NOT_COMPRESSED) {
//printf (" Compression Type: EFI_NOT_COMPRESSED\n");
if (CompressedLength != UncompressedLength) {
Error ("FMMT", 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) + LargeHeaderOffset;
} else if (CompressionType == EFI_STANDARD_COMPRESSION) {
GetInfoFunction = EfiGetInfo;
DecompressFunction = EfiDecompress;
CompressedBuffer = Ptr + sizeof (EFI_COMPRESSION_SECTION) + LargeHeaderOffset;
Status = GetInfoFunction (CompressedBuffer, CompressedLength, &DstSize, &ScratchSize);
if (EFI_ERROR (Status)) {
Error ("FMMT", 0, 0003, "error getting compression info from compression section", NULL);
return EFI_SECTION_ERROR;
}
if (DstSize != UncompressedLength) {
Error ("FMMT", 0, 0003, "compression error in the compression section", NULL);
return EFI_SECTION_ERROR;
}
ScratchBuffer = malloc (ScratchSize);
if (ScratchBuffer == NULL) {
Error ("FMMT", 0, 0003, "Allocate memory failed", NULL);
return EFI_OUT_OF_RESOURCES;
}
UncompressedBuffer = malloc (UncompressedLength);
if (UncompressedBuffer == NULL) {
Error ("FMMT", 0, 0003, "Allocate memory failed", NULL);
free (ScratchBuffer);
return EFI_OUT_OF_RESOURCES;
}
//
// Decompress the section.
//
Status = DecompressFunction (
CompressedBuffer,
CompressedLength,
UncompressedBuffer,
UncompressedLength,
ScratchBuffer,
ScratchSize
);
free (ScratchBuffer);
if (EFI_ERROR (Status)) {
Error ("FMMT", 0, 0003, "decompress failed", NULL);
free (UncompressedBuffer);
return EFI_SECTION_ERROR;
}
} else {
Error ("FMMT", 0, 0003, "unrecognized compression type", "type 0x%X", CompressionType);
return EFI_SECTION_ERROR;
}
Status = LibParseSection ( UncompressedBuffer,
UncompressedLength,
CurrentFv,
FvName,
CurrentFile,
Level,
&LocalEncapData,
FfsLevel,
FfsCount,
FvCount,
ViewFlag,
ErasePolarity,
IsFfsGenerated);
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:
//
// Process GUID defined
// looks up the appropriate tool to use for extracting
// a GUID defined FV section.
//
Level ++;
NumberOfSections++;
EncapDataNeedUpdata = TRUE;
//
// Put in encapsulate data information.
//
LocalEncapData = *CurrentFvEncapData;
if (LocalEncapData->NextNode != NULL) {
EncapDataNeedUpdata = FALSE;
while (LocalEncapData->RightNode != NULL) {
LocalEncapData = LocalEncapData->RightNode;
}
}
GuidAttr = ((EFI_GUID_DEFINED_SECTION *)(Ptr + LargeHeaderOffset))->Attributes;
DataOffset = ((EFI_GUID_DEFINED_SECTION *)(Ptr + LargeHeaderOffset))->DataOffset;
if ((ViewFlag) && ((GuidAttr & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) == 0)) {
ToolOutputBuffer = Ptr + DataOffset;
ToolOutputLength = SectionLength - DataOffset;
Status = LibParseSection(
ToolOutputBuffer,
ToolOutputLength,
CurrentFv,
FvName,
CurrentFile,
Level,
&LocalEncapData,
FfsLevel,
FfsCount,
FvCount,
ViewFlag,
ErasePolarity,
IsFfsGenerated
);
if (EFI_ERROR(Status)) {
Error(NULL, 0, 0003, "parse of decoded GUIDED section failed", NULL);
return EFI_SECTION_ERROR;
}
break;
}
if (EncapDataNeedUpdata) {
//
// Put in this is an FFS with FV section
//
//
// Construct the new ENCAP_DATA
//
LocalEncapData->NextNode = (ENCAP_INFO_DATA *) malloc (sizeof (ENCAP_INFO_DATA));
if (LocalEncapData->NextNode == NULL) {
Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);
return EFI_ABORTED;
}
LocalEncapData = LocalEncapData->NextNode;
LocalEncapData->Level = Level;
LocalEncapData->Type = FMMT_ENCAP_TREE_GUIDED_SECTION;
LocalEncapData->Depex = NULL;
LocalEncapData->DepexLen = 0;
LocalEncapData->UiNameSize = 0;
//
// We don't need additional data for encapsulate this FFS but type.
// include DataOffset + Attributes
//
LocalEncapData->Data = (EFI_GUID *) malloc (sizeof (EFI_GUID) + 4);
if (LocalEncapData->Data == NULL) {
Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);
return EFI_ABORTED;
}
//
// include guid attribute and dataoffset
//
memcpy (LocalEncapData->Data, Ptr + LargeHeaderOffset + OFFSET_OF (EFI_GUID_DEFINED_SECTION, SectionDefinitionGuid), sizeof (EFI_GUID) + 4);
LocalEncapData->FvExtHeader = NULL;
LocalEncapData->NextNode = NULL;
LocalEncapData->RightNode = NULL;
} else {
LocalEncapData->RightNode = (ENCAP_INFO_DATA *) malloc (sizeof (ENCAP_INFO_DATA));
if (LocalEncapData->RightNode == NULL) {
Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);
return EFI_ABORTED;
}
LocalEncapData = LocalEncapData->RightNode;
LocalEncapData->Level = Level;
LocalEncapData->Type = FMMT_ENCAP_TREE_GUIDED_SECTION;
LocalEncapData->Depex = NULL;
LocalEncapData->DepexLen = 0;
LocalEncapData->UiNameSize = 0;
//
// We don't need additional data for encapsulate this FFS but type.
// include DataOffset + Attributes
//
LocalEncapData->Data = (EFI_GUID *) malloc (sizeof (EFI_GUID) + 4);
if (LocalEncapData->Data == NULL) {
Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);
return EFI_ABORTED;
}
//
// include guid attribute and dataoffset
//
memcpy (LocalEncapData->Data, Ptr + LargeHeaderOffset + OFFSET_OF (EFI_GUID_DEFINED_SECTION, SectionDefinitionGuid), sizeof (EFI_GUID) + 4);
LocalEncapData->FvExtHeader = NULL;
LocalEncapData->NextNode = NULL;
LocalEncapData->RightNode = NULL;
}
CurrentFv->FfsAttuibutes[*FfsCount].IsLeaf = FALSE;
ExtractionTool =
LookupGuidedSectionToolPath (
mParsedGuidedSectionTools,
&((EFI_GUID_DEFINED_SECTION *) (Ptr + LargeHeaderOffset))->SectionDefinitionGuid
);
if (ExtractionTool != NULL && ((GuidAttr & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) != 0)) {
TempDir = getcwd (NULL, _MAX_PATH);
if (strlen (TempDir) + strlen(OS_SEP_STR) + strlen (TEMP_DIR_NAME) > _MAX_PATH - 1) {
Error("FMMT", 0, 1001, "The directory is too long.", "");
free (ExtractionTool);
return EFI_SECTION_ERROR;
}
strncat (TempDir, OS_SEP_STR, _MAX_PATH - strlen(TempDir) - 1);
strncat (TempDir, TEMP_DIR_NAME, _MAX_PATH - strlen(TempDir) - 1);
mkdir(TempDir, S_IRWXU | S_IRWXG | S_IRWXO);
ToolInputFile = GenTempFile ();
if (ToolInputFile == NULL) {
Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);
free (ExtractionTool);
return EFI_OUT_OF_RESOURCES;
}
ToolOutputFile = GenTempFile ();
if (ToolOutputFile == NULL) {
free (ToolInputFile);
Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);
free (ExtractionTool);
return EFI_OUT_OF_RESOURCES;
}
ToolInputFileName = strrchr(ToolInputFile, OS_SEP);
if (ToolInputFileName == NULL) {
free (ToolInputFile);
free (ToolOutputFile);
free (ExtractionTool);
return EFI_ABORTED;
}
ToolOutputFileName = strrchr(ToolOutputFile, OS_SEP);
if (ToolOutputFileName == NULL) {
free (ToolInputFile);
free (ToolOutputFile);
free (ExtractionTool);
return EFI_ABORTED;
}
ToolInputFileFullName = malloc (strlen("%s%s") + strlen(TempDir) + strlen(ToolInputFileName) + 1);
if (ToolInputFileFullName == NULL) {
free (ToolInputFile);
free (ToolOutputFile);
free (ExtractionTool);
Error ("FMMT", 0, 0003, "Allocate memory failed", NULL);
return EFI_OUT_OF_RESOURCES;
}
ToolOutputFileFullName = malloc (strlen("%s%s") + strlen(TempDir) + strlen(ToolOutputFileName) + 1);
if (ToolOutputFileFullName == NULL) {
free (ToolInputFile);
free (ToolOutputFile);
free (ToolInputFileFullName);
free (ExtractionTool);
Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);
return EFI_OUT_OF_RESOURCES;
}
sprintf (ToolInputFileFullName, "%s%s", TempDir, ToolInputFileName);
sprintf (ToolOutputFileFullName, "%s%s", TempDir, ToolOutputFileName);
//
// Construction 'system' command string
//
SystemCommandFormatString = "%s -d -o \"%s\" \"%s\"";
SystemCommand = malloc (
strlen (SystemCommandFormatString) +
strlen (ExtractionTool) +
strlen (ToolInputFileFullName) +
strlen (ToolOutputFileFullName) +
1
);
if (SystemCommand == NULL) {
free (ToolInputFile);
free (ToolOutputFile);
free (ToolInputFileFullName);
free (ToolOutputFileFullName);
free (ExtractionTool);
return EFI_ABORTED;
}
sprintf (
SystemCommand,
"%s -d -o \"%s\" \"%s\"",
ExtractionTool,
ToolOutputFileFullName,
ToolInputFileFullName
);
free (ExtractionTool);
ExtractionTool = NULL;
Status = PutFileImage (
ToolInputFileFullName,
(CHAR8*) Ptr + ((EFI_GUID_DEFINED_SECTION *) (Ptr + LargeHeaderOffset))->DataOffset,
SectionLength - ((EFI_GUID_DEFINED_SECTION *) (Ptr + LargeHeaderOffset))->DataOffset
);
if (HasDepexSection) {
HasDepexSection = FALSE;
}
if (EFI_ERROR (Status)) {
Error ("FMMT", 0, 0004, "unable to decoded GUIDED section", NULL);
free (SystemCommand);
free (ToolInputFile);
free (ToolOutputFile);
free (ToolOutputFileFullName);
remove (ToolInputFileFullName);
free (ToolInputFileFullName);
return EFI_SECTION_ERROR;
}
if (system (SystemCommand) != EFI_SUCCESS) {
printf("Command failed: %s\n", SystemCommand);
free (SystemCommand);
free (ToolInputFile);
free (ToolOutputFile);
free (ToolOutputFileFullName);
remove (ToolInputFileFullName);
free (ToolInputFileFullName);
return EFI_ABORTED;
}
free (SystemCommand);
remove (ToolInputFileFullName);
free (ToolInputFile);
free (ToolInputFileFullName);
ToolInputFile = NULL;
ToolInputFileFullName = NULL;
Status = GetFileImage (
ToolOutputFileFullName,
(CHAR8 **)&ToolOutputBuffer,
&ToolOutputLength
);
remove (ToolOutputFileFullName);
free (ToolOutputFile);
free (ToolOutputFileFullName);
ToolOutputFile = NULL;
ToolOutputFileFullName = NULL;
if (EFI_ERROR (Status)) {
Error ("FMMT", 0, 0004, "unable to read decoded GUIDED section", NULL);
return EFI_SECTION_ERROR;
}
Status = LibParseSection (
ToolOutputBuffer,
ToolOutputLength,
CurrentFv,
FvName,
CurrentFile,
Level,
&LocalEncapData,
FfsLevel,
FfsCount,
FvCount,
ViewFlag,
ErasePolarity,
IsFfsGenerated
);
if (EFI_ERROR (Status)) {
Error (NULL, 0, 0003, "parse of decoded GUIDED section failed", NULL);
return EFI_SECTION_ERROR;
}
} else if ((GuidAttr & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) == 0){
Status = LibParseSection (
Ptr + ((EFI_GUID_DEFINED_SECTION *) (Ptr + LargeHeaderOffset))->DataOffset,
SectionLength - ((EFI_GUID_DEFINED_SECTION *) (Ptr + LargeHeaderOffset))->DataOffset,
CurrentFv,
FvName,
CurrentFile,
Level,
&LocalEncapData,
FfsLevel,
FfsCount,
FvCount,
ViewFlag,
ErasePolarity,
IsFfsGenerated
);
if (ExtractionTool != NULL) {
free (ExtractionTool);
ExtractionTool = NULL;
}
if (EFI_ERROR (Status)) {
Error (NULL, 0, 0003, "parse of decoded GUIDED section failed", NULL);
return EFI_SECTION_ERROR;
}
}else {
//
// We don't know how to parse it now.
//
if (ExtractionTool != NULL) {
free (ExtractionTool);
ExtractionTool = NULL;
}
Error ("FMMT", 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 %s file.", mGuidToolDefinition);
printf(" Its GUID is: ");
PrintGuid(&(((EFI_GUID_DEFINED_SECTION *)(Ptr + LargeHeaderOffset))->SectionDefinitionGuid));
return EFI_UNSUPPORTED;
}
break;
//
//Leaf sections
//
case EFI_SECTION_RAW:
NumberOfSections ++;
CurrentFv->FfsAttuibutes[*FfsCount].Level = Level;
if (!ViewFlag) {
if (!*IsFfsGenerated) {
LibGenFfsFile(CurrentFile, CurrentFv, FvName, Level, FfsCount, ErasePolarity);
*IsFfsGenerated = TRUE;
}
}
break;
case EFI_SECTION_PE32:
NumberOfSections ++;
CurrentFv->FfsAttuibutes[*FfsCount].Level = Level;
if (!ViewFlag) {
if (!*IsFfsGenerated) {
LibGenFfsFile(CurrentFile, CurrentFv, FvName, Level, FfsCount, ErasePolarity);
*IsFfsGenerated = TRUE;
}
}
break;
case EFI_SECTION_PIC:
NumberOfSections ++;
CurrentFv->FfsAttuibutes[*FfsCount].Level = Level;
if (!ViewFlag) {
if (!*IsFfsGenerated) {
LibGenFfsFile(CurrentFile, CurrentFv, FvName, Level, FfsCount, ErasePolarity);
*IsFfsGenerated = TRUE;
}
}
break;
case EFI_SECTION_TE:
NumberOfSections ++;
CurrentFv->FfsAttuibutes[*FfsCount].Level = Level;
if (!ViewFlag) {
if (!*IsFfsGenerated) {
LibGenFfsFile(CurrentFile, CurrentFv, FvName, Level, FfsCount, ErasePolarity);
*IsFfsGenerated = TRUE;
}
}
break;
case EFI_SECTION_COMPATIBILITY16:
NumberOfSections ++;
CurrentFv->FfsAttuibutes[*FfsCount].Level = Level;
if (!ViewFlag) {
if (!*IsFfsGenerated) {
LibGenFfsFile(CurrentFile, CurrentFv, FvName, Level, FfsCount, ErasePolarity);
*IsFfsGenerated = TRUE;
}
}
break;
case EFI_SECTION_FREEFORM_SUBTYPE_GUID:
NumberOfSections ++;
CurrentFv->FfsAttuibutes[*FfsCount].Level = Level;
if (!ViewFlag) {
if (!*IsFfsGenerated) {
LibGenFfsFile(CurrentFile, CurrentFv, FvName, Level, FfsCount, ErasePolarity);
*IsFfsGenerated = TRUE;
}
}
break;
case EFI_SECTION_VERSION:
NumberOfSections ++;
CurrentFv->FfsAttuibutes[*FfsCount].Level = Level;
break;
case EFI_SECTION_PEI_DEPEX:
NumberOfSections ++;
CurrentFv->FfsAttuibutes[*FfsCount].Level = Level;
HasDepexSection = TRUE;
CurrentFv->FfsAttuibutes[*FfsCount].Depex = malloc (SectionLength);
memcpy(CurrentFv->FfsAttuibutes[*FfsCount].Depex, Ptr, SectionLength);
CurrentFv->FfsAttuibutes[*FfsCount].DepexLen = SectionLength;
break;
case EFI_SECTION_DXE_DEPEX:
NumberOfSections ++;
CurrentFv->FfsAttuibutes[*FfsCount].Level = Level;
HasDepexSection = TRUE;
CurrentFv->FfsAttuibutes[*FfsCount].Depex = malloc (SectionLength);
memcpy(CurrentFv->FfsAttuibutes[*FfsCount].Depex, Ptr, SectionLength);
CurrentFv->FfsAttuibutes[*FfsCount].DepexLen = SectionLength;
break;
case EFI_SECTION_SMM_DEPEX:
NumberOfSections ++;
CurrentFv->FfsAttuibutes[*FfsCount].Level = Level;
HasDepexSection = TRUE;
CurrentFv->FfsAttuibutes[*FfsCount].Depex = malloc (SectionLength);
memcpy(CurrentFv->FfsAttuibutes[*FfsCount].Depex, Ptr, SectionLength);
CurrentFv->FfsAttuibutes[*FfsCount].DepexLen = SectionLength;
break;
case EFI_SECTION_USER_INTERFACE:
NumberOfSections ++;
CurrentFv->FfsAttuibutes[*FfsCount].Level = Level;
UiSectionLength = GetLength (((EFI_USER_INTERFACE_SECTION *) Ptr)->CommonHeader.Size);
if (UiSectionLength == 0xffffff) {
UiSectionLength = ((EFI_USER_INTERFACE_SECTION2 *) Ptr)->CommonHeader.ExtendedSize;
UINameSize = UiSectionLength - sizeof(EFI_COMMON_SECTION_HEADER2);
} else {
UINameSize = UiSectionLength - sizeof(EFI_COMMON_SECTION_HEADER);
}
UIName = (CHAR16 *) malloc (UINameSize + 2);
if (UIName != NULL) {
memset (UIName, '\0', UINameSize + 2);
if (UiSectionLength >= 0xffffff) {
memcpy(UIName, ((EFI_USER_INTERFACE_SECTION2 *) Ptr)->FileNameString, UINameSize);
} else {
memcpy(UIName, ((EFI_USER_INTERFACE_SECTION *) Ptr)->FileNameString, UINameSize);
}
} else {
Error ("FMMT", 0, 0001, "Memory allocate error!", NULL);
return EFI_OUT_OF_RESOURCES;
}
BlankChar = LibConstructBlankChar( CurrentFv->FvLevel * 2);
if (BlankChar == NULL) {
free(UIName);
return EFI_OUT_OF_RESOURCES;
}
if (ViewFlag) {
UIFileName = malloc (UINameSize + 2);
if (UIFileName == NULL) {
Error ("FMMT", 0, 4001, "Memory allocation fail!", NULL);
free (UIName);
free (BlankChar);
return EFI_OUT_OF_RESOURCES;
}
Unicode2AsciiString (UIName, UIFileName);
fprintf(stdout, "%sFile \"%s\"\n", BlankChar, UIFileName);
free(UIFileName);
}
free (BlankChar);
//
// If Ffs file has been generated, then the FfsCount should decrease 1.
//
if (*IsFfsGenerated) {
memcpy (CurrentFv->FfsAttuibutes[*FfsCount -1].UiName, UIName, UINameSize);
CurrentFv->FfsAttuibutes[*FfsCount -1].UiNameSize = UINameSize;
} else {
memcpy (CurrentFv->FfsAttuibutes[*FfsCount].UiName, UIName, UINameSize);
CurrentFv->FfsAttuibutes[*FfsCount].UiNameSize = UINameSize;
}
HasDepexSection = FALSE;
free(UIName);
UINameSize = 0;
break;
default:
break;
}
ParsedLength += SectionLength;
//
// We make then next section begin on a 4-byte boundary
//
ParsedLength = GetOccupiedSize (ParsedLength, 4);
}
if (ParsedLength < BufferLength) {
Error ("FMMT", 0, 0003, "sections do not completely fill the sectioned buffer being parsed", NULL);
return EFI_SECTION_ERROR;
}
return EFI_SUCCESS;
}
/**
Iterates through the files contained within the firmware volume
@param[in] Fv - Address of the Fv in memory
@param[in] Key - Should be 0 to get the first file. After that, it should be
passed back in without modifying it's contents to retrieve
subsequent files.
@param[in] File- Output file pointer
File == NULL - invalid parameter
otherwise - *File will be update to the location of the file
@return EFI_STATUS
EFI_NOT_FOUND
EFI_VOLUME_CORRUPTED
**/
EFI_STATUS
FvBufFindNextFile (
IN VOID *Fv,
IN OUT UINTN *Key,
OUT VOID **File
)
{
EFI_FIRMWARE_VOLUME_HEADER *hdr;
EFI_FFS_FILE_HEADER *fhdr;
EFI_FIRMWARE_VOLUME_EXT_HEADER *FwVolExtHeader;
EFI_FVB_ATTRIBUTES_2 FvbAttributes;
UINTN fsize;
EFI_STATUS Status;
UINTN fvSize;
hdr = (EFI_FIRMWARE_VOLUME_HEADER*)Fv;
fhdr = NULL;
if (Fv == NULL) {
return EFI_INVALID_PARAMETER;
}
Status = FvBufGetSize (Fv, &fvSize);
if (EFI_ERROR (Status)) {
return Status;
}
if (*Key == 0) {
if (hdr->ExtHeaderOffset != 0) {
//
// Searching for files starts on an 8 byte aligned boundary after the end of the Extended Header if it exists.
//
FwVolExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *)((UINT8 *)hdr + hdr->ExtHeaderOffset);
*Key = (UINTN)hdr->ExtHeaderOffset + FwVolExtHeader->ExtHeaderSize;
*Key = (UINTN)ALIGN_POINTER(*Key, 8);
} else {
*Key = hdr->HeaderLength;
}
}
FvbAttributes = hdr->Attributes;
for(
*Key = (UINTN)ALIGN_POINTER (*Key, 8);
(*Key + sizeof (*fhdr)) < fvSize;
*Key = (UINTN)ALIGN_POINTER (*Key, 8)
) {
fhdr = (EFI_FFS_FILE_HEADER*) ((UINT8*)hdr + *Key);
fsize = GetFfsFileLength (fhdr);
if (!EFI_TEST_FFS_ATTRIBUTES_BIT(
FvbAttributes,
fhdr->State,
EFI_FILE_HEADER_VALID
) ||
EFI_TEST_FFS_ATTRIBUTES_BIT(
FvbAttributes,
fhdr->State,
EFI_FILE_HEADER_INVALID
)
) {
*Key = *Key + 1;
continue;
} else if(
EFI_TEST_FFS_ATTRIBUTES_BIT(
FvbAttributes,
fhdr->State,
EFI_FILE_MARKED_FOR_UPDATE
) ||
EFI_TEST_FFS_ATTRIBUTES_BIT(
FvbAttributes,
fhdr->State,
EFI_FILE_DELETED
)
) {
*Key = *Key + fsize;
continue;
} else if (EFI_TEST_FFS_ATTRIBUTES_BIT(
FvbAttributes,
fhdr->State,
EFI_FILE_DATA_VALID
)
) {
*File = (UINT8*)hdr + *Key;
*Key = *Key + fsize;
return EFI_SUCCESS;
}
*Key = *Key + 1;
}
return EFI_NOT_FOUND;
}
/**
TODO: Add function description
FvImage - TODO: add argument description
FileHeader - TODO: add argument description
ErasePolarity - TODO: add argument description
EFI_SUCCESS - TODO: Add description for return value
EFI_ABORTED - TODO: Add description for return value
**/
EFI_STATUS
LibGetFileInfo (
EFI_FIRMWARE_VOLUME_HEADER *FvImage,
EFI_FFS_FILE_HEADER2 *CurrentFile,
BOOLEAN ErasePolarity,
FV_INFORMATION *CurrentFv,
CHAR8 *FvName,
UINT8 Level,
ENCAP_INFO_DATA **CurrentFvEncapData,
UINT32 *FfsCount,
UINT8 *FvCount,
BOOLEAN ViewFlag
)
{
UINT32 FileLength;
UINT8 FileState;
UINT8 Checksum;
EFI_FFS_FILE_HEADER2 BlankHeader;
EFI_STATUS Status;
UINT8 GuidBuffer[PRINTED_GUID_BUFFER_SIZE];
ENCAP_INFO_DATA *LocalEncapData;
BOOLEAN EncapDataNeedUpdateFlag;
BOOLEAN IsGeneratedFfs;
UINT32 FfsFileHeaderSize;
Status = EFI_SUCCESS;
LocalEncapData = NULL;
EncapDataNeedUpdateFlag = TRUE;
IsGeneratedFfs = FALSE;
FfsFileHeaderSize = GetFfsHeaderLength ((EFI_FFS_FILE_HEADER *) CurrentFile);
FileLength = GetFfsFileLength ((EFI_FFS_FILE_HEADER *) CurrentFile);
//
// Check if we have free space
//
if (ErasePolarity) {
memset (&BlankHeader, -1, FfsFileHeaderSize);
} else {
memset (&BlankHeader, 0, FfsFileHeaderSize);
}
//
// Is this FV blank?
//
if (memcmp (&BlankHeader, CurrentFile, FfsFileHeaderSize) == 0) {
return EFI_SUCCESS;
}
//
// Print file information.
//
FileState = GetFileState (ErasePolarity, (EFI_FFS_FILE_HEADER *)CurrentFile);
PrintGuidToBuffer (&(CurrentFile->Name), GuidBuffer, PRINTED_GUID_BUFFER_SIZE, FALSE);
if (FileState == EFI_FILE_DATA_VALID) {
//
// Calculate header checksum
//
Checksum = CalculateSum8 ((UINT8 *) CurrentFile, FfsFileHeaderSize);
Checksum = (UINT8) (Checksum - CurrentFile->IntegrityCheck.Checksum.File);
Checksum = (UINT8) (Checksum - CurrentFile->State);
if (Checksum != 0) {
Error ("FMMT", 0, 0003, "error parsing FFS file", "FFS file with Guid %s has invalid header checksum", GuidBuffer);
return EFI_ABORTED;
}
if (CurrentFile->Attributes & FFS_ATTRIB_CHECKSUM) {
//
// Calculate file checksum
//
Checksum = CalculateSum8 ((UINT8 *) ((UINTN)CurrentFile + FfsFileHeaderSize), FileLength - FfsFileHeaderSize);
Checksum = Checksum + CurrentFile->IntegrityCheck.Checksum.File;
if (Checksum != 0) {
Error ("FMMT", 0, 0003, "error parsing FFS file", "FFS file with Guid %s has invalid file checksum", GuidBuffer);
return EFI_ABORTED;
}
} else {
if (CurrentFile->IntegrityCheck.Checksum.File != FFS_FIXED_CHECKSUM) {
Error ("FMMT", 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;
}
}
} else {
Error ("FMMT", 0, 0003, "error parsing FFS file", "FFS file with Guid %s has the invalid/unrecognized file state bits", GuidBuffer);
return EFI_ABORTED;
}
Level += 1;
if ((CurrentFile->Type != EFI_FV_FILETYPE_ALL) && (CurrentFile->Type != EFI_FV_FILETYPE_FFS_PAD)) {
//
// Put in encapsulate data information.
//
LocalEncapData = *CurrentFvEncapData;
if (LocalEncapData->NextNode != NULL) {
LocalEncapData = LocalEncapData->NextNode;
EncapDataNeedUpdateFlag = FALSE;
while (LocalEncapData->RightNode != NULL) {
LocalEncapData = LocalEncapData->RightNode;
}
}
if (EncapDataNeedUpdateFlag) {
//
// Construct the new ENCAP_DATA
//
LocalEncapData->NextNode = (ENCAP_INFO_DATA *) malloc (sizeof (ENCAP_INFO_DATA));
if (LocalEncapData->NextNode == NULL) {
Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);
return EFI_ABORTED;
}
LocalEncapData = LocalEncapData->NextNode;
LocalEncapData->Level = Level;
LocalEncapData->Type = FMMT_ENCAP_TREE_FFS;
LocalEncapData->FvExtHeader = NULL;
LocalEncapData->Depex = NULL;
LocalEncapData->DepexLen = 0;
LocalEncapData->UiNameSize = 0;
//
// Store the header of FFS file.
//
LocalEncapData->Data = malloc (FfsFileHeaderSize);
if (LocalEncapData->Data == NULL) {
Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);
return EFI_ABORTED;
}
memcpy (LocalEncapData->Data, CurrentFile, FfsFileHeaderSize);
LocalEncapData->FvExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *)malloc(sizeof(EFI_FIRMWARE_VOLUME_EXT_HEADER));
if (LocalEncapData->FvExtHeader == NULL) {
Error(NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);
return EFI_ABORTED;
}
LocalEncapData->FvExtHeader->FvName.Data1 = CurrentFile->Name.Data1;
LocalEncapData->FvExtHeader->FvName.Data2 = CurrentFile->Name.Data2;
LocalEncapData->FvExtHeader->FvName.Data3 = CurrentFile->Name.Data3;
LocalEncapData->FvExtHeader->FvName.Data4[0] = CurrentFile->Name.Data4[0];
LocalEncapData->FvExtHeader->FvName.Data4[1] = CurrentFile->Name.Data4[1];
LocalEncapData->FvExtHeader->FvName.Data4[2] = CurrentFile->Name.Data4[2];
LocalEncapData->FvExtHeader->FvName.Data4[3] = CurrentFile->Name.Data4[3];
LocalEncapData->FvExtHeader->FvName.Data4[4] = CurrentFile->Name.Data4[4];
LocalEncapData->FvExtHeader->FvName.Data4[5] = CurrentFile->Name.Data4[5];
LocalEncapData->FvExtHeader->FvName.Data4[6] = CurrentFile->Name.Data4[6];
LocalEncapData->FvExtHeader->FvName.Data4[7] = CurrentFile->Name.Data4[7];
LocalEncapData->NextNode = NULL;
LocalEncapData->RightNode = NULL;
}else{
//
// Construct the new ENCAP_DATA
//
LocalEncapData->RightNode = (ENCAP_INFO_DATA *) malloc (sizeof (ENCAP_INFO_DATA));
if (LocalEncapData->RightNode == NULL) {
Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);
return EFI_ABORTED;
}
LocalEncapData = LocalEncapData->RightNode;
LocalEncapData->Level = Level;
LocalEncapData->Type = FMMT_ENCAP_TREE_FFS;
LocalEncapData->FvExtHeader = NULL;
LocalEncapData->Depex = NULL;
LocalEncapData->DepexLen = 0;
LocalEncapData->UiNameSize = 0;
//
// Store the header of FFS file.
//
LocalEncapData->Data = malloc (FfsFileHeaderSize);
if (LocalEncapData->Data == NULL) {
Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);
return EFI_ABORTED;
}
memcpy (LocalEncapData->Data, CurrentFile, FfsFileHeaderSize);
LocalEncapData->FvExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *)malloc(sizeof(EFI_FIRMWARE_VOLUME_EXT_HEADER));
if (LocalEncapData->FvExtHeader == NULL) {
Error(NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);
return EFI_ABORTED;
}
LocalEncapData->FvExtHeader->FvName.Data1 = CurrentFile->Name.Data1;
LocalEncapData->FvExtHeader->FvName.Data2 = CurrentFile->Name.Data2;
LocalEncapData->FvExtHeader->FvName.Data3 = CurrentFile->Name.Data3;
LocalEncapData->FvExtHeader->FvName.Data4[0] = CurrentFile->Name.Data4[0];
LocalEncapData->FvExtHeader->FvName.Data4[1] = CurrentFile->Name.Data4[1];
LocalEncapData->FvExtHeader->FvName.Data4[2] = CurrentFile->Name.Data4[2];
LocalEncapData->FvExtHeader->FvName.Data4[3] = CurrentFile->Name.Data4[3];
LocalEncapData->FvExtHeader->FvName.Data4[4] = CurrentFile->Name.Data4[4];
LocalEncapData->FvExtHeader->FvName.Data4[5] = CurrentFile->Name.Data4[5];
LocalEncapData->FvExtHeader->FvName.Data4[6] = CurrentFile->Name.Data4[6];
LocalEncapData->FvExtHeader->FvName.Data4[7] = CurrentFile->Name.Data4[7];
LocalEncapData->RightNode = NULL;
LocalEncapData->NextNode = NULL;
}
if ( CurrentFile->Type == EFI_FV_FILETYPE_RAW){
CurrentFv->FfsAttuibutes[*FfsCount].Level = Level;
if (!ViewFlag){
LibGenFfsFile(CurrentFile, CurrentFv, FvName, Level, FfsCount, ErasePolarity);
}
} else if( CurrentFile->Type == EFI_FV_FILETYPE_FFS_PAD){
//EFI_FV_FILETYPE_FFS_PAD
} else {
//
// All other files have sections
//
Status = LibParseSection (
(UINT8 *) ((UINTN) CurrentFile + FfsFileHeaderSize),
FileLength - FfsFileHeaderSize,
CurrentFv,
FvName,
CurrentFile,
Level,
&LocalEncapData,
Level,
FfsCount,
FvCount,
ViewFlag,
ErasePolarity,
&IsGeneratedFfs
);
}
if (EFI_ERROR (Status)) {
printf ("ERROR: Parsing the FFS file.\n");
return Status;
}
}
return EFI_SUCCESS;
}
/**
Get firmware information. Including the FV headers,
@param[in] Fv - Firmware Volume to get information from
@return EFI_STATUS
**/
EFI_STATUS
LibGetFvInfo (
IN VOID *Fv,
IN OUT FV_INFORMATION *CurrentFv,
IN CHAR8 *FvName,
IN UINT8 Level,
IN ENCAP_INFO_DATA **CurrentFvEncapData,
IN UINT32 *FfsCount,
IN OUT UINT8 *FvCount,
IN BOOLEAN ViewFlag,
IN BOOLEAN IsChildFv
)
{
EFI_STATUS Status;
UINTN NumberOfFiles;
BOOLEAN ErasePolarity;
UINTN FvSize;
EFI_FFS_FILE_HEADER2 *CurrentFile;
UINTN Key;
ENCAP_INFO_DATA *LocalEncapData;
EFI_FIRMWARE_VOLUME_EXT_HEADER *ExtHdrPtr;
EFI_FIRMWARE_VOLUME_HEADER *FvHdr;
NumberOfFiles = 0;
Key = 0;
LocalEncapData = NULL;
CurrentFile = NULL;
FvHdr = (EFI_FIRMWARE_VOLUME_HEADER *)Fv;
Level += 1;
*FvCount += 1;
CurrentFv->FvLevel += 1;
Status = FvBufGetSize (Fv, &FvSize);
ErasePolarity = (((EFI_FIRMWARE_VOLUME_HEADER*)Fv)->Attributes & EFI_FVB2_ERASE_POLARITY) ? TRUE : FALSE;
Status = LibReadFvHeader (Fv, ViewFlag, CurrentFv->FvLevel, *FvCount - 1, CurrentFv->FvName);
if (EFI_ERROR (Status)) {
Error (NULL, 0, 0003, "error parsing FV image", "Header is invalid");
return EFI_ABORTED;
}
if (!IsChildFv) {
//
// Write FV header information into CurrentFv struct.
//
CurrentFv->FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) malloc (FvHdr->HeaderLength);
if (CurrentFv->FvHeader == NULL) {
Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);
return EFI_ABORTED;
}
//
// Get the FV Header information
//
memcpy(CurrentFv->FvHeader, Fv, FvHdr->HeaderLength);
CurrentFv->FvExtHeader = NULL;
CurrentFv->FvUiName = NULL;
//
// Exist Extend FV header.
//
if (CurrentFv->FvHeader->ExtHeaderOffset != 0){
ExtHdrPtr = (VOID *)((UINTN)Fv + CurrentFv->FvHeader->ExtHeaderOffset);
CurrentFv->FvExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *) malloc (ExtHdrPtr->ExtHeaderSize);
if (CurrentFv->FvExtHeader == NULL) {
Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);
return EFI_ABORTED;
}
//
// Get the FV extended Header information
//
memcpy (CurrentFv->FvExtHeader, (VOID *)((UINTN)Fv + CurrentFv->FvHeader->ExtHeaderOffset), ExtHdrPtr->ExtHeaderSize);
LibExtractFvUiName(CurrentFv->FvExtHeader, &CurrentFv->FvUiName);
}
}
//
// Put encapsulate information into structure.
//
LocalEncapData = *CurrentFvEncapData;
if (LocalEncapData == NULL && !IsChildFv) {
//
// First time in, the root FV
//
LocalEncapData = (ENCAP_INFO_DATA *) malloc (sizeof (ENCAP_INFO_DATA));
CurrentFv->EncapData = LocalEncapData;
if (CurrentFv->EncapData == NULL) {
Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);
return EFI_ABORTED;
}
CurrentFv->EncapData->FvExtHeader = NULL;
CurrentFv->EncapData->Depex = NULL;
CurrentFv->EncapData->DepexLen = 0;
CurrentFv->EncapData->UiNameSize = 0;
CurrentFv->EncapData->Level = Level;
CurrentFv->EncapData->Type = FMMT_ENCAP_TREE_FV;
CurrentFv->EncapData->Data = (EFI_FIRMWARE_VOLUME_HEADER *) malloc (sizeof (EFI_FIRMWARE_VOLUME_HEADER));
CurrentFv->EncapData->FvId = *FvCount;
if (CurrentFv->EncapData->Data == NULL) {
Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);
return EFI_ABORTED;
}
memcpy (CurrentFv->EncapData->Data, Fv, sizeof (EFI_FIRMWARE_VOLUME_HEADER));
if (((EFI_FIRMWARE_VOLUME_HEADER *)(CurrentFv->EncapData->Data))->ExtHeaderOffset != 0) {
ExtHdrPtr = (VOID *)((UINTN)Fv + ((EFI_FIRMWARE_VOLUME_HEADER *)(CurrentFv->EncapData->Data))->ExtHeaderOffset);
CurrentFv->EncapData->FvExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *) malloc (ExtHdrPtr->ExtHeaderSize);
if (CurrentFv->EncapData->FvExtHeader == NULL) {
Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);
return EFI_ABORTED;
}
//
// Get the FV extended Header information
//
memcpy(CurrentFv->EncapData->FvExtHeader, (VOID *)((UINTN)Fv + ((EFI_FIRMWARE_VOLUME_HEADER *)(CurrentFv->EncapData->Data))->ExtHeaderOffset), ExtHdrPtr->ExtHeaderSize);
}
CurrentFv->EncapData->NextNode = NULL;
CurrentFv->EncapData->RightNode = NULL;
} else if (LocalEncapData == NULL) {
return EFI_ABORTED;
} else if (IsChildFv) {
LocalEncapData = *CurrentFvEncapData;
while (LocalEncapData->NextNode != NULL) {
LocalEncapData = LocalEncapData->NextNode;
}
//
// Construct the new ENCAP_DATA
//
LocalEncapData->NextNode = (ENCAP_INFO_DATA *) malloc (sizeof (ENCAP_INFO_DATA));
if (LocalEncapData->NextNode == NULL) {
Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);
return EFI_ABORTED;
}
LocalEncapData = LocalEncapData->NextNode;
LocalEncapData->Level = Level;
LocalEncapData->Type = FMMT_ENCAP_TREE_FV;
LocalEncapData->Data = (EFI_FIRMWARE_VOLUME_HEADER *) malloc (sizeof (EFI_FIRMWARE_VOLUME_HEADER));
LocalEncapData->FvExtHeader = NULL;
LocalEncapData->Depex = NULL;
LocalEncapData->DepexLen = 0;
LocalEncapData->UiNameSize = 0;
LocalEncapData->FvId = *FvCount;
if (LocalEncapData->Data == NULL) {
Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);
return EFI_ABORTED;
}
memcpy (LocalEncapData->Data, Fv, sizeof (EFI_FIRMWARE_VOLUME_HEADER));
if (((EFI_FIRMWARE_VOLUME_HEADER *)(LocalEncapData->Data))->ExtHeaderOffset != 0) {
ExtHdrPtr = (VOID *)((UINTN)Fv + ((EFI_FIRMWARE_VOLUME_HEADER *)(LocalEncapData->Data))->ExtHeaderOffset);
LocalEncapData->FvExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *)malloc(ExtHdrPtr->ExtHeaderSize);
if (LocalEncapData->FvExtHeader == NULL) {
Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);
return EFI_ABORTED;
}
//
// Get the FV extended Header information
//
memcpy(LocalEncapData->FvExtHeader, (VOID *)((UINTN)Fv + ((EFI_FIRMWARE_VOLUME_HEADER *)(LocalEncapData->Data))->ExtHeaderOffset), ExtHdrPtr->ExtHeaderSize);
}
LocalEncapData->NextNode = NULL;
LocalEncapData->RightNode = NULL;
}
//
// Get the first file
//
Status = FvBufFindNextFile (Fv, &Key, (VOID **) &CurrentFile);
if (Status == EFI_NOT_FOUND) {
CurrentFile = NULL;
} else if (EFI_ERROR (Status)) {
Error ("FMMT", 0, 0003, "error parsing FV image", "cannot find the first file in the FV image");
return Status;
}
while (CurrentFile != NULL) {
//
// Increment the number of files counter
//
NumberOfFiles++;
//
// Store FFS file Header information
//
CurrentFv->FfsHeader[*FfsCount].Attributes = CurrentFile->Attributes;
CurrentFv->FfsHeader[*FfsCount].IntegrityCheck = CurrentFile->IntegrityCheck;
CurrentFv->FfsHeader[*FfsCount].Name = CurrentFile->Name;
CurrentFv->FfsHeader[*FfsCount].Size[0] = CurrentFile->Size[0];
CurrentFv->FfsHeader[*FfsCount].Size[1] = CurrentFile->Size[1];
CurrentFv->FfsHeader[*FfsCount].Size[2] = CurrentFile->Size[2];
CurrentFv->FfsHeader[*FfsCount].State = CurrentFile->State;
CurrentFv->FfsHeader[*FfsCount].Type = CurrentFile->Type;
CurrentFv->FfsHeader[*FfsCount].ExtendedSize = CurrentFile->ExtendedSize;
CurrentFv->FfsAttuibutes[*FfsCount].Offset = Key - GetFfsFileLength ((EFI_FFS_FILE_HEADER *) CurrentFile);
CurrentFv->FfsAttuibutes[*FfsCount].FvLevel = CurrentFv->FvLevel;
if (CurrentFv->FvLevel > CurrentFv->MulFvLevel) {
CurrentFv->MulFvLevel = CurrentFv->FvLevel;
}
//
// Display info about this file
//
Status = LibGetFileInfo (Fv, CurrentFile, ErasePolarity, CurrentFv, FvName, Level, &LocalEncapData, FfsCount, FvCount, ViewFlag);
if (EFI_ERROR (Status)) {
Error ("FMMT", 0, 0003, "error parsing FV image", "failed to parse a file in the FV");
return Status;
}
//
// Get the next file
//
Status = FvBufFindNextFile (Fv, &Key, (VOID **) &CurrentFile);
if (Status == EFI_NOT_FOUND) {
CurrentFile = NULL;
} else if (EFI_ERROR (Status)) {
Error ("FMMT", 0, 0003, "error parsing FV image", "cannot find the next file in the FV image");
return Status;
}
}
if (IsChildFv) {
if (CurrentFv->FvLevel > 1) {
CurrentFv->FvLevel -= 1;
}
}
return EFI_SUCCESS;
}
/**
This function returns the next larger size that meets the alignment
requirement specified.
@param[in] ActualSize The size.
@param[in] Alignment The desired alignment.
@retval EFI_SUCCESS Function completed successfully.
@retval EFI_ABORTED The function encountered an error.
**/
UINT32
GetOccupiedSize (
IN UINT32 ActualSize,
IN UINT32 Alignment
)
{
UINT32 OccupiedSize;
OccupiedSize = ActualSize;
while ((OccupiedSize & (Alignment - 1)) != 0) {
OccupiedSize++;
}
return OccupiedSize;
}
EFI_STATUS
LibDeleteAndRenameFfs(
IN CHAR8* DeleteFile,
IN CHAR8* NewFile
)
{
CHAR8* SystemCommand;
CHAR8* TemDir;
SystemCommand = NULL;
if (DeleteFile == NULL ||
NewFile == NULL) {
return EFI_INVALID_PARAMETER;
}
//
// Delete the file of the specified extract FFS file.
//
SystemCommand = malloc (
strlen (DEL_STR) +
strlen (DeleteFile) +
1
);
if (SystemCommand == NULL) {
Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);
return EFI_ABORTED;
}
sprintf (
SystemCommand,
DEL_STR,
DeleteFile
);
if (system (SystemCommand) != EFI_SUCCESS) {
free(SystemCommand);
return EFI_ABORTED;
}
free(SystemCommand);
TemDir = getcwd (NULL, _MAX_PATH);
if (strlen (TemDir) + strlen(OS_SEP_STR) + strlen (TEMP_DIR_NAME) > _MAX_PATH - 1) {
Error("FMMT", 0, 1001, "The directory is too long.", "");
return EFI_ABORTED;
}
strncat (TemDir, OS_SEP_STR, _MAX_PATH - strlen(TemDir) - 1);
strncat (TemDir, TEMP_DIR_NAME, _MAX_PATH - strlen(TemDir) - 1);
mkdir(TemDir, S_IRWXU | S_IRWXG | S_IRWXO);
//
// Create a copy the new file.
//
SystemCommand = malloc (
strlen (COPY_STR) +
strlen (NewFile) +
strlen (DeleteFile) +
1
);
if (SystemCommand == NULL) {
Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);
return EFI_ABORTED;
}
sprintf (
SystemCommand,
COPY_STR,
NewFile,
DeleteFile
);
if (system (SystemCommand) != EFI_SUCCESS) {
free(SystemCommand);
return EFI_ABORTED;
}
free(SystemCommand);
return EFI_SUCCESS;
}
/**
Converts ASCII characters to Unicode.
Assumes that the Unicode characters are only these defined in the ASCII set.
String - Pointer to string that is written to FILE.
UniString - Pointer to unicode string
The address to the ASCII string - same as AsciiStr.
**/
VOID
LibAscii2Unicode (
IN CHAR8 *String,
OUT CHAR16 *UniString
)
{
while (*String != '\0') {
*(UniString++) = (CHAR16) *(String++);
}
//
// End the UniString with a NULL.
//
*UniString = '\0';
}
EFI_STATUS
LibCreateGuidedSectionOriginalData(
IN CHAR8* FileIn,
IN CHAR8* ToolName,
IN CHAR8* FileOut
)
{
CHAR8* SystemCommandFormatString;
CHAR8* SystemCommand;
SystemCommandFormatString = NULL;
SystemCommand = NULL;
if (FileIn == NULL ||
ToolName == NULL ||
FileOut == NULL) {
return EFI_INVALID_PARAMETER;
}
//
// Delete the file of the specified extract FFS file.
//
SystemCommandFormatString = "%s -e \"%s\" -o \"%s\"";
SystemCommand = malloc (
strlen (SystemCommandFormatString) +
strlen (FileIn) +
strlen (ToolName) +
strlen (FileOut) +
1
);
if (SystemCommand == NULL) {
Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);
return EFI_ABORTED;
}
sprintf (
SystemCommand,
"%s -e \"%s\" -o \"%s\"",
ToolName,
FileIn,
FileOut
);
if (system (SystemCommand) != EFI_SUCCESS) {
printf("Command failed: %s\n", SystemCommand);
free(SystemCommand);
return EFI_ABORTED;
}
free(SystemCommand);
return EFI_SUCCESS;
}
/**
This function convert the FV header's attribute to a string. The converted string
will be put into an INF file as the input of GenFV.
@param[in] Attr FV header's attribute.
@param[out] InfFile InfFile contain FV header attribute information.
@retval EFI_SUCCESS.
@retval EFI_INVLID_PARAMETER
@retval EFI_OUT_OF_RESOURCES
**/
EFI_STATUS
LibFvHeaderAttributeToStr (
IN EFI_FVB_ATTRIBUTES_2 Attr,
IN FILE* InfFile
)
{
CHAR8 *LocalStr;
LocalStr = NULL;
LocalStr = (CHAR8 *) malloc (1024 * 4);
if (LocalStr == NULL) {
printf ("Memory allocate error!\n");
return EFI_OUT_OF_RESOURCES;
}
memset (LocalStr, '\0', 1024 * 4);
if (Attr == 0 || InfFile == NULL) {
free (LocalStr);
return EFI_INVALID_PARAMETER;
}
strncat (LocalStr, "[attributes] \n", sizeof("[attributes] \n"));
if (Attr & EFI_FVB2_READ_DISABLED_CAP) {
strncat (LocalStr, "EFI_READ_DISABLED_CAP = TRUE \n", sizeof ("EFI_READ_DISABLED_CAP = TRUE \n"));
}
if (Attr & EFI_FVB2_READ_ENABLED_CAP) {
strncat (LocalStr, "EFI_READ_ENABLED_CAP = TRUE \n", sizeof ("EFI_READ_ENABLED_CAP = TRUE \n"));
}
if (Attr & EFI_FVB2_READ_STATUS) {
strncat (LocalStr, "EFI_READ_STATUS = TRUE \n", sizeof ("EFI_READ_STATUS = TRUE \n"));
}
if (Attr & EFI_FVB2_WRITE_DISABLED_CAP) {
strncat (LocalStr, "EFI_WRITE_DISABLED_CAP = TRUE \n", sizeof ("EFI_WRITE_DISABLED_CAP = TRUE \n"));
}
if (Attr & EFI_FVB2_WRITE_ENABLED_CAP) {
strncat (LocalStr, "EFI_WRITE_ENABLED_CAP = TRUE \n", sizeof ("EFI_WRITE_ENABLED_CAP = TRUE \n"));
}
if (Attr & EFI_FVB2_WRITE_STATUS) {
strncat (LocalStr, "EFI_WRITE_STATUS = TRUE \n", sizeof ("EFI_WRITE_STATUS = TRUE \n"));
}
if (Attr & EFI_FVB2_LOCK_CAP) {
strncat (LocalStr, "EFI_LOCK_CAP = TRUE \n", sizeof ("EFI_LOCK_CAP = TRUE \n"));
}
if (Attr & EFI_FVB2_LOCK_STATUS) {
strncat (LocalStr, "EFI_LOCK_STATUS = TRUE \n", sizeof ("EFI_LOCK_STATUS = TRUE \n"));
}
if (Attr & EFI_FVB2_STICKY_WRITE) {
strncat (LocalStr, "EFI_STICKY_WRITE = TRUE \n", sizeof ("EFI_STICKY_WRITE = TRUE \n"));
}
if (Attr & EFI_FVB2_MEMORY_MAPPED) {
strncat (LocalStr, "EFI_MEMORY_MAPPED = TRUE \n", sizeof ("EFI_MEMORY_MAPPED = TRUE \n"));
}
if (Attr & EFI_FVB2_ERASE_POLARITY) {
strncat (LocalStr, "EFI_ERASE_POLARITY = 1 \n", sizeof ("EFI_ERASE_POLARITY = 1 \n"));
}
if (Attr & EFI_FVB2_READ_LOCK_CAP) {
strncat (LocalStr, "EFI_READ_LOCK_CAP = TRUE \n", sizeof ("EFI_READ_LOCK_CAP = TRUE \n"));
}
if (Attr & EFI_FVB2_READ_LOCK_STATUS) {
strncat (LocalStr, "EFI_READ_LOCK_STATUS = TRUE \n", sizeof ("EFI_READ_LOCK_STATUS = TRUE \n"));
}
if (Attr & EFI_FVB2_WRITE_LOCK_CAP) {
strncat (LocalStr, "EFI_WRITE_LOCK_CAP = TRUE \n", sizeof ("EFI_WRITE_LOCK_CAP = TRUE \n"));
}
if (Attr & EFI_FVB2_WRITE_LOCK_STATUS) {
strncat (LocalStr, "EFI_WRITE_LOCK_STATUS = TRUE \n", sizeof ("EFI_WRITE_LOCK_STATUS = TRUE \n"));
}
if (Attr & EFI_FVB2_LOCK_STATUS) {
strncat (LocalStr, "EFI_READ_LOCK_STATUS = TRUE \n", sizeof ("EFI_READ_LOCK_STATUS = TRUE \n"));
}
//
// Alignment
//
if (Attr & EFI_FVB2_ALIGNMENT_1) {
strncat (LocalStr, "EFI_FVB2_ALIGNMENT_1 = TRUE \n", sizeof ("EFI_FVB2_ALIGNMENT_1 = TRUE \n"));
} else if (Attr & EFI_FVB2_ALIGNMENT_2) {
strncat (LocalStr, "EFI_FVB2_ALIGNMENT_2 = TRUE \n", sizeof ("EFI_FVB2_ALIGNMENT_2 = TRUE \n"));
} else if (Attr & EFI_FVB2_ALIGNMENT_4) {
strncat (LocalStr, "EFI_FVB2_ALIGNMENT_4 = TRUE \n", sizeof ("EFI_FVB2_ALIGNMENT_4 = TRUE \n"));
} else if (Attr & EFI_FVB2_ALIGNMENT_8) {
strncat (LocalStr, "EFI_FVB2_ALIGNMENT_8 = TRUE \n", sizeof ("EFI_FVB2_ALIGNMENT_8 = TRUE \n"));
} else if (Attr & EFI_FVB2_ALIGNMENT_16) {
strncat (LocalStr, "EFI_FVB2_ALIGNMENT_16 = TRUE \n", sizeof ("EFI_FVB2_ALIGNMENT_16 = TRUE \n"));
} else if (Attr & EFI_FVB2_ALIGNMENT_32) {
strncat (LocalStr, "EFI_FVB2_ALIGNMENT_32 = TRUE \n", sizeof ("EFI_FVB2_ALIGNMENT_32 = TRUE \n"));
} else if (Attr & EFI_FVB2_ALIGNMENT_64) {
strncat (LocalStr, "EFI_FVB2_ALIGNMENT_64 = TRUE \n", sizeof ("EFI_FVB2_ALIGNMENT_64 = TRUE \n"));
} else if (Attr & EFI_FVB2_ALIGNMENT_128) {
strncat (LocalStr, "EFI_FVB2_ALIGNMENT_128 = TRUE \n", sizeof ("EFI_FVB2_ALIGNMENT_128 = TRUE \n"));
} else if (Attr & EFI_FVB2_ALIGNMENT_256) {
strncat (LocalStr, "EFI_FVB2_ALIGNMENT_256 = TRUE \n", sizeof ("EFI_FVB2_ALIGNMENT_256 = TRUE \n"));
} else if (Attr & EFI_FVB2_ALIGNMENT_512) {
strncat (LocalStr, "EFI_FVB2_ALIGNMENT_512 = TRUE \n", sizeof ("EFI_FVB2_ALIGNMENT_512 = TRUE \n"));
} else if (Attr & EFI_FVB2_ALIGNMENT_1K) {
strncat (LocalStr, "EFI_FVB2_ALIGNMENT_1K = TRUE \n", sizeof ("EFI_FVB2_ALIGNMENT_1K = TRUE \n"));
} else if (Attr & EFI_FVB2_ALIGNMENT_2K) {
strncat (LocalStr, "EFI_FVB2_ALIGNMENT_2K = TRUE \n", sizeof ("EFI_FVB2_ALIGNMENT_2K = TRUE \n"));
} else if (Attr & EFI_FVB2_ALIGNMENT_4K) {
strncat (LocalStr, "EFI_FVB2_ALIGNMENT_4K = TRUE \n", sizeof ("EFI_FVB2_ALIGNMENT_4K = TRUE \n"));
} else if (Attr & EFI_FVB2_ALIGNMENT_8K) {
strncat (LocalStr, "EFI_FVB2_ALIGNMENT_8K = TRUE \n", sizeof ("EFI_FVB2_ALIGNMENT_8K = TRUE \n"));
} else if (Attr & EFI_FVB2_ALIGNMENT_16K) {
strncat (LocalStr, "EFI_FVB2_ALIGNMENT_16K = TRUE \n", sizeof ("EFI_FVB2_ALIGNMENT_16K = TRUE \n"));
} else if (Attr & EFI_FVB2_ALIGNMENT_32K) {
strncat (LocalStr, "EFI_FVB2_ALIGNMENT_32K = TRUE \n", sizeof ("EFI_FVB2_ALIGNMENT_32K = TRUE \n"));
} else if (Attr & EFI_FVB2_ALIGNMENT_64K) {
strncat (LocalStr, "EFI_FVB2_ALIGNMENT_64K = TRUE \n", sizeof ("EFI_FVB2_ALIGNMENT_64K = TRUE \n"));
} else if (Attr & EFI_FVB2_ALIGNMENT_128K) {
strncat (LocalStr, "EFI_FVB2_ALIGNMENT_128K = TRUE \n", sizeof ("EFI_FVB2_ALIGNMENT_128K = TRUE \n"));
} else if (Attr & EFI_FVB2_ALIGNMENT_256K) {
strncat (LocalStr, "EFI_FVB2_ALIGNMENT_256K = TRUE \n", sizeof ("EFI_FVB2_ALIGNMENT_256K = TRUE \n"));
} else if (Attr & EFI_FVB2_ALIGNMENT_512K) {
strncat (LocalStr, "EFI_FVB2_ALIGNMENT_512K = TRUE \n", sizeof ("EFI_FVB2_ALIGNMENT_512K = TRUE \n"));
} else if (Attr & EFI_FVB2_ALIGNMENT_1M) {
strncat (LocalStr, "EFI_FVB2_ALIGNMENT_1M = TRUE \n", sizeof ("EFI_FVB2_ALIGNMENT_1M = TRUE \n"));
} else if (Attr & EFI_FVB2_ALIGNMENT_2M) {
strncat (LocalStr, "EFI_FVB2_ALIGNMENT_2M = TRUE \n", sizeof ("EFI_FVB2_ALIGNMENT_2M = TRUE \n"));
} else if (Attr & EFI_FVB2_ALIGNMENT_4M) {
strncat (LocalStr, "EFI_FVB2_ALIGNMENT_4M = TRUE \n", sizeof ("EFI_FVB2_ALIGNMENT_4M = TRUE \n"));
} else if (Attr & EFI_FVB2_ALIGNMENT_8M) {
strncat (LocalStr, "EFI_FVB2_ALIGNMENT_8M = TRUE \n", sizeof ("EFI_FVB2_ALIGNMENT_8M = TRUE \n"));
} else if (Attr & EFI_FVB2_ALIGNMENT_16M) {
strncat (LocalStr, "EFI_FVB2_ALIGNMENT_16M = TRUE \n", sizeof ("EFI_FVB2_ALIGNMENT_16M = TRUE \n"));
} else if (Attr & EFI_FVB2_ALIGNMENT_32M) {
strncat (LocalStr, "EFI_FVB2_ALIGNMENT_32M = TRUE \n", sizeof ("EFI_FVB2_ALIGNMENT_32M = TRUE \n"));
} else if (Attr & EFI_FVB2_ALIGNMENT_64M) {
strncat (LocalStr, "EFI_FVB2_ALIGNMENT_64M = TRUE \n", sizeof ("EFI_FVB2_ALIGNMENT_64M = TRUE \n"));
} else if (Attr & EFI_FVB2_ALIGNMENT_128M) {
strncat (LocalStr, "EFI_FVB2_ALIGNMENT_128M = TRUE \n", sizeof ("EFI_FVB2_ALIGNMENT_128M = TRUE \n"));
} else if (Attr & EFI_FVB2_ALIGNMENT_256M) {
strncat (LocalStr, "EFI_FVB2_ALIGNMENT_256M = TRUE \n", sizeof ("EFI_FVB2_ALIGNMENT_256M = TRUE \n"));
} else if (Attr & EFI_FVB2_ALIGNMENT_512M) {
strncat (LocalStr, "EFI_FVB2_ALIGNMENT_512M = TRUE \n", sizeof ("EFI_FVB2_ALIGNMENT_512M = TRUE \n"));
} else if (Attr & EFI_FVB2_ALIGNMENT_1G) {
strncat (LocalStr, "EFI_FVB2_ALIGNMENT_1G = TRUE \n", sizeof ("EFI_FVB2_ALIGNMENT_1G = TRUE \n"));
} else if (Attr & EFI_FVB2_ALIGNMENT_2G) {
strncat (LocalStr, "EFI_FVB2_ALIGNMENT_2G = TRUE \n", sizeof ("EFI_FVB2_ALIGNMENT_2G = TRUE \n"));
}
if (fwrite (LocalStr, 1, (size_t) strlen (LocalStr), InfFile) != (size_t) strlen (LocalStr)) {
printf ("Error while writing data to %p file.", (void*)InfFile);
free (LocalStr);
return EFI_ABORTED;
}
free (LocalStr);
return EFI_SUCCESS;
}
/**
This function fill the FV inf files option field.
@param[in] BlockMap FV header's attribute.
@param[out] InfFile InfFile contain FV header attribute information.
@retval EFI_SUCCESS.
@retval EFI_INVLID_PARAMETER
**/
EFI_STATUS
LibFvHeaderOptionToStr (
IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader,
IN FILE* InfFile,
IN BOOLEAN IsRootFv
)
{
CHAR8 *LocalStr;
CHAR8 *TempStr;
EFI_FV_BLOCK_MAP_ENTRY *BlockMap;
LocalStr = NULL;
TempStr = NULL;
if (FvHeader == NULL || InfFile == NULL) {
return EFI_INVALID_PARAMETER;
}
//
// This section will not over 1024 bytes and each line will never over 128 bytes.
//
LocalStr = (CHAR8 *) malloc (1024);
TempStr = (CHAR8 *) malloc (128);
if (LocalStr == NULL ||
TempStr == NULL ) {
if (LocalStr != NULL) {
free (LocalStr);
}
if (TempStr != NULL) {
free (TempStr);
}
printf ("Memory allocate error! \n");
return EFI_OUT_OF_RESOURCES;
}
BlockMap = FvHeader->BlockMap;
memset (LocalStr, '\0', 1024);
memset (TempStr, '\0', 128);
strncat (LocalStr, "[options] \n", sizeof("[Options] \n"));
snprintf (TempStr, 128, "EFI_BLOCK_SIZE = 0x%x \n", BlockMap->Length);
strncat (LocalStr, TempStr, strlen(TempStr));
if (IsRootFv) {
snprintf (TempStr, 128, "EFI_NUM_BLOCKS = 0x%x \n", BlockMap->NumBlocks);
strncat (LocalStr, TempStr, strlen(TempStr));
}
if (fwrite (LocalStr, 1, (size_t) strlen (LocalStr), InfFile) != (size_t) strlen (LocalStr)) {
printf ("Error while writing data to %p file.", (void*)InfFile);
free (LocalStr);
free (TempStr);
return EFI_ABORTED;
}
free (LocalStr);
free (TempStr);
return EFI_SUCCESS;
}
/**
This function fill the FV inf files option field.
@param[in] FfsName Ffs file path/name.
@param[out] InfFile InfFile contain FV header attribute information
@param[in] FirstIn Is the first time call this function? If yes, should create [files] section.
@retval EFI_SUCCESS.
@retval EFI_INVLID_PARAMETER
**/
EFI_STATUS
LibAddFfsFileToFvInf (
IN CHAR8 *FfsName,
IN FILE* InfFile,
IN BOOLEAN FirstIn
)
{
CHAR8 *LocalStr;
LocalStr = NULL;
if (FfsName == NULL || InfFile == NULL) {
return EFI_INVALID_PARAMETER;
}
if (strlen(FfsName) == 0) {
return EFI_SUCCESS;
}
LocalStr = (CHAR8 *) malloc (_MAX_PATH);
if (LocalStr == NULL) {
printf ("Memory allocate error! \n");
return EFI_OUT_OF_RESOURCES;
}
memset (LocalStr, '\0', _MAX_PATH);
if (FirstIn) {
sprintf (LocalStr, "[files] \nEFI_FILE_NAME = %s \n", FfsName);
} else {
sprintf (LocalStr, "EFI_FILE_NAME = %s \n", FfsName);
}
if (fwrite (LocalStr, 1, (size_t) strlen (LocalStr), InfFile) != (size_t) strlen (LocalStr)) {
printf ("Error while writing data to %p file.", (void*)InfFile);
free (LocalStr);
return EFI_ABORTED;
}
free (LocalStr);
return EFI_SUCCESS;
}
/**
Convert EFI file to PE or TE section
@param[in] InputFilePath .efi file, it's optional unless process PE/TE section.
@param[in] Type PE or TE and UI/Version
@param[in] OutputFilePath .te or .pe file
@param[in] UiString String for generate UI section usage, this parameter is optional
unless Type is EFI_SECTION_USER_INTERFACE.
@param[in] VerString String for generate Version section usage, this parameter is optional
unless Type is EFI_SECTION_VERSION.
@retval EFI_SUCCESS
**/
EFI_STATUS
LibCreateFfsSection (
IN FV_INFORMATION *FvInFd, OPTIONAL
IN CHAR8* InputFilePath, OPTIONAL
IN CHAR8* Sections, OPTIONAL
IN UINT8 Type,
IN CHAR8* OutputFilePath,
IN CHAR8* UiString, OPTIONAL
IN CHAR8* VerString, OPTIONAL
IN CHAR8* GuidToolGuid, OPTIONAL
IN UINT16 GuidHeaderLength,
IN UINT16 GuidAttr,
IN CHAR8* CompressType OPTIONAL
)
{
//EFI_STATUS Status;
CHAR8* SystemCommandFormatString;
CHAR8* SystemCommand;
FILE *file;
UINT8 Buffer[4];
int BitNum;
int Position;
UINT32 AlignmentValue;
//
// Workaround for static code checkers.
// Ensures the size of 'AlignmentStr' can hold all the digits of an
// unsigned 32-bit integer plus the size unit character.
//
char AlignmentStr[16];
SystemCommandFormatString = NULL;
SystemCommand = NULL;
strcpy(AlignmentStr,"1");
//
// Call GenSec tool to generate FFS section.
//
//
// -s SectionType.
//
if (Type != 0) {
switch (Type) {
//
// Process compression section
//
case EFI_SECTION_COMPRESSION:
SystemCommandFormatString = "GenSec -s %s -c %s \"%s\" -o \"%s\"";
SystemCommand = malloc (
strlen (SystemCommandFormatString) +
strlen (mSectionTypeName[Type]) +
strlen (CompressType) +
strlen (InputFilePath) +
strlen (OutputFilePath) +
1
);
if (SystemCommand == NULL) {
Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);
return EFI_ABORTED;
}
sprintf (
SystemCommand,
"GenSec -s %s -c %s \"%s\" -o \"%s\"",
mSectionTypeName[Type],
CompressType,
InputFilePath,
OutputFilePath
);
if (system (SystemCommand) != EFI_SUCCESS) {
free(SystemCommand);
return EFI_ABORTED;
}
free(SystemCommand);
break;
//
// Process GUID defined section
//
case EFI_SECTION_GUID_DEFINED:
SystemCommandFormatString = "GenSec -s %s -g %s \"%s\" -o \"%s\" -r %s -r %s -l %d";
SystemCommand = malloc (
strlen (SystemCommandFormatString) +
strlen (mSectionTypeName[Type]) +
strlen (GuidToolGuid) +
strlen (InputFilePath) +
strlen (OutputFilePath) +
strlen (mGuidSectionAttr[GuidAttr&0x01]) +
strlen (mGuidSectionAttr[GuidAttr&0x02]) +
4 +
1
);
if (SystemCommand == NULL) {
Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);
return EFI_ABORTED;
}
sprintf (
SystemCommand,
"GenSec -s %s -g %s \"%s\" -o \"%s\" -r %s -r %s -l %d",
mSectionTypeName[Type],
GuidToolGuid,
InputFilePath,
OutputFilePath,
mGuidSectionAttr[GuidAttr&0x01],
mGuidSectionAttr[GuidAttr&0x02],
GuidHeaderLength
);
if (system (SystemCommand) != EFI_SUCCESS) {
free(SystemCommand);
return EFI_ABORTED;
}
free(SystemCommand);
break;
case EFI_SECTION_FIRMWARE_VOLUME_IMAGE:
SystemCommandFormatString = "GenSec -s %s \"%s\" -o \"%s\"";
SystemCommand = malloc (
strlen (SystemCommandFormatString) +
strlen (mSectionTypeName[Type]) +
strlen (InputFilePath) +
strlen (OutputFilePath) +
1
);
if (SystemCommand == NULL) {
Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);
return EFI_ABORTED;
}
sprintf (
SystemCommand,
"GenSec -s %s \"%s\" -o \"%s\"",
mSectionTypeName[Type],
InputFilePath,
OutputFilePath
);
if (system (SystemCommand) != EFI_SUCCESS) {
free(SystemCommand);
return EFI_ABORTED;
}
free(SystemCommand);
break;
default:
Error ("FMMT", 0, 0003, "Please specify the section type while call GenSec tool.", NULL);
return EFI_UNSUPPORTED;
}
} else {
//
// Create Dummy section.
//
file = fopen(InputFilePath, "rb");
if (file == NULL) {
Error(NULL, 0, 0001, "Error opening the file", InputFilePath);
return EFI_INVALID_PARAMETER;
}
// The Section Struct, 3 bits for Size, then 1 bit for Type
if (fread(Buffer, 1, (size_t)(4), file) != (size_t)(4)) {
fclose(file);
return EFI_ABORTED;
}
if (*(Buffer + 3) == EFI_SECTION_FIRMWARE_VOLUME_IMAGE) {
// The Section Struct, if size is not 0xFFFF, the length is 4
Position = 4;
// If Size is 0xFFFFFF then ExtendedSize contains the size of the section
if ((*Buffer == 0xFF) && (*(Buffer + 1) == 0xFF) && (*(Buffer + 2) == 0xFF)) {
Position = 8;
}
//Per EFI_FIRMWARE_VOLUME_HEADER struct, 0x2E bit is EFI_FVB_ATTRIBUTES_2 attr
fseek(file, 0x2E + Position, SEEK_SET);
BitNum = fgetc(file);
AlignmentValue = 1 << (BitNum & 0x1F);
if (AlignmentValue >= 0x400){
if (AlignmentValue >= 0x10000){
strcpy(AlignmentStr,"64K");
}
else{
sprintf(AlignmentStr, "%d", AlignmentValue/0x400);
strcat(AlignmentStr, "K");
}
}
else{
sprintf(AlignmentStr, "%d", AlignmentValue);
}
strcpy(FvInFd->AlignmentStr, AlignmentStr);
}
fclose(file);
SystemCommandFormatString = "GenSec \"%s\" -o \"%s\" --sectionalign %s";
SystemCommand = malloc (
strlen (SystemCommandFormatString) +
strlen (InputFilePath) +
strlen (OutputFilePath) +
4 + // Alignment maximum length
1
);
if (SystemCommand == NULL) {
Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);
return EFI_ABORTED;
}
sprintf (
SystemCommand,
"GenSec \"%s\" -o \"%s\" --sectionalign %s",
InputFilePath,
OutputFilePath,
AlignmentStr
);
if (system (SystemCommand) != EFI_SUCCESS) {
free(SystemCommand);
return EFI_ABORTED;
}
free(SystemCommand);
}
return EFI_SUCCESS;
}
/**
Encapsulate FFSs to FV
@param[in] InputFilePath Section file will be read into this FFS file. This option is required.
@param[in] OutputFilePath The created PI firmware file name. This option is required.
@param[in] BlockSize BlockSize is one HEX or DEC format value required by FV image.
@param[in] FileTakeSize
@retval EFI_SUCCESS
**/
EFI_STATUS
LibEncapsulateFfsToFv (
IN CHAR8* InfFilePath,
IN CHAR8* InputFFSs,
IN CHAR8* OutputFilePath,
IN CHAR8* FvGuidName,
IN BOOLEAN IsLargeFile
)
{
CHAR8* SystemCommandFormatString;
CHAR8* SystemCommand;
CHAR8* FfsGuid = "8c8ce578-8a3d-4f1c-9935-896185c32dd3";
if (IsLargeFile == TRUE) {
FfsGuid = "5473c07a-3dcb-4dca-bd6f-1e9689e7349a";
}
SystemCommandFormatString = NULL;
SystemCommand = NULL;
if (OutputFilePath == NULL ||
InfFilePath == NULL ) {
return EFI_INVALID_PARAMETER;
}
if (InfFilePath != NULL) {
if (FvGuidName == NULL) {
SystemCommandFormatString = "GenFv -i \"%s\" -g %s -o \"%s\"";
SystemCommand = malloc (
strlen (SystemCommandFormatString) +
strlen (InfFilePath) +
strlen (FfsGuid) +
strlen (OutputFilePath) +
1
);
if (SystemCommand == NULL) {
Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);
return EFI_ABORTED;
}
sprintf (
SystemCommand,
"GenFv -i \"%s\" -g %s -o \"%s\"",
InfFilePath, // -i
FfsGuid, // -g
OutputFilePath // -o
);
if (system (SystemCommand) != EFI_SUCCESS) {
free(SystemCommand);
return EFI_ABORTED;
}
free(SystemCommand);
} else {
//
// Have FvGuidName in it.
//
SystemCommandFormatString = "GenFv -i \"%s\" -g %s -o \"%s\" --FvNameGuid %s";
SystemCommand = malloc (
strlen (SystemCommandFormatString) +
strlen (InfFilePath) +
strlen (FfsGuid) +
strlen (OutputFilePath) +
strlen (FvGuidName) +
1
);
if (SystemCommand == NULL) {
Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);
return EFI_ABORTED;
}
sprintf (
SystemCommand,
"GenFv -i \"%s\" -g %s -o \"%s\" --FvNameGuid %s",
InfFilePath, // -i
FfsGuid, // -g
OutputFilePath, // -o
FvGuidName // FvNameGuid
);
if (system (SystemCommand) != EFI_SUCCESS) {
free(SystemCommand);
return EFI_ABORTED;
}
free(SystemCommand);
}
}
return EFI_SUCCESS;
}
/**
Convert a GUID to a string.
@param[in] Guid - Pointer to GUID to print.
@return The string after convert.
**/
CHAR8 *
LibFmmtGuidToStr (
IN EFI_GUID *Guid
)
{
CHAR8 * Buffer;
Buffer = NULL;
if (Guid == NULL) {
printf ("The guid is NULL while convert guid to string! \n");
return NULL;
}
Buffer = (CHAR8 *) malloc (36 + 1);
if (Buffer == NULL) {
printf ("Error while allocate resource! \n");
return NULL;
}
memset (Buffer, '\0', 36 + 1);
sprintf (
Buffer,
"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
Guid->Data1,
Guid->Data2,
Guid->Data3,
Guid->Data4[0],
Guid->Data4[1],
Guid->Data4[2],
Guid->Data4[3],
Guid->Data4[4],
Guid->Data4[5],
Guid->Data4[6],
Guid->Data4[7]
);
return Buffer;
}
/**
Encapsulate an FFS section file to an FFS file.
@param[in] Type Type is one FV file type defined in PI spec, which is one type of EFI_FV_FILETYPE_RAW, EFI_FV_FILETYPE_FREEFORM,
EFI_FV_FILETYPE_SECURITY_CORE, EFI_FV_FILETYPE_PEIM, EFI_FV_FILETYPE_PEI_CORE, EFI_FV_FILETYPE_DXE_CORE,
EFI_FV_FILETYPE_DRIVER, EFI_FV_FILETYPE_APPLICATION, EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER,
EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE. This option is required.
@param[in] InputFilePath Section file will be read into this FFS file. This option is required.
@param[in] OutputFilePath The created PI firmware file name. This option is required.
@param[in] FileGuid FileGuid is the unique identifier for this FFS file. This option is required.
@param[in] Fixed Set fixed attribute in FFS file header to indicate that the file may not be moved from its present location.
@param[in] SectionAlign FileAlign specifies FFS file alignment, which only support the following alignment: 8,16,128,512,1K,4K,32K,64K.
@retval EFI_SUCCESS
**/
EFI_STATUS
LibEncapSectionFileToFFS (
IN UINT8 Type,
IN CHAR8* InputFilePath,
IN CHAR8* OutputFilePath,
IN EFI_GUID FileGuid,
IN BOOLEAN Fixed,
IN CHAR8* SectionAlign
)
{
CHAR8* SystemCommandFormatString;
CHAR8* SystemCommand;
CHAR8* GuidStr;
SystemCommandFormatString = NULL;
SystemCommand = NULL;
GuidStr = NULL;
GuidStr = LibFmmtGuidToStr(&FileGuid);
if (GuidStr == NULL) {
return EFI_ABORTED;
}
//
// -t Type
// -i InputFilePath
// -o OutPutFilePath
// -g FileGuid
// -x Fixed
// -n SectionAlign
//
if (Fixed) {
SystemCommandFormatString = "GenFfs -t %s -i \"%s\" -g %s -x -o \"%s\" -a %s";
SystemCommand = malloc (
strlen (SystemCommandFormatString) +
strlen (mFfsFileType[Type]) +
strlen (InputFilePath) +
strlen (GuidStr) +
strlen (OutputFilePath) +
4 +
1
);
if (SystemCommand == NULL) {
Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);
free (GuidStr);
return EFI_ABORTED;
}
sprintf (
SystemCommand,
"GenFfs -t %s -i \"%s\" -g %s -x -o \"%s\" -a %s",
mFfsFileType[Type], // -t
InputFilePath, // -i
GuidStr, // -g
OutputFilePath, // -o
SectionAlign
);
free (GuidStr);
if (system (SystemCommand) != EFI_SUCCESS) {
free(SystemCommand);
return EFI_ABORTED;
}
free(SystemCommand);
} else {
SystemCommandFormatString = "GenFfs -t %s -i \"%s\" -g %s -o \"%s\" -a %s";
SystemCommand = malloc (
strlen (SystemCommandFormatString) +
strlen (mFfsFileType[Type]) +
strlen (InputFilePath) +
strlen (GuidStr) +
strlen (OutputFilePath) +
4 +
1
);
if (SystemCommand == NULL) {
free (GuidStr);
Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);
return EFI_ABORTED;
}
sprintf (
SystemCommand,
"GenFfs -t %s -i \"%s\" -g %s -o \"%s\" -a %s",
mFfsFileType[Type], // -t
InputFilePath, // -i
GuidStr, // -g
OutputFilePath, // -o
SectionAlign
);
free (GuidStr);
if (system (SystemCommand) != EFI_SUCCESS) {
free(SystemCommand);
return EFI_ABORTED;
}
free(SystemCommand);
}
return EFI_SUCCESS;
}
EFI_STATUS
LibCreateNewFdCopy(
IN CHAR8* OldFd,
IN CHAR8* NewFd
)
{
FILE* NewFdFile;
FILE* OldFdFile;
CHAR8 *NewFdDir;
CHAR8 *OldFdDir;
UINT64 FdLength;
UINT32 Count;
BOOLEAN UseNewDirFlag;
CHAR8 *Buffer;
NewFdFile = NULL;
OldFdFile = NULL;
NewFdDir = NULL;
OldFdDir = NULL;
Count = 0;
UseNewDirFlag = FALSE;
if (OldFd == NULL ||
NewFd == NULL) {
return EFI_INVALID_PARAMETER;
}
NewFdDir = getcwd (NULL, _MAX_PATH);
Count = strlen(NewFdDir);
if (strlen(NewFd) > Count) {
do {
if (NewFdDir[Count-1] == NewFd[Count-1]) {
Count--;
} else {
if (strlen(NewFdDir) + strlen (OS_SEP_STR) + strlen (NewFd) > _MAX_PATH -1) {
return EFI_ABORTED;
}
strncat (NewFdDir,OS_SEP_STR, _MAX_PATH - strlen (NewFdDir) -1);
strncat (NewFdDir,NewFd, _MAX_PATH - strlen (NewFdDir) -1);
UseNewDirFlag = TRUE;
break;
}
} while (Count != 1);
}else {
if (strlen(NewFdDir) + strlen (OS_SEP_STR) + strlen (NewFd) > _MAX_PATH -1) {
return EFI_ABORTED;
}
strncat (NewFdDir,OS_SEP_STR, _MAX_PATH - strlen (NewFdDir) -1);
strncat (NewFdDir,NewFd, _MAX_PATH - strlen (NewFdDir) -1);
UseNewDirFlag = TRUE;
}
if (UseNewDirFlag) {
NewFdFile = fopen (NewFdDir, "wb+");
if (NewFdFile == NULL) {
NewFdFile = fopen (NewFd, "wb+");
}
} else {
NewFdFile = fopen (NewFd, "wb+");
}
// support network path file
if (OldFd[0] == '\\' && OldFd[1] == '\\') {
OldFdFile = fopen (OldFd, "rb");
} else {
UseNewDirFlag = FALSE;
OldFdDir = getcwd (NULL, _MAX_PATH);
Count = strlen(OldFdDir);
if (strlen(OldFd) > Count) {
do {
if (OldFdDir[Count-1] == OldFd[Count-1]) {
Count--;
} else {
if (strlen(OldFdDir) + strlen (OS_SEP_STR) + strlen (OldFd) > _MAX_PATH -1) {
if (NewFdFile != NULL) {
fclose(NewFdFile);
}
return EFI_ABORTED;
}
strncat (OldFdDir,OS_SEP_STR, _MAX_PATH - strlen (OldFdDir) -1);
strncat (OldFdDir,OldFd, _MAX_PATH - strlen (OldFdDir) -1);
UseNewDirFlag = TRUE;
break;
}
} while (Count != 1);
}else {
if (strlen(OldFdDir) + strlen (OS_SEP_STR) + strlen (OldFd) > _MAX_PATH -1) {
if (NewFdFile != NULL) {
fclose(NewFdFile);
}
return EFI_ABORTED;
}
strncat (OldFdDir,OS_SEP_STR, _MAX_PATH - strlen (OldFdDir) -1);
strncat (OldFdDir,OldFd, _MAX_PATH - strlen (OldFdDir) -1);
UseNewDirFlag = TRUE;
}
if (UseNewDirFlag) {
OldFdFile = fopen (OldFdDir, "rb+");
if (OldFdFile == NULL) {
OldFdFile = fopen (OldFd, "rb+");
}
} else {
OldFdFile = fopen (OldFd, "rb+");
}
}
if (NewFdFile == NULL) {
Error ("FMMT", 0, 0003, "error Open FD file", "cannot Create a new FD file.");
if (OldFdFile != NULL) {
fclose (OldFdFile);
}
return EFI_ABORTED;
}
if (OldFdFile == NULL) {
Error ("FMMT", 0, 0003, "error Open FD file", "cannot Create a new FD file.");
if (NewFdFile != NULL) {
fclose (NewFdFile);
}
return EFI_ABORTED;
}
fseek(OldFdFile,0,SEEK_SET);
fseek(OldFdFile,0,SEEK_END);
FdLength = ftell(OldFdFile);
fseek(OldFdFile,0,SEEK_SET);
fseek(NewFdFile,0,SEEK_SET);
Buffer = malloc ((size_t)FdLength);
if (Buffer == NULL) {
fclose(OldFdFile);
fclose(NewFdFile);
return EFI_ABORTED;
}
if (fread (Buffer, 1, (size_t) FdLength, OldFdFile) != (size_t) FdLength) {
Error ("FMMT", 0, 0003, "error reading FD file %s", OldFd);
free (Buffer);
fclose(OldFdFile);
fclose(NewFdFile);
return EFI_ABORTED;
}
if (fwrite (Buffer, 1, (size_t) FdLength, NewFdFile) != (size_t) FdLength) {
Error ("FMMT", 0, 0004, "error writing FD file", "cannot Create a new FD file.");
free (Buffer);
fclose(OldFdFile);
fclose(NewFdFile);
return EFI_ABORTED;
}
free (Buffer);
fclose(OldFdFile);
fclose (NewFdFile);
return EFI_SUCCESS;
}
/**
This function will assemble the filename, directory and extend and return the combined string.
Like FileName = file1, Dir = c:\temp extend = txt, the output string will be:
c:\temp\file1.txt.
@param[in]
@param[in]
@param[in]
@retrun A string contain all the input information.
**/
CHAR8 *
LibFilenameStrExtended (
IN CHAR8 *FileName,
IN CHAR8 *Dir,
IN CHAR8 *Extend
)
{
CHAR8 *RetStr;
RetStr = NULL;
if (FileName == NULL) {
return NULL;
}
if (Dir == NULL || Extend == NULL) {
return FileName;
}
RetStr = (CHAR8 *) malloc (strlen (FileName) +
strlen (Dir) +
strlen (Extend) +
strlen ("%s%s.%s") +
1);
if (RetStr == NULL) {
Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);
return NULL;
}
memset (RetStr, '\0', (strlen (FileName) + strlen (Dir) + strlen (Extend) + strlen ("%s%s.%s") + 1));
sprintf (RetStr, "%s%s.%s", Dir, FileName, Extend);
return RetStr;
}
/**
Delete a directory and files in it.
@param[in] DirName Name of the directory need to be deleted.
@return EFI_INVALID_PARAMETER
@return EFI_SUCCESS
**/
EFI_STATUS
LibRmDir (
IN CHAR8* DirName
)
{
CHAR8* SystemCommand;
SystemCommand = NULL;
if (DirName == NULL) {
return EFI_INVALID_PARAMETER;
}
if (access (DirName, 0) == -1){
return EFI_SUCCESS;
}
//
// Delete a directory and files in it.
//
SystemCommand = malloc (
strlen (RMDIR_STR) +
strlen (DirName) +
1
);
if (SystemCommand == NULL) {
Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);
return EFI_ABORTED;
}
sprintf (
SystemCommand,
RMDIR_STR,
DirName
);
if (system (SystemCommand) != EFI_SUCCESS) {
free(SystemCommand);
return EFI_ABORTED;
}
free(SystemCommand);
return EFI_SUCCESS;
}
EFI_STATUS
LibGenExtFile(
CONST EFI_FIRMWARE_VOLUME_EXT_HEADER *ExtPtr,
FILE *InfFile
)
{
CHAR8 *TempDir;
FILE *ExtFile;
CHAR8 OutputExtFile[_MAX_PATH];
CHAR8 Line[512];
size_t Len;
TempDir = NULL;
TempDir = getcwd(NULL, _MAX_PATH);
if (strlen (TempDir) + strlen(OS_SEP_STR) + strlen (TEMP_DIR_NAME) > _MAX_PATH - 1) {
Error("FMMT", 0, 1001, "The directory is too long.", "");
return EFI_ABORTED;
}
strncat (TempDir, OS_SEP_STR, _MAX_PATH - strlen (TempDir) -1);
strncat (TempDir, TEMP_DIR_NAME, _MAX_PATH - strlen (TempDir) -1);
mkdir(TempDir, S_IRWXU | S_IRWXG | S_IRWXO);
sprintf(
Line,
"%c%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X%d.ext",
OS_SEP,
(unsigned)ExtPtr->FvName.Data1,
ExtPtr->FvName.Data2,
ExtPtr->FvName.Data3,
ExtPtr->FvName.Data4[0],
ExtPtr->FvName.Data4[1],
ExtPtr->FvName.Data4[2],
ExtPtr->FvName.Data4[3],
ExtPtr->FvName.Data4[4],
ExtPtr->FvName.Data4[5],
ExtPtr->FvName.Data4[6],
ExtPtr->FvName.Data4[7],
ExtPtr->ExtHeaderSize
);
if (strlen (TempDir) + strlen (Line) > _MAX_PATH - 1) {
Error("FMMT", 0, 1001, "The directory is too long.", "");
return EFI_ABORTED;
}
strncpy (OutputExtFile, TempDir, _MAX_PATH - 1);
OutputExtFile[_MAX_PATH - 1] = 0;
strncat (OutputExtFile, Line, _MAX_PATH - strlen (OutputExtFile) - 1);
ExtFile = fopen(OutputExtFile, "wb+");
if (ExtFile == NULL) {
return EFI_ABORTED;
}
if (fwrite(ExtPtr, 1, ExtPtr->ExtHeaderSize, ExtFile) != ExtPtr->ExtHeaderSize) {
fclose(ExtFile);
return EFI_ABORTED;
}
fclose(ExtFile);
strcpy (Line, "EFI_FV_EXT_HEADER_FILE_NAME = ");
if (strlen (Line) + strlen (OutputExtFile) + 1 > sizeof(Line) / sizeof (CHAR8) - 1) {
Error("FMMT", 0, 1001, "The directory is too long.", "");
return EFI_ABORTED;
}
strncat (Line, OutputExtFile, sizeof(Line) / sizeof (CHAR8) - strlen (Line) - 1);
strncat (Line, "\n", sizeof(Line) / sizeof (CHAR8) - strlen (Line) - 1);
Len = strlen(Line);
if (fwrite(Line, 1, Len, InfFile) != Len) {
return EFI_ABORTED;
}
return EFI_SUCCESS;
}
/**
Delete a file.
@param[in] FileName Name of the file need to be deleted.
@return EFI_INVALID_PARAMETER
@return EFI_SUCCESS
**/
EFI_STATUS
LibFmmtDeleteFile(
IN CHAR8 *FileName
)
{
CHAR8* SystemCommand;
CHAR8 *TemDir;
SystemCommand = NULL;
TemDir = NULL;
if (FileName == NULL) {
return EFI_INVALID_PARAMETER;
}
// if the FileName is not in TemDir, we don't need to delete.
TemDir = getcwd (NULL, _MAX_PATH);
if (*(TemDir + strlen(TemDir) - 1) == OS_SEP) {
*(TemDir + strlen(TemDir) - 1) = '\0';
}
if (strlen (TemDir) + strlen (OS_SEP_STR) + strlen (TEMP_DIR_NAME) > _MAX_PATH - 1) {
Error (NULL, 0, 2000, "Path: The current path is too long.", NULL);
return EFI_ABORTED;
}
strncat (TemDir, OS_SEP_STR, _MAX_PATH - strlen (TemDir) - 1);
strncat (TemDir, TEMP_DIR_NAME, _MAX_PATH - strlen (TemDir) - 1);
if (strstr(FileName, TemDir) == NULL) {
return EFI_SUCCESS;
}
//
// Delete a file
//
SystemCommand = malloc (
strlen (DEL_STR) +
strlen (FileName) +
1
);
if (SystemCommand == NULL) {
Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);
return EFI_ABORTED;
}
sprintf (
SystemCommand,
DEL_STR,
FileName
);
if (system (SystemCommand) != EFI_SUCCESS) {
free(SystemCommand);
return EFI_ABORTED;
}
free(SystemCommand);
return EFI_SUCCESS;
}
/**
Free the whole Fd data structure.
@param[in] Fd The pointer point to the Fd data structure.
**/
VOID
LibFmmtFreeFd (
FIRMWARE_DEVICE *Fd
)
{
FV_INFORMATION *CurrentFv;
FV_INFORMATION *TempFv;
ENCAP_INFO_DATA *EncapData1;
ENCAP_INFO_DATA *EncapData2;
CurrentFv = NULL;
TempFv = NULL;
EncapData1 = NULL;
EncapData2 = NULL;
if (Fd == NULL) {
return;
}
CurrentFv = Fd->Fv;
do {
TempFv = CurrentFv;
CurrentFv = CurrentFv->FvNext;
free (TempFv->FvHeader);
if (TempFv->FvExtHeader != NULL) {
free (TempFv->FvExtHeader);
}
if (TempFv->FvUiName) {
free(TempFv->FvUiName);
}
//
// Free encapsulate data;
//
EncapData1 = TempFv->EncapData;
while (EncapData1 != NULL) {
EncapData2 = EncapData1;
EncapData1 = EncapData1->NextNode;
if (EncapData2->Data != NULL) {
free (EncapData2->Data);
}
if (EncapData2->FvExtHeader != NULL) {
free(EncapData2->FvExtHeader);
}
free (EncapData2);
EncapData2 = NULL;
}
EncapData1 = NULL;
free (TempFv);
TempFv = NULL;
} while (CurrentFv != NULL);
CurrentFv = NULL;
free (Fd);
Fd = NULL;
return;
}
/**
Generate the compressed section with specific type.
Type could be EFI_STANDARD_COMPRESSION or EFI_NOT_COMPRESSED
@param[in] InputFileName File name of the raw data.
@param[in] OutPutFileName File name of the sectioned data.
@param[in] CompressionType The compression type.
@return EFI_INVALID_PARAMETER
@return EFI_ABORTED
@return EFI_OUT_OF_RESOURCES
@return EFI_SUCCESS
**/
EFI_STATUS
LibGenCompressedSection (
CHAR8 *InputFileName,
CHAR8 *OutPutFileName,
UINT8 CompressionType
)
{
//FILE *UnCompressFile;
//FILE *CompressedFile;
//VOID *UnCompressedBuffer;
//VOID *CompressedBuffer;
//UINT32 UnCompressedSize;
//UINT32 CompressedSize;
//CHAR8 *TempName;
//CHAR8 *TemDir;
//EFI_STATUS Status;
//UnCompressFile = NULL;
//CompressedFile = NULL;
//UnCompressedBuffer = NULL;
//CompressedBuffer = NULL;
//TempName = NULL;
//TemDir = NULL;
//UnCompressedSize = 0;
//CompressedSize = 0;
if ( InputFileName == NULL ||
OutPutFileName == NULL) {
printf ("Error while generate compressed section!\n");
return EFI_INVALID_PARAMETER;
}
if (CompressionType == EFI_STANDARD_COMPRESSION) {
/*
UnCompressFile = fopen (InputFileName, "rb");
if (UnCompressFile == NULL) {
printf ("Error while open file %s \n", InputFileName);
return EFI_ABORTED;
}
TemDir = _getcwd (NULL, _MAX_PATH);
sprintf(TemDir, "%s\\%s", TemDir, TEMP_DIR_NAME);
TempName= LibFilenameStrExtended (strrchr(CloneString (tmpnam (NULL)),'\\'), TemDir, "comp");
CompressedFile = fopen (TempName, "wb+");
if (CompressedFile == NULL) {
printf ("Error while open file %s \n", TempName);
return EFI_ABORTED;
}
//
// Get the original file size;
//
fseek(UnCompressFile,0,SEEK_SET);
fseek(UnCompressFile,0,SEEK_END);
UnCompressedSize = ftell(UnCompressFile);
fseek(UnCompressFile,0,SEEK_SET);
UnCompressedBuffer = malloc (UnCompressedSize);
if (UnCompressedBuffer == NULL) {
printf("Error while allocate memory! \n");
return EFI_OUT_OF_RESOURCES;
}
CompressedBuffer = malloc (UnCompressedSize);
if (CompressedBuffer == NULL) {
printf("Error while allocate memory! \n");
return EFI_OUT_OF_RESOURCES;
}
if (fread (UnCompressedBuffer, 1, (size_t) UnCompressedSize, UnCompressFile) == (size_t) UnCompressedSize) {
CompressedSize = UnCompressedSize;
Status = EfiCompress ( UnCompressedBuffer,
UnCompressedSize,
CompressedBuffer,
&CompressedSize);
if (EFI_ERROR(Status)) {
printf("Error while do compress operation! \n");
return EFI_ABORTED;
}
if (CompressedSize > UnCompressedSize) {
printf("Error while do compress operation! \n");
return EFI_ABORTED;
}
} else {
printf("Error while reading file %s! \n", InputFileName);
return EFI_ABORTED;
}
//
// Write the compressed data into output file
//
if (fwrite (CompressedBuffer, 1, (size_t) CompressedSize, CompressedFile) != (size_t) CompressedSize) {
Error ("FMMT", 0, 0004, "error writing %s file", OutPutFileName);
fclose(UnCompressFile);
fclose (CompressedFile);
return EFI_ABORTED;
}
fclose(UnCompressFile);
fclose (CompressedFile);
*/
//
// Call GenSec tool to generate the compressed section.
//
LibCreateFfsSection(NULL, InputFileName, NULL, EFI_SECTION_COMPRESSION, OutPutFileName, NULL, NULL, NULL, 0, 0, "PI_STD");
} else if (CompressionType == EFI_NOT_COMPRESSED) {
LibCreateFfsSection(NULL, InputFileName, NULL, EFI_SECTION_COMPRESSION, OutPutFileName, NULL, NULL, NULL, 0, 0, "PI_NONE");
} else {
printf ("Error while generate compressed section, unknown compression type! \n");
return EFI_INVALID_PARAMETER;
}
return EFI_SUCCESS;
}
EFI_STATUS
LibEncapNewFvFile(
IN FV_INFORMATION *FvInFd,
IN CHAR8 *TemDir,
IN ENCAP_INFO_DATA *CurrentEncapData,
IN UINT32 Level_Break,
OUT FFS_INFORMATION **OutputFile
)
{
EFI_STATUS Status;
UINT32 ParentType;
UINT8 ParentLevel;
UINT32 Type;
UINT8 Level;
CHAR8 *InfFileName;
FILE *InfFile;
ENCAP_INFO_DATA *LocalEncapData;
ENCAP_INFO_DATA *LocalEncapDataTemp;
ENCAP_INFO_DATA *LocalEncapDataNext;
BOOLEAN FfsFoundFlag;
UINT32 Index;
UINT32 OuterIndex;
CHAR8 *ExtractionTool;
BOOLEAN IsLastLevelFfs;
BOOLEAN IsLeafFlagIgnore;
BOOLEAN FirstInFlag;
BOOLEAN OutputFileNameListFlag;
CHAR8 *InputFileName;
CHAR8 *OutputFileName;
FFS_INFORMATION *OutputFileNameList;
FFS_INFORMATION *ChildFileNameList;
FFS_INFORMATION *NewFileNameList;
CHAR8 *FvGuidName;
UINT16 GuidAttributes;
UINT16 GuidDataOffset;
BOOLEAN IsRootFv;
BOOLEAN IsLargeFile;
UINT32 EncapFvStart;
UINT32 EncapFvIndex;
CHAR8 *TmpFileName;
FILE *TmpFile;
FILE *InputFile;
FILE *OutFile;
UINT32 InputFileSize;
UINT32 OutputFileSize;
UINT32 LargeFileSize;
UINT8 *Buffer = NULL;
UINT8 SectionHeader[4] = { 0x00, 0x00, 0x00, 0x00 };
UINT32 Id;
UINT32 SubFvId;
UINT32 header;
UINT8 AlignN;
UINT8 AlignV[1] = {0xFF};
AlignN = 0;
Id = 0;
InputFileSize = 0;
EncapFvIndex = 0;
Index = 0;
OuterIndex = 0;
ParentType = 0;
ParentLevel = 0;
Type = 0;
Level = 0;
SubFvId = 0;
FfsFoundFlag = FALSE;
LocalEncapDataTemp = NULL;
LocalEncapDataNext = NULL;
ExtractionTool = NULL;
InputFileName = NULL;
OutputFileName = NULL;
IsLastLevelFfs = TRUE;
IsLeafFlagIgnore = FALSE;
FirstInFlag = TRUE;
FvGuidName = NULL;
OutputFileNameListFlag = TRUE;
IsLargeFile = FALSE;
OutputFileSize = 0;
LargeFileSize = 0x1000000;
OutputFileNameList = (FFS_INFORMATION *)malloc(sizeof(FV_INFORMATION));
if (OutputFileNameList == NULL) {
Error ("FMMT", 0, 0004, "Out of resource, memory allocation failed! \n", "");
return EFI_OUT_OF_RESOURCES;
}
OutputFileNameList->FFSName = NULL;
OutputFileNameList->InFvId = 0;
OutputFileNameList->IsFFS = FALSE;
OutputFileNameList->ParentLevel = 0;
OutputFileNameList->Next = NULL;
OutputFileNameList->UiNameSize = 0;
OutputFileNameList->Depex = NULL;
OutputFileNameList->DepexLen = 0;
OutputFileNameList->FfsFoundFlag = FALSE;
ChildFileNameList = (FFS_INFORMATION *)malloc(sizeof(FV_INFORMATION));
if (ChildFileNameList == NULL) {
Error ("FMMT", 0, 0004, "Out of resource, memory allocation failed! \n", "");
return EFI_OUT_OF_RESOURCES;
}
ChildFileNameList->FFSName = NULL;
ChildFileNameList->InFvId = 0;
ChildFileNameList->ParentLevel = 0;
ChildFileNameList->Next = NULL;
ChildFileNameList->IsFFS = FALSE;
ChildFileNameList->UiNameSize = 0;
ChildFileNameList->Depex = NULL;
ChildFileNameList->DepexLen = 0;
ChildFileNameList->FfsFoundFlag = FALSE;
//
// Encapsulate from the lowest FFS file level.
//
LocalEncapData = CurrentEncapData;
if (LocalEncapData == NULL) {
LocalEncapData = FvInFd->EncapData;
}
Level = LocalEncapData->Level;
Type = LocalEncapData->Type;
if (CurrentEncapData == NULL) {
LocalEncapData = FvInFd->EncapData;
while (LocalEncapData != NULL) {
if (LocalEncapData->Type == FMMT_ENCAP_TREE_FFS) {
LocalEncapDataTemp = LocalEncapData->RightNode;
while (LocalEncapDataTemp != NULL) {
LocalEncapDataNext = LocalEncapDataTemp->NextNode;
if (LocalEncapDataNext != NULL && LocalEncapDataNext->NextNode != NULL) {
LibEncapNewFvFile(FvInFd, TemDir, LocalEncapDataTemp, 1, &ChildFileNameList);
ChildFileNameList->ParentLevel = LocalEncapDataTemp->Level -1;
if (FvInFd->ChildFvFFS == NULL) {
FvInFd->ChildFvFFS = ChildFileNameList;
} else {
NewFileNameList = FvInFd->ChildFvFFS;
while (NewFileNameList->Next != NULL) {
NewFileNameList = NewFileNameList->Next;
}
NewFileNameList->Next = ChildFileNameList;
}
}
LocalEncapDataTemp = LocalEncapDataTemp->RightNode;
}
}
if (LocalEncapData->Level > Level) {
if (LocalEncapData->Type == FMMT_ENCAP_TREE_FFS) {
ParentLevel = Level;
ParentType = Type;
}
Level = LocalEncapData->Level;
Type = LocalEncapData->Type;
}
LocalEncapData = LocalEncapData->NextNode;
}
} else {
LocalEncapData = CurrentEncapData;
while (LocalEncapData != NULL) {
if (LocalEncapData->Level > Level) {
if (LocalEncapData->Type == FMMT_ENCAP_TREE_FFS) {
ParentLevel = Level;
ParentType = Type;
}
Level = LocalEncapData->Level;
Type = LocalEncapData->Type;
}
LocalEncapData = LocalEncapData->NextNode;
}
}
do {
switch (ParentType) {
case FMMT_ENCAP_TREE_FV:
OutputFileNameListFlag = TRUE;
EncapFvStart = 0;
for(OuterIndex=0;OutputFileNameListFlag;OuterIndex++){
//
// Generate FV.inf attributes.
//
InfFileName = LibFilenameStrExtended (strrchr(GenTempFile (),OS_SEP), TemDir, "inf");
FirstInFlag = TRUE;
InfFile = fopen (InfFileName, "wt+");
if (InfFile == NULL) {
Error ("FMMT", 0, 0004, "Could not open inf file %s to store FV information! \n", "");
free (OutputFileNameList);
free (ChildFileNameList);
return EFI_ABORTED;
}
if (CurrentEncapData == NULL) {
LocalEncapData = FvInFd->EncapData;
} else {
LocalEncapData = CurrentEncapData;
}
while (LocalEncapData->NextNode != NULL) {
if (LocalEncapData->Level == ParentLevel) {
break;
}
LocalEncapData = LocalEncapData->NextNode;
}
if (((EFI_FIRMWARE_VOLUME_HEADER *)(LocalEncapData->Data))->ExtHeaderOffset != 0) {
//
// FV GUID Name memory allocation
//
FvGuidName = (CHAR8 *) malloc (255);
if (FvGuidName == NULL) {
Error ("FMMT", 0, 0004, "Out of resource, memory allocation failed! \n", "");
fclose (InfFile);
free (OutputFileNameList);
free (ChildFileNameList);
return EFI_ABORTED;
}
memset(FvGuidName, '\0', 255);
sprintf(
FvGuidName,
"%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X\n",
LocalEncapData->FvExtHeader->FvName.Data1,
LocalEncapData->FvExtHeader->FvName.Data2,
LocalEncapData->FvExtHeader->FvName.Data3,
LocalEncapData->FvExtHeader->FvName.Data4[0],
LocalEncapData->FvExtHeader->FvName.Data4[1],
LocalEncapData->FvExtHeader->FvName.Data4[2],
LocalEncapData->FvExtHeader->FvName.Data4[3],
LocalEncapData->FvExtHeader->FvName.Data4[4],
LocalEncapData->FvExtHeader->FvName.Data4[5],
LocalEncapData->FvExtHeader->FvName.Data4[6],
LocalEncapData->FvExtHeader->FvName.Data4[7]
);
} else {
FvGuidName = NULL;
}
if (ParentLevel == 1) {
Status = LibFvHeaderOptionToStr((EFI_FIRMWARE_VOLUME_HEADER *)LocalEncapData->Data, InfFile, TRUE);
} else {
Status = LibFvHeaderOptionToStr((EFI_FIRMWARE_VOLUME_HEADER *)LocalEncapData->Data, InfFile, FALSE);
}
if (EFI_ERROR (Status)) {
Error ("FMMT", 0, 0004, "error while encapsulate FD Image", "generate FV INF file [Options] section failed.");
fclose (InfFile);
free (OutputFileNameList);
free (ChildFileNameList);
return Status;
}
Status = LibFvHeaderAttributeToStr(((EFI_FIRMWARE_VOLUME_HEADER *)LocalEncapData->Data)->Attributes, InfFile);
if (EFI_ERROR (Status)) {
Error ("FMMT", 0, 0004, "error while encapsulate FD Image", "Generate FV header attribute failed");
fclose (InfFile);
free (OutputFileNameList);
free (ChildFileNameList);
return Status;
}
if (LocalEncapData->FvExtHeader != NULL) {
Status = LibGenExtFile(LocalEncapData->FvExtHeader, InfFile);
if (EFI_ERROR(Status)) {
Error("FMMT", 0, 0004, "error while encapsulate FD Image", "Generate FV EXT header failed");
fclose (InfFile);
free (OutputFileNameList);
free (ChildFileNameList);
return Status;
}
FvGuidName = NULL;
}
if (CurrentEncapData != NULL) {
for (Index = 0; Index <= FvInFd->FfsNumbers; Index++) {
if ((memcmp(&FvInFd->FfsAttuibutes[Index].GuidName, &(CurrentEncapData->FvExtHeader->FvName), sizeof(EFI_GUID)) == 0)) {
SubFvId = Index;
break;
}
}
}
//
// Found FFSs from Fv structure.
//
FfsFoundFlag = FALSE;
IsRootFv = FALSE;
for (Index=0; Index <= FvInFd->FfsNumbers; Index++) {
if (OutputFileNameList != NULL && OutputFileNameList->FFSName != NULL && OutputFileNameList->IsFFS == FALSE){
break;
}
if (OutputFileNameList != NULL && OutputFileNameList->FFSName != NULL && OutputFileNameList->IsFFS == TRUE){
if (Index == EncapFvIndex) {
if (FirstInFlag) {
Status = LibAddFfsFileToFvInf (OutputFileNameList->FFSName, InfFile, TRUE);
FirstInFlag = FALSE;
} else {
Status = LibAddFfsFileToFvInf (OutputFileNameList->FFSName, InfFile, FALSE);
}
if (EFI_ERROR (Status)) {
Error ("FMMT", 0, 0004, "error while encapsulate FD Image", "Generate FV inf file [files] section failed!");
fclose (InfFile);
free (OutputFileNameList);
free (ChildFileNameList);
return Status;
}
}
}
NewFileNameList = FvInFd->ChildFvFFS;
while (NewFileNameList != NULL && NewFileNameList -> FFSName != NULL) {
if (NewFileNameList -> ParentLevel == ParentLevel && Index == NewFileNameList->InFvId && NewFileNameList->FfsFoundFlag==TRUE) {
if (FirstInFlag) {
Status = LibAddFfsFileToFvInf (NewFileNameList->FFSName, InfFile, TRUE);
FirstInFlag = FALSE;
} else {
Status = LibAddFfsFileToFvInf (NewFileNameList->FFSName, InfFile, FALSE);
}
if (EFI_ERROR (Status)) {
Error ("FMMT", 0, 0004, "error while encapsulate FD Image", "Generate FV inf file [files] section failed!");
fclose (InfFile);
free (OutputFileNameList);
free (ChildFileNameList);
return Status;
}
}
NewFileNameList = NewFileNameList->Next;
}
if (FvInFd->FfsAttuibutes[Index].IsHandle==TRUE) {
continue;
}
if (SubFvId > 0 && Index < SubFvId) {
continue;
}
//
// For the last level FFS, the level below FFSs we should not care the IsLeaf Flag.
//
if (IsLastLevelFfs) {
IsLeafFlagIgnore = TRUE;
} else {
IsLeafFlagIgnore = FvInFd->FfsAttuibutes[Index].IsLeaf;
}
if (FvInFd->FfsAttuibutes[Index].Level >= ParentLevel + 1 && IsLeafFlagIgnore) {
if (FirstInFlag) {
if (FvInFd->FfsAttuibutes[Index].Level < 0xFF) {
FfsFoundFlag = TRUE;
Status = LibAddFfsFileToFvInf (FvInFd->FfsAttuibutes[Index].FfsName, InfFile, TRUE);
FirstInFlag = FALSE;
FvInFd->FfsAttuibutes[Index].IsHandle=TRUE;
EncapFvStart = Index;
}
if (EFI_ERROR (Status)) {
Error ("FMMT", 0, 0004, "error while encapsulate FD Image", "Generate FV inf file [files] section failed!");
fclose (InfFile);
free (OutputFileNameList);
free (ChildFileNameList);
return Status;
}
if (Index == 0) {
// Root FV need to include all FFS files.
IsRootFv = TRUE;
}
} else {
if (FvInFd->FfsAttuibutes[Index].Level < 0xFF) {
FfsFoundFlag = TRUE;
Status = LibAddFfsFileToFvInf (FvInFd->FfsAttuibutes[Index].FfsName, InfFile, FALSE);
FvInFd->FfsAttuibutes[Index].IsHandle=TRUE;
}
if (EFI_ERROR (Status)) {
Error ("FMMT", 0, 0004, "error while encapsulate FD Image", "Generate FV inf file [files] section failed!");
fclose (InfFile);
free (OutputFileNameList);
free (ChildFileNameList);
return Status;
}
if (Index == 0) {
// Root FV need to include all FFS files.
IsRootFv = TRUE;
}
}
//avoid a FV contain too many ffs files
if ((!IsRootFv) && (FvInFd->FfsAttuibutes[Index].FvLevel <= FvInFd->MulFvLevel) && (FvInFd->FfsAttuibutes[Index+1].FvLevel <= FvInFd->MulFvLevel) &&
(FvInFd->FfsAttuibutes[Index].FvLevel != FvInFd->FfsAttuibutes[Index+1].FvLevel) && (ParentLevel != 1) && (FvInFd->FfsAttuibutes[Index].Level != FvInFd->FfsAttuibutes[Index+1].Level) &&
FvInFd->FfsAttuibutes[Index].Level != 0xFF && FvInFd->FfsAttuibutes[Index+1].Level != 0xFF && FvInFd->FfsAttuibutes[Index+1].Level != 0x0){
FvInFd->FfsAttuibutes[Index].Level = 0;
break;
}else{
if (FvInFd->FfsAttuibutes[Index].Level != 0xFF){
FvInFd->FfsAttuibutes[Index].Level = 0;
}
}
}
}
// The Fv may has multiple level (> 2), when it is in the FvLevel == 2, we set the IsLastLevelFfs Flag
if (Index <=FvInFd->FfsNumbers && FvInFd->FfsAttuibutes[Index].FvLevel <= FvInFd->MulFvLevel) {
if (FvInFd->FfsAttuibutes[Index].FvLevel == 2) {
IsLastLevelFfs = FALSE;
}
}
if (!FfsFoundFlag){
OutputFileNameListFlag = FALSE;
if (OuterIndex > 0){
fclose (InfFile);
break;
}
}
//
// Create FV
//
fclose (InfFile);
EncapFvIndex = EncapFvStart;
OutputFileName= LibFilenameStrExtended (strrchr(GenTempFile (), OS_SEP), TemDir, "FV");
Status = LibEncapsulateFfsToFv (InfFileName, NULL, OutputFileName, FvGuidName, IsLargeFile);
if (EFI_ERROR (Status)) {
Error ("FMMT", 0, 0004, "error while encapsulate FD Image", "Generate FV failed!");
free (OutputFileNameList);
free (ChildFileNameList);
return Status;
}
OutputFileNameList->FFSName = (char *)malloc(strlen(OutputFileName)+1);
if (OutputFileNameList->FFSName == NULL) {
Error ("FMMT", 0, 0004, "Out of resource, memory allocation failed! \n", "");
return EFI_OUT_OF_RESOURCES;
}
memcpy((char *)OutputFileNameList->FFSName, (char *)OutputFileName, strlen(OutputFileName)+1);
if (CurrentEncapData != NULL) {
OutputFileNameList->InFvId = EncapFvIndex;
if (EncapFvIndex > 0) {
memcpy(OutputFileNameList->UiName,FvInFd->FfsAttuibutes[EncapFvIndex - 1].UiName, FvInFd->FfsAttuibutes[EncapFvIndex - 1].UiNameSize);
OutputFileNameList->UiNameSize = FvInFd->FfsAttuibutes[EncapFvIndex - 1].UiNameSize;
OutputFileNameList->Depex = FvInFd->FfsAttuibutes[EncapFvIndex - 1].Depex;
OutputFileNameList->DepexLen = FvInFd->FfsAttuibutes[EncapFvIndex - 1].DepexLen;
OutputFileNameList->FfsFoundFlag = FfsFoundFlag;
}
}
}
break;
case FMMT_ENCAP_TREE_FFS:
while(OutputFileNameList!= NULL && OutputFileNameList->FFSName != NULL){
InputFileName = OutputFileNameList->FFSName;
OutputFileName= LibFilenameStrExtended (strrchr(GenTempFile (), OS_SEP), TemDir, "ffs");
LocalEncapData = CurrentEncapData;
if (LocalEncapData == NULL) {
LocalEncapData = FvInFd->EncapData;
}
while (LocalEncapData->NextNode != NULL) {
if (LocalEncapData->Level == ParentLevel) {
for(;LocalEncapData->NextNode != NULL;) {
if(LocalEncapData->FvExtHeader != NULL) {
break;
}
LocalEncapData = LocalEncapData->NextNode;
}
break;
}
LocalEncapData = LocalEncapData->NextNode;
}
if (LocalEncapData->FvExtHeader == NULL) {
Error ("FMMT", 0, 0004, "error while encapsulate FD Image", "Generate FFS file failed!");
free (OutputFileNameList);
free (ChildFileNameList);
return EFI_ABORTED;
}
if (OutputFileNameList->UiNameSize > 0) {
TmpFileName = LibFilenameStrExtended(strrchr(GenTempFile (), OS_SEP), TemDir, "tmp");
TmpFile = fopen(TmpFileName, "wb+");
if (TmpFile == NULL) {
Error("FMMT", 0, 0004, "Could not open tmp file %s to store UI section information! \n", "");
free (OutputFileNameList);
free (ChildFileNameList);
return EFI_ABORTED;
}
header = (OutputFileNameList->UiNameSize+4) | (EFI_SECTION_USER_INTERFACE << 24);
Index = 0;
while (header) {
SectionHeader[Index] = header % 0x100;
header /= 0x100;
Index ++;
}
InputFile = fopen(InputFileName, "rb+");
if (InputFile == NULL) {
Error("FMMT", 0, 0004, "Could not open input file %s! \n", "");
fclose(TmpFile);
free (OutputFileNameList);
free (ChildFileNameList);
return EFI_ABORTED;
}
fseek(InputFile, 0, SEEK_SET);
fseek(InputFile, 0, SEEK_END);
InputFileSize = ftell(InputFile);
fseek(InputFile, 0, SEEK_SET);
Buffer = malloc(InputFileSize+OutputFileNameList->UiNameSize+4);
memcpy(Buffer, (CHAR16 *)SectionHeader, 4);
memcpy(Buffer + 4, (CHAR16 *)(OutputFileNameList->UiName), OutputFileNameList->UiNameSize);
if (fread(Buffer+4+OutputFileNameList->UiNameSize, 1, InputFileSize, InputFile) != InputFileSize) {
Error("FMMT", 0, 0004, "Could not open sec file %s to add UI section information! \n", "");
fclose(TmpFile);
fclose(InputFile);
free(Buffer);
free (OutputFileNameList);
free (ChildFileNameList);
return EFI_ABORTED;
}
fwrite(Buffer, 1, InputFileSize + OutputFileNameList->UiNameSize + 4, TmpFile);
free(Buffer);
fclose(TmpFile);
fclose(InputFile);
InputFileName = TmpFileName;
}
if (OutputFileNameList->DepexLen > 0) {
TmpFileName = LibFilenameStrExtended(strrchr(GenTempFile (), OS_SEP), TemDir, "tmp");
TmpFile = fopen(TmpFileName, "wb+");
if (TmpFile == NULL) {
Error("FMMT", 0, 0004, "Could not open tmp file %s to store Depex section information! \n", "");
free (OutputFileNameList);
free (ChildFileNameList);
return EFI_ABORTED;
}
InputFile = fopen(InputFileName, "rb+");
if (InputFile == NULL) {
Error("FMMT", 0, 0004, "Could not open input file %s! \n", "");
fclose(TmpFile);
free (OutputFileNameList);
free (ChildFileNameList);
return EFI_ABORTED;
}
fseek(InputFile, 0, SEEK_SET);
fseek(InputFile, 0, SEEK_END);
InputFileSize = ftell(InputFile);
fseek(InputFile, 0, SEEK_SET);
// make sure the section is 4 byte align
if (OutputFileNameList->DepexLen % 4 != 0) {
AlignN = 4 - OutputFileNameList->DepexLen % 4;
}
Buffer = malloc(InputFileSize + OutputFileNameList->DepexLen + AlignN);
memcpy(Buffer, OutputFileNameList->Depex, OutputFileNameList->DepexLen);
if (AlignN != 0) {
for (Index = 0; Index < AlignN; Index ++) {
memcpy(Buffer + OutputFileNameList->DepexLen + Index, AlignV, 1);
}
}
if (fread(Buffer + OutputFileNameList->DepexLen + AlignN, 1, InputFileSize, InputFile) != InputFileSize) {
Error("FMMT", 0, 0004, "Could not open sec file %s to add Depex section information! \n", "");
fclose(TmpFile);
fclose(InputFile);
free(Buffer);
free (OutputFileNameList);
free (ChildFileNameList);
return EFI_ABORTED;
}
fwrite(Buffer, 1, InputFileSize + OutputFileNameList->DepexLen + AlignN, TmpFile);
free(Buffer);
fclose(TmpFile);
fclose(InputFile);
InputFileName = TmpFileName;
}
for (Id = FvInFd->FfsNumbers; Id <= FvInFd->FfsNumbers; Id--) {
if ((memcmp(&FvInFd->FfsAttuibutes[Id].GuidName, &(LocalEncapData->FvExtHeader->FvName), sizeof(EFI_GUID)) == 0)){
if (access(FvInFd->FfsAttuibutes[Id].FfsName, 0) != -1) {
Status = LibFmmtDeleteFile(FvInFd->FfsAttuibutes[Id].FfsName);
if (EFI_ERROR(Status)) {
Error("FMMT", 0, 0004, "error while encapsulate FD Image", "Delete the specified file failed!");
free (OutputFileNameList);
free (ChildFileNameList);
return Status;
}
memset(FvInFd->FfsAttuibutes[Id].FfsName, '\0', _MAX_PATH);
FvInFd->FfsAttuibutes[Id].Level = 0xFF;
break;
}
}
}
if (LocalEncapData->NextNode != NULL) {
LocalEncapDataTemp = LocalEncapData->NextNode;
if ((LocalEncapDataTemp->Type == FMMT_ENCAP_TREE_GUIDED_SECTION) || (LocalEncapDataTemp->Type == FMMT_ENCAP_TREE_COMPRESS_SECTION)) {
Status = LibEncapSectionFileToFFS(EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE, InputFileName, OutputFileName, LocalEncapData->FvExtHeader->FvName, FALSE, "1");
}
else{
Status = LibEncapSectionFileToFFS(EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE, InputFileName, OutputFileName, LocalEncapData->FvExtHeader->FvName, FALSE, FvInFd->AlignmentStr);
}
}
else{
Status = LibEncapSectionFileToFFS(EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE, InputFileName, OutputFileName, LocalEncapData->FvExtHeader->FvName, FALSE, FvInFd->AlignmentStr);
}
if (EFI_ERROR (Status)) {
Error ("FMMT", 0, 0004, "error while encapsulate FD Image", "Generate FFS file failed!");
free (OutputFileNameList);
free (ChildFileNameList);
return Status;
}
free(LocalEncapData->FvExtHeader);
LocalEncapData->FvExtHeader = NULL;
OutputFileNameList->FFSName = (char *)malloc(strlen(OutputFileName)+1);
if (OutputFileNameList->FFSName == NULL) {
Error ("FMMT", 0, 0004, "Out of resource, memory allocation failed! \n", "");
return EFI_OUT_OF_RESOURCES;
}
memcpy((char *)OutputFileNameList->FFSName, (char *)OutputFileName, strlen(OutputFileName)+1);
OutputFileNameList->IsFFS = TRUE;
if (OutputFileNameList->Next == NULL){
break;
}
OutputFileNameList = OutputFileNameList->Next;
}
break;
case FMMT_ENCAP_TREE_GUIDED_SECTION:
while(OutputFileNameList!= NULL && OutputFileNameList->FFSName != NULL){
//
// Create the guided section original data, do compress operation.
//
InputFileName = OutputFileNameList->FFSName;
OutputFileName= LibFilenameStrExtended (strrchr(GenTempFile (), OS_SEP), TemDir, "compressed");
//
// Use the guided section header guid to find out compress application name.
//
LocalEncapData = CurrentEncapData;
if (LocalEncapData == NULL) {
LocalEncapData = FvInFd->EncapData;
}
while (LocalEncapData->NextNode != NULL) {
if (LocalEncapData->Level == ParentLevel) {
break;
}
LocalEncapData = LocalEncapData->NextNode;
}
ExtractionTool =
LookupGuidedSectionToolPath (
mParsedGuidedSectionTools,
(EFI_GUID *)LocalEncapData->Data
);
GuidDataOffset = *(UINT16 *) ((UINT8 *) LocalEncapData->Data + sizeof (EFI_GUID));
GuidAttributes = *(UINT16 *) ((UINT8 *) LocalEncapData->Data + sizeof (EFI_GUID) + sizeof (UINT16));
Status = LibCreateGuidedSectionOriginalData (InputFileName, ExtractionTool, OutputFileName);
if (EFI_ERROR (Status) || GuidDataOffset < sizeof (EFI_GUID_DEFINED_SECTION)) {
Error ("FMMT", 0, 0004, "error while encapsulate FD Image", "Compress guided data failed!");
free (OutputFileNameList);
free (ChildFileNameList);
return Status;
}
GuidDataOffset = GuidDataOffset - sizeof (EFI_GUID_DEFINED_SECTION);
InputFileName = OutputFileName;
OutputFileName= LibFilenameStrExtended (strrchr(GenTempFile (), OS_SEP), TemDir, "guided");
Status = LibCreateFfsSection(NULL, InputFileName, NULL, EFI_SECTION_GUID_DEFINED, OutputFileName, NULL, NULL, LibFmmtGuidToStr((EFI_GUID *)LocalEncapData->Data), GuidDataOffset, GuidAttributes, NULL);
OutFile = fopen(OutputFileName, "rb+");
if (OutFile == NULL) {
Error("FMMT", 0, 0004, "Could not open the file %s! \n", "");
free (OutputFileNameList);
free (ChildFileNameList);
return EFI_ABORTED;
}
fseek(OutFile, 0, SEEK_SET);
fseek(OutFile, 0, SEEK_END);
OutputFileSize = ftell(OutFile);
fclose(OutFile);
if (OutputFileSize > LargeFileSize) {
IsLargeFile = TRUE;
}
OutputFileNameList->FFSName = (char *)malloc(strlen(OutputFileName)+1);
if (OutputFileNameList->FFSName == NULL) {
Error ("FMMT", 0, 0004, "Out of resource, memory allocation failed! \n", "");
return EFI_OUT_OF_RESOURCES;
}
memcpy((char *)OutputFileNameList->FFSName, (char *)OutputFileName, strlen(OutputFileName)+1);
if (EFI_ERROR (Status)) {
Error ("FMMT", 0, 0004, "error while encapsulate FD Image", "Generate guided section failed!");
free (OutputFileNameList);
free (ChildFileNameList);
return Status;
}
if (OutputFileNameList->Next == NULL){
break;
}
OutputFileNameList = OutputFileNameList->Next;
}
break;
case FMMT_ENCAP_TREE_COMPRESS_SECTION:
while(OutputFileNameList!= NULL && OutputFileNameList->FFSName != NULL){
InputFileName = OutputFileNameList->FFSName;
OutputFileName= LibFilenameStrExtended (strrchr(GenTempFile (), OS_SEP), TemDir, "comsec");
LocalEncapData = CurrentEncapData;
if (LocalEncapData == NULL) {
LocalEncapData = FvInFd->EncapData;
}
while (LocalEncapData->NextNode != NULL) {
if (LocalEncapData->Level == ParentLevel) {
break;
}
LocalEncapData = LocalEncapData->NextNode;
}
Status = LibGenCompressedSection (InputFileName, OutputFileName, *(UINT8 *)(LocalEncapData->Data));
OutputFileNameList->FFSName = (char *)malloc(strlen(OutputFileName)+1);
if (OutputFileNameList->FFSName == NULL) {
Error ("FMMT", 0, 0004, "Out of resource, memory allocation failed! \n", "");
return EFI_OUT_OF_RESOURCES;
}
memcpy((char *)OutputFileNameList->FFSName, (char *)OutputFileName, strlen(OutputFileName)+1);
if (EFI_ERROR (Status)) {
Error ("FMMT", 0, 0004, "error while encapsulate FD Image", "Generate compressed section failed!");
free (OutputFileNameList);
free (ChildFileNameList);
return Status;
}
if (OutputFileNameList->Next == NULL){
break;
}
OutputFileNameList = OutputFileNameList->Next;
}
break;
case FMMT_ENCAP_TREE_FV_SECTION:
while(OutputFileNameList!= NULL && OutputFileNameList->FFSName != NULL){
InputFileName = OutputFileNameList->FFSName;
OutputFileName= LibFilenameStrExtended (strrchr(GenTempFile (), OS_SEP), TemDir, "sec");
Status = LibCreateFfsSection(NULL, InputFileName, NULL, EFI_SECTION_FIRMWARE_VOLUME_IMAGE, OutputFileName, NULL, NULL, NULL, 0, 0, NULL);
if (EFI_ERROR (Status)) {
Error ("FMMT", 0, 0004, "error while encapsulate FD Image", "Generate FV section failed!");
free (OutputFileNameList);
free (ChildFileNameList);
return Status;
}
InputFileName = OutputFileName;
OutputFileName= LibFilenameStrExtended (strrchr(GenTempFile (), OS_SEP), TemDir, "sec");
//
// Make it alignment.
//
Status = LibCreateFfsSection(FvInFd, InputFileName, NULL, 0, OutputFileName, NULL, NULL, NULL, 0, 0, NULL);
OutFile = fopen(OutputFileName, "rb+");
if (OutFile == NULL) {
Error("FMMT", 0, 0004, "Could not open the file %s! \n", "");
free (OutputFileNameList);
free (ChildFileNameList);
return EFI_ABORTED;
}
fseek(OutFile, 0, SEEK_SET);
fseek(OutFile, 0, SEEK_END);
OutputFileSize = ftell(OutFile);
fclose(OutFile);
if (OutputFileSize > LargeFileSize) {
IsLargeFile = TRUE;
}
OutputFileNameList->FFSName = (char *)malloc(strlen(OutputFileName)+1);
if (OutputFileNameList->FFSName == NULL) {
Error ("FMMT", 0, 0004, "Out of resource, memory allocation failed! \n", "");
return EFI_OUT_OF_RESOURCES;
}
memcpy((char *)OutputFileNameList->FFSName, (char *)OutputFileName, strlen(OutputFileName)+1);
if (EFI_ERROR (Status)) {
Error ("FMMT", 0, 0004, "error while encapsulate FD Image", "Generate FV section failed!");
free (OutputFileNameList);
free (ChildFileNameList);
return Status;
}
if (OutputFileNameList->Next == NULL){
break;
}
OutputFileNameList = OutputFileNameList->Next;
}
break;
default:
for (Id = FvInFd->FfsNumbers; Id <= FvInFd->FfsNumbers; Id--) {
if ((memcmp(&FvInFd->FfsAttuibutes[Id].GuidName, &(CurrentEncapData->FvExtHeader->FvName), sizeof(EFI_GUID)) == 0)){
FvInFd->FfsAttuibutes[Id].IsHandle = TRUE;
memcpy(OutputFileNameList->UiName, FvInFd->FfsAttuibutes[Id].UiName, FvInFd->FfsAttuibutes[Id].UiNameSize);
OutputFileNameList->UiNameSize = FvInFd->FfsAttuibutes[Id].UiNameSize;
OutputFileNameList->FFSName = FvInFd->FfsAttuibutes[Id].FfsName;
OutputFileNameList->Depex = FvInFd->FfsAttuibutes[Id].Depex;
OutputFileNameList->DepexLen = FvInFd->FfsAttuibutes[Id].DepexLen;
OutputFileNameList->FfsFoundFlag = TRUE;
OutputFileNameList->IsFFS = TRUE;
OutputFileNameList->InFvId = Id;
*OutputFile = OutputFileNameList;
return EFI_SUCCESS;
}
}
}
if (CurrentEncapData == NULL) {
LocalEncapData = FvInFd->EncapData;
} else {
if (OutputFileNameList != NULL && OutputFileNameList->FFSName != NULL && OutputFileNameList->IsFFS == TRUE) {
*OutputFile = OutputFileNameList;
return EFI_SUCCESS;
}
LocalEncapData = CurrentEncapData;
}
ParentLevel -= 1;
while (LocalEncapData->NextNode != NULL) {
if (LocalEncapData->Level == ParentLevel) {
LocalEncapDataTemp = LocalEncapData->NextNode;
if ((LocalEncapDataTemp != NULL) && (LocalEncapDataTemp->Level == ParentLevel)) {
ParentType = LocalEncapDataTemp->Type;
break;
}
ParentType = LocalEncapData->Type;
break;
}
LocalEncapData = LocalEncapData->NextNode;
}
} while (ParentLevel != Level_Break);
*OutputFile = OutputFileNameList;
return EFI_SUCCESS;
}
EFI_STATUS
LibFindFvInEncapData (
ENCAP_INFO_DATA *EncapData,
UINT8 *Index
)
{
ENCAP_INFO_DATA *LocalEncapData;
LocalEncapData = EncapData;
if (LocalEncapData == NULL) {
Error("FMMT", 0, 0005, "error while find FV in Encapulate buffer", "Invalid parameters.");
return EFI_INVALID_PARAMETER;
}
while (LocalEncapData != NULL) {
if (LocalEncapData->RightNode != NULL) {
LibFindFvInEncapData (LocalEncapData->RightNode, Index);
}
if (LocalEncapData->Type == FMMT_ENCAP_TREE_FV) {
(*Index)++;
}
LocalEncapData = LocalEncapData->NextNode;
}
return EFI_SUCCESS;
}
EFI_STATUS
LibLocateFvViaFvId (
IN FIRMWARE_DEVICE *FdData,
IN CHAR8 *FvId,
IN OUT FV_INFORMATION **FvInFd
)
{
UINT8 FvIndex1;
UINT8 FvIndex2;
BOOLEAN FvFoundFlag;
CHAR8* FvGuidName;
ENCAP_INFO_DATA *LocalEncapData;
ENCAP_INFO_DATA *LocalEncapDataRight;
ENCAP_INFO_DATA *LocalEncapDataNext;
FvIndex1 = 0;
FvIndex2 = 0;
FvFoundFlag = FALSE;
FvGuidName = NULL;
LocalEncapDataNext = NULL;
LocalEncapDataRight = NULL;
if (FdData == NULL || FvId == NULL || FvInFd == NULL || FdData->Fv == NULL) {
Error ("FMMT", 0, 0005, "error while find FV in FD", "Invalid parameters.");
return EFI_INVALID_PARAMETER;
}
*FvInFd = FdData->Fv;
if (strlen(FvId) < 3) {
Error ("FMMT", 0, 0005, "error while find FV in FD", "Invalid FvId, please double check the FvId. You can use view operate to get the FvId information!");
return EFI_ABORTED;
}
FvGuidName = (CHAR8 *) malloc (255);
if (FvGuidName == NULL) {
Error ("FMMT", 0, 0005, "Resource: Memory can't be allocated", NULL);
return EFI_ABORTED;
}
memset(FvGuidName, '\0', 255);
LocalEncapData = NULL;
if (strlen(FvId) == 36) {
while (FvInFd != NULL) {
if (((*FvInFd)->FvExtHeader) != NULL) {
sprintf(
FvGuidName,
"%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
(*FvInFd)->FvExtHeader->FvName.Data1,
(*FvInFd)->FvExtHeader->FvName.Data2,
(*FvInFd)->FvExtHeader->FvName.Data3,
(*FvInFd)->FvExtHeader->FvName.Data4[0],
(*FvInFd)->FvExtHeader->FvName.Data4[1],
(*FvInFd)->FvExtHeader->FvName.Data4[2],
(*FvInFd)->FvExtHeader->FvName.Data4[3],
(*FvInFd)->FvExtHeader->FvName.Data4[4],
(*FvInFd)->FvExtHeader->FvName.Data4[5],
(*FvInFd)->FvExtHeader->FvName.Data4[6],
(*FvInFd)->FvExtHeader->FvName.Data4[7]);
if (strcmp(FvGuidName, FvId) == 0) {
FvId = (*FvInFd)->FvName;
break;
}
}
if ((*FvInFd)->MulFvLevel > 1) {
LocalEncapData = (*FvInFd) -> EncapData;
LocalEncapData = LocalEncapData->NextNode;
while (LocalEncapData != NULL) {
if (LocalEncapData->RightNode != NULL) {
LocalEncapDataRight = LocalEncapData->RightNode;
while (LocalEncapDataRight !=NULL) {
if (LocalEncapDataRight->NextNode != NULL) {
LocalEncapDataNext = LocalEncapDataRight->NextNode;
while (LocalEncapDataNext != NULL) {
if (LocalEncapDataNext->Type == FMMT_ENCAP_TREE_FV) {
if (LocalEncapDataNext->FvExtHeader != NULL) {
sprintf(
FvGuidName,
"%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
LocalEncapDataNext->FvExtHeader->FvName.Data1,
LocalEncapDataNext->FvExtHeader->FvName.Data2,
LocalEncapDataNext->FvExtHeader->FvName.Data3,
LocalEncapDataNext->FvExtHeader->FvName.Data4[0],
LocalEncapDataNext->FvExtHeader->FvName.Data4[1],
LocalEncapDataNext->FvExtHeader->FvName.Data4[2],
LocalEncapDataNext->FvExtHeader->FvName.Data4[3],
LocalEncapDataNext->FvExtHeader->FvName.Data4[4],
LocalEncapDataNext->FvExtHeader->FvName.Data4[5],
LocalEncapDataNext->FvExtHeader->FvName.Data4[6],
LocalEncapDataNext->FvExtHeader->FvName.Data4[7]);
if (strcmp(FvGuidName, FvId) == 0)
{
sprintf(FvId, "%s%d", "FV", LocalEncapDataNext->FvId - 1);
break;
}
}
}
LocalEncapDataNext = LocalEncapDataNext->NextNode;
}
}
LocalEncapDataRight = LocalEncapDataRight->RightNode;
}
}
if (LocalEncapData->Type == FMMT_ENCAP_TREE_FV) {
if (LocalEncapData->FvExtHeader != NULL) {
sprintf(
FvGuidName,
"%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
LocalEncapData->FvExtHeader->FvName.Data1,
LocalEncapData->FvExtHeader->FvName.Data2,
LocalEncapData->FvExtHeader->FvName.Data3,
LocalEncapData->FvExtHeader->FvName.Data4[0],
LocalEncapData->FvExtHeader->FvName.Data4[1],
LocalEncapData->FvExtHeader->FvName.Data4[2],
LocalEncapData->FvExtHeader->FvName.Data4[3],
LocalEncapData->FvExtHeader->FvName.Data4[4],
LocalEncapData->FvExtHeader->FvName.Data4[5],
LocalEncapData->FvExtHeader->FvName.Data4[6],
LocalEncapData->FvExtHeader->FvName.Data4[7]);
if (strcmp(FvGuidName, FvId) == 0) {
sprintf(FvId, "%s%d", "FV", LocalEncapData->FvId - 1);
break;
}
}
}
LocalEncapData = LocalEncapData->NextNode;
}
}
if ((*FvInFd)->FvNext == 0) {
break;
}
*FvInFd = (*FvInFd)->FvNext;
}
}
*FvInFd = FdData->Fv;
FvIndex1 = (UINT8) atoi (FvId + 2);
while (FvInFd != NULL) {
if (((*FvInFd)->FvName) != NULL) {
FvIndex2 = (UINT8) atoi ((*FvInFd)->FvName + 2);
LocalEncapData = (*FvInFd)->EncapData;
LibFindFvInEncapData (LocalEncapData, &FvIndex2);
if ((FvIndex2 - 1 >= FvIndex1)) {
FvFoundFlag = TRUE;
break;
}
if ((*FvInFd)->FvNext == 0) {
break;
}
}
*FvInFd = (*FvInFd)->FvNext;
}
if (FvGuidName != NULL) {
free (FvGuidName);
}
//
// The specified FV id has issue, can not find the FV in FD.
//
if (!FvFoundFlag) {
Error ("FMMT", 0, 0005, "error while find FV in FD", "Invalid FvId, please double check the FvId. You can use view operate to get the FvId information!");
return EFI_ABORTED;
}
return EFI_SUCCESS;
}
#define BUILD_IN_TOOL_COUNT 4
EFI_HANDLE
LibPreDefinedGuidedTools (
VOID
)
{
EFI_GUID Guid;
STRING_LIST *Tool;
GUID_SEC_TOOL_ENTRY *FirstGuidTool;
GUID_SEC_TOOL_ENTRY *LastGuidTool;
GUID_SEC_TOOL_ENTRY *NewGuidTool;
UINT8 Index;
EFI_STATUS Status;
CHAR8 PreDefinedGuidedTool[BUILD_IN_TOOL_COUNT][255] = {
"a31280ad-481e-41b6-95e8-127f4c984779 TIANO TianoCompress",
"ee4e5898-3914-4259-9d6e-dc7bd79403cf LZMA LzmaCompress",
"fc1bcdb0-7d31-49aa-936a-a4600d9dd083 CRC32 GenCrc32",
"3d532050-5cda-4fd0-879e-0f7f630d5afb BROTLI BrotliCompress"
};
Tool = NULL;
FirstGuidTool = NULL;
LastGuidTool = NULL;
NewGuidTool = NULL;
Index = 0;
for (Index = 0; Index < BUILD_IN_TOOL_COUNT; Index++) {
Tool = SplitStringByWhitespace (PreDefinedGuidedTool[Index]);
if ((Tool != NULL) &&
(Tool->Count == 3)
) {
Status = StringToGuid (Tool->Strings[0], &Guid);
if (!EFI_ERROR (Status)) {
NewGuidTool = malloc (sizeof (GUID_SEC_TOOL_ENTRY));
if (NewGuidTool != NULL) {
memcpy (&(NewGuidTool->Guid), &Guid, sizeof (Guid));
NewGuidTool->Name = CloneString(Tool->Strings[1]);
NewGuidTool->Path = CloneString(Tool->Strings[2]);
NewGuidTool->Next = NULL;
} else {
printf ("Error while allocate resource! \n");
FreeStringList (Tool);
return NULL;
}
if (FirstGuidTool == NULL) {
FirstGuidTool = NewGuidTool;
} else {
LastGuidTool->Next = NewGuidTool;
}
LastGuidTool = NewGuidTool;
}
} else {
fprintf (stdout, "Error");
}
if (Tool != NULL) {
FreeStringList (Tool);
Tool = NULL;
}
}
return FirstGuidTool;
}