* [PATCH v4 07/10] Silicon/Phytium: Added flash driver support to Phytium Silicon
@ 2021-08-18 9:47 Ling Jia
2021-08-18 9:47 ` [PATCH v4 08/10] Silicon/Phytium: Added fvb driver for norflash Ling Jia
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: Ling Jia @ 2021-08-18 9:47 UTC (permalink / raw)
To: devel; +Cc: Leif Lindholm, Ling Jia
The SpiNorFlashDxe provided norflash initialization,
read-write, erase and other interfaces.
Signed-off-by: Ling Jia <jialing@phytium.com.cn>
---
Silicon/Phytium/PhytiumCommonPkg/PhytiumCommonPkg.dec | 1 +
Platform/Phytium/DurianPkg/DurianPkg.dsc | 5 +
Platform/Phytium/DurianPkg/DurianPkg.fdf | 1 +
Silicon/Phytium/FT2000-4Pkg/Drivers/SpiNorFlashDxe/SpiNorFlashDxe.inf | 48 +++
Silicon/Phytium/FT2000-4Pkg/Drivers/SpiNorFlashDxe/SpiNorFlashDxe.h | 95 +++++
Silicon/Phytium/PhytiumCommonPkg/Include/Protocol/SpiNorFlashProtocol.h | 74 ++++
Silicon/Phytium/FT2000-4Pkg/Drivers/SpiNorFlashDxe/SpiNorFlashDxe.c | 412 ++++++++++++++++++++
7 files changed, 636 insertions(+)
diff --git a/Silicon/Phytium/PhytiumCommonPkg/PhytiumCommonPkg.dec b/Silicon/Phytium/PhytiumCommonPkg/PhytiumCommonPkg.dec
index 69842b89e0..2686ba3cc3 100644
--- a/Silicon/Phytium/PhytiumCommonPkg/PhytiumCommonPkg.dec
+++ b/Silicon/Phytium/PhytiumCommonPkg/PhytiumCommonPkg.dec
@@ -48,3 +48,4 @@
[Protocols]
gSpiMasterProtocolGuid = { 0xdf093560, 0xf955, 0x11ea, { 0x96, 0x42, 0x43, 0x9d, 0x80, 0xdd, 0x0b, 0x7c}}
+ gSpiNorFlashProtocolGuid = { 0x00b4af42, 0xfbd0, 0x11ea, { 0x80, 0x3a, 0x27, 0xea, 0x5e, 0x65, 0xe3, 0xf6}}
diff --git a/Platform/Phytium/DurianPkg/DurianPkg.dsc b/Platform/Phytium/DurianPkg/DurianPkg.dsc
index 68698d613f..1c47051441 100644
--- a/Platform/Phytium/DurianPkg/DurianPkg.dsc
+++ b/Platform/Phytium/DurianPkg/DurianPkg.dsc
@@ -249,6 +249,11 @@
#
Silicon/Phytium/FT2000-4Pkg/Drivers/SpiDxe/SpiDxe.inf
+ #
+ # NOR Flash driver
+ #
+ Silicon/Phytium/FT2000-4Pkg/Drivers/SpiNorFlashDxe/SpiNorFlashDxe.inf
+
#
# Usb Support
#
diff --git a/Platform/Phytium/DurianPkg/DurianPkg.fdf b/Platform/Phytium/DurianPkg/DurianPkg.fdf
index 1cf1927484..831f7a6828 100644
--- a/Platform/Phytium/DurianPkg/DurianPkg.fdf
+++ b/Platform/Phytium/DurianPkg/DurianPkg.fdf
@@ -96,6 +96,7 @@ READ_LOCK_STATUS = TRUE
INF EmbeddedPkg/MetronomeDxe/MetronomeDxe.inf
INF Silicon/Phytium/FT2000-4Pkg/Drivers/SpiDxe/SpiDxe.inf
+ INF Silicon/Phytium/FT2000-4Pkg/Drivers/SpiNorFlashDxe/SpiNorFlashDxe.inf
INF MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
INF MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
diff --git a/Silicon/Phytium/FT2000-4Pkg/Drivers/SpiNorFlashDxe/SpiNorFlashDxe.inf b/Silicon/Phytium/FT2000-4Pkg/Drivers/SpiNorFlashDxe/SpiNorFlashDxe.inf
new file mode 100644
index 0000000000..2933dc502e
--- /dev/null
+++ b/Silicon/Phytium/FT2000-4Pkg/Drivers/SpiNorFlashDxe/SpiNorFlashDxe.inf
@@ -0,0 +1,48 @@
+#/** @file
+# Phytium NorFlash Drivers.
+#
+# Copyright (C) 2020, Phytium Technology Co, Ltd. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x0001001b
+ BASE_NAME = SpiNorFlashDxe
+ FILE_GUID = f37ef706-187c-48fd-9102-ddbf86f551be
+ MODULE_TYPE = DXE_RUNTIME_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = NorFlashPlatformEntryPoint
+
+[Sources.common]
+ SpiNorFlashDxe.c
+ SpiNorFlashDxe.h
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ MdePkg/MdePkg.dec
+ Silicon/Phytium/PhytiumCommonPkg/PhytiumCommonPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ DebugLib
+ IoLib
+ UefiLib
+ UefiBootServicesTableLib
+ UefiRuntimeLib
+ UefiDriverEntryPoint
+
+[FixedPcd]
+ gPhytiumPlatformTokenSpaceGuid.PcdSpiFlashBase
+ gPhytiumPlatformTokenSpaceGuid.PcdSpiFlashSize
+ gPhytiumPlatformTokenSpaceGuid.PcdSpiControllerBase
+[Guids]
+ gEfiEventVirtualAddressChangeGuid
+
+[Protocols]
+ gSpiMasterProtocolGuid
+ gSpiNorFlashProtocolGuid
+
+ [Depex]
+ TRUE
diff --git a/Silicon/Phytium/FT2000-4Pkg/Drivers/SpiNorFlashDxe/SpiNorFlashDxe.h b/Silicon/Phytium/FT2000-4Pkg/Drivers/SpiNorFlashDxe/SpiNorFlashDxe.h
new file mode 100644
index 0000000000..40d9607233
--- /dev/null
+++ b/Silicon/Phytium/FT2000-4Pkg/Drivers/SpiNorFlashDxe/SpiNorFlashDxe.h
@@ -0,0 +1,95 @@
+/** @file
+ Phytium NorFlash Drivers Header.
+
+ Copyright (C) 2020, Phytium Technology Co Ltd. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef SPI_NORFLASH_DXE_H_
+#define SPI_NORFLASH_DXE_H_
+
+#include <Protocol/SpiProtocol.h>
+#include <Protocol/SpiNorFlashProtocol.h>
+
+//
+// Norflash registers
+//
+#define REG_FLASH_CAP 0x000
+#define REG_RD_CFG 0x004
+#define REG_WR_CFG 0x008
+#define REG_FLUSH_REG 0x00C
+#define REG_CMD_PORT 0x010
+#define REG_ADDR_PORT 0x014
+#define REG_HD_PORT 0x018
+#define REG_LD_PORT 0x01C
+#define REG_CS_CFG 0x020
+#define REG_WIP_CFG 0x024
+#define REG_WP_REG 0x028
+
+#define NORFLASH_SIGNATURE SIGNATURE_32 ('F', 'T', 'S', 'F')
+#define SPI_FLASH_BASE FixedPcdGet64 (PcdSpiFlashBase)
+#define SPI_FLASH_SIZE FixedPcdGet64 (PcdSpiFlashSize)
+
+extern EFI_GUID gSpiMasterProtocolGuid;
+extern EFI_GUID gSpiNorFlashProtocolGuid;
+
+//
+// Platform Nor Flash Functions
+//
+EFI_STATUS
+EFIAPI
+NorFlashPlatformEraseSingleBlock (
+ IN UINTN BlockAddress
+ );
+
+EFI_STATUS
+EFIAPI
+NorFlashPlatformErase (
+ IN UINT64 Offset,
+ IN UINT64 Length
+ );
+
+EFI_STATUS
+EFIAPI
+NorFlashPlatformRead (
+ IN UINTN Address,
+ IN VOID *Buffer,
+ OUT UINT32 Len
+ );
+
+EFI_STATUS
+EFIAPI
+NorFlashPlatformWrite (
+ IN UINTN Address,
+ IN VOID *Buffer,
+ IN UINT32 Len
+ );
+
+EFI_STATUS
+EFIAPI
+NorFlashPlatformGetDevices (
+ OUT NOR_FLASH_DEVICE_DESCRIPTION *NorFlashDevices
+ );
+
+EFI_STATUS
+EFIAPI
+NorFlashPlatformInitialization (
+ VOID
+ );
+
+EFI_STATUS
+EFIAPI
+NorFlashPlatformEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+typedef struct {
+ EFI_NORFLASH_DRV_PROTOCOL FlashProtocol;
+ UINTN Signature;
+ EFI_HANDLE Handle;
+} NorFlash_Device;
+
+#endif // SPI_NORFLASH_DXE_H_
diff --git a/Silicon/Phytium/PhytiumCommonPkg/Include/Protocol/SpiNorFlashProtocol.h b/Silicon/Phytium/PhytiumCommonPkg/Include/Protocol/SpiNorFlashProtocol.h
new file mode 100644
index 0000000000..f925c7c0ff
--- /dev/null
+++ b/Silicon/Phytium/PhytiumCommonPkg/Include/Protocol/SpiNorFlashProtocol.h
@@ -0,0 +1,74 @@
+/** @file
+ The Header of Protocol For NorFlash.
+
+ Copyright (C) 2020, Phytium Technology Co Ltd. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef SPI_NORFLASH_H_
+#define SPI_NORFLASH_H_
+
+typedef struct _EFI_NORFLASH_DRV_PROTOCOL EFI_NORFLASH_DRV_PROTOCOL;
+extern EFI_GUID gSpiNorFlashProtocolGuid;
+
+typedef struct {
+ UINTN DeviceBaseAddress; // Start address of the Device Base Address (DBA)
+ UINTN RegionBaseAddress; // Start address of one single region
+ UINTN Size;
+ UINTN BlockSize;
+ EFI_GUID Guid;
+} NOR_FLASH_DEVICE_DESCRIPTION;
+
+typedef
+EFI_STATUS
+(EFIAPI *NORFLASH_PLATFORM_ERASE_INTERFACE) (
+ IN UINT64 Offset,
+ IN UINT64 Length
+ );
+
+typedef
+EFI_STATUS
+(EFIAPI *NORFLASH_PLATFORM_ERASESIGLEBLOCK_INTERFACE) (
+ IN UINTN BlockAddress
+ );
+
+typedef
+EFI_STATUS
+(EFIAPI *NORFLASH_PLATFORM_READ_INTERFACE) (
+ IN UINTN Address,
+ IN VOID *Buffer,
+ OUT UINT32 Len
+ );
+
+typedef
+EFI_STATUS
+(EFIAPI *NORFLASH_PLATFORM_WRITE_INTERFACE) (
+ IN UINTN Address,
+ IN VOID *Buffer,
+ IN UINT32 Len
+ );
+
+typedef
+EFI_STATUS
+(EFIAPI *NORFLASH_PLATFORM_GETDEVICE_INTERFACE) (
+ OUT NOR_FLASH_DEVICE_DESCRIPTION *NorFlashDevices
+ );
+
+typedef
+EFI_STATUS
+(EFIAPI *NORFLASH_PLATFORM_INIT_INTERFACE) (
+ VOID
+ );
+
+struct _EFI_NORFLASH_DRV_PROTOCOL{
+ NORFLASH_PLATFORM_INIT_INTERFACE Initialization;
+ NORFLASH_PLATFORM_GETDEVICE_INTERFACE GetDevices;
+ NORFLASH_PLATFORM_ERASE_INTERFACE Erase;
+ NORFLASH_PLATFORM_ERASESIGLEBLOCK_INTERFACE EraseSingleBlock;
+ NORFLASH_PLATFORM_READ_INTERFACE Read;
+ NORFLASH_PLATFORM_WRITE_INTERFACE Write;
+};
+
+#endif // SPI_NORFLASH_H_
diff --git a/Silicon/Phytium/FT2000-4Pkg/Drivers/SpiNorFlashDxe/SpiNorFlashDxe.c b/Silicon/Phytium/FT2000-4Pkg/Drivers/SpiNorFlashDxe/SpiNorFlashDxe.c
new file mode 100644
index 0000000000..051f88f1be
--- /dev/null
+++ b/Silicon/Phytium/FT2000-4Pkg/Drivers/SpiNorFlashDxe/SpiNorFlashDxe.c
@@ -0,0 +1,412 @@
+/** @file
+ Phytium NorFlash Drivers.
+
+ Copyright (C) 2020, Phytium Technology Co Ltd. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeLib.h>
+#include "SpiNorFlashDxe.h"
+
+STATIC EFI_EVENT mSpiNorFlashVirtualAddrChangeEvent;
+STATIC UINTN mNorFlashControlBase;
+STATIC UINT8 mCmdWrite;
+STATIC UINT8 mCmdErase;
+STATIC UINT8 mCmdPp;
+
+EFI_SPI_DRV_PROTOCOL *mSpiMasterProtocol;
+NorFlash_Device *mFlashInstance;
+
+NOR_FLASH_DEVICE_DESCRIPTION mNorFlashDevices = {
+ SPI_FLASH_BASE, /* Device Base Address */
+ SPI_FLASH_BASE, /* Region Base Address */
+ SIZE_1MB * 16, /* Size */
+ SIZE_64KB, /* Block Size */
+ {0xE7223039, 0x5836, 0x41E1, { 0xB5, 0x42, 0xD7, 0xEC, 0x73, 0x6C, 0x5E, 0x59 } }
+};
+
+
+/**
+ This function writed up to 256 bytes to flash through spi driver.
+
+ @param[in] Address The address of the flash.
+ @param[in] Buffer The pointer of buffer to be writed.
+ @param[in] BufferSizeInBytes The bytes to be writed.
+
+ @retval EFI_SUCCESS NorFlashWrite256() is executed successfully.
+
+**/
+STATIC
+EFI_STATUS
+NorFlashWrite256 (
+ IN UINTN Address,
+ IN VOID *Buffer,
+ IN UINT32 BufferSizeInBytes
+ )
+{
+ UINT32 Index;
+ UINT32 *TempBuffer;
+ UINT8 WriteSize;
+
+ TempBuffer = Buffer;
+ WriteSize = sizeof (UINT32);
+
+ if (BufferSizeInBytes > 256) {
+ DEBUG ((DEBUG_ERROR, "The max length is 256 bytes.\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((BufferSizeInBytes % WriteSize) != 0) {
+ DEBUG ((DEBUG_ERROR, "The length must four bytes aligned.\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Address % WriteSize) != 0) {
+ DEBUG ((DEBUG_ERROR, "The address must four bytes aligned.\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ mSpiMasterProtocol->SpiSetConfig (mCmdPp, 0x400000, REG_CMD_PORT);
+ mSpiMasterProtocol->SpiSetConfig (0, 0x1, REG_LD_PORT);
+
+ mSpiMasterProtocol->SpiSetConfig (mCmdWrite, 0x000208, REG_WR_CFG);
+
+ for (Index = 0; Index < (BufferSizeInBytes / WriteSize); Index++) {
+ MmioWrite32 ((Address + (Index * WriteSize)), TempBuffer[Index]);
+ }
+
+ mSpiMasterProtocol->SpiSetConfig (0, 0x1, REG_FLUSH_REG);
+
+ mSpiMasterProtocol->SpiSetConfig (0, 0x0, REG_WR_CFG);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function erased a sector of flash through spi driver.
+
+ @param[in] BlockAddress The sector address to be erased.
+
+ @retval None.
+
+**/
+STATIC
+inline void
+NorFlashPlatformEraseSector (
+ IN UINTN BlockAddress
+ )
+{
+ mSpiMasterProtocol->SpiSetConfig (mCmdPp, 0x400000, REG_CMD_PORT);
+ mSpiMasterProtocol->SpiSetConfig (0, 0x1, REG_LD_PORT);
+
+ mSpiMasterProtocol->SpiSetConfig (mCmdErase, 0x408000, REG_CMD_PORT);
+ mSpiMasterProtocol->SpiSetConfig (0, BlockAddress, REG_ADDR_PORT);
+ mSpiMasterProtocol->SpiSetConfig (0, 0x1, REG_LD_PORT);
+
+}
+
+
+/**
+ Fixup internal data so that EFI can be call in virtual mode.
+ Call the passed in Child Notify event and convert any pointers in
+ lib to virtual mode.
+
+ @param[in] Event The Event that is being processed.
+
+ @param[in] Context Event Context.
+
+ @retval None.
+
+**/
+VOID
+EFIAPI
+PlatformNorFlashVirtualNotifyEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EfiConvertPointer (0x0, (VOID **)&mNorFlashControlBase);
+ EfiConvertPointer (0x0, (VOID **)&mSpiMasterProtocol->SpiGetConfig);
+ EfiConvertPointer (0x0, (VOID **)&mSpiMasterProtocol->SpiSetConfig);
+ EfiConvertPointer (0x0, (VOID **)&mSpiMasterProtocol);
+}
+
+
+/**
+ This function inited the flash platform.
+
+ @param None.
+
+ @retval EFI_SUCCESS NorFlashPlatformInitialization() is executed successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+NorFlashPlatformInitialization (
+ VOID
+ )
+{
+
+ mCmdWrite = 0x2;
+ mCmdErase = 0xD8;
+ mCmdPp = 0x6;
+
+ mNorFlashControlBase = FixedPcdGet64 (PcdSpiControllerBase);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This function geted the flash device information.
+
+ @param[out] NorFlashDevices the pointer to store flash device information.
+ @param[out] Count the number of the flash device.
+
+ @retval EFI_SUCCESS NorFlashPlatformGetDevices() is executed successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+NorFlashPlatformGetDevices (
+ OUT NOR_FLASH_DEVICE_DESCRIPTION *NorFlashDevices
+ )
+{
+
+ *NorFlashDevices = mNorFlashDevices;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This function readed flash content form the specified area of flash.
+
+ @param[in] Address The address of the flash.
+ @param[in] Buffer The pointer of the Buffer to be stored.
+ @param[out] Len The bytes readed form flash.
+
+ @retval EFI_SUCCESS NorFlashPlatformRead() is executed successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+NorFlashPlatformRead (
+ IN UINTN Address,
+ IN VOID *Buffer,
+ OUT UINT32 Len
+ )
+{
+
+ DEBUG ((DEBUG_BLKIO,
+ "NorFlashPlatformRead: Address: 0x%lx Buffer:0x%p Len:0x%x\n",
+ Address, Buffer, Len
+ ));
+
+ CopyMem ((VOID *)Buffer, (VOID *)Address, Len);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This function erased one block flash content.
+
+ @param[in] BlockAddress the BlockAddress to be erased.
+
+ @retval EFI_SUCCESS NorFlashPlatformEraseSingleBlock() is executed successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+NorFlashPlatformEraseSingleBlock (
+ IN UINTN BlockAddress
+ )
+{
+
+ NorFlashPlatformEraseSector (BlockAddress);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This function erased the flash content of the specified area.
+
+ @param[in] Offset the offset of the flash.
+ @param[in] Length length to be erased.
+
+ @retval EFI_SUCCESS NorFlashPlatformErase() is executed successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+NorFlashPlatformErase (
+ IN UINT64 Offset,
+ IN UINT64 Length
+ )
+{
+ EFI_STATUS Status;
+ UINT64 Index;
+ UINT64 Count;
+
+ Status = EFI_SUCCESS;
+ if ((Length % SIZE_64KB) == 0) {
+ Count = Length / SIZE_64KB;
+ for (Index = 0; Index < Count; Index++) {
+ NorFlashPlatformEraseSingleBlock (Offset);
+ Offset += SIZE_64KB;
+ }
+ } else {
+ Status = EFI_INVALID_PARAMETER;
+ }
+
+ return Status;
+}
+
+
+/**
+ This function writed data to flash.
+
+ @param[in] Address the address of the flash.
+
+ @param[in] Buffer the pointer of the Buffer to be writed.
+
+ @param[in] BufferSizeInBytes the bytes of the Buffer.
+
+ @retval EFI_SUCCESS NorFlashPlatformWrite() is executed successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+NorFlashPlatformWrite (
+ IN UINTN Address,
+ IN VOID *Buffer,
+ IN UINT32 BufferSizeInBytes
+ )
+{
+ UINT32 Index;
+ UINT32 Remainder;
+ UINT32 Quotient;
+ EFI_STATUS Status;
+ UINTN TmpAddress;
+
+ TmpAddress = Address;
+ Remainder = BufferSizeInBytes % 256;
+ Quotient = BufferSizeInBytes / 256;
+
+ if (BufferSizeInBytes <= 256) {
+ Status = NorFlashWrite256 (TmpAddress, Buffer, BufferSizeInBytes);
+ } else {
+ for (Index = 0; Index < Quotient; Index++) {
+ Status = NorFlashWrite256 (TmpAddress, Buffer, 256);
+ TmpAddress += 256;
+ Buffer += 256;
+ }
+
+ if (Remainder != 0) {
+ Status = NorFlashWrite256 (TmpAddress, Buffer, Remainder);
+ }
+ }
+
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ return EFI_SUCCESS;
+
+}
+
+
+/**
+ This function inited the flash driver protocol.
+
+ @param[in] NorFlashProtocol A pointer to the norflash protocol struct.
+
+ @retval EFI_SUCCESS NorFlashPlatformInitProtocol() is executed successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+NorFlashPlatformInitProtocol (
+ IN EFI_NORFLASH_DRV_PROTOCOL *NorFlashProtocol
+ )
+{
+ NorFlashProtocol->Initialization = NorFlashPlatformInitialization;
+ NorFlashProtocol->GetDevices = NorFlashPlatformGetDevices;
+ NorFlashProtocol->Erase = NorFlashPlatformErase;
+ NorFlashProtocol->EraseSingleBlock = NorFlashPlatformEraseSingleBlock;
+ NorFlashProtocol->Read = NorFlashPlatformRead;
+ NorFlashProtocol->Write = NorFlashPlatformWrite;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This function is the entrypoint of the norflash driver.
+
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.
+
+ @param[in] SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The entry point is executed successfully.
+
+ @retval other Some error occurs when executing this entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+NorFlashPlatformEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ Status = gBS->LocateProtocol (
+ &gSpiMasterProtocolGuid,
+ NULL,
+ (VOID **)&mSpiMasterProtocol
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ mFlashInstance = AllocateRuntimeZeroPool (sizeof (NorFlash_Device));
+ if (mFlashInstance == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ NorFlashPlatformInitProtocol (&mFlashInstance->FlashProtocol);
+
+ mFlashInstance->Signature = NORFLASH_SIGNATURE;
+
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &(mFlashInstance->Handle),
+ &gSpiNorFlashProtocolGuid,
+ &(mFlashInstance->FlashProtocol),
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //Register for the virtual address change event
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ PlatformNorFlashVirtualNotifyEvent,
+ NULL,
+ &gEfiEventVirtualAddressChangeGuid,
+ &mSpiNorFlashVirtualAddrChangeEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
--
2.25.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH v4 08/10] Silicon/Phytium: Added fvb driver for norflash
2021-08-18 9:47 [PATCH v4 07/10] Silicon/Phytium: Added flash driver support to Phytium Silicon Ling Jia
@ 2021-08-18 9:47 ` Ling Jia
2021-08-18 9:47 ` [PATCH v4 09/10] Silicon/Phytium: Added Rtc driver to FT2000/4 Ling Jia
2021-08-18 9:47 ` [PATCH v4 10/10] Maintainers.txt: Added maintainers and reviewers for the DurianPkg Ling Jia
2 siblings, 0 replies; 4+ messages in thread
From: Ling Jia @ 2021-08-18 9:47 UTC (permalink / raw)
To: devel; +Cc: Leif Lindholm, Ling Jia
The FlashFvbDxe provided the fvb protocol,
which requested by the flash operators.
Signed-off-by: Ling Jia <jialing@phytium.com.cn>
Reviewed-by: Leif Lindholm <leif@nuviainc.com>
---
Platform/Phytium/DurianPkg/DurianPkg.dsc | 1 +
Platform/Phytium/DurianPkg/DurianPkg.fdf | 1 +
Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.inf | 61 +
Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.h | 104 ++
Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.c | 1304 ++++++++++++++++++++
5 files changed, 1471 insertions(+)
diff --git a/Platform/Phytium/DurianPkg/DurianPkg.dsc b/Platform/Phytium/DurianPkg/DurianPkg.dsc
index 1c47051441..99034365d3 100644
--- a/Platform/Phytium/DurianPkg/DurianPkg.dsc
+++ b/Platform/Phytium/DurianPkg/DurianPkg.dsc
@@ -253,6 +253,7 @@
# NOR Flash driver
#
Silicon/Phytium/FT2000-4Pkg/Drivers/SpiNorFlashDxe/SpiNorFlashDxe.inf
+ Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.inf
#
# Usb Support
diff --git a/Platform/Phytium/DurianPkg/DurianPkg.fdf b/Platform/Phytium/DurianPkg/DurianPkg.fdf
index 831f7a6828..67458458dd 100644
--- a/Platform/Phytium/DurianPkg/DurianPkg.fdf
+++ b/Platform/Phytium/DurianPkg/DurianPkg.fdf
@@ -103,6 +103,7 @@ READ_LOCK_STATUS = TRUE
INF ArmPkg/Drivers/ArmGic/ArmGicDxe.inf
INF ArmPkg/Drivers/CpuDxe/CpuDxe.inf
+ INF Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.inf
INF ArmPkg/Drivers/TimerDxe/TimerDxe.inf
INF ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdogDxe.inf
diff --git a/Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.inf b/Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.inf
new file mode 100644
index 0000000000..ff23721d6e
--- /dev/null
+++ b/Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.inf
@@ -0,0 +1,61 @@
+#/** @file
+# Phytium NorFlash Fvb Drivers.
+#
+# Copyright (c) 2011 - 2014, ARM Ltd. All rights reserved.<BR>
+# Copyright (C) 2020, Phytium Technology Co, Ltd. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x0001001b
+ BASE_NAME = FlashFvbDxe
+ FILE_GUID = b8923820-3e7c-11eb-b12c-17525e90ecc8
+ MODULE_TYPE = DXE_RUNTIME_DRIVER
+ VERSION_STRING = 0.1
+ ENTRY_POINT = FvbEntryPoint
+
+[Sources]
+ FlashFvbDxe.c
+ FlashFvbDxe.h
+
+[Packages]
+ EmbeddedPkg/EmbeddedPkg.dec
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ Silicon/Phytium/PhytiumCommonPkg/PhytiumCommonPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ DebugLib
+ DxeServicesTableLib
+ HobLib
+ MemoryAllocationLib
+ UefiBootServicesTableLib
+ UefiRuntimeLib
+ UefiDriverEntryPoint
+
+[Guids]
+ gEfiAuthenticatedVariableGuid
+ gEfiEventVirtualAddressChangeGuid
+ gEfiSystemNvDataFvGuid
+ gEfiVariableGuid
+
+[Protocols]
+ gEfiDevicePathProtocolGuid
+ gEfiFirmwareVolumeBlockProtocolGuid
+ gSpiNorFlashProtocolGuid
+
+[Pcd.common]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase64
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase64
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize
+ gPhytiumPlatformTokenSpaceGuid.PcdSpiFlashBase
+ gPhytiumPlatformTokenSpaceGuid.PcdSpiFlashSize
+
+[Depex]
+ gSpiNorFlashProtocolGuid
diff --git a/Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.h b/Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.h
new file mode 100644
index 0000000000..e63ff9f220
--- /dev/null
+++ b/Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.h
@@ -0,0 +1,104 @@
+/** @file
+ Phytium NorFlash Fvb Drivers Header.
+
+ Copyright (C) 2020, Phytium Technology Co Ltd. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#ifndef FVB_FLASH_DXE_H_
+#define FVB_FLASH_DXE_H_
+
+#include <Protocol/BlockIo.h>
+#include <Protocol/FirmwareVolumeBlock.h>
+#include <Protocol/SpiNorFlashProtocol.h>
+
+#define GET_DATA_OFFSET(BaseAddr, Lba, LbaSize) ((BaseAddr) + (UINTN)((Lba) * (LbaSize)))
+#define FVB_FLASH_SIGNATURE SIGNATURE_32('S', 'N', 'O', 'R')
+#define INSTANCE_FROM_FVB_THIS(a) CR(a, FT_FVB_DEVICE, FvbProtocol, FVB_FLASH_SIGNATURE)
+
+typedef struct _FT_FVB_DEVICE FT_FVB_DEVICE;
+
+#define NOR_FLASH_ERASE_RETRY 10
+
+typedef struct {
+ VENDOR_DEVICE_PATH Vendor;
+ EFI_DEVICE_PATH_PROTOCOL End;
+ } FT_FVB_DEVICE_PATH;
+
+struct _FT_FVB_DEVICE {
+ UINT32 Signature;
+ EFI_HANDLE Handle;
+
+ UINTN DeviceBaseAddress;
+ UINTN RegionBaseAddress;
+ UINTN Size;
+ EFI_LBA StartLba;
+ EFI_BLOCK_IO_MEDIA Media;
+
+ EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL FvbProtocol;
+
+ FT_FVB_DEVICE_PATH DevicePath;
+ EFI_NORFLASH_DRV_PROTOCOL *SpiFlashProtocol;
+ VOID *ShadowBuffer;
+ UINTN FvbSize;
+ };
+
+EFI_STATUS
+EFIAPI
+FvbGetAttributes (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL * This,
+ OUT EFI_FVB_ATTRIBUTES_2 * Attributes
+ );
+
+EFI_STATUS
+EFIAPI
+FvbSetAttributes (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL * This,
+ IN OUT EFI_FVB_ATTRIBUTES_2 * Attributes
+ );
+
+EFI_STATUS
+EFIAPI
+FvbGetPhysicalAddress (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL * This,
+ OUT EFI_PHYSICAL_ADDRESS * Address
+ );
+
+EFI_STATUS
+EFIAPI
+FvbGetBlockSize (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL * This,
+ IN EFI_LBA Lba,
+ OUT UINTN * BlockSize,
+ OUT UINTN * NumberOfBlocks
+ );
+
+EFI_STATUS
+EFIAPI
+FvbRead (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL * This,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN OUT UINTN * NumBytes,
+ IN OUT UINT8 * Buffer
+ );
+
+EFI_STATUS
+EFIAPI
+FvbWrite (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL * This,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN OUT UINTN * NumBytes,
+ IN UINT8 * Buffer
+ );
+
+EFI_STATUS
+EFIAPI
+FvbEraseBlocks (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL * This,
+ ...
+ );
+
+#endif // FVB_FLASH_DXE_H_
diff --git a/Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.c b/Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.c
new file mode 100644
index 0000000000..794db68987
--- /dev/null
+++ b/Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.c
@@ -0,0 +1,1304 @@
+/** @file
+ Phytium NorFlash Fvb Drivers.
+
+ Copyright (c) 2011 - 2014, ARM Ltd. All rights reserved.<BR>
+ Copyright (C) 2020, Phytium Technology Co Ltd. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/HobLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeLib.h>
+#include <Guid/VariableFormat.h>
+
+#include "FlashFvbDxe.h"
+
+STATIC EFI_EVENT FvbVirtualAddrChangeEvent;
+STATIC FT_FVB_DEVICE *FvbDevice;
+STATIC UINTN mFlashNvStorageVariableBase;
+STATIC UINTN mFlashNvStorageFtwWorkingBase;
+STATIC UINTN mFlashNvStorageFtwSpareBase;
+STATIC UINT32 mFlashNvStorageVariableSize;
+STATIC UINT32 mFlashNvStorageFtwWorkingSize;
+STATIC UINT32 mFlashNvStorageFtwSpareSize;
+
+STATIC FT_FVB_DEVICE FvbFlashInstanceTemplate = {
+ FVB_FLASH_SIGNATURE, // Signature
+ NULL, // Handle ... NEED TO BE FILLED
+ 0, // DeviceBaseAddress ... NEED TO BE FILLED
+ 0, // RegionBaseAddress ... NEED TO BE FILLED
+ 0, // Size ... NEED TO BE FILLED
+ 0, // StartLba
+ {
+ 0, // MediaId ... NEED TO BE FILLED
+ FALSE, // RemovableMedia
+ TRUE, // MediaPresent
+ FALSE, // LogicalPartition
+ FALSE, // ReadOnly
+ FALSE, // WriteCaching;
+ 0, // BlockSize ... NEED TO BE FILLED
+ 4, // IoAlign
+ 0, // LastBlock ... NEED TO BE FILLED
+ 0, // LowestAlignedLba
+ 1, // LogicalBlocksPerPhysicalBlock
+ }, //Media;
+ {
+ FvbGetAttributes, // GetAttributes
+ FvbSetAttributes, // SetAttributes
+ FvbGetPhysicalAddress, // GetPhysicalAddress
+ FvbGetBlockSize, // GetBlockSize
+ FvbRead, // Read
+ FvbWrite, // Write
+ FvbEraseBlocks, // EraseBlocks
+ NULL, // ParentHandle
+ }, // FvbProtoccol;
+
+ {
+ {
+ {
+ HARDWARE_DEVICE_PATH,
+ HW_VENDOR_DP,
+ {
+ (UINT8) sizeof (VENDOR_DEVICE_PATH),
+ (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
+ }
+ },
+ {
+ 0x0, 0x0, 0x0, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }
+ }, // GUID ... NEED TO BE FILLED
+ },
+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ {
+ sizeof (EFI_DEVICE_PATH_PROTOCOL),
+ 0
+ }
+ }
+ }, // DevicePath
+
+ NULL, // SpiFlashProtocol ... NEED TO BE FILLED
+ NULL, // ShadowBuffer ... NEED TO BE FILLED
+ 0 // Fvb Size
+};
+
+
+/**
+ Erases a single block of flash.
+
+ @param[in] FlashInstance The poiter of the fvb device sturct.
+
+ @param[in] BlockAddress Physical address of Lba to be erased.
+
+ @retval EFI_SUCCESS The erase single block request successfully completed.
+
+**/
+STATIC
+EFI_STATUS
+FvbFlashEraseSingleBlock (
+ IN FT_FVB_DEVICE *FlashInstance,
+ IN UINTN BlockAddress
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ EFI_TPL OriginalTPL;
+
+ if ( ! EfiAtRuntime ()) {
+ OriginalTPL = gBS->RaiseTPL (TPL_HIGH_LEVEL);
+ } else {
+ OriginalTPL = TPL_HIGH_LEVEL;
+ }
+
+ Index = 0;
+
+ do {
+ Status = FlashInstance->SpiFlashProtocol->EraseSingleBlock (BlockAddress);
+ Index++;
+ } while ((Index < NOR_FLASH_ERASE_RETRY) && (Status == EFI_WRITE_PROTECTED));
+
+ if (Index == NOR_FLASH_ERASE_RETRY) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "EraseSingleBlock(BlockAddress=0x%08x: BlockLocked Error (try to erase % d times)\n",
+ BlockAddress,
+ Index
+ ));
+ }
+
+ if ( ! EfiAtRuntime ()) {
+ gBS->RestoreTPL (OriginalTPL);
+ }
+
+ return Status;
+}
+
+
+/**
+ Readed the specified number of bytes from the form the block to output buffer.
+
+ @param[in] FlashInstance The pointer of FT_FVB_DEVICE instance.
+
+ @param[in] Lba The starting logical block index to write to.
+
+ @param[in] Offset Offset into the block at which to begin writing.
+
+ @param[in] BufferSizeInBytes The number of bytes to be writed.
+
+ @param[out] Buffer The pointer to a caller-allocated buffer that
+ contains the source for the write.
+
+ @retval EFI_SUCCESS FvbFlashRead() is executed successfully.
+
+**/
+STATIC
+EFI_STATUS
+FvbFlashRead (
+ IN FT_FVB_DEVICE *FlashInstance,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN UINTN BufferSizeInBytes,
+ OUT VOID *Buffer
+ )
+{
+ UINTN Address;
+
+ Address = GET_DATA_OFFSET (
+ FlashInstance->RegionBaseAddress,
+ Lba,
+ FlashInstance->Media.BlockSize
+ ) + Offset;
+
+ if (BufferSizeInBytes == 0) {
+ return EFI_SUCCESS;
+ }
+
+ // The buffer must be valid
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return FlashInstance->SpiFlashProtocol->Read (Address, Buffer, BufferSizeInBytes);
+}
+
+
+/**
+ Write a full or portion of a block. It must not span block boundaries; that is,
+ Offset + *NumBytes <= FlashInstance->Media.BlockSize.
+
+ @param[in] FlashInstance The pointer of FT_FVB_DEVICE instance.
+
+ @param[in] Lba The starting logical block index to write to.
+
+ @param[in] Offset Offset into the block at which to begin writing.
+
+ @param[in] BufferSizeInBytes The number of bytes to be writed.
+
+ @param[out] Buffer The pointer to a caller-allocated buffer that
+ contains the source for the write.
+
+ @retval EFI_SUCCESS FvbWriteBlock() is executed successfully.
+
+ @retval EFI_BAD_BUFFER_SIZE The write spaned block boundaries.
+
+**/
+STATIC
+EFI_STATUS
+FvbWriteBlock (
+ IN FT_FVB_DEVICE *FlashInstance,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN UINTN BufferSizeInBytes,
+ IN UINT8 *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINTN BlockSize;
+ UINTN BlockAddress;
+
+ // Detect WriteDisabled state
+ if (FlashInstance->Media.ReadOnly == TRUE) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "FvbWriteBlock: ERROR - Can not write:Device is in WriteDisabled state.\n"
+ ));
+ // It is in WriteDisabled state, return an error right away
+ return EFI_ACCESS_DENIED;
+ }
+
+ // Cache the block size to avoid de-referencing pointers all the time
+ BlockSize = FlashInstance->Media.BlockSize;
+
+ // The write must not span block boundaries.
+ // We need to check each variable individually because adding two large values together overflows.
+ if ((Offset >= BlockSize) ||
+ (BufferSizeInBytes > BlockSize) ||
+ ((Offset + BufferSizeInBytes) > BlockSize))
+ {
+ DEBUG ((
+ DEBUG_ERROR,
+ "FvbWriteBlock: ERROR - EFI_BAD_BUFFER_SIZE: (Offset =0x %x + NumBytes =0x%x) > BlockSize =0x%x\n",
+ Offset,
+ BufferSizeInBytes,
+ BlockSize
+ ));
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ // We must have some bytes to write
+ if (BufferSizeInBytes == 0) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "FvbWriteBlock: ERROR - EFI_BAD_BUFFER_SIZE: NumBytes == 0\n"
+ ));
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ // Check we did get some memory. Buffer is BlockSize.
+ if (FlashInstance->ShadowBuffer == NULL) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "FvbWriteBlock: ERROR - ShadowBuffer is NULL!\n"
+ ));
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Write the word to NOR.
+ //
+ BlockAddress = GET_DATA_OFFSET (
+ FlashInstance->RegionBaseAddress,
+ Lba,
+ FlashInstance->Media.BlockSize
+ );
+
+ // Read NOR Flash data into shadow buffer
+ Status = FlashInstance->SpiFlashProtocol->Read (
+ BlockAddress,
+ FlashInstance->ShadowBuffer,
+ BlockSize
+ );
+ if (EFI_ERROR (Status)) {
+ // Return one of the pre-approved error statuses
+ return EFI_DEVICE_ERROR;
+ }
+
+ // Put the data at the appropriate location inside the buffer area
+ CopyMem (
+ (VOID *) ((UINTN)FlashInstance->ShadowBuffer + Offset),
+ Buffer,
+ BufferSizeInBytes
+ );
+
+ Status = FlashInstance->SpiFlashProtocol->EraseSingleBlock (BlockAddress);
+ if (EFI_ERROR (Status)) {
+ // Return one of the pre-approved error statuses
+ return EFI_DEVICE_ERROR;
+ }
+
+ // Write the modified buffer back to the NorFlash
+ Status = FlashInstance->SpiFlashProtocol->Write (BlockAddress,
+ FlashInstance->ShadowBuffer,
+ BlockSize
+ );
+ if (EFI_ERROR (Status)) {
+ // Return one of the pre-approved error statuses
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Writes the specified number of bytes from the input buffer to the block.
+
+ @param[in] FlashInstance The pointer of FT_FVB_DEVICE instance.
+
+ @param[in] Lba The starting logical block index to write to.
+
+ @param[in] Offset Offset into the block at which to begin writing.
+
+ @param[in] BufferSizeInBytes The number of bytes to be writed.
+
+ @param[in] Buffer The pointer to a caller-allocated buffer that
+ contains the source for the write.
+
+ @retval EFI_SUCCESS FvbFlashWrite() is executed successfully.
+
+ @retval EFI_WRITE_PROTECTED Flash state is in the WriteDisabled state.
+
+ @retval EFI_INVALID_PARAMETER The pointer of Buffer is NULL.
+
+**/
+STATIC
+EFI_STATUS
+FvbFlashWrite (
+ IN FT_FVB_DEVICE *FlashInstance,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN UINTN BufferSizeInBytes,
+ IN VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINT32 BlockSize;
+ UINT32 BlockOffset;
+ UINTN RemainingBytes;
+ UINTN WriteSize;
+
+ if (FlashInstance->Media.ReadOnly == TRUE) {
+ return EFI_WRITE_PROTECTED;
+ }
+
+ if (BufferSizeInBytes == 0) {
+ return EFI_SUCCESS;
+ }
+
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = EFI_SUCCESS;
+ BlockSize = FlashInstance->Media.BlockSize;
+ BlockOffset = Offset;
+ RemainingBytes = BufferSizeInBytes;
+
+ // The write must not span block boundaries.
+ // We need to check each variable individually because adding
+ // two large values together overflows.
+ if (Offset >= BlockSize) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "FvbFlashWrite: ERROR - EFI_BAD_BUFFER_SIZE: Offset =0x%x > BlockSize =0x%x\n",
+ Offset,
+ BlockSize
+ ));
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ // We must have some bytes to read
+ // Write either all the remaining bytes, or the number of bytes that bring
+ // us up to a block boundary, whichever is less.
+ // (DiskOffset | (BlockSize - 1)) + 1) rounds DiskOffset up to the next
+ // block boundary (even if it is already on one).
+ WriteSize = MIN (RemainingBytes, BlockSize - BlockOffset);
+
+ do {
+ Status = FvbWriteBlock (
+ FlashInstance,
+ Lba,
+ BlockOffset,
+ WriteSize,
+ Buffer
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ // Now continue writing either all the remaining bytes or single blocks.
+ RemainingBytes -= WriteSize;
+ Buffer = (UINT8 *) Buffer + WriteSize;
+ Lba++;
+ BlockOffset = 0;
+ WriteSize = MIN (RemainingBytes, BlockSize);
+ } while (RemainingBytes);
+
+ return Status;
+}
+
+
+/**
+ Initialises the FV Header and Variable Store Header
+ to support variable operations.
+
+ @param[in] Ptr Location to initialise the headers.
+
+ @retval EFI_SUCCESS FvbInitFvAndVariableStoreHeaders()
+ is executed successfully.
+
+**/
+STATIC
+EFI_STATUS
+FvbInitFvAndVariableStoreHeaders (
+ IN FT_FVB_DEVICE *FlashInstance
+ )
+{
+ EFI_STATUS Status;
+ VOID * Headers;
+ UINTN HeadersLength;
+ UINT32 TempAttributes;
+ EFI_FIRMWARE_VOLUME_HEADER *FirmwareVolumeHeader;
+ VARIABLE_STORE_HEADER *VariableStoreHeader;
+
+ HeadersLength = sizeof (EFI_FIRMWARE_VOLUME_HEADER) +
+ sizeof (EFI_FV_BLOCK_MAP_ENTRY) +
+ sizeof (VARIABLE_STORE_HEADER);
+
+ Headers = AllocateZeroPool (HeadersLength);
+
+ // FirmwareVolumeHeader->FvLength is declared to have the Variable area
+ // AND the FTW working area AND the FTW Spare contiguous.
+ ASSERT (mFlashNvStorageVariableBase + mFlashNvStorageVariableSize == mFlashNvStorageFtwWorkingBase);
+ ASSERT (mFlashNvStorageFtwWorkingBase + mFlashNvStorageFtwWorkingSize == mFlashNvStorageFtwSpareBase);
+
+ // Check if the size of the area is at least one block size
+ ASSERT ((mFlashNvStorageVariableSize > 0) && (mFlashNvStorageVariableSize / FlashInstance->Media.BlockSize > 0));
+ ASSERT ((mFlashNvStorageFtwWorkingSize > 0) && (mFlashNvStorageFtwWorkingSize / FlashInstance->Media.BlockSize > 0));
+ ASSERT ((mFlashNvStorageFtwSpareSize > 0) && (mFlashNvStorageFtwSpareSize / FlashInstance->Media.BlockSize > 0));
+
+ // Ensure the Variable area Base Addresses are aligned on a block size boundaries
+ ASSERT (mFlashNvStorageVariableBase % FlashInstance->Media.BlockSize == 0);
+ ASSERT (mFlashNvStorageFtwWorkingBase % FlashInstance->Media.BlockSize == 0);
+ ASSERT (mFlashNvStorageFtwSpareBase % FlashInstance->Media.BlockSize == 0);
+
+ //
+ // EFI_FIRMWARE_VOLUME_HEADER
+ //
+ FirmwareVolumeHeader = (EFI_FIRMWARE_VOLUME_HEADER *)Headers;
+ CopyGuid (&FirmwareVolumeHeader->FileSystemGuid, &gEfiSystemNvDataFvGuid);
+ FirmwareVolumeHeader->FvLength = FlashInstance->FvbSize;
+
+ TempAttributes = (
+ EFI_FVB2_READ_ENABLED_CAP | // Reads may be enabled
+ EFI_FVB2_READ_STATUS | // Reads are currently enabled
+ EFI_FVB2_STICKY_WRITE | // A block erase is required to
+ EFI_FVB2_MEMORY_MAPPED | // It is memory mapped
+ EFI_FVB2_ERASE_POLARITY | // After erasure all bits take this value
+ EFI_FVB2_WRITE_STATUS | // Writes are currently enabled
+ EFI_FVB2_WRITE_ENABLED_CAP // Writes may be enabled
+ );
+
+ FirmwareVolumeHeader->Signature = EFI_FVH_SIGNATURE;
+ FirmwareVolumeHeader->Attributes = (EFI_FVB_ATTRIBUTES_2) TempAttributes;
+
+ FirmwareVolumeHeader->HeaderLength = sizeof (EFI_FIRMWARE_VOLUME_HEADER) + sizeof (EFI_FV_BLOCK_MAP_ENTRY);
+ FirmwareVolumeHeader->Revision = EFI_FVH_REVISION;
+ FirmwareVolumeHeader->BlockMap[0].NumBlocks = FlashInstance->Media.LastBlock + 1;
+ FirmwareVolumeHeader->BlockMap[0].Length = FlashInstance->Media.BlockSize;
+ FirmwareVolumeHeader->BlockMap[1].NumBlocks = 0;
+ FirmwareVolumeHeader->BlockMap[1].Length = 0;
+ FirmwareVolumeHeader->Checksum = CalculateCheckSum16 (
+ (UINT16 *)FirmwareVolumeHeader,
+ FirmwareVolumeHeader->HeaderLength
+ );
+
+ //
+ // VARIABLE_STORE_HEADER
+ //
+ VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINTN)Headers + FirmwareVolumeHeader->HeaderLength);
+ CopyGuid (&VariableStoreHeader->Signature, &gEfiAuthenticatedVariableGuid);
+ VariableStoreHeader->Size = mFlashNvStorageVariableSize - FirmwareVolumeHeader->HeaderLength;
+ VariableStoreHeader->Format = VARIABLE_STORE_FORMATTED;
+ VariableStoreHeader->State = VARIABLE_STORE_HEALTHY;
+
+ // Install the combined super-header in the NorFlash
+ Status = FvbWrite (&FlashInstance->FvbProtocol, 0, 0, &HeadersLength, Headers);
+
+ FreePool (Headers);
+
+ return Status;
+}
+
+
+/**
+ Check the integrity of firmware volume header.
+
+ @param[in] FwVolHeader A pointer to a firmware volume header
+
+ @retval EFI_SUCCESS The firmware volume is consistent
+
+ @retval EFI_NOT_FOUND The firmware volume has been corrupted.
+
+**/
+STATIC
+EFI_STATUS
+FvbValidateFvHeader (
+ IN FT_FVB_DEVICE *FlashInstance
+ )
+{
+ UINT16 Checksum;
+ EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
+ VARIABLE_STORE_HEADER *VariableStoreHeader;
+ UINTN VariableStoreLength;
+ UINTN FvLength;
+
+ FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)GET_DATA_OFFSET (FlashInstance->RegionBaseAddress,
+ FlashInstance->StartLba,
+ FlashInstance->Media.BlockSize
+ );
+ FvLength = FlashInstance->FvbSize;
+
+
+ if ((FwVolHeader->Revision != EFI_FVH_REVISION) ||
+ (FwVolHeader->Signature != EFI_FVH_SIGNATURE) ||
+ (FwVolHeader->FvLength != FvLength))
+ {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ValidateFvHeader: No Firmware Volume header present\n"
+ ));
+ return EFI_NOT_FOUND;
+ }
+
+ // Check the Firmware Volume Guid
+ if ( CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiSystemNvDataFvGuid) == FALSE ) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ValidateFvHeader: Firmware Volume Guid non-compatible\n"
+ ));
+ return EFI_NOT_FOUND;
+ }
+
+ // Verify the header checksum
+ Checksum = CalculateSum16 ((UINT16 *)FwVolHeader, FwVolHeader->HeaderLength);
+ if (Checksum != 0) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ValidateFvHeader: FV checksum is invalid (Checksum:0x%X)\n",
+ Checksum));
+ return EFI_NOT_FOUND;
+ }
+
+ VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINTN)FwVolHeader + FwVolHeader->HeaderLength);
+
+ // Check the Variable Store Guid
+ if ( ! CompareGuid (&VariableStoreHeader->Signature, &gEfiVariableGuid) &&
+ ! CompareGuid (&VariableStoreHeader->Signature,
+ &gEfiAuthenticatedVariableGuid))
+ {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: Variable Store Guid non-compatible\n"
+ ));
+ return EFI_NOT_FOUND;
+ }
+
+ VariableStoreLength = mFlashNvStorageVariableSize - FwVolHeader->HeaderLength;
+ if (VariableStoreHeader->Size != VariableStoreLength) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ValidateFvHeader: Variable Store Length does not match\n"
+ ));
+ return EFI_NOT_FOUND;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ The FvbGetAttributes() function retrieves the attributes and
+ current settings of the block.
+
+ @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
+
+ @param Attributes Pointer to EFI_FVB_ATTRIBUTES_2 in which the attributes and
+ current settings are returned.
+ Type EFI_FVB_ATTRIBUTES_2 is defined in
+ EFI_FIRMWARE_VOLUME_HEADER.
+
+ @retval EFI_SUCCESS The firmware volume attributes were returned.
+
+**/
+EFI_STATUS
+EFIAPI
+FvbGetAttributes (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ OUT EFI_FVB_ATTRIBUTES_2 *Attributes
+ )
+{
+ EFI_FVB_ATTRIBUTES_2 FlashFvbAttributes;
+ CONST FT_FVB_DEVICE *FlashInstance;
+
+ FlashInstance = INSTANCE_FROM_FVB_THIS (This);
+
+ FlashFvbAttributes = (EFI_FVB_ATTRIBUTES_2) (
+ EFI_FVB2_READ_ENABLED_CAP | // Reads may be enabled
+ EFI_FVB2_READ_STATUS | // Reads are currently enabled
+ EFI_FVB2_STICKY_WRITE | // A block erase is required to flip bits into EFI_FVB2_ERASE_POLARITY
+ EFI_FVB2_MEMORY_MAPPED | // It is memory mapped
+ EFI_FVB2_ERASE_POLARITY // After erasure all bits take this value (i.e. '1')
+ );
+
+ // Check if it is write protected
+ if (FlashInstance->Media.ReadOnly != TRUE) {
+ FlashFvbAttributes = FlashFvbAttributes |
+ EFI_FVB2_WRITE_STATUS | // Writes are currently enabled
+ EFI_FVB2_WRITE_ENABLED_CAP; // Writes may be enabled
+ }
+
+ *Attributes = FlashFvbAttributes;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ The FvbSetAttributes() function sets configurable firmware volume attributes
+ and returns the new settings of the firmware volume.
+
+ @param This EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
+
+ @param Attributes On input, Attributes is a pointer to
+ EFI_FVB_ATTRIBUTES_2 that contains the desired
+ firmware volume settings.
+ On successful return, it contains the new
+ settings of the firmware volume.
+
+ @retval EFI_SUCCESS The firmware volume attributes were returned.
+
+ @retval EFI_INVALID_PARAMETER The attributes requested are in conflict with
+ the capabilities as declared in the firmware
+ volume header.
+
+**/
+EFI_STATUS
+EFIAPI
+FvbSetAttributes (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+
+/**
+ The FvbGetPhysicalAddress() function retrieves the base address of
+ a memory-mapped firmware volume. This function should be called
+ only for memory-mapped firmware volumes.
+
+ @param This EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
+
+ @param Address Pointer to a caller-allocated
+ EFI_PHYSICAL_ADDRESS that, on successful
+ return from GetPhysicalAddress(), contains the
+ base address of the firmware volume.
+
+ @retval EFI_SUCCESS The firmware volume base address was returned.
+
+ @retval EFI_NOT_SUPPORTED The firmware volume is not memory mapped.
+
+**/
+EFI_STATUS
+EFIAPI
+FvbGetPhysicalAddress (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ OUT EFI_PHYSICAL_ADDRESS *Address
+ )
+{
+ ASSERT (Address != NULL);
+
+ *Address = mFlashNvStorageVariableBase;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ The FvbGetBlockSize() function retrieves the size of the requested
+ block. It also returns the number of additional blocks with
+ the identical size. The FvbGetBlockSize() function is used to
+ retrieve the block map (see EFI_FIRMWARE_VOLUME_HEADER).
+
+
+ @param This EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
+
+ @param Lba Indicates the block whose size to return.
+
+ @param BlockSize Pointer to a caller-allocated UINTN in which
+ the size of the block is returned.
+
+ @param NumberOfBlocks Pointer to a caller-allocated UINTN in
+ which the number of consecutive blocks,
+ starting with Lba, is returned. All
+ blocks in this range have a size of
+ BlockSize.
+
+
+ @retval EFI_SUCCESS The firmware volume base address was returned.
+
+ @retval EFI_INVALID_PARAMETER The requested LBA is out of range.
+
+**/
+EFI_STATUS
+EFIAPI
+FvbGetBlockSize (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ IN EFI_LBA Lba,
+ OUT UINTN *BlockSize,
+ OUT UINTN *NumberOfBlocks
+ )
+{
+ EFI_STATUS Status;
+ FT_FVB_DEVICE *FlashInstance;
+
+ FlashInstance = INSTANCE_FROM_FVB_THIS (This);
+
+ if (Lba > FlashInstance->Media.LastBlock) {
+ Status = EFI_INVALID_PARAMETER;
+ } else {
+ // This is easy because in this platform each NorFlash device has equal sized blocks.
+ *BlockSize = (UINTN) FlashInstance->Media.BlockSize;
+ *NumberOfBlocks = (UINTN) (FlashInstance->Media.LastBlock - Lba + 1);
+ Status = EFI_SUCCESS;
+ }
+
+ return Status;
+}
+
+
+/**
+ Reads the specified number of bytes into a buffer from the specified block.
+
+ The FvbRead() function reads the requested number of bytes from the
+ requested block and stores them in the provided buffer.
+
+ @param This EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
+
+ @param Lba The starting logical block index from which to read.
+
+ @param Offset Offset into the block at which to begin reading.
+
+ @param NumBytes Pointer to a UINTN.
+ At entry, *NumBytes contains the total size of the
+ buffer.
+ At exit, *NumBytes contains the total number of
+ bytes read.
+
+ @param Buffer Pointer to a caller-allocated buffer that will be
+ used to hold the data that is read.
+
+ @retval EFI_SUCCESS The firmware volume was read successfully, and
+ contents are in Buffer.
+
+ @retval EFI_BAD_BUFFER_SIZE Read attempted across an LBA boundary.
+ On output, NumBytes contains the total number of
+ bytes returned in Buffer.
+
+ @retval EFI_ACCESS_DENIED The firmware volume is in the ReadDisabled state.
+
+ @retval EFI_DEVICE_ERROR The block device is not functioning correctly and
+ could not be read.
+**/
+EFI_STATUS
+EFIAPI
+FvbRead (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN OUT UINTN *NumBytes,
+ IN OUT UINT8 *Buffer
+ )
+{
+ UINTN BlockSize;
+ FT_FVB_DEVICE *FlashInstance;
+ EFI_STATUS Status;
+
+ FlashInstance = INSTANCE_FROM_FVB_THIS (This);
+
+ // Cache the block size to avoid de-referencing pointers all the time
+ BlockSize = FlashInstance->Media.BlockSize;
+
+ // The read must not span block boundaries.
+ // We need to check each variable individually because adding two large values together overflows.
+ if ((Offset >= BlockSize) ||
+ (*NumBytes > BlockSize) ||
+ ((Offset + *NumBytes) > BlockSize)) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ // We must have some bytes to read
+ if (*NumBytes == 0) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ Status = FvbFlashRead (
+ FlashInstance,
+ FlashInstance->StartLba + Lba,
+ Offset,
+ *NumBytes,
+ Buffer
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Writes the specified number of bytes from the input buffer to the block.
+
+ The FvbWrite() function writes the specified number of bytes from
+ the provided buffer to the specified block and offset.
+
+ @param This EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
+
+ @param Lba The starting logical block index to write to.
+
+ @param Offset Offset into the block at which to begin writing.
+
+ @param NumBytes The pointer to a UINTN.
+ At entry, *NumBytes contains the total size of the
+ buffer.
+ At exit, *NumBytes contains the total number of
+ bytes actually written.
+
+ @param Buffer The pointer to a caller-allocated buffer that
+ contains the source for the write.
+
+ @retval EFI_SUCCESS The firmware volume was written successfully.
+
+ @retval EFI_BAD_BUFFER_SIZE The write was attempted across an LBA boundary.
+ On output, NumBytes contains the total number of
+ bytes actually written.
+
+ @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisabled state.
+
+ @retval EFI_DEVICE_ERROR The block device is malfunctioning and could not be
+ written.
+
+**/
+EFI_STATUS
+EFIAPI
+FvbWrite (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN OUT UINTN *NumBytes,
+ IN UINT8 *Buffer
+ )
+{
+ FT_FVB_DEVICE *FlashInstance;
+
+ FlashInstance = INSTANCE_FROM_FVB_THIS (This);
+
+ return FvbFlashWrite (FlashInstance,
+ FlashInstance->StartLba + Lba,
+ Offset,
+ *NumBytes,
+ Buffer
+ );
+}
+
+
+/**
+ Erases and initialises a firmware volume block.
+
+ The FvbEraseBlocks() function erases one or more blocks as denoted
+ by the variable argument list.
+
+ @param This EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL
+ instance.
+
+ @param ... The variable argument list is a list of tuples.
+ Each tuple describes a range of LBAs to erase
+ and consists of the following:
+ An EFI_LBA that indicates the starting LBA
+ A UINTN that indicates the number of blocks
+ to erase.
+
+ The list is terminated with an
+ EFI_LBA_LIST_TERMINATOR.
+
+ @retval EFI_SUCCESS The erase request successfully completed.
+
+ @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisabled
+ state.
+
+ @retval EFI_DEVICE_ERROR The block device is not functioning correctly
+ and could not be written.
+ The firmware device may have been partially
+ erased.
+
+ @retval EFI_INVALID_PARAMETER One or more of the LBAs listed in the variable
+ argument list do not exist in the firmware
+ volume.
+
+**/
+EFI_STATUS
+EFIAPI
+FvbEraseBlocks (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ ...
+ )
+{
+ EFI_STATUS Status;
+ VA_LIST Args;
+ UINTN BlockAddress; // Physical address of Lba to erase
+ EFI_LBA StartingLba; // Lba from which we start erasing
+ UINTN NumOfLba; // Number of Lba blocks to erase
+ FT_FVB_DEVICE *Instance;
+
+ Instance = INSTANCE_FROM_FVB_THIS (This);
+
+ Status = EFI_SUCCESS;
+
+ // Detect WriteDisabled state
+ if (Instance->Media.ReadOnly == TRUE) {
+ // Firmware volume is in WriteDisabled state
+ DEBUG ((
+ DEBUG_ERROR,
+ "FvbEraseBlocks: ERROR - Device is in WriteDisabled state.\n"
+ ));
+ return EFI_ACCESS_DENIED;
+ }
+
+ // Before erasing, check the entire list of parameters to ensure all specified blocks are valid
+
+ VA_START (Args, This);
+ do {
+ // Get the Lba from which we start erasing
+ StartingLba = VA_ARG (Args, EFI_LBA);
+
+ // Have we reached the end of the list?
+ if (StartingLba == EFI_LBA_LIST_TERMINATOR) {
+ //Exit the while loop
+ break;
+ }
+
+ // How many Lba blocks are we requested to erase?
+ NumOfLba = VA_ARG (Args, UINT32);
+
+ // All blocks must be within range
+ if ((NumOfLba == 0) || ((Instance->StartLba + StartingLba + NumOfLba - 1) > Instance->Media.LastBlock)) {
+ VA_END (Args);
+ DEBUG ((
+ DEBUG_ERROR,
+ "FvbEraseBlocks: ERROR - Lba range goes past the last Lba.\n"
+ ));
+ Status = EFI_INVALID_PARAMETER;
+ goto EXIT;
+ }
+ } while (TRUE);
+
+ VA_END (Args);
+
+ //
+ // To get here, all must be ok, so start erasing
+ //
+ VA_START (Args, This);
+ do {
+ // Get the Lba from which we start erasing
+ StartingLba = VA_ARG (Args, EFI_LBA);
+
+ // Have we reached the end of the list?
+ if (StartingLba == EFI_LBA_LIST_TERMINATOR) {
+ // Exit the while loop
+ break;
+ }
+
+ // How many Lba blocks are we requested to erase?
+ NumOfLba = VA_ARG (Args, UINT32);
+
+ // Go through each one and erase it
+ while (NumOfLba > 0) {
+ // Get the physical address of Lba to erase
+ BlockAddress = GET_DATA_OFFSET (
+ Instance->RegionBaseAddress,
+ Instance->StartLba + StartingLba,
+ Instance->Media.BlockSize
+ );
+
+ // Erase it
+ Status = FvbFlashEraseSingleBlock (Instance, BlockAddress);
+ if (EFI_ERROR (Status)) {
+ VA_END (Args);
+ Status = EFI_DEVICE_ERROR;
+ goto EXIT;
+ }
+
+ // Move to the next Lba
+ StartingLba++;
+ NumOfLba--;
+ }
+ } while (TRUE);
+
+ VA_END (Args);
+
+EXIT:
+ return Status;
+}
+
+
+/**
+ This function inited the NorFlash instance.
+
+ @param[in][out] FlashInstance The pointer of FT_FVB_DEVICE instance.
+
+ @retval EFI_SUCCESS PhytNorFlashFvbInitialize() is executed successfully.
+
+**/
+STATIC
+EFI_STATUS
+PhytNorFlashFvbInitialize (
+ IN OUT FT_FVB_DEVICE *FlashInstance
+ )
+{
+ EFI_STATUS Status;
+ UINT32 FvbNumLba;
+ EFI_BOOT_MODE BootMode;
+ UINTN TotalFvbSize;
+
+ // Declare the Non-Volatile storage as EFI_MEMORY_RUNTIME
+ Status = gDS->AddMemorySpace (
+ EfiGcdMemoryTypeMemoryMappedIo,
+ mFlashNvStorageVariableBase,
+ FlashInstance->FvbSize,
+ EFI_MEMORY_UC | EFI_MEMORY_RUNTIME
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = gDS->SetMemorySpaceAttributes (
+ mFlashNvStorageVariableBase,
+ FlashInstance->FvbSize,
+ EFI_MEMORY_UC | EFI_MEMORY_RUNTIME
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ TotalFvbSize = FlashInstance->FvbSize;
+
+ // Set the index of the first LBA for the FVB
+ FlashInstance->StartLba = (mFlashNvStorageVariableBase - FlashInstance->RegionBaseAddress) / FlashInstance->Media.BlockSize;
+
+ BootMode = GetBootModeHob ();
+ if (BootMode == BOOT_WITH_DEFAULT_SETTINGS) {
+ Status = EFI_INVALID_PARAMETER;
+ } else {
+ // Determine if there is a valid header at the beginning of the NorFlash
+ Status = FvbValidateFvHeader (FlashInstance);
+ }
+
+ // Install the Default FVB header if required
+ if (EFI_ERROR (Status)) {
+ // There is no valid header, so time to install one.
+ DEBUG ((
+ DEBUG_ERROR,
+ "NorFlashFvbInitialize: ERROR - The FVB Header is invalid. Installing a correct one for this volume.\n"
+ ));
+
+ // Erase all the NorFlash that is reserved for variable storage
+ FvbNumLba = TotalFvbSize / FlashInstance->Media.BlockSize;
+
+ Status = FvbEraseBlocks (
+ &FlashInstance->FvbProtocol,
+ (EFI_LBA)0,
+ FvbNumLba,
+ EFI_LBA_LIST_TERMINATOR
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ // Install all appropriate headers
+ Status = FvbInitFvAndVariableStoreHeaders (FlashInstance);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ return Status;
+}
+
+
+/**
+ The CreateInstance() function Create Fvb Instance.
+
+ @retval EFI_SUCCESS Create Instance successfully.
+
+ @retval other Create Instance failed.
+
+**/
+STATIC
+EFI_STATUS
+CreateInstance (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ NOR_FLASH_DEVICE_DESCRIPTION *NorFlashDevice;
+
+ // Locate flash protocols
+ Status = gBS->LocateProtocol (&gSpiNorFlashProtocolGuid,
+ NULL,
+ (VOID **)&FvbDevice->SpiFlashProtocol);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "Cannot locate NorFlash protocol.\n"
+ ));
+ return Status;
+ }
+
+ NorFlashDevice = AllocateRuntimePool (sizeof (NOR_FLASH_DEVICE_DESCRIPTION));
+ if (NorFlashDevice == NULL) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "Cannot Allocate NorFlashDevice Pool.\n"
+ ));
+ return Status;
+ }
+
+ Status = FvbDevice->SpiFlashProtocol->GetDevices (NorFlashDevice);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = FvbDevice->SpiFlashProtocol->Initialization ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ FvbDevice->DeviceBaseAddress = NorFlashDevice->DeviceBaseAddress;
+ FvbDevice->RegionBaseAddress = NorFlashDevice->RegionBaseAddress;
+ FvbDevice->Size = NorFlashDevice->Size;
+
+ FvbDevice->Media.MediaId = 0;
+ FvbDevice->Media.BlockSize = NorFlashDevice->BlockSize;
+ FvbDevice->Media.LastBlock = (FvbDevice->Size / FvbDevice->Media.BlockSize) - 1;
+ FvbDevice->FvbSize = mFlashNvStorageVariableSize +
+ mFlashNvStorageFtwWorkingSize +
+ mFlashNvStorageFtwSpareSize;
+
+ CopyGuid (&FvbDevice->DevicePath.Vendor.Guid, &NorFlashDevice->Guid);
+
+ FvbDevice->ShadowBuffer = AllocateRuntimePool (FvbDevice->Media.BlockSize);
+ if (FvbDevice->ShadowBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &FvbDevice->Handle,
+ &gEfiDevicePathProtocolGuid,
+ &FvbDevice->DevicePath,
+ &gEfiFirmwareVolumeBlockProtocolGuid,
+ &FvbDevice->FvbProtocol,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (FvbDevice);
+ return Status;
+ }
+
+ Status = PhytNorFlashFvbInitialize (FvbDevice);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "PhytNorFlashFvbInitialize: Fail to init NorFlash devices\n"
+ ));
+ return Status;
+ }
+
+ FreePool (NorFlashDevice);
+
+ return Status;
+}
+
+
+/**
+ Fixup internal data so that EFI can be call in virtual mode.
+ Call the passed in Child Notify event and convert any pointers
+ in lib to virtual mode.
+
+ @param[in] Event The Event that is being processed.
+
+ @param[in] Context Event Context.
+
+ @retval None.
+
+**/
+STATIC
+VOID
+EFIAPI
+FvbVirtualNotifyEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ // Convert SpiFlashProtocol
+ EfiConvertPointer (0x0, (VOID **)&FvbDevice->SpiFlashProtocol->Erase);
+ EfiConvertPointer (0x0, (VOID **)&FvbDevice->SpiFlashProtocol->Write);
+ EfiConvertPointer (0x0, (VOID **)&FvbDevice->SpiFlashProtocol->Read);
+ EfiConvertPointer (0x0, (VOID **)&FvbDevice->SpiFlashProtocol->GetDevices);
+ EfiConvertPointer (0x0, (VOID **)&FvbDevice->SpiFlashProtocol->Initialization);
+ EfiConvertPointer (0x0, (VOID **)&FvbDevice->SpiFlashProtocol->EraseSingleBlock);
+ EfiConvertPointer (0x0, (VOID **)&FvbDevice->SpiFlashProtocol);
+
+ EfiConvertPointer (0x0, (VOID **)&mFlashNvStorageVariableBase);
+ EfiConvertPointer (0x0, (VOID **)&mFlashNvStorageFtwWorkingBase);
+ EfiConvertPointer (0x0, (VOID **)&mFlashNvStorageFtwSpareBase);
+ EfiConvertPointer (0x0, (VOID **)&FvbDevice);
+
+ return;
+}
+
+
+/**
+ This function is the entrypoint of the fvb driver.
+
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.
+
+ @param[in] SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The entry point is executed successfully.
+
+ @retval other Some error occurs when executing this entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+FvbEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ FvbDevice = AllocateRuntimeCopyPool (
+ sizeof (FvbFlashInstanceTemplate),
+ &FvbFlashInstanceTemplate
+ );
+ if (FvbDevice == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ mFlashNvStorageVariableBase = FixedPcdGet64 (PcdFlashNvStorageVariableBase64);
+ mFlashNvStorageFtwWorkingBase = FixedPcdGet64 (PcdFlashNvStorageFtwWorkingBase64);
+ mFlashNvStorageFtwSpareBase = FixedPcdGet64 (PcdFlashNvStorageFtwSpareBase64);
+ mFlashNvStorageVariableSize = FixedPcdGet32 (PcdFlashNvStorageVariableSize);
+ mFlashNvStorageFtwWorkingSize = FixedPcdGet32 (PcdFlashNvStorageFtwWorkingSize);
+ mFlashNvStorageFtwSpareSize = FixedPcdGet32 (PcdFlashNvStorageFtwSpareSize);
+
+ Status = CreateInstance ();
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "CreateInstance: Fail to create instance for NorFlash\n"
+ ));
+ }
+
+//
+// Register for the virtual address change event
+//
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ FvbVirtualNotifyEvent,
+ NULL,
+ &gEfiEventVirtualAddressChangeGuid,
+ &FvbVirtualAddrChangeEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
--
2.25.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH v4 09/10] Silicon/Phytium: Added Rtc driver to FT2000/4
2021-08-18 9:47 [PATCH v4 07/10] Silicon/Phytium: Added flash driver support to Phytium Silicon Ling Jia
2021-08-18 9:47 ` [PATCH v4 08/10] Silicon/Phytium: Added fvb driver for norflash Ling Jia
@ 2021-08-18 9:47 ` Ling Jia
2021-08-18 9:47 ` [PATCH v4 10/10] Maintainers.txt: Added maintainers and reviewers for the DurianPkg Ling Jia
2 siblings, 0 replies; 4+ messages in thread
From: Ling Jia @ 2021-08-18 9:47 UTC (permalink / raw)
To: devel; +Cc: Leif Lindholm, Ling Jia
The RealTimeClockLib implemented EFI RealTimeClock
runtime services via RTC Lib.
Signed-off-by: Ling Jia <jialing@phytium.com.cn>
---
Silicon/Phytium/PhytiumCommonPkg/PhytiumCommonPkg.dec | 1 +
Platform/Phytium/DurianPkg/DurianPkg.dsc | 6 +
Platform/Phytium/DurianPkg/DurianPkg.fdf | 2 +
Silicon/Phytium/FT2000-4Pkg/Library/RealTimeClockLib/RealTimeClockLib.inf | 39 ++
Silicon/Phytium/FT2000-4Pkg/Library/RealTimeClockLib/RealTimeClockLib.h | 24 +
Silicon/Phytium/FT2000-4Pkg/Library/RealTimeClockLib/RealTimeClockLib.c | 462 ++++++++++++++++++++
6 files changed, 534 insertions(+)
diff --git a/Silicon/Phytium/PhytiumCommonPkg/PhytiumCommonPkg.dec b/Silicon/Phytium/PhytiumCommonPkg/PhytiumCommonPkg.dec
index 2686ba3cc3..4c6c5c5f11 100644
--- a/Silicon/Phytium/PhytiumCommonPkg/PhytiumCommonPkg.dec
+++ b/Silicon/Phytium/PhytiumCommonPkg/PhytiumCommonPkg.dec
@@ -45,6 +45,7 @@
gPhytiumPlatformTokenSpaceGuid.PcdSpiFlashSize|0x0|UINT64|0x00000005
gPhytiumPlatformTokenSpaceGuid.PcdSpiControllerBase|0x0|UINT64|0x00000006
gPhytiumPlatformTokenSpaceGuid.PcdSpiControllerSize|0x0|UINT64|0x00000007
+ gPhytiumPlatformTokenSpaceGuid.PcdRtcBaseAddress|0x0|UINT32|0x00000008
[Protocols]
gSpiMasterProtocolGuid = { 0xdf093560, 0xf955, 0x11ea, { 0x96, 0x42, 0x43, 0x9d, 0x80, 0xdd, 0x0b, 0x7c}}
diff --git a/Platform/Phytium/DurianPkg/DurianPkg.dsc b/Platform/Phytium/DurianPkg/DurianPkg.dsc
index 99034365d3..9579f8e9b7 100644
--- a/Platform/Phytium/DurianPkg/DurianPkg.dsc
+++ b/Platform/Phytium/DurianPkg/DurianPkg.dsc
@@ -29,6 +29,10 @@
# Phytium Platform library
ArmPlatformLib|Silicon/Phytium/FT2000-4Pkg/Library/PlatformLib/PlatformLib.inf
+ #FT2000-4Pkg RTC Driver
+ RealTimeClockLib|Silicon/Phytium/FT2000-4Pkg/Library/RealTimeClockLib/RealTimeClockLib.inf
+ TimeBaseLib|EmbeddedPkg/Library/TimeBaseLib/TimeBaseLib.inf
+
# PL011 UART Driver and Dependency Libraries
SerialPortLib|ArmPlatformPkg/Library/PL011SerialPortLib/PL011SerialPortLib.inf
PL011UartClockLib|ArmPlatformPkg/Library/PL011UartClockLib/PL011UartClockLib.inf
@@ -168,6 +172,8 @@
NULL|MdeModulePkg/Library/VarCheckUefiLib/VarCheckUefiLib.inf
}
MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf
+ EmbeddedPkg/ResetRuntimeDxe/ResetRuntimeDxe.inf
+ EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClockRuntimeDxe.inf
#
# Common Arm Timer and Gic Components
diff --git a/Platform/Phytium/DurianPkg/DurianPkg.fdf b/Platform/Phytium/DurianPkg/DurianPkg.fdf
index 67458458dd..242f647ca1 100644
--- a/Platform/Phytium/DurianPkg/DurianPkg.fdf
+++ b/Platform/Phytium/DurianPkg/DurianPkg.fdf
@@ -93,6 +93,8 @@ READ_LOCK_STATUS = TRUE
#
INF MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf
INF MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf
+ INF EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClockRuntimeDxe.inf
+ INF EmbeddedPkg/ResetRuntimeDxe/ResetRuntimeDxe.inf
INF EmbeddedPkg/MetronomeDxe/MetronomeDxe.inf
INF Silicon/Phytium/FT2000-4Pkg/Drivers/SpiDxe/SpiDxe.inf
diff --git a/Silicon/Phytium/FT2000-4Pkg/Library/RealTimeClockLib/RealTimeClockLib.inf b/Silicon/Phytium/FT2000-4Pkg/Library/RealTimeClockLib/RealTimeClockLib.inf
new file mode 100644
index 0000000000..09a06d53ae
--- /dev/null
+++ b/Silicon/Phytium/FT2000-4Pkg/Library/RealTimeClockLib/RealTimeClockLib.inf
@@ -0,0 +1,39 @@
+#/** @file
+# Phytium RealTime Clock Library file.
+#
+# Copyright (C) 2020, Phytium Technology Co, Ltd. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x0001001b
+ BASE_NAME = RealTimeClockLib
+ FILE_GUID = fb320c94-40fe-11eb-b990-171865af292c
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = RealTimeClockLib
+
+[Sources.common]
+ RealTimeClockLib.c
+ RealTimeClockLib.h
+
+[Packages]
+ ArmPlatformPkg/ArmPlatformPkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+ MdePkg/MdePkg.dec
+ Silicon/Phytium/PhytiumCommonPkg/PhytiumCommonPkg.dec
+
+[LibraryClasses]
+ DebugLib
+ DxeServicesTableLib
+ IoLib
+ TimeBaseLib
+ UefiRuntimeLib
+
+[Guids]
+ gEfiEventVirtualAddressChangeGuid
+
+[Pcd]
+ gPhytiumPlatformTokenSpaceGuid.PcdRtcBaseAddress
diff --git a/Silicon/Phytium/FT2000-4Pkg/Library/RealTimeClockLib/RealTimeClockLib.h b/Silicon/Phytium/FT2000-4Pkg/Library/RealTimeClockLib/RealTimeClockLib.h
new file mode 100644
index 0000000000..41ce002dc3
--- /dev/null
+++ b/Silicon/Phytium/FT2000-4Pkg/Library/RealTimeClockLib/RealTimeClockLib.h
@@ -0,0 +1,24 @@
+/** @file
+ Phytium RealTime Clock Header.
+
+ Copyright (C) 2020, Phytium Technology Co Ltd. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef REAL_TIME_CLOCK_H_
+#define REAL_TIME_CLOCK_H_
+
+#define RTC_CMR 0x4
+#define RTC_AES_SEL 0x8
+#define RTC_CCR 0xC
+#define RTC_STAT 0x10
+#define RTC_RSTAT 0x14
+#define RTC_EOI 0x18
+#define RTC_CDR_LOW 0x20
+#define RTC_CCVR 0x24
+#define RTC_CLR_LOW 0x28
+#define RTC_CLR 0x2C
+
+#endif // REAL_TIME_CLOCK_H_
diff --git a/Silicon/Phytium/FT2000-4Pkg/Library/RealTimeClockLib/RealTimeClockLib.c b/Silicon/Phytium/FT2000-4Pkg/Library/RealTimeClockLib/RealTimeClockLib.c
new file mode 100644
index 0000000000..1c88958e3b
--- /dev/null
+++ b/Silicon/Phytium/FT2000-4Pkg/Library/RealTimeClockLib/RealTimeClockLib.c
@@ -0,0 +1,462 @@
+/** @file
+ Implement EFI RealTimeClock runtime services via RTC Lib.
+
+ Copyright (C) 2020, Phytium Technology Co Ltd. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiDxe.h>
+
+#include <Library/DebugLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/IoLib.h>
+#include <Library/TimeBaseLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeLib.h>
+#include <Protocol/RealTimeClock.h>
+#include "RealTimeClockLib.h"
+
+STATIC EFI_EVENT mRtcVirtualAddrChangeEvent;
+STATIC UINTN mRtcBase;
+STATIC CONST CHAR16 mTimeZoneVariableName[] = L"RtcTimeZone";
+STATIC CONST CHAR16 mDaylightVariableName[] = L"RtcDaylight";
+
+/**
+ Returns the current time and date information, and the time-keeping capabilities
+ of the hardware platform.
+
+ @param Time A pointer to storage to receive a snapshot of the current time.
+ @param Capabilities An optional pointer to a buffer to receive the real time clock
+ device's capabilities.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_INVALID_PARAMETER Time is NULL.
+ @retval EFI_DEVICE_ERROR The time could not be retrieved due to hardware error.
+ @retval EFI_SECURITY_VIOLATION The time could not be retrieved due to an authentication failure.
+
+**/
+EFI_STATUS
+EFIAPI
+LibGetTime (
+ OUT EFI_TIME *Time,
+ OUT EFI_TIME_CAPABILITIES *Capabilities
+ )
+{
+ UINT32 EpochSeconds;
+ INT16 TimeZone;
+ UINT8 Daylight;
+ UINTN Size;
+ EFI_STATUS Status;
+
+ // Ensure Time is a valid pointer
+ if (Time == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ MmioWrite32 (mRtcBase + RTC_AES_SEL, 0x100);
+ //
+ //read cdr high 32bit
+ //
+ EpochSeconds = MmioRead32 (mRtcBase + RTC_CCVR);
+ MmioRead32 (mRtcBase + RTC_CDR_LOW);
+ //
+ // Get the current time zone information from non-volatile storage
+ //
+ Size = sizeof (TimeZone);
+ Status = EfiGetVariable (
+ (CHAR16 *)mTimeZoneVariableName,
+ &gEfiCallerIdGuid,
+ NULL,
+ &Size,
+ (VOID *)&TimeZone
+ );
+
+ if (EFI_ERROR (Status)) {
+ ASSERT (Status != EFI_INVALID_PARAMETER);
+ ASSERT (Status != EFI_BUFFER_TOO_SMALL);
+ //
+ // The time zone variable does not exist in non-volatile storage, so create it.
+ //UTC+8:00
+ //
+ Time->TimeZone = -480;
+ //
+ // Store it
+ //
+ Status = EfiSetVariable (
+ (CHAR16 *)mTimeZoneVariableName,
+ &gEfiCallerIdGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ Size,
+ (VOID *)&(Time->TimeZone)
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ } else {
+ //
+ // Got the time zone
+ //
+ Time->TimeZone = TimeZone;
+ //
+ // Check TimeZone bounds: -1440 to 1440 or 2047
+ //
+ if(!IsValidTimeZone(Time->TimeZone)) {
+ Time->TimeZone = EFI_UNSPECIFIED_TIMEZONE;
+ }
+ //
+ // Adjust for the correct time zone
+ //
+ if (IsValidTimeZone(Time->TimeZone)) {
+ EpochSeconds -= Time->TimeZone * SEC_PER_MIN;
+ }
+ }
+ //
+ // Get the current daylight information from non-volatile storage
+ //
+ Size = sizeof (Daylight);
+ Status = EfiGetVariable (
+ (CHAR16 *)mDaylightVariableName,
+ &gEfiCallerIdGuid,
+ NULL,
+ &Size,
+ (VOID *)&Daylight
+ );
+
+ if (EFI_ERROR (Status)) {
+ ASSERT (Status != EFI_INVALID_PARAMETER);
+ ASSERT (Status != EFI_BUFFER_TOO_SMALL);
+ //
+ // The daylight variable does not exist in non-volatile storage, so create it.
+ //
+ Time->Daylight = 0;
+ //
+ // Store it
+ //
+ Status = EfiSetVariable (
+ (CHAR16 *)mDaylightVariableName,
+ &gEfiCallerIdGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ Size,
+ (VOID *)&(Time->Daylight)
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ } else {
+ //
+ // Got the daylight information
+ //
+ Time->Daylight = Daylight;
+ //
+ // Adjust for the correct period
+ //
+ if ((Time->Daylight & EFI_TIME_IN_DAYLIGHT) == EFI_TIME_IN_DAYLIGHT) {
+ //
+ // Convert to adjusted time, i.e. spring forwards one hour
+ //
+ EpochSeconds += SEC_PER_HOUR;
+ }
+ }
+
+ //
+ // Convert from internal 32-bit time to UEFI time
+ //
+ EpochToEfiTime (EpochSeconds, Time);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Sets the current local time and date information.
+
+ @param[in] Time A pointer to the current time.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_INVALID_PARAMETER A time field is out of range.
+ @retval EFI_DEVICE_ERROR The time could not be set due due to hardware error.
+
+**/
+EFI_STATUS
+EFIAPI
+LibSetTime (
+ IN EFI_TIME *Time
+ )
+{
+ UINTN EpochSeconds;
+ EFI_STATUS Status;
+ //
+ // the maximum time span is just over 136 years.
+ // Time is stored in Unix Epoch format, so it starts in 1970,
+ // Therefore it can not exceed the year 2106.
+ //
+ if ((Time->Year < 1970) || (Time->Year >= 2106)) {
+ return EFI_UNSUPPORTED;
+ }
+ EpochSeconds = EfiTimeToEpoch (Time);
+ //
+ // Adjust for the correct time zone, i.e. convert to UTC time zone
+ //
+ if (IsValidTimeZone(Time->TimeZone)) {
+ EpochSeconds += Time->TimeZone * SEC_PER_MIN;
+ }
+ //
+ // Adjust for the correct period
+ //
+ if (((Time->Daylight & EFI_TIME_IN_DAYLIGHT) == EFI_TIME_IN_DAYLIGHT)
+ && (EpochSeconds > SEC_PER_HOUR)) {
+ //
+ // Convert to un-adjusted time, i.e. fall back one hour
+ //
+ EpochSeconds -= SEC_PER_HOUR;
+ }
+ //
+ // Set the Rtc
+ //
+ MmioWrite32 (mRtcBase + RTC_AES_SEL, 0x100);
+ MmioWrite32 (mRtcBase + RTC_CLR_LOW, 0x0);
+ MmioWrite32 (mRtcBase + RTC_CLR, (UINT32)EpochSeconds);
+ //
+ // Save the current time zone information into non-volatile storage
+ //
+ Status = EfiSetVariable (
+ (CHAR16 *)mTimeZoneVariableName,
+ &gEfiCallerIdGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ sizeof (Time->TimeZone),
+ (VOID *)&(Time->TimeZone)
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Save the current daylight information into non-volatile storage
+ //
+ Status = EfiSetVariable (
+ (CHAR16 *)mDaylightVariableName,
+ &gEfiCallerIdGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ sizeof (Time->Daylight),
+ (VOID *)&(Time->Daylight)
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Returns the current wakeup alarm clock setting.
+
+ @param[out] Enabled Indicates if the alarm is currently enabled or disabled.
+ @param[out] Pending Indicates if the alarm signal is pending and requires acknowledgement.
+ @param[out] Time The current alarm setting.
+
+ @retval EFI_SUCCESS The alarm settings were returned.
+ @retval EFI_INVALID_PARAMETER Any parameter is NULL.
+ @retval EFI_DEVICE_ERROR The wakeup time could not be retrieved due to a hardware error.
+
+**/
+EFI_STATUS
+EFIAPI
+LibGetWakeupTime (
+ OUT BOOLEAN *Enabled,
+ OUT BOOLEAN *Pending,
+ OUT EFI_TIME *Time
+ )
+{
+ // Not a required feature
+ return EFI_UNSUPPORTED;
+}
+
+
+/**
+ Sets the system wakeup alarm clock time.
+
+ @param[in] Enabled Enable or disable the wakeup alarm.
+ @param[out] Time If Enable is TRUE, the time to set the wakeup alarm for.
+
+ @retval EFI_SUCCESS If Enable is TRUE, then the wakeup alarm was enabled. If
+ Enable is FALSE, then the wakeup alarm was disabled.
+ @retval EFI_INVALID_PARAMETER A time field is out of range.
+ @retval EFI_DEVICE_ERROR The wakeup time could not be set due to a hardware error.
+ @retval EFI_UNSUPPORTED A wakeup timer is not supported on this platform.
+
+**/
+EFI_STATUS
+EFIAPI
+LibSetWakeupTime (
+ IN BOOLEAN Enabled,
+ OUT EFI_TIME *Time
+ )
+{
+ // Not a required feature
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Fixup internal data so that EFI can be call in virtual mode.
+ Call the passed in Child Notify event and convert any pointers in
+ lib to virtual mode.
+
+ @param[in] Event The Event that is being processed
+ @param[in] Context Event Context
+
+**/
+VOID
+EFIAPI
+LibRtcVirtualNotifyEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ //
+ // Only needed if you are going to support the OS calling RTC functions in virtual mode.
+ // You will need to call EfiConvertPointer (). To convert any stored physical addresses
+ // to virtual address. After the OS transitions to calling in virtual mode, all future
+ // runtime calls will be made in virtual mode.
+ //
+ EfiConvertPointer (0x0, (VOID **)&mRtcBase);
+
+ return;
+}
+
+/**
+ This is the declaration of an EFI image entry point. This can be the entry point to an application
+ written to this specification, an EFI boot service driver, or an EFI runtime driver.
+
+ @param[in] ImageHandle Handle that identifies the loaded image.
+ @param[in] SystemTable System Table for this image.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+LibRtcInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE Handle;
+ INT16 TimeZone;
+ UINTN Size;
+ EFI_TIME Time;
+ UINT8 Daylight;
+ //
+ // Initialize RTC Base Address
+ //
+ mRtcBase = PcdGet32 (PcdRtcBaseAddress);
+ //
+ // Declare the controller as EFI_MEMORY_RUNTIME
+ //
+ Status = gDS->AddMemorySpace (
+ EfiGcdMemoryTypeMemoryMappedIo,
+ mRtcBase,
+ SIZE_4KB,
+ EFI_MEMORY_UC | EFI_MEMORY_RUNTIME
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ //init timezone
+ //
+ Size = sizeof (TimeZone);
+ Status = EfiGetVariable (
+ (CHAR16 *)mTimeZoneVariableName,
+ &gEfiCallerIdGuid,
+ NULL,
+ &Size,
+ (VOID *)&TimeZone
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (Status != EFI_INVALID_PARAMETER);
+ ASSERT (Status != EFI_BUFFER_TOO_SMALL);
+ //
+ // The time zone variable does not exist in non-volatile storage, so create it.
+ //UTC 8:00
+ //
+ Time.TimeZone = -480;
+ //
+ // Store it
+ //
+ Status = EfiSetVariable (
+ (CHAR16 *)mTimeZoneVariableName,
+ &gEfiCallerIdGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ Size,
+ (VOID *)&(Time.TimeZone)
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+ //
+ //daylight init
+ //
+ Size = sizeof (Daylight);
+ Status = EfiGetVariable (
+ (CHAR16 *)mDaylightVariableName,
+ &gEfiCallerIdGuid,
+ NULL,
+ &Size,
+ (VOID *)&Daylight
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (Status != EFI_INVALID_PARAMETER);
+ ASSERT (Status != EFI_BUFFER_TOO_SMALL);
+ //
+ // The daylight variable does not exist in non-volatile storage, so create it.
+ //
+ Time.Daylight = 0;
+ //
+ // Store it
+ //
+ Status = EfiSetVariable (
+ (CHAR16 *)mDaylightVariableName,
+ &gEfiCallerIdGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ Size,
+ (VOID *)&(Time.Daylight)
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ Status = gDS->SetMemorySpaceAttributes (mRtcBase, SIZE_4KB, EFI_MEMORY_UC | EFI_MEMORY_RUNTIME);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Install the protocol
+ //
+ Handle = NULL;
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Handle,
+ &gEfiRealTimeClockArchProtocolGuid,
+ NULL,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+ //
+ // Register for the virtual address change event
+ //
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ LibRtcVirtualNotifyEvent,
+ NULL,
+ &gEfiEventVirtualAddressChangeGuid,
+ &mRtcVirtualAddrChangeEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
--
2.25.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH v4 10/10] Maintainers.txt: Added maintainers and reviewers for the DurianPkg
2021-08-18 9:47 [PATCH v4 07/10] Silicon/Phytium: Added flash driver support to Phytium Silicon Ling Jia
2021-08-18 9:47 ` [PATCH v4 08/10] Silicon/Phytium: Added fvb driver for norflash Ling Jia
2021-08-18 9:47 ` [PATCH v4 09/10] Silicon/Phytium: Added Rtc driver to FT2000/4 Ling Jia
@ 2021-08-18 9:47 ` Ling Jia
2 siblings, 0 replies; 4+ messages in thread
From: Ling Jia @ 2021-08-18 9:47 UTC (permalink / raw)
To: devel; +Cc: Leif Lindholm, Ling Jia
Signed-off-by: Ling Jia <jialing@phytium.com.cn>
Reviewed-by: Leif Lindholm <leif@nuviainc.com>
---
Maintainers.txt | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/Maintainers.txt b/Maintainers.txt
index 9b8d6aead9..7266b434d5 100644
--- a/Maintainers.txt
+++ b/Maintainers.txt
@@ -363,3 +363,11 @@ F: Silicon/SiFive/
M: Abner Chang <abner.chang@hpe.com>
M: Gilbert Chen <gilbert.chen@hpe.com>
R: Daniel Schaefer <daniel.schaefer@hpe.com>
+
+Phytium platforms and silicon
+F: Platform/Phytium/
+F: Silicon/silicon/
+M: Leif Lindholm <leif@nuviainc.com>
+R: Peng Xie <xiepeng@phytium.com.cn>
+R: Ling Jia <jialing@phytium.com.cn>
+R: Yiqi Shu <shuyiqi@phytium.com.cn>
--
2.25.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
end of thread, other threads:[~2021-08-18 9:48 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2021-08-18 9:47 [PATCH v4 07/10] Silicon/Phytium: Added flash driver support to Phytium Silicon Ling Jia
2021-08-18 9:47 ` [PATCH v4 08/10] Silicon/Phytium: Added fvb driver for norflash Ling Jia
2021-08-18 9:47 ` [PATCH v4 09/10] Silicon/Phytium: Added Rtc driver to FT2000/4 Ling Jia
2021-08-18 9:47 ` [PATCH v4 10/10] Maintainers.txt: Added maintainers and reviewers for the DurianPkg Ling Jia
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox