From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from zg8tmja2lje4os4yms4ymjma.icoremail.net (zg8tmja2lje4os4yms4ymjma.icoremail.net [206.189.21.223]) by mx.groups.io with SMTP id smtpd.web08.1457.1610700567958367929 for ; Fri, 15 Jan 2021 00:49:28 -0800 Authentication-Results: mx.groups.io; dkim=missing; spf=pass (domain: phytium.com.cn, ip: 206.189.21.223, mailfrom: jialing@phytium.com.cn) Received: from localhost.localdomain (unknown [117.136.88.47]) by c1app12 (Coremail) with SMTP id DAINCgDHzpbFVgFgExlyBA--.39669S11; Fri, 15 Jan 2021 16:49:19 +0800 (CST) From: Ling Jia To: devel@edk2.groups.io Cc: Leif Lindholm , Ling , Peng Xie , Yiqi Shu Subject: [PATCH v1 09/10] Silicon/Phytium: Added fvb driver for norflash Date: Fri, 15 Jan 2021 08:48:01 +0000 Message-Id: <20210115084802.62196-10-jialing@phytium.com.cn> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210115084802.62196-1-jialing@phytium.com.cn> References: <20210115084802.62196-1-jialing@phytium.com.cn> MIME-Version: 1.0 X-CM-TRANSID: DAINCgDHzpbFVgFgExlyBA--.39669S11 X-Coremail-Antispam: 1UD129KBjvAXoWDJw4UXryDCw4Duw1UuFW8tFb_yoWrKF48Jo WxZr4fW348trWIgrs8Gryqk3y7XFn5Xrsxtrs5Zry2q3Z5Xw1YvFWIy3W8Xw4ftr1jkrnx G34fJas3JFW3tFykn29KB7ZKAUJUUUUU529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 AaLaJ3UjIYCTnIWjp_UUUY_7AC8VAFwI0_Wr0E3s1l1xkIjI8I6I8E6xAIw20EY4v20xva j40_Wr0E3s1l1IIY67AEw4v_Jr0_Jr4l82xGYIkIc2x26280x7IE14v26r126s0DM28Irc Ia0xkI8VCY1x0267AKxVW5JVCq3wA2ocxC64kIII0Yj41l84x0c7CEw4AK67xGY2AK021l 84ACjcxK6xIIjxv20xvE14v26ryj6F1UM28EF7xvwVC0I7IYx2IY6xkF7I0E14v26F4j6r 4UJwA2z4x0Y4vEx4A2jsIE14v26r4UJVWxJr1l84ACjcxK6I8E87Iv6xkF7I0E14v26F4U JVW0owAS0I0E0xvYzxvE52x082IY62kv0487Mc02F40EFcxC0VAKzVAqx4xG6I80ewAv7V C0I7IYx2IY67AKxVWUJVWUGwAv7VC2z280aVAFwI0_Jr0_Gr1lOx8S6xCaFVCjc4AY6r1j 6r4UM4x0Y48IcxkI7VAKI48JM4x0x7Aq67IIx4CEVc8vx2IErcIFxwCY02Avz4vE14v_GF yl42xK82IYc2Ij64vIr41l4I8I3I0E4IkC6x0Yz7v_Jr0_Gr1lx2IqxVAqx4xG67AKxVWU JVWUGwC20s026x8GjcxK67AKxVWUGVWUWwC2zVAF1VAY17CE14v26r126r1DMIIYrxkI7V AKI48JMIIF0xvE2Ix0cI8IcVAFwI0_JFI_Gr1lIxAIcVC0I7IYx2IY6xkF7I0E14v26r4j 6F4UMIIF0xvE42xK8VAvwI8IcIk0rVWUJVWUCwCI42IY6I8E87Iv67AKxVWUJVW8JwCI42 IY6I8E87Iv6xkF7I0E14v26r4j6r4UJbIYCTnIWIevJa73UjIFyTuYvjfUeeHqDUUUU X-Originating-IP: [117.136.88.47] X-CM-SenderInfo: xmldzxdqj61x51wl3zoofrzhdfq/ Content-Transfer-Encoding: quoted-printable From: Ling The PhytiumFlashFvbDxe provided the fvb protocol, which requested by the flah operators. Cc: Leif Lindholm Signed-off-by: Ling Jia Signed-off-by: Peng Xie Reviewed-by: Yiqi Shu --- Platform/Phytium/Durian/DurianPkg.dsc | = 1 + Platform/Phytium/Durian/DurianPkg.fdf | = 1 + Silicon/Phytium/CommonDrivers/PhytiumFlashFvbDxe/PhytiumFlashFvbDxe.inf | = 72 ++ Silicon/Phytium/CommonDrivers/PhytiumFlashFvbDxe/PhytiumFlashFvbDxe.h | = 106 ++ Silicon/Phytium/CommonDrivers/PhytiumFlashFvbDxe/PhytiumFlashFvbDxe.c | = 1235 ++++++++++++++++++++ 5 files changed, 1415 insertions(+) diff --git a/Platform/Phytium/Durian/DurianPkg.dsc b/Platform/Phytium/Duria= n/DurianPkg.dsc index d34432e95049..df43c3d5d23a 100644 --- a/Platform/Phytium/Durian/DurianPkg.dsc +++ b/Platform/Phytium/Durian/DurianPkg.dsc @@ -265,6 +265,7 @@ [Components.common] # NOR Flash driver=0D #=0D Silicon/Phytium/CommonDrivers/PhytiumSpiNorFlashDxe/PhytiumSpiNorFlashDx= e.inf=0D + Silicon/Phytium/CommonDrivers/PhytiumFlashFvbDxe/PhytiumFlashFvbDxe.inf= =0D =0D #=0D # Usb Support=0D diff --git a/Platform/Phytium/Durian/DurianPkg.fdf b/Platform/Phytium/Duria= n/DurianPkg.fdf index 703537033944..1a1dde1c64f6 100644 --- a/Platform/Phytium/Durian/DurianPkg.fdf +++ b/Platform/Phytium/Durian/DurianPkg.fdf @@ -102,6 +102,7 @@ [FV.FvMain] =0D INF ArmPkg/Drivers/ArmGic/ArmGicDxe.inf=0D INF ArmPkg/Drivers/CpuDxe/CpuDxe.inf=0D + INF Silicon/Phytium/CommonDrivers/PhytiumFlashFvbDxe/PhytiumFlashFvbDxe.= inf=0D INF ArmPkg/Drivers/TimerDxe/TimerDxe.inf=0D INF ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdogDxe.inf=0D =0D diff --git a/Silicon/Phytium/CommonDrivers/PhytiumFlashFvbDxe/PhytiumFlashF= vbDxe.inf b/Silicon/Phytium/CommonDrivers/PhytiumFlashFvbDxe/PhytiumFlashFv= bDxe.inf new file mode 100644 index 000000000000..3d177dd92c7e --- /dev/null +++ b/Silicon/Phytium/CommonDrivers/PhytiumFlashFvbDxe/PhytiumFlashFvbDxe.i= nf @@ -0,0 +1,72 @@ +#/** @file=0D +# Phytium NorFlash Fvb Drivers.=0D +#=0D +# Copyright (C) 2020, Phytium Technology Co,Ltd. All rights reserved.
= =0D +#=0D +# SPDX-License-Identifier: BSD-2-Clause-Patent=0D +#=0D +#**/=0D +=0D +[Defines]=0D + INF_VERSION =3D 0x00010019=0D + BASE_NAME =3D PhytiumFlashFvbDxe=0D + FILE_GUID =3D b8923820-3e7c-11eb-b12c-17525e90ecc8= =0D + MODULE_TYPE =3D DXE_RUNTIME_DRIVER=0D + VERSION_STRING =3D 0.1=0D + ENTRY_POINT =3D PhytiumFvbEntryPoint=0D +=0D +[Sources]=0D + PhytiumFlashFvbDxe.c=0D + PhytiumFlashFvbDxe.h=0D +=0D +[Packages]=0D + EmbeddedPkg/EmbeddedPkg.dec=0D + MdePkg/MdePkg.dec=0D + MdeModulePkg/MdeModulePkg.dec=0D + ArmPlatformPkg/ArmPlatformPkg.dec=0D + Silicon/Phytium/Phytium.dec=0D +=0D +[LibraryClasses]=0D + BaseMemoryLib=0D + DevicePathLib=0D + MemoryAllocationLib=0D + UefiRuntimeServicesTableLib=0D + IoLib=0D + BaseLib=0D + DebugLib=0D + HobLib=0D + UefiLib=0D + UefiDriverEntryPoint=0D + UefiBootServicesTableLib=0D + UefiRuntimeLib=0D + DxeServicesTableLib=0D + PcdLib=0D +=0D +[Guids]=0D + gEfiSystemNvDataFvGuid=0D + gEfiVariableGuid=0D + gEfiEventVirtualAddressChangeGuid=0D + gEfiAuthenticatedVariableGuid=0D +=0D +[Protocols]=0D + gEfiDevicePathProtocolGuid=0D + gEfiFirmwareVolumeBlockProtocolGuid=0D + gPhytiumFlashProtocolGuid=0D +=0D +[Pcd.common]=0D + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64=0D + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize=0D + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase64=0D + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize=0D + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase64=0D + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize=0D + gArmPlatformTokenSpaceGuid.PcdNorFlashCheckBlockLocked=0D + gPhytiumPlatformTokenSpaceGuid.PcdSpiFlashBase=0D + gPhytiumPlatformTokenSpaceGuid.PcdSpiFlashSize=0D +=0D +[Depex]=0D + #TRUE=0D + gPhytiumFlashProtocolGuid=0D + #gEfiCpuArchProtocolGuid AND=0D + #gPhytiumSpiMasterProtocolGuid AND=0D + #gPhytiumFlashProtocolGuid=0D diff --git a/Silicon/Phytium/CommonDrivers/PhytiumFlashFvbDxe/PhytiumFlashF= vbDxe.h b/Silicon/Phytium/CommonDrivers/PhytiumFlashFvbDxe/PhytiumFlashFvbD= xe.h new file mode 100644 index 000000000000..6d7fe18e0137 --- /dev/null +++ b/Silicon/Phytium/CommonDrivers/PhytiumFlashFvbDxe/PhytiumFlashFvbDxe.h @@ -0,0 +1,106 @@ +/** @file=0D + Phytium NorFlash Fvb Drivers Header.=0D +=0D + Copyright (C) 2020, Phytium Technology Co Ltd. All rights reserved.
= =0D +=0D + SPDX-License-Identifier: BSD-2-Clause-Patent=0D +=0D +**/=0D +#ifndef __FVB_FLASH_DXE_H__=0D +#define __FVB_FLASH_DXE_H__=0D +=0D +#include =0D +#include =0D +#include =0D +=0D +#define GET_DATA_OFFSET(BaseAddr, Lba, LbaSize) ((BaseAddr) + (UINTN)((Lba= ) * (LbaSize)))=0D +#define FVB_FLASH_SIGNATURE SIGNATURE_32('S', 'n', '= o', 'r')=0D +#define INSTANCE_FROM_FVB_THIS(a) CR(a, FT_FVB_DEVICE, Fvb= Protocol, FVB_FLASH_SIGNATURE)=0D +=0D +typedef struct _FT_FVB_DEVICE FT_FVB_DEVICE;=0D +=0D +#define NOR_FLASH_ERASE_RETRY 10=0D +=0D +typedef struct {=0D + VENDOR_DEVICE_PATH Vendor;=0D + EFI_DEVICE_PATH_PROTOCOL End;=0D + } FT_FVB_DEVICE_PATH;=0D +=0D +struct _FT_FVB_DEVICE {=0D + UINT32 Signature;=0D + EFI_HANDLE Handle;=0D +=0D + UINTN DeviceBaseAddress;=0D + UINTN RegionBaseAddress;=0D + UINTN Size;=0D + EFI_LBA StartLba;=0D + EFI_BLOCK_IO_MEDIA Media;=0D +=0D + EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL FvbProtocol;=0D +=0D + FT_FVB_DEVICE_PATH DevicePath;=0D + EFI_NORFLASH_DRV_PROTOCOL *SpiFlashProtocol;=0D + VOID *ShadowBuffer;=0D + UINTN FvbSize;=0D + };=0D +=0D +extern CONST EFI_GUID* CONST NorFlashVariableGuid;=0D +=0D +EFI_STATUS=0D +EFIAPI=0D +PhytiumFvbGetAttributes(=0D + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL* This,=0D + OUT EFI_FVB_ATTRIBUTES_2* Attributes=0D + );=0D +=0D +EFI_STATUS=0D +EFIAPI=0D +PhytiumFvbSetAttributes(=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 +PhytiumFvbGetPhysicalAddress(=0D + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL* This,=0D + OUT EFI_PHYSICAL_ADDRESS* Address=0D + );=0D +=0D +EFI_STATUS=0D +EFIAPI=0D +PhytiumFvbGetBlockSize(=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 +PhytiumFvbRead(=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 +PhytiumFvbWrite(=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 +PhytiumFvbEraseBlocks(=0D + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL* This,=0D + ...=0D + );=0D +=0D +#endif /* __FVB_FLASH_DXE_H__ */=0D diff --git a/Silicon/Phytium/CommonDrivers/PhytiumFlashFvbDxe/PhytiumFlashF= vbDxe.c b/Silicon/Phytium/CommonDrivers/PhytiumFlashFvbDxe/PhytiumFlashFvbD= xe.c new file mode 100644 index 000000000000..a2ac7abe09ad --- /dev/null +++ b/Silicon/Phytium/CommonDrivers/PhytiumFlashFvbDxe/PhytiumFlashFvbDxe.c @@ -0,0 +1,1235 @@ +/** @file=0D + Phytium NorFlash Fvb Drivers.=0D +=0D + Copyright (c) 2011 - 2014, ARM Ltd. All rights reserved.
=0D + Copyright (C) 2020, Phytium Technology Co Ltd. All rights reserved.
= =0D +=0D + SPDX-License-Identifier: BSD-2-Clause-Patent=0D +=0D +**/=0D +=0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +=0D +#include =0D +#include =0D +#include =0D +=0D +#include "PhytiumFlashFvbDxe.h"=0D +=0D +STATIC EFI_EVENT FvbVirtualAddrChangeEvent;=0D +STATIC FT_FVB_DEVICE *PhytiumFvbDevice;=0D +STATIC UINTN mFlashNvStorageVariableBase;=0D +CONST EFI_GUID* CONST NorFlashVariableGuid =3D &gEfiAuthenticatedVariableG= uid;=0D +=0D +STATIC CONST FT_FVB_DEVICE PhytiumFvbFlashInstanceTemplate =3D {=0D + FVB_FLASH_SIGNATURE, // Signature=0D + NULL, // Handle ... NEED TO BE FILLED=0D + 0, // DeviceBaseAddress ... NEED TO BE FILLED=0D + 0, // RegionBaseAddress ... NEED TO BE FILLED=0D + 0, // Size ... NEED TO BE FILLED=0D + 0, // StartLba=0D + {=0D + 0, // MediaId ... NEED TO BE FILLED=0D + FALSE, // RemovableMedia=0D + TRUE, // MediaPresent=0D + FALSE, // LogicalPartition=0D + FALSE, // ReadOnly=0D + FALSE, // WriteCaching;=0D + 0, // BlockSize ... NEED TO BE FILLED=0D + 4, // IoAlign=0D + 0, // LastBlock ... NEED TO BE FILLED=0D + 0, // LowestAlignedLba=0D + 1, // LogicalBlocksPerPhysicalBlock=0D + }, //Media;=0D + {=0D + PhytiumFvbGetAttributes, // GetAttributes=0D + PhytiumFvbSetAttributes, // SetAttributes=0D + PhytiumFvbGetPhysicalAddress, // GetPhysicalAddress=0D + PhytiumFvbGetBlockSize, // GetBlockSize=0D + PhytiumFvbRead, // Read=0D + PhytiumFvbWrite, // Write=0D + PhytiumFvbEraseBlocks, // EraseBlocks=0D + NULL, // ParentHandle=0D + }, // FvbProtoccol;=0D +=0D + {=0D + {=0D + {=0D + HARDWARE_DEVICE_PATH,=0D + HW_VENDOR_DP,=0D + { (UINT8)sizeof(VENDOR_DEVICE_PATH), (UINT8)((sizeof(VENDOR_DEVICE= _PATH)) >> 8) }=0D + },=0D + { 0x0, 0x0, 0x0, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } }, // GU= ID ... NEED TO BE FILLED=0D + },=0D + {=0D + END_DEVICE_PATH_TYPE,=0D + END_ENTIRE_DEVICE_PATH_SUBTYPE,=0D + { sizeof (EFI_DEVICE_PATH_PROTOCOL), 0 }=0D + }=0D + }, // DevicePath=0D +=0D + NULL, // SpiFlashProtocol ... NEED TO BE FILLED=0D + NULL, // ShadowBuffer ... NEED TO BE FILLED=0D + 0, // Fvb Size=0D +};=0D +=0D +=0D +/**=0D + Erases a single block of flash.=0D +=0D + @param[in] FlashInstance The poiter of the fvb device sturct.=0D +=0D + @param[in] BlockAddress Physical address of Lba to be erased.=0D +=0D + @retval EFI_SUCCESS The erase single block request successfull= y completed.=0D +=0D +**/=0D +STATIC=0D +EFI_STATUS=0D +FvbFlashEraseSingleBlock (=0D + IN FT_FVB_DEVICE *FlashInstance,=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 +=0D + Index =3D 0;=0D + // The block erase might fail a first time (SW bug ?). Retry it ...=0D + do {=0D + Status =3D FlashInstance->SpiFlashProtocol->EraseSingleBlock(BlockAddr= ess);=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 Loc= ked 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 +=0D +/**=0D + Readed the specified number of bytes from the form the block to output b= uffer.=0D +=0D + @param[in] FlashInstance The pointer of FT_FVB_DEVICE instance.= =0D +=0D + @param[in] Lba The starting logical block index to wri= te to.=0D +=0D + @param[in] Offset Offset into the block at which to begin= writing.=0D +=0D + @param[in] BufferSizeInBytes The number of bytes to be writed.=0D +=0D + @param[out] Buffer The pointer to a caller-allocated buffe= r that=0D + contains the source for the write.=0D +=0D + @retval EFI_SUCCESS PhytiumFvbFlashRead() is executed succe= ssfully.=0D +=0D +**/=0D +STATIC=0D +EFI_STATUS=0D +PhytiumFvbFlashRead (=0D + IN FT_FVB_DEVICE *FlashInstance,=0D + IN EFI_LBA Lba,=0D + IN UINTN Offset,=0D + IN UINTN BufferSizeInBytes,=0D + OUT VOID *Buffer=0D + )=0D +{=0D + UINTN Address =3D GET_DATA_OFFSET(FlashInstance->RegionBaseAddress, Lba,= FlashInstance->Media.BlockSize) + Offset;=0D +=0D + if (BufferSizeInBytes =3D=3D 0) {=0D + return EFI_SUCCESS;=0D + }=0D +=0D + // The buffer must be valid=0D + if (Buffer =3D=3D NULL) {=0D + return EFI_INVALID_PARAMETER;=0D + }=0D + return FlashInstance->SpiFlashProtocol->Read (Address, Buffer, BufferSiz= eInBytes);=0D +}=0D +=0D +=0D +/**=0D + Write a full or portion of a block. It must not span block boundaries; t= hat is,=0D + Offset + *NumBytes <=3D FlashInstance->Media.BlockSize.=0D +=0D + @param[in] FlashInstance The pointer of FT_FVB_DEVICE instance.= =0D +=0D + @param[in] Lba The starting logical block index to wri= te to.=0D +=0D + @param[in] Offset Offset into the block at which to begin= writing.=0D +=0D + @param[in] BufferSizeInBytes The number of bytes to be writed.=0D +=0D + @param[out] Buffer The pointer to a caller-allocated buffe= r that=0D + contains the source for the write.=0D +=0D + @retval EFI_SUCCESS PhytiumFvbWriteBlock() is executed succ= essfully.=0D +=0D + @retval EFI_BAD_BUFFER_SIZE The write spaned block boundaries.=0D +=0D +**/=0D +STATIC=0D +EFI_STATUS=0D +PhytiumFvbWriteBlock (=0D + IN FT_FVB_DEVICE *FlashInstance,=0D + IN EFI_LBA Lba,=0D + IN UINTN Offset,=0D + IN UINTN BufferSizeInBytes,=0D + IN UINT8 *Buffer=0D + )=0D +{=0D + EFI_STATUS Status;=0D + UINTN BlockSize;=0D + UINTN BlockAddress;=0D +=0D + // Detect WriteDisabled state=0D + if (FlashInstance->Media.ReadOnly =3D=3D TRUE) {=0D + DEBUG ((DEBUG_ERROR, "PhytiumFvbWriteBlock: ERROR - Can not write: Dev= ice is in WriteDisabled state.\n"));=0D + // It is in WriteDisabled state, return an error right away=0D + return EFI_ACCESS_DENIED;=0D + }=0D +=0D + // Cache the block size to avoid de-referencing pointers all the time=0D + BlockSize =3D FlashInstance->Media.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 + (BufferSizeInBytes > BlockSize) ||=0D + ((Offset + BufferSizeInBytes) > BlockSize)) {=0D + DEBUG ((DEBUG_ERROR, "PhytiumFvbWriteBlock: ERROR - EFI_BAD_BUFFER_SIZ= E: (Offset=3D0x%x + NumBytes=3D0x%x) > BlockSize=3D0x%x\n", Offset, BufferS= izeInBytes, BlockSize ));=0D + return EFI_BAD_BUFFER_SIZE;=0D + }=0D +=0D + // We must have some bytes to write=0D + if (BufferSizeInBytes =3D=3D 0) {=0D + DEBUG ((DEBUG_ERROR, "PhytiumFvbWriteBlock: ERROR - EFI_BAD_BUFFER_SIZ= E: NumBytes =3D=3D 0\n"));=0D + return EFI_BAD_BUFFER_SIZE;=0D + }=0D +=0D + // Check we did get some memory. Buffer is BlockSize.=0D + if (FlashInstance->ShadowBuffer =3D=3D NULL) {=0D + DEBUG ((DEBUG_ERROR, "PhytiumFvbWriteBlock: ERROR - ShadowBuffer is NU= LL!\n"));=0D + return EFI_DEVICE_ERROR;=0D + }=0D +=0D + //=0D + // Write the word to NOR.=0D + //=0D + BlockAddress =3D GET_DATA_OFFSET(FlashInstance->RegionBaseAddress, Lba, = FlashInstance->Media.BlockSize);=0D +=0D + // Read NOR Flash data into shadow buffer=0D + Status =3D FlashInstance->SpiFlashProtocol->Read (BlockAddress, FlashIns= tance->ShadowBuffer, BlockSize);=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)FlashInstance->ShadowBuffer + Offset), Buffer, B= ufferSizeInBytes);=0D +=0D + Status =3D FlashInstance->SpiFlashProtocol->EraseSingleBlock (BlockAddre= ss);=0D + if (EFI_ERROR (Status)) {=0D + // Return one of the pre-approved error statuses=0D + return EFI_DEVICE_ERROR;=0D + }=0D +=0D + // Write the modified buffer back to the NorFlash=0D + Status =3D FlashInstance->SpiFlashProtocol->Write(BlockAddress, FlashIns= tance->ShadowBuffer, BlockSize);=0D + if (EFI_ERROR (Status)) {=0D + // Return one of the pre-approved error statuses=0D + return EFI_DEVICE_ERROR;=0D + }=0D +=0D + return EFI_SUCCESS;=0D +}=0D +=0D +=0D +/**=0D + Writes the specified number of bytes from the input buffer to the block.= =0D +=0D + @param[in] FlashInstance The pointer of FT_FVB_DEVICE instance.=0D +=0D + @param[in] Lba The starting logical block index to writ= e to.=0D +=0D + @param[in] Offset Offset into the block at which to begin = writing.=0D +=0D + @param[in] BufferSizeInBytes The number of bytes to be writed.=0D +=0D + @param[in] Buffer The pointer to a caller-allocated buffer= that=0D + contains the source for the write.=0D +=0D + @retval EFI_SUCCESS PhytiumFvbFlashWrite() is executed succe= ssfully.=0D +=0D + @retval EFI_WRITE_PROTECTED Flash state is in the WriteDisabled stat= e.=0D +=0D + @retval EFI_INVALID_PARAMETER The pointer of Buffer is NULL.=0D +=0D +**/=0D +STATIC=0D +EFI_STATUS=0D +PhytiumFvbFlashWrite (=0D + IN FT_FVB_DEVICE *FlashInstance,=0D + IN EFI_LBA Lba,=0D + IN UINTN Offset,=0D + IN UINTN BufferSizeInBytes,=0D + IN VOID *Buffer=0D + )=0D +{=0D + EFI_STATUS Status =3D EFI_SUCCESS;=0D + UINT32 BlockSize;=0D + UINT32 BlockOffset;=0D + UINTN RemainingBytes;=0D + UINTN WriteSize;=0D +=0D + if (FlashInstance->Media.ReadOnly =3D=3D TRUE) {=0D + return EFI_WRITE_PROTECTED;=0D + }=0D +=0D + if (BufferSizeInBytes =3D=3D 0) {=0D + return EFI_SUCCESS;=0D + }=0D +=0D + if (Buffer =3D=3D NULL) {=0D + return EFI_INVALID_PARAMETER;=0D + }=0D +=0D + BlockSize =3D FlashInstance->Media.BlockSize;=0D + BlockOffset =3D Offset;=0D + RemainingBytes =3D BufferSizeInBytes;=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 + DEBUG ((DEBUG_ERROR, "FvbFlashWrite: ERROR - EFI_BAD_BUFFER_SIZE: Offs= et=3D0x%x > BlockSize=3D0x%x\n", Offset, BlockSize));=0D + return EFI_BAD_BUFFER_SIZE;=0D + }=0D +=0D + // We must have some bytes to read=0D + // Write either all the remaining bytes, or the number of bytes that bri= ng=0D + // us up to a block boundary, whichever is less.=0D + // (DiskOffset | (BlockSize - 1)) + 1) rounds DiskOffset up to the next= =0D + // block boundary (even if it is already on one).=0D + WriteSize =3D MIN (RemainingBytes, BlockSize - BlockOffset);=0D +=0D + do {=0D + Status =3D PhytiumFvbWriteBlock (FlashInstance, Lba, BlockOffset, Writ= eSize, Buffer);=0D + if (EFI_ERROR (Status)) {=0D + return Status;=0D + }=0D +=0D + // Now continue writing either all the remaining bytes or single block= s.=0D + RemainingBytes -=3D WriteSize;=0D + Buffer =3D (UINT8 *) Buffer + WriteSize;=0D + Lba++;=0D + BlockOffset =3D 0;=0D + WriteSize =3D MIN (RemainingBytes, BlockSize);=0D + } while (RemainingBytes);=0D +=0D + return Status;=0D +}=0D +=0D +=0D +/**=0D + Initialises the FV Header and Variable Store Header=0D + to support variable operations.=0D +=0D + @param[in] Ptr Location to initialise the headers.=0D +=0D + @retval EFI_SUCCESS PhytiumFvbInitFvAndVariableStoreHeaders()=0D + is executed successfully.=0D +=0D +**/=0D +STATIC=0D +EFI_STATUS=0D +PhytiumFvbInitFvAndVariableStoreHeaders (=0D + IN FT_FVB_DEVICE *FlashInstance=0D + )=0D +{=0D + EFI_STATUS Status;=0D + VOID* Headers;=0D + UINTN HeadersLength;=0D + EFI_FIRMWARE_VOLUME_HEADER *FirmwareVolumeHeader;=0D + VARIABLE_STORE_HEADER *VariableStoreHeader;=0D +=0D + HeadersLength =3D sizeof(EFI_FIRMWARE_VOLUME_HEADER) + sizeof(EFI_FV_BLO= CK_MAP_ENTRY) + sizeof(VARIABLE_STORE_HEADER);=0D + Headers =3D AllocateZeroPool (HeadersLength);=0D +=0D + // FirmwareVolumeHeader->FvLength is declared to have the Variable area = AND the FTW working area AND the FTW Spare contiguous.=0D + ASSERT(PcdGet64 (PcdFlashNvStorageVariableBase64) + PcdGet32 (PcdFlashNv= StorageVariableSize) =3D=3D PcdGet64(PcdFlashNvStorageFtwWorkingBase64));=0D + ASSERT(PcdGet64 (PcdFlashNvStorageFtwWorkingBase64) + PcdGet32 (PcdFlash= NvStorageFtwWorkingSize) =3D=3D PcdGet64(PcdFlashNvStorageFtwSpareBase64));= =0D +=0D + // Check if the size of the area is at least one block size=0D + ASSERT((PcdGet32 (PcdFlashNvStorageVariableSize) > 0) && (PcdGet32 (PcdF= lashNvStorageVariableSize) / FlashInstance->Media.BlockSize > 0));=0D + ASSERT((PcdGet32 (PcdFlashNvStorageFtwWorkingSize) > 0) && (PcdGet32 (Pc= dFlashNvStorageFtwWorkingSize) / FlashInstance->Media.BlockSize > 0));=0D + ASSERT((PcdGet32 (PcdFlashNvStorageFtwSpareSize) > 0) && (PcdGet32 (PcdF= lashNvStorageFtwSpareSize) / FlashInstance->Media.BlockSize > 0));=0D +=0D + // Ensure the Variable area Base Addresses are aligned on a block size b= oundaries=0D + ASSERT(PcdGet64 (PcdFlashNvStorageVariableBase64) % FlashInstance->Media= .BlockSize =3D=3D 0);=0D + ASSERT(PcdGet64 (PcdFlashNvStorageFtwWorkingBase64) % FlashInstance->Med= ia.BlockSize =3D=3D 0);=0D + ASSERT(PcdGet64 (PcdFlashNvStorageFtwSpareBase64) % FlashInstance->Media= .BlockSize =3D=3D 0);=0D +=0D + //=0D + // EFI_FIRMWARE_VOLUME_HEADER=0D + //=0D + FirmwareVolumeHeader =3D (EFI_FIRMWARE_VOLUME_HEADER*)Headers;=0D + CopyGuid (&FirmwareVolumeHeader->FileSystemGuid, &gEfiSystemNvDataFvGuid= );=0D + FirmwareVolumeHeader->FvLength =3D FlashInstance->FvbSize;=0D +=0D + FirmwareVolumeHeader->Signature =3D EFI_FVH_SIGNATURE;=0D + FirmwareVolumeHeader->Attributes =3D (EFI_FVB_ATTRIBUTES_2) (=0D + EFI_FVB2_READ_ENABLED_CAP | //= Reads may be enabled=0D + EFI_FVB2_READ_STATUS | //= Reads are currently enabled=0D + EFI_FVB2_STICKY_WRITE | //= A block erase is required to flip bits into EFI_FVB2_ERASE_POLARITY=0D + EFI_FVB2_MEMORY_MAPPED | //= It is memory mapped=0D + EFI_FVB2_ERASE_POLARITY | //= After erasure all bits take this value (i.e. '1')=0D + EFI_FVB2_WRITE_STATUS | //= Writes are currently enabled=0D + EFI_FVB2_WRITE_ENABLED_CAP //= Writes may be enabled=0D + );=0D +=0D + FirmwareVolumeHeader->HeaderLength =3D sizeof(EFI_FIRMWARE_VOLUME_HEADER= ) + sizeof(EFI_FV_BLOCK_MAP_ENTRY);=0D + FirmwareVolumeHeader->Revision =3D EFI_FVH_REVISION;=0D + FirmwareVolumeHeader->BlockMap[0].NumBlocks =3D FlashInstance->Media.Las= tBlock + 1;=0D + FirmwareVolumeHeader->BlockMap[0].Length =3D FlashInstance->Media.Blo= ckSize;=0D + FirmwareVolumeHeader->BlockMap[1].NumBlocks =3D 0;=0D + FirmwareVolumeHeader->BlockMap[1].Length =3D 0;=0D + FirmwareVolumeHeader->Checksum =3D CalculateCheckSum16 ((UINT16*)Firmwar= eVolumeHeader, FirmwareVolumeHeader->HeaderLength);=0D +=0D + //=0D + // VARIABLE_STORE_HEADER=0D + //=0D + VariableStoreHeader =3D (VARIABLE_STORE_HEADER*)((UINTN)Headers + Firmwa= reVolumeHeader->HeaderLength);=0D + CopyGuid (&VariableStoreHeader->Signature, NorFlashVariableGuid);=0D + VariableStoreHeader->Size =3D PcdGet32 (PcdFlashNvStorageVariableSize)= - FirmwareVolumeHeader->HeaderLength;=0D + VariableStoreHeader->Format =3D VARIABLE_STORE_FORMATTED;=0D + VariableStoreHeader->State =3D VARIABLE_STORE_HEALTHY;=0D +=0D + // Install the combined super-header in the NorFlash=0D + Status =3D PhytiumFvbWrite (&FlashInstance->FvbProtocol, 0, 0, &HeadersL= ength, Headers);=0D +=0D + FreePool (Headers);=0D +=0D + return Status;=0D +}=0D +=0D +=0D +/**=0D + Check the integrity of firmware volume header.=0D +=0D + @param[in] FwVolHeader A pointer to a firmware volume header=0D +=0D + @retval EFI_SUCCESS The firmware volume is consistent=0D +=0D + @retval EFI_NOT_FOUND The firmware volume has been corrupted.=0D +=0D +**/=0D +STATIC=0D +EFI_STATUS=0D +PhytiumFvbValidateFvHeader (=0D + IN FT_FVB_DEVICE *FlashInstance=0D + )=0D +{=0D + UINT16 Checksum;=0D + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;=0D + VARIABLE_STORE_HEADER *VariableStoreHeader;=0D + UINTN VariableStoreLength;=0D + UINTN FvLength;=0D +=0D + FwVolHeader =3D (EFI_FIRMWARE_VOLUME_HEADER*)GET_DATA_OFFSET(FlashInstan= ce->RegionBaseAddress, FlashInstance->StartLba, FlashInstance->Media.BlockS= ize);=0D + FvLength =3D FlashInstance->FvbSize;=0D +=0D + //=0D + // Verify the header revision, header signature, length=0D + // Length of FvBlock cannot be 2**64-1=0D + // HeaderLength cannot be an odd number=0D + //=0D + if ((FwVolHeader->Revision !=3D EFI_FVH_REVISION) ||=0D + (FwVolHeader->Signature !=3D EFI_FVH_SIGNATURE) ||=0D + (FwVolHeader->FvLength !=3D FvLength))=0D + {=0D + DEBUG ((DEBUG_ERROR, "ValidateFvHeader: No Firmware Volume header pres= ent\n"));=0D + return EFI_NOT_FOUND;=0D + }=0D +=0D + // Check the Firmware Volume Guid=0D + if( CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiSystemNvDataFvGuid) = =3D=3D FALSE ) {=0D + DEBUG ((DEBUG_ERROR, "ValidateFvHeader: Firmware Volume Guid non-compa= tible\n"));=0D + return EFI_NOT_FOUND;=0D + }=0D +=0D + // Verify the header checksum=0D + Checksum =3D CalculateSum16 ((UINT16*)FwVolHeader, FwVolHeader->HeaderLe= ngth);=0D + if (Checksum !=3D 0) {=0D + DEBUG ((DEBUG_ERROR, "ValidateFvHeader: FV checksum is invalid (Checks= um:0x%X)\n",Checksum));=0D + return EFI_NOT_FOUND;=0D + }=0D +=0D + VariableStoreHeader =3D (VARIABLE_STORE_HEADER*)((UINTN)FwVolHeader + Fw= VolHeader->HeaderLength);=0D +=0D + // Check the Variable Store Guid=0D + if (!CompareGuid (&VariableStoreHeader->Signature, &gEfiVariableGuid) &&= =0D + !CompareGuid (&VariableStoreHeader->Signature,=0D + &gEfiAuthenticatedVariableGuid)) {=0D + DEBUG ((DEBUG_ERROR, "%a: Variable Store Guid non-compatible\n"));=0D + return EFI_NOT_FOUND;=0D + }=0D +=0D + VariableStoreLength =3D PcdGet32 (PcdFlashNvStorageVariableSize) - FwVol= Header->HeaderLength;=0D + if (VariableStoreHeader->Size !=3D VariableStoreLength) {=0D + DEBUG ((DEBUG_ERROR, "ValidateFvHeader: Variable Store Length does not= match\n"));=0D + return EFI_NOT_FOUND;=0D + }=0D +=0D + return EFI_SUCCESS;=0D +}=0D +=0D +=0D +/**=0D + The PhytiumFvbGetAttributes() function retrieves the attributes and=0D + current settings of the block.=0D +=0D + @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL in= stance.=0D +=0D + @param Attributes Pointer to EFI_FVB_ATTRIBUTES_2 in which the attribu= tes and=0D + current settings are returned.=0D + Type EFI_FVB_ATTRIBUTES_2 is defined in=0D + EFI_FIRMWARE_VOLUME_HEADER.=0D +=0D + @retval EFI_SUCCESS The firmware volume attributes were returned.=0D +=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +PhytiumFvbGetAttributes (=0D + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,=0D + OUT EFI_FVB_ATTRIBUTES_2 *Attributes=0D + )=0D +{=0D + EFI_FVB_ATTRIBUTES_2 FlashFvbAttributes;=0D + CONST FT_FVB_DEVICE *FlashInstance;=0D +=0D + FlashInstance =3D INSTANCE_FROM_FVB_THIS(This);=0D +=0D + FlashFvbAttributes =3D (EFI_FVB_ATTRIBUTES_2) (=0D +=0D + EFI_FVB2_READ_ENABLED_CAP | // Reads may be enabled=0D + EFI_FVB2_READ_STATUS | // Reads are currently enabled=0D + EFI_FVB2_STICKY_WRITE | // A block erase is required to flip bit= s into EFI_FVB2_ERASE_POLARITY=0D + EFI_FVB2_MEMORY_MAPPED | // It is memory mapped=0D + EFI_FVB2_ERASE_POLARITY // After erasure all bits take this valu= e (i.e. '1')=0D +=0D + );=0D +=0D + // Check if it is write protected=0D + if (FlashInstance->Media.ReadOnly !=3D TRUE) {=0D +=0D + FlashFvbAttributes =3D FlashFvbAttributes |=0D + EFI_FVB2_WRITE_STATUS | // Writes are curren= tly enabled=0D + EFI_FVB2_WRITE_ENABLED_CAP; // Writes may be ena= bled=0D + }=0D +=0D + *Attributes =3D FlashFvbAttributes;=0D +=0D + return EFI_SUCCESS;=0D +}=0D +=0D +=0D +/**=0D + The PhytiumFvbSetAttributes() function sets configurable firmware volume= attributes=0D + and returns the new settings of the firmware volume.=0D +=0D + @param This EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL inst= ance.=0D +=0D + @param Attributes On input, Attributes is a pointer to=0D + EFI_FVB_ATTRIBUTES_2 that contains the d= esired=0D + firmware volume settings.=0D + On successful return, it contains the ne= w=0D + settings of the firmware volume.=0D +=0D + @retval EFI_SUCCESS The firmware volume attributes were retu= rned.=0D +=0D + @retval EFI_INVALID_PARAMETER The attributes requested are in conflict= with=0D + the capabilities as declared in the firm= ware=0D + volume header.=0D +=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +PhytiumFvbSetAttributes (=0D + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,=0D + IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes=0D + )=0D +{=0D + return EFI_UNSUPPORTED;=0D +}=0D +=0D +=0D +/**=0D + The PhytiumFvbGetPhysicalAddress() function retrieves the base address o= f=0D + a memory-mapped firmware volume. This function should be called=0D + only for memory-mapped firmware volumes.=0D +=0D + @param This EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.= =0D +=0D + @param Address Pointer to a caller-allocated=0D + EFI_PHYSICAL_ADDRESS that, on successful=0D + return from GetPhysicalAddress(), contains the= =0D + base address of the firmware volume.=0D +=0D + @retval EFI_SUCCESS The firmware volume base address was returned.= =0D +=0D + @retval EFI_NOT_SUPPORTED The firmware volume is not memory mapped.=0D +=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +PhytiumFvbGetPhysicalAddress (=0D + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,=0D + OUT EFI_PHYSICAL_ADDRESS *Address=0D + )=0D +{=0D + FT_FVB_DEVICE *FlashInstance;=0D +=0D + ASSERT (Address !=3D NULL);=0D +=0D + FlashInstance =3D INSTANCE_FROM_FVB_THIS (This);=0D +=0D + *Address =3D mFlashNvStorageVariableBase;=0D +=0D + return EFI_SUCCESS;=0D +}=0D +=0D +=0D +/**=0D + The PhytiumFvbGetBlockSize() function retrieves the size of the requeste= d=0D + block. It also returns the number of additional blocks with=0D + the identical size. The PhytiumFvbGetBlockSize() function is used to=0D + retrieve the block map (see EFI_FIRMWARE_VOLUME_HEADER).=0D +=0D +=0D + @param This EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL inst= ance.=0D +=0D + @param Lba Indicates the block whose size to return= .=0D +=0D + @param BlockSize Pointer to a caller-allocated UINTN in w= hich=0D + the size of the block is returned.=0D +=0D + @param NumberOfBlocks Pointer to a caller-allocated UINTN in=0D + which the number of consecutive blocks,= =0D + starting with Lba, is returned. All=0D + blocks in this range have a size of=0D + BlockSize.=0D +=0D +=0D + @retval EFI_SUCCESS The firmware volume base address was ret= urned.=0D +=0D + @retval EFI_INVALID_PARAMETER The requested LBA is out of range.=0D +=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +PhytiumFvbGetBlockSize (=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 Status;=0D + FT_FVB_DEVICE *FlashInstance;=0D +=0D + FlashInstance =3D INSTANCE_FROM_FVB_THIS(This);=0D +=0D + if (Lba > FlashInstance->Media.LastBlock) {=0D + Status =3D EFI_INVALID_PARAMETER;=0D + } else {=0D + // This is easy because in this platform each NorFlash device has equa= l sized blocks.=0D + *BlockSize =3D (UINTN) FlashInstance->Media.BlockSize;=0D + *NumberOfBlocks =3D (UINTN) (FlashInstance->Media.LastBlock - Lba + 1)= ;=0D + Status =3D EFI_SUCCESS;=0D + }=0D +=0D + return Status;=0D +}=0D +=0D +=0D +/**=0D + Reads the specified number of bytes into a buffer from the specified blo= ck.=0D +=0D + The PhytiumFvbRead() function reads the requested number of bytes from t= he=0D + requested block and stores them in the provided buffer.=0D + Implementations should be mindful that the firmware volume=0D + might be in the ReadDisabled state. If it is in this state,=0D + the PhytiumFvbRead() function must return the status code=0D + EFI_ACCESS_DENIED without modifying the contents of the=0D + buffer. The PhytiumFvbRead() function must also prevent spanning block=0D + boundaries. If a read is requested that would span a block=0D + boundary, the read must read up to the boundary but not=0D + beyond. The output parameter NumBytes must be set to correctly=0D + indicate the number of bytes actually read. The caller must be=0D + aware that a read may be partially completed.=0D +=0D + @param This EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance= .=0D +=0D + @param Lba The starting logical block index from which = to read.=0D +=0D + @param Offset Offset into the block at which to begin read= ing.=0D +=0D + @param NumBytes Pointer to a UINTN.=0D + At entry, *NumBytes contains the total size = of the=0D + buffer.=0D + At exit, *NumBytes contains the total number= of=0D + bytes read.=0D +=0D + @param Buffer Pointer to a caller-allocated buffer that wi= ll be=0D + used to hold the data that is read.=0D +=0D + @retval EFI_SUCCESS The firmware volume was read successfully, a= nd=0D + contents are in Buffer.=0D +=0D + @retval EFI_BAD_BUFFER_SIZE Read attempted across an LBA boundary.=0D + On output, NumBytes contains the total numbe= r of=0D + bytes returned in Buffer.=0D +=0D + @retval EFI_ACCESS_DENIED The firmware volume is in the ReadDisabled s= tate.=0D +=0D + @retval EFI_DEVICE_ERROR The block device is not functioning correctl= y and=0D + could not be read.=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +PhytiumFvbRead (=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 + UINTN BlockSize;=0D + FT_FVB_DEVICE *FlashInstance;=0D + EFI_STATUS Status;=0D +=0D + FlashInstance =3D INSTANCE_FROM_FVB_THIS(This);=0D +=0D + // Cache the block size to avoid de-referencing pointers all the time=0D + BlockSize =3D FlashInstance->Media.BlockSize;=0D +=0D + // The read 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 + (*NumBytes > BlockSize) ||=0D + ((Offset + *NumBytes) > BlockSize)) {=0D + return EFI_BAD_BUFFER_SIZE;=0D + }=0D +=0D + // We must have some bytes to read=0D + if (*NumBytes =3D=3D 0) {=0D + return EFI_BAD_BUFFER_SIZE;=0D + }=0D +=0D + Status =3D PhytiumFvbFlashRead (FlashInstance, FlashInstance->StartLba += Lba, Offset, *NumBytes, Buffer);=0D + if (EFI_ERROR (Status)) {=0D + return EFI_DEVICE_ERROR;=0D + }=0D +=0D + return EFI_SUCCESS;=0D +}=0D +=0D +=0D +/**=0D + Writes the specified number of bytes from the input buffer to the block.= =0D +=0D + The PhytiumFvbWrite() function writes the specified number of bytes from= =0D + the provided buffer to the specified block and offset. If the=0D + firmware volume is sticky write, the caller must ensure that=0D + all the bits of the specified range to write are in the=0D + EFI_FVB_ERASE_POLARITY state before calling the PhytiumFvbWrite()=0D + function, or else the result will be unpredictable. This=0D + unpredictability arises because, for a sticky-write firmware=0D + volume, a write may negate a bit in the EFI_FVB_ERASE_POLARITY=0D + state but cannot flip it back again. Before calling the=0D + PhytiumFvbWrite() function, it is recommended for the caller to=0D + first call the PhytiumFvbEraseBlocks() function to erase the specified=0D + block to write. A block erase cycle will transition bits from=0D + the (NOT)EFI_FVB_ERASE_POLARITY state back to the=0D + EFI_FVB_ERASE_POLARITY state. Implementations should be=0D + mindful that the firmware volume might be in the WriteDisabled=0D + state. If it is in this state, the PhytiumFvbWrite() function must=0D + return the status code EFI_ACCESS_DENIED without modifying the=0D + contents of the firmware volume. The PhytiumFvbWrite() function must=0D + also prevent spanning block boundaries. If a write is=0D + requested that spans a block boundary, the write must store up=0D + to the boundary but not beyond. The output parameter NumBytes=0D + must be set to correctly indicate the number of bytes actually=0D + written. The caller must be aware that a write may be=0D + partially completed. All writes, partial or otherwise, must be=0D + fully flushed to the hardware before the PhytiumFvbWrite() service=0D + returns.=0D +=0D + @param This EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance= .=0D +=0D + @param Lba The starting logical block index to write to= .=0D +=0D + @param Offset Offset into the block at which to begin writ= ing.=0D +=0D + @param NumBytes The pointer to a UINTN.=0D + At entry, *NumBytes contains the total size = of the=0D + buffer.=0D + At exit, *NumBytes contains the total number= of=0D + bytes actually written.=0D +=0D + @param Buffer The pointer to a caller-allocated buffer tha= t=0D + contains the source for the write.=0D +=0D + @retval EFI_SUCCESS The firmware volume was written successfully= .=0D +=0D + @retval EFI_BAD_BUFFER_SIZE The write was attempted across an LBA bounda= ry.=0D + On output, NumBytes contains the total numbe= r of=0D + bytes actually written.=0D +=0D + @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisabled = state.=0D +=0D + @retval EFI_DEVICE_ERROR The block device is malfunctioning and could= not be=0D + written.=0D +=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +PhytiumFvbWrite (=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 + FT_FVB_DEVICE *FlashInstance;=0D +=0D + FlashInstance =3D INSTANCE_FROM_FVB_THIS (This);=0D +=0D + return PhytiumFvbFlashWrite (FlashInstance, FlashInstance->StartLba + Lb= a, Offset, *NumBytes, Buffer);=0D +}=0D +=0D +=0D +/**=0D + Erases and initialises a firmware volume block.=0D +=0D + The PhytiumFvbEraseBlocks() function erases one or more blocks as denote= d=0D + by the variable argument list. The entire parameter list of=0D + blocks must be verified before erasing any blocks. If a block is=0D + requested that does not exist within the associated firmware=0D + volume (it has a larger index than the last block of the=0D + firmware volume), the PhytiumFvbEraseBlocks() function must return the=0D + status code EFI_INVALID_PARAMETER without modifying the contents=0D + of the firmware volume. Implementations should be mindful that=0D + the firmware volume might be in the WriteDisabled state. If it=0D + is in this state, the PhytiumFvbEraseBlocks() function must return the=0D + status code EFI_ACCESS_DENIED without modifying the contents of=0D + the firmware volume. All calls to PhytiumFvbEraseBlocks() must be fully= =0D + flushed to the hardware before the PhytiumFvbEraseBlocks() service=0D + returns.=0D +=0D + @param This EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL=0D + instance.=0D +=0D + @param ... The variable argument list is a list of = tuples.=0D + Each tuple describes a range of LBAs to = erase=0D + and consists of the following:=0D + An EFI_LBA that indicates the starting L= BA=0D + A UINTN that indicates the number of blo= cks=0D + to erase.=0D +=0D + The list is terminated with an=0D + EFI_LBA_LIST_TERMINATOR.=0D +=0D + @retval EFI_SUCCESS The erase request successfully completed= .=0D +=0D + @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisab= led=0D + state.=0D +=0D + @retval EFI_DEVICE_ERROR The block device is not functioning corr= ectly=0D + and could not be written.=0D + The firmware device may have been partia= lly=0D + erased.=0D +=0D + @retval EFI_INVALID_PARAMETER One or more of the LBAs listed in the va= riable=0D + argument list do not exist in the firmwa= re=0D + volume.=0D +=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +PhytiumFvbEraseBlocks (=0D + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,=0D + ...=0D + )=0D +{=0D + EFI_STATUS Status;=0D + VA_LIST Args;=0D + 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 + FT_FVB_DEVICE *Instance;=0D +=0D + Instance =3D INSTANCE_FROM_FVB_THIS(This);=0D +=0D + Status =3D EFI_SUCCESS;=0D +=0D + // Detect WriteDisabled state=0D + if (Instance->Media.ReadOnly =3D=3D TRUE) {=0D + // Firmware volume is in WriteDisabled state=0D + DEBUG ((DEBUG_ERROR, "FvbEraseBlocks: ERROR - Device is in WriteDisabl= ed state.\n"));=0D + return EFI_ACCESS_DENIED;=0D + }=0D +=0D + // Before erasing, check the entire list of parameters to ensure all spe= cified blocks are valid=0D +=0D + VA_START (Args, This);=0D + do {=0D + // Get the Lba from which we start erasing=0D + StartingLba =3D VA_ARG (Args, EFI_LBA);=0D +=0D + // Have we reached the end of the list?=0D + if (StartingLba =3D=3D EFI_LBA_LIST_TERMINATOR) {=0D + //Exit the while loop=0D + break;=0D + }=0D +=0D + // How many Lba blocks are we requested to erase?=0D + NumOfLba =3D VA_ARG (Args, UINT32);=0D +=0D + // All blocks must be within range=0D + if ((NumOfLba =3D=3D 0) || ((Instance->StartLba + StartingLba + NumOfL= ba - 1) > Instance->Media.LastBlock)) {=0D + VA_END (Args);=0D + DEBUG ((DEBUG_ERROR, "FvbEraseBlocks: ERROR - Lba range goes past th= e last Lba.\n"));=0D + Status =3D EFI_INVALID_PARAMETER;=0D + goto EXIT;=0D + }=0D + } while (TRUE);=0D + VA_END (Args);=0D +=0D + //=0D + // To get here, all must be ok, so start erasing=0D + //=0D + VA_START (Args, This);=0D + do {=0D + // Get the Lba from which we start erasing=0D + StartingLba =3D VA_ARG (Args, EFI_LBA);=0D +=0D + // Have we reached the end of the list?=0D + if (StartingLba =3D=3D EFI_LBA_LIST_TERMINATOR) {=0D + // Exit the while loop=0D + break;=0D + }=0D +=0D + // How many Lba blocks are we requested to erase?=0D + NumOfLba =3D VA_ARG (Args, UINT32);=0D +=0D + // Go through each one and erase it=0D + while (NumOfLba > 0) {=0D +=0D + // Get the physical address of Lba to erase=0D + BlockAddress =3D GET_DATA_OFFSET (=0D + Instance->RegionBaseAddress,=0D + Instance->StartLba + StartingLba,=0D + Instance->Media.BlockSize=0D + );=0D +=0D + // Erase it=0D + Status =3D FvbFlashEraseSingleBlock (Instance, BlockAddress);=0D + if (EFI_ERROR(Status)) {=0D + VA_END (Args);=0D + Status =3D EFI_DEVICE_ERROR;=0D + goto EXIT;=0D + }=0D +=0D + // Move to the next Lba=0D + StartingLba++;=0D + NumOfLba--;=0D + }=0D + } while (TRUE);=0D +=0D + VA_END (Args);=0D +=0D +EXIT:=0D + return Status;=0D +}=0D +=0D +=0D +//extern const UINT64 _gPcd_FixedAtBuild_PcdSpiControllerBase;=0D +//extern const UINT64 _gPcd_FixedAtBuild_PcdSpiControllerSize;=0D +//#define SPI_CONTROLLER_BASE _gPcd_FixedAtBuild_PcdSpiControllerBase= =0D +//#define SPI_CONTROLLER_SIZE _gPcd_FixedAtBuild_PcdSpiControllerSize= =0D +=0D +/**=0D + This function inited the NorFlash instance.=0D +=0D + @param[in][out] FlashInstance The pointer of FT_FVB_DEVICE instance.=0D +=0D + @retval EFI_SUCCESS PhytNorFlashFvbInitialize() is executed = successfully.=0D +=0D +**/=0D +STATIC=0D +EFI_STATUS=0D +PhytNorFlashFvbInitialize (=0D + IN OUT FT_FVB_DEVICE *FlashInstance=0D + )=0D +{=0D + EFI_STATUS Status;=0D + UINT32 FvbNumLba;=0D + EFI_BOOT_MODE BootMode;=0D + UINTN TotalFvbSize;=0D +=0D + mFlashNvStorageVariableBase =3D FixedPcdGet64 (PcdFlashNvStorageVariable= Base64);=0D +=0D + // Declare the Non-Volatile storage as EFI_MEMORY_RUNTIME=0D +=0D + // Note: all the NOR Flash region needs to be reserved into the UEFI Run= time memory;=0D + // even if we only use the small block region at the top of the NO= R Flash.=0D + // The reason is when the NOR Flash memory is set into program mod= e, the command=0D + // is written as the base of the flash region (ie: FlashInstance->= DeviceBaseAddress)=0D + // Todo: SPI control block should be remapped, otherwise ...=0D + Status =3D gDS->AddMemorySpace (=0D + EfiGcdMemoryTypeMemoryMappedIo,=0D + mFlashNvStorageVariableBase, FlashInstance->FvbSize,=0D + EFI_MEMORY_UC | EFI_MEMORY_RUNTIME=0D + );=0D + ASSERT_EFI_ERROR (Status);=0D +=0D + Status =3D gDS->SetMemorySpaceAttributes (=0D + mFlashNvStorageVariableBase, FlashInstance->FvbSize,=0D + EFI_MEMORY_UC | EFI_MEMORY_RUNTIME=0D + );=0D + ASSERT_EFI_ERROR (Status);=0D +=0D + TotalFvbSize =3D FlashInstance->FvbSize;=0D +=0D + // Set the index of the first LBA for the FVB=0D + FlashInstance->StartLba =3D (PcdGet64 (PcdFlashNvStorageVariableBase64) = - FlashInstance->RegionBaseAddress) / FlashInstance->Media.BlockSize;=0D +=0D + BootMode =3D GetBootModeHob ();=0D + if (BootMode =3D=3D BOOT_WITH_DEFAULT_SETTINGS) {=0D + Status =3D EFI_INVALID_PARAMETER;=0D + } else {=0D + // Determine if there is a valid header at the beginning of the NorFla= sh=0D + Status =3D PhytiumFvbValidateFvHeader (FlashInstance);=0D + }=0D +=0D + // Install the Default FVB header if required=0D + if (EFI_ERROR(Status)) {=0D + // There is no valid header, so time to install one.=0D + DEBUG((DEBUG_ERROR,"NorFlashFvbInitialize: ERROR - The FVB Header is i= nvalid. Installing a correct one for this volume.\n"));=0D +=0D + // Erase all the NorFlash that is reserved for variable storage=0D + FvbNumLba =3D TotalFvbSize / FlashInstance->Media.BlockSize;=0D +=0D + Status =3D PhytiumFvbEraseBlocks (&FlashInstance->FvbProtocol, (EFI_LB= A)0, FvbNumLba, EFI_LBA_LIST_TERMINATOR);=0D + if (EFI_ERROR(Status)) {=0D + return Status;=0D + }=0D +=0D + // Install all appropriate headers=0D + Status =3D PhytiumFvbInitFvAndVariableStoreHeaders (FlashInstance);=0D + if (EFI_ERROR(Status)) {=0D + return Status;=0D + }=0D + }=0D +=0D + return Status;=0D +}=0D +=0D +=0D +/**=0D + The CreateInstance() function Create Fvb Instance.=0D +=0D + @retval EFI_SUCCESS Create Instance successfully.=0D +=0D + @retval other Create Instance failed.=0D +=0D +**/=0D +STATIC=0D +EFI_STATUS=0D +CreateInstance (=0D + VOID=0D + )=0D +{=0D + EFI_STATUS Status;=0D + NOR_FLASH_DEVICE_DESCRIPTION *NorFlashDevice;=0D +=0D + // Locate flash protocols=0D + Status =3D gBS->LocateProtocol (&gPhytiumFlashProtocolGuid,=0D + NULL,=0D + (VOID **)&PhytiumFvbDevice->SpiFlashProtocol);=0D + if (EFI_ERROR (Status)) {=0D + DEBUG ((DEBUG_ERROR, "Cannot locate NorFlash protocol.\n"));=0D + return Status;=0D + }=0D +=0D + NorFlashDevice =3D AllocateRuntimePool(sizeof(NOR_FLASH_DEVICE_DESCRIPTI= ON));=0D + if (NorFlashDevice =3D=3D NULL) {=0D + DEBUG ((DEBUG_ERROR, "Cannot Allocate NorFlashDevice Pool.\n"));=0D + return Status;=0D + }=0D +=0D + Status =3D PhytiumFvbDevice->SpiFlashProtocol->GetDevices (NorFlashDevic= e);=0D + if (EFI_ERROR(Status)) {=0D + return Status;=0D + }=0D +=0D + Status =3D PhytiumFvbDevice->SpiFlashProtocol->Initialization();=0D + if (EFI_ERROR(Status)) {=0D + return Status;=0D + }=0D +=0D + PhytiumFvbDevice->DeviceBaseAddress =3D NorFlashDevice->DeviceBaseAddres= s;=0D + PhytiumFvbDevice->RegionBaseAddress =3D NorFlashDevice->RegionBaseAddres= s;=0D + PhytiumFvbDevice->Size =3D NorFlashDevice->Size;=0D +=0D + PhytiumFvbDevice->Media.MediaId =3D 0;=0D + PhytiumFvbDevice->Media.BlockSize =3D NorFlashDevice->BlockSize;=0D + PhytiumFvbDevice->Media.LastBlock =3D (PhytiumFvbDevice->Size / PhytiumF= vbDevice->Media.BlockSize) - 1;=0D + PhytiumFvbDevice->FvbSize =3D PcdGet32 (PcdFlashNvStorageVariableSize) += =0D + PcdGet32 (PcdFlashNvStorageFtwWorkingSize) += =0D + PcdGet32 (PcdFlashNvStorageFtwSpareSize);=0D + DEBUG ((DEBUG_INFO, "%a: line at %d, DeviceBaseAddress=3D%x,PhytiumFvbDe= vice->Size=3D%x\n", __FUNCTION__, __LINE__, PhytiumFvbDevice->DeviceBaseAdd= ress, PhytiumFvbDevice->Size));=0D +=0D + CopyGuid (&PhytiumFvbDevice->DevicePath.Vendor.Guid, &NorFlashDevice->Gu= id);=0D +=0D + PhytiumFvbDevice->ShadowBuffer =3D AllocateRuntimePool (PhytiumFvbDevice= ->Media.BlockSize);=0D + if (PhytiumFvbDevice->ShadowBuffer =3D=3D NULL) {=0D + return EFI_OUT_OF_RESOURCES;=0D + }=0D +=0D + Status =3D gBS->InstallMultipleProtocolInterfaces (=0D + &PhytiumFvbDevice->Handle,=0D + &gEfiDevicePathProtocolGuid, &PhytiumFvbDevice->DevicePath,= =0D + &gEfiFirmwareVolumeBlockProtocolGuid, &PhytiumFvbDevice->Fvb= Protocol,=0D + NULL=0D + );=0D + if (EFI_ERROR(Status)) {=0D + FreePool (PhytiumFvbDevice);=0D + return Status;=0D + }=0D +=0D + Status =3D PhytNorFlashFvbInitialize(PhytiumFvbDevice);=0D + if (EFI_ERROR(Status)) {=0D + DEBUG((DEBUG_ERROR, "PhytNorFlashFvbInitialize: Fail to init NorFlash = devices\n"));=0D + return Status;=0D + }=0D +=0D + FreePool(NorFlashDevice);=0D +=0D + return Status;=0D +}=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 lib to= virtual mode.=0D +=0D + @param[in] Event The Event that is being processed.=0D +=0D + @param[in] Context Event Context.=0D +=0D + @retval None.=0D +=0D +**/=0D +STATIC=0D +VOID=0D +EFIAPI=0D +PhytiumFvbVirtualNotifyEvent (=0D + IN EFI_EVENT Event,=0D + IN VOID *Context=0D + )=0D +{=0D + // Convert SpiFlashProtocol=0D + EfiConvertPointer (0x0, (VOID**)&PhytiumFvbDevice->SpiFlashProtocol->Era= se);=0D + EfiConvertPointer (0x0, (VOID**)&PhytiumFvbDevice->SpiFlashProtocol->Wri= te);=0D + EfiConvertPointer (0x0, (VOID**)&PhytiumFvbDevice->SpiFlashProtocol->Rea= d);=0D + EfiConvertPointer (0x0, (VOID**)&PhytiumFvbDevice->SpiFlashProtocol->Get= Devices);=0D + EfiConvertPointer (0x0, (VOID**)&PhytiumFvbDevice->SpiFlashProtocol->Ini= tialization);=0D + EfiConvertPointer (0x0, (VOID**)&PhytiumFvbDevice->SpiFlashProtocol->Era= seSingleBlock);=0D + EfiConvertPointer (0x0, (VOID**)&PhytiumFvbDevice->SpiFlashProtocol);=0D +=0D + EfiConvertPointer (0x0, (VOID**)&mFlashNvStorageVariableBase);=0D + EfiConvertPointer (0x0, (VOID**)&PhytiumFvbDevice);=0D +=0D + return;=0D +}=0D +=0D +=0D +/**=0D + This function is the entrypoint of the fvb driver.=0D +=0D + @param[in] ImageHandle The firmware allocated handle for the EFI imag= e.=0D +=0D + @param[in] SystemTable A pointer to the EFI System Table.=0D +=0D + @retval EFI_SUCCESS The entry point is executed successfully.=0D +=0D + @retval other Some error occurs when executing this entry po= int.=0D +=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +PhytiumFvbEntryPoint (=0D + IN EFI_HANDLE ImageHandle,=0D + IN EFI_SYSTEM_TABLE *SystemTable=0D + )=0D +{=0D + EFI_STATUS Status;=0D +=0D + PhytiumFvbDevice =3D AllocateRuntimeCopyPool (sizeof(PhytiumFvbFlashInst= anceTemplate), &PhytiumFvbFlashInstanceTemplate);=0D + if (PhytiumFvbDevice =3D=3D NULL) {=0D + DEBUG ((DEBUG_ERROR, "%a: Cannot allocate memory\n", __FUNCTION__));=0D + return EFI_OUT_OF_RESOURCES;=0D + }=0D +=0D + Status =3D CreateInstance ();=0D + if (EFI_ERROR(Status)) {=0D + DEBUG((DEBUG_ERROR, "CreateInstance: Fail to create instance for NorFl= ash\n"));=0D + }=0D +=0D +//=0D +// Register for the virtual address change event=0D +//=0D + Status =3D gBS->CreateEventEx (=0D + EVT_NOTIFY_SIGNAL,=0D + TPL_NOTIFY,=0D + PhytiumFvbVirtualNotifyEvent,=0D + NULL,=0D + &gEfiEventVirtualAddressChangeGuid,=0D + &FvbVirtualAddrChangeEvent=0D + );=0D + ASSERT_EFI_ERROR (Status);=0D +=0D + return Status;=0D +}=0D --=20 2.25.1