From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by mx.groups.io with SMTP id smtpd.web08.14952.1653215091667067527 for ; Sun, 22 May 2022 03:24:52 -0700 Authentication-Results: mx.groups.io; dkim=fail reason="unable to parse pub key" header.i=@intel.com header.s=intel header.b=a4Nm0YtB; spf=pass (domain: intel.com, ip: 134.134.136.126, 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=1653215091; x=1684751091; h=from:to:cc:subject:date:message-id:references: in-reply-to:content-transfer-encoding:mime-version; bh=g3zIMC8+/5Mh7xtTe5Tm71k02SAUClvX9IAYwO8w4VM=; b=a4Nm0YtBz6aLFGr+QOnedBiuPDACyrE2RQahX51mqSIzxwCXoVjdhPCi +3ewVJatietwdoGvxGX1nrnRvHMx6SqZaWaCqWVGPuY9wFXHt9x6H9LKQ ypt2QIVlCk8sz+D8JGD6ZR9/LFMAvDflGwOJbe8YQostDvqNu0yGlWn06 LxA5syGwiP0AEkDX93TkNxWN3z5c0fzhUXQcdKCGFCnL4CV5DPX+ojZ7s 8vyM5rfY8UDo8AdR6l8BCTxUWymqEq26uPuP7FVTstTRv7yTQgI+j2rtx jmb8xMhe5i1oeSZsztQ5TGOggKaY/MDRjeFiwHwQiEmiD9rEzzH4Xn4/U Q==; X-IronPort-AV: E=McAfee;i="6400,9594,10354"; a="255030651" X-IronPort-AV: E=Sophos;i="5.91,244,1647327600"; d="scan'208";a="255030651" Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by orsmga106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 May 2022 03:24:50 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.91,244,1647327600"; d="scan'208";a="628876398" Received: from fmsmsx605.amr.corp.intel.com ([10.18.126.85]) by fmsmga008.fm.intel.com with ESMTP; 22 May 2022 03:24:50 -0700 Received: from fmsmsx608.amr.corp.intel.com (10.18.126.88) by fmsmsx605.amr.corp.intel.com (10.18.126.85) 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 03:24:49 -0700 Received: from fmsmsx610.amr.corp.intel.com (10.18.126.90) by fmsmsx608.amr.corp.intel.com (10.18.126.88) 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 03:24:49 -0700 Received: from fmsedg601.ED.cps.intel.com (10.1.192.135) by fmsmsx610.amr.corp.intel.com (10.18.126.90) 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 03:24:49 -0700 Received: from NAM12-MW2-obe.outbound.protection.outlook.com (104.47.66.49) by edgegateway.intel.com (192.55.55.70) 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 03:24:48 -0700 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=SKnfpO8l/MYVRFTSrYQENgpiXSd4GvzIgXrQYBznp8TZilHRa3VGk3n1BcYnTH7Hlom1i99jyjOk8YIKKmQk2cOl2wTxaI0WzRDqGKwBG5jf83BHK/+8aj2sd5kLIJRYQ6pBOSiJ8Q/yXu0KcVIXctqMgFvS3ETzsmoVbLnAxx7uvaN5LKa1i4GdioTbWu+kijmwS06Gi1nmhHYnmLM2Yk1tO47BIZz+Rg2SNWBGKC5Rzq6MS+3UwWXLfBxNRL0eiho/2kk7nEp5OoGDKEVgxcOnHEPSg4W9xTiF1E74FQh8mBTUpDH61rz/G1bk9jFO/PvmIhfc7NHA0p9mzIwMPA== 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=WD1K9um98WDRhB3ShrrG1xpSWktjc7D8GL9LY0EP7FA=; b=cbBrUPhrvZVUtor7RBYPDq1TIPyuEXzNz5NeTkc9gJjT5yZL/bltp0aAt9gJaMz5vM+Uj5sJ50DvboAZo42DV2auKnI6byqYb9GtRvPpElhxwP+mwhXPiw4pMKbQM9IgyqFtfilo7l/5w+pEBuEG7vc1y2n95qe2CO25+//GH4mG9eu3oQnd3cxG+++KDeKMJ0yzjzQGdt0iP1CvnLvSnOD7xxFnXLXNtAaAL3U80nWRjPrBd0E03jV/9RcnxZxSIVkKhhssV/6MxZol0V8VR7mmhmkw6OtQe21L3/+SEHSorvme8HPgIE5KTb5Ko0lQpZm6T8aGL59wOl9oCVnC4Q== 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 BN7PR11MB2596.namprd11.prod.outlook.com (2603:10b6:406:b2::20) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5273.17; Sun, 22 May 2022 10:24:40 +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 10:24:40 +0000 From: "Wang, Jian J" To: "Vang, Judah" , "devel@edk2.groups.io" CC: "Gao, Liming" , "Mistry, Nishant C" Subject: Re: [Patch v2 08/28] MdeModulePkg: Add new Variable functionality Thread-Topic: [Patch v2 08/28] MdeModulePkg: Add new Variable functionality Thread-Index: AQHYW/O6I5TG/eeAnUizVYlYzprsea0qvWkQ Date: Sun, 22 May 2022 10:24:40 +0000 Message-ID: References: <20220429180430.3292-1-judah.vang@intel.com> <20220429180430.3292-9-judah.vang@intel.com> In-Reply-To: <20220429180430.3292-9-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: d51f7164-82b6-4bf9-7511-08da3bdd47ba x-ms-traffictypediagnostic: BN7PR11MB2596: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: /xo35Hhum+RlxYHRd+PkdchXCrIgBR1l9ysQB9RY9rjVGjOm29Qsd+67hwVlWg+hyB06Kl1cL//xUHmE8oJKN2HfMZvn+6XkBBHamXQQ90jX1cyQDcQz4/RzA94Xjqz82LpGV9OyePRb+Hux4xtyb7sj23LCkXsltOo1qnBRnHgpIVCdUxkwM/ivWtBHrIafAAhOpkT9RON2LONBH+zMYRhVOm2gSbZJ/IvRr/oXmm0aYt/hQ92qdL5zTspUt11ggSnFWrDTKVPIwRwNOtRXPnAt2dxfBfANnHYLm5NmhcT9UQ8fYFZL7RnDuSnBDxxAAi8ANW7hbbo1zeK6aRRVAKV+YRVTgSE8AbSqz+T+BlKrNdPcD6GT+nEOH1cLQe8V16BnHPMkTF0e5/TgV44EfzvyxYSsuBadOPiU4RAL8k97ugqUiFIUwldEjpHaeSw4NEL0O2FxtDQvJXk/EsjxkFiAykLmC4qjjVMmtMKzC6r/eA1m7jtE6GjL/EoknO6V5uHQHGwP3ijxm6C3M3lH0E0k2v0iOxfkK2HXslrOjq1dGRWwDQ/vF6h+RiwtCW4j2DW6rr3FQmZokK+z6CBQNA4XB0f/oeAEuuCvG/RyLKjO97ZBZOBs2j68JNbnf6Cgs0v9SJZjXjaF8jgsXL1aipCK9gTlDQuvH3RSSbEE6hjlcTiqrn7OqPK4pKXsys5aUDDEoToozUkDQYpUvSyWNylNP3NziNRnViDmRhmVfmvHYiMZjHFDE5VwVLy14Ok0fRDlrORHtxAK6mOIPq3zp/KA0lFa8akj0wwKm/IAt7s= 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)(186003)(55016003)(83380400001)(33656002)(110136005)(54906003)(86362001)(107886003)(38070700005)(82960400001)(122000001)(76116006)(66946007)(66556008)(66476007)(66446008)(64756008)(8676002)(4326008)(19627235002)(316002)(71200400001)(38100700002)(30864003)(52536014)(5660300002)(966005)(53546011)(9686003)(7696005)(45080400002)(26005)(6506007)(2906002)(508600001)(8936002)(559001)(579004);DIR:OUT;SFP:1102; x-ms-exchange-antispam-messagedata-chunkcount: 1 x-ms-exchange-antispam-messagedata-0: =?us-ascii?Q?OeoynIRKWsAk/Sqe+mGI4ViSB56CKwttnYSlM4yi/JepuDwE+eSy8v8aPM0h?= =?us-ascii?Q?MJlKXwBpDc1ebsl+D7wr9SEjOG6U30lmu92AskBQqKuzys/d3Ezlywjgj1JI?= =?us-ascii?Q?6bG+wV1S8xB6UBJ0JhA8+2KY7zAVUxtCQgWFJAkOjFIicdC+0mdoVT0NHn5u?= =?us-ascii?Q?TDz2UklzbiSlr6FtqlgQZd0NL2EDFSof96qnwyS73nV2p3f5mtKiquzTX1KC?= =?us-ascii?Q?WodYj6uzDpqRtvyFCrbJfi/r67UWR/xqLSUi8R0PshrwrMdjdqqBLA+XYY2B?= =?us-ascii?Q?HZezLBmzoL0yrbndbLQqfGGLjhXA4VqhsMHkfjrZmHpiPClCxYmrgxUeYNdG?= =?us-ascii?Q?cXXijCAY2eogWtS1Ud8qYasev83PzA7AsmikuYqyAWzzk1iyOdzg7WZYi9F6?= =?us-ascii?Q?+TWvuEjQRF5ZwsXKuKYuqRd6MhPocwFeXuxs0IDOcoCB0SXRzZZvrKja5dx9?= =?us-ascii?Q?qpycGh5/2b7xErNrJUTm8s+fbNiCnWa1oftNN1eN1r5zmXVSytqM3IfHwTeS?= =?us-ascii?Q?0TJzVbNDwSbpjFcgoi+7S1NSojgiClOeoRUPZ61igNUqGpDs051xHb1wWO30?= =?us-ascii?Q?D0YDppE+WgB3jLBYecBFQnZUbsaxbdsVcu2c1fCb4/Z5fR85hHllpznvSC4D?= =?us-ascii?Q?d4fLVTj3E4b2ze1HCtwyD0zuXb2BT6vrXIZvN3Fd+Wciv2yT44RXO6gkACF6?= =?us-ascii?Q?pmQ3kWA7MVVMmKA6F0qBajF9+1pD4UI5xwqSA1UeA3Z3OaMFaNuWVfBp9S9d?= =?us-ascii?Q?Vr+412zk6rqmHKnivwjsvA8pwiYJo3j4ud2aVIW7ydBhnt5CPIJKr5c2vdpq?= =?us-ascii?Q?9iQOyiCfgw2FF3HjYPzHmWHjsoXU6WB4az+N8Q28N4hGx7Ee3xRyDsogVBlF?= =?us-ascii?Q?nSyi/klVNfiCdTNdSyOjGUl1/kmqeN8uTSVzVy30M97/01CHQRVWHzXriEnr?= =?us-ascii?Q?QmER+gGpIStkUeONaj/KPs3/vDHBQ4hhIbJ1M8kVpDTYn2v/WcQdhYwz6d2Y?= =?us-ascii?Q?WfrCelSGtF0ToBUTPTOs8oPziZ+3OJDSmMh9oG/rO1IfNeRg10wtJiMDqYuF?= =?us-ascii?Q?2YKagd5lVEnLx8br3VBuzH9LZ+VBdyPSWMlJMuW81sMjjXnBqdFJoIiF+oij?= =?us-ascii?Q?DeMA3Rr+Gr+NKdar2545bLRnIs7GqSn8Llih6WeamjSeleD10rHmLHXSHsrB?= =?us-ascii?Q?9Abuj2bBOqERMovPsln5/1rAbYlgq2qDEvHxSpJVojmsM5Mt1y+Xd5FH31LA?= =?us-ascii?Q?Jdpct1I3ul92pYJid7wVUyxLtK6PfL/LZ4FBMjRlVuxKW0LgZFI26oOiU8MV?= =?us-ascii?Q?aHPgcIPDX+HQYcvgfNIvMx38w4acFBKrMCP1vBzJ3veQGfx1+psjOMtpGH6U?= =?us-ascii?Q?J+VcsJF9qktSubnC6pzR4WTPmFHICWLlYGKs/lk7TuIsH1pt6Qg6Cl5hOFXb?= =?us-ascii?Q?GjXhL79wtb5ZFRtiQ42QJ6Wf7Jt3pJJ46sHAx5/bQEUdusNwGNxOe3wKr6cf?= =?us-ascii?Q?vfb/qR/HWf/gTF7l6pEFtFb9gHOv/y+1x7GwT8MNIyC6NUC65jFrSuTqD44q?= =?us-ascii?Q?RK5gH5EyR54WZpNekc9AvKSVhWCSj54m64nWZOKBYPXcdTdY3tuOC/aNaaB9?= =?us-ascii?Q?aNGdEZsZIOoB774QEAO8Qc4arqk9DJK8KklJP8+mbIDpEZMX0xS4iUBOpogm?= =?us-ascii?Q?X1vZlMLawZJMahFfMZe9Z7UgtA9OBMDk1bzafRaMCaTceMrcmuMaA6+LAEsM?= =?us-ascii?Q?kyMJJ9laxg=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: d51f7164-82b6-4bf9-7511-08da3bdd47ba X-MS-Exchange-CrossTenant-originalarrivaltime: 22 May 2022 10:24:40.3403 (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: TIAiuS+ARSnDDZ/OSDBHbMux1K9McquAq8TZOjfStS+RrTHiLXpC1gdaSqtAm7CMlrkcoE4BYzPn4MBgkgGVrQ== X-MS-Exchange-Transport-CrossTenantHeadersStamped: BN7PR11MB2596 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, One general comment: please add variable store provision/recovery flow and explanations in the readme. See my other 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 08/28] MdeModulePkg: Add new Variable functionality >=20 > REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3D2594 >=20 > Provide new APIs for retrieving variable information. > Add new function stubs for retrieving Protected > variable information. >=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/Pei/VariablePei.inf | 10 +- > MdeModulePkg/Universal/Variable/Pei/Variable.h | 80 +- > MdeModulePkg/Universal/Variable/Pei/VariableParsing.h | 309 +++++++ > MdeModulePkg/Universal/Variable/Pei/VariableStore.h | 116 +++ > MdeModulePkg/Universal/Variable/Pei/Variable.c | 886 +++---------= ------ > MdeModulePkg/Universal/Variable/Pei/VariableParsing.c | 941 > ++++++++++++++++++++ > MdeModulePkg/Universal/Variable/Pei/VariableStore.c | 305 +++++++ > 7 files changed, 1891 insertions(+), 756 deletions(-) >=20 > diff --git a/MdeModulePkg/Universal/Variable/Pei/VariablePei.inf > b/MdeModulePkg/Universal/Variable/Pei/VariablePei.inf > index 7cbdd2385e8f..af172126a011 100644 > --- a/MdeModulePkg/Universal/Variable/Pei/VariablePei.inf > +++ b/MdeModulePkg/Universal/Variable/Pei/VariablePei.inf > @@ -3,7 +3,7 @@ > # > # This module implements ReadOnly Variable Services required by PEIM an= d > installs PEI ReadOnly Varaiable2 PPI. > # > -# 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 > # > ## > @@ -26,6 +26,10 @@ [Defines] > [Sources] > Variable.c > Variable.h > + VariableStore.c > + VariableStore.h > + VariableParsing.c > + VariableParsing.h >=20 > [Packages] > MdePkg/MdePkg.dec > @@ -39,6 +43,7 @@ [LibraryClasses] > DebugLib > PeiServicesTablePointerLib > PeiServicesLib > + ProtectedVariableLib >=20 > [Guids] > ## CONSUMES ## GUID # Variable store header > @@ -56,7 +61,8 @@ [Guids] > gEdkiiFaultTolerantWriteGuid >=20 > [Ppis] > - gEfiPeiReadOnlyVariable2PpiGuid ## PRODUCES > + gEfiPeiReadOnlyVariable2PpiGuid ## PRODUCES > + gEfiPeiVariableStoreDiscoveredPpiGuid ## CONSUMES >=20 > [Pcd] > gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase ## > SOMETIMES_CONSUMES > diff --git a/MdeModulePkg/Universal/Variable/Pei/Variable.h > b/MdeModulePkg/Universal/Variable/Pei/Variable.h > index 7f9ad5bfc357..115426edd626 100644 > --- a/MdeModulePkg/Universal/Variable/Pei/Variable.h > +++ b/MdeModulePkg/Universal/Variable/Pei/Variable.h > @@ -2,7 +2,7 @@ > The internal header file includes the common header files, defines > internal structure and functions used by PeiVariable module. >=20 > -Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.
> +Copyright (c) 2006 - 2022, Intel Corporation. All rights reserved.
> SPDX-License-Identifier: BSD-2-Clause-Patent >=20 > **/ > @@ -20,11 +20,13 @@ SPDX-License-Identifier: BSD-2-Clause-Patent > #include > #include > #include > +#include >=20 > #include > #include > #include > #include > +#include >=20 > typedef enum { > VariableStoreTypeHob, > @@ -142,4 +144,80 @@ PeiGetNextVariableName ( > IN OUT EFI_GUID *VariableGuid > ); >=20 > +/** > + This service retrieves a variable's value using its name and GUID. > + > + Read the specified variable from the UEFI variable store. If the Data > + buffer is too small to hold the contents of the variable, the error > + EFI_BUFFER_TOO_SMALL is returned and DataSize is set to the required b= uffer > + size to obtain the data. > + > + @param This A pointer to this instance of the > EFI_PEI_READ_ONLY_VARIABLE2_PPI. > + @param VariableName A pointer to a null-terminated string th= at is the > variable's name. > + @param VariableGuid A pointer to an EFI_GUID that is the var= iable's > GUID. The combination of > + VariableGuid and VariableName must be un= ique. > + @param Attributes If non-NULL, on return, points to the va= riable's > attributes. > + @param DataSize On entry, points to the size in bytes of= the Data > buffer. > + On return, points to the size of the dat= a returned in Data. > + @param Data Points to the buffer which will hold the= returned > variable value. > + May be NULL with a zero DataSize in orde= r to determine the > size of the buffer needed. > + > + @retval EFI_SUCCESS The variable was read successfully. > + @retval EFI_NOT_FOUND The variable was not found. > + @retval EFI_BUFFER_TOO_SMALL The DataSize is too small for the result= ing > data. > + DataSize is updated with the size requir= ed for > + the specified variable. > + @retval EFI_INVALID_PARAMETER VariableName, VariableGuid, DataSize or > Data is NULL. > + @retval EFI_DEVICE_ERROR The variable could not be retrieved beca= use of > a device error. > + > +**/ > +EFI_STATUS > +EFIAPI > +PeiGetVariableEx ( > + IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI *This, > + IN CONST CHAR16 *VariableName, > + IN CONST EFI_GUID *VariableGuid, > + OUT UINT32 *Attributes, > + IN OUT UINTN *DataSize, > + OUT VOID *Data OPTIONAL > + ); > + > +/** > + Return the next variable name and GUID. > + > + This function is called multiple times to retrieve the VariableName > + and VariableGuid of all variables currently available in the system. > + On each call, the previous results are passed into the interface, > + and, on return, the interface returns the data for the next > + interface. When the entire variable list has been returned, > + EFI_NOT_FOUND is returned. > + > + @param This A pointer to this instance of the > EFI_PEI_READ_ONLY_VARIABLE2_PPI. > + > + @param VariableNameSize On entry, points to the size of the buffer p= ointed > to by VariableName. > + @param VariableName On entry, a pointer to a null-terminated str= ing that > is the variable's name. > + On return, points to the next variable's nul= l-terminated name > string. > + > + @param VariableGuid On entry, a pointer to an UEFI _GUID that is= the > variable's GUID. > + On return, a pointer to the next variable's = GUID. > + > + @retval EFI_SUCCESS The variable was read successfully. > + @retval EFI_NOT_FOUND The variable could not be found. > + @retval EFI_BUFFER_TOO_SMALL The VariableNameSize is too small for th= e > resulting > + data. VariableNameSize is updated with t= he size > + required for the specified variable. > + @retval EFI_INVALID_PARAMETER VariableName, VariableGuid or > + VariableNameSize is NULL. > + @retval EFI_DEVICE_ERROR The variable could not be retrieved beca= use of > a device error. > + > +**/ > +EFI_STATUS > +EFIAPI > +PeiGetNextVariableNameEx ( > + IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI *This, > + IN OUT UINTN *VariableNameSize, > + IN OUT CHAR16 *VariableName, > + IN OUT EFI_GUID *VariableGuid > + ); > + > #endif > diff --git a/MdeModulePkg/Universal/Variable/Pei/VariableParsing.h > b/MdeModulePkg/Universal/Variable/Pei/VariableParsing.h > new file mode 100644 > index 000000000000..d7af6cb6e8be > --- /dev/null > +++ b/MdeModulePkg/Universal/Variable/Pei/VariableParsing.h > @@ -0,0 +1,309 @@ > +/** @file > + The internal header file includes the common header files, defines > + internal structure and functions used by PeiVariable module. > + > +Copyright (c) 2022, Intel Corporation. All rights reserved.
> +SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#ifndef PEI_VARIABLE_PARSING_H_ > +#define PEI_VARIABLE_PARSING_H_ > + > +#include "Variable.h" > + > +/** > + > + Gets the pointer to the first variable header in given variable store = area. > + > + @param[in] VarStoreHeader Pointer to the Variable Store Header. > + > + @return Pointer to the first variable header. > + > +**/ > +VARIABLE_HEADER * > +GetStartPointer ( > + IN VARIABLE_STORE_HEADER *VarStoreHeader > + ); > + > +/** > + > + Gets the pointer to the end of the variable storage area. > + > + This function gets pointer to the end of the variable storage > + area, according to the input variable store header. > + > + @param[in] VarStoreHeader Pointer to the Variable Store Header. > + > + @return Pointer to the end of the variable storage area. > + > +**/ > +VARIABLE_HEADER * > +GetEndPointer ( > + IN VARIABLE_STORE_HEADER *VarStoreHeader > + ); > + > +/** > + This code checks if variable header is valid or not. > + > + @param[in] Variable Pointer to the Variable Header. > + > + @retval TRUE Variable header is valid. > + @retval FALSE Variable header is not valid. > + > +**/ > +BOOLEAN > +IsValidVariableHeader ( > + IN VARIABLE_HEADER *Variable > + ); > + > +/** > + This code gets the pointer to the next variable header. > + > + @param[in] StoreInfo Pointer to variable store info structure= . > + @param[in] Variable Pointer to the Variable Header. > + @param[in] VariableHeader Pointer to the Variable Header that has > consecutive content. > + > + @return A VARIABLE_HEADER* pointer to next variable header. > + > +**/ > +VARIABLE_HEADER * > +GetNextVariablePtr ( > + IN VARIABLE_STORE_INFO *StoreInfo, > + IN VARIABLE_HEADER *Variable, > + IN VARIABLE_HEADER *VariableHeader > + ); > + > +/** > + This code gets the pointer to the variable guid. > + > + @param[in] Variable Pointer to the Variable Header. > + @param[in] AuthFlag Authenticated variable flag. > + > + @return A EFI_GUID* pointer to Vendor Guid. > + > +**/ > +EFI_GUID * > +GetVendorGuidPtr ( > + IN VARIABLE_HEADER *Variable, > + IN BOOLEAN AuthFlag > + ); > + > +/** > + This code gets the pointer to the variable name. > + > + @param[in] Variable Pointer to the Variable Header. > + @param[in] AuthFlag Authenticated variable flag. > + > + @return A CHAR16* pointer to Variable Name. > + > +**/ > +CHAR16 * > +GetVariableNamePtr ( > + IN VARIABLE_HEADER *Variable, > + IN BOOLEAN AuthFlag > + ); > + > +/** > + This code gets the size of name of variable. > + > + @param[in] Variable Pointer to the Variable Header. > + @param[in] AuthFlag Authenticated variable flag. > + > + @return Size of variable in bytes in type UINTN. > + > +**/ > +UINTN > +NameSizeOfVariable ( > + IN VARIABLE_HEADER *Variable, > + IN BOOLEAN AuthFlag > + ); > + > +/** > + This code gets the size of data of variable. > + > + @param[in] Variable Pointer to the Variable Header. > + @param[in] AuthFlag Authenticated variable flag. > + > + @return Size of variable in bytes in type UINTN. > + > +**/ > +UINTN > +DataSizeOfVariable ( > + IN VARIABLE_HEADER *Variable, > + IN BOOLEAN AuthFlag > + ); > + > +/** > + This code gets the pointer to the variable data. > + > + @param[in] Variable Pointer to the Variable Header. > + @param[in] VariableHeader Pointer to the Variable Header that has > consecutive content. > + @param[in] AuthFlag Authenticated variable flag. > + > + @return A UINT8* pointer to Variable Data. > + > +**/ > +UINT8 * > +GetVariableDataPtr ( > + IN VARIABLE_HEADER *Variable, > + IN VARIABLE_HEADER *VariableHeader, > + IN BOOLEAN AuthFlag > + ); > + > +/** > + Get variable header that has consecutive content. > + > + @param[in] StoreInfo Pointer to variable store info structure. > + @param[in] Variable Pointer to the Variable Header. > + @param[out] VariableHeader Pointer to Pointer to the Variable Header t= hat > has consecutive content. > + > + @retval TRUE Variable header is valid. > + @retval FALSE Variable header is not valid. > + > +**/ > +BOOLEAN > +GetVariableHeader ( > + IN VARIABLE_STORE_INFO *StoreInfo, > + IN VARIABLE_HEADER *Variable, > + OUT VARIABLE_HEADER **VariableHeader > + ); > + > +/** > + This code gets the size of variable header. > + > + @param[in] AuthFlag Authenticated variable flag. > + > + @return Size of variable header in bytes in type UINTN. > + > +**/ > +UINTN > +GetVariableHeaderSize ( > + IN BOOLEAN AuthFlag > + ); > + > +/** > + Get variable name or data to output buffer. > + > + @param[in] StoreInfo Pointer to variable store info structure. > + @param[in] NameOrData Pointer to the variable name/data that may b= e > inconsecutive. > + @param[in] Size Variable name/data size. > + @param[out] Buffer Pointer to output buffer to hold the variabl= e > name/data. > + > +**/ > +VOID > +GetVariableNameOrData ( > + IN VARIABLE_STORE_INFO *StoreInfo, > + IN UINT8 *NameOrData, > + IN UINTN Size, > + OUT UINT8 *Buffer > + ); > + > +/** > + This function compares a variable with variable entries in database. > + > + @param[in] StoreInfo Pointer to variable store info structure. > + @param[in] Variable Pointer to the variable in our database > + @param[in] VariableHeader Pointer to the Variable Header that has > consecutive content. > + @param[in] VariableName Name of the variable to compare to 'Variable= ' > + @param[in] VendorGuid GUID of the variable to compare to 'Variable= ' > + @param[out] PtrTrack Variable Track Pointer structure that contai= ns > Variable Information. > + > + @retval EFI_SUCCESS Found match variable > + @retval EFI_NOT_FOUND Variable not found > + > +**/ > +EFI_STATUS > +CompareWithValidVariable ( > + IN VARIABLE_STORE_INFO *StoreInfo, > + IN VARIABLE_HEADER *Variable, > + IN VARIABLE_HEADER *VariableHeader, > + IN CONST CHAR16 *VariableName, > + IN CONST EFI_GUID *VendorGuid, > + OUT VARIABLE_POINTER_TRACK *PtrTrack > + ); > + > +/** > + > + 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 > + ); > + > +/** > + > + 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 > + ); > + > +/** > + > + Find variable specified with input parameters. > + > + @param[in] StoreInfo Pointer to variable information. > + @param[in] VariableName Pointer to variable name. > + @param[in] VendorGuid Pointer to variable GUID. > + @param[in] PtrTrack Pointer to variable track. > + > + @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 > +FindVariableEx ( > + IN VARIABLE_STORE_INFO *StoreInfo, > + IN CONST CHAR16 *VariableName, > + IN CONST EFI_GUID *VendorGuid, > + OUT VARIABLE_POINTER_TRACK *PtrTrack > + ); > + > +#endif > diff --git a/MdeModulePkg/Universal/Variable/Pei/VariableStore.h > b/MdeModulePkg/Universal/Variable/Pei/VariableStore.h > new file mode 100644 > index 000000000000..6e2f6f939bab > --- /dev/null > +++ b/MdeModulePkg/Universal/Variable/Pei/VariableStore.h > @@ -0,0 +1,116 @@ > +/** @file > + Implement ReadOnly Variable Services required by PEIM and install > + PEI ReadOnly Varaiable2 PPI. These services operates the non volatile = storage > space. > + > +Copyright (c) 2022, Intel Corporation. All rights reserved.
> +SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#ifndef PEI_VARIABLE_STORE_H_ > +#define PEI_VARIABLE_STORE_H_ > + > +/** > + Get variable store status. > + > + @param[in] VarStoreHeader Pointer to the Variable Store Header. > + > + @retval EfiRaw Variable store is raw > + @retval EfiValid Variable store is valid > + @retval EfiInvalid Variable store is invalid > + > +**/ > +VARIABLE_STORE_STATUS > +GetVariableStoreStatus ( > + IN VARIABLE_STORE_HEADER *VarStoreHeader > + ); > + > +/** > + Reports HOB variable store is available or not. > + > + @retval EFI_NOT_READY HOB variable store info not available. > + @retval EFI_NOT_FOUND HOB variable store is NOT available. > + @retval EFI_SUCCESS HOB variable store is available. > +**/ > +EFI_STATUS > +EFIAPI > +IsHobVariableStoreAvailable ( > + VOID > + ); > + > +/** > + Get HOB variable store. > + > + @param[out] StoreInfo Return the store info. > + > +**/ > +VOID > +GetHobVariableStore ( > + OUT VARIABLE_STORE_INFO *StoreInfo > + ); > + > +/** > + Get NV variable store. > + > + @param[out] StoreInfo Return the store info. > + @param[out] VariableStoreHeader Return header of FV containing the s= tore. > + > +**/ > +VOID > +GetNvVariableStore ( > + OUT VARIABLE_STORE_INFO *StoreInfo, > + OUT EFI_FIRMWARE_VOLUME_HEADER **VariableFvHeader > + ); > + > +/** > + Return the variable store header and the store info based on the Index= . > + > + @param[in] Type The type of the variable store. > + @param[out] StoreInfo Return the store info. > + > + @return Pointer to the variable store header. > +**/ > +VARIABLE_STORE_HEADER * > +GetVariableStore ( > + IN VARIABLE_STORE_TYPE Type, > + OUT VARIABLE_STORE_INFO *StoreInfo > + ); > + > +/** > + Make a cached copy of NV variable storage. > + > + To save memory in PEI phase, only valid variables are copied into cach= e. > + An IndexTable could be used to store the offset (relative to NV storag= e > + base) of each copied variable, in case we need to restore the storage > + as the same (valid) variables layout as in original one. > + > + Variables with valid format and following state can be taken as valid: > + - with state VAR_ADDED; > + - with state VAR_IN_DELETED_TRANSITION but without the same variable > + with state VAR_ADDED; > + - with state VAR_ADDED and/or VAR_IN_DELETED_TRANSITION for variable > + MetaDataHmacVar. > + > + @param[out] StoreCacheBase Base address of variable storage cac= he. > + @param[in,out] StoreCacheSize Size of space in StoreCacheBase. > + @param[out] IndexTable Buffer of index (offset) table with = entries of > + VariableNumber. > + @param[out] VariableNumber Number of valid variables. > + @param[out] AuthFlag Aut-variable indicator. > + > + @return EFI_INVALID_PARAMETER Invalid StoreCacheSize and/or > StoreCacheBase. > + @return EFI_VOLUME_CORRUPTED Invalid or no NV variable storage found. > + @return EFI_BUFFER_TOO_SMALL StoreCacheSize is smaller than needed. > + @return EFI_SUCCESS NV variable storage is cached successful= ly. > +**/ > +EFI_STATUS > +EFIAPI > +InitNvVariableStore ( > + OUT EFI_PHYSICAL_ADDRESS StoreCacheBase OPTIONAL, > + IN OUT UINT32 *StoreCacheSize, > + OUT UINT32 *IndexTable OPTIONAL, > + OUT UINT32 *VariableNumber OPTIONAL, > + OUT BOOLEAN *AuthFlag OPTIONAL > + ); > + > +#endif > diff --git a/MdeModulePkg/Universal/Variable/Pei/Variable.c > b/MdeModulePkg/Universal/Variable/Pei/Variable.c > index b36dd0de67b2..ce790946626e 100644 > --- a/MdeModulePkg/Universal/Variable/Pei/Variable.c > +++ b/MdeModulePkg/Universal/Variable/Pei/Variable.c > @@ -2,20 +2,22 @@ > Implement ReadOnly Variable Services required by PEIM and install > PEI ReadOnly Varaiable2 PPI. These services operates the non volatile = storage > space. >=20 > -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 >=20 > **/ >=20 > #include "Variable.h" > +#include "VariableParsing.h" > +#include "VariableStore.h" >=20 > // > // Module globals > // > EFI_PEI_READ_ONLY_VARIABLE2_PPI mVariablePpi =3D { > - PeiGetVariable, > - PeiGetNextVariableName > + PeiGetVariableEx, > + PeiGetNextVariableNameEx > }; >=20 > EFI_PEI_PPI_DESCRIPTOR mPpiListVariable =3D { > @@ -41,759 +43,33 @@ PeimInitializeVariableServices ( > IN CONST EFI_PEI_SERVICES **PeiServices > ) > { > + EFI_STATUS Status; > + PROTECTED_VARIABLE_CONTEXT_IN ContextIn; > + > + // > + // If protected variable services are not supported, EFI_UNSUPPORTED s= hould > + // be always returned. Check it here. > + // > + ContextIn.StructVersion =3D > PROTECTED_VARIABLE_CONTEXT_IN_STRUCT_VERSION; > + ContextIn.StructSize =3D sizeof (ContextIn); > + > + ContextIn.MaxVariableSize =3D 0; > + ContextIn.VariableServiceUser =3D FromPeiModule; > + ContextIn.GetVariableInfo =3D GetVariableInfo; > + ContextIn.GetNextVariableInfo =3D GetNextVariableInfo; > + ContextIn.FindVariableSmm =3D NULL; > + ContextIn.UpdateVariableStore =3D NULL; > + ContextIn.UpdateVariable =3D NULL; > + ContextIn.IsHobVariableStoreAvailable =3D IsHobVariableStoreAvailable; > + > + Status =3D ProtectedVariableLibInitialize (&ContextIn); > + if (EFI_ERROR (Status) && (Status !=3D EFI_UNSUPPORTED)) { > + return Status; > + } > + > return PeiServicesInstallPpi (&mPpiListVariable); > } >=20 > -/** > - > - Gets the pointer to the first variable header in given variable store = area. > - > - @param VarStoreHeader Pointer to the Variable Store Header. > - > - @return Pointer to the first variable header. > - > -**/ > -VARIABLE_HEADER * > -GetStartPointer ( > - IN VARIABLE_STORE_HEADER *VarStoreHeader > - ) > -{ > - // > - // The start of variable store > - // > - return (VARIABLE_HEADER *)HEADER_ALIGN (VarStoreHeader + 1); > -} > - > -/** > - > - Gets the pointer to the end of the variable storage area. > - > - This function gets pointer to the end of the variable storage > - area, according to the input variable store header. > - > - @param VarStoreHeader Pointer to the Variable Store Header. > - > - @return Pointer to the end of the variable storage area. > - > -**/ > -VARIABLE_HEADER * > -GetEndPointer ( > - IN VARIABLE_STORE_HEADER *VarStoreHeader > - ) > -{ > - // > - // The end of variable store > - // > - return (VARIABLE_HEADER *)HEADER_ALIGN ((UINTN)VarStoreHeader + > VarStoreHeader->Size); > -} > - > -/** > - This code checks if variable header is valid or not. > - > - @param Variable Pointer to the Variable Header. > - > - @retval TRUE Variable header is valid. > - @retval FALSE Variable header is not valid. > - > -**/ > -BOOLEAN > -IsValidVariableHeader ( > - IN VARIABLE_HEADER *Variable > - ) > -{ > - if ((Variable =3D=3D NULL) || (Variable->StartId !=3D VARIABLE_DATA)) = { > - return FALSE; > - } > - > - return TRUE; > -} > - > -/** > - This code gets the size of variable header. > - > - @param AuthFlag Authenticated variable flag. > - > - @return Size of variable header in bytes in type UINTN. > - > -**/ > -UINTN > -GetVariableHeaderSize ( > - IN BOOLEAN AuthFlag > - ) > -{ > - UINTN Value; > - > - if (AuthFlag) { > - Value =3D sizeof (AUTHENTICATED_VARIABLE_HEADER); > - } else { > - Value =3D sizeof (VARIABLE_HEADER); > - } > - > - return Value; > -} > - > -/** > - This code gets the size of name of variable. > - > - @param Variable Pointer to the Variable Header. > - @param AuthFlag Authenticated variable flag. > - > - @return Size of variable in bytes in type UINTN. > - > -**/ > -UINTN > -NameSizeOfVariable ( > - IN VARIABLE_HEADER *Variable, > - IN BOOLEAN AuthFlag > - ) > -{ > - AUTHENTICATED_VARIABLE_HEADER *AuthVariable; > - > - AuthVariable =3D (AUTHENTICATED_VARIABLE_HEADER *)Variable; > - if (AuthFlag) { > - if ((AuthVariable->State =3D=3D (UINT8)(-1)) || > - (AuthVariable->DataSize =3D=3D (UINT32)(-1)) || > - (AuthVariable->NameSize =3D=3D (UINT32)(-1)) || > - (AuthVariable->Attributes =3D=3D (UINT32)(-1))) > - { > - return 0; > - } > - > - return (UINTN)AuthVariable->NameSize; > - } else { > - if ((Variable->State =3D=3D (UINT8)(-1)) || > - (Variable->DataSize =3D=3D (UINT32)(-1)) || > - (Variable->NameSize =3D=3D (UINT32)(-1)) || > - (Variable->Attributes =3D=3D (UINT32)(-1))) > - { > - return 0; > - } > - > - return (UINTN)Variable->NameSize; > - } > -} > - > -/** > - This code gets the size of data of variable. > - > - @param Variable Pointer to the Variable Header. > - @param AuthFlag Authenticated variable flag. > - > - @return Size of variable in bytes in type UINTN. > - > -**/ > -UINTN > -DataSizeOfVariable ( > - IN VARIABLE_HEADER *Variable, > - IN BOOLEAN AuthFlag > - ) > -{ > - AUTHENTICATED_VARIABLE_HEADER *AuthVariable; > - > - AuthVariable =3D (AUTHENTICATED_VARIABLE_HEADER *)Variable; > - if (AuthFlag) { > - if ((AuthVariable->State =3D=3D (UINT8)(-1)) || > - (AuthVariable->DataSize =3D=3D (UINT32)(-1)) || > - (AuthVariable->NameSize =3D=3D (UINT32)(-1)) || > - (AuthVariable->Attributes =3D=3D (UINT32)(-1))) > - { > - return 0; > - } > - > - return (UINTN)AuthVariable->DataSize; > - } else { > - if ((Variable->State =3D=3D (UINT8)(-1)) || > - (Variable->DataSize =3D=3D (UINT32)(-1)) || > - (Variable->NameSize =3D=3D (UINT32)(-1)) || > - (Variable->Attributes =3D=3D (UINT32)(-1))) > - { > - return 0; > - } > - > - return (UINTN)Variable->DataSize; > - } > -} > - > -/** > - This code gets the pointer to the variable name. > - > - @param Variable Pointer to the Variable Header. > - @param AuthFlag Authenticated variable flag. > - > - @return A CHAR16* pointer to Variable Name. > - > -**/ > -CHAR16 * > -GetVariableNamePtr ( > - IN VARIABLE_HEADER *Variable, > - IN BOOLEAN AuthFlag > - ) > -{ > - return (CHAR16 *)((UINTN)Variable + GetVariableHeaderSize (AuthFlag)); > -} > - > -/** > - This code gets the pointer to the variable guid. > - > - @param Variable Pointer to the Variable Header. > - @param AuthFlag Authenticated variable flag. > - > - @return A EFI_GUID* pointer to Vendor Guid. > - > -**/ > -EFI_GUID * > -GetVendorGuidPtr ( > - IN VARIABLE_HEADER *Variable, > - IN BOOLEAN AuthFlag > - ) > -{ > - AUTHENTICATED_VARIABLE_HEADER *AuthVariable; > - > - AuthVariable =3D (AUTHENTICATED_VARIABLE_HEADER *)Variable; > - if (AuthFlag) { > - return &AuthVariable->VendorGuid; > - } else { > - return &Variable->VendorGuid; > - } > -} > - > -/** > - This code gets the pointer to the variable data. > - > - @param Variable Pointer to the Variable Header. > - @param VariableHeader Pointer to the Variable Header that has > consecutive content. > - @param AuthFlag Authenticated variable flag. > - > - @return A UINT8* pointer to Variable Data. > - > -**/ > -UINT8 * > -GetVariableDataPtr ( > - IN VARIABLE_HEADER *Variable, > - IN VARIABLE_HEADER *VariableHeader, > - IN BOOLEAN AuthFlag > - ) > -{ > - UINTN Value; > - > - // > - // Be careful about pad size for alignment > - // > - Value =3D (UINTN)GetVariableNamePtr (Variable, AuthFlag); > - Value +=3D NameSizeOfVariable (VariableHeader, AuthFlag); > - Value +=3D GET_PAD_SIZE (NameSizeOfVariable (VariableHeader, AuthFlag)= ); > - > - return (UINT8 *)Value; > -} > - > -/** > - This code gets the pointer to the next variable header. > - > - @param StoreInfo Pointer to variable store info structure. > - @param Variable Pointer to the Variable Header. > - @param VariableHeader Pointer to the Variable Header that has > consecutive content. > - > - @return A VARIABLE_HEADER* pointer to next variable header. > - > -**/ > -VARIABLE_HEADER * > -GetNextVariablePtr ( > - IN VARIABLE_STORE_INFO *StoreInfo, > - IN VARIABLE_HEADER *Variable, > - IN VARIABLE_HEADER *VariableHeader > - ) > -{ > - EFI_PHYSICAL_ADDRESS TargetAddress; > - EFI_PHYSICAL_ADDRESS SpareAddress; > - UINTN Value; > - > - Value =3D (UINTN)GetVariableDataPtr (Variable, VariableHeader, Store= Info- > >AuthFlag); > - Value +=3D DataSizeOfVariable (VariableHeader, StoreInfo->AuthFlag); > - Value +=3D GET_PAD_SIZE (DataSizeOfVariable (VariableHeader, StoreInfo= - > >AuthFlag)); > - // > - // Be careful about pad size for alignment > - // > - Value =3D HEADER_ALIGN (Value); > - > - if (StoreInfo->FtwLastWriteData !=3D NULL) { > - TargetAddress =3D StoreInfo->FtwLastWriteData->TargetAddress; > - SpareAddress =3D StoreInfo->FtwLastWriteData->SpareAddress; > - if (((UINTN)Variable < (UINTN)TargetAddress) && (Value >=3D > (UINTN)TargetAddress)) { > - // > - // Next variable is in spare block. > - // > - Value =3D (UINTN)SpareAddress + (Value - (UINTN)TargetAddress); > - } > - } > - > - return (VARIABLE_HEADER *)Value; > -} > - > -/** > - Get variable store status. > - > - @param VarStoreHeader Pointer to the Variable Store Header. > - > - @retval EfiRaw Variable store is raw > - @retval EfiValid Variable store is valid > - @retval EfiInvalid Variable store is invalid > - > -**/ > -VARIABLE_STORE_STATUS > -GetVariableStoreStatus ( > - IN VARIABLE_STORE_HEADER *VarStoreHeader > - ) > -{ > - if ((CompareGuid (&VarStoreHeader->Signature, > &gEfiAuthenticatedVariableGuid) || > - CompareGuid (&VarStoreHeader->Signature, &gEfiVariableGuid)) && > - (VarStoreHeader->Format =3D=3D VARIABLE_STORE_FORMATTED) && > - (VarStoreHeader->State =3D=3D VARIABLE_STORE_HEALTHY) > - ) > - { > - return EfiValid; > - } > - > - if ((((UINT32 *)(&VarStoreHeader->Signature))[0] =3D=3D 0xffffffff) && > - (((UINT32 *)(&VarStoreHeader->Signature))[1] =3D=3D 0xffffffff) && > - (((UINT32 *)(&VarStoreHeader->Signature))[2] =3D=3D 0xffffffff) && > - (((UINT32 *)(&VarStoreHeader->Signature))[3] =3D=3D 0xffffffff) && > - (VarStoreHeader->Size =3D=3D 0xffffffff) && > - (VarStoreHeader->Format =3D=3D 0xff) && > - (VarStoreHeader->State =3D=3D 0xff) > - ) > - { > - return EfiRaw; > - } else { > - return EfiInvalid; > - } > -} > - > -/** > - Compare two variable names, one of them may be inconsecutive. > - > - @param StoreInfo Pointer to variable store info structure. > - @param Name1 Pointer to one variable name. > - @param Name2 Pointer to another variable name. > - @param NameSize Variable name size. > - > - @retval TRUE Name1 and Name2 are identical. > - @retval FALSE Name1 and Name2 are not identical. > - > -**/ > -BOOLEAN > -CompareVariableName ( > - IN VARIABLE_STORE_INFO *StoreInfo, > - IN CONST CHAR16 *Name1, > - IN CONST CHAR16 *Name2, > - IN UINTN NameSize > - ) > -{ > - EFI_PHYSICAL_ADDRESS TargetAddress; > - EFI_PHYSICAL_ADDRESS SpareAddress; > - UINTN PartialNameSize; > - > - if (StoreInfo->FtwLastWriteData !=3D NULL) { > - TargetAddress =3D StoreInfo->FtwLastWriteData->TargetAddress; > - SpareAddress =3D StoreInfo->FtwLastWriteData->SpareAddress; > - if (((UINTN)Name1 < (UINTN)TargetAddress) && (((UINTN)Name1 + > NameSize) > (UINTN)TargetAddress)) { > - // > - // Name1 is inconsecutive. > - // > - PartialNameSize =3D (UINTN)TargetAddress - (UINTN)Name1; > - // > - // Partial content is in NV storage. > - // > - if (CompareMem ((UINT8 *)Name1, (UINT8 *)Name2, PartialNameSize) = =3D=3D 0) > { > - // > - // Another partial content is in spare block. > - // > - if (CompareMem ((UINT8 *)(UINTN)SpareAddress, (UINT8 *)Name2 + > PartialNameSize, NameSize - PartialNameSize) =3D=3D 0) { > - return TRUE; > - } > - } > - > - return FALSE; > - } else if (((UINTN)Name2 < (UINTN)TargetAddress) && (((UINTN)Name2 + > NameSize) > (UINTN)TargetAddress)) { > - // > - // Name2 is inconsecutive. > - // > - PartialNameSize =3D (UINTN)TargetAddress - (UINTN)Name2; > - // > - // Partial content is in NV storage. > - // > - if (CompareMem ((UINT8 *)Name2, (UINT8 *)Name1, PartialNameSize) = =3D=3D 0) > { > - // > - // Another partial content is in spare block. > - // > - if (CompareMem ((UINT8 *)(UINTN)SpareAddress, (UINT8 *)Name1 + > PartialNameSize, NameSize - PartialNameSize) =3D=3D 0) { > - return TRUE; > - } > - } > - > - return FALSE; > - } > - } > - > - // > - // Both Name1 and Name2 are consecutive. > - // > - if (CompareMem ((UINT8 *)Name1, (UINT8 *)Name2, NameSize) =3D=3D 0) { > - return TRUE; > - } > - > - return FALSE; > -} > - > -/** > - This function compares a variable with variable entries in database. > - > - @param StoreInfo Pointer to variable store info structure. > - @param Variable Pointer to the variable in our database > - @param VariableHeader Pointer to the Variable Header that has consecu= tive > content. > - @param VariableName Name of the variable to compare to 'Variable' > - @param VendorGuid GUID of the variable to compare to 'Variable' > - @param PtrTrack Variable Track Pointer structure that contains V= ariable > Information. > - > - @retval EFI_SUCCESS Found match variable > - @retval EFI_NOT_FOUND Variable not found > - > -**/ > -EFI_STATUS > -CompareWithValidVariable ( > - IN VARIABLE_STORE_INFO *StoreInfo, > - IN VARIABLE_HEADER *Variable, > - IN VARIABLE_HEADER *VariableHeader, > - IN CONST CHAR16 *VariableName, > - IN CONST EFI_GUID *VendorGuid, > - OUT VARIABLE_POINTER_TRACK *PtrTrack > - ) > -{ > - VOID *Point; > - EFI_GUID *TempVendorGuid; > - > - TempVendorGuid =3D GetVendorGuidPtr (VariableHeader, StoreInfo->AuthFl= ag); > - > - if (VariableName[0] =3D=3D 0) { > - PtrTrack->CurrPtr =3D Variable; > - return EFI_SUCCESS; > - } else { > - // > - // Don't use CompareGuid function here for performance reasons. > - // Instead we compare the GUID a UINT32 at a time and branch > - // on the first failed comparison. > - // > - if ((((INT32 *)VendorGuid)[0] =3D=3D ((INT32 *)TempVendorGuid)[0]) &= & > - (((INT32 *)VendorGuid)[1] =3D=3D ((INT32 *)TempVendorGuid)[1]) &= & > - (((INT32 *)VendorGuid)[2] =3D=3D ((INT32 *)TempVendorGuid)[2]) &= & > - (((INT32 *)VendorGuid)[3] =3D=3D ((INT32 *)TempVendorGuid)[3]) > - ) > - { > - ASSERT (NameSizeOfVariable (VariableHeader, StoreInfo->AuthFlag) != =3D 0); > - Point =3D (VOID *)GetVariableNamePtr (Variable, StoreInfo->AuthFla= g); > - if (CompareVariableName (StoreInfo, VariableName, Point, > NameSizeOfVariable (VariableHeader, StoreInfo->AuthFlag))) { > - PtrTrack->CurrPtr =3D Variable; > - return EFI_SUCCESS; > - } > - } > - } > - > - return EFI_NOT_FOUND; > -} > - > -/** > - Get HOB variable store. > - > - @param[out] StoreInfo Return the store info. > - @param[out] VariableStoreHeader Return variable store header. > - > -**/ > -VOID > -GetHobVariableStore ( > - OUT VARIABLE_STORE_INFO *StoreInfo, > - OUT VARIABLE_STORE_HEADER **VariableStoreHeader > - ) > -{ > - EFI_HOB_GUID_TYPE *GuidHob; > - > - // > - // Make sure there is no more than one Variable HOB. > - // > - DEBUG_CODE_BEGIN (); > - GuidHob =3D GetFirstGuidHob (&gEfiAuthenticatedVariableGuid); > - if (GuidHob !=3D NULL) { > - if ((GetNextGuidHob (&gEfiAuthenticatedVariableGuid, GET_NEXT_HOB > (GuidHob)) !=3D NULL)) { > - DEBUG ((DEBUG_ERROR, "ERROR: Found two Auth Variable HOBs\n")); > - ASSERT (FALSE); > - } else if (GetFirstGuidHob (&gEfiVariableGuid) !=3D NULL) { > - DEBUG ((DEBUG_ERROR, "ERROR: Found one Auth + one Normal Variable > HOBs\n")); > - ASSERT (FALSE); > - } > - } else { > - GuidHob =3D GetFirstGuidHob (&gEfiVariableGuid); > - if (GuidHob !=3D NULL) { > - if ((GetNextGuidHob (&gEfiVariableGuid, GET_NEXT_HOB (GuidHob)) != =3D > NULL)) { > - DEBUG ((DEBUG_ERROR, "ERROR: Found two Normal Variable HOBs\n"))= ; > - ASSERT (FALSE); > - } > - } > - } > - > - DEBUG_CODE_END (); > - > - GuidHob =3D GetFirstGuidHob (&gEfiAuthenticatedVariableGuid); > - if (GuidHob !=3D NULL) { > - *VariableStoreHeader =3D (VARIABLE_STORE_HEADER > *)GET_GUID_HOB_DATA (GuidHob); > - StoreInfo->AuthFlag =3D TRUE; > - } else { > - GuidHob =3D GetFirstGuidHob (&gEfiVariableGuid); > - if (GuidHob !=3D NULL) { > - *VariableStoreHeader =3D (VARIABLE_STORE_HEADER > *)GET_GUID_HOB_DATA (GuidHob); > - StoreInfo->AuthFlag =3D FALSE; > - } > - } > -} > - > -/** > - Return the variable store header and the store info based on the Index= . > - > - @param Type The type of the variable store. > - @param StoreInfo Return the store info. > - > - @return Pointer to the variable store header. > -**/ > -VARIABLE_STORE_HEADER * > -GetVariableStore ( > - IN VARIABLE_STORE_TYPE Type, > - OUT VARIABLE_STORE_INFO *StoreInfo > - ) > -{ > - EFI_HOB_GUID_TYPE *GuidHob; > - EFI_FIRMWARE_VOLUME_HEADER *FvHeader; > - VARIABLE_STORE_HEADER *VariableStoreHeader; > - EFI_PHYSICAL_ADDRESS NvStorageBase; > - UINT32 NvStorageSize; > - FAULT_TOLERANT_WRITE_LAST_WRITE_DATA *FtwLastWriteData; > - UINT32 BackUpOffset; > - > - StoreInfo->IndexTable =3D NULL; > - StoreInfo->FtwLastWriteData =3D NULL; > - StoreInfo->AuthFlag =3D FALSE; > - VariableStoreHeader =3D NULL; > - switch (Type) { > - case VariableStoreTypeHob: > - GetHobVariableStore (StoreInfo, &VariableStoreHeader); > - > - break; > - > - case VariableStoreTypeNv: > - if (!PcdGetBool (PcdEmuVariableNvModeEnable)) { > - // > - // Emulated non-volatile variable mode is not enabled. > - // > - > - NvStorageSize =3D PcdGet32 (PcdFlashNvStorageVariableSize); > - NvStorageBase =3D (EFI_PHYSICAL_ADDRESS)(PcdGet64 > (PcdFlashNvStorageVariableBase64) !=3D 0 ? > - PcdGet64 (PcdFlashNvStora= geVariableBase64) : > - PcdGet32 (PcdFlashNvStora= geVariableBase) > - ); > - ASSERT (NvStorageBase !=3D 0); > - > - // > - // First let FvHeader point to NV storage base. > - // > - FvHeader =3D (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)NvStorageBase; > - > - // > - // Check the FTW last write data hob. > - // > - BackUpOffset =3D 0; > - GuidHob =3D GetFirstGuidHob (&gEdkiiFaultTolerantWriteGuid)= ; > - if (GuidHob !=3D NULL) { > - FtwLastWriteData =3D (FAULT_TOLERANT_WRITE_LAST_WRITE_DATA > *)GET_GUID_HOB_DATA (GuidHob); > - if (FtwLastWriteData->TargetAddress =3D=3D NvStorageBase) { > - // > - // Let FvHeader point to spare block. > - // > - FvHeader =3D (EFI_FIRMWARE_VOLUME_HEADER > *)(UINTN)FtwLastWriteData->SpareAddress; > - DEBUG ((DEBUG_INFO, "PeiVariable: NV storage is backed up in= spare > block: 0x%x\n", (UINTN)FtwLastWriteData->SpareAddress)); > - } else if ((FtwLastWriteData->TargetAddress > NvStorageBase) &= & > (FtwLastWriteData->TargetAddress < (NvStorageBase + NvStorageSize))) { > - StoreInfo->FtwLastWriteData =3D FtwLastWriteData; > - // > - // Flash NV storage from the offset is backed up in spare bl= ock. > - // > - BackUpOffset =3D (UINT32)(FtwLastWriteData->TargetAddress - > NvStorageBase); > - DEBUG ((DEBUG_INFO, "PeiVariable: High partial NV storage fr= om > offset: %x is backed up in spare block: 0x%x\n", BackUpOffset, > (UINTN)FtwLastWriteData->SpareAddress)); > - // > - // At least one block data in flash NV storage is still vali= d, so still leave > FvHeader point to NV storage base. > - // > - } > - } > - > - // > - // Check if the Firmware Volume is not corrupted > - // > - if ((FvHeader->Signature !=3D EFI_FVH_SIGNATURE) || (!CompareGui= d > (&gEfiSystemNvDataFvGuid, &FvHeader->FileSystemGuid))) { > - DEBUG ((DEBUG_ERROR, "Firmware Volume for Variable Store is > corrupted\n")); > - break; > - } > - > - VariableStoreHeader =3D (VARIABLE_STORE_HEADER *)((UINT8 *)FvHea= der + > FvHeader->HeaderLength); > - > - StoreInfo->AuthFlag =3D (BOOLEAN)(CompareGuid (&VariableStoreHea= der- > >Signature, &gEfiAuthenticatedVariableGuid)); > - > - GuidHob =3D GetFirstGuidHob (&gEfiVariableIndexTableGuid); > - if (GuidHob !=3D NULL) { > - StoreInfo->IndexTable =3D GET_GUID_HOB_DATA (GuidHob); > - } else { > - // > - // If it's the first time to access variable region in flash, = create a guid hob > to record > - // VAR_ADDED type variable info. > - // Note that as the resource of PEI phase is limited, only sto= re the limited > number of > - // VAR_ADDED type variables to reduce access time. > - // > - StoreInfo->IndexTable =3D (VARIABLE_INDEX_TABLE *= )BuildGuidHob > (&gEfiVariableIndexTableGuid, sizeof (VARIABLE_INDEX_TABLE)); > - StoreInfo->IndexTable->Length =3D 0; > - StoreInfo->IndexTable->StartPtr =3D GetStartPointer > (VariableStoreHeader); > - StoreInfo->IndexTable->EndPtr =3D GetEndPointer (Variable= StoreHeader); > - StoreInfo->IndexTable->GoneThrough =3D 0; > - } > - } > - > - break; > - > - default: > - ASSERT (FALSE); > - break; > - } > - > - StoreInfo->VariableStoreHeader =3D VariableStoreHeader; > - return VariableStoreHeader; > -} > - > -/** > - Get variable header that has consecutive content. > - > - @param StoreInfo Pointer to variable store info structure. > - @param Variable Pointer to the Variable Header. > - @param VariableHeader Pointer to Pointer to the Variable Header that h= as > consecutive content. > - > - @retval TRUE Variable header is valid. > - @retval FALSE Variable header is not valid. > - > -**/ > -BOOLEAN > -GetVariableHeader ( > - IN VARIABLE_STORE_INFO *StoreInfo, > - IN VARIABLE_HEADER *Variable, > - OUT VARIABLE_HEADER **VariableHeader > - ) > -{ > - EFI_PHYSICAL_ADDRESS TargetAddress; > - EFI_PHYSICAL_ADDRESS SpareAddress; > - EFI_HOB_GUID_TYPE *GuidHob; > - UINTN PartialHeaderSize; > - > - if (Variable =3D=3D NULL) { > - return FALSE; > - } > - > - // > - // First assume variable header pointed by Variable is consecutive. > - // > - *VariableHeader =3D Variable; > - > - if (StoreInfo->FtwLastWriteData !=3D NULL) { > - TargetAddress =3D StoreInfo->FtwLastWriteData->TargetAddress; > - SpareAddress =3D StoreInfo->FtwLastWriteData->SpareAddress; > - if (((UINTN)Variable > (UINTN)SpareAddress) && > - (((UINTN)Variable - (UINTN)SpareAddress + (UINTN)TargetAddress) = >=3D > (UINTN)GetEndPointer (StoreInfo->VariableStoreHeader))) > - { > - // > - // Reach the end of variable store. > - // > - return FALSE; > - } > - > - if (((UINTN)Variable < (UINTN)TargetAddress) && (((UINTN)Variable + > GetVariableHeaderSize (StoreInfo->AuthFlag)) > (UINTN)TargetAddress)) { > - // > - // Variable header pointed by Variable is inconsecutive, > - // create a guid hob to combine the two partial variable header co= ntent > together. > - // > - GuidHob =3D GetFirstGuidHob (&gEfiCallerIdGuid); > - if (GuidHob !=3D NULL) { > - *VariableHeader =3D (VARIABLE_HEADER *)GET_GUID_HOB_DATA (GuidHo= b); > - } else { > - *VariableHeader =3D (VARIABLE_HEADER *)BuildGuidHob (&gEfiCall= erIdGuid, > GetVariableHeaderSize (StoreInfo->AuthFlag)); > - PartialHeaderSize =3D (UINTN)TargetAddress - (UINTN)Variable; > - // > - // Partial content is in NV storage. > - // > - CopyMem ((UINT8 *)*VariableHeader, (UINT8 *)Variable, > PartialHeaderSize); > - // > - // Another partial content is in spare block. > - // > - CopyMem ((UINT8 *)*VariableHeader + PartialHeaderSize, (UINT8 > *)(UINTN)SpareAddress, GetVariableHeaderSize (StoreInfo->AuthFlag) - > PartialHeaderSize); > - } > - } > - } else { > - if (Variable >=3D GetEndPointer (StoreInfo->VariableStoreHeader)) { > - // > - // Reach the end of variable store. > - // > - return FALSE; > - } > - } > - > - return IsValidVariableHeader (*VariableHeader); > -} > - > -/** > - Get variable name or data to output buffer. > - > - @param StoreInfo Pointer to variable store info structure. > - @param NameOrData Pointer to the variable name/data that may be > inconsecutive. > - @param Size Variable name/data size. > - @param Buffer Pointer to output buffer to hold the variable na= me/data. > - > -**/ > -VOID > -GetVariableNameOrData ( > - IN VARIABLE_STORE_INFO *StoreInfo, > - IN UINT8 *NameOrData, > - IN UINTN Size, > - OUT UINT8 *Buffer > - ) > -{ > - EFI_PHYSICAL_ADDRESS TargetAddress; > - EFI_PHYSICAL_ADDRESS SpareAddress; > - UINTN PartialSize; > - > - if (StoreInfo->FtwLastWriteData !=3D NULL) { > - TargetAddress =3D StoreInfo->FtwLastWriteData->TargetAddress; > - SpareAddress =3D StoreInfo->FtwLastWriteData->SpareAddress; > - if (((UINTN)NameOrData < (UINTN)TargetAddress) && > (((UINTN)NameOrData + Size) > (UINTN)TargetAddress)) { > - // > - // Variable name/data is inconsecutive. > - // > - PartialSize =3D (UINTN)TargetAddress - (UINTN)NameOrData; > - // > - // Partial content is in NV storage. > - // > - CopyMem (Buffer, NameOrData, PartialSize); > - // > - // Another partial content is in spare block. > - // > - CopyMem (Buffer + PartialSize, (UINT8 *)(UINTN)SpareAddress, Size = - > PartialSize); > - return; > - } > - } > - > - // > - // Variable name/data is consecutive. > - // > - CopyMem (Buffer, NameOrData, Size); > -} > - > /** > Find the variable in the specified variable store. >=20 > @@ -1246,3 +522,107 @@ PeiGetNextVariableName ( > } > } > } > + > +/** > + This service retrieves a variable's value using its name and GUID. > + > + Read the specified variable from the UEFI variable store. If the Data > + buffer is too small to hold the contents of the variable, the error > + EFI_BUFFER_TOO_SMALL is returned and DataSize is set to the required b= uffer > + size to obtain the data. > + > + @param This A pointer to this instance of the > EFI_PEI_READ_ONLY_VARIABLE2_PPI. > + @param VariableName A pointer to a null-terminated string th= at is the > variable's name. > + @param VariableGuid A pointer to an EFI_GUID that is the var= iable's > GUID. The combination of > + VariableGuid and VariableName must be un= ique. > + @param Attributes If non-NULL, on return, points to the va= riable's > attributes. > + @param DataSize On entry, points to the size in bytes of= the Data > buffer. > + On return, points to the size of the dat= a returned in Data. > + @param Data Points to the buffer which will hold the= returned > variable value. > + May be NULL with a zero DataSize in orde= r to determine the > size of the buffer needed. > + > + @retval EFI_SUCCESS The variable was read successfully. > + @retval EFI_NOT_FOUND The variable was be found. > + @retval EFI_BUFFER_TOO_SMALL The DataSize is too small for the result= ing > data. > + DataSize is updated with the size requir= ed for > + the specified variable. > + @retval EFI_INVALID_PARAMETER VariableName, VariableGuid, DataSize or > Data is NULL. > + @retval EFI_DEVICE_ERROR The variable could not be retrieved beca= use of > a device error. > + > +**/ > +EFI_STATUS > +EFIAPI > +PeiGetVariableEx ( > + IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI *This, > + IN CONST CHAR16 *VariableName, > + IN CONST EFI_GUID *VariableGuid, > + OUT UINT32 *Attributes, > + IN OUT UINTN *DataSize, > + OUT VOID *Data OPTIONAL > + ) > +{ > + EFI_STATUS Status; > + > + // > + // If variable protection is employed, always get variable data throug= h > + // ProtectedVariableLib. > + // > + Status =3D ProtectedVariableLibGetByName (VariableName, VariableGuid, > Attributes, DataSize, Data); > + if (Status !=3D EFI_UNSUPPORTED) { > + return Status; > + } > + > + return PeiGetVariable (This, VariableName, VariableGuid, Attributes, D= ataSize, > Data); > +} > + > +/** > + Return the next variable name and GUID. > + > + This function is called multiple times to retrieve the VariableName > + and VariableGuid of all variables currently available in the system. > + On each call, the previous results are passed into the interface, > + and, on return, the interface returns the data for the next > + interface. When the entire variable list has been returned, > + EFI_NOT_FOUND is returned. > + > + @param This A pointer to this instance of the > EFI_PEI_READ_ONLY_VARIABLE2_PPI. > + > + @param VariableNameSize On entry, points to the size of the buffer p= ointed > to by VariableName. > + On return, the size of the variable name buf= fer. > + @param VariableName On entry, a pointer to a null-terminated str= ing that > is the variable's name. > + On return, points to the next variable's nul= l-terminated name > string. > + @param VariableGuid On entry, a pointer to an EFI_GUID that is t= he > variable's GUID. > + On return, a pointer to the next variable's = GUID. > + > + @retval EFI_SUCCESS The variable was read successfully. > + @retval EFI_NOT_FOUND The variable could not be found. > + @retval EFI_BUFFER_TOO_SMALL The VariableNameSize is too small for th= e > resulting > + data. VariableNameSize is updated with t= he size > + required for the specified variable. > + @retval EFI_INVALID_PARAMETER VariableName, VariableGuid or > + VariableNameSize is NULL. > + @retval EFI_DEVICE_ERROR The variable could not be retrieved beca= use of > a device error. > + > +**/ > +EFI_STATUS > +EFIAPI > +PeiGetNextVariableNameEx ( > + IN CONST EFI_PEI_READ_ONLY_VARIABLE2_PPI *This, > + IN OUT UINTN *VariableNameSize, > + IN OUT CHAR16 *VariableName, > + IN OUT EFI_GUID *VariableGuid > + ) > +{ > + EFI_STATUS Status; > + > + // > + // If variable protection is employed, always get next variable throug= h > + // ProtectedVariableLib. > + // > + Status =3D ProtectedVariableLibFindNext (VariableNameSize, VariableNam= e, > VariableGuid); > + if (Status !=3D EFI_UNSUPPORTED) { > + return Status; > + } > + > + return PeiGetNextVariableName (This, VariableNameSize, VariableName, > VariableGuid); > +} > diff --git a/MdeModulePkg/Universal/Variable/Pei/VariableParsing.c > b/MdeModulePkg/Universal/Variable/Pei/VariableParsing.c > new file mode 100644 > index 000000000000..2d605d39cbb6 > --- /dev/null > +++ b/MdeModulePkg/Universal/Variable/Pei/VariableParsing.c > @@ -0,0 +1,941 @@ > +/** @file > + Implement ReadOnly Variable Services required by PEIM and install > + PEI ReadOnly Varaiable2 PPI. These services operates the non volatile = storage > space. > + > +Copyright (c) 2022, Intel Corporation. All rights reserved.
> +SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#include "Variable.h" > +#include "VariableStore.h" > + > +/** > + > + Gets the pointer to the first variable header in given variable store = area. > + > + @param[in] VarStoreHeader Pointer to the Variable Store Header. > + > + @return Pointer to the first variable header. > + > +**/ > +VARIABLE_HEADER * > +GetStartPointer ( > + IN VARIABLE_STORE_HEADER *VarStoreHeader > + ) > +{ > + // > + // The start of variable store > + // > + return (VARIABLE_HEADER *)HEADER_ALIGN (VarStoreHeader + 1); > +} > + > +/** > + > + Gets the pointer to the end of the variable storage area. > + > + This function gets pointer to the end of the variable storage > + area, according to the input variable store header. > + > + @param[in] VarStoreHeader Pointer to the Variable Store Header. > + > + @return Pointer to the end of the variable storage area. > + > +**/ > +VARIABLE_HEADER * > +GetEndPointer ( > + IN VARIABLE_STORE_HEADER *VarStoreHeader > + ) > +{ > + // > + // The end of variable store > + // > + return (VARIABLE_HEADER *)HEADER_ALIGN ((UINTN)VarStoreHeader + > VarStoreHeader->Size); > +} > + > +/** > + This code checks if variable header is valid or not. > + > + @param[in] Variable Pointer to the Variable Header. > + > + @retval TRUE Variable header is valid. > + @retval FALSE Variable header is not valid. > + > +**/ > +BOOLEAN > +IsValidVariableHeader ( > + IN VARIABLE_HEADER *Variable > + ) > +{ > + if ((Variable =3D=3D NULL) || (Variable->StartId !=3D VARIABLE_DATA)) = { > + return FALSE; > + } > + > + return TRUE; > +} > + > +/** > + This code gets the size of variable header. > + > + @param[in] AuthFlag Authenticated variable flag. > + > + @return Size of variable header in bytes in type UINTN. > + > +**/ > +UINTN > +GetVariableHeaderSize ( > + IN BOOLEAN AuthFlag > + ) > +{ > + UINTN Value; > + > + if (AuthFlag) { > + Value =3D sizeof (AUTHENTICATED_VARIABLE_HEADER); > + } else { > + Value =3D sizeof (VARIABLE_HEADER); > + } > + > + return Value; > +} > + > +/** > + This code gets the size of name of variable. > + > + @param[in] Variable Pointer to the Variable Header. > + @param[in] AuthFlag Authenticated variable flag. > + > + @return Size of variable in bytes in type UINTN. > + > +**/ > +UINTN > +NameSizeOfVariable ( > + IN VARIABLE_HEADER *Variable, > + IN BOOLEAN AuthFlag > + ) > +{ > + AUTHENTICATED_VARIABLE_HEADER *AuthVariable; > + > + AuthVariable =3D (AUTHENTICATED_VARIABLE_HEADER *)Variable; > + if (AuthFlag) { > + if ((AuthVariable->State =3D=3D (UINT8)(-1)) || > + (AuthVariable->DataSize =3D=3D (UINT32)(-1)) || > + (AuthVariable->NameSize =3D=3D (UINT32)(-1)) || > + (AuthVariable->Attributes =3D=3D (UINT32)(-1))) > + { > + return 0; > + } > + > + return (UINTN)AuthVariable->NameSize; > + } else { > + if ((Variable->State =3D=3D (UINT8)(-1)) || > + (Variable->DataSize =3D=3D (UINT32)(-1)) || > + (Variable->NameSize =3D=3D (UINT32)(-1)) || > + (Variable->Attributes =3D=3D (UINT32)(-1))) > + { > + return 0; > + } > + > + return (UINTN)Variable->NameSize; > + } > +} > + > +/** > + This code gets the size of data of variable. > + > + @param[in] Variable Pointer to the Variable Header. > + @param[in] AuthFlag Authenticated variable flag. > + > + @return Size of variable in bytes in type UINTN. > + > +**/ > +UINTN > +DataSizeOfVariable ( > + IN VARIABLE_HEADER *Variable, > + IN BOOLEAN AuthFlag > + ) > +{ > + AUTHENTICATED_VARIABLE_HEADER *AuthVariable; > + > + AuthVariable =3D (AUTHENTICATED_VARIABLE_HEADER *)Variable; > + if (AuthFlag) { > + if ((AuthVariable->State =3D=3D (UINT8)(-1)) || > + (AuthVariable->DataSize =3D=3D (UINT32)(-1)) || > + (AuthVariable->NameSize =3D=3D (UINT32)(-1)) || > + (AuthVariable->Attributes =3D=3D (UINT32)(-1))) > + { > + return 0; > + } > + > + return (UINTN)AuthVariable->DataSize; > + } else { > + if ((Variable->State =3D=3D (UINT8)(-1)) || > + (Variable->DataSize =3D=3D (UINT32)(-1)) || > + (Variable->NameSize =3D=3D (UINT32)(-1)) || > + (Variable->Attributes =3D=3D (UINT32)(-1))) > + { > + return 0; > + } > + > + return (UINTN)Variable->DataSize; > + } > +} > + > +/** > + This code gets the pointer to the variable name. > + > + @param[in] Variable Pointer to the Variable Header. > + @param[in] AuthFlag Authenticated variable flag. > + > + @return A CHAR16* pointer to Variable Name. > + > +**/ > +CHAR16 * > +GetVariableNamePtr ( > + IN VARIABLE_HEADER *Variable, > + IN BOOLEAN AuthFlag > + ) > +{ > + return (CHAR16 *)((UINTN)Variable + GetVariableHeaderSize (AuthFlag)); > +} > + > +/** > + This code gets the pointer to the variable guid. > + > + @param[in] Variable Pointer to the Variable Header. > + @param[in] AuthFlag Authenticated variable flag. > + > + @return A EFI_GUID* pointer to Vendor Guid. > + > +**/ > +EFI_GUID * > +GetVendorGuidPtr ( > + IN VARIABLE_HEADER *Variable, > + IN BOOLEAN AuthFlag > + ) > +{ > + AUTHENTICATED_VARIABLE_HEADER *AuthVariable; > + > + AuthVariable =3D (AUTHENTICATED_VARIABLE_HEADER *)Variable; > + if (AuthFlag) { > + return &AuthVariable->VendorGuid; > + } else { > + return &Variable->VendorGuid; > + } > +} > + > +/** > + This code gets the pointer to the variable data. > + > + @param[in] Variable Pointer to the Variable Header. > + @param[in] VariableHeader Pointer to the Variable Header that has > consecutive content. > + @param[in] AuthFlag Authenticated variable flag. > + > + @return A UINT8* pointer to Variable Data. > + > +**/ > +UINT8 * > +GetVariableDataPtr ( > + IN VARIABLE_HEADER *Variable, > + IN VARIABLE_HEADER *VariableHeader, > + IN BOOLEAN AuthFlag > + ) > +{ > + UINTN Value; > + > + // > + // Be careful about pad size for alignment > + // > + Value =3D (UINTN)GetVariableNamePtr (Variable, AuthFlag); > + Value +=3D NameSizeOfVariable (VariableHeader, AuthFlag); > + Value +=3D GET_PAD_SIZE (NameSizeOfVariable (VariableHeader, AuthFlag)= ); > + > + return (UINT8 *)Value; > +} > + > +/** > + This code gets the pointer to the next variable header. > + > + @param[in] StoreInfo Pointer to variable store info structure= . > + @param[in] Variable Pointer to the Variable Header. > + @param[in] VariableHeader Pointer to the Variable Header that has > consecutive content. > + > + @return A VARIABLE_HEADER* pointer to next variable header. > + > +**/ > +VARIABLE_HEADER * > +GetNextVariablePtr ( > + IN VARIABLE_STORE_INFO *StoreInfo, > + IN VARIABLE_HEADER *Variable, > + IN VARIABLE_HEADER *VariableHeader > + ) > +{ > + EFI_PHYSICAL_ADDRESS TargetAddress; > + EFI_PHYSICAL_ADDRESS SpareAddress; > + UINTN Value; > + > + Value =3D (UINTN)GetVariableDataPtr (Variable, VariableHeader, Store= Info- > >AuthFlag); > + Value +=3D DataSizeOfVariable (VariableHeader, StoreInfo->AuthFlag); > + Value +=3D GET_PAD_SIZE (DataSizeOfVariable (VariableHeader, StoreInfo= - > >AuthFlag)); > + // > + // Be careful about pad size for alignment > + // > + Value =3D HEADER_ALIGN (Value); > + > + if (StoreInfo->FtwLastWriteData !=3D NULL) { > + TargetAddress =3D StoreInfo->FtwLastWriteData->TargetAddress; > + SpareAddress =3D StoreInfo->FtwLastWriteData->SpareAddress; > + if (((UINTN)Variable < (UINTN)TargetAddress) && (Value >=3D > (UINTN)TargetAddress)) { > + // > + // Next variable is in spare block. > + // > + Value =3D (UINTN)SpareAddress + (Value - (UINTN)TargetAddress); > + } > + } > + > + return (VARIABLE_HEADER *)Value; > +} > + > +/** > + Compare two variable names, one of them may be inconsecutive. > + > + @param[in] StoreInfo Pointer to variable store info structure. > + @param[in] Name1 Pointer to one variable name. > + @param[in] Name2 Pointer to another variable name. > + @param[in] NameSize Variable name size. > + > + @retval TRUE Name1 and Name2 are identical. > + @retval FALSE Name1 and Name2 are not identical. > + > +**/ > +BOOLEAN > +CompareVariableName ( > + IN VARIABLE_STORE_INFO *StoreInfo, > + IN CONST CHAR16 *Name1, > + IN CONST CHAR16 *Name2, > + IN UINTN NameSize > + ) > +{ > + EFI_PHYSICAL_ADDRESS TargetAddress; > + EFI_PHYSICAL_ADDRESS SpareAddress; > + UINTN PartialNameSize; > + > + if (StoreInfo->FtwLastWriteData !=3D NULL) { > + TargetAddress =3D StoreInfo->FtwLastWriteData->TargetAddress; > + SpareAddress =3D StoreInfo->FtwLastWriteData->SpareAddress; > + if (((UINTN)Name1 < (UINTN)TargetAddress) && (((UINTN)Name1 + > NameSize) > (UINTN)TargetAddress)) { > + // > + // Name1 is inconsecutive. > + // > + PartialNameSize =3D (UINTN)TargetAddress - (UINTN)Name1; > + // > + // Partial content is in NV storage. > + // > + if (CompareMem ((UINT8 *)Name1, (UINT8 *)Name2, PartialNameSize) = =3D=3D > 0) { > + // > + // Another partial content is in spare block. > + // > + if (CompareMem ((UINT8 *)(UINTN)SpareAddress, (UINT8 *)Name2 + > PartialNameSize, NameSize - PartialNameSize) =3D=3D 0) { > + return TRUE; > + } > + } > + > + return FALSE; > + } else if (((UINTN)Name2 < (UINTN)TargetAddress) && (((UINTN)Name2 + > NameSize) > (UINTN)TargetAddress)) { > + // > + // Name2 is inconsecutive. > + // > + PartialNameSize =3D (UINTN)TargetAddress - (UINTN)Name2; > + // > + // Partial content is in NV storage. > + // > + if (CompareMem ((UINT8 *)Name2, (UINT8 *)Name1, PartialNameSize) = =3D=3D > 0) { > + // > + // Another partial content is in spare block. > + // > + if (CompareMem ((UINT8 *)(UINTN)SpareAddress, (UINT8 *)Name1 + > PartialNameSize, NameSize - PartialNameSize) =3D=3D 0) { > + return TRUE; > + } > + } > + > + return FALSE; > + } > + } > + > + // > + // Both Name1 and Name2 are consecutive. > + // > + if (CompareMem ((UINT8 *)Name1, (UINT8 *)Name2, NameSize) =3D=3D 0) { > + return TRUE; > + } > + > + return FALSE; > +} > + > +/** > + This function compares a variable with variable entries in database. > + > + @param[in] StoreInfo Pointer to variable store info structure= . > + @param[in] Variable Pointer to the variable in our database > + @param[in] VariableHeader Pointer to the Variable Header that has > + consecutive content. > + @param[in] VariableName Name of the variable to compare to 'Vari= able' > + @param[in] VendorGuid GUID of the variable to compare to 'Vari= able' > + @param[out] PtrTrack Variable Track Pointer structure that co= ntains > + Variable Information. > + > + @retval EFI_SUCCESS Found match variable > + @retval EFI_NOT_FOUND Variable not found > + > +**/ > +EFI_STATUS > +CompareWithValidVariable ( > + IN VARIABLE_STORE_INFO *StoreInfo, > + IN VARIABLE_HEADER *Variable, > + IN VARIABLE_HEADER *VariableHeader, > + IN CONST CHAR16 *VariableName, > + IN CONST EFI_GUID *VendorGuid, > + OUT VARIABLE_POINTER_TRACK *PtrTrack > + ) > +{ > + VOID *Point; > + EFI_GUID *TempVendorGuid; > + > + TempVendorGuid =3D GetVendorGuidPtr (VariableHeader, StoreInfo->AuthFl= ag); > + > + if (VariableName[0] =3D=3D 0) { > + PtrTrack->CurrPtr =3D Variable; > + return EFI_SUCCESS; > + } else { > + // > + // Don't use CompareGuid function here for performance reasons. > + // Instead we compare the GUID a UINT32 at a time and branch > + // on the first failed comparison. > + // > + if ((((INT32 *)VendorGuid)[0] =3D=3D ((INT32 *)TempVendorGuid)[0]) &= & > + (((INT32 *)VendorGuid)[1] =3D=3D ((INT32 *)TempVendorGuid)[1]) &= & > + (((INT32 *)VendorGuid)[2] =3D=3D ((INT32 *)TempVendorGuid)[2]) &= & > + (((INT32 *)VendorGuid)[3] =3D=3D ((INT32 *)TempVendorGuid)[3]) > + ) > + { > + ASSERT (NameSizeOfVariable (VariableHeader, StoreInfo->AuthFlag) != =3D 0); > + Point =3D (VOID *)GetVariableNamePtr (Variable, StoreInfo->AuthFla= g); > + if (CompareVariableName (StoreInfo, VariableName, Point, > NameSizeOfVariable (VariableHeader, StoreInfo->AuthFlag))) { > + PtrTrack->CurrPtr =3D Variable; > + return EFI_SUCCESS; > + } > + } > + } > + > + return EFI_NOT_FOUND; > +} > + > +/** > + Get variable header that has consecutive content. > + > + @param[in] StoreInfo Pointer to variable store info structure. > + @param[in] Variable Pointer to the Variable Header. > + @param[out] VariableHeader Pointer to Pointer to the Variable Header > + that has consecutive content. > + > + @retval TRUE Variable header is valid. > + @retval FALSE Variable header is not valid. > + > +**/ > +BOOLEAN > +GetVariableHeader ( > + IN VARIABLE_STORE_INFO *StoreInfo, > + IN VARIABLE_HEADER *Variable, > + OUT VARIABLE_HEADER **VariableHeader > + ) > +{ > + EFI_PHYSICAL_ADDRESS TargetAddress; > + EFI_PHYSICAL_ADDRESS SpareAddress; > + EFI_HOB_GUID_TYPE *GuidHob; > + UINTN PartialHeaderSize; > + > + if (Variable =3D=3D NULL) { > + return FALSE; > + } > + > + // > + // First assume variable header pointed by Variable is consecutive. > + // > + *VariableHeader =3D Variable; > + > + if (StoreInfo->FtwLastWriteData !=3D NULL) { > + TargetAddress =3D StoreInfo->FtwLastWriteData->TargetAddress; > + SpareAddress =3D StoreInfo->FtwLastWriteData->SpareAddress; > + if (((UINTN)Variable > (UINTN)SpareAddress) && > + (((UINTN)Variable - (UINTN)SpareAddress + (UINTN)TargetAddress) = >=3D > (UINTN)GetEndPointer (StoreInfo->VariableStoreHeader))) > + { > + // > + // Reach the end of variable store. > + // > + return FALSE; > + } > + > + if (((UINTN)Variable < (UINTN)TargetAddress) && (((UINTN)Variable + > GetVariableHeaderSize (StoreInfo->AuthFlag)) > (UINTN)TargetAddress)) { > + // > + // Variable header pointed by Variable is inconsecutive, > + // create a guid hob to combine the two partial variable header co= ntent > together. > + // > + GuidHob =3D GetFirstGuidHob (&gEfiCallerIdGuid); > + if (GuidHob !=3D NULL) { > + *VariableHeader =3D (VARIABLE_HEADER *)GET_GUID_HOB_DATA > (GuidHob); > + } else { > + *VariableHeader =3D (VARIABLE_HEADER *)BuildGuidHob > (&gEfiCallerIdGuid, GetVariableHeaderSize (StoreInfo->AuthFlag)); > + PartialHeaderSize =3D (UINTN)TargetAddress - (UINTN)Variable; > + // > + // Partial content is in NV storage. > + // > + CopyMem ((UINT8 *)*VariableHeader, (UINT8 *)Variable, > PartialHeaderSize); > + // > + // Another partial content is in spare block. > + // > + CopyMem ((UINT8 *)*VariableHeader + PartialHeaderSize, (UINT8 > *)(UINTN)SpareAddress, GetVariableHeaderSize (StoreInfo->AuthFlag) - > PartialHeaderSize); > + } > + } > + } else { > + if (Variable >=3D GetEndPointer (StoreInfo->VariableStoreHeader)) { > + // > + // Reach the end of variable store. > + // > + return FALSE; > + } > + } > + > + return IsValidVariableHeader (*VariableHeader); > +} > + > +/** > + Get variable name or data to output buffer. > + > + @param[in] StoreInfo Pointer to variable store info structure. > + @param[in] NameOrData Pointer to the variable name/data that may = be > inconsecutive. > + @param[in] Size Variable name/data size. > + @param[out] Buffer Pointer to output buffer to hold the variab= le > name/data. > + > +**/ > +VOID > +GetVariableNameOrData ( > + IN VARIABLE_STORE_INFO *StoreInfo, > + IN UINT8 *NameOrData, > + IN UINTN Size, > + OUT UINT8 *Buffer > + ) > +{ > + EFI_PHYSICAL_ADDRESS TargetAddress; > + EFI_PHYSICAL_ADDRESS SpareAddress; > + UINTN PartialSize; > + > + if (StoreInfo->FtwLastWriteData !=3D NULL) { > + TargetAddress =3D StoreInfo->FtwLastWriteData->TargetAddress; > + SpareAddress =3D StoreInfo->FtwLastWriteData->SpareAddress; > + if (((UINTN)NameOrData < (UINTN)TargetAddress) && > (((UINTN)NameOrData + Size) > (UINTN)TargetAddress)) { > + // > + // Variable name/data is inconsecutive. > + // > + PartialSize =3D (UINTN)TargetAddress - (UINTN)NameOrData; > + // > + // Partial content is in NV storage. > + // > + CopyMem (Buffer, NameOrData, PartialSize); > + // > + // Another partial content is in spare block. > + // > + CopyMem (Buffer + PartialSize, (UINT8 *)(UINTN)SpareAddress, Size = - > PartialSize); > + return; > + } > + } > + > + // > + // Variable name/data is consecutive. > + // > + CopyMem (Buffer, NameOrData, Size); > +} > + > +/** > + > + Internal function to retrieve variable information. > + > + @param[in,out] VariableInfo Pointer to variable information. > + @param[in] StoreInfo Pointer to store copy of variable (opt= ional). > + @param[in] VariablePtr Pointer to variable buffer. > + @param[in] VariableHeader Pointer to variable header. > + > + @retval EFI_INVALID_PARAMETER One ore more required parameters are > NULL. > + @retval EFI_BUFFER_TOO_SMALL Given buffer is too small to hold data. > + @retval EFI_SUCCESS Variable details are retrieved successf= ully. > + > +**/ > +EFI_STATUS > +EFIAPI > +GetVariableInfoInternal ( > + IN OUT PROTECTED_VARIABLE_INFO *VariableInfo, > + IN VARIABLE_STORE_INFO *StoreInfo OPTIONAL, > + IN VARIABLE_HEADER *VariablePtr, > + IN VARIABLE_HEADER *VariableHeader > + ) > +{ > + VARIABLE_HEADER *VariableBuffer; > + AUTHENTICATED_VARIABLE_HEADER *AuthVariableHeader; > + UINTN NameSize; > + UINTN DataSize; > + UINTN VariableSize; > + > + if ((VariableInfo =3D=3D NULL) || (VariablePtr =3D=3D NULL) || (Variab= leHeader =3D=3D > NULL)) { > + ASSERT (VariableInfo !=3D NULL); > + ASSERT (VariablePtr !=3D NULL); > + ASSERT (VariableHeader !=3D NULL); > + return EFI_INVALID_PARAMETER; > + } > + > + VariableBuffer =3D VariableInfo->Buffer; > + > + // > + // Make a copy of the whole variable if VariableInfo->Buffer is given.= But > + // don't do this if StoreInfo is not given, because VariableInfo->Buff= er > + // has already hold a copy of variable in such situation. > + // > + NameSize =3D NameSizeOfVariable (VariableHeader, VariableInfo->Flags.A= uth); > + DataSize =3D DataSizeOfVariable (VariableHeader, VariableInfo->Flags.A= uth); > + if ((VariableBuffer !=3D NULL) && (VariableBuffer !=3D VariablePtr)) { > + if (StoreInfo !=3D NULL) { > + CopyMem ( > + VariableBuffer, > + VariableHeader, > + GetVariableHeaderSize (VariableInfo->Flags.Auth) > + ); > + GetVariableNameOrData ( > + StoreInfo, > + (UINT8 *)GetVariableNamePtr (VariablePtr, VariableInfo->Flags.Au= th), > + NameSize, > + (UINT8 *)GetVariableNamePtr (VariableBuffer, VariableInfo->Flags= .Auth) > + ); > + GetVariableNameOrData ( > + StoreInfo, > + (UINT8 *)GetVariableDataPtr (VariablePtr, VariableHeader, Variab= leInfo- > >Flags.Auth), > + DataSize, > + (UINT8 *)GetVariableDataPtr (VariableBuffer, VariableHeader, > VariableInfo->Flags.Auth) > + ); > + } else { > + // > + // Suppose the variable is in consecutive space. > + // > + VariableSize =3D GetVariableHeaderSize (VariableInfo->Flags.Auth) > + + NameSize + GET_PAD_SIZE (NameSize) > + + DataSize; > + CopyMem (VariableBuffer, VariablePtr, VariableSize); > + } > + } > + > + // > + // Generally, if no consecutive buffer passed in, don't return back an= y data. > + // > + // If follow pointers are NULL, return back pointers to following data= inside > + // VariableInfo->Buffer, if it's given. > + // > + // VariableInfo->Header.VariableName > + // VariableInfo->Header.Data > + // VariableInfo->Header.VendorGuid > + // VariableInfo->Header.TimeStamp > + // > + // Otherwise, suppose they're buffers used to hold a copy of correspon= ding > + // data. > + // > + // > + > + // > + // AuthVariable header > + // > + if (VariableInfo->Flags.Auth) { > + AuthVariableHeader =3D (AUTHENTICATED_VARIABLE_HEADER > *)VariableHeader; > + > + VariableInfo->Header.State =3D AuthVariableHeader->State; > + VariableInfo->Header.Attributes =3D AuthVariableHeader->Attribut= es; > + VariableInfo->Header.PubKeyIndex =3D AuthVariableHeader->PubKeyIn= dex; > + VariableInfo->Header.MonotonicCount =3D ReadUnaligned64 ( > + &(AuthVariableHeader->Monoto= nicCount) > + ); > + if (VariableInfo->Header.TimeStamp !=3D NULL) { > + CopyMem ( > + VariableInfo->Header.TimeStamp, > + &AuthVariableHeader->TimeStamp, > + sizeof (EFI_TIME) > + ); > + } else if (VariableBuffer !=3D NULL) { > + AuthVariableHeader =3D (AUTHENTICATED_VARIABLE_HEADER > *)VariableBuffer; > + VariableInfo->Header.TimeStamp =3D &AuthVariableHeader->TimeStamp; > + } > + } else { > + VariableInfo->Header.State =3D VariableHeader->State; > + VariableInfo->Header.Attributes =3D VariableHeader->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 (VariableHeader, VariableInfo->Flags.Auth) > + ); > + } else if (VariableBuffer !=3D NULL) { > + VariableInfo->Header.VendorGuid > + =3D GetVendorGuidPtr (VariableBuffer, VariableInfo->Flags.Auth); > + } > + > + // > + // VariableName > + // > + if ( (VariableInfo->Header.VariableName !=3D NULL) > + && (VariableInfo->Header.NameSize >=3D NameSize)) > + { > + GetVariableNameOrData ( > + StoreInfo, > + (UINT8 *)GetVariableNamePtr (VariablePtr, VariableInfo->Flags.Auth= ), > + NameSize, > + (UINT8 *)VariableInfo->Header.VariableName > + ); > + } else if (VariableBuffer !=3D NULL) { > + VariableInfo->Header.VariableName > + =3D GetVariableNamePtr (VariableBuffer, VariableInfo->Flags.Auth); > + } else if (VariableInfo->Header.VariableName !=3D NULL) { > + return EFI_BUFFER_TOO_SMALL; > + } > + > + // > + // Data > + // > + if ( (VariableInfo->Header.Data !=3D NULL) > + && (VariableInfo->Header.DataSize >=3D DataSize)) > + { > + GetVariableNameOrData ( > + StoreInfo, > + GetVariableDataPtr (VariablePtr, VariableHeader, StoreInfo->AuthFl= ag), > + DataSize, > + VariableInfo->Header.Data > + ); > + } else if (VariableBuffer !=3D NULL) { > + VariableInfo->Header.Data > + =3D GetVariableDataPtr (VariableBuffer, VariableBuffer, VariableIn= fo- > >Flags.Auth); > + } else if (VariableInfo->Header.Data !=3D NULL) { > + return EFI_BUFFER_TOO_SMALL; > + } > + > + // > + // Update size information about name & data. > + // > + VariableInfo->Header.NameSize =3D NameSize; > + VariableInfo->Header.DataSize =3D DataSize; > + > + return EFI_SUCCESS; > +} > + > +/** > + > + Retrieve details about a variable, given by VariableInfo->Buffer or > + VariableInfo->Index, and pass the details back in VariableInfo->Header= . > + > + This function is used to resolve the variable data structure into > + VariableInfo->Header, for easier access later without revisiting the v= ariable > + data in variable store. If pointers in the structure of VariableInfo->= Header > + are not NULL, it's supposed that they are buffers passed in to hold a = copy of > + data of corresponding data fields in variable data structure. Otherwis= e, this > + function simply returns pointers pointing to address of those data fie= lds. > + > + The variable is specified by either VariableInfo->Index or VariableInf= o->Buffer. > + If VariableInfo->Index is given, this function finds the corresponding= variable > + first from variable storage according to the Index. > + > + If both VariableInfo->Index and VariableInfo->Buffer are given, it's s= upposed > + that VariableInfo->Buffer is a buffer passed in to hold a whole copy o= f > + requested variable data to be returned. > + > + @param[in,out] VariableInfo Pointer to variable informatio= n. > + > + @retval EFI_INVALID_PARAMETER VariableInfo is NULL or both VariableIn= fo- > >Buffer > + and VariableInfo->Index are NULL (0). > + @retval EFI_NOT_FOUND If given Buffer or Index is out of rang= e 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_HEADER *VariablePtr; > + VARIABLE_HEADER *VariableHeader; > + VARIABLE_STORE_TYPE StoreType; > + VARIABLE_STORE_INFO StoreInfo; > + UINTN Offset; > + > + if ((VariableInfo =3D=3D NULL) || > + ((VariableInfo->Buffer =3D=3D NULL) && (VariableInfo->StoreIndex = =3D=3D > VAR_INDEX_INVALID))) > + { > + ASSERT (VariableInfo !=3D NULL); > + ASSERT (VariableInfo->StoreIndex !=3D VAR_INDEX_INVALID || VariableI= nfo- > >Buffer !=3D NULL); > + return EFI_INVALID_PARAMETER; > + } > + > + StoreInfo.VariableStoreHeader =3D NULL; > + for (StoreType =3D VariableStoreTypeHob; StoreType < VariableStoreType= Max; > ++StoreType) { > + GetVariableStore (StoreType, &StoreInfo); > + if (StoreInfo.VariableStoreHeader !=3D NULL) { > + break; > + } > + } > + > + ASSERT (StoreInfo.VariableStoreHeader !=3D NULL); > + > + // > + // No StoreIndex? Don't retrieve variable information from store but j= ust from > + // VariableInfo->Buffer. > + // > + if (VariableInfo->StoreIndex =3D=3D VAR_INDEX_INVALID) { > + VariablePtr =3D VariableInfo->Buffer; > + VariableHeader =3D VariablePtr; > + > + return GetVariableInfoInternal (VariableInfo, NULL, VariablePtr, > VariableHeader); > + } > + > + Offset =3D (UINTN)VariableInfo->StoreIndex; > + if ( (StoreInfo.FtwLastWriteData !=3D NULL) > + && (Offset >=3D ((UINTN)StoreInfo.FtwLastWriteData->TargetAddress > + - (UINTN)StoreInfo.VariableStoreHeader))) > + { > + Offset -=3D ((UINTN)StoreInfo.FtwLastWriteData->TargetAddress > + - (UINTN)StoreInfo.VariableStoreHeader); > + VariablePtr =3D (VARIABLE_HEADER *) > + ((UINTN)StoreInfo.FtwLastWriteData->SpareAddress + Off= set); > + } else { > + VariablePtr =3D (VARIABLE_HEADER *) > + ((UINTN)StoreInfo.VariableStoreHeader + Offset); > + } > + > + // > + // Note that variable might be in unconsecutive space. Always get a co= py > + // of its header in consecutive buffer. > + // > + if (!GetVariableHeader (&StoreInfo, VariablePtr, &VariableHeader)) { > + return EFI_NOT_FOUND; > + } > + > + return GetVariableInfoInternal (VariableInfo, &StoreInfo, VariablePtr, > VariableHeader); > +} > + > +/** > + > + Retrieve details of the variable next to given variable within Variabl= eStore. > + > + If VarInfo->Buffer is NULL, the first one in VariableStore is returned= . > + > + 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_HEADER *VariablePtr; > + VARIABLE_HEADER *VariableHeader; > + VARIABLE_STORE_INFO StoreInfo; > + VARIABLE_STORE_TYPE StoreType; > + UINTN Offset; > + > + if (VariableInfo =3D=3D NULL) { > + ASSERT (VariableInfo !=3D NULL); > + return EFI_INVALID_PARAMETER; > + } > + > + StoreInfo.VariableStoreHeader =3D NULL; > + for (StoreType =3D VariableStoreTypeHob; StoreType < VariableStoreType= Max; > ++StoreType) { > + GetVariableStore (StoreType, &StoreInfo); > + if (StoreInfo.VariableStoreHeader !=3D NULL) { > + break; > + } > + } > + > + ASSERT (StoreInfo.VariableStoreHeader !=3D NULL); > + > + // > + // VariableInfo->StoreIndex is supposed to be the index to variable fo= und > + // last time. Use it to get the variable next to it in store. If it's = invalid, > + // return the first variable available in store. > + // > + VariableInfo->Flags.Auth =3D StoreInfo.AuthFlag; > + if (VariableInfo->StoreIndex =3D=3D VAR_INDEX_INVALID) { > + VariablePtr =3D GetStartPointer (StoreInfo.VariableStoreHeader); > + } else { > + Offset =3D (UINTN)VariableInfo->StoreIndex; > + if ( (StoreInfo.FtwLastWriteData !=3D NULL) > + && (Offset >=3D ((UINTN)StoreInfo.FtwLastWriteData->TargetAddress > + - (UINTN)StoreInfo.VariableStoreHeader))) > + { > + Offset -=3D ((UINTN)StoreInfo.FtwLastWriteData->TargetAddress > + - (UINTN)StoreInfo.VariableStoreHeader); > + VariablePtr =3D (VARIABLE_HEADER *) > + ((UINTN)StoreInfo.FtwLastWriteData->SpareAddress + O= ffset); > + } else { > + VariablePtr =3D (VARIABLE_HEADER *) > + ((UINTN)StoreInfo.VariableStoreHeader + Offset); > + } > + > + // > + // Note that variable might be in unconsecutive space. Always get a = copy > + // of its header in consecutive buffer. > + // > + if (!GetVariableHeader (&StoreInfo, VariablePtr, &VariableHeader)) { > + return EFI_NOT_FOUND; > + } > + > + VariablePtr =3D GetNextVariablePtr (&StoreInfo, VariablePtr, Variabl= eHeader); > + } > + > + // > + // Get a copy of variable header in consecutive buffer. > + // > + if (!GetVariableHeader (&StoreInfo, VariablePtr, &VariableHeader)) { > + return EFI_NOT_FOUND; > + } > + > + // > + // Use the offset to the start of variable store as index of the varia= ble. > + // > + if ( (StoreInfo.FtwLastWriteData =3D=3D NULL) > + || ((UINTN)VariablePtr < (UINTN)StoreInfo.FtwLastWriteData- > >TargetAddress)) > + { > + VariableInfo->StoreIndex > + =3D (UINT64)((UINTN)VariablePtr - (UINTN)StoreInfo.VariableStoreHe= ader); > + } else { > + VariableInfo->StoreIndex > + =3D (UINT64)((UINTN)StoreInfo.FtwLastWriteData->TargetAddress > + - (UINTN)StoreInfo.VariableStoreHeader); > + VariableInfo->StoreIndex > + +=3D (UINT64)((UINTN)VariablePtr - (UINTN)StoreInfo.FtwLastWriteDa= ta- > >SpareAddress); > + } > + > + if ((StoreType =3D=3D VariableStoreTypeHob) && (VariableInfo->Buffer = =3D=3D NULL)) { > + VariableInfo->Buffer =3D VariablePtr; > + } > + > + return GetVariableInfoInternal (VariableInfo, &StoreInfo, VariablePtr, > VariableHeader); > +} > diff --git a/MdeModulePkg/Universal/Variable/Pei/VariableStore.c > b/MdeModulePkg/Universal/Variable/Pei/VariableStore.c > new file mode 100644 > index 000000000000..72bd17a43048 > --- /dev/null > +++ b/MdeModulePkg/Universal/Variable/Pei/VariableStore.c > @@ -0,0 +1,305 @@ > +/** @file > + Implement ReadOnly Variable Services required by PEIM and install > + PEI ReadOnly Varaiable2 PPI. These services operates the non volatile = storage > space. > + > +Copyright (c) 2022, Intel Corporation. All rights reserved.
> +SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#include "VariableParsing.h" > +#include "VariableStore.h" > + > +/** > + Get variable store status. > + > + @param[in] VarStoreHeader Pointer to the Variable Store Header. > + > + @retval EfiRaw Variable store is raw > + @retval EfiValid Variable store is valid > + @retval EfiInvalid Variable store is invalid > + > +**/ > +VARIABLE_STORE_STATUS > +GetVariableStoreStatus ( > + IN VARIABLE_STORE_HEADER *VarStoreHeader > + ) > +{ > + if ((CompareGuid (&VarStoreHeader->Signature, > &gEfiAuthenticatedVariableGuid) || > + CompareGuid (&VarStoreHeader->Signature, &gEfiVariableGuid)) && > + (VarStoreHeader->Format =3D=3D VARIABLE_STORE_FORMATTED) && > + (VarStoreHeader->State =3D=3D VARIABLE_STORE_HEALTHY) > + ) > + { > + return EfiValid; > + } > + > + if ((((UINT32 *)(&VarStoreHeader->Signature))[0] =3D=3D 0xffffffff) && > + (((UINT32 *)(&VarStoreHeader->Signature))[1] =3D=3D 0xffffffff) && > + (((UINT32 *)(&VarStoreHeader->Signature))[2] =3D=3D 0xffffffff) && > + (((UINT32 *)(&VarStoreHeader->Signature))[3] =3D=3D 0xffffffff) && > + (VarStoreHeader->Size =3D=3D 0xffffffff) && > + (VarStoreHeader->Format =3D=3D 0xff) && > + (VarStoreHeader->State =3D=3D 0xff) > + ) > + { > + return EfiRaw; > + } else { > + return EfiInvalid; > + } > +} > + > +/** > + Reports HOB variable store is available or not. > + > + @retval EFI_NOT_READY HOB variable store info not available. > + @retval EFI_NOT_FOUND HOB variable store is NOT available. > + @retval EFI_SUCCESS HOB variable store is available. > +**/ > +EFI_STATUS > +EFIAPI > +IsHobVariableStoreAvailable ( > + VOID > + ) > +{ > + EFI_HOB_GUID_TYPE *GuidHob; > + VOID *VariableStoreInfoHob; > + > + // > + // Discover if Variable Store Info Hob has been published by platform = driver. > + // It contains information regards to HOB or NV Variable Store availab= ility > + // > + GuidHob =3D GetFirstGuidHob (&gEfiPeiVariableStoreDiscoveredPpiGuid); > + if (GuidHob =3D=3D NULL) { > + return EFI_NOT_READY; > + } > + > + // > + // Check if HOB Variable Store is available > + // > + VariableStoreInfoHob =3D GET_GUID_HOB_DATA (GuidHob); > + if (*(BOOLEAN *)VariableStoreInfoHob =3D=3D TRUE) { [JianJW] What's the scenario in which *(BOOLEAN *)VariableStoreInfoHob equals FALSE? Which case the VariableStoreInfoHob is generated but HOB variable store ava= ilable? Is it possible to simply use VariableStoreDiscoveredPpi notify callback onl= y? Then you can just check HOB(gEfiAuthenticatedVariableGuid) or HOB(gEfiVariableGu= id) to confirm if the HOB version of variable store is available now. > + return EFI_SUCCESS; > + } > + > + // > + // This might be NV Variable Store > + // > + return EFI_NOT_FOUND; > +} > + > +/** > + Get HOB variable store. > + > + @param[out] StoreInfo Return the store info. > + > +**/ > +VOID > +GetHobVariableStore ( > + OUT VARIABLE_STORE_INFO *StoreInfo > + ) > +{ > + EFI_HOB_GUID_TYPE *GuidHob; > + > + // > + // Make sure there is no more than one Variable HOB. > + // > + DEBUG_CODE_BEGIN (); > + GuidHob =3D GetFirstGuidHob (&gEfiAuthenticatedVariableGuid); > + if (GuidHob !=3D NULL) { > + if ((GetNextGuidHob (&gEfiAuthenticatedVariableGuid, GET_NEXT_HOB > (GuidHob)) !=3D NULL)) { > + DEBUG ((DEBUG_ERROR, "ERROR: Found two Auth Variable HOBs\n")); > + ASSERT (FALSE); > + } else if (GetFirstGuidHob (&gEfiVariableGuid) !=3D NULL) { > + DEBUG ((DEBUG_ERROR, "ERROR: Found one Auth + one Normal Variable > HOBs\n")); > + ASSERT (FALSE); > + } > + } else { > + GuidHob =3D GetFirstGuidHob (&gEfiVariableGuid); > + if (GuidHob !=3D NULL) { > + if ((GetNextGuidHob (&gEfiVariableGuid, GET_NEXT_HOB (GuidHob)) != =3D > NULL)) { > + DEBUG ((DEBUG_ERROR, "ERROR: Found two Normal Variable HOBs\n"))= ; > + ASSERT (FALSE); > + } > + } > + } > + > + DEBUG_CODE_END (); > + > + GuidHob =3D GetFirstGuidHob (&gEfiAuthenticatedVariableGuid); > + if (GuidHob !=3D NULL) { > + StoreInfo->VariableStoreHeader =3D (VARIABLE_STORE_HEADER > *)GET_GUID_HOB_DATA (GuidHob); > + StoreInfo->AuthFlag =3D TRUE; > + } else { > + GuidHob =3D GetFirstGuidHob (&gEfiVariableGuid); > + if (GuidHob !=3D NULL) { > + StoreInfo->VariableStoreHeader =3D (VARIABLE_STORE_HEADER > *)GET_GUID_HOB_DATA (GuidHob); > + StoreInfo->AuthFlag =3D FALSE; > + } > + } > +} > + > +/** > + Get NV variable store. > + > + @param[out] StoreInfo Return the store info. > + @param[out] VariableFvHeader Return header of FV containing the s= tore. > + > +**/ > +VOID > +GetNvVariableStore ( > + OUT VARIABLE_STORE_INFO *StoreInfo, > + OUT EFI_FIRMWARE_VOLUME_HEADER **VariableFvHeader > + ) > +{ > + EFI_HOB_GUID_TYPE *GuidHob; > + EFI_FIRMWARE_VOLUME_HEADER *FvHeader; > + VARIABLE_STORE_HEADER *StoreHeader; > + FAULT_TOLERANT_WRITE_LAST_WRITE_DATA *HobData; > + FAULT_TOLERANT_WRITE_LAST_WRITE_DATA *FtwLastWriteData; > + EFI_PHYSICAL_ADDRESS NvStorageBase; > + UINT32 NvStorageSize; > + UINT32 BackUpOffset; > + > + NvStorageSize =3D PcdGet32 (PcdFlashNvStorageVariableSize); > + NvStorageBase =3D (EFI_PHYSICAL_ADDRESS) > + (PcdGet64 (PcdFlashNvStorageVariableBase64) !=3D 0) > + ? PcdGet64 (PcdFlashNvStorageVariableBase64) > + : PcdGet32 (PcdFlashNvStorageVariableBase); > + ASSERT (NvStorageBase !=3D 0); > + > + FvHeader =3D (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)NvStorageBase; > + > + // > + // Check the FTW last write data hob. > + // > + BackUpOffset =3D 0; > + FtwLastWriteData =3D NULL; > + HobData =3D NULL; > + GuidHob =3D GetFirstGuidHob (&gEdkiiFaultTolerantWriteGuid); > + > + if (GuidHob !=3D NULL) { > + HobData =3D (FAULT_TOLERANT_WRITE_LAST_WRITE_DATA > *)GET_GUID_HOB_DATA (GuidHob); > + if (HobData->TargetAddress =3D=3D NvStorageBase) { > + // > + // Let FvHeader point to spare block. > + // > + DEBUG (( > + EFI_D_INFO, > + "PeiVariable: NV storage is backed up in spare block: 0x%x\n", > + (UINTN)HobData->SpareAddress > + )); > + > + FvHeader =3D (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)HobData- > >SpareAddress; > + HobData =3D NULL; > + } else if ((HobData->TargetAddress > NvStorageBase) && > + (HobData->TargetAddress < (NvStorageBase + NvStorageSize)= )) > + { > + // > + // Flash NV storage from the offset is backed up in spare block. > + // > + BackUpOffset =3D (UINT32)(HobData->TargetAddress - NvStorageBase); > + DEBUG (( > + EFI_D_INFO, > + "PeiVariable: High partial NV storage from offset: %x is backed = up in spare > block: 0x%x\n", > + BackUpOffset, > + (UINTN)FtwLastWriteData->SpareAddress > + )); > + // > + // At least one block data in flash NV storage is still valid, so = still > + // leave FvHeader point to NV storage base. > + // > + } > + } > + > + if (StoreInfo !=3D NULL) { > + StoreInfo->FtwLastWriteData =3D HobData; > + } > + > + if (VariableFvHeader !=3D NULL) { > + *VariableFvHeader =3D FvHeader; > + } > + > + // > + // Check if the Firmware Volume is not corrupted > + // > + if ((FvHeader->Signature =3D=3D EFI_FVH_SIGNATURE) && > + CompareGuid (&gEfiSystemNvDataFvGuid, &FvHeader->FileSystemGuid)) [JianJW] It'd be better also validate the FvHeader->HeaderLength, to make s= ure StoreHeader is in the valid area. > + { > + StoreHeader =3D (VARIABLE_STORE_HEADER *)((UINTN)FvHeader + FvHeader= - > >HeaderLength); > + } else { > + StoreHeader =3D NULL; > + DEBUG ((DEBUG_ERROR, "Firmware Volume for Variable Store is > corrupted\n")); > + } > + > + if (StoreInfo !=3D NULL) { > + StoreInfo->VariableStoreHeader =3D StoreHeader; > + if (StoreHeader !=3D NULL) { > + StoreInfo->AuthFlag =3D CompareGuid ( > + &StoreHeader->Signature, > + &gEfiAuthenticatedVariableGuid > + ); > + } > + } > +} > + > +/** > + Return the variable store header and the store info based on the Index= . > + > + @param[in] Type The type of the variable store. > + @param[out] StoreInfo Return the store info. > + > + @return Pointer to the variable store header. > +**/ > +VARIABLE_STORE_HEADER * > +GetVariableStore ( > + IN VARIABLE_STORE_TYPE Type, > + OUT VARIABLE_STORE_INFO *StoreInfo > + ) > +{ > + EFI_HOB_GUID_TYPE *GuidHob; > + > + StoreInfo->VariableStoreHeader =3D NULL; > + StoreInfo->IndexTable =3D NULL; > + StoreInfo->FtwLastWriteData =3D NULL; > + StoreInfo->AuthFlag =3D FALSE; > + switch (Type) { > + case VariableStoreTypeHob: > + GetHobVariableStore (StoreInfo); > + break; > + > + case VariableStoreTypeNv: > + if (!PcdGetBool (PcdEmuVariableNvModeEnable)) { > + // > + // Emulated non-volatile variable mode is not enabled. > + // > + GetNvVariableStore (StoreInfo, NULL); > + if (StoreInfo->VariableStoreHeader !=3D NULL) { > + GuidHob =3D GetFirstGuidHob (&gEfiVariableIndexTableGuid); > + if (GuidHob !=3D NULL) { > + StoreInfo->IndexTable =3D GET_GUID_HOB_DATA (GuidHob); > + } else { > + // > + // If it's the first time to access variable region in flash= , create a guid hob > to record > + // VAR_ADDED type variable info. > + // Note that as the resource of PEI phase is limited, only s= tore the > limited number of > + // VAR_ADDED type variables to reduce access time. > + // > + StoreInfo->IndexTable =3D (VARIABLE_INDEX_TABLE > *)BuildGuidHob (&gEfiVariableIndexTableGuid, sizeof (VARIABLE_INDEX_TABLE= )); > + StoreInfo->IndexTable->Length =3D 0; > + StoreInfo->IndexTable->StartPtr =3D GetStartPointer (Stor= eInfo- > >VariableStoreHeader); > + StoreInfo->IndexTable->EndPtr =3D GetEndPointer (StoreI= nfo- > >VariableStoreHeader); > + StoreInfo->IndexTable->GoneThrough =3D 0; > + } > + } > + } > + > + break; > + > + default: > + ASSERT (FALSE); > + break; > + } > + > + return StoreInfo->VariableStoreHeader; > +} > -- > 2.35.1.windows.2