From: "Tuan Phan" <tphan@ventanamicro.com>
To: devel@edk2.groups.io
Cc: andyw@imsa.edu, maobibo@loongson.cn, lichao@loongson.cn,
kraxel@redhat.com, jiewen.yao@intel.com,
leif.lindholm@oss.qualcomm.com, sami.mujawar@arm.com,
sunilvl@ventanamicro.com, ardb+tianocore@kernel.org,
lixianglai@loongson.cn, Tuan Phan <tphan@ventanamicro.com>
Subject: [edk2-devel] [PATCH 1/3] OvmfPkg/VirtNorFlash: Move low level NOR flash functions into library
Date: Mon, 21 Apr 2025 09:58:17 -0700 [thread overview]
Message-ID: <20250421165819.18451-2-tphan@ventanamicro.com> (raw)
In-Reply-To: <20250421165819.18451-1-tphan@ventanamicro.com>
This patch refactors low level NOR flash functions into a dedicated library
to enable reuse, particularly for supporting the firmware upgrade feature.
Signed-off-by: Tuan Phan <tphan@ventanamicro.com>
---
.../Include/Library/VirtNorFlashDeviceLib.h | 201 +++++++++
.../VirtNorFlashDeviceLib.c} | 411 ++++++++++++------
.../VirtNorFlashDeviceLib.inf | 30 ++
OvmfPkg/LoongArchVirt/LoongArchVirtQemu.dsc | 5 +-
OvmfPkg/OvmfPkg.dec | 4 +
OvmfPkg/RiscVVirt/RiscVVirtQemu.dsc | 5 +-
OvmfPkg/VirtNorFlashDxe/VirtNorFlash.h | 345 ---------------
OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.c | 180 ++------
OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.h | 156 +++++++
OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.inf | 3 +-
OvmfPkg/VirtNorFlashDxe/VirtNorFlashFvb.c | 53 ++-
11 files changed, 749 insertions(+), 644 deletions(-)
create mode 100644 OvmfPkg/Include/Library/VirtNorFlashDeviceLib.h
rename OvmfPkg/{VirtNorFlashDxe/VirtNorFlash.c => Library/VirtNorFlashDeviceLib/VirtNorFlashDeviceLib.c} (63%)
create mode 100644 OvmfPkg/Library/VirtNorFlashDeviceLib/VirtNorFlashDeviceLib.inf
delete mode 100644 OvmfPkg/VirtNorFlashDxe/VirtNorFlash.h
create mode 100644 OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.h
diff --git a/OvmfPkg/Include/Library/VirtNorFlashDeviceLib.h b/OvmfPkg/Include/Library/VirtNorFlashDeviceLib.h
new file mode 100644
index 000000000000..45f4bf628097
--- /dev/null
+++ b/OvmfPkg/Include/Library/VirtNorFlashDeviceLib.h
@@ -0,0 +1,201 @@
+/** @file VirtNorFlashDeviceLib.h
+
+ Copyright (c) 2011 - 2014, ARM Ltd. All rights reserved.<BR>
+ Copyright (c) 2025, Ventana Micro Systems Inc. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __VIRT_NOR_FLASH_DEVICE_LIB__
+#define __VIRT_NOR_FLASH_DEVICE_LIB__
+
+#include <Base.h>
+#include <PiDxe.h>
+
+#include <Guid/EventGroup.h>
+
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/UefiLib.h>
+
+#define NOR_FLASH_ERASE_RETRY 10
+
+// Device access macros
+// These are necessary because we use 2 x 16bit parts to make up 32bit data
+
+#define HIGH_16_BITS 0xFFFF0000
+#define LOW_16_BITS 0x0000FFFF
+#define LOW_8_BITS 0x000000FF
+
+#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, Offset, Cmd) MmioWrite32 (CREATE_NOR_ADDRESS(BaseAddr,Offset), 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 ((UINTN)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
+
+EFI_STATUS
+NorFlashWriteBuffer (
+ IN UINTN DeviceBaseAddress,
+ IN UINTN TargetAddress,
+ IN UINTN BufferSizeInBytes,
+ IN UINT32 *Buffer
+ );
+
+EFI_STATUS
+NorFlashWriteSingleBlock (
+ IN UINTN DeviceBaseAddress,
+ IN UINTN RegionBaseAddress,
+ IN EFI_LBA Lba,
+ IN UINT32 LastBlock,
+ IN UINT32 BlockSize,
+ IN UINTN Size,
+ IN UINTN Offset,
+ IN OUT UINTN *NumBytes,
+ IN UINT8 *Buffer,
+ IN VOID *ShadowBuffer
+ );
+
+EFI_STATUS
+NorFlashWriteBlocks (
+ IN UINTN DeviceBaseAddress,
+ IN UINTN RegionBaseAddress,
+ IN EFI_LBA Lba,
+ IN EFI_LBA LastBlock,
+ IN UINT32 BlockSize,
+ IN UINTN BufferSizeInBytes,
+ IN VOID *Buffer
+ );
+
+EFI_STATUS
+NorFlashReadBlocks (
+ IN UINTN DeviceBaseAddress,
+ IN UINTN RegionBaseAddress,
+ IN EFI_LBA Lba,
+ IN EFI_LBA LastBlock,
+ IN UINT32 BlockSize,
+ IN UINTN BufferSizeInBytes,
+ OUT VOID *Buffer
+ );
+
+EFI_STATUS
+NorFlashRead (
+ IN UINTN DeviceBaseAddress,
+ IN UINTN RegionBaseAddress,
+ IN EFI_LBA Lba,
+ IN UINT32 BlockSize,
+ IN UINTN Size,
+ IN UINTN Offset,
+ IN UINTN BufferSizeInBytes,
+ OUT VOID *Buffer
+ );
+
+EFI_STATUS
+NorFlashEraseSingleBlock (
+ IN UINTN DeviceBaseAddress,
+ IN UINTN BlockAddress
+ );
+
+EFI_STATUS
+NorFlashUnlockSingleBlockIfNecessary (
+ IN UINTN DeviceBaseAddress,
+ IN UINTN BlockAddress
+ );
+
+EFI_STATUS
+NorFlashWriteSingleWord (
+ IN UINTN DeviceBaseAddress,
+ IN UINTN WordAddress,
+ IN UINT32 WriteData
+ );
+
+EFI_STATUS
+NorFlashWriteFullBlock (
+ IN UINTN DeviceBaseAddress,
+ IN UINTN RegionBaseAddress,
+ IN EFI_LBA Lba,
+ IN UINT32 *DataBuffer,
+ IN UINT32 BlockSizeInWords
+ );
+
+EFI_STATUS
+NorFlashUnlockAndEraseSingleBlock (
+ IN UINTN DeviceBaseAddress,
+ IN UINTN BlockAddress
+ );
+
+EFI_STATUS
+NorFlashReset (
+ IN UINTN DeviceBaseAddress
+ );
+
+#endif /* __VIRT_NOR_FLASH_DEVICE_LIB__ */
diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c b/OvmfPkg/Library/VirtNorFlashDeviceLib/VirtNorFlashDeviceLib.c
similarity index 63%
rename from OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c
rename to OvmfPkg/Library/VirtNorFlashDeviceLib/VirtNorFlashDeviceLib.c
index e6aaed27ceba..604ac4df3f0b 100644
--- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c
+++ b/OvmfPkg/Library/VirtNorFlashDeviceLib/VirtNorFlashDeviceLib.c
@@ -8,31 +8,25 @@
**/
#include <Library/BaseMemoryLib.h>
-
-#include "VirtNorFlash.h"
-
-//
-// Global variable declarations
-//
-extern NOR_FLASH_INSTANCE **mNorFlashInstances;
-extern UINT32 mNorFlashDeviceCount;
+#include <Library/IoLib.h>
+#include <Library/VirtNorFlashDeviceLib.h>
UINT32
NorFlashReadStatusRegister (
- IN NOR_FLASH_INSTANCE *Instance,
- IN UINTN SR_Address
+ IN UINTN DeviceBaseAddress,
+ IN UINTN SR_Address
)
{
// Prepare to read the status register
- SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_STATUS_REGISTER);
- return MmioRead32 (Instance->DeviceBaseAddress);
+ SEND_NOR_COMMAND (DeviceBaseAddress, 0, P30_CMD_READ_STATUS_REGISTER);
+ return MmioRead32 (DeviceBaseAddress);
}
STATIC
BOOLEAN
NorFlashBlockIsLocked (
- IN NOR_FLASH_INSTANCE *Instance,
- IN UINTN BlockAddress
+ IN UINTN DeviceBaseAddress,
+ IN UINTN BlockAddress
)
{
UINT32 LockStatus;
@@ -56,8 +50,8 @@ NorFlashBlockIsLocked (
STATIC
EFI_STATUS
NorFlashUnlockSingleBlock (
- IN NOR_FLASH_INSTANCE *Instance,
- IN UINTN BlockAddress
+ IN UINTN DeviceBaseAddress,
+ IN UINTN BlockAddress
)
{
UINT32 LockStatus;
@@ -73,7 +67,7 @@ NorFlashUnlockSingleBlock (
// Wait until the status register gives us the all clear
do {
- LockStatus = NorFlashReadStatusRegister (Instance, BlockAddress);
+ LockStatus = NorFlashReadStatusRegister (DeviceBaseAddress, BlockAddress);
} while ((LockStatus & P30_SR_BIT_WRITE) != P30_SR_BIT_WRITE);
// Put device back into Read Array mode
@@ -86,16 +80,16 @@ NorFlashUnlockSingleBlock (
EFI_STATUS
NorFlashUnlockSingleBlockIfNecessary (
- IN NOR_FLASH_INSTANCE *Instance,
- IN UINTN BlockAddress
+ IN UINTN DeviceBaseAddress,
+ IN UINTN BlockAddress
)
{
EFI_STATUS Status;
Status = EFI_SUCCESS;
- if (NorFlashBlockIsLocked (Instance, BlockAddress)) {
- Status = NorFlashUnlockSingleBlock (Instance, BlockAddress);
+ if (NorFlashBlockIsLocked (DeviceBaseAddress, BlockAddress)) {
+ Status = NorFlashUnlockSingleBlock (DeviceBaseAddress, BlockAddress);
}
return Status;
@@ -106,8 +100,8 @@ NorFlashUnlockSingleBlockIfNecessary (
**/
EFI_STATUS
NorFlashEraseSingleBlock (
- IN NOR_FLASH_INSTANCE *Instance,
- IN UINTN BlockAddress
+ IN UINTN DeviceBaseAddress,
+ IN UINTN BlockAddress
)
{
EFI_STATUS Status;
@@ -121,7 +115,7 @@ NorFlashEraseSingleBlock (
// Wait until the status register gives us the all clear
do {
- StatusRegister = NorFlashReadStatusRegister (Instance, BlockAddress);
+ StatusRegister = NorFlashReadStatusRegister (DeviceBaseAddress, BlockAddress);
} while ((StatusRegister & P30_SR_BIT_WRITE) != P30_SR_BIT_WRITE);
if (StatusRegister & P30_SR_BIT_VPP) {
@@ -147,20 +141,20 @@ NorFlashEraseSingleBlock (
if (EFI_ERROR (Status)) {
// Clear the Status Register
- SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_CLEAR_STATUS_REGISTER);
+ SEND_NOR_COMMAND (DeviceBaseAddress, 0, P30_CMD_CLEAR_STATUS_REGISTER);
}
// Put device back into Read Array mode
- SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);
+ SEND_NOR_COMMAND (DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);
return Status;
}
EFI_STATUS
NorFlashWriteSingleWord (
- IN NOR_FLASH_INSTANCE *Instance,
- IN UINTN WordAddress,
- IN UINT32 WriteData
+ IN UINTN DeviceBaseAddress,
+ IN UINTN WordAddress,
+ IN UINT32 WriteData
)
{
EFI_STATUS Status;
@@ -177,7 +171,7 @@ NorFlashWriteSingleWord (
// Wait for the write to complete and then check for any errors; i.e. check the Status Register
do {
// Prepare to read the status register
- StatusRegister = NorFlashReadStatusRegister (Instance, WordAddress);
+ StatusRegister = NorFlashReadStatusRegister (DeviceBaseAddress, WordAddress);
// The chip is busy while the WRITE bit is not asserted
} while ((StatusRegister & P30_SR_BIT_WRITE) != P30_SR_BIT_WRITE);
@@ -202,7 +196,7 @@ NorFlashWriteSingleWord (
if (!EFI_ERROR (Status)) {
// Clear the Status Register
- SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_CLEAR_STATUS_REGISTER);
+ SEND_NOR_COMMAND (DeviceBaseAddress, 0, P30_CMD_CLEAR_STATUS_REGISTER);
}
return Status;
@@ -225,10 +219,10 @@ NorFlashWriteSingleWord (
*/
EFI_STATUS
NorFlashWriteBuffer (
- IN NOR_FLASH_INSTANCE *Instance,
- IN UINTN TargetAddress,
- IN UINTN BufferSizeInBytes,
- IN UINT32 *Buffer
+ IN UINTN DeviceBaseAddress,
+ IN UINTN TargetAddress,
+ IN UINTN BufferSizeInBytes,
+ IN UINT32 *Buffer
)
{
EFI_STATUS Status;
@@ -299,11 +293,11 @@ NorFlashWriteBuffer (
}
// Issue the Buffered Program Confirm command, to start the programming operation
- SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_BUFFERED_PROGRAM_CONFIRM);
+ SEND_NOR_COMMAND (DeviceBaseAddress, 0, P30_CMD_BUFFERED_PROGRAM_CONFIRM);
// Wait for the write to complete and then check for any errors; i.e. check the Status Register
do {
- StatusRegister = NorFlashReadStatusRegister (Instance, TargetAddress);
+ StatusRegister = NorFlashReadStatusRegister (DeviceBaseAddress, TargetAddress);
// The chip is busy while the WRITE bit is not asserted
} while ((StatusRegister & P30_SR_BIT_WRITE) != P30_SR_BIT_WRITE);
@@ -330,7 +324,135 @@ NorFlashWriteBuffer (
if (!EFI_ERROR (Status)) {
// Clear the Status Register
- SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_CLEAR_STATUS_REGISTER);
+ SEND_NOR_COMMAND (DeviceBaseAddress, 0, P30_CMD_CLEAR_STATUS_REGISTER);
+ }
+
+ return Status;
+}
+
+/**
+ * This function unlock and erase an entire NOR Flash block.
+ **/
+EFI_STATUS
+NorFlashUnlockAndEraseSingleBlock (
+ IN UINTN DeviceBaseAddress,
+ IN UINTN BlockAddress
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+
+ Index = 0;
+ // The block erase might fail a first time (SW bug ?). Retry it ...
+ do {
+ // Unlock the block if we have to
+ Status = NorFlashUnlockSingleBlockIfNecessary (DeviceBaseAddress, BlockAddress);
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+
+ Status = NorFlashEraseSingleBlock (DeviceBaseAddress, BlockAddress);
+ Index++;
+ } while ((Index < NOR_FLASH_ERASE_RETRY) && (Status == EFI_WRITE_PROTECTED));
+
+ if (Index == NOR_FLASH_ERASE_RETRY) {
+ DEBUG ((DEBUG_ERROR, "EraseSingleBlock(BlockAddress=0x%08x: Block Locked Error (try to erase %d times)\n", BlockAddress, Index));
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+NorFlashWriteFullBlock (
+ IN UINTN DeviceBaseAddress,
+ IN UINTN RegionBaseAddress,
+ IN EFI_LBA Lba,
+ IN UINT32 *DataBuffer,
+ IN UINT32 BlockSizeInWords
+ )
+{
+ EFI_STATUS Status;
+ UINTN WordAddress;
+ UINT32 WordIndex;
+ UINTN BufferIndex;
+ UINTN BlockAddress;
+ UINTN BuffersInBlock;
+ UINTN RemainingWords;
+ UINTN Cnt;
+
+ Status = EFI_SUCCESS;
+
+ // Get the physical address of the block
+ BlockAddress = GET_NOR_BLOCK_ADDRESS (RegionBaseAddress, Lba, BlockSizeInWords * 4);
+
+ // Start writing from the first address at the start of the block
+ WordAddress = BlockAddress;
+ Status = NorFlashUnlockAndEraseSingleBlock (DeviceBaseAddress, BlockAddress);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "WriteSingleBlock: ERROR - Failed to Unlock and Erase the single block at 0x%X\n", BlockAddress));
+ goto EXIT;
+ }
+
+ // To speed up the programming operation, NOR Flash is programmed using the Buffered Programming method.
+
+ // 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 * 4) / P30_MAX_BUFFER_SIZE_IN_BYTES;
+
+ // Then feed each buffer chunk to the NOR Flash
+ // If a buffer does not contain any data, don't write it.
+ for (BufferIndex = 0;
+ BufferIndex < BuffersInBlock;
+ BufferIndex++, WordAddress += P30_MAX_BUFFER_SIZE_IN_BYTES, DataBuffer += P30_MAX_BUFFER_SIZE_IN_WORDS
+ )
+ {
+ // Check the buffer to see if it contains any data (not set all 1s).
+ for (Cnt = 0; Cnt < P30_MAX_BUFFER_SIZE_IN_WORDS; Cnt++) {
+ if (~DataBuffer[Cnt] != 0 ) {
+ // Some data found, write the buffer.
+ Status = NorFlashWriteBuffer (
+ DeviceBaseAddress,
+ WordAddress,
+ P30_MAX_BUFFER_SIZE_IN_BYTES,
+ DataBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ goto EXIT;
+ }
+
+ break;
+ }
+ }
+ }
+
+ // 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 (DeviceBaseAddress, 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 (DeviceBaseAddress, WordAddress, *DataBuffer);
+ if (EFI_ERROR (Status)) {
+ goto EXIT;
+ }
+ }
+ }
+
+EXIT:
+ // Put device back into Read Array mode
+ SEND_NOR_COMMAND (DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "NOR FLASH Programming [WriteSingleBlock] failed at address 0x%08x. Exit Status = \"%r\".\n", WordAddress, Status));
}
return Status;
@@ -338,10 +460,13 @@ NorFlashWriteBuffer (
EFI_STATUS
NorFlashWriteBlocks (
- IN NOR_FLASH_INSTANCE *Instance,
- IN EFI_LBA Lba,
- IN UINTN BufferSizeInBytes,
- IN VOID *Buffer
+ IN UINTN DeviceBaseAddress,
+ IN UINTN RegionBaseAddress,
+ IN EFI_LBA Lba,
+ IN EFI_LBA LastBlock,
+ IN UINT32 BlockSize,
+ IN UINTN BufferSizeInBytes,
+ IN VOID *Buffer
)
{
UINT32 *pWriteBuffer;
@@ -365,22 +490,22 @@ NorFlashWriteBlocks (
}
// The size of the buffer must be a multiple of the block size
- DEBUG ((DEBUG_BLKIO, "NorFlashWriteBlocks: BlockSize in bytes =0x%x\n", Instance->BlockSize));
- if ((BufferSizeInBytes % Instance->BlockSize) != 0) {
+ DEBUG ((DEBUG_BLKIO, "NorFlashWriteBlocks: BlockSize in bytes =0x%x\n", BlockSize));
+ if ((BufferSizeInBytes % BlockSize) != 0) {
return EFI_BAD_BUFFER_SIZE;
}
// All blocks must be within the device
- NumBlocks = ((UINT32)BufferSizeInBytes) / Instance->BlockSize;
+ NumBlocks = ((UINT32)BufferSizeInBytes) / BlockSize;
- DEBUG ((DEBUG_BLKIO, "NorFlashWriteBlocks: NumBlocks=%d, LastBlock=%ld, Lba=%ld.\n", NumBlocks, Instance->LastBlock, Lba));
+ DEBUG ((DEBUG_BLKIO, "NorFlashWriteBlocks: NumBlocks=%d, LastBlock=%ld, Lba=%ld.\n", NumBlocks, LastBlock, Lba));
- if ((Lba + NumBlocks) > (Instance->LastBlock + 1)) {
+ if ((Lba + NumBlocks) > (LastBlock + 1)) {
DEBUG ((DEBUG_ERROR, "NorFlashWriteBlocks: ERROR - Write will exceed last block.\n"));
return EFI_INVALID_PARAMETER;
}
- BlockSizeInWords = Instance->BlockSize / 4;
+ BlockSizeInWords = 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
@@ -390,7 +515,13 @@ NorFlashWriteBlocks (
for (BlockCount = 0; BlockCount < NumBlocks; BlockCount++, CurrentBlock++, pWriteBuffer = pWriteBuffer + BlockSizeInWords) {
DEBUG ((DEBUG_BLKIO, "NorFlashWriteBlocks: Writing block #%d\n", (UINTN)CurrentBlock));
- Status = NorFlashWriteFullBlock (Instance, CurrentBlock, pWriteBuffer, BlockSizeInWords);
+ Status = NorFlashWriteFullBlock (
+ DeviceBaseAddress,
+ RegionBaseAddress,
+ CurrentBlock,
+ pWriteBuffer,
+ BlockSizeInWords
+ );
if (EFI_ERROR (Status)) {
break;
@@ -403,10 +534,13 @@ NorFlashWriteBlocks (
EFI_STATUS
NorFlashReadBlocks (
- IN NOR_FLASH_INSTANCE *Instance,
- IN EFI_LBA Lba,
- IN UINTN BufferSizeInBytes,
- OUT VOID *Buffer
+ IN UINTN DeviceBaseAddress,
+ IN UINTN RegionBaseAddress,
+ IN EFI_LBA Lba,
+ IN EFI_LBA LastBlock,
+ IN UINT32 BlockSize,
+ IN UINTN BufferSizeInBytes,
+ OUT VOID *Buffer
)
{
UINT32 NumBlocks;
@@ -416,8 +550,8 @@ NorFlashReadBlocks (
DEBUG_BLKIO,
"NorFlashReadBlocks: BufferSize=0x%xB BlockSize=0x%xB LastBlock=%ld, Lba=%ld.\n",
BufferSizeInBytes,
- Instance->BlockSize,
- Instance->LastBlock,
+ BlockSize,
+ LastBlock,
Lba
));
@@ -432,27 +566,27 @@ NorFlashReadBlocks (
}
// The size of the buffer must be a multiple of the block size
- if ((BufferSizeInBytes % Instance->BlockSize) != 0) {
+ if ((BufferSizeInBytes % BlockSize) != 0) {
return EFI_BAD_BUFFER_SIZE;
}
// All blocks must be within the device
- NumBlocks = ((UINT32)BufferSizeInBytes) / Instance->BlockSize;
+ NumBlocks = ((UINT32)BufferSizeInBytes) / BlockSize;
- if ((Lba + NumBlocks) > (Instance->LastBlock + 1)) {
+ if ((Lba + NumBlocks) > (LastBlock + 1)) {
DEBUG ((DEBUG_ERROR, "NorFlashReadBlocks: ERROR - Read will exceed last block\n"));
return EFI_INVALID_PARAMETER;
}
// Get the address to start reading from
StartAddress = GET_NOR_BLOCK_ADDRESS (
- Instance->RegionBaseAddress,
+ RegionBaseAddress,
Lba,
- Instance->BlockSize
+ BlockSize
);
// Put the device into Read Array mode
- SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);
+ SEND_NOR_COMMAND (DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);
// Readout the data
CopyMem (Buffer, (VOID *)StartAddress, BufferSizeInBytes);
@@ -462,11 +596,14 @@ NorFlashReadBlocks (
EFI_STATUS
NorFlashRead (
- IN NOR_FLASH_INSTANCE *Instance,
- IN EFI_LBA Lba,
- IN UINTN Offset,
- IN UINTN BufferSizeInBytes,
- OUT VOID *Buffer
+ IN UINTN DeviceBaseAddress,
+ IN UINTN RegionBaseAddress,
+ IN EFI_LBA Lba,
+ IN UINT32 BlockSize,
+ IN UINTN Size,
+ IN UINTN Offset,
+ IN UINTN BufferSizeInBytes,
+ OUT VOID *Buffer
)
{
UINTN StartAddress;
@@ -481,20 +618,20 @@ NorFlashRead (
return EFI_SUCCESS;
}
- if (((Lba * Instance->BlockSize) + Offset + BufferSizeInBytes) > Instance->Size) {
+ if (((Lba * BlockSize) + Offset + BufferSizeInBytes) > Size) {
DEBUG ((DEBUG_ERROR, "NorFlashRead: ERROR - Read will exceed device size.\n"));
return EFI_INVALID_PARAMETER;
}
// Get the address to start reading from
StartAddress = GET_NOR_BLOCK_ADDRESS (
- Instance->RegionBaseAddress,
+ RegionBaseAddress,
Lba,
- Instance->BlockSize
+ BlockSize
);
// Put the device into Read Array mode
- SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);
+ SEND_NOR_COMMAND (DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);
// Readout the data
CopyMem (Buffer, (VOID *)(StartAddress + Offset), BufferSizeInBytes);
@@ -505,27 +642,47 @@ NorFlashRead (
STATIC
EFI_STATUS
NorFlashWriteSingleBlockWithErase (
- IN NOR_FLASH_INSTANCE *Instance,
- IN EFI_LBA Lba,
- IN UINTN Offset,
- IN OUT UINTN *NumBytes,
- IN UINT8 *Buffer
+ IN UINTN DeviceBaseAddress,
+ IN UINTN RegionBaseAddress,
+ IN EFI_LBA Lba,
+ IN UINT32 LastBlock,
+ IN UINT32 BlockSize,
+ IN UINTN Offset,
+ IN OUT UINTN *NumBytes,
+ IN UINT8 *Buffer,
+ IN VOID *ShadowBuffer
)
{
EFI_STATUS Status;
// Read NOR Flash data into shadow buffer
- Status = NorFlashReadBlocks (Instance, Lba, Instance->BlockSize, Instance->ShadowBuffer);
+ Status = NorFlashReadBlocks (
+ DeviceBaseAddress,
+ RegionBaseAddress,
+ Lba,
+ LastBlock,
+ BlockSize,
+ BlockSize,
+ ShadowBuffer
+ );
if (EFI_ERROR (Status)) {
// Return one of the pre-approved error statuses
return EFI_DEVICE_ERROR;
}
// Put the data at the appropriate location inside the buffer area
- CopyMem ((VOID *)((UINTN)Instance->ShadowBuffer + Offset), Buffer, *NumBytes);
+ CopyMem ((VOID *)((UINTN)ShadowBuffer + Offset), Buffer, *NumBytes);
// Write the modified buffer back to the NorFlash
- Status = NorFlashWriteBlocks (Instance, Lba, Instance->BlockSize, Instance->ShadowBuffer);
+ Status = NorFlashWriteBlocks (
+ DeviceBaseAddress,
+ RegionBaseAddress,
+ Lba,
+ LastBlock,
+ BlockSize,
+ BlockSize,
+ ShadowBuffer
+ );
if (EFI_ERROR (Status)) {
// Return one of the pre-approved error statuses
return EFI_DEVICE_ERROR;
@@ -540,16 +697,20 @@ NorFlashWriteSingleBlockWithErase (
*/
EFI_STATUS
NorFlashWriteSingleBlock (
- IN NOR_FLASH_INSTANCE *Instance,
- IN EFI_LBA Lba,
- IN UINTN Offset,
- IN OUT UINTN *NumBytes,
- IN UINT8 *Buffer
+ IN UINTN DeviceBaseAddress,
+ IN UINTN RegionBaseAddress,
+ IN EFI_LBA Lba,
+ IN UINT32 LastBlock,
+ IN UINT32 BlockSize,
+ IN UINTN Size,
+ IN UINTN Offset,
+ IN OUT UINTN *NumBytes,
+ IN UINT8 *Buffer,
+ IN VOID *ShadowBuffer
)
{
EFI_STATUS Status;
UINTN CurOffset;
- UINTN BlockSize;
UINTN BlockAddress;
UINT8 *OrigData;
UINTN Start, End;
@@ -558,14 +719,11 @@ NorFlashWriteSingleBlock (
DEBUG ((DEBUG_BLKIO, "NorFlashWriteSingleBlock(Parameters: Lba=%ld, Offset=0x%x, *NumBytes=0x%x, Buffer @ 0x%08x)\n", Lba, Offset, *NumBytes, Buffer));
// Check we did get some memory. Buffer is BlockSize.
- if (Instance->ShadowBuffer == NULL) {
+ if (ShadowBuffer == NULL) {
DEBUG ((DEBUG_ERROR, "FvbWrite: ERROR - Buffer not ready\n"));
return EFI_DEVICE_ERROR;
}
- // Cache the block size to avoid de-referencing pointers all the time
- BlockSize = Instance->BlockSize;
-
// The write must not span block boundaries.
// We need to check each variable individually because adding two large values together overflows.
if ((Offset >= BlockSize) ||
@@ -620,11 +778,14 @@ NorFlashWriteSingleBlock (
// Read the old version of the data into the shadow buffer
Status = NorFlashRead (
- Instance,
+ DeviceBaseAddress,
+ RegionBaseAddress,
Lba,
+ BlockSize,
+ Size,
Start,
End - Start,
- Instance->ShadowBuffer
+ ShadowBuffer
);
if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR;
@@ -632,7 +793,7 @@ NorFlashWriteSingleBlock (
// Make OrigData point to the start of the old version of the data inside
// the word aligned buffer
- OrigData = Instance->ShadowBuffer + (Offset & BOUNDARY_OF_32_WORDS);
+ OrigData = ShadowBuffer + (Offset & BOUNDARY_OF_32_WORDS);
// Update the buffer containing the old version of the data with the new
// contents, while checking whether the old version had any bits cleared
@@ -640,11 +801,15 @@ NorFlashWriteSingleBlock (
for (CurOffset = 0; CurOffset < *NumBytes; CurOffset++) {
if (~(UINT32)OrigData[CurOffset] & (UINT32)Buffer[CurOffset]) {
Status = NorFlashWriteSingleBlockWithErase (
- Instance,
+ DeviceBaseAddress,
+ RegionBaseAddress,
Lba,
+ LastBlock,
+ BlockSize,
Offset,
NumBytes,
- Buffer
+ Buffer,
+ ShadowBuffer
);
return Status;
}
@@ -655,10 +820,10 @@ NorFlashWriteSingleBlock (
//
// Write the updated buffer to NOR.
//
- BlockAddress = GET_NOR_BLOCK_ADDRESS (Instance->RegionBaseAddress, Lba, BlockSize);
+ BlockAddress = GET_NOR_BLOCK_ADDRESS (RegionBaseAddress, Lba, BlockSize);
// Unlock the block if we have to
- Status = NorFlashUnlockSingleBlockIfNecessary (Instance, BlockAddress);
+ Status = NorFlashUnlockSingleBlockIfNecessary (DeviceBaseAddress, BlockAddress);
if (EFI_ERROR (Status)) {
goto Exit;
}
@@ -666,10 +831,10 @@ NorFlashWriteSingleBlock (
Count = (End - Start) / P30_MAX_BUFFER_SIZE_IN_BYTES;
for (Index = 0; Index < Count; Index++) {
Status = NorFlashWriteBuffer (
- Instance,
+ DeviceBaseAddress,
BlockAddress + Start + Index * P30_MAX_BUFFER_SIZE_IN_BYTES,
P30_MAX_BUFFER_SIZE_IN_BYTES,
- Instance->ShadowBuffer + Index * P30_MAX_BUFFER_SIZE_IN_BYTES
+ ShadowBuffer + Index * P30_MAX_BUFFER_SIZE_IN_BYTES
);
if (EFI_ERROR (Status)) {
goto Exit;
@@ -677,66 +842,32 @@ NorFlashWriteSingleBlock (
}
} else {
Status = NorFlashWriteSingleBlockWithErase (
- Instance,
+ DeviceBaseAddress,
+ RegionBaseAddress,
Lba,
+ LastBlock,
+ BlockSize,
Offset,
NumBytes,
- Buffer
+ Buffer,
+ ShadowBuffer
);
return Status;
}
Exit:
// Put device back into Read Array mode
- SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);
+ SEND_NOR_COMMAND (DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);
return Status;
}
EFI_STATUS
NorFlashReset (
- IN NOR_FLASH_INSTANCE *Instance
+ IN UINTN DeviceBaseAddress
)
{
// As there is no specific RESET to perform, ensure that the devices is in the default Read Array mode
- SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);
+ SEND_NOR_COMMAND (DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);
return EFI_SUCCESS;
}
-
-/**
- Fixup internal data so that EFI can be call in virtual mode.
- Call the passed in Child Notify event and convert any pointers in
- lib to virtual mode.
-
- @param[in] Event The Event that is being processed
- @param[in] Context Event Context
-**/
-VOID
-EFIAPI
-NorFlashVirtualNotifyEvent (
- IN EFI_EVENT Event,
- IN VOID *Context
- )
-{
- UINTN Index;
-
- for (Index = 0; Index < mNorFlashDeviceCount; Index++) {
- EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->DeviceBaseAddress);
- EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->RegionBaseAddress);
-
- // Convert Fvb
- EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->FvbProtocol.EraseBlocks);
- EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->FvbProtocol.GetAttributes);
- EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->FvbProtocol.GetBlockSize);
- EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->FvbProtocol.GetPhysicalAddress);
- EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->FvbProtocol.Read);
- EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->FvbProtocol.SetAttributes);
- EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->FvbProtocol.Write);
-
- if (mNorFlashInstances[Index]->ShadowBuffer != NULL) {
- EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->ShadowBuffer);
- }
- }
-
- return;
-}
diff --git a/OvmfPkg/Library/VirtNorFlashDeviceLib/VirtNorFlashDeviceLib.inf b/OvmfPkg/Library/VirtNorFlashDeviceLib/VirtNorFlashDeviceLib.inf
new file mode 100644
index 000000000000..f99c8fb6b33a
--- /dev/null
+++ b/OvmfPkg/Library/VirtNorFlashDeviceLib/VirtNorFlashDeviceLib.inf
@@ -0,0 +1,30 @@
+#/** @file
+#
+# Component description file for NorFlashDxe module
+#
+# Copyright (c) 2011 - 2021, Arm Limited. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#**/
+
+[Defines]
+ INF_VERSION = 1.29
+ BASE_NAME = VirtNorFlashDeviceLib
+ FILE_GUID = 3f8c8c4b-5b92-4e71-ae73-9f7d2f1e33d4
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = VirtNorFlashDeviceLib
+
+[Sources.common]
+ VirtNorFlashDeviceLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ OvmfPkg/OvmfPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ IoLib
diff --git a/OvmfPkg/LoongArchVirt/LoongArchVirtQemu.dsc b/OvmfPkg/LoongArchVirt/LoongArchVirtQemu.dsc
index 89abdf9f779e..27a2d1baf5df 100644
--- a/OvmfPkg/LoongArchVirt/LoongArchVirtQemu.dsc
+++ b/OvmfPkg/LoongArchVirt/LoongArchVirtQemu.dsc
@@ -507,7 +507,10 @@
#
# Variable
#
- OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.inf
+ OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.inf {
+ <LibraryClasses>
+ VirtNorFlashDeviceLib|OvmfPkg/Library/VirtNorFlashDeviceLib/VirtNorFlashDeviceLib.inf
+ }
MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf {
<LibraryClasses>
NULL|EmbeddedPkg/Library/NvVarStoreFormattedLib/NvVarStoreFormattedLib.inf
diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec
index 1703f5063711..529983af1923 100644
--- a/OvmfPkg/OvmfPkg.dec
+++ b/OvmfPkg/OvmfPkg.dec
@@ -120,6 +120,10 @@
# transports.
VirtioMmioDeviceLib|Include/Library/VirtioMmioDeviceLib.h
+ ## @libraryclass Provides a Device Nor flash interface.
+ #
+ VirtNorFlashDeviceLib|Include/Library/VirtNorFlashDeviceLib.h
+
## @libraryclass Provides a Nor flash interface.
#
VirtNorFlashPlatformLib|Include/Library/VirtNorFlashPlatformLib.h
diff --git a/OvmfPkg/RiscVVirt/RiscVVirtQemu.dsc b/OvmfPkg/RiscVVirt/RiscVVirtQemu.dsc
index ca211b3db356..8e864e123f08 100644
--- a/OvmfPkg/RiscVVirt/RiscVVirtQemu.dsc
+++ b/OvmfPkg/RiscVVirt/RiscVVirtQemu.dsc
@@ -324,7 +324,10 @@
MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf
UefiCpuPkg/CpuTimerDxeRiscV64/CpuTimerDxeRiscV64.inf
- OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.inf
+ OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.inf {
+ <LibraryClasses>
+ VirtNorFlashDeviceLib|OvmfPkg/Library/VirtNorFlashDeviceLib/VirtNorFlashDeviceLib.inf
+ }
MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
#
diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.h b/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.h
deleted file mode 100644
index 455eafacc2cf..000000000000
--- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.h
+++ /dev/null
@@ -1,345 +0,0 @@
-/** @file NorFlash.h
-
- Copyright (c) 2011 - 2014, ARM Ltd. All rights reserved.<BR>
-
- SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#ifndef __VIRT_NOR_FLASH__
-#define __VIRT_NOR_FLASH__
-
-#include <Base.h>
-#include <PiDxe.h>
-
-#include <Guid/EventGroup.h>
-
-#include <Protocol/FirmwareVolumeBlock.h>
-
-#include <Library/DebugLib.h>
-#include <Library/IoLib.h>
-#include <Library/UefiLib.h>
-#include <Library/UefiRuntimeLib.h>
-#include <Library/VirtNorFlashPlatformLib.h>
-
-#define NOR_FLASH_ERASE_RETRY 10
-
-// Device access macros
-// These are necessary because we use 2 x 16bit parts to make up 32bit data
-
-#define HIGH_16_BITS 0xFFFF0000
-#define LOW_16_BITS 0x0000FFFF
-#define LOW_8_BITS 0x000000FF
-
-#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, Offset, Cmd) MmioWrite32 (CREATE_NOR_ADDRESS(BaseAddr,Offset), 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 ((UINTN)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)
-
-typedef struct _NOR_FLASH_INSTANCE NOR_FLASH_INSTANCE;
-
-#pragma pack (1)
-typedef struct {
- VENDOR_DEVICE_PATH Vendor;
- UINT8 Index;
- EFI_DEVICE_PATH_PROTOCOL End;
-} NOR_FLASH_DEVICE_PATH;
-#pragma pack ()
-
-struct _NOR_FLASH_INSTANCE {
- UINT32 Signature;
- EFI_HANDLE Handle;
-
- UINTN DeviceBaseAddress;
- UINTN RegionBaseAddress;
- UINTN Size;
- EFI_LBA StartLba;
- EFI_LBA LastBlock;
- UINT32 BlockSize;
-
- EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL FvbProtocol;
- VOID *ShadowBuffer;
-
- NOR_FLASH_DEVICE_PATH DevicePath;
-};
-
-EFI_STATUS
-NorFlashReadCfiData (
- IN UINTN DeviceBaseAddress,
- IN UINTN CFI_Offset,
- IN UINT32 NumberOfBytes,
- OUT UINT32 *Data
- );
-
-EFI_STATUS
-NorFlashWriteBuffer (
- IN NOR_FLASH_INSTANCE *Instance,
- IN UINTN TargetAddress,
- IN UINTN BufferSizeInBytes,
- IN UINT32 *Buffer
- );
-
-//
-// NorFlashFvbDxe.c
-//
-
-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,
- ...
- );
-
-EFI_STATUS
-ValidateFvHeader (
- IN NOR_FLASH_INSTANCE *Instance
- );
-
-EFI_STATUS
-InitializeFvAndVariableStoreHeaders (
- IN NOR_FLASH_INSTANCE *Instance
- );
-
-VOID
-EFIAPI
-FvbVirtualNotifyEvent (
- IN EFI_EVENT Event,
- IN VOID *Context
- );
-
-//
-// NorFlashDxe.c
-//
-
-EFI_STATUS
-NorFlashWriteFullBlock (
- IN NOR_FLASH_INSTANCE *Instance,
- IN EFI_LBA Lba,
- IN UINT32 *DataBuffer,
- IN UINT32 BlockSizeInWords
- );
-
-EFI_STATUS
-NorFlashUnlockAndEraseSingleBlock (
- IN NOR_FLASH_INSTANCE *Instance,
- IN UINTN BlockAddress
- );
-
-EFI_STATUS
-NorFlashCreateInstance (
- IN UINTN NorFlashDeviceBase,
- IN UINTN NorFlashRegionBase,
- IN UINTN NorFlashSize,
- IN UINT32 Index,
- IN UINT32 BlockSize,
- IN BOOLEAN SupportFvb,
- OUT NOR_FLASH_INSTANCE **NorFlashInstance
- );
-
-EFI_STATUS
-EFIAPI
-NorFlashFvbInitialize (
- IN NOR_FLASH_INSTANCE *Instance
- );
-
-//
-// NorFlash.c
-//
-EFI_STATUS
-NorFlashWriteSingleBlock (
- IN NOR_FLASH_INSTANCE *Instance,
- IN EFI_LBA Lba,
- IN UINTN Offset,
- IN OUT UINTN *NumBytes,
- IN UINT8 *Buffer
- );
-
-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
-NorFlashRead (
- IN NOR_FLASH_INSTANCE *Instance,
- IN EFI_LBA Lba,
- IN UINTN Offset,
- IN UINTN BufferSizeInBytes,
- OUT VOID *Buffer
- );
-
-EFI_STATUS
-NorFlashWrite (
- IN NOR_FLASH_INSTANCE *Instance,
- IN EFI_LBA Lba,
- IN UINTN Offset,
- IN OUT UINTN *NumBytes,
- IN UINT8 *Buffer
- );
-
-EFI_STATUS
-NorFlashReset (
- IN NOR_FLASH_INSTANCE *Instance
- );
-
-EFI_STATUS
-NorFlashEraseSingleBlock (
- IN NOR_FLASH_INSTANCE *Instance,
- IN UINTN BlockAddress
- );
-
-EFI_STATUS
-NorFlashUnlockSingleBlockIfNecessary (
- IN NOR_FLASH_INSTANCE *Instance,
- IN UINTN BlockAddress
- );
-
-EFI_STATUS
-NorFlashWriteSingleWord (
- IN NOR_FLASH_INSTANCE *Instance,
- IN UINTN WordAddress,
- IN UINT32 WriteData
- );
-
-VOID
-EFIAPI
-NorFlashVirtualNotifyEvent (
- IN EFI_EVENT Event,
- IN VOID *Context
- );
-
-#endif /* __VIRT_NOR_FLASH__ */
diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.c b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.c
index 6b9ef261335e..1b46d2690108 100644
--- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.c
+++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.c
@@ -1,4 +1,4 @@
-/** @file NorFlashDxe.c
+/** @file VirtNorFlashDxe.c
Copyright (c) 2011 - 2021, Arm Limited. All rights reserved.<BR>
@@ -14,7 +14,7 @@
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiLib.h>
-#include "VirtNorFlash.h"
+#include "VirtNorFlashDxe.h"
STATIC EFI_EVENT mNorFlashVirtualAddrChangeEvent;
@@ -138,161 +138,41 @@ NorFlashCreateInstance (
}
/**
- * This function unlock and erase an entire NOR Flash block.
- **/
-EFI_STATUS
-NorFlashUnlockAndEraseSingleBlock (
- IN NOR_FLASH_INSTANCE *Instance,
- IN UINTN BlockAddress
- )
-{
- EFI_STATUS Status;
- UINTN Index;
- EFI_TPL OriginalTPL;
-
- if (!EfiAtRuntime ()) {
- // Raise TPL to TPL_HIGH to stop anyone from interrupting us.
- OriginalTPL = gBS->RaiseTPL (TPL_HIGH_LEVEL);
- } else {
- // This initialization is only to prevent the compiler to complain about the
- // use of uninitialized variables
- OriginalTPL = TPL_HIGH_LEVEL;
- }
+ Fixup internal data so that EFI can be call in virtual mode.
+ Call the passed in Child Notify event and convert any pointers in
+ lib to virtual mode.
- Index = 0;
- // The block erase might fail a first time (SW bug ?). Retry it ...
- do {
- // Unlock the block if we have to
- Status = NorFlashUnlockSingleBlockIfNecessary (Instance, BlockAddress);
- if (EFI_ERROR (Status)) {
- break;
- }
-
- Status = NorFlashEraseSingleBlock (Instance, BlockAddress);
- Index++;
- } while ((Index < NOR_FLASH_ERASE_RETRY) && (Status == EFI_WRITE_PROTECTED));
-
- if (Index == NOR_FLASH_ERASE_RETRY) {
- DEBUG ((DEBUG_ERROR, "EraseSingleBlock(BlockAddress=0x%08x: Block Locked Error (try to erase %d times)\n", BlockAddress, Index));
- }
-
- if (!EfiAtRuntime ()) {
- // Interruptions can resume.
- gBS->RestoreTPL (OriginalTPL);
- }
-
- return Status;
-}
-
-EFI_STATUS
-NorFlashWriteFullBlock (
- IN NOR_FLASH_INSTANCE *Instance,
- IN EFI_LBA Lba,
- IN UINT32 *DataBuffer,
- IN UINT32 BlockSizeInWords
+ @param[in] Event The Event that is being processed
+ @param[in] Context Event Context
+**/
+VOID
+EFIAPI
+NorFlashVirtualNotifyEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
)
{
- EFI_STATUS Status;
- UINTN WordAddress;
- UINT32 WordIndex;
- UINTN BufferIndex;
- UINTN BlockAddress;
- UINTN BuffersInBlock;
- UINTN RemainingWords;
- EFI_TPL OriginalTPL;
- UINTN Cnt;
-
- Status = EFI_SUCCESS;
-
- // Get the physical address of the block
- BlockAddress = GET_NOR_BLOCK_ADDRESS (Instance->RegionBaseAddress, Lba, BlockSizeInWords * 4);
-
- // Start writing from the first address at the start of the block
- WordAddress = BlockAddress;
-
- if (!EfiAtRuntime ()) {
- // Raise TPL to TPL_HIGH to stop anyone from interrupting us.
- OriginalTPL = gBS->RaiseTPL (TPL_HIGH_LEVEL);
- } else {
- // This initialization is only to prevent the compiler to complain about the
- // use of uninitialized variables
- OriginalTPL = TPL_HIGH_LEVEL;
- }
-
- Status = NorFlashUnlockAndEraseSingleBlock (Instance, BlockAddress);
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "WriteSingleBlock: ERROR - Failed to Unlock and Erase the single block at 0x%X\n", BlockAddress));
- goto EXIT;
- }
-
- // To speed up the programming operation, NOR Flash is programmed using the Buffered Programming method.
-
- // 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 * 4) / P30_MAX_BUFFER_SIZE_IN_BYTES;
-
- // Then feed each buffer chunk to the NOR Flash
- // If a buffer does not contain any data, don't write it.
- for (BufferIndex = 0;
- BufferIndex < BuffersInBlock;
- BufferIndex++, WordAddress += P30_MAX_BUFFER_SIZE_IN_BYTES, DataBuffer += P30_MAX_BUFFER_SIZE_IN_WORDS
- )
- {
- // Check the buffer to see if it contains any data (not set all 1s).
- for (Cnt = 0; Cnt < P30_MAX_BUFFER_SIZE_IN_WORDS; Cnt++) {
- if (~DataBuffer[Cnt] != 0 ) {
- // Some data found, write the buffer.
- Status = NorFlashWriteBuffer (
- Instance,
- WordAddress,
- P30_MAX_BUFFER_SIZE_IN_BYTES,
- DataBuffer
- );
- if (EFI_ERROR (Status)) {
- goto EXIT;
- }
-
- break;
- }
- }
- }
-
- // Finally, finish off any remaining words that are less than the maximum size of the buffer
- RemainingWords = BlockSizeInWords % P30_MAX_BUFFER_SIZE_IN_WORDS;
+ UINTN Index;
- if (RemainingWords != 0) {
- Status = NorFlashWriteBuffer (Instance, 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 (Instance, WordAddress, *DataBuffer);
- if (EFI_ERROR (Status)) {
- goto EXIT;
- }
+ for (Index = 0; Index < mNorFlashDeviceCount; Index++) {
+ EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->DeviceBaseAddress);
+ EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->RegionBaseAddress);
+
+ // Convert Fvb
+ EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->FvbProtocol.EraseBlocks);
+ EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->FvbProtocol.GetAttributes);
+ EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->FvbProtocol.GetBlockSize);
+ EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->FvbProtocol.GetPhysicalAddress);
+ EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->FvbProtocol.Read);
+ EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->FvbProtocol.SetAttributes);
+ EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->FvbProtocol.Write);
+
+ if (mNorFlashInstances[Index]->ShadowBuffer != NULL) {
+ EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->ShadowBuffer);
}
}
-EXIT:
- // Put device back into Read Array mode
- SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);
-
- if (!EfiAtRuntime ()) {
- // Interruptions can resume.
- gBS->RestoreTPL (OriginalTPL);
- }
-
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "NOR FLASH Programming [WriteSingleBlock] failed at address 0x%08x. Exit Status = \"%r\".\n", WordAddress, Status));
- }
-
- return Status;
+ return;
}
EFI_STATUS
diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.h b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.h
new file mode 100644
index 000000000000..3c7f5094153f
--- /dev/null
+++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.h
@@ -0,0 +1,156 @@
+/** @file VirtNorFlashDxe.h
+
+ Copyright (c) 2011 - 2021, Arm Limited. All rights reserved.<BR>
+ Copyright (c) 2025, Ventana Micro Systems Inc. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __VIRT_NOR_FLASH_DXE__
+#define __VIRT_NOR_FLASH_DXE__
+
+#include <Base.h>
+#include <PiDxe.h>
+
+#include <Guid/EventGroup.h>
+
+#include <Protocol/FirmwareVolumeBlock.h>
+
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiRuntimeLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/VirtNorFlashDeviceLib.h>
+#include <Library/VirtNorFlashPlatformLib.h>
+
+#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)
+
+typedef struct _NOR_FLASH_INSTANCE NOR_FLASH_INSTANCE;
+
+#pragma pack (1)
+typedef struct {
+ VENDOR_DEVICE_PATH Vendor;
+ UINT8 Index;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} NOR_FLASH_DEVICE_PATH;
+#pragma pack ()
+
+struct _NOR_FLASH_INSTANCE {
+ UINT32 Signature;
+ EFI_HANDLE Handle;
+
+ UINTN DeviceBaseAddress;
+ UINTN RegionBaseAddress;
+ UINTN Size;
+ EFI_LBA StartLba;
+ EFI_LBA LastBlock;
+ UINT32 BlockSize;
+
+ EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL FvbProtocol;
+ VOID *ShadowBuffer;
+
+ NOR_FLASH_DEVICE_PATH DevicePath;
+};
+
+//
+// NorFlashFvbDxe.c
+//
+
+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,
+ ...
+ );
+
+EFI_STATUS
+ValidateFvHeader (
+ IN NOR_FLASH_INSTANCE *Instance
+ );
+
+EFI_STATUS
+InitializeFvAndVariableStoreHeaders (
+ IN NOR_FLASH_INSTANCE *Instance
+ );
+
+VOID
+EFIAPI
+FvbVirtualNotifyEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+//
+// NorFlashDxe.c
+//
+EFI_STATUS
+NorFlashCreateInstance (
+ IN UINTN NorFlashDeviceBase,
+ IN UINTN NorFlashRegionBase,
+ IN UINTN NorFlashSize,
+ IN UINT32 Index,
+ IN UINT32 BlockSize,
+ IN BOOLEAN SupportFvb,
+ OUT NOR_FLASH_INSTANCE **NorFlashInstance
+ );
+
+EFI_STATUS
+EFIAPI
+NorFlashFvbInitialize (
+ IN NOR_FLASH_INSTANCE *Instance
+ );
+
+#endif /* __VIRT_NOT_FLASH_DXE__ */
diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.inf b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.inf
index f549400280a1..6d6d615a6219 100644
--- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.inf
+++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.inf
@@ -17,8 +17,6 @@
ENTRY_POINT = NorFlashInitialise
[Sources.common]
- VirtNorFlash.c
- VirtNorFlash.h
VirtNorFlashDxe.c
VirtNorFlashFvb.c
@@ -39,6 +37,7 @@
UefiDriverEntryPoint
UefiLib
UefiRuntimeLib
+ VirtNorFlashDeviceLib
VirtNorFlashPlatformLib
[Guids]
diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashFvb.c b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashFvb.c
index c8b5e0be1379..0d6c9ef01631 100644
--- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashFvb.c
+++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashFvb.c
@@ -19,7 +19,7 @@
#include <Guid/SystemNvDataGuid.h>
#include <Guid/VariableFormat.h>
-#include "VirtNorFlash.h"
+#include "VirtNorFlashDxe.h"
extern UINTN mFlashNvStorageVariableBase;
///
@@ -653,13 +653,30 @@ FvbRead (
// Decide if we are doing full block reads or not.
if (*NumBytes % BlockSize != 0) {
- TempStatus = NorFlashRead (Instance, Instance->StartLba + Lba, Offset, *NumBytes, Buffer);
+ TempStatus = NorFlashRead (
+ Instance->DeviceBaseAddress,
+ Instance->RegionBaseAddress,
+ Instance->StartLba + Lba,
+ Instance->BlockSize,
+ Instance->Size,
+ Offset,
+ *NumBytes,
+ Buffer
+ );
if (EFI_ERROR (TempStatus)) {
return EFI_DEVICE_ERROR;
}
} else {
// Read NOR Flash data into shadow buffer
- TempStatus = NorFlashReadBlocks (Instance, Instance->StartLba + Lba, BlockSize, Buffer);
+ TempStatus = NorFlashReadBlocks (
+ Instance->DeviceBaseAddress,
+ Instance->RegionBaseAddress,
+ Instance->StartLba + Lba,
+ Instance->LastBlock,
+ Instance->BlockSize,
+ BlockSize,
+ Buffer
+ );
if (EFI_ERROR (TempStatus)) {
// Return one of the pre-approved error statuses
return EFI_DEVICE_ERROR;
@@ -737,7 +754,18 @@ FvbWrite (
Instance = INSTANCE_FROM_FVB_THIS (This);
- return NorFlashWriteSingleBlock (Instance, Instance->StartLba + Lba, Offset, NumBytes, Buffer);
+ return NorFlashWriteSingleBlock (
+ Instance->DeviceBaseAddress,
+ Instance->RegionBaseAddress,
+ Instance->StartLba + Lba,
+ Instance->LastBlock,
+ Instance->BlockSize,
+ Instance->Size,
+ Offset,
+ NumBytes,
+ Buffer,
+ Instance->ShadowBuffer
+ );
}
/**
@@ -795,6 +823,7 @@ FvbEraseBlocks (
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
+ EFI_TPL OriginalTPL;
NOR_FLASH_INSTANCE *Instance;
Instance = INSTANCE_FROM_FVB_THIS (This);
@@ -865,7 +894,21 @@ FvbEraseBlocks (
// Erase it
DEBUG ((DEBUG_BLKIO, "FvbEraseBlocks: Erasing Lba=%ld @ 0x%08x.\n", Instance->StartLba + StartingLba, BlockAddress));
- Status = NorFlashUnlockAndEraseSingleBlock (Instance, BlockAddress);
+ if (!EfiAtRuntime ()) {
+ // Raise TPL to TPL_HIGH to stop anyone from interrupting us.
+ OriginalTPL = gBS->RaiseTPL (TPL_HIGH_LEVEL);
+ } else {
+ // This initialization is only to prevent the compiler to complain about the
+ // use of uninitialized variables
+ OriginalTPL = TPL_HIGH_LEVEL;
+ }
+
+ Status = NorFlashUnlockAndEraseSingleBlock (Instance->DeviceBaseAddress, BlockAddress);
+ if (!EfiAtRuntime ()) {
+ // Interruptions can resume.
+ gBS->RestoreTPL (OriginalTPL);
+ }
+
if (EFI_ERROR (Status)) {
VA_END (Args);
Status = EFI_DEVICE_ERROR;
--
2.34.1
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#121276): https://edk2.groups.io/g/devel/message/121276
Mute This Topic: https://groups.io/mt/112379038/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-
next prev parent reply other threads:[~2025-04-21 16:58 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-04-21 16:58 [edk2-devel] [PATCH 0/3] OvmfPkg/RiscVVirt: Add support for Capsule Firmware Upgrade Tuan Phan
2025-04-21 16:58 ` Tuan Phan [this message]
2025-04-21 16:58 ` [edk2-devel] [PATCH 2/3] ArmVirtPkg: Link all targets to the new VirtNorFlashDeviceLib Tuan Phan
2025-04-21 16:58 ` [edk2-devel] [PATCH 3/3] OvmfPkg/RiscVVirt: Add support for Capsule Firmware Upgrade Tuan Phan
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250421165819.18451-2-tphan@ventanamicro.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox