public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Sean" <spbrogan@outlook.com>
To: devel@edk2.groups.io, wei6.xu@intel.com
Cc: Michael D Kinney <michael.d.kinney@intel.com>,
	Liming Gao <liming.gao@intel.com>,
	Sean Brogan <sean.brogan@microsoft.com>
Subject: Re: [edk2-devel] [PATCH V3 1/5] FmpDevicePkg: Add FmpDependency library class and BASE instance
Date: Thu, 14 May 2020 17:59:07 -0700	[thread overview]
Message-ID: <BN8PR07MB6962C86CE609D366FD44EC5AC8BD0@BN8PR07MB6962.namprd07.prod.outlook.com> (raw)
In-Reply-To: <20200514215232.13372-2-wei6.xu@intel.com>

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."
> 

  reply	other threads:[~2020-05-15  0:59 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
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 [this message]
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

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=BN8PR07MB6962C86CE609D366FD44EC5AC8BD0@BN8PR07MB6962.namprd07.prod.outlook.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox