[edk2-devel] [PATCH V3 3/5] FmpDevicePkg: Add FmpDependencyCheck library class and instances

Xu, Wei6 posted 5 patches 8 weeks ago

[edk2-devel] [PATCH V3 3/5] FmpDevicePkg: Add FmpDependencyCheck library class and instances

Posted by Xu, Wei6 8 weeks ago
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


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.

View/Reply Online (#59605): https://edk2.groups.io/g/devel/message/59605
Mute This Topic: https://groups.io/mt/74215663/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub  [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-