mirror of
https://github.com/acidanthera/audk.git
synced 2025-05-23 07:50:09 +02:00
FCE is a tool to retrieve and change HII configuration data in Firmware Device(*.fd) files. https://bugzilla.tianocore.org/show_bug.cgi?id=1848 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>
1327 lines
36 KiB
C
1327 lines
36 KiB
C
/** @file
|
|
|
|
The API to parse the binary.
|
|
|
|
Copyright (c) 2011-2019, Intel Corporation. All rights reserved.<BR>
|
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
|
|
**/
|
|
|
|
#ifndef __GNUC__
|
|
#include "windows.h"
|
|
#else
|
|
#include <sys/types.h>
|
|
#include <dirent.h>
|
|
#include <unistd.h>
|
|
#endif
|
|
#include "BinaryParse.h"
|
|
#include "BinaryCreate.h"
|
|
#include "VariableCommon.h"
|
|
#include "FirmwareVolumeBufferLib.h"
|
|
|
|
extern G_EFI_FD_INFO gEfiFdInfo;
|
|
extern EFI_HANDLE mParsedGuidedSectionTools;
|
|
extern CHAR8 mInputFdName[MAX_FILENAME_LEN];
|
|
|
|
//
|
|
// The Guid to sign the position of Vfr and Uni array in FV
|
|
//
|
|
EFI_GUID gVfrArrayAttractGuid = EFI_VFR_ATTRACT_GUID;
|
|
EFI_GUID gUniStrArrayAttractGuid = EFI_UNI_STR_ATTRACT_GUID;
|
|
EFI_GUID gEfiSystemNvDataFvGuid = EFI_SYSTEM_NVDATA_FV_GUID;
|
|
EFI_GUID gEfiCrc32GuidedSectionExtractionProtocolGuid = EFI_CRC32_GUIDED_SECTION_EXTRACTION_PROTOCOL_GUID;
|
|
|
|
/**
|
|
Converts a three byte length value into a UINT32.
|
|
|
|
@param ThreeByteLength Pointer to the first of the 3 byte length.
|
|
|
|
@retval Length Size of the section
|
|
|
|
**/
|
|
static
|
|
UINT32
|
|
Get3ByteLength (
|
|
IN UINT8 *ThreeByteLength
|
|
)
|
|
{
|
|
UINT32 Length;
|
|
|
|
Length = 0;
|
|
|
|
if (ThreeByteLength == NULL) {
|
|
return 0;
|
|
}
|
|
|
|
Length = *((UINT32 *) ThreeByteLength);
|
|
Length = Length & 0x00FFFFFF;
|
|
|
|
return Length;
|
|
}
|
|
|
|
/**
|
|
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;
|
|
}
|
|
|
|
/**
|
|
Check whether exist the same Ifr FFS. If not existed, return TRUE.
|
|
|
|
@param[in] FfsImage The pointer to the binary.
|
|
@param[in] FileSize The size of binary.
|
|
|
|
@return The string after convert.
|
|
**/
|
|
static
|
|
BOOLEAN
|
|
NotExistSameFfsIfr (
|
|
IN VOID *FfsImage
|
|
)
|
|
{
|
|
UINT32 Index;
|
|
|
|
Index = 0;
|
|
|
|
while (gEfiFdInfo.FfsArray[Index] != NULL) {
|
|
if (memcmp (gEfiFdInfo.FfsArray[Index], FfsImage, sizeof (EFI_GUID)) == 0) {
|
|
return FALSE;
|
|
}
|
|
Index++;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
This function returns the next larger size that meets the alignment
|
|
requirement specified.
|
|
|
|
@param ActualSize The size.
|
|
@param Alignment The desired alignment.
|
|
|
|
@retval The Occupied length
|
|
|
|
**/
|
|
static
|
|
UINT32
|
|
GetOccupiedSize (
|
|
IN UINT32 ActualSize,
|
|
IN UINT32 Alignment
|
|
)
|
|
{
|
|
UINT32 OccupiedSize;
|
|
|
|
OccupiedSize = ActualSize;
|
|
while ((OccupiedSize & (Alignment - 1)) != 0) {
|
|
OccupiedSize++;
|
|
}
|
|
|
|
return OccupiedSize;
|
|
}
|
|
|
|
|
|
/**
|
|
Parses FFS Sections, and remove the FFS headers. Tis function olny handle one efi in this FFS.
|
|
|
|
@param SectionBuffer The section base address
|
|
@param BufferLength The length of FFS.
|
|
@param EfiBufferHeader The structure dual pointer to the efi informations
|
|
|
|
@retval EFI_SUCCESS The application exited normally.
|
|
@retval EFI_ABORTED An error occurred.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
ParseSection (
|
|
IN BOOLEAN IsFfsOrEfi,
|
|
IN OUT UINT8 *SectionBuffer,
|
|
IN UINT32 BufferLength,
|
|
IN OUT EFI_SECTION_STRUCT **EfiBufferHeader
|
|
)
|
|
{
|
|
UINT32 ParsedLength;
|
|
EFI_SECTION_TYPE Type;
|
|
UINT8 *Ptr;
|
|
UINT32 SectionLength;
|
|
UINT8 *CompressedBuffer;
|
|
UINT32 CompressedLength;
|
|
UINT8 *UncompressedBuffer;
|
|
UINT32 UncompressedLength;
|
|
UINT8 CompressionType;
|
|
DECOMPRESS_FUNCTION DecompressFunction;
|
|
GETINFO_FUNCTION GetInfoFunction;
|
|
UINT32 ScratchSize;
|
|
UINT8 *ScratchBuffer;
|
|
EFI_STATUS Status;
|
|
UINT32 DstSize;
|
|
CHAR8 *ExtractionTool;
|
|
CHAR8 *ToolInputFile;
|
|
CHAR8 *ToolOutputFile;
|
|
CHAR8 *SystemCommandFormatString;
|
|
CHAR8 *SystemCommand;
|
|
UINT8 *ToolOutputBuffer;
|
|
UINT32 ToolOutputLength;
|
|
BOOLEAN HasDepexSection;
|
|
|
|
Ptr = NULL;
|
|
SectionLength = 0;
|
|
CompressedBuffer = NULL;
|
|
CompressedLength = 0;
|
|
UncompressedBuffer = NULL;
|
|
UncompressedLength = 0;
|
|
CompressionType = 0;
|
|
ScratchSize = 0;
|
|
ScratchBuffer = NULL;
|
|
Status = EFI_SUCCESS;
|
|
DstSize = 0;
|
|
ExtractionTool = NULL;
|
|
ToolInputFile = NULL;
|
|
ToolOutputFile = NULL;
|
|
SystemCommandFormatString = NULL;
|
|
SystemCommand = NULL;
|
|
|
|
//
|
|
// Jump the FFS header
|
|
//
|
|
if (IsFfsOrEfi) {
|
|
SectionBuffer = SectionBuffer + sizeof (EFI_FFS_FILE_HEADER);
|
|
BufferLength = BufferLength - sizeof (EFI_FFS_FILE_HEADER);
|
|
}
|
|
ParsedLength = 0;
|
|
HasDepexSection = FALSE;
|
|
ExtractionTool = NULL;
|
|
ToolOutputLength = 0;
|
|
ToolOutputBuffer = NULL;
|
|
|
|
(*EfiBufferHeader)->Length = BufferLength;
|
|
|
|
while (ParsedLength < BufferLength) {
|
|
Ptr = SectionBuffer + ParsedLength;
|
|
|
|
SectionLength = Get3ByteLength (((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;
|
|
}
|
|
|
|
switch (Type) {
|
|
|
|
case EFI_SECTION_PE32:
|
|
case EFI_SECTION_TE:
|
|
//
|
|
//Got the correct address
|
|
//
|
|
(*EfiBufferHeader)->BufferBase = (UINTN)(Ptr + sizeof (EFI_COMMON_SECTION_HEADER));
|
|
return EFI_SUCCESS;
|
|
|
|
case EFI_SECTION_RAW:
|
|
case EFI_SECTION_PIC:
|
|
break;
|
|
|
|
case EFI_SECTION_USER_INTERFACE:
|
|
HasDepexSection = FALSE;
|
|
break;
|
|
|
|
case EFI_SECTION_FIRMWARE_VOLUME_IMAGE:
|
|
case EFI_SECTION_COMPATIBILITY16:
|
|
case EFI_SECTION_FREEFORM_SUBTYPE_GUID:
|
|
break;
|
|
|
|
case EFI_SECTION_PEI_DEPEX:
|
|
case EFI_SECTION_DXE_DEPEX:
|
|
case EFI_SECTION_SMM_DEPEX:
|
|
HasDepexSection = TRUE;
|
|
break;
|
|
|
|
case EFI_SECTION_VERSION:
|
|
break;
|
|
case EFI_SECTION_COMPRESSION:
|
|
UncompressedBuffer = NULL;
|
|
CompressedLength = SectionLength - sizeof (EFI_COMPRESSION_SECTION);
|
|
UncompressedLength = ((EFI_COMPRESSION_SECTION *) Ptr)->UncompressedLength;
|
|
CompressionType = ((EFI_COMPRESSION_SECTION *) Ptr)->CompressionType;
|
|
|
|
if (CompressionType == EFI_NOT_COMPRESSED) {
|
|
if (CompressedLength != UncompressedLength) {
|
|
Error (
|
|
NULL,
|
|
0,
|
|
0,
|
|
"file is not compressed, but the compressed length does not match the uncompressed length",
|
|
NULL
|
|
);
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
UncompressedBuffer = Ptr + sizeof (EFI_COMPRESSION_SECTION);
|
|
} else if (CompressionType == EFI_STANDARD_COMPRESSION) {
|
|
GetInfoFunction = EfiGetInfo;
|
|
DecompressFunction = EfiDecompress;
|
|
CompressedBuffer = Ptr + sizeof (EFI_COMPRESSION_SECTION);
|
|
|
|
Status = GetInfoFunction (
|
|
CompressedBuffer,
|
|
CompressedLength,
|
|
&DstSize,
|
|
&ScratchSize
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
Error (NULL, 0, 0003, "error getting compression info from compression section", NULL);
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
if (DstSize != UncompressedLength) {
|
|
Error (NULL, 0, 0003, "compression error in the compression section", NULL);
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
ScratchBuffer = malloc (ScratchSize);
|
|
if (ScratchBuffer == NULL) {
|
|
return EFI_ABORTED;
|
|
}
|
|
UncompressedBuffer = malloc (UncompressedLength);
|
|
if (UncompressedBuffer == NULL) {
|
|
free (ScratchBuffer);
|
|
return EFI_ABORTED;
|
|
}
|
|
memset (UncompressedBuffer, 0, UncompressedLength);
|
|
|
|
Status = DecompressFunction (
|
|
CompressedBuffer,
|
|
CompressedLength,
|
|
UncompressedBuffer,
|
|
UncompressedLength,
|
|
ScratchBuffer,
|
|
ScratchSize
|
|
);
|
|
free (ScratchBuffer);
|
|
if (Status != EFI_SUCCESS) {
|
|
Error (NULL, 0, 0003, "decompress failed", NULL);
|
|
free (UncompressedBuffer);
|
|
return EFI_ABORTED;
|
|
}
|
|
} else {
|
|
Error (NULL, 0, 0003, "unrecognized compression type", "type 0x%X", CompressionType);
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
Status = ParseSection (FALSE, UncompressedBuffer, UncompressedLength, EfiBufferHeader);
|
|
if (Status != EFI_SUCCESS) {
|
|
Error (NULL, 0, 0003, "failed to parse section", NULL);
|
|
free (UncompressedBuffer);
|
|
UncompressedBuffer = NULL;
|
|
} else {
|
|
return EFI_SUCCESS;
|
|
}
|
|
//
|
|
// Store the allocate memory address for UncompressedBuffer
|
|
//
|
|
if (UncompressedBuffer != NULL) {
|
|
(*EfiBufferHeader)->UncompressedBuffer[(*EfiBufferHeader)->UnCompressIndex] = (UINTN) UncompressedBuffer;
|
|
(*EfiBufferHeader)->UnCompressIndex = (*EfiBufferHeader)->UnCompressIndex + 1;
|
|
}
|
|
break;
|
|
|
|
case EFI_SECTION_GUID_DEFINED:
|
|
//
|
|
// Decompress failed, and then check for CRC32 sections which we can handle internally if needed.
|
|
// Maybe this section is no-compressed.
|
|
//
|
|
if (!CompareGuid (
|
|
&((EFI_GUID_DEFINED_SECTION *) Ptr)->SectionDefinitionGuid,
|
|
&gEfiCrc32GuidedSectionExtractionProtocolGuid
|
|
)) {
|
|
//
|
|
// CRC32 guided section
|
|
//
|
|
Status = ParseSection (
|
|
FALSE,
|
|
SectionBuffer + ((EFI_GUID_DEFINED_SECTION *) Ptr)->DataOffset,
|
|
BufferLength - ((EFI_GUID_DEFINED_SECTION *) Ptr)->DataOffset,
|
|
EfiBufferHeader
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
Error (NULL, 0, 0003, "parse of CRC32 GUIDED section failed", NULL);
|
|
return EFI_ABORTED;
|
|
} else {
|
|
return EFI_SUCCESS;
|
|
}
|
|
} else {
|
|
ExtractionTool = LookupGuidedSectionToolPath (
|
|
mParsedGuidedSectionTools,
|
|
&((EFI_GUID_DEFINED_SECTION *) Ptr)->SectionDefinitionGuid
|
|
);
|
|
|
|
if (ExtractionTool != NULL) {
|
|
ToolInputFile = GenTempFile ();
|
|
ToolOutputFile = GenTempFile ();
|
|
//
|
|
// Construction 'system' command string
|
|
//
|
|
SystemCommandFormatString = "%s -d -o \"%s\" \"%s\"";
|
|
SystemCommand = malloc (
|
|
strlen (SystemCommandFormatString) \
|
|
+ strlen (ExtractionTool) \
|
|
+ strlen (ToolInputFile) \
|
|
+ strlen (ToolOutputFile) \
|
|
+ 1
|
|
);
|
|
if (SystemCommand == NULL) {
|
|
free (ExtractionTool);
|
|
free (ToolInputFile);
|
|
free (ToolOutputFile);
|
|
return EFI_ABORTED;
|
|
}
|
|
sprintf (
|
|
SystemCommand,
|
|
"%s -d -o \"%s\" \"%s\"",
|
|
ExtractionTool,
|
|
ToolOutputFile,
|
|
ToolInputFile
|
|
);
|
|
free (ExtractionTool);
|
|
|
|
Status = PutFileImage (
|
|
ToolInputFile,
|
|
(CHAR8*) Ptr + ((EFI_GUID_DEFINED_SECTION *) Ptr)->DataOffset,
|
|
SectionLength - ((EFI_GUID_DEFINED_SECTION *) Ptr)->DataOffset
|
|
);
|
|
|
|
if (HasDepexSection) {
|
|
HasDepexSection = FALSE;
|
|
}
|
|
|
|
system (SystemCommand);
|
|
remove (ToolInputFile);
|
|
free (ToolInputFile);
|
|
ToolInputFile = NULL;
|
|
free (SystemCommand);
|
|
SystemCommand = NULL;
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
Error ("FCE", 0, 0004, "unable to decoded GUIDED section", NULL);
|
|
free (ToolOutputFile);
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
Status = GetFileImage (
|
|
ToolOutputFile,
|
|
(CHAR8 **)&ToolOutputBuffer,
|
|
&ToolOutputLength
|
|
);
|
|
remove (ToolOutputFile);
|
|
free (ToolOutputFile);
|
|
ToolOutputFile = NULL;
|
|
if (EFI_ERROR (Status)) {
|
|
return EFI_ABORTED;
|
|
}
|
|
}
|
|
Status = ParseSection (
|
|
FALSE,
|
|
ToolOutputBuffer,
|
|
ToolOutputLength,
|
|
EfiBufferHeader
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
Error (NULL, 0, 0003, "parse of decoded GUIDED section failed", NULL);
|
|
return EFI_ABORTED;
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
;
|
|
}
|
|
ParsedLength += SectionLength;
|
|
//
|
|
// We make then next section begin on a 4-byte boundary
|
|
//
|
|
ParsedLength = GetOccupiedSize (ParsedLength, 4);
|
|
}
|
|
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
static
|
|
BOOLEAN
|
|
GetNextOffset (
|
|
IN UINT8 *Data,
|
|
IN EFI_GUID *Guid,
|
|
IN UINTN Len,
|
|
IN OUT UINTN *Offset
|
|
)
|
|
{
|
|
UINTN NextOffset;
|
|
if (*Offset >= Len || Len - *Offset <= sizeof (EFI_GUID)) {
|
|
return FALSE;
|
|
}
|
|
|
|
for (NextOffset = *Offset; NextOffset < Len - sizeof (EFI_GUID); NextOffset++) {
|
|
if (CompareGuid(Guid, (EFI_GUID*)(Data + NextOffset)) == 0) {
|
|
*Offset = NextOffset + sizeof(EFI_GUID);
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
/**
|
|
Get the address by Guid.
|
|
|
|
Parse the FFS image, and find the GUID address.There may be some Guids matching the
|
|
searched Guid.
|
|
|
|
@param Fv the Pointer to the image.
|
|
@param Guid The Guid need to find.
|
|
@param Offset The dual Pointer to the offset.
|
|
@param NumOfMatchGuid The number of matching Guid offset.
|
|
|
|
@retval EFI_SUCCESS The Search was complete successfully
|
|
@return EFI_ABORTED An error occurred
|
|
**/
|
|
EFI_STATUS
|
|
GetAddressByGuid (
|
|
IN VOID *Fv,
|
|
IN EFI_GUID *Guid,
|
|
IN UINTN Len,
|
|
OUT UINTN **Offset,
|
|
OUT UINT8 *NumOfMatchGuid
|
|
)
|
|
{
|
|
VOID *LocalFv;
|
|
UINT8 Flag;
|
|
|
|
EFI_RAW_SECTION* Section;
|
|
UINT8 *RawData;
|
|
VOID* SectionStart;
|
|
UINTN NextOffset;
|
|
UINTN Key;
|
|
UINTN TotalSectionsSize;
|
|
UINTN SecLen;
|
|
UINTN SecHdr;
|
|
EFI_STATUS Status;
|
|
|
|
if( (Fv == NULL) || (Fv == NULL) || (Guid == NULL) || Len == 0 ){
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
LocalFv = Fv;
|
|
Flag = 0;
|
|
Section = NULL;
|
|
Key = 0;
|
|
|
|
if (NumOfMatchGuid != NULL) {
|
|
*NumOfMatchGuid = 0;
|
|
}
|
|
|
|
SectionStart = (VOID*)((UINTN)LocalFv + FvBufGetFfsHeaderSize(LocalFv));
|
|
TotalSectionsSize = Len - FvBufGetFfsHeaderSize(LocalFv);
|
|
while (TRUE) {
|
|
Status = FvBufFindNextSection (
|
|
SectionStart,
|
|
TotalSectionsSize,
|
|
&Key,
|
|
(VOID **)&Section
|
|
);
|
|
if (Section == NULL || EFI_ERROR (Status)) {
|
|
break;
|
|
}
|
|
|
|
if (EFI_SECTION_RAW == Section->Type) {
|
|
if ((*(UINT32 *)Section->Size & 0xffffff) == 0xffffff) {
|
|
SecLen = ((EFI_RAW_SECTION2 *)Section)->ExtendedSize;
|
|
SecHdr = sizeof(EFI_RAW_SECTION2);
|
|
} else {
|
|
SecLen = *(UINT32 *)Section->Size & 0xffffff;
|
|
SecHdr = sizeof(EFI_RAW_SECTION);
|
|
}
|
|
if (SecLen <= SecHdr || SecLen - SecHdr < sizeof(EFI_GUID)) {
|
|
continue;
|
|
}
|
|
RawData = (UINT8 *)Section + SecHdr;
|
|
NextOffset = 0;
|
|
while (GetNextOffset(RawData, Guid, SecLen - SecHdr, &NextOffset)) {
|
|
Flag = 1;
|
|
if ((NumOfMatchGuid != NULL) && (Offset != NULL)) {
|
|
if (*NumOfMatchGuid == 0) {
|
|
*Offset = malloc (sizeof (UINTN) * MAX_MATCH_GUID_NUM);
|
|
if (*Offset == NULL) {
|
|
return EFI_ABORTED;
|
|
}
|
|
memset (*Offset, 0, sizeof (UINTN) * MAX_MATCH_GUID_NUM);
|
|
}
|
|
*(*Offset + *NumOfMatchGuid) = NextOffset + (RawData - (UINT8 *)Fv);
|
|
(*NumOfMatchGuid)++;
|
|
} else {
|
|
return EFI_SUCCESS;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if( Flag == 0 ) {
|
|
return EFI_ABORTED;
|
|
}
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Search the VfrBin Base address.
|
|
|
|
According the known GUID gVfrArrayAttractGuid to get the base address from FFS.
|
|
|
|
@param Fv the Pointer to the FFS
|
|
@param EfiAddr the Pointer to the EFI in FFS
|
|
@param Length the length of Fv
|
|
@param Offset the Pointer to the Addr (Offset)
|
|
@param NumOfMachingOffset the number of Addr (Offset)
|
|
|
|
@retval EFI_SUCCESS Get the address successfully.
|
|
**/
|
|
EFI_STATUS
|
|
SearchVfrBinInFFS (
|
|
IN VOID *Fv,
|
|
IN VOID *EfiAddr,
|
|
IN UINTN Length,
|
|
OUT UINTN **Offset,
|
|
OUT UINT8 *NumOfMachingOffset
|
|
)
|
|
{
|
|
UINTN Index;
|
|
EFI_STATUS Status;
|
|
UINTN VirOffValue;
|
|
|
|
Index = 0;
|
|
Status = EFI_SUCCESS;
|
|
VirOffValue = 0;
|
|
|
|
if ((Fv == NULL) || (Offset == NULL)) {
|
|
return EFI_ABORTED;
|
|
}
|
|
Status = GetAddressByGuid (
|
|
Fv,
|
|
&gVfrArrayAttractGuid,
|
|
Length,
|
|
Offset,
|
|
NumOfMachingOffset
|
|
);
|
|
if (Status != EFI_SUCCESS) {
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
while (Index < *NumOfMachingOffset) {
|
|
//
|
|
// Got the virOffset after the GUID
|
|
//
|
|
VirOffValue = *(UINTN *)((UINTN)Fv + *(*Offset + Index));
|
|
//
|
|
//Transfer the offset to the VA address. One modules may own more VfrBin address.
|
|
//
|
|
*(*Offset + Index) = (UINTN) EfiAddr + VirOffValue;
|
|
Index++;
|
|
}
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Search the UniBin Base address.
|
|
|
|
According the known GUID gUniStrArrayAttractGuid to get the base address from FFS.
|
|
|
|
@param Fv the Pointer to the FFS
|
|
@param EfiAddr the Pointer to the EFI in FFS
|
|
@param Length the length of Fv
|
|
@param Offset the Pointer to the Addr (Offset)
|
|
|
|
@retval Base address Get the address successfully.
|
|
**/
|
|
EFI_STATUS
|
|
SearchUniBinInFFS (
|
|
IN VOID *Fv,
|
|
IN VOID *EfiAddr,
|
|
IN UINTN Length,
|
|
OUT UINTN **Offset
|
|
)
|
|
{
|
|
UINT8 NumOfMachingOffset;
|
|
EFI_STATUS Status;
|
|
UINTN VirOffValue;
|
|
|
|
NumOfMachingOffset = 0;
|
|
Status = EFI_SUCCESS;
|
|
VirOffValue = 0;
|
|
|
|
if ((Fv == NULL) || (Offset == NULL)) {
|
|
return EFI_ABORTED;
|
|
}
|
|
Status = GetAddressByGuid (
|
|
Fv,
|
|
&gUniStrArrayAttractGuid,
|
|
Length,
|
|
Offset,
|
|
&NumOfMachingOffset
|
|
);
|
|
if (Status != EFI_SUCCESS) {
|
|
return EFI_ABORTED;
|
|
}
|
|
//
|
|
//Transfer the offset to the VA address. There is only one UniArray in one modules.
|
|
//
|
|
if (NumOfMachingOffset == 1) {
|
|
VirOffValue = *(UINTN *)((UINTN)Fv + **Offset);
|
|
**Offset = (UINTN) EfiAddr + VirOffValue;
|
|
} else {
|
|
printf ("Error. Find more than 1 UniBin in FFS.\n");
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS
|
|
SearchNvStoreDatabaseInFd(
|
|
IN VOID *Fv,
|
|
IN UINTN length
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINTN Offset;
|
|
PCD_NV_STORE_DEFAULT_BUFFER_HEADER *NvStoreHeader;
|
|
Status = EFI_SUCCESS;
|
|
Offset = 0;
|
|
if (Fv == NULL) {
|
|
printf ("The FV is NULL.");
|
|
return EFI_ABORTED;
|
|
}
|
|
while (Offset < (length - sizeof(PCD_NV_STORE_DEFAULT_BUFFER_HEADER))){
|
|
NvStoreHeader = (PCD_NV_STORE_DEFAULT_BUFFER_HEADER *)((UINT8*)Fv + Offset);
|
|
if (NvStoreHeader->Signature == PCD_NV_STORE_DEFAULT_BUFFER_SIGNATURE) {
|
|
gEfiFdInfo.ExistNvStoreDatabase = TRUE;
|
|
gEfiFdInfo.NvStoreDatabase = (UINT8 *) NvStoreHeader;
|
|
break;
|
|
}
|
|
Offset++;
|
|
}
|
|
if (Offset == (length - sizeof(PCD_NV_STORE_DEFAULT_BUFFER_HEADER)) || gEfiFdInfo.ExistNvStoreDatabase != TRUE) {
|
|
//printf ("Not found the PcdNvStoreDefaultValueBuffer\n");
|
|
return Status;
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Get the address by Guid.
|
|
|
|
Parse the FD image, and find the GUID address.There may be some Guids matching the
|
|
searched Guid.
|
|
|
|
@param Fv the Pointer to the image.
|
|
@param Guid The Guid need to find.
|
|
@param Offset The dual Pointer to the offset.
|
|
@param NumOfMatchGuid The number of matching Guid offset.
|
|
|
|
@retval EFI_SUCCESS The Search was complete successfully
|
|
@return EFI_ABORTED An error occurred
|
|
**/
|
|
EFI_STATUS
|
|
GetVariableAddressByGuid (
|
|
IN VOID *Fv,
|
|
IN EFI_GUID *Guid,
|
|
IN UINTN Len,
|
|
OUT UINTN **Offset,
|
|
OUT UINT8 *NumOfMatchGuid
|
|
)
|
|
{
|
|
UINTN NextOffset;
|
|
UINT8 Flag;
|
|
|
|
if( (Fv == NULL) || (Fv == NULL) || (Guid == NULL) ){
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
Flag = 0;
|
|
NextOffset = 0;
|
|
|
|
if (NumOfMatchGuid != NULL) {
|
|
*NumOfMatchGuid = 0;
|
|
}
|
|
while (GetNextOffset(Fv, Guid, Len, &NextOffset)) {
|
|
Flag = 1;
|
|
if (NumOfMatchGuid != NULL && Offset != NULL) {
|
|
if (*NumOfMatchGuid == 0) {
|
|
*Offset = malloc (sizeof (UINTN) * MAX_MATCH_GUID_NUM);
|
|
if (*Offset == NULL) {
|
|
return EFI_ABORTED;
|
|
}
|
|
memset (*Offset, 0, sizeof (UINTN) * MAX_MATCH_GUID_NUM);
|
|
}
|
|
*(*Offset + *NumOfMatchGuid) = NextOffset;
|
|
(*NumOfMatchGuid)++;
|
|
} else {
|
|
return EFI_SUCCESS;
|
|
}
|
|
}
|
|
|
|
if( Flag == 0 ) {
|
|
return EFI_ABORTED;
|
|
}
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Search the EFI Variable Base address.
|
|
|
|
According the known GUID gEfiSystemNvDataFvGuid to get the base address from FFS.
|
|
|
|
@param Fv the Pointer to the FFS
|
|
@param Length the length of Fv
|
|
@param Offset the Pointer to the Addr (Offset)
|
|
@param NumOfMachingOffset the number of IFR array in one FFS
|
|
|
|
@retval EFI_SUCCESS Get the address successfully.
|
|
@retval EFI_ABORTED An error occured.
|
|
**/
|
|
EFI_STATUS
|
|
SearchEfiVarInFFS (
|
|
IN VOID *Fv,
|
|
IN UINTN Length,
|
|
OUT UINTN **Offset,
|
|
OUT UINT8 *NumOfMachingOffset
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINT8 Index;
|
|
|
|
Status = EFI_SUCCESS;
|
|
Index = 0;
|
|
|
|
if ((Fv == NULL) || (Offset == NULL)) {
|
|
printf ("The FV or offset is NULL.");
|
|
return EFI_ABORTED;
|
|
}
|
|
Status = GetVariableAddressByGuid (
|
|
Fv,
|
|
&gEfiSystemNvDataFvGuid,
|
|
Length,
|
|
Offset,
|
|
NumOfMachingOffset
|
|
);
|
|
if (Status != EFI_SUCCESS) {
|
|
return EFI_ABORTED;
|
|
}
|
|
//
|
|
//Transfer the offset to the VA address.
|
|
//
|
|
while (Index < *NumOfMachingOffset) {
|
|
*(*Offset + Index) = (UINTN) Fv + *(*Offset + Index);
|
|
Index++;
|
|
}
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Parse the Ffs header to get the size.
|
|
|
|
@param InputFile The pointer to the input file
|
|
@param FvSize The pointer to the file size
|
|
|
|
@return EFI_SUCCESS Get the file size successfully
|
|
**/
|
|
EFI_STATUS
|
|
ReadFfsHeader (
|
|
IN FILE *InputFile,
|
|
OUT UINT32 *FvSize
|
|
)
|
|
{
|
|
EFI_FFS_FILE_HEADER FfsHeader;
|
|
EFI_FV_FILETYPE Type;
|
|
|
|
//
|
|
// Check input parameters
|
|
//
|
|
if ((InputFile == NULL) || (FvSize == NULL)) {
|
|
return EFI_ABORTED;
|
|
}
|
|
//
|
|
// Read the header
|
|
//
|
|
fread (
|
|
&FfsHeader,
|
|
sizeof (EFI_FFS_FILE_HEADER),
|
|
1,
|
|
InputFile
|
|
);
|
|
Type = FfsHeader.Type;
|
|
|
|
if (Type == EFI_FV_FILETYPE_DRIVER) {
|
|
*FvSize = *(UINT32 *)FfsHeader.Size & 0xffffff;
|
|
} else if (Type == EFI_FV_FILETYPE_APPLICATION) {
|
|
*FvSize = *(UINT32 *)FfsHeader.Size & 0xffffff;
|
|
} else if (Type == EFI_FV_FILETYPE_FREEFORM) {
|
|
*FvSize = *(UINT32 *)FfsHeader.Size & 0xffffff;
|
|
} else {
|
|
return EFI_ABORTED;
|
|
}
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
Read the length of the whole FD
|
|
|
|
This function determines the size of the FV.
|
|
|
|
@param InputFile The file that contains the FV image.
|
|
@param FvSize The size of the FV.
|
|
|
|
@retval EFI_SUCCESS The application exited normally.
|
|
@retval EFI_ABORTED An error occurred.
|
|
|
|
**/
|
|
static
|
|
EFI_STATUS
|
|
ReadFdHeader (
|
|
IN FILE *InputFile,
|
|
OUT UINT32 *FvSize
|
|
)
|
|
{
|
|
//
|
|
// Check input parameters
|
|
//
|
|
if ((InputFile == NULL) || (FvSize == NULL)) {
|
|
return EFI_ABORTED;
|
|
}
|
|
*FvSize = 0;
|
|
//
|
|
// Get the total size of FD file (Fixed the length)
|
|
//
|
|
fseek(InputFile,0,SEEK_END);
|
|
*FvSize = ftell(InputFile);
|
|
fseek(InputFile,0,SEEK_SET);
|
|
|
|
if (*FvSize == 0) {
|
|
return EFI_ABORTED;
|
|
}
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Read the file to memory.
|
|
|
|
@param InputFile The file that contains the FV image.
|
|
@param Size The size of the file.
|
|
|
|
@retval The pointer to the begining position of memory.
|
|
**/
|
|
VOID *
|
|
ReadFileToMemory (
|
|
IN CHAR8 *FileName,
|
|
OUT UINT32 *Size
|
|
)
|
|
{
|
|
FILE *InFile;
|
|
VOID *Address;
|
|
UINT32 BytesRead;
|
|
EFI_STATUS Status;
|
|
|
|
InFile = NULL;
|
|
Address = NULL;
|
|
BytesRead = 0;
|
|
Status = EFI_SUCCESS;
|
|
|
|
InFile = fopen (FileName,"rb");
|
|
if (InFile == NULL) {
|
|
return NULL;
|
|
}
|
|
//
|
|
// Determine the size of FV
|
|
//
|
|
Status = ReadFdHeader (InFile, Size);
|
|
if (Status != EFI_SUCCESS) {
|
|
fclose (InFile);
|
|
return NULL;
|
|
}
|
|
//
|
|
// Allocate a buffer for the FV image
|
|
//
|
|
Address = malloc (*Size);
|
|
if (Address == NULL) {
|
|
fclose (InFile);
|
|
return NULL;
|
|
}
|
|
memset (Address, 0, *Size);
|
|
//
|
|
// Seek to the start of the image, then read the entire FV to the buffer
|
|
//
|
|
fseek (InFile, 0, SEEK_SET);
|
|
BytesRead = fread (Address, 1, *Size, InFile);
|
|
fclose (InFile);
|
|
if ((UINTN) BytesRead != *Size) {
|
|
free (Address);
|
|
return NULL;
|
|
}
|
|
return Address;
|
|
}
|
|
|
|
/**
|
|
Search the EFI variables address in Fd.
|
|
|
|
Open and read the *.fd to the memory, initialize the global structure.
|
|
Update the EFI variables addr and the begining position of memory.
|
|
|
|
@retval EFI_SUCCESS Get the address successfully.
|
|
**/
|
|
EFI_STATUS
|
|
GetEfiVariablesAddr (
|
|
BOOLEAN UqiIsSet
|
|
)
|
|
{
|
|
VOID *FdImage;
|
|
UINT32 FdSize;
|
|
EFI_STATUS Status;
|
|
UINTN *EfiVarAddr;
|
|
UINT8 NumOfMachingVar;
|
|
UINT32 Index;
|
|
BOOLEAN GotFlag;
|
|
EFI_FIRMWARE_VOLUME_HEADER *Variable;
|
|
BOOLEAN AuthencitatedMonotonicOrNot;
|
|
BOOLEAN AuthencitatedBasedTimeOrNot;
|
|
BOOLEAN NormalOrNot;
|
|
|
|
FdImage = NULL;
|
|
FdSize = 0;
|
|
Status = EFI_SUCCESS;
|
|
EfiVarAddr = NULL;
|
|
NumOfMachingVar = 0;
|
|
Index = 0;
|
|
GotFlag = TRUE;
|
|
Variable = NULL;
|
|
|
|
FdImage = ReadFileToMemory (mInputFdName, &FdSize);
|
|
if (FdImage == NULL) {
|
|
return EFI_ABORTED;
|
|
}
|
|
if (!UqiIsSet) {
|
|
Status = SearchNvStoreDatabaseInFd(FdImage, FdSize);
|
|
if (EFI_ERROR (Status)) {
|
|
return EFI_ABORTED;
|
|
}
|
|
}
|
|
Status = SearchEfiVarInFFS (
|
|
FdImage,
|
|
FdSize,
|
|
&EfiVarAddr,
|
|
&NumOfMachingVar
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return EFI_ABORTED;
|
|
}
|
|
//
|
|
// Check the signature "_FVH"
|
|
//
|
|
Index = 0;
|
|
GotFlag = FALSE;
|
|
|
|
while (Index < NumOfMachingVar) {
|
|
Variable = (EFI_FIRMWARE_VOLUME_HEADER *)(*(EfiVarAddr + Index) - 0x20);
|
|
if (Variable->Signature == 0x4856465F) {
|
|
AuthencitatedMonotonicOrNot = CheckMonotonicBasedVarStore ((UINT8 *)Variable + Variable->HeaderLength);
|
|
AuthencitatedBasedTimeOrNot = CheckTimeBasedVarStoreOrNot ((UINT8 *)Variable + Variable->HeaderLength);
|
|
NormalOrNot = CheckNormalVarStoreOrNot ((UINT8 *)Variable + Variable->HeaderLength);
|
|
if (AuthencitatedMonotonicOrNot || AuthencitatedBasedTimeOrNot || NormalOrNot) {
|
|
GotFlag = TRUE;
|
|
gEfiFdInfo.EfiVariableAddr = (UINTN)Variable;
|
|
break;
|
|
}
|
|
}
|
|
Index++;
|
|
}
|
|
free (EfiVarAddr);
|
|
if (!GotFlag) {
|
|
return EFI_ABORTED;
|
|
}
|
|
gEfiFdInfo.Fd = FdImage;
|
|
gEfiFdInfo.FdSize = FdSize;
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Pick up the FFS which includes IFR section.
|
|
|
|
Parse all FFS extracted by BfmLib, and save all which includes IFR
|
|
Binary to gEfiFdInfo structure.
|
|
|
|
@retval EFI_SUCCESS Get the address successfully.
|
|
@retval EFI_BUFFER_TOO_SMALL Memory can't be allocated.
|
|
@retval EFI_ABORTED Read FFS Failed.
|
|
**/
|
|
EFI_STATUS
|
|
FindFileInFolder (
|
|
IN CHAR8 *FolderName,
|
|
OUT BOOLEAN *ExistStorageInBfv,
|
|
OUT BOOLEAN *SizeOptimized
|
|
)
|
|
{
|
|
CHAR8 *FileName;
|
|
CHAR8 *CurFolderName;
|
|
EFI_STATUS Status;
|
|
UINTN MaxFileNameLen;
|
|
UINTN Index;
|
|
CHAR8 FileNameArry[MAX_FILENAME_LEN];
|
|
FILE *FfsFile;
|
|
UINTN FileSize;
|
|
VOID *FfsImage;
|
|
UINTN BytesRead;
|
|
#ifndef __GNUC__
|
|
HANDLE FindHandle;
|
|
WIN32_FIND_DATA FindFileData;
|
|
#else
|
|
struct dirent *pDirent;
|
|
DIR *pDir;
|
|
#endif
|
|
|
|
FileName = NULL;
|
|
CurFolderName = NULL;
|
|
Status = EFI_SUCCESS;
|
|
MaxFileNameLen = 0;
|
|
Index = 0;
|
|
FileSize = 0;
|
|
BytesRead = 0;
|
|
FfsImage = NULL;
|
|
FfsFile = NULL;
|
|
|
|
MaxFileNameLen = strlen (FolderName) + MAX_FILENAME_LEN;
|
|
CurFolderName = (CHAR8 *)calloc(
|
|
strlen (FolderName) + strlen (OS_SEP_STR) + strlen ("*.*")+ 1,
|
|
sizeof(CHAR8)
|
|
);
|
|
if (CurFolderName == NULL) {
|
|
return EFI_BUFFER_TOO_SMALL;
|
|
}
|
|
strcpy (CurFolderName, FolderName);
|
|
strcat (CurFolderName, OS_SEP_STR);
|
|
strcat (CurFolderName, "*.*");
|
|
FileName = (CHAR8 *)calloc(
|
|
MaxFileNameLen,
|
|
sizeof(CHAR8)
|
|
);
|
|
if (FileName == NULL) {
|
|
free (CurFolderName);
|
|
return EFI_BUFFER_TOO_SMALL;
|
|
}
|
|
|
|
#ifndef __GNUC__
|
|
if((FindHandle = FindFirstFile(CurFolderName, &FindFileData)) != INVALID_HANDLE_VALUE){
|
|
do {
|
|
memset (FileName, 0, MaxFileNameLen);
|
|
if ((strcmp (FindFileData.cFileName, ".") == 0)
|
|
|| (strcmp (FindFileData.cFileName, "..") == 0)
|
|
) {
|
|
continue;
|
|
}
|
|
if (strlen(FolderName) + strlen ("\\") + strlen (FindFileData.cFileName) > MAX_FILENAME_LEN - 1) {
|
|
Status = EFI_ABORTED;
|
|
goto Done;
|
|
}
|
|
snprintf (FileNameArry, MAX_FILENAME_LEN, "%s%c%s", FolderName, OS_SEP, FindFileData.cFileName);
|
|
FfsFile = fopen (FileNameArry, "rb");
|
|
if (FfsFile == NULL) {
|
|
Status = EFI_ABORTED;
|
|
goto Done;
|
|
}
|
|
Status = ReadFfsHeader (FfsFile, (UINT32 *)&FileSize);
|
|
if (EFI_ERROR (Status)) {
|
|
fclose (FfsFile);
|
|
Status = EFI_SUCCESS;
|
|
continue;
|
|
}
|
|
//
|
|
// Allocate a buffer for the FFS file
|
|
//
|
|
FfsImage = malloc (FileSize);
|
|
if (FfsImage == NULL) {
|
|
fclose (FfsFile);
|
|
Status = EFI_BUFFER_TOO_SMALL;
|
|
goto Done;
|
|
}
|
|
//
|
|
// Seek to the start of the image, then read the entire FV to the buffer
|
|
//
|
|
fseek (FfsFile, 0, SEEK_SET);
|
|
BytesRead = fread (FfsImage, 1, FileSize, FfsFile);
|
|
fclose (FfsFile);
|
|
|
|
if ((UINTN) BytesRead != FileSize) {
|
|
free (FfsImage);
|
|
Status = EFI_ABORTED;
|
|
goto Done;
|
|
}
|
|
//
|
|
// Check whether exists the storage ffs in BFV for multi-platform mode
|
|
//
|
|
if (CompareGuid(&gEfiFfsBfvForMultiPlatformGuid,(EFI_GUID *) FfsImage) == 0) {
|
|
*ExistStorageInBfv = TRUE;
|
|
*SizeOptimized = FALSE;
|
|
gEfiFdInfo.StorageFfsInBfv = FfsImage;
|
|
continue;
|
|
}
|
|
//
|
|
// Check whether exists the optimized storage ffs in BFV for multi-platform mode
|
|
//
|
|
if (CompareGuid(&gEfiFfsBfvForMultiPlatformGuid2,(EFI_GUID *) FfsImage) == 0) {
|
|
*ExistStorageInBfv = TRUE;
|
|
*SizeOptimized = TRUE;
|
|
gEfiFdInfo.StorageFfsInBfv = FfsImage;
|
|
continue;
|
|
}
|
|
//
|
|
// Check whether current FFS includes IFR
|
|
//
|
|
Status = GetAddressByGuid (
|
|
FfsImage,
|
|
&gVfrArrayAttractGuid,
|
|
FileSize,
|
|
NULL,
|
|
NULL
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
free (FfsImage);
|
|
Status = EFI_SUCCESS;
|
|
} else {
|
|
//
|
|
// Check whether existed same IFR binary. If existed, not insert the new one.
|
|
//
|
|
if (NotExistSameFfsIfr (FfsImage)) {
|
|
gEfiFdInfo.FfsArray[Index] = FfsImage;
|
|
gEfiFdInfo.Length[Index++] = FileSize;
|
|
}
|
|
}
|
|
|
|
} while (FindNextFile (FindHandle, &FindFileData));
|
|
FindClose(FindHandle);
|
|
} else {
|
|
Status = EFI_ABORTED;
|
|
goto Done;
|
|
}
|
|
|
|
Done:
|
|
free (CurFolderName);
|
|
free (FileName);
|
|
|
|
#else
|
|
if((pDir = opendir(FolderName)) != NULL){
|
|
while ((pDirent = readdir(pDir)) != NULL){
|
|
memset (FileName, 0, MaxFileNameLen);
|
|
if ((strcmp (pDirent->d_name, ".") == 0)
|
|
|| (strcmp (pDirent->d_name, "..") == 0)
|
|
) {
|
|
continue;
|
|
}
|
|
sprintf (FileNameArry, "%s%c%s", FolderName, OS_SEP, pDirent->d_name);
|
|
FfsFile = fopen (FileNameArry, "rb");
|
|
Status = ReadFfsHeader (FfsFile, (UINT32 *)&FileSize);
|
|
if (EFI_ERROR (Status)) {
|
|
fclose (FfsFile);
|
|
Status = EFI_SUCCESS;
|
|
continue;
|
|
}
|
|
//
|
|
// Allocate a buffer for the FFS file
|
|
//
|
|
FfsImage = malloc (FileSize);
|
|
if (FfsImage == NULL) {
|
|
fclose (FfsFile);
|
|
Status = EFI_BUFFER_TOO_SMALL;
|
|
goto Done;
|
|
}
|
|
//
|
|
// Seek to the start of the image, then read the entire FV to the buffer
|
|
//
|
|
fseek (FfsFile, 0, SEEK_SET);
|
|
BytesRead = fread (FfsImage, 1, FileSize, FfsFile);
|
|
fclose (FfsFile);
|
|
|
|
if ((UINTN) BytesRead != FileSize) {
|
|
free (FfsImage);
|
|
Status = EFI_ABORTED;
|
|
goto Done;
|
|
}
|
|
//
|
|
// Check whether exists the storage ffs in BFV for multi-platform mode
|
|
//
|
|
if (CompareGuid(&gEfiFfsBfvForMultiPlatformGuid,(EFI_GUID *) FfsImage) == 0) {
|
|
*ExistStorageInBfv = TRUE;
|
|
*SizeOptimized = FALSE;
|
|
gEfiFdInfo.StorageFfsInBfv = FfsImage;
|
|
continue;
|
|
}
|
|
//
|
|
// Check whether exists the optimized storage ffs in BFV for multi-platform mode
|
|
//
|
|
if (CompareGuid(&gEfiFfsBfvForMultiPlatformGuid2,(EFI_GUID *) FfsImage) == 0) {
|
|
*ExistStorageInBfv = TRUE;
|
|
*SizeOptimized = TRUE;
|
|
gEfiFdInfo.StorageFfsInBfv = FfsImage;
|
|
continue;
|
|
}
|
|
//
|
|
// Check whether current FFS includes IFR
|
|
//
|
|
Status = GetAddressByGuid (
|
|
FfsImage,
|
|
&gVfrArrayAttractGuid,
|
|
FileSize,
|
|
NULL,
|
|
NULL
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
free (FfsImage);
|
|
Status = EFI_SUCCESS;
|
|
} else {
|
|
//
|
|
// Check whether existed same IFR binary. If existed, not insert the new one.
|
|
//
|
|
if (NotExistSameFfsIfr (FfsImage)) {
|
|
gEfiFdInfo.FfsArray[Index] = FfsImage;
|
|
gEfiFdInfo.Length[Index++] = FileSize;
|
|
}
|
|
}
|
|
|
|
}
|
|
closedir(pDir);
|
|
} else {
|
|
Status = EFI_ABORTED;
|
|
goto Done;
|
|
}
|
|
|
|
Done:
|
|
free (CurFolderName);
|
|
free (FileName);
|
|
#endif
|
|
return Status;
|
|
}
|
|
|