From nobody Mon Feb 9 19:52:57 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+72820+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+72820+1787277+3901457@groups.io ARC-Seal: i=1; a=rsa-sha256; t=1615842084; cv=none; d=zohomail.com; s=zohoarc; b=WHSkhIjMLNlioroPedN/w4qfp0kD9jwulS5al1J6oiGWCPDi7bQUoarrC7UT0n0ZvMiTeTdLgXJdA/4hTYN0OivAcvV13BD9+H3zUeopCCUM8tJNkI7Qo6y6SSwVysvqSiSHlNRSFkrv7zz3zBJU5j0qTjVKzilMlPeH+t2yI2k= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1615842084; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Id:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=8q76vcfqDFkEgalQVYNjPzG6r80kVYmw519YqO6HAK0=; b=Mqav8h/qO/hfiywDSvrnav9MIWkwz1GkT8nLEkwbavZis5quLsDApgNk69C0Y+/HUHPN5xYGGUDt54DpTqwD/dHOxP8s08XIt4/itbe0tyBQqQu2cJHaxifVkBg+RbwBT98K79ahD4drsBluaxPhH9TcXiOVp3EwfwypARTCRqs= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+72820+1787277+3901457@groups.io Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1615842081274399.49307075808883; Mon, 15 Mar 2021 14:01:21 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id uJG8YY1788612xw2iJzs1bzX; Mon, 15 Mar 2021 14:01:18 -0700 X-Received: from zg8tmty1ljiyny4xntqumjca.icoremail.net (zg8tmty1ljiyny4xntqumjca.icoremail.net [165.227.154.27]) by mx.groups.io with SMTP id smtpd.web10.6609.1615546927523840071 for ; Fri, 12 Mar 2021 03:02:08 -0800 X-Received: from localhost.localdomain (unknown [223.104.131.160]) by c1app4 (Coremail) with SMTP id BAINCgC3mwEVSktgMY01BQ--.34795S11; Fri, 12 Mar 2021 19:02:04 +0800 (CST) From: Ling Jia To: devel@edk2.groups.io Cc: Leif Lindholm , Peng Xie , Yiqi Shu , Ling Jia Subject: [edk2-devel] [PATCH v3 21/46] Silicon/Phytium: Added fvb driver for norflash Date: Fri, 12 Mar 2021 19:01:29 +0800 Message-Id: <20210312110141.75749-10-jialing@phytium.com.cn> In-Reply-To: <20210312110141.75749-1-jialing@phytium.com.cn> References: <20210312110141.75749-1-jialing@phytium.com.cn> MIME-Version: 1.0 X-CM-TRANSID: BAINCgC3mwEVSktgMY01BQ--.34795S11 X-Coremail-Antispam: 1UD129KBjvAXoWDJw4UXrW3KF15Kr4DKr13twb_yoWrCrykWo WxZr4fXw18trWSgFs8trWjk3yxJFnaqanxtrs5Zry2q3Z5Jw1a9FWIy3WUWw4ft34jkrnx KryfX3s5JFW3trykn29KB7ZKAUJUUUUU529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 AaLaJ3UjIYCTnIWjp_UUUY_7AC8VAFwI0_Wr0E3s1l1xkIjI8I6I8E6xAIw20EY4v20xva j40_Wr0E3s1l1IIY67AEw4v_Jr0_Jr4l82xGYIkIc2x26280x7IE14v26r126s0DM28Irc Ia0xkI8VCY1x0267AKxVW5JVCq3wA2ocxC64kIII0Yj41l84x0c7CEw4AK67xGY2AK021l 84ACjcxK6xIIjxv20xvE14v26r4j6ryUM28EF7xvwVC0I7IYx2IY6xkF7I0E14v26F4j6r 4UJwA2z4x0Y4vEx4A2jsIE14v26r4UJVWxJr1l84ACjcxK6I8E87Iv6xkF7I0E14v26rxl 6s0DM2AIxVAIcxkEcVAq07x20xvEncxIr21l5I8CrVACY4xI64kE6c02F40Ex7xfMcIj6x IIjxv20xvE14v26r106r15McIj6I8E87Iv67AKxVWUJVW8JwAm72CE4IkC6x0Yz7v_Jr0_ Gr1lF7xvr2IYc2Ij64vIr41lF7I21c0EjII2zVCS5cI20VAGYxC7MxkIecxEwVAFwVW8Kw CF04k20xvY0x0EwIxGrwCFx2IqxVCFs4IE7xkEbVWUJVW8JwC20s026c02F40E14v26r1j 6r18MI8I3I0E7480Y4vE14v26r106r1rMI8E67AF67kF1VAFwI0_JF0_Jw1lIxkGc2Ij64 vIr41lIxAIcVC0I7IYx2IY67AKxVW8JVW5JwCI42IY6xIIjxv20xvEc7CjxVAFwI0_Cr0_ Gr1UMIIF0xvE42xK8VAvwI8IcIk0rVWUJVWUCwCI42IY6I8E87Iv67AKxVW8JVWxJwCI42 IY6I8E87Iv6xkF7I0E14v26r4j6r4UJbIYCTnIWIevJa73UjIFyTuYvjfUOsjjDUUUU X-Originating-IP: [223.104.131.160] X-CM-SenderInfo: xmldzxdqj61x51wl3zoofrzhdfq/ Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,jialing@phytium.com.cn X-Gm-Message-State: tJMetzSQK0LL04zTbFwwRYPPx1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1615842078; bh=64wY2wHuEKyULfz6Dx4flWeuMnRVG5i0tEJ1WHP9qsY=; h=Cc:Date:From:Reply-To:Subject:To; b=kVkTjYE9877jSsrNiegBilvMHMA4v1+wN+fAo9Z+/+GD7cbHQMM22O24xXrfz6FrXNP /VRIxDvaV39XRQQjyFh+6vfxnXjkImaky6QflPd4kqS1IaRI1QQamtWGKwqMEKhNmAfeE 4YiWhBzr2d5CGwykR46zV4ZYYU4rlIJ8quY= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Type: text/plain; charset="utf-8" The FlashFvbDxe provided the fvb protocol, which requested by the flash operators. v3: Optimized the codes to conform to specifications. Signed-off-by: Ling Jia Reviewed-by: Leif Lindholm --- Platform/Phytium/DurianPkg/DurianPkg.dsc | = 1 + Platform/Phytium/DurianPkg/DurianPkg.fdf | = 1 + Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.inf | 6= 1 + Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.h | 10= 4 ++ Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.c | 130= 4 ++++++++++++++++++++ 5 files changed, 1471 insertions(+) diff --git a/Platform/Phytium/DurianPkg/DurianPkg.dsc b/Platform/Phytium/Du= rianPkg/DurianPkg.dsc index 1c4705144151..99034365d38f 100644 --- a/Platform/Phytium/DurianPkg/DurianPkg.dsc +++ b/Platform/Phytium/DurianPkg/DurianPkg.dsc @@ -253,6 +253,7 @@ [Components.common] # NOR Flash driver # Silicon/Phytium/FT2000-4Pkg/Drivers/SpiNorFlashDxe/SpiNorFlashDxe.inf + Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.inf =20 # # Usb Support diff --git a/Platform/Phytium/DurianPkg/DurianPkg.fdf b/Platform/Phytium/Du= rianPkg/DurianPkg.fdf index 831f7a682837..67458458ddd5 100644 --- a/Platform/Phytium/DurianPkg/DurianPkg.fdf +++ b/Platform/Phytium/DurianPkg/DurianPkg.fdf @@ -103,6 +103,7 @@ [FV.FvMain] =20 INF ArmPkg/Drivers/ArmGic/ArmGicDxe.inf INF ArmPkg/Drivers/CpuDxe/CpuDxe.inf + INF Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.inf INF ArmPkg/Drivers/TimerDxe/TimerDxe.inf INF ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdogDxe.inf =20 diff --git a/Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbD= xe.inf b/Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.i= nf new file mode 100644 index 000000000000..ff23721d6e41 --- /dev/null +++ b/Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.inf @@ -0,0 +1,61 @@ +#/** @file +# Phytium NorFlash Fvb Drivers. +# +# Copyright (c) 2011 - 2014, ARM Ltd. All rights reserved.
+# Copyright (C) 2020, Phytium Technology Co, Ltd. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +#**/ + +[Defines] + INF_VERSION =3D 0x0001001b + BASE_NAME =3D FlashFvbDxe + FILE_GUID =3D b8923820-3e7c-11eb-b12c-17525e90ecc8 + MODULE_TYPE =3D DXE_RUNTIME_DRIVER + VERSION_STRING =3D 0.1 + ENTRY_POINT =3D FvbEntryPoint + +[Sources] + FlashFvbDxe.c + FlashFvbDxe.h + +[Packages] + EmbeddedPkg/EmbeddedPkg.dec + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + Silicon/Phytium/PhytiumCommonPkg/PhytiumCommonPkg.dec + +[LibraryClasses] + BaseLib + DebugLib + DxeServicesTableLib + HobLib + MemoryAllocationLib + UefiBootServicesTableLib + UefiRuntimeLib + UefiDriverEntryPoint + +[Guids] + gEfiAuthenticatedVariableGuid + gEfiEventVirtualAddressChangeGuid + gEfiSystemNvDataFvGuid + gEfiVariableGuid + +[Protocols] + gEfiDevicePathProtocolGuid + gEfiFirmwareVolumeBlockProtocolGuid + gSpiNorFlashProtocolGuid + +[Pcd.common] + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64 + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase64 + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase64 + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize + gPhytiumPlatformTokenSpaceGuid.PcdSpiFlashBase + gPhytiumPlatformTokenSpaceGuid.PcdSpiFlashSize + +[Depex] + gSpiNorFlashProtocolGuid diff --git a/Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbD= xe.h b/Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.h new file mode 100644 index 000000000000..e63ff9f220f6 --- /dev/null +++ b/Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.h @@ -0,0 +1,104 @@ +/** @file + Phytium NorFlash Fvb Drivers Header. + + Copyright (C) 2020, Phytium Technology Co Ltd. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ +#ifndef FVB_FLASH_DXE_H_ +#define FVB_FLASH_DXE_H_ + +#include +#include +#include + +#define GET_DATA_OFFSET(BaseAddr, Lba, LbaSize) ((BaseAddr) + (UINTN)((Lba= ) * (LbaSize))) +#define FVB_FLASH_SIGNATURE SIGNATURE_32('S', 'N', '= O', 'R') +#define INSTANCE_FROM_FVB_THIS(a) CR(a, FT_FVB_DEVICE, Fvb= Protocol, FVB_FLASH_SIGNATURE) + +typedef struct _FT_FVB_DEVICE FT_FVB_DEVICE; + +#define NOR_FLASH_ERASE_RETRY 10 + +typedef struct { + VENDOR_DEVICE_PATH Vendor; + EFI_DEVICE_PATH_PROTOCOL End; + } FT_FVB_DEVICE_PATH; + +struct _FT_FVB_DEVICE { + UINT32 Signature; + EFI_HANDLE Handle; + + UINTN DeviceBaseAddress; + UINTN RegionBaseAddress; + UINTN Size; + EFI_LBA StartLba; + EFI_BLOCK_IO_MEDIA Media; + + EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL FvbProtocol; + + FT_FVB_DEVICE_PATH DevicePath; + EFI_NORFLASH_DRV_PROTOCOL *SpiFlashProtocol; + VOID *ShadowBuffer; + UINTN FvbSize; + }; + +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, + ... + ); + +#endif // FVB_FLASH_DXE_H_ diff --git a/Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbD= xe.c b/Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.c new file mode 100644 index 000000000000..f6369c1ad979 --- /dev/null +++ b/Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.c @@ -0,0 +1,1304 @@ +/** @file + Phytium NorFlash Fvb Drivers. + + Copyright (c) 2011 - 2014, ARM Ltd. All rights reserved.
+ Copyright (C) 2020, Phytium Technology Co Ltd. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "FlashFvbDxe.h" + +STATIC EFI_EVENT FvbVirtualAddrChangeEvent; +STATIC FT_FVB_DEVICE *FvbDevice; +STATIC UINTN mFlashNvStorageVariableBase; +STATIC UINTN mFlashNvStorageFtwWorkingBase; +STATIC UINTN mFlashNvStorageFtwSpareBase; +STATIC UINT32 mFlashNvStorageVariableSize; +STATIC UINT32 mFlashNvStorageFtwWorkingSize; +STATIC UINT32 mFlashNvStorageFtwSpareSize; + +STATIC FT_FVB_DEVICE FvbFlashInstanceTemplate =3D { + FVB_FLASH_SIGNATURE, // Signature + NULL, // Handle ... NEED TO BE FILLED + 0, // DeviceBaseAddress ... NEED TO BE FILLED + 0, // RegionBaseAddress ... NEED TO BE FILLED + 0, // Size ... NEED TO BE FILLED + 0, // StartLba + { + 0, // MediaId ... NEED TO BE FILLED + FALSE, // RemovableMedia + TRUE, // MediaPresent + FALSE, // LogicalPartition + FALSE, // ReadOnly + FALSE, // WriteCaching; + 0, // BlockSize ... NEED TO BE FILLED + 4, // IoAlign + 0, // LastBlock ... NEED TO BE FILLED + 0, // LowestAlignedLba + 1, // LogicalBlocksPerPhysicalBlock + }, //Media; + { + FvbGetAttributes, // GetAttributes + FvbSetAttributes, // SetAttributes + FvbGetPhysicalAddress, // GetPhysicalAddress + FvbGetBlockSize, // GetBlockSize + FvbRead, // Read + FvbWrite, // Write + FvbEraseBlocks, // EraseBlocks + NULL, // ParentHandle + }, // FvbProtoccol; + + { + { + { + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP, + { + (UINT8) sizeof (VENDOR_DEVICE_PATH), + (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) + } + }, + { + 0x0, 0x0, 0x0, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } + }, // GUID ... NEED TO BE FILLED + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + sizeof (EFI_DEVICE_PATH_PROTOCOL), + 0 + } + } + }, // DevicePath + + NULL, // SpiFlashProtocol ... NEED TO BE FILLED + NULL, // ShadowBuffer ... NEED TO BE FILLED + 0 // Fvb Size +}; + + +/** + Erases a single block of flash. + + @param[in] FlashInstance The poiter of the fvb device sturct. + + @param[in] BlockAddress Physical address of Lba to be erased. + + @retval EFI_SUCCESS The erase single block request successfull= y completed. + +**/ +STATIC +EFI_STATUS +FvbFlashEraseSingleBlock ( + IN FT_FVB_DEVICE *FlashInstance, + IN UINTN BlockAddress + ) +{ + EFI_STATUS Status; + UINTN Index; + EFI_TPL OriginalTPL; + + if ( ! EfiAtRuntime ()) { + OriginalTPL =3D gBS->RaiseTPL (TPL_HIGH_LEVEL); + } else { + OriginalTPL =3D TPL_HIGH_LEVEL; + } + + Index =3D 0; + + do { + Status =3D FlashInstance->SpiFlashProtocol->EraseSingleBlock (BlockAdd= ress); + Index++; + } while ((Index < NOR_FLASH_ERASE_RETRY) && (Status =3D=3D EFI_WRITE_PRO= TECTED)); + + if (Index =3D=3D NOR_FLASH_ERASE_RETRY) { + DEBUG (( + DEBUG_ERROR, + "EraseSingleBlock(BlockAddress=3D0x%08x: BlockLocked Error (try to e= rase % d times)\n", + BlockAddress, + Index + )); + } + + if ( ! EfiAtRuntime ()) { + gBS->RestoreTPL (OriginalTPL); + } + + return Status; +} + + +/** + Readed the specified number of bytes from the form the block to output b= uffer. + + @param[in] FlashInstance The pointer of FT_FVB_DEVICE instance. + + @param[in] Lba The starting logical block index to wri= te to. + + @param[in] Offset Offset into the block at which to begin= writing. + + @param[in] BufferSizeInBytes The number of bytes to be writed. + + @param[out] Buffer The pointer to a caller-allocated buffe= r that + contains the source for the write. + + @retval EFI_SUCCESS FvbFlashRead() is executed successfully. + +**/ +STATIC +EFI_STATUS +FvbFlashRead ( + IN FT_FVB_DEVICE *FlashInstance, + IN EFI_LBA Lba, + IN UINTN Offset, + IN UINTN BufferSizeInBytes, + OUT VOID *Buffer + ) +{ + UINTN Address; + + Address =3D GET_DATA_OFFSET ( + FlashInstance->RegionBaseAddress, + Lba, + FlashInstance->Media.BlockSize + ) + Offset; + + if (BufferSizeInBytes =3D=3D 0) { + return EFI_SUCCESS; + } + + // The buffer must be valid + if (Buffer =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + return FlashInstance->SpiFlashProtocol->Read (Address, Buffer, BufferSiz= eInBytes); +} + + +/** + Write a full or portion of a block. It must not span block boundaries; t= hat is, + Offset + *NumBytes <=3D FlashInstance->Media.BlockSize. + + @param[in] FlashInstance The pointer of FT_FVB_DEVICE instance. + + @param[in] Lba The starting logical block index to wri= te to. + + @param[in] Offset Offset into the block at which to begin= writing. + + @param[in] BufferSizeInBytes The number of bytes to be writed. + + @param[out] Buffer The pointer to a caller-allocated buffe= r that + contains the source for the write. + + @retval EFI_SUCCESS FvbWriteBlock() is executed successfull= y. + + @retval EFI_BAD_BUFFER_SIZE The write spaned block boundaries. + +**/ +STATIC +EFI_STATUS +FvbWriteBlock ( + IN FT_FVB_DEVICE *FlashInstance, + IN EFI_LBA Lba, + IN UINTN Offset, + IN UINTN BufferSizeInBytes, + IN UINT8 *Buffer + ) +{ + EFI_STATUS Status; + UINTN BlockSize; + UINTN BlockAddress; + + // Detect WriteDisabled state + if (FlashInstance->Media.ReadOnly =3D=3D TRUE) { + DEBUG (( + DEBUG_ERROR, + "FvbWriteBlock: ERROR - Can not write:Device is in WriteDisabled sta= te.\n" + )); + // It is in WriteDisabled state, return an error right away + return EFI_ACCESS_DENIED; + } + + // Cache the block size to avoid de-referencing pointers all the time + BlockSize =3D FlashInstance->Media.BlockSize; + + // The write must not span block boundaries. + // We need to check each variable individually because adding two large = values together overflows. + if ((Offset >=3D BlockSize) || + (BufferSizeInBytes > BlockSize) || + ((Offset + BufferSizeInBytes) > BlockSize)) + { + DEBUG (( + DEBUG_ERROR, + "FvbWriteBlock: ERROR - EFI_BAD_BUFFER_SIZE: (Offset =3D0x %x + NumB= ytes =3D0x%x) > BlockSize =3D0x%x\n", + Offset, + BufferSizeInBytes, + BlockSize + )); + return EFI_BAD_BUFFER_SIZE; + } + + // We must have some bytes to write + if (BufferSizeInBytes =3D=3D 0) { + DEBUG (( + DEBUG_ERROR, + "FvbWriteBlock: ERROR - EFI_BAD_BUFFER_SIZE: NumBytes =3D=3D 0\n" + )); + return EFI_BAD_BUFFER_SIZE; + } + + // Check we did get some memory. Buffer is BlockSize. + if (FlashInstance->ShadowBuffer =3D=3D NULL) { + DEBUG (( + DEBUG_ERROR, + "FvbWriteBlock: ERROR - ShadowBuffer is NULL!\n" + )); + return EFI_DEVICE_ERROR; + } + + // + // Write the word to NOR. + // + BlockAddress =3D GET_DATA_OFFSET ( + FlashInstance->RegionBaseAddress, + Lba, + FlashInstance->Media.BlockSize + ); + + // Read NOR Flash data into shadow buffer + Status =3D FlashInstance->SpiFlashProtocol->Read ( + BlockAddress, + FlashInstance->ShadowBuffer, + BlockSize + ); + 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)FlashInstance->ShadowBuffer + Offset), + Buffer, + BufferSizeInBytes + ); + + Status =3D FlashInstance->SpiFlashProtocol->EraseSingleBlock (BlockAddre= ss); + if (EFI_ERROR (Status)) { + // Return one of the pre-approved error statuses + return EFI_DEVICE_ERROR; + } + + // Write the modified buffer back to the NorFlash + Status =3D FlashInstance->SpiFlashProtocol->Write (BlockAddress, + FlashInstance->ShadowBuffer, + BlockSize + ); + if (EFI_ERROR (Status)) { + // Return one of the pre-approved error statuses + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + + +/** + Writes the specified number of bytes from the input buffer to the block. + + @param[in] FlashInstance The pointer of FT_FVB_DEVICE instance. + + @param[in] Lba The starting logical block index to writ= e to. + + @param[in] Offset Offset into the block at which to begin = writing. + + @param[in] BufferSizeInBytes The number of bytes to be writed. + + @param[in] Buffer The pointer to a caller-allocated buffer= that + contains the source for the write. + + @retval EFI_SUCCESS FvbFlashWrite() is executed successfully. + + @retval EFI_WRITE_PROTECTED Flash state is in the WriteDisabled stat= e. + + @retval EFI_INVALID_PARAMETER The pointer of Buffer is NULL. + +**/ +STATIC +EFI_STATUS +FvbFlashWrite ( + IN FT_FVB_DEVICE *FlashInstance, + IN EFI_LBA Lba, + IN UINTN Offset, + IN UINTN BufferSizeInBytes, + IN VOID *Buffer + ) +{ + EFI_STATUS Status; + UINT32 BlockSize; + UINT32 BlockOffset; + UINTN RemainingBytes; + UINTN WriteSize; + + if (FlashInstance->Media.ReadOnly =3D=3D TRUE) { + return EFI_WRITE_PROTECTED; + } + + if (BufferSizeInBytes =3D=3D 0) { + return EFI_SUCCESS; + } + + if (Buffer =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + Status =3D EFI_SUCCESS; + BlockSize =3D FlashInstance->Media.BlockSize; + BlockOffset =3D Offset; + RemainingBytes =3D BufferSizeInBytes; + + // The write must not span block boundaries. + // We need to check each variable individually because adding + // two large values together overflows. + if (Offset >=3D BlockSize) { + DEBUG (( + DEBUG_ERROR, + "FvbFlashWrite: ERROR - EFI_BAD_BUFFER_SIZE: Offset =3D0x%x > BlockS= ize =3D0x%x\n", + Offset, + BlockSize + )); + return EFI_BAD_BUFFER_SIZE; + } + + // We must have some bytes to read + // Write either all the remaining bytes, or the number of bytes that bri= ng + // us up to a block boundary, whichever is less. + // (DiskOffset | (BlockSize - 1)) + 1) rounds DiskOffset up to the next + // block boundary (even if it is already on one). + WriteSize =3D MIN (RemainingBytes, BlockSize - BlockOffset); + + do { + Status =3D FvbWriteBlock ( + FlashInstance, + Lba, + BlockOffset, + WriteSize, + Buffer + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // Now continue writing either all the remaining bytes or single block= s. + RemainingBytes -=3D WriteSize; + Buffer =3D (UINT8 *) Buffer + WriteSize; + Lba++; + BlockOffset =3D 0; + WriteSize =3D MIN (RemainingBytes, BlockSize); + } while (RemainingBytes); + + return Status; +} + + +/** + Initialises the FV Header and Variable Store Header + to support variable operations. + + @param[in] Ptr Location to initialise the headers. + + @retval EFI_SUCCESS FvbInitFvAndVariableStoreHeaders() + is executed successfully. + +**/ +STATIC +EFI_STATUS +FvbInitFvAndVariableStoreHeaders ( + IN FT_FVB_DEVICE *FlashInstance + ) +{ + EFI_STATUS Status; + VOID * Headers; + UINTN HeadersLength; + UINT32 TempAttributes; + EFI_FIRMWARE_VOLUME_HEADER *FirmwareVolumeHeader; + VARIABLE_STORE_HEADER *VariableStoreHeader; + + HeadersLength =3D sizeof (EFI_FIRMWARE_VOLUME_HEADER) + + sizeof (EFI_FV_BLOCK_MAP_ENTRY) + + sizeof (VARIABLE_STORE_HEADER); + + Headers =3D AllocateZeroPool (HeadersLength); + + // FirmwareVolumeHeader->FvLength is declared to have the Variable area + // AND the FTW working area AND the FTW Spare contiguous. + ASSERT (mFlashNvStorageVariableBase + mFlashNvStorageVariableSize =3D=3D= mFlashNvStorageFtwWorkingBase); + ASSERT (mFlashNvStorageFtwWorkingBase + mFlashNvStorageFtwWorkingSize = =3D=3D mFlashNvStorageFtwSpareBase); + + // Check if the size of the area is at least one block size + ASSERT ((mFlashNvStorageVariableSize > 0) && (mFlashNvStorageVariableSiz= e / FlashInstance->Media.BlockSize > 0)); + ASSERT ((mFlashNvStorageFtwWorkingSize > 0) && (mFlashNvStorageFtwWorkin= gSize / FlashInstance->Media.BlockSize > 0)); + ASSERT ((mFlashNvStorageFtwSpareSize > 0) && (mFlashNvStorageFtwSpareSiz= e / FlashInstance->Media.BlockSize > 0)); + + // Ensure the Variable area Base Addresses are aligned on a block size b= oundaries + ASSERT (mFlashNvStorageVariableBase % FlashInstance->Media.BlockSize =3D= =3D 0); + ASSERT (mFlashNvStorageFtwWorkingBase % FlashInstance->Media.BlockSize = =3D=3D 0); + ASSERT (mFlashNvStorageFtwSpareBase % FlashInstance->Media.BlockSize =3D= =3D 0); + + // + // EFI_FIRMWARE_VOLUME_HEADER + // + FirmwareVolumeHeader =3D (EFI_FIRMWARE_VOLUME_HEADER *)Headers; + CopyGuid (&FirmwareVolumeHeader->FileSystemGuid, &gEfiSystemNvDataFvGuid= ); + FirmwareVolumeHeader->FvLength =3D FlashInstance->FvbSize; + + TempAttributes =3D ( + EFI_FVB2_READ_ENABLED_CAP | // Reads may be enabled + EFI_FVB2_READ_STATUS | // Reads are currently = enabled + EFI_FVB2_STICKY_WRITE | // A block erase is req= uired to + EFI_FVB2_MEMORY_MAPPED | // It is memory mapped + EFI_FVB2_ERASE_POLARITY | // After erasure all bi= ts take this value + EFI_FVB2_WRITE_STATUS | // Writes are currently= enabled + EFI_FVB2_WRITE_ENABLED_CAP // Writes may be enabled + ); + + FirmwareVolumeHeader->Signature =3D EFI_FVH_SIGNATURE; + FirmwareVolumeHeader->Attributes =3D (EFI_FVB_ATTRIBUTES_2) TempAttribut= es; + + FirmwareVolumeHeader->HeaderLength =3D sizeof (EFI_FIRMWARE_VOLUME_HEADE= R) + sizeof (EFI_FV_BLOCK_MAP_ENTRY); + FirmwareVolumeHeader->Revision =3D EFI_FVH_REVISION; + FirmwareVolumeHeader->BlockMap[0].NumBlocks =3D FlashInstance->Media.Las= tBlock + 1; + FirmwareVolumeHeader->BlockMap[0].Length =3D FlashInstance->Media.Blo= ckSize; + FirmwareVolumeHeader->BlockMap[1].NumBlocks =3D 0; + FirmwareVolumeHeader->BlockMap[1].Length =3D 0; + FirmwareVolumeHeader->Checksum =3D CalculateCheckSum16 ( + (UINT16 *)FirmwareVolumeHeader, + FirmwareVolumeHeader->HeaderLength + ); + + // + // VARIABLE_STORE_HEADER + // + VariableStoreHeader =3D (VARIABLE_STORE_HEADER *) ((UINTN)Headers + Firm= wareVolumeHeader->HeaderLength); + CopyGuid (&VariableStoreHeader->Signature, &gEfiAuthenticatedVariableGui= d); + VariableStoreHeader->Size =3D mFlashNvStorageVariableSize - FirmwareVo= lumeHeader->HeaderLength; + VariableStoreHeader->Format =3D VARIABLE_STORE_FORMATTED; + VariableStoreHeader->State =3D VARIABLE_STORE_HEALTHY; + + // Install the combined super-header in the NorFlash + Status =3D FvbWrite (&FlashInstance->FvbProtocol, 0, 0, &HeadersLength, = Headers); + + FreePool (Headers); + + return Status; +} + + +/** + Check the integrity of firmware volume header. + + @param[in] FwVolHeader A pointer to a firmware volume header + + @retval EFI_SUCCESS The firmware volume is consistent + + @retval EFI_NOT_FOUND The firmware volume has been corrupted. + +**/ +STATIC +EFI_STATUS +FvbValidateFvHeader ( + IN FT_FVB_DEVICE *FlashInstance + ) +{ + UINT16 Checksum; + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; + VARIABLE_STORE_HEADER *VariableStoreHeader; + UINTN VariableStoreLength; + UINTN FvLength; + + FwVolHeader =3D (EFI_FIRMWARE_VOLUME_HEADER *)GET_DATA_OFFSET (FlashInst= ance->RegionBaseAddress, + FlashInstance->StartLba, + FlashInstance->Media.Block= Size + ); + FvLength =3D FlashInstance->FvbSize; + + + if ((FwVolHeader->Revision !=3D EFI_FVH_REVISION) || + (FwVolHeader->Signature !=3D EFI_FVH_SIGNATURE) || + (FwVolHeader->FvLength !=3D FvLength)) + { + DEBUG (( + DEBUG_ERROR, + "ValidateFvHeader: No Firmware Volume header present\n" + )); + return EFI_NOT_FOUND; + } + + // Check the Firmware Volume Guid + if ( CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiSystemNvDataFvGuid)= =3D=3D FALSE ) { + DEBUG (( + DEBUG_ERROR, + "ValidateFvHeader: Firmware Volume Guid non-compatible\n" + )); + return EFI_NOT_FOUND; + } + + // Verify the header checksum + Checksum =3D CalculateSum16 ((UINT16 *)FwVolHeader, FwVolHeader->HeaderL= ength); + if (Checksum !=3D 0) { + DEBUG (( + DEBUG_ERROR, + "ValidateFvHeader: FV checksum is invalid (Checksum:0x%X)\n", + Checksum)); + return EFI_NOT_FOUND; + } + + VariableStoreHeader =3D (VARIABLE_STORE_HEADER *) ((UINTN)FwVolHeader + = FwVolHeader->HeaderLength); + + // Check the Variable Store Guid + if ( ! CompareGuid (&VariableStoreHeader->Signature, &gEfiVariableGuid) = && + ! CompareGuid (&VariableStoreHeader->Signature, + &gEfiAuthenticatedVariableGuid)) + { + DEBUG (( + DEBUG_ERROR, + "%a: Variable Store Guid non-compatible\n" + )); + return EFI_NOT_FOUND; + } + + VariableStoreLength =3D mFlashNvStorageVariableSize - FwVolHeader->Heade= rLength; + if (VariableStoreHeader->Size !=3D VariableStoreLength) { + DEBUG (( + DEBUG_ERROR, + "ValidateFvHeader: Variable Store Length does not match\n" + )); + return EFI_NOT_FOUND; + } + + return EFI_SUCCESS; +} + + +/** + The FvbGetAttributes() function retrieves the attributes and + current settings of the block. + + @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL in= stance. + + @param Attributes Pointer to EFI_FVB_ATTRIBUTES_2 in which the attribu= tes and + current settings are returned. + Type EFI_FVB_ATTRIBUTES_2 is defined in + EFI_FIRMWARE_VOLUME_HEADER. + + @retval EFI_SUCCESS The firmware volume attributes were returned. + +**/ +EFI_STATUS +EFIAPI +FvbGetAttributes ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, + OUT EFI_FVB_ATTRIBUTES_2 *Attributes + ) +{ + EFI_FVB_ATTRIBUTES_2 FlashFvbAttributes; + CONST FT_FVB_DEVICE *FlashInstance; + + FlashInstance =3D INSTANCE_FROM_FVB_THIS (This); + + FlashFvbAttributes =3D (EFI_FVB_ATTRIBUTES_2) ( + EFI_FVB2_READ_ENABLED_CAP | // Reads may be enabled + EFI_FVB2_READ_STATUS | // Reads are currently enabled + EFI_FVB2_STICKY_WRITE | // A block erase is required to flip bit= s into EFI_FVB2_ERASE_POLARITY + EFI_FVB2_MEMORY_MAPPED | // It is memory mapped + EFI_FVB2_ERASE_POLARITY // After erasure all bits take this valu= e (i.e. '1') + ); + + // Check if it is write protected + if (FlashInstance->Media.ReadOnly !=3D TRUE) { + FlashFvbAttributes =3D FlashFvbAttributes | + EFI_FVB2_WRITE_STATUS | // Writes are curren= tly enabled + EFI_FVB2_WRITE_ENABLED_CAP; // Writes may be ena= bled + } + + *Attributes =3D FlashFvbAttributes; + + return EFI_SUCCESS; +} + + +/** + The FvbSetAttributes() function sets configurable firmware volume attrib= utes + and returns the new settings of the firmware volume. + + @param This EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL inst= ance. + + @param Attributes On input, Attributes is a pointer to + EFI_FVB_ATTRIBUTES_2 that contains the d= esired + firmware volume settings. + On successful return, it contains the new + settings of the firmware volume. + + @retval EFI_SUCCESS The firmware volume attributes were retu= rned. + + @retval EFI_INVALID_PARAMETER The attributes requested are in conflict= with + the capabilities as declared in the firm= ware + volume header. + +**/ +EFI_STATUS +EFIAPI +FvbSetAttributes ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, + IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes + ) +{ + return EFI_UNSUPPORTED; +} + + +/** + The FvbGetPhysicalAddress() function retrieves the base address of + a memory-mapped firmware volume. This function should be called + only for memory-mapped firmware volumes. + + @param This EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance. + + @param Address Pointer to a caller-allocated + EFI_PHYSICAL_ADDRESS that, on successful + return from GetPhysicalAddress(), contains the + base address of the firmware volume. + + @retval EFI_SUCCESS The firmware volume base address was returned. + + @retval EFI_NOT_SUPPORTED The firmware volume is not memory mapped. + +**/ +EFI_STATUS +EFIAPI +FvbGetPhysicalAddress ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, + OUT EFI_PHYSICAL_ADDRESS *Address + ) +{ + ASSERT (Address !=3D NULL); + + *Address =3D mFlashNvStorageVariableBase; + + return EFI_SUCCESS; +} + + +/** + The FvbGetBlockSize() function retrieves the size of the requested + block. It also returns the number of additional blocks with + the identical size. The FvbGetBlockSize() function is used to + retrieve the block map (see EFI_FIRMWARE_VOLUME_HEADER). + + + @param This EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL inst= ance. + + @param Lba Indicates the block whose size to return. + + @param BlockSize Pointer to a caller-allocated UINTN in w= hich + the size of the block is returned. + + @param NumberOfBlocks Pointer to a caller-allocated UINTN in + which the number of consecutive blocks, + starting with Lba, is returned. All + blocks in this range have a size of + BlockSize. + + + @retval EFI_SUCCESS The firmware volume base address was ret= urned. + + @retval EFI_INVALID_PARAMETER The requested LBA is out of range. + +**/ +EFI_STATUS +EFIAPI +FvbGetBlockSize ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, + IN EFI_LBA Lba, + OUT UINTN *BlockSize, + OUT UINTN *NumberOfBlocks + ) +{ + EFI_STATUS Status; + FT_FVB_DEVICE *FlashInstance; + + FlashInstance =3D INSTANCE_FROM_FVB_THIS (This); + + if (Lba > FlashInstance->Media.LastBlock) { + Status =3D EFI_INVALID_PARAMETER; + } else { + // This is easy because in this platform each NorFlash device has equa= l sized blocks. + *BlockSize =3D (UINTN) FlashInstance->Media.BlockSize; + *NumberOfBlocks =3D (UINTN) (FlashInstance->Media.LastBlock - Lba + 1); + Status =3D EFI_SUCCESS; + } + + return Status; +} + + +/** + Reads the specified number of bytes into a buffer from the specified blo= ck. + + The FvbRead() function reads the requested number of bytes from the + requested block and stores them in the provided buffer. + + @param This EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance. + + @param Lba The starting logical block index from which = to read. + + @param Offset Offset into the block at which to begin read= ing. + + @param NumBytes Pointer to a UINTN. + At entry, *NumBytes contains the total size = of the + buffer. + At exit, *NumBytes contains the total number= of + bytes read. + + @param Buffer Pointer to a caller-allocated buffer that wi= ll be + used to hold the data that is read. + + @retval EFI_SUCCESS The firmware volume was read successfully, a= nd + contents are in Buffer. + + @retval EFI_BAD_BUFFER_SIZE Read attempted across an LBA boundary. + On output, NumBytes contains the total numbe= r of + bytes returned in Buffer. + + @retval EFI_ACCESS_DENIED The firmware volume is in the ReadDisabled s= tate. + + @retval EFI_DEVICE_ERROR The block device is not functioning correctl= y and + could not be read. +**/ +EFI_STATUS +EFIAPI +FvbRead ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + IN OUT UINT8 *Buffer + ) +{ + UINTN BlockSize; + FT_FVB_DEVICE *FlashInstance; + EFI_STATUS Status; + + FlashInstance =3D INSTANCE_FROM_FVB_THIS (This); + + // Cache the block size to avoid de-referencing pointers all the time + BlockSize =3D FlashInstance->Media.BlockSize; + + // The read must not span block boundaries. + // We need to check each variable individually because adding two large = values together overflows. + if ((Offset >=3D BlockSize) || + (*NumBytes > BlockSize) || + ((Offset + *NumBytes) > BlockSize)) { + return EFI_BAD_BUFFER_SIZE; + } + + // We must have some bytes to read + if (*NumBytes =3D=3D 0) { + return EFI_BAD_BUFFER_SIZE; + } + + Status =3D FvbFlashRead ( + FlashInstance, + FlashInstance->StartLba + Lba, + Offset, + *NumBytes, + Buffer + ); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + + +/** + Writes the specified number of bytes from the input buffer to the block. + + The FvbWrite() function writes the specified number of bytes from + the provided buffer to the specified block and offset. + + @param This EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance. + + @param Lba The starting logical block index to write to. + + @param Offset Offset into the block at which to begin writ= ing. + + @param NumBytes The pointer to a UINTN. + At entry, *NumBytes contains the total size = of the + buffer. + At exit, *NumBytes contains the total number= of + bytes actually written. + + @param Buffer The pointer to a caller-allocated buffer that + contains the source for the write. + + @retval EFI_SUCCESS The firmware volume was written successfully. + + @retval EFI_BAD_BUFFER_SIZE The write was attempted across an LBA bounda= ry. + On output, NumBytes contains the total numbe= r of + bytes actually written. + + @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisabled = state. + + @retval EFI_DEVICE_ERROR The block device is malfunctioning and could= not be + written. + +**/ +EFI_STATUS +EFIAPI +FvbWrite ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer + ) +{ + FT_FVB_DEVICE *FlashInstance; + + FlashInstance =3D INSTANCE_FROM_FVB_THIS (This); + + return FvbFlashWrite (FlashInstance, + FlashInstance->StartLba + Lba, + Offset, + *NumBytes, + Buffer + ); +} + + +/** + Erases and initialises a firmware volume block. + + The FvbEraseBlocks() function erases one or more blocks as denoted + by the variable argument list. + + @param This EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL + instance. + + @param ... The variable argument list is a list of = tuples. + Each tuple describes a range of LBAs to = erase + and consists of the following: + An EFI_LBA that indicates the starting L= BA + A UINTN that indicates the number of blo= cks + to erase. + + The list is terminated with an + EFI_LBA_LIST_TERMINATOR. + + @retval EFI_SUCCESS The erase request successfully completed. + + @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisab= led + state. + + @retval EFI_DEVICE_ERROR The block device is not functioning corr= ectly + and could not be written. + The firmware device may have been partia= lly + erased. + + @retval EFI_INVALID_PARAMETER One or more of the LBAs listed in the va= riable + argument list do not exist in the firmwa= re + volume. + +**/ +EFI_STATUS +EFIAPI +FvbEraseBlocks ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, + ... + ) +{ + EFI_STATUS Status; + VA_LIST Args; + UINTN BlockAddress; // Physical address of Lba to erase + EFI_LBA StartingLba; // Lba from which we start erasing + UINTN NumOfLba; // Number of Lba blocks to erase + FT_FVB_DEVICE *Instance; + + Instance =3D INSTANCE_FROM_FVB_THIS (This); + + Status =3D EFI_SUCCESS; + + // Detect WriteDisabled state + if (Instance->Media.ReadOnly =3D=3D TRUE) { + // Firmware volume is in WriteDisabled state + DEBUG (( + DEBUG_ERROR, + "FvbEraseBlocks: ERROR - Device is in WriteDisabled state.\n" + )); + return EFI_ACCESS_DENIED; + } + + // Before erasing, check the entire list of parameters to ensure all spe= cified blocks are valid + + VA_START (Args, This); + do { + // Get the Lba from which we start erasing + StartingLba =3D VA_ARG (Args, EFI_LBA); + + // Have we reached the end of the list? + if (StartingLba =3D=3D EFI_LBA_LIST_TERMINATOR) { + //Exit the while loop + break; + } + + // How many Lba blocks are we requested to erase? + NumOfLba =3D VA_ARG (Args, UINT32); + + // All blocks must be within range + if ((NumOfLba =3D=3D 0) || ((Instance->StartLba + StartingLba + NumOfL= ba - 1) > Instance->Media.LastBlock)) { + VA_END (Args); + DEBUG (( + DEBUG_ERROR, + "FvbEraseBlocks: ERROR - Lba range goes past the last Lba.\n" + )); + Status =3D EFI_INVALID_PARAMETER; + goto EXIT; + } + } while (TRUE); + + VA_END (Args); + + // + // To get here, all must be ok, so start erasing + // + VA_START (Args, This); + do { + // Get the Lba from which we start erasing + StartingLba =3D VA_ARG (Args, EFI_LBA); + + // Have we reached the end of the list? + if (StartingLba =3D=3D EFI_LBA_LIST_TERMINATOR) { + // Exit the while loop + break; + } + + // How many Lba blocks are we requested to erase? + NumOfLba =3D VA_ARG (Args, UINT32); + + // Go through each one and erase it + while (NumOfLba > 0) { + // Get the physical address of Lba to erase + BlockAddress =3D GET_DATA_OFFSET ( + Instance->RegionBaseAddress, + Instance->StartLba + StartingLba, + Instance->Media.BlockSize + ); + + // Erase it + Status =3D FvbFlashEraseSingleBlock (Instance, BlockAddress); + if (EFI_ERROR (Status)) { + VA_END (Args); + Status =3D EFI_DEVICE_ERROR; + goto EXIT; + } + + // Move to the next Lba + StartingLba++; + NumOfLba--; + } + } while (TRUE); + + VA_END (Args); + +EXIT: + return Status; +} + + +/** + This function inited the NorFlash instance. + + @param[in][out] FlashInstance The pointer of FT_FVB_DEVICE instance. + + @retval EFI_SUCCESS PhytNorFlashFvbInitialize() is executed = successfully. + +**/ +STATIC +EFI_STATUS +PhytNorFlashFvbInitialize ( + IN OUT FT_FVB_DEVICE *FlashInstance + ) +{ + EFI_STATUS Status; + UINT32 FvbNumLba; + EFI_BOOT_MODE BootMode; + UINTN TotalFvbSize; + + mFlashNvStorageVariableBase =3D FixedPcdGet64 (PcdFlashNvStorageVariab= leBase64); + mFlashNvStorageFtwWorkingBase =3D FixedPcdGet64 (PcdFlashNvStorageFtwWor= kingBase64); + mFlashNvStorageFtwSpareBase =3D FixedPcdGet64 (PcdFlashNvStorageFtwSpa= reBase64); + mFlashNvStorageVariableSize =3D FixedPcdGet64 (PcdFlashNvStorageVariab= leSize); + mFlashNvStorageFtwWorkingSize =3D FixedPcdGet64 (PcdFlashNvStorageFtwWor= kingSize); + mFlashNvStorageFtwSpareSize =3D FixedPcdGet64 (PcdFlashNvStorageFtwSpa= reSize); + + // Declare the Non-Volatile storage as EFI_MEMORY_RUNTIME + Status =3D gDS->AddMemorySpace ( + EfiGcdMemoryTypeMemoryMappedIo, + mFlashNvStorageVariableBase, + FlashInstance->FvbSize, + EFI_MEMORY_UC | EFI_MEMORY_RUNTIME + ); + ASSERT_EFI_ERROR (Status); + + Status =3D gDS->SetMemorySpaceAttributes ( + mFlashNvStorageVariableBase, + FlashInstance->FvbSize, + EFI_MEMORY_UC | EFI_MEMORY_RUNTIME + ); + ASSERT_EFI_ERROR (Status); + + TotalFvbSize =3D FlashInstance->FvbSize; + + // Set the index of the first LBA for the FVB + FlashInstance->StartLba =3D (mFlashNvStorageVariableBase - FlashInstance= ->RegionBaseAddress) / FlashInstance->Media.BlockSize; + + BootMode =3D GetBootModeHob (); + if (BootMode =3D=3D BOOT_WITH_DEFAULT_SETTINGS) { + Status =3D EFI_INVALID_PARAMETER; + } else { + // Determine if there is a valid header at the beginning of the NorFla= sh + Status =3D FvbValidateFvHeader (FlashInstance); + } + + // Install the Default FVB header if required + if (EFI_ERROR (Status)) { + // There is no valid header, so time to install one. + DEBUG (( + DEBUG_ERROR, + "NorFlashFvbInitialize: ERROR - The FVB Header is invalid. Installin= g a correct one for this volume.\n" + )); + + // Erase all the NorFlash that is reserved for variable storage + FvbNumLba =3D TotalFvbSize / FlashInstance->Media.BlockSize; + + Status =3D FvbEraseBlocks ( + &FlashInstance->FvbProtocol, + (EFI_LBA)0, + FvbNumLba, + EFI_LBA_LIST_TERMINATOR + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // Install all appropriate headers + Status =3D FvbInitFvAndVariableStoreHeaders (FlashInstance); + if (EFI_ERROR (Status)) { + return Status; + } + } + + return Status; +} + + +/** + The CreateInstance() function Create Fvb Instance. + + @retval EFI_SUCCESS Create Instance successfully. + + @retval other Create Instance failed. + +**/ +STATIC +EFI_STATUS +CreateInstance ( + VOID + ) +{ + EFI_STATUS Status; + NOR_FLASH_DEVICE_DESCRIPTION *NorFlashDevice; + + // Locate flash protocols + Status =3D gBS->LocateProtocol (&gSpiNorFlashProtocolGuid, + NULL, + (VOID **)&FvbDevice->SpiFlashProtocol); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "Cannot locate NorFlash protocol.\n" + )); + return Status; + } + + NorFlashDevice =3D AllocateRuntimePool (sizeof (NOR_FLASH_DEVICE_DESCRIP= TION)); + if (NorFlashDevice =3D=3D NULL) { + DEBUG (( + DEBUG_ERROR, + "Cannot Allocate NorFlashDevice Pool.\n" + )); + return Status; + } + + Status =3D FvbDevice->SpiFlashProtocol->GetDevices (NorFlashDevice); + if (EFI_ERROR (Status)) { + return Status; + } + + Status =3D FvbDevice->SpiFlashProtocol->Initialization (); + if (EFI_ERROR (Status)) { + return Status; + } + + FvbDevice->DeviceBaseAddress =3D NorFlashDevice->DeviceBaseAddress; + FvbDevice->RegionBaseAddress =3D NorFlashDevice->RegionBaseAddress; + FvbDevice->Size =3D NorFlashDevice->Size; + + FvbDevice->Media.MediaId =3D 0; + FvbDevice->Media.BlockSize =3D NorFlashDevice->BlockSize; + FvbDevice->Media.LastBlock =3D (FvbDevice->Size / FvbDevice->Media.Block= Size) - 1; + FvbDevice->FvbSize =3D mFlashNvStorageVariableBase + + mFlashNvStorageFtwWorkingBase + + mFlashNvStorageFtwSpareBase; + + CopyGuid (&FvbDevice->DevicePath.Vendor.Guid, &NorFlashDevice->Guid); + + FvbDevice->ShadowBuffer =3D AllocateRuntimePool (FvbDevice->Media.BlockS= ize); + if (FvbDevice->ShadowBuffer =3D=3D NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Status =3D gBS->InstallMultipleProtocolInterfaces ( + &FvbDevice->Handle, + &gEfiDevicePathProtocolGuid, + &FvbDevice->DevicePath, + &gEfiFirmwareVolumeBlockProtocolGuid, + &FvbDevice->FvbProtocol, + NULL + ); + if (EFI_ERROR (Status)) { + FreePool (FvbDevice); + return Status; + } + + Status =3D PhytNorFlashFvbInitialize (FvbDevice); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "PhytNorFlashFvbInitialize: Fail to init NorFlash devices\n" + )); + return Status; + } + + FreePool (NorFlashDevice); + + return Status; +} + + +/** + Fixup internal data so that EFI can be call in virtual mode. + Call the passed in Child Notify event and convert any pointers + in lib to virtual mode. + + @param[in] Event The Event that is being processed. + + @param[in] Context Event Context. + + @retval None. + +**/ +STATIC +VOID +EFIAPI +FvbVirtualNotifyEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + // Convert SpiFlashProtocol + EfiConvertPointer (0x0, (VOID **)&FvbDevice->SpiFlashProtocol->Erase); + EfiConvertPointer (0x0, (VOID **)&FvbDevice->SpiFlashProtocol->Write); + EfiConvertPointer (0x0, (VOID **)&FvbDevice->SpiFlashProtocol->Read); + EfiConvertPointer (0x0, (VOID **)&FvbDevice->SpiFlashProtocol->GetDevice= s); + EfiConvertPointer (0x0, (VOID **)&FvbDevice->SpiFlashProtocol->Initializ= ation); + EfiConvertPointer (0x0, (VOID **)&FvbDevice->SpiFlashProtocol->EraseSing= leBlock); + EfiConvertPointer (0x0, (VOID **)&FvbDevice->SpiFlashProtocol); + + EfiConvertPointer (0x0, (VOID **)&mFlashNvStorageVariableBase); + EfiConvertPointer (0x0, (VOID **)&mFlashNvStorageFtwWorkingBase); + EfiConvertPointer (0x0, (VOID **)&mFlashNvStorageFtwSpareBase); + EfiConvertPointer (0x0, (VOID **)&FvbDevice); + + return; +} + + +/** + This function is the entrypoint of the fvb driver. + + @param[in] ImageHandle The firmware allocated handle for the EFI imag= e. + + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The entry point is executed successfully. + + @retval other Some error occurs when executing this entry po= int. + +**/ +EFI_STATUS +EFIAPI +FvbEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + FvbDevice =3D AllocateRuntimeCopyPool ( + sizeof (FvbFlashInstanceTemplate), + &FvbFlashInstanceTemplate + ); + if (FvbDevice =3D=3D NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Status =3D CreateInstance (); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "CreateInstance: Fail to create instance for NorFlash\n" + )); + } + +// +// Register for the virtual address change event +// + Status =3D gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + FvbVirtualNotifyEvent, + NULL, + &gEfiEventVirtualAddressChangeGuid, + &FvbVirtualAddrChangeEvent + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} --=20 2.25.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#72820): https://edk2.groups.io/g/devel/message/72820 Mute This Topic: https://groups.io/mt/81361274/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-