From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-wm1-f52.google.com (mail-wm1-f52.google.com [209.85.128.52]) by mx.groups.io with SMTP id smtpd.web09.11202.1635250898580174621 for ; Tue, 26 Oct 2021 05:21:39 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@nuviainc-com.20210112.gappssmtp.com header.s=20210112 header.b=Xj0kNDsL; spf=pass (domain: nuviainc.com, ip: 209.85.128.52, mailfrom: leif@nuviainc.com) Received: by mail-wm1-f52.google.com with SMTP id z11-20020a1c7e0b000000b0030db7b70b6bso2946537wmc.1 for ; Tue, 26 Oct 2021 05:21:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nuviainc-com.20210112.gappssmtp.com; s=20210112; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:in-reply-to; bh=zveoASdVqK0S26P8P1co6w7dFLBCuzydWxfYFBXksWU=; b=Xj0kNDsLws6WEg4qgulTSR+DZUd7O1aTiSq9l7BfhfdYsGvSbPNz/UhhcKDc0VYukT g0Hh7cPykn+yNIRf3vO0lT/ynrAVwNL188qUvD0/qz7wgzkniVuWW9xRUrCX219e9Vt+ +Cv6PJJhjuabPMFjU3/KGAmgSHzamZ4/a5woXpK6W1GdwOaIJY8qnET8YLhZ8kPP+5o/ vMXCOWYYhmYt/7cQG8Aw6+dSaPwzUnQ0iKCTkgJz4zKc2uxKqCHsA7NdJYTAT/roDivD NJH/TwnPps/xZ2VRYPqZ+FIXx7p+o5f1r+K3910TVlVlYsKLa5bFe/mpb0XBGJXH2NHr Ji7g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to; bh=zveoASdVqK0S26P8P1co6w7dFLBCuzydWxfYFBXksWU=; b=j6rJ2Eo9TMMOB7UOVDRYaUa5GKYqgXZu9V2fblzrxg8/7BjhvhLU82Z0TT11aLXZbU 77Z3ksWC1UKjSXiXnWBszXzVLnVWETYV39zjySta3GurGZL+ojJ/CQSNiE1RPxVim0vT 8ljHVVF+8B3/nTOIWhEMe8fSo1x2prqinVrsIoJ0eKVzZpifHMgKGy32KjGPYFvjRKcG MlR/1+hGN2JCLLNqgCoNfhCNQm2l7jxyXZra6uWclkjtSK62hFhRadsK6YHZZEHuym+G pnFfnCwUlMJYZ5HCK6s5kA+pbe9eGKEM2bHxY7hle/Y0kLBiVyRqmZmBWdryD5um+s17 yqQw== X-Gm-Message-State: AOAM532eoAeIcWbIczlrkZjxuPgUZBPKJmbX7kqVcaAgtZf949RgBv4z ct8i0xT5UhCDfjKq+IWh6wT7tQ== X-Google-Smtp-Source: ABdhPJyDYQwE/AhwehkPV3DZOsLMl45kEXlp+suVRsCvLYsqVI5mxNAiH8P+AxaHFp2GjdeyW+nUyQ== X-Received: by 2002:a05:600c:511c:: with SMTP id o28mr55843118wms.81.1635250896920; Tue, 26 Oct 2021 05:21:36 -0700 (PDT) Return-Path: Received: from leviathan (cpc92314-cmbg19-2-0-cust559.5-4.cable.virginm.net. [82.11.186.48]) by smtp.gmail.com with ESMTPSA id r1sm474565wmr.36.2021.10.26.05.21.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 26 Oct 2021 05:21:36 -0700 (PDT) Date: Tue, 26 Oct 2021 13:21:23 +0100 From: "Leif Lindholm" To: Nhi Pham Cc: devel@edk2.groups.io, patches@amperecomputing.com, vunguyen@os.amperecomputing.com, Thang Nguyen , Chuong Tran , Phong Vo , Michael D Kinney , Ard Biesheuvel , Nate DeSimone Subject: Re: [edk2-platforms][PATCH v4 08/31] AmpereAltraPkg: Support UEFI non-volatile variable Message-ID: <20211026122123.ugd5wcn7vpicfvc7@leviathan> References: <20211022061809.31087-1-nhi@os.amperecomputing.com> <20211022061809.31087-9-nhi@os.amperecomputing.com> MIME-Version: 1.0 In-Reply-To: <20211022061809.31087-9-nhi@os.amperecomputing.com> Content-Type: text/plain; charset=us-ascii Content-Disposition: inline On Fri, Oct 22, 2021 at 13:17:46 +0700, Nhi Pham wrote: > From: Vu Nguyen > > 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 > Cc: Chuong Tran > Cc: Phong Vo > Cc: Leif Lindholm > Cc: Michael D Kinney > Cc: Ard Biesheuvel > Cc: Nate DeSimone > > Signed-off-by: Nhi Pham Reviewed-by: Leif Lindholm > --- > 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 { > > @@ -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 { > - > - gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvModeEnable|TRUE > > 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.
> +# > +# 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.
> +# > +# 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.
> + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#include > +#include > +#include > +#include > +#include > +#include > + > +// > +// 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.
> + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#include > +#include > + > +#include > +#include > +#include > +#include > +#include > +#include > + > +/** > + 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 >