[edk2-devel] [edk2-platforms][PATCH v4 08/31] AmpereAltraPkg: Support UEFI non-volatile variable

Leif Lindholm leif at nuviainc.com
Tue Oct 26 12:21:23 UTC 2021


On Fri, Oct 22, 2021 at 13:17:46 +0700, Nhi Pham wrote:
> From: Vu Nguyen <vunguyen at os.amperecomputing.com>
> 
> This change supports storing the UEFI non-volatile varibles on the
> Flash through below modules:
> * FlashPei driver helps to restore the saved variables from
>   flash on each boot.
> * FlashFvbDxe driver provides the implementation for the
>   gEfiFirmwareVolumeBlock protocol
> 
> Cc: Thang Nguyen <thang at os.amperecomputing.com>
> Cc: Chuong Tran <chuong at os.amperecomputing.com>
> Cc: Phong Vo <phong at os.amperecomputing.com>
> Cc: Leif Lindholm <leif at nuviainc.com>
> Cc: Michael D Kinney <michael.d.kinney at intel.com>
> Cc: Ard Biesheuvel <ardb+tianocore at kernel.org>
> Cc: Nate DeSimone <nathaniel.l.desimone at intel.com>
> 
> Signed-off-by: Nhi Pham <nhi at os.amperecomputing.com>

Reviewed-by: Leif Lindholm <leif at nuviainc.com>

