[PATCH v8 3/4] Silicon/Phytium: Added fvb driver for flash


Ling Jia
 

From: Ling Jia <jialing@...>

The FlashFvbDxe provided the fvb protocol,
which requested by the flash operators.

Signed-off-by: Ling Jia <jialing@...>
---
Silicon/Phytium/PhytiumCommonPkg/PhytiumCommonPkg.dsc.inc | =
3 +-
Platform/Phytium/DurianPkg/DurianPkg.dsc | =
1 +
Platform/Phytium/DurianPkg/DurianPkg.fdf | =
2 +
Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.inf | 6=
2 +
Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.h | 11=
7 ++
Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.c | 145=
0 ++++++++++++++++++++
6 files changed, 1634 insertions(+), 1 deletion(-)

diff --git a/Silicon/Phytium/PhytiumCommonPkg/PhytiumCommonPkg.dsc.inc b/Si=
licon/Phytium/PhytiumCommonPkg/PhytiumCommonPkg.dsc.inc
index 7166212875ec..5dd5ce0390f3 100644
--- a/Silicon/Phytium/PhytiumCommonPkg/PhytiumCommonPkg.dsc.inc
+++ b/Silicon/Phytium/PhytiumCommonPkg/PhytiumCommonPkg.dsc.inc
@@ -1,7 +1,7 @@
## @file=0D
# This package provides common open source Phytium silicon modules.=0D
#=0D
-# Copyright (C) 2020, Phytium Technology Co, Ltd. All rights reserved.=0D
+# Copyright (C) 2020-2023, Phytium Technology Co., Ltd. All rights reserve=
d.=0D
#=0D
# SPDX-License-Identifier:BSD-2-Clause-Patent=0D
#=0D
@@ -23,6 +23,7 @@ [LibraryClasses.common]
=0D
AcpiLib|EmbeddedPkg/Library/AcpiLib/AcpiLib.inf=0D
AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLib=
Null.inf=0D
+ PlatformPKProtectionLib|SecurityPkg/Library/PlatformPKProtectionLibVarPo=
licy/PlatformPKProtectionLibVarPolicy.inf=0D
=0D
BaseLib|MdePkg/Library/BaseLib/BaseLib.inf=0D
BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf=0D
diff --git a/Platform/Phytium/DurianPkg/DurianPkg.dsc b/Platform/Phytium/Du=
rianPkg/DurianPkg.dsc
index 7a390fbe1383..b541e407ac8b 100644
--- a/Platform/Phytium/DurianPkg/DurianPkg.dsc
+++ b/Platform/Phytium/DurianPkg/DurianPkg.dsc
@@ -267,6 +267,7 @@ [Components.common]
# 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 560be98199d2..70b7e99270c2 100644
--- a/Platform/Phytium/DurianPkg/DurianPkg.fdf
+++ b/Platform/Phytium/DurianPkg/DurianPkg.fdf
@@ -88,6 +88,7 @@ [FV.FvMain]
INF MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf=0D
INF Silicon/Phytium/FT2000-4Pkg/Drivers/SpiDxe/SpiDxe.inf=0D
INF Silicon/Phytium/FT2000-4Pkg/Drivers/SpiNorFlashDxe/SpiNorFlashDxe.=
inf=0D
+ INF Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.i=
nf=0D
}=0D
=0D
INF MdeModulePkg/Core/Dxe/DxeMain.inf=0D
@@ -104,6 +105,7 @@ [FV.FvMain]
=0D
INF Silicon/Phytium/FT2000-4Pkg/Drivers/SpiDxe/SpiDxe.inf=0D
INF Silicon/Phytium/FT2000-4Pkg/Drivers/SpiNorFlashDxe/SpiNorFlashDxe.in=
f=0D
+ INF Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.inf=
=0D
=0D
INF MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf=0D
INF MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRu=
ntimeDxe.inf=0D
diff --git a/Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbD=
xe.inf b/Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.i=
nf
new file mode 100755
index 000000000000..96df8de51115
--- /dev/null
+++ b/Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.inf
@@ -0,0 +1,62 @@
+## @file=0D
+# Phytium NorFlash Fvb Drivers.=0D
+#=0D
+# Copyright (c) 2011 - 2014, ARM Ltd. All rights reserved.<BR>=0D
+# Copyright (C) 2023, Phytium Technology Co., Ltd. All rights reserved.<B=
R>=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
+ UefiRuntimeServicesTableLib=0D
+=0D
+[Guids]=0D
+ gEfiAuthenticatedVariableGuid=0D
+ gEfiEventVirtualAddressChangeGuid=0D
+ gEfiSystemNvDataFvGuid=0D
+ gEfiVariableGuid=0D
+=0D
+[Protocols]=0D
+ gEfiDevicePathProtocolGuid=0D
+ gEfiFirmwareVolumeBlockProtocolGuid=0D
+ gSpiNorFlashProtocolGuid=0D
+=0D
+[FixedPcd]=0D
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize=0D
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize=0D
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize=0D
+=0D
+[Pcd]=0D
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64=0D
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase64=0D
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase64=0D
+=0D
+[Depex]=0D
+ TRUE=0D
diff --git a/Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbD=
xe.h b/Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.h
new file mode 100755
index 000000000000..216e7bf69944
--- /dev/null
+++ b/Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.h
@@ -0,0 +1,117 @@
+/** @file=0D
+ Phytium NorFlash Fvb Drivers Header.=0D
+=0D
+ Copyright (C) 2023, Phytium Technology Co., Ltd. All rights reserved.<BR=
=0D
+=0D
+ SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+=0D
+**/=0D
+#ifndef FLASH_FVB_DXE_H_=0D
+#define FLASH_FVB_DXE_H_=0D
+=0D
+#include <Guid/VariableFormat.h>=0D
+=0D
+#include <Library/BaseLib.h>=0D
+#include <Library/BaseMemoryLib.h>=0D
+#include <Library/DebugLib.h>=0D
+#include <Library/DxeServicesTableLib.h>=0D
+#include <Library/HobLib.h>=0D
+#include <Library/MemoryAllocationLib.h>=0D
+#include <Library/UefiBootServicesTableLib.h>=0D
+#include <Library/UefiRuntimeLib.h>=0D
+=0D
+#include <Protocol/BlockIo.h>=0D
+#include <Protocol/FirmwareVolumeBlock.h>=0D
+=0D
+#include <Protocol/SpiProtocol.h>=0D
+#include <Protocol/SpiNorFlashProtocol.h>=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
+ UINTN FvbSize;=0D
+ VOID* TempBuffer;=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 // FLASH_FVB_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 100755
index 000000000000..0c6efa5d8368
--- /dev/null
+++ b/Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.c
@@ -0,0 +1,1450 @@
+/** @file=0D
+ Phytium NorFlash Fvb Drivers.=0D
+=0D
+ Copyright (c) 2011 - 2014, ARM Ltd. All rights reserved.<BR>=0D
+ Copyright (C) 2023, Phytium Technology Co., Ltd. All rights reserved.<BR=
=0D
+=0D
+ SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+=0D
+**/=0D
+=0D
+#include "FlashFvbDxe.h"=0D
+=0D
+STATIC EFI_EVENT mFvbVirtualAddrChangeEvent;=0D
+STATIC FT_FVB_DEVICE *mFvbDevice;=0D
+UINTN mFlashNvStorageVariableBase;=0D
+UINTN mFlashNvStorageFtwWorkingBase;=0D
+UINTN mFlashNvStorageFtwSpareBase;=0D
+UINT32 mFlashNvStorageVariableSize;=0D
+UINT32 mFlashNvStorageFtwWorkingSize;=0D
+UINT32 mFlashNvStorageFtwSpareSize;=0D
+=0D
+STATIC CONST FT_FVB_DEVICE mFvbFlashInstanceTemplate =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
+ 0, // Fvb Size ... NEED TO BE FILLED=0D
+ NULL // TempBuffer ... NEED TO BE FILLED=0D
+};=0D
+=0D
+=0D
+/**=0D
+ Erased 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 ( BlockAd=
dress);=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
+ // The buffer must be valid=0D
+ if (Buffer =3D=3D NULL) {=0D
+ return EFI_INVALID_PARAMETER;=0D
+ }=0D
+=0D
+ if (BufferSizeInBytes =3D=3D 0) {=0D
+ return EFI_SUCCESS;=0D
+ }=0D
+=0D
+ if (((Lba * FlashInstance->Media.BlockSize) + Offset + BufferSizeInBytes=
) > FlashInstance->Size) {=0D
+ DEBUG ((DEBUG_ERROR, "FvbFlashRead: ERROR - Read will exceed device si=
ze.\n"));=0D
+ return EFI_INVALID_PARAMETER;=0D
+ }=0D
+=0D
+ Address =3D GET_DATA_OFFSET (=0D
+ FlashInstance->RegionBaseAddress,=0D
+ Lba,=0D
+ FlashInstance->Media.BlockSize=0D
+ ) + Offset;=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 + BufferSizeInBytes <=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
+ UINTN BlockAddress;=0D
+ UINTN BlockSize;=0D
+ UINTN BytesToWrite;=0D
+ UINTN CurOffset;=0D
+ BOOLEAN DoErase;=0D
+ UINT32 Mask;=0D
+ EFI_STATUS Status;=0D
+ UINT32 Tmp;=0D
+ UINT32 TmpBuf;=0D
+ UINTN WordAddr;=0D
+ UINT32 WordToWrite;=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 + Buff=
erSizeInBytes =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: BufferSizeInBytes =3D=
=3D 0\n"=0D
+ ));=0D
+ return EFI_BAD_BUFFER_SIZE;=0D
+ }=0D
+ // Pick 128bytes as a good start for word operations as opposed to erasi=
ng the=0D
+ // block and writing the data regardless if an erase is really needed.=0D
+ // It looks like most individual NV variable writes are smaller than 128=
bytes.=0D
+ if (BufferSizeInBytes <=3D 128) {=0D
+ // Check to see if we need to erase before programming the data into N=
OR.=0D
+ // If the destination bits are only changing from 1s to 0s we can just=
write.=0D
+ // After a block is erased all bits in the block is set to 1.=0D
+ // If any byte requires us to erase we just give up and rewrite all of=
it.=0D
+ DoErase =3D FALSE;=0D
+ BytesToWrite =3D BufferSizeInBytes;=0D
+ CurOffset =3D Offset;=0D
+=0D
+ while (BytesToWrite > 0) {=0D
+ // Read full word from NOR, splice as required. A word is the smalle=
st=0D
+ // unit we can write.=0D
+ Status =3D FvbFlashRead (FlashInstance, Lba, CurOffset & ~(0x3), siz=
eof (Tmp), &Tmp);=0D
+ if (EFI_ERROR (Status)) {=0D
+ return EFI_DEVICE_ERROR;=0D
+ }=0D
+=0D
+ // Physical address of word in NOR to write.=0D
+ WordAddr =3D (CurOffset & ~(0x3)) + GET_DATA_OFFSET (=0D
+ FlashInstance->RegionBaseAddress=
,=0D
+ Lba,=0D
+ BlockSize=0D
+ );=0D
+ // The word of data that is to be written.=0D
+ TmpBuf =3D *((UINT32 *)(Buffer + (BufferSizeInBytes - BytesToWrite))=
);=0D
+=0D
+ // First do word aligned chunks.=0D
+ if ((CurOffset & 0x3) =3D=3D 0) {=0D
+ if (BytesToWrite >=3D 4) {=0D
+ // Is the destination still in 'erased' state?=0D
+ if (~Tmp !=3D 0) {=0D
+ // Check to see if we are only changing bits to zero.=0D
+ if ((Tmp ^ TmpBuf) & TmpBuf) {=0D
+ DoErase =3D TRUE;=0D
+ break;=0D
+ }=0D
+ }=0D
+=0D
+ // Write this word to NOR=0D
+ WordToWrite =3D TmpBuf;=0D
+ CurOffset +=3D sizeof (TmpBuf);=0D
+ BytesToWrite -=3D sizeof (TmpBuf);=0D
+ } else {=0D
+ // BytesToWrite < 4. Do small writes and left-overs=0D
+ Mask =3D ~((~0) << (BytesToWrite * 8));=0D
+ // Mask out the bytes we want.=0D
+ TmpBuf &=3D Mask;=0D
+ // Is the destination still in 'erased' state?=0D
+ if ((Tmp & Mask) !=3D Mask) {=0D
+ // Check to see if we are only changing bits to zero.=0D
+ if ((Tmp ^ TmpBuf) & TmpBuf) {=0D
+ DoErase =3D TRUE;=0D
+ break;=0D
+ }=0D
+ }=0D
+=0D
+ // Merge old and new data. Write merged word to NOR=0D
+ WordToWrite =3D (Tmp & ~Mask) | TmpBuf;=0D
+ CurOffset +=3D BytesToWrite;=0D
+ BytesToWrite =3D 0;=0D
+ }=0D
+ } else {=0D
+ // Do multiple words, but starting unaligned.=0D
+ if (BytesToWrite > (4 - (CurOffset & 0x3))) {=0D
+ Mask =3D ((~0) << ((CurOffset & 0x3) * 8));=0D
+ // Mask out the bytes we want.=0D
+ TmpBuf &=3D Mask;=0D
+ // Is the destination still in 'erased' state?=0D
+ if ((Tmp & Mask) !=3D Mask) {=0D
+ // Check to see if we are only changing bits to zero.=0D
+ if ((Tmp ^ TmpBuf) & TmpBuf) {=0D
+ DoErase =3D TRUE;=0D
+ break;=0D
+ }=0D
+ }=0D
+=0D
+ // Merge old and new data. Write merged word to NOR=0D
+ WordToWrite =3D (Tmp & ~Mask) | TmpBuf;=0D
+ BytesToWrite -=3D (4 - (CurOffset & 0x3));=0D
+ CurOffset +=3D (4 - (CurOffset & 0x3));=0D
+ } else {=0D
+ // Unaligned and fits in one word.=0D
+ Mask =3D (~((~0) << (BytesToWrite * 8))) << ((CurOffset & 0x3) *=
8);=0D
+ // Mask out the bytes we want.=0D
+ TmpBuf =3D (TmpBuf << ((CurOffset & 0x3) * 8)) & Mask;=0D
+ // Is the destination still in 'erased' state?=0D
+ if ((Tmp & Mask) !=3D Mask) {=0D
+ // Check to see if we are only changing bits to zero.=0D
+ if ((Tmp ^ TmpBuf) & TmpBuf) {=0D
+ DoErase =3D TRUE;=0D
+ break;=0D
+ }=0D
+ }=0D
+=0D
+ // Merge old and new data. Write merged word to NOR=0D
+ WordToWrite =3D (Tmp & ~Mask) | TmpBuf;=0D
+ CurOffset +=3D BytesToWrite;=0D
+ BytesToWrite =3D 0;=0D
+ }=0D
+ }=0D
+=0D
+ //=0D
+ // Write the word to NOR.=0D
+ //=0D
+ Status =3D FlashInstance->SpiFlashProtocol->Write (=0D
+ WordAddr,=0D
+ &WordToWrite,=0D
+ 4=0D
+ );=0D
+ if (EFI_ERROR (Status)) {=0D
+ return EFI_DEVICE_ERROR;=0D
+ }=0D
+ }=0D
+=0D
+ // Exit if we got here and could write all the data. Otherwise do the=
=0D
+ // Erase-Write cycle.=0D
+ if (!DoErase) {=0D
+ return EFI_SUCCESS;=0D
+ }=0D
+ }=0D
+=0D
+ if (FlashInstance->TempBuffer =3D=3D NULL) {=0D
+ DEBUG ((DEBUG_ERROR, "FvbWriteBlock: ERROR - Buffer not ready\n"));=0D
+ return EFI_DEVICE_ERROR;=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
+ // Read NOR Flash data into shadow buffer=0D
+ Status =3D FlashInstance->SpiFlashProtocol->Read (=0D
+ BlockAddress,=0D
+ FlashInstance->TempBuffer,=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->TempBuffer + Offset),=0D
+ Buffer,=0D
+ BufferSizeInBytes=0D
+ );=0D
+ Status =3D FlashInstance->SpiFlashProtocol->EraseSingleBlock (BlockAddre=
ss);=0D
+=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 (=0D
+ BlockAddress,=0D
+ FlashInstance->TempBuffer,=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
+ EFI_FVB2_ALIGNMENT_4;=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 RuntimeMmioRegionSize;=0D
+=0D
+ RuntimeMmioRegionSize =3D FlashInstance->Size;=0D
+=0D
+ // Declare the Non-Volatile storage as EFI_MEMORY_RUNTIME=0D
+ Status =3D gDS->AddMemorySpace (=0D
+ EfiGcdMemoryTypeMemoryMappedIo,=0D
+ FlashInstance->RegionBaseAddress,=0D
+ RuntimeMmioRegionSize,=0D
+ EFI_MEMORY_UC | EFI_MEMORY_RUNTIME=0D
+ );=0D
+ ASSERT_EFI_ERROR (Status);=0D
+=0D
+ Status =3D gDS->SetMemorySpaceAttributes (=0D
+ FlashInstance->RegionBaseAddress,=0D
+ RuntimeMmioRegionSize,=0D
+ EFI_MEMORY_UC | EFI_MEMORY_RUNTIME=0D
+ );=0D
+ ASSERT_EFI_ERROR (Status);=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 FlashInstance->FvbSize / 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
+ mFvbDevice =3D AllocateRuntimeCopyPool (sizeof (mFvbFlashInstanceTemplat=
e), &mFvbFlashInstanceTemplate);=0D
+ if (mFvbDevice =3D=3D NULL) {=0D
+ return EFI_OUT_OF_RESOURCES;=0D
+=0D
+ }=0D
+ // Locate flash protocols=0D
+ Status =3D gBS->LocateProtocol (&gSpiNorFlashProtocolGuid,=0D
+ NULL,=0D
+ (VOID **)&mFvbDevice->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 mFvbDevice->SpiFlashProtocol->GetDevices (NorFlashDevice);=0D
+ if (EFI_ERROR (Status)) {=0D
+ return Status;=0D
+ }=0D
+=0D
+ Status =3D mFvbDevice->SpiFlashProtocol->Initialization ();=0D
+ if (EFI_ERROR (Status)) {=0D
+ return Status;=0D
+ }=0D
+=0D
+ mFvbDevice->DeviceBaseAddress =3D NorFlashDevice->DeviceBaseAddress;=0D
+ mFvbDevice->RegionBaseAddress =3D NorFlashDevice->RegionBaseAddress;=0D
+ mFvbDevice->Size =3D NorFlashDevice->Size;=0D
+=0D
+ mFvbDevice->Media.MediaId =3D 0;=0D
+ mFvbDevice->Media.BlockSize =3D NorFlashDevice->BlockSize;=0D
+ mFvbDevice->Media.LastBlock =3D (mFvbDevice->Size / mFvbDevice->Media.Bl=
ockSize) - 1;=0D
+ mFvbDevice->FvbSize =3D mFlashNvStorageVariableSize +=0D
+ mFlashNvStorageFtwWorkingSize +=0D
+ mFlashNvStorageFtwSpareSize;=0D
+ DEBUG((DEBUG_INFO, "mFvbDevice->fvbSize=3D%x\n", mFvbDevice->FvbSize));=
=0D
+ CopyGuid (&mFvbDevice->DevicePath.Vendor.Guid, &NorFlashDevice->Guid);=0D
+=0D
+ mFvbDevice->TempBuffer =3D AllocateRuntimePool (mFvbDevice->Media.BlockS=
ize);=0D
+ if (mFvbDevice->TempBuffer =3D=3D NULL) {=0D
+ return EFI_OUT_OF_RESOURCES;=0D
+ }=0D
+=0D
+ Status =3D PhytNorFlashFvbInitialize (mFvbDevice);=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
+ Status =3D gBS->InstallMultipleProtocolInterfaces (=0D
+ &mFvbDevice->Handle,=0D
+ &gEfiDevicePathProtocolGuid,=0D
+ &mFvbDevice->DevicePath,=0D
+ &gEfiFirmwareVolumeBlockProtocolGuid,=0D
+ &mFvbDevice->FvbProtocol,=0D
+ NULL=0D
+ );=0D
+ if (EFI_ERROR (Status)) {=0D
+ FreePool (mFvbDevice);=0D
+ FreePool (NorFlashDevice);=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
+ VOID *Pointer;=0D
+=0D
+ EfiConvertPointer (0x0, (VOID **)&mFlashNvStorageVariableBase);=0D
+ EfiConvertPointer (0x0, (VOID **)&mFlashNvStorageFtwWorkingBase);=0D
+ EfiConvertPointer (0x0, (VOID **)&mFlashNvStorageFtwSpareBase);=0D
+ if (!mFvbDevice->DeviceBaseAddress) {=0D
+ mFvbDevice->DeviceBaseAddress |=3D 0x1;=0D
+ }=0D
+=0D
+ if (!mFvbDevice->RegionBaseAddress) {=0D
+ mFvbDevice->RegionBaseAddress |=3D 0x1;=0D
+ }=0D
+ EfiConvertPointer (0x0, (VOID **)&mFvbDevice->DeviceBaseAddress);=0D
+ EfiConvertPointer (0x0, (VOID **)&mFvbDevice->RegionBaseAddress);=0D
+=0D
+ mFvbDevice->DeviceBaseAddress &=3D ~(EFI_PHYSICAL_ADDRESS)0x1;=0D
+ mFvbDevice->RegionBaseAddress &=3D ~(EFI_PHYSICAL_ADDRESS)0x1;=0D
+=0D
+ // Convert SpiFlashProtocol=0D
+ EfiConvertPointer (0x0, (VOID **)&(mFvbDevice->SpiFlashProtocol->Erase))=
;=0D
+ EfiConvertPointer (0x0, (VOID **)&(mFvbDevice->SpiFlashProtocol->Write))=
;=0D
+ EfiConvertPointer (0x0, (VOID **)&(mFvbDevice->SpiFlashProtocol->Read));=
=0D
+ EfiConvertPointer (0x0, (VOID **)&(mFvbDevice->SpiFlashProtocol->GetDevi=
ces));=0D
+ EfiConvertPointer (0x0, (VOID **)&(mFvbDevice->SpiFlashProtocol));=0D
+=0D
+ EfiConvertPointer (0x0, (VOID **)&(mFvbDevice->FvbProtocol.EraseBlocks))=
;=0D
+ EfiConvertPointer (0x0, (VOID **)&(mFvbDevice->FvbProtocol.GetAttributes=
));=0D
+ EfiConvertPointer (0x0, (VOID **)&(mFvbDevice->FvbProtocol.GetBlockSize)=
);=0D
+=0D
+ Pointer =3D (VOID *)(UINTN)mFvbDevice->FvbProtocol.GetPhysicalAddress;=0D
+ EfiConvertPointer (0x0, &Pointer);=0D
+ mFvbDevice->FvbProtocol.GetPhysicalAddress =3D (EFI_FVB_GET_PHYSICAL_ADD=
RESS)(UINTN)Pointer;=0D
+ EfiConvertPointer (0x0, (VOID **)&(mFvbDevice->FvbProtocol.Read));=0D
+ EfiConvertPointer (0x0, (VOID **)&(mFvbDevice->FvbProtocol.SetAttributes=
));=0D
+ EfiConvertPointer (0x0, (VOID **)&(mFvbDevice->FvbProtocol.Write));=0D
+ EfiConvertPointer (0x0, (VOID **)&(mFvbDevice->FvbProtocol));=0D
+=0D
+ if (mFvbDevice->TempBuffer !=3D NULL) {=0D
+ EfiConvertPointer (0x0, (VOID **)&(mFvbDevice->TempBuffer));=0D
+ }=0D
+ EfiConvertPointer (0x0, (VOID **)&(mFvbDevice));=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
+ 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
+ // 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
+ &mFvbVirtualAddrChangeEvent=0D
+ );=0D
+ ASSERT_EFI_ERROR (Status);=0D
+=0D
+ return Status;=0D
+}=0D
--=20
2.25.1