From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from zg8tmtyylji0my4xnjqunzqa.icoremail.net (zg8tmtyylji0my4xnjqunzqa.icoremail.net [162.243.164.74]) by mx.groups.io with SMTP id smtpd.web08.52138.1629280091781704447 for ; Wed, 18 Aug 2021 02:48:12 -0700 Authentication-Results: mx.groups.io; dkim=missing; spf=pass (domain: phytium.com.cn, ip: 162.243.164.74, mailfrom: jialing@phytium.com.cn) Received: from prodtpl.icoremail.net (unknown [10.12.1.20]) by hzbj-icmmx-2 (Coremail) with SMTP id AQAAfwAnUdF01xxhUOltAQ--.34326S2; Wed, 18 Aug 2021 17:48:36 +0800 (CST) Received: from localhost.localdomain (unknown [223.104.21.14]) by mail (Coremail) with SMTP id AQAAfwA30XxX1xxhqDMAAA--.626S3; Wed, 18 Aug 2021 17:48:08 +0800 (CST) From: "Ling Jia" To: devel@edk2.groups.io Cc: Leif Lindholm , Ling Jia Subject: [PATCH v4 08/10] Silicon/Phytium: Added fvb driver for norflash Date: Wed, 18 Aug 2021 17:47:53 +0800 Message-Id: <20210818094755.40300-2-jialing@phytium.com.cn> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210818094755.40300-1-jialing@phytium.com.cn> References: <20210818094755.40300-1-jialing@phytium.com.cn> MIME-Version: 1.0 X-CM-TRANSID: AQAAfwA30XxX1xxhqDMAAA--.626S3 X-CM-SenderInfo: xmldzxdqj61x51wl3zoofrzhdfq/ Authentication-Results: hzbj-icmmx-2; spf=neutral smtp.mail=jialing@ph ytium.com.cn; X-Coremail-Antispam: 1Uk129KBjvAXoWDJw4UXrW3KF15Kr4DKr13twb_yoWrCry8to WxZr4fXw18trWSgFs8KrWjk3y7JFnaqanxtrs5Zry2q3Z5Jw1a9FWIy3WUWw4ft34jkrnx KryfX3s5JFW3trykn29KB7ZKAUJUUUUU529EdanIXcx71UUUUU7KY7ZEXasCq-sGcSsGvf J3UbIjqfuFe4nvWSU8nxnvy29KBjDU0xBIdaVrnUUvcSsGvfC2KfnxnUUI43ZEXa7xR_UU UUUUUUU== Content-Transfer-Encoding: quoted-printable The FlashFvbDxe provided the fvb protocol, which requested by the flash operators. 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 1c47051441..99034365d3 100644 --- a/Platform/Phytium/DurianPkg/DurianPkg.dsc +++ b/Platform/Phytium/DurianPkg/DurianPkg.dsc @@ -253,6 +253,7 @@ # NOR Flash driver=0D #=0D Silicon/Phytium/FT2000-4Pkg/Drivers/SpiNorFlashDxe/SpiNorFlashDxe.inf=0D + Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.inf=0D =0D #=0D # Usb Support=0D diff --git a/Platform/Phytium/DurianPkg/DurianPkg.fdf b/Platform/Phytium/Du= rianPkg/DurianPkg.fdf index 831f7a6828..67458458dd 100644 --- a/Platform/Phytium/DurianPkg/DurianPkg.fdf +++ b/Platform/Phytium/DurianPkg/DurianPkg.fdf @@ -103,6 +103,7 @@ READ_LOCK_STATUS =3D TRUE =0D INF ArmPkg/Drivers/ArmGic/ArmGicDxe.inf=0D INF ArmPkg/Drivers/CpuDxe/CpuDxe.inf=0D + INF Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.inf= =0D INF ArmPkg/Drivers/TimerDxe/TimerDxe.inf=0D INF ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdogDxe.inf=0D =0D 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 0000000000..ff23721d6e --- /dev/null +++ b/Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.inf @@ -0,0 +1,61 @@ +#/** @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 +[Defines]=0D + INF_VERSION =3D 0x0001001b=0D + BASE_NAME =3D FlashFvbDxe=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 FvbEntryPoint=0D +=0D +[Sources]=0D + FlashFvbDxe.c=0D + FlashFvbDxe.h=0D +=0D +[Packages]=0D + EmbeddedPkg/EmbeddedPkg.dec=0D + MdePkg/MdePkg.dec=0D + MdeModulePkg/MdeModulePkg.dec=0D + Silicon/Phytium/PhytiumCommonPkg/PhytiumCommonPkg.dec=0D +=0D +[LibraryClasses]=0D + BaseLib=0D + DebugLib=0D + DxeServicesTableLib=0D + HobLib=0D + MemoryAllocationLib=0D + UefiBootServicesTableLib=0D + UefiRuntimeLib=0D + UefiDriverEntryPoint=0D +=0D +[Guids]=0D + gEfiAuthenticatedVariableGuid=0D + gEfiEventVirtualAddressChangeGuid=0D + gEfiSystemNvDataFvGuid=0D + gEfiVariableGuid=0D +=0D +[Protocols]=0D + gEfiDevicePathProtocolGuid=0D + gEfiFirmwareVolumeBlockProtocolGuid=0D + gSpiNorFlashProtocolGuid=0D +=0D +[Pcd.common]=0D + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64=0D + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize=0D + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase64=0D + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize=0D + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase64=0D + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize=0D + gPhytiumPlatformTokenSpaceGuid.PcdSpiFlashBase=0D + gPhytiumPlatformTokenSpaceGuid.PcdSpiFlashSize=0D +=0D +[Depex]=0D + gSpiNorFlashProtocolGuid=0D diff --git a/Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbD= xe.h b/Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.h new file mode 100644 index 0000000000..e63ff9f220 --- /dev/null +++ b/Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.h @@ -0,0 +1,104 @@ +/** @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 +EFI_STATUS=0D +EFIAPI=0D +FvbGetAttributes (=0D + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL * This,=0D + OUT EFI_FVB_ATTRIBUTES_2 * Attributes=0D + );=0D +=0D +EFI_STATUS=0D +EFIAPI=0D +FvbSetAttributes (=0D + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL * This,=0D + IN OUT EFI_FVB_ATTRIBUTES_2 * Attributes=0D + );=0D +=0D +EFI_STATUS=0D +EFIAPI=0D +FvbGetPhysicalAddress (=0D + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL * This,=0D + OUT EFI_PHYSICAL_ADDRESS * Address=0D + );=0D +=0D +EFI_STATUS=0D +EFIAPI=0D +FvbGetBlockSize (=0D + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL * This,=0D + IN EFI_LBA Lba,=0D + OUT UINTN * BlockSize,=0D + OUT UINTN * NumberOfBlocks=0D + );=0D +=0D +EFI_STATUS=0D +EFIAPI=0D +FvbRead (=0D + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL * This,=0D + IN EFI_LBA Lba,=0D + IN UINTN Offset,=0D + IN OUT UINTN * NumBytes,=0D + IN OUT UINT8 * Buffer=0D + );=0D +=0D +EFI_STATUS=0D +EFIAPI=0D +FvbWrite (=0D + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL * This,=0D + IN EFI_LBA Lba,=0D + IN UINTN Offset,=0D + IN OUT UINTN * NumBytes,=0D + IN UINT8 * Buffer=0D + );=0D +=0D +EFI_STATUS=0D +EFIAPI=0D +FvbEraseBlocks (=0D + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL * This,=0D + ...=0D + );=0D +=0D +#endif // FVB_FLASH_DXE_H_=0D diff --git a/Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbD= xe.c b/Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.c new file mode 100644 index 0000000000..794db68987 --- /dev/null +++ b/Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.c @@ -0,0 +1,1304 @@ +/** @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 +=0D +#include "FlashFvbDxe.h"=0D +=0D +STATIC EFI_EVENT FvbVirtualAddrChangeEvent;=0D +STATIC FT_FVB_DEVICE *FvbDevice;=0D +STATIC UINTN mFlashNvStorageVariableBase;=0D +STATIC UINTN mFlashNvStorageFtwWorkingBase;=0D +STATIC UINTN mFlashNvStorageFtwSpareBase;=0D +STATIC UINT32 mFlashNvStorageVariableSize;=0D +STATIC UINT32 mFlashNvStorageFtwWorkingSize;=0D +STATIC UINT32 mFlashNvStorageFtwSpareSize;=0D +=0D +STATIC FT_FVB_DEVICE FvbFlashInstanceTemplate =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 + FvbGetAttributes, // GetAttributes=0D + FvbSetAttributes, // SetAttributes=0D + FvbGetPhysicalAddress, // GetPhysicalAddress=0D + FvbGetBlockSize, // GetBlockSize=0D + FvbRead, // Read=0D + FvbWrite, // Write=0D + FvbEraseBlocks, // EraseBlocks=0D + NULL, // ParentHandle=0D + }, // FvbProtoccol;=0D +=0D + {=0D + {=0D + {=0D + HARDWARE_DEVICE_PATH,=0D + HW_VENDOR_DP,=0D + {=0D + (UINT8) sizeof (VENDOR_DEVICE_PATH),=0D + (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)=0D + }=0D + },=0D + {=0D + 0x0, 0x0, 0x0, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }=0D + }, // GUID ... NEED TO BE FILLED=0D + },=0D + {=0D + END_DEVICE_PATH_TYPE,=0D + END_ENTIRE_DEVICE_PATH_SUBTYPE,=0D + {=0D + sizeof (EFI_DEVICE_PATH_PROTOCOL),=0D + 0=0D + }=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 + OriginalTPL =3D gBS->RaiseTPL (TPL_HIGH_LEVEL);=0D + } else {=0D + OriginalTPL =3D TPL_HIGH_LEVEL;=0D + }=0D +=0D + Index =3D 0;=0D +=0D + do {=0D + Status =3D FlashInstance->SpiFlashProtocol->EraseSingleBlock (BlockAdd= ress);=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 ((=0D + DEBUG_ERROR,=0D + "EraseSingleBlock(BlockAddress=3D0x%08x: BlockLocked Error (try to e= rase % d times)\n",=0D + BlockAddress,=0D + Index=0D + ));=0D + }=0D +=0D + if ( ! EfiAtRuntime ()) {=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 FvbFlashRead() is executed successfully= .=0D +=0D +**/=0D +STATIC=0D +EFI_STATUS=0D +FvbFlashRead (=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;=0D +=0D + Address =3D GET_DATA_OFFSET (=0D + FlashInstance->RegionBaseAddress,=0D + Lba,=0D + FlashInstance->Media.BlockSize=0D + ) + 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 +=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 FvbWriteBlock() is executed successfull= y.=0D +=0D + @retval EFI_BAD_BUFFER_SIZE The write spaned block boundaries.=0D +=0D +**/=0D +STATIC=0D +EFI_STATUS=0D +FvbWriteBlock (=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 ((=0D + DEBUG_ERROR,=0D + "FvbWriteBlock: ERROR - Can not write:Device is in WriteDisabled sta= te.\n"=0D + ));=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 + {=0D + DEBUG ((=0D + DEBUG_ERROR,=0D + "FvbWriteBlock: ERROR - EFI_BAD_BUFFER_SIZE: (Offset =3D0x %x + NumB= ytes =3D0x%x) > BlockSize =3D0x%x\n",=0D + Offset,=0D + BufferSizeInBytes,=0D + BlockSize=0D + ));=0D + return EFI_BAD_BUFFER_SIZE;=0D + }=0D +=0D + // We must have some bytes to write=0D + if (BufferSizeInBytes =3D=3D 0) {=0D + DEBUG ((=0D + DEBUG_ERROR,=0D + "FvbWriteBlock: ERROR - EFI_BAD_BUFFER_SIZE: NumBytes =3D=3D 0\n"=0D + ));=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 ((=0D + DEBUG_ERROR,=0D + "FvbWriteBlock: ERROR - ShadowBuffer is NULL!\n"=0D + ));=0D + return EFI_DEVICE_ERROR;=0D + }=0D +=0D + //=0D + // Write the word to NOR.=0D + //=0D + BlockAddress =3D GET_DATA_OFFSET (=0D + FlashInstance->RegionBaseAddress,=0D + Lba,=0D + FlashInstance->Media.BlockSize=0D + );=0D +=0D + // Read NOR Flash data into shadow buffer=0D + Status =3D FlashInstance->SpiFlashProtocol->Read (=0D + BlockAddress,=0D + FlashInstance->ShadowBuffer,=0D + BlockSize=0D + );=0D + if (EFI_ERROR (Status)) {=0D + // Return one of the pre-approved error statuses=0D + return EFI_DEVICE_ERROR;=0D + }=0D +=0D + // Put the data at the appropriate location inside the buffer area=0D + CopyMem (=0D + (VOID *) ((UINTN)FlashInstance->ShadowBuffer + Offset),=0D + Buffer,=0D + BufferSizeInBytes=0D + );=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,=0D + FlashInstance->ShadowBuffer,=0D + BlockSize=0D + );=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 FvbFlashWrite() is executed successfully= .=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 +FvbFlashWrite (=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;=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 + Status =3D EFI_SUCCESS;=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=0D + // two large values together overflows.=0D + if (Offset >=3D BlockSize) {=0D + DEBUG ((=0D + DEBUG_ERROR,=0D + "FvbFlashWrite: ERROR - EFI_BAD_BUFFER_SIZE: Offset =3D0x%x > BlockS= ize =3D0x%x\n",=0D + Offset,=0D + BlockSize=0D + ));=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 FvbWriteBlock (=0D + FlashInstance,=0D + Lba,=0D + BlockOffset,=0D + WriteSize,=0D + Buffer=0D + );=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 FvbInitFvAndVariableStoreHeaders()=0D + is executed successfully.=0D +=0D +**/=0D +STATIC=0D +EFI_STATUS=0D +FvbInitFvAndVariableStoreHeaders (=0D + IN FT_FVB_DEVICE *FlashInstance=0D + )=0D +{=0D + EFI_STATUS Status;=0D + VOID * Headers;=0D + UINTN HeadersLength;=0D + UINT32 TempAttributes;=0D + EFI_FIRMWARE_VOLUME_HEADER *FirmwareVolumeHeader;=0D + VARIABLE_STORE_HEADER *VariableStoreHeader;=0D +=0D + HeadersLength =3D sizeof (EFI_FIRMWARE_VOLUME_HEADER) +=0D + sizeof (EFI_FV_BLOCK_MAP_ENTRY) +=0D + sizeof (VARIABLE_STORE_HEADER);=0D +=0D + Headers =3D AllocateZeroPool (HeadersLength);=0D +=0D + // FirmwareVolumeHeader->FvLength is declared to have the Variable area= =0D + // AND the FTW working area AND the FTW Spare contiguous.=0D + ASSERT (mFlashNvStorageVariableBase + mFlashNvStorageVariableSize =3D=3D= mFlashNvStorageFtwWorkingBase);=0D + ASSERT (mFlashNvStorageFtwWorkingBase + mFlashNvStorageFtwWorkingSize = =3D=3D mFlashNvStorageFtwSpareBase);=0D +=0D + // Check if the size of the area is at least one block size=0D + ASSERT ((mFlashNvStorageVariableSize > 0) && (mFlashNvStorageVariableSiz= e / FlashInstance->Media.BlockSize > 0));=0D + ASSERT ((mFlashNvStorageFtwWorkingSize > 0) && (mFlashNvStorageFtwWorkin= gSize / FlashInstance->Media.BlockSize > 0));=0D + ASSERT ((mFlashNvStorageFtwSpareSize > 0) && (mFlashNvStorageFtwSpareSiz= e / FlashInstance->Media.BlockSize > 0));=0D +=0D + // Ensure the Variable area Base Addresses are aligned on a block size b= oundaries=0D + ASSERT (mFlashNvStorageVariableBase % FlashInstance->Media.BlockSize =3D= =3D 0);=0D + ASSERT (mFlashNvStorageFtwWorkingBase % FlashInstance->Media.BlockSize = =3D=3D 0);=0D + ASSERT (mFlashNvStorageFtwSpareBase % 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 + TempAttributes =3D (=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 req= uired to=0D + EFI_FVB2_MEMORY_MAPPED | // It is memory mapped= =0D + EFI_FVB2_ERASE_POLARITY | // After erasure all bi= ts take this value=0D + EFI_FVB2_WRITE_STATUS | // Writes are currently= enabled=0D + EFI_FVB2_WRITE_ENABLED_CAP // Writes may be enable= d=0D + );=0D +=0D + FirmwareVolumeHeader->Signature =3D EFI_FVH_SIGNATURE;=0D + FirmwareVolumeHeader->Attributes =3D (EFI_FVB_ATTRIBUTES_2) TempAttribut= es;=0D +=0D + FirmwareVolumeHeader->HeaderLength =3D sizeof (EFI_FIRMWARE_VOLUME_HEADE= R) + 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 (=0D + (UINT16 *)FirmwareVolumeHeader,=0D + FirmwareVolumeHeader->HeaderLength=0D + );=0D +=0D + //=0D + // VARIABLE_STORE_HEADER=0D + //=0D + VariableStoreHeader =3D (VARIABLE_STORE_HEADER *) ((UINTN)Headers + Firm= wareVolumeHeader->HeaderLength);=0D + CopyGuid (&VariableStoreHeader->Signature, &gEfiAuthenticatedVariableGui= d);=0D + VariableStoreHeader->Size =3D mFlashNvStorageVariableSize - FirmwareVo= lumeHeader->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 FvbWrite (&FlashInstance->FvbProtocol, 0, 0, &HeadersLength, = 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 +FvbValidateFvHeader (=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 (FlashInst= ance->RegionBaseAddress,=0D + FlashInstance->StartLba,=0D + FlashInstance->Media.Block= Size=0D + );=0D + FvLength =3D FlashInstance->FvbSize;=0D +=0D +=0D + if ((FwVolHeader->Revision !=3D EFI_FVH_REVISION) ||=0D + (FwVolHeader->Signature !=3D EFI_FVH_SIGNATURE) ||=0D + (FwVolHeader->FvLength !=3D FvLength))=0D + {=0D + DEBUG ((=0D + DEBUG_ERROR,=0D + "ValidateFvHeader: No Firmware Volume header present\n"=0D + ));=0D + return EFI_NOT_FOUND;=0D + }=0D +=0D + // Check the Firmware Volume Guid=0D + if ( CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiSystemNvDataFvGuid)= =3D=3D FALSE ) {=0D + DEBUG ((=0D + DEBUG_ERROR,=0D + "ValidateFvHeader: Firmware Volume Guid non-compatible\n"=0D + ));=0D + return EFI_NOT_FOUND;=0D + }=0D +=0D + // Verify the header checksum=0D + Checksum =3D CalculateSum16 ((UINT16 *)FwVolHeader, FwVolHeader->HeaderL= ength);=0D + if (Checksum !=3D 0) {=0D + DEBUG ((=0D + DEBUG_ERROR,=0D + "ValidateFvHeader: FV checksum is invalid (Checksum:0x%X)\n",=0D + Checksum));=0D + return EFI_NOT_FOUND;=0D + }=0D +=0D + VariableStoreHeader =3D (VARIABLE_STORE_HEADER *) ((UINTN)FwVolHeader + = FwVolHeader->HeaderLength);=0D +=0D + // Check the Variable Store Guid=0D + if ( ! CompareGuid (&VariableStoreHeader->Signature, &gEfiVariableGuid) = &&=0D + ! CompareGuid (&VariableStoreHeader->Signature,=0D + &gEfiAuthenticatedVariableGuid))=0D + {=0D + DEBUG ((=0D + DEBUG_ERROR,=0D + "%a: Variable Store Guid non-compatible\n"=0D + ));=0D + return EFI_NOT_FOUND;=0D + }=0D +=0D + VariableStoreLength =3D mFlashNvStorageVariableSize - FwVolHeader->Heade= rLength;=0D + if (VariableStoreHeader->Size !=3D VariableStoreLength) {=0D + DEBUG ((=0D + DEBUG_ERROR,=0D + "ValidateFvHeader: Variable Store Length does not match\n"=0D + ));=0D + return EFI_NOT_FOUND;=0D + }=0D +=0D + return EFI_SUCCESS;=0D +}=0D +=0D +=0D +/**=0D + The FvbGetAttributes() 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 +FvbGetAttributes (=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 + 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 + // Check if it is write protected=0D + if (FlashInstance->Media.ReadOnly !=3D TRUE) {=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 FvbSetAttributes() function sets configurable firmware volume attrib= utes=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 +FvbSetAttributes (=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 FvbGetPhysicalAddress() function retrieves the base address of=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 +FvbGetPhysicalAddress (=0D + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,=0D + OUT EFI_PHYSICAL_ADDRESS *Address=0D + )=0D +{=0D + ASSERT (Address !=3D NULL);=0D +=0D + *Address =3D mFlashNvStorageVariableBase;=0D +=0D + return EFI_SUCCESS;=0D +}=0D +=0D +=0D +/**=0D + The FvbGetBlockSize() function retrieves the size of the requested=0D + block. It also returns the number of additional blocks with=0D + the identical size. The FvbGetBlockSize() 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 +FvbGetBlockSize (=0D + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,=0D + IN EFI_LBA Lba,=0D + OUT UINTN *BlockSize,=0D + OUT UINTN *NumberOfBlocks=0D + )=0D +{=0D + EFI_STATUS 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 FvbRead() function reads the requested number of bytes from the=0D + requested block and stores them in the provided buffer.=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 +FvbRead (=0D + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,=0D + IN EFI_LBA Lba,=0D + IN UINTN Offset,=0D + IN OUT UINTN *NumBytes,=0D + IN OUT UINT8 *Buffer=0D + )=0D +{=0D + 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 FvbFlashRead (=0D + FlashInstance,=0D + FlashInstance->StartLba + Lba,=0D + Offset,=0D + *NumBytes,=0D + Buffer=0D + );=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 FvbWrite() function writes the specified number of bytes from=0D + the provided buffer to the specified block and offset.=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 +FvbWrite (=0D + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,=0D + IN EFI_LBA Lba,=0D + IN UINTN Offset,=0D + IN OUT UINTN *NumBytes,=0D + IN UINT8 *Buffer=0D + )=0D +{=0D + FT_FVB_DEVICE *FlashInstance;=0D +=0D + FlashInstance =3D INSTANCE_FROM_FVB_THIS (This);=0D +=0D + return FvbFlashWrite (FlashInstance,=0D + FlashInstance->StartLba + Lba,=0D + Offset,=0D + *NumBytes,=0D + Buffer=0D + );=0D +}=0D +=0D +=0D +/**=0D + Erases and initialises a firmware volume block.=0D +=0D + The FvbEraseBlocks() function erases one or more blocks as denoted=0D + by the variable argument list.=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 +FvbEraseBlocks (=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 ((=0D + DEBUG_ERROR,=0D + "FvbEraseBlocks: ERROR - Device is in WriteDisabled state.\n"=0D + ));=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 ((=0D + DEBUG_ERROR,=0D + "FvbEraseBlocks: ERROR - Lba range goes past the last Lba.\n"=0D + ));=0D + Status =3D EFI_INVALID_PARAMETER;=0D + goto EXIT;=0D + }=0D + } while (TRUE);=0D +=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 + // 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 +/**=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 + // Declare the Non-Volatile storage as EFI_MEMORY_RUNTIME=0D + Status =3D gDS->AddMemorySpace (=0D + EfiGcdMemoryTypeMemoryMappedIo,=0D + mFlashNvStorageVariableBase,=0D + FlashInstance->FvbSize,=0D + EFI_MEMORY_UC | EFI_MEMORY_RUNTIME=0D + );=0D + ASSERT_EFI_ERROR (Status);=0D +=0D + Status =3D gDS->SetMemorySpaceAttributes (=0D + mFlashNvStorageVariableBase,=0D + 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 (mFlashNvStorageVariableBase - 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 FvbValidateFvHeader (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 ((=0D + DEBUG_ERROR,=0D + "NorFlashFvbInitialize: ERROR - The FVB Header is invalid. Installin= g a correct one for this volume.\n"=0D + ));=0D +=0D + // Erase all the NorFlash that is reserved for variable storage=0D + FvbNumLba =3D TotalFvbSize / FlashInstance->Media.BlockSize;=0D +=0D + Status =3D FvbEraseBlocks (=0D + &FlashInstance->FvbProtocol,=0D + (EFI_LBA)0,=0D + FvbNumLba,=0D + EFI_LBA_LIST_TERMINATOR=0D + );=0D + if (EFI_ERROR (Status)) {=0D + return Status;=0D + }=0D +=0D + // Install all appropriate headers=0D + Status =3D FvbInitFvAndVariableStoreHeaders (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 (&gSpiNorFlashProtocolGuid,=0D + NULL,=0D + (VOID **)&FvbDevice->SpiFlashProtocol);=0D + if (EFI_ERROR (Status)) {=0D + DEBUG ((=0D + DEBUG_ERROR,=0D + "Cannot locate NorFlash protocol.\n"=0D + ));=0D + return Status;=0D + }=0D +=0D + NorFlashDevice =3D AllocateRuntimePool (sizeof (NOR_FLASH_DEVICE_DESCRIP= TION));=0D + if (NorFlashDevice =3D=3D NULL) {=0D + DEBUG ((=0D + DEBUG_ERROR,=0D + "Cannot Allocate NorFlashDevice Pool.\n"=0D + ));=0D + return Status;=0D + }=0D +=0D + Status =3D FvbDevice->SpiFlashProtocol->GetDevices (NorFlashDevice);=0D + if (EFI_ERROR (Status)) {=0D + return Status;=0D + }=0D +=0D + Status =3D FvbDevice->SpiFlashProtocol->Initialization ();=0D + if (EFI_ERROR (Status)) {=0D + return Status;=0D + }=0D +=0D + FvbDevice->DeviceBaseAddress =3D NorFlashDevice->DeviceBaseAddress;=0D + FvbDevice->RegionBaseAddress =3D NorFlashDevice->RegionBaseAddress;=0D + FvbDevice->Size =3D NorFlashDevice->Size;=0D +=0D + FvbDevice->Media.MediaId =3D 0;=0D + FvbDevice->Media.BlockSize =3D NorFlashDevice->BlockSize;=0D + FvbDevice->Media.LastBlock =3D (FvbDevice->Size / FvbDevice->Media.Block= Size) - 1;=0D + FvbDevice->FvbSize =3D mFlashNvStorageVariableSize +=0D + mFlashNvStorageFtwWorkingSize +=0D + mFlashNvStorageFtwSpareSize;=0D +=0D + CopyGuid (&FvbDevice->DevicePath.Vendor.Guid, &NorFlashDevice->Guid);=0D +=0D + FvbDevice->ShadowBuffer =3D AllocateRuntimePool (FvbDevice->Media.BlockS= ize);=0D + if (FvbDevice->ShadowBuffer =3D=3D NULL) {=0D + return EFI_OUT_OF_RESOURCES;=0D + }=0D +=0D + Status =3D gBS->InstallMultipleProtocolInterfaces (=0D + &FvbDevice->Handle,=0D + &gEfiDevicePathProtocolGuid,=0D + &FvbDevice->DevicePath,=0D + &gEfiFirmwareVolumeBlockProtocolGuid,=0D + &FvbDevice->FvbProtocol,=0D + NULL=0D + );=0D + if (EFI_ERROR (Status)) {=0D + FreePool (FvbDevice);=0D + return Status;=0D + }=0D +=0D + Status =3D PhytNorFlashFvbInitialize (FvbDevice);=0D + if (EFI_ERROR (Status)) {=0D + DEBUG ((=0D + DEBUG_ERROR,=0D + "PhytNorFlashFvbInitialize: Fail to init NorFlash devices\n"=0D + ));=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=0D + 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 +FvbVirtualNotifyEvent (=0D + IN EFI_EVENT Event,=0D + IN VOID *Context=0D + )=0D +{=0D + // Convert SpiFlashProtocol=0D + EfiConvertPointer (0x0, (VOID **)&FvbDevice->SpiFlashProtocol->Erase);=0D + EfiConvertPointer (0x0, (VOID **)&FvbDevice->SpiFlashProtocol->Write);=0D + EfiConvertPointer (0x0, (VOID **)&FvbDevice->SpiFlashProtocol->Read);=0D + EfiConvertPointer (0x0, (VOID **)&FvbDevice->SpiFlashProtocol->GetDevice= s);=0D + EfiConvertPointer (0x0, (VOID **)&FvbDevice->SpiFlashProtocol->Initializ= ation);=0D + EfiConvertPointer (0x0, (VOID **)&FvbDevice->SpiFlashProtocol->EraseSing= leBlock);=0D + EfiConvertPointer (0x0, (VOID **)&FvbDevice->SpiFlashProtocol);=0D +=0D + EfiConvertPointer (0x0, (VOID **)&mFlashNvStorageVariableBase);=0D + EfiConvertPointer (0x0, (VOID **)&mFlashNvStorageFtwWorkingBase);=0D + EfiConvertPointer (0x0, (VOID **)&mFlashNvStorageFtwSpareBase);=0D + EfiConvertPointer (0x0, (VOID **)&FvbDevice);=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 +FvbEntryPoint (=0D + IN EFI_HANDLE ImageHandle,=0D + IN EFI_SYSTEM_TABLE *SystemTable=0D + )=0D +{=0D + EFI_STATUS Status;=0D +=0D + FvbDevice =3D AllocateRuntimeCopyPool (=0D + sizeof (FvbFlashInstanceTemplate),=0D + &FvbFlashInstanceTemplate=0D + );=0D + if (FvbDevice =3D=3D NULL) {=0D + return EFI_OUT_OF_RESOURCES;=0D + }=0D +=0D + mFlashNvStorageVariableBase =3D FixedPcdGet64 (PcdFlashNvStorageVariab= leBase64);=0D + mFlashNvStorageFtwWorkingBase =3D FixedPcdGet64 (PcdFlashNvStorageFtwWor= kingBase64);=0D + mFlashNvStorageFtwSpareBase =3D FixedPcdGet64 (PcdFlashNvStorageFtwSpa= reBase64);=0D + mFlashNvStorageVariableSize =3D FixedPcdGet32 (PcdFlashNvStorageVariab= leSize);=0D + mFlashNvStorageFtwWorkingSize =3D FixedPcdGet32 (PcdFlashNvStorageFtwWor= kingSize);=0D + mFlashNvStorageFtwSpareSize =3D FixedPcdGet32 (PcdFlashNvStorageFtwSpa= reSize);=0D +=0D + Status =3D CreateInstance ();=0D + if (EFI_ERROR (Status)) {=0D + DEBUG ((=0D + DEBUG_ERROR,=0D + "CreateInstance: Fail to create instance for NorFlash\n"=0D + ));=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 + FvbVirtualNotifyEvent,=0D + NULL,=0D + &gEfiEventVirtualAddressChangeGuid,=0D + &FvbVirtualAddrChangeEvent=0D + );=0D + ASSERT_EFI_ERROR (Status);=0D +=0D + return Status;=0D +}=0D --=20 2.25.1