ArmPlatformPkg/NorFlashDxe: Move NorFlash driver from ArmVExpressPkg to ArmPlatformPkg
authoroliviermartin <oliviermartin@6f19259b-4bc3-4df7-8a09-765794883524>
Fri, 3 Jun 2011 09:35:57 +0000 (09:35 +0000)
committeroliviermartin <oliviermartin@6f19259b-4bc3-4df7-8a09-765794883524>
Fri, 3 Jun 2011 09:35:57 +0000 (09:35 +0000)
This NOR Flash driver can be reused for other platform (eg: ARM Realview EB).

To make this driver reusable on other platforms the NorFlashPlatformLib library
has been created to abstract the platform specific bits such as the pre-requirements
steps to the initialization and the geometry of the NOR Flash regions.

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11746 6f19259b-4bc3-4df7-8a09-765794883524

16 files changed:
ArmPlatformPkg/ArmPlatformPkg.dec
ArmPlatformPkg/ArmVExpressPkg/ArmVExpress-CTA9x4.dsc
ArmPlatformPkg/ArmVExpressPkg/ArmVExpress-CTA9x4.fdf
ArmPlatformPkg/ArmVExpressPkg/Library/NorFlashArmVExpressLib/NorFlashArmVExpress.c [new file with mode: 0644]
ArmPlatformPkg/ArmVExpressPkg/Library/NorFlashArmVExpressLib/NorFlashArmVExpressLib.inf [new file with mode: 0644]
ArmPlatformPkg/ArmVExpressPkg/NorFlashDxe/NorFlashBlockIoDxe.c [deleted file]
ArmPlatformPkg/ArmVExpressPkg/NorFlashDxe/NorFlashDxe.c [deleted file]
ArmPlatformPkg/ArmVExpressPkg/NorFlashDxe/NorFlashDxe.h [deleted file]
ArmPlatformPkg/ArmVExpressPkg/NorFlashDxe/NorFlashDxe.inf [deleted file]
ArmPlatformPkg/ArmVExpressPkg/NorFlashDxe/NorFlashFvbDxe.c [deleted file]
ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashBlockIoDxe.c [new file with mode: 0644]
ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.c [new file with mode: 0644]
ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.h [new file with mode: 0644]
ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.inf [new file with mode: 0644]
ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashFvbDxe.c [new file with mode: 0644]
ArmPlatformPkg/Include/Library/NorFlashPlatformLib.h [new file with mode: 0644]

index 66ec195..1f83f43 100644 (file)
 
 [Guids.common]
   gArmPlatformTokenSpaceGuid    =  { 0x9c0aaed4, 0x74c5, 0x4043, { 0xb4, 0x17, 0xa3, 0x22, 0x38, 0x14, 0xce, 0x76 } }
+  #
+  # Following Guid must match FILE_GUID in MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
+  #
+  gVariableRuntimeDxeFileGuid = { 0xcbd2e4d5, 0x7068, 0x4ff5, { 0xb4, 0x62, 0x98, 0x22, 0xb4, 0xad, 0x8d, 0x60 } }
 
 [PcdsFeatureFlag.common]
   gArmPlatformTokenSpaceGuid.PcdStandalone|FALSE|BOOLEAN|0x00000001
index 2adbf2d..2aeeaf1 100644 (file)
   PL301AxiLib|ArmPkg/Drivers/PL301Axi/PL301Axi.inf
   # ARM PL011 UART Driver
   PL011UartLib|ArmPlatformPkg/Drivers/PL011Uart/PL011Uart.inf
+  
+  NorFlashPlatformLib|ArmPlatformPkg/ArmVExpressPkg/Library/NorFlashArmVExpressLib/NorFlashArmVExpressLib.inf
 
 #
 # Assume everything is fixed at build
   EmbeddedPkg/SimpleTextInOutSerial/SimpleTextInOutSerial.inf
 
   ArmPkg/Drivers/PL390Gic/PL390GicDxe.inf
-  ArmPlatformPkg/ArmVExpressPkg/NorFlashDxe/NorFlashDxe.inf
+  ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.inf
   ArmPlatformPkg/Drivers/SP804TimerDxe/SP804TimerDxe.inf
 
   #
index 12af856..1932df4 100644 (file)
@@ -160,7 +160,7 @@ READ_LOCK_STATUS   = TRUE
 
   INF ArmPkg/Drivers/PL390Gic/PL390GicDxe.inf
   INF ArmPlatformPkg/Drivers/SP804TimerDxe/SP804TimerDxe.inf
-  INF ArmPlatformPkg/ArmVExpressPkg/NorFlashDxe/NorFlashDxe.inf
+  INF ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.inf
 
   #
   # Semi-hosting filesystem
