* [edk2-devel] [edk2-platforms][PATCH V1 0/5] Enable non volatile storage on N1SDP @ 2023-11-16 11:45 sahil 2023-11-16 11:45 ` [edk2-devel] [edk2-platforms][PATCH V1 1/5] Silicon/ARM/NeoverseN1Soc: Enable SCP QSPI flash region sahil ` (4 more replies) 0 siblings, 5 replies; 17+ messages in thread From: sahil @ 2023-11-16 11:45 UTC (permalink / raw) To: devel; +Cc: Ard Biesheuvel, Leif Lindholm, Sami Mujawar, Sahil N1SDP uses an emulated variable storage on DDR memory for the variable storage. But this emulated variable storage is a volatile memory and so the values of variable cant persist on next reboot or in power cycle. In N1SDP platform, the SoC is connected to IOFPGA which has a Cadence Quad SPI (QSPI) controller. This QSPI controller manages the flash chip device (NOR Flash with 32 MB memory capacity, 4KB block size) via QSPI bus. With these changes we use this NOR flash device for persistent variable storage. Link to branch with the patches in this series - https://github.com/sah01Kaushal/edk2-platforms/tree/n1sdp_persistent_storage sahil (5): Silicon/ARM/NeoverseN1Soc: Enable SCP QSPI flash region Silicon/ARM/NeoverseN1Soc: NOR flash library for N1Sdp Platform/ARM/N1Sdp: NOR flash Dxe Driver for N1Sdp Platform/ARM/N1Sdp: Persistent storage for N1Sdp Platform/ARM/N1Sdp: Enable FaultTolerantWrite Dxe driver for N1Sdp Platform/ARM/N1Sdp/N1SdpPlatform.dec | 5 +- Platform/ARM/N1Sdp/N1SdpPlatform.dsc | 25 +- Platform/ARM/N1Sdp/N1SdpPlatform.fdf | 5 +- Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiDxe.inf | 72 ++ Silicon/ARM/NeoverseN1Soc/Library/NorFlashLib/NorFlashLib.inf | 36 + Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiReg.h | 33 + Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/NorFlash.h | 491 +++++++++ Silicon/ARM/NeoverseN1Soc/Include/NeoverseN1Soc.h | 6 +- Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiDxe.c | 409 ++++++++ Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/NorFlash.c | 1100 ++++++++++++++++++++ Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/NorFlashFvb.c | 647 ++++++++++++ Silicon/ARM/NeoverseN1Soc/Library/NorFlashLib/NorFlashLib.c | 52 + Silicon/ARM/NeoverseN1Soc/Library/PlatformLib/PlatformLibMem.c | 10 +- 13 files changed, 2880 insertions(+), 11 deletions(-) create mode 100644 Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiDxe.inf create mode 100644 Silicon/ARM/NeoverseN1Soc/Library/NorFlashLib/NorFlashLib.inf create mode 100644 Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiReg.h create mode 100644 Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/NorFlash.h create mode 100644 Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiDxe.c create mode 100644 Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/NorFlash.c create mode 100644 Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/NorFlashFvb.c create mode 100644 Silicon/ARM/NeoverseN1Soc/Library/NorFlashLib/NorFlashLib.c -- 2.25.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#111310): https://edk2.groups.io/g/devel/message/111310 Mute This Topic: https://groups.io/mt/102625035/7686176 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io] -=-=-=-=-=-=-=-=-=-=-=- ^ permalink raw reply [flat|nested] 17+ messages in thread
* [edk2-devel] [edk2-platforms][PATCH V1 1/5] Silicon/ARM/NeoverseN1Soc: Enable SCP QSPI flash region 2023-11-16 11:45 [edk2-devel] [edk2-platforms][PATCH V1 0/5] Enable non volatile storage on N1SDP sahil @ 2023-11-16 11:45 ` sahil 2023-12-07 10:59 ` Thomas Abraham 2023-12-18 15:12 ` Sami Mujawar 2023-11-16 11:45 ` [edk2-devel] [edk2-platforms][PATCH V1 2/5] Silicon/ARM/NeoverseN1Soc: NOR flash library for N1Sdp sahil ` (3 subsequent siblings) 4 siblings, 2 replies; 17+ messages in thread From: sahil @ 2023-11-16 11:45 UTC (permalink / raw) To: devel; +Cc: Ard Biesheuvel, Leif Lindholm, Sami Mujawar, Sahil Enable SCP QSPI flash region access by adding it in the PlatformLibMem Signed-off-by: sahil <sahil@arm.com> --- Silicon/ARM/NeoverseN1Soc/Include/NeoverseN1Soc.h | 6 +++++- Silicon/ARM/NeoverseN1Soc/Library/PlatformLib/PlatformLibMem.c | 10 ++++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/Silicon/ARM/NeoverseN1Soc/Include/NeoverseN1Soc.h b/Silicon/ARM/NeoverseN1Soc/Include/NeoverseN1Soc.h index 097160c7e2d1..92b8c9c45775 100644 --- a/Silicon/ARM/NeoverseN1Soc/Include/NeoverseN1Soc.h +++ b/Silicon/ARM/NeoverseN1Soc/Include/NeoverseN1Soc.h @@ -1,6 +1,6 @@ /** @file * -* Copyright (c) 2018 - 2020, ARM Limited. All rights reserved. +* Copyright (c) 2018 - 2023, ARM Limited. All rights reserved. * * SPDX-License-Identifier: BSD-2-Clause-Patent * @@ -41,6 +41,10 @@ #define NEOVERSEN1SOC_EXP_PERIPH_BASE0 0x1C000000 #define NEOVERSEN1SOC_EXP_PERIPH_BASE0_SZ 0x1300000 +// SCP QSPI flash device +#define NEOVERSEN1SOC_SCP_QSPI_AHB_BASE 0x18000000 +#define NEOVERSEN1SOC_SCP_QSPI_AHB_SZ 0x2000000 + // Base address to a structure of type NEOVERSEN1SOC_PLAT_INFO which is // pre-populated by a earlier boot stage #define NEOVERSEN1SOC_PLAT_INFO_STRUCT_BASE (NEOVERSEN1SOC_NON_SECURE_SRAM_BASE + \ diff --git a/Silicon/ARM/NeoverseN1Soc/Library/PlatformLib/PlatformLibMem.c b/Silicon/ARM/NeoverseN1Soc/Library/PlatformLib/PlatformLibMem.c index 9e8a1efc557d..eb099953fe29 100644 --- a/Silicon/ARM/NeoverseN1Soc/Library/PlatformLib/PlatformLibMem.c +++ b/Silicon/ARM/NeoverseN1Soc/Library/PlatformLib/PlatformLibMem.c @@ -1,6 +1,6 @@ /** @file - Copyright (c) 2018 - 2021, ARM Limited. All rights reserved.<BR> + Copyright (c) 2018 - 2023, ARM Limited. All rights reserved.<BR> SPDX-License-Identifier: BSD-2-Clause-Patent @@ -13,7 +13,7 @@ #include <NeoverseN1Soc.h> // The total number of descriptors, including the final "end-of-table" descriptor. -#define MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS 19 +#define MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS 20 /** Returns the Virtual Memory Map of the platform. @@ -184,6 +184,12 @@ ArmPlatformGetVirtualMemoryMap ( VirtualMemoryTable[Index].Length = NEOVERSEN1SOC_EXP_PERIPH_BASE0_SZ; VirtualMemoryTable[Index].Attributes = ARM_MEMORY_REGION_ATTRIBUTE_DEVICE; + // SCP QSPI flash device + VirtualMemoryTable[++Index].PhysicalBase = NEOVERSEN1SOC_SCP_QSPI_AHB_BASE; + VirtualMemoryTable[Index].VirtualBase = NEOVERSEN1SOC_SCP_QSPI_AHB_BASE; + VirtualMemoryTable[Index].Length = NEOVERSEN1SOC_SCP_QSPI_AHB_SZ; + VirtualMemoryTable[Index].Attributes = ARM_MEMORY_REGION_ATTRIBUTE_DEVICE; + if (PlatInfo->MultichipMode == 1) { //Remote DDR (2GB) VirtualMemoryTable[++Index].PhysicalBase = PcdGet64 (PcdExtMemorySpace) + -- 2.25.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#111308): https://edk2.groups.io/g/devel/message/111308 Mute This Topic: https://groups.io/mt/102625033/7686176 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io] -=-=-=-=-=-=-=-=-=-=-=- ^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [edk2-devel] [edk2-platforms][PATCH V1 1/5] Silicon/ARM/NeoverseN1Soc: Enable SCP QSPI flash region 2023-11-16 11:45 ` [edk2-devel] [edk2-platforms][PATCH V1 1/5] Silicon/ARM/NeoverseN1Soc: Enable SCP QSPI flash region sahil @ 2023-12-07 10:59 ` Thomas Abraham 2023-12-18 15:12 ` Sami Mujawar 1 sibling, 0 replies; 17+ messages in thread From: Thomas Abraham @ 2023-12-07 10:59 UTC (permalink / raw) To: devel@edk2.groups.io, Sahil Kaushal Cc: Ard Biesheuvel, Leif Lindholm, Sami Mujawar, Chandni Cherukuri > -----Original Message----- > From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of sahil via > groups.io > Sent: Thursday, November 16, 2023 11:46 AM > To: devel@edk2.groups.io > Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>; Leif Lindholm > <quic_llindhol@quicinc.com>; Sami Mujawar <Sami.Mujawar@arm.com>; > Sahil Kaushal <Sahil.Kaushal@arm.com> > Subject: [edk2-devel] [edk2-platforms][PATCH V1 1/5] > Silicon/ARM/NeoverseN1Soc: Enable SCP QSPI flash region > > Enable SCP QSPI flash region access by adding it in the PlatformLibMem > > Signed-off-by: sahil <sahil@arm.com> > --- > Silicon/ARM/NeoverseN1Soc/Include/NeoverseN1Soc.h | 6 +++++- > Silicon/ARM/NeoverseN1Soc/Library/PlatformLib/PlatformLibMem.c | 10 > ++++++++-- > 2 files changed, 13 insertions(+), 3 deletions(-) > > diff --git a/Silicon/ARM/NeoverseN1Soc/Include/NeoverseN1Soc.h > b/Silicon/ARM/NeoverseN1Soc/Include/NeoverseN1Soc.h > index 097160c7e2d1..92b8c9c45775 100644 > --- a/Silicon/ARM/NeoverseN1Soc/Include/NeoverseN1Soc.h > +++ b/Silicon/ARM/NeoverseN1Soc/Include/NeoverseN1Soc.h > @@ -1,6 +1,6 @@ > /** @file > > * > > -* Copyright (c) 2018 - 2020, ARM Limited. All rights reserved. > > +* Copyright (c) 2018 - 2023, ARM Limited. All rights reserved. > > * > > * SPDX-License-Identifier: BSD-2-Clause-Patent > > * > > @@ -41,6 +41,10 @@ > #define NEOVERSEN1SOC_EXP_PERIPH_BASE0 0x1C000000 > > #define NEOVERSEN1SOC_EXP_PERIPH_BASE0_SZ 0x1300000 > > > > +// SCP QSPI flash device > > +#define NEOVERSEN1SOC_SCP_QSPI_AHB_BASE 0x18000000 > > +#define NEOVERSEN1SOC_SCP_QSPI_AHB_SZ 0x2000000 > > + > > // Base address to a structure of type NEOVERSEN1SOC_PLAT_INFO which is > > // pre-populated by a earlier boot stage > > #define NEOVERSEN1SOC_PLAT_INFO_STRUCT_BASE > (NEOVERSEN1SOC_NON_SECURE_SRAM_BASE + \ > > diff --git a/Silicon/ARM/NeoverseN1Soc/Library/PlatformLib/PlatformLibMem.c > b/Silicon/ARM/NeoverseN1Soc/Library/PlatformLib/PlatformLibMem.c > index 9e8a1efc557d..eb099953fe29 100644 > --- a/Silicon/ARM/NeoverseN1Soc/Library/PlatformLib/PlatformLibMem.c > +++ b/Silicon/ARM/NeoverseN1Soc/Library/PlatformLib/PlatformLibMem.c > @@ -1,6 +1,6 @@ > /** @file > > > > - Copyright (c) 2018 - 2021, ARM Limited. All rights reserved.<BR> > > + Copyright (c) 2018 - 2023, ARM Limited. All rights reserved.<BR> > > > > SPDX-License-Identifier: BSD-2-Clause-Patent > > > > @@ -13,7 +13,7 @@ > #include <NeoverseN1Soc.h> > > > > // The total number of descriptors, including the final "end-of-table" descriptor. > > -#define MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS 19 > > +#define MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS 20 > > > > /** > > Returns the Virtual Memory Map of the platform. > > @@ -184,6 +184,12 @@ ArmPlatformGetVirtualMemoryMap ( > VirtualMemoryTable[Index].Length = > NEOVERSEN1SOC_EXP_PERIPH_BASE0_SZ; > > VirtualMemoryTable[Index].Attributes = > ARM_MEMORY_REGION_ATTRIBUTE_DEVICE; > > > > + // SCP QSPI flash device > > + VirtualMemoryTable[++Index].PhysicalBase = > NEOVERSEN1SOC_SCP_QSPI_AHB_BASE; > > + VirtualMemoryTable[Index].VirtualBase = > NEOVERSEN1SOC_SCP_QSPI_AHB_BASE; > > + VirtualMemoryTable[Index].Length = > NEOVERSEN1SOC_SCP_QSPI_AHB_SZ; > > + VirtualMemoryTable[Index].Attributes = > ARM_MEMORY_REGION_ATTRIBUTE_DEVICE; > > + > > if (PlatInfo->MultichipMode == 1) { > > //Remote DDR (2GB) > > VirtualMemoryTable[++Index].PhysicalBase = PcdGet64 > (PcdExtMemorySpace) + > Reviewed-by: Thomas Abraham <thomas.abraham@arm.com> IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you. -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#112181): https://edk2.groups.io/g/devel/message/112181 Mute This Topic: https://groups.io/mt/102625033/7686176 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io] -=-=-=-=-=-=-=-=-=-=-=- ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [edk2-devel] [edk2-platforms][PATCH V1 1/5] Silicon/ARM/NeoverseN1Soc: Enable SCP QSPI flash region 2023-11-16 11:45 ` [edk2-devel] [edk2-platforms][PATCH V1 1/5] Silicon/ARM/NeoverseN1Soc: Enable SCP QSPI flash region sahil 2023-12-07 10:59 ` Thomas Abraham @ 2023-12-18 15:12 ` Sami Mujawar 1 sibling, 0 replies; 17+ messages in thread From: Sami Mujawar @ 2023-12-18 15:12 UTC (permalink / raw) To: devel, sahil; +Cc: Ard Biesheuvel, Leif Lindholm, nd@arm.com Hi Sahil, Please see my response inline marked [SAMI]. Regards, Sami Mujawar On 16/11/2023 11:45 am, sahil via groups.io wrote: > Enable SCP QSPI flash region access by adding it in the PlatformLibMem > > Signed-off-by: sahil <sahil@arm.com> > --- > Silicon/ARM/NeoverseN1Soc/Include/NeoverseN1Soc.h | 6 +++++- > Silicon/ARM/NeoverseN1Soc/Library/PlatformLib/PlatformLibMem.c | 10 ++++++++-- > 2 files changed, 13 insertions(+), 3 deletions(-) > > diff --git a/Silicon/ARM/NeoverseN1Soc/Include/NeoverseN1Soc.h b/Silicon/ARM/NeoverseN1Soc/Include/NeoverseN1Soc.h > index 097160c7e2d1..92b8c9c45775 100644 > --- a/Silicon/ARM/NeoverseN1Soc/Include/NeoverseN1Soc.h > +++ b/Silicon/ARM/NeoverseN1Soc/Include/NeoverseN1Soc.h > @@ -1,6 +1,6 @@ > /** @file > > * > > -* Copyright (c) 2018 - 2020, ARM Limited. All rights reserved. > > +* Copyright (c) 2018 - 2023, ARM Limited. All rights reserved. > > * > > * SPDX-License-Identifier: BSD-2-Clause-Patent > > * > > @@ -41,6 +41,10 @@ > #define NEOVERSEN1SOC_EXP_PERIPH_BASE0 0x1C000000 > > #define NEOVERSEN1SOC_EXP_PERIPH_BASE0_SZ 0x1300000 > > > > +// SCP QSPI flash device > > +#define NEOVERSEN1SOC_SCP_QSPI_AHB_BASE 0x18000000 > > +#define NEOVERSEN1SOC_SCP_QSPI_AHB_SZ 0x2000000 [SAMI] Can you elaborate what is meant by 'SCP', please? Does this mean the flash is shared by SCP and AP? It would be good to clarify that in the commit message. Also, if you can add a reference to the relevant document in the file header it would be of great help. [/SAMI] > > + > > // Base address to a structure of type NEOVERSEN1SOC_PLAT_INFO which is > > // pre-populated by a earlier boot stage > > #define NEOVERSEN1SOC_PLAT_INFO_STRUCT_BASE (NEOVERSEN1SOC_NON_SECURE_SRAM_BASE + \ > > diff --git a/Silicon/ARM/NeoverseN1Soc/Library/PlatformLib/PlatformLibMem.c b/Silicon/ARM/NeoverseN1Soc/Library/PlatformLib/PlatformLibMem.c > index 9e8a1efc557d..eb099953fe29 100644 > --- a/Silicon/ARM/NeoverseN1Soc/Library/PlatformLib/PlatformLibMem.c > +++ b/Silicon/ARM/NeoverseN1Soc/Library/PlatformLib/PlatformLibMem.c > @@ -1,6 +1,6 @@ > /** @file > > > > - Copyright (c) 2018 - 2021, ARM Limited. All rights reserved.<BR> > > + Copyright (c) 2018 - 2023, ARM Limited. All rights reserved.<BR> > > > > SPDX-License-Identifier: BSD-2-Clause-Patent > > > > @@ -13,7 +13,7 @@ > #include <NeoverseN1Soc.h> > > > > // The total number of descriptors, including the final "end-of-table" descriptor. > > -#define MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS 19 > > +#define MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS 20 > > > > /** > > Returns the Virtual Memory Map of the platform. > > @@ -184,6 +184,12 @@ ArmPlatformGetVirtualMemoryMap ( > VirtualMemoryTable[Index].Length = NEOVERSEN1SOC_EXP_PERIPH_BASE0_SZ; > > VirtualMemoryTable[Index].Attributes = ARM_MEMORY_REGION_ATTRIBUTE_DEVICE; > > > > + // SCP QSPI flash device > > + VirtualMemoryTable[++Index].PhysicalBase = NEOVERSEN1SOC_SCP_QSPI_AHB_BASE; > > + VirtualMemoryTable[Index].VirtualBase = NEOVERSEN1SOC_SCP_QSPI_AHB_BASE; > > + VirtualMemoryTable[Index].Length = NEOVERSEN1SOC_SCP_QSPI_AHB_SZ; > > + VirtualMemoryTable[Index].Attributes = ARM_MEMORY_REGION_ATTRIBUTE_DEVICE; > > + > > if (PlatInfo->MultichipMode == 1) { > > //Remote DDR (2GB) > > VirtualMemoryTable[++Index].PhysicalBase = PcdGet64 (PcdExtMemorySpace) + > -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#112643): https://edk2.groups.io/g/devel/message/112643 Mute This Topic: https://groups.io/mt/102625033/7686176 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io] -=-=-=-=-=-=-=-=-=-=-=- ^ permalink raw reply [flat|nested] 17+ messages in thread
* [edk2-devel] [edk2-platforms][PATCH V1 2/5] Silicon/ARM/NeoverseN1Soc: NOR flash library for N1Sdp 2023-11-16 11:45 [edk2-devel] [edk2-platforms][PATCH V1 0/5] Enable non volatile storage on N1SDP sahil 2023-11-16 11:45 ` [edk2-devel] [edk2-platforms][PATCH V1 1/5] Silicon/ARM/NeoverseN1Soc: Enable SCP QSPI flash region sahil @ 2023-11-16 11:45 ` sahil 2023-12-07 12:01 ` Thomas Abraham 2023-12-18 15:12 ` Sami Mujawar 2023-11-16 11:45 ` [edk2-devel] [edk2-platforms][PATCH V1 3/5] Platform/ARM/N1Sdp: NOR flash Dxe Driver " sahil ` (2 subsequent siblings) 4 siblings, 2 replies; 17+ messages in thread From: sahil @ 2023-11-16 11:45 UTC (permalink / raw) To: devel; +Cc: Ard Biesheuvel, Leif Lindholm, Sami Mujawar, Sahil Add NOR flash library, this library provides APIs for getting the list of NOR flash devices on the platform. Signed-off-by: sahil <sahil@arm.com> --- Silicon/ARM/NeoverseN1Soc/Library/NorFlashLib/NorFlashLib.inf | 36 ++++++++++++++ Silicon/ARM/NeoverseN1Soc/Library/NorFlashLib/NorFlashLib.c | 52 ++++++++++++++++++++ 2 files changed, 88 insertions(+) diff --git a/Silicon/ARM/NeoverseN1Soc/Library/NorFlashLib/NorFlashLib.inf b/Silicon/ARM/NeoverseN1Soc/Library/NorFlashLib/NorFlashLib.inf new file mode 100644 index 000000000000..14f81125c4e1 --- /dev/null +++ b/Silicon/ARM/NeoverseN1Soc/Library/NorFlashLib/NorFlashLib.inf @@ -0,0 +1,36 @@ +## @file +# NOR flash lib for ARM Neoverse N1 platform. +# +# Copyright (c) 2023, ARM Limited. All rights reserved.<BR> +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x0001001B + BASE_NAME = NorFlashNeoverseN1SocLib + FILE_GUID = 7006fcf1-a585-4272-92e3-b286b1dff5bb + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = NorFlashPlatformLib + +[Sources.common] + NorFlashLib.c + +[Packages] + MdeModulePkg/MdeModulePkg.dec + MdePkg/MdePkg.dec + Platform/ARM/ARM.dec + Silicon/ARM/NeoverseN1Soc/NeoverseN1Soc.dec + +[LibraryClasses] + BaseLib + DebugLib + IoLib + +[FixedPcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize diff --git a/Silicon/ARM/NeoverseN1Soc/Library/NorFlashLib/NorFlashLib.c b/Silicon/ARM/NeoverseN1Soc/Library/NorFlashLib/NorFlashLib.c new file mode 100644 index 000000000000..a508d7d77373 --- /dev/null +++ b/Silicon/ARM/NeoverseN1Soc/Library/NorFlashLib/NorFlashLib.c @@ -0,0 +1,52 @@ +/** @file +* NOR flash lib for ARM Neoverse N1 platform +* +* Copyright (c) 2023, ARM Limited. All rights reserved.<BR> +* +* SPDX-License-Identifier: BSD-2-Clause-Patent +* +**/ + +#include <Library/DebugLib.h> +#include <Library/IoLib.h> +#include <Library/NorFlashPlatformLib.h> +#include <NeoverseN1Soc.h> +#include <PiDxe.h> + +#define FW_ENV_REGION_BASE FixedPcdGet32 (PcdFlashNvStorageVariableBase) +#define FW_ENV_REGION_SIZE (FixedPcdGet32 (PcdFlashNvStorageVariableSize) + \ + FixedPcdGet32 (PcdFlashNvStorageFtwWorkingSize) + \ + FixedPcdGet32 (PcdFlashNvStorageFtwSpareSize)) + +STATIC NOR_FLASH_DESCRIPTION mNorFlashDevices[] = { + { + /// Environment variable region + NEOVERSEN1SOC_SCP_QSPI_AHB_BASE, ///< device base + FW_ENV_REGION_BASE, ///< region base + FW_ENV_REGION_SIZE, ///< region size + SIZE_4KB, ///< block size + }, +}; + +/** + Get NOR flash region info + + @param[out] NorFlashDevices NOR flash regions info. + @param[out] Count number of flash instance. + + @retval EFI_SUCCESS Success. +**/ +EFI_STATUS +NorFlashPlatformGetDevices ( + OUT NOR_FLASH_DESCRIPTION **NorFlashDevices, + OUT UINT32 *Count + ) +{ + if ((NorFlashDevices == NULL) || (Count == NULL)) { + return EFI_INVALID_PARAMETER; + } + + *NorFlashDevices = mNorFlashDevices; + *Count = ARRAY_SIZE (mNorFlashDevices); + return EFI_SUCCESS; +} -- 2.25.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#111309): https://edk2.groups.io/g/devel/message/111309 Mute This Topic: https://groups.io/mt/102625034/7686176 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io] -=-=-=-=-=-=-=-=-=-=-=- ^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [edk2-devel] [edk2-platforms][PATCH V1 2/5] Silicon/ARM/NeoverseN1Soc: NOR flash library for N1Sdp 2023-11-16 11:45 ` [edk2-devel] [edk2-platforms][PATCH V1 2/5] Silicon/ARM/NeoverseN1Soc: NOR flash library for N1Sdp sahil @ 2023-12-07 12:01 ` Thomas Abraham 2023-12-18 15:12 ` Sami Mujawar 1 sibling, 0 replies; 17+ messages in thread From: Thomas Abraham @ 2023-12-07 12:01 UTC (permalink / raw) To: devel@edk2.groups.io, Sahil Kaushal Cc: Ard Biesheuvel, Leif Lindholm, Sami Mujawar, Chandni Cherukuri, nd Hi Sahil, > -----Original Message----- > From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of sahil via > groups.io > Sent: Thursday, November 16, 2023 11:46 AM > To: devel@edk2.groups.io > Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>; Leif Lindholm > <quic_llindhol@quicinc.com>; Sami Mujawar <Sami.Mujawar@arm.com>; > Sahil Kaushal <Sahil.Kaushal@arm.com> > Subject: [edk2-devel] [edk2-platforms][PATCH V1 2/5] > Silicon/ARM/NeoverseN1Soc: NOR flash library for N1Sdp > > Add NOR flash library, this library provides APIs for getting the list > of NOR flash devices on the platform. > > Signed-off-by: sahil <sahil@arm.com> > --- > Silicon/ARM/NeoverseN1Soc/Library/NorFlashLib/NorFlashLib.inf | 36 > ++++++++++++++ > Silicon/ARM/NeoverseN1Soc/Library/NorFlashLib/NorFlashLib.c | 52 > ++++++++++++++++++++ > 2 files changed, 88 insertions(+) > > diff --git a/Silicon/ARM/NeoverseN1Soc/Library/NorFlashLib/NorFlashLib.inf > b/Silicon/ARM/NeoverseN1Soc/Library/NorFlashLib/NorFlashLib.inf > new file mode 100644 > index 000000000000..14f81125c4e1 > --- /dev/null > +++ b/Silicon/ARM/NeoverseN1Soc/Library/NorFlashLib/NorFlashLib.inf > @@ -0,0 +1,36 @@ > +## @file > > +# NOR flash lib for ARM Neoverse N1 platform. > > +# > > +# Copyright (c) 2023, ARM Limited. All rights reserved.<BR> > > +# > > +# SPDX-License-Identifier: BSD-2-Clause-Patent > > +# > > +## > > + > > +[Defines] > > + INF_VERSION = 0x0001001B > > + BASE_NAME = NorFlashNeoverseN1SocLib > > + FILE_GUID = 7006fcf1-a585-4272-92e3-b286b1dff5bb > > + MODULE_TYPE = DXE_DRIVER > > + VERSION_STRING = 1.0 > > + LIBRARY_CLASS = NorFlashPlatformLib > > + > > +[Sources.common] > > + NorFlashLib.c > > + > > +[Packages] > > + MdeModulePkg/MdeModulePkg.dec > > + MdePkg/MdePkg.dec > > + Platform/ARM/ARM.dec > > + Silicon/ARM/NeoverseN1Soc/NeoverseN1Soc.dec > > + > > +[LibraryClasses] > > + BaseLib > > + DebugLib > > + IoLib > > + > > +[FixedPcd] > > + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize > > + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize > > + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase > > + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize > > diff --git a/Silicon/ARM/NeoverseN1Soc/Library/NorFlashLib/NorFlashLib.c > b/Silicon/ARM/NeoverseN1Soc/Library/NorFlashLib/NorFlashLib.c > new file mode 100644 > index 000000000000..a508d7d77373 > --- /dev/null > +++ b/Silicon/ARM/NeoverseN1Soc/Library/NorFlashLib/NorFlashLib.c > @@ -0,0 +1,52 @@ > +/** @file > > +* NOR flash lib for ARM Neoverse N1 platform > > +* > > +* Copyright (c) 2023, ARM Limited. All rights reserved.<BR> > > +* > > +* SPDX-License-Identifier: BSD-2-Clause-Patent > > +* > > +**/ > > + > > +#include <Library/DebugLib.h> > > +#include <Library/IoLib.h> > > +#include <Library/NorFlashPlatformLib.h> > > +#include <NeoverseN1Soc.h> > > +#include <PiDxe.h> > > + > > +#define FW_ENV_REGION_BASE FixedPcdGet32 > (PcdFlashNvStorageVariableBase) > > +#define FW_ENV_REGION_SIZE (FixedPcdGet32 > (PcdFlashNvStorageVariableSize) + \ > > + FixedPcdGet32 (PcdFlashNvStorageFtwWorkingSize) + \ > > + FixedPcdGet32 (PcdFlashNvStorageFtwSpareSize)) Why is FtwWorkingSize and FtwSpareSize included in the calculation of the size? Are these not offsets inside a flash region? > > + > > +STATIC NOR_FLASH_DESCRIPTION mNorFlashDevices[] = { > > + { > > + /// Environment variable region > > + NEOVERSEN1SOC_SCP_QSPI_AHB_BASE, ///< device base > > + FW_ENV_REGION_BASE, ///< region base > > + FW_ENV_REGION_SIZE, ///< region size > > + SIZE_4KB, ///< block size > > + }, > > +}; > > + > > +/** > > + Get NOR flash region info > > + > > + @param[out] NorFlashDevices NOR flash regions info. > > + @param[out] Count number of flash instance. > > + > > + @retval EFI_SUCCESS Success. > > +**/ > > +EFI_STATUS > > +NorFlashPlatformGetDevices ( > > + OUT NOR_FLASH_DESCRIPTION **NorFlashDevices, > > + OUT UINT32 *Count > > + ) > > +{ > > + if ((NorFlashDevices == NULL) || (Count == NULL)) { > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + *NorFlashDevices = mNorFlashDevices; > > + *Count = ARRAY_SIZE (mNorFlashDevices); > > + return EFI_SUCCESS; > > +} > > -- > 2.25.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#112184): https://edk2.groups.io/g/devel/message/112184 Mute This Topic: https://groups.io/mt/102625034/7686176 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io] -=-=-=-=-=-=-=-=-=-=-=- ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [edk2-devel] [edk2-platforms][PATCH V1 2/5] Silicon/ARM/NeoverseN1Soc: NOR flash library for N1Sdp 2023-11-16 11:45 ` [edk2-devel] [edk2-platforms][PATCH V1 2/5] Silicon/ARM/NeoverseN1Soc: NOR flash library for N1Sdp sahil 2023-12-07 12:01 ` Thomas Abraham @ 2023-12-18 15:12 ` Sami Mujawar 1 sibling, 0 replies; 17+ messages in thread From: Sami Mujawar @ 2023-12-18 15:12 UTC (permalink / raw) To: sahil, devel; +Cc: Ard Biesheuvel, Leif Lindholm, nd@arm.com [-- Attachment #1: Type: text/plain, Size: 5104 bytes --] Hi Sahil, Please find my feedback marked inline as [SAMI]. With those fixed, Reviewed-by: Sami Mujawar <sami.mujawar@arm.com> Regards, Sami Mujawar On 16/11/2023 11:45 am, sahil wrote: > Add NOR flash library, this library provides APIs for getting the list > of NOR flash devices on the platform. > > Signed-off-by: sahil<sahil@arm.com> > --- > Silicon/ARM/NeoverseN1Soc/Library/NorFlashLib/NorFlashLib.inf | 36 ++++++++++++++ > Silicon/ARM/NeoverseN1Soc/Library/NorFlashLib/NorFlashLib.c | 52 ++++++++++++++++++++ > 2 files changed, 88 insertions(+) > > diff --git a/Silicon/ARM/NeoverseN1Soc/Library/NorFlashLib/NorFlashLib.inf b/Silicon/ARM/NeoverseN1Soc/Library/NorFlashLib/NorFlashLib.inf > new file mode 100644 > index 000000000000..14f81125c4e1 > --- /dev/null > +++ b/Silicon/ARM/NeoverseN1Soc/Library/NorFlashLib/NorFlashLib.inf > @@ -0,0 +1,36 @@ > +## @file > > +# NOR flash lib for ARM Neoverse N1 platform. > > +# > > +# Copyright (c) 2023, ARM Limited. All rights reserved.<BR> > > +# > > +# SPDX-License-Identifier: BSD-2-Clause-Patent > > +# > > +## > > + > > +[Defines] > > + INF_VERSION = 0x0001001B > > + BASE_NAME = NorFlashNeoverseN1SocLib > > + FILE_GUID = 7006fcf1-a585-4272-92e3-b286b1dff5bb > > + MODULE_TYPE = DXE_DRIVER > > + VERSION_STRING = 1.0 > > + LIBRARY_CLASS = NorFlashPlatformLib [SAMI] Since this library class is NorFlashPlatformLib, you need to implement NorFlashPlatformInitialization(). A platform may not need to do anything in NorFlashPlatformInitialization() and just return success. [/SAMI] > > + > > +[Sources.common] > > + NorFlashLib.c > > + > > +[Packages] > > + MdeModulePkg/MdeModulePkg.dec > > + MdePkg/MdePkg.dec > > + Platform/ARM/ARM.dec > > + Silicon/ARM/NeoverseN1Soc/NeoverseN1Soc.dec > > + > > +[LibraryClasses] > > + BaseLib > > + DebugLib > > + IoLib > > + > > +[FixedPcd] > > + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize > > + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize > > + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase > > + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize > > diff --git a/Silicon/ARM/NeoverseN1Soc/Library/NorFlashLib/NorFlashLib.c b/Silicon/ARM/NeoverseN1Soc/Library/NorFlashLib/NorFlashLib.c > new file mode 100644 > index 000000000000..a508d7d77373 > --- /dev/null > +++ b/Silicon/ARM/NeoverseN1Soc/Library/NorFlashLib/NorFlashLib.c > @@ -0,0 +1,52 @@ > +/** @file > > +* NOR flash lib for ARM Neoverse N1 platform > > +* > > +* Copyright (c) 2023, ARM Limited. All rights reserved.<BR> > > +* > > +* SPDX-License-Identifier: BSD-2-Clause-Patent > > +* > > +**/ > > + > > +#include <Library/DebugLib.h> > > +#include <Library/IoLib.h> > > +#include <Library/NorFlashPlatformLib.h> > > +#include <NeoverseN1Soc.h> > > +#include <PiDxe.h> > > + > > +#define FW_ENV_REGION_BASE FixedPcdGet32 (PcdFlashNvStorageVariableBase) > > +#define FW_ENV_REGION_SIZE (FixedPcdGet32 (PcdFlashNvStorageVariableSize) + \ > > + FixedPcdGet32 (PcdFlashNvStorageFtwWorkingSize) + \ > > + FixedPcdGet32 (PcdFlashNvStorageFtwSpareSize)) [SAMI] Please limit line length to 80 characters. Also run uncrustify. > > + > > +STATIC NOR_FLASH_DESCRIPTION mNorFlashDevices[] = { > > + { > > + /// Environment variable region > > + NEOVERSEN1SOC_SCP_QSPI_AHB_BASE, ///< device base > > + FW_ENV_REGION_BASE, ///< region base > > + FW_ENV_REGION_SIZE, ///< region size > > + SIZE_4KB, ///< block size > > + }, > > +}; > > + > > +/** > > + Get NOR flash region info > > + > > + @param[out] NorFlashDevices NOR flash regions info. > > + @param[out] Count number of flash instance. > > + > > + @retval EFI_SUCCESS Success. [SAMI] EFI_INVALID_PARAMETER ? > > +**/ > > +EFI_STATUS > > +NorFlashPlatformGetDevices ( > > + OUT NOR_FLASH_DESCRIPTION **NorFlashDevices, > > + OUT UINT32 *Count > > + ) > > +{ > > + if ((NorFlashDevices == NULL) || (Count == NULL)) { > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + *NorFlashDevices = mNorFlashDevices; > > + *Count = ARRAY_SIZE (mNorFlashDevices); > > + return EFI_SUCCESS; > > +} > -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#112642): https://edk2.groups.io/g/devel/message/112642 Mute This Topic: https://groups.io/mt/102625034/7686176 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io] -=-=-=-=-=-=-=-=-=-=-=- [-- Attachment #2: Type: text/html, Size: 6549 bytes --] ^ permalink raw reply [flat|nested] 17+ messages in thread
* [edk2-devel] [edk2-platforms][PATCH V1 3/5] Platform/ARM/N1Sdp: NOR flash Dxe Driver for N1Sdp 2023-11-16 11:45 [edk2-devel] [edk2-platforms][PATCH V1 0/5] Enable non volatile storage on N1SDP sahil 2023-11-16 11:45 ` [edk2-devel] [edk2-platforms][PATCH V1 1/5] Silicon/ARM/NeoverseN1Soc: Enable SCP QSPI flash region sahil 2023-11-16 11:45 ` [edk2-devel] [edk2-platforms][PATCH V1 2/5] Silicon/ARM/NeoverseN1Soc: NOR flash library for N1Sdp sahil @ 2023-11-16 11:45 ` sahil 2023-12-07 14:46 ` Thomas Abraham ` (2 more replies) 2023-11-16 11:45 ` [edk2-devel] [edk2-platforms][PATCH V1 4/5] Platform/ARM/N1Sdp: Persistent storage " sahil 2023-11-16 11:45 ` [edk2-devel] [edk2-platforms][PATCH V1 5/5] Platform/ARM/N1Sdp: Enable FaultTolerantWrite Dxe driver " sahil 4 siblings, 3 replies; 17+ messages in thread From: sahil @ 2023-11-16 11:45 UTC (permalink / raw) To: devel; +Cc: Ard Biesheuvel, Leif Lindholm, Sami Mujawar, Sahil Add NOR flash DXE driver, this brings up NV storage on QSPI's flash device using FVB protocol. Signed-off-by: sahil <sahil@arm.com> --- Platform/ARM/N1Sdp/N1SdpPlatform.dec | 5 +- Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiDxe.inf | 72 ++ Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiReg.h | 33 + Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/NorFlash.h | 491 +++++++++ Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiDxe.c | 409 ++++++++ Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/NorFlash.c | 1100 ++++++++++++++++++++ Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/NorFlashFvb.c | 647 ++++++++++++ 7 files changed, 2756 insertions(+), 1 deletion(-) diff --git a/Platform/ARM/N1Sdp/N1SdpPlatform.dec b/Platform/ARM/N1Sdp/N1SdpPlatform.dec index 16937197b8e8..67b5f4c871b6 100644 --- a/Platform/ARM/N1Sdp/N1SdpPlatform.dec +++ b/Platform/ARM/N1Sdp/N1SdpPlatform.dec @@ -1,7 +1,7 @@ ## @file # Describes the N1Sdp configuration. # -# Copyright (c) 2021, ARM Limited. All rights reserved.<BR> +# Copyright (c) 2021-2023, ARM Limited. All rights reserved.<BR> # # SPDX-License-Identifier: BSD-2-Clause-Patent ## @@ -89,3 +89,6 @@ # unmapped reserved region results in a DECERR response. # gArmN1SdpTokenSpaceGuid.PcdCsComponentSize|0x1000|UINT32|0x00000049 + + # Base address of Cadence QSPI controller configuration registers + gArmN1SdpTokenSpaceGuid.PcdCadenceQspiDxeRegBaseAddress|0x1C0C0000|UINT32|0x0000004A diff --git a/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiDxe.inf b/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiDxe.inf new file mode 100644 index 000000000000..62a4944c95db --- /dev/null +++ b/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiDxe.inf @@ -0,0 +1,72 @@ +## @file +# NOR flash DXE +# +# Copyright (c) 2023, ARM Limited. All rights reserved.<BR> +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x0001001B + BASE_NAME = CadenceQspiDxe + FILE_GUID = CC8A9713-4442-4A6C-B389-8B46490A0641 + MODULE_TYPE = DXE_RUNTIME_DRIVER + VERSION_STRING = 0.1 + ENTRY_POINT = NorFlashInitialise + +[Sources] + CadenceQspiDxe.c + CadenceQspiReg.h + NorFlash.c + NorFlash.h + NorFlashFvb.c + +[Packages] + EmbeddedPkg/EmbeddedPkg.dec + MdeModulePkg/MdeModulePkg.dec + MdePkg/MdePkg.dec + Platform/ARM/ARM.dec + Platform/ARM/N1Sdp/N1SdpPlatform.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + DebugLib + DevicePathLib + DxeServicesTableLib + HobLib + IoLib + MemoryAllocationLib + NorFlashInfoLib + NorFlashPlatformLib + TimerLib + UefiBootServicesTableLib + UefiDriverEntryPoint + UefiLib + UefiRuntimeLib + UefiRuntimeServicesTableLib + +[Guids] + gEdkiiNvVarStoreFormattedGuid + gEfiAuthenticatedVariableGuid + gEfiEventVirtualAddressChangeGuid + gEfiSystemNvDataFvGuid + gEfiVariableGuid + gEfiGlobalVariableGuid + +[Protocols] + gEfiDevicePathProtocolGuid + gEfiFirmwareVolumeBlockProtocolGuid + +[FixedPcd] + gArmN1SdpTokenSpaceGuid.PcdCadenceQspiDxeRegBaseAddress + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize + +[Depex] + gEfiCpuArchProtocolGuid diff --git a/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiReg.h b/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiReg.h new file mode 100644 index 000000000000..535e6d738d31 --- /dev/null +++ b/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiReg.h @@ -0,0 +1,33 @@ +/** @file + + Copyright (c) 2023, ARM Limited. All rights reserved.<BR> + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef CADENCE_QSPI_REG_H_ +#define CADENCE_QSPI_REG_H_ + +// QSPI Controller defines +#define CDNS_QSPI_FLASH_CMD_CTRL_REG_OFFSET 0x90 +#define CDNS_QSPI_FLASH_CMD_CTRL_REG_EXECUTE 0x01 +#define CDNS_QSPI_FLASH_CMD_CTRL_REG_ADDR_ENABLE 0x01 +#define CDNS_QSPI_FLASH_CMD_CTRL_REG_ADDR_BIT_POS 19 +#define CDNS_QSPI_FLASH_CMD_CTRL_REG_ADDR_BYTE_BIT_POS 16 +#define CDNS_QSPI_FLASH_CMD_CTRL_REG_STATUS_BIT 0x02 +#define CDNS_QSPI_FLASH_CMD_CTRL_REG_OPCODE_BIT_POS 24 +#define CDNS_QSPI_FLASH_CMD_CTRL_REG_READ_ENABLE 0x01 +#define CDNS_QSPI_FLASH_CMD_CTRL_REG_READ_BYTE_3B 0x02 +#define CDNS_QSPI_FLASH_CMD_CTRL_REG_READEN_BIT_POS 23 +#define CDNS_QSPI_FLASH_CMD_CTRL_REG_READBYTE_BIT_POS 20 +#define CDNS_QSPI_FLASH_CMD_CTRL_REG_DUMMY_8C 0x8 +#define CDNS_QSPI_FLASH_CMD_CTRL_REG_DUMMY_BIT_POS 7 +#define CDNS_QSPI_FLASH_CMD_CTRL_REG_NUM_DATA_BYTES(x) ((x - 1) << CDNS_QSPI_FLASH_CMD_CTRL_REG_READBYTE_BIT_POS) +#define CDNS_QSPI_FLASH_CMD_CTRL_REG_NUM_ADDR_BYTES(x) ((x - 1) << CDNS_QSPI_FLASH_CMD_CTRL_REG_ADDR_BYTE_BIT_POS) + +#define CDNS_QSPI_FLASH_CMD_READ_DATA_REG_OFFSET 0xA0 + +#define CDNS_QSPI_FLASH_CMD_ADDR_REG_OFFSET 0x94 + +#endif /* CADENCE_QSPI_REG_H_ */ diff --git a/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/NorFlash.h b/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/NorFlash.h new file mode 100644 index 000000000000..38ae1c2fae89 --- /dev/null +++ b/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/NorFlash.h @@ -0,0 +1,491 @@ +/** @file + + Copyright (c) 2023, ARM Limited. All rights reserved.<BR> + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef NOR_FLASH_DXE_H_ +#define NOR_FLASH_DXE_H_ + +#include <Guid/EventGroup.h> +#include <Library/DebugLib.h> +#include <Library/IoLib.h> +#include <Library/NorFlashPlatformLib.h> +#include <PiDxe.h> +#include <Protocol/BlockIo.h> +#include <Protocol/DiskIo.h> +#include <Protocol/FirmwareVolumeBlock.h> + +#include "CadenceQspiReg.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('S', 'n', 'o', 'r') +#define INSTANCE_FROM_FVB_THIS(a) CR(a, NOR_FLASH_INSTANCE, FvbProtocol, \ + NOR_FLASH_SIGNATURE) + +#define NOR_FLASH_POLL_FSR BIT0 + +typedef struct _NOR_FLASH_INSTANCE NOR_FLASH_INSTANCE; + +typedef EFI_STATUS (*NOR_FLASH_INITIALIZE) ( + NOR_FLASH_INSTANCE *Instance + ); + +#pragma pack(1) +typedef struct { + VENDOR_DEVICE_PATH Vendor; + UINT8 Index; + EFI_DEVICE_PATH_PROTOCOL End; +} NOR_FLASH_DEVICE_PATH; +#pragma pack() + +struct _NOR_FLASH_INSTANCE { + UINT32 Signature; + EFI_HANDLE Handle; + + BOOLEAN Initialized; + NOR_FLASH_INITIALIZE Initialize; + + UINTN HostRegisterBaseAddress; + UINTN DeviceBaseAddress; + UINTN RegionBaseAddress; + UINTN Size; + UINTN BlockSize; + UINTN LastBlock; + EFI_LBA StartLba; + EFI_LBA OffsetLba; + + EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL FvbProtocol; + VOID *ShadowBuffer; + + NOR_FLASH_DEVICE_PATH DevicePath; + + UINT32 Flags; +}; + +typedef struct { + EFI_TPL OriginalTPL; + BOOLEAN InterruptsEnabled; +} NOR_FLASH_LOCK_CONTEXT; + +/** + Lock all pending read/write to Nor flash device + + @param[in] Context Nor flash device context structure. +**/ +VOID +EFIAPI +NorFlashLock ( + IN NOR_FLASH_LOCK_CONTEXT *Context + ); + +/** + Unlock all pending read/write to Nor flash device + + @param[in] Context Nor flash device context structure. +**/ +VOID +EFIAPI +NorFlashUnlock ( + IN NOR_FLASH_LOCK_CONTEXT *Context + ); + +extern UINTN mFlashNvStorageVariableBase; + +/** + Create Nor flash Instance for given region. + + @param[in] HostRegisterBase Base address of Nor flash controller. + @param[in] NorFlashDeviceBase Base address of flash device. + @param[in] NorFlashRegionBase Base address of flash region on device. + @param[in] NorFlashSize Size of flash region. + @param[in] Index Index of given flash region. + @param[in] BlockSize Block size of NOR flash device. + @param[in] HasVarStore Boolean set for VarStore on given region. + @param[out] NorFlashInstance Instance of given flash region. + + @retval EFI_SUCCESS On successful creation of NOR flash instance. +**/ +EFI_STATUS +NorFlashCreateInstance ( + IN UINTN HostRegisterBase, + IN UINTN NorFlashDeviceBase, + IN UINTN NorFlashRegionBase, + IN UINTN NorFlashSize, + IN UINT32 Index, + IN UINT32 BlockSize, + IN BOOLEAN HasVarStore, + OUT NOR_FLASH_INSTANCE **NorFlashInstance + ); + +/** + Install Fv block on to variable store region + + @param[in] Instance Instance of Nor flash variable region. + + @retval EFI_SUCCESS The entry point is executed successfully. +**/ +EFI_STATUS +EFIAPI +NorFlashFvbInitialize ( + IN NOR_FLASH_INSTANCE *Instance + ); + +/** + Check the integrity of firmware volume header. + + @param[in] Instance Instance of Nor flash variable region. + + @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 + ); + +/** + Initialize the FV Header and Variable Store Header + to support variable operations. + + @param[in] Instance Location to Initialize the headers + + @retval EFI_SUCCESS Fv init is done + +**/ +EFI_STATUS +InitializeFvAndVariableStoreHeaders ( + IN NOR_FLASH_INSTANCE *Instance + ); + +/** + Retrieves the attributes and current settings of the block. + + @param[in] This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance. + + @param[out] 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 + ); + +/** + Sets configurable firmware volume attributes and returns the + new settings of the firmware volume. + + + @param[in] This EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance. + + @param[in, out] Attributes On input, Attributes is a pointer to + EFI_FVB_ATTRIBUTES_2 that contains the desired + firmware volume settings. + On successful return, it contains the new + settings of the firmware volume. + + @retval EFI_UNSUPPORTED The firmware volume attributes are not supported. + +**/ +EFI_STATUS +EFIAPI +FvbSetAttributes ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, + IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes + ); + +/** + Retrieves the base address of a memory-mapped firmware volume. + This function should be called only for memory-mapped firmware volumes. + + @param[in] This EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance. + + @param[out] 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. + +**/ +EFI_STATUS +EFIAPI +FvbGetPhysicalAddress ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, + OUT EFI_PHYSICAL_ADDRESS *Address + ); + +/** + 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[in] This EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance. + + @param[in] Lba Indicates the block whose size to return + + @param[out] BlockSize Pointer to a caller-allocated UINTN in which + the size of the block is returned. + + @param[out] 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 + ); + +/** + 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. + + @param[in] This EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance. + + @param[in] Lba The starting logical block index from which to read + + @param[in] Offset Offset into the block at which to begin reading. + + @param[in, out] NumBytes Pointer to a UINTN. + At entry, *NumBytes contains the total size of the + buffer. *NumBytes should have a non zero value. + At exit, *NumBytes contains the total number of + bytes read. + + @param[in out] 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. + + @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 + ); + +/** + Writes the specified number of bytes from the input buffer to the block. + + @param[in] This EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance. + + @param[in] Lba The starting logical block index to write to. + + @param[in] Offset Offset into the block at which to begin writing. + + @param[in, out] 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[in] Buffer The pointer to a caller-allocated buffer that + contains the source for the write. + + @retval EFI_SUCCESS The firmware volume was written successfully. + +**/ +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 + ); + +/** + Erases and initialises a firmware volume block. + + @param[in] This EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL + + @param[in] ... The variable argument list is a list of tuples. + Each tuple describes a range of LBAs to erase + and consists of the following: + - An EFI_LBA that indicates the starting LBA + - A UINTN that indicates the number of blocks + to erase. + + The list is terminated with an + EFI_LBA_LIST_TERMINATOR. + + @retval EFI_SUCCESS The erase request successfully completed. + + @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisabled + state. + + @retval EFI_DEVICE_ERROR The block device is not functioning correctly + and could not be written. + The firmware device may have been partially + erased. + + @retval EFI_INVALID_PARAMETER One or more of the LBAs listed in the variable + argument list do not exist in the firmware + volume. + +**/ +EFI_STATUS +EFIAPI +FvbEraseBlocks ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, + ... + ); + +/** + This function unlock and erase an entire NOR Flash block. + + @param[in] Instance NOR flash Instance of variable store region. + @param[in] BlockAddress Block address within the variable store region. + + @retval EFI_SUCCESS The erase and unlock successfully completed. +**/ +EFI_STATUS +NorFlashUnlockAndEraseSingleBlock ( + IN NOR_FLASH_INSTANCE *Instance, + IN UINTN BlockAddress + ); + +/** + Write a full or portion of a block. + + @param[in] Instance NOR flash Instance of variable store region. + @param[in] Lba The starting logical block index to write to. + @param[in] Offset Offset into the block at which to begin writing. + @param[in,out] NumBytes The total size of the buffer. + @param[in] Buffer The pointer to a caller-allocated buffer that + contains the source for the write. + + @retval EFI_SUCCESS The write is completed. +**/ +EFI_STATUS +NorFlashWriteSingleBlock ( + IN NOR_FLASH_INSTANCE *Instance, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer + ); + +/** + Write a full block. + + @param[in] Instance NOR flash Instance of variable store region. + @param[in] Lba The starting logical block index to write to. + @param[in] BufferSizeInBytes The number of bytes to write. + @param[in] Buffer The pointer to a caller-allocated buffer that + contains the source for the write. + + @retval EFI_SUCCESS The write is completed. +**/ +EFI_STATUS +NorFlashWriteBlocks ( + IN NOR_FLASH_INSTANCE *Instance, + IN EFI_LBA Lba, + IN UINTN BufferSizeInBytes, + IN VOID *Buffer + ); + +/** + Read a full block. + + @param[in] Instance NOR flash Instance of variable store region. + @param[in] Lba The starting logical block index to read from. + @param[in] BufferSizeInBytes The number of bytes to read. + @param[out] Buffer The pointer to a caller-allocated buffer that + should be copied with read data. + + @retval EFI_SUCCESS The read is completed. +**/ +EFI_STATUS +NorFlashReadBlocks ( + IN NOR_FLASH_INSTANCE *Instance, + IN EFI_LBA Lba, + IN UINTN BufferSizeInBytes, + OUT VOID *Buffer + ); + +/** + Read from nor flash. + + @param[in] Instance NOR flash Instance of variable store region. + @param[in] Lba The starting logical block index to read from. + @param[in] Offset Offset into the block at which to begin reading. + @param[in] BufferSizeInBytes The number of bytes to read. + @param[out] Buffer The pointer to a caller-allocated buffer that + should copied with read data. + + @retval EFI_SUCCESS The read is completed. +**/ +EFI_STATUS +NorFlashRead ( + IN NOR_FLASH_INSTANCE *Instance, + IN EFI_LBA Lba, + IN UINTN Offset, + IN UINTN BufferSizeInBytes, + OUT VOID *Buffer + ); + +/** + Read JEDEC ID of NOR flash device. + + @param[in] Instance NOR flash Instance of variable store region. + @param[out] JedecId JEDEC ID of NOR flash device. + + @retval EFI_SUCCESS The write is completed. +**/ +EFI_STATUS +NorFlashReadID ( + IN NOR_FLASH_INSTANCE *Instance, + OUT UINT8 JedecId[3] + ); + +#define SPINOR_SR_WIP BIT0 // Write in progress + +#define SPINOR_OP_WREN 0x06 // Write enable +#define SPINOR_OP_BE_4K 0x20 // Erase 4KiB block +#define SPINOR_OP_RDID 0x9f // Read JEDEC ID +#define SPINOR_OP_RDSR 0x05 // Read status register + +#define SPINOR_SR_WIP_POLL_TIMEOUT_MS 1000u // Status Register read timeout + +#endif /* NOR_FLASH_DXE_H_ */ diff --git a/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiDxe.c b/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiDxe.c new file mode 100644 index 000000000000..fffe689161a6 --- /dev/null +++ b/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiDxe.c @@ -0,0 +1,409 @@ +/** @file + NOR flash DXE + + Copyright (c) 2023, ARM Limited. All rights reserved.<BR> + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include <Library/BaseMemoryLib.h> +#include <Library/DxeServicesTableLib.h> +#include <Library/HobLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/NorFlashInfoLib.h> +#include <Library/PcdLib.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Library/UefiLib.h> +#include <Library/UefiRuntimeLib.h> +#include <Library/UefiRuntimeServicesTableLib.h> + +#include "NorFlash.h" + +STATIC NOR_FLASH_INSTANCE **mNorFlashInstances; +STATIC UINT32 mNorFlashDeviceCount; + +STATIC EFI_EVENT mNorFlashVirtualAddrChangeEvent; + +/** + Install Fv block onto variable store region + + @param[in] Instance Instance of Nor flash variable region. + + @retval EFI_SUCCESS The entry point is executed successfully. +**/ +EFI_STATUS +EFIAPI +NorFlashFvbInitialize ( + IN NOR_FLASH_INSTANCE *Instance + ) +{ + EFI_STATUS Status; + UINT32 FvbNumLba; + EFI_BOOT_MODE BootMode; + UINTN RuntimeMmioRegionSize; + UINTN RuntimeMmioDeviceSize; + UINTN BlockSize; + + DEBUG ((DEBUG_INFO, "NorFlashFvbInitialize\n")); + + BlockSize = Instance->BlockSize; + + // FirmwareVolumeHeader->FvLength is declared to have the Variable area + // AND the FTW working area AND the FTW Spare contiguous. + ASSERT ( + PcdGet32 (PcdFlashNvStorageVariableBase) + + PcdGet32 (PcdFlashNvStorageVariableSize) == + PcdGet32 (PcdFlashNvStorageFtwWorkingBase) + ); + ASSERT ( + PcdGet32 (PcdFlashNvStorageFtwWorkingBase) + + PcdGet32 (PcdFlashNvStorageFtwWorkingSize) == + PcdGet32 (PcdFlashNvStorageFtwSpareBase) + ); + + // Check if the size of the area is at least one block size. + ASSERT ( + (PcdGet32 (PcdFlashNvStorageVariableSize) > 0) && + (PcdGet32 (PcdFlashNvStorageVariableSize) / BlockSize > 0) + ); + ASSERT ( + (PcdGet32 (PcdFlashNvStorageFtwWorkingSize) > 0) && + (PcdGet32 (PcdFlashNvStorageFtwWorkingSize) / BlockSize > 0) + ); + ASSERT ( + (PcdGet32 (PcdFlashNvStorageFtwSpareSize) > 0) && + (PcdGet32 (PcdFlashNvStorageFtwSpareSize) / BlockSize > 0) + ); + + // Ensure the Variable areas are aligned on block size boundaries. + ASSERT ((PcdGet32 (PcdFlashNvStorageVariableBase) % BlockSize) == 0); + ASSERT ((PcdGet32 (PcdFlashNvStorageFtwWorkingBase) % BlockSize) == 0); + ASSERT ((PcdGet32 (PcdFlashNvStorageFtwSpareBase) % BlockSize) == 0); + + Instance->Initialized = TRUE; + mFlashNvStorageVariableBase = FixedPcdGet32 (PcdFlashNvStorageVariableBase); + + // Set the index of the first LBA for the FVB. + Instance->StartLba = (PcdGet32 (PcdFlashNvStorageVariableBase) - + Instance->RegionBaseAddress) / 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", __func__)); + DEBUG (( + DEBUG_INFO, + "%a: Installing a correct one for this volume.\n", + __func__ + )); + + // Erase all the NorFlash that is reserved for variable storage. + FvbNumLba = (PcdGet32 (PcdFlashNvStorageVariableSize) + + PcdGet32 (PcdFlashNvStorageFtwWorkingSize) + + PcdGet32 (PcdFlashNvStorageFtwSpareSize)) / + Instance->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; + } + + // validate FV header again if FV was created successfully. + Status = ValidateFvHeader (Instance); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "ValidateFvHeader is failed \n")); + return Status; + } + } + + // The driver implementing the variable read service can now be dispatched; + // the varstore headers are in place. + Status = gBS->InstallProtocolInterface ( + &gImageHandle, + &gEdkiiNvVarStoreFormattedGuid, + EFI_NATIVE_INTERFACE, + NULL + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "%a: Failed to install gEdkiiNvVarStoreFormattedGuid\n", + __func__ + )); + return Status; + } + + // Declare the Non-Volatile storage as EFI_MEMORY_RUNTIME. + RuntimeMmioRegionSize = Instance->Size; + RuntimeMmioDeviceSize = Instance->RegionBaseAddress - Instance->DeviceBaseAddress; + + Status = gDS->AddMemorySpace ( + EfiGcdMemoryTypeMemoryMappedIo, + Instance->RegionBaseAddress, + RuntimeMmioRegionSize, + EFI_MEMORY_UC | EFI_MEMORY_RUNTIME + ); + ASSERT_EFI_ERROR (Status); + + Status = gDS->AddMemorySpace ( + EfiGcdMemoryTypeMemoryMappedIo, + Instance->DeviceBaseAddress, + RuntimeMmioDeviceSize, + EFI_MEMORY_UC | EFI_MEMORY_RUNTIME + ); + ASSERT_EFI_ERROR (Status); + + Status = gDS->SetMemorySpaceAttributes ( + Instance->RegionBaseAddress, + RuntimeMmioRegionSize, + EFI_MEMORY_UC | EFI_MEMORY_RUNTIME + ); + ASSERT_EFI_ERROR (Status); + + Status = gDS->SetMemorySpaceAttributes ( + Instance->DeviceBaseAddress, + RuntimeMmioDeviceSize, + EFI_MEMORY_UC | EFI_MEMORY_RUNTIME + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +/** + Fixup internal data so that EFI can be called in virtual mode. + convert any pointers in lib to virtual mode. + + @param[in] Event The Event that is being processed + @param[in] Context Event Context +**/ +STATIC +VOID +EFIAPI +NorFlashVirtualNotifyEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + UINTN Index; + + EfiConvertPointer (0x0, (VOID **)&mFlashNvStorageVariableBase); + + for (Index = 0; Index < mNorFlashDeviceCount; Index++) { + EfiConvertPointer ( + 0x0, + (VOID **)&mNorFlashInstances[Index]->HostRegisterBaseAddress + ); + EfiConvertPointer ( + 0x0, + (VOID **)&mNorFlashInstances[Index]->DeviceBaseAddress + ); + EfiConvertPointer ( + 0x0, + (VOID **)&mNorFlashInstances[Index]->RegionBaseAddress + ); + + // 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); + } + } +} + +/** + Entrypoint of Platform Nor flash DXE driver + + @param[in] ImageHandle The firmware allocated handle for the EFI image. + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The entry point is executed successfully. +**/ +EFI_STATUS +EFIAPI +NorFlashInitialise ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS HostRegisterBaseAddress; + UINT32 Index; + NOR_FLASH_DESCRIPTION *NorFlashDevices; + BOOLEAN ContainVariableStorage; + + HostRegisterBaseAddress = PcdGet32 (PcdCadenceQspiDxeRegBaseAddress); + + Status = gDS->AddMemorySpace ( + EfiGcdMemoryTypeMemoryMappedIo, + HostRegisterBaseAddress, + SIZE_64KB, + EFI_MEMORY_UC | EFI_MEMORY_RUNTIME + ); + ASSERT_EFI_ERROR (Status); + + Status = gDS->SetMemorySpaceAttributes ( + HostRegisterBaseAddress, + SIZE_64KB, + EFI_MEMORY_UC | EFI_MEMORY_RUNTIME + ); + ASSERT_EFI_ERROR (Status); + + // Initialize NOR flash instances. + Status = NorFlashPlatformGetDevices (&NorFlashDevices, &mNorFlashDeviceCount); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "NorFlashInitialise: Fail to get Nor Flash devices\n")); + return Status; + } + + mNorFlashInstances = AllocateRuntimePool ( + sizeof (NOR_FLASH_INSTANCE *) * + mNorFlashDeviceCount + ); + + if (mNorFlashInstances == NULL) { + DEBUG (( + DEBUG_ERROR, + "NorFlashInitialise: Failed to allocate mem for NorFlashInstance\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 <= + PcdGet32 (PcdFlashNvStorageVariableBase)) && + (PcdGet32 (PcdFlashNvStorageVariableBase) + + PcdGet32 (PcdFlashNvStorageVariableSize) <= + NorFlashDevices[Index].RegionBaseAddress + NorFlashDevices[Index].Size); + + Status = NorFlashCreateInstance ( + HostRegisterBaseAddress, + NorFlashDevices[Index].DeviceBaseAddress, + NorFlashDevices[Index].RegionBaseAddress, + NorFlashDevices[Index].Size, + Index, + NorFlashDevices[Index].BlockSize, + ContainVariableStorage, + &mNorFlashInstances[Index] + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "NorFlashInitialise: Fail to create instance for NorFlash[%d]\n", + Index + )); + continue; + } + + Status = gBS->InstallMultipleProtocolInterfaces ( + &mNorFlashInstances[Index]->Handle, + &gEfiDevicePathProtocolGuid, + &mNorFlashInstances[Index]->DevicePath, + &gEfiFirmwareVolumeBlockProtocolGuid, + &mNorFlashInstances[Index]->FvbProtocol, + NULL + ); + ASSERT_EFI_ERROR (Status); + } + + // Register for the virtual address change event. + Status = gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + NorFlashVirtualNotifyEvent, + NULL, + &gEfiEventVirtualAddressChangeGuid, + &mNorFlashVirtualAddrChangeEvent + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +/** + Lock all pending read/write to Nor flash device + + @param[in] Context Nor flash device context structure. +**/ +VOID +EFIAPI +NorFlashLock ( + IN NOR_FLASH_LOCK_CONTEXT *Context + ) +{ + if (!EfiAtRuntime ()) { + // Raise TPL to TPL_HIGH to stop anyone from interrupting us. + Context->OriginalTPL = gBS->RaiseTPL (TPL_HIGH_LEVEL); + } else { + Context->InterruptsEnabled = SaveAndDisableInterrupts (); + } +} + +/** + Unlock all pending read/write to Nor flash device + + @param[in] Context Nor flash device context structure. +**/ +VOID +EFIAPI +NorFlashUnlock ( + IN NOR_FLASH_LOCK_CONTEXT *Context + ) +{ + if (!EfiAtRuntime ()) { + // Interruptions can resume. + gBS->RestoreTPL (Context->OriginalTPL); + } else if (Context->InterruptsEnabled) { + SetInterruptState (TRUE); + } +} diff --git a/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/NorFlash.c b/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/NorFlash.c new file mode 100644 index 000000000000..be7b626c5697 --- /dev/null +++ b/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/NorFlash.c @@ -0,0 +1,1100 @@ +/** @file + + Copyright (c) 2023 ARM Limited. All rights reserved.<BR> + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include <Library/BaseMemoryLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/NorFlashInfoLib.h> +#include <Library/PcdLib.h> +#include <Library/TimerLib.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Library/UefiLib.h> + +#include "NorFlash.h" + +STATIC CONST NOR_FLASH_INSTANCE mNorFlashInstanceTemplate = { + NOR_FLASH_SIGNATURE, // Signature + NULL, // Handle + + FALSE, // Initialized + NULL, // Initialize + + 0, // HostRegisterBaseAddress + 0, // DeviceBaseAddress + 0, // RegionBaseAddress + 0, // Size + 0, // BlockSize + 0, // LastBlock + 0, // StartLba + 0, // OffsetLba + + { + FvbGetAttributes, // GetAttributes + FvbSetAttributes, // SetAttributes + FvbGetPhysicalAddress, // GetPhysicalAddress + FvbGetBlockSize, // GetBlockSize + FvbRead, // Read + FvbWrite, // Write + FvbEraseBlocks, // EraseBlocks + NULL, // ParentHandle + }, // FvbProtoccol; + NULL, // ShadowBuffer + + { + { + { + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP, + { + (UINT8)(OFFSET_OF (NOR_FLASH_DEVICE_PATH, End)), + (UINT8)(OFFSET_OF (NOR_FLASH_DEVICE_PATH, End) >> 8) + } + }, + { 0x0, 0x0, 0x0, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } + }, + }, + 0, // Index + + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { sizeof (EFI_DEVICE_PATH_PROTOCOL), 0 } + } + }, // DevicePath + 0 // Flags +}; + +/** + Execute Flash cmd ctrl and Read Status. + + @param[in] Instance NOR flash Instance. + @param[in] Val Value to be written to Flash cmd ctrl Register. + + @retval EFI_SUCCESS Request is executed successfully. + +**/ +STATIC +EFI_STATUS +CdnsQspiExecuteCommand ( + IN NOR_FLASH_INSTANCE *Instance, + IN UINT32 Val + ) +{ + // Set the command + MmioWrite32 ( + Instance->HostRegisterBaseAddress + CDNS_QSPI_FLASH_CMD_CTRL_REG_OFFSET, + Val + ); + // Execute the command + MmioWrite32 ( + Instance->HostRegisterBaseAddress + CDNS_QSPI_FLASH_CMD_CTRL_REG_OFFSET, + Val | CDNS_QSPI_FLASH_CMD_CTRL_REG_EXECUTE + ); + + // Wait until command has been executed + while ((MmioRead32 (Instance->HostRegisterBaseAddress + CDNS_QSPI_FLASH_CMD_CTRL_REG_OFFSET) + & CDNS_QSPI_FLASH_CMD_CTRL_REG_STATUS_BIT) == CDNS_QSPI_FLASH_CMD_CTRL_REG_STATUS_BIT) + { + continue; + } + + return EFI_SUCCESS; +} + +/** + Create Nor flash Instance for given region. + + @param[in] HostRegisterBase Base address of Nor flash controller. + @param[in] NorFlashDeviceBase Base address of flash device. + @param[in] NorFlashRegionBase Base address of flash region on device. + @param[in] NorFlashSize Size of flash region. + @param[in] Index Index of given flash region. + @param[in] BlockSize Block size of NOR flash device. + @param[in] HasVarStore Boolean set for VarStore on given region. + @param[out] NorFlashInstance Instance of given flash region. + + @retval EFI_SUCCESS On successful creation of NOR flash instance. +**/ +EFI_STATUS +NorFlashCreateInstance ( + IN UINTN HostRegisterBase, + IN UINTN NorFlashDeviceBase, + IN UINTN NorFlashRegionBase, + IN UINTN NorFlashSize, + IN UINT32 Index, + IN UINT32 BlockSize, + IN BOOLEAN HasVarStore, + OUT NOR_FLASH_INSTANCE **NorFlashInstance + ) +{ + EFI_STATUS Status; + NOR_FLASH_INSTANCE *Instance; + NOR_FLASH_INFO *FlashInfo; + UINT8 JedecId[3]; + + ASSERT (NorFlashInstance != NULL); + Instance = AllocateRuntimeCopyPool ( + sizeof (mNorFlashInstanceTemplate), + &mNorFlashInstanceTemplate + ); + if (Instance == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Instance->HostRegisterBaseAddress = HostRegisterBase; + Instance->DeviceBaseAddress = NorFlashDeviceBase; + Instance->RegionBaseAddress = NorFlashRegionBase; + Instance->Size = NorFlashSize; + Instance->BlockSize = BlockSize; + Instance->LastBlock = (NorFlashSize / BlockSize) - 1; + + Instance->OffsetLba = (NorFlashRegionBase - NorFlashDeviceBase) / BlockSize; + + CopyGuid (&Instance->DevicePath.Vendor.Guid, &gEfiCallerIdGuid); + Instance->DevicePath.Index = (UINT8)Index; + + Status = NorFlashReadID (Instance, JedecId); + if (EFI_ERROR (Status)) { + goto FreeInstance; + } + + Status = NorFlashGetInfo (JedecId, &FlashInfo, TRUE); + if (EFI_ERROR (Status)) { + goto FreeInstance; + } + + NorFlashPrintInfo (FlashInfo); + + Instance->Flags = 0; + if (FlashInfo->Flags & NOR_FLASH_WRITE_FSR) { + Instance->Flags = NOR_FLASH_POLL_FSR; + } + + Instance->ShadowBuffer = AllocateRuntimePool (BlockSize); + if (Instance->ShadowBuffer == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto FreeInstance; + } + + if (HasVarStore) { + Instance->Initialize = NorFlashFvbInitialize; + } + + *NorFlashInstance = Instance; + FreePool (FlashInfo); + return EFI_SUCCESS; + +FreeInstance: + FreePool (Instance); + return Status; +} + +/** + Converts milliseconds into number of ticks of the performance counter. + + @param[in] Milliseconds Milliseconds to convert into ticks. + + @retval Milliseconds expressed as number of ticks. + +**/ +STATIC +UINT64 +MilliSecondsToTicks ( + IN UINTN Milliseconds + ) +{ + CONST UINT64 NanoSecondsPerTick = GetTimeInNanoSecond (1); + + return (Milliseconds * 1000000) / NanoSecondsPerTick; +} + +/** + Poll Status register for NOR flash erase/write completion. + + @param[in] Instance NOR flash Instance. + + @retval EFI_SUCCESS Request is executed successfully. + @retval EFI_TIMEOUT Operation timed out. + @retval EFI_DEVICE_ERROR Controller operartion failed. + +**/ +STATIC +EFI_STATUS +NorFlashPollStatusRegister ( + IN NOR_FLASH_INSTANCE *Instance + ) +{ + BOOLEAN SRegDone; + UINT32 val; + + val = SPINOR_OP_RDSR << CDNS_QSPI_FLASH_CMD_CTRL_REG_OPCODE_BIT_POS | + CDNS_QSPI_FLASH_CMD_CTRL_REG_READ_ENABLE << CDNS_QSPI_FLASH_CMD_CTRL_REG_READEN_BIT_POS | + CDNS_QSPI_FLASH_CMD_CTRL_REG_NUM_DATA_BYTES (1) | + CDNS_QSPI_FLASH_CMD_CTRL_REG_DUMMY_8C << CDNS_QSPI_FLASH_CMD_CTRL_REG_DUMMY_BIT_POS; + + CONST UINT64 TickOut = + GetPerformanceCounter () + MilliSecondsToTicks (SPINOR_SR_WIP_POLL_TIMEOUT_MS); + + do { + if (GetPerformanceCounter () > TickOut) { + DEBUG (( + DEBUG_ERROR, + "NorFlashPollStatusRegister: Timeout waiting for erase/write.\n" + )); + return EFI_TIMEOUT; + } + + if (EFI_ERROR (CdnsQspiExecuteCommand (Instance, val))) { + return EFI_DEVICE_ERROR; + } + + SRegDone = + (MmioRead8 (Instance->HostRegisterBaseAddress + CDNS_QSPI_FLASH_CMD_READ_DATA_REG_OFFSET) + & SPINOR_SR_WIP) == 0; + } while (!SRegDone); + + return EFI_SUCCESS; +} + +/** + Check whether NOR flash opertions are Locked. + + @param[in] Instance NOR flash Instance. + @param[in] BlockAddress BlockAddress in NOR flash device. + + @retval FALSE If NOR flash is not locked. +**/ +STATIC +BOOLEAN +NorFlashBlockIsLocked ( + IN NOR_FLASH_INSTANCE *Instance, + IN UINTN BlockAddress + ) +{ + return FALSE; +} + +/** + Unlock NOR flash operations on given block. + + @param[in] Instance NOR flash instance. + @param[in] BlockAddress BlockAddress in NOR flash device. + + @retval EFI_SUCCESS NOR flash operations is unlocked. +**/ +STATIC +EFI_STATUS +NorFlashUnlockSingleBlock ( + IN NOR_FLASH_INSTANCE *Instance, + IN UINTN BlockAddress + ) +{ + return EFI_SUCCESS; +} + +/** + Unlock NOR flash operations if it is necessary. + + @param[in] Instance NOR flash instance. + @param[in] BlockAddress BlockAddress in NOR flash device. + + @retval EFI_SUCCESS Request is executed successfully. +**/ +STATIC +EFI_STATUS +NorFlashUnlockSingleBlockIfNecessary ( + IN NOR_FLASH_INSTANCE *Instance, + IN UINTN BlockAddress + ) +{ + EFI_STATUS Status; + + Status = EFI_SUCCESS; + + if (!NorFlashBlockIsLocked (Instance, BlockAddress)) { + Status = NorFlashUnlockSingleBlock (Instance, BlockAddress); + } + + return Status; +} + +/** + Enable write to NOR flash device. + + @param[in] Instance NOR flash instance. + + @retval EFI_SUCCESS Request is executed successfully. +**/ +STATIC +EFI_STATUS +NorFlashEnableWrite ( + IN NOR_FLASH_INSTANCE *Instance + ) +{ + UINT32 val; + + DEBUG ((DEBUG_INFO, "NorFlashEnableWrite()\n")); + val = (SPINOR_OP_WREN << CDNS_QSPI_FLASH_CMD_CTRL_REG_OPCODE_BIT_POS); + if (EFI_ERROR (CdnsQspiExecuteCommand (Instance, val))) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +/** + The following function presumes that the block has already been unlocked. + + @param[in] Instance NOR flash instance. + @param[in] BlockAddress Block address within the variable region. + + @retval EFI_SUCCESS Request is executed successfully. + **/ +EFI_STATUS +NorFlashEraseSingleBlock ( + IN NOR_FLASH_INSTANCE *Instance, + IN UINTN BlockAddress + ) +{ + UINT32 DevConfigVal; + UINT32 EraseOffset; + + EraseOffset = 0x0; + + DEBUG (( + DEBUG_INFO, + "NorFlashEraseSingleBlock(BlockAddress=0x%08x)\n", + BlockAddress + )); + + if (EFI_ERROR (NorFlashEnableWrite (Instance))) { + return EFI_DEVICE_ERROR; + } + + EraseOffset = BlockAddress - Instance->DeviceBaseAddress; + + MmioWrite32 ( + Instance->HostRegisterBaseAddress + CDNS_QSPI_FLASH_CMD_ADDR_REG_OFFSET, + EraseOffset + ); + + DevConfigVal = SPINOR_OP_BE_4K << CDNS_QSPI_FLASH_CMD_CTRL_REG_OPCODE_BIT_POS | + CDNS_QSPI_FLASH_CMD_CTRL_REG_ADDR_ENABLE << CDNS_QSPI_FLASH_CMD_CTRL_REG_ADDR_BIT_POS | + CDNS_QSPI_FLASH_CMD_CTRL_REG_NUM_ADDR_BYTES (3); + + if (EFI_ERROR (CdnsQspiExecuteCommand (Instance, DevConfigVal))) { + return EFI_DEVICE_ERROR; + } + + if (EFI_ERROR (NorFlashPollStatusRegister (Instance))) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +/** + This function unlock and erase an entire NOR Flash block. + + @param[in] Instance NOR flash Instance of variable store region. + @param[in] BlockAddress Block address within the variable store region. + + @retval EFI_SUCCESS The erase and unlock successfully completed. +**/ +EFI_STATUS +NorFlashUnlockAndEraseSingleBlock ( + IN NOR_FLASH_INSTANCE *Instance, + IN UINTN BlockAddress + ) +{ + EFI_STATUS Status; + UINTN Index; + NOR_FLASH_LOCK_CONTEXT Lock; + + NorFlashLock (&Lock); + + Index = 0; + do { + // Unlock the block if we have to + Status = NorFlashUnlockSingleBlockIfNecessary (Instance, BlockAddress); + if (EFI_ERROR (Status)) { + break; + } + + Status = NorFlashEraseSingleBlock (Instance, BlockAddress); + if (EFI_ERROR (Status)) { + break; + } + + Index++; + } while ((Index < NOR_FLASH_ERASE_RETRY) && (Status == EFI_WRITE_PROTECTED)); + + if (Index == NOR_FLASH_ERASE_RETRY) { + DEBUG (( + DEBUG_ERROR, + "EraseSingleBlock(BlockAddress=0x%08x: Block Locked Error (try to erase %d times)\n", + BlockAddress, + Index + )); + } + + NorFlashUnlock (&Lock); + + return Status; +} + +/** + Write a single word to given location. + + @param[in] Instance NOR flash Instance of variable store region. + @param[in] WordAddress The address in NOR flash to write given word. + @param[in] WriteData The data to write into NOR flash location. + + @retval EFI_SUCCESS The write is completed. +**/ +STATIC +EFI_STATUS +NorFlashWriteSingleWord ( + IN NOR_FLASH_INSTANCE *Instance, + IN UINTN WordAddress, + IN UINT32 WriteData + ) +{ + DEBUG (( + DEBUG_INFO, + "NorFlashWriteSingleWord(WordAddress=0x%08x, WriteData=0x%08x)\n", + WordAddress, + WriteData + )); + + if (EFI_ERROR (NorFlashEnableWrite (Instance))) { + return EFI_DEVICE_ERROR; + } + + MmioWrite32 (WordAddress, WriteData); + if (EFI_ERROR (NorFlashPollStatusRegister (Instance))) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +/** + Write a full block to given location. + + @param[in] Instance NOR flash Instance of variable store region. + @param[in] Lba The logical block address in NOR flash. + @param[in] DataBuffer The data to write into NOR flash location. + @param[in] BlockSizeInWords The number of bytes to write. + + @retval EFI_SUCCESS The write is completed. +**/ +STATIC +EFI_STATUS +NorFlashWriteFullBlock ( + IN NOR_FLASH_INSTANCE *Instance, + IN EFI_LBA Lba, + IN UINT32 *DataBuffer, + IN UINT32 BlockSizeInWords + ) +{ + EFI_STATUS Status; + UINTN WordAddress; + UINT32 WordIndex; + UINTN BlockAddress; + NOR_FLASH_LOCK_CONTEXT Lock; + + Status = EFI_SUCCESS; + + // Get the physical address of the block + BlockAddress = GET_NOR_BLOCK_ADDRESS ( + Instance->RegionBaseAddress, + Lba, + BlockSizeInWords * 4 + ); + + // Start writing from the first address at the start of the block + WordAddress = BlockAddress; + + NorFlashLock (&Lock); + + Status = NorFlashUnlockAndEraseSingleBlock (Instance, BlockAddress); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "WriteSingleBlock: ERROR - Failed to Unlock and Erase the single block at 0x%X\n", + BlockAddress + )); + goto EXIT; + } + + for (WordIndex = 0; + WordIndex < BlockSizeInWords; + WordIndex++, DataBuffer++, WordAddress += 4) + { + Status = NorFlashWriteSingleWord (Instance, WordAddress, *DataBuffer); + if (EFI_ERROR (Status)) { + goto EXIT; + } + } + +EXIT: + NorFlashUnlock (&Lock); + + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "NOR FLASH Programming [WriteSingleBlock] failed at address 0x%08x. Exit Status = %r.\n", + WordAddress, + Status + )); + } + + return Status; +} + +/** + Write a full block. + + @param[in] Instance NOR flash Instance of variable store region. + @param[in] Lba The starting logical block index. + @param[in] BufferSizeInBytes The number of bytes to read. + @param[in] Buffer The pointer to a caller-allocated buffer that + contains the source for the write. + + @retval EFI_SUCCESS The write is completed. +**/ +EFI_STATUS +NorFlashWriteBlocks ( + IN NOR_FLASH_INSTANCE *Instance, + IN EFI_LBA Lba, + IN UINTN BufferSizeInBytes, + IN VOID *Buffer + ) +{ + UINT32 *pWriteBuffer; + EFI_STATUS Status; + EFI_LBA CurrentBlock; + UINT32 BlockSizeInWords; + UINT32 NumBlocks; + UINT32 BlockCount; + + Status = EFI_SUCCESS; + // The buffer must be valid + if (Buffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + // We must have some bytes to read + DEBUG (( + DEBUG_INFO, + "NorFlashWriteBlocks: BufferSizeInBytes=0x%x\n", + BufferSizeInBytes + )); + if (BufferSizeInBytes == 0) { + return EFI_BAD_BUFFER_SIZE; + } + + // The size of the buffer must be a multiple of the block size + DEBUG (( + DEBUG_INFO, + "NorFlashWriteBlocks: BlockSize in bytes =0x%x\n", + Instance->BlockSize + )); + if ((BufferSizeInBytes % Instance->BlockSize) != 0) { + return EFI_BAD_BUFFER_SIZE; + } + + // All blocks must be within the device + NumBlocks = ((UINT32)BufferSizeInBytes) / Instance->BlockSize; + + DEBUG (( + DEBUG_INFO, + "NorFlashWriteBlocks: NumBlocks=%d, LastBlock=%ld, Lba=%ld.\n", + NumBlocks, + Instance->LastBlock, + Lba + )); + + if ((Lba + NumBlocks) > (Instance->LastBlock + 1)) { + DEBUG (( + DEBUG_ERROR, + "NorFlashWriteBlocks: ERROR - Write will exceed last block.\n" + )); + return EFI_INVALID_PARAMETER; + } + + ASSERT (((UINTN)Buffer % sizeof (UINT32)) == 0); + + BlockSizeInWords = Instance->BlockSize / 4; + + // 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 *ReadBuffer + pWriteBuffer = (UINT32 *)Buffer; + + CurrentBlock = Lba; + for (BlockCount = 0; + BlockCount < NumBlocks; + BlockCount++, CurrentBlock++, pWriteBuffer += BlockSizeInWords) + { + DEBUG (( + DEBUG_INFO, + "NorFlashWriteBlocks: Writing block #%d\n", + (UINTN)CurrentBlock + )); + + Status = NorFlashWriteFullBlock ( + Instance, + CurrentBlock, + pWriteBuffer, + BlockSizeInWords + ); + + if (EFI_ERROR (Status)) { + break; + } + } + + DEBUG ((DEBUG_INFO, "NorFlashWriteBlocks: Exit Status = %r.\n", Status)); + return Status; +} + +/** + Read a full block. + + @param[in] Instance NOR flash Instance of variable store region. + @param[in] Lba The starting logical block index to read from. + @param[in] BufferSizeInBytes The number of bytes to read. + @param[out] Buffer The pointer to a caller-allocated buffer that + should be copied with read data. + + @retval EFI_SUCCESS The read is completed. +**/ +EFI_STATUS +NorFlashReadBlocks ( + IN NOR_FLASH_INSTANCE *Instance, + IN EFI_LBA Lba, + IN UINTN BufferSizeInBytes, + OUT VOID *Buffer + ) +{ + UINT32 NumBlocks; + UINTN StartAddress; + + DEBUG (( + DEBUG_INFO, + "NorFlashReadBlocks: BufferSize=0x%xB BlockSize=0x%xB LastBlock=%ld, Lba=%ld.\n", + BufferSizeInBytes, + Instance->BlockSize, + Instance->LastBlock, + Lba + )); + + // The buffer must be valid + if (Buffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + // Return if we do not have any byte to read + if (BufferSizeInBytes == 0) { + return EFI_SUCCESS; + } + + // The size of the buffer must be a multiple of the block size + if ((BufferSizeInBytes % Instance->BlockSize) != 0) { + return EFI_BAD_BUFFER_SIZE; + } + + NumBlocks = ((UINT32)BufferSizeInBytes) / Instance->BlockSize; + + if ((Lba + NumBlocks) > (Instance->LastBlock + 1)) { + DEBUG (( + DEBUG_ERROR, + "NorFlashReadBlocks: ERROR - Read will exceed last block\n" + )); + return EFI_INVALID_PARAMETER; + } + + // Get the address to start reading from + StartAddress = GET_NOR_BLOCK_ADDRESS ( + Instance->RegionBaseAddress, + Lba, + Instance->BlockSize + ); + + // Readout the data + CopyMem (Buffer, (UINTN *)StartAddress, BufferSizeInBytes); + + return EFI_SUCCESS; +} + +/** + Read from nor flash. + + @param[in] Instance NOR flash Instance of variable store region. + @param[in] Lba The starting logical block index to read from. + @param[in] Offset Offset into the block at which to begin reading. + @param[in] BufferSizeInBytes The number of bytes to read. + @param[out] Buffer The pointer to a caller-allocated buffer that + should copied with read data. + + @retval EFI_SUCCESS The read is completed. +**/ +EFI_STATUS +NorFlashRead ( + IN NOR_FLASH_INSTANCE *Instance, + IN EFI_LBA Lba, + IN UINTN Offset, + IN UINTN BufferSizeInBytes, + OUT VOID *Buffer + ) +{ + UINTN StartAddress; + + // The buffer must be valid + if (Buffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + // Return if we do not have any byte to read + if (BufferSizeInBytes == 0) { + return EFI_SUCCESS; + } + + if (((Lba * Instance->BlockSize) + Offset + BufferSizeInBytes) > + Instance->Size) + { + DEBUG (( + DEBUG_ERROR, + "NorFlashRead: ERROR - Read will exceed device size.\n" + )); + return EFI_INVALID_PARAMETER; + } + + // Get the address to start reading from + StartAddress = GET_NOR_BLOCK_ADDRESS ( + Instance->RegionBaseAddress, + Lba, + Instance->BlockSize + ); + + // Readout the data + CopyMem (Buffer, (UINTN *)(StartAddress + Offset), BufferSizeInBytes); + + return EFI_SUCCESS; +} + +/** + Write a full or portion of a block. + + @param[in] Instance NOR flash Instance of variable store region. + @param[in] Lba The starting logical block index to write to. + @param[in] Offset Offset into the block at which to begin writing. + @param[in, out] NumBytes The total size of the buffer. + @param[in] Buffer The pointer to a caller-allocated buffer that + contains the source for the write. + + @retval EFI_SUCCESS The write is completed. +**/ +EFI_STATUS +NorFlashWriteSingleBlock ( + IN NOR_FLASH_INSTANCE *Instance, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer + ) +{ + EFI_STATUS Status; + UINT32 Tmp; + UINT32 TmpBuf; + UINT32 WordToWrite; + UINT32 Mask; + BOOLEAN DoErase; + UINTN BytesToWrite; + UINTN CurOffset; + UINTN WordAddr; + UINTN BlockSize; + UINTN BlockAddress; + UINTN PrevBlockAddress; + + if (Buffer == NULL) { + DEBUG (( + DEBUG_ERROR, + "NorFlashWriteSingleBlock: ERROR - Buffer is invalid\n" + )); + return EFI_OUT_OF_RESOURCES; + } + + PrevBlockAddress = 0; + if (!Instance->Initialized && Instance->Initialize) { + Instance->Initialize (Instance); + } + + DEBUG (( + DEBUG_INFO, + "NorFlashWriteSingleBlock(Parameters: Lba=%ld, Offset=0x%x, *NumBytes=0x%x, Buffer @ 0x%08x)\n", + Lba, + Offset, + *NumBytes, + Buffer + )); + + // Localise the block size to avoid de-referencing pointers all the time + BlockSize = Instance->BlockSize; + + // The write must not span block boundaries. + // We need to check each variable individually because adding two large + // values together overflows. + if ((Offset >= BlockSize) || + (*NumBytes > BlockSize) || + ((Offset + *NumBytes) > BlockSize)) + { + DEBUG (( + DEBUG_ERROR, + "NorFlashWriteSingleBlock: ERROR - EFI_BAD_BUFFER_SIZE: (Offset=0x%x + NumBytes=0x%x) > BlockSize=0x%x\n", + Offset, + *NumBytes, + BlockSize + )); + return EFI_BAD_BUFFER_SIZE; + } + + // We must have some bytes to write + if (*NumBytes == 0) { + DEBUG (( + DEBUG_ERROR, + "NorFlashWriteSingleBlock: ERROR - EFI_BAD_BUFFER_SIZE: (Offset=0x%x + NumBytes=0x%x) > BlockSize=0x%x\n", + Offset, + *NumBytes, + BlockSize + )); + return EFI_BAD_BUFFER_SIZE; + } + + // 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) { + // Check to see if we need to erase before programming the data into NOR. + // 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 = FALSE; + BytesToWrite = *NumBytes; + CurOffset = Offset; + + while (BytesToWrite > 0) { + // Read full word from NOR, splice as required. A word is the smallest + // unit we can write. + Status = NorFlashRead ( + Instance, + Lba, + CurOffset & ~(0x3), + sizeof (Tmp), + &Tmp + ); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + // Physical address of word in NOR to write. + WordAddr = (CurOffset & ~(0x3)) + + GET_NOR_BLOCK_ADDRESS ( + Instance->RegionBaseAddress, + Lba, + BlockSize + ); + + // The word of data that is to be written. + TmpBuf = ReadUnaligned32 ((UINT32 *)(Buffer + (*NumBytes - BytesToWrite))); + + // First do word aligned chunks. + if ((CurOffset & 0x3) == 0) { + if (BytesToWrite >= 4) { + // Is the destination still in 'erased' state? + if (~Tmp != 0) { + // Check to see if we are only changing bits to zero. + if ((Tmp ^ TmpBuf) & TmpBuf) { + DoErase = TRUE; + break; + } + } + + // Write this word to NOR + WordToWrite = TmpBuf; + CurOffset += sizeof (TmpBuf); + BytesToWrite -= sizeof (TmpBuf); + } else { + // BytesToWrite < 4. Do small writes and left-overs + Mask = ~((~0) << (BytesToWrite * 8)); + // Mask out the bytes we want. + TmpBuf &= Mask; + // Is the destination still in 'erased' state? + if ((Tmp & Mask) != Mask) { + // Check to see if we are only changing bits to zero. + if ((Tmp ^ TmpBuf) & TmpBuf) { + DoErase = TRUE; + break; + } + } + + // Merge old and new data. Write merged word to NOR + WordToWrite = (Tmp & ~Mask) | TmpBuf; + CurOffset += BytesToWrite; + BytesToWrite = 0; + } + } else { + // Do multiple words, but starting unaligned. + if (BytesToWrite > (4 - (CurOffset & 0x3))) { + Mask = ((~0) << ((CurOffset & 0x3) * 8)); + // Mask out the bytes we want. + TmpBuf &= Mask; + // Is the destination still in 'erased' state? + if ((Tmp & Mask) != Mask) { + // Check to see if we are only changing bits to zero. + if ((Tmp ^ TmpBuf) & TmpBuf) { + DoErase = TRUE; + break; + } + } + + // Merge old and new data. Write merged word to NOR + WordToWrite = (Tmp & ~Mask) | TmpBuf; + BytesToWrite -= (4 - (CurOffset & 0x3)); + CurOffset += (4 - (CurOffset & 0x3)); + } else { + // Unaligned and fits in one word. + Mask = (~((~0) << (BytesToWrite * 8))) << ((CurOffset & 0x3) * 8); + // Mask out the bytes we want. + TmpBuf = (TmpBuf << ((CurOffset & 0x3) * 8)) & Mask; + // Is the destination still in 'erased' state? + if ((Tmp & Mask) != Mask) { + // Check to see if we are only changing bits to zero. + if ((Tmp ^ TmpBuf) & TmpBuf) { + DoErase = TRUE; + break; + } + } + + // Merge old and new data. Write merged word to NOR + WordToWrite = (Tmp & ~Mask) | TmpBuf; + CurOffset += BytesToWrite; + BytesToWrite = 0; + } + } + + BlockAddress = GET_NOR_BLOCK_ADDRESS ( + Instance->RegionBaseAddress, + Lba, + BlockSize + ); + if (BlockAddress != PrevBlockAddress) { + Status = NorFlashUnlockSingleBlockIfNecessary (Instance, BlockAddress); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + PrevBlockAddress = BlockAddress; + } + + Status = NorFlashWriteSingleWord (Instance, WordAddr, WordToWrite); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + } + + // Exit if we got here and could write all the data. Otherwise do the + // Erase-Write cycle. + if (!DoErase) { + return EFI_SUCCESS; + } + } + + // 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; + } + + // Read NOR Flash data into shadow buffer + Status = NorFlashReadBlocks ( + Instance, + 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); + + // Write the modified buffer back to the NorFlash + Status = NorFlashWriteBlocks ( + Instance, + Lba, + BlockSize, + Instance->ShadowBuffer + ); + if (EFI_ERROR (Status)) { + // Return one of the pre-approved error statuses + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +/** + Read JEDEC ID of NOR flash device. + + @param[in] Instance NOR flash Instance of variable store region. + @param[out] JedecId JEDEC ID of NOR flash device. + + @retval EFI_SUCCESS The write is completed. +**/ +EFI_STATUS +NorFlashReadID ( + IN NOR_FLASH_INSTANCE *Instance, + OUT UINT8 JedecId[3] + ) +{ + UINT32 val; + + if ((Instance == NULL) || (JedecId == NULL)) { + return EFI_INVALID_PARAMETER; + } + + val = SPINOR_OP_RDID << CDNS_QSPI_FLASH_CMD_CTRL_REG_OPCODE_BIT_POS | + CDNS_QSPI_FLASH_CMD_CTRL_REG_READ_ENABLE << CDNS_QSPI_FLASH_CMD_CTRL_REG_READEN_BIT_POS | + CDNS_QSPI_FLASH_CMD_CTRL_REG_NUM_DATA_BYTES (3); + + if (EFI_ERROR (CdnsQspiExecuteCommand (Instance, val))) { + return EFI_DEVICE_ERROR; + } + + val = MmioRead32 (Instance->HostRegisterBaseAddress + CDNS_QSPI_FLASH_CMD_READ_DATA_REG_OFFSET); + + // Manu.ID field + JedecId[0] = (UINT8)val; + // Type field + JedecId[1] = (UINT8)(val >> 8); + // Capacity field + JedecId[2] = (UINT8)(val >> 16); + + DEBUG (( + DEBUG_INFO, + "Nor flash detected, Jedec ID, Manu.Id=%x Type=%x Capacity=%x \n", + JedecId[0], + JedecId[1], + JedecId[2] + )); + + return EFI_SUCCESS; +} diff --git a/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/NorFlashFvb.c b/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/NorFlashFvb.c new file mode 100644 index 000000000000..8281d4825dc9 --- /dev/null +++ b/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/NorFlashFvb.c @@ -0,0 +1,647 @@ +/** @file + + Copyright (c) 2023, ARM Limited. All rights reserved.<BR> + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include <Guid/VariableFormat.h> +#include <Guid/SystemNvDataGuid.h> + +#include <Library/BaseLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/PcdLib.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Library/UefiLib.h> + +#include <PiDxe.h> + +#include "NorFlash.h" + +UINTN mFlashNvStorageVariableBase; + +/** + Initialize the FV Header and Variable Store Header + to support variable operations. + + @param[in] Instance Location to initialise the headers. + + @retval EFI_SUCCESS Fv init is done. + +**/ +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); + + 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_FVB2_READ_ENABLED_CAP | + EFI_FVB2_READ_STATUS | + EFI_FVB2_STICKY_WRITE | + EFI_FVB2_MEMORY_MAPPED | + EFI_FVB2_ERASE_POLARITY | + EFI_FVB2_WRITE_STATUS | + EFI_FVB2_WRITE_ENABLED_CAP; + + FirmwareVolumeHeader->HeaderLength = sizeof (EFI_FIRMWARE_VOLUME_HEADER) + + sizeof (EFI_FV_BLOCK_MAP_ENTRY); + FirmwareVolumeHeader->Revision = EFI_FVH_REVISION; + FirmwareVolumeHeader->BlockMap[0].NumBlocks = Instance->LastBlock + 1; + FirmwareVolumeHeader->BlockMap[0].Length = Instance->BlockSize; + FirmwareVolumeHeader->BlockMap[1].NumBlocks = 0; + FirmwareVolumeHeader->BlockMap[1].Length = 0; + FirmwareVolumeHeader->Checksum = CalculateCheckSum16 ( + (UINT16 *)FirmwareVolumeHeader, + FirmwareVolumeHeader->HeaderLength + ); + + VariableStoreHeader = (VOID *)((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] Instance Instance of Nor flash variable region. + + @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 + ) +{ + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; + VARIABLE_STORE_HEADER *VariableStoreHeader; + UINTN VariableStoreLength; + UINTN FvLength; + + FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)Instance->RegionBaseAddress; + + FvLength = PcdGet32 (PcdFlashNvStorageVariableSize) + + PcdGet32 (PcdFlashNvStorageFtwWorkingSize) + + PcdGet32 (PcdFlashNvStorageFtwSpareSize); + + if ( (FwVolHeader->Revision != EFI_FVH_REVISION) + || (FwVolHeader->Signature != EFI_FVH_SIGNATURE) + || (FwVolHeader->FvLength != FvLength) + ) + { + DEBUG (( + DEBUG_ERROR, + "%a: No Firmware Volume header present\n", + __func__ + )); + return EFI_NOT_FOUND; + } + + // Check the Firmware Volume Guid + if (!CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiSystemNvDataFvGuid)) { + DEBUG (( + DEBUG_ERROR, + "%a: Firmware Volume Guid non-compatible\n", + __func__ + )); + return EFI_NOT_FOUND; + } + + VariableStoreHeader = (VOID *)((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", + __func__ + )); + return EFI_NOT_FOUND; + } + + VariableStoreLength = PcdGet32 (PcdFlashNvStorageVariableSize) - + FwVolHeader->HeaderLength; + if (VariableStoreHeader->Size != VariableStoreLength) { + DEBUG (( + DEBUG_ERROR, + "%a: Variable Store Length does not match\n", + __func__ + )); + return EFI_NOT_FOUND; + } + + return EFI_SUCCESS; +} + +/** + Retrieves the attributes and current settings of the block. + + @param[in] This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance. + + @param[out] 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; + + FlashFvbAttributes = EFI_FVB2_READ_ENABLED_CAP | EFI_FVB2_READ_STATUS | + EFI_FVB2_WRITE_ENABLED_CAP | EFI_FVB2_WRITE_STATUS | + EFI_FVB2_STICKY_WRITE | EFI_FVB2_MEMORY_MAPPED | + EFI_FVB2_ERASE_POLARITY; + + *Attributes = FlashFvbAttributes; + + DEBUG ((DEBUG_INFO, "FvbGetAttributes(0x%X)\n", *Attributes)); + + return EFI_SUCCESS; +} + +/** + Sets configurable firmware volume attributes and returns the + new settings of the firmware volume. + + + @param[in] This EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance. + + @param[in, out] Attributes On input, Attributes is a pointer to + EFI_FVB_ATTRIBUTES_2 that contains the desired + firmware volume settings. + On successful return, it contains the new + settings of the firmware volume. + + @retval EFI_UNSUPPORTED The firmware volume attributes are not supported. + +**/ +EFI_STATUS +EFIAPI +FvbSetAttributes ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, + IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes + ) +{ + DEBUG (( + DEBUG_INFO, + "FvbSetAttributes(0x%X) is not supported\n", + *Attributes + )); + return EFI_UNSUPPORTED; +} + +/** + Retrieves the base address of a memory-mapped firmware volume. + This function should be called only for memory-mapped firmware volumes. + + @param[in] This EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance. + + @param[out] 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. + +**/ +EFI_STATUS +EFIAPI +FvbGetPhysicalAddress ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, + OUT EFI_PHYSICAL_ADDRESS *Address + ) +{ + NOR_FLASH_INSTANCE *Instance; + + Instance = INSTANCE_FROM_FVB_THIS (This); + + DEBUG (( + DEBUG_INFO, + "FvbGetPhysicalAddress(BaseAddress=0x%08x)\n", + Instance->RegionBaseAddress + )); + + ASSERT (Address != NULL); + + *Address = Instance->RegionBaseAddress; + return EFI_SUCCESS; +} + +/** + 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[in] This EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance. + + @param[in] Lba Indicates the block whose size to return + + @param[out] BlockSize Pointer to a caller-allocated UINTN in which + the size of the block is returned. + + @param[out] 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_INFO, + "FvbGetBlockSize(Lba=%ld, BlockSize=0x%x, LastBlock=%ld)\n", + Lba, + Instance->BlockSize, + Instance->LastBlock + )); + + if (Lba > Instance->LastBlock) { + DEBUG (( + DEBUG_ERROR, + "FvbGetBlockSize: ERROR - Parameter LBA %ld is beyond the last Lba (%ld).\n", + Lba, + Instance->LastBlock + )); + Status = EFI_INVALID_PARAMETER; + } else { + // This is easy because in this platform each NorFlash device has equal sized blocks. + *BlockSize = (UINTN)Instance->BlockSize; + *NumberOfBlocks = (UINTN)(Instance->LastBlock - Lba + 1); + + DEBUG (( + DEBUG_INFO, + "FvbGetBlockSize: *BlockSize=0x%x, *NumberOfBlocks=0x%x.\n", + *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. + + @param[in] This EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance. + + @param[in] Lba The starting logical block index from which to read + + @param[in] Offset Offset into the block at which to begin reading. + + @param[in, out] NumBytes Pointer to a UINTN. + At entry, *NumBytes contains the total size of the + buffer. *NumBytes should have a non zero value. + At exit, *NumBytes contains the total number of + bytes read. + + @param[in, out] 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. + + @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 + ) +{ + EFI_STATUS Status; + UINTN BlockSize; + NOR_FLASH_INSTANCE *Instance; + + Instance = INSTANCE_FROM_FVB_THIS (This); + + DEBUG (( + DEBUG_INFO, + "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); + } + + BlockSize = Instance->BlockSize; + + DEBUG (( + DEBUG_INFO, + "FvbRead: Check if (Offset=0x%x + NumBytes=0x%x) <= BlockSize=0x%x\n", + Offset, + *NumBytes, + BlockSize + )); + + // The read must not span block boundaries. + // We need to check each variable individually because adding two large + // values together overflows. + if ((Offset >= BlockSize) || + (*NumBytes > BlockSize) || + ((Offset + *NumBytes) > BlockSize)) + { + DEBUG (( + DEBUG_ERROR, + "FvbRead: ERROR - EFI_BAD_BUFFER_SIZE: (Offset=0x%x + NumBytes=0x%x) > BlockSize=0x%x\n", + Offset, + *NumBytes, + BlockSize + )); + return EFI_BAD_BUFFER_SIZE; + } + + // We must have some bytes to read + if (*NumBytes == 0) { + return EFI_BAD_BUFFER_SIZE; + } + + // Decide if we are doing full block reads or not. + if (*NumBytes % BlockSize != 0) { + Status = NorFlashRead ( + Instance, + Instance->StartLba + Lba, + Offset, + *NumBytes, + Buffer + ); + } else { + // Read NOR Flash data into shadow buffer + Status = NorFlashReadBlocks ( + Instance, + Instance->StartLba + Lba, + BlockSize, + Buffer + ); + } + + if (EFI_ERROR (Status)) { + // Return one of the pre-approved error statuses + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +/** + Writes the specified number of bytes from the input buffer to the block. + + @param[in] This EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance. + + @param[in] Lba The starting logical block index to write to. + + @param[in] Offset Offset into the block at which to begin writing. + + @param[in, out] 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[in] Buffer The pointer to a caller-allocated buffer that + contains the source for the write. + + @retval EFI_SUCCESS The firmware volume was written successfully. + +**/ +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; + + Instance = INSTANCE_FROM_FVB_THIS (This); + + return NorFlashWriteSingleBlock ( + Instance, + Instance->StartLba + Lba, + Offset, + NumBytes, + Buffer + ); +} + +/** + Erases and initialises a firmware volume block. + + @param[in] This EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL + + @param[in] ... The variable argument list is a list of tuples. + Each tuple describes a range of LBAs to erase + and consists of the following: + - An EFI_LBA that indicates the starting LBA + - A UINTN that indicates the number of blocks + to erase. + + The list is terminated with an + EFI_LBA_LIST_TERMINATOR. + + @retval EFI_SUCCESS The erase request successfully completed. + + @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisabled + state. + + @retval EFI_DEVICE_ERROR The block device is not functioning correctly + and could not be written. + The firmware device may have been partially + erased. + + @retval EFI_INVALID_PARAMETER One or more of the LBAs listed in the variable + argument list do not exist in the firmware + volume. + +**/ +EFI_STATUS +EFIAPI +FvbEraseBlocks ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, + ... + ) +{ + EFI_STATUS Status; + VA_LIST Args; + UINTN BlockAddress; // Physical address of Lba to erase + EFI_LBA StartingLba; // Lba from which we start erasing + UINTN NumOfLba; // Number of Lba blocks to erase + NOR_FLASH_INSTANCE *Instance; + + Instance = INSTANCE_FROM_FVB_THIS (This); + + DEBUG ((DEBUG_INFO, "FvbEraseBlocks()\n")); + + Status = EFI_SUCCESS; + + // 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) { + break; + } + + // How many Lba blocks are we requested to erase? + NumOfLba = VA_ARG (Args, UINT32); + + // All blocks must be within range + DEBUG (( + DEBUG_INFO, + "FvbEraseBlocks: Check if: ( StartingLba=%ld + NumOfLba=%d - 1 ) > LastBlock=%ld.\n", + Instance->StartLba + StartingLba, + NumOfLba, + Instance->LastBlock + )); + if ((NumOfLba == 0) || + ((Instance->StartLba + StartingLba + NumOfLba - 1) > + Instance->LastBlock)) + { + VA_END (Args); + DEBUG (( + DEBUG_ERROR, + "FvbEraseBlocks: ERROR - Lba range goes past the last Lba.\n" + )); + return EFI_INVALID_PARAMETER; + } + } while (TRUE); + + VA_END (Args); + + 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->BlockSize + ); + + // Erase it + DEBUG (( + DEBUG_INFO, + "FvbEraseBlocks: Erasing Lba=%ld @ 0x%08x.\n", + Instance->StartLba + StartingLba, + BlockAddress + )); + Status = NorFlashUnlockAndEraseSingleBlock (Instance, BlockAddress); + if (EFI_ERROR (Status)) { + VA_END (Args); + return EFI_DEVICE_ERROR; + } + + // Move to the next Lba + StartingLba++; + NumOfLba--; + } + } while (TRUE); + + VA_END (Args); + + return Status; +} -- 2.25.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#111311): https://edk2.groups.io/g/devel/message/111311 Mute This Topic: https://groups.io/mt/102625036/7686176 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io] -=-=-=-=-=-=-=-=-=-=-=- ^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [edk2-devel] [edk2-platforms][PATCH V1 3/5] Platform/ARM/N1Sdp: NOR flash Dxe Driver for N1Sdp 2023-11-16 11:45 ` [edk2-devel] [edk2-platforms][PATCH V1 3/5] Platform/ARM/N1Sdp: NOR flash Dxe Driver " sahil @ 2023-12-07 14:46 ` Thomas Abraham 2023-12-12 12:08 ` levi.yun 2023-12-18 15:12 ` Sami Mujawar 2 siblings, 0 replies; 17+ messages in thread From: Thomas Abraham @ 2023-12-07 14:46 UTC (permalink / raw) To: devel@edk2.groups.io, Sahil Kaushal Cc: Ard Biesheuvel, Leif Lindholm, Sami Mujawar, Chandni Cherukuri, nd > -----Original Message----- > From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of sahil via > groups.io > Sent: Thursday, November 16, 2023 11:46 AM > To: devel@edk2.groups.io > Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>; Leif Lindholm > <quic_llindhol@quicinc.com>; Sami Mujawar <Sami.Mujawar@arm.com>; > Sahil Kaushal <Sahil.Kaushal@arm.com> > Subject: [edk2-devel] [edk2-platforms][PATCH V1 3/5] Platform/ARM/N1Sdp: > NOR flash Dxe Driver for N1Sdp > > Add NOR flash DXE driver, this brings up NV storage on > QSPI's flash device using FVB protocol. > > Signed-off-by: sahil <sahil@arm.com> > --- > Platform/ARM/N1Sdp/N1SdpPlatform.dec | 5 +- > Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiDxe.inf | 72 ++ > Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiReg.h | 33 + > Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/NorFlash.h | 491 > +++++++++ > Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiDxe.c | 409 > ++++++++ > Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/NorFlash.c | 1100 > ++++++++++++++++++++ > Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/NorFlashFvb.c | 647 > ++++++++++++ > 7 files changed, 2756 insertions(+), 1 deletion(-) Can this driver be moved to either the edk2-platform drivers/ or the Platform/Arm/Drivers directory? Otherwise, looks okay. Reviewed-by: Thomas Abraham <thomas.abraham@arm.com> [snip] -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#112194): https://edk2.groups.io/g/devel/message/112194 Mute This Topic: https://groups.io/mt/102625036/7686176 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io] -=-=-=-=-=-=-=-=-=-=-=- ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [edk2-devel] [edk2-platforms][PATCH V1 3/5] Platform/ARM/N1Sdp: NOR flash Dxe Driver for N1Sdp 2023-11-16 11:45 ` [edk2-devel] [edk2-platforms][PATCH V1 3/5] Platform/ARM/N1Sdp: NOR flash Dxe Driver " sahil 2023-12-07 14:46 ` Thomas Abraham @ 2023-12-12 12:08 ` levi.yun 2023-12-18 15:12 ` Sami Mujawar 2 siblings, 0 replies; 17+ messages in thread From: levi.yun @ 2023-12-12 12:08 UTC (permalink / raw) To: devel, sahil; +Cc: Ard Biesheuvel, Leif Lindholm, Sami Mujawar Hi Sahil! On 16/11/2023 11:45, sahil via groups.io wrote: > Add NOR flash DXE driver, this brings up NV storage on > QSPI's flash device using FVB protocol. > > Signed-off-by: sahil <sahil@arm.com> > --- > Platform/ARM/N1Sdp/N1SdpPlatform.dec | 5 +- > Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiDxe.inf | 72 ++ > Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiReg.h | 33 + > Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/NorFlash.h | 491 +++++++++ > Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiDxe.c | 409 ++++++++ > Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/NorFlash.c | 1100 ++++++++++++++++++++ > Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/NorFlashFvb.c | 647 ++++++++++++ > 7 files changed, 2756 insertions(+), 1 deletion(-) > > diff --git a/Platform/ARM/N1Sdp/N1SdpPlatform.dec b/Platform/ARM/N1Sdp/N1SdpPlatform.dec > index 16937197b8e8..67b5f4c871b6 100644 > --- a/Platform/ARM/N1Sdp/N1SdpPlatform.dec > +++ b/Platform/ARM/N1Sdp/N1SdpPlatform.dec > @@ -1,7 +1,7 @@ > ## @file > # Describes the N1Sdp configuration. > # > -# Copyright (c) 2021, ARM Limited. All rights reserved.<BR> > +# Copyright (c) 2021-2023, ARM Limited. All rights reserved.<BR> > # > # SPDX-License-Identifier: BSD-2-Clause-Patent > ## > @@ -89,3 +89,6 @@ > # unmapped reserved region results in a DECERR response. > # > gArmN1SdpTokenSpaceGuid.PcdCsComponentSize|0x1000|UINT32|0x00000049 > + > + # Base address of Cadence QSPI controller configuration registers > + gArmN1SdpTokenSpaceGuid.PcdCadenceQspiDxeRegBaseAddress|0x1C0C0000|UINT32|0x0000004A > diff --git a/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiDxe.inf b/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiDxe.inf > new file mode 100644 > index 000000000000..62a4944c95db > --- /dev/null > +++ b/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiDxe.inf > @@ -0,0 +1,72 @@ > +## @file > +# NOR flash DXE > +# > +# Copyright (c) 2023, ARM Limited. All rights reserved.<BR> > +# > +# SPDX-License-Identifier: BSD-2-Clause-Patent > +# > +## > + > +[Defines] > + INF_VERSION = 0x0001001B > + BASE_NAME = CadenceQspiDxe > + FILE_GUID = CC8A9713-4442-4A6C-B389-8B46490A0641 > + MODULE_TYPE = DXE_RUNTIME_DRIVER > + VERSION_STRING = 0.1 > + ENTRY_POINT = NorFlashInitialise > + > +[Sources] > + CadenceQspiDxe.c > + CadenceQspiReg.h > + NorFlash.c > + NorFlash.h > + NorFlashFvb.c > + > +[Packages] > + EmbeddedPkg/EmbeddedPkg.dec > + MdeModulePkg/MdeModulePkg.dec > + MdePkg/MdePkg.dec > + Platform/ARM/ARM.dec > + Platform/ARM/N1Sdp/N1SdpPlatform.dec > + > +[LibraryClasses] > + BaseLib > + BaseMemoryLib > + DebugLib > + DevicePathLib > + DxeServicesTableLib > + HobLib > + IoLib > + MemoryAllocationLib > + NorFlashInfoLib > + NorFlashPlatformLib > + TimerLib > + UefiBootServicesTableLib > + UefiDriverEntryPoint > + UefiLib > + UefiRuntimeLib > + UefiRuntimeServicesTableLib > + > +[Guids] > + gEdkiiNvVarStoreFormattedGuid > + gEfiAuthenticatedVariableGuid > + gEfiEventVirtualAddressChangeGuid > + gEfiSystemNvDataFvGuid > + gEfiVariableGuid > + gEfiGlobalVariableGuid > + > +[Protocols] > + gEfiDevicePathProtocolGuid > + gEfiFirmwareVolumeBlockProtocolGuid > + > +[FixedPcd] > + gArmN1SdpTokenSpaceGuid.PcdCadenceQspiDxeRegBaseAddress > + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase > + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize > + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase > + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize > + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase > + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize > + > +[Depex] > + gEfiCpuArchProtocolGuid > diff --git a/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiReg.h b/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiReg.h > new file mode 100644 > index 000000000000..535e6d738d31 > --- /dev/null > +++ b/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiReg.h > @@ -0,0 +1,33 @@ > +/** @file > + > + Copyright (c) 2023, ARM Limited. All rights reserved.<BR> > + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#ifndef CADENCE_QSPI_REG_H_ > +#define CADENCE_QSPI_REG_H_ If you don't mind, would you add some of Reference page to understand NorFlash in CadenceQspi please with @par? > +/** > + Write a full block to given location. > + > + @param[in] Instance NOR flash Instance of variable store region. > + @param[in] Lba The logical block address in NOR flash. > + @param[in] DataBuffer The data to write into NOR flash location. > + @param[in] BlockSizeInWords The number of bytes to write. > + > + @retval EFI_SUCCESS The write is completed. > +**/ > +STATIC > +EFI_STATUS > +NorFlashWriteFullBlock ( > + IN NOR_FLASH_INSTANCE *Instance, > + IN EFI_LBA Lba, > + IN UINT32 *DataBuffer, > + IN UINT32 BlockSizeInWords > + ) > +{ > + EFI_STATUS Status; > + UINTN WordAddress; > + UINT32 WordIndex; > + UINTN BlockAddress; > + NOR_FLASH_LOCK_CONTEXT Lock; > + > + Status = EFI_SUCCESS; > + > + // Get the physical address of the block > + BlockAddress = GET_NOR_BLOCK_ADDRESS ( > + Instance->RegionBaseAddress, > + Lba, > + BlockSizeInWords * 4 > + ); > + > + // Start writing from the first address at the start of the block > + WordAddress = BlockAddress; > + > + NorFlashLock (&Lock); > + > + Status = NorFlashUnlockAndEraseSingleBlock (Instance, BlockAddress); > + if (EFI_ERROR (Status)) { > + DEBUG (( > + DEBUG_ERROR, > + "WriteSingleBlock: ERROR - Failed to Unlock and Erase the single block at 0x%X\n", > + BlockAddress > + )); > + goto EXIT; > + } > + > + for (WordIndex = 0; > + WordIndex < BlockSizeInWords; > + WordIndex++, DataBuffer++, WordAddress += 4) > + { > + Status = NorFlashWriteSingleWord (Instance, WordAddress, *DataBuffer); > + if (EFI_ERROR (Status)) { > + goto EXIT; > + } > + } > + > +EXIT: > + NorFlashUnlock (&Lock); > + IIUC, NorFlashUnlockAndEraseSingleBlock calls NorFlashLock and NorFLashUnlock too. After calling NorFlashUnlock, it seems TPL or Interrupt seems to be enabled again. Isn't it problem? Thanks. -------- Sincerely, Levi. IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you. -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#112389): https://edk2.groups.io/g/devel/message/112389 Mute This Topic: https://groups.io/mt/102625036/7686176 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io] -=-=-=-=-=-=-=-=-=-=-=- ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [edk2-devel] [edk2-platforms][PATCH V1 3/5] Platform/ARM/N1Sdp: NOR flash Dxe Driver for N1Sdp 2023-11-16 11:45 ` [edk2-devel] [edk2-platforms][PATCH V1 3/5] Platform/ARM/N1Sdp: NOR flash Dxe Driver " sahil 2023-12-07 14:46 ` Thomas Abraham 2023-12-12 12:08 ` levi.yun @ 2023-12-18 15:12 ` Sami Mujawar 2 siblings, 0 replies; 17+ messages in thread From: Sami Mujawar @ 2023-12-18 15:12 UTC (permalink / raw) To: sahil, devel; +Cc: Ard Biesheuvel, Leif Lindholm, nd@arm.com Hi Sahil, Where can I find the documentation for Cadence QSPI? Can you add a link to the relevant file headers, please? Also, this patch is duplicating a lot of the code in edk2-platforms\Platform\ARM\Drivers\NorFlashDxe and I have already spotted some new bugs in this patch. Have you considered splitting the NorFlashDxe to introduce a NorFlashDeviceLib that implements the specifics for the respective flash? i.e. NorFlashDxe links with NorFlashDeviceLib and the platforms can specify the respective NorFlashDeviceLib instances. NorFlashDeviceLib|Platform/Arm/Library/P30NorFlashDeviceLib/P30NorFlashDeviceLib.inf NorFlashDeviceLib|Platform/Arm/Library/CadenceQspiNorFlashDeviceLib/CadenceQspiNorFlashDeviceLib.inf Regards, Sami Mujawar On 16/11/2023 11:45 am, sahil wrote: > Add NOR flash DXE driver, this brings up NV storage on > QSPI's flash device using FVB protocol. > > Signed-off-by: sahil <sahil@arm.com> > --- > Platform/ARM/N1Sdp/N1SdpPlatform.dec | 5 +- > Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiDxe.inf | 72 ++ > Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiReg.h | 33 + > Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/NorFlash.h | 491 +++++++++ > Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiDxe.c | 409 ++++++++ > Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/NorFlash.c | 1100 ++++++++++++++++++++ > Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/NorFlashFvb.c | 647 ++++++++++++ > 7 files changed, 2756 insertions(+), 1 deletion(-) > > diff --git a/Platform/ARM/N1Sdp/N1SdpPlatform.dec b/Platform/ARM/N1Sdp/N1SdpPlatform.dec > index 16937197b8e8..67b5f4c871b6 100644 > --- a/Platform/ARM/N1Sdp/N1SdpPlatform.dec > +++ b/Platform/ARM/N1Sdp/N1SdpPlatform.dec > @@ -1,7 +1,7 @@ > ## @file > > # Describes the N1Sdp configuration. > > # > > -# Copyright (c) 2021, ARM Limited. All rights reserved.<BR> > > +# Copyright (c) 2021-2023, ARM Limited. All rights reserved.<BR> > > # > > # SPDX-License-Identifier: BSD-2-Clause-Patent > > ## > > @@ -89,3 +89,6 @@ > # unmapped reserved region results in a DECERR response. > > # > > gArmN1SdpTokenSpaceGuid.PcdCsComponentSize|0x1000|UINT32|0x00000049 > > + > > + # Base address of Cadence QSPI controller configuration registers > > + gArmN1SdpTokenSpaceGuid.PcdCadenceQspiDxeRegBaseAddress|0x1C0C0000|UINT32|0x0000004A > > diff --git a/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiDxe.inf b/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiDxe.inf > new file mode 100644 > index 000000000000..62a4944c95db > --- /dev/null > +++ b/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiDxe.inf > @@ -0,0 +1,72 @@ > +## @file > > +# NOR flash DXE > > +# > > +# Copyright (c) 2023, ARM Limited. All rights reserved.<BR> > > +# > > +# SPDX-License-Identifier: BSD-2-Clause-Patent > > +# > > +## > > + > > +[Defines] > > + INF_VERSION = 0x0001001B > > + BASE_NAME = CadenceQspiDxe > > + FILE_GUID = CC8A9713-4442-4A6C-B389-8B46490A0641 > > + MODULE_TYPE = DXE_RUNTIME_DRIVER > > + VERSION_STRING = 0.1 > > + ENTRY_POINT = NorFlashInitialise > > + > > +[Sources] > > + CadenceQspiDxe.c > > + CadenceQspiReg.h > > + NorFlash.c > > + NorFlash.h > > + NorFlashFvb.c > > + > > +[Packages] > > + EmbeddedPkg/EmbeddedPkg.dec > > + MdeModulePkg/MdeModulePkg.dec > > + MdePkg/MdePkg.dec > > + Platform/ARM/ARM.dec > > + Platform/ARM/N1Sdp/N1SdpPlatform.dec > > + > > +[LibraryClasses] > > + BaseLib > > + BaseMemoryLib > > + DebugLib > > + DevicePathLib > > + DxeServicesTableLib > > + HobLib > > + IoLib > > + MemoryAllocationLib > > + NorFlashInfoLib > > + NorFlashPlatformLib > > + TimerLib > > + UefiBootServicesTableLib > > + UefiDriverEntryPoint > > + UefiLib > > + UefiRuntimeLib > > + UefiRuntimeServicesTableLib > > + > > +[Guids] > > + gEdkiiNvVarStoreFormattedGuid > > + gEfiAuthenticatedVariableGuid > > + gEfiEventVirtualAddressChangeGuid > > + gEfiSystemNvDataFvGuid > > + gEfiVariableGuid > > + gEfiGlobalVariableGuid > > + > > +[Protocols] > > + gEfiDevicePathProtocolGuid > > + gEfiFirmwareVolumeBlockProtocolGuid > > + > > +[FixedPcd] > > + gArmN1SdpTokenSpaceGuid.PcdCadenceQspiDxeRegBaseAddress > > + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase > > + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize > > + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase > > + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize > > + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase > > + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize > > + > > +[Depex] > > + gEfiCpuArchProtocolGuid > > diff --git a/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiReg.h b/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiReg.h > new file mode 100644 > index 000000000000..535e6d738d31 > --- /dev/null > +++ b/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiReg.h > @@ -0,0 +1,33 @@ > +/** @file > > + > > + Copyright (c) 2023, ARM Limited. All rights reserved.<BR> > > + > > + SPDX-License-Identifier: BSD-2-Clause-Patent > > + > > +**/ > > + > > +#ifndef CADENCE_QSPI_REG_H_ > > +#define CADENCE_QSPI_REG_H_ > > + > > +// QSPI Controller defines > > +#define CDNS_QSPI_FLASH_CMD_CTRL_REG_OFFSET 0x90 > > +#define CDNS_QSPI_FLASH_CMD_CTRL_REG_EXECUTE 0x01 > > +#define CDNS_QSPI_FLASH_CMD_CTRL_REG_ADDR_ENABLE 0x01 > > +#define CDNS_QSPI_FLASH_CMD_CTRL_REG_ADDR_BIT_POS 19 > > +#define CDNS_QSPI_FLASH_CMD_CTRL_REG_ADDR_BYTE_BIT_POS 16 > > +#define CDNS_QSPI_FLASH_CMD_CTRL_REG_STATUS_BIT 0x02 > > +#define CDNS_QSPI_FLASH_CMD_CTRL_REG_OPCODE_BIT_POS 24 > > +#define CDNS_QSPI_FLASH_CMD_CTRL_REG_READ_ENABLE 0x01 > > +#define CDNS_QSPI_FLASH_CMD_CTRL_REG_READ_BYTE_3B 0x02 > > +#define CDNS_QSPI_FLASH_CMD_CTRL_REG_READEN_BIT_POS 23 > > +#define CDNS_QSPI_FLASH_CMD_CTRL_REG_READBYTE_BIT_POS 20 > > +#define CDNS_QSPI_FLASH_CMD_CTRL_REG_DUMMY_8C 0x8 > > +#define CDNS_QSPI_FLASH_CMD_CTRL_REG_DUMMY_BIT_POS 7 > > +#define CDNS_QSPI_FLASH_CMD_CTRL_REG_NUM_DATA_BYTES(x) ((x - 1) << CDNS_QSPI_FLASH_CMD_CTRL_REG_READBYTE_BIT_POS) > > +#define CDNS_QSPI_FLASH_CMD_CTRL_REG_NUM_ADDR_BYTES(x) ((x - 1) << CDNS_QSPI_FLASH_CMD_CTRL_REG_ADDR_BYTE_BIT_POS) > > + > > +#define CDNS_QSPI_FLASH_CMD_READ_DATA_REG_OFFSET 0xA0 > > + > > +#define CDNS_QSPI_FLASH_CMD_ADDR_REG_OFFSET 0x94 > > + > > +#endif /* CADENCE_QSPI_REG_H_ */ > > diff --git a/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/NorFlash.h b/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/NorFlash.h > new file mode 100644 > index 000000000000..38ae1c2fae89 > --- /dev/null > +++ b/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/NorFlash.h > @@ -0,0 +1,491 @@ > +/** @file > > + > > + Copyright (c) 2023, ARM Limited. All rights reserved.<BR> > > + > > + SPDX-License-Identifier: BSD-2-Clause-Patent > > + > > +**/ > > + > > +#ifndef NOR_FLASH_DXE_H_ > > +#define NOR_FLASH_DXE_H_ > > + > > +#include <Guid/EventGroup.h> > > +#include <Library/DebugLib.h> > > +#include <Library/IoLib.h> > > +#include <Library/NorFlashPlatformLib.h> > > +#include <PiDxe.h> > > +#include <Protocol/BlockIo.h> > > +#include <Protocol/DiskIo.h> > > +#include <Protocol/FirmwareVolumeBlock.h> > > + > > +#include "CadenceQspiReg.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('S', 'n', 'o', 'r') > > +#define INSTANCE_FROM_FVB_THIS(a) CR(a, NOR_FLASH_INSTANCE, FvbProtocol, \ > > + NOR_FLASH_SIGNATURE) > > + > > +#define NOR_FLASH_POLL_FSR BIT0 > > + > > +typedef struct _NOR_FLASH_INSTANCE NOR_FLASH_INSTANCE; > > + > > +typedef EFI_STATUS (*NOR_FLASH_INITIALIZE) ( > > + NOR_FLASH_INSTANCE *Instance > > + ); > > + > > +#pragma pack(1) > > +typedef struct { > > + VENDOR_DEVICE_PATH Vendor; > > + UINT8 Index; > > + EFI_DEVICE_PATH_PROTOCOL End; > > +} NOR_FLASH_DEVICE_PATH; > > +#pragma pack() > > + > > +struct _NOR_FLASH_INSTANCE { > > + UINT32 Signature; > > + EFI_HANDLE Handle; > > + > > + BOOLEAN Initialized; > > + NOR_FLASH_INITIALIZE Initialize; > > + > > + UINTN HostRegisterBaseAddress; > > + UINTN DeviceBaseAddress; > > + UINTN RegionBaseAddress; > > + UINTN Size; > > + UINTN BlockSize; > > + UINTN LastBlock; > > + EFI_LBA StartLba; > > + EFI_LBA OffsetLba; > > + > > + EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL FvbProtocol; > > + VOID *ShadowBuffer; > > + > > + NOR_FLASH_DEVICE_PATH DevicePath; > > + > > + UINT32 Flags; > > +}; > > + > > +typedef struct { > > + EFI_TPL OriginalTPL; > > + BOOLEAN InterruptsEnabled; > > +} NOR_FLASH_LOCK_CONTEXT; > > + > > +/** > > + Lock all pending read/write to Nor flash device > > + > > + @param[in] Context Nor flash device context structure. > > +**/ > > +VOID > > +EFIAPI > > +NorFlashLock ( > > + IN NOR_FLASH_LOCK_CONTEXT *Context > > + ); > > + > > +/** > > + Unlock all pending read/write to Nor flash device > > + > > + @param[in] Context Nor flash device context structure. > > +**/ > > +VOID > > +EFIAPI > > +NorFlashUnlock ( > > + IN NOR_FLASH_LOCK_CONTEXT *Context > > + ); > > + > > +extern UINTN mFlashNvStorageVariableBase; > > + > > +/** > > + Create Nor flash Instance for given region. > > + > > + @param[in] HostRegisterBase Base address of Nor flash controller. > > + @param[in] NorFlashDeviceBase Base address of flash device. > > + @param[in] NorFlashRegionBase Base address of flash region on device. > > + @param[in] NorFlashSize Size of flash region. > > + @param[in] Index Index of given flash region. > > + @param[in] BlockSize Block size of NOR flash device. > > + @param[in] HasVarStore Boolean set for VarStore on given region. > > + @param[out] NorFlashInstance Instance of given flash region. > > + > > + @retval EFI_SUCCESS On successful creation of NOR flash instance. > > +**/ > > +EFI_STATUS > > +NorFlashCreateInstance ( > > + IN UINTN HostRegisterBase, > > + IN UINTN NorFlashDeviceBase, > > + IN UINTN NorFlashRegionBase, > > + IN UINTN NorFlashSize, > > + IN UINT32 Index, > > + IN UINT32 BlockSize, > > + IN BOOLEAN HasVarStore, > > + OUT NOR_FLASH_INSTANCE **NorFlashInstance > > + ); > > + > > +/** > > + Install Fv block on to variable store region > > + > > + @param[in] Instance Instance of Nor flash variable region. > > + > > + @retval EFI_SUCCESS The entry point is executed successfully. > > +**/ > > +EFI_STATUS > > +EFIAPI > > +NorFlashFvbInitialize ( > > + IN NOR_FLASH_INSTANCE *Instance > > + ); > > + > > +/** > > + Check the integrity of firmware volume header. > > + > > + @param[in] Instance Instance of Nor flash variable region. > > + > > + @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 > > + ); > > + > > +/** > > + Initialize the FV Header and Variable Store Header > > + to support variable operations. > > + > > + @param[in] Instance Location to Initialize the headers > > + > > + @retval EFI_SUCCESS Fv init is done > > + > > +**/ > > +EFI_STATUS > > +InitializeFvAndVariableStoreHeaders ( > > + IN NOR_FLASH_INSTANCE *Instance > > + ); > > + > > +/** > > + Retrieves the attributes and current settings of the block. > > + > > + @param[in] This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance. > > + > > + @param[out] 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 > > + ); > > + > > +/** > > + Sets configurable firmware volume attributes and returns the > > + new settings of the firmware volume. > > + > > + > > + @param[in] This EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance. > > + > > + @param[in, out] Attributes On input, Attributes is a pointer to > > + EFI_FVB_ATTRIBUTES_2 that contains the desired > > + firmware volume settings. > > + On successful return, it contains the new > > + settings of the firmware volume. > > + > > + @retval EFI_UNSUPPORTED The firmware volume attributes are not supported. > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +FvbSetAttributes ( > > + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, > > + IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes > > + ); > > + > > +/** > > + Retrieves the base address of a memory-mapped firmware volume. > > + This function should be called only for memory-mapped firmware volumes. > > + > > + @param[in] This EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance. > > + > > + @param[out] 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. > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +FvbGetPhysicalAddress ( > > + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, > > + OUT EFI_PHYSICAL_ADDRESS *Address > > + ); > > + > > +/** > > + 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[in] This EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance. > > + > > + @param[in] Lba Indicates the block whose size to return > > + > > + @param[out] BlockSize Pointer to a caller-allocated UINTN in which > > + the size of the block is returned. > > + > > + @param[out] 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 > > + ); > > + > > +/** > > + 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. > > + > > + @param[in] This EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance. > > + > > + @param[in] Lba The starting logical block index from which to read > > + > > + @param[in] Offset Offset into the block at which to begin reading. > > + > > + @param[in, out] NumBytes Pointer to a UINTN. > > + At entry, *NumBytes contains the total size of the > > + buffer. *NumBytes should have a non zero value. > > + At exit, *NumBytes contains the total number of > > + bytes read. > > + > > + @param[in out] 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. > > + > > + @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 > > + ); > > + > > +/** > > + Writes the specified number of bytes from the input buffer to the block. > > + > > + @param[in] This EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance. > > + > > + @param[in] Lba The starting logical block index to write to. > > + > > + @param[in] Offset Offset into the block at which to begin writing. > > + > > + @param[in, out] 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[in] Buffer The pointer to a caller-allocated buffer that > > + contains the source for the write. > > + > > + @retval EFI_SUCCESS The firmware volume was written successfully. > > + > > +**/ > > +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 > > + ); > > + > > +/** > > + Erases and initialises a firmware volume block. > > + > > + @param[in] This EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL > > + > > + @param[in] ... The variable argument list is a list of tuples. > > + Each tuple describes a range of LBAs to erase > > + and consists of the following: > > + - An EFI_LBA that indicates the starting LBA > > + - A UINTN that indicates the number of blocks > > + to erase. > > + > > + The list is terminated with an > > + EFI_LBA_LIST_TERMINATOR. > > + > > + @retval EFI_SUCCESS The erase request successfully completed. > > + > > + @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisabled > > + state. > > + > > + @retval EFI_DEVICE_ERROR The block device is not functioning correctly > > + and could not be written. > > + The firmware device may have been partially > > + erased. > > + > > + @retval EFI_INVALID_PARAMETER One or more of the LBAs listed in the variable > > + argument list do not exist in the firmware > > + volume. > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +FvbEraseBlocks ( > > + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, > > + ... > > + ); > > + > > +/** > > + This function unlock and erase an entire NOR Flash block. > > + > > + @param[in] Instance NOR flash Instance of variable store region. > > + @param[in] BlockAddress Block address within the variable store region. > > + > > + @retval EFI_SUCCESS The erase and unlock successfully completed. > > +**/ > > +EFI_STATUS > > +NorFlashUnlockAndEraseSingleBlock ( > > + IN NOR_FLASH_INSTANCE *Instance, > > + IN UINTN BlockAddress > > + ); > > + > > +/** > > + Write a full or portion of a block. > > + > > + @param[in] Instance NOR flash Instance of variable store region. > > + @param[in] Lba The starting logical block index to write to. > > + @param[in] Offset Offset into the block at which to begin writing. > > + @param[in,out] NumBytes The total size of the buffer. > > + @param[in] Buffer The pointer to a caller-allocated buffer that > > + contains the source for the write. > > + > > + @retval EFI_SUCCESS The write is completed. > > +**/ > > +EFI_STATUS > > +NorFlashWriteSingleBlock ( > > + IN NOR_FLASH_INSTANCE *Instance, > > + IN EFI_LBA Lba, > > + IN UINTN Offset, > > + IN OUT UINTN *NumBytes, > > + IN UINT8 *Buffer > > + ); > > + > > +/** > > + Write a full block. > > + > > + @param[in] Instance NOR flash Instance of variable store region. > > + @param[in] Lba The starting logical block index to write to. > > + @param[in] BufferSizeInBytes The number of bytes to write. > > + @param[in] Buffer The pointer to a caller-allocated buffer that > > + contains the source for the write. > > + > > + @retval EFI_SUCCESS The write is completed. > > +**/ > > +EFI_STATUS > > +NorFlashWriteBlocks ( > > + IN NOR_FLASH_INSTANCE *Instance, > > + IN EFI_LBA Lba, > > + IN UINTN BufferSizeInBytes, > > + IN VOID *Buffer > > + ); > > + > > +/** > > + Read a full block. > > + > > + @param[in] Instance NOR flash Instance of variable store region. > > + @param[in] Lba The starting logical block index to read from. > > + @param[in] BufferSizeInBytes The number of bytes to read. > > + @param[out] Buffer The pointer to a caller-allocated buffer that > > + should be copied with read data. > > + > > + @retval EFI_SUCCESS The read is completed. > > +**/ > > +EFI_STATUS > > +NorFlashReadBlocks ( > > + IN NOR_FLASH_INSTANCE *Instance, > > + IN EFI_LBA Lba, > > + IN UINTN BufferSizeInBytes, > > + OUT VOID *Buffer > > + ); > > + > > +/** > > + Read from nor flash. > > + > > + @param[in] Instance NOR flash Instance of variable store region. > > + @param[in] Lba The starting logical block index to read from. > > + @param[in] Offset Offset into the block at which to begin reading. > > + @param[in] BufferSizeInBytes The number of bytes to read. > > + @param[out] Buffer The pointer to a caller-allocated buffer that > > + should copied with read data. > > + > > + @retval EFI_SUCCESS The read is completed. > > +**/ > > +EFI_STATUS > > +NorFlashRead ( > > + IN NOR_FLASH_INSTANCE *Instance, > > + IN EFI_LBA Lba, > > + IN UINTN Offset, > > + IN UINTN BufferSizeInBytes, > > + OUT VOID *Buffer > > + ); > > + > > +/** > > + Read JEDEC ID of NOR flash device. > > + > > + @param[in] Instance NOR flash Instance of variable store region. > > + @param[out] JedecId JEDEC ID of NOR flash device. > > + > > + @retval EFI_SUCCESS The write is completed. > > +**/ > > +EFI_STATUS > > +NorFlashReadID ( > > + IN NOR_FLASH_INSTANCE *Instance, > > + OUT UINT8 JedecId[3] > > + ); > > + > > +#define SPINOR_SR_WIP BIT0 // Write in progress > > + > > +#define SPINOR_OP_WREN 0x06 // Write enable > > +#define SPINOR_OP_BE_4K 0x20 // Erase 4KiB block > > +#define SPINOR_OP_RDID 0x9f // Read JEDEC ID > > +#define SPINOR_OP_RDSR 0x05 // Read status register > > + > > +#define SPINOR_SR_WIP_POLL_TIMEOUT_MS 1000u // Status Register read timeout > > + > > +#endif /* NOR_FLASH_DXE_H_ */ > > diff --git a/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiDxe.c b/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiDxe.c > new file mode 100644 > index 000000000000..fffe689161a6 > --- /dev/null > +++ b/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiDxe.c > @@ -0,0 +1,409 @@ > +/** @file > > + NOR flash DXE > > + > > + Copyright (c) 2023, ARM Limited. All rights reserved.<BR> > > + > > + SPDX-License-Identifier: BSD-2-Clause-Patent > > + > > +**/ > > + > > +#include <Library/BaseMemoryLib.h> > > +#include <Library/DxeServicesTableLib.h> > > +#include <Library/HobLib.h> > > +#include <Library/MemoryAllocationLib.h> > > +#include <Library/NorFlashInfoLib.h> > > +#include <Library/PcdLib.h> > > +#include <Library/UefiBootServicesTableLib.h> > > +#include <Library/UefiLib.h> > > +#include <Library/UefiRuntimeLib.h> > > +#include <Library/UefiRuntimeServicesTableLib.h> > > + > > +#include "NorFlash.h" > > + > > +STATIC NOR_FLASH_INSTANCE **mNorFlashInstances; > > +STATIC UINT32 mNorFlashDeviceCount; > > + > > +STATIC EFI_EVENT mNorFlashVirtualAddrChangeEvent; > > + > > +/** > > + Install Fv block onto variable store region > > + > > + @param[in] Instance Instance of Nor flash variable region. > > + > > + @retval EFI_SUCCESS The entry point is executed successfully. > > +**/ > > +EFI_STATUS > > +EFIAPI > > +NorFlashFvbInitialize ( > > + IN NOR_FLASH_INSTANCE *Instance > > + ) > > +{ > > + EFI_STATUS Status; > > + UINT32 FvbNumLba; > > + EFI_BOOT_MODE BootMode; > > + UINTN RuntimeMmioRegionSize; > > + UINTN RuntimeMmioDeviceSize; > > + UINTN BlockSize; > > + > > + DEBUG ((DEBUG_INFO, "NorFlashFvbInitialize\n")); > > + > > + BlockSize = Instance->BlockSize; > > + > > + // FirmwareVolumeHeader->FvLength is declared to have the Variable area > > + // AND the FTW working area AND the FTW Spare contiguous. > > + ASSERT ( > > + PcdGet32 (PcdFlashNvStorageVariableBase) + > > + PcdGet32 (PcdFlashNvStorageVariableSize) == > > + PcdGet32 (PcdFlashNvStorageFtwWorkingBase) > > + ); > > + ASSERT ( > > + PcdGet32 (PcdFlashNvStorageFtwWorkingBase) + > > + PcdGet32 (PcdFlashNvStorageFtwWorkingSize) == > > + PcdGet32 (PcdFlashNvStorageFtwSpareBase) > > + ); > > + > > + // Check if the size of the area is at least one block size. > > + ASSERT ( > > + (PcdGet32 (PcdFlashNvStorageVariableSize) > 0) && > > + (PcdGet32 (PcdFlashNvStorageVariableSize) / BlockSize > 0) > > + ); > > + ASSERT ( > > + (PcdGet32 (PcdFlashNvStorageFtwWorkingSize) > 0) && > > + (PcdGet32 (PcdFlashNvStorageFtwWorkingSize) / BlockSize > 0) > > + ); > > + ASSERT ( > > + (PcdGet32 (PcdFlashNvStorageFtwSpareSize) > 0) && > > + (PcdGet32 (PcdFlashNvStorageFtwSpareSize) / BlockSize > 0) > > + ); > > + > > + // Ensure the Variable areas are aligned on block size boundaries. > > + ASSERT ((PcdGet32 (PcdFlashNvStorageVariableBase) % BlockSize) == 0); > > + ASSERT ((PcdGet32 (PcdFlashNvStorageFtwWorkingBase) % BlockSize) == 0); > > + ASSERT ((PcdGet32 (PcdFlashNvStorageFtwSpareBase) % BlockSize) == 0); > > + > > + Instance->Initialized = TRUE; > > + mFlashNvStorageVariableBase = FixedPcdGet32 (PcdFlashNvStorageVariableBase); > > + > > + // Set the index of the first LBA for the FVB. > > + Instance->StartLba = (PcdGet32 (PcdFlashNvStorageVariableBase) - > > + Instance->RegionBaseAddress) / 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", __func__)); > > + DEBUG (( > > + DEBUG_INFO, > > + "%a: Installing a correct one for this volume.\n", > > + __func__ > > + )); > > + > > + // Erase all the NorFlash that is reserved for variable storage. > > + FvbNumLba = (PcdGet32 (PcdFlashNvStorageVariableSize) + > > + PcdGet32 (PcdFlashNvStorageFtwWorkingSize) + > > + PcdGet32 (PcdFlashNvStorageFtwSpareSize)) / > > + Instance->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; > > + } > > + > > + // validate FV header again if FV was created successfully. > > + Status = ValidateFvHeader (Instance); > > + if (EFI_ERROR (Status)) { > > + DEBUG ((DEBUG_ERROR, "ValidateFvHeader is failed \n")); > > + return Status; > > + } > > + } > > + > > + // The driver implementing the variable read service can now be dispatched; > > + // the varstore headers are in place. > > + Status = gBS->InstallProtocolInterface ( > > + &gImageHandle, > > + &gEdkiiNvVarStoreFormattedGuid, > > + EFI_NATIVE_INTERFACE, > > + NULL > > + ); > > + if (EFI_ERROR (Status)) { > > + DEBUG (( > > + DEBUG_ERROR, > > + "%a: Failed to install gEdkiiNvVarStoreFormattedGuid\n", > > + __func__ > > + )); > > + return Status; > > + } > > + > > + // Declare the Non-Volatile storage as EFI_MEMORY_RUNTIME. > > + RuntimeMmioRegionSize = Instance->Size; > > + RuntimeMmioDeviceSize = Instance->RegionBaseAddress - Instance->DeviceBaseAddress; > > + > > + Status = gDS->AddMemorySpace ( > > + EfiGcdMemoryTypeMemoryMappedIo, > > + Instance->RegionBaseAddress, > > + RuntimeMmioRegionSize, > > + EFI_MEMORY_UC | EFI_MEMORY_RUNTIME > > + ); > > + ASSERT_EFI_ERROR (Status); > > + > > + Status = gDS->AddMemorySpace ( > > + EfiGcdMemoryTypeMemoryMappedIo, > > + Instance->DeviceBaseAddress, > > + RuntimeMmioDeviceSize, > > + EFI_MEMORY_UC | EFI_MEMORY_RUNTIME > > + ); > > + ASSERT_EFI_ERROR (Status); > > + > > + Status = gDS->SetMemorySpaceAttributes ( > > + Instance->RegionBaseAddress, > > + RuntimeMmioRegionSize, > > + EFI_MEMORY_UC | EFI_MEMORY_RUNTIME > > + ); > > + ASSERT_EFI_ERROR (Status); > > + > > + Status = gDS->SetMemorySpaceAttributes ( > > + Instance->DeviceBaseAddress, > > + RuntimeMmioDeviceSize, > > + EFI_MEMORY_UC | EFI_MEMORY_RUNTIME > > + ); > > + ASSERT_EFI_ERROR (Status); > > + > > + return Status; > > +} > > + > > +/** > > + Fixup internal data so that EFI can be called in virtual mode. > > + convert any pointers in lib to virtual mode. > > + > > + @param[in] Event The Event that is being processed > > + @param[in] Context Event Context > > +**/ > > +STATIC > > +VOID > > +EFIAPI > > +NorFlashVirtualNotifyEvent ( > > + IN EFI_EVENT Event, > > + IN VOID *Context > > + ) > > +{ > > + UINTN Index; > > + > > + EfiConvertPointer (0x0, (VOID **)&mFlashNvStorageVariableBase); > > + > > + for (Index = 0; Index < mNorFlashDeviceCount; Index++) { > > + EfiConvertPointer ( > > + 0x0, > > + (VOID **)&mNorFlashInstances[Index]->HostRegisterBaseAddress > > + ); > > + EfiConvertPointer ( > > + 0x0, > > + (VOID **)&mNorFlashInstances[Index]->DeviceBaseAddress > > + ); > > + EfiConvertPointer ( > > + 0x0, > > + (VOID **)&mNorFlashInstances[Index]->RegionBaseAddress > > + ); > > + > > + // 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); > > + } > > + } > > +} > > + > > +/** > > + Entrypoint of Platform Nor flash DXE driver > > + > > + @param[in] ImageHandle The firmware allocated handle for the EFI image. > > + @param[in] SystemTable A pointer to the EFI System Table. > > + > > + @retval EFI_SUCCESS The entry point is executed successfully. > > +**/ > > +EFI_STATUS > > +EFIAPI > > +NorFlashInitialise ( > > + IN EFI_HANDLE ImageHandle, > > + IN EFI_SYSTEM_TABLE *SystemTable > > + ) > > +{ > > + EFI_STATUS Status; > > + EFI_PHYSICAL_ADDRESS HostRegisterBaseAddress; > > + UINT32 Index; > > + NOR_FLASH_DESCRIPTION *NorFlashDevices; > > + BOOLEAN ContainVariableStorage; > > + > > + HostRegisterBaseAddress = PcdGet32 (PcdCadenceQspiDxeRegBaseAddress); > > + > > + Status = gDS->AddMemorySpace ( > > + EfiGcdMemoryTypeMemoryMappedIo, > > + HostRegisterBaseAddress, > > + SIZE_64KB, > > + EFI_MEMORY_UC | EFI_MEMORY_RUNTIME > > + ); > > + ASSERT_EFI_ERROR (Status); > > + > > + Status = gDS->SetMemorySpaceAttributes ( > > + HostRegisterBaseAddress, > > + SIZE_64KB, > > + EFI_MEMORY_UC | EFI_MEMORY_RUNTIME > > + ); > > + ASSERT_EFI_ERROR (Status); > > + > > + // Initialize NOR flash instances. > > + Status = NorFlashPlatformGetDevices (&NorFlashDevices, &mNorFlashDeviceCount); > > + if (EFI_ERROR (Status)) { > > + DEBUG ((DEBUG_ERROR, "NorFlashInitialise: Fail to get Nor Flash devices\n")); > > + return Status; > > + } > > + > > + mNorFlashInstances = AllocateRuntimePool ( > > + sizeof (NOR_FLASH_INSTANCE *) * > > + mNorFlashDeviceCount > > + ); > > + > > + if (mNorFlashInstances == NULL) { > > + DEBUG (( > > + DEBUG_ERROR, > > + "NorFlashInitialise: Failed to allocate mem for NorFlashInstance\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 <= > > + PcdGet32 (PcdFlashNvStorageVariableBase)) && > > + (PcdGet32 (PcdFlashNvStorageVariableBase) + > > + PcdGet32 (PcdFlashNvStorageVariableSize) <= > > + NorFlashDevices[Index].RegionBaseAddress + NorFlashDevices[Index].Size); > > + > > + Status = NorFlashCreateInstance ( > > + HostRegisterBaseAddress, > > + NorFlashDevices[Index].DeviceBaseAddress, > > + NorFlashDevices[Index].RegionBaseAddress, > > + NorFlashDevices[Index].Size, > > + Index, > > + NorFlashDevices[Index].BlockSize, > > + ContainVariableStorage, > > + &mNorFlashInstances[Index] > > + ); > > + if (EFI_ERROR (Status)) { > > + DEBUG (( > > + DEBUG_ERROR, > > + "NorFlashInitialise: Fail to create instance for NorFlash[%d]\n", > > + Index > > + )); > > + continue; > > + } > > + > > + Status = gBS->InstallMultipleProtocolInterfaces ( > > + &mNorFlashInstances[Index]->Handle, > > + &gEfiDevicePathProtocolGuid, > > + &mNorFlashInstances[Index]->DevicePath, > > + &gEfiFirmwareVolumeBlockProtocolGuid, > > + &mNorFlashInstances[Index]->FvbProtocol, > > + NULL > > + ); > > + ASSERT_EFI_ERROR (Status); > > + } > > + > > + // Register for the virtual address change event. > > + Status = gBS->CreateEventEx ( > > + EVT_NOTIFY_SIGNAL, > > + TPL_NOTIFY, > > + NorFlashVirtualNotifyEvent, > > + NULL, > > + &gEfiEventVirtualAddressChangeGuid, > > + &mNorFlashVirtualAddrChangeEvent > > + ); > > + ASSERT_EFI_ERROR (Status); > > + > > + return Status; > > +} > > + > > +/** > > + Lock all pending read/write to Nor flash device > > + > > + @param[in] Context Nor flash device context structure. > > +**/ > > +VOID > > +EFIAPI > > +NorFlashLock ( > > + IN NOR_FLASH_LOCK_CONTEXT *Context > > + ) > > +{ > > + if (!EfiAtRuntime ()) { > > + // Raise TPL to TPL_HIGH to stop anyone from interrupting us. > > + Context->OriginalTPL = gBS->RaiseTPL (TPL_HIGH_LEVEL); > > + } else { > > + Context->InterruptsEnabled = SaveAndDisableInterrupts (); > > + } > > +} > > + > > +/** > > + Unlock all pending read/write to Nor flash device > > + > > + @param[in] Context Nor flash device context structure. > > +**/ > > +VOID > > +EFIAPI > > +NorFlashUnlock ( > > + IN NOR_FLASH_LOCK_CONTEXT *Context > > + ) > > +{ > > + if (!EfiAtRuntime ()) { > > + // Interruptions can resume. > > + gBS->RestoreTPL (Context->OriginalTPL); > > + } else if (Context->InterruptsEnabled) { > > + SetInterruptState (TRUE); > > + } > > +} > > diff --git a/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/NorFlash.c b/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/NorFlash.c > new file mode 100644 > index 000000000000..be7b626c5697 > --- /dev/null > +++ b/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/NorFlash.c > @@ -0,0 +1,1100 @@ > +/** @file > > + > > + Copyright (c) 2023 ARM Limited. All rights reserved.<BR> > > + > > + SPDX-License-Identifier: BSD-2-Clause-Patent > > + > > +**/ > > + > > +#include <Library/BaseMemoryLib.h> > > +#include <Library/MemoryAllocationLib.h> > > +#include <Library/NorFlashInfoLib.h> > > +#include <Library/PcdLib.h> > > +#include <Library/TimerLib.h> > > +#include <Library/UefiBootServicesTableLib.h> > > +#include <Library/UefiLib.h> > > + > > +#include "NorFlash.h" > > + > > +STATIC CONST NOR_FLASH_INSTANCE mNorFlashInstanceTemplate = { > > + NOR_FLASH_SIGNATURE, // Signature > > + NULL, // Handle > > + > > + FALSE, // Initialized > > + NULL, // Initialize > > + > > + 0, // HostRegisterBaseAddress > > + 0, // DeviceBaseAddress > > + 0, // RegionBaseAddress > > + 0, // Size > > + 0, // BlockSize > > + 0, // LastBlock > > + 0, // StartLba > > + 0, // OffsetLba > > + > > + { > > + FvbGetAttributes, // GetAttributes > > + FvbSetAttributes, // SetAttributes > > + FvbGetPhysicalAddress, // GetPhysicalAddress > > + FvbGetBlockSize, // GetBlockSize > > + FvbRead, // Read > > + FvbWrite, // Write > > + FvbEraseBlocks, // EraseBlocks > > + NULL, // ParentHandle > > + }, // FvbProtoccol; > > + NULL, // ShadowBuffer > > + > > + { > > + { > > + { > > + HARDWARE_DEVICE_PATH, > > + HW_VENDOR_DP, > > + { > > + (UINT8)(OFFSET_OF (NOR_FLASH_DEVICE_PATH, End)), > > + (UINT8)(OFFSET_OF (NOR_FLASH_DEVICE_PATH, End) >> 8) > > + } > > + }, > > + { 0x0, 0x0, 0x0, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } > > + }, > > + }, > > + 0, // Index > > + > > + { > > + END_DEVICE_PATH_TYPE, > > + END_ENTIRE_DEVICE_PATH_SUBTYPE, > > + { sizeof (EFI_DEVICE_PATH_PROTOCOL), 0 } > > + } > > + }, // DevicePath > > + 0 // Flags > > +}; > > + > > +/** > > + Execute Flash cmd ctrl and Read Status. > > + > > + @param[in] Instance NOR flash Instance. > > + @param[in] Val Value to be written to Flash cmd ctrl Register. > > + > > + @retval EFI_SUCCESS Request is executed successfully. > > + > > +**/ > > +STATIC > > +EFI_STATUS > > +CdnsQspiExecuteCommand ( > > + IN NOR_FLASH_INSTANCE *Instance, > > + IN UINT32 Val > > + ) > > +{ > > + // Set the command > > + MmioWrite32 ( > > + Instance->HostRegisterBaseAddress + CDNS_QSPI_FLASH_CMD_CTRL_REG_OFFSET, > > + Val > > + ); > > + // Execute the command > > + MmioWrite32 ( > > + Instance->HostRegisterBaseAddress + CDNS_QSPI_FLASH_CMD_CTRL_REG_OFFSET, > > + Val | CDNS_QSPI_FLASH_CMD_CTRL_REG_EXECUTE > > + ); > > + > > + // Wait until command has been executed > > + while ((MmioRead32 (Instance->HostRegisterBaseAddress + CDNS_QSPI_FLASH_CMD_CTRL_REG_OFFSET) > > + & CDNS_QSPI_FLASH_CMD_CTRL_REG_STATUS_BIT) == CDNS_QSPI_FLASH_CMD_CTRL_REG_STATUS_BIT) > > + { > > + continue; > > + } > > + > > + return EFI_SUCCESS; > > +} > > + > > +/** > > + Create Nor flash Instance for given region. > > + > > + @param[in] HostRegisterBase Base address of Nor flash controller. > > + @param[in] NorFlashDeviceBase Base address of flash device. > > + @param[in] NorFlashRegionBase Base address of flash region on device. > > + @param[in] NorFlashSize Size of flash region. > > + @param[in] Index Index of given flash region. > > + @param[in] BlockSize Block size of NOR flash device. > > + @param[in] HasVarStore Boolean set for VarStore on given region. > > + @param[out] NorFlashInstance Instance of given flash region. > > + > > + @retval EFI_SUCCESS On successful creation of NOR flash instance. > > +**/ > > +EFI_STATUS > > +NorFlashCreateInstance ( > > + IN UINTN HostRegisterBase, > > + IN UINTN NorFlashDeviceBase, > > + IN UINTN NorFlashRegionBase, > > + IN UINTN NorFlashSize, > > + IN UINT32 Index, > > + IN UINT32 BlockSize, > > + IN BOOLEAN HasVarStore, > > + OUT NOR_FLASH_INSTANCE **NorFlashInstance > > + ) > > +{ > > + EFI_STATUS Status; > > + NOR_FLASH_INSTANCE *Instance; > > + NOR_FLASH_INFO *FlashInfo; > > + UINT8 JedecId[3]; > > + > > + ASSERT (NorFlashInstance != NULL); > > + Instance = AllocateRuntimeCopyPool ( > > + sizeof (mNorFlashInstanceTemplate), > > + &mNorFlashInstanceTemplate > > + ); > > + if (Instance == NULL) { > > + return EFI_OUT_OF_RESOURCES; > > + } > > + > > + Instance->HostRegisterBaseAddress = HostRegisterBase; > > + Instance->DeviceBaseAddress = NorFlashDeviceBase; > > + Instance->RegionBaseAddress = NorFlashRegionBase; > > + Instance->Size = NorFlashSize; > > + Instance->BlockSize = BlockSize; > > + Instance->LastBlock = (NorFlashSize / BlockSize) - 1; > > + > > + Instance->OffsetLba = (NorFlashRegionBase - NorFlashDeviceBase) / BlockSize; > > + > > + CopyGuid (&Instance->DevicePath.Vendor.Guid, &gEfiCallerIdGuid); > > + Instance->DevicePath.Index = (UINT8)Index; > > + > > + Status = NorFlashReadID (Instance, JedecId); > > + if (EFI_ERROR (Status)) { > > + goto FreeInstance; > > + } > > + > > + Status = NorFlashGetInfo (JedecId, &FlashInfo, TRUE); > > + if (EFI_ERROR (Status)) { > > + goto FreeInstance; > > + } > > + > > + NorFlashPrintInfo (FlashInfo); > > + > > + Instance->Flags = 0; > > + if (FlashInfo->Flags & NOR_FLASH_WRITE_FSR) { > > + Instance->Flags = NOR_FLASH_POLL_FSR; > > + } > > + > > + Instance->ShadowBuffer = AllocateRuntimePool (BlockSize); > > + if (Instance->ShadowBuffer == NULL) { > > + Status = EFI_OUT_OF_RESOURCES; > > + goto FreeInstance; > > + } > > + > > + if (HasVarStore) { > > + Instance->Initialize = NorFlashFvbInitialize; > > + } > > + > > + *NorFlashInstance = Instance; > > + FreePool (FlashInfo); > > + return EFI_SUCCESS; > > + > > +FreeInstance: > > + FreePool (Instance); > > + return Status; > > +} > > + > > +/** > > + Converts milliseconds into number of ticks of the performance counter. > > + > > + @param[in] Milliseconds Milliseconds to convert into ticks. > > + > > + @retval Milliseconds expressed as number of ticks. > > + > > +**/ > > +STATIC > > +UINT64 > > +MilliSecondsToTicks ( > > + IN UINTN Milliseconds > > + ) > > +{ > > + CONST UINT64 NanoSecondsPerTick = GetTimeInNanoSecond (1); > > + > > + return (Milliseconds * 1000000) / NanoSecondsPerTick; > > +} > > + > > +/** > > + Poll Status register for NOR flash erase/write completion. > > + > > + @param[in] Instance NOR flash Instance. > > + > > + @retval EFI_SUCCESS Request is executed successfully. > > + @retval EFI_TIMEOUT Operation timed out. > > + @retval EFI_DEVICE_ERROR Controller operartion failed. > > + > > +**/ > > +STATIC > > +EFI_STATUS > > +NorFlashPollStatusRegister ( > > + IN NOR_FLASH_INSTANCE *Instance > > + ) > > +{ > > + BOOLEAN SRegDone; > > + UINT32 val; > > + > > + val = SPINOR_OP_RDSR << CDNS_QSPI_FLASH_CMD_CTRL_REG_OPCODE_BIT_POS | > > + CDNS_QSPI_FLASH_CMD_CTRL_REG_READ_ENABLE << CDNS_QSPI_FLASH_CMD_CTRL_REG_READEN_BIT_POS | > > + CDNS_QSPI_FLASH_CMD_CTRL_REG_NUM_DATA_BYTES (1) | > > + CDNS_QSPI_FLASH_CMD_CTRL_REG_DUMMY_8C << CDNS_QSPI_FLASH_CMD_CTRL_REG_DUMMY_BIT_POS; > > + > > + CONST UINT64 TickOut = > > + GetPerformanceCounter () + MilliSecondsToTicks (SPINOR_SR_WIP_POLL_TIMEOUT_MS); > > + > > + do { > > + if (GetPerformanceCounter () > TickOut) { > > + DEBUG (( > > + DEBUG_ERROR, > > + "NorFlashPollStatusRegister: Timeout waiting for erase/write.\n" > > + )); > > + return EFI_TIMEOUT; > > + } > > + > > + if (EFI_ERROR (CdnsQspiExecuteCommand (Instance, val))) { > > + return EFI_DEVICE_ERROR; > > + } > > + > > + SRegDone = > > + (MmioRead8 (Instance->HostRegisterBaseAddress + CDNS_QSPI_FLASH_CMD_READ_DATA_REG_OFFSET) > > + & SPINOR_SR_WIP) == 0; > > + } while (!SRegDone); > > + > > + return EFI_SUCCESS; > > +} > > + > > +/** > > + Check whether NOR flash opertions are Locked. > > + > > + @param[in] Instance NOR flash Instance. > > + @param[in] BlockAddress BlockAddress in NOR flash device. > > + > > + @retval FALSE If NOR flash is not locked. > > +**/ > > +STATIC > > +BOOLEAN > > +NorFlashBlockIsLocked ( > > + IN NOR_FLASH_INSTANCE *Instance, > > + IN UINTN BlockAddress > > + ) > > +{ > > + return FALSE; > > +} > > + > > +/** > > + Unlock NOR flash operations on given block. > > + > > + @param[in] Instance NOR flash instance. > > + @param[in] BlockAddress BlockAddress in NOR flash device. > > + > > + @retval EFI_SUCCESS NOR flash operations is unlocked. > > +**/ > > +STATIC > > +EFI_STATUS > > +NorFlashUnlockSingleBlock ( > > + IN NOR_FLASH_INSTANCE *Instance, > > + IN UINTN BlockAddress > > + ) > > +{ > > + return EFI_SUCCESS; > > +} > > + > > +/** > > + Unlock NOR flash operations if it is necessary. > > + > > + @param[in] Instance NOR flash instance. > > + @param[in] BlockAddress BlockAddress in NOR flash device. > > + > > + @retval EFI_SUCCESS Request is executed successfully. > > +**/ > > +STATIC > > +EFI_STATUS > > +NorFlashUnlockSingleBlockIfNecessary ( > > + IN NOR_FLASH_INSTANCE *Instance, > > + IN UINTN BlockAddress > > + ) > > +{ > > + EFI_STATUS Status; > > + > > + Status = EFI_SUCCESS; > > + > > + if (!NorFlashBlockIsLocked (Instance, BlockAddress)) { > > + Status = NorFlashUnlockSingleBlock (Instance, BlockAddress); > > + } > > + > > + return Status; > > +} > > + > > +/** > > + Enable write to NOR flash device. > > + > > + @param[in] Instance NOR flash instance. > > + > > + @retval EFI_SUCCESS Request is executed successfully. > > +**/ > > +STATIC > > +EFI_STATUS > > +NorFlashEnableWrite ( > > + IN NOR_FLASH_INSTANCE *Instance > > + ) > > +{ > > + UINT32 val; > > + > > + DEBUG ((DEBUG_INFO, "NorFlashEnableWrite()\n")); > > + val = (SPINOR_OP_WREN << CDNS_QSPI_FLASH_CMD_CTRL_REG_OPCODE_BIT_POS); > > + if (EFI_ERROR (CdnsQspiExecuteCommand (Instance, val))) { > > + return EFI_DEVICE_ERROR; > > + } > > + > > + return EFI_SUCCESS; > > +} > > + > > +/** > > + The following function presumes that the block has already been unlocked. > > + > > + @param[in] Instance NOR flash instance. > > + @param[in] BlockAddress Block address within the variable region. > > + > > + @retval EFI_SUCCESS Request is executed successfully. > > + **/ > > +EFI_STATUS > > +NorFlashEraseSingleBlock ( > > + IN NOR_FLASH_INSTANCE *Instance, > > + IN UINTN BlockAddress > > + ) > > +{ > > + UINT32 DevConfigVal; > > + UINT32 EraseOffset; > > + > > + EraseOffset = 0x0; > > + > > + DEBUG (( > > + DEBUG_INFO, > > + "NorFlashEraseSingleBlock(BlockAddress=0x%08x)\n", > > + BlockAddress > > + )); > > + > > + if (EFI_ERROR (NorFlashEnableWrite (Instance))) { > > + return EFI_DEVICE_ERROR; > > + } > > + > > + EraseOffset = BlockAddress - Instance->DeviceBaseAddress; > > + > > + MmioWrite32 ( > > + Instance->HostRegisterBaseAddress + CDNS_QSPI_FLASH_CMD_ADDR_REG_OFFSET, > > + EraseOffset > > + ); > > + > > + DevConfigVal = SPINOR_OP_BE_4K << CDNS_QSPI_FLASH_CMD_CTRL_REG_OPCODE_BIT_POS | > > + CDNS_QSPI_FLASH_CMD_CTRL_REG_ADDR_ENABLE << CDNS_QSPI_FLASH_CMD_CTRL_REG_ADDR_BIT_POS | > > + CDNS_QSPI_FLASH_CMD_CTRL_REG_NUM_ADDR_BYTES (3); > > + > > + if (EFI_ERROR (CdnsQspiExecuteCommand (Instance, DevConfigVal))) { > > + return EFI_DEVICE_ERROR; > > + } > > + > > + if (EFI_ERROR (NorFlashPollStatusRegister (Instance))) { > > + return EFI_DEVICE_ERROR; > > + } > > + > > + return EFI_SUCCESS; > > +} > > + > > +/** > > + This function unlock and erase an entire NOR Flash block. > > + > > + @param[in] Instance NOR flash Instance of variable store region. > > + @param[in] BlockAddress Block address within the variable store region. > > + > > + @retval EFI_SUCCESS The erase and unlock successfully completed. > > +**/ > > +EFI_STATUS > > +NorFlashUnlockAndEraseSingleBlock ( > > + IN NOR_FLASH_INSTANCE *Instance, > > + IN UINTN BlockAddress > > + ) > > +{ > > + EFI_STATUS Status; > > + UINTN Index; > > + NOR_FLASH_LOCK_CONTEXT Lock; > > + > > + NorFlashLock (&Lock); > > + > > + Index = 0; > > + do { > > + // Unlock the block if we have to > > + Status = NorFlashUnlockSingleBlockIfNecessary (Instance, BlockAddress); > > + if (EFI_ERROR (Status)) { > > + break; > > + } > > + > > + Status = NorFlashEraseSingleBlock (Instance, BlockAddress); > > + if (EFI_ERROR (Status)) { > > + break; > > + } > > + > > + Index++; > > + } while ((Index < NOR_FLASH_ERASE_RETRY) && (Status == EFI_WRITE_PROTECTED)); > > + > > + if (Index == NOR_FLASH_ERASE_RETRY) { > > + DEBUG (( > > + DEBUG_ERROR, > > + "EraseSingleBlock(BlockAddress=0x%08x: Block Locked Error (try to erase %d times)\n", > > + BlockAddress, > > + Index > > + )); > > + } > > + > > + NorFlashUnlock (&Lock); > > + > > + return Status; > > +} > > + > > +/** > > + Write a single word to given location. > > + > > + @param[in] Instance NOR flash Instance of variable store region. > > + @param[in] WordAddress The address in NOR flash to write given word. > > + @param[in] WriteData The data to write into NOR flash location. > > + > > + @retval EFI_SUCCESS The write is completed. > > +**/ > > +STATIC > > +EFI_STATUS > > +NorFlashWriteSingleWord ( > > + IN NOR_FLASH_INSTANCE *Instance, > > + IN UINTN WordAddress, > > + IN UINT32 WriteData > > + ) > > +{ > > + DEBUG (( > > + DEBUG_INFO, > > + "NorFlashWriteSingleWord(WordAddress=0x%08x, WriteData=0x%08x)\n", > > + WordAddress, > > + WriteData > > + )); > > + > > + if (EFI_ERROR (NorFlashEnableWrite (Instance))) { > > + return EFI_DEVICE_ERROR; > > + } > > + > > + MmioWrite32 (WordAddress, WriteData); > > + if (EFI_ERROR (NorFlashPollStatusRegister (Instance))) { > > + return EFI_DEVICE_ERROR; > > + } > > + > > + return EFI_SUCCESS; > > +} > > + > > +/** > > + Write a full block to given location. > > + > > + @param[in] Instance NOR flash Instance of variable store region. > > + @param[in] Lba The logical block address in NOR flash. > > + @param[in] DataBuffer The data to write into NOR flash location. > > + @param[in] BlockSizeInWords The number of bytes to write. > > + > > + @retval EFI_SUCCESS The write is completed. > > +**/ > > +STATIC > > +EFI_STATUS > > +NorFlashWriteFullBlock ( > > + IN NOR_FLASH_INSTANCE *Instance, > > + IN EFI_LBA Lba, > > + IN UINT32 *DataBuffer, > > + IN UINT32 BlockSizeInWords > > + ) > > +{ > > + EFI_STATUS Status; > > + UINTN WordAddress; > > + UINT32 WordIndex; > > + UINTN BlockAddress; > > + NOR_FLASH_LOCK_CONTEXT Lock; > > + > > + Status = EFI_SUCCESS; > > + > > + // Get the physical address of the block > > + BlockAddress = GET_NOR_BLOCK_ADDRESS ( > > + Instance->RegionBaseAddress, > > + Lba, > > + BlockSizeInWords * 4 > > + ); > > + > > + // Start writing from the first address at the start of the block > > + WordAddress = BlockAddress; > > + > > + NorFlashLock (&Lock); > > + > > + Status = NorFlashUnlockAndEraseSingleBlock (Instance, BlockAddress); > > + if (EFI_ERROR (Status)) { > > + DEBUG (( > > + DEBUG_ERROR, > > + "WriteSingleBlock: ERROR - Failed to Unlock and Erase the single block at 0x%X\n", > > + BlockAddress > > + )); > > + goto EXIT; > > + } > > + > > + for (WordIndex = 0; > > + WordIndex < BlockSizeInWords; > > + WordIndex++, DataBuffer++, WordAddress += 4) > > + { > > + Status = NorFlashWriteSingleWord (Instance, WordAddress, *DataBuffer); > > + if (EFI_ERROR (Status)) { > > + goto EXIT; > > + } > > + } > > + > > +EXIT: > > + NorFlashUnlock (&Lock); > > + > > + if (EFI_ERROR (Status)) { > > + DEBUG (( > > + DEBUG_ERROR, > > + "NOR FLASH Programming [WriteSingleBlock] failed at address 0x%08x. Exit Status = %r.\n", > > + WordAddress, > > + Status > > + )); > > + } > > + > > + return Status; > > +} > > + > > +/** > > + Write a full block. > > + > > + @param[in] Instance NOR flash Instance of variable store region. > > + @param[in] Lba The starting logical block index. > > + @param[in] BufferSizeInBytes The number of bytes to read. > > + @param[in] Buffer The pointer to a caller-allocated buffer that > > + contains the source for the write. > > + > > + @retval EFI_SUCCESS The write is completed. > > +**/ > > +EFI_STATUS > > +NorFlashWriteBlocks ( > > + IN NOR_FLASH_INSTANCE *Instance, > > + IN EFI_LBA Lba, > > + IN UINTN BufferSizeInBytes, > > + IN VOID *Buffer > > + ) > > +{ > > + UINT32 *pWriteBuffer; > > + EFI_STATUS Status; > > + EFI_LBA CurrentBlock; > > + UINT32 BlockSizeInWords; > > + UINT32 NumBlocks; > > + UINT32 BlockCount; > > + > > + Status = EFI_SUCCESS; > > + // The buffer must be valid > > + if (Buffer == NULL) { > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + // We must have some bytes to read > > + DEBUG (( > > + DEBUG_INFO, > > + "NorFlashWriteBlocks: BufferSizeInBytes=0x%x\n", > > + BufferSizeInBytes > > + )); > > + if (BufferSizeInBytes == 0) { > > + return EFI_BAD_BUFFER_SIZE; > > + } > > + > > + // The size of the buffer must be a multiple of the block size > > + DEBUG (( > > + DEBUG_INFO, > > + "NorFlashWriteBlocks: BlockSize in bytes =0x%x\n", > > + Instance->BlockSize > > + )); > > + if ((BufferSizeInBytes % Instance->BlockSize) != 0) { > > + return EFI_BAD_BUFFER_SIZE; > > + } > > + > > + // All blocks must be within the device > > + NumBlocks = ((UINT32)BufferSizeInBytes) / Instance->BlockSize; > > + > > + DEBUG (( > > + DEBUG_INFO, > > + "NorFlashWriteBlocks: NumBlocks=%d, LastBlock=%ld, Lba=%ld.\n", > > + NumBlocks, > > + Instance->LastBlock, > > + Lba > > + )); > > + > > + if ((Lba + NumBlocks) > (Instance->LastBlock + 1)) { > > + DEBUG (( > > + DEBUG_ERROR, > > + "NorFlashWriteBlocks: ERROR - Write will exceed last block.\n" > > + )); > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + ASSERT (((UINTN)Buffer % sizeof (UINT32)) == 0); > > + > > + BlockSizeInWords = Instance->BlockSize / 4; > > + > > + // 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 *ReadBuffer > > + pWriteBuffer = (UINT32 *)Buffer; > > + > > + CurrentBlock = Lba; > > + for (BlockCount = 0; > > + BlockCount < NumBlocks; > > + BlockCount++, CurrentBlock++, pWriteBuffer += BlockSizeInWords) > > + { > > + DEBUG (( > > + DEBUG_INFO, > > + "NorFlashWriteBlocks: Writing block #%d\n", > > + (UINTN)CurrentBlock > > + )); > > + > > + Status = NorFlashWriteFullBlock ( > > + Instance, > > + CurrentBlock, > > + pWriteBuffer, > > + BlockSizeInWords > > + ); > > + > > + if (EFI_ERROR (Status)) { > > + break; > > + } > > + } > > + > > + DEBUG ((DEBUG_INFO, "NorFlashWriteBlocks: Exit Status = %r.\n", Status)); > > + return Status; > > +} > > + > > +/** > > + Read a full block. > > + > > + @param[in] Instance NOR flash Instance of variable store region. > > + @param[in] Lba The starting logical block index to read from. > > + @param[in] BufferSizeInBytes The number of bytes to read. > > + @param[out] Buffer The pointer to a caller-allocated buffer that > > + should be copied with read data. > > + > > + @retval EFI_SUCCESS The read is completed. > > +**/ > > +EFI_STATUS > > +NorFlashReadBlocks ( > > + IN NOR_FLASH_INSTANCE *Instance, > > + IN EFI_LBA Lba, > > + IN UINTN BufferSizeInBytes, > > + OUT VOID *Buffer > > + ) > > +{ > > + UINT32 NumBlocks; > > + UINTN StartAddress; > > + > > + DEBUG (( > > + DEBUG_INFO, > > + "NorFlashReadBlocks: BufferSize=0x%xB BlockSize=0x%xB LastBlock=%ld, Lba=%ld.\n", > > + BufferSizeInBytes, > > + Instance->BlockSize, > > + Instance->LastBlock, > > + Lba > > + )); > > + > > + // The buffer must be valid > > + if (Buffer == NULL) { > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + // Return if we do not have any byte to read > > + if (BufferSizeInBytes == 0) { > > + return EFI_SUCCESS; > > + } > > + > > + // The size of the buffer must be a multiple of the block size > > + if ((BufferSizeInBytes % Instance->BlockSize) != 0) { > > + return EFI_BAD_BUFFER_SIZE; > > + } > > + > > + NumBlocks = ((UINT32)BufferSizeInBytes) / Instance->BlockSize; > > + > > + if ((Lba + NumBlocks) > (Instance->LastBlock + 1)) { > > + DEBUG (( > > + DEBUG_ERROR, > > + "NorFlashReadBlocks: ERROR - Read will exceed last block\n" > > + )); > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + // Get the address to start reading from > > + StartAddress = GET_NOR_BLOCK_ADDRESS ( > > + Instance->RegionBaseAddress, > > + Lba, > > + Instance->BlockSize > > + ); > > + > > + // Readout the data > > + CopyMem (Buffer, (UINTN *)StartAddress, BufferSizeInBytes); > > + > > + return EFI_SUCCESS; > > +} > > + > > +/** > > + Read from nor flash. > > + > > + @param[in] Instance NOR flash Instance of variable store region. > > + @param[in] Lba The starting logical block index to read from. > > + @param[in] Offset Offset into the block at which to begin reading. > > + @param[in] BufferSizeInBytes The number of bytes to read. > > + @param[out] Buffer The pointer to a caller-allocated buffer that > > + should copied with read data. > > + > > + @retval EFI_SUCCESS The read is completed. > > +**/ > > +EFI_STATUS > > +NorFlashRead ( > > + IN NOR_FLASH_INSTANCE *Instance, > > + IN EFI_LBA Lba, > > + IN UINTN Offset, > > + IN UINTN BufferSizeInBytes, > > + OUT VOID *Buffer > > + ) > > +{ > > + UINTN StartAddress; > > + > > + // The buffer must be valid > > + if (Buffer == NULL) { > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + // Return if we do not have any byte to read > > + if (BufferSizeInBytes == 0) { > > + return EFI_SUCCESS; > > + } > > + > > + if (((Lba * Instance->BlockSize) + Offset + BufferSizeInBytes) > > > + Instance->Size) > > + { > > + DEBUG (( > > + DEBUG_ERROR, > > + "NorFlashRead: ERROR - Read will exceed device size.\n" > > + )); > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + // Get the address to start reading from > > + StartAddress = GET_NOR_BLOCK_ADDRESS ( > > + Instance->RegionBaseAddress, > > + Lba, > > + Instance->BlockSize > > + ); > > + > > + // Readout the data > > + CopyMem (Buffer, (UINTN *)(StartAddress + Offset), BufferSizeInBytes); > > + > > + return EFI_SUCCESS; > > +} > > + > > +/** > > + Write a full or portion of a block. > > + > > + @param[in] Instance NOR flash Instance of variable store region. > > + @param[in] Lba The starting logical block index to write to. > > + @param[in] Offset Offset into the block at which to begin writing. > > + @param[in, out] NumBytes The total size of the buffer. > > + @param[in] Buffer The pointer to a caller-allocated buffer that > > + contains the source for the write. > > + > > + @retval EFI_SUCCESS The write is completed. > > +**/ > > +EFI_STATUS > > +NorFlashWriteSingleBlock ( > > + IN NOR_FLASH_INSTANCE *Instance, > > + IN EFI_LBA Lba, > > + IN UINTN Offset, > > + IN OUT UINTN *NumBytes, > > + IN UINT8 *Buffer > > + ) > > +{ > > + EFI_STATUS Status; > > + UINT32 Tmp; > > + UINT32 TmpBuf; > > + UINT32 WordToWrite; > > + UINT32 Mask; > > + BOOLEAN DoErase; > > + UINTN BytesToWrite; > > + UINTN CurOffset; > > + UINTN WordAddr; > > + UINTN BlockSize; > > + UINTN BlockAddress; > > + UINTN PrevBlockAddress; > > + > > + if (Buffer == NULL) { > > + DEBUG (( > > + DEBUG_ERROR, > > + "NorFlashWriteSingleBlock: ERROR - Buffer is invalid\n" > > + )); > > + return EFI_OUT_OF_RESOURCES; > > + } > > + > > + PrevBlockAddress = 0; > > + if (!Instance->Initialized && Instance->Initialize) { > > + Instance->Initialize (Instance); > > + } > > + > > + DEBUG (( > > + DEBUG_INFO, > > + "NorFlashWriteSingleBlock(Parameters: Lba=%ld, Offset=0x%x, *NumBytes=0x%x, Buffer @ 0x%08x)\n", > > + Lba, > > + Offset, > > + *NumBytes, > > + Buffer > > + )); > > + > > + // Localise the block size to avoid de-referencing pointers all the time > > + BlockSize = Instance->BlockSize; > > + > > + // The write must not span block boundaries. > > + // We need to check each variable individually because adding two large > > + // values together overflows. > > + if ((Offset >= BlockSize) || > > + (*NumBytes > BlockSize) || > > + ((Offset + *NumBytes) > BlockSize)) > > + { > > + DEBUG (( > > + DEBUG_ERROR, > > + "NorFlashWriteSingleBlock: ERROR - EFI_BAD_BUFFER_SIZE: (Offset=0x%x + NumBytes=0x%x) > BlockSize=0x%x\n", > > + Offset, > > + *NumBytes, > > + BlockSize > > + )); > > + return EFI_BAD_BUFFER_SIZE; > > + } > > + > > + // We must have some bytes to write > > + if (*NumBytes == 0) { > > + DEBUG (( > > + DEBUG_ERROR, > > + "NorFlashWriteSingleBlock: ERROR - EFI_BAD_BUFFER_SIZE: (Offset=0x%x + NumBytes=0x%x) > BlockSize=0x%x\n", > > + Offset, > > + *NumBytes, > > + BlockSize > > + )); > > + return EFI_BAD_BUFFER_SIZE; > > + } > > + > > + // 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) { > > + // Check to see if we need to erase before programming the data into NOR. > > + // 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 = FALSE; > > + BytesToWrite = *NumBytes; > > + CurOffset = Offset; > > + > > + while (BytesToWrite > 0) { > > + // Read full word from NOR, splice as required. A word is the smallest > > + // unit we can write. > > + Status = NorFlashRead ( > > + Instance, > > + Lba, > > + CurOffset & ~(0x3), > > + sizeof (Tmp), > > + &Tmp > > + ); > > + if (EFI_ERROR (Status)) { > > + return EFI_DEVICE_ERROR; > > + } > > + > > + // Physical address of word in NOR to write. > > + WordAddr = (CurOffset & ~(0x3)) + > > + GET_NOR_BLOCK_ADDRESS ( > > + Instance->RegionBaseAddress, > > + Lba, > > + BlockSize > > + ); > > + > > + // The word of data that is to be written. > > + TmpBuf = ReadUnaligned32 ((UINT32 *)(Buffer + (*NumBytes - BytesToWrite))); > > + > > + // First do word aligned chunks. > > + if ((CurOffset & 0x3) == 0) { > > + if (BytesToWrite >= 4) { > > + // Is the destination still in 'erased' state? > > + if (~Tmp != 0) { > > + // Check to see if we are only changing bits to zero. > > + if ((Tmp ^ TmpBuf) & TmpBuf) { > > + DoErase = TRUE; > > + break; > > + } > > + } > > + > > + // Write this word to NOR > > + WordToWrite = TmpBuf; > > + CurOffset += sizeof (TmpBuf); > > + BytesToWrite -= sizeof (TmpBuf); > > + } else { > > + // BytesToWrite < 4. Do small writes and left-overs > > + Mask = ~((~0) << (BytesToWrite * 8)); > > + // Mask out the bytes we want. > > + TmpBuf &= Mask; > > + // Is the destination still in 'erased' state? > > + if ((Tmp & Mask) != Mask) { > > + // Check to see if we are only changing bits to zero. > > + if ((Tmp ^ TmpBuf) & TmpBuf) { > > + DoErase = TRUE; > > + break; > > + } > > + } > > + > > + // Merge old and new data. Write merged word to NOR > > + WordToWrite = (Tmp & ~Mask) | TmpBuf; > > + CurOffset += BytesToWrite; > > + BytesToWrite = 0; > > + } > > + } else { > > + // Do multiple words, but starting unaligned. > > + if (BytesToWrite > (4 - (CurOffset & 0x3))) { > > + Mask = ((~0) << ((CurOffset & 0x3) * 8)); > > + // Mask out the bytes we want. > > + TmpBuf &= Mask; > > + // Is the destination still in 'erased' state? > > + if ((Tmp & Mask) != Mask) { > > + // Check to see if we are only changing bits to zero. > > + if ((Tmp ^ TmpBuf) & TmpBuf) { > > + DoErase = TRUE; > > + break; > > + } > > + } > > + > > + // Merge old and new data. Write merged word to NOR > > + WordToWrite = (Tmp & ~Mask) | TmpBuf; > > + BytesToWrite -= (4 - (CurOffset & 0x3)); > > + CurOffset += (4 - (CurOffset & 0x3)); > > + } else { > > + // Unaligned and fits in one word. > > + Mask = (~((~0) << (BytesToWrite * 8))) << ((CurOffset & 0x3) * 8); > > + // Mask out the bytes we want. > > + TmpBuf = (TmpBuf << ((CurOffset & 0x3) * 8)) & Mask; > > + // Is the destination still in 'erased' state? > > + if ((Tmp & Mask) != Mask) { > > + // Check to see if we are only changing bits to zero. > > + if ((Tmp ^ TmpBuf) & TmpBuf) { > > + DoErase = TRUE; > > + break; > > + } > > + } > > + > > + // Merge old and new data. Write merged word to NOR > > + WordToWrite = (Tmp & ~Mask) | TmpBuf; > > + CurOffset += BytesToWrite; > > + BytesToWrite = 0; > > + } > > + } > > + > > + BlockAddress = GET_NOR_BLOCK_ADDRESS ( > > + Instance->RegionBaseAddress, > > + Lba, > > + BlockSize > > + ); > > + if (BlockAddress != PrevBlockAddress) { > > + Status = NorFlashUnlockSingleBlockIfNecessary (Instance, BlockAddress); > > + if (EFI_ERROR (Status)) { > > + return EFI_DEVICE_ERROR; > > + } > > + > > + PrevBlockAddress = BlockAddress; > > + } > > + > > + Status = NorFlashWriteSingleWord (Instance, WordAddr, WordToWrite); > > + if (EFI_ERROR (Status)) { > > + return EFI_DEVICE_ERROR; > > + } > > + } > > + > > + // Exit if we got here and could write all the data. Otherwise do the > > + // Erase-Write cycle. > > + if (!DoErase) { > > + return EFI_SUCCESS; > > + } > > + } > > + > > + // 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; > > + } > > + > > + // Read NOR Flash data into shadow buffer > > + Status = NorFlashReadBlocks ( > > + Instance, > > + 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); > > + > > + // Write the modified buffer back to the NorFlash > > + Status = NorFlashWriteBlocks ( > > + Instance, > > + Lba, > > + BlockSize, > > + Instance->ShadowBuffer > > + ); > > + if (EFI_ERROR (Status)) { > > + // Return one of the pre-approved error statuses > > + return EFI_DEVICE_ERROR; > > + } > > + > > + return EFI_SUCCESS; > > +} > > + > > +/** > > + Read JEDEC ID of NOR flash device. > > + > > + @param[in] Instance NOR flash Instance of variable store region. > > + @param[out] JedecId JEDEC ID of NOR flash device. > > + > > + @retval EFI_SUCCESS The write is completed. > > +**/ > > +EFI_STATUS > > +NorFlashReadID ( > > + IN NOR_FLASH_INSTANCE *Instance, > > + OUT UINT8 JedecId[3] > > + ) > > +{ > > + UINT32 val; > > + > > + if ((Instance == NULL) || (JedecId == NULL)) { > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + val = SPINOR_OP_RDID << CDNS_QSPI_FLASH_CMD_CTRL_REG_OPCODE_BIT_POS | > > + CDNS_QSPI_FLASH_CMD_CTRL_REG_READ_ENABLE << CDNS_QSPI_FLASH_CMD_CTRL_REG_READEN_BIT_POS | > > + CDNS_QSPI_FLASH_CMD_CTRL_REG_NUM_DATA_BYTES (3); > > + > > + if (EFI_ERROR (CdnsQspiExecuteCommand (Instance, val))) { > > + return EFI_DEVICE_ERROR; > > + } > > + > > + val = MmioRead32 (Instance->HostRegisterBaseAddress + CDNS_QSPI_FLASH_CMD_READ_DATA_REG_OFFSET); > > + > > + // Manu.ID field > > + JedecId[0] = (UINT8)val; > > + // Type field > > + JedecId[1] = (UINT8)(val >> 8); > > + // Capacity field > > + JedecId[2] = (UINT8)(val >> 16); > > + > > + DEBUG (( > > + DEBUG_INFO, > > + "Nor flash detected, Jedec ID, Manu.Id=%x Type=%x Capacity=%x \n", > > + JedecId[0], > > + JedecId[1], > > + JedecId[2] > > + )); > > + > > + return EFI_SUCCESS; > > +} > > diff --git a/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/NorFlashFvb.c b/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/NorFlashFvb.c > new file mode 100644 > index 000000000000..8281d4825dc9 > --- /dev/null > +++ b/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/NorFlashFvb.c > @@ -0,0 +1,647 @@ > +/** @file > > + > > + Copyright (c) 2023, ARM Limited. All rights reserved.<BR> > > + > > + SPDX-License-Identifier: BSD-2-Clause-Patent > > + > > +**/ > > + > > +#include <Guid/VariableFormat.h> > > +#include <Guid/SystemNvDataGuid.h> > > + > > +#include <Library/BaseLib.h> > > +#include <Library/BaseMemoryLib.h> > > +#include <Library/MemoryAllocationLib.h> > > +#include <Library/PcdLib.h> > > +#include <Library/UefiBootServicesTableLib.h> > > +#include <Library/UefiLib.h> > > + > > +#include <PiDxe.h> > > + > > +#include "NorFlash.h" > > + > > +UINTN mFlashNvStorageVariableBase; > > + > > +/** > > + Initialize the FV Header and Variable Store Header > > + to support variable operations. > > + > > + @param[in] Instance Location to initialise the headers. > > + > > + @retval EFI_SUCCESS Fv init is done. > > + > > +**/ > > +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); > > + > > + 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_FVB2_READ_ENABLED_CAP | > > + EFI_FVB2_READ_STATUS | > > + EFI_FVB2_STICKY_WRITE | > > + EFI_FVB2_MEMORY_MAPPED | > > + EFI_FVB2_ERASE_POLARITY | > > + EFI_FVB2_WRITE_STATUS | > > + EFI_FVB2_WRITE_ENABLED_CAP; > > + > > + FirmwareVolumeHeader->HeaderLength = sizeof (EFI_FIRMWARE_VOLUME_HEADER) + > > + sizeof (EFI_FV_BLOCK_MAP_ENTRY); > > + FirmwareVolumeHeader->Revision = EFI_FVH_REVISION; > > + FirmwareVolumeHeader->BlockMap[0].NumBlocks = Instance->LastBlock + 1; > > + FirmwareVolumeHeader->BlockMap[0].Length = Instance->BlockSize; > > + FirmwareVolumeHeader->BlockMap[1].NumBlocks = 0; > > + FirmwareVolumeHeader->BlockMap[1].Length = 0; > > + FirmwareVolumeHeader->Checksum = CalculateCheckSum16 ( > > + (UINT16 *)FirmwareVolumeHeader, > > + FirmwareVolumeHeader->HeaderLength > > + ); > > + > > + VariableStoreHeader = (VOID *)((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] Instance Instance of Nor flash variable region. > > + > > + @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 > > + ) > > +{ > > + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; > > + VARIABLE_STORE_HEADER *VariableStoreHeader; > > + UINTN VariableStoreLength; > > + UINTN FvLength; > > + > > + FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)Instance->RegionBaseAddress; > > + > > + FvLength = PcdGet32 (PcdFlashNvStorageVariableSize) + > > + PcdGet32 (PcdFlashNvStorageFtwWorkingSize) + > > + PcdGet32 (PcdFlashNvStorageFtwSpareSize); > > + > > + if ( (FwVolHeader->Revision != EFI_FVH_REVISION) > > + || (FwVolHeader->Signature != EFI_FVH_SIGNATURE) > > + || (FwVolHeader->FvLength != FvLength) > > + ) > > + { > > + DEBUG (( > > + DEBUG_ERROR, > > + "%a: No Firmware Volume header present\n", > > + __func__ > > + )); > > + return EFI_NOT_FOUND; > > + } > > + > > + // Check the Firmware Volume Guid > > + if (!CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiSystemNvDataFvGuid)) { > > + DEBUG (( > > + DEBUG_ERROR, > > + "%a: Firmware Volume Guid non-compatible\n", > > + __func__ > > + )); > > + return EFI_NOT_FOUND; > > + } > > + > > + VariableStoreHeader = (VOID *)((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", > > + __func__ > > + )); > > + return EFI_NOT_FOUND; > > + } > > + > > + VariableStoreLength = PcdGet32 (PcdFlashNvStorageVariableSize) - > > + FwVolHeader->HeaderLength; > > + if (VariableStoreHeader->Size != VariableStoreLength) { > > + DEBUG (( > > + DEBUG_ERROR, > > + "%a: Variable Store Length does not match\n", > > + __func__ > > + )); > > + return EFI_NOT_FOUND; > > + } > > + > > + return EFI_SUCCESS; > > +} > > + > > +/** > > + Retrieves the attributes and current settings of the block. > > + > > + @param[in] This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance. > > + > > + @param[out] 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; > > + > > + FlashFvbAttributes = EFI_FVB2_READ_ENABLED_CAP | EFI_FVB2_READ_STATUS | > > + EFI_FVB2_WRITE_ENABLED_CAP | EFI_FVB2_WRITE_STATUS | > > + EFI_FVB2_STICKY_WRITE | EFI_FVB2_MEMORY_MAPPED | > > + EFI_FVB2_ERASE_POLARITY; > > + > > + *Attributes = FlashFvbAttributes; > > + > > + DEBUG ((DEBUG_INFO, "FvbGetAttributes(0x%X)\n", *Attributes)); > > + > > + return EFI_SUCCESS; > > +} > > + > > +/** > > + Sets configurable firmware volume attributes and returns the > > + new settings of the firmware volume. > > + > > + > > + @param[in] This EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance. > > + > > + @param[in, out] Attributes On input, Attributes is a pointer to > > + EFI_FVB_ATTRIBUTES_2 that contains the desired > > + firmware volume settings. > > + On successful return, it contains the new > > + settings of the firmware volume. > > + > > + @retval EFI_UNSUPPORTED The firmware volume attributes are not supported. > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +FvbSetAttributes ( > > + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, > > + IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes > > + ) > > +{ > > + DEBUG (( > > + DEBUG_INFO, > > + "FvbSetAttributes(0x%X) is not supported\n", > > + *Attributes > > + )); > > + return EFI_UNSUPPORTED; > > +} > > + > > +/** > > + Retrieves the base address of a memory-mapped firmware volume. > > + This function should be called only for memory-mapped firmware volumes. > > + > > + @param[in] This EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance. > > + > > + @param[out] 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. > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +FvbGetPhysicalAddress ( > > + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, > > + OUT EFI_PHYSICAL_ADDRESS *Address > > + ) > > +{ > > + NOR_FLASH_INSTANCE *Instance; > > + > > + Instance = INSTANCE_FROM_FVB_THIS (This); > > + > > + DEBUG (( > > + DEBUG_INFO, > > + "FvbGetPhysicalAddress(BaseAddress=0x%08x)\n", > > + Instance->RegionBaseAddress > > + )); > > + > > + ASSERT (Address != NULL); > > + > > + *Address = Instance->RegionBaseAddress; > > + return EFI_SUCCESS; > > +} > > + > > +/** > > + 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[in] This EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance. > > + > > + @param[in] Lba Indicates the block whose size to return > > + > > + @param[out] BlockSize Pointer to a caller-allocated UINTN in which > > + the size of the block is returned. > > + > > + @param[out] 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_INFO, > > + "FvbGetBlockSize(Lba=%ld, BlockSize=0x%x, LastBlock=%ld)\n", > > + Lba, > > + Instance->BlockSize, > > + Instance->LastBlock > > + )); > > + > > + if (Lba > Instance->LastBlock) { > > + DEBUG (( > > + DEBUG_ERROR, > > + "FvbGetBlockSize: ERROR - Parameter LBA %ld is beyond the last Lba (%ld).\n", > > + Lba, > > + Instance->LastBlock > > + )); > > + Status = EFI_INVALID_PARAMETER; > > + } else { > > + // This is easy because in this platform each NorFlash device has equal sized blocks. > > + *BlockSize = (UINTN)Instance->BlockSize; > > + *NumberOfBlocks = (UINTN)(Instance->LastBlock - Lba + 1); > > + > > + DEBUG (( > > + DEBUG_INFO, > > + "FvbGetBlockSize: *BlockSize=0x%x, *NumberOfBlocks=0x%x.\n", > > + *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. > > + > > + @param[in] This EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance. > > + > > + @param[in] Lba The starting logical block index from which to read > > + > > + @param[in] Offset Offset into the block at which to begin reading. > > + > > + @param[in, out] NumBytes Pointer to a UINTN. > > + At entry, *NumBytes contains the total size of the > > + buffer. *NumBytes should have a non zero value. > > + At exit, *NumBytes contains the total number of > > + bytes read. > > + > > + @param[in, out] 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. > > + > > + @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 > > + ) > > +{ > > + EFI_STATUS Status; > > + UINTN BlockSize; > > + NOR_FLASH_INSTANCE *Instance; > > + > > + Instance = INSTANCE_FROM_FVB_THIS (This); > > + > > + DEBUG (( > > + DEBUG_INFO, > > + "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); > > + } > > + > > + BlockSize = Instance->BlockSize; > > + > > + DEBUG (( > > + DEBUG_INFO, > > + "FvbRead: Check if (Offset=0x%x + NumBytes=0x%x) <= BlockSize=0x%x\n", > > + Offset, > > + *NumBytes, > > + BlockSize > > + )); > > + > > + // The read must not span block boundaries. > > + // We need to check each variable individually because adding two large > > + // values together overflows. > > + if ((Offset >= BlockSize) || > > + (*NumBytes > BlockSize) || > > + ((Offset + *NumBytes) > BlockSize)) > > + { > > + DEBUG (( > > + DEBUG_ERROR, > > + "FvbRead: ERROR - EFI_BAD_BUFFER_SIZE: (Offset=0x%x + NumBytes=0x%x) > BlockSize=0x%x\n", > > + Offset, > > + *NumBytes, > > + BlockSize > > + )); > > + return EFI_BAD_BUFFER_SIZE; > > + } > > + > > + // We must have some bytes to read > > + if (*NumBytes == 0) { > > + return EFI_BAD_BUFFER_SIZE; > > + } > > + > > + // Decide if we are doing full block reads or not. > > + if (*NumBytes % BlockSize != 0) { > > + Status = NorFlashRead ( > > + Instance, > > + Instance->StartLba + Lba, > > + Offset, > > + *NumBytes, > > + Buffer > > + ); > > + } else { > > + // Read NOR Flash data into shadow buffer > > + Status = NorFlashReadBlocks ( > > + Instance, > > + Instance->StartLba + Lba, > > + BlockSize, > > + Buffer > > + ); > > + } > > + > > + if (EFI_ERROR (Status)) { > > + // Return one of the pre-approved error statuses > > + return EFI_DEVICE_ERROR; > > + } > > + > > + return EFI_SUCCESS; > > +} > > + > > +/** > > + Writes the specified number of bytes from the input buffer to the block. > > + > > + @param[in] This EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance. > > + > > + @param[in] Lba The starting logical block index to write to. > > + > > + @param[in] Offset Offset into the block at which to begin writing. > > + > > + @param[in, out] 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[in] Buffer The pointer to a caller-allocated buffer that > > + contains the source for the write. > > + > > + @retval EFI_SUCCESS The firmware volume was written successfully. > > + > > +**/ > > +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; > > + > > + Instance = INSTANCE_FROM_FVB_THIS (This); > > + > > + return NorFlashWriteSingleBlock ( > > + Instance, > > + Instance->StartLba + Lba, > > + Offset, > > + NumBytes, > > + Buffer > > + ); > > +} > > + > > +/** > > + Erases and initialises a firmware volume block. > > + > > + @param[in] This EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL > > + > > + @param[in] ... The variable argument list is a list of tuples. > > + Each tuple describes a range of LBAs to erase > > + and consists of the following: > > + - An EFI_LBA that indicates the starting LBA > > + - A UINTN that indicates the number of blocks > > + to erase. > > + > > + The list is terminated with an > > + EFI_LBA_LIST_TERMINATOR. > > + > > + @retval EFI_SUCCESS The erase request successfully completed. > > + > > + @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisabled > > + state. > > + > > + @retval EFI_DEVICE_ERROR The block device is not functioning correctly > > + and could not be written. > > + The firmware device may have been partially > > + erased. > > + > > + @retval EFI_INVALID_PARAMETER One or more of the LBAs listed in the variable > > + argument list do not exist in the firmware > > + volume. > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +FvbEraseBlocks ( > > + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, > > + ... > > + ) > > +{ > > + EFI_STATUS Status; > > + VA_LIST Args; > > + UINTN BlockAddress; // Physical address of Lba to erase > > + EFI_LBA StartingLba; // Lba from which we start erasing > > + UINTN NumOfLba; // Number of Lba blocks to erase > > + NOR_FLASH_INSTANCE *Instance; > > + > > + Instance = INSTANCE_FROM_FVB_THIS (This); > > + > > + DEBUG ((DEBUG_INFO, "FvbEraseBlocks()\n")); > > + > > + Status = EFI_SUCCESS; > > + > > + // 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) { > > + break; > > + } > > + > > + // How many Lba blocks are we requested to erase? > > + NumOfLba = VA_ARG (Args, UINT32); > > + > > + // All blocks must be within range > > + DEBUG (( > > + DEBUG_INFO, > > + "FvbEraseBlocks: Check if: ( StartingLba=%ld + NumOfLba=%d - 1 ) > LastBlock=%ld.\n", > > + Instance->StartLba + StartingLba, > > + NumOfLba, > > + Instance->LastBlock > > + )); > > + if ((NumOfLba == 0) || > > + ((Instance->StartLba + StartingLba + NumOfLba - 1) > > > + Instance->LastBlock)) > > + { > > + VA_END (Args); > > + DEBUG (( > > + DEBUG_ERROR, > > + "FvbEraseBlocks: ERROR - Lba range goes past the last Lba.\n" > > + )); > > + return EFI_INVALID_PARAMETER; > > + } > > + } while (TRUE); > > + > > + VA_END (Args); > > + > > + 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->BlockSize > > + ); > > + > > + // Erase it > > + DEBUG (( > > + DEBUG_INFO, > > + "FvbEraseBlocks: Erasing Lba=%ld @ 0x%08x.\n", > > + Instance->StartLba + StartingLba, > > + BlockAddress > > + )); > > + Status = NorFlashUnlockAndEraseSingleBlock (Instance, BlockAddress); > > + if (EFI_ERROR (Status)) { > > + VA_END (Args); > > + return EFI_DEVICE_ERROR; > > + } > > + > > + // Move to the next Lba > > + StartingLba++; > > + NumOfLba--; > > + } > > + } while (TRUE); > > + > > + VA_END (Args); > > + > > + return Status; > > +} > -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#112644): https://edk2.groups.io/g/devel/message/112644 Mute This Topic: https://groups.io/mt/102625036/7686176 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io] -=-=-=-=-=-=-=-=-=-=-=- ^ permalink raw reply [flat|nested] 17+ messages in thread
* [edk2-devel] [edk2-platforms][PATCH V1 4/5] Platform/ARM/N1Sdp: Persistent storage for N1Sdp 2023-11-16 11:45 [edk2-devel] [edk2-platforms][PATCH V1 0/5] Enable non volatile storage on N1SDP sahil ` (2 preceding siblings ...) 2023-11-16 11:45 ` [edk2-devel] [edk2-platforms][PATCH V1 3/5] Platform/ARM/N1Sdp: NOR flash Dxe Driver " sahil @ 2023-11-16 11:45 ` sahil 2023-12-07 14:48 ` Thomas Abraham 2023-12-18 15:13 ` Sami Mujawar 2023-11-16 11:45 ` [edk2-devel] [edk2-platforms][PATCH V1 5/5] Platform/ARM/N1Sdp: Enable FaultTolerantWrite Dxe driver " sahil 4 siblings, 2 replies; 17+ messages in thread From: sahil @ 2023-11-16 11:45 UTC (permalink / raw) To: devel; +Cc: Ard Biesheuvel, Leif Lindholm, Sami Mujawar, Sahil Enable persistent storage on QSPI flash device. Signed-off-by: sahil <sahil@arm.com> --- Platform/ARM/N1Sdp/N1SdpPlatform.dsc | 20 ++++++++++++++------ Platform/ARM/N1Sdp/N1SdpPlatform.fdf | 4 +++- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/Platform/ARM/N1Sdp/N1SdpPlatform.dsc b/Platform/ARM/N1Sdp/N1SdpPlatform.dsc index d04b22d3ef51..10fe2db9e1b1 100644 --- a/Platform/ARM/N1Sdp/N1SdpPlatform.dsc +++ b/Platform/ARM/N1Sdp/N1SdpPlatform.dsc @@ -4,7 +4,7 @@ # This provides platform specific component descriptions and libraries that # conform to EFI/Framework standards. # -# Copyright (c) 2018 - 2021, ARM Limited. All rights reserved.<BR> +# Copyright (c) 2018 - 2023, ARM Limited. All rights reserved.<BR> # # SPDX-License-Identifier: BSD-2-Clause-Patent # @@ -44,6 +44,9 @@ # file explorer library support FileExplorerLib|MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf + # NOR flash support + NorFlashInfoLib|EmbeddedPkg/Library/NorFlashInfoLib/NorFlashInfoLib.inf + [LibraryClasses.common.SEC] HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf @@ -161,11 +164,9 @@ # ACPI Table Version gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiExposedTableVersions|0x20 - # Runtime Variable storage - gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvStoreReserved|0 - gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvModeEnable|TRUE - gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x2000 - gEfiMdeModulePkgTokenSpaceGuid.PcdMaxAuthVariableSize|0x2800 + # NOR flash support + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase|0x18F00000 + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize|0x00020000 ################################################################################ # @@ -197,6 +198,12 @@ gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x8000000F } + # NOR flash support + Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiDxe.inf { + <LibraryClasses> + NorFlashPlatformLib|Silicon/ARM/NeoverseN1Soc/Library/NorFlashLib/NorFlashLib.inf + } + # Architectural Protocols ArmPkg/Drivers/CpuDxe/CpuDxe.inf ArmPkg/Drivers/ArmGic/ArmGicDxe.inf @@ -217,6 +224,7 @@ MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf { <LibraryClasses> NULL|MdeModulePkg/Library/VarCheckUefiLib/VarCheckUefiLib.inf + NULL|EmbeddedPkg/Library/NvVarStoreFormattedLib/NvVarStoreFormattedLib.inf BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf } diff --git a/Platform/ARM/N1Sdp/N1SdpPlatform.fdf b/Platform/ARM/N1Sdp/N1SdpPlatform.fdf index e5e24ea50294..4329f892f7c5 100644 --- a/Platform/ARM/N1Sdp/N1SdpPlatform.fdf +++ b/Platform/ARM/N1Sdp/N1SdpPlatform.fdf @@ -1,7 +1,7 @@ ## @file # FDF file of N1Sdp # -# Copyright (c) 2018 - 2021, ARM Limited. All rights reserved.<BR> +# Copyright (c) 2018 - 2023, ARM Limited. All rights reserved.<BR> # # SPDX-License-Identifier: BSD-2-Clause-Patent ## @@ -140,6 +140,8 @@ READ_LOCK_STATUS = TRUE INF ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdogDxe.inf INF ArmPkg/Drivers/TimerDxe/TimerDxe.inf + INF Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiDxe.inf + INF Platform/ARM/Drivers/BootMonFs/BootMonFs.inf INF MdeModulePkg/Universal/PCD/Dxe/Pcd.inf -- 2.25.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#111312): https://edk2.groups.io/g/devel/message/111312 Mute This Topic: https://groups.io/mt/102625037/7686176 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io] -=-=-=-=-=-=-=-=-=-=-=- ^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [edk2-devel] [edk2-platforms][PATCH V1 4/5] Platform/ARM/N1Sdp: Persistent storage for N1Sdp 2023-11-16 11:45 ` [edk2-devel] [edk2-platforms][PATCH V1 4/5] Platform/ARM/N1Sdp: Persistent storage " sahil @ 2023-12-07 14:48 ` Thomas Abraham 2023-12-18 15:13 ` Sami Mujawar 1 sibling, 0 replies; 17+ messages in thread From: Thomas Abraham @ 2023-12-07 14:48 UTC (permalink / raw) To: devel@edk2.groups.io, Sahil Kaushal Cc: Ard Biesheuvel, Leif Lindholm, Sami Mujawar, Chandni Cherukuri, nd > -----Original Message----- > From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of sahil via > groups.io > Sent: Thursday, November 16, 2023 11:46 AM > To: devel@edk2.groups.io > Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>; Leif Lindholm > <quic_llindhol@quicinc.com>; Sami Mujawar <Sami.Mujawar@arm.com>; > Sahil Kaushal <Sahil.Kaushal@arm.com> > Subject: [edk2-devel] [edk2-platforms][PATCH V1 4/5] Platform/ARM/N1Sdp: > Persistent storage for N1Sdp > > Enable persistent storage on QSPI flash device. > > Signed-off-by: sahil <sahil@arm.com> > --- > Platform/ARM/N1Sdp/N1SdpPlatform.dsc | 20 ++++++++++++++------ > Platform/ARM/N1Sdp/N1SdpPlatform.fdf | 4 +++- > 2 files changed, 17 insertions(+), 7 deletions(-) > > diff --git a/Platform/ARM/N1Sdp/N1SdpPlatform.dsc > b/Platform/ARM/N1Sdp/N1SdpPlatform.dsc > index d04b22d3ef51..10fe2db9e1b1 100644 > --- a/Platform/ARM/N1Sdp/N1SdpPlatform.dsc > +++ b/Platform/ARM/N1Sdp/N1SdpPlatform.dsc > @@ -4,7 +4,7 @@ > # This provides platform specific component descriptions and libraries that > > # conform to EFI/Framework standards. > > # > > -# Copyright (c) 2018 - 2021, ARM Limited. All rights reserved.<BR> > > +# Copyright (c) 2018 - 2023, ARM Limited. All rights reserved.<BR> > > # > > # SPDX-License-Identifier: BSD-2-Clause-Patent > > # > > @@ -44,6 +44,9 @@ > # file explorer library support > > FileExplorerLib|MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf > > > > + # NOR flash support > > + NorFlashInfoLib|EmbeddedPkg/Library/NorFlashInfoLib/NorFlashInfoLib.inf > > + > > [LibraryClasses.common.SEC] > > HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf > > > MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAll > ocationLib.inf > > @@ -161,11 +164,9 @@ > # ACPI Table Version > > gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiExposedTableVersions|0x20 > > > > - # Runtime Variable storage > > - gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvStoreReserved|0 > > - gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvModeEnable|TRUE > > - gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x2000 > > - gEfiMdeModulePkgTokenSpaceGuid.PcdMaxAuthVariableSize|0x2800 > > + # NOR flash support > > + > gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase|0x18F0000 > 0 > > + > gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize|0x0002000 > 0 > > > > > ################################################################ > ################ > > # > > @@ -197,6 +198,12 @@ > gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x8000000F > > } > > > > + # NOR flash support > > + Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiDxe.inf { > > + <LibraryClasses> > > + > NorFlashPlatformLib|Silicon/ARM/NeoverseN1Soc/Library/NorFlashLib/NorFlas > hLib.inf > > + } > > + > > # Architectural Protocols > > ArmPkg/Drivers/CpuDxe/CpuDxe.inf > > ArmPkg/Drivers/ArmGic/ArmGicDxe.inf > > @@ -217,6 +224,7 @@ > MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf { > > <LibraryClasses> > > NULL|MdeModulePkg/Library/VarCheckUefiLib/VarCheckUefiLib.inf > > + > NULL|EmbeddedPkg/Library/NvVarStoreFormattedLib/NvVarStoreFormattedLib. > inf > > BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf > > } > > > > diff --git a/Platform/ARM/N1Sdp/N1SdpPlatform.fdf > b/Platform/ARM/N1Sdp/N1SdpPlatform.fdf > index e5e24ea50294..4329f892f7c5 100644 > --- a/Platform/ARM/N1Sdp/N1SdpPlatform.fdf > +++ b/Platform/ARM/N1Sdp/N1SdpPlatform.fdf > @@ -1,7 +1,7 @@ > ## @file > > # FDF file of N1Sdp > > # > > -# Copyright (c) 2018 - 2021, ARM Limited. All rights reserved.<BR> > > +# Copyright (c) 2018 - 2023, ARM Limited. All rights reserved.<BR> > > # > > # SPDX-License-Identifier: BSD-2-Clause-Patent > > ## > > @@ -140,6 +140,8 @@ READ_LOCK_STATUS = TRUE > INF ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdogDxe.inf > > INF ArmPkg/Drivers/TimerDxe/TimerDxe.inf > > > > + INF Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiDxe.inf > > + > > INF Platform/ARM/Drivers/BootMonFs/BootMonFs.inf > > INF MdeModulePkg/Universal/PCD/Dxe/Pcd.inf > > > > -- > 2.25.1 Reviewed-by: Thomas Abraham <thomas.abraham@arm.com> -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#112195): https://edk2.groups.io/g/devel/message/112195 Mute This Topic: https://groups.io/mt/102625037/7686176 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io] -=-=-=-=-=-=-=-=-=-=-=- ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [edk2-devel] [edk2-platforms][PATCH V1 4/5] Platform/ARM/N1Sdp: Persistent storage for N1Sdp 2023-11-16 11:45 ` [edk2-devel] [edk2-platforms][PATCH V1 4/5] Platform/ARM/N1Sdp: Persistent storage " sahil 2023-12-07 14:48 ` Thomas Abraham @ 2023-12-18 15:13 ` Sami Mujawar 1 sibling, 0 replies; 17+ messages in thread From: Sami Mujawar @ 2023-12-18 15:13 UTC (permalink / raw) To: sahil, devel; +Cc: Ard Biesheuvel, Leif Lindholm, nd@arm.com Hi Sahil, Please see my response for Patch 3/5. Regards, Sami Mujawar On 16/11/2023 11:45 am, sahil wrote: > Enable persistent storage on QSPI flash device. > > Signed-off-by: sahil <sahil@arm.com> > --- > Platform/ARM/N1Sdp/N1SdpPlatform.dsc | 20 ++++++++++++++------ > Platform/ARM/N1Sdp/N1SdpPlatform.fdf | 4 +++- > 2 files changed, 17 insertions(+), 7 deletions(-) > > diff --git a/Platform/ARM/N1Sdp/N1SdpPlatform.dsc b/Platform/ARM/N1Sdp/N1SdpPlatform.dsc > index d04b22d3ef51..10fe2db9e1b1 100644 > --- a/Platform/ARM/N1Sdp/N1SdpPlatform.dsc > +++ b/Platform/ARM/N1Sdp/N1SdpPlatform.dsc > @@ -4,7 +4,7 @@ > # This provides platform specific component descriptions and libraries that > > # conform to EFI/Framework standards. > > # > > -# Copyright (c) 2018 - 2021, ARM Limited. All rights reserved.<BR> > > +# Copyright (c) 2018 - 2023, ARM Limited. All rights reserved.<BR> > > # > > # SPDX-License-Identifier: BSD-2-Clause-Patent > > # > > @@ -44,6 +44,9 @@ > # file explorer library support > > FileExplorerLib|MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf > > > > + # NOR flash support > > + NorFlashInfoLib|EmbeddedPkg/Library/NorFlashInfoLib/NorFlashInfoLib.inf > > + > > [LibraryClasses.common.SEC] > > HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf > > MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf > > @@ -161,11 +164,9 @@ > # ACPI Table Version > > gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiExposedTableVersions|0x20 > > > > - # Runtime Variable storage > > - gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvStoreReserved|0 > > - gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvModeEnable|TRUE > > - gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x2000 > > - gEfiMdeModulePkgTokenSpaceGuid.PcdMaxAuthVariableSize|0x2800 > > + # NOR flash support > > + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase|0x18F00000 > > + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize|0x00020000 > > > > ################################################################################ > > # > > @@ -197,6 +198,12 @@ > gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x8000000F > > } > > > > + # NOR flash support > > + Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiDxe.inf { > > + <LibraryClasses> > > + NorFlashPlatformLib|Silicon/ARM/NeoverseN1Soc/Library/NorFlashLib/NorFlashLib.inf > > + } > > + > > # Architectural Protocols > > ArmPkg/Drivers/CpuDxe/CpuDxe.inf > > ArmPkg/Drivers/ArmGic/ArmGicDxe.inf > > @@ -217,6 +224,7 @@ > MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf { > > <LibraryClasses> > > NULL|MdeModulePkg/Library/VarCheckUefiLib/VarCheckUefiLib.inf > > + NULL|EmbeddedPkg/Library/NvVarStoreFormattedLib/NvVarStoreFormattedLib.inf > > BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf > > } > > > > diff --git a/Platform/ARM/N1Sdp/N1SdpPlatform.fdf b/Platform/ARM/N1Sdp/N1SdpPlatform.fdf > index e5e24ea50294..4329f892f7c5 100644 > --- a/Platform/ARM/N1Sdp/N1SdpPlatform.fdf > +++ b/Platform/ARM/N1Sdp/N1SdpPlatform.fdf > @@ -1,7 +1,7 @@ > ## @file > > # FDF file of N1Sdp > > # > > -# Copyright (c) 2018 - 2021, ARM Limited. All rights reserved.<BR> > > +# Copyright (c) 2018 - 2023, ARM Limited. All rights reserved.<BR> > > # > > # SPDX-License-Identifier: BSD-2-Clause-Patent > > ## > > @@ -140,6 +140,8 @@ READ_LOCK_STATUS = TRUE > INF ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdogDxe.inf > > INF ArmPkg/Drivers/TimerDxe/TimerDxe.inf > > > > + INF Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiDxe.inf > > + > > INF Platform/ARM/Drivers/BootMonFs/BootMonFs.inf > > INF MdeModulePkg/Universal/PCD/Dxe/Pcd.inf > > > -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#112645): https://edk2.groups.io/g/devel/message/112645 Mute This Topic: https://groups.io/mt/102625037/7686176 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io] -=-=-=-=-=-=-=-=-=-=-=- ^ permalink raw reply [flat|nested] 17+ messages in thread
* [edk2-devel] [edk2-platforms][PATCH V1 5/5] Platform/ARM/N1Sdp: Enable FaultTolerantWrite Dxe driver for N1Sdp 2023-11-16 11:45 [edk2-devel] [edk2-platforms][PATCH V1 0/5] Enable non volatile storage on N1SDP sahil ` (3 preceding siblings ...) 2023-11-16 11:45 ` [edk2-devel] [edk2-platforms][PATCH V1 4/5] Platform/ARM/N1Sdp: Persistent storage " sahil @ 2023-11-16 11:45 ` sahil 2023-12-07 14:51 ` Thomas Abraham 2023-12-18 15:16 ` Sami Mujawar 4 siblings, 2 replies; 17+ messages in thread From: sahil @ 2023-11-16 11:45 UTC (permalink / raw) To: devel; +Cc: Ard Biesheuvel, Leif Lindholm, Sami Mujawar, Sahil Signed-off-by: sahil <sahil@arm.com> --- Platform/ARM/N1Sdp/N1SdpPlatform.dsc | 5 +++++ Platform/ARM/N1Sdp/N1SdpPlatform.fdf | 1 + 2 files changed, 6 insertions(+) diff --git a/Platform/ARM/N1Sdp/N1SdpPlatform.dsc b/Platform/ARM/N1Sdp/N1SdpPlatform.dsc index 10fe2db9e1b1..703829bbac99 100644 --- a/Platform/ARM/N1Sdp/N1SdpPlatform.dsc +++ b/Platform/ARM/N1Sdp/N1SdpPlatform.dsc @@ -165,6 +165,10 @@ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiExposedTableVersions|0x20 # NOR flash support + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase|0x18F40000 + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize|0x00020000 + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase|0x18F20000 + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize|0x00020000 gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase|0x18F00000 gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize|0x00020000 @@ -227,6 +231,7 @@ NULL|EmbeddedPkg/Library/NvVarStoreFormattedLib/NvVarStoreFormattedLib.inf BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf } + MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf # ACPI Support MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf diff --git a/Platform/ARM/N1Sdp/N1SdpPlatform.fdf b/Platform/ARM/N1Sdp/N1SdpPlatform.fdf index 4329f892f7c5..17d370a371cf 100644 --- a/Platform/ARM/N1Sdp/N1SdpPlatform.fdf +++ b/Platform/ARM/N1Sdp/N1SdpPlatform.fdf @@ -90,6 +90,7 @@ READ_LOCK_STATUS = TRUE INF MdeModulePkg/Universal/Metronome/Metronome.inf INF MdeModulePkg/Universal/ResetSystemRuntimeDxe/ResetSystemRuntimeDxe.inf INF MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf + INF MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf INF MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf INF MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf INF MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf -- 2.25.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#111313): https://edk2.groups.io/g/devel/message/111313 Mute This Topic: https://groups.io/mt/102625038/7686176 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io] -=-=-=-=-=-=-=-=-=-=-=- ^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [edk2-devel] [edk2-platforms][PATCH V1 5/5] Platform/ARM/N1Sdp: Enable FaultTolerantWrite Dxe driver for N1Sdp 2023-11-16 11:45 ` [edk2-devel] [edk2-platforms][PATCH V1 5/5] Platform/ARM/N1Sdp: Enable FaultTolerantWrite Dxe driver " sahil @ 2023-12-07 14:51 ` Thomas Abraham 2023-12-18 15:16 ` Sami Mujawar 1 sibling, 0 replies; 17+ messages in thread From: Thomas Abraham @ 2023-12-07 14:51 UTC (permalink / raw) To: devel@edk2.groups.io, Sahil Kaushal Cc: Ard Biesheuvel, Leif Lindholm, Sami Mujawar, Chandni Cherukuri, nd > -----Original Message----- > From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of sahil via > groups.io > Sent: Thursday, November 16, 2023 11:46 AM > To: devel@edk2.groups.io > Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>; Leif Lindholm > <quic_llindhol@quicinc.com>; Sami Mujawar <Sami.Mujawar@arm.com>; > Sahil Kaushal <Sahil.Kaushal@arm.com> > Subject: [edk2-devel] [edk2-platforms][PATCH V1 5/5] Platform/ARM/N1Sdp: > Enable FaultTolerantWrite Dxe driver for N1Sdp Add a commit message. > > Signed-off-by: sahil <sahil@arm.com> > --- > Platform/ARM/N1Sdp/N1SdpPlatform.dsc | 5 +++++ > Platform/ARM/N1Sdp/N1SdpPlatform.fdf | 1 + > 2 files changed, 6 insertions(+) > > diff --git a/Platform/ARM/N1Sdp/N1SdpPlatform.dsc > b/Platform/ARM/N1Sdp/N1SdpPlatform.dsc > index 10fe2db9e1b1..703829bbac99 100644 > --- a/Platform/ARM/N1Sdp/N1SdpPlatform.dsc > +++ b/Platform/ARM/N1Sdp/N1SdpPlatform.dsc > @@ -165,6 +165,10 @@ > gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiExposedTableVersions|0x20 > > > > # NOR flash support > > + > gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase|0x18F400 > 00 > > + > gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize|0x0002000 > 0 > > + > gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase|0x18F2 > 0000 > > + > gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize|0x0002 > 0000 > > > gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase|0x18F0000 > 0 > > > gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize|0x0002000 > 0 > > > > @@ -227,6 +231,7 @@ > > NULL|EmbeddedPkg/Library/NvVarStoreFormattedLib/NvVarStoreFormattedLib. > inf > > BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf > > } > > + MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf > > > > # ACPI Support > > MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf > > diff --git a/Platform/ARM/N1Sdp/N1SdpPlatform.fdf > b/Platform/ARM/N1Sdp/N1SdpPlatform.fdf > index 4329f892f7c5..17d370a371cf 100644 > --- a/Platform/ARM/N1Sdp/N1SdpPlatform.fdf > +++ b/Platform/ARM/N1Sdp/N1SdpPlatform.fdf > @@ -90,6 +90,7 @@ READ_LOCK_STATUS = TRUE > INF MdeModulePkg/Universal/Metronome/Metronome.inf > > INF > MdeModulePkg/Universal/ResetSystemRuntimeDxe/ResetSystemRuntimeDxe.in > f > > INF MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf > > + INF > MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf > > INF > MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterR > untimeDxe.inf > > INF MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf > > INF MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf > > -- > 2.25.1 With the commit message included, Reviewed-by: Thomas Abraham <thomas.abraham@arm.com> -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#112196): https://edk2.groups.io/g/devel/message/112196 Mute This Topic: https://groups.io/mt/102625038/7686176 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io] -=-=-=-=-=-=-=-=-=-=-=- ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [edk2-devel] [edk2-platforms][PATCH V1 5/5] Platform/ARM/N1Sdp: Enable FaultTolerantWrite Dxe driver for N1Sdp 2023-11-16 11:45 ` [edk2-devel] [edk2-platforms][PATCH V1 5/5] Platform/ARM/N1Sdp: Enable FaultTolerantWrite Dxe driver " sahil 2023-12-07 14:51 ` Thomas Abraham @ 2023-12-18 15:16 ` Sami Mujawar 1 sibling, 0 replies; 17+ messages in thread From: Sami Mujawar @ 2023-12-18 15:16 UTC (permalink / raw) To: sahil, devel; +Cc: Ard Biesheuvel, Leif Lindholm, nd@arm.com Hi Sahil, As such these changes look good to me. But, we would need to revisit this based on my response for Patch 3/5. Regards, Sami Mujawar On 16/11/2023 11:45 am, sahil wrote: > Signed-off-by: sahil <sahil@arm.com> > --- > Platform/ARM/N1Sdp/N1SdpPlatform.dsc | 5 +++++ > Platform/ARM/N1Sdp/N1SdpPlatform.fdf | 1 + > 2 files changed, 6 insertions(+) > > diff --git a/Platform/ARM/N1Sdp/N1SdpPlatform.dsc b/Platform/ARM/N1Sdp/N1SdpPlatform.dsc > index 10fe2db9e1b1..703829bbac99 100644 > --- a/Platform/ARM/N1Sdp/N1SdpPlatform.dsc > +++ b/Platform/ARM/N1Sdp/N1SdpPlatform.dsc > @@ -165,6 +165,10 @@ > gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiExposedTableVersions|0x20 > > > > # NOR flash support > > + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase|0x18F40000 > > + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize|0x00020000 > > + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase|0x18F20000 > > + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize|0x00020000 > > gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase|0x18F00000 > > gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize|0x00020000 > > > > @@ -227,6 +231,7 @@ > NULL|EmbeddedPkg/Library/NvVarStoreFormattedLib/NvVarStoreFormattedLib.inf > > BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf > > } > > + MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf > > > > # ACPI Support > > MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf > > diff --git a/Platform/ARM/N1Sdp/N1SdpPlatform.fdf b/Platform/ARM/N1Sdp/N1SdpPlatform.fdf > index 4329f892f7c5..17d370a371cf 100644 > --- a/Platform/ARM/N1Sdp/N1SdpPlatform.fdf > +++ b/Platform/ARM/N1Sdp/N1SdpPlatform.fdf > @@ -90,6 +90,7 @@ READ_LOCK_STATUS = TRUE > INF MdeModulePkg/Universal/Metronome/Metronome.inf > > INF MdeModulePkg/Universal/ResetSystemRuntimeDxe/ResetSystemRuntimeDxe.inf > > INF MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf > > + INF MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf > > INF MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf > > INF MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf > > INF MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf > -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#112646): https://edk2.groups.io/g/devel/message/112646 Mute This Topic: https://groups.io/mt/102625038/7686176 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io] -=-=-=-=-=-=-=-=-=-=-=- ^ permalink raw reply [flat|nested] 17+ messages in thread
end of thread, other threads:[~2023-12-18 15:16 UTC | newest] Thread overview: 17+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2023-11-16 11:45 [edk2-devel] [edk2-platforms][PATCH V1 0/5] Enable non volatile storage on N1SDP sahil 2023-11-16 11:45 ` [edk2-devel] [edk2-platforms][PATCH V1 1/5] Silicon/ARM/NeoverseN1Soc: Enable SCP QSPI flash region sahil 2023-12-07 10:59 ` Thomas Abraham 2023-12-18 15:12 ` Sami Mujawar 2023-11-16 11:45 ` [edk2-devel] [edk2-platforms][PATCH V1 2/5] Silicon/ARM/NeoverseN1Soc: NOR flash library for N1Sdp sahil 2023-12-07 12:01 ` Thomas Abraham 2023-12-18 15:12 ` Sami Mujawar 2023-11-16 11:45 ` [edk2-devel] [edk2-platforms][PATCH V1 3/5] Platform/ARM/N1Sdp: NOR flash Dxe Driver " sahil 2023-12-07 14:46 ` Thomas Abraham 2023-12-12 12:08 ` levi.yun 2023-12-18 15:12 ` Sami Mujawar 2023-11-16 11:45 ` [edk2-devel] [edk2-platforms][PATCH V1 4/5] Platform/ARM/N1Sdp: Persistent storage " sahil 2023-12-07 14:48 ` Thomas Abraham 2023-12-18 15:13 ` Sami Mujawar 2023-11-16 11:45 ` [edk2-devel] [edk2-platforms][PATCH V1 5/5] Platform/ARM/N1Sdp: Enable FaultTolerantWrite Dxe driver " sahil 2023-12-07 14:51 ` Thomas Abraham 2023-12-18 15:16 ` Sami Mujawar
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox