From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-wm1-f45.google.com (mail-wm1-f45.google.com [209.85.128.45]) by mx.groups.io with SMTP id smtpd.web10.10955.1612985637050461357 for ; Wed, 10 Feb 2021 11:33:57 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@nuviainc-com.20150623.gappssmtp.com header.s=20150623 header.b=tSI6kZDj; spf=pass (domain: nuviainc.com, ip: 209.85.128.45, mailfrom: leif@nuviainc.com) Received: by mail-wm1-f45.google.com with SMTP id o24so2896140wmh.5 for ; Wed, 10 Feb 2021 11:33:56 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nuviainc-com.20150623.gappssmtp.com; s=20150623; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:in-reply-to:user-agent; bh=Pwtt4NTlFBpMxWOTcNKxDa33HAl/CCmMwAJ65SA0EiM=; b=tSI6kZDjoIlAO285OEIG0SEmI4MSRQ28phCh9O61qPradHBDqwJWwmNPhLx0yMViMV 43IpjnsbkyJeDsoXKHsgBbAVEEkg5Mpny56uJERJeP6HfnkQbYFcYdsadNGfgFoe6R1X ceKGPNHy2E3PdQIC5MwHuTAe0F0W6B3fln0muXeRMAVWdWv495wH3Zhambks9c4pAqM+ N4axrEI3s+WKL6x9h8TXlWrQIdlV1PiuUEuCDDHvp4i8i6ADparzcrBUvJwEVkseAhiZ 5rsHQRZfK2IjxYN8bno+crxnb8YMuPRS8hqixl9LkxrPAyBZ/hvhPlu9Ct9TjKwNadWr FPsg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=Pwtt4NTlFBpMxWOTcNKxDa33HAl/CCmMwAJ65SA0EiM=; b=DPr7CqeBqLKThdgHUIXRYV6Wn20BAtVPfLysaixJEvLIceH0oY4gCOfZWa0A2lwtKX /3uSG14uuntRW8mtCM5RXkavvrQLf0b7Qf05wDPpsO0jk3FI4GfUMrIFzi22Uja1/JMA dEWB9Q89RGiD1+KTxEDgUN6l06Cuc3ZGCEjggZQ7as/CYLfvqZqvyRe3AILdpMmPjR3M V84406dCtZsi1K50QuLs2zDDEVyWhaQs8qctP+fWbnylwOX+JJ9Ez8En+mwcud+6oYoB 05J/5CrzbBMzCnhYDwAEcjjR9JVLiQiiyESMStRdKC09J5R53Mj78AezGCIV4R8tRviH qgww== X-Gm-Message-State: AOAM532M72elXhuqafFVWOLyhEF4EiUAfTL82YbTxOfg2CkM6J6MWATp 6LKv54ZtX/Ed/JFTa+4RrUp3dgozihsCaw== X-Google-Smtp-Source: ABdhPJwj4L3bU+lnX0rrrHulN2r0Rgli70bUFIydJ+eKwmXKwR0vJ1h13TWzIQG6/6cNvx108ZfLww== X-Received: by 2002:a1c:1c9:: with SMTP id 192mr536615wmb.150.1612985635005; Wed, 10 Feb 2021 11:33:55 -0800 (PST) Return-Path: Received: from vanye (cpc1-cmbg19-2-0-cust915.5-4.cable.virginm.net. [82.27.183.148]) by smtp.gmail.com with ESMTPSA id o83sm4023890wme.37.2021.02.10.11.33.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 10 Feb 2021 11:33:54 -0800 (PST) Date: Wed, 10 Feb 2021 19:33:52 +0000 From: "Leif Lindholm" To: Ling Jia Cc: devel@edk2.groups.io Subject: Re: [PATCH v1 08/10] Silicon/Phytium: Added fvb driver for norflash Message-ID: <20210210193352.GT1664@vanye> References: <20210205100630.46848-1-jialing@phytium.com.cn> <20210205100630.46848-20-jialing@phytium.com.cn> MIME-Version: 1.0 In-Reply-To: <20210205100630.46848-20-jialing@phytium.com.cn> User-Agent: Mutt/1.10.1 (2018-07-13) Content-Type: text/plain; charset=us-ascii Content-Disposition: inline On Fri, Feb 05, 2021 at 18:06:28 +0800, Ling Jia wrote: > The FlashFvbDxe provided the fvb protocol, > which requested by the flash operators. > > Signed-off-by: Ling Jia > --- > Platform/Phytium/DurianPkg/DurianPkg.dsc | 1 + > Platform/Phytium/DurianPkg/DurianPkg.fdf | 1 + > Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.inf | 61 + > Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.h | 104 ++ > Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.c | 1196 ++++++++++++++++++++ > 5 files changed, 1363 insertions(+) > > diff --git a/Platform/Phytium/DurianPkg/DurianPkg.dsc b/Platform/Phytium/DurianPkg/DurianPkg.dsc > index 884e01643498..48fe1b4fd4ad 100644 > --- a/Platform/Phytium/DurianPkg/DurianPkg.dsc > +++ b/Platform/Phytium/DurianPkg/DurianPkg.dsc > @@ -233,6 +233,7 @@ [Components.common] > # NOR Flash driver > # > Silicon/Phytium/FT2000-4Pkg/Drivers/SpiNorFlashDxe/SpiNorFlashDxe.inf > + Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.inf > > # > # Usb Support > diff --git a/Platform/Phytium/DurianPkg/DurianPkg.fdf b/Platform/Phytium/DurianPkg/DurianPkg.fdf > index 76b02417344d..863f4fb831c2 100644 > --- a/Platform/Phytium/DurianPkg/DurianPkg.fdf > +++ b/Platform/Phytium/DurianPkg/DurianPkg.fdf > @@ -103,6 +103,7 @@ [FV.FvMain] > > INF ArmPkg/Drivers/ArmGic/ArmGicDxe.inf > INF ArmPkg/Drivers/CpuDxe/CpuDxe.inf > + INF Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.inf > INF ArmPkg/Drivers/TimerDxe/TimerDxe.inf > INF ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdogDxe.inf > > diff --git a/Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.inf b/Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.inf > new file mode 100644 > index 000000000000..f818c8944bcb > --- /dev/null > +++ b/Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.inf > @@ -0,0 +1,61 @@ > +#/** @file > +# Phytium NorFlash Fvb Drivers. > +# > +# Copyright (c) 2011 - 2014, ARM Ltd. All rights reserved.
> +# Copyright (C) 2020, Phytium Technology Co,Ltd. All rights reserved.
> +# > +# SPDX-License-Identifier: BSD-2-Clause-Patent > +# > +#**/ > + > +[Defines] > + INF_VERSION = 0x0001001b > + BASE_NAME = FlashFvbDxe > + FILE_GUID = b8923820-3e7c-11eb-b12c-17525e90ecc8 > + MODULE_TYPE = DXE_RUNTIME_DRIVER > + VERSION_STRING = 0.1 > + ENTRY_POINT = FvbEntryPoint > + > +[Sources] > + FlashFvbDxe.c > + FlashFvbDxe.h > + > +[Packages] > + EmbeddedPkg/EmbeddedPkg.dec > + MdePkg/MdePkg.dec > + MdeModulePkg/MdeModulePkg.dec > + Silicon/Phytium/PhytiumCommonPkg/PhytiumCommonPkg.dec > + > +[LibraryClasses] > + BaseLib > + DebugLib > + DxeServicesTableLib > + HobLib > + MemoryAllocationLib > + UefiBootServicesTableLib > + UefiRuntimeLib > + UefiDriverEntryPoint > + > +[Guids] > + gEfiSystemNvDataFvGuid > + gEfiVariableGuid > + gEfiEventVirtualAddressChangeGuid > + gEfiAuthenticatedVariableGuid > + > +[Protocols] > + gEfiDevicePathProtocolGuid > + gEfiFirmwareVolumeBlockProtocolGuid > + gSpiNorFlashProtocolGuid > + > +[Pcd.common] > + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64 > + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize > + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase64 > + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize > + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase64 > + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize > + gPhytiumPlatformTokenSpaceGuid.PcdSpiFlashBase > + gPhytiumPlatformTokenSpaceGuid.PcdSpiFlashSize > + > +[Depex] > + gSpiNorFlashProtocolGuid > diff --git a/Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.h b/Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.h > new file mode 100644 > index 000000000000..36ce1e87acce > --- /dev/null > +++ b/Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.h > @@ -0,0 +1,104 @@ > +/** @file > + Phytium NorFlash Fvb Drivers Header. > + > + Copyright (C) 2020, Phytium Technology Co Ltd. All rights reserved.
> + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > +#ifndef FVB_FLASH_DXE_H_ > +#define FVB_FLASH_DXE_H_ > + > +#include > +#include > +#include > + > +#define GET_DATA_OFFSET(BaseAddr, Lba, LbaSize) ((BaseAddr) + (UINTN)((Lba) * (LbaSize))) > +#define FVB_FLASH_SIGNATURE SIGNATURE_32('S', 'N', 'O', 'R') > +#define INSTANCE_FROM_FVB_THIS(a) CR(a, FT_FVB_DEVICE, FvbProtocol, FVB_FLASH_SIGNATURE) > + > +typedef struct _FT_FVB_DEVICE FT_FVB_DEVICE; > + > +#define NOR_FLASH_ERASE_RETRY 10 > + > +typedef struct { > + VENDOR_DEVICE_PATH Vendor; > + EFI_DEVICE_PATH_PROTOCOL End; > + } FT_FVB_DEVICE_PATH; > + > +struct _FT_FVB_DEVICE { > + UINT32 Signature; > + EFI_HANDLE Handle; > + > + UINTN DeviceBaseAddress; > + UINTN RegionBaseAddress; > + UINTN Size; > + EFI_LBA StartLba; > + EFI_BLOCK_IO_MEDIA Media; > + > + EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL FvbProtocol; > + > + FT_FVB_DEVICE_PATH DevicePath; > + EFI_NORFLASH_DRV_PROTOCOL *SpiFlashProtocol; > + VOID *ShadowBuffer; > + UINTN FvbSize; > + }; > + > +EFI_STATUS > +EFIAPI > +FvbGetAttributes( > + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL* This, > + OUT EFI_FVB_ATTRIBUTES_2* Attributes > + ); > + > +EFI_STATUS > +EFIAPI > +FvbSetAttributes( > + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL* This, > + IN OUT EFI_FVB_ATTRIBUTES_2* Attributes > + ); > + > +EFI_STATUS > +EFIAPI > +FvbGetPhysicalAddress( > + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL* This, > + OUT EFI_PHYSICAL_ADDRESS* Address > + ); > + > +EFI_STATUS > +EFIAPI > +FvbGetBlockSize( > + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL* This, > + IN EFI_LBA Lba, > + OUT UINTN* BlockSize, > + OUT UINTN* NumberOfBlocks > + ); > + > +EFI_STATUS > +EFIAPI > +FvbRead( > + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL* This, > + IN EFI_LBA Lba, > + IN UINTN Offset, > + IN OUT UINTN* NumBytes, > + IN OUT UINT8* Buffer > + ); > + > +EFI_STATUS > +EFIAPI > +FvbWrite( > + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL* This, > + IN EFI_LBA Lba, > + IN UINTN Offset, > + IN OUT UINTN* NumBytes, > + IN UINT8* Buffer > + ); > + > +EFI_STATUS > +EFIAPI > +FvbEraseBlocks( > + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL* This, > + ... > + ); > + > +#endif // FVB_FLASH_DXE_H_ > diff --git a/Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.c b/Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.c > new file mode 100644 > index 000000000000..e6777a136707 > --- /dev/null > +++ b/Silicon/Phytium/PhytiumCommonPkg/Drivers/FlashFvbDxe/FlashFvbDxe.c > @@ -0,0 +1,1196 @@ > +/** @file > + Phytium NorFlash Fvb Drivers. > + > + Copyright (c) 2011 - 2014, ARM Ltd. All rights reserved.
> + Copyright (C) 2020, Phytium Technology Co Ltd. All rights reserved.
> + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include "FlashFvbDxe.h" > + > +STATIC EFI_EVENT FvbVirtualAddrChangeEvent; > +STATIC FT_FVB_DEVICE *FvbDevice; > +STATIC UINTN mFlashNvStorageVariableBase; > + > +STATIC FT_FVB_DEVICE FvbFlashInstanceTemplate = { > + FVB_FLASH_SIGNATURE, // Signature > + NULL, // Handle ... NEED TO BE FILLED > + 0, // DeviceBaseAddress ... NEED TO BE FILLED > + 0, // RegionBaseAddress ... NEED TO BE FILLED > + 0, // Size ... NEED TO BE FILLED > + 0, // StartLba > + { > + 0, // MediaId ... NEED TO BE FILLED > + FALSE, // RemovableMedia > + TRUE, // MediaPresent > + FALSE, // LogicalPartition > + FALSE, // ReadOnly > + FALSE, // WriteCaching; > + 0, // BlockSize ... NEED TO BE FILLED > + 4, // IoAlign > + 0, // LastBlock ... NEED TO BE FILLED > + 0, // LowestAlignedLba > + 1, // LogicalBlocksPerPhysicalBlock > + }, //Media; > + { > + FvbGetAttributes, // GetAttributes > + FvbSetAttributes, // SetAttributes > + FvbGetPhysicalAddress, // GetPhysicalAddress > + FvbGetBlockSize, // GetBlockSize > + FvbRead, // Read > + FvbWrite, // Write > + FvbEraseBlocks, // EraseBlocks > + NULL, // ParentHandle > + }, // FvbProtoccol; > + > + { > + { > + { > + HARDWARE_DEVICE_PATH, > + HW_VENDOR_DP, > + { > + (UINT8) sizeof (VENDOR_DEVICE_PATH), > + (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) > + } > + }, > + { > + 0x0, 0x0, 0x0, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } > + }, // GUID ... NEED TO BE FILLED > + }, > + { > + END_DEVICE_PATH_TYPE, > + END_ENTIRE_DEVICE_PATH_SUBTYPE, > + { > + sizeof (EFI_DEVICE_PATH_PROTOCOL), > + 0 > + } > + } > + }, // DevicePath > + > + NULL, // SpiFlashProtocol ... NEED TO BE FILLED > + NULL, // ShadowBuffer ... NEED TO BE FILLED > + 0 // Fvb Size > +}; > + > + > +/** > + Erases a single block of flash. > + > + @param[in] FlashInstance The poiter of the fvb device sturct. > + > + @param[in] BlockAddress Physical address of Lba to be erased. > + > + @retval EFI_SUCCESS The erase single block request successfully completed. > + > +**/ > +STATIC > +EFI_STATUS > +FvbFlashEraseSingleBlock ( > + IN FT_FVB_DEVICE *FlashInstance, > + IN UINTN BlockAddress > + ) > +{ > + EFI_STATUS Status; > + UINTN Index; > + EFI_TPL OriginalTPL; > + > + if (!EfiAtRuntime ()) { > + OriginalTPL = gBS->RaiseTPL (TPL_HIGH_LEVEL); > + } else { > + OriginalTPL = TPL_HIGH_LEVEL; > + } > + > + Index = 0; > + > + do { > + Status = FlashInstance->SpiFlashProtocol->EraseSingleBlock(BlockAddress); > + Index++; > + } while ((Index < NOR_FLASH_ERASE_RETRY) && (Status == EFI_WRITE_PROTECTED)); > + > + if (Index == NOR_FLASH_ERASE_RETRY) { > + DEBUG ((DEBUG_ERROR, "EraseSingleBlock(BlockAddress=0x%08x: Block\ > + Locked Error (try to erase %d times)\n", BlockAddress, Index)); Please don't break the format string with \. just move it to a separate line: DEBUG ((DEBUG_ERROR, "EraseSingleBlock(BlockAddress=0x%08x: Block Locked Error (try to erase %d times)\n", BlockAddress, Index)); I see this pattern again below. If the intent was to print a line break, write '\n' without breaking the format string. Or split the DEBUG up into two DEBUG statements. Please apply in all instances below too. > + } > + > + if (!EfiAtRuntime ()) { > + // Interruptions can resume. > + gBS->RestoreTPL (OriginalTPL); > + } > + > + return Status; > +} > + > + > +/** > + Readed the specified number of bytes from the form the block to output buffer. > + > + @param[in] FlashInstance The pointer of FT_FVB_DEVICE instance. > + > + @param[in] Lba The starting logical block index to write to. > + > + @param[in] Offset Offset into the block at which to begin writing. > + > + @param[in] BufferSizeInBytes The number of bytes to be writed. > + > + @param[out] Buffer The pointer to a caller-allocated buffer that > + contains the source for the write. > + > + @retval EFI_SUCCESS FvbFlashRead() is executed successfully. > + > +**/ > +STATIC > +EFI_STATUS > +FvbFlashRead ( > + IN FT_FVB_DEVICE *FlashInstance, > + IN EFI_LBA Lba, > + IN UINTN Offset, > + IN UINTN BufferSizeInBytes, > + OUT VOID *Buffer > + ) > +{ > + UINTN Address; > + > + Address = GET_DATA_OFFSET(FlashInstance->RegionBaseAddress, \ This is not a macro, you do not need the '\'. > + Lba, FlashInstance->Media.BlockSize) + Offset; Drop the double space. > + > + if (BufferSizeInBytes == 0) { > + return EFI_SUCCESS; > + } > + > + // The buffer must be valid > + if (Buffer == NULL) { > + return EFI_INVALID_PARAMETER; > + } > + > + return FlashInstance->SpiFlashProtocol->Read (Address, Buffer, BufferSizeInBytes); > +} > + > + > +/** > + Write a full or portion of a block. It must not span block boundaries; that is, > + Offset + *NumBytes <= FlashInstance->Media.BlockSize. > + > + @param[in] FlashInstance The pointer of FT_FVB_DEVICE instance. > + > + @param[in] Lba The starting logical block index to write to. > + > + @param[in] Offset Offset into the block at which to begin writing. > + > + @param[in] BufferSizeInBytes The number of bytes to be writed. > + > + @param[out] Buffer The pointer to a caller-allocated buffer that > + contains the source for the write. > + > + @retval EFI_SUCCESS FvbWriteBlock() is executed successfully. > + > + @retval EFI_BAD_BUFFER_SIZE The write spaned block boundaries. > + > +**/ > +STATIC > +EFI_STATUS > +FvbWriteBlock ( > + IN FT_FVB_DEVICE *FlashInstance, > + IN EFI_LBA Lba, > + IN UINTN Offset, > + IN UINTN BufferSizeInBytes, > + IN UINT8 *Buffer > + ) > +{ > + EFI_STATUS Status; > + UINTN BlockSize; > + UINTN BlockAddress; > + > + // Detect WriteDisabled state > + if (FlashInstance->Media.ReadOnly == TRUE) { > + DEBUG ((DEBUG_ERROR, "FvbWriteBlock: ERROR - Can not write: \ > + Device is in WriteDisabled state.\n")); > + // It is in WriteDisabled state, return an error right away > + return EFI_ACCESS_DENIED; > + } > + > + // Cache the block size to avoid de-referencing pointers all the time > + BlockSize = FlashInstance->Media.BlockSize; > + > + // The write must not span block boundaries. > + // We need to check each variable individually because adding two large values together overflows. > + if ((Offset >= BlockSize) || > + (BufferSizeInBytes > BlockSize) || > + ((Offset + BufferSizeInBytes) > BlockSize)) { > + DEBUG ((DEBUG_ERROR, "FvbWriteBlock: ERROR - EFI_BAD_BUFFER_SIZE: \ > + (Offset=0x%x + NumBytes=0x%x) > BlockSize=0x%x\n", Offset, BufferSizeInBytes, BlockSize)); > + return EFI_BAD_BUFFER_SIZE; > + } > + > + // We must have some bytes to write > + if (BufferSizeInBytes == 0) { > + DEBUG ((DEBUG_ERROR, "FvbWriteBlock: ERROR - EFI_BAD_BUFFER_SIZE: NumBytes == 0\n")); > + return EFI_BAD_BUFFER_SIZE; > + } > + > + // Check we did get some memory. Buffer is BlockSize. > + if (FlashInstance->ShadowBuffer == NULL) { > + DEBUG ((DEBUG_ERROR, "FvbWriteBlock: ERROR - ShadowBuffer is NULL!\n")); > + return EFI_DEVICE_ERROR; > + } > + > + // > + // Write the word to NOR. > + // > + BlockAddress = GET_DATA_OFFSET (FlashInstance->RegionBaseAddress, Lba, FlashInstance->Media.BlockSize); > + > + // Read NOR Flash data into shadow buffer > + Status = FlashInstance->SpiFlashProtocol->Read (BlockAddress, FlashInstance->ShadowBuffer, BlockSize); > + if (EFI_ERROR (Status)) { > + // Return one of the pre-approved error statuses > + return EFI_DEVICE_ERROR; > + } > + > + // Put the data at the appropriate location inside the buffer area > + CopyMem ((VOID*)((UINTN)FlashInstance->ShadowBuffer + Offset), Buffer, BufferSizeInBytes); > + > + Status = FlashInstance->SpiFlashProtocol->EraseSingleBlock (BlockAddress); > + if (EFI_ERROR (Status)) { > + // Return one of the pre-approved error statuses > + return EFI_DEVICE_ERROR; > + } > + > + // Write the modified buffer back to the NorFlash > + Status = FlashInstance->SpiFlashProtocol->Write (BlockAddress, FlashInstance->ShadowBuffer, BlockSize); > + if (EFI_ERROR (Status)) { > + // Return one of the pre-approved error statuses > + return EFI_DEVICE_ERROR; > + } > + > + return EFI_SUCCESS; > +} > + > + > +/** > + Writes the specified number of bytes from the input buffer to the block. > + > + @param[in] FlashInstance The pointer of FT_FVB_DEVICE instance. > + > + @param[in] Lba The starting logical block index to write to. > + > + @param[in] Offset Offset into the block at which to begin writing. > + > + @param[in] BufferSizeInBytes The number of bytes to be writed. > + > + @param[in] Buffer The pointer to a caller-allocated buffer that > + contains the source for the write. > + > + @retval EFI_SUCCESS FvbFlashWrite() is executed successfully. > + > + @retval EFI_WRITE_PROTECTED Flash state is in the WriteDisabled state. > + > + @retval EFI_INVALID_PARAMETER The pointer of Buffer is NULL. > + > +**/ > +STATIC > +EFI_STATUS > +FvbFlashWrite ( > + IN FT_FVB_DEVICE *FlashInstance, > + IN EFI_LBA Lba, > + IN UINTN Offset, > + IN UINTN BufferSizeInBytes, > + IN VOID *Buffer > + ) > +{ > + EFI_STATUS Status; > + UINT32 BlockSize; > + UINT32 BlockOffset; > + UINTN RemainingBytes; > + UINTN WriteSize; > + > + if (FlashInstance->Media.ReadOnly == TRUE) { > + return EFI_WRITE_PROTECTED; > + } > + > + if (BufferSizeInBytes == 0) { > + return EFI_SUCCESS; > + } > + > + if (Buffer == NULL) { > + return EFI_INVALID_PARAMETER; > + } > + > + Status = EFI_SUCCESS; > + BlockSize = FlashInstance->Media.BlockSize; > + BlockOffset = Offset; > + RemainingBytes = BufferSizeInBytes; > + > + // The write must not span block boundaries. > + // We need to check each variable individually because adding > + // two large values together overflows. > + if (Offset >= BlockSize) { > + DEBUG ((DEBUG_ERROR, "FvbFlashWrite: ERROR - EFI_BAD_BUFFER_SIZE: \ > + Offset=0x%x > BlockSize=0x%x\n", Offset, BlockSize)); > + return EFI_BAD_BUFFER_SIZE; > + } > + > + // We must have some bytes to read > + // Write either all the remaining bytes, or the number of bytes that bring > + // us up to a block boundary, whichever is less. > + // (DiskOffset | (BlockSize - 1)) + 1) rounds DiskOffset up to the next > + // block boundary (even if it is already on one). > + WriteSize = MIN (RemainingBytes, BlockSize - BlockOffset); > + > + do { > + Status = FvbWriteBlock (FlashInstance, Lba, BlockOffset, WriteSize, Buffer); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + // Now continue writing either all the remaining bytes or single blocks. > + RemainingBytes -= WriteSize; > + Buffer = (UINT8 *) Buffer + WriteSize; > + Lba++; > + BlockOffset = 0; > + WriteSize = MIN (RemainingBytes, BlockSize); > + } while (RemainingBytes); > + > + return Status; > +} > + > + > +/** > + Initialises the FV Header and Variable Store Header > + to support variable operations. > + > + @param[in] Ptr Location to initialise the headers. > + > + @retval EFI_SUCCESS FvbInitFvAndVariableStoreHeaders() > + is executed successfully. > + > +**/ > +STATIC > +EFI_STATUS > +FvbInitFvAndVariableStoreHeaders ( > + IN FT_FVB_DEVICE *FlashInstance > + ) > +{ > + EFI_STATUS Status; > + VOID* Headers; > + UINTN HeadersLength; > + EFI_FIRMWARE_VOLUME_HEADER *FirmwareVolumeHeader; > + VARIABLE_STORE_HEADER *VariableStoreHeader; > + > + HeadersLength = sizeof (EFI_FIRMWARE_VOLUME_HEADER) + sizeof (EFI_FV_BLOCK_MAP_ENTRY) \ > + + sizeof (VARIABLE_STORE_HEADER); Lots of very long lines in this function. Please wrap them all, and get rid of the '\'s. > + Headers = AllocateZeroPool (HeadersLength); > + > + // FirmwareVolumeHeader->FvLength is declared to have the Variable area > + // AND the FTW working area AND the FTW Spare contiguous. > + ASSERT (PcdGet64 (PcdFlashNvStorageVariableBase64) + PcdGet32 (PcdFlashNvStorageVariableSize) \ > + == PcdGet64 (PcdFlashNvStorageFtwWorkingBase64)); > + ASSERT(PcdGet64 (PcdFlashNvStorageFtwWorkingBase64) + PcdGet32 (PcdFlashNvStorageFtwWorkingSize) \ > + == PcdGet64 (PcdFlashNvStorageFtwSpareBase64)); > + > + // Check if the size of the area is at least one block size > + ASSERT((PcdGet32 (PcdFlashNvStorageVariableSize) > 0) && (PcdGet32 (PcdFlashNvStorageVariableSize) \ > + / FlashInstance->Media.BlockSize > 0)); > + ASSERT((PcdGet32 (PcdFlashNvStorageFtwWorkingSize) > 0) && (PcdGet32 (PcdFlashNvStorageFtwWorkingSize) \ > + / FlashInstance->Media.BlockSize > 0)); > + ASSERT((PcdGet32 (PcdFlashNvStorageFtwSpareSize) > 0) && (PcdGet32 (PcdFlashNvStorageFtwSpareSize) \ > + / FlashInstance->Media.BlockSize > 0)); > + > + // Ensure the Variable area Base Addresses are aligned on a block size boundaries > + ASSERT (PcdGet64 (PcdFlashNvStorageVariableBase64) % FlashInstance->Media.BlockSize == 0); > + ASSERT (PcdGet64 (PcdFlashNvStorageFtwWorkingBase64) % FlashInstance->Media.BlockSize == 0); > + ASSERT (PcdGet64 (PcdFlashNvStorageFtwSpareBase64) % FlashInstance->Media.BlockSize == 0); > + > + // > + // EFI_FIRMWARE_VOLUME_HEADER > + // > + FirmwareVolumeHeader = (EFI_FIRMWARE_VOLUME_HEADER*)Headers; > + CopyGuid (&FirmwareVolumeHeader->FileSystemGuid, &gEfiSystemNvDataFvGuid); > + FirmwareVolumeHeader->FvLength = FlashInstance->FvbSize; > + > + FirmwareVolumeHeader->Signature = EFI_FVH_SIGNATURE; > + FirmwareVolumeHeader->Attributes = (EFI_FVB_ATTRIBUTES_2) ( > + EFI_FVB2_READ_ENABLED_CAP | // Reads may be enabled > + EFI_FVB2_READ_STATUS | // Reads are currently enabled > + EFI_FVB2_STICKY_WRITE | // A block erase is required to > + // flip bits into EFI_FVB2_ERASE_POLARITY > + EFI_FVB2_MEMORY_MAPPED | // It is memory mapped > + EFI_FVB2_ERASE_POLARITY | // After erasure all bits take this value > + EFI_FVB2_WRITE_STATUS | // Writes are currently enabled > + EFI_FVB2_WRITE_ENABLED_CAP // Writes may be enabled Please use a temporary variable to reduce the indentation here. > + ); > + > + FirmwareVolumeHeader->HeaderLength = sizeof (EFI_FIRMWARE_VOLUME_HEADER) + sizeof (EFI_FV_BLOCK_MAP_ENTRY); > + FirmwareVolumeHeader->Revision = EFI_FVH_REVISION; > + FirmwareVolumeHeader->BlockMap[0].NumBlocks = FlashInstance->Media.LastBlock + 1; > + FirmwareVolumeHeader->BlockMap[0].Length = FlashInstance->Media.BlockSize; > + FirmwareVolumeHeader->BlockMap[1].NumBlocks = 0; > + FirmwareVolumeHeader->BlockMap[1].Length = 0; > + FirmwareVolumeHeader->Checksum = CalculateCheckSum16 ((UINT16*)FirmwareVolumeHeader, FirmwareVolumeHeader->HeaderLength); > + > + // > + // VARIABLE_STORE_HEADER > + // > + VariableStoreHeader = (VARIABLE_STORE_HEADER*)((UINTN)Headers + FirmwareVolumeHeader->HeaderLength); > + CopyGuid (&VariableStoreHeader->Signature, &gEfiAuthenticatedVariableGuid); > + VariableStoreHeader->Size = PcdGet32 (PcdFlashNvStorageVariableSize) - FirmwareVolumeHeader->HeaderLength; > + VariableStoreHeader->Format = VARIABLE_STORE_FORMATTED; > + VariableStoreHeader->State = VARIABLE_STORE_HEALTHY; > + > + // Install the combined super-header in the NorFlash > + Status = FvbWrite (&FlashInstance->FvbProtocol, 0, 0, &HeadersLength, Headers); > + > + FreePool (Headers); > + > + return Status; > +} > + > + > +/** > + Check the integrity of firmware volume header. > + > + @param[in] FwVolHeader A pointer to a firmware volume header > + > + @retval EFI_SUCCESS The firmware volume is consistent > + > + @retval EFI_NOT_FOUND The firmware volume has been corrupted. > + > +**/ > +STATIC > +EFI_STATUS > +FvbValidateFvHeader ( > + IN FT_FVB_DEVICE *FlashInstance > + ) > +{ > + UINT16 Checksum; > + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; > + VARIABLE_STORE_HEADER *VariableStoreHeader; > + UINTN VariableStoreLength; > + UINTN FvLength; > + > + FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER*)GET_DATA_OFFSET (FlashInstance->RegionBaseAddress, \ > + FlashInstance->StartLba, FlashInstance->Media.BlockSize); More very long lines, with pointless '\' characters. / Leif > + FvLength = FlashInstance->FvbSize; > + > + // > + // Verify the header revision, header signature, length > + // Length of FvBlock cannot be 2**64-1 > + // HeaderLength cannot be an odd number > + // > + if ((FwVolHeader->Revision != EFI_FVH_REVISION) || > + (FwVolHeader->Signature != EFI_FVH_SIGNATURE) || > + (FwVolHeader->FvLength != FvLength)) > + { > + DEBUG ((DEBUG_ERROR, "ValidateFvHeader: No Firmware Volume header present\n")); > + return EFI_NOT_FOUND; > + } > + > + // Check the Firmware Volume Guid > + if( CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiSystemNvDataFvGuid) == FALSE ) { > + DEBUG ((DEBUG_ERROR, "ValidateFvHeader: Firmware Volume Guid non-compatible\n")); > + return EFI_NOT_FOUND; > + } > + > + // Verify the header checksum > + Checksum = CalculateSum16 ((UINT16*)FwVolHeader, FwVolHeader->HeaderLength); > + if (Checksum != 0) { > + DEBUG ((DEBUG_ERROR, "ValidateFvHeader: FV checksum is invalid (Checksum:0x%X)\n", Checksum)); > + return EFI_NOT_FOUND; > + } > + > + VariableStoreHeader = (VARIABLE_STORE_HEADER*)((UINTN)FwVolHeader + FwVolHeader->HeaderLength); > + > + // Check the Variable Store Guid > + if (!CompareGuid (&VariableStoreHeader->Signature, &gEfiVariableGuid) && > + !CompareGuid (&VariableStoreHeader->Signature, > + &gEfiAuthenticatedVariableGuid)) { > + DEBUG ((DEBUG_ERROR, "%a: Variable Store Guid non-compatible\n")); > + return EFI_NOT_FOUND; > + } > + > + VariableStoreLength = PcdGet32 (PcdFlashNvStorageVariableSize) - FwVolHeader->HeaderLength; > + if (VariableStoreHeader->Size != VariableStoreLength) { > + DEBUG ((DEBUG_ERROR, "ValidateFvHeader: Variable Store Length does not match\n")); > + return EFI_NOT_FOUND; > + } > + > + return EFI_SUCCESS; > +} > + > + > +/** > + The FvbGetAttributes() function retrieves the attributes and > + current settings of the block. > + > + @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance. > + > + @param Attributes Pointer to EFI_FVB_ATTRIBUTES_2 in which the attributes and > + current settings are returned. > + Type EFI_FVB_ATTRIBUTES_2 is defined in > + EFI_FIRMWARE_VOLUME_HEADER. > + > + @retval EFI_SUCCESS The firmware volume attributes were returned. > + > +**/ > +EFI_STATUS > +EFIAPI > +FvbGetAttributes ( > + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, > + OUT EFI_FVB_ATTRIBUTES_2 *Attributes > + ) > +{ > + EFI_FVB_ATTRIBUTES_2 FlashFvbAttributes; > + CONST FT_FVB_DEVICE *FlashInstance; > + > + FlashInstance = INSTANCE_FROM_FVB_THIS (This); > + > + FlashFvbAttributes = (EFI_FVB_ATTRIBUTES_2) ( > + > + EFI_FVB2_READ_ENABLED_CAP | // Reads may be enabled > + EFI_FVB2_READ_STATUS | // Reads are currently enabled > + EFI_FVB2_STICKY_WRITE | // A block erase is required to flip bits into EFI_FVB2_ERASE_POLARITY > + EFI_FVB2_MEMORY_MAPPED | // It is memory mapped > + EFI_FVB2_ERASE_POLARITY // After erasure all bits take this value (i.e. '1') > + > + ); > + > + // Check if it is write protected > + if (FlashInstance->Media.ReadOnly != TRUE) { > + > + FlashFvbAttributes = FlashFvbAttributes | > + EFI_FVB2_WRITE_STATUS | // Writes are currently enabled > + EFI_FVB2_WRITE_ENABLED_CAP; // Writes may be enabled > + } > + > + *Attributes = FlashFvbAttributes; > + > + return EFI_SUCCESS; > +} > + > + > +/** > + The FvbSetAttributes() function sets configurable firmware volume attributes > + and returns the new settings of the firmware volume. > + > + @param This EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance. > + > + @param Attributes On input, Attributes is a pointer to > + EFI_FVB_ATTRIBUTES_2 that contains the desired > + firmware volume settings. > + On successful return, it contains the new > + settings of the firmware volume. > + > + @retval EFI_SUCCESS The firmware volume attributes were returned. > + > + @retval EFI_INVALID_PARAMETER The attributes requested are in conflict with > + the capabilities as declared in the firmware > + volume header. > + > +**/ > +EFI_STATUS > +EFIAPI > +FvbSetAttributes ( > + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, > + IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes > + ) > +{ > + return EFI_UNSUPPORTED; > +} > + > + > +/** > + The FvbGetPhysicalAddress() function retrieves the base address of > + a memory-mapped firmware volume. This function should be called > + only for memory-mapped firmware volumes. > + > + @param This EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance. > + > + @param Address Pointer to a caller-allocated > + EFI_PHYSICAL_ADDRESS that, on successful > + return from GetPhysicalAddress(), contains the > + base address of the firmware volume. > + > + @retval EFI_SUCCESS The firmware volume base address was returned. > + > + @retval EFI_NOT_SUPPORTED The firmware volume is not memory mapped. > + > +**/ > +EFI_STATUS > +EFIAPI > +FvbGetPhysicalAddress ( > + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, > + OUT EFI_PHYSICAL_ADDRESS *Address > + ) > +{ > + ASSERT (Address != NULL); > + > + *Address = mFlashNvStorageVariableBase; > + > + return EFI_SUCCESS; > +} > + > + > +/** > + The FvbGetBlockSize() function retrieves the size of the requested > + block. It also returns the number of additional blocks with > + the identical size. The FvbGetBlockSize() function is used to > + retrieve the block map (see EFI_FIRMWARE_VOLUME_HEADER). > + > + > + @param This EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance. > + > + @param Lba Indicates the block whose size to return. > + > + @param BlockSize Pointer to a caller-allocated UINTN in which > + the size of the block is returned. > + > + @param NumberOfBlocks Pointer to a caller-allocated UINTN in > + which the number of consecutive blocks, > + starting with Lba, is returned. All > + blocks in this range have a size of > + BlockSize. > + > + > + @retval EFI_SUCCESS The firmware volume base address was returned. > + > + @retval EFI_INVALID_PARAMETER The requested LBA is out of range. > + > +**/ > +EFI_STATUS > +EFIAPI > +FvbGetBlockSize ( > + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, > + IN EFI_LBA Lba, > + OUT UINTN *BlockSize, > + OUT UINTN *NumberOfBlocks > + ) > +{ > + EFI_STATUS Status; > + FT_FVB_DEVICE *FlashInstance; > + > + FlashInstance = INSTANCE_FROM_FVB_THIS (This); > + > + if (Lba > FlashInstance->Media.LastBlock) { > + Status = EFI_INVALID_PARAMETER; > + } else { > + // This is easy because in this platform each NorFlash device has equal sized blocks. > + *BlockSize = (UINTN) FlashInstance->Media.BlockSize; > + *NumberOfBlocks = (UINTN) (FlashInstance->Media.LastBlock - Lba + 1); > + Status = EFI_SUCCESS; > + } > + > + return Status; > +} > + > + > +/** > + Reads the specified number of bytes into a buffer from the specified block. > + > + The FvbRead() function reads the requested number of bytes from the > + requested block and stores them in the provided buffer. > + > + @param This EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance. > + > + @param Lba The starting logical block index from which to read. > + > + @param Offset Offset into the block at which to begin reading. > + > + @param NumBytes Pointer to a UINTN. > + At entry, *NumBytes contains the total size of the > + buffer. > + At exit, *NumBytes contains the total number of > + bytes read. > + > + @param Buffer Pointer to a caller-allocated buffer that will be > + used to hold the data that is read. > + > + @retval EFI_SUCCESS The firmware volume was read successfully, and > + contents are in Buffer. > + > + @retval EFI_BAD_BUFFER_SIZE Read attempted across an LBA boundary. > + On output, NumBytes contains the total number of > + bytes returned in Buffer. > + > + @retval EFI_ACCESS_DENIED The firmware volume is in the ReadDisabled state. > + > + @retval EFI_DEVICE_ERROR The block device is not functioning correctly and > + could not be read. > +**/ > +EFI_STATUS > +EFIAPI > +FvbRead ( > + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, > + IN EFI_LBA Lba, > + IN UINTN Offset, > + IN OUT UINTN *NumBytes, > + IN OUT UINT8 *Buffer > + ) > +{ > + UINTN BlockSize; > + FT_FVB_DEVICE *FlashInstance; > + EFI_STATUS Status; > + > + FlashInstance = INSTANCE_FROM_FVB_THIS (This); > + > + // Cache the block size to avoid de-referencing pointers all the time > + BlockSize = FlashInstance->Media.BlockSize; > + > + // The read must not span block boundaries. > + // We need to check each variable individually because adding two large values together overflows. > + if ((Offset >= BlockSize) || > + (*NumBytes > BlockSize) || > + ((Offset + *NumBytes) > BlockSize)) { > + return EFI_BAD_BUFFER_SIZE; > + } > + > + // We must have some bytes to read > + if (*NumBytes == 0) { > + return EFI_BAD_BUFFER_SIZE; > + } > + > + Status = FvbFlashRead (FlashInstance, FlashInstance->StartLba + Lba, Offset, *NumBytes, Buffer); > + if (EFI_ERROR (Status)) { > + return EFI_DEVICE_ERROR; > + } > + > + return EFI_SUCCESS; > +} > + > + > +/** > + Writes the specified number of bytes from the input buffer to the block. > + > + The FvbWrite() function writes the specified number of bytes from > + the provided buffer to the specified block and offset. > + > + @param This EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance. > + > + @param Lba The starting logical block index to write to. > + > + @param Offset Offset into the block at which to begin writing. > + > + @param NumBytes The pointer to a UINTN. > + At entry, *NumBytes contains the total size of the > + buffer. > + At exit, *NumBytes contains the total number of > + bytes actually written. > + > + @param Buffer The pointer to a caller-allocated buffer that > + contains the source for the write. > + > + @retval EFI_SUCCESS The firmware volume was written successfully. > + > + @retval EFI_BAD_BUFFER_SIZE The write was attempted across an LBA boundary. > + On output, NumBytes contains the total number of > + bytes actually written. > + > + @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisabled state. > + > + @retval EFI_DEVICE_ERROR The block device is malfunctioning and could not be > + written. > + > +**/ > +EFI_STATUS > +EFIAPI > +FvbWrite ( > + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, > + IN EFI_LBA Lba, > + IN UINTN Offset, > + IN OUT UINTN *NumBytes, > + IN UINT8 *Buffer > + ) > +{ > + FT_FVB_DEVICE *FlashInstance; > + > + FlashInstance = INSTANCE_FROM_FVB_THIS (This); > + > + return FvbFlashWrite (FlashInstance, FlashInstance->StartLba + Lba, Offset, *NumBytes, Buffer); > +} > + > + > +/** > + Erases and initialises a firmware volume block. > + > + The FvbEraseBlocks() function erases one or more blocks as denoted > + by the variable argument list. > + > + @param This EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL > + instance. > + > + @param ... The variable argument list is a list of tuples. > + Each tuple describes a range of LBAs to erase > + and consists of the following: > + An EFI_LBA that indicates the starting LBA > + A UINTN that indicates the number of blocks > + to erase. > + > + The list is terminated with an > + EFI_LBA_LIST_TERMINATOR. > + > + @retval EFI_SUCCESS The erase request successfully completed. > + > + @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisabled > + state. > + > + @retval EFI_DEVICE_ERROR The block device is not functioning correctly > + and could not be written. > + The firmware device may have been partially > + erased. > + > + @retval EFI_INVALID_PARAMETER One or more of the LBAs listed in the variable > + argument list do not exist in the firmware > + volume. > + > +**/ > +EFI_STATUS > +EFIAPI > +FvbEraseBlocks ( > + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, > + ... > + ) > +{ > + EFI_STATUS Status; > + VA_LIST Args; > + UINTN BlockAddress; // Physical address of Lba to erase > + EFI_LBA StartingLba; // Lba from which we start erasing > + UINTN NumOfLba; // Number of Lba blocks to erase > + FT_FVB_DEVICE *Instance; > + > + Instance = INSTANCE_FROM_FVB_THIS (This); > + > + Status = EFI_SUCCESS; > + > + // Detect WriteDisabled state > + if (Instance->Media.ReadOnly == TRUE) { > + // Firmware volume is in WriteDisabled state > + DEBUG ((DEBUG_ERROR, "FvbEraseBlocks: ERROR - Device is in WriteDisabled state.\n")); > + return EFI_ACCESS_DENIED; > + } > + > + // Before erasing, check the entire list of parameters to ensure all specified blocks are valid > + > + VA_START (Args, This); > + do { > + // Get the Lba from which we start erasing > + StartingLba = VA_ARG (Args, EFI_LBA); > + > + // Have we reached the end of the list? > + if (StartingLba == EFI_LBA_LIST_TERMINATOR) { > + //Exit the while loop > + break; > + } > + > + // How many Lba blocks are we requested to erase? > + NumOfLba = VA_ARG (Args, UINT32); > + > + // All blocks must be within range > + if ((NumOfLba == 0) || ((Instance->StartLba + StartingLba + NumOfLba - 1) \ > + > Instance->Media.LastBlock)) { > + VA_END (Args); > + DEBUG ((DEBUG_ERROR, "FvbEraseBlocks: ERROR - Lba range goes past the last Lba.\n")); > + Status = EFI_INVALID_PARAMETER; > + goto EXIT; > + } > + } while (TRUE); > + > + VA_END (Args); > + > + // > + // To get here, all must be ok, so start erasing > + // > + VA_START (Args, This); > + do { > + // Get the Lba from which we start erasing > + StartingLba = VA_ARG (Args, EFI_LBA); > + > + // Have we reached the end of the list? > + if (StartingLba == EFI_LBA_LIST_TERMINATOR) { > + // Exit the while loop > + break; > + } > + > + // How many Lba blocks are we requested to erase? > + NumOfLba = VA_ARG (Args, UINT32); > + > + // Go through each one and erase it > + while (NumOfLba > 0) { > + // Get the physical address of Lba to erase > + BlockAddress = GET_DATA_OFFSET ( > + Instance->RegionBaseAddress, > + Instance->StartLba + StartingLba, > + Instance->Media.BlockSize > + ); > + > + // Erase it > + Status = FvbFlashEraseSingleBlock (Instance, BlockAddress); > + if (EFI_ERROR (Status)) { > + VA_END (Args); > + Status = EFI_DEVICE_ERROR; > + goto EXIT; > + } > + > + // Move to the next Lba > + StartingLba++; > + NumOfLba--; > + } > + } while (TRUE); > + > + VA_END (Args); > + > +EXIT: > + return Status; > +} > + > + > +/** > + This function inited the NorFlash instance. > + > + @param[in][out] FlashInstance The pointer of FT_FVB_DEVICE instance. > + > + @retval EFI_SUCCESS PhytNorFlashFvbInitialize() is executed successfully. > + > +**/ > +STATIC > +EFI_STATUS > +PhytNorFlashFvbInitialize ( > + IN OUT FT_FVB_DEVICE *FlashInstance > + ) > +{ > + EFI_STATUS Status; > + UINT32 FvbNumLba; > + EFI_BOOT_MODE BootMode; > + UINTN TotalFvbSize; > + > + mFlashNvStorageVariableBase = FixedPcdGet64 (PcdFlashNvStorageVariableBase64); > + > + // Declare the Non-Volatile storage as EFI_MEMORY_RUNTIME > + Status = gDS->AddMemorySpace ( > + EfiGcdMemoryTypeMemoryMappedIo, > + mFlashNvStorageVariableBase, FlashInstance->FvbSize, > + EFI_MEMORY_UC | EFI_MEMORY_RUNTIME > + ); > + ASSERT_EFI_ERROR (Status); > + > + Status = gDS->SetMemorySpaceAttributes ( > + mFlashNvStorageVariableBase, FlashInstance->FvbSize, > + EFI_MEMORY_UC | EFI_MEMORY_RUNTIME > + ); > + ASSERT_EFI_ERROR (Status); > + > + TotalFvbSize = FlashInstance->FvbSize; > + > + // Set the index of the first LBA for the FVB > + FlashInstance->StartLba = (PcdGet64 (PcdFlashNvStorageVariableBase64) - \ > + FlashInstance->RegionBaseAddress) / FlashInstance->Media.BlockSize; > + > + BootMode = GetBootModeHob (); > + if (BootMode == BOOT_WITH_DEFAULT_SETTINGS) { > + Status = EFI_INVALID_PARAMETER; > + } else { > + // Determine if there is a valid header at the beginning of the NorFlash > + Status = FvbValidateFvHeader (FlashInstance); > + } > + > + // Install the Default FVB header if required > + if (EFI_ERROR (Status)) { > + // There is no valid header, so time to install one. > + DEBUG ((DEBUG_ERROR,"NorFlashFvbInitialize: ERROR - The FVB Header is invalid. \ > + Installing a correct one for this volume.\n")); > + > + // Erase all the NorFlash that is reserved for variable storage > + FvbNumLba = TotalFvbSize / FlashInstance->Media.BlockSize; > + > + Status = FvbEraseBlocks (&FlashInstance->FvbProtocol, (EFI_LBA)0,\ > + FvbNumLba, EFI_LBA_LIST_TERMINATOR); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + // Install all appropriate headers > + Status = FvbInitFvAndVariableStoreHeaders (FlashInstance); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + } > + > + return Status; > +} > + > + > +/** > + The CreateInstance() function Create Fvb Instance. > + > + @retval EFI_SUCCESS Create Instance successfully. > + > + @retval other Create Instance failed. > + > +**/ > +STATIC > +EFI_STATUS > +CreateInstance ( > + VOID > + ) > +{ > + EFI_STATUS Status; > + NOR_FLASH_DEVICE_DESCRIPTION *NorFlashDevice; > + > + // Locate flash protocols > + Status = gBS->LocateProtocol (&gSpiNorFlashProtocolGuid, > + NULL, > + (VOID **)&FvbDevice->SpiFlashProtocol); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "Cannot locate NorFlash protocol.\n")); > + return Status; > + } > + > + NorFlashDevice = AllocateRuntimePool (sizeof (NOR_FLASH_DEVICE_DESCRIPTION)); > + if (NorFlashDevice == NULL) { > + DEBUG ((DEBUG_ERROR, "Cannot Allocate NorFlashDevice Pool.\n")); > + return Status; > + } > + > + Status = FvbDevice->SpiFlashProtocol->GetDevices (NorFlashDevice); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + Status = FvbDevice->SpiFlashProtocol->Initialization(); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + FvbDevice->DeviceBaseAddress = NorFlashDevice->DeviceBaseAddress; > + FvbDevice->RegionBaseAddress = NorFlashDevice->RegionBaseAddress; > + FvbDevice->Size = NorFlashDevice->Size; > + > + FvbDevice->Media.MediaId = 0; > + FvbDevice->Media.BlockSize = NorFlashDevice->BlockSize; > + FvbDevice->Media.LastBlock = (FvbDevice->Size / FvbDevice->Media.BlockSize) - 1; > + FvbDevice->FvbSize = PcdGet32 (PcdFlashNvStorageVariableSize) + > + PcdGet32 (PcdFlashNvStorageFtwWorkingSize) + > + PcdGet32 (PcdFlashNvStorageFtwSpareSize); > + > + CopyGuid (&FvbDevice->DevicePath.Vendor.Guid, &NorFlashDevice->Guid); > + > + FvbDevice->ShadowBuffer = AllocateRuntimePool (FvbDevice->Media.BlockSize); > + if (FvbDevice->ShadowBuffer == NULL) { > + return EFI_OUT_OF_RESOURCES; > + } > + > + Status = gBS->InstallMultipleProtocolInterfaces ( > + &FvbDevice->Handle, > + &gEfiDevicePathProtocolGuid, &FvbDevice->DevicePath, > + &gEfiFirmwareVolumeBlockProtocolGuid, &FvbDevice->FvbProtocol, > + NULL > + ); > + if (EFI_ERROR (Status)) { > + FreePool (FvbDevice); > + return Status; > + } > + > + Status = PhytNorFlashFvbInitialize (FvbDevice); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "PhytNorFlashFvbInitialize: Fail to init NorFlash devices\n")); > + return Status; > + } > + > + FreePool (NorFlashDevice); > + > + return Status; > +} > + > + > +/** > + Fixup internal data so that EFI can be call in virtual mode. > + Call the passed in Child Notify event and convert any pointers > + in lib to virtual mode. > + > + @param[in] Event The Event that is being processed. > + > + @param[in] Context Event Context. > + > + @retval None. > + > +**/ > +STATIC > +VOID > +EFIAPI > +FvbVirtualNotifyEvent ( > + IN EFI_EVENT Event, > + IN VOID *Context > + ) > +{ > + // Convert SpiFlashProtocol > + EfiConvertPointer (0x0, (VOID**)&FvbDevice->SpiFlashProtocol->Erase); > + EfiConvertPointer (0x0, (VOID**)&FvbDevice->SpiFlashProtocol->Write); > + EfiConvertPointer (0x0, (VOID**)&FvbDevice->SpiFlashProtocol->Read); > + EfiConvertPointer (0x0, (VOID**)&FvbDevice->SpiFlashProtocol->GetDevices); > + EfiConvertPointer (0x0, (VOID**)&FvbDevice->SpiFlashProtocol->Initialization); > + EfiConvertPointer (0x0, (VOID**)&FvbDevice->SpiFlashProtocol->EraseSingleBlock); > + EfiConvertPointer (0x0, (VOID**)&FvbDevice->SpiFlashProtocol); > + > + EfiConvertPointer (0x0, (VOID**)&mFlashNvStorageVariableBase); > + EfiConvertPointer (0x0, (VOID**)&FvbDevice); > + > + return; > +} > + > + > +/** > + This function is the entrypoint of the fvb driver. > + > + @param[in] ImageHandle The firmware allocated handle for the EFI image. > + > + @param[in] SystemTable A pointer to the EFI System Table. > + > + @retval EFI_SUCCESS The entry point is executed successfully. > + > + @retval other Some error occurs when executing this entry point. > + > +**/ > +EFI_STATUS > +EFIAPI > +FvbEntryPoint ( > + IN EFI_HANDLE ImageHandle, > + IN EFI_SYSTEM_TABLE *SystemTable > + ) > +{ > + EFI_STATUS Status; > + > + FvbDevice = AllocateRuntimeCopyPool (sizeof (FvbFlashInstanceTemplate), \ > + &FvbFlashInstanceTemplate); > + if (FvbDevice == NULL) { > + DEBUG ((DEBUG_ERROR, "%a: Cannot allocate memory\n", __FUNCTION__)); > + return EFI_OUT_OF_RESOURCES; > + } > + > + Status = CreateInstance (); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "CreateInstance: Fail to create instance for NorFlash\n")); > + } > + > +// > +// Register for the virtual address change event > +// > + Status = gBS->CreateEventEx ( > + EVT_NOTIFY_SIGNAL, > + TPL_NOTIFY, > + FvbVirtualNotifyEvent, > + NULL, > + &gEfiEventVirtualAddressChangeGuid, > + &FvbVirtualAddrChangeEvent > + ); > + ASSERT_EFI_ERROR (Status); > + > + return Status; > +} > -- > 2.25.1 >