From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=2607:f8b0:4001:c0b::231; helo=mail-it0-x231.google.com; envelope-from=ard.biesheuvel@linaro.org; receiver=edk2-devel@lists.01.org Received: from mail-it0-x231.google.com (mail-it0-x231.google.com [IPv6:2607:f8b0:4001:c0b::231]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id DE0CC210F624A for ; Fri, 15 Jun 2018 03:52:28 -0700 (PDT) Received: by mail-it0-x231.google.com with SMTP id n7-v6so2098792itn.1 for ; Fri, 15 Jun 2018 03:52:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc:content-transfer-encoding; bh=90jkQnhgk8by8Dzt8iapsDVmfoE+76RIy0Tuz3sRRIg=; b=bZ9j60twukXgymn20sfO++f4mJ/f+gvPNTRTjqVE6TJEuJh4vfhEcdU5pPwxlEkpTI +boWex2AFUSainJo5J9dhVq+axiQme6kSWaVKW1F4LHCZqz99HbMCwk6BtD93KB0YvAu 9NaoLL7lgNkme74r2b5IdSwP9eLi9eJsCHiY8= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc:content-transfer-encoding; bh=90jkQnhgk8by8Dzt8iapsDVmfoE+76RIy0Tuz3sRRIg=; b=mbHgeTwvl2vbQU5Uk5h0EuBRPb4yukbrxFQMNcx8Qt6nwFqPC8guTv3oI9JmH0K4xr jyVPdt4iNrjJATw5YPJDGaF3Na4JIR9j4gQ2G/ABkc0jGnGfhUG0fKjV9dmBwRW75bl1 oCpucSlml8WuRVNnQZHG1MdoOBezMqNq/O4A8LBIQfYGhqEKeZ5vh9BbfirKtnaS8hVf TNBt1PbBsjcwr1rRIgYSc0C2a8/MBFQS/7RMbSMlRv5xBHbiK/g3pNDDK0es+LgHqea5 NIGvQ1ZkWS7fQPoR2SQQL/sJtzOyT9hx0wQ/NXj1szfteIhPnrJ0LW4Iq2luwwn53QjS Xu3g== X-Gm-Message-State: APt69E3CVcOrJ00MtD/Ercr8e0P1oonjOPQs80iVCHv0+R3cIMEk5eR/ OsKFF0yYGBlHLxrcPElIrSgXa8bl+Qno031PrwDv7A== X-Google-Smtp-Source: ADUXVKITaps04BP4+catx/zgj/o2J8e8nWTZ5NEBRhhFX1TFRJsCmBrdjBTCXoDLXOcik5grfU9aCgh21IqNNQRwL6M= X-Received: by 2002:a02:6001:: with SMTP id i1-v6mr340122jac.5.1529059947929; Fri, 15 Jun 2018 03:52:27 -0700 (PDT) MIME-Version: 1.0 Received: by 2002:a6b:bbc7:0:0:0:0:0 with HTTP; Fri, 15 Jun 2018 03:52:27 -0700 (PDT) In-Reply-To: <0C09AFA07DD0434D9E2A0C6AEB0483103BB57B3D@shsmsx102.ccr.corp.intel.com> References: <20180613080901.7156-1-ard.biesheuvel@linaro.org> <20180613080901.7156-2-ard.biesheuvel@linaro.org> <0C09AFA07DD0434D9E2A0C6AEB0483103BB57B3D@shsmsx102.ccr.corp.intel.com> From: Ard Biesheuvel Date: Fri, 15 Jun 2018 12:52:27 +0200 Message-ID: To: "Zeng, Star" Cc: "edk2-devel@lists.01.org" , "leif.lindholm@linaro.org" , "Yao, Jiewen" , "Kinney, Michael D" Subject: Re: [PATCH v4 1/4] MdeModulePkg/CapsuleRuntimeDxe: clean the capsule payload to DRAM X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.26 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 15 Jun 2018 10:52:29 -0000 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable On 14 June 2018 at 02:54, Zeng, Star wrote: > With 'EFIAPI' removed from IsPersistAcrossResetCapsuleSupported and Capsu= leCacheWriteBack definitions, Reviewed-by: Star Zeng . > > You can wait a little more time in case Jiewen/Mike has comments. > Thank you Star. I will push these by the end of today unless anyone objects. > -----Original Message----- > From: Ard Biesheuvel [mailto:ard.biesheuvel@linaro.org] > Sent: Wednesday, June 13, 2018 4:09 PM > To: edk2-devel@lists.01.org > Cc: leif.lindholm@linaro.org; Zeng, Star ; Yao, Jiew= en ; Kinney, Michael D ; = Ard Biesheuvel > Subject: [PATCH v4 1/4] MdeModulePkg/CapsuleRuntimeDxe: clean the capsule= payload to DRAM > > When capsule updates are staged for processing after a warm reboot, they = are copied into memory with the MMU and caches enabled. When the capsule PE= I gets around to coalescing the capsule, the MMU and caches may still be di= sabled, and so on architectures where uncached accesses are incoherent with= the caches (such as ARM and AARCH64), we need to ensure that the data pass= ed into UpdateCapsule() is written back to main memory before performing th= e warm reboot. > > Unfortunately, on ARM, the only type of cache maintenance instructions th= at are suitable for this purpose operate on virtual addresses only, and giv= en that the UpdateCapsule() prototype includes the physical address of a li= nked list of scatter/gather data structures that are mapped at an address t= hat is unknown to the firmware (and may not even be mapped at all when Upda= teCapsule() is invoked), we can only perform this cache maintenance at boot= time. Fortunately, both Windows and Linux only invoke UpdateCapsule() befo= re calling ExitBootServices(), so this is not a problem in practice. > > In the future, we may propose adding a secure firmware service that permi= ts performing the cache maintenance at OS runtime, in which case this code = may be enhanced to call that service if available. For now, we just fail an= y UpdateCapsule() calls performed at OS runtime on ARM. > > Contributed-under: TianoCore Contribution Agreement 1.1 > Signed-off-by: Ard Biesheuvel > --- > MdeModulePkg/Universal/CapsuleRuntimeDxe/Arm/CapsuleReset.c | 77 ++++= ++++++++++++++++ > MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleReset.c | 51 ++++= +++++++++ > MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf | 14 +++- > MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.c | 33 ++--= ----- > MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.h | 73 ++++= +++++++++++++++ > 5 files changed, 219 insertions(+), 29 deletions(-) > > diff --git a/MdeModulePkg/Universal/CapsuleRuntimeDxe/Arm/CapsuleReset.c = b/MdeModulePkg/Universal/CapsuleRuntimeDxe/Arm/CapsuleReset.c > new file mode 100644 > index 000000000000..7e0ca06ce7d0 > --- /dev/null > +++ b/MdeModulePkg/Universal/CapsuleRuntimeDxe/Arm/CapsuleReset.c > @@ -0,0 +1,77 @@ > + /** @file > + ARM implementation of architecture specific routines related to > + PersistAcrossReset capsules > + > + Copyright (c) 2018, Linaro, Ltd. All rights reserved.
> + > + This program and the accompanying materials are licensed and made > + available under the terms and conditions of the BSD License which > + accompanies this distribution. The full text of the license may be > + found at http://opensource.org/licenses/bsd-license.php > + > + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IM= PLIED. > + > +**/ > + > +#include "CapsuleService.h" > + > +#include > + > +/** > + Whether the platform supports capsules that persist across reset. > +Note that > + some platforms only support such capsules at boot time. > + > + @return TRUE if a PersistAcrossReset capsule may be passed to UpdateC= apsule() > + at this time > + FALSE otherwise > +**/ > +BOOLEAN > +EFIAPI > +IsPersistAcrossResetCapsuleSupported ( > + VOID > + ) > +{ > + // > + // ARM requires the capsule payload to be cleaned to the point of > +coherency > + // (PoC), but only permits doing so using cache maintenance > +instructions that > + // operate on virtual addresses. Since at runtime, we don't know the > +virtual > + // addresses of the data structures that make up the scatter/gather > +list, we > + // cannot perform the maintenance, and all we can do is give up. > + // > + return FeaturePcdGet (PcdSupportUpdateCapsuleReset) && !EfiAtRuntime > +(); } > + > +/** > + Writes Back a range of data cache lines covering a set of capsules in = memory. > + > + Writes Back the data cache lines specified by ScatterGatherList. > + > + @param ScatterGatherList Physical address of the data structure that > + describes a set of capsules in memory > + > +**/ > +VOID > +EFIAPI > +CapsuleCacheWriteBack ( > + IN EFI_PHYSICAL_ADDRESS ScatterGatherList > + ) > +{ > + EFI_CAPSULE_BLOCK_DESCRIPTOR *Desc; > + > + Desc =3D (EFI_CAPSULE_BLOCK_DESCRIPTOR *)(UINTN)ScatterGatherList; do > + { > + WriteBackDataCacheRange (Desc, sizeof *Desc); > + > + if (Desc->Length > 0) { > + WriteBackDataCacheRange ((VOID *)(UINTN)Desc->Union.DataBlock, > + Desc->Length > + ); > + Desc++; > + } else if (Desc->Union.ContinuationPointer > 0) { > + Desc =3D (EFI_CAPSULE_BLOCK_DESCRIPTOR *)(UINTN)Desc->Union.Contin= uationPointer; > + } > + } while (Desc->Length > 0 || Desc->Union.ContinuationPointer > 0); > + > + WriteBackDataCacheRange (Desc, sizeof *Desc); } > diff --git a/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleReset.c b/Md= eModulePkg/Universal/CapsuleRuntimeDxe/CapsuleReset.c > new file mode 100644 > index 000000000000..09616999e3f8 > --- /dev/null > +++ b/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleReset.c > @@ -0,0 +1,51 @@ > +/** @file > + Default implementation of architecture specific routines related to > + PersistAcrossReset capsules > + > + Copyright (c) 2018, Linaro, Ltd. All rights reserved.
> + > + This program and the accompanying materials are licensed and made > + available under the terms and conditions of the BSD License which > + accompanies this distribution. The full text of the license may be > + found at http://opensource.org/licenses/bsd-license.php > + > + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IM= PLIED. > + > +**/ > + > +#include "CapsuleService.h" > + > +/** > + Whether the platform supports capsules that persist across reset. > +Note that > + some platforms only support such capsules at boot time. > + > + @return TRUE if a PersistAcrossReset capsule may be passed to UpdateC= apsule() > + at this time > + FALSE otherwise > +**/ > +BOOLEAN > +EFIAPI > +IsPersistAcrossResetCapsuleSupported ( > + VOID > + ) > +{ > + return FeaturePcdGet (PcdSupportUpdateCapsuleReset); } > + > +/** > + Writes Back a range of data cache lines covering a set of capsules in = memory. > + > + Writes Back the data cache lines specified by ScatterGatherList. > + > + @param ScatterGatherList Physical address of the data structure that > + describes a set of capsules in memory > + > +**/ > +VOID > +EFIAPI > +CapsuleCacheWriteBack ( > + IN EFI_PHYSICAL_ADDRESS ScatterGatherList > + ) > +{ > +} > diff --git a/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.i= nf b/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf > index 9ab04ce1b301..43a29ee22948 100644 > --- a/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf > +++ b/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf > @@ -27,17 +27,24 @@ [Defines] > # > # The following information is for reference only and not required by th= e build tools. > # > -# VALID_ARCHITECTURES =3D IA32 X64 IPF EBC > +# VALID_ARCHITECTURES =3D IA32 X64 IPF EBC ARM AARCH64 > # > > [Sources] > CapsuleService.c > + CapsuleService.h > > -[Sources.Ia32, Sources.IPF, Sources.EBC, Sources.ARM, Sources.AARCH64] > +[Sources.Ia32, Sources.IPF, Sources.EBC] > SaveLongModeContext.c > + CapsuleReset.c > > [Sources.X64] > X64/SaveLongModeContext.c > + CapsuleReset.c > + > +[Sources.ARM, Sources.AARCH64] > + SaveLongModeContext.c > + Arm/CapsuleReset.c > > [Packages] > MdePkg/MdePkg.dec > @@ -59,6 +66,9 @@ [LibraryClasses.X64] > UefiLib > BaseMemoryLib > > +[LibraryClasses.ARM, LibraryClasses.AARCH64] > + CacheMaintenanceLib > + > [Guids] > ## SOMETIMES_PRODUCES ## Variable:L"CapsuleUpdateData" # (Process ac= ross reset capsule image) for capsule updated data > ## SOMETIMES_PRODUCES ## Variable:L"CapsuleLongModeBuffer" # The lon= g mode buffer used by IA32 Capsule PEIM to call X64 CapsuleCoalesce code to= handle >4GB capsule blocks > diff --git a/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.c b/= MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.c > index 216798d1617e..23fd6d59c59e 100644 > --- a/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.c > +++ b/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.c > @@ -15,22 +15,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EIT= HER EXPRESS OR IMPLIED. > > **/ > > -#include > - > -#include > -#include > -#include > - > -#include > -#include > -#include > -#include -#include > -#include > -#include > -#include > -#include > -#include > +#include "CapsuleService.h" > + > // > // Handle for the installation of Capsule Architecture Protocol. > // > @@ -44,15 +30,6 @@ UINTN mTimes =3D 0; > UINT32 mMaxSizePopulateCapsule =3D 0; > UINT32 mMaxSizeNonPopulateCapsule =3D 0; > > -/** > - Create the variable to save the base address of page table and stack > - for transferring into long mode in IA32 PEI. > -**/ > -VOID > -SaveLongModeContext ( > - VOID > - ); > - > /** > Passes capsules to the firmware with both virtual and physical mapping= . Depending on the intended > consumption, the firmware may process the capsule immediately. If the = payload should persist @@ -194,10 +171,12 @@ UpdateCapsule ( > // > // Check if the platform supports update capsule across a system reset > // > - if (!FeaturePcdGet(PcdSupportUpdateCapsuleReset)) { > + if (!IsPersistAcrossResetCapsuleSupported ()) { > return EFI_UNSUPPORTED; > } > > + CapsuleCacheWriteBack (ScatterGatherList); > + > // > // Construct variable name CapsuleUpdateData, CapsuleUpdateData1, Caps= uleUpdateData2... > // if user calls UpdateCapsule multiple times. > @@ -344,7 +323,7 @@ QueryCapsuleCapabilities ( > // > //Check if the platform supports update capsule across a system rese= t > // > - if (!FeaturePcdGet(PcdSupportUpdateCapsuleReset)) { > + if (!IsPersistAcrossResetCapsuleSupported ()) { > return EFI_UNSUPPORTED; > } > *ResetType =3D EfiResetWarm; > diff --git a/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.h b/= MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.h > new file mode 100644 > index 000000000000..85aafc144b41 > --- /dev/null > +++ b/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.h > @@ -0,0 +1,73 @@ > +/** @file > + Capsule Runtime Driver produces two UEFI capsule runtime services. > + (UpdateCapsule, QueryCapsuleCapabilities) > + It installs the Capsule Architectural Protocol defined in PI1.0a to > +signify > + the capsule runtime services are ready. > + > + Copyright (c) 2006 - 2017, Intel Corporation. All rights > + reserved.
Copyright (c) 2018, Linaro, Ltd. All rights > + reserved.
> + > + This program and the accompanying materials are licensed and made > + available under the terms and conditions of the BSD License which > + accompanies this distribution. The full text of the license may be > + found at http://opensource.org/licenses/bsd-license.php > + > + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IM= PLIED. > + > +**/ > + > +#include > + > +#include > +#include > +#include > + > +#include > +#include > +#include > +#include #include > + > +#include > +#include > +#include > +#include > +#include > + > +/** > + Create the variable to save the base address of page table and stack > + for transferring into long mode in IA32 PEI. > +**/ > +VOID > +SaveLongModeContext ( > + VOID > + ); > + > +/** > + Whether the platform supports capsules that persist across reset. > +Note that > + some platforms only support such capsules at boot time. > + > + @return TRUE if a PersistAcrossReset capsule may be passed to UpdateC= apsule() > + at this time > + FALSE otherwise > +**/ > +BOOLEAN > +EFIAPI > +IsPersistAcrossResetCapsuleSupported ( > + VOID > + ); > + > +/** > + Writes Back a range of data cache lines covering a set of capsules in = memory. > + > + Writes Back the data cache lines specified by ScatterGatherList. > + > + @param ScatterGatherList Physical address of the data structure that > + describes a set of capsules in memory > + > +**/ > +VOID > +EFIAPI > +CapsuleCacheWriteBack ( > + IN EFI_PHYSICAL_ADDRESS ScatterGatherList > + ); > -- > 2.17.1 >