From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by mx.groups.io with SMTP id smtpd.web10.16192.1653228236586994920 for ; Sun, 22 May 2022 07:03:57 -0700 Authentication-Results: mx.groups.io; dkim=fail reason="unable to parse pub key" header.i=@intel.com header.s=intel header.b=h0/De0Sc; spf=pass (domain: intel.com, ip: 134.134.136.24, mailfrom: jian.j.wang@intel.com) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1653228236; x=1684764236; h=from:to:cc:subject:date:message-id:references: in-reply-to:content-transfer-encoding:mime-version; bh=RGRPbUu8vUsd/KAlW+oq8bKBrOMBPi5yCx1HnuKm7F8=; b=h0/De0ScSCZpIQt7LRSpMFic+3Mgr7MXsnaRR1mti1CJ46PeNOycspgd Z3G6qp9rMyGnveu9Td9pjEuJFTHaGXpffiHMyHrMOw2SZ+fgY/uOxxq/k uTTh1bfBat0z0m7Yid7eLkeY7RMzUxFYNU02V6IWqZxeD+cJgs/cbpRgV XjddToBEk3g5Xt0PQcJBaWiuffJKrUY1uP96NiQi1VDwgvl6yEfG0zYec aFUHAnzWxsKQhd8BKzzYnUlxLhaALMa57Me6JuWC5jX5NYacda6C+gnsW WpHYjWDrQ2dnO5NZTf5sC141CVyFfswmU/Q9Tw/AK6AEECMHWnztPz4zU w==; X-IronPort-AV: E=McAfee;i="6400,9594,10355"; a="272712768" X-IronPort-AV: E=Sophos;i="5.91,244,1647327600"; d="scan'208";a="272712768" Received: from fmsmga005.fm.intel.com ([10.253.24.32]) by orsmga102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 May 2022 07:03:53 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.91,244,1647327600"; d="scan'208";a="900149699" Received: from fmsmsx603.amr.corp.intel.com ([10.18.126.83]) by fmsmga005.fm.intel.com with ESMTP; 22 May 2022 07:03:53 -0700 Received: from fmsmsx602.amr.corp.intel.com (10.18.126.82) by fmsmsx603.amr.corp.intel.com (10.18.126.83) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2308.27; Sun, 22 May 2022 07:03:52 -0700 Received: from FMSEDG603.ED.cps.intel.com (10.1.192.133) by fmsmsx602.amr.corp.intel.com (10.18.126.82) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2308.27 via Frontend Transport; Sun, 22 May 2022 07:03:52 -0700 Received: from NAM10-MW2-obe.outbound.protection.outlook.com (104.47.55.105) by edgegateway.intel.com (192.55.55.68) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.1.2308.27; Sun, 22 May 2022 07:03:51 -0700 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=jF0WNEjpCG/ExiZoJkpNN8/BjJkH2cgvvx6psaREgXWPijMQKOnrX+RyaBShlQWhfUz5rLb7IdYiOwYqML8/0t9PXf27LTLL+lEg83CV0OLV6P+Y12lL+tVHQnqRwucMPP3+XtrvGp4JAD5CkZlmWJedihqJbte52kcTRNkdM1kA4kx4U8X7vaW8+ILIV67f357WXdoIeiHyGHoZL2xe3MGpJTzhhDe/y/VDtSDORUjIjXJPLNNkAM4o1ekAir3qZgwiGU+8QSZ4hJz+6QjFnXi9UcW9Re1MZttX+xsVDhq82ckHKcVwuBB1aiNv0wy/a1o7N9bRVVls2Jn090BHjQ== 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-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=yR5LLjlNIurkPfSGq6XktyOilnFFYe9t2xRX+ghwasI=; b=TMiFaR6JEqmRSxbBg7IUou2x/rGVkZxjr5yzDxVgutWl9QV82MOomgxyeyii53zkFqzpuMTl3QIm0Fobt1e7uXxVEIFnewLppLMjpJUQtbYcEIughh5etTb+qSsDFufVg9h+06PKHJSZveJxoRyOpEtV10X1IqttJSWJQpyHvER/kzuHY7ph+KCkFyewuCMaXFDXqJ+u4T9Cd921uIFj3tukQ3eM2vFrXHYNmYUUwih4cr6GEaN5sFEOkwLBmdLle9BHGb2gpzTb63e4WJxNm4N72gSn2asWAeEY4DA3cX1Oz/yYzeD3wv8Tpc7m4/vmgqKp826640BdadoM40zl3w== 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 Received: from CO1PR11MB4945.namprd11.prod.outlook.com (2603:10b6:303:9c::8) by BN8PR11MB3571.namprd11.prod.outlook.com (2603:10b6:408:8f::14) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5273.13; Sun, 22 May 2022 14:03:41 +0000 Received: from CO1PR11MB4945.namprd11.prod.outlook.com ([fe80::a420:db2c:31db:7906]) by CO1PR11MB4945.namprd11.prod.outlook.com ([fe80::a420:db2c:31db:7906%9]) with mapi id 15.20.5273.022; Sun, 22 May 2022 14:03:41 +0000 From: "Wang, Jian J" To: "Vang, Judah" , "devel@edk2.groups.io" CC: "Gao, Liming" , "Mistry, Nishant C" Subject: Re: [Patch v2 09/28] MdeModulePkg: Add support for Protected Variables Thread-Topic: [Patch v2 09/28] MdeModulePkg: Add support for Protected Variables Thread-Index: AQHYW/O6ibja8TJq40CkuAHy4+/ziq0q1vzQ Date: Sun, 22 May 2022 14:03:41 +0000 Message-ID: References: <20220429180430.3292-1-judah.vang@intel.com> <20220429180430.3292-10-judah.vang@intel.com> In-Reply-To: <20220429180430.3292-10-judah.vang@intel.com> Accept-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: dlp-reaction: no-action dlp-version: 11.6.401.20 dlp-product: dlpe-windows authentication-results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=intel.com; x-ms-publictraffictype: Email x-ms-office365-filtering-correlation-id: 70eee63d-0500-4289-4a50-08da3bfbe05a x-ms-traffictypediagnostic: BN8PR11MB3571:EE_ x-ld-processed: 46c98d88-e344-4ed4-8496-4ed7712e255d,ExtAddr x-microsoft-antispam-prvs: x-ms-exchange-senderadcheck: 1 x-ms-exchange-antispam-relay: 0 x-microsoft-antispam: BCL:0; x-microsoft-antispam-message-info: GcF+Ehi9ZHQQtkM18sv6VmaChpWV2JUlWThb+m3e8hm/9b0ACxip6O902r8IAo6/4jTq1sdav/7+/Y16B8s3fafR+9H+09sVj2RLEqHizYLUZLWOnKBBf+XFW7V5NqPAvLrKANpAPrwUSrIZMFT6hiiqeYeElswLJqS/P73Iq8+NISnguAxm2lNR4pCYQKaDEp9ipC7fwukIWMYurBsMxjNdv7FH7NxJM95fch0lfVY4k6ygWiN3rkHMGh/uBD1bon7mxj0sRv8IP4MV6Oa6swdMfwHXoVM2xCzkJDtjDUgcnRcVnMrF7wdOhElcCcQcd6YAAGeyAtoPK9PCUsgchYMDJJw5SjXIhtdq/Y8Foq8YprQLGp1Ht0YSZmFgufJNDcuRkxlaeduL0RdVRW/6VSMClsVC8xpkoZ1JojgMu+onSdb878F6CWyGuEjsgDWZnMrl8ZKTVRv6EXn2s+u7G/ghj8J0uMJLWP+L+Ly7yG9H/O62kjqe4NDxUA2ZHU/EVQzwhS955Jgwu8x2YuGDHK78Xggk36IuDkFsqNdonIpMTSfAXxNkXHXW5hHMJPLvXOkqCbckzbUpqzzyIWM9lo5dAaK2n+hQqpmYqhp2yw8Wo1LY2+bH6eOimHPQoBOu35h2kJ+2en9Ct4yLy/gCNPGE+TboHmElD9UOWKADxtLW/cDqtvBNyrmTnsFW5XS7xkqjJoDiMaffhKLE7EzX09JrW03L7fGwZXE0hXVgszQ4XPqIoTf52EvVqS7xApYQrsWDU86MjKdGX5Xbc8h1ChKpQQGMyAx4TGYdoE6L94U= x-forefront-antispam-report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:CO1PR11MB4945.namprd11.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230001)(366004)(5660300002)(30864003)(64756008)(66446008)(76116006)(66946007)(66556008)(8676002)(66476007)(52536014)(38100700002)(4326008)(38070700005)(26005)(82960400001)(122000001)(8936002)(9686003)(2906002)(53546011)(86362001)(186003)(54906003)(110136005)(966005)(508600001)(6506007)(7696005)(45080400002)(71200400001)(83380400001)(55016003)(316002)(107886003)(33656002)(559001)(579004);DIR:OUT;SFP:1102; x-ms-exchange-antispam-messagedata-chunkcount: 1 x-ms-exchange-antispam-messagedata-0: =?us-ascii?Q?k1ivPic/6jA8kaREdKFKHtwhAVZhBgEY25HE2bm3OjJWMuaGkJmQLKIjBU6u?= =?us-ascii?Q?O8qfGNgUkm9dqg62/OoIiRw5vPgnQdPs+ICpmONB2E2xocV52zk53SehW7qb?= =?us-ascii?Q?5t2p7NBq+/qzHMj8/mFgDrqhUTL4bfgIf/Cg2HjPZA62iXRKqiYT7a2j+csq?= =?us-ascii?Q?oo17cqwF1XDYhjnK/zUZgC3QHDvcH2kuSUH04CXYdotKC4FUNiS5t1f7sKgt?= =?us-ascii?Q?HcGeE5wvAZSA22AgSdOh/3EdIs1dk/ulMOM4A3rfAVhpsXmLPrsl/Knpu3X9?= =?us-ascii?Q?wMURrM8GS6k9p/Sn+tgQKQrrUupLP2gZfyCqOPwGse/J9ffn3QbD3929FUt3?= =?us-ascii?Q?LAJoXvgXY1ffC4TEi0ok4SLzqBVj6QRfe71YAlD8/jfvxBypINoTsWv852L3?= =?us-ascii?Q?PotSSWQj1i9rBefUHulH0hm8o42G0uvZShi8WasDUxWHkJS+G8wjcCL6Yjff?= =?us-ascii?Q?gacbZBrSBLFF2HZ2r2w615jSXrZCZOeSB8eCdnOFn8oY7uAT9LNHlAdzgDYP?= =?us-ascii?Q?G02QUs/tQcoNixUnvyB/65RJRl/BjBDpwRJXzeRC0klaUTgPvenKDMHMLjmf?= =?us-ascii?Q?obdGdpcFQUzE3WUW/h7NbiGZM4JvXeMs/48a4ak9U6WLQnpff2kCOlLftEou?= =?us-ascii?Q?mhTaQ0gfDzXozaBd/PYarxrUnUWgfg6WKWgSv4Jkfo9LJ7SrexzI/s5fsvjc?= =?us-ascii?Q?TyGWYQreyF/Zt85C0ZRvz1OQr9Pp/7ILZbLQRVo4ELFQq98j5QfZbsjixKf5?= =?us-ascii?Q?D7yKgNUyc1wLfIFv56XyWumQEoP8J6WLJqj3Z/gUlQhCTVFro0VgNZ9e4CB6?= =?us-ascii?Q?1oSJ6Z43vMZE30cJK5t28vl/YECf6AzUPvnow3Ra1QJuI19Tq34rWyF/wDVK?= =?us-ascii?Q?0alsJgCAMJm5DKJoRu9Zn5Lgwx/BpuPXynYpxVz+osOYdGRJ9Q+3rCQMJUt9?= =?us-ascii?Q?Ws083BvmFyWuggvQaSTvPXUvmRAyR0yUZrgqD1gE5TOWPGDIAD65GBLL3K1o?= =?us-ascii?Q?hPv0J9qf6qa6ce7VB8she5N/gknA5ndWIVSuS7VZyFa80FfIEYhJAGjPnDyP?= =?us-ascii?Q?/VkzgRw/xHljk4b1TZEQsUzWZA/UxSrFt1kqSFmZyfpUPjHGSiunQ7Kt+vsM?= =?us-ascii?Q?NsKKCzQEkkK3HkCFXeambfTMYmLHC2QsOJTe6kkPgaUGzy4LdupPWds9qy1O?= =?us-ascii?Q?vdo8YdpGtqU2fZ3E4AM1UNzhjLOdc/3uct+KtyolfQ8MKr7mnwhp0hmm26c1?= =?us-ascii?Q?U60MWLAmUqid5YWhPiSYPPD1nqHnQXruOwRzSlE+1aBcjINLikNkWhAoCmOy?= =?us-ascii?Q?J8Q42m4Q0LcxV3YI8kIOWzJ5ZtsPliIbkiNwNpzSfp5qLtr0ZBmhdEw+6Whc?= =?us-ascii?Q?EWbQlVT3726l2xAmWtt9goNWDsn+fcCGoA94+u1LT0N9ZbbOB597KXSsjbyI?= =?us-ascii?Q?p5azJwGR1vVo4N1NsCKfFZiIceRlE1V1Uy9A4bX9ZmYcqpxSycUpTtDfuOt5?= =?us-ascii?Q?oFhlbfjVng30uXCcoafQ/rBKKfXFH+CzT7J+/zQNBoADmHoHl21RS9N2CgRb?= =?us-ascii?Q?onfdwUXq5zo/yp5kcW8YvDpvlodNobqIjrAOWLyuvP+Pt1CWo2iQHVLC05hh?= =?us-ascii?Q?yCrlgF/T0Ps7A0fDf4sOXT1o7JvCtgJEAncn3MtcadtELhtHasTDJ+na9f7O?= =?us-ascii?Q?lLkvkm3qhxi6qnmjZ0x7SqrAyKPguG+J3SERwzXjRpXtZts+ooO3IH8FmLPD?= =?us-ascii?Q?vOUEdKUaCg=3D=3D?= MIME-Version: 1.0 X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-AuthSource: CO1PR11MB4945.namprd11.prod.outlook.com X-MS-Exchange-CrossTenant-Network-Message-Id: 70eee63d-0500-4289-4a50-08da3bfbe05a X-MS-Exchange-CrossTenant-originalarrivaltime: 22 May 2022 14:03:41.2722 (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: voDfrf8Jqv49dYjzxRYziTbPiAwCH9XKLna8SWyeA+62Uu/G3hntjrkQTUeJWAHkKw4N9e1zJrqD7y/K4bLhHA== X-MS-Exchange-Transport-CrossTenantHeadersStamped: BN8PR11MB3571 Return-Path: jian.j.wang@intel.com X-OriginatorOrg: intel.com Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Judah, See my inline comments below. Regards, Jian > -----Original Message----- > From: Vang, Judah > Sent: Saturday, April 30, 2022 2:04 AM > To: devel@edk2.groups.io > Cc: Wang, Jian J ; Gao, Liming > ; Mistry, Nishant C > Subject: [Patch v2 09/28] MdeModulePkg: Add support for Protected Variabl= es >=20 > REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3D2594 >=20 > Add support for Protected Variables. > Add new API to retrieve Variable Infomation and data. > Add new API to update variable in non-volatile storage or > cached copy. >=20 > Cc: Jian J Wang > Cc: Liming Gao > Cc: Nishant C Mistry > Signed-off-by: Jian J Wang > Signed-off-by: Nishant C Mistry > Signed-off-by: Judah Vang > --- > MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf | = 3 > +- > MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf | = 3 +- > MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf | > 4 +- > MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf | > 3 +- > MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.h | = 126 +- > MdeModulePkg/Universal/Variable/RuntimeDxe/VariableParsing.h | = 91 +- > MdeModulePkg/Universal/Variable/RuntimeDxe/Reclaim.c | = 349 +++- > MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c | 2= 139 > +++++++++++--------- > MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c | = 26 +- > MdeModulePkg/Universal/Variable/RuntimeDxe/VariableExLib.c | = 167 +- > MdeModulePkg/Universal/Variable/RuntimeDxe/VariableNonVolatile.c | = 194 > +- > MdeModulePkg/Universal/Variable/RuntimeDxe/VariableParsing.c | = 320 > ++- > MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeCache.c | > 2 +- > MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c | = 39 +- > MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c | > 41 +- > 15 files changed, 2454 insertions(+), 1053 deletions(-) >=20 > diff --git > a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf > b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf > index c9434df631ee..c0b90e6ca066 100644 > --- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf > +++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf > @@ -9,7 +9,7 @@ > # This external input must be validated carefully to avoid security iss= ues such as > # buffer overflow or integer overflow. > # > -# Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
> +# Copyright (c) 2006 - 2022, Intel Corporation. All rights reserved.
> # Copyright (c) Microsoft Corporation. > # SPDX-License-Identifier: BSD-2-Clause-Patent > # > @@ -73,6 +73,7 @@ [LibraryClasses] > VarCheckLib > VariablePolicyLib > VariablePolicyHelperLib > + ProtectedVariableLib >=20 > [Protocols] > gEfiFirmwareVolumeBlockProtocolGuid ## CONSUMES > diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf > b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf > index eaa97a01c6e5..6f9f027fbb0f 100644 > --- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf > +++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf > @@ -18,7 +18,7 @@ > # may not be modified without authorization. If platform fails to prote= ct these > resources, > # the authentication service provided in this driver will be broken, an= d the > behavior is undefined. > # > -# Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.
> +# Copyright (c) 2010 - 2022, Intel Corporation. All rights reserved.
> # Copyright (c) Microsoft Corporation. > # SPDX-License-Identifier: BSD-2-Clause-Patent > # > @@ -82,6 +82,7 @@ [LibraryClasses] > UefiBootServicesTableLib > VariablePolicyLib > VariablePolicyHelperLib > + ProtectedVariableLib >=20 > [Protocols] > gEfiSmmFirmwareVolumeBlockProtocolGuid ## CONSUMES > diff --git > a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf > b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf > index a0d8b2267e92..5d2fc78ea917 100644 > --- > a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf > +++ > b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf > @@ -13,7 +13,7 @@ > # may not be modified without authorization. If platform fails to prote= ct these > resources, > # the authentication service provided in this driver will be broken, an= d the > behavior is undefined. > # > -# Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.
> +# Copyright (c) 2010 - 2022, Intel Corporation. All rights reserved.
> # Copyright (c) Microsoft Corporation.
> # SPDX-License-Identifier: BSD-2-Clause-Patent > # > @@ -61,6 +61,8 @@ [LibraryClasses] > SafeIntLib > PcdLib > MmUnblockMemoryLib > + ProtectedVariableLib > + IoLib [JianJW]=20 Why's IoLib needed here? I didn't find any of its interfaces used in this p= atch. >=20 > [Protocols] > gEfiVariableWriteArchProtocolGuid ## PRODUCES > diff --git > a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf > b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf > index d8c4f77e7f1f..6ea7b8d4293e 100644 > --- > a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf > +++ > b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf > @@ -18,7 +18,7 @@ > # may not be modified without authorization. If platform fails to prote= ct these > resources, > # the authentication service provided in this driver will be broken, an= d the > behavior is undefined. > # > -# Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.
> +# Copyright (c) 2010 - 2022, Intel Corporation. All rights reserved.
> # Copyright (c) 2018, Linaro, Ltd. All rights reserved.
> # Copyright (c) Microsoft Corporation. > # SPDX-License-Identifier: BSD-2-Clause-Patent > @@ -78,6 +78,7 @@ [LibraryClasses] > VarCheckLib > VariablePolicyLib > VariablePolicyHelperLib > + ProtectedVariableLib >=20 > [Protocols] > gEfiSmmFirmwareVolumeBlockProtocolGuid ## CONSUMES > diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.h > b/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.h > index 31e408976a35..97b4f9c906ff 100644 > --- a/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.h > +++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.h > @@ -2,7 +2,7 @@ > The internal header file includes the common header files, defines > internal structure and functions used by Variable modules. >=20 > -Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
> +Copyright (c) 2006 - 2022, Intel Corporation. All rights reserved.
> SPDX-License-Identifier: BSD-2-Clause-Patent >=20 > **/ > @@ -31,6 +31,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent > #include > #include > #include > +#include > #include > #include > #include > @@ -823,4 +824,127 @@ VariableExLibAtRuntime ( > VOID > ); >=20 > +/** > + Is user variable? > + > + @param[in] Variable Pointer to variable header. > + > + @retval TRUE User variable. > + @retval FALSE System variable. > + > +**/ > +BOOLEAN > +IsUserVariable ( > + IN VARIABLE_HEADER *Variable > + ); > + > +/** > + > + Variable store garbage collection and reclaim operation. > + > + @param[in] VariableBase Base address of variable store= . > + @param[out] LastVariableOffset Offset of last variable. > + @param[in] IsVolatile The variable store is volatile= or not; > + if it is non-volatile, need FT= W. > + @param[in, out] UpdatingPtrTrack Pointer to updating variable p= ointer > track structure. > + @param[in] NewVariable Pointer to new variable. > + @param[in] NewVariableSize New variable size. > + > + @return EFI_SUCCESS Reclaim operation has finished su= ccessfully. > + @return EFI_OUT_OF_RESOURCES No enough memory resources or > variable space. > + @return Others Unexpect error happened during re= claim > operation. > + > +**/ > +EFI_STATUS > +Reclaim ( > + IN EFI_PHYSICAL_ADDRESS VariableBase, > + OUT UINTN *LastVariableOffset, > + IN BOOLEAN IsVolatile, > + IN OUT VARIABLE_POINTER_TRACK *UpdatingPtrTrack, > + IN VARIABLE_HEADER *NewVariable, > + IN UINTN NewVariableSize > + ); > + > +/** > + > + This function writes data to the FWH at the correct LBA even if the LB= As > + are fragmented. > + > + @param Global Pointer to VARIABLE_GLOBAL structure. > + @param Volatile Point out the Variable is Volatile or N= on-Volatile. > + @param SetByIndex TRUE if target pointer is given as inde= x. > + FALSE if target pointer is absolute. > + @param Fvb Pointer to the writable FVB protocol. > + @param DataPtrIndex Pointer to the Data from the end of > VARIABLE_STORE_HEADER > + structure. > + @param DataSize Size of data to be written. > + @param Buffer Pointer to the buffer from which data i= s written. > + > + @retval EFI_INVALID_PARAMETER Parameters not valid. > + @retval EFI_UNSUPPORTED Fvb is a NULL for Non-Volatile variable > update. > + @retval EFI_OUT_OF_RESOURCES The remaining size is not enough. > + @retval EFI_SUCCESS Variable store successfully updated. > + > +**/ > +EFI_STATUS > +UpdateVariableStore ( > + IN VARIABLE_GLOBAL *Global, > + IN BOOLEAN Volatile, > + IN BOOLEAN SetByIndex, > + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb, > + IN UINTN DataPtrIndex, > + IN UINT32 DataSize, > + IN UINT8 *Buffer > + ); > + > +/** > + Update partial data of a variable on NV storage and/or cached copy. > + > + @param[in] VariableInfo Pointer to a variable with detailed informat= ion. > + @param[in] Offset Offset to write from. > + @param[in] Size Size of data Buffer to update. > + @param[in] Buffer Pointer to data buffer to update. > + > + @retval EFI_SUCCESS The variable data was updated successf= ully. > + @retval EFI_UNSUPPORTED If this function is called directly in= runtime. > + @retval EFI_INVALID_PARAMETER If VariableInfo, Buffer or Size are no= t > valid. > + @retval Others Failed to update NV storage or variabl= e cache. > + > +**/ > +EFI_STATUS > +EFIAPI > +VariableExLibUpdateNvVariable ( > + IN PROTECTED_VARIABLE_INFO *VariableInfo, > + IN UINTN Offset, > + IN UINT32 Size, > + IN UINT8 *Buffer > + ); > + > +/** > + 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 it car= efully 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 variable fou= nd. > + @param[in, out] DataSize Size of Data found. If size is less= than the > + data, this value contains the requi= red 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 not be= found. > + > +**/ > +EFI_STATUS > +FindVariableInSmm ( > + IN CHAR16 *VariableName, > + IN EFI_GUID *VendorGuid, > + OUT UINT32 *Attributes OPTIONAL, > + IN OUT UINTN *DataSize, > + OUT VOID *Data OPTIONAL > + ); > + > #endif > diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableParsing.h > b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableParsing.h > index 951e8a089e34..3a4e8019aaf9 100644 > --- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableParsing.h > +++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableParsing.h > @@ -2,7 +2,7 @@ > Functions in this module are associated with variable parsing operatio= ns and > are intended to be usable across variable driver source files. >=20 > -Copyright (c) 2019, Intel Corporation. All rights reserved.
> +Copyright (c) 2019 - 2022, Intel Corporation. All rights reserved.
> SPDX-License-Identifier: BSD-2-Clause-Patent >=20 > **/ > @@ -19,6 +19,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent >=20 > @param[in] Variable Pointer to the Variable Header. > @param[in] VariableStoreEnd Pointer to the Variable Store End. > + @param[in] AuthFormat Auth-variable indicator. >=20 > @retval TRUE Variable header is valid. > @retval FALSE Variable header is not valid. > @@ -27,7 +28,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent > BOOLEAN > IsValidVariableHeader ( > IN VARIABLE_HEADER *Variable, > - IN VARIABLE_HEADER *VariableStoreEnd > + IN VARIABLE_HEADER *VariableStoreEnd, > + IN BOOLEAN AuthFormat > ); >=20 > /** > @@ -192,6 +194,28 @@ GetVariableDataOffset ( > IN BOOLEAN AuthFormat > ); >=20 > +/** > + Get variable data payload. > + > + @param[in] Variable Pointer to the Variable Header. > + @param[out] Data Pointer to buffer used to store the varia= ble data. > + @param[in] DataSize Size of buffer passed by Data. > + @param[out] DataSize Size of data copied into Data buffer. > + @param[in] AuthFlag Auth-variable indicator. > + > + @return EFI_SUCCESS Data was fetched. > + @return EFI_INVALID_PARAMETER DataSize is NULL. > + @return EFI_BUFFER_TOO_SMALL DataSize is smaller than size of varia= ble > data. > + > +**/ > +EFI_STATUS > +GetVariableData ( > + IN VARIABLE_HEADER *Variable, > + IN OUT VOID *Data, > + IN OUT UINT32 *DataSize, > + IN BOOLEAN AuthFlag > + ); > + > /** >=20 > This code gets the pointer to the next variable header. > @@ -344,4 +368,67 @@ UpdateVariableInfo ( > IN OUT VARIABLE_INFO_ENTRY **VariableInfo > ); >=20 > +/** > + > + Retrieve details of the variable next to given variable within Variabl= eStore. > + > + If VarInfo->Address is NULL, the first one in VariableStore is returne= d. > + > + VariableStart and/or VariableEnd can be given optionally for the situa= tion > + in which the valid storage space is smaller than the VariableStore->Si= ze. > + This usually happens when PEI variable services make a compact variabl= e > + cache to save memory, which cannot make use VariableStore->Size to > determine > + the correct variable storage range. > + > + @param VariableStore Pointer to a variable storage. It's op= tional. > + @param VariableStart Start point of valid range in Variable= Store. > + @param VariableEnd End point of valid range in VariableSt= ore. > + @param VariableInfo Pointer to variable information. [JianJW]=20 The parameters don't match the prototype below > + > + @retval EFI_INVALID_PARAMETER VariableInfo or VariableStore is NULL. > + @retval EFI_NOT_FOUND If the end of VariableStore is reached. > + @retval EFI_SUCCESS The next variable is retrieved successf= ully. > + > +**/ > +EFI_STATUS > +EFIAPI > +GetNextVariableInfo ( > + IN OUT PROTECTED_VARIABLE_INFO *VarInfo > + ); > + > +/** > + > + Retrieve details about a variable and return them in VariableInfo->Hea= der. > + > + If VariableInfo->Address is given, this function will calculate its of= fset > + relative to given variable storage via VariableStore; Otherwise, it wi= ll try > + other internal variable storages or cached copies. It's assumed that, = for all > + copies of NV variable storage, all variables are stored in the same re= lative > + position. If VariableInfo->Address is found in the range of any storag= e copies, > + its offset relative to that storage should be the same in other copies= . > + > + If VariableInfo->Offset is given (non-zero) but not VariableInfo->Addr= ess, > + this function will return the variable memory address inside VariableS= tore, > + if given, via VariableInfo->Address; Otherwise, the address of other s= torage > + copies will be returned, if any. > + > + For a new variable whose offset has not been determined, a value of -1= as > + VariableInfo->Offset should be passed to skip the offset calculation. > + > + @param VariableStore Pointer to a variable storage. It's op= tional. > + @param VariableInfo Pointer to variable information. [JianJW]=20 The parameters doesn't match the prototype below > + > + @retval EFI_INVALID_PARAMETER VariableInfo is NULL or both VariableIn= fo- > >Address > + and VariableInfo->Offset are NULL (0). > + @retval EFI_NOT_FOUND If given Address or Offset is out of ra= nge of > + any given or internal storage copies. > + @retval EFI_SUCCESS Variable details are retrieved successf= ully. > + > +**/ > +EFI_STATUS > +EFIAPI > +GetVariableInfo ( > + IN OUT PROTECTED_VARIABLE_INFO *VarInfo > + ); > + > #endif > diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/Reclaim.c > b/MdeModulePkg/Universal/Variable/RuntimeDxe/Reclaim.c > index fe64d0a2b3dd..a5b7f8a1fbe2 100644 > --- a/MdeModulePkg/Universal/Variable/RuntimeDxe/Reclaim.c > +++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/Reclaim.c > @@ -2,12 +2,15 @@ > Handles non-volatile variable store garbage collection, using FTW > (Fault Tolerant Write) protocol. >=20 > -Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.
> +Copyright (c) 2006 - 2022, Intel Corporation. All rights reserved.
> SPDX-License-Identifier: BSD-2-Clause-Patent >=20 > **/ >=20 > #include "Variable.h" > +#include "VariableNonVolatile.h" > +#include "VariableParsing.h" > +#include "VariableRuntimeCache.h" >=20 > /** > Gets LBA of block and offset by given address. > @@ -155,3 +158,347 @@ FtwVariableSpace ( >=20 > return Status; > } > + > +/** > + > + Variable store garbage collection and reclaim operation. > + > + @param[in] VariableBase Base address of variable store= . > + @param[out] LastVariableOffset Offset of last variable. > + @param[in] IsVolatile The variable store is volatile= or not; > + if it is non-volatile, need FT= W. > + @param[in, out] UpdatingPtrTrack Pointer to updating variable p= ointer > track structure. > + @param[in] NewVariable Pointer to new variable. > + @param[in] NewVariableSize New variable size. > + > + @return EFI_SUCCESS Reclaim operation has finished su= ccessfully. > + @return EFI_OUT_OF_RESOURCES No enough memory resources or > variable space. > + @return Others Unexpect error happened during re= claim > operation. > + > +**/ > +EFI_STATUS > +Reclaim ( > + IN EFI_PHYSICAL_ADDRESS VariableBase, > + OUT UINTN *LastVariableOffset, > + IN BOOLEAN IsVolatile, > + IN OUT VARIABLE_POINTER_TRACK *UpdatingPtrTrack, > + IN VARIABLE_HEADER *NewVariable, > + IN UINTN NewVariableSize > + ) > +{ > + VARIABLE_HEADER *Variable; > + VARIABLE_HEADER *AddedVariable; > + VARIABLE_HEADER *NextVariable; > + VARIABLE_HEADER *NextAddedVariable; > + VARIABLE_STORE_HEADER *VariableStoreHeader; > + UINT8 *ValidBuffer; > + UINTN MaximumBufferSize; > + UINTN VariableSize; > + UINTN NameSize; > + UINT8 *CurrPtr; > + VOID *Point0; > + VOID *Point1; > + BOOLEAN FoundAdded; > + EFI_STATUS Status; > + EFI_STATUS DoneStatus; > + UINTN CommonVariableTotalSize; > + UINTN CommonUserVariableTotalSize; > + UINTN HwErrVariableTotalSize; > + VARIABLE_HEADER *UpdatingVariable; > + VARIABLE_HEADER *UpdatingInDeletedTransition; > + BOOLEAN AuthFormat; > + > + AuthFormat =3D mVariableModuleGlobal->VariableGlobal.= AuthFormat; > + UpdatingVariable =3D NULL; > + UpdatingInDeletedTransition =3D NULL; > + if (UpdatingPtrTrack !=3D NULL) { > + UpdatingVariable =3D UpdatingPtrTrack->CurrPtr; > + UpdatingInDeletedTransition =3D UpdatingPtrTrack->InDeletedTransitio= nPtr; > + } > + > + VariableStoreHeader =3D (VARIABLE_STORE_HEADER *)((UINTN)VariableBase)= ; > + > + CommonVariableTotalSize =3D 0; > + CommonUserVariableTotalSize =3D 0; > + HwErrVariableTotalSize =3D 0; > + > + if (IsVolatile || mVariableModuleGlobal->VariableGlobal.EmuNvMode) { > + // > + // Start Pointers for the variable. > + // > + Variable =3D GetStartPointer (VariableStoreHeader); > + MaximumBufferSize =3D sizeof (VARIABLE_STORE_HEADER); > + > + while (IsValidVariableHeader (Variable, GetEndPointer (VariableStore= Header), > AuthFormat)) { > + NextVariable =3D GetNextVariablePtr (Variable, AuthFormat); > + if (((Variable->State =3D=3D VAR_ADDED) || (Variable->State =3D=3D > (VAR_IN_DELETED_TRANSITION & VAR_ADDED))) && > + (Variable !=3D UpdatingVariable) && > + (Variable !=3D UpdatingInDeletedTransition) > + ) > + { > + VariableSize =3D (UINTN)NextVariable - (UINTN)Variable; > + MaximumBufferSize +=3D VariableSize; > + } > + > + Variable =3D NextVariable; > + } > + > + if (NewVariable !=3D NULL) { > + // > + // Add the new variable size. > + // > + MaximumBufferSize +=3D NewVariableSize; > + } > + > + // > + // Reserve the 1 Bytes with Oxff to identify the > + // end of the variable buffer. > + // > + MaximumBufferSize +=3D 1; > + ValidBuffer =3D AllocatePool (MaximumBufferSize); > + if (ValidBuffer =3D=3D NULL) { > + return EFI_OUT_OF_RESOURCES; > + } > + } else { > + // > + // For NV variable reclaim, don't allocate pool here and just use > mNvVariableCache > + // as the buffer to reduce SMRAM consumption for SMM variable driver= . > + // > + MaximumBufferSize =3D mNvVariableCache->Size; > + ValidBuffer =3D (UINT8 *)mNvVariableCache; > + } > + > + SetMem (ValidBuffer, MaximumBufferSize, 0xff); > + > + // > + // Copy variable store header. > + // > + CopyMem (ValidBuffer, VariableStoreHeader, sizeof > (VARIABLE_STORE_HEADER)); > + CurrPtr =3D (UINT8 *)GetStartPointer ((VARIABLE_STORE_HEADER *)ValidBu= ffer); > + > + // > + // Reinstall all ADDED variables as long as they are not identical to = Updating > Variable. > + // > + Variable =3D GetStartPointer (VariableStoreHeader); > + while (IsValidVariableHeader (Variable, GetEndPointer (VariableStoreHe= ader), > AuthFormat)) { > + NextVariable =3D GetNextVariablePtr (Variable, AuthFormat); > + if ((Variable !=3D UpdatingVariable) && (Variable->State =3D=3D VAR_= ADDED)) { > + VariableSize =3D (UINTN)NextVariable - (UINTN)Variable; > + CopyMem (CurrPtr, (UINT8 *)Variable, VariableSize); > + if (!IsVolatile) { > + (VOID)ProtectedVariableLibRefresh ( > + (VARIABLE_HEADER *)CurrPtr, > + VariableSize, > + (UINTN)CurrPtr - (UINTN)ValidBuffer, > + FALSE > + ); > + > + if ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) > + =3D=3D EFI_VARIABLE_HARDWARE_ERROR_RECORD) > + { > + HwErrVariableTotalSize +=3D VariableSize; > + } else { > + CommonVariableTotalSize +=3D VariableSize; > + if (IsUserVariable (Variable)) { > + CommonUserVariableTotalSize +=3D VariableSize; > + } > + } > + } > + > + CurrPtr +=3D VariableSize; > + } > + > + Variable =3D NextVariable; > + } > + > + // > + // Reinstall all in delete transition variables. > + // > + Variable =3D GetStartPointer (VariableStoreHeader); > + while (IsValidVariableHeader (Variable, GetEndPointer (VariableStoreHe= ader), > AuthFormat)) { > + NextVariable =3D GetNextVariablePtr (Variable, AuthFormat); > + if ((Variable !=3D UpdatingVariable) && (Variable !=3D > UpdatingInDeletedTransition) && (Variable->State =3D=3D > (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) && > + (ProtectedVariableLibIsHmac (GetVariableNamePtr (Variable, AuthF= ormat)) > =3D=3D FALSE)) > + { > + FoundAdded =3D FALSE; > + AddedVariable =3D GetStartPointer ((VARIABLE_STORE_HEADER *)ValidB= uffer); > + while (IsValidVariableHeader (AddedVariable, GetEndPointer > ((VARIABLE_STORE_HEADER *)ValidBuffer), AuthFormat)) { > + NextAddedVariable =3D GetNextVariablePtr (AddedVariable, AuthFor= mat); > + NameSize =3D NameSizeOfVariable (AddedVariable, AuthFor= mat); > + if (CompareGuid ( > + GetVendorGuidPtr (AddedVariable, AuthFormat), > + GetVendorGuidPtr (Variable, AuthFormat) > + ) && (NameSize =3D=3D NameSizeOfVariable (Variable, AuthFo= rmat))) > + { > + Point0 =3D (VOID *)GetVariableNamePtr (AddedVariable, AuthForm= at); > + Point1 =3D (VOID *)GetVariableNamePtr (Variable, AuthFormat); > + if (CompareMem (Point0, Point1, NameSize) =3D=3D 0) { > + FoundAdded =3D TRUE; > + break; > + } > + } > + > + AddedVariable =3D NextAddedVariable; > + } > + > + if (!FoundAdded) { > + // > + // Promote VAR_IN_DELETED_TRANSITION to VAR_ADDED. > + // > + VariableSize =3D (UINTN)NextVariable - (UINTN)Variable; > + CopyMem (CurrPtr, (UINT8 *)Variable, VariableSize); > + ((VARIABLE_HEADER *)CurrPtr)->State =3D VAR_ADDED; > + if (!IsVolatile) { > + (VOID)ProtectedVariableLibRefresh ( > + (VARIABLE_HEADER *)CurrPtr, > + VariableSize, > + (UINTN)CurrPtr - (UINTN)ValidBuffer, > + FALSE > + ); > + > + if ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD= ) > + =3D=3D EFI_VARIABLE_HARDWARE_ERROR_RECORD) > + { > + HwErrVariableTotalSize +=3D VariableSize; > + } else { > + CommonVariableTotalSize +=3D VariableSize; > + if (IsUserVariable (Variable)) { > + CommonUserVariableTotalSize +=3D VariableSize; > + } > + } > + } > + > + CurrPtr +=3D VariableSize; > + } > + } > + > + Variable =3D NextVariable; > + } > + > + // > + // Install the new variable if it is not NULL. > + // > + if (NewVariable !=3D NULL) { > + if (((UINTN)CurrPtr - (UINTN)ValidBuffer) + NewVariableSize > > VariableStoreHeader->Size) { > + // > + // No enough space to store the new variable. > + // > + Status =3D EFI_OUT_OF_RESOURCES; > + goto Done; > + } > + > + if (!IsVolatile) { > + if ((NewVariable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) > =3D=3D EFI_VARIABLE_HARDWARE_ERROR_RECORD) { > + HwErrVariableTotalSize +=3D NewVariableSize; > + } else if ((NewVariable->Attributes & > EFI_VARIABLE_HARDWARE_ERROR_RECORD) !=3D > EFI_VARIABLE_HARDWARE_ERROR_RECORD) { > + CommonVariableTotalSize +=3D NewVariableSize; > + if (IsUserVariable (NewVariable)) { > + CommonUserVariableTotalSize +=3D NewVariableSize; > + } > + } > + > + if ((HwErrVariableTotalSize > PcdGet32 (PcdHwErrStorageSize)) || > + (CommonVariableTotalSize > mVariableModuleGlobal- > >CommonVariableSpace) || > + (CommonUserVariableTotalSize > mVariableModuleGlobal- > >CommonMaxUserVariableSpace)) > + { > + // > + // No enough space to store the new variable by NV or NV+HR attr= ibute. > + // > + Status =3D EFI_OUT_OF_RESOURCES; > + goto Done; > + } > + } > + > + CopyMem (CurrPtr, (UINT8 *)NewVariable, NewVariableSize); > + ((VARIABLE_HEADER *)CurrPtr)->State =3D VAR_ADDED; > + if (UpdatingVariable !=3D NULL) { > + UpdatingPtrTrack->CurrPtr =3D (VARIABLE_HEADER > *)((UINTN)UpdatingPtrTrack->StartPtr + ((UINTN)CurrPtr - > (UINTN)GetStartPointer ((VARIABLE_STORE_HEADER *)ValidBuffer))); > + UpdatingPtrTrack->InDeletedTransitionPtr =3D NULL; > + } > + > + CurrPtr +=3D NewVariableSize; > + } > + > + if (IsVolatile || mVariableModuleGlobal->VariableGlobal.EmuNvMode) { > + // > + // If volatile/emulated non-volatile variable store, just copy valid= buffer. > + // > + SetMem ((UINT8 *)(UINTN)VariableBase, VariableStoreHeader->Size, 0xf= f); > + CopyMem ((UINT8 *)(UINTN)VariableBase, ValidBuffer, (UINTN)CurrPtr - > (UINTN)ValidBuffer); > + *LastVariableOffset =3D (UINTN)CurrPtr - (UINTN)ValidBuffer; > + if (!IsVolatile) { > + // > + // Emulated non-volatile variable mode. > + // > + mVariableModuleGlobal->HwErrVariableTotalSize =3D > HwErrVariableTotalSize; > + mVariableModuleGlobal->CommonVariableTotalSize =3D > CommonVariableTotalSize; > + mVariableModuleGlobal->CommonUserVariableTotalSize =3D > CommonUserVariableTotalSize; > + } > + > + Status =3D EFI_SUCCESS; > + } else { > + // > + // If non-volatile variable store, perform FTW here. > + // > + Status =3D FtwVariableSpace ( > + VariableBase, > + (VARIABLE_STORE_HEADER *)ValidBuffer > + ); > + if (!EFI_ERROR (Status)) { > + *LastVariableOffset =3D (UINTN)Curr= Ptr - (UINTN)ValidBuffer; > + mVariableModuleGlobal->HwErrVariableTotalSize =3D > HwErrVariableTotalSize; > + mVariableModuleGlobal->CommonVariableTotalSize =3D > CommonVariableTotalSize; > + mVariableModuleGlobal->CommonUserVariableTotalSize =3D > CommonUserVariableTotalSize; > + } else { > + mVariableModuleGlobal->HwErrVariableTotalSize =3D 0; > + mVariableModuleGlobal->CommonVariableTotalSize =3D 0; > + mVariableModuleGlobal->CommonUserVariableTotalSize =3D 0; > + Variable =3D GetStartPoi= nter > ((VARIABLE_STORE_HEADER *)(UINTN)VariableBase); > + while (IsValidVariableHeader (Variable, GetEndPointer > ((VARIABLE_STORE_HEADER *)(UINTN)VariableBase), AuthFormat)) { > + NextVariable =3D GetNextVariablePtr (Variable, AuthFormat); > + VariableSize =3D (UINTN)NextVariable - (UINTN)Variable; > + if ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) > =3D=3D EFI_VARIABLE_HARDWARE_ERROR_RECORD) { > + mVariableModuleGlobal->HwErrVariableTotalSize +=3D VariableSiz= e; > + } else if ((Variable->Attributes & > EFI_VARIABLE_HARDWARE_ERROR_RECORD) !=3D > EFI_VARIABLE_HARDWARE_ERROR_RECORD) { > + mVariableModuleGlobal->CommonVariableTotalSize +=3D VariableSi= ze; > + if (IsUserVariable (Variable)) { > + mVariableModuleGlobal->CommonUserVariableTotalSize +=3D > VariableSize; > + } > + } > + > + Variable =3D NextVariable; > + } > + > + *LastVariableOffset =3D (UINTN)Variable - (UINTN)VariableBase; > + } > + } > + > +Done: > + DoneStatus =3D EFI_SUCCESS; > + if (IsVolatile || mVariableModuleGlobal->VariableGlobal.EmuNvMode) { > + DoneStatus =3D SynchronizeRuntimeVariableCache ( > + &mVariableModuleGlobal- > >VariableGlobal.VariableRuntimeCacheContext.VariableRuntimeVolatileCache, > + 0, > + VariableStoreHeader->Size > + ); > + ASSERT_EFI_ERROR (DoneStatus); > + FreePool (ValidBuffer); > + } else { > + // > + // For NV variable reclaim, we use mNvVariableCache as the buffer, s= o copy > the data back. > + // > + CopyMem (mNvVariableCache, (UINT8 *)(UINTN)VariableBase, > VariableStoreHeader->Size); > + DoneStatus =3D SynchronizeRuntimeVariableCache ( > + &mVariableModuleGlobal- > >VariableGlobal.VariableRuntimeCacheContext.VariableRuntimeNvCache, > + 0, > + VariableStoreHeader->Size > + ); > + ASSERT_EFI_ERROR (DoneStatus); > + } > + > + if (!EFI_ERROR (Status) && EFI_ERROR (DoneStatus)) { > + Status =3D DoneStatus; > + } > + > + return Status; > +} > diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c > b/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c > index 6c1a3440ac8c..6e86099eb72b 100644 > --- a/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c > +++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c > @@ -16,7 +16,7 @@ > VariableServiceSetVariable() should also check authenticate data to av= oid > buffer overflow, > integer overflow. It should also check attribute to avoid authenticati= on bypass. >=20 > -Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.
> +Copyright (c) 2006 - 2022, Intel Corporation. All rights reserved.
> (C) Copyright 2015-2018 Hewlett Packard Enterprise Development LP
> Copyright (c) Microsoft Corporation.
> Copyright (c) 2022, ARM Limited. All rights reserved.
> @@ -30,7 +30,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent > #include "VariableParsing.h" > #include "VariableRuntimeCache.h" >=20 > -VARIABLE_MODULE_GLOBAL *mVariableModuleGlobal; > +VARIABLE_MODULE_GLOBAL *mVariableModuleGlobal =3D NULL; >=20 > /// > /// Define a memory cache that improves the search performance for a var= iable. > @@ -458,7 +458,7 @@ CalculateCommonUserVariableTotalSize ( > // > if (mEndOfDxe && (mVariableModuleGlobal- > >CommonMaxUserVariableSpace !=3D mVariableModuleGlobal- > >CommonVariableSpace)) { > Variable =3D GetStartPointer (mNvVariableCache); > - while (IsValidVariableHeader (Variable, GetEndPointer (mNvVariableCa= che))) { > + while (IsValidVariableHeader (Variable, GetEndPointer (mNvVariableCa= che), > mVariableModuleGlobal->VariableGlobal.AuthFormat)) { > NextVariable =3D GetNextVariablePtr (Variable, mVariableModuleGlob= al- > >VariableGlobal.AuthFormat); > VariableSize =3D (UINTN)NextVariable - (UINTN)Variable; > if ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != =3D > EFI_VARIABLE_HARDWARE_ERROR_RECORD) { > @@ -497,330 +497,6 @@ InitializeVariableQuota ( > CalculateCommonUserVariableTotalSize (); > } >=20 > -/** > - > - Variable store garbage collection and reclaim operation. > - > - @param[in] VariableBase Base address of variable store= . > - @param[out] LastVariableOffset Offset of last variable. > - @param[in] IsVolatile The variable store is volatile= or not; > - if it is non-volatile, need FT= W. > - @param[in, out] UpdatingPtrTrack Pointer to updating variable p= ointer > track structure. > - @param[in] NewVariable Pointer to new variable. > - @param[in] NewVariableSize New variable size. > - > - @return EFI_SUCCESS Reclaim operation has finished su= ccessfully. > - @return EFI_OUT_OF_RESOURCES No enough memory resources or > variable space. > - @return Others Unexpect error happened during re= claim > operation. > - > -**/ > -EFI_STATUS > -Reclaim ( > - IN EFI_PHYSICAL_ADDRESS VariableBase, > - OUT UINTN *LastVariableOffset, > - IN BOOLEAN IsVolatile, > - IN OUT VARIABLE_POINTER_TRACK *UpdatingPtrTrack, > - IN VARIABLE_HEADER *NewVariable, > - IN UINTN NewVariableSize > - ) > -{ > - VARIABLE_HEADER *Variable; > - VARIABLE_HEADER *AddedVariable; > - VARIABLE_HEADER *NextVariable; > - VARIABLE_HEADER *NextAddedVariable; > - VARIABLE_STORE_HEADER *VariableStoreHeader; > - UINT8 *ValidBuffer; > - UINTN MaximumBufferSize; > - UINTN VariableSize; > - UINTN NameSize; > - UINT8 *CurrPtr; > - VOID *Point0; > - VOID *Point1; > - BOOLEAN FoundAdded; > - EFI_STATUS Status; > - EFI_STATUS DoneStatus; > - UINTN CommonVariableTotalSize; > - UINTN CommonUserVariableTotalSize; > - UINTN HwErrVariableTotalSize; > - VARIABLE_HEADER *UpdatingVariable; > - VARIABLE_HEADER *UpdatingInDeletedTransition; > - BOOLEAN AuthFormat; > - > - AuthFormat =3D mVariableModuleGlobal->VariableGlobal.= AuthFormat; > - UpdatingVariable =3D NULL; > - UpdatingInDeletedTransition =3D NULL; > - if (UpdatingPtrTrack !=3D NULL) { > - UpdatingVariable =3D UpdatingPtrTrack->CurrPtr; > - UpdatingInDeletedTransition =3D UpdatingPtrTrack->InDeletedTransitio= nPtr; > - } > - > - VariableStoreHeader =3D (VARIABLE_STORE_HEADER *)((UINTN)VariableBase)= ; > - > - CommonVariableTotalSize =3D 0; > - CommonUserVariableTotalSize =3D 0; > - HwErrVariableTotalSize =3D 0; > - > - if (IsVolatile || mVariableModuleGlobal->VariableGlobal.EmuNvMode) { > - // > - // Start Pointers for the variable. > - // > - Variable =3D GetStartPointer (VariableStoreHeader); > - MaximumBufferSize =3D sizeof (VARIABLE_STORE_HEADER); > - > - while (IsValidVariableHeader (Variable, GetEndPointer (VariableStore= Header))) > { > - NextVariable =3D GetNextVariablePtr (Variable, AuthFormat); > - if (((Variable->State =3D=3D VAR_ADDED) || (Variable->State =3D=3D > (VAR_IN_DELETED_TRANSITION & VAR_ADDED))) && > - (Variable !=3D UpdatingVariable) && > - (Variable !=3D UpdatingInDeletedTransition) > - ) > - { > - VariableSize =3D (UINTN)NextVariable - (UINTN)Variable; > - MaximumBufferSize +=3D VariableSize; > - } > - > - Variable =3D NextVariable; > - } > - > - if (NewVariable !=3D NULL) { > - // > - // Add the new variable size. > - // > - MaximumBufferSize +=3D NewVariableSize; > - } > - > - // > - // Reserve the 1 Bytes with Oxff to identify the > - // end of the variable buffer. > - // > - MaximumBufferSize +=3D 1; > - ValidBuffer =3D AllocatePool (MaximumBufferSize); > - if (ValidBuffer =3D=3D NULL) { > - return EFI_OUT_OF_RESOURCES; > - } > - } else { > - // > - // For NV variable reclaim, don't allocate pool here and just use > mNvVariableCache > - // as the buffer to reduce SMRAM consumption for SMM variable driver= . > - // > - MaximumBufferSize =3D mNvVariableCache->Size; > - ValidBuffer =3D (UINT8 *)mNvVariableCache; > - } > - > - SetMem (ValidBuffer, MaximumBufferSize, 0xff); > - > - // > - // Copy variable store header. > - // > - CopyMem (ValidBuffer, VariableStoreHeader, sizeof > (VARIABLE_STORE_HEADER)); > - CurrPtr =3D (UINT8 *)GetStartPointer ((VARIABLE_STORE_HEADER *)ValidBu= ffer); > - > - // > - // Reinstall all ADDED variables as long as they are not identical to = Updating > Variable. > - // > - Variable =3D GetStartPointer (VariableStoreHeader); > - while (IsValidVariableHeader (Variable, GetEndPointer (VariableStoreHe= ader))) > { > - NextVariable =3D GetNextVariablePtr (Variable, AuthFormat); > - if ((Variable !=3D UpdatingVariable) && (Variable->State =3D=3D VAR_= ADDED)) { > - VariableSize =3D (UINTN)NextVariable - (UINTN)Variable; > - CopyMem (CurrPtr, (UINT8 *)Variable, VariableSize); > - CurrPtr +=3D VariableSize; > - if ((!IsVolatile) && ((Variable->Attributes & > EFI_VARIABLE_HARDWARE_ERROR_RECORD) =3D=3D > EFI_VARIABLE_HARDWARE_ERROR_RECORD)) { > - HwErrVariableTotalSize +=3D VariableSize; > - } else if ((!IsVolatile) && ((Variable->Attributes & > EFI_VARIABLE_HARDWARE_ERROR_RECORD) !=3D > EFI_VARIABLE_HARDWARE_ERROR_RECORD)) { > - CommonVariableTotalSize +=3D VariableSize; > - if (IsUserVariable (Variable)) { > - CommonUserVariableTotalSize +=3D VariableSize; > - } > - } > - } > - > - Variable =3D NextVariable; > - } > - > - // > - // Reinstall all in delete transition variables. > - // > - Variable =3D GetStartPointer (VariableStoreHeader); > - while (IsValidVariableHeader (Variable, GetEndPointer (VariableStoreHe= ader))) > { > - NextVariable =3D GetNextVariablePtr (Variable, AuthFormat); > - if ((Variable !=3D UpdatingVariable) && (Variable !=3D > UpdatingInDeletedTransition) && (Variable->State =3D=3D > (VAR_IN_DELETED_TRANSITION & VAR_ADDED))) { > - // > - // Buffer has cached all ADDED variable. > - // Per IN_DELETED variable, we have to guarantee that > - // no ADDED one in previous buffer. > - // > - > - FoundAdded =3D FALSE; > - AddedVariable =3D GetStartPointer ((VARIABLE_STORE_HEADER *)ValidB= uffer); > - while (IsValidVariableHeader (AddedVariable, GetEndPointer > ((VARIABLE_STORE_HEADER *)ValidBuffer))) { > - NextAddedVariable =3D GetNextVariablePtr (AddedVariable, AuthFor= mat); > - NameSize =3D NameSizeOfVariable (AddedVariable, AuthFor= mat); > - if (CompareGuid ( > - GetVendorGuidPtr (AddedVariable, AuthFormat), > - GetVendorGuidPtr (Variable, AuthFormat) > - ) && (NameSize =3D=3D NameSizeOfVariable (Variable, AuthFo= rmat))) > - { > - Point0 =3D (VOID *)GetVariableNamePtr (AddedVariable, AuthForm= at); > - Point1 =3D (VOID *)GetVariableNamePtr (Variable, AuthFormat); > - if (CompareMem (Point0, Point1, NameSize) =3D=3D 0) { > - FoundAdded =3D TRUE; > - break; > - } > - } > - > - AddedVariable =3D NextAddedVariable; > - } > - > - if (!FoundAdded) { > - // > - // Promote VAR_IN_DELETED_TRANSITION to VAR_ADDED. > - // > - VariableSize =3D (UINTN)NextVariable - (UINTN)Variable; > - CopyMem (CurrPtr, (UINT8 *)Variable, VariableSize); > - ((VARIABLE_HEADER *)CurrPtr)->State =3D VAR_ADDED; > - CurrPtr +=3D VariableSize; > - if ((!IsVolatile) && ((Variable->Attributes & > EFI_VARIABLE_HARDWARE_ERROR_RECORD) =3D=3D > EFI_VARIABLE_HARDWARE_ERROR_RECORD)) { > - HwErrVariableTotalSize +=3D VariableSize; > - } else if ((!IsVolatile) && ((Variable->Attributes & > EFI_VARIABLE_HARDWARE_ERROR_RECORD) !=3D > EFI_VARIABLE_HARDWARE_ERROR_RECORD)) { > - CommonVariableTotalSize +=3D VariableSize; > - if (IsUserVariable (Variable)) { > - CommonUserVariableTotalSize +=3D VariableSize; > - } > - } > - } > - } > - > - Variable =3D NextVariable; > - } > - > - // > - // Install the new variable if it is not NULL. > - // > - if (NewVariable !=3D NULL) { > - if (((UINTN)CurrPtr - (UINTN)ValidBuffer) + NewVariableSize > > VariableStoreHeader->Size) { > - // > - // No enough space to store the new variable. > - // > - Status =3D EFI_OUT_OF_RESOURCES; > - goto Done; > - } > - > - if (!IsVolatile) { > - if ((NewVariable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) > =3D=3D EFI_VARIABLE_HARDWARE_ERROR_RECORD) { > - HwErrVariableTotalSize +=3D NewVariableSize; > - } else if ((NewVariable->Attributes & > EFI_VARIABLE_HARDWARE_ERROR_RECORD) !=3D > EFI_VARIABLE_HARDWARE_ERROR_RECORD) { > - CommonVariableTotalSize +=3D NewVariableSize; > - if (IsUserVariable (NewVariable)) { > - CommonUserVariableTotalSize +=3D NewVariableSize; > - } > - } > - > - if ((HwErrVariableTotalSize > PcdGet32 (PcdHwErrStorageSize)) || > - (CommonVariableTotalSize > mVariableModuleGlobal- > >CommonVariableSpace) || > - (CommonUserVariableTotalSize > mVariableModuleGlobal- > >CommonMaxUserVariableSpace)) > - { > - // > - // No enough space to store the new variable by NV or NV+HR attr= ibute. > - // > - Status =3D EFI_OUT_OF_RESOURCES; > - goto Done; > - } > - } > - > - CopyMem (CurrPtr, (UINT8 *)NewVariable, NewVariableSize); > - ((VARIABLE_HEADER *)CurrPtr)->State =3D VAR_ADDED; > - if (UpdatingVariable !=3D NULL) { > - UpdatingPtrTrack->CurrPtr =3D (VARIABLE_HEADER > *)((UINTN)UpdatingPtrTrack->StartPtr + ((UINTN)CurrPtr - > (UINTN)GetStartPointer ((VARIABLE_STORE_HEADER *)ValidBuffer))); > - UpdatingPtrTrack->InDeletedTransitionPtr =3D NULL; > - } > - > - CurrPtr +=3D NewVariableSize; > - } > - > - if (IsVolatile || mVariableModuleGlobal->VariableGlobal.EmuNvMode) { > - // > - // If volatile/emulated non-volatile variable store, just copy valid= buffer. > - // > - SetMem ((UINT8 *)(UINTN)VariableBase, VariableStoreHeader->Size, 0xf= f); > - CopyMem ((UINT8 *)(UINTN)VariableBase, ValidBuffer, (UINTN)CurrPtr - > (UINTN)ValidBuffer); > - *LastVariableOffset =3D (UINTN)CurrPtr - (UINTN)ValidBuffer; > - if (!IsVolatile) { > - // > - // Emulated non-volatile variable mode. > - // > - mVariableModuleGlobal->HwErrVariableTotalSize =3D > HwErrVariableTotalSize; > - mVariableModuleGlobal->CommonVariableTotalSize =3D > CommonVariableTotalSize; > - mVariableModuleGlobal->CommonUserVariableTotalSize =3D > CommonUserVariableTotalSize; > - } > - > - Status =3D EFI_SUCCESS; > - } else { > - // > - // If non-volatile variable store, perform FTW here. > - // > - Status =3D FtwVariableSpace ( > - VariableBase, > - (VARIABLE_STORE_HEADER *)ValidBuffer > - ); > - if (!EFI_ERROR (Status)) { > - *LastVariableOffset =3D (UINTN)Curr= Ptr - (UINTN)ValidBuffer; > - mVariableModuleGlobal->HwErrVariableTotalSize =3D > HwErrVariableTotalSize; > - mVariableModuleGlobal->CommonVariableTotalSize =3D > CommonVariableTotalSize; > - mVariableModuleGlobal->CommonUserVariableTotalSize =3D > CommonUserVariableTotalSize; > - } else { > - mVariableModuleGlobal->HwErrVariableTotalSize =3D 0; > - mVariableModuleGlobal->CommonVariableTotalSize =3D 0; > - mVariableModuleGlobal->CommonUserVariableTotalSize =3D 0; > - Variable =3D GetStartPoi= nter > ((VARIABLE_STORE_HEADER *)(UINTN)VariableBase); > - while (IsValidVariableHeader (Variable, GetEndPointer > ((VARIABLE_STORE_HEADER *)(UINTN)VariableBase))) { > - NextVariable =3D GetNextVariablePtr (Variable, AuthFormat); > - VariableSize =3D (UINTN)NextVariable - (UINTN)Variable; > - if ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) = =3D=3D > EFI_VARIABLE_HARDWARE_ERROR_RECORD) { > - mVariableModuleGlobal->HwErrVariableTotalSize +=3D VariableSiz= e; > - } else if ((Variable->Attributes & > EFI_VARIABLE_HARDWARE_ERROR_RECORD) !=3D > EFI_VARIABLE_HARDWARE_ERROR_RECORD) { > - mVariableModuleGlobal->CommonVariableTotalSize +=3D VariableSi= ze; > - if (IsUserVariable (Variable)) { > - mVariableModuleGlobal->CommonUserVariableTotalSize +=3D Vari= ableSize; > - } > - } > - > - Variable =3D NextVariable; > - } > - > - *LastVariableOffset =3D (UINTN)Variable - (UINTN)VariableBase; > - } > - } > - > -Done: > - DoneStatus =3D EFI_SUCCESS; > - if (IsVolatile || mVariableModuleGlobal->VariableGlobal.EmuNvMode) { > - DoneStatus =3D SynchronizeRuntimeVariableCache ( > - &mVariableModuleGlobal- > >VariableGlobal.VariableRuntimeCacheContext.VariableRuntimeVolatileCache, > - 0, > - VariableStoreHeader->Size > - ); > - ASSERT_EFI_ERROR (DoneStatus); > - FreePool (ValidBuffer); > - } else { > - // > - // For NV variable reclaim, we use mNvVariableCache as the buffer, s= o copy > the data back. > - // > - CopyMem (mNvVariableCache, (UINT8 *)(UINTN)VariableBase, > VariableStoreHeader->Size); > - DoneStatus =3D SynchronizeRuntimeVariableCache ( > - &mVariableModuleGlobal- > >VariableGlobal.VariableRuntimeCacheContext.VariableRuntimeNvCache, > - 0, > - VariableStoreHeader->Size > - ); > - ASSERT_EFI_ERROR (DoneStatus); > - } > - > - if (!EFI_ERROR (Status) && EFI_ERROR (DoneStatus)) { > - Status =3D DoneStatus; > - } > - > - return Status; > -} > - > /** > Finds variable in storage blocks of volatile and non-volatile storage = areas. >=20 > @@ -1657,9 +1333,665 @@ AutoUpdateLangVariable ( > } >=20 > /** > - Update the variable region with Variable information. If > EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS is set, > - index of associated public key is needed. > + Check if there's enough free space in storage to write the new variabl= e. >=20 > + @param[in] NewVariable Pointer to buffer of new variable. > + @param[in] VariableSize Size of new variable. > + @param[in] VariableName Name of variable. > + @param[in] VendorGuid Guid of variable. > + @param[in] Attributes Attributes of the variable. > + @param[in] VolatileFlag Volatile/non-volatile variable indicator= . > + > + @retval EFI_SUCCESS Enough free space on variable storage. > + @retval EFI_BUFFER_TOO_SMALL There's not enough continuous free space= . > + @retval EFI_OUT_OF_RESOURCES There's not enough free space in total. > +**/ > +EFI_STATUS > +CheckVariableStoreSpace ( > + IN VARIABLE_HEADER *NewVariable, > + IN UINTN VariableSize, > + IN CHAR16 *VariableName, > + IN EFI_GUID *VendorGuid, > + IN UINT32 Attributes, > + IN BOOLEAN VolatileFlag > + ) > +{ > + BOOLEAN IsCommonVariable; > + BOOLEAN IsCommonUserVariable; > + UINTN CommonVariableTotalSize; > + UINTN CommonUserVariableTotalSize; > + UINTN HwErrVariableTotalSize; > + VARIABLE_STORE_HEADER *VarStore; > + > + if ((NewVariable =3D=3D NULL) || (VariableSize =3D=3D 0)) { > + return EFI_SUCCESS; > + } > + > + if (VolatileFlag) { > + VarStore =3D (VARIABLE_STORE_HEADER *)(UINTN) > + mVariableModuleGlobal->VariableGlobal.VolatileVariableBas= e; > + if ((UINT32)(VariableSize + mVariableModuleGlobal- > >VolatileLastVariableOffset) > + > VarStore->Size) > + { > + return EFI_BUFFER_TOO_SMALL; > + } > + } else { > + if ((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) =3D=3D 0) { > + IsCommonVariable =3D TRUE; > + IsCommonUserVariable =3D IsUserVariable (NewVariable); > + } else { > + IsCommonVariable =3D FALSE; > + IsCommonUserVariable =3D FALSE; > + } > + > + CommonVariableTotalSize =3D mVariableModuleGlobal- > >CommonVariableTotalSize + VariableSize; > + CommonUserVariableTotalSize =3D mVariableModuleGlobal- > >CommonUserVariableTotalSize + VariableSize; > + HwErrVariableTotalSize =3D mVariableModuleGlobal- > >HwErrVariableTotalSize + VariableSize; > + > + if ( (((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) !=3D 0) && > + (HwErrVariableTotalSize > PcdGet32 (PcdHwErrStorageSize))) > + || (IsCommonVariable && (CommonVariableTotalSize > > mVariableModuleGlobal->CommonVariableSpace)) > + || (IsCommonVariable && > + AtRuntime () && > + (CommonVariableTotalSize > mVariableModuleGlobal- > >CommonRuntimeVariableSpace)) > + || (IsCommonUserVariable && > + (CommonUserVariableTotalSize > mVariableModuleGlobal- > >CommonMaxUserVariableSpace))) > + { > + if (AtRuntime ()) { > + if (IsCommonUserVariable && > + ((VariableSize + mVariableModuleGlobal- > >CommonUserVariableTotalSize) > + > mVariableModuleGlobal->CommonMaxUserVariableSpace)) > + { > + RecordVarErrorFlag ( > + VAR_ERROR_FLAG_USER_ERROR, > + VariableName, > + VendorGuid, > + Attributes, > + VariableSize > + ); > + } > + > + if (IsCommonVariable && > + ((VariableSize + mVariableModuleGlobal->CommonVariableTotalS= ize) > + > mVariableModuleGlobal->CommonRuntimeVariableSpace)) > + { > + RecordVarErrorFlag ( > + VAR_ERROR_FLAG_SYSTEM_ERROR, > + VariableName, > + VendorGuid, > + Attributes, > + VariableSize > + ); > + } > + > + return EFI_OUT_OF_RESOURCES; > + } > + > + return EFI_BUFFER_TOO_SMALL; > + } > + } > + > + return EFI_SUCCESS; > +} > + > +/** > + Fill specific data of auth-variable in buffer. > + > + @param[in,out] NewVariable Pointer to buffer of new variable. > + @param[in] OldVariable Pointer to buffer of old copy of th= e variable. > + @param[in] Attributes Attributes of the variable. > + @param[in] KeyIndex Index of associated public key. > + @param[in] MonotonicCount Value of associated monotonic count= . > + @param[in] TimeStamp Value of associated TimeStamp. > + > +**/ > +VOID > +SetVariableAuthData ( > + IN OUT AUTHENTICATED_VARIABLE_HEADER *NewVariable, > + IN AUTHENTICATED_VARIABLE_HEADER *OldVariable, > + IN UINT32 Attributes, > + IN UINT32 KeyIndex, > + IN UINT64 MonotonicCount, > + IN EFI_TIME *TimeStamp > + ) > +{ > + NewVariable->PubKeyIndex =3D KeyIndex; > + NewVariable->MonotonicCount =3D MonotonicCount; > + > + if ((TimeStamp !=3D NULL) && > + ((Attributes & > EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) !=3D 0)) > + { > + // > + // In the case when the EFI_VARIABLE_APPEND_WRITE attribute is set, = only > + // when the new TimeStamp value is later than the current timestamp > associated > + // with the variable, we need associate the new timestamp with the u= pdated > value. > + // > + if (((Attributes & EFI_VARIABLE_APPEND_WRITE) !=3D 0) && > + (OldVariable !=3D NULL) && > + !VariableCompareTimeStampInternal (&OldVariable->TimeStamp, > TimeStamp)) > + { > + TimeStamp =3D &OldVariable->TimeStamp; > + } > + > + CopyMem (&NewVariable->TimeStamp, TimeStamp, sizeof (EFI_TIME)); > + } else { > + ZeroMem (&NewVariable->TimeStamp, sizeof (EFI_TIME)); > + } > +} > + > +/** > + Fill the variable data buffer according to variable format on storage. > + > + @param[in,out] NewVariable Pointer to buffer of new variable. > + @param[in] OldVariable Pointer to buffer of old copy of th= e variable. > + @param[in] VariableName Name of variable. > + @param[in] VendorGuid Guid of variable. > + @param[in] Data Variable data. > + @param[in] DataSize Size of data. 0 means delete. > + @param[in] Attributes Attributes of the variable. > + @param[in] KeyIndex Index of associated public key. > + @param[in] MonotonicCount Value of associated monotonic count= . > + @param[in] TimeStamp Value of associated TimeStamp. > + > + @retval Size of the new variable. > + > +**/ > +UINTN > +SetVariableData ( > + IN OUT VARIABLE_HEADER *NewVariable, > + IN VARIABLE_HEADER *OldVariable, > + IN CHAR16 *VariableName, > + IN EFI_GUID *VendorGuid, > + IN VOID *Data, > + IN UINTN DataSize, > + IN UINT32 Attributes, > + IN UINT32 KeyIndex, > + IN UINT64 MonotonicCount, > + IN EFI_TIME *TimeStamp > + ) > +{ > + EFI_STATUS Status; > + BOOLEAN AuthFormat; > + UINT8 *DataPtr; > + UINTN NameSize; > + UINTN OldDataSize; > + > + AuthFormat =3D mVariableModuleGlobal->VariableGlobal.AuthFormat; > + > + if (AuthFormat) { > + SetVariableAuthData ( > + (AUTHENTICATED_VARIABLE_HEADER *)NewVariable, > + (AUTHENTICATED_VARIABLE_HEADER *)OldVariable, > + Attributes, > + KeyIndex, > + MonotonicCount, > + TimeStamp > + ); > + } > + > + NewVariable->StartId =3D VARIABLE_DATA; > + NewVariable->State =3D VAR_ADDED; > + NewVariable->Reserved =3D 0; > + NewVariable->Attributes =3D Attributes & (~EFI_VARIABLE_APPEND_WRITE); > + > + CopyMem ( > + GetVendorGuidPtr (NewVariable, AuthFormat), > + VendorGuid, > + sizeof (EFI_GUID) > + ); > + > + NameSize =3D StrSize (VariableName); > + SetNameSizeOfVariable (NewVariable, NameSize, AuthFormat); > + CopyMem ( > + (UINT8 *)GetVariableNamePtr (NewVariable, AuthFormat), > + VariableName, > + NameSize > + ); > + > + // > + // Set data size first otherwise we can't get correct data pointer in = the > + // buffer of new variable. > + // > + SetDataSizeOfVariable (NewVariable, DataSize, AuthFormat); > + DataPtr =3D GetVariableDataPtr (NewVariable, AuthFormat); > + if (((Attributes & EFI_VARIABLE_APPEND_WRITE) !=3D 0) && > + (OldVariable !=3D NULL) && > + ((OldVariable->State =3D=3D VAR_ADDED) || > + (OldVariable->State =3D=3D (VAR_ADDED & VAR_IN_DELETED_TRANSITION= )))) > + { > + // > + // Get old data, which might be encrypted. > + // > + OldDataSize =3D mVariableModuleGlobal->ScratchBufferSize > + - ((UINTN)DataPtr - (UINTN)NewVariable); > + Status =3D ProtectedVariableLibGetByBuffer ( > + OldVariable, > + DataPtr, > + (UINT32 *)&OldDataSize, > + AuthFormat > + ); > + if (Status =3D=3D EFI_UNSUPPORTED) { > + OldDataSize =3D DataSizeOfVariable (OldVariable, AuthFormat); > + CopyMem (DataPtr, GetVariableDataPtr (OldVariable, AuthFormat), > OldDataSize); > + } else if (EFI_ERROR (Status)) { > + ASSERT_EFI_ERROR (Status); > + return 0; > + } > + > + DataPtr +=3D OldDataSize; > + // > + // Update data size. > + // > + SetDataSizeOfVariable (NewVariable, DataSize + OldDataSize, AuthForm= at); > + } > + > + CopyMem (DataPtr, Data, DataSize); > + > + // > + // The actual size of the variable stored in storage should include pa= dding. > + // > + return ((UINTN)GetNextVariablePtr (NewVariable, AuthFormat) - > (UINTN)NewVariable); > +} > + > +/** > + Update state of given variable as well as its cached copy. > + > + @param[in,out] Variable Pointer to the buffer of the variable. > + @param[in,out] CacheVariable Cache copy of the variable. > + @param[in] NewState New state value. > + @param[in] Volatile Volatile/non-volatile variable indicat= or. > + > + @retval EFI_SUCCESS Variable state was updated successfully. > + @retval Others Failed to update the variable state. > + > +**/ > +EFI_STATUS > +UpdateVariableState ( > + IN OUT VARIABLE_HEADER *Variable, > + IN OUT VARIABLE_HEADER *CacheVariable, > + IN UINT8 NewState, > + IN BOOLEAN Volatile > + ) > +{ > + EFI_STATUS Status; > + > + Status =3D UpdateVariableStore ( > + &mVariableModuleGlobal->VariableGlobal, > + Volatile, > + FALSE, > + mVariableModuleGlobal->FvbInstance, > + (UINTN)&Variable->State, > + sizeof (NewState), > + &NewState > + ); > + if (!EFI_ERROR (Status) && (CacheVariable !=3D NULL)) { > + CacheVariable->State =3D NewState; > + } > + > + return Status; > +} > + > +/** > + Flush variable data to variable storage. > + > + @param[in] VarStoreBase Base address of variable storage. > + @param[in,out] Offset Offset to write the variable from. > + Offset from where next variable can be= written. > + @param[in,out] NewVariable Pointer to the buffer of new variable. > + @param[in] VariableSize Size of new variable. > + @param[in] Volatile Volatile/non-volatile variable indicat= or. > + @param[in] AuthFormat Auth-variable indicator. > + > + @retval EFI_SUCCESS Variable(s) were written successfully. > + @retval Others Failed to write the variable data. > + > +**/ > +EFI_STATUS > +WriteVariable ( > + IN EFI_PHYSICAL_ADDRESS VarStoreBase, > + IN OUT UINTN *Offset, > + IN OUT VARIABLE_HEADER **NewVariable, > + IN UINT32 VariableSize, > + IN BOOLEAN Volatile, > + IN BOOLEAN AuthFormat > + ) > +{ > + EFI_STATUS Status; > + > + struct { > + UINTN Offset; > + UINT8 *Buffer; > + UINT32 Size; > + UINT8 State; > + } WriteSteps[4]; > + UINTN Index; > + UINTN Steps; > + VARIABLE_HEADER *Variable; > + > + Variable =3D *NewVariable; > + if (Volatile) { > + // > + // For non-volatile variable, one step only : > + // > + WriteSteps[0].Offset =3D *Offset; > + WriteSteps[0].Buffer =3D (UINT8 *)Variable; > + WriteSteps[0].Size =3D VariableSize; > + > + Steps =3D 1; > + } else { > + // > + // Four steps for non-volatile variable: > + // > + // 1. Write variable header > + // 2. Set variable state to header valid > + // 3. Write variable name and data > + // 4. Set variable state to valid > + // > + Variable->State =3D 0xff; > + WriteSteps[0].Offset =3D *Offset; > + WriteSteps[0].Buffer =3D (UINT8 *)Variable; > + WriteSteps[0].Size =3D (UINT32)GetVariableHeaderSize (AuthFormat); > + > + WriteSteps[1].State =3D VAR_HEADER_VALID_ONLY; > + WriteSteps[1].Offset =3D *Offset + OFFSET_OF (VARIABLE_HEADER, State= ); > + WriteSteps[1].Buffer =3D &WriteSteps[1].State; > + WriteSteps[1].Size =3D sizeof (Variable->State); > + > + WriteSteps[2].Offset =3D *Offset + GetVariableHeaderSize (AuthFormat= ); > + WriteSteps[2].Buffer =3D (UINT8 *)Variable + GetVariableHeaderSize > (AuthFormat); > + WriteSteps[2].Size =3D VariableSize - (UINT32)GetVariableHeaderSiz= e > (AuthFormat); > + > + WriteSteps[3].State =3D VAR_ADDED; > + WriteSteps[3].Offset =3D *Offset + OFFSET_OF (VARIABLE_HEADER, State= ); > + WriteSteps[3].Buffer =3D &WriteSteps[3].State; > + WriteSteps[3].Size =3D sizeof (Variable->State); > + > + Steps =3D ARRAY_SIZE (WriteSteps); > + } > + > + for (Index =3D 0; Index < Steps; ++Index) { > + Status =3D UpdateVariableStore ( > + &mVariableModuleGlobal->VariableGlobal, > + Volatile, > + TRUE, > + mVariableModuleGlobal->FvbInstance, > + WriteSteps[Index].Offset, > + WriteSteps[Index].Size, > + WriteSteps[Index].Buffer > + ); > + if (EFI_ERROR (Status)) { > + ASSERT_EFI_ERROR (Status); > + return Status; > + } > + } > + > + Variable->State =3D VAR_ADDED; > + if (!Volatile) { > + CopyMem ((UINT8 *)mNvVariableCache + *Offset, Variable, VariableSize= ); > + } > + > + *NewVariable =3D (VARIABLE_HEADER *)((UINTN)VarStoreBase + *Offset); > + *Offset +=3D HEADER_ALIGN (VariableSize); > + > + return EFI_SUCCESS; > +} > + > +/** > + Rebase the given variable pointer(s) to the equivalent one in given va= riable > + storage via VarStore. > + > + @param[in] InVarTrackPtr Pointer to current variable in cache= . > + @param[out] OutVarTrackPtr Pointer to rebased variable against = VarStore. > + @param[in] VarStore Start of variable storage to rebase = against. > + @param[in] VariableName Name of variable. > + @param[in] VendorGuid Guid of variable. > + @param[in] ByOffset If TRUE, don't do variable search in= VarStore. > + > + @retval EFI_SUCCESS Variable(s) were deleted successfully. > + @retval EFI_INVALID_PARAMETER Invalid parameters passed. > + @retval EFI_NOT_FOUND Given variable (VariableName & VendorGui= d) > was > + not found in VarStore, if ByOffset is FA= LSE. > + > +**/ > +EFI_STATUS > +RebaseVariablePtr ( > + IN VARIABLE_POINTER_TRACK *InVarTrackPtr, > + OUT VARIABLE_POINTER_TRACK *OutVarTrackPtr, > + IN VARIABLE_STORE_HEADER *VarStore, > + IN CHAR16 *VariableName, > + IN EFI_GUID *VendorGuid, > + IN BOOLEAN ByOffset > + ) > +{ > + EFI_STATUS Status; > + BOOLEAN AuthFormat; > + VARIABLE_HEADER *NewStart; > + > + if ((InVarTrackPtr =3D=3D NULL) || (OutVarTrackPtr =3D=3D NULL) || (Va= rStore =3D=3D > NULL)) { > + ASSERT (InVarTrackPtr !=3D NULL); > + ASSERT (OutVarTrackPtr !=3D NULL); > + ASSERT (VarStore !=3D NULL); > + return EFI_INVALID_PARAMETER; > + } > + > + AuthFormat =3D mVariableModuleGlobal->VariableGlobal.AuthFormat; > + > + if ( (InVarTrackPtr->CurrPtr =3D=3D NULL) > + || (InVarTrackPtr->StartPtr =3D=3D GetStartPointer (VarStore))) > + { > + CopyMem (OutVarTrackPtr, InVarTrackPtr, sizeof > (VARIABLE_POINTER_TRACK)); > + return EFI_SUCCESS; > + } > + > + NewStart =3D GetStartPointer (VarStore); > + if (ByOffset) { > + OutVarTrackPtr->CurrPtr =3D (VARIABLE_HEADER *) > + ((UINTN)NewStart + ((UINTN)InVarTrackPtr->= CurrPtr - > + (UINTN)InVarTrackPtr->= StartPtr)); > + > + if (InVarTrackPtr->InDeletedTransitionPtr !=3D NULL) { > + OutVarTrackPtr->InDeletedTransitionPtr =3D > + (VARIABLE_HEADER *)((UINTN)NewStart + > + ((UINTN)InVarTrackPtr->InDeletedTransitionPt= r - > + (UINTN)InVarTrackPtr->StartPtr)); > + } else { > + OutVarTrackPtr->InDeletedTransitionPtr =3D NULL; > + } > + > + OutVarTrackPtr->StartPtr =3D NewStart; > + OutVarTrackPtr->EndPtr =3D GetEndPointer (VarStore); > + } else { > + OutVarTrackPtr->StartPtr =3D NewStart; > + OutVarTrackPtr->EndPtr =3D GetEndPointer (VarStore); > + > + Status =3D FindVariableEx (VariableName, VendorGuid, FALSE, OutVarTr= ackPtr, > AuthFormat); > + if ((OutVarTrackPtr->CurrPtr =3D=3D NULL) || EFI_ERROR (Status)) { > + return EFI_NOT_FOUND; > + } > + } > + > + if ( (VarStore =3D=3D mNvVariableCache) > + || ((UINTN)VarStore =3D=3D (UINTN)mVariableModuleGlobal- > >VariableGlobal.NonVolatileVariableBase)) > + { > + OutVarTrackPtr->Volatile =3D FALSE; > + } > + > + return EFI_SUCCESS; > +} > + > +/** > + Check if the given variable is from HOB. > + > + @param[in] CacheVariable Pointer to current variable in cache. > + > + @retval TRUE The variable is from HOB. > + @retval FALSE The variable is NOT from HOB. > + > +**/ > +BOOLEAN > +IsHobVariable ( > + IN VARIABLE_POINTER_TRACK *CacheVariable > + ) > +{ > + VARIABLE_STORE_HEADER *HobVarStore; > + > + HobVarStore =3D (VARIABLE_STORE_HEADER *)(UINTN) > + mVariableModuleGlobal->VariableGlobal.HobVariableBase; > + return (CacheVariable->CurrPtr !=3D NULL && > + HobVarStore !=3D NULL && > + CacheVariable->StartPtr =3D=3D GetStartPointer (HobVarStore)); > +} > + > +/** > + Get temporary buffer for a new variable data. > + > + @retval Pointer to the buffer address. > + > +**/ > +VARIABLE_HEADER * > +GetNewVariableBuffer ( > + VOID > + ) > +{ > + VARIABLE_HEADER *NewVariable; > + VARIABLE_STORE_HEADER *VarStore; > + > + // > + // Tricky part: Use scratch data area at the end of volatile variable = store > + // as a temporary storage. > + // > + VarStore =3D (VARIABLE_STORE_HEADER *)(UINTN) > + mVariableModuleGlobal->VariableGlobal.VolatileVariableBase; > + NewVariable =3D GetEndPointer (VarStore); > + > + SetMem (NewVariable, mVariableModuleGlobal->ScratchBufferSize, 0xff); > + > + return NewVariable; > +} > + > +/** > + Delete old copies of variable completely. > + > + @param[in] VariableName Name of variable. > + @param[in] VendorGuid Guid of variable. > + @param[in] Variable Pointer to current variable on stor= age. > + @param[in,out] CacheVariable Pointer to current variable in cach= e. > + @param[in] VolatileFlag Auth-variable indicator. > + > + @retval EFI_SUCCESS Variable(s) were deleted successfully. > + @retval Others Failed to update variable state. > + > +**/ > +EFI_STATUS > +DeleteVariable ( > + IN CHAR16 *VariableName, > + IN EFI_GUID *VendorGuid, > + IN VARIABLE_POINTER_TRACK *Variable, > + IN OUT VARIABLE_POINTER_TRACK *CacheVariable, > + IN BOOLEAN VolatileFlag > + ) > +{ > + EFI_STATUS Status; > + > + if (Variable->InDeletedTransitionPtr !=3D NULL) { > + ASSERT (CacheVariable->InDeletedTransitionPtr !=3D NULL); > + // > + // Both ADDED and IN_DELETED_TRANSITION variable are present, > + // set IN_DELETED_TRANSITION one to DELETED state first. > + // > + Status =3D UpdateVariableState ( > + Variable->InDeletedTransitionPtr, > + CacheVariable->InDeletedTransitionPtr, > + CacheVariable->InDeletedTransitionPtr->State & VAR_DELETE= D, > + VolatileFlag > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + } > + > + ASSERT (CacheVariable->CurrPtr !=3D NULL); > + Status =3D UpdateVariableState ( > + Variable->CurrPtr, > + CacheVariable->CurrPtr, > + CacheVariable->CurrPtr->State & VAR_DELETED, > + VolatileFlag > + ); > + > + if (!EFI_ERROR (Status)) { > + UpdateVariableInfo ( > + VariableName, > + VendorGuid, > + Variable->Volatile, > + FALSE, > + FALSE, > + TRUE, > + FALSE, > + &gVariableInfo > + ); > + if (!Variable->Volatile) { > + FlushHobVariableToFlash (VariableName, VendorGuid); > + } > + } > + > + return Status; > +} > + > +/** > + Check if it's the right time to update a variable. > + > + @param[in] Attributes Attributes of a variable. > + > + @retval TRUE It's ready for variable update. > + @retval FALSE It's NOT ready for variable update. > + > +**/ > +BOOLEAN > +ReadyForUpdate ( > + IN UINT32 Attributes > + ) > +{ > + if ((mVariableModuleGlobal->FvbInstance =3D=3D NULL) && > + !mVariableModuleGlobal->VariableGlobal.EmuNvMode) > + { > + // > + // The FVB protocol is not ready, so the > EFI_VARIABLE_WRITE_ARCH_PROTOCOL > + // is not installed. > + // > + if ((Attributes & EFI_VARIABLE_NON_VOLATILE) !=3D 0) { > + // > + // Trying to update NV variable prior to the installation of > + // EFI_VARIABLE_WRITE_ARCH_PROTOCOL > + // > + DEBUG (( > + DEBUG_ERROR, > + "Update NV variable before EFI_VARIABLE_WRITE_ARCH_PROTOCOL > ready - %r\n", > + EFI_NOT_AVAILABLE_YET > + )); > + return FALSE; > + } else if ((Attributes & VARIABLE_ATTRIBUTE_AT_AW) !=3D 0) { > + // > + // Trying to update volatile authenticated variable prior to the > + // installation of EFI_VARIABLE_WRITE_ARCH_PROTOCOL. The > authenticated > + // variable perhaps is not initialized, just return here. > + // > + DEBUG (( > + DEBUG_ERROR, > + "Update AUTH variable before EFI_VARIABLE_WRITE_ARCH_PROTOCOL > ready - %r\n", > + EFI_NOT_AVAILABLE_YET > + )); > + return FALSE; > + } > + } > + > + return TRUE; > +} > + > +/** > + Check parameters associated with the variable to update. > + > + @param[in] Variable Pointer to current variable on storage. > + @param[in] CacheVariable Pointer to current variable in cache. > @param[in] VariableName Name of variable. > @param[in] VendorGuid Guid of variable. > @param[in] Data Variable data. > @@ -1667,9 +1999,130 @@ AutoUpdateLangVariable ( > @param[in] Attributes Attributes of the variable. > @param[in] KeyIndex Index of associated public key. > @param[in] MonotonicCount Value of associated monotonic count. > - @param[in, out] CacheVariable The variable information which is used t= o keep > track of variable usage. > @param[in] TimeStamp Value of associated TimeStamp. >=20 > + @retval EFI_SUCCESS The variable is ok to be updated. > + @retval EFI_ALREADY_STARTED No need to update the variable. > + @retval EFI_WRITE_PROTECTED The variable cannot be updated. > + @retval EFI_INVALID_PARAMETER The variable attributes are not valid. > + @retval EFI_NOT_FOUND Trying to delete non-existing variable. > + > +**/ > +EFI_STATUS > +ValidateVariableParameters ( > + IN VARIABLE_POINTER_TRACK *Variable, > + IN VARIABLE_POINTER_TRACK *CacheVariable, > + IN CHAR16 *VariableName, > + IN EFI_GUID *VendorGuid, > + IN VOID *Data, > + IN UINTN DataSize, > + IN UINT32 Attributes, > + IN UINT32 KeyIndex, > + IN UINT64 MonotonicCount, > + IN EFI_TIME *TimeStamp > + ) > +{ > + BOOLEAN AuthFlag; > + > + AuthFlag =3D mVariableModuleGlobal->VariableGlobal.AuthFormat; > + > + if ((DataSize =3D=3D 0) && ((Attributes & EFI_VARIABLE_APPEND_WRITE) != =3D 0)) { > + return EFI_ALREADY_STARTED; > + } > + > + if (Variable->CurrPtr !=3D NULL) { > + // > + // Update/Delete existing variable. > + // > + if (AtRuntime ()) { > + // > + // If AtRuntime and the variable is Volatile and Runtime Access, > + // the volatile is ReadOnly, and SetVariable should be aborted and > + // return EFI_WRITE_PROTECTED. > + // > + if (Variable->Volatile) { > + return EFI_WRITE_PROTECTED; > + } > + > + // > + // Only variable that have NV attributes can be updated/deleted in= Runtime. > + // > + if ((CacheVariable->CurrPtr->Attributes & EFI_VARIABLE_NON_VOLATIL= E) > =3D=3D 0) { > + return EFI_INVALID_PARAMETER; > + } > + > + // > + // Only variable that have RT attributes can be updated/deleted in= Runtime. > + // > + if ((CacheVariable->CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACC= ESS) > =3D=3D 0) { > + return EFI_INVALID_PARAMETER; > + } > + } > + > + // > + // Variable content unchanged and no need to update timestamp, just = return. > + // > + if ( ((Attributes & EFI_VARIABLE_APPEND_WRITE) =3D=3D 0) > + && (TimeStamp =3D=3D NULL) > + && (DataSizeOfVariable (CacheVariable->CurrPtr, AuthFlag) =3D=3D = DataSize) > + && (CompareMem (Data, GetVariableDataPtr (CacheVariable->CurrPtr, > AuthFlag), DataSize) =3D=3D 0)) > + { > + UpdateVariableInfo ( > + VariableName, > + VendorGuid, > + Variable->Volatile, > + FALSE, > + TRUE, > + FALSE, > + FALSE, > + &gVariableInfo > + ); > + return EFI_ALREADY_STARTED; > + } > + } else { > + // > + // Create a new variable. > + // > + > + // > + // Make sure we are trying to create a new variable. You cannot dele= te a > new > + // variable. > + // > + if ((DataSize =3D=3D 0) || > + ((Attributes & > (EFI_VARIABLE_RUNTIME_ACCESS|EFI_VARIABLE_BOOTSERVICE_ACCESS)) =3D=3D > 0)) > + { > + return EFI_NOT_FOUND; > + } > + > + // > + // Only variable have NV|RT attribute can be created in Runtime. > + // > + if ( AtRuntime () > + && ( ((Attributes & EFI_VARIABLE_RUNTIME_ACCESS) =3D=3D 0) > + || ((Attributes & EFI_VARIABLE_NON_VOLATILE) =3D=3D 0))) > + { > + return EFI_INVALID_PARAMETER; > + } > + } > + > + return EFI_SUCCESS; > +} > + > +/** > + Update the variable region with Variable information. If > EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS is set, > + index of associated public key is needed. > + > + @param[in] VariableName Name of variable. > + @param[in] VendorGuid Guid of variable. > + @param[in] Data Variable data. > + @param[in] DataSize Size of data. 0 means delete. > + @param[in] Attributes Attributes of the variable. > + @param[in] KeyIndex Index of associated public key. > + @param[in] MonotonicCount Value of associated monotonic count= . > + @param[in,out] CacheVariable The variable information which is u= sed > + to keep track of variable usage. > + @param[in] TimeStamp Value of associated TimeStamp. > + > @retval EFI_SUCCESS The update operation is success. > @retval EFI_OUT_OF_RESOURCES Variable region is full, can not write o= ther > data into this region. >=20 > @@ -1687,710 +2140,381 @@ UpdateVariable ( > IN EFI_TIME *TimeStamp OPTIONAL > ) > { > - EFI_STATUS Status; > - VARIABLE_HEADER *NextVariable; > - UINTN ScratchSize; > - UINTN MaxDataSize; > - UINTN VarNameOffset; > - UINTN VarDataOffset; > - UINTN VarNameSize; > - UINTN VarSize; > - BOOLEAN Volatile; > - EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb; > - UINT8 State; > - VARIABLE_POINTER_TRACK *Variable; > - VARIABLE_POINTER_TRACK NvVariable; > - VARIABLE_STORE_HEADER *VariableStoreHeader; > - VARIABLE_RUNTIME_CACHE *VolatileCacheInstance; > - UINT8 *BufferForMerge; > - UINTN MergedBufSize; > - BOOLEAN DataReady; > - UINTN DataOffset; > - BOOLEAN IsCommonVariable; > - BOOLEAN IsCommonUserVariable; > - AUTHENTICATED_VARIABLE_HEADER *AuthVariable; > - BOOLEAN AuthFormat; > + EFI_STATUS Status; > + VARIABLE_GLOBAL *VarGlobal; > + VARIABLE_HEADER *NewVariable; > + VARIABLE_HEADER *NextVariable; > + VARIABLE_HEADER *UpdatingVariable; > + UINTN VarSize; > + UINTN UpdateSize; > + UINTN Offset; > + VARIABLE_POINTER_TRACK *Variable; > + VARIABLE_POINTER_TRACK NvVariable; > + VARIABLE_STORE_HEADER *VariableStoreHeader; > + VARIABLE_RUNTIME_CACHE *VolatileCacheInstance; > + BOOLEAN IsCommonVariable; > + BOOLEAN IsCommonUserVariable; > + BOOLEAN DeleteFlag; > + BOOLEAN VolatileFlag; > + BOOLEAN HobVarOnlyFlag; > + EFI_PHYSICAL_ADDRESS VarStoreBase; > + UINTN *LastVariableOffset; >=20 > - if ((mVariableModuleGlobal->FvbInstance =3D=3D NULL) > && !mVariableModuleGlobal->VariableGlobal.EmuNvMode) { > - // > - // The FVB protocol is not ready, so the > EFI_VARIABLE_WRITE_ARCH_PROTOCOL is not installed. > - // > - if ((Attributes & EFI_VARIABLE_NON_VOLATILE) !=3D 0) { > - // > - // Trying to update NV variable prior to the installation of > EFI_VARIABLE_WRITE_ARCH_PROTOCOL > - // > - DEBUG ((DEBUG_ERROR, "Update NV variable before > EFI_VARIABLE_WRITE_ARCH_PROTOCOL ready - %r\n", > EFI_NOT_AVAILABLE_YET)); > - return EFI_NOT_AVAILABLE_YET; > - } else if ((Attributes & VARIABLE_ATTRIBUTE_AT_AW) !=3D 0) { > - // > - // Trying to update volatile authenticated variable prior to the i= nstallation of > EFI_VARIABLE_WRITE_ARCH_PROTOCOL > - // The authenticated variable perhaps is not initialized, just ret= urn here. > - // > - DEBUG ((DEBUG_ERROR, "Update AUTH variable before > EFI_VARIABLE_WRITE_ARCH_PROTOCOL ready - %r\n", > EFI_NOT_AVAILABLE_YET)); > - return EFI_NOT_AVAILABLE_YET; > - } > + if (!ReadyForUpdate (Attributes)) { > + return EFI_NOT_AVAILABLE_YET; > } >=20 > - AuthFormat =3D mVariableModuleGlobal->VariableGlobal.AuthFormat; > + VarGlobal =3D &mVariableModuleGlobal->VariableGlobal; > + > + if ( (((Attributes & EFI_VARIABLE_APPEND_WRITE) =3D=3D 0) && (DataSiz= e =3D=3D 0)) > + || (Attributes =3D=3D 0) > + || (AtRuntime () && ((Attributes & (EFI_VARIABLE_RUNTIME_ACCESS > + |EFI_VARIABLE_BOOTSERVICE_ACCES= S)) =3D=3D 0))) > + { > + DeleteFlag =3D TRUE; > + } else { > + DeleteFlag =3D FALSE; > + } > + > + if ( ((Attributes & EFI_VARIABLE_NON_VOLATILE) !=3D 0) > + || ((CacheVariable->CurrPtr !=3D NULL) && > + ((CacheVariable->CurrPtr->Attributes & EFI_VARIABLE_NON_VOLATIL= E) !=3D > 0))) > + { > + VolatileFlag =3D FALSE; > + } else { > + VolatileFlag =3D TRUE; > + } >=20 > // > // Check if CacheVariable points to the variable in variable HOB. > // If yes, let CacheVariable points to the variable in NV variable cac= he. > // > - if ((CacheVariable->CurrPtr !=3D NULL) && > - (mVariableModuleGlobal->VariableGlobal.HobVariableBase !=3D 0) && > - (CacheVariable->StartPtr =3D=3D GetStartPointer ((VARIABLE_STORE_H= EADER > *)(UINTN)mVariableModuleGlobal->VariableGlobal.HobVariableBase)) > - ) > - { > - CacheVariable->StartPtr =3D GetStartPointer (mNvVariableCache); > - CacheVariable->EndPtr =3D GetEndPointer (mNvVariableCache); > - CacheVariable->Volatile =3D FALSE; > - Status =3D FindVariableEx (VariableName, VendorGuid= , FALSE, > CacheVariable, AuthFormat); > + HobVarOnlyFlag =3D FALSE; > + if (IsHobVariable (CacheVariable)) { > + Status =3D RebaseVariablePtr ( > + CacheVariable, > + CacheVariable, > + mNvVariableCache, > + VariableName, > + VendorGuid, > + FALSE > + ); > if ((CacheVariable->CurrPtr =3D=3D NULL) || EFI_ERROR (Status)) { > // > // There is no matched variable in NV variable cache. > // > - if ((((Attributes & EFI_VARIABLE_APPEND_WRITE) =3D=3D 0) && (DataS= ize =3D=3D 0)) > || (Attributes =3D=3D 0)) { > + if (DeleteFlag) { > // > - // It is to delete variable, > - // go to delete this variable in variable HOB and > - // try to flush other variables from HOB to flash. > + // Leave the deletion to FlushHobVariableToFlash() before return= . > // > - UpdateVariableInfo (VariableName, VendorGuid, FALSE, FALSE, FALS= E, > TRUE, FALSE, &gVariableInfo); > - FlushHobVariableToFlash (VariableName, VendorGuid); > - return EFI_SUCCESS; > + HobVarOnlyFlag =3D TRUE; > + Status =3D EFI_SUCCESS; > + goto Done; > } > } > } >=20 > + // > + // Determine the physical position of variable store to update, due to= cache > + // mechanims of variable service. > + // > if ((CacheVariable->CurrPtr =3D=3D NULL) || CacheVariable->Volatile) { > + // > + // - Add new variable (volatile or non-volatile); Or > + // - Update/delete volatile variable in place. > + // > Variable =3D CacheVariable; > } else { > // > - // Update/Delete existing NV variable. > - // CacheVariable points to the variable in the memory copy of Flash = area > - // Now let Variable points to the same variable in Flash area. > + // - Update/Delete existing NV variable. > + // CacheVariable points to the variable in the memory copy of Fla= sh area. > + // Now let Variable points to the same variable in Flash area. > // > - VariableStoreHeader =3D (VARIABLE_STORE_HEADER > *)((UINTN)mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase); > - Variable =3D &NvVariable; > - Variable->StartPtr =3D GetStartPointer (VariableStoreHeader); > - Variable->EndPtr =3D (VARIABLE_HEADER *)((UINTN)Variable->StartPt= r + > ((UINTN)CacheVariable->EndPtr - (UINTN)CacheVariable->StartPtr)); > - > - Variable->CurrPtr =3D (VARIABLE_HEADER *)((UINTN)Variable->StartPtr = + > ((UINTN)CacheVariable->CurrPtr - (UINTN)CacheVariable->StartPtr)); > - if (CacheVariable->InDeletedTransitionPtr !=3D NULL) { > - Variable->InDeletedTransitionPtr =3D (VARIABLE_HEADER *)((UINTN)Va= riable- > >StartPtr + ((UINTN)CacheVariable->InDeletedTransitionPtr - > (UINTN)CacheVariable->StartPtr)); > - } else { > - Variable->InDeletedTransitionPtr =3D NULL; > - } > - > - Variable->Volatile =3D FALSE; > + VariableStoreHeader =3D (VARIABLE_STORE_HEADER *)(UINTN) > + VarGlobal->NonVolatileVariableBase; > + Variable =3D &NvVariable; > + Status =3D RebaseVariablePtr ( > + CacheVariable, > + Variable, > + VariableStoreHeader, > + VariableName, > + VendorGuid, > + TRUE > + ); > + ASSERT_EFI_ERROR (Status); > } >=20 > - Fvb =3D mVariableModuleGlobal->FvbInstance; > - > // > - // Tricky part: Use scratch data area at the end of volatile variable = store > - // as a temporary storage. > + // Validate variable parameters. > // > - NextVariable =3D GetEndPointer ((VARIABLE_STORE_HEADER > *)((UINTN)mVariableModuleGlobal->VariableGlobal.VolatileVariableBase)); > - ScratchSize =3D mVariableModuleGlobal->ScratchBufferSize; > - SetMem (NextVariable, ScratchSize, 0xff); > - DataReady =3D FALSE; > - > - if (Variable->CurrPtr !=3D NULL) { > - // > - // Update/Delete existing variable. > - // > - if (AtRuntime ()) { > - // > - // If AtRuntime and the variable is Volatile and Runtime Access, > - // the volatile is ReadOnly, and SetVariable should be aborted and > - // return EFI_WRITE_PROTECTED. > - // > - if (Variable->Volatile) { > - Status =3D EFI_WRITE_PROTECTED; > - goto Done; > - } > - > - // > - // Only variable that have NV attributes can be updated/deleted in= Runtime. > - // > - if ((CacheVariable->CurrPtr->Attributes & EFI_VARIABLE_NON_VOLATIL= E) =3D=3D > 0) { > - Status =3D EFI_INVALID_PARAMETER; > - goto Done; > - } > - > - // > - // Only variable that have RT attributes can be updated/deleted in= Runtime. > - // > - if ((CacheVariable->CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACC= ESS) > =3D=3D 0) { > - Status =3D EFI_INVALID_PARAMETER; > - goto Done; > - } > - } > - > - // > - // Setting a data variable with no access, or zero DataSize attribut= es > - // causes it to be deleted. > - // When the EFI_VARIABLE_APPEND_WRITE attribute is set, DataSize of = zero > will > - // not delete the variable. > - // > - if ((((Attributes & EFI_VARIABLE_APPEND_WRITE) =3D=3D 0) && (DataSiz= e =3D=3D 0)) || > ((Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | > EFI_VARIABLE_BOOTSERVICE_ACCESS)) =3D=3D 0)) { > - if (Variable->InDeletedTransitionPtr !=3D NULL) { > - // > - // Both ADDED and IN_DELETED_TRANSITION variable are present, > - // set IN_DELETED_TRANSITION one to DELETED state first. > - // > - ASSERT (CacheVariable->InDeletedTransitionPtr !=3D NULL); > - State =3D CacheVariable->InDeletedTransitionPtr->State; > - State &=3D VAR_DELETED; > - Status =3D UpdateVariableStore ( > - &mVariableModuleGlobal->VariableGlobal, > - Variable->Volatile, > - FALSE, > - Fvb, > - (UINTN)&Variable->InDeletedTransitionPtr->State, > - sizeof (UINT8), > - &State > - ); > - if (!EFI_ERROR (Status)) { > - if (!Variable->Volatile) { > - CacheVariable->InDeletedTransitionPtr->State =3D State; > - } > - } else { > - goto Done; > - } > - } > - > - State =3D CacheVariable->CurrPtr->State; > - State &=3D VAR_DELETED; > - > - Status =3D UpdateVariableStore ( > - &mVariableModuleGlobal->VariableGlobal, > - Variable->Volatile, > - FALSE, > - Fvb, > - (UINTN)&Variable->CurrPtr->State, > - sizeof (UINT8), > - &State > - ); > - if (!EFI_ERROR (Status)) { > - UpdateVariableInfo (VariableName, VendorGuid, Variable->Volatile= , FALSE, > FALSE, TRUE, FALSE, &gVariableInfo); > - if (!Variable->Volatile) { > - CacheVariable->CurrPtr->State =3D State; > - FlushHobVariableToFlash (VariableName, VendorGuid); > - } > - } > + Status =3D ValidateVariableParameters ( > + Variable, > + CacheVariable, > + VariableName, > + VendorGuid, > + Data, > + DataSize, > + Attributes, > + KeyIndex, > + MonotonicCount, > + TimeStamp > + ); > + if (EFI_ERROR (Status)) { > + goto Done; > + } >=20 > - goto Done; > - } > + // > + // Add or update a variable. Allocate a buffer to hold it temporarily. > + // > + NewVariable =3D GetNewVariableBuffer (); >=20 > + // > + // Fill-up variable data first, if necessary. > + // > + IsCommonVariable =3D FALSE; > + IsCommonUserVariable =3D FALSE; > + if (DeleteFlag) { > // > - // If the variable is marked valid, and the same data has been passe= d in, > - // then return to the caller immediately. > + // No need to fill up variable buffer when deleting a variable. But = the > + // buffer is still needed if variable protection is employed. > // > - if ((DataSizeOfVariable (CacheVariable->CurrPtr, AuthFormat) =3D=3D = DataSize) > && > - (CompareMem (Data, GetVariableDataPtr (CacheVariable->CurrPtr, > AuthFormat), DataSize) =3D=3D 0) && > - ((Attributes & EFI_VARIABLE_APPEND_WRITE) =3D=3D 0) && > - (TimeStamp =3D=3D NULL)) > - { > - // > - // Variable content unchanged and no need to update timestamp, jus= t return. > - // > - UpdateVariableInfo (VariableName, VendorGuid, Variable->Volatile, = FALSE, > TRUE, FALSE, FALSE, &gVariableInfo); > - Status =3D EFI_SUCCESS; > - goto Done; > - } else if ((CacheVariable->CurrPtr->State =3D=3D VAR_ADDED) || > - (CacheVariable->CurrPtr->State =3D=3D (VAR_ADDED & > VAR_IN_DELETED_TRANSITION))) > - { > - // > - // EFI_VARIABLE_APPEND_WRITE attribute only effects for existing v= ariable. > - // > - if ((Attributes & EFI_VARIABLE_APPEND_WRITE) !=3D 0) { > - // > - // NOTE: From 0 to DataOffset of NextVariable is reserved for Va= riable > Header and Name. > - // From DataOffset of NextVariable is to save the existing varia= ble data. > - // > - DataOffset =3D GetVariableDataOffset (CacheVariable->CurrPtr= , > AuthFormat); > - BufferForMerge =3D (UINT8 *)((UINTN)NextVariable + DataOffset); > - CopyMem ( > - BufferForMerge, > - (UINT8 *)((UINTN)CacheVariable->CurrPtr + DataOffset), > - DataSizeOfVariable (CacheVariable->CurrPtr, AuthFormat) > - ); > - > - // > - // Set Max Auth/Non-Volatile/Volatile Variable Data Size as defa= ult > MaxDataSize. > - // > - if ((Attributes & VARIABLE_ATTRIBUTE_AT_AW) !=3D 0) { > - MaxDataSize =3D mVariableModuleGlobal->MaxAuthVariableSize - > DataOffset; > - } else if ((Attributes & EFI_VARIABLE_NON_VOLATILE) !=3D 0) { > - MaxDataSize =3D mVariableModuleGlobal->MaxVariableSize - DataO= ffset; > - } else { > - MaxDataSize =3D mVariableModuleGlobal->MaxVolatileVariableSize= - > DataOffset; > - } > - > - // > - // Append the new data to the end of existing data. > - // Max Harware error record variable data size is different from > common/auth variable. > - // > - if ((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) =3D=3D > EFI_VARIABLE_HARDWARE_ERROR_RECORD) { > - MaxDataSize =3D PcdGet32 (PcdMaxHardwareErrorVariableSize) - > DataOffset; > - } > - > - if (DataSizeOfVariable (CacheVariable->CurrPtr, AuthFormat) + Da= taSize > > MaxDataSize) { > - // > - // Existing data size + new data size exceed maximum variable = size > limitation. > - // > - Status =3D EFI_INVALID_PARAMETER; > - goto Done; > - } > - > - CopyMem ( > - (UINT8 *)( > - (UINTN)BufferForMerge + DataSizeOfVariable (CacheVar= iable- > >CurrPtr, AuthFormat) > - ), > - Data, > - DataSize > - ); > - MergedBufSize =3D DataSizeOfVariable (CacheVariable->CurrPtr, Au= thFormat) > + > - DataSize; > - > - // > - // BufferForMerge(from DataOffset of NextVariable) has included = the > merged existing and new data. > - // > - Data =3D BufferForMerge; > - DataSize =3D MergedBufSize; > - DataReady =3D TRUE; > - } > - > - // > - // Mark the old variable as in delete transition. > - // > - State =3D CacheVariable->CurrPtr->State; > - State &=3D VAR_IN_DELETED_TRANSITION; > - > - Status =3D UpdateVariableStore ( > - &mVariableModuleGlobal->VariableGlobal, > - Variable->Volatile, > - FALSE, > - Fvb, > - (UINTN)&Variable->CurrPtr->State, > - sizeof (UINT8), > - &State > - ); > - if (EFI_ERROR (Status)) { > - goto Done; > - } > - > - if (!Variable->Volatile) { > - CacheVariable->CurrPtr->State =3D State; > - } > - } > + VarSize =3D 0; > } else { > - // > - // Not found existing variable. Create a new variable. > - // > + VarSize =3D SetVariableData ( > + NewVariable, > + CacheVariable->CurrPtr, > + VariableName, > + VendorGuid, > + Data, > + DataSize, > + Attributes, > + KeyIndex, > + MonotonicCount, > + TimeStamp > + ); >=20 > - if ((DataSize =3D=3D 0) && ((Attributes & EFI_VARIABLE_APPEND_WRITE)= !=3D 0)) { > - Status =3D EFI_SUCCESS; > - goto Done; > - } > - > - // > - // Make sure we are trying to create a new variable. > - // Setting a data variable with zero DataSize or no access attribute= s means to > delete it. > - // > - if ((DataSize =3D=3D 0) || ((Attributes & (EFI_VARIABLE_RUNTIME_ACCE= SS | > EFI_VARIABLE_BOOTSERVICE_ACCESS)) =3D=3D 0)) { > - Status =3D EFI_NOT_FOUND; > - goto Done; > - } > - > - // > - // Only variable have NV|RT attribute can be created in Runtime. > - // > - if (AtRuntime () && > - (((Attributes & EFI_VARIABLE_RUNTIME_ACCESS) =3D=3D 0) || ((Attr= ibutes & > EFI_VARIABLE_NON_VOLATILE) =3D=3D 0))) > - { > - Status =3D EFI_INVALID_PARAMETER; > - goto Done; > - } > - } > - > - // > - // Function part - create a new variable and copy the data. > - // Both update a variable and create a variable will come here. > - // > - NextVariable->StartId =3D VARIABLE_DATA; > - // > - // NextVariable->State =3D VAR_ADDED; > - // > - NextVariable->Reserved =3D 0; > - if (mVariableModuleGlobal->VariableGlobal.AuthFormat) { > - AuthVariable =3D (AUTHENTICATED_VARIABLE_HEADER > *)NextVariable; > - AuthVariable->PubKeyIndex =3D KeyIndex; > - AuthVariable->MonotonicCount =3D MonotonicCount; > - ZeroMem (&AuthVariable->TimeStamp, sizeof (EFI_TIME)); > - > - if (((Attributes & > EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) !=3D 0) && > - (TimeStamp !=3D NULL)) > - { > - if ((Attributes & EFI_VARIABLE_APPEND_WRITE) =3D=3D 0) { > - CopyMem (&AuthVariable->TimeStamp, TimeStamp, sizeof (EFI_TIME))= ; > - } else { > - // > - // In the case when the EFI_VARIABLE_APPEND_WRITE attribute is s= et, > only > - // when the new TimeStamp value is later than the current timest= amp > associated > - // with the variable, we need associate the new timestamp with t= he > updated value. > - // > - if (Variable->CurrPtr !=3D NULL) { > - if (VariableCompareTimeStampInternal > (&(((AUTHENTICATED_VARIABLE_HEADER *)CacheVariable->CurrPtr)- > >TimeStamp), TimeStamp)) { > - CopyMem (&AuthVariable->TimeStamp, TimeStamp, sizeof (EFI_TI= ME)); > - } else { > - CopyMem (&AuthVariable->TimeStamp, > &(((AUTHENTICATED_VARIABLE_HEADER *)CacheVariable->CurrPtr)- > >TimeStamp), sizeof (EFI_TIME)); > - } > - } > - } > - } > - } > - > - // > - // The EFI_VARIABLE_APPEND_WRITE attribute will never be set in the > returned > - // Attributes bitmask parameter of a GetVariable() call. > - // > - NextVariable->Attributes =3D Attributes & (~EFI_VARIABLE_APPEND_WRITE)= ; > - > - VarNameOffset =3D GetVariableHeaderSize (AuthFormat); > - VarNameSize =3D StrSize (VariableName); > - CopyMem ( > - (UINT8 *)((UINTN)NextVariable + VarNameOffset), > - VariableName, > - VarNameSize > - ); > - VarDataOffset =3D VarNameOffset + VarNameSize + GET_PAD_SIZE > (VarNameSize); > - > - // > - // If DataReady is TRUE, it means the variable data has been saved int= o > - // NextVariable during EFI_VARIABLE_APPEND_WRITE operation preparation= . > - // > - if (!DataReady) { > - CopyMem ( > - (UINT8 *)((UINTN)NextVariable + VarDataOffset), > - Data, > - DataSize > - ); > - } > - > - CopyMem ( > - GetVendorGuidPtr (NextVariable, AuthFormat), > - VendorGuid, > - sizeof (EFI_GUID) > - ); > - // > - // There will be pad bytes after Data, the NextVariable->NameSize and > - // NextVariable->DataSize should not include pad size so that variable > - // service can get actual size in GetVariable. > - // > - SetNameSizeOfVariable (NextVariable, VarNameSize, AuthFormat); > - SetDataSizeOfVariable (NextVariable, DataSize, AuthFormat); > - > - // > - // The actual size of the variable that stores in storage should > - // include pad size. > - // > - VarSize =3D VarDataOffset + DataSize + GET_PAD_SIZE (DataSize); > - if ((Attributes & EFI_VARIABLE_NON_VOLATILE) !=3D 0) { > - // > - // Create a nonvolatile variable. > - // > - Volatile =3D FALSE; > - > - IsCommonVariable =3D FALSE; > - IsCommonUserVariable =3D FALSE; > if ((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) =3D=3D 0) { > IsCommonVariable =3D TRUE; > - IsCommonUserVariable =3D IsUserVariable (NextVariable); > + IsCommonUserVariable =3D IsUserVariable (NewVariable); > } > + } >=20 > - if ( ( ((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) !=3D 0) > - && ((VarSize + mVariableModuleGlobal->HwErrVariableTotalSize) = > > PcdGet32 (PcdHwErrStorageSize))) > - || (IsCommonVariable && ((VarSize + mVariableModuleGlobal- > >CommonVariableTotalSize) > mVariableModuleGlobal- > >CommonVariableSpace)) > - || (IsCommonVariable && AtRuntime () && ((VarSize + > mVariableModuleGlobal->CommonVariableTotalSize) > > mVariableModuleGlobal->CommonRuntimeVariableSpace)) > - || (IsCommonUserVariable && ((VarSize + mVariableModuleGlobal- > >CommonUserVariableTotalSize) > mVariableModuleGlobal- > >CommonMaxUserVariableSpace))) > - { > - if (AtRuntime ()) { > - if (IsCommonUserVariable && ((VarSize + mVariableModuleGlobal- > >CommonUserVariableTotalSize) > mVariableModuleGlobal- > >CommonMaxUserVariableSpace)) { > - RecordVarErrorFlag (VAR_ERROR_FLAG_USER_ERROR, VariableName, > VendorGuid, Attributes, VarSize); > - } > - > - if (IsCommonVariable && ((VarSize + mVariableModuleGlobal- > >CommonVariableTotalSize) > mVariableModuleGlobal- > >CommonRuntimeVariableSpace)) { > - RecordVarErrorFlag (VAR_ERROR_FLAG_SYSTEM_ERROR, VariableName, > VendorGuid, Attributes, VarSize); > - } > - > - Status =3D EFI_OUT_OF_RESOURCES; > - goto Done; > - } > - > - // > - // Perform garbage collection & reclaim operation, and integrate t= he new > variable at the same time. > - // > - Status =3D Reclaim ( > - mVariableModuleGlobal->VariableGlobal.NonVolatileVariab= leBase, > - &mVariableModuleGlobal->NonVolatileLastVariableOffset, > - FALSE, > - Variable, > - NextVariable, > - HEADER_ALIGN (VarSize) > - ); > - if (!EFI_ERROR (Status)) { > - // > - // The new variable has been integrated successfully during recl= aiming. > - // > - if (Variable->CurrPtr !=3D NULL) { > - CacheVariable->CurrPtr =3D (VARIABLE_HEADER > *)((UINTN)CacheVariable->StartPtr + ((UINTN)Variable->CurrPtr - > (UINTN)Variable->StartPtr)); > - CacheVariable->InDeletedTransitionPtr =3D NULL; > - } > - > - UpdateVariableInfo (VariableName, VendorGuid, FALSE, FALSE, TRUE= , > FALSE, FALSE, &gVariableInfo); > - FlushHobVariableToFlash (VariableName, VendorGuid); > - } else { > - if (IsCommonUserVariable && ((VarSize + mVariableModuleGlobal- > >CommonUserVariableTotalSize) > mVariableModuleGlobal- > >CommonMaxUserVariableSpace)) { > - RecordVarErrorFlag (VAR_ERROR_FLAG_USER_ERROR, VariableName, > VendorGuid, Attributes, VarSize); > - } > + // > + // We might need to do protection for non-volatile variable before flu= shing > + // the data to storage. A null version (meaning no protection) of foll= owing > + // APIs should simply return EFI_SUCCESS or EFI_UNSUPPORTED without an= y > + // changes to original data. > + // > + if (!VolatileFlag) { > + Status =3D ProtectedVariableLibUpdate ( > + Variable->CurrPtr, > + Variable->InDeletedTransitionPtr, > + NewVariable, > + &VarSize > + ); > + if (EFI_ERROR (Status) && (Status !=3D EFI_UNSUPPORTED)) { > + return Status; > + } >=20 > - if (IsCommonVariable && ((VarSize + mVariableModuleGlobal- > >CommonVariableTotalSize) > mVariableModuleGlobal- > >CommonVariableSpace)) { > - RecordVarErrorFlag (VAR_ERROR_FLAG_SYSTEM_ERROR, VariableName, > VendorGuid, Attributes, VarSize); > - } > - } > + Status =3D EFI_SUCCESS; > + } >=20 > + // > + // Mark the old variable as in delete transition first. There's no suc= h need > + // for deleting a variable, even if variable protection is employed. > + // > + if ( !DeleteFlag > + && (CacheVariable->CurrPtr !=3D NULL) > + && ( (CacheVariable->CurrPtr->State =3D=3D VAR_ADDED) > + || (CacheVariable->CurrPtr->State =3D=3D (VAR_ADDED & > VAR_IN_DELETED_TRANSITION)))) > + { > + Status =3D UpdateVariableState ( > + Variable->CurrPtr, > + CacheVariable->CurrPtr, > + CacheVariable->CurrPtr->State & VAR_IN_DELETED_TRANSITION= , > + Variable->Volatile > + ); > + if (EFI_ERROR (Status)) { > goto Done; > } > - > - if (!mVariableModuleGlobal->VariableGlobal.EmuNvMode) { > - // > - // Four steps > - // 1. Write variable header > - // 2. Set variable state to header valid > - // 3. Write variable data > - // 4. Set variable state to valid > - // > - // > - // Step 1: > - // > - Status =3D UpdateVariableStore ( > - &mVariableModuleGlobal->VariableGlobal, > - FALSE, > - TRUE, > - Fvb, > - mVariableModuleGlobal->NonVolatileLastVariableOffset, > - (UINT32)GetVariableHeaderSize (AuthFormat), > - (UINT8 *)NextVariable > - ); > - > - if (EFI_ERROR (Status)) { > - goto Done; > - } > - > - // > - // Step 2: > - // > - NextVariable->State =3D VAR_HEADER_VALID_ONLY; > - Status =3D UpdateVariableStore ( > - &mVariableModuleGlobal->VariableGlobal, > - FALSE, > - TRUE, > - Fvb, > - mVariableModuleGlobal->NonVolatileLastVari= ableOffset + > OFFSET_OF (VARIABLE_HEADER, State), > - sizeof (UINT8), > - &NextVariable->State > - ); > - > - if (EFI_ERROR (Status)) { > - goto Done; > - } > - > - // > - // Step 3: > - // > - Status =3D UpdateVariableStore ( > - &mVariableModuleGlobal->VariableGlobal, > - FALSE, > - TRUE, > - Fvb, > - mVariableModuleGlobal->NonVolatileLastVariableOffset + > GetVariableHeaderSize (AuthFormat), > - (UINT32)(VarSize - GetVariableHeaderSize (AuthFormat)), > - (UINT8 *)NextVariable + GetVariableHeaderSize (AuthForm= at) > + } > + > + // > + // Have enough space to store the variable? > + // > + Status =3D CheckVariableStoreSpace ( > + NewVariable, > + VarSize, > + VariableName, > + VendorGuid, > + Attributes, > + VolatileFlag > + ); > + if (Status =3D=3D EFI_OUT_OF_RESOURCES) { > + // > + // Not a chance. > + // > + goto Done; > + } > + > + // > + // Maybe not... > + // > + VarStoreBase =3D (VolatileFlag) ? VarGlobal->VolatileVariableBase > + : VarGlobal->NonVolatileVariableBase; > + LastVariableOffset =3D (VolatileFlag) > + ? &mVariableModuleGlobal->VolatileLastVariableOf= fset > + : &mVariableModuleGlobal->NonVolatileLastVariabl= eOffset; > + if (!EFI_ERROR (Status)) { > + // > + // There's enough free space at the tail of variable storage. > + // > + > + // > + // If non-volatile variable is protected, a separate variable > (MetaDataHmacVar) > + // is always updated along with current updating variable. The buffe= r pointed > + // by NewVariable must have two variables. They should be written at= this > + // time orderly. > + // > + NextVariable =3D NewVariable; > + UpdatingVariable =3D NULL; > + UpdateSize =3D 0; > + while ( !EFI_ERROR (Status) > + && ((UINTN)NextVariable - (UINTN)NewVariable) < VarSize) > + { > + UpdatingVariable =3D NextVariable; > + NextVariable =3D GetNextVariablePtr (UpdatingVariable, VarGlob= al- > >AuthFormat); > + UpdateSize =3D (UINTN)NextVariable - (UINTN)UpdatingVariable= ; > + > + Status =3D WriteVariable ( > + VarStoreBase, > + LastVariableOffset, > + &UpdatingVariable, > + (UINT32)UpdateSize, > + VolatileFlag, > + VarGlobal->AuthFormat > ); > - > - if (EFI_ERROR (Status)) { > - goto Done; > - } > - > - // > - // Step 4: > - // > - NextVariable->State =3D VAR_ADDED; > - Status =3D UpdateVariableStore ( > - &mVariableModuleGlobal->VariableGlobal, > - FALSE, > - TRUE, > - Fvb, > - mVariableModuleGlobal->NonVolatileLastVari= ableOffset + > OFFSET_OF (VARIABLE_HEADER, State), > - sizeof (UINT8), > - &NextVariable->State > - ); > - > - if (EFI_ERROR (Status)) { > - goto Done; > - } > - > - // > - // Update the memory copy of Flash region. > - // > - CopyMem ((UINT8 *)mNvVariableCache + mVariableModuleGlobal- > >NonVolatileLastVariableOffset, (UINT8 *)NextVariable, VarSize); > - } else { > - // > - // Emulated non-volatile variable mode. > - // > - NextVariable->State =3D VAR_ADDED; > - Status =3D UpdateVariableStore ( > - &mVariableModuleGlobal->VariableGlobal, > - FALSE, > - TRUE, > - Fvb, > - mVariableModuleGlobal->NonVolatileLastVari= ableOffset, > - (UINT32)VarSize, > - (UINT8 *)NextVariable > - ); > - > - if (EFI_ERROR (Status)) { > - goto Done; > - } > } >=20 > - mVariableModuleGlobal->NonVolatileLastVariableOffset +=3D HEADER_ALI= GN > (VarSize); > - > + // > + // UpdatingVariable must point to the last written variable. Restore= it to > + // the first one so that we can calculate the offset in variable sto= rage. > + // > + UpdatingVariable =3D (VARIABLE_HEADER *)((UINTN)UpdatingVariable + > UpdateSize > + - VarSize); > if ((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) !=3D 0) { > - mVariableModuleGlobal->HwErrVariableTotalSize +=3D HEADER_ALIGN > (VarSize); > + mVariableModuleGlobal->HwErrVariableTotalSize +=3D VarSize; > } else { > - mVariableModuleGlobal->CommonVariableTotalSize +=3D HEADER_ALIGN > (VarSize); > + mVariableModuleGlobal->CommonVariableTotalSize +=3D VarSize; > if (IsCommonUserVariable) { > - mVariableModuleGlobal->CommonUserVariableTotalSize +=3D > HEADER_ALIGN (VarSize); > + mVariableModuleGlobal->CommonUserVariableTotalSize +=3D VarSize; > } > } > - } else { > - // > - // Create a volatile variable. > - // > - Volatile =3D TRUE; >=20 > - if ((UINT32)(VarSize + mVariableModuleGlobal->VolatileLastVariableOf= fset) > > - ((VARIABLE_STORE_HEADER *)((UINTN)(mVariableModuleGlobal- > >VariableGlobal.VolatileVariableBase)))->Size) > - { > - // > - // Perform garbage collection & reclaim operation, and integrate t= he new > variable at the same time. > - // > - Status =3D Reclaim ( > - mVariableModuleGlobal->VariableGlobal.VolatileVariableB= ase, > - &mVariableModuleGlobal->VolatileLastVariableOffset, > - TRUE, > + // > + // Mark the old variable(s) as deleted. > + // > + if (!EFI_ERROR (Status) && (Variable->CurrPtr !=3D NULL)) { > + Status =3D DeleteVariable ( > + VariableName, > + VendorGuid, > Variable, > - NextVariable, > - HEADER_ALIGN (VarSize) > + CacheVariable, > + VolatileFlag > ); > - if (!EFI_ERROR (Status)) { > - // > - // The new variable has been integrated successfully during recl= aiming. > - // > - if (Variable->CurrPtr !=3D NULL) { > - CacheVariable->CurrPtr =3D (VARIABLE_HEADER > *)((UINTN)CacheVariable->StartPtr + ((UINTN)Variable->CurrPtr - > (UINTN)Variable->StartPtr)); > - CacheVariable->InDeletedTransitionPtr =3D NULL; > - } > - > - UpdateVariableInfo (VariableName, VendorGuid, TRUE, FALSE, TRUE, > FALSE, FALSE, &gVariableInfo); > - } > - > - goto Done; > } > - > - NextVariable->State =3D VAR_ADDED; > - Status =3D UpdateVariableStore ( > - &mVariableModuleGlobal->VariableGlobal, > - TRUE, > - TRUE, > - Fvb, > - mVariableModuleGlobal->VolatileLastVariableO= ffset, > - (UINT32)VarSize, > - (UINT8 *)NextVariable > - ); > - > - if (EFI_ERROR (Status)) { > - goto Done; > - } > - > - mVariableModuleGlobal->VolatileLastVariableOffset +=3D HEADER_ALIGN > (VarSize); > - } > - > - // > - // Mark the old variable as deleted. > - // > - if (!EFI_ERROR (Status) && (Variable->CurrPtr !=3D NULL)) { > - if (Variable->InDeletedTransitionPtr !=3D NULL) { > - // > - // Both ADDED and IN_DELETED_TRANSITION old variable are present, > - // set IN_DELETED_TRANSITION one to DELETED state first. > - // > - ASSERT (CacheVariable->InDeletedTransitionPtr !=3D NULL); > - State =3D CacheVariable->InDeletedTransitionPtr->State; > - State &=3D VAR_DELETED; > - Status =3D UpdateVariableStore ( > - &mVariableModuleGlobal->VariableGlobal, > - Variable->Volatile, > - FALSE, > - Fvb, > - (UINTN)&Variable->InDeletedTransitionPtr->State, > - sizeof (UINT8), > - &State > - ); > - if (!EFI_ERROR (Status)) { > - if (!Variable->Volatile) { > - CacheVariable->InDeletedTransitionPtr->State =3D State; > - } > - } else { > - goto Done; > - } > - } > - > - State =3D CacheVariable->CurrPtr->State; > - State &=3D VAR_DELETED; > - > - Status =3D UpdateVariableStore ( > - &mVariableModuleGlobal->VariableGlobal, > - Variable->Volatile, > - FALSE, > - Fvb, > - (UINTN)&Variable->CurrPtr->State, > - sizeof (UINT8), > - &State > + } else { > + // > + // There's not enough space at the tail of variable storage but ther= e's > + // enough free space holes in the whole storage. Perform garbage col= lection > + // & reclaim operation, and integrate the new variable at the same t= ime. > + // > + Status =3D Reclaim ( > + VarStoreBase, > + LastVariableOffset, > + VolatileFlag, > + Variable, > + NewVariable, > + VarSize > ); > - if (!EFI_ERROR (Status) && !Variable->Volatile) { > - CacheVariable->CurrPtr->State =3D State; > - } > - } > + UpdatingVariable =3D Variable->CurrPtr; >=20 > - if (!EFI_ERROR (Status)) { > - UpdateVariableInfo (VariableName, VendorGuid, Volatile, FALSE, TRUE, > FALSE, FALSE, &gVariableInfo); > - if (!Volatile) { > - FlushHobVariableToFlash (VariableName, VendorGuid); > + if (EFI_ERROR (Status) && > + ((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) =3D=3D 0)) > + { > + // > + // Out of space. > + // > + IsCommonUserVariable =3D IsUserVariable (NewVariable); > + IsCommonVariable =3D TRUE; > + > + if (IsCommonUserVariable && > + ((VarSize + mVariableModuleGlobal->CommonUserVariableTotalSize= ) > + > mVariableModuleGlobal->CommonMaxUserVariableSpace)) > + { > + RecordVarErrorFlag ( > + VAR_ERROR_FLAG_USER_ERROR, > + VariableName, > + VendorGuid, > + Attributes, > + VarSize > + ); > + } > + > + if (IsCommonVariable && > + ((VarSize + mVariableModuleGlobal->CommonVariableTotalSize) > + > mVariableModuleGlobal->CommonVariableSpace)) > + { > + RecordVarErrorFlag ( > + VAR_ERROR_FLAG_SYSTEM_ERROR, > + VariableName, > + VendorGuid, > + Attributes, > + VarSize > + ); > + } > } > } >=20 > Done: > if (!EFI_ERROR (Status)) { > - if (((Variable->CurrPtr !=3D NULL) && !Variable->Volatile) || ((Attr= ibutes & > EFI_VARIABLE_NON_VOLATILE) !=3D 0)) { > - VolatileCacheInstance =3D &(mVariableModuleGlobal- > >VariableGlobal.VariableRuntimeCacheContext.VariableRuntimeNvCache); > + if (!VolatileFlag) { > + Offset =3D (UpdatingVariable !=3D NULL) ? (UINTN)UpdatingVariable = - > (UINTN)VarStoreBase > + : 0; > + Status =3D ProtectedVariableLibWriteFinal ( > + NewVariable, > + VarSize, > + Offset > + ); > + if (EFI_ERROR (Status) && (Status !=3D EFI_UNSUPPORTED)) { > + return Status; > + } > + > + Status =3D EFI_SUCCESS; > + } > + > + UpdateVariableInfo ( > + VariableName, > + VendorGuid, > + VolatileFlag, > + FALSE, > + TRUE, > + FALSE, > + FALSE, > + &gVariableInfo > + ); > + // > + // HOB copy of the same variable is no longer needed, no matter it h= as > + // been deleted, updated or added from/to real variable storage. > + // > + if (HobVarOnlyFlag || !VolatileFlag) { > + FlushHobVariableToFlash (VariableName, VendorGuid); > + } > + > + if (!VolatileFlag) { > + VolatileCacheInstance =3D &(VarGlobal- > >VariableRuntimeCacheContext.VariableRuntimeNvCache); > } else { > - VolatileCacheInstance =3D &(mVariableModuleGlobal- > >VariableGlobal.VariableRuntimeCacheContext.VariableRuntimeVolatileCache)= ; > + VolatileCacheInstance =3D &(VarGlobal- > >VariableRuntimeCacheContext.VariableRuntimeVolatileCache); > } >=20 > if (VolatileCacheInstance->Store !=3D NULL) { > @@ -2401,6 +2525,11 @@ Done: > ); > ASSERT_EFI_ERROR (Status); > } > + } else if (Status =3D=3D EFI_ALREADY_STARTED) { > + // > + // Meaning nothing needs to be done. Just return success. > + // > + Status =3D EFI_SUCCESS; > } >=20 > return Status; > @@ -2440,7 +2569,6 @@ VariableServiceGetVariable ( > { > EFI_STATUS Status; > VARIABLE_POINTER_TRACK Variable; > - UINTN VarDataSize; >=20 > if ((VariableName =3D=3D NULL) || (VendorGuid =3D=3D NULL) || (DataSiz= e =3D=3D NULL)) { > return EFI_INVALID_PARAMETER; > @@ -2458,28 +2586,26 @@ VariableServiceGetVariable ( > } >=20 > // > - // Get data size > + // Get data and its size > // > - VarDataSize =3D DataSizeOfVariable (Variable.CurrPtr, mVariableModuleG= lobal- > >VariableGlobal.AuthFormat); > - ASSERT (VarDataSize !=3D 0); > + if (!Variable.Volatile) { > + // > + // Currently only non-volatile variable needs protection. > + // > + Status =3D ProtectedVariableLibGetByBuffer ( > + Variable.CurrPtr, > + Data, > + (UINT32 *)DataSize, > + mVariableModuleGlobal->VariableGlobal.AuthFormat > + ); > + } >=20 > - if (*DataSize >=3D VarDataSize) { > - if (Data =3D=3D NULL) { > - Status =3D EFI_INVALID_PARAMETER; > - goto Done; > - } > + if (Variable.Volatile || (Status =3D=3D EFI_UNSUPPORTED)) { > + Status =3D GetVariableData (Variable.CurrPtr, Data, (UINT32 *)DataSi= ze, > mVariableModuleGlobal->VariableGlobal.AuthFormat); > + } >=20 > - CopyMem (Data, GetVariableDataPtr (Variable.CurrPtr, > mVariableModuleGlobal->VariableGlobal.AuthFormat), VarDataSize); > - > - *DataSize =3D VarDataSize; > + if (!EFI_ERROR (Status)) { > UpdateVariableInfo (VariableName, VendorGuid, Variable.Volatile, TRU= E, > FALSE, FALSE, FALSE, &gVariableInfo); > - > - Status =3D EFI_SUCCESS; > - goto Done; > - } else { > - *DataSize =3D VarDataSize; > - Status =3D EFI_BUFFER_TOO_SMALL; > - goto Done; > } >=20 > Done: > @@ -2860,7 +2986,7 @@ VariableServiceSetVariable ( > // Parse non-volatile variable data and get last variable offset. > // > NextVariable =3D GetStartPointer ((VARIABLE_STORE_HEADER *)(UINTN)Po= int); > - while (IsValidVariableHeader (NextVariable, GetEndPointer > ((VARIABLE_STORE_HEADER *)(UINTN)Point))) { > + while (IsValidVariableHeader (NextVariable, GetEndPointer > ((VARIABLE_STORE_HEADER *)(UINTN)Point), AuthFormat)) { > NextVariable =3D GetNextVariablePtr (NextVariable, AuthFormat); > } >=20 > @@ -3022,7 +3148,12 @@ VariableServiceQueryVariableInfoInternal ( > // > // Now walk through the related variable store. > // > - while (IsValidVariableHeader (Variable, GetEndPointer (VariableStoreHe= ader))) > { > + while (IsValidVariableHeader ( > + Variable, > + GetEndPointer (VariableStoreHeader), > + mVariableModuleGlobal->VariableGlobal.AuthFormat > + )) > + { > NextVariable =3D GetNextVariablePtr (Variable, mVariableModuleGlobal= - > >VariableGlobal.AuthFormat); > VariableSize =3D (UINT64)(UINTN)NextVariable - (UINT64)(UINTN)Variab= le; >=20 > @@ -3315,7 +3446,7 @@ FlushHobVariableToFlash ( > // > mVariableModuleGlobal->VariableGlobal.HobVariableBase =3D 0; > for ( Variable =3D GetStartPointer (VariableStoreHeader) > - ; IsValidVariableHeader (Variable, GetEndPointer (VariableStor= eHeader)) > + ; IsValidVariableHeader (Variable, GetEndPointer (VariableStor= eHeader), > AuthFormat) > ; Variable =3D GetNextVariablePtr (Variable, AuthFormat) > ) > { > @@ -3525,11 +3656,11 @@ ConvertNormalVarStorageToAuthVarStorage ( > VARIABLE_HEADER *StartPtr; > UINT8 *NextPtr; > VARIABLE_HEADER *EndPtr; > - UINTN AuthVarStroageSize; > + UINTN AuthVarStorageSize; > AUTHENTICATED_VARIABLE_HEADER *AuthStartPtr; > VARIABLE_STORE_HEADER *AuthVarStorage; >=20 > - AuthVarStroageSize =3D sizeof (VARIABLE_STORE_HEADER); > + AuthVarStorageSize =3D sizeof (VARIABLE_STORE_HEADER); > // > // Set AuthFormat as FALSE for normal variable storage > // > @@ -3542,10 +3673,10 @@ ConvertNormalVarStorageToAuthVarStorage ( > EndPtr =3D GetEndPointer (NormalVarStorage); > while (StartPtr < EndPtr) { > if (StartPtr->State =3D=3D VAR_ADDED) { > - AuthVarStroageSize =3D HEADER_ALIGN (AuthVarStroageSize); > - AuthVarStroageSize +=3D sizeof (AUTHENTICATED_VARIABLE_HEADER); > - AuthVarStroageSize +=3D StartPtr->NameSize + GET_PAD_SIZE (StartPt= r- > >NameSize); > - AuthVarStroageSize +=3D StartPtr->DataSize + GET_PAD_SIZE (StartPt= r- > >DataSize); > + AuthVarStorageSize =3D HEADER_ALIGN (AuthVarStorageSize); > + AuthVarStorageSize +=3D sizeof (AUTHENTICATED_VARIABLE_HEADER); > + AuthVarStorageSize +=3D StartPtr->NameSize + GET_PAD_SIZE (StartPt= r- > >NameSize); > + AuthVarStorageSize +=3D StartPtr->DataSize + GET_PAD_SIZE (StartPt= r- > >DataSize); > } >=20 > StartPtr =3D GetNextVariablePtr (StartPtr, mVariableModuleGlobal- > >VariableGlobal.AuthFormat); > @@ -3554,7 +3685,7 @@ ConvertNormalVarStorageToAuthVarStorage ( > // > // Allocate Runtime memory for Auth Variable Storage > // > - AuthVarStorage =3D AllocateRuntimeZeroPool (AuthVarStroageSize); > + AuthVarStorage =3D AllocateRuntimeZeroPool (AuthVarStorageSize); > ASSERT (AuthVarStorage !=3D NULL); > if (AuthVarStorage =3D=3D NULL) { > return NULL; > @@ -3608,7 +3739,7 @@ ConvertNormalVarStorageToAuthVarStorage ( > AuthVarStorage->State =3D NormalVarStorage->State; > AuthVarStorage->Size =3D (UINT32)((UINTN)AuthStartPtr - > (UINTN)AuthVarStorage); > CopyGuid (&AuthVarStorage->Signature, &gEfiAuthenticatedVariableGuid); > - ASSERT (AuthVarStorage->Size <=3D AuthVarStroageSize); > + ASSERT (AuthVarStorage->Size <=3D AuthVarStorageSize); >=20 > // > // Restore AuthFormat > @@ -3774,7 +3905,7 @@ VariableCommonInitialize ( > // > // Allocate memory for volatile variable store, note that there is a s= cratch > space to store scratch data. > // > - ScratchSize =3D GetMaxVariableSize (); > + ScratchSize =3D GetMaxVariableSize () * 2= ; > mVariableModuleGlobal->ScratchBufferSize =3D ScratchSize; > VolatileVariableStore =3D AllocateRuntimePool (PcdG= et32 > (PcdVariableStoreSize) + ScratchSize); > if (VolatileVariableStore =3D=3D NULL) { > diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c > b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c > index 03fec3048dc4..52bf29ec4c5c 100644 > --- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c > +++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c > @@ -3,7 +3,7 @@ > and volatile storage space and install variable architecture protocol. >=20 > Copyright (C) 2013, Red Hat, Inc. > -Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
> +Copyright (c) 2006 - 2022, Intel Corporation. All rights reserved.
> (C) Copyright 2015 Hewlett Packard Enterprise Development LP
> Copyright (c) Microsoft Corporation. > SPDX-License-Identifier: BSD-2-Clause-Patent > @@ -14,6 +14,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent >=20 > #include > #include > +#include "VariableParsing.h" >=20 > EFI_STATUS > EFIAPI > @@ -534,6 +535,29 @@ VariableServiceInitialize ( > EFI_EVENT ReadyToBootEvent; > EFI_EVENT EndOfDxeEvent; >=20 > + PROTECTED_VARIABLE_CONTEXT_IN ContextIn; > + > + // > + // Initialze protected variable service, if enabled. > + // > + ContextIn.StructSize =3D sizeof (ContextIn); > + ContextIn.StructVersion =3D > PROTECTED_VARIABLE_CONTEXT_IN_STRUCT_VERSION; > + > + ContextIn.FindVariableSmm =3D NULL; > + ContextIn.GetVariableInfo =3D GetVariableInfo; > + ContextIn.GetNextVariableInfo =3D GetNextVariableInfo; > + ContextIn.UpdateVariableStore =3D VariableExLibUpdateNvVariable; > + ContextIn.UpdateVariable =3D VariableExLibUpdateVariable; > + > + ContextIn.MaxVariableSize =3D (UINT32)GetMaxVariableSize (); > + ContextIn.VariableServiceUser =3D FromSmmModule; > + > + Status =3D ProtectedVariableLibInitialize (&ContextIn); > + if (EFI_ERROR (Status) && (Status !=3D EFI_UNSUPPORTED)) { > + ASSERT_EFI_ERROR (Status); > + return Status; > + } > + > Status =3D VariableCommonInitialize (); > ASSERT_EFI_ERROR (Status); >=20 > diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableExLib.c > b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableExLib.c > index 62cde0335512..5904bcbff78a 100644 > --- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableExLib.c > +++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableExLib.c > @@ -1,13 +1,14 @@ > /** @file > Provides variable driver extended services. >=20 > -Copyright (c) 2015 - 2019, Intel Corporation. All rights reserved.
> +Copyright (c) 2015 - 2022, Intel Corporation. All rights reserved.
> SPDX-License-Identifier: BSD-2-Clause-Patent >=20 > **/ >=20 > #include "Variable.h" > #include "VariableParsing.h" > +#include "VariableRuntimeCache.h" >=20 > /** > Finds variable in storage blocks of volatile and non-volatile storage = areas. > @@ -38,6 +39,7 @@ VariableExLibFindVariable ( > EFI_STATUS Status; > VARIABLE_POINTER_TRACK Variable; > AUTHENTICATED_VARIABLE_HEADER *AuthVariable; > + PROTECTED_VARIABLE_INFO VarInfo; >=20 > Status =3D FindVariable ( > VariableName, > @@ -56,9 +58,12 @@ VariableExLibFindVariable ( > return Status; > } >=20 > - AuthVariableInfo->DataSize =3D DataSizeOfVariable (Variable.CurrPtr, > mVariableModuleGlobal->VariableGlobal.AuthFormat); > - AuthVariableInfo->Data =3D GetVariableDataPtr (Variable.CurrPtr, > mVariableModuleGlobal->VariableGlobal.AuthFormat); > - AuthVariableInfo->Attributes =3D Variable.CurrPtr->Attributes; > + AuthVariableInfo->NameSize =3D NameSizeOfVariable (Variable.CurrPt= r, > mVariableModuleGlobal->VariableGlobal.AuthFormat); > + AuthVariableInfo->VariableName =3D GetVariableNamePtr (Variable.CurrPt= r, > mVariableModuleGlobal->VariableGlobal.AuthFormat); > + AuthVariableInfo->VendorGuid =3D GetVendorGuidPtr (Variable.CurrPtr, > mVariableModuleGlobal->VariableGlobal.AuthFormat); > + AuthVariableInfo->DataSize =3D DataSizeOfVariable (Variable.CurrPt= r, > mVariableModuleGlobal->VariableGlobal.AuthFormat); > + AuthVariableInfo->Data =3D GetVariableDataPtr (Variable.CurrPt= r, > mVariableModuleGlobal->VariableGlobal.AuthFormat); > + AuthVariableInfo->Attributes =3D Variable.CurrPtr->Attributes; > if (mVariableModuleGlobal->VariableGlobal.AuthFormat) { > AuthVariable =3D (AUTHENTICATED_VARIABLE_HEADER > *)Variable.CurrPtr; > AuthVariableInfo->PubKeyIndex =3D AuthVariable->PubKeyIndex; > @@ -66,6 +71,24 @@ VariableExLibFindVariable ( > AuthVariableInfo->TimeStamp =3D &AuthVariable->TimeStamp; > } >=20 > + CopyMem (&VarInfo.Header, AuthVariableInfo, sizeof (VarInfo.Header)); > + > + VarInfo.Buffer =3D Variable.CurrPtr; > + VarInfo.PlainData =3D NULL; > + VarInfo.PlainDataSize =3D 0; > + VarInfo.Flags.Auth =3D mVariableModuleGlobal->VariableGlobal.AuthFo= rmat; > + > + // > + // In case the variable is encrypted. > + // > + Status =3D ProtectedVariableLibGetByInfo (&VarInfo); > + if (!EFI_ERROR (Status)) { > + if (VarInfo.PlainData !=3D NULL) { > + AuthVariableInfo->Data =3D VarInfo.PlainData; > + AuthVariableInfo->DataSize =3D VarInfo.PlainDataSize; > + } > + } > + > return EFI_SUCCESS; > } >=20 > @@ -99,6 +122,7 @@ VariableExLibFindNextVariable ( > VARIABLE_HEADER *VariablePtr; > AUTHENTICATED_VARIABLE_HEADER *AuthVariablePtr; > VARIABLE_STORE_HEADER > *VariableStoreHeader[VariableStoreTypeMax]; > + PROTECTED_VARIABLE_INFO VarInfo; >=20 > VariableStoreHeader[VariableStoreTypeVolatile] =3D (VARIABLE_STORE_HEA= DER > *)(UINTN)mVariableModuleGlobal->VariableGlobal.VolatileVariableBase; > VariableStoreHeader[VariableStoreTypeHob] =3D (VARIABLE_STORE_HEA= DER > *)(UINTN)mVariableModuleGlobal->VariableGlobal.HobVariableBase; > @@ -123,6 +147,7 @@ VariableExLibFindNextVariable ( > return Status; > } >=20 > + AuthVariableInfo->NameSize =3D NameSizeOfVariable (VariablePtr, > mVariableModuleGlobal->VariableGlobal.AuthFormat); > AuthVariableInfo->VariableName =3D GetVariableNamePtr (VariablePtr, > mVariableModuleGlobal->VariableGlobal.AuthFormat); > AuthVariableInfo->VendorGuid =3D GetVendorGuidPtr (VariablePtr, > mVariableModuleGlobal->VariableGlobal.AuthFormat); > AuthVariableInfo->DataSize =3D DataSizeOfVariable (VariablePtr, > mVariableModuleGlobal->VariableGlobal.AuthFormat); > @@ -135,6 +160,20 @@ VariableExLibFindNextVariable ( > AuthVariableInfo->TimeStamp =3D &AuthVariablePtr->TimeStamp; > } >=20 > + CopyMem (&VarInfo.Header, AuthVariableInfo, sizeof (VarInfo.Header)); > + > + VarInfo.Buffer =3D VariablePtr; > + VarInfo.PlainData =3D NULL; > + VarInfo.PlainDataSize =3D 0; > + > + Status =3D ProtectedVariableLibGetByInfo (&VarInfo); > + if (!EFI_ERROR (Status)) { > + if (VarInfo.PlainData !=3D NULL) { > + AuthVariableInfo->Data =3D VarInfo.PlainData; > + AuthVariableInfo->DataSize =3D VarInfo.PlainDataSize; > + } > + } > + > return EFI_SUCCESS; > } >=20 > @@ -256,3 +295,123 @@ VariableExLibAtRuntime ( > { > return AtRuntime (); > } > + > +/** > + Update partial data of a variable on NV storage and/or cached copy. > + > + @param[in] VariableInfo Pointer to a variable with detailed informat= ion. > + @param[in] Offset Offset to write from. > + @param[in] Size Size of data Buffer to update. > + @param[in] Buffer Pointer to data buffer to update. > + > + @retval EFI_SUCCESS The variable data was updated successf= ully. > + @retval EFI_UNSUPPORTED If this function is called directly in= runtime. > + @retval EFI_INVALID_PARAMETER If VariableInfo, Buffer or Size are no= t > valid. > + @retval Others Failed to update NV storage or variabl= e cache. > + > +**/ > +EFI_STATUS > +EFIAPI > +VariableExLibUpdateNvVariable ( > + IN PROTECTED_VARIABLE_INFO *VariableInfo, > + IN UINTN Offset, > + IN UINT32 Size, > + IN UINT8 *Buffer > + ) > +{ > + EFI_STATUS Status; > + VARIABLE_GLOBAL *Global; > + VARIABLE_RUNTIME_CACHE *CacheInstance; > + VARIABLE_HEADER *VariableCache; > + > + if ((mVariableModuleGlobal =3D=3D NULL) || (mNvVariableCache =3D=3D NU= LL)) { > + return EFI_UNSUPPORTED; > + } > + > + // > + // Flush the cache to store. > + // > + if (Size =3D=3D (UINT32)-1) { > + Status =3D FtwVariableSpace ( > + mVariableModuleGlobal->VariableGlobal.NonVolatileVariable= Base, > + mNvVariableCache > + ); > + if ( !EFI_ERROR (Status) > + && (mVariableModuleGlobal->VariableGlobal.HobVariableBase !=3D 0)= ) > + { > + FlushHobVariableToFlash (NULL, NULL); > + if (mVariableModuleGlobal->VariableGlobal.HobVariableBase !=3D 0) = { > + FreePool ((VOID *)(UINTN)mVariableModuleGlobal- > >VariableGlobal.HobVariableBase); > + mVariableModuleGlobal->VariableGlobal.HobVariableBase =3D 0; > + } > + } > + > + return Status; > + } > + > + if ( (VariableInfo =3D=3D NULL) > + || (VariableInfo->StoreIndex =3D=3D VAR_INDEX_INVALID) > + || (Buffer =3D=3D NULL) > + || (Size =3D=3D 0)) > + { > + ASSERT (VariableInfo !=3D NULL); > + ASSERT (VariableInfo->StoreIndex !=3D VAR_INDEX_INVALID); > + ASSERT (Buffer !=3D NULL); > + ASSERT (Size !=3D 0); > + return EFI_INVALID_PARAMETER; > + } > + > + Global =3D &mVariableModuleGlobal->VariableGlobal; > + > + VariableCache =3D (VARIABLE_HEADER *)((UINTN)mNvVariableCache + > (UINTN)VariableInfo->StoreIndex); > + > + ASSERT ( > + StrCmp ( > + VariableInfo->Header.VariableName, > + GetVariableNamePtr (VariableCache, Global->AuthFormat) > + ) =3D=3D 0 > + ); > + ASSERT ( > + CompareGuid ( > + VariableInfo->Header.VendorGuid, > + GetVendorGuidPtr (VariableCache, Global->AuthFormat) > + ) > + ); > + > + // > + // Forcibly update part data of flash copy of the variable ... > + // > + Status =3D UpdateVariableStore ( > + Global, > + FALSE, > + FALSE, > + mVariableModuleGlobal->FvbInstance, > + (UINTN)(Global->NonVolatileVariableBase + VariableInfo->St= oreIndex + > Offset), > + Size, > + Buffer > + ); > + if (EFI_ERROR (Status)) { > + ASSERT_EFI_ERROR (Status); > + return Status; > + } > + > + // > + // ... as well as the local cached copy. > + // > + CopyMem ((VOID *)((UINTN)VariableCache + Offset), Buffer, Size); > + > + // > + // Sync remote cached copy. > + // > + CacheInstance =3D &Global- > >VariableRuntimeCacheContext.VariableRuntimeNvCache; > + if (CacheInstance->Store !=3D NULL) { > + Status =3D SynchronizeRuntimeVariableCache ( > + CacheInstance, > + (UINTN)VariableInfo->StoreIndex + Offset, > + Size > + ); > + ASSERT_EFI_ERROR (Status); > + } > + > + return EFI_SUCCESS; > +} > diff --git > a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableNonVolatile.c > b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableNonVolatile.c > index 5e9d40b67ac2..e8b8f0b7f705 100644 > --- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableNonVolatile.c > +++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableNonVolatile.c > @@ -1,7 +1,7 @@ > /** @file > Common variable non-volatile store routines. >=20 > -Copyright (c) 2019, Intel Corporation. All rights reserved.
> +Copyright (c) 2019 - 2022, Intel Corporation. All rights reserved.
> SPDX-License-Identifier: BSD-2-Clause-Patent >=20 > **/ > @@ -120,6 +120,181 @@ InitEmuNonVolatileVariableStore ( > return EFI_SUCCESS; > } >=20 > +/** > + > + Create a dummy variable used to fill the gap in NV variable storage ca= used by > + the invalid variables found in HMAC verification phase. > + > + @param[out] Variable Variable buffer. > + @param[in] Name Variable Name. > + @param[in] Guid Vendor GUID of the variable. > + @param[in] Size Whole size of the variable requested. > + @param[in] AuthFlag Variable format flag. > + > +**/ > +STATIC > +VOID > +CreateDummyVariable ( > + OUT VARIABLE_HEADER *Variable, > + IN CHAR16 *Name, > + IN EFI_GUID *Guid, > + IN UINT32 Size, > + IN BOOLEAN AuthFlag > + ) > +{ > + AUTHENTICATED_VARIABLE_HEADER *AuthVariable; > + > + ASSERT (Variable !=3D NULL); > + > + if (Name =3D=3D NULL) { > + Name =3D L"Dummy"; > + } > + > + if (AuthFlag) { > + AuthVariable =3D (AUTHENTICATED_VARIABLE_HEADER *)Variable; > + > + AuthVariable->StartId =3D VARIABLE_DATA; > + AuthVariable->State =3D VAR_ADDED & VAR_DELETED; > + AuthVariable->Attributes =3D EFI_VARIABLE_NON_VOLATILE; > + AuthVariable->NameSize =3D (UINT32)StrSize (Name); > + AuthVariable->DataSize =3D Size - sizeof > (AUTHENTICATED_VARIABLE_HEADER) > + - AuthVariable->NameSize; > + if (Guid !=3D NULL) { > + CopyMem ((VOID *)&AuthVariable->VendorGuid, (VOID *)Guid, sizeof > (EFI_GUID)); > + } > + > + CopyMem (GetVariableNamePtr (Variable, AuthFlag), (VOID *)Name, > AuthVariable->NameSize); > + } else { > + Variable->StartId =3D VARIABLE_DATA; > + Variable->State =3D VAR_ADDED & VAR_DELETED; > + Variable->Attributes =3D EFI_VARIABLE_NON_VOLATILE; > + Variable->NameSize =3D (UINT32)StrSize (Name); > + Variable->DataSize =3D Size - sizeof (VARIABLE_HEADER) - Variable- > >NameSize; > + if (Guid !=3D NULL) { > + CopyMem ((VOID *)&Variable->VendorGuid, (VOID *)Guid, sizeof > (EFI_GUID)); > + } > + > + CopyMem (GetVariableNamePtr (Variable, AuthFlag), (VOID *)Name, > Variable->NameSize); > + } > +} > + > +/** > + > + Init protected variable store. > + > + @param[in, out] VariableStore Pointer to real protected variable sto= re base. > + > +**/ > +EFI_STATUS > +InitProtectedVariableStore ( > + IN OUT VARIABLE_STORE_HEADER *VariableStore > + ) > +{ > + EFI_STATUS Status; > + PROTECTED_VARIABLE_INFO VarInfo; > + UINTN Size; > + UINTN Index; > + BOOLEAN AuthFlag; > + EFI_PHYSICAL_ADDRESS NextVariableStore; > + EFI_PHYSICAL_ADDRESS *VarList; > + UINTN NumVars; > + UINTN CurrVar; > + > + SetMem ( > + (UINT8 *)VariableStore + sizeof (VARIABLE_STORE_HEADER), > + VariableStore->Size - sizeof (VARIABLE_STORE_HEADER), > + 0xFF > + ); > + Index =3D sizeof (VARIABLE_STORE_HEADER); > + > + VarList =3D NULL; > + NumVars =3D 0; > + ProtectedVariableLibGetSortedList (&VarList, &NumVars); > + > + // > + // Search variable in the order of StoreIndex > + // > + ZeroMem (&VarInfo, sizeof (VarInfo)); > + > + for (CurrVar =3D 0; CurrVar < NumVars; CurrVar++) { > + VarInfo.Buffer =3D NULL; > + VarInfo.StoreIndex =3D VarList[CurrVar]; > + if (VarInfo.StoreIndex =3D=3D VAR_INDEX_INVALID) { > + break; > + } > + > + Status =3D ProtectedVariableLibFind (&VarInfo); > + if (EFI_ERROR (Status)) { > + break; > + } > + > + ASSERT (VarInfo.Buffer !=3D NULL); > + > + AuthFlag =3D VarInfo.Flags.Auth; > + if (VarInfo.StoreIndex =3D=3D VAR_INDEX_INVALID) { > + continue; > + } else { > + ASSERT (VarInfo.StoreIndex =3D=3D HEADER_ALIGN (VarInfo.StoreIndex= )); > + ASSERT (VarInfo.StoreIndex < (VariableStore->Size - sizeof > (VARIABLE_STORE_HEADER))); > + ASSERT ((VariableStore->Size - VarInfo.StoreIndex) > GetVariableHe= aderSize > (AuthFlag)); > + } > + > + // > + // Fill gap caused by invalid variable. > + // > + if (VarInfo.StoreIndex > Index) { > + Size =3D (UINTN)VarInfo.StoreIndex - Index; > + CreateDummyVariable ( > + (VARIABLE_HEADER *)((UINT8 *)VariableStore + Index), > + NULL, > + NULL, > + (UINT32)Size, > + AuthFlag > + ); > + Index +=3D Size; > + } > + > + Size =3D (UINTN)GetNextVariablePtr (VarInfo.Buffer, AuthFlag) > + - (UINTN)VarInfo.Buffer; > + CopyMem ((UINT8 *)VariableStore + VarInfo.StoreIndex, VarInfo.Buffer= , > Size); > + > + Index +=3D Size; > + Index =3D HEADER_ALIGN (Index); > + > + NextVariableStore =3D (EFI_PHYSICAL_ADDRESS)((UINTN)VariableStore + > VarInfo.StoreIndex + Size); > + } > + > + // > + // Search variable in the order of StoreIndex > + // > + ZeroMem (&VarInfo, sizeof (VarInfo)); > + for ( ; CurrVar < NumVars; CurrVar++) { > + VarInfo.Buffer =3D NULL; > + VarInfo.StoreIndex =3D VarList[CurrVar]; > + Status =3D ProtectedVariableLibFind (&VarInfo); > + if (EFI_ERROR (Status)) { > + break; > + } > + > + ASSERT (VarInfo.Buffer !=3D NULL); > + > + AuthFlag =3D VarInfo.Flags.Auth; > + if (VarInfo.StoreIndex =3D=3D VAR_INDEX_INVALID) { > + Size =3D (UINTN)GetNextVariablePtr (VarInfo.Buffer, AuthFlag) > + - (UINTN)VarInfo.Buffer; > + CopyMem ((UINT8 *)&NextVariableStore, VarInfo.Buffer, Size); > + Status =3D ProtectedVariableLibRefresh (VarInfo.Buffer,= 0, > NextVariableStore - (UINTN)VariableStore, FALSE); > + NextVariableStore =3D NextVariableStore + Size; > + } > + } > + > + if (Status =3D=3D EFI_UNSUPPORTED) { > + return Status; > + } > + > + return EFI_SUCCESS; > +} > + > /** > Init real non-volatile variable store. >=20 > @@ -230,6 +405,16 @@ InitRealNonVolatileVariableStore ( > return EFI_VOLUME_CORRUPTED; > } >=20 > + // > + // Overwrite the store with verified copy of protected variables, if e= nabled. > + // > + Status =3D InitProtectedVariableStore (VariableStore); > + if ((Status !=3D EFI_SUCCESS) && (Status !=3D EFI_UNSUPPORTED)) { > + FreePool (NvStorageData); > + DEBUG ((DEBUG_ERROR, "Variable integrity might have been > compromised\n")); > + return Status; > + } > + > mNvFvHeaderCache =3D FvHeader; >=20 > *VariableStoreBase =3D (EFI_PHYSICAL_ADDRESS)(UINTN)VariableStore; > @@ -323,7 +508,12 @@ InitNonVolatileVariableStore ( > // Parse non-volatile variable data and get last variable offset. > // > Variable =3D GetStartPointer (mNvVariableCache); > - while (IsValidVariableHeader (Variable, GetEndPointer (mNvVariableCach= e))) { > + while (IsValidVariableHeader ( > + Variable, > + GetEndPointer (mNvVariableCache), > + mVariableModuleGlobal->VariableGlobal.AuthFormat > + )) > + { > NextVariable =3D GetNextVariablePtr (Variable, mVariableModuleGlobal= - > >VariableGlobal.AuthFormat); > VariableSize =3D (UINTN)NextVariable - (UINTN)Variable; > if ((Variable->Attributes & (EFI_VARIABLE_NON_VOLATILE | > EFI_VARIABLE_HARDWARE_ERROR_RECORD)) =3D=3D > (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) > { > diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableParsing.c > b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableParsing.c > index 39060ed405b8..000e4b546888 100644 > --- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableParsing.c > +++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableParsing.c > @@ -2,11 +2,12 @@ > Functions in this module are associated with variable parsing operatio= ns and > are intended to be usable across variable driver source files. >=20 > -Copyright (c) 2019, Intel Corporation. All rights reserved.
> +Copyright (c) 2019 - 2022, Intel Corporation. All rights reserved.
> SPDX-License-Identifier: BSD-2-Clause-Patent >=20 > **/ >=20 > +#include "Variable.h" > #include "VariableParsing.h" >=20 > /** > @@ -15,6 +16,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent >=20 > @param[in] Variable Pointer to the Variable Header. > @param[in] VariableStoreEnd Pointer to the Variable Store End. > + @param[in] AuthFormat TRUE indicates authenticated variables a= re used. > + FALSE indicates authenticated variables = are not used. >=20 > @retval TRUE Variable header is valid. > @retval FALSE Variable header is not valid. > @@ -23,10 +26,14 @@ SPDX-License-Identifier: BSD-2-Clause-Patent > BOOLEAN > IsValidVariableHeader ( > IN VARIABLE_HEADER *Variable, > - IN VARIABLE_HEADER *VariableStoreEnd > + IN VARIABLE_HEADER *VariableStoreEnd, > + IN BOOLEAN AuthFormat > ) > { > - if ((Variable =3D=3D NULL) || (Variable >=3D VariableStoreEnd) || (Var= iable->StartId !=3D > VARIABLE_DATA)) { > + if ( (Variable =3D=3D NULL) > + || (((UINTN)Variable + GetVariableHeaderSize (AuthFormat)) >=3D > (UINTN)VariableStoreEnd) > + || (Variable->StartId !=3D VARIABLE_DATA)) > + { > // > // Variable is NULL or has reached the end of variable store, > // or the StartId is not correct. > @@ -341,6 +348,52 @@ GetVariableDataOffset ( > return Value; > } >=20 > +/** > + Get variable data payload. > + > + @param[in] Variable Pointer to the Variable Header. > + @param[in,out] Data Pointer to buffer used to store the varia= ble data. > + @param[in,out] DataSize Size of buffer passed by Data. > + Size of data copied into Data buffer. > + @param[in] AuthFlag Auth-variable indicator. > + > + @return EFI_SUCCESS Data was fetched. > + @return EFI_INVALID_PARAMETER DataSize is NULL. > + @return EFI_BUFFER_TOO_SMALL DataSize is smaller than size of varia= ble > data. > + > +**/ > +EFI_STATUS > +GetVariableData ( > + IN VARIABLE_HEADER *Variable, > + IN OUT VOID *Data, > + IN OUT UINT32 *DataSize, > + IN BOOLEAN AuthFlag > + ) > +{ > + UINT32 Size; > + > + if (DataSize =3D=3D NULL) { > + ASSERT (DataSize !=3D NULL); > + return EFI_INVALID_PARAMETER; > + } > + > + Size =3D (UINT32)DataSizeOfVariable (Variable, AuthFlag); > + if (*DataSize < Size) { > + *DataSize =3D Size; > + return EFI_BUFFER_TOO_SMALL; > + } > + > + if (Data =3D=3D NULL) { > + ASSERT (Data !=3D NULL); > + return EFI_INVALID_PARAMETER; > + } > + > + CopyMem (Data, GetVariableDataPtr (Variable, AuthFlag), Size); > + *DataSize =3D Size; > + > + return EFI_SUCCESS; > +} > + > /** >=20 > This code gets the pointer to the next variable header. > @@ -479,7 +532,7 @@ FindVariableEx ( > InDeletedVariable =3D NULL; >=20 > for ( PtrTrack->CurrPtr =3D PtrTrack->StartPtr > - ; IsValidVariableHeader (PtrTrack->CurrPtr, PtrTrack->EndPtr) > + ; IsValidVariableHeader (PtrTrack->CurrPtr, PtrTrack->EndPtr, Au= thFormat) > ; PtrTrack->CurrPtr =3D GetNextVariablePtr (PtrTrack->CurrPtr, A= uthFormat) > ) > { > @@ -608,7 +661,7 @@ VariableServiceGetNextVariableInternal ( > // > // Switch to the next variable store if needed > // > - while (!IsValidVariableHeader (Variable.CurrPtr, Variable.EndPtr)) { > + while (!IsValidVariableHeader (Variable.CurrPtr, Variable.EndPtr, > AuthFormat)) { > // > // Find current storage index > // > @@ -804,3 +857,260 @@ UpdateVariableInfo ( > } > } > } > + > +/** > + > + Retrieve details about a variable and return them in VariableInfo->Hea= der. > + > + If VariableInfo->Address is given, this function will calculate its of= fset > + relative to given variable storage via VariableStore; Otherwise, it wi= ll try > + other internal variable storages or cached copies. It's assumed that, = for all > + copies of NV variable storage, all variables are stored in the same re= lative > + position. If VariableInfo->Address is found in the range of any storag= e copies, > + its offset relative to that storage should be the same in other copies= . > + > + If VariableInfo->Offset is given (non-zero) but not VariableInfo->Addr= ess, > + this function will return the variable memory address inside VariableS= tore, > + if given, via VariableInfo->Address; Otherwise, the address of other s= torage > + copies will be returned, if any. > + > + For a new variable whose offset has not been determined, a value of -1= as > + VariableInfo->Offset should be passed to skip the offset calculation. > + > + @param[in,out] VariableInfo Pointer to variable informatio= n. > + > + @retval EFI_INVALID_PARAMETER VariableInfo is NULL or both VariableIn= fo- > >Address > + and VariableInfo->Offset are NULL (0). > + @retval EFI_NOT_FOUND If given Address or Offset is out of ra= nge of > + any given or internal storage copies. > + @retval EFI_SUCCESS Variable details are retrieved successf= ully. > + > +**/ > +EFI_STATUS > +EFIAPI > +GetVariableInfo ( > + IN OUT PROTECTED_VARIABLE_INFO *VariableInfo > + ) > +{ > + VARIABLE_STORE_HEADER *Stores[2]; > + UINTN Index; > + VARIABLE_HEADER *VariablePtr; > + VARIABLE_HEADER *VariableBuffer; > + AUTHENTICATED_VARIABLE_HEADER *AuthVariablePtr; > + BOOLEAN AuthFlag; > + UINTN NameSize; > + UINTN DataSize; > + UINTN VariableSize; > + > + if ((VariableInfo =3D=3D NULL) || ( (VariableInfo->Buffer =3D=3D NULL= ) > + && (VariableInfo->StoreIndex =3D=3D VAR_= INDEX_INVALID))) > + { > + ASSERT (VariableInfo !=3D NULL); > + ASSERT (VariableInfo->Buffer !=3D NULL || VariableInfo->StoreIndex != =3D > VAR_INDEX_INVALID); > + return EFI_INVALID_PARAMETER; > + } > + > + Stores[0] =3D mNvVariableCache; > + Stores[1] =3D (mVariableModuleGlobal !=3D NULL) > + ? (VARIABLE_STORE_HEADER *)(UINTN)mVariableModuleGlobal- > >VariableGlobal.NonVolatileVariableBase > + : NULL; > + > + VariableBuffer =3D VariableInfo->Buffer; > + VariablePtr =3D NULL; > + if (VariableInfo->StoreIndex !=3D VAR_INDEX_INVALID) { > + for (Index =3D 0; Index < ARRAY_SIZE (Stores); ++Index) { > + if (Stores[Index] =3D=3D NULL) { > + continue; > + } > + > + if ((UINTN)VariableInfo->StoreIndex > + < ((UINTN)GetEndPointer (Stores[Index]) - (UINTN)Stores[Index]= )) > + { > + VariablePtr =3D (VARIABLE_HEADER *)((UINTN)Stores[Index= ] + > (UINTN)VariableInfo->StoreIndex); > + VariableInfo->Buffer =3D VariablePtr; > + break; > + } > + } > + } else { > + VariablePtr =3D VariableInfo->Buffer; > + } > + > + if (VariablePtr =3D=3D NULL) { > + return EFI_NOT_FOUND; > + } > + > + AuthFlag =3D VariableInfo->Flags.Auth; > + ASSERT (AuthFlag =3D=3D TRUE || AuthFlag =3D=3D FALSE); > + > + // > + // Make a copy of the whole variable if a buffer is passed in. > + // > + if ((VariableBuffer !=3D NULL) && (VariableBuffer !=3D VariablePtr)) { > + VariableSize =3D (UINTN)GetNextVariablePtr (VariablePtr, AuthFlag) > + - (UINTN)VariablePtr; > + CopyMem (VariableBuffer, VariablePtr, VariableSize); > + } > + > + // > + // AuthVariable header > + // > + if (AuthFlag) { > + AuthVariablePtr =3D (AUTHENTICATED_VARIABLE_HEADER *)VariablePtr; > + > + VariableInfo->Header.State =3D AuthVariablePtr->State; > + VariableInfo->Header.Attributes =3D AuthVariablePtr->Attributes; > + VariableInfo->Header.PubKeyIndex =3D AuthVariablePtr->PubKeyIndex= ; > + VariableInfo->Header.MonotonicCount =3D ReadUnaligned64 ( > + &(AuthVariablePtr->Monotonic= Count) > + ); > + if (VariableInfo->Header.TimeStamp !=3D NULL) { > + CopyMem ( > + VariableInfo->Header.TimeStamp, > + &AuthVariablePtr->TimeStamp, > + sizeof (EFI_TIME) > + ); > + } else if (VariableBuffer !=3D NULL) { > + AuthVariablePtr =3D (AUTHENTICATED_VARIABLE_HEADER > *)VariableBuffer; > + VariableInfo->Header.TimeStamp =3D &AuthVariablePtr->TimeStamp; > + } > + } else { > + VariableInfo->Header.State =3D VariablePtr->State; > + VariableInfo->Header.Attributes =3D VariablePtr->Attributes; > + VariableInfo->Header.PubKeyIndex =3D 0; > + VariableInfo->Header.MonotonicCount =3D 0; > + VariableInfo->Header.TimeStamp =3D NULL; > + } > + > + // > + // VendorGuid > + // > + if (VariableInfo->Header.VendorGuid !=3D NULL) { > + CopyGuid ( > + VariableInfo->Header.VendorGuid, > + GetVendorGuidPtr (VariablePtr, AuthFlag) > + ); > + } else { > + VariableInfo->Header.VendorGuid =3D GetVendorGuidPtr (VariablePtr, > AuthFlag); > + } > + > + // > + // VariableName > + // > + NameSize =3D NameSizeOfVariable (VariablePtr, AuthFlag); > + if ( (VariableInfo->Header.VariableName !=3D NULL) > + && (VariableInfo->Header.NameSize >=3D NameSize)) > + { > + CopyMem ( > + VariableInfo->Header.VariableName, > + GetVariableNamePtr (VariablePtr, AuthFlag), > + NameSize > + ); > + } else if (VariableInfo->Header.VariableName !=3D NULL) { > + return EFI_BUFFER_TOO_SMALL; > + } else { > + VariableInfo->Header.VariableName =3D GetVariableNamePtr (VariablePt= r, > AuthFlag); > + } > + > + // > + // Data > + // > + DataSize =3D DataSizeOfVariable (VariablePtr, AuthFlag); > + if ( (VariableInfo->Header.Data !=3D NULL) > + && (VariableInfo->Header.DataSize >=3D DataSize)) > + { > + CopyMem ( > + VariableInfo->Header.Data, > + GetVariableDataPtr (VariablePtr, AuthFlag), > + NameSize > + ); > + } else if (VariableInfo->Header.Data !=3D NULL) { > + return EFI_BUFFER_TOO_SMALL; > + } else { > + VariableInfo->Header.Data =3D GetVariableDataPtr (VariablePtr, AuthF= lag); > + } > + > + // > + // Update size information about name & data. > + // > + VariableInfo->Header.NameSize =3D NameSize; > + VariableInfo->Header.DataSize =3D DataSize; > + > + return EFI_SUCCESS; > +} > + > +/** > + > + Retrieve details of the variable next to given variable within Variabl= eStore. > + > + If VarInfo->Address is NULL, the first one in VariableStore is returne= d. > + > + VariableStart and/or VariableEnd can be given optionally for the situa= tion > + in which the valid storage space is smaller than the VariableStore->Si= ze. > + This usually happens when PEI variable services make a compact variabl= e > + cache to save memory, which cannot make use VariableStore->Size to > determine > + the correct variable storage range. > + > + @param[in,out] VariableInfo Pointer to variable informatio= n. > + > + @retval EFI_INVALID_PARAMETER VariableInfo or VariableStore is NULL. > + @retval EFI_NOT_FOUND If the end of VariableStore is reached. > + @retval EFI_SUCCESS The next variable is retrieved successf= ully. > + > +**/ > +EFI_STATUS > +EFIAPI > +GetNextVariableInfo ( > + IN OUT PROTECTED_VARIABLE_INFO *VariableInfo > + ) > +{ > + VARIABLE_STORE_HEADER *VarStore; > + VARIABLE_HEADER *VariablePtr; > + VARIABLE_HEADER *VariableStart; > + VARIABLE_HEADER *VariableEnd; > + BOOLEAN AuthFlag; > + > + if (VariableInfo =3D=3D NULL) { > + ASSERT (VariableInfo !=3D NULL); > + return EFI_INVALID_PARAMETER; > + } > + > + if (mNvVariableCache !=3D NULL) { > + VarStore =3D mNvVariableCache; > + } else if (mVariableModuleGlobal !=3D NULL) { > + VarStore =3D (VARIABLE_STORE_HEADER *)(UINTN) > + mVariableModuleGlobal->VariableGlobal.NonVolatileVariable= Base; > + } else { > + return EFI_NOT_FOUND; > + } > + > + VariableStart =3D GetStartPointer (VarStore); > + VariableEnd =3D GetEndPointer (VarStore); > + > + if ((VariableInfo->Flags.Auth !=3D TRUE) && (VariableInfo->Flags.Auth = !=3D FALSE)) > { > + VariableInfo->Flags.Auth =3D CompareGuid ( > + &VarStore->Signature, > + &gEfiAuthenticatedVariableGuid > + ); > + } > + > + AuthFlag =3D VariableInfo->Flags.Auth; > + > + if (VariableInfo->StoreIndex =3D=3D VAR_INDEX_INVALID) { > + VariablePtr =3D VariableStart; > + } else { > + VariablePtr =3D (VARIABLE_HEADER *) > + ((UINTN)VarStore + (UINTN)VariableInfo->StoreIndex); > + if (VariablePtr >=3D VariableEnd) { > + return EFI_NOT_FOUND; > + } > + > + VariablePtr =3D GetNextVariablePtr (VariablePtr, AuthFlag); > + } > + > + if (!IsValidVariableHeader (VariablePtr, VariableEnd, AuthFlag)) { > + return EFI_NOT_FOUND; > + } > + > + VariableInfo->StoreIndex =3D (UINTN)VariablePtr - (UINTN)VarStore; > + return GetVariableInfo (VariableInfo); > +} > diff --git > a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeCache.c > b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeCache.c > index 9bb30bc1e804..dc319feee727 100644 > --- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeCache.c > +++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeCache.c > @@ -7,7 +7,7 @@ > This external input must be validated carefully to avoid security issu= e like > buffer overflow, integer overflow. >=20 > -Copyright (c) 2019, Intel Corporation. All rights reserved.
> +Copyright (c) 2019 - 2022, Intel Corporation. All rights reserved.
[JianJW]=20 It looks that there's no other changes in this file. No need to update the = year. > SPDX-License-Identifier: BSD-2-Clause-Patent >=20 > **/ > diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c > b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c > index 517cae7b00f8..c2b689f6202d 100644 > --- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c > +++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c > @@ -14,7 +14,7 @@ > VariableServiceSetVariable(), VariableServiceQueryVariableInfo(), > ReclaimForOS(), > SmmVariableGetStatistics() should also do validation based on its own > knowledge. >=20 > -Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.
> +Copyright (c) 2010 - 2022, Intel Corporation. All rights reserved.
> Copyright (c) 2018, Linaro, Ltd. All rights reserved.
> SPDX-License-Identifier: BSD-2-Clause-Patent >=20 > @@ -1045,6 +1045,13 @@ VariableWriteServiceInitializeSmm ( > { > EFI_STATUS Status; >=20 > + Status =3D ProtectedVariableLibWriteInit (); > + if (EFI_ERROR (Status) && (Status !=3D EFI_UNSUPPORTED)) { > + DEBUG ((DEBUG_ERROR, "Variable protection service: write-init failed= . > Status =3D %r\n", Status)); > + ASSERT_EFI_ERROR (Status); > + return; > + } > + > Status =3D VariableWriteServiceInitialize (); > if (EFI_ERROR (Status)) { > DEBUG ((DEBUG_ERROR, "Variable write service initialization failed. = Status > =3D %r\n", Status)); > @@ -1143,10 +1150,32 @@ MmVariableServiceInitialize ( > VOID > ) > { > - EFI_STATUS Status; > - EFI_HANDLE VariableHandle; > - VOID *SmmFtwRegistration; > - VOID *SmmEndOfDxeRegistration; > + EFI_STATUS Status; > + EFI_HANDLE VariableHandle; > + VOID *SmmFtwRegistration; > + VOID *SmmEndOfDxeRegistration; > + PROTECTED_VARIABLE_CONTEXT_IN ContextIn; > + > + // > + // Initialize protected variable service, if enabled. > + // > + ContextIn.StructSize =3D sizeof (ContextIn); > + ContextIn.StructVersion =3D > PROTECTED_VARIABLE_CONTEXT_IN_STRUCT_VERSION; > + > + ContextIn.FindVariableSmm =3D NULL; > + ContextIn.GetVariableInfo =3D GetVariableInfo; > + ContextIn.GetNextVariableInfo =3D GetNextVariableInfo; > + ContextIn.UpdateVariableStore =3D VariableExLibUpdateNvVariable; > + ContextIn.UpdateVariable =3D VariableExLibUpdateVariable; > + > + ContextIn.MaxVariableSize =3D (UINT32)GetMaxVariableSize (); > + ContextIn.VariableServiceUser =3D FromSmmModule; > + > + Status =3D ProtectedVariableLibInitialize (&ContextIn); > + if (EFI_ERROR (Status) && (Status !=3D EFI_UNSUPPORTED)) { > + ASSERT_EFI_ERROR (Status); > + return Status; > + } >=20 > // > // Variable initialize. > diff --git > a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c > b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c > index 4aaeb5ba8806..8fb8679671ad 100644 > --- > a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c > +++ > b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c > @@ -13,7 +13,7 @@ >=20 > InitCommunicateBuffer() is really function to check the variable data = size. >=20 > -Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.
> +Copyright (c) 2010 - 2022, Intel Corporation. All rights reserved.
> Copyright (c) Microsoft Corporation.
> SPDX-License-Identifier: BSD-2-Clause-Patent >=20 > @@ -36,11 +36,13 @@ SPDX-License-Identifier: BSD-2-Clause-Patent > #include > #include > #include > +#include [JianJW]=20 I didn't find any interface from IoLib.h used this file. >=20 > #include > #include >=20 > #include "PrivilegePolymorphic.h" > +#include "Variable.h" > #include "VariableParsing.h" >=20 > EFI_HANDLE mHandle =3D= NULL; > @@ -53,6 +55,8 @@ VARIABLE_INFO_ENTRY *mVariableInfo > =3D NULL; > VARIABLE_STORE_HEADER *mVariableRuntimeHobCacheBuffer =3D= NULL; > VARIABLE_STORE_HEADER *mVariableRuntimeNvCacheBuffer =3D= NULL; > VARIABLE_STORE_HEADER *mVariableRuntimeVolatileCacheBuffer =3D > NULL; > +VARIABLE_STORE_HEADER *mNvVariableCache =3D= NULL; > +VARIABLE_MODULE_GLOBAL *mVariableModuleGlobal =3D= NULL; > UINTN mVariableBufferSize; > UINTN mVariableRuntimeHobCacheBufferSize; > UINTN mVariableRuntimeNvCacheBufferSize; > @@ -616,7 +620,6 @@ FindVariableInRuntimeCache ( > ) > { > EFI_STATUS Status; > - UINTN TempDataSize; > VARIABLE_POINTER_TRACK RtPtrTrack; > VARIABLE_STORE_TYPE StoreType; > VARIABLE_STORE_HEADER *VariableStoreList[VariableStoreTypeMax]; > @@ -669,31 +672,23 @@ FindVariableInRuntimeCache ( > // > // 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); > - *DataSize =3D TempDataSize; > - > - UpdateVariableInfo (VariableName, VendorGuid, RtPtrTrack.Volatil= e, TRUE, > FALSE, FALSE, TRUE, &mVariableInfo); > - > - Status =3D EFI_SUCCESS; > - goto Done; > - } else { > - *DataSize =3D TempDataSize; > - Status =3D EFI_BUFFER_TOO_SMALL; > - goto Done; > + if (!RtPtrTrack.Volatile) { > + // > + // Currently only non-volatile variable needs protection. > + // > + Status =3D ProtectedVariableLibGetByBuffer (RtPtrTrack.CurrPtr, = Data, > (UINT32 *)DataSize, mVariableAuthFormat); > + } > + > + if (RtPtrTrack.Volatile || (Status =3D=3D EFI_UNSUPPORTED)) { > + Status =3D GetVariableData (RtPtrTrack.CurrPtr, Data, (UINT32 *)= DataSize, > mVariableAuthFormat); > + } > + > + if (!EFI_ERROR (Status)) { > + UpdateVariableInfo (VariableName, VendorGuid, RtPtrTrack.Volatil= e, > TRUE, FALSE, FALSE, FALSE, &mVariableInfo); > } > } > } >=20 > -Done: > if ((Status =3D=3D EFI_SUCCESS) || (Status =3D=3D EFI_BUFFER_TOO_SMALL= )) { > if ((Attributes !=3D NULL) && (RtPtrTrack.CurrPtr !=3D NULL)) { > *Attributes =3D RtPtrTrack.CurrPtr->Attributes; > -- > 2.35.1.windows.2