public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH v7 0/4] Improved support for FT2004/4 chip.
@ 2022-04-14  6:03 Ling Jia
  2022-04-14  6:03 ` [PATCH v7 1/4] Platform/Phytium: Solved problems during boot Ling Jia
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Ling Jia @ 2022-04-14  6:03 UTC (permalink / raw)
  To: devel; +Cc: Leif Lindholm, Ling Jia

Completed the flash driver and fvb driver.
Solved the problems in boot process.
Added virtual address conversion.

The public git repository is :
https://github.com/jialing2020/edk2-platforms/tree/Phytium_Opensource_For_FT2000-4_v7

Ling Jia (4):
  Platform/Phytium: Solved problems during boot.
  Silicon/Phytium: Added flash driver support to Phytium Silicon.
  Silicon/Phytium: Added fvb driver for flash
  Silicon/Phytium: Added runtime support to spi master.

 Silicon/Phytium/PhytiumCommonPkg/PhytiumCommonPkg.dec                                        |    1 +
 Platform/Phytium/DurianPkg/DurianPkg.dsc                                                     |   14 +
 Platform/Phytium/DurianPkg/DurianPkg.fdf                                                     |   32 +-
 Silicon/Phytium/FT2000-4Pkg/Drivers/SpiDxe/SpiDxe.inf                                        |    5 +
 Silicon/Phytium/FT2000-4Pkg/Drivers/{SpiDxe/SpiDxe.inf => SpiNorFlashDxe/SpiNorFlashDxe.inf} |   25 +-
 Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.inf                         |   63 +
 Silicon/Phytium/FT2000-4Pkg/Drivers/SpiDxe/SpiDxe.h                                          |    2 +
 Silicon/Phytium/FT2000-4Pkg/Drivers/SpiNorFlashDxe/SpiNorFlashDxe.h                          |   95 ++
 Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.h                           |  105 ++
 Silicon/Phytium/PhytiumCommonPkg/Include/Protocol/SpiNorFlashProtocol.h                      |   74 ++
 Silicon/Phytium/FT2000-4Pkg/Drivers/SpiDxe/SpiDxe.c                                          |   84 +-
 Silicon/Phytium/FT2000-4Pkg/Drivers/SpiNorFlashDxe/SpiNorFlashDxe.c                          |  412 ++++++
 Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.c                           | 1329 ++++++++++++++++++++
 13 files changed, 2210 insertions(+), 31 deletions(-)
 copy Silicon/Phytium/FT2000-4Pkg/Drivers/{SpiDxe/SpiDxe.inf => SpiNorFlashDxe/SpiNorFlashDxe.inf} (55%)
 mode change 100644 => 100755
 create mode 100755 Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.inf
 create mode 100755 Silicon/Phytium/FT2000-4Pkg/Drivers/SpiNorFlashDxe/SpiNorFlashDxe.h
 create mode 100755 Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.h
 create mode 100755 Silicon/Phytium/PhytiumCommonPkg/Include/Protocol/SpiNorFlashProtocol.h
 create mode 100755 Silicon/Phytium/FT2000-4Pkg/Drivers/SpiNorFlashDxe/SpiNorFlashDxe.c
 create mode 100755 Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.c

-- 
2.25.1


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH v7 1/4] Platform/Phytium: Solved problems during boot.
  2022-04-14  6:03 [PATCH v7 0/4] Improved support for FT2004/4 chip Ling Jia
@ 2022-04-14  6:03 ` Ling Jia
  2022-04-14  6:03 ` [PATCH v7 2/4] Silicon/Phytium: Added flash driver support to Phytium Silicon Ling Jia
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Ling Jia @ 2022-04-14  6:03 UTC (permalink / raw)
  To: devel; +Cc: Leif Lindholm, Ling Jia

Solved the problem of lack of dependent Library
in PciHostBridgeDxe.

Solved the problem of missing boot magager menu.

Signed-off-by: Ling Jia <jialing@phytium.com.cn>
Reviewed-by: leif Lindholm <leif@nuviainc.com>
---
 Platform/Phytium/DurianPkg/DurianPkg.fdf | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/Platform/Phytium/DurianPkg/DurianPkg.fdf b/Platform/Phytium/DurianPkg/DurianPkg.fdf
index 2d4427e5ea..efb855c5da 100644
--- a/Platform/Phytium/DurianPkg/DurianPkg.fdf
+++ b/Platform/Phytium/DurianPkg/DurianPkg.fdf
@@ -142,6 +142,7 @@ READ_LOCK_STATUS   = TRUE
   #
   # PCI Support
   #
+  INF ArmPkg/Drivers/ArmPciCpuIo2Dxe/ArmPciCpuIo2Dxe.inf
   INF MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
   INF MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
 
@@ -204,6 +205,11 @@ READ_LOCK_STATUS   = TRUE
   INF MdeModulePkg/Universal/BdsDxe/BdsDxe.inf
   INF MdeModulePkg/Application/UiApp/UiApp.inf
 
+  #
+  #Setup
+  #
+  INF MdeModulePkg/Application/BootManagerMenuApp/BootManagerMenuApp.inf
+
 [FV.FVMAIN_COMPACT]
 FvAlignment        = 16
 ERASE_POLARITY     = 1
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH v7 2/4] Silicon/Phytium: Added flash driver support to Phytium Silicon.
  2022-04-14  6:03 [PATCH v7 0/4] Improved support for FT2004/4 chip Ling Jia
  2022-04-14  6:03 ` [PATCH v7 1/4] Platform/Phytium: Solved problems during boot Ling Jia
@ 2022-04-14  6:03 ` Ling Jia
  2022-04-14  6:03 ` [PATCH v7 3/4] Silicon/Phytium: Added fvb driver for flash Ling Jia
  2022-04-14  6:03 ` [PATCH v7 4/4] Silicon/Phytium: Added runtime support to spi master Ling Jia
  3 siblings, 0 replies; 5+ messages in thread
From: Ling Jia @ 2022-04-14  6:03 UTC (permalink / raw)
  To: devel; +Cc: Leif Lindholm, Ling Jia

The SpiNorFlashDxe provided norflash initialization,
read-write, erase and other interfaces.

This is a set of special communication protocol for
ft2004/4 chip QSPI controller.

Signed-off-by: Ling Jia <jialing@phytium.com.cn>
Reviewed-by: leif Lindholm <leif@nuviainc.com>
---
 Silicon/Phytium/PhytiumCommonPkg/PhytiumCommonPkg.dec                   |   1 +
 Platform/Phytium/DurianPkg/DurianPkg.dsc                                |  13 +
 Platform/Phytium/DurianPkg/DurianPkg.fdf                                |  24 +-
 Silicon/Phytium/FT2000-4Pkg/Drivers/SpiNorFlashDxe/SpiNorFlashDxe.inf   |  49 +++
 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, 658 insertions(+), 10 deletions(-)

diff --git a/Silicon/Phytium/PhytiumCommonPkg/PhytiumCommonPkg.dec b/Silicon/Phytium/PhytiumCommonPkg/PhytiumCommonPkg.dec
index 8427f32211..4c6c5c5f11 100644
--- a/Silicon/Phytium/PhytiumCommonPkg/PhytiumCommonPkg.dec
+++ b/Silicon/Phytium/PhytiumCommonPkg/PhytiumCommonPkg.dec
@@ -49,3 +49,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 c1519070d6..cc0d418555 100644
--- a/Platform/Phytium/DurianPkg/DurianPkg.dsc
+++ b/Platform/Phytium/DurianPkg/DurianPkg.dsc
@@ -100,6 +100,14 @@
   # Stack Size
   gArmPlatformTokenSpaceGuid.PcdCPUCorePrimaryStackSize|0x4000
 
+  #
+  # SPI Flash Control Register Base Address and Size
+  #
+  gPhytiumPlatformTokenSpaceGuid.PcdSpiFlashBase|0x0
+  gPhytiumPlatformTokenSpaceGuid.PcdSpiFlashSize|0x1000000
+  gPhytiumPlatformTokenSpaceGuid.PcdSpiControllerBase|0x28014000
+  gPhytiumPlatformTokenSpaceGuid.PcdSpiControllerSize|0x1000
+  gPhytiumPlatformTokenSpaceGuid.PcdRtcBaseAddress|0x2800D000
   #
   # Designware PCI Root Complex
   #
@@ -255,6 +263,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 efb855c5da..5c1471d8ed 100644
--- a/Platform/Phytium/DurianPkg/DurianPkg.fdf
+++ b/Platform/Phytium/DurianPkg/DurianPkg.fdf
@@ -83,6 +83,11 @@ READ_LOCK_STATUS   = TRUE
 
   APRIORI DXE {
     INF MdeModulePkg/Universal/PCD/Dxe/Pcd.inf
+    INF ArmPkg/Drivers/CpuDxe/CpuDxe.inf
+    INF ArmPkg/Drivers/ArmGic/ArmGicDxe.inf
+    INF MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf
+    INF Silicon/Phytium/FT2000-4Pkg/Drivers/SpiDxe/SpiDxe.inf
+    INF Silicon/Phytium/FT2000-4Pkg/Drivers/SpiNorFlashDxe/SpiNorFlashDxe.inf
   }
 
   INF MdeModulePkg/Core/Dxe/DxeMain.inf
@@ -91,29 +96,28 @@ READ_LOCK_STATUS   = TRUE
   #
   # PI DXE Drivers producing Architectural Protocols (EFI Services)
   #
+  INF ArmPkg/Drivers/ArmGic/ArmGicDxe.inf
+  INF ArmPkg/Drivers/CpuDxe/CpuDxe.inf
   INF MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf
+  INF MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.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
-
-  INF MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
-  INF MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
-
-  INF ArmPkg/Drivers/ArmGic/ArmGicDxe.inf
-  INF ArmPkg/Drivers/CpuDxe/CpuDxe.inf
-  INF ArmPkg/Drivers/TimerDxe/TimerDxe.inf
-  INF ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdogDxe.inf
+  INF Silicon/Phytium/FT2000-4Pkg/Drivers/SpiNorFlashDxe/SpiNorFlashDxe.inf
 
   #
   # Variable services
   #
   INF MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
   INF MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf
+  INF EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClockRuntimeDxe.inf
 
+  INF ArmPkg/Drivers/TimerDxe/TimerDxe.inf
+  INF ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdogDxe.inf
   INF MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf
+  INF MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
+  INF EmbeddedPkg/MetronomeDxe/MetronomeDxe.inf
 
   #
   # ACPI Support
diff --git a/Silicon/Phytium/FT2000-4Pkg/Drivers/SpiNorFlashDxe/SpiNorFlashDxe.inf b/Silicon/Phytium/FT2000-4Pkg/Drivers/SpiNorFlashDxe/SpiNorFlashDxe.inf
new file mode 100755
index 0000000000..2173405809
--- /dev/null
+++ b/Silicon/Phytium/FT2000-4Pkg/Drivers/SpiNorFlashDxe/SpiNorFlashDxe.inf
@@ -0,0 +1,49 @@
+#/** @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
+  UefiRuntimeServicesTableLib
+
+[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 100755
index 0000000000..16981504ab
--- /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        Length
+  );
+
+EFI_STATUS
+EFIAPI
+NorFlashPlatformWrite (
+  IN UINTN         Address,
+  IN VOID          *Buffer,
+  IN UINT32        Length
+  );
+
+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 100755
index 0000000000..ce1877f13a
--- /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              Length
+  );
+
+typedef
+EFI_STATUS
+(EFIAPI *NORFLASH_PLATFORM_WRITE_INTERFACE) (
+  IN UINTN         Address,
+  IN VOID          *Buffer,
+  IN UINT32        Length
+  );
+
+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 100755
index 0000000000..fbeb3d1a71
--- /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 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 */
+    SPI_FLASH_SIZE,   /* 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
+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 **)&(mSpiMasterProtocol->SpiGetConfig));
+  EfiConvertPointer (0x0, (VOID **)&(mSpiMasterProtocol->SpiSetConfig));
+  EfiConvertPointer (0x0, (VOID **)&(mSpiMasterProtocol));
+  EfiConvertPointer (0x0, (VOID **)&(mFlashInstance->FlashProtocol.Erase));
+  EfiConvertPointer (0x0, (VOID **)&(mFlashInstance->FlashProtocol.Read));
+  EfiConvertPointer (0x0, (VOID **)&(mFlashInstance->FlashProtocol.Write));
+  EfiConvertPointer (0x0, (VOID **)&(mFlashInstance->FlashProtocol.EraseSingleBlock));
+  EfiConvertPointer (0x0, (VOID **)&(mFlashInstance->FlashProtocol));
+  EfiConvertPointer (0x0, (VOID **)&(mFlashInstance));
+  EfiConvertPointer (0x0, (VOID **)&(mNorFlashDevices));
+
+  return;
+}
+
+
+/**
+  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;
+
+  mSpiMasterProtocol->SpiInit();
+
+  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] Length             The bytes readed form flash.
+
+  @retval EFI_SUCCESS            NorFlashPlatformRead() is executed successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+NorFlashPlatformRead (
+  IN UINTN                Address,
+  IN VOID                 *Buffer,
+  OUT UINT32              Length
+  )
+{
+
+  CopyMem ((VOID *)Buffer, (VOID *)Address, Length);
+
+  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] 5+ messages in thread

* [PATCH v7 3/4] Silicon/Phytium: Added fvb driver for flash
  2022-04-14  6:03 [PATCH v7 0/4] Improved support for FT2004/4 chip Ling Jia
  2022-04-14  6:03 ` [PATCH v7 1/4] Platform/Phytium: Solved problems during boot Ling Jia
  2022-04-14  6:03 ` [PATCH v7 2/4] Silicon/Phytium: Added flash driver support to Phytium Silicon Ling Jia
@ 2022-04-14  6:03 ` Ling Jia
  2022-04-14  6:03 ` [PATCH v7 4/4] Silicon/Phytium: Added runtime support to spi master Ling Jia
  3 siblings, 0 replies; 5+ messages in thread
From: Ling Jia @ 2022-04-14  6:03 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                             |    2 +
 Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.inf |   63 +
 Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.h   |  105 ++
 Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.c   | 1329 ++++++++++++++++++++
 5 files changed, 1500 insertions(+)

diff --git a/Platform/Phytium/DurianPkg/DurianPkg.dsc b/Platform/Phytium/DurianPkg/DurianPkg.dsc
index cc0d418555..cedf7480a5 100644
--- a/Platform/Phytium/DurianPkg/DurianPkg.dsc
+++ b/Platform/Phytium/DurianPkg/DurianPkg.dsc
@@ -267,6 +267,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 5c1471d8ed..1a52250db2 100644
--- a/Platform/Phytium/DurianPkg/DurianPkg.fdf
+++ b/Platform/Phytium/DurianPkg/DurianPkg.fdf
@@ -88,6 +88,7 @@ READ_LOCK_STATUS   = TRUE
     INF MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf
     INF Silicon/Phytium/FT2000-4Pkg/Drivers/SpiDxe/SpiDxe.inf
     INF Silicon/Phytium/FT2000-4Pkg/Drivers/SpiNorFlashDxe/SpiNorFlashDxe.inf
+    INF Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.inf
   }
 
   INF MdeModulePkg/Core/Dxe/DxeMain.inf
@@ -105,6 +106,7 @@ READ_LOCK_STATUS   = TRUE
 
   INF Silicon/Phytium/FT2000-4Pkg/Drivers/SpiDxe/SpiDxe.inf
   INF Silicon/Phytium/FT2000-4Pkg/Drivers/SpiNorFlashDxe/SpiNorFlashDxe.inf
+  INF Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.inf
 
   #
   # Variable services
diff --git a/Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.inf b/Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.inf
new file mode 100755
index 0000000000..9121be921c
--- /dev/null
+++ b/Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.inf
@@ -0,0 +1,63 @@
+#/** @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
+  UefiRuntimeServicesTableLib
+
+[Guids]
+  gEfiAuthenticatedVariableGuid
+  gEfiEventVirtualAddressChangeGuid
+  gEfiSystemNvDataFvGuid
+  gEfiVariableGuid
+
+[Protocols]
+  gEfiDevicePathProtocolGuid
+  gEfiFirmwareVolumeBlockProtocolGuid
+  gSpiNorFlashProtocolGuid
+
+[FixedPcd]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize
+
+[Pcd]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase64
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase64
+
+
+[Depex]
+  TRUE
diff --git a/Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.h b/Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.h
new file mode 100755
index 0000000000..923ad3ccbb
--- /dev/null
+++ b/Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.h
@@ -0,0 +1,105 @@
+/** @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/SpiProtocol.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;
+  UINTN                               FvbSize;
+  VOID*                               TempBuffer;
+  };
+
+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 100755
index 0000000000..6fad70f28b
--- /dev/null
+++ b/Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.c
@@ -0,0 +1,1329 @@
+/** @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       mFvbVirtualAddrChangeEvent;
+STATIC FT_FVB_DEVICE   *mFvbDevice;
+UINTN           mFlashNvStorageVariableBase;
+UINTN           mFlashNvStorageFtwWorkingBase;
+UINTN           mFlashNvStorageFtwSpareBase;
+UINT32          mFlashNvStorageVariableSize;
+UINT32          mFlashNvStorageFtwWorkingSize;
+UINT32          mFlashNvStorageFtwSpareSize;
+
+STATIC CONST FT_FVB_DEVICE mFvbFlashInstanceTemplate = {
+  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
+  0,     // Fvb Size
+  NULL   // TempBuffer
+};
+
+
+/**
+  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;
+
+  // The buffer must be valid
+  if (Buffer == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (BufferSizeInBytes == 0) {
+    return EFI_SUCCESS;
+  }
+
+  if (((Lba * FlashInstance->Media.BlockSize) + Offset + BufferSizeInBytes) > FlashInstance->Size) {
+    DEBUG ((DEBUG_ERROR, "FvbFlashRead: ERROR - Read will exceed device size.\n"));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Address = GET_DATA_OFFSET (
+              FlashInstance->RegionBaseAddress,
+              Lba,
+              FlashInstance->Media.BlockSize
+              ) + Offset;
+
+  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;
+  }
+
+  if (FlashInstance->TempBuffer == NULL) {
+    DEBUG ((DEBUG_ERROR, "FvbWriteBlock: ERROR - Buffer not ready\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->TempBuffer,
+             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->TempBuffer + 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->TempBuffer,
+             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
+                         EFI_FVB2_ALIGNMENT_4;
+  }
+
+  *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          RuntimeMmioRegionSize;
+
+  RuntimeMmioRegionSize =  FlashInstance->Size;
+
+  // Declare the Non-Volatile storage as EFI_MEMORY_RUNTIME
+  Status = gDS->AddMemorySpace (
+                  EfiGcdMemoryTypeMemoryMappedIo,
+                  FlashInstance->RegionBaseAddress,
+                  RuntimeMmioRegionSize,
+                  EFI_MEMORY_UC | EFI_MEMORY_RUNTIME
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  Status = gDS->SetMemorySpaceAttributes (
+                  FlashInstance->RegionBaseAddress,
+                  RuntimeMmioRegionSize,
+                  EFI_MEMORY_UC | EFI_MEMORY_RUNTIME
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  // 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 = FlashInstance->FvbSize / 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;
+
+  mFvbDevice = AllocateRuntimeCopyPool (sizeof (mFvbFlashInstanceTemplate), &mFvbFlashInstanceTemplate);
+  if (mFvbDevice == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+
+  }
+  // Locate flash protocols
+  Status = gBS->LocateProtocol (&gSpiNorFlashProtocolGuid,
+                  NULL,
+                  (VOID **)&mFvbDevice->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 = mFvbDevice->SpiFlashProtocol->GetDevices (NorFlashDevice);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = mFvbDevice->SpiFlashProtocol->Initialization ();
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  mFvbDevice->DeviceBaseAddress = NorFlashDevice->DeviceBaseAddress;
+  mFvbDevice->RegionBaseAddress = NorFlashDevice->RegionBaseAddress;
+  mFvbDevice->Size = NorFlashDevice->Size;
+
+  mFvbDevice->Media.MediaId = 0;
+  mFvbDevice->Media.BlockSize = NorFlashDevice->BlockSize;
+  mFvbDevice->Media.LastBlock = (mFvbDevice->Size / mFvbDevice->Media.BlockSize) - 1;
+  mFvbDevice->FvbSize = mFlashNvStorageVariableSize   +
+                        mFlashNvStorageFtwWorkingSize +
+                        mFlashNvStorageFtwSpareSize;
+  DEBUG((DEBUG_INFO, "mFvbDevice->fvbSize=%x\n", mFvbDevice->FvbSize));
+  CopyGuid (&mFvbDevice->DevicePath.Vendor.Guid, &NorFlashDevice->Guid);
+
+  mFvbDevice->TempBuffer = AllocateRuntimePool (mFvbDevice->Media.BlockSize);
+  if (mFvbDevice->TempBuffer == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  Status = PhytNorFlashFvbInitialize (mFvbDevice);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "PhytNorFlashFvbInitialize: Fail to init NorFlash devices\n"
+      ));
+    return Status;
+  }
+
+  Status = gBS->InstallMultipleProtocolInterfaces (
+             &mFvbDevice->Handle,
+             &gEfiDevicePathProtocolGuid,
+             &mFvbDevice->DevicePath,
+             &gEfiFirmwareVolumeBlockProtocolGuid,
+             &mFvbDevice->FvbProtocol,
+             NULL
+             );
+  if (EFI_ERROR (Status)) {
+    FreePool (mFvbDevice);
+    FreePool (NorFlashDevice);
+    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
+  )
+{
+  VOID *Pointer;
+
+  EfiConvertPointer (0x0, (VOID **)&mFlashNvStorageVariableBase);
+  EfiConvertPointer (0x0, (VOID **)&mFlashNvStorageFtwWorkingBase);
+  EfiConvertPointer (0x0, (VOID **)&mFlashNvStorageFtwSpareBase);
+  if (!mFvbDevice->DeviceBaseAddress) {
+    mFvbDevice->DeviceBaseAddress |= 0x1;
+  }
+
+  if (!mFvbDevice->RegionBaseAddress) {
+    mFvbDevice->RegionBaseAddress |= 0x1;
+  }
+  EfiConvertPointer (0x0, (VOID **)&mFvbDevice->DeviceBaseAddress);
+  EfiConvertPointer (0x0, (VOID **)&mFvbDevice->RegionBaseAddress);
+
+  mFvbDevice->DeviceBaseAddress &= ~(EFI_PHYSICAL_ADDRESS)0x1;
+  mFvbDevice->RegionBaseAddress &= ~(EFI_PHYSICAL_ADDRESS)0x1;
+
+  // Convert SpiFlashProtocol
+  EfiConvertPointer (0x0, (VOID **)&(mFvbDevice->SpiFlashProtocol->Erase));
+  EfiConvertPointer (0x0, (VOID **)&(mFvbDevice->SpiFlashProtocol->Write));
+  EfiConvertPointer (0x0, (VOID **)&(mFvbDevice->SpiFlashProtocol->Read));
+  EfiConvertPointer (0x0, (VOID **)&(mFvbDevice->SpiFlashProtocol->GetDevices));
+  EfiConvertPointer (0x0, (VOID **)&(mFvbDevice->SpiFlashProtocol));
+
+  EfiConvertPointer (0x0, (VOID **)&(mFvbDevice->FvbProtocol.EraseBlocks));
+  EfiConvertPointer (0x0, (VOID **)&(mFvbDevice->FvbProtocol.GetAttributes));
+  EfiConvertPointer (0x0, (VOID **)&(mFvbDevice->FvbProtocol.GetBlockSize));
+
+  Pointer = (VOID *)(UINTN)mFvbDevice->FvbProtocol.GetPhysicalAddress;
+  EfiConvertPointer (0x0, &Pointer);
+  mFvbDevice->FvbProtocol.GetPhysicalAddress = (EFI_FVB_GET_PHYSICAL_ADDRESS)(UINTN)Pointer;
+  EfiConvertPointer (0x0, (VOID **)&(mFvbDevice->FvbProtocol.Read));
+  EfiConvertPointer (0x0, (VOID **)&(mFvbDevice->FvbProtocol.SetAttributes));
+  EfiConvertPointer (0x0, (VOID **)&(mFvbDevice->FvbProtocol.Write));
+  EfiConvertPointer (0x0, (VOID **)&(mFvbDevice->FvbProtocol));
+
+  if (mFvbDevice->TempBuffer != NULL) {
+    EfiConvertPointer (0x0, (VOID **)&(mFvbDevice->TempBuffer));
+  }
+  EfiConvertPointer (0x0, (VOID **)&(mFvbDevice));
+
+  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;
+
+  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,
+             &mFvbVirtualAddrChangeEvent
+             );
+  ASSERT_EFI_ERROR (Status);
+
+  return Status;
+}
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH v7 4/4] Silicon/Phytium: Added runtime support to spi master.
  2022-04-14  6:03 [PATCH v7 0/4] Improved support for FT2004/4 chip Ling Jia
                   ` (2 preceding siblings ...)
  2022-04-14  6:03 ` [PATCH v7 3/4] Silicon/Phytium: Added fvb driver for flash Ling Jia
@ 2022-04-14  6:03 ` Ling Jia
  3 siblings, 0 replies; 5+ messages in thread
