From nobody Tue Jan 7 01:46:07 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) smtp.mailfrom=edk2-devel-bounces@lists.01.org Return-Path: Received: from ml01.01.org (ml01.01.org [198.145.21.10]) by mx.zohomail.com with SMTPS id 1525466511118193.21717214939497; Fri, 4 May 2018 13:41:51 -0700 (PDT) Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id 6347F203BEA3A; Fri, 4 May 2018 13:41:50 -0700 (PDT) Received: from foss.arm.com (foss.arm.com [217.140.101.70]) by ml01.01.org (Postfix) with ESMTP id A4699203BEA2B for ; Fri, 4 May 2018 13:41:49 -0700 (PDT) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 8392A1435; Fri, 4 May 2018 13:41:49 -0700 (PDT) Received: from u201365.usa.Arm.com (bc-c3-3-14.eu.iaas.arm.com [10.6.43.238]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id DCF203F487; Fri, 4 May 2018 13:41:47 -0700 (PDT) X-Original-To: edk2-devel@lists.01.org Received-SPF: none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) client-ip=198.145.21.10; envelope-from=edk2-devel-bounces@lists.01.org; helo=ml01.01.org; Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=217.140.101.70; helo=foss.arm.com; envelope-from=supreeth.venkatesh@arm.com; receiver=edk2-devel@lists.01.org From: Supreeth Venkatesh To: edk2-devel@lists.01.org Date: Fri, 4 May 2018 21:40:59 +0100 Message-Id: <20180504204109.3354-8-supreeth.venkatesh@arm.com> X-Mailer: git-send-email 2.16.2 In-Reply-To: <20180504204109.3354-1-supreeth.venkatesh@arm.com> References: <20180504204109.3354-1-supreeth.venkatesh@arm.com> Subject: [edk2] [PATCH v2 07/17] StandaloneMmPkg/FvLib: Add a common FV Library for management mode. X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.26 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: ard.biesheuvel@linaro.org, leif.lindholm@linaro.org, jiewen.yao@intel.com, liming.gao@intel.com, michael.d.kinney@intel.com MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Errors-To: edk2-devel-bounces@lists.01.org Sender: "edk2-devel" X-ZohoMail: RSF_4 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" This patch implements a firmware volume library that can be used by the Standalone management mode core module to parse the firmware volume. Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Supreeth Venkatesh Reviewed-by: Achin Gupta Reviewed-by: Jiewen Yao --- StandaloneMmPkg/Include/Library/FvLib.h | 109 +++++++++ StandaloneMmPkg/Library/FvLib/FvLib.c | 386 ++++++++++++++++++++++++++++= ++++ StandaloneMmPkg/Library/FvLib/FvLib.inf | 57 +++++ 3 files changed, 552 insertions(+) create mode 100644 StandaloneMmPkg/Include/Library/FvLib.h create mode 100644 StandaloneMmPkg/Library/FvLib/FvLib.c create mode 100644 StandaloneMmPkg/Library/FvLib/FvLib.inf diff --git a/StandaloneMmPkg/Include/Library/FvLib.h b/StandaloneMmPkg/Incl= ude/Library/FvLib.h new file mode 100644 index 0000000000..64e65b412d --- /dev/null +++ b/StandaloneMmPkg/Include/Library/FvLib.h @@ -0,0 +1,109 @@ +/** @file + +Copyright (c) 2015, Intel Corporation. All rights reserved.
+Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.
+ +This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD = License +which accompanies this distribution. The full text of the license may be = found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLI= ED. + +**/ + +#ifndef _FV_LIB_H_ +#define _FV_LIB_H_ + +#include +#include +#include + +/** + Given the input file pointer, search for the next matching file in the + FFS volume as defined by SearchType. The search starts from FileHeader i= nside + the Firmware Volume defined by FwVolHeader. + + @param SearchType Filter to find only files of this type. + Type EFI_FV_FILETYPE_ALL causes no filtering to be d= one. + @param FwVolHeader Pointer to the FV header of the volume to search. + This parameter must point to a valid FFS volume. + @param FileHeader Pointer to the current file from which to begin sear= ching. + This pointer will be updated upon return to reflect = the file found. + + @retval EFI_NOT_FOUND No files matching the search criteria were found + @retval EFI_SUCCESS +**/ +EFI_STATUS +EFIAPI +FfsFindNextFile ( + IN EFI_FV_FILETYPE SearchType, + IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader, + IN OUT EFI_FFS_FILE_HEADER **FileHeader + ); + +/** + Given the input file pointer, search for the next matching section in the + FFS volume. + + @param SearchType Filter to find only sections of this type. + @param FfsFileHeader Pointer to the current file to search. + @param SectionHeader Pointer to the Section matching SectionType in Ffs= FileHeader. + NULL if section not found + + @retval EFI_NOT_FOUND No files matching the search criteria were found + @retval EFI_SUCCESS +**/ +EFI_STATUS +FfsFindSection ( + IN EFI_SECTION_TYPE SectionType, + IN EFI_FFS_FILE_HEADER *FfsFileHeader, + IN OUT EFI_COMMON_SECTION_HEADER **SectionHeader + ); + +/** + Locates a section within a series of sections + with the specified section type. + + @param[in] Sections The sections to search + @param[in] SizeOfSections Total size of all sections + @param[in] SectionType The section type to locate + @param[out] FoundSection The FFS section if found + + @retval EFI_SUCCESS The file and section was found + @retval EFI_NOT_FOUND The file and section was not found + @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted +**/ +EFI_STATUS +EFIAPI +FindFfsSectionInSections ( + IN VOID *Sections, + IN UINTN SizeOfSections, + IN EFI_SECTION_TYPE SectionType, + OUT EFI_COMMON_SECTION_HEADER **FoundSection + ); + +/** + Given the input file pointer, search for the next matching section in the + FFS volume. + + @param SearchType Filter to find only sections of this type. + @param FfsFileHeader Pointer to the current file to search. + @param SectionData Pointer to the Section matching SectionType in F= fsFileHeader. + NULL if section not found + @param SectionDataSize The size of SectionData + + @retval EFI_NOT_FOUND No files matching the search criteria were found + @retval EFI_SUCCESS +**/ +EFI_STATUS +EFIAPI +FfsFindSectionData ( + IN EFI_SECTION_TYPE SectionType, + IN EFI_FFS_FILE_HEADER *FfsFileHeader, + OUT VOID **SectionData, + OUT UINTN *SectionDataSize + ); + +#endif diff --git a/StandaloneMmPkg/Library/FvLib/FvLib.c b/StandaloneMmPkg/Librar= y/FvLib/FvLib.c new file mode 100644 index 0000000000..4c0993ffb8 --- /dev/null +++ b/StandaloneMmPkg/Library/FvLib/FvLib.c @@ -0,0 +1,386 @@ +/** @file + +Copyright (c) 2015, Intel Corporation. All rights reserved.
+Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.
+ +This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD = License +which accompanies this distribution. The full text of the license may be = found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLI= ED. + +**/ + +#include + +#include +#include +#include + +#define GET_OCCUPIED_SIZE(ActualSize, Alignment) \ + (ActualSize) + (((Alignment) - ((ActualSize) & ((Alignment) - 1))) & ((A= lignment) - 1)) + +/** + Returns the highest bit set of the State field + + @param ErasePolarity Erase Polarity as defined by EFI_FVB_ERASE_POLAR= ITY + in the Attributes field. + @param FfsHeader Pointer to FFS File Header. + + @return the highest bit in the State field +**/ +EFI_FFS_FILE_STATE +GetFileState ( + IN UINT8 ErasePolarity, + IN EFI_FFS_FILE_HEADER *FfsHeader + ) +{ + EFI_FFS_FILE_STATE FileState; + EFI_FFS_FILE_STATE HighestBit; + + FileState =3D FfsHeader->State; + + if (ErasePolarity !=3D 0) { + FileState =3D (EFI_FFS_FILE_STATE)~FileState; + } + + HighestBit =3D 0x80; + while (HighestBit !=3D 0 && (HighestBit & FileState) =3D=3D 0) { + HighestBit >>=3D 1; + } + + return HighestBit; +} + +/** + Calculates the checksum of the header of a file. + + @param FileHeader Pointer to FFS File Header. + + @return Checksum of the header. +**/ +UINT8 +CalculateHeaderChecksum ( + IN EFI_FFS_FILE_HEADER *FileHeader + ) +{ + UINT8 *ptr; + UINTN Index; + UINT8 Sum; + + Sum =3D 0; + ptr =3D (UINT8 *) FileHeader; + + for (Index =3D 0; Index < sizeof (EFI_FFS_FILE_HEADER) - 3; Index +=3D 4= ) { + Sum =3D (UINT8) (Sum + ptr[Index]); + Sum =3D (UINT8) (Sum + ptr[Index + 1]); + Sum =3D (UINT8) (Sum + ptr[Index + 2]); + Sum =3D (UINT8) (Sum + ptr[Index + 3]); + } + + for (; Index < sizeof (EFI_FFS_FILE_HEADER); Index++) { + Sum =3D (UINT8) (Sum + ptr[Index]); + } + // + // State field (since this indicates the different state of file). + // + Sum =3D (UINT8) (Sum - FileHeader->State); + // + // Checksum field of the file is not part of the header checksum. + // + Sum =3D (UINT8) (Sum - FileHeader->IntegrityCheck.Checksum.File); + + return Sum; +} + +/** + Given the input file pointer, search for the next matching file in the + FFS volume as defined by SearchType. The search starts from FileHeader i= nside + the Firmware Volume defined by FwVolHeader. + + @param SearchType Filter to find only files of this type. + Type EFI_FV_FILETYPE_ALL causes no filtering to be d= one. + @param FwVolHeader Pointer to the FV header of the volume to search. + This parameter must point to a valid FFS volume. + @param FileHeader Pointer to the current file from which to begin sear= ching. + This pointer will be updated upon return to reflect = the file found. + + @retval EFI_NOT_FOUND No files matching the search criteria were found + @retval EFI_SUCCESS +**/ +EFI_STATUS +EFIAPI +FfsFindNextFile ( + IN EFI_FV_FILETYPE SearchType, + IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader, + IN OUT EFI_FFS_FILE_HEADER **FileHeader + ) +{ + EFI_FIRMWARE_VOLUME_EXT_HEADER *FvExtHeader; + + EFI_FFS_FILE_HEADER *FfsFileHeader; + UINT32 FileLength; + UINT32 FileOccupiedSize; + UINT32 FileOffset; + UINT64 FvLength; + UINT8 ErasePolarity; + UINT8 FileState; + + FvLength =3D FwVolHeader->FvLength; + if (FwVolHeader->Attributes & EFI_FVB2_ERASE_POLARITY) { + ErasePolarity =3D 1; + } else { + ErasePolarity =3D 0; + } + // + // If FileHeader is not specified (NULL) start with the first file in the + // firmware volume. Otherwise, start from the FileHeader. + // + if (*FileHeader =3D=3D NULL) { + + if (FwVolHeader->ExtHeaderOffset !=3D 0) { + + FvExtHeader =3D (EFI_FIRMWARE_VOLUME_EXT_HEADER *)((UINT8 *)FwVolHea= der + + FwVolHeader->ExtHea= derOffset); + + FfsFileHeader =3D (EFI_FFS_FILE_HEADER *)((UINT8 *)FvExtHeader + + FvExtHeader->ExtHeaderSize); + + } else { + + FfsFileHeader =3D (EFI_FFS_FILE_HEADER *)((UINT8 *)FwVolHeader + + FwVolHeader->HeaderLength); + + } + + FfsFileHeader =3D (EFI_FFS_FILE_HEADER *)((UINTN)FwVolHeader + + ALIGN_VALUE((UINTN)FfsFileHead= er - + (UINTN)FwVolHeader= , 8)); + } else { + // + // Length is 24 bits wide so mask upper 8 bits + // FileLength is adjusted to FileOccupiedSize as it is 8 byte aligned. + // + FileLength =3D FFS_FILE_SIZE(*FileHeader); + FileOccupiedSize =3D GET_OCCUPIED_SIZE (FileLength, 8); + FfsFileHeader =3D (EFI_FFS_FILE_HEADER *) ((UINT8 *) *FileHeader += FileOccupiedSize); + } + + FileOffset =3D (UINT32) ((UINT8 *) FfsFileHeader - (UINT8 *) FwVolHeader= ); + + while (FileOffset < (FvLength - sizeof (EFI_FFS_FILE_HEADER))) { + // + // Get FileState which is the highest bit of the State + // + FileState =3D GetFileState (ErasePolarity, FfsFileHeader); + + switch (FileState) { + + case EFI_FILE_HEADER_INVALID: + FileOffset +=3D sizeof (EFI_FFS_FILE_HEADER); + FfsFileHeader =3D (EFI_FFS_FILE_HEADER *) ((UINT8 *) FfsFileHeader += sizeof (EFI_FFS_FILE_HEADER)); + break; + + case EFI_FILE_DATA_VALID: + case EFI_FILE_MARKED_FOR_UPDATE: + if (CalculateHeaderChecksum (FfsFileHeader) =3D=3D 0) { + FileLength =3D FFS_FILE_SIZE(FfsFileHeader); + FileOccupiedSize =3D GET_OCCUPIED_SIZE (FileLength, 8); + + if ((SearchType =3D=3D FfsFileHeader->Type) || (SearchType =3D=3D = EFI_FV_FILETYPE_ALL)) { + + *FileHeader =3D FfsFileHeader; + + return EFI_SUCCESS; + } + + FileOffset +=3D FileOccupiedSize; + FfsFileHeader =3D (EFI_FFS_FILE_HEADER *) ((UINT8 *) FfsFileHeader= + FileOccupiedSize); + } else { + return EFI_NOT_FOUND; + } + break; + + case EFI_FILE_DELETED: + FileLength =3D FFS_FILE_SIZE(FfsFileHeader); + FileOccupiedSize =3D GET_OCCUPIED_SIZE (FileLength, 8); + FileOffset +=3D FileOccupiedSize; + FfsFileHeader =3D (EFI_FFS_FILE_HEADER *) ((UINT8 *) FfsFileHeader += FileOccupiedSize); + break; + + default: + return EFI_NOT_FOUND; + + } + } + + return EFI_NOT_FOUND; +} + +/** + Locates a section within a series of sections + with the specified section type. + + @param[in] Sections The sections to search + @param[in] SizeOfSections Total size of all sections + @param[in] SectionType The section type to locate + @param[out] FoundSection The FFS section if found + + @retval EFI_SUCCESS The file and section was found + @retval EFI_NOT_FOUND The file and section was not found + @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted +**/ +EFI_STATUS +EFIAPI +FindFfsSectionInSections ( + IN VOID *Sections, + IN UINTN SizeOfSections, + IN EFI_SECTION_TYPE SectionType, + OUT EFI_COMMON_SECTION_HEADER **FoundSection + ) +{ + EFI_PHYSICAL_ADDRESS CurrentAddress; + UINT32 Size; + EFI_PHYSICAL_ADDRESS EndOfSections; + EFI_COMMON_SECTION_HEADER *Section; + EFI_PHYSICAL_ADDRESS EndOfSection; + + // + // Loop through the FFS file sections + // + EndOfSection =3D (EFI_PHYSICAL_ADDRESS)(UINTN) Sections; + EndOfSections =3D EndOfSection + SizeOfSections; + for (;;) { + if (EndOfSection =3D=3D EndOfSections) { + break; + } + CurrentAddress =3D EndOfSection; + + Section =3D (EFI_COMMON_SECTION_HEADER*)(UINTN) CurrentAddress; +// printf ("Section->Type: 0x%08x\n", Section->Type); + + Size =3D SECTION_SIZE (Section); + if (Size < sizeof (*Section)) { + return EFI_VOLUME_CORRUPTED; + } + + EndOfSection =3D CurrentAddress + Size; + if (EndOfSection > EndOfSections) { + return EFI_VOLUME_CORRUPTED; + } + Size =3D GET_OCCUPIED_SIZE (Size, 4); + + // + // Look for the requested section type + // + if (Section->Type =3D=3D SectionType) { + *FoundSection =3D Section; + return EFI_SUCCESS; + } + } + + return EFI_NOT_FOUND; +} + +/** + Given the input file pointer, search for the next matching section in the + FFS volume. + + @param SearchType Filter to find only sections of this type. + @param FfsFileHeader Pointer to the current file to search. + @param SectionHeader Pointer to the Section matching SectionType in Ffs= FileHeader. + NULL if section not found + + @retval EFI_NOT_FOUND No files matching the search criteria were found + @retval EFI_SUCCESS +**/ +EFI_STATUS +EFIAPI +FfsFindSection ( + IN EFI_SECTION_TYPE SectionType, + IN EFI_FFS_FILE_HEADER *FfsFileHeader, + IN OUT EFI_COMMON_SECTION_HEADER **SectionHeader + ) +{ + UINT32 FileSize; + EFI_COMMON_SECTION_HEADER *Section; + EFI_STATUS Status; + + // + // Size is 24 bits wide so mask upper 8 bits. + // Does not include FfsFileHeader header size + // FileSize is adjusted to FileOccupiedSize as it is 8 byte aligned. + // + Section =3D (EFI_COMMON_SECTION_HEADER *) (FfsFileHeader + 1); + FileSize =3D FFS_FILE_SIZE(FfsFileHeader); + FileSize -=3D sizeof (EFI_FFS_FILE_HEADER); + + Status =3D FindFfsSectionInSections ( + Section, + FileSize, + SectionType, + SectionHeader + ); + return Status; +} + +/** + Given the input file pointer, search for the next matching section in the + FFS volume. + + @param SearchType Filter to find only sections of this type. + @param FfsFileHeader Pointer to the current file to search. + @param SectionData Pointer to the Section matching SectionType in F= fsFileHeader. + NULL if section not found + @param SectionDataSize The size of SectionData + + @retval EFI_NOT_FOUND No files matching the search criteria were found + @retval EFI_SUCCESS +**/ +EFI_STATUS +EFIAPI +FfsFindSectionData ( + IN EFI_SECTION_TYPE SectionType, + IN EFI_FFS_FILE_HEADER *FfsFileHeader, + IN OUT VOID **SectionData, + IN OUT UINTN *SectionDataSize + ) +{ + UINT32 FileSize; + EFI_COMMON_SECTION_HEADER *Section; + UINT32 SectionLength; + UINT32 ParsedLength; + + // + // Size is 24 bits wide so mask upper 8 bits. + // Does not include FfsFileHeader header size + // FileSize is adjusted to FileOccupiedSize as it is 8 byte aligned. + // + Section =3D (EFI_COMMON_SECTION_HEADER *) (FfsFileHeader + 1); + FileSize =3D FFS_FILE_SIZE(FfsFileHeader); + FileSize -=3D sizeof (EFI_FFS_FILE_HEADER); + + *SectionData =3D NULL; + ParsedLength =3D 0; + while (ParsedLength < FileSize) { + if (Section->Type =3D=3D SectionType) { + *SectionData =3D (VOID *) (Section + 1); + *SectionDataSize =3D SECTION_SIZE(Section); + return EFI_SUCCESS; + } + // + // Size is 24 bits wide so mask upper 8 bits. + // SectionLength is adjusted it is 4 byte aligned. + // Go to the next section + // + SectionLength =3D SECTION_SIZE(Section); + SectionLength =3D GET_OCCUPIED_SIZE (SectionLength, 4); + + ParsedLength +=3D SectionLength; + Section =3D (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) Section + Section= Length); + } + + return EFI_NOT_FOUND; +} diff --git a/StandaloneMmPkg/Library/FvLib/FvLib.inf b/StandaloneMmPkg/Libr= ary/FvLib/FvLib.inf new file mode 100644 index 0000000000..f768810ee5 --- /dev/null +++ b/StandaloneMmPkg/Library/FvLib/FvLib.inf @@ -0,0 +1,57 @@ +## @file +# +# Copyright (c) 2015, Intel Corporation. All rights reserved.
+# Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the B= SD License +# which accompanies this distribution. The full text of the license may b= e found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IM= PLIED. +# +## + +##########################################################################= ###### +# +# Defines Section - statements that will be processed to create a Makefile. +# +##########################################################################= ###### +[Defines] + INF_VERSION =3D 0x0001001A + BASE_NAME =3D FvLib + FILE_GUID =3D C20085E9-E3AB-4938-A727-C10935FEEE2B + MODULE_TYPE =3D BASE + VERSION_STRING =3D 1.0 + LIBRARY_CLASS =3D FvLib + +# +# The following information is for reference only and not required by the = build tools. +# +# VALID_ARCHITECTURES =3D IA32 +# + +##########################################################################= ###### +# +# Sources Section - list of files that are required for the build to succe= ed. +# +##########################################################################= ###### + +[Sources] + FvLib.c + +##########################################################################= ###### +# +# Package Dependency Section - list of Package files that are required for +# this module. +# +##########################################################################= ###### + +[Packages] + MdePkg/MdePkg.dec + StandaloneMmPkg/StandaloneMmPkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + DebugLib --=20 2.16.2 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel