From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mga04.intel.com (mga04.intel.com [192.55.52.120]) by mx.groups.io with SMTP id smtpd.web11.1970.1589493168169412090 for ; Thu, 14 May 2020 14:52:48 -0700 Authentication-Results: mx.groups.io; dkim=missing; spf=pass (domain: intel.com, ip: 192.55.52.120, mailfrom: wei6.xu@intel.com) IronPort-SDR: Mp9sSl03ZmPC1zTAJhL4e5WRKMHNhK8pmUeUiiyUQEcrhGCSlsCiyawJk97ODfSJjKSd819/mu 21hGBlBCTtQA== X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga004.jf.intel.com ([10.7.209.38]) by fmsmga104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 14 May 2020 14:52:47 -0700 IronPort-SDR: 0tvgk3gigW68QuZSnT8Wdsu6VmHraI6vAWYonQ+IsS6HrMM9I9te/S05SlpfGPDzV31ps1nF0T Q+/32XX6GufA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.73,392,1583222400"; d="scan'208";a="410233830" Received: from shwdeopenpsi174.ccr.corp.intel.com ([10.239.157.39]) by orsmga004.jf.intel.com with ESMTP; 14 May 2020 14:52:44 -0700 From: "Xu, Wei6" To: devel@edk2.groups.io Cc: Michael D Kinney , Liming Gao , Sean Brogan Subject: [edk2-devel] [PATCH V3 1/5] FmpDevicePkg: Add FmpDependency library class and BASE instance Date: Fri, 15 May 2020 05:52:28 +0800 Message-Id: <20200514215232.13372-2-wei6.xu@intel.com> X-Mailer: git-send-email 2.16.2.windows.1 In-Reply-To: <20200514215232.13372-1-wei6.xu@intel.com> References: <20200514215232.13372-1-wei6.xu@intel.com> REF: https://bugzilla.tianocore.org/show_bug.cgi?id=2696 This library provides services to evaluate Fmp capsule dependency expression, validate dependency expression and get dependency from firmware image. Cc: Michael D Kinney Cc: Liming Gao Cc: Sean Brogan Signed-off-by: Wei6 Xu --- FmpDevicePkg/FmpDevicePkg.dec | 6 +- FmpDevicePkg/FmpDevicePkg.dsc | 4 +- FmpDevicePkg/Include/Library/FmpDependencyLib.h | 89 ++++ .../Library/FmpDependencyLib/FmpDependencyLib.c | 546 +++++++++++++++++++++ .../Library/FmpDependencyLib/FmpDependencyLib.inf | 34 ++ .../Library/FmpDependencyLib/FmpDependencyLib.uni | 12 + 6 files changed, 689 insertions(+), 2 deletions(-) create mode 100644 FmpDevicePkg/Include/Library/FmpDependencyLib.h create mode 100644 FmpDevicePkg/Library/FmpDependencyLib/FmpDependencyLib.c create mode 100644 FmpDevicePkg/Library/FmpDependencyLib/FmpDependencyLib.inf create mode 100644 FmpDevicePkg/Library/FmpDependencyLib/FmpDependencyLib.uni diff --git a/FmpDevicePkg/FmpDevicePkg.dec b/FmpDevicePkg/FmpDevicePkg.dec index 55671878dd..4947008346 100644 --- a/FmpDevicePkg/FmpDevicePkg.dec +++ b/FmpDevicePkg/FmpDevicePkg.dec @@ -5,11 +5,11 @@ # instance that supports the update of firmware storage devices using UEFI # Capsules. The behavior of the Firmware Management Protocol instance is # customized using libraries and PCDs. # # Copyright (c) 2016, Microsoft Corporation. All rights reserved.
-# Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.
+# Copyright (c) 2018 - 2020, Intel Corporation. All rights reserved.
# # SPDX-License-Identifier: BSD-2-Clause-Patent # ## @@ -33,10 +33,14 @@ ## @libraryclass Provides firmware device specific services to support # updates of a firmware image stored in a firmware device. FmpDeviceLib|Include/Library/FmpDeviceLib.h + ## @libraryclass Provides generic services to support capsule dependency + # expression evaluation. + FmpDependencyLib|Include/Library/FmpDependencyLib.h + [LibraryClasses.Common.Private] ## @libraryclass Provides services to retrieve values from a capsule's FMP # Payload Header. The structure is not included in the # library class. Instead, services are provided to retrieve # information from the FMP Payload Header. If information is diff --git a/FmpDevicePkg/FmpDevicePkg.dsc b/FmpDevicePkg/FmpDevicePkg.dsc index b8fb9d7c19..dfb3c1a141 100644 --- a/FmpDevicePkg/FmpDevicePkg.dsc +++ b/FmpDevicePkg/FmpDevicePkg.dsc @@ -5,11 +5,11 @@ # instance that supports the update of firmware storage devices using UEFI # Capsules. The behavior of the Firmware Management Protocol instance is # customized using libraries and PCDs. # # Copyright (c) 2016, Microsoft Corporation. All rights reserved.
-# Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.
+# Copyright (c) 2018 - 2020, Intel Corporation. All rights reserved.
# Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.
# # SPDX-License-Identifier: BSD-2-Clause-Patent # ## @@ -58,10 +58,11 @@ !endif FmpAuthenticationLib|SecurityPkg/Library/FmpAuthenticationLibPkcs7/FmpAuthenticationLibPkcs7.inf CapsuleUpdatePolicyLib|FmpDevicePkg/Library/CapsuleUpdatePolicyLibNull/CapsuleUpdatePolicyLibNull.inf FmpPayloadHeaderLib|FmpDevicePkg/Library/FmpPayloadHeaderLibV1/FmpPayloadHeaderLibV1.inf FmpDeviceLib|FmpDevicePkg/Library/FmpDeviceLibNull/FmpDeviceLibNull.inf + FmpDependencyLib|FmpDevicePkg/Library/FmpDependencyLib/FmpDependencyLib.inf TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf [LibraryClasses.ARM, LibraryClasses.AARCH64] # # It is not possible to prevent the ARM compiler for generic intrinsic functions. @@ -86,10 +87,11 @@ # FmpDevicePkg/Library/CapsuleUpdatePolicyLibNull/CapsuleUpdatePolicyLibNull.inf FmpDevicePkg/Library/CapsuleUpdatePolicyLibOnProtocol/CapsuleUpdatePolicyLibOnProtocol.inf FmpDevicePkg/Library/FmpPayloadHeaderLibV1/FmpPayloadHeaderLibV1.inf FmpDevicePkg/Library/FmpDeviceLibNull/FmpDeviceLibNull.inf + FmpDevicePkg/Library/FmpDependencyLib/FmpDependencyLib.inf FmpDevicePkg/FmpDxe/FmpDxeLib.inf # # Modules # diff --git a/FmpDevicePkg/Include/Library/FmpDependencyLib.h b/FmpDevicePkg/Include/Library/FmpDependencyLib.h new file mode 100644 index 0000000000..1a191ca6ee --- /dev/null +++ b/FmpDevicePkg/Include/Library/FmpDependencyLib.h @@ -0,0 +1,89 @@ +/** @file + Fmp Capsule Dependency support functions for Firmware Management Protocol based + firmware updates. + + Copyright (c) 2020, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __FMP_DEPENDENCY_LIB__ +#define __FMP_DEPENDENCY_LIB__ + +#include +#include + +// +// Data struct to store FMP ImageType and version for dependency check. +// +typedef struct { + EFI_GUID ImageTypeId; + UINT32 Version; +} FMP_DEPEX_CHECK_VERSION_DATA; + +/** + Validate the dependency expression and output its size. + + @param[in] Dependencies Pointer to the EFI_FIRMWARE_IMAGE_DEP. + @param[in] MaxDepexSize Max size of the dependency. + @param[out] DepexSize Size of dependency. + + @retval TRUE The capsule is valid. + @retval FALSE The capsule is invalid. + +**/ +BOOLEAN +EFIAPI +ValidateDependency ( + IN EFI_FIRMWARE_IMAGE_DEP *Dependencies, + IN CONST UINTN MaxDepexSize, + OUT UINT32 *DepexSize + ); + +/** + Get dependency from firmware image. + + @param[in] Image Points to the firmware image. + @param[in] ImageSize Size, in bytes, of the firmware image. + @param[out] DepexSize Size, in bytes, of the dependency. + + @retval The pointer to dependency. + @retval Null + +**/ +EFI_FIRMWARE_IMAGE_DEP* +EFIAPI +GetImageDependency ( + IN EFI_FIRMWARE_IMAGE_AUTHENTICATION *Image, + IN UINTN ImageSize, + OUT UINT32 *DepexSize + ); + +/** + Evaluate the dependencies. The caller must search all the Fmp instances and + gather their versions into FmpVersions parameter. If there is PUSH_GUID opcode + in dependency expression with no FmpVersions provided, the dependency will + evaluate to FALSE. + + @param[in] Dependencies Dependency expressions. + @param[in] DependenciesSize Size of Dependency expressions. + @param[in] FmpVersions Array of Fmp ImageTypeId and version. This + parameter is optional and can be set to NULL. + @param[in] FmpVersionsCount Element count of the array. When FmpVersions + is NULL, FmpVersionsCount must be 0. + + @retval TRUE Dependency expressions evaluate to TRUE. + @retval FALSE Dependency expressions evaluate to FALSE. + +**/ +BOOLEAN +EFIAPI +EvaluateDependency ( + IN EFI_FIRMWARE_IMAGE_DEP *Dependencies, + IN UINTN DependenciesSize, + IN FMP_DEPEX_CHECK_VERSION_DATA *FmpVersions OPTIONAL, + IN UINTN FmpVersionsCount + ); + +#endif diff --git a/FmpDevicePkg/Library/FmpDependencyLib/FmpDependencyLib.c b/FmpDevicePkg/Library/FmpDependencyLib/FmpDependencyLib.c new file mode 100644 index 0000000000..a8083bff12 --- /dev/null +++ b/FmpDevicePkg/Library/FmpDependencyLib/FmpDependencyLib.c @@ -0,0 +1,546 @@ +/** @file + Supports Fmp Capsule Dependency Expression. + + Copyright (c) 2020, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ +#include +#include +#include +#include +#include +#include + +// +// Define the initial size of the dependency expression evaluation stack +// +#define DEPEX_STACK_SIZE_INCREMENT 0x1000 + +// +// Type of stack element +// +typedef enum { + BooleanType, + VersionType +} ELEMENT_TYPE; + +// +// Value of stack element +// +typedef union { + BOOLEAN Boolean; + UINT32 Version; +} ELEMENT_VALUE; + +// +// Stack element used to evaluate dependency expressions +// +typedef struct { + ELEMENT_VALUE Value; + ELEMENT_TYPE Type; +} DEPEX_ELEMENT; + +// +// Global stack used to evaluate dependency expressions +// +DEPEX_ELEMENT *mDepexEvaluationStack = NULL; +DEPEX_ELEMENT *mDepexEvaluationStackEnd = NULL; +DEPEX_ELEMENT *mDepexEvaluationStackPointer = NULL; + +/** + Grow size of the Depex stack + + @retval EFI_SUCCESS Stack successfully growed. + @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack. + +**/ +EFI_STATUS +GrowDepexStack ( + VOID + ) +{ + DEPEX_ELEMENT *NewStack; + UINTN Size; + + Size = DEPEX_STACK_SIZE_INCREMENT; + if (mDepexEvaluationStack != NULL) { + Size = Size + (mDepexEvaluationStackEnd - mDepexEvaluationStack); + } + + NewStack = AllocatePool (Size * sizeof (DEPEX_ELEMENT)); + if (NewStack == NULL) { + DEBUG ((DEBUG_ERROR, "GrowDepexStack: Cannot allocate memory for dependency evaluation stack!\n")); + return EFI_OUT_OF_RESOURCES; + } + + if (mDepexEvaluationStack != NULL) { + // + // Copy to Old Stack to the New Stack + // + CopyMem ( + NewStack, + mDepexEvaluationStack, + (mDepexEvaluationStackEnd - mDepexEvaluationStack) * sizeof (DEPEX_ELEMENT) + ); + + // + // Free The Old Stack + // + FreePool (mDepexEvaluationStack); + } + + // + // Make the Stack pointer point to the old data in the new stack + // + mDepexEvaluationStackPointer = NewStack + (mDepexEvaluationStackPointer - mDepexEvaluationStack); + mDepexEvaluationStack = NewStack; + mDepexEvaluationStackEnd = NewStack + Size; + + return EFI_SUCCESS; +} + +/** + Push an element onto the Stack. + + @param[in] Value Value to push. + @param[in] Type Element Type + + @retval EFI_SUCCESS The value was pushed onto the stack. + @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack. + @retval EFI_INVALID_PARAMETER Wrong stack element type. + +**/ +EFI_STATUS +Push ( + IN UINT32 Value, + IN UINTN Type + ) +{ + EFI_STATUS Status; + DEPEX_ELEMENT Element; + + // + // Check Type + // + if (Type != BooleanType && Type != VersionType) { + return EFI_INVALID_PARAMETER; + } + + // + // Check for a stack overflow condition + // + if (mDepexEvaluationStackPointer == mDepexEvaluationStackEnd) { + // + // Grow the stack + // + Status = GrowDepexStack (); + if (EFI_ERROR (Status)) { + return Status; + } + } + + Element.Value.Version = Value; + Element.Type = Type; + + // + // Push the item onto the stack + // + *mDepexEvaluationStackPointer = Element; + mDepexEvaluationStackPointer++; + + return EFI_SUCCESS; +} + +/** + Pop an element from the stack. + + @param[out] Element Element to pop. + @param[in] Type Type of element. + + @retval EFI_SUCCESS The value was popped onto the stack. + @retval EFI_ACCESS_DENIED The pop operation underflowed the stack. + @retval EFI_INVALID_PARAMETER Type is mismatched. + +**/ +EFI_STATUS +Pop ( + OUT DEPEX_ELEMENT *Element, + IN ELEMENT_TYPE Type + ) +{ + // + // Check for a stack underflow condition + // + if (mDepexEvaluationStackPointer == mDepexEvaluationStack) { + DEBUG ((DEBUG_ERROR, "EvaluateDependency: Stack underflow!\n")); + return EFI_ACCESS_DENIED; + } + + // + // Pop the item off the stack + // + mDepexEvaluationStackPointer--; + *Element = *mDepexEvaluationStackPointer; + if ((*Element).Type != Type) { + DEBUG ((DEBUG_ERROR, "EvaluateDependency: Popped element type is mismatched!\n")); + return EFI_INVALID_PARAMETER; + } + return EFI_SUCCESS; +} + +/** + Evaluate the dependencies. The caller must search all the Fmp instances and + gather their versions into FmpVersions parameter. If there is PUSH_GUID opcode + in dependency expression with no FmpVersions provided, the dependency will + evaluate to FALSE. + + @param[in] Dependencies Dependency expressions. + @param[in] DependenciesSize Size of Dependency expressions. + @param[in] FmpVersions Array of Fmp ImageTypeId and version. This + parameter is optional and can be set to NULL. + @param[in] FmpVersionsCount Element count of the array. When FmpVersions + is NULL, FmpVersionsCount must be 0. + + @retval TRUE Dependency expressions evaluate to TRUE. + @retval FALSE Dependency expressions evaluate to FALSE. + +**/ +BOOLEAN +EFIAPI +EvaluateDependency ( + IN EFI_FIRMWARE_IMAGE_DEP *Dependencies, + IN UINTN DependenciesSize, + IN FMP_DEPEX_CHECK_VERSION_DATA *FmpVersions OPTIONAL, + IN UINTN FmpVersionsCount + ) +{ + EFI_STATUS Status; + UINT8 *Iterator; + UINT8 Index; + DEPEX_ELEMENT Element1; + DEPEX_ELEMENT Element2; + GUID ImageTypeId; + UINT32 Version; + + // + // Check if parameter is valid. + // + if (Dependencies == NULL || DependenciesSize == 0) { + return FALSE; + } + + if (FmpVersions == NULL && FmpVersionsCount > 0) { + return FALSE; + } + + // + // Clean out memory leaks in Depex Boolean stack. Leaks are only caused by + // incorrectly formed DEPEX expressions + // + mDepexEvaluationStackPointer = mDepexEvaluationStack; + + Iterator = (UINT8 *) Dependencies->Dependencies; + while (Iterator < (UINT8 *) Dependencies->Dependencies + DependenciesSize) { + switch (*Iterator) + { + case EFI_FMP_DEP_PUSH_GUID: + if (Iterator + sizeof (EFI_GUID) >= (UINT8 *) Dependencies->Dependencies + DependenciesSize) { + DEBUG ((DEBUG_ERROR, "EvaluateDependency: GUID extends beyond end of dependency expression!\n")); + goto Error; + } + + CopyGuid (&ImageTypeId, (EFI_GUID *) (Iterator + 1)); + Iterator = Iterator + sizeof (EFI_GUID); + + for (Index = 0; Index < FmpVersionsCount; Index ++) { + if(CompareGuid (&FmpVersions[Index].ImageTypeId, &ImageTypeId)){ + Status = Push (FmpVersions[Index].Version, VersionType); + if (EFI_ERROR (Status)) { + goto Error; + } + break; + } + } + if (Index == FmpVersionsCount) { + DEBUG ((DEBUG_ERROR, "EvaluateDependency: %g is not found!\n", &ImageTypeId)); + goto Error; + } + break; + case EFI_FMP_DEP_PUSH_VERSION: + if (Iterator + sizeof (UINT32) >= (UINT8 *) Dependencies->Dependencies + DependenciesSize ) { + DEBUG ((DEBUG_ERROR, "EvaluateDependency: VERSION extends beyond end of dependency expression!\n")); + goto Error; + } + + Version = *(UINT32 *) (Iterator + 1); + Status = Push (Version, VersionType); + if (EFI_ERROR (Status)) { + goto Error; + } + Iterator = Iterator + sizeof (UINT32); + break; + case EFI_FMP_DEP_VERSION_STR: + Iterator += AsciiStrnLenS ((CHAR8 *) Iterator, DependenciesSize - (Iterator - Dependencies->Dependencies)); + if (Iterator == (UINT8 *) Dependencies->Dependencies + DependenciesSize) { + DEBUG ((DEBUG_ERROR, "EvaluateDependency: STRING extends beyond end of dependency expression!\n")); + } + break; + case EFI_FMP_DEP_AND: + Status = Pop (&Element1, BooleanType); + if (EFI_ERROR (Status)) { + goto Error; + } + Status = Pop (&Element2, BooleanType); + if (EFI_ERROR (Status)) { + goto Error; + } + Status = Push (Element1.Value.Boolean & Element2.Value.Boolean, BooleanType); + if (EFI_ERROR (Status)) { + goto Error; + } + break; + case EFI_FMP_DEP_OR: + Status = Pop (&Element1, BooleanType); + if (EFI_ERROR (Status)) { + goto Error; + } + Status = Pop(&Element2, BooleanType); + if (EFI_ERROR (Status)) { + goto Error; + } + Status = Push (Element1.Value.Boolean | Element2.Value.Boolean, BooleanType); + if (EFI_ERROR (Status)) { + goto Error; + } + break; + case EFI_FMP_DEP_NOT: + Status = Pop (&Element1, BooleanType); + if (EFI_ERROR (Status)) { + goto Error; + } + Status = Push (!(Element1.Value.Boolean), BooleanType); + if (EFI_ERROR (Status)) { + goto Error; + } + break; + case EFI_FMP_DEP_TRUE: + Status = Push (TRUE, BooleanType); + if (EFI_ERROR (Status)) { + goto Error; + } + break; + case EFI_FMP_DEP_FALSE: + Status = Push (FALSE, BooleanType); + if (EFI_ERROR (Status)) { + goto Error; + } + break; + case EFI_FMP_DEP_EQ: + Status = Pop (&Element1, VersionType); + if (EFI_ERROR (Status)) { + goto Error; + } + Status = Pop (&Element2, VersionType); + if (EFI_ERROR (Status)) { + goto Error; + } + Status = (Element1.Value.Version == Element2.Value.Version) ? Push (TRUE, BooleanType) : Push (FALSE, BooleanType); + if (EFI_ERROR (Status)) { + goto Error; + } + break; + case EFI_FMP_DEP_GT: + Status = Pop (&Element1, VersionType); + if (EFI_ERROR (Status)) { + goto Error; + } + Status = Pop (&Element2, VersionType); + if (EFI_ERROR (Status)) { + goto Error; + } + Status = (Element1.Value.Version > Element2.Value.Version) ? Push (TRUE, BooleanType) : Push (FALSE, BooleanType); + if (EFI_ERROR (Status)) { + goto Error; + } + break; + case EFI_FMP_DEP_GTE: + Status = Pop (&Element1, VersionType); + if (EFI_ERROR (Status)) { + goto Error; + } + Status = Pop (&Element2, VersionType); + if (EFI_ERROR (Status)) { + goto Error; + } + Status = (Element1.Value.Version >= Element2.Value.Version) ? Push (TRUE, BooleanType) : Push (FALSE, BooleanType); + if (EFI_ERROR (Status)) { + goto Error; + } + break; + case EFI_FMP_DEP_LT: + Status = Pop (&Element1, VersionType); + if (EFI_ERROR (Status)) { + goto Error; + } + Status = Pop (&Element2, VersionType); + if (EFI_ERROR (Status)) { + goto Error; + } + Status = (Element1.Value.Version < Element2.Value.Version) ? Push (TRUE, BooleanType) : Push (FALSE, BooleanType); + if (EFI_ERROR (Status)) { + goto Error; + } + break; + case EFI_FMP_DEP_LTE: + Status = Pop (&Element1, VersionType); + if (EFI_ERROR (Status)) { + goto Error; + } + Status = Pop (&Element2, VersionType); + if (EFI_ERROR (Status)) { + goto Error; + } + Status = (Element1.Value.Version <= Element2.Value.Version) ? Push (TRUE, BooleanType) : Push (FALSE, BooleanType); + if (EFI_ERROR (Status)) { + goto Error; + } + break; + case EFI_FMP_DEP_END: + Status = Pop (&Element1, BooleanType); + if (EFI_ERROR (Status)) { + goto Error; + } + return Element1.Value.Boolean; + default: + DEBUG ((DEBUG_ERROR, "EvaluateDependency: Unknown Opcode - %02x!\n", *Iterator)); + goto Error; + } + Iterator++; + } + + DEBUG ((DEBUG_ERROR, "EvaluateDependency: No EFI_FMP_DEP_END Opcode in exression!\n")); + +Error: + return FALSE; +} + +/** + Validate the dependency expression and output its size. + + @param[in] Dependencies Pointer to the EFI_FIRMWARE_IMAGE_DEP. + @param[in] MaxDepexSize Max size of the dependency. + @param[out] DepexSize Size of dependency. + + @retval TRUE The capsule is valid. + @retval FALSE The capsule is invalid. + +**/ +BOOLEAN +EFIAPI +ValidateDependency ( + IN EFI_FIRMWARE_IMAGE_DEP *Dependencies, + IN CONST UINTN MaxDepexSize, + OUT UINT32 *DepexSize + ) +{ + UINT8 *Depex; + + if (DepexSize != NULL) { + *DepexSize = 0; + } + + if (Dependencies == NULL) { + return FALSE; + } + + Depex = Dependencies->Dependencies; + while (Depex < Dependencies->Dependencies + MaxDepexSize) { + switch (*Depex) + { + case EFI_FMP_DEP_PUSH_GUID: + Depex += sizeof (EFI_GUID) + 1; + break; + case EFI_FMP_DEP_PUSH_VERSION: + Depex += sizeof (UINT32) + 1; + break; + case EFI_FMP_DEP_VERSION_STR: + Depex += AsciiStrnLenS ((CHAR8 *) Depex, Dependencies->Dependencies + MaxDepexSize - Depex) + 1; + break; + case EFI_FMP_DEP_AND: + case EFI_FMP_DEP_OR: + case EFI_FMP_DEP_NOT: + case EFI_FMP_DEP_TRUE: + case EFI_FMP_DEP_FALSE: + case EFI_FMP_DEP_EQ: + case EFI_FMP_DEP_GT: + case EFI_FMP_DEP_GTE: + case EFI_FMP_DEP_LT: + case EFI_FMP_DEP_LTE: + Depex += 1; + break; + case EFI_FMP_DEP_END: + Depex += 1; + if (DepexSize != NULL) { + *DepexSize = (UINT32)(Depex - Dependencies->Dependencies); + } + return TRUE; + default: + return FALSE; + } + } + + return FALSE; +} + +/** + Get dependency from firmware image. + + @param[in] Image Points to the firmware image. + @param[in] ImageSize Size, in bytes, of the firmware image. + @param[out] DepexSize Size, in bytes, of the dependency. + + @retval The pointer to dependency. + @retval Null + +**/ +EFI_FIRMWARE_IMAGE_DEP* +EFIAPI +GetImageDependency ( + IN EFI_FIRMWARE_IMAGE_AUTHENTICATION *Image, + IN UINTN ImageSize, + OUT UINT32 *DepexSize + ) +{ + EFI_FIRMWARE_IMAGE_DEP *Depex; + UINTN MaxDepexSize; + + if (Image == NULL) { + return NULL; + } + + // + // Check to make sure that operation can be safely performed. + // + if (((UINTN)Image + sizeof (Image->MonotonicCount) + Image->AuthInfo.Hdr.dwLength) < (UINTN)Image || \ + ((UINTN)Image + sizeof (Image->MonotonicCount) + Image->AuthInfo.Hdr.dwLength) >= (UINTN)Image + ImageSize) { + // + // Pointer overflow. Invalid image. + // + return NULL; + } + + Depex = (EFI_FIRMWARE_IMAGE_DEP*)((UINT8 *)Image + sizeof (Image->MonotonicCount) + Image->AuthInfo.Hdr.dwLength); + MaxDepexSize = ImageSize - (sizeof (Image->MonotonicCount) + Image->AuthInfo.Hdr.dwLength); + + // + // Validate the dependency and get the size of dependency + // + if (ValidateDependency (Depex, MaxDepexSize, DepexSize)) { + return Depex; + } + + return NULL; +} + diff --git a/FmpDevicePkg/Library/FmpDependencyLib/FmpDependencyLib.inf b/FmpDevicePkg/Library/FmpDependencyLib/FmpDependencyLib.inf new file mode 100644 index 0000000000..b7e5c8d002 --- /dev/null +++ b/FmpDevicePkg/Library/FmpDependencyLib/FmpDependencyLib.inf @@ -0,0 +1,34 @@ +## @file +# Provides Fmp Capsule Dependency Expression support. +# +# Copyright (c) 2020, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = FmpDependencyLib + MODULE_UNI_FILE = FmpDependencyLib.uni + FILE_GUID = 67F55EA4-B4CF-4A08-931B-0BBCF1E0F7A3 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = FmpDependencyLib + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 ARM AARCH64 +# + +[Sources] + FmpDependencyLib.c + +[Packages] + MdePkg/MdePkg.dec + FmpDevicePkg/FmpDevicePkg.dec + +[LibraryClasses] + BaseLib + DebugLib + BaseMemoryLib diff --git a/FmpDevicePkg/Library/FmpDependencyLib/FmpDependencyLib.uni b/FmpDevicePkg/Library/FmpDependencyLib/FmpDependencyLib.uni new file mode 100644 index 0000000000..422a96b570 --- /dev/null +++ b/FmpDevicePkg/Library/FmpDependencyLib/FmpDependencyLib.uni @@ -0,0 +1,12 @@ +// /** @file +// Provides Fmp Capsule Dependency Expression support. +// +// Copyright (c) 2020, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + +#string STR_MODULE_ABSTRACT #language en-US "FMP Dependency Lib" + +#string STR_MODULE_DESCRIPTION #language en-US "Provides Fmp Capsule Dependency Expression support." -- 2.16.2.windows.1