From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by mx.groups.io with SMTP id smtpd.web11.1012.1571275499310767129 for ; Wed, 16 Oct 2019 18:24:59 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@intel.onmicrosoft.com header.s=selector2-intel-onmicrosoft-com header.b=iDHql5zK; spf=pass (domain: intel.com, ip: 134.134.136.20, mailfrom: michael.a.kubacki@intel.com) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by orsmga101.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 16 Oct 2019 18:24:58 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.67,305,1566889200"; d="scan'208";a="195009441" Received: from orsmsx105.amr.corp.intel.com ([10.22.225.132]) by fmsmga008.fm.intel.com with ESMTP; 16 Oct 2019 18:24:57 -0700 Received: from orsmsx607.amr.corp.intel.com (10.22.229.20) by ORSMSX105.amr.corp.intel.com (10.22.225.132) with Microsoft SMTP Server (TLS) id 14.3.439.0; Wed, 16 Oct 2019 18:24:57 -0700 Received: from orsmsx607.amr.corp.intel.com (10.22.229.20) by ORSMSX607.amr.corp.intel.com (10.22.229.20) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.1713.5; Wed, 16 Oct 2019 18:24:56 -0700 Received: from ORSEDG001.ED.cps.intel.com (10.7.248.4) by orsmsx607.amr.corp.intel.com (10.22.229.20) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) id 15.1.1713.5 via Frontend Transport; Wed, 16 Oct 2019 18:24:56 -0700 Received: from NAM05-DM3-obe.outbound.protection.outlook.com (104.47.49.57) by edgegateway.intel.com (134.134.137.100) with Microsoft SMTP Server (TLS) id 14.3.439.0; Wed, 16 Oct 2019 18:24:56 -0700 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=iUaCAgEQywEL/ywrnLSXwLeyKWtV6BM/OoQdqISwxhtoBQJeG6fS3Qth+kgwTmk+1QdqGLjz3tUWMmbYNf1Xzcp8WVhuBV7wwCfwqAy/GDTy21dG97yZDQCYIrLfR2ePjRZH1pY+5BVwPKfKZAZkc130ylyuU6pZe8SqN1k2fHdDExV3x2ib3fJZUnxlJo5BouAu7CwbauaTiUSoo/mhIngjFkn45uB3XMw/7Wx1QpBX8uWT89DKQrQsaBkegScdLru4QmU8EDXN2DXT41QouYstXHkA0YY59IhBwuT2PJ/HEkBXP0tlT8ldd+2R3sJHbdiOyIzcouhZjrtGF35JpQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=fx8YODb3W+vbi96DhQDiqrw7DYU2GhyJXKHlhLkFhCA=; b=GgjAr4sCNy+9MaB7C0i8GW0w+AdqPjiz1p66Ycbr7r1wc9vO2x+ZeNg4/RTFmEQOTWupPLDfS+ZcZpY/Ni+AhBIJwV3P4+U0yQvBCTSr1GRvavRmNctoYDOsy1c8M/x0ifR82zsJ+mN17TykK9TXg3EHuwzzYcvkVguBVoU6+XClS+mIkgYwUFdYFNCREFbLefaQNpQiVHXa0W3iAmhlxCb7Cb5VBgFirJS7J8i6g2klW4lfsCR89h7t4OgrBNphi0jp1irBHwxP0dvwNyTeR5ZiSqKAjAu/wkDy1AghxgqMElSgtOgAbzRgkeGqbSFFJxWEZKIXdSP+WODdCMxVew== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=intel.com; dmarc=pass action=none header.from=intel.com; dkim=pass header.d=intel.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=intel.onmicrosoft.com; s=selector2-intel-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=fx8YODb3W+vbi96DhQDiqrw7DYU2GhyJXKHlhLkFhCA=; b=iDHql5zKDOmDkCw/Uz0UqQeOrOnRAlJ3kuPY5l0udHqntni9ySLqdlc8BZvoEHepHwwfbMoEOJ/CDGNKkT8xK914x5oCD7FSoiqHETOqk+47IAA2GUNDtFOR7pLkRWiquMMdMakZezNHU1g2APifdlXBBD+plcxr2MQ2PhERFQA= Received: from DM6PR11MB3834.namprd11.prod.outlook.com (20.179.17.87) by DM6PR11MB3964.namprd11.prod.outlook.com (20.176.124.157) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.2347.18; Thu, 17 Oct 2019 01:24:53 +0000 Received: from DM6PR11MB3834.namprd11.prod.outlook.com ([fe80::21f7:6d8d:919b:d755]) by DM6PR11MB3834.namprd11.prod.outlook.com ([fe80::21f7:6d8d:919b:d755%6]) with mapi id 15.20.2347.023; Thu, 17 Oct 2019 01:24:53 +0000 From: "Kubacki, Michael A" To: "Wang, Jian J" , "devel@edk2.groups.io" CC: "Bi, Dandan" , Ard Biesheuvel , "Dong, Eric" , Laszlo Ersek , "Gao, Liming" , "Kinney, Michael D" , "Ni, Ray" , "Wu, Hao A" , "Yao, Jiewen" Subject: Re: [edk2-devel] [PATCH V4 07/10] MdeModulePkg/Variable: Add RT GetVariable() cache support Thread-Topic: [edk2-devel] [PATCH V4 07/10] MdeModulePkg/Variable: Add RT GetVariable() cache support Thread-Index: AQHVg+6UKIRU3LGAyESXDfF4IudU/KdeArTA Date: Thu, 17 Oct 2019 01:24:53 +0000 Message-ID: References: <20191014233001.33024-1-michael.a.kubacki@intel.com> <20191014233001.33024-8-michael.a.kubacki@intel.com> <15CE0DB2DE3EB613.1607@groups.io> In-Reply-To: Accept-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: dlp-product: dlpe-windows x-ctpclassification: CTP_NT x-titus-metadata-40: eyJDYXRlZ29yeUxhYmVscyI6IiIsIk1ldGFkYXRhIjp7Im5zIjoiaHR0cDpcL1wvd3d3LnRpdHVzLmNvbVwvbnNcL0ludGVsMyIsImlkIjoiNDYzMGE3YTctMjNmYS00MzgzLTg3MTAtZDI4YjkwOGEyZTIwIiwicHJvcHMiOlt7Im4iOiJDVFBDbGFzc2lmaWNhdGlvbiIsInZhbHMiOlt7InZhbHVlIjoiQ1RQX05UIn1dfV19LCJTdWJqZWN0TGFiZWxzIjpbXSwiVE1DVmVyc2lvbiI6IjE3LjEwLjE4MDQuNDkiLCJUcnVzdGVkTGFiZWxIYXNoIjoiMUs4amtBU3BVNVhQQzhTQUtoTElMVFJxSUY5RUx5elNLam01SElCaGk0d05NVG9ac2FCMmczNzB6RjMxZFpqbSJ9 dlp-reaction: no-action dlp-version: 11.2.0.6 authentication-results: spf=none (sender IP is ) smtp.mailfrom=michael.a.kubacki@intel.com; x-originating-ip: [134.134.136.217] x-ms-publictraffictype: Email x-ms-office365-filtering-correlation-id: 8191af69-7f36-48b4-fcc7-08d752a0d03a x-ms-traffictypediagnostic: DM6PR11MB3964: x-ms-exchange-purlcount: 3 x-ld-processed: 46c98d88-e344-4ed4-8496-4ed7712e255d,ExtAddr x-ms-exchange-transport-forked: True x-microsoft-antispam-prvs: x-ms-oob-tlc-oobclassifiers: OLM:10000; x-forefront-prvs: 01930B2BA8 x-forefront-antispam-report: SFV:NSPM;SFS:(10019020)(366004)(346002)(39850400004)(396003)(376002)(136003)(189003)(199004)(52314003)(13464003)(256004)(3846002)(14444005)(6116002)(7696005)(99286004)(110136005)(54906003)(5660300002)(14454004)(6506007)(316002)(76176011)(30864003)(6436002)(966005)(6246003)(53546011)(478600001)(229853002)(2501003)(25786009)(9686003)(107886003)(4326008)(52536014)(6306002)(55016002)(71190400001)(66946007)(66476007)(446003)(86362001)(66446008)(76116006)(11346002)(81156014)(71200400001)(74316002)(66066001)(486006)(102836004)(26005)(2906002)(33656002)(81166006)(8676002)(186003)(476003)(8936002)(66556008)(305945005)(64756008)(7736002)(567084001)(579004)(559001)(569006);DIR:OUT;SFP:1102;SCL:1;SRVR:DM6PR11MB3964;H:DM6PR11MB3834.namprd11.prod.outlook.com;FPR:;SPF:None;LANG:en;PTR:InfoNoRecords;MX:1;A:1; x-ms-exchange-senderadcheck: 1 x-microsoft-antispam: BCL:0; x-microsoft-antispam-message-info: i90UAMdiiDElgbK1fiouZxdEc4eCKC4bkuSBSi9/9mRPLTS9IGKNZNBcWr1N5TUQ1SZiqfvYWV3nBNAk/fmUOz0iXJLq9UylFR7gHbjjOt39b6s9bfGKROg7Qd7lVEeN/Cp8OMjiEeFf1hb71dPf7JJ3PilLzykwa/0sQuXgrSxnoxpD54ff3duJiI04ondKClWQlrLctYk1EvC+qo/QhUK+u4kqayZRf+dILtbwngdX7t5aijqmvKkkc6fu6vLOW3qiC8WzWnwbZxoA9Ldh2Y5wkK7wBYZMl75jUmt8e8OBEgINEWjxZZC/tstccEp1uArGIavK/X5hUy+SQbsf7Z9be92r/h/GmmIChVxIMMzb9KSDhqoqLjruRYnOpcJA95uPrcrTKHPVOG70o4QVcNRWTbwkAYhzNdldX8Y3jX0KlaEF3MGQj6lsolJ0lrEP82/CcOTPvuW70n+9ztYymQ== MIME-Version: 1.0 X-MS-Exchange-CrossTenant-Network-Message-Id: 8191af69-7f36-48b4-fcc7-08d752a0d03a X-MS-Exchange-CrossTenant-originalarrivaltime: 17 Oct 2019 01:24:53.5877 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 46c98d88-e344-4ed4-8496-4ed7712e255d X-MS-Exchange-CrossTenant-mailboxtype: HOSTED X-MS-Exchange-CrossTenant-userprincipalname: OQZKZ+tyPA8zdh76lGN4PHHvQzDOQKDiTGXhelIrX1bWFxIVx2RgctMxng0sr45K+BazYRLTpLcgS27vzKmyYQPe+YZLTzuNqyuEQ8FukVU= X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM6PR11MB3964 Return-Path: michael.a.kubacki@intel.com X-OriginatorOrg: intel.com Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable The "Data" parameter is marked OPTIONAL in FindVariableInRuntimeCache () fo= r essentially the same reason it is labeled OPTIONAL in the GetVariable () API in the UEFI specification= . Callers expect that they can pass a NULL as an actual parameter for Data and get back the size of a buffer nee= ded for the given variable name and GUID. I addressed the implementation of AtRuntime () in VariableSmmRuntimeDxe.c = alongside EfiAtRuntime () calls in the file in another V4 reply. The conclusion is AtRuntime () is called by = functions in VariableParsing.c which due to its generic nature is linked against VariableSmmRuntimeDxe and Variable= Smm. VariableSmm cannot call EfiAtRuntime (). There's various ways to twist this but most I've consider= ed are really cosmetic tradeoffs. Jian, you left it open to me as to whether the buffers should be freed in = SmmVariableReady () in VariableSmmRuntimeDxe.c in the failure case. During implementation, I initially thought the platfo= rm would roughly "earmark" a fixed amount of overall EfiRuntimeServicesData memory (typical value + some threshold) for= S4 memory map consistency so it's not consuming memory not already accounted for. I was also not aware of any ha= rmful effects to not freeing the buffers, but I did mean to reconsider this in the future. I still don't have enough= justification to form a strong opinion either way, so please let me know if you think it's necessary. Thanks, Michael > -----Original Message----- > From: Wang, Jian J > Sent: Tuesday, October 15, 2019 11:55 PM > To: devel@edk2.groups.io; Wang, Jian J ; Kubacki, > Michael A > Cc: Bi, Dandan ; Ard Biesheuvel > ; Dong, Eric ; Laszlo Er= sek > ; Gao, Liming ; Kinney, Michael > D ; Ni, Ray ; Wu, Hao A > ; Yao, Jiewen > Subject: RE: [edk2-devel] [PATCH V4 07/10] MdeModulePkg/Variable: Add > RT GetVariable() cache support >=20 > The comments are for VariableRuntimeCache.c only. >=20 > Regards, > Jian >=20 > > -----Original Message----- > > From: devel@edk2.groups.io On Behalf Of Wang, > Jian > > J > > Sent: Wednesday, October 16, 2019 2:46 PM > > To: Kubacki, Michael A ; > devel@edk2.groups.io > > Cc: Bi, Dandan ; Ard Biesheuvel > > ; Dong, Eric ; Laszlo > Ersek > > ; Gao, Liming ; Kinney, > Michael D > > ; Ni, Ray ; Wu, Hao A > > ; Yao, Jiewen > > Subject: Re: [edk2-devel] [PATCH V4 07/10] MdeModulePkg/Variable: Add > RT > > GetVariable() cache support > > > > Hi Michael, > > > > Please see my inline comments. > > > > > -----Original Message----- > > > From: Kubacki, Michael A > > > Sent: Tuesday, October 15, 2019 7:30 AM > > > To: devel@edk2.groups.io > > > Cc: Bi, Dandan ; Ard Biesheuvel > > > ; Dong, Eric ; Laszl= o > Ersek > > > ; Gao, Liming ; Kinney, > Michael > > D > > > ; Ni, Ray ; Wang, Jian= J > > > ; Wu, Hao A ; Yao, > Jiewen > > > > > > Subject: [PATCH V4 07/10] MdeModulePkg/Variable: Add RT > GetVariable() > > cache > > > support > > > > > > REF:https://bugzilla.tianocore.org/show_bug.cgi?id=3D2220 > > > > > > This change reduces SMIs for GetVariable () by maintaining a > > > UEFI variable cache in Runtime DXE in addition to the pre- > > > existing cache in SMRAM. When the Runtime Service GetVariable() > > > is invoked, a Runtime DXE cache is used instead of triggering an > > > SMI to VariableSmm. This can improve overall system performance > > > by servicing variable read requests without rendezvousing all > > > cores into SMM. > > > > > > The runtime cache can be disabled with by setting the FeaturePCD > > > gEfiMdeModulePkgTokenSpaceGuid.PcdEnableVariableRuntimeCache > > > to FALSE. If the PCD is set to FALSE, the runtime cache will not be > > > used and an SMI will be triggered for Runtime Service > > > GetVariable () and GetNextVariableName () invocations. > > > > > > The following are important points regarding the behavior of the > > > variable drivers when the variable runtime cache is enabled. > > > > > > 1. All of the non-volatile storage contents are loaded into the > > > cache upon driver load. This one time load operation from storage > > > is preferred as opposed to building the cache on demand. An on- > > > demand cache would require a fallback SMI to load data into the > > > cache as variables are requested. > > > > > > 2. SetVariable () requests will continue to always trigger an SMI. > > > This occurs regardless of whether the variable is volatile or > > > non-volatile. > > > > > > 3. Both volatile and non-volatile variables are cached in a runtime > > > buffer. As is the case in the current EDK II variable driver, the= y > > > continue to be cached in separate buffers. > > > > > > 4. The cache in Runtime DXE and SMM are intended to be exact copies > > > of one another. All SMM variable accesses only return data from t= he > > > SMM cache. The runtime caches are only updated after the variable= I/O > > > operation is successful in SMM. The runtime caches are only updat= ed > > > from SMM. > > > > > > 5. Synchronization mechanisms are in place to ensure the runtime cac= he > > > content integrity with the SMM cache. These may result in updates= to > > > runtime cache that are the same in content but different in offse= t and > > > size from updates to the SMM cache. > > > > > > When using SMM variables with runtime cache enabled, two caches will > now > > > be present. > > > 1. "Runtime Cache" - Maintained in VariableSmmRuntimeDxe. Used to > service > > > Runtime Services GetVariable () and GetNextVariableName () caller= s. > > > 2. "SMM Cache" - Maintained in VariableSmm to service SMM > GetVariable () > > > and GetNextVariableName () callers. > > > a. This cache is retained so SMM modules do not operate on data > outside > > > SMRAM. > > > > > > Because a race condition can occur if an SMI occurs during the execu= tion > > > of runtime code reading from the runtime cache, a runtime cache read > lock > > > is introduced that explicitly moves pending updates from SMM to the > runtime > > > cache if an SMM update occurs while the runtime cache is locked. Not= e > that > > > it is not expected a Runtime services call will interrupt SMM proces= sing > > > since all CPU cores rendezvous in SMM. > > > > > > It is possible to view UEFI variable read and write statistics by se= tting > > > the gEfiMdeModulePkgTokenSpaceGuid.PcdVariableCollectStatistics > > FeaturePcd > > > to TRUE and using the VariableInfo UEFI application in MdeModulePkg = to > > dump > > > variable statistics to the console. By doing so, a user can view the= number > > > of GetVariable () hits from the Runtime DXE variable driver (Runtime > Cache > > > hits) and the SMM variable driver (SMM Cache hits). SMM Cache hits f= or > > > GetVariable () will occur when SMM modules invoke GetVariable (). > > > > > > Cc: Dandan Bi > > > Cc: Ard Biesheuvel > > > Cc: Eric Dong > > > Cc: Laszlo Ersek > > > Cc: Liming Gao > > > Cc: Michael D Kinney > > > Cc: Ray Ni > > > Cc: Jian J Wang > > > Cc: Hao A Wu > > > Cc: Jiewen Yao > > > Signed-off-by: Michael Kubacki > > > --- > > > MdeModulePkg/MdeModulePkg.dec = | 12 + > > > > MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf > | > > 2 > > > + > > > MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf > | 2 + > > > > MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.i > nf > > | > > > 20 +- > > > > MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf > | > > > 2 + > > > MdeModulePkg/Include/Guid/SmmVariableCommon.h = | 29 > +- > > > MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.h = | 32 > +- > > > > MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeCache.h > | > > > 51 ++ > > > MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c = | 50 > +- > > > > MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeCache.c > | > > > 153 ++++++ > > > MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c = | > 114 > > > ++++- > > > > MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe. > c > > | > > > 512 +++++++++++++++++++- > > > 12 files changed, 938 insertions(+), 41 deletions(-) > > > > > > diff --git a/MdeModulePkg/MdeModulePkg.dec > > > b/MdeModulePkg/MdeModulePkg.dec > > > index 59b8c21713..a00835cb84 100644 > > > --- a/MdeModulePkg/MdeModulePkg.dec > > > +++ b/MdeModulePkg/MdeModulePkg.dec > > > @@ -641,6 +641,18 @@ > > > # @Prompt Enable Device Path From Text support. > > > > > > > > > gEfiMdeModulePkgTokenSpaceGuid.PcdDevicePathSupportDevicePathFrom > Text > > > |TRUE|BOOLEAN|0x00010038 > > > > > > + ## Indicates if the UEFI variable runtime cache should be enabled= . > > > + # This setting only applies if SMM variables are enabled. When > enabled, all > > > variable > > > + # data for Runtime Service GetVariable () and GetNextVariableNam= e > () calls > > is > > > retrieved > > > + # from a runtime data buffer referred to as the "runtime cache".= An > SMI is > > not > > > triggered > > > + # at all for these requests. Variables writes still trigger an S= MI. This can > > > greatly > > > + # reduce overall system SMM usage as most boots tend to issue fa= r > more > > > variable reads > > > + # than writes.

