From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail05.groups.io (mail05.groups.io [45.79.224.7]) by spool.mail.gandi.net (Postfix) with ESMTPS id 40BF7941A82 for ; Mon, 21 Apr 2025 16:58:42 +0000 (UTC) DKIM-Signature: a=rsa-sha256; bh=CtOzu1shXMJNwogbeiSe7M0P6uOz0T54UZjspcxTnD4=; c=relaxed/simple; d=groups.io; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References:MIME-Version:Precedence:List-Subscribe:List-Help:Sender:List-Id:Mailing-List:Delivered-To:Resent-Date:Resent-From:Reply-To:List-Unsubscribe-Post:List-Unsubscribe:Content-Transfer-Encoding; s=20240830; t=1745254721; v=1; x=1745513920; b=WxP/7jVWzIN1VoDkt3Xh6m2Xu9Sn5TGvx+Op+kBu9dC6KXp7dqj0kjxW9GREEEgnYxZlW8kA JvTUkWo/B+XHuCqjuUPHKeW5BKMyR3xrnifXUWV8f1IBOpv3y3NoImBynyDhcS3DRIOJFRASN2p +/2zYmiI9E3A+lnBlXh0DZXVL+NmAhWm790KhgHEOJb9bocArQ/hfXhAElOr1PUKDwxe9QJz2TQ 8pepzMpv4FBK1LxvosiYBO0NkEKUS1e2DtSFC2KG3CbYYUfgiKRhpBkkhFYDiiE4xSF+weDqH2M Ov0AJ/b3kM6coivXrGAAYf6TdpuQVIYcPDRHO9dc2OzxQ== X-Received: by 127.0.0.2 with SMTP id cU7dYY7687511xCEZzIpvMS6; Mon, 21 Apr 2025 09:58:40 -0700 X-Received: from mail-pf1-f175.google.com (mail-pf1-f175.google.com [209.85.210.175]) by mx.groups.io with SMTP id smtpd.web10.19894.1745254719691390298 for ; Mon, 21 Apr 2025 09:58:39 -0700 X-Received: by mail-pf1-f175.google.com with SMTP id d2e1a72fcca58-736aa9d0f2aso5024630b3a.0 for ; Mon, 21 Apr 2025 09:58:39 -0700 (PDT) X-Gm-Message-State: YjSLHkkH8Rl4oFsEcZftokGlx7686176AA= X-Gm-Gg: ASbGncvv3+oZ1YL8SwNgVXHwkcOAGvLYvtkE3/jgsGZrmKhQV5Q9j4E4KygZqgmbFfR rBIl+RKx1vojN9olVdQcG7qcwQ6umAsYG1phaKj6x3Ps3Cg/vz6MOvkVqpkXuYAiMVUAICZnh/l ta2y9eCwcik7aUlqecXkj1xZlnEBuhpddXMM9xr1I6MLxA+rIGZJOKHk7iFMgebcxjkwLW7jtwb WdHNjpVIEX7eQUKUh0XnheWhxHaF/rmFBDK8YFfb3e0srAdMlXxUoVQTnLljrCx/fV36xj6P4/r 8EWvfvBb39RmZLBmu7YzmmIvFtzBh2spQSk16+8fh3F/14TE8OZBVijyoebA0fFfxkSpeqGfTHT tu7xH1LvpRpvHCSlnIO7/Klz3cRq35m0cho4u0l8PMw== X-Google-Smtp-Source: AGHT+IFbdYtNnfLzdRlmHIfMta/AnZrylclaYm2rtlVVb+D0qDcgbQzt35fBdNV6Whv68Lish1h6Ag== X-Received: by 2002:a05:6a00:35cd:b0:736:a8db:93b8 with SMTP id d2e1a72fcca58-73dc14443dcmr16972752b3a.3.1745254718189; Mon, 21 Apr 2025 09:58:38 -0700 (PDT) X-Received: from DESKTOP-I1ETA6N.dc1.ventanamicro.com (c-174-50-177-196.hsd1.ca.comcast.net. [174.50.177.196]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-73dbfa59f87sm7055330b3a.91.2025.04.21.09.58.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 21 Apr 2025 09:58:37 -0700 (PDT) From: "Tuan Phan" 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 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 Message-Id: <20250421165819.18451-2-tphan@ventanamicro.com> In-Reply-To: <20250421165819.18451-1-tphan@ventanamicro.com> References: <20250421165819.18451-1-tphan@ventanamicro.com> MIME-Version: 1.0 Precedence: Bulk List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Resent-Date: Mon, 21 Apr 2025 09:58:40 -0700 Resent-From: tphan@ventanamicro.com Reply-To: devel@edk2.groups.io,tphan@ventanamicro.com List-Unsubscribe-Post: List-Unsubscribe=One-Click List-Unsubscribe: Content-Transfer-Encoding: quoted-printable X-GND-Status: LEGIT Authentication-Results: spool.mail.gandi.net; dkim=pass header.d=groups.io header.s=20240830 header.b="WxP/7jVW"; dmarc=none; spf=pass (spool.mail.gandi.net: domain of bounce@groups.io designates 45.79.224.7 as permitted sender) smtp.mailfrom=bounce@groups.io 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 --- .../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 =3D> Library/VirtNorFlashDe= viceLib/VirtNorFlashDeviceLib.c} (63%) create mode 100644 OvmfPkg/Library/VirtNorFlashDeviceLib/VirtNorFlashDevic= eLib.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/Incl= ude/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=0D +=0D + Copyright (c) 2011 - 2014, ARM Ltd. All rights reserved.
=0D + Copyright (c) 2025, Ventana Micro Systems Inc. All rights reserved.
= =0D +=0D + SPDX-License-Identifier: BSD-2-Clause-Patent=0D +=0D +**/=0D +=0D +#ifndef __VIRT_NOR_FLASH_DEVICE_LIB__=0D +#define __VIRT_NOR_FLASH_DEVICE_LIB__=0D +=0D +#include =0D +#include =0D +=0D +#include =0D +=0D +#include =0D +#include =0D +#include =0D +=0D +#define NOR_FLASH_ERASE_RETRY 10=0D +=0D +// Device access macros=0D +// These are necessary because we use 2 x 16bit parts to make up 32bit dat= a=0D +=0D +#define HIGH_16_BITS 0xFFFF0000=0D +#define LOW_16_BITS 0x0000FFFF=0D +#define LOW_8_BITS 0x000000FF=0D +=0D +#define FOLD_32BIT_INTO_16BIT(value) ( ( value >> 16 ) | ( value & LOW_16= _BITS ) )=0D +=0D +#define GET_LOW_BYTE(value) ( value & LOW_8_BITS )=0D +#define GET_HIGH_BYTE(value) ( GET_LOW_BYTE( value >> 16 ) )=0D +=0D +// Each command must be sent simultaneously to both chips,=0D +// i.e. at the lower 16 bits AND at the higher 16 bits=0D +#define CREATE_NOR_ADDRESS(BaseAddr, OffsetAddr) ((BaseAddr) + ((Off= setAddr) << 2))=0D +#define CREATE_DUAL_CMD(Cmd) ( ( Cmd << 16) | ( = Cmd & LOW_16_BITS) )=0D +#define SEND_NOR_COMMAND(BaseAddr, Offset, Cmd) MmioWrite32 (CREATE= _NOR_ADDRESS(BaseAddr,Offset), CREATE_DUAL_CMD(Cmd))=0D +#define GET_NOR_BLOCK_ADDRESS(BaseAddr, Lba, LbaSize) ( BaseAddr + (UINTN= )((Lba) * LbaSize) )=0D +=0D +// Status Register Bits=0D +#define P30_SR_BIT_WRITE (BIT7 << 16 | BIT7)=0D +#define P30_SR_BIT_ERASE_SUSPEND (BIT6 << 16 | BIT6)=0D +#define P30_SR_BIT_ERASE (BIT5 << 16 | BIT5)=0D +#define P30_SR_BIT_PROGRAM (BIT4 << 16 | BIT4)=0D +#define P30_SR_BIT_VPP (BIT3 << 16 | BIT3)=0D +#define P30_SR_BIT_PROGRAM_SUSPEND (BIT2 << 16 | BIT2)=0D +#define P30_SR_BIT_BLOCK_LOCKED (BIT1 << 16 | BIT1)=0D +#define P30_SR_BIT_BEFP (BIT0 << 16 | BIT0)=0D +=0D +// Device Commands for Intel StrataFlash(R) Embedded Memory (P30) Family=0D +=0D +// On chip buffer size for buffered programming operations=0D +// There are 2 chips, each chip can buffer up to 32 (16-bit)words, and eac= h word is 2 bytes.=0D +// Therefore the total size of the buffer is 2 x 32 x 2 =3D 128 bytes=0D +#define P30_MAX_BUFFER_SIZE_IN_BYTES ((UINTN)128)=0D +#define P30_MAX_BUFFER_SIZE_IN_WORDS (P30_MAX_BUFFER_SIZE_IN_BYTES/((UINT= N)4))=0D +#define MAX_BUFFERED_PROG_ITERATIONS 10000000=0D +#define BOUNDARY_OF_32_WORDS ((UINTN)0x7F)=0D +=0D +// CFI Addresses=0D +#define P30_CFI_ADDR_QUERY_UNIQUE_QRY 0x10=0D +#define P30_CFI_ADDR_VENDOR_ID 0x13=0D +=0D +// CFI Data=0D +#define CFI_QRY 0x00595251=0D +=0D +// READ Commands=0D +#define P30_CMD_READ_DEVICE_ID 0x0090=0D +#define P30_CMD_READ_STATUS_REGISTER 0x0070=0D +#define P30_CMD_CLEAR_STATUS_REGISTER 0x0050=0D +#define P30_CMD_READ_ARRAY 0x00FF=0D +#define P30_CMD_READ_CFI_QUERY 0x0098=0D +=0D +// WRITE Commands=0D +#define P30_CMD_WORD_PROGRAM_SETUP 0x0040=0D +#define P30_CMD_ALTERNATE_WORD_PROGRAM_SETUP 0x0010=0D +#define P30_CMD_BUFFERED_PROGRAM_SETUP 0x00E8=0D +#define P30_CMD_BUFFERED_PROGRAM_CONFIRM 0x00D0=0D +#define P30_CMD_BEFP_SETUP 0x0080=0D +#define P30_CMD_BEFP_CONFIRM 0x00D0=0D +=0D +// ERASE Commands=0D +#define P30_CMD_BLOCK_ERASE_SETUP 0x0020=0D +#define P30_CMD_BLOCK_ERASE_CONFIRM 0x00D0=0D +=0D +// SUSPEND Commands=0D +#define P30_CMD_PROGRAM_OR_ERASE_SUSPEND 0x00B0=0D +#define P30_CMD_SUSPEND_RESUME 0x00D0=0D +=0D +// BLOCK LOCKING / UNLOCKING Commands=0D +#define P30_CMD_LOCK_BLOCK_SETUP 0x0060=0D +#define P30_CMD_LOCK_BLOCK 0x0001=0D +#define P30_CMD_UNLOCK_BLOCK 0x00D0=0D +#define P30_CMD_LOCK_DOWN_BLOCK 0x002F=0D +=0D +// PROTECTION Commands=0D +#define P30_CMD_PROGRAM_PROTECTION_REGISTER_SETUP 0x00C0=0D +=0D +// CONFIGURATION Commands=0D +#define P30_CMD_READ_CONFIGURATION_REGISTER_SETUP 0x0060=0D +#define P30_CMD_READ_CONFIGURATION_REGISTER 0x0003=0D +=0D +EFI_STATUS=0D +NorFlashWriteBuffer (=0D + IN UINTN DeviceBaseAddress,=0D + IN UINTN TargetAddress,=0D + IN UINTN BufferSizeInBytes,=0D + IN UINT32 *Buffer=0D + );=0D +=0D +EFI_STATUS=0D +NorFlashWriteSingleBlock (=0D + IN UINTN DeviceBaseAddress,=0D + IN UINTN RegionBaseAddress,=0D + IN EFI_LBA Lba,=0D + IN UINT32 LastBlock,=0D + IN UINT32 BlockSize,=0D + IN UINTN Size,=0D + IN UINTN Offset,=0D + IN OUT UINTN *NumBytes,=0D + IN UINT8 *Buffer,=0D + IN VOID *ShadowBuffer=0D + );=0D +=0D +EFI_STATUS=0D +NorFlashWriteBlocks (=0D + IN UINTN DeviceBaseAddress,=0D + IN UINTN RegionBaseAddress,=0D + IN EFI_LBA Lba,=0D + IN EFI_LBA LastBlock,=0D + IN UINT32 BlockSize,=0D + IN UINTN BufferSizeInBytes,=0D + IN VOID *Buffer=0D + );=0D +=0D +EFI_STATUS=0D +NorFlashReadBlocks (=0D + IN UINTN DeviceBaseAddress,=0D + IN UINTN RegionBaseAddress,=0D + IN EFI_LBA Lba,=0D + IN EFI_LBA LastBlock,=0D + IN UINT32 BlockSize,=0D + IN UINTN BufferSizeInBytes,=0D + OUT VOID *Buffer=0D + );=0D +=0D +EFI_STATUS=0D +NorFlashRead (=0D + IN UINTN DeviceBaseAddress,=0D + IN UINTN RegionBaseAddress,=0D + IN EFI_LBA Lba,=0D + IN UINT32 BlockSize,=0D + IN UINTN Size,=0D + IN UINTN Offset,=0D + IN UINTN BufferSizeInBytes,=0D + OUT VOID *Buffer=0D + );=0D +=0D +EFI_STATUS=0D +NorFlashEraseSingleBlock (=0D + IN UINTN DeviceBaseAddress,=0D + IN UINTN BlockAddress=0D + );=0D +=0D +EFI_STATUS=0D +NorFlashUnlockSingleBlockIfNecessary (=0D + IN UINTN DeviceBaseAddress,=0D + IN UINTN BlockAddress=0D + );=0D +=0D +EFI_STATUS=0D +NorFlashWriteSingleWord (=0D + IN UINTN DeviceBaseAddress,=0D + IN UINTN WordAddress,=0D + IN UINT32 WriteData=0D + );=0D +=0D +EFI_STATUS=0D +NorFlashWriteFullBlock (=0D + IN UINTN DeviceBaseAddress,=0D + IN UINTN RegionBaseAddress,=0D + IN EFI_LBA Lba,=0D + IN UINT32 *DataBuffer,=0D + IN UINT32 BlockSizeInWords=0D + );=0D +=0D +EFI_STATUS=0D +NorFlashUnlockAndEraseSingleBlock (=0D + IN UINTN DeviceBaseAddress,=0D + IN UINTN BlockAddress=0D + );=0D +=0D +EFI_STATUS=0D +NorFlashReset (=0D + IN UINTN DeviceBaseAddress=0D + );=0D +=0D +#endif /* __VIRT_NOR_FLASH_DEVICE_LIB__ */=0D diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.c b/OvmfPkg/Library/VirtN= orFlashDeviceLib/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 @@ **/=0D =0D #include =0D -=0D -#include "VirtNorFlash.h"=0D -=0D -//=0D -// Global variable declarations=0D -//=0D -extern NOR_FLASH_INSTANCE **mNorFlashInstances;=0D -extern UINT32 mNorFlashDeviceCount;=0D +#include =0D +#include =0D =0D UINT32=0D NorFlashReadStatusRegister (=0D - IN NOR_FLASH_INSTANCE *Instance,=0D - IN UINTN SR_Address=0D + IN UINTN DeviceBaseAddress,=0D + IN UINTN SR_Address=0D )=0D {=0D // Prepare to read the status register=0D - SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_STATUS_RE= GISTER);=0D - return MmioRead32 (Instance->DeviceBaseAddress);=0D + SEND_NOR_COMMAND (DeviceBaseAddress, 0, P30_CMD_READ_STATUS_REGISTER);=0D + return MmioRead32 (DeviceBaseAddress);=0D }=0D =0D STATIC=0D BOOLEAN=0D NorFlashBlockIsLocked (=0D - IN NOR_FLASH_INSTANCE *Instance,=0D - IN UINTN BlockAddress=0D + IN UINTN DeviceBaseAddress,=0D + IN UINTN BlockAddress=0D )=0D {=0D UINT32 LockStatus;=0D @@ -56,8 +50,8 @@ NorFlashBlockIsLocked ( STATIC=0D EFI_STATUS=0D NorFlashUnlockSingleBlock (=0D - IN NOR_FLASH_INSTANCE *Instance,=0D - IN UINTN BlockAddress=0D + IN UINTN DeviceBaseAddress,=0D + IN UINTN BlockAddress=0D )=0D {=0D UINT32 LockStatus;=0D @@ -73,7 +67,7 @@ NorFlashUnlockSingleBlock ( =0D // Wait until the status register gives us the all clear=0D do {=0D - LockStatus =3D NorFlashReadStatusRegister (Instance, BlockAddress);=0D + LockStatus =3D NorFlashReadStatusRegister (DeviceBaseAddress, BlockAdd= ress);=0D } while ((LockStatus & P30_SR_BIT_WRITE) !=3D P30_SR_BIT_WRITE);=0D =0D // Put device back into Read Array mode=0D @@ -86,16 +80,16 @@ NorFlashUnlockSingleBlock ( =0D EFI_STATUS=0D NorFlashUnlockSingleBlockIfNecessary (=0D - IN NOR_FLASH_INSTANCE *Instance,=0D - IN UINTN BlockAddress=0D + IN UINTN DeviceBaseAddress,=0D + IN UINTN BlockAddress=0D )=0D {=0D EFI_STATUS Status;=0D =0D Status =3D EFI_SUCCESS;=0D =0D - if (NorFlashBlockIsLocked (Instance, BlockAddress)) {=0D - Status =3D NorFlashUnlockSingleBlock (Instance, BlockAddress);=0D + if (NorFlashBlockIsLocked (DeviceBaseAddress, BlockAddress)) {=0D + Status =3D NorFlashUnlockSingleBlock (DeviceBaseAddress, BlockAddress)= ;=0D }=0D =0D return Status;=0D @@ -106,8 +100,8 @@ NorFlashUnlockSingleBlockIfNecessary ( **/=0D EFI_STATUS=0D NorFlashEraseSingleBlock (=0D - IN NOR_FLASH_INSTANCE *Instance,=0D - IN UINTN BlockAddress=0D + IN UINTN DeviceBaseAddress,=0D + IN UINTN BlockAddress=0D )=0D {=0D EFI_STATUS Status;=0D @@ -121,7 +115,7 @@ NorFlashEraseSingleBlock ( =0D // Wait until the status register gives us the all clear=0D do {=0D - StatusRegister =3D NorFlashReadStatusRegister (Instance, BlockAddress)= ;=0D + StatusRegister =3D NorFlashReadStatusRegister (DeviceBaseAddress, Bloc= kAddress);=0D } while ((StatusRegister & P30_SR_BIT_WRITE) !=3D P30_SR_BIT_WRITE);=0D =0D if (StatusRegister & P30_SR_BIT_VPP) {=0D @@ -147,20 +141,20 @@ NorFlashEraseSingleBlock ( =0D if (EFI_ERROR (Status)) {=0D // Clear the Status Register=0D - SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_CLEAR_STATUS= _REGISTER);=0D + SEND_NOR_COMMAND (DeviceBaseAddress, 0, P30_CMD_CLEAR_STATUS_REGISTER)= ;=0D }=0D =0D // Put device back into Read Array mode=0D - SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);=0D + SEND_NOR_COMMAND (DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);=0D =0D return Status;=0D }=0D =0D EFI_STATUS=0D NorFlashWriteSingleWord (=0D - IN NOR_FLASH_INSTANCE *Instance,=0D - IN UINTN WordAddress,=0D - IN UINT32 WriteData=0D + IN UINTN DeviceBaseAddress,=0D + IN UINTN WordAddress,=0D + IN UINT32 WriteData=0D )=0D {=0D EFI_STATUS Status;=0D @@ -177,7 +171,7 @@ NorFlashWriteSingleWord ( // Wait for the write to complete and then check for any errors; i.e. ch= eck the Status Register=0D do {=0D // Prepare to read the status register=0D - StatusRegister =3D NorFlashReadStatusRegister (Instance, WordAddress);= =0D + StatusRegister =3D NorFlashReadStatusRegister (DeviceBaseAddress, Word= Address);=0D // The chip is busy while the WRITE bit is not asserted=0D } while ((StatusRegister & P30_SR_BIT_WRITE) !=3D P30_SR_BIT_WRITE);=0D =0D @@ -202,7 +196,7 @@ NorFlashWriteSingleWord ( =0D if (!EFI_ERROR (Status)) {=0D // Clear the Status Register=0D - SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_CLEAR_STATUS= _REGISTER);=0D + SEND_NOR_COMMAND (DeviceBaseAddress, 0, P30_CMD_CLEAR_STATUS_REGISTER)= ;=0D }=0D =0D return Status;=0D @@ -225,10 +219,10 @@ NorFlashWriteSingleWord ( */=0D EFI_STATUS=0D NorFlashWriteBuffer (=0D - IN NOR_FLASH_INSTANCE *Instance,=0D - IN UINTN TargetAddress,=0D - IN UINTN BufferSizeInBytes,=0D - IN UINT32 *Buffer=0D + IN UINTN DeviceBaseAddress,=0D + IN UINTN TargetAddress,=0D + IN UINTN BufferSizeInBytes,=0D + IN UINT32 *Buffer=0D )=0D {=0D EFI_STATUS Status;=0D @@ -299,11 +293,11 @@ NorFlashWriteBuffer ( }=0D =0D // Issue the Buffered Program Confirm command, to start the programming = operation=0D - SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_BUFFERED_PROGR= AM_CONFIRM);=0D + SEND_NOR_COMMAND (DeviceBaseAddress, 0, P30_CMD_BUFFERED_PROGRAM_CONFIRM= );=0D =0D // Wait for the write to complete and then check for any errors; i.e. ch= eck the Status Register=0D do {=0D - StatusRegister =3D NorFlashReadStatusRegister (Instance, TargetAddress= );=0D + StatusRegister =3D NorFlashReadStatusRegister (DeviceBaseAddress, Targ= etAddress);=0D // The chip is busy while the WRITE bit is not asserted=0D } while ((StatusRegister & P30_SR_BIT_WRITE) !=3D P30_SR_BIT_WRITE);=0D =0D @@ -330,7 +324,135 @@ NorFlashWriteBuffer ( =0D if (!EFI_ERROR (Status)) {=0D // Clear the Status Register=0D - SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_CLEAR_STATUS= _REGISTER);=0D + SEND_NOR_COMMAND (DeviceBaseAddress, 0, P30_CMD_CLEAR_STATUS_REGISTER)= ;=0D + }=0D +=0D + return Status;=0D +}=0D +=0D +/**=0D + * This function unlock and erase an entire NOR Flash block.=0D + **/=0D +EFI_STATUS=0D +NorFlashUnlockAndEraseSingleBlock (=0D + IN UINTN DeviceBaseAddress,=0D + IN UINTN BlockAddress=0D + )=0D +{=0D + EFI_STATUS Status;=0D + UINTN Index;=0D +=0D + Index =3D 0;=0D + // The block erase might fail a first time (SW bug ?). Retry it ...=0D + do {=0D + // Unlock the block if we have to=0D + Status =3D NorFlashUnlockSingleBlockIfNecessary (DeviceBaseAddress, Bl= ockAddress);=0D + if (EFI_ERROR (Status)) {=0D + break;=0D + }=0D +=0D + Status =3D NorFlashEraseSingleBlock (DeviceBaseAddress, BlockAddress);= =0D + Index++;=0D + } while ((Index < NOR_FLASH_ERASE_RETRY) && (Status =3D=3D EFI_WRITE_PRO= TECTED));=0D +=0D + if (Index =3D=3D NOR_FLASH_ERASE_RETRY) {=0D + DEBUG ((DEBUG_ERROR, "EraseSingleBlock(BlockAddress=3D0x%08x: Block Lo= cked Error (try to erase %d times)\n", BlockAddress, Index));=0D + }=0D +=0D + return Status;=0D +}=0D +=0D +EFI_STATUS=0D +NorFlashWriteFullBlock (=0D + IN UINTN DeviceBaseAddress,=0D + IN UINTN RegionBaseAddress,=0D + IN EFI_LBA Lba,=0D + IN UINT32 *DataBuffer,=0D + IN UINT32 BlockSizeInWords=0D + )=0D +{=0D + EFI_STATUS Status;=0D + UINTN WordAddress;=0D + UINT32 WordIndex;=0D + UINTN BufferIndex;=0D + UINTN BlockAddress;=0D + UINTN BuffersInBlock;=0D + UINTN RemainingWords;=0D + UINTN Cnt;=0D +=0D + Status =3D EFI_SUCCESS;=0D +=0D + // Get the physical address of the block=0D + BlockAddress =3D GET_NOR_BLOCK_ADDRESS (RegionBaseAddress, Lba, BlockSiz= eInWords * 4);=0D +=0D + // Start writing from the first address at the start of the block=0D + WordAddress =3D BlockAddress;=0D + Status =3D NorFlashUnlockAndEraseSingleBlock (DeviceBaseAddress, Bl= ockAddress);=0D + if (EFI_ERROR (Status)) {=0D + DEBUG ((DEBUG_ERROR, "WriteSingleBlock: ERROR - Failed to Unlock and E= rase the single block at 0x%X\n", BlockAddress));=0D + goto EXIT;=0D + }=0D +=0D + // To speed up the programming operation, NOR Flash is programmed using = the Buffered Programming method.=0D +=0D + // Check that the address starts at a 32-word boundary, i.e. last 7 bits= must be zero=0D + if ((WordAddress & BOUNDARY_OF_32_WORDS) =3D=3D 0x00) {=0D + // First, break the entire block into buffer-sized chunks.=0D + BuffersInBlock =3D (UINTN)(BlockSizeInWords * 4) / P30_MAX_BUFFER_SIZE= _IN_BYTES;=0D +=0D + // Then feed each buffer chunk to the NOR Flash=0D + // If a buffer does not contain any data, don't write it.=0D + for (BufferIndex =3D 0;=0D + BufferIndex < BuffersInBlock;=0D + BufferIndex++, WordAddress +=3D P30_MAX_BUFFER_SIZE_IN_BYTES, Dat= aBuffer +=3D P30_MAX_BUFFER_SIZE_IN_WORDS=0D + )=0D + {=0D + // Check the buffer to see if it contains any data (not set all 1s).= =0D + for (Cnt =3D 0; Cnt < P30_MAX_BUFFER_SIZE_IN_WORDS; Cnt++) {=0D + if (~DataBuffer[Cnt] !=3D 0 ) {=0D + // Some data found, write the buffer.=0D + Status =3D NorFlashWriteBuffer (=0D + DeviceBaseAddress,=0D + WordAddress,=0D + P30_MAX_BUFFER_SIZE_IN_BYTES,=0D + DataBuffer=0D + );=0D + if (EFI_ERROR (Status)) {=0D + goto EXIT;=0D + }=0D +=0D + break;=0D + }=0D + }=0D + }=0D +=0D + // Finally, finish off any remaining words that are less than the maxi= mum size of the buffer=0D + RemainingWords =3D BlockSizeInWords % P30_MAX_BUFFER_SIZE_IN_WORDS;=0D +=0D + if (RemainingWords !=3D 0) {=0D + Status =3D NorFlashWriteBuffer (DeviceBaseAddress, WordAddress, (Rem= ainingWords * 4), DataBuffer);=0D + if (EFI_ERROR (Status)) {=0D + goto EXIT;=0D + }=0D + }=0D + } else {=0D + // For now, use the single word programming algorithm=0D + // It is unlikely that the NOR Flash will exist in an address which fa= lls within a 32 word boundary range,=0D + // i.e. which ends in the range 0x......01 - 0x......7F.=0D + for (WordIndex =3D 0; WordIndex < BlockSizeInWords; WordIndex++, DataB= uffer++, WordAddress =3D WordAddress + 4) {=0D + Status =3D NorFlashWriteSingleWord (DeviceBaseAddress, WordAddress, = *DataBuffer);=0D + if (EFI_ERROR (Status)) {=0D + goto EXIT;=0D + }=0D + }=0D + }=0D +=0D +EXIT:=0D + // Put device back into Read Array mode=0D + SEND_NOR_COMMAND (DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);=0D +=0D + if (EFI_ERROR (Status)) {=0D + DEBUG ((DEBUG_ERROR, "NOR FLASH Programming [WriteSingleBlock] failed = at address 0x%08x. Exit Status =3D \"%r\".\n", WordAddress, Status));=0D }=0D =0D return Status;=0D @@ -338,10 +460,13 @@ NorFlashWriteBuffer ( =0D EFI_STATUS=0D NorFlashWriteBlocks (=0D - IN NOR_FLASH_INSTANCE *Instance,=0D - IN EFI_LBA Lba,=0D - IN UINTN BufferSizeInBytes,=0D - IN VOID *Buffer=0D + IN UINTN DeviceBaseAddress,=0D + IN UINTN RegionBaseAddress,=0D + IN EFI_LBA Lba,=0D + IN EFI_LBA LastBlock,=0D + IN UINT32 BlockSize,=0D + IN UINTN BufferSizeInBytes,=0D + IN VOID *Buffer=0D )=0D {=0D UINT32 *pWriteBuffer;=0D @@ -365,22 +490,22 @@ NorFlashWriteBlocks ( }=0D =0D // The size of the buffer must be a multiple of the block size=0D - DEBUG ((DEBUG_BLKIO, "NorFlashWriteBlocks: BlockSize in bytes =3D0x%x\n"= , Instance->BlockSize));=0D - if ((BufferSizeInBytes % Instance->BlockSize) !=3D 0) {=0D + DEBUG ((DEBUG_BLKIO, "NorFlashWriteBlocks: BlockSize in bytes =3D0x%x\n"= , BlockSize));=0D + if ((BufferSizeInBytes % BlockSize) !=3D 0) {=0D return EFI_BAD_BUFFER_SIZE;=0D }=0D =0D // All blocks must be within the device=0D - NumBlocks =3D ((UINT32)BufferSizeInBytes) / Instance->BlockSize;=0D + NumBlocks =3D ((UINT32)BufferSizeInBytes) / BlockSize;=0D =0D - DEBUG ((DEBUG_BLKIO, "NorFlashWriteBlocks: NumBlocks=3D%d, LastBlock=3D%= ld, Lba=3D%ld.\n", NumBlocks, Instance->LastBlock, Lba));=0D + DEBUG ((DEBUG_BLKIO, "NorFlashWriteBlocks: NumBlocks=3D%d, LastBlock=3D%= ld, Lba=3D%ld.\n", NumBlocks, LastBlock, Lba));=0D =0D - if ((Lba + NumBlocks) > (Instance->LastBlock + 1)) {=0D + if ((Lba + NumBlocks) > (LastBlock + 1)) {=0D DEBUG ((DEBUG_ERROR, "NorFlashWriteBlocks: ERROR - Write will exceed l= ast block.\n"));=0D return EFI_INVALID_PARAMETER;=0D }=0D =0D - BlockSizeInWords =3D Instance->BlockSize / 4;=0D + BlockSizeInWords =3D BlockSize / 4;=0D =0D // Because the target *Buffer is a pointer to VOID, we must put all the = data into a pointer=0D // to a proper data type, so use *ReadBuffer=0D @@ -390,7 +515,13 @@ NorFlashWriteBlocks ( for (BlockCount =3D 0; BlockCount < NumBlocks; BlockCount++, CurrentBloc= k++, pWriteBuffer =3D pWriteBuffer + BlockSizeInWords) {=0D DEBUG ((DEBUG_BLKIO, "NorFlashWriteBlocks: Writing block #%d\n", (UINT= N)CurrentBlock));=0D =0D - Status =3D NorFlashWriteFullBlock (Instance, CurrentBlock, pWriteBuffe= r, BlockSizeInWords);=0D + Status =3D NorFlashWriteFullBlock (=0D + DeviceBaseAddress,=0D + RegionBaseAddress,=0D + CurrentBlock,=0D + pWriteBuffer,=0D + BlockSizeInWords=0D + );=0D =0D if (EFI_ERROR (Status)) {=0D break;=0D @@ -403,10 +534,13 @@ NorFlashWriteBlocks ( =0D EFI_STATUS=0D NorFlashReadBlocks (=0D - IN NOR_FLASH_INSTANCE *Instance,=0D - IN EFI_LBA Lba,=0D - IN UINTN BufferSizeInBytes,=0D - OUT VOID *Buffer=0D + IN UINTN DeviceBaseAddress,=0D + IN UINTN RegionBaseAddress,=0D + IN EFI_LBA Lba,=0D + IN EFI_LBA LastBlock,=0D + IN UINT32 BlockSize,=0D + IN UINTN BufferSizeInBytes,=0D + OUT VOID *Buffer=0D )=0D {=0D UINT32 NumBlocks;=0D @@ -416,8 +550,8 @@ NorFlashReadBlocks ( DEBUG_BLKIO,=0D "NorFlashReadBlocks: BufferSize=3D0x%xB BlockSize=3D0x%xB LastBlock=3D= %ld, Lba=3D%ld.\n",=0D BufferSizeInBytes,=0D - Instance->BlockSize,=0D - Instance->LastBlock,=0D + BlockSize,=0D + LastBlock,=0D Lba=0D ));=0D =0D @@ -432,27 +566,27 @@ NorFlashReadBlocks ( }=0D =0D // The size of the buffer must be a multiple of the block size=0D - if ((BufferSizeInBytes % Instance->BlockSize) !=3D 0) {=0D + if ((BufferSizeInBytes % BlockSize) !=3D 0) {=0D return EFI_BAD_BUFFER_SIZE;=0D }=0D =0D // All blocks must be within the device=0D - NumBlocks =3D ((UINT32)BufferSizeInBytes) / Instance->BlockSize;=0D + NumBlocks =3D ((UINT32)BufferSizeInBytes) / BlockSize;=0D =0D - if ((Lba + NumBlocks) > (Instance->LastBlock + 1)) {=0D + if ((Lba + NumBlocks) > (LastBlock + 1)) {=0D DEBUG ((DEBUG_ERROR, "NorFlashReadBlocks: ERROR - Read will exceed las= t block\n"));=0D return EFI_INVALID_PARAMETER;=0D }=0D =0D // Get the address to start reading from=0D StartAddress =3D GET_NOR_BLOCK_ADDRESS (=0D - Instance->RegionBaseAddress,=0D + RegionBaseAddress,=0D Lba,=0D - Instance->BlockSize=0D + BlockSize=0D );=0D =0D // Put the device into Read Array mode=0D - SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);=0D + SEND_NOR_COMMAND (DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);=0D =0D // Readout the data=0D CopyMem (Buffer, (VOID *)StartAddress, BufferSizeInBytes);=0D @@ -462,11 +596,14 @@ NorFlashReadBlocks ( =0D EFI_STATUS=0D NorFlashRead (=0D - IN NOR_FLASH_INSTANCE *Instance,=0D - IN EFI_LBA Lba,=0D - IN UINTN Offset,=0D - IN UINTN BufferSizeInBytes,=0D - OUT VOID *Buffer=0D + IN UINTN DeviceBaseAddress,=0D + IN UINTN RegionBaseAddress,=0D + IN EFI_LBA Lba,=0D + IN UINT32 BlockSize,=0D + IN UINTN Size,=0D + IN UINTN Offset,=0D + IN UINTN BufferSizeInBytes,=0D + OUT VOID *Buffer=0D )=0D {=0D UINTN StartAddress;=0D @@ -481,20 +618,20 @@ NorFlashRead ( return EFI_SUCCESS;=0D }=0D =0D - if (((Lba * Instance->BlockSize) + Offset + BufferSizeInBytes) > Instanc= e->Size) {=0D + if (((Lba * BlockSize) + Offset + BufferSizeInBytes) > Size) {=0D DEBUG ((DEBUG_ERROR, "NorFlashRead: ERROR - Read will exceed device si= ze.\n"));=0D return EFI_INVALID_PARAMETER;=0D }=0D =0D // Get the address to start reading from=0D StartAddress =3D GET_NOR_BLOCK_ADDRESS (=0D - Instance->RegionBaseAddress,=0D + RegionBaseAddress,=0D Lba,=0D - Instance->BlockSize=0D + BlockSize=0D );=0D =0D // Put the device into Read Array mode=0D - SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);=0D + SEND_NOR_COMMAND (DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);=0D =0D // Readout the data=0D CopyMem (Buffer, (VOID *)(StartAddress + Offset), BufferSizeInBytes);=0D @@ -505,27 +642,47 @@ NorFlashRead ( STATIC=0D EFI_STATUS=0D NorFlashWriteSingleBlockWithErase (=0D - IN NOR_FLASH_INSTANCE *Instance,=0D - IN EFI_LBA Lba,=0D - IN UINTN Offset,=0D - IN OUT UINTN *NumBytes,=0D - IN UINT8 *Buffer=0D + IN UINTN DeviceBaseAddress,=0D + IN UINTN RegionBaseAddress,=0D + IN EFI_LBA Lba,=0D + IN UINT32 LastBlock,=0D + IN UINT32 BlockSize,=0D + IN UINTN Offset,=0D + IN OUT UINTN *NumBytes,=0D + IN UINT8 *Buffer,=0D + IN VOID *ShadowBuffer=0D )=0D {=0D EFI_STATUS Status;=0D =0D // Read NOR Flash data into shadow buffer=0D - Status =3D NorFlashReadBlocks (Instance, Lba, Instance->BlockSize, Insta= nce->ShadowBuffer);=0D + Status =3D NorFlashReadBlocks (=0D + DeviceBaseAddress,=0D + RegionBaseAddress,=0D + Lba,=0D + LastBlock,=0D + BlockSize,=0D + BlockSize,=0D + ShadowBuffer=0D + );=0D if (EFI_ERROR (Status)) {=0D // Return one of the pre-approved error statuses=0D return EFI_DEVICE_ERROR;=0D }=0D =0D // Put the data at the appropriate location inside the buffer area=0D - CopyMem ((VOID *)((UINTN)Instance->ShadowBuffer + Offset), Buffer, *NumB= ytes);=0D + CopyMem ((VOID *)((UINTN)ShadowBuffer + Offset), Buffer, *NumBytes);=0D =0D // Write the modified buffer back to the NorFlash=0D - Status =3D NorFlashWriteBlocks (Instance, Lba, Instance->BlockSize, Inst= ance->ShadowBuffer);=0D + Status =3D NorFlashWriteBlocks (=0D + DeviceBaseAddress,=0D + RegionBaseAddress,=0D + Lba,=0D + LastBlock,=0D + BlockSize,=0D + BlockSize,=0D + ShadowBuffer=0D + );=0D if (EFI_ERROR (Status)) {=0D // Return one of the pre-approved error statuses=0D return EFI_DEVICE_ERROR;=0D @@ -540,16 +697,20 @@ NorFlashWriteSingleBlockWithErase ( */=0D EFI_STATUS=0D NorFlashWriteSingleBlock (=0D - IN NOR_FLASH_INSTANCE *Instance,=0D - IN EFI_LBA Lba,=0D - IN UINTN Offset,=0D - IN OUT UINTN *NumBytes,=0D - IN UINT8 *Buffer=0D + IN UINTN DeviceBaseAddress,=0D + IN UINTN RegionBaseAddress,=0D + IN EFI_LBA Lba,=0D + IN UINT32 LastBlock,=0D + IN UINT32 BlockSize,=0D + IN UINTN Size,=0D + IN UINTN Offset,=0D + IN OUT UINTN *NumBytes,=0D + IN UINT8 *Buffer,=0D + IN VOID *ShadowBuffer=0D )=0D {=0D EFI_STATUS Status;=0D UINTN CurOffset;=0D - UINTN BlockSize;=0D UINTN BlockAddress;=0D UINT8 *OrigData;=0D UINTN Start, End;=0D @@ -558,14 +719,11 @@ NorFlashWriteSingleBlock ( DEBUG ((DEBUG_BLKIO, "NorFlashWriteSingleBlock(Parameters: Lba=3D%ld, Of= fset=3D0x%x, *NumBytes=3D0x%x, Buffer @ 0x%08x)\n", Lba, Offset, *NumBytes,= Buffer));=0D =0D // Check we did get some memory. Buffer is BlockSize.=0D - if (Instance->ShadowBuffer =3D=3D NULL) {=0D + if (ShadowBuffer =3D=3D NULL) {=0D DEBUG ((DEBUG_ERROR, "FvbWrite: ERROR - Buffer not ready\n"));=0D return EFI_DEVICE_ERROR;=0D }=0D =0D - // Cache the block size to avoid de-referencing pointers all the time=0D - BlockSize =3D Instance->BlockSize;=0D -=0D // The write must not span block boundaries.=0D // We need to check each variable individually because adding two large = values together overflows.=0D if ((Offset >=3D BlockSize) ||=0D @@ -620,11 +778,14 @@ NorFlashWriteSingleBlock ( =0D // Read the old version of the data into the shadow buffer=0D Status =3D NorFlashRead (=0D - Instance,=0D + DeviceBaseAddress,=0D + RegionBaseAddress,=0D Lba,=0D + BlockSize,=0D + Size,=0D Start,=0D End - Start,=0D - Instance->ShadowBuffer=0D + ShadowBuffer=0D );=0D if (EFI_ERROR (Status)) {=0D return EFI_DEVICE_ERROR;=0D @@ -632,7 +793,7 @@ NorFlashWriteSingleBlock ( =0D // Make OrigData point to the start of the old version of the data ins= ide=0D // the word aligned buffer=0D - OrigData =3D Instance->ShadowBuffer + (Offset & BOUNDARY_OF_32_WORDS);= =0D + OrigData =3D ShadowBuffer + (Offset & BOUNDARY_OF_32_WORDS);=0D =0D // Update the buffer containing the old version of the data with the n= ew=0D // contents, while checking whether the old version had any bits clear= ed=0D @@ -640,11 +801,15 @@ NorFlashWriteSingleBlock ( for (CurOffset =3D 0; CurOffset < *NumBytes; CurOffset++) {=0D if (~(UINT32)OrigData[CurOffset] & (UINT32)Buffer[CurOffset]) {=0D Status =3D NorFlashWriteSingleBlockWithErase (=0D - Instance,=0D + DeviceBaseAddress,=0D + RegionBaseAddress,=0D Lba,=0D + LastBlock,=0D + BlockSize,=0D Offset,=0D NumBytes,=0D - Buffer=0D + Buffer,=0D + ShadowBuffer=0D );=0D return Status;=0D }=0D @@ -655,10 +820,10 @@ NorFlashWriteSingleBlock ( //=0D // Write the updated buffer to NOR.=0D //=0D - BlockAddress =3D GET_NOR_BLOCK_ADDRESS (Instance->RegionBaseAddress, L= ba, BlockSize);=0D + BlockAddress =3D GET_NOR_BLOCK_ADDRESS (RegionBaseAddress, Lba, BlockS= ize);=0D =0D // Unlock the block if we have to=0D - Status =3D NorFlashUnlockSingleBlockIfNecessary (Instance, BlockAddres= s);=0D + Status =3D NorFlashUnlockSingleBlockIfNecessary (DeviceBaseAddress, Bl= ockAddress);=0D if (EFI_ERROR (Status)) {=0D goto Exit;=0D }=0D @@ -666,10 +831,10 @@ NorFlashWriteSingleBlock ( Count =3D (End - Start) / P30_MAX_BUFFER_SIZE_IN_BYTES;=0D for (Index =3D 0; Index < Count; Index++) {=0D Status =3D NorFlashWriteBuffer (=0D - Instance,=0D + DeviceBaseAddress,=0D BlockAddress + Start + Index * P30_MAX_BUFFER_SIZE_IN_BYT= ES,=0D P30_MAX_BUFFER_SIZE_IN_BYTES,=0D - Instance->ShadowBuffer + Index * P30_MAX_BUFFER_SIZE_IN_B= YTES=0D + ShadowBuffer + Index * P30_MAX_BUFFER_SIZE_IN_BYTES=0D );=0D if (EFI_ERROR (Status)) {=0D goto Exit;=0D @@ -677,66 +842,32 @@ NorFlashWriteSingleBlock ( }=0D } else {=0D Status =3D NorFlashWriteSingleBlockWithErase (=0D - Instance,=0D + DeviceBaseAddress,=0D + RegionBaseAddress,=0D Lba,=0D + LastBlock,=0D + BlockSize,=0D Offset,=0D NumBytes,=0D - Buffer=0D + Buffer,=0D + ShadowBuffer=0D );=0D return Status;=0D }=0D =0D Exit:=0D // Put device back into Read Array mode=0D - SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);=0D + SEND_NOR_COMMAND (DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);=0D =0D return Status;=0D }=0D =0D EFI_STATUS=0D NorFlashReset (=0D - IN NOR_FLASH_INSTANCE *Instance=0D + IN UINTN DeviceBaseAddress=0D )=0D {=0D // As there is no specific RESET to perform, ensure that the devices is = in the default Read Array mode=0D - SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);=0D + SEND_NOR_COMMAND (DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);=0D return EFI_SUCCESS;=0D }=0D -=0D -/**=0D - Fixup internal data so that EFI can be call in virtual mode.=0D - Call the passed in Child Notify event and convert any pointers in=0D - lib to virtual mode.=0D -=0D - @param[in] Event The Event that is being processed=0D - @param[in] Context Event Context=0D -**/=0D -VOID=0D -EFIAPI=0D -NorFlashVirtualNotifyEvent (=0D - IN EFI_EVENT Event,=0D - IN VOID *Context=0D - )=0D -{=0D - UINTN Index;=0D -=0D - for (Index =3D 0; Index < mNorFlashDeviceCount; Index++) {=0D - EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->DeviceBas= eAddress);=0D - EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->RegionBas= eAddress);=0D -=0D - // Convert Fvb=0D - EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->FvbProtoc= ol.EraseBlocks);=0D - EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->FvbProtoc= ol.GetAttributes);=0D - EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->FvbProtoc= ol.GetBlockSize);=0D - EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->FvbProtoc= ol.GetPhysicalAddress);=0D - EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->FvbProtoc= ol.Read);=0D - EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->FvbProtoc= ol.SetAttributes);=0D - EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->FvbProtoc= ol.Write);=0D -=0D - if (mNorFlashInstances[Index]->ShadowBuffer !=3D NULL) {=0D - EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->ShadowB= uffer);=0D - }=0D - }=0D -=0D - return;=0D -}=0D diff --git a/OvmfPkg/Library/VirtNorFlashDeviceLib/VirtNorFlashDeviceLib.in= f 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=0D +#=0D +# Component description file for NorFlashDxe module=0D +#=0D +# Copyright (c) 2011 - 2021, Arm Limited. All rights reserved.
=0D +#=0D +# SPDX-License-Identifier: BSD-2-Clause-Patent=0D +#=0D +#**/=0D +=0D +[Defines]=0D + INF_VERSION =3D 1.29=0D + BASE_NAME =3D VirtNorFlashDeviceLib=0D + FILE_GUID =3D 3f8c8c4b-5b92-4e71-ae73-9f7d2f1e33d4= =0D + MODULE_TYPE =3D BASE=0D + VERSION_STRING =3D 1.0=0D + LIBRARY_CLASS =3D VirtNorFlashDeviceLib=0D +=0D +[Sources.common]=0D + VirtNorFlashDeviceLib.c=0D +=0D +[Packages]=0D + MdePkg/MdePkg.dec=0D + OvmfPkg/OvmfPkg.dec=0D +=0D +[LibraryClasses]=0D + BaseLib=0D + BaseMemoryLib=0D + DebugLib=0D + IoLib=0D diff --git a/OvmfPkg/LoongArchVirt/LoongArchVirtQemu.dsc b/OvmfPkg/LoongArc= hVirt/LoongArchVirtQemu.dsc index 89abdf9f779e..27a2d1baf5df 100644 --- a/OvmfPkg/LoongArchVirt/LoongArchVirtQemu.dsc +++ b/OvmfPkg/LoongArchVirt/LoongArchVirtQemu.dsc @@ -507,7 +507,10 @@ #=0D # Variable=0D #=0D - OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.inf=0D + OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.inf {=0D + =0D + VirtNorFlashDeviceLib|OvmfPkg/Library/VirtNorFlashDeviceLib/VirtNorF= lashDeviceLib.inf=0D + }=0D MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf {= =0D =0D NULL|EmbeddedPkg/Library/NvVarStoreFormattedLib/NvVarStoreFormattedL= ib.inf=0D 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.=0D VirtioMmioDeviceLib|Include/Library/VirtioMmioDeviceLib.h=0D =0D + ## @libraryclass Provides a Device Nor flash interface.=0D + #=0D + VirtNorFlashDeviceLib|Include/Library/VirtNorFlashDeviceLib.h=0D +=0D ## @libraryclass Provides a Nor flash interface.=0D #=0D VirtNorFlashPlatformLib|Include/Library/VirtNorFlashPlatformLib.h=0D diff --git a/OvmfPkg/RiscVVirt/RiscVVirtQemu.dsc b/OvmfPkg/RiscVVirt/RiscVV= irtQemu.dsc index ca211b3db356..8e864e123f08 100644 --- a/OvmfPkg/RiscVVirt/RiscVVirtQemu.dsc +++ b/OvmfPkg/RiscVVirt/RiscVVirtQemu.dsc @@ -324,7 +324,10 @@ MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf=0D =0D UefiCpuPkg/CpuTimerDxeRiscV64/CpuTimerDxeRiscV64.inf=0D - OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.inf=0D + OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.inf {=0D + =0D + VirtNorFlashDeviceLib|OvmfPkg/Library/VirtNorFlashDeviceLib/VirtNorF= lashDeviceLib.inf=0D + }=0D MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf=0D =0D #=0D diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.h b/OvmfPkg/VirtNorFlashD= xe/VirtNorFlash.h deleted file mode 100644 index 455eafacc2cf..000000000000 --- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlash.h +++ /dev/null @@ -1,345 +0,0 @@ -/** @file NorFlash.h=0D -=0D - Copyright (c) 2011 - 2014, ARM Ltd. All rights reserved.
=0D -=0D - SPDX-License-Identifier: BSD-2-Clause-Patent=0D -=0D -**/=0D -=0D -#ifndef __VIRT_NOR_FLASH__=0D -#define __VIRT_NOR_FLASH__=0D -=0D -#include =0D -#include =0D -=0D -#include =0D -=0D -#include =0D -=0D -#include =0D -#include =0D -#include =0D -#include =0D -#include =0D -=0D -#define NOR_FLASH_ERASE_RETRY 10=0D -=0D -// Device access macros=0D -// These are necessary because we use 2 x 16bit parts to make up 32bit dat= a=0D -=0D -#define HIGH_16_BITS 0xFFFF0000=0D -#define LOW_16_BITS 0x0000FFFF=0D -#define LOW_8_BITS 0x000000FF=0D -=0D -#define FOLD_32BIT_INTO_16BIT(value) ( ( value >> 16 ) | ( value & LOW_16= _BITS ) )=0D -=0D -#define GET_LOW_BYTE(value) ( value & LOW_8_BITS )=0D -#define GET_HIGH_BYTE(value) ( GET_LOW_BYTE( value >> 16 ) )=0D -=0D -// Each command must be sent simultaneously to both chips,=0D -// i.e. at the lower 16 bits AND at the higher 16 bits=0D -#define CREATE_NOR_ADDRESS(BaseAddr, OffsetAddr) ((BaseAddr) + ((Off= setAddr) << 2))=0D -#define CREATE_DUAL_CMD(Cmd) ( ( Cmd << 16) | ( = Cmd & LOW_16_BITS) )=0D -#define SEND_NOR_COMMAND(BaseAddr, Offset, Cmd) MmioWrite32 (CREATE= _NOR_ADDRESS(BaseAddr,Offset), CREATE_DUAL_CMD(Cmd))=0D -#define GET_NOR_BLOCK_ADDRESS(BaseAddr, Lba, LbaSize) ( BaseAddr + (UINTN= )((Lba) * LbaSize) )=0D -=0D -// Status Register Bits=0D -#define P30_SR_BIT_WRITE (BIT7 << 16 | BIT7)=0D -#define P30_SR_BIT_ERASE_SUSPEND (BIT6 << 16 | BIT6)=0D -#define P30_SR_BIT_ERASE (BIT5 << 16 | BIT5)=0D -#define P30_SR_BIT_PROGRAM (BIT4 << 16 | BIT4)=0D -#define P30_SR_BIT_VPP (BIT3 << 16 | BIT3)=0D -#define P30_SR_BIT_PROGRAM_SUSPEND (BIT2 << 16 | BIT2)=0D -#define P30_SR_BIT_BLOCK_LOCKED (BIT1 << 16 | BIT1)=0D -#define P30_SR_BIT_BEFP (BIT0 << 16 | BIT0)=0D -=0D -// Device Commands for Intel StrataFlash(R) Embedded Memory (P30) Family=0D -=0D -// On chip buffer size for buffered programming operations=0D -// There are 2 chips, each chip can buffer up to 32 (16-bit)words, and eac= h word is 2 bytes.=0D -// Therefore the total size of the buffer is 2 x 32 x 2 =3D 128 bytes=0D -#define P30_MAX_BUFFER_SIZE_IN_BYTES ((UINTN)128)=0D -#define P30_MAX_BUFFER_SIZE_IN_WORDS (P30_MAX_BUFFER_SIZE_IN_BYTES/((UINT= N)4))=0D -#define MAX_BUFFERED_PROG_ITERATIONS 10000000=0D -#define BOUNDARY_OF_32_WORDS ((UINTN)0x7F)=0D -=0D -// CFI Addresses=0D -#define P30_CFI_ADDR_QUERY_UNIQUE_QRY 0x10=0D -#define P30_CFI_ADDR_VENDOR_ID 0x13=0D -=0D -// CFI Data=0D -#define CFI_QRY 0x00595251=0D -=0D -// READ Commands=0D -#define P30_CMD_READ_DEVICE_ID 0x0090=0D -#define P30_CMD_READ_STATUS_REGISTER 0x0070=0D -#define P30_CMD_CLEAR_STATUS_REGISTER 0x0050=0D -#define P30_CMD_READ_ARRAY 0x00FF=0D -#define P30_CMD_READ_CFI_QUERY 0x0098=0D -=0D -// WRITE Commands=0D -#define P30_CMD_WORD_PROGRAM_SETUP 0x0040=0D -#define P30_CMD_ALTERNATE_WORD_PROGRAM_SETUP 0x0010=0D -#define P30_CMD_BUFFERED_PROGRAM_SETUP 0x00E8=0D -#define P30_CMD_BUFFERED_PROGRAM_CONFIRM 0x00D0=0D -#define P30_CMD_BEFP_SETUP 0x0080=0D -#define P30_CMD_BEFP_CONFIRM 0x00D0=0D -=0D -// ERASE Commands=0D -#define P30_CMD_BLOCK_ERASE_SETUP 0x0020=0D -#define P30_CMD_BLOCK_ERASE_CONFIRM 0x00D0=0D -=0D -// SUSPEND Commands=0D -#define P30_CMD_PROGRAM_OR_ERASE_SUSPEND 0x00B0=0D -#define P30_CMD_SUSPEND_RESUME 0x00D0=0D -=0D -// BLOCK LOCKING / UNLOCKING Commands=0D -#define P30_CMD_LOCK_BLOCK_SETUP 0x0060=0D -#define P30_CMD_LOCK_BLOCK 0x0001=0D -#define P30_CMD_UNLOCK_BLOCK 0x00D0=0D -#define P30_CMD_LOCK_DOWN_BLOCK 0x002F=0D -=0D -// PROTECTION Commands=0D -#define P30_CMD_PROGRAM_PROTECTION_REGISTER_SETUP 0x00C0=0D -=0D -// CONFIGURATION Commands=0D -#define P30_CMD_READ_CONFIGURATION_REGISTER_SETUP 0x0060=0D -#define P30_CMD_READ_CONFIGURATION_REGISTER 0x0003=0D -=0D -#define NOR_FLASH_SIGNATURE SIGNATURE_32('n', 'o', 'r', '0')=0D -#define INSTANCE_FROM_FVB_THIS(a) CR(a, NOR_FLASH_INSTANCE, FvbProtocol, = NOR_FLASH_SIGNATURE)=0D -=0D -typedef struct _NOR_FLASH_INSTANCE NOR_FLASH_INSTANCE;=0D -=0D -#pragma pack (1)=0D -typedef struct {=0D - VENDOR_DEVICE_PATH Vendor;=0D - UINT8 Index;=0D - EFI_DEVICE_PATH_PROTOCOL End;=0D -} NOR_FLASH_DEVICE_PATH;=0D -#pragma pack ()=0D -=0D -struct _NOR_FLASH_INSTANCE {=0D - UINT32 Signature;=0D - EFI_HANDLE Handle;=0D -=0D - UINTN DeviceBaseAddress;=0D - UINTN RegionBaseAddress;=0D - UINTN Size;=0D - EFI_LBA StartLba;=0D - EFI_LBA LastBlock;=0D - UINT32 BlockSize;=0D -=0D - EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL FvbProtocol;=0D - VOID *ShadowBuffer;=0D -=0D - NOR_FLASH_DEVICE_PATH DevicePath;=0D -};=0D -=0D -EFI_STATUS=0D -NorFlashReadCfiData (=0D - IN UINTN DeviceBaseAddress,=0D - IN UINTN CFI_Offset,=0D - IN UINT32 NumberOfBytes,=0D - OUT UINT32 *Data=0D - );=0D -=0D -EFI_STATUS=0D -NorFlashWriteBuffer (=0D - IN NOR_FLASH_INSTANCE *Instance,=0D - IN UINTN TargetAddress,=0D - IN UINTN BufferSizeInBytes,=0D - IN UINT32 *Buffer=0D - );=0D -=0D -//=0D -// NorFlashFvbDxe.c=0D -//=0D -=0D -EFI_STATUS=0D -EFIAPI=0D -FvbGetAttributes (=0D - IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,=0D - OUT EFI_FVB_ATTRIBUTES_2 *Attributes=0D - );=0D -=0D -EFI_STATUS=0D -EFIAPI=0D -FvbSetAttributes (=0D - IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,=0D - IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes=0D - );=0D -=0D -EFI_STATUS=0D -EFIAPI=0D -FvbGetPhysicalAddress (=0D - IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,=0D - OUT EFI_PHYSICAL_ADDRESS *Address=0D - );=0D -=0D -EFI_STATUS=0D -EFIAPI=0D -FvbGetBlockSize (=0D - IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,=0D - IN EFI_LBA Lba,=0D - OUT UINTN *BlockSize,=0D - OUT UINTN *NumberOfBlocks=0D - );=0D -=0D -EFI_STATUS=0D -EFIAPI=0D -FvbRead (=0D - IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,=0D - IN EFI_LBA Lba,=0D - IN UINTN Offset,=0D - IN OUT UINTN *NumBytes,=0D - IN OUT UINT8 *Buffer=0D - );=0D -=0D -EFI_STATUS=0D -EFIAPI=0D -FvbWrite (=0D - IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,=0D - IN EFI_LBA Lba,=0D - IN UINTN Offset,=0D - IN OUT UINTN *NumBytes,=0D - IN UINT8 *Buffer=0D - );=0D -=0D -EFI_STATUS=0D -EFIAPI=0D -FvbEraseBlocks (=0D - IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,=0D - ...=0D - );=0D -=0D -EFI_STATUS=0D -ValidateFvHeader (=0D - IN NOR_FLASH_INSTANCE *Instance=0D - );=0D -=0D -EFI_STATUS=0D -InitializeFvAndVariableStoreHeaders (=0D - IN NOR_FLASH_INSTANCE *Instance=0D - );=0D -=0D -VOID=0D -EFIAPI=0D -FvbVirtualNotifyEvent (=0D - IN EFI_EVENT Event,=0D - IN VOID *Context=0D - );=0D -=0D -//=0D -// NorFlashDxe.c=0D -//=0D -=0D -EFI_STATUS=0D -NorFlashWriteFullBlock (=0D - IN NOR_FLASH_INSTANCE *Instance,=0D - IN EFI_LBA Lba,=0D - IN UINT32 *DataBuffer,=0D - IN UINT32 BlockSizeInWords=0D - );=0D -=0D -EFI_STATUS=0D -NorFlashUnlockAndEraseSingleBlock (=0D - IN NOR_FLASH_INSTANCE *Instance,=0D - IN UINTN BlockAddress=0D - );=0D -=0D -EFI_STATUS=0D -NorFlashCreateInstance (=0D - IN UINTN NorFlashDeviceBase,=0D - IN UINTN NorFlashRegionBase,=0D - IN UINTN NorFlashSize,=0D - IN UINT32 Index,=0D - IN UINT32 BlockSize,=0D - IN BOOLEAN SupportFvb,=0D - OUT NOR_FLASH_INSTANCE **NorFlashInstance=0D - );=0D -=0D -EFI_STATUS=0D -EFIAPI=0D -NorFlashFvbInitialize (=0D - IN NOR_FLASH_INSTANCE *Instance=0D - );=0D -=0D -//=0D -// NorFlash.c=0D -//=0D -EFI_STATUS=0D -NorFlashWriteSingleBlock (=0D - IN NOR_FLASH_INSTANCE *Instance,=0D - IN EFI_LBA Lba,=0D - IN UINTN Offset,=0D - IN OUT UINTN *NumBytes,=0D - IN UINT8 *Buffer=0D - );=0D -=0D -EFI_STATUS=0D -NorFlashWriteBlocks (=0D - IN NOR_FLASH_INSTANCE *Instance,=0D - IN EFI_LBA Lba,=0D - IN UINTN BufferSizeInBytes,=0D - IN VOID *Buffer=0D - );=0D -=0D -EFI_STATUS=0D -NorFlashReadBlocks (=0D - IN NOR_FLASH_INSTANCE *Instance,=0D - IN EFI_LBA Lba,=0D - IN UINTN BufferSizeInBytes,=0D - OUT VOID *Buffer=0D - );=0D -=0D -EFI_STATUS=0D -NorFlashRead (=0D - IN NOR_FLASH_INSTANCE *Instance,=0D - IN EFI_LBA Lba,=0D - IN UINTN Offset,=0D - IN UINTN BufferSizeInBytes,=0D - OUT VOID *Buffer=0D - );=0D -=0D -EFI_STATUS=0D -NorFlashWrite (=0D - IN NOR_FLASH_INSTANCE *Instance,=0D - IN EFI_LBA Lba,=0D - IN UINTN Offset,=0D - IN OUT UINTN *NumBytes,=0D - IN UINT8 *Buffer=0D - );=0D -=0D -EFI_STATUS=0D -NorFlashReset (=0D - IN NOR_FLASH_INSTANCE *Instance=0D - );=0D -=0D -EFI_STATUS=0D -NorFlashEraseSingleBlock (=0D - IN NOR_FLASH_INSTANCE *Instance,=0D - IN UINTN BlockAddress=0D - );=0D -=0D -EFI_STATUS=0D -NorFlashUnlockSingleBlockIfNecessary (=0D - IN NOR_FLASH_INSTANCE *Instance,=0D - IN UINTN BlockAddress=0D - );=0D -=0D -EFI_STATUS=0D -NorFlashWriteSingleWord (=0D - IN NOR_FLASH_INSTANCE *Instance,=0D - IN UINTN WordAddress,=0D - IN UINT32 WriteData=0D - );=0D -=0D -VOID=0D -EFIAPI=0D -NorFlashVirtualNotifyEvent (=0D - IN EFI_EVENT Event,=0D - IN VOID *Context=0D - );=0D -=0D -#endif /* __VIRT_NOR_FLASH__ */=0D diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.c b/OvmfPkg/VirtNorFla= shDxe/VirtNorFlashDxe.c index 6b9ef261335e..1b46d2690108 100644 --- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.c +++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.c @@ -1,4 +1,4 @@ -/** @file NorFlashDxe.c=0D +/** @file VirtNorFlashDxe.c=0D =0D Copyright (c) 2011 - 2021, Arm Limited. All rights reserved.
=0D =0D @@ -14,7 +14,7 @@ #include =0D #include =0D =0D -#include "VirtNorFlash.h"=0D +#include "VirtNorFlashDxe.h"=0D =0D STATIC EFI_EVENT mNorFlashVirtualAddrChangeEvent;=0D =0D @@ -138,161 +138,41 @@ NorFlashCreateInstance ( }=0D =0D /**=0D - * This function unlock and erase an entire NOR Flash block.=0D - **/=0D -EFI_STATUS=0D -NorFlashUnlockAndEraseSingleBlock (=0D - IN NOR_FLASH_INSTANCE *Instance,=0D - IN UINTN BlockAddress=0D - )=0D -{=0D - EFI_STATUS Status;=0D - UINTN Index;=0D - EFI_TPL OriginalTPL;=0D -=0D - if (!EfiAtRuntime ()) {=0D - // Raise TPL to TPL_HIGH to stop anyone from interrupting us.=0D - OriginalTPL =3D gBS->RaiseTPL (TPL_HIGH_LEVEL);=0D - } else {=0D - // This initialization is only to prevent the compiler to complain abo= ut the=0D - // use of uninitialized variables=0D - OriginalTPL =3D TPL_HIGH_LEVEL;=0D - }=0D + Fixup internal data so that EFI can be call in virtual mode.=0D + Call the passed in Child Notify event and convert any pointers in=0D + lib to virtual mode.=0D =0D - Index =3D 0;=0D - // The block erase might fail a first time (SW bug ?). Retry it ...=0D - do {=0D - // Unlock the block if we have to=0D - Status =3D NorFlashUnlockSingleBlockIfNecessary (Instance, BlockAddres= s);=0D - if (EFI_ERROR (Status)) {=0D - break;=0D - }=0D -=0D - Status =3D NorFlashEraseSingleBlock (Instance, BlockAddress);=0D - Index++;=0D - } while ((Index < NOR_FLASH_ERASE_RETRY) && (Status =3D=3D EFI_WRITE_PRO= TECTED));=0D -=0D - if (Index =3D=3D NOR_FLASH_ERASE_RETRY) {=0D - DEBUG ((DEBUG_ERROR, "EraseSingleBlock(BlockAddress=3D0x%08x: Block Lo= cked Error (try to erase %d times)\n", BlockAddress, Index));=0D - }=0D -=0D - if (!EfiAtRuntime ()) {=0D - // Interruptions can resume.=0D - gBS->RestoreTPL (OriginalTPL);=0D - }=0D -=0D - return Status;=0D -}=0D -=0D -EFI_STATUS=0D -NorFlashWriteFullBlock (=0D - IN NOR_FLASH_INSTANCE *Instance,=0D - IN EFI_LBA Lba,=0D - IN UINT32 *DataBuffer,=0D - IN UINT32 BlockSizeInWords=0D + @param[in] Event The Event that is being processed=0D + @param[in] Context Event Context=0D +**/=0D +VOID=0D +EFIAPI=0D +NorFlashVirtualNotifyEvent (=0D + IN EFI_EVENT Event,=0D + IN VOID *Context=0D )=0D {=0D - EFI_STATUS Status;=0D - UINTN WordAddress;=0D - UINT32 WordIndex;=0D - UINTN BufferIndex;=0D - UINTN BlockAddress;=0D - UINTN BuffersInBlock;=0D - UINTN RemainingWords;=0D - EFI_TPL OriginalTPL;=0D - UINTN Cnt;=0D -=0D - Status =3D EFI_SUCCESS;=0D -=0D - // Get the physical address of the block=0D - BlockAddress =3D GET_NOR_BLOCK_ADDRESS (Instance->RegionBaseAddress, Lba= , BlockSizeInWords * 4);=0D -=0D - // Start writing from the first address at the start of the block=0D - WordAddress =3D BlockAddress;=0D -=0D - if (!EfiAtRuntime ()) {=0D - // Raise TPL to TPL_HIGH to stop anyone from interrupting us.=0D - OriginalTPL =3D gBS->RaiseTPL (TPL_HIGH_LEVEL);=0D - } else {=0D - // This initialization is only to prevent the compiler to complain abo= ut the=0D - // use of uninitialized variables=0D - OriginalTPL =3D TPL_HIGH_LEVEL;=0D - }=0D -=0D - Status =3D NorFlashUnlockAndEraseSingleBlock (Instance, BlockAddress);=0D - if (EFI_ERROR (Status)) {=0D - DEBUG ((DEBUG_ERROR, "WriteSingleBlock: ERROR - Failed to Unlock and E= rase the single block at 0x%X\n", BlockAddress));=0D - goto EXIT;=0D - }=0D -=0D - // To speed up the programming operation, NOR Flash is programmed using = the Buffered Programming method.=0D -=0D - // Check that the address starts at a 32-word boundary, i.e. last 7 bits= must be zero=0D - if ((WordAddress & BOUNDARY_OF_32_WORDS) =3D=3D 0x00) {=0D - // First, break the entire block into buffer-sized chunks.=0D - BuffersInBlock =3D (UINTN)(BlockSizeInWords * 4) / P30_MAX_BUFFER_SIZE= _IN_BYTES;=0D -=0D - // Then feed each buffer chunk to the NOR Flash=0D - // If a buffer does not contain any data, don't write it.=0D - for (BufferIndex =3D 0;=0D - BufferIndex < BuffersInBlock;=0D - BufferIndex++, WordAddress +=3D P30_MAX_BUFFER_SIZE_IN_BYTES, Dat= aBuffer +=3D P30_MAX_BUFFER_SIZE_IN_WORDS=0D - )=0D - {=0D - // Check the buffer to see if it contains any data (not set all 1s).= =0D - for (Cnt =3D 0; Cnt < P30_MAX_BUFFER_SIZE_IN_WORDS; Cnt++) {=0D - if (~DataBuffer[Cnt] !=3D 0 ) {=0D - // Some data found, write the buffer.=0D - Status =3D NorFlashWriteBuffer (=0D - Instance,=0D - WordAddress,=0D - P30_MAX_BUFFER_SIZE_IN_BYTES,=0D - DataBuffer=0D - );=0D - if (EFI_ERROR (Status)) {=0D - goto EXIT;=0D - }=0D -=0D - break;=0D - }=0D - }=0D - }=0D -=0D - // Finally, finish off any remaining words that are less than the maxi= mum size of the buffer=0D - RemainingWords =3D BlockSizeInWords % P30_MAX_BUFFER_SIZE_IN_WORDS;=0D + UINTN Index;=0D =0D - if (RemainingWords !=3D 0) {=0D - Status =3D NorFlashWriteBuffer (Instance, WordAddress, (RemainingWor= ds * 4), DataBuffer);=0D - if (EFI_ERROR (Status)) {=0D - goto EXIT;=0D - }=0D - }=0D - } else {=0D - // For now, use the single word programming algorithm=0D - // It is unlikely that the NOR Flash will exist in an address which fa= lls within a 32 word boundary range,=0D - // i.e. which ends in the range 0x......01 - 0x......7F.=0D - for (WordIndex =3D 0; WordIndex < BlockSizeInWords; WordIndex++, DataB= uffer++, WordAddress =3D WordAddress + 4) {=0D - Status =3D NorFlashWriteSingleWord (Instance, WordAddress, *DataBuff= er);=0D - if (EFI_ERROR (Status)) {=0D - goto EXIT;=0D - }=0D + for (Index =3D 0; Index < mNorFlashDeviceCount; Index++) {=0D + EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->DeviceBas= eAddress);=0D + EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->RegionBas= eAddress);=0D +=0D + // Convert Fvb=0D + EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->FvbProtoc= ol.EraseBlocks);=0D + EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->FvbProtoc= ol.GetAttributes);=0D + EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->FvbProtoc= ol.GetBlockSize);=0D + EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->FvbProtoc= ol.GetPhysicalAddress);=0D + EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->FvbProtoc= ol.Read);=0D + EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->FvbProtoc= ol.SetAttributes);=0D + EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->FvbProtoc= ol.Write);=0D +=0D + if (mNorFlashInstances[Index]->ShadowBuffer !=3D NULL) {=0D + EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->ShadowB= uffer);=0D }=0D }=0D =0D -EXIT:=0D - // Put device back into Read Array mode=0D - SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);=0D -=0D - if (!EfiAtRuntime ()) {=0D - // Interruptions can resume.=0D - gBS->RestoreTPL (OriginalTPL);=0D - }=0D -=0D - if (EFI_ERROR (Status)) {=0D - DEBUG ((DEBUG_ERROR, "NOR FLASH Programming [WriteSingleBlock] failed = at address 0x%08x. Exit Status =3D \"%r\".\n", WordAddress, Status));=0D - }=0D -=0D - return Status;=0D + return;=0D }=0D =0D EFI_STATUS=0D diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.h b/OvmfPkg/VirtNorFla= shDxe/VirtNorFlashDxe.h new file mode 100644 index 000000000000..3c7f5094153f --- /dev/null +++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.h @@ -0,0 +1,156 @@ +/** @file VirtNorFlashDxe.h=0D +=0D + Copyright (c) 2011 - 2021, Arm Limited. All rights reserved.
=0D + Copyright (c) 2025, Ventana Micro Systems Inc. All rights reserved.
= =0D +=0D + SPDX-License-Identifier: BSD-2-Clause-Patent=0D +=0D +**/=0D +=0D +#ifndef __VIRT_NOR_FLASH_DXE__=0D +#define __VIRT_NOR_FLASH_DXE__=0D +=0D +#include =0D +#include =0D +=0D +#include =0D +=0D +#include =0D +=0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +=0D +#define NOR_FLASH_SIGNATURE SIGNATURE_32('n', 'o', 'r', '0')=0D +#define INSTANCE_FROM_FVB_THIS(a) CR(a, NOR_FLASH_INSTANCE, FvbProtocol, = NOR_FLASH_SIGNATURE)=0D +=0D +typedef struct _NOR_FLASH_INSTANCE NOR_FLASH_INSTANCE;=0D +=0D +#pragma pack (1)=0D +typedef struct {=0D + VENDOR_DEVICE_PATH Vendor;=0D + UINT8 Index;=0D + EFI_DEVICE_PATH_PROTOCOL End;=0D +} NOR_FLASH_DEVICE_PATH;=0D +#pragma pack ()=0D +=0D +struct _NOR_FLASH_INSTANCE {=0D + UINT32 Signature;=0D + EFI_HANDLE Handle;=0D +=0D + UINTN DeviceBaseAddress;=0D + UINTN RegionBaseAddress;=0D + UINTN Size;=0D + EFI_LBA StartLba;=0D + EFI_LBA LastBlock;=0D + UINT32 BlockSize;=0D +=0D + EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL FvbProtocol;=0D + VOID *ShadowBuffer;=0D +=0D + NOR_FLASH_DEVICE_PATH DevicePath;=0D +};=0D +=0D +//=0D +// NorFlashFvbDxe.c=0D +//=0D +=0D +EFI_STATUS=0D +EFIAPI=0D +FvbGetAttributes (=0D + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,=0D + OUT EFI_FVB_ATTRIBUTES_2 *Attributes=0D + );=0D +=0D +EFI_STATUS=0D +EFIAPI=0D +FvbSetAttributes (=0D + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,=0D + IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes=0D + );=0D +=0D +EFI_STATUS=0D +EFIAPI=0D +FvbGetPhysicalAddress (=0D + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,=0D + OUT EFI_PHYSICAL_ADDRESS *Address=0D + );=0D +=0D +EFI_STATUS=0D +EFIAPI=0D +FvbGetBlockSize (=0D + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,=0D + IN EFI_LBA Lba,=0D + OUT UINTN *BlockSize,=0D + OUT UINTN *NumberOfBlocks=0D + );=0D +=0D +EFI_STATUS=0D +EFIAPI=0D +FvbRead (=0D + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,=0D + IN EFI_LBA Lba,=0D + IN UINTN Offset,=0D + IN OUT UINTN *NumBytes,=0D + IN OUT UINT8 *Buffer=0D + );=0D +=0D +EFI_STATUS=0D +EFIAPI=0D +FvbWrite (=0D + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,=0D + IN EFI_LBA Lba,=0D + IN UINTN Offset,=0D + IN OUT UINTN *NumBytes,=0D + IN UINT8 *Buffer=0D + );=0D +=0D +EFI_STATUS=0D +EFIAPI=0D +FvbEraseBlocks (=0D + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,=0D + ...=0D + );=0D +=0D +EFI_STATUS=0D +ValidateFvHeader (=0D + IN NOR_FLASH_INSTANCE *Instance=0D + );=0D +=0D +EFI_STATUS=0D +InitializeFvAndVariableStoreHeaders (=0D + IN NOR_FLASH_INSTANCE *Instance=0D + );=0D +=0D +VOID=0D +EFIAPI=0D +FvbVirtualNotifyEvent (=0D + IN EFI_EVENT Event,=0D + IN VOID *Context=0D + );=0D +=0D +//=0D +// NorFlashDxe.c=0D +//=0D +EFI_STATUS=0D +NorFlashCreateInstance (=0D + IN UINTN NorFlashDeviceBase,=0D + IN UINTN NorFlashRegionBase,=0D + IN UINTN NorFlashSize,=0D + IN UINT32 Index,=0D + IN UINT32 BlockSize,=0D + IN BOOLEAN SupportFvb,=0D + OUT NOR_FLASH_INSTANCE **NorFlashInstance=0D + );=0D +=0D +EFI_STATUS=0D +EFIAPI=0D +NorFlashFvbInitialize (=0D + IN NOR_FLASH_INSTANCE *Instance=0D + );=0D +=0D +#endif /* __VIRT_NOT_FLASH_DXE__ */=0D diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.inf b/OvmfPkg/VirtNorF= lashDxe/VirtNorFlashDxe.inf index f549400280a1..6d6d615a6219 100644 --- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.inf +++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.inf @@ -17,8 +17,6 @@ ENTRY_POINT =3D NorFlashInitialise=0D =0D [Sources.common]=0D - VirtNorFlash.c=0D - VirtNorFlash.h=0D VirtNorFlashDxe.c=0D VirtNorFlashFvb.c=0D =0D @@ -39,6 +37,7 @@ UefiDriverEntryPoint=0D UefiLib=0D UefiRuntimeLib=0D + VirtNorFlashDeviceLib=0D VirtNorFlashPlatformLib=0D =0D [Guids]=0D diff --git a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashFvb.c b/OvmfPkg/VirtNorFla= shDxe/VirtNorFlashFvb.c index c8b5e0be1379..0d6c9ef01631 100644 --- a/OvmfPkg/VirtNorFlashDxe/VirtNorFlashFvb.c +++ b/OvmfPkg/VirtNorFlashDxe/VirtNorFlashFvb.c @@ -19,7 +19,7 @@ #include =0D #include =0D =0D -#include "VirtNorFlash.h"=0D +#include "VirtNorFlashDxe.h"=0D =0D extern UINTN mFlashNvStorageVariableBase;=0D ///=0D @@ -653,13 +653,30 @@ FvbRead ( =0D // Decide if we are doing full block reads or not.=0D if (*NumBytes % BlockSize !=3D 0) {=0D - TempStatus =3D NorFlashRead (Instance, Instance->StartLba + Lba, Offse= t, *NumBytes, Buffer);=0D + TempStatus =3D NorFlashRead (=0D + Instance->DeviceBaseAddress,=0D + Instance->RegionBaseAddress,=0D + Instance->StartLba + Lba,=0D + Instance->BlockSize,=0D + Instance->Size,=0D + Offset,=0D + *NumBytes,=0D + Buffer=0D + );=0D if (EFI_ERROR (TempStatus)) {=0D return EFI_DEVICE_ERROR;=0D }=0D } else {=0D // Read NOR Flash data into shadow buffer=0D - TempStatus =3D NorFlashReadBlocks (Instance, Instance->StartLba + Lba,= BlockSize, Buffer);=0D + TempStatus =3D NorFlashReadBlocks (=0D + Instance->DeviceBaseAddress,=0D + Instance->RegionBaseAddress,=0D + Instance->StartLba + Lba,=0D + Instance->LastBlock,=0D + Instance->BlockSize,=0D + BlockSize,=0D + Buffer=0D + );=0D if (EFI_ERROR (TempStatus)) {=0D // Return one of the pre-approved error statuses=0D return EFI_DEVICE_ERROR;=0D @@ -737,7 +754,18 @@ FvbWrite ( =0D Instance =3D INSTANCE_FROM_FVB_THIS (This);=0D =0D - return NorFlashWriteSingleBlock (Instance, Instance->StartLba + Lba, Off= set, NumBytes, Buffer);=0D + return NorFlashWriteSingleBlock (=0D + Instance->DeviceBaseAddress,=0D + Instance->RegionBaseAddress,=0D + Instance->StartLba + Lba,=0D + Instance->LastBlock,=0D + Instance->BlockSize,=0D + Instance->Size,=0D + Offset,=0D + NumBytes,=0D + Buffer,=0D + Instance->ShadowBuffer=0D + );=0D }=0D =0D /**=0D @@ -795,6 +823,7 @@ FvbEraseBlocks ( UINTN BlockAddress; // Physical address of Lba to erase=0D EFI_LBA StartingLba; // Lba from which we start erasing=0D UINTN NumOfLba; // Number of Lba blocks to erase=0D + EFI_TPL OriginalTPL;=0D NOR_FLASH_INSTANCE *Instance;=0D =0D Instance =3D INSTANCE_FROM_FVB_THIS (This);=0D @@ -865,7 +894,21 @@ FvbEraseBlocks ( =0D // Erase it=0D DEBUG ((DEBUG_BLKIO, "FvbEraseBlocks: Erasing Lba=3D%ld @ 0x%08x.\n"= , Instance->StartLba + StartingLba, BlockAddress));=0D - Status =3D NorFlashUnlockAndEraseSingleBlock (Instance, BlockAddress= );=0D + if (!EfiAtRuntime ()) {=0D + // Raise TPL to TPL_HIGH to stop anyone from interrupting us.=0D + OriginalTPL =3D gBS->RaiseTPL (TPL_HIGH_LEVEL);=0D + } else {=0D + // This initialization is only to prevent the compiler to complain= about the=0D + // use of uninitialized variables=0D + OriginalTPL =3D TPL_HIGH_LEVEL;=0D + }=0D +=0D + Status =3D NorFlashUnlockAndEraseSingleBlock (Instance->DeviceBaseAd= dress, BlockAddress);=0D + if (!EfiAtRuntime ()) {=0D + // Interruptions can resume.=0D + gBS->RestoreTPL (OriginalTPL);=0D + }=0D +=0D if (EFI_ERROR (Status)) {=0D VA_END (Args);=0D Status =3D EFI_DEVICE_ERROR;=0D --=20 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] -=-=-=-=-=-=-=-=-=-=-=-