From: Ling Jia @ 2022-04-14  6:03 UTC (permalink / raw)
  To: devel; +Cc: Leif Lindholm, Ling Jia

Solved the problem of virtual address translation
in runtime access under OS

Signed-off-by: Ling Jia <jialing@phytium.com.cn>
Reviewed-by: leif Lindholm <leif@nuviainc.com>
---
 Silicon/Phytium/FT2000-4Pkg/Drivers/SpiDxe/SpiDxe.inf |  5 ++
 Silicon/Phytium/FT2000-4Pkg/Drivers/SpiDxe/SpiDxe.h   |  2 +
 Silicon/Phytium/FT2000-4Pkg/Drivers/SpiDxe/SpiDxe.c   | 84 +++++++++++++++++---
 3 files changed, 80 insertions(+), 11 deletions(-)

diff --git a/Silicon/Phytium/FT2000-4Pkg/Drivers/SpiDxe/SpiDxe.inf b/Silicon/Phytium/FT2000-4Pkg/Drivers/SpiDxe/SpiDxe.inf
index 21d75f268d..0b23821c65 100644
--- a/Silicon/Phytium/FT2000-4Pkg/Drivers/SpiDxe/SpiDxe.inf
+++ b/Silicon/Phytium/FT2000-4Pkg/Drivers/SpiDxe/SpiDxe.inf
@@ -27,18 +27,23 @@
 [LibraryClasses]
   BaseLib
   DebugLib
