mirror of
https://github.com/acidanthera/audk.git
synced 2025-05-03 06:00:10 +02:00
BmfLib is added for FCE tool. 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>
4356 lines
123 KiB
C
4356 lines
123 KiB
C
/** @file
|
|
|
|
Library to process EFI image.
|
|
|
|
Copyright (c) 2011-2019, Intel Corporation. All rights reserved.<BR>
|
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
|
|
**/
|
|
|
|
#include "BinFileManager.h"
|
|
|
|
#define EFI_TEST_FFS_ATTRIBUTES_BIT(FvbAttributes, TestAttributes, Bit) \
|
|
( \
|
|
(BOOLEAN) ( \
|
|
(FvbAttributes & EFI_FVB2_ERASE_POLARITY) ? (((~TestAttributes) & Bit) == Bit) : ((TestAttributes & Bit) == Bit) \
|
|
) \
|
|
)
|
|
|
|
#ifndef __GNUC__
|
|
#define DECODE_STR "%s -d -o \"%s\" \"%s\" > NUL"
|
|
#define ENCODE_STR "%s -e \"%s\" -o \"%s\" > NUL"
|
|
#define GENSEC_COMPRESSION "GenSec -s %s -c %s \"%s\" -o \"%s\" > NUL"
|
|
#define GENSEC_GUID "GenSec -s %s -r PROCESSING_REQUIRED -g %s \"%s\" -o \"%s\" > NUL"
|
|
#define GENSEC_STR "GenSec -s %s \"%s\" -o \"%s\" > NUL"
|
|
#define GENSEC_ALIGN "GenSec --sectionalign 16 \"%s\" -o \"%s\" > NUL"
|
|
#define GENFV_STR "GenFv -i \"%s\" -o \"%s\" > NUL"
|
|
#define GENFV_FVGUID "GenFv -i \"%s\" -o \"%s\" --FvNameGuid %s > NUL"
|
|
#define GENFV_FFS "GenFv -f \"%s\" -g %s -o \"%s\" > NUL"
|
|
#define GENFFS_STR "GenFfs -t %s -i \"%s\" -g %s -o \"%s\" > NUL"
|
|
#define GENFFS_FIX "GenFfs -t %s -i \"%s\" -g %s -x -o \"%s\" > NUL"
|
|
#else
|
|
#define DECODE_STR "%s -d -o \"%s\" \"%s\" > /dev/null"
|
|
#define ENCODE_STR "%s -e \"%s\" -o \"%s\" > /dev/null"
|
|
#define GENSEC_COMPRESSION "GenSec -s %s -c %s \"%s\" -o \"%s\" > /dev/null"
|
|
#define GENSEC_GUID "GenSec -s %s -r PROCESSING_REQUIRED -g %s \"%s\" -o \"%s\" > /dev/null"
|
|
#define GENSEC_STR "GenSec -s %s \"%s\" -o \"%s\" > /dev/null"
|
|
#define GENSEC_ALIGN "GenSec --sectionalign 16 \"%s\" -o \"%s\" > /dev/null"
|
|
#define GENFV_STR "GenFv -i \"%s\" -o \"%s\" > /dev/null"
|
|
#define GENFV_FVGUID "GenFv -i \"%s\" -o \"%s\" --FvNameGuid %s > /dev/null"
|
|
#define GENFV_FFS "GenFv -f \"%s\" -g %s -o \"%s\" > /dev/null"
|
|
#define GENFFS_STR "GenFfs -t %s -i \"%s\" -g %s -o \"%s\" > /dev/null"
|
|
#define GENFFS_FIX "GenFfs -t %s -i \"%s\" -g %s -x -o \"%s\" > /dev/null"
|
|
#endif
|
|
|
|
#define DECODE_STR_ERR "%s -d -o \"%s\" \"%s\" "
|
|
#define ENCODE_STR_ERR "%s -e \"%s\" -o \"%s\" "
|
|
|
|
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 };
|
|
extern CHAR8* mGuidToolDefinition;
|
|
UINT32 PadSizeOfBfv;
|
|
|
|
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
|
|
};
|
|
|
|
FV_INFORMATION *
|
|
LibInitializeFvStruct (
|
|
FV_INFORMATION *Fv
|
|
)
|
|
{
|
|
UINT32 Index;
|
|
|
|
if (Fv == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
memset (Fv, '\0', sizeof (FV_INFORMATION));
|
|
|
|
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);
|
|
|
|
Fv->FfsAttuibutes[Index].IsLeaf = TRUE;
|
|
Fv->FfsAttuibutes[Index].TotalSectionNum = 0;
|
|
}
|
|
|
|
Fv->PatchData = NULL;
|
|
Fv->EncapData = NULL;
|
|
Fv->FvNext = NULL;
|
|
Fv->FvLevel = 0;
|
|
Fv->IsBfvFlag = FALSE;
|
|
Fv->IsInputFvFlag = FALSE;
|
|
|
|
return Fv;
|
|
}
|
|
|
|
/**
|
|
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;
|
|
}
|
|
|
|
EFI_STATUS
|
|
LibFindFvInFd (
|
|
IN FILE *InputFile,
|
|
IN OUT FIRMWARE_DEVICE **FdData
|
|
)
|
|
{
|
|
FIRMWARE_DEVICE *LocalFdData;
|
|
UINT16 Index;
|
|
CHAR8 Ffs2Guid[16];
|
|
CHAR8 SignatureCheck[4];
|
|
CHAR8 Signature[5] = "_FVH";
|
|
FV_INFORMATION *CurrentFv;
|
|
FV_INFORMATION *NewFoundFv;
|
|
BOOLEAN FirstMatch;
|
|
UINT32 FdSize;
|
|
UINT16 FvCount;
|
|
VOID *FdBuffer;
|
|
VOID *FdBufferOri;
|
|
UINT32 Count;
|
|
|
|
|
|
CurrentFv = NULL;
|
|
NewFoundFv = NULL;
|
|
FdBuffer = NULL;
|
|
FdBufferOri = NULL;
|
|
FirstMatch = TRUE;
|
|
Index = 0;
|
|
FdSize = 0;
|
|
FvCount = 0;
|
|
Count = 0;
|
|
LocalFdData = NULL;
|
|
|
|
if (InputFile == NULL) {
|
|
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 *) calloc (sizeof (FIRMWARE_DEVICE), sizeof(UINT8));
|
|
if (LocalFdData == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
LocalFdData->Fv = (FV_INFORMATION *) calloc (sizeof (FV_INFORMATION), sizeof(UINT8));
|
|
if (LocalFdData->Fv == NULL) {
|
|
free (LocalFdData);
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
LibInitializeFvStruct (LocalFdData->Fv);
|
|
|
|
//
|
|
// Readout the FD file data to buffer.
|
|
//
|
|
FdBuffer = malloc (FdSize);
|
|
|
|
if (FdBuffer == NULL) {
|
|
free (LocalFdData->Fv);
|
|
free (LocalFdData);
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
if (fread (FdBuffer, 1, FdSize, InputFile) != FdSize) {
|
|
free (LocalFdData->Fv);
|
|
free (LocalFdData);
|
|
free (FdBuffer);
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
FdBufferOri = FdBuffer;
|
|
|
|
for (Count=0; Count < FdSize - 4; Count++) {
|
|
//
|
|
// Copy 4 bytes of fd data to check the _FVH signature
|
|
//
|
|
memcpy (SignatureCheck, FdBuffer, 4);
|
|
FdBuffer =(UINT8 *)FdBuffer + 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.
|
|
// Turn back 28 bytes to find the GUID.
|
|
//
|
|
FdBuffer = (UINT8 *)FdBuffer - 28;
|
|
memcpy (Ffs2Guid, FdBuffer, 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;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Point to the original address
|
|
//
|
|
FdBuffer = (UINT8 *)FdBuffer + 28;
|
|
|
|
//
|
|
// Here we found an FV.
|
|
//
|
|
if (Index == 16) {
|
|
if (FirstMatch) {
|
|
LocalFdData->Fv->ImageAddress = (UINTN)((UINT8 *)FdBuffer - (UINT8 *)FdBufferOri) - 0x2c;
|
|
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 (NULL == NewFoundFv) {
|
|
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) - 0x2c;
|
|
|
|
//
|
|
// 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 ++;
|
|
Index = 0;
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// We need to turn back 3 bytes.
|
|
//
|
|
FdBuffer = (UINT8 *)FdBuffer - 3;
|
|
}
|
|
|
|
LocalFdData->Size = FdSize;
|
|
|
|
*FdData = LocalFdData;
|
|
|
|
free (FdBufferOri);
|
|
|
|
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) {
|
|
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;
|
|
}
|
|
|
|
/**
|
|
|
|
Expands the 3 byte size commonly used in Firmware Volume data structures
|
|
|
|
@param[in] Size - Address of the 3 byte array representing the size
|
|
|
|
@return UINT32
|
|
|
|
**/
|
|
UINT32
|
|
FvBufExpand3ByteSize (
|
|
IN VOID* Size
|
|
)
|
|
{
|
|
return (((UINT8*)Size)[2] << 16) +
|
|
(((UINT8*)Size)[1] << 8) +
|
|
((UINT8*)Size)[0];
|
|
}
|
|
|
|
/**
|
|
|
|
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;
|
|
}
|
|
/**
|
|
|
|
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;
|
|
}
|
|
|
|
/*
|
|
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;
|
|
CHAR8 TempBuf[_MAX_PATH];
|
|
|
|
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) {
|
|
printf ("The directory is too long \n");
|
|
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 (NULL == FfsFileName) {
|
|
return EFI_ABORTED;
|
|
}
|
|
memset (FfsFileName, '\0', _MAX_PATH);
|
|
FfsFileSize = GetFfsFileLength ((EFI_FFS_FILE_HEADER *) CurrentFile);
|
|
|
|
sprintf (
|
|
TempBuf,
|
|
"-Num%d-%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X-Level%d",
|
|
*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
|
|
);
|
|
if (strlen (TempDir) + strlen (OS_SEP_STR) + strlen (TEMP_DIR_NAME) + strlen(TempBuf) > _MAX_PATH - 1) {
|
|
free(FfsFileName);
|
|
printf ("The directory is too long \n");
|
|
return EFI_ABORTED;
|
|
}
|
|
strcpy (FfsFileName, TempDir);
|
|
strncat (FfsFileName, OS_SEP_STR, _MAX_PATH - strlen (FfsFileName) - 1);
|
|
strncat (FfsFileName, CurrentFv->FvName, _MAX_PATH - strlen (FfsFileName) - 1);
|
|
strncat (FfsFileName, TempBuf, _MAX_PATH - strlen (FfsFileName) - 1);
|
|
|
|
memcpy (CurrentFv->FfsAttuibutes[*FfsCount].FfsName, FfsFileName, strlen(FfsFileName));
|
|
|
|
//
|
|
// Update current FFS files file state.
|
|
//
|
|
if (ErasePolarity) {
|
|
CurrentFile->State = (UINT8)~(CurrentFile->State);
|
|
}
|
|
|
|
FfsFile = fopen (FfsFileName, "wb+");
|
|
if (FfsFile == NULL) {
|
|
free(FfsFileName);
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
if (fwrite (CurrentFile, 1, FfsFileSize, FfsFile) != FfsFileSize) {
|
|
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;
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
LibCheckPadFfsContainFvNameGuid (
|
|
IN FV_INFORMATION *CurrentFv,
|
|
IN EFI_FFS_FILE_HEADER2 *CurrentFile
|
|
)
|
|
{
|
|
UINT32 FfsFileSize;
|
|
UINT32 FfsDataSize;
|
|
EFI_GUID *FfsData;
|
|
ENCAP_INFO_DATA *LocalEncapData;
|
|
|
|
LocalEncapData = NULL;
|
|
|
|
FfsFileSize = GetFfsFileLength ((EFI_FFS_FILE_HEADER *) CurrentFile);
|
|
FfsDataSize = FfsFileSize - GetFfsHeaderLength ((EFI_FFS_FILE_HEADER *) CurrentFile);
|
|
FfsData = (EFI_GUID *) ((INT8 *)CurrentFile + GetFfsHeaderLength ((EFI_FFS_FILE_HEADER *) CurrentFile));
|
|
|
|
if (FfsDataSize == 0) {
|
|
return TRUE;
|
|
}
|
|
|
|
LocalEncapData = CurrentFv->EncapData;
|
|
|
|
do {
|
|
if (LocalEncapData->FvExtHeader != NULL) {
|
|
if (CompareGuid(FfsData, &LocalEncapData->FvExtHeader->FvName) == 0) {
|
|
return TRUE;
|
|
}
|
|
}
|
|
LocalEncapData = LocalEncapData->NextNode;
|
|
} while (LocalEncapData->NextNode != NULL);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOLEAN
|
|
LibCheckPadFfsNotNull (
|
|
IN EFI_FFS_FILE_HEADER2 *CurrentFile
|
|
)
|
|
{
|
|
UINT32 FfsFileSize;
|
|
UINT32 FfsDataSize;
|
|
INT8 *FfsData;
|
|
|
|
FfsFileSize = GetFfsFileLength ((EFI_FFS_FILE_HEADER *) CurrentFile);
|
|
FfsDataSize = FfsFileSize - GetFfsHeaderLength ((EFI_FFS_FILE_HEADER *) CurrentFile);
|
|
FfsData = (INT8 *)CurrentFile + GetFfsHeaderLength ((EFI_FFS_FILE_HEADER *) CurrentFile);
|
|
|
|
if (FfsDataSize == 0) {
|
|
return FALSE;
|
|
}
|
|
|
|
while (FfsDataSize > 0) {
|
|
if (((FfsData[FfsDataSize-1]) & 0xFF) != 0xFF) {
|
|
return TRUE;
|
|
}
|
|
FfsDataSize--;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/**
|
|
Find a maximum length of free space in PAD FFS of Bfv.
|
|
|
|
@PadFfsHeader - The header of PAD FFS file
|
|
|
|
@return The length of free space
|
|
|
|
**/
|
|
UINT32
|
|
GetBfvMaxFreeSpace (
|
|
IN EFI_FFS_FILE_HEADER2 *PadFfsHeader
|
|
)
|
|
{
|
|
UINT32 FfsSize;
|
|
UINT32 Count;
|
|
UINT32 Index;
|
|
UINT32 MaxSize;
|
|
UINT32 HeaderSize;
|
|
|
|
Index = 0;
|
|
MaxSize = 0;
|
|
|
|
if (PadFfsHeader == NULL) {
|
|
return MaxSize;
|
|
}
|
|
|
|
FfsSize = GetFfsFileLength ((EFI_FFS_FILE_HEADER *) PadFfsHeader);
|
|
HeaderSize = GetFfsHeaderLength ((EFI_FFS_FILE_HEADER *) PadFfsHeader);
|
|
|
|
for (Count = HeaderSize; Count < FfsSize; Count++) {
|
|
if (((((INT8 *)PadFfsHeader)[Count]) & 0xFF) == 0xFF) {
|
|
Index++;
|
|
} else {
|
|
if (Index > MaxSize) {
|
|
MaxSize = Index;
|
|
}
|
|
Index = 0;
|
|
}
|
|
}
|
|
return MaxSize;
|
|
}
|
|
|
|
|
|
/**
|
|
|
|
Get the Offset and data of PAD FFS file in FV file.
|
|
This function should be only called for find an PAD FFS contain additional data
|
|
(usually will contain FIT table data or reset vector.)
|
|
|
|
BFV:
|
|
---------------------- <- Low
|
|
| |
|
|
| |
|
|
-----------------------
|
|
| FFSs ... |
|
|
-----------------------
|
|
| |
|
|
| |
|
|
-----------------------
|
|
| PAD FFS file |
|
|
| |
|
|
| reset vector |
|
|
| |
|
|
| FIT table |
|
|
-----------------------
|
|
| SEC CORE | <- High
|
|
-----------------------
|
|
|
|
**/
|
|
|
|
EFI_STATUS
|
|
LibFindResetVectorAndFitTableData(
|
|
IN EFI_FIRMWARE_VOLUME_HEADER *FvImage,
|
|
IN EFI_FFS_FILE_HEADER2 *CurrentFile,
|
|
IN OUT FV_INFORMATION *CurrentFv
|
|
)
|
|
{
|
|
UINT32 Count1;
|
|
UINT32 Count2;
|
|
UINT32 FfsFileSize;
|
|
BOOLEAN FfsFoundFlag;
|
|
UINT32 FfsOffset;
|
|
UINT32 DataOffset;
|
|
UINT32 HeaderSize;
|
|
PATCH_DATA_PAD_FFS *LocalPatchData;
|
|
|
|
FfsFileSize = 0;
|
|
Count1 = 0;
|
|
Count2 = 0;
|
|
FfsOffset = 0;
|
|
DataOffset = 0;
|
|
FfsFoundFlag = FALSE;
|
|
LocalPatchData = NULL;
|
|
|
|
if (CurrentFv == NULL || CurrentFile == NULL || FvImage == NULL) {
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
FfsFileSize = GetFfsFileLength ((EFI_FFS_FILE_HEADER *) CurrentFile);
|
|
HeaderSize = GetFfsHeaderLength ((EFI_FFS_FILE_HEADER *) CurrentFile);
|
|
|
|
for (Count1=0; Count1 < (FvImage->FvLength - FfsFileSize); Count1 ++) {
|
|
for (Count2=0; Count2 < FfsFileSize; Count2 ++) {
|
|
if (((INT8*)FvImage)[Count1 + Count2] != ((INT8 *) CurrentFile)[Count2]){
|
|
break;
|
|
}
|
|
}
|
|
if (Count2 == FfsFileSize) {
|
|
FfsFoundFlag = TRUE;
|
|
FfsOffset = Count1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (FfsFoundFlag) {
|
|
//
|
|
// Find data in FFS file;
|
|
// Will skip FFS header;
|
|
//
|
|
for (Count1 = HeaderSize; Count1 < FfsFileSize; Count1++) {
|
|
if (((((INT8 *)CurrentFile)[Count1]) & 0xFF) != 0xFF) {
|
|
DataOffset = FfsOffset + Count1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (CurrentFv->PatchData == NULL) {
|
|
//
|
|
// First time found data.
|
|
//
|
|
CurrentFv->PatchData = (PATCH_DATA_PAD_FFS *) malloc (sizeof (PATCH_DATA_PAD_FFS));
|
|
if (CurrentFv->PatchData == NULL) {
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
CurrentFv->PatchData->Offset = DataOffset;
|
|
CurrentFv->PatchData->Data = malloc(FfsFileSize - Count1);
|
|
CurrentFv->PatchData->Length = FfsFileSize - Count1;
|
|
CurrentFv->PatchData->NextNode = NULL;
|
|
|
|
if (CurrentFv->PatchData->Data == NULL) {
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
memcpy (CurrentFv->PatchData->Data, (INT8 *)CurrentFile + Count1, FfsFileSize - Count1);
|
|
} else {
|
|
LocalPatchData = CurrentFv->PatchData;
|
|
|
|
while (LocalPatchData->NextNode != NULL) {
|
|
LocalPatchData = LocalPatchData->NextNode;
|
|
}
|
|
|
|
LocalPatchData = (PATCH_DATA_PAD_FFS *) malloc (sizeof (PATCH_DATA_PAD_FFS));
|
|
|
|
if (LocalPatchData == NULL) {
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
LocalPatchData->Offset = DataOffset;
|
|
LocalPatchData->Data = malloc(FfsFileSize - Count1);
|
|
LocalPatchData->Length = FfsFileSize - Count1;
|
|
LocalPatchData->NextNode = NULL;
|
|
|
|
if (LocalPatchData->Data == NULL) {
|
|
free (LocalPatchData);
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
memcpy (LocalPatchData->Data, (INT8 *)CurrentFile + Count1, FfsFileSize - Count1);
|
|
while (CurrentFv->PatchData->NextNode != NULL) {
|
|
CurrentFv->PatchData = CurrentFv->PatchData->NextNode;
|
|
}
|
|
CurrentFv->PatchData->NextNode = LocalPatchData;
|
|
}
|
|
|
|
} else {
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
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 (NULL == RetStr) {
|
|
return NULL;
|
|
}
|
|
|
|
memset (RetStr , '\0', Count + 1);
|
|
|
|
for (Index=0; Index <= Count -1; Index ++) {
|
|
RetStr[Index] = ' ';
|
|
}
|
|
|
|
return RetStr;
|
|
|
|
}
|
|
|
|
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,
|
|
UINT32 *FfsCount,
|
|
BOOLEAN ViewFlag,
|
|
BOOLEAN ErasePolarity,
|
|
BOOLEAN FfsGeneratedFlag
|
|
)
|
|
{
|
|
UINT32 ParsedLength;
|
|
UINT8 *Ptr;
|
|
UINT32 SectionLength;
|
|
UINT32 UiSectionLength;
|
|
EFI_SECTION_TYPE Type;
|
|
EFI_STATUS Status;
|
|
CHAR8 *ExtractionTool;
|
|
CHAR8 *ToolInputFile;
|
|
CHAR8 *ToolOutputFile;
|
|
CHAR8 *SystemCommand;
|
|
UINT8 *ToolOutputBuffer;
|
|
UINT32 ToolOutputLength;
|
|
CHAR16 *UIName;
|
|
UINT32 UINameSize;
|
|
BOOLEAN HasDepexSection;
|
|
UINT32 NumberOfSections;
|
|
BOOLEAN IsFfsGenerated;
|
|
ENCAP_INFO_DATA *LocalEncapData;
|
|
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;
|
|
CHAR8 *UIFileName;
|
|
CHAR8 *ToolInputFileName;
|
|
CHAR8 *ToolOutputFileName;
|
|
|
|
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;
|
|
ToolOutputBuffer = NULL;
|
|
UIName = NULL;
|
|
LocalEncapData = NULL;
|
|
BlankChar = NULL;
|
|
UncompressedBuffer = NULL;
|
|
CompressedBuffer = NULL;
|
|
ScratchBuffer = NULL;
|
|
TempDir = NULL;
|
|
ToolInputFileFullName = NULL;
|
|
ToolOutputFileFullName = NULL;
|
|
ToolInputFileName = NULL;
|
|
ToolOutputFileName = NULL;
|
|
HasDepexSection = FALSE;
|
|
IsFfsGenerated = FfsGeneratedFlag;
|
|
EncapDataNeedUpdata = TRUE;
|
|
LargeHeaderOffset = 0;
|
|
|
|
|
|
while (ParsedLength < BufferLength) {
|
|
Ptr = SectionBuffer + ParsedLength;
|
|
|
|
SectionLength = FvBufExpand3ByteSize (((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;
|
|
|
|
//
|
|
// Put in encapsulate data information.
|
|
//
|
|
LocalEncapData = CurrentFv->EncapData;
|
|
while (LocalEncapData->NextNode != NULL) {
|
|
if (LocalEncapData->Level == Level) {
|
|
EncapDataNeedUpdata = FALSE;
|
|
break;
|
|
}
|
|
LocalEncapData = LocalEncapData->NextNode;
|
|
}
|
|
|
|
if (EncapDataNeedUpdata) {
|
|
//
|
|
// Put in this is an FFS with FV section
|
|
//
|
|
LocalEncapData = CurrentFv->EncapData;
|
|
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) {
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
LocalEncapData = LocalEncapData->NextNode;
|
|
|
|
LocalEncapData->Level = Level;
|
|
LocalEncapData->Type = BFM_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;
|
|
}
|
|
|
|
Status = LibGetFvInfo ((UINT8*)((EFI_FIRMWARE_VOLUME_IMAGE_SECTION*)Ptr + 1) + LargeHeaderOffset, CurrentFv, FvName, Level, FfsCount, ViewFlag, TRUE);
|
|
if (EFI_ERROR (Status)) {
|
|
return EFI_SECTION_ERROR;
|
|
}
|
|
break;
|
|
|
|
case EFI_SECTION_COMPRESSION:
|
|
Level ++;
|
|
NumberOfSections ++;
|
|
|
|
EncapDataNeedUpdata = TRUE;
|
|
//
|
|
// Put in encapsulate data information.
|
|
//
|
|
LocalEncapData = CurrentFv->EncapData;
|
|
while (LocalEncapData->NextNode != NULL) {
|
|
if (LocalEncapData->Level == Level) {
|
|
EncapDataNeedUpdata = FALSE;
|
|
break;
|
|
}
|
|
LocalEncapData = LocalEncapData->NextNode;
|
|
}
|
|
|
|
if (EncapDataNeedUpdata) {
|
|
//
|
|
// Put in this is an FFS with FV section
|
|
//
|
|
LocalEncapData = CurrentFv->EncapData;
|
|
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) {
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
LocalEncapData = LocalEncapData->NextNode;
|
|
|
|
LocalEncapData->Level = Level;
|
|
LocalEncapData->Type = BFM_ENCAP_TREE_COMPRESS_SECTION;
|
|
|
|
//
|
|
// Store the compress type
|
|
//
|
|
LocalEncapData->Data = malloc (sizeof (UINT8));
|
|
|
|
if (LocalEncapData->Data == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
*(UINT8 *)LocalEncapData->Data = ((EFI_COMPRESSION_SECTION *) (Ptr + LargeHeaderOffset))->CompressionType;
|
|
LocalEncapData->FvExtHeader = NULL;
|
|
LocalEncapData->NextNode = 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) {
|
|
|
|
if (CompressedLength != UncompressedLength) {
|
|
printf ("Error. File is not compressed, but the compressed length does not match the uncompressed length.\n");
|
|
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)) {
|
|
return EFI_SECTION_ERROR;
|
|
}
|
|
|
|
if (DstSize != UncompressedLength) {
|
|
return EFI_SECTION_ERROR;
|
|
}
|
|
|
|
ScratchBuffer = malloc (ScratchSize);
|
|
if (ScratchBuffer == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
UncompressedBuffer = malloc (UncompressedLength);
|
|
|
|
if (UncompressedBuffer == 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)) {
|
|
free (UncompressedBuffer);
|
|
return EFI_SECTION_ERROR;
|
|
}
|
|
} else {
|
|
return EFI_SECTION_ERROR;
|
|
}
|
|
|
|
Status = LibParseSection ( UncompressedBuffer,
|
|
UncompressedLength,
|
|
CurrentFv,
|
|
FvName,
|
|
CurrentFile,
|
|
Level,
|
|
FfsCount,
|
|
ViewFlag,
|
|
ErasePolarity,
|
|
IsFfsGenerated);
|
|
|
|
if (CompressionType == EFI_STANDARD_COMPRESSION) {
|
|
//
|
|
// We need to deallocate Buffer
|
|
//
|
|
free (UncompressedBuffer);
|
|
}
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
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 = CurrentFv->EncapData;
|
|
while (LocalEncapData->NextNode != NULL) {
|
|
if (LocalEncapData->Level == Level) {
|
|
EncapDataNeedUpdata = FALSE;
|
|
break;
|
|
}
|
|
LocalEncapData = LocalEncapData->NextNode;
|
|
}
|
|
if (EncapDataNeedUpdata) {
|
|
|
|
//
|
|
// Put in this is an FFS with FV section
|
|
//
|
|
LocalEncapData = CurrentFv->EncapData;
|
|
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) {
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
LocalEncapData = LocalEncapData->NextNode;
|
|
|
|
LocalEncapData->Level = Level;
|
|
LocalEncapData->Type = BFM_ENCAP_TREE_GUIDED_SECTION;
|
|
|
|
//
|
|
// We don't need additional data for encapsulate this FFS but type.
|
|
//
|
|
|
|
LocalEncapData->Data = (EFI_GUID *) malloc (sizeof (EFI_GUID));
|
|
|
|
if (LocalEncapData->Data == NULL) {
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
memcpy (LocalEncapData->Data, &((EFI_GUID_DEFINED_SECTION *) (Ptr + LargeHeaderOffset))->SectionDefinitionGuid, sizeof (EFI_GUID));
|
|
|
|
LocalEncapData->FvExtHeader = NULL;
|
|
LocalEncapData->NextNode = NULL;
|
|
}
|
|
|
|
CurrentFv->FfsAttuibutes[*FfsCount].IsLeaf = FALSE;
|
|
|
|
ExtractionTool =
|
|
LookupGuidedSectionToolPath (
|
|
mParsedGuidedSectionTools,
|
|
&((EFI_GUID_DEFINED_SECTION *) (Ptr + LargeHeaderOffset))->SectionDefinitionGuid
|
|
);
|
|
|
|
if ((((EFI_GUID_DEFINED_SECTION *) (Ptr + LargeHeaderOffset))->Attributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) == 0) {
|
|
//
|
|
// Not require process, directly gets data.
|
|
//
|
|
Status = LibParseSection (
|
|
Ptr + ((EFI_GUID_DEFINED_SECTION *) (Ptr + LargeHeaderOffset))->DataOffset,
|
|
SectionLength - ((EFI_GUID_DEFINED_SECTION *) (Ptr + LargeHeaderOffset))->DataOffset,
|
|
CurrentFv,
|
|
FvName,
|
|
CurrentFile,
|
|
Level,
|
|
FfsCount,
|
|
ViewFlag,
|
|
ErasePolarity,
|
|
IsFfsGenerated
|
|
);
|
|
if (ExtractionTool != NULL) {
|
|
free (ExtractionTool);
|
|
ExtractionTool = NULL;
|
|
}
|
|
if (EFI_ERROR (Status)) {
|
|
return EFI_SECTION_ERROR;
|
|
}
|
|
} else if (ExtractionTool != NULL) {
|
|
|
|
TempDir = getcwd (NULL, _MAX_PATH);
|
|
if (strlen (TempDir) + strlen (OS_SEP_STR) + strlen (TEMP_DIR_NAME) > _MAX_PATH - 1) {
|
|
printf ("The directory is too long \n");
|
|
free (ExtractionTool);
|
|
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);
|
|
|
|
ToolInputFile = GenTempFile ();
|
|
ToolOutputFile = GenTempFile ();
|
|
ToolInputFileName = strrchr(ToolInputFile, OS_SEP);
|
|
ToolOutputFileName = strrchr(ToolOutputFile, OS_SEP);
|
|
|
|
ToolInputFileFullName = malloc (strlen("%s%s") + strlen(TempDir) + strlen(ToolInputFileName) + 1);
|
|
if (ToolInputFileFullName == NULL) {
|
|
free (ExtractionTool);
|
|
free (ToolInputFile);
|
|
free (ToolOutputFile);
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
ToolOutputFileFullName = malloc (strlen("%s%s") + strlen(TempDir) + strlen(ToolOutputFileName) + 1);
|
|
if (ToolOutputFileFullName == NULL) {
|
|
free (ToolInputFileFullName);
|
|
free (ExtractionTool);
|
|
free (ToolInputFile);
|
|
free (ToolOutputFile);
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
sprintf (ToolInputFileFullName, "%s%s", TempDir, ToolInputFileName);
|
|
sprintf (ToolOutputFileFullName, "%s%s", TempDir, ToolOutputFileName);
|
|
|
|
//
|
|
// Construction 'system' command string
|
|
//
|
|
SystemCommand = malloc (
|
|
strlen (DECODE_STR) +
|
|
strlen (ExtractionTool) +
|
|
strlen (ToolInputFileFullName) +
|
|
strlen (ToolOutputFileFullName) +
|
|
1
|
|
);
|
|
if (SystemCommand == NULL) {
|
|
free (ToolInputFile);
|
|
free (ToolOutputFile);
|
|
free (ToolInputFileFullName);
|
|
free (ToolOutputFileFullName);
|
|
free (ExtractionTool);
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
sprintf (
|
|
SystemCommand,
|
|
DECODE_STR,
|
|
ExtractionTool,
|
|
ToolOutputFileFullName,
|
|
ToolInputFileFullName
|
|
);
|
|
|
|
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)) {
|
|
free(SystemCommand);
|
|
free (ToolOutputFileFullName);
|
|
free (ToolOutputFile);
|
|
remove (ToolInputFileFullName);
|
|
free (ToolInputFile);
|
|
free (ToolInputFileFullName);
|
|
return EFI_SECTION_ERROR;
|
|
}
|
|
|
|
if (system (SystemCommand) != EFI_SUCCESS) {
|
|
SystemCommand = malloc (
|
|
strlen (DECODE_STR_ERR) +
|
|
strlen (ExtractionTool) +
|
|
strlen (ToolInputFileFullName) +
|
|
strlen (ToolOutputFileFullName) +
|
|
1
|
|
);
|
|
if (SystemCommand == NULL) {
|
|
free (ExtractionTool);
|
|
LibRmDir (TempDir);
|
|
remove (ToolInputFileFullName);
|
|
free (ToolInputFile);
|
|
free (ToolInputFileFullName);
|
|
free (ToolOutputFileFullName);
|
|
free (ToolOutputFile);
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
sprintf (
|
|
SystemCommand,
|
|
DECODE_STR_ERR,
|
|
ExtractionTool,
|
|
ToolOutputFileFullName,
|
|
ToolInputFileFullName
|
|
);
|
|
system (SystemCommand);
|
|
printf("Command failed: %s\n", SystemCommand);
|
|
free (ExtractionTool);
|
|
ExtractionTool = NULL;
|
|
LibRmDir (TempDir);
|
|
free(SystemCommand);
|
|
remove (ToolInputFileFullName);
|
|
free (ToolInputFile);
|
|
free (ToolInputFileFullName);
|
|
free (ToolOutputFileFullName);
|
|
free (ToolOutputFile);
|
|
return EFI_ABORTED;
|
|
}
|
|
free (ExtractionTool);
|
|
ExtractionTool = NULL;
|
|
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)) {
|
|
return EFI_SECTION_ERROR;
|
|
}
|
|
|
|
Status = LibParseSection (
|
|
ToolOutputBuffer,
|
|
ToolOutputLength,
|
|
CurrentFv,
|
|
FvName,
|
|
CurrentFile,
|
|
Level,
|
|
FfsCount,
|
|
ViewFlag,
|
|
ErasePolarity,
|
|
IsFfsGenerated
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return EFI_SECTION_ERROR;
|
|
}
|
|
} else {
|
|
//
|
|
// We don't know how to parse it now.
|
|
//
|
|
if (ExtractionTool != NULL) {
|
|
free (ExtractionTool);
|
|
ExtractionTool = NULL;
|
|
}
|
|
printf(" EFI_SECTION_GUID_DEFINED cannot be parsed at this time. Tool to decode this section should have been defined in %s file.\n", 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;
|
|
break;
|
|
case EFI_SECTION_DXE_DEPEX:
|
|
NumberOfSections ++;
|
|
CurrentFv->FfsAttuibutes[*FfsCount].Level = Level;
|
|
HasDepexSection = TRUE;
|
|
break;
|
|
case EFI_SECTION_SMM_DEPEX:
|
|
NumberOfSections ++;
|
|
CurrentFv->FfsAttuibutes[*FfsCount].Level = Level;
|
|
HasDepexSection = TRUE;
|
|
break;
|
|
|
|
case EFI_SECTION_USER_INTERFACE:
|
|
NumberOfSections ++;
|
|
CurrentFv->FfsAttuibutes[*FfsCount].Level = Level;
|
|
|
|
UiSectionLength = FvBufExpand3ByteSize (((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 {
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
BlankChar = LibConstructBlankChar( CurrentFv->FvLevel * 2);
|
|
if (BlankChar == NULL) {
|
|
free (UIName);
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
if (ViewFlag) {
|
|
UIFileName = malloc (UINameSize + 2);
|
|
if (UIFileName == NULL) {
|
|
free(BlankChar);
|
|
free(UIName);
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
Unicode2AsciiString (UIName, UIFileName);
|
|
fprintf(stdout, "%sFile \"%s\"\n", BlankChar, UIFileName);
|
|
free(UIFileName);
|
|
}
|
|
|
|
free (BlankChar);
|
|
BlankChar = NULL;
|
|
|
|
//
|
|
// If Ffs file has been generated, then the FfsCount should decrease 1.
|
|
//
|
|
if (IsFfsGenerated) {
|
|
memcpy (CurrentFv->FfsAttuibutes[*FfsCount -1].UiName, UIName, UINameSize);
|
|
} else {
|
|
memcpy (CurrentFv->FfsAttuibutes[*FfsCount].UiName, UIName, 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) {
|
|
return EFI_SECTION_ERROR;
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
|
|
Add function description
|
|
|
|
FvImage - add argument description
|
|
FileHeader - add argument description
|
|
ErasePolarity - add argument description
|
|
|
|
EFI_SUCCESS - Add description for return value
|
|
EFI_ABORTED - 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,
|
|
UINT32 *FfsCount,
|
|
BOOLEAN ViewFlag
|
|
)
|
|
{
|
|
UINT32 FileLength;
|
|
UINT8 FileState;
|
|
UINT8 Checksum;
|
|
EFI_FFS_FILE_HEADER2 BlankHeader;
|
|
EFI_STATUS Status;
|
|
ENCAP_INFO_DATA *LocalEncapData;
|
|
BOOLEAN EncapDataNeedUpdateFlag;
|
|
UINT32 FfsFileHeaderSize;
|
|
|
|
Status = EFI_SUCCESS;
|
|
|
|
LocalEncapData = NULL;
|
|
EncapDataNeedUpdateFlag = TRUE;
|
|
|
|
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);
|
|
|
|
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) {
|
|
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) {
|
|
return EFI_ABORTED;
|
|
}
|
|
} else {
|
|
if (CurrentFile->IntegrityCheck.Checksum.File != FFS_FIXED_CHECKSUM) {
|
|
return EFI_ABORTED;
|
|
}
|
|
}
|
|
} else {
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
Level += 1;
|
|
|
|
if (CurrentFile->Type != EFI_FV_FILETYPE_ALL) {
|
|
|
|
//
|
|
// Put in encapsulate data information.
|
|
//
|
|
LocalEncapData = CurrentFv->EncapData;
|
|
while (LocalEncapData->NextNode != NULL) {
|
|
if (LocalEncapData->Level == Level) {
|
|
EncapDataNeedUpdateFlag = FALSE;
|
|
break;
|
|
}
|
|
LocalEncapData = LocalEncapData->NextNode;
|
|
}
|
|
|
|
if (EncapDataNeedUpdateFlag) {
|
|
//
|
|
// Construct the new ENCAP_DATA
|
|
//
|
|
LocalEncapData->NextNode = (ENCAP_INFO_DATA *) malloc (sizeof (ENCAP_INFO_DATA));
|
|
|
|
if (LocalEncapData->NextNode == NULL) {
|
|
printf ("Out of resource, memory allocation failed. \n");
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
LocalEncapData = LocalEncapData->NextNode;
|
|
|
|
LocalEncapData->Level = Level;
|
|
LocalEncapData->Type = BFM_ENCAP_TREE_FFS;
|
|
LocalEncapData->FvExtHeader = NULL;
|
|
|
|
//
|
|
// Store the header of FFS file.
|
|
//
|
|
LocalEncapData->Data = malloc (FfsFileHeaderSize);
|
|
if (LocalEncapData->Data == NULL) {
|
|
printf ("Out of resource, memory allocation failed. \n");
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
memcpy (LocalEncapData->Data, CurrentFile, FfsFileHeaderSize);
|
|
|
|
LocalEncapData->NextNode = NULL;
|
|
}
|
|
|
|
if ( CurrentFile->Type == EFI_FV_FILETYPE_FREEFORM ){
|
|
CurrentFv->FfsAttuibutes[*FfsCount].Level = Level;
|
|
if (!ViewFlag) {
|
|
LibGenFfsFile(CurrentFile, CurrentFv, FvName, Level, FfsCount, ErasePolarity);
|
|
}
|
|
}else 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_SECURITY_CORE){
|
|
CurrentFv->FfsAttuibutes[*FfsCount].Level = Level;
|
|
//
|
|
// If an FV contain SECCORE, this FV will be considered as BFV.
|
|
//
|
|
CurrentFv->IsBfvFlag = TRUE;
|
|
if (!ViewFlag){
|
|
LibGenFfsFile(CurrentFile, CurrentFv, FvName, Level, FfsCount, ErasePolarity);
|
|
}
|
|
} else if( CurrentFile->Type == EFI_FV_FILETYPE_FFS_PAD){
|
|
//
|
|
// First check whether the FFS file contain FvExtended FvNameGuid information.
|
|
//
|
|
if (!LibCheckPadFfsContainFvNameGuid (CurrentFv, CurrentFile)) {
|
|
//
|
|
// Then check whether the PAD file have no additional data or not.
|
|
//
|
|
if (LibCheckPadFfsNotNull (CurrentFile)) {
|
|
CurrentFv->FfsAttuibutes[*FfsCount].Level = Level;
|
|
//
|
|
// Get the size of PAD in BFV
|
|
//
|
|
PadSizeOfBfv = GetBfvMaxFreeSpace (CurrentFile);
|
|
if (!ViewFlag){
|
|
//
|
|
//LibGenFfsFile(CurrentFile, CurrentFv, FvName, Level, FfsCount, ErasePolarity);
|
|
//
|
|
Status = LibFindResetVectorAndFitTableData (FvImage, CurrentFile, CurrentFv);
|
|
if (EFI_ERROR (Status)) {
|
|
printf ("Find reset vector and FIT table data failed. \n");
|
|
return EFI_ABORTED;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
//
|
|
// All other files have sections
|
|
//
|
|
Status = LibParseSection (
|
|
(UINT8 *) ((UINTN) CurrentFile + FfsFileHeaderSize),
|
|
FileLength - FfsFileHeaderSize,
|
|
CurrentFv,
|
|
FvName,
|
|
CurrentFile,
|
|
Level,
|
|
FfsCount,
|
|
ViewFlag,
|
|
ErasePolarity,
|
|
FALSE
|
|
);
|
|
}
|
|
if (EFI_ERROR (Status)) {
|
|
printf ("Error while parse the FFS file.\n");
|
|
return EFI_ABORTED;
|
|
}
|
|
}
|
|
|
|
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 UINT32 *FfsCount,
|
|
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;
|
|
|
|
NumberOfFiles = 0;
|
|
Key = 0;
|
|
LocalEncapData = NULL;
|
|
CurrentFile = NULL;
|
|
|
|
Level += 1;
|
|
CurrentFv->FvLevel += 1;
|
|
|
|
Status = FvBufGetSize (Fv, &FvSize);
|
|
|
|
ErasePolarity = (((EFI_FIRMWARE_VOLUME_HEADER*)Fv)->Attributes & EFI_FVB2_ERASE_POLARITY) ? TRUE : FALSE;
|
|
|
|
if (!IsChildFv) {
|
|
//
|
|
// Write FV header information into CurrentFv struct.
|
|
//
|
|
CurrentFv->FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) malloc (sizeof (EFI_FIRMWARE_VOLUME_HEADER));
|
|
|
|
if (CurrentFv->FvHeader == NULL) {
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
//
|
|
// Get the FV Header information
|
|
//
|
|
memcpy (CurrentFv->FvHeader, Fv, sizeof (EFI_FIRMWARE_VOLUME_HEADER));
|
|
CurrentFv->FvExtHeader = NULL;
|
|
|
|
//
|
|
// Exist Extend FV header.
|
|
//
|
|
if (CurrentFv->FvHeader->ExtHeaderOffset != 0){
|
|
CurrentFv->FvExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *) malloc (sizeof (EFI_FIRMWARE_VOLUME_EXT_HEADER));
|
|
|
|
if (CurrentFv->FvExtHeader == NULL) {
|
|
printf ("Out of resource, memory allocation failed. \n");
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
//
|
|
// Get the FV extended Header information
|
|
//
|
|
memcpy (CurrentFv->FvExtHeader, (VOID *)((UINTN)Fv + CurrentFv->FvHeader->ExtHeaderOffset), sizeof (EFI_FIRMWARE_VOLUME_EXT_HEADER));
|
|
if (mFvGuidIsSet) {
|
|
if (CompareGuid (&CurrentFv->FvExtHeader->FvName, &mFvNameGuid) == 0) {
|
|
CurrentFv->IsInputFvFlag = TRUE;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// Put encapsulate information into structure.
|
|
//
|
|
if (CurrentFv->EncapData == NULL && !IsChildFv) {
|
|
//
|
|
// First time in, the root FV
|
|
//
|
|
CurrentFv->EncapData = (ENCAP_INFO_DATA *) malloc (sizeof (ENCAP_INFO_DATA));
|
|
|
|
if (CurrentFv->EncapData == NULL) {
|
|
return EFI_ABORTED;
|
|
}
|
|
CurrentFv->EncapData->FvExtHeader = NULL;
|
|
CurrentFv->EncapData->Level = Level;
|
|
CurrentFv->EncapData->Type = BFM_ENCAP_TREE_FV;
|
|
CurrentFv->EncapData->Data = (EFI_FIRMWARE_VOLUME_HEADER *) malloc (sizeof (EFI_FIRMWARE_VOLUME_HEADER));
|
|
|
|
if (CurrentFv->EncapData->Data == 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) {
|
|
printf ("Out of resource, memory allocation failed. \n");
|
|
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);
|
|
if (mFvGuidIsSet) {
|
|
if (CompareGuid (&CurrentFv->EncapData->FvExtHeader->FvName, &mFvNameGuid) == 0) {
|
|
CurrentFv->IsInputFvFlag = TRUE;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
CurrentFv->EncapData->NextNode = NULL;
|
|
|
|
} else if (CurrentFv->EncapData == NULL) {
|
|
return EFI_ABORTED;
|
|
} else if (IsChildFv) {
|
|
|
|
LocalEncapData = CurrentFv->EncapData;
|
|
|
|
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) {
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
LocalEncapData = LocalEncapData->NextNode;
|
|
|
|
LocalEncapData->Level = Level;
|
|
LocalEncapData->Type = BFM_ENCAP_TREE_FV;
|
|
LocalEncapData->Data = (EFI_FIRMWARE_VOLUME_HEADER *) malloc (sizeof (EFI_FIRMWARE_VOLUME_HEADER));
|
|
LocalEncapData->FvExtHeader = NULL;
|
|
|
|
if (LocalEncapData->Data == 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) {
|
|
printf ("Out of resource, memory allocation failed. \n");
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
//
|
|
// Get the first file
|
|
//
|
|
Status = FvBufFindNextFile (Fv, &Key, (VOID **) &CurrentFile);
|
|
if (Status == EFI_NOT_FOUND) {
|
|
CurrentFile = NULL;
|
|
} else if (EFI_ERROR (Status)) {
|
|
printf ("Failed to find the first file from Fv. \n");
|
|
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;
|
|
|
|
//
|
|
// Display info about this file
|
|
//
|
|
Status = LibGetFileInfo (Fv, CurrentFile, ErasePolarity, CurrentFv, FvName, Level, FfsCount, ViewFlag);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Get the next file
|
|
//
|
|
Status = FvBufFindNextFile (Fv, &Key, (VOID **) &CurrentFile);
|
|
if (Status == EFI_NOT_FOUND) {
|
|
CurrentFile = NULL;
|
|
} else if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
}
|
|
|
|
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) {
|
|
printf ("The directory is too long \n");
|
|
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) {
|
|
printf ("The directory is too long \n");
|
|
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) {
|
|
printf ("The directory is too long \n");
|
|
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;
|
|
}
|
|
|
|
|
|
/**
|
|
|
|
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;
|
|
}
|
|
|
|
/**
|
|
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* SystemCommand;
|
|
|
|
SystemCommand = NULL;
|
|
|
|
if (FileIn == NULL ||
|
|
ToolName == NULL ||
|
|
FileOut == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
SystemCommand = malloc (
|
|
strlen (ENCODE_STR) +
|
|
strlen (FileIn) +
|
|
strlen (ToolName) +
|
|
strlen (FileOut) +
|
|
1
|
|
);
|
|
|
|
if (NULL == SystemCommand) {
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
sprintf (
|
|
SystemCommand,
|
|
ENCODE_STR,
|
|
ToolName,
|
|
FileIn,
|
|
FileOut
|
|
);
|
|
|
|
if (system (SystemCommand) != EFI_SUCCESS) {
|
|
SystemCommand = malloc (
|
|
strlen (ENCODE_STR_ERR) +
|
|
strlen (FileIn) +
|
|
strlen (ToolName) +
|
|
strlen (FileOut) +
|
|
1
|
|
);
|
|
if (NULL == SystemCommand) {
|
|
return EFI_ABORTED;
|
|
}
|
|
sprintf (
|
|
SystemCommand,
|
|
ENCODE_STR_ERR,
|
|
ToolName,
|
|
FileIn,
|
|
FileOut
|
|
);
|
|
system (SystemCommand);
|
|
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 ("Out of resource, memory allocation failed. \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 write data to %p file. \n", (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_FV_BLOCK_MAP_ENTRY *BlockMap,
|
|
IN FILE* InfFile,
|
|
IN BOOLEAN IsRootFv
|
|
)
|
|
{
|
|
CHAR8 *LocalStr;
|
|
CHAR8 *BlockSize;
|
|
CHAR8 *NumOfBlocks;
|
|
|
|
LocalStr = NULL;
|
|
BlockSize = NULL;
|
|
NumOfBlocks = NULL;
|
|
|
|
if (BlockMap == 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);
|
|
BlockSize = (CHAR8 *) malloc (128);
|
|
NumOfBlocks = (CHAR8 *) malloc (128);
|
|
|
|
if (LocalStr == NULL ||
|
|
BlockSize == NULL ||
|
|
NumOfBlocks == NULL) {
|
|
if (LocalStr != NULL) {
|
|
free (LocalStr);
|
|
}
|
|
if (BlockSize != NULL) {
|
|
free (BlockSize);
|
|
}
|
|
if (NumOfBlocks != NULL) {
|
|
free (NumOfBlocks);
|
|
}
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
memset (LocalStr, '\0', 1024);
|
|
memset (BlockSize, '\0', 128);
|
|
memset (NumOfBlocks, '\0', 128);
|
|
|
|
strncat (LocalStr, "[options] \n", sizeof("[Options] \n"));
|
|
|
|
sprintf (BlockSize, "EFI_BLOCK_SIZE = 0x%x \n", BlockMap->Length);
|
|
strncat (LocalStr, BlockSize, strlen(BlockSize));
|
|
|
|
if (IsRootFv) {
|
|
sprintf (NumOfBlocks, "EFI_NUM_BLOCKS = 0x%x \n", BlockMap->NumBlocks);
|
|
strncat (LocalStr, NumOfBlocks, strlen(NumOfBlocks));
|
|
}
|
|
|
|
if (fwrite (LocalStr, 1, (size_t) strlen (LocalStr), InfFile) != (size_t) strlen (LocalStr)) {
|
|
free (LocalStr);
|
|
free (BlockSize);
|
|
free (NumOfBlocks);
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
free (LocalStr);
|
|
free (BlockSize);
|
|
free (NumOfBlocks);
|
|
|
|
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 ("Out of resource, memory allocation failed. \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 write data to %p file. \n", (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 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 CHAR8* CompressType OPTIONAL
|
|
)
|
|
{
|
|
CHAR8* SystemCommand;
|
|
SystemCommand = NULL;
|
|
|
|
//
|
|
// Call GenSec tool to generate FFS section.
|
|
//
|
|
|
|
//
|
|
// -s SectionType.
|
|
//
|
|
if (Type != 0) {
|
|
switch (Type) {
|
|
//
|
|
// Process compression section
|
|
//
|
|
case EFI_SECTION_COMPRESSION:
|
|
SystemCommand = malloc (
|
|
strlen (GENSEC_COMPRESSION) +
|
|
strlen (mSectionTypeName[Type]) +
|
|
strlen (CompressType) +
|
|
strlen (InputFilePath) +
|
|
strlen (OutputFilePath) +
|
|
1
|
|
);
|
|
if (NULL == SystemCommand) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
sprintf (
|
|
SystemCommand,
|
|
GENSEC_COMPRESSION,
|
|
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:
|
|
SystemCommand = malloc (
|
|
strlen (GENSEC_GUID) +
|
|
strlen (mSectionTypeName[Type]) +
|
|
strlen (GuidToolGuid) +
|
|
strlen (InputFilePath) +
|
|
strlen (OutputFilePath) +
|
|
1
|
|
);
|
|
if (NULL == SystemCommand) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
sprintf (
|
|
SystemCommand,
|
|
GENSEC_GUID,
|
|
mSectionTypeName[Type],
|
|
GuidToolGuid,
|
|
InputFilePath,
|
|
OutputFilePath
|
|
);
|
|
if (system (SystemCommand) != EFI_SUCCESS) {
|
|
free(SystemCommand);
|
|
return EFI_ABORTED;
|
|
}
|
|
free(SystemCommand);
|
|
break;
|
|
|
|
case EFI_SECTION_FIRMWARE_VOLUME_IMAGE:
|
|
SystemCommand = malloc (
|
|
strlen (GENSEC_STR) +
|
|
strlen (mSectionTypeName[Type]) +
|
|
strlen (InputFilePath) +
|
|
strlen (OutputFilePath) +
|
|
1
|
|
);
|
|
if (NULL == SystemCommand) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
sprintf (
|
|
SystemCommand,
|
|
GENSEC_STR,
|
|
mSectionTypeName[Type],
|
|
InputFilePath,
|
|
OutputFilePath
|
|
);
|
|
if (system (SystemCommand) != EFI_SUCCESS) {
|
|
free(SystemCommand);
|
|
return EFI_ABORTED;
|
|
}
|
|
free(SystemCommand);
|
|
break;
|
|
|
|
case EFI_SECTION_RAW:
|
|
SystemCommand = malloc (
|
|
strlen (GENSEC_STR) +
|
|
strlen (mSectionTypeName[Type]) +
|
|
strlen (InputFilePath) +
|
|
strlen (OutputFilePath) +
|
|
1
|
|
);
|
|
if (NULL == SystemCommand) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
sprintf (
|
|
SystemCommand,
|
|
GENSEC_STR,
|
|
mSectionTypeName[Type],
|
|
InputFilePath,
|
|
OutputFilePath
|
|
);
|
|
if (system (SystemCommand) != EFI_SUCCESS) {
|
|
free(SystemCommand);
|
|
return EFI_ABORTED;
|
|
}
|
|
free(SystemCommand);
|
|
break;
|
|
|
|
default:
|
|
printf ("Please specify the section type while call GenSec tool.\n");
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
} else {
|
|
//
|
|
// Create Dummy section.
|
|
//
|
|
SystemCommand = malloc (
|
|
strlen (GENSEC_ALIGN) +
|
|
strlen (InputFilePath) +
|
|
strlen (OutputFilePath) +
|
|
1
|
|
);
|
|
if (NULL == SystemCommand) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
sprintf (
|
|
SystemCommand,
|
|
GENSEC_ALIGN,
|
|
InputFilePath,
|
|
OutputFilePath
|
|
);
|
|
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
|
|
)
|
|
{
|
|
|
|
CHAR8* SystemCommand;
|
|
CHAR8* FfsGuid = "8c8ce578-8a3d-4f1c-9935-896185c32dd3";
|
|
|
|
SystemCommand = NULL;
|
|
|
|
if (OutputFilePath == NULL ||
|
|
InfFilePath == NULL ) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (InfFilePath != NULL) {
|
|
if (FvGuidName == NULL) {
|
|
SystemCommand = malloc (
|
|
strlen (GENFV_STR) +
|
|
strlen (InfFilePath) +
|
|
strlen (OutputFilePath) +
|
|
1
|
|
);
|
|
if (NULL == SystemCommand) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
sprintf (
|
|
SystemCommand,
|
|
GENFV_STR,
|
|
InfFilePath, // -i
|
|
OutputFilePath // -o
|
|
);
|
|
|
|
if (system (SystemCommand) != EFI_SUCCESS) {
|
|
free(SystemCommand);
|
|
return EFI_ABORTED;
|
|
}
|
|
free(SystemCommand);
|
|
} else {
|
|
//
|
|
// Have FvGuidName in it.
|
|
//
|
|
SystemCommand = malloc (
|
|
strlen (GENFV_FVGUID) +
|
|
strlen (InfFilePath) +
|
|
strlen (OutputFilePath) +
|
|
strlen (FvGuidName) +
|
|
1
|
|
);
|
|
if (NULL == SystemCommand) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
sprintf (
|
|
SystemCommand,
|
|
GENFV_FVGUID,
|
|
InfFilePath, // -i
|
|
OutputFilePath, // -o
|
|
FvGuidName // FvNameGuid
|
|
);
|
|
if (system (SystemCommand) != EFI_SUCCESS) {
|
|
free(SystemCommand);
|
|
return EFI_ABORTED;
|
|
}
|
|
free(SystemCommand);
|
|
|
|
}
|
|
}
|
|
|
|
if (InputFFSs != NULL) {
|
|
SystemCommand = malloc (
|
|
strlen (GENFV_FFS) +
|
|
strlen (InputFFSs) +
|
|
strlen (FfsGuid) +
|
|
strlen (OutputFilePath) +
|
|
100
|
|
);
|
|
if (NULL == SystemCommand) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
sprintf (
|
|
SystemCommand,
|
|
GENFV_FFS,
|
|
InputFFSs, // -f
|
|
FfsGuid, // -g
|
|
OutputFilePath // -o
|
|
);
|
|
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 *
|
|
LibBfmGuidToStr (
|
|
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 UINT32 SectionAlign
|
|
)
|
|
{
|
|
CHAR8* SystemCommand;
|
|
CHAR8* GuidStr;
|
|
|
|
SystemCommand = NULL;
|
|
GuidStr = NULL;
|
|
|
|
GuidStr = LibBfmGuidToStr(&FileGuid);
|
|
|
|
if (NULL == GuidStr) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
if (Type == EFI_FV_FILETYPE_RAW) {
|
|
SystemCommand = malloc (
|
|
strlen (GENFFS_STR) +
|
|
strlen (mFfsFileType[Type]) +
|
|
strlen (InputFilePath) +
|
|
strlen (GuidStr) +
|
|
strlen (OutputFilePath) +
|
|
1
|
|
);
|
|
if (NULL == SystemCommand) {
|
|
free (GuidStr);
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
sprintf (
|
|
SystemCommand,
|
|
GENFFS_STR,
|
|
mFfsFileType[Type], // -t
|
|
InputFilePath, // -i
|
|
GuidStr, // -g
|
|
OutputFilePath // -o
|
|
);
|
|
|
|
if (system (SystemCommand) != EFI_SUCCESS) {
|
|
free(SystemCommand);
|
|
free (GuidStr);
|
|
return EFI_ABORTED;
|
|
}
|
|
free(SystemCommand);
|
|
|
|
} else {
|
|
//
|
|
// -t Type
|
|
// -i InputFilePath
|
|
// -o OutPutFilePath
|
|
// -g FileGuid
|
|
// -x Fixed
|
|
// -n SectionAlign
|
|
//
|
|
if (Fixed) {
|
|
SystemCommand = malloc (
|
|
strlen (GENFFS_FIX) +
|
|
strlen (mFfsFileType[Type]) +
|
|
strlen (InputFilePath) +
|
|
strlen (GuidStr) +
|
|
strlen (OutputFilePath) +
|
|
1
|
|
);
|
|
if (NULL == SystemCommand) {
|
|
free (GuidStr);
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
sprintf (
|
|
SystemCommand,
|
|
GENFFS_FIX,
|
|
mFfsFileType[Type], // -t
|
|
InputFilePath, // -i
|
|
GuidStr, // -g
|
|
OutputFilePath // -o
|
|
);
|
|
if (system (SystemCommand) != EFI_SUCCESS) {
|
|
free(SystemCommand);
|
|
free (GuidStr);
|
|
return EFI_ABORTED;
|
|
}
|
|
free(SystemCommand);
|
|
} else {
|
|
SystemCommand = malloc (
|
|
strlen (GENFFS_STR) +
|
|
strlen (mFfsFileType[Type]) +
|
|
strlen (InputFilePath) +
|
|
strlen (GuidStr) +
|
|
strlen (OutputFilePath) +
|
|
1
|
|
);
|
|
if (NULL == SystemCommand) {
|
|
free (GuidStr);
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
sprintf (
|
|
SystemCommand,
|
|
GENFFS_STR,
|
|
mFfsFileType[Type], // -t
|
|
InputFilePath, // -i
|
|
GuidStr, // -g
|
|
OutputFilePath // -o
|
|
);
|
|
if (system (SystemCommand) != EFI_SUCCESS) {
|
|
free(SystemCommand);
|
|
free (GuidStr);
|
|
return EFI_ABORTED;
|
|
}
|
|
free(SystemCommand);
|
|
}
|
|
}
|
|
free (GuidStr);
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS
|
|
LibCreateNewFdCopy(
|
|
IN CHAR8* OldFd,
|
|
IN CHAR8* NewFd
|
|
)
|
|
{
|
|
CHAR8* SystemCommand;
|
|
SystemCommand = NULL;
|
|
|
|
|
|
if (OldFd == NULL ||
|
|
NewFd == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
//
|
|
// Create a copy the new file.
|
|
//
|
|
|
|
SystemCommand = malloc (
|
|
strlen (COPY_STR) +
|
|
strlen (OldFd) +
|
|
strlen (NewFd) +
|
|
1
|
|
);
|
|
if (NULL == SystemCommand) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
sprintf (
|
|
SystemCommand,
|
|
COPY_STR,
|
|
OldFd,
|
|
NewFd
|
|
);
|
|
|
|
if (system (SystemCommand) != EFI_SUCCESS) {
|
|
free(SystemCommand);
|
|
return EFI_ABORTED;
|
|
}
|
|
free(SystemCommand);
|
|
|
|
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 (NULL == RetStr) {
|
|
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 (NULL == SystemCommand) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
sprintf (
|
|
SystemCommand,
|
|
RMDIR_STR,
|
|
DirName
|
|
);
|
|
|
|
if (system (SystemCommand) != EFI_SUCCESS) {
|
|
free(SystemCommand);
|
|
return EFI_ABORTED;
|
|
}
|
|
free(SystemCommand);
|
|
|
|
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
|
|
LibBfmDeleteFile(
|
|
IN CHAR8 *FileName
|
|
)
|
|
{
|
|
CHAR8* SystemCommand;
|
|
|
|
SystemCommand = NULL;
|
|
|
|
|
|
if (FileName == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
|
|
//
|
|
// Delete a file.
|
|
//
|
|
SystemCommand = malloc (
|
|
strlen (DEL_STR) +
|
|
strlen (FileName) +
|
|
1
|
|
);
|
|
if (NULL == SystemCommand) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
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
|
|
LibBfmFreeFd (
|
|
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;
|
|
|
|
if (TempFv->FvHeader != NULL) {
|
|
free (TempFv->FvHeader);
|
|
}
|
|
if (TempFv->FvExtHeader != NULL) {
|
|
free (TempFv->FvExtHeader);
|
|
}
|
|
|
|
//
|
|
// 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;
|
|
CHAR8 *TemString;
|
|
EFI_STATUS Status;
|
|
|
|
UnCompressFile = NULL;
|
|
CompressedFile = NULL;
|
|
UnCompressedBuffer = NULL;
|
|
CompressedBuffer = NULL;
|
|
TempName = NULL;
|
|
TemDir = NULL;
|
|
TemString = 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);
|
|
if (strlen (TemDir) + strlen (OS_SEP_STR) + strlen (TEMP_DIR_NAME) > _MAX_PATH - 1) {
|
|
printf ("The directory is too long \n");
|
|
fclose (UnCompressFile);
|
|
return EFI_ABORTED;
|
|
}
|
|
strncat (TemDir, OS_SEP_STR, _MAX_PATH - strlen (TemDir) - 1);
|
|
strncat (TemDir, TEMP_DIR_NAME, _MAX_PATH - strlen (TemDir) - 1);
|
|
TemString = GenTempFile ();
|
|
TempName= LibFilenameStrExtended (strrchr(TemString, OS_SEP), TemDir, "comp");
|
|
free (TemString);
|
|
TemString = NULL;
|
|
if (TempName == NULL) {
|
|
fclose(UnCompressFile);
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
CompressedFile = fopen (TempName, "wb+");
|
|
if (CompressedFile == NULL) {
|
|
printf ("Error while open file %s \n", TempName);
|
|
fclose(UnCompressFile);
|
|
free (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 ("Out of resource, memory allocation failed. \n");
|
|
fclose (CompressedFile);
|
|
fclose(UnCompressFile);
|
|
free (TempName);
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
CompressedBuffer = malloc (UnCompressedSize);
|
|
|
|
if (CompressedBuffer == NULL) {
|
|
printf ("Out of resource, memory allocation failed. \n");
|
|
free (UnCompressedBuffer);
|
|
fclose (CompressedFile);
|
|
fclose(UnCompressFile);
|
|
free (TempName);
|
|
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");
|
|
free (UnCompressedBuffer);
|
|
free (CompressedBuffer);
|
|
fclose (CompressedFile);
|
|
fclose(UnCompressFile);
|
|
free (TempName);
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
if (CompressedSize > UnCompressedSize) {
|
|
printf("Error while do compress operation! \n");
|
|
free (UnCompressedBuffer);
|
|
free (CompressedBuffer);
|
|
fclose (CompressedFile);
|
|
fclose(UnCompressFile);
|
|
free (TempName);
|
|
return EFI_ABORTED;
|
|
}
|
|
} else {
|
|
printf("Error while reading file %s! \n", InputFileName);
|
|
free (UnCompressedBuffer);
|
|
free (CompressedBuffer);
|
|
fclose (CompressedFile);
|
|
fclose(UnCompressFile);
|
|
free (TempName);
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
//
|
|
// Write the compressed data into output file
|
|
//
|
|
if (fwrite (CompressedBuffer, 1, (size_t) CompressedSize, CompressedFile) != (size_t) CompressedSize) {
|
|
printf ("Error while writing %s file. \n", OutPutFileName);
|
|
free (UnCompressedBuffer);
|
|
free (CompressedBuffer);
|
|
fclose(UnCompressFile);
|
|
fclose (CompressedFile);
|
|
free (TempName);
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
fclose(UnCompressFile);
|
|
fclose (CompressedFile);
|
|
free (UnCompressedBuffer);
|
|
free (CompressedBuffer);
|
|
|
|
//
|
|
// Call GenSec tool to generate the compressed section.
|
|
//
|
|
LibCreateFfsSection(TempName, NULL, EFI_SECTION_COMPRESSION, OutPutFileName, NULL, NULL, NULL, "PI_STD");
|
|
free (TempName);
|
|
TempName = NULL;
|
|
|
|
} else if (CompressionType == EFI_NOT_COMPRESSED) {
|
|
|
|
LibCreateFfsSection(InputFileName, NULL, EFI_SECTION_COMPRESSION, OutPutFileName, NULL, NULL, NULL, "PI_NONE");
|
|
|
|
} else {
|
|
printf ("Error while generate compressed section, unknown compression type! \n");
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
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 ( "Fail to allocate memory. \n");
|
|
if (Tool != NULL) {
|
|
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;
|
|
}
|
|
|
|
EFI_STATUS
|
|
LibLocateFvViaFvId (
|
|
IN FIRMWARE_DEVICE *FdData,
|
|
IN CHAR8 *FvId,
|
|
IN OUT FV_INFORMATION **FvInFd
|
|
)
|
|
{
|
|
UINT8 FvIndex1;
|
|
UINT8 FvIndex2;
|
|
BOOLEAN FvFoundFlag;
|
|
|
|
FvIndex1 = 0;
|
|
FvIndex2 = 0;
|
|
FvFoundFlag = FALSE;
|
|
|
|
if (FdData == NULL || FvId == NULL) {
|
|
printf ( "Error while find FV in FD. \n");
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
*FvInFd = FdData->Fv;
|
|
|
|
FvIndex1 = (UINT8) atoi (FvId + 2);
|
|
|
|
while (FvInFd != NULL) {
|
|
if (((*FvInFd)->FvName) != NULL) {
|
|
FvIndex2 = (UINT8) atoi ((*FvInFd)->FvName + 2);
|
|
|
|
if ((FvIndex2 <= FvIndex1) && (((*FvInFd)->FvLevel + FvIndex2) -1 >= FvIndex1)) {
|
|
FvFoundFlag = TRUE;
|
|
break;
|
|
}
|
|
if ((*FvInFd)->FvNext == 0) {
|
|
break;
|
|
}
|
|
*FvInFd = (*FvInFd)->FvNext;
|
|
}
|
|
}
|
|
|
|
//
|
|
// The specified FV id has issue, can not find the FV in FD.
|
|
//
|
|
if (!FvFoundFlag) {
|
|
printf ( "Error while find FV in FD. \n");
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
EFI_STATUS
|
|
LibPatchResetVectorAndFitTableData (
|
|
IN CHAR8 *OutputFileName,
|
|
IN PATCH_DATA_PAD_FFS *PatchData
|
|
)
|
|
{
|
|
FILE* NewFvFile;
|
|
UINT64 NewFvLength;
|
|
UINT8 *Buffer;
|
|
UINT32 Count;
|
|
|
|
|
|
Count = 0;
|
|
Buffer = NULL;
|
|
NewFvFile = NULL;
|
|
|
|
if (OutputFileName == NULL || PatchData == NULL) {
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
NewFvFile = fopen (OutputFileName, "rb+");
|
|
if (NewFvFile == NULL) {
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
fseek(NewFvFile, 0, SEEK_SET);
|
|
fseek(NewFvFile, 0, SEEK_END);
|
|
|
|
NewFvLength = ftell(NewFvFile);
|
|
|
|
do {
|
|
|
|
//
|
|
// The FV length should larger than Offset.
|
|
//
|
|
if (NewFvLength < PatchData->Offset) {
|
|
fclose (NewFvFile);
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
fseek(NewFvFile,PatchData->Offset,SEEK_SET);
|
|
|
|
Buffer = (UINT8 *) malloc (PatchData->Length);
|
|
|
|
if (Buffer == NULL) {
|
|
fclose (NewFvFile);
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
if (fread (Buffer, 1, (size_t) PatchData->Length, NewFvFile) != (size_t) PatchData->Length) {
|
|
fclose (NewFvFile);
|
|
free(Buffer);
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
//
|
|
// The area used to patch data should be filled by 0xff.
|
|
//
|
|
for (Count = 0; Count< PatchData->Length; Count++) {
|
|
if (Buffer[Count] != 0xff){
|
|
fclose (NewFvFile);
|
|
free(Buffer);
|
|
return EFI_ABORTED;
|
|
}
|
|
}
|
|
|
|
free(Buffer);
|
|
|
|
fseek(NewFvFile,PatchData->Offset,SEEK_SET);
|
|
|
|
if (fwrite (PatchData->Data, 1, (size_t) PatchData->Length, NewFvFile) != (size_t) PatchData->Length) {
|
|
fclose (NewFvFile);
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
PatchData = PatchData->NextNode;
|
|
} while (PatchData != NULL);
|
|
|
|
fclose (NewFvFile);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS
|
|
LibEncapNewFvFile(
|
|
IN FV_INFORMATION *FvInFd,
|
|
IN CHAR8 *TemDir,
|
|
OUT CHAR8 **OutputFile
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINT32 ParentType;
|
|
UINT8 ParentLevel;
|
|
UINT32 Type;
|
|
UINT8 Level;
|
|
CHAR8 *InfFileName;
|
|
FILE *InfFile;
|
|
ENCAP_INFO_DATA *LocalEncapData;
|
|
BOOLEAN FfsFoundFlag;
|
|
UINT32 Index;
|
|
CHAR8 *ExtractionTool;
|
|
BOOLEAN IsLastLevelFfs;
|
|
BOOLEAN IsLeafFlagIgnore;
|
|
BOOLEAN FirstInFlag;
|
|
CHAR8 *InputFileName;
|
|
CHAR8 *OutputFileName;
|
|
CHAR8 *FvGuidName;
|
|
|
|
Index = 0;
|
|
ParentType = 0;
|
|
ParentLevel = 0;
|
|
Type = 0;
|
|
Level = 0;
|
|
FfsFoundFlag = FALSE;
|
|
ExtractionTool = NULL;
|
|
InputFileName = NULL;
|
|
OutputFileName = NULL;
|
|
IsLastLevelFfs = TRUE;
|
|
IsLeafFlagIgnore = FALSE;
|
|
FirstInFlag = TRUE;
|
|
FvGuidName = NULL;
|
|
|
|
//
|
|
// Encapsulate from the lowest FFS file level.
|
|
//
|
|
LocalEncapData = FvInFd->EncapData;
|
|
Level = LocalEncapData->Level;
|
|
Type = LocalEncapData->Type;
|
|
|
|
//
|
|
// Get FV Name GUID
|
|
//
|
|
|
|
while (LocalEncapData != NULL) {
|
|
//
|
|
// Has changed.
|
|
//
|
|
if (LocalEncapData->Level > Level) {
|
|
if (LocalEncapData->Type == BFM_ENCAP_TREE_FFS) {
|
|
ParentLevel = Level;
|
|
ParentType = Type;
|
|
}
|
|
|
|
Level = LocalEncapData->Level;
|
|
Type = LocalEncapData->Type;
|
|
}
|
|
|
|
if (LocalEncapData->NextNode != NULL) {
|
|
LocalEncapData = LocalEncapData->NextNode;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
do {
|
|
switch (ParentType) {
|
|
case BFM_ENCAP_TREE_FV:
|
|
|
|
//
|
|
// Generate FV.inf attributes.
|
|
//
|
|
InfFileName = LibFilenameStrExtended (strrchr(GenTempFile (), OS_SEP), TemDir, "inf");
|
|
|
|
InfFile = fopen (InfFileName, "wt+");
|
|
|
|
if (InfFile == NULL) {
|
|
printf ("Could not open inf file %s to store FV information. \n", InfFileName);
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
LocalEncapData = FvInFd->EncapData;
|
|
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) {
|
|
printf ("Out of resource, memory allocation failed. \n");
|
|
fclose (InfFile);
|
|
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)->BlockMap, InfFile, TRUE);
|
|
} else {
|
|
Status = LibFvHeaderOptionToStr(((EFI_FIRMWARE_VOLUME_HEADER *)LocalEncapData->Data)->BlockMap, InfFile, FALSE);
|
|
}
|
|
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
printf ("Generate FV INF file [Options] section failed.\n");
|
|
fclose (InfFile);
|
|
if (FvGuidName != NULL) {
|
|
free (FvGuidName);
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
Status = LibFvHeaderAttributeToStr(((EFI_FIRMWARE_VOLUME_HEADER *)LocalEncapData->Data)->Attributes, InfFile);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
printf ("Generate FV header attribute failed.\n");
|
|
if (FvGuidName != NULL) {
|
|
free (FvGuidName);
|
|
}
|
|
fclose (InfFile);
|
|
return Status;
|
|
}
|
|
if (LocalEncapData->FvExtHeader != NULL) {
|
|
Status = LibGenExtFile(LocalEncapData->FvExtHeader, InfFile);
|
|
if (FvGuidName != NULL) {
|
|
free (FvGuidName);
|
|
}
|
|
if (EFI_ERROR(Status)) {
|
|
printf("Generate FV EXT header failed.\n");
|
|
fclose (InfFile);
|
|
return Status;
|
|
}
|
|
FvGuidName = NULL;
|
|
}
|
|
|
|
//
|
|
// Found FFSs from Fv structure.
|
|
//
|
|
FfsFoundFlag = FALSE;
|
|
for (Index = 0; Index <= FvInFd->FfsNumbers; Index++) {
|
|
|
|
//
|
|
// 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) {
|
|
Status = LibAddFfsFileToFvInf (FvInFd->FfsAttuibutes[Index].FfsName, InfFile, TRUE);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
printf ("Error while generate FV inf file [files] section. \n");
|
|
fclose (InfFile);
|
|
return Status;
|
|
}
|
|
|
|
FvInFd->FfsAttuibutes[Index].Level = 0;
|
|
FirstInFlag = FALSE;
|
|
} else {
|
|
Status = LibAddFfsFileToFvInf (FvInFd->FfsAttuibutes[Index].FfsName, InfFile, FALSE);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
printf ("Error while generate FV inf file [files] section. \n");
|
|
fclose (InfFile);
|
|
return Status;
|
|
}
|
|
|
|
FvInFd->FfsAttuibutes[Index].Level = 0;
|
|
}
|
|
FfsFoundFlag = TRUE;
|
|
}
|
|
//
|
|
// Also add the sub FV
|
|
//
|
|
if (FvInFd->FfsAttuibutes[Index].Level - 1 == ParentLevel+ 1) {
|
|
LocalEncapData = FvInFd->EncapData;
|
|
while (LocalEncapData->NextNode != NULL) {
|
|
if (LocalEncapData->Level == ParentLevel + 2) {
|
|
break;
|
|
}
|
|
LocalEncapData = LocalEncapData->NextNode;
|
|
}
|
|
|
|
if (LocalEncapData->Type == BFM_ENCAP_TREE_GUIDED_SECTION) {
|
|
Status = LibAddFfsFileToFvInf (FvInFd->FfsAttuibutes[Index].FfsName, InfFile, FALSE);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
printf ("Error while generate FV inf file [files] section.\n");
|
|
fclose (InfFile);
|
|
return Status;
|
|
}
|
|
|
|
FvInFd->FfsAttuibutes[Index].Level = 0;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
IsLastLevelFfs = FALSE;
|
|
FirstInFlag = TRUE;
|
|
if (!FfsFoundFlag) {
|
|
Status = LibAddFfsFileToFvInf (OutputFileName, InfFile, TRUE);
|
|
if (EFI_ERROR (Status)) {
|
|
printf ("Error while generate FV inf file [files] section.\n");
|
|
fclose (InfFile);
|
|
return Status;
|
|
}
|
|
}
|
|
/*
|
|
if (OutputFileName != NULL && FfsFoundFlag) {
|
|
Status = LibAddFfsFileToFvInf (OutputFileName, InfFile, FALSE);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
//Error ("FMMT", 0, 0004, "error while encapsulate FD Image", "Generate FV inf file [files] section failed!");
|
|
return Status;
|
|
}
|
|
}
|
|
*/
|
|
//
|
|
// Create FV
|
|
//
|
|
fclose (InfFile);
|
|
OutputFileName= LibFilenameStrExtended (strrchr(GenTempFile (), OS_SEP), TemDir, "FV");
|
|
Status = LibEncapsulateFfsToFv (InfFileName, NULL, OutputFileName, FvGuidName);
|
|
if (FvGuidName != NULL) {
|
|
free (FvGuidName);
|
|
}
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Patch FIT Table Data or reset vector data if exist.
|
|
//
|
|
if ((FvInFd->PatchData != NULL) && (1 == ParentLevel)) {
|
|
Status = LibPatchResetVectorAndFitTableData(OutputFileName, FvInFd->PatchData);
|
|
if (EFI_ERROR (Status)) {
|
|
printf ("Error while patch FIT Table Data or reset vector data. \n");
|
|
return Status;
|
|
}
|
|
}
|
|
|
|
break;
|
|
case BFM_ENCAP_TREE_FFS:
|
|
if (OutputFileName != NULL) {
|
|
InputFileName = OutputFileName;
|
|
OutputFileName= LibFilenameStrExtended (strrchr(GenTempFile (), OS_SEP), TemDir, "ffs");
|
|
|
|
LocalEncapData = FvInFd->EncapData;
|
|
while (LocalEncapData->NextNode != NULL) {
|
|
if (LocalEncapData->Level == Level) {
|
|
break;
|
|
}
|
|
LocalEncapData = LocalEncapData->NextNode;
|
|
}
|
|
|
|
Status = LibEncapSectionFileToFFS(EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE, InputFileName, OutputFileName, ((EFI_FFS_FILE_HEADER *)LocalEncapData->Data)->Name, FALSE, 0);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
printf ("Error while generate FFS file. \n");
|
|
return Status;
|
|
}
|
|
}
|
|
break;
|
|
case BFM_ENCAP_TREE_GUIDED_SECTION:
|
|
//
|
|
// Create the guided section original data, do compress operation.
|
|
//
|
|
InputFileName = OutputFileName;
|
|
OutputFileName= LibFilenameStrExtended (strrchr(GenTempFile (), OS_SEP), TemDir, "compressed");
|
|
|
|
//
|
|
// Use the guided section header guid to find out compress application name.
|
|
//
|
|
LocalEncapData = FvInFd->EncapData;
|
|
while (LocalEncapData->NextNode != NULL) {
|
|
if (LocalEncapData->Level == ParentLevel) {
|
|
break;
|
|
}
|
|
LocalEncapData = LocalEncapData->NextNode;
|
|
}
|
|
|
|
ExtractionTool =
|
|
LookupGuidedSectionToolPath (
|
|
mParsedGuidedSectionTools,
|
|
(EFI_GUID *)LocalEncapData->Data
|
|
);
|
|
|
|
Status = LibCreateGuidedSectionOriginalData (InputFileName, ExtractionTool, OutputFileName);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
printf ("Error while compress guided data. \n");
|
|
return Status;
|
|
}
|
|
|
|
InputFileName = OutputFileName;
|
|
OutputFileName= LibFilenameStrExtended (strrchr(GenTempFile (), OS_SEP), TemDir, "guided");
|
|
|
|
Status = LibCreateFfsSection(InputFileName, NULL, EFI_SECTION_GUID_DEFINED, OutputFileName, NULL, NULL, LibBfmGuidToStr((EFI_GUID *)LocalEncapData->Data), NULL);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
printf ("Error while generate guided section. \n");
|
|
return Status;
|
|
}
|
|
|
|
break;
|
|
case BFM_ENCAP_TREE_COMPRESS_SECTION:
|
|
if (OutputFileName != NULL) {
|
|
InputFileName = OutputFileName;
|
|
|
|
OutputFileName= LibFilenameStrExtended (strrchr(GenTempFile (), OS_SEP), TemDir, "comsec");
|
|
|
|
LocalEncapData = FvInFd->EncapData;
|
|
while (LocalEncapData->NextNode != NULL) {
|
|
if (LocalEncapData->Level == ParentLevel) {
|
|
break;
|
|
}
|
|
LocalEncapData = LocalEncapData->NextNode;
|
|
}
|
|
|
|
Status = LibGenCompressedSection (InputFileName, OutputFileName, *(UINT8 *)(LocalEncapData->Data));
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
printf ("Error while generate compressed section. \n");
|
|
return Status;
|
|
}
|
|
}
|
|
break;
|
|
case BFM_ENCAP_TREE_FV_SECTION:
|
|
InputFileName = OutputFileName;
|
|
OutputFileName= LibFilenameStrExtended (strrchr(GenTempFile (), OS_SEP), TemDir, "sec");
|
|
|
|
Status = LibCreateFfsSection(InputFileName, NULL, EFI_SECTION_FIRMWARE_VOLUME_IMAGE, OutputFileName, NULL, NULL, NULL, NULL);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
printf ("Error while generate FV section. \n");
|
|
return Status;
|
|
}
|
|
|
|
InputFileName = OutputFileName;
|
|
OutputFileName= LibFilenameStrExtended (strrchr(GenTempFile (), OS_SEP), TemDir, "sec");
|
|
|
|
//
|
|
// Make it alignment.
|
|
//
|
|
Status = LibCreateFfsSection(InputFileName, NULL, 0, OutputFileName, NULL, NULL, NULL, NULL);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
printf ("Error while generate FV section. \n");
|
|
return Status;
|
|
}
|
|
|
|
break;
|
|
default:
|
|
printf("Don't know how to encapsulate the FD file! \n");
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
|
|
//
|
|
// Find next level and encapsulate type
|
|
//
|
|
ParentLevel -= 1;
|
|
LocalEncapData = FvInFd->EncapData;
|
|
while (LocalEncapData->NextNode != NULL) {
|
|
if (LocalEncapData->Level == ParentLevel) {
|
|
ParentType = LocalEncapData->Type;
|
|
break;
|
|
}
|
|
LocalEncapData = LocalEncapData->NextNode;
|
|
}
|
|
} while (ParentLevel != 0);
|
|
|
|
|
|
*OutputFile = OutputFileName;
|
|
|
|
return EFI_SUCCESS;
|
|
|
|
}
|
|
|
|
EFI_STATUS
|
|
LibLocateBfv(
|
|
IN FIRMWARE_DEVICE *FdData,
|
|
IN OUT CHAR8 **FvId,
|
|
IN OUT FV_INFORMATION **FvInFd
|
|
)
|
|
{
|
|
UINT8 FvIndex1;
|
|
UINT8 FvIndex2;
|
|
BOOLEAN FvFoundFlag;
|
|
|
|
FvIndex1 = 0;
|
|
FvIndex2 = 0;
|
|
FvFoundFlag = FALSE;
|
|
|
|
if (FdData == NULL || FvId == NULL || FvInFd == NULL) {
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
*FvId = (*FvInFd)->FvName;
|
|
|
|
FvIndex1 = (UINT8) atoi ((*FvInFd)->FvName + 2);
|
|
|
|
*FvInFd = FdData->Fv;
|
|
|
|
while (FvInFd != NULL) {
|
|
if (((*FvInFd)->FvName) != NULL) {
|
|
FvIndex2 = (UINT8) atoi ((*FvInFd)->FvName + 2);
|
|
|
|
if ((FvIndex2 <= FvIndex1) && (((*FvInFd)->FvLevel + FvIndex2) -1 >= FvIndex1)) {
|
|
FvFoundFlag = TRUE;
|
|
break;
|
|
}
|
|
if ((*FvInFd)->FvNext == 0) {
|
|
break;
|
|
}
|
|
*FvInFd = (*FvInFd)->FvNext;
|
|
}
|
|
}
|
|
|
|
//
|
|
// The specified FV id has issue, can not find the FV in FD.
|
|
//
|
|
if (!FvFoundFlag) {
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
|
|
Get the length of a file.
|
|
|
|
@param[in] FileName The name of a file.
|
|
|
|
@retval The length of file.
|
|
|
|
**/
|
|
UINT64
|
|
GetFileSize (
|
|
IN CHAR8 *FileName
|
|
)
|
|
{
|
|
FILE* File;
|
|
UINT64 Length;
|
|
|
|
File = NULL;
|
|
|
|
if (FileName == NULL) {
|
|
return 0;
|
|
}
|
|
File = fopen(FileName, "r");
|
|
|
|
if (File == NULL) {
|
|
return 0;
|
|
}
|
|
fseek(File, 0L, SEEK_END);
|
|
Length = ftell(File);
|
|
fclose(File);
|
|
|
|
return Length;
|
|
}
|
|
|
|
/**
|
|
|
|
Get the length of BFV PAD file.
|
|
|
|
@retval The length of PAD file.
|
|
|
|
**/
|
|
UINT32
|
|
GetBfvPadSize (
|
|
VOID
|
|
)
|
|
{
|
|
return PadSizeOfBfv;
|
|
}
|
|
|