Adding support for NOR flash Driver
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Vabhav <vabhav.sharma@nxp.com>
---
.../NXP/Drivers/NorFlashDxe/NorFlashBlockIoDxe.c | 254 +++++++
Platform/NXP/Drivers/NorFlashDxe/NorFlashDxe.c | 444 +++++++++++
Platform/NXP/Drivers/NorFlashDxe/NorFlashDxe.inf | 65 ++
Platform/NXP/Drivers/NorFlashDxe/NorFlashFvbDxe.c | 814 +++++++++++++++++++++
Platform/NXP/Include/Library/NorFlash.h | 222 ++++++
Silicon/NXP/Chassis/Chassis.c | 15 +
Silicon/NXP/Chassis/Chassis.h | 7 +
Silicon/NXP/Chassis/Chassis2/Soc.c | 1 +
Silicon/NXP/Chassis/LS1043aSocLib.inf | 2 +
9 files changed, 1824 insertions(+)
create mode 100644 Platform/NXP/Drivers/NorFlashDxe/NorFlashBlockIoDxe.c
create mode 100644 Platform/NXP/Drivers/NorFlashDxe/NorFlashDxe.c
create mode 100755 Platform/NXP/Drivers/NorFlashDxe/NorFlashDxe.inf
create mode 100644 Platform/NXP/Drivers/NorFlashDxe/NorFlashFvbDxe.c
create mode 100644 Platform/NXP/Include/Library/NorFlash.h
diff --git a/Platform/NXP/Drivers/NorFlashDxe/NorFlashBlockIoDxe.c b/Platform/NXP/Drivers/NorFlashDxe/NorFlashBlockIoDxe.c
new file mode 100644
index 0000000..bad397f
--- /dev/null
+++ b/Platform/NXP/Drivers/NorFlashDxe/NorFlashBlockIoDxe.c
@@ -0,0 +1,254 @@
+/** @NorFlashBlockIoDxe.c
+
+ Based on NorFlash implementation available in ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashBlockIoDxe.c
+
+ Copyright (c) 2011 - 2014, ARM Ltd. All rights reserved.
+ Copyright 2017 NXP
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Library/DebugLib.h>
+#include <Library/NorFlash.h>
+
+//
+// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.Reset
+//
+EFI_STATUS
+EFIAPI
+NorFlashBlockIoReset (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ )
+{
+ NOR_FLASH_INSTANCE *Instance;
+
+ Instance = INSTANCE_FROM_BLKIO_THIS (This);
+
+ DEBUG ((DEBUG_INFO, "NorFlashBlockIoReset (MediaId=0x%x)\n",
+ This->Media->MediaId));
+
+ return NorFlashPlatformReset (Instance->DeviceBaseAddress);
+}
+
+//
+// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.ReadBlocks
+//
+EFI_STATUS
+EFIAPI
+NorFlashBlockIoReadBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSizeInBytes,
+ OUT VOID *Buffer
+ )
+{
+ NOR_FLASH_INSTANCE *Instance;
+ EFI_STATUS Status;
+ EFI_BLOCK_IO_MEDIA *Media;
+ UINTN NumBlocks;
+ UINT8 *pReadBuffer;
+ UINTN BlockCount;
+ UINTN BlockSizeInBytes;
+ EFI_LBA CurrentBlock;
+
+ Status = EFI_SUCCESS;
+
+ if ((This == NULL) || (Buffer == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Instance = INSTANCE_FROM_BLKIO_THIS (This);
+ Media = This->Media;
+
+ if (Media == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a : Media is NULL\n", __FUNCTION__));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ NumBlocks = ((UINTN)BufferSizeInBytes) / Instance->Media.BlockSize ;
+
+ DEBUG ((DEBUG_BLKIO, "%a : (MediaId=0x%x, Lba=%ld, "
+ "BufferSize=0x%x bytes (%d kB)"
+ ", BufferPtr @ 0x%p)\n",
+ __FUNCTION__,MediaId, Lba,
+ BufferSizeInBytes, Buffer));
+
+ if (!Media) {
+ Status = EFI_INVALID_PARAMETER;
+ }
+ else if (!Media->MediaPresent) {
+ Status = EFI_NO_MEDIA;
+ }
+ else if (Media->MediaId != MediaId) {
+ Status = EFI_MEDIA_CHANGED;
+ }
+ else if ((Media->IoAlign >= 2) &&
+ (((UINTN)Buffer & (Media->IoAlign - 1)) != 0)) {
+ Status = EFI_INVALID_PARAMETER;
+ }
+ else if (BufferSizeInBytes == 0) {
+ // Return if we have not any byte to read
+ Status = EFI_SUCCESS;
+ }
+ else if ((BufferSizeInBytes % Media->BlockSize) != 0) {
+ // The size of the buffer must be a multiple of the block size
+ DEBUG ((DEBUG_ERROR, "%a : BlockSize in bytes = 0x%x\n",__FUNCTION__,
+ BufferSizeInBytes));
+ Status = EFI_INVALID_PARAMETER;
+ } else if ((Lba + NumBlocks - 1) > Media->LastBlock) {
+ // All blocks must be within the device
+ DEBUG ((DEBUG_ERROR, "%a : Read will exceed last block %d, %d, %d \n",
+ __FUNCTION__, Lba, NumBlocks, Media->LastBlock));
+ Status = EFI_INVALID_PARAMETER;
+ } else {
+ BlockSizeInBytes = Instance->Media.BlockSize;
+
+ /* Because the target *Buffer is a pointer to VOID,
+ * we must put all the data into a pointer
+ * to a proper data type, so use *pReadBuffer */
+ pReadBuffer = (UINT8 *)Buffer;
+
+ CurrentBlock = Lba;
+ // Read data block by Block
+ for (BlockCount = 0; BlockCount < NumBlocks; BlockCount++, CurrentBlock++,
+ pReadBuffer = pReadBuffer + BlockSizeInBytes) {
+ DEBUG ((DEBUG_BLKIO, "%a: Reading block #%d\n",
+ __FUNCTION__,(UINTN)CurrentBlock));
+
+ Status = NorFlashPlatformRead (Instance, CurrentBlock, (UINTN)0 ,
+ BlockSizeInBytes,pReadBuffer);
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+ }
+ }
+ DEBUG ((DEBUG_BLKIO,"%a: Exit Status = \"%r\".\n",__FUNCTION__,Status));
+
+ return Status;
+}
+
+//
+// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.WriteBlocks
+//
+EFI_STATUS
+EFIAPI
+NorFlashBlockIoWriteBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSizeInBytes,
+ IN VOID *Buffer
+ )
+{
+ NOR_FLASH_INSTANCE *Instance;
+ EFI_STATUS Status;
+ EFI_BLOCK_IO_MEDIA *Media;
+ UINTN NumBlocks;
+ EFI_LBA CurrentBlock;
+ UINTN BlockSizeInBytes;
+ UINT32 BlockCount;
+ UINTN SectorAddress;
+ UINT8 *pWriteBuffer;
+
+ Status = EFI_SUCCESS;
+
+ if ((This == NULL) || (Buffer == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Instance = INSTANCE_FROM_BLKIO_THIS (This);
+ Media = This->Media;
+
+ if (Media == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a : Media is NULL\n", __FUNCTION__));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ NumBlocks = ((UINTN)BufferSizeInBytes) / Instance->Media.BlockSize ;
+
+ DEBUG ((DEBUG_BLKIO, "%a : (MediaId=0x%x, Lba=%ld, BufferSize=0x%x "
+ "bytes (%d kB) BufferPtr @ 0x%08x)\n",
+ __FUNCTION__,MediaId, Lba,BufferSizeInBytes, Buffer));
+
+ if (!Media->MediaPresent) {
+ Status = EFI_NO_MEDIA;
+ }
+ else if (Media->MediaId != MediaId) {
+ Status = EFI_MEDIA_CHANGED;
+ }
+ else if (Media->ReadOnly) {
+ Status = EFI_WRITE_PROTECTED;
+ }
+ else if (BufferSizeInBytes == 0) {
+ Status = EFI_BAD_BUFFER_SIZE;
+ }
+ else if ((BufferSizeInBytes % Media->BlockSize) != 0) {
+ // The size of the buffer must be a multiple of the block size
+ DEBUG ((DEBUG_ERROR, "%a : BlockSize in bytes = 0x%x\n",__FUNCTION__,
+ BufferSizeInBytes));
+ Status = EFI_INVALID_PARAMETER;
+ } else if ((Lba + NumBlocks - 1) > Media->LastBlock) {
+ // All blocks must be within the device
+ DEBUG ((DEBUG_ERROR, "%a: Write will exceed last block %d, %d, %d \n",
+ __FUNCTION__,Lba, NumBlocks, Media->LastBlock));
+ Status = EFI_INVALID_PARAMETER;
+ } else {
+ BlockSizeInBytes = Instance->Media.BlockSize;
+
+ pWriteBuffer = (UINT8 *)Buffer;
+
+ CurrentBlock = Lba;
+ // Program data block by Block
+ for (BlockCount = 0; BlockCount < NumBlocks;
+ BlockCount++, CurrentBlock++,
+ pWriteBuffer = (pWriteBuffer + BlockSizeInBytes)) {
+ DEBUG ((DEBUG_BLKIO, "%a: Writing block #%d\n",
+ __FUNCTION__,(UINTN)CurrentBlock));
+ // Erase the Block(Sector) to be written to
+ SectorAddress = GET_NOR_BLOCK_ADDRESS (
+ Instance->RegionBaseAddress,
+ CurrentBlock,
+ Instance->Media.BlockSize
+ );
+ Status = NorFlashPlatformEraseSector (Instance, (UINTN)SectorAddress);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: Failed to erase Target 0x%x (0x%x) \n",
+ __FUNCTION__,SectorAddress, Status));
+ break;
+ }
+ // Program Block(Sector) to be written to
+ Status = NorFlashWrite (Instance, CurrentBlock, (UINTN)0,
+ &BlockSizeInBytes, pWriteBuffer);
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+ }
+ }
+ DEBUG ((DEBUG_BLKIO, "%a: Exit Status = \"%r\".\n",__FUNCTION__,Status));
+ return Status;
+}
+
+//
+// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.FlushBlocks
+//
+EFI_STATUS
+EFIAPI
+NorFlashBlockIoFlushBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This
+ )
+{
+
+ DEBUG ((DEBUG_BLKIO, "%a NOT IMPLEMENTED (not required)\n", __FUNCTION__));
+
+ // Nothing to do so just return without error
+ return EFI_SUCCESS;
+}
diff --git a/Platform/NXP/Drivers/NorFlashDxe/NorFlashDxe.c b/Platform/NXP/Drivers/NorFlashDxe/NorFlashDxe.c
new file mode 100644
index 0000000..ca17001
--- /dev/null
+++ b/Platform/NXP/Drivers/NorFlashDxe/NorFlashDxe.c
@@ -0,0 +1,444 @@
+/** @file NorFlashDxe.c
+
+ Based on NorFlash implementation available in ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.c
+
+ Copyright (c) 2011 - 2014, ARM Ltd. All rights reserved.
+ Copyright 2017 NXP
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Bitops.h>
+#include <Library/NorFlash.h>
+#include <Library/NorFlashLib.h>
+#include <Library/UefiRuntimeLib.h>
+
+STATIC EFI_EVENT mNorFlashVirtualAddrChangeEvent;
+
+//
+// Global variable declarations
+//
+NOR_FLASH_INSTANCE **mNorFlashInstances;
+UINT32 mNorFlashDeviceCount;
+
+NOR_FLASH_INSTANCE mNorFlashInstanceTemplate = {
+ .Signature = NOR_FLASH_SIGNATURE,
+ .Initialized = FALSE,
+ .Initialize = NULL,
+ .StartLba = 0,
+ .BlockIoProtocol = {
+ .Revision = EFI_BLOCK_IO_PROTOCOL_REVISION2,
+ .Reset = NorFlashBlockIoReset,
+ .ReadBlocks = NorFlashBlockIoReadBlocks,
+ .WriteBlocks = NorFlashBlockIoWriteBlocks,
+ .FlushBlocks = NorFlashBlockIoFlushBlocks,
+ },
+
+ .Media = {
+ .RemovableMedia = FALSE,
+ .MediaPresent = TRUE,
+ .LogicalPartition = FALSE,
+ .ReadOnly = FALSE,
+ .WriteCaching = FALSE,
+ .IoAlign = 4,
+ .LowestAlignedLba = 0,
+ .LogicalBlocksPerPhysicalBlock = 1,
+ },
+
+ .FvbProtocol = {
+ .GetAttributes = FvbGetAttributes,
+ .SetAttributes = FvbSetAttributes,
+ .GetPhysicalAddress = FvbGetPhysicalAddress,
+ .GetBlockSize = FvbGetBlockSize,
+ .Read = FvbRead,
+ .Write = FvbWrite,
+ .EraseBlocks = FvbEraseBlocks,
+ .ParentHandle = NULL,
+ },
+ .ShadowBuffer = NULL,
+ .DevicePath = {
+ .Vendor = {
+ .Header = {
+ .Type = HARDWARE_DEVICE_PATH,
+ .SubType = HW_VENDOR_DP,
+ .Length = {(UINT8)sizeof (VENDOR_DEVICE_PATH),
+ (UINT8)((sizeof (VENDOR_DEVICE_PATH)) >> 8) }
+ },
+ .Guid = EFI_CALLER_ID_GUID, // GUID ... NEED TO BE FILLED
+ },
+ .End = {
+ .Type = END_DEVICE_PATH_TYPE,
+ .SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ .Length = { sizeof (EFI_DEVICE_PATH_PROTOCOL), 0 }
+ }
+ }
+};
+
+EFI_STATUS
+NorFlashCreateInstance (
+ IN UINTN NorFlashDeviceBase,
+ IN UINTN NorFlashRegionBase,
+ IN UINTN NorFlashSize,
+ IN UINT32 MediaId,
+ IN UINT32 BlockSize,
+ IN BOOLEAN SupportFvb,
+ OUT NOR_FLASH_INSTANCE** NorFlashInstance
+ )
+{
+ EFI_STATUS Status;
+ NOR_FLASH_INSTANCE* Instance;
+
+ ASSERT(NorFlashInstance != NULL);
+
+ Instance = AllocateRuntimeCopyPool (sizeof (NOR_FLASH_INSTANCE),
+ &mNorFlashInstanceTemplate);
+ if (Instance == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Instance->DeviceBaseAddress = NorFlashDeviceBase;
+ Instance->RegionBaseAddress = NorFlashRegionBase;
+ Instance->Size = NorFlashSize;
+
+ Instance->BlockIoProtocol.Media = &Instance->Media;
+ Instance->Media.MediaId = MediaId;
+ Instance->Media.BlockSize = BlockSize;
+ Instance->Media.LastBlock = (NorFlashSize / BlockSize)-1;
+
+ Instance->ShadowBuffer = AllocateRuntimePool (BlockSize);
+ if (Instance->ShadowBuffer == NULL) {
+ FreePool (Instance);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if (SupportFvb) {
+ Instance->SupportFvb = TRUE;
+ Instance->Initialize = NorFlashFvbInitialize;
+
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Instance->Handle,
+ &gEfiDevicePathProtocolGuid, &Instance->DevicePath,
+ &gEfiBlockIoProtocolGuid, &Instance->BlockIoProtocol,
+ &gEfiFirmwareVolumeBlockProtocolGuid, &Instance->FvbProtocol,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (Instance->ShadowBuffer);
+ FreePool (Instance);
+ return Status;
+ }
+ } else {
+ Instance->Initialized = TRUE;
+
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Instance->Handle,
+ &gEfiDevicePathProtocolGuid, &Instance->DevicePath,
+ &gEfiBlockIoProtocolGuid, &Instance->BlockIoProtocol,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (Instance->ShadowBuffer);
+ FreePool (Instance);
+ return Status;
+ }
+ }
+
+ *NorFlashInstance = Instance;
+
+ return Status;
+}
+
+/*
+ Write a full or portion of a block.
+ It must not span block boundaries; that is,
+ Offset + NumBytes <= Instance->Media.BlockSize.
+ */
+EFI_STATUS
+NorFlashWrite (
+ IN NOR_FLASH_INSTANCE *Instance,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN OUT UINTN *NumBytes,
+ IN UINT8 *Buffer
+)
+{
+ EFI_STATUS Status;
+ UINTN BlockSize;
+ BOOLEAN DoErase;
+ VOID *Source;
+ UINTN SectorAddress;
+
+ Status = EFI_SUCCESS;
+ Source = NULL;
+
+ DEBUG ((DEBUG_BLKIO, "%a(Parameters: Lba=%ld, Offset=0x%x, NumBytes=0x%x, "
+ "Buffer @ 0x%08x)\n", __FUNCTION__,
+ Lba, Offset, *NumBytes, Buffer));
+
+ // The buffer must be valid
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Detect WriteDisabled state
+ if (Instance->Media.ReadOnly == TRUE) {
+ DEBUG ((DEBUG_ERROR, "NorFlashWrite: ERROR - Can not write: "
+ "Device is in WriteDisabled state.\n"));
+ // It is in WriteDisabled state, return an error right away
+ return EFI_ACCESS_DENIED;
+ }
+
+ // Cache the block size to avoid de-referencing pointers all the time
+ BlockSize = Instance->Media.BlockSize;
+
+ // We must have some bytes to write
+ if ((*NumBytes == 0) || (*NumBytes > BlockSize)) {
+ DEBUG ((DEBUG_ERROR, "NorFlashWrite: ERROR - EFI_BAD_BUFFER_SIZE: "
+ "(Offset=0x%x + NumBytes=0x%x) > BlockSize=0x%x\n", \
+ Offset, *NumBytes, BlockSize ));
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ if (((Lba * BlockSize) + Offset + *NumBytes) > Instance->Size) {
+ DEBUG ((DEBUG_ERROR, "%a: ERROR - Write will exceed device size.\n",
+ __FUNCTION__));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Check we did get some memory. Buffer is BlockSize.
+ if (Instance->ShadowBuffer == NULL) {
+ DEBUG ((DEBUG_ERROR, "FvbWrite: ERROR - Buffer not ready\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ SectorAddress = GET_NOR_BLOCK_ADDRESS (
+ Instance->RegionBaseAddress,
+ Lba,
+ Instance->Media.BlockSize
+ );
+
+ // Pick 128bytes as a good start for word operations as opposed to erasing the
+ // block and writing the data regardless if an erase is really needed.
+ // It looks like most individual NV variable writes are smaller than 128bytes.
+ if (*NumBytes <= 128) {
+ Source = Instance->ShadowBuffer;
+ //First Read the data into shadow buffer from location where data is to be written
+ Status = NorFlashPlatformRead (
+ Instance,
+ Lba,
+ Offset,
+ *NumBytes,
+ Source
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: ERROR - Failed to "
+ "Read @ %p Status=%d\n", __FUNCTION__,
+ Offset + SectorAddress, Status));
+ return Status;
+ }
+ // Check to see if we need to erase before programming the data into NorFlash.
+ // If the destination bits are only changing from 1s to 0s we can
+ // just write. After a block is erased all bits in the block is set to 1.
+ // If any byte requires us to erase we just give up and rewrite all of it.
+ DoErase = TestBitSetClear (Source, Buffer, *NumBytes, TRUE);
+
+ // if we got here then write all the data. Otherwise do the
+ // Erase-Write cycle.
+ if (!DoErase) {
+ Status = NorFlashPlatformWriteBuffer (
+ Instance,
+ Lba,
+ Offset,
+ NumBytes,
+ Buffer
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: ERROR - Failed to "
+ "Write @ %p Status=%d\n", __FUNCTION__,
+ Offset + SectorAddress, Status));
+ return Status;
+ }
+ return EFI_SUCCESS;
+ }
+ }
+
+ // If we are not going to write full block, read block and then update bytes in it
+ if (*NumBytes != BlockSize) {
+ // Read NorFlash Flash data into shadow buffer
+ Status = NorFlashBlockIoReadBlocks (
+ &(Instance->BlockIoProtocol),
+ Instance->Media.MediaId,
+ Lba,
+ BlockSize,
+ Instance->ShadowBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ // Return one of the pre-approved error statuses
+ return EFI_DEVICE_ERROR;
+ }
+ // Put the data at the appropriate location inside the buffer area
+ CopyMem ((VOID *)((UINTN)Instance->ShadowBuffer + Offset), Buffer, *NumBytes);
+ }
+ //Erase Block
+ Status = NorFlashPlatformEraseSector (Instance, SectorAddress);
+ if (EFI_ERROR (Status)) {
+ // Return one of the pre-approved error statuses
+ return EFI_DEVICE_ERROR;
+ }
+ if (*NumBytes != BlockSize) {
+ // Write the modified shadow buffer back to the NorFlash
+ Status = NorFlashPlatformWriteBuffer (
+ Instance,
+ Lba,
+ 0,
+ &BlockSize,
+ Instance->ShadowBuffer
+ );
+ } else {
+ // Write the Buffer to an entire block in NorFlash
+ Status = NorFlashPlatformWriteBuffer (
+ Instance,
+ Lba,
+ 0,
+ &BlockSize,
+ Buffer
+ );
+ }
+ if (EFI_ERROR (Status)) {
+ // Return one of the pre-approved error statuses
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Fixup internal data so that EFI can be call in virtual mode.
+ Call the passed in Child Notify event and convert any pointers in
+ lib to virtual mode.
+
+ @param[in] Event The Event that is being processed
+ @param[in] Context Event Context
+**/
+VOID
+EFIAPI
+NorFlashVirtualNotifyEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ UINTN Index;
+
+ for (Index = 0; Index < mNorFlashDeviceCount; Index++) {
+ EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->DeviceBaseAddress);
+ EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->RegionBaseAddress);
+
+ // Convert BlockIo protocol
+ EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->BlockIoProtocol.FlushBlocks);
+ EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->BlockIoProtocol.ReadBlocks);
+ EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->BlockIoProtocol.Reset);
+ EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->BlockIoProtocol.WriteBlocks);
+
+ // Convert Fvb
+ EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->FvbProtocol.EraseBlocks);
+ EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->FvbProtocol.GetAttributes);
+ EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->FvbProtocol.GetBlockSize);
+ EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->FvbProtocol.GetPhysicalAddress);
+ EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->FvbProtocol.Read);
+ EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->FvbProtocol.SetAttributes);
+ EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->FvbProtocol.Write);
+ if (mNorFlashInstances[Index]->ShadowBuffer != NULL) {
+ EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->ShadowBuffer);
+ }
+ }
+
+ return;
+}
+
+EFI_STATUS
+EFIAPI
+NorFlashInitialise (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Index;
+ NorFlashDescription* NorFlashDevices;
+ BOOLEAN ContainVariableStorage;
+
+ ContainVariableStorage = 0;
+
+ Status = NorFlashPlatformGetDevices (&NorFlashDevices, &mNorFlashDeviceCount);
+ if (EFI_ERROR(Status)) {
+ DEBUG((DEBUG_ERROR,"%a : Failed to get Nor devices (0x%x)\n",
+ __FUNCTION__, Status));
+ return Status;
+ }
+
+ Status = NorFlashPlatformFlashGetAttributes (NorFlashDevices,
+ mNorFlashDeviceCount);
+ if (EFI_ERROR(Status)) {
+ DEBUG ((DEBUG_ERROR,"%a : Failed to get NOR device attributes (0x%x)\n",
+ __FUNCTION__, Status));
+ ASSERT_EFI_ERROR (Status); /* System becomes unusable if NOR flash is not detected */
+ return Status;
+ }
+
+ mNorFlashInstances = AllocateRuntimePool (
+ sizeof(NOR_FLASH_INSTANCE*) * mNorFlashDeviceCount);
+ if (mNorFlashInstances == NULL) {
+ DEBUG ((DEBUG_ERROR,"%a : Failed to allocate runtime memory \n"));
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ for (Index = 0; Index < mNorFlashDeviceCount; Index++) {
+ // Check if this NOR Flash device contain the variable storage region
+ ContainVariableStorage =
+ (NorFlashDevices[Index].RegionBaseAddress <= PcdGet64 (PcdFlashNvStorageVariableBase64)) &&
+ (PcdGet64 (PcdFlashNvStorageVariableBase64) + PcdGet32 (PcdFlashNvStorageVariableSize) <=
+ NorFlashDevices[Index].RegionBaseAddress + NorFlashDevices[Index].Size);
+
+ Status = NorFlashCreateInstance (
+ NorFlashDevices[Index].DeviceBaseAddress,
+ NorFlashDevices[Index].RegionBaseAddress,
+ NorFlashDevices[Index].Size,
+ Index,
+ NorFlashDevices[Index].BlockSize,
+ ContainVariableStorage,
+ &mNorFlashInstances[Index]
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR,"%a : Failed to create instance for "
+ "NorFlash[%d] (0x%x)\n",Index, Status));
+ }
+
+ }
+
+ //
+ // Register for the virtual address change event
+ //
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ NorFlashVirtualNotifyEvent,
+ NULL,
+ &gEfiEventVirtualAddressChangeGuid,
+ &mNorFlashVirtualAddrChangeEvent
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR,"Failed to create VirtualAddressChange event 0x%x\n",
+ Status));
+ }
+
+ return Status;
+}
diff --git a/Platform/NXP/Drivers/NorFlashDxe/NorFlashDxe.inf b/Platform/NXP/Drivers/NorFlashDxe/NorFlashDxe.inf
new file mode 100755
index 0000000..2da8a51
--- /dev/null
+++ b/Platform/NXP/Drivers/NorFlashDxe/NorFlashDxe.inf
@@ -0,0 +1,65 @@
+#/** @file
+#
+# Component description file for NorFlashDxe module
+#
+# Copyright 2017 NXP
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x0001001A
+ BASE_NAME = NorFlashDxe
+ FILE_GUID = 616fe8d8-f4aa-42e0-a393-b332bdb2d3c1
+ MODULE_TYPE = DXE_RUNTIME_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = NorFlashInitialise
+
+[Sources.common]
+ NorFlashDxe.c
+ NorFlashFvbDxe.c
+ NorFlashBlockIoDxe.c
+
+[Packages]
+ ArmPlatformPkg/ArmPlatformPkg.dec
+ Platform/NXP/NxpQoriqLs.dec
+ MdeModulePkg/MdeModulePkg.dec
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ DxeServicesTableLib
+ HobLib
+ NorFlashLib
+ UefiDriverEntryPoint
+ UefiRuntimeLib
+
+[Guids]
+ gEfiSystemNvDataFvGuid
+ gEfiVariableGuid
+ gEfiAuthenticatedVariableGuid
+ gEfiEventVirtualAddressChangeGuid
+
+[Protocols]
+ gEfiBlockIoProtocolGuid
+ gEfiFirmwareVolumeBlockProtocolGuid
+
+[Pcd.common]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase64
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase64
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize
+
+[Depex]
+ #
+ # NorFlashDxe must be loaded before VariableRuntimeDxe in case empty flash needs populating with default values
+ #
+ BEFORE gVariableRuntimeDxeFileGuid
diff --git a/Platform/NXP/Drivers/NorFlashDxe/NorFlashFvbDxe.c b/Platform/NXP/Drivers/NorFlashDxe/NorFlashFvbDxe.c
new file mode 100644
index 0000000..f74ffc9
--- /dev/null
+++ b/Platform/NXP/Drivers/NorFlashDxe/NorFlashFvbDxe.c
@@ -0,0 +1,814 @@
+/*@NorFlashFvbDxe.c
+
+ Based on NorFlash implementation available in ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashFvbDxe.c
+
+ Copyright (c) 2011 - 2014, ARM Ltd. All rights reserved.
+ Copyright 2017 NXP
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ --*/
+
+#include <Guid/VariableFormat.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/HobLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/NorFlash.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiRuntimeLib.h>
+
+STATIC EFI_EVENT mFvbVirtualAddrChangeEvent;
+STATIC UINTN mFlashNvStorageVariableBase;
+
+///
+/// The Firmware Volume Block Protocol is the low-level interface
+/// to a firmware volume. File-level access to a firmware volume
+/// should not be done using the Firmware Volume Block Protocol.
+/// Normal access to a firmware volume must use the Firmware
+/// Volume Protocol. Typically, only the file system driver that
+/// produces the Firmware Volume Protocol will bind to the
+/// Firmware Volume Block Protocol.
+///
+
+/**
+ Initialises the FV Header and Variable Store Header
+ to support variable operations.
+
+ @param[in] Ptr - Location to initialise the headers
+
+**/
+EFI_STATUS
+InitializeFvAndVariableStoreHeaders (
+ IN NOR_FLASH_INSTANCE *Instance
+ )
+{
+ EFI_STATUS Status;
+ VOID* Headers;
+ UINTN HeadersLength;
+ EFI_FIRMWARE_VOLUME_HEADER *FirmwareVolumeHeader;
+ VARIABLE_STORE_HEADER *VariableStoreHeader;
+
+ if (!Instance->Initialized && Instance->Initialize) {
+ Instance->Initialize (Instance);
+ }
+
+ HeadersLength = sizeof (EFI_FIRMWARE_VOLUME_HEADER) + sizeof (EFI_FV_BLOCK_MAP_ENTRY) + sizeof (VARIABLE_STORE_HEADER);
+ Headers = AllocateZeroPool (HeadersLength);
+ if (Headers == NULL) {
+ DEBUG ((DEBUG_ERROR, "Memory allocation failed for Headers \n"));
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ // FirmwareVolumeHeader->FvLength is declared to have the Variable area AND the FTW working area AND the FTW Spare contiguous.
+ ASSERT (PcdGet64 (PcdFlashNvStorageVariableBase64) + PcdGet32 (PcdFlashNvStorageVariableSize) == PcdGet64 (PcdFlashNvStorageFtwWorkingBase64));
+ ASSERT (PcdGet64 (PcdFlashNvStorageFtwWorkingBase64) + PcdGet32 (PcdFlashNvStorageFtwWorkingSize) == PcdGet64 (PcdFlashNvStorageFtwSpareBase64));
+
+ // Check if the size of the area is at least one block size
+ ASSERT ((PcdGet32 (PcdFlashNvStorageVariableSize) > 0) && (PcdGet32 (PcdFlashNvStorageVariableSize) / Instance->Media.BlockSize > 0));
+ ASSERT ((PcdGet32 (PcdFlashNvStorageFtwWorkingSize) > 0) && (PcdGet32 (PcdFlashNvStorageFtwWorkingSize) / Instance->Media.BlockSize > 0));
+ ASSERT ((PcdGet32 (PcdFlashNvStorageFtwSpareSize) > 0) && (PcdGet32 (PcdFlashNvStorageFtwSpareSize) / Instance->Media.BlockSize > 0));
+
+ // Ensure the Variable area Base Addresses are aligned on a block size boundaries
+ ASSERT (PcdGet64 (PcdFlashNvStorageVariableBase64) % Instance->Media.BlockSize == 0);
+ ASSERT (PcdGet64 (PcdFlashNvStorageFtwWorkingBase64) % Instance->Media.BlockSize == 0);
+ ASSERT (PcdGet64 (PcdFlashNvStorageFtwSpareBase64) % Instance->Media.BlockSize == 0);
+
+ //
+ // EFI_FIRMWARE_VOLUME_HEADER
+ //
+ FirmwareVolumeHeader = (EFI_FIRMWARE_VOLUME_HEADER*)Headers;
+ CopyGuid (&FirmwareVolumeHeader->FileSystemGuid, &gEfiSystemNvDataFvGuid);
+ FirmwareVolumeHeader->FvLength =
+ PcdGet32 (PcdFlashNvStorageVariableSize) +
+ PcdGet32 (PcdFlashNvStorageFtwWorkingSize) +
+ PcdGet32 (PcdFlashNvStorageFtwSpareSize);
+ FirmwareVolumeHeader->Signature = EFI_FVH_SIGNATURE;
+ FirmwareVolumeHeader->Attributes = (EFI_FVB_ATTRIBUTES_2) (
+ EFI_FVB2_READ_ENABLED_CAP | // Reads may be enabled
+ EFI_FVB2_READ_STATUS | // Reads are currently enabled
+ EFI_FVB2_STICKY_WRITE | // A block erase is required to flip bits into EFI_FVB2_ERASE_POLARITY
+ EFI_FVB2_MEMORY_MAPPED | // It is memory mapped
+ EFI_FVB2_ERASE_POLARITY | // After erasure all bits take this value (i.e. '1')
+ EFI_FVB2_WRITE_STATUS | // Writes are currently enabled
+ EFI_FVB2_WRITE_ENABLED_CAP // Writes may be enabled
+ );
+ FirmwareVolumeHeader->HeaderLength = sizeof (EFI_FIRMWARE_VOLUME_HEADER) + sizeof (EFI_FV_BLOCK_MAP_ENTRY);
+ FirmwareVolumeHeader->Revision = EFI_FVH_REVISION;
+ //i.e. if blocks are 0-5 then last block = 5, total blocks = 6
+ FirmwareVolumeHeader->BlockMap[0].NumBlocks = Instance->Media.LastBlock + 1;
+ FirmwareVolumeHeader->BlockMap[0].Length = Instance->Media.BlockSize;
+ FirmwareVolumeHeader->BlockMap[1].NumBlocks = 0;
+ FirmwareVolumeHeader->BlockMap[1].Length = 0;
+ FirmwareVolumeHeader->Checksum = CalculateCheckSum16 ((UINT16*)FirmwareVolumeHeader,FirmwareVolumeHeader->HeaderLength);
+
+ //
+ // VARIABLE_STORE_HEADER
+ //
+ VariableStoreHeader = (VARIABLE_STORE_HEADER*)((UINTN)Headers + FirmwareVolumeHeader->HeaderLength);
+ CopyGuid (&VariableStoreHeader->Signature, &gEfiAuthenticatedVariableGuid);
+ VariableStoreHeader->Size = PcdGet32(PcdFlashNvStorageVariableSize) - FirmwareVolumeHeader->HeaderLength;
+ VariableStoreHeader->Format = VARIABLE_STORE_FORMATTED;
+ VariableStoreHeader->State = VARIABLE_STORE_HEALTHY;
+
+ // Install the combined super-header in the NorFlash
+ Status = FvbWrite (&Instance->FvbProtocol, 0, 0, &HeadersLength, Headers);
+
+ FreePool (Headers);
+ return Status;
+}
+
+/**
+ Check the integrity of firmware volume header.
+
+ @param[in] FwVolHeader - A pointer to a firmware volume header
+
+ @retval EFI_SUCCESS - The firmware volume is consistent
+ @retval EFI_NOT_FOUND - The firmware volume has been corrupted.
+
+**/
+EFI_STATUS
+ValidateFvHeader (
+ IN NOR_FLASH_INSTANCE *Instance
+ )
+{
+ UINT16 Checksum;
+ EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
+ VARIABLE_STORE_HEADER *VariableStoreHeader;
+ UINTN VariableStoreLength;
+ UINTN FvLength;
+
+ FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER*)mFlashNvStorageVariableBase;
+
+ FvLength = PcdGet32 (PcdFlashNvStorageVariableSize) + PcdGet32 (PcdFlashNvStorageFtwWorkingSize) +
+ PcdGet32 (PcdFlashNvStorageFtwSpareSize);
+
+ //
+ // Verify the header revision, header signature, length
+ // Length of FvBlock cannot be 2**64-1
+ // HeaderLength cannot be an odd number
+ //
+ if ( (FwVolHeader->Revision != EFI_FVH_REVISION)
+ || (FwVolHeader->Signature != EFI_FVH_SIGNATURE)
+ || (FwVolHeader->FvLength != FvLength)
+ )
+ {
+ DEBUG ((DEBUG_ERROR, "%a: No Firmware Volume header present\n",
+ __FUNCTION__));
+ return EFI_NOT_FOUND;
+ }
+
+ // Check the Firmware Volume Guid
+ if( CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiSystemNvDataFvGuid) == FALSE ) {
+ DEBUG ((DEBUG_ERROR, "%a: Firmware Volume Guid non-compatible\n",
+ __FUNCTION__));
+ return EFI_NOT_FOUND;
+ }
+
+ // Verify the header checksum
+ Checksum = CalculateSum16 ((UINT16*)FwVolHeader, FwVolHeader->HeaderLength);
+ if (Checksum != 0) {
+ DEBUG ((DEBUG_ERROR, "%a: FV checksum is invalid (Checksum:0x%X)\n",
+ __FUNCTION__, Checksum));
+ return EFI_NOT_FOUND;
+ }
+
+ VariableStoreHeader = (VARIABLE_STORE_HEADER*)((UINTN)FwVolHeader +
+ FwVolHeader->HeaderLength);
+
+ // Check the Variable Store Guid
+ if (!CompareGuid (&VariableStoreHeader->Signature, &gEfiVariableGuid) &&
+ !CompareGuid (&VariableStoreHeader->Signature, &gEfiAuthenticatedVariableGuid)) {
+ DEBUG ((DEBUG_ERROR, "%a: Variable Store Guid non-compatible\n",
+ __FUNCTION__));
+ return EFI_NOT_FOUND;
+ }
+
+ VariableStoreLength = PcdGet32 (PcdFlashNvStorageVariableSize) - FwVolHeader->HeaderLength;
+ if (VariableStoreHeader->Size != VariableStoreLength) {
+ DEBUG ((DEBUG_ERROR, "%a: Variable Store Length does not match\n",
+ __FUNCTION__));
+ return EFI_NOT_FOUND;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ The GetAttributes() function retrieves the attributes and
+ current settings of the block.
+
+ @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
+
+ @param Attributes Pointer to EFI_FVB_ATTRIBUTES_2 in which the attributes and
+ current settings are returned.
+ Type EFI_FVB_ATTRIBUTES_2 is defined in EFI_FIRMWARE_VOLUME_HEADER.
+
+ @retval EFI_SUCCESS The firmware volume attributes were returned.
+
+ **/
+EFI_STATUS
+EFIAPI
+FvbGetAttributes(
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ OUT EFI_FVB_ATTRIBUTES_2 *Attributes
+ )
+{
+ EFI_FVB_ATTRIBUTES_2 FlashFvbAttributes;
+ NOR_FLASH_INSTANCE *Instance;
+
+ Instance = INSTANCE_FROM_FVB_THIS (This);
+
+ FlashFvbAttributes = (EFI_FVB_ATTRIBUTES_2) (
+
+ EFI_FVB2_READ_ENABLED_CAP | // Reads may be enabled
+ EFI_FVB2_READ_STATUS | // Reads are currently enabled
+ EFI_FVB2_STICKY_WRITE | // A block erase is required to flip bits into EFI_FVB2_ERASE_POLARITY
+ EFI_FVB2_MEMORY_MAPPED | // It is memory mapped
+ EFI_FVB2_ERASE_POLARITY // After erasure all bits take this value (i.e. '1')
+
+ );
+
+ // Check if it is write protected
+ if (Instance->Media.ReadOnly != TRUE) {
+
+ FlashFvbAttributes = FlashFvbAttributes |
+ EFI_FVB2_WRITE_STATUS | // Writes are currently enabled
+ EFI_FVB2_WRITE_ENABLED_CAP; // Writes may be enabled
+ }
+
+ *Attributes = FlashFvbAttributes;
+
+ DEBUG ((DEBUG_BLKIO, "FvbGetAttributes(0x%X)\n", *Attributes));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ The SetAttributes() function sets configurable firmware volume attributes
+ and returns the new settings of the firmware volume.
+
+
+ @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
+
+ @param Attributes On input, Attributes is a pointer to EFI_FVB_ATTRIBUTES_2
+ that contains the desired firmware volume settings.
+ On successful return, it contains the new settings of
+ the firmware volume.
+ Type EFI_FVB_ATTRIBUTES_2 is defined in EFI_FIRMWARE_VOLUME_HEADER.
+
+ @retval EFI_SUCCESS The firmware volume attributes were returned.
+
+ @retval EFI_INVALID_PARAMETER The attributes requested are in conflict with the capabilities
+ as declared in the firmware volume header.
+
+ **/
+EFI_STATUS
+EFIAPI
+FvbSetAttributes(
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes
+ )
+{
+ DEBUG ((DEBUG_BLKIO, "FvbSetAttributes(0x%X) is not supported\n",*Attributes));
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ The GetPhysicalAddress() function retrieves the base address of
+ a memory-mapped firmware volume. This function should be called
+ only for memory-mapped firmware volumes.
+
+ @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
+
+ @param Address Pointer to a caller-allocated
+ EFI_PHYSICAL_ADDRESS that, on successful
+ return from GetPhysicalAddress(), contains the
+ base address of the firmware volume.
+
+ @retval EFI_SUCCESS The firmware volume base address was returned.
+
+ @retval EFI_NOT_SUPPORTED The firmware volume is not memory mapped.
+
+ **/
+EFI_STATUS
+EFIAPI
+FvbGetPhysicalAddress (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ OUT EFI_PHYSICAL_ADDRESS *Address
+ )
+{
+ *Address = mFlashNvStorageVariableBase;
+ return EFI_SUCCESS;
+}
+
+/**
+ The GetBlockSize() function retrieves the size of the requested
+ block. It also returns the number of additional blocks with
+ the identical size. The GetBlockSize() function is used to
+ retrieve the block map (see EFI_FIRMWARE_VOLUME_HEADER).
+
+
+ @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
+
+ @param Lba Indicates the block for which to return the size.
+
+ @param BlockSize Pointer to a caller-allocated UINTN in which
+ the size of the block is returned.
+
+ @param NumberOfBlocks Pointer to a caller-allocated UINTN in
+ which the number of consecutive blocks,
+ starting with Lba, is returned. All
+ blocks in this range have a size of
+ BlockSize.
+
+
+ @retval EFI_SUCCESS The firmware volume base address was returned.
+
+ @retval EFI_INVALID_PARAMETER The requested LBA is out of range.
+
+ **/
+EFI_STATUS
+EFIAPI
+FvbGetBlockSize (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ IN EFI_LBA Lba,
+ OUT UINTN *BlockSize,
+ OUT UINTN *NumberOfBlocks
+ )
+{
+ EFI_STATUS Status;
+ NOR_FLASH_INSTANCE *Instance;
+
+ Instance = INSTANCE_FROM_FVB_THIS(This);
+
+ DEBUG ((DEBUG_BLKIO, "FvbGetBlockSize(Lba=%ld, BlockSize=0x%x, LastBlock=%ld)\n",
+ Lba, Instance->Media.BlockSize, Instance->Media.LastBlock));
+
+ if (Lba > Instance->Media.LastBlock) {
+ DEBUG ((DEBUG_ERROR, "%a : Parameter LBA %ld is beyond the last Lba (%ld)\n",
+ __FUNCTION__, Lba, Instance->Media.LastBlock));
+ Status = EFI_INVALID_PARAMETER;
+ } else {
+ // In this platform each NorFlash device has equal sized blocks.
+ *BlockSize = (UINTN) Instance->Media.BlockSize;
+ *NumberOfBlocks = (UINTN) (Instance->Media.LastBlock - Lba + 1);
+
+ DEBUG ((DEBUG_BLKIO, "%a : *BlockSize=0x%x, *NumberOfBlocks=0x%x.\n",
+ __FUNCTION__, *BlockSize, *NumberOfBlocks));
+
+ Status = EFI_SUCCESS;
+ }
+
+ return Status;
+}
+
+/**
+ Reads the specified number of bytes into a buffer from the specified block.
+
+ The Read() function reads the requested number of bytes from the
+ requested block and stores them in the provided buffer.
+ Implementations should be mindful that the firmware volume
+ might be in the ReadDisabled state. If it is in this state,
+ the Read() function must return the status code
+ EFI_ACCESS_DENIED without modifying the contents of the
+ buffer. The Read() function must also prevent spanning block
+ boundaries. If a read is requested that would span a block
+ boundary, the read must read up to the boundary but not
+ beyond. The output parameter NumBytes must be set to correctly
+ indicate the number of bytes actually read. The caller must be
+ aware that a read may be partially completed.
+
+ @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
+
+ @param Lba The starting logical block index from which to read.
+
+ @param Offset Offset into the block at which to begin reading.
+
+ @param NumBytes Pointer to a UINTN.
+ At entry, *NumBytes contains the total size of the buffer.
+ At exit, *NumBytes contains the total number of bytes read.
+
+ @param Buffer Pointer to a caller-allocated buffer that will be used
+ to hold the data that is read.
+
+ @retval EFI_SUCCESS The firmware volume was read successfully, and contents are
+ in Buffer.
+
+ @retval EFI_BAD_BUFFER_SIZE Read attempted across an LBA boundary.
+ On output, NumBytes contains the total number of bytes
+ returned in Buffer.
+
+ @retval EFI_ACCESS_DENIED The firmware volume is in the ReadDisabled state.
+
+ @retval EFI_DEVICE_ERROR The block device is not functioning correctly and could not be read.
+
+ **/
+EFI_STATUS
+EFIAPI
+FvbRead (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN OUT UINTN *NumBytes,
+ IN OUT UINT8 *Buffer
+ )
+{
+ UINTN BlockSize;
+ NOR_FLASH_INSTANCE *Instance;
+
+ Instance = INSTANCE_FROM_FVB_THIS (This);
+
+ DEBUG ((DEBUG_BLKIO, "FvbRead(Parameters: Lba=%ld, Offset=0x%x, "
+ "*NumBytes=0x%x, Buffer @ 0x%08x)\n",
+ Instance->StartLba + Lba, Offset, *NumBytes, Buffer));
+
+ if (!Instance->Initialized && Instance->Initialize) {
+ Instance->Initialize(Instance);
+ }
+
+ // Cache the block size to avoid de-referencing pointers all the time
+ BlockSize = Instance->Media.BlockSize;
+
+ DEBUG ((DEBUG_BLKIO, "FvbRead: Check if (Offset=0x%x + NumBytes=0x%x) <= "
+ "BlockSize=0x%x\n", Offset, *NumBytes, BlockSize ));
+
+ // The read must not span block boundaries.
+ while (Offset >= BlockSize) {
+ Offset -= BlockSize;
+ Lba++;
+ }
+
+ if ((Instance->StartLba + Lba) > Instance->Media.LastBlock) {
+ DEBUG ((DEBUG_ERROR, "%a : Parameter LBA %ld is beyond the last Lba (%ld)\n",
+ __FUNCTION__, Lba, Instance->Media.LastBlock));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Offset + *NumBytes) > BlockSize) {
+ *NumBytes = BlockSize-Offset;
+ }
+
+ return NorFlashPlatformRead (Instance, Instance->StartLba + Lba,
+ Offset, *NumBytes, Buffer);
+}
+
+/**
+ Writes the specified number of bytes from the input buffer to the block.
+
+ The Write() function writes the specified number of bytes from
+ the provided buffer to the specified block and offset. If the
+ firmware volume is sticky write, the caller must ensure that
+ all the bits of the specified range to write are in the
+ EFI_FVB_ERASE_POLARITY state before calling the Write()
+ function, or else the result will be unpredictable. This
+ unpredictability arises because, for a sticky-write firmware
+ volume, a write may negate a bit in the EFI_FVB_ERASE_POLARITY
+ state but cannot flip it back again. Before calling the
+ Write() function, it is recommended for the caller to first call
+ the EraseBlocks() function to erase the specified block to
+ write. A block erase cycle will transition bits from the
+ (NOT)EFI_FVB_ERASE_POLARITY state back to the
+ EFI_FVB_ERASE_POLARITY state. Implementations should be
+ mindful that the firmware volume might be in the WriteDisabled
+ state. If it is in this state, the Write() function must
+ return the status code EFI_ACCESS_DENIED without modifying the
+ contents of the firmware volume. The Write() function must
+ also prevent spanning block boundaries. If a write is
+ requested that spans a block boundary, the write must store up
+ to the boundary but not beyond. The output parameter NumBytes
+ must be set to correctly indicate the number of bytes actually
+ written. The caller must be aware that a write may be
+ partially completed. All writes, partial or otherwise, must be
+ fully flushed to the hardware before the Write() service
+ returns.
+
+ @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
+
+ @param Lba The starting logical block index to write to.
+
+ @param Offset Offset into the block at which to begin writing.
+
+ @param NumBytes The pointer to a UINTN.
+ At entry, *NumBytes contains the total size of the buffer.
+ At exit, *NumBytes contains the total number of bytes actually written.
+
+ @param Buffer The pointer to a caller-allocated buffer that contains the source for the write.
+
+ @retval EFI_SUCCESS The firmware volume was written successfully.
+
+ @retval EFI_BAD_BUFFER_SIZE The write was attempted across an LBA boundary.
+ On output, NumBytes contains the total number of bytes
+ actually written.
+
+ @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisabled state.
+
+ @retval EFI_DEVICE_ERROR The block device is malfunctioning and could not be written.
+
+
+ **/
+EFI_STATUS
+EFIAPI
+FvbWrite (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN OUT UINTN *NumBytes,
+ IN UINT8 *Buffer
+ )
+{
+ NOR_FLASH_INSTANCE *Instance;
+ UINTN BlockSize;
+
+ Instance = INSTANCE_FROM_FVB_THIS (This);
+ // Cache the block size to avoid de-referencing pointers all the time
+ BlockSize = Instance->Media.BlockSize;
+
+ if (!Instance->Initialized && Instance->Initialize) {
+ Instance->Initialize(Instance);
+ }
+
+ // The write must not span block boundaries.
+ while(Offset >= BlockSize) {
+ Offset -= BlockSize;
+ Lba++;
+ }
+
+ if ((Instance->StartLba + Lba) > Instance->Media.LastBlock) {
+ DEBUG ((DEBUG_ERROR, "%a : Parameter LBA %ld is beyond the last Lba (%ld)\n",
+ __FUNCTION__, Lba, Instance->Media.LastBlock));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Offset + *NumBytes) > BlockSize) {
+ *NumBytes = BlockSize-Offset;
+ }
+
+ return NorFlashWrite (Instance, Instance->StartLba + Lba,
+ Offset, NumBytes, Buffer);
+}
+
+/**
+ Erases and initialises a firmware volume block.
+
+ The EraseBlocks() function erases one or more blocks as denoted
+ by the variable argument list. The entire parameter list of
+ blocks must be verified before erasing any blocks. If a block is
+ requested that does not exist within the associated firmware
+ volume (it has a larger index than the last block of the
+ firmware volume), the EraseBlocks() function must return the
+ status code EFI_INVALID_PARAMETER without modifying the contents
+ of the firmware volume. Implementations should be mindful that
+ the firmware volume might be in the WriteDisabled state. If it
+ is in this state, the EraseBlocks() function must return the
+ status code EFI_ACCESS_DENIED without modifying the contents of
+ the firmware volume. All calls to EraseBlocks() must be fully
+ flushed to the hardware before the EraseBlocks() service
+ returns.
+
+ @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL
+ instance.
+
+ @param ... The variable argument list is a list of tuples.
+ Each tuple describes a range of LBAs to erase
+ and consists of the following:
+ - An EFI_LBA that indicates the starting LBA
+ - A UINTN that indicates the number of blocks to erase.
+
+ The list is terminated with an EFI_LBA_LIST_TERMINATOR.
+ For example, the following indicates that two ranges of blocks
+ (5-7 and 10-11) are to be erased:
+ EraseBlocks (This, 5, 3, 10, 2, EFI_LBA_LIST_TERMINATOR);
+
+ @retval EFI_SUCCESS The erase request successfully completed.
+
+ @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisabled state.
+
+ @retval EFI_DEVICE_ERROR The block device is not functioning correctly and could not be written.
+ The firmware device may have been partially erased.
+
+ @retval EFI_INVALID_PARAMETER One or more of the LBAs listed in the variable argument list do
+ not exist in the firmware volume.
+
+ **/
+EFI_STATUS
+EFIAPI
+FvbEraseBlocks (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ ...
+ )
+{
+ EFI_STATUS Status;
+ VA_LIST Args;
+ UINTN BlockAddress; // Physical address of Lba to erase
+ EFI_LBA StartingLba; // Lba from which we start erasing
+ UINTN NumOfLba; // Number of Lba blocks to erase
+ NOR_FLASH_INSTANCE *Instance;
+
+ Instance = INSTANCE_FROM_FVB_THIS (This);
+
+ DEBUG ((DEBUG_BLKIO, "FvbEraseBlocks()\n"));
+
+ Status = EFI_SUCCESS;
+
+ // Detect WriteDisabled state
+ if (Instance->Media.ReadOnly == TRUE) {
+ // Firmware volume is in WriteDisabled state
+ DEBUG ((DEBUG_ERROR, "%a : Device is in WriteDisabled state\n"));
+ return EFI_ACCESS_DENIED;
+ }
+
+ // Before erasing, check the entire list of parameters to
+ // ensure all specified blocks are valid
+
+ VA_START (Args, This);
+ do {
+ // Get the Lba from which we start erasing
+ StartingLba = VA_ARG (Args, EFI_LBA);
+
+ // Have we reached the end of the list?
+ if (StartingLba == EFI_LBA_LIST_TERMINATOR) {
+ //Exit the while loop
+ break;
+ }
+
+ // How many Lba blocks are we requested to erase?
+ NumOfLba = VA_ARG (Args, UINT32);
+
+ // All blocks must be within range
+ DEBUG ((DEBUG_BLKIO, "FvbEraseBlocks: Check if: ( StartingLba=%ld + "
+ "NumOfLba=%d - 1 ) > LastBlock=%ld.\n",
+ Instance->StartLba + StartingLba, NumOfLba,
+ Instance->Media.LastBlock));
+ if ((NumOfLba == 0) ||
+ ((Instance->StartLba + StartingLba + NumOfLba - 1) >
+ Instance->Media.LastBlock)) {
+ VA_END (Args);
+ DEBUG ((DEBUG_ERROR, "%a : Lba range goes past the last Lba\n"));
+ Status = EFI_INVALID_PARAMETER;
+ goto EXIT;
+ }
+ } while (TRUE);
+ VA_END (Args);
+
+ //
+ // To get here, all must be ok, so start erasing
+ //
+ VA_START (Args, This);
+ do {
+ // Get the Lba from which we start erasing
+ StartingLba = VA_ARG (Args, EFI_LBA);
+
+ // Have we reached the end of the list?
+ if (StartingLba == EFI_LBA_LIST_TERMINATOR) {
+ // Exit the while loop
+ break;
+ }
+
+ // How many Lba blocks are we requested to erase?
+ NumOfLba = VA_ARG (Args, UINT32);
+
+ // Go through each one and erase it
+ while (NumOfLba > 0) {
+
+ // Get the physical address of Lba to erase
+ BlockAddress = GET_NOR_BLOCK_ADDRESS (
+ Instance->RegionBaseAddress,
+ Instance->StartLba + StartingLba,
+ Instance->Media.BlockSize
+ );
+
+ // Erase it
+ DEBUG ((DEBUG_BLKIO, "FvbEraseBlocks: Erasing Lba=%ld @ 0x%08x.\n",
+ Instance->StartLba + StartingLba, BlockAddress));
+ Status = NorFlashPlatformEraseSector(Instance, BlockAddress);
+ if (EFI_ERROR (Status)) {
+ VA_END (Args);
+ Status = EFI_DEVICE_ERROR;
+ goto EXIT;
+ }
+
+ // Move to the next Lba
+ StartingLba++;
+ NumOfLba--;
+ }
+ } while (TRUE);
+ VA_END (Args);
+
+EXIT:
+ return Status;
+}
+
+/**
+ Fixup internal data so that EFI can be call in virtual mode.
+ Call the passed in Child Notify event and convert any pointers in
+ lib to virtual mode.
+
+ @param[in] Event The Event that is being processed
+ @param[in] Context Event Context
+**/
+VOID
+EFIAPI
+FvbVirtualNotifyEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EfiConvertPointer (0x0, (VOID**)&mFlashNvStorageVariableBase);
+ return;
+}
+
+EFI_STATUS
+EFIAPI
+NorFlashFvbInitialize (
+ IN NOR_FLASH_INSTANCE* Instance
+ )
+{
+ EFI_STATUS Status;
+ UINT32 FvbNumLba;
+ EFI_BOOT_MODE BootMode;
+ UINTN RuntimeMmioRegionSize;
+
+ DEBUG ((DEBUG_BLKIO,"NorFlashFvbInitialize\n"));
+
+ Instance->Initialized = TRUE;
+ mFlashNvStorageVariableBase = FixedPcdGet64 (PcdFlashNvStorageVariableBase64);
+
+ // Set the index of the first LBA for the FVB
+ Instance->StartLba = (PcdGet64 (PcdFlashNvStorageVariableBase64) - Instance->RegionBaseAddress) / Instance->Media.BlockSize;
+
+ BootMode = GetBootModeHob ();
+ if (BootMode == BOOT_WITH_DEFAULT_SETTINGS) {
+ Status = EFI_INVALID_PARAMETER;
+ }
+ else {
+ // Determine if there is a valid header at the beginning of the NorFlash
+ Status = ValidateFvHeader (Instance);
+ }
+
+ // Install the Default FVB header if required
+ if (EFI_ERROR (Status)) {
+ // There is no valid header, so time to install one.
+ DEBUG ((DEBUG_INFO, "%a: The FVB Header is not valid.\n", __FUNCTION__));
+ DEBUG ((DEBUG_INFO, "%a: Installing a correct one for this volume.\n",
+ __FUNCTION__));
+
+ // Erase all the NorFlash that is reserved for variable storage
+ FvbNumLba = (PcdGet32 (PcdFlashNvStorageVariableSize) + PcdGet32 (PcdFlashNvStorageFtwWorkingSize) + PcdGet32 (PcdFlashNvStorageFtwSpareSize)) / Instance->Media.BlockSize;
+
+ Status = FvbEraseBlocks (&Instance->FvbProtocol, (EFI_LBA)0, FvbNumLba, EFI_LBA_LIST_TERMINATOR);
+ if (EFI_ERROR (Status))
+ return Status;
+
+ // Install all appropriate headers
+ Status = InitializeFvAndVariableStoreHeaders (Instance);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ //
+ // Declare the Non-Volatile storage as EFI_MEMORY_RUNTIME
+ //
+
+ // Note: all the NOR Flash region needs to be reserved into the UEFI Runtime memory;
+ // even if we only use the small block region at the top of the NOR Flash.
+ // The reason is when the NOR Flash memory is set into program mode, the command
+ // is written as the base of the flash region (ie: Instance->DeviceBaseAddress)
+ RuntimeMmioRegionSize = (Instance->RegionBaseAddress - Instance->DeviceBaseAddress) + Instance->Size;
+
+ Status = gDS->AddMemorySpace (
+ EfiGcdMemoryTypeMemoryMappedIo,
+ Instance->DeviceBaseAddress, RuntimeMmioRegionSize,
+ EFI_MEMORY_UC | EFI_MEMORY_RUNTIME
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = gDS->SetMemorySpaceAttributes (
+ Instance->DeviceBaseAddress, RuntimeMmioRegionSize,
+ EFI_MEMORY_UC | EFI_MEMORY_RUNTIME);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Register for the virtual address change event
+ //
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ FvbVirtualNotifyEvent,
+ NULL,
+ &gEfiEventVirtualAddressChangeGuid,
+ &mFvbVirtualAddrChangeEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
diff --git a/Platform/NXP/Include/Library/NorFlash.h b/Platform/NXP/Include/Library/NorFlash.h
new file mode 100644
index 0000000..37099ff
--- /dev/null
+++ b/Platform/NXP/Include/Library/NorFlash.h
@@ -0,0 +1,222 @@
+/** @NorFlash.h
+
+ Based on NOR flash access APIs used in ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.h
+
+ Copyright (c) 2011 - 2014, ARM Ltd. All rights reserved.
+ Copyright 2017 NXP
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __NOR_FLASH_H__
+#define __NOR_FLASH_H__
+
+#include <Protocol/BlockIo.h>
+#include <Protocol/FirmwareVolumeBlock.h>
+
+#define NOR_FLASH_ERASE_RETRY 10
+
+#define GET_NOR_BLOCK_ADDRESS(BaseAddr,Lba,LbaSize) ( BaseAddr + (UINTN)((Lba) * LbaSize) )
+
+#define NOR_FLASH_SIGNATURE SIGNATURE_32('n', 'o', 'r', '0')
+#define INSTANCE_FROM_FVB_THIS(a) CR(a, NOR_FLASH_INSTANCE, FvbProtocol, NOR_FLASH_SIGNATURE)
+#define INSTANCE_FROM_BLKIO_THIS(a) CR(a, NOR_FLASH_INSTANCE, BlockIoProtocol, NOR_FLASH_SIGNATURE)
+
+typedef struct _NOR_FLASH_INSTANCE NOR_FLASH_INSTANCE;
+
+typedef EFI_STATUS (*NOR_FLASH_INITIALIZE) (NOR_FLASH_INSTANCE* Instance);
+
+typedef struct {
+ VENDOR_DEVICE_PATH Vendor;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} NOR_FLASH_DEVICE_PATH;
+
+struct _NOR_FLASH_INSTANCE {
+ UINT32 Signature;
+ EFI_HANDLE Handle;
+ BOOLEAN Initialized;
+ NOR_FLASH_INITIALIZE Initialize;
+ UINTN DeviceBaseAddress;
+ UINTN RegionBaseAddress;
+ UINTN Size;
+ EFI_LBA StartLba;
+ EFI_BLOCK_IO_PROTOCOL BlockIoProtocol;
+ EFI_BLOCK_IO_MEDIA Media;
+ BOOLEAN SupportFvb;
+ EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL FvbProtocol;
+ VOID* ShadowBuffer;
+ NOR_FLASH_DEVICE_PATH DevicePath;
+};
+
+//
+// NorFlashLib.c related
+//
+
+EFI_STATUS
+NorFlashPlatformWriteBuffer (
+ IN NOR_FLASH_INSTANCE *Instance,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN OUT UINTN *NumBytes,
+ IN UINT8 *Buffer
+ );
+
+EFI_STATUS
+NorFlashPlatformEraseSector (
+ IN NOR_FLASH_INSTANCE *Instance,
+ IN UINTN SectorAddress
+ );
+
+EFI_STATUS
+NorFlashPlatformControllerInitialization (
+ VOID
+ );
+
+EFI_STATUS
+NorFlashPlatformRead (
+ IN NOR_FLASH_INSTANCE *Instance,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN UINTN BufferSizeInBytes,
+ OUT UINT8 *Buffer
+ );
+
+EFI_STATUS
+NorFlashPlatformReset (
+ IN UINTN Instance
+ );
+
+extern CONST EFI_GUID* CONST mNorFlashVariableGuid;
+
+//
+// NorFlashFvbDxe.c
+//
+
+EFI_STATUS
+EFIAPI
+NorFlashFvbInitialize (
+ IN NOR_FLASH_INSTANCE* Instance
+ );
+
+EFI_STATUS
+EFIAPI
+FvbGetAttributes(
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ OUT EFI_FVB_ATTRIBUTES_2 *Attributes
+ );
+
+EFI_STATUS
+EFIAPI
+FvbSetAttributes(
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes
+ );
+
+EFI_STATUS
+EFIAPI
+FvbGetPhysicalAddress(
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ OUT EFI_PHYSICAL_ADDRESS *Address
+ );
+
+EFI_STATUS
+EFIAPI
+FvbGetBlockSize(
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ IN EFI_LBA Lba,
+ OUT UINTN *BlockSize,
+ OUT UINTN *NumberOfBlocks
+ );
+
+EFI_STATUS
+EFIAPI
+FvbRead(
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN OUT UINTN *NumBytes,
+ IN OUT UINT8 *Buffer
+ );
+
+EFI_STATUS
+EFIAPI
+FvbWrite(
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN OUT UINTN *NumBytes,
+ IN UINT8 *Buffer
+ );
+
+EFI_STATUS
+EFIAPI
+FvbEraseBlocks(
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ ...
+ );
+//
+// NorFlashBlockIoDxe.c
+//
+
+//
+// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.Reset
+//
+EFI_STATUS
+EFIAPI
+NorFlashBlockIoReset (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ );
+
+//
+// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.ReadBlocks
+//
+EFI_STATUS
+EFIAPI
+NorFlashBlockIoReadBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSizeInBytes,
+ OUT VOID *Buffer
+);
+
+//
+// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.WriteBlocks
+//
+EFI_STATUS
+EFIAPI
+NorFlashBlockIoWriteBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSizeInBytes,
+ IN VOID *Buffer
+);
+
+//
+// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.FlushBlocks
+//
+EFI_STATUS
+EFIAPI
+NorFlashBlockIoFlushBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This
+);
+
+EFI_STATUS
+NorFlashWrite (
+ IN NOR_FLASH_INSTANCE *Instance,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN OUT UINTN *NumBytes,
+ IN UINT8 *Buffer
+);
+
+#endif /* __NOR_FLASH_DXE_H__ */
diff --git a/Silicon/NXP/Chassis/Chassis.c b/Silicon/NXP/Chassis/Chassis.c
index a6a77c2..ab0076f 100644
--- a/Silicon/NXP/Chassis/Chassis.c
+++ b/Silicon/NXP/Chassis/Chassis.c
@@ -17,6 +17,7 @@
#include <Library/BaseLib.h>
#include <Library/BeIoLib.h>
#include <Library/DebugLib.h>
+#include <Library/IfcBase.h>
#include <Library/IoLib.h>
#include <Library/PcdLib.h>
#include <Library/PrintLib.h>
@@ -411,3 +412,17 @@ CalculateI2cClockRate (
return SocSysInfo.FreqSystemBus;
}
+
+/**
+ Initialize IFC device timings
+**/
+VOID
+IfcInit (
+ VOID
+ )
+{
+ // NOR Init
+ if (FixedPcdGet64 (PcdIfcNorEnabled)) {
+ IfcNorInit ();
+ }
+}
diff --git a/Silicon/NXP/Chassis/Chassis.h b/Silicon/NXP/Chassis/Chassis.h
index 4bdb4d0..c8057f0 100644
--- a/Silicon/NXP/Chassis/Chassis.h
+++ b/Silicon/NXP/Chassis/Chassis.h
@@ -141,4 +141,11 @@ CpuNumCores (
VOID
);
+/**
+ Initialize IFC Device timings
+ **/
+VOID
+IfcInit (
+ VOID
+ );
#endif /* __CHASSIS_H__ */
diff --git a/Silicon/NXP/Chassis/Chassis2/Soc.c b/Silicon/NXP/Chassis/Chassis2/Soc.c
index 2f57929..847bbc2 100644
--- a/Silicon/NXP/Chassis/Chassis2/Soc.c
+++ b/Silicon/NXP/Chassis/Chassis2/Soc.c
@@ -140,6 +140,7 @@ SocInit (
PrintCpuInfo ();
PrintRCW ();
+ IfcInit ();
return;
}
diff --git a/Silicon/NXP/Chassis/LS1043aSocLib.inf b/Silicon/NXP/Chassis/LS1043aSocLib.inf
index e6e7ac4..b11fdc2 100644
--- a/Silicon/NXP/Chassis/LS1043aSocLib.inf
+++ b/Silicon/NXP/Chassis/LS1043aSocLib.inf
@@ -32,6 +32,7 @@
BeIoLib
DebugLib
SerialPortLib
+ NorFlashLib
[Sources.common]
Chassis.c
@@ -45,3 +46,4 @@
gNxpQoriqLsTokenSpaceGuid.PcdSerdes2Enabled
gNxpQoriqLsTokenSpaceGuid.PcdGurBigEndian
gNxpQoriqLsTokenSpaceGuid.PcdClkBaseAddr
+ gNxpQoriqLsTokenSpaceGuid.PcdIfcNorEnabled
--
1.9.1
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel
© 2016 - 2024 Red Hat, Inc.