From nobody Thu Apr 25 13:05:11 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+41948+1787277+3901457@groups.io; helo=web01.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+41948+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1559749342; cv=none; d=zoho.com; s=zohoarc; b=l0UmPcFKVdrlJITRKcgXmDKlpYhkvQy20GIN+H6/oWN71DzAHRuShvtzfC4JKm8Zl8ukNjs6YFGGJKN6fYwN653kCA6wOqQ9mEiwe2lETSJ9ayB2tBTkAyLDU9XiwrKqCjE6B8g22WmgpxpGXc+ynTYA+aBSUPc1NnPYyEdxEtw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1559749342; h=Cc:Date:From:In-Reply-To:List-Id:List-Unsubscribe:Message-ID:Reply-To:References:Sender:Subject:To:ARC-Authentication-Results; bh=yJ8iNfAl0JCsTZu0gRNdTwVMpclpAj7ZbHisA91CkKk=; b=QUoa8tBh7hY95Oaq+8DJuO6odClCACEYjUB3yprXUzbfBFtD/gqC0h7zo+yEjDK6znlCPuD37mJWH2sIArlX6WLuzV74xFSpySR3lHW4GAn16VL/13dd54JiO7wvUasIW3Rek9pvkMoEw6kXPS6zgNjRSo7cnDpB9BdvZ9e69p0= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=pass; spf=pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+41948+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) header.from= Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1559749342427359.62220004016194; Wed, 5 Jun 2019 08:42:22 -0700 (PDT) Return-Path: X-Received: from mga09.intel.com (mga09.intel.com []) by groups.io with SMTP; Wed, 05 Jun 2019 08:42:21 -0700 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-Received: from orsmga005.jf.intel.com ([10.7.209.41]) by orsmga102.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 05 Jun 2019 08:42:20 -0700 X-ExtLoop1: 1 X-Received: from shwdeopenpsi174.ccr.corp.intel.com ([10.239.157.33]) by orsmga005.jf.intel.com with ESMTP; 05 Jun 2019 08:42:19 -0700 From: "Xu, Wei6" To: devel@edk2.groups.io Cc: Michael D Kinney , Liming Gao , Chao B Zhang , Wei6 Xu Subject: [edk2-devel][Patch v2 1/7] MdePkg: Add Pei Boot In CapsuleOnDisk Mode Ppi definition. Date: Wed, 5 Jun 2019 23:41:57 +0800 Message-Id: <20190605154203.11012-2-wei6.xu@intel.com> In-Reply-To: <20190605154203.11012-1-wei6.xu@intel.com> References: <20190605154203.11012-1-wei6.xu@intel.com> Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,wei6.xu@intel.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1559749341; bh=lbFlwCRyTGkOtxtQm2Vrlfz4yt1Wddrc/Rdotv+H1Pc=; h=Cc:Date:From:Reply-To:Subject:To; b=pM5RYe6VhV4mQbdwwyY6mkS9SvkHjEdbZ9WDPFhedd982nNGhp4aqZZbZDs2pg2ny+U epxzVYj0GJKNO78BzWu+YBAN/kkAtvxX7GFY+5TQbZxJ20whvIfOcUY0HeaF+JVN3JsbY xJTSY2jmNFgm201ynJafFt9M/MzUFLWL37A= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3D1852 This PPI indicates current boot mode is capsule on disk mode. Cc: Michael D Kinney Cc: Liming Gao Cc: Chao B Zhang Signed-off-by: Wei6 Xu --- MdePkg/Include/Ppi/BootInRecoveryMode.h | 9 ++++++++- MdePkg/MdePkg.dec | 3 +++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/MdePkg/Include/Ppi/BootInRecoveryMode.h b/MdePkg/Include/Ppi/B= ootInRecoveryMode.h index ae40744d9b..71b0ca8586 100644 --- a/MdePkg/Include/Ppi/BootInRecoveryMode.h +++ b/MdePkg/Include/Ppi/BootInRecoveryMode.h @@ -1,10 +1,10 @@ /** @file This PPI is installed by the platform PEIM to designate that a recovery = boot is in progress. =20 - Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent =20 @par Revision Reference: This PPI is introduced in PI Version 1.0. =20 @@ -19,6 +19,13 @@ } =20 =20 extern EFI_GUID gEfiPeiBootInRecoveryModePpiGuid; =20 +#define EFI_PEI_BOOT_IN_CAPSULE_ON_DISK_MODE_PPI \ + { \ + 0xb08a11e4, 0xe2b7, 0x4b75, { 0xb5, 0x15, 0xaf, 0x61, 0x6, 0x68, 0xbf,= 0xd1 } \ + } + +extern EFI_GUID gEfiPeiBootInCapsuleOnDiskModePpiGuid; + #endif diff --git a/MdePkg/MdePkg.dec b/MdePkg/MdePkg.dec index 6c563375ee..ec02b8c7c7 100644 --- a/MdePkg/MdePkg.dec +++ b/MdePkg/MdePkg.dec @@ -790,10 +790,13 @@ gEfiPeiMemoryDiscoveredPpiGuid =3D {0xf894643d, 0xc449, 0x42d1, {0x8e, 0= xa8, 0x85, 0xbd, 0xd8, 0xc6, 0x5b, 0xde } } =20 ## Include/Ppi/BootInRecoveryMode.h gEfiPeiBootInRecoveryModePpiGuid =3D { 0x17ee496a, 0xd8e4, 0x4b9a, {0x94= , 0xd1, 0xce, 0x82, 0x72, 0x30, 0x8, 0x50 } } =20 + ## Include/Ppi/BootInRecoveryMode.h + gEfiPeiBootInCapsuleOnDiskModePpiGuid =3D { 0xb08a11e4, 0xe2b7, 0x4b75, = { 0xb5, 0x15, 0xaf, 0x61, 0x6, 0x68, 0xbf, 0xd1 } } + ## Include/Ppi/EndOfPeiPhase.h gEfiEndOfPeiSignalPpiGuid =3D {0x605EA650, 0xC65C, 0x42e1, {0xBA, 0x80, = 0x91, 0xA5, 0x2A, 0xB6, 0x18, 0xC6 } } =20 ## Include/Ppi/Reset.h gEfiPeiResetPpiGuid =3D { 0xef398d58, 0x9dfd, 0x4103, {0xbf, 0x94, 0x78,= 0xc6, 0xf4, 0xfe, 0x71, 0x2f } } --=20 2.16.2.windows.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#41948): https://edk2.groups.io/g/devel/message/41948 Mute This Topic: https://groups.io/mt/31938575/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Thu Apr 25 13:05:11 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+41949+1787277+3901457@groups.io; helo=web01.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+41949+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1559749344; cv=none; d=zoho.com; s=zohoarc; b=XjS9CrRT4psodogkWjH3A+1cBfJcAszlfpnirz68y+KONcMLBdAofQl531bgYkFWFs5DMF5C7zvnzvuoRXh55YnAKzssDyxG78sc1avSGXs2FjSJJJPSCGAj41yYd8igrP1phWv+FnpVgtMmRlJ5/NGFK/hMvZLEVSba5nDu9uc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1559749344; h=Cc:Date:From:In-Reply-To:List-Id:List-Unsubscribe:Message-ID:Reply-To:References:Sender:Subject:To:ARC-Authentication-Results; bh=YQMKkcHchCrX4CLvIKoo04bbFD/U0VXYB29A4TvdKJ4=; b=eU0CWoLll4LNChEMgT/U3mrfSMOJP33vfrj9vxED+x7KxCTEi7paLqEHi4fR9d9rICRZ4ydOia9r9GmOLX67Nqtfv+dWvwEQ7vQOROYBEa4gSjMEawBOMBuH3pV27BXqKtH8qehP1gzJcbqmySTqfChCyVrcPW8VrOnSRM7c2DM= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=pass; spf=pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+41949+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) header.from= Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1559749344965693.564047858364; Wed, 5 Jun 2019 08:42:24 -0700 (PDT) Return-Path: X-Received: from mga09.intel.com (mga09.intel.com []) by groups.io with SMTP; Wed, 05 Jun 2019 08:42:23 -0700 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-Received: from orsmga005.jf.intel.com ([10.7.209.41]) by orsmga102.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 05 Jun 2019 08:42:23 -0700 X-ExtLoop1: 1 X-Received: from shwdeopenpsi174.ccr.corp.intel.com ([10.239.157.33]) by orsmga005.jf.intel.com with ESMTP; 05 Jun 2019 08:42:22 -0700 From: "Xu, Wei6" To: devel@edk2.groups.io Cc: Jian J Wang , Hao A Wu , Chao B Zhang , Wei6 Xu Subject: [edk2-devel][Patch v2 2/7] MdeModulePkg: Add Capsule On Disk related definition. Date: Wed, 5 Jun 2019 23:41:58 +0800 Message-Id: <20190605154203.11012-3-wei6.xu@intel.com> In-Reply-To: <20190605154203.11012-1-wei6.xu@intel.com> References: <20190605154203.11012-1-wei6.xu@intel.com> Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,wei6.xu@intel.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1559749344; bh=OEbi/npHvfX/IpWGe8LPGvBPeyU6FmqL1avVPBwN+/k=; h=Cc:Date:From:Reply-To:Subject:To; b=AJb5lB8oh0cFBMXa4cd+JQFKTileID1lXBfxyi71KOMnYpdw+0BPUKRm8jhz6jEEOpa JRxlOmq0RX7cj4H1JGDaDEog745PrFvg1kJ58IPQGW5ACEgYKZJRgIWncmEWyXBA910Ia 9MydADytlLJ6v+aM6cvbcJ9/xLaWgpeEHL4= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3D1852 This patch will add Capsule On Disk related definition, including GUID, PPI and PCDs: The Capsule On Disk Name GUID indicates the capsule is to store Capsule On Disk file names. The Pei Capsule On Disk PPI provides service to retrieve capsules from Capsule On Disk temp relocation file on mass storage devices and create capsule hob for these capsules. PcdCapsuleOnDiskSupport is used to enable/disable Capsule On Disk. PcdCapsuleInRamSupport is used to enabble/disable Capsule In Ram. PcdCoDRelocationFileName specifies the Capsule On Disk temp relocation file name. PcdCodRelocationDevPath specifies platform specific device to store Capsule On Disk tem relocation file. Cc: Jian J Wang Cc: Hao A Wu Cc: Chao B Zhang Signed-off-by: Wei6 Xu --- MdeModulePkg/Include/Ppi/CapsuleOnDisk.h | 48 ++++++++++++++++++++++++++++= ++++ MdeModulePkg/MdeModulePkg.dec | 43 ++++++++++++++++++++++++++++ MdeModulePkg/MdeModulePkg.uni | 32 +++++++++++++++++++++ 3 files changed, 123 insertions(+) create mode 100644 MdeModulePkg/Include/Ppi/CapsuleOnDisk.h diff --git a/MdeModulePkg/Include/Ppi/CapsuleOnDisk.h b/MdeModulePkg/Includ= e/Ppi/CapsuleOnDisk.h new file mode 100644 index 0000000000..28be6e42be --- /dev/null +++ b/MdeModulePkg/Include/Ppi/CapsuleOnDisk.h @@ -0,0 +1,48 @@ +/** @file + This file declares Capsule On Disk PPI. This PPI is used to find and lo= ad the + capsule on files that are relocated into a temp file under rootdir. + + Copyright (c) 2019, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __PEI_CAPSULE_ON_DISK_PPI_H__ +#define __PEI_CAPSULE_ON_DISK_PPI_H__ + +#define EFI_PEI_CAPSULE_ON_DISK_PPI_GUID \ + { \ + 0x71a9ea61, 0x5a35, 0x4a5d, {0xac, 0xef, 0x9c, 0xf8, 0x6d, 0x6d, 0x67,= 0xe0 } \ + } + +typedef struct _EFI_PEI_CAPSULE_ON_DISK_PPI EFI_PEI_CAPSULE_ON_DISK_PPI; + +/** + Loads a DXE capsule from some media into memory and updates the HOB table + with the DXE firmware volume information. + + @param PeiServices General-purpose services that are available to eve= ry PEIM. + @param This Indicates the EFI_PEI_RECOVERY_MODULE_PPI instance. + + @retval EFI_SUCCESS The capsule was loaded correctly. + @retval EFI_DEVICE_ERROR A device error occurred. + @retval EFI_NOT_FOUND A recovery DXE capsule cannot be found. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_LOAD_CAPSULE_ON_DISK)( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_CAPSULE_ON_DISK_PPI *This + ); + +/// +/// Finds and loads the recovery files. +/// +struct _EFI_PEI_CAPSULE_ON_DISK_PPI { + EFI_PEI_LOAD_CAPSULE_ON_DISK LoadCapsuleOnDisk; ///< Loads a DXE binary= capsule into memory. +}; + +extern EFI_GUID gEdkiiPeiCapsuleOnDiskPpiGuid; + +#endif diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec index 6cba729982..d80b728313 100644 --- a/MdeModulePkg/MdeModulePkg.dec +++ b/MdeModulePkg/MdeModulePkg.dec @@ -394,10 +394,13 @@ gEdkiiS3SmmInitDoneGuid =3D { 0x8f9d4825, 0x797d, 0x48fc, { 0x84, 0x71, = 0x84, 0x50, 0x25, 0x79, 0x2e, 0xf6 } } =20 ## Include/Guid/S3StorageDeviceInitList.h gS3StorageDeviceInitListGuid =3D { 0x310e9b8c, 0xcf90, 0x421e, { 0x8e, 0= x9b, 0x9e, 0xef, 0xb6, 0x17, 0xc8, 0xef } } =20 + ## GUID indicates the capsule is to store Capsule On Disk file names. + gEdkiiCapsuleOnDiskNameGuid =3D { 0x98c80a4f, 0xe16b, 0x4d11, { 0x93, 0x= 9a, 0xab, 0xe5, 0x61, 0x26, 0x3, 0x30 } } + [Ppis] ## Include/Ppi/AtaController.h gPeiAtaControllerPpiGuid =3D { 0xa45e60d1, 0xc719, 0x44aa, { 0xb0,= 0x7a, 0xaa, 0x77, 0x7f, 0x85, 0x90, 0x6d }} =20 ## Include/Ppi/UsbHostController.h @@ -464,10 +467,13 @@ gEdkiiPeiAtaPassThruPpiGuid =3D { 0xa16473fd, 0xd474, 0x4c= 89, { 0xae, 0xc7, 0x90, 0xb8, 0x3c, 0x73, 0x86, 0x9 } } =20 ## Include/Ppi/Debug.h gEdkiiDebugPpiGuid =3D { 0x999e699c, 0xb013, 0x47= 5e, { 0xb1, 0x7b, 0xf3, 0xa8, 0xae, 0x5c, 0x48, 0x75 } } =20 + ## Include/Ppi/CapsuleOnDisk.h + gEdkiiPeiCapsuleOnDiskPpiGuid =3D {0x71a9ea61, 0x5a35, 0x4a= 5d, {0xac, 0xef, 0x9c, 0xf8, 0x6d, 0x6d, 0x67, 0xe0}} + [Protocols] ## Load File protocol provides capability to load and unload EFI image i= nto memory and execute it. # Include/Protocol/LoadPe32Image.h # This protocol is deprecated. Native EDKII module should NOT use this = protocol to load/unload image. # If developer need implement such functionality, they should use BaseP= eCoffLib. @@ -1473,10 +1479,26 @@ =20 ## Indicates the allowable maximum number of Reset Filters, Reset Notifi= cations or Reset Handlers in PEI phase. # @Prompt Maximum Number of PEI Reset Filters, Reset Notifications or Re= set Handlers. gEfiMdeModulePkgTokenSpaceGuid.PcdMaximumPeiResetNotifies|0x10|UINT32|0x= 0000010A =20 + ## Capsule On Disk is to deliver capsules via files on Mass Storage devi= ce.

+ # This PCD indicates if the Capsule On Disk is supported.
+ # TRUE - Capsule On Disk is supported.
+ # FALSE - Capsule On Disk is not supported.
+ # If platform does not use this feature, this PCD should be set to FALS= E.

+ # Two sulotions to deliver Capsule On Disk:
+ # a) If PcdCapsuleInRamSupport =3D TRUE, Load Capsule On Disk image o= ut of TCB, and reuse + # Capsule In Ram to deliver capsule.
+ # b) If PcdCapsuleInRamSupport =3D FALSE, Relocate Capsule On Disk im= age to RootDir out + # of TCB, and reuse FatPei to load capsules from external storage.=
+ # Note:
+ # If Both Capsule In Ram and Capsule On Disk are provisioned at the s= ame time, the Capsule + # On Disk will be bypassed. + # @Prompt Enable Capsule On Disk support. + gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleOnDiskSupport|FALSE|BOOLEAN|0x0= 000002d + [PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx] ## This PCD defines the Console output row. The default value is 25 acco= rding to UEFI spec. # This PCD could be set to 0 then console output would be at max column= and max row. # @Prompt Console output row. gEfiMdeModulePkgTokenSpaceGuid.PcdConOutRow|25|UINT32|0x40000006 @@ -1932,10 +1954,17 @@ # The file name must be the 8.3 format. # The PCD data must be in UNICODE format. # @Prompt Recover file name in PEI phase gEfiMdeModulePkgTokenSpaceGuid.PcdRecoveryFileName|L"FVMAIN.FV"|VOID*|0x= 30001045 =20 + ## This is Capsule Temp Relocation file name in PEI phase. + # The file must be in the root directory. + # The file name must be the 8.3 format. + # The PCD data must be in UNICODE format. + # @Prompt Capsule On Disk Temp Relocation file name in PEI phase + gEfiMdeModulePkgTokenSpaceGuid.PcdCoDRelocationFileName|L"TempCod.tmp"|V= OID*|0x30001048 + ## This PCD hold a list GUIDs for the ImageTypeId to indicate the # FMP capsule is a system FMP. # @Prompt A list of system FMP ImageTypeId GUIDs gEfiMdeModulePkgTokenSpaceGuid.PcdSystemFmpCapsuleImageTypeIdGuid|{0x0}|= VOID*|0x30001046 =20 @@ -1943,10 +1972,24 @@ # enabled on AMD processors supporting the Secure Encrypted Virtualizat= ion (SEV) feature. # This mask should be applied when creating 1:1 virtual to physical map= ping tables. # @Prompt The address mask when memory encryption is enabled. gEfiMdeModulePkgTokenSpaceGuid.PcdPteMemoryEncryptionAddressOrMask|0x0|U= INT64|0x30001047 =20 + ## Capsule In Ram is to use memory to deliver the capsules that will be = processed after system + # reset.

+ # This PCD indicates if the Capsule In Ram is supported.
+ # TRUE - Capsule In Ram is supported.
+ # FALSE - Capsule In Ram is not supported. + # @Prompt Enable Capsule In Ram support. + gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleInRamSupport|TRUE|BOOLEAN|0x000= 0002e + + ## Full device path of plaform specific device to store Capsule On Disk = temp relocation file.
+ # If this PCD is set, Capsule On Disk temp relocation file will be stor= ed in the device specified + # by this PCD, instead of the EFI System Partition that stores capsule = image file. + # @Prompt Capsule On Disk relocation device path. + gEfiMdeModulePkgTokenSpaceGuid.PcdCodRelocationDevPath|{0xFF}|VOID*|0x00= 00002f + [PcdsPatchableInModule] ## Specify memory size with page number for PEI code when # Loading Module at Fixed Address feature is enabled. # The value will be set by the build tool. # @Prompt LMFA PEI code page number. diff --git a/MdeModulePkg/MdeModulePkg.uni b/MdeModulePkg/MdeModulePkg.uni index ed8ac9eadc..85c6beae0d 100644 --- a/MdeModulePkg/MdeModulePkg.uni +++ b/MdeModulePkg/MdeModulePkg.uni @@ -1064,10 +1064,17 @@ #string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdRecoveryFileName_HELP #lang= uage en-US "This is recover file name in PEI phase.\n" = "The file must be in the root directory.\n" = "The file name must be the 8.3 format.\n" = "The PCD data must be in UNICODE format." =20 +#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdCoDRelocationFileName_PROMPT= #language en-US "Capsule On Disk Temp Relocation file name in PEI phase" + +#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdCoDRelocationFileName_HELP = #language en-US "This is Capsule Temp Relocation file name in PEI phase.\n" + = "The file must be in the root directory.\n" + = "The file name must be the 8.3 format.\n" + = "The PCD data must be in UNICODE format." + #string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdSystemFmpCapsuleImageTypeIdG= uid_PROMPT #language en-US "A list of system FMP ImageTypeId GUIDs" =20 #string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdSystemFmpCapsuleImageTypeIdG= uid_HELP #language en-US "This PCD hold a list GUIDs for the ImageTypeId t= o indicate the\n" = "FMP capsule is a system FMP." =20 @@ -1129,10 +1136,35 @@ =20 #string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdPteMemoryEncryptionAddressOr= Mask_HELP #language en-US "This PCD holds the address mask for page table = entries when memory encryption is\n" = "enabled on AMD processors supporting the Secure= Encrypted Virtualization (SEV) feature.\n" = "This mask should be applied when creating 1:1 v= irtual to physical mapping tables." =20 +#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdCapsuleOnDiskSupport_PROMPT = #language en-US "Enable Capsule On Disk support" + +#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdCapsuleOnDiskSupport_HELP #= language en-US "Capsule On Disk is to deliver capsules via files on Mass = Storage device.

" + = "This PCD indicates if the Capsule On Disk is supported." + = " TRUE - Capsule On Disk is supported.
" + = " FALSE - Capsule On Disk is not supported.
" + = "If platform does not use this feature, this PCD should be= set to FALSE.

" + = "Two sulotions to deliver Capsule On Disk:
" + = " a) If PcdCapsuleInRamSupport =3D TRUE, Load Capsule On D= isk image out of TCB, and reuse Capsule In Ram to deliver capsule.
" + = " b) If PcdCapsuleInRamSupport =3D FALSE, Relocate Capsule= On Disk image to RootDir out of TCB, and reuse FatPei to load capsules fro= m external storage.
" + = "Note:
" + = "If Both Capsule In Ram and Capsule On Disk are provisione= d at the same time, the Capsule On Disk will be bypassed." + +#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdCapsuleInRamSupport_PROMPT = #language en-US "Enable Capsule In Ram support" + +#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdCapsuleInRamSupport_HELP #l= anguage en-US "Capsule In Ram is to use memory to deliver the capsules th= at will be processed after system reset.

" + = "This PCD indicates if the Capsule In Ram is supported.
" + = " TRUE - Capsule In Ram is supported.
" + = " FALSE - Capsule In Ram is not supported." + +#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdCodRelocationDevPath_PROMPT = #language en-US "Capsule On Disk relacation device path." + +#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdCodRelocationDevPath_HELP #= language en-US "Full device path of plaform specific device to store Caps= ule On Disk temp relocation file.
" + = "If this PCD is set, Capsule On Disk temp relocation file = will be stored in the device specified by this PCD, instead of the EFI Syst= em Partition that stores capsule image file." + #string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdNullPointerDetectionProperty= Mask_PROMPT #language en-US "Enable NULL pointer detection" =20 #string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdNullPointerDetectionProperty= Mask_HELP #language en-US "Mask to control the NULL address detection in= code for different phases.\n" = " If enabled, accessing NULL address in UEFI o= r SMM code can be caught.\n\n" = " BIT0 - Enable NULL pointer detection fo= r UEFI.\n" --=20 2.16.2.windows.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#41949): https://edk2.groups.io/g/devel/message/41949 Mute This Topic: https://groups.io/mt/31938576/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Thu Apr 25 13:05:11 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+41950+1787277+3901457@groups.io; helo=web01.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+41950+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1559749346; cv=none; d=zoho.com; s=zohoarc; b=ciCqK4GNtb7vB3ds5QfMtWbPqh4zg8APzFSqU335fDtAuxdf1DtZoXuUa8prNuRyISWchNg6AEmrMG1sI96Fl4z7JuV0Zlp4thk70KIQ9LG7xeuQcSmoL+HxDbqOk8lUgpeIpN6yJVBtEmZh5Y3ihB4Y+qPgdjQkdwvXZI4N4lU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1559749346; h=Cc:Date:From:In-Reply-To:List-Id:List-Unsubscribe:Message-ID:Reply-To:References:Sender:Subject:To:ARC-Authentication-Results; bh=2J/epPs8UesqtBVbt55G3NKLISvhAwuwDRTczExAxkc=; b=STJNwqQmDooi5wjUfF1k7eG7I1Z/BIZawLZr95nWH9GVVtWoXxTTIguCpX3r+I7lWhXn7dlKyGnvjX/xidS8oiOECcoTHU+GBipemEjqfpdr+B3xabLFZlfJnu7FZRwpmUi/Anus4BYeB6Hq81JjC6UI6AIUjhZ0EMx4J1uzzEo= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=pass; spf=pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+41950+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) header.from= Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1559749346662239.10334310406313; Wed, 5 Jun 2019 08:42:26 -0700 (PDT) Return-Path: X-Received: from mga09.intel.com (mga09.intel.com []) by groups.io with SMTP; Wed, 05 Jun 2019 08:42:25 -0700 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-Received: from orsmga005.jf.intel.com ([10.7.209.41]) by orsmga102.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 05 Jun 2019 08:42:25 -0700 X-ExtLoop1: 1 X-Received: from shwdeopenpsi174.ccr.corp.intel.com ([10.239.157.33]) by orsmga005.jf.intel.com with ESMTP; 05 Jun 2019 08:42:24 -0700 From: "Xu, Wei6" To: devel@edk2.groups.io Cc: Jian J Wang , Hao A Wu , Chao B Zhang , Wei6 Xu Subject: [edk2-devel][Patch v2 3/7] MdeModulePkg: Add CapsuleOnDiskLoadPei PEIM. Date: Wed, 5 Jun 2019 23:41:59 +0800 Message-Id: <20190605154203.11012-4-wei6.xu@intel.com> In-Reply-To: <20190605154203.11012-1-wei6.xu@intel.com> References: <20190605154203.11012-1-wei6.xu@intel.com> Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,wei6.xu@intel.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1559749346; bh=26BWClFKUjwCqAg8O+pVd37zR/KEML1hH1/4v2dNSAM=; h=Cc:Date:From:Reply-To:Subject:To; b=RaNLajBRW4s9d1ARVoUIhTrxhRic4WobuIbnD46brsW+5GPQyeKzgBjvM4nxg78gg3S TnXpvsn8U9Nof1Pmka3O6tp4S34DiK77WBzZ94fWTbz28oDPQH4V9lSZ0/Y8bPp5Jgp9H iMQ8Ypd4uy9zZ5iOURWX4anxXG92C41aHEc= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3D1852 This module provides PPI to load Capsule On Disk temp relocation file from Root Directory file system, retrieve the capsules from the temp file and create capsule hobs for these capsules. Cc: Jian J Wang Cc: Hao A Wu Cc: Chao B Zhang Signed-off-by: Wei6 Xu --- MdeModulePkg/MdeModulePkg.dsc | 4 + .../CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.c | 442 +++++++++++++++++= ++++ .../CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.inf | 64 +++ .../CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.uni | 15 + .../CapsuleOnDiskLoadPeiExtra.uni | 14 + 5 files changed, 539 insertions(+) create mode 100644 MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDi= skLoadPei.c create mode 100644 MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDi= skLoadPei.inf create mode 100644 MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDi= skLoadPei.uni create mode 100644 MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDi= skLoadPeiExtra.uni diff --git a/MdeModulePkg/MdeModulePkg.dsc b/MdeModulePkg/MdeModulePkg.dsc index 995fd805e1..615edddbcc 100644 --- a/MdeModulePkg/MdeModulePkg.dsc +++ b/MdeModulePkg/MdeModulePkg.dsc @@ -197,10 +197,13 @@ gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x06 gEfiMdeModulePkgTokenSpaceGuid.PcdMaxSizeNonPopulateCapsule|0x0 gEfiMdeModulePkgTokenSpaceGuid.PcdMaxSizePopulateCapsule|0x0 gEfiMdeModulePkgTokenSpaceGuid.PcdMaxPeiPerformanceLogEntries|28 =20 +[PcdsDynamicExDefault] + gEfiMdeModulePkgTokenSpaceGuid.PcdRecoveryFileName|L"FVMAIN.FV" + [Components] MdeModulePkg/Application/HelloWorld/HelloWorld.inf MdeModulePkg/Application/DumpDynPcd/DumpDynPcd.inf MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfo.inf =20 @@ -315,10 +318,11 @@ NULL|MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanc= eManagerUiLib.inf } MdeModulePkg/Universal/DriverHealthManagerDxe/DriverHealthManagerDxe.inf MdeModulePkg/Universal/BootManagerPolicyDxe/BootManagerPolicyDxe.inf MdeModulePkg/Universal/CapsulePei/CapsulePei.inf + MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.inf MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf MdeModulePkg/Universal/Console/GraphicsOutputDxe/GraphicsOutputDxe.inf diff --git a/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadP= ei.c b/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.c new file mode 100644 index 0000000000..40d25f3d3b --- /dev/null +++ b/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.c @@ -0,0 +1,442 @@ +/** @file + Recovery module. + + Caution: This module requires additional review when modified. + This module will have external input - Capsule-on-Disk Temp Relocation i= mage. + This external input must be validated carefully to avoid security issue = like + buffer overflow, integer overflow. + + RetrieveRelocatedCapsule() will receive untrusted input and do basic val= idation. + + Copyright (c) 2019, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +// +// The package level header files this module uses +// +#include +#include + +// +// The protocols, PPI and GUID defintions for this module +// +#include +#include +#include +#include +#include +#include + +#include +// +// The Library classes this module consumes +// +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + Loads a DXE capsule from some media into memory and updates the HOB table + with the DXE firmware volume information. + + @param[in] PeiServices General-purpose services that are available to= every PEIM. + @param[in] This Indicates the EFI_PEI_RECOVERY_MODULE_PPI inst= ance. + + @retval EFI_SUCCESS The capsule was loaded correctly. + @retval EFI_DEVICE_ERROR A device error occurred. + @retval EFI_NOT_FOUND A recovery DXE capsule cannot be found. + +**/ +EFI_STATUS +EFIAPI +LoadCapsuleOnDisk ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_CAPSULE_ON_DISK_PPI *This + ); + +EFI_PEI_CAPSULE_ON_DISK_PPI mCapsuleOnDiskPpi =3D { + LoadCapsuleOnDisk +}; + +EFI_PEI_PPI_DESCRIPTOR mCapsuleOnDiskPpiList =3D { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEdkiiPeiCapsuleOnDiskPpiGuid, + &mCapsuleOnDiskPpi +}; + +/** + Determine if capsule comes from memory by checking Capsule PPI. + + @param[in] PeiServices General purpose services available to every PEIM. + + @retval TRUE Capsule comes from memory. + @retval FALSE No capsule comes from memory. + +**/ +STATIC +BOOLEAN +CheckCapsuleFromRam ( + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + EFI_STATUS Status; + PEI_CAPSULE_PPI *Capsule; + + Status =3D PeiServicesLocatePpi ( + &gPeiCapsulePpiGuid, + 0, + NULL, + (VOID **) &Capsule + ); + if (!EFI_ERROR(Status)) { + Status =3D Capsule->CheckCapsuleUpdate ((EFI_PEI_SERVICES **)PeiServic= es); + if (!EFI_ERROR(Status)) { + return TRUE; + } + } + + return FALSE; +} + +/** + Determine if it is a Capsule On Disk mode. + + @retval TRUE Capsule On Disk mode. + @retval FALSE Not capsule On Disk mode. + +**/ +BOOLEAN +IsCapsuleOnDiskMode ( + VOID + ) +{ + EFI_STATUS Status; + UINTN Size; + EFI_PEI_READ_ONLY_VARIABLE2_PPI *PPIVariableServices; + BOOLEAN CodRelocInfo; + + Status =3D PeiServicesLocatePpi ( + &gEfiPeiReadOnlyVariable2PpiGuid, + 0, + NULL, + (VOID **) &PPIVariableServices + ); + ASSERT_EFI_ERROR (Status); + + Size =3D sizeof (BOOLEAN); + Status =3D PPIVariableServices->GetVariable ( + PPIVariableServices, + COD_RELOCATION_INFO_VAR_NAME, + &gEfiCapsuleVendorGuid, + NULL, + &Size, + &CodRelocInfo + ); + + if (EFI_ERROR (Status) || Size !=3D sizeof(BOOLEAN) || CodRelocInfo !=3D= TRUE) { + DEBUG (( DEBUG_ERROR, "Error Get CodRelocationInfo variable %r!\n", St= atus)); + return FALSE; + } + + return TRUE; +} + +/** + Gets capsule images from relocated capsule buffer. + Create Capsule hob for each Capsule. + + Caution: This function may receive untrusted input. + Capsule-on-Disk Temp Relocation image is external input, so this function + will validate Capsule-on-Disk Temp Relocation image to make sure the con= tent + is read within the buffer. + + @param[in] RelocCapsuleBuf Buffer pointer to the relocated capsu= le. + @param[in] RelocCapsuleTotalSize Total size of the relocated capsule. + + @retval EFI_SUCCESS Succeed to get capsules and create hob. + @retval Others Fail to get capsules and create hob. + +**/ +EFI_STATUS +EFIAPI +RetrieveRelocatedCapsule ( + IN UINT8 *RelocCapsuleBuf, + IN UINTN RelocCapsuleTotalSize + ) +{ + EFI_STATUS Status; + UINTN Index; + UINT8 *CapsuleDataBufEnd; + UINT8 *CapsulePtr; + UINT32 CapsuleSize; + UINT64 TotalImageSize; + UINTN CapsuleNum; + + CapsuleNum =3D 0; + + // + // Temp file contains at least 2 capsule (including 1 capsule name capsu= le) & 1 UINT64 + // + if (RelocCapsuleTotalSize < sizeof(UINT64) + sizeof(EFI_CAPSULE_HEADER) = * 2) { + return EFI_INVALID_PARAMETER; + } + + CopyMem(&TotalImageSize, RelocCapsuleBuf, sizeof(UINT64)); + + DEBUG ((DEBUG_INFO, "ProcessRelocatedCapsule CapsuleBuf %x TotalCapSize = %lx\n", + RelocCapsuleBuf, TotalImageSize)); + + RelocCapsuleBuf +=3D sizeof(UINT64); + + // + // TempCaspule file length check + // + if (MAX_ADDRESS - TotalImageSize <=3D sizeof(UINT64) || + (UINT64)RelocCapsuleTotalSize !=3D TotalImageSize + sizeof(UINT64) || + (UINTN)(MAX_ADDRESS - (PHYSICAL_ADDRESS)(UINTN)RelocCapsuleBuf) <=3D= TotalImageSize) { + return EFI_INVALID_PARAMETER; + } + + CapsuleDataBufEnd =3D RelocCapsuleBuf + TotalImageSize; + + // + // TempCapsule file integrity check over Capsule Header to ensure no dat= a corruption in NV Var & Relocation storage + // + CapsulePtr =3D RelocCapsuleBuf; + + while (CapsulePtr < CapsuleDataBufEnd) { + if ((CapsuleDataBufEnd - CapsulePtr) < sizeof(EFI_CAPSULE_HEADER) || + ((EFI_CAPSULE_HEADER *)CapsulePtr)->CapsuleImageSize < sizeof(EFI_= CAPSULE_HEADER) || + (UINTN)(MAX_ADDRESS - (PHYSICAL_ADDRESS)(UINTN)CapsulePtr) < ((EFI= _CAPSULE_HEADER *)CapsulePtr)->CapsuleImageSize + ) { + break; + } + CapsulePtr +=3D ((EFI_CAPSULE_HEADER *)CapsulePtr)->CapsuleImageSize; + CapsuleNum ++; + } + + if (CapsulePtr !=3D CapsuleDataBufEnd) { + Status =3D EFI_INVALID_PARAMETER; + goto EXIT; + } + + // + // Capsule count must be less than PcdCapsuleMax, avoid building too man= y CvHobs to occupy all the free space in HobList. + // + if (CapsuleNum > PcdGet16 (PcdCapsuleMax)) { + Status =3D EFI_INVALID_PARAMETER; + goto EXIT; + } + + // + // Re-iterate the capsule buffer to create Capsule hob & Capsule Name St= r Hob for each Capsule saved in relocated capsule file + // + CapsulePtr =3D RelocCapsuleBuf; + Index =3D 0; + while (CapsulePtr < CapsuleDataBufEnd) { + CapsuleSize =3D ((EFI_CAPSULE_HEADER *)CapsulePtr)->CapsuleImageSize; + BuildCvHob ((EFI_PHYSICAL_ADDRESS)(UINTN)CapsulePtr, CapsuleSize); + + DEBUG((DEBUG_INFO, "Capsule saved in address %x size %x\n", CapsulePtr= , CapsuleSize)); + + CapsulePtr +=3D CapsuleSize; + Index++; + } + +EXIT: + + return Status; +} + +/** + Recovery module entrypoint + + @param[in] FileHandle Handle of the file being invoked. + @param[in] PeiServices Describes the list of possible PEI Services. + + @return EFI_SUCCESS Recovery module is initialized. +**/ +EFI_STATUS +EFIAPI +InitializeCapsuleOnDiskLoad ( + IN EFI_PEI_FILE_HANDLE FileHandle, + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + EFI_STATUS Status; + UINTN BootMode; + UINTN FileNameSize; + + BootMode =3D GetBootModeHob(); + ASSERT(BootMode =3D=3D BOOT_ON_FLASH_UPDATE); + + // + // If there are capsules provisioned in memory, quit. + // Only one capsule resource is accept, CapsuleOnRam's priority is highe= r than CapsuleOnDisk. + // + if (CheckCapsuleFromRam(PeiServices)) { + DEBUG((DEBUG_ERROR, "Capsule On Memory Detected! Quit.\n")); + return EFI_ABORTED; + } + + DEBUG_CODE ( + VOID *CapsuleOnDiskModePpi; + + if (!IsCapsuleOnDiskMode()){ + return EFI_NOT_FOUND; + } + + // + // Check Capsule On Disk Relocation flag. If exists, load capsule & crea= te Capsule Hob + // + Status =3D PeiServicesLocatePpi ( + &gEfiPeiBootInCapsuleOnDiskModePpiGuid, + 0, + NULL, + (VOID **)&CapsuleOnDiskModePpi + ); + if (EFI_ERROR(Status)) { + DEBUG((DEBUG_ERROR, "Locate CapsuleOnDiskModePpi error %x\n", Status= )); + return Status; + } + ); + + Status =3D (**PeiServices).InstallPpi (PeiServices, &mCapsuleOnDiskPpiLi= st); + ASSERT_EFI_ERROR (Status); + + FileNameSize =3D PcdGetSize (PcdCoDRelocationFileName); + Status =3D PcdSetPtrS (PcdRecoveryFileName, &FileNameSize, (VOID *) PcdG= etPtr(PcdCoDRelocationFileName)); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +/** + Loads a DXE capsule from some media into memory and updates the HOB table + with the DXE firmware volume information. + + @param[in] PeiServices General-purpose services that are available to= every PEIM. + @param[in] This Indicates the EFI_PEI_RECOVERY_MODULE_PPI inst= ance. + + @retval EFI_SUCCESS The capsule was loaded correctly. + @retval EFI_DEVICE_ERROR A device error occurred. + @retval EFI_NOT_FOUND A recovery DXE capsule cannot be found. + +**/ +EFI_STATUS +EFIAPI +LoadCapsuleOnDisk ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_CAPSULE_ON_DISK_PPI *This + ) +{ + EFI_STATUS Status; + EFI_PEI_DEVICE_RECOVERY_MODULE_PPI *DeviceRecoveryPpi; + UINTN NumberRecoveryCapsules; + UINTN Instance; + UINTN CapsuleInstance; + UINTN CapsuleSize; + EFI_GUID CapsuleType; + VOID *CapsuleBuffer; + + DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Load Capsule On Disk Entry\n")); + + for (Instance =3D 0; ; Instance++) { + Status =3D PeiServicesLocatePpi ( + &gEfiPeiDeviceRecoveryModulePpiGuid, + Instance, + NULL, + (VOID **)&DeviceRecoveryPpi + ); + DEBUG ((DEBUG_INFO, "LoadCapsuleOnDisk - LocateRecoveryPpi (%d) - %r\n= ", Instance, Status)); + if (EFI_ERROR (Status)) { + if (Instance =3D=3D 0) { + REPORT_STATUS_CODE ( + EFI_ERROR_CODE | EFI_ERROR_MAJOR, + (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_EC_RECOVERY_PPI_NOT_FOUND) + ); + } + break; + } + NumberRecoveryCapsules =3D 0; + Status =3D DeviceRecoveryPpi->GetNumberRecoveryCapsules ( + (EFI_PEI_SERVICES **)PeiServices, + DeviceRecoveryPpi, + &NumberRecoveryCapsules + ); + DEBUG ((DEBUG_INFO, "LoadCapsuleOnDisk - GetNumberRecoveryCapsules (%d= ) - %r\n", NumberRecoveryCapsules, Status)); + if (EFI_ERROR (Status)) { + continue; + } + + for (CapsuleInstance =3D 1; CapsuleInstance <=3D NumberRecoveryCapsule= s; CapsuleInstance++) { + CapsuleSize =3D 0; + Status =3D DeviceRecoveryPpi->GetRecoveryCapsuleInfo ( + (EFI_PEI_SERVICES **)PeiServices, + DeviceRecoveryPpi, + CapsuleInstance, + &CapsuleSize, + &CapsuleType + ); + DEBUG ((DEBUG_INFO, "LoadCapsuleOnDisk - GetRecoveryCapsuleInfo (%d = - %x) - %r\n", CapsuleInstance, CapsuleSize, Status)); + if (EFI_ERROR (Status)) { + break; + } + + // + // Allocate the memory so that it gets preserved into DXE. + // Capsule is special because it may need to populate to system table + // + CapsuleBuffer =3D AllocateRuntimePages (EFI_SIZE_TO_PAGES (CapsuleSi= ze)); + + if (CapsuleBuffer =3D=3D NULL) { + DEBUG ((DEBUG_ERROR, "LoadCapsuleOnDisk - AllocateRuntimePages fai= l\n")); + continue; + } + + Status =3D DeviceRecoveryPpi->LoadRecoveryCapsule ( + (EFI_PEI_SERVICES **)PeiServices, + DeviceRecoveryPpi, + CapsuleInstance, + CapsuleBuffer + ); + DEBUG ((DEBUG_INFO, "LoadCapsuleOnDisk - LoadRecoveryCapsule (%d) - = %r\n", CapsuleInstance, Status)); + if (EFI_ERROR (Status)) { + FreePages (CapsuleBuffer, EFI_SIZE_TO_PAGES(CapsuleSize)); + break; + } + + // + // Capsule Update Mode, Split relocated Capsule buffer into differen= t capsule vehical hobs. + // + Status =3D RetrieveRelocatedCapsule(CapsuleBuffer, CapsuleSize); + + break; + } + + if (EFI_ERROR (Status)) { + REPORT_STATUS_CODE ( + EFI_ERROR_CODE | EFI_ERROR_MAJOR, + (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_EC_NO_RECOVERY_CAPSULE) + ); + } + + return Status; + } + + // + // Any attack against GPT, Relocation Info Variable or temp relocation f= ile will result in no Capsule HOB and return EFI_NOT_FOUND. + // After flow to DXE phase. since no capsule hob is detected. Platform w= ill clear Info flag and force restart. + // No volunerability will be exposed + // + + return EFI_NOT_FOUND; +} diff --git a/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadP= ei.inf b/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.i= nf new file mode 100644 index 0000000000..4af07440b7 --- /dev/null +++ b/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.inf @@ -0,0 +1,64 @@ +## @file +# Load Capsule on Disk module. +# +# Load Capsule On Disk from Root Directory file system. Create CV hob +# based on temporary Capsule On Disk file. +# +# Copyright (c) 2019, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D CapsuleOnDiskLoadPei + MODULE_UNI_FILE =3D CapsuleOnDiskLoadPei.uni + FILE_GUID =3D 8ADEDF9E-2EC8-40fb-AE56-B76D90225D2D + MODULE_TYPE =3D PEIM + VERSION_STRING =3D 1.0 + ENTRY_POINT =3D InitializeCapsuleOnDiskLoad + +# +# The following information is for reference only and not required by the = build tools. +# +# VALID_ARCHITECTURES =3D IA32 X64 EBC +# + +[Sources] + CapsuleOnDiskLoadPei.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + PeimEntryPoint + DebugLib + HobLib + BaseMemoryLib + MemoryAllocationLib + ReportStatusCodeLib + +[Ppis] + gEdkiiPeiCapsuleOnDiskPpiGuid ## PRODUCES + gEfiPeiReadOnlyVariable2PpiGuid ## CONSUMES + gEfiPeiBootInCapsuleOnDiskModePpiGuid ## SOMETIMES_CONSUMES + gEfiPeiDeviceRecoveryModulePpiGuid ## CONSUMES + gPeiCapsulePpiGuid ## CONSUMES + +[Guids] + gEfiCapsuleVendorGuid ## SOMETIMES_CONSUMES ## Variabl= e L"CodRelocationInfo" + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdCoDRelocationFileName = ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleMax = ## CONSUMES + +[PcdEx] + gEfiMdeModulePkgTokenSpaceGuid.PcdRecoveryFileName = ## PRODUCES + +[depex] + gEfiPeiBootInCapsuleOnDiskModePpiGuid + +[UserExtensions.TianoCore."ExtraFiles"] + CapsuleOnDiskLoadPeiExtra.uni diff --git a/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadP= ei.uni b/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.u= ni new file mode 100644 index 0000000000..c3eae6a5c2 --- /dev/null +++ b/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.uni @@ -0,0 +1,15 @@ +// /** @file +// Caspule On Disk Load module. +// +// Load Capsule On Disk and build CV hob. +// +// Copyright (c) 2019, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Caspule On Disk L= oad module." + +#string STR_MODULE_DESCRIPTION #language en-US "Load Capsule On D= isk and build CV hob." diff --git a/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadP= eiExtra.uni b/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoad= PeiExtra.uni new file mode 100644 index 0000000000..81034f6294 --- /dev/null +++ b/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPeiExtra= .uni @@ -0,0 +1,14 @@ +// /** @file +// CapsuleOnDiskLoadPei Localized Strings and Content +// +// Copyright (c) 2019, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + +#string STR_PROPERTIES_MODULE_NAME +#language en-US +"CapsuleOnDiskLoad PEI Driver" + + --=20 2.16.2.windows.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#41950): https://edk2.groups.io/g/devel/message/41950 Mute This Topic: https://groups.io/mt/31938577/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Thu Apr 25 13:05:11 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+41951+1787277+3901457@groups.io; helo=web01.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+41951+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1559749348; cv=none; d=zoho.com; s=zohoarc; b=QwSYODbjAcRZbVItHUGUkitQS01gsU2SACPQFDgZBHVB6gbJU5BcNRi6M5Di+jsuM3+/rJxkxsUhf0nEXrL9QOr11JYP32Jzst88wD0JKN1lTzZ95LKKslICan3lBKn7wXNY9Xnv7vAOwOgPUkDxYGG+chuEP6IPjq/6G/yY6gU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1559749348; h=Cc:Date:From:In-Reply-To:List-Id:List-Unsubscribe:Message-ID:Reply-To:References:Sender:Subject:To:ARC-Authentication-Results; bh=4HwgRKoJuxnLXlGDYutcr7zh0bCE+GFKUiSpRS1+riQ=; b=FEfNGMOXKNvlrokGQPYellNnlxOpYjJe3JKFYb4O29/Hj1u9v3xe0P1Lv3N/o2GG509h3TxfJODGlPEpz6iq1Ogt4y0rZSRPvmZzcD7yyrynUShgH2Z9KFsATg6g+yltIKoZj4ySoCzYOuV6GG5gJ7JMmIb/TXbSrs3xzWttFoM= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=pass; spf=pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+41951+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) header.from= Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1559749348873623.9087013617876; Wed, 5 Jun 2019 08:42:28 -0700 (PDT) Return-Path: X-Received: from mga09.intel.com (mga09.intel.com []) by groups.io with SMTP; Wed, 05 Jun 2019 08:42:27 -0700 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-Received: from orsmga005.jf.intel.com ([10.7.209.41]) by orsmga102.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 05 Jun 2019 08:42:27 -0700 X-ExtLoop1: 1 X-Received: from shwdeopenpsi174.ccr.corp.intel.com ([10.239.157.33]) by orsmga005.jf.intel.com with ESMTP; 05 Jun 2019 08:42:26 -0700 From: "Xu, Wei6" To: devel@edk2.groups.io Cc: Jian J Wang , Hao A Wu , Chao B Zhang , Wei6 Xu Subject: [edk2-devel][Patch v2 4/7] MdeModulePkg/BdsDxe: Support Capsule On Disk. Date: Wed, 5 Jun 2019 23:42:00 +0800 Message-Id: <20190605154203.11012-5-wei6.xu@intel.com> In-Reply-To: <20190605154203.11012-1-wei6.xu@intel.com> References: <20190605154203.11012-1-wei6.xu@intel.com> Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,wei6.xu@intel.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1559749348; bh=CF8rLrJNwlz6KASFCOXzD4Hjk4LQjdPAfoU3ryO4EVk=; h=Cc:Date:From:Reply-To:Subject:To; b=PVWHYPq+Y9kGBV2CTgS9q6rC/+IWHtDPWgm62Oqj+gUNuAPxt0bkmC3G+8Pu7aSVn4I oMlDrnpaeMqORfGhxTecMkKGhyqfCDrY8+36JABZQYJDvl859vJBYGv+6t1neiPfuF0VU mbHGtavS9JCsAK1fgubAC9e54CfK+BvmbjY= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3D1852 Set EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED bit of "OsIndicationsSupported" variable to indicate the Capsule On Disk is supported or not, according to PcdCapsuleOnDiskSupport. Cc: Jian J Wang Cc: Hao A Wu Cc: Chao B Zhang Signed-off-by: Wei6 Xu --- MdeModulePkg/Universal/BdsDxe/BdsDxe.inf | 3 ++- MdeModulePkg/Universal/BdsDxe/BdsEntry.c | 6 +++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/MdeModulePkg/Universal/BdsDxe/BdsDxe.inf b/MdeModulePkg/Univer= sal/BdsDxe/BdsDxe.inf index 6913389d34..3d13c725ce 100644 --- a/MdeModulePkg/Universal/BdsDxe/BdsDxe.inf +++ b/MdeModulePkg/Universal/BdsDxe/BdsDxe.inf @@ -3,11 +3,11 @@ # # When DxeCore dispatching all DXE driver, this module will produce archi= tecture protocol # gEfiBdsArchProtocolGuid. After DxeCore finish dispatching, DxeCore will= invoke Entry # interface of protocol gEfiBdsArchProtocolGuid, then BDS phase is entere= d. # -# Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.
+# Copyright (c) 2008 - 2019, Intel Corporation. All rights reserved.
# SPDX-License-Identifier: BSD-2-Clause-Patent # ## =20 [Defines] @@ -93,10 +93,11 @@ gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareVendor ## C= ONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareRevision ## C= ONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdConInConnectOnDemand ## C= ONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdErrorCodeSetVariable ## S= OMETIMES_CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdTestKeyUsed ## C= ONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleOnDiskSupport ## C= ONSUMES =20 [Depex] TRUE =20 [UserExtensions.TianoCore."ExtraFiles"] diff --git a/MdeModulePkg/Universal/BdsDxe/BdsEntry.c b/MdeModulePkg/Univer= sal/BdsDxe/BdsEntry.c index 9d312bd982..2a4ae9f488 100644 --- a/MdeModulePkg/Universal/BdsDxe/BdsEntry.c +++ b/MdeModulePkg/Universal/BdsDxe/BdsEntry.c @@ -3,11 +3,11 @@ When this module was dispatched by DxeCore, gEfiBdsArchProtocolGuid will= be installed which contains interface of BdsEntry. After DxeCore finish DXE phase, gEfiBdsArchProtocolGuid->BdsEntry will b= e invoked to enter BDS phase. =20 -Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.
+Copyright (c) 2004 - 2019, Intel Corporation. All rights reserved.
(C) Copyright 2016 Hewlett Packard Enterprise Development LP
(C) Copyright 2015 Hewlett-Packard Development Company, L.P.
SPDX-License-Identifier: BSD-2-Clause-Patent =20 **/ @@ -550,10 +550,14 @@ BdsFormalizeOSIndicationVariable ( EfiBootManagerFreeLoadOption (&BootManagerMenu); } else { OsIndicationSupport =3D EFI_OS_INDICATIONS_START_PLATFORM_RECOVERY; } =20 + if (PcdGetBool(PcdCapsuleOnDiskSupport)) { + OsIndicationSupport |=3D EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPP= ORTED; + } + Status =3D gRT->SetVariable ( EFI_OS_INDICATIONS_SUPPORT_VARIABLE_NAME, &gEfiGlobalVariableGuid, EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_A= CCESS, sizeof(UINT64), --=20 2.16.2.windows.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#41951): https://edk2.groups.io/g/devel/message/41951 Mute This Topic: https://groups.io/mt/31938578/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Thu Apr 25 13:05:11 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+41952+1787277+3901457@groups.io; helo=web01.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+41952+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1559749350; cv=none; d=zoho.com; s=zohoarc; b=DFjPTyZVzWDSXhDAIS93F2kWGvHxP6DTiySqVvG7Aa+GoRZZpuPHgxWLbfK0CBPLtCPVGu8MAw8g4EDlaCgNuWFHJUqFZNA35AgdIF402a9bA9/pplbRHxk173ee6PF/jTS5a/o3UCyaCdaVnH5M+//1mCdBcDv2sSIweOnah+U= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1559749350; h=Cc:Date:From:In-Reply-To:List-Id:List-Unsubscribe:Message-ID:Reply-To:References:Sender:Subject:To:ARC-Authentication-Results; bh=qBt3NfiT+3UdsHm1aDbROGRMw2X/O1MJ5CzJIMtiYpQ=; b=Pv5o9qoksNB7xM2oSQKPOdmBbjGd7t5LyoCSAOHE6I4tOVOvScn9Y6ClP91qL7swhwN3jAUok9A92Vvxv3+EUQrbfKyQwLM09NdqpjxQE4a4Ui+UHLT0MzamOc8snkhyIymDMuzyJt1ALLsKUJBKANdhfRuCegZdAQ7In7GPGfQ= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=pass; spf=pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+41952+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) header.from= Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1559749350752153.6433598571706; Wed, 5 Jun 2019 08:42:30 -0700 (PDT) Return-Path: X-Received: from mga09.intel.com (mga09.intel.com []) by groups.io with SMTP; Wed, 05 Jun 2019 08:42:29 -0700 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-Received: from orsmga005.jf.intel.com ([10.7.209.41]) by orsmga102.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 05 Jun 2019 08:42:29 -0700 X-ExtLoop1: 1 X-Received: from shwdeopenpsi174.ccr.corp.intel.com ([10.239.157.33]) by orsmga005.jf.intel.com with ESMTP; 05 Jun 2019 08:42:28 -0700 From: "Xu, Wei6" To: devel@edk2.groups.io Cc: Jian J Wang , Hao A Wu , Chao B Zhang , Wei6 Xu Subject: [edk2-devel][Patch v2 5/7] MdeModulePkg/CapsuleRuntimeDxe: Introduce PCD to control this feature. Date: Wed, 5 Jun 2019 23:42:01 +0800 Message-Id: <20190605154203.11012-6-wei6.xu@intel.com> In-Reply-To: <20190605154203.11012-1-wei6.xu@intel.com> References: <20190605154203.11012-1-wei6.xu@intel.com> Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,wei6.xu@intel.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1559749349; bh=hLAYEw4E017T2A++5A2sJza84XrfhG1QaX/CynSLlgI=; h=Cc:Date:From:Reply-To:Subject:To; b=jHGfoK8E34UoBcjU1PrUXqa97HaB7ccOcq0S19MTSFzeqZN6R1nARfdHBJ87S/iNlXz 8aFsVxedZrilYUiYL7MZ2t2X825QOYxrdOHI0lSa+/3r2KBT/ml3TKw2wdBC4VcE7gNra qjtn6RLLvwSQ+dgPrR6s57ClHVjfCBK/3BU= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3D1852 Introduce PcdCapsuleInRamSupport to turn on/off Capsule In Ram feature. Platform could choose to drop CapsulePei/CapsuleX64 and not to support Capsule In Ram. Cc: Jian J Wang Cc: Hao A Wu Cc: Chao B Zhang Signed-off-by: Wei6 Xu --- MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf | 1 + MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.c | 10 ++++++= +++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf= b/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf index 338577e293..9da450722b 100644 --- a/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf +++ b/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf @@ -88,10 +88,11 @@ gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode ## CONSUMES =20 [Pcd] gEfiMdeModulePkgTokenSpaceGuid.PcdMaxSizeNonPopulateCapsule ## SOMETIM= ES_CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdMaxSizePopulateCapsule ## SOMETIM= ES_CONSUMES # Populate Image requires reset support. + gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleInRamSupport ## CONSUMES =20 [Pcd.X64] gEfiMdeModulePkgTokenSpaceGuid.PcdCapsulePeiLongModeStackSize ## SOMET= IMES_CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable ## SOMET= IMES_CONSUMES =20 diff --git a/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.c b/Md= eModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.c index aaf819c4c6..53a1af44e2 100644 --- a/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.c +++ b/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleService.c @@ -2,11 +2,11 @@ Capsule Runtime Driver produces two UEFI capsule runtime services. (UpdateCapsule, QueryCapsuleCapabilities) It installs the Capsule Architectural Protocol defined in PI1.0a to sign= ify the capsule runtime services are ready. =20 -Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent =20 **/ =20 #include "CapsuleService.h" @@ -69,10 +69,18 @@ UpdateCapsule ( BOOLEAN NeedReset; BOOLEAN InitiateReset; CHAR16 CapsuleVarName[30]; CHAR16 *TempVarName; =20 + // + // Check if platform support Capsule In RAM or not. + // Platform could choose to drop CapsulePei/CapsuleX64 and do not suppor= t Capsule In RAM. + // + if (!PcdGetBool(PcdCapsuleInRamSupport)) { + return EFI_UNSUPPORTED; + } + // // Capsule Count can't be less than one. // if (CapsuleCount < 1) { return EFI_INVALID_PARAMETER; --=20 2.16.2.windows.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#41952): https://edk2.groups.io/g/devel/message/41952 Mute This Topic: https://groups.io/mt/31938579/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Thu Apr 25 13:05:11 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+41953+1787277+3901457@groups.io; helo=web01.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+41953+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1559749352; cv=none; d=zoho.com; s=zohoarc; b=hIdd4rNxRPxieNxz1UBvM7csS+xUvZuPt0yjL+15x0Z3yFd8DMkygpB2Ihut6y+82QY83wvBAHCB1GPhYbXBDyf61q7jKgfPWnJLu09OUJRHvJVGTJByKo4NAD+KUgy37BVVFGfqiygcYle+lXeUAiNc3xNaWtjfzsFnn3GQQzw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1559749352; h=Cc:Date:From:In-Reply-To:List-Id:List-Unsubscribe:Message-ID:Reply-To:References:Sender:Subject:To:ARC-Authentication-Results; bh=9beh+gqiGw5Y6vnscO0ogVnN68Mr94thR7Z6dr5/mMg=; b=S3Rg12a2sZ9pZjlZva6ntW0fhG9mMV4fE8b+WoVIWl0khUSwFbMLIHvLzEGqDqCqIJvykihsgPDDHo/NNrYbCNAcKb4ertkD1LVhmSjWPPcWk7KE50z6E2swOWvSODFUrlg7GtFHyvb+bItsdpxVBeghWbBA2bfSmh8TycnYNTU= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=pass; spf=pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+41953+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) header.from= Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1559749352768760.5507182664612; Wed, 5 Jun 2019 08:42:32 -0700 (PDT) Return-Path: X-Received: from mga09.intel.com (mga09.intel.com []) by groups.io with SMTP; Wed, 05 Jun 2019 08:42:31 -0700 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-Received: from orsmga005.jf.intel.com ([10.7.209.41]) by orsmga102.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 05 Jun 2019 08:42:31 -0700 X-ExtLoop1: 1 X-Received: from shwdeopenpsi174.ccr.corp.intel.com ([10.239.157.33]) by orsmga005.jf.intel.com with ESMTP; 05 Jun 2019 08:42:30 -0700 From: "Xu, Wei6" To: devel@edk2.groups.io Cc: Jian J Wang , Hao A Wu , Chao B Zhang , Wei6 Xu Subject: [edk2-devel][Patch v2 6/7] MdeModulePkg/DxeIpl: Support Capsule On Disk. Date: Wed, 5 Jun 2019 23:42:02 +0800 Message-Id: <20190605154203.11012-7-wei6.xu@intel.com> In-Reply-To: <20190605154203.11012-1-wei6.xu@intel.com> References: <20190605154203.11012-1-wei6.xu@intel.com> Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,wei6.xu@intel.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1559749351; bh=m5scMQ1u13z47qna7NuMiZwjVhZZtk/rLHf+VTer6hA=; h=Cc:Date:From:Reply-To:Subject:To; b=FfA7Ql5jOzP6svKr7N/RBlIYPP8HGNYjg+TFsfeQOzQO4rOXb5evWHJ83yXnEuTOd1a RtJ9qb2Mbx0x44qN3Z2hlIfi4MdOAARr42Aj81zVbNSkuCHJoes2J9Hm8BZATnRPXpVsx d2Un+A/HrnzxNRAZmSPz+fUvNi2rIiNUTMI= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3D1852 If Capsule On Disk mode, call Capsule On Disk Load PPI to load capsules. When it fails, still goes to Firmware Update boot path. BDS will clear corresponding indicator and reboot later on. Cc: Jian J Wang Cc: Hao A Wu Cc: Chao B Zhang Signed-off-by: Wei6 Xu --- MdeModulePkg/Core/DxeIplPeim/DxeIpl.h | 3 ++- MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf | 20 ++++++++++-------- MdeModulePkg/Core/DxeIplPeim/DxeLoad.c | 37 +++++++++++++++++++++++++++++= +++- 3 files changed, 49 insertions(+), 11 deletions(-) diff --git a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.h b/MdeModulePkg/Core/DxeI= plPeim/DxeIpl.h index 063fefb414..90b5b5b211 100644 --- a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.h +++ b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.h @@ -1,10 +1,10 @@ /** @file Master header file for DxeIpl PEIM. All source files in this module shou= ld include this file for common definitions. =20 -Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent =20 **/ =20 #ifndef __PEI_DXEIPL_H__ @@ -19,10 +19,11 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include #include #include #include #include +#include #include =20 #include #include #include diff --git a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf b/MdeModulePkg/Core/Dx= eIplPeim/DxeIpl.inf index 62bb3f3077..ff036d8688 100644 --- a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf +++ b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf @@ -3,11 +3,11 @@ # # This module produces a special PPI named the DXE Initial Program Load (= IPL) # PPI to discover and dispatch the DXE Foundation and components that are # needed to run the DXE Foundation. # -# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
# Copyright (c) 2017, AMD Incorporated. All rights reserved.
# # SPDX-License-Identifier: BSD-2-Clause-Patent # ## @@ -74,21 +74,23 @@ =20 [LibraryClasses.ARM, LibraryClasses.AARCH64] ArmMmuLib =20 [Ppis] - gEfiDxeIplPpiGuid ## PRODUCES - gEfiPeiDecompressPpiGuid ## PRODUCES - gEfiEndOfPeiSignalPpiGuid ## SOMETIMES_PRODUCES # Not produced o= n S3 boot path - gEfiPeiReadOnlyVariable2PpiGuid ## SOMETIMES_CONSUMES - gEfiPeiLoadFilePpiGuid ## SOMETIMES_CONSUMES - gEfiPeiS3Resume2PpiGuid ## SOMETIMES_CONSUMES # Consumed on S3= boot path - gEfiPeiRecoveryModulePpiGuid ## SOMETIMES_CONSUMES # Consumed on re= covery boot path + gEfiDxeIplPpiGuid ## PRODUCES + gEfiPeiDecompressPpiGuid ## PRODUCES + gEfiEndOfPeiSignalPpiGuid ## SOMETIMES_PRODUCES # Not produ= ced on S3 boot path + gEfiPeiReadOnlyVariable2PpiGuid ## SOMETIMES_CONSUMES + gEfiPeiLoadFilePpiGuid ## SOMETIMES_CONSUMES + gEfiPeiS3Resume2PpiGuid ## SOMETIMES_CONSUMES # Consumed = on S3 boot path + gEfiPeiRecoveryModulePpiGuid ## SOMETIMES_CONSUMES # Consumed = on recovery boot path ## SOMETIMES_CONSUMES ## UNDEFINED # HOB gEfiVectorHandoffInfoPpiGuid - gEfiPeiMemoryDiscoveredPpiGuid ## SOMETIMES_CONSUMES + gEfiPeiMemoryDiscoveredPpiGuid ## SOMETIMES_CONSUMES + gEfiPeiBootInCapsuleOnDiskModePpiGuid ## SOMETIMES_CONSUMES + gEdkiiPeiCapsuleOnDiskPpiGuid ## SOMETIMES_CONSUMES # Consumed = on firmware update boot path =20 [Guids] ## SOMETIMES_CONSUMES ## Variable:L"MemoryTypeInformation" ## SOMETIMES_PRODUCES ## HOB gEfiMemoryTypeInformationGuid diff --git a/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c b/MdeModulePkg/Core/Dxe= IplPeim/DxeLoad.c index c6e5b83309..9dc2d4485f 100644 --- a/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c +++ b/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c @@ -1,11 +1,11 @@ /** @file Last PEIM. Responsibility of this module is to load the DXE Core from a Firmware Vo= lume. =20 Copyright (c) 2016 HP Development Company, L.P. -Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent =20 **/ =20 #include "DxeIpl.h" @@ -263,17 +263,38 @@ DxeLoadCore ( UINTN Instance; UINT32 AuthenticationState; UINTN DataSize; EFI_PEI_S3_RESUME2_PPI *S3Resume; EFI_PEI_RECOVERY_MODULE_PPI *PeiRecovery; + EFI_PEI_CAPSULE_ON_DISK_PPI *PeiCapsuleOnDisk; EFI_MEMORY_TYPE_INFORMATION MemoryData[EfiMaxMemoryType + = 1]; + VOID *CapsuleOnDiskModePpi; + BOOLEAN IsCapsuleOnDiskMode; + + IsCapsuleOnDiskMode =3D FALSE; =20 // // if in S3 Resume, restore configure // BootMode =3D GetBootModeHob (); =20 + // + // If Capsule On Disk mode, call storage stack to read Capsule Relocatio= n file + // IoMmmu is highly recommmended to enable before reading + // + if (BootMode =3D=3D BOOT_ON_FLASH_UPDATE) { + Status =3D PeiServicesLocatePpi ( + &gEfiPeiBootInCapsuleOnDiskModePpiGuid, + 0, + NULL, + &CapsuleOnDiskModePpi + ); + if (!EFI_ERROR(Status)) { + IsCapsuleOnDiskMode =3D TRUE; + } + } + if (BootMode =3D=3D BOOT_ON_S3_RESUME) { Status =3D PeiServicesLocatePpi ( &gEfiPeiS3Resume2PpiGuid, 0, NULL, @@ -328,10 +349,24 @@ DxeLoadCore ( } REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_SOFTWARE_PEI_MODULE | EFI_= SW_PEI_PC_CAPSULE_START)); // // Now should have a HOB with the DXE core // + } else if (IsCapsuleOnDiskMode) { + Status =3D PeiServicesLocatePpi ( + &gEdkiiPeiCapsuleOnDiskPpiGuid, + 0, + NULL, + (VOID **) &PeiCapsuleOnDisk + ); + + // + // Whether failed, still goes to Firmware Update boot path. BDS will c= lear corresponding indicator and reboot later on + // + if (!EFI_ERROR (Status)) { + Status =3D PeiCapsuleOnDisk->LoadCapsuleOnDisk (PeiServices, PeiCaps= uleOnDisk); + } } =20 if (GetFirstGuidHob ((CONST EFI_GUID *)&gEfiMemoryTypeInformationGuid) = =3D=3D NULL) { // // Don't build GuidHob if GuidHob has been installed. --=20 2.16.2.windows.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#41953): https://edk2.groups.io/g/devel/message/41953 Mute This Topic: https://groups.io/mt/31938580/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Thu Apr 25 13:05:11 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+41954+1787277+3901457@groups.io; helo=web01.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+41954+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1559749356; cv=none; d=zoho.com; s=zohoarc; b=il9uy1Ur+znUbPt4xXL/KnbZozk8ZwQ3v3h2bxw7OdM7rykNk8WmPpLSCNndsLccWCpt2jjnmnLyr8KqQg4knlKNKNKNpxnsmV+Mal1Ju84Ql8Q/txcTfK59t5hXqs/iXEY5xrj0KXVkbZ7GtbXmm8TBg8l+aY1rl3c+ha/3UPc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1559749356; h=Cc:Date:From:In-Reply-To:List-Id:List-Unsubscribe:Message-ID:Reply-To:References:Sender:Subject:To:ARC-Authentication-Results; bh=zxbm6JHbSMIuJ+OZuHGbPjsW+707pRC812UMQp29+/8=; b=RRCEVlQY7Hq3+p2M4m/0trZKY78n1S0KSV1VRzOaNHJeyTBnbZM8hAMSCxrBxcz4jDS6QJbdoaDiFnSzSCHvpz01ePr0HflYisAy4DrbtRoAGNufx6jAXnXvFeWP+9OtcViBUGsuKNXyscBoL2CLoX/mYDu7Rx4dM9TMsHEjyKs= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=pass; spf=pass (zoho.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+41954+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) header.from= Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 155974935633533.92357395580541; Wed, 5 Jun 2019 08:42:36 -0700 (PDT) Return-Path: X-Received: from mga09.intel.com (mga09.intel.com []) by groups.io with SMTP; Wed, 05 Jun 2019 08:42:34 -0700 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-Received: from orsmga005.jf.intel.com ([10.7.209.41]) by orsmga102.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 05 Jun 2019 08:42:34 -0700 X-ExtLoop1: 1 X-Received: from shwdeopenpsi174.ccr.corp.intel.com ([10.239.157.33]) by orsmga005.jf.intel.com with ESMTP; 05 Jun 2019 08:42:31 -0700 From: "Xu, Wei6" To: devel@edk2.groups.io Cc: Jian J Wang , Hao A Wu , Chao B Zhang , Wei6 Xu Subject: [edk2-devel][Patch v2 7/7] MdeModulePkg: Add Capsule On Disk APIs into CapsuleLib. Date: Wed, 5 Jun 2019 23:42:03 +0800 Message-Id: <20190605154203.11012-8-wei6.xu@intel.com> In-Reply-To: <20190605154203.11012-1-wei6.xu@intel.com> References: <20190605154203.11012-1-wei6.xu@intel.com> Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,wei6.xu@intel.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1559749355; bh=TUTEt9sE6+E3sHRxBVdA0HpCd8KPYJoAY3eaeJpXqcg=; h=Cc:Date:From:Reply-To:Subject:To; b=uFEGxtYagZT7nfxwBpJNVUvJnUZTM/P18Y0baxW+V8d7sa53eppFfPkHSEcDU9KRk2O dr98Bq9VwJLEci6A1KHN4drck7UHSM249DDHGdLyRg3hYQzVySDc0J/SdtO6NUfmDktap GUYGkP+f1Ivo/WQOilTNPh/O0u2Pt5N01A0= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3D1852 CoDCheckCapsuleOnDiskFlag() is to check if CapsuleOnDisk flag in "OsIndications" Variable is enabled. It is used to indicate whether capsule on disk is provisioned in normal boot path. CoDClearCapsuleOnDiskFlag() is to to clear CapsuleOnDisk flags, including "OsIndications" and "BootNext" variable. CoDRelocateCapsule() is to relocate the capsules from EFI system partition. Depends on PcdCapsuleInRamSupport, there are two solutions to relocate the capsule on disk images: When Capsule In Ram is supported, the Capsule On Disk images are relocated into memory, and call UpdateCapsule() service to deliver the capsules. When Capsule In Ram is not supported, the Capsule On Disk images are relocated into a temp file which will be stored in root directory on a platform specific storage device. CapsuleOnDiskLoadPei PEIM will retrieve the capsules from the relocation temp file and report capsule hobs for them. CoDRemoveTempFile() is to remove the relocation temp file in the next boot after capsules are processed. Cc: Jian J Wang Cc: Hao A Wu Cc: Chao B Zhang Signed-off-by: Wei6 Xu --- MdeModulePkg/Include/Library/CapsuleLib.h | 94 +- .../Library/DxeCapsuleLibFmp/CapsuleOnDisk.c | 1983 ++++++++++++++++= ++++ .../Library/DxeCapsuleLibFmp/CapsuleOnDisk.h | 63 + .../Library/DxeCapsuleLibFmp/DxeCapsuleLib.c | 56 +- .../Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf | 21 +- .../DxeCapsuleLibFmp/DxeCapsuleProcessLib.c | 121 +- .../Library/DxeCapsuleLibFmp/DxeCapsuleReportLib.c | 67 +- .../DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf | 3 +- .../Library/DxeCapsuleLibNull/DxeCapsuleLibNull.c | 85 +- 9 files changed, 2466 insertions(+), 27 deletions(-) create mode 100644 MdeModulePkg/Library/DxeCapsuleLibFmp/CapsuleOnDisk.c create mode 100644 MdeModulePkg/Library/DxeCapsuleLibFmp/CapsuleOnDisk.h diff --git a/MdeModulePkg/Include/Library/CapsuleLib.h b/MdeModulePkg/Inclu= de/Library/CapsuleLib.h index 1fc2fba3a2..f3cb17cbf9 100644 --- a/MdeModulePkg/Include/Library/CapsuleLib.h +++ b/MdeModulePkg/Include/Library/CapsuleLib.h @@ -1,17 +1,37 @@ /** @file =20 This library class defines a set of interfaces for how to process capsul= e image updates. =20 -Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent =20 **/ =20 #ifndef __CAPSULE_LIB_H__ #define __CAPSULE_LIB_H__ =20 +#include + + +typedef struct { + // + // image address. + // + VOID *ImageAddress; + // + // The file info of the image comes from. + // if FileInfo =3D=3D NULL. means image does not come from file + // + EFI_FILE_INFO *FileInfo; +} IMAGE_INFO; + +// +// BOOLEAN Variable to save the total size of all Capsule On Disk during r= elocation +// +#define COD_RELOCATION_INFO_VAR_NAME L"CodRelocationInfo" + /** The firmware checks whether the capsule image is supported by the CapsuleGuid in CapsuleHeader or if there is other specific inform= ation in the capsule image. =20 @@ -79,6 +99,78 @@ EFI_STATUS EFIAPI ProcessCapsules ( VOID ); =20 +/** + This routine is called to check if CapsuleOnDisk flag in OsIndications V= ariable + is enabled. + + @retval TRUE Flag is enabled + @retval FALSE Flag is not enabled + +**/ +BOOLEAN +EFIAPI +CoDCheckCapsuleOnDiskFlag( + VOID + ); + + +/** + This routine is called to clear CapsuleOnDisk flags including OsIndicati= ons and BootNext variable + + @retval EFI_SUCCESS All Capsule On Disk flags are cleared + +**/ +EFI_STATUS +EFIAPI +CoDClearCapsuleOnDiskFlag( + VOID + ); + +/** + Relocate Capsule on Disk from EFI system partition. + + Two solution to deliver Capsule On Disk: + Solution A: If PcdCapsuleInRamSupport is enabled, relocate Capsule On Di= sk to memory and call UpdateCapsule(). + Solution B: If PcdCapsuleInRamSupport is disabled, relocate Capsule On D= isk to a platform-specific NV storage + device with BlockIo protocol. + + Device enumeration like USB costs time, user can input MaxRetry to tell = function to retry. + Function will stall 100ms between each retry. + + Side Effects: + Capsule Delivery Supported Flag in OsIndication variable and BootNext = variable will be cleared. + Solution B: Content corruption. Block IO write directly touches low le= vel write. Orignal partitions, file + systems of the relocation device will be corrupted. + + @param[in] MaxRetry Max Connection Retry. Stall 100ms bet= ween each connection try to ensure + devices like USB can get enumerated. + + @retval EFI_SUCCESS Capsule on Disk images are sucessfully relocated. + +**/ +EFI_STATUS +EFIAPI +CoDRelocateCapsule( + UINTN MaxRetry + ); + +/** + Remove the temp file from the root of EFI System Partition. + Device enumeration like USB costs time, user can input MaxRetry to tell = function to retry. + Function will stall 100ms between each retry. + + @param[in] MaxRetry Max Connection Retry. Stall 100ms bet= ween each connection try to ensure + devices like USB can get enumerated. + + @retval EFI_SUCCESS Remove the temp file successfully. + +**/ +EFI_STATUS +EFIAPI +CoDRemoveTempFile ( + UINTN MaxRetry + ); + #endif diff --git a/MdeModulePkg/Library/DxeCapsuleLibFmp/CapsuleOnDisk.c b/MdeMod= ulePkg/Library/DxeCapsuleLibFmp/CapsuleOnDisk.c new file mode 100644 index 0000000000..5f1edbbbae --- /dev/null +++ b/MdeModulePkg/Library/DxeCapsuleLibFmp/CapsuleOnDisk.c @@ -0,0 +1,1983 @@ +/** @file + The implementation supports Capusle on Disk. + + Copyright (c) 2019, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "CapsuleOnDisk.h" + +/** + Return if this capsule is a capsule name capsule, based upon CapsuleHead= er. + + @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER + + @retval TRUE It is a capsule name capsule. + @retval FALSE It is not a capsule name capsule. +**/ +BOOLEAN +IsCapsuleNameCapsule ( + IN EFI_CAPSULE_HEADER *CapsuleHeader + ); + +/** + Check the integrity of the capsule name capsule. + If the capsule is vaild, return the physical address of each capsule nam= e string. + + @param[in] CapsuleHeader Pointer to the capsule header of a capsule n= ame capsule. + @param[out] CapsuleNameNum Number of capsule name. + + @retval NULL Capsule name capsule is not valid. + @retval CapsuleNameBuf Array of capsule name physical address. + +**/ +EFI_PHYSICAL_ADDRESS * +ValidateCapsuleNameCapsuleIntegrity ( + IN EFI_CAPSULE_HEADER *CapsuleHeader, + OUT UINTN *CapsuleNameNum + ) +{ + UINT8 *CapsuleNamePtr; + UINT8 *CapsuleNameBufStart; + UINT8 *CapsuleNameBufEnd; + UINTN Index; + UINTN StringSize; + EFI_PHYSICAL_ADDRESS *CapsuleNameBuf; + + if (!IsCapsuleNameCapsule (CapsuleHeader)) { + return NULL; + } + + // + // Total string size must be even. + // + if (((CapsuleHeader->CapsuleImageSize - CapsuleHeader->HeaderSize) & BIT= 0) !=3D 0) { + return NULL; + } + + *CapsuleNameNum =3D 0; + Index =3D 0; + CapsuleNameBufStart =3D (UINT8 *) CapsuleHeader + CapsuleHeader->HeaderS= ize; + + // + // If strings are not aligned on a 16-bit boundary, reallocate memory fo= r it. + // + if (((UINTN) CapsuleNameBufStart & BIT0) !=3D 0) { + CapsuleNameBufStart =3D AllocateCopyPool (CapsuleHeader->CapsuleImageS= ize - CapsuleHeader->HeaderSize, CapsuleNameBufStart); + } + + CapsuleNameBufEnd =3D CapsuleNameBufStart + CapsuleHeader->CapsuleImageS= ize - CapsuleHeader->HeaderSize; + + CapsuleNamePtr =3D CapsuleNameBufStart; + while (CapsuleNamePtr < CapsuleNameBufEnd) { + StringSize=3D StrnSizeS ((CHAR16 *) CapsuleNamePtr, (CapsuleNameBufEnd= - CapsuleNamePtr)/sizeof(CHAR16)); + CapsuleNamePtr +=3D StringSize; + (*CapsuleNameNum) ++; + } + + // + // Integrity check. + // + if (CapsuleNamePtr !=3D CapsuleNameBufEnd) { + if (CapsuleNameBufStart !=3D (UINT8 *)CapsuleHeader + CapsuleHeader->H= eaderSize) { + FreePool (CapsuleNameBufStart); + } + return NULL; + } + + CapsuleNameBuf =3D AllocatePool (*CapsuleNameNum * sizeof (EFI_PHYSICAL_= ADDRESS)); + if (CapsuleNameBuf =3D=3D NULL) { + if (CapsuleNameBufStart !=3D (UINT8 *)CapsuleHeader + CapsuleHeader->H= eaderSize) { + FreePool (CapsuleNameBufStart); + } + return NULL; + } + + CapsuleNamePtr =3D CapsuleNameBufStart; + while (CapsuleNamePtr < CapsuleNameBufEnd) { + StringSize=3D StrnSizeS ((CHAR16 *) CapsuleNamePtr, (CapsuleNameBufEnd= - CapsuleNamePtr)/sizeof(CHAR16)); + CapsuleNameBuf[Index] =3D (EFI_PHYSICAL_ADDRESS)(UINTN) CapsuleNamePtr; + CapsuleNamePtr +=3D StringSize; + Index ++; + } + + return CapsuleNameBuf; +} + +/** + This routine is called to upper case given unicode string. + + @param[in] Str String to upper case + + @retval upper cased string after process + +**/ +STATIC +CHAR16 * +UpperCaseString ( + IN CHAR16 *Str + ) +{ + CHAR16 *Cptr; + + for (Cptr =3D Str; *Cptr; Cptr++) { + if (L'a' <=3D *Cptr && *Cptr <=3D L'z') { + *Cptr =3D *Cptr - L'a' + L'A'; + } + } + + return Str; +} + +/** + This routine is used to return substring before period '.' or '\0' + Caller should respsonsible of substr space allocation & free + + @param[in] Str String to check + @param[out] SubStr First part of string before period or '\0' + @param[out] SubStrLen Length of first part of string + +**/ +STATIC +VOID +GetSubStringBeforePeriod ( + IN CHAR16 *Str, + OUT CHAR16 *SubStr, + OUT UINTN *SubStrLen + ) +{ + UINTN Index; + for (Index =3D 0; Str[Index] !=3D L'.' && Str[Index] !=3D L'\0'; Index++= ) { + SubStr[Index] =3D Str[Index]; + } + + SubStr[Index] =3D L'\0'; + *SubStrLen =3D Index; +} + +/** + This routine pad the string in tail with input character. + + @param[in] StrBuf Str buffer to be padded, should be enough= room for + @param[in] PadLen Expected padding length + @param[in] Character Character used to pad + +**/ +STATIC +VOID +PadStrInTail ( + IN CHAR16 *StrBuf, + IN UINTN PadLen, + IN CHAR16 Character + ) +{ + UINTN Index; + + for (Index =3D 0; StrBuf[Index] !=3D L'\0'; Index++); + + while(PadLen !=3D 0) { + StrBuf[Index] =3D Character; + Index++; + PadLen--; + } + + StrBuf[Index] =3D L'\0'; +} + +/** + This routine find the offset of the last period '.' of string. If No per= iod exists + function FileNameExtension is set to L'\0' + + @param[in] FileName File name to split between last period + @param[out] FileNameFirst First FileName before last period + @param[out] FileNameExtension FileName after last period + +**/ +STATIC +VOID +SplitFileNameExtension ( + IN CHAR16 *FileName, + OUT CHAR16 *FileNameFirst, + OUT CHAR16 *FileNameExtension + ) +{ + UINTN Index; + UINTN StringLen; + + StringLen =3D StrnLenS(FileName, MAX_FILE_NAME_SIZE); + for (Index =3D StringLen; Index > 0 && FileName[Index] !=3D L'.'; Index-= -); + + // + // No period exists. No FileName Extension + // + if (Index =3D=3D 0 && FileName[Index] !=3D L'.') { + FileNameExtension[0] =3D L'\0'; + Index =3D StringLen; + } else { + StrCpyS(FileNameExtension, MAX_FILE_NAME_SIZE, &FileName[Index+1]); + } + + // + // Copy First file name + // + StrnCpyS(FileNameFirst, MAX_FILE_NAME_SIZE, FileName, Index); + FileNameFirst[Index] =3D L'\0'; +} + +/** + This routine is called to get all boot options in the order determnined = by: + 1. "OptionBuf" + 2. "BootOrder" + + @param[out] OptionBuf BootList buffer to all boot options retu= rned + @param[out] OptionCount BootList count of all boot options retur= ned + + @retval EFI_SUCCESS There is no error when processing capsule + +**/ +EFI_STATUS +GetBootOptionInOrder( + OUT EFI_BOOT_MANAGER_LOAD_OPTION **OptionBuf, + OUT UINTN *OptionCount + ) +{ + EFI_STATUS Status; + UINTN DataSize; + UINT16 BootNext; + CHAR16 BootOptionName[20]; + EFI_BOOT_MANAGER_LOAD_OPTION *BootOrderOptionBuf; + UINTN BootOrderCount; + EFI_BOOT_MANAGER_LOAD_OPTION BootNextOptionEntry; + UINTN BootNextCount; + EFI_BOOT_MANAGER_LOAD_OPTION *TempBuf; + + BootOrderOptionBuf =3D NULL; + TempBuf =3D NULL; + BootNextCount =3D 0; + BootOrderCount =3D 0; + *OptionBuf =3D NULL; + *OptionCount =3D 0; + + // + // First Get BootOption from "BootNext" + // + DataSize =3D sizeof(BootNext); + Status =3D gRT->GetVariable ( + EFI_BOOT_NEXT_VARIABLE_NAME, + &gEfiGlobalVariableGuid, + NULL, + &DataSize, + (VOID *)&BootNext + ); + // + // BootNext variable is a single UINT16 + // + if (!EFI_ERROR(Status) && DataSize =3D=3D sizeof(UINT16)) { + // + // Add the boot next boot option + // + UnicodeSPrint (BootOptionName, sizeof (BootOptionName), L"Boot%04x", B= ootNext); + ZeroMem(&BootNextOptionEntry, sizeof(EFI_BOOT_MANAGER_LOAD_OPTION)); + Status =3D EfiBootManagerVariableToLoadOption (BootOptionName, &BootNe= xtOptionEntry); + + if (!EFI_ERROR(Status)) { + BootNextCount =3D 1; + } + } + + // + // Second get BootOption from "BootOrder" + // + BootOrderOptionBuf =3D EfiBootManagerGetLoadOptions (&BootOrderCount, Lo= adOptionTypeBoot); + if (BootNextCount =3D=3D 0 && BootOrderCount =3D=3D 0) { + return EFI_NOT_FOUND; + } + + // + // At least one BootOption is found + // + TempBuf =3D AllocatePool(sizeof(EFI_BOOT_MANAGER_LOAD_OPTION) * (BootNex= tCount + BootOrderCount)); + if (TempBuf !=3D NULL) { + if (BootNextCount =3D=3D 1) { + CopyMem(TempBuf, &BootNextOptionEntry, sizeof(EFI_BOOT_MANAGER_LOAD_= OPTION)); + } + + if (BootOrderCount > 0) { + CopyMem(TempBuf + BootNextCount, BootOrderOptionBuf, sizeof(EFI_BOOT= _MANAGER_LOAD_OPTION) * BootOrderCount); + } + + *OptionBuf =3D TempBuf; + *OptionCount =3D BootNextCount + BootOrderCount; + Status =3D EFI_SUCCESS; + } else { + Status =3D EFI_OUT_OF_RESOURCES; + } + + FreePool(BootOrderOptionBuf); + + return Status; +} + +/** + This routine is called to get boot option by OptionNumber. + + @param[in] Number The OptionNumber of boot option + @param[out] OptionBuf BootList buffer to all boot options retu= rned + + @retval EFI_SUCCESS There is no error when getting boot opti= on + +**/ +EFI_STATUS +GetBootOptionByNumber( + IN UINT16 Number, + OUT EFI_BOOT_MANAGER_LOAD_OPTION **OptionBuf + ) +{ + EFI_STATUS Status; + CHAR16 BootOptionName[20]; + EFI_BOOT_MANAGER_LOAD_OPTION BootOption; + + UnicodeSPrint (BootOptionName, sizeof (BootOptionName), L"Boot%04x", Num= ber); + ZeroMem (&BootOption, sizeof (EFI_BOOT_MANAGER_LOAD_OPTION)); + Status =3D EfiBootManagerVariableToLoadOption (BootOptionName, &BootOpti= on); + + if (!EFI_ERROR (Status)) { + *OptionBuf =3D AllocatePool (sizeof (EFI_BOOT_MANAGER_LOAD_OPTION)); + CopyMem (*OptionBuf, &BootOption, sizeof (EFI_BOOT_MANAGER_LOAD_OPTION= )); + return EFI_SUCCESS; + } + + return Status; +} + +/** + Get Active EFI System Partition within GPT based on device path. + + @param[in] DevicePath Device path to find a active EFI System Partiti= on + @param[out] FsHandle BootList points to all boot options returned + + @retval EFI_SUCCESS Active EFI System Partition is succesfully found + @retval EFI_NOT_FOUND No Active EFI System Partition is found + +**/ +EFI_STATUS +GetEfiSysPartitionFromDevPath( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + OUT EFI_HANDLE *FsHandle + ) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; + HARDDRIVE_DEVICE_PATH *Hd; + EFI_HANDLE Handle; + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Fs; + + // + // Check if the device path contains GPT node + // + TempDevicePath =3D DevicePath; + while (!IsDevicePathEnd (TempDevicePath)) { + if ((DevicePathType (TempDevicePath) =3D=3D MEDIA_DEVICE_PATH) && + (DevicePathSubType (TempDevicePath) =3D=3D MEDIA_HARDDRIVE_DP)) { + Hd =3D (HARDDRIVE_DEVICE_PATH *)TempDevicePath; + if (Hd->MBRType =3D=3D MBR_TYPE_EFI_PARTITION_TABLE_HEADER) { + break; + } + } + TempDevicePath =3D NextDevicePathNode (TempDevicePath); + } + + if (!IsDevicePathEnd (TempDevicePath)) { + // + // Search for EFI system partition protocol on full device path in Boo= t Option + // + Status =3D gBS->LocateDevicePath (&gEfiPartTypeSystemPartGuid, &Device= Path, &Handle); + + // + // Search for simple file system on this handler + // + if (!EFI_ERROR(Status)) { + Status =3D gBS->HandleProtocol(Handle, &gEfiSimpleFileSystemProtocol= Guid, (VOID **)&Fs); + if (!EFI_ERROR(Status)) { + *FsHandle =3D Handle; + return EFI_SUCCESS; + } + } + } + + return EFI_NOT_FOUND; +} + +/** + This routine is called to get Simple File System protocol on the first E= FI system partition found in + active boot option. The boot option list is detemined in order by + 1. "BootNext" + 2. "BootOrder" + + @param[in] MaxRetry Max Connection Retry. Stall 100ms be= tween each connection try to ensure + device like USB can get enumerated. + @param[in, out] LoadOptionNumber On input, specify the boot option to= get EFI system partition. + On output, return the OptionNumber o= f the boot option where EFI + system partition is got from. + @param[out] FsFsHandle Simple File System Protocol found on= first active EFI system partition + + @retval EFI_SUCCESS Simple File System protocol found for EFI system= partition + @retval EFI_NOT_FOUND No Simple File System protocol found for EFI sys= tem partition + +**/ +EFI_STATUS +GetEfiSysPartitionFromActiveBootOption( + IN UINTN MaxRetry, + IN OUT UINT16 **LoadOptionNumber, + OUT EFI_HANDLE *FsHandle + ) +{ + EFI_STATUS Status; + EFI_BOOT_MANAGER_LOAD_OPTION *BootOptionBuf; + UINTN BootOptionNum; + UINTN Index; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_DEVICE_PATH_PROTOCOL *CurFullPath; + EFI_DEVICE_PATH_PROTOCOL *PreFullPath; + + *FsHandle =3D NULL; + + if (*LoadOptionNumber !=3D NULL) { + BootOptionNum =3D 1; + Status =3D GetBootOptionByNumber(**LoadOptionNumber, &BootOptionBuf); + if (EFI_ERROR(Status)) { + DEBUG ((DEBUG_ERROR, "GetBootOptionByIndex Failed %x! No BootOption = available for connection\n", Status)); + return Status; + } + } else { + Status =3D GetBootOptionInOrder(&BootOptionBuf, &BootOptionNum); + if (EFI_ERROR(Status)) { + DEBUG ((DEBUG_ERROR, "GetBootOptionInOrder Failed %x! No BootOption = available for connection\n", Status)); + return Status; + } + } + + // + // Search BootOptionList to check if it is an active boot option with EF= I system partition + // 1. Connect device path + // 2. expend short/plug in devicepath + // 3. LoadImage + // + for (Index =3D 0; Index < BootOptionNum; Index++) { + // + // Get the boot option from the link list + // + DevicePath =3D BootOptionBuf[Index].FilePath; + + // + // Skip inactive or legacy boot options + // + if ((BootOptionBuf[Index].Attributes & LOAD_OPTION_ACTIVE) =3D=3D 0 || + DevicePathType (DevicePath) =3D=3D BBS_DEVICE_PATH) { + continue; + } + + DEBUG_CODE ( + CHAR16 *DevicePathStr; + + DevicePathStr =3D ConvertDevicePathToText(DevicePath, TRUE, TRUE); + if (DevicePathStr !=3D NULL){ + DEBUG((DEBUG_INFO, "Try BootOption %s\n", DevicePathStr)); + FreePool(DevicePathStr); + } else { + DEBUG((DEBUG_INFO, "DevicePathToStr failed\n")); + } + ); + + CurFullPath =3D NULL; + // + // Try every full device Path generated from bootoption + // + do { + PreFullPath =3D CurFullPath; + CurFullPath =3D EfiBootManagerGetNextLoadOptionDevicePath(DevicePath= , CurFullPath); + + if (PreFullPath !=3D NULL) { + FreePool (PreFullPath); + } + + if (CurFullPath =3D=3D NULL) { + // + // No Active EFI system partition is found in BootOption device pa= th + // + Status =3D EFI_NOT_FOUND; + break; + } + + DEBUG_CODE ( + CHAR16 *DevicePathStr1; + + DevicePathStr1 =3D ConvertDevicePathToText(CurFullPath, TRUE, TRUE= ); + if (DevicePathStr1 !=3D NULL){ + DEBUG((DEBUG_INFO, "Full device path %s\n", DevicePathStr1)); + FreePool(DevicePathStr1); + } + ); + + // + // Make sure the boot option device path connected. + // Only handle first device in boot option. Other optional device pa= ths are described as OSV specific + // FullDevice could contain extra directory & file info. So don't ch= eck connection status here. + // + EfiBootManagerConnectDevicePath (CurFullPath, NULL); + Status =3D GetEfiSysPartitionFromDevPath(CurFullPath, FsHandle); + + // + // Some relocation device like USB need more time to get enumerated + // + while (EFI_ERROR(Status) && MaxRetry > 0) { + EfiBootManagerConnectDevicePath(CurFullPath, NULL); + + // + // Search for EFI system partition protocol on full device path in= Boot Option + // + Status =3D GetEfiSysPartitionFromDevPath(CurFullPath, FsHandle); + if (!EFI_ERROR(Status)) { + break; + } + DEBUG((DEBUG_ERROR, "GetEfiSysPartitionFromDevPath Loop %x\n", Sta= tus)); + // + // Stall 100ms if connection failed to ensure USB stack is ready + // + gBS->Stall(100000); + MaxRetry --; + } + } while(EFI_ERROR(Status)); + + // + // Find a qualified Simple File System + // + if (!EFI_ERROR(Status)) { + break; + } + + } + + // + // Return the OptionNumber of the boot option where EFI system partition= is got from + // + if (*LoadOptionNumber =3D=3D NULL) { + *LoadOptionNumber =3D AllocateCopyPool (sizeof(UINT16), (UINT16 *) &Bo= otOptionBuf[Index].OptionNumber); + } + + // + // No qualified EFI system partition found + // + if (*FsHandle =3D=3D NULL) { + Status =3D EFI_NOT_FOUND; + } + + DEBUG_CODE ( + CHAR16 *DevicePathStr2; + if (*FsHandle !=3D NULL) { + DevicePathStr2 =3D ConvertDevicePathToText(CurFullPath, TRUE, TRUE); + if (DevicePathStr2 !=3D NULL){ + DEBUG((DEBUG_INFO, "Found Active EFI System Partion on %s\n", Devi= cePathStr2)); + FreePool(DevicePathStr2); + } + } else { + DEBUG((DEBUG_INFO, "Failed to found Active EFI System Partion\n")); + } + ); + + if (CurFullPath !=3D NULL) { + FreePool(CurFullPath); + } + + // + // Free BootOption Buffer + // + for (Index =3D 0; Index < BootOptionNum; Index++) { + if (BootOptionBuf[Index].Description !=3D NULL) { + FreePool(BootOptionBuf[Index].Description); + } + + if (BootOptionBuf[Index].FilePath !=3D NULL) { + FreePool(BootOptionBuf[Index].FilePath); + } + + if (BootOptionBuf[Index].OptionalData !=3D NULL) { + FreePool(BootOptionBuf[Index].OptionalData); + } + } + + FreePool(BootOptionBuf); + + return Status; +} + + +/** + This routine is called to get all file infos with in a given dir & with = given file attribute, the file info is listed in + alphabetical order described in UEFI spec. + + @param[in] Dir Directory file handler + @param[in] FileAttr Attribute of file to be red from directo= ry + @param[out] FileInfoList File images info list red from directory + @param[out] FileNum File images number red from directory + + @retval EFI_SUCCESS File FileInfo list in the given + +**/ +EFI_STATUS +GetFileInfoListInAlphabetFromDir( + IN EFI_FILE_HANDLE Dir, + IN UINT64 FileAttr, + OUT LIST_ENTRY *FileInfoList, + OUT UINTN *FileNum + ) +{ + EFI_STATUS Status; + FILE_INFO_ENTRY *NewFileInfoEntry; + FILE_INFO_ENTRY *TempFileInfoEntry; + EFI_FILE_INFO *FileInfo; + CHAR16 *NewFileName; + CHAR16 *ListedFileName; + CHAR16 *NewFileNameExtension; + CHAR16 *ListedFileNameExtension; + CHAR16 *TempNewSubStr; + CHAR16 *TempListedSubStr; + LIST_ENTRY *Link; + BOOLEAN NoFile; + UINTN FileCount; + UINTN IndexNew; + UINTN IndexListed; + UINTN NewSubStrLen; + UINTN ListedSubStrLen; + INTN SubStrCmpResult; + + Status =3D EFI_SUCCESS; + NewFileName =3D NULL; + ListedFileName =3D NULL; + NewFileNameExtension =3D NULL; + ListedFileNameExtension =3D NULL; + TempNewSubStr =3D NULL; + TempListedSubStr =3D NULL; + NoFile =3D FALSE; + FileCount =3D 0; + + InitializeListHead(FileInfoList); + + TempNewSubStr =3D (CHAR16 *) AllocateZeroPool(MAX_FILE_NAME_SI= ZE); + TempListedSubStr =3D (CHAR16 *) AllocateZeroPool(MAX_FILE_NAME_SI= ZE); + + if (TempNewSubStr =3D=3D NULL || TempListedSubStr =3D=3D NULL ) { + Status =3D EFI_OUT_OF_RESOURCES; + goto EXIT; + } + + for ( Status =3D FileHandleFindFirstFile(Dir, &FileInfo) + ; !EFI_ERROR(Status) && !NoFile + ; Status =3D FileHandleFindNextFile(Dir, FileInfo, &NoFile) + ){ + + // + // Skip file with mismatching File attribute + // + if ((FileInfo->Attribute & (FileAttr)) =3D=3D 0) { + continue; + } + + NewFileInfoEntry =3D NULL; + NewFileInfoEntry =3D (FILE_INFO_ENTRY*)AllocateZeroPool(sizeof(FILE_IN= FO_ENTRY)); + if (NewFileInfoEntry =3D=3D NULL) { + Status =3D EFI_OUT_OF_RESOURCES; + goto EXIT; + } + NewFileInfoEntry->Signature =3D FILE_INFO_SIGNATURE; + NewFileInfoEntry->FileInfo =3D AllocateCopyPool((UINTN) FileInfo->Siz= e, FileInfo); + if (NewFileInfoEntry->FileInfo =3D=3D NULL) { + FreePool(NewFileInfoEntry); + Status =3D EFI_OUT_OF_RESOURCES; + goto EXIT; + } + + NewFileInfoEntry->FileNameFirstPart =3D (CHAR16 *) AllocateZeroPool(M= AX_FILE_NAME_SIZE); + if (NewFileInfoEntry->FileNameFirstPart =3D=3D NULL) { + FreePool(NewFileInfoEntry->FileInfo); + FreePool(NewFileInfoEntry); + Status =3D EFI_OUT_OF_RESOURCES; + goto EXIT; + } + NewFileInfoEntry->FileNameSecondPart =3D (CHAR16 *) AllocateZeroPool(M= AX_FILE_NAME_SIZE); + if (NewFileInfoEntry->FileNameSecondPart =3D=3D NULL) { + FreePool(NewFileInfoEntry->FileInfo); + FreePool(NewFileInfoEntry->FileNameFirstPart); + FreePool(NewFileInfoEntry); + Status =3D EFI_OUT_OF_RESOURCES; + goto EXIT; + } + + // + // Splitter the whole New file name into 2 parts between the last peri= od L'.' into NewFileName NewFileExtension + // If no period in the whole file name. NewFileExtension is set to L'\= 0' + // + NewFileName =3D NewFileInfoEntry->FileNameFirstPart; + NewFileNameExtension =3D NewFileInfoEntry->FileNameSecondPart; + SplitFileNameExtension(FileInfo->FileName, NewFileName, NewFileNameExt= ension); + UpperCaseString(NewFileName); + UpperCaseString(NewFileNameExtension); + + // + // Insert capsule file in alphabetical ordered list + // + for (Link =3D FileInfoList->ForwardLink; Link !=3D FileInfoList; Link = =3D Link->ForwardLink) { + // + // Get the FileInfo from the link list + // + TempFileInfoEntry =3D CR (Link, FILE_INFO_ENTRY, Link, FILE_INFO_SIG= NATURE); + ListedFileName =3D TempFileInfoEntry->FileNameFirstPart; + ListedFileNameExtension =3D TempFileInfoEntry->FileNameSecondPart; + + // + // Follow rule in UEFI spec 8.5.5 to compare file name + // + IndexListed =3D 0; + IndexNew =3D 0; + while (TRUE){ + // + // First compare each substrings in NewFileName & ListedFileName b= etween periods + // + GetSubStringBeforePeriod(&NewFileName[IndexNew], TempNewSubStr, &N= ewSubStrLen); + GetSubStringBeforePeriod(&ListedFileName[IndexListed], TempListedS= ubStr, &ListedSubStrLen); + if (NewSubStrLen > ListedSubStrLen) { + // + // Substr in NewFileName is longer. Pad tail with SPACE + // + PadStrInTail(TempListedSubStr, NewSubStrLen - ListedSubStrLen, L= ' '); + } else if (NewSubStrLen < ListedSubStrLen){ + // + // Substr in ListedFileName is longer. Pad tail with SPACE + // + PadStrInTail(TempNewSubStr, ListedSubStrLen - NewSubStrLen, L' '= ); + } + + SubStrCmpResult =3D StrnCmp(TempNewSubStr, TempListedSubStr, MAX_F= ILE_NAME_LEN); + if (SubStrCmpResult !=3D 0) { + break; + } + + // + // Move to skip this substring + // + IndexNew +=3D NewSubStrLen; + IndexListed +=3D ListedSubStrLen; + // + // Reach File First Name end + // + if (NewFileName[IndexNew] =3D=3D L'\0' || ListedFileName[IndexList= ed] =3D=3D L'\0') { + break; + } + + // + // Skip the period L'.' + // + IndexNew++; + IndexListed++; + } + + if (SubStrCmpResult < 0) { + // + // NewFileName is smaller. Find the right place to insert New file + // + break; + } else if (SubStrCmpResult =3D=3D 0) { + // + // 2 cases whole NewFileName is smaller than ListedFileName + // 1. if NewFileName =3D=3D ListedFileName. Continue to compare = FileNameExtension + // 2. if NewFileName is shorter than ListedFileName + // + if (NewFileName[IndexNew] =3D=3D L'\0') { + if (ListedFileName[IndexListed] !=3D L'\0' || (StrnCmp(NewFileNa= meExtension, ListedFileNameExtension, MAX_FILE_NAME_LEN) < 0)) { + break; + } + } + } + + // + // Other case, ListedFileName is smaller. Continue to compare the ne= xt file in the list + // + } + + // + // If Find an entry in the list whose name is bigger than new FileInfo= in alphabet order + // Insert it before this entry + // else + // Insert at the tail of this list (Link =3D FileInfoList) + // + InsertTailList(Link, &NewFileInfoEntry->Link); + + FileCount++; + } + + *FileNum =3D FileCount; + +EXIT: + + if (TempNewSubStr !=3D NULL) { + FreePool(TempNewSubStr); + } + + if (TempListedSubStr !=3D NULL) { + FreePool(TempListedSubStr); + } + + if (EFI_ERROR(Status)) { + while(!IsListEmpty(FileInfoList)) { + Link =3D FileInfoList->ForwardLink; + RemoveEntryList(Link); + + TempFileInfoEntry =3D CR (Link, FILE_INFO_ENTRY, Link, FILE_INFO_SIG= NATURE); + + FreePool(TempFileInfoEntry->FileInfo); + FreePool(TempFileInfoEntry->FileNameFirstPart); + FreePool(TempFileInfoEntry->FileNameSecondPart); + FreePool(TempFileInfoEntry); + } + *FileNum =3D 0; + } + + return Status; +} + + +/** + This routine is called to get all qualified image from file from an give= n directory + in alphabetic order. All the file image is copied to allocated boottime = memory. + Caller should free these memory + + @param[in] Dir Directory file handler + @param[in] FileAttr Attribute of file to be red from directory + @param[out] FilePtr File images Info buffer red from directory + @param[out] FileNum File images number red from directory + + @retval EFI_SUCCESS Succeed to get all capsules in alphabetic order. + +**/ +EFI_STATUS +GetFileImageInAlphabetFromDir( + IN EFI_FILE_HANDLE Dir, + IN UINT64 FileAttr, + OUT IMAGE_INFO **FilePtr, + OUT UINTN *FileNum + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Link; + EFI_FILE_HANDLE FileHandle; + FILE_INFO_ENTRY *FileInfoEntry; + EFI_FILE_INFO *FileInfo; + UINTN FileCount; + IMAGE_INFO *TempFilePtrBuf; + UINTN Size; + LIST_ENTRY FileInfoList; + + FileHandle =3D NULL; + FileCount =3D 0; + TempFilePtrBuf =3D NULL; + *FilePtr =3D NULL; + + // + // Get file list in Dir in alphabetical order + // + Status =3D GetFileInfoListInAlphabetFromDir( + Dir, + FileAttr, + &FileInfoList, + &FileCount + ); + if (EFI_ERROR(Status)) { + DEBUG ((DEBUG_ERROR, "GetFileInfoListInAlphabetFromDir Failed!\n")); + goto EXIT; + } + + if (FileCount =3D=3D 0) { + DEBUG ((DEBUG_ERROR, "No file found in Dir!\n")); + Status =3D EFI_NOT_FOUND; + goto EXIT; + } + + TempFilePtrBuf =3D (IMAGE_INFO *)AllocateZeroPool(sizeof(IMAGE_INFO) * F= ileCount); + if (TempFilePtrBuf =3D=3D NULL) { + Status =3D EFI_OUT_OF_RESOURCES; + goto EXIT; + } + + // + // Read all files from FileInfoList to BS memory + // + FileCount =3D 0; + for (Link =3D FileInfoList.ForwardLink; Link !=3D &FileInfoList; Link = =3D Link->ForwardLink) { + // + // Get FileInfo from the link list + // + FileInfoEntry =3D CR (Link, FILE_INFO_ENTRY, Link, FILE_INFO_SIGNATURE= ); + FileInfo =3D FileInfoEntry->FileInfo; + + Status =3D Dir->Open( + Dir, + &FileHandle, + FileInfo->FileName, + EFI_FILE_MODE_READ, + 0 + ); + if (EFI_ERROR(Status)){ + continue; + } + + Size =3D (UINTN)FileInfo->FileSize; + TempFilePtrBuf[FileCount].ImageAddress =3D AllocateZeroPool(Size); + if (TempFilePtrBuf[FileCount].ImageAddress =3D=3D NULL) { + DEBUG((DEBUG_ERROR, "Fail to allocate memory for capsule. Stop proce= ssing the rest.\n")); + break; + } + + Status =3D FileHandle->Read( + FileHandle, + &Size, + TempFilePtrBuf[FileCount].ImageAddress + ); + + FileHandle->Close(FileHandle); + + // + // Skip read error file + // + if (EFI_ERROR(Status) || Size !=3D (UINTN)FileInfo->FileSize) { + // + // Remove this error file info accordingly + // & move Link to BackLink + // + Link =3D RemoveEntryList(Link); + Link =3D Link->BackLink; + + FreePool(FileInfoEntry->FileInfo); + FreePool(FileInfoEntry->FileNameFirstPart); + FreePool(FileInfoEntry->FileNameSecondPart); + FreePool(FileInfoEntry); + + FreePool(TempFilePtrBuf[FileCount].ImageAddress); + TempFilePtrBuf[FileCount].ImageAddress =3D NULL; + TempFilePtrBuf[FileCount].FileInfo =3D NULL; + + continue; + } + TempFilePtrBuf[FileCount].FileInfo =3D FileInfo; + FileCount++; + } + + DEBUG_CODE ( + for (Link =3D FileInfoList.ForwardLink; Link !=3D &FileInfoList; Link = =3D Link->ForwardLink) { + FileInfoEntry =3D CR (Link, FILE_INFO_ENTRY, Link, FILE_INFO_SIGNATU= RE); + FileInfo =3D FileInfoEntry->FileInfo; + DEBUG((DEBUG_INFO, "Successfully read capsule file %s from disk.\n",= FileInfo->FileName)); + } + ); + +EXIT: + + *FilePtr =3D TempFilePtrBuf; + *FileNum =3D FileCount; + + // + // FileInfo will be freed by Calller + // + while(!IsListEmpty(&FileInfoList)) { + Link =3D FileInfoList.ForwardLink; + RemoveEntryList(Link); + + FileInfoEntry =3D CR (Link, FILE_INFO_ENTRY, Link, FILE_INFO_SIGNATURE= ); + + FreePool(FileInfoEntry->FileNameFirstPart); + FreePool(FileInfoEntry->FileNameSecondPart); + FreePool(FileInfoEntry); + } + + return Status; +} + +/** + This routine is called to remove all qualified image from file from an g= iven directory. + + @param[in] Dir Directory file handler + @param[in] FileAttr Attribute of files to be deleted + + @retval EFI_SUCCESS Succeed to remove all files from an given directory. + +**/ +EFI_STATUS +RemoveFileFromDir( + IN EFI_FILE_HANDLE Dir, + IN UINT64 FileAttr + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Link; + LIST_ENTRY FileInfoList; + EFI_FILE_HANDLE FileHandle; + FILE_INFO_ENTRY *FileInfoEntry; + EFI_FILE_INFO *FileInfo; + UINTN FileCount; + + FileHandle =3D NULL; + + // + // Get file list in Dir in alphabetical order + // + Status =3D GetFileInfoListInAlphabetFromDir( + Dir, + FileAttr, + &FileInfoList, + &FileCount + ); + if (EFI_ERROR(Status)) { + DEBUG ((DEBUG_ERROR, "GetFileInfoListInAlphabetFromDir Failed!\n")); + goto EXIT; + } + + if (FileCount =3D=3D 0) { + DEBUG ((DEBUG_ERROR, "No file found in Dir!\n")); + Status =3D EFI_NOT_FOUND; + goto EXIT; + } + + // + // Delete all files with given attribute in Dir + // + for (Link =3D FileInfoList.ForwardLink; Link !=3D &(FileInfoList); Link = =3D Link->ForwardLink) { + // + // Get FileInfo from the link list + // + FileInfoEntry =3D CR (Link, FILE_INFO_ENTRY, Link, FILE_INFO_SIGNATURE= ); + FileInfo =3D FileInfoEntry->FileInfo; + + Status =3D Dir->Open( + Dir, + &FileHandle, + FileInfo->FileName, + EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE, + 0 + ); + if (EFI_ERROR(Status)){ + continue; + } + + Status =3D FileHandle->Delete(FileHandle); + } + +EXIT: + + while(!IsListEmpty(&FileInfoList)) { + Link =3D FileInfoList.ForwardLink; + RemoveEntryList(Link); + + FileInfoEntry =3D CR (Link, FILE_INFO_ENTRY, Link, FILE_INFO_SIGNATURE= ); + + FreePool(FileInfoEntry->FileInfo); + FreePool(FileInfoEntry); + } + + return Status; +} + +/** + This routine is called to get all caspules from file. The capsule file i= mage is + copied to BS memory. Caller is responsible to free them. + + @param[in] MaxRetry Max Connection Retry. Stall 100ms bet= ween each connection try to ensure + devices like USB can get enumerated. + @param[out] CapsulePtr Copied Capsule file Image Info buffer + @param[out] CapsuleNum CapsuleNumber + @param[out] FsHandle File system handle + @param[out] LoadOptionNumber OptionNumber of boot option + + @retval EFI_SUCCESS Succeed to get all capsules. + +**/ +EFI_STATUS +EFIAPI +GetAllCapsuleOnDisk( + IN UINTN MaxRetry, + OUT IMAGE_INFO **CapsulePtr, + OUT UINTN *CapsuleNum, + OUT EFI_HANDLE *FsHandle, + OUT UINT16 *LoadOptionNumber + ) +{ + EFI_STATUS Status; + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Fs; + EFI_FILE_HANDLE RootDir; + EFI_FILE_HANDLE FileDir; + UINT16 *TempOptionNumber; + + Fs =3D NULL; + RootDir =3D NULL; + FileDir =3D NULL; + TempOptionNumber =3D NULL; + *CapsuleNum =3D 0; + + Status =3D GetEfiSysPartitionFromActiveBootOption(MaxRetry, &TempOptionN= umber, FsHandle); + if (EFI_ERROR(Status)) { + return Status; + } + + Status =3D gBS->HandleProtocol(*FsHandle, &gEfiSimpleFileSystemProtocolG= uid, (VOID **)&Fs); + if (EFI_ERROR(Status)) { + return Status; + } + + Status =3D Fs->OpenVolume(Fs, &RootDir); + if (EFI_ERROR(Status)) { + return Status; + } + + Status =3D RootDir->Open( + RootDir, + &FileDir, + EFI_CAPSULE_FILE_DIRECTORY, + EFI_FILE_MODE_READ, + 0 + ); + if (EFI_ERROR(Status)) { + DEBUG((DEBUG_ERROR, "CodLibGetAllCapsuleOnDisk fail to open RootDir!\n= ")); + goto EXIT; + } + + // + // Only Load files with EFI_FILE_SYSTEM or EFI_FILE_ARCHIVE attribute + // ignore EFI_FILE_READ_ONLY, EFI_FILE_HIDDEN, EFI_FILE_RESERVED, EFI_FI= LE_DIRECTORY + // + Status =3D GetFileImageInAlphabetFromDir( + FileDir, + EFI_FILE_SYSTEM | EFI_FILE_ARCHIVE, + CapsulePtr, + CapsuleNum + ); + DEBUG((DEBUG_INFO, "GetFileImageInAlphabetFromDir status %x\n", Status)); + + // + // Always remove file to avoid deadloop in capsule process + // + Status =3D RemoveFileFromDir(FileDir, EFI_FILE_SYSTEM | EFI_FILE_ARCHIVE= ); + DEBUG((DEBUG_INFO, "RemoveFileFromDir status %x\n", Status)); + + if (LoadOptionNumber !=3D NULL) { + *LoadOptionNumber =3D *TempOptionNumber; + } + +EXIT: + + if (FileDir !=3D NULL) { + FileDir->Close (FileDir); + } + + if (RootDir !=3D NULL) { + RootDir->Close (RootDir); + } + + return Status; +} + +/** + Build Gather list for a list of capsule images. + + @param[in] CapsuleBuffer An array of pointer to capsule images + @param[in] CapsuleSize An array of UINTN to capsule images size + @param[in] CapsuleNum The count of capsule images + @param[out] BlockDescriptors The block descriptors for the capsule images + + @retval EFI_SUCCESS The block descriptors for the capsule images are con= structed. + +**/ +EFI_STATUS +BuildGatherList ( + IN VOID **CapsuleBuffer, + IN UINTN *CapsuleSize, + IN UINTN CapsuleNum, + OUT EFI_CAPSULE_BLOCK_DESCRIPTOR **BlockDescriptors + ) +{ + EFI_STATUS Status; + EFI_CAPSULE_BLOCK_DESCRIPTOR *BlockDescriptors1; + EFI_CAPSULE_BLOCK_DESCRIPTOR *BlockDescriptorPre; + EFI_CAPSULE_BLOCK_DESCRIPTOR *BlockDescriptorsHeader; + UINTN Index; + + BlockDescriptors1 =3D NULL; + BlockDescriptorPre =3D NULL; + BlockDescriptorsHeader =3D NULL; + + for (Index =3D 0; Index < CapsuleNum; Index++) { + // + // Allocate memory for the descriptors. + // + BlockDescriptors1 =3D AllocateZeroPool (2 * sizeof (EFI_CAPSULE_BLOCK= _DESCRIPTOR)); + if (BlockDescriptors1 =3D=3D NULL) { + DEBUG ((DEBUG_ERROR, "BuildGatherList: failed to allocate memory for= descriptors\n")); + Status =3D EFI_OUT_OF_RESOURCES; + goto ERREXIT; + } else { + DEBUG ((DEBUG_INFO, "BuildGatherList: creating capsule descriptors a= t 0x%X\n", (UINTN) BlockDescriptors1)); + } + + // + // Record descirptor header + // + if (Index =3D=3D 0) { + BlockDescriptorsHeader =3D BlockDescriptors1; + } + + if (BlockDescriptorPre !=3D NULL) { + BlockDescriptorPre->Union.ContinuationPointer =3D (UINTN) BlockDescr= iptors1; + BlockDescriptorPre->Length =3D 0; + } + + BlockDescriptors1->Union.DataBlock =3D (UINTN) CapsuleBuffer[Index]; + BlockDescriptors1->Length =3D CapsuleSize[Index]; + + BlockDescriptorPre =3D BlockDescriptors1 + 1; + BlockDescriptors1 =3D NULL; + } + + // + // Null-terminate. + // + if (BlockDescriptorPre !=3D NULL) { + BlockDescriptorPre->Union.ContinuationPointer =3D (UINTN)NULL; + BlockDescriptorPre->Length =3D 0; + *BlockDescriptors =3D BlockDescriptorsHeader; + } + + return EFI_SUCCESS; + +ERREXIT: + if (BlockDescriptors1 !=3D NULL) { + FreePool (BlockDescriptors1); + } + + return Status; +} + +/** + This routine is called to check if CapsuleOnDisk flag in OsIndications V= ariable + is enabled. + + @retval TRUE Flag is enabled + @retval FALSE Flag is not enabled + +**/ +BOOLEAN +EFIAPI +CoDCheckCapsuleOnDiskFlag( + VOID + ) +{ + EFI_STATUS Status; + UINT64 OsIndication; + UINTN DataSize; + + // + // Check File Capsule Delivery Supported Flag in OsIndication variable + // + OsIndication =3D 0; + DataSize =3D sizeof(UINT64); + Status =3D gRT->GetVariable ( + EFI_OS_INDICATIONS_VARIABLE_NAME, + &gEfiGlobalVariableGuid, + NULL, + &DataSize, + &OsIndication + ); + if (!EFI_ERROR(Status) && + (OsIndication & EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED) = !=3D 0) { + return TRUE; + } + + return FALSE; +} + + +/** + This routine is called to clear CapsuleOnDisk flags including OsIndicati= ons and BootNext variable. + + @retval EFI_SUCCESS All Capsule On Disk flags are cleared + +**/ +EFI_STATUS +EFIAPI +CoDClearCapsuleOnDiskFlag( + VOID + ) +{ + EFI_STATUS Status; + UINT64 OsIndication; + UINTN DataSize; + + // + // Reset File Capsule Delivery Supported Flag in OsIndication variable + // + OsIndication =3D 0; + DataSize =3D sizeof(UINT64); + Status =3D gRT->GetVariable ( + EFI_OS_INDICATIONS_VARIABLE_NAME, + &gEfiGlobalVariableGuid, + NULL, + &DataSize, + &OsIndication + ); + if (EFI_ERROR(Status) || + (OsIndication & EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED) = =3D=3D 0) { + return Status; + } + + OsIndication &=3D ~((UINT64)EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUP= PORTED); + Status =3D gRT->SetVariable ( + EFI_OS_INDICATIONS_VARIABLE_NAME, + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_A= CCESS | EFI_VARIABLE_NON_VOLATILE, + sizeof(UINT64), + &OsIndication + ); + ASSERT(!EFI_ERROR(Status)); + + // + // Delete BootNext variable. Capsule Process may reset system, so can't = rely on Bds to clear this variable + // + Status =3D gRT->SetVariable ( + EFI_BOOT_NEXT_VARIABLE_NAME, + &gEfiGlobalVariableGuid, + 0, + 0, + NULL + ); + ASSERT (Status =3D=3D EFI_SUCCESS || Status =3D=3D EFI_NOT_FOUND); + + return EFI_SUCCESS; +} + +/** + This routine is called to clear Capsule On Disk Relocation flag + The flag is the total size of capsules being relocated. It is saved + in CapsuleOnDisk Relocation Info varible in form of UINT64 + + @param[out] CapsuleRelocInfo The value of "CapsuleRelocInfo" variable + + @retval EFI_SUCCESS Capsule Relocation flag is cleared + +**/ +EFI_STATUS +CoDCheckCapsuleRelocationInfo( + OUT BOOLEAN *CapsuleRelocInfo + ) +{ + EFI_STATUS Status; + UINTN DataSize; + + DataSize =3D sizeof(BOOLEAN); + + Status=3D gRT->GetVariable ( + COD_RELOCATION_INFO_VAR_NAME, + &gEfiCapsuleVendorGuid, + NULL, + &DataSize, + CapsuleRelocInfo + ); + + if (DataSize !=3D sizeof(BOOLEAN)) { + return EFI_INVALID_PARAMETER; + } + + return Status; +} + +/** + This routine is called to clear CapsuleOnDisk Relocation Info variable. + Total Capsule On Disk length is recorded in this variable + + @retval EFI_SUCCESS Capsule On Disk flags are cleared + +**/ +EFI_STATUS +CoDClearCapsuleRelocationInfo( + VOID + ) +{ + return gRT->SetVariable ( + COD_RELOCATION_INFO_VAR_NAME, + &gEfiCapsuleVendorGuid, + 0, + 0, + NULL + ); +} + +/** + Relocate Capsule on Disk from EFI system partition to a platform-specifi= c NV storage device + with BlockIo protocol. Relocation device path, identified by PcdCodReloc= ationDevPath, must + be a full device path. + Device enumeration like USB costs time, user can input MaxRetry to tell = function to retry. + Function will stall 100ms between each retry. + + Side Effects: + Content corruption. Block IO write directly touches low level write. O= rignal partitions, file systems + of the relocation device will be corrupted. + + @param[in] MaxRetry Max Connection Retry. Stall 100ms bet= ween each connection try to ensure + devices like USB can get enumerated. + + @retval EFI_SUCCESS Capsule on Disk images are sucessfully relocated t= o the platform-specific device. + +**/ +EFI_STATUS +EFIAPI +RelocateCapsuleToDisk( + UINTN MaxRetry + ) +{ + EFI_STATUS Status; + UINTN CapsuleOnDiskNum; + UINTN Index; + UINTN DataSize; + UINT64 TotalImageSize; + UINT64 TotalImageNameSize; + IMAGE_INFO *CapsuleOnDiskBuf; + EFI_HANDLE Handle; + EFI_HANDLE TempHandle; + EFI_HANDLE *HandleBuffer; + UINTN NumberOfHandles; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + UINT8 *CapsuleDataBuf; + UINT8 *CapsulePtr; + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Fs; + EFI_FILE_HANDLE RootDir; + EFI_FILE_HANDLE TempCodFile; + UINT64 TempCodFileSize; + EFI_DEVICE_PATH *TempDevicePath; + BOOLEAN RelocationInfo; + UINT16 LoadOptionNumber; + EFI_CAPSULE_HEADER FileNameCapsuleHeader; + + RootDir =3D NULL; + TempCodFile =3D NULL; + HandleBuffer =3D NULL; + CapsuleDataBuf =3D NULL; + CapsuleOnDiskBuf =3D NULL; + NumberOfHandles =3D 0; + + DEBUG ((DEBUG_INFO, "CapsuleOnDisk RelocateCapsule Enter\n")); + + // + // 1. Load all Capsule On Disks in to memory + // + Status =3D GetAllCapsuleOnDisk(MaxRetry, &CapsuleOnDiskBuf, &CapsuleOnDi= skNum, &Handle, &LoadOptionNumber); + if (EFI_ERROR(Status) || CapsuleOnDiskNum =3D=3D 0) { + DEBUG ((DEBUG_INFO, "RelocateCapsule: GetAllCapsuleOnDisk Status - 0x%= x\n", Status)); + return EFI_NOT_FOUND; + } + + // + // 2. Connect platform special dev path or Use EFI System Partition as r= elocation device + // + if (PcdGetSize(PcdCodRelocationDevPath) > sizeof(EFI_DEVICE_PATH_PROTOCO= L)) { + Status =3D EfiBootManagerConnectDevicePath ((EFI_DEVICE_PATH *)PcdGetP= tr(PcdCodRelocationDevPath), &TempHandle); + if (EFI_ERROR(Status)) { + DEBUG ((DEBUG_ERROR, "RelocateCapsule: EfiBootManagerConnectDevicePa= th Status - 0x%x\n", Status)); + goto EXIT; + } + + // + // Connect all the child handle. Partition & FAT drivers are allowed i= n this case + // + gBS->ConnectController (TempHandle, NULL, NULL, TRUE); + Status =3D gBS->LocateHandleBuffer( + ByProtocol, + &gEfiSimpleFileSystemProtocolGuid, + NULL, + &NumberOfHandles, + &HandleBuffer + ); + if (EFI_ERROR(Status)) { + DEBUG ((DEBUG_ERROR, "RelocateCapsule: LocateHandleBuffer Status - 0= x%x\n", Status)); + goto EXIT; + } + + // + // Find first Simple File System Handle which can match PcdCodRelocati= onDevPath + // + for (Index =3D 0; Index < NumberOfHandles; Index++) { + Status =3D gBS->HandleProtocol(HandleBuffer[Index], &gEfiDevicePathP= rotocolGuid, (VOID **)&TempDevicePath); + if (EFI_ERROR(Status)) { + continue; + } + + DataSize =3D GetDevicePathSize((EFI_DEVICE_PATH *)PcdGetPtr(PcdCodRe= locationDevPath)) - sizeof(EFI_DEVICE_PATH); + if (0 =3D=3D CompareMem((EFI_DEVICE_PATH *)PcdGetPtr(PcdCodRelocatio= nDevPath), TempDevicePath, DataSize)) { + Handle =3D HandleBuffer[Index]; + break; + } + } + + FreePool(HandleBuffer); + + if (Index =3D=3D NumberOfHandles) { + DEBUG ((DEBUG_ERROR, "RelocateCapsule: No simple file system protoco= l found.\n")); + Status =3D EFI_NOT_FOUND; + } + } + + Status =3D gBS->HandleProtocol(Handle, &gEfiBlockIoProtocolGuid, (VOID *= *)&BlockIo); + if (EFI_ERROR(Status) || BlockIo->Media->ReadOnly) { + DEBUG((DEBUG_ERROR, "Fail to find Capsule on Disk relocation BlockIo d= evice or device is ReadOnly!\n")); + return Status; + } + + Status =3D gBS->HandleProtocol(Handle, &gEfiSimpleFileSystemProtocolGuid= , (VOID **)&Fs); + if (EFI_ERROR(Status)) { + return Status; + } + + // + // Check if device used to relocate Capsule On Disk is big enough + // + TotalImageSize =3D 0; + TotalImageNameSize =3D 0; + for (Index =3D 0; Index < CapsuleOnDiskNum; Index++) { + // + // Overflow check + // + if (MAX_ADDRESS - (UINTN)TotalImageSize <=3D CapsuleOnDiskBuf[Index].F= ileInfo->FileSize) { + return EFI_INVALID_PARAMETER; + } + + if (MAX_ADDRESS - (UINTN)TotalImageNameSize <=3D StrSize(CapsuleOnDisk= Buf[Index].FileInfo->FileName)) { + return EFI_INVALID_PARAMETER; + } + + TotalImageSize +=3D CapsuleOnDiskBuf[Index].FileInfo->FileSize; + TotalImageNameSize +=3D StrSize(CapsuleOnDiskBuf[Index].FileInfo->File= Name); + DEBUG((DEBUG_INFO, "RelocateCapsule: %x Size %x\n",CapsuleOnDiskBuf[In= dex].FileInfo->FileName, CapsuleOnDiskBuf[Index].FileInfo->FileSize)); + } + + DEBUG((DEBUG_INFO, "RelocateCapsule: TotalImageSize %x\n", TotalImageSiz= e)); + DEBUG((DEBUG_INFO, "RelocateCapsule: TotalImageNameSize %x\n", TotalImag= eNameSize)); + + if (MAX_ADDRESS - (UINTN)TotalImageNameSize <=3D sizeof(UINT64) * 2 || + MAX_ADDRESS - (UINTN)TotalImageSize <=3D (UINTN)TotalImageNameSize += sizeof(UINT64) * 2) { + return EFI_INVALID_PARAMETER; + } + + TempCodFileSize =3D sizeof(UINT64) + TotalImageSize + sizeof(EFI_CAPSULE= _HEADER) + TotalImageNameSize; + + // + // Check if CapsuleTotalSize. There could be reminder, so use LastBlock = number directly + // + if (DivU64x32(TempCodFileSize, BlockIo->Media->BlockSize) > BlockIo->Med= ia->LastBlock) { + DEBUG((DEBUG_ERROR, "RelocateCapsule: Relocation device isn't big enou= gh to hold all Capsule on Disk!\n")); + DEBUG((DEBUG_ERROR, "TotalImageSize =3D %x\n", TotalImageSize)); + DEBUG((DEBUG_ERROR, "TotalImageNameSize =3D %x\n", TotalImageNameSize)= ); + DEBUG((DEBUG_ERROR, "RelocationDev BlockSize =3D %x LastBlock =3D %x\n= ", BlockIo->Media->BlockSize, BlockIo->Media->LastBlock)); + Status =3D EFI_OUT_OF_RESOURCES; + goto EXIT; + } + + CapsuleDataBuf =3D AllocatePool((UINTN) TempCodFileSize); + if (CapsuleDataBuf =3D=3D NULL) { + Status =3D EFI_OUT_OF_RESOURCES; + goto EXIT; + } + + // + // First UINT64 reserved for total image size, including capsule name ca= psule. + // + *(UINT64 *) CapsuleDataBuf =3D TotalImageSize + sizeof(EFI_CAPSULE_HEADE= R) + TotalImageNameSize; + + // + // Line up all the Capsule on Disk and write to relocation disk at one t= ime. It could save some time in disk write + // + for (Index =3D 0, CapsulePtr =3D CapsuleDataBuf + sizeof(UINT64); Index = < CapsuleOnDiskNum; Index++) { + CopyMem(CapsulePtr, CapsuleOnDiskBuf[Index].ImageAddress, (UINTN) Caps= uleOnDiskBuf[Index].FileInfo->FileSize); + CapsulePtr +=3D CapsuleOnDiskBuf[Index].FileInfo->FileSize; + } + + // + // Line the capsule header for capsule name capsule. + // + CopyGuid(&FileNameCapsuleHeader.CapsuleGuid, &gEdkiiCapsuleOnDiskNameGui= d); + FileNameCapsuleHeader.CapsuleImageSize =3D (UINT32) TotalImageNameSize += sizeof(EFI_CAPSULE_HEADER); + FileNameCapsuleHeader.Flags =3D CAPSULE_FLAGS_PERSIST_ACROSS_= RESET; + FileNameCapsuleHeader.HeaderSize =3D sizeof(EFI_CAPSULE_HEADER); + CopyMem(CapsulePtr, &FileNameCapsuleHeader, FileNameCapsuleHeader.Header= Size); + CapsulePtr +=3D FileNameCapsuleHeader.HeaderSize; + + // + // Line up all the Capsule file names. + // + for (Index =3D 0; Index < CapsuleOnDiskNum; Index++) { + CopyMem(CapsulePtr, CapsuleOnDiskBuf[Index].FileInfo->FileName, StrSiz= e(CapsuleOnDiskBuf[Index].FileInfo->FileName)); + CapsulePtr +=3D StrSize(CapsuleOnDiskBuf[Index].FileInfo->FileName); + } + + // + // 5. Flash all Capsules on Disk to TempCoD.tmp under RootDir + // + Status =3D Fs->OpenVolume(Fs, &RootDir); + if (EFI_ERROR(Status)) { + DEBUG((DEBUG_ERROR, "RelocateCapsule: OpenVolume error. %x\n", Status)= ); + goto EXIT; + } + + Status =3D RootDir->Open( + RootDir, + &TempCodFile, + (CHAR16 *)PcdGetPtr(PcdCoDRelocationFileName), + EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE, + 0 + ); + if (!EFI_ERROR(Status)) { + // + // Error handling code to prevent malicious code to hold this file to = block capsule on disk + // + TempCodFile->Delete(TempCodFile); + } + Status =3D RootDir->Open( + RootDir, + &TempCodFile, + (CHAR16 *)PcdGetPtr(PcdCoDRelocationFileName), + EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_= MODE_CREATE, + 0 + ); + if (EFI_ERROR(Status)) { + DEBUG((DEBUG_ERROR, "RelocateCapsule: Open TemCoD.tmp error. %x\n", St= atus)); + goto EXIT; + } + + // + // Always write at the begining of TempCap file + // + DataSize =3D (UINTN) TempCodFileSize; + Status =3D TempCodFile->Write( + TempCodFile, + &DataSize, + CapsuleDataBuf + ); + if (EFI_ERROR(Status)) { + DEBUG((DEBUG_ERROR, "RelocateCapsule: Write TemCoD.tmp error. %x\n", S= tatus)); + goto EXIT; + } + + if (DataSize !=3D TempCodFileSize) { + Status =3D EFI_DEVICE_ERROR; + goto EXIT; + } + + // + // Save Capsule On Disk relocation info to "CodRelocationInfo" Var + // It is used in next reboot by TCB + // + RelocationInfo =3D TRUE; + Status =3D gRT->SetVariable( + COD_RELOCATION_INFO_VAR_NAME, + &gEfiCapsuleVendorGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_AC= CESS, + sizeof (BOOLEAN), + &RelocationInfo + ); + // + // Save the LoadOptionNumber of the boot option, where the capsule is re= located, + // into "CodRelocationLoadOption" var. It is used in next reboot after c= apsule is + // updated out of TCB to remove the TempCoDFile. + // + Status =3D gRT->SetVariable( + COD_RELOCATION_LOAD_OPTION_VAR_NAME, + &gEfiCapsuleVendorGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_AC= CESS, + sizeof (UINT16), + &LoadOptionNumber + ); + +EXIT: + + if (CapsuleDataBuf !=3D NULL) { + FreePool(CapsuleDataBuf); + } + + if (CapsuleOnDiskBuf !=3D NULL) { + // + // Free resources allocated by CodLibGetAllCapsuleOnDisk + // + for (Index =3D 0; Index < CapsuleOnDiskNum; Index++ ) { + FreePool(CapsuleOnDiskBuf[Index].ImageAddress); + FreePool(CapsuleOnDiskBuf[Index].FileInfo); + } + FreePool(CapsuleOnDiskBuf); + } + + if (TempCodFile !=3D NULL) { + if (EFI_ERROR(Status)) { + TempCodFile->Delete (TempCodFile); + } else { + TempCodFile->Close (TempCodFile); + } + } + + if (RootDir !=3D NULL) { + RootDir->Close (RootDir); + } + + return Status; +} + +/** + For the platforms that support Capsule In Ram, reuse the Capsule In Ram = to deliver capsule. + Relocate Capsule On Disk to memory and call UpdateCapsule(). + Device enumeration like USB costs time, user can input MaxRetry to tell = function to retry. + Function will stall 100ms between each retry. + + @param[in] MaxRetry Max Connection Retry. Stall 100ms bet= ween each connection try to ensure + devices like USB can get enumerated. + + @retval EFI_SUCCESS Deliver capsule through Capsule In Ram successfull= y. + +**/ +EFI_STATUS +EFIAPI +RelocateCapsuleToRam ( + UINTN MaxRetry + ) +{ + EFI_STATUS Status; + UINTN CapsuleOnDiskNum; + IMAGE_INFO *CapsuleOnDiskBuf; + EFI_HANDLE Handle; + EFI_CAPSULE_BLOCK_DESCRIPTOR *BlockDescriptors; + VOID **CapsuleBuffer; + UINTN *CapsuleSize; + EFI_CAPSULE_HEADER *FileNameCapsule; + UINTN Index; + UINT8 *StringBuf; + UINTN StringSize; + UINTN TotalStringSize; + + CapsuleOnDiskBuf =3D NULL; + BlockDescriptors =3D NULL; + CapsuleBuffer =3D NULL; + CapsuleSize =3D NULL; + FileNameCapsule =3D NULL; + TotalStringSize =3D 0; + + // + // 1. Load all Capsule On Disks into memory + // + Status =3D GetAllCapsuleOnDisk (MaxRetry, &CapsuleOnDiskBuf, &CapsuleOnD= iskNum, &Handle, NULL); + if (EFI_ERROR (Status) || CapsuleOnDiskNum =3D=3D 0) { + DEBUG ((DEBUG_ERROR, "GetAllCapsuleOnDisk Status - 0x%x\n", Status)); + return EFI_NOT_FOUND; + } + + // + // 2. Add a capsule for Capsule file name strings + // + CapsuleBuffer =3D AllocateZeroPool ((CapsuleOnDiskNum + 1) * sizeof (VOI= D *)); + if (CapsuleBuffer =3D=3D NULL) { + DEBUG ((DEBUG_ERROR, "Fail to allocate memory for capsules.\n")); + return EFI_OUT_OF_RESOURCES; + } + + CapsuleSize =3D AllocateZeroPool ((CapsuleOnDiskNum + 1) * sizeof (UINTN= )); + if (CapsuleSize =3D=3D NULL) { + DEBUG ((DEBUG_ERROR, "Fail to allocate memory for capsules.\n")); + return EFI_OUT_OF_RESOURCES; + } + + for (Index =3D 0; Index < CapsuleOnDiskNum; Index++) { + CapsuleBuffer[Index] =3D (VOID *)(UINTN) CapsuleOnDiskBuf[Index].Image= Address; + CapsuleSize[Index] =3D (UINTN) CapsuleOnDiskBuf[Index].FileInfo->FileS= ize; + TotalStringSize +=3D StrSize (CapsuleOnDiskBuf[Index].FileInfo->FileNa= me); + } + + FileNameCapsule =3D AllocateZeroPool (sizeof (EFI_CAPSULE_HEADER) + Tota= lStringSize); + if (FileNameCapsule =3D=3D NULL) { + DEBUG ((DEBUG_ERROR, "Fail to allocate memory for name capsule.\n")); + return EFI_OUT_OF_RESOURCES; + } + + FileNameCapsule->CapsuleImageSize =3D (UINT32) (sizeof (EFI_CAPSULE_HEAD= ER) + TotalStringSize); + FileNameCapsule->Flags =3D CAPSULE_FLAGS_PERSIST_ACROSS_RESET; + FileNameCapsule->HeaderSize =3D sizeof (EFI_CAPSULE_HEADER); + CopyGuid (&(FileNameCapsule->CapsuleGuid), &gEdkiiCapsuleOnDiskNameGuid); + + StringBuf =3D (UINT8 *)FileNameCapsule + FileNameCapsule->HeaderSize; + for (Index =3D 0; Index < CapsuleOnDiskNum; Index ++) { + StringSize =3D StrSize (CapsuleOnDiskBuf[Index].FileInfo->FileName); + CopyMem (StringBuf, CapsuleOnDiskBuf[Index].FileInfo->FileName, String= Size); + StringBuf +=3D StringSize; + } + + CapsuleBuffer[CapsuleOnDiskNum] =3D FileNameCapsule; + CapsuleSize[CapsuleOnDiskNum] =3D TotalStringSize + sizeof (EFI_CAPSULE_= HEADER); + + // + // 3. Build Gather list for the capsules + // + Status =3D BuildGatherList (CapsuleBuffer, CapsuleSize, CapsuleOnDiskNum= + 1, &BlockDescriptors); + if (EFI_ERROR (Status) || BlockDescriptors =3D=3D NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // 4. Call UpdateCapsule() service + // + Status =3D gRT->UpdateCapsule((EFI_CAPSULE_HEADER **) CapsuleBuffer, Cap= suleOnDiskNum + 1, (UINTN) BlockDescriptors); + + return Status; +} + +/** + Relocate Capsule on Disk from EFI system partition. + + Two solution to deliver Capsule On Disk: + Solution A: If PcdCapsuleInRamSupport is enabled, relocate Capsule On Di= sk to memory and call UpdateCapsule(). + Solution B: If PcdCapsuleInRamSupport is disabled, relocate Capsule On D= isk to a platform-specific NV storage + device with BlockIo protocol. + + Device enumeration like USB costs time, user can input MaxRetry to tell = function to retry. + Function will stall 100ms between each retry. + + Side Effects: + Capsule Delivery Supported Flag in OsIndication variable and BootNext = variable will be cleared. + Solution B: Content corruption. Block IO write directly touches low le= vel write. Orignal partitions, file + systems of the relocation device will be corrupted. + + @param[in] MaxRetry Max Connection Retry. Stall 100ms bet= ween each connection try to ensure + devices like USB can get enumerated. + + @retval EFI_SUCCESS Capsule on Disk images are sucessfully relocated. + +**/ +EFI_STATUS +EFIAPI +CoDRelocateCapsule( + UINTN MaxRetry + ) +{ + if (!PcdGetBool (PcdCapsuleOnDiskSupport)) { + return EFI_UNSUPPORTED; + } + + // + // Clear CapsuleOnDisk Flag firstly. + // + CoDClearCapsuleOnDiskFlag (); + + // + // If Capsule In Ram is supported, delivery capsules through memory + // + if (PcdGetBool (PcdCapsuleInRamSupport)) { + DEBUG ((DEBUG_INFO, "Capsule In Ram is supported, call gRT->UpdateCaps= ule().\n")); + return RelocateCapsuleToRam (MaxRetry); + } else { + DEBUG ((DEBUG_INFO, "Reallcoate all Capsule on Disks to %s in RootDir.= \n", (CHAR16 *)PcdGetPtr(PcdCoDRelocationFileName))); + return RelocateCapsuleToDisk (MaxRetry); + } +} + +/** + Remove the temp file from the root of EFI System Partition. + Device enumeration like USB costs time, user can input MaxRetry to tell = function to retry. + Function will stall 100ms between each retry. + + @param[in] MaxRetry Max Connection Retry. Stall 100ms bet= ween each connection try to ensure + devices like USB can get enumerated. + + @retval EFI_SUCCESS Remove the temp file successfully. + +**/ +EFI_STATUS +EFIAPI +CoDRemoveTempFile ( + UINTN MaxRetry + ) +{ + EFI_STATUS Status; + UINTN DataSize; + UINT16 *LoadOptionNumber; + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Fs; + EFI_HANDLE FsHandle; + EFI_FILE_HANDLE RootDir; + EFI_FILE_HANDLE TempCodFile; + + RootDir =3D NULL; + TempCodFile =3D NULL; + + LoadOptionNumber =3D AllocatePool (sizeof(UINT16)); + DataSize =3D sizeof(UINT16); + + // + // Check if capsule files are relocated + // + Status =3D gRT->GetVariable ( + COD_RELOCATION_LOAD_OPTION_VAR_NAME, + &gEfiCapsuleVendorGuid, + NULL, + &DataSize, + (VOID *)LoadOptionNumber + ); + if (EFI_ERROR(Status) || DataSize !=3D sizeof(UINT16)) { + return Status; + } + + // + // Get the EFI file system from the boot option where the capsules are r= elocated + // + Status =3D GetEfiSysPartitionFromActiveBootOption(MaxRetry, &LoadOptionN= umber, &FsHandle); + if (EFI_ERROR(Status)) { + return Status; + } + + Status =3D gBS->HandleProtocol(FsHandle, &gEfiSimpleFileSystemProtocolGu= id, (VOID **)&Fs); + if (EFI_ERROR(Status)) { + return Status; + } + + Status =3D Fs->OpenVolume(Fs, &RootDir); + if (EFI_ERROR(Status)) { + return Status; + } + + // + // Delete the TempCoDFile + // + Status =3D RootDir->Open( + RootDir, + &TempCodFile, + (CHAR16 *)PcdGetPtr(PcdCoDRelocationFileName), + EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE, + 0 + ); + if (!EFI_ERROR(Status)) { + TempCodFile->Delete(TempCodFile); + } + + if (RootDir !=3D NULL) { + RootDir->Close(RootDir); + } + + // + // Clear "CoDRelocationLoadOption" variable + // + Status =3D gRT->SetVariable ( + COD_RELOCATION_LOAD_OPTION_VAR_NAME, + &gEfiCapsuleVendorGuid, + 0, + 0, + NULL + ); + + return EFI_SUCCESS; +} diff --git a/MdeModulePkg/Library/DxeCapsuleLibFmp/CapsuleOnDisk.h b/MdeMod= ulePkg/Library/DxeCapsuleLibFmp/CapsuleOnDisk.h new file mode 100644 index 0000000000..064dc791b8 --- /dev/null +++ b/MdeModulePkg/Library/DxeCapsuleLibFmp/CapsuleOnDisk.h @@ -0,0 +1,63 @@ +/** @file + Defines several datastructures used by Capsule On Disk feature. + They are mainly used for FAT files. + + Copyright (c) 2019, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _CAPSULES_ON_DISK_H_ +#define _CAPSULES_ON_DISK_H_ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +// +// This data structure is the part of FILE_INFO_ENTRY +// +#define FILE_INFO_SIGNATURE SIGNATURE_32 ('F', 'L', 'I', 'F') + +// +// LoadOptionNumber of the boot option where the capsules is relocated. +// +#define COD_RELOCATION_LOAD_OPTION_VAR_NAME L"CodRelocationLoadOption" + +typedef struct { + UINTN Signature; + LIST_ENTRY Link; /// Linked list members. + EFI_FILE_INFO *FileInfo; /// Pointer to the FileInfo stru= ct for this file or NULL. + CHAR16 *FileNameFirstPart; /// Text to the left of right-mo= st period in the file name. String is capitialized + CHAR16 *FileNameSecondPart; /// Text to the right of right-m= ost period in the file name.String is capitialized. Maybe NULL +} FILE_INFO_ENTRY; + +// +// (20 * (6+5+2))+1) unicode characters from EFI FAT spec (doubled for byt= es) +// +#define MAX_FILE_NAME_SIZE 522 +#define MAX_FILE_NAME_LEN (MAX_FILE_NAME_SIZE / sizeof(CHAR16)) + +#define MAX_FILE_INFO_LEN (OFFSET_OF(EFI_FILE_INFO, FileName) + MAX_FIL= E_NAME_LEN) + +#endif // _CAPSULES_ON_DISK_H_ diff --git a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c b/MdeMod= ulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c index f38ab69e38..4254cc8270 100644 --- a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c +++ b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c @@ -8,11 +8,11 @@ =20 SupportCapsuleImage(), ProcessCapsuleImage(), IsValidCapsuleHeader(), ValidateFmpCapsule(), and DisplayCapsuleImage() receives untrusted input= and performs basic validation. =20 - Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.
+ Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent =20 **/ =20 #include @@ -88,11 +88,12 @@ EFI_STATUS RecordFmpCapsuleStatusVariable ( IN EFI_CAPSULE_HEADER *CapsuleHeader, IN EFI_STATUS CapsuleStatus, IN UINTN PayloadIndex, IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader, - IN EFI_DEVICE_PATH_PROTOCOL *FmpDevicePath OPTIONAL + IN EFI_DEVICE_PATH_PROTOCOL *FmpDevicePath, OPTIONAL + IN CHAR16 *CapFileName OPTIONAL ); =20 /** Function indicate the current completion progress of the firmware update. Platform may override with own specific progress function. @@ -107,10 +108,26 @@ EFI_STATUS EFIAPI UpdateImageProgress ( IN UINTN Completion ); =20 +/** + Return if this capsule is a capsule name capsule, based upon CapsuleHead= er. + + @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER + + @retval TRUE It is a capsule name capsule. + @retval FALSE It is not a capsule name capsule. +**/ +BOOLEAN +IsCapsuleNameCapsule ( + IN EFI_CAPSULE_HEADER *CapsuleHeader + ) +{ + return CompareGuid (&CapsuleHeader->CapsuleGuid, &gEdkiiCapsuleOnDiskNam= eGuid); +} + /** Return if this CapsuleGuid is a FMP capsule GUID or not. =20 @param[in] CapsuleGuid A pointer to EFI_GUID =20 @@ -1032,23 +1049,25 @@ StartFmpImage ( } =20 /** Record FMP capsule status. =20 - @param[in] Handle A FMP handle. + @param[in] Handle A FMP handle. @param[in] CapsuleHeader The capsule image header @param[in] CapsuleStatus The capsule process stauts @param[in] PayloadIndex FMP payload index @param[in] ImageHeader FMP image header + @param[in] CapFileName Capsule file name **/ VOID RecordFmpCapsuleStatus ( IN EFI_HANDLE Handle, OPTIONAL IN EFI_CAPSULE_HEADER *CapsuleHeader, IN EFI_STATUS CapsuleStatus, IN UINTN PayloadIndex, - IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader + IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader, + IN CHAR16 *CapFileName OPTIONAL ) { EFI_STATUS Status; EFI_DEVICE_PATH_PROTOCOL *FmpDevicePath; UINT32 FmpImageInfoDescriptorVer; @@ -1068,11 +1087,12 @@ RecordFmpCapsuleStatus ( RecordFmpCapsuleStatusVariable ( CapsuleHeader, CapsuleStatus, PayloadIndex, ImageHeader, - FmpDevicePath + FmpDevicePath, + CapFileName ); =20 // // Update corresponding ESRT entry LastAttemp Status // @@ -1113,10 +1133,11 @@ RecordFmpCapsuleStatus ( EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER are correct. =20 This function need support nested FMP capsule. =20 @param[in] CapsuleHeader Points to a capsule header. + @param[in] CapFileName Capsule file name. @param[out] ResetRequired Indicates whether reset is required or= not. =20 @retval EFI_SUCESS Process Capsule Image successfully. @retval EFI_UNSUPPORTED Capsule image is not supported by the firm= ware. @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted. @@ -1124,10 +1145,11 @@ RecordFmpCapsuleStatus ( @retval EFI_NOT_READY No FMP protocol to handle this FMP capsule. **/ EFI_STATUS ProcessFmpCapsuleImage ( IN EFI_CAPSULE_HEADER *CapsuleHeader, + IN CHAR16 *CapFileName, OPTIONAL OUT BOOLEAN *ResetRequired OPTIONAL ) { EFI_STATUS Status; EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *FmpCapsuleHeader; @@ -1143,11 +1165,11 @@ ProcessFmpCapsuleImage ( UINTN Index2; BOOLEAN NotReady; BOOLEAN Abort; =20 if (!IsFmpCapsuleGuid(&CapsuleHeader->CapsuleGuid)) { - return ProcessFmpCapsuleImage ((EFI_CAPSULE_HEADER *)((UINTN)CapsuleHe= ader + CapsuleHeader->HeaderSize), ResetRequired); + return ProcessFmpCapsuleImage ((EFI_CAPSULE_HEADER *)((UINTN)CapsuleHe= ader + CapsuleHeader->HeaderSize), CapFileName, ResetRequired); } =20 NotReady =3D FALSE; Abort =3D FALSE; =20 @@ -1225,11 +1247,12 @@ ProcessFmpCapsuleImage ( RecordFmpCapsuleStatus ( NULL, CapsuleHeader, EFI_NOT_READY, Index - FmpCapsuleHeader->EmbeddedDriverCount, - ImageHeader + ImageHeader, + CapFileName ); continue; } =20 for (Index2 =3D 0; Index2 < NumberOfHandles; Index2++) { @@ -1237,11 +1260,12 @@ ProcessFmpCapsuleImage ( RecordFmpCapsuleStatus ( HandleBuffer[Index2], CapsuleHeader, EFI_ABORTED, Index - FmpCapsuleHeader->EmbeddedDriverCount, - ImageHeader + ImageHeader, + CapFileName ); continue; } =20 Status =3D SetFmpImageData ( @@ -1260,11 +1284,12 @@ ProcessFmpCapsuleImage ( RecordFmpCapsuleStatus ( HandleBuffer[Index2], CapsuleHeader, Status, Index - FmpCapsuleHeader->EmbeddedDriverCount, - ImageHeader + ImageHeader, + CapFileName ); } if (HandleBuffer !=3D NULL) { FreePool(HandleBuffer); } @@ -1412,10 +1437,17 @@ SupportCapsuleImage ( // if (CompareGuid (&gWindowsUxCapsuleGuid, &CapsuleHeader->CapsuleGuid)) { return EFI_SUCCESS; } =20 + // + // Check capsule file name capsule + // + if (IsCapsuleNameCapsule(CapsuleHeader)) { + return EFI_SUCCESS; + } + if (IsFmpCapsule(CapsuleHeader)) { // // Fake capsule header is valid case in QueryCapsuleCpapbilities(). // if (CapsuleHeader->HeaderSize =3D=3D CapsuleHeader->CapsuleImageSize) { @@ -1434,10 +1466,11 @@ SupportCapsuleImage ( The firmware implements to process the capsule image. =20 Caution: This function may receive untrusted input. =20 @param[in] CapsuleHeader Points to a capsule header. + @param[in] CapFileName Capsule file name. @param[out] ResetRequired Indicates whether reset is required or= not. =20 @retval EFI_SUCESS Process Capsule Image successfully. @retval EFI_UNSUPPORTED Capsule image is not supported by the firm= ware. @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted. @@ -1445,10 +1478,11 @@ SupportCapsuleImage ( **/ EFI_STATUS EFIAPI ProcessThisCapsuleImage ( IN EFI_CAPSULE_HEADER *CapsuleHeader, + IN CHAR16 *CapFileName, OPTIONAL OUT BOOLEAN *ResetRequired OPTIONAL ) { EFI_STATUS Status; =20 @@ -1482,11 +1516,11 @@ ProcessThisCapsuleImage ( =20 // // Process EFI FMP Capsule // DEBUG((DEBUG_INFO, "ProcessFmpCapsuleImage ...\n")); - Status =3D ProcessFmpCapsuleImage(CapsuleHeader, ResetRequired); + Status =3D ProcessFmpCapsuleImage(CapsuleHeader, CapFileName, ResetReq= uired); DEBUG((DEBUG_INFO, "ProcessFmpCapsuleImage - %r\n", Status)); =20 return Status; } =20 @@ -1509,11 +1543,11 @@ EFI_STATUS EFIAPI ProcessCapsuleImage ( IN EFI_CAPSULE_HEADER *CapsuleHeader ) { - return ProcessThisCapsuleImage (CapsuleHeader, NULL); + return ProcessThisCapsuleImage (CapsuleHeader, NULL, NULL); } =20 /** Callback function executed when the EndOfDxe event group is signaled. =20 diff --git a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf b/MdeM= odulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf index 14c3d19bc3..05de4299fb 100644 --- a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf +++ b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf @@ -1,11 +1,11 @@ ## @file # Capsule library instance for DXE_DRIVER. # # Capsule library instance for DXE_DRIVER module types. # -# Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.
+# Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.
# SPDX-License-Identifier: BSD-2-Clause-Patent # ## =20 [Defines] @@ -27,10 +27,12 @@ =20 [Sources] DxeCapsuleLib.c DxeCapsuleProcessLib.c DxeCapsuleReportLib.c + CapsuleOnDisk.c + CapsuleOnDisk.h =20 [Packages] MdePkg/MdePkg.dec MdeModulePkg/MdeModulePkg.dec =20 @@ -45,10 +47,12 @@ ReportStatusCodeLib PrintLib HobLib BmpSupportLib DisplayUpdateProgressLib + FileHandleLib + UefiBootManagerLib =20 [Pcd] gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleMax = ## CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdSystemRebootAfterCapsuleProcessFlag = ## CONSUMES =20 @@ -57,23 +61,38 @@ gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeProcessCapsulesEnd = ## CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeUpdatingFirmware = ## CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeUpdateFirmwareSuccess= ## CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeUpdateFirmwareFailed = ## CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeResettingSystem = ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleInRamSupport = ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleOnDiskSupport = ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdCodRelocationDevPath = ## SOMETIMES_CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdCoDRelocationFileName = ## CONSUMES =20 [Protocols] gEsrtManagementProtocolGuid ## CONSUMES gEfiFirmwareManagementProtocolGuid ## CONSUMES gEdkiiVariableLockProtocolGuid ## SOMETIMES_CONSUMES gEdkiiFirmwareManagementProgressProtocolGuid ## SOMETIMES_CONSUMES + gEfiSimpleFileSystemProtocolGuid ## SOMETIMES_CONSUMES + gEfiBlockIoProtocolGuid ## CONSUMES + gEfiDiskIoProtocolGuid ## CONSUMES =20 [Guids] gEfiFmpCapsuleGuid ## SOMETIMES_CONSUMES ## GUID gWindowsUxCapsuleGuid ## SOMETIMES_CONSUMES ## GUID ## SOMETIMES_CONSUMES ## Variable:L"CapsuleMax" ## SOMETIMES_PRODUCES ## Variable:L"CapsuleMax" gEfiCapsuleReportGuid gEfiCapsuleVendorGuid ## SOMETIMES_CONSUMES ## Variabl= e:L"CapsuleUpdateData" gEfiEndOfDxeEventGroupGuid ## CONSUMES ## Event + gEfiPartTypeSystemPartGuid ## SOMETIMES_CONSUMES + gEfiCapsuleVendorGuid ## SOMETIMES_CONSUMES ## Variabl= e:L"CodRelocationInfo" + ## SOMETIMES_CONSUMES ## Variable:L"OsIndications" + ## SOMETIMES_PRODUCES ## Variable:L"OsIndications" + ## SOMETIMES_CONSUMES ## Variable:L"BootNext" + ## SOMETIMES_PRODUCES ## Variable:L"BootNext" + gEfiGlobalVariableGuid + gEdkiiCapsuleOnDiskNameGuid ## SOMETIMES_CONSUMES ## GUID =20 [Depex] gEfiVariableWriteArchProtocolGuid diff --git a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleProcessLib.c b= /MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleProcessLib.c index 5e2d2b87a8..e07dd7986e 100644 --- a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleProcessLib.c +++ b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleProcessLib.c @@ -7,11 +7,11 @@ buffer overflow, integer overflow. =20 ProcessCapsules(), ProcessTheseCapsules() will receive untrusted input and do basic validation. =20 - Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.
+ Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent =20 **/ =20 #include @@ -90,14 +90,45 @@ BOOLEAN IsValidCapsuleHeader ( IN EFI_CAPSULE_HEADER *CapsuleHeader, IN UINT64 CapsuleSize ); =20 +/** + Return if this capsule is a capsule name capsule, based upon CapsuleHead= er. + + @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER + + @retval TRUE It is a capsule name capsule. + @retval FALSE It is not a capsule name capsule. +**/ +BOOLEAN +IsCapsuleNameCapsule ( + IN EFI_CAPSULE_HEADER *CapsuleHeader + ); + +/** + Check the integrity of the capsule name capsule. + If the capsule is vaild, return the physical address of each capsule nam= e string. + + @param[in] CapsuleHeader Pointer to the capsule header of a capsule n= ame capsule. + @param[out] CapsuleNameNum Number of capsule name. + + @retval NULL Capsule name capsule is not valid. + @retval CapsuleNameBuf Array of capsule name physical address. + +**/ +EFI_PHYSICAL_ADDRESS * +ValidateCapsuleNameCapsuleIntegrity ( + IN EFI_CAPSULE_HEADER *CapsuleHeader, + OUT UINTN *CapsuleNameNum + ); + extern BOOLEAN mDxeCapsuleLibEndOfDxe; BOOLEAN mNeedReset =3D FALSE; =20 VOID **mCapsulePtr; +CHAR16 **mCapsuleNamePtr; EFI_STATUS *mCapsuleStatusArray; UINT32 mCapsuleTotalNumber; =20 /** The firmware implements to process the capsule image. @@ -114,10 +145,11 @@ UINT32 mCapsuleTotalNumber; **/ EFI_STATUS EFIAPI ProcessThisCapsuleImage ( IN EFI_CAPSULE_HEADER *CapsuleHeader, + IN CHAR16 *CapFileName, OPTIONAL OUT BOOLEAN *ResetRequired OPTIONAL ); =20 /** Function indicate the current completion progress of the firmware @@ -183,20 +215,36 @@ InitCapsulePtr ( VOID ) { EFI_PEI_HOB_POINTERS HobPointer; UINTN Index; + UINTN Index2; + UINTN Index3; + UINTN CapsuleNameNumber; + UINTN CapsuleNameTotalNumber; + UINTN CapsuleNameCapsuleTotalNumber; + VOID **CapsuleNameCapsulePtr; + EFI_PHYSICAL_ADDRESS *CapsuleNameAddress; + + CapsuleNameNumber =3D 0; + CapsuleNameTotalNumber =3D 0; + CapsuleNameCapsuleTotalNumber =3D 0; + CapsuleNameCapsulePtr =3D NULL; =20 // // Find all capsule images from hob // HobPointer.Raw =3D GetHobList (); while ((HobPointer.Raw =3D GetNextHob (EFI_HOB_TYPE_UEFI_CAPSULE, HobPoi= nter.Raw)) !=3D NULL) { if (!IsValidCapsuleHeader((VOID *)(UINTN)HobPointer.Capsule->BaseAddre= ss, HobPointer.Capsule->Length)) { HobPointer.Header->HobType =3D EFI_HOB_TYPE_UNUSED; // Mark this hob= as invalid } else { - mCapsuleTotalNumber++; + if (IsCapsuleNameCapsule((VOID *)(UINTN)HobPointer.Capsule->BaseAddr= ess)) { + CapsuleNameCapsuleTotalNumber++; + } else { + mCapsuleTotalNumber++; + } } HobPointer.Raw =3D GET_NEXT_HOB (HobPointer); } =20 DEBUG ((DEBUG_INFO, "mCapsuleTotalNumber - 0x%x\n", mCapsuleTotalNumber)= ); @@ -222,19 +270,76 @@ InitCapsulePtr ( mCapsuleTotalNumber =3D 0; return ; } SetMemN (mCapsuleStatusArray, sizeof (EFI_STATUS) * mCapsuleTotalNumber,= EFI_NOT_READY); =20 + if (CapsuleNameCapsuleTotalNumber !=3D 0) { + CapsuleNameCapsulePtr =3D (VOID **) AllocateZeroPool (sizeof (VOID *)= * CapsuleNameCapsuleTotalNumber); + if (CapsuleNameCapsulePtr =3D=3D NULL) { + DEBUG ((DEBUG_ERROR, "Allocate CapsuleNameCapsulePtr fail!\n")); + FreePool (mCapsulePtr); + FreePool (mCapsuleStatusArray); + mCapsulePtr =3D NULL; + mCapsuleStatusArray =3D NULL; + mCapsuleTotalNumber =3D 0; + return ; + } + } + // // Find all capsule images from hob // HobPointer.Raw =3D GetHobList (); - Index =3D 0; + Index =3D 0; + Index2 =3D 0; while ((HobPointer.Raw =3D GetNextHob (EFI_HOB_TYPE_UEFI_CAPSULE, HobPoi= nter.Raw)) !=3D NULL) { - mCapsulePtr [Index++] =3D (VOID *) (UINTN) HobPointer.Capsule->BaseAdd= ress; + if (!IsCapsuleNameCapsule ((VOID *) (UINTN) HobPointer.Capsule->BaseAd= dress)) { + mCapsulePtr [Index++] =3D (VOID *) (UINTN) HobPointer.Capsule->BaseA= ddress; + } else { + CapsuleNameCapsulePtr [Index2++] =3D (VOID *) (UINTN) HobPointer.Cap= sule->BaseAddress; + } HobPointer.Raw =3D GET_NEXT_HOB (HobPointer); } + + // + // Find Capsule On Disk Names + // + for (Index =3D 0; Index < CapsuleNameCapsuleTotalNumber; Index ++) { + CapsuleNameAddress =3D ValidateCapsuleNameCapsuleIntegrity (CapsuleNam= eCapsulePtr[Index], &CapsuleNameNumber); + if (CapsuleNameAddress !=3D NULL ) { + CapsuleNameTotalNumber +=3D CapsuleNameNumber; + } + } + + if (CapsuleNameTotalNumber =3D=3D mCapsuleTotalNumber) { + mCapsuleNamePtr =3D (CHAR16 **) AllocateZeroPool (sizeof (CHAR16 *) * = mCapsuleTotalNumber); + if (mCapsuleNamePtr =3D=3D NULL) { + DEBUG ((DEBUG_ERROR, "Allocate mCapsuleNamePtr fail!\n")); + FreePool (mCapsulePtr); + FreePool (mCapsuleStatusArray); + FreePool (CapsuleNameCapsulePtr); + mCapsulePtr =3D NULL; + mCapsuleStatusArray =3D NULL; + mCapsuleTotalNumber =3D 0; + return ; + } + + for (Index =3D 0, Index3 =3D 0; Index < CapsuleNameCapsuleTotalNumber;= Index ++) { + CapsuleNameAddress =3D ValidateCapsuleNameCapsuleIntegrity (CapsuleN= ameCapsulePtr[Index], &CapsuleNameNumber); + if (CapsuleNameAddress !=3D NULL ) { + for (Index2 =3D 0; Index2 < CapsuleNameNumber; Index2 ++) { + mCapsuleNamePtr[Index3 ++] =3D (CHAR16 *)(UINTN) CapsuleNameAddr= ess[Index2]; + } + } + } + } else { + mCapsuleNamePtr =3D NULL; + } + + if (CapsuleNameCapsulePtr !=3D NULL) { + FreePool (CapsuleNameCapsulePtr); + } } =20 /** This function returns if all capsule images are processed. =20 @@ -394,10 +499,11 @@ ProcessTheseCapsules ( EFI_CAPSULE_HEADER *CapsuleHeader; UINT32 Index; ESRT_MANAGEMENT_PROTOCOL *EsrtManagement; UINT16 EmbeddedDriverCount; BOOLEAN ResetRequired; + CHAR16 *CapsuleName; =20 REPORT_STATUS_CODE(EFI_PROGRESS_CODE, (EFI_SOFTWARE | PcdGet32(PcdStatus= CodeSubClassCapsule) | PcdGet32(PcdCapsuleStatusCodeProcessCapsulesBegin))); =20 if (FirstRound) { InitCapsulePtr (); @@ -406,10 +512,11 @@ ProcessTheseCapsules ( if (mCapsuleTotalNumber =3D=3D 0) { // // We didn't find a hob, so had no errors. // DEBUG ((DEBUG_ERROR, "We can not find capsule data in capsule update b= oot mode.\n")); + mNeedReset =3D TRUE; return EFI_SUCCESS; } =20 if (AreAllImagesProcessed ()) { return EFI_SUCCESS; @@ -428,14 +535,15 @@ ProcessTheseCapsules ( // // If Windows UX capsule exist, process it first // for (Index =3D 0; Index < mCapsuleTotalNumber; Index++) { CapsuleHeader =3D (EFI_CAPSULE_HEADER*) mCapsulePtr [Index]; + CapsuleName =3D (mCapsuleNamePtr =3D=3D NULL) ? NULL : mCapsuleNamePtr= [Index]; if (CompareGuid (&CapsuleHeader->CapsuleGuid, &gWindowsUxCapsuleGuid))= { DEBUG ((DEBUG_INFO, "ProcessThisCapsuleImage (Ux) - 0x%x\n", Capsule= Header)); DEBUG ((DEBUG_INFO, "Display logo capsule is found.\n")); - Status =3D ProcessThisCapsuleImage (CapsuleHeader, NULL); + Status =3D ProcessThisCapsuleImage (CapsuleHeader, CapsuleName, NULL= ); mCapsuleStatusArray [Index] =3D EFI_SUCCESS; DEBUG((DEBUG_INFO, "ProcessThisCapsuleImage (Ux) - %r\n", Status)); break; } } @@ -449,10 +557,11 @@ ProcessTheseCapsules ( if (mCapsuleStatusArray [Index] !=3D EFI_NOT_READY) { // already processed continue; } CapsuleHeader =3D (EFI_CAPSULE_HEADER*) mCapsulePtr [Index]; + CapsuleName =3D (mCapsuleNamePtr =3D=3D NULL) ? NULL : mCapsuleNamePtr= [Index]; if (!CompareGuid (&CapsuleHeader->CapsuleGuid, &gWindowsUxCapsuleGuid)= ) { // // Call capsule library to process capsule image. // EmbeddedDriverCount =3D 0; @@ -469,11 +578,11 @@ ProcessTheseCapsules ( } =20 if ((!FirstRound) || (EmbeddedDriverCount =3D=3D 0)) { DEBUG((DEBUG_INFO, "ProcessThisCapsuleImage - 0x%x\n", CapsuleHead= er)); ResetRequired =3D FALSE; - Status =3D ProcessThisCapsuleImage (CapsuleHeader, &ResetRequired); + Status =3D ProcessThisCapsuleImage (CapsuleHeader, CapsuleName, &R= esetRequired); mCapsuleStatusArray [Index] =3D Status; DEBUG((DEBUG_INFO, "ProcessThisCapsuleImage - %r\n", Status)); =20 if (Status !=3D EFI_NOT_READY) { if (EFI_ERROR(Status)) { diff --git a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleReportLib.c b/= MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleReportLib.c index 6ad766d65a..0ec5f20676 100644 --- a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleReportLib.c +++ b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleReportLib.c @@ -1,9 +1,9 @@ /** @file DXE capsule report related function. =20 - Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.
+ Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent =20 **/ =20 #include @@ -27,10 +27,22 @@ #include #include =20 #include =20 +/** + This routine is called to clear CapsuleOnDisk Relocation Info variable. + Total Capsule On Disk length is recorded in this variable + + @retval EFI_SUCCESS Capsule On Disk flags are cleared + +**/ +EFI_STATUS +CoDClearCapsuleRelocationInfo( + VOID + ); + /** Get current capsule last variable index. =20 @return Current capsule last variable index. @retval -1 No current capsule last variable. @@ -172,44 +184,55 @@ RecordCapsuleStatusVariable ( @param[in] CapsuleHeader The capsule image header @param[in] CapsuleStatus The capsule process stauts @param[in] PayloadIndex FMP payload index @param[in] ImageHeader FMP image header @param[in] FmpDevicePath DevicePath associated with the FMP producer + @param[in] CapFileName Capsule file name =20 @retval EFI_SUCCESS The capsule status variable is recorded. @retval EFI_OUT_OF_RESOURCES No resource to record the capsule status va= riable. **/ EFI_STATUS RecordFmpCapsuleStatusVariable ( IN EFI_CAPSULE_HEADER *CapsuleHeader, IN EFI_STATUS CapsuleStatus, IN UINTN PayloadIndex, IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader, - IN EFI_DEVICE_PATH_PROTOCOL *FmpDevicePath OPTIONAL + IN EFI_DEVICE_PATH_PROTOCOL *FmpDevicePath, OPTIONAL + IN CHAR16 *CapFileName OPTIONAL ) { EFI_CAPSULE_RESULT_VARIABLE_HEADER *CapsuleResultVariableHeader; EFI_CAPSULE_RESULT_VARIABLE_FMP *CapsuleResultVariableFmp; EFI_STATUS Status; UINT8 *CapsuleResultVariable; UINTN CapsuleResultVariableSize; CHAR16 *DevicePathStr; UINTN DevicePathStrSize; + UINTN CapFileNameSize; + + DevicePathStr =3D NULL; + CapFileNameSize =3D sizeof(CHAR16); =20 - DevicePathStr =3D NULL; if (FmpDevicePath !=3D NULL) { DevicePathStr =3D ConvertDevicePathToText (FmpDevicePath, FALSE, FALSE= ); } if (DevicePathStr !=3D NULL) { DevicePathStrSize =3D StrSize(DevicePathStr); } else { DevicePathStrSize =3D sizeof(CHAR16); } + + if (CapFileName !=3D NULL) { + CapFileNameSize =3D StrSize(CapFileName); + } + // - // Allocate zero CHAR16 for CapsuleFileName. + // Allocate room for CapsuleFileName. // - CapsuleResultVariableSize =3D sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER)= + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP) + sizeof(CHAR16) + DevicePathStr= Size; + CapsuleResultVariableSize =3D sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER)= + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP) + CapFileNameSize + DevicePathSt= rSize; + CapsuleResultVariable =3D AllocateZeroPool (CapsuleResultVariableSiz= e); if (CapsuleResultVariable =3D=3D NULL) { return EFI_OUT_OF_RESOURCES; } CapsuleResultVariableHeader =3D (VOID *)CapsuleResultVariable; @@ -223,12 +246,17 @@ RecordFmpCapsuleStatusVariable ( CapsuleResultVariableFmp =3D (VOID *)(CapsuleResultVariable + sizeof(EFI= _CAPSULE_RESULT_VARIABLE_HEADER)); CapsuleResultVariableFmp->Version =3D 0x1; CapsuleResultVariableFmp->PayloadIndex =3D (UINT8)PayloadIndex; CapsuleResultVariableFmp->UpdateImageIndex =3D ImageHeader->UpdateImageI= ndex; CopyGuid (&CapsuleResultVariableFmp->UpdateImageTypeId, &ImageHeader->Up= dateImageTypeId); + + if (CapFileName !=3D NULL) { + CopyMem((UINT8 *)CapsuleResultVariableFmp + sizeof(EFI_CAPSULE_RESULT_= VARIABLE_FMP), CapFileName, CapFileNameSize); + } + if (DevicePathStr !=3D NULL) { - CopyMem ((UINT8 *)CapsuleResultVariableFmp + sizeof(EFI_CAPSULE_RESULT= _VARIABLE_FMP) + sizeof(CHAR16), DevicePathStr, DevicePathStrSize); + CopyMem ((UINT8 *)CapsuleResultVariableFmp + sizeof(EFI_CAPSULE_RESULT= _VARIABLE_FMP) + CapFileNameSize, DevicePathStr, DevicePathStrSize); FreePool (DevicePathStr); DevicePathStr =3D NULL; } =20 Status =3D EFI_SUCCESS; @@ -398,10 +426,35 @@ InitCapsuleUpdateVariable ( } Index++; } } =20 +/** + Initialize capsule relocation info variable. +**/ +VOID +InitCapsuleRelocationInfo ( + VOID + ) +{ + EFI_STATUS Status; + EDKII_VARIABLE_LOCK_PROTOCOL *VariableLock; + + CoDClearCapsuleRelocationInfo(); + + // + // Unlock Capsule On Disk relocation Info variable only when Capsule On = Disk flag is enabled + // + if (!CoDCheckCapsuleOnDiskFlag()) { + Status =3D gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL,= (VOID **) &VariableLock); + if (!EFI_ERROR (Status)) { + Status =3D VariableLock->RequestToLock (VariableLock, COD_RELOCATION= _INFO_VAR_NAME, &gEfiCapsuleVendorGuid); + ASSERT_EFI_ERROR (Status); + } + } +} + /** Initialize capsule related variables. **/ VOID InitCapsuleVariable ( @@ -409,10 +462,12 @@ InitCapsuleVariable ( ) { InitCapsuleUpdateVariable(); InitCapsuleMaxVariable(); InitCapsuleLastVariable(); + InitCapsuleRelocationInfo(); + // // No need to clear L"Capsule####", because OS/APP should refer L"Capsul= eLast" // to check status and delete them. // } diff --git a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf= b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf index 2c93e68700..bf56f4623f 100644 --- a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf +++ b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf @@ -1,11 +1,11 @@ ## @file # Capsule library instance for DXE_RUNTIME_DRIVER. # # Capsule library instance for DXE_RUNTIME_DRIVER module types. # -# Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.
+# Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.
# SPDX-License-Identifier: BSD-2-Clause-Patent # ## =20 [Defines] @@ -66,8 +66,9 @@ gEfiCapsuleReportGuid gEfiCapsuleVendorGuid ## SOMETIMES_CONSUMES ## Variabl= e:L"CapsuleUpdateData" gEfiEndOfDxeEventGroupGuid ## CONSUMES ## Event gEfiEventReadyToBootGuid ## CONSUMES ## Event gEfiEventVirtualAddressChangeGuid ## CONSUMES ## Event + gEdkiiCapsuleOnDiskNameGuid ## SOMETIMES_CONSUMES ## GUID =20 [Depex] gEfiVariableWriteArchProtocolGuid diff --git a/MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.c b/M= deModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.c index 06a1abe16b..39e37cffcd 100644 --- a/MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.c +++ b/MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.c @@ -1,9 +1,9 @@ /** @file Null Dxe Capsule Library instance does nothing and returns unsupport sta= tus. =20 -Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent =20 **/ #include #include @@ -83,5 +83,88 @@ ProcessCapsules ( ) { return EFI_UNSUPPORTED; } =20 + +/** + This routine is called to check if CapsuleOnDisk flag in OsIndications V= ariable + is enabled. + + @retval TRUE Flag is enabled + @retval FALSE Flag is not enabled + +**/ +BOOLEAN +EFIAPI +CoDCheckCapsuleOnDiskFlag( + VOID + ) +{ + return FALSE; +} + +/** + This routine is called to clear CapsuleOnDisk flags including OsIndicati= ons and BootNext variable. + + @retval EFI_SUCCESS All Capsule On Disk flags are cleared + +**/ +EFI_STATUS +EFIAPI +CoDClearCapsuleOnDiskFlag( + VOID + ) +{ + return EFI_UNSUPPORTED; +} + +/** + Relocate Capsule on Disk from EFI system partition. + + Two solution to deliver Capsule On Disk: + Solution A: If PcdCapsuleInRamSupport is enabled, relocate Capsule On Di= sk to memory and call UpdateCapsule(). + Solution B: If PcdCapsuleInRamSupport is disabled, relocate Capsule On D= isk to a platform-specific NV storage + device with BlockIo protocol. + + Device enumeration like USB costs time, user can input MaxRetry to tell = function to retry. + Function will stall 100ms between each retry. + + Side Effects: + Capsule Delivery Supported Flag in OsIndication variable and BootNext = variable will be cleared. + Solution B: Content corruption. Block IO write directly touches low le= vel write. Orignal partitions, file + systems of the relocation device will be corrupted. + + @param[in] MaxRetry Max Connection Retry. Stall 100ms bet= ween each connection try to ensure + devices like USB can get enumerated. + + @retval EFI_SUCCESS Capsule on Disk images are sucessfully relocated. + +**/ +EFI_STATUS +EFIAPI +CoDRelocateCapsule( + UINTN MaxRetry + ) +{ + return EFI_UNSUPPORTED; +} + +/** + Remove the temp file from the root of EFI System Partition. + Device enumeration like USB costs time, user can input MaxRetry to tell = function to retry. + Function will stall 100ms between each retry. + + @param[in] MaxRetry Max Connection Retry. Stall 100ms bet= ween each connection try to ensure + devices like USB can get enumerated. + + @retval EFI_SUCCESS Remove the temp file successfully. + +**/ +EFI_STATUS +EFIAPI +CoDRemoveTempFile ( + UINTN MaxRetry + ) +{ + return EFI_UNSUPPORTED; +} --=20 2.16.2.windows.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#41954): https://edk2.groups.io/g/devel/message/41954 Mute This Topic: https://groups.io/mt/31938582/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-