回复: [edk2-devel] [PATCH] MdeModulePkg/DxeCapsuleLibFmp: Add runtime SetImage support


gaoliming
 

Bob:
I suggest to obviously describe that FMP protocol services may be available in EFI runtime, and define the standard method to know whether FMP protocol supports runtime attribute.

Because UEFI spec is required to be updated, the code enhancement in DxeCapsuleLibFmp and FmpDevicePkg can go through code first process and be placed into edk2-staging first.

Thanks
Liming

-----邮件原件-----
发件人: devel@edk2.groups.io <devel@edk2.groups.io> 代表 Bob Morgan
via groups.io
发送时间: 2021年11月5日 6:53
收件人: devel@edk2.groups.io; gaoliming@...
抄送: 'Jian J Wang' <jian.j.wang@...>; 'Guomin Jiang'
<guomin.jiang@...>
主题: Re: [edk2-devel] [PATCH] MdeModulePkg/DxeCapsuleLibFmp: Add
runtime SetImage support

Hi Liming,

The Uefi spec Version 2.9 appears to have some inconsistencies regarding the
possibility of runtime processing of FMP capsules. The UpdateCapsule()
runtime service in Section 8.5.3 states that "the firmware may process the
capsule immediately", but in Section 23.3.1, where the FMP capsule is
described, the last paragraph states "By definition Firmware Management
protocol services are not available in EFI runtime".

I think the following spec changes would document the optional runtime FMP
capsule processing as implemented in this patch:

1. Reword Section 23.3.1 Description last paragraph, first sentence.
From: "By definition Firmware Management protocol services are not
available in EFI runtime and depending upon platform capabilities, EFI runtime
delivery of this capsule may not be supported and may return an error when
delivered in EFI runtime with CAPSULE_FLAGS_PERSIST_ACROSS_RESET bit
defined."

To something like this: "Depending upon platform capabilities, EFI runtime
delivery or processing of this capsule may not be supported and may return an
error when delivered in EFI runtime.

2. Reword Section 23.3.3 Step 3.
From: "If system is not in boot services and platform does not support
persistence of capsule across reset when initiated within EFI Runtime,
EFI_OUT_OF_RESOURCES error is returned."

To something like this: "If system is not in boot services and the
CAPSULE_FLAGS_PERSIST_ACROSS_RESET flag is set, but the platform does
not support persistence of capsule across reset when initiated within EFI
Runtime, EFI_OUT_OF_RESOURCES error is returned." <<<By the way,
UpdateCapsule() currently appears to return EFI_UNSUPPORTED in this case,
see the IsPersistAcrossResetCapsuleSupported () check near the end>>>

3. Add runtime FMP support info to Section 23.3.3 Step 3.
If system is not in boot services and the
CAPSULE_FLAGS_PERSIST_ACROSS_RESET flag is not set, but the platform
does not support processing of capsules within EFI Runtime,
EFI_OUT_OF_RESOURCES error is returned. If the platform supports
processing of capsules within EFI Runtime, steps 4-10 are not applicable and
the capsules are processed according to steps 11-14.

Let me know what you think and we can get an ECR process started to update
the spec.

Thanks,

-bob

-----Original Message-----
From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of gaoliming
via groups.io
Sent: Monday, November 1, 2021 7:17 PM
To: devel@edk2.groups.io; Bob Morgan <bobm@...>
Cc: 'Jian J Wang' <jian.j.wang@...>; 'Guomin Jiang'
<guomin.jiang@...>
Subject: 回复: [edk2-devel] [PATCH] MdeModulePkg/DxeCapsuleLibFmp:
Add runtime SetImage support

External email: Use caution opening links or attachments


Bob:
Thanks for your detail. PcdRuntimeFmpCapsuleImageTypeIdGuid is edk2
implementation solution. Have you the proposal on how to update UEFI spec
to support runtime FMP protocol?

Thanks
Liming
-----邮件原件-----
发件人: devel@edk2.groups.io <devel@edk2.groups.io> 代表 Bob
Morgan via
groups.io
发送时间: 2021年10月30日 1:59
收件人: gaoliming <gaoliming@...>; devel@edk2.groups.io
抄送: 'Jian J Wang' <jian.j.wang@...>; 'Guomin Jiang'
<guomin.jiang@...>
主题: Re: [edk2-devel] [PATCH] MdeModulePkg/DxeCapsuleLibFmp: Add
runtime SetImage support

Hi Liming, See inline below.

-----Original Message-----
From: gaoliming <gaoliming@...>
Sent: Thursday, October 28, 2021 7:57 PM
To: devel@edk2.groups.io; Bob Morgan <bobm@...>
Cc: 'Jian J Wang' <jian.j.wang@...>; 'Guomin Jiang'
<guomin.jiang@...>
Subject: 回复: [edk2-devel] [PATCH] MdeModulePkg/DxeCapsuleLibFmp:
Add runtime SetImage support

External email: Use caution opening links or attachments


Bob:
I think this patch needs to work together with the changes of
FmpDevicePkg: Add support for runtime FmpDxe driver.
Yes, this patch adds support to process FMP capsules at runtime if the
capsule’s UpdateImageTypeId is supported by a runtime-capable FmpDxe
driver (e.g. using the FmpDevicePkg patch you mentioned). The
PcdSupportProcessCapsuleAtRuntime PCD must be TRUE and the capsule’s
CAPSULE_FLAGS_PERSIST_ACROSS_RESET flag must be FALSE.

Capsule is runtime service. If it consumes FMP to do update, FMP
service can support runtime. But, how does Capsule know whether FMP
protocol supports runtime or not?
Right, this patch requires an implementation to list the FMP
ImageTypeId GUIDs supported by any runtime-capable FmpDxe drivers in
the new PcdRuntimeFmpCapsuleImageTypeIdGuid array PCD. This PCD is
used by the new InitializeRuntimeFmpArrays() function during
DxeRuntimeCapsuleLib initialization to find the FMP instances that
support those ImageTypeIds and save their
EFI_FIRMWARE_MANAGEMENT_PROTOCOL protocol structure pointers for
runtime use during capsule processing.

When ProcessFmpCapsuleImage() executes its step ‘2. Route payload to
right FMP instance’, it detects runtime execution and uses the saved
runtime-capable FMP protocol structure pointer if its ImageTypeId
matches that of the capsule being processed.

I hope that helps. Please let me know if additional clarification is needed.

Thanks,
-bob

Thanks
Liming
-----邮件原件-----
发件人: devel@edk2.groups.io <devel@edk2.groups.io> 代表 Bob
Morgan
via
groups.io
发送时间: 2021年10月20日 4:11
收件人: devel@edk2.groups.io
抄送: Bob Morgan <bobm@...>; Jian J Wang
<jian.j.wang@...>;
Liming Gao <gaoliming@...>; Guomin Jiang
<guomin.jiang@...>
主题: [edk2-devel] [PATCH] MdeModulePkg/DxeCapsuleLibFmp: Add
runtime
SetImage support

Adds optional support for processing FMP capusle images after
ExitBootServices() if the ImageTypeIdGuid is mentioned in the new
PcdRuntimeFmpCapsuleImageTypeIdGuid list.

Cc: Jian J Wang <jian.j.wang@...>
Cc: Liming Gao <gaoliming@...>
Cc: Guomin Jiang <guomin.jiang@...>
Signed-off-by: Bob Morgan <bobm@...>
---
.../Library/DxeCapsuleLibFmp/DxeCapsuleLib.c | 81 +++++++++---
.../DxeCapsuleLibFmp/DxeCapsuleRuntime.c | 119
++++++++++++++++++
.../DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf | 4 +
MdeModulePkg/MdeModulePkg.dec | 7 +-
4 files changed, 192 insertions(+), 19 deletions(-)

diff --git a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c
b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c
index 90942135d7..0000f91c6a 100644
--- a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c
+++ b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c
@@ -10,6 +10,7 @@
ValidateFmpCapsule(), and DisplayCapsuleImage() receives
untrusted input and
performs basic validation.

+ Copyright (c) 2021, NVIDIA CORPORATION. All rights
+ reserved.<BR>
Copyright (c) 2016 - 2019, Intel Corporation. All rights
reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent

@@ -41,6 +42,11 @@
#include <Protocol/FirmwareManagementProgress.h>
#include <Protocol/DevicePath.h>

