From: "Nhi Pham" <nhi@os.amperecomputing.com>
To: devel@edk2.groups.io
Cc: Nhi Pham <nhi@os.amperecomputing.com>
Subject: [edk2-platforms][PATCH 25/34] AmpereAltraPkg: Implement PlatformFlashAccessLib instance
Date: Wed, 9 Dec 2020 16:25:22 +0700 [thread overview]
Message-ID: <20201209092531.30867-26-nhi@os.amperecomputing.com> (raw)
In-Reply-To: <20201209092531.30867-1-nhi@os.amperecomputing.com>
This library provides API functions to perform flash write operation
via Secure UEFI MM interface.
The platform flash device is controlled by Arm Trusted Firmware (ATF)
in the secure world. UEFI can not write directly an update image
to the flash device. So, this instance of PlatformFlashAccessLib is
implemented to transfer the update image to ATF secure world via the
Firmware Update SMC service. Then that service will proceed the update.
Signed-off-by: Nhi Pham <nhi@os.amperecomputing.com>
---
Silicon/Ampere/AmpereAltraPkg/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.inf | 37 +++
Silicon/Ampere/AmpereAltraPkg/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.c | 318 ++++++++++++++++++++
2 files changed, 355 insertions(+)
diff --git a/Silicon/Ampere/AmpereAltraPkg/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.inf b/Silicon/Ampere/AmpereAltraPkg/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.inf
new file mode 100644
index 000000000000..fddc0dfbb916
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.inf
@@ -0,0 +1,37 @@
+## @file
+# Platform flash device access library.
+#
+# Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2020, Ampere Computing LLC. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001001B
+ BASE_NAME = PlatformFlashAccessLib
+ FILE_GUID = C2821AC7-331A-48FC-90C2-6660ED40EB25
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PlatformFlashAccessLib|DXE_DRIVER
+
+[Sources]
+ PlatformFlashAccessLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ SignedCapsulePkg/SignedCapsulePkg.dec
+ ArmPkg/ArmPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ UefiBootServicesTableLib
+
+[Protocols]
+ gEfiMmCommunicationProtocolGuid
+
+[Depex]
+ TRUE
diff --git a/Silicon/Ampere/AmpereAltraPkg/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.c b/Silicon/Ampere/AmpereAltraPkg/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.c
new file mode 100644
index 000000000000..ecb08431ac01
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.c
@@ -0,0 +1,318 @@
+/** @file
+ Platform flash device access library.
+
+ Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2020, Ampere Computing LLC. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiDxe.h>
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/PlatformFlashAccessLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Protocol/MmCommunication.h>
+
+EFI_MM_COMMUNICATION_PROTOCOL *mMmCommunication = NULL;
+
+#define EFI_MM_MAX_PAYLOAD_U64_E 10
+#define EFI_MM_MAX_PAYLOAD_SIZE (EFI_MM_MAX_PAYLOAD_U64_E * sizeof (UINT64))
+
+/* FWU MM GUID */
+STATIC CONST EFI_GUID mFwuMmGuid = { 0x452240CD, 0xB3B3, 0x4695, { 0x9A, 0x63, 0xDF, 0xEC, 0x50, 0x82, 0xE7, 0x7A } };
+
+typedef struct {
+ /* Allows for disambiguation of the message format */
+ EFI_GUID HeaderGuid;
+ /*
+ * Describes the size of Data (in bytes) and does not include the size
+ * of the header
+ */
+ UINTN MsgLength;
+} EFI_MM_COMM_HEADER_NOPAYLOAD;
+
+typedef struct {
+ UINT64 Data[EFI_MM_MAX_PAYLOAD_U64_E];
+} EFI_MM_COMM_FWU_PAYLOAD;
+
+typedef struct {
+ EFI_MM_COMM_HEADER_NOPAYLOAD EfiMmHdr;
+ EFI_MM_COMM_FWU_PAYLOAD PayLoad;
+} EFI_MM_COMM_REQUEST;
+
+EFI_MM_COMM_REQUEST mEfiMmSysFwuReq;
+
+typedef struct {
+ UINT64 Status;
+ UINT64 Progress;
+} EFI_MM_COMMUNICATE_FWU_RES;
+
+#define FWU_MM_RES_SUCCESS 0xAABBCC00
+#define FWU_MM_RES_IN_PROGRESS 0xAABBCC01
+#define FWU_MM_RES_SECURITY_VIOLATION 0xAABBCC02
+#define FWU_MM_RES_OUT_OF_RESOURCES 0xAABBCC03
+#define FWU_MM_RES_IO_ERROR 0xAABBCC04
+#define FWU_MM_RES_FAIL 0xAABBCCFF
+
+/*
+ * The ARM Trusted Firmware (ATF) defined image types to support updating
+ * various firmware via SMC Firmware Update service.
+ * The value of definition here must be the same in ATF code.
+ */
+#define FWU_IMG_TYPE_INVALID 0
+#define FWU_IMG_TYPE_ATFBIOS 2 // ARM Trusted Firmware and UEFI Image
+#define FWU_IMG_TYPE_MAX 5
+
+/*
+ * According to PLATFORM_FIRMWARE_TYPE,
+ * Type 0x80000000 ~ 0xFFFFFFFF is reserved for OEM.
+ * A type of firmware image is determined by FirmwareType value
+ * in the Configuration of Firmware Update.
+ * Formula: FirmwareType = ImageType + 0x80000000
+ */
+#define FIRMWARE_TYPE_OEM_OFFSET 0x80000000
+
+/*
+ * Size of Firmware Descriptor File Volume
+ */
+#define FIRMWARE_DESCRIPTOR_SIZE 0x10000
+
+VOID
+UefiMmCreateSysFwuReq (
+ VOID *Data,
+ UINT64 Size
+ )
+{
+ CopyGuid (&mEfiMmSysFwuReq.EfiMmHdr.HeaderGuid, &mFwuMmGuid);
+ mEfiMmSysFwuReq.EfiMmHdr.MsgLength = Size;
+
+ if (Size != 0) {
+ ASSERT (Data != NULL);
+ ASSERT (Size <= EFI_MM_MAX_PAYLOAD_SIZE);
+
+ CopyMem (&mEfiMmSysFwuReq.PayLoad.Data, Data, Size);
+ }
+}
+
+EFI_STATUS
+MmFlashUpdate (
+ IN UINT32 ImageType,
+ IN VOID *FirmwareImage,
+ IN UINT64 ImageSize,
+ IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress,
+ IN UINTN StartPercentage,
+ IN UINTN EndPercentage
+ )
+{
+ EFI_MM_COMMUNICATE_FWU_RES *MmFwuStatus;
+ UINTN ProgressUpdate = StartPercentage;
+ UINTN Size;
+ UINT64 MmData[5];
+ EFI_STATUS Status;
+
+ if (FirmwareImage == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a:%d Invalid inputs.\n", __FUNCTION__, __LINE__));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ DEBUG ((DEBUG_INFO, "%a:%d Image: %p Size 0x%lx\n",
+ __FUNCTION__, __LINE__, FirmwareImage, ImageSize));
+
+ if (mMmCommunication == NULL) {
+ Status = gBS->LocateProtocol(
+ &gEfiMmCommunicationProtocolGuid,
+ NULL,
+ (VOID **) &mMmCommunication);
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: Can't locate gEfiMmCommunicationProtocolGuid.\n", __FUNCTION__));
+ return Status;
+ }
+ }
+
+ MmData[0] = ImageType;
+ MmData[1] = ImageSize;
+ MmData[2] = (UINT64) FirmwareImage;
+ MmData[3] = 1; // MM yield for progress reporting.
+
+ while (TRUE) {
+ UefiMmCreateSysFwuReq ((VOID *) &MmData, sizeof (MmData));
+
+ Size = sizeof (EFI_MM_COMM_HEADER_NOPAYLOAD) + sizeof (MmData);
+ Status = mMmCommunication->Communicate (
+ mMmCommunication,
+ (VOID *) &mEfiMmSysFwuReq,
+ &Size
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a:%d MM communication error - %r\n",
+ __FUNCTION__, __LINE__, Status));
+ return EFI_DEVICE_ERROR;
+ }
+
+ /* Return data in the first double word of payload */
+ MmFwuStatus = (EFI_MM_COMMUNICATE_FWU_RES *) mEfiMmSysFwuReq.PayLoad.Data;
+ if (MmFwuStatus->Status == FWU_MM_RES_IN_PROGRESS) {
+ if (NULL != Progress) {
+ Progress (ProgressUpdate);
+ }
+
+ ProgressUpdate = StartPercentage +
+ (((EndPercentage - StartPercentage) * (MmFwuStatus->Progress)) / 100);
+ continue;
+ }
+ break;
+ }
+
+ switch (MmFwuStatus->Status) {
+ case FWU_MM_RES_SUCCESS:
+ if (NULL != Progress) {
+ Progress (EndPercentage);
+ }
+ Status = EFI_SUCCESS;
+ break;
+
+ case FWU_MM_RES_SECURITY_VIOLATION:
+ DEBUG ((DEBUG_ERROR, "%a:%d Failed to update - Security Violation!\n",
+ __FUNCTION__, __LINE__));
+ Status = EFI_SECURITY_VIOLATION;
+ break;
+
+ case FWU_MM_RES_OUT_OF_RESOURCES:
+ DEBUG ((DEBUG_ERROR, "%a:%d Failed to update - Insufficient resources!\n",
+ __FUNCTION__, __LINE__));
+ Status = EFI_OUT_OF_RESOURCES;
+ break;
+
+ case FWU_MM_RES_IO_ERROR:
+ DEBUG ((DEBUG_ERROR, "%a:%d Failed to update - IO Error!\n",
+ __FUNCTION__, __LINE__));
+ Status = EFI_DEVICE_ERROR;
+ break;
+
+ default:
+ DEBUG ((DEBUG_ERROR, "%a:%d Failed to update - Unknown Error!\n",
+ __FUNCTION__, __LINE__));
+ Status = EFI_INVALID_PARAMETER;
+ break;
+ }
+
+ return Status;
+}
+
+/**
+ 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
+ )
+{
+ UINT32 ImageType;
+
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ /*
+ * As per the design of firmware capsule, the Firmware Descriptor File
+ * Volume which is used to provide description of firmware update is
+ * attached at the beginning of the firmware file. It must be removed
+ * before writing.
+ */
+ if (Length <= FIRMWARE_DESCRIPTOR_SIZE) {
+ DEBUG ((DEBUG_ERROR, "%a %d The length of firmware image is invalid.\n",
+ __FUNCTION__, __LINE__));
+ return EFI_INVALID_PARAMETER;
+ }
+ Length -= FIRMWARE_DESCRIPTOR_SIZE;
+ Buffer += FIRMWARE_DESCRIPTOR_SIZE;
+
+ ImageType = FirmwareType - FIRMWARE_TYPE_OEM_OFFSET;
+ if (ImageType >= FWU_IMG_TYPE_MAX) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return MmFlashUpdate (
+ ImageType,
+ Buffer,
+ Length,
+ Progress,
+ StartPercentage,
+ EndPercentage
+ );
+}
+
+/**
+ 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
+ );
+}
--
2.17.1
next prev parent reply other threads:[~2020-12-09 9:24 UTC|newest]
Thread overview: 40+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-12-09 9:24 [edk2-platforms][PATCH 00/34] Add new Ampere Mt. Jade platform Nhi Pham
2020-12-09 9:24 ` [edk2-platforms][PATCH 01/34] Initial support for Ampere Altra and " Nhi Pham
2021-01-07 23:57 ` [edk2-devel] " Leif Lindholm
2021-01-15 4:59 ` Vu Nguyen
2020-12-09 9:24 ` [edk2-platforms][PATCH 02/34] Platform/Ampere: Implement FailSafe library Nhi Pham
2020-12-09 9:25 ` [edk2-platforms][PATCH 03/34] Platform/Ampere: Add FailSafe and WDT support Nhi Pham
2020-12-09 9:25 ` [edk2-platforms][PATCH 04/34] AmpereAltraPkg: Implement GpioLib and I2cLib modules Nhi Pham
2020-12-09 9:25 ` [edk2-platforms][PATCH 05/34] JadePkg: Implement RealTimeClockLib for PCF85063 Nhi Pham
2020-12-09 9:25 ` [edk2-platforms][PATCH 06/34] Platform/Ampere: Add AcpiPccLib to support ACPI PCCT Table Nhi Pham
2020-12-09 9:25 ` [edk2-platforms][PATCH 07/34] Platform/Ampere: Add AcpiHelperLib to update ACPI DSDT table Nhi Pham
2020-12-09 9:25 ` [edk2-platforms][PATCH 08/34] JadePkg: Initial support for static ACPI tables Nhi Pham
2020-12-09 9:25 ` [edk2-platforms][PATCH 09/34] JadePkg: Install some ACPI tables at runtime Nhi Pham
2020-12-09 9:25 ` [edk2-platforms][PATCH 10/34] Silicon/Ampere: Support Non Volatile storage for Variable service Nhi Pham
2020-12-09 9:25 ` [edk2-platforms][PATCH 11/34] Silicon/Ampere: Support PlatformManagerUiLib Nhi Pham
2020-12-09 9:25 ` [edk2-platforms][PATCH 12/34] AmpereAltraPkg: Add PcieCore Library Nhi Pham
2020-12-09 9:25 ` [edk2-platforms][PATCH 13/34] AmpereAltraPkg: Add PciHostBridge driver Nhi Pham
2020-12-09 9:25 ` [edk2-platforms][PATCH 14/34] JadePkg: Add implementation for PcieBoardLib Nhi Pham
2020-12-09 9:25 ` [edk2-platforms][PATCH 15/34] JadePkg: Enable PCIe support Nhi Pham
2020-12-09 9:25 ` [edk2-platforms][PATCH 16/34] JadePkg: Add ASpeed GOP driver Nhi Pham
2020-12-09 9:25 ` [edk2-platforms][PATCH 17/34] Silicon/Ampere: Add Random Number Generator Support Nhi Pham
2020-12-09 9:25 ` [edk2-platforms][PATCH 18/34] Silicon/Ampere: Fixup runtime memory attribute Nhi Pham
2020-12-09 9:25 ` [edk2-platforms][PATCH 19/34] JadePkg: Add SMBIOS tables support Nhi Pham
2020-12-09 9:25 ` [edk2-platforms][PATCH 20/34] AmpereAltraPkg: Add DebugInfoPei module Nhi Pham
2020-12-09 9:25 ` [edk2-platforms][PATCH 21/34] Silicon/Ampere: Add platform info screen Nhi Pham
2020-12-09 9:25 ` [edk2-platforms][PATCH 22/34] Silicon/Ampere: Add Memory " Nhi Pham
2020-12-09 9:25 ` [edk2-platforms][PATCH 23/34] AmpereAltraPkg: Add CPU Configuration for SubNUMA Nhi Pham
2020-12-09 9:25 ` [edk2-platforms][PATCH 24/34] AmpereAltraPkg: Add ACPI configuration screen Nhi Pham
2020-12-09 9:25 ` Nhi Pham [this message]
2020-12-09 9:25 ` [edk2-platforms][PATCH 26/34] JadePkg: Add implementation for UEFI Capsule Update Nhi Pham
2020-12-09 9:25 ` [edk2-platforms][PATCH 27/34] JadePkg: Add Capsule Update support Nhi Pham
2020-12-09 9:25 ` [edk2-platforms][PATCH 28/34] Silicon/Ampere: Implement PlatformBootManagerLib for LinuxBoot Nhi Pham
2020-12-09 9:25 ` [edk2-platforms][PATCH 29/34] Platform/Ampere: Add LinuxBoot image Nhi Pham
2020-12-10 12:40 ` [edk2-devel] " Leif Lindholm
2020-12-11 2:38 ` Nhi Pham
2020-12-11 11:15 ` Leif Lindholm
2020-12-09 9:25 ` [edk2-platforms][PATCH 30/34] JadePkg: Support LinuxBoot DSC/FDF build for Jade platform Nhi Pham
2020-12-09 9:25 ` [edk2-platforms][PATCH 31/34] AmpereAltraPkg: Add BootProgress support Nhi Pham
2020-12-09 9:25 ` [edk2-platforms][PATCH 32/34] JadePkg: Add ACPI/APEI tables Nhi Pham
2020-12-09 9:25 ` [edk2-platforms][PATCH 33/34] Platform/Ampere: Add AcpiApeiLib Nhi Pham
2020-12-09 9:25 ` [edk2-platforms][PATCH 34/34] AmpereAltraPkg, JadePkg: Add RAS setting screen Nhi Pham
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20201209092531.30867-26-nhi@os.amperecomputing.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox