public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Nhi Pham" <nhi@os.amperecomputing.com>
To: devel@edk2.groups.io
Cc: patches@amperecomputing.com, nhi@os.amperecomputing.com,
	vunguyen@os.amperecomputing.com,
	Thang Nguyen <thang@os.amperecomputing.com>,
	Chuong Tran <chuong@os.amperecomputing.com>,
	Phong Vo <phong@os.amperecomputing.com>,
	Leif Lindholm <leif@nuviainc.com>,
	Michael D Kinney <michael.d.kinney@intel.com>,
	Ard Biesheuvel <ardb+tianocore@kernel.org>,
	Nate DeSimone <nathaniel.l.desimone@intel.com>
Subject: [edk2-platforms][PATCH v5 02/30] AmpereAltraPkg: Add FlashLib library instance
Date: Wed, 17 Nov 2021 23:46:59 +0700	[thread overview]
Message-ID: <20211117164727.10922-3-nhi@os.amperecomputing.com> (raw)
In-Reply-To: <20211117164727.10922-1-nhi@os.amperecomputing.com>

From: Vu Nguyen <vunguyen@os.amperecomputing.com>

Provides functions to access the NVRAM, NVRAM2 and FailSafe region on the
Flash over MM communication.

Cc: Thang Nguyen <thang@os.amperecomputing.com>
Cc: Chuong Tran <chuong@os.amperecomputing.com>
Cc: Phong Vo <phong@os.amperecomputing.com>
Cc: Leif Lindholm <leif@nuviainc.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>

Signed-off-by: Nhi Pham <nhi@os.amperecomputing.com>
---
 Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec                   |   3 +
 Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc               |   2 +
 Silicon/Ampere/AmpereAltraPkg/Library/FlashLib/FlashLib.inf        |  35 ++
 Silicon/Ampere/AmpereAltraPkg/Library/FlashLib/RuntimeFlashLib.inf |  37 ++
 Silicon/Ampere/AmpereAltraPkg/Include/Library/FlashLib.h           | 118 +++++++
 Silicon/Ampere/AmpereAltraPkg/Library/FlashLib/FlashLibCommon.h    |  92 +++++
 Silicon/Ampere/AmpereAltraPkg/Library/FlashLib/FlashLib.c          |  83 +++++
 Silicon/Ampere/AmpereAltraPkg/Library/FlashLib/FlashLibCommon.c    | 372 ++++++++++++++++++++
 Silicon/Ampere/AmpereAltraPkg/Library/FlashLib/RuntimeFlashLib.c   | 137 +++++++
 9 files changed, 879 insertions(+)

diff --git a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec
index 0813fc9b4b69..ac778674266d 100644
--- a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec
+++ b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec
@@ -34,6 +34,9 @@ [LibraryClasses]
   ##  @libraryclass  Defines a set of methods to generate random numbers by using Hardware RNG.
   TrngLib|Silicon/Ampere/AmpereAltraPkg/Include/Library/TrngLib.h
 
+  ##  @libraryclass  Defines a set of methods to access flash memory.
+  FlashLib|Silicon/Ampere/AmpereAltraPkg/Include/Library/FlashLib.h
+
 [Guids]
   ## NVParam MM GUID
   gNVParamMmGuid               = { 0xE4AC5024, 0x29BE, 0x4ADC, { 0x93, 0x36, 0x87, 0xB5, 0xA0, 0x76, 0x23, 0x2D } }
diff --git a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc
index 15f649d97f30..cf1be4df8f27 100644
--- a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc
+++ b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc
@@ -84,6 +84,7 @@ [LibraryClasses.common]
   AmpereCpuLib|Silicon/Ampere/AmpereAltraPkg/Library/AmpereCpuLib/AmpereCpuLib.inf
   TimeBaseLib|EmbeddedPkg/Library/TimeBaseLib/TimeBaseLib.inf
   MmCommunicationLib|Silicon/Ampere/AmpereAltraPkg/Library/MmCommunicationLib/MmCommunicationLib.inf
+  FlashLib|Silicon/Ampere/AmpereAltraPkg/Library/FlashLib/FlashLib.inf
 
   #
   # ARM PL011 UART Driver
@@ -252,6 +253,7 @@ [LibraryClasses.common.DXE_RUNTIME_DRIVER]
   ArmSmcLib|ArmPkg/Library/ArmSmcLib/ArmSmcLib.inf
   NVParamLib|Silicon/Ampere/AmpereAltraPkg/Library/NVParamLib/RuntimeNVParamLib.inf
   AmpereCpuLib|Silicon/Ampere/AmpereAltraPkg/Library/AmpereCpuLib/RuntimeAmpereCpuLib.inf
+  FlashLib|Silicon/Ampere/AmpereAltraPkg/Library/FlashLib/RuntimeFlashLib.inf
 
 [LibraryClasses.ARM,LibraryClasses.AARCH64]
   #
