From nobody Mon Feb 9 11:30:19 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+42670+1787277+3901457@groups.io; helo=web01.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+42670+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1561080415; cv=none; d=zoho.com; s=zohoarc; b=FO1Sb1FBcdGzgyTx+u4ajciVpRcITIE0qbijtMc9fDXfs32kI8Uef4YLuAOuWyq1sdLhKx2R8Bvwgk2/de+++zr4zqYp9NtdqVjCIZsDSs21u70ASWc9xiTj85dophk9XGdI83iPKrZZcYcdaF9gahH0eShTOusHjKm8lwXxJSc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1561080415; h=Cc:Date:From:In-Reply-To:List-Id:List-Unsubscribe:Message-ID:Reply-To:References:Sender:Subject:To:ARC-Authentication-Results; bh=EQZDf8iXIIQvmFc61qcKxQUKZg/l8CT57DkmkhoRvyM=; b=FOKhjSIRR2GM1UGijdiDFUCNmRrhKqArkIuLy2YQkx5u0OkVCmHnR8DkNjW5S3Lw7oplJCRUG5imNRLh02/lVhe4jAFa6NpkQWg6Kv/YM56ARlJUBkE3djTjjRSHAspecdxYWbrcivu/eqfnNGX9HhhGlAa8N/vy8bjZcocVpLo= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=pass; spf=pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+42670+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) header.from= Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1561080415785921.5881109259184; Thu, 20 Jun 2019 18:26:55 -0700 (PDT) Return-Path: X-Received: from mga01.intel.com (mga01.intel.com []) by groups.io with SMTP; Thu, 20 Jun 2019 18:26:54 -0700 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-Received: from fmsmga005.fm.intel.com ([10.253.24.32]) by fmsmga101.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 20 Jun 2019 18:26:54 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.63,398,1557212400"; d="scan'208";a="358723167" X-Received: from shenglei-dev.ccr.corp.intel.com ([10.239.158.52]) by fmsmga005.fm.intel.com with ESMTP; 20 Jun 2019 18:26:52 -0700 From: "Zhang, Shenglei" To: devel@edk2.groups.io Cc: Bob Feng , Liming Gao Subject: [edk2-devel] [edk2-platform patch 2/6] Platform\Tools: Add a tool BfmLib Date: Fri, 21 Jun 2019 09:26:39 +0800 Message-Id: <20190621012643.9352-3-shenglei.zhang@intel.com> In-Reply-To: <20190621012643.9352-1-shenglei.zhang@intel.com> References: <20190621012643.9352-1-shenglei.zhang@intel.com> Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,shenglei.zhang@intel.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1561080415; bh=qAAdOhqa+RlYjH069UbLGvADF45E2jzNUz4rmsUHxO8=; h=Cc:Date:From:Reply-To:Subject:To; b=XyvT3xN2TxSyQn9IgTTjz0WtcbylLjn1suDqcvYJpLy2mUMZzqqFctgnmSwrjrieiTo D9ArAAsz54p/U9n9WyUUIlYp70/O1bXXfaiSMjvttULBUA80RPRdvkuanxs8Y9V8/9Jv+ Ds5nLtkrvymGIc4CsrdIitiEgq26IDmgP68= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" BmfLib is added for FCE tool. https://bugzilla.tianocore.org/show_bug.cgi?id=3D1848 Cc: Bob Feng Cc: Liming Gao Signed-off-by: Shenglei Zhang --- Platform/Intel/Tools/BfmLib/BfmLib.c | 4355 ++++++++++++++++++ Platform/Intel/Tools/BfmLib/BinFileManager.c | 1024 ++++ Platform/Intel/Tools/BfmLib/BinFileManager.h | 439 ++ Platform/Intel/Tools/BfmLib/GNUmakefile | 15 + Platform/Intel/Tools/BfmLib/Makefile | 17 + 5 files changed, 5850 insertions(+) create mode 100644 Platform/Intel/Tools/BfmLib/BfmLib.c create mode 100644 Platform/Intel/Tools/BfmLib/BinFileManager.c create mode 100644 Platform/Intel/Tools/BfmLib/BinFileManager.h create mode 100644 Platform/Intel/Tools/BfmLib/GNUmakefile create mode 100644 Platform/Intel/Tools/BfmLib/Makefile diff --git a/Platform/Intel/Tools/BfmLib/BfmLib.c b/Platform/Intel/Tools/Bf= mLib/BfmLib.c new file mode 100644 index 0000000000..9dedda3da2 --- /dev/null +++ b/Platform/Intel/Tools/BfmLib/BfmLib.c @@ -0,0 +1,4355 @@ +/** @file + + Library to process EFI image. + + Copyright (c) 2011-2019, Intel Corporation. All rights reserved.
+ 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) =3D=3D Bit) : ((TestAttributes & Bit) =3D=3D 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\" > /de= v/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] =3D {0x78, 0xE5, 0x8C, 0x8C, 0x3D,= 0x8A, 0x1C, 0x4F, 0x99, 0x35, 0x89, 0x61, 0x85, 0xC3, 0x2D, 0xD3}; + +CHAR8 mFirmwareFileSystem3Guid[16] =3D {0x7A, 0xC0, 0x73, 0x54, 0xCB,= 0x3D, 0xCA, 0x4D, 0xBD, 0x6F, 0x1E, 0x96, 0x89, 0xE7, 0x34, 0x9A }; +extern CHAR8* mGuidToolDefinition; +UINT32 PadSizeOfBfv; + +static CHAR8 *mSectionTypeName[] =3D { + 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[] =3D { + 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 =3D=3D NULL) { + return NULL; + } + + memset (Fv, '\0', sizeof (FV_INFORMATION)); + + for (Index =3D 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 =3D TRUE; + Fv->FfsAttuibutes[Index].TotalSectionNum =3D 0; + } + + Fv->PatchData =3D NULL; + Fv->EncapData =3D NULL; + Fv->FvNext =3D NULL; + Fv->FvLevel =3D 0; + Fv->IsBfvFlag =3D FALSE; + Fv->IsInputFvFlag =3D FALSE; + + return Fv; +} + +/** + Generate the unique template filename. +**/ +CHAR8 * +GenTempFile ( + VOID + ) +{ + CHAR8 *TemString; + TemString =3D NULL; +#ifndef __GNUC__ + TemString =3D CloneString (tmpnam (NULL)); +#else + CHAR8 tmp[] =3D "/tmp/fileXXXXXX"; + UINTN Fdtmp; + Fdtmp =3D mkstemp(tmp); + TemString =3D 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] =3D "_FVH"; + FV_INFORMATION *CurrentFv; + FV_INFORMATION *NewFoundFv; + BOOLEAN FirstMatch; + UINT32 FdSize; + UINT16 FvCount; + VOID *FdBuffer; + VOID *FdBufferOri; + UINT32 Count; + + + CurrentFv =3D NULL; + NewFoundFv =3D NULL; + FdBuffer =3D NULL; + FdBufferOri =3D NULL; + FirstMatch =3D TRUE; + Index =3D 0; + FdSize =3D 0; + FvCount =3D 0; + Count =3D 0; + LocalFdData =3D NULL; + + if (InputFile =3D=3D NULL) { + return EFI_ABORTED; + } + + // + // Find each FVs in the FD + // + + fseek(InputFile,0,SEEK_SET); + fseek(InputFile,0,SEEK_END); + + FdSize =3D ftell(InputFile); + + fseek(InputFile,0,SEEK_SET); + // + // Create an FD structure to store useful information. + // + LocalFdData =3D (FIRMWARE_DEVICE *) calloc (sizeof (FIRMWARE_DEVICE)= , sizeof(UINT8)); + if (LocalFdData =3D=3D NULL) { + return EFI_OUT_OF_RESOURCES; + } + LocalFdData->Fv =3D (FV_INFORMATION *) calloc (sizeof (FV_INFORMATION),= sizeof(UINT8)); + if (LocalFdData->Fv =3D=3D NULL) { + free (LocalFdData); + return EFI_OUT_OF_RESOURCES; + } + LibInitializeFvStruct (LocalFdData->Fv); + + // + // Readout the FD file data to buffer. + // + FdBuffer =3D malloc (FdSize); + + if (FdBuffer =3D=3D NULL) { + free (LocalFdData->Fv); + free (LocalFdData); + return EFI_OUT_OF_RESOURCES; + } + + if (fread (FdBuffer, 1, FdSize, InputFile) !=3D FdSize) { + free (LocalFdData->Fv); + free (LocalFdData); + free (FdBuffer); + return EFI_ABORTED; + } + + FdBufferOri =3D FdBuffer; + + for (Count=3D0; Count < FdSize - 4; Count++) { + // + // Copy 4 bytes of fd data to check the _FVH signature + // + memcpy (SignatureCheck, FdBuffer, 4); + FdBuffer =3D(UINT8 *)FdBuffer + 4; + + if (strncmp(SignatureCheck, Signature, 4) =3D=3D 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 =3D (UINT8 *)FdBuffer - 28; + memcpy (Ffs2Guid, FdBuffer, 16); + + // + // Compare GUID. + // + for (Index =3D 0; Index < 16; Index ++) { + if (Ffs2Guid[Index] !=3D mFirmwareFileSystem2Guid[Index]) { + break; + } + } + if (Index !=3D 16) { + for (Index =3D 0; Index < 16; Index ++) { + if (Ffs2Guid[Index] !=3D mFirmwareFileSystem3Guid[Index]) { + break; + } + } + } + + // + // Point to the original address + // + FdBuffer =3D (UINT8 *)FdBuffer + 28; + + // + // Here we found an FV. + // + if (Index =3D=3D 16) { + if (FirstMatch) { + LocalFdData->Fv->ImageAddress =3D (UINTN)((UINT8 *)FdBuffer - (U= INT8 *)FdBufferOri) - 0x2c; + CurrentFv =3D LocalFdData->Fv; + CurrentFv->FvNext =3D NULL; + // + // Store the FV name by found sequence + // + sprintf(CurrentFv->FvName, "FV%d", FvCount); + + FirstMatch =3D FALSE; + } else { + NewFoundFv =3D (FV_INFORMATION *) malloc (sizeof (FV_INFORMATI= ON)); + if (NULL =3D=3D NewFoundFv) { + free (LocalFdData->Fv); + free (LocalFdData); + free (FdBuffer); + return EFI_OUT_OF_RESOURCES; + } + + LibInitializeFvStruct (NewFoundFv); + + // + // Need to turn back 0x2c bytes + // + NewFoundFv->ImageAddress =3D (UINTN)((UINT8 *)FdBuffer - (UINT= 8 *)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 =3D NULL; + CurrentFv->FvNext =3D NewFoundFv; + + // + // Make the CurrentFv point to next FV. + // + CurrentFv =3D CurrentFv->FvNext; + } + + FvCount ++; + Index =3D 0; + } + + } + + // + // We need to turn back 3 bytes. + // + FdBuffer =3D (UINT8 *)FdBuffer - 3; + } + + LocalFdData->Size =3D FdSize; + + *FdData =3D 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 =3D 0; + Size =3D 0; + + if (InputFile =3D=3D NULL || FvSize =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + fseek (InputFile, sizeof (EFI_FIRMWARE_VOLUME_HEADER) - sizeof (EFI_FV_B= LOCK_MAP_ENTRY), SEEK_CUR); + do { + fread (&BlockMap, sizeof (EFI_FV_BLOCK_MAP_ENTRY), 1, InputFile); + BytesRead +=3D sizeof (EFI_FV_BLOCK_MAP_ENTRY); + + if (BlockMap.NumBlocks !=3D 0) { + Size +=3D BlockMap.NumBlocks * BlockMap.Length; + } + } while (!(BlockMap.NumBlocks =3D=3D 0 && BlockMap.Length =3D=3D 0)); + + + *FvSize =3D 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 =3D 0; + hdr =3D (EFI_FIRMWARE_VOLUME_HEADER*)Fv; + blk =3D hdr->BlockMap; + + while (blk->Length !=3D 0 || blk->NumBlocks !=3D 0) { + *Size =3D *Size + (blk->Length * blk->NumBlocks); + if (*Size >=3D 0x40000000) { + // + // If size is greater than 1GB, then assume it is corrupted + // + return EFI_VOLUME_CORRUPTED; + } + blk++; + } + + if (*Size =3D=3D 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 s= hould be + passed back in without modifying it's contents to re= trieve + subsequent files. + @param[in] File- Output file pointer + File =3D=3D 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 =3D (EFI_FIRMWARE_VOLUME_HEADER*)Fv; + fhdr =3D NULL; + + if (Fv =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + Status =3D FvBufGetSize (Fv, &fvSize); + if (EFI_ERROR (Status)) { + return Status; + } + + if (*Key =3D=3D 0) { + if (hdr->ExtHeaderOffset !=3D 0) { + // + // Searching for files starts on an 8 byte aligned boundary after th= e end of the Extended Header if it exists. + // + FwVolExtHeader =3D (EFI_FIRMWARE_VOLUME_EXT_HEADER *) ((UINT8 *) hdr= + hdr->ExtHeaderOffset); + *Key =3D (UINTN)hdr->ExtHeaderOffset + FwVolExtHeader->ExtHeaderSiz= e; + *Key =3D (UINTN)ALIGN_POINTER (*Key, 8); + } else { + *Key =3D hdr->HeaderLength; + } + } + + FvbAttributes =3D hdr->Attributes; + + for( + *Key =3D (UINTN)ALIGN_POINTER (*Key, 8); + (*Key + sizeof (*fhdr)) < fvSize; + *Key =3D (UINTN)ALIGN_POINTER (*Key, 8) + ) { + fhdr =3D (EFI_FFS_FILE_HEADER*) ((UINT8*)hdr + *Key); + fsize =3D 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 =3D *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 =3D *Key + fsize; + continue; + } else if (EFI_TEST_FFS_ATTRIBUTES_BIT( + FvbAttributes, + fhdr->State, + EFI_FILE_DATA_VALID + ) + ) { + *File =3D (UINT8*)hdr + *Key; + *Key =3D *Key + fsize; + return EFI_SUCCESS; + } + + *Key =3D *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 =3D 0; + FfsFileName =3D NULL; + FfsFile =3D NULL; + TempDir =3D NULL; + + TempDir =3D 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 =3D (CHAR8 *) malloc (_MAX_PATH); + if (NULL =3D=3D FfsFileName) { + return EFI_ABORTED; + } + memset (FfsFileName, '\0', _MAX_PATH); + FfsFileSize =3D 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) + st= rlen(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 =3D (UINT8)~(CurrentFile->State); + } + + FfsFile =3D fopen (FfsFileName, "wb+"); + if (FfsFile =3D=3D NULL) { + free(FfsFileName); + return EFI_ABORTED; + } + + if (fwrite (CurrentFile, 1, FfsFileSize, FfsFile) !=3D FfsFileSize) { + fclose(FfsFile); + free(FfsFileName); + return EFI_ABORTED; + } + + fclose(FfsFile); + free(FfsFileName); + FfsFileName =3D NULL; + + CurrentFv->FfsNumbers =3D *FfsCount; + + *FfsCount +=3D 1; + + if (ErasePolarity) { + CurrentFile->State =3D (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 =3D NULL; + + FfsFileSize =3D GetFfsFileLength ((EFI_FFS_FILE_HEADER *) CurrentFile); + FfsDataSize =3D FfsFileSize - GetFfsHeaderLength ((EFI_FFS_FILE_HEADER = *) CurrentFile); + FfsData =3D (EFI_GUID *) ((INT8 *)CurrentFile + GetFfsHeaderLength = ((EFI_FFS_FILE_HEADER *) CurrentFile)); + + if (FfsDataSize =3D=3D 0) { + return TRUE; + } + + LocalEncapData =3D CurrentFv->EncapData; + + do { + if (LocalEncapData->FvExtHeader !=3D NULL) { + if (CompareGuid(FfsData, &LocalEncapData->FvExtHeader->FvName) =3D= =3D 0) { + return TRUE; + } + } + LocalEncapData =3D LocalEncapData->NextNode; + } while (LocalEncapData->NextNode !=3D NULL); + + return FALSE; +} + +BOOLEAN +LibCheckPadFfsNotNull ( + IN EFI_FFS_FILE_HEADER2 *CurrentFile +) +{ + UINT32 FfsFileSize; + UINT32 FfsDataSize; + INT8 *FfsData; + + FfsFileSize =3D GetFfsFileLength ((EFI_FFS_FILE_HEADER *) CurrentFile); + FfsDataSize =3D FfsFileSize - GetFfsHeaderLength ((EFI_FFS_FILE_HEADER = *) CurrentFile); + FfsData =3D (INT8 *)CurrentFile + GetFfsHeaderLength ((EFI_FFS_FILE= _HEADER *) CurrentFile); + + if (FfsDataSize =3D=3D 0) { + return FALSE; + } + + while (FfsDataSize > 0) { + if (((FfsData[FfsDataSize-1]) & 0xFF) !=3D 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 =3D 0; + MaxSize =3D 0; + + if (PadFfsHeader =3D=3D NULL) { + return MaxSize; + } + + FfsSize =3D GetFfsFileLength ((EFI_FFS_FILE_HEADER *) PadFfsHeader); + HeaderSize =3D GetFfsHeaderLength ((EFI_FFS_FILE_HEADER *) PadFfsHeade= r); + + for (Count =3D HeaderSize; Count < FfsSize; Count++) { + if (((((INT8 *)PadFfsHeader)[Count]) & 0xFF) =3D=3D 0xFF) { + Index++; + } else { + if (Index > MaxSize) { + MaxSize =3D Index; + } + Index =3D 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 addition= al 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 =3D 0; + Count1 =3D 0; + Count2 =3D 0; + FfsOffset =3D 0; + DataOffset =3D 0; + FfsFoundFlag =3D FALSE; + LocalPatchData =3D NULL; + + if (CurrentFv =3D=3D NULL || CurrentFile =3D=3D NULL || FvImage =3D=3D N= ULL) { + return EFI_ABORTED; + } + + FfsFileSize =3D GetFfsFileLength ((EFI_FFS_FILE_HEADER *) CurrentFile); + HeaderSize =3D GetFfsHeaderLength ((EFI_FFS_FILE_HEADER *) CurrentFile= ); + + for (Count1=3D0; Count1 < (FvImage->FvLength - FfsFileSize); Count1 ++) { + for (Count2=3D0; Count2 < FfsFileSize; Count2 ++) { + if (((INT8*)FvImage)[Count1 + Count2] !=3D ((INT8 *) CurrentFile)[Co= unt2]){ + break; + } + } + if (Count2 =3D=3D FfsFileSize) { + FfsFoundFlag =3D TRUE; + FfsOffset =3D Count1; + break; + } + } + + if (FfsFoundFlag) { + // + // Find data in FFS file; + // Will skip FFS header; + // + for (Count1 =3D HeaderSize; Count1 < FfsFileSize; Count1++) { + if (((((INT8 *)CurrentFile)[Count1]) & 0xFF) !=3D 0xFF) { + DataOffset =3D FfsOffset + Count1; + break; + } + } + + if (CurrentFv->PatchData =3D=3D NULL) { + // + // First time found data. + // + CurrentFv->PatchData =3D (PATCH_DATA_PAD_FFS *) malloc (sizeof (PATC= H_DATA_PAD_FFS)); + if (CurrentFv->PatchData =3D=3D NULL) { + return EFI_ABORTED; + } + + CurrentFv->PatchData->Offset =3D DataOffset; + CurrentFv->PatchData->Data =3D malloc(FfsFileSize - Count1); + CurrentFv->PatchData->Length =3D FfsFileSize - Count1; + CurrentFv->PatchData->NextNode =3D NULL; + + if (CurrentFv->PatchData->Data =3D=3D NULL) { + return EFI_ABORTED; + } + + memcpy (CurrentFv->PatchData->Data, (INT8 *)CurrentFile + Count1, Ff= sFileSize - Count1); + } else { + LocalPatchData =3D CurrentFv->PatchData; + + while (LocalPatchData->NextNode !=3D NULL) { + LocalPatchData =3D LocalPatchData->NextNode; + } + + LocalPatchData =3D (PATCH_DATA_PAD_FFS *) malloc (sizeof (PATCH_DATA= _PAD_FFS)); + + if (LocalPatchData =3D=3D NULL) { + return EFI_ABORTED; + } + + LocalPatchData->Offset =3D DataOffset; + LocalPatchData->Data =3D malloc(FfsFileSize - Count1); + LocalPatchData->Length =3D FfsFileSize - Count1; + LocalPatchData->NextNode =3D NULL; + + if (LocalPatchData->Data =3D=3D NULL) { + free (LocalPatchData); + return EFI_ABORTED; + } + + memcpy (LocalPatchData->Data, (INT8 *)CurrentFile + Count1, FfsFileS= ize - Count1); + while (CurrentFv->PatchData->NextNode !=3D NULL) { + CurrentFv->PatchData =3D CurrentFv->PatchData->NextNode; + } + CurrentFv->PatchData->NextNode =3D 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 =3D 0; + RetStr =3D NULL; + + RetStr =3D (CHAR8 *) malloc (Count +1); + + if (NULL =3D=3D RetStr) { + return NULL; + } + + memset (RetStr , '\0', Count + 1); + + for (Index=3D0; Index <=3D Count -1; Index ++) { + RetStr[Index] =3D ' '; + } + + return RetStr; + +} + +VOID +Unicode2AsciiString ( + IN CHAR16 *Source, + OUT CHAR8 *Destination + ) + /*++ + + Routine Description: + + Convert a null-terminated unicode string to a null-terminated ascii stri= ng. + + 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 !=3D '\0') { + *(Destination++) =3D (CHAR8) *(Source++); + } + // + // End the ascii with a NULL. + // + *Destination =3D '\0'; +} + + +/** + + Parses EFI Sections, if the view flag turn on, then will collect FFS sec= tion 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 =3D 0; + ToolOutputLength =3D 0; + UINameSize =3D 0; + NumberOfSections =3D 0; + UncompressedLength =3D 0; + CompressedLength =3D 0; + CompressionType =3D 0; + DstSize =3D 0; + ScratchSize =3D 0; + Ptr =3D NULL; + ExtractionTool =3D NULL; + ToolInputFile =3D NULL; + ToolOutputFile =3D NULL; + SystemCommand =3D NULL; + ToolOutputBuffer =3D NULL; + UIName =3D NULL; + LocalEncapData =3D NULL; + BlankChar =3D NULL; + UncompressedBuffer =3D NULL; + CompressedBuffer =3D NULL; + ScratchBuffer =3D NULL; + TempDir =3D NULL; + ToolInputFileFullName =3D NULL; + ToolOutputFileFullName =3D NULL; + ToolInputFileName =3D NULL; + ToolOutputFileName =3D NULL; + HasDepexSection =3D FALSE; + IsFfsGenerated =3D FfsGeneratedFlag; + EncapDataNeedUpdata =3D TRUE; + LargeHeaderOffset =3D 0; + + + while (ParsedLength < BufferLength) { + Ptr =3D SectionBuffer + ParsedLength; + + SectionLength =3D FvBufExpand3ByteSize (((EFI_COMMON_SECTION_HEADER *)= Ptr)->Size); + Type =3D ((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 se= ction + // header worth of 0xFF bytes. + // + if (SectionLength =3D=3D 0xffffff && Type =3D=3D 0xff) { + ParsedLength +=3D 4; + continue; + } + // + //If Size is 0xFFFFFF then ExtendedSize contains the size of the section. + // + if (SectionLength =3D=3D 0xffffff) { + SectionLength =3D ((EFI_COMMON_SECTION_HEADER2 *) Ptr)->ExtendedSi= ze; + LargeHeaderOffset =3D sizeof (EFI_COMMON_SECTION_HEADER2) - sizeof (EF= I_COMMON_SECTION_HEADER); + } + + switch (Type) { + + case EFI_SECTION_FIRMWARE_VOLUME_IMAGE: + EncapDataNeedUpdata =3D TRUE; + + Level ++; + NumberOfSections ++; + + CurrentFv->FfsAttuibutes[*FfsCount].IsLeaf =3D FALSE; + + // + // Put in encapsulate data information. + // + LocalEncapData =3D CurrentFv->EncapData; + while (LocalEncapData->NextNode !=3D NULL) { + if (LocalEncapData->Level =3D=3D Level) { + EncapDataNeedUpdata =3D FALSE; + break; + } + LocalEncapData =3D LocalEncapData->NextNode; + } + + if (EncapDataNeedUpdata) { + // + // Put in this is an FFS with FV section + // + LocalEncapData =3D CurrentFv->EncapData; + while (LocalEncapData->NextNode !=3D NULL) { + LocalEncapData =3D LocalEncapData->NextNode; + } + + // + // Construct the new ENCAP_DATA + // + LocalEncapData->NextNode =3D (ENCAP_INFO_DATA *) malloc (sizeof (E= NCAP_INFO_DATA)); + + if (LocalEncapData->NextNode =3D=3D NULL) { + return EFI_ABORTED; + } + + LocalEncapData =3D LocalEncapData->NextNode; + + LocalEncapData->Level =3D Level; + LocalEncapData->Type =3D BFM_ENCAP_TREE_FV_SECTION; + + // + // We don't need additional data for encapsulate this FFS but type. + // + LocalEncapData->Data =3D NULL; + LocalEncapData->FvExtHeader =3D NULL; + LocalEncapData->NextNode =3D NULL; + } + + Status =3D LibGetFvInfo ((UINT8*)((EFI_FIRMWARE_VOLUME_IMAGE_SECTION= *)Ptr + 1) + LargeHeaderOffset, CurrentFv, FvName, Level, FfsCount, ViewFla= g, TRUE); + if (EFI_ERROR (Status)) { + return EFI_SECTION_ERROR; + } + break; + + case EFI_SECTION_COMPRESSION: + Level ++; + NumberOfSections ++; + + EncapDataNeedUpdata =3D TRUE; + // + // Put in encapsulate data information. + // + LocalEncapData =3D CurrentFv->EncapData; + while (LocalEncapData->NextNode !=3D NULL) { + if (LocalEncapData->Level =3D=3D Level) { + EncapDataNeedUpdata =3D FALSE; + break; + } + LocalEncapData =3D LocalEncapData->NextNode; + } + + if (EncapDataNeedUpdata) { + // + // Put in this is an FFS with FV section + // + LocalEncapData =3D CurrentFv->EncapData; + while (LocalEncapData->NextNode !=3D NULL) { + LocalEncapData =3D LocalEncapData->NextNode; + } + + // + // Construct the new ENCAP_DATA + // + LocalEncapData->NextNode =3D (ENCAP_INFO_DATA *) malloc (sizeof (E= NCAP_INFO_DATA)); + + if (LocalEncapData->NextNode =3D=3D NULL) { + return EFI_ABORTED; + } + + LocalEncapData =3D LocalEncapData->NextNode; + + LocalEncapData->Level =3D Level; + LocalEncapData->Type =3D BFM_ENCAP_TREE_COMPRESS_SECTION; + + // + // Store the compress type + // + LocalEncapData->Data =3D malloc (sizeof (UINT8)); + + if (LocalEncapData->Data =3D=3D NULL) { + return EFI_OUT_OF_RESOURCES; + } + + *(UINT8 *)LocalEncapData->Data =3D ((EFI_COMPRESSION_SECTION *= ) (Ptr + LargeHeaderOffset))->CompressionType; + LocalEncapData->FvExtHeader =3D NULL; + LocalEncapData->NextNode =3D NULL; + } + + // + // Process compressed section + // + CurrentFv->FfsAttuibutes[*FfsCount].IsLeaf =3D FALSE; + + UncompressedBuffer =3D NULL; + CompressedLength =3D SectionLength - sizeof (EFI_COMPRESSION_SECT= ION) - LargeHeaderOffset; + UncompressedLength =3D ((EFI_COMPRESSION_SECTION *) (Ptr + LargeHea= derOffset))->UncompressedLength; + CompressionType =3D ((EFI_COMPRESSION_SECTION *) (Ptr + LargeHea= derOffset))->CompressionType; + + if (CompressionType =3D=3D EFI_NOT_COMPRESSED) { + + if (CompressedLength !=3D UncompressedLength) { + printf ("Error. File is not compressed, but the compressed lengt= h does not match the uncompressed length.\n"); + return EFI_SECTION_ERROR; + } + + UncompressedBuffer =3D Ptr + sizeof (EFI_COMPRESSION_SECTION) + La= rgeHeaderOffset; + } else if (CompressionType =3D=3D EFI_STANDARD_COMPRESSION) { + GetInfoFunction =3D EfiGetInfo; + DecompressFunction =3D EfiDecompress; + + CompressedBuffer =3D Ptr + sizeof (EFI_COMPRESSION_SECTION) + Lar= geHeaderOffset; + + Status =3D GetInfoFunction (CompressedBuffer, Compresse= dLength, &DstSize, &ScratchSize); + if (EFI_ERROR (Status)) { + return EFI_SECTION_ERROR; + } + + if (DstSize !=3D UncompressedLength) { + return EFI_SECTION_ERROR; + } + + ScratchBuffer =3D malloc (ScratchSize); + if (ScratchBuffer =3D=3D NULL) { + return EFI_OUT_OF_RESOURCES; + } + UncompressedBuffer =3D malloc (UncompressedLength); + + if (UncompressedBuffer =3D=3D NULL) { + free (ScratchBuffer); + return EFI_OUT_OF_RESOURCES; + } + // + // Decompress the section. + // + Status =3D 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 =3D LibParseSection ( UncompressedBuffer, + UncompressedLength, + CurrentFv, + FvName, + CurrentFile, + Level, + FfsCount, + ViewFlag, + ErasePolarity, + IsFfsGenerated); + + if (CompressionType =3D=3D 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 =3D TRUE; + // + // Put in encapsulate data information. + // + LocalEncapData =3D CurrentFv->EncapData; + while (LocalEncapData->NextNode !=3D NULL) { + if (LocalEncapData->Level =3D=3D Level) { + EncapDataNeedUpdata =3D FALSE; + break; + } + LocalEncapData =3D LocalEncapData->NextNode; + } + if (EncapDataNeedUpdata) { + + // + // Put in this is an FFS with FV section + // + LocalEncapData =3D CurrentFv->EncapData; + while (LocalEncapData->NextNode !=3D NULL) { + LocalEncapData =3D LocalEncapData->NextNode; + } + + // + // Construct the new ENCAP_DATA + // + LocalEncapData->NextNode =3D (ENCAP_INFO_DATA *) malloc (sizeof (E= NCAP_INFO_DATA)); + + if (LocalEncapData->NextNode =3D=3D NULL) { + return EFI_ABORTED; + } + + LocalEncapData =3D LocalEncapData->NextNode; + + LocalEncapData->Level =3D Level; + LocalEncapData->Type =3D BFM_ENCAP_TREE_GUIDED_SECTION; + + // + // We don't need additional data for encapsulate this FFS but type. + // + + LocalEncapData->Data =3D (EFI_GUID *) malloc (sizeof (EFI_GUID= )); + + if (LocalEncapData->Data =3D=3D NULL) { + return EFI_ABORTED; + } + + memcpy (LocalEncapData->Data, &((EFI_GUID_DEFINED_SECTION *) (Ptr + La= rgeHeaderOffset))->SectionDefinitionGuid, sizeof (EFI_GUID)); + + LocalEncapData->FvExtHeader =3D NULL; + LocalEncapData->NextNode =3D NULL; + } + + CurrentFv->FfsAttuibutes[*FfsCount].IsLeaf =3D FALSE; + + ExtractionTool =3D + LookupGuidedSectionToolPath ( + mParsedGuidedSectionTools, + &((EFI_GUID_DEFINED_SECTION *) (Ptr + LargeHeaderOffset))->Secti= onDefinitionGuid + ); + + if ((((EFI_GUID_DEFINED_SECTION *) (Ptr + LargeHeaderOffset))->Attri= butes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) =3D=3D 0) { + // + // Not require process, directly gets data. + // + Status =3D LibParseSection ( + Ptr + ((EFI_GUID_DEFINED_SECTION *) (Ptr + LargeHeaderOffset))->= DataOffset, + SectionLength - ((EFI_GUID_DEFINED_SECTION *) (Ptr + LargeHeader= Offset))->DataOffset, + CurrentFv, + FvName, + CurrentFile, + Level, + FfsCount, + ViewFlag, + ErasePolarity, + IsFfsGenerated + ); + if (ExtractionTool !=3D NULL) { + free (ExtractionTool); + ExtractionTool =3D NULL; + } + if (EFI_ERROR (Status)) { + return EFI_SECTION_ERROR; + } + } else if (ExtractionTool !=3D NULL) { + + TempDir =3D 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 =3D GenTempFile (); + ToolOutputFile =3D GenTempFile (); + ToolInputFileName =3D strrchr(ToolInputFile, OS_SEP); + ToolOutputFileName =3D strrchr(ToolOutputFile, OS_SEP); + + ToolInputFileFullName =3D malloc (strlen("%s%s") + strlen(TempDi= r) + strlen(ToolInputFileName) + 1); + if (ToolInputFileFullName =3D=3D NULL) { + free (ExtractionTool); + free (ToolInputFile); + free (ToolOutputFile); + return EFI_OUT_OF_RESOURCES; + } + ToolOutputFileFullName =3D malloc (strlen("%s%s") + strlen(TempDi= r) + strlen(ToolOutputFileName) + 1); + if (ToolOutputFileFullName =3D=3D 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, ToolOutputFileNa= me); + + // + // Construction 'system' command string + // + SystemCommand =3D malloc ( + strlen (DECODE_STR) + + strlen (ExtractionTool) + + strlen (ToolInputFileFullName) + + strlen (ToolOutputFileFullName) + + 1 + ); + if (SystemCommand =3D=3D NULL) { + free (ToolInputFile); + free (ToolOutputFile); + free (ToolInputFileFullName); + free (ToolOutputFileFullName); + free (ExtractionTool); + return EFI_OUT_OF_RESOURCES; + } + sprintf ( + SystemCommand, + DECODE_STR, + ExtractionTool, + ToolOutputFileFullName, + ToolInputFileFullName + ); + + Status =3D PutFileImage ( + ToolInputFileFullName, + (CHAR8*) Ptr + ((EFI_GUID_DEFINED_SECTION *) (Ptr + LargeHeaderOff= set))->DataOffset, + SectionLength - ((EFI_GUID_DEFINED_SECTION *) (Ptr + LargeHeaderOf= fset))->DataOffset + ); + + if (HasDepexSection) { + HasDepexSection =3D FALSE; + } + + if (EFI_ERROR (Status)) { + free(SystemCommand); + free (ToolOutputFileFullName); + free (ToolOutputFile); + remove (ToolInputFileFullName); + free (ToolInputFile); + free (ToolInputFileFullName); + return EFI_SECTION_ERROR; + } + + if (system (SystemCommand) !=3D EFI_SUCCESS) { + SystemCommand =3D malloc ( + strlen (DECODE_STR_ERR) + + strlen (ExtractionTool) + + strlen (ToolInputFileFullName) + + strlen (ToolOutputFileFullName) + + 1 + ); + if (SystemCommand =3D=3D 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 =3D NULL; + LibRmDir (TempDir); + free(SystemCommand); + remove (ToolInputFileFullName); + free (ToolInputFile); + free (ToolInputFileFullName); + free (ToolOutputFileFullName); + free (ToolOutputFile); + return EFI_ABORTED; + } + free (ExtractionTool); + ExtractionTool =3D NULL; + free (SystemCommand); + remove (ToolInputFileFullName); + free (ToolInputFile); + free (ToolInputFileFullName); + ToolInputFile =3D NULL; + ToolInputFileFullName =3D NULL; + + + Status =3D GetFileImage ( + ToolOutputFileFullName, + (CHAR8 **)&ToolOutputBuffer, + &ToolOutputLength + ); + remove (ToolOutputFileFullName); + free (ToolOutputFile); + free (ToolOutputFileFullName); + ToolOutputFile =3D NULL; + ToolOutputFileFullName =3D NULL; + + if (EFI_ERROR (Status)) { + return EFI_SECTION_ERROR; + } + + Status =3D 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 !=3D NULL) { + free (ExtractionTool); + ExtractionTool =3D 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", mGuidT= oolDefinition); + 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 =3D Level; + if (!ViewFlag) { + if (!IsFfsGenerated) { + LibGenFfsFile(CurrentFile, CurrentFv, FvName, Level, FfsCount, E= rasePolarity); + IsFfsGenerated =3D TRUE; + } + } + + break; + case EFI_SECTION_PE32: + NumberOfSections ++; + CurrentFv->FfsAttuibutes[*FfsCount].Level =3D Level; + if (!ViewFlag) { + if (!IsFfsGenerated) { + LibGenFfsFile(CurrentFile, CurrentFv, FvName, Level, FfsCount, E= rasePolarity); + IsFfsGenerated =3D TRUE; + } + } + + break; + case EFI_SECTION_PIC: + NumberOfSections ++; + CurrentFv->FfsAttuibutes[*FfsCount].Level =3D Level; + if (!ViewFlag) { + if (!IsFfsGenerated) { + LibGenFfsFile(CurrentFile, CurrentFv, FvName, Level, FfsCount, E= rasePolarity); + IsFfsGenerated =3D TRUE; + } + } + + break; + case EFI_SECTION_TE: + NumberOfSections ++; + CurrentFv->FfsAttuibutes[*FfsCount].Level =3D Level; + if (!ViewFlag) { + if (!IsFfsGenerated) { + LibGenFfsFile(CurrentFile, CurrentFv, FvName, Level, FfsCount, E= rasePolarity); + IsFfsGenerated =3D TRUE; + } + } + break; + + case EFI_SECTION_COMPATIBILITY16: + NumberOfSections ++; + CurrentFv->FfsAttuibutes[*FfsCount].Level =3D Level; + + if (!ViewFlag) { + if (!IsFfsGenerated) { + LibGenFfsFile(CurrentFile, CurrentFv, FvName, Level, FfsCount, E= rasePolarity); + IsFfsGenerated =3D TRUE; + } + } + break; + + case EFI_SECTION_FREEFORM_SUBTYPE_GUID: + NumberOfSections ++; + CurrentFv->FfsAttuibutes[*FfsCount].Level =3D Level; + if (!ViewFlag) { + if (!IsFfsGenerated) { + LibGenFfsFile(CurrentFile, CurrentFv, FvName, Level, FfsCount, E= rasePolarity); + IsFfsGenerated =3D TRUE; + } + } + break; + + case EFI_SECTION_VERSION: + NumberOfSections ++; + CurrentFv->FfsAttuibutes[*FfsCount].Level =3D Level; + break; + case EFI_SECTION_PEI_DEPEX: + NumberOfSections ++; + CurrentFv->FfsAttuibutes[*FfsCount].Level =3D Level; + HasDepexSection =3D TRUE; + break; + case EFI_SECTION_DXE_DEPEX: + NumberOfSections ++; + CurrentFv->FfsAttuibutes[*FfsCount].Level =3D Level; + HasDepexSection =3D TRUE; + break; + case EFI_SECTION_SMM_DEPEX: + NumberOfSections ++; + CurrentFv->FfsAttuibutes[*FfsCount].Level =3D Level; + HasDepexSection =3D TRUE; + break; + + case EFI_SECTION_USER_INTERFACE: + NumberOfSections ++; + CurrentFv->FfsAttuibutes[*FfsCount].Level =3D Level; + + UiSectionLength =3D FvBufExpand3ByteSize (((EFI_USER_INTERFACE_SECTI= ON *) Ptr)->CommonHeader.Size); + if (UiSectionLength =3D=3D 0xffffff) { + UiSectionLength =3D ((EFI_USER_INTERFACE_SECTION2 *) Ptr)->CommonH= eader.ExtendedSize; + UINameSize =3D UiSectionLength - sizeof(EFI_COMMON_SECTION_HEAD= ER2); + } else { + UINameSize =3D UiSectionLength - sizeof(EFI_COMMON_SECTION_HEADER); + } + + UIName =3D (CHAR16 *) malloc (UINameSize + 2); + if (UIName !=3D NULL) { + memset (UIName, '\0', UINameSize + 2); + if (UiSectionLength >=3D 0xffffff) { + memcpy(UIName, ((EFI_USER_INTERFACE_SECTION2 *) Ptr)->FileNameSt= ring, UINameSize); + } else { + memcpy(UIName, ((EFI_USER_INTERFACE_SECTION *) Ptr)->FileNameStr= ing, UINameSize); + } + } else { + return EFI_ABORTED; + } + + BlankChar =3D LibConstructBlankChar( CurrentFv->FvLevel * 2); + if (BlankChar =3D=3D NULL) { + free (UIName); + return EFI_ABORTED; + } + + if (ViewFlag) { + UIFileName =3D malloc (UINameSize + 2); + if (UIFileName =3D=3D 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 =3D NULL; + + // + // If Ffs file has been generated, then the FfsCount should decrease= 1. + // + if (IsFfsGenerated) { + memcpy (CurrentFv->FfsAttuibutes[*FfsCount -1].UiName, UIName, UIN= ameSize); + } else { + memcpy (CurrentFv->FfsAttuibutes[*FfsCount].UiName, UIName, UIName= Size); + } + HasDepexSection =3D FALSE; + free(UIName); + UINameSize =3D 0; + + break; + default: + break; + } + + ParsedLength +=3D SectionLength; + // + // We make then next section begin on a 4-byte boundary + // + ParsedLength =3D 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 =3D EFI_SUCCESS; + + LocalEncapData =3D NULL; + EncapDataNeedUpdateFlag =3D TRUE; + + FfsFileHeaderSize =3D GetFfsHeaderLength ((EFI_FFS_FILE_HEADER *) Curre= ntFile); + FileLength =3D GetFfsFileLength ((EFI_FFS_FILE_HEADER *) CurrentF= ile); + + // + // 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) =3D=3D 0) { + return EFI_SUCCESS; + } + + // + // Print file information. + // + FileState =3D GetFileState (ErasePolarity, (EFI_FFS_FILE_HEADER *)Curren= tFile); + + if (FileState =3D=3D EFI_FILE_DATA_VALID) { + // + // Calculate header checksum + // + Checksum =3D CalculateSum8 ((UINT8 *) CurrentFile, FfsFileHeaderSize); + Checksum =3D (UINT8) (Checksum - CurrentFile->IntegrityCheck.Checksum= .File); + Checksum =3D (UINT8) (Checksum - CurrentFile->State); + if (Checksum !=3D 0) { + return EFI_ABORTED; + } + + if (CurrentFile->Attributes & FFS_ATTRIB_CHECKSUM) { + // + // Calculate file checksum + // + Checksum =3D CalculateSum8 ((UINT8 *) ((UINTN)CurrentFile + FfsFile= HeaderSize), FileLength - FfsFileHeaderSize); + Checksum =3D Checksum + CurrentFile->IntegrityCheck.Checksum.File; + if (Checksum !=3D 0) { + return EFI_ABORTED; + } + } else { + if (CurrentFile->IntegrityCheck.Checksum.File !=3D FFS_FIXED_CHECKSU= M) { + return EFI_ABORTED; + } + } + } else { + return EFI_ABORTED; + } + + Level +=3D 1; + + if (CurrentFile->Type !=3D EFI_FV_FILETYPE_ALL) { + + // + // Put in encapsulate data information. + // + LocalEncapData =3D CurrentFv->EncapData; + while (LocalEncapData->NextNode !=3D NULL) { + if (LocalEncapData->Level =3D=3D Level) { + EncapDataNeedUpdateFlag =3D FALSE; + break; + } + LocalEncapData =3D LocalEncapData->NextNode; + } + + if (EncapDataNeedUpdateFlag) { + // + // Construct the new ENCAP_DATA + // + LocalEncapData->NextNode =3D (ENCAP_INFO_DATA *) malloc (sizeof (ENC= AP_INFO_DATA)); + + if (LocalEncapData->NextNode =3D=3D NULL) { + printf ("Out of resource, memory allocation failed. \n"); + return EFI_ABORTED; + } + + LocalEncapData =3D LocalEncapData->NextNode; + + LocalEncapData->Level =3D Level; + LocalEncapData->Type =3D BFM_ENCAP_TREE_FFS; + LocalEncapData->FvExtHeader =3D NULL; + + // + // Store the header of FFS file. + // + LocalEncapData->Data =3D malloc (FfsFileHeaderSize); + if (LocalEncapData->Data =3D=3D NULL) { + printf ("Out of resource, memory allocation failed. \n"); + return EFI_ABORTED; + } + + memcpy (LocalEncapData->Data, CurrentFile, FfsFileHeaderSize); + + LocalEncapData->NextNode =3D NULL; + } + + if ( CurrentFile->Type =3D=3D EFI_FV_FILETYPE_FREEFORM ){ + CurrentFv->FfsAttuibutes[*FfsCount].Level =3D Level; + if (!ViewFlag) { + LibGenFfsFile(CurrentFile, CurrentFv, FvName, Level, FfsCount, Era= sePolarity); + } + }else if ( CurrentFile->Type =3D=3D EFI_FV_FILETYPE_RAW){ + CurrentFv->FfsAttuibutes[*FfsCount].Level =3D Level; + if (!ViewFlag){ + LibGenFfsFile(CurrentFile, CurrentFv, FvName, Level, FfsCount, Era= sePolarity); + } + } else if ( CurrentFile->Type =3D=3D EFI_FV_FILETYPE_SECURITY_CORE){ + CurrentFv->FfsAttuibutes[*FfsCount].Level =3D Level; + // + // If an FV contain SECCORE, this FV will be considered as BFV. + // + CurrentFv->IsBfvFlag =3D TRUE; + if (!ViewFlag){ + LibGenFfsFile(CurrentFile, CurrentFv, FvName, Level, FfsCount, Era= sePolarity); + } + } else if( CurrentFile->Type =3D=3D EFI_FV_FILETYPE_FFS_PAD){ + // + // First check whether the FFS file contain FvExtended FvNameGuid in= formation. + // + if (!LibCheckPadFfsContainFvNameGuid (CurrentFv, CurrentFile)) { + // + // Then check whether the PAD file have no additional data or not. + // + if (LibCheckPadFfsNotNull (CurrentFile)) { + CurrentFv->FfsAttuibutes[*FfsCount].Level =3D Level; + // + // Get the size of PAD in BFV + // + PadSizeOfBfv =3D GetBfvMaxFreeSpace (CurrentFile); + if (!ViewFlag){ + // + //LibGenFfsFile(CurrentFile, CurrentFv, FvName, Level, FfsCoun= t, ErasePolarity); + // + Status =3D LibFindResetVectorAndFitTableData (FvImage, Current= File, 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 =3D 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 =3D 0; + Key =3D 0; + LocalEncapData =3D NULL; + CurrentFile =3D NULL; + + Level +=3D 1; + CurrentFv->FvLevel +=3D 1; + + Status =3D FvBufGetSize (Fv, &FvSize); + + ErasePolarity =3D (((EFI_FIRMWARE_VOLUME_HEADER*)Fv)->Attributes & EFI_F= VB2_ERASE_POLARITY) ? TRUE : FALSE; + + if (!IsChildFv) { + // + // Write FV header information into CurrentFv struct. + // + CurrentFv->FvHeader =3D (EFI_FIRMWARE_VOLUME_HEADER *) malloc (sizeof = (EFI_FIRMWARE_VOLUME_HEADER)); + + if (CurrentFv->FvHeader =3D=3D NULL) { + return EFI_ABORTED; + } + + // + // Get the FV Header information + // + memcpy (CurrentFv->FvHeader, Fv, sizeof (EFI_FIRMWARE_VOLUME_HEADER)); + CurrentFv->FvExtHeader =3D NULL; + + // + // Exist Extend FV header. + // + if (CurrentFv->FvHeader->ExtHeaderOffset !=3D 0){ + CurrentFv->FvExtHeader =3D (EFI_FIRMWARE_VOLUME_EXT_HEADER *) malloc= (sizeof (EFI_FIRMWARE_VOLUME_EXT_HEADER)); + + if (CurrentFv->FvExtHeader =3D=3D 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->FvHe= ader->ExtHeaderOffset), sizeof (EFI_FIRMWARE_VOLUME_EXT_HEADER)); + if (mFvGuidIsSet) { + if (CompareGuid (&CurrentFv->FvExtHeader->FvName, &mFvNameGuid) = =3D=3D 0) { + CurrentFv->IsInputFvFlag =3D TRUE; + } + } + + } + + } + + // + // Put encapsulate information into structure. + // + if (CurrentFv->EncapData =3D=3D NULL && !IsChildFv) { + // + // First time in, the root FV + // + CurrentFv->EncapData =3D (ENCAP_INFO_DATA *) malloc (sizeof (ENCAP_INF= O_DATA)); + + if (CurrentFv->EncapData =3D=3D NULL) { + return EFI_ABORTED; + } + CurrentFv->EncapData->FvExtHeader =3D NULL; + CurrentFv->EncapData->Level =3D Level; + CurrentFv->EncapData->Type =3D BFM_ENCAP_TREE_FV; + CurrentFv->EncapData->Data =3D (EFI_FIRMWARE_VOLUME_HEADER *) malloc = (sizeof (EFI_FIRMWARE_VOLUME_HEADER)); + + if (CurrentFv->EncapData->Data =3D=3D NULL) { + return EFI_ABORTED; + } + + memcpy (CurrentFv->EncapData->Data, Fv, sizeof (EFI_FIRMWARE_VOLUME_HE= ADER)); + + if (((EFI_FIRMWARE_VOLUME_HEADER *)(CurrentFv->EncapData->Data))->ExtH= eaderOffset !=3D 0) { + ExtHdrPtr =3D (VOID *)((UINTN)Fv + ((EFI_FIRMWARE_VOLUME_HEADER *)(C= urrentFv->EncapData->Data))->ExtHeaderOffset); + CurrentFv->EncapData->FvExtHeader =3D (EFI_FIRMWARE_VOLUME_EXT_HEADE= R *) malloc (ExtHdrPtr->ExtHeaderSize); + + if (CurrentFv->EncapData->FvExtHeader =3D=3D 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, &mFvN= ameGuid) =3D=3D 0) { + CurrentFv->IsInputFvFlag =3D TRUE; + } + } + + } + + CurrentFv->EncapData->NextNode =3D NULL; + + } else if (CurrentFv->EncapData =3D=3D NULL) { + return EFI_ABORTED; + } else if (IsChildFv) { + + LocalEncapData =3D CurrentFv->EncapData; + + while (LocalEncapData->NextNode !=3D NULL) { + LocalEncapData =3D LocalEncapData->NextNode; + } + + // + // Construct the new ENCAP_DATA + // + LocalEncapData->NextNode =3D (ENCAP_INFO_DATA *) malloc (sizeof (ENC= AP_INFO_DATA)); + + if (LocalEncapData->NextNode =3D=3D NULL) { + return EFI_ABORTED; + } + + LocalEncapData =3D LocalEncapData->NextNode; + + LocalEncapData->Level =3D Level; + LocalEncapData->Type =3D BFM_ENCAP_TREE_FV; + LocalEncapData->Data =3D (EFI_FIRMWARE_VOLUME_HEADER *) malloc (siz= eof (EFI_FIRMWARE_VOLUME_HEADER)); + LocalEncapData->FvExtHeader =3D NULL; + + if (LocalEncapData->Data =3D=3D NULL) { + return EFI_ABORTED; + } + + memcpy (LocalEncapData->Data, Fv, sizeof (EFI_FIRMWARE_VOLUME_HEADER= )); + + if (((EFI_FIRMWARE_VOLUME_HEADER *)(LocalEncapData->Data))->ExtHeade= rOffset !=3D 0) { + ExtHdrPtr =3D (VOID *)((UINTN)Fv + ((EFI_FIRMWARE_VOLUME_HEADER *)= (LocalEncapData->Data))->ExtHeaderOffset); + LocalEncapData->FvExtHeader =3D (EFI_FIRMWARE_VOLUME_EXT_HEADER *)= malloc(ExtHdrPtr->ExtHeaderSize); + + if (LocalEncapData->FvExtHeader =3D=3D 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_FIR= MWARE_VOLUME_HEADER *)(LocalEncapData->Data))->ExtHeaderOffset), ExtHdrPtr-= >ExtHeaderSize); + } + + LocalEncapData->NextNode =3D NULL; + + } + + + // + // Get the first file + // + Status =3D FvBufFindNextFile (Fv, &Key, (VOID **) &CurrentFile); + if (Status =3D=3D EFI_NOT_FOUND) { + CurrentFile =3D NULL; + } else if (EFI_ERROR (Status)) { + printf ("Failed to find the first file from Fv. \n"); + return Status; + } + + while (CurrentFile !=3D NULL) { + + // + // Increment the number of files counter + // + NumberOfFiles++; + + // + // Store FFS file Header information + // + CurrentFv->FfsHeader[*FfsCount].Attributes =3D CurrentFile->Attr= ibutes; + CurrentFv->FfsHeader[*FfsCount].IntegrityCheck =3D CurrentFile->Inte= grityCheck; + CurrentFv->FfsHeader[*FfsCount].Name =3D CurrentFile->Name; + CurrentFv->FfsHeader[*FfsCount].Size[0] =3D CurrentFile->Size= [0]; + CurrentFv->FfsHeader[*FfsCount].Size[1] =3D CurrentFile->Size= [1]; + CurrentFv->FfsHeader[*FfsCount].Size[2] =3D CurrentFile->Size= [2]; + CurrentFv->FfsHeader[*FfsCount].State =3D CurrentFile->Stat= e; + CurrentFv->FfsHeader[*FfsCount].Type =3D CurrentFile->Type; + CurrentFv->FfsHeader[*FfsCount].ExtendedSize =3D CurrentFile->Exte= ndedSize; + + // + // Display info about this file + // + Status =3D LibGetFileInfo (Fv, CurrentFile, ErasePolarity, CurrentFv, = FvName, Level, FfsCount, ViewFlag); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Get the next file + // + Status =3D FvBufFindNextFile (Fv, &Key, (VOID **) &CurrentFile); + if (Status =3D=3D EFI_NOT_FOUND) { + CurrentFile =3D 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 =3D NULL; + + TempDir =3D getcwd(NULL, _MAX_PATH); + + if (strlen (TempDir) + strlen (OS_SEP_STR) + strlen (TEMP_DIR_NAME) > _M= AX_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] =3D 0; + strncat (OutputExtFile, Line, _MAX_PATH - strlen (OutputExtFile) - 1); + + + ExtFile =3D fopen(OutputExtFile, "wb+"); + if (ExtFile =3D=3D NULL) { + return EFI_ABORTED; + } + + if (fwrite(ExtPtr, 1, ExtPtr->ExtHeaderSize, ExtFile) !=3D ExtPtr->ExtHe= aderSize) { + fclose(ExtFile); + return EFI_ABORTED; + } + + fclose(ExtFile); + + strcpy (Line, "EFI_FV_EXT_HEADER_FILE_NAME =3D "); + 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 (Li= ne) - 1); + strncat (Line, "\n", sizeof(Line) / sizeof (CHAR8) - strlen (Line) - 1); + Len =3D strlen(Line); + if (fwrite(Line, 1, Len, InfFile) !=3D 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 =3D ActualSize; + while ((OccupiedSize & (Alignment - 1)) !=3D 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 !=3D '\0') { + *(UniString++) =3D (CHAR16) *(String++); + } + // + // End the UniString with a NULL. + // + *UniString =3D '\0'; +} + + +EFI_STATUS +LibCreateGuidedSectionOriginalData( + IN CHAR8* FileIn, + IN CHAR8* ToolName, + IN CHAR8* FileOut +) +{ + CHAR8* SystemCommand; + + SystemCommand =3D NULL; + + if (FileIn =3D=3D NULL || + ToolName =3D=3D NULL || + FileOut =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + SystemCommand =3D malloc ( + strlen (ENCODE_STR) + + strlen (FileIn) + + strlen (ToolName) + + strlen (FileOut) + + 1 + ); + + if (NULL =3D=3D SystemCommand) { + return EFI_ABORTED; + } + + sprintf ( + SystemCommand, + ENCODE_STR, + ToolName, + FileIn, + FileOut + ); + + if (system (SystemCommand) !=3D EFI_SUCCESS) { + SystemCommand =3D malloc ( + strlen (ENCODE_STR_ERR) + + strlen (FileIn) + + strlen (ToolName) + + strlen (FileOut) + + 1 + ); + if (NULL =3D=3D 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 conver= ted 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 informat= ion. + + @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 =3D NULL; + + LocalStr =3D (CHAR8 *) malloc (1024 * 4); + + if (LocalStr =3D=3D NULL) { + printf ("Out of resource, memory allocation failed. \n"); + return EFI_OUT_OF_RESOURCES; + } + + memset (LocalStr, '\0', 1024 * 4); + + if (Attr =3D=3D 0 || InfFile =3D=3D 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 =3D TRUE \n", sizeof ("EFI_R= EAD_DISABLED_CAP =3D TRUE \n")); + } + + if (Attr & EFI_FVB2_READ_ENABLED_CAP) { + strncat (LocalStr, "EFI_READ_ENABLED_CAP =3D TRUE \n", sizeof ("EFI_RE= AD_ENABLED_CAP =3D TRUE \n")); + } + + if (Attr & EFI_FVB2_READ_STATUS) { + strncat (LocalStr, "EFI_READ_STATUS =3D TRUE \n", sizeof ("EFI_READ_ST= ATUS =3D TRUE \n")); + } + + if (Attr & EFI_FVB2_WRITE_DISABLED_CAP) { + strncat (LocalStr, "EFI_WRITE_DISABLED_CAP =3D TRUE \n", sizeof ("EFI_= WRITE_DISABLED_CAP =3D TRUE \n")); + } + + if (Attr & EFI_FVB2_WRITE_ENABLED_CAP) { + strncat (LocalStr, "EFI_WRITE_ENABLED_CAP =3D TRUE \n", sizeof ("EFI_W= RITE_ENABLED_CAP =3D TRUE \n")); + } + + if (Attr & EFI_FVB2_WRITE_STATUS) { + strncat (LocalStr, "EFI_WRITE_STATUS =3D TRUE \n", sizeof ("EFI_WRITE_= STATUS =3D TRUE \n")); + } + + if (Attr & EFI_FVB2_LOCK_CAP) { + strncat (LocalStr, "EFI_LOCK_CAP =3D TRUE \n", sizeof ("EFI_LOCK_CAP = =3D TRUE \n")); + } + + if (Attr & EFI_FVB2_LOCK_STATUS) { + strncat (LocalStr, "EFI_LOCK_STATUS =3D TRUE \n", sizeof ("EFI_LOCK_ST= ATUS =3D TRUE \n")); + } + + if (Attr & EFI_FVB2_STICKY_WRITE) { + strncat (LocalStr, "EFI_STICKY_WRITE =3D TRUE \n", sizeof ("EFI_STICKY= _WRITE =3D TRUE \n")); + } + + if (Attr & EFI_FVB2_MEMORY_MAPPED) { + strncat (LocalStr, "EFI_MEMORY_MAPPED =3D TRUE \n", sizeof ("EFI_MEMOR= Y_MAPPED =3D TRUE \n")); + } + + if (Attr & EFI_FVB2_ERASE_POLARITY) { + strncat (LocalStr, "EFI_ERASE_POLARITY =3D 1 \n", sizeof ("EFI_ERASE_P= OLARITY =3D 1 \n")); + } + + if (Attr & EFI_FVB2_READ_LOCK_CAP) { + strncat (LocalStr, "EFI_READ_LOCK_CAP =3D TRUE \n", sizeof ("EFI_READ_= LOCK_CAP =3D TRUE \n")); + } + + if (Attr & EFI_FVB2_READ_LOCK_STATUS) { + strncat (LocalStr, "EFI_READ_LOCK_STATUS =3D TRUE \n", sizeof ("EFI_RE= AD_LOCK_STATUS =3D TRUE \n")); + } + + if (Attr & EFI_FVB2_WRITE_LOCK_CAP) { + strncat (LocalStr, "EFI_WRITE_LOCK_CAP =3D TRUE \n", sizeof ("EFI_WRIT= E_LOCK_CAP =3D TRUE \n")); + } + + if (Attr & EFI_FVB2_WRITE_LOCK_STATUS) { + strncat (LocalStr, "EFI_WRITE_LOCK_STATUS =3D TRUE \n", sizeof ("EFI_W= RITE_LOCK_STATUS =3D TRUE \n")); + } + + if (Attr & EFI_FVB2_LOCK_STATUS) { + strncat (LocalStr, "EFI_READ_LOCK_STATUS =3D TRUE \n", sizeof ("EFI_RE= AD_LOCK_STATUS =3D TRUE \n")); + } + + // + // Alignment + // + if (Attr & EFI_FVB2_ALIGNMENT_1) { + strncat (LocalStr, "EFI_FVB2_ALIGNMENT_1 =3D TRUE \n", sizeof ("EFI_FV= B2_ALIGNMENT_1 =3D TRUE \n")); + } else if (Attr & EFI_FVB2_ALIGNMENT_2) { + strncat (LocalStr, "EFI_FVB2_ALIGNMENT_2 =3D TRUE \n", sizeof ("EFI_FV= B2_ALIGNMENT_2 =3D TRUE \n")); + } else if (Attr & EFI_FVB2_ALIGNMENT_4) { + strncat (LocalStr, "EFI_FVB2_ALIGNMENT_4 =3D TRUE \n", sizeof ("EFI_FV= B2_ALIGNMENT_4 =3D TRUE \n")); + } else if (Attr & EFI_FVB2_ALIGNMENT_8) { + strncat (LocalStr, "EFI_FVB2_ALIGNMENT_8 =3D TRUE \n", sizeof ("EFI_FV= B2_ALIGNMENT_8 =3D TRUE \n")); + } else if (Attr & EFI_FVB2_ALIGNMENT_16) { + strncat (LocalStr, "EFI_FVB2_ALIGNMENT_16 =3D TRUE \n", sizeof ("EFI_F= VB2_ALIGNMENT_16 =3D TRUE \n")); + } else if (Attr & EFI_FVB2_ALIGNMENT_32) { + strncat (LocalStr, "EFI_FVB2_ALIGNMENT_32 =3D TRUE \n", sizeof ("EFI_F= VB2_ALIGNMENT_32 =3D TRUE \n")); + } else if (Attr & EFI_FVB2_ALIGNMENT_64) { + strncat (LocalStr, "EFI_FVB2_ALIGNMENT_64 =3D TRUE \n", sizeof ("EFI_F= VB2_ALIGNMENT_64 =3D TRUE \n")); + } else if (Attr & EFI_FVB2_ALIGNMENT_128) { + strncat (LocalStr, "EFI_FVB2_ALIGNMENT_128 =3D TRUE \n", sizeof ("EFI_= FVB2_ALIGNMENT_128 =3D TRUE \n")); + } else if (Attr & EFI_FVB2_ALIGNMENT_256) { + strncat (LocalStr, "EFI_FVB2_ALIGNMENT_256 =3D TRUE \n", sizeof ("EFI_= FVB2_ALIGNMENT_256 =3D TRUE \n")); + } else if (Attr & EFI_FVB2_ALIGNMENT_512) { + strncat (LocalStr, "EFI_FVB2_ALIGNMENT_512 =3D TRUE \n", sizeof ("EFI_= FVB2_ALIGNMENT_512 =3D TRUE \n")); + } else if (Attr & EFI_FVB2_ALIGNMENT_1K) { + strncat (LocalStr, "EFI_FVB2_ALIGNMENT_1K =3D TRUE \n", sizeof ("EFI_F= VB2_ALIGNMENT_1K =3D TRUE \n")); + } else if (Attr & EFI_FVB2_ALIGNMENT_2K) { + strncat (LocalStr, "EFI_FVB2_ALIGNMENT_2K =3D TRUE \n", sizeof ("EFI_F= VB2_ALIGNMENT_2K =3D TRUE \n")); + } else if (Attr & EFI_FVB2_ALIGNMENT_4K) { + strncat (LocalStr, "EFI_FVB2_ALIGNMENT_4K =3D TRUE \n", sizeof ("EFI_F= VB2_ALIGNMENT_4K =3D TRUE \n")); + } else if (Attr & EFI_FVB2_ALIGNMENT_8K) { + strncat (LocalStr, "EFI_FVB2_ALIGNMENT_8K =3D TRUE \n", sizeof ("EFI_F= VB2_ALIGNMENT_8K =3D TRUE \n")); + } else if (Attr & EFI_FVB2_ALIGNMENT_16K) { + strncat (LocalStr, "EFI_FVB2_ALIGNMENT_16K =3D TRUE \n", sizeof ("EFI_= FVB2_ALIGNMENT_16K =3D TRUE \n")); + } else if (Attr & EFI_FVB2_ALIGNMENT_32K) { + strncat (LocalStr, "EFI_FVB2_ALIGNMENT_32K =3D TRUE \n", sizeof ("EFI_= FVB2_ALIGNMENT_32K =3D TRUE \n")); + } else if (Attr & EFI_FVB2_ALIGNMENT_64K) { + strncat (LocalStr, "EFI_FVB2_ALIGNMENT_64K =3D TRUE \n", sizeof ("EFI_= FVB2_ALIGNMENT_64K =3D TRUE \n")); + } else if (Attr & EFI_FVB2_ALIGNMENT_128K) { + strncat (LocalStr, "EFI_FVB2_ALIGNMENT_128K =3D TRUE \n", sizeof ("EFI= _FVB2_ALIGNMENT_128K =3D TRUE \n")); + } else if (Attr & EFI_FVB2_ALIGNMENT_256K) { + strncat (LocalStr, "EFI_FVB2_ALIGNMENT_256K =3D TRUE \n", sizeof ("EFI= _FVB2_ALIGNMENT_256K =3D TRUE \n")); + } else if (Attr & EFI_FVB2_ALIGNMENT_512K) { + strncat (LocalStr, "EFI_FVB2_ALIGNMENT_512K =3D TRUE \n", sizeof ("EFI= _FVB2_ALIGNMENT_512K =3D TRUE \n")); + } else if (Attr & EFI_FVB2_ALIGNMENT_1M) { + strncat (LocalStr, "EFI_FVB2_ALIGNMENT_1M =3D TRUE \n", sizeof ("EFI_F= VB2_ALIGNMENT_1M =3D TRUE \n")); + } else if (Attr & EFI_FVB2_ALIGNMENT_2M) { + strncat (LocalStr, "EFI_FVB2_ALIGNMENT_2M =3D TRUE \n", sizeof ("EFI_F= VB2_ALIGNMENT_2M =3D TRUE \n")); + } else if (Attr & EFI_FVB2_ALIGNMENT_4M) { + strncat (LocalStr, "EFI_FVB2_ALIGNMENT_4M =3D TRUE \n", sizeof ("EFI_F= VB2_ALIGNMENT_4M =3D TRUE \n")); + } else if (Attr & EFI_FVB2_ALIGNMENT_8M) { + strncat (LocalStr, "EFI_FVB2_ALIGNMENT_8M =3D TRUE \n", sizeof ("EFI_F= VB2_ALIGNMENT_8M =3D TRUE \n")); + } else if (Attr & EFI_FVB2_ALIGNMENT_16M) { + strncat (LocalStr, "EFI_FVB2_ALIGNMENT_16M =3D TRUE \n", sizeof ("EFI_= FVB2_ALIGNMENT_16M =3D TRUE \n")); + } else if (Attr & EFI_FVB2_ALIGNMENT_32M) { + strncat (LocalStr, "EFI_FVB2_ALIGNMENT_32M =3D TRUE \n", sizeof ("EFI_= FVB2_ALIGNMENT_32M =3D TRUE \n")); + } else if (Attr & EFI_FVB2_ALIGNMENT_64M) { + strncat (LocalStr, "EFI_FVB2_ALIGNMENT_64M =3D TRUE \n", sizeof ("EFI_= FVB2_ALIGNMENT_64M =3D TRUE \n")); + } else if (Attr & EFI_FVB2_ALIGNMENT_128M) { + strncat (LocalStr, "EFI_FVB2_ALIGNMENT_128M =3D TRUE \n", sizeof ("EFI= _FVB2_ALIGNMENT_128M =3D TRUE \n")); + } else if (Attr & EFI_FVB2_ALIGNMENT_256M) { + strncat (LocalStr, "EFI_FVB2_ALIGNMENT_256M =3D TRUE \n", sizeof ("EFI= _FVB2_ALIGNMENT_256M =3D TRUE \n")); + } else if (Attr & EFI_FVB2_ALIGNMENT_512M) { + strncat (LocalStr, "EFI_FVB2_ALIGNMENT_512M =3D TRUE \n", sizeof ("EFI= _FVB2_ALIGNMENT_512M =3D TRUE \n")); + } else if (Attr & EFI_FVB2_ALIGNMENT_1G) { + strncat (LocalStr, "EFI_FVB2_ALIGNMENT_1G =3D TRUE \n", sizeof ("EFI_F= VB2_ALIGNMENT_1G =3D TRUE \n")); + } else if (Attr & EFI_FVB2_ALIGNMENT_2G) { + strncat (LocalStr, "EFI_FVB2_ALIGNMENT_2G =3D TRUE \n", sizeof ("EFI_F= VB2_ALIGNMENT_2G =3D TRUE \n")); + } + + if (fwrite (LocalStr, 1, (size_t) strlen (LocalStr), InfFile) !=3D (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 informat= ion. + + @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 =3D NULL; + BlockSize =3D NULL; + NumOfBlocks =3D NULL; + + if (BlockMap =3D=3D NULL || InfFile =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // This section will not over 1024 bytes and each line will never over 1= 28 bytes. + // + LocalStr =3D (CHAR8 *) malloc (1024); + BlockSize =3D (CHAR8 *) malloc (128); + NumOfBlocks =3D (CHAR8 *) malloc (128); + + if (LocalStr =3D=3D NULL || + BlockSize =3D=3D NULL || + NumOfBlocks =3D=3D NULL) { + if (LocalStr !=3D NULL) { + free (LocalStr); + } + if (BlockSize !=3D NULL) { + free (BlockSize); + } + if (NumOfBlocks !=3D 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 =3D 0x%x \n", BlockMap->Length); + strncat (LocalStr, BlockSize, strlen(BlockSize)); + + if (IsRootFv) { + sprintf (NumOfBlocks, "EFI_NUM_BLOCKS =3D 0x%x \n", BlockMap->NumBlocks= ); + strncat (LocalStr, NumOfBlocks, strlen(NumOfBlocks)); + } + + if (fwrite (LocalStr, 1, (size_t) strlen (LocalStr), InfFile) !=3D (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 informat= ion + @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 =3D NULL; + + if (FfsName =3D=3D NULL || InfFile =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + if (strlen(FfsName) =3D=3D 0) { + return EFI_SUCCESS; + } + + LocalStr =3D (CHAR8 *) malloc (_MAX_PATH); + + if (LocalStr =3D=3D 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 =3D %s \n", FfsName); + } else { + sprintf (LocalStr, "EFI_FILE_NAME =3D %s \n", FfsName); + } + + if (fwrite (LocalStr, 1, (size_t) strlen (LocalStr), InfFile) !=3D (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 =3D NULL; + + // + // Call GenSec tool to generate FFS section. + // + + // + // -s SectionType. + // + if (Type !=3D 0) { + switch (Type) { + // + // Process compression section + // + case EFI_SECTION_COMPRESSION: + SystemCommand =3D malloc ( + strlen (GENSEC_COMPRESSION) + + strlen (mSectionTypeName[Type]) + + strlen (CompressType) + + strlen (InputFilePath) + + strlen (OutputFilePath) + + 1 + ); + if (NULL =3D=3D SystemCommand) { + return EFI_OUT_OF_RESOURCES; + } + sprintf ( + SystemCommand, + GENSEC_COMPRESSION, + mSectionTypeName[Type], + CompressType, + InputFilePath, + OutputFilePath + ); + if (system (SystemCommand) !=3D EFI_SUCCESS) { + free(SystemCommand); + return EFI_ABORTED; + } + free(SystemCommand); + break; + + // + // Process GUID defined section + // + case EFI_SECTION_GUID_DEFINED: + SystemCommand =3D malloc ( + strlen (GENSEC_GUID) + + strlen (mSectionTypeName[Type]) + + strlen (GuidToolGuid) + + strlen (InputFilePath) + + strlen (OutputFilePath) + + 1 + ); + if (NULL =3D=3D SystemCommand) { + return EFI_OUT_OF_RESOURCES; + } + sprintf ( + SystemCommand, + GENSEC_GUID, + mSectionTypeName[Type], + GuidToolGuid, + InputFilePath, + OutputFilePath + ); + if (system (SystemCommand) !=3D EFI_SUCCESS) { + free(SystemCommand); + return EFI_ABORTED; + } + free(SystemCommand); + break; + + case EFI_SECTION_FIRMWARE_VOLUME_IMAGE: + SystemCommand =3D malloc ( + strlen (GENSEC_STR) + + strlen (mSectionTypeName[Type]) + + strlen (InputFilePath) + + strlen (OutputFilePath) + + 1 + ); + if (NULL =3D=3D SystemCommand) { + return EFI_OUT_OF_RESOURCES; + } + sprintf ( + SystemCommand, + GENSEC_STR, + mSectionTypeName[Type], + InputFilePath, + OutputFilePath + ); + if (system (SystemCommand) !=3D EFI_SUCCESS) { + free(SystemCommand); + return EFI_ABORTED; + } + free(SystemCommand); + break; + + case EFI_SECTION_RAW: + SystemCommand =3D malloc ( + strlen (GENSEC_STR) + + strlen (mSectionTypeName[Type]) + + strlen (InputFilePath) + + strlen (OutputFilePath) + + 1 + ); + if (NULL =3D=3D SystemCommand) { + return EFI_OUT_OF_RESOURCES; + } + sprintf ( + SystemCommand, + GENSEC_STR, + mSectionTypeName[Type], + InputFilePath, + OutputFilePath + ); + if (system (SystemCommand) !=3D 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 =3D malloc ( + strlen (GENSEC_ALIGN) + + strlen (InputFilePath) + + strlen (OutputFilePath) + + 1 + ); + if (NULL =3D=3D SystemCommand) { + return EFI_OUT_OF_RESOURCES; + } + sprintf ( + SystemCommand, + GENSEC_ALIGN, + InputFilePath, + OutputFilePath + ); + if (system (SystemCommand) !=3D 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 fil= e. This option is required. + @param[in] OutputFilePath The created PI firmware file name. This opt= ion is required. + @param[in] BlockSize BlockSize is one HEX or DEC format value re= quired 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 =3D "8c8ce578-8a3d-4f1c-9935-896185c32dd3= "; + + SystemCommand =3D NULL; + + if (OutputFilePath =3D=3D NULL || + InfFilePath =3D=3D NULL ) { + return EFI_INVALID_PARAMETER; + } + + if (InfFilePath !=3D NULL) { + if (FvGuidName =3D=3D NULL) { + SystemCommand =3D malloc ( + strlen (GENFV_STR) + + strlen (InfFilePath) + + strlen (OutputFilePath) + + 1 + ); + if (NULL =3D=3D SystemCommand) { + return EFI_OUT_OF_RESOURCES; + } + + sprintf ( + SystemCommand, + GENFV_STR, + InfFilePath, // -i + OutputFilePath // -o + ); + + if (system (SystemCommand) !=3D EFI_SUCCESS) { + free(SystemCommand); + return EFI_ABORTED; + } + free(SystemCommand); + } else { + // + // Have FvGuidName in it. + // + SystemCommand =3D malloc ( + strlen (GENFV_FVGUID) + + strlen (InfFilePath) + + strlen (OutputFilePath) + + strlen (FvGuidName) + + 1 + ); + if (NULL =3D=3D SystemCommand) { + return EFI_OUT_OF_RESOURCES; + } + + sprintf ( + SystemCommand, + GENFV_FVGUID, + InfFilePath, // -i + OutputFilePath, // -o + FvGuidName // FvNameGuid + ); + if (system (SystemCommand) !=3D EFI_SUCCESS) { + free(SystemCommand); + return EFI_ABORTED; + } + free(SystemCommand); + + } + } + + if (InputFFSs !=3D NULL) { + SystemCommand =3D malloc ( + strlen (GENFV_FFS) + + strlen (InputFFSs) + + strlen (FfsGuid) + + strlen (OutputFilePath) + + 100 + ); + if (NULL =3D=3D SystemCommand) { + return EFI_OUT_OF_RESOURCES; + } + + sprintf ( + SystemCommand, + GENFV_FFS, + InputFFSs, // -f + FfsGuid, // -g + OutputFilePath // -o + ); + if (system (SystemCommand) !=3D 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 =3D NULL; + + if (Guid =3D=3D NULL) { + printf ("The guid is NULL while convert guid to string! \n"); + return NULL; + } + + Buffer =3D (CHAR8 *) malloc (36 + 1); + + if (Buffer =3D=3D 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_FILET= YPE_PEIM, EFI_FV_FILETYPE_PEI_CORE, EFI_FV_FILETYPE_DXE_CORE, + EFI_FV_FILETYPE_DRIVER, EFI_FV_FILETYPE_APP= LICATION, 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 fil= e. This option is required. + @param[in] OutputFilePath The created PI firmware file name. This opt= ion 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 i= ndicate that the file may not be moved from its present location. + @param[in] SectionAlign FileAlign specifies FFS file alignment, whi= ch 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 =3D NULL; + GuidStr =3D NULL; + + GuidStr =3D LibBfmGuidToStr(&FileGuid); + + if (NULL =3D=3D GuidStr) { + return EFI_OUT_OF_RESOURCES; + } + + if (Type =3D=3D EFI_FV_FILETYPE_RAW) { + SystemCommand =3D malloc ( + strlen (GENFFS_STR) + + strlen (mFfsFileType[Type]) + + strlen (InputFilePath) + + strlen (GuidStr) + + strlen (OutputFilePath) + + 1 + ); + if (NULL =3D=3D SystemCommand) { + free (GuidStr); + return EFI_OUT_OF_RESOURCES; + } + sprintf ( + SystemCommand, + GENFFS_STR, + mFfsFileType[Type], // -t + InputFilePath, // -i + GuidStr, // -g + OutputFilePath // -o + ); + + if (system (SystemCommand) !=3D 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 =3D malloc ( + strlen (GENFFS_FIX) + + strlen (mFfsFileType[Type]) + + strlen (InputFilePath) + + strlen (GuidStr) + + strlen (OutputFilePath) + + 1 + ); + if (NULL =3D=3D SystemCommand) { + free (GuidStr); + return EFI_OUT_OF_RESOURCES; + } + sprintf ( + SystemCommand, + GENFFS_FIX, + mFfsFileType[Type], // -t + InputFilePath, // -i + GuidStr, // -g + OutputFilePath // -o + ); + if (system (SystemCommand) !=3D EFI_SUCCESS) { + free(SystemCommand); + free (GuidStr); + return EFI_ABORTED; + } + free(SystemCommand); + } else { + SystemCommand =3D malloc ( + strlen (GENFFS_STR) + + strlen (mFfsFileType[Type]) + + strlen (InputFilePath) + + strlen (GuidStr) + + strlen (OutputFilePath) + + 1 + ); + if (NULL =3D=3D SystemCommand) { + free (GuidStr); + return EFI_OUT_OF_RESOURCES; + } + sprintf ( + SystemCommand, + GENFFS_STR, + mFfsFileType[Type], // -t + InputFilePath, // -i + GuidStr, // -g + OutputFilePath // -o + ); + if (system (SystemCommand) !=3D 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 =3D NULL; + + + if (OldFd =3D=3D NULL || + NewFd =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Create a copy the new file. + // + + SystemCommand =3D malloc ( + strlen (COPY_STR) + + strlen (OldFd) + + strlen (NewFd) + + 1 + ); + if (NULL =3D=3D SystemCommand) { + return EFI_OUT_OF_RESOURCES; + } + + sprintf ( + SystemCommand, + COPY_STR, + OldFd, + NewFd + ); + + if (system (SystemCommand) !=3D EFI_SUCCESS) { + free(SystemCommand); + return EFI_ABORTED; + } + free(SystemCommand); + + return EFI_SUCCESS; +} + + +/** + This function will assemble the filename, directory and extend and retur= n the combined string. + Like FileName =3D file1, Dir =3D c:\temp extend =3D txt, the output stri= ng 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 =3D NULL; + + if (FileName =3D=3D NULL) { + return NULL; + } + + if (Dir =3D=3D NULL || Extend =3D=3D NULL) { + return FileName; + } + + RetStr =3D (CHAR8 *) malloc (strlen (FileName) + + strlen (Dir) + + strlen (Extend) + + strlen ("%s%s.%s") + + 1); + if (NULL =3D=3D 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 =3D NULL; + + + if (DirName =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + if (access (DirName, 0) =3D=3D -1){ + return EFI_SUCCESS; + } + + // + // Delete a directory and files in it + // + SystemCommand =3D malloc ( + strlen (RMDIR_STR) + + strlen (DirName) + + 1 + ); + if (NULL =3D=3D SystemCommand) { + return EFI_OUT_OF_RESOURCES; + } + + sprintf ( + SystemCommand, + RMDIR_STR, + DirName + ); + + if (system (SystemCommand) !=3D 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 =3D NULL; + + + if (FileName =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + + // + // Delete a file. + // + SystemCommand =3D malloc ( + strlen (DEL_STR) + + strlen (FileName) + + 1 + ); + if (NULL =3D=3D SystemCommand) { + return EFI_OUT_OF_RESOURCES; + } + sprintf ( + SystemCommand, + DEL_STR, + FileName + ); + + if (system (SystemCommand) !=3D 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 =3D NULL; + TempFv =3D NULL; + EncapData1 =3D NULL; + EncapData2 =3D NULL; + + if (Fd =3D=3D NULL) { + return; + } + + CurrentFv =3D Fd->Fv; + + do { + TempFv =3D CurrentFv; + CurrentFv =3D CurrentFv->FvNext; + + if (TempFv->FvHeader !=3D NULL) { + free (TempFv->FvHeader); + } + if (TempFv->FvExtHeader !=3D NULL) { + free (TempFv->FvExtHeader); + } + + // + // Free encapsulate data; + // + EncapData1 =3D TempFv->EncapData; + + while (EncapData1 !=3D NULL) { + + EncapData2 =3D EncapData1; + EncapData1 =3D EncapData1->NextNode; + + if (EncapData2->Data !=3D NULL) { + free (EncapData2->Data); + } + if (EncapData2->FvExtHeader !=3D NULL) { + free(EncapData2->FvExtHeader); + } + free (EncapData2); + EncapData2 =3D NULL; + } + + EncapData1 =3D NULL; + + free (TempFv); + TempFv =3D NULL; + + } while (CurrentFv !=3D NULL); + + CurrentFv =3D NULL; + free (Fd); + Fd =3D 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 =3D NULL; + CompressedFile =3D NULL; + UnCompressedBuffer =3D NULL; + CompressedBuffer =3D NULL; + TempName =3D NULL; + TemDir =3D NULL; + TemString =3D NULL; + UnCompressedSize =3D 0; + CompressedSize =3D 0; + + if ( InputFileName =3D=3D NULL || + OutPutFileName =3D=3D NULL) { + printf ("Error while generate compressed section!\n"); + return EFI_INVALID_PARAMETER; + } + + if (CompressionType =3D=3D EFI_STANDARD_COMPRESSION) { + UnCompressFile =3D fopen (InputFileName, "rb"); + if (UnCompressFile =3D=3D NULL) { + printf ("Error while open file %s \n", InputFileName); + return EFI_ABORTED; + } + + TemDir =3D 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 =3D GenTempFile (); + TempName=3D LibFilenameStrExtended (strrchr(TemString, OS_SEP), TemDir= , "comp"); + free (TemString); + TemString =3D NULL; + if (TempName =3D=3D NULL) { + fclose(UnCompressFile); + return EFI_ABORTED; + } + + CompressedFile =3D fopen (TempName, "wb+"); + if (CompressedFile =3D=3D 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 =3D ftell(UnCompressFile); + + fseek(UnCompressFile,0,SEEK_SET); + + UnCompressedBuffer =3D malloc (UnCompressedSize); + + if (UnCompressedBuffer =3D=3D NULL) { + printf ("Out of resource, memory allocation failed. \n"); + fclose (CompressedFile); + fclose(UnCompressFile); + free (TempName); + return EFI_OUT_OF_RESOURCES; + } + + CompressedBuffer =3D malloc (UnCompressedSize); + + if (CompressedBuffer =3D=3D 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, UnCompres= sFile) =3D=3D (size_t) UnCompressedSize) { + CompressedSize =3D UnCompressedSize; + + Status =3D 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, CompressedFi= le) !=3D (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, OutPutFil= eName, NULL, NULL, NULL, "PI_STD"); + free (TempName); + TempName =3D NULL; + + } else if (CompressionType =3D=3D EFI_NOT_COMPRESSED) { + + LibCreateFfsSection(InputFileName, NULL, EFI_SECTION_COMPRESSION, OutP= utFileName, 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] =3D { + "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 =3D NULL; + FirstGuidTool =3D NULL; + LastGuidTool =3D NULL; + NewGuidTool =3D NULL; + Index =3D 0; + + for (Index =3D 0; Index < BUILD_IN_TOOL_COUNT; Index++) { + Tool =3D SplitStringByWhitespace (PreDefinedGuidedTool[Index]); + if ((Tool !=3D NULL) && + (Tool->Count =3D=3D 3) + ) { + Status =3D StringToGuid (Tool->Strings[0], &Guid); + if (!EFI_ERROR (Status)) { + NewGuidTool =3D malloc (sizeof (GUID_SEC_TOOL_ENTRY)); + if (NewGuidTool !=3D NULL) { + memcpy (&(NewGuidTool->Guid), &Guid, sizeof (Guid)); + NewGuidTool->Name =3D CloneString(Tool->Strings[1]); + NewGuidTool->Path =3D CloneString(Tool->Strings[2]); + NewGuidTool->Next =3D NULL; + } else { + printf ( "Fail to allocate memory. \n"); + if (Tool !=3D NULL) { + FreeStringList (Tool); + } + return NULL; + } + if (FirstGuidTool =3D=3D NULL) { + FirstGuidTool =3D NewGuidTool; + } else { + LastGuidTool->Next =3D NewGuidTool; + } + LastGuidTool =3D NewGuidTool; + } + } else { + fprintf (stdout, "Error"); + } + if (Tool !=3D NULL) { + FreeStringList (Tool); + Tool =3D 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 =3D 0; + FvIndex2 =3D 0; + FvFoundFlag =3D FALSE; + + if (FdData =3D=3D NULL || FvId =3D=3D NULL) { + printf ( "Error while find FV in FD. \n"); + return EFI_INVALID_PARAMETER; + } + + *FvInFd =3D FdData->Fv; + + FvIndex1 =3D (UINT8) atoi (FvId + 2); + + while (FvInFd !=3D NULL) { + if (((*FvInFd)->FvName) !=3D NULL) { + FvIndex2 =3D (UINT8) atoi ((*FvInFd)->FvName + 2); + + if ((FvIndex2 <=3D FvIndex1) && (((*FvInFd)->FvLevel + FvIndex2) -1 = >=3D FvIndex1)) { + FvFoundFlag =3D TRUE; + break; + } + if ((*FvInFd)->FvNext =3D=3D 0) { + break; + } + *FvInFd =3D (*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 =3D 0; + Buffer =3D NULL; + NewFvFile =3D NULL; + + if (OutputFileName =3D=3D NULL || PatchData =3D=3D NULL) { + return EFI_ABORTED; + } + + NewFvFile =3D fopen (OutputFileName, "rb+"); + if (NewFvFile =3D=3D NULL) { + return EFI_ABORTED; + } + + fseek(NewFvFile, 0, SEEK_SET); + fseek(NewFvFile, 0, SEEK_END); + + NewFvLength =3D 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 =3D (UINT8 *) malloc (PatchData->Length); + + if (Buffer =3D=3D NULL) { + fclose (NewFvFile); + return EFI_ABORTED; + } + + if (fread (Buffer, 1, (size_t) PatchData->Length, NewFvFile) !=3D (siz= e_t) PatchData->Length) { + fclose (NewFvFile); + free(Buffer); + return EFI_ABORTED; + } + + // + // The area used to patch data should be filled by 0xff. + // + for (Count =3D 0; Count< PatchData->Length; Count++) { + if (Buffer[Count] !=3D 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)= !=3D (size_t) PatchData->Length) { + fclose (NewFvFile); + return EFI_ABORTED; + } + + PatchData =3D PatchData->NextNode; + } while (PatchData !=3D 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 =3D 0; + ParentType =3D 0; + ParentLevel =3D 0; + Type =3D 0; + Level =3D 0; + FfsFoundFlag =3D FALSE; + ExtractionTool =3D NULL; + InputFileName =3D NULL; + OutputFileName =3D NULL; + IsLastLevelFfs =3D TRUE; + IsLeafFlagIgnore =3D FALSE; + FirstInFlag =3D TRUE; + FvGuidName =3D NULL; + + // + // Encapsulate from the lowest FFS file level. + // + LocalEncapData =3D FvInFd->EncapData; + Level =3D LocalEncapData->Level; + Type =3D LocalEncapData->Type; + + // + // Get FV Name GUID + // + + while (LocalEncapData !=3D NULL) { + // + // Has changed. + // + if (LocalEncapData->Level > Level) { + if (LocalEncapData->Type =3D=3D BFM_ENCAP_TREE_FFS) { + ParentLevel =3D Level; + ParentType =3D Type; + } + + Level =3D LocalEncapData->Level; + Type =3D LocalEncapData->Type; + } + + if (LocalEncapData->NextNode !=3D NULL) { + LocalEncapData =3D LocalEncapData->NextNode; + } else { + break; + } + } + + do { + switch (ParentType) { + case BFM_ENCAP_TREE_FV: + + // + // Generate FV.inf attributes. + // + InfFileName =3D LibFilenameStrExtended (strrchr(GenTempFile (), OS= _SEP), TemDir, "inf"); + + InfFile =3D fopen (InfFileName, "wt+"); + + if (InfFile =3D=3D NULL) { + printf ("Could not open inf file %s to store FV information. \n"= , InfFileName); + return EFI_ABORTED; + } + + LocalEncapData =3D FvInFd->EncapData; + while (LocalEncapData->NextNode !=3D NULL) { + if (LocalEncapData->Level =3D=3D ParentLevel) { + break; + } + LocalEncapData =3D LocalEncapData->NextNode; + } + + if (((EFI_FIRMWARE_VOLUME_HEADER *)(LocalEncapData->Data))->ExtHea= derOffset !=3D 0) { + // + // FV GUID Name memory allocation + // + FvGuidName =3D (CHAR8 *) malloc (255); + + if (FvGuidName =3D=3D 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 =3D NULL; + } + + + if (ParentLevel =3D=3D 1) { + Status =3D LibFvHeaderOptionToStr(((EFI_FIRMWARE_VOLUME_HEADER *= )LocalEncapData->Data)->BlockMap, InfFile, TRUE); + } else { + Status =3D 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 !=3D NULL) { + free (FvGuidName); + } + return Status; + } + + Status =3D LibFvHeaderAttributeToStr(((EFI_FIRMWARE_VOLUME_HEADER = *)LocalEncapData->Data)->Attributes, InfFile); + + if (EFI_ERROR (Status)) { + printf ("Generate FV header attribute failed.\n"); + if (FvGuidName !=3D NULL) { + free (FvGuidName); + } + fclose (InfFile); + return Status; + } + if (LocalEncapData->FvExtHeader !=3D NULL) { + Status =3D LibGenExtFile(LocalEncapData->FvExtHeader, InfFile); + if (FvGuidName !=3D NULL) { + free (FvGuidName); + } + if (EFI_ERROR(Status)) { + printf("Generate FV EXT header failed.\n"); + fclose (InfFile); + return Status; + } + FvGuidName =3D NULL; + } + + // + // Found FFSs from Fv structure. + // + FfsFoundFlag =3D FALSE; + for (Index =3D 0; Index <=3D FvInFd->FfsNumbers; Index++) { + + // + // For the last level FFS, the level below FFSs we should not ca= re the IsLeaf Flag. + // + if (IsLastLevelFfs) { + IsLeafFlagIgnore =3D TRUE; + } else { + IsLeafFlagIgnore =3D FvInFd->FfsAttuibutes[Index].IsLeaf; + } + + if (FvInFd->FfsAttuibutes[Index].Level >=3D ParentLevel + 1 && I= sLeafFlagIgnore) { + if (FirstInFlag) { + Status =3D 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 =3D 0; + FirstInFlag =3D FALSE; + } else { + Status =3D LibAddFfsFileToFvInf (FvInFd->FfsAttuibutes[Ind= ex].FfsName, InfFile, FALSE); + + if (EFI_ERROR (Status)) { + printf ("Error while generate FV inf file [files] sectio= n. \n"); + fclose (InfFile); + return Status; + } + + FvInFd->FfsAttuibutes[Index].Level =3D 0; + } + FfsFoundFlag =3D TRUE; + } + // + // Also add the sub FV + // + if (FvInFd->FfsAttuibutes[Index].Level - 1 =3D=3D ParentLevel+= 1) { + LocalEncapData =3D FvInFd->EncapData; + while (LocalEncapData->NextNode !=3D NULL) { + if (LocalEncapData->Level =3D=3D ParentLevel + 2) { + break; + } + LocalEncapData =3D LocalEncapData->NextNode; + } + + if (LocalEncapData->Type =3D=3D BFM_ENCAP_TREE_GUIDED_SECTIO= N) { + Status =3D LibAddFfsFileToFvInf (FvInFd->FfsAttuibutes[Ind= ex].FfsName, InfFile, FALSE); + + if (EFI_ERROR (Status)) { + printf ("Error while generate FV inf file [files] sectio= n.\n"); + fclose (InfFile); + return Status; + } + + FvInFd->FfsAttuibutes[Index].Level =3D 0; + } + + } + } + + IsLastLevelFfs =3D FALSE; + FirstInFlag =3D TRUE; + if (!FfsFoundFlag) { + Status =3D LibAddFfsFileToFvInf (OutputFileName, InfFile, TRUE); + if (EFI_ERROR (Status)) { + printf ("Error while generate FV inf file [files] section.\n"); + fclose (InfFile); + return Status; + } + } + /* + if (OutputFileName !=3D NULL && FfsFoundFlag) { + Status =3D 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=3D LibFilenameStrExtended (strrchr(GenTempFile (), = OS_SEP), TemDir, "FV"); + Status =3D LibEncapsulateFfsToFv (InfFileName, NULL, OutputFileNam= e, FvGuidName); + if (FvGuidName !=3D NULL) { + free (FvGuidName); + } + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Patch FIT Table Data or reset vector data if exist. + // + if ((FvInFd->PatchData !=3D NULL) && (1 =3D=3D ParentLevel)) { + Status =3D LibPatchResetVectorAndFitTableData(OutputFileName, Fv= InFd->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 !=3D NULL) { + InputFileName =3D OutputFileName; + OutputFileName=3D LibFilenameStrExtended (strrchr(GenTempFile ()= , OS_SEP), TemDir, "ffs"); + + LocalEncapData =3D FvInFd->EncapData; + while (LocalEncapData->NextNode !=3D NULL) { + if (LocalEncapData->Level =3D=3D Level) { + break; + } + LocalEncapData =3D LocalEncapData->NextNode; + } + + Status =3D LibEncapSectionFileToFFS(EFI_FV_FILETYPE_FIRMWARE_VOL= UME_IMAGE, InputFileName, OutputFileName, ((EFI_FFS_FILE_HEADER *)LocalEnca= pData->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 =3D OutputFileName; + OutputFileName=3D LibFilenameStrExtended (strrchr(GenTempFile (), = OS_SEP), TemDir, "compressed"); + + // + // Use the guided section header guid to find out compress applica= tion name. + // + LocalEncapData =3D FvInFd->EncapData; + while (LocalEncapData->NextNode !=3D NULL) { + if (LocalEncapData->Level =3D=3D ParentLevel) { + break; + } + LocalEncapData =3D LocalEncapData->NextNode; + } + + ExtractionTool =3D + LookupGuidedSectionToolPath ( + mParsedGuidedSectionTools, + (EFI_GUID *)LocalEncapData->Data + ); + + Status =3D LibCreateGuidedSectionOriginalData (InputFileName, Extr= actionTool, OutputFileName); + + if (EFI_ERROR (Status)) { + printf ("Error while compress guided data. \n"); + return Status; + } + + InputFileName =3D OutputFileName; + OutputFileName=3D LibFilenameStrExtended (strrchr(GenTempFile (), = OS_SEP), TemDir, "guided"); + + Status =3D LibCreateFfsSection(InputFileName, NULL, EFI_SECTION_GU= ID_DEFINED, OutputFileName, NULL, NULL, LibBfmGuidToStr((EFI_GUID *)LocalEn= capData->Data), NULL); + + if (EFI_ERROR (Status)) { + printf ("Error while generate guided section. \n"); + return Status; + } + + break; + case BFM_ENCAP_TREE_COMPRESS_SECTION: + if (OutputFileName !=3D NULL) { + InputFileName =3D OutputFileName; + + OutputFileName=3D LibFilenameStrExtended (strrchr(GenTempFile ()= , OS_SEP), TemDir, "comsec"); + + LocalEncapData =3D FvInFd->EncapData; + while (LocalEncapData->NextNode !=3D NULL) { + if (LocalEncapData->Level =3D=3D ParentLevel) { + break; + } + LocalEncapData =3D LocalEncapData->NextNode; + } + + Status =3D LibGenCompressedSection (InputFileName, OutputFileNam= e, *(UINT8 *)(LocalEncapData->Data)); + + if (EFI_ERROR (Status)) { + printf ("Error while generate compressed section. \n"); + return Status; + } + } + break; + case BFM_ENCAP_TREE_FV_SECTION: + InputFileName =3D OutputFileName; + OutputFileName=3D LibFilenameStrExtended (strrchr(GenTempFile (), = OS_SEP), TemDir, "sec"); + + Status =3D LibCreateFfsSection(InputFileName, NULL, EFI_SECTION_FI= RMWARE_VOLUME_IMAGE, OutputFileName, NULL, NULL, NULL, NULL); + + if (EFI_ERROR (Status)) { + printf ("Error while generate FV section. \n"); + return Status; + } + + InputFileName =3D OutputFileName; + OutputFileName=3D LibFilenameStrExtended (strrchr(GenTempFile (), = OS_SEP), TemDir, "sec"); + + // + // Make it alignment. + // + Status =3D LibCreateFfsSection(InputFileName, NULL, 0, OutputFileN= ame, 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 -=3D 1; + LocalEncapData =3D FvInFd->EncapData; + while (LocalEncapData->NextNode !=3D NULL) { + if (LocalEncapData->Level =3D=3D ParentLevel) { + ParentType =3D LocalEncapData->Type; + break; + } + LocalEncapData =3D LocalEncapData->NextNode; + } + } while (ParentLevel !=3D 0); + + + *OutputFile =3D 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 =3D 0; + FvIndex2 =3D 0; + FvFoundFlag =3D FALSE; + + if (FdData =3D=3D NULL || FvId =3D=3D NULL || FvInFd =3D=3D NULL) { + return EFI_ABORTED; + } + + *FvId =3D (*FvInFd)->FvName; + + FvIndex1 =3D (UINT8) atoi ((*FvInFd)->FvName + 2); + + *FvInFd =3D FdData->Fv; + + while (FvInFd !=3D NULL) { + if (((*FvInFd)->FvName) !=3D NULL) { + FvIndex2 =3D (UINT8) atoi ((*FvInFd)->FvName + 2); + + if ((FvIndex2 <=3D FvIndex1) && (((*FvInFd)->FvLevel + FvIndex2) -1 = >=3D FvIndex1)) { + FvFoundFlag =3D TRUE; + break; + } + if ((*FvInFd)->FvNext =3D=3D 0) { + break; + } + *FvInFd =3D (*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 =3D NULL; + + if (FileName =3D=3D NULL) { + return 0; + } + File =3D fopen(FileName, "r"); + + if (File =3D=3D NULL) { + return 0; + } + fseek(File, 0L, SEEK_END); + Length =3D ftell(File); + fclose(File); + + return Length; +} + +/** + + Get the length of BFV PAD file. + + @retval The length of PAD file. + +**/ +UINT32 +GetBfvPadSize ( + VOID +) +{ + return PadSizeOfBfv; +} + diff --git a/Platform/Intel/Tools/BfmLib/BinFileManager.c b/Platform/Intel/= Tools/BfmLib/BinFileManager.c new file mode 100644 index 0000000000..8c8b67bd37 --- /dev/null +++ b/Platform/Intel/Tools/BfmLib/BinFileManager.c @@ -0,0 +1,1024 @@ +/** @file + + The main entry of BFM tool. + + Copyright (c) 2011-2019, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "BinFileManager.h" + +BOOLEAN mFvGuidIsSet =3D FALSE; +EFI_GUID mFvNameGuid =3D {0}; +CHAR8* mFvNameGuidString =3D NULL; +CHAR8* mGuidToolDefinition =3D "GuidToolDefinitionConf.ini"; + +// +// Store GUIDed Section guid->tool mapping +// +EFI_HANDLE mParsedGuidedSectionTools =3D NULL; + + +/** + Search the config file from the path list. + + Split the path from env PATH, and then search the cofig + file from these paths. The priority is from left to + right of PATH string. When met the first Config file, it + will break and return the pointer to the full file name. + + @param PathList the pointer to the path list. + @param FileName the pointer to the file name. + + @retval The pointer to the file name. + @return NULL An error occurred. +**/ +CHAR8 * +SearchConfigFromPathList ( + IN CHAR8 *PathList, + IN CHAR8 *FileName +) +{ + CHAR8 *CurDir; + CHAR8 *FileNamePath; + + CurDir =3D NULL; + FileNamePath =3D NULL; +#ifndef __GNUC__ + CurDir =3D strtok (PathList,";"); +#else + CurDir =3D strtok (PathList,":"); +#endif + while (CurDir !=3D NULL) { + FileNamePath =3D (char *)calloc( + strlen (CurDir) + strlen (OS_SEP_STR) +strlen (FileNa= me) + 1, + sizeof(char) + ); + if (FileNamePath =3D=3D NULL) { + return NULL; + } + sprintf(FileNamePath, "%s%c%s", CurDir, OS_SEP, FileName); + if (access (FileNamePath, 0) !=3D -1) { + return FileNamePath; + } +#ifndef __GNUC__ + CurDir =3D strtok(NULL, ";"); +#else + CurDir =3D strtok(NULL, ":"); +#endif + free (FileNamePath); + FileNamePath =3D NULL; + } + return NULL; +} + +/** + + Show the FD image layout information. Only display the modules with UI n= ame. + + @param[in] FdInName Input FD binary/image file name; + @param[in] FvName The FV ID in the FD file; + @param[in] ViewFlag Is this call for view or other operate(add/del/= replace) + @param[in] FdData The Fd data structure store the FD information. + + @retval EFI_SUCCESS + @retval EFI_INVALID_PARAMETER + @retval EFI_ABORTED + +**/ +EFI_STATUS +BfmImageView ( + IN CHAR8* FdInName, + IN CHAR8* FvName, + IN BOOLEAN ViewFlag, + IN FIRMWARE_DEVICE **FdData +) +{ + EFI_STATUS Status; + FIRMWARE_DEVICE *LocalFdData; + FV_INFORMATION *CurrentFv; + FILE *InputFile; + UINT32 FvSize; + UINTN BytesRead; + EFI_FIRMWARE_VOLUME_HEADER *FvImage; + UINT32 FfsCount; + UINT8 FvCount; + UINT8 LastFvNumber; + + LocalFdData =3D NULL; + CurrentFv =3D NULL; + FvImage =3D NULL; + FvSize =3D 0; + BytesRead =3D 0; + FfsCount =3D 0; + FvCount =3D 0; + LastFvNumber =3D 0; + + // + // Check the FD file name/path. + // + if (FdInName =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Open the file containing the FV + // + InputFile =3D fopen (FdInName, "rb"); + if (InputFile =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + Status =3D LibFindFvInFd (InputFile, &LocalFdData); + + if (EFI_ERROR(Status)) { + fclose (InputFile); + return EFI_ABORTED; + } + + CurrentFv =3D LocalFdData->Fv; + + do { + + memset (CurrentFv->FvName, '\0', _MAX_PATH); + + if (LastFvNumber =3D=3D 0) { + sprintf (CurrentFv->FvName, "FV%d", LastFvNumber); + } else { + sprintf (CurrentFv->FvName, "FV%d", LastFvNumber); + } + + // + // Determine size of FV + // + if (fseek (InputFile, CurrentFv->ImageAddress, SEEK_SET) !=3D 0) { + fclose (InputFile); + LibBfmFreeFd( LocalFdData); + return EFI_ABORTED; + } + + Status =3D LibGetFvSize(InputFile, &FvSize); + if (EFI_ERROR (Status)) { + fclose (InputFile); + return EFI_ABORTED; + } + + // + // Seek to the start of the image, then read the entire FV to the buff= er + // + fseek (InputFile, CurrentFv->ImageAddress, SEEK_SET); + + FvImage =3D (EFI_FIRMWARE_VOLUME_HEADER *) malloc (FvSize); + + if (FvImage =3D=3D NULL) { + fclose (InputFile); + LibBfmFreeFd( LocalFdData); + return EFI_ABORTED; + } + + BytesRead =3D fread (FvImage, 1, FvSize, InputFile); + if ((unsigned int) BytesRead !=3D FvSize) { + free (FvImage); + fclose (InputFile); + LibBfmFreeFd( LocalFdData); + return EFI_ABORTED; + } + + // + // Collect FV information each by each. + // + Status =3D LibGetFvInfo (FvImage, CurrentFv, FvName, 0, &FfsCount, Vie= wFlag, FALSE); + free (FvImage); + FvImage =3D NULL; + if (EFI_ERROR (Status)) { + fclose (InputFile); + LibBfmFreeFd( LocalFdData); + return Status; + } + FvCount =3D CurrentFv->FvLevel; + LastFvNumber =3D LastFvNumber+FvCount; + + FfsCount =3D 0; + + CurrentFv =3D CurrentFv->FvNext; + + } while (CurrentFv !=3D NULL); + + if (!ViewFlag) { + *FdData =3D LocalFdData; + } else { + LibBfmFreeFd( LocalFdData); + } + + fclose (InputFile); + + return EFI_SUCCESS; +} + +/** + Add an FFS file into a specify FV. + + @param[in] FdInName Input FD binary/image file name; + @param[in] NewFile The name of the file add in; + @param[in] FdOutName Name of output fd file. + + @retval EFI_SUCCESS + @retval EFI_INVALID_PARAMETER + @retval EFI_ABORTED + +**/ +EFI_STATUS +BfmImageAdd ( + IN CHAR8* FdInName, + IN CHAR8* NewFile, + IN CHAR8* FdOutName +) +{ + EFI_STATUS Status; + FIRMWARE_DEVICE *FdData; + FV_INFORMATION *FvInFd; + ENCAP_INFO_DATA *LocalEncapData; + ENCAP_INFO_DATA *LocalEncapDataTemp; + FILE* NewFdFile; + FILE* NewFvFile; + UINT64 NewFvLength; + UINT64 NewFfsLength; + VOID* Buffer; + CHAR8 *TemDir; + UINT8 FvEncapLevel; + UINT8 NewAddedFfsLevel; + BOOLEAN FfsLevelFoundFlag; + CHAR8 *OutputFileName; + CHAR8 *FvId; + BOOLEAN FirstInFlag; + BOOLEAN FvGuidExisted; + + NewFvLength =3D 0; + FvEncapLevel =3D 0; + NewAddedFfsLevel =3D 0; + + FfsLevelFoundFlag =3D FALSE; + FirstInFlag =3D TRUE; + FdData =3D NULL; + FvInFd =3D NULL; + LocalEncapData =3D NULL; + NewFdFile =3D NULL; + NewFvFile =3D NULL; + Buffer =3D NULL; + TemDir =3D NULL; + LocalEncapDataTemp =3D NULL; + OutputFileName =3D NULL; + FvId =3D NULL; + FvGuidExisted =3D FALSE; + + // + // Get the size of ffs file to be inserted. + // + NewFfsLength =3D GetFileSize(NewFile); + + Status =3D BfmImageView (FdInName, NULL, FALSE, &FdData); + + if (EFI_ERROR (Status)) { + printf ("Error while parse %s FD image.\n", FdInName); + return Status; + } + // + // Check the FvGuid whether exists or not when the BIOS hasn't default s= etting. + // If the FV image with -g GUID can't be found, the storage is still sav= ed into the BFV and report warning message. + // + FvInFd =3D FdData->Fv; + do { + if (mFvGuidIsSet && FvInFd->IsInputFvFlag) { + FvGuidExisted =3D TRUE; + break; + } + FvInFd =3D FvInFd->FvNext; + } while (FvInFd !=3D NULL); + + if (mFvGuidIsSet && !FvGuidExisted) { + printf ("Fv image with the specified FV Name Guid %s can't be found in= current FD.\n", mFvNameGuidString); + LibBfmFreeFd(FdData); + return EFI_ABORTED; + } + // + // Iterate to write FFS to each BFV. + // + FvInFd =3D FdData->Fv; + do { + if ((FvGuidExisted && mFvGuidIsSet && FvInFd->IsInputFvFlag) || ((!FvG= uidExisted || (!mFvGuidIsSet)) && FvInFd->IsBfvFlag)) { + + Status =3D LibLocateBfv (FdData, &FvId, &FvInFd); + + if (EFI_ERROR (Status)) { + printf("Error while locate BFV from FD.\n"); + LibBfmFreeFd(FdData); + return Status; + } + + // + // Determine the new added ffs file level in the FV. + // + LocalEncapData =3D FvInFd->EncapData; + + while (LocalEncapData !=3D NULL && !FfsLevelFoundFlag ) { + if (LocalEncapData->Type =3D=3D BFM_ENCAP_TREE_FV) { + if (FvEncapLevel =3D=3D ((UINT8) atoi (FvId + 2) - (UINT8) atoi = (FvInFd->FvName + 2))) { + // + // Found the FFS level in this FV. + // + LocalEncapDataTemp =3D LocalEncapData; + while (LocalEncapDataTemp !=3D NULL) { + if (LocalEncapDataTemp->Type =3D=3D BFM_ENCAP_TREE_FFS) { + NewAddedFfsLevel =3D LocalEncapDataTemp->Level; + FfsLevelFoundFlag =3D TRUE; + break; + } + if (LocalEncapDataTemp->NextNode !=3D NULL) { + LocalEncapDataTemp =3D LocalEncapDataTemp->NextNode; + } else { + break; + } + } + } + FvEncapLevel ++; + } + + if (LocalEncapData->NextNode =3D=3D NULL) { + break; + } else { + LocalEncapData =3D LocalEncapData->NextNode; + } + } + + // + // Add the new file into FV. + // + FvInFd->FfsNumbers +=3D 1; + if (strlen (NewFile) > _MAX_PATH - 1) { + printf ("The NewFile name is too long \n"); + LibBfmFreeFd(FdData); + return EFI_ABORTED; + } + strncpy (FvInFd->FfsAttuibutes[FvInFd->FfsNumbers].FfsName, NewFile,= _MAX_PATH - 1); + FvInFd->FfsAttuibutes[FvInFd->FfsNumbers].FfsName[_MAX_PATH - 1] =3D= 0; + FvInFd->FfsAttuibutes[FvInFd->FfsNumbers].Level =3D NewAddedFfsLev= el; + + TemDir =3D 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"); + LibBfmFreeFd(FdData); + return EFI_ABORTED; + } + strncat (TemDir, OS_SEP_STR, _MAX_PATH - strlen (TemDir) - 1); + strncat (TemDir, TEMP_DIR_NAME, _MAX_PATH - strlen (TemDir) - 1); + mkdir(TemDir, S_IRWXU | S_IRWXG | S_IRWXO); + Status =3D LibEncapNewFvFile (FvInFd, TemDir, &OutputFileName); + + if (EFI_ERROR (Status)) { + printf("Error. The boot firmware volume (BFV) has only the spare s= pace 0x%lx bytes. But the default setting data takes 0x%llx bytes, which ca= n't be inserted into BFV. \n",(unsigned long) GetBfvPadSize (), (unsigned l= ong long)NewFfsLength); + LibBfmFreeFd(FdData); + return Status; + } + + if (FirstInFlag) { + // + // Write New Fv file into the NewFd file. + // + Status =3D LibCreateNewFdCopy (FdInName, FdOutName); + if (EFI_ERROR (Status)) { + printf("Error while copy from %s to %s file. \n", FdInName, FdOu= tName); + LibBfmFreeFd(FdData); + return Status; + } + FirstInFlag =3D FALSE; + } + + NewFdFile =3D fopen (FdOutName, "rb+"); + if (NewFdFile =3D=3D NULL) { + printf("Error while create FD file %s. \n", FdOutName); + LibBfmFreeFd(FdData); + return EFI_ABORTED; + } + + NewFvFile =3D fopen (OutputFileName, "rb+"); + + if (NewFvFile =3D=3D NULL) { + printf("Error while create Fv file %s. \n", OutputFileName); + fclose(NewFdFile); + LibBfmFreeFd(FdData); + return EFI_ABORTED; + } + + fseek(NewFvFile,0,SEEK_SET); + fseek(NewFvFile,0,SEEK_END); + + NewFvLength =3D ftell(NewFvFile); + + fseek(NewFvFile,0,SEEK_SET); + + Buffer =3D malloc ((size_t)NewFvLength); + + if (Buffer =3D=3D NULL) { + printf ("Error while allocate resource! \n"); + fclose(NewFdFile); + fclose(NewFvFile); + LibBfmFreeFd(FdData); + return EFI_ABORTED; + } + + if (fread (Buffer, 1, (size_t) NewFvLength, NewFvFile) !=3D (size_t)= NewFvLength) { + printf("Error while reading Fv file %s. \n", OutputFileName); + free (Buffer); + fclose(NewFdFile); + fclose(NewFvFile); + LibBfmFreeFd(FdData); + return EFI_ABORTED; + } + + fseek(NewFdFile, FvInFd->ImageAddress, SEEK_SET); + fseek(NewFdFile, FvInFd->ImageAddress, SEEK_SET); + + if (NewFvLength <=3D FvInFd->FvHeader->FvLength) { + if (fwrite (Buffer, 1, (size_t) NewFvLength, NewFdFile) !=3D (size= _t) NewFvLength) { + printf("Error while writing FD file %s. \n", FdOutName); + fclose(NewFdFile); + fclose (NewFvFile); + free (Buffer); + LibBfmFreeFd(FdData); + return EFI_ABORTED; + } + } else { + printf("Error. The new size of BFV is 0x%llx bytes, which is large= r than the previous size of BFV 0x%llx bytes. \n", (unsigned long long) New= FvLength, (unsigned long long) FvInFd->FvHeader->FvLength); + free (Buffer); + fclose(NewFdFile); + fclose(NewFvFile); + LibBfmFreeFd(FdData); + return EFI_ABORTED; + } + + fclose(NewFdFile); + fclose(NewFvFile); + free (Buffer); + Buffer =3D NULL; + + } + FvInFd =3D FvInFd->FvNext; + } while (FvInFd !=3D NULL); + + + LibBfmFreeFd(FdData); + + if (TemDir =3D=3D NULL) { + if (mFvGuidIsSet) { + printf ("Fv image with the specified FV Name Guid %s can't be found.= \n", mFvNameGuidString); + } else { + printf ("BFV image can't be found.\n"); + } + return EFI_NOT_FOUND; + } + + Status =3D LibRmDir (TemDir); + + if (EFI_ERROR (Status)) { + printf("Error while remove temporary directory. \n"); + return Status; + } + + return EFI_SUCCESS; +} + + +/** + Replace an FFS file into a specify FV. + + @param[in] FdInName Input FD binary/image file name; + @param[in] NewFile The name of the file add in; + @param[in] FdOutName Name of output fd file. + + @retval EFI_SUCCESS + @retval EFI_INVALID_PARAMETER + @retval EFI_ABORTED + +**/ +EFI_STATUS +BfmImageReplace ( + IN CHAR8* FdInName, + IN CHAR8* NewFile, + IN CHAR8* FdOutName +) +{ + EFI_STATUS Status; + FIRMWARE_DEVICE *FdData; + FV_INFORMATION *FvInFd; + FILE* NewFdFile; + FILE* NewFvFile; + UINT64 NewFvLength; + UINT64 NewFfsLength; + VOID* Buffer; + CHAR8 *TemDir; + CHAR8 *OutputFileName; + CHAR8 *FvId; + BOOLEAN FirstInFlag; + UINT32 Index; + BOOLEAN FvToBeUpdate; + BOOLEAN FdIsUpdate; + ENCAP_INFO_DATA *LocalEncapData; + ENCAP_INFO_DATA *LocalEncapDataTemp; + UINT8 FvEncapLevel; + UINT8 NewAddedFfsLevel; + BOOLEAN FfsLevelFoundFlag; + EFI_GUID EfiNewAddToBfvGuid; + FILE* FfsFile; + UINTN BytesRead; + BOOLEAN ReplaceSameFv; + BOOLEAN FvGuidExisted; + + NewFvLength =3D 0; + FdIsUpdate =3D FALSE; + FirstInFlag =3D TRUE; + FdData =3D NULL; + FvInFd =3D NULL; + NewFdFile =3D NULL; + NewFvFile =3D NULL; + Buffer =3D NULL; + TemDir =3D NULL; + OutputFileName =3D NULL; + FvId =3D NULL; + FfsFile =3D NULL; + BytesRead =3D 0; + ReplaceSameFv =3D FALSE; + FvGuidExisted =3D FALSE; + + // + // Get the size of ffs file to be inserted. + // + NewFfsLength =3D GetFileSize(NewFile); + // + // Get FFS GUID + // + FfsFile =3D fopen (NewFile, "rb"); + if (FfsFile =3D=3D NULL) { + printf ("Error while read %s.\n", NewFile); + return EFI_ABORTED; + } + fseek (FfsFile, 0, SEEK_SET); + BytesRead =3D fread (&EfiNewAddToBfvGuid, 1, sizeof(EFI_GUID), FfsFile); + fclose (FfsFile); + if (BytesRead !=3D sizeof(EFI_GUID)) { + printf ("Error while read the GUID from %s.\n", NewFile); + return EFI_ABORTED; + } + Status =3D BfmImageView (FdInName, NULL, FALSE, &FdData); + + if (EFI_ERROR (Status)) { + printf ("Error while parse %s FD image.\n", FdInName); + return Status; + } + + // + // Check the FvGuid whether exists or not when the BIOS has default sett= ing. + // 1. No option means the storage is saved into the same FV image. + // 2. The FV image with -g GUID can't be found. The storage is still sa= ved into the same FV image and report warning message. + // + if (!mFvGuidIsSet) { + ReplaceSameFv =3D TRUE; + } + FvInFd =3D FdData->Fv; + do { + if (mFvGuidIsSet && FvInFd->IsInputFvFlag) { + FvGuidExisted =3D TRUE; + break; + } + FvInFd =3D FvInFd->FvNext; + } while (FvInFd !=3D NULL); + + if (mFvGuidIsSet && !FvGuidExisted) { + printf ("Fv image with the specified FV Name Guid %s can't be found in= current FD.\n", mFvNameGuidString); + ReplaceSameFv =3D TRUE; + LibBfmFreeFd(FdData); + return EFI_ABORTED; + } + // + // Interate to insert or replace default setting to Fv + // + FvInFd =3D FdData->Fv; + do { + FvToBeUpdate =3D FALSE; + if (mFvGuidIsSet && FvInFd->IsInputFvFlag) { + FvToBeUpdate =3D TRUE; + } + + Status =3D LibLocateBfv (FdData, &FvId, &FvInFd); + + if (EFI_ERROR (Status)) { + printf("Error while locate BFV from FD.\n"); + LibBfmFreeFd(FdData); + return Status; + } + + Index =3D 0; + while (Index <=3D FvInFd->FfsNumbers) { + // + // Locate the multi-platform ffs in Fv and then replace or delete it. + // + if (!CompareGuid(&FvInFd->FfsHeader[Index].Name, &EfiNewAddToBfvGuid= )) { + if (ReplaceSameFv) { + FvToBeUpdate =3D TRUE; + } + break; + } + Index ++; + } + + if (FvToBeUpdate || (Index <=3D FvInFd->FfsNumbers)) { + if (FvToBeUpdate) { + FdIsUpdate =3D TRUE; + if (Index <=3D FvInFd->FfsNumbers) { + // + // Override original default data by New File + // + if (strlen (NewFile) > _MAX_PATH - 1) { + printf ("The NewFile name is too long \n"); + LibBfmFreeFd(FdData); + return EFI_ABORTED; + } + strncpy (FvInFd->FfsAttuibutes[Index].FfsName, NewFile, _MAX_PAT= H - 1); + FvInFd->FfsAttuibutes[Index].FfsName[_MAX_PATH - 1] =3D 0; + } else { + FfsLevelFoundFlag =3D FALSE; + FvEncapLevel =3D 0; + NewAddedFfsLevel =3D 0; + // + // Determine the new added ffs file level in the FV. + // + LocalEncapData =3D FvInFd->EncapData; + + while (LocalEncapData !=3D NULL && !FfsLevelFoundFlag ) { + if (LocalEncapData->Type =3D=3D BFM_ENCAP_TREE_FV) { + if (FvEncapLevel =3D=3D ((UINT8) atoi (FvId + 2) - (UINT8) a= toi (FvInFd->FvName + 2))) { + // + // Found the FFS level in this FV. + // + LocalEncapDataTemp =3D LocalEncapData; + while (LocalEncapDataTemp !=3D NULL) { + if (LocalEncapDataTemp->Type =3D=3D BFM_ENCAP_TREE_FFS) { + NewAddedFfsLevel =3D LocalEncapDataTemp->Level; + FfsLevelFoundFlag =3D TRUE; + break; + } + if (LocalEncapDataTemp->NextNode !=3D NULL) { + LocalEncapDataTemp =3D LocalEncapDataTemp->NextNode; + } else { + break; + } + } + } + FvEncapLevel ++; + } + + if (LocalEncapData->NextNode =3D=3D NULL) { + break; + } else { + LocalEncapData =3D LocalEncapData->NextNode; + } + } + + // + // Add the new file into FV. + // + FvInFd->FfsNumbers +=3D 1; + memcpy (FvInFd->FfsAttuibutes[FvInFd->FfsNumbers].FfsName, NewFi= le, _MAX_PATH); + FvInFd->FfsAttuibutes[FvInFd->FfsNumbers].Level =3D NewAddedFf= sLevel; + } + } else { + // + // Remove original default data from FV. + // + FvInFd->FfsAttuibutes[Index].FfsName[0] =3D '\0'; + } + + if (TemDir =3D=3D NULL) { + TemDir =3D 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"); + LibBfmFreeFd(FdData); + return EFI_ABORTED; + } + strncat (TemDir, OS_SEP_STR, _MAX_PATH - strlen (TemDir) - 1); + strncat (TemDir, TEMP_DIR_NAME, _MAX_PATH - strlen (TemDir) - 1); + mkdir(TemDir, S_IRWXU | S_IRWXG | S_IRWXO); + } + + Status =3D LibEncapNewFvFile (FvInFd, TemDir, &OutputFileName); + + if (EFI_ERROR (Status)) { + printf("Error. The boot firmware volume (BFV) has only the spare s= pace 0x%lx bytes. But the default setting data takes 0x%llx bytes, which ca= n't be inserted into BFV. \n", (unsigned long) GetBfvPadSize (), (unsigned = long long) NewFfsLength); + LibBfmFreeFd(FdData); + return Status; + } + + if (FirstInFlag) { + // + // Write New Fv file into the NewFd file. + // + Status =3D LibCreateNewFdCopy (FdInName, FdOutName); + if (EFI_ERROR (Status)) { + printf("Error while copy from %s to %s file. \n", FdInName, FdOu= tName); + LibBfmFreeFd(FdData); + return Status; + } + FirstInFlag =3D FALSE; + } + + NewFdFile =3D fopen (FdOutName, "rb+"); + if (NewFdFile =3D=3D NULL) { + printf("Error while create FD file %s. \n", FdOutName); + LibBfmFreeFd(FdData); + return EFI_ABORTED; + } + + NewFvFile =3D fopen (OutputFileName, "rb+"); + + if (NewFvFile =3D=3D NULL) { + printf("Error while create Fv file %s. \n", OutputFileName); + LibBfmFreeFd(FdData); + fclose (NewFdFile); + return EFI_ABORTED; + } + + fseek(NewFvFile,0,SEEK_SET); + fseek(NewFvFile,0,SEEK_END); + + NewFvLength =3D ftell(NewFvFile); + + fseek(NewFvFile,0,SEEK_SET); + + Buffer =3D malloc ((size_t)NewFvLength); + + if (Buffer =3D=3D NULL) { + LibBfmFreeFd(FdData); + fclose (NewFdFile); + fclose (NewFvFile); + return EFI_ABORTED; + } + + if (fread (Buffer, 1, (size_t) NewFvLength, NewFvFile) !=3D (size_t)= NewFvLength) { + printf("Error while read Fv file %s. \n", OutputFileName); + LibBfmFreeFd(FdData); + free (Buffer); + fclose (NewFdFile); + fclose (NewFvFile); + return EFI_ABORTED; + } + + fseek(NewFdFile, FvInFd->ImageAddress, SEEK_SET); + fseek(NewFdFile, FvInFd->ImageAddress, SEEK_SET); + + if (NewFvLength <=3D FvInFd->FvHeader->FvLength) { + if (fwrite (Buffer, 1, (size_t) NewFvLength, NewFdFile) !=3D (size= _t) NewFvLength) { + printf("Error while write FD file %s. \n", FdOutName); + fclose(NewFdFile); + fclose (NewFvFile); + LibBfmFreeFd(FdData); + free (Buffer); + return EFI_ABORTED; + } + } else { + printf("Error. The new size of BFV is 0x%llx bytes, which is large= r than the previous size of BFV 0x%llx bytes. \n", (unsigned long long) New= FvLength, (unsigned long long) FvInFd->FvHeader->FvLength); + free (Buffer); + LibBfmFreeFd(FdData); + fclose (NewFdFile); + fclose (NewFvFile); + return EFI_ABORTED; + } + + fclose(NewFdFile); + fclose(NewFvFile); + free (Buffer); + Buffer =3D NULL; + + } + FvInFd =3D FvInFd->FvNext; + } while (FvInFd !=3D NULL); + + LibBfmFreeFd(FdData); + + if (TemDir =3D=3D NULL || !FdIsUpdate) { + if (mFvGuidIsSet) { + printf ("Fv image with the specified FV Name Guid %s can't be found.= \n", mFvNameGuidString); + } else { + printf ("BFV image can't be found.\n"); + } + return EFI_NOT_FOUND; + } + + Status =3D LibRmDir (TemDir); + + if (EFI_ERROR (Status)) { + printf("Error while remove temporary directory. \n"); + return Status; + } + + return EFI_SUCCESS; +} + +/** + + The main entry of BFM tool. + +**/ +int main( + int Argc, + char *Argv[] +) +{ + EFI_STATUS Status; + FIRMWARE_DEVICE *FdData; + CHAR8 *InFilePath; + CHAR8 FullGuidToolDefinition[_MAX_PATH]; + CHAR8 *FileName; + UINTN FileNameIndex; + CHAR8 *PathList; + UINTN EnvLen; + CHAR8 *NewPathList; + + FdData =3D NULL; + PathList =3D NULL; + NewPathList =3D NULL; + EnvLen =3D 0; + + if (Argc <=3D 1) { + return -1; + } + FileName =3D Argv[0]; + // + // Save, skip filename arg + // + Argc--; + Argv++; + + if ((stricmp(Argv[0], "-v") =3D=3D 0)) { + // + // Check the revison of BfmLib + // BfmLib -v + // + printf("%s\n", __BUILD_VERSION); + return 1; + + } + // + // Workaroud: the first call to this function + // returns a file name ends with dot + // +#ifndef __GNUC__ + tmpnam (NULL); +#else + CHAR8 tmp[] =3D "/tmp/fileXXXXXX"; + UINTN Fdtmp; + Fdtmp =3D mkstemp(tmp); + close(Fdtmp); +#endif + // + // Get the same path with the application itself + // + if (strlen (FileName) > _MAX_PATH - 1) { + Error (NULL, 0, 2000, "Parameter: Input file name is too long", NULL); + return -1; + } + strncpy (FullGuidToolDefinition, FileName, _MAX_PATH - 1); + FullGuidToolDefinition[_MAX_PATH - 1] =3D 0; + FileNameIndex =3D strlen (FullGuidToolDefinition); + while (FileNameIndex !=3D 0) { + FileNameIndex --; + if (FullGuidToolDefinition[FileNameIndex] =3D=3D OS_SEP) { + FullGuidToolDefinition[FileNameIndex] =3D 0; + break; + } + } + // + // Build the path list for Config file scan. The priority is below. + // 1. Scan the current path + // 2. Scan the same path with the application itself + // 3. Scan the current %PATH% of OS environment + // 4. Use the build-in default configuration + // + PathList =3D getenv("PATH"); + if (PathList =3D=3D NULL) { + Error (NULL, 0, 1001, "Option: Environment variable 'PATH' does not ex= ist", NULL); + return -1; + } + EnvLen =3D strlen(PathList); + NewPathList =3D (char *)calloc( + strlen (".") + + strlen (";") + + strlen (FullGuidToolDefinition) + + strlen (";") + + EnvLen + + 1, + sizeof(char) + ); + if (NewPathList =3D=3D NULL) { + Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL); + PathList =3D NULL; + free (PathList); + return -1; + } +#ifndef __GNUC__ + sprintf (NewPathList, "%s;%s;%s", ".", FullGuidToolDefinition, PathList); +#else + sprintf (NewPathList, "%s:%s:%s", ".", FullGuidToolDefinition, PathList); +#endif + + PathList =3D NULL; + free (PathList); + // + // Load Guid Tools definition + // + InFilePath =3D SearchConfigFromPathList(NewPathList, mGuidToolDefinition= ); + free (NewPathList); + if (InFilePath !=3D NULL) { + printf ("\nThe Guid Tool Definition of BfmLib comes from the '%s'. \n"= , InFilePath); + mParsedGuidedSectionTools =3D ParseGuidedSectionToolsFile (InFilePath); + free (InFilePath); + } else { + // + // Use the pre-defined standard guided tools. + // + printf ("\nThe Guid Tool Definition of BfmLib comes from the build-in de= fault configuration. \n"); + mParsedGuidedSectionTools =3D LibPreDefinedGuidedTools (); + } + + // + // BfmLib -e FdName.Fd + // + if ((stricmp(Argv[0], "-e") =3D=3D 0)) { + + if (Argc !=3D 2) { + return -1; + } + // + // Extract FFS files. + // + Status =3D BfmImageView (Argv[1], NULL, FALSE, &FdData); + + if (EFI_ERROR (Status)) { + return -1; + } + + if (FdData =3D=3D NULL) { + return -1; + } + + LibBfmFreeFd(FdData); + + } else if ((stricmp(Argv[0], "-i") =3D=3D 0)) { + // + // Insert FFS files to BFV + // BfmLib -i InFdName.Fd FfsName.ffs OutFdName.Fd -g FvNameGuid + // + if (Argc =3D=3D 6) { + mFvGuidIsSet =3D TRUE; + mFvNameGuidString =3D Argv[5]; + StringToGuid (Argv[5], &mFvNameGuid); + Argc -=3D 2; + } + if (Argc !=3D 4) { + return -1; + } + Status =3D BfmImageAdd(Argv[1], Argv[2], Argv[3]); + + if (EFI_ERROR (Status)) { + return -1; + } + + } else if ((stricmp(Argv[0], "-r") =3D=3D 0)) { + // + // Replace FFS files in BFV + // BfmLib -r InFdName.Fd FfsName.ffs OutFdName.Fd -g FvNameGuid + // + if (Argc =3D=3D 6) { + mFvGuidIsSet =3D TRUE; + mFvNameGuidString =3D Argv[5]; + StringToGuid (Argv[5], &mFvNameGuid); + Argc -=3D 2; + } + if (Argc !=3D 4) { + return -1; + } + Status =3D BfmImageReplace (Argv[1], Argv[2], Argv[3]); + + if (EFI_ERROR (Status)) { + return -1; + } + + } else { + // + // Invalid parameter. + // + return -1; + } + + return 1; +} + diff --git a/Platform/Intel/Tools/BfmLib/BinFileManager.h b/Platform/Intel/= Tools/BfmLib/BinFileManager.h new file mode 100644 index 0000000000..ea27f2e8f2 --- /dev/null +++ b/Platform/Intel/Tools/BfmLib/BinFileManager.h @@ -0,0 +1,439 @@ +/** @file + + The header of BinFileManager.c. + +Copyright (c) 2011-2019, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _BIN_FILE_MANAGER_ +#define _BIN_FILE_MANAGER_ + +#ifdef __GNUC__ +#include +#else +#include +#include +#endif +#include +#include +#include +#include +#include +#include +#include + +#include "CommonLib.h" +#include "EfiUtilityMsgs.h" +#include "ParseGuidedSectionTools.h" +#include "StringFuncs.h" +#include "Compress.h" +#include "Decompress.h" +#include "ParseInf.h" + +#ifndef _MAX_PATH +#define _MAX_PATH 500 +#endif + +#ifdef __GNUC__ +#define OS_SEP '/' +#define OS_SEP_STR "/" +#define COPY_STR "cp \"%s\" \"%s\" > /dev/null" +#define RMDIR_STR "rm -r \"%s\" > /dev/null" +#define DEL_STR "rm \"%s\" > /dev/null" +#else +#define OS_SEP '\\' +#define OS_SEP_STR "\\" +#define COPY_STR "copy \"%s\" \"%s\" > NUL" +#define RMDIR_STR "rmdir /S /Q \"%s\" > NUL" +#define DEL_STR "del \"%s\" > NUL" +#endif + +#define TEMP_DIR_NAME "Temp" +#define UTILITY_NAME "Binary File Manager (BFM)" +#define UTILITY_SHORT_NAME "BFM" +#define UTILITY_MAJOR_VERSION 0 +#define UTILITY_MINOR_VERSION 1 +#define MAX_BASENAME_LEN 60 // not good to HardCode, but let's = be reasonable +#define EFI_SECTION_ERROR EFIERR (100) +// +// The maximum number of Pad file guid entries. +// +#define MAX_NUMBER_OF_PAD_FILE_GUIDS 1024 + +// +// The maximum number of block map entries supported by the library +// +#define MAX_NUMBER_OF_FV_BLOCKS 100 + + +// +// The maximum number of sections in an FFS file. +// +#define MAX_NUMBER_OF_SECTION_IN_FFS 100 + +// +// The maximum number of files in the FV supported by the library +// +#define MAX_NUMBER_OF_FILES_IN_FV 1000 +#define MAX_NUMBER_OF_FILES_IN_CAP 1000 + + + +/// +/// If present, this must be the first and only opcode, +/// EFI_DEP_BEFORE is only used by DXE driver. +/// +#define EFI_DEP_BEFORE 0x00 + +/// +/// If present, this must be the first and only opcode, +/// EFI_DEP_AFTER is only used by DXE driver. +/// +#define EFI_DEP_AFTER 0x01 + +#define EFI_DEP_PUSH 0x02 +#define EFI_DEP_AND 0x03 +#define EFI_DEP_OR 0x04 +#define EFI_DEP_NOT 0x05 +#define EFI_DEP_TRUE 0x06 +#define EFI_DEP_FALSE 0x07 +#define EFI_DEP_END 0x08 + + +/// +/// If present, this must be the first opcode, +/// EFI_DEP_SOR is only used by DXE driver. +/// +#define EFI_DEP_SOR 0x09 + +// +// INF file strings +// +#define OPTIONS_SECTION_STRING "[options]" +#define ATTRIBUTES_SECTION_STRING "[attributes]" +#define FILES_SECTION_STRING "[files]" +#define FV_BASE_ADDRESS_STRING "[FV_BASE_ADDRESS]" + +// +// Options section +// +#define EFI_FV_BASE_ADDRESS_STRING "EFI_BASE_ADDRESS" +#define EFI_FV_FILE_NAME_STRING "EFI_FILE_NAME" +#define EFI_NUM_BLOCKS_STRING "EFI_NUM_BLOCKS" +#define EFI_BLOCK_SIZE_STRING "EFI_BLOCK_SIZE" +#define EFI_GUID_STRING "EFI_GUID" +#define EFI_FV_FILESYSTEMGUID_STRING "EFI_FV_GUID" +#define EFI_FV_NAMEGUID_STRING "EFI_FVNAME_GUID" +#define EFI_CAPSULE_GUID_STRING "EFI_CAPSULE_GUID" +#define EFI_CAPSULE_HEADER_SIZE_STRING "EFI_CAPSULE_HEADER_SIZE" +#define EFI_CAPSULE_FLAGS_STRING "EFI_CAPSULE_FLAGS" +#define EFI_CAPSULE_VERSION_STRING "EFI_CAPSULE_VERSION" + +#define EFI_FV_TOTAL_SIZE_STRING "EFI_FV_TOTAL_SIZE" +#define EFI_FV_TAKEN_SIZE_STRING "EFI_FV_TAKEN_SIZE" +#define EFI_FV_SPACE_SIZE_STRING "EFI_FV_SPACE_SIZE" + + +typedef UINT32 BFM_ENCAP_TYPE; + +#define MAX_LEVEL_IN_FV_FILE 32 + +// +// Types of BFM_ENCAP_TREENODE_TYPE +// +#define BFM_ENCAP_TREE_FV 0x1 +#define BFM_ENCAP_TREE_FFS 0x2 +#define BFM_ENCAP_TREE_GUIDED_SECTION 0x3 +#define BFM_ENCAP_TREE_COMPRESS_SECTION 0x4 +#define BFM_ENCAP_TREE_FV_SECTION 0x5 + +extern EFI_HANDLE mParsedGuidedSectionTools; +extern BOOLEAN mFvGuidIsSet; +extern EFI_GUID mFvNameGuid; + +// +// Structure to keep a list of GUID-To-BaseNames +// +typedef struct _GUID_TO_BASENAME { + struct _GUID_TO_BASENAME *Next; + INT8 Guid[PRINTED_GUID_BUFFER_SIZE]; + INT8 BaseName[MAX_BASENAME_LEN]; +} GUID_TO_BASENAME; + +typedef struct _GUID_SEC_TOOL_ENTRY { + EFI_GUID Guid; + CHAR8* Name; + CHAR8* Path; + struct _GUID_SEC_TOOL_ENTRY *Next; +} GUID_SEC_TOOL_ENTRY; + +// +// Private data types +// +// +// Component information +// +typedef struct { + UINTN Size; + CHAR8 ComponentName[_MAX_PATH]; +} COMPONENT_INFO; + +typedef struct { + CHAR8 FfsName[_MAX_PATH]; + + // + // UI Name for this FFS file, if has. + // + CHAR16 UiName[_MAX_PATH]; + + // + // Total section number in this FFS. + // + UINT32 TotalSectionNum; + + // + // Describe the position of the FFS file. + // + UINT8 Level; + // + // If this FFS has no encapsulate section, this flag will set to True. + // + BOOLEAN IsLeaf; + // + // Section type for each section in FFS. + // + EFI_SECTION_TYPE SectionType[MAX_NUMBER_OF_SECTION_IN_FFS]; + +}FFS_ATTRIBUTES; + + +typedef struct __ENCAP_INFO_DATA{ + // + // Now Level + // + UINT8 Level; + + // + // Encapsulate type. + // + BFM_ENCAP_TYPE Type; + + // + // Data, if it's FV, should be FV header. + // + VOID *Data; + + // + // if FV ExtHeaderOffset not to zero, should also have FvExtHeader infor= mation + // + EFI_FIRMWARE_VOLUME_EXT_HEADER *FvExtHeader; + + + // + // Next node. + // + struct __ENCAP_INFO_DATA *NextNode; +}ENCAP_INFO_DATA; + + +// +// Contain Offset and Data for PAD FFS contain reset vector or FIT data. +// +typedef struct _PATCH_DATA_PAD_FFS { + // + // The offset of data relative to FV start address; + // + UINT32 Offset; + // + // Data + // + VOID *Data; + // + // Length of Data + // + UINT32 Length; + // + // Next node. + // + struct _PATCH_DATA_PAD_FFS *NextNode; +} PATCH_DATA_PAD_FFS; + + +// +// FV and capsule information holder +// +typedef struct _FV_INFOMATION{ + EFI_FIRMWARE_VOLUME_HEADER *FvHeader; + EFI_FIRMWARE_VOLUME_EXT_HEADER *FvExtHeader; + UINT32 ImageAddress; + UINT32 FfsNumbers; + CHAR8 FvName[_MAX_PATH]; + EFI_FV_BLOCK_MAP_ENTRY FvBlocks[MAX_NUMBER_OF_FV_BLOCKS]; + FFS_ATTRIBUTES FfsAttuibutes[MAX_NUMBER_OF_FILES_IN_FV]; + EFI_FFS_FILE_HEADER2 FfsHeader[MAX_NUMBER_OF_FILES_IN_FV]; + struct _FV_INFOMATION *FvNext; + ENCAP_INFO_DATA *EncapData; + UINT8 FvLevel; + PATCH_DATA_PAD_FFS *PatchData; + BOOLEAN IsBfvFlag; + BOOLEAN IsInputFvFlag; + +} FV_INFORMATION; + +typedef struct _FIRMWARE_DEVICE { + /// + /// Size of FD file + /// + UINT32 Size; + FV_INFORMATION *Fv; +} FIRMWARE_DEVICE; + +VOID +Usage ( + VOID +); + + +CHAR8 * +GenTempFile ( + VOID +); + +EFI_STATUS +LibFindFvInFd ( + IN FILE *InputFile, + IN OUT FIRMWARE_DEVICE **FdData +); + +/** + + Add function description + + @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 + ); + +/* + Get size info from FV file. + + @param[in] + @param[out] + + @retval + +*/ +EFI_STATUS +LibGetFvSize ( + IN FILE *InputFile, + OUT UINT32 *FvSize + ); + + /** + + 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 + ); + +EFI_STATUS +LibCreateNewFdCopy( + IN CHAR8* OldFd, + IN CHAR8* NewFd + ); + +/** + 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 + ); + + +/** + + Free the whole Fd data structure. + + @param[in] Fd The pointer point to the Fd data structure. + +**/ +VOID +LibBfmFreeFd ( + FIRMWARE_DEVICE *Fd +); + +EFI_HANDLE +LibPreDefinedGuidedTools ( + VOID +); + +EFI_STATUS +LibEncapNewFvFile( + IN FV_INFORMATION *FvInFd, + IN CHAR8 *TemDir, + OUT CHAR8 **OutputFile +); + +EFI_STATUS +LibLocateBfv( + IN FIRMWARE_DEVICE *FdData, + IN OUT CHAR8 **FvId, + IN OUT FV_INFORMATION **FvInFd +); + +/** + + Get the length of a file. + + @param[in] FileName The name of a file. + + @retval The length of file. + +**/ +UINT64 +GetFileSize ( + IN CHAR8 *FileName +); + +/** + + Get the length of BFV PAD file. + + @retval The length of PAD file. + +**/ +UINT32 +GetBfvPadSize ( + VOID +); +#endif diff --git a/Platform/Intel/Tools/BfmLib/GNUmakefile b/Platform/Intel/Tools= /BfmLib/GNUmakefile new file mode 100644 index 0000000000..bd88c58afe --- /dev/null +++ b/Platform/Intel/Tools/BfmLib/GNUmakefile @@ -0,0 +1,15 @@ +## @file +# GNU/Linux makefile for 'BfmLib' module build. +# +# Copyright (c) 2011-2019, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +MAKEROOT ?=3D $(EDK_TOOLS_PATH)/Source/C + +APPNAME =3D BfmLib + +LIBS =3D -lCommon + +OBJECTS =3D BinFileManager.o BfmLib.o + +include $(MAKEROOT)/Makefiles/app.makefile diff --git a/Platform/Intel/Tools/BfmLib/Makefile b/Platform/Intel/Tools/Bf= mLib/Makefile new file mode 100644 index 0000000000..0d10f4ff2d --- /dev/null +++ b/Platform/Intel/Tools/BfmLib/Makefile @@ -0,0 +1,17 @@ +## @file +# +# Windows makefile for 'BfmLib' module build. +# +# Copyright (c) 2011-2019, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent# +## +!INCLUDE $(EDK_TOOLS_PATH)\Source\C\Makefiles\ms.common + +APPNAME =3D BfmLib + +LIBS =3D $(LIB_PATH)\Common.lib + +OBJECTS =3D BinFileManager.obj BfmLib.obj + +!INCLUDE $(EDK_TOOLS_PATH)\Source\C\Makefiles\ms.app + --=20 2.18.0.windows.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#42670): https://edk2.groups.io/g/devel/message/42670 Mute This Topic: https://groups.io/mt/32154335/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-