> > > + # TRUE - The UEFI variable runtime cache is enabled.
> > > + # FALSE - The UEFI variable runtime cache is disabled.
> > > + # @Prompt Enable the UEFI variable runtime cache. > > > + > > > > > > gEfiMdeModulePkgTokenSpaceGuid.PcdEnableVariableRuntimeCache|FALS > E|B > > > OOLEAN|0x00010039 > > > + > > > ## Indicates if the statistics about variable usage will be colle= cted. This > > > information is > > > # stored as a vendor configuration table into the EFI system tab= le. > > > # Set this PCD to TRUE to use VariableInfo application in > > > MdeModulePkg\Application directory to get > > > diff --git > > > > a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf > > > > b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf > > > index 08a5490787..ceea5d1ff9 100644 > > > --- > a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf > > > +++ > > > b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf > > > @@ -40,6 +40,8 @@ > > > VariableNonVolatile.h > > > VariableParsing.c > > > VariableParsing.h > > > + VariableRuntimeCache.c > > > + VariableRuntimeCache.h > > > PrivilegePolymorphic.h > > > Measurement.c > > > TcgMorLockDxe.c > > > diff --git > a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf > > > b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf > > > index 6dc2721b81..bc3033588d 100644 > > > --- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf > > > +++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf > > > @@ -49,6 +49,8 @@ > > > VariableNonVolatile.h > > > VariableParsing.c > > > VariableParsing.h > > > + VariableRuntimeCache.c > > > + VariableRuntimeCache.h > > > VarCheck.c > > > Variable.h > > > PrivilegePolymorphic.h > > > diff --git > > > > > > a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDx > e.inf > > > > > > b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDx > e.inf > > > index 14894e6f13..b5a779a233 100644 > > > --- > > > > > > a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDx > e.inf > > > +++ > > > > > > b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDx > e.inf > > > @@ -13,7 +13,7 @@ > > > # may not be modified without authorization. If platform fails to = protect > > these > > > resources, > > > # the authentication service provided in this driver will be broke= n, and > the > > > behavior is undefined. > > > # > > > -# Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved= .
> > > +# Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved= .
> > > # SPDX-License-Identifier: BSD-2-Clause-Patent > > > # > > > ## > > > @@ -39,6 +39,10 @@ > > > VariableSmmRuntimeDxe.c > > > PrivilegePolymorphic.h > > > Measurement.c > > > + VariableParsing.c > > > + VariableParsing.h > > > + VariableRuntimeCache.c > > > + VariableRuntimeCache.h > > > > > > [Packages] > > > MdePkg/MdePkg.dec > > > @@ -65,7 +69,21 @@ > > > gEdkiiVariableLockProtocolGuid ## PRODUCES > > > gEdkiiVarCheckProtocolGuid ## PRODUCES > > > > > > +[FeaturePcd] > > > + gEfiMdeModulePkgTokenSpaceGuid.PcdEnableVariableRuntimeCache > > > ## CONSUMES > > > + gEfiMdeModulePkgTokenSpaceGuid.PcdVariableCollectStatistics > ## > > > CONSUMES > > > + > > > [Guids] > > > + ## PRODUCES ## GUID # Signature of Variable store hea= der > > > + ## CONSUMES ## GUID # Signature of Variable store hea= der > > > + ## SOMETIMES_PRODUCES ## SystemTable > > > + gEfiAuthenticatedVariableGuid > > > + > > > + ## PRODUCES ## GUID # Signature of Variable store hea= der > > > + ## CONSUMES ## GUID # Signature of Variable store hea= der > > > + ## SOMETIMES_PRODUCES ## SystemTable > > > + gEfiVariableGuid > > > + > > > gEfiEventVirtualAddressChangeGuid ## CONSUMES ## Even= t > > > gEfiEventExitBootServicesGuid ## CONSUMES ## Even= t > > > ## CONSUMES ## GUID # Locate protocol > > > diff --git > > > > a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.i > nf > > > > b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm. > inf > > > index f8a3742959..6e17f6cdf5 100644 > > > --- > > > > a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.i > nf > > > +++ > > > > b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm. > inf > > > @@ -49,6 +49,8 @@ > > > VariableNonVolatile.h > > > VariableParsing.c > > > VariableParsing.h > > > + VariableRuntimeCache.c > > > + VariableRuntimeCache.h > > > VarCheck.c > > > Variable.h > > > PrivilegePolymorphic.h > > > diff --git a/MdeModulePkg/Include/Guid/SmmVariableCommon.h > > > b/MdeModulePkg/Include/Guid/SmmVariableCommon.h > > > index c527a59891..ceef44dfd2 100644 > > > --- a/MdeModulePkg/Include/Guid/SmmVariableCommon.h > > > +++ b/MdeModulePkg/Include/Guid/SmmVariableCommon.h > > > @@ -1,7 +1,7 @@ > > > /** @file > > > The file defined some common structures used for communicating > between > > > SMM variable module and SMM variable wrapper module. > > > > > > -Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<= BR> > > > +Copyright (c) 2011 - 2019, Intel Corporation. All rights reserved.<= BR> > > > SPDX-License-Identifier: BSD-2-Clause-Patent > > > > > > **/ > > > @@ -9,6 +9,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent > > > #ifndef _SMM_VARIABLE_COMMON_H_ > > > #define _SMM_VARIABLE_COMMON_H_ > > > > > > +#include > > > #include > > > > > > #define EFI_SMM_VARIABLE_WRITE_GUID \ > > > @@ -66,6 +67,16 @@ typedef struct { > > > #define > SMM_VARIABLE_FUNCTION_VAR_CHECK_VARIABLE_PROPERTY_GET > > > 10 > > > > > > #define SMM_VARIABLE_FUNCTION_GET_PAYLOAD_SIZE 11 > > > +// > > > +// The payload for this function is > > > > SMM_VARIABLE_COMMUNICATE_RUNTIME_VARIABLE_CACHE_CONTEXT > > > +// > > > +#define > > > > SMM_VARIABLE_FUNCTION_INIT_RUNTIME_VARIABLE_CACHE_CONTEXT > > 12 > > > + > > > +#define SMM_VARIABLE_FUNCTION_SYNC_RUNTIME_CACHE > 13 > > > +// > > > +// The payload for this function is > > > SMM_VARIABLE_COMMUNICATE_GET_RUNTIME_CACHE_INFO > > > +// > > > +#define SMM_VARIABLE_FUNCTION_GET_RUNTIME_CACHE_INFO > > 14 > > > > > > /// > > > /// Size of SMM communicate header, without including the payload. > > > @@ -120,4 +131,20 @@ typedef struct { > > > UINTN VariablePayloadSize; > > > } SMM_VARIABLE_COMMUNICATE_GET_PAYLOAD_SIZE; > > > > > > +typedef struct { > > > + BOOLEAN *ReadLock; > > > + BOOLEAN *PendingUpdate; > > > + BOOLEAN *HobFlushComplete; > > > + VARIABLE_STORE_HEADER *RuntimeHobCache; > > > + VARIABLE_STORE_HEADER *RuntimeNvCache; > > > + VARIABLE_STORE_HEADER *RuntimeVolatileCache; > > > +} > SMM_VARIABLE_COMMUNICATE_RUNTIME_VARIABLE_CACHE_CONTEXT; > > > + > > > +typedef struct { > > > + UINTN TotalHobStorageSize; > > > + UINTN TotalNvStorageSize; > > > + UINTN TotalVolatileStorageSize; > > > + BOOLEAN AuthenticatedVariableUsage; > > > +} SMM_VARIABLE_COMMUNICATE_GET_RUNTIME_CACHE_INFO; > > > + > > > #endif // _SMM_VARIABLE_COMMON_H_ > > > diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.h > > > b/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.h > > > index fb574b2e32..0b2bb6ae66 100644 > > > --- a/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.h > > > +++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.h > > > @@ -64,6 +64,21 @@ typedef enum { > > > VariableStoreTypeMax > > > } VARIABLE_STORE_TYPE; > > > > > > +typedef struct { > > > + UINT32 PendingUpdateOffset; > > > + UINT32 PendingUpdateLength; > > > + VARIABLE_STORE_HEADER *Store; > > > +} VARIABLE_RUNTIME_CACHE; > > > + > > > +typedef struct { > > > + BOOLEAN *ReadLock; > > > + BOOLEAN *PendingUpdate; > > > + BOOLEAN *HobFlushComplete; > > > + VARIABLE_RUNTIME_CACHE VariableRuntimeHobCache; > > > + VARIABLE_RUNTIME_CACHE VariableRuntimeNvCache; > > > + VARIABLE_RUNTIME_CACHE VariableRuntimeVolatileCache; > > > +} VARIABLE_RUNTIME_CACHE_CONTEXT; > > > + > > > typedef struct { > > > VARIABLE_HEADER *CurrPtr; > > > // > > > @@ -79,14 +94,15 @@ typedef struct { > > > } VARIABLE_POINTER_TRACK; > > > > > > typedef struct { > > > - EFI_PHYSICAL_ADDRESS HobVariableBase; > > > - EFI_PHYSICAL_ADDRESS VolatileVariableBase; > > > - EFI_PHYSICAL_ADDRESS NonVolatileVariableBase; > > > - EFI_LOCK VariableServicesLock; > > > - UINT32 ReentrantState; > > > - BOOLEAN AuthFormat; > > > - BOOLEAN AuthSupport; > > > - BOOLEAN EmuNvMode; > > > + EFI_PHYSICAL_ADDRESS HobVariableBase; > > > + EFI_PHYSICAL_ADDRESS VolatileVariableBase; > > > + EFI_PHYSICAL_ADDRESS NonVolatileVariableBase; > > > + VARIABLE_RUNTIME_CACHE_CONTEXT > VariableRuntimeCacheContext; > > > + EFI_LOCK VariableServicesLock; > > > + UINT32 ReentrantState; > > > + BOOLEAN AuthFormat; > > > + BOOLEAN AuthSupport; > > > + BOOLEAN EmuNvMode; > > > } VARIABLE_GLOBAL; > > > > > > typedef struct { > > > diff --git > > > > a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeCache.h > > > > b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeCache. > h > > > new file mode 100644 > > > index 0000000000..f9804a1d69 > > > --- /dev/null > > > +++ > > > b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeCache. > h > > > @@ -0,0 +1,51 @@ > > > +/** @file > > > + The common variable volatile store routines shared by the > DXE_RUNTIME > > > variable > > > + module and the DXE_SMM variable module. > > > + > > > +Copyright (c) 2019, Intel Corporation. All rights reserved.
> > > +SPDX-License-Identifier: BSD-2-Clause-Patent > > > + > > > +**/ > > > + > > > +#ifndef _VARIABLE_RUNTIME_CACHE_H_ > > > +#define _VARIABLE_RUNTIME_CACHE_H_ > > > + > > > +#include "Variable.h" > > > + > > > +/** > > > + Copies any pending updates to runtime variable caches. > > > + > > > + @retval EFI_UNSUPPORTED The volatile store to be updated = is not > > > initialized properly. > > > + @retval EFI_SUCCESS The volatile store was updated > successfully. > > > + > > > +**/ > > > +EFI_STATUS > > > +FlushPendingRuntimeVariableCacheUpdates ( > > > + VOID > > > + ); > > > + > > > +/** > > > + Synchronizes the runtime variable caches with all pending updates > outside > > > runtime. > > > + > > > + Ensures all conditions are met to maintain coherency for runtime = cache > > > updates. This function will attempt > > > + to write the given update (and any other pending updates) if the > ReadLock is > > > available. Otherwise, the > > > + update is added as a pending update for the given variable store = and it > will > > be > > > flushed to the runtime cache > > > + at the next opportunity the ReadLock is available. > > > + > > > + @param[in] VariableRuntimeCache Variable runtime cache structure > for the > > > runtime cache being synchronized. > > > + @param[in] Offset Offset in bytes to apply the upda= te. > > > + @param[in] Length Length of data in bytes of the up= date. > > > + > > > + @retval EFI_SUCCESS The update was added as a pending > update > > > successfully. If the variable runtime > > > + cache ReadLock was available, the= runtime cache was > > > updated successfully. > > > + @retval EFI_UNSUPPORTED The volatile store to be updated = is not > > > initialized properly. > > > + > > > +**/ > > > +EFI_STATUS > > > +SynchronizeRuntimeVariableCache ( > > > + IN VARIABLE_RUNTIME_CACHE *VariableRuntimeCache, > > > + IN UINTN Offset, > > > + IN UINTN Length > > > + ); > > > + > > > +#endif > > > diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c > > > b/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c > > > index 0bd2f22e1a..29d6aca993 100644 > > > --- a/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c > > > +++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c > > > @@ -25,6 +25,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent > > > #include "Variable.h" > > > #include "VariableNonVolatile.h" > > > #include "VariableParsing.h" > > > +#include "VariableRuntimeCache.h" > > > > > > VARIABLE_MODULE_GLOBAL *mVariableModuleGlobal; > > > > > > @@ -332,6 +333,12 @@ RecordVarErrorFlag ( > > > // Update the data in NV cache. > > > // > > > *VarErrFlag =3D TempFlag; > > > + Status =3D SynchronizeRuntimeVariableCache ( > > > + &mVariableModuleGlobal- > > > > >VariableGlobal.VariableRuntimeCacheContext.VariableRuntimeNvCache, > > > + (UINTN) VarErrFlag - (UINTN) mNvVariableCache + (= UINTN) > > > mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase, > > > + sizeof (TempFlag) > > > + ); > > > + ASSERT_EFI_ERROR (Status); > > > } > > > } > > > } > > > @@ -766,12 +773,24 @@ Reclaim ( > > > > > > Done: > > > if (IsVolatile || mVariableModuleGlobal->VariableGlobal.EmuNvMode= ) > { > > > + Status =3D SynchronizeRuntimeVariableCache ( > > > + &mVariableModuleGlobal- > > > > >VariableGlobal.VariableRuntimeCacheContext.VariableRuntimeVolatileCach > e, > > > + 0, > > > + VariableStoreHeader->Size > > > + ); > > > + ASSERT_EFI_ERROR (Status); > > > FreePool (ValidBuffer); > > > } else { > > > // > > > // For NV variable reclaim, we use mNvVariableCache as the buff= er, so > copy > > > the data back. > > > // > > > - CopyMem (mNvVariableCache, (UINT8 *)(UINTN)VariableBase, > > > VariableStoreHeader->Size); > > > + CopyMem (mNvVariableCache, (UINT8 *) (UINTN) VariableBase, > > > VariableStoreHeader->Size); > > > + Status =3D SynchronizeRuntimeVariableCache ( > > > + &mVariableModuleGlobal- > > > > >VariableGlobal.VariableRuntimeCacheContext.VariableRuntimeNvCache, > > > + 0, > > > + VariableStoreHeader->Size > > > + ); > > > + ASSERT_EFI_ERROR (Status); > > > } > > > > > > return Status; > > > @@ -1614,6 +1633,7 @@ UpdateVariable ( > > > VARIABLE_POINTER_TRACK *Variable; > > > VARIABLE_POINTER_TRACK NvVariable; > > > VARIABLE_STORE_HEADER *VariableStoreHeader; > > > + VARIABLE_RUNTIME_CACHE *VolatileCacheInstance; > > > UINT8 *BufferForMerge; > > > UINTN MergedBufSize; > > > BOOLEAN DataReady; > > > @@ -2275,6 +2295,23 @@ UpdateVariable ( > > > } > > > > > > Done: > > > + if (!EFI_ERROR (Status)) { > > > + if (Variable->Volatile) { > > > + VolatileCacheInstance =3D &(mVariableModuleGlobal- > > > > >VariableGlobal.VariableRuntimeCacheContext.VariableRuntimeVolatileCach > e > > ); > > > + } else { > > > + VolatileCacheInstance =3D &(mVariableModuleGlobal- > > > > >VariableGlobal.VariableRuntimeCacheContext.VariableRuntimeNvCache); > > > + } > > > + > > > + if (VolatileCacheInstance->Store !=3D NULL) { > > > + Status =3D SynchronizeRuntimeVariableCache ( > > > + VolatileCacheInstance, > > > + 0, > > > + VolatileCacheInstance->Store->Size > > > + ); > > > + ASSERT_EFI_ERROR (Status); > > > + } > > > + } > > > + > > > return Status; > > > } > > > > > > @@ -3200,6 +3237,14 @@ FlushHobVariableToFlash ( > > > ErrorFlag =3D TRUE; > > > } > > > } > > > + if (mVariableModuleGlobal- > > > > >VariableGlobal.VariableRuntimeCacheContext.VariableRuntimeHobCache.S > to > > r > > > e !=3D NULL) { > > > + Status =3D SynchronizeRuntimeVariableCache ( > > > + &mVariableModuleGlobal- > > > > >VariableGlobal.VariableRuntimeCacheContext.VariableRuntimeHobCache, > > > + 0, > > > + mVariableModuleGlobal- > > > > >VariableGlobal.VariableRuntimeCacheContext.VariableRuntimeHobCache.S > to > > r > > > e->Size > > > + ); > > > + ASSERT_EFI_ERROR (Status); > > > + } > > > if (ErrorFlag) { > > > // > > > // We still have HOB variable(s) not flushed in flash. > > > @@ -3210,6 +3255,9 @@ FlushHobVariableToFlash ( > > > // All HOB variables have been flushed in flash. > > > // > > > DEBUG ((EFI_D_INFO, "Variable driver: all HOB variables have = been > flushed > > > in flash.\n")); > > > + if (mVariableModuleGlobal- > > > >VariableGlobal.VariableRuntimeCacheContext.HobFlushComplete !=3D > NULL) { > > > + *(mVariableModuleGlobal- > > > >VariableGlobal.VariableRuntimeCacheContext.HobFlushComplete) =3D > TRUE; > > > + } > > > if (!AtRuntime ()) { > > > FreePool ((VOID *) VariableStoreHeader); > > > } > > > diff --git > > > > a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeCache.c > > > > b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeCache.c > > > new file mode 100644 > > > index 0000000000..bc93cc07d2 > > > --- /dev/null > > > +++ > > > b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeCache.c > > > @@ -0,0 +1,153 @@ > > > +/** @file > > > + Functions related to managing the UEFI variable runtime cache. Th= is file > > > should only include functions > > > + used by the SMM UEFI variable driver. > > > + > > > + Caution: This module requires additional review when modified. > > > + This driver will have external input - variable data. They may be= input in > SMM > > > mode. > > > + This external input must be validated carefully to avoid security= issue > like > > > + buffer overflow, integer overflow. > > > + > > > +Copyright (c) 2019, Intel Corporation. All rights reserved.
> > > +SPDX-License-Identifier: BSD-2-Clause-Patent > > > + > > > +**/ > > > + > > > +#include "VariableParsing.h" > > > +#include "VariableRuntimeCache.h" > > > + > > > +extern VARIABLE_MODULE_GLOBAL *mVariableModuleGlobal; > > > +extern VARIABLE_STORE_HEADER *mNvVariableCache; > > > + > > > +/** > > > + Copies any pending updates to runtime variable caches. > > > + > > > + @retval EFI_UNSUPPORTED The volatile store to be updated = is not > > > initialized properly. > > > + @retval EFI_SUCCESS The volatile store was updated > successfully. > > > + > > > +**/ > > > +EFI_STATUS > > > +FlushPendingRuntimeVariableCacheUpdates ( > > > + VOID > > > + ) > > > +{ > > > + VARIABLE_RUNTIME_CACHE_CONTEXT > *VariableRuntimeCacheContext; > > > + > > > + VariableRuntimeCacheContext =3D &mVariableModuleGlobal- > > > >VariableGlobal.VariableRuntimeCacheContext; > > > + > > > + if (VariableRuntimeCacheContext->VariableRuntimeNvCache.Store =3D= = =3D > NULL > > > || > > > + VariableRuntimeCacheContext- > >VariableRuntimeVolatileCache.Store =3D=3D > > > NULL || > > > + VariableRuntimeCacheContext->PendingUpdate =3D=3D NULL) { > > > + return EFI_UNSUPPORTED; > > > + } > > > + > > > + if (*(VariableRuntimeCacheContext->PendingUpdate)) { > > > + if (VariableRuntimeCacheContext->VariableRuntimeHobCache.Store > !=3D > > NULL > > > && > > > + mVariableModuleGlobal->VariableGlobal.HobVariableBase > 0) = { > > > + CopyMem ( > > > + (VOID *) ( > > > + ((UINT8 *) (UINTN) VariableRuntimeCacheContext- > > > >VariableRuntimeHobCache.Store) + > > > + VariableRuntimeCacheContext- > > > >VariableRuntimeHobCache.PendingUpdateOffset > > > + ), > > > + (VOID *) ( > > > + ((UINT8 *) (UINTN) mVariableModuleGlobal- > > > >VariableGlobal.HobVariableBase) + > > > + VariableRuntimeCacheContext- > > > >VariableRuntimeHobCache.PendingUpdateOffset > > > + ), > > > + VariableRuntimeCacheContext- > > > >VariableRuntimeHobCache.PendingUpdateLength > > > + ); > > > + VariableRuntimeCacheContext- > > > >VariableRuntimeHobCache.PendingUpdateLength =3D 0; > > > + VariableRuntimeCacheContext- > > > >VariableRuntimeHobCache.PendingUpdateOffset =3D 0; > > > + } > > > + > > > + CopyMem ( > > > + (VOID *) ( > > > + ((UINT8 *) (UINTN) VariableRuntimeCacheContext- > > > >VariableRuntimeNvCache.Store) + > > > + VariableRuntimeCacheContext- > > > >VariableRuntimeNvCache.PendingUpdateOffset > > > + ), > > > + (VOID *) ( > > > + ((UINT8 *) (UINTN) mNvVariableCache) + > > > + VariableRuntimeCacheContext- > > > >VariableRuntimeNvCache.PendingUpdateOffset > > > + ), > > > + VariableRuntimeCacheContext- > > > >VariableRuntimeNvCache.PendingUpdateLength > > > + ); > > > + VariableRuntimeCacheContext- > > > >VariableRuntimeNvCache.PendingUpdateLength =3D 0; > > > + VariableRuntimeCacheContext- > > > >VariableRuntimeNvCache.PendingUpdateOffset =3D 0; > > > + > > > + CopyMem ( > > > + (VOID *) ( > > > + ((UINT8 *) (UINTN) VariableRuntimeCacheContext- > > > >VariableRuntimeVolatileCache.Store) + > > > + VariableRuntimeCacheContext- > > > >VariableRuntimeVolatileCache.PendingUpdateOffset > > > + ), > > > + (VOID *) ( > > > + ((UINT8 *) (UINTN) mVariableModuleGlobal- > > > >VariableGlobal.VolatileVariableBase) + > > > + VariableRuntimeCacheContext- > > > >VariableRuntimeVolatileCache.PendingUpdateOffset > > > + ), > > > + VariableRuntimeCacheContext- > > > >VariableRuntimeVolatileCache.PendingUpdateLength > > > + ); > > > + VariableRuntimeCacheContext- > > > >VariableRuntimeVolatileCache.PendingUpdateLength =3D 0; > > > + VariableRuntimeCacheContext- > > > >VariableRuntimeVolatileCache.PendingUpdateOffset =3D 0; > > > + *(VariableRuntimeCacheContext->PendingUpdate) =3D FALSE; > > > + } > > > + > > > + return EFI_SUCCESS; > > > +} > > > + > > > +/** > > > + Synchronizes the runtime variable caches with all pending updates > outside > > > runtime. > > > + > > > + Ensures all conditions are met to maintain coherency for runtime = cache > > > updates. This function will attempt > > > + to write the given update (and any other pending updates) if the > ReadLock is > > > available. Otherwise, the > > > + update is added as a pending update for the given variable store = and it > will > > be > > > flushed to the runtime cache > > > + at the next opportunity the ReadLock is available. > > > + > > > + @param[in] VariableRuntimeCache Variable runtime cache structure > for the > > > runtime cache being synchronized. > > > + @param[in] Offset Offset in bytes to apply the upda= te. > > > + @param[in] Length Length of data in bytes of the up= date. > > > + > > > + @retval EFI_SUCCESS The update was added as a pending > update > > > successfully. If the variable runtime > > > + cache ReadLock was available, the= runtime cache was > > > updated successfully. > > > + @retval EFI_UNSUPPORTED The volatile store to be updated = is not > > > initialized properly. > > > + > > > +**/ > > > +EFI_STATUS > > > +SynchronizeRuntimeVariableCache ( > > > + IN VARIABLE_RUNTIME_CACHE *VariableRuntimeCache, > > > + IN UINTN Offset, > > > + IN UINTN Length > > > + ) > > > +{ > > > + if (VariableRuntimeCache =3D=3D NULL) { > > > + return EFI_INVALID_PARAMETER; > > > + } else if (VariableRuntimeCache->Store =3D=3D NULL) { > > > + // The runtime cache may not be active or allocated yet. > > > + // In either case, return EFI_SUCCESS instead of > EFI_NOT_AVAILABLE_YET. > > > + return EFI_SUCCESS; > > > + } > > > + > > > + if (mVariableModuleGlobal- > > > >VariableGlobal.VariableRuntimeCacheContext.PendingUpdate =3D=3D NUL= L > || > > > + mVariableModuleGlobal- > > > >VariableGlobal.VariableRuntimeCacheContext.ReadLock =3D=3D NULL) { > > > + return EFI_UNSUPPORTED; > > > + } > > > + > > > + if (*(mVariableModuleGlobal- > > > >VariableGlobal.VariableRuntimeCacheContext.PendingUpdate) && > > > + VariableRuntimeCache->PendingUpdateLength > 0) { > > > + VariableRuntimeCache->PendingUpdateLength =3D > > > + (UINT32) ( > > > + MAX ( > > > + (UINTN) (VariableRuntimeCache->PendingUpdateOffset + > > > VariableRuntimeCache->PendingUpdateLength), > > > + Offset + Length > > > + ) - MIN ((UINTN) VariableRuntimeCache->PendingUpdateOffset, > Offset) > > > + ); > > > + VariableRuntimeCache->PendingUpdateOffset =3D > > > + (UINT32) MIN ((UINTN) VariableRuntimeCache- > >PendingUpdateOffset, > > > Offset); > > > + } else { > > > + VariableRuntimeCache->PendingUpdateLength =3D (UINT32) Length; > > > + VariableRuntimeCache->PendingUpdateOffset =3D (UINT32) Offset; > > > + } > > > + *(mVariableModuleGlobal- > > > >VariableGlobal.VariableRuntimeCacheContext.PendingUpdate) =3D TRUE; > > > + > > > + if (*(mVariableModuleGlobal- > > > >VariableGlobal.VariableRuntimeCacheContext.ReadLock) =3D=3D FALSE) = { > > > + return FlushPendingRuntimeVariableCacheUpdates (); > > > + } > > > + > > > + return EFI_SUCCESS; > > > +} > > > diff --git > a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c > > > b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c > > > index 5e24bc4a62..45814b8996 100644 > > > --- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c > > > +++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c > > > @@ -31,6 +31,9 @@ SPDX-License-Identifier: BSD-2-Clause-Patent > > > #include > > > #include "Variable.h" > > > #include "VariableParsing.h" > > > +#include "VariableRuntimeCache.h" > > > + > > > +extern VARIABLE_STORE_HEADER *mNvVariableCa= che; > > > > > > BOOLEAN mAtRuntime = =3D FALSE; > > > UINT8 *mVariableBuff= erPayload =3D NULL; > > > @@ -451,25 +454,29 @@ SmmVariableGetStatistics ( > > > EFI_STATUS > > > EFIAPI > > > SmmVariableHandler ( > > > - IN EFI_HANDLE DispatchHandle, > > > - IN CONST VOID *RegisterContext= , > > > - IN OUT VOID *CommBuffer, > > > - IN OUT UINTN *CommBufferSize > > > + IN EFI_HANDLE DispatchH= andle, > > > + IN CONST VOID *Register= Context, > > > + IN OUT VOID *CommBuff= er, > > > + IN OUT UINTN *CommBuff= erSize > > > ) > > > { > > > - EFI_STATUS Status; > > > - SMM_VARIABLE_COMMUNICATE_HEADER > > > *SmmVariableFunctionHeader; > > > - SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE > > > *SmmVariableHeader; > > > - SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME > > > *GetNextVariableName; > > > - SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO > > > *QueryVariableInfo; > > > - SMM_VARIABLE_COMMUNICATE_GET_PAYLOAD_SIZE > *GetPayloadSize; > > > - VARIABLE_INFO_ENTRY *VariableInfo; > > > - SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE > *VariableToLock; > > > - SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY > > > *CommVariableProperty; > > > - UINTN InfoSize; > > > - UINTN NameBufferSize; > > > - UINTN CommBufferPayloa= dSize; > > > - UINTN TempCommBufferSi= ze; > > > + EFI_STATUS Status; > > > + SMM_VARIABLE_COMMUNICATE_HEADER > > > *SmmVariableFunctionHeader; > > > + SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE > > > *SmmVariableHeader; > > > + SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME > > > *GetNextVariableName; > > > + SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO > > > *QueryVariableInfo; > > > + SMM_VARIABLE_COMMUNICATE_GET_PAYLOAD_SIZE > > > *GetPayloadSize; > > > + > SMM_VARIABLE_COMMUNICATE_RUNTIME_VARIABLE_CACHE_CONTEXT > > > *RuntimeVariableCacheContext; > > > + SMM_VARIABLE_COMMUNICATE_GET_RUNTIME_CACHE_INFO > > > *GetRuntimeCacheInfo; > > > + SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE > > *VariableToLock; > > > + SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY > > > *CommVariableProperty; > > > + VARIABLE_INFO_ENTRY *Variable= Info; > > > + VARIABLE_RUNTIME_CACHE_CONTEXT > > *VariableCacheContext; > > > + VARIABLE_STORE_HEADER *Variable= Cache; > > > + UINTN InfoSize; > > > + UINTN NameBuffe= rSize; > > > + UINTN CommBuffe= rPayloadSize; > > > + UINTN TempCommB= ufferSize; > > > > > > // > > > // If input is invalid, stop processing this SMI > > > @@ -789,6 +796,79 @@ SmmVariableHandler ( > > > ); > > > CopyMem (SmmVariableFunctionHeader->Data, > mVariableBufferPayload, > > > CommBufferPayloadSize); > > > break; > > > + case > > > > SMM_VARIABLE_FUNCTION_INIT_RUNTIME_VARIABLE_CACHE_CONTEXT: > > > + if (CommBufferPayloadSize < sizeof > > > > (SMM_VARIABLE_COMMUNICATE_RUNTIME_VARIABLE_CACHE_CONTEXT) > ) { > > > + DEBUG ((DEBUG_ERROR, "InitRuntimeVariableCacheContext: SMM > > > communication buffer size invalid!\n")); > > > + } else if (mEndOfDxe) { > > > + DEBUG ((DEBUG_ERROR, "InitRuntimeVariableCacheContext: > Cannot init > > > context after end of DXE!\n")); > > > + } else { > > > + RuntimeVariableCacheContext =3D > > > > (SMM_VARIABLE_COMMUNICATE_RUNTIME_VARIABLE_CACHE_CONTEXT > *) > > > SmmVariableFunctionHeader->Data; > > > + VariableCacheContext =3D &mVariableModuleGlobal- > > > >VariableGlobal.VariableRuntimeCacheContext; > > > + > > > + ASSERT (RuntimeVariableCacheContext->RuntimeVolatileCache != = =3D > NULL); > > > + ASSERT (RuntimeVariableCacheContext->RuntimeNvCache !=3D > NULL); > > > + ASSERT (RuntimeVariableCacheContext->PendingUpdate !=3D NUL= L); > > > + ASSERT (RuntimeVariableCacheContext->ReadLock !=3D NULL); > > > + ASSERT (RuntimeVariableCacheContext->HobFlushComplete !=3D > NULL); > > > + > > > + VariableCacheContext->VariableRuntimeHobCache.Store = =3D > > > RuntimeVariableCacheContext->RuntimeHobCache; > > > + VariableCacheContext->VariableRuntimeVolatileCache.Store = =3D > > > RuntimeVariableCacheContext->RuntimeVolatileCache; > > > + VariableCacheContext->VariableRuntimeNvCache.Store = =3D > > > RuntimeVariableCacheContext->RuntimeNvCache; > > > + VariableCacheContext->PendingUpdate = =3D > > > RuntimeVariableCacheContext->PendingUpdate; > > > + VariableCacheContext->ReadLock = =3D > > > RuntimeVariableCacheContext->ReadLock; > > > + VariableCacheContext->HobFlushComplete = =3D > > > RuntimeVariableCacheContext->HobFlushComplete; > > > + > > > + // Set up the intial pending request since the RT cache nee= ds to be > in sync > > > with SMM cache > > > + if (mVariableModuleGlobal->VariableGlobal.HobVariableBase = =3D=3D 0) > { > > > + VariableCacheContext- > > >VariableRuntimeHobCache.PendingUpdateOffset > > > =3D 0; > > > + VariableCacheContext- > > > >VariableRuntimeHobCache.PendingUpdateLength =3D 0; > > > + } else { > > > + VariableCache =3D (VARIABLE_STORE_HEADER *) (UINTN) > > > mVariableModuleGlobal->VariableGlobal.HobVariableBase; > > > + VariableCacheContext- > > >VariableRuntimeHobCache.PendingUpdateOffset > > > =3D 0; > > > + VariableCacheContext- > > > >VariableRuntimeHobCache.PendingUpdateLength =3D (UINT32) ((UINTN) > > > GetEndPointer (VariableCache) - (UINTN) VariableCache); > > > + CopyGuid (&(VariableCacheContext- > >VariableRuntimeHobCache.Store- > > > >Signature), &(VariableCache->Signature)); > > > + } > > > + VariableCache =3D (VARIABLE_STORE_HEADER *) (UINTN) > > > mVariableModuleGlobal->VariableGlobal.VolatileVariableBase; > > > + VariableCacheContext- > > > >VariableRuntimeVolatileCache.PendingUpdateOffset =3D 0; > > > + VariableCacheContext- > > > >VariableRuntimeVolatileCache.PendingUpdateLength =3D (UINT32) > ((UINTN) > > > GetEndPointer (VariableCache) - (UINTN) VariableCache); > > > + CopyGuid (&(VariableCacheContext- > > >VariableRuntimeVolatileCache.Store- > > > >Signature), &(VariableCache->Signature)); > > > + > > > + VariableCache =3D (VARIABLE_STORE_HEADER *) (UINTN) > > > mNvVariableCache; > > > + VariableCacheContext- > >VariableRuntimeNvCache.PendingUpdateOffset > > =3D > > > 0; > > > + VariableCacheContext- > >VariableRuntimeNvCache.PendingUpdateLength > > =3D > > > (UINT32) ((UINTN) GetEndPointer (VariableCache) - (UINTN) > VariableCache); > > > + CopyGuid (&(VariableCacheContext- > >VariableRuntimeNvCache.Store- > > > >Signature), &(VariableCache->Signature)); > > > + > > > + *(VariableCacheContext->PendingUpdate) =3D TRUE; > > > + *(VariableCacheContext->ReadLock) =3D FALSE; > > > + *(VariableCacheContext->HobFlushComplete) =3D FALSE; > > > + } > > > + Status =3D EFI_SUCCESS; > > > + break; > > > + case SMM_VARIABLE_FUNCTION_SYNC_RUNTIME_CACHE: > > > + Status =3D FlushPendingRuntimeVariableCacheUpdates (); > > > + break; > > > + case SMM_VARIABLE_FUNCTION_GET_RUNTIME_CACHE_INFO: > > > + if (CommBufferPayloadSize < sizeof > > > (SMM_VARIABLE_COMMUNICATE_GET_RUNTIME_CACHE_INFO)) { > > > + DEBUG ((DEBUG_ERROR, "GetRuntimeCacheInfo: SMM > communication > > > buffer size invalid!\n")); > > > + return EFI_SUCCESS; > > > + } > > > + GetRuntimeCacheInfo =3D > > > (SMM_VARIABLE_COMMUNICATE_GET_RUNTIME_CACHE_INFO *) > > > SmmVariableFunctionHeader->Data; > > > + > > > + if (mVariableModuleGlobal->VariableGlobal.HobVariableBase > 0= ) { > > > + VariableCache =3D (VARIABLE_STORE_HEADER *) (UINTN) > > > mVariableModuleGlobal->VariableGlobal.HobVariableBase; > > > + GetRuntimeCacheInfo->TotalHobStorageSize =3D VariableCache- > >Size; > > > + } else { > > > + GetRuntimeCacheInfo->TotalHobStorageSize =3D 0; > > > + } > > > + > > > + VariableCache =3D (VARIABLE_STORE_HEADER *) (UINTN) > > > mVariableModuleGlobal->VariableGlobal.VolatileVariableBase; > > > + GetRuntimeCacheInfo->TotalVolatileStorageSize =3D VariableCac= he- > >Size; > > > + VariableCache =3D (VARIABLE_STORE_HEADER *) (UINTN) > > mNvVariableCache; > > > + GetRuntimeCacheInfo->TotalNvStorageSize =3D (UINTN) > VariableCache- > > >Size; > > > + GetRuntimeCacheInfo->AuthenticatedVariableUsage =3D > > > mVariableModuleGlobal->VariableGlobal.AuthFormat; > > > + > > > + Status =3D EFI_SUCCESS; > > > + break; > > > > > > default: > > > Status =3D EFI_UNSUPPORTED; > > > diff --git > > > > a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDx > e.c > > > > b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDx > e.c > > > index 0a1888e5ef..e236ddff33 100644 > > > --- > > > > a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDx > e.c > > > +++ > > > > b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDx > e.c > > > @@ -13,7 +13,7 @@ > > > > > > InitCommunicateBuffer() is really function to check the variable = data > size. > > > > > > -Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved.<= BR> > > > +Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.<= BR> > > > SPDX-License-Identifier: BSD-2-Clause-Patent > > > > > > **/ > > > @@ -39,6 +39,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent > > > #include > > > > > > #include "PrivilegePolymorphic.h" > > > +#include "VariableParsing.h" > > > > > > EFI_HANDLE mHandle =3D NUL= L; > > > EFI_SMM_VARIABLE_PROTOCOL *mSmmVariable =3D NUL= L; > > > @@ -46,8 +47,19 @@ EFI_EVENT > mVirtualAddressChangeEvent =3D > > > NULL; > > > EFI_SMM_COMMUNICATION_PROTOCOL *mSmmCommunication > =3D > > NULL; > > > UINT8 *mVariableBuffer =3D NUL= L; > > > UINT8 *mVariableBufferPhysical =3D NUL= L; > > > +VARIABLE_INFO_ENTRY *mVariableInfo =3D NUL= L; > > > +VARIABLE_STORE_HEADER *mVariableRuntimeHobCacheBuffer > =3D > > > NULL; > > > +VARIABLE_STORE_HEADER *mVariableRuntimeNvCacheBuffer > =3D > > > NULL; > > > +VARIABLE_STORE_HEADER > *mVariableRuntimeVolatileCacheBuffer =3D > > > NULL; > > > UINTN mVariableBufferSize; > > > +UINTN mVariableRuntimeHobCacheBufferSize= ; > > > +UINTN mVariableRuntimeNvCacheBufferSize; > > > +UINTN mVariableRuntimeVolatileCacheBuffe= rSize; > > > UINTN mVariableBufferPayloadSize; > > > +BOOLEAN mVariableRuntimeCachePendingUpdate= ; > > > +BOOLEAN mVariableRuntimeCacheReadLock; > > > +BOOLEAN mVariableAuthFormat; > > > +BOOLEAN mHobFlushComplete; > > > EFI_LOCK mVariableServicesLock; > > > EDKII_VARIABLE_LOCK_PROTOCOL mVariableLock; > > > EDKII_VAR_CHECK_PROTOCOL mVarCheck; > > > @@ -107,6 +119,72 @@ ReleaseLockOnlyAtBootTime ( > > > } > > > } > > > > > > +/** > > > + Return TRUE if ExitBootServices () has been called. > > > + > > > + @retval TRUE If ExitBootServices () has been called. FALSE if > > ExitBootServices > > > () has not been called. > > > +**/ > > > +BOOLEAN > > > +AtRuntime ( > > > + VOID > > > + ) > > > +{ > > > + return EfiAtRuntime (); > > > +} > > > + > > > > AtRuntime() is kept here. But EfiAtRuntime() is still used elsewhere i= n this > file. > > > > > +/** > > > + Initialize the variable cache buffer as an empty variable store. > > > + > > > + @param[out] VariableCacheBuffer A pointer to pointer of a= cache > > > variable store. > > > + @param[in,out] TotalVariableCacheSize On input, the minimum siz= e > > needed > > > for the UEFI variable store cache > > > + buffer that is allocated.= On output, the actual size > of > > the > > > buffer allocated. > > > + If TotalVariableCacheSize= is zero, a buffer will not > be > > > allocated and the > > > + function will return with= EFI_SUCCESS. > > > + > > > + @retval EFI_SUCCESS The variable cache was allocated = and > initialized > > > successfully. > > > + @retval EFI_INVALID_PARAMETER A given pointer is NULL or an > invalid > > > variable store size was specified. > > > + @retval EFI_OUT_OF_RESOURCES Insufficient resources are availa= ble > to > > > allocate the variable store cache buffer. > > > + > > > +**/ > > > +EFI_STATUS > > > +InitVariableCache ( > > > + OUT VARIABLE_STORE_HEADER **VariableCacheBuffer, > > > + IN OUT UINTN *TotalVariableCacheSize > > > + ) > > > +{ > > > + VARIABLE_STORE_HEADER *VariableCacheStorePtr; > > > + > > > + if (TotalVariableCacheSize =3D=3D NULL) { > > > + return EFI_INVALID_PARAMETER; > > > + } > > > + if (*TotalVariableCacheSize =3D=3D 0) { > > > + return EFI_SUCCESS; > > > + } > > > + if (VariableCacheBuffer =3D=3D NULL || *TotalVariableCacheSize < = sizeof > > > (VARIABLE_STORE_HEADER)) { > > > + return EFI_INVALID_PARAMETER; > > > + } > > > + *TotalVariableCacheSize =3D ALIGN_VALUE (*TotalVariableCacheSize, > sizeof > > > (UINT32)); > > > + > > > + // > > > + // Allocate NV Storage Cache and initialize it to all 1's (like a= n erased FV) > > > + // > > > + *VariableCacheBuffer =3D (VARIABLE_STORE_HEADER *) > > AllocateRuntimePages > > > ( > > > + EFI_SIZE_TO_PAGES (*TotalVariableCacheS= ize) > > > + ); > > > + if (*VariableCacheBuffer =3D=3D NULL) { > > > + return EFI_OUT_OF_RESOURCES; > > > + } > > > + VariableCacheStorePtr =3D *VariableCacheBuffer; > > > + SetMem32 ((VOID *) VariableCacheStorePtr, *TotalVariableCacheSize= , > > > (UINT32) 0xFFFFFFFF); > > > + > > > + ZeroMem ((VOID *) VariableCacheStorePtr, sizeof > > > (VARIABLE_STORE_HEADER)); > > > + VariableCacheStorePtr->Size =3D (UINT32) *TotalVariableCacheSi= ze; > > > + VariableCacheStorePtr->Format =3D VARIABLE_STORE_FORMATTED; > > > + VariableCacheStorePtr->State =3D VARIABLE_STORE_HEALTHY; > > > + > > > + return EFI_SUCCESS; > > > +} > > > + > > > /** > > > Initialize the communicate buffer using DataSize and Function. > > > > > > @@ -425,7 +503,169 @@ Done: > > > } > > > > > > /** > > > - This code finds variable in storage blocks (Volatile or Non-Volat= ile). > > > + Signals SMM to synchronize any pending variable updates with the > runtime > > > cache(s). > > > + > > > +**/ > > > +VOID > > > +SyncRuntimeCache ( > > > + VOID > > > + ) > > > +{ > > > + // > > > + // Init the communicate buffer. The buffer data size is: > > > + // SMM_COMMUNICATE_HEADER_SIZE + > > > SMM_VARIABLE_COMMUNICATE_HEADER_SIZE. > > > + // > > > + InitCommunicateBuffer (NULL, 0, > > > SMM_VARIABLE_FUNCTION_SYNC_RUNTIME_CACHE); > > > + > > > + // > > > + // Send data to SMM. > > > + // > > > + SendCommunicateBuffer (0); > > > +} > > > + > > > +/** > > > + Check whether a SMI must be triggered to retrieve pending cache > updates. > > > + > > > + If the variable HOB was finished being flushed since the last che= ck for a > > > runtime cache update, this function > > > + will prevent the HOB cache from being used for future runtime cac= he > hits. > > > + > > > +**/ > > > +VOID > > > +CheckForRuntimeCacheSync ( > > > + VOID > > > + ) > > > +{ > > > + if (mVariableRuntimeCachePendingUpdate) { > > > + SyncRuntimeCache (); > > > + } > > > + ASSERT (!mVariableRuntimeCachePendingUpdate); > > > + > > > + // > > > + // The HOB variable data may have finished being flushed in the > runtime > > cache > > > sync update > > > + // > > > + if (mHobFlushComplete && mVariableRuntimeHobCacheBuffer !=3D > NULL) { > > > + if (!EfiAtRuntime ()) { > > > + FreePool (mVariableRuntimeHobCacheBuffer); > > > + } > > > + mVariableRuntimeHobCacheBuffer =3D NULL; > > > + } > > > +} > > > + > > > +/** > > > + Finds the given variable in a runtime cache variable store. > > > + > > > + Caution: This function may receive untrusted input. > > > + The data size is external input, so this function will validate i= t carefully > to > > > avoid buffer overflow. > > > + > > > + @param[in] VariableName Name of Variable to be found. > > > + @param[in] VendorGuid Variable vendor GUID. > > > + @param[out] Attributes Attribute value of the variabl= e found. > > > + @param[in, out] DataSize Size of Data found. If size is= less than > the > > > + data, this value contains the = required size. > > > + @param[out] Data Data pointer. > > > + > > > + @retval EFI_SUCCESS Found the specified variable. > > > + @retval EFI_INVALID_PARAMETER Invalid parameter. > > > + @retval EFI_NOT_FOUND The specified variable could n= ot be > found. > > > + > > > +**/ > > > +EFI_STATUS > > > +FindVariableInRuntimeCache ( > > > + IN CHAR16 *VariableName, > > > + IN EFI_GUID *VendorGuid, > > > + OUT UINT32 *Attributes OPTIONAL, > > > + IN OUT UINTN *DataSize, > > > + OUT VOID *Data OPTIONAL > > > > I'm not sure the newly added OPTIONAL to last parameter 'Data' is corr= ect. > > Per my understanding on below code, 'Data' is always required when > > mVariableRuntimeCachePendingUpdate is FALSE. In other words, 'Data' > > passing with NULL has no meaning. In my opinion it's should not be > > 'optional'. > > > > > + ) > > > +{ > > > + EFI_STATUS Status; > > > + UINTN TempDataSize; > > > + VARIABLE_POINTER_TRACK RtPtrTrack; > > > + VARIABLE_STORE_TYPE StoreType; > > > + VARIABLE_STORE_HEADER > *VariableStoreList[VariableStoreTypeMax]; > > > + > > > + Status =3D EFI_NOT_FOUND; > > > + > > > + if (VariableName =3D=3D NULL || VendorGuid =3D=3D NULL || DataSiz= e =3D=3D > NULL) { > > > + return EFI_INVALID_PARAMETER; > > > + } > > > + > > > + // > > > + // The UEFI specification restricts Runtime Services callers from > invoking the > > > same or certain other Runtime Service > > > + // functions prior to completion and return from a previous Runti= me > Service > > > call. These restrictions prevent > > > + // a GetVariable () or GetNextVariable () call from being issued = until a > prior > > call > > > has returned. The runtime > > > + // cache read lock should always be free when entering this funct= ion. > > > + // > > > + ASSERT (!mVariableRuntimeCacheReadLock); > > > + > > > + mVariableRuntimeCacheReadLock =3D TRUE; > > > + CheckForRuntimeCacheSync (); > > > + > > > + if (!mVariableRuntimeCachePendingUpdate) { > > > + // > > > + // 0: Volatile, 1: HOB, 2: Non-Volatile. > > > + // The index and attributes mapping must be kept in this order = as > > > FindVariable > > > + // makes use of this mapping to implement search algorithm. > > > + // > > > + VariableStoreList[VariableStoreTypeVolatile] =3D > > > mVariableRuntimeVolatileCacheBuffer; > > > + VariableStoreList[VariableStoreTypeHob] =3D > > > mVariableRuntimeHobCacheBuffer; > > > + VariableStoreList[VariableStoreTypeNv] =3D > > > mVariableRuntimeNvCacheBuffer; > > > + > > > + for (StoreType =3D (VARIABLE_STORE_TYPE) 0; StoreType < > > > VariableStoreTypeMax; StoreType++) { > > > + if (VariableStoreList[StoreType] =3D=3D NULL) { > > > + continue; > > > + } > > > + > > > + RtPtrTrack.StartPtr =3D GetStartPointer (VariableStoreList[St= oreType]); > > > + RtPtrTrack.EndPtr =3D GetEndPointer (VariableStoreList[St= oreType]); > > > + RtPtrTrack.Volatile =3D (BOOLEAN) (StoreType =3D=3D > VariableStoreTypeVolatile); > > > + > > > + Status =3D FindVariableEx (VariableName, VendorGuid, FALSE, > &RtPtrTrack, > > > mVariableAuthFormat); > > > + if (!EFI_ERROR (Status)) { > > > + break; > > > + } > > > + } > > > + > > > + if (!EFI_ERROR (Status)) { > > > + // > > > + // Get data size > > > + // > > > + TempDataSize =3D DataSizeOfVariable (RtPtrTrack.CurrPtr, > > > mVariableAuthFormat); > > > + ASSERT (TempDataSize !=3D 0); > > > + > > > + if (*DataSize >=3D TempDataSize) { > > > + if (Data =3D=3D NULL) { > > > + Status =3D EFI_INVALID_PARAMETER; > > > + goto Done; > > > + } > > > + > > > + CopyMem (Data, GetVariableDataPtr (RtPtrTrack.CurrPtr, > > > mVariableAuthFormat), TempDataSize); > > > + if (Attributes !=3D NULL) { > > > + *Attributes =3D RtPtrTrack.CurrPtr->Attributes; > > > + } > > > + > > > + *DataSize =3D TempDataSize; > > > + > > > + UpdateVariableInfo (VariableName, VendorGuid, > RtPtrTrack.Volatile, > > > TRUE, FALSE, FALSE, TRUE, &mVariableInfo); > > > + > > > + Status =3D EFI_SUCCESS; > > > + goto Done; > > > + } else { > > > + *DataSize =3D TempDataSize; > > > + Status =3D EFI_BUFFER_TOO_SMALL; > > > + goto Done; > > > + } > > > + } > > > + } > > > + > > > +Done: > > > + mVariableRuntimeCacheReadLock =3D FALSE; > > > + > > > + return Status; > > > +} > > > + > > > +/** > > > + Finds the given variable in a variable store in SMM. > > > > > > Caution: This function may receive untrusted input. > > > The data size is external input, so this function will validate i= t carefully to > > avoid > > > buffer overflow. > > > @@ -437,20 +677,18 @@ Done: > > > data, this value contains the = required size. > > > @param[out] Data Data pointer. > > > > > > + @retval EFI_SUCCESS Found the specified variable. > > > @retval EFI_INVALID_PARAMETER Invalid parameter. > > > - @retval EFI_SUCCESS Find the specified variable. > > > - @retval EFI_NOT_FOUND Not found. > > > - @retval EFI_BUFFER_TO_SMALL DataSize is too small for the = result. > > > + @retval EFI_NOT_FOUND The specified variable could n= ot be > found. > > > > > > **/ > > > EFI_STATUS > > > -EFIAPI > > > -RuntimeServiceGetVariable ( > > > +FindVariableInSmm ( > > > IN CHAR16 *VariableName, > > > IN EFI_GUID *VendorGuid, > > > OUT UINT32 *Attributes OPTIONAL, > > > IN OUT UINTN *DataSize, > > > - OUT VOID *Data > > > + OUT VOID *Data OPTIONAL > > > ) > > > { > > > EFI_STATUS Status; > > > @@ -474,8 +712,6 @@ RuntimeServiceGetVariable ( > > > return EFI_INVALID_PARAMETER; > > > } > > > > > > - AcquireLockOnlyAtBootTime(&mVariableServicesLock); > > > - > > > // > > > // Init the communicate buffer. The buffer data size is: > > > // SMM_COMMUNICATE_HEADER_SIZE + > > > SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize. > > > @@ -488,7 +724,7 @@ RuntimeServiceGetVariable ( > > > } > > > PayloadSize =3D OFFSET_OF > > > (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + > > > VariableNameSize + TempDataSize; > > > > > > - Status =3D InitCommunicateBuffer ((VOID **)&SmmVariableHeader, > > PayloadSize, > > > SMM_VARIABLE_FUNCTION_GET_VARIABLE); > > > + Status =3D InitCommunicateBuffer ((VOID **) &SmmVariableHeader, > > > PayloadSize, SMM_VARIABLE_FUNCTION_GET_VARIABLE); > > > if (EFI_ERROR (Status)) { > > > goto Done; > > > } > > > @@ -534,11 +770,58 @@ RuntimeServiceGetVariable ( > > > } > > > > > > Done: > > > + return Status; > > > +} > > > + > > > +/** > > > + This code finds variable in storage blocks (Volatile or Non-Volat= ile). > > > + > > > + Caution: This function may receive untrusted input. > > > + The data size is external input, so this function will validate i= t carefully > to > > > avoid buffer overflow. > > > + > > > + @param[in] VariableName Name of Variable to be found. > > > + @param[in] VendorGuid Variable vendor GUID. > > > + @param[out] Attributes Attribute value of the variabl= e found. > > > + @param[in, out] DataSize Size of Data found. If size is= less than > the > > > + data, this value contains the = required size. > > > + @param[out] Data Data pointer. > > > + > > > + @retval EFI_INVALID_PARAMETER Invalid parameter. > > > + @retval EFI_SUCCESS Find the specified variable. > > > + @retval EFI_NOT_FOUND Not found. > > > + @retval EFI_BUFFER_TO_SMALL DataSize is too small for the = result. > > > + > > > +**/ > > > +EFI_STATUS > > > +EFIAPI > > > +RuntimeServiceGetVariable ( > > > + IN CHAR16 *VariableName, > > > + IN EFI_GUID *VendorGuid, > > > + OUT UINT32 *Attributes OPTIONAL, > > > + IN OUT UINTN *DataSize, > > > + OUT VOID *Data > > > + ) > > > +{ > > > + EFI_STATUS Status; > > > + > > > + if (VariableName =3D=3D NULL || VendorGuid =3D=3D NULL || DataSiz= e =3D=3D > NULL) { > > > + return EFI_INVALID_PARAMETER; > > > + } > > > + if (VariableName[0] =3D=3D 0) { > > > + return EFI_NOT_FOUND; > > > + } > > > + > > > + AcquireLockOnlyAtBootTime (&mVariableServicesLock); > > > + if (FeaturePcdGet (PcdEnableVariableRuntimeCache)) { > > > + Status =3D FindVariableInRuntimeCache (VariableName, VendorGuid= , > > Attributes, > > > DataSize, Data); > > > + } else { > > > + Status =3D FindVariableInSmm (VariableName, VendorGuid, Attribu= tes, > > DataSize, > > > Data); > > > + } > > > ReleaseLockOnlyAtBootTime (&mVariableServicesLock); > > > + > > > return Status; > > > } > > > > > > - > > > /** > > > This code Finds the Next available variable. > > > > > > @@ -870,6 +1153,17 @@ OnReadyToBoot ( > > > // > > > SendCommunicateBuffer (0); > > > > > > + // > > > + // Install the system configuration table for variable info data = captured > > > + // > > > + if (FeaturePcdGet (PcdEnableVariableRuntimeCache) && > FeaturePcdGet > > > (PcdVariableCollectStatistics)) { > > > + if (mVariableAuthFormat) { > > > + gBS->InstallConfigurationTable (&gEfiAuthenticatedVariableGui= d, > > > mVariableInfo); > > > + } else { > > > + gBS->InstallConfigurationTable (&gEfiVariableGuid, mVariableI= nfo); > > > + } > > > + } > > > + > > > gBS->CloseEvent (Event); > > > } > > > > > > @@ -893,6 +1187,9 @@ VariableAddressChangeEvent ( > > > { > > > EfiConvertPointer (0x0, (VOID **) &mVariableBuffer); > > > EfiConvertPointer (0x0, (VOID **) &mSmmCommunication); > > > + EfiConvertPointer (0x0, (VOID **) > &mVariableRuntimeHobCacheBuffer); > > > + EfiConvertPointer (0x0, (VOID **) > &mVariableRuntimeNvCacheBuffer); > > > + EfiConvertPointer (0x0, (VOID **) > &mVariableRuntimeVolatileCacheBuffer); > > > } > > > > > > /** > > > @@ -969,6 +1266,159 @@ Done: > > > return Status; > > > } > > > > > > +/** > > > + This code gets information needed from SMM for runtime cache > > initialization. > > > + > > > + @param[out] TotalHobStorageSize Output pointer for the to= tal > HOB > > > storage size in bytes. > > > + @param[out] TotalNvStorageSize Output pointer for the to= tal non- > > > volatile storage size in bytes. > > > + @param[out] TotalVolatileStorageSize Output pointer for the to= tal > volatile > > > storage size in bytes. > > > + @param[out] AuthenticatedVariableUsage Output pointer that > indicates if > > > authenticated variables are to be used. > > > + > > > + @retval EFI_SUCCESS Retrieved the size succes= sfully. > > > + @retval EFI_INVALID_PARAMETER TotalNvStorageSize parame= ter > is > > > NULL. > > > + @retval EFI_OUT_OF_RESOURCES The memory resources > needed for > > a > > > CommBuffer are not available. > > > + @retval Others Could not retrieve the si= ze successfully. > > > + > > > +**/ > > > +EFI_STATUS > > > +GetRuntimeCacheInfo ( > > > + OUT UINTN *TotalHobStorageSize, > > > + OUT UINTN *TotalNvStorageSize, > > > + OUT UINTN *TotalVolatileStorageSize, > > > + OUT BOOLEAN *AuthenticatedVariableUsage > > > + ) > > > +{ > > > + EFI_STATUS Status; > > > + SMM_VARIABLE_COMMUNICATE_GET_RUNTIME_CACHE_INFO > > > *SmmGetRuntimeCacheInfo; > > > + EFI_SMM_COMMUNICATE_HEADER > > *SmmCommunicateHeader; > > > + SMM_VARIABLE_COMMUNICATE_HEADER > > > *SmmVariableFunctionHeader; > > > + UINTN CommSize; > > > + UINT8 *CommBuffer; > > > + > > > + SmmGetRuntimeCacheInfo =3D NULL; > > > + CommBuffer =3D mVariableBuffer; > > > + > > > + if (TotalHobStorageSize =3D=3D NULL || TotalNvStorageSize =3D=3D = NULL || > > > TotalVolatileStorageSize =3D=3D NULL || AuthenticatedVariableUsage = =3D=3D > NULL) { > > > + return EFI_INVALID_PARAMETER; > > > + } > > > + > > > + if (CommBuffer =3D=3D NULL) { > > > + return EFI_OUT_OF_RESOURCES; > > > + } > > > + > > > + AcquireLockOnlyAtBootTime (&mVariableServicesLock); > > > + > > > + CommSize =3D SMM_COMMUNICATE_HEADER_SIZE + > > > SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + sizeof > > > (SMM_VARIABLE_COMMUNICATE_GET_RUNTIME_CACHE_INFO); > > > + ZeroMem (CommBuffer, CommSize); > > > + > > > + SmmCommunicateHeader =3D (EFI_SMM_COMMUNICATE_HEADER *) > > > CommBuffer; > > > + CopyGuid (&SmmCommunicateHeader->HeaderGuid, > > > &gEfiSmmVariableProtocolGuid); > > > + SmmCommunicateHeader->MessageLength =3D > > > SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + sizeof > > > (SMM_VARIABLE_COMMUNICATE_GET_RUNTIME_CACHE_INFO); > > > + > > > + SmmVariableFunctionHeader =3D > (SMM_VARIABLE_COMMUNICATE_HEADER > > *) > > > SmmCommunicateHeader->Data; > > > + SmmVariableFunctionHeader->Function =3D > > > SMM_VARIABLE_FUNCTION_GET_RUNTIME_CACHE_INFO; > > > + SmmGetRuntimeCacheInfo =3D > > > (SMM_VARIABLE_COMMUNICATE_GET_RUNTIME_CACHE_INFO *) > > > SmmVariableFunctionHeader->Data; > > > + > > > + // > > > + // Send data to SMM. > > > + // > > > + Status =3D mSmmCommunication->Communicate > (mSmmCommunication, > > > CommBuffer, &CommSize); > > > + ASSERT_EFI_ERROR (Status); > > > + if (CommSize <=3D SMM_VARIABLE_COMMUNICATE_HEADER_SIZE) { > > > + Status =3D EFI_BAD_BUFFER_SIZE; > > > + goto Done; > > > + } > > > + > > > + Status =3D SmmVariableFunctionHeader->ReturnStatus; > > > + if (EFI_ERROR (Status)) { > > > + goto Done; > > > + } > > > + > > > + // > > > + // Get data from SMM. > > > + // > > > + *TotalHobStorageSize =3D SmmGetRuntimeCacheInfo- > >TotalHobStorageSize; > > > + *TotalNvStorageSize =3D SmmGetRuntimeCacheInfo- > >TotalNvStorageSize; > > > + *TotalVolatileStorageSize =3D SmmGetRuntimeCacheInfo- > > > >TotalVolatileStorageSize; > > > + *AuthenticatedVariableUsage =3D SmmGetRuntimeCacheInfo- > > > >AuthenticatedVariableUsage; > > > + > > > +Done: > > > + ReleaseLockOnlyAtBootTime (&mVariableServicesLock); > > > + return Status; > > > +} > > > + > > > +/** > > > + Sends the runtime variable cache context information to SMM. > > > + > > > + @retval EFI_SUCCESS Retrieved the size successfully= . > > > + @retval EFI_INVALID_PARAMETER TotalNvStorageSize parameter is > NULL. > > > + @retval EFI_OUT_OF_RESOURCES The memory resources needed > for a > > > CommBuffer are not available. > > > + @retval Others Could not retrieve the size suc= cessfully.; > > > + > > > +**/ > > > +EFI_STATUS > > > +SendRuntimeVariableCacheContextToSmm ( > > > + VOID > > > + ) > > > +{ > > > + EFI_STATUS Status; > > > + > SMM_VARIABLE_COMMUNICATE_RUNTIME_VARIABLE_CACHE_CONTEXT > > > *SmmRuntimeVarCacheContext; > > > + EFI_SMM_COMMUNICATE_HEADER > > > *SmmCommunicateHeader; > > > + SMM_VARIABLE_COMMUNICATE_HEADER > > > *SmmVariableFunctionHeader; > > > + UINTN CommSiz= e; > > > + UINT8 *CommBu= ffer; > > > + > > > + SmmRuntimeVarCacheContext =3D NULL; > > > + CommBuffer =3D mVariableBuffer; > > > + > > > + if (CommBuffer =3D=3D NULL) { > > > + return EFI_OUT_OF_RESOURCES; > > > + } > > > + > > > + AcquireLockOnlyAtBootTime (&mVariableServicesLock); > > > + > > > + // > > > + // Init the communicate buffer. The buffer data size is: > > > + // SMM_COMMUNICATE_HEADER_SIZE + > > > SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + sizeof > > > > (SMM_VARIABLE_COMMUNICATE_RUNTIME_VARIABLE_CACHE_CONTEXT) > ; > > > + // > > > + CommSize =3D SMM_COMMUNICATE_HEADER_SIZE + > > > SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + sizeof > > > > (SMM_VARIABLE_COMMUNICATE_RUNTIME_VARIABLE_CACHE_CONTEXT) > ; > > > + ZeroMem (CommBuffer, CommSize); > > > + > > > + SmmCommunicateHeader =3D (EFI_SMM_COMMUNICATE_HEADER *) > > > CommBuffer; > > > + CopyGuid (&SmmCommunicateHeader->HeaderGuid, > > > &gEfiSmmVariableProtocolGuid); > > > + SmmCommunicateHeader->MessageLength =3D > > > SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + sizeof > > > > (SMM_VARIABLE_COMMUNICATE_RUNTIME_VARIABLE_CACHE_CONTEXT) > ; > > > + > > > + SmmVariableFunctionHeader =3D > (SMM_VARIABLE_COMMUNICATE_HEADER > > *) > > > SmmCommunicateHeader->Data; > > > + SmmVariableFunctionHeader->Function =3D > > > > SMM_VARIABLE_FUNCTION_INIT_RUNTIME_VARIABLE_CACHE_CONTEXT; > > > + SmmRuntimeVarCacheContext =3D > > > > (SMM_VARIABLE_COMMUNICATE_RUNTIME_VARIABLE_CACHE_CONTEXT > *) > > > SmmVariableFunctionHeader->Data; > > > + > > > + SmmRuntimeVarCacheContext->RuntimeHobCache =3D > > > mVariableRuntimeHobCacheBuffer; > > > + SmmRuntimeVarCacheContext->RuntimeVolatileCache =3D > > > mVariableRuntimeVolatileCacheBuffer; > > > + SmmRuntimeVarCacheContext->RuntimeNvCache =3D > > > mVariableRuntimeNvCacheBuffer; > > > + SmmRuntimeVarCacheContext->PendingUpdate =3D > > > &mVariableRuntimeCachePendingUpdate; > > > + SmmRuntimeVarCacheContext->ReadLock =3D > > > &mVariableRuntimeCacheReadLock; > > > + SmmRuntimeVarCacheContext->HobFlushComplete =3D > > &mHobFlushComplete; > > > + > > > + // > > > + // Send data to SMM. > > > + // > > > + Status =3D mSmmCommunication->Communicate > (mSmmCommunication, > > > CommBuffer, &CommSize); > > > + ASSERT_EFI_ERROR (Status); > > > + if (CommSize <=3D SMM_VARIABLE_COMMUNICATE_HEADER_SIZE) { > > > + Status =3D EFI_BAD_BUFFER_SIZE; > > > + goto Done; > > > + } > > > + > > > + Status =3D SmmVariableFunctionHeader->ReturnStatus; > > > + if (EFI_ERROR (Status)) { > > > + goto Done; > > > + } > > > + > > > +Done: > > > + ReleaseLockOnlyAtBootTime (&mVariableServicesLock); > > > + return Status; > > > +} > > > + > > > /** > > > Initialize variable service and install Variable Architectural pr= otocol. > > > > > > @@ -985,7 +1435,7 @@ SmmVariableReady ( > > > { > > > EFI_STATUS Status; > > > > > > - Status =3D gBS->LocateProtocol (&gEfiSmmVariableProtocolGuid, NUL= L, > (VOID > > > **)&mSmmVariable); > > > + Status =3D gBS->LocateProtocol (&gEfiSmmVariableProtocolGuid, NUL= L, > > (VOID > > > **) &mSmmVariable); > > > if (EFI_ERROR (Status)) { > > > return; > > > } > > > @@ -1007,6 +1457,42 @@ SmmVariableReady ( > > > // > > > mVariableBufferPhysical =3D mVariableBuffer; > > > > > > + if (FeaturePcdGet (PcdEnableVariableRuntimeCache)) { > > > + DEBUG ((DEBUG_INFO, "Variable driver runtime cache is > enabled.\n")); > > > + // > > > + // Allocate runtime variable cache memory buffers. > > > + // > > > + Status =3D GetRuntimeCacheInfo ( > > > + &mVariableRuntimeHobCacheBufferSize, > > > + &mVariableRuntimeNvCacheBufferSize, > > > + &mVariableRuntimeVolatileCacheBufferSize, > > > + &mVariableAuthFormat > > > + ); > > > + if (!EFI_ERROR (Status)) { > > > + Status =3D InitVariableCache (&mVariableRuntimeHobCacheBuffer= , > > > &mVariableRuntimeHobCacheBufferSize); > > > + if (!EFI_ERROR (Status)) { > > > + Status =3D InitVariableCache (&mVariableRuntimeNvCacheBuffe= r, > > > &mVariableRuntimeNvCacheBufferSize); > > > + if (!EFI_ERROR (Status)) { > > > + Status =3D InitVariableCache > (&mVariableRuntimeVolatileCacheBuffer, > > > &mVariableRuntimeVolatileCacheBufferSize); > > > + if (!EFI_ERROR (Status)) { > > > + Status =3D SendRuntimeVariableCacheContextToSmm (); > > > + if (!EFI_ERROR (Status)) { > > > + SyncRuntimeCache (); > > > + } > > > + } > > > + } > > > + } > > > + if (EFI_ERROR (Status)) { > > > + mVariableRuntimeHobCacheBuffer =3D NULL; > > > + mVariableRuntimeNvCacheBuffer =3D NULL; > > > + mVariableRuntimeVolatileCacheBuffer =3D NULL; > > > + } > > > + } > > > > Above code uses a little bit deep of nested if-statement, and is a lit= tle bit > harder > > to > > read. What about flatten it? For example, one of the ways is using sho= rt- > > circuiting > > expression in one if-statement. Using 'goto' is another option. > > > > if (GetRuntimeCacheInfo (&mVariableRuntimeHobCacheBufferSize, > > &mVariableRuntimeNvCacheBufferSize, > > &mVariableRuntimeVolatileCacheBufferSize, > > &mVariableAuthFormat) =3D=3D EFI_SUCCESS = && > > InitVariableCache (&mVariableRuntimeHobCacheBuffer, > > &mVariableRuntimeHobCacheBufferSize) =3D=3D= EFI_SUCCESS > && > > InitVariableCache (&mVariableRuntimeNvCacheBuffer, > > &mVariableRuntimeNvCacheBufferSize) =3D=3D = EFI_SUCCESS && > > InitVariableCache (&mVariableRuntimeVolatileCacheBuffer, > > &mVariableRuntimeVolatileCacheBufferSize) = =3D=3D EFI_SUCCESS > && > > SendRuntimeVariableCacheContextToSmm () =3D=3D EFI_SUCCESS) { > > SyncRuntimeCache (); > > } else { > > Status =3D EFI_OUT_OF_RESOURCES; > > mVariableRuntimeHobCacheBuffer =3D NULL; > > mVariableRuntimeNvCacheBuffer =3D NULL; > > mVariableRuntimeVolatileCacheBuffer =3D NULL; > > } > > > > Your code is not wrong, except that the memory already allocated is no= t > freed > > due to later > > error. But maybe there's no need to free in such fatal situation. Anyw= ay, > you > > don't have > > to do above change. I'll leave it to you to make decision. > > > > Regards, > > Jian > > > + ASSERT_EFI_ERROR (Status); > > > + } else { > > > + DEBUG ((DEBUG_INFO, "Variable driver runtime cache is > disabled.\n")); > > > + } > > > + > > > gRT->GetVariable =3D RuntimeServiceGetVariable; > > > gRT->GetNextVariableName =3D RuntimeServiceGetNextVariableName; > > > gRT->SetVariable =3D RuntimeServiceSetVariable; > > > -- > > > 2.16.2.windows.1 > > > > > >=20 >=20