From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=134.134.136.100; helo=mga07.intel.com; envelope-from=star.zeng@intel.com; receiver=edk2-devel@lists.01.org Received: from mga07.intel.com (mga07.intel.com [134.134.136.100]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id DF7AC211A322E for ; Wed, 13 Jun 2018 17:54:05 -0700 (PDT) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by orsmga105.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 13 Jun 2018 17:54:05 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.51,220,1526367600"; d="scan'208";a="62992013" Received: from fmsmsx104.amr.corp.intel.com ([10.18.124.202]) by fmsmga004.fm.intel.com with ESMTP; 13 Jun 2018 17:54:05 -0700 Received: from FMSMSX109.amr.corp.intel.com (10.18.116.9) by fmsmsx104.amr.corp.intel.com (10.18.124.202) with Microsoft SMTP Server (TLS) id 14.3.319.2; Wed, 13 Jun 2018 17:54:04 -0700 Received: from shsmsx104.ccr.corp.intel.com (10.239.4.70) by fmsmsx109.amr.corp.intel.com (10.18.116.9) with Microsoft SMTP Server (TLS) id 14.3.319.2; Wed, 13 Jun 2018 17:54:03 -0700 Received: from shsmsx102.ccr.corp.intel.com ([169.254.2.223]) by SHSMSX104.ccr.corp.intel.com ([169.254.5.87]) with mapi id 14.03.0319.002; Thu, 14 Jun 2018 08:54:02 +0800 From: "Zeng, Star" To: Ard Biesheuvel , "edk2-devel@lists.01.org" CC: "leif.lindholm@linaro.org" , "Yao, Jiewen" , "Kinney, Michael D" , "Zeng, Star" Thread-Topic: [PATCH v4 1/4] MdeModulePkg/CapsuleRuntimeDxe: clean the capsule payload to DRAM Thread-Index: AQHUAu3bSf3J+WXAnUSnRrlxjdZWiqRe7gqw Date: Thu, 14 Jun 2018 00:54:00 +0000 Message-ID: <0C09AFA07DD0434D9E2A0C6AEB0483103BB57B3D@shsmsx102.ccr.corp.intel.com> References: <20180613080901.7156-1-ard.biesheuvel@linaro.org> <20180613080901.7156-2-ard.biesheuvel@linaro.org> In-Reply-To: <20180613080901.7156-2-ard.biesheuvel@linaro.org> Accept-Language: zh-CN, en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [10.239.127.40] MIME-Version: 1.0 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: Thu, 14 Jun 2018 00:54:06 -0000 Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable With 'EFIAPI' removed from IsPersistAcrossResetCapsuleSupported and Capsule= CacheWriteBack definitions, Reviewed-by: Star Zeng . You can wait a little more time in case Jiewen/Mike has comments. Thanks, Star -----Original Message----- From: Ard Biesheuvel [mailto:ard.biesheuvel@linaro.org]=20 Sent: Wednesday, June 13, 2018 4:09 PM To: edk2-devel@lists.01.org Cc: leif.lindholm@linaro.org; Zeng, Star ; Yao, Jiewen= ; Kinney, Michael D ; Ar= d Biesheuvel Subject: [PATCH v4 1/4] MdeModulePkg/CapsuleRuntimeDxe: clean the capsule p= ayload to DRAM When capsule updates are staged for processing after a warm reboot, they ar= e copied into memory with the MMU and caches enabled. When the capsule PEI = gets around to coalescing the capsule, the MMU and caches may still be disa= bled, and so on architectures where uncached accesses are incoherent with t= he caches (such as ARM and AARCH64), we need to ensure that the data passed= into UpdateCapsule() is written back to main memory before performing the = warm reboot. Unfortunately, on ARM, the only type of cache maintenance instructions that= are suitable for this purpose operate on virtual addresses only, and given= that the UpdateCapsule() prototype includes the physical address of a link= ed list of scatter/gather data structures that are mapped at an address tha= t is unknown to the firmware (and may not even be mapped at all when Update= Capsule() is invoked), we can only perform this cache maintenance at boot t= ime. Fortunately, both Windows and Linux only invoke UpdateCapsule() before= calling ExitBootServices(), so this is not a problem in practice. In the future, we may propose adding a secure firmware service that permits= performing the cache maintenance at OS runtime, in which case this code ma= y be enhanced to call that service if available. For now, we just fail any = 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 =20 + PersistAcrossReset capsules + + Copyright (c) 2018, Linaro, Ltd. All rights reserved.
+ + This program and the accompanying materials are licensed and made=20 + available under the terms and conditions of the BSD License which=20 + accompanies this distribution. The full text of the license may be=20 + found at http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, =20 + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPL= IED. + +**/ + +#include "CapsuleService.h" + +#include + +/** + Whether the platform supports capsules that persist across reset.=20 +Note that + some platforms only support such capsules at boot time. + + @return TRUE if a PersistAcrossReset capsule may be passed to UpdateCap= sule() + at this time + FALSE otherwise +**/ +BOOLEAN +EFIAPI +IsPersistAcrossResetCapsuleSupported ( + VOID + ) +{ + // + // ARM requires the capsule payload to be cleaned to the point of=20 +coherency + // (PoC), but only permits doing so using cache maintenance=20 +instructions that + // operate on virtual addresses. Since at runtime, we don't know the=20 +virtual + // addresses of the data structures that make up the scatter/gather=20 +list, we + // cannot perform the maintenance, and all we can do is give up. + // + return FeaturePcdGet (PcdSupportUpdateCapsuleReset) && !EfiAtRuntime=20 +(); } + +/** + Writes Back a range of data cache lines covering a set of capsules in me= mory. + + 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=20 + { + 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.Continua= tionPointer; + } + } while (Desc->Length > 0 || Desc->Union.ContinuationPointer > 0); + + WriteBackDataCacheRange (Desc, sizeof *Desc); } diff --git a/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleReset.c b/MdeM= odulePkg/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=20 + available under the terms and conditions of the BSD License which=20 + accompanies this distribution. The full text of the license may be=20 + found at http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, =20 + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPL= IED. + +**/ + +#include "CapsuleService.h" + +/** + Whether the platform supports capsules that persist across reset.=20 +Note that + some platforms only support such capsules at boot time. + + @return TRUE if a PersistAcrossReset capsule may be passed to UpdateCap= sule() + 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 me= mory. + + 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.inf= 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 the = build tools. # -# VALID_ARCHITECTURES =3D IA32 X64 IPF EBC +# VALID_ARCHITECTURES =3D IA32 X64 IPF EBC ARM AARCH64 # =20 [Sources] CapsuleService.c + CapsuleService.h =20 -[Sources.Ia32, Sources.IPF, Sources.EBC, Sources.ARM, Sources.AARCH64] +[Sources.Ia32, Sources.IPF, Sources.EBC] SaveLongModeContext.c + CapsuleReset.c =20 [Sources.X64] X64/SaveLongModeContext.c + CapsuleReset.c + +[Sources.ARM, Sources.AARCH64] + SaveLongModeContext.c + Arm/CapsuleReset.c =20 [Packages] MdePkg/MdePkg.dec @@ -59,6 +66,9 @@ [LibraryClasses.X64] UefiLib BaseMemoryLib =20 +[LibraryClasses.ARM, LibraryClasses.AARCH64] + CacheMaintenanceLib + [Guids] ## SOMETIMES_PRODUCES ## Variable:L"CapsuleUpdateData" # (Process acro= ss reset capsule image) for capsule updated data ## SOMETIMES_PRODUCES ## Variable:L"CapsuleLongModeBuffer" # The long = mode buffer used by IA32 Capsule PEIM to call X64 CapsuleCoalesce code to h= andle >4GB capsule blocks diff --git a/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.c b/Md= eModulePkg/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, EITHE= R EXPRESS OR IMPLIED. =20 **/ =20 -#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; =20 -/** - 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 pa= yload 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; } =20 + CapsuleCacheWriteBack (ScatterGatherList); + // // Construct variable name CapsuleUpdateData, CapsuleUpdateData1, Capsul= eUpdateData2... // if user calls UpdateCapsule multiple times. @@ -344,7 +323,7 @@ QueryCapsuleCapabilities ( // //Check if the platform supports update capsule across a system reset // - if (!FeaturePcdGet(PcdSupportUpdateCapsuleReset)) { + if (!IsPersistAcrossResetCapsuleSupported ()) { return EFI_UNSUPPORTED; } *ResetType =3D EfiResetWarm; diff --git a/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.h b/Md= eModulePkg/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=20 +signify + the capsule runtime services are ready. + + Copyright (c) 2006 - 2017, Intel Corporation. All rights=20 + reserved.
Copyright (c) 2018, Linaro, Ltd. All rights=20 + reserved.
+ + This program and the accompanying materials are licensed and made=20 + available under the terms and conditions of the BSD License which=20 + accompanies this distribution. The full text of the license may be=20 + found at http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, =20 + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPL= IED. + +**/ + +#include + +#include +#include +#include + +#include +#include +#include +#include #include=20 + +#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.=20 +Note that + some platforms only support such capsules at boot time. + + @return TRUE if a PersistAcrossReset capsule may be passed to UpdateCap= sule() + at this time + FALSE otherwise +**/ +BOOLEAN +EFIAPI +IsPersistAcrossResetCapsuleSupported ( + VOID + ); + +/** + Writes Back a range of data cache lines covering a set of capsules in me= mory. + + 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