diff --git a/Silicon/Ampere/AmpereAltraPkg/Library/FlashLib/FlashLib.inf b/Silicon/Ampere/AmpereAltraPkg/Library/FlashLib/FlashLib.inf
new file mode 100644
index 000000000000..896d8fd965c8
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Library/FlashLib/FlashLib.inf
@@ -0,0 +1,35 @@
+## @file
+#
+# Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                   = 0x0001001B
+  BASE_NAME                     = FlashLib
+  FILE_GUID                     = 9E9D093D-6484-45AE-BA49-0745AA0BB481
+  MODULE_TYPE                   = BASE
+  VERSION_STRING                = 0.1
+  LIBRARY_CLASS                 = FlashLib
+  CONSTRUCTOR                   = FlashLibConstructor
+
+[Sources.common]
+  FlashLib.c
+  FlashLibCommon.c
+
+[Packages]
+  ArmPkg/ArmPkg.dec
+  ArmPlatformPkg/ArmPlatformPkg.dec
+  MdePkg/MdePkg.dec
+  Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec
+
+[LibraryClasses]
+  BaseMemoryLib
+  DebugLib
+  MemoryAllocationLib
+  MmCommunicationLib
+
+[Guids]
+  gSpiNorMmGuid
diff --git a/Silicon/Ampere/AmpereAltraPkg/Library/FlashLib/RuntimeFlashLib.inf b/Silicon/Ampere/AmpereAltraPkg/Library/FlashLib/RuntimeFlashLib.inf
new file mode 100644
index 000000000000..e729e29cf450
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Library/FlashLib/RuntimeFlashLib.inf
@@ -0,0 +1,37 @@
+## @file
+#
+# Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                   = 0x0001001B
+  BASE_NAME                     = RuntimeFlashLib
+  FILE_GUID                     = 0FDF1187-A2DA-4876-8B1F-6D1E928AA319
+  MODULE_TYPE                   = DXE_RUNTIME_DRIVER
+  VERSION_STRING                = 0.1
+  LIBRARY_CLASS                 = FlashLib
+  CONSTRUCTOR                   = FlashLibConstructor
+
+[Sources.common]
+  FlashLibCommon.c
+  RuntimeFlashLib.c
+
+[Packages]
+  ArmPkg/ArmPkg.dec
+  ArmPlatformPkg/ArmPlatformPkg.dec
+  MdePkg/MdePkg.dec
+  Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec
+
+[LibraryClasses]
+  BaseMemoryLib
+  DebugLib
+  MemoryAllocationLib
+
+[Guids]
+  gSpiNorMmGuid
+
+[Protocols]
+  gEfiMmCommunication2ProtocolGuid
diff --git a/Silicon/Ampere/AmpereAltraPkg/Include/Library/FlashLib.h b/Silicon/Ampere/AmpereAltraPkg/Include/Library/FlashLib.h
new file mode 100644
index 000000000000..ce50602f9934
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Include/Library/FlashLib.h
@@ -0,0 +1,118 @@
+/** @file
+
+  Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef FLASH_LIB_H_
+#define FLASH_LIB_H_
+
+/**
+  Get the information about the Flash region to store the FailSafe status.
+
+  @param[out] FailSafeBase       Base address of the FailSafe space.
+  @param[out] FailSafeSize       Total size of the FailSafe space.
+
+  @retval EFI_SUCCESS            Operation succeeded.
+  @retval EFI_INVALID_PARAMETER  FailSafeBase or FailSafeSize is NULL.
+  @retval Others                 An error has occurred.
+**/
+EFI_STATUS
+EFIAPI
+FlashGetFailSafeInfo (
+  OUT UINTN  *FailSafeBase,
+  OUT UINT32 *FailSafeSize
+  );
+
+/**
+  Get the information about the Flash region to store the NVRAM variables.
+
+  @param[out] NvRamBase          Base address of the NVRAM space.
+  @param[out] NvRamSize          Total size of the NVRAM space.
+
+  @retval EFI_SUCCESS            Operation succeeded.
+  @retval EFI_INVALID_PARAMETER  NvRamBase or NvRamSize is NULL.
+  @retval Others                 An error has occurred.
+**/
+EFI_STATUS
+EFIAPI
+FlashGetNvRamInfo (
+  OUT UINTN  *NvRamBase,
+  OUT UINT32 *NvRamSize
+  );
+
+/**
+  Get the information about the second Flash region to store the NVRAM variables.
+
+  @param[out] NvRam2Base         Base address of the NVRAM space.
+  @param[out] NvRam2Size         Total size of the NVRAM space.
+
+  @retval EFI_SUCCESS            Operation succeeded.
+  @retval EFI_INVALID_PARAMETER  NvRam2Base or NvRam2Size is NULL.
+  @retval Others                 An error has occurred.
+**/
+EFI_STATUS
+EFIAPI
+FlashGetNvRam2Info (
+  OUT UINTN  *NvRam2Base,
+  OUT UINT32 *NvRam2Size
+  );
+
+/**
+  Erase a region of the Flash.
+
+  @param[in] ByteAddress         Start address of the region.
+  @param[in] Length              Number of bytes to erase.
+
+  @retval EFI_SUCCESS            Operation succeeded.
+  @retval EFI_INVALID_PARAMETER  Length is Zero.
+  @retval Others                 An error has occurred.
+**/
+EFI_STATUS
+EFIAPI
+FlashEraseCommand (
+  IN  UINTN  ByteAddress,
+  IN  UINT32 Length
+  );
+
+/**
+  Write data buffer to the Flash.
+
+  @param[in] ByteAddress         Start address of the region.
+  @param[in] Buffer              Pointer to the data buffer.
+  @param[in] Length              Number of bytes to write.
+
+  @retval EFI_SUCCESS            Operation succeeded.
+  @retval EFI_INVALID_PARAMETER  Buffer is NULL or Length is Zero.
+  @retval Others                 An error has occurred.
+**/
+EFI_STATUS
+EFIAPI
+FlashWriteCommand (
+  IN  UINTN  ByteAddress,
+  IN  VOID   *Buffer,
+  IN  UINT32 Length
+  );
+
+/**
+  Read data from the Flash into Buffer.
+
+  @param[in]  ByteAddress        Start address of the region.
+  @param[out] Buffer             Pointer to the data buffer.
+  @param[in]  Length             Number of bytes to read.
+
+  @retval EFI_SUCCESS            Operation succeeded.
+  @retval EFI_INVALID_PARAMETER  Buffer is NULL or Length is Zero.
+  @retval Others                 An error has occurred.
+**/
+EFI_STATUS
+EFIAPI
+FlashReadCommand (
+  IN  UINTN  ByteAddress,
+  OUT VOID   *Buffer,
+  IN  UINT32 Length
+  );
+
+#endif /* FLASH_LIB_H_ */
diff --git a/Silicon/Ampere/AmpereAltraPkg/Library/FlashLib/FlashLibCommon.h b/Silicon/Ampere/AmpereAltraPkg/Library/FlashLib/FlashLibCommon.h
new file mode 100644
index 000000000000..327429a8f998
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Library/FlashLib/FlashLibCommon.h
@@ -0,0 +1,92 @@
+/** @file
+
+  Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef FLASH_LIB_COMMON_H_
+#define FLASH_LIB_COMMON_H_
+
+#define EFI_MM_MAX_TMP_BUF_SIZE           0x1000
+#define EFI_MM_MAX_PAYLOAD_SIZE           0x50
+
+#define MM_SPINOR_FUNC_GET_INFO           0x00
+#define MM_SPINOR_FUNC_READ               0x01
+#define MM_SPINOR_FUNC_WRITE              0x02
+#define MM_SPINOR_FUNC_ERASE              0x03
+#define MM_SPINOR_FUNC_GET_NVRAM_INFO     0x04
+#define MM_SPINOR_FUNC_GET_NVRAM2_INFO    0x05
+#define MM_SPINOR_FUNC_GET_FAILSAFE_INFO  0x06
+
+#define MM_SPINOR_RES_SUCCESS             0xAABBCC00
+#define MM_SPINOR_RES_FAIL                0xAABBCCFF
+
+#pragma pack(1)
+
+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    MessageLength;
+
+  //
+  // Designates an array of bytes that is MessageLength in size.
+  //
+  UINT8    Data[EFI_MM_MAX_PAYLOAD_SIZE];
+} EFI_MM_COMMUNICATE_REQUEST;
+
+typedef struct {
+  UINT64 Status;
+  UINT64 DeviceBase;
+  UINT64 PageSize;
+  UINT64 SectorSize;
+  UINT64 DeviceSize;
+} EFI_MM_COMMUNICATE_SPINOR_RESPONSE;
+
+typedef struct {
+  UINT64 Status;
+  UINT64 FailSafeBase;
+  UINT64 FailSafeSize;
+} EFI_MM_COMMUNICATE_FAILSAFE_INFO_RESPONSE;
+
+typedef struct {
+  UINT64 Status;
+  UINT64 NvRamBase;
+  UINT64 NvRamSize;
+} EFI_MM_COMMUNICATE_NVRAM_INFO_RESPONSE;
+
+#pragma pack()
+
+extern BOOLEAN                        gFlashLibRuntime;
+extern UINT8                          *gFlashLibPhysicalBuffer;
+extern UINT8                          *gFlashLibVirtualBuffer;
+
+/**
+  Provides an interface to access the Flash services via MM interface.
+
+  @param[in]  Request             Pointer to the request buffer
+  @param[in]  RequestDataSize     Size of the request buffer.
+  @param[out] Response            Pointer to the response buffer
+  @param[in]  ResponseDataSize    Size of the response buffer.
+
+  @retval EFI_SUCCESS             Operation succeeded.
+  @retval EFI_INVALID_PARAMETER   An invalid data parameter or an invalid
+                                  combination of data parameters.
+  @retval Others                  An error has occurred.
+**/
+EFI_STATUS
+FlashMmCommunicate (
+  IN  VOID   *Request,
+  IN  UINT32 RequestDataSize,
+  OUT VOID   *Response,
+  IN  UINT32 ResponseDataSize
+  );
+
+#endif /* FLASH_LIB_COMMON_H_ */
diff --git a/Silicon/Ampere/AmpereAltraPkg/Library/FlashLib/FlashLib.c b/Silicon/Ampere/AmpereAltraPkg/Library/FlashLib/FlashLib.c
new file mode 100644
index 000000000000..6c8a79699cd4
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Library/FlashLib/FlashLib.c
@@ -0,0 +1,83 @@
+/** @file
+
+  Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/MmCommunicationLib.h>
+
+#include "FlashLibCommon.h"
+
+/**
+  Constructor function of the FlashLib
+
+  @retval EFI_SUCCESS            The constructor executes successfully.
+**/
+EFI_STATUS
+EFIAPI
+FlashLibConstructor (
+  VOID
+  )
+{
+  gFlashLibPhysicalBuffer = AllocateZeroPool (EFI_MM_MAX_TMP_BUF_SIZE);
+  gFlashLibVirtualBuffer = gFlashLibPhysicalBuffer;
+  ASSERT (gFlashLibPhysicalBuffer != NULL);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Provides an interface to access the Flash services via MM interface.
+
+  @param[in]  Request             Pointer to the request buffer
+  @param[in]  RequestDataSize     Size of the request buffer.
+  @param[out] Response            Pointer to the response buffer
+  @param[in]  ResponseDataSize    Size of the response buffer.
+
+  @retval EFI_SUCCESS             Operation succeeded.
+  @retval EFI_INVALID_PARAMETER   An invalid data parameter or an invalid
+                                  combination of data parameters.
+  @retval Others                  An error has occurred.
+**/
+EFI_STATUS
+FlashMmCommunicate (
+  IN  VOID   *Request,
+  IN  UINT32 RequestDataSize,
+  OUT VOID   *Response,
+  IN  UINT32 ResponseDataSize
+  )
+{
+  EFI_MM_COMMUNICATE_REQUEST CommBuffer;
+  EFI_STATUS                 Status;
+
+  if (Request == NULL || RequestDataSize == 0
+      || RequestDataSize > EFI_MM_MAX_PAYLOAD_SIZE
+      || (ResponseDataSize == 0 && Response == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  CopyGuid (&CommBuffer.HeaderGuid, &gSpiNorMmGuid);
+  CommBuffer.MessageLength = RequestDataSize;
+  CopyMem (CommBuffer.Data, Request, RequestDataSize);
+
+  Status = MmCommunicationCommunicate (
+             &CommBuffer,
+             NULL
+             );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  if (ResponseDataSize > 0) {
+    CopyMem (Response, CommBuffer.Data, ResponseDataSize);
+  }
+
+  return EFI_SUCCESS;
+}
diff --git a/Silicon/Ampere/AmpereAltraPkg/Library/FlashLib/FlashLibCommon.c b/Silicon/Ampere/AmpereAltraPkg/Library/FlashLib/FlashLibCommon.c
new file mode 100644
index 000000000000..83695c857a11
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Library/FlashLib/FlashLibCommon.c
@@ -0,0 +1,372 @@
+/** @file
+
+  Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/FlashLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+#include "FlashLibCommon.h"
+
+BOOLEAN                       gFlashLibRuntime = FALSE;
+UINT8                         *gFlashLibPhysicalBuffer;
+UINT8                         *gFlashLibVirtualBuffer;
+
+/**
+  Convert Virtual Address to Physical Address at Runtime.
+
+  @param[in] VirtualPtr       Virtual Address Pointer.
+  @param[in] Size             Total bytes of the buffer.
+
+  @retval Pointer to the physical address of the converted buffer.
+**/
+STATIC
+UINT8 *
+ConvertToPhysicalBuffer (
+  IN UINT8  *VirtualPtr,
+  IN UINT32 Size
+  )
+{
+  if (gFlashLibRuntime) {
+    ASSERT (VirtualPtr != NULL);
+    CopyMem (gFlashLibVirtualBuffer, VirtualPtr, Size);
+    return gFlashLibPhysicalBuffer;
+  }
+
+  return VirtualPtr;
+}
+
+/**
+  Get the information about the Flash region to store the FailSafe status.
+
+  @param[out] FailSafeBase       Base address of the FailSafe space.
+  @param[out] FailSafeSize       Total size of the FailSafe space.
+
+  @retval EFI_SUCCESS            Operation succeeded.
+  @retval EFI_INVALID_PARAMETER  FailSafeBase or FailSafeSize is NULL.
+  @retval Others                 An error has occurred.
+**/
+EFI_STATUS
+EFIAPI
+FlashGetFailSafeInfo (
+  OUT UINTN  *FailSafeBase,
+  OUT UINT32 *FailSafeSize
+  )
+{
+  EFI_MM_COMMUNICATE_FAILSAFE_INFO_RESPONSE FailSafeInfo;
+  EFI_STATUS                                Status;
+  UINT64                                    MmData[5];
+
+  if (FailSafeBase == NULL || FailSafeSize == NULL ) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  MmData[0] = MM_SPINOR_FUNC_GET_FAILSAFE_INFO;
+
+  Status = FlashMmCommunicate (
+             MmData,
+             sizeof (MmData),
+             &FailSafeInfo,
+             sizeof (FailSafeInfo)
+             );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  if (FailSafeInfo.Status == MM_SPINOR_RES_SUCCESS) {
+    *FailSafeBase = FailSafeInfo.FailSafeBase;
+    *FailSafeSize = FailSafeInfo.FailSafeSize;
+
+    DEBUG ((
+      DEBUG_INFO,
+      "%a: FailSafe Base 0x%llx, Size 0x%lx\n",
+      __FUNCTION__,
+      *FailSafeBase,
+      *FailSafeSize
+      ));
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Get the information about the Flash region to store the NVRAM variables.
+
+  @param[out] NvRamBase          Base address of the NVRAM space.
+  @param[out] NvRamSize          Total size of the NVRAM space.
+
+  @retval EFI_SUCCESS            Operation succeeded.
+  @retval EFI_INVALID_PARAMETER  NvRamBase or NvRamSize is NULL.
+  @retval Others                 An error has occurred.
+**/
+EFI_STATUS
+EFIAPI
+FlashGetNvRamInfo (
+  OUT UINTN  *NvRamBase,
+  OUT UINT32 *NvRamSize
+  )
+{
+  EFI_MM_COMMUNICATE_NVRAM_INFO_RESPONSE    NvRamInfo;
+  EFI_STATUS                                Status;
+  UINT64                                    MmData[5];
+
+  if (NvRamBase == NULL || NvRamSize == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  MmData[0] = MM_SPINOR_FUNC_GET_NVRAM_INFO;
+
+  Status = FlashMmCommunicate (
+             MmData,
+             sizeof (MmData),
+             &NvRamInfo,
+             sizeof (NvRamInfo)
+             );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  if (NvRamInfo.Status == MM_SPINOR_RES_SUCCESS) {
+    *NvRamBase = NvRamInfo.NvRamBase;
+    *NvRamSize = NvRamInfo.NvRamSize;
+    DEBUG ((
+      DEBUG_INFO,
+      "%a: NVRAM Base 0x%llx, Size 0x%lx\n",
+      __FUNCTION__,
+      *NvRamBase,
+      *NvRamSize
+      ));
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Get the information about the second Flash region to store the NVRAM variables.
+
+  @param[out] NvRam2Base         Base address of the NVRAM space.
+  @param[out] NvRam2Size         Total size of the NVRAM space.
+
+  @retval EFI_SUCCESS            Operation succeeded.
+  @retval EFI_INVALID_PARAMETER  NvRam2Base or NvRam2Size is NULL.
+  @retval Others                 An error has occurred.
+**/
+EFI_STATUS
+EFIAPI
+FlashGetNvRam2Info (
+  OUT UINTN  *NvRam2Base,
+  OUT UINT32 *NvRam2Size
+  )
+{
+  EFI_MM_COMMUNICATE_NVRAM_INFO_RESPONSE NvRam2Info;
+  EFI_STATUS                             Status;
+  UINT64                                 MmData[5];
+
+  if (NvRam2Base == NULL || NvRam2Size == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  MmData[0] = MM_SPINOR_FUNC_GET_NVRAM2_INFO;
+
+  Status = FlashMmCommunicate (
+             MmData,
+             sizeof (MmData),
+             &NvRam2Info,
+             sizeof (NvRam2Info)
+             );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  if (NvRam2Info.Status == MM_SPINOR_RES_SUCCESS) {
+    *NvRam2Base = NvRam2Info.NvRamBase;
+    *NvRam2Size = NvRam2Info.NvRamSize;
+    DEBUG ((
+      DEBUG_INFO,
+      "%a: NVRAM2 Base 0x%llx, Size 0x%lx\n",
+      __FUNCTION__,
+      *NvRam2Base,
+      *NvRam2Size
+      ));
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Erase a region of the Flash.
+
+  @param[in] ByteAddress         Start address of the region.
+  @param[in] Length              Number of bytes to erase.
+
+  @retval EFI_SUCCESS            Operation succeeded.
+  @retval EFI_INVALID_PARAMETER  Length is Zero.
+  @retval Others                 An error has occurred.
+**/
+EFI_STATUS
+EFIAPI
+FlashEraseCommand (
+  IN  UINTN  ByteAddress,
+  IN  UINT32 Length
+  )
+{
+  EFI_MM_COMMUNICATE_SPINOR_RESPONSE MmSpiNorRes;
+  EFI_STATUS                         Status;
+  UINT64                             MmData[5];
+
+  if (Length == 0) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  MmData[0] = MM_SPINOR_FUNC_ERASE;
+  MmData[1] = ByteAddress;
+  MmData[2] = Length;
+
+  Status = FlashMmCommunicate (
+             MmData,
+             sizeof (MmData),
+             &MmSpiNorRes,
+             sizeof (MmSpiNorRes)
+             );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  if (MmSpiNorRes.Status != MM_SPINOR_RES_SUCCESS) {
+    DEBUG ((DEBUG_ERROR, "%a: Device error %llx\n", __FUNCTION__, MmSpiNorRes.Status));
+    return EFI_DEVICE_ERROR;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Write data buffer to the Flash.
+
+  @param[in] ByteAddress         Start address of the region.
+  @param[in] Buffer              Pointer to the data buffer.
+  @param[in] Length              Number of bytes to write.
+
+  @retval EFI_SUCCESS            Operation succeeded.
+  @retval EFI_INVALID_PARAMETER  Buffer is NULL or Length is Zero.
+  @retval Others                 An error has occurred.
+**/
+EFI_STATUS
+EFIAPI
+FlashWriteCommand (
+  IN  UINTN  ByteAddress,
+  IN  VOID   *Buffer,
+  IN  UINT32 Length
+  )
+{
+  EFI_MM_COMMUNICATE_SPINOR_RESPONSE MmSpiNorRes;
+  EFI_STATUS                         Status;
+  UINT64                             MmData[5];
+  UINTN                              Remain, NumWrite;
+  UINTN                              Count = 0;
+
+  if (Buffer == NULL || Length == 0) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Remain = Length;
+  while (Remain > 0) {
+    NumWrite = (Remain > EFI_MM_MAX_TMP_BUF_SIZE) ? EFI_MM_MAX_TMP_BUF_SIZE : Remain;
+
+    MmData[0] = MM_SPINOR_FUNC_WRITE;
+    MmData[1] = ByteAddress + Count;
+    MmData[2] = NumWrite;
+    MmData[3] = (UINT64)ConvertToPhysicalBuffer (Buffer + Count, NumWrite);
+
+    Status = FlashMmCommunicate (
+              MmData,
+              sizeof (MmData),
+              &MmSpiNorRes,
+              sizeof (MmSpiNorRes)
+              );
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+
+    if (MmSpiNorRes.Status != MM_SPINOR_RES_SUCCESS) {
+      DEBUG ((DEBUG_ERROR, "%a: Device error 0x%llx\n", __FUNCTION__, MmSpiNorRes.Status));
+      return EFI_DEVICE_ERROR;
+    }
+
+    Remain -= NumWrite;
+    Count += NumWrite;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Read data from the Flash into Buffer.
+
+  @param[in]  ByteAddress        Start address of the region.
+  @param[out] Buffer             Pointer to the data buffer.
+  @param[in]  Length             Number of bytes to read.
+
+  @retval EFI_SUCCESS            Operation succeeded.
+  @retval EFI_INVALID_PARAMETER  Buffer is NULL or Length is Zero.
+  @retval Others                 An error has occurred.
+**/
+EFI_STATUS
+EFIAPI
+FlashReadCommand (
+  IN  UINTN  ByteAddress,
+  OUT VOID   *Buffer,
+  IN  UINT32 Length
+  )
+{
+  EFI_MM_COMMUNICATE_SPINOR_RESPONSE MmSpiNorRes;
+  EFI_STATUS                         Status;
+  UINT64                             MmData[5];
+  UINTN                              Remain, NumRead;
+  UINTN                              Count = 0;
+
+  if (Buffer == NULL || Length == 0) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Remain = Length;
+  while (Remain > 0) {
+    NumRead = (Remain > EFI_MM_MAX_TMP_BUF_SIZE) ? EFI_MM_MAX_TMP_BUF_SIZE : Remain;
+
+    MmData[0] = MM_SPINOR_FUNC_READ;
+    MmData[1] = ByteAddress + Count;
+    MmData[2] = NumRead;
+    MmData[3] = (UINT64)gFlashLibPhysicalBuffer;  // Read data into the temp buffer with specified virtual address
+
+    Status = FlashMmCommunicate (
+              MmData,
+              sizeof (MmData),
+              &MmSpiNorRes,
+              sizeof (MmSpiNorRes)
+              );
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+
+    if (MmSpiNorRes.Status != MM_SPINOR_RES_SUCCESS) {
+      DEBUG ((DEBUG_ERROR, "%a: Device error %llx\n", __FUNCTION__, MmSpiNorRes.Status));
+      return EFI_DEVICE_ERROR;
+    }
+
+    //
+    // Get data from the virtual address of the temp buffer.
+    //
+    CopyMem ((VOID *)(Buffer + Count), (VOID *)gFlashLibVirtualBuffer, NumRead);
+    Remain -= NumRead;
+    Count += NumRead;
+  }
+
+  return EFI_SUCCESS;
+}
diff --git a/Silicon/Ampere/AmpereAltraPkg/Library/FlashLib/RuntimeFlashLib.c b/Silicon/Ampere/AmpereAltraPkg/Library/FlashLib/RuntimeFlashLib.c
new file mode 100644
index 000000000000..2dcd13e08146
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Library/FlashLib/RuntimeFlashLib.c
@@ -0,0 +1,137 @@
+/** @file
+
+  Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Protocol/MmCommunication2.h>
+
+#include "FlashLibCommon.h"
+
+STATIC EFI_MM_COMMUNICATION2_PROTOCOL *mMmCommunicationProtocol = NULL;
+
+/**
+  This is a notification function registered on EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE
+  event. It converts a pointer to a new virtual address.
+
+  @param[in] Event        Event whose notification function is being invoked.
+  @param[in] Context      Pointer to the notification function's context
+**/
+VOID
+EFIAPI
+FlashLibAddressChangeEvent (
+  IN EFI_EVENT Event,
+  IN VOID      *Context
+  )
+{
+  gRT->ConvertPointer (0x0, (VOID **)&gFlashLibVirtualBuffer);
+  gRT->ConvertPointer (0x0, (VOID **)&mMmCommunicationProtocol);
+
+  gFlashLibRuntime = TRUE;
+}
+
+/**
+  Constructor function of the RuntimeFlashLib.
+
+  @param[in] ImageHandle   The image handle.
+  @param[in] SystemTable   The system table.
+
+  @retval EFI_SUCCESS      Operation succeeded.
+  @retval Others           An error has occurred.
+**/
+EFI_STATUS
+EFIAPI
+FlashLibConstructor (
+  IN EFI_HANDLE       ImageHandle,
+  IN EFI_SYSTEM_TABLE *SystemTable
+  )
+{
+  EFI_EVENT  VirtualAddressChangeEvent = NULL;
+  EFI_STATUS Status;
+
+  gFlashLibPhysicalBuffer = AllocateRuntimeZeroPool (EFI_MM_MAX_TMP_BUF_SIZE);
+  gFlashLibVirtualBuffer = gFlashLibPhysicalBuffer;
+  ASSERT (gFlashLibPhysicalBuffer != NULL);
+
+  Status = gBS->LocateProtocol (
+                  &gEfiMmCommunication2ProtocolGuid,
+                  NULL,
+                  (VOID **)&mMmCommunicationProtocol
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  Status = gBS->CreateEvent (
+                  EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE,
+                  TPL_CALLBACK,
+                  FlashLibAddressChangeEvent,
+                  NULL,
+                  &VirtualAddressChangeEvent
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  return Status;
+}
+
+/**
+  Provides an interface to access the Flash services via MM interface.
+
+  @param[in]  Request             Pointer to the request buffer
+  @param[in]  RequestDataSize     Size of the request buffer.
+  @param[out] Response            Pointer to the response buffer
+  @param[in]  ResponseDataSize    Size of the response buffer.
+
+  @retval EFI_SUCCESS             Operation succeeded.
+  @retval EFI_INVALID_PARAMETER   An invalid data parameter or an invalid
+                                  combination of data parameters.
+  @retval Others                  An error has occurred.
+**/
+EFI_STATUS
+FlashMmCommunicate (
+  IN  VOID   *Request,
+  IN  UINT32 RequestDataSize,
+  OUT VOID   *Response,
+  IN  UINT32 ResponseDataSize
+  )
+{
+  EFI_MM_COMMUNICATE_REQUEST CommBuffer;
+  EFI_STATUS                 Status;
+
+  if (Request == NULL || RequestDataSize == 0
+      || RequestDataSize > EFI_MM_MAX_PAYLOAD_SIZE
+      || (ResponseDataSize == 0 && Response == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  CopyGuid (&CommBuffer.HeaderGuid, &gSpiNorMmGuid);
+  CommBuffer.MessageLength = RequestDataSize;
+  CopyMem (CommBuffer.Data, Request, RequestDataSize);
+
+  if (mMmCommunicationProtocol == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = mMmCommunicationProtocol->Communicate (
+                                       mMmCommunicationProtocol,
+                                       &CommBuffer,
+                                       &CommBuffer,
+                                       NULL
+                                       );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  if (ResponseDataSize > 0) {
+    CopyMem (Response, CommBuffer.Data, ResponseDataSize);
+  }
+
+  return EFI_SUCCESS;
+}
-- 
2.17.1


  parent reply	other threads:[~2021-11-17 16:49 UTC|newest]

Thread overview: 38+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-11-17 16:46 [edk2-platforms][PATCH v5 00/30] Add new Ampere Mt. Jade platform Nhi Pham
2021-11-17 16:46 ` [edk2-platforms][PATCH v5 01/30] Ampere: Initial support for Ampere Altra processor and " Nhi Pham
2021-11-17 16:46 ` Nhi Pham [this message]
2021-11-18 12:50   ` [edk2-platforms][PATCH v5 02/30] AmpereAltraPkg: Add FlashLib library instance Leif Lindholm
2021-11-17 16:47 ` [edk2-platforms][PATCH v5 03/30] AmpereAltraPkg: Add DwI2cLib " Nhi Pham
2021-11-17 16:47 ` [edk2-platforms][PATCH v5 04/30] AmpereAltraPkg: Add DwGpioLib " Nhi Pham
2021-11-17 16:47 ` [edk2-platforms][PATCH v5 05/30] JadePkg: Implement RealTimeClockLib for PCF85063 Nhi Pham
2021-11-17 16:47 ` [edk2-platforms][PATCH v5 06/30] AmpereAltraPkg: Add BootProgress support Nhi Pham
2021-11-17 16:47 ` [edk2-platforms][PATCH v5 07/30] AmpereAltraPkg: Support UEFI non-volatile variable Nhi Pham
2021-11-17 16:47 ` [edk2-platforms][PATCH v5 08/30] AmpereSiliconPkg: Add PlatformManagerUiLib library instance Nhi Pham
2021-11-17 16:47 ` [edk2-platforms][PATCH v5 09/30] AmpereAltraPkg, JadePkg: Add ACPI support Nhi Pham
2021-11-17 16:47 ` [edk2-platforms][PATCH v5 10/30] AmpereAltraPkg: Add Root Complex HOB data structures Nhi Pham
2021-11-17 16:47 ` [edk2-platforms][PATCH v5 11/30] AmpereAltraPkg: Add Ac01PcieLib library instance Nhi Pham
2021-11-18 12:33   ` Leif Lindholm
2021-11-18 13:33     ` Nhi Pham
2021-11-17 16:47 ` [edk2-platforms][PATCH v5 12/30] JadePkg: Add BoardPcieLib " Nhi Pham
2021-11-17 16:47 ` [edk2-platforms][PATCH v5 13/30] AmpereAltraPkg: Add driver to initialize PCIe Root Complex Nhi Pham
2021-11-17 16:47 ` [edk2-platforms][PATCH v5 14/30] AmpereAltraPkg: Add PciHostBridgeLib library instance Nhi Pham
2021-11-17 16:47 ` [edk2-platforms][PATCH v5 15/30] AmpereAltraPkg: Add PciSegmentLib " Nhi Pham
2021-11-18 13:10   ` Leif Lindholm
2021-11-17 16:47 ` [edk2-platforms][PATCH v5 16/30] JadePkg: Enable PciHostBridgeDxe driver Nhi Pham
2021-11-17 16:47 ` [edk2-platforms][PATCH v5 17/30] JadePkg: Add PciPlatformDxe driver Nhi Pham
2021-11-17 16:47 ` [edk2-platforms][PATCH v5 18/30] JadePkg: Add ACPI tables to support PCIe Nhi Pham
2021-11-17 16:47 ` [edk2-platforms][PATCH v5 19/30] JadePkg: Add ASpeed GOP driver Nhi Pham
2021-11-17 16:47 ` [edk2-platforms][PATCH v5 20/30] AmpereAltraPkg: Add Random Number Generator Support Nhi Pham
2021-11-17 16:47 ` [edk2-platforms][PATCH v5 21/30] JadePkg: Add SMBIOS tables support Nhi Pham
2021-11-17 16:47 ` [edk2-platforms][PATCH v5 22/30] AmpereAltraPkg: Add DebugInfoPei module Nhi Pham
2021-11-17 16:47 ` [edk2-platforms][PATCH v5 23/30] AmpereAltraPkg: Add configuration screen for PCIe Nhi Pham
2021-11-17 16:47 ` [edk2-platforms][PATCH v5 24/30] Ampere: Utilize the PCIe User setting Nhi Pham
2021-11-17 16:47 ` [edk2-platforms][PATCH v5 25/30] AmpereAltraPkg: Add platform info screen Nhi Pham
2021-11-17 16:47 ` [edk2-platforms][PATCH v5 26/30] AmpereAltraPkg: Add configuration screen for Memory Nhi Pham
2021-11-17 16:47 ` [edk2-platforms][PATCH v5 27/30] AmpereAltraPkg: Add configuration screen for CPU Nhi Pham
2021-11-17 16:47 ` [edk2-platforms][PATCH v5 28/30] AmpereAltraPkg: Add configuration screen for ACPI Nhi Pham
2021-11-17 16:47 ` [edk2-platforms][PATCH v5 29/30] AmpereAltraPkg: Add configuration screen for RAS Nhi Pham
2021-11-17 16:47 ` [edk2-platforms][PATCH v5 30/30] AmpereAltraPkg: Add configuration screen for Watchdog timer Nhi Pham
2021-11-18 13:02 ` [edk2-platforms][PATCH v5 00/30] Add new Ampere Mt. Jade platform Leif Lindholm
2021-11-18 13:45   ` Nhi Pham
2021-11-18 14:25     ` Leif Lindholm

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=20211117164727.10922-3-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