> ---
>  Silicon/Ampere/AmpereSiliconPkg/AmpereSiliconPkg.dec              |   5 +
>  Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc              |   6 +-
>  Platform/Ampere/JadePkg/Jade.dsc                                  |   5 +
>  Platform/Ampere/JadePkg/Jade.fdf                                  |  62 ++-
>  Silicon/Ampere/AmpereAltraPkg/Drivers/FlashFvbDxe/FlashFvbDxe.inf |  54 ++
>  Silicon/Ampere/AmpereAltraPkg/Drivers/FlashPei/FlashPei.inf       |  49 ++
>  Silicon/Ampere/AmpereAltraPkg/Drivers/FlashFvbDxe/FlashFvbDxe.c   | 525 ++++++++++++++++++++
>  Silicon/Ampere/AmpereAltraPkg/Drivers/FlashPei/FlashPei.c         | 125 +++++
>  8 files changed, 827 insertions(+), 4 deletions(-)
> 
> diff --git a/Silicon/Ampere/AmpereSiliconPkg/AmpereSiliconPkg.dec b/Silicon/Ampere/AmpereSiliconPkg/AmpereSiliconPkg.dec
> index 6ebdf7db0a57..c6827d0cad7e 100644
> --- a/Silicon/Ampere/AmpereSiliconPkg/AmpereSiliconPkg.dec
> +++ b/Silicon/Ampere/AmpereSiliconPkg/AmpereSiliconPkg.dec
> @@ -31,6 +31,11 @@ [Guids]
>  [Ppis]
>  
>  [PcdsFixedAtBuild]
> +  #
> +  # NVRAM
> +  #
> +  gAmpereTokenSpaceGuid.PcdPlatformConfigUuid|"C416535D-970B-41B9-859A-3CAF0FAF198C"|VOID*|0x00000010
> +
>    #
>    # SMpro PMpro Pcds
>    #
> diff --git a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc
> index cd982e987745..69bf00ee56c4 100644
> --- a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc
> +++ b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc
> @@ -523,8 +523,10 @@ [Components.common]
>    ArmPlatformPkg/PlatformPei/PlatformPeim.inf
>    Silicon/Ampere/AmpereAltraPkg/Drivers/ATFHobPei/ATFHobPeim.inf
>    ArmPlatformPkg/MemoryInitPei/MemoryInitPeim.inf
> +  Silicon/Ampere/AmpereAltraPkg/Drivers/FlashPei/FlashPei.inf
>    ArmPkg/Drivers/CpuPei/CpuPei.inf
>    UefiCpuPkg/CpuIoPei/CpuIoPei.inf
> +  MdeModulePkg/Universal/FaultTolerantWritePei/FaultTolerantWritePei.inf
>    MdeModulePkg/Universal/Variable/Pei/VariablePei.inf
>    MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf {
>      <LibraryClasses>
> @@ -578,9 +580,9 @@ [Components.common]
>    #
>    # Environment Variables Protocol
>    #
> +  Silicon/Ampere/AmpereAltraPkg/Drivers/FlashFvbDxe/FlashFvbDxe.inf
> +  MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf
>    MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf {
> -    <PcdsFixedAtBuild>
> -      gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvModeEnable|TRUE
>      <LibraryClasses>
>        BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
>        TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf
> diff --git a/Platform/Ampere/JadePkg/Jade.dsc b/Platform/Ampere/JadePkg/Jade.dsc
> index 7b70c5d6b5fb..0dd30dc14841 100644
> --- a/Platform/Ampere/JadePkg/Jade.dsc
> +++ b/Platform/Ampere/JadePkg/Jade.dsc
> @@ -51,6 +51,7 @@ [Defines]
>    DEFINE FIRMWARE_VER            = 0.01.001
>    DEFINE SECURE_BOOT_ENABLE      = FALSE
>    DEFINE INCLUDE_TFTP_COMMAND    = TRUE
> +  DEFINE PLATFORM_CONFIG_UUID    = 84BC921F-9D4A-4D1D-A1A1-1AE13EDD07E5
>  
>    #
>    # Network definition
> @@ -83,6 +84,10 @@ [LibraryClasses]
>  ################################################################################
>  [PcdsFeatureFlag.common]
>  [PcdsFixedAtBuild.common]
> +  #
> +  # Platform config UUID
> +  #
> +  gAmpereTokenSpaceGuid.PcdPlatformConfigUuid|"$(PLATFORM_CONFIG_UUID)"
>  
>  !if $(SECURE_BOOT_ENABLE) == TRUE
>    # Override the default values from SecurityPkg to ensure images
> diff --git a/Platform/Ampere/JadePkg/Jade.fdf b/Platform/Ampere/JadePkg/Jade.fdf
> index bbee31c3fc99..5727d8706240 100644
> --- a/Platform/Ampere/JadePkg/Jade.fdf
> +++ b/Platform/Ampere/JadePkg/Jade.fdf
> @@ -26,7 +26,7 @@ [FD.BL33_JADE_UEFI]
>  ErasePolarity = 1
>  
>  # This one is tricky, it must be: BlockSize * NumBlocks = Size
> -BlockSize     = 0x10000
> +BlockSize     = 0x10000|gAmpereTokenSpaceGuid.PcdFvBlockSize
>  NumBlocks     = 0x7C
>  
>  ################################################################################
> @@ -56,8 +56,61 @@ [FD.BL33_JADE_UEFI]
>  
>  #
>  # NV Variables
> -# Placeholder
> +# Offset: 0x00740000
> +# Size:   0x00080000
>  #
> +0x00740000|0x00030000
> +gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64|gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize
> +DATA = {
> +  ## This is the EFI_FIRMWARE_VOLUME_HEADER
> +  # ZeroVector []
> +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +  # FileSystemGuid: gEfiSystemNvDataFvGuid         =
> +  #   { 0xFFF12B8D, 0x7696, 0x4C8B,
> +  #     { 0xA9, 0x85, 0x27, 0x47, 0x07, 0x5B, 0x4F, 0x50 }}
> +  0x8D, 0x2B, 0xF1, 0xFF, 0x96, 0x76, 0x8B, 0x4C,
> +  0xA9, 0x85, 0x27, 0x47, 0x07, 0x5B, 0x4F, 0x50,
> +  # FvLength: 0x80000
> +  0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
> +  # Signature "_FVH"       # Attributes
> +  0x5f, 0x46, 0x56, 0x48, 0xff, 0xfe, 0x04, 0x00,
> +  # HeaderLength # CheckSum # ExtHeaderOffset #Reserved #Revision
> +  0x48, 0x00, 0x2D, 0x09, 0x00, 0x00, 0x00, 0x02,
> +  # Blockmap[0]: 0x2 Blocks * 0x40000 Bytes / Block
> +  0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
> +  # Blockmap[1]: End
> +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +  ## This is the VARIABLE_STORE_HEADER
> +  # It is compatible with SECURE_BOOT_ENABLE == FALSE as well.
> +  # Signature: gEfiAuthenticatedVariableGuid =
> +  #   { 0xaaf32c78, 0x947b, 0x439a,
> +  #     { 0xa1, 0x80, 0x2e, 0x14, 0x4e, 0xc3, 0x77, 0x92 }}
> +  0x78, 0x2c, 0xf3, 0xaa, 0x7b, 0x94, 0x9a, 0x43,
> +  0xa1, 0x80, 0x2e, 0x14, 0x4e, 0xc3, 0x77, 0x92,
> +  # Size: 0x30000 (gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize) -
> +  #         0x48 (size of EFI_FIRMWARE_VOLUME_HEADER) = 0x2FFB8
> +  # This can speed up the Variable Dispatch a bit.
> +  0xB8, 0xFF, 0x02, 0x00,
> +  # FORMATTED: 0x5A #HEALTHY: 0xFE #Reserved: UINT16 #Reserved1: UINT32
> +  0x5A, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
> +}
> +
> +0x00770000|0x00010000
> +gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase64|gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize
> +DATA = {
> +  # EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER->Signature = gEdkiiWorkingBlockSignatureGuid =
> +  #  { 0x9e58292b, 0x7c68, 0x497d, { 0xa0, 0xce, 0x65,  0x0, 0xfd, 0x9f, 0x1b, 0x95 }}
> +  0x2b, 0x29, 0x58, 0x9e, 0x68, 0x7c, 0x7d, 0x49,
> +  0xa0, 0xce, 0x65,  0x0, 0xfd, 0x9f, 0x1b, 0x95,
> +  # Crc:UINT32            #WorkingBlockValid:1, WorkingBlockInvalid:1, Reserved
> +  0x2c, 0xaf, 0x2c, 0x64, 0xFE, 0xFF, 0xFF, 0xFF,
> +  # WriteQueueSize: UINT64 Size: 0x10000 - 0x20 (FTW_WORKING_HEADER) = 0xFFE0
> +  0xE0, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
> +}
> +
> +0x00780000|0x00040000
> +gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase64|gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize
>  
>  ################################################################################
>  #
> @@ -101,9 +154,11 @@ [FV.FVMAIN_COMPACT]
>    INF ArmPlatformPkg/PlatformPei/PlatformPeim.inf
>    INF Silicon/Ampere/AmpereAltraPkg/Drivers/ATFHobPei/ATFHobPeim.inf
>    INF ArmPlatformPkg/MemoryInitPei/MemoryInitPeim.inf
> +  INF Silicon/Ampere/AmpereAltraPkg/Drivers/FlashPei/FlashPei.inf
>    INF Silicon/Ampere/AmpereAltraPkg/Drivers/BootProgress/BootProgressPeim/BootProgressPeim.inf
>    INF ArmPkg/Drivers/CpuPei/CpuPei.inf
>    INF MdeModulePkg/Universal/PCD/Pei/Pcd.inf
> +  INF MdeModulePkg/Universal/FaultTolerantWritePei/FaultTolerantWritePei.inf
>    INF MdeModulePkg/Universal/Variable/Pei/VariablePei.inf
>    INF MdeModulePkg/Universal/ReportStatusCodeRouter/Pei/ReportStatusCodeRouterPei.inf
>    INF MdeModulePkg/Universal/StatusCodeHandler/Pei/StatusCodeHandlerPei.inf
> @@ -144,6 +199,7 @@ [FV.FvMain]
>    INF MdeModulePkg/Universal/StatusCodeHandler/RuntimeDxe/StatusCodeHandlerRuntimeDxe.inf
>    INF ArmPkg/Drivers/CpuDxe/CpuDxe.inf
>    INF ArmPkg/Drivers/MmCommunicationDxe/MmCommunication.inf
> +  INF Silicon/Ampere/AmpereAltraPkg/Drivers/FlashFvbDxe/FlashFvbDxe.inf
>  }
>  
>    INF MdeModulePkg/Core/Dxe/DxeMain.inf
> @@ -173,6 +229,8 @@ [FV.FvMain]
>    # Environment Variables Protocol
>    #
>    INF MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
> +  INF MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf
> +  INF Silicon/Ampere/AmpereAltraPkg/Drivers/FlashFvbDxe/FlashFvbDxe.inf
>  
>    #
>    # Multiple Console IO support
> diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/FlashFvbDxe/FlashFvbDxe.inf b/Silicon/Ampere/AmpereAltraPkg/Drivers/FlashFvbDxe/FlashFvbDxe.inf
> new file mode 100644
> index 000000000000..008fd2315ffe
> --- /dev/null
> +++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/FlashFvbDxe/FlashFvbDxe.inf
> @@ -0,0 +1,54 @@
> +## @file
> +#
> +# Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x0001001B
> +  BASE_NAME                      = FlashFvbDxe
> +  FILE_GUID                      = 9E6EA240-DF80-11EA-8B6E-0800200C9A66
> +  MODULE_TYPE                    = DXE_RUNTIME_DRIVER
> +  VERSION_STRING                 = 0.1
> +  ENTRY_POINT                    = FlashFvbDxeInitialize
> +
> +[Sources]
> +  FlashFvbDxe.c
> +
> +[Packages]
> +  ArmPkg/ArmPkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  MdePkg/MdePkg.dec
> +  Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec
> +  Silicon/Ampere/AmpereSiliconPkg/AmpereSiliconPkg.dec
> +
> +[LibraryClasses]
> +  DebugLib
> +  FlashLib
> +  PcdLib
> +  UefiBootServicesTableLib
> +  UefiDriverEntryPoint
> +  UefiRuntimeLib
> +
> +[FixedPcd]
> +  gAmpereTokenSpaceGuid.PcdFvBlockSize
> +
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize
> +
> +[Pcd]
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64
> +
> +[Guids]
> +  gEfiEventVirtualAddressChangeGuid
> +  gSpiNorMmGuid
> +
> +[Protocols]
> +  gEfiFirmwareVolumeBlockProtocolGuid             ## PRODUCES
> +  gEfiMmCommunication2ProtocolGuid                ## CONSUMES
> +
> +[Depex]
> +  gEfiMmCommunication2ProtocolGuid
> diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/FlashPei/FlashPei.inf b/Silicon/Ampere/AmpereAltraPkg/Drivers/FlashPei/FlashPei.inf
> new file mode 100644
> index 000000000000..2b329c5d0987
> --- /dev/null
> +++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/FlashPei/FlashPei.inf
> @@ -0,0 +1,49 @@
> +## @file
> +#
> +# Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x0001001B
> +  BASE_NAME                      = FlashPei
> +  FILE_GUID                      = 967CFBD0-DF81-11EA-8B6E-0800200C9A66
> +  MODULE_TYPE                    = PEIM
> +  VERSION_STRING                 = 1.0
> +  ENTRY_POINT                    = FlashPeiEntryPoint
> +
> +[Sources]
> +  FlashPei.c
> +
> +[Packages]
> +  ArmPkg/ArmPkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  MdePkg/MdePkg.dec
> +  Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec
> +  Silicon/Ampere/AmpereSiliconPkg/AmpereSiliconPkg.dec
> +
> +[LibraryClasses]
> +  ArmSmcLib
> +  BaseMemoryLib
> +  DebugLib
> +  FlashLib
> +  MmCommunicationLib
> +  PcdLib
> +  PeimEntryPoint
> +
> +[FixedPcd]
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize
> +
> +[Pcd]
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase64
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase64
> +
> +  gAmpereTokenSpaceGuid.PcdPlatformConfigUuid
> +
> +[Depex]
> +  TRUE
> diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/FlashFvbDxe/FlashFvbDxe.c b/Silicon/Ampere/AmpereAltraPkg/Drivers/FlashFvbDxe/FlashFvbDxe.c
> new file mode 100644
> index 000000000000..009694703ddd
> --- /dev/null
> +++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/FlashFvbDxe/FlashFvbDxe.c
> @@ -0,0 +1,525 @@
> +/** @file
> +
> +  Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include <Library/DebugLib.h>
> +#include <Library/FlashLib.h>
> +#include <Library/PcdLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiRuntimeLib.h>
> +#include <Protocol/FirmwareVolumeBlock.h>
> +
> +//
> +// These temporary buffers are used to calculate and convert linear virtual
> +// to physical address
> +//
> +STATIC UINT64 mNvFlashBase;
> +STATIC UINT32 mNvFlashSize;
> +STATIC UINT32 mFlashBlockSize;
> +STATIC UINT64 mNvStorageBase;
> +STATIC UINT64 mNvStorageSize;
> +
> +/**
> +  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
> +**/
> +VOID
> +EFIAPI
> +FlashFvbAddressChangeEvent (
> +  IN EFI_EVENT Event,
> +  IN VOID      *Context
> +  )
> +{
> +  EfiConvertPointer (0x0, (VOID **)&mNvStorageBase);
> +}
> +
> +/**
> +  The GetAttributes() 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
> +FlashFvbDxeGetAttributes (
> +  IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
> +  OUT      EFI_FVB_ATTRIBUTES_2                *Attributes
> +  )
> +{
> +  ASSERT (Attributes != NULL);
> +
> +  *Attributes = EFI_FVB2_READ_ENABLED_CAP   | // Reads may be enabled
> +                EFI_FVB2_READ_STATUS        | // Reads are currently enabled
> +                EFI_FVB2_WRITE_STATUS       | // Writes are currently enabled
> +                EFI_FVB2_WRITE_ENABLED_CAP  | // Writes may be 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_ALIGNMENT          |
> +                EFI_FVB2_ERASE_POLARITY;      // After erasure all bits take this value (i.e. '1')
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  The SetAttributes() function sets configurable firmware volume
> +  attributes and returns the new settings of the firmware volume.
> +
> +  @param This         Indicates the 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. Type
> +                      EFI_FVB_ATTRIBUTES_2 is defined in
> +                      EFI_FIRMWARE_VOLUME_HEADER.
> +
> +  @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
> +FlashFvbDxeSetAttributes (
> +  IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
> +  IN OUT   EFI_FVB_ATTRIBUTES_2                *Attributes
> +  )
> +{
> +  return EFI_SUCCESS;  // ignore for now
> +}
> +
> +/**
> +  The GetPhysicalAddress() function retrieves the base address of
> +  a memory-mapped firmware volume. This function should be called
> +  only for memory-mapped firmware volumes.
> +
> +  @param This     Indicates the 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_UNSUPPORTED   The firmware volume is not memory mapped.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +FlashFvbDxeGetPhysicalAddress (
> +  IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
> +  OUT      EFI_PHYSICAL_ADDRESS                *Address
> +  )
> +{
> +  ASSERT (Address != NULL);
> +
> +  *Address = (EFI_PHYSICAL_ADDRESS)mNvStorageBase;
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  The GetBlockSize() function retrieves the size of the requested
> +  block. It also returns the number of additional blocks with
> +  the identical size. The GetBlockSize() function is used to
> +  retrieve the block map (see EFI_FIRMWARE_VOLUME_HEADER).
> +
> +
> +  @param This           Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
> +
> +  @param Lba            Indicates the block for which to return the size.
> +
> +  @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
> +FlashFvbDxeGetBlockSize (
> +  IN  CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
> +  IN        EFI_LBA                             Lba,
> +  OUT       UINTN                               *BlockSize,
> +  OUT       UINTN                               *NumberOfBlocks
> +  )
> +{
> +  UINTN TotalNvStorageBlocks;
> +
> +  ASSERT (BlockSize != NULL);
> +  ASSERT (NumberOfBlocks != NULL);
> +
> +  TotalNvStorageBlocks = mNvStorageSize / mFlashBlockSize;
> +
> +  if (TotalNvStorageBlocks <= (UINTN)Lba) {
> +    DEBUG ((DEBUG_ERROR, "The requested LBA is out of range\n"));
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  *NumberOfBlocks = TotalNvStorageBlocks - (UINTN)Lba;
> +  *BlockSize = mFlashBlockSize;
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Reads the specified number of bytes into a buffer from the specified block.
> +
> +  The Read() function reads the requested number of bytes from the
> +  requested block and stores them in the provided buffer.
> +  Implementations should be mindful that the firmware volume
> +  might be in the ReadDisabled state. If it is in this state,
> +  the Read() function must return the status code
> +  EFI_ACCESS_DENIED without modifying the contents of the
> +  buffer. The Read() function must also prevent spanning block
> +  boundaries. If a read is requested that would span a block
> +  boundary, the read must read up to the boundary but not
> +  beyond. The output parameter NumBytes must be set to correctly
> +  indicate the number of bytes actually read. The caller must be
> +  aware that a read may be partially completed.
> +
> +  @param This     Indicates the 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
> +FlashFvbDxeRead (
> +  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 Status;
> +
> +  ASSERT (NumBytes != NULL);
> +  ASSERT (Buffer != NULL);
> +
> +  if (Offset + *NumBytes > mFlashBlockSize) {
> +    return EFI_BAD_BUFFER_SIZE;
> +  }
> +
> +  Status = FlashReadCommand (
> +             mNvFlashBase + Lba * mFlashBlockSize + Offset,
> +             Buffer,
> +             *NumBytes
> +             );
> +
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "Failed to do flash read\n"));
> +    return EFI_DEVICE_ERROR;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Writes the specified number of bytes from the input buffer to the block.
> +
> +  The Write() function writes the specified number of bytes from
> +  the provided buffer to the specified block and offset. If the
> +  firmware volume is sticky write, the caller must ensure that
> +  all the bits of the specified range to write are in the
> +  EFI_FVB_ERASE_POLARITY state before calling the Write()
> +  function, or else the result will be unpredictable. This
> +  unpredictability arises because, for a sticky-write firmware
> +  volume, a write may negate a bit in the EFI_FVB_ERASE_POLARITY
> +  state but cannot flip it back again.  Before calling the
> +  Write() function,  it is recommended for the caller to first call
> +  the EraseBlocks() function to erase the specified block to
> +  write. A block erase cycle will transition bits from the
> +  (NOT)EFI_FVB_ERASE_POLARITY state back to the
> +  EFI_FVB_ERASE_POLARITY state. Implementations should be
> +  mindful that the firmware volume might be in the WriteDisabled
> +  state. If it is in this state, the Write() function must
> +  return the status code EFI_ACCESS_DENIED without modifying the
> +  contents of the firmware volume. The Write() function must
> +  also prevent spanning block boundaries. If a write is
> +  requested that spans a block boundary, the write must store up
> +  to the boundary but not beyond. The output parameter NumBytes
> +  must be set to correctly indicate the number of bytes actually
> +  written. The caller must be aware that a write may be
> +  partially completed. All writes, partial or otherwise, must be
> +  fully flushed to the hardware before the Write() service
> +  returns.
> +
> +  @param This     Indicates the 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
> +FlashFvbDxeWrite (
> +  IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
> +  IN       EFI_LBA                             Lba,
> +  IN       UINTN                               Offset,
> +  IN OUT   UINTN                               *NumBytes,
> +  IN       UINT8                               *Buffer
> +  )
> +{
> +  EFI_STATUS Status;
> +
> +  ASSERT (NumBytes != NULL);
> +  ASSERT (Buffer != NULL);
> +
> +  if (Offset + *NumBytes > mFlashBlockSize) {
> +    return EFI_BAD_BUFFER_SIZE;
> +  }
> +
> +  Status = FlashWriteCommand (
> +             mNvFlashBase + Lba * mFlashBlockSize + Offset,
> +             Buffer,
> +             *NumBytes
> +             );
> +
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "Failed to do flash write\n"));
> +    return EFI_DEVICE_ERROR;
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Erases and initializes a firmware volume block.
> +
> +  The EraseBlocks() function erases one or more blocks as denoted
> +  by the variable argument list. The entire parameter list of
> +  blocks must be verified before 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 EraseBlocks() function must return the
> +  status code EFI_INVALID_PARAMETER without modifying the contents
> +  of the firmware volume. Implementations should be mindful that
> +  the firmware volume might be in the WriteDisabled state. If it
> +  is in this state, the EraseBlocks() function must return the
> +  status code EFI_ACCESS_DENIED without modifying the contents of
> +  the firmware volume. All calls to EraseBlocks() must be fully
> +  flushed to the hardware before the EraseBlocks() service
> +  returns.
> +
> +  @param This   Indicates the 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. For example, the
> +                following indicates that two ranges of blocks
> +                (5-7 and 10-11) are to be erased: EraseBlocks
> +                (This, 5, 3, 10, 2, 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
> +FlashFvbDxeErase (
> +  IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
> +  ...
> +  )
> +{
> +  VA_LIST    Args;
> +  EFI_LBA    Start;
> +  UINTN      Length;
> +  EFI_STATUS Status;
> +
> +  Status = EFI_SUCCESS;
> +
> +  VA_START (Args, This);
> +
> +  for (Start = VA_ARG (Args, EFI_LBA);
> +       Start != EFI_LBA_LIST_TERMINATOR;
> +       Start = VA_ARG (Args, EFI_LBA))
> +  {
> +    Length = VA_ARG (Args, UINTN);
> +    Status = FlashEraseCommand (
> +               mNvFlashBase + Start * mFlashBlockSize,
> +               Length * mFlashBlockSize
> +               );
> +  }
> +
> +  VA_END (Args);
> +
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "Failed to do flash erase\n"));
> +    return EFI_DEVICE_ERROR;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL mFlashFvbProtocol = {
> +  FlashFvbDxeGetAttributes,
> +  FlashFvbDxeSetAttributes,
> +  FlashFvbDxeGetPhysicalAddress,
> +  FlashFvbDxeGetBlockSize,
> +  FlashFvbDxeRead,
> +  FlashFvbDxeWrite,
> +  FlashFvbDxeErase
> +};
> +
> +EFI_STATUS
> +EFIAPI
> +FlashFvbDxeInitialize (
> +  IN EFI_HANDLE       ImageHandle,
> +  IN EFI_SYSTEM_TABLE *SystemTable
> +  )
> +{
> +  EFI_STATUS Status;
> +  EFI_HANDLE FvbHandle = NULL;
> +  EFI_EVENT  VirtualAddressChangeEvent;
> +
> +  // Get NV store FV info
> +  mFlashBlockSize = FixedPcdGet32 (PcdFvBlockSize);
> +  mNvStorageBase = PcdGet64 (PcdFlashNvStorageVariableBase64);
> +  mNvStorageSize = FixedPcdGet32 (PcdFlashNvStorageVariableSize) +
> +                   FixedPcdGet32 (PcdFlashNvStorageFtwWorkingSize) +
> +                   FixedPcdGet32 (PcdFlashNvStorageFtwSpareSize);
> +
> +  DEBUG ((
> +    DEBUG_INFO,
> +    "%a: Using NV store FV in-memory copy at 0x%lx with size 0x%x\n",
> +    __FUNCTION__,
> +    mNvStorageBase,
> +    mNvStorageSize
> +    ));
> +
> +  // Get NV Flash information
> +  Status = FlashGetNvRamInfo (&mNvFlashBase, &mNvFlashSize);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "%a: Failed to get Flash info\n", __FUNCTION__));
> +    return EFI_DEVICE_ERROR;
> +  }
> +
> +  if (mNvFlashSize >= (mNvStorageSize * 2)) {
> +    DEBUG ((DEBUG_INFO, "%a: NV store on Flash is valid\n", __FUNCTION__));
> +  } else {
> +    DEBUG ((DEBUG_ERROR, "%a: NV store on Flash is invalid\n", __FUNCTION__));
> +    return EFI_DEVICE_ERROR;
> +  }
> +
> +  Status = gBS->CreateEventEx (
> +                  EVT_NOTIFY_SIGNAL,
> +                  TPL_NOTIFY,
> +                  FlashFvbAddressChangeEvent,
> +                  NULL,
> +                  &gEfiEventVirtualAddressChangeGuid,
> +                  &VirtualAddressChangeEvent
> +                  );
> +  ASSERT_EFI_ERROR (Status);
> +
> +  Status = gBS->InstallMultipleProtocolInterfaces (
> +                  &FvbHandle,
> +                  &gEfiFirmwareVolumeBlockProtocolGuid,
> +                  &mFlashFvbProtocol,
> +                  NULL
> +                  );
> +
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "Failed to install Firmware Volume Block protocol\n"));
> +    return Status;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/FlashPei/FlashPei.c b/Silicon/Ampere/AmpereAltraPkg/Drivers/FlashPei/FlashPei.c
> new file mode 100644
> index 000000000000..3da7df3907dc
> --- /dev/null
> +++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/FlashPei/FlashPei.c
> @@ -0,0 +1,125 @@
> +/** @file
> +
> +  Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include <PiPei.h>
> +#include <Uefi.h>
> +
> +#include <Library/ArmSmcLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/FlashLib.h>
> +#include <Library/PcdLib.h>
> +#include <Library/PeimEntryPoint.h>
> +
> +/**
> +  Entry point function for the PEIM
> +
> +  @param FileHandle      Handle of the file being invoked.
> +  @param PeiServices     Describes the list of possible PEI Services.
> +
> +  @return EFI_SUCCESS    If we installed our PPI
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +FlashPeiEntryPoint (
> +  IN       EFI_PEI_FILE_HANDLE FileHandle,
> +  IN CONST EFI_PEI_SERVICES    **PeiServices
> +  )
> +{
> +  CHAR8               BuildUuid[PcdGetSize (PcdPlatformConfigUuid)];
> +  CHAR8               StoredUuid[PcdGetSize (PcdPlatformConfigUuid)];
> +  EFI_STATUS          Status;
> +  UINTN               FWNvRamStartOffset;
> +  UINT32              FWNvRamSize;
> +  UINTN               NvRamAddress;
> +  UINT32              NvRamSize;
> +
> +  CopyMem ((VOID *)BuildUuid, PcdGetPtr (PcdPlatformConfigUuid), sizeof (BuildUuid));
> +
> +  NvRamAddress = PcdGet64 (PcdFlashNvStorageVariableBase64);
> +  NvRamSize = FixedPcdGet32 (PcdFlashNvStorageVariableSize) +
> +              FixedPcdGet32 (PcdFlashNvStorageFtwWorkingSize) +
> +              FixedPcdGet32 (PcdFlashNvStorageFtwSpareSize);
> +
> +  DEBUG ((
> +    DEBUG_INFO,
> +    "%a: Using NV store FV in-memory copy at 0x%lx with size 0x%x\n",
> +    __FUNCTION__,
> +    NvRamAddress,
> +    NvRamSize
> +    ));
> +
> +  Status = FlashGetNvRamInfo (&FWNvRamStartOffset, &FWNvRamSize);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "%a: Failed to get Flash NVRAM info %r\n", __FUNCTION__, Status));
> +    return Status;
> +  }
> +
> +  if (FWNvRamSize < (NvRamSize * 2 + sizeof (BuildUuid))) {
> +    //
> +    // NVRAM size provided by FW is not enough
> +    //
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  //
> +  // We stored BUILD UUID build at the offset NVRAM_SIZE * 2
> +  //
> +  Status = FlashReadCommand (
> +             FWNvRamStartOffset + NvRamSize * 2,
> +             (UINT8 *)StoredUuid,
> +             sizeof (StoredUuid)
> +             );
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  if (CompareMem ((VOID *)StoredUuid, (VOID *)BuildUuid, sizeof (BuildUuid)) != 0) {
> +    DEBUG ((DEBUG_INFO, "BUILD UUID Changed, Update Storage with NVRAM FV\n"));
> +
> +    Status = FlashEraseCommand (FWNvRamStartOffset, NvRamSize * 2 + sizeof (BuildUuid));
> +    if (EFI_ERROR (Status)) {
> +      return Status;
> +    }
> +
> +    Status = FlashWriteCommand (
> +               FWNvRamStartOffset,
> +               (UINT8 *)NvRamAddress,
> +               NvRamSize
> +               );
> +    if (EFI_ERROR (Status)) {
> +      return Status;
> +    }
> +
> +    //
> +    // Write new BUILD UUID to the Flash
> +    //
> +    Status = FlashWriteCommand (
> +               FWNvRamStartOffset + NvRamSize * 2,
> +               (UINT8 *)BuildUuid,
> +               sizeof (BuildUuid)
> +               );
> +    if (EFI_ERROR (Status)) {
> +      return Status;
> +    }
> +  } else {
> +    DEBUG ((DEBUG_INFO, "Identical UUID, copy stored NVRAM to RAM\n"));
> +
> +    Status = FlashReadCommand (
> +               FWNvRamStartOffset,
> +               (UINT8 *)NvRamAddress,
> +               NvRamSize
> +               );
> +    if (EFI_ERROR (Status)) {
> +      return Status;
> +    }
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> -- 
> 2.17.1
> 


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#82685): https://edk2.groups.io/g/devel/message/82685
Mute This Topic: https://groups.io/mt/86507920/1813853
Group Owner: devel+owner at edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [edk2-devel-archive at redhat.com]
-=-=-=-=-=-=-=-=-=-=-=-





More information about the edk2-devel-archive mailing list