+  DxeServicesTableLib
   IoLib
   UefiLib
   UefiBootServicesTableLib
   UefiDriverEntryPoint
+  UefiRuntimeLib
+  UefiRuntimeServicesTableLib
 
 [Guids]
+  gEfiEventVirtualAddressChangeGuid
 
 [Protocols]
   gSpiMasterProtocolGuid
 
 [FixedPcd]
   gPhytiumPlatformTokenSpaceGuid.PcdSpiControllerBase
+  gPhytiumPlatformTokenSpaceGuid.PcdSpiControllerSize
 
 [Depex]
   TRUE
diff --git a/Silicon/Phytium/FT2000-4Pkg/Drivers/SpiDxe/SpiDxe.h b/Silicon/Phytium/FT2000-4Pkg/Drivers/SpiDxe/SpiDxe.h
index 8795ea238d..842d0c3d18 100644
--- a/Silicon/Phytium/FT2000-4Pkg/Drivers/SpiDxe/SpiDxe.h
+++ b/Silicon/Phytium/FT2000-4Pkg/Drivers/SpiDxe/SpiDxe.h
@@ -10,6 +10,8 @@
 #ifndef SPI_DXE_H_
 #define SPI_DXE_H_
 
+#include <Library/DxeServicesTableLib.h>
+#include <Library/UefiRuntimeLib.h>
 #include <Protocol/SpiProtocol.h>
 
 #define SPI_MASTER_SIGNATURE         SIGNATURE_32 ('M', 'S', 'P', 'I')