diff --git a/ArmPlatformPkg/ArmVExpressPkg/Library/NorFlashArmVExpressLib/NorFlashArmVExpress.c b/ArmPlatformPkg/ArmVExpressPkg/Library/NorFlashArmVExpressLib/NorFlashArmVExpress.c
new file mode 100644 (file)
index 0000000..4171aae
--- /dev/null
@@ -0,0 +1,79 @@
+/** @file\r
+\r
+ Copyright (c) 2011, ARM Ltd. All rights reserved.<BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution.  The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+ **/\r
+\r
+#include <PiDxe.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/IoLib.h>\r
+#include <Library/NorFlashPlatformLib.h>\r
+#include <ArmPlatform.h>\r
+\r
+#define NOR_FLASH_DEVICE_COUNT                     4\r
+\r
+NOR_FLASH_DESCRIPTION mNorFlashDevices[NOR_FLASH_DEVICE_COUNT] = {\r
+  { // BootMon\r
+    ARM_VE_SMB_NOR0_BASE,\r
+    SIZE_256KB * 255,\r
+    SIZE_256KB,\r
+    {0xE7223039, 0x5836, 0x41E1, 0xB5, 0x42, 0xD7, 0xEC, 0x73, 0x6C, 0x5E, 0x59}\r
+  },\r
+  { // BootMon non-volatile storage\r
+    ARM_VE_SMB_NOR0_BASE + SIZE_256KB * 255,\r
+    SIZE_64KB * 4,\r
+    SIZE_64KB,\r
+    {0x02118005, 0x9DA7, 0x443A, 0x92, 0xD5, 0x78, 0x1F, 0x02, 0x2A, 0xED, 0xBB}\r
+  },\r
+  { // UEFI\r
+    ARM_VE_SMB_NOR1_BASE,\r
+    SIZE_256KB * 255,\r
+    SIZE_256KB,\r
+    {0x1F15DA3C, 0x37FF, 0x4070, 0xB4, 0x71, 0xBB, 0x4A, 0xF1, 0x2A, 0x72, 0x4A}\r
+  },\r
+  { // UEFI Variable Services non-volatile storage\r
+    ARM_VE_SMB_NOR1_BASE + SIZE_256KB * 255,\r
+    SIZE_64KB * 3, //FIXME: Set 3 blocks because I did not succeed to copy 4 blocks into the ARM Versatile Express NOR Flash in the last NOR Flash. It should be 4 blocks\r
+    SIZE_64KB,\r
+    {0xCC2CBF29, 0x1498, 0x4CDD, 0x81, 0x71, 0xF8, 0xB6, 0xB4, 0x1D, 0x09, 0x09}\r
+  }\r
+};\r
+\r
+EFI_STATUS\r
+NorFlashPlatformInitialization (\r
+  VOID\r
+  )\r
+{\r
+  // Everything seems ok so far, so now we need to disable the platform-specific\r
+  // flash write protection for Versatile Express\r
+  if ((MmioRead32 (ARM_VE_SYS_FLASH) & 0x1) == 0) {\r
+    // Writing to NOR FLASH is disabled, so enable it\r
+    MmioWrite32 (ARM_VE_SYS_FLASH,1);\r
+    DEBUG((DEBUG_BLKIO, "NorFlashWriteBlocks: informational - Had to enable HSYS_FLASH flag.\n" ));\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+NorFlashPlatformGetDevices (\r
+  OUT NOR_FLASH_DESCRIPTION   **NorFlashDevices,\r
+  OUT UINT32                  *Count\r
+  )\r
+{\r
+  if ((NorFlashDevices == NULL) || (Count == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  *NorFlashDevices = mNorFlashDevices;\r
+  *Count = NOR_FLASH_DEVICE_COUNT;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
diff --git a/ArmPlatformPkg/ArmVExpressPkg/Library/NorFlashArmVExpressLib/NorFlashArmVExpressLib.inf b/ArmPlatformPkg/ArmVExpressPkg/Library/NorFlashArmVExpressLib/NorFlashArmVExpressLib.inf
new file mode 100644 (file)
index 0000000..85b17ef
--- /dev/null
@@ -0,0 +1,41 @@
+#/** @file
+#  
+#  Component discription file for ArmVeGraphicsDxe module
+#  
+#  Copyright (c) 2011, ARM Ltd. All rights reserved.<BR>
+#  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                    = 0x00010005
+  BASE_NAME                      = NorFlashArmVExpressLib
+  FILE_GUID                      = c0f5dfa0-7599-11e0-9665-0002a5d5c51b
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = NorFlashPlatformLib
+  
+[Sources.common]
+  NorFlashArmVExpress.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  ArmPlatformPkg/ArmPlatformPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  DebugLib
+  IoLib
+
+[Guids]
+
+[Protocols]
+
+[Pcd]
+
diff --git a/ArmPlatformPkg/ArmVExpressPkg/NorFlashDxe/NorFlashBlockIoDxe.c b/ArmPlatformPkg/ArmVExpressPkg/NorFlashDxe/NorFlashBlockIoDxe.c
deleted file mode 100644 (file)
index ad2c87b..0000000
+++ /dev/null
@@ -1,149 +0,0 @@
-/** @file  NorFlashBlockIoDxe.c
-
-  Copyright (c) 2010, ARM Ltd. All rights reserved.<BR>
-  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/BaseMemoryLib.h>
-#include <Library/UefiBootServicesTableLib.h>
-
-#include "NorFlashDxe.h"
-
-EFI_STATUS
-EFIAPI
-NorFlashBlkIoInitialize (
-  IN NOR_FLASH_INSTANCE* Instance
-  ) {
-  UINT32                Reply;
-  EFI_STATUS            Status = EFI_SUCCESS;
-
-  DEBUG((DEBUG_BLKIO,"NorFlashBlkIoInitialize()\n"));
-
-  //
-  // Verify that there is a physical hardware device where we expect it to be.
-  //
-
-  // Read a specific CFI query that returns back "QRY"
-  // This ensures that there is really a device present there
-  SEND_NOR_COMMAND( Instance->BaseAddress, 0, P30_CMD_READ_CFI_QUERY );
-
-  // Read CFI 'QRY' data
-  Status = NorFlashReadCfiData( Instance->BaseAddress,
-                                 P30_CFI_ADDR_QUERY_UNIQUE_QRY,
-                                 3,
-                                 &Reply
-                               );
-  if (EFI_ERROR(Status)) {
-    goto EXIT;
-  }
-
-  if ( Reply != CFI_QRY ) {
-    DEBUG((EFI_D_ERROR, "NorFlashBlkIoInitialize: CFI QRY=0x%x (expected 0x595251)\n", Reply));
-    Status = EFI_DEVICE_ERROR;
-    goto EXIT;
-  }
-
-EXIT:
-  // Reset the device
-  Status = NorFlashBlockIoReset( &Instance->BlockIoProtocol, FALSE );
-  if (EFI_ERROR(Status)) {
-    goto EXIT;
-  }
-
-  Instance->Initialized = TRUE;
-  return EFI_SUCCESS;
-}
-
-
-//
-// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.Reset
-//
-EFI_STATUS
-EFIAPI
-NorFlashBlockIoReset (
-  IN EFI_BLOCK_IO_PROTOCOL  *This,
-  IN BOOLEAN                ExtendedVerification
-  )
-{
-  EFI_STATUS     Status;
-  NOR_FLASH_INSTANCE *Instance;
-
-  Instance = INSTANCE_FROM_BLKIO_THIS(This);
-
-  DEBUG ((DEBUG_BLKIO, "NorFlashBlockIoReset(MediaId=0x%x)\n", This->Media->MediaId));
-
-  Status = NorFlashReset(Instance);
-
-  return Status;
-
-}
-
-//
-// 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;
-
-  Instance = INSTANCE_FROM_BLKIO_THIS(This);
-
-  DEBUG ((DEBUG_BLKIO, "NorFlashBlockIoReadBlocks(MediaId=0x%x, Lba=%ld, BufferSize=0x%x bytes (%d kB), BufferPtr @ 0x%08x)\n", MediaId, Lba, BufferSizeInBytes, Buffer));
-
-  return NorFlashReadBlocks(Instance,Lba,BufferSizeInBytes,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
-  )
-{
-  NOR_FLASH_INSTANCE *Instance;
-
-  Instance = INSTANCE_FROM_BLKIO_THIS(This);
-
-  DEBUG ((DEBUG_BLKIO, "NorFlashBlockIoWriteBlocks(MediaId=0x%x, Lba=%ld, BufferSize=0x%x bytes (%d kB), BufferPtr @ 0x%08x)\n", MediaId, Lba, BufferSizeInBytes, Buffer));
-
-  return NorFlashWriteBlocks(Instance,Lba,BufferSizeInBytes,Buffer);
-}
-
-//
-// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.FlushBlocks
-//
-EFI_STATUS
-EFIAPI
-NorFlashBlockIoFlushBlocks (
-  IN EFI_BLOCK_IO_PROTOCOL  *This
-  )
-{
-  // No Flush required for the NOR Flash driver
-  // because cache operations are not permitted.
-
-  DEBUG ((DEBUG_BLKIO, "NorFlashBlockIoFlushBlocks: Function NOT IMPLEMENTED (not required).\n"));
-
-  // Nothing to do so just return without error
-  return EFI_SUCCESS;
-}
diff --git a/ArmPlatformPkg/ArmVExpressPkg/NorFlashDxe/NorFlashDxe.c b/ArmPlatformPkg/ArmVExpressPkg/NorFlashDxe/NorFlashDxe.c
deleted file mode 100644 (file)
index 0fd41ce..0000000
+++ /dev/null
@@ -1,800 +0,0 @@
-/** @file  NorFlashDxe.c
-
-  Copyright (c) 2011, ARM Ltd. All rights reserved.<BR>
-  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/UefiLib.h>
-#include <Library/DebugLib.h>
-#include <Library/BaseMemoryLib.h>
-#include <Library/MemoryAllocationLib.h>
-#include <Library/UefiBootServicesTableLib.h>
-#include <Library/PcdLib.h>
-
-#include "NorFlashDxe.h"
-
-
-//
-// Global variable declarations
-//
-
-#define NOR_FLASH_LAST_DEVICE                     4
-
-NOR_FLASH_DESCRIPTION mNorFlashDescription[NOR_FLASH_LAST_DEVICE] = {
-  { // BootMon
-    ARM_VE_SMB_NOR0_BASE,
-    SIZE_256KB * 255,
-    SIZE_256KB,
-    {0xE7223039, 0x5836, 0x41E1, 0xB5, 0x42, 0xD7, 0xEC, 0x73, 0x6C, 0x5E, 0x59}
-  },
-  { // BootMon non-volatile storage
-    ARM_VE_SMB_NOR0_BASE + SIZE_256KB * 255,
-    SIZE_64KB * 4,
-    SIZE_64KB,
-    {0x02118005, 0x9DA7, 0x443A, 0x92, 0xD5, 0x78, 0x1F, 0x02, 0x2A, 0xED, 0xBB}
-  },
-  { // UEFI
-    ARM_VE_SMB_NOR1_BASE,
-    SIZE_256KB * 255,
-    SIZE_256KB,
-    {0x1F15DA3C, 0x37FF, 0x4070, 0xB4, 0x71, 0xBB, 0x4A, 0xF1, 0x2A, 0x72, 0x4A}
-  },
-  { // UEFI Variable Services non-volatile storage
-    ARM_VE_SMB_NOR1_BASE + SIZE_256KB * 255,
-    SIZE_64KB * 3, //FIXME: Set 3 blocks because I did not succeed to copy 4 blocks into the ARM Versastile Express NOR Falsh in the last NOR Flash. It should be 4 blocks
-    SIZE_64KB,
-    {0xCC2CBF29, 0x1498, 0x4CDD, 0x81, 0x71, 0xF8, 0xB6, 0xB4, 0x1D, 0x09, 0x09}
-  }
-};
-
-NOR_FLASH_INSTANCE *mNorFlashInstances[ NOR_FLASH_LAST_DEVICE ];
-
-NOR_FLASH_INSTANCE  mNorFlashInstanceTemplate = {
-  NOR_FLASH_SIGNATURE, // Signature
-  NULL, // Handle ... NEED TO BE FILLED
-
-  FALSE, // Initialized
-  NULL, // Initialize
-
-  0, // BaseAddress ... NEED TO BE FILLED
-  0, // Size ... NEED TO BE FILLED
-
-  {\r
-    EFI_BLOCK_IO_PROTOCOL_REVISION2, // Revision\r
-    NULL, // Media ... NEED TO BE FILLED\r
-    NorFlashBlockIoReset, // Reset;\r
-    NorFlashBlockIoReadBlocks,          // ReadBlocks
-    NorFlashBlockIoWriteBlocks,         // WriteBlocks
-    NorFlashBlockIoFlushBlocks          // FlushBlocks\r
-  }, // BlockIoProtocol
-
-  {\r
-    0, // MediaId ... NEED TO BE FILLED\r
-    FALSE, // RemovableMedia\r
-    TRUE, // MediaPresent\r
-    FALSE, // LogicalPartition\r
-    FALSE, // ReadOnly\r
-    FALSE, // WriteCaching;\r
-    0, // BlockSize ... NEED TO BE FILLED\r
-    4, //  IoAlign\r
-    0, // LastBlock ... NEED TO BE FILLED\r
-    0, // LowestAlignedLba\r
-    1, // LogicalBlocksPerPhysicalBlock\r
-  }, //Media;
-
-  FALSE, // SupportFvb ... NEED TO BE FILLED
-  {\r
-    FvbGetAttributes, // GetAttributes
-    FvbSetAttributes, // SetAttributes
-    FvbGetPhysicalAddress,  // GetPhysicalAddress
-    FvbGetBlockSize,  // GetBlockSize
-    FvbRead,  // Read
-    FvbWrite, // Write
-    FvbEraseBlocks, // EraseBlocks\r
-    NULL, //ParentHandle\r
-  }, //  FvbProtoccol;
-
-  {
-    {
-      {
-        HARDWARE_DEVICE_PATH,
-        HW_VENDOR_DP,
-        (UINT8)( sizeof(VENDOR_DEVICE_PATH)      ),
-        (UINT8)((sizeof(VENDOR_DEVICE_PATH)) >> 8),
-      },
-      { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, // GUID ... NEED TO BE FILLED
-    },
-    {
-      END_DEVICE_PATH_TYPE,
-      END_ENTIRE_DEVICE_PATH_SUBTYPE,
-      sizeof (EFI_DEVICE_PATH_PROTOCOL),
-      0
-    }
-    } // DevicePath
-};
-
-EFI_STATUS NorFlashCreateInstance(
-    IN UINTN NorFlashBase,
-    IN UINTN NorFlashSize,
-    IN UINT32 MediaId,
-    IN UINT32  BlockSize,
-    IN BOOLEAN SupportFvb,
-    IN CONST GUID  *NorFlashGuid,
-    OUT NOR_FLASH_INSTANCE** NorFlashInstance
-  ) {
-  EFI_STATUS Status;
-  NOR_FLASH_INSTANCE* Instance;
-
-  ASSERT(NorFlashInstance != NULL);
-
-  Instance = AllocateCopyPool (sizeof(NOR_FLASH_INSTANCE),&mNorFlashInstanceTemplate);
-  if (Instance == NULL) {
-    return EFI_OUT_OF_RESOURCES;
-  }
-
-  Instance->BaseAddress = NorFlashBase;
-  Instance->Size = NorFlashSize;
-
-  Instance->BlockIoProtocol.Media = &Instance->Media;
-  Instance->Media.MediaId = MediaId;
-  Instance->Media.BlockSize = BlockSize;
-  Instance->Media.LastBlock = (NorFlashSize / BlockSize)-1;
-\r
-  CopyGuid (&Instance->DevicePath.Vendor.Guid,NorFlashGuid);\r
-
-  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);
-      return Status;
-    }
-  } else {
-    Instance->Initialize = NorFlashBlkIoInitialize;
-
-    Status = gBS->InstallMultipleProtocolInterfaces (
-                    &Instance->Handle,
-                    &gEfiDevicePathProtocolGuid, &Instance->DevicePath,
-                    &gEfiBlockIoProtocolGuid,  &Instance->BlockIoProtocol,
-                    NULL
-                    );
-    if (EFI_ERROR(Status)) {
-      FreePool(Instance);
-      return Status;
-    }
-  }
-\r
-  *NorFlashInstance = Instance;\r
-  return Status;\r
-}
-
-EFI_STATUS
-NorFlashReadCfiData (
-  IN UINTN   BaseAddress,
-  IN UINTN   CFI_Offset,
-  IN UINT32  NumberOfBytes,
-  OUT UINT32 *Data
-)
-{
-  UINT32          CurrentByte;
-  volatile UINTN  *ReadAddress;
-  UINT32          ReadData;
-  UINT32          Byte1;
-  UINT32          Byte2;
-  UINT32          CombinedData = 0;
-  EFI_STATUS      Status = EFI_SUCCESS;
-
-
-  if( NumberOfBytes > 4 ) {
-    // Using 32 bit variable so can only read 4 bytes
-    return EFI_INVALID_PARAMETER;
-  }
-
-  // First combine the base address with the offset address
-  // to create an absolute read address.
-  // However, because we are in little endian, read from the last address down to the first
-  ReadAddress = CREATE_NOR_ADDRESS( BaseAddress, CFI_Offset ) + NumberOfBytes - 1;
-
-  // Although each read returns 32 bits, because of the NOR Flash structure,
-  // each 16 bits (16 MSB and 16 LSB) come from two different chips.
-  // When in CFI mode, each chip read returns valid data in only the 8 LSBits;
-  // the 8 MSBits are invalid and can be ignored.
-  // Therefore, each read address returns one byte from each chip.
-  //
-  // Also note: As we are in little endian notation and we are reading
-  // bytes from incremental addresses, we should assemble them in little endian order.
-  for( CurrentByte=0; CurrentByte<NumberOfBytes; CurrentByte++  ) {
-
-    // Read the bytes from the two chips
-    ReadData = *ReadAddress;
-
-    // Check the data validity:
-    // The 'Dual Data' function means that
-    // each chip should return identical data.
-    // If that is not the case then we have a problem.
-    Byte1 = GET_LOW_BYTE ( ReadData );
-    Byte2 = GET_HIGH_BYTE( ReadData );
-
-    if( Byte1 != Byte2 ) {
-      // The two bytes should have been identical
-      return EFI_DEVICE_ERROR;
-    } else {
-
-      // Each successive iteration of the 'for' loop reads a lower address.
-      // As we read lower addresses and as we use little endian,
-      // we read lower significance bytes. So combine them in the correct order.
-      CombinedData = (CombinedData << 8) | Byte1;
-
-      // Decrement down to the next address
-      ReadAddress--;
-    }
-  }
-
-  *Data = CombinedData;
-
-  return Status;
-}
-
-EFI_STATUS
-NorFlashReadStatusRegister(
-  IN UINTN SR_Address
-  )
-{
-  volatile UINT32       *pStatusRegister;
-  UINT32                StatusRegister;
-  UINT32                ErrorMask;
-  EFI_STATUS            Status = EFI_SUCCESS;
-
-  // Prepare the read address
-  pStatusRegister = (UINT32 *) SR_Address;
-
-  do {
-    // Prepare to read the status register
-    SEND_NOR_COMMAND( SR_Address, 0, P30_CMD_READ_STATUS_REGISTER );
-    // Snapshot the status register
-    StatusRegister = *pStatusRegister;
-  }
-  // The chip is busy while the WRITE bit is not asserted
-  while ( (StatusRegister & P30_SR_BIT_WRITE) != P30_SR_BIT_WRITE );
-
-
-  // Perform a full status check:
-  // Mask the relevant bits of Status Register.
-  // Everything should be zero, if not, we have a problem
-
-  // Prepare the Error Mask by setting bits 5, 4, 3, 1
-  ErrorMask = P30_SR_BIT_ERASE | P30_SR_BIT_PROGRAM | P30_SR_BIT_VPP | P30_SR_BIT_BLOCK_LOCKED ;
-
-  if ( (StatusRegister & ErrorMask) != 0 ) {
-    if ( (StatusRegister & P30_SR_BIT_VPP) != 0 ) {
-      DEBUG((EFI_D_ERROR,"NorFlashReadStatusRegister: VPP Range Error\n"));
-    } else if ( (StatusRegister & (P30_SR_BIT_ERASE | P30_SR_BIT_PROGRAM) ) != 0 ) {
-      DEBUG((EFI_D_ERROR,"NorFlashReadStatusRegister: Command Sequence Error\n"));
-    } else if ( (StatusRegister & P30_SR_BIT_PROGRAM) != 0 ) {
-      DEBUG((EFI_D_ERROR,"NorFlashReadStatusRegister: Program Error\n"));
-    } else if ( (StatusRegister & P30_SR_BIT_BLOCK_LOCKED) != 0 ) {
-      DEBUG((EFI_D_ERROR,"NorFlashReadStatusRegister: Device Protect Error\n"));
-    } else {\r
-      DEBUG((EFI_D_ERROR,"NorFlashReadStatusRegister: Error (0x%X)\n",Status));\r
-    }
-
-    // If an error is detected we must clear the Status Register
-    SEND_NOR_COMMAND( SR_Address, 0, P30_CMD_CLEAR_STATUS_REGISTER );
-    Status = EFI_DEVICE_ERROR;
-  }
-
-  SEND_NOR_COMMAND( SR_Address, 0, P30_CMD_READ_ARRAY );
-
-  return Status;
-}
-
-
-BOOLEAN
-NorFlashBlockIsLocked(
-  IN UINTN BlockAddress
-  )
-{
-  volatile UINT32       *pReadData;
-  UINT32                LockStatus;
-  BOOLEAN               BlockIsLocked = TRUE;
-
-  // Prepare the read address
-  pReadData = (UINT32 *) CREATE_NOR_ADDRESS( BlockAddress, 2 );
-
-  // Send command for reading device id
-  SEND_NOR_COMMAND( BlockAddress, 2, P30_CMD_READ_DEVICE_ID );
-
-  // Read block lock status
-  LockStatus = *pReadData;
-
-  // Decode block lock status
-  LockStatus = FOLD_32BIT_INTO_16BIT(LockStatus);
-
-  if( (LockStatus & 0x2) != 0 ) {
-    DEBUG((EFI_D_ERROR, "UnlockSingleBlock: WARNING: Block LOCKED DOWN\n"));
-  }
-
-  if( (LockStatus & 0x1) == 0 ) {
-    // This means the block is unlocked
-    DEBUG((DEBUG_BLKIO, "UnlockSingleBlock: Block 0x%08x unlocked\n", BlockAddress ));
-    BlockIsLocked = FALSE;
-  }
-
-  return BlockIsLocked;
-}
-
-
-EFI_STATUS
-NorFlashUnlockSingleBlock(
-  IN UINTN  BlockAddress
-  )
-{
-  EFI_STATUS            Status = EFI_SUCCESS;
-
-  // Raise the Task Priority Level to TPL_NOTIFY to serialise all its operations
-  // and to protect shared data structures.
-
-  //while( NorFlashBlockIsLocked( BlockAddress ) )
-  {
-    // Request a lock setup
-    SEND_NOR_COMMAND( BlockAddress, 0, P30_CMD_LOCK_BLOCK_SETUP );
-
-    // Request an unlock
-    SEND_NOR_COMMAND( BlockAddress, 0, P30_CMD_UNLOCK_BLOCK );
-  }
-
-  // Put device back into Read Array mode
-  SEND_NOR_COMMAND( BlockAddress, 0, P30_CMD_READ_ARRAY );
-
-  DEBUG((DEBUG_BLKIO, "UnlockSingleBlock: BlockAddress=0x%08x, Exit Status = \"%r\".\n", BlockAddress, Status));
-
-  return Status;
-}
-
-
-EFI_STATUS
-NorFlashUnlockSingleBlockIfNecessary(
-  IN UINTN BlockAddress
-  )
-{
-  EFI_STATUS Status = EFI_SUCCESS;
-
-  if ( NorFlashBlockIsLocked( BlockAddress ) == TRUE ) {
-    Status = NorFlashUnlockSingleBlock( BlockAddress );
-  }
-
-  return Status;
-}
-
-
-/**
- * The following function presumes that the block has already been unlocked.
- **/
-EFI_STATUS
-NorFlashEraseSingleBlock(
-  IN UINTN BlockAddress
-  )
-{
-  EFI_STATUS            Status = EFI_SUCCESS;
-
-  // Request a block erase and then confirm it
-  SEND_NOR_COMMAND( BlockAddress, 0, P30_CMD_BLOCK_ERASE_SETUP );
-  SEND_NOR_COMMAND( BlockAddress, 0, P30_CMD_BLOCK_ERASE_CONFIRM );
-  // Wait until the status register gives us the all clear
-  Status = NorFlashReadStatusRegister( BlockAddress );
-
-  if (EFI_ERROR(Status)) {
-    DEBUG((DEBUG_BLKIO, "EraseSingleBlock(BlockAddress=0x%08x) = '%r'\n", BlockAddress, Status));
-  }
-  return Status;
-}
-
-/**
- * The following function presumes that the block has already been unlocked.
- **/
-EFI_STATUS
-NorFlashUnlockAndEraseSingleBlock(
-  IN  UINTN   BlockAddress
-  )
-{
-  EFI_STATUS   Status;
-
-  // Unlock the block if we have to
-  Status = NorFlashUnlockSingleBlockIfNecessary( BlockAddress );
-  if (!EFI_ERROR(Status)) {
-    Status = NorFlashEraseSingleBlock( BlockAddress );
-  }
-
-  return Status;
-}
-
-
-EFI_STATUS
-NorFlashWriteSingleWord (
-    IN  UINTN   WordAddress,
-    IN  UINT32  WriteData
-  )
-{
-  EFI_STATUS            Status;
-  volatile UINT32       *Data;
-
-  // Prepare the read address
-  Data = (UINT32 *)WordAddress;
-
-  // Request a write single word command
-  SEND_NOR_COMMAND( WordAddress, 0, P30_CMD_WORD_PROGRAM_SETUP );
-
-  // Store the word into NOR Flash;
-  *Data = WriteData;
-
-  // Wait for the write to complete and then check for any errors; i.e. check the Status Register
-  Status = NorFlashReadStatusRegister( WordAddress );
-
-  return Status;
-}
-
-/*
- * Writes data to the NOR Flash using the Buffered Programming method.
- *
- * The maximum size of the on-chip buffer is 32-words, because of hardware restrictions.
- * Therefore this function will only handle buffers up to 32 words or 128 bytes.
- * To deal with larger buffers, call this function again.
- *
- * This function presumes that both the TargetAddress and the TargetAddress+BufferSize
- * exist entirely within the NOR Flash. Therefore these conditions will not be checked here.
- *
- * In buffered programming, if the target address not at the beginning of a 32-bit word boundary,
- * then programming time is doubled and power consumption is increased.
- * Therefore, it is a requirement to align buffer writes to 32-bit word boundaries.
- * i.e. the last 4 bits of the target start address must be zero: 0x......00
- */
-EFI_STATUS
-NorFlashWriteBuffer (
-    IN  UINTN   TargetAddress,
-    IN  UINTN   BufferSizeInBytes,
-    IN  UINT32  *Buffer
-  )
-{
-  EFI_STATUS            Status;
-  UINTN                 BufferSizeInWords;
-  UINTN                 Count;
-  volatile UINT32       *Data;
-  UINTN                 WaitForBuffer   = MAX_BUFFERED_PROG_ITERATIONS;
-  BOOLEAN               BufferAvailable = FALSE;
-
-
-  // Check that the target address does not cross a 32-word boundary.
-  if ( (TargetAddress & BOUNDARY_OF_32_WORDS) != 0 ) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  // Check there are some data to program
-  if ( BufferSizeInBytes == 0 ) {
-    return EFI_BUFFER_TOO_SMALL;
-  }
-
-  // Check that the buffer size does not exceed the maximum hardware buffer size on chip.
-  if ( BufferSizeInBytes > P30_MAX_BUFFER_SIZE_IN_BYTES ) {
-    return EFI_BAD_BUFFER_SIZE;
-  }
-
-  // Check that the buffer size is a multiple of 32-bit words
-  if ( (BufferSizeInBytes % 4) != 0 ) {
-    return EFI_BAD_BUFFER_SIZE;
-  }
-
-  // Pre-programming conditions checked, now start the algorithm.
-
-  // Prepare the data destination address
-  Data = (UINT32 *)TargetAddress;
-
-  // Check the availability of the buffer
-  do {
-    // Issue the Buffered Program Setup command
-    SEND_NOR_COMMAND( TargetAddress, 0, P30_CMD_BUFFERED_PROGRAM_SETUP );
-
-    // Read back the status register bit#7 from the same address
-    if ( ((*Data) & P30_SR_BIT_WRITE) == P30_SR_BIT_WRITE ) {
-      BufferAvailable = TRUE;
-    }
-
-    // Update the loop counter
-    WaitForBuffer--;
-
-  } while (( WaitForBuffer > 0 ) && ( BufferAvailable == FALSE ));
-
-  // The buffer was not available for writing
-  if ( WaitForBuffer == 0 ) {
-    return EFI_DEVICE_ERROR;
-  }
-
-  // From now on we work in 32-bit words
-  BufferSizeInWords = BufferSizeInBytes / (UINTN)4;
-
-  // Write the word count, which is (buffer_size_in_words - 1),
-  // because word count 0 means one word.
-  SEND_NOR_COMMAND( TargetAddress, 0, (BufferSizeInWords - 1) );
-
-  // Write the data to the NOR Flash, advancing each address by 4 bytes
-  for( Count=0; Count<BufferSizeInWords; Count++, Data++, Buffer++ ) {
-    *Data = *Buffer;
-  }
-
-  // Issue the Buffered Program Confirm command, to start the programming operation
-  SEND_NOR_COMMAND( TargetAddress, 0, P30_CMD_BUFFERED_PROGRAM_CONFIRM );
-
-  // Wait for the write to complete and then check for any errors; i.e. check the Status Register
-  Status = NorFlashReadStatusRegister( TargetAddress );
-
-  return Status;
-}
-
-EFI_STATUS
-NorFlashWriteSingleBlock (
-    IN  UINTN     DeviceBaseAddress,
-    IN  EFI_LBA   Lba,
-    IN  UINT32    *DataBuffer,
-    IN  UINT32    BlockSizeInWords
-  )
-{
-  EFI_STATUS    Status = EFI_SUCCESS;
-  UINTN         WordAddress;
-  UINT32        WordIndex;
-  UINTN         BufferIndex;
-  UINTN         BlockAddress;
-  UINTN         BuffersInBlock;
-  UINTN         RemainingWords;
-
-  // Get the physical address of the block
-  BlockAddress = GET_NOR_BLOCK_ADDRESS(DeviceBaseAddress, Lba, BlockSizeInWords * 4);
-
-  Status = NorFlashUnlockAndEraseSingleBlock( BlockAddress );
-  if (EFI_ERROR(Status)) {
-    DEBUG((EFI_D_ERROR, "WriteSingleBlock: ERROR - Failed to Unlock and Erase the single block at 0x%X\n", BlockAddress));
-    return Status;
-  }
-
-  // To speed up the programming operation, NOR Flash is programmed using the Buffered Programming method.
-
-  // Start writing from the first address at the start of the block
-  WordAddress = BlockAddress;
-
-  // Check that the address starts at a 32-word boundary, i.e. last 7 bits must be zero
-  if ( (WordAddress & BOUNDARY_OF_32_WORDS) == 0x00 ) {
-
-    // First, break the entire block into buffer-sized chunks.
-    BuffersInBlock = (UINTN)BlockSizeInWords / P30_MAX_BUFFER_SIZE_IN_BYTES;
-
-    // Then feed each buffer chunk to the NOR Flash
-    for( BufferIndex=0;
-         BufferIndex < BuffersInBlock;
-         BufferIndex++, WordAddress += P30_MAX_BUFFER_SIZE_IN_BYTES, DataBuffer += P30_MAX_BUFFER_SIZE_IN_WORDS
-       ) {
-      Status = NorFlashWriteBuffer ( WordAddress, P30_MAX_BUFFER_SIZE_IN_BYTES, DataBuffer );
-      if (EFI_ERROR(Status)) {
-        goto EXIT;
-      }
-    }
-
-    // Finally, finish off any remaining words that are less than the maximum size of the buffer
-    RemainingWords = BlockSizeInWords % P30_MAX_BUFFER_SIZE_IN_WORDS;
-
-    if( RemainingWords != 0) {
-      Status = NorFlashWriteBuffer ( WordAddress, (RemainingWords * 4), DataBuffer );
-      if (EFI_ERROR(Status)) {
-        goto EXIT;
-      }
-    }
-
-  } else {
-    // For now, use the single word programming algorithm
-    // It is unlikely that the NOR Flash will exist in an address which falls within a 32 word boundary range,
-    // i.e. which ends in the range 0x......01 - 0x......7F.
-    for( WordIndex=0; WordIndex<BlockSizeInWords; WordIndex++, DataBuffer++, WordAddress = WordAddress + 4 ) {
-      Status = NorFlashWriteSingleWord( WordAddress, *DataBuffer );
-      if (EFI_ERROR(Status)) {
-        goto EXIT;
-      }
-    }
-  }
-
-  EXIT:
-  if (EFI_ERROR(Status)) {
-    DEBUG((EFI_D_ERROR, "NOR FLASH Programming [WriteSingleBlock] failed at address 0x%08x. Exit Status = \"%r\".\n", WordAddress, Status));
-  }
-  return Status;
-}
-
-
-EFI_STATUS
-NorFlashWriteBlocks (
-  IN  NOR_FLASH_INSTANCE *Instance,
-  IN EFI_LBA                Lba,
-  IN UINTN                  BufferSizeInBytes,
-  IN VOID                   *Buffer
-  )
-{
-  UINT32          *pWriteBuffer;
-  EFI_STATUS      Status = EFI_SUCCESS;
-  EFI_LBA         CurrentBlock;
-  UINT32          BlockSizeInWords;
-  UINT32          NumBlocks;
-  UINT32          BlockCount;
-  volatile UINT32 *VersatileExpress_SYS_FLASH;
-
-  // The buffer must be valid
-  if (Buffer == NULL) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  if( Instance->Media.ReadOnly == TRUE ) {
-    return EFI_WRITE_PROTECTED;
-  }
-
-  // We must have some bytes to read
-  DEBUG((DEBUG_BLKIO, "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_BLKIO, "NorFlashWriteBlocks: BlockSize in bytes =0x%x\n", Instance->Media.BlockSize ));
-  if ((BufferSizeInBytes % Instance->Media.BlockSize) != 0) {
-    return EFI_BAD_BUFFER_SIZE;
-  }
-
-  // All blocks must be within the device
-  NumBlocks = ((UINT32)BufferSizeInBytes) / Instance->Media.BlockSize ;
-
-  DEBUG((DEBUG_BLKIO, "NorFlashWriteBlocks: NumBlocks=%d, LastBlock=%ld, Lba=%ld.\n", NumBlocks, Instance->Media.LastBlock, Lba));
-
-  if ( ( Lba + NumBlocks ) > ( Instance->Media.LastBlock + 1 ) ) {
-    DEBUG((EFI_D_ERROR, "NorFlashWriteBlocks: ERROR - Write will exceed last block.\n"));
-    return EFI_INVALID_PARAMETER;
-  }
-
-  // Everything seems ok so far, so now we need to disable the platform-specific
-  // flash write protection for Versatile Express
-  VersatileExpress_SYS_FLASH = (UINT32 *)VE_REGISTER_SYS_FLASH_ADDR;
-  if( (*VersatileExpress_SYS_FLASH & 0x1) == 0 ) {
-    // Writing to NOR FLASH is disabled, so enable it
-    *VersatileExpress_SYS_FLASH = 0x1;
-    DEBUG((DEBUG_BLKIO, "NorFlashWriteBlocks: informational - Had to enable HSYS_FLASH flag.\n" ));
-  }
-
-  BlockSizeInWords = Instance->Media.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 = pWriteBuffer + BlockSizeInWords ) {
-
-    DEBUG((DEBUG_BLKIO, "NorFlashWriteBlocks: Writing block #%d\n", (UINTN)CurrentBlock ));
-
-    Status = NorFlashWriteSingleBlock( Instance->BaseAddress, CurrentBlock, pWriteBuffer, BlockSizeInWords );
-
-    if (EFI_ERROR(Status)) {
-      break;
-    }
-
-  }
-
-  DEBUG((DEBUG_BLKIO, "NorFlashWriteBlocks: Exit Status = \"%r\".\n", Status));
-  return Status;
-}
-
-
-EFI_STATUS
-NorFlashReadBlocks (
-  IN NOR_FLASH_INSTANCE   *Instance,
-  IN EFI_LBA                Lba,
-  IN UINTN                  BufferSizeInBytes,
-  OUT VOID                  *Buffer
-  )
-{
-  UINT32              NumBlocks;
-  UINTN               StartAddress;
-
-  // The buffer must be valid
-  if (Buffer == NULL) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  // We must have some bytes to read
-  DEBUG((DEBUG_BLKIO, "NorFlashReadBlocks: BufferSize=0x%x bytes.\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_BLKIO, "NorFlashReadBlocks: BlockSize=0x%x bytes.\n", Instance->Media.BlockSize ));
-  if ((BufferSizeInBytes % Instance->Media.BlockSize) != 0) {
-    return EFI_BAD_BUFFER_SIZE;
-  }
-
-  // All blocks must be within the device
-  NumBlocks = ((UINT32)BufferSizeInBytes) / Instance->Media.BlockSize ;
-
-  DEBUG((DEBUG_BLKIO, "NorFlashReadBlocks: NumBlocks=%d, LastBlock=%ld, Lba=%ld\n", NumBlocks, Instance->Media.LastBlock, Lba));
-
-  if ( ( Lba + NumBlocks ) > (Instance->Media.LastBlock + 1) ) {
-    DEBUG((EFI_D_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->BaseAddress,
-                                        Lba,
-                                        Instance->Media.BlockSize
-                                      );
-
-  // Put the device into Read Array mode
-  SEND_NOR_COMMAND( Instance->BaseAddress, 0, P30_CMD_READ_ARRAY );
-
-  // Readout the data
-  CopyMem(Buffer, (UINTN *)StartAddress, BufferSizeInBytes);
-
-  return EFI_SUCCESS;
-}
-
-
-EFI_STATUS
-NorFlashReset (
-  IN  NOR_FLASH_INSTANCE *Instance
-  )
-{
-  DEBUG((DEBUG_BLKIO, "NorFlashReset(BaseAddress=0x%08x)\n", Instance->BaseAddress));
-
-  // As there is no specific RESET to perform, ensure that the devices is in the default Read Array mode
-  SEND_NOR_COMMAND( Instance->BaseAddress, 0, P30_CMD_READ_ARRAY );
-
-  return EFI_SUCCESS;
-}
-
-
-
-EFI_STATUS
-EFIAPI
-NorFlashInitialise (
-  IN EFI_HANDLE         ImageHandle,
-  IN EFI_SYSTEM_TABLE   *SystemTable
-  )
-{
-  EFI_STATUS    Status = EFI_SUCCESS;
-  UINT32        Index;
-  UINTN NvStorageVariableBase = (UINTN) PcdGet32 (PcdFlashNvStorageVariableBase);
-
-  for (Index = 0; Index < NOR_FLASH_LAST_DEVICE; Index++) {
-    Status = NorFlashCreateInstance(
-      mNorFlashDescription[Index].BaseAddress,
-      mNorFlashDescription[Index].Size,
-      Index,
-      mNorFlashDescription[Index].BlockSize,
-      (mNorFlashDescription[Index].BaseAddress == NvStorageVariableBase),
-      &mNorFlashDescription[Index].Guid,
-      &mNorFlashInstances[Index]
-    );
-    if (EFI_ERROR(Status)) {
-      DEBUG((EFI_D_ERROR,"NorFlashInitialise: Fail to create instance for NorFlash[%d]\n",Index));
-    }
-  }
-
-  return Status;
-}
diff --git a/ArmPlatformPkg/ArmVExpressPkg/NorFlashDxe/NorFlashDxe.h b/ArmPlatformPkg/ArmVExpressPkg/NorFlashDxe/NorFlashDxe.h
deleted file mode 100644 (file)
index 7da9942..0000000
+++ /dev/null
@@ -1,327 +0,0 @@
-/** @file  NorFlashDxe.h
-
-  Copyright (c) 2010, ARM Ltd. All rights reserved.<BR>
-  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_DXE_H__
-#define __NOR_FLASH_DXE_H__
-
-
-#include <Base.h>
-#include <PiDxe.h>
-
-#include <Protocol/BlockIo.h>
-#include <Protocol/FirmwareVolumeBlock.h>
-
-#include <ArmPlatform.h>
-
-#define HIGH_16_BITS                              0xFFFF0000
-#define LOW_16_BITS                               0x0000FFFF
-#define LOW_8_BITS                                0x000000FF
-
-// Hardware addresses
-
-#define VE_SYSTEM_REGISTERS_OFFSET                0x00000000
-#define SYSTEM_REGISTER_SYS_FLASH                 0x0000004C
-
-#define VE_REGISTER_SYS_FLASH_ADDR                ( ARM_VE_BOARD_PERIPH_BASE + VE_SYSTEM_REGISTERS_OFFSET + SYSTEM_REGISTER_SYS_FLASH )
-
-// Device access macros
-// These are necessary because we use 2 x 16bit parts to make up 32bit data
-
-#define FOLD_32BIT_INTO_16BIT(value)              ( ( value >> 16 ) | ( value & LOW_16_BITS ) )
-
-#define GET_LOW_BYTE(value)                       ( value & LOW_8_BITS )
-#define GET_HIGH_BYTE(value)                      ( GET_LOW_BYTE( value >> 16 ) )
-
-// Each command must be sent simultaneously to both chips,
-// i.e. at the lower 16 bits AND at the higher 16 bits
-#define CREATE_NOR_ADDRESS(BaseAddr,OffsetAddr)   ( (volatile UINTN *)((BaseAddr) + ((OffsetAddr) << 2)) )
-#define CREATE_DUAL_CMD(Cmd)                      ( ( Cmd << 16) | ( Cmd & LOW_16_BITS) )
-#define SEND_NOR_COMMAND(BaseAddr,OffsetAddr,Cmd) ( *CREATE_NOR_ADDRESS(BaseAddr,OffsetAddr) = CREATE_DUAL_CMD(Cmd) )
-#define GET_NOR_BLOCK_ADDRESS(BaseAddr,Lba,LbaSize)( BaseAddr + (UINTN)(Lba * LbaSize) )
-
-// Status Register Bits
-#define P30_SR_BIT_WRITE                          0x00800080     /* Bit 7 */
-#define P30_SR_BIT_ERASE_SUSPEND                  0x00400040     /* Bit 6 */
-#define P30_SR_BIT_ERASE                          0x00200020     /* Bit 5 */
-#define P30_SR_BIT_PROGRAM                        0x00100010     /* Bit 4 */
-#define P30_SR_BIT_VPP                            0x00080008     /* Bit 3 */
-#define P30_SR_BIT_PROGRAM_SUSPEND                0x00040004     /* Bit 2 */
-#define P30_SR_BIT_BLOCK_LOCKED                   0x00020002     /* Bit 1 */
-#define P30_SR_BIT_BEFP                           0x00010001     /* Bit 0 */
-
-// Device Commands for Intel StrataFlash(R) Embedded Memory (P30) Family
-
-// On chip buffer size for buffered programming operations
-// There are 2 chips, each chip can buffer up to 32 (16-bit)words, and each word is 2 bytes.
-// Therefore the total size of the buffer is 2 x 32 x 2 = 128 bytes
-#define P30_MAX_BUFFER_SIZE_IN_BYTES              ((UINTN)128)
-#define P30_MAX_BUFFER_SIZE_IN_WORDS              (P30_MAX_BUFFER_SIZE_IN_BYTES/((UINTN)4))
-#define MAX_BUFFERED_PROG_ITERATIONS              10000000
-#define BOUNDARY_OF_32_WORDS                      0x7F
-
-// CFI Addresses
-#define P30_CFI_ADDR_QUERY_UNIQUE_QRY             0x10
-#define P30_CFI_ADDR_VENDOR_ID                    0x13
-
-// CFI Data
-#define CFI_QRY                                   0x00595251
-
-// READ Commands
-#define P30_CMD_READ_DEVICE_ID                    0x0090
-#define P30_CMD_READ_STATUS_REGISTER              0x0070
-#define P30_CMD_CLEAR_STATUS_REGISTER             0x0050
-#define P30_CMD_READ_ARRAY                        0x00FF
-#define P30_CMD_READ_CFI_QUERY                    0x0098
-
-// WRITE Commands
-#define P30_CMD_WORD_PROGRAM_SETUP                0x0040
-#define P30_CMD_ALTERNATE_WORD_PROGRAM_SETUP      0x0010
-#define P30_CMD_BUFFERED_PROGRAM_SETUP            0x00E8
-#define P30_CMD_BUFFERED_PROGRAM_CONFIRM          0x00D0
-#define P30_CMD_BEFP_SETUP                        0x0080
-#define P30_CMD_BEFP_CONFIRM                      0x00D0
-
-// ERASE Commands
-#define P30_CMD_BLOCK_ERASE_SETUP                 0x0020
-#define P30_CMD_BLOCK_ERASE_CONFIRM               0x00D0
-
-// SUSPEND Commands
-#define P30_CMD_PROGRAM_OR_ERASE_SUSPEND          0x00B0
-#define P30_CMD_SUSPEND_RESUME                    0x00D0
-
-// BLOCK LOCKING / UNLOCKING Commands
-#define P30_CMD_LOCK_BLOCK_SETUP                  0x0060
-#define P30_CMD_LOCK_BLOCK                        0x0001
-#define P30_CMD_UNLOCK_BLOCK                      0x00D0
-#define P30_CMD_LOCK_DOWN_BLOCK                   0x002F
-
-// PROTECTION Commands
-#define P30_CMD_PROGRAM_PROTECTION_REGISTER_SETUP 0x00C0
-
-// CONFIGURATION Commands
-#define P30_CMD_READ_CONFIGURATION_REGISTER_SETUP 0x0060
-#define P30_CMD_READ_CONFIGURATION_REGISTER       0x0003
-
-#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 {
-    UINTN                             BaseAddress;
-    UINTN                             Size;
-    UINTN                             BlockSize;
-    EFI_GUID                          Guid;
-} NOR_FLASH_DESCRIPTION;
-
-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                               BaseAddress;
-  UINTN                               Size;
-
-  EFI_BLOCK_IO_PROTOCOL               BlockIoProtocol;
-  EFI_BLOCK_IO_MEDIA                  Media;
-
-  BOOLEAN                             SupportFvb;
-  EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL FvbProtocol;
-
-  NOR_FLASH_DEVICE_PATH                      DevicePath;
-};
-
-EFI_STATUS
-EFIAPI
-NorFlashBlkIoInitialize (
-  IN NOR_FLASH_INSTANCE*      Instance
-  );
-
-EFI_STATUS
-NorFlashReadCfiData (
-  IN UINTN                    BaseAddress,
-  IN UINTN                    CFI_Offset,
-  IN UINT32                   NumberOfBytes,
-  OUT UINT32                  *Data
-);
-
-EFI_STATUS
-NorFlashWriteBuffer (
-    IN  UINTN                 TargetAddress,
-    IN  UINTN                 BufferSizeInBytes,
-    IN  UINT32                *Buffer
-);
-
-
-//
-// 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
-);
-
-
-//
-// 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,
-  ...
-);
-
-//
-// NorFlashDxe.c
-//
-
-EFI_STATUS
-NorFlashUnlockAndEraseSingleBlock(
-  IN  UINTN             BlockAddress
-);
-
-EFI_STATUS
-NorFlashWriteSingleBlock (
-  IN  UINTN             DeviceBaseAddress,
-  IN  EFI_LBA           Lba,
-  IN  UINT32            *pDataBuffer,
-  IN  UINT32            BlockSizeInWords
-);
-
-EFI_STATUS
-NorFlashWriteBlocks (
-  IN  NOR_FLASH_INSTANCE *Instance,
-  IN  EFI_LBA           Lba,
-  IN  UINTN             BufferSizeInBytes,
-  IN  VOID              *Buffer
-);
-
-EFI_STATUS
-NorFlashReadBlocks (
-  IN  NOR_FLASH_INSTANCE *Instance,
-  IN  EFI_LBA           Lba,
-  IN  UINTN             BufferSizeInBytes,
-  OUT VOID              *Buffer
-);
-
-EFI_STATUS
-NorFlashReset (
-  IN  NOR_FLASH_INSTANCE *Instance
-);
-
-#endif /* __NOR_FLASH_DXE_H__ */
diff --git a/ArmPlatformPkg/ArmVExpressPkg/NorFlashDxe/NorFlashDxe.inf b/ArmPlatformPkg/ArmVExpressPkg/NorFlashDxe/NorFlashDxe.inf
deleted file mode 100644 (file)
index 0ea1ded..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-#/** @file
-#  
-#  Component discription file for NorFlashDxe module
-#  
-#  Copyright (c) 2010, ARM Ltd. All rights reserved.<BR>
-#  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                    = 0x00010005
-  BASE_NAME                      = ArmVeNorFlashDxe
-  FILE_GUID                      = 93E34C7E-B50E-11DF-9223-2443DFD72085
-  MODULE_TYPE                    = DXE_DRIVER
-  VERSION_STRING                 = 1.0
-  ENTRY_POINT                    = NorFlashInitialise
-
-[Sources.common]
-  NorFlashDxe.c
-  NorFlashFvbDxe.c
-  NorFlashBlockIoDxe.c
-
-[Packages]
-  MdePkg/MdePkg.dec
-  MdeModulePkg/MdeModulePkg.dec
-  ArmPlatformPkg/ArmVExpressPkg/ArmVExpressPkg.dec
-
-[LibraryClasses]
-  IoLib
-  BaseLib
-  UefiLib
-  DebugLib
-  UefiDriverEntryPoint
-  UefiBootServicesTableLib
-
-[Guids]
-  gEfiSystemNvDataFvGuid
-  gEfiVariableGuid
-
-[Protocols]
-  gEfiBlockIoProtocolGuid
-  gEfiDevicePathProtocolGuid
-  gEfiFirmwareVolumeBlockProtocolGuid
-  
-[Pcd.common]
-  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize
-  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase
-
-
-[Depex]
-  #
-  # NorFlashDxe must be loaded before VariableRuntimeDxe in case empty flash needs populating with default values
-  # 
-  BEFORE gVariableRuntimeDxeFileGuid 
diff --git a/ArmPlatformPkg/ArmVExpressPkg/NorFlashDxe/NorFlashFvbDxe.c b/ArmPlatformPkg/ArmVExpressPkg/NorFlashDxe/NorFlashFvbDxe.c
deleted file mode 100644 (file)
index ffc2d5d..0000000
+++ /dev/null
@@ -1,790 +0,0 @@
-/*++ @file  NorFlashFvbDxe.c
-
- Copyright (c) 2011, ARM Ltd. All rights reserved.<BR>
- This program and the accompanying materials
- are licensed and made available under the terms and conditions of the BSD License
- which accompanies this distribution.  The full text of the license may be found at
- http://opensource.org/licenses/bsd-license.php
-
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
- --*/
-
-#include <PiDxe.h>
-
-#include <Library/PcdLib.h>
-#include <Library/BaseLib.h>
-#include <Library/UefiLib.h>
-#include <Library/DebugLib.h>
-#include <Library/BaseMemoryLib.h>
-#include <Library/MemoryAllocationLib.h>
-#include <Library/UefiBootServicesTableLib.h>
-
-#include <Guid/VariableFormat.h>
-#include <Guid/SystemNvDataGuid.h>
-
-#include "NorFlashDxe.h"
-
-
-///
-/// 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);
-  }
-
-  HeadersLength = sizeof(EFI_FIRMWARE_VOLUME_HEADER) + sizeof(EFI_FV_BLOCK_MAP_ENTRY) + sizeof(VARIABLE_STORE_HEADER);
-  Headers = AllocateZeroPool(HeadersLength);
-
-  //
-  // EFI_FIRMWARE_VOLUME_HEADER
-  //
-  FirmwareVolumeHeader = (EFI_FIRMWARE_VOLUME_HEADER*)Headers;
-  CopyGuid (&FirmwareVolumeHeader->FileSystemGuid, &gEfiSystemNvDataFvGuid);
-  FirmwareVolumeHeader->FvLength = Instance->Media.BlockSize * (Instance->Media.LastBlock + 1);
-  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;
-  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*)((UINT32)Headers + FirmwareVolumeHeader->HeaderLength);
-  CopyGuid (&VariableStoreHeader->Signature, &gEfiVariableGuid);
-  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;
-
-  FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER*)Instance->BaseAddress;
-
-  //
-  // 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      != Instance->Media.BlockSize * (Instance->Media.LastBlock + 1) )
-      ) {
-    DEBUG ((EFI_D_ERROR, "ValidateFvHeader: No Firmware Volume header present\n"));
-    return EFI_NOT_FOUND;
-  }
-
-  // Check the Firmware Volume Guid
-  if( CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiSystemNvDataFvGuid) == FALSE ) {
-    DEBUG ((EFI_D_ERROR, "ValidateFvHeader: Firmware Volume Guid non-compatible\n"));
-    return EFI_NOT_FOUND;
-  }
-
-  // Verify the header checksum
-  Checksum = CalculateSum16((UINT16*)FwVolHeader, FwVolHeader->HeaderLength);
-  if (Checksum != 0) {
-    DEBUG ((EFI_D_ERROR, "ValidateFvHeader: FV checksum is invalid (Checksum:0x%X)\n",Checksum));
-    return EFI_NOT_FOUND;
-  }
-
-  VariableStoreHeader = (VARIABLE_STORE_HEADER*)((UINT32)FwVolHeader + FwVolHeader->HeaderLength);
-
-  // Check the Variable Store Guid
-  if( CompareGuid (&VariableStoreHeader->Signature, &gEfiVariableGuid) == FALSE ) {
-    DEBUG ((EFI_D_ERROR, "ValidateFvHeader: Variable Store Guid non-compatible\n"));
-    return EFI_NOT_FOUND;
-  }
-
-  VariableStoreLength = PcdGet32 (PcdFlashNvStorageVariableSize) - FwVolHeader->HeaderLength;
-  if (VariableStoreHeader->Size != VariableStoreLength) {
-    DEBUG ((EFI_D_ERROR, "ValidateFvHeader: Variable Store Length does not match\n"));
-    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
-  )
-{
-  NOR_FLASH_INSTANCE *Instance;
-
-  Instance = INSTANCE_FROM_FVB_THIS(This);
-
-  DEBUG ((DEBUG_BLKIO, "FvbGetPhysicalAddress(BaseAddress=0x%08x)\n", Instance->BaseAddress));
-
-  ASSERT(Address != NULL);
-
-  *Address = Instance->BaseAddress;
-  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 ((EFI_D_ERROR, "FvbGetBlockSize: ERROR - Parameter LBA %ld is beyond the last Lba (%ld).\n", Lba, Instance->Media.LastBlock));
-    Status = EFI_INVALID_PARAMETER;
-  } else {
-    // This is easy because 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, "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.
- 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
-  )
-{
-  EFI_STATUS    Status;
-  EFI_STATUS    TempStatus;
-  UINTN         BlockSize;
-  UINT8         *BlockBuffer;
-  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", Lba, Offset, *NumBytes, Buffer));
-
-  if (!Instance->Initialized) {
-    Instance->Initialize(Instance);
-  }
-
-  Status = EFI_SUCCESS;
-  TempStatus = Status;
-
-  // 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.
-  // We need to check each variable individually because adding two large values together overflows.
-  if ( ( Offset               >= BlockSize ) ||
-       ( *NumBytes            >  BlockSize ) ||
-       ( (Offset + *NumBytes) >  BlockSize )    ) {
-    DEBUG ((EFI_D_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;
-  }
-
-  // FixMe: Allow an arbitrary number of bytes to be read out, not just a multiple of block size.
-
-  // Allocate runtime memory to read in the NOR Flash data. Variable Services are runtime.
-  BlockBuffer = AllocateRuntimePool(BlockSize);
-
-  // Check if the memory allocation was successful
-  if( BlockBuffer == NULL ) {
-    DEBUG ((EFI_D_ERROR, "FvbRead: ERROR - Could not allocate BlockBuffer @ 0x%08x.\n", BlockBuffer));
-    return EFI_DEVICE_ERROR;
-  }
-
-  // Read NOR Flash data into shadow buffer
-  TempStatus = NorFlashReadBlocks(Instance, Lba, BlockSize, BlockBuffer);
-  if (EFI_ERROR (TempStatus)) {
-    // Return one of the pre-approved error statuses
-    Status = EFI_DEVICE_ERROR;
-    goto FREE_MEMORY;
-  }
-
-  // Put the data at the appropriate location inside the buffer area
-  DEBUG ((DEBUG_BLKIO, "FvbRead: CopyMem( Dst=0x%08x, Src=0x%08x, Size=0x%x ).\n", Buffer, BlockBuffer + Offset, *NumBytes));
-
-  CopyMem(Buffer, BlockBuffer + Offset, *NumBytes);
-
-FREE_MEMORY:
-  FreePool(BlockBuffer);
-
-  DEBUG ((DEBUG_BLKIO, "FvbRead - end\n"));
-  return Status;
-}
-
-/**
- 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
-  )
-{
-  EFI_STATUS  Status;
-  EFI_STATUS  TempStatus;
-  UINTN       BlockSize;
-  UINT8       *BlockBuffer;
-  NOR_FLASH_INSTANCE *Instance;
-
-  Instance = INSTANCE_FROM_FVB_THIS(This);
-
-  if (!Instance->Initialized) {
-    Instance->Initialize(Instance);
-  }
-
-  DEBUG ((DEBUG_BLKIO, "FvbWrite(Parameters: Lba=%ld, Offset=0x%x, *NumBytes=0x%x, Buffer @ 0x%08x)\n", Lba, Offset, *NumBytes, Buffer));
-
-  Status = EFI_SUCCESS;
-  TempStatus = Status;
-
-  // Detect WriteDisabled state
-  if (Instance->Media.ReadOnly == TRUE) {
-    DEBUG ((EFI_D_ERROR, "FvbWrite: 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;
-
-  // 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 ((EFI_D_ERROR, "FvbWrite: 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 ((EFI_D_ERROR, "FvbWrite: ERROR - EFI_BAD_BUFFER_SIZE: (Offset=0x%x + NumBytes=0x%x) > BlockSize=0x%x\n", Offset, *NumBytes, BlockSize ));
-    return EFI_BAD_BUFFER_SIZE;
-  }
-
-  // Allocate runtime memory to read in the NOR Flash data.
-  // Since the intention is to use this with Variable Services and since these are runtime,
-  // allocate the memory from the runtime pool.
-  BlockBuffer = AllocateRuntimePool(BlockSize);
-
-  // Check we did get some memory
-  if( BlockBuffer == NULL ) {
-    DEBUG ((EFI_D_ERROR, "FvbWrite: ERROR - Can not allocate BlockBuffer @ 0x%08x.\n", BlockBuffer));
-    return EFI_DEVICE_ERROR;
-  }
-
-  // Read NOR Flash data into shadow buffer
-  TempStatus = NorFlashReadBlocks(Instance, Lba, BlockSize, BlockBuffer);
-  if (EFI_ERROR (TempStatus)) {
-    // Return one of the pre-approved error statuses
-    Status = EFI_DEVICE_ERROR;
-    goto FREE_MEMORY;
-  }
-
-  // Put the data at the appropriate location inside the buffer area
-  CopyMem((BlockBuffer + Offset), Buffer, *NumBytes);
-
-  // Write the modified buffer back to the NorFlash
-  Status = NorFlashWriteBlocks(Instance, Lba, BlockSize, BlockBuffer);
-  if (EFI_ERROR (TempStatus)) {
-    // Return one of the pre-approved error statuses
-    Status = EFI_DEVICE_ERROR;
-    goto FREE_MEMORY;
-  }
-
-FREE_MEMORY:
-  FreePool(BlockBuffer);
-  return Status;
-}
-
-/**
- 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 ((EFI_D_ERROR, "FvbEraseBlocks: ERROR - Device is in WriteDisabled state.\n"));
-    return EFI_ACCESS_DENIED;
-  }
-
-  // Before erasing, check the entire list of parameters to ensure all specified blocks are valid
-
-  VA_START (args, This);
-
-  do {
-
-    // Get the Lba from which we start erasing
-    StartingLba = VA_ARG (args, EFI_LBA);
-
-    // Have we reached the end of the list?
-    if (StartingLba == EFI_LBA_LIST_TERMINATOR) {
-      //Exit the while loop
-      break;
-    }
-
-    // How many Lba blocks are we requested to erase?
-    NumOfLba = VA_ARG (args, UINT32);
-
-    // All blocks must be within range
-    DEBUG ((DEBUG_BLKIO, "FvbEraseBlocks: Check if: ( StartingLba=%ld + NumOfLba=%d - 1 ) > LastBlock=%ld.\n", StartingLba, NumOfLba, Instance->Media.LastBlock));
-    if ((NumOfLba == 0) || ((StartingLba + NumOfLba - 1) > Instance->Media.LastBlock)) {
-      VA_END (args);
-      DEBUG ((DEBUG_BLKIO, "FvbEraseBlocks: Check if: ( StartingLba=%ld + NumOfLba=%d - 1 ) > LastBlock=%ld.\n", StartingLba, NumOfLba, Instance->Media.LastBlock));
-      DEBUG ((EFI_D_ERROR, "FvbEraseBlocks: ERROR - Lba range goes past the last Lba.\n"));
-      Status = EFI_INVALID_PARAMETER;
-      goto EXIT;
-    }
-
-  } while (TRUE);
-
-  VA_END (args);
-
-  // To get here, all must be ok, so start erasing
-
-  VA_START (args, This);
-
-  do {
-
-    // Get the Lba from which we start erasing
-    StartingLba = VA_ARG (args, EFI_LBA);
-
-    // Have we reached the end of the list?
-    if (StartingLba == EFI_LBA_LIST_TERMINATOR) {
-      // Exit the while loop
-      break;
-    }
-
-    // How many Lba blocks are we requested to erase?
-    NumOfLba = VA_ARG (args, UINT32);
-
-    // Go through each one and erase it
-    while (NumOfLba > 0) {
-
-      // Get the physical address of Lba to erase
-      BlockAddress = GET_NOR_BLOCK_ADDRESS (
-          Instance->BaseAddress,
-          StartingLba,
-          Instance->Media.BlockSize
-      );
-
-      // Erase it
-      DEBUG ((DEBUG_BLKIO, "FvbEraseBlocks: Erasing Lba=%ld @ 0x%08x.\n", StartingLba, BlockAddress));
-      Status = NorFlashUnlockAndEraseSingleBlock (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;
-}
-
-EFI_STATUS
-EFIAPI
-NorFlashFvbInitialize (
-  IN NOR_FLASH_INSTANCE* Instance
-  ) {
-  EFI_STATUS Status;
-
-  DEBUG((DEBUG_BLKIO,"NorFlashFvbInitialize\n"));
-
-  Status = NorFlashBlkIoInitialize(Instance);
-  if (EFI_ERROR(Status)) {
-    DEBUG((EFI_D_ERROR,"NorFlashFvbInitialize: ERROR - Failed to initialize FVB\n"));
-    return Status;
-  }
-  Instance->Initialized = TRUE;
-
-  // Determine if there is a valid header at the beginning of the NorFlash
-  Status = ValidateFvHeader (Instance);
-  if (EFI_ERROR(Status)) {
-    // There is no valid header, so time to install one.
-    DEBUG((EFI_D_ERROR,"NorFlashFvbInitialize: ERROR - The FVB Header is not valid. Installing a correct one for this volume.\n"));
-
-    // Erase all the NorFlash that is reserved for variable storage
-    Status = FvbEraseBlocks ( &Instance->FvbProtocol, (EFI_LBA)0, (UINT32)(Instance->Media.LastBlock + 1), EFI_LBA_LIST_TERMINATOR );
-    if (EFI_ERROR(Status)) {
-      return Status;
-    }
-
-    // Install all appropriate headers
-    InitializeFvAndVariableStoreHeaders ( Instance );
-    if (EFI_ERROR(Status)) {
-      return Status;
-    }
-  }
-
-  return Status;
-}
diff --git a/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashBlockIoDxe.c b/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashBlockIoDxe.c
new file mode 100644 (file)
index 0000000..17a5369
--- /dev/null
@@ -0,0 +1,159 @@
+/** @file  NorFlashBlockIoDxe.c
+
+  Copyright (c) 2011, ARM Ltd. All rights reserved.<BR>
+  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/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include "NorFlashDxe.h"
+
+EFI_STATUS
+EFIAPI
+NorFlashBlkIoInitialize (
+  IN NOR_FLASH_INSTANCE* Instance
+  )
+{
+  UINT32                Reply;
+  EFI_STATUS            Status = EFI_SUCCESS;
+
+  DEBUG((DEBUG_BLKIO,"NorFlashBlkIoInitialize()\n"));
+
+  //
+  // Verify that there is a physical hardware device where we expect it to be.
+  //
+
+  // Read a specific CFI query that returns back "QRY"
+  // This ensures that there is really a device present there
+  SEND_NOR_COMMAND (Instance->BaseAddress, 0, P30_CMD_READ_CFI_QUERY);
+
+  // Read CFI 'QRY' data
+  Status = NorFlashReadCfiData (Instance->BaseAddress, P30_CFI_ADDR_QUERY_UNIQUE_QRY, 3, &Reply);
+  if (EFI_ERROR(Status)) {
+    return Status;
+  }
+
+  if (Reply != CFI_QRY) {
+    DEBUG((EFI_D_ERROR, "NorFlashBlkIoInitialize: CFI QRY=0x%x (expected 0x595251)\n", Reply));
+    return EFI_DEVICE_ERROR;
+  }
+
+  // Reset the device
+  Status = NorFlashBlockIoReset (&Instance->BlockIoProtocol, FALSE);
+  if (EFI_ERROR(Status)) {
+    return Status;
+  }
+
+  Instance->Initialized = TRUE;
+  return EFI_SUCCESS;
+}
+
+
+//
+// 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_BLKIO, "NorFlashBlockIoReset(MediaId=0x%x)\n", This->Media->MediaId));
+
+  return NorFlashReset(Instance);
+}
+
+//
+// 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;
+
+  Instance = INSTANCE_FROM_BLKIO_THIS(This);
+
+  DEBUG ((DEBUG_BLKIO, "NorFlashBlockIoReadBlocks(MediaId=0x%x, Lba=%ld, BufferSize=0x%x bytes (%d kB), BufferPtr @ 0x%08x)\n", MediaId, Lba, BufferSizeInBytes, Buffer));
+
+  if( !This->Media->MediaPresent ) {
+    Status = EFI_NO_MEDIA;
+  } else if( This->Media->MediaId != MediaId ) {
+    Status = EFI_MEDIA_CHANGED;
+  } else {
+    Status = NorFlashReadBlocks(Instance,Lba,BufferSizeInBytes,Buffer);
+  }
+
+  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;
+
+  Instance = INSTANCE_FROM_BLKIO_THIS(This);
+
+  DEBUG ((DEBUG_BLKIO, "NorFlashBlockIoWriteBlocks(MediaId=0x%x, Lba=%ld, BufferSize=0x%x bytes (%d kB), BufferPtr @ 0x%08x)\n", MediaId, Lba, BufferSizeInBytes, Buffer));
+
+  if( !This->Media->MediaPresent ) {
+    Status = EFI_NO_MEDIA;
+  } else if( This->Media->MediaId != MediaId ) {
+    Status = EFI_MEDIA_CHANGED;
+  } else if( This->Media->ReadOnly ) {
+    Status = EFI_WRITE_PROTECTED;
+  } else {
+    Status = NorFlashWriteBlocks(Instance,Lba,BufferSizeInBytes,Buffer);
+  }
+
+  return Status;
+}
+
+//
+// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.FlushBlocks
+//
+EFI_STATUS
+EFIAPI
+NorFlashBlockIoFlushBlocks (
+  IN EFI_BLOCK_IO_PROTOCOL  *This
+  )
+{
+  // No Flush required for the NOR Flash driver
+  // because cache operations are not permitted.
+
+  DEBUG ((DEBUG_BLKIO, "NorFlashBlockIoFlushBlocks: Function NOT IMPLEMENTED (not required).\n"));
+
+  // Nothing to do so just return without error
+  return EFI_SUCCESS;
+}
diff --git a/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.c b/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.c
new file mode 100644 (file)
index 0000000..a3d5bf6
--- /dev/null
@@ -0,0 +1,770 @@
+/** @file  NorFlashDxe.c
+
+  Copyright (c) 2011, ARM Ltd. All rights reserved.<BR>
+  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/UefiLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/PcdLib.h>
+
+#include "NorFlashDxe.h"
+
+
+//
+// Global variable declarations
+//
+NOR_FLASH_INSTANCE **mNorFlashInstances;
+
+NOR_FLASH_INSTANCE  mNorFlashInstanceTemplate = {
+  NOR_FLASH_SIGNATURE, // Signature
+  NULL, // Handle ... NEED TO BE FILLED
+
+  FALSE, // Initialized
+  NULL, // Initialize
+
+  0, // BaseAddress ... NEED TO BE FILLED
+  0, // Size ... NEED TO BE FILLED
+  0, // StartLba
+
+  {\r
+    EFI_BLOCK_IO_PROTOCOL_REVISION2, // Revision\r
+    NULL, // Media ... NEED TO BE FILLED\r
+    NorFlashBlockIoReset, // Reset;\r
+    NorFlashBlockIoReadBlocks,          // ReadBlocks
+    NorFlashBlockIoWriteBlocks,         // WriteBlocks
+    NorFlashBlockIoFlushBlocks          // FlushBlocks\r
+  }, // BlockIoProtocol
+
+  {\r
+    0, // MediaId ... NEED TO BE FILLED\r
+    FALSE, // RemovableMedia\r
+    TRUE, // MediaPresent\r
+    FALSE, // LogicalPartition\r
+    FALSE, // ReadOnly\r
+    FALSE, // WriteCaching;\r
+    0, // BlockSize ... NEED TO BE FILLED\r
+    4, //  IoAlign\r
+    0, // LastBlock ... NEED TO BE FILLED\r
+    0, // LowestAlignedLba\r
+    1, // LogicalBlocksPerPhysicalBlock\r
+  }, //Media;
+
+  FALSE, // SupportFvb ... NEED TO BE FILLED
+  {\r
+    FvbGetAttributes, // GetAttributes
+    FvbSetAttributes, // SetAttributes
+    FvbGetPhysicalAddress,  // GetPhysicalAddress
+    FvbGetBlockSize,  // GetBlockSize
+    FvbRead,  // Read
+    FvbWrite, // Write
+    FvbEraseBlocks, // EraseBlocks\r
+    NULL, //ParentHandle\r
+  }, //  FvbProtoccol;
+
+  {
+    {
+      {
+        HARDWARE_DEVICE_PATH,
+        HW_VENDOR_DP,
+        (UINT8)( sizeof(VENDOR_DEVICE_PATH)      ),
+        (UINT8)((sizeof(VENDOR_DEVICE_PATH)) >> 8),
+      },
+      { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, // GUID ... NEED TO BE FILLED
+    },
+    {
+      END_DEVICE_PATH_TYPE,
+      END_ENTIRE_DEVICE_PATH_SUBTYPE,
+      sizeof (EFI_DEVICE_PATH_PROTOCOL),
+      0
+    }
+    } // DevicePath
+};
+
+EFI_STATUS
+NorFlashCreateInstance (
+  IN UINTN                  NorFlashBase,
+  IN UINTN                  NorFlashSize,
+  IN UINT32                 MediaId,
+  IN UINT32                 BlockSize,
+  IN BOOLEAN                SupportFvb,
+  IN CONST GUID             *NorFlashGuid,
+  OUT NOR_FLASH_INSTANCE**  NorFlashInstance
+  )
+{
+  EFI_STATUS Status;
+  NOR_FLASH_INSTANCE* Instance;
+
+  ASSERT(NorFlashInstance != NULL);
+
+  Instance = AllocateCopyPool (sizeof(NOR_FLASH_INSTANCE),&mNorFlashInstanceTemplate);
+  if (Instance == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  Instance->BaseAddress = NorFlashBase;
+  Instance->Size = NorFlashSize;
+
+  Instance->BlockIoProtocol.Media = &Instance->Media;
+  Instance->Media.MediaId = MediaId;
+  Instance->Media.BlockSize = BlockSize;
+  Instance->Media.LastBlock = (NorFlashSize / BlockSize)-1;
+\r
+  CopyGuid (&Instance->DevicePath.Vendor.Guid,NorFlashGuid);\r
+
+  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);
+      return Status;
+    }
+  } else {
+    Instance->Initialize = NorFlashBlkIoInitialize;
+
+    Status = gBS->InstallMultipleProtocolInterfaces (
+                    &Instance->Handle,
+                    &gEfiDevicePathProtocolGuid, &Instance->DevicePath,
+                    &gEfiBlockIoProtocolGuid,  &Instance->BlockIoProtocol,
+                    NULL
+                    );
+    if (EFI_ERROR(Status)) {
+      FreePool(Instance);
+      return Status;
+    }
+  }
+\r
+  *NorFlashInstance = Instance;\r
+  return Status;\r
+}
+
+EFI_STATUS
+NorFlashReadCfiData (
+  IN UINTN   BaseAddress,
+  IN UINTN   CfiOffset,
+  IN UINT32  NumberOfBytes,
+  OUT UINT32 *Data
+  )
+{
+  UINT32          CurrentByte;
+  UINTN           ReadAddress;
+  UINT32          ReadData;
+  UINT32          Byte1;
+  UINT32          Byte2;
+  UINT32          CombinedData = 0;
+  EFI_STATUS      Status = EFI_SUCCESS;
+
+
+  if (NumberOfBytes > 4) {
+    // Using 32 bit variable so can only read 4 bytes
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // First combine the base address with the offset address to create an absolute read address.
+  // However, because we are in little endian, read from the last address down to the first
+  ReadAddress = CREATE_NOR_ADDRESS (BaseAddress, CfiOffset) + (NumberOfBytes - 1) * sizeof(UINT32);
+
+  // Although each read returns 32 bits, because of the NOR Flash structure,
+  // each 16 bits (16 MSB and 16 LSB) come from two different chips.
+  // When in CFI mode, each chip read returns valid data in only the 8 LSBits;
+  // the 8 MSBits are invalid and can be ignored.
+  // Therefore, each read address returns one byte from each chip.
+  //
+  // Also note: As we are in little endian notation and we are reading
+  // bytes from incremental addresses, we should assemble them in little endian order.
+  for (CurrentByte=0; CurrentByte<NumberOfBytes; CurrentByte++) {
+    // Read the bytes from the two chips
+    ReadData = MmioRead32(ReadAddress);
+
+    // Check the data validity:
+    // The 'Dual Data' function means that
+    // each chip should return identical data.
+    // If that is not the case then we have a problem.
+    Byte1 = GET_LOW_BYTE (ReadData);
+    Byte2 = GET_HIGH_BYTE(ReadData);
+
+    if(Byte1 != Byte2) {
+      // The two bytes should have been identical
+      return EFI_DEVICE_ERROR;
+    } else {
+      // Each successive iteration of the 'for' loop reads a lower address.
+      // As we read lower addresses and as we use little endian,
+      // we read lower significance bytes. So combine them in the correct order.
+      CombinedData = (CombinedData << 8) | Byte1;
+
+      // Decrement down to the next address
+      ReadAddress -= sizeof(UINT32);
+    }
+  }
+
+  *Data = CombinedData;
+
+  return Status;
+}
+
+EFI_STATUS
+NorFlashReadStatusRegister (
+  IN UINTN SR_Address
+  )
+{
+  volatile UINT32       *pStatusRegister;
+  UINT32                StatusRegister;
+  UINT32                ErrorMask;
+  EFI_STATUS            Status = EFI_SUCCESS;
+
+  // Prepare the read address
+  pStatusRegister = (UINT32 *) SR_Address;
+
+  do {
+    // Prepare to read the status register
+    SEND_NOR_COMMAND (SR_Address, 0, P30_CMD_READ_STATUS_REGISTER);
+    // Snapshot the status register
+    StatusRegister = *pStatusRegister;
+  }
+  // The chip is busy while the WRITE bit is not asserted
+  while ((StatusRegister & P30_SR_BIT_WRITE) != P30_SR_BIT_WRITE);
+
+
+  // Perform a full status check:
+  // Mask the relevant bits of Status Register.
+  // Everything should be zero, if not, we have a problem
+
+  // Prepare the Error Mask by setting bits 5, 4, 3, 1
+  ErrorMask = P30_SR_BIT_ERASE | P30_SR_BIT_PROGRAM | P30_SR_BIT_VPP | P30_SR_BIT_BLOCK_LOCKED ;
+
+  if ( (StatusRegister & ErrorMask) != 0 ) {
+    if ( (StatusRegister & P30_SR_BIT_VPP) != 0 ) {
+      DEBUG((EFI_D_ERROR,"NorFlashReadStatusRegister: VPP Range Error\n"));
+    } else if ( (StatusRegister & (P30_SR_BIT_ERASE | P30_SR_BIT_PROGRAM) ) != 0 ) {
+      DEBUG((EFI_D_ERROR,"NorFlashReadStatusRegister: Command Sequence Error\n"));
+    } else if ( (StatusRegister & P30_SR_BIT_PROGRAM) != 0 ) {
+      DEBUG((EFI_D_ERROR,"NorFlashReadStatusRegister: Program Error\n"));
+    } else if ( (StatusRegister & P30_SR_BIT_BLOCK_LOCKED) != 0 ) {
+      DEBUG((EFI_D_ERROR,"NorFlashReadStatusRegister: Device Protect Error\n"));
+    } else {\r
+      DEBUG((EFI_D_ERROR,"NorFlashReadStatusRegister: Error (0x%X)\n",Status));\r
+    }
+
+    // If an error is detected we must clear the Status Register
+    SEND_NOR_COMMAND(SR_Address, 0, P30_CMD_CLEAR_STATUS_REGISTER);
+    Status = EFI_DEVICE_ERROR;
+  }
+
+  SEND_NOR_COMMAND(SR_Address, 0, P30_CMD_READ_ARRAY);
+
+  return Status;
+}
+
+
+BOOLEAN
+NorFlashBlockIsLocked (
+  IN UINTN BlockAddress
+  )
+{
+  UINT32                LockStatus;
+  BOOLEAN               BlockIsLocked = TRUE;
+
+  // Send command for reading device id
+  SEND_NOR_COMMAND (BlockAddress, 2, P30_CMD_READ_DEVICE_ID);
+
+  // Read block lock status
+  LockStatus = MmioRead32 (CREATE_NOR_ADDRESS( BlockAddress, 2 ));
+
+  // Decode block lock status
+  LockStatus = FOLD_32BIT_INTO_16BIT(LockStatus);
+
+  if((LockStatus & 0x2) != 0) {
+    DEBUG((EFI_D_ERROR, "UnlockSingleBlock: WARNING: Block LOCKED DOWN\n"));
+  }
+
+  if((LockStatus & 0x1) == 0) {
+    // This means the block is unlocked
+    DEBUG((DEBUG_BLKIO, "UnlockSingleBlock: Block 0x%08x unlocked\n", BlockAddress ));
+    BlockIsLocked = FALSE;
+  }
+
+  return BlockIsLocked;
+}
+
+
+EFI_STATUS
+NorFlashUnlockSingleBlock (
+  IN UINTN  BlockAddress
+  )
+{
+  EFI_STATUS            Status = EFI_SUCCESS;
+
+  // Raise the Task Priority Level to TPL_NOTIFY to serialise all its operations
+  // and to protect shared data structures.
+
+  // Request a lock setup
+  SEND_NOR_COMMAND(BlockAddress, 0, P30_CMD_LOCK_BLOCK_SETUP);
+
+  // Request an unlock
+  SEND_NOR_COMMAND(BlockAddress, 0, P30_CMD_UNLOCK_BLOCK);
+
+  // Put device back into Read Array mode
+  SEND_NOR_COMMAND(BlockAddress, 0, P30_CMD_READ_ARRAY);
+
+  DEBUG((DEBUG_BLKIO, "UnlockSingleBlock: BlockAddress=0x%08x, Exit Status = \"%r\".\n", BlockAddress, Status));
+
+  return Status;
+}
+
+
+EFI_STATUS
+NorFlashUnlockSingleBlockIfNecessary (
+  IN UINTN BlockAddress
+  )
+{
+  EFI_STATUS Status = EFI_SUCCESS;
+
+  if ( NorFlashBlockIsLocked(BlockAddress) == TRUE ) {
+    Status = NorFlashUnlockSingleBlock(BlockAddress);
+  }
+
+  return Status;
+}
+
+
+/**
+ * The following function presumes that the block has already been unlocked.
+ **/
+EFI_STATUS
+NorFlashEraseSingleBlock (
+  IN UINTN BlockAddress
+  )
+{
+  EFI_STATUS            Status = EFI_SUCCESS;
+
+  // Request a block erase and then confirm it
+  SEND_NOR_COMMAND (BlockAddress, 0, P30_CMD_BLOCK_ERASE_SETUP);
+  SEND_NOR_COMMAND (BlockAddress, 0, P30_CMD_BLOCK_ERASE_CONFIRM);
+  // Wait until the status register gives us the all clear
+  Status = NorFlashReadStatusRegister( BlockAddress );
+
+  if (EFI_ERROR(Status)) {
+    DEBUG((DEBUG_BLKIO, "EraseSingleBlock(BlockAddress=0x%08x) = '%r'\n", BlockAddress, Status));
+  }
+  return Status;
+}
+
+/**
+ * The following function presumes that the block has already been unlocked.
+ **/
+EFI_STATUS
+NorFlashUnlockAndEraseSingleBlock (
+  IN  UINTN   BlockAddress
+  )
+{
+  EFI_STATUS   Status;
+
+  // Unlock the block if we have to
+  Status = NorFlashUnlockSingleBlockIfNecessary (BlockAddress);
+  if (!EFI_ERROR(Status)) {
+    Status = NorFlashEraseSingleBlock(BlockAddress);
+  }
+
+  return Status;
+}
+
+
+EFI_STATUS
+NorFlashWriteSingleWord (
+  IN  UINTN   WordAddress,
+  IN  UINT32  WriteData
+  )
+{
+  EFI_STATUS            Status;
+  volatile UINT32       *Data;
+
+  // Prepare the read address
+  Data = (UINT32 *)WordAddress;
+
+  // Request a write single word command
+  SEND_NOR_COMMAND( WordAddress, 0, P30_CMD_WORD_PROGRAM_SETUP );
+
+  // Store the word into NOR Flash;
+  *Data = WriteData;
+
+  // Wait for the write to complete and then check for any errors; i.e. check the Status Register
+  Status = NorFlashReadStatusRegister( WordAddress );
+
+  return Status;
+}
+
+/*
+ * Writes data to the NOR Flash using the Buffered Programming method.
+ *
+ * The maximum size of the on-chip buffer is 32-words, because of hardware restrictions.
+ * Therefore this function will only handle buffers up to 32 words or 128 bytes.
+ * To deal with larger buffers, call this function again.
+ *
+ * This function presumes that both the TargetAddress and the TargetAddress+BufferSize
+ * exist entirely within the NOR Flash. Therefore these conditions will not be checked here.
+ *
+ * In buffered programming, if the target address not at the beginning of a 32-bit word boundary,
+ * then programming time is doubled and power consumption is increased.
+ * Therefore, it is a requirement to align buffer writes to 32-bit word boundaries.
+ * i.e. the last 4 bits of the target start address must be zero: 0x......00
+ */
+EFI_STATUS
+NorFlashWriteBuffer (
+  IN  UINTN   TargetAddress,
+  IN  UINTN   BufferSizeInBytes,
+  IN  UINT32  *Buffer
+  )
+{
+  EFI_STATUS            Status;
+  UINTN                 BufferSizeInWords;
+  UINTN                 Count;
+  volatile UINT32       *Data;
+  UINTN                 WaitForBuffer   = MAX_BUFFERED_PROG_ITERATIONS;
+  BOOLEAN               BufferAvailable = FALSE;
+
+
+  // Check that the target address does not cross a 32-word boundary.
+  if ( (TargetAddress & BOUNDARY_OF_32_WORDS) != 0 ) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // Check there are some data to program
+  if ( BufferSizeInBytes == 0 ) {
+    return EFI_BUFFER_TOO_SMALL;
+  }
+
+  // Check that the buffer size does not exceed the maximum hardware buffer size on chip.
+  if ( BufferSizeInBytes > P30_MAX_BUFFER_SIZE_IN_BYTES ) {
+    return EFI_BAD_BUFFER_SIZE;
+  }
+
+  // Check that the buffer size is a multiple of 32-bit words
+  if ( (BufferSizeInBytes % 4) != 0 ) {
+    return EFI_BAD_BUFFER_SIZE;
+  }
+
+  // Pre-programming conditions checked, now start the algorithm.
+
+  // Prepare the data destination address
+  Data = (UINT32 *)TargetAddress;
+
+  // Check the availability of the buffer
+  do {
+    // Issue the Buffered Program Setup command
+    SEND_NOR_COMMAND( TargetAddress, 0, P30_CMD_BUFFERED_PROGRAM_SETUP );
+
+    // Read back the status register bit#7 from the same address
+    if ( ((*Data) & P30_SR_BIT_WRITE) == P30_SR_BIT_WRITE ) {
+      BufferAvailable = TRUE;
+    }
+
+    // Update the loop counter
+    WaitForBuffer--;
+
+  } while (( WaitForBuffer > 0 ) && ( BufferAvailable == FALSE ));
+
+  // The buffer was not available for writing
+  if ( WaitForBuffer == 0 ) {
+    return EFI_DEVICE_ERROR;
+  }
+
+  // From now on we work in 32-bit words
+  BufferSizeInWords = BufferSizeInBytes / (UINTN)4;
+
+  // Write the word count, which is (buffer_size_in_words - 1),
+  // because word count 0 means one word.
+  SEND_NOR_COMMAND( TargetAddress, 0, (BufferSizeInWords - 1) );
+
+  // Write the data to the NOR Flash, advancing each address by 4 bytes
+  for( Count=0; Count<BufferSizeInWords; Count++, Data++, Buffer++ ) {
+    *Data = *Buffer;
+  }
+
+  // Issue the Buffered Program Confirm command, to start the programming operation
+  SEND_NOR_COMMAND( TargetAddress, 0, P30_CMD_BUFFERED_PROGRAM_CONFIRM );
+
+  // Wait for the write to complete and then check for any errors; i.e. check the Status Register
+  Status = NorFlashReadStatusRegister( TargetAddress );
+
+  return Status;
+}
+
+EFI_STATUS
+NorFlashWriteSingleBlock (
+  IN  UINTN     DeviceBaseAddress,
+  IN  EFI_LBA   Lba,
+  IN  UINT32    *DataBuffer,
+  IN  UINT32    BlockSizeInWords
+  )
+{
+  EFI_STATUS    Status = EFI_SUCCESS;
+  UINTN         WordAddress;
+  UINT32        WordIndex;
+  UINTN         BufferIndex;
+  UINTN         BlockAddress;
+  UINTN         BuffersInBlock;
+  UINTN         RemainingWords;
+
+  // Get the physical address of the block
+  BlockAddress = GET_NOR_BLOCK_ADDRESS(DeviceBaseAddress, Lba, BlockSizeInWords * 4);
+
+  Status = NorFlashUnlockAndEraseSingleBlock( BlockAddress );
+  if (EFI_ERROR(Status)) {
+    DEBUG((EFI_D_ERROR, "WriteSingleBlock: ERROR - Failed to Unlock and Erase the single block at 0x%X\n", BlockAddress));
+    return Status;
+  }
+
+  // To speed up the programming operation, NOR Flash is programmed using the Buffered Programming method.
+
+  // Start writing from the first address at the start of the block
+  WordAddress = BlockAddress;
+
+  // Check that the address starts at a 32-word boundary, i.e. last 7 bits must be zero
+  if ((WordAddress & BOUNDARY_OF_32_WORDS) == 0x00) {
+
+    // First, break the entire block into buffer-sized chunks.
+    BuffersInBlock = (UINTN)BlockSizeInWords / P30_MAX_BUFFER_SIZE_IN_BYTES;
+
+    // Then feed each buffer chunk to the NOR Flash
+    for( BufferIndex=0;
+         BufferIndex < BuffersInBlock;
+         BufferIndex++, WordAddress += P30_MAX_BUFFER_SIZE_IN_BYTES, DataBuffer += P30_MAX_BUFFER_SIZE_IN_WORDS
+       ) {
+      Status = NorFlashWriteBuffer ( WordAddress, P30_MAX_BUFFER_SIZE_IN_BYTES, DataBuffer );
+      if (EFI_ERROR(Status)) {
+        goto EXIT;
+      }
+    }
+
+    // Finally, finish off any remaining words that are less than the maximum size of the buffer
+    RemainingWords = BlockSizeInWords % P30_MAX_BUFFER_SIZE_IN_WORDS;
+
+    if( RemainingWords != 0) {
+      Status = NorFlashWriteBuffer ( WordAddress, (RemainingWords * 4), DataBuffer );
+      if (EFI_ERROR(Status)) {
+        goto EXIT;
+      }
+    }
+
+  } else {
+    // For now, use the single word programming algorithm
+    // It is unlikely that the NOR Flash will exist in an address which falls within a 32 word boundary range,
+    // i.e. which ends in the range 0x......01 - 0x......7F.
+    for( WordIndex=0; WordIndex<BlockSizeInWords; WordIndex++, DataBuffer++, WordAddress = WordAddress + 4 ) {
+      Status = NorFlashWriteSingleWord( WordAddress, *DataBuffer );
+      if (EFI_ERROR(Status)) {
+        goto EXIT;
+      }
+    }
+  }
+
+  EXIT:
+  if (EFI_ERROR(Status)) {
+    DEBUG((EFI_D_ERROR, "NOR FLASH Programming [WriteSingleBlock] failed at address 0x%08x. Exit Status = \"%r\".\n", WordAddress, Status));
+  }
+  return Status;
+}
+
+
+EFI_STATUS
+NorFlashWriteBlocks (
+  IN  NOR_FLASH_INSTANCE *Instance,
+  IN EFI_LBA                Lba,
+  IN UINTN                  BufferSizeInBytes,
+  IN VOID                   *Buffer
+  )
+{
+  UINT32          *pWriteBuffer;
+  EFI_STATUS      Status = EFI_SUCCESS;
+  EFI_LBA         CurrentBlock;
+  UINT32          BlockSizeInWords;
+  UINT32          NumBlocks;
+  UINT32          BlockCount;
+
+  // The buffer must be valid
+  if (Buffer == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if( Instance->Media.ReadOnly == TRUE ) {
+    return EFI_WRITE_PROTECTED;
+  }
+
+  // We must have some bytes to read
+  DEBUG((DEBUG_BLKIO, "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_BLKIO, "NorFlashWriteBlocks: BlockSize in bytes =0x%x\n", Instance->Media.BlockSize ));
+  if ((BufferSizeInBytes % Instance->Media.BlockSize) != 0) {
+    return EFI_BAD_BUFFER_SIZE;
+  }
+
+  // All blocks must be within the device
+  NumBlocks = ((UINT32)BufferSizeInBytes) / Instance->Media.BlockSize ;
+
+  DEBUG((DEBUG_BLKIO, "NorFlashWriteBlocks: NumBlocks=%d, LastBlock=%ld, Lba=%ld.\n", NumBlocks, Instance->Media.LastBlock, Lba));
+
+  if ( ( Lba + NumBlocks ) > ( Instance->Media.LastBlock + 1 ) ) {
+    DEBUG((EFI_D_ERROR, "NorFlashWriteBlocks: ERROR - Write will exceed last block.\n"));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  BlockSizeInWords = Instance->Media.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 = pWriteBuffer + BlockSizeInWords ) {
+
+    DEBUG((DEBUG_BLKIO, "NorFlashWriteBlocks: Writing block #%d\n", (UINTN)CurrentBlock ));
+
+    Status = NorFlashWriteSingleBlock( Instance->BaseAddress, CurrentBlock, pWriteBuffer, BlockSizeInWords );
+
+    if (EFI_ERROR(Status)) {
+      break;
+    }
+
+  }
+
+  DEBUG((DEBUG_BLKIO, "NorFlashWriteBlocks: Exit Status = \"%r\".\n", Status));
+  return Status;
+}
+
+
+EFI_STATUS
+NorFlashReadBlocks (
+  IN NOR_FLASH_INSTANCE   *Instance,
+  IN EFI_LBA                Lba,
+  IN UINTN                  BufferSizeInBytes,
+  OUT VOID                  *Buffer
+  )
+{
+  UINT32              NumBlocks;
+  UINTN               StartAddress;
+
+  // The buffer must be valid
+  if (Buffer == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // We must have some bytes to read
+  DEBUG((DEBUG_BLKIO, "NorFlashReadBlocks: BufferSize=0x%x bytes.\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_BLKIO, "NorFlashReadBlocks: BlockSize=0x%x bytes.\n", Instance->Media.BlockSize ));
+  if ((BufferSizeInBytes % Instance->Media.BlockSize) != 0) {
+    return EFI_BAD_BUFFER_SIZE;
+  }
+
+  // All blocks must be within the device
+  NumBlocks = ((UINT32)BufferSizeInBytes) / Instance->Media.BlockSize ;
+
+  DEBUG((DEBUG_BLKIO, "NorFlashReadBlocks: NumBlocks=%d, LastBlock=%ld, Lba=%ld\n", NumBlocks, Instance->Media.LastBlock, Lba));
+
+  if ( ( Lba + NumBlocks ) > (Instance->Media.LastBlock + 1) ) {
+    DEBUG((EFI_D_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->BaseAddress,
+                                        Lba,
+                                        Instance->Media.BlockSize
+                                        );
+
+  // Put the device into Read Array mode
+  SEND_NOR_COMMAND (Instance->BaseAddress, 0, P30_CMD_READ_ARRAY);
+
+  // Readout the data
+  CopyMem(Buffer, (UINTN *)StartAddress, BufferSizeInBytes);
+
+  return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+NorFlashReset (
+  IN  NOR_FLASH_INSTANCE *Instance
+  )
+{
+  // As there is no specific RESET to perform, ensure that the devices is in the default Read Array mode
+  SEND_NOR_COMMAND( Instance->BaseAddress, 0, P30_CMD_READ_ARRAY);
+  return EFI_SUCCESS;
+}
+
+
+
+EFI_STATUS
+EFIAPI
+NorFlashInitialise (
+  IN EFI_HANDLE         ImageHandle,
+  IN EFI_SYSTEM_TABLE   *SystemTable
+  )
+{
+  EFI_STATUS              Status;
+  UINT32                  Index;
+  NOR_FLASH_DESCRIPTION*  NorFlashDevices;
+  UINT32                  NorFlashDeviceCount;
+  BOOLEAN                 ContainVariableStorage;
+
+  Status = NorFlashPlatformInitialization ();
+  if (EFI_ERROR(Status)) {
+    DEBUG((EFI_D_ERROR,"NorFlashInitialise: Fail to initialize Nor Flash devices\n"));
+    return Status;
+  }
+
+  Status = NorFlashPlatformGetDevices (&NorFlashDevices,&NorFlashDeviceCount);
+  if (EFI_ERROR(Status)) {
+    DEBUG((EFI_D_ERROR,"NorFlashInitialise: Fail to get Nor Flash devices\n"));
+    return Status;
+  }
+
+  mNorFlashInstances = AllocatePool(sizeof(NOR_FLASH_INSTANCE*) * NorFlashDeviceCount);
+
+  for (Index = 0; Index < NorFlashDeviceCount; Index++) {
+    // Check if this NOR Flash device contain the variable storage region
+    ContainVariableStorage =
+        (NorFlashDevices[Index].BaseAddress <= PcdGet32 (PcdFlashNvStorageVariableBase)) &&
+        (PcdGet32 (PcdFlashNvStorageVariableBase) + PcdGet32 (PcdFlashNvStorageVariableSize) <= NorFlashDevices[Index].BaseAddress + NorFlashDevices[Index].Size);
+
+    Status = NorFlashCreateInstance (
+      NorFlashDevices[Index].BaseAddress,
+      NorFlashDevices[Index].Size,
+      Index,
+      NorFlashDevices[Index].BlockSize,
+      ContainVariableStorage,
+      &NorFlashDevices[Index].Guid,
+      &mNorFlashInstances[Index]
+    );
+    if (EFI_ERROR(Status)) {
+      DEBUG((EFI_D_ERROR,"NorFlashInitialise: Fail to create instance for NorFlash[%d]\n",Index));
+    }
+  }
+
+  return Status;
+}
diff --git a/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.h b/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.h
new file mode 100644 (file)
index 0000000..60cdbd5
--- /dev/null
@@ -0,0 +1,337 @@
+/** @file  NorFlashDxe.h
+
+  Copyright (c) 2011, ARM Ltd. All rights reserved.<BR>
+  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_DXE_H__
+#define __NOR_FLASH_DXE_H__
+
+
+#include <Base.h>
+#include <PiDxe.h>
+
+#include <Protocol/BlockIo.h>
+#include <Protocol/FirmwareVolumeBlock.h>
+
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/NorFlashPlatformLib.h>
+#include <Library/UefiLib.h>
+
+#include <ArmPlatform.h>
+
+#define HIGH_16_BITS                              0xFFFF0000
+#define LOW_16_BITS                               0x0000FFFF
+#define LOW_8_BITS                                0x000000FF
+
+// Device access macros
+// These are necessary because we use 2 x 16bit parts to make up 32bit data
+
+#define FOLD_32BIT_INTO_16BIT(value)              ( ( value >> 16 ) | ( value & LOW_16_BITS ) )
+
+#define GET_LOW_BYTE(value)                       ( value & LOW_8_BITS )
+#define GET_HIGH_BYTE(value)                      ( GET_LOW_BYTE( value >> 16 ) )
+
+// Each command must be sent simultaneously to both chips,
+// i.e. at the lower 16 bits AND at the higher 16 bits
+#define CREATE_NOR_ADDRESS(BaseAddr,OffsetAddr)   ((BaseAddr) + ((OffsetAddr) << 2))
+#define CREATE_DUAL_CMD(Cmd)                      ( ( Cmd << 16) | ( Cmd & LOW_16_BITS) )
+#define SEND_NOR_COMMAND(BaseAddr,OffsetAddr,Cmd) MmioWrite32 (CREATE_NOR_ADDRESS(BaseAddr,OffsetAddr), CREATE_DUAL_CMD(Cmd))
+#define GET_NOR_BLOCK_ADDRESS(BaseAddr,Lba,LbaSize)( BaseAddr + (UINTN)((Lba) * LbaSize) )
+
+// Status Register Bits
+#define P30_SR_BIT_WRITE                          (BIT7 << 16 | BIT7)
+#define P30_SR_BIT_ERASE_SUSPEND                  (BIT6 << 16 | BIT6)
+#define P30_SR_BIT_ERASE                          (BIT5 << 16 | BIT5)
+#define P30_SR_BIT_PROGRAM                        (BIT4 << 16 | BIT4)
+#define P30_SR_BIT_VPP                            (BIT3 << 16 | BIT3)
+#define P30_SR_BIT_PROGRAM_SUSPEND                (BIT2 << 16 | BIT2)
+#define P30_SR_BIT_BLOCK_LOCKED                   (BIT1 << 16 | BIT1)
+#define P30_SR_BIT_BEFP                           (BIT0 << 16 | BIT0)
+
+// Device Commands for Intel StrataFlash(R) Embedded Memory (P30) Family
+
+// On chip buffer size for buffered programming operations
+// There are 2 chips, each chip can buffer up to 32 (16-bit)words, and each word is 2 bytes.
+// Therefore the total size of the buffer is 2 x 32 x 2 = 128 bytes
+#define P30_MAX_BUFFER_SIZE_IN_BYTES              ((UINTN)128)
+#define P30_MAX_BUFFER_SIZE_IN_WORDS              (P30_MAX_BUFFER_SIZE_IN_BYTES/((UINTN)4))
+#define MAX_BUFFERED_PROG_ITERATIONS              10000000
+#define BOUNDARY_OF_32_WORDS                      0x7F
+
+// CFI Addresses
+#define P30_CFI_ADDR_QUERY_UNIQUE_QRY             0x10
+#define P30_CFI_ADDR_VENDOR_ID                    0x13
+
+// CFI Data
+#define CFI_QRY                                   0x00595251
+
+// READ Commands
+#define P30_CMD_READ_DEVICE_ID                    0x0090
+#define P30_CMD_READ_STATUS_REGISTER              0x0070
+#define P30_CMD_CLEAR_STATUS_REGISTER             0x0050
+#define P30_CMD_READ_ARRAY                        0x00FF
+#define P30_CMD_READ_CFI_QUERY                    0x0098
+
+// WRITE Commands
+#define P30_CMD_WORD_PROGRAM_SETUP                0x0040
+#define P30_CMD_ALTERNATE_WORD_PROGRAM_SETUP      0x0010
+#define P30_CMD_BUFFERED_PROGRAM_SETUP            0x00E8
+#define P30_CMD_BUFFERED_PROGRAM_CONFIRM          0x00D0
+#define P30_CMD_BEFP_SETUP                        0x0080
+#define P30_CMD_BEFP_CONFIRM                      0x00D0
+
+// ERASE Commands
+#define P30_CMD_BLOCK_ERASE_SETUP                 0x0020
+#define P30_CMD_BLOCK_ERASE_CONFIRM               0x00D0
+
+// SUSPEND Commands
+#define P30_CMD_PROGRAM_OR_ERASE_SUSPEND          0x00B0
+#define P30_CMD_SUSPEND_RESUME                    0x00D0
+
+// BLOCK LOCKING / UNLOCKING Commands
+#define P30_CMD_LOCK_BLOCK_SETUP                  0x0060
+#define P30_CMD_LOCK_BLOCK                        0x0001
+#define P30_CMD_UNLOCK_BLOCK                      0x00D0
+#define P30_CMD_LOCK_DOWN_BLOCK                   0x002F
+
+// PROTECTION Commands
+#define P30_CMD_PROGRAM_PROTECTION_REGISTER_SETUP 0x00C0
+
+// CONFIGURATION Commands
+#define P30_CMD_READ_CONFIGURATION_REGISTER_SETUP 0x0060
+#define P30_CMD_READ_CONFIGURATION_REGISTER       0x0003
+
+#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                               BaseAddress;
+  UINTN                               Size;
+  EFI_LBA                             StartLba;
+
+  EFI_BLOCK_IO_PROTOCOL               BlockIoProtocol;
+  EFI_BLOCK_IO_MEDIA                  Media;
+
+  BOOLEAN                             SupportFvb;
+  EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL FvbProtocol;
+
+  NOR_FLASH_DEVICE_PATH                      DevicePath;
+};
+
+EFI_STATUS
+EFIAPI
+NorFlashGetDriverName (
+  IN  EFI_COMPONENT_NAME_PROTOCOL  *This,
+  IN  CHAR8                        *Language,
+  OUT CHAR16                       **DriverName
+  );
+
+EFI_STATUS
+EFIAPI
+NorFlashGetControllerName (
+  IN  EFI_COMPONENT_NAME_PROTOCOL                     *This,
+  IN  EFI_HANDLE                                      ControllerHandle,
+  IN  EFI_HANDLE                                      ChildHandle        OPTIONAL,
+  IN  CHAR8                                           *Language,
+  OUT CHAR16                                          **ControllerName
+  );
+
+EFI_STATUS
+EFIAPI
+NorFlashBlkIoInitialize (
+  IN NOR_FLASH_INSTANCE*      Instance
+  );
+
+EFI_STATUS
+NorFlashReadCfiData (
+  IN UINTN                    BaseAddress,
+  IN UINTN                    CFI_Offset,
+  IN UINT32                   NumberOfBytes,
+  OUT UINT32                  *Data
+);
+
+EFI_STATUS
+NorFlashWriteBuffer (
+    IN  UINTN                 TargetAddress,
+    IN  UINTN                 BufferSizeInBytes,
+    IN  UINT32                *Buffer
+);
+
+
+//
+// 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
+);
+
+
+//
+// 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,
+  ...
+);
+
+//
+// NorFlashDxe.c
+//
+
+EFI_STATUS
+NorFlashUnlockAndEraseSingleBlock(
+  IN  UINTN             BlockAddress
+);
+
+EFI_STATUS
+NorFlashWriteSingleBlock (
+  IN  UINTN             DeviceBaseAddress,
+  IN  EFI_LBA           Lba,
+  IN  UINT32            *pDataBuffer,
+  IN  UINT32            BlockSizeInWords
+);
+
+EFI_STATUS
+NorFlashWriteBlocks (
+  IN  NOR_FLASH_INSTANCE *Instance,
+  IN  EFI_LBA           Lba,
+  IN  UINTN             BufferSizeInBytes,
+  IN  VOID              *Buffer
+);
+
+EFI_STATUS
+NorFlashReadBlocks (
+  IN  NOR_FLASH_INSTANCE *Instance,
+  IN  EFI_LBA           Lba,
+  IN  UINTN             BufferSizeInBytes,
+  OUT VOID              *Buffer
+);
+
+EFI_STATUS
+NorFlashReset (
+  IN  NOR_FLASH_INSTANCE *Instance
+);
+
+#endif /* __NOR_FLASH_DXE_H__ */
diff --git a/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.inf b/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.inf
new file mode 100644 (file)
index 0000000..43f670e
--- /dev/null
@@ -0,0 +1,64 @@
+#/** @file
+#  
+#  Component discription file for NorFlashDxe module
+#  
+#  Copyright (c) 2010, ARM Ltd. All rights reserved.<BR>
+#  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                    = 0x00010005
+  BASE_NAME                      = ArmVeNorFlashDxe
+  FILE_GUID                      = 93E34C7E-B50E-11DF-9223-2443DFD72085
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = NorFlashInitialise
+
+[Sources.common]
+  NorFlashDxe.c
+  NorFlashFvbDxe.c
+  NorFlashBlockIoDxe.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  ArmPlatformPkg/ArmPlatformPkg.dec
+
+[LibraryClasses]
+  IoLib
+  BaseLib
+  DebugLib
+  NorFlashPlatformLib
+  UefiLib
+  UefiDriverEntryPoint
+  UefiBootServicesTableLib
+
+[Guids]
+  gEfiSystemNvDataFvGuid
+  gEfiVariableGuid
+
+[Protocols]
+  gEfiBlockIoProtocolGuid
+  gEfiDevicePathProtocolGuid
+  gEfiFirmwareVolumeBlockProtocolGuid
+  
+[Pcd.common]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize
+
+[Depex]
+  #
+  # NorFlashDxe must be loaded before VariableRuntimeDxe in case empty flash needs populating with default values
+  # 
+  BEFORE gVariableRuntimeDxeFileGuid 
diff --git a/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashFvbDxe.c b/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashFvbDxe.c
new file mode 100644 (file)
index 0000000..c4a61c1
--- /dev/null
@@ -0,0 +1,808 @@
+/*++ @file  NorFlashFvbDxe.c
+
+ Copyright (c) 2011, ARM Ltd. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution.  The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ --*/
+
+#include <PiDxe.h>
+
+#include <Library/PcdLib.h>
+#include <Library/BaseLib.h>
+#include <Library/UefiLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include <Guid/VariableFormat.h>
+#include <Guid/SystemNvDataGuid.h>
+
+#include "NorFlashDxe.h"
+
+
+///
+/// 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);
+  }
+
+  HeadersLength = sizeof(EFI_FIRMWARE_VOLUME_HEADER) + sizeof(EFI_FV_BLOCK_MAP_ENTRY) + sizeof(VARIABLE_STORE_HEADER);
+  Headers = AllocateZeroPool(HeadersLength);
+
+  // FirmwareVolumeHeader->FvLength is declared to have the Variable area AND the FTW working area AND the FTW Spare contiguous.
+  ASSERT(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) / 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(PcdGet32(PcdFlashNvStorageVariableBase) % Instance->Media.BlockSize == 0);
+  ASSERT(PcdGet32(PcdFlashNvStorageFtwWorkingBase) % Instance->Media.BlockSize == 0);
+  ASSERT(PcdGet32(PcdFlashNvStorageFtwSpareBase) % 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;
+  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*)((UINT32)Headers + FirmwareVolumeHeader->HeaderLength);
+  CopyGuid (&VariableStoreHeader->Signature, &gEfiVariableGuid);
+  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*)Instance->BaseAddress;
+
+  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 ((EFI_D_ERROR, "ValidateFvHeader: No Firmware Volume header present\n"));
+    return EFI_NOT_FOUND;
+  }
+
+  // Check the Firmware Volume Guid
+  if( CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiSystemNvDataFvGuid) == FALSE ) {
+    DEBUG ((EFI_D_ERROR, "ValidateFvHeader: Firmware Volume Guid non-compatible\n"));
+    return EFI_NOT_FOUND;
+  }
+
+  // Verify the header checksum
+  Checksum = CalculateSum16((UINT16*)FwVolHeader, FwVolHeader->HeaderLength);
+  if (Checksum != 0) {
+    DEBUG ((EFI_D_ERROR, "ValidateFvHeader: FV checksum is invalid (Checksum:0x%X)\n",Checksum));
+    return EFI_NOT_FOUND;
+  }
+
+  VariableStoreHeader = (VARIABLE_STORE_HEADER*)((UINT32)FwVolHeader + FwVolHeader->HeaderLength);
+
+  // Check the Variable Store Guid
+  if( CompareGuid (&VariableStoreHeader->Signature, &gEfiVariableGuid) == FALSE ) {
+    DEBUG ((EFI_D_ERROR, "ValidateFvHeader: Variable Store Guid non-compatible\n"));
+    return EFI_NOT_FOUND;
+  }
+
+  VariableStoreLength = PcdGet32 (PcdFlashNvStorageVariableSize) - FwVolHeader->HeaderLength;
+  if (VariableStoreHeader->Size != VariableStoreLength) {
+    DEBUG ((EFI_D_ERROR, "ValidateFvHeader: Variable Store Length does not match\n"));
+    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
+  )
+{
+  NOR_FLASH_INSTANCE *Instance;
+
+  Instance = INSTANCE_FROM_FVB_THIS(This);
+
+  DEBUG ((DEBUG_BLKIO, "FvbGetPhysicalAddress(BaseAddress=0x%08x)\n", Instance->BaseAddress));
+
+  ASSERT(Address != NULL);
+
+  *Address = PcdGet32 (PcdFlashNvStorageVariableBase);
+  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 ((EFI_D_ERROR, "FvbGetBlockSize: ERROR - Parameter LBA %ld is beyond the last Lba (%ld).\n", Lba, Instance->Media.LastBlock));
+    Status = EFI_INVALID_PARAMETER;
+  } else {
+    // This is easy because 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, "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.
+ 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
+  )
+{
+  EFI_STATUS    Status;
+  EFI_STATUS    TempStatus;
+  UINTN         BlockSize;
+  UINT8         *BlockBuffer;
+  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);
+  }
+
+  Status = EFI_SUCCESS;
+  TempStatus = Status;
+
+  // 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.
+  // We need to check each variable individually because adding two large values together overflows.
+  if ((Offset               >= BlockSize) ||
+      (*NumBytes            >  BlockSize) ||
+      ((Offset + *NumBytes) >  BlockSize)) {
+    DEBUG ((EFI_D_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;
+  }
+
+  // FixMe: Allow an arbitrary number of bytes to be read out, not just a multiple of block size.
+
+  // Allocate runtime memory to read in the NOR Flash data. Variable Services are runtime.
+  BlockBuffer = AllocateRuntimePool(BlockSize);
+
+  // Check if the memory allocation was successful
+  if (BlockBuffer == NULL) {
+    DEBUG ((EFI_D_ERROR, "FvbRead: ERROR - Could not allocate BlockBuffer @ 0x%08x.\n", BlockBuffer));
+    return EFI_DEVICE_ERROR;
+  }
+
+  // Read NOR Flash data into shadow buffer
+  TempStatus = NorFlashReadBlocks (Instance, Instance->StartLba + Lba, BlockSize, BlockBuffer);
+  if (EFI_ERROR (TempStatus)) {
+    // Return one of the pre-approved error statuses
+    Status = EFI_DEVICE_ERROR;
+    goto FREE_MEMORY;
+  }
+
+  // Put the data at the appropriate location inside the buffer area
+  DEBUG ((DEBUG_BLKIO, "FvbRead: CopyMem( Dst=0x%08x, Src=0x%08x, Size=0x%x ).\n", Buffer, BlockBuffer + Offset, *NumBytes));
+
+  CopyMem(Buffer, BlockBuffer + Offset, *NumBytes);
+
+FREE_MEMORY:
+  FreePool(BlockBuffer);
+  return Status;
+}
+
+/**
+ 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
+  )
+{
+  EFI_STATUS  Status;
+  EFI_STATUS  TempStatus;
+  UINTN       BlockSize;
+  UINT8       *BlockBuffer;
+  NOR_FLASH_INSTANCE *Instance;
+
+  Instance = INSTANCE_FROM_FVB_THIS(This);
+
+  if (!Instance->Initialized) {
+    Instance->Initialize(Instance);
+  }
+
+  DEBUG ((DEBUG_BLKIO, "FvbWrite(Parameters: Lba=%ld, Offset=0x%x, *NumBytes=0x%x, Buffer @ 0x%08x)\n", Instance->StartLba + Lba, Offset, *NumBytes, Buffer));
+
+  Status = EFI_SUCCESS;
+  TempStatus = Status;
+
+  // Detect WriteDisabled state
+  if (Instance->Media.ReadOnly == TRUE) {
+    DEBUG ((EFI_D_ERROR, "FvbWrite: 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;
+
+  // 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 ((EFI_D_ERROR, "FvbWrite: 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 ((EFI_D_ERROR, "FvbWrite: ERROR - EFI_BAD_BUFFER_SIZE: (Offset=0x%x + NumBytes=0x%x) > BlockSize=0x%x\n", Offset, *NumBytes, BlockSize ));
+    return EFI_BAD_BUFFER_SIZE;
+  }
+
+  // Allocate runtime memory to read in the NOR Flash data.
+  // Since the intention is to use this with Variable Services and since these are runtime,
+  // allocate the memory from the runtime pool.
+  BlockBuffer = AllocateRuntimePool(BlockSize);
+
+  // Check we did get some memory
+  if( BlockBuffer == NULL ) {
+    DEBUG ((EFI_D_ERROR, "FvbWrite: ERROR - Can not allocate BlockBuffer @ 0x%08x.\n", BlockBuffer));
+    return EFI_DEVICE_ERROR;
+  }
+
+  // Read NOR Flash data into shadow buffer
+  TempStatus = NorFlashReadBlocks(Instance, Instance->StartLba + Lba, BlockSize, BlockBuffer);
+  if (EFI_ERROR (TempStatus)) {
+    // Return one of the pre-approved error statuses
+    Status = EFI_DEVICE_ERROR;
+    goto FREE_MEMORY;
+  }
+
+  // Put the data at the appropriate location inside the buffer area
+  CopyMem((BlockBuffer + Offset), Buffer, *NumBytes);
+
+  // Write the modified buffer back to the NorFlash
+  Status = NorFlashWriteBlocks(Instance, Instance->StartLba + Lba, BlockSize, BlockBuffer);
+  if (EFI_ERROR (TempStatus)) {
+    // Return one of the pre-approved error statuses
+    Status = EFI_DEVICE_ERROR;
+    goto FREE_MEMORY;
+  }
+
+FREE_MEMORY:
+  FreePool(BlockBuffer);
+  return Status;
+}
+
+/**
+ 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 ((EFI_D_ERROR, "FvbEraseBlocks: ERROR - Device is in WriteDisabled state.\n"));
+    return EFI_ACCESS_DENIED;
+  }
+
+  // Before erasing, check the entire list of parameters to ensure all specified blocks are valid
+
+  VA_START (Args, This);
+  do {
+    // Get the Lba from which we start erasing
+    StartingLba = VA_ARG (Args, EFI_LBA);
+
+    // Have we reached the end of the list?
+    if (StartingLba == EFI_LBA_LIST_TERMINATOR) {
+      //Exit the while loop
+      break;
+    }
+
+    // How many Lba blocks are we requested to erase?
+    NumOfLba = VA_ARG (Args, UINT32);
+
+    // All blocks must be within range
+    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 ((EFI_D_ERROR, "FvbEraseBlocks: ERROR - Lba range goes past the last Lba.\n"));
+      Status = EFI_INVALID_PARAMETER;
+      goto EXIT;
+    }
+  } while (TRUE);
+  VA_END (Args);
+
+
+  //
+  // To get here, all must be ok, so start erasing
+  //
+  VA_START (Args, This);
+  do {
+    // Get the Lba from which we start erasing
+    StartingLba = VA_ARG (Args, EFI_LBA);
+
+    // Have we reached the end of the list?
+    if (StartingLba == EFI_LBA_LIST_TERMINATOR) {
+      // Exit the while loop
+      break;
+    }
+
+    // How many Lba blocks are we requested to erase?
+    NumOfLba = VA_ARG (Args, UINT32);
+
+    // Go through each one and erase it
+    while (NumOfLba > 0) {
+
+      // Get the physical address of Lba to erase
+      BlockAddress = GET_NOR_BLOCK_ADDRESS (
+          Instance->BaseAddress,
+          Instance->StartLba + StartingLba,
+          Instance->Media.BlockSize
+      );
+
+      // Erase it
+      DEBUG ((DEBUG_BLKIO, "FvbEraseBlocks: Erasing Lba=%ld @ 0x%08x.\n", Instance->StartLba + StartingLba, BlockAddress));
+      Status = NorFlashUnlockAndEraseSingleBlock (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;
+}
+
+EFI_STATUS
+EFIAPI
+NorFlashFvbInitialize (
+  IN NOR_FLASH_INSTANCE* Instance
+  )
+{
+  EFI_STATUS  Status;
+  UINT32      FvbNumLba;
+
+  DEBUG((DEBUG_BLKIO,"NorFlashFvbInitialize\n"));
+
+  Status = NorFlashBlkIoInitialize (Instance);
+  if (EFI_ERROR(Status)) {
+    DEBUG((EFI_D_ERROR,"NorFlashFvbInitialize: ERROR - Failed to initialize FVB\n"));
+    return Status;
+  }
+  Instance->Initialized = TRUE;
+
+  // Set the index of the first LBA for the FVB
+  Instance->StartLba = (PcdGet32 (PcdFlashNvStorageVariableBase) - Instance->BaseAddress) / Instance->Media.BlockSize;
+
+  // Determine if there is a valid header at the beginning of the NorFlash
+  Status = ValidateFvHeader (Instance);
+  if (EFI_ERROR(Status)) {
+    // There is no valid header, so time to install one.
+    DEBUG((EFI_D_ERROR,"NorFlashFvbInitialize: ERROR - The FVB Header is not valid. Installing a correct one for this volume.\n"));
+
+    // 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;
+    }
+  }
+  return Status;
+}
diff --git a/ArmPlatformPkg/Include/Library/NorFlashPlatformLib.h b/ArmPlatformPkg/Include/Library/NorFlashPlatformLib.h
new file mode 100644 (file)
index 0000000..d5b427d
--- /dev/null
@@ -0,0 +1,35 @@
+/** @file\r
+\r
+ Copyright (c) 2011, ARM Ltd. All rights reserved.<BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution.  The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+ **/\r
+\r
+#ifndef _NORFLASHPLATFORMLIB_H_\r
+#define _NORFLASHPLATFORMLIB_H_\r
+\r
+typedef struct {\r
+    UINTN                             BaseAddress;\r
+    UINTN                             Size;\r
+    UINTN                             BlockSize;\r
+    EFI_GUID                          Guid;\r
+} NOR_FLASH_DESCRIPTION;\r
+\r
+EFI_STATUS\r
+NorFlashPlatformInitialization (\r
+  VOID\r
+  );\r
+\r
+EFI_STATUS\r
+NorFlashPlatformGetDevices (\r
+  OUT NOR_FLASH_DESCRIPTION   **NorFlashDescriptions,\r
+  OUT UINT32                  *Count\r
+  );\r
+\r
+#endif /* _NORFLASHPLATFORMLIB_H_ */\r