From 5925977a4e713dcec3ad34f1ee5362fb1bf8ea18 Mon Sep 17 00:00:00 2001 From: Tuan Phan Date: Thu, 27 Mar 2025 14:33:35 -0700 Subject: [PATCH] OvmfPkg/RiscVVirt: Add support for Capsule Firmware Upgrade This patch introduces support for firmware upgrades using the FMP capsule update mechanism. Signed-off-by: Tuan Phan --- OvmfPkg/OvmfPkg.ci.yaml | 3 +- .../Capsule/GenerateCapsule/GenCapsule.py | 332 ++++++++ .../CapsuleUpdatePolicyLib.c | 121 +++ .../CapsuleUpdatePolicyLib.inf | 29 + .../CapsuleUpdatePolicyLib.uni | 12 + .../Library/FmpDeviceLib/FmpDeviceLib.c | 774 ++++++++++++++++++ .../Library/FmpDeviceLib/FmpDeviceLib.inf | 46 ++ .../PlatformFlashAccessLib.c | 233 ++++++ .../PlatformFlashAccessLib.h | 95 +++ .../PlatformFlashAccessLib.inf | 34 + OvmfPkg/RiscVVirt/RiscVVirtQemu.dsc | 39 + OvmfPkg/RiscVVirt/RiscVVirtQemu.fdf | 5 + OvmfPkg/RiscVVirt/RiscVVirtSystemFW.dsc.inc | 61 ++ 13 files changed, 1783 insertions(+), 1 deletion(-) create mode 100644 OvmfPkg/RiscVVirt/Feature/Capsule/GenerateCapsule/GenCapsule.py create mode 100644 OvmfPkg/RiscVVirt/Feature/Capsule/Library/CapsuleUpdatePolicyLib/CapsuleUpdatePolicyLib.c create mode 100644 OvmfPkg/RiscVVirt/Feature/Capsule/Library/CapsuleUpdatePolicyLib/CapsuleUpdatePolicyLib.inf create mode 100644 OvmfPkg/RiscVVirt/Feature/Capsule/Library/CapsuleUpdatePolicyLib/CapsuleUpdatePolicyLib.uni create mode 100644 OvmfPkg/RiscVVirt/Feature/Capsule/Library/FmpDeviceLib/FmpDeviceLib.c create mode 100644 OvmfPkg/RiscVVirt/Feature/Capsule/Library/FmpDeviceLib/FmpDeviceLib.inf create mode 100644 OvmfPkg/RiscVVirt/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.c create mode 100644 OvmfPkg/RiscVVirt/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.h create mode 100644 OvmfPkg/RiscVVirt/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.inf create mode 100644 OvmfPkg/RiscVVirt/RiscVVirtSystemFW.dsc.inc diff --git a/OvmfPkg/OvmfPkg.ci.yaml b/OvmfPkg/OvmfPkg.ci.yaml index 62f3aef3c5..f44c1b8f2d 100644 --- a/OvmfPkg/OvmfPkg.ci.yaml +++ b/OvmfPkg/OvmfPkg.ci.yaml @@ -54,7 +54,8 @@ "ShellPkg/ShellPkg.dec", "EmbeddedPkg/EmbeddedPkg.dec", "SourceLevelDebugPkg/SourceLevelDebugPkg.dec", - "StandaloneMmPkg/StandaloneMmPkg.dec" + "StandaloneMmPkg/StandaloneMmPkg.dec", + "FmpDevicePkg/FmpDevicePkg.dec" ], # For host based unit tests "AcceptableDependencies-HOST_APPLICATION":[ diff --git a/OvmfPkg/RiscVVirt/Feature/Capsule/GenerateCapsule/GenCapsule.py b/OvmfPkg/RiscVVirt/Feature/Capsule/GenerateCapsule/GenCapsule.py new file mode 100644 index 0000000000..1889328fb9 --- /dev/null +++ b/OvmfPkg/RiscVVirt/Feature/Capsule/GenerateCapsule/GenCapsule.py @@ -0,0 +1,332 @@ +## @file +# Generate capsules for RiscVVirt platform +# openssl, gcab must be install and in path +# +# Copyright (c) 2019, Intel Corporation. All rights reserved.
+# Copyright (c) 2025, Ventana Micro Systems Inc. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +''' +GenCapsuleAll +''' + +import os +import sys +import argparse +import subprocess +import glob +import shutil +import struct +import datetime + +# +# Globals for help information +# +__prog__ = 'GenCapsuleAll' +__copyright__ = 'Copyright (c) 2019, Intel Corporation. All rights reserved.' +__description__ = 'Generate RiscVVirt capsules.\n' + +# +# Globals +# +gWorkspace = '' +gBaseToolsPath = '' +gArgs = None + +def LogAlways(Message): + sys.stdout.write (__prog__ + ': ' + Message + '\n') + sys.stdout.flush() + +def Log(Message): + global gArgs + if not gArgs.Verbose: + return + sys.stdout.write (__prog__ + ': ' + Message + '\n') + sys.stdout.flush() + +def Error(Message, ExitValue=1): + sys.stderr.write (__prog__ + ': ERROR: ' + Message + '\n') + sys.exit (ExitValue) + +def RelativePath(target): + global gWorkspace + Log('RelativePath' + target) + return os.path.relpath (target, gWorkspace) + +def NormalizePath(target): + if isinstance(target, tuple): + return os.path.normpath (os.path.join (*target)) + else: + return os.path.normpath (target) + +def RemoveFile(target): + target = NormalizePath(target) + if not target or target == os.pathsep: + Error ('RemoveFile() invalid target') + if os.path.exists(target): + os.remove (target) + Log ('remove %s' % (RelativePath (target))) + +def RemoveDirectory(target): + target = NormalizePath(target) + if not target or target == os.pathsep: + Error ('RemoveDirectory() invalid target') + if os.path.exists(target): + Log ('rmdir %s' % (RelativePath (target))) + shutil.rmtree(target) + +def CreateDirectory(target): + target = NormalizePath(target) + if not os.path.exists(target): + Log ('mkdir %s' % (RelativePath (target))) + os.makedirs (target) + +def Copy(src, dst): + src = NormalizePath(src) + dst = NormalizePath(dst) + for File in glob.glob(src): + Log ('copy %s -> %s' % (RelativePath (File), RelativePath (dst))) + shutil.copy (File, dst) + +GenerateCapsuleCommand = ''' +GenerateCapsule +--encode +--guid {FMP_CAPSULE_GUID} +--fw-version {FMP_CAPSULE_VERSION} +--lsv {FMP_CAPSULE_LSV} +--signer-private-cert={BASE_TOOLS_PATH}/Source/Python/Pkcs7Sign/TestCert.pem +--other-public-cert={BASE_TOOLS_PATH}/Source/Python/Pkcs7Sign/TestSub.pub.pem +--trusted-public-cert={BASE_TOOLS_PATH}/Source/Python/Pkcs7Sign/TestRoot.pub.pem +-o {FMP_CAPSULE_FILE} +{FMP_CAPSULE_PAYLOAD} +''' +MetaInfoXmlTemplate = ''' + + + com.intel.FMP_CAPSULE_BASE_NAME.firmware + FMP_CAPSULE_BASE_NAME + System firmware for the FMP_CAPSULE_BASE_NAME + + Description of System firmware for the FMP_CAPSULE_BASE_NAME + + + FMP_CAPSULE_GUID + + http://www.tianocore.org + CC0-1.0 + BSD + Tianocore + + + + Build FMP_CAPSULE_STRING + + + + + + + + +''' + +def GenCapsuleDevice (BaseName, PayloadFileName, Guid, Version, Lsv, CapsulesPath, CapsulesSubDir): + global gBaseToolsPath + LogAlways ('Generate Capsule: {0} {1:08x} {2:08x} {3}'.format (Guid, Version, Lsv, PayloadFileName)) + + VersionString = '.'.join([str(ord(x)) for x in struct.pack('>I', Version).decode()]) + + FmpCapsuleFile = NormalizePath ((CapsulesPath, CapsulesSubDir, BaseName + '.' + VersionString + '.cap')) + Command = GenerateCapsuleCommand.format ( + FMP_CAPSULE_GUID = Guid, + FMP_CAPSULE_VERSION = Version, + FMP_CAPSULE_LSV = Lsv, + BASE_TOOLS_PATH = gBaseToolsPath, + FMP_CAPSULE_FILE = FmpCapsuleFile, + FMP_CAPSULE_PAYLOAD = PayloadFileName + ) + Command = ' '.join(Command.splitlines()).strip() + if gArgs.Verbose: + Command = Command + ' -v' + + Log (Command) + + Process = subprocess.Popen(Command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) + ProcessOutput = Process.communicate() + + if Process.returncode == 0: + Log (ProcessOutput[0].decode()) + else: + LogAlways (Command) + LogAlways (ProcessOutput[0].decode()) + Error ('GenerateCapsule returned an error') + + Copy (PayloadFileName, (CapsulesPath, 'firmware.bin')) + MetaInfoXml = MetaInfoXmlTemplate + MetaInfoXml = MetaInfoXml.replace ('FMP_CAPSULE_GUID', Guid) + MetaInfoXml = MetaInfoXml.replace ('FMP_CAPSULE_BASE_NAME', BaseName) + MetaInfoXml = MetaInfoXml.replace ('FMP_CAPSULE_VERSION_DECIMAL', str(Version)) + MetaInfoXml = MetaInfoXml.replace ('FMP_CAPSULE_STRING', VersionString) + MetaInfoXml = MetaInfoXml.replace ('FMP_CAPSULE_DATE', str(datetime.date.today())) + f = open (NormalizePath ((CapsulesPath, 'firmware.metainfo.xml')), 'w') + f.write(MetaInfoXml) + f.close() + + Command = 'gcab --create firmware.cab firmware.bin firmware.metainfo.xml' + Log (Command) + + Process = subprocess.Popen(Command, cwd=CapsulesPath, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) + ProcessOutput = Process.communicate() + + if Process.returncode == 0: + Log (ProcessOutput[0].decode()) + else: + LogAlways (Command) + LogAlways (ProcessOutput[0].decode()) + Error ('GenerateCapsule returned an error') + + FmpCabinetFile = NormalizePath ((CapsulesPath, CapsulesSubDir, BaseName + '.' + VersionString + '.cab')) + + Copy ((CapsulesPath, 'firmware.cab'), FmpCabinetFile) + + RemoveFile ((CapsulesPath, 'firmware.cab')) + RemoveFile ((CapsulesPath, 'firmware.metainfo.xml')) + RemoveFile ((CapsulesPath, 'firmware.bin')) + +if __name__ == '__main__': + # + # Create command line argument parser object + # + parser = argparse.ArgumentParser ( + prog = __prog__, + description = __description__ + __copyright__, + conflict_handler = 'resolve' + ) + parser.add_argument ( + '-a', '--arch', dest = 'Arch', nargs = '+', action = 'append', + required = True, + help = '''ARCHS is one of list: IA32, X64, IPF, ARM, AARCH64, RISCV64 + or EBC, which overrides target.txt's TARGET_ARCH definition. + To specify more archs, please repeat this option.''' + ) + parser.add_argument ( + '-t', '--tagname', dest = 'ToolChain', required = True, + help = '''Using the Tool Chain Tagname to build the platform, + overriding target.txt's TOOL_CHAIN_TAG definition.''' + ) + parser.add_argument ( + '-p', '--platform', dest = 'PlatformFile', required = True, + help = '''Build the platform specified by the DSC file name argument, + overriding target.txt's ACTIVE_PLATFORM definition.''' + ) + parser.add_argument ( + '-b', '--buildtarget', dest = 'BuildTarget', required = True, + help = '''Using the TARGET to build the platform, overriding + target.txt's TARGET definition.''' + ) + parser.add_argument ( + '--conf=', dest = 'ConfDirectory', required = True, + help = '''Specify the customized Conf directory.''' + ) + parser.add_argument ( + '-D', '--define', dest = 'Define', nargs='*', action = 'append', + help = '''Macro: "Name [= Value]".''' + ) + parser.add_argument ( + '-v', '--verbose', dest = 'Verbose', action = 'store_true', + help = '''Turn on verbose output with informational messages printed''' + ) + parser.add_argument ( + '--package', dest = 'Package', nargs = '*', action = 'append', + help = '''The directory name of a package of tests to copy''' + ) + + # + # Parse command line arguments + # + gArgs, remaining = parser.parse_known_args() + gArgs.BuildType = 'all' + for BuildType in ['all', 'fds', 'genc', 'genmake', 'clean', 'cleanall', 'modules', 'libraries', 'run']: + if BuildType in remaining: + gArgs.BuildType = BuildType + remaining.remove(BuildType) + break + gArgs.Remaining = ' '.join(remaining) + + # + # Get WORKSPACE environment variable + # + try: + gWorkspace = os.environ['WORKSPACE'] + except: + Error ('WORKSPACE environment variable not set') + + # + # Get PACKAGES_PATH and generate prioritized list of paths + # + PathList = [gWorkspace] + try: + PathList += os.environ['PACKAGES_PATH'].split(os.pathsep) + except: + pass + + # + # Determine full path to BaseTools + # + for Path in PathList: + if os.path.exists (os.path.join (Path, 'BaseTools')): + gBaseToolsPath = os.path.join (Path, 'BaseTools') + break + + # + # Parse PLATFORM_NAME from DSC file + # + for Path in PathList: + if os.path.exists (os.path.join (Path, gArgs.PlatformFile)): + Dsc = open (os.path.join (Path, gArgs.PlatformFile), 'r').readlines() + break + for Line in Dsc: + if Line.strip().startswith('PLATFORM_NAME'): + OutputDirectory = os.path.join ('Build', Line.strip().split('=')[1].strip()) + break + + # + # Determine full paths to EDK II build directory, EDK II build output + # directory and the CPU arch of the UEFI phase. + # + CommandDir = os.path.dirname(sys.argv[0]) + EdkiiBuildDir = os.path.join (gWorkspace, OutputDirectory) + EdkiiBuildOutput = os.path.join (EdkiiBuildDir, gArgs.BuildTarget + '_' + gArgs.ToolChain) + UefiArch = gArgs.Arch[0][0] + if len (gArgs.Arch) > 1: + if ['RISCV64'] in gArgs.Arch: + UefiArch = 'RISCV64' + + CapsulesPath = NormalizePath((EdkiiBuildDir, 'Capsules')) + + CapsulesSubDir = 'TestCert' + '_' + UefiArch + '_' + gArgs.BuildTarget + '_' + gArgs.ToolChain + + # + # Create output directories + # + try: + CreateDirectory ((CapsulesPath)) + except: + pass + try: + CreateDirectory ((CapsulesPath, CapsulesSubDir)) + except: + pass + + # + # Copy CapsuleApp + # + Copy ((EdkiiBuildOutput, UefiArch, 'CapsuleApp.efi'), (CapsulesPath, CapsulesSubDir)) + + # + # Generate capsules for RiscVVirt Firmware Updates + # + CodeFW = os.path.join (EdkiiBuildOutput, 'FV', 'RISCV_VIRT_CODE.fd') + GenCapsuleDevice('RISCVVIRT', CodeFW,'bcbacac2-1d1d-4c14-89a3-5e27496b702d',0x00010000,0x00000000, CapsulesPath, CapsulesSubDir) diff --git a/OvmfPkg/RiscVVirt/Feature/Capsule/Library/CapsuleUpdatePolicyLib/CapsuleUpdatePolicyLib.c b/OvmfPkg/RiscVVirt/Feature/Capsule/Library/CapsuleUpdatePolicyLib/CapsuleUpdatePolicyLib.c new file mode 100644 index 0000000000..3d1adfac18 --- /dev/null +++ b/OvmfPkg/RiscVVirt/Feature/Capsule/Library/CapsuleUpdatePolicyLib/CapsuleUpdatePolicyLib.c @@ -0,0 +1,121 @@ +/** @file + Provides platform policy services used during a capsule update. + + Copyright (c) 2016, Microsoft Corporation. All rights reserved.
+ Copyright (c) 2018, Intel Corporation. All rights reserved.
+ Copyright (c) 2025, Ventana Micro Systems Inc. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include + +/** + Determine if the system power state supports a capsule update. + + @param[out] Good Returns TRUE if system power state supports a capsule + update. Returns FALSE if system power state does not + support a capsule update. Return value is only valid if + return status is EFI_SUCCESS. + + @retval EFI_SUCCESS Good parameter has been updated with result. + @retval EFI_INVALID_PARAMETER Good is NULL. + @retval EFI_DEVICE_ERROR System power state can not be determined. + +**/ +EFI_STATUS +EFIAPI +CheckSystemPower ( + OUT BOOLEAN *Good + ) +{ + *Good = TRUE; + return EFI_SUCCESS; +} + +/** + Determines if the system thermal state supports a capsule update. + + @param[out] Good Returns TRUE if system thermal state supports a capsule + update. Returns FALSE if system thermal state does not + support a capsule update. Return value is only valid if + return status is EFI_SUCCESS. + + @retval EFI_SUCCESS Good parameter has been updated with result. + @retval EFI_INVALID_PARAMETER Good is NULL. + @retval EFI_DEVICE_ERROR System thermal state can not be determined. + +**/ +EFI_STATUS +EFIAPI +CheckSystemThermal ( + OUT BOOLEAN *Good + ) +{ + *Good = TRUE; + return EFI_SUCCESS; +} + +/** + Determines if the system environment state supports a capsule update. + + @param[out] Good Returns TRUE if system environment state supports a capsule + update. Returns FALSE if system environment state does not + support a capsule update. Return value is only valid if + return status is EFI_SUCCESS. + + @retval EFI_SUCCESS Good parameter has been updated with result. + @retval EFI_INVALID_PARAMETER Good is NULL. + @retval EFI_DEVICE_ERROR System environment state can not be determined. + +**/ +EFI_STATUS +EFIAPI +CheckSystemEnvironment ( + OUT BOOLEAN *Good + ) +{ + *Good = TRUE; + return EFI_SUCCESS; +} + +/** + Determines if the Lowest Supported Version checks should be performed. The + expected result from this function is TRUE. A platform can choose to return + FALSE (e.g. during manufacturing or servicing) to allow a capsule update to a + version below the current Lowest Supported Version. + + @retval TRUE The lowest supported version check is required. + @retval FALSE Do not perform lowest support version check. + +**/ +BOOLEAN +EFIAPI +IsLowestSupportedVersionCheckRequired ( + VOID + ) +{ + return TRUE; +} + +/** + Determines if the FMP device should be locked when the event specified by + PcdFmpDeviceLockEventGuid is signaled. The expected result from this function + is TRUE so the FMP device is always locked. A platform can choose to return + FALSE (e.g. during manufacturing) to allow FMP devices to remain unlocked. + + @retval TRUE The FMP device lock action is required at lock event guid. + @retval FALSE Do not perform FMP device lock at lock event guid. + +**/ +BOOLEAN +EFIAPI +IsLockFmpDeviceAtLockEventGuidRequired ( + VOID + ) +{ + // Not lock FMP device for this platform + return FALSE; +} diff --git a/OvmfPkg/RiscVVirt/Feature/Capsule/Library/CapsuleUpdatePolicyLib/CapsuleUpdatePolicyLib.inf b/OvmfPkg/RiscVVirt/Feature/Capsule/Library/CapsuleUpdatePolicyLib/CapsuleUpdatePolicyLib.inf new file mode 100644 index 0000000000..5008100e51 --- /dev/null +++ b/OvmfPkg/RiscVVirt/Feature/Capsule/Library/CapsuleUpdatePolicyLib/CapsuleUpdatePolicyLib.inf @@ -0,0 +1,29 @@ +## @file +# Provides platform policy services used during a capsule update. +# +# Copyright (c) 2016, Microsoft Corporation. All rights reserved.
+# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# Copyright (c) 2025, Ventana Micro Systems Inc. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +## + +[Defines] + INF_VERSION = 1.30 + BASE_NAME = CapsuleUpdatePolicyLib + MODULE_UNI_FILE = CapsuleUpdatePolicyLib.uni + FILE_GUID = 3ed188f7-7aba-47ff-bdeb-2ac23287a5ea + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = CapsuleUpdatePolicyLib + +# +# VALID_ARCHITECTURES = RISCV64 +# + +[Sources] + CapsuleUpdatePolicyLib.c + +[Packages] + MdePkg/MdePkg.dec + FmpDevicePkg/FmpDevicePkg.dec diff --git a/OvmfPkg/RiscVVirt/Feature/Capsule/Library/CapsuleUpdatePolicyLib/CapsuleUpdatePolicyLib.uni b/OvmfPkg/RiscVVirt/Feature/Capsule/Library/CapsuleUpdatePolicyLib/CapsuleUpdatePolicyLib.uni new file mode 100644 index 0000000000..d26e716b11 --- /dev/null +++ b/OvmfPkg/RiscVVirt/Feature/Capsule/Library/CapsuleUpdatePolicyLib/CapsuleUpdatePolicyLib.uni @@ -0,0 +1,12 @@ +// /** @file +// Provides platform policy services used during a capsule update. +// +// Copyright (c) 2018, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + +#string STR_MODULE_ABSTRACT #language en-US "Provides platform policy services used during a capsule update." + +#string STR_MODULE_DESCRIPTION #language en-US "Provides platform policy services used during a capsule update." diff --git a/OvmfPkg/RiscVVirt/Feature/Capsule/Library/FmpDeviceLib/FmpDeviceLib.c b/OvmfPkg/RiscVVirt/Feature/Capsule/Library/FmpDeviceLib/FmpDeviceLib.c new file mode 100644 index 0000000000..4fe21b763d --- /dev/null +++ b/OvmfPkg/RiscVVirt/Feature/Capsule/Library/FmpDeviceLib/FmpDeviceLib.c @@ -0,0 +1,774 @@ +/** @file + Provides firmware device specific services to support updates of a firmware + image stored in a firmware device. + + Copyright (c) Microsoft Corporation.
+ Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.
+ Copyright (c) 2025, Ventana Micro Systems Inc. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include "../PlatformFlashAccessLib/PlatformFlashAccessLib.h" + +#define __BUILD_STRING(x) L ## #x +#define BUILD_STRING(x) L"build #" __BUILD_STRING(x) +#define CURRENT_FIRMWARE_VERSION FixedPcdGet32 (PcdFirmwareRevision) +#define CURRENT_FIRMWARE_VERSION_STRING BUILD_STRING (CURRENT_FIRMWARE_VERSION) + +typedef struct { + PLATFORM_FIRMWARE_TYPE FirmwareType; + FLASH_ADDRESS_TYPE AddressType; + EFI_PHYSICAL_ADDRESS BaseAddress; + UINTN Length; + UINTN ImageOffset; +} UPDATE_CONFIG_DATA; + +UPDATE_CONFIG_DATA mUpdateConfigData[] = { + { PlatformFirmwareTypeSystemFirmware, FlashAddressTypeAbsoluteAddress, 0x20000000, 0x00800000, 0x00000000 }, +}; + +/** + Provide a function to install the Firmware Management Protocol instance onto a + device handle when the device is managed by a driver that follows the UEFI + Driver Model. If the device is not managed by a driver that follows the UEFI + Driver Model, then EFI_UNSUPPORTED is returned. + + @param[in] FmpInstaller Function that installs the Firmware Management + Protocol. + + @retval EFI_SUCCESS The device is managed by a driver that follows the + UEFI Driver Model. FmpInstaller must be called on + each Driver Binding Start(). + @retval EFI_UNSUPPORTED The device is not managed by a driver that follows + the UEFI Driver Model. + @retval other The Firmware Management Protocol for this firmware + device is not installed. The firmware device is + still locked using FmpDeviceLock(). + +**/ +EFI_STATUS +EFIAPI +RegisterFmpInstaller ( + IN FMP_DEVICE_LIB_REGISTER_FMP_INSTALLER Function + ) +{ + // + // This is a system firmware update that does not use Driver Binding Protocol + // + return EFI_UNSUPPORTED; +} + +/** + Provide a function to uninstall the Firmware Management Protocol instance from a + device handle when the device is managed by a driver that follows the UEFI + Driver Model. If the device is not managed by a driver that follows the UEFI + Driver Model, then EFI_UNSUPPORTED is returned. + + @param[in] FmpUninstaller Function that installs the Firmware Management + Protocol. + + @retval EFI_SUCCESS The device is managed by a driver that follows the + UEFI Driver Model. FmpUninstaller must be called on + each Driver Binding Stop(). + @retval EFI_UNSUPPORTED The device is not managed by a driver that follows + the UEFI Driver Model. + @retval other The Firmware Management Protocol for this firmware + device is not installed. The firmware device is + still locked using FmpDeviceLock(). + +**/ +EFI_STATUS +EFIAPI +RegisterFmpUninstaller ( + IN FMP_DEVICE_LIB_REGISTER_FMP_UNINSTALLER Function + ) +{ + // + // This is a system firmware update that does not use Driver Binding Protocol + // + return EFI_UNSUPPORTED; +} + +/** + Set the device context for the FmpDeviceLib services when the device is + managed by a driver that follows the UEFI Driver Model. If the device is not + managed by a driver that follows the UEFI Driver Model, then EFI_UNSUPPORTED + is returned. Once a device context is set, the FmpDeviceLib services + operate on the currently set device context. + + @param[in] Handle Device handle for the FmpDeviceLib services. + If Handle is NULL, then Context is freed. + @param[in, out] Context Device context for the FmpDeviceLib services. + If Context is NULL, then a new context is allocated + for Handle and the current device context is set and + returned in Context. If Context is not NULL, then + the current device context is set. + + @retval EFI_SUCCESS The device is managed by a driver that follows the + UEFI Driver Model. + @retval EFI_UNSUPPORTED The device is not managed by a driver that follows + the UEFI Driver Model. + @retval other The Firmware Management Protocol for this firmware + device is not installed. The firmware device is + still locked using FmpDeviceLock(). + +**/ +EFI_STATUS +EFIAPI +FmpDeviceSetContext ( + IN EFI_HANDLE Handle, + IN OUT VOID **Context + ) +{ + // + // This is a system firmware update that does not use Driver Binding Protocol + // + return EFI_UNSUPPORTED; +} + +/** + Returns the size, in bytes, of the firmware image currently stored in the + firmware device. This function is used to by the GetImage() and + GetImageInfo() services of the Firmware Management Protocol. If the image + size can not be determined from the firmware device, then 0 must be returned. + + @param[out] Size Pointer to the size, in bytes, of the firmware image + currently stored in the firmware device. + + @retval EFI_SUCCESS The size of the firmware image currently + stored in the firmware device was returned. + @retval EFI_INVALID_PARAMETER Size is NULL. + @retval EFI_UNSUPPORTED The firmware device does not support reporting + the size of the currently stored firmware image. + @retval EFI_DEVICE_ERROR An error occurred attempting to determine the + size of the firmware image currently stored in + in the firmware device. + +**/ +EFI_STATUS +EFIAPI +FmpDeviceGetSize ( + OUT UINTN *Size + ) +{ + if (Size == NULL) { + return EFI_INVALID_PARAMETER; + } + + return EFI_UNSUPPORTED; +} + +/** + Returns the GUID value used to fill in the ImageTypeId field of the + EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is returned by the GetImageInfo() + service of the Firmware Management Protocol. If EFI_UNSUPPORTED is returned, + then the ImageTypeId field is set to gEfiCallerIdGuid. If EFI_SUCCESS is + returned, then ImageTypeId is set to the Guid returned from this function. + + @param[out] Guid Double pointer to a GUID value that is updated to point to + to a GUID value. The GUID value is not allocated and must + not be modified or freed by the caller. + + @retval EFI_SUCCESS EFI_FIRMWARE_IMAGE_DESCRIPTOR ImageTypeId GUID is set + to the returned Guid value. + @retval EFI_UNSUPPORTED EFI_FIRMWARE_IMAGE_DESCRIPTOR ImageTypeId GUID is set + to gEfiCallerIdGuid. + +**/ +EFI_STATUS +EFIAPI +FmpDeviceGetImageTypeIdGuidPtr ( + OUT EFI_GUID **Guid + ) +{ + *Guid = &gEfiCallerIdGuid; + + return EFI_SUCCESS; +} + +/** + Returns values used to fill in the AttributesSupported and AttributesSettings + fields of the EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is returned by the + GetImageInfo() service of the Firmware Management Protocol. The following + bit values from the Firmware Management Protocol may be combined: + IMAGE_ATTRIBUTE_IMAGE_UPDATABLE + IMAGE_ATTRIBUTE_RESET_REQUIRED + IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED + IMAGE_ATTRIBUTE_IN_USE + IMAGE_ATTRIBUTE_UEFI_IMAGE + + @param[out] Supported Attributes supported by this firmware device. + @param[out] Setting Attributes settings for this firmware device. + + @retval EFI_SUCCESS The attributes supported by the firmware + device were returned. + @retval EFI_INVALID_PARAMETER Supported is NULL. + @retval EFI_INVALID_PARAMETER Setting is NULL. + +**/ +EFI_STATUS +EFIAPI +FmpDeviceGetAttributes ( + OUT UINT64 *Supported, + OUT UINT64 *Setting + ) +{ + if ((Supported == NULL) || (Setting == NULL)) { + return EFI_INVALID_PARAMETER; + } + + *Supported = (IMAGE_ATTRIBUTE_IMAGE_UPDATABLE | + IMAGE_ATTRIBUTE_RESET_REQUIRED | + IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED | + IMAGE_ATTRIBUTE_IN_USE + ); + *Setting = (IMAGE_ATTRIBUTE_IMAGE_UPDATABLE | + IMAGE_ATTRIBUTE_RESET_REQUIRED | + IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED | + IMAGE_ATTRIBUTE_IN_USE + ); + return EFI_SUCCESS; +} + +/** + Returns the value used to fill in the LowestSupportedVersion field of the + EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is returned by the GetImageInfo() + service of the Firmware Management Protocol. If EFI_SUCCESS is returned, then + the firmware device supports a method to report the LowestSupportedVersion + value from the currently stored firmware image. If the value can not be + reported for the firmware image currently stored in the firmware device, then + EFI_UNSUPPORTED must be returned. EFI_DEVICE_ERROR is returned if an error + occurs attempting to retrieve the LowestSupportedVersion value for the + currently stored firmware image. + + @note It is recommended that all firmware devices support a method to report + the LowestSupportedVersion value from the currently stored firmware + image. + + @param[out] LowestSupportedVersion LowestSupportedVersion value retrieved + from the currently stored firmware image. + + @retval EFI_SUCCESS The lowest supported version of currently stored + firmware image was returned in LowestSupportedVersion. + @retval EFI_UNSUPPORTED The firmware device does not support a method to + report the lowest supported version of the currently + stored firmware image. + @retval EFI_DEVICE_ERROR An error occurred attempting to retrieve the lowest + supported version of the currently stored firmware + image. + +**/ +EFI_STATUS +EFIAPI +FmpDeviceGetLowestSupportedVersion ( + OUT UINT32 *LowestSupportedVersion + ) +{ + *LowestSupportedVersion = PcdGet32 (PcdFmpDeviceBuildTimeLowestSupportedVersion); + return EFI_SUCCESS; +} + +/** + Returns the Null-terminated Unicode string that is used to fill in the + VersionName field of the EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is + returned by the GetImageInfo() service of the Firmware Management Protocol. + The returned string must be allocated using EFI_BOOT_SERVICES.AllocatePool(). + + @note It is recommended that all firmware devices support a method to report + the VersionName string from the currently stored firmware image. + + @param[out] VersionString The version string retrieved from the currently + stored firmware image. + + @retval EFI_SUCCESS The version string of currently stored + firmware image was returned in Version. + @retval EFI_INVALID_PARAMETER VersionString is NULL. + @retval EFI_UNSUPPORTED The firmware device does not support a method + to report the version string of the currently + stored firmware image. + @retval EFI_DEVICE_ERROR An error occurred attempting to retrieve the + version string of the currently stored + firmware image. + @retval EFI_OUT_OF_RESOURCES There are not enough resources to allocate the + buffer for the version string of the currently + stored firmware image. + +**/ +EFI_STATUS +EFIAPI +FmpDeviceGetVersionString ( + OUT CHAR16 **VersionString + ) +{ + if (VersionString == NULL) { + return EFI_INVALID_PARAMETER; + } + + *VersionString = (CHAR16 *)AllocateCopyPool ( + sizeof (CURRENT_FIRMWARE_VERSION_STRING), + CURRENT_FIRMWARE_VERSION_STRING + ); + if (*VersionString == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + return EFI_SUCCESS; +} + +/** + Returns the value used to fill in the Version field of the + EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is returned by the GetImageInfo() + service of the Firmware Management Protocol. If EFI_SUCCESS is returned, then + the firmware device supports a method to report the Version value from the + currently stored firmware image. If the value can not be reported for the + firmware image currently stored in the firmware device, then EFI_UNSUPPORTED + must be returned. EFI_DEVICE_ERROR is returned if an error occurs attempting + to retrieve the LowestSupportedVersion value for the currently stored firmware + image. + + @note It is recommended that all firmware devices support a method to report + the Version value from the currently stored firmware image. + + @param[out] Version The version value retrieved from the currently stored + firmware image. + + @retval EFI_SUCCESS The version of currently stored firmware image was + returned in Version. + @retval EFI_UNSUPPORTED The firmware device does not support a method to + report the version of the currently stored firmware + image. + @retval EFI_DEVICE_ERROR An error occurred attempting to retrieve the version + of the currently stored firmware image. + +**/ +EFI_STATUS +EFIAPI +FmpDeviceGetVersion ( + OUT UINT32 *Version + ) +{ + *Version = PcdGet32 (PcdFirmwareRevision); + return EFI_SUCCESS; +} + +/** + Returns the value used to fill in the HardwareInstance field of the + EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is returned by the GetImageInfo() + service of the Firmware Management Protocol. If EFI_SUCCESS is returned, then + the firmware device supports a method to report the HardwareInstance value. + If the value can not be reported for the firmware device, then EFI_UNSUPPORTED + must be returned. EFI_DEVICE_ERROR is returned if an error occurs attempting + to retrieve the HardwareInstance value for the firmware device. + + @param[out] HardwareInstance The hardware instance value for the firmware + device. + + @retval EFI_SUCCESS The hardware instance for the current firmware + device is returned in HardwareInstance. + @retval EFI_UNSUPPORTED The firmware device does not support a method to + report the hardware instance value. + @retval EFI_DEVICE_ERROR An error occurred attempting to retrieve the hardware + instance value. + +**/ +EFI_STATUS +EFIAPI +FmpDeviceGetHardwareInstance ( + OUT UINT64 *HardwareInstance + ) +{ + return EFI_UNSUPPORTED; +} + +/** + Returns a copy of the firmware image currently stored in the firmware device. + + @note It is recommended that all firmware devices support a method to retrieve + a copy currently stored firmware image. This can be used to support + features such as recovery and rollback. + + @param[out] Image Pointer to a caller allocated buffer where the + currently stored firmware image is copied to. + @param[in, out] ImageSize Pointer the size, in bytes, of the Image buffer. + On return, points to the size, in bytes, of firmware + image currently stored in the firmware device. + + @retval EFI_SUCCESS Image contains a copy of the firmware image + currently stored in the firmware device, and + ImageSize contains the size, in bytes, of the + firmware image currently stored in the + firmware device. + @retval EFI_BUFFER_TOO_SMALL The buffer specified by ImageSize is too small + to hold the firmware image currently stored in + the firmware device. The buffer size required + is returned in ImageSize. + @retval EFI_INVALID_PARAMETER The Image is NULL. + @retval EFI_INVALID_PARAMETER The ImageSize is NULL. + @retval EFI_UNSUPPORTED The operation is not supported. + @retval EFI_DEVICE_ERROR An error occurred attempting to retrieve the + firmware image currently stored in the firmware + device. + +**/ +EFI_STATUS +EFIAPI +FmpDeviceGetImage ( + OUT VOID *Image, + IN OUT UINTN *ImageSize + ) +{ + return EFI_UNSUPPORTED; +} + +/** + Checks if a new firmware image is valid for the firmware device. This + function allows firmware update operation to validate the firmware image + before FmpDeviceSetImage() is called. + + @param[in] Image Points to a new firmware image. + @param[in] ImageSize Size, in bytes, of a new firmware image. + @param[out] ImageUpdatable Indicates if a new firmware image is valid for + a firmware update to the firmware device. The + following values from the Firmware Management + Protocol are supported: + IMAGE_UPDATABLE_VALID + IMAGE_UPDATABLE_INVALID + IMAGE_UPDATABLE_INVALID_TYPE + IMAGE_UPDATABLE_INVALID_OLD + IMAGE_UPDATABLE_VALID_WITH_VENDOR_CODE + + @retval EFI_SUCCESS The image was successfully checked. Additional + status information is returned in + ImageUpdatable. + @retval EFI_INVALID_PARAMETER Image is NULL. + @retval EFI_INVALID_PARAMETER ImageUpdatable is NULL. + +**/ +EFI_STATUS +EFIAPI +FmpDeviceCheckImage ( + IN CONST VOID *Image, + IN UINTN ImageSize, + OUT UINT32 *ImageUpdatable + ) +{ + UINT32 LastAttemptStatus; + + return FmpDeviceCheckImageWithStatus (Image, ImageSize, ImageUpdatable, &LastAttemptStatus); +} + +/** + Checks if a new firmware image is valid for the firmware device. This + function allows firmware update operation to validate the firmware image + before FmpDeviceSetImage() is called. + + @param[in] Image Points to a new firmware image. + @param[in] ImageSize Size, in bytes, of a new firmware image. + @param[out] ImageUpdatable Indicates if a new firmware image is valid for + a firmware update to the firmware device. The + following values from the Firmware Management + Protocol are supported: + IMAGE_UPDATABLE_VALID + IMAGE_UPDATABLE_INVALID + IMAGE_UPDATABLE_INVALID_TYPE + IMAGE_UPDATABLE_INVALID_OLD + IMAGE_UPDATABLE_VALID_WITH_VENDOR_CODE + @param[out] LastAttemptStatus A pointer to a UINT32 that holds the last attempt + status to report back to the ESRT table in case + of error. + + The return status code must fall in the range of + LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CODE_VALUE to + LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MAX_ERROR_CODE_VALUE. + + If the value falls outside this range, it will be converted + to LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL. + + @retval EFI_SUCCESS The image was successfully checked. Additional + status information is returned in + ImageUpdatable. + @retval EFI_INVALID_PARAMETER Image is NULL. + @retval EFI_INVALID_PARAMETER ImageUpdatable is NULL. + +**/ +EFI_STATUS +EFIAPI +FmpDeviceCheckImageWithStatus ( + IN CONST VOID *Image, + IN UINTN ImageSize, + OUT UINT32 *ImageUpdatable, + OUT UINT32 *LastAttemptStatus + ) +{ + if (LastAttemptStatus == NULL) { + DEBUG ((DEBUG_ERROR, "CheckImageWithStatus - LastAttemptStatus Pointer Parameter is NULL.\n")); + return EFI_INVALID_PARAMETER; + } + + *LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS; + + if (ImageUpdatable == NULL) { + DEBUG ((DEBUG_ERROR, "CheckImageWithStatus - ImageUpdatable Pointer Parameter is NULL.\n")); + *LastAttemptStatus = LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CODE_VALUE; + return EFI_INVALID_PARAMETER; + } + + // + // Set to valid and then if any tests fail it will update this flag. + // + *ImageUpdatable = IMAGE_UPDATABLE_VALID; + + if (Image == NULL) { + DEBUG ((DEBUG_ERROR, "CheckImageWithStatus - Image Pointer Parameter is NULL.\n")); + // + // Not sure if this is needed + // + *ImageUpdatable = IMAGE_UPDATABLE_INVALID; + *LastAttemptStatus = LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CODE_VALUE; + return EFI_INVALID_PARAMETER; + } + + return EFI_SUCCESS; +} + +/** + Updates a firmware device with a new firmware image. This function returns + EFI_UNSUPPORTED if the firmware image is not updatable. If the firmware image + is updatable, the function should perform the following minimal validations + before proceeding to do the firmware image update. + - Validate that the image is a supported image for this firmware device. + Return EFI_ABORTED if the image is not supported. Additional details + on why the image is not a supported image may be returned in AbortReason. + - Validate the data from VendorCode if is not NULL. Firmware image + validation must be performed before VendorCode data validation. + VendorCode data is ignored or considered invalid if image validation + fails. Return EFI_ABORTED if the VendorCode data is invalid. + + VendorCode enables vendor to implement vendor-specific firmware image update + policy. Null if the caller did not specify the policy or use the default + policy. As an example, vendor can implement a policy to allow an option to + force a firmware image update when the abort reason is due to the new firmware + image version is older than the current firmware image version or bad image + checksum. Sensitive operations such as those wiping the entire firmware image + and render the device to be non-functional should be encoded in the image + itself rather than passed with the VendorCode. AbortReason enables vendor to + have the option to provide a more detailed description of the abort reason to + the caller. + + @param[in] Image Points to the new firmware image. + @param[in] ImageSize Size, in bytes, of the new firmware image. + @param[in] VendorCode This enables vendor to implement vendor-specific + firmware image update policy. NULL indicates + the caller did not specify the policy or use the + default policy. + @param[in] Progress A function used to report the progress of + updating the firmware device with the new + firmware image. + @param[in] CapsuleFwVersion The version of the new firmware image from the + update capsule that provided the new firmware + image. + @param[out] AbortReason A pointer to a pointer to a Null-terminated + Unicode string providing more details on an + aborted operation. The buffer is allocated by + this function with + EFI_BOOT_SERVICES.AllocatePool(). It is the + caller's responsibility to free this buffer with + EFI_BOOT_SERVICES.FreePool(). + + @retval EFI_SUCCESS The firmware device was successfully updated + with the new firmware image. + @retval EFI_ABORTED The operation is aborted. Additional details + are provided in AbortReason. + @retval EFI_INVALID_PARAMETER The Image was NULL. + @retval EFI_UNSUPPORTED The operation is not supported. + +**/ +EFI_STATUS +EFIAPI +FmpDeviceSetImage ( + IN CONST VOID *Image, + IN UINTN ImageSize, + IN CONST VOID *VendorCode OPTIONAL, + IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress OPTIONAL, + IN UINT32 CapsuleFwVersion, + OUT CHAR16 **AbortReason + ) +{ + UINT32 LastAttemptStatus; + + return FmpDeviceSetImageWithStatus ( + Image, + ImageSize, + VendorCode, + Progress, + CapsuleFwVersion, + AbortReason, + &LastAttemptStatus + ); +} + +/** + Updates a firmware device with a new firmware image. This function returns + EFI_UNSUPPORTED if the firmware image is not updatable. If the firmware image + is updatable, the function should perform the following minimal validations + before proceeding to do the firmware image update. + - Validate that the image is a supported image for this firmware device. + Return EFI_ABORTED if the image is not supported. Additional details + on why the image is not a supported image may be returned in AbortReason. + - Validate the data from VendorCode if is not NULL. Firmware image + validation must be performed before VendorCode data validation. + VendorCode data is ignored or considered invalid if image validation + fails. Return EFI_ABORTED if the VendorCode data is invalid. + + VendorCode enables vendor to implement vendor-specific firmware image update + policy. Null if the caller did not specify the policy or use the default + policy. As an example, vendor can implement a policy to allow an option to + force a firmware image update when the abort reason is due to the new firmware + image version is older than the current firmware image version or bad image + checksum. Sensitive operations such as those wiping the entire firmware image + and render the device to be non-functional should be encoded in the image + itself rather than passed with the VendorCode. AbortReason enables vendor to + have the option to provide a more detailed description of the abort reason to + the caller. + + @param[in] Image Points to the new firmware image. + @param[in] ImageSize Size, in bytes, of the new firmware image. + @param[in] VendorCode This enables vendor to implement vendor-specific + firmware image update policy. NULL indicates + the caller did not specify the policy or use the + default policy. + @param[in] Progress A function used to report the progress of + updating the firmware device with the new + firmware image. + @param[in] CapsuleFwVersion The version of the new firmware image from the + update capsule that provided the new firmware + image. + @param[out] AbortReason A pointer to a pointer to a Null-terminated + Unicode string providing more details on an + aborted operation. The buffer is allocated by + this function with + EFI_BOOT_SERVICES.AllocatePool(). It is the + caller's responsibility to free this buffer with + EFI_BOOT_SERVICES.FreePool(). + @param[out] LastAttemptStatus A pointer to a UINT32 that holds the last attempt + status to report back to the ESRT table in case + of error. This value will only be checked when this + function returns an error. + + The return status code must fall in the range of + LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CODE_VALUE to + LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MAX_ERROR_CODE_VALUE. + + If the value falls outside this range, it will be converted + to LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL. + + @retval EFI_SUCCESS The firmware device was successfully updated + with the new firmware image. + @retval EFI_ABORTED The operation is aborted. Additional details + are provided in AbortReason. + @retval EFI_INVALID_PARAMETER The Image was NULL. + @retval EFI_UNSUPPORTED The operation is not supported. + +**/ +EFI_STATUS +EFIAPI +FmpDeviceSetImageWithStatus ( + IN CONST VOID *Image, + IN UINTN ImageSize, + IN CONST VOID *VendorCode OPTIONAL, + IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress OPTIONAL, + IN UINT32 CapsuleFwVersion, + OUT CHAR16 **AbortReason, + OUT UINT32 *LastAttemptStatus + ) +{ + EFI_STATUS Status; + UINTN Index; + UPDATE_CONFIG_DATA *ConfigData; + UINTN TotalSize; + UINTN BytesWritten; + + if (Progress == NULL) { + DEBUG ((DEBUG_ERROR, "FmpDeviceSetImageWithStatus - Invalid progress callback\n")); + *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSATISFIED_DEPENDENCIES; + return EFI_INVALID_PARAMETER; + } + + *LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS; + DEBUG ((DEBUG_INFO, "FmpDeviceSetImageWithStatus - %d Images ...\n", ARRAY_SIZE (mUpdateConfigData))); + + // + // Compute total size of update + // + for (Index = 0, TotalSize = 0; Index < ARRAY_SIZE (mUpdateConfigData); Index++) { + TotalSize += mUpdateConfigData[Index].Length; + } + + BytesWritten = 0; + for (Index = 0, ConfigData = mUpdateConfigData; Index < ARRAY_SIZE (mUpdateConfigData); Index++, ConfigData++) { + DEBUG (( + DEBUG_INFO, + "PlatformUpdate(%d): BaseAddress - 0x%lx ImageOffset - 0x%x Length - 0x%x\n", + Index, + ConfigData->BaseAddress, + ConfigData->ImageOffset, + ConfigData->Length + )); + Status = PerformFlashWriteWithProgress ( + ConfigData->FirmwareType, // FirmwareType + ConfigData->BaseAddress, // FlashAddress + ConfigData->AddressType, // FlashAddressType + (VOID *)((UINTN)Image + (UINTN)ConfigData->ImageOffset), // Buffer + ConfigData->Length, // BufferLength + Progress, // Progress + BytesWritten / TotalSize, // StartPercentage + (BytesWritten + ConfigData->Length) * 80 / TotalSize // EndPercentage + ); + if (EFI_ERROR (Status)) { + break; + } + + BytesWritten += ConfigData->Length; + } + + DEBUG ((DEBUG_INFO, "FmpDeviceSetImageWithStatus - %r\n", Status)); + + if (EFI_ERROR (Status)) { + *LastAttemptStatus = LAST_ATTEMPT_STATUS_DEVICE_LIBRARY_MIN_ERROR_CODE_VALUE; + } + + return Status; +} + +/** + Lock the firmware device that contains a firmware image. Once a firmware + device is locked, any attempts to modify the firmware image contents in the + firmware device must fail. + + @note It is recommended that all firmware devices support a lock method to + prevent modifications to a stored firmware image. + + @note A firmware device lock mechanism is typically only cleared by a full + system reset (not just sleep state/low power mode). + + @retval EFI_SUCCESS The firmware device was locked. + @retval EFI_UNSUPPORTED The firmware device does not support locking + +**/ +EFI_STATUS +EFIAPI +FmpDeviceLock ( + VOID + ) +{ + return EFI_UNSUPPORTED; +} diff --git a/OvmfPkg/RiscVVirt/Feature/Capsule/Library/FmpDeviceLib/FmpDeviceLib.inf b/OvmfPkg/RiscVVirt/Feature/Capsule/Library/FmpDeviceLib/FmpDeviceLib.inf new file mode 100644 index 0000000000..abdf5d5d6d --- /dev/null +++ b/OvmfPkg/RiscVVirt/Feature/Capsule/Library/FmpDeviceLib/FmpDeviceLib.inf @@ -0,0 +1,46 @@ +## @file +# Provides firmware device specific services to support updates of a firmware +# image stored in a firmware device. +# +# Copyright (c) 2016, Microsoft Corporation. All rights reserved.
+# Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.
+# Copyright (c) 2025, Ventana Micro Systems Inc. All Rights Reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +## + +[Defines] + INF_VERSION = 1.30 + BASE_NAME = FmpDeviceLib + FILE_GUID = BCBACAC2-1D1D-4C14-89A3-5E27496B702D + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = FmpDeviceLib|DXE_DRIVER UEFI_DRIVER + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 ARM AARCH64 RISCV64 +# + +[Sources] + FmpDeviceLib.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + FmpDevicePkg/FmpDevicePkg.dec + +[LibraryClasses] + DebugLib + BaseLib + BaseMemoryLib + MemoryAllocationLib + PlatformFlashAccessLib + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareRevision + gFmpDevicePkgTokenSpaceGuid.PcdFmpDeviceBuildTimeLowestSupportedVersion + + + diff --git a/OvmfPkg/RiscVVirt/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.c b/OvmfPkg/RiscVVirt/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.c new file mode 100644 index 0000000000..cea6f8d803 --- /dev/null +++ b/OvmfPkg/RiscVVirt/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.c @@ -0,0 +1,233 @@ +/** @file + Platform Flash Access library. + + Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.
+ Copyright (c) 2025, Ventana Micro Systems Inc. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include "PlatformFlashAccessLib.h" + +#define ALIGN(v, a) (UINTN)((((v) - 1) | ((a) - 1)) + 1) + +#define FLASH_CODE_BASE 0x20000000 +#define FLASH_DATA_BASE 0x22000000 +#define FLASH_SIZE SIZE_32MB +#define BLOCK_SIZE SIZE_256KB + +/** + Perform flash write operation with progress indicator. The start and end + completion percentage values are passed into this function. If the requested + flash write operation is broken up, then completion percentage between the + start and end values may be passed to the provided Progress function. The + caller of this function is required to call the Progress function for the + start and end completion percentage values. This allows the Progress, + StartPercentage, and EndPercentage parameters to be ignored if the requested + flash write operation can not be broken up + + @param[in] FirmwareType The type of firmware. + @param[in] FlashAddress The address of flash device to be accessed. + @param[in] FlashAddressType The type of flash device address. + @param[in] Buffer The pointer to the data buffer. + @param[in] Length The length of data buffer in bytes. + @param[in] Progress A function used report the progress of the + firmware update. This is an optional parameter + that may be NULL. + @param[in] StartPercentage The start completion percentage value that may + be used to report progress during the flash + write operation. + @param[in] EndPercentage The end completion percentage value that may + be used to report progress during the flash + write operation. + + @retval EFI_SUCCESS The operation returns successfully. + @retval EFI_WRITE_PROTECTED The flash device is read only. + @retval EFI_UNSUPPORTED The flash device access is unsupported. + @retval EFI_INVALID_PARAMETER The input parameter is not valid. +**/ +EFI_STATUS +EFIAPI +PerformFlashWriteWithProgress ( + IN PLATFORM_FIRMWARE_TYPE FirmwareType, + IN EFI_PHYSICAL_ADDRESS FlashAddress, + IN FLASH_ADDRESS_TYPE FlashAddressType, + IN VOID *Buffer, + IN UINTN Length, + IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress, OPTIONAL + IN UINTN StartPercentage, + IN UINTN EndPercentage + ) +{ + EFI_STATUS Status = EFI_SUCCESS; + UINTN LbaNum; + UINTN Lba; + UINTN Index; + VOID *ShadowBuffer; + UINTN LastBlock; + UINTN NumByte; + UINTN FlashBase; + + DEBUG ((DEBUG_INFO, "PerformFlashWrite - 0x%x(%x) - 0x%x\n", (UINTN)FlashAddress, (UINTN)FlashAddressType, Length)); + + if (FlashAddressType != FlashAddressTypeAbsoluteAddress) { + // Only support absolute address for this platform + return EFI_INVALID_PARAMETER; + } + + if (FirmwareType == PlatformFirmwareTypeSystemFirmware) { + if ((FlashAddress < FLASH_CODE_BASE) || ((FlashAddress + Length) > (FLASH_CODE_BASE + FLASH_SIZE))) { + return EFI_INVALID_PARAMETER; + } + + FlashBase = FLASH_CODE_BASE; + } else { + if ((FlashAddress < FLASH_DATA_BASE) || ((FlashAddress + Length) > (FLASH_DATA_BASE + FLASH_SIZE))) { + return EFI_INVALID_PARAMETER; + } + + FlashBase = FLASH_DATA_BASE; + } + + ShadowBuffer = AllocateZeroPool (BLOCK_SIZE); + LastBlock = FLASH_SIZE / BLOCK_SIZE - 1; + if ( (ALIGN (FlashAddress, BLOCK_SIZE) != FlashAddress) + || (Length % BLOCK_SIZE)) + { + // Not expect un-aligned flash address + return EFI_INVALID_PARAMETER; + } + + // + // Erase & Write + // + LbaNum = Length / BLOCK_SIZE; + Lba = (FlashAddress - FlashBase) / BLOCK_SIZE; + for (Index = 0; Index < LbaNum; Index++) { + if (Progress != NULL) { + Progress (StartPercentage + ((Index * (EndPercentage - StartPercentage)) / LbaNum)); + } + + if (CompareMem ( + (UINT8 *)(UINTN)(GET_NOR_BLOCK_ADDRESS (FlashBase, Lba + Index, BLOCK_SIZE)), + (UINT8 *)Buffer + Index * BLOCK_SIZE, + BLOCK_SIZE + ) == 0) + { + DEBUG ((DEBUG_INFO, "Sector - 0x%x - skip\n", Index)); + continue; + } + + DEBUG ((DEBUG_INFO, "Sector - 0x%x - update...\n", Index)); + NumByte = BLOCK_SIZE; + Status = NorFlashWriteSingleBlock ( + FlashBase, + FlashBase, + Lba + Index, + LastBlock, + BLOCK_SIZE, + FLASH_SIZE, + 0, + &NumByte, + (UINT8 *)Buffer + Index * BLOCK_SIZE, + ShadowBuffer + ); + if ((Status != EFI_SUCCESS) || (NumByte != BLOCK_SIZE)) { + DEBUG (( + DEBUG_ERROR, + "Sector - 0x%x - update failed (bytes written)...\n", + Index, + NumByte + )); + break; + } + } + + if (Progress != NULL) { + Progress (EndPercentage); + } + + FreePool (ShadowBuffer); + return Status; +} + +/** + Perform flash write operation. + + @param[in] FirmwareType The type of firmware. + @param[in] FlashAddress The address of flash device to be accessed. + @param[in] FlashAddressType The type of flash device address. + @param[in] Buffer The pointer to the data buffer. + @param[in] Length The length of data buffer in bytes. + + @retval EFI_SUCCESS The operation returns successfully. + @retval EFI_WRITE_PROTECTED The flash device is read only. + @retval EFI_UNSUPPORTED The flash device access is unsupported. + @retval EFI_INVALID_PARAMETER The input parameter is not valid. +**/ +EFI_STATUS +EFIAPI +PerformFlashWrite ( + IN PLATFORM_FIRMWARE_TYPE FirmwareType, + IN EFI_PHYSICAL_ADDRESS FlashAddress, + IN FLASH_ADDRESS_TYPE FlashAddressType, + IN VOID *Buffer, + IN UINTN Length + ) +{ + return PerformFlashWriteWithProgress ( + FirmwareType, + FlashAddress, + FlashAddressType, + Buffer, + Length, + NULL, + 0, + 0 + ); +} + +/** + Platform Flash Access Lib Constructor. + + @retval EFI_SUCCESS Constructor returns successfully. +**/ +EFI_STATUS +EFIAPI +PlatformFlashAccessLibConstructor ( + VOID + ) +{ + EFI_STATUS Status; + + // + // map the code flash region, the data flash region + // already mapped via variable driver + // + Status = gDS->AddMemorySpace ( + EfiGcdMemoryTypeMemoryMappedIo, + FLASH_CODE_BASE, + SIZE_32MB, + EFI_MEMORY_UC + ); + if (!EFI_ERROR (Status)) { + Status = gDS->SetMemorySpaceAttributes ( + FLASH_CODE_BASE, + SIZE_32MB, + EFI_MEMORY_UC + ); + ASSERT_EFI_ERROR (Status); + } + + return EFI_SUCCESS; +} diff --git a/OvmfPkg/RiscVVirt/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.h b/OvmfPkg/RiscVVirt/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.h new file mode 100644 index 0000000000..fe3cf0a17b --- /dev/null +++ b/OvmfPkg/RiscVVirt/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.h @@ -0,0 +1,95 @@ +/** @file + Platform flash device access library. + + Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __PLATFORM_FLASH_ACCESS_LIB_H__ +#define __PLATFORM_FLASH_ACCESS_LIB_H__ + +#include + +typedef enum { + FlashAddressTypeRelativeAddress, + FlashAddressTypeAbsoluteAddress, +} FLASH_ADDRESS_TYPE; + +// +// Type 0 ~ 0x7FFFFFFF is defined in this library. +// Type 0x80000000 ~ 0xFFFFFFFF is reserved for OEM. +// +typedef enum { + PlatformFirmwareTypeSystemFirmware, + PlatformFirmwareTypeNvRam, +} PLATFORM_FIRMWARE_TYPE; + +/** + Perform flash write operation. + + @param[in] FirmwareType The type of firmware. + @param[in] FlashAddress The address of flash device to be accessed. + @param[in] FlashAddressType The type of flash device address. + @param[in] Buffer The pointer to the data buffer. + @param[in] Length The length of data buffer in bytes. + + @retval EFI_SUCCESS The operation returns successfully. + @retval EFI_WRITE_PROTECTED The flash device is read only. + @retval EFI_UNSUPPORTED The flash device access is unsupported. + @retval EFI_INVALID_PARAMETER The input parameter is not valid. +**/ +EFI_STATUS +EFIAPI +PerformFlashWrite ( + IN PLATFORM_FIRMWARE_TYPE FirmwareType, + IN EFI_PHYSICAL_ADDRESS FlashAddress, + IN FLASH_ADDRESS_TYPE FlashAddressType, + IN VOID *Buffer, + IN UINTN Length + ); + +/** + Perform flash write operation with progress indicator. The start and end + completion percentage values are passed into this function. If the requested + flash write operation is broken up, then completion percentage between the + start and end values may be passed to the provided Progress function. The + caller of this function is required to call the Progress function for the + start and end completion percentage values. This allows the Progress, + StartPercentage, and EndPercentage parameters to be ignored if the requested + flash write operation can not be broken up + + @param[in] FirmwareType The type of firmware. + @param[in] FlashAddress The address of flash device to be accessed. + @param[in] FlashAddressType The type of flash device address. + @param[in] Buffer The pointer to the data buffer. + @param[in] Length The length of data buffer in bytes. + @param[in] Progress A function used report the progress of the + firmware update. This is an optional parameter + that may be NULL. + @param[in] StartPercentage The start completion percentage value that may + be used to report progress during the flash + write operation. + @param[in] EndPercentage The end completion percentage value that may + be used to report progress during the flash + write operation. + + @retval EFI_SUCCESS The operation returns successfully. + @retval EFI_WRITE_PROTECTED The flash device is read only. + @retval EFI_UNSUPPORTED The flash device access is unsupported. + @retval EFI_INVALID_PARAMETER The input parameter is not valid. +**/ +EFI_STATUS +EFIAPI +PerformFlashWriteWithProgress ( + IN PLATFORM_FIRMWARE_TYPE FirmwareType, + IN EFI_PHYSICAL_ADDRESS FlashAddress, + IN FLASH_ADDRESS_TYPE FlashAddressType, + IN VOID *Buffer, + IN UINTN Length, + IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress OPTIONAL, + IN UINTN StartPercentage, + IN UINTN EndPercentage + ); + +#endif diff --git a/OvmfPkg/RiscVVirt/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.inf b/OvmfPkg/RiscVVirt/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.inf new file mode 100644 index 0000000000..1c632f2fde --- /dev/null +++ b/OvmfPkg/RiscVVirt/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.inf @@ -0,0 +1,34 @@ +## @file +# Platform Flash Access library. +# +# Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.
+# Copyright (c) 2025, Ventana Micro Systems Inc. All Rights Reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 1.30 + BASE_NAME = PlatformFlashAccessLibDxe + FILE_GUID = 2FDAFAFE-0179-4047-90A4-40BC56CFBBAE + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = PlatformFlashAccessLib + CONSTRUCTOR = PlatformFlashAccessLibConstructor + +[Sources] + PlatformFlashAccessLib.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + OvmfPkg/OvmfPkg.dec + +[LibraryClasses] + BaseMemoryLib + PcdLib + DebugLib + VirtNorFlashDeviceLib + UefiBootServicesTableLib + DxeServicesTableLib diff --git a/OvmfPkg/RiscVVirt/RiscVVirtQemu.dsc b/OvmfPkg/RiscVVirt/RiscVVirtQemu.dsc index aeda34247b..8480ec5de6 100644 --- a/OvmfPkg/RiscVVirt/RiscVVirtQemu.dsc +++ b/OvmfPkg/RiscVVirt/RiscVVirtQemu.dsc @@ -56,10 +56,20 @@ !error "NETWORK_SNP_ENABLE is IA32/X64/EBC only" !endif + # + # UPDATE/RECOVERY definition + # + DEFINE CAPSULE_ENABLE = FALSE + DEFINE FMP_SYSTEM_DEVICE = BCBACAC2-1D1D-4C14-89A3-5E27496B702D !include MdePkg/MdeLibs.dsc.inc !include NetworkPkg/Network.dsc.inc +!if $(CAPSULE_ENABLE) == TRUE + POSTBUILD = python OvmfPkg/RiscVVirt/Feature/Capsule/GenerateCapsule/GenCapsule.py +!include OvmfPkg/RiscVVirt/RiscVVirtSystemFW.dsc.inc +!endif + [BuildOptions] GCC:RELEASE_*_*_CC_FLAGS = -DMDEPKG_NDEBUG !ifdef $(SOURCE_DEBUG_ENABLE) @@ -119,6 +129,18 @@ TpmPlatformHierarchyLib|SecurityPkg/Library/PeiDxeTpmPlatformHierarchyLibNull/PeiDxeTpmPlatformHierarchyLib.inf !endif +!if $(CAPSULE_ENABLE) == TRUE + CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf + BmpSupportLib|MdeModulePkg/Library/BaseBmpSupportLib/BaseBmpSupportLib.inf + SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf + OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf + IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf + FmpAuthenticationLib|SecurityPkg/Library/FmpAuthenticationLibPkcs7/FmpAuthenticationLibPkcs7.inf + DisplayUpdateProgressLib|MdeModulePkg/Library/DisplayUpdateProgressLibText/DisplayUpdateProgressLibText.inf + RngLib|MdeModulePkg/Library/BaseRngLibTimerLib/BaseRngLibTimerLib.inf +!endif + [LibraryClasses.common.DXE_DRIVER] AcpiPlatformLib|OvmfPkg/Library/AcpiPlatformLib/DxeAcpiPlatformLib.inf ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf @@ -132,6 +154,11 @@ UefiScsiLib|MdePkg/Library/UefiScsiLib/UefiScsiLib.inf PciExpressLib|OvmfPkg/Library/BaseCachingPciExpressLib/BaseCachingPciExpressLib.inf +[LibraryClasses.common.DXE_RUNTIME_DRIVER] +!if $(CAPSULE_ENABLE) == TRUE + CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf +!endif + ################################################################################ # # Pcd Section - list of all EDK II PCD Entries defined by this Platform. @@ -231,6 +258,10 @@ gEfiSecurityPkgTokenSpaceGuid.PcdTpmBaseAddress|0x0 !endif +!if $(CAPSULE_ENABLE) == TRUE + gEfiMdeModulePkgTokenSpaceGuid.PcdSystemFmpCapsuleImageTypeIdGuid|{GUID("$(FMP_SYSTEM_DEVICE)")}|VOID*|0x10 +!endif + [PcdsDynamicHii] gUefiOvmfPkgTokenSpaceGuid.PcdForceNoAcpi|L"ForceNoAcpi"|gOvmfVariableGuid|0x0|FALSE|NV,BS @@ -491,3 +522,11 @@ NULL|OvmfPkg/Fdt/FdtPciPcdProducerLib/FdtPciPcdProducerLib.inf } + +!if $(CAPSULE_ENABLE) == TRUE + MdeModulePkg/Universal/EsrtFmpDxe/EsrtFmpDxe.inf + MdeModulePkg/Application/CapsuleApp/CapsuleApp.inf { + + PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf + } +!endif diff --git a/OvmfPkg/RiscVVirt/RiscVVirtQemu.fdf b/OvmfPkg/RiscVVirt/RiscVVirtQemu.fdf index 4528a44d3b..8cbd5711aa 100644 --- a/OvmfPkg/RiscVVirt/RiscVVirtQemu.fdf +++ b/OvmfPkg/RiscVVirt/RiscVVirtQemu.fdf @@ -216,6 +216,11 @@ INF MdeModulePkg/Logo/LogoDxe.inf # INF MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskDxe.inf +!if $(CAPSULE_ENABLE) == TRUE +INF MdeModulePkg/Universal/EsrtFmpDxe/EsrtFmpDxe.inf +INF FILE_GUID = $(FMP_SYSTEM_DEVICE) FmpDevicePkg/FmpDxe/FmpDxe.inf +!endif + ################################################################################ [FV.FVMAIN_COMPACT] diff --git a/OvmfPkg/RiscVVirt/RiscVVirtSystemFW.dsc.inc b/OvmfPkg/RiscVVirt/RiscVVirtSystemFW.dsc.inc new file mode 100644 index 0000000000..644e894e03 --- /dev/null +++ b/OvmfPkg/RiscVVirt/RiscVVirtSystemFW.dsc.inc @@ -0,0 +1,61 @@ +## @file +# FmpDxe driver for system firmware update. +# +# Copyright (c) 2025, Ventana Micro Systems Inc. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +FmpDevicePkg/FmpDxe/FmpDxe.inf { + + # + # ESRT and FMP GUID for system device capsule update + # + FILE_GUID = $(FMP_SYSTEM_DEVICE) + + + # + # Unicode name string that is used to populate FMP Image Descriptor for this capsule update module + # + gFmpDevicePkgTokenSpaceGuid.PcdFmpDeviceImageIdName|L"RISC-V VIRT System Firmware Device" + + # + # ESRT and FMP Lowest Support Version for this capsule update module + # 000.000.000.000 + # + gFmpDevicePkgTokenSpaceGuid.PcdFmpDeviceBuildTimeLowestSupportedVersion|0x00000001 + + gFmpDevicePkgTokenSpaceGuid.PcdFmpDeviceProgressWatchdogTimeInSeconds|2 + + # + # Capsule Update Progress Bar Color. Set to Green (RGB) (0, 255, 0) + # + gFmpDevicePkgTokenSpaceGuid.PcdFmpDeviceProgressColor|0x0000FF00 + + # + # Certificates used to authenticate capsule update image + # EDKII Test certificate + # + !include BaseTools/Source/Python/Pkcs7Sign/TestRoot.cer.gFmpDevicePkgTokenSpaceGuid.PcdFmpDevicePkcs7CertBufferXdr.inc + + + # + # Generic libraries that are used "as is" by all FMP modules + # + FmpPayloadHeaderLib|FmpDevicePkg/Library/FmpPayloadHeaderLibV1/FmpPayloadHeaderLibV1.inf + FmpAuthenticationLib|SecurityPkg/Library/FmpAuthenticationLibPkcs7/FmpAuthenticationLibPkcs7.inf + FmpDependencyLib|FmpDevicePkg/Library/FmpDependencyLib/FmpDependencyLib.inf + FmpDependencyCheckLib|FmpDevicePkg/Library/FmpDependencyCheckLibNull/FmpDependencyCheckLibNull.inf + FmpDependencyDeviceLib|FmpDevicePkg/Library/FmpDependencyDeviceLibNull/FmpDependencyDeviceLibNull.inf + # + # Platform specific capsule policy library + # + CapsuleUpdatePolicyLib|OvmfPkg/RiscVVirt/Feature/Capsule/Library/CapsuleUpdatePolicyLib/CapsuleUpdatePolicyLib.inf + # + # Device specific library that processes a capsule and updates the FW storage device + # + FmpDeviceLib|OvmfPkg/RiscVVirt/Feature/Capsule/Library/FmpDeviceLib/FmpDeviceLib.inf + VirtNorFlashDeviceLib|OvmfPkg/Library/VirtNorFlashDeviceLib/VirtNorFlashDeviceLib.inf + PlatformFlashAccessLib|OvmfPkg/RiscVVirt/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.inf + }