* [PATCH 1/4] Platform/NXP : Add Integrated flash controller library support
2017-12-01 4:10 [PATCH 0/4] Platform/NXP-Adding NXP NOR IP Vabhav
@ 2017-12-01 4:10 ` Vabhav
2017-12-01 4:10 ` [PATCH 2/4] Platform/NXP : Add Support for NOR flash Library Vabhav
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Vabhav @ 2017-12-01 4:10 UTC (permalink / raw)
To: ard.biesheuvel, leif.lindholm, michael.d.kinney, edk2-devel
On NXP Layerscape SoCs,NOR Flash device interfacing is
via IFC and IfcFlashLib provides helper functions to be
used by NXP NOR flash library
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Vabhav <vabhav.sharma@nxp.com>
---
Platform/NXP/Include/Library/Ifc.h | 147 +++++++++++++++++++++
Platform/NXP/Include/Library/IfcBase.h | 139 +++++++++++++++++++
.../Include/Library/IfcBoardSpecificLib.h | 51 +++++++
Platform/NXP/Library/IfcFlashLib/IfcFlashLib.c | 65 +++++++++
Platform/NXP/Library/IfcFlashLib/IfcFlashLib.inf | 30 +++++
5 files changed, 432 insertions(+)
create mode 100755 Platform/NXP/Include/Library/Ifc.h
create mode 100644 Platform/NXP/Include/Library/IfcBase.h
create mode 100755 Platform/NXP/LS1043aRdbPkg/Include/Library/IfcBoardSpecificLib.h
create mode 100644 Platform/NXP/Library/IfcFlashLib/IfcFlashLib.c
create mode 100644 Platform/NXP/Library/IfcFlashLib/IfcFlashLib.inf
diff --git a/Platform/NXP/Include/Library/Ifc.h b/Platform/NXP/Include/Library/Ifc.h
new file mode 100755
index 0000000..8cc13f6
--- /dev/null
+++ b/Platform/NXP/Include/Library/Ifc.h
@@ -0,0 +1,147 @@
+/** @Ifc.h
+
+ Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
+ Copyright 2017 NXP
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __IFC_H__
+#define __IFC_H__
+
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/IfcBase.h>
+#include <Library/IoLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#define IFC_BANK_COUNT 4
+
+#define IFC_CSPR_REG_LEN 148
+#define IFC_AMASK_REG_LEN 144
+#define IFC_CSOR_REG_LEN 144
+#define IFC_FTIM_REG_LEN 576
+
+#define IFC_CSPR_USED_LEN sizeof(IFC_CSPR) * \
+ IFC_BANK_COUNT
+
+#define IFC_AMASK_USED_LEN sizeof(IFC_AMASK) * \
+ IFC_BANK_COUNT
+
+#define IFC_CSOR_USED_LEN sizeof(IFC_CSOR) * \
+ IFC_BANK_COUNT
+
+#define IFC_FTIM_USED_LEN sizeof(IFC_FTIM) * \
+ IFC_BANK_COUNT
+
+typedef enum {
+ IFC_CS0 = 0,
+ IFC_CS1,
+ IFC_CS2,
+ IFC_CS3,
+ IFC_CS4,
+ IFC_CS5,
+ IFC_CS6,
+ IFC_CS7,
+} IFC_CHIP_SEL;
+
+typedef enum {
+ IFC_FTIM0 = 0,
+ IFC_FTIM1,
+ IFC_FTIM2,
+ IFC_FTIM3,
+} IFC_FTIMS;
+
+typedef struct {
+ UINT32 CsprExt;
+ UINT32 Cspr;
+ UINT32 Res;
+} IFC_CSPR;
+
+typedef struct {
+ UINT32 Amask;
+ UINT32 Res[0x2];
+} IFC_AMASK;
+
+typedef struct {
+ UINT32 Csor;
+ UINT32 CsorExt;
+ UINT32 Res;
+} IFC_CSOR;
+
+typedef struct {
+ UINT32 Ftim[4];
+ UINT32 Res[0x8];
+}IFC_FTIM ;
+
+/*
+ * IFC controller NOR Machine registers
+ */
+typedef struct {
+ UINT32 NorEvterStat;
+ UINT32 Res1[0x2];
+ UINT32 NorEvterEn;
+ UINT32 Res2[0x2];
+ UINT32 NorEvterIntrEn;
+ UINT32 Res3[0x2];
+ UINT32 NorErattr0;
+ UINT32 NorErattr1;
+ UINT32 NorErattr2;
+ UINT32 Res4[0x4];
+ UINT32 NorCr;
+ UINT32 Res5[0xEF];
+} IFC_NOR;
+
+/*
+ * IFC Controller Registers
+ */
+typedef struct {
+ UINT32 IfcRev;
+ UINT32 Res1[0x2];
+ IFC_CSPR CsprCs[IFC_BANK_COUNT];
+ UINT8 Res2[IFC_CSPR_REG_LEN - IFC_CSPR_USED_LEN];
+ IFC_AMASK AmaskCs[IFC_BANK_COUNT];
+ UINT8 Res3[IFC_AMASK_REG_LEN - IFC_AMASK_USED_LEN];
+ IFC_CSOR CsorCs[IFC_BANK_COUNT];
+ UINT8 Res4[IFC_CSOR_REG_LEN - IFC_CSOR_USED_LEN];
+ IFC_FTIM FtimCs[IFC_BANK_COUNT];
+ UINT8 Res5[IFC_FTIM_REG_LEN - IFC_FTIM_USED_LEN];
+ UINT32 RbStat;
+ UINT32 RbMap;
+ UINT32 WpMap;
+ UINT32 IfcGcr;
+ UINT32 Res7[0x2];
+ UINT32 CmEvter_stat;
+ UINT32 Res8[0x2];
+ UINT32 CmEvterEn;
+ UINT32 Res9[0x2];
+ UINT32 CmEvterIntrEn;
+ UINT32 Res10[0x2];
+ UINT32 CmErattr0;
+ UINT32 CmErattr1;
+ UINT32 Res11[0x2];
+ UINT32 IfcCcr;
+ UINT32 IfcCsr;
+ UINT32 DdrCcrLow;
+ UINT32 Res12[0x2EA];
+ IFC_NOR IfcNor;
+} IFC_REGS;
+
+typedef struct {
+ UINT32 Ftim[IFC_BANK_COUNT];
+ UINT32 CsprExt;
+ UINT32 Cspr;
+ UINT32 Csor;
+ UINT32 Amask;
+} IfcTimings;
+
+#endif //__IFC_H__
diff --git a/Platform/NXP/Include/Library/IfcBase.h b/Platform/NXP/Include/Library/IfcBase.h
new file mode 100644
index 0000000..7020a29
--- /dev/null
+++ b/Platform/NXP/Include/Library/IfcBase.h
@@ -0,0 +1,139 @@
+/** @IfcLib.h
+
+ Copyright 2017 NXP
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __IFC_COMMON_H__
+#define __IFC_COMMON_H__
+
+#define NOR_FLASH_DEVICE_COUNT 1
+
+#define MAX_RETRY_COUNT 150000
+
+/*
+ * CSPR - Chip Select Property Register
+ */
+
+#define IFC_CSPR_BA 0xFFFF0000
+#define IFC_CSPR_BA_SHIFT 16
+#define IFC_CSPR_PORT_SIZE 0x00000180
+#define IFC_CSPR_PORT_SIZE_SHIFT 7
+
+// Port Size 8 bit
+#define IFC_CSPR_PORT_SIZE_8 0x00000080
+
+// Port Size 16 bit
+#define IFC_CSPR_PORT_SIZE_16 0x00000100
+
+// Port Size 32 bit
+#define IFC_CSPR_PORT_SIZE_32 0x00000180
+
+// Write Protect
+#define IFC_CSPR_WP 0x00000040
+#define IFC_CSPR_WP_SHIFT 6
+
+// Machine Select
+#define IFC_CSPR_MSEL 0x00000006
+#define IFC_CSPR_MSEL_SHIFT 1
+
+// NOR
+#define IFC_CSPR_MSEL_NOR 0x00000000
+
+// Bank Valid
+#define IFC_CSPR_V 0x00000001
+#define IFC_CSPR_V_SHIFT 0
+
+/*
+ * Chip Select Option Register - NOR Flash Mode
+ */
+
+// Enable Address shift Mode
+#define IFC_CSOR_NOR_ADM_SHFT_MODE_EN 0x80000000
+
+// Page Read Enable from NOR device
+#define IFC_CSOR_NOR_PGRD_EN 0x10000000
+
+// AVD Toggle Enable during Burst Program
+#define IFC_CSOR_NOR_AVD_TGL_PGM_EN 0x01000000
+
+// Address Data Multiplexing Shift
+#define IFC_CSOR_NOR_ADM_MASK 0x0003E000
+#define IFC_CSOR_NOR_ADM_SHIFT_SHIFT 13
+#define IFC_CSOR_NOR_ADM_SHIFT(n) ((n) << IFC_CSOR_NOR_ADM_SHIFT_SHIFT)
+
+// Type of the NOR device hooked
+#define IFC_CSOR_NOR_NOR_MODE_AYSNC_NOR 0x00000000
+#define IFC_CSOR_NOR_NOR_MODE_AVD_NOR 0x00000020
+
+// Time for Read Enable High to Output High Impedance
+#define IFC_CSOR_NOR_TRHZ_MASK 0x0000001C
+#define IFC_CSOR_NOR_TRHZ_SHIFT 2
+#define IFC_CSOR_NOR_TRHZ_20 0x00000000
+#define IFC_CSOR_NOR_TRHZ_40 0x00000004
+#define IFC_CSOR_NOR_TRHZ_60 0x00000008
+#define IFC_CSOR_NOR_TRHZ_80 0x0000000C
+#define IFC_CSOR_NOR_TRHZ_100 0x00000010
+
+// Buffer control disable
+#define IFC_CSOR_NOR_BCTLD 0x00000001
+
+/*
+ * FTIM0 - NOR Flash Mode
+ */
+#define IFC_FTIM0_NOR 0xF03F3F3F
+#define IFC_FTIM0_NOR_TACSE_SHIFT 28
+#define IFC_FTIM0_NOR_TACSE(n) ((n) << IFC_FTIM0_NOR_TACSE_SHIFT)
+#define IFC_FTIM0_NOR_TEADC_SHIFT 16
+#define IFC_FTIM0_NOR_TEADC(n) ((n) << IFC_FTIM0_NOR_TEADC_SHIFT)
+#define IFC_FTIM0_NOR_TAVDS_SHIFT 8
+#define IFC_FTIM0_NOR_TAVDS(n) ((n) << IFC_FTIM0_NOR_TAVDS_SHIFT)
+#define IFC_FTIM0_NOR_TEAHC_SHIFT 0
+#define IFC_FTIM0_NOR_TEAHC(n) ((n) << IFC_FTIM0_NOR_TEAHC_SHIFT)
+
+/*
+ * FTIM1 - NOR Flash Mode
+ */
+#define IFC_FTIM1_NOR 0xFF003F3F
+#define IFC_FTIM1_NOR_TACO_SHIFT 24
+#define IFC_FTIM1_NOR_TACO(n) ((n) << IFC_FTIM1_NOR_TACO_SHIFT)
+#define IFC_FTIM1_NOR_TRAD_NOR_SHIFT 8
+#define IFC_FTIM1_NOR_TRAD_NOR(n) ((n) << IFC_FTIM1_NOR_TRAD_NOR_SHIFT)
+#define IFC_FTIM1_NOR_TSEQRAD_NOR_SHIFT 0
+#define IFC_FTIM1_NOR_TSEQRAD_NOR(n) ((n) << IFC_FTIM1_NOR_TSEQRAD_NOR_SHIFT)
+
+/*
+ * FTIM2 - NOR Flash Mode
+ */
+#define IFC_FTIM2_NOR 0x0F3CFCFF
+#define IFC_FTIM2_NOR_TCS_SHIFT 24
+#define IFC_FTIM2_NOR_TCS(n) ((n) << IFC_FTIM2_NOR_TCS_SHIFT)
+#define IFC_FTIM2_NOR_TCH_SHIFT 18
+#define IFC_FTIM2_NOR_TCH(n) ((n) << IFC_FTIM2_NOR_TCH_SHIFT)
+#define IFC_FTIM2_NOR_TWPH_SHIFT 10
+#define IFC_FTIM2_NOR_TWPH(n) ((n) << IFC_FTIM2_NOR_TWPH_SHIFT)
+#define IFC_FTIM2_NOR_TWP_SHIFT 0
+#define IFC_FTIM2_NOR_TWP(n) ((n) << IFC_FTIM2_NOR_TWP_SHIFT)
+
+/* Convert an address into the right format for the CSPR Registers */
+#define IFC_CSPR_PHYS_ADDR(x) (((UINTN)x) & 0xffff0000)
+
+/*
+ * Address Mask Register
+ */
+#define IFC_AMASK_MASK 0xFFFF0000
+#define IFC_AMASK_SHIFT 16
+#define IFC_AMASK(n) (IFC_AMASK_MASK << \
+ (HighBitSet32(n) - IFC_AMASK_SHIFT))
+
+VOID IfcNorInit(VOID);
+
+#endif //__IFC_COMMON_H__
diff --git a/Platform/NXP/LS1043aRdbPkg/Include/Library/IfcBoardSpecificLib.h b/Platform/NXP/LS1043aRdbPkg/Include/Library/IfcBoardSpecificLib.h
new file mode 100755
index 0000000..d3c3c7c
--- /dev/null
+++ b/Platform/NXP/LS1043aRdbPkg/Include/Library/IfcBoardSpecificLib.h
@@ -0,0 +1,51 @@
+/** IfcBoardSpecificLib.h
+ IFC Flash Board Specific library
+
+ Copyright 2017 NXP
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#ifndef __IFC__BOARD_SPECIFIC_LIB_H__
+#define __IFC__BOARD_SPECIFIC_LIB_H__
+
+// On board flash support,endianness
+#define NOR_SUPPORT
+#define SYS_IFC_NOR_BE
+#define IFC_REG_BASE 0x1530000
+#define IFC_NOR_BUF_BASE 0x60000000
+
+// On board Inegrated flash Controller chip select configuration
+#define IFC_NOR_CS IFC_CS0
+
+// board-specific NOR flash timing
+#define NOR_FTIM0 (IFC_FTIM0_NOR_TACSE(0x1) | \
+ IFC_FTIM0_NOR_TEADC(0x1) | \
+ IFC_FTIM0_NOR_TAVDS(0x0) | \
+ IFC_FTIM0_NOR_TEAHC(0xc))
+#define NOR_FTIM1 (IFC_FTIM1_NOR_TACO(0x1c) | \
+ IFC_FTIM1_NOR_TRAD_NOR(0xb) |\
+ IFC_FTIM1_NOR_TSEQRAD_NOR(0x9))
+#define NOR_FTIM2 (IFC_FTIM2_NOR_TCS(0x1) | \
+ IFC_FTIM2_NOR_TCH(0x4) | \
+ IFC_FTIM2_NOR_TWPH(0x8) | \
+ IFC_FTIM2_NOR_TWP(0x10))
+#define NOR_FTIM3 0x0
+
+#define NOR_CSPR (IFC_CSPR_PHYS_ADDR(IFC_NOR_BUF_BASE) \
+ | IFC_CSPR_PORT_SIZE_16 \
+ | IFC_CSPR_MSEL_NOR \
+ | IFC_CSPR_V)
+
+#define NOR_CSPR_EXT 0x0
+#define NOR_AMASK IFC_AMASK(128*1024*1024)
+#define NOR_CSOR (IFC_CSOR_NOR_ADM_SHIFT(4) | \
+ IFC_CSOR_NOR_TRHZ_80)
+
+#endif //__IFC__BOARD_SPECIFIC_LIB_H__
diff --git a/Platform/NXP/Library/IfcFlashLib/IfcFlashLib.c b/Platform/NXP/Library/IfcFlashLib/IfcFlashLib.c
new file mode 100644
index 0000000..7748972
--- /dev/null
+++ b/Platform/NXP/Library/IfcFlashLib/IfcFlashLib.c
@@ -0,0 +1,65 @@
+/** @IfcFlashLib.c
+
+ Copyright 2017 NXP
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Library/NorFlashLib.h>
+// Include board specific file for Flash timing
+#include <LS1043aRdbPkg/Include/Library/IfcBoardSpecificLib.h>
+
+#ifdef NOR_SUPPORT
+VOID
+GetIfcNorFlashInfo (
+ IN NorFlashInfo *NorFlashInfo
+ )
+{
+ NorFlashInfo->IfcRegs = (IFC_REGS*) IFC_REG_BASE;
+ NorFlashInfo->ChipSelect = IFC_NOR_CS;
+ return ;
+}
+
+VOID
+GetIfcNorFlashTimings (
+ IN IfcTimings * NorIfcTimings
+ )
+{
+ NorIfcTimings->Ftim[0] = NOR_FTIM0;
+ NorIfcTimings->Ftim[1] = NOR_FTIM1;
+ NorIfcTimings->Ftim[2] = NOR_FTIM2;
+ NorIfcTimings->Ftim[3] = NOR_FTIM3;
+ NorIfcTimings->Cspr = NOR_CSPR;
+ NorIfcTimings->CsprExt = NOR_CSPR_EXT;
+ NorIfcTimings->Amask = NOR_AMASK;
+ NorIfcTimings->Csor = NOR_CSOR;
+ return ;
+}
+
+VOID IfcNorWrite32 (VOID *a, UINT32 v) {
+#ifdef SYS_IFC_NOR_BE
+ MmioWriteBe32((UINTN)a, v);
+#else
+ MmioWrite32((UINTN)a, v);
+#endif
+}
+
+FLASH_DATA
+IfcNorFlashData (
+ FLASH_DATA Value
+ )
+{
+#ifdef SYS_IFC_NOR_BE
+ return SwapBytes16(Value);
+#else
+ return Value;
+#endif
+}
+#endif //NOR_SUPPORT
diff --git a/Platform/NXP/Library/IfcFlashLib/IfcFlashLib.inf b/Platform/NXP/Library/IfcFlashLib/IfcFlashLib.inf
new file mode 100644
index 0000000..bd92474
--- /dev/null
+++ b/Platform/NXP/Library/IfcFlashLib/IfcFlashLib.inf
@@ -0,0 +1,30 @@
+#/** IfcFlashLib.inf
+#
+# Component description file for IFC FLASH Library
+#
+# Copyright 2017 NXP
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x0001001A
+ BASE_NAME = IfcFlashLib
+ FILE_GUID = 8ecefc8f-a2c4-4091-b80f-92da7c4ab37f
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = IfcFlashLib
+
+[Sources.common]
+ IfcFlashLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ Platform/NXP/NxpQoriqLs.dec
--
1.9.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 2/4] Platform/NXP : Add Support for NOR flash Library
2017-12-01 4:10 [PATCH 0/4] Platform/NXP-Adding NXP NOR IP Vabhav
2017-12-01 4:10 ` [PATCH 1/4] Platform/NXP : Add Integrated flash controller library support Vabhav
@ 2017-12-01 4:10 ` Vabhav
2017-12-01 4:10 ` [PATCH 3/4] Platform/NXP : Add Support for NOR Flash driver Vabhav
2017-12-01 4:10 ` [PATCH 4/4] Compilation:Modify dsc, fdf files and add inc file Vabhav
3 siblings, 0 replies; 5+ messages in thread
From: Vabhav @ 2017-12-01 4:10 UTC (permalink / raw)
To: ard.biesheuvel, leif.lindholm, michael.d.kinney, edk2-devel
This patch adds support for NOR flash library(NorFlashLib)
to provide functions which will be used by NOR flash
Driver.
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Vabhav <vabhav.sharma@nxp.com>
---
Platform/NXP/Include/Library/NorFlashLib.h | 67 +++
Platform/NXP/Library/NorFlashLib/CfiCommand.h | 99 ++++
Platform/NXP/Library/NorFlashLib/CfiNorFlashLib.c | 184 ++++++
Platform/NXP/Library/NorFlashLib/CfiNorFlashLib.h | 54 ++
Platform/NXP/Library/NorFlashLib/IfcNorFlashLib.c | 52 ++
Platform/NXP/Library/NorFlashLib/NorFlashLib.c | 658 ++++++++++++++++++++++
Platform/NXP/Library/NorFlashLib/NorFlashLib.inf | 42 ++
7 files changed, 1156 insertions(+)
create mode 100644 Platform/NXP/Include/Library/NorFlashLib.h
create mode 100644 Platform/NXP/Library/NorFlashLib/CfiCommand.h
create mode 100644 Platform/NXP/Library/NorFlashLib/CfiNorFlashLib.c
create mode 100644 Platform/NXP/Library/NorFlashLib/CfiNorFlashLib.h
create mode 100644 Platform/NXP/Library/NorFlashLib/IfcNorFlashLib.c
create mode 100644 Platform/NXP/Library/NorFlashLib/NorFlashLib.c
create mode 100644 Platform/NXP/Library/NorFlashLib/NorFlashLib.inf
diff --git a/Platform/NXP/Include/Library/NorFlashLib.h b/Platform/NXP/Include/Library/NorFlashLib.h
new file mode 100644
index 0000000..8eb0f82
--- /dev/null
+++ b/Platform/NXP/Include/Library/NorFlashLib.h
@@ -0,0 +1,67 @@
+/** @file
+
+ Copyright (c) 2011-2012, ARM Ltd. All rights reserved.
+ Copyright (c) 2016, Freescale Semiconductor. All rights reserved.
+ Copyright 2017 NXP
+
+This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ **/
+
+#ifndef _NOR_FLASH_LIB_H_
+#define _NOR_FLASH_LIB_H_
+
+#include <Library/Ifc.h>
+
+typedef struct {
+ UINTN DeviceBaseAddress; // Start address of the Device Base Address (DBA)
+ UINTN RegionBaseAddress; // Start address of one single region
+ UINTN Size;
+ UINTN BlockSize;
+ UINTN MultiByteWordCount; // Maximum Word count that can be written to Nor Flash in multi byte write
+ UINTN WordWriteTimeOut; // single byte/word timeout usec
+ UINTN BufferWriteTimeOut; // buffer write timeout usec
+ UINTN BlockEraseTimeOut; // block erase timeout usec
+ UINTN ChipEraseTimeOut; // chip erase timeout usec
+} NorFlashDescription;
+
+EFI_STATUS
+NorFlashPlatformGetDevices (
+ OUT NorFlashDescription **NorFlashDevices,
+ OUT UINT32 *Count
+ );
+
+EFI_STATUS
+NorFlashPlatformFlashGetAttributes (
+ OUT NorFlashDescription *NorFlashDevices,
+ IN UINT32 Count
+ );
+
+typedef struct {
+ UINT8 ChipSelect;
+ IFC_REGS* IfcRegs;
+} NorFlashInfo;
+
+VOID
+GetIfcNorFlashInfo (
+ IN NorFlashInfo *NorFlashInfo
+ );
+
+VOID
+GetIfcNorFlashTimings (
+ IN IfcTimings * NorIfcTimings
+ );
+
+typedef UINT16 FLASH_DATA;
+
+FLASH_DATA IfcNorFlashData (FLASH_DATA Val);
+
+VOID IfcNorWrite32 (VOID *a, UINT32 v);
+
+#endif /* _NOR_FLASH_LIB_H_ */
diff --git a/Platform/NXP/Library/NorFlashLib/CfiCommand.h b/Platform/NXP/Library/NorFlashLib/CfiCommand.h
new file mode 100644
index 0000000..5e755be
--- /dev/null
+++ b/Platform/NXP/Library/NorFlashLib/CfiCommand.h
@@ -0,0 +1,99 @@
+/** @CfiCommand.h
+
+ Copyright 2017 NXP
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __CFI_COMMAND_H__
+#define __CFI_COMMAND_H__
+
+// CFI Data "QRY"
+#define CFI_QRY_Q 0x51
+#define CFI_QRY_R 0x52
+#define CFI_QRY_Y 0x59
+#define CFI_QRY 0x515259
+
+#define ENTER_CFI_QUERY_MODE_ADDR 0x0055
+#define ENTER_CFI_QUERY_MODE_CMD 0x0098
+
+#define CFI_QUERY_UNIQUE_QRY_STRING 0x10
+
+// Offsets for CFI queries
+#define CFI_QUERY_TYP_TIMEOUT_WORD_WRITE 0x1F
+#define CFI_QUERY_TYP_TIMEOUT_MAX_BUFFER_WRITE 0x20
+#define CFI_QUERY_TYP_TIMEOUT_BLOCK_ERASE 0x21
+#define CFI_QUERY_TYP_TIMEOUT_CHIP_ERASE 0x22
+#define CFI_QUERY_MAX_TIMEOUT_WORD_WRITE 0x23
+#define CFI_QUERY_MAX_TIMEOUT_MAX_BUFFER_WRITE 0x24
+#define CFI_QUERY_MAX_TIMEOUT_BLOCK_ERASE 0x25
+#define CFI_QUERY_MAX_TIMEOUT_CHIP_ERASE 0x26
+#define CFI_QUERY_DEVICE_SIZE 0x27
+#define CFI_QUERY_MAX_NUM_BYTES_WRITE 0x2A
+#define CFI_QUERY_BLOCK_SIZE 0x2F
+
+// Unlock Address
+#define CMD_UNLOCK_1_ADDR 0x555
+#define CMD_UNLOCK_2_ADDR 0x2AA
+
+// RESET Command
+#define CMD_RESET_FIRST 0xAA
+#define CMD_RESET_SECOND 0x55
+#define CMD_RESET 0xF0
+
+// READ Command
+
+// Manufacturer ID
+#define CMD_READ_M_ID_FIRST 0xAA
+#define CMD_READ_M_ID_SECOND 0x55
+#define CMD_READ_M_ID_THIRD 0x90
+#define CMD_READ_M_ID_FOURTH 0x01
+
+// Device ID
+#define CMD_READ_D_ID_FIRST 0xAA
+#define CMD_READ_D_ID_SECOND 0x55
+#define CMD_READ_D_ID_THIRD 0x90
+#define CMD_READ_D_ID_FOURTH 0x7E
+#define CMD_READ_D_ID_FIFTH 0x13
+#define CMD_READ_D_ID_SIXTH 0x00
+
+// WRITE Commands
+
+// PROGRAM Commands
+#define CMD_PROGRAM_FIRST 0xAA
+#define CMD_PROGRAM_SECOND 0x55
+#define CMD_PROGRAM_THIRD 0xA0
+
+// Write Buffer Commands
+#define CMD_WRITE_TO_BUFFER_FIRST 0xAA
+#define CMD_WRITE_TO_BUFFER_SECOND 0x55
+#define CMD_WRITE_TO_BUFFER_THIRD 0x25
+#define CMD_WRITE_TO_BUFFER_CONFIRM 0x29
+
+// ERASE Commands
+
+// UNLOCK COMMANDS FOR ERASE
+#define CMD_ERASE_FIRST 0xAA
+#define CMD_ERASE_SECOND 0x55
+#define CMD_ERASE_THIRD 0x80
+#define CMD_ERASE_FOURTH 0xAA
+#define CMD_ERASE_FIFTH 0x55
+
+// Chip Erase Commands
+#define CMD_CHIP_ERASE_SIXTH 0x10
+
+// Sector Erase Commands
+#define CMD_SECTOR_ERASE_SIXTH 0x30
+
+// SUSPEND Commands
+#define CMD_PROGRAM_OR_ERASE_SUSPEND 0xB0
+#define CMD_PROGRAM_OR_ERASE_RESUME 0x30
+
+#endif /* __CFI_FLASH_H__ */
diff --git a/Platform/NXP/Library/NorFlashLib/CfiNorFlashLib.c b/Platform/NXP/Library/NorFlashLib/CfiNorFlashLib.c
new file mode 100644
index 0000000..2683cae
--- /dev/null
+++ b/Platform/NXP/Library/NorFlashLib/CfiNorFlashLib.c
@@ -0,0 +1,184 @@
+/** @CfiNorFlashLib.c
+
+ Copyright (c) 2015, Freescale Semiconductor, Inc. All rights reserved.
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ **/
+
+#include <PiDxe.h>
+#include <Library/ArmLib.h>
+#include <Library/NorFlash.h>
+#include "CfiCommand.h"
+#include "CfiNorFlashLib.h"
+
+VOID
+FlashWrite_Data (
+ FLASH_DATA Val,
+ UINTN Addr
+ )
+{
+ *(volatile FLASH_DATA *)(Addr) = (Val);
+}
+
+VOID
+FlashWrite (
+ FLASH_DATA Val,
+ UINTN Addr
+ )
+{
+ FLASH_DATA ShiftVal;
+ ShiftVal = IfcNorFlashData (Val);
+
+ *(volatile FLASH_DATA *)(Addr) = (ShiftVal);
+}
+
+FLASH_DATA
+FlashReadData (
+ UINTN Addr
+ )
+{
+ FLASH_DATA Val;
+ Val = *(volatile FLASH_DATA *)(Addr);
+
+ return (Val);
+}
+
+FLASH_DATA
+FlashRead (
+ UINTN Addr
+ )
+{
+ FLASH_DATA Val;
+ FLASH_DATA ShiftVal;
+
+ Val = *(volatile FLASH_DATA *)(Addr);
+ ShiftVal = IfcNorFlashData (Val);
+
+ return (ShiftVal);
+}
+
+STATIC
+VOID
+NorFlashReadCfiData (
+ IN UINTN DeviceBaseAddress,
+ IN UINTN CFI_Offset,
+ IN UINT32 NumberOfShorts,
+ OUT VOID *Data
+ )
+{
+ UINT32 Count;
+ FLASH_DATA *TmpData = (FLASH_DATA *)Data;
+
+ for (Count = 0; Count < NumberOfShorts; Count++, TmpData++) {
+ *TmpData = FLASH_READ ((UINTN)((FLASH_DATA*)DeviceBaseAddress + CFI_Offset));
+ CFI_Offset++;
+ }
+}
+
+/*
+ Currently we support only CFI flash devices; Bail-out otherwise
+*/
+EFI_STATUS
+CfiNorFlashFlashGetAttributes (
+ OUT NorFlashDescription *NorFlashDevices,
+ IN UINT32 Index
+ )
+{
+ UINT32 Count;
+ FLASH_DATA QryData[3] = {0};
+ FLASH_DATA BlockSize[2] = {0};
+ UINTN DeviceBaseAddress = 0;
+ FLASH_DATA MaxNumBytes[2] = {0};
+ FLASH_DATA Size = 0;
+ FLASH_DATA HighByteMask = 0xFF; // Masks High byte in a UIN16 word
+ FLASH_DATA HighByteShift = 8; // Bitshifts needed to make a byte High Byte in a UIN16 word
+ FLASH_DATA Temp1 = 0;
+ FLASH_DATA Temp2 = 0;
+
+ for (Count = 0; Count < Index; Count++) {
+
+ NorFlashDevices[Count].DeviceBaseAddress = DeviceBaseAddress = PcdGet64 (PcdFlashDeviceBase64);
+
+ // Reset flash first
+ NorFlashPlatformReset (DeviceBaseAddress);
+
+ // Enter the CFI Query Mode
+ SEND_NOR_COMMAND (DeviceBaseAddress, ENTER_CFI_QUERY_MODE_ADDR,
+ ENTER_CFI_QUERY_MODE_CMD);
+
+ ArmDataSynchronizationBarrier ();
+
+ // Query the unique QRY
+ NorFlashReadCfiData (DeviceBaseAddress,
+ CFI_QUERY_UNIQUE_QRY_STRING,
+ 3,
+ &QryData);
+ if (QryData[0] != (FLASH_DATA)CFI_QRY_Q || QryData[1] !=
+ (FLASH_DATA)CFI_QRY_R || QryData[2] != (FLASH_DATA)CFI_QRY_Y ) {
+ DEBUG ((DEBUG_ERROR, "Not a CFI flash (QRY not recvd): "
+ "Got = 0x%04x, 0x%04x, 0x%04x\n",
+ QryData[0], QryData[1], QryData[2]));
+ return EFI_DEVICE_ERROR;
+ }
+
+ NorFlashReadCfiData (DeviceBaseAddress, CFI_QUERY_DEVICE_SIZE,
+ 1, &Size);
+ // Refer CFI Specification
+ NorFlashDevices[Count].Size = 1 << Size;
+
+ NorFlashReadCfiData (DeviceBaseAddress, CFI_QUERY_BLOCK_SIZE,
+ 2, &BlockSize);
+ // Refer CFI Specification
+ NorFlashDevices[Count].BlockSize = 256 * ((FLASH_DATA) ((BlockSize[1] <<
+ HighByteShift) | (BlockSize[0] & HighByteMask)));
+
+ NorFlashReadCfiData (DeviceBaseAddress,
+ CFI_QUERY_MAX_NUM_BYTES_WRITE, 2, &MaxNumBytes);
+ // Refer CFI Specification
+ /* from CFI query we get the Max. number of BYTE in multi-byte write = 2^N.
+ But our Flash Library is able to read/write in WORD size (2 bytes) which
+ is why we need to CONVERT MAX BYTES TO MAX WORDS by diving it by
+ width of word size */
+ NorFlashDevices[Count].MultiByteWordCount =\
+ (1 << ((FLASH_DATA)((MaxNumBytes[1] << HighByteShift) |
+ (MaxNumBytes[0] & HighByteMask))))/sizeof(FLASH_DATA);
+
+ NorFlashReadCfiData (DeviceBaseAddress,
+ CFI_QUERY_TYP_TIMEOUT_WORD_WRITE, 1, &Temp1);
+ NorFlashReadCfiData (DeviceBaseAddress,
+ CFI_QUERY_MAX_TIMEOUT_WORD_WRITE, 1, &Temp2);
+ NorFlashDevices[Count].WordWriteTimeOut = (1U << Temp1) * (1U << Temp2);
+
+ NorFlashReadCfiData (DeviceBaseAddress,
+ CFI_QUERY_TYP_TIMEOUT_MAX_BUFFER_WRITE, 1, &Temp1);
+ NorFlashReadCfiData (DeviceBaseAddress,
+ CFI_QUERY_MAX_TIMEOUT_MAX_BUFFER_WRITE, 1, &Temp2);
+ NorFlashDevices[Count].BufferWriteTimeOut = (1U << Temp1) * (1U << Temp2);
+
+ NorFlashReadCfiData (DeviceBaseAddress,
+ CFI_QUERY_TYP_TIMEOUT_BLOCK_ERASE, 1, &Temp1);
+ NorFlashReadCfiData (DeviceBaseAddress,
+ CFI_QUERY_MAX_TIMEOUT_BLOCK_ERASE, 1, &Temp2);
+ NorFlashDevices[Count].BlockEraseTimeOut =
+ (1U << Temp1) * (1U << Temp2) * 1000;
+
+ NorFlashReadCfiData (DeviceBaseAddress,
+ CFI_QUERY_TYP_TIMEOUT_CHIP_ERASE, 1, &Temp1);
+ NorFlashReadCfiData (DeviceBaseAddress,
+ CFI_QUERY_MAX_TIMEOUT_CHIP_ERASE, 1, &Temp2);
+ NorFlashDevices[Count].ChipEraseTimeOut =
+ (1U << Temp1) * (1U << Temp2) * 1000;
+
+ // Put device back into Read Array mode (via Reset)
+ NorFlashPlatformReset (DeviceBaseAddress);
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/Platform/NXP/Library/NorFlashLib/CfiNorFlashLib.h b/Platform/NXP/Library/NorFlashLib/CfiNorFlashLib.h
new file mode 100644
index 0000000..7e798dc
--- /dev/null
+++ b/Platform/NXP/Library/NorFlashLib/CfiNorFlashLib.h
@@ -0,0 +1,54 @@
+/** @CfiNorFlashLib.h
+
+ Copyright (c) 2015, Freescale Semiconductor, Inc. All rights reserved.
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __CFI_NOR_FLASH_LIB_H__
+#define __CFI_NOR_FLASH_LIB_H__
+
+#include <Library/DebugLib.h>
+#include <Library/NorFlashLib.h>
+
+/*
+ * Values for the width of the port
+ */
+#define FLASH_CFI_8BIT 0x01
+#define FLASH_CFI_16BIT 0x02
+#define FLASH_CFI_32BIT 0x04
+#define FLASH_CFI_64BIT 0x08
+
+#define NOR_FLASH_ERASE_RETRY 10
+
+#define CREATE_BYTE_OFFSET(OffsetAddr) ((sizeof(FLASH_DATA)) * (OffsetAddr))
+#define CREATE_NOR_ADDRESS(BaseAddr,OffsetAddr) ((BaseAddr) + (OffsetAddr))
+#define FLASH_READ(Addr) FlashRead((Addr))
+#define FLASH_WRITE(Addr, Val) FlashWrite((Val), (Addr))
+#define FLASH_READ_DATA(Addr) FlashReadData((Addr))
+#define FLASH_WRITE_DATA(Addr, Val) FlashWrite_Data((Val), (Addr))
+
+#define SEND_NOR_COMMAND(BaseAddr,Offset,Cmd) FLASH_WRITE(CREATE_NOR_ADDRESS(BaseAddr,CREATE_BYTE_OFFSET(Offset)), (Cmd))
+
+#define GET_NOR_BLOCK_ADDRESS(BaseAddr,Lba,LbaSize) ( BaseAddr + (UINTN)((Lba) * LbaSize) )
+
+VOID FlashWrite (FLASH_DATA Val, UINTN Addr);
+FLASH_DATA FlashRead (UINTN Addr);
+
+VOID FlashWrite_Data (FLASH_DATA Val, UINTN Addr);
+FLASH_DATA FlashReadData (UINTN Addr);
+
+EFI_STATUS
+CfiNorFlashFlashGetAttributes (
+ OUT NorFlashDescription *NorFlashDevices,
+ IN UINT32 Index
+ );
+
+#endif /* __CFI_NOR_FLASH_LIB_H__ */
diff --git a/Platform/NXP/Library/NorFlashLib/IfcNorFlashLib.c b/Platform/NXP/Library/NorFlashLib/IfcNorFlashLib.c
new file mode 100644
index 0000000..f87ebc3
--- /dev/null
+++ b/Platform/NXP/Library/NorFlashLib/IfcNorFlashLib.c
@@ -0,0 +1,52 @@
+/** @IfcNorLib.c
+
+ Copyright (c) 2017 NXP
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ **/
+
+#include <Library/NorFlashLib.h>
+
+/*
+ Initialise Integrated flash controller(IFC) NOR flash
+*/
+VOID
+IfcNorInit (
+ VOID
+ )
+{
+ UINT32 NorCs;
+ NorFlashInfo NorFlashInfo;
+ IfcTimings NorIfcTimings;
+
+ GetIfcNorFlashInfo (&NorFlashInfo);
+ NorCs = NorFlashInfo.ChipSelect;
+
+ // Get Nor Flash Timings
+ GetIfcNorFlashTimings (&NorIfcTimings);
+
+ // Tune IFC Nor Flash Timings
+ IfcNorWrite32 (&NorFlashInfo.IfcRegs->CsprCs[NorCs].CsprExt,
+ NorIfcTimings.CsprExt);
+ IfcNorWrite32 (&NorFlashInfo.IfcRegs->FtimCs[NorCs].Ftim[IFC_FTIM0],
+ NorIfcTimings.Ftim[0]);
+ IfcNorWrite32 (&NorFlashInfo.IfcRegs->FtimCs[NorCs].Ftim[IFC_FTIM1],
+ NorIfcTimings.Ftim[1]);
+ IfcNorWrite32 (&NorFlashInfo.IfcRegs->FtimCs[NorCs].Ftim[IFC_FTIM2],
+ NorIfcTimings.Ftim[2]);
+ IfcNorWrite32 (&NorFlashInfo.IfcRegs->FtimCs[NorCs].Ftim[IFC_FTIM3],
+ NorIfcTimings.Ftim[3]);
+ IfcNorWrite32 (&NorFlashInfo.IfcRegs->CsprCs[NorCs].Cspr,
+ NorIfcTimings.Cspr);
+ IfcNorWrite32 (&NorFlashInfo.IfcRegs->AmaskCs[NorCs].Amask,
+ NorIfcTimings.Amask);
+ IfcNorWrite32 (&NorFlashInfo.IfcRegs->CsorCs[NorCs].Csor,
+ NorIfcTimings.Csor);
+}
diff --git a/Platform/NXP/Library/NorFlashLib/NorFlashLib.c b/Platform/NXP/Library/NorFlashLib/NorFlashLib.c
new file mode 100644
index 0000000..e5e469f
--- /dev/null
+++ b/Platform/NXP/Library/NorFlashLib/NorFlashLib.c
@@ -0,0 +1,658 @@
+/** @NorFlashLib.c
+
+ Based on NorFlash implementation available in NorFlashDxe.c
+
+ Copyright (c) 2011 - 2014, ARM Ltd. All rights reserved.
+ Copyright (c) 2015, Freescale Semiconductor, Inc. All rights reserved.
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <PiDxe.h>
+#include <Library/BaseMemoryLib/MemLibInternals.h>
+#include <Library/NorFlash.h>
+#include <Library/TimerLib.h>
+
+#include "CfiCommand.h"
+#include "CfiNorFlashLib.h"
+
+#define GET_BLOCK_OFFSET(Lba) ((Instance->RegionBaseAddress)-(Instance->DeviceBaseAddress)+((UINTN)((Lba) * Instance->Media.BlockSize)))
+
+NorFlashDescription mNorFlashDevices[NOR_FLASH_DEVICE_COUNT];
+
+STATIC VOID
+UnlockEraseAddress (
+ IN UINTN DeviceBaseAddress
+ )
+{ // Issue the Unlock cmds
+ SEND_NOR_COMMAND (DeviceBaseAddress, CMD_UNLOCK_1_ADDR,
+ CMD_ERASE_FIRST);
+
+ SEND_NOR_COMMAND (DeviceBaseAddress, CMD_UNLOCK_2_ADDR,
+ CMD_ERASE_SECOND);
+
+ // Issue a setup command
+ SEND_NOR_COMMAND (DeviceBaseAddress, CMD_UNLOCK_1_ADDR,
+ CMD_ERASE_THIRD);
+
+ // Issue the Unlock cmds
+ SEND_NOR_COMMAND (DeviceBaseAddress, CMD_UNLOCK_1_ADDR,
+ CMD_ERASE_FOURTH);
+
+ SEND_NOR_COMMAND (DeviceBaseAddress, CMD_UNLOCK_2_ADDR,
+ CMD_ERASE_FIFTH);
+
+ return;
+}
+
+STATIC
+UINT64
+ConvertMicroSecondsToTicks(
+ IN UINTN MicroSeconds
+)
+{
+ UINT64 TimerTicks64;
+
+ TimerTicks64 = 0;
+
+ // Calculate counter ticks that represent requested delay:
+ // = MicroSeconds x TICKS_PER_MICRO_SEC
+ // = MicroSeconds x Timer Frequency(in Hz) x 10^-6
+ // GetPerformanceCounterProperties = Get Arm Timer Frequency in Hz
+ TimerTicks64 = DivU64x32 (
+ MultU64x64 (
+ MicroSeconds,
+ GetPerformanceCounterProperties (NULL, NULL)
+ ),
+ 1000000U
+ );
+ return TimerTicks64;
+}
+
+/**
+ * The following function erases a NOR flash sector.
+ **/
+EFI_STATUS
+NorFlashPlatformEraseSector (
+ IN NOR_FLASH_INSTANCE *Instance,
+ IN UINTN SectorAddress
+ )
+{
+ FLASH_DATA EraseStatus1;
+ FLASH_DATA EraseStatus2;
+ UINT64 Timeout;
+ UINT64 SystemCounterVal;
+
+ EraseStatus1 = 0;
+ EraseStatus2 = 0;
+ Timeout = 0;
+
+ Timeout = ConvertMicroSecondsToTicks (
+ mNorFlashDevices[Instance->Media.MediaId].BlockEraseTimeOut);
+ // Request a sector erase by writing two unlock cycles, followed by a
+ // setup command and two additional unlock cycles
+
+ UnlockEraseAddress (Instance->DeviceBaseAddress);
+
+ // Now send the address of the sector to be erased
+ SEND_NOR_COMMAND (SectorAddress, 0, CMD_SECTOR_ERASE_SIXTH);
+
+ // Wait for erase to complete
+ // Read Sector start address twice to detect bit toggle and to
+ // determine ERASE DONE (all bits are 1)
+ // Get the maximum timer ticks needed to complete the operation
+ // Check if operation is complete or not in continous loop?
+ // if complete, exit from loop
+ // if not check the ticks that have been passed from the begining of loop
+ // if Maximum Ticks allocated for operation has passed exit from loop
+
+ SystemCounterVal = GetPerformanceCounter ();
+ Timeout += SystemCounterVal;
+ while (SystemCounterVal < Timeout) {
+ if ((EraseStatus1 = FLASH_READ(SectorAddress)) ==
+ (EraseStatus2 = FLASH_READ(SectorAddress))) {
+ if (0xFFFF == FLASH_READ(SectorAddress)) {
+ break;
+ }
+ }
+ SystemCounterVal = GetPerformanceCounter ();
+ }
+
+ if(SystemCounterVal >= Timeout) {
+ DEBUG((DEBUG_ERROR, "%a :Failed to Erase @ SectorAddress 0x%p, Timeout\n",
+ __FUNCTION__, SectorAddress));
+ return EFI_DEVICE_ERROR;
+ } else {
+ return EFI_SUCCESS;
+ }
+}
+
+EFI_STATUS NorFlashPlatformWriteWord
+(
+ IN NOR_FLASH_INSTANCE *Instance,
+ IN UINTN WordOffset,
+ IN FLASH_DATA Word
+)
+{
+ UINT64 Timeout;
+ UINTN TargetAddress;
+ UINT64 SystemCounterVal;
+ FLASH_DATA Read1;
+ FLASH_DATA Read2;
+
+ Timeout = 0;
+
+ Timeout = ConvertMicroSecondsToTicks(
+ mNorFlashDevices[Instance->Media.MediaId].WordWriteTimeOut);
+
+ TargetAddress = CREATE_NOR_ADDRESS(Instance->DeviceBaseAddress,
+ CREATE_BYTE_OFFSET(WordOffset));
+
+ // Issue the Unlock cmds
+ SEND_NOR_COMMAND (Instance->DeviceBaseAddress, CMD_UNLOCK_1_ADDR,
+ CMD_PROGRAM_FIRST);
+
+ SEND_NOR_COMMAND (Instance->DeviceBaseAddress, CMD_UNLOCK_2_ADDR,
+ CMD_PROGRAM_SECOND);
+
+ SEND_NOR_COMMAND (Instance->DeviceBaseAddress, CMD_UNLOCK_1_ADDR,
+ CMD_PROGRAM_THIRD);
+
+ FLASH_WRITE_DATA (TargetAddress, Word);
+
+ // Wait for Write to Complete
+ // Read the last written address twice to detect bit toggle and
+ // to determine if date is wriiten successfully or not ?
+ // Get the maximum timer ticks needed to complete the operation
+ // Check if operation is complete or not in continous loop?
+ // if complete, exit from loop
+ // if not check the ticks that have been passed from the begining of loop
+ // if Maximum Ticks allocated for operation has passed, then exit from loop
+
+ SystemCounterVal = GetPerformanceCounter ();
+ Timeout += SystemCounterVal;
+ while (SystemCounterVal < Timeout) {
+ if ((Read1 = FLASH_READ_DATA(TargetAddress)) ==
+ (Read2 = FLASH_READ_DATA(TargetAddress))) {
+ if (Word == FLASH_READ_DATA(TargetAddress)) {
+ break;
+ }
+ }
+ SystemCounterVal = GetPerformanceCounter ();
+ }
+
+ if(SystemCounterVal >= Timeout) {
+ DEBUG((DEBUG_ERROR, "%a: Failed to Write @ TargetAddress 0x%p, Timeout\n",
+ __FUNCTION__, TargetAddress));
+ return EFI_DEVICE_ERROR;
+ } else {
+ return EFI_SUCCESS;
+ }
+}
+
+EFI_STATUS NorFlashPlatformWritePageBuffer
+(
+ IN NOR_FLASH_INSTANCE *Instance,
+ IN UINTN PageBufferOffset,
+ IN UINTN NumWords,
+ IN FLASH_DATA *Buffer
+)
+{
+ UINT64 Timeout;
+ UINTN LastWrittenAddress;
+ FLASH_DATA LastWritenData;
+ UINTN current_offset;
+ UINTN end_offset;
+ UINTN TargetAddress;
+ UINT64 SystemCounterVal;
+ FLASH_DATA Read1;
+ FLASH_DATA Read2;
+
+ // Initialize variables
+ Timeout = 0;
+ LastWrittenAddress = 0;
+ LastWritenData = 0;
+ current_offset = PageBufferOffset;
+ end_offset = PageBufferOffset + NumWords - 1;
+ Timeout = ConvertMicroSecondsToTicks (
+ mNorFlashDevices[Instance->Media.MediaId].BufferWriteTimeOut);
+ TargetAddress = CREATE_NOR_ADDRESS (Instance->DeviceBaseAddress,
+ CREATE_BYTE_OFFSET (current_offset));
+
+ // don't try with a count of zero
+ if (!NumWords) {
+ return EFI_SUCCESS;
+ }
+ else if (NumWords == 1) {
+ return NorFlashPlatformWriteWord (Instance, PageBufferOffset, *Buffer);
+ }
+
+ // Issue the Unlock cmds
+ SEND_NOR_COMMAND (Instance->DeviceBaseAddress, CMD_UNLOCK_1_ADDR,
+ CMD_WRITE_TO_BUFFER_FIRST);
+
+ SEND_NOR_COMMAND (Instance->DeviceBaseAddress, CMD_UNLOCK_2_ADDR,
+ CMD_WRITE_TO_BUFFER_SECOND);
+
+ // Write the buffer load
+ SEND_NOR_COMMAND (TargetAddress, 0, CMD_WRITE_TO_BUFFER_THIRD);
+
+ // Write # of locations to program
+ SEND_NOR_COMMAND (TargetAddress, 0, (NumWords - 1));
+
+ // Load Data into Buffer
+ while (current_offset <= end_offset) {
+ LastWrittenAddress = CREATE_NOR_ADDRESS (Instance->DeviceBaseAddress,
+ CREATE_BYTE_OFFSET (current_offset++));
+ LastWritenData = *Buffer++;
+
+ // Write Data
+ FLASH_WRITE_DATA (LastWrittenAddress,LastWritenData);
+ }
+
+ // Issue the Buffered Program Confirm command
+ SEND_NOR_COMMAND (TargetAddress, 0, CMD_WRITE_TO_BUFFER_CONFIRM);
+
+ /* Wait for Write to Complete
+ Read the last written address twice to detect bit toggle and
+ to determine if date is wriiten successfully or not ?
+ Get the maximum timer ticks needed to complete the operation
+ Check if operation is complete or not in continous loop?
+ if complete, exit from loop
+ if not check the ticks that have been passed from the begining of loop
+ if Maximum Ticks allocated for operation has passed, then exit from loop **/
+ SystemCounterVal = GetPerformanceCounter();
+ Timeout += SystemCounterVal;
+ while (SystemCounterVal < Timeout) {
+ if ((Read1 = FLASH_READ_DATA (LastWrittenAddress)) ==
+ (Read2 = FLASH_READ_DATA (LastWrittenAddress))) {
+ if (LastWritenData == FLASH_READ_DATA (LastWrittenAddress)) {
+ break;
+ }
+ }
+ SystemCounterVal = GetPerformanceCounter ();
+ }
+
+ if (SystemCounterVal >= Timeout) {
+ DEBUG((DEBUG_ERROR, "%a: Failed to Write @LastWrittenAddress 0x%p, Timeout\n",
+ __FUNCTION__, LastWrittenAddress));
+ return EFI_DEVICE_ERROR;
+ } else {
+ return EFI_SUCCESS;
+ }
+}
+
+EFI_STATUS NorFlashPlatformWriteWordAlignedAddressBuffer
+(
+ IN NOR_FLASH_INSTANCE *Instance,
+ IN UINTN Offset,
+ IN UINTN NumWords,
+ IN FLASH_DATA *Buffer
+ )
+{
+ UINTN MultiByteWordCount;
+ UINTN Mask;
+ UINTN IntWords;
+ EFI_STATUS Status;
+
+ MultiByteWordCount = mNorFlashDevices[Instance->Media.MediaId].MultiByteWordCount;
+ Mask = MultiByteWordCount - 1;
+ IntWords = NumWords;
+ Status = EFI_SUCCESS;
+
+ if (Offset & Mask)
+ {
+ // program only as much as necessary, so pick the lower of the two numbers
+ if (NumWords < (MultiByteWordCount - (Offset & Mask))) {
+ IntWords = NumWords;
+ }
+ else {
+ IntWords = MultiByteWordCount - (Offset & Mask);
+ }
+
+ // program the first few to get write buffer aligned
+ Status = NorFlashPlatformWritePageBuffer (Instance, Offset, IntWords, Buffer);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Offset += IntWords; // adjust pointers and counter
+ NumWords -= IntWords;
+ Buffer += IntWords;
+
+ if (NumWords == 0) {
+ return Status;
+ }
+ }
+
+ while (NumWords >= MultiByteWordCount) // while big chunks to do
+ {
+ Status = NorFlashPlatformWritePageBuffer (Instance, Offset,
+ MultiByteWordCount, Buffer);
+ if (EFI_ERROR (Status)) {
+ return (Status);
+ }
+
+ Offset += MultiByteWordCount; // adjust pointers and counter
+ NumWords -= MultiByteWordCount;
+ Buffer += MultiByteWordCount;
+ }
+ if (NumWords == 0) {
+ return (Status);
+ }
+
+ Status = NorFlashPlatformWritePageBuffer (Instance, Offset, NumWords, Buffer);
+ return (Status);
+}
+
+/*
+ * Writes data to the NOR Flash using the Buffered Programming method.
+ *
+ * Write Buffer Programming allows the system to write a maximum of 32 bytes
+ * in one programming operation. Therefore this function will only handle
+ * buffers up to 32 bytes.
+ * To deal with larger buffers, call this function again.
+ */
+EFI_STATUS
+NorFlashPlatformWriteBuffer (
+ IN NOR_FLASH_INSTANCE *Instance,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN OUT UINTN *NumBytes,
+ IN UINT8 *Buffer
+ )
+{
+ EFI_STATUS Status;
+ FLASH_DATA *pSrcBuffer;
+ UINTN TargetOffsetinBytes;
+ UINTN WordsToWrite;
+ UINTN Mask;
+ UINTN BufferSizeInBytes;
+ UINTN IntBytes;
+ UINT8 *CopyFrom, *CopyTo;
+ FLASH_DATA TempWrite = 0;
+
+ pSrcBuffer = (FLASH_DATA *)Buffer;
+ TargetOffsetinBytes = 0;
+ WordsToWrite = 0;
+ Mask = sizeof(FLASH_DATA) - 1;
+ BufferSizeInBytes = *NumBytes;
+ IntBytes = BufferSizeInBytes; // Intermediate Bytes needed to copy for alignment
+ TempWrite = 0;
+
+ DEBUG ((DEBUG_BLKIO, "%a(Parameters: Lba=%ld, Offset=0x%x, "
+ "*NumBytes=0x%x, Buffer @ 0x%08x)\n",
+ __FUNCTION__, Lba, Offset, *NumBytes, Buffer));
+
+ TargetOffsetinBytes = GET_BLOCK_OFFSET (Lba) + (UINTN)(Offset);
+
+ if (TargetOffsetinBytes & Mask) {
+ // Write only as much as necessary, so pick the lower of the two numbers
+ // and call it Intermediate bytes to write to make alignment proper
+ if (BufferSizeInBytes < (sizeof(FLASH_DATA) - (TargetOffsetinBytes & Mask))) {
+ IntBytes = BufferSizeInBytes;
+ }
+ else {
+ IntBytes = sizeof(FLASH_DATA) - (TargetOffsetinBytes & Mask);
+ }
+
+ // Read the first few to get Read buffer aligned
+ NorFlashPlatformRead (Instance, Lba, (TargetOffsetinBytes & ~Mask) -
+ GET_BLOCK_OFFSET (Lba), sizeof(TempWrite), (UINT8*)&TempWrite);
+
+ CopyTo = (UINT8*)&TempWrite;
+ CopyTo += (TargetOffsetinBytes & Mask);
+ CopyFrom = (UINT8*)Buffer;
+
+ InternalMemCopyMem (CopyTo, CopyFrom, IntBytes);
+
+ Status = NorFlashPlatformWriteWordAlignedAddressBuffer (Instance,
+ (UINTN)((TargetOffsetinBytes & ~Mask)/sizeof(FLASH_DATA)),
+ 1, &TempWrite);
+ if (EFI_ERROR (Status)) {
+ DEBUG((DEBUG_ERROR, "%a : Failed to Write @TargetOffset 0x%x (0x%x)\n",
+ __FUNCTION__, TargetOffsetinBytes, Status));
+ goto EXIT;
+ }
+
+ TargetOffsetinBytes += IntBytes; /* adjust pointers and counter */
+ BufferSizeInBytes -= IntBytes;
+ Buffer += IntBytes;
+
+ if (BufferSizeInBytes == 0) {
+ goto EXIT;
+ }
+ }
+
+ // Write the bytes to CFI width aligned address.
+ // Note we can Write number of bytes=CFI width in one operation
+ WordsToWrite = BufferSizeInBytes/sizeof(FLASH_DATA);
+ pSrcBuffer = (FLASH_DATA*)Buffer;
+
+ Status = NorFlashPlatformWriteWordAlignedAddressBuffer (
+ Instance,
+ (UINTN)(TargetOffsetinBytes/sizeof(FLASH_DATA)),
+ WordsToWrite,
+ pSrcBuffer);
+ if (EFI_ERROR(Status)) {
+ DEBUG((DEBUG_ERROR, "%a : Failed to Write @ TargetOffset 0x%x (0x%x)\n",
+ __FUNCTION__, TargetOffsetinBytes, Status));
+ goto EXIT;
+ }
+
+ BufferSizeInBytes -= (WordsToWrite*sizeof(FLASH_DATA));
+ Buffer += (WordsToWrite*sizeof(FLASH_DATA));
+ TargetOffsetinBytes += (WordsToWrite*sizeof(FLASH_DATA));
+
+ if (BufferSizeInBytes == 0) {
+ goto EXIT;
+ }
+
+ // Now Write bytes that are remaining and are less than CFI width.
+ // Read the first few to get Read buffer aligned
+ NorFlashPlatformRead (Instance,
+ Lba,
+ TargetOffsetinBytes - GET_BLOCK_OFFSET (Lba),
+ sizeof(TempWrite),
+ (UINT8*)&TempWrite);
+
+ CopyFrom = (UINT8*)Buffer;
+ CopyTo = (UINT8*)&TempWrite;
+
+ InternalMemCopyMem (CopyTo, CopyFrom, BufferSizeInBytes);
+
+ Status = NorFlashPlatformWriteWordAlignedAddressBuffer (Instance,
+ (UINTN)(TargetOffsetinBytes/sizeof(FLASH_DATA)),
+ 1,
+ &TempWrite);
+ if (EFI_ERROR(Status)) {
+ DEBUG((DEBUG_ERROR, "%a: Failed to Write @TargetOffset 0x%x Status=%d\n",
+ __FUNCTION__, TargetOffsetinBytes, Status));
+ goto EXIT;
+ }
+
+EXIT:
+ // Put device back into Read Array mode (via Reset)
+ NorFlashPlatformReset (Instance->DeviceBaseAddress);
+ return (Status);
+}
+
+EFI_STATUS
+NorFlashPlatformRead (
+ IN NOR_FLASH_INSTANCE *Instance,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN UINTN BufferSizeInBytes,
+ OUT UINT8 *Buffer
+ )
+{
+ UINTN IntBytes;
+ UINTN Mask;
+ FLASH_DATA TempRead;
+ UINT8 *CopyFrom, *CopyTo;
+ UINTN TargetOffsetinBytes;
+ FLASH_DATA *pReadData;
+ UINTN BlockSize;
+
+ IntBytes = BufferSizeInBytes; // Intermediate Bytes needed to copy for alignment
+ Mask = sizeof(FLASH_DATA) - 1;
+ TempRead = 0;
+ TargetOffsetinBytes = (UINTN)(GET_BLOCK_OFFSET (Lba) + Offset);
+ BlockSize = Instance->Media.BlockSize;
+
+ DEBUG ((DEBUG_BLKIO, "%a(Parameters: Lba=%ld, Offset=0x%x,"
+ " BufferSizeInBytes=0x%x, Buffer @ 0x%p)\n",
+ __FUNCTION__, Lba, Offset, BufferSizeInBytes, Buffer));
+
+ // The buffer must be valid
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Return if we have not any byte to read
+ if (BufferSizeInBytes == 0) {
+ return EFI_SUCCESS;
+ }
+
+ if (((Lba * BlockSize) + BufferSizeInBytes) > Instance->Size) {
+ DEBUG ((DEBUG_ERROR, "%a : Read will exceed device size.\n", __FUNCTION__));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Put device back into Read Array mode (via Reset)
+ NorFlashPlatformReset (Instance->DeviceBaseAddress);
+
+ // First Read bytes to make buffer aligned to CFI width
+ if (TargetOffsetinBytes & Mask) {
+ // Read only as much as necessary, so pick the lower of the two numbers
+ if (BufferSizeInBytes < (sizeof(FLASH_DATA) - (TargetOffsetinBytes & Mask))) {
+ IntBytes = BufferSizeInBytes;
+ }
+ else {
+ IntBytes = sizeof(FLASH_DATA) - (TargetOffsetinBytes & Mask);
+ }
+
+ // Read the first few to get Read buffer aligned
+ TempRead = FLASH_READ_DATA (CREATE_NOR_ADDRESS (
+ Instance->DeviceBaseAddress,
+ CREATE_BYTE_OFFSET ((TargetOffsetinBytes & ~Mask)/sizeof(FLASH_DATA))));
+
+ CopyFrom = (UINT8*)&TempRead;
+ CopyFrom += (TargetOffsetinBytes & Mask);
+ CopyTo = (UINT8*)Buffer;
+
+ InternalMemCopyMem (CopyTo, CopyFrom, IntBytes);
+
+ TargetOffsetinBytes += IntBytes; // adjust pointers and counter
+ BufferSizeInBytes -= IntBytes;
+ Buffer += IntBytes;
+ if (BufferSizeInBytes == 0) {
+ return EFI_SUCCESS;
+ }
+ }
+
+ pReadData = (FLASH_DATA*)Buffer;
+
+ // Readout the bytes from CFI width aligned address.
+ // Note we can read number of bytes=CFI width in one operation
+ while (BufferSizeInBytes >= sizeof(FLASH_DATA)) {
+ *pReadData = FLASH_READ_DATA (CREATE_NOR_ADDRESS (
+ Instance->DeviceBaseAddress,
+ CREATE_BYTE_OFFSET (TargetOffsetinBytes/sizeof(FLASH_DATA))));
+ pReadData += 1;
+ BufferSizeInBytes -= sizeof(FLASH_DATA);
+ TargetOffsetinBytes += sizeof(FLASH_DATA);
+ }
+ if (BufferSizeInBytes == 0) {
+ return EFI_SUCCESS;
+ }
+
+ // Now read bytes that are remaining and are less than CFI width.
+ CopyTo = (UINT8*)pReadData;
+ // Read the first few to get Read buffer aligned
+ TempRead = FLASH_READ_DATA (CREATE_NOR_ADDRESS (
+ Instance->DeviceBaseAddress,
+ CREATE_BYTE_OFFSET (TargetOffsetinBytes/sizeof(FLASH_DATA))));
+ CopyFrom = (UINT8*)&TempRead;
+
+ InternalMemCopyMem (CopyTo, CopyFrom, BufferSizeInBytes);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+NorFlashPlatformReset (
+ IN UINTN DeviceBaseAddress
+ )
+{
+ SEND_NOR_COMMAND (DeviceBaseAddress, CMD_UNLOCK_1_ADDR,
+ CMD_RESET_FIRST);
+
+ SEND_NOR_COMMAND (DeviceBaseAddress, CMD_UNLOCK_2_ADDR,
+ CMD_RESET_SECOND);
+
+ SEND_NOR_COMMAND (DeviceBaseAddress, 0, CMD_RESET);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+NorFlashPlatformGetDevices (
+ OUT NorFlashDescription **NorFlashDevices,
+ OUT UINT32 *Count
+ )
+{
+ if ((NorFlashDevices == NULL) || (Count == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Get the number of NOR flash devices supported
+ *NorFlashDevices = mNorFlashDevices;
+ *Count = NOR_FLASH_DEVICE_COUNT;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+NorFlashPlatformFlashGetAttributes (
+ OUT NorFlashDescription *NorFlashDevices,
+ IN UINT32 Count
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Index;
+
+ if ((NorFlashDevices == NULL) || (Count == 0)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Check the attributes of the NOR flash slave we are connected to.
+ // Currently we support only CFI flash devices. Bail-out otherwise.
+ Status = CfiNorFlashFlashGetAttributes (NorFlashDevices, Count);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ // Limit the Size of Nor Flash that can be programmed
+ for (Index = 0; Index < Count; Index++) {
+ NorFlashDevices[Index].RegionBaseAddress = PcdGet64 (PcdFlashReservedRegionBase64);
+ NorFlashDevices[Index].Size -= (NorFlashDevices[Index].RegionBaseAddress -
+ NorFlashDevices[Index].DeviceBaseAddress);
+ if((NorFlashDevices[Index].RegionBaseAddress - NorFlashDevices[Index].DeviceBaseAddress) %
+ NorFlashDevices[Index].BlockSize) {
+ DEBUG ((DEBUG_ERROR, "%a : Reserved Region(0x%p) doesn't start "
+ "from block boundry(0x%08x)\n", __FUNCTION__,
+ (UINTN)NorFlashDevices[Index].RegionBaseAddress,
+ (UINT32)NorFlashDevices[Index].BlockSize));
+ return EFI_DEVICE_ERROR;
+ }
+ }
+ return Status;
+}
diff --git a/Platform/NXP/Library/NorFlashLib/NorFlashLib.inf b/Platform/NXP/Library/NorFlashLib/NorFlashLib.inf
new file mode 100644
index 0000000..14ca0ab
--- /dev/null
+++ b/Platform/NXP/Library/NorFlashLib/NorFlashLib.inf
@@ -0,0 +1,42 @@
+#/** @NorFlashLib.inf
+#
+# Component description file for NorFlashLib module
+#
+# Copyright 2017 NXP
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x0001001A
+ BASE_NAME = NorFlashLib
+ FILE_GUID = f3176a49-dde1-450d-a909-8580c03b9ba8
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = NorFlashLib
+
+[Sources.common]
+ NorFlashLib.c
+ IfcNorFlashLib.c
+ CfiNorFlashLib.c
+
+[LibraryClasses]
+ ArmLib
+ IfcFlashLib
+ TimerLib
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ MdePkg/MdePkg.dec
+ Platform/NXP/NxpQoriqLs.dec
+
+[Pcd.common]
+ gNxpQoriqLsTokenSpaceGuid.PcdFlashDeviceBase64
+ gNxpQoriqLsTokenSpaceGuid.PcdFlashReservedRegionBase64
--
1.9.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 3/4] Platform/NXP : Add Support for NOR Flash driver
2017-12-01 4:10 [PATCH 0/4] Platform/NXP-Adding NXP NOR IP Vabhav
2017-12-01 4:10 ` [PATCH 1/4] Platform/NXP : Add Integrated flash controller library support Vabhav
2017-12-01 4:10 ` [PATCH 2/4] Platform/NXP : Add Support for NOR flash Library Vabhav
@ 2017-12-01 4:10 ` Vabhav
2017-12-01 4:10 ` [PATCH 4/4] Compilation:Modify dsc, fdf files and add inc file Vabhav
3 siblings, 0 replies; 5+ messages in thread
From: Vabhav @ 2017-12-01 4:10 UTC (permalink / raw)
To: ard.biesheuvel, leif.lindholm, michael.d.kinney, edk2-devel
This patch adds support for NOR flash Driver
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Vabhav <vabhav.sharma@nxp.com>
---
.../NXP/Drivers/NorFlashDxe/NorFlashBlockIoDxe.c | 254 +++++++
Platform/NXP/Drivers/NorFlashDxe/NorFlashDxe.c | 446 ++++++++++++
Platform/NXP/Drivers/NorFlashDxe/NorFlashDxe.inf | 65 ++
Platform/NXP/Drivers/NorFlashDxe/NorFlashFvbDxe.c | 807 +++++++++++++++++++++
Platform/NXP/Include/Library/NorFlash.h | 222 ++++++
5 files changed, 1794 insertions(+)
create mode 100644 Platform/NXP/Drivers/NorFlashDxe/NorFlashBlockIoDxe.c
create mode 100644 Platform/NXP/Drivers/NorFlashDxe/NorFlashDxe.c
create mode 100755 Platform/NXP/Drivers/NorFlashDxe/NorFlashDxe.inf
create mode 100644 Platform/NXP/Drivers/NorFlashDxe/NorFlashFvbDxe.c
create mode 100644 Platform/NXP/Include/Library/NorFlash.h
diff --git a/Platform/NXP/Drivers/NorFlashDxe/NorFlashBlockIoDxe.c b/Platform/NXP/Drivers/NorFlashDxe/NorFlashBlockIoDxe.c
new file mode 100644
index 0000000..5f3c2ad
--- /dev/null
+++ b/Platform/NXP/Drivers/NorFlashDxe/NorFlashBlockIoDxe.c
@@ -0,0 +1,254 @@
+/** @NorFlashBlockIoDxe.c
+
+ Based on NorFlash implementation available in ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashBlockIoDxe.c
+
+ Copyright (c) 2011 - 2014, ARM Ltd. All rights reserved.
+ Copyright 2017 NXP
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Library/DebugLib.h>
+#include <Library/NorFlash.h>
+
+//
+// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.Reset
+//
+EFI_STATUS
+EFIAPI
+NorFlashBlockIoReset (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ )
+{
+ NOR_FLASH_INSTANCE *Instance;
+
+ Instance = INSTANCE_FROM_BLKIO_THIS(This);
+
+ DEBUG ((DEBUG_INFO, "NorFlashBlockIoReset(MediaId=0x%x)\n",
+ This->Media->MediaId));
+
+ return NorFlashPlatformReset (Instance->DeviceBaseAddress);
+}
+
+//
+// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.ReadBlocks
+//
+EFI_STATUS
+EFIAPI
+NorFlashBlockIoReadBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSizeInBytes,
+ OUT VOID *Buffer
+ )
+{
+ NOR_FLASH_INSTANCE *Instance;
+ EFI_STATUS Status;
+ EFI_BLOCK_IO_MEDIA *Media;
+ UINTN NumBlocks;
+ UINT8 *pReadBuffer;
+ UINTN BlockCount;
+ UINTN BlockSizeInBytes;
+ EFI_LBA CurrentBlock;
+
+ Status = EFI_SUCCESS;
+
+ if ((This == NULL) || (Buffer == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Instance = INSTANCE_FROM_BLKIO_THIS(This);
+ Media = This->Media;
+
+ if (Media == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a : Media is NULL\n", __FUNCTION__));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ NumBlocks = ((UINTN)BufferSizeInBytes) / Instance->Media.BlockSize ;
+
+ DEBUG ((DEBUG_BLKIO, "%a : (MediaId=0x%x, Lba=%ld, "
+ "BufferSize=0x%x bytes (%d kB)"
+ ", BufferPtr @ 0x%p)\n",
+ __FUNCTION__,MediaId, Lba,
+ BufferSizeInBytes, Buffer));
+
+ if (!Media) {
+ Status = EFI_INVALID_PARAMETER;
+ }
+ else if (!Media->MediaPresent) {
+ Status = EFI_NO_MEDIA;
+ }
+ else if (Media->MediaId != MediaId) {
+ Status = EFI_MEDIA_CHANGED;
+ }
+ else if ((Media->IoAlign >= 2) &&
+ (((UINTN)Buffer & (Media->IoAlign - 1)) != 0)) {
+ Status = EFI_INVALID_PARAMETER;
+ }
+ else if (BufferSizeInBytes == 0) {
+ // Return if we have not any byte to read
+ Status = EFI_SUCCESS;
+ }
+ else if ((BufferSizeInBytes % Media->BlockSize) != 0) {
+ // The size of the buffer must be a multiple of the block size
+ DEBUG((DEBUG_ERROR, "%a : BlockSize in bytes = 0x%x\n",__FUNCTION__,
+ BufferSizeInBytes));
+ Status = EFI_INVALID_PARAMETER;
+ } else if ((Lba + NumBlocks - 1) > Media->LastBlock) {
+ // All blocks must be within the device
+ DEBUG((DEBUG_ERROR, "%a : Read will exceed last block %d, %d, %d \n",
+ __FUNCTION__, Lba, NumBlocks, Media->LastBlock));
+ Status = EFI_INVALID_PARAMETER;
+ } else {
+ BlockSizeInBytes = Instance->Media.BlockSize;
+
+ /* Because the target *Buffer is a pointer to VOID,
+ * we must put all the data into a pointer
+ * to a proper data type, so use *pReadBuffer */
+ pReadBuffer = (UINT8 *)Buffer;
+
+ CurrentBlock = Lba;
+ // Read data block by Block
+ for (BlockCount = 0; BlockCount < NumBlocks; BlockCount++, CurrentBlock++,
+ pReadBuffer = pReadBuffer + BlockSizeInBytes) {
+ DEBUG((DEBUG_BLKIO, "%a: Reading block #%d\n",
+ __FUNCTION__,(UINTN)CurrentBlock));
+
+ Status = NorFlashPlatformRead (Instance, CurrentBlock, (UINTN)0 ,
+ BlockSizeInBytes,pReadBuffer);
+ if (EFI_ERROR(Status)) {
+ break;
+ }
+ }
+ }
+ DEBUG((DEBUG_BLKIO,"%a: Exit Status = \"%r\".\n",__FUNCTION__,Status));
+
+ return Status;
+}
+
+//
+// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.WriteBlocks
+//
+EFI_STATUS
+EFIAPI
+NorFlashBlockIoWriteBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSizeInBytes,
+ IN VOID *Buffer
+ )
+{
+ NOR_FLASH_INSTANCE *Instance;
+ EFI_STATUS Status;
+ EFI_BLOCK_IO_MEDIA *Media;
+ UINTN NumBlocks;
+ EFI_LBA CurrentBlock;
+ UINTN BlockSizeInBytes;
+ UINT32 BlockCount;
+ UINTN SectorAddress;
+ UINT8 *pWriteBuffer;
+
+ Status = EFI_SUCCESS;
+
+ if ((This == NULL) || (Buffer == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Instance = INSTANCE_FROM_BLKIO_THIS(This);
+ Media = This->Media;
+
+ if (Media == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a : Media is NULL\n", __FUNCTION__));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ NumBlocks = ((UINTN)BufferSizeInBytes) / Instance->Media.BlockSize ;
+
+ DEBUG ((DEBUG_BLKIO, "%a : (MediaId=0x%x, Lba=%ld, BufferSize=0x%x "
+ "bytes (%d kB) BufferPtr @ 0x%08x)\n",
+ __FUNCTION__,MediaId, Lba,BufferSizeInBytes, Buffer));
+
+ if (!Media->MediaPresent) {
+ Status = EFI_NO_MEDIA;
+ }
+ else if (Media->MediaId != MediaId) {
+ Status = EFI_MEDIA_CHANGED;
+ }
+ else if (Media->ReadOnly) {
+ Status = EFI_WRITE_PROTECTED;
+ }
+ else if (BufferSizeInBytes == 0) {
+ Status = EFI_BAD_BUFFER_SIZE;
+ }
+ else if ((BufferSizeInBytes % Media->BlockSize) != 0) {
+ // The size of the buffer must be a multiple of the block size
+ DEBUG((DEBUG_ERROR, "%a : BlockSize in bytes = 0x%x\n",__FUNCTION__,
+ BufferSizeInBytes));
+ Status = EFI_INVALID_PARAMETER;
+ } else if ((Lba + NumBlocks - 1) > Media->LastBlock) {
+ // All blocks must be within the device
+ DEBUG((DEBUG_ERROR, "%a: Write will exceed last block %d, %d, %d \n",
+ __FUNCTION__,Lba, NumBlocks, Media->LastBlock));
+ Status = EFI_INVALID_PARAMETER;
+ } else {
+ BlockSizeInBytes = Instance->Media.BlockSize;
+
+ pWriteBuffer = (UINT8 *)Buffer;
+
+ CurrentBlock = Lba;
+ // Program data block by Block
+ for (BlockCount = 0; BlockCount < NumBlocks;
+ BlockCount++, CurrentBlock++,
+ pWriteBuffer = (pWriteBuffer + BlockSizeInBytes)) {
+ DEBUG((DEBUG_BLKIO, "%a: Writing block #%d\n",
+ __FUNCTION__,(UINTN)CurrentBlock));
+ // Erase the Block(Sector) to be written to
+ SectorAddress = GET_NOR_BLOCK_ADDRESS (
+ Instance->RegionBaseAddress,
+ CurrentBlock,
+ Instance->Media.BlockSize
+ );
+ Status = NorFlashPlatformEraseSector (Instance, (UINTN)SectorAddress);
+ if (EFI_ERROR(Status)) {
+ DEBUG((DEBUG_ERROR, "%a: Failed to erase Target 0x%x (0x%x) \n",
+ __FUNCTION__,SectorAddress, Status));
+ break;
+ }
+ // Program Block(Sector) to be written to
+ Status = NorFlashWrite (Instance, CurrentBlock, (UINTN)0,
+ &BlockSizeInBytes, pWriteBuffer);
+ if (EFI_ERROR(Status)) {
+ break;
+ }
+ }
+ }
+ DEBUG((DEBUG_BLKIO, "%a: Exit Status = \"%r\".\n",__FUNCTION__,Status));
+ return Status;
+}
+
+//
+// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.FlushBlocks
+//
+EFI_STATUS
+EFIAPI
+NorFlashBlockIoFlushBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This
+ )
+{
+
+ DEBUG ((DEBUG_BLKIO, "%a NOT IMPLEMENTED (not required)\n", __FUNCTION__));
+
+ // Nothing to do so just return without error
+ return EFI_SUCCESS;
+}
diff --git a/Platform/NXP/Drivers/NorFlashDxe/NorFlashDxe.c b/Platform/NXP/Drivers/NorFlashDxe/NorFlashDxe.c
new file mode 100644
index 0000000..1d553fc
--- /dev/null
+++ b/Platform/NXP/Drivers/NorFlashDxe/NorFlashDxe.c
@@ -0,0 +1,446 @@
+/** @file NorFlashDxe.c
+
+ Based on NorFlash implementation available in ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.c
+
+ Copyright (c) 2011 - 2014, ARM Ltd. All rights reserved.
+ Copyright 2017 NXP
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Bitops.h>
+#include <Library/NorFlash.h>
+#include <Library/NorFlashLib.h>
+#include <Library/UefiRuntimeLib.h>
+
+STATIC EFI_EVENT mNorFlashVirtualAddrChangeEvent;
+
+//
+// Global variable declarations
+//
+NOR_FLASH_INSTANCE **mNorFlashInstances;
+UINT32 mNorFlashDeviceCount;
+
+NOR_FLASH_INSTANCE mNorFlashInstanceTemplate = {
+ .Signature = NOR_FLASH_SIGNATURE,
+ .Initialized = FALSE,
+ .Initialize = NULL,
+ .StartLba = 0,
+ .BlockIoProtocol = {
+ .Revision = EFI_BLOCK_IO_PROTOCOL_REVISION2,
+ .Reset = NorFlashBlockIoReset,
+ .ReadBlocks = NorFlashBlockIoReadBlocks,
+ .WriteBlocks = NorFlashBlockIoWriteBlocks,
+ .FlushBlocks = NorFlashBlockIoFlushBlocks,
+ },
+
+ .Media = {
+ .RemovableMedia = FALSE,
+ .MediaPresent = TRUE,
+ .LogicalPartition = FALSE,
+ .ReadOnly = FALSE,
+ .WriteCaching = FALSE,
+ .IoAlign = 4,
+ .LowestAlignedLba = 0,
+ .LogicalBlocksPerPhysicalBlock = 1,
+ },
+
+ .FvbProtocol = {
+ .GetAttributes = FvbGetAttributes,
+ .SetAttributes = FvbSetAttributes,
+ .GetPhysicalAddress = FvbGetPhysicalAddress,
+ .GetBlockSize = FvbGetBlockSize,
+ .Read = FvbRead,
+ .Write = FvbWrite,
+ .EraseBlocks = FvbEraseBlocks,
+ .ParentHandle = NULL,
+ },
+ .ShadowBuffer = NULL,
+ .DevicePath = {
+ .Vendor = {
+ .Header = {
+ .Type = HARDWARE_DEVICE_PATH,
+ .SubType = HW_VENDOR_DP,
+ .Length = {(UINT8)sizeof(VENDOR_DEVICE_PATH),
+ (UINT8)((sizeof(VENDOR_DEVICE_PATH)) >> 8) }
+ },
+ .Guid = EFI_CALLER_ID_GUID, // GUID ... NEED TO BE FILLED
+ },
+ .End = {
+ .Type = END_DEVICE_PATH_TYPE,
+ .SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ .Length = { sizeof (EFI_DEVICE_PATH_PROTOCOL), 0 }
+ }
+ }
+};
+
+EFI_STATUS
+NorFlashCreateInstance (
+ IN UINTN NorFlashDeviceBase,
+ IN UINTN NorFlashRegionBase,
+ IN UINTN NorFlashSize,
+ IN UINT32 MediaId,
+ IN UINT32 BlockSize,
+ IN BOOLEAN SupportFvb,
+ OUT NOR_FLASH_INSTANCE** NorFlashInstance
+ )
+{
+ EFI_STATUS Status;
+ NOR_FLASH_INSTANCE* Instance;
+
+ ASSERT(NorFlashInstance != NULL);
+
+ Instance = AllocateRuntimeCopyPool(sizeof(NOR_FLASH_INSTANCE),
+ &mNorFlashInstanceTemplate);
+ if (Instance == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Instance->DeviceBaseAddress = NorFlashDeviceBase;
+ Instance->RegionBaseAddress = NorFlashRegionBase;
+ Instance->Size = NorFlashSize;
+
+ Instance->BlockIoProtocol.Media = &Instance->Media;
+ Instance->Media.MediaId = MediaId;
+ Instance->Media.BlockSize = BlockSize;
+ Instance->Media.LastBlock = (NorFlashSize / BlockSize)-1;
+
+ Instance->ShadowBuffer = AllocateRuntimePool (BlockSize);
+ if (Instance->ShadowBuffer == NULL) {
+ FreePool (Instance);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if (SupportFvb) {
+ Instance->SupportFvb = TRUE;
+ Instance->Initialize = NorFlashFvbInitialize;
+
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Instance->Handle,
+ &gEfiDevicePathProtocolGuid, &Instance->DevicePath,
+ &gEfiBlockIoProtocolGuid, &Instance->BlockIoProtocol,
+ &gEfiFirmwareVolumeBlockProtocolGuid, &Instance->FvbProtocol,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (Instance->ShadowBuffer);
+ FreePool (Instance);
+ return Status;
+ }
+ } else {
+ Instance->Initialized = TRUE;
+
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Instance->Handle,
+ &gEfiDevicePathProtocolGuid, &Instance->DevicePath,
+ &gEfiBlockIoProtocolGuid, &Instance->BlockIoProtocol,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (Instance->ShadowBuffer);
+ FreePool (Instance);
+ return Status;
+ }
+ }
+
+ *NorFlashInstance = Instance;
+
+ return Status;
+}
+
+/*
+ Write a full or portion of a block.
+ It must not span block boundaries; that is,
+ Offset + NumBytes <= Instance->Media.BlockSize.
+ */
+EFI_STATUS
+NorFlashWrite (
+ IN NOR_FLASH_INSTANCE *Instance,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN OUT UINTN *NumBytes,
+ IN UINT8 *Buffer
+)
+{
+ EFI_STATUS Status;
+ UINTN BlockSize;
+ BOOLEAN DoErase;
+ VOID *Source;
+ UINTN SectorAddress;
+
+ Status = EFI_SUCCESS;
+ Source = NULL;
+
+ DEBUG ((DEBUG_BLKIO, "%a(Parameters: Lba=%ld, Offset=0x%x, NumBytes=0x%x, "
+ "Buffer @ 0x%08x)\n", __FUNCTION__,
+ Lba, Offset, *NumBytes, Buffer));
+
+ // The buffer must be valid
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Detect WriteDisabled state
+ if (Instance->Media.ReadOnly == TRUE) {
+ DEBUG ((DEBUG_ERROR, "NorFlashWrite: 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 = Instance->Media.BlockSize;
+
+ // We must have some bytes to write
+ if ((*NumBytes == 0) || (*NumBytes > BlockSize)) {
+ DEBUG ((DEBUG_ERROR, "NorFlashWrite: ERROR - EFI_BAD_BUFFER_SIZE: "
+ "(Offset=0x%x + NumBytes=0x%x) > BlockSize=0x%x\n", \
+ Offset, *NumBytes, BlockSize ));
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ if (((Lba * BlockSize) + Offset + *NumBytes) > Instance->Size) {
+ DEBUG ((DEBUG_ERROR, "%a: ERROR - Write will exceed device size.\n",
+ __FUNCTION__));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Check we did get some memory. Buffer is BlockSize.
+ if (Instance->ShadowBuffer == NULL) {
+ DEBUG ((DEBUG_ERROR, "FvbWrite: ERROR - Buffer not ready\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ SectorAddress = GET_NOR_BLOCK_ADDRESS (
+ Instance->RegionBaseAddress,
+ Lba,
+ Instance->Media.BlockSize
+ );
+
+ // Pick 128bytes as a good start for word operations as opposed to erasing the
+ // block and writing the data regardless if an erase is really needed.
+ // It looks like most individual NV variable writes are smaller than 128bytes.
+ if (*NumBytes <= 128) {
+ Source = Instance->ShadowBuffer;
+ //First Read the data into shadow buffer from location where data is to be written
+ Status = NorFlashPlatformRead (
+ Instance,
+ Lba,
+ Offset,
+ *NumBytes,
+ Source
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG((DEBUG_ERROR, "%a: ERROR - Failed to "
+ "Read @ %p Status=%d\n", __FUNCTION__,
+ Offset + SectorAddress, Status));
+ return Status;
+ }
+ // Check to see if we need to erase before programming the data into NorFlash.
+ // If the destination bits are only changing from 1s to 0s we can
+ // just write. After a block is erased all bits in the block is set to 1.
+ // If any byte requires us to erase we just give up and rewrite all of it.
+ DoErase = TestBitSetClear(Source, Buffer, *NumBytes, TRUE);
+
+ // if we got here then write all the data. Otherwise do the
+ // Erase-Write cycle.
+ if (!DoErase) {
+ Status = NorFlashPlatformWriteBuffer (
+ Instance,
+ Lba,
+ Offset,
+ NumBytes,
+ Buffer
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG((DEBUG_ERROR, "%a: ERROR - Failed to "
+ "Write @ %p Status=%d\n", __FUNCTION__,
+ Offset + SectorAddress, Status));
+ return Status;
+ }
+ return EFI_SUCCESS;
+ }
+ }
+
+ // If we are not going to write full block, read block and then update bytes in it
+ if (*NumBytes != BlockSize) {
+ // Read NorFlash Flash data into shadow buffer
+ Status = NorFlashBlockIoReadBlocks (
+ &(Instance->BlockIoProtocol),
+ Instance->Media.MediaId,
+ Lba,
+ BlockSize,
+ Instance->ShadowBuffer
+ );
+ 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)Instance->ShadowBuffer + Offset), Buffer, *NumBytes);
+ }
+ //Erase Block
+ Status = NorFlashPlatformEraseSector (Instance, SectorAddress);
+ if (EFI_ERROR (Status)) {
+ // Return one of the pre-approved error statuses
+ return EFI_DEVICE_ERROR;
+ }
+ if (*NumBytes != BlockSize) {
+ // Write the modified shadow buffer back to the NorFlash
+ Status = NorFlashPlatformWriteBuffer (
+ Instance,
+ Lba,
+ 0,
+ &BlockSize,
+ Instance->ShadowBuffer
+ );
+ } else {
+ // Write the Buffer to an entire block in NorFlash
+ Status = NorFlashPlatformWriteBuffer (
+ Instance,
+ Lba,
+ 0,
+ &BlockSize,
+ Buffer
+ );
+ }
+ if (EFI_ERROR (Status)) {
+ // Return one of the pre-approved error statuses
+ return EFI_DEVICE_ERROR;
+ }
+
+ 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
+**/
+VOID
+EFIAPI
+NorFlashVirtualNotifyEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ UINTN Index;
+
+ for (Index = 0; Index < mNorFlashDeviceCount; Index++) {
+ EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->DeviceBaseAddress);
+ EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->RegionBaseAddress);
+
+ // Convert BlockIo protocol
+ EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->BlockIoProtocol.FlushBlocks);
+ EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->BlockIoProtocol.ReadBlocks);
+ EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->BlockIoProtocol.Reset);
+ EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->BlockIoProtocol.WriteBlocks);
+
+ // Convert Fvb
+ EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->FvbProtocol.EraseBlocks);
+ EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->FvbProtocol.GetAttributes);
+ EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->FvbProtocol.GetBlockSize);
+ EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->FvbProtocol.GetPhysicalAddress);
+ EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->FvbProtocol.Read);
+ EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->FvbProtocol.SetAttributes);
+ EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->FvbProtocol.Write);
+ if (mNorFlashInstances[Index]->ShadowBuffer != NULL) {
+ EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->ShadowBuffer);
+ }
+ }
+
+ return;
+}
+
+EFI_STATUS
+EFIAPI
+NorFlashInitialise (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Index;
+ NorFlashDescription* NorFlashDevices;
+ BOOLEAN ContainVariableStorage;
+
+ ContainVariableStorage = 0;
+
+ IfcNorInit();
+
+ Status = NorFlashPlatformGetDevices (&NorFlashDevices, &mNorFlashDeviceCount);
+ if (EFI_ERROR(Status)) {
+ DEBUG((DEBUG_ERROR,"%a : Failed to get Nor devices (0x%x)\n",
+ __FUNCTION__, Status));
+ return Status;
+ }
+
+ Status = NorFlashPlatformFlashGetAttributes (NorFlashDevices,
+ mNorFlashDeviceCount);
+ if (EFI_ERROR(Status)) {
+ DEBUG((DEBUG_ERROR,"%a : Failed to get NOR device attributes (0x%x)\n",
+ __FUNCTION__, Status));
+ ASSERT_EFI_ERROR (Status); /* System becomes unusable if NOR flash is not detected */
+ return Status;
+ }
+
+ mNorFlashInstances = AllocateRuntimePool (
+ sizeof(NOR_FLASH_INSTANCE*) * mNorFlashDeviceCount);
+ if (mNorFlashInstances == NULL) {
+ DEBUG((DEBUG_ERROR,"%a : Failed to allocate runtime memory \n"));
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ for (Index = 0; Index < mNorFlashDeviceCount; Index++) {
+ // Check if this NOR Flash device contain the variable storage region
+ ContainVariableStorage =
+ (NorFlashDevices[Index].RegionBaseAddress <= PcdGet64(PcdFlashNvStorageVariableBase64)) &&
+ (PcdGet64(PcdFlashNvStorageVariableBase64) + PcdGet32(PcdFlashNvStorageVariableSize) <=
+ NorFlashDevices[Index].RegionBaseAddress + NorFlashDevices[Index].Size);
+
+ Status = NorFlashCreateInstance (
+ NorFlashDevices[Index].DeviceBaseAddress,
+ NorFlashDevices[Index].RegionBaseAddress,
+ NorFlashDevices[Index].Size,
+ Index,
+ NorFlashDevices[Index].BlockSize,
+ ContainVariableStorage,
+ &mNorFlashInstances[Index]
+ );
+
+ if (EFI_ERROR(Status)) {
+ DEBUG((DEBUG_ERROR,"%a : Failed to create instance for "
+ "NorFlash[%d] (0x%x)\n",Index, Status));
+ }
+
+ }
+
+ //
+ // Register for the virtual address change event
+ //
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ NorFlashVirtualNotifyEvent,
+ NULL,
+ &gEfiEventVirtualAddressChangeGuid,
+ &mNorFlashVirtualAddrChangeEvent
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG((DEBUG_ERROR,"Failed to create VirtualAddressChange event 0x%x\n",
+ Status));
+ }
+
+ return Status;
+}
diff --git a/Platform/NXP/Drivers/NorFlashDxe/NorFlashDxe.inf b/Platform/NXP/Drivers/NorFlashDxe/NorFlashDxe.inf
new file mode 100755
index 0000000..2da8a51
--- /dev/null
+++ b/Platform/NXP/Drivers/NorFlashDxe/NorFlashDxe.inf
@@ -0,0 +1,65 @@
+#/** @file
+#
+# Component description file for NorFlashDxe module
+#
+# Copyright 2017 NXP
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x0001001A
+ BASE_NAME = NorFlashDxe
+ FILE_GUID = 616fe8d8-f4aa-42e0-a393-b332bdb2d3c1
+ MODULE_TYPE = DXE_RUNTIME_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = NorFlashInitialise
+
+[Sources.common]
+ NorFlashDxe.c
+ NorFlashFvbDxe.c
+ NorFlashBlockIoDxe.c
+
+[Packages]
+ ArmPlatformPkg/ArmPlatformPkg.dec
+ Platform/NXP/NxpQoriqLs.dec
+ MdeModulePkg/MdeModulePkg.dec
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ DxeServicesTableLib
+ HobLib
+ NorFlashLib
+ UefiDriverEntryPoint
+ UefiRuntimeLib
+
+[Guids]
+ gEfiSystemNvDataFvGuid
+ gEfiVariableGuid
+ gEfiAuthenticatedVariableGuid
+ gEfiEventVirtualAddressChangeGuid
+
+[Protocols]
+ gEfiBlockIoProtocolGuid
+ gEfiFirmwareVolumeBlockProtocolGuid
+
+[Pcd.common]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase64
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase64
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize
+
+[Depex]
+ #
+ # NorFlashDxe must be loaded before VariableRuntimeDxe in case empty flash needs populating with default values
+ #
+ BEFORE gVariableRuntimeDxeFileGuid
diff --git a/Platform/NXP/Drivers/NorFlashDxe/NorFlashFvbDxe.c b/Platform/NXP/Drivers/NorFlashDxe/NorFlashFvbDxe.c
new file mode 100644
index 0000000..e368464
--- /dev/null
+++ b/Platform/NXP/Drivers/NorFlashDxe/NorFlashFvbDxe.c
@@ -0,0 +1,807 @@
+/*@NorFlashFvbDxe.c
+
+ Based on NorFlash implementation available in ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashFvbDxe.c
+
+ Copyright (c) 2011 - 2014, ARM Ltd. All rights reserved.
+ Copyright 2017 NXP
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ --*/
+
+#include <Guid/VariableFormat.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/HobLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/NorFlash.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiRuntimeLib.h>
+
+STATIC EFI_EVENT mFvbVirtualAddrChangeEvent;
+STATIC UINTN mFlashNvStorageVariableBase;
+
+///
+/// The Firmware Volume Block Protocol is the low-level interface
+/// to a firmware volume. File-level access to a firmware volume
+/// should not be done using the Firmware Volume Block Protocol.
+/// Normal access to a firmware volume must use the Firmware
+/// Volume Protocol. Typically, only the file system driver that
+/// produces the Firmware Volume Protocol will bind to the
+/// Firmware Volume Block Protocol.
+///
+
+/**
+ Initialises the FV Header and Variable Store Header
+ to support variable operations.
+
+ @param[in] Ptr - Location to initialise the headers
+
+**/
+EFI_STATUS
+InitializeFvAndVariableStoreHeaders (
+ IN NOR_FLASH_INSTANCE *Instance
+ )
+{
+ EFI_STATUS Status;
+ VOID* Headers;
+ UINTN HeadersLength;
+ EFI_FIRMWARE_VOLUME_HEADER *FirmwareVolumeHeader;
+ VARIABLE_STORE_HEADER *VariableStoreHeader;
+
+ if (!Instance->Initialized && Instance->Initialize) {
+ Instance->Initialize (Instance);
+ }
+
+ HeadersLength = sizeof(EFI_FIRMWARE_VOLUME_HEADER) + sizeof(EFI_FV_BLOCK_MAP_ENTRY) + sizeof(VARIABLE_STORE_HEADER);
+ Headers = AllocateZeroPool(HeadersLength);
+ if (Headers == NULL) {
+ DEBUG((DEBUG_ERROR, "Memory allocation failed for Headers \n"));
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ // FirmwareVolumeHeader->FvLength is declared to have the Variable area AND the FTW working area AND the FTW Spare contiguous.
+ ASSERT(PcdGet64(PcdFlashNvStorageVariableBase64) + PcdGet32(PcdFlashNvStorageVariableSize) == PcdGet64(PcdFlashNvStorageFtwWorkingBase64));
+ ASSERT(PcdGet64(PcdFlashNvStorageFtwWorkingBase64) + PcdGet32(PcdFlashNvStorageFtwWorkingSize) == PcdGet64(PcdFlashNvStorageFtwSpareBase64));
+
+ // Check if the size of the area is at least one block size
+ ASSERT((PcdGet32(PcdFlashNvStorageVariableSize) > 0) && (PcdGet32(PcdFlashNvStorageVariableSize) / Instance->Media.BlockSize > 0));
+ ASSERT((PcdGet32(PcdFlashNvStorageFtwWorkingSize) > 0) && (PcdGet32(PcdFlashNvStorageFtwWorkingSize) / Instance->Media.BlockSize > 0));
+ ASSERT((PcdGet32(PcdFlashNvStorageFtwSpareSize) > 0) && (PcdGet32(PcdFlashNvStorageFtwSpareSize) / Instance->Media.BlockSize > 0));
+
+ // Ensure the Variable area Base Addresses are aligned on a block size boundaries
+ ASSERT(PcdGet64(PcdFlashNvStorageVariableBase64) % Instance->Media.BlockSize == 0);
+ ASSERT(PcdGet64(PcdFlashNvStorageFtwWorkingBase64) % Instance->Media.BlockSize == 0);
+ ASSERT(PcdGet64(PcdFlashNvStorageFtwSpareBase64) % Instance->Media.BlockSize == 0);
+
+ //
+ // EFI_FIRMWARE_VOLUME_HEADER
+ //
+ FirmwareVolumeHeader = (EFI_FIRMWARE_VOLUME_HEADER*)Headers;
+ CopyGuid (&FirmwareVolumeHeader->FileSystemGuid, &gEfiSystemNvDataFvGuid);
+ FirmwareVolumeHeader->FvLength =
+ PcdGet32(PcdFlashNvStorageVariableSize) +
+ PcdGet32(PcdFlashNvStorageFtwWorkingSize) +
+ PcdGet32(PcdFlashNvStorageFtwSpareSize);
+ FirmwareVolumeHeader->Signature = EFI_FVH_SIGNATURE;
+ FirmwareVolumeHeader->Attributes = (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')
+ EFI_FVB2_WRITE_STATUS | // Writes are currently enabled
+ EFI_FVB2_WRITE_ENABLED_CAP // Writes may be enabled
+ );
+ FirmwareVolumeHeader->HeaderLength = sizeof(EFI_FIRMWARE_VOLUME_HEADER) + sizeof(EFI_FV_BLOCK_MAP_ENTRY);
+ FirmwareVolumeHeader->Revision = EFI_FVH_REVISION;
+ //i.e. if blocks are 0-5 then last block = 5, total blocks = 6
+ FirmwareVolumeHeader->BlockMap[0].NumBlocks = Instance->Media.LastBlock + 1;
+ FirmwareVolumeHeader->BlockMap[0].Length = Instance->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 = PcdGet32(PcdFlashNvStorageVariableSize) - FirmwareVolumeHeader->HeaderLength;
+ VariableStoreHeader->Format = VARIABLE_STORE_FORMATTED;
+ VariableStoreHeader->State = VARIABLE_STORE_HEALTHY;
+
+ // Install the combined super-header in the NorFlash
+ Status = FvbWrite (&Instance->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.
+
+**/
+EFI_STATUS
+ValidateFvHeader (
+ IN NOR_FLASH_INSTANCE *Instance
+ )
+{
+ UINT16 Checksum;
+ EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
+ VARIABLE_STORE_HEADER *VariableStoreHeader;
+ UINTN VariableStoreLength;
+ UINTN FvLength;
+
+ FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER*)mFlashNvStorageVariableBase;
+
+ FvLength = PcdGet32(PcdFlashNvStorageVariableSize) + PcdGet32(PcdFlashNvStorageFtwWorkingSize) +
+ PcdGet32(PcdFlashNvStorageFtwSpareSize);
+
+ //
+ // Verify the header revision, header signature, length
+ // Length of FvBlock cannot be 2**64-1
+ // HeaderLength cannot be an odd number
+ //
+ if ( (FwVolHeader->Revision != EFI_FVH_REVISION)
+ || (FwVolHeader->Signature != EFI_FVH_SIGNATURE)
+ || (FwVolHeader->FvLength != FvLength)
+ )
+ {
+ DEBUG ((DEBUG_ERROR, "%a: No Firmware Volume header present\n",
+ __FUNCTION__));
+ return EFI_NOT_FOUND;
+ }
+
+ // Check the Firmware Volume Guid
+ if( CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiSystemNvDataFvGuid) == FALSE ) {
+ DEBUG ((DEBUG_ERROR, "%a: Firmware Volume Guid non-compatible\n",
+ __FUNCTION__));
+ return EFI_NOT_FOUND;
+ }
+
+ // Verify the header checksum
+ Checksum = CalculateSum16((UINT16*)FwVolHeader, FwVolHeader->HeaderLength);
+ if (Checksum != 0) {
+ DEBUG ((DEBUG_ERROR, "%a: FV checksum is invalid (Checksum:0x%X)\n",
+ __FUNCTION__, 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",
+ __FUNCTION__));
+ return EFI_NOT_FOUND;
+ }
+
+ VariableStoreLength = PcdGet32 (PcdFlashNvStorageVariableSize) - FwVolHeader->HeaderLength;
+ if (VariableStoreHeader->Size != VariableStoreLength) {
+ DEBUG ((DEBUG_ERROR, "%a: Variable Store Length does not match\n",
+ __FUNCTION__));
+ return EFI_NOT_FOUND;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ The GetAttributes() 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;
+ NOR_FLASH_INSTANCE *Instance;
+
+ Instance = 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 (Instance->Media.ReadOnly != TRUE) {
+
+ FlashFvbAttributes = FlashFvbAttributes |
+ EFI_FVB2_WRITE_STATUS | // Writes are currently enabled
+ EFI_FVB2_WRITE_ENABLED_CAP; // Writes may be enabled
+ }
+
+ *Attributes = FlashFvbAttributes;
+
+ DEBUG ((DEBUG_BLKIO, "FvbGetAttributes(0x%X)\n", *Attributes));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ The SetAttributes() function sets configurable firmware volume attributes
+ and returns the new settings of the firmware volume.
+
+
+ @param This Indicates the 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.
+ Type EFI_FVB_ATTRIBUTES_2 is defined in EFI_FIRMWARE_VOLUME_HEADER.
+
+ @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
+ )
+{
+ DEBUG ((DEBUG_BLKIO, "FvbSetAttributes(0x%X) is not supported\n",*Attributes));
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ The GetPhysicalAddress() function retrieves the base address of
+ a memory-mapped firmware volume. This function should be called
+ only for memory-mapped firmware volumes.
+
+ @param This Indicates the 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
+ )
+{
+ *Address = mFlashNvStorageVariableBase;
+ return EFI_SUCCESS;
+}
+
+/**
+ The GetBlockSize() function retrieves the size of the requested
+ block. It also returns the number of additional blocks with
+ the identical size. The GetBlockSize() function is used to
+ retrieve the block map (see EFI_FIRMWARE_VOLUME_HEADER).
+
+
+ @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
+
+ @param Lba Indicates the block for which to return the size.
+
+ @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;
+ NOR_FLASH_INSTANCE *Instance;
+
+ Instance = INSTANCE_FROM_FVB_THIS(This);
+
+ DEBUG ((DEBUG_BLKIO, "FvbGetBlockSize(Lba=%ld, BlockSize=0x%x, LastBlock=%ld)\n",
+ Lba, Instance->Media.BlockSize, Instance->Media.LastBlock));
+
+ if (Lba > Instance->Media.LastBlock) {
+ DEBUG ((DEBUG_ERROR, "%a : Parameter LBA %ld is beyond the last Lba (%ld)\n",
+ __FUNCTION__, Lba, Instance->Media.LastBlock));
+ Status = EFI_INVALID_PARAMETER;
+ } else {
+ // In this platform each NorFlash device has equal sized blocks.
+ *BlockSize = (UINTN) Instance->Media.BlockSize;
+ *NumberOfBlocks = (UINTN) (Instance->Media.LastBlock - Lba + 1);
+
+ DEBUG ((DEBUG_BLKIO, "%a : *BlockSize=0x%x, *NumberOfBlocks=0x%x.\n",
+ __FUNCTION__, *BlockSize, *NumberOfBlocks));
+
+ Status = EFI_SUCCESS;
+ }
+
+ return Status;
+}
+
+/**
+ Reads the specified number of bytes into a buffer from the specified block.
+
+ The Read() function reads the requested number of bytes from the
+ requested block and stores them in the provided buffer.
+ Implementations should be mindful that the firmware volume
+ might be in the ReadDisabled state. If it is in this state,
+ the Read() function must return the status code
+ EFI_ACCESS_DENIED without modifying the contents of the
+ buffer. The Read() function must also prevent spanning block
+ boundaries. If a read is requested that would span a block
+ boundary, the read must read up to the boundary but not
+ beyond. The output parameter NumBytes must be set to correctly
+ indicate the number of bytes actually read. The caller must be
+ aware that a read may be partially completed.
+
+ @param This Indicates the 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;
+ NOR_FLASH_INSTANCE *Instance;
+
+ Instance = INSTANCE_FROM_FVB_THIS(This);
+
+ DEBUG ((DEBUG_BLKIO, "FvbRead(Parameters: Lba=%ld, Offset=0x%x, "
+ "*NumBytes=0x%x, Buffer @ 0x%08x)\n",
+ Instance->StartLba + Lba, Offset, *NumBytes, Buffer));
+
+ if (!Instance->Initialized && Instance->Initialize)
+ Instance->Initialize(Instance);
+
+ // Cache the block size to avoid de-referencing pointers all the time
+ BlockSize = Instance->Media.BlockSize;
+
+ DEBUG ((DEBUG_BLKIO, "FvbRead: Check if (Offset=0x%x + NumBytes=0x%x) <= "
+ "BlockSize=0x%x\n", Offset, *NumBytes, BlockSize ));
+
+ // The read must not span block boundaries.
+ while(Offset >= BlockSize) {
+ Offset -= BlockSize;
+ Lba++;
+ }
+
+ if ((Instance->StartLba + Lba) > Instance->Media.LastBlock) {
+ DEBUG ((DEBUG_ERROR, "%a : Parameter LBA %ld is beyond the last Lba (%ld)\n",
+ __FUNCTION__, Lba, Instance->Media.LastBlock));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if((Offset + *NumBytes) > BlockSize)
+ *NumBytes = BlockSize-Offset;
+
+ return NorFlashPlatformRead (Instance, Instance->StartLba + Lba,
+ Offset, *NumBytes, Buffer);
+}
+
+/**
+ Writes the specified number of bytes from the input buffer to the block.
+
+ The Write() function writes the specified number of bytes from
+ the provided buffer to the specified block and offset. If the
+ firmware volume is sticky write, the caller must ensure that
+ all the bits of the specified range to write are in the
+ EFI_FVB_ERASE_POLARITY state before calling the Write()
+ function, or else the result will be unpredictable. This
+ unpredictability arises because, for a sticky-write firmware
+ volume, a write may negate a bit in the EFI_FVB_ERASE_POLARITY
+ state but cannot flip it back again. Before calling the
+ Write() function, it is recommended for the caller to first call
+ the EraseBlocks() function to erase the specified block to
+ write. A block erase cycle will transition bits from the
+ (NOT)EFI_FVB_ERASE_POLARITY state back to the
+ EFI_FVB_ERASE_POLARITY state. Implementations should be
+ mindful that the firmware volume might be in the WriteDisabled
+ state. If it is in this state, the Write() function must
+ return the status code EFI_ACCESS_DENIED without modifying the
+ contents of the firmware volume. The Write() function must
+ also prevent spanning block boundaries. If a write is
+ requested that spans a block boundary, the write must store up
+ to the boundary but not beyond. The output parameter NumBytes
+ must be set to correctly indicate the number of bytes actually
+ written. The caller must be aware that a write may be
+ partially completed. All writes, partial or otherwise, must be
+ fully flushed to the hardware before the Write() service
+ returns.
+
+ @param This Indicates the 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
+ )
+{
+ NOR_FLASH_INSTANCE *Instance;
+ UINTN BlockSize;
+
+ Instance = INSTANCE_FROM_FVB_THIS (This);
+ // Cache the block size to avoid de-referencing pointers all the time
+ BlockSize = Instance->Media.BlockSize;
+
+ if (!Instance->Initialized && Instance->Initialize)
+ Instance->Initialize(Instance);
+
+ // The write must not span block boundaries.
+ while(Offset >= BlockSize) {
+ Offset -= BlockSize;
+ Lba++;
+ }
+
+ if ((Instance->StartLba + Lba) > Instance->Media.LastBlock) {
+ DEBUG ((DEBUG_ERROR, "%a : Parameter LBA %ld is beyond the last Lba (%ld)\n",
+ __FUNCTION__, Lba, Instance->Media.LastBlock));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if((Offset + *NumBytes) > BlockSize)
+ *NumBytes = BlockSize-Offset;
+
+ return NorFlashWrite (Instance, Instance->StartLba + Lba,
+ Offset, NumBytes, Buffer);
+}
+
+/**
+ Erases and initialises a firmware volume block.
+
+ The EraseBlocks() function erases one or more blocks as denoted
+ by the variable argument list. The entire parameter list of
+ blocks must be verified before erasing any blocks. If a block is
+ requested that does not exist within the associated firmware
+ volume (it has a larger index than the last block of the
+ firmware volume), the EraseBlocks() function must return the
+ status code EFI_INVALID_PARAMETER without modifying the contents
+ of the firmware volume. Implementations should be mindful that
+ the firmware volume might be in the WriteDisabled state. If it
+ is in this state, the EraseBlocks() function must return the
+ status code EFI_ACCESS_DENIED without modifying the contents of
+ the firmware volume. All calls to EraseBlocks() must be fully
+ flushed to the hardware before the EraseBlocks() service
+ returns.
+
+ @param This Indicates the 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.
+ For example, the following indicates that two ranges of blocks
+ (5-7 and 10-11) are to be erased:
+ EraseBlocks (This, 5, 3, 10, 2, 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
+ NOR_FLASH_INSTANCE *Instance;
+
+ Instance = INSTANCE_FROM_FVB_THIS(This);
+
+ DEBUG ((DEBUG_BLKIO, "FvbEraseBlocks()\n"));
+
+ Status = EFI_SUCCESS;
+
+ // Detect WriteDisabled state
+ if (Instance->Media.ReadOnly == TRUE) {
+ // Firmware volume is in WriteDisabled state
+ DEBUG ((DEBUG_ERROR, "%a : 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
+ DEBUG ((DEBUG_BLKIO, "FvbEraseBlocks: Check if: ( StartingLba=%ld + "
+ "NumOfLba=%d - 1 ) > LastBlock=%ld.\n",
+ Instance->StartLba + StartingLba, NumOfLba,
+ Instance->Media.LastBlock));
+ if ((NumOfLba == 0) ||
+ ((Instance->StartLba + StartingLba + NumOfLba - 1) >
+ Instance->Media.LastBlock)) {
+ VA_END (Args);
+ DEBUG ((DEBUG_ERROR, "%a : 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_NOR_BLOCK_ADDRESS (
+ Instance->RegionBaseAddress,
+ Instance->StartLba + StartingLba,
+ Instance->Media.BlockSize
+ );
+
+ // Erase it
+ DEBUG ((DEBUG_BLKIO, "FvbEraseBlocks: Erasing Lba=%ld @ 0x%08x.\n",
+ Instance->StartLba + StartingLba, BlockAddress));
+ Status = NorFlashPlatformEraseSector(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;
+}
+
+/**
+ 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
+FvbVirtualNotifyEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EfiConvertPointer (0x0, (VOID**)&mFlashNvStorageVariableBase);
+ return;
+}
+
+EFI_STATUS
+EFIAPI
+NorFlashFvbInitialize (
+ IN NOR_FLASH_INSTANCE* Instance
+ )
+{
+ EFI_STATUS Status;
+ UINT32 FvbNumLba;
+ EFI_BOOT_MODE BootMode;
+ UINTN RuntimeMmioRegionSize;
+
+ DEBUG((DEBUG_BLKIO,"NorFlashFvbInitialize\n"));
+
+ Instance->Initialized = TRUE;
+ mFlashNvStorageVariableBase = FixedPcdGet64 (PcdFlashNvStorageVariableBase64);
+
+ // Set the index of the first LBA for the FVB
+ Instance->StartLba = (PcdGet64 (PcdFlashNvStorageVariableBase64) - Instance->RegionBaseAddress) / Instance->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 = ValidateFvHeader (Instance);
+
+ // Install the Default FVB header if required
+ if (EFI_ERROR(Status)) {
+ // There is no valid header, so time to install one.
+ DEBUG ((DEBUG_INFO, "%a: The FVB Header is not valid.\n", __FUNCTION__));
+ DEBUG ((DEBUG_INFO, "%a: Installing a correct one for this volume.\n",
+ __FUNCTION__));
+
+ // Erase all the NorFlash that is reserved for variable storage
+ FvbNumLba = (PcdGet32(PcdFlashNvStorageVariableSize) + PcdGet32(PcdFlashNvStorageFtwWorkingSize) + PcdGet32(PcdFlashNvStorageFtwSpareSize)) / Instance->Media.BlockSize;
+
+ Status = FvbEraseBlocks (&Instance->FvbProtocol, (EFI_LBA)0, FvbNumLba, EFI_LBA_LIST_TERMINATOR);
+ if (EFI_ERROR(Status))
+ return Status;
+
+ // Install all appropriate headers
+ Status = InitializeFvAndVariableStoreHeaders (Instance);
+ if (EFI_ERROR(Status))
+ return Status;
+ }
+
+ //
+ // Declare the Non-Volatile storage as EFI_MEMORY_RUNTIME
+ //
+
+ // Note: all the NOR Flash region needs to be reserved into the UEFI Runtime memory;
+ // even if we only use the small block region at the top of the NOR Flash.
+ // The reason is when the NOR Flash memory is set into program mode, the command
+ // is written as the base of the flash region (ie: Instance->DeviceBaseAddress)
+ RuntimeMmioRegionSize = (Instance->RegionBaseAddress - Instance->DeviceBaseAddress) + Instance->Size;
+
+ Status = gDS->AddMemorySpace (
+ EfiGcdMemoryTypeMemoryMappedIo,
+ Instance->DeviceBaseAddress, RuntimeMmioRegionSize,
+ EFI_MEMORY_UC | EFI_MEMORY_RUNTIME
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = gDS->SetMemorySpaceAttributes (
+ Instance->DeviceBaseAddress, RuntimeMmioRegionSize,
+ 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,
+ FvbVirtualNotifyEvent,
+ NULL,
+ &gEfiEventVirtualAddressChangeGuid,
+ &mFvbVirtualAddrChangeEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
diff --git a/Platform/NXP/Include/Library/NorFlash.h b/Platform/NXP/Include/Library/NorFlash.h
new file mode 100644
index 0000000..79312f5
--- /dev/null
+++ b/Platform/NXP/Include/Library/NorFlash.h
@@ -0,0 +1,222 @@
+/** @NorFlash.h
+
+ Based on NOR flash access APIs used in ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.h
+
+ Copyright (c) 2011 - 2014, ARM Ltd. All rights reserved.
+ Copyright 2017 NXP
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __NOR_FLASH_H__
+#define __NOR_FLASH_H__
+
+#include <Protocol/BlockIo.h>
+#include <Protocol/FirmwareVolumeBlock.h>
+
+#define NOR_FLASH_ERASE_RETRY 10
+
+#define GET_NOR_BLOCK_ADDRESS(BaseAddr,Lba,LbaSize) ( BaseAddr + (UINTN)((Lba) * LbaSize) )
+
+#define NOR_FLASH_SIGNATURE SIGNATURE_32('n', 'o', 'r', '0')
+#define INSTANCE_FROM_FVB_THIS(a) CR(a, NOR_FLASH_INSTANCE, FvbProtocol, NOR_FLASH_SIGNATURE)
+#define INSTANCE_FROM_BLKIO_THIS(a) CR(a, NOR_FLASH_INSTANCE, BlockIoProtocol, NOR_FLASH_SIGNATURE)
+
+typedef struct _NOR_FLASH_INSTANCE NOR_FLASH_INSTANCE;
+
+typedef EFI_STATUS (*NOR_FLASH_INITIALIZE) (NOR_FLASH_INSTANCE* Instance);
+
+typedef struct {
+ VENDOR_DEVICE_PATH Vendor;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} NOR_FLASH_DEVICE_PATH;
+
+struct _NOR_FLASH_INSTANCE {
+ UINT32 Signature;
+ EFI_HANDLE Handle;
+ BOOLEAN Initialized;
+ NOR_FLASH_INITIALIZE Initialize;
+ UINTN DeviceBaseAddress;
+ UINTN RegionBaseAddress;
+ UINTN Size;
+ EFI_LBA StartLba;
+ EFI_BLOCK_IO_PROTOCOL BlockIoProtocol;
+ EFI_BLOCK_IO_MEDIA Media;
+ BOOLEAN SupportFvb;
+ EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL FvbProtocol;
+ VOID* ShadowBuffer;
+ NOR_FLASH_DEVICE_PATH DevicePath;
+};
+
+//
+// NorFlashLib.c related
+//
+
+EFI_STATUS
+NorFlashPlatformWriteBuffer (
+ IN NOR_FLASH_INSTANCE *Instance,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN OUT UINTN *NumBytes,
+ IN UINT8 *Buffer
+ );
+
+EFI_STATUS
+NorFlashPlatformEraseSector (
+ IN NOR_FLASH_INSTANCE *Instance,
+ IN UINTN SectorAddress
+ );
+
+EFI_STATUS
+NorFlashPlatformControllerInitialization (
+ VOID
+ );
+
+EFI_STATUS
+NorFlashPlatformRead (
+ IN NOR_FLASH_INSTANCE *Instance,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN UINTN BufferSizeInBytes,
+ OUT UINT8 *Buffer
+ );
+
+EFI_STATUS
+NorFlashPlatformReset (
+ IN UINTN Instance
+ );
+
+extern CONST EFI_GUID* CONST mNorFlashVariableGuid;
+
+//
+// NorFlashFvbDxe.c
+//
+
+EFI_STATUS
+EFIAPI
+NorFlashFvbInitialize (
+ IN NOR_FLASH_INSTANCE* Instance
+ );
+
+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,
+ ...
+ );
+//
+// NorFlashBlockIoDxe.c
+//
+
+//
+// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.Reset
+//
+EFI_STATUS
+EFIAPI
+NorFlashBlockIoReset (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ );
+
+//
+// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.ReadBlocks
+//
+EFI_STATUS
+EFIAPI
+NorFlashBlockIoReadBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSizeInBytes,
+ OUT VOID *Buffer
+);
+
+//
+// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.WriteBlocks
+//
+EFI_STATUS
+EFIAPI
+NorFlashBlockIoWriteBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSizeInBytes,
+ IN VOID *Buffer
+);
+
+//
+// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.FlushBlocks
+//
+EFI_STATUS
+EFIAPI
+NorFlashBlockIoFlushBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This
+);
+
+EFI_STATUS
+NorFlashWrite (
+ IN NOR_FLASH_INSTANCE *Instance,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN OUT UINTN *NumBytes,
+ IN UINT8 *Buffer
+);
+
+#endif /* __NOR_FLASH_DXE_H__ */
--
1.9.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 4/4] Compilation:Modify dsc, fdf files and add inc file
2017-12-01 4:10 [PATCH 0/4] Platform/NXP-Adding NXP NOR IP Vabhav
` (2 preceding siblings ...)
2017-12-01 4:10 ` [PATCH 3/4] Platform/NXP : Add Support for NOR Flash driver Vabhav
@ 2017-12-01 4:10 ` Vabhav
3 siblings, 0 replies; 5+ messages in thread
From: Vabhav @ 2017-12-01 4:10 UTC (permalink / raw)
To: ard.biesheuvel, leif.lindholm, michael.d.kinney, edk2-devel
This patch adds support for compilation of IfcFlashLib,
NorFlashLib,Nor flash Driver and include runtime
variable support
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Vabhav <vabhav.sharma@nxp.com>
---
Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.dsc | 22 +++++++
Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.fdf | 9 ++-
Platform/NXP/LS1043aRdbPkg/VarStore.fdf.inc | 98 ++++++++++++++++++++++++++++
Platform/NXP/NxpQoriqLs.dsc | 6 +-
4 files changed, 133 insertions(+), 2 deletions(-)
create mode 100644 Platform/NXP/LS1043aRdbPkg/VarStore.fdf.inc
diff --git a/Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.dsc b/Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.dsc
index 19d4d30..4b3ac02 100644
--- a/Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.dsc
+++ b/Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.dsc
@@ -39,6 +39,16 @@
SocLib|edk2-platforms/Silicon/NXP/Chassis/LS1043aSocLib.inf
RealTimeClockLib|edk2-platforms/Silicon/Maxim/Library/Ds1307RtcLib/Ds1307RtcLib.inf
+ #
+ # Nor Lib
+ #
+ NorFlashLib|edk2-platforms/Platform/NXP/Library/NorFlashLib/NorFlashLib.inf
+
+ #
+ # IFC FLASH Lib
+ #
+ IfcFlashLib|edk2-platforms/Platform/NXP/Library/IfcFlashLib/IfcFlashLib.inf
+
[PcdsFixedAtBuild.common]
gArmPlatformTokenSpaceGuid.PcdFirmwareVendor|"LS1043a RDB board"
@@ -55,6 +65,13 @@
gNxpQoriqLsTokenSpaceGuid.PcdWdogBigEndian|TRUE
#
+ # NV Storage PCDs.
+ #
+ gArmTokenSpaceGuid.PcdVFPEnabled|1
+ gNxpQoriqLsTokenSpaceGuid.PcdFlashDeviceBase64|0x060000000
+ gNxpQoriqLsTokenSpaceGuid.PcdFlashReservedRegionBase64|0x60300000
+
+ #
# I2C controller Pcds
#
gNxpQoriqLsTokenSpaceGuid.PcdI2cBus|0
@@ -74,4 +91,9 @@
edk2-platforms/Platform/NXP/Drivers/WatchDog/WatchDogDxe.inf
edk2-platforms/Platform/NXP/Drivers/I2cDxe/I2cDxe.inf
+ #
+ # NOR
+ #
+ edk2-platforms/Platform/NXP/Drivers/NorFlashDxe/NorFlashDxe.inf
+
##
diff --git a/Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.fdf b/Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.fdf
index 9a8f242..902de2d 100644
--- a/Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.fdf
+++ b/Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.fdf
@@ -54,6 +54,7 @@ NumBlocks = 0xEC890
gArmTokenSpaceGuid.PcdFvBaseAddress|gArmTokenSpaceGuid.PcdFvSize
FV = FVMAIN_COMPACT
+!include VarStore.fdf.inc
################################################################################
#
@@ -103,7 +104,8 @@ READ_LOCK_STATUS = TRUE
INF MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
INF MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf
INF EmbeddedPkg/EmbeddedMonotonicCounter/EmbeddedMonotonicCounter.inf
- INF MdeModulePkg/Universal/Variable/EmuRuntimeDxe/EmuVariableRuntimeDxe.inf
+ INF MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
+ INF MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf
INF MdeModulePkg/Universal/ResetSystemRuntimeDxe/ResetSystemRuntimeDxe.inf
INF EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClockRuntimeDxe.inf
@@ -120,6 +122,11 @@ READ_LOCK_STATUS = TRUE
INF EmbeddedPkg/SimpleTextInOutSerial/SimpleTextInOutSerial.inf
#
+ # NOR Driver
+ #
+ INF edk2-platforms/Platform/NXP/Drivers/NorFlashDxe/NorFlashDxe.inf
+
+ #
# Network modules
#
INF MdeModulePkg/Universal/Network/SnpDxe/SnpDxe.inf
diff --git a/Platform/NXP/LS1043aRdbPkg/VarStore.fdf.inc b/Platform/NXP/LS1043aRdbPkg/VarStore.fdf.inc
new file mode 100644
index 0000000..0aea642
--- /dev/null
+++ b/Platform/NXP/LS1043aRdbPkg/VarStore.fdf.inc
@@ -0,0 +1,98 @@
+## @file
+# FDF include file with FD definition that defines an empty variable store.
+#
+# Copyright (c) 2016, Freescale Semiconductor. All rights reserved.
+# Copyright (c) 2016, Linaro, Ltd. All rights reserved.
+# Copyright (C) 2014, Red Hat, Inc.
+# Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.
+#
+# This program and the accompanying materials are licensed and made available
+# under the terms and conditions of the BSD License which accompanies this
+# distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR
+# IMPLIED.
+#
+##
+
+[FD.LS1043aRdbNv_EFI]
+
+BaseAddress = 0x60300000|gNxpQoriqLsTokenSpaceGuid.PcdNvFdBase #The base address of the FLASH device
+Size = 0x000C0000|gNxpQoriqLsTokenSpaceGuid.PcdNvFdSize #The size in bytes of the FLASH device
+ErasePolarity = 1
+BlockSize = 0x1
+NumBlocks = 0xC0000
+
+#
+# Place NV Storage just above Platform Data Base
+#
+DEFINE NVRAM_AREA_VARIABLE_BASE = 0x00000000
+DEFINE NVRAM_AREA_VARIABLE_SIZE = 0x00040000
+DEFINE FTW_WORKING_BASE = $(NVRAM_AREA_VARIABLE_BASE) + $(NVRAM_AREA_VARIABLE_SIZE)
+DEFINE FTW_WORKING_SIZE = 0x00040000
+DEFINE FTW_SPARE_BASE = $(FTW_WORKING_BASE) + $(FTW_WORKING_SIZE)
+DEFINE FTW_SPARE_SIZE = 0x00040000
+
+#############################################################################
+# LS1043ARDB NVRAM Area
+# LS1043ARDB NVRAM Area contains: Variable + FTW Working + FTW Spare
+#############################################################################
+
+
+$(NVRAM_AREA_VARIABLE_BASE)|$(NVRAM_AREA_VARIABLE_SIZE)
+gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64|gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize
+#NV_VARIABLE_STORE
+DATA = {
+ ## This is the EFI_FIRMWARE_VOLUME_HEADER
+ # ZeroVector []
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ # FileSystemGuid: gEfiSystemNvDataFvGuid =
+ # { 0xFFF12B8D, 0x7696, 0x4C8B,
+ # { 0xA9, 0x85, 0x27, 0x47, 0x07, 0x5B, 0x4F, 0x50 }}
+ 0x8D, 0x2B, 0xF1, 0xFF, 0x96, 0x76, 0x8B, 0x4C,
+ 0xA9, 0x85, 0x27, 0x47, 0x07, 0x5B, 0x4F, 0x50,
+ # FvLength: 0xC0000
+ 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00,
+ # Signature "_FVH" # Attributes
+ 0x5f, 0x46, 0x56, 0x48, 0x36, 0x0E, 0x00, 0x00,
+ # HeaderLength # CheckSum # ExtHeaderOffset #Reserved #Revision
+ 0x48, 0x00, 0xC2, 0xF9, 0x00, 0x00, 0x00, 0x02,
+ # Blockmap[0]: 0x3 Blocks * 0x40000 Bytes / Block
+ 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
+ # Blockmap[1]: End
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ ## This is the VARIABLE_STORE_HEADER
+ # It is compatible with SECURE_BOOT_ENABLE == FALSE as well.
+ # Signature: gEfiAuthenticatedVariableGuid =
+ # { 0xaaf32c78, 0x947b, 0x439a,
+ # { 0xa1, 0x80, 0x2e, 0x14, 0x4e, 0xc3, 0x77, 0x92 }}
+ 0x78, 0x2c, 0xf3, 0xaa, 0x7b, 0x94, 0x9a, 0x43,
+ 0xa1, 0x80, 0x2e, 0x14, 0x4e, 0xc3, 0x77, 0x92,
+ # Size: 0x40000 (gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize) -
+ # 0x48 (size of EFI_FIRMWARE_VOLUME_HEADER) = 0x3ffb8
+ # This can speed up the Variable Dispatch a bit.
+ 0xB8, 0xFF, 0x03, 0x00,
+ # FORMATTED: 0x5A #HEALTHY: 0xFE #Reserved: UINT16 #Reserved1: UINT32
+ 0x5A, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+}
+
+$(FTW_WORKING_BASE)|$(FTW_WORKING_SIZE)
+gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase64|gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize
+#NV_FTW_WORKING
+DATA = {
+ # EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER->Signature = gEdkiiWorkingBlockSignatureGuid =
+ # { 0x9e58292b, 0x7c68, 0x497d, { 0xa0, 0xce, 0x65, 0x0, 0xfd, 0x9f, 0x1b, 0x95 }}
+ 0x2b, 0x29, 0x58, 0x9e, 0x68, 0x7c, 0x7d, 0x49,
+ 0xa0, 0xce, 0x65, 0x0, 0xfd, 0x9f, 0x1b, 0x95,
+ # Crc:UINT32 #WorkingBlockValid:1, WorkingBlockInvalid:1, Reserved
+ 0x5b, 0xe7, 0xc6, 0x86, 0xFE, 0xFF, 0xFF, 0xFF,
+ # WriteQueueSize: UINT64
+ 0xE0, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00
+}
+
+$(FTW_SPARE_BASE)|$(FTW_SPARE_SIZE)
+gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase64|gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize
+#NV_FTW_SPARE
diff --git a/Platform/NXP/NxpQoriqLs.dsc b/Platform/NXP/NxpQoriqLs.dsc
index 2ea3757..ec49e85 100644
--- a/Platform/NXP/NxpQoriqLs.dsc
+++ b/Platform/NXP/NxpQoriqLs.dsc
@@ -349,7 +349,11 @@
MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf
MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf
MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
- MdeModulePkg/Universal/Variable/EmuRuntimeDxe/EmuVariableRuntimeDxe.inf
+ MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf{
+ <LibraryClasses>
+ NULL|MdeModulePkg/Library/VarCheckUefiLib/VarCheckUefiLib.inf
+ }
+ MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf
MdeModulePkg/Universal/ResetSystemRuntimeDxe/ResetSystemRuntimeDxe.inf
EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClockRuntimeDxe.inf
EmbeddedPkg/EmbeddedMonotonicCounter/EmbeddedMonotonicCounter.inf
--
1.9.1
^ permalink raw reply related [flat|nested] 5+ messages in thread