From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: mx.groups.io; dkim=pass header.i=@linaro.org header.s=google header.b=zWCEa7uS; spf=pass (domain: linaro.org, ip: 209.85.128.50, mailfrom: leif.lindholm@linaro.org) Received: from mail-wm1-f50.google.com (mail-wm1-f50.google.com [209.85.128.50]) by groups.io with SMTP; Thu, 03 Oct 2019 09:58:29 -0700 Received: by mail-wm1-f50.google.com with SMTP id i16so2789015wmd.3 for ; Thu, 03 Oct 2019 09:58:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:in-reply-to:user-agent; bh=Ai6WGWTpDhGgqNDSEVmGG4sUtt5b579AMRjp5siBZh0=; b=zWCEa7uSHDiVkC1x5RiM7ksR250k+3NYHqQ1CfHOyBw3XqabsHxCAp50XZ1rXsKjuW muM2a7FgdOtfGptFH/0Zwup17Ux2GWoBOdxnMKDKFvMowiK3EatVOFVQVJKjZnOFplhP s4qNDt8IrlhsT0TS5Y3DEmqcv1lYhnyCnvxEkIkyTvYsVx7R6rp+R+xVWZZ8l22tlbeA EaHANCWDSR9gZm9Y3sFIusx4YQ+Tu8X7MPDRVZeoefl7pZNAT3tA7g7oPAZueLAFCBGE eGdt9evBQzf5P78dvy2yNFn3tcNZCgawUlz8raYALU2s3nU4LpXa8xDD+aZuPus8LCx9 4z5g== 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=Ai6WGWTpDhGgqNDSEVmGG4sUtt5b579AMRjp5siBZh0=; b=flQaMbxhXnRi2GW7VoTpaHEbJbNit6WQd3MgsTatF4bXxo4CGevCTydvTaIYfi4G3W XJ1+W1igec6S/O39AtSeHMpyv8m35lm2GridV7w/H2j3856RtoWhTQLfd+CmUBSuAJZF qTC9pVyC+huzwLOuU5FKyCqp/pLc5hretKz7oG+n3nvvZ6ZFlMKeMNiEcieodFWD+fMU 6o2BaN5hnynDe6Sky5MWA7MjvsCqvDEBTFckNlIIer9hdsC9jq2lboTZ6mdSJVyXDDiz gLGgOQ97wljahtc1te/PbZsMIWm38mSM2/0wnObMWCIN6aIhKF2pPnsgdA6EksgAitAm /Reg== X-Gm-Message-State: APjAAAXHiipyDZfeywfIQddicQUmkIX46s4xpPwUJJBbyZKV3HTqnjtG iOnMlGw2HbmeBk1mgoKIUfEaBpGMJPE= X-Google-Smtp-Source: APXvYqysHh2nP+lvg9s7XM9A8VHzpUuXbM1PAn51aVgWfNq/3n/2mbF9qPMmJEA/EU9hqOdYGM/dXw== X-Received: by 2002:a1c:7d92:: with SMTP id y140mr7603057wmc.141.1570121906353; Thu, 03 Oct 2019 09:58:26 -0700 (PDT) Return-Path: Received: from bivouac.eciton.net (bivouac.eciton.net. [2a00:1098:0:86:1000:23:0:2]) by smtp.gmail.com with ESMTPSA id n1sm5783804wrg.67.2019.10.03.09.58.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 03 Oct 2019 09:58:25 -0700 (PDT) Date: Thu, 3 Oct 2019 17:58:23 +0100 From: "Leif Lindholm" To: devel@edk2.groups.io, gilbert.chen@hpe.com Cc: Palmer Dabbelt Subject: Re: [edk2-devel] [plaforms/devel-riscv-v2 PATCHv2 11/14] U500Pkg/RamFvbServiceruntimeDxe: FVB driver for EFI variable. Message-ID: <20191003165823.GO25504@bivouac.eciton.net> References: <20190919035131.4700-1-gilbert.chen@hpe.com> <20190919035131.4700-12-gilbert.chen@hpe.com> MIME-Version: 1.0 In-Reply-To: <20190919035131.4700-12-gilbert.chen@hpe.com> User-Agent: Mutt/1.10.1 (2018-07-13) Content-Type: text/plain; charset=us-ascii Content-Disposition: inline On Thu, Sep 19, 2019 at 11:51:28AM +0800, Gilbert Chen wrote: > Firmware Volume Block driver instance for ram based EFI variable on U500 > platform. > > Signed-off-by: Gilbert Chen > --- > .../Dxe/RamFvbServicesRuntimeDxe/FvbInfo.c | 127 +++ > .../FvbServicesRuntimeDxe.inf | 81 ++ > .../Dxe/RamFvbServicesRuntimeDxe/FwBlockService.c | 1123 ++++++++++++++++++++ > .../Dxe/RamFvbServicesRuntimeDxe/FwBlockService.h | 187 ++++ > .../RamFvbServicesRuntimeDxe/FwBlockServiceDxe.c | 151 +++ > .../Dxe/RamFvbServicesRuntimeDxe/RamFlash.c | 144 +++ > .../Dxe/RamFvbServicesRuntimeDxe/RamFlash.h | 85 ++ > .../Dxe/RamFvbServicesRuntimeDxe/RamFlashDxe.c | 20 + > 8 files changed, 1918 insertions(+) > create mode 100644 Platform/RiscV/SiFive/U500Pkg/Universal/Dxe/RamFvbServicesRuntimeDxe/FvbInfo.c > create mode 100644 Platform/RiscV/SiFive/U500Pkg/Universal/Dxe/RamFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf > create mode 100644 Platform/RiscV/SiFive/U500Pkg/Universal/Dxe/RamFvbServicesRuntimeDxe/FwBlockService.c > create mode 100644 Platform/RiscV/SiFive/U500Pkg/Universal/Dxe/RamFvbServicesRuntimeDxe/FwBlockService.h > create mode 100644 Platform/RiscV/SiFive/U500Pkg/Universal/Dxe/RamFvbServicesRuntimeDxe/FwBlockServiceDxe.c > create mode 100644 Platform/RiscV/SiFive/U500Pkg/Universal/Dxe/RamFvbServicesRuntimeDxe/RamFlash.c > create mode 100644 Platform/RiscV/SiFive/U500Pkg/Universal/Dxe/RamFvbServicesRuntimeDxe/RamFlash.h > create mode 100644 Platform/RiscV/SiFive/U500Pkg/Universal/Dxe/RamFvbServicesRuntimeDxe/RamFlashDxe.c > > diff --git a/Platform/RiscV/SiFive/U500Pkg/Universal/Dxe/RamFvbServicesRuntimeDxe/FvbInfo.c b/Platform/RiscV/SiFive/U500Pkg/Universal/Dxe/RamFvbServicesRuntimeDxe/FvbInfo.c > new file mode 100644 > index 00000000..1ade0d14 > --- /dev/null > +++ b/Platform/RiscV/SiFive/U500Pkg/Universal/Dxe/RamFvbServicesRuntimeDxe/FvbInfo.c > @@ -0,0 +1,127 @@ > +/**@file > + > + Copyright (c) 2019, Hewlett Packard Enterprise Development LP. All rights reserved.
> + Copyright (c) 2006, Intel Corporation. All rights reserved.
> + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > + Module Name: > + > + FvbInfo.c > + > + Abstract: > + > + Defines data structure that is the volume header found.These data is intent > + to decouple FVB driver with FV header. > + > +**/ > + > +// > +// The package level header files this module uses > +// > +#include > + > +// > +// The protocols, PPI and GUID defintions for this module > +// > +#include > +// > +// The Library classes this module consumes > +// > +#include > +#include > + > +typedef struct { > + UINT64 FvLength; > + EFI_FIRMWARE_VOLUME_HEADER FvbInfo; > + // > + // EFI_FV_BLOCK_MAP_ENTRY ExtraBlockMap[n];//n=0 > + // > + EFI_FV_BLOCK_MAP_ENTRY End[1]; > +} EFI_FVB_MEDIA_INFO; > + > +EFI_FVB_MEDIA_INFO mPlatformFvbMediaInfo[] = { > + // > + // Systen NvStorage FVB > + // > + { > + FixedPcdGet32 (PcdFlashNvStorageVariableSize) + > + FixedPcdGet32 (PcdFlashNvStorageFtwWorkingSize) + > + FixedPcdGet32 (PcdFlashNvStorageFtwSpareSize), > + { > + { > + 0, > + }, // ZeroVector[16] > + EFI_SYSTEM_NV_DATA_FV_GUID, > + FixedPcdGet32 (PcdFlashNvStorageVariableSize) + > + FixedPcdGet32 (PcdFlashNvStorageFtwWorkingSize) + > + FixedPcdGet32 (PcdFlashNvStorageFtwSpareSize), > + EFI_FVH_SIGNATURE, > + EFI_FVB2_MEMORY_MAPPED | > + EFI_FVB2_READ_ENABLED_CAP | > + EFI_FVB2_READ_STATUS | > + EFI_FVB2_WRITE_ENABLED_CAP | > + EFI_FVB2_WRITE_STATUS | > + EFI_FVB2_ERASE_POLARITY | > + EFI_FVB2_ALIGNMENT_16, > + sizeof (EFI_FIRMWARE_VOLUME_HEADER) + sizeof (EFI_FV_BLOCK_MAP_ENTRY), > + 0, // CheckSum > + 0, // ExtHeaderOffset > + { > + 0, > + }, // Reserved[1] > + 2, // Revision > + { > + { > + (FixedPcdGet32 (PcdFlashNvStorageVariableSize) + > + FixedPcdGet32 (PcdFlashNvStorageFtwWorkingSize) + > + FixedPcdGet32 (PcdFlashNvStorageFtwSpareSize)) / > + FixedPcdGet32 (PcdVariableFdBlockSize), > + FixedPcdGet32 (PcdVariableFdBlockSize), > + } > + } // BlockMap[1] > + }, > + { > + { > + 0, > + 0 > + } > + } // End[1] > + } > +}; > + > +EFI_STATUS > +GetFvbInfo ( > + IN UINT64 FvLength, > + OUT EFI_FIRMWARE_VOLUME_HEADER **FvbInfo > + ) > +{ > + STATIC BOOLEAN Checksummed = FALSE; > + UINTN Index; > + > + if (!Checksummed) { > + for (Index = 0; > + Index < sizeof (mPlatformFvbMediaInfo) / sizeof (EFI_FVB_MEDIA_INFO); > + Index += 1) { > + UINT16 Checksum; > + mPlatformFvbMediaInfo[Index].FvbInfo.Checksum = 0; > + Checksum = CalculateCheckSum16 ( > + (UINT16*) &mPlatformFvbMediaInfo[Index].FvbInfo, > + mPlatformFvbMediaInfo[Index].FvbInfo.HeaderLength > + ); > + mPlatformFvbMediaInfo[Index].FvbInfo.Checksum = Checksum; > + } > + Checksummed = TRUE; > + } > + > + for (Index = 0; > + Index < sizeof (mPlatformFvbMediaInfo) / sizeof (EFI_FVB_MEDIA_INFO); > + Index += 1) { > + if (mPlatformFvbMediaInfo[Index].FvLength == FvLength) { > + *FvbInfo = &mPlatformFvbMediaInfo[Index].FvbInfo; > + return EFI_SUCCESS; > + } > + } > + > + return EFI_NOT_FOUND; > +} > diff --git a/Platform/RiscV/SiFive/U500Pkg/Universal/Dxe/RamFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf b/Platform/RiscV/SiFive/U500Pkg/Universal/Dxe/RamFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf > new file mode 100644 > index 00000000..1e8aa592 > --- /dev/null > +++ b/Platform/RiscV/SiFive/U500Pkg/Universal/Dxe/RamFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf > @@ -0,0 +1,81 @@ > +## @file > +# Component description file for RAM Flash Fimware Volume Block DXE driver > +# module. > +# > +# This DXE runtime driver implements and produces the Fimware Volue Block > +# Protocol for a RAM flash device. > +# > +# Copyright (c) 2019, Hewlett Packard Enterprise Development LP. All rights reserved.
> +# Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.
> +# > +# SPDX-License-Identifier: BSD-2-Clause-Patent > +# > +## > + > +[Defines] > + INF_VERSION = 0x00010005 > + BASE_NAME = FvbServicesRuntimeDxe > + FILE_GUID = B04036D3-4C60-43D6-9850-0FCC090FF054 > + MODULE_TYPE = DXE_RUNTIME_DRIVER > + VERSION_STRING = 1.0 > + ENTRY_POINT = FvbInitialize > + > +# > +# The following information is for reference only and not required by the build > +# tools. > +# > +# VALID_ARCHITECTURES = IA32 X64 > +# > + > +[Sources] > + FvbInfo.c > + FwBlockService.c > + FwBlockServiceDxe.c > + RamFlash.c > + RamFlashDxe.c > + > +[Packages] > + MdePkg/MdePkg.dec > + MdeModulePkg/MdeModulePkg.dec > + Platform/RiscV/RiscVPlatformPkg.dec > + > +[LibraryClasses] > + BaseLib > + BaseMemoryLib > + DebugLib > + DevicePathLib > + DxeServicesTableLib > + MemoryAllocationLib > + PcdLib > + UefiBootServicesTableLib > + UefiDriverEntryPoint > + UefiRuntimeLib > + > +[Guids] > + gEfiEventVirtualAddressChangeGuid # ALWAYS_CONSUMED > + # gEfiEventVirtualAddressChangeGuid # Create Event: EVENT_GROUP_GUID > + > +[Protocols] > + gEfiFirmwareVolumeBlockProtocolGuid # PROTOCOL SOMETIMES_PRODUCED > + gEfiDevicePathProtocolGuid # PROTOCOL SOMETIMES_PRODUCED > + > +[FixedPcd] > + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize > + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize > + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize > + > + gUefiRiscVPlatformPkgTokenSpaceGuid.PcdPlatformFlashNvStorageVariableBase > + gUefiRiscVPlatformPkgTokenSpaceGuid.PcdPlatformFlashNvStorageFtwWorkingBase > + gUefiRiscVPlatformPkgTokenSpaceGuid.PcdPlatformFlashNvStorageFtwSpareBase > + gUefiRiscVPlatformPkgTokenSpaceGuid.PcdVariableFdBaseAddress > + gUefiRiscVPlatformPkgTokenSpaceGuid.PcdVariableFdSize > + gUefiRiscVPlatformPkgTokenSpaceGuid.PcdVariableFdBlockSize > + > +[Pcd] > + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase > + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase > + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase > + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64 > + > +[Depex] > + TRUE > diff --git a/Platform/RiscV/SiFive/U500Pkg/Universal/Dxe/RamFvbServicesRuntimeDxe/FwBlockService.c b/Platform/RiscV/SiFive/U500Pkg/Universal/Dxe/RamFvbServicesRuntimeDxe/FwBlockService.c > new file mode 100644 > index 00000000..8b89d2e0 > --- /dev/null > +++ b/Platform/RiscV/SiFive/U500Pkg/Universal/Dxe/RamFvbServicesRuntimeDxe/FwBlockService.c > @@ -0,0 +1,1123 @@ > +/**@file > + > + Copyright (c) 2019, Hewlett Packard Enterprise Development LP. All rights reserved.
> + Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
> + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > + Module Name: > + > + FWBlockService.c > + > + Abstract: > + > + Revision History > + > +**/ > + > +// > +// The protocols, PPI and GUID defintions for this module > +// > +#include > +#include > + > +// > +// The Library classes this module consumes > +// > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include "FwBlockService.h" > +#include "RamFlash.h" > + > +#define EFI_FVB2_STATUS \ > + (EFI_FVB2_READ_STATUS | EFI_FVB2_WRITE_STATUS | EFI_FVB2_LOCK_STATUS) > + > +ESAL_FWB_GLOBAL *mFvbModuleGlobal; > + > +FV_MEMMAP_DEVICE_PATH mFvMemmapDevicePathTemplate = { > + { > + { > + HARDWARE_DEVICE_PATH, > + HW_MEMMAP_DP, > + { > + (UINT8)(sizeof (MEMMAP_DEVICE_PATH)), > + (UINT8)(sizeof (MEMMAP_DEVICE_PATH) >> 8) > + } > + }, > + EfiMemoryMappedIO, > + (EFI_PHYSICAL_ADDRESS) 0, > + (EFI_PHYSICAL_ADDRESS) 0, > + }, > + { > + END_DEVICE_PATH_TYPE, > + END_ENTIRE_DEVICE_PATH_SUBTYPE, > + { > + END_DEVICE_PATH_LENGTH, > + 0 > + } > + } > +}; > + > +FV_PIWG_DEVICE_PATH mFvPIWGDevicePathTemplate = { > + { > + { > + MEDIA_DEVICE_PATH, > + MEDIA_PIWG_FW_VOL_DP, > + { > + (UINT8)(sizeof (MEDIA_FW_VOL_DEVICE_PATH)), > + (UINT8)(sizeof (MEDIA_FW_VOL_DEVICE_PATH) >> 8) > + } > + }, > + { 0 } > + }, > + { > + END_DEVICE_PATH_TYPE, > + END_ENTIRE_DEVICE_PATH_SUBTYPE, > + { > + END_DEVICE_PATH_LENGTH, > + 0 > + } > + } > +}; > + > +EFI_FW_VOL_BLOCK_DEVICE mFvbDeviceTemplate = { > + FVB_DEVICE_SIGNATURE, > + NULL, > + 0, > + { > + FvbProtocolGetAttributes, > + FvbProtocolSetAttributes, > + FvbProtocolGetPhysicalAddress, > + FvbProtocolGetBlockSize, > + FvbProtocolRead, > + FvbProtocolWrite, > + FvbProtocolEraseBlocks, > + NULL > + } > +}; > + > + > +EFI_STATUS > +GetFvbInstance ( > + IN UINTN Instance, > + IN ESAL_FWB_GLOBAL *Global, > + OUT EFI_FW_VOL_INSTANCE **FwhInstance > + ) > +/*++ > + > + Routine Description: > + Retrieves the physical address of a memory mapped FV > + > + Arguments: > + Instance - The FV instance whose base address is going to be > + returned > + Global - Pointer to ESAL_FWB_GLOBAL that contains all > + instance data > + FwhInstance - The EFI_FW_VOL_INSTANCE fimrware instance structure > + > + Returns: > + EFI_SUCCESS - Successfully returns > + EFI_INVALID_PARAMETER - Instance not found > + > +--*/ > +{ > + EFI_FW_VOL_INSTANCE *FwhRecord; > + > + *FwhInstance = NULL; > + if (Instance >= Global->NumFv) { > + return EFI_INVALID_PARAMETER; > + } > + // > + // Find the right instance of the FVB private data > + // > + FwhRecord = Global->FvInstance; > + while (Instance > 0) { > + FwhRecord = (EFI_FW_VOL_INSTANCE *) > + ( > + (UINTN) ((UINT8 *) FwhRecord) + FwhRecord->VolumeHeader.HeaderLength + Please don't cast to UINT8 * to get around integer arithmetic, just cast to UINTN from the start. > + (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER)) > + ); > + Instance--; > + } > + > + *FwhInstance = FwhRecord; > + > + return EFI_SUCCESS; > +} > + > +EFI_STATUS > +FvbGetPhysicalAddress ( > + IN UINTN Instance, > + OUT EFI_PHYSICAL_ADDRESS *Address, > + IN ESAL_FWB_GLOBAL *Global > + ) > +/*++ > + > + Routine Description: > + Retrieves the physical address of a memory mapped FV > + > + Arguments: > + Instance - The FV instance whose base address is going to be > + returned > + Address - Pointer to a caller allocated EFI_PHYSICAL_ADDRESS > + that on successful return, contains the base > + address of the firmware volume. > + Global - Pointer to ESAL_FWB_GLOBAL that contains all > + instance data > + > + Returns: > + EFI_SUCCESS - Successfully returns > + EFI_INVALID_PARAMETER - Instance not found > + > +--*/ > +{ > + EFI_FW_VOL_INSTANCE *FwhInstance; > + EFI_STATUS Status; > + > + // > + // Find the right instance of the FVB private data > + // > + Status = GetFvbInstance (Instance, Global, &FwhInstance); > + ASSERT_EFI_ERROR (Status); > + *Address = FwhInstance->FvBase; > + > + return EFI_SUCCESS; > +} > + > +EFI_STATUS > +FvbGetVolumeAttributes ( > + IN UINTN Instance, > + OUT EFI_FVB_ATTRIBUTES_2 *Attributes, > + IN ESAL_FWB_GLOBAL *Global > + ) > +/*++ > + > + Routine Description: > + Retrieves attributes, insures positive polarity of attribute bits, returns > + resulting attributes in output parameter > + > + Arguments: > + Instance - The FV instance whose attributes is going to be > + returned > + Attributes - Output buffer which contains attributes > + Global - Pointer to ESAL_FWB_GLOBAL that contains all > + instance data > + > + Returns: > + EFI_SUCCESS - Successfully returns > + EFI_INVALID_PARAMETER - Instance not found > + > +--*/ > +{ > + EFI_FW_VOL_INSTANCE *FwhInstance; > + EFI_STATUS Status; > + > + // > + // Find the right instance of the FVB private data > + // > + Status = GetFvbInstance (Instance, Global, &FwhInstance); > + ASSERT_EFI_ERROR (Status); > + *Attributes = FwhInstance->VolumeHeader.Attributes; > + > + return EFI_SUCCESS; > +} > + > +EFI_STATUS > +FvbGetLbaAddress ( > + IN UINTN Instance, > + IN EFI_LBA Lba, > + OUT UINTN *LbaAddress, > + OUT UINTN *LbaLength, > + OUT UINTN *NumOfBlocks, > + IN ESAL_FWB_GLOBAL *Global > + ) > +/*++ > + > + Routine Description: > + Retrieves the starting address of an LBA in an FV > + > + Arguments: > + Instance - The FV instance which the Lba belongs to > + Lba - The logical block address > + LbaAddress - On output, contains the physical starting address > + of the Lba > + LbaLength - On output, contains the length of the block > + NumOfBlocks - A 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 > + Global - Pointer to ESAL_FWB_GLOBAL that contains all > + instance data > + > + Returns: > + EFI_SUCCESS - Successfully returns > + EFI_INVALID_PARAMETER - Instance not found > + > +--*/ > +{ > + UINT32 NumBlocks; > + UINT32 BlockLength; > + UINTN Offset; > + EFI_LBA StartLba; > + EFI_LBA NextLba; > + EFI_FW_VOL_INSTANCE *FwhInstance; > + EFI_FV_BLOCK_MAP_ENTRY *BlockMap; > + EFI_STATUS Status; > + > + // > + // Find the right instance of the FVB private data > + // > + Status = GetFvbInstance (Instance, Global, &FwhInstance); > + ASSERT_EFI_ERROR (Status); > + > + StartLba = 0; > + Offset = 0; > + BlockMap = &(FwhInstance->VolumeHeader.BlockMap[0]); > + > + // > + // Parse the blockmap of the FV to find which map entry the Lba belongs to > + // > + while (TRUE) { > + NumBlocks = BlockMap->NumBlocks; > + BlockLength = BlockMap->Length; > + > + if (NumBlocks == 0 || BlockLength == 0) { > + return EFI_INVALID_PARAMETER; > + } > + > + NextLba = StartLba + NumBlocks; > + > + // > + // The map entry found > + // > + if (Lba >= StartLba && Lba < NextLba) { > + Offset = Offset + (UINTN) MultU64x32 ((Lba - StartLba), BlockLength); > + if (LbaAddress != NULL) { > + *LbaAddress = FwhInstance->FvBase + Offset; > + } > + > + if (LbaLength != NULL) { > + *LbaLength = BlockLength; > + } > + > + if (NumOfBlocks != NULL) { > + *NumOfBlocks = (UINTN) (NextLba - Lba); > + } > + > + return EFI_SUCCESS; > + } > + > + StartLba = NextLba; > + Offset = Offset + NumBlocks * BlockLength; > + BlockMap++; > + } > +} > + > +EFI_STATUS > +FvbSetVolumeAttributes ( > + IN UINTN Instance, > + IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes, > + IN ESAL_FWB_GLOBAL *Global > + ) > +/*++ > + > + Routine Description: > + Modifies the current settings of the firmware volume according to the > + input parameter, and returns the new setting of the volume > + > + Arguments: > + Instance - The FV instance whose attributes is going to be > + modified > + Attributes - On input, it is a pointer to EFI_FVB_ATTRIBUTES_2 > + containing the desired firmware volume settings. > + On successful return, it contains the new settings > + of the firmware volume > + Global - Pointer to ESAL_FWB_GLOBAL that contains all > + instance data > + > + Returns: > + EFI_SUCCESS - Successfully returns > + EFI_ACCESS_DENIED - The volume setting is locked and cannot be modified > + EFI_INVALID_PARAMETER - Instance not found, or The attributes requested are > + in conflict with the capabilities as declared in > + the firmware volume header > + > +--*/ > +{ > + EFI_FW_VOL_INSTANCE *FwhInstance; > + EFI_FVB_ATTRIBUTES_2 OldAttributes; > + EFI_FVB_ATTRIBUTES_2 *AttribPtr; > + UINT32 Capabilities; > + UINT32 OldStatus; > + UINT32 NewStatus; > + EFI_STATUS Status; > + EFI_FVB_ATTRIBUTES_2 UnchangedAttributes; > + > + // > + // Find the right instance of the FVB private data > + // > + Status = GetFvbInstance (Instance, Global, &FwhInstance); > + ASSERT_EFI_ERROR (Status); > + > + AttribPtr = > + (EFI_FVB_ATTRIBUTES_2 *) &(FwhInstance->VolumeHeader.Attributes); > + OldAttributes = *AttribPtr; > + Capabilities = OldAttributes & (EFI_FVB2_READ_DISABLED_CAP | \ > + EFI_FVB2_READ_ENABLED_CAP | \ > + EFI_FVB2_WRITE_DISABLED_CAP | \ > + EFI_FVB2_WRITE_ENABLED_CAP | \ > + EFI_FVB2_LOCK_CAP \ > + ); > + OldStatus = OldAttributes & EFI_FVB2_STATUS; > + NewStatus = *Attributes & EFI_FVB2_STATUS; > + > + UnchangedAttributes = EFI_FVB2_READ_DISABLED_CAP | \ > + EFI_FVB2_READ_ENABLED_CAP | \ > + EFI_FVB2_WRITE_DISABLED_CAP | \ > + EFI_FVB2_WRITE_ENABLED_CAP | \ > + EFI_FVB2_LOCK_CAP | \ > + EFI_FVB2_STICKY_WRITE | \ > + EFI_FVB2_MEMORY_MAPPED | \ > + EFI_FVB2_ERASE_POLARITY | \ > + EFI_FVB2_READ_LOCK_CAP | \ > + EFI_FVB2_WRITE_LOCK_CAP | \ > + EFI_FVB2_ALIGNMENT; > + > + // > + // Some attributes of FV is read only can *not* be set > + // > + if ((OldAttributes & UnchangedAttributes) ^ > + (*Attributes & UnchangedAttributes)) { > + return EFI_INVALID_PARAMETER; > + } > + // > + // If firmware volume is locked, no status bit can be updated > + // > + if (OldAttributes & EFI_FVB2_LOCK_STATUS) { > + if (OldStatus ^ NewStatus) { > + return EFI_ACCESS_DENIED; > + } > + } > + // > + // Test read disable > + // > + if ((Capabilities & EFI_FVB2_READ_DISABLED_CAP) == 0) { > + if ((NewStatus & EFI_FVB2_READ_STATUS) == 0) { > + return EFI_INVALID_PARAMETER; > + } > + } > + // > + // Test read enable > + // > + if ((Capabilities & EFI_FVB2_READ_ENABLED_CAP) == 0) { > + if (NewStatus & EFI_FVB2_READ_STATUS) { > + return EFI_INVALID_PARAMETER; > + } > + } > + // > + // Test write disable > + // > + if ((Capabilities & EFI_FVB2_WRITE_DISABLED_CAP) == 0) { > + if ((NewStatus & EFI_FVB2_WRITE_STATUS) == 0) { > + return EFI_INVALID_PARAMETER; > + } > + } > + // > + // Test write enable > + // > + if ((Capabilities & EFI_FVB2_WRITE_ENABLED_CAP) == 0) { > + if (NewStatus & EFI_FVB2_WRITE_STATUS) { > + return EFI_INVALID_PARAMETER; > + } > + } > + // > + // Test lock > + // > + if ((Capabilities & EFI_FVB2_LOCK_CAP) == 0) { > + if (NewStatus & EFI_FVB2_LOCK_STATUS) { > + return EFI_INVALID_PARAMETER; > + } > + } > + > + *AttribPtr = (*AttribPtr) & (0xFFFFFFFF & (~EFI_FVB2_STATUS)); > + *AttribPtr = (*AttribPtr) | NewStatus; > + *Attributes = *AttribPtr; > + > + return EFI_SUCCESS; > +} > + > +// > +// FVB protocol APIs > +// > +EFI_STATUS > +EFIAPI > +FvbProtocolGetPhysicalAddress ( > + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, > + OUT EFI_PHYSICAL_ADDRESS *Address > + ) > +/*++ > + > + Routine Description: > + > + Retrieves the physical address of the device. > + > + Arguments: > + > + This - Calling context > + Address - Output buffer containing the address. > + > + Returns: > + EFI_SUCCESS - Successfully returns > + > +--*/ > +{ > + EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; > + > + FvbDevice = FVB_DEVICE_FROM_THIS (This); > + > + return FvbGetPhysicalAddress (FvbDevice->Instance, Address, > + mFvbModuleGlobal); > +} > + > +EFI_STATUS > +EFIAPI > +FvbProtocolGetBlockSize ( > + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, > + IN CONST EFI_LBA Lba, > + OUT UINTN *BlockSize, > + OUT UINTN *NumOfBlocks > + ) > +/*++ > + > + Routine Description: > + Retrieve the size of a logical block > + > + Arguments: > + This - Calling context > + Lba - Indicates which block to return the size for. > + BlockSize - A pointer to a caller allocated UINTN in which > + the size of the block is returned > + NumOfBlocks - a 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 > + > + Returns: > + EFI_SUCCESS - The firmware volume was read successfully and > + contents are in Buffer > + > +--*/ > +{ > + EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; > + > + FvbDevice = FVB_DEVICE_FROM_THIS (This); > + > + return FvbGetLbaAddress ( > + FvbDevice->Instance, > + Lba, > + NULL, > + BlockSize, > + NumOfBlocks, > + mFvbModuleGlobal > + ); > +} > + > +EFI_STATUS > +EFIAPI > +FvbProtocolGetAttributes ( > + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, > + OUT EFI_FVB_ATTRIBUTES_2 *Attributes > + ) > +/*++ > + > + Routine Description: > + Retrieves Volume attributes. No polarity translations are done. > + > + Arguments: > + This - Calling context > + Attributes - output buffer which contains attributes > + > + Returns: > + EFI_SUCCESS - Successfully returns > + > +--*/ > +{ > + EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; > + > + FvbDevice = FVB_DEVICE_FROM_THIS (This); > + > + return FvbGetVolumeAttributes (FvbDevice->Instance, Attributes, > + mFvbModuleGlobal); > +} > + > +EFI_STATUS > +EFIAPI > +FvbProtocolSetAttributes ( > + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, > + IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes > + ) > +/*++ > + > + Routine Description: > + Sets Volume attributes. No polarity translations are done. > + > + Arguments: > + This - Calling context > + Attributes - output buffer which contains attributes > + > + Returns: > + EFI_SUCCESS - Successfully returns > + > +--*/ > +{ > + EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; > + > + FvbDevice = FVB_DEVICE_FROM_THIS (This); > + > + return FvbSetVolumeAttributes (FvbDevice->Instance, Attributes, > + mFvbModuleGlobal); > +} > + > +EFI_STATUS > +EFIAPI > +FvbProtocolEraseBlocks ( > + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, > + ... > + ) > +/*++ > + > + Routine Description: > + > + The EraseBlock() function erases one or more blocks as denoted by the > + variable argument list. The entire parameter list of blocks must be > + verified prior to erasing any blocks. If a block is requested that does > + not exist within the associated firmware volume (it has a larger index than > + the last block of the firmware volume), the EraseBlock() function must > + return EFI_INVALID_PARAMETER without modifying the contents of the firmware > + volume. > + > + Arguments: > + This - Calling context > + ... - Starting LBA followed by Number of Lba to erase. > + a -1 to terminate the list. > + > + Returns: > + EFI_SUCCESS - The erase request was successfully completed > + EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state > + EFI_DEVICE_ERROR - The block device is not functioning correctly and > + could not be written. Firmware device may have been > + partially erased > + > +--*/ > +{ > + EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; > + EFI_FW_VOL_INSTANCE *FwhInstance; > + UINTN NumOfBlocks; > + VA_LIST args; > + EFI_LBA StartingLba; > + UINTN NumOfLba; > + EFI_STATUS Status; > + > + FvbDevice = FVB_DEVICE_FROM_THIS (This); > + > + Status = GetFvbInstance (FvbDevice->Instance, mFvbModuleGlobal, > + &FwhInstance); > + ASSERT_EFI_ERROR (Status); > + > + NumOfBlocks = FwhInstance->NumOfBlocks; > + > + VA_START (args, This); > + > + do { > + StartingLba = VA_ARG (args, EFI_LBA); > + if (StartingLba == EFI_LBA_LIST_TERMINATOR) { > + break; > + } > + > + NumOfLba = VA_ARG (args, UINT32); > + > + // > + // Check input parameters > + // > + if ((NumOfLba == 0) || ((StartingLba + NumOfLba) > NumOfBlocks)) { > + VA_END (args); > + return EFI_INVALID_PARAMETER; > + } > + } while (1); > + > + VA_END (args); > + > + VA_START (args, This); > + do { > + StartingLba = VA_ARG (args, EFI_LBA); > + if (StartingLba == EFI_LBA_LIST_TERMINATOR) { > + break; > + } > + > + NumOfLba = VA_ARG (args, UINT32); > + > + while (NumOfLba > 0) { > + Status = RamFlashEraseBlock (StartingLba); > + if (EFI_ERROR (Status)) { > + VA_END (args); > + return Status; > + } > + > + StartingLba++; > + NumOfLba--; > + } > + > + } while (1); > + > + VA_END (args); > + > + return EFI_SUCCESS; > +} > + > +EFI_STATUS > +EFIAPI > +FvbProtocolWrite ( > + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, > + IN EFI_LBA Lba, > + IN UINTN Offset, > + IN OUT UINTN *NumBytes, > + IN UINT8 *Buffer > + ) Urgh, please move prototype below document comment - throughout. > +/*++ > + > + Routine Description: > + > + Writes data beginning at Lba:Offset from FV. The write terminates either > + when *NumBytes of data have been written, or when a block boundary is > + reached. *NumBytes is updated to reflect the actual number of bytes > + written. The write opertion does not include erase. This routine will > + attempt to write only the specified bytes. If the writes do not stick, > + it will return an error. > + > + Arguments: > + This - Calling context > + Lba - Block in which to begin write > + Offset - Offset in the block at which to begin write > + NumBytes - On input, indicates the requested write size. On > + output, indicates the actual number of bytes > + written > + Buffer - Buffer containing source data for the write. > + > + Returns: > + EFI_SUCCESS - The firmware volume was written successfully > + EFI_BAD_BUFFER_SIZE - Write attempted across a LBA boundary. On output, > + NumBytes contains the total number of bytes > + actually written > + EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state > + EFI_DEVICE_ERROR - The block device is not functioning correctly and > + could not be written > + EFI_INVALID_PARAMETER - NumBytes or Buffer are NULL > + > +--*/ > +{ > + return RamFlashWrite ((EFI_LBA)Lba, (UINTN)Offset, NumBytes, > + (UINT8 *)Buffer); Buffer is a UINT8 *, why the cast? > +} > + > +EFI_STATUS > +EFIAPI > +FvbProtocolRead ( > + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, > + IN CONST EFI_LBA Lba, > + IN CONST UINTN Offset, > + IN OUT UINTN *NumBytes, > + IN UINT8 *Buffer > + ) > +/*++ > + > + Routine Description: > + > + Reads data beginning at Lba:Offset from FV. The Read terminates either > + when *NumBytes of data have been read, or when a block boundary is > + reached. *NumBytes is updated to reflect the actual number of bytes > + written. The write opertion does not include erase. This routine will > + attempt to write only the specified bytes. If the writes do not stick, > + it will return an error. > + > + Arguments: > + This - Calling context > + Lba - Block in which to begin Read > + Offset - Offset in the block at which to begin Read > + NumBytes - On input, indicates the requested write size. On > + output, indicates the actual number of bytes Read > + Buffer - Buffer containing source data for the Read. > + > + Returns: > + EFI_SUCCESS - The firmware volume was read successfully and > + contents are in Buffer > + EFI_BAD_BUFFER_SIZE - Read attempted across a LBA boundary. On output, > + NumBytes contains the total number of bytes > + returned in Buffer > + EFI_ACCESS_DENIED - The firmware volume is in the ReadDisabled state > + EFI_DEVICE_ERROR - The block device is not functioning correctly and > + could not be read > + EFI_INVALID_PARAMETER - NumBytes or Buffer are NULL > + > +--*/ > +{ > + return RamFlashRead ((EFI_LBA)Lba, (UINTN)Offset, NumBytes, > + (UINT8 *)Buffer); Buffer is already a UINT8 *, why the cast? > +} > + > +EFI_STATUS > +ValidateFvHeader ( > + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader > + ) > +/*++ > + > + Routine Description: > + Check the integrity of firmware volume header > + > + Arguments: > + FwVolHeader - A pointer to a firmware volume header > + > + Returns: > + EFI_SUCCESS - The firmware volume is consistent > + EFI_NOT_FOUND - The firmware volume has corrupted. So it is not an > + FV > + > +--*/ > +{ > + UINT16 Checksum; > + > + // > + // 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 == ((UINTN) -1)) || > + ((FwVolHeader->HeaderLength & 0x01) != 0) > + ) { > + return EFI_NOT_FOUND; > + } > + > + // > + // Verify the header checksum > + // > + > + Checksum = CalculateSum16 ((UINT16 *) FwVolHeader, > + FwVolHeader->HeaderLength); > + if (Checksum != 0) { > + UINT16 Expected; > + > + Expected = > + (UINT16) (((UINTN) FwVolHeader->Checksum + 0x10000 - Checksum) & 0xffff); > + > + DEBUG ((DEBUG_INFO, "FV@%p Checksum is 0x%x, expected 0x%x\n", > + FwVolHeader, FwVolHeader->Checksum, Expected)); > + return EFI_NOT_FOUND; > + } > + > + return EFI_SUCCESS; > +} > + > +STATIC > +EFI_STATUS > +MarkMemoryRangeForRuntimeAccess ( > + EFI_PHYSICAL_ADDRESS BaseAddress, > + UINTN Length > + ) > +{ > + EFI_STATUS Status; > + > + // > + // Mark flash region as runtime memory > + // > + Status = gDS->RemoveMemorySpace ( > + BaseAddress, > + Length > + ); > + > + Status = gDS->AddMemorySpace ( > + EfiGcdMemoryTypeSystemMemory, > + BaseAddress, > + Length, > + EFI_MEMORY_UC | EFI_MEMORY_RUNTIME > + ); > + ASSERT_EFI_ERROR (Status); > + > + Status = gBS->AllocatePages ( > + AllocateAddress, > + EfiRuntimeServicesData, > + EFI_SIZE_TO_PAGES (Length), > + &BaseAddress > + ); > + ASSERT_EFI_ERROR (Status); > + > + return Status; > +} > + > +STATIC > +EFI_STATUS > +InitializeVariableFvHeader ( > + VOID > + ) > +{ > + EFI_STATUS Status; > + EFI_FIRMWARE_VOLUME_HEADER *GoodFwVolHeader; > + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; > + UINTN Length; > + UINTN WriteLength; > + UINTN BlockSize; > + > + FwVolHeader = > + (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) > + PcdGet32 (PcdPlatformFlashNvStorageVariableBase); > + > + Length = > + (FixedPcdGet32 (PcdFlashNvStorageVariableSize) + > + FixedPcdGet32 (PcdFlashNvStorageFtwWorkingSize) + > + FixedPcdGet32 (PcdFlashNvStorageFtwSpareSize)); > + > + BlockSize = PcdGet32 (PcdVariableFdBlockSize); > + > + Status = ValidateFvHeader (FwVolHeader); > + if (!EFI_ERROR (Status)) { > + DEBUG ((DEBUG_INFO, "ValidateFvHeader() return ok\n")); > + if (FwVolHeader->FvLength != Length || > + FwVolHeader->BlockMap[0].Length != BlockSize) { > + Status = EFI_VOLUME_CORRUPTED; > + DEBUG ((DEBUG_INFO, "FwVolHeader->FvLength(%x) != Length(%x) || FwVolHeader->BlockMap[0].Length(%x) != BlockSize(%x)\n", FwVolHeader->FvLength, Length, FwVolHeader->BlockMap[0].Length, BlockSize)); > + } > + } > + else { > + DEBUG ((DEBUG_INFO, "ValidateFvHeader() return failed\n")); > + } > + if (EFI_ERROR (Status)) { > + UINTN Offset; > + UINTN Start; > + > + DEBUG ((DEBUG_INFO, > + "Variable FV header is not valid. It will be reinitialized.\n")); > + > + // > + // Get FvbInfo to provide in FwhInstance. > + // > + Status = GetFvbInfo (Length, &GoodFwVolHeader); > + ASSERT (!EFI_ERROR (Status)); > + > + Start = (UINTN)(UINT8*) FwVolHeader - PcdGet32 (PcdVariableFdBaseAddress); > + ASSERT (Start % BlockSize == 0 && Length % BlockSize == 0); > + ASSERT (GoodFwVolHeader->HeaderLength <= BlockSize); > + > + // > + // Erase all the blocks > + // > + for (Offset = Start; Offset < Start + Length; Offset += BlockSize) { > + Status = RamFlashEraseBlock (Offset / BlockSize); > + ASSERT_EFI_ERROR (Status); > + } > + > + // > + // Write good FV header > + // > + WriteLength = GoodFwVolHeader->HeaderLength; > + Status = RamFlashWrite ( > + Start / BlockSize, > + 0, > + &WriteLength, > + (UINT8 *) GoodFwVolHeader); > + ASSERT_EFI_ERROR (Status); > + ASSERT (WriteLength == GoodFwVolHeader->HeaderLength); > + } > + > + return Status; > +} > + > +EFI_STATUS > +EFIAPI > +FvbInitialize ( > + IN EFI_HANDLE ImageHandle, > + IN EFI_SYSTEM_TABLE *SystemTable > + ) > +/*++ > + > + Routine Description: > + This function does common initialization for FVB services > + > + Arguments: > + > + Returns: > + > +--*/ > +{ > + EFI_STATUS Status; > + EFI_FW_VOL_INSTANCE *FwhInstance; > + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; > + UINT32 BufferSize; > + EFI_FV_BLOCK_MAP_ENTRY *PtrBlockMapEntry; > + EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; > + UINT32 MaxLbaSize; > + EFI_PHYSICAL_ADDRESS BaseAddress; > + UINTN Length; > + UINTN NumOfBlocks; > + > + if (EFI_ERROR (RamFlashInitialize ())) { > + // > + // Return an error so image will be unloaded > + // > + DEBUG ((DEBUG_INFO, > + "RAM flash was not detected. Writable FVB is not being installed.\n")); > + return EFI_WRITE_PROTECTED; > + } > + > + // > + // Allocate runtime services data for global variable, which contains > + // the private data of all firmware volume block instances > + // > + mFvbModuleGlobal = AllocateRuntimePool (sizeof (ESAL_FWB_GLOBAL)); > + ASSERT (mFvbModuleGlobal != NULL); > + > + BaseAddress = (UINTN) PcdGet32 (PcdVariableFdBaseAddress); > + Length = PcdGet32 (PcdVariableFdSize); > + DEBUG ((DEBUG_INFO, "FvbInitialize(): BaseAddress: 0x%lx Length:0x%x\n", BaseAddress, Length)); > + Status = InitializeVariableFvHeader (); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_INFO, > + "RAM Flash: Unable to initialize variable FV header\n")); > + return EFI_WRITE_PROTECTED; > + } > + > + FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) BaseAddress; > + Status = ValidateFvHeader (FwVolHeader); > + if (EFI_ERROR (Status)) { > + // > + // Get FvbInfo > + // > + DEBUG ((DEBUG_INFO, "FvbInitialize(): ValidateFvHeader() return error(%r)\n", Status)); > + > + Status = GetFvbInfo (Length, &FwVolHeader); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_INFO, "FvbInitialize(): GetFvbInfo (Length, &FwVolHeader) return error(%r)\n", Status)); > + return EFI_WRITE_PROTECTED; > + } > + } > + > + BufferSize = (sizeof (EFI_FW_VOL_INSTANCE) + > + FwVolHeader->HeaderLength - > + sizeof (EFI_FIRMWARE_VOLUME_HEADER) > + ); > + mFvbModuleGlobal->FvInstance = AllocateRuntimePool (BufferSize); > + ASSERT (mFvbModuleGlobal->FvInstance != NULL); > + > + FwhInstance = mFvbModuleGlobal->FvInstance; > + > + mFvbModuleGlobal->NumFv = 0; > + MaxLbaSize = 0; > + > + FwVolHeader = > + (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) > + PcdGet32 (PcdPlatformFlashNvStorageVariableBase); > + > + FwhInstance->FvBase = (UINTN) BaseAddress; > + > + CopyMem ((UINTN *) &(FwhInstance->VolumeHeader), (UINTN *) FwVolHeader, > + FwVolHeader->HeaderLength); > + FwVolHeader = &(FwhInstance->VolumeHeader); > + > + NumOfBlocks = 0; > + > + for (PtrBlockMapEntry = FwVolHeader->BlockMap; > + PtrBlockMapEntry->NumBlocks != 0; > + PtrBlockMapEntry++) { > + // > + // Get the maximum size of a block. > + // > + if (MaxLbaSize < PtrBlockMapEntry->Length) { > + MaxLbaSize = PtrBlockMapEntry->Length; > + } > + > + NumOfBlocks = NumOfBlocks + PtrBlockMapEntry->NumBlocks; > + } > + > + // > + // The total number of blocks in the FV. > + // > + FwhInstance->NumOfBlocks = NumOfBlocks; > + > + // > + // Add a FVB Protocol Instance > + // > + FvbDevice = AllocateRuntimePool (sizeof (EFI_FW_VOL_BLOCK_DEVICE)); > + ASSERT (FvbDevice != NULL); > + > + CopyMem (FvbDevice, &mFvbDeviceTemplate, sizeof (EFI_FW_VOL_BLOCK_DEVICE)); > + > + FvbDevice->Instance = mFvbModuleGlobal->NumFv; > + mFvbModuleGlobal->NumFv++; > + > + // > + // Set up the devicepath > + // > + if (FwVolHeader->ExtHeaderOffset == 0) { > + FV_MEMMAP_DEVICE_PATH *FvMemmapDevicePath; > + > + // > + // FV does not contains extension header, then produce MEMMAP_DEVICE_PATH > + // > + FvMemmapDevicePath = AllocateCopyPool (sizeof (FV_MEMMAP_DEVICE_PATH), > + &mFvMemmapDevicePathTemplate); > + FvMemmapDevicePath->MemMapDevPath.StartingAddress = BaseAddress; > + FvMemmapDevicePath->MemMapDevPath.EndingAddress = > + BaseAddress + FwVolHeader->FvLength - 1; > + FvbDevice->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)FvMemmapDevicePath; > + } else { > + FV_PIWG_DEVICE_PATH *FvPiwgDevicePath; > + > + FvPiwgDevicePath = AllocateCopyPool (sizeof (FV_PIWG_DEVICE_PATH), > + &mFvPIWGDevicePathTemplate); > + CopyGuid ( > + &FvPiwgDevicePath->FvDevPath.FvName, > + (GUID *)(UINTN)(BaseAddress + FwVolHeader->ExtHeaderOffset) > + ); > + FvbDevice->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)FvPiwgDevicePath; > + } > + > + // > + // Module type specific hook. > + // > + InstallProtocolInterfaces (FvbDevice); > + > + MarkMemoryRangeForRuntimeAccess (BaseAddress, Length); > + > + // > + // Set several PCD values to point to flash > + // > + PcdSet64 ( > + PcdFlashNvStorageVariableBase64, > + (UINTN) PcdGet32 (PcdPlatformFlashNvStorageVariableBase) > + ); > + PcdSet32 ( > + PcdFlashNvStorageFtwWorkingBase, > + PcdGet32 (PcdPlatformFlashNvStorageFtwWorkingBase) > + ); > + PcdSet32 ( > + PcdFlashNvStorageFtwSpareBase, > + PcdGet32 (PcdPlatformFlashNvStorageFtwSpareBase) > + ); > + > + FwhInstance = (EFI_FW_VOL_INSTANCE *) > + ( > + (UINTN) ((UINT8 *) FwhInstance) + FwVolHeader->HeaderLength + Please don't cast to UINT8 * to get around pointer arithmetic - cast it directly to UINTN. > + (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER)) > + ); > + > + // > + // Module type specific hook. > + // > + InstallVirtualAddressChangeHandler (); > + return EFI_SUCCESS; > +} > diff --git a/Platform/RiscV/SiFive/U500Pkg/Universal/Dxe/RamFvbServicesRuntimeDxe/FwBlockService.h b/Platform/RiscV/SiFive/U500Pkg/Universal/Dxe/RamFvbServicesRuntimeDxe/FwBlockService.h > new file mode 100644 > index 00000000..a1aeb2c3 > --- /dev/null > +++ b/Platform/RiscV/SiFive/U500Pkg/Universal/Dxe/RamFvbServicesRuntimeDxe/FwBlockService.h > @@ -0,0 +1,187 @@ > +/**@file > + > + Copyright (c) 2019, Hewlett Packard Enterprise Development LP. All rights reserved.
> + Copyright (c) 2006, Intel Corporation. All rights reserved.
> + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > + Module Name: > + > + FwBlockService.h > + > + Abstract: > + > + Firmware volume block driver for Intel Firmware Hub (FWH) device > + > +**/ > + > +#ifndef _FW_BLOCK_SERVICE_H_ > +#define _FW_BLOCK_SERVICE_H_ Please drop leading _. > + > +typedef struct { > + UINTN FvBase; > + UINTN NumOfBlocks; > + EFI_FIRMWARE_VOLUME_HEADER VolumeHeader; > +} EFI_FW_VOL_INSTANCE; > + > +typedef struct { > + UINT32 NumFv; > + EFI_FW_VOL_INSTANCE *FvInstance; > +} ESAL_FWB_GLOBAL; > + > +extern ESAL_FWB_GLOBAL *mFvbModuleGlobal; > + > +// > +// Fvb Protocol instance data > +// > +#define FVB_DEVICE_FROM_THIS(a) CR (a, EFI_FW_VOL_BLOCK_DEVICE, \ > + FwVolBlockInstance, FVB_DEVICE_SIGNATURE) > + > +#define FVB_EXTEND_DEVICE_FROM_THIS(a) CR (a, EFI_FW_VOL_BLOCK_DEVICE, \ > + FvbExtension, FVB_DEVICE_SIGNATURE) > + > +#define FVB_DEVICE_SIGNATURE SIGNATURE_32 ('F', 'V', 'B', 'N') > + > +typedef struct { > + MEDIA_FW_VOL_DEVICE_PATH FvDevPath; > + EFI_DEVICE_PATH_PROTOCOL EndDevPath; > +} FV_PIWG_DEVICE_PATH; > + > +typedef struct { > + MEMMAP_DEVICE_PATH MemMapDevPath; > + EFI_DEVICE_PATH_PROTOCOL EndDevPath; > +} FV_MEMMAP_DEVICE_PATH; > + > +typedef struct { > + UINTN Signature; > + EFI_DEVICE_PATH_PROTOCOL *DevicePath; > + UINTN Instance; > + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL FwVolBlockInstance; > +} EFI_FW_VOL_BLOCK_DEVICE; > + > +EFI_STATUS > +GetFvbInfo ( > + IN UINT64 FvLength, > + OUT EFI_FIRMWARE_VOLUME_HEADER **FvbInfo > + ); > + > +EFI_STATUS > +FvbSetVolumeAttributes ( > + IN UINTN Instance, > + IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes, > + IN ESAL_FWB_GLOBAL *Global > + ); > + > +EFI_STATUS > +FvbGetVolumeAttributes ( > + IN UINTN Instance, > + OUT EFI_FVB_ATTRIBUTES_2 *Attributes, > + IN ESAL_FWB_GLOBAL *Global > + ); > + > +EFI_STATUS > +FvbGetPhysicalAddress ( > + IN UINTN Instance, > + OUT EFI_PHYSICAL_ADDRESS *Address, > + IN ESAL_FWB_GLOBAL *Global > + ); > + > +EFI_STATUS > +EFIAPI > +FvbInitialize ( > + IN EFI_HANDLE ImageHandle, > + IN EFI_SYSTEM_TABLE *SystemTable > + ); > + > + > +VOID > +EFIAPI > +FvbClassAddressChangeEvent ( > + IN EFI_EVENT Event, > + IN VOID *Context > + ); > + > +EFI_STATUS > +FvbGetLbaAddress ( > + IN UINTN Instance, > + IN EFI_LBA Lba, > + OUT UINTN *LbaAddress, > + OUT UINTN *LbaLength, > + OUT UINTN *NumOfBlocks, > + IN ESAL_FWB_GLOBAL *Global > + ); > + > +// > +// Protocol APIs > +// > +EFI_STATUS > +EFIAPI > +FvbProtocolGetAttributes ( > + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, > + OUT EFI_FVB_ATTRIBUTES_2 *Attributes > + ); > + > +EFI_STATUS > +EFIAPI > +FvbProtocolSetAttributes ( > + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, > + IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes > + ); > + > +EFI_STATUS > +EFIAPI > +FvbProtocolGetPhysicalAddress ( > + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, > + OUT EFI_PHYSICAL_ADDRESS *Address > + ); > + > +EFI_STATUS > +EFIAPI > +FvbProtocolGetBlockSize ( > + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, > + IN CONST EFI_LBA Lba, > + OUT UINTN *BlockSize, > + OUT UINTN *NumOfBlocks > + ); > + > +EFI_STATUS > +EFIAPI > +FvbProtocolRead ( > + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, > + IN CONST EFI_LBA Lba, > + IN CONST UINTN Offset, > + IN OUT UINTN *NumBytes, > + IN UINT8 *Buffer > + ); > + > +EFI_STATUS > +EFIAPI > +FvbProtocolWrite ( > + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, > + IN EFI_LBA Lba, > + IN UINTN Offset, > + IN OUT UINTN *NumBytes, > + IN UINT8 *Buffer > + ); > + > +EFI_STATUS > +EFIAPI > +FvbProtocolEraseBlocks ( > + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, > + ... > + ); > + > +// > +// The following functions have different implementations dependent on the > +// module type chosen for building this driver. > +// > +VOID > +InstallProtocolInterfaces ( > + IN EFI_FW_VOL_BLOCK_DEVICE *FvbDevice > + ); > + > +VOID > +InstallVirtualAddressChangeHandler ( > + VOID > + ); > +#endif > diff --git a/Platform/RiscV/SiFive/U500Pkg/Universal/Dxe/RamFvbServicesRuntimeDxe/FwBlockServiceDxe.c b/Platform/RiscV/SiFive/U500Pkg/Universal/Dxe/RamFvbServicesRuntimeDxe/FwBlockServiceDxe.c > new file mode 100644 > index 00000000..46112365 > --- /dev/null > +++ b/Platform/RiscV/SiFive/U500Pkg/Universal/Dxe/RamFvbServicesRuntimeDxe/FwBlockServiceDxe.c > @@ -0,0 +1,151 @@ > +/**@file > + Functions related to the Firmware Volume Block service whose > + implementation is specific to the runtime DXE driver build. > + > + Copyright (c) 2019, Hewlett Packard Enterprise Development LP. All rights reserved.
> + Copyright (C) 2015, Red Hat, Inc. > + Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
> + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include "FwBlockService.h" > +#include "RamFlash.h" > + > +VOID > +InstallProtocolInterfaces ( > + IN EFI_FW_VOL_BLOCK_DEVICE *FvbDevice > + ) > +{ > + EFI_STATUS Status; > + EFI_HANDLE FwbHandle; > + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *OldFwbInterface; > + > + // > + // Find a handle with a matching device path that has supports FW Block > + // protocol > + // > + Status = gBS->LocateDevicePath (&gEfiFirmwareVolumeBlockProtocolGuid, > + &FvbDevice->DevicePath, &FwbHandle); > + if (EFI_ERROR (Status)) { > + // > + // LocateDevicePath fails so install a new interface and device path > + // > + FwbHandle = NULL; > + DEBUG ((DEBUG_INFO, "Installing RAM FVB\n")); > + Status = gBS->InstallMultipleProtocolInterfaces ( > + &FwbHandle, > + &gEfiFirmwareVolumeBlockProtocolGuid, > + &FvbDevice->FwVolBlockInstance, > + &gEfiDevicePathProtocolGuid, > + FvbDevice->DevicePath, > + NULL > + ); > + ASSERT_EFI_ERROR (Status); > + } else if (IsDevicePathEnd (FvbDevice->DevicePath)) { > + // > + // Device already exists, so reinstall the FVB protocol > + // > + Status = gBS->HandleProtocol ( > + FwbHandle, > + &gEfiFirmwareVolumeBlockProtocolGuid, > + (VOID**)&OldFwbInterface > + ); > + ASSERT_EFI_ERROR (Status); > + > + DEBUG ((DEBUG_INFO, "Reinstalling FVB for Ram flash region\n")); > + Status = gBS->ReinstallProtocolInterface ( > + FwbHandle, > + &gEfiFirmwareVolumeBlockProtocolGuid, > + OldFwbInterface, > + &FvbDevice->FwVolBlockInstance > + ); > + ASSERT_EFI_ERROR (Status); > + } else { > + // > + // There was a FVB protocol on an End Device Path node > + // > + ASSERT (FALSE); > + } > +} > + > + > +STATIC > +VOID > +EFIAPI > +FvbVirtualAddressChangeEvent ( > + IN EFI_EVENT Event, > + IN VOID *Context > + ) > +/*++ > + > + Routine Description: > + > + Fixup internal data so that EFI and SAL can be call in virtual mode. > + Call the passed in Child Notify event and convert the mFvbModuleGlobal > + date items to there virtual address. > + > + Arguments: > + > + (Standard EFI notify event - EFI_EVENT_NOTIFY) > + > + Returns: > + > + None > + > +--*/ > +{ > + EFI_FW_VOL_INSTANCE *FwhInstance; > + UINTN Index; > + > + FwhInstance = mFvbModuleGlobal->FvInstance; > + EfiConvertPointer (0x0, (VOID **) &mFvbModuleGlobal->FvInstance); > + > + // > + // Convert the base address of all the instances > + // > + Index = 0; > + while (Index < mFvbModuleGlobal->NumFv) { > + EfiConvertPointer (0x0, (VOID **) &FwhInstance->FvBase); > + FwhInstance = (EFI_FW_VOL_INSTANCE *) > + ( > + (UINTN) ((UINT8 *) FwhInstance) + Please don't cast to UINT8 * to get around pointer arithmetic - cast it directly to UINTN. > + FwhInstance->VolumeHeader.HeaderLength + > + (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER)) > + ); > + Index++; > + } > + > + EfiConvertPointer (0x0, (VOID **) &mFvbModuleGlobal); > + RamFlashConvertPointers (); > +} > + > + > +VOID > +InstallVirtualAddressChangeHandler ( > + VOID > + ) > +{ > + EFI_STATUS Status; > + EFI_EVENT VirtualAddressChangeEvent; > + > + Status = gBS->CreateEventEx ( > + EVT_NOTIFY_SIGNAL, > + TPL_NOTIFY, > + FvbVirtualAddressChangeEvent, > + NULL, > + &gEfiEventVirtualAddressChangeGuid, > + &VirtualAddressChangeEvent > + ); > + ASSERT_EFI_ERROR (Status); > +} > diff --git a/Platform/RiscV/SiFive/U500Pkg/Universal/Dxe/RamFvbServicesRuntimeDxe/RamFlash.c b/Platform/RiscV/SiFive/U500Pkg/Universal/Dxe/RamFvbServicesRuntimeDxe/RamFlash.c > new file mode 100644 > index 00000000..6c3e613a > --- /dev/null > +++ b/Platform/RiscV/SiFive/U500Pkg/Universal/Dxe/RamFvbServicesRuntimeDxe/RamFlash.c > @@ -0,0 +1,144 @@ > +/** @file > + Copyright (c) 2019, Hewlett Packard Enterprise Development LP. All rights reserved.
> + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#include > +#include > +#include > + > +#include "RamFlash.h" > + > +UINT8 *mFlashBase; This appears to be set as UINT8 * only to avoid pointer arithmetic effects. Please don't do that. If there is no actual type that is suitable, please use VOID *. > + > +STATIC UINTN mFdBlockSize = 0; > +STATIC UINTN mFdBlockCount = 0; > + > +STATIC > +volatile UINT8* It would be VOLATILE, but I'm pretty sure this doesn't do what you expect it to do. > +RamFlashPtr ( > + IN EFI_LBA Lba, > + IN UINTN Offset > + ) > +{ > + return mFlashBase + ((UINTN)Lba * mFdBlockSize) + Offset; > +} > + > +/** > + Read from Ram Flash > + > + @param[in] Lba The starting logical block index to read from. > + @param[in] Offset Offset into the block at which to begin reading. > + @param[in] NumBytes On input, indicates the requested read size. On > + output, indicates the actual number of bytes read > + @param[in] Buffer Pointer to the buffer to read into. > + > +**/ > +EFI_STATUS > +RamFlashRead ( > + IN EFI_LBA Lba, > + IN UINTN Offset, > + IN UINTN *NumBytes, > + IN UINT8 *Buffer > + ) > +{ > + UINT8 *Ptr; > + > + // > + // Only write to the first 64k. We don't bother saving the FTW Spare > + // block into the flash memory. > + // > + if (Lba >= mFdBlockCount) { > + return EFI_INVALID_PARAMETER; > + } > + > + // > + // Get flash address > + // > + Ptr = (UINT8*) RamFlashPtr (Lba, Offset); > + > + CopyMem (Buffer, Ptr, *NumBytes); > + > + return EFI_SUCCESS; > +} > + > + > +/** > + Write to Ram Flash > + > + @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] NumBytes On input, indicates the requested write size. On > + output, indicates the actual number of bytes written > + @param[in] Buffer Pointer to the data to write. > + > +**/ > +EFI_STATUS > +RamFlashWrite ( > + IN EFI_LBA Lba, > + IN UINTN Offset, > + IN UINTN *NumBytes, > + IN UINT8 *Buffer > + ) > +{ > + volatile UINT8 *Ptr; I would much rather see the use of IoLib. > + UINTN Loop; > + > + // > + // Only write to the first 64k. We don't bother saving the FTW Spare > + // block into the flash memory. > + // > + if (Lba >= mFdBlockCount) { > + return EFI_INVALID_PARAMETER; > + } > + > + // > + // Program flash > + // > + Ptr = RamFlashPtr (Lba, Offset); > + for (Loop = 0; Loop < *NumBytes; Loop++) { > + *Ptr = Buffer[Loop]; > + Ptr++; > + } > + > + return EFI_SUCCESS; > +} > + > + > +/** > + Erase a Ram Flash block > + > + @param Lba The logical block index to erase. > + > +**/ > +EFI_STATUS > +RamFlashEraseBlock ( > + IN EFI_LBA Lba > + ) > +{ > + > + return EFI_SUCCESS; > +} > + > + > +/** > + Initializes Ram flash memory support > + > + @retval EFI_WRITE_PROTECTED The Ram flash device is not present. > + @retval EFI_SUCCESS The Ram flash device is supported. > + > +**/ > +EFI_STATUS > +RamFlashInitialize ( > + VOID > + ) > +{ > + mFlashBase = (UINT8*)(UINTN) PcdGet32 (PcdVariableFdBaseAddress); > + mFdBlockSize = PcdGet32 (PcdVariableFdBlockSize); > + ASSERT(PcdGet32 (PcdVariableFdSize) % mFdBlockSize == 0); > + mFdBlockCount = PcdGet32 (PcdVariableFdSize) / mFdBlockSize; > + > + return EFI_SUCCESS; > +} > diff --git a/Platform/RiscV/SiFive/U500Pkg/Universal/Dxe/RamFvbServicesRuntimeDxe/RamFlash.h b/Platform/RiscV/SiFive/U500Pkg/Universal/Dxe/RamFvbServicesRuntimeDxe/RamFlash.h > new file mode 100644 > index 00000000..008c795e > --- /dev/null > +++ b/Platform/RiscV/SiFive/U500Pkg/Universal/Dxe/RamFvbServicesRuntimeDxe/RamFlash.h > @@ -0,0 +1,85 @@ > +/** @file > + Ram flash device for EFI variable > + > + Copyright (c) 2019, Hewlett Packard Enterprise Development LP. All rights reserved.
> + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#ifndef _RAM_FLASH_H_ > +#define _RAM_FLASH_H_ Please drop leading _. > + > +#include > + > +extern UINT8 *mFlashBase; Please change also this extern declaration. / Leif > + > +/** > + Read from Ram Flash > + > + @param[in] Lba The starting logical block index to read from. > + @param[in] Offset Offset into the block at which to begin reading. > + @param[in] NumBytes On input, indicates the requested read size. On > + output, indicates the actual number of bytes read > + @param[in] Buffer Pointer to the buffer to read into. > + > +**/ > +EFI_STATUS > +RamFlashRead ( > + IN EFI_LBA Lba, > + IN UINTN Offset, > + IN UINTN *NumBytes, > + IN UINT8 *Buffer > + ); > + > + > +/** > + Write to Ram Flash > + > + @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] NumBytes On input, indicates the requested write size. On > + output, indicates the actual number of bytes written > + @param[in] Buffer Pointer to the data to write. > + > +**/ > +EFI_STATUS > +RamFlashWrite ( > + IN EFI_LBA Lba, > + IN UINTN Offset, > + IN UINTN *NumBytes, > + IN UINT8 *Buffer > + ); > + > + > +/** > + Erase a Ram Flash block > + > + @param Lba The logical block index to erase. > + > +**/ > +EFI_STATUS > +RamFlashEraseBlock ( > + IN EFI_LBA Lba > + ); > + > + > +/** > + Initializes Ram flash memory support > + > + @retval EFI_WRITE_PROTECTED The Ram flash device is not present. > + @retval EFI_SUCCESS The Ram flash device is supported. > + > +**/ > +EFI_STATUS > +RamFlashInitialize ( > + VOID > + ); > + > + > +VOID > +RamFlashConvertPointers ( > + VOID > + ); > + > +#endif > diff --git a/Platform/RiscV/SiFive/U500Pkg/Universal/Dxe/RamFvbServicesRuntimeDxe/RamFlashDxe.c b/Platform/RiscV/SiFive/U500Pkg/Universal/Dxe/RamFvbServicesRuntimeDxe/RamFlashDxe.c > new file mode 100644 > index 00000000..a9d48637 > --- /dev/null > +++ b/Platform/RiscV/SiFive/U500Pkg/Universal/Dxe/RamFvbServicesRuntimeDxe/RamFlashDxe.c > @@ -0,0 +1,20 @@ > +/** @file > + Ram flash device for EFI variable > + > + Copyright (c) 2019, Hewlett Packard Enterprise Development LP. All rights reserved.
> + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#include > + > +#include "RamFlash.h" > + > +VOID > +RamFlashConvertPointers ( > + VOID > + ) > +{ > + EfiConvertPointer (0x0, (VOID **) &mFlashBase); > +} > -- > 2.12.0.windows.1 > > > >