From: Vu Nguyen <[email protected]> Provides functions to access the NVRAM, NVRAM2 and FailSafe region on the Flash over MM communication.
Cc: Thang Nguyen <[email protected]> Cc: Chuong Tran <[email protected]> Cc: Phong Vo <[email protected]> Cc: Leif Lindholm <[email protected]> Cc: Michael D Kinney <[email protected]> Cc: Ard Biesheuvel <[email protected]> Cc: Nate DeSimone <[email protected]> Signed-off-by: Nhi Pham <[email protected]> --- 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 | 88 +++++ Silicon/Ampere/AmpereAltraPkg/Library/FlashLib/FlashLib.c | 86 +++++ Silicon/Ampere/AmpereAltraPkg/Library/FlashLib/FlashLibCommon.c | 372 ++++++++++++++++++++ Silicon/Ampere/AmpereAltraPkg/Library/FlashLib/RuntimeFlashLib.c | 141 ++++++++ 9 files changed, 882 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 3b33be6280ce..69a6caa56752 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..36ef9b8ca25d --- /dev/null +++ b/Silicon/Ampere/AmpereAltraPkg/Library/FlashLib/FlashLibCommon.h @@ -0,0 +1,88 @@ +/** @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() + +/** + 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..e844a5c73f6c --- /dev/null +++ b/Silicon/Ampere/AmpereAltraPkg/Library/FlashLib/FlashLib.c @@ -0,0 +1,86 @@ +/** @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" + +extern UINT8 *mTempBufferPhysical; +extern UINT8 *mTempBufferVirtual; + +/** + Constructor function of the FlashLib + + @retval EFI_SUCCESS The constructor executes successfully. +**/ +EFI_STATUS +EFIAPI +FlashLibConstructor ( + VOID + ) +{ + mTempBufferPhysical = AllocateZeroPool (EFI_MM_MAX_TMP_BUF_SIZE); + mTempBufferVirtual = mTempBufferPhysical; + ASSERT (mTempBufferPhysical != 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..08aab4ba9f0c --- /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 mIsEfiRuntime = FALSE; +UINT8 *mTempBufferPhysical; +UINT8 *mTempBufferVirtual; + +/** + 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 (mIsEfiRuntime) { + ASSERT (VirtualPtr != NULL); + CopyMem (mTempBufferVirtual, VirtualPtr, Size); + return mTempBufferPhysical; + } + + 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)mTempBufferPhysical; // 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 *)mTempBufferVirtual, 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..edea47313501 --- /dev/null +++ b/Silicon/Ampere/AmpereAltraPkg/Library/FlashLib/RuntimeFlashLib.c @@ -0,0 +1,141 @@ +/** @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" + +extern BOOLEAN mIsEfiRuntime; +extern UINT8 *mTempBufferPhysical; +extern UINT8 *mTempBufferVirtual; + +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 **)&mTempBufferVirtual); + gRT->ConvertPointer (0x0, (VOID **)&mMmCommunicationProtocol); + + mIsEfiRuntime = 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; + + mTempBufferPhysical = AllocateRuntimeZeroPool (EFI_MM_MAX_TMP_BUF_SIZE); + mTempBufferVirtual = mTempBufferPhysical; + ASSERT (mTempBufferPhysical != 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 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#82476): https://edk2.groups.io/g/devel/message/82476 Mute This Topic: https://groups.io/mt/86507912/21656 Group Owner: [email protected] Unsubscribe: https://edk2.groups.io/g/devel/unsub [[email protected]] -=-=-=-=-=-=-=-=-=-=-=-
