From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-wm1-f43.google.com (mail-wm1-f43.google.com [209.85.128.43]) by mx.groups.io with SMTP id smtpd.web09.6553.1622849778008013507 for ; Fri, 04 Jun 2021 16:36:18 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@nuviainc-com.20150623.gappssmtp.com header.s=20150623 header.b=lB0RMNuv; spf=pass (domain: nuviainc.com, ip: 209.85.128.43, mailfrom: leif@nuviainc.com) Received: by mail-wm1-f43.google.com with SMTP id f17so6252769wmf.2 for ; Fri, 04 Jun 2021 16:36:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nuviainc-com.20150623.gappssmtp.com; s=20150623; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:in-reply-to; bh=GA7YV1yqgGzuacCFogt339vBwXo4P/V7UqoxtfEgmRM=; b=lB0RMNuvn9BULE0u8cjler81Vh8k/x/LrqIfIYdlq0Mn1qEiIwwrusETKu5TgpQgsU fwGdnFrpYGX0A5AFFjTLgM5FJP/V5foqe41hkR0EPTplsnm6ODjZZdyz6BE+ypot9jw8 Vgcoje3E7jzLNNC0RY6LUvzfjNobnqZRJHMbPNeZa903LoQSW4LQ9oe46FSECh2EL5PV KtO39U/0NwE7jtKgFnJeBXAz0aymkyEbTBJxSNGE3VRaMmxjf9JOUhuafdoQKMgK4VnE FRG926kMaahhyDNdzNJYaEW2CrUiB7ZaozOMes8F/sBU2H853waFSIUEXxUgagkaMVk9 Rtgw== 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; bh=GA7YV1yqgGzuacCFogt339vBwXo4P/V7UqoxtfEgmRM=; b=npdO+wqt0hacmxQtknchoG1zBvpiODw/4M7b3vlQEObezSwQEsC8+gP8hbRiCIycQS lgCtGHo14VM1HdWO6g1OHcCIWaRQXbdoh51TJPZ3P3H+TIWGFWNHir55oKgTBPxr+tNO hGMFAcFRe9UjcGtNvaVndDwu+0Bur1frCcwfLdq4D8d7V/UaDzj1EDpIOqicoiQdOq46 eQQh8/l+vwPmBfkwnamXp6Iu/ZUC6iurzVAgJVWaqnaE+3+J5bJSBtn2MxM9diaodnWf E6rNJ2lvsCP9vy0DAefltxWescy0mSgjkllZqvcox3P+3dMFfegRp2CHtSQeaTBIHuld JrkQ== X-Gm-Message-State: AOAM530MUazxFC96kVl2CuL5K7T99GCNT9V0HNax85O8YeG22JNIYtij qJuUy7Xin4oj43J2zZri7zqtHw== X-Google-Smtp-Source: ABdhPJx3WQyMm+z+PaZUdCMZWhjSKbL+inWzeb3z+lPEH9ImxVYUBozPP+yRj5N5gLpPufPrQp7VHg== X-Received: by 2002:a05:600c:4148:: with SMTP id h8mr5748628wmm.176.1622849776310; Fri, 04 Jun 2021 16:36:16 -0700 (PDT) Return-Path: Received: from leviathan (cpc1-cmbg19-2-0-cust915.5-4.cable.virginm.net. [82.27.183.148]) by smtp.gmail.com with ESMTPSA id j131sm10333570wma.40.2021.06.04.16.36.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 04 Jun 2021 16:36:15 -0700 (PDT) Date: Sat, 5 Jun 2021 00:36:13 +0100 From: "Leif Lindholm" To: Nhi Pham Cc: devel@edk2.groups.io, Vu Nguyen , Thang Nguyen , Chuong Tran , Phong Vo , Michael D Kinney , Ard Biesheuvel , Nate DeSimone Subject: Re: [edk2-platforms][PATCH v2 09/32] AmpereAltraPkg: Support non-volatile variables Message-ID: <20210604233613.hltqv7uyytfzu23e@leviathan> References: <20210526100724.5359-1-nhi@os.amperecomputing.com> <20210526100724.5359-11-nhi@os.amperecomputing.com> MIME-Version: 1.0 In-Reply-To: <20210526100724.5359-11-nhi@os.amperecomputing.com> Content-Type: text/plain; charset=us-ascii Content-Disposition: inline On Wed, May 26, 2021 at 17:07:01 +0700, Nhi Pham wrote: > From: Vu Nguyen > > Non-volatile variables now can be stored on flash. MM communication > protocol is used to access storage on flash. > > Included in this change are: > * FlashPei module is used to compare saved UUID with firmware's > UEFI_UUID on each boot. If UUIDs match, data is stored to RAM. > Otherwise fill the storage with default value from NVRAM FV. > * FlashLib provide APIs to access flash through MM Communication > protocol > * FlashFvbDxe installs gEfiFirmwareVolumeBlock protocol which will be > used by the variable services to get/set variables. > > 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: Vu Nguyen > --- > Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec | 3 + > Silicon/Ampere/AmpereSiliconPkg/AmpereSiliconPkg.dec | 3 + > Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc | 11 +- > Platform/Ampere/JadePkg/Jade.dsc | 1 + > Platform/Ampere/JadePkg/Jade.fdf | 62 ++- > Silicon/Ampere/AmpereAltraPkg/Drivers/FlashFvbDxe/FlashFvbDxe.inf | 54 ++ > Silicon/Ampere/AmpereAltraPkg/Drivers/FlashPei/FlashPei.inf | 51 ++ > Silicon/Ampere/AmpereAltraPkg/Library/FlashLib/FlashLib.inf | 36 ++ > Silicon/Ampere/AmpereAltraPkg/Include/Library/FlashLib.h | 42 ++ > Silicon/Ampere/AmpereAltraPkg/Drivers/FlashFvbDxe/FlashFvbDxe.c | 525 ++++++++++++++++++++ > Silicon/Ampere/AmpereAltraPkg/Drivers/FlashPei/FlashPei.c | 283 +++++++++++ > Silicon/Ampere/AmpereAltraPkg/Library/FlashLib/FlashLib.c | 358 +++++++++++++ > 12 files changed, 1425 insertions(+), 4 deletions(-) > > diff --git a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec > index be827dd19a96..d5b12a81e9bf 100644 > --- a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec > +++ b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec > @@ -37,6 +37,9 @@ [LibraryClasses] > ## @libraryclass Defines a set of methods to communicate with secure parition over MM interface. > MmCommunicationLib|Silicon/Ampere/AmpereAltraPkg/Include/Library/MmCommunicationLib.h > > + ## @libraryclass Defines a set of methods to access flash memory. > + FlashLib|Silicon/Ampere/AmpereAltraPkg/Include/Library/FlashLib.h > + > ## @libraryclass Defines a set of methods to generate random numbers by using Hardware RNG. > TrngLib|Silicon/Ampere/AmpereAltraPkg/Include/Library/TrngLib.h > > diff --git a/Silicon/Ampere/AmpereSiliconPkg/AmpereSiliconPkg.dec b/Silicon/Ampere/AmpereSiliconPkg/AmpereSiliconPkg.dec > index 6ebdf7db0a57..26e020715290 100755 > --- a/Silicon/Ampere/AmpereSiliconPkg/AmpereSiliconPkg.dec > +++ b/Silicon/Ampere/AmpereSiliconPkg/AmpereSiliconPkg.dec > @@ -44,3 +44,6 @@ [PcdsFixedAtBuild, PcdsDynamic, PcdsDynamicEx] > # Firmware Volume Pcds > # > gAmpereTokenSpaceGuid.PcdFvBlockSize|0|UINT32|0xB0000001 > + > + # NVRam Pcds > + gAmpereTokenSpaceGuid.PcdNvramErased|FALSE|BOOLEAN|0xB0000009 > diff --git a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc > index 9f75da6f05ad..65973569a41d 100755 > --- a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc > +++ b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc > @@ -14,6 +14,7 @@ [BuildOptions.common.EDKII.DXE_RUNTIME_DRIVER] > > [BuildOptions] > GCC:RELEASE_*_*_CC_FLAGS = -DMDEPKG_NDEBUG > + GCC:*_*_*_CC_FLAGS = -DUEFI_UUID=$(UEFI_UUID) This isn't obvious enough. I'm a bear of very little brain, and I could possibly figure out what's happening here, given time, but please put a proper description in commit message (and possibly here? whatever makes sense). > > [LibraryClasses.common] > !if $(TARGET) == RELEASE > @@ -224,6 +225,7 @@ [LibraryClasses.common.DXE_DRIVER] > SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf > PerformanceLib|MdeModulePkg/Library/DxePerformanceLib/DxePerformanceLib.inf > MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf > + FlashLib|Silicon/Ampere/AmpereAltraPkg/Library/FlashLib/FlashLib.inf > > [LibraryClasses.common.UEFI_APPLICATION] > UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiTianoCustomDecompressLib.inf > @@ -254,6 +256,7 @@ [LibraryClasses.common.DXE_RUNTIME_DRIVER] > > EfiResetSystemLib|ArmPkg/Library/ArmPsciResetSystemLib/ArmPsciResetSystemLib.inf > ArmSmcLib|ArmPkg/Library/ArmSmcLib/ArmSmcLib.inf > + FlashLib|Silicon/Ampere/AmpereAltraPkg/Library/FlashLib/FlashLib.inf > > [LibraryClasses.ARM,LibraryClasses.AARCH64] > # > @@ -500,6 +503,8 @@ [PcdsDynamicDefault.common] > gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase64|0x0 > gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase64|0x0 > > + gAmpereTokenSpaceGuid.PcdNvramErased|FALSE > + > ################################################################################ > # > # Component Section - list of all EDK II Component Entries defined by this Platform > @@ -520,8 +525,10 @@ [Components.common] > Silicon/Ampere/AmpereAltraPkg/Drivers/ATFHobPei/ATFHobPeim.inf > Silicon/Ampere/AmpereAltraPkg/Drivers/MemoryInitPeim/MemoryInitPeim.inf > Silicon/Ampere/AmpereAltraPkg/Drivers/MmCommunicationPei/MmCommunicationPei.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 { > > @@ -575,9 +582,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 f37ab1a92e44..9b9a5d0bad0f 100755 > --- a/Platform/Ampere/JadePkg/Jade.dsc > +++ b/Platform/Ampere/JadePkg/Jade.dsc > @@ -52,6 +52,7 @@ [Defines] > DEFINE EDK2_SKIP_PEICORE = TRUE > DEFINE SECURE_BOOT_ENABLE = FALSE > DEFINE INCLUDE_TFTP_COMMAND = TRUE > + DEFINE UEFI_UUID = 84BC921F-9D4A-4D1D-A1A1-1AE13EDD07E5 This is a horrible name for a UUID. What is it meant to identify? > # > # Network definition > diff --git a/Platform/Ampere/JadePkg/Jade.fdf b/Platform/Ampere/JadePkg/Jade.fdf > index 1857296a8ea5..375455086d0b 100755 > --- 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 > -# T.B.D Ah. If I can make a retroactive comment - could this be introduced as "Placeholder" rather than "T.B.D."? / Leif > +# 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 > > ################################################################################ > # > @@ -102,9 +155,11 @@ [FV.FVMAIN_COMPACT] > INF Silicon/Ampere/AmpereAltraPkg/Drivers/ATFHobPei/ATFHobPeim.inf > INF Silicon/Ampere/AmpereAltraPkg/Drivers/MemoryInitPeim/MemoryInitPeim.inf > INF Silicon/Ampere/AmpereAltraPkg/Drivers/MmCommunicationPei/MmCommunicationPei.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/ReportStatusCodeRouter/RuntimeDxe/ReportStatusCodeRouterRuntimeDxe.inf > INF MdeModulePkg/Universal/StatusCodeHandler/RuntimeDxe/StatusCodeHandlerRuntimeDxe.inf > INF Silicon/Ampere/AmpereAltraPkg/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..782278615094 > --- /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 > + gEfiMmCommunicationProtocolGuid ## CONSUMES > + > +[Depex] > + gEfiMmCommunicationProtocolGuid > diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/FlashPei/FlashPei.inf b/Silicon/Ampere/AmpereAltraPkg/Drivers/FlashPei/FlashPei.inf > new file mode 100644 > index 000000000000..a4eaf5039bb0 > --- /dev/null > +++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/FlashPei/FlashPei.inf > @@ -0,0 +1,51 @@ > +## @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 > + MmCommunicationLib > + PcdLib > + PeimEntryPoint > + > +[Guids] > + gSpiNorMmGuid > + > +[FixedPcd] > + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize > + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize > + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize > + > +[Pcd] > + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64 > + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase64 > + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase64 > + > + gAmpereTokenSpaceGuid.PcdNvramErased > + > +[Depex] > + TRUE > diff --git a/Silicon/Ampere/AmpereAltraPkg/Library/FlashLib/FlashLib.inf b/Silicon/Ampere/AmpereAltraPkg/Library/FlashLib/FlashLib.inf > new file mode 100644 > index 000000000000..2d5003d1af17 > --- /dev/null > +++ b/Silicon/Ampere/AmpereAltraPkg/Library/FlashLib/FlashLib.inf > @@ -0,0 +1,36 @@ > +## @file > +# > +# Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.
> +# > +# SPDX-License-Identifier: BSD-2-Clause-Patent > +# > +## > + > +[Defines] > + INF_VERSION = 0x0001001B > + BASE_NAME = FlashLib > + FILE_GUID = 9E9D093D-6484-45AE-BA49-0745AA0BB481 > + MODULE_TYPE = DXE_DRIVER > + VERSION_STRING = 0.1 > + LIBRARY_CLASS = FlashLib > + CONSTRUCTOR = FlashLibConstructor > + > +[Sources.common] > + FlashLib.c > + > +[Packages] > + ArmPkg/ArmPkg.dec > + ArmPlatformPkg/ArmPlatformPkg.dec > + MdePkg/MdePkg.dec > + Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec > + > +[LibraryClasses] > + BaseMemoryLib > + DebugLib > + MemoryAllocationLib > + > +[Guids] > + gSpiNorMmGuid > + > +[Protocols] > + gEfiMmCommunicationProtocolGuid > diff --git a/Silicon/Ampere/AmpereAltraPkg/Include/Library/FlashLib.h b/Silicon/Ampere/AmpereAltraPkg/Include/Library/FlashLib.h > new file mode 100644 > index 000000000000..9207dee643a5 > --- /dev/null > +++ b/Silicon/Ampere/AmpereAltraPkg/Include/Library/FlashLib.h > @@ -0,0 +1,42 @@ > +/** @file > + > + Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.
> + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#ifndef FLASH_LIB_H_ > +#define FLASH_LIB_H_ > + > +EFI_STATUS > +EFIAPI > +FlashGetNvRamInfo ( > + OUT UINT64 *NvRamBase, > + OUT UINT32 *NvRamSize > + ); > + > +EFI_STATUS > +EFIAPI > +FlashEraseCommand ( > + IN UINT8 *pBlockAddress, > + IN UINT32 Length > + ); > + > +EFI_STATUS > +EFIAPI > +FlashProgramCommand ( > + IN UINT8 *pByteAddress, > + IN UINT8 *Byte, > + IN OUT UINTN *Length > + ); > + > +EFI_STATUS > +EFIAPI > +FlashReadCommand ( > + IN UINT8 *pByteAddress, > + OUT UINT8 *Byte, > + IN OUT UINTN *Length > + ); > + > +#endif /* FLASH_LIB_H_ */ > diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/FlashFvbDxe/FlashFvbDxe.c b/Silicon/Ampere/AmpereAltraPkg/Drivers/FlashFvbDxe/FlashFvbDxe.c > new file mode 100644 > index 000000000000..dcd92151b7d2 > --- /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 ( > + (UINT8 *)(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 = FlashProgramCommand ( > + (UINT8 *)(mNvFlashBase + Lba * mFlashBlockSize + Offset), > + Buffer, > + NumBytes > + ); > + > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "Failed to do flash program\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 ( > + (UINT8 *)(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 ((UINT64 *)&mNvFlashBase, (UINT32 *)&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..6bfbbbebaa85 > --- /dev/null > +++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/FlashPei/FlashPei.c > @@ -0,0 +1,283 @@ > +/** @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 > +#include > + > +// Convert to string > +#define _STR(x) #x > + > +// Make sure the argument is expanded before converting to string > +#define STR(x) _STR(x) > + > +// Use dynamic UEFI_UUID of each build time > +#define UEFI_UUID_BUILD STR(UEFI_UUID) > + > +EFI_MM_COMM_REQUEST mEfiMmSpiNorReq; > + > +STATIC CHAR8 mBuildUuid[sizeof (UEFI_UUID_BUILD)]; > +STATIC CHAR8 mStoredUuid[sizeof (UEFI_UUID_BUILD)]; > + > +STATIC > +EFI_STATUS > +UefiMmCreateSpiNorReq ( > + VOID *Data, > + UINT64 Size > + ) > +{ > + CopyGuid (&mEfiMmSpiNorReq.EfiMmHdr.HeaderGuid, &gSpiNorMmGuid); > + mEfiMmSpiNorReq.EfiMmHdr.MsgLength = Size; > + > + if (Size != 0) { > + ASSERT (Data); > + ASSERT (Size <= EFI_MM_MAX_PAYLOAD_SIZE); > + > + CopyMem (mEfiMmSpiNorReq.PayLoad.Data, Data, Size); > + } > + > + return EFI_SUCCESS; > +} > + > +/** > + 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 > + ) > +{ > + UINT64 FWNvRamStartOffset; > + EFI_STATUS Status; > + EFI_MM_COMMUNICATE_SPINOR_RES *MmSpiNorRes; > + EFI_MM_COMMUNICATE_SPINOR_NVINFO_RES *MmSpiNorNVInfoRes; > + UINT64 MmData[5]; > + UINTN Size; > + VOID *NvRamAddress; > + UINTN NvRamSize; > + > +#if defined(RAM_BLOCKIO_START_ADDRESS) && defined(RAM_BLOCKIO_SIZE) > + EFI_MM_COMMUNICATE_SPINOR_NVINFO_RES *MmSpiNorNV2InfoRes; > + UINT64 NV2Base, NV2Size; > +#endif > + > + NvRamAddress = (VOID *)PcdGet64 (PcdFlashNvStorageVariableBase64); > + NvRamSize = FixedPcdGet32 (PcdFlashNvStorageVariableSize) + > + FixedPcdGet32 (PcdFlashNvStorageFtwWorkingSize) + > + FixedPcdGet32 (PcdFlashNvStorageFtwSpareSize); > + > + /* Find out about the start offset of NVRAM to be passed to SMC */ > + ZeroMem ((VOID *)MmData, sizeof (MmData)); > + MmData[0] = MM_SPINOR_FUNC_GET_NVRAM_INFO; > + UefiMmCreateSpiNorReq ((VOID *)&MmData, sizeof (MmData)); > + > + Size = sizeof (EFI_MM_COMM_HEADER_NOPAYLOAD) + sizeof (MmData); > + Status = MmCommunicationCommunicate ( > + (VOID *)&mEfiMmSpiNorReq, > + &Size > + ); > + ASSERT_EFI_ERROR (Status); > + > + MmSpiNorNVInfoRes = (EFI_MM_COMMUNICATE_SPINOR_NVINFO_RES *)&mEfiMmSpiNorReq.PayLoad; > + if (MmSpiNorNVInfoRes->Status != MM_SPINOR_RES_SUCCESS) { > + /* Old FW so just exit */ > + return EFI_SUCCESS; > + } > + FWNvRamStartOffset = MmSpiNorNVInfoRes->NVBase; > + > + CopyMem ((VOID *)mBuildUuid, (VOID *)UEFI_UUID_BUILD, sizeof (UEFI_UUID_BUILD)); > + if (MmSpiNorNVInfoRes->NVSize < (NvRamSize * 2 + sizeof (mBuildUuid))) { > + /* NVRAM size provided by FW is not enough */ > + return EFI_INVALID_PARAMETER; > + } > + > + /* We stored BIOS UUID build at the offset NVRAM_SIZE * 2 */ > + ZeroMem ((VOID *)MmData, sizeof (MmData)); > + MmData[0] = MM_SPINOR_FUNC_READ; > + MmData[1] = (UINT64)(FWNvRamStartOffset + NvRamSize * 2); > + MmData[2] = (UINT64)sizeof (mStoredUuid); > + MmData[3] = (UINT64)mStoredUuid; > + UefiMmCreateSpiNorReq ((VOID *)&MmData, sizeof (MmData)); > + > + Size = sizeof (EFI_MM_COMM_HEADER_NOPAYLOAD) + sizeof (MmData); > + Status = MmCommunicationCommunicate ( > + (VOID *)&mEfiMmSpiNorReq, > + &Size > + ); > + ASSERT_EFI_ERROR (Status); > + > + MmSpiNorRes = (EFI_MM_COMMUNICATE_SPINOR_RES *)&mEfiMmSpiNorReq.PayLoad; > + if (MmSpiNorRes->Status != MM_SPINOR_RES_SUCCESS) { > + return Status; > + } > + > + if (CompareMem ((VOID *)mStoredUuid, (VOID *)mBuildUuid, sizeof (mBuildUuid))) { > + ZeroMem ((VOID *)MmData, sizeof (MmData)); > + MmData[0] = MM_SPINOR_FUNC_ERASE; > + MmData[1] = (UINT64)FWNvRamStartOffset; > + MmData[2] = (UINT64)(NvRamSize * 2); > + UefiMmCreateSpiNorReq ((VOID *)&MmData, sizeof (MmData)); > + > + Size = sizeof (EFI_MM_COMM_HEADER_NOPAYLOAD) + sizeof (MmData); > + Status = MmCommunicationCommunicate ( > + (VOID *)&mEfiMmSpiNorReq, > + &Size > + ); > + ASSERT_EFI_ERROR (Status); > + > + MmSpiNorRes = (EFI_MM_COMMUNICATE_SPINOR_RES *)&mEfiMmSpiNorReq.PayLoad; > + if (MmSpiNorRes->Status != MM_SPINOR_RES_SUCCESS) { > + return Status; > + } > + > + ZeroMem ((VOID *)MmData, sizeof (MmData)); > + MmData[0] = MM_SPINOR_FUNC_WRITE; > + MmData[1] = (UINT64)FWNvRamStartOffset; > + MmData[2] = (UINT64)(NvRamSize * 2); > + MmData[3] = (UINT64)NvRamAddress; > + UefiMmCreateSpiNorReq ((VOID *)&MmData, sizeof (MmData)); > + > + Size = sizeof (EFI_MM_COMM_HEADER_NOPAYLOAD) + sizeof (MmData); > + Status = MmCommunicationCommunicate ( > + (VOID *)&mEfiMmSpiNorReq, > + &Size > + ); > + ASSERT_EFI_ERROR (Status); > + > + MmSpiNorRes = (EFI_MM_COMMUNICATE_SPINOR_RES *)&mEfiMmSpiNorReq.PayLoad; > + if (MmSpiNorRes->Status != MM_SPINOR_RES_SUCCESS) { > + return Status; > + } > + > + /* Update UUID */ > + ZeroMem ((VOID *)MmData, sizeof (MmData)); > + MmData[0] = MM_SPINOR_FUNC_ERASE; > + MmData[1] = (UINT64)(FWNvRamStartOffset + NvRamSize * 2); > + MmData[2] = (UINT64)sizeof (mBuildUuid); > + UefiMmCreateSpiNorReq ((VOID *)&MmData, sizeof (MmData)); > + > + Size = sizeof (EFI_MM_COMM_HEADER_NOPAYLOAD) + sizeof (MmData); > + Status = MmCommunicationCommunicate ( > + (VOID *)&mEfiMmSpiNorReq, > + &Size > + ); > + ASSERT_EFI_ERROR (Status); > + > + MmSpiNorRes = (EFI_MM_COMMUNICATE_SPINOR_RES *)&mEfiMmSpiNorReq.PayLoad; > + if (MmSpiNorRes->Status != MM_SPINOR_RES_SUCCESS) { > + return Status; > + } > + > + ZeroMem ((VOID *)MmData, sizeof (MmData)); > + MmData[0] = MM_SPINOR_FUNC_WRITE; > + MmData[1] = (UINT64)(FWNvRamStartOffset + NvRamSize * 2); > + MmData[2] = (UINT64)sizeof (mBuildUuid); > + MmData[3] = (UINT64)mBuildUuid; > + UefiMmCreateSpiNorReq ((VOID *)&MmData, sizeof (MmData)); > + > + Size = sizeof (EFI_MM_COMM_HEADER_NOPAYLOAD) + sizeof (MmData); > + Status = MmCommunicationCommunicate ( > + (VOID *)&mEfiMmSpiNorReq, > + &Size > + ); > + ASSERT_EFI_ERROR (Status); > + > + MmSpiNorRes = (EFI_MM_COMMUNICATE_SPINOR_RES *)&mEfiMmSpiNorReq.PayLoad; > + if (MmSpiNorRes->Status != MM_SPINOR_RES_SUCCESS) { > + return Status; > + } > + DEBUG ((DEBUG_INFO, "UUID Changed, Update Storage with FV NVRAM\n")); > + > + /* Indicate that NVRAM was cleared */ > + PcdSetBoolS (PcdNvramErased, TRUE); > + } else { > + /* Copy the stored NVRAM to RAM */ > + ZeroMem ((VOID *)MmData, sizeof (MmData)); > + MmData[0] = MM_SPINOR_FUNC_READ; > + MmData[1] = (UINT64)FWNvRamStartOffset; > + MmData[2] = (UINT64)(NvRamSize * 2); > + MmData[3] = (UINT64)NvRamAddress; > + UefiMmCreateSpiNorReq ((VOID *)&MmData, sizeof (MmData)); > + > + Size = sizeof (EFI_MM_COMM_HEADER_NOPAYLOAD) + sizeof (MmData); > + Status = MmCommunicationCommunicate ( > + (VOID *)&mEfiMmSpiNorReq, > + &Size > + ); > + ASSERT_EFI_ERROR (Status); > + > + MmSpiNorRes = (EFI_MM_COMMUNICATE_SPINOR_RES *)&mEfiMmSpiNorReq.PayLoad; > + if (MmSpiNorRes->Status != MM_SPINOR_RES_SUCCESS) { > + return Status; > + } > + DEBUG ((DEBUG_INFO, "Identical UUID, copy stored NVRAM to RAM\n")); > + } > + > +#if defined(RAM_BLOCKIO_START_ADDRESS) && defined(RAM_BLOCKIO_SIZE) > + /* Find out about the start offset of NVRAM2 to be passed to SMC */ > + ZeroMem ((VOID *)MmData, sizeof (MmData)); > + MmData[0] = MM_SPINOR_FUNC_GET_NVRAM2_INFO; > + UefiMmCreateSpiNorReq ((VOID *)&MmData, sizeof (MmData)); > + > + Size = sizeof (EFI_MM_COMM_HEADER_NOPAYLOAD) + sizeof (MmData); > + Status = MmCommunicationCommunicate ( > + (VOID *)&mEfiMmSpiNorReq, > + &Size > + ); > + ASSERT_EFI_ERROR (Status); > + > + MmSpiNorNV2InfoRes = (EFI_MM_COMMUNICATE_SPINOR_NVINFO_RES *)&mEfiMmSpiNorReq.PayLoad; > + if (MmSpiNorNV2InfoRes->Status == MM_SPINOR_RES_SUCCESS) { > + NV2Base = MmSpiNorNV2InfoRes->NVBase; > + NV2Size = MmSpiNorNV2InfoRes->NVSize; > + /* Make sure the requested size is smaller than allocated */ > + if (RAM_BLOCKIO_SIZE <= NV2Size) { > + /* Copy the ramdisk image to RAM */ > + ZeroMem ((VOID *)MmData, sizeof (MmData)); > + MmData[0] = MM_SPINOR_FUNC_READ; > + MmData[1] = (UINT64)NV2Base; /* Start virtual address */ > + MmData[2] = (UINT64)RAM_BLOCKIO_SIZE; > + MmData[3] = (UINT64)RAM_BLOCKIO_START_ADDRESS; > + UefiMmCreateSpiNorReq ((VOID *)&MmData, sizeof (MmData)); > + > + Size = sizeof (EFI_MM_COMM_HEADER_NOPAYLOAD) + sizeof (MmData); > + Status = MmCommunicationCommunicate ( > + (VOID *)&mEfiMmSpiNorReq, > + &Size > + ); > + ASSERT_EFI_ERROR (Status); > + > + MmSpiNorRes = (EFI_MM_COMMUNICATE_SPINOR_RES *)&mEfiMmSpiNorReq.PayLoad; > + ASSERT (MmSpiNorRes->Status == MM_SPINOR_RES_SUCCESS); > + } > + > + BuildMemoryAllocationHob ( > + (EFI_PHYSICAL_ADDRESS)RAM_BLOCKIO_START_ADDRESS, > + EFI_SIZE_TO_PAGES (RAM_BLOCKIO_SIZE) * EFI_PAGE_SIZE, > + EfiLoaderData > + ); > + } > +#endif > + > + return EFI_SUCCESS; > +} > diff --git a/Silicon/Ampere/AmpereAltraPkg/Library/FlashLib/FlashLib.c b/Silicon/Ampere/AmpereAltraPkg/Library/FlashLib/FlashLib.c > new file mode 100644 > index 000000000000..cd77aed3cfe1 > --- /dev/null > +++ b/Silicon/Ampere/AmpereAltraPkg/Library/FlashLib/FlashLib.c > @@ -0,0 +1,358 @@ > +/** @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 > +#include > + > +STATIC EFI_MM_COMMUNICATION_PROTOCOL *mMmCommunicationProtocol = NULL; > +STATIC EFI_MM_COMM_REQUEST *mCommBuffer = NULL; > + > +BOOLEAN mIsEfiRuntime; > +UINT8 *mTmpBufVirt; > +UINT8 *mTmpBufPhy; > + > +/** > + This is a notification function registered on EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE > + event. It converts a pointer to a new virtual address. > + > + @param Event Event whose notification function is being invoked. > + @param Context Pointer to the notification function's context > + > +**/ > +VOID > +EFIAPI > +FlashLibAddressChangeEvent ( > + IN EFI_EVENT Event, > + IN VOID *Context > + ) > +{ > + gRT->ConvertPointer (0x0, (VOID **)&mTmpBufVirt); > + gRT->ConvertPointer (0x0, (VOID **)&mCommBuffer); > + gRT->ConvertPointer (0x0, (VOID **)&mMmCommunicationProtocol); > + > + mIsEfiRuntime = TRUE; > +} > + > +EFI_STATUS > +EFIAPI > +FlashLibConstructor ( > + IN EFI_HANDLE ImageHandle, > + IN EFI_SYSTEM_TABLE *SystemTable > + ) > +{ > + EFI_EVENT VirtualAddressChangeEvent = NULL; > + EFI_STATUS Status = EFI_SUCCESS; > + > + mCommBuffer = AllocateRuntimeZeroPool (sizeof (EFI_MM_COMM_REQUEST)); > + ASSERT (mCommBuffer != NULL); > + > + mTmpBufPhy = AllocateRuntimeZeroPool (EFI_MM_MAX_TMP_BUF_SIZE); > + mTmpBufVirt = mTmpBufPhy; > + ASSERT (mTmpBufPhy != NULL); > + > + Status = gBS->LocateProtocol ( > + &gEfiMmCommunicationProtocolGuid, > + NULL, > + (VOID **)&mMmCommunicationProtocol > + ); > + ASSERT_EFI_ERROR (Status); > + > + Status = gBS->CreateEvent ( > + EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE, > + TPL_CALLBACK, > + FlashLibAddressChangeEvent, > + NULL, > + &VirtualAddressChangeEvent > + ); > + ASSERT_EFI_ERROR (Status); > + > + return EFI_SUCCESS; > +} > + > +STATIC > +EFI_STATUS > +FlashMmCommunicate ( > + IN OUT VOID *CommBuffer, > + IN OUT UINTN *CommSize > + ) > +{ > + if (mMmCommunicationProtocol == NULL) { > + return EFI_INVALID_PARAMETER; > + } > + > + return mMmCommunicationProtocol->Communicate ( > + mMmCommunicationProtocol, > + CommBuffer, > + CommSize > + ); > +} > + > +STATIC > +EFI_STATUS > +UefiMmCreateSpiNorReq ( > + IN VOID *Data, > + IN UINT64 Size > + ) > +{ > + if (mCommBuffer == NULL) { > + return EFI_INVALID_PARAMETER; > + } > + > + CopyGuid (&mCommBuffer->EfiMmHdr.HeaderGuid, &gSpiNorMmGuid); > + mCommBuffer->EfiMmHdr.MsgLength = Size; > + > + if (Size != 0) { > + ASSERT (Data); > + ASSERT (Size <= EFI_MM_MAX_PAYLOAD_SIZE); > + > + CopyMem (mCommBuffer->PayLoad.Data, Data, Size); > + } > + > + return EFI_SUCCESS; > +} > + > +/** > + Convert Virtual Address to Physical Address at Runtime Services > + > + @param VirtualPtr Virtual Address Pointer > + @param Size Total bytes of the buffer > + > + @retval Ptr Return the pointer of the converted address > + > +**/ > +STATIC > +UINT8 * > +ConvertVirtualToPhysical ( > + IN UINT8 *VirtualPtr, > + IN UINTN Size > + ) > +{ > + if (mIsEfiRuntime) { > + ASSERT (VirtualPtr != NULL); > + CopyMem ((VOID *)mTmpBufVirt, (VOID *)VirtualPtr, Size); > + return (UINT8 *)mTmpBufPhy; > + } > + > + return (UINT8 *)VirtualPtr; > +} > + > +/** > + Convert Physical Address to Virtual Address at Runtime Services > + > + @param VirtualPtr Physical Address Pointer > + @param Size Total bytes of the buffer > + > +**/ > +STATIC > +VOID > +ConvertPhysicaltoVirtual ( > + IN UINT8 *PhysicalPtr, > + IN UINTN Size > + ) > +{ > + if (mIsEfiRuntime) { > + ASSERT (PhysicalPtr != NULL); > + CopyMem ((VOID *)PhysicalPtr, (VOID *)mTmpBufVirt, Size); > + } > +} > + > +EFI_STATUS > +EFIAPI > +FlashGetNvRamInfo ( > + OUT UINT64 *NvRamBase, > + OUT UINT32 *NvRamSize > + ) > +{ > + EFI_MM_COMMUNICATE_SPINOR_NVINFO_RES *MmSpiNorNVInfoRes; > + EFI_STATUS Status; > + UINT64 MmData[5]; > + UINTN Size; > + > + MmData[0] = MM_SPINOR_FUNC_GET_NVRAM_INFO; > + > + Status = UefiMmCreateSpiNorReq ((VOID *)&MmData, sizeof (MmData)); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + Size = sizeof (EFI_MM_COMM_HEADER_NOPAYLOAD) + sizeof (MmData); > + Status = FlashMmCommunicate ( > + mCommBuffer, > + &Size > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + MmSpiNorNVInfoRes = (EFI_MM_COMMUNICATE_SPINOR_NVINFO_RES *)&mCommBuffer->PayLoad; > + if (MmSpiNorNVInfoRes->Status == MM_SPINOR_RES_SUCCESS) { > + *NvRamBase = MmSpiNorNVInfoRes->NVBase; > + *NvRamSize = MmSpiNorNVInfoRes->NVSize; > + DEBUG ((DEBUG_INFO, "NVInfo Base 0x%llx, Size 0x%lx\n", *NvRamBase, *NvRamSize)); > + } > + > + return EFI_SUCCESS; > +} > + > +EFI_STATUS > +EFIAPI > +FlashEraseCommand ( > + IN UINT8 *pBlockAddress, > + IN UINT32 Length > + ) > +{ > + EFI_MM_COMMUNICATE_SPINOR_RES *MmSpiNorRes; > + EFI_STATUS Status; > + UINT64 MmData[5]; > + UINTN Size; > + > + ASSERT (pBlockAddress != NULL); > + > + MmData[0] = MM_SPINOR_FUNC_ERASE; > + MmData[1] = (UINT64)pBlockAddress; > + MmData[2] = Length; > + > + Status = UefiMmCreateSpiNorReq ((VOID *)&MmData, sizeof (MmData)); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + Size = sizeof (EFI_MM_COMM_HEADER_NOPAYLOAD) + sizeof (MmData); > + Status = FlashMmCommunicate ( > + mCommBuffer, > + &Size > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + MmSpiNorRes = (EFI_MM_COMMUNICATE_SPINOR_RES *)&mCommBuffer->PayLoad; > + if (MmSpiNorRes->Status != MM_SPINOR_RES_SUCCESS) { > + DEBUG ((DEBUG_ERROR, "Flash Erase: Device error %llx\n", MmSpiNorRes->Status)); > + return EFI_DEVICE_ERROR; > + } > + > + return EFI_SUCCESS; > +} > + > +EFI_STATUS > +EFIAPI > +FlashProgramCommand ( > + IN UINT8 *pByteAddress, > + IN UINT8 *Byte, > + IN OUT UINTN *Length > + ) > +{ > + EFI_MM_COMMUNICATE_SPINOR_RES *MmSpiNorRes; > + EFI_STATUS Status; > + UINT64 MmData[5]; > + UINTN Remain, Size, NumWrite; > + UINTN Count = 0; > + > + ASSERT (pByteAddress != NULL); > + ASSERT (Byte != NULL); > + ASSERT (Length != NULL); > + > + Remain = *Length; > + while (Remain > 0) { > + NumWrite = (Remain > EFI_MM_MAX_TMP_BUF_SIZE) ? EFI_MM_MAX_TMP_BUF_SIZE : Remain; > + > + MmData[0] = MM_SPINOR_FUNC_WRITE; > + MmData[1] = (UINT64)pByteAddress; > + MmData[2] = NumWrite; > + MmData[3] = (UINT64)ConvertVirtualToPhysical (Byte + Count, NumWrite); > + > + Status = UefiMmCreateSpiNorReq ((VOID *)&MmData, sizeof (MmData)); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + Size = sizeof (EFI_MM_COMM_HEADER_NOPAYLOAD) + sizeof (MmData); > + Status = FlashMmCommunicate ( > + mCommBuffer, > + &Size > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + MmSpiNorRes = (EFI_MM_COMMUNICATE_SPINOR_RES *)&mCommBuffer->PayLoad; > + if (MmSpiNorRes->Status != MM_SPINOR_RES_SUCCESS) { > + DEBUG ((DEBUG_ERROR, "Flash program: Device error 0x%llx\n", MmSpiNorRes->Status)); > + return EFI_DEVICE_ERROR; > + } > + > + Remain -= NumWrite; > + Count += NumWrite; > + } > + > + return EFI_SUCCESS; > +} > + > +EFI_STATUS > +EFIAPI > +FlashReadCommand ( > + IN UINT8 *pByteAddress, > + OUT UINT8 *Byte, > + IN OUT UINTN *Length > + ) > +{ > + EFI_MM_COMMUNICATE_SPINOR_RES *MmSpiNorRes; > + EFI_STATUS Status; > + UINT64 MmData[5]; > + UINTN Remain, Size, NumRead; > + UINTN Count = 0; > + > + ASSERT (pByteAddress != NULL); > + ASSERT (Byte != NULL); > + ASSERT (Length != NULL); > + > + Remain = *Length; > + while (Remain > 0) { > + NumRead = (Remain > EFI_MM_MAX_TMP_BUF_SIZE) ? EFI_MM_MAX_TMP_BUF_SIZE : Remain; > + > + MmData[0] = MM_SPINOR_FUNC_READ; > + MmData[1] = (UINT64)pByteAddress; > + MmData[2] = NumRead; > + MmData[3] = (UINT64)ConvertVirtualToPhysical (Byte + Count, NumRead); > + > + Status = UefiMmCreateSpiNorReq ((VOID *)&MmData, sizeof (MmData)); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + Size = sizeof (EFI_MM_COMM_HEADER_NOPAYLOAD) + sizeof (MmData); > + Status = FlashMmCommunicate ( > + mCommBuffer, > + &Size > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + MmSpiNorRes = (EFI_MM_COMMUNICATE_SPINOR_RES *)&mCommBuffer->PayLoad; > + if (MmSpiNorRes->Status != MM_SPINOR_RES_SUCCESS) { > + DEBUG ((DEBUG_ERROR, "Flash Read: Device error %llx\n", MmSpiNorRes->Status)); > + return EFI_DEVICE_ERROR; > + } > + > + ConvertPhysicaltoVirtual (Byte + Count, NumRead); > + Remain -= NumRead; > + Count += NumRead; > + } > + > + return EFI_SUCCESS; > +} > -- > 2.17.1 >