* [edk2-devel] [PATCH V3 0/5] FmpDevicePkg: Move capsule dependency implement to library
@ 2020-05-14 21:52 Xu, Wei6
2020-05-14 21:52 ` [edk2-devel] [PATCH V3 1/5] FmpDevicePkg: Add FmpDependency library class and BASE instance Xu, Wei6
` (4 more replies)
0 siblings, 5 replies; 7+ messages in thread
From: Xu, Wei6 @ 2020-05-14 21:52 UTC (permalink / raw)
To: devel; +Cc: Michael D Kinney, Liming Gao, Sean Brogan
v3:
- Refine description and comments of API: EvaluateDependency(),
GetFmpDependency(), CheckFmpDependency().
- Remove the check on the dependencies coming from other FMP instances.
v2:
- Remove API GetDependencySize in FmpDependencyLib.
- Correct comments in FmpDependencyLib unit test; Correct the error status
when CreateUnitTestSuite fails.
- Update comments for null instance of FmpDependencyCheckLib; Remove
SaveFmpDependency and GetFmpDependency from FmpDependencyCheckLib
- Add new FmpDependencyDevice library class to provide firmware device
specific SaveFmpDependency and GetFmpDependency services.
- Update FmpDxe to use new FmpDependencyDeviceLib
v1:
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=2696
This patch series move the implementation of Fmp Capsule Dependency from
FmpDxe driver into two library classes. FmpDependencyLib is a base lib
to provide generic dependency evaluation services. FmpDependencyCheckLib
is a platform lib to provide dependency check services during firmware
update. Platform can perform the dependency check in platform specific
manner by implementing its own FmpDependencyCheckLib.
This patch series also add unit test for EvaluateDependency API in
FmpDependencyLib.
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Sean Brogan <sean.brogan@microsoft.com>
Signed-off-by: Wei6 Xu <wei6.xu@intel.com>
Wei6 Xu (5):
FmpDevicePkg: Add FmpDependency library class and BASE instance
FmpDevicePkg/Test: Add FmpDependencyLib unit test
FmpDevicePkg: Add FmpDependencyCheck library class and instances
FmpDevicePkg: Add FmpDependencyDevice library class and NULL instance
FmpDevicePkg/FmpDxe: Use new Fmp dependency libraries
FmpDevicePkg/FmpDevicePkg.ci.yaml | 10 +
FmpDevicePkg/FmpDevicePkg.dec | 15 +-
FmpDevicePkg/FmpDevicePkg.dsc | 16 +-
FmpDevicePkg/FmpDxe/Dependency.h | 63 ----
FmpDevicePkg/FmpDxe/FmpDxe.c | 256 ++++------------
FmpDevicePkg/FmpDxe/FmpDxe.h | 4 +
FmpDevicePkg/FmpDxe/FmpDxe.inf | 5 +-
FmpDevicePkg/FmpDxe/FmpDxeLib.inf | 5 +-
.../Include/Library/FmpDependencyCheckLib.h | 38 +++
.../Include/Library/FmpDependencyDeviceLib.h | 51 ++++
FmpDevicePkg/Include/Library/FmpDependencyLib.h | 89 ++++++
.../FmpDependencyCheckLib/FmpDependencyCheckLib.c | 196 ++++++++++++
.../FmpDependencyCheckLib.inf | 43 +++
.../FmpDependencyCheckLib.uni | 13 +
.../FmpDependencyCheckLibNull.c | 34 +++
.../FmpDependencyCheckLibNull.inf | 30 ++
.../FmpDependencyCheckLibNull.uni | 13 +
.../FmpDependencyDeviceLib.c | 50 +++
.../FmpDependencyDeviceLibNull.inf | 29 ++
.../FmpDependencyDeviceLibNull.uni | 12 +
.../FmpDependencyLib/FmpDependencyLib.c} | 337 +++++++--------------
.../Library/FmpDependencyLib/FmpDependencyLib.inf | 34 +++
.../Library/FmpDependencyLib/FmpDependencyLib.uni | 12 +
FmpDevicePkg/Test/FmpDeviceHostPkgTest.dsc | 28 ++
.../FmpDependencyLib/EvaluateDependencyUnitTest.c | 270 +++++++++++++++++
.../FmpDependencyLibUnitTestsHost.inf | 34 +++
.../FmpDependencyLibUnitTestsUefi.inf | 35 +++
27 files changed, 1216 insertions(+), 506 deletions(-)
delete mode 100644 FmpDevicePkg/FmpDxe/Dependency.h
create mode 100644 FmpDevicePkg/Include/Library/FmpDependencyCheckLib.h
create mode 100644 FmpDevicePkg/Include/Library/FmpDependencyDeviceLib.h
create mode 100644 FmpDevicePkg/Include/Library/FmpDependencyLib.h
create mode 100644 FmpDevicePkg/Library/FmpDependencyCheckLib/FmpDependencyCheckLib.c
create mode 100644 FmpDevicePkg/Library/FmpDependencyCheckLib/FmpDependencyCheckLib.inf
create mode 100644 FmpDevicePkg/Library/FmpDependencyCheckLib/FmpDependencyCheckLib.uni
create mode 100644 FmpDevicePkg/Library/FmpDependencyCheckLibNull/FmpDependencyCheckLibNull.c
create mode 100644 FmpDevicePkg/Library/FmpDependencyCheckLibNull/FmpDependencyCheckLibNull.inf
create mode 100644 FmpDevicePkg/Library/FmpDependencyCheckLibNull/FmpDependencyCheckLibNull.uni
create mode 100644 FmpDevicePkg/Library/FmpDependencyDeviceLibNull/FmpDependencyDeviceLib.c
create mode 100644 FmpDevicePkg/Library/FmpDependencyDeviceLibNull/FmpDependencyDeviceLibNull.inf
create mode 100644 FmpDevicePkg/Library/FmpDependencyDeviceLibNull/FmpDependencyDeviceLibNull.uni
rename FmpDevicePkg/{FmpDxe/Dependency.c => Library/FmpDependencyLib/FmpDependencyLib.c} (53%)
create mode 100644 FmpDevicePkg/Library/FmpDependencyLib/FmpDependencyLib.inf
create mode 100644 FmpDevicePkg/Library/FmpDependencyLib/FmpDependencyLib.uni
create mode 100644 FmpDevicePkg/Test/FmpDeviceHostPkgTest.dsc
create mode 100644 FmpDevicePkg/Test/UnitTest/Library/FmpDependencyLib/EvaluateDependencyUnitTest.c
create mode 100644 FmpDevicePkg/Test/UnitTest/Library/FmpDependencyLib/FmpDependencyLibUnitTestsHost.inf
create mode 100644 FmpDevicePkg/Test/UnitTest/Library/FmpDependencyLib/FmpDependencyLibUnitTestsUefi.inf
--
2.16.2.windows.1
^ permalink raw reply [flat|nested] 7+ messages in thread
* [edk2-devel] [PATCH V3 1/5] FmpDevicePkg: Add FmpDependency library class and BASE instance
2020-05-14 21:52 [edk2-devel] [PATCH V3 0/5] FmpDevicePkg: Move capsule dependency implement to library Xu, Wei6
@ 2020-05-14 21:52 ` Xu, Wei6
2020-05-15 0:59 ` Sean
2020-05-14 21:52 ` [edk2-devel] [PATCH V3 2/5] FmpDevicePkg/Test: Add FmpDependencyLib unit test Xu, Wei6
` (3 subsequent siblings)
4 siblings, 1 reply; 7+ messages in thread
From: Xu, Wei6 @ 2020-05-14 21:52 UTC (permalink / raw)
To: devel; +Cc: Michael D Kinney, Liming Gao, Sean Brogan
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 <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Sean Brogan <sean.brogan@microsoft.com>
Signed-off-by: Wei6 Xu <wei6.xu@intel.com>
---
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.<BR>
-# Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2018 - 2020, Intel Corporation. All rights reserved.<BR>
#
# 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.<BR>
-# Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2018 - 2020, Intel Corporation. All rights reserved.<BR>
# Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
#
# 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.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __FMP_DEPENDENCY_LIB__
+#define __FMP_DEPENDENCY_LIB__
+
+#include <PiDxe.h>
+#include <Protocol/FirmwareManagement.h>
+
+//
+// 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.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include <PiDxe.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/FmpDependencyLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+//
+// 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.<BR>
+#
+# 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.<BR>
+//
+// 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
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [edk2-devel] [PATCH V3 2/5] FmpDevicePkg/Test: Add FmpDependencyLib unit test
2020-05-14 21:52 [edk2-devel] [PATCH V3 0/5] FmpDevicePkg: Move capsule dependency implement to library Xu, Wei6
2020-05-14 21:52 ` [edk2-devel] [PATCH V3 1/5] FmpDevicePkg: Add FmpDependency library class and BASE instance Xu, Wei6
@ 2020-05-14 21:52 ` Xu, Wei6
2020-05-14 21:52 ` [edk2-devel] [PATCH V3 3/5] FmpDevicePkg: Add FmpDependencyCheck library class and instances Xu, Wei6
` (2 subsequent siblings)
4 siblings, 0 replies; 7+ messages in thread
From: Xu, Wei6 @ 2020-05-14 21:52 UTC (permalink / raw)
To: devel; +Cc: Michael D Kinney, Liming Gao, Sean Brogan
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=2696
* Add unit tests for EvaluateDependency API in FmpDependencyLib.
* Add Test/FmpDeviceHostPkgTest.dsc to build host based unit test.
* Update FmpDevicePkg.dsc to build target based unit test.
* Update FmpDevicePkg.ci.yaml to build and run host based test.
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Sean Brogan <sean.brogan@microsoft.com>
Signed-off-by: Wei6 Xu <wei6.xu@intel.com>
---
FmpDevicePkg/FmpDevicePkg.ci.yaml | 10 +
FmpDevicePkg/FmpDevicePkg.dsc | 7 +
FmpDevicePkg/Test/FmpDeviceHostPkgTest.dsc | 28 +++
.../FmpDependencyLib/EvaluateDependencyUnitTest.c | 270 +++++++++++++++++++++
.../FmpDependencyLibUnitTestsHost.inf | 34 +++
.../FmpDependencyLibUnitTestsUefi.inf | 35 +++
6 files changed, 384 insertions(+)
create mode 100644 FmpDevicePkg/Test/FmpDeviceHostPkgTest.dsc
create mode 100644 FmpDevicePkg/Test/UnitTest/Library/FmpDependencyLib/EvaluateDependencyUnitTest.c
create mode 100644 FmpDevicePkg/Test/UnitTest/Library/FmpDependencyLib/FmpDependencyLibUnitTestsHost.inf
create mode 100644 FmpDevicePkg/Test/UnitTest/Library/FmpDependencyLib/FmpDependencyLibUnitTestsUefi.inf
diff --git a/FmpDevicePkg/FmpDevicePkg.ci.yaml b/FmpDevicePkg/FmpDevicePkg.ci.yaml
index c17b355d42..74a0aefe8e 100644
--- a/FmpDevicePkg/FmpDevicePkg.ci.yaml
+++ b/FmpDevicePkg/FmpDevicePkg.ci.yaml
@@ -6,26 +6,36 @@
##
{
"CompilerPlugin": {
"DscPath": "FmpDevicePkg.dsc"
},
+ "HostUnitTestCompilerPlugin": {
+ "DscPath": "Test/FmpDeviceHostPkgTest.dsc"
+ },
"CharEncodingCheck": {
"IgnoreFiles": []
},
"DependencyCheck": {
"AcceptableDependencies": [
"MdePkg/MdePkg.dec",
"MdeModulePkg/MdeModulePkg.dec",
"FmpDevicePkg/FmpDevicePkg.dec",
"CryptoPkg/CryptoPkg.dec"
],
+ "AcceptableDependencies-HOST_APPLICATION":[
+ "UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec"
+ ],
"IgnoreInf": []
},
"DscCompleteCheck": {
"DscPath": "FmpDevicePkg.dsc",
"IgnoreInf": []
},
+ "HostUnitTestDscCompleteCheck": {
+ "IgnoreInf": [],
+ "DscPath": "Test/FmpDeviceHostPkgTest.dsc"
+ },
"GuidCheck": {
"IgnoreGuidName": [],
"IgnoreGuidValue": [],
"IgnoreFoldersAndFiles": []
},
diff --git a/FmpDevicePkg/FmpDevicePkg.dsc b/FmpDevicePkg/FmpDevicePkg.dsc
index dfb3c1a141..49c6ff3a30 100644
--- a/FmpDevicePkg/FmpDevicePkg.dsc
+++ b/FmpDevicePkg/FmpDevicePkg.dsc
@@ -34,10 +34,12 @@
# TRUE - Build FmpDxe module for with storage access enabled
# FALSE - Build FmpDxe module for with storage access disabled
#
DEFINE DEVICE_FMP_STORAGE_ACCESS_ENABLE = TRUE
+!include UnitTestFrameworkPkg/UnitTestFrameworkPkgTarget.dsc.inc
+
[LibraryClasses]
UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf
UefiLib|MdePkg/Library/UefiLib/UefiLib.inf
UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf
@@ -161,7 +163,12 @@
# in a system firmware image.
#
CapsuleUpdatePolicyLib|FmpDevicePkg/Library/CapsuleUpdatePolicyLibNull/CapsuleUpdatePolicyLibNull.inf
}
+ #
+ # Add UEFI Target Based Unit Tests
+ #
+ FmpDevicePkg/Test/UnitTest/Library/FmpDependencyLib/FmpDependencyLibUnitTestsUefi.inf
+
[BuildOptions]
*_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES
diff --git a/FmpDevicePkg/Test/FmpDeviceHostPkgTest.dsc b/FmpDevicePkg/Test/FmpDeviceHostPkgTest.dsc
new file mode 100644
index 0000000000..83574399be
--- /dev/null
+++ b/FmpDevicePkg/Test/FmpDeviceHostPkgTest.dsc
@@ -0,0 +1,28 @@
+## @file
+# FmpDevicePkg DSC file used to build host-based unit tests.
+#
+# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ PLATFORM_NAME = FmpDevicePkgHostTest
+ PLATFORM_GUID = 80B12646-9A30-4516-AABF-DE1919B573E3
+ PLATFORM_VERSION = 0.1
+ DSC_SPECIFICATION = 0x00010005
+ OUTPUT_DIRECTORY = Build/FmpDevicePkg/HostTest
+ SUPPORTED_ARCHITECTURES = IA32|X64
+ BUILD_TARGETS = NOOPT
+ SKUID_IDENTIFIER = DEFAULT
+
+!include UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc
+
+[LibraryClasses]
+ FmpDependencyLib|FmpDevicePkg/Library/FmpDependencyLib/FmpDependencyLib.inf
+
+[Components]
+ #
+ # Build HOST_APPLICATION that tests the FmpDependencyLib
+ #
+ FmpDevicePkg/Test/UnitTest/Library/FmpDependencyLib/FmpDependencyLibUnitTestsHost.inf
diff --git a/FmpDevicePkg/Test/UnitTest/Library/FmpDependencyLib/EvaluateDependencyUnitTest.c b/FmpDevicePkg/Test/UnitTest/Library/FmpDependencyLib/EvaluateDependencyUnitTest.c
new file mode 100644
index 0000000000..f8ccdd906f
--- /dev/null
+++ b/FmpDevicePkg/Test/UnitTest/Library/FmpDependencyLib/EvaluateDependencyUnitTest.c
@@ -0,0 +1,270 @@
+/** @file
+ Unit tests of EvaluateDependency API in FmpDependencyLib.
+
+ Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/FmpDependencyLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UnitTestLib.h>
+
+#define UNIT_TEST_APP_NAME "FmpDependencyLib Unit Test Application"
+#define UNIT_TEST_APP_VERSION "1.0"
+
+typedef struct {
+ UINT8 *Dependencies;
+ UINTN DependenciesSize;
+ BOOLEAN ExpectedResult;
+} BASIC_TEST_CONTEXT;
+
+//
+// Image Type ID of FMP device A
+//
+#define IMAGE_TYPE_ID_1 { 0x97144DFA, 0xEB8E, 0xD14D, {0x8B, 0x4D, 0x39, 0x88, 0x24, 0x96, 0x56, 0x42}}
+
+//
+// Image Type ID of FMP device B
+//
+#define IMAGE_TYPE_ID_2 { 0xA42A7370, 0x433A, 0x684D, {0x9A, 0xA1, 0xDE, 0x62, 0x23, 0x30, 0x6C, 0xF3}}
+
+//
+// Device A's version is 0x00000002
+// Device B's version is 0x00000003
+//
+static FMP_DEPEX_CHECK_VERSION_DATA mFmpVersions[] = {
+ {IMAGE_TYPE_ID_1, 0x00000002},
+ {IMAGE_TYPE_ID_2, 0x00000003}
+};
+
+// Valid Dependency Expression 1: (Version(A) > 0x00000001) && (Version(B) >= 0x00000003)
+static UINT8 mExpression1[] = {
+ EFI_FMP_DEP_PUSH_VERSION, 0x01, 0x00, 0x00, 0x00,
+ EFI_FMP_DEP_PUSH_GUID, 0xFA, 0x4D, 0x14, 0x97, 0x8E, 0xEB, 0x4D, 0xD1, 0x8B, 0x4D, 0x39, 0x88, 0x24, 0x96, 0x56, 0x42,
+ EFI_FMP_DEP_GT,
+ EFI_FMP_DEP_PUSH_VERSION, 0x03, 0x00, 0x00, 0x00,
+ EFI_FMP_DEP_PUSH_GUID, 0x70, 0x73, 0x2A, 0xA4, 0x3A, 0x43, 0x4D, 0x68, 0x9A, 0xA1, 0xDE, 0x62, 0x23, 0x30, 0x6C, 0xF3,
+ EFI_FMP_DEP_GTE,
+ EFI_FMP_DEP_AND,
+ EFI_FMP_DEP_END
+};
+
+// Valid Dependency Expression 2: (Version(A) < 0x00000002) || (Version(B) <= 0x00000003)
+static UINT8 mExpression2[] = {
+ EFI_FMP_DEP_PUSH_VERSION, 0x02, 0x00, 0x00, 0x00,
+ EFI_FMP_DEP_PUSH_GUID, 0xFA, 0x4D, 0x14, 0x97, 0x8E, 0xEB, 0x4D, 0xD1, 0x8B, 0x4D, 0x39, 0x88, 0x24, 0x96, 0x56, 0x42,
+ EFI_FMP_DEP_LT,
+ EFI_FMP_DEP_PUSH_VERSION, 0x03, 0x00, 0x00, 0x00,
+ EFI_FMP_DEP_PUSH_GUID, 0x70, 0x73, 0x2A, 0xA4, 0x3A, 0x43, 0x4D, 0x68, 0x9A, 0xA1, 0xDE, 0x62, 0x23, 0x30, 0x6C, 0xF3,
+ EFI_FMP_DEP_LTE,
+ EFI_FMP_DEP_OR,
+ EFI_FMP_DEP_END
+};
+
+// Valid Dependency Expression 3: !(Version(A) == 0x0000002)
+static UINT8 mExpression3[] = {
+ EFI_FMP_DEP_PUSH_VERSION, 0x02, 0x00, 0x00, 0x00,
+ EFI_FMP_DEP_PUSH_GUID, 0xFA, 0x4D, 0x14, 0x97, 0x8E, 0xEB, 0x4D, 0xD1, 0x8B, 0x4D, 0x39, 0x88, 0x24, 0x96, 0x56, 0x42,
+ EFI_FMP_DEP_EQ,
+ EFI_FMP_DEP_NOT,
+ EFI_FMP_DEP_END
+};
+
+// Valid Dependency Expression 4: "Test" TRUE && FALSE
+static UINT8 mExpression4[] = {
+ EFI_FMP_DEP_VERSION_STR, 'T', 'e', 's', 't', '\0',
+ EFI_FMP_DEP_TRUE,
+ EFI_FMP_DEP_FALSE,
+ EFI_FMP_DEP_AND,
+ EFI_FMP_DEP_END
+};
+
+// Invalid Dependency Expression 1: Invalid Op-code
+static UINT8 mExpression5[] = {EFI_FMP_DEP_TRUE, 0xAA, EFI_FMP_DEP_END};
+
+// Invalid Dependency Expression 2: String doesn't end with '\0'
+static UINT8 mExpression6[] = {EFI_FMP_DEP_VERSION_STR, 'T', 'e', 's', 't', EFI_FMP_DEP_TRUE, EFI_FMP_DEP_END};
+
+// Invalid Dependency Expression 3: GUID is in invalid size
+static UINT8 mExpression7[] = {
+ EFI_FMP_DEP_PUSH_VERSION, 0x02, 0x00, 0x00, 0x00,
+ EFI_FMP_DEP_PUSH_GUID, 0xAA, 0xBB, 0xCC, 0xDD,
+ EFI_FMP_DEP_GTE,
+ EFI_FMP_DEP_END
+};
+
+// Invalid Dependency Expression 4: Version is in invalid size
+static UINT8 mExpression8[] = {
+ EFI_FMP_DEP_PUSH_VERSION, 0x02, 0x00,
+ EFI_FMP_DEP_PUSH_GUID, 0xDA, 0xCB, 0x25, 0xAC, 0x9E, 0xCD, 0x5E, 0xE2, 0x9C, 0x5E, 0x4A, 0x99, 0x35, 0xA7, 0x67, 0x53,
+ EFI_FMP_DEP_GTE,
+ EFI_FMP_DEP_END
+};
+
+// Invalid Dependency Expression 5: Operand and operator mismatch
+static UINT8 mExpression9[] = {EFI_FMP_DEP_TRUE, EFI_FMP_DEP_FALSE, EFI_FMP_DEP_GTE, EFI_FMP_DEP_END};
+
+// Invalid Dependency Expression 6: GUID is NOT FOUND
+static UINT8 mExpression10[] = {
+ EFI_FMP_DEP_PUSH_VERSION, 0x02, 0x00, 0x00, 0x00,
+ EFI_FMP_DEP_PUSH_GUID, 0xDA, 0xCB, 0x25, 0xAC, 0x9E, 0xCD, 0x5E, 0xE2, 0x9C, 0x5E, 0x4A, 0x99, 0x35, 0xA7, 0x67, 0x53,
+ EFI_FMP_DEP_GT,
+ EFI_FMP_DEP_END
+};
+
+// Invalid Dependency Expression 7: Stack underflow
+static UINT8 mExpression11[] = {
+ EFI_FMP_DEP_PUSH_VERSION, 0x02, 0x00, 0x00, 0x00,
+ EFI_FMP_DEP_GT,
+ EFI_FMP_DEP_END
+};
+
+// ------------------------------------------------Test Depex------Depex Size----------------Expected Result
+static BASIC_TEST_CONTEXT mBasicTestTrue1 = {mExpression1, sizeof(mExpression1), TRUE};
+static BASIC_TEST_CONTEXT mBasicTestTrue2 = {mExpression2, sizeof(mExpression2), TRUE};
+static BASIC_TEST_CONTEXT mBasicTestFalse1 = {mExpression3, sizeof(mExpression3), FALSE};
+static BASIC_TEST_CONTEXT mBasicTestFalse2 = {mExpression4, sizeof(mExpression4), FALSE};
+static BASIC_TEST_CONTEXT mBasicTestInvalid1 = {mExpression1, sizeof(mExpression1) - 1, FALSE};
+static BASIC_TEST_CONTEXT mBasicTestInvalid2 = {mExpression5, sizeof(mExpression5), FALSE};
+static BASIC_TEST_CONTEXT mBasicTestInvalid3 = {mExpression6, sizeof(mExpression6), FALSE};
+static BASIC_TEST_CONTEXT mBasicTestInvalid4 = {mExpression7, sizeof(mExpression7), FALSE};
+static BASIC_TEST_CONTEXT mBasicTestInvalid5 = {mExpression8, sizeof(mExpression8), FALSE};
+static BASIC_TEST_CONTEXT mBasicTestInvalid6 = {mExpression9, sizeof(mExpression9), FALSE};
+static BASIC_TEST_CONTEXT mBasicTestInvalid7 = {mExpression10, sizeof(mExpression10), FALSE};
+static BASIC_TEST_CONTEXT mBasicTestInvalid8 = {mExpression11, sizeof(mExpression11), FALSE};
+
+/**
+ Unit test for EvaluateDependency() API of the FmpDependencyLib.
+
+ @param[in] Context [Optional] An optional parameter that enables:
+ 1) test-case reuse with varied parameters and
+ 2) test-case re-entry for Target tests that need a
+ reboot. This parameter is a VOID* and it is the
+ responsibility of the test author to ensure that the
+ contents are well understood by all test cases that may
+ consume it.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+STATIC
+UNIT_TEST_STATUS
+EFIAPI
+EvaluateDependencyTest (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ BASIC_TEST_CONTEXT *TestContext;
+ BOOLEAN EvaluationResult;
+
+ TestContext = (BASIC_TEST_CONTEXT *)Context;
+
+ EvaluationResult = EvaluateDependency (
+ (EFI_FIRMWARE_IMAGE_DEP *)TestContext->Dependencies,
+ TestContext->DependenciesSize,
+ mFmpVersions,
+ sizeof(mFmpVersions)/sizeof(FMP_DEPEX_CHECK_VERSION_DATA)
+ );
+
+ UT_ASSERT_EQUAL (EvaluationResult, TestContext->ExpectedResult);
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Initialize the unit test framework, suite, and unit tests for the
+ EvaluateDependency API in FmpDependencyLib and run the unit tests.
+
+ @retval EFI_SUCCESS All test cases were dispatched.
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available to
+ initialize the unit tests.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+UnitTestingEntry (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UNIT_TEST_FRAMEWORK_HANDLE Fw;
+ UNIT_TEST_SUITE_HANDLE DepexEvalTests;
+
+ Fw = NULL;
+
+ DEBUG ((DEBUG_INFO, "%a v%a\n", UNIT_TEST_APP_NAME, UNIT_TEST_APP_VERSION));
+
+ //
+ // Start setting up the test framework for running the tests.
+ //
+ Status = InitUnitTestFramework (&Fw, UNIT_TEST_APP_NAME, gEfiCallerBaseName, UNIT_TEST_APP_VERSION);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed in InitUnitTestFramework. Status = %r\n", Status));
+ goto EXIT;
+ }
+
+ //
+ // Populate the Unit Test Suite.
+ //
+ Status = CreateUnitTestSuite (&DepexEvalTests, Fw, "Evaluate Dependency Test", "FmpDependencyLib.EvaluateDependency", NULL, NULL);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for DepexEvalTests\n"));
+ goto EXIT;
+ }
+
+ AddTestCase (DepexEvalTests, "Evaluate to True - 1", "Test1", EvaluateDependencyTest, NULL, NULL, &mBasicTestTrue1);
+ AddTestCase (DepexEvalTests, "Evaluate to True - 2", "Test2", EvaluateDependencyTest, NULL, NULL, &mBasicTestTrue2);
+ AddTestCase (DepexEvalTests, "Evaluate to False - 1", "Test3", EvaluateDependencyTest, NULL, NULL, &mBasicTestFalse1);
+ AddTestCase (DepexEvalTests, "Evaluate to False - 2", "Test4", EvaluateDependencyTest, NULL, NULL, &mBasicTestFalse2);
+ AddTestCase (DepexEvalTests, "Error: Non-END-terminated expression", "Test5", EvaluateDependencyTest, NULL, NULL, &mBasicTestInvalid1);
+ AddTestCase (DepexEvalTests, "Error: UNKNOWN Op-Code", "Test6", EvaluateDependencyTest, NULL, NULL, &mBasicTestInvalid2);
+ AddTestCase (DepexEvalTests, "Error: Non-Null-terminated string", "Test7", EvaluateDependencyTest, NULL, NULL, &mBasicTestInvalid3);
+ AddTestCase (DepexEvalTests, "Error: GUID size is not 16", "Test8", EvaluateDependencyTest, NULL, NULL, &mBasicTestInvalid4);
+ AddTestCase (DepexEvalTests, "Error: Version size is not 4", "Test9", EvaluateDependencyTest, NULL, NULL, &mBasicTestInvalid5);
+ AddTestCase (DepexEvalTests, "Error: Operand and operator mismatch", "Test10", EvaluateDependencyTest, NULL, NULL, &mBasicTestInvalid6);
+ AddTestCase (DepexEvalTests, "Error: GUID is NOT FOUND", "Test11", EvaluateDependencyTest, NULL, NULL, &mBasicTestInvalid7);
+ AddTestCase (DepexEvalTests, "Error: Stack Underflow", "Test12", EvaluateDependencyTest, NULL, NULL, &mBasicTestInvalid8);
+
+ //
+ // Execute the tests.
+ //
+ Status = RunAllTestSuites (Fw);
+
+EXIT:
+ if (Fw) {
+ FreeUnitTestFramework (Fw);
+ }
+
+ return Status;
+}
+
+/**
+ Standard UEFI entry point for target based unit test execution from UEFI Shell.
+**/
+EFI_STATUS
+EFIAPI
+FmpDependencyLibUnitTestAppEntry (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ return UnitTestingEntry ();
+}
+
+/**
+ Standard POSIX C entry point for host based unit test execution.
+**/
+int
+main (
+ int argc,
+ char *argv[]
+ )
+{
+ return UnitTestingEntry ();
+}
diff --git a/FmpDevicePkg/Test/UnitTest/Library/FmpDependencyLib/FmpDependencyLibUnitTestsHost.inf b/FmpDevicePkg/Test/UnitTest/Library/FmpDependencyLib/FmpDependencyLibUnitTestsHost.inf
new file mode 100644
index 0000000000..93ae635da5
--- /dev/null
+++ b/FmpDevicePkg/Test/UnitTest/Library/FmpDependencyLib/FmpDependencyLibUnitTestsHost.inf
@@ -0,0 +1,34 @@
+## @file
+# Unit tests of EvaluateDependency API in FmpDependencyLib that are run from host
+# environment.
+#
+# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION = 0x00010006
+ BASE_NAME = FmpDependencyLibUnitTestsHost
+ FILE_GUID = CE32C647-CAD7-4099-9463-653B932C1691
+ MODULE_TYPE = HOST_APPLICATION
+ VERSION_STRING = 1.0
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ EvaluateDependencyUnitTest.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ FmpDevicePkg/FmpDevicePkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ UnitTestLib
+ FmpDependencyLib
diff --git a/FmpDevicePkg/Test/UnitTest/Library/FmpDependencyLib/FmpDependencyLibUnitTestsUefi.inf b/FmpDevicePkg/Test/UnitTest/Library/FmpDependencyLib/FmpDependencyLibUnitTestsUefi.inf
new file mode 100644
index 0000000000..a2ca369171
--- /dev/null
+++ b/FmpDevicePkg/Test/UnitTest/Library/FmpDependencyLib/FmpDependencyLibUnitTestsUefi.inf
@@ -0,0 +1,35 @@
+## @file
+# Unit tests of EvaluateDependency API in FmpDependencyLib that are run from UEFI Shell.
+#
+# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION = 0x00010006
+ BASE_NAME = FmpDependencyLibUnitTestsUefi
+ FILE_GUID = 8FF4C129-C2EF-445D-8658-9A342A1FCC4D
+ MODULE_TYPE = UEFI_APPLICATION
+ VERSION_STRING = 1.0
+ ENTRY_POINT = FmpDependencyLibUnitTestAppEntry
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ EvaluateDependencyUnitTest.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ FmpDevicePkg/FmpDevicePkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ UefiApplicationEntryPoint
+ DebugLib
+ UnitTestLib
+ FmpDependencyLib
--
2.16.2.windows.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [edk2-devel] [PATCH V3 3/5] FmpDevicePkg: Add FmpDependencyCheck library class and instances
2020-05-14 21:52 [edk2-devel] [PATCH V3 0/5] FmpDevicePkg: Move capsule dependency implement to library Xu, Wei6
2020-05-14 21:52 ` [edk2-devel] [PATCH V3 1/5] FmpDevicePkg: Add FmpDependency library class and BASE instance Xu, Wei6
2020-05-14 21:52 ` [edk2-devel] [PATCH V3 2/5] FmpDevicePkg/Test: Add FmpDependencyLib unit test Xu, Wei6
@ 2020-05-14 21:52 ` Xu, Wei6
2020-05-14 21:52 ` [edk2-devel] [PATCH V3 4/5] FmpDevicePkg: Add FmpDependencyDevice library class and NULL instance Xu, Wei6
2020-05-14 21:52 ` [edk2-devel] [PATCH V3 5/5] FmpDevicePkg/FmpDxe: Use new Fmp dependency libraries Xu, Wei6
4 siblings, 0 replies; 7+ messages in thread
From: Xu, Wei6 @ 2020-05-14 21:52 UTC (permalink / raw)
To: devel; +Cc: Michael D Kinney, Liming Gao, Sean Brogan
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=2696
* This library class provides platform specific services to support
dependency check during updating firmware image. Platform can perform
dependency check in platform specific manner by implementing its own
FmpDependencyCheckLib.
* Add FmpDependencyCheck instance to provide a sample of dependency
check. The sample instance only checks the dependency from capsule
image. The dependency from other FMP instances isn't checked here.
* Add NULL instance as an option to skip the dependency check.
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Sean Brogan <sean.brogan@microsoft.com>
Signed-off-by: Wei6 Xu <wei6.xu@intel.com>
---
FmpDevicePkg/FmpDevicePkg.dec | 4 +
FmpDevicePkg/FmpDevicePkg.dsc | 3 +
.../Include/Library/FmpDependencyCheckLib.h | 38 ++++
.../FmpDependencyCheckLib/FmpDependencyCheckLib.c | 196 +++++++++++++++++++++
.../FmpDependencyCheckLib.inf | 43 +++++
.../FmpDependencyCheckLib.uni | 13 ++
.../FmpDependencyCheckLibNull.c | 34 ++++
.../FmpDependencyCheckLibNull.inf | 30 ++++
.../FmpDependencyCheckLibNull.uni | 13 ++
9 files changed, 374 insertions(+)
create mode 100644 FmpDevicePkg/Include/Library/FmpDependencyCheckLib.h
create mode 100644 FmpDevicePkg/Library/FmpDependencyCheckLib/FmpDependencyCheckLib.c
create mode 100644 FmpDevicePkg/Library/FmpDependencyCheckLib/FmpDependencyCheckLib.inf
create mode 100644 FmpDevicePkg/Library/FmpDependencyCheckLib/FmpDependencyCheckLib.uni
create mode 100644 FmpDevicePkg/Library/FmpDependencyCheckLibNull/FmpDependencyCheckLibNull.c
create mode 100644 FmpDevicePkg/Library/FmpDependencyCheckLibNull/FmpDependencyCheckLibNull.inf
create mode 100644 FmpDevicePkg/Library/FmpDependencyCheckLibNull/FmpDependencyCheckLibNull.uni
diff --git a/FmpDevicePkg/FmpDevicePkg.dec b/FmpDevicePkg/FmpDevicePkg.dec
index 4947008346..871d5ce890 100644
--- a/FmpDevicePkg/FmpDevicePkg.dec
+++ b/FmpDevicePkg/FmpDevicePkg.dec
@@ -37,10 +37,14 @@
## @libraryclass Provides generic services to support capsule dependency
# expression evaluation.
FmpDependencyLib|Include/Library/FmpDependencyLib.h
+ ## @libraryclass Provides platform specific services to support dependency
+ # check during update of firmware image.
+ FmpDependencyCheckLib|Include/Library/FmpDependencyCheckLib.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 49c6ff3a30..7e80806171 100644
--- a/FmpDevicePkg/FmpDevicePkg.dsc
+++ b/FmpDevicePkg/FmpDevicePkg.dsc
@@ -61,10 +61,11 @@
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
+ FmpDependencyCheckLib|FmpDevicePkg/Library/FmpDependencyCheckLibNull/FmpDependencyCheckLibNull.inf
TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf
[LibraryClasses.ARM, LibraryClasses.AARCH64]
#
# It is not possible to prevent the ARM compiler for generic intrinsic functions.
@@ -90,10 +91,12 @@
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/Library/FmpDependencyCheckLib/FmpDependencyCheckLib.inf
+ FmpDevicePkg/Library/FmpDependencyCheckLibNull/FmpDependencyCheckLibNull.inf
FmpDevicePkg/FmpDxe/FmpDxeLib.inf
#
# Modules
#
diff --git a/FmpDevicePkg/Include/Library/FmpDependencyCheckLib.h b/FmpDevicePkg/Include/Library/FmpDependencyCheckLib.h
new file mode 100644
index 0000000000..ec380c4947
--- /dev/null
+++ b/FmpDevicePkg/Include/Library/FmpDependencyCheckLib.h
@@ -0,0 +1,38 @@
+/** @file
+ Fmp Capsule Dependency check functions for Firmware Management Protocol based
+ firmware updates.
+
+ Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __FMP_DEPENDENCY_CHECK_LIB__
+#define __FMP_DEPENDENCY_CHECK_LIB__
+
+#include <PiDxe.h>
+#include <Protocol/FirmwareManagement.h>
+
+/**
+ Check dependency for firmware update.
+
+ @param[in] ImageTypeId Image Type Id.
+ @param[in] Version New version.
+ @param[in] Dependencies Fmp dependency.
+ @param[in] DependenciesSize Size, in bytes, of the Fmp dependency.
+
+ @retval TRUE Dependencies are satisfied.
+ @retval FALSE Dependencies are unsatisfied or dependency check fails.
+
+**/
+BOOLEAN
+EFIAPI
+CheckFmpDependency (
+ IN EFI_GUID ImageTypeId,
+ IN UINT32 Version,
+ IN EFI_FIRMWARE_IMAGE_DEP *Dependencies, OPTIONAL
+ IN UINT32 DependenciesSize
+ );
+
+#endif
diff --git a/FmpDevicePkg/Library/FmpDependencyCheckLib/FmpDependencyCheckLib.c b/FmpDevicePkg/Library/FmpDependencyCheckLib/FmpDependencyCheckLib.c
new file mode 100644
index 0000000000..5e0241b259
--- /dev/null
+++ b/FmpDevicePkg/Library/FmpDependencyCheckLib/FmpDependencyCheckLib.c
@@ -0,0 +1,196 @@
+/** @file
+ Provides FMP capsule dependency check services when updating the firmware
+ image of a FMP device.
+
+ Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include <PiDxe.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/FmpDependencyLib.h>
+#include <Library/FmpDependencyCheckLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+/**
+ Check dependency for firmware update.
+
+ @param[in] ImageTypeId Image Type Id.
+ @param[in] Version New version.
+ @param[in] Dependencies Fmp dependency.
+ @param[in] DependenciesSize Size, in bytes, of the Fmp dependency.
+
+ @retval TRUE Dependencies are satisfied.
+ @retval FALSE Dependencies are unsatisfied or dependency check fails.
+
+**/
+BOOLEAN
+EFIAPI
+CheckFmpDependency (
+ IN EFI_GUID ImageTypeId,
+ IN UINT32 Version,
+ IN EFI_FIRMWARE_IMAGE_DEP *Dependencies, OPTIONAL
+ IN UINT32 DependenciesSize
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *HandleBuffer;
+ UINTN Index;
+ EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp;
+ UINTN ImageInfoSize;
+ UINT32 *DescriptorVer;
+ UINT8 FmpImageInfoCount;
+ UINTN *DescriptorSize;
+ UINT32 PackageVersion;
+ CHAR16 *PackageVersionName;
+ UINTN NumberOfFmpInstance;
+ EFI_FIRMWARE_IMAGE_DESCRIPTOR **FmpImageInfoBuf;
+ FMP_DEPEX_CHECK_VERSION_DATA *FmpVersions;
+ UINTN FmpVersionsCount;
+ BOOLEAN IsSatisfied;
+
+ FmpImageInfoBuf = NULL;
+ DescriptorVer = NULL;
+ DescriptorSize = NULL;
+ NumberOfFmpInstance = 0;
+ FmpVersions = NULL;
+ FmpVersionsCount = 0;
+ IsSatisfied = TRUE;
+ PackageVersionName = NULL;
+
+ //
+ // Get ImageDescriptors of all FMP instances, and archive them for dependency evaluation.
+ //
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiFirmwareManagementProtocolGuid,
+ NULL,
+ &NumberOfFmpInstance,
+ &HandleBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "CheckFmpDependency: Get Firmware Management Protocol failed. (%r)", Status));
+ goto cleanup;
+ }
+
+ FmpImageInfoBuf = AllocateZeroPool (sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR *) * NumberOfFmpInstance);
+ if (FmpImageInfoBuf == NULL) {
+ IsSatisfied = FALSE;
+ goto cleanup;
+ }
+
+ DescriptorVer = AllocateZeroPool (sizeof(UINT32) * NumberOfFmpInstance);
+ if (DescriptorVer == NULL ) {
+ IsSatisfied = FALSE;
+ goto cleanup;
+ }
+
+ DescriptorSize = AllocateZeroPool (sizeof(UINTN) * NumberOfFmpInstance);
+ if (DescriptorSize == NULL ) {
+ IsSatisfied = FALSE;
+ goto cleanup;
+ }
+
+ FmpVersions = AllocateZeroPool (sizeof(FMP_DEPEX_CHECK_VERSION_DATA) * NumberOfFmpInstance);
+ if (FmpVersions == NULL) {
+ IsSatisfied = FALSE;
+ goto cleanup;
+ }
+
+ for (Index = 0; Index < NumberOfFmpInstance; Index ++) {
+ Status = gBS->HandleProtocol (
+ HandleBuffer[Index],
+ &gEfiFirmwareManagementProtocolGuid,
+ (VOID **) &Fmp
+ );
+ if (EFI_ERROR(Status)) {
+ continue;
+ }
+
+ ImageInfoSize = 0;
+ Status = Fmp->GetImageInfo (
+ Fmp,
+ &ImageInfoSize,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ );
+ if (Status != EFI_BUFFER_TOO_SMALL) {
+ continue;
+ }
+
+ FmpImageInfoBuf[Index] = AllocateZeroPool (ImageInfoSize);
+ if (FmpImageInfoBuf[Index] == NULL) {
+ continue;
+ }
+
+ Status = Fmp->GetImageInfo (
+ Fmp,
+ &ImageInfoSize, // ImageInfoSize
+ FmpImageInfoBuf[Index], // ImageInfo
+ &DescriptorVer[Index], // DescriptorVersion
+ &FmpImageInfoCount, // DescriptorCount
+ &DescriptorSize[Index], // DescriptorSize
+ &PackageVersion, // PackageVersion
+ &PackageVersionName // PackageVersionName
+ );
+ if (EFI_ERROR(Status)) {
+ FreePool (FmpImageInfoBuf[Index]);
+ FmpImageInfoBuf[Index] = NULL;
+ continue;
+ }
+
+ if (PackageVersionName != NULL) {
+ FreePool (PackageVersionName);
+ PackageVersionName = NULL;
+ }
+
+ CopyGuid (&FmpVersions[FmpVersionsCount].ImageTypeId, &FmpImageInfoBuf[Index]->ImageTypeId);
+ FmpVersions[FmpVersionsCount].Version = FmpImageInfoBuf[Index]->Version;
+ FmpVersionsCount ++;
+ }
+
+ //
+ // Evaluate firmware image's depex, against the version of other Fmp instances.
+ //
+ if (Dependencies != NULL) {
+ IsSatisfied = EvaluateDependency (Dependencies, DependenciesSize, FmpVersions, FmpVersionsCount);
+ }
+
+ if (!IsSatisfied) {
+ DEBUG ((DEBUG_ERROR, "CheckFmpDependency: %g\'s dependency is not satisfied!\n", ImageTypeId));
+ goto cleanup;
+ }
+
+cleanup:
+ if (FmpImageInfoBuf != NULL) {
+ for (Index = 0; Index < NumberOfFmpInstance; Index ++) {
+ if (FmpImageInfoBuf[Index] != NULL) {
+ FreePool (FmpImageInfoBuf[Index]);
+ }
+ }
+ FreePool (FmpImageInfoBuf);
+ }
+
+ if (DescriptorVer != NULL) {
+ FreePool (DescriptorVer);
+ }
+
+ if (DescriptorSize != NULL) {
+ FreePool (DescriptorSize);
+ }
+
+ if (FmpVersions != NULL) {
+ FreePool (FmpVersions);
+ }
+
+ return IsSatisfied;
+}
diff --git a/FmpDevicePkg/Library/FmpDependencyCheckLib/FmpDependencyCheckLib.inf b/FmpDevicePkg/Library/FmpDependencyCheckLib/FmpDependencyCheckLib.inf
new file mode 100644
index 0000000000..2050cc6490
--- /dev/null
+++ b/FmpDevicePkg/Library/FmpDependencyCheckLib/FmpDependencyCheckLib.inf
@@ -0,0 +1,43 @@
+## @file
+# Provides FMP capsule dependency check services when updating the firmware
+# image of a FMP device.
+#
+# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = FmpDependencyCheckLib
+ MODULE_UNI_FILE = FmpDependencyCheckLib.uni
+ FILE_GUID = 8296D425-3095-4CFE-88D8-B0A44DB174A8
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = FmpDependencyCheckLib|DXE_DRIVER UEFI_DRIVER UEFI_APPLICATION
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 ARM AARCH64
+#
+
+[Sources]
+ FmpDependencyCheckLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ FmpDevicePkg/FmpDevicePkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ FmpDependencyLib
+ MemoryAllocationLib
+ UefiLib
+ UefiBootServicesTableLib
+
+[Protocols]
+ gEfiFirmwareManagementProtocolGuid ## CONSUMES
diff --git a/FmpDevicePkg/Library/FmpDependencyCheckLib/FmpDependencyCheckLib.uni b/FmpDevicePkg/Library/FmpDependencyCheckLib/FmpDependencyCheckLib.uni
new file mode 100644
index 0000000000..c6369e2277
--- /dev/null
+++ b/FmpDevicePkg/Library/FmpDependencyCheckLib/FmpDependencyCheckLib.uni
@@ -0,0 +1,13 @@
+// /** @file
+// Provides FMP capsule dependency check services when updating the firmware
+// image of a FMP device.
+//
+// Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+#string STR_MODULE_ABSTRACT #language en-US "FMP Dependency Check Lib"
+
+#string STR_MODULE_DESCRIPTION #language en-US "Provides FMP capsule dependency check services when updating the firmware image of a FMP device."
diff --git a/FmpDevicePkg/Library/FmpDependencyCheckLibNull/FmpDependencyCheckLibNull.c b/FmpDevicePkg/Library/FmpDependencyCheckLibNull/FmpDependencyCheckLibNull.c
new file mode 100644
index 0000000000..55e9af2290
--- /dev/null
+++ b/FmpDevicePkg/Library/FmpDependencyCheckLibNull/FmpDependencyCheckLibNull.c
@@ -0,0 +1,34 @@
+/** @file
+ Null instance of FmpDependencyCheckLib.
+
+ Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include <PiDxe.h>
+#include <Library/FmpDependencyCheckLib.h>
+
+/**
+ Check dependency for firmware update.
+
+ @param[in] ImageTypeId Image Type Id.
+ @param[in] Version New version.
+ @param[in] Dependencies Fmp dependency.
+ @param[in] DependenciesSize Size, in bytes, of the Fmp dependency.
+
+ @retval TRUE Dependencies are satisfied.
+ @retval FALSE Dependencies are unsatisfied or dependency check fails.
+
+**/
+BOOLEAN
+EFIAPI
+CheckFmpDependency (
+ IN EFI_GUID ImageTypeId,
+ IN UINT32 Version,
+ IN EFI_FIRMWARE_IMAGE_DEP *Dependencies, OPTIONAL
+ IN UINT32 DependenciesSize
+ )
+{
+ return TRUE;
+}
diff --git a/FmpDevicePkg/Library/FmpDependencyCheckLibNull/FmpDependencyCheckLibNull.inf b/FmpDevicePkg/Library/FmpDependencyCheckLibNull/FmpDependencyCheckLibNull.inf
new file mode 100644
index 0000000000..5794d89191
--- /dev/null
+++ b/FmpDevicePkg/Library/FmpDependencyCheckLibNull/FmpDependencyCheckLibNull.inf
@@ -0,0 +1,30 @@
+## @file
+# Null instance of FmpDependencyCheckLib as an option to skip the dependency
+# check when updating the firmware image of a FMP device.
+#
+# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = FmpDependencyCheckLibNull
+ MODULE_UNI_FILE = FmpDependencyCheckLibNull.uni
+ FILE_GUID = D63F3166-9CBC-4AC2-8F23-8818E42EA2BD
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = FmpDependencyCheckLib|DXE_DRIVER UEFI_DRIVER UEFI_APPLICATION
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 ARM AARCH64
+#
+
+[Sources]
+ FmpDependencyCheckLibNull.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ FmpDevicePkg/FmpDevicePkg.dec
diff --git a/FmpDevicePkg/Library/FmpDependencyCheckLibNull/FmpDependencyCheckLibNull.uni b/FmpDevicePkg/Library/FmpDependencyCheckLibNull/FmpDependencyCheckLibNull.uni
new file mode 100644
index 0000000000..7942d08f76
--- /dev/null
+++ b/FmpDevicePkg/Library/FmpDependencyCheckLibNull/FmpDependencyCheckLibNull.uni
@@ -0,0 +1,13 @@
+// /** @file
+// Null instance of FmpDependencyCheckLib as an option to skip the dependency
+// check when updating the firmware image of a FMP device.
+//
+// Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+#string STR_MODULE_ABSTRACT #language en-US "FMP Dependency Check Library NULL instance"
+
+#string STR_MODULE_DESCRIPTION #language en-US "Null instance of FmpDependencyCheckLib as an option to skip the dependency check when updating the firmware image of a FMP device."
--
2.16.2.windows.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [edk2-devel] [PATCH V3 4/5] FmpDevicePkg: Add FmpDependencyDevice library class and NULL instance
2020-05-14 21:52 [edk2-devel] [PATCH V3 0/5] FmpDevicePkg: Move capsule dependency implement to library Xu, Wei6
` (2 preceding siblings ...)
2020-05-14 21:52 ` [edk2-devel] [PATCH V3 3/5] FmpDevicePkg: Add FmpDependencyCheck library class and instances Xu, Wei6
@ 2020-05-14 21:52 ` Xu, Wei6
2020-05-14 21:52 ` [edk2-devel] [PATCH V3 5/5] FmpDevicePkg/FmpDxe: Use new Fmp dependency libraries Xu, Wei6
4 siblings, 0 replies; 7+ messages in thread
From: Xu, Wei6 @ 2020-05-14 21:52 UTC (permalink / raw)
To: devel; +Cc: Michael D Kinney, Liming Gao, Sean Brogan
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=2696
This library provides firmware device specific services to support
saving dependency to firmware device and getting dependency from
firmware device.
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Sean Brogan <sean.brogan@microsoft.com>
Signed-off-by: Wei6 Xu <wei6.xu@intel.com>
---
FmpDevicePkg/FmpDevicePkg.dec | 5 +++
FmpDevicePkg/FmpDevicePkg.dsc | 2 +
.../Include/Library/FmpDependencyDeviceLib.h | 51 ++++++++++++++++++++++
.../FmpDependencyDeviceLib.c | 50 +++++++++++++++++++++
.../FmpDependencyDeviceLibNull.inf | 29 ++++++++++++
.../FmpDependencyDeviceLibNull.uni | 12 +++++
6 files changed, 149 insertions(+)
create mode 100644 FmpDevicePkg/Include/Library/FmpDependencyDeviceLib.h
create mode 100644 FmpDevicePkg/Library/FmpDependencyDeviceLibNull/FmpDependencyDeviceLib.c
create mode 100644 FmpDevicePkg/Library/FmpDependencyDeviceLibNull/FmpDependencyDeviceLibNull.inf
create mode 100644 FmpDevicePkg/Library/FmpDependencyDeviceLibNull/FmpDependencyDeviceLibNull.uni
diff --git a/FmpDevicePkg/FmpDevicePkg.dec b/FmpDevicePkg/FmpDevicePkg.dec
index 871d5ce890..cab63f5a47 100644
--- a/FmpDevicePkg/FmpDevicePkg.dec
+++ b/FmpDevicePkg/FmpDevicePkg.dec
@@ -41,10 +41,15 @@
## @libraryclass Provides platform specific services to support dependency
# check during update of firmware image.
FmpDependencyCheckLib|Include/Library/FmpDependencyCheckLib.h
+ ## @libraryclass Provides firmware device specific services to support
+ # saving dependency to firmware device and getting dependency
+ # from firmware device.
+ FmpDependencyDeviceLib|Include/Library/FmpDependencyDeviceLib.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 7e80806171..bdb73f2828 100644
--- a/FmpDevicePkg/FmpDevicePkg.dsc
+++ b/FmpDevicePkg/FmpDevicePkg.dsc
@@ -62,10 +62,11 @@
CapsuleUpdatePolicyLib|FmpDevicePkg/Library/CapsuleUpdatePolicyLibNull/CapsuleUpdatePolicyLibNull.inf
FmpPayloadHeaderLib|FmpDevicePkg/Library/FmpPayloadHeaderLibV1/FmpPayloadHeaderLibV1.inf
FmpDeviceLib|FmpDevicePkg/Library/FmpDeviceLibNull/FmpDeviceLibNull.inf
FmpDependencyLib|FmpDevicePkg/Library/FmpDependencyLib/FmpDependencyLib.inf
FmpDependencyCheckLib|FmpDevicePkg/Library/FmpDependencyCheckLibNull/FmpDependencyCheckLibNull.inf
+ FmpDependencyDeviceLib|FmpDevicePkg/Library/FmpDependencyDeviceLibNull/FmpDependencyDeviceLibNull.inf
TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf
[LibraryClasses.ARM, LibraryClasses.AARCH64]
#
# It is not possible to prevent the ARM compiler for generic intrinsic functions.
@@ -93,10 +94,11 @@
FmpDevicePkg/Library/FmpPayloadHeaderLibV1/FmpPayloadHeaderLibV1.inf
FmpDevicePkg/Library/FmpDeviceLibNull/FmpDeviceLibNull.inf
FmpDevicePkg/Library/FmpDependencyLib/FmpDependencyLib.inf
FmpDevicePkg/Library/FmpDependencyCheckLib/FmpDependencyCheckLib.inf
FmpDevicePkg/Library/FmpDependencyCheckLibNull/FmpDependencyCheckLibNull.inf
+ FmpDevicePkg/Library/FmpDependencyDeviceLibNull/FmpDependencyDeviceLibNull.inf
FmpDevicePkg/FmpDxe/FmpDxeLib.inf
#
# Modules
#
diff --git a/FmpDevicePkg/Include/Library/FmpDependencyDeviceLib.h b/FmpDevicePkg/Include/Library/FmpDependencyDeviceLib.h
new file mode 100644
index 0000000000..4351173b7e
--- /dev/null
+++ b/FmpDevicePkg/Include/Library/FmpDependencyDeviceLib.h
@@ -0,0 +1,51 @@
+/** @file
+ Provides firmware device specific services to support saving dependency to
+ firmware device and getting dependency from firmware device.
+
+ Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __FMP_DEPENDENCY_DEVICE_LIB__
+#define __FMP_DEPENDENCY_DEVICE_LIB__
+
+#include <PiDxe.h>
+#include <Protocol/FirmwareManagement.h>
+
+/**
+ Save dependency to Fmp device.
+
+ @param[in] Depex Fmp dependency.
+ @param[in] DepexSize Size, in bytes, of the Fmp dependency.
+
+ @retval EFI_SUCCESS Save Fmp dependency succeeds.
+ @retval EFI_UNSUPPORTED Save Fmp dependency is not supported.
+ @retval Others Save Fmp dependency fails.
+
+**/
+EFI_STATUS
+EFIAPI
+SaveFmpDependency (
+ IN EFI_FIRMWARE_IMAGE_DEP *Depex,
+ IN UINT32 DepexSize
+ );
+
+/**
+ Get dependency from the Fmp device.
+ This caller is responsible for freeing the dependency buffer.
+
+ @param[out] DepexSize Size, in bytes, of the dependency.
+
+ @retval The pointer to dependency.
+ @retval NULL
+
+**/
+EFI_FIRMWARE_IMAGE_DEP*
+EFIAPI
+GetFmpDependency (
+ OUT UINT32 *DepexSize
+ );
+
+#endif
diff --git a/FmpDevicePkg/Library/FmpDependencyDeviceLibNull/FmpDependencyDeviceLib.c b/FmpDevicePkg/Library/FmpDependencyDeviceLibNull/FmpDependencyDeviceLib.c
new file mode 100644
index 0000000000..0839681430
--- /dev/null
+++ b/FmpDevicePkg/Library/FmpDependencyDeviceLibNull/FmpDependencyDeviceLib.c
@@ -0,0 +1,50 @@
+/** @file
+ Null instance of FmpDependencyDeviceLib.
+
+ Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include <PiDxe.h>
+#include <Library/FmpDependencyDeviceLib.h>
+
+/**
+ Save dependency to Fmp device.
+
+ @param[in] Depex Fmp dependency.
+ @param[in] DepexSize Size, in bytes, of the Fmp dependency.
+
+ @retval EFI_SUCCESS Save Fmp dependency succeeds.
+ @retval EFI_UNSUPPORTED Save Fmp dependency is not supported.
+ @retval Others Save Fmp dependency fails.
+
+**/
+EFI_STATUS
+EFIAPI
+SaveFmpDependency (
+ IN EFI_FIRMWARE_IMAGE_DEP *Depex,
+ IN UINT32 DepexSize
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Get dependency from the Fmp device.
+ This caller is responsible for freeing the dependency buffer.
+
+ @param[out] DepexSize Size, in bytes, of the dependency.
+
+ @retval The pointer to dependency.
+ @retval NULL
+
+**/
+EFI_FIRMWARE_IMAGE_DEP*
+EFIAPI
+GetFmpDependency (
+ OUT UINT32 *DepexSize
+ )
+{
+ return NULL;
+}
diff --git a/FmpDevicePkg/Library/FmpDependencyDeviceLibNull/FmpDependencyDeviceLibNull.inf b/FmpDevicePkg/Library/FmpDependencyDeviceLibNull/FmpDependencyDeviceLibNull.inf
new file mode 100644
index 0000000000..d318cc9a67
--- /dev/null
+++ b/FmpDevicePkg/Library/FmpDependencyDeviceLibNull/FmpDependencyDeviceLibNull.inf
@@ -0,0 +1,29 @@
+## @file
+# Fmp Dependency Device Library Null instance.
+#
+# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = FmpDependencyDeviceLibNull
+ MODULE_UNI_FILE = FmpDependencyDeviceLibNull.uni
+ FILE_GUID = 05BE67B1-0748-4022-97E6-7C0D2F992AA6
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = FmpDependencyDeviceLib|DXE_DRIVER UEFI_DRIVER
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 ARM AARCH64
+#
+
+[Sources]
+ FmpDependencyDeviceLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ FmpDevicePkg/FmpDevicePkg.dec
diff --git a/FmpDevicePkg/Library/FmpDependencyDeviceLibNull/FmpDependencyDeviceLibNull.uni b/FmpDevicePkg/Library/FmpDependencyDeviceLibNull/FmpDependencyDeviceLibNull.uni
new file mode 100644
index 0000000000..730ff65cbd
--- /dev/null
+++ b/FmpDevicePkg/Library/FmpDependencyDeviceLibNull/FmpDependencyDeviceLibNull.uni
@@ -0,0 +1,12 @@
+// /** @file
+// Fmp Dependency Device Library Null instance.
+//
+// Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+#string STR_MODULE_ABSTRACT #language en-US "Fmp Dependency Device Library Null instance."
+
+#string STR_MODULE_DESCRIPTION #language en-US "Null instance that does not support saving and getting dependency for Fmp device."
--
2.16.2.windows.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [edk2-devel] [PATCH V3 5/5] FmpDevicePkg/FmpDxe: Use new Fmp dependency libraries
2020-05-14 21:52 [edk2-devel] [PATCH V3 0/5] FmpDevicePkg: Move capsule dependency implement to library Xu, Wei6
` (3 preceding siblings ...)
2020-05-14 21:52 ` [edk2-devel] [PATCH V3 4/5] FmpDevicePkg: Add FmpDependencyDevice library class and NULL instance Xu, Wei6
@ 2020-05-14 21:52 ` Xu, Wei6
4 siblings, 0 replies; 7+ messages in thread
From: Xu, Wei6 @ 2020-05-14 21:52 UTC (permalink / raw)
To: devel; +Cc: Michael D Kinney, Liming Gao, Sean Brogan
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=2696
Remove the orginal Fmp Capsule Dependency implement, and use new
FmpDependencyLib, FmpDependencyCheckLib and FmpDependencyDeviceLib
APIs instead.
A platform can perform the dependency check in a platform specific
manner by implementing its own FmpDependencyCheckLib.
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Sean Brogan <sean.brogan@microsoft.com>
Signed-off-by: Wei6 Xu <wei6.xu@intel.com>
---
FmpDevicePkg/FmpDxe/Dependency.c | 679 --------------------------------------
FmpDevicePkg/FmpDxe/Dependency.h | 63 ----
FmpDevicePkg/FmpDxe/FmpDxe.c | 256 +++-----------
FmpDevicePkg/FmpDxe/FmpDxe.h | 4 +
FmpDevicePkg/FmpDxe/FmpDxe.inf | 5 +-
FmpDevicePkg/FmpDxe/FmpDxeLib.inf | 5 +-
6 files changed, 64 insertions(+), 948 deletions(-)
delete mode 100644 FmpDevicePkg/FmpDxe/Dependency.c
delete mode 100644 FmpDevicePkg/FmpDxe/Dependency.h
diff --git a/FmpDevicePkg/FmpDxe/Dependency.c b/FmpDevicePkg/FmpDxe/Dependency.c
deleted file mode 100644
index 65c23989c6..0000000000
--- a/FmpDevicePkg/FmpDxe/Dependency.c
+++ /dev/null
@@ -1,679 +0,0 @@
-/** @file
- Supports Capsule Dependency Expression.
-
- Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
-
- SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-#include "FmpDxe.h"
-#include "Dependency.h"
-
-//
-// 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 variable used to support dependency evaluation
-//
-UINTN mNumberOfFmpInstance = 0;
-EFI_FIRMWARE_IMAGE_DESCRIPTOR **mFmpImageInfoBuf = NULL;
-
-//
-// Indicates the status of dependency check, default value is DEPENDENCIES_SATISFIED.
-//
-UINT8 mDependenciesCheckStatus = DEPENDENCIES_SATISFIED;
-
-//
-// 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) {
- 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) {
- return EFI_ACCESS_DENIED;
- }
-
- //
- // Pop the item off the stack
- //
- mDepexEvaluationStackPointer--;
- *Element = *mDepexEvaluationStackPointer;
- if ((*Element).Type != Type) {
- return EFI_INVALID_PARAMETER;
- }
- return EFI_SUCCESS;
-}
-
-/**
- Evaluate the dependencies.
-
- @param[in] Dependencies Dependency expressions.
- @param[in] DependenciesSize Size of Dependency expressions.
-
- @retval TRUE Dependency expressions evaluate to TRUE.
- @retval FALSE Dependency expressions evaluate to FALSE.
-
-**/
-BOOLEAN
-EvaluateDependencies (
- IN CONST EFI_FIRMWARE_IMAGE_DEP * Dependencies,
- IN CONST UINTN DependenciesSize
- )
-{
- EFI_STATUS Status;
- UINT8 *Iterator;
- UINT8 Index;
- DEPEX_ELEMENT Element1;
- DEPEX_ELEMENT Element2;
- GUID ImageTypeId;
- UINT32 Version;
-
- if (Dependencies == NULL || DependenciesSize == 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) {
- Status = EFI_INVALID_PARAMETER;
- goto Error;
- }
-
- CopyGuid (&ImageTypeId, (EFI_GUID *) (Iterator + 1));
- Iterator = Iterator + sizeof (EFI_GUID);
-
- for (Index = 0; Index < mNumberOfFmpInstance; Index ++){
- if (mFmpImageInfoBuf[Index] == NULL) {
- continue;
- }
- if(CompareGuid (&mFmpImageInfoBuf[Index]->ImageTypeId, &ImageTypeId)){
- Status = Push (mFmpImageInfoBuf[Index]->Version, VersionType);
- if (EFI_ERROR (Status)) {
- goto Error;
- }
- break;
- }
- }
- if (Index == mNumberOfFmpInstance) {
- Status = EFI_NOT_FOUND;
- goto Error;
- }
- break;
- case EFI_FMP_DEP_PUSH_VERSION:
- if (Iterator + sizeof (UINT32) >= (UINT8 *) Dependencies->Dependencies + DependenciesSize ) {
- Status = EFI_INVALID_PARAMETER;
- 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));
- 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:
- Status = EFI_INVALID_PARAMETER;
- goto Error;
- }
- Iterator++;
- }
-
-Error:
-
- DEBUG ((DEBUG_ERROR, "FmpDxe(%s): EvaluateDependencies() - RESULT = FALSE (Status = %r)\n", mImageIdName, Status));
- return FALSE;
-}
-
-/**
- Validate the dependency expression and output its size.
-
- @param[in] ImageDepex 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
-ValidateImageDepex (
- IN EFI_FIRMWARE_IMAGE_DEP *ImageDepex,
- IN CONST UINTN MaxDepexSize,
- OUT UINT32 *DepexSize
- )
-{
- UINT8 *Depex;
-
- *DepexSize = 0;
- Depex = ImageDepex->Dependencies;
- while (Depex < ImageDepex->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, ImageDepex->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;
- *DepexSize = (UINT32)(Depex - ImageDepex->Dependencies);
- return TRUE;
- default:
- return FALSE;
- }
- }
-
- return FALSE;
-}
-
-
-/**
- Get the size of dependencies. Assume the dependencies is validated before
- calling this function.
-
- @param[in] Dependencies Pointer to the EFI_FIRMWARE_IMAGE_DEP.
-
- @retval The size of dependencies.
-
-**/
-UINTN
-GetDepexSize (
- IN CONST EFI_FIRMWARE_IMAGE_DEP *Dependencies
- )
-{
- UINTN Index;
-
- if (Dependencies == NULL) {
- return 0;
- }
-
- Index = 0;
- while (Dependencies->Dependencies[Index] != EFI_FMP_DEP_END) {
- Index ++;
- }
-
- return Index + 1;
-}
-
-/**
- Check dependency for firmware update.
-
- @param[in] ImageTypeId Image Type Id.
- @param[in] Version New version.
- @param[in] Dependencies The dependencies.
- @param[in] DependenciesSize Size of the dependencies
- @param[out] IsSatisfied Indicate the dependencies is satisfied or not.
-
- @retval EFI_SUCCESS Dependency Evaluation is successful.
- @retval Others Dependency Evaluation fails with unexpected error.
-
-**/
-EFI_STATUS
-EvaluateImageDependencies (
- IN CONST EFI_GUID ImageTypeId,
- IN CONST UINT32 Version,
- IN CONST EFI_FIRMWARE_IMAGE_DEP *Dependencies,
- IN CONST UINT32 DependenciesSize,
- OUT BOOLEAN *IsSatisfied
- )
-{
- EFI_STATUS Status;
- EFI_HANDLE *HandleBuffer;
- UINTN Index;
- EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp;
- UINTN ImageInfoSize;
- UINT32 FmpImageInfoDescriptorVer;
- UINT8 FmpImageInfoCount;
- UINTN DescriptorSize;
- UINT32 PackageVersion;
- CHAR16 *PackageVersionName;
- UINTN DepexSize;
-
- *IsSatisfied = TRUE;
- PackageVersionName = NULL;
-
- //
- // Get ImageDescriptors of all FMP instances, and archive them for depex evaluation.
- //
- Status = gBS->LocateHandleBuffer (
- ByProtocol,
- &gEfiFirmwareManagementProtocolGuid,
- NULL,
- &mNumberOfFmpInstance,
- &HandleBuffer
- );
- if (EFI_ERROR (Status)) {
- return EFI_ABORTED;
- }
-
- mFmpImageInfoBuf = AllocateZeroPool (sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR *) * mNumberOfFmpInstance);
- if (mFmpImageInfoBuf == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- for (Index = 0; Index < mNumberOfFmpInstance; Index ++) {
- Status = gBS->HandleProtocol (
- HandleBuffer[Index],
- &gEfiFirmwareManagementProtocolGuid,
- (VOID **) &Fmp
- );
- if (EFI_ERROR(Status)) {
- continue;
- }
-
- ImageInfoSize = 0;
- Status = Fmp->GetImageInfo (
- Fmp,
- &ImageInfoSize,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL
- );
- if (Status != EFI_BUFFER_TOO_SMALL) {
- continue;
- }
-
- mFmpImageInfoBuf[Index] = AllocateZeroPool (ImageInfoSize);
- if (mFmpImageInfoBuf[Index] == NULL) {
- continue;
- }
-
- Status = Fmp->GetImageInfo (
- Fmp,
- &ImageInfoSize, // ImageInfoSize
- mFmpImageInfoBuf[Index], // ImageInfo
- &FmpImageInfoDescriptorVer, // DescriptorVersion
- &FmpImageInfoCount, // DescriptorCount
- &DescriptorSize, // DescriptorSize
- &PackageVersion, // PackageVersion
- &PackageVersionName // PackageVersionName
- );
- if (EFI_ERROR(Status)) {
- FreePool (mFmpImageInfoBuf[Index]);
- mFmpImageInfoBuf[Index] = NULL;
- continue;
- }
-
- if (PackageVersionName != NULL) {
- FreePool (PackageVersionName);
- PackageVersionName = NULL;
- }
- }
-
- //
- // Step 1 - Evaluate firmware image's depex, against the version of other Fmp instances.
- //
- if (Dependencies != NULL) {
- *IsSatisfied = EvaluateDependencies (Dependencies, DependenciesSize);
- }
-
- if (!*IsSatisfied) {
- goto cleanup;
- }
-
- //
- // Step 2 - Evaluate the depex of all other Fmp instances, against the new version in
- // the firmware image.
- //
-
- //
- // Update the new version to mFmpImageInfoBuf.
- //
- for (Index = 0; Index < mNumberOfFmpInstance; Index ++) {
- if (mFmpImageInfoBuf[Index] != NULL) {
- if (CompareGuid (&ImageTypeId, &mFmpImageInfoBuf[Index]->ImageTypeId)) {
- mFmpImageInfoBuf[Index]->Version = Version;
- break;
- }
- }
- }
-
- //
- // Evaluate the Dependencies one by one.
- //
- for (Index = 0; Index < mNumberOfFmpInstance; Index ++) {
- if (mFmpImageInfoBuf[Index] != NULL) {
- //
- // Skip the Fmp instance to be "SetImage".
- //
- if (CompareGuid (&ImageTypeId, &mFmpImageInfoBuf[Index]->ImageTypeId)) {
- continue;
- }
- if ((mFmpImageInfoBuf[Index]->AttributesSupported & IMAGE_ATTRIBUTE_DEPENDENCY) &&
- mFmpImageInfoBuf[Index]->Dependencies != NULL) {
- //
- // Get the size of depex.
- // Assume that the dependencies in EFI_FIRMWARE_IMAGE_DESCRIPTOR is validated when PopulateDescriptor().
- //
- DepexSize = GetDepexSize (mFmpImageInfoBuf[Index]->Dependencies);
- if (DepexSize > 0) {
- *IsSatisfied = EvaluateDependencies (mFmpImageInfoBuf[Index]->Dependencies, DepexSize);
- if (!*IsSatisfied) {
- break;
- }
- }
- }
- }
- }
-
-cleanup:
- if (mFmpImageInfoBuf != NULL) {
- for (Index = 0; Index < mNumberOfFmpInstance; Index ++) {
- if (mFmpImageInfoBuf[Index] != NULL) {
- FreePool (mFmpImageInfoBuf[Index]);
- }
- }
- FreePool (mFmpImageInfoBuf);
- }
-
- return EFI_SUCCESS;
-}
diff --git a/FmpDevicePkg/FmpDxe/Dependency.h b/FmpDevicePkg/FmpDxe/Dependency.h
deleted file mode 100644
index badd2542d6..0000000000
--- a/FmpDevicePkg/FmpDxe/Dependency.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/** @file
- Fmp Capsule Dependency support functions for Firmware Management Protocol based
- firmware updates.
-
- Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
-
- SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#ifndef __DEPENDENCY_H__
-#define __DEPENDENCY_H__
-
-#include <Library/UefiLib.h>
-#include <Protocol/FirmwareManagement.h>
-
-#define DEPENDENCIES_SATISFIED 0
-#define DEPENDENCIES_UNSATISFIED 1
-#define DEPENDENCIES_INVALID 2
-
-extern UINT8 mDependenciesCheckStatus;
-
-/**
- Validate the dependency expression and output its size.
-
- @param[in] ImageDepex 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
-ValidateImageDepex (
- IN EFI_FIRMWARE_IMAGE_DEP *ImageDepex,
- IN CONST UINTN MaxDepexSize,
- OUT UINT32 *DepexSize
- );
-
-/**
- Check dependency for firmware update.
-
- @param[in] ImageTypeId Image Type Id.
- @param[in] Version New version.
- @param[in] Dependencies The dependencies.
- @param[in] DepexSize Size of the dependencies
- @param[out] IsSatisfied Indicate the dependencies is satisfied or not.
-
- @retval EFI_SUCCESS Dependency Evaluation is successful.
- @retval Others Dependency Evaluation fails with unexpected error.
-
-**/
-EFI_STATUS
-EvaluateImageDependencies (
- IN CONST EFI_GUID ImageTypeId,
- IN CONST UINT32 Version,
- IN CONST EFI_FIRMWARE_IMAGE_DEP *Dependencies,
- IN CONST UINT32 DepexSize,
- OUT BOOLEAN *IsSatisfied
- );
-
-#endif
diff --git a/FmpDevicePkg/FmpDxe/FmpDxe.c b/FmpDevicePkg/FmpDxe/FmpDxe.c
index 5b523291e4..58841774fe 100644
--- a/FmpDevicePkg/FmpDxe/FmpDxe.c
+++ b/FmpDevicePkg/FmpDxe/FmpDxe.c
@@ -10,11 +10,10 @@
**/
#include "FmpDxe.h"
#include "VariableSupport.h"
-#include "Dependency.h"
///
/// FILE_GUID from FmpDxe.inf. When FmpDxe.inf is used in a platform, the
/// FILE_GUID must always be overridden in the <Defines> section to provide
/// the ESRT GUID value associated with the updatable firmware image. A
@@ -79,11 +78,12 @@ const FIRMWARE_MANAGEMENT_PRIVATE_DATA mFirmwareManagementPrivateDataTemplate =
NULL, // FmpDeviceContext
NULL, // VersionVariableName
NULL, // LsvVariableName
NULL, // LastAttemptStatusVariableName
NULL, // LastAttemptVersionVariableName
- NULL // FmpStateVariableName
+ NULL, // FmpStateVariableName
+ TRUE // DependenciesSatisfied
};
///
/// GUID that is used to create event used to lock the firmware storage device.
///
@@ -274,17 +274,11 @@ VOID
PopulateDescriptor (
FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private
)
{
EFI_STATUS Status;
- VOID *Image;
- UINTN ImageSize;
- BOOLEAN IsDepexValid;
- UINT32 DepexSize;
-
- Image = NULL;
- ImageSize = 0;
+ UINT32 DependenciesSize;
if (Private->DescriptorPopulated) {
return;
}
@@ -385,50 +379,22 @@ PopulateDescriptor (
Private->Descriptor.LastAttemptVersion = GetLastAttemptVersionFromVariable (Private);
Private->Descriptor.LastAttemptStatus = GetLastAttemptStatusFromVariable (Private);
//
- // Get the dependency from the FmpDeviceLib and populate it to the descriptor.
+ // Get the dependency from the FmpDependencyDeviceLib.
//
Private->Descriptor.Dependencies = NULL;
//
// Check the attribute IMAGE_ATTRIBUTE_DEPENDENCY
//
- if (Private->Descriptor.AttributesSupported & IMAGE_ATTRIBUTE_DEPENDENCY) {
- //
- // The parameter "Image" of FmpDeviceGetImage() is extended to contain the dependency.
- // Get the dependency from the Image.
- //
- ImageSize = Private->Descriptor.Size;
- Image = AllocatePool (ImageSize);
- if (Image != NULL) {
- Status = FmpDeviceGetImage (Image, &ImageSize);
- if (Status == EFI_BUFFER_TOO_SMALL) {
- FreePool (Image);
- Image = AllocatePool (ImageSize);
- if (Image != NULL) {
- Status = FmpDeviceGetImage (Image, &ImageSize);
- }
- }
- }
- if (!EFI_ERROR (Status) && Image != NULL) {
- IsDepexValid = ValidateImageDepex ((EFI_FIRMWARE_IMAGE_DEP *) Image, ImageSize, &DepexSize);
- if (IsDepexValid) {
- Private->Descriptor.Dependencies = AllocatePool (DepexSize);
- if (Private->Descriptor.Dependencies != NULL) {
- CopyMem (Private->Descriptor.Dependencies->Dependencies, Image, DepexSize);
- }
- }
- }
+ if (Private->Descriptor.AttributesSetting & IMAGE_ATTRIBUTE_DEPENDENCY) {
+ Private->Descriptor.Dependencies = GetFmpDependency (&DependenciesSize);
}
Private->DescriptorPopulated = TRUE;
-
- if (Image != NULL) {
- FreePool (Image);
- }
}
/**
Returns information about the current firmware image(s) of the device.
@@ -586,21 +552,16 @@ GetTheImage (
)
{
EFI_STATUS Status;
FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private;
UINTN Size;
- UINT8 *ImageBuffer;
- UINTN ImageBufferSize;
- UINT32 DepexSize;
if (!FeaturePcdGet (PcdFmpDeviceStorageAccessEnable)) {
return EFI_UNSUPPORTED;
}
- Status = EFI_SUCCESS;
- ImageBuffer = NULL;
- DepexSize = 0;
+ Status = EFI_SUCCESS;
//
// Retrieve the private context structure
//
Private = FIRMWARE_MANAGEMENT_PRIVATE_DATA_FROM_THIS (This);
@@ -626,49 +587,12 @@ GetTheImage (
//
Status = FmpDeviceGetSize (&Size);
if (EFI_ERROR (Status)) {
Size = 0;
}
-
- //
- // The parameter "Image" of FmpDeviceGetImage() is extended to contain the dependency.
- // Get the Fmp Payload from the Image.
- //
- ImageBufferSize = Size;
- ImageBuffer = AllocatePool (ImageBufferSize);
- if (ImageBuffer == NULL) {
- DEBUG ((DEBUG_ERROR, "FmpDxe(%s): GetImage() - AllocatePool fails.\n", mImageIdName));
- Status = EFI_NOT_FOUND;
- goto cleanup;
- }
- Status = FmpDeviceGetImage (ImageBuffer, &ImageBufferSize);
- if (Status == EFI_BUFFER_TOO_SMALL) {
- FreePool (ImageBuffer);
- ImageBuffer = AllocatePool (ImageBufferSize);
- if (ImageBuffer == NULL) {
- DEBUG ((DEBUG_ERROR, "FmpDxe(%s): GetImage() - AllocatePool fails.\n", mImageIdName));
- Status = EFI_NOT_FOUND;
- goto cleanup;
- }
- Status = FmpDeviceGetImage (ImageBuffer, &ImageBufferSize);
- }
- if (EFI_ERROR (Status)) {
- goto cleanup;
- }
-
- //
- // Check the attribute IMAGE_ATTRIBUTE_DEPENDENCY
- //
- if (Private->Descriptor.AttributesSetting & IMAGE_ATTRIBUTE_DEPENDENCY) {
- //
- // Validate the dependency to get its size.
- //
- ValidateImageDepex ((EFI_FIRMWARE_IMAGE_DEP *) ImageBuffer, ImageBufferSize, &DepexSize);
- }
-
- if (*ImageSize < ImageBufferSize - DepexSize) {
- *ImageSize = ImageBufferSize - DepexSize;
+ if (*ImageSize < Size) {
+ *ImageSize = Size;
DEBUG ((DEBUG_VERBOSE, "FmpDxe(%s): GetImage() - ImageSize is to small.\n", mImageIdName));
Status = EFI_BUFFER_TOO_SMALL;
goto cleanup;
}
@@ -676,57 +600,50 @@ GetTheImage (
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): GetImage() - Image Pointer Parameter is NULL.\n", mImageIdName));
Status = EFI_INVALID_PARAMETER;
goto cleanup;
}
- //
- // Image is after the dependency expression.
- //
- *ImageSize = ImageBufferSize - DepexSize;
- CopyMem (Image, ImageBuffer + DepexSize, *ImageSize);
- Status = EFI_SUCCESS;
-
+ Status = FmpDeviceGetImage (Image, ImageSize);
cleanup:
- if (ImageBuffer != NULL) {
- FreePool (ImageBuffer);
- }
return Status;
}
/**
Helper function to safely retrieve the FMP header from
within an EFI_FIRMWARE_IMAGE_AUTHENTICATION structure.
- @param[in] Image Pointer to the image.
- @param[in] ImageSize Size of the image.
+ @param[in] Image Pointer to the image.
+ @param[in] ImageSize Size of the image.
+ @param[in] AdditionalHeaderSize Size of any headers that cannot be calculated by this function.
@param[out] PayloadSize
@retval !NULL Valid pointer to the header.
@retval NULL Structure is bad and pointer cannot be found.
**/
VOID *
GetFmpHeader (
IN CONST EFI_FIRMWARE_IMAGE_AUTHENTICATION *Image,
IN CONST UINTN ImageSize,
+ IN CONST UINTN AdditionalHeaderSize,
OUT UINTN *PayloadSize
)
{
//
// 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) {
+ if (((UINTN)Image + sizeof (Image->MonotonicCount) + Image->AuthInfo.Hdr.dwLength) + AdditionalHeaderSize < (UINTN)Image || \
+ ((UINTN)Image + sizeof (Image->MonotonicCount) + Image->AuthInfo.Hdr.dwLength) + AdditionalHeaderSize >= (UINTN)Image + ImageSize) {
//
// Pointer overflow. Invalid image.
//
return NULL;
}
- *PayloadSize = ImageSize - (sizeof (Image->MonotonicCount) + Image->AuthInfo.Hdr.dwLength);
- return (VOID *)((UINT8 *)Image + sizeof (Image->MonotonicCount) + Image->AuthInfo.Hdr.dwLength);
+ *PayloadSize = ImageSize - (sizeof (Image->MonotonicCount) + Image->AuthInfo.Hdr.dwLength + AdditionalHeaderSize);
+ return (VOID *)((UINT8 *)Image + sizeof (Image->MonotonicCount) + Image->AuthInfo.Hdr.dwLength + AdditionalHeaderSize);
}
/**
Helper function to safely calculate the size of all headers
within an EFI_FIRMWARE_IMAGE_AUTHENTICATION structure.
@@ -809,12 +726,10 @@ CheckTheImage (
UINTN PublicKeyDataLength;
UINT8 *PublicKeyDataXdr;
UINT8 *PublicKeyDataXdrEnd;
EFI_FIRMWARE_IMAGE_DEP *Dependencies;
UINT32 DependenciesSize;
- BOOLEAN IsDepexValid;
- BOOLEAN IsDepexSatisfied;
Status = EFI_SUCCESS;
RawSize = 0;
FmpPayloadHeader = NULL;
FmpPayloadSize = 0;
@@ -848,10 +763,15 @@ CheckTheImage (
//
//Set to valid and then if any tests fail it will update this flag.
//
*ImageUpdatable = IMAGE_UPDATABLE_VALID;
+ //
+ // Set to satisfied and then if dependency evaluates to false it will update this flag.
+ //
+ Private->DependenciesSatisfied = TRUE;
+
if (Image == NULL) {
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckImage() - Image Pointer Parameter is NULL.\n", mImageIdName));
//
// not sure if this is needed
//
@@ -933,49 +853,30 @@ CheckTheImage (
*ImageUpdatable = IMAGE_UPDATABLE_INVALID_TYPE;
Status = EFI_SUCCESS;
goto cleanup;
}
+ //
+ // Get the dependency from Image.
+ //
+ Dependencies = GetImageDependency ((EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, ImageSize, &DependenciesSize);
//
// Check the FmpPayloadHeader
//
- FmpPayloadHeader = GetFmpHeader ( (EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, ImageSize, &FmpPayloadSize );
+ FmpPayloadHeader = GetFmpHeader ( (EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, ImageSize, DependenciesSize, &FmpPayloadSize );
if (FmpPayloadHeader == NULL) {
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - GetFmpHeader failed.\n", mImageIdName));
Status = EFI_ABORTED;
goto cleanup;
}
Status = GetFmpPayloadHeaderVersion (FmpPayloadHeader, FmpPayloadSize, &Version);
if (EFI_ERROR (Status)) {
- //
- // Check if there is dependency expression
- //
- IsDepexValid = ValidateImageDepex ((EFI_FIRMWARE_IMAGE_DEP*) FmpPayloadHeader, FmpPayloadSize, &DependenciesSize);
- if (IsDepexValid && (DependenciesSize < FmpPayloadSize)) {
- //
- // Fmp payload is after dependency expression
- //
- Dependencies = (EFI_FIRMWARE_IMAGE_DEP*) FmpPayloadHeader;
- FmpPayloadHeader = (UINT8 *) Dependencies + DependenciesSize;
- FmpPayloadSize = FmpPayloadSize - DependenciesSize;
- Status = GetFmpPayloadHeaderVersion (FmpPayloadHeader, FmpPayloadSize, &Version);
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - GetFmpPayloadHeaderVersion failed %r.\n", mImageIdName, Status));
- *ImageUpdatable = IMAGE_UPDATABLE_INVALID;
- Status = EFI_SUCCESS;
- goto cleanup;
- }
- } else {
- DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - Dependency is invalid.\n", mImageIdName));
- mDependenciesCheckStatus = DEPENDENCIES_INVALID;
- *ImageUpdatable = IMAGE_UPDATABLE_INVALID;
- Status = EFI_SUCCESS;
- goto cleanup;
- }
- } else {
- DEBUG ((DEBUG_WARN, "FmpDxe(%s): CheckTheImage() - No dependency associated in image.\n", mImageIdName));
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - GetFmpPayloadHeaderVersion failed %r.\n", mImageIdName, Status));
+ *ImageUpdatable = IMAGE_UPDATABLE_INVALID;
+ Status = EFI_SUCCESS;
+ goto cleanup;
}
//
// Check the lowest supported version
//
@@ -991,18 +892,13 @@ CheckTheImage (
}
//
// Evaluate dependency expression
//
- Status = EvaluateImageDependencies (Private->Descriptor.ImageTypeId, Version, Dependencies, DependenciesSize, &IsDepexSatisfied);
- if (!IsDepexSatisfied || EFI_ERROR (Status)) {
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - Dependency check failed %r.\n", mImageIdName, Status));
- } else {
- DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - Dependency is not satisfied.\n", mImageIdName));
- }
- mDependenciesCheckStatus = DEPENDENCIES_UNSATISFIED;
+ Private->DependenciesSatisfied = CheckFmpDependency (Private->Descriptor.ImageTypeId, Version, Dependencies, DependenciesSize);
+ if (!Private->DependenciesSatisfied) {
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - Dependency check failed.\n", mImageIdName));
*ImageUpdatable = IMAGE_UPDATABLE_INVALID;
Status = EFI_SUCCESS;
goto cleanup;
}
@@ -1111,13 +1007,10 @@ SetTheImage (
UINT32 LastAttemptStatus;
UINT32 Version;
UINT32 LowestSupportedVersion;
EFI_FIRMWARE_IMAGE_DEP *Dependencies;
UINT32 DependenciesSize;
- BOOLEAN IsDepexValid;
- UINT8 *ImageBuffer;
- UINTN ImageBufferSize;
Status = EFI_SUCCESS;
Updateable = 0;
BooleanValue = FALSE;
FmpHeaderSize = 0;
@@ -1126,12 +1019,10 @@ SetTheImage (
AllHeaderSize = 0;
IncomingFwVersion = 0;
LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;
Dependencies = NULL;
DependenciesSize = 0;
- ImageBuffer = NULL;
- ImageBufferSize = 0;
if (!FeaturePcdGet (PcdFmpDeviceStorageAccessEnable)) {
return EFI_UNSUPPORTED;
}
@@ -1159,15 +1050,10 @@ SetTheImage (
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - Device is already locked. Can't update.\n", mImageIdName));
Status = EFI_UNSUPPORTED;
goto cleanup;
}
- //
- // Set check status to satisfied before CheckTheImage()
- //
- mDependenciesCheckStatus = DEPENDENCIES_SATISFIED;
-
//
// Call check image to verify the image
//
Status = CheckTheImage (This, ImageIndex, Image, ImageSize, &Updateable);
if (EFI_ERROR (Status)) {
@@ -1176,36 +1062,26 @@ SetTheImage (
LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_AUTH_ERROR;
}
goto cleanup;
}
+ //
+ // Get the dependency from Image.
+ //
+ Dependencies = GetImageDependency ((EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, ImageSize, &DependenciesSize);
+
//
// No functional error in CheckTheImage. Attempt to get the Version to
// support better error reporting.
//
- FmpHeader = GetFmpHeader ( (EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, ImageSize, &FmpPayloadSize );
+ FmpHeader = GetFmpHeader ( (EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, ImageSize, DependenciesSize, &FmpPayloadSize );
if (FmpHeader == NULL) {
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - GetFmpHeader failed.\n", mImageIdName));
Status = EFI_ABORTED;
goto cleanup;
}
Status = GetFmpPayloadHeaderVersion (FmpHeader, FmpPayloadSize, &IncomingFwVersion);
- if (EFI_ERROR (Status)) {
- //
- // Check if there is dependency expression
- //
- IsDepexValid = ValidateImageDepex ((EFI_FIRMWARE_IMAGE_DEP*) FmpHeader, FmpPayloadSize, &DependenciesSize);
- if (IsDepexValid && (DependenciesSize < FmpPayloadSize)) {
- //
- // Fmp payload is after dependency expression
- //
- Dependencies = (EFI_FIRMWARE_IMAGE_DEP*) FmpHeader;
- FmpHeader = (UINT8 *) FmpHeader + DependenciesSize;
- FmpPayloadSize = FmpPayloadSize - DependenciesSize;
- Status = GetFmpPayloadHeaderVersion (FmpHeader, FmpPayloadSize, &IncomingFwVersion);
- }
- }
if (!EFI_ERROR (Status)) {
//
// Set to actual value
//
SetLastAttemptVersionInVariable (Private, IncomingFwVersion);
@@ -1216,14 +1092,12 @@ SetTheImage (
DEBUG (
(DEBUG_ERROR,
"FmpDxe(%s): SetTheImage() - Check The Image returned that the Image was not valid for update. Updatable value = 0x%X.\n",
mImageIdName, Updateable)
);
- if (mDependenciesCheckStatus == DEPENDENCIES_UNSATISFIED) {
+ if (Private->DependenciesSatisfied == FALSE) {
LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSATISFIED_DEPENDENCIES;
- } else if (mDependenciesCheckStatus == DEPENDENCIES_INVALID) {
- LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT;
}
Status = EFI_ABORTED;
goto cleanup;
}
@@ -1321,59 +1195,41 @@ SetTheImage (
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - GetAllHeaderSize failed.\n", mImageIdName));
Status = EFI_ABORTED;
goto cleanup;
}
- //
- // Check the attribute IMAGE_ATTRIBUTE_DEPENDENCY
- //
- if (Private->Descriptor.AttributesSetting & IMAGE_ATTRIBUTE_DEPENDENCY) {
- //
- // To support saving dependency, extend param "Image" of FmpDeviceSetImage() to
- // contain the dependency inside. FmpDeviceSetImage() is responsible for saving
- // the dependency which can be used for future dependency check.
- //
- ImageBufferSize = DependenciesSize + ImageSize - AllHeaderSize;
- ImageBuffer = AllocatePool (ImageBufferSize);
- if (ImageBuffer == NULL) {
- DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - AllocatePool failed.\n", mImageIdName));
- Status = EFI_ABORTED;
- goto cleanup;
- }
- CopyMem (ImageBuffer, Dependencies->Dependencies, DependenciesSize);
- CopyMem (ImageBuffer + DependenciesSize, (UINT8 *)Image + AllHeaderSize, ImageBufferSize - DependenciesSize);
- } else {
- ImageBufferSize = ImageSize - AllHeaderSize;
- ImageBuffer = AllocateCopyPool(ImageBufferSize, (UINT8 *)Image + AllHeaderSize);
- if (ImageBuffer == NULL) {
- DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - AllocatePool failed.\n", mImageIdName));
- Status = EFI_ABORTED;
- goto cleanup;
- }
- }
-
//
// Indicate that control is handed off to FmpDeviceLib
//
Progress (5);
//
//Copy the requested image to the firmware using the FmpDeviceLib
//
Status = FmpDeviceSetImage (
- ImageBuffer,
- ImageBufferSize,
+ (((UINT8 *)Image) + AllHeaderSize),
+ ImageSize - AllHeaderSize,
VendorCode,
FmpDxeProgress,
IncomingFwVersion,
AbortReason
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() SetImage from FmpDeviceLib failed. Status = %r.\n", mImageIdName, Status));
goto cleanup;
}
+ //
+ // Store the dependency
+ //
+ if (Private->Descriptor.AttributesSetting & IMAGE_ATTRIBUTE_DEPENDENCY) {
+ Status = SaveFmpDependency (Dependencies, DependenciesSize);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() SaveFmpDependency from FmpDependencyCheckLib failed. (%r)\n", mImageIdName, Status));
+ }
+ Status = EFI_SUCCESS;
+ }
//
// Finished the update without error
// Indicate that control has been returned from FmpDeviceLib
//
@@ -1396,14 +1252,10 @@ SetTheImage (
SetLowestSupportedVersionInVariable (Private, LowestSupportedVersion);
LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
cleanup:
- if (ImageBuffer != NULL) {
- FreePool (ImageBuffer);
- }
-
mProgressFunc = NULL;
SetLastAttemptStatusInVariable (Private, LastAttemptStatus);
if (Progress != NULL) {
//
diff --git a/FmpDevicePkg/FmpDxe/FmpDxe.h b/FmpDevicePkg/FmpDxe/FmpDxe.h
index 150f18b656..30754dea49 100644
--- a/FmpDevicePkg/FmpDxe/FmpDxe.h
+++ b/FmpDevicePkg/FmpDxe/FmpDxe.h
@@ -26,10 +26,13 @@
#include <Library/PrintLib.h>
#include <Library/FmpAuthenticationLib.h>
#include <Library/FmpDeviceLib.h>
#include <Library/FmpPayloadHeaderLib.h>
#include <Library/CapsuleUpdatePolicyLib.h>
+#include <Library/FmpDependencyLib.h>
+#include <Library/FmpDependencyCheckLib.h>
+#include <Library/FmpDependencyDeviceLib.h>
#include <Protocol/FirmwareManagement.h>
#include <Protocol/FirmwareManagementProgress.h>
#include <Protocol/VariableLock.h>
#include <Guid/SystemResourceTable.h>
#include <Guid/EventGroup.h>
@@ -64,10 +67,11 @@ typedef struct {
CHAR16 *VersionVariableName;
CHAR16 *LsvVariableName;
CHAR16 *LastAttemptStatusVariableName;
CHAR16 *LastAttemptVersionVariableName;
CHAR16 *FmpStateVariableName;
+ BOOLEAN DependenciesSatisfied;
} FIRMWARE_MANAGEMENT_PRIVATE_DATA;
///
///
///
diff --git a/FmpDevicePkg/FmpDxe/FmpDxe.inf b/FmpDevicePkg/FmpDxe/FmpDxe.inf
index 97b6518fa1..eeb904a091 100644
--- a/FmpDevicePkg/FmpDxe/FmpDxe.inf
+++ b/FmpDevicePkg/FmpDxe/FmpDxe.inf
@@ -26,12 +26,10 @@
#
[Sources]
FmpDxe.c
FmpDxe.h
- Dependency.c
- Dependency.h
DetectTestKey.c
VariableSupport.h
VariableSupport.c
[Packages]
@@ -52,10 +50,13 @@
BaseCryptLib
FmpAuthenticationLib
FmpDeviceLib
FmpPayloadHeaderLib
CapsuleUpdatePolicyLib
+ FmpDependencyLib
+ FmpDependencyCheckLib
+ FmpDependencyDeviceLib
[Guids]
gEfiEndOfDxeEventGroupGuid
[Protocols]
diff --git a/FmpDevicePkg/FmpDxe/FmpDxeLib.inf b/FmpDevicePkg/FmpDxe/FmpDxeLib.inf
index de005b6892..9a93b5e6ac 100644
--- a/FmpDevicePkg/FmpDxe/FmpDxeLib.inf
+++ b/FmpDevicePkg/FmpDxe/FmpDxeLib.inf
@@ -27,12 +27,10 @@
#
[Sources]
FmpDxe.c
FmpDxe.h
- Dependency.c
- Dependency.h
DetectTestKey.c
VariableSupport.h
VariableSupport.c
[Packages]
@@ -52,10 +50,13 @@
BaseCryptLib
FmpAuthenticationLib
FmpDeviceLib
FmpPayloadHeaderLib
CapsuleUpdatePolicyLib
+ FmpDependencyLib
+ FmpDependencyCheckLib
+ FmpDependencyDeviceLib
[Guids]
gEfiEndOfDxeEventGroupGuid
[Protocols]
--
2.16.2.windows.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [edk2-devel] [PATCH V3 1/5] FmpDevicePkg: Add FmpDependency library class and BASE instance
2020-05-14 21:52 ` [edk2-devel] [PATCH V3 1/5] FmpDevicePkg: Add FmpDependency library class and BASE instance Xu, Wei6
@ 2020-05-15 0:59 ` Sean
0 siblings, 0 replies; 7+ messages in thread
From: Sean @ 2020-05-15 0:59 UTC (permalink / raw)
To: devel, wei6.xu; +Cc: Michael D Kinney, Liming Gao, Sean Brogan
To keep api common please remove the CONST in ValidateDependency
function (header and c file). With that change my review applies to the
whole series.
After this stable tag it would be great to work on some documentation
for FmpDxe. This driver was already complex and has now got even more
complicated.
Reviewed-by: Sean Brogan <sean.brogan@microsoft.com>
On 5/14/2020 2:52 PM, Xu, Wei6 wrote:
> 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 <michael.d.kinney@intel.com>
> Cc: Liming Gao <liming.gao@intel.com>
> Cc: Sean Brogan <sean.brogan@microsoft.com>
> Signed-off-by: Wei6 Xu <wei6.xu@intel.com>
> ---
> 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.<BR>
> -# Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.<BR>
> +# Copyright (c) 2018 - 2020, Intel Corporation. All rights reserved.<BR>
> #
> # 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.<BR>
> -# Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.<BR>
> +# Copyright (c) 2018 - 2020, Intel Corporation. All rights reserved.<BR>
> # Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
> #
> # 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.<BR>
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#ifndef __FMP_DEPENDENCY_LIB__
> +#define __FMP_DEPENDENCY_LIB__
> +
> +#include <PiDxe.h>
> +#include <Protocol/FirmwareManagement.h>
> +
> +//
> +// 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.<BR>
> +
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +#include <PiDxe.h>
> +#include <Library/BaseLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/FmpDependencyLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +
> +//
> +// 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.<BR>
> +#
> +# 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.<BR>
> +//
> +// 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."
>
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2020-05-15 0:59 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2020-05-14 21:52 [edk2-devel] [PATCH V3 0/5] FmpDevicePkg: Move capsule dependency implement to library Xu, Wei6
2020-05-14 21:52 ` [edk2-devel] [PATCH V3 1/5] FmpDevicePkg: Add FmpDependency library class and BASE instance Xu, Wei6
2020-05-15 0:59 ` Sean
2020-05-14 21:52 ` [edk2-devel] [PATCH V3 2/5] FmpDevicePkg/Test: Add FmpDependencyLib unit test Xu, Wei6
2020-05-14 21:52 ` [edk2-devel] [PATCH V3 3/5] FmpDevicePkg: Add FmpDependencyCheck library class and instances Xu, Wei6
2020-05-14 21:52 ` [edk2-devel] [PATCH V3 4/5] FmpDevicePkg: Add FmpDependencyDevice library class and NULL instance Xu, Wei6
2020-05-14 21:52 ` [edk2-devel] [PATCH V3 5/5] FmpDevicePkg/FmpDxe: Use new Fmp dependency libraries Xu, Wei6
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox