summaryrefslogtreecommitdiff
path: root/Platform/Qemu/RiscVServerRef/Feature/Capsule/Library
diff options
context:
space:
mode:
authorTuan Phan <tuan.phan@oss.qualcomm.com>2026-08-14 21:53:21 +0300
committerSunil V L <sunil.vl@kerodi.in>2026-11-09 11:09:39 +0300
commit61547c5cfead0055ef1bb999e89d750d86903040 (patch)
treeb9f59a38bb76b3f731184f09754a7631dcdb91cf /Platform/Qemu/RiscVServerRef/Feature/Capsule/Library
parentb907bd67e2effea54b5ef3929b24dfa5ba36b1a2 (diff)
downloadedk2-platforms-master.tar.xz
RiscVServerRef: Add firmware capsule update supportHEADmaster
Enable firmware capsule generation and include the required components to support firmware capsule updates. Signed-off-by: Tuan Phan <tuan.phan@oss.qualcomm.com>
Diffstat (limited to 'Platform/Qemu/RiscVServerRef/Feature/Capsule/Library')
-rw-r--r--Platform/Qemu/RiscVServerRef/Feature/Capsule/Library/CapsuleUpdatePolicyLib/CapsuleUpdatePolicyLib.c121
-rw-r--r--Platform/Qemu/RiscVServerRef/Feature/Capsule/Library/CapsuleUpdatePolicyLib/CapsuleUpdatePolicyLib.inf29
-rw-r--r--Platform/Qemu/RiscVServerRef/Feature/Capsule/Library/CapsuleUpdatePolicyLib/CapsuleUpdatePolicyLib.uni12
-rw-r--r--Platform/Qemu/RiscVServerRef/Feature/Capsule/Library/FmpDeviceLib/FmpDeviceLib.c774
-rw-r--r--Platform/Qemu/RiscVServerRef/Feature/Capsule/Library/FmpDeviceLib/FmpDeviceLib.inf40
-rw-r--r--Platform/Qemu/RiscVServerRef/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.c235
-rw-r--r--Platform/Qemu/RiscVServerRef/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.h92
-rw-r--r--Platform/Qemu/RiscVServerRef/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.inf34
8 files changed, 1337 insertions, 0 deletions
diff --git a/Platform/Qemu/RiscVServerRef/Feature/Capsule/Library/CapsuleUpdatePolicyLib/CapsuleUpdatePolicyLib.c b/Platform/Qemu/RiscVServerRef/Feature/Capsule/Library/CapsuleUpdatePolicyLib/CapsuleUpdatePolicyLib.c
new file mode 100644
index 0000000000..feec40dd78
--- /dev/null
+++ b/Platform/Qemu/RiscVServerRef/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.<BR>
+ Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiDxe.h>
+#include <Library/CapsuleUpdatePolicyLib.h>
+
+/**
+ 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/Platform/Qemu/RiscVServerRef/Feature/Capsule/Library/CapsuleUpdatePolicyLib/CapsuleUpdatePolicyLib.inf b/Platform/Qemu/RiscVServerRef/Feature/Capsule/Library/CapsuleUpdatePolicyLib/CapsuleUpdatePolicyLib.inf
new file mode 100644
index 0000000000..48d136abca
--- /dev/null
+++ b/Platform/Qemu/RiscVServerRef/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.<BR>
+# Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION = 1.30
+ BASE_NAME = CapsuleUpdatePolicyLib
+ MODULE_UNI_FILE = CapsuleUpdatePolicyLib.uni
+ FILE_GUID = CB9F4E17-2D68-4A35-9F71-6E2C8B5D04A9
+ 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/Platform/Qemu/RiscVServerRef/Feature/Capsule/Library/CapsuleUpdatePolicyLib/CapsuleUpdatePolicyLib.uni b/Platform/Qemu/RiscVServerRef/Feature/Capsule/Library/CapsuleUpdatePolicyLib/CapsuleUpdatePolicyLib.uni
new file mode 100644
index 0000000000..d26e716b11
--- /dev/null
+++ b/Platform/Qemu/RiscVServerRef/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.<BR>
+//
+// 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/Platform/Qemu/RiscVServerRef/Feature/Capsule/Library/FmpDeviceLib/FmpDeviceLib.c b/Platform/Qemu/RiscVServerRef/Feature/Capsule/Library/FmpDeviceLib/FmpDeviceLib.c
new file mode 100644
index 0000000000..020f898aaa
--- /dev/null
+++ b/Platform/Qemu/RiscVServerRef/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.<BR>
+ Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiDxe.h>
+#include <Guid/SystemResourceTable.h>
+#include <Library/DebugLib.h>
+#include <Library/FmpDeviceLib.h>
+#include <Library/PcdLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Include/LastAttemptStatus.h>
+#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/Platform/Qemu/RiscVServerRef/Feature/Capsule/Library/FmpDeviceLib/FmpDeviceLib.inf b/Platform/Qemu/RiscVServerRef/Feature/Capsule/Library/FmpDeviceLib/FmpDeviceLib.inf
new file mode 100644
index 0000000000..9c755ac293
--- /dev/null
+++ b/Platform/Qemu/RiscVServerRef/Feature/Capsule/Library/FmpDeviceLib/FmpDeviceLib.inf
@@ -0,0 +1,40 @@
+## @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.<BR>
+# Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION = 1.30
+ BASE_NAME = FmpDeviceLib
+ FILE_GUID = F3D81A6E-9C42-4F7B-B1E5-2A6D9C4F7812
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = FmpDeviceLib|DXE_DRIVER UEFI_DRIVER
+
+[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/Platform/Qemu/RiscVServerRef/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.c b/Platform/Qemu/RiscVServerRef/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.c
new file mode 100644
index 0000000000..ce3963fb9a
--- /dev/null
+++ b/Platform/Qemu/RiscVServerRef/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.c
@@ -0,0 +1,235 @@
+/** @file
+ Platform Flash Access library.
+
+ Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiDxe.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/VirtNorFlashDeviceLib.h>
+#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;
+ }
+
+ 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;
+ }
+
+ ShadowBuffer = AllocateZeroPool (BLOCK_SIZE);
+
+ //
+ // 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/Platform/Qemu/RiscVServerRef/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.h b/Platform/Qemu/RiscVServerRef/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.h
new file mode 100644
index 0000000000..434287e937
--- /dev/null
+++ b/Platform/Qemu/RiscVServerRef/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.h
@@ -0,0 +1,92 @@
+/** @file
+ Platform flash device access library.
+
+ Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#pragma once
+
+#include <Protocol/FirmwareManagement.h>
+
+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
+ );
diff --git a/Platform/Qemu/RiscVServerRef/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.inf b/Platform/Qemu/RiscVServerRef/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.inf
new file mode 100644
index 0000000000..81a3e4a07f
--- /dev/null
+++ b/Platform/Qemu/RiscVServerRef/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.inf
@@ -0,0 +1,34 @@
+## @file
+# Platform Flash Access library.
+#
+# Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 1.30
+ BASE_NAME = PlatformFlashAccessLibDxe
+ FILE_GUID = A7C2E9D4-5F18-4B63-8D2A-91F4C7E5B830
+ 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