+BOOLEAN (EFIAPI *mLibAtRuntimeFunction) (VOID)
=
NULL;
+EFI_FIRMWARE_MANAGEMENT_PROTOCOL *mRuntimeFmp
= NULL;
+VOID
**mRuntimeFmpProtocolArray
= NULL;
+EFI_GUID *mRuntimeFmpGuidArray
= NULL;
+
EFI_SYSTEM_RESOURCE_TABLE *mEsrtTable =
NULL;
BOOLEAN mIsVirtualAddrConverted =
FALSE;

@@ -551,6 +557,11 @@ DumpAllFmpInfo (
UINT32
PackageVersion;
CHAR16
*PackageVersionName;

+ // Dump not supported at runtime.
+ if ((mLibAtRuntimeFunction != NULL) && mLibAtRuntimeFunction ())
{
+ return;
+ }
+
Status = gBS->LocateHandleBuffer (
ByProtocol,
&gEfiFirmwareManagementProtocolGuid,
@@ -906,25 +917,35 @@ SetFmpImageData (
CHAR16
*AbortReason;
EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS
ProgressCallback;

- Status = gBS->HandleProtocol(
- Handle,
- &gEfiFirmwareManagementProtocolGuid,
- (VOID **)&Fmp
- );
- if (EFI_ERROR(Status)) {
- return Status;
- }
+ // If not using optional runtime support, get FMP protocol for
+ given
Handle.
+ // Otherwise, use the one saved by ProcessFmpCapsuleImage().
+ if ((mLibAtRuntimeFunction == NULL) || !mLibAtRuntimeFunction ())
{
+ Status = gBS->HandleProtocol(
+ Handle,
+ &gEfiFirmwareManagementProtocolGuid,
+ (VOID **)&Fmp
+ );
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }

- //
- // Lookup Firmware Management Progress Protocol before
SetImage() is called
- // This is an optional protocol that may not be present on Handle.
- //
- Status = gBS->HandleProtocol (
- Handle,
-
&gEdkiiFirmwareManagementProgressProtocolGuid,
- (VOID **)&mFmpProgress
- );
- if (EFI_ERROR (Status)) {
+ //
+ // Lookup Firmware Management Progress Protocol before
SetImage()
is called
+ // This is an optional protocol that may not be present on Handle.
+ //
+ Status = gBS->HandleProtocol (
+ Handle,
+
&gEdkiiFirmwareManagementProgressProtocolGuid,
+ (VOID **)&mFmpProgress
+ );
+ if (EFI_ERROR (Status)) {
+ mFmpProgress = NULL;
+ }
+ } else {
+ if (mRuntimeFmp == NULL) {
+ return EFI_UNSUPPORTED;
+ }
+ Fmp = mRuntimeFmp;
mFmpProgress = NULL;
}

@@ -1259,6 +1280,30 @@ ProcessFmpCapsuleImage (
UpdateHardwareInstance =
ImageHeader->UpdateHardwareInstance;
}

+ // Optional runtime FMP SetImage processing sequence
+ if ((mLibAtRuntimeFunction != NULL) && mLibAtRuntimeFunction
+ ()
&&
+ (mRuntimeFmpProtocolArray != NULL)) {
+ mRuntimeFmp = NULL;
+ Index2 = 0;
+ while (mRuntimeFmpProtocolArray[Index2] != NULL) {
+ if (CompareGuid (&ImageHeader->UpdateImageTypeId,
+ &mRuntimeFmpGuidArray[Index2])) {
+ mRuntimeFmp =
(EFI_FIRMWARE_MANAGEMENT_PROTOCOL
*)
+ mRuntimeFmpProtocolArray[Index2];
+ break;
+ }
+ Index2++;
+ }
+
+ Status = SetFmpImageData (NULL,
+ ImageHeader,
+ Index -
FmpCapsuleHeader->EmbeddedDriverCount);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ continue;
+ }
+
Status = GetFmpHandleBufferByType (
&ImageHeader->UpdateImageTypeId,
UpdateHardwareInstance, diff --git
a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleRuntime.c
b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleRuntime.c
index f94044a409..6feb6dab79 100644
--- a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleRuntime.c
+++
b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleRuntime.c
@@ -1,6 +1,7 @@
/** @file
Capsule library runtime support.

+ Copyright (c) 2021, NVIDIA CORPORATION. All rights
+ reserved.<BR>
Copyright (c) 2016 - 2017, Intel Corporation. All rights
reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent

@@ -19,7 +20,11 @@
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiRuntimeLib.h>

+extern BOOLEAN (EFIAPI
*mLibAtRuntimeFunction)
(VOID);
+extern VOID **mRuntimeFmpProtocolArray;
+extern EFI_GUID *mRuntimeFmpGuidArray;
extern EFI_SYSTEM_RESOURCE_TABLE *mEsrtTable;
extern BOOLEAN mIsVirtualAddrConverted;
EFI_EVENT
mDxeRuntimeCapsuleLibVirtualAddressChangeEvent = NULL; @@
-40,9
+45,121 @@ DxeCapsuleLibVirtualAddressChangeEvent (
)
{
gRT->ConvertPointer (EFI_OPTIONAL_PTR, (VOID **)&mEsrtTable);
+
+ if (mRuntimeFmpProtocolArray != NULL) {
+ VOID **FmpArrayEntry;
+
+ FmpArrayEntry = mRuntimeFmpProtocolArray;
+ while (*FmpArrayEntry != NULL) {
+ EfiConvertPointer (0x0, (VOID **) FmpArrayEntry);
+ FmpArrayEntry++;
+ }
+ EfiConvertPointer (0x0, (VOID **)
&mRuntimeFmpProtocolArray); }
+ if (mRuntimeFmpGuidArray != NULL) {
+ EfiConvertPointer (0x0, (VOID **) &mRuntimeFmpGuidArray); }
if
+ (mLibAtRuntimeFunction != NULL ) {
+ EfiConvertPointer (0x0, (VOID **) &mLibAtRuntimeFunction); }
+
mIsVirtualAddrConverted = TRUE; }

+/**
+ Initialize optional runtime FMP arrays to support FMP SetImage
processing
+ after ExitBootServices() is called.
+
+ The ImageTypeIdGuids of runtime-capable FMP protocol drivers
+ are
extracted
+ from the PcdRuntimeFmpCapsuleImageTypeIdGuid list and their
+ protocol structure pointers are saved in the
+ mRuntimeFmpProtocolArray for use
during
+ UpdateCapsule() processing. UpdateHardwareInstance is not
supported.
+
+**/
+STATIC
+VOID
+EFIAPI
+InitializeRuntimeFmpArrays (
+ VOID
+ )
+{
+ EFI_GUID *Guid;
+ UINTN NumHandles;
+ EFI_HANDLE *HandleBuffer;
+ EFI_STATUS Status;
+ UINTN Count;
+ UINTN Index;
+ UINTN FmpArrayIndex;
+
+ EFI_STATUS
+ GetFmpHandleBufferByType (
+ IN EFI_GUID
*UpdateImageTypeId,
+ IN UINT64
UpdateHardwareInstance,
+ OUT UINTN *NoHandles,
OPTIONAL
+ OUT EFI_HANDLE **HandleBuf,
OPTIONAL
+ OUT BOOLEAN
**ResetRequiredBuf
OPTIONAL
+ );
+
+ Count = PcdGetSize (PcdRuntimeFmpCapsuleImageTypeIdGuid) /
sizeof
(GUID);
+ if (Count == 0) {
+ return;
+ }
+
+ // mRuntimeFmpProtocolArray is a NULL-terminated list of FMP
+ protocol
pointers
+ mRuntimeFmpProtocolArray = (VOID **)
+ AllocateRuntimeZeroPool ((Count + 1) * sizeof (VOID *)); if
+ (mRuntimeFmpProtocolArray == NULL) {
+ DEBUG ((DEBUG_ERROR, "Error allocating
mRuntimeFmpProtocolArray\n"));
+ return;
+ }
+ mRuntimeFmpGuidArray = (EFI_GUID *)
+ AllocateRuntimeZeroPool (Count * sizeof (EFI_GUID)); if
+ (mRuntimeFmpGuidArray == NULL) {
+ DEBUG ((DEBUG_ERROR, "Error allocating
mRuntimeFmpGuidArray"));
+ FreePool (mRuntimeFmpProtocolArray);
+ return;
+ }
+
+ // For each runtime ImageTypeIdGuid in the PCD, save its GUID
+ and FMP
protocol
+ FmpArrayIndex = 0;
+ Guid = PcdGetPtr (PcdRuntimeFmpCapsuleImageTypeIdGuid);
+ for (Index = 0; Index < Count; Index++, Guid++) {
+ mRuntimeFmpGuidArray[FmpArrayIndex] = *Guid;
+ HandleBuffer = NULL;
+ Status = GetFmpHandleBufferByType (Guid,
+ 0,
+ &NumHandles,
+ &HandleBuffer,
+ NULL);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR,
+ "Error finding FMP handle for runtime
ImageTypeIdGuid=%g: %r\n",
+ Guid, Status));
+ continue;
+ }
+
+ if (NumHandles > 1) {
+ DEBUG ((DEBUG_ERROR,
+ "FMP runtime ImageTypeIdGuid=%g returned %u
handles,
only 1 supported\n",
+ Guid, NumHandles));
+ }
+ Status = gBS->HandleProtocol (HandleBuffer[0],
+
&gEfiFirmwareManagementProtocolGuid,
+
&mRuntimeFmpProtocolArray[FmpArrayIndex]);
+ FreePool (HandleBuffer);
+ if (EFI_ERROR(Status)) {
+ DEBUG ((DEBUG_ERROR,
+ "Error getting FMP protocol for runtime
ImageTypeIdGuid=%g: %r\n",
+ Guid, Status));
+ continue;
+ }
+
+ FmpArrayIndex++;
+ }
+
+ mLibAtRuntimeFunction = EfiAtRuntime; }
+
/**
Notify function for event group
EFI_EVENT_GROUP_READY_TO_BOOT.

@@ -93,6 +210,8 @@ DxeCapsuleLibReadyToBootEventNotify (
//
mEsrtTable->FwResourceCountMax =
mEsrtTable->FwResourceCount;
}
+
+ InitializeRuntimeFmpArrays ();
}

/**
diff --git
a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf
b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf
index bf56f4623f..7b3f5e04f8 100644
---
a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf
+++
b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf
@@ -49,6 +49,7 @@
PrintLib
HobLib
BmpSupportLib
+ PcdLib


[Protocols]
@@ -70,5 +71,8 @@
gEfiEventVirtualAddressChangeGuid ## CONSUMES ##
Event
gEdkiiCapsuleOnDiskNameGuid ##
SOMETIMES_CONSUMES ## GUID

+[Pcd]
+
gEfiMdeModulePkgTokenSpaceGuid.PcdRuntimeFmpCapsuleImageTypeIdG
ui
d
+
[Depex]
gEfiVariableWriteArchProtocolGuid diff --git
a/MdeModulePkg/MdeModulePkg.dec
b/MdeModulePkg/MdeModulePkg.dec
index 133e04ee86..869aa892f7
100644
--- a/MdeModulePkg/MdeModulePkg.dec
+++ b/MdeModulePkg/MdeModulePkg.dec
@@ -3,7 +3,7 @@
# It also provides the definitions(including PPIs/PROTOCOLs/GUIDs
and library classes) # and libraries instances, which are used
for those modules.
#
-# Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved.
+# Copyright (c) 2019-2021, NVIDIA CORPORATION. All rights
+reserved.<BR>
# Copyright (c) 2007 - 2021, Intel Corporation. All rights
reserved.<BR> # Copyright (c) 2016, Linaro Ltd. All rights
reserved.<BR> # (C) Copyright 2016 - 2019 Hewlett Packard
Enterprise Development LP<BR> @@ -2020,6 +2020,11 @@
# @Prompt Capsule On Disk Temp Relocation file name in PEI
phase

gEfiMdeModulePkgTokenSpaceGuid.PcdCoDRelocationFileName|L"Cod.tmp
"|
VOID*|0x30001048

+ ## This PCD holds a list of GUIDs for the ImageTypeId to
+ indicate the # FMP is runtime capable.
+ # @Prompt A list of runtime-capable FMP ImageTypeId GUIDs
+
gEfiMdeModulePkgTokenSpaceGuid.PcdRuntimeFmpCapsuleImageTypeIdG
ui
d|{0x0}|VOID*|0x30001049
+
## This PCD hold a list GUIDs for the ImageTypeId to indicate the
# FMP capsule is a system FMP.
# @Prompt A list of system FMP ImageTypeId GUIDs
--
2.17.1

















Join {devel@edk2.groups.io to automatically receive all group messages.