diff --git a/Silicon/Phytium/FT2000-4Pkg/Drivers/SpiDxe/SpiDxe.c b/Silicon/Phytium/FT2000-4Pkg/Drivers/SpiDxe/SpiDxe.c
index 7602a3e0cd..5358ff6090 100644
--- a/Silicon/Phytium/FT2000-4Pkg/Drivers/SpiDxe/SpiDxe.c
+++ b/Silicon/Phytium/FT2000-4Pkg/Drivers/SpiDxe/SpiDxe.c
@@ -13,8 +13,9 @@
 #include <Uefi/UefiBaseType.h>
 #include "SpiDxe.h"
 
-PHYT_SPI_MASTER *pSpiMasterInstance;
-static UINTN     mSpiControlBase;
+STATIC EFI_EVENT  mSpiMasterVirtualAddrChangeEvent;
+STATIC UINTN      mSpiMasterControlBase;
+PHYT_SPI_MASTER   *mSpiMasterInstance;
 
 /**
   This function inited a spi driver.
@@ -66,7 +67,7 @@ SpiMasterSetConfig (
     Value = Config;
   }
 
-  SpiAddr = mSpiControlBase + RegAddr;
+  SpiAddr = mSpiMasterControlBase + RegAddr;
   MmioWrite32 (SpiAddr, Value);
 
   return EFI_SUCCESS;
@@ -99,7 +100,7 @@ SpiMasterGetConfig (
   SpiAddr = 0;
   Value   = 0;
 
-  SpiAddr = mSpiControlBase + RegAddr;
+  SpiAddr = mSpiMasterControlBase + RegAddr;
   Value = MmioRead32 (SpiAddr);
 
   if (CmdId != 0) {
@@ -157,6 +158,34 @@ SpiMasterInitProtocol (
   return EFI_SUCCESS;
 }
 
+/**
+  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
+SpiMasterVirtualNotifyEvent (
+  IN EFI_EVENT        Event,
+  IN VOID             *Context
+  )
+{
+  EfiConvertPointer (0x0, (VOID **)&(mSpiMasterControlBase));
+  EfiConvertPointer (0x0, (VOID **)&(mSpiMasterInstance->SpiMasterProtocol.SpiGetConfig));
+  EfiConvertPointer (0x0, (VOID **)&(mSpiMasterInstance->SpiMasterProtocol.SpiSetConfig));
+  EfiConvertPointer (0x0, (VOID **)&(mSpiMasterInstance->SpiMasterProtocol));
+  EfiConvertPointer (0x0, (VOID **)&(mSpiMasterInstance));
+
+  return;
+}
 
 /**
   This function is the entrypoint of the spi driver.
@@ -178,25 +207,58 @@ SpiMasterDrvEntryPoint (
   )
 {
   EFI_STATUS  Status;
+  UINTN       SpiMasterControlSize;
 
-  pSpiMasterInstance = AllocateRuntimeZeroPool (sizeof (PHYT_SPI_MASTER));
-  if (pSpiMasterInstance == NULL) {
+  mSpiMasterControlBase = FixedPcdGet64 (PcdSpiControllerBase);
+  SpiMasterControlSize = FixedPcdGet64 (PcdSpiControllerSize);
+
+  mSpiMasterInstance = AllocateRuntimeZeroPool (sizeof (PHYT_SPI_MASTER));
+  if (mSpiMasterInstance == NULL) {
     return EFI_OUT_OF_RESOURCES;
   }
 
-  mSpiControlBase = FixedPcdGet64 (PcdSpiControllerBase);
+  mSpiMasterControlBase = FixedPcdGet64 (PcdSpiControllerBase);
 
-  SpiMasterInitProtocol (&pSpiMasterInstance->SpiMasterProtocol);
+  SpiMasterInitProtocol (&mSpiMasterInstance->SpiMasterProtocol);
 
-  pSpiMasterInstance->Signature = SPI_MASTER_SIGNATURE;
+  mSpiMasterInstance->Signature = SPI_MASTER_SIGNATURE;
 
   Status = gBS->InstallMultipleProtocolInterfaces (
-                &(pSpiMasterInstance->Handle),
+                &(mSpiMasterInstance->Handle),
                 &gSpiMasterProtocolGuid,
-                &(pSpiMasterInstance->SpiMasterProtocol),
+                &(mSpiMasterInstance->SpiMasterProtocol),
                 NULL
                 );
   ASSERT_EFI_ERROR (Status);
 
+  //
+  // Declare the SPI Controller Space as EFI_MEMORY_RUNTIME
+  //
+  Status = gDS->AddMemorySpace (
+                  EfiGcdMemoryTypeMemoryMappedIo,
+                  (mSpiMasterControlBase >> EFI_PAGE_SHIFT) << EFI_PAGE_SHIFT, EFI_PAGES_TO_SIZE(EFI_SIZE_TO_PAGES(SpiMasterControlSize)),
+                  EFI_MEMORY_UC | EFI_MEMORY_RUNTIME
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  Status = gDS->SetMemorySpaceAttributes (
+                  (mSpiMasterControlBase >> EFI_PAGE_SHIFT) << EFI_PAGE_SHIFT, EFI_PAGES_TO_SIZE(EFI_SIZE_TO_PAGES(SpiMasterControlSize)),
+                  EFI_MEMORY_UC | EFI_MEMORY_RUNTIME
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Register for the virtual address change event
+  //
+  Status = gBS->CreateEventEx (
+             EVT_NOTIFY_SIGNAL,
+             TPL_NOTIFY,
+             SpiMasterVirtualNotifyEvent,
+             NULL,
+             &gEfiEventVirtualAddressChangeGuid,
+             &mSpiMasterVirtualAddrChangeEvent
+             );
+  ASSERT_EFI_ERROR (Status);
+
   return EFI_SUCCESS;
 }
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2022-04-14  6:03 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-04-14  6:03 [PATCH v7 0/4] Improved support for FT2004/4 chip Ling Jia
2022-04-14  6:03 ` [PATCH v7 1/4] Platform/Phytium: Solved problems during boot Ling Jia
2022-04-14  6:03 ` [PATCH v7 2/4] Silicon/Phytium: Added flash driver support to Phytium Silicon Ling Jia
2022-04-14  6:03 ` [PATCH v7 3/4] Silicon/Phytium: Added fvb driver for flash Ling Jia
2022-04-14  6:03 ` [PATCH v7 4/4] Silicon/Phytium: Added runtime support to spi master Ling Jia

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox