From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from NAM11-BN8-obe.outbound.protection.outlook.com (NAM11-BN8-obe.outbound.protection.outlook.com [40.107.236.134]) by mx.groups.io with SMTP id smtpd.web11.1545.1593674182231722306 for ; Thu, 02 Jul 2020 00:16:22 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@microsoft.com header.s=selector2 header.b=EFB//LVJ; spf=pass (domain: microsoft.com, ip: 40.107.236.134, mailfrom: bret.barkelew@microsoft.com) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=ocqhEp+gVb1ymU+kHj2wE+IItTEVTeV6DrhqUXItdLxh7bsj1hb2SCEy9IfpLH0x3DJEL0XZOY4/7M3RZ7iEmIMYQ9U1+C1870TWJMFpqz299duTyExel41FGbkmdMKqmaRDlHJ/ItV+NFJq/05ckXhSBHW4srwodC4iijwU7VaUTIjGbkY6ZFAb6+nlnaDkhpXShQYWxY9WTICZDEsZTeRkVE+NlKn1cl1l0Wl0Irlel14bzewSujpnK6Vrqgqqsy4v5U3fd5+bN+jDEnM1MEtaSUev+0470FkD7MVHyyD/D58q+ndW2s6dOlr5q13wie0mp6aQ7UZGJek/qGbi/A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=Qd9b9WT5GVklRDtbuVV2FTJKTyJ+gP1YLFNI17HsC2g=; b=CBBd6M167ka3t7Sz7JPm77ZNsJk6QMPhrxIZ6ysysWzGltGsqClPBZbaN7tBMfMTwB3zKJU3fJ80+/1+rBiosHSGG208atX1ZswnP+52/4TkkzXL9i9uZ7eem9TJXMqfAypc2xOREWrIw1y7yRL9RN4QjCIdvi+ftvm6DxG3242MUSb+uWM8LqyDXMdvpyixcuY355m9JCHpO5iPpo1k2g7GfXvgKvTBEBn8iwZyLEoJ3k7ZlA9XVUOr3ilFVWnSj8R+xT5DIIW5XzcgVFntsjZ1V7ZsjzfUu+Qd8OTNZ9VfdgGCXPSMEqDFOBFEPJ1Otyq6FKuHnzQ9J3fprdA0GA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=microsoft.com; dmarc=pass action=none header.from=microsoft.com; dkim=pass header.d=microsoft.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=Qd9b9WT5GVklRDtbuVV2FTJKTyJ+gP1YLFNI17HsC2g=; b=EFB//LVJCgnSAgDuMpUga3KDnmNhRaIk9cumLxMJvbii7FAnbSupJiTpNPYSktzsEKb0Dtd2xTUCZwo8MjP17UpiIh3/hpFWCj12Ane4QV5otONzyPbKKIDNw52S6cv7LiR6/D8ogWst8tV9cUWCI3oiNB/GUTW5JBkhw/8jVeM= Received: from CY4PR21MB0743.namprd21.prod.outlook.com (2603:10b6:903:b2::9) by CY4PR21MB0773.namprd21.prod.outlook.com (2603:10b6:903:b8::19) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3174.4; Thu, 2 Jul 2020 07:16:13 +0000 Received: from CY4PR21MB0743.namprd21.prod.outlook.com ([fe80::f112:82fb:d4fd:f7dd]) by CY4PR21MB0743.namprd21.prod.outlook.com ([fe80::f112:82fb:d4fd:f7dd%12]) with mapi id 15.20.3174.012; Thu, 2 Jul 2020 07:16:13 +0000 From: "Bret Barkelew" To: "devel@edk2.groups.io" , "dandan.bi@intel.com" , "bret@corthon.com" CC: "Wang, Jian J" , "Wu, Hao A" , liming.gao Subject: Re: [edk2-devel] [PATCH v6 02/14] MdeModulePkg: Define the VariablePolicyLib Thread-Topic: [edk2-devel] [PATCH v6 02/14] MdeModulePkg: Define the VariablePolicyLib Thread-Index: AQHWUBZoKnqVLI210UyrVOLIfp38sKjz4LoN Date: Thu, 2 Jul 2020 07:16:13 +0000 Message-ID: References: <20200623064104.1908-1-brbarkel@microsoft.com> <20200623064104.1908-3-brbarkel@microsoft.com>, In-Reply-To: Accept-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: msip_labels: MSIP_Label_f42aa342-8706-4288-bd11-ebb85995028c_Enabled=True;MSIP_Label_f42aa342-8706-4288-bd11-ebb85995028c_SiteId=72f988bf-86f1-41af-91ab-2d7cd011db47;MSIP_Label_f42aa342-8706-4288-bd11-ebb85995028c_SetDate=2020-07-02T07:14:40.0980358Z;MSIP_Label_f42aa342-8706-4288-bd11-ebb85995028c_ContentBits=0;MSIP_Label_f42aa342-8706-4288-bd11-ebb85995028c_Method=Privileged authentication-results: edk2.groups.io; dkim=none (message not signed) header.d=none;edk2.groups.io; dmarc=none action=none header.from=microsoft.com; x-originating-ip: [174.21.80.75] x-ms-publictraffictype: Email x-ms-office365-filtering-ht: Tenant x-ms-office365-filtering-correlation-id: d3045e6c-1353-4a72-f890-08d81e57cd97 x-ms-traffictypediagnostic: CY4PR21MB0773: x-ld-processed: 72f988bf-86f1-41af-91ab-2d7cd011db47,ExtAddr x-microsoft-antispam-prvs: x-ms-oob-tlc-oobclassifiers: OLM:10000; x-ms-exchange-senderadcheck: 1 x-microsoft-antispam: BCL:0; x-microsoft-antispam-message-info: IAcVT9f++0c/2Pt8mjgRk21H65fPYsKnoz0qC/FihzPI1ttCcd1IpfG99sHOrMkcUO2HHykqognl4x4GP1iY6fWff8k3CLY4fQbEU/YBQiWze8stGBadXA7XTsPcPHGhmygE7Wh8HtbK4CqTOpiDM03sM1c09FJExwPCazSwMuQF2OLt6vAkByptDBS/cfmkTWcOSpxno73OqlONl/6v8rwVRBNVQgyZ5xyERD1rid623PQ5xCVgv0dfWG0M+kg1v7MwKfVajv06+1oMlG8yY0Yt0AZ7dj7xEDJ1/zDPJVpAG0IxVlZyh29C+ofp/QKWRHDuUfr1DEID7su8+itthi1ERYMhPAyxOe8r9lDUMT/iNbGLvXptiJyzZ06hNAQal5XTCLrjkh07djY0fxpW7VQZOqU69KKItxzfHWaffmYlNt/YEkFkNopgWtMK51ip x-forefront-antispam-report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:CY4PR21MB0743.namprd21.prod.outlook.com;PTR:;CAT:NONE;SFTY:;SFS:(4636009)(366004)(136003)(376002)(39860400002)(346002)(396003)(8676002)(2906002)(4326008)(66476007)(64756008)(66946007)(966005)(10290500003)(33656002)(110136005)(316002)(66556008)(76116006)(478600001)(54906003)(66446008)(52536014)(19627235002)(8990500004)(8936002)(9686003)(30864003)(5660300002)(83380400001)(55016002)(166002)(82950400001)(82960400001)(86362001)(26005)(71200400001)(186003)(6506007)(53546011)(7696005)(559001)(569008);DIR:OUT;SFP:1102; x-ms-exchange-antispam-messagedata: 6/HfAaEcrSguTstrRYu3O6lTOi6Y31axSK6NKXL4s+ZhJhe2L4Nj9qG5DWRImcEoG/GxTe1olMa+O4Z8aRpn44tX0aSHw8a6+cFrAqx4ftRlTPY33On36Enu2TqkDeBDf9wNwai6nVdpmFYUHWQiJe3cJJpOO1Y6ZiXojGi7aI5T0sxx8/MTDj0uSANiDEBFDfHz2iO1C2e4uke6P/yM3X62iDTSjbN4Tmf2gD2FyhkTLF8YODM28PG3H9mKIrCVA0D7dVCacUnpvu1mPosv71Ia9QNYh68KN4XekbGaYJbbAyDMWuaWBYoVfFYUzu2mGrgSVeStpHkMqtqS+tFpJwt5voWis2MY2/CEKv01iRJfUkmcTPcMHUImQf0gHEC5M3p267tvjtVqFotxq+29E/CKKOmp/HpMNX6D65ChQZmL9YmAcm/se0nYssPaEwQM1tu8kDDsPrmIl8mkd/K4vZMqBAamJdHRE8sV2jW4YXA= x-ms-exchange-transport-forked: True MIME-Version: 1.0 X-OriginatorOrg: microsoft.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-AuthSource: CY4PR21MB0743.namprd21.prod.outlook.com X-MS-Exchange-CrossTenant-Network-Message-Id: d3045e6c-1353-4a72-f890-08d81e57cd97 X-MS-Exchange-CrossTenant-originalarrivaltime: 02 Jul 2020 07:16:13.1562 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 72f988bf-86f1-41af-91ab-2d7cd011db47 X-MS-Exchange-CrossTenant-mailboxtype: HOSTED X-MS-Exchange-CrossTenant-userprincipalname: TUmFFBpwlvCbEVUC4Fkv+t93pOkJYOu3czRmUPge2QRTWWsbYChy14b8NI2mIHP+DkMKBrXJNE/f7Dq5HqWfjQ== X-MS-Exchange-Transport-CrossTenantHeadersStamped: CY4PR21MB0773 Content-Language: en-US Content-Type: multipart/alternative; boundary="_000_CY4PR21MB074399EFFD54FE103EF7B5B8EF6D0CY4PR21MB0743namp_" --_000_CY4PR21MB074399EFFD54FE103EF7B5B8EF6D0CY4PR21MB0743namp_ Content-Type: text/plain; charset="Windows-1252" Content-Transfer-Encoding: quoted-printable 1. Done 2. Done 3. BestResult can=92t be anything but NULL if MatchPriority isn=92t ini= tialized, so the second half of this will never be evaluated, but I see you= r point. I=92ve added a default initialization for the variable. 4. Done Thanks! - Bret From: Dandan Bi via groups.io Sent: Wednesday, July 1, 2020 7:13 PM To: devel@edk2.groups.io; bret@corthon.com Cc: Wang, Jian J; Wu, Hao A; liming.gao Subject: [EXTERNAL] Re: [edk2-devel] [PATCH v6 02/14] MdeModulePkg: Define= the VariablePolicyLib 4 comments inline, please check. Thanks, Dandan > -----Original Message----- > From: devel@edk2.groups.io On Behalf Of Bret > Barkelew > Sent: Tuesday, June 23, 2020 2:41 PM > To: devel@edk2.groups.io > Cc: Wang, Jian J ; Wu, Hao A = ; > Gao, Liming > Subject: [edk2-devel] [PATCH v6 02/14] MdeModulePkg: Define the > VariablePolicyLib > > https://nam06.safelinks.protection.outlook.com/?url=3Dhttps%3A%2F%2Fbugz= illa.tianocore.org%2Fshow_bug.cgi%3Fid%3D2522&data=3D02%7C01%7Cbret.bar= kelew%40microsoft.com%7C4ff781c598384282187708d81e2d8858%7C72f988bf86f141af= 91ab2d7cd011db47%7C1%7C0%7C637292528218882209&sdata=3Dcw75EiZAUXPo9iwbb= kXrZwoLpuv1F7rHZIiDDHSToDA%3D&reserved=3D0 > > VariablePolicy is an updated interface to > replace VarLock and VarCheckProtocol. > > Add the VariablePolicyLib library that implements > the portable business logic for the VariablePolicy > engine. > > Also add host-based CI test cases for the lib. > > Cc: Jian J Wang > Cc: Hao A Wu > Cc: Liming Gao > Cc: Bret Barkelew > Signed-off-by: Bret Barkelew > --- > MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitNull.c > | 46 + > > MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitRuntimeDx > e.c | 85 + > MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c > | 816 +++++++ > > MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePo > licyUnitTest.c | 2436 ++++++++++++++++++++ > MdeModulePkg/Include/Library/VariablePolicyLib.h = | > 207 ++ > MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf > | 44 + > MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.uni > | 12 + > MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf > | 51 + > > MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePo > licyUnitTest.inf | 40 + > MdeModulePkg/MdeModulePkg.dec = | 3 + > MdeModulePkg/MdeModulePkg.dsc = | 5 + > MdeModulePkg/Test/MdeModulePkgHostTest.dsc = | > 11 + > 12 files changed, 3756 insertions(+) > > diff --git > a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitNull.c > b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitNull.c > new file mode 100644 > index 000000000000..ad2ee0b2fb8f > --- /dev/null > +++ > b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitNull.c > @@ -0,0 +1,46 @@ > +/** @file -- VariablePolicyExtraInitNull.c > > +This file contains extra init and deinit routines that don't do anythin= g > > +extra. > > + > > +Copyright (c) Microsoft Corporation. > > +SPDX-License-Identifier: BSD-2-Clause-Patent > > + > > +**/ > > + > > +#include > > + > > + > > +/** > > + An extra init hook that enables the RuntimeDxe library instance to > > + register VirtualAddress change callbacks. Among other things. > > + > > + @retval EFI_SUCCESS Everything is good. Continue with init. > > + @retval Others Uh... don't continue. > > + > > +**/ > > +EFI_STATUS > > +VariablePolicyExtraInit ( > > + VOID > > + ) > > +{ > > + // NULL implementation. > > + return EFI_SUCCESS; > > +} > > + > > + > > +/** > > + An extra deinit hook that enables the RuntimeDxe library instance to > > + register VirtualAddress change callbacks. Among other things. > > + > > + @retval EFI_SUCCESS Everything is good. Continue with deinit. > > + @retval Others Uh... don't continue. > > + > > +**/ > > +EFI_STATUS > > +VariablePolicyExtraDeinit ( > > + VOID > > + ) > > +{ > > + // NULL implementation. > > + return EFI_SUCCESS; > > +} > > diff --git > a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitRuntimeD > xe.c > b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitRuntime > Dxe.c > new file mode 100644 > index 000000000000..3ca87048b14b > --- /dev/null > +++ > b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitRuntime > Dxe.c > @@ -0,0 +1,85 @@ > +/** @file -- VariablePolicyExtraInitRuntimeDxe.c > > +This file contains extra init and deinit routines that register and unr= egister > > +VariableAddressChange callbacks. > > + > > +Copyright (c) Microsoft Corporation. > > +SPDX-License-Identifier: BSD-2-Clause-Patent > > + > > +**/ > > + > > +#include > > +#include > > + > > +extern EFI_GET_VARIABLE mGetVariableHelper; > > +extern UINT8 *mPolicyTable; > > +STATIC BOOLEAN mIsVirtualAddrConverted; > > +STATIC EFI_EVENT mVariablePolicyLibVirtualAddressChangeEvent = = =3D > NULL; > > + > > +/** > > + For the RuntimeDxe version of this lib, convert internal pointer addr= esses > to virtual addresses. > > + > > + @param[in] Event Event whose notification function is being invo= ked. > > + @param[in] Context The pointer to the notification function's cont= ext, > which > > + is implementation-dependent. > > +**/ > > +STATIC > > +VOID > > +EFIAPI > > +VariablePolicyLibVirtualAddressCallback ( > > + IN EFI_EVENT Event, > > + IN VOID *Context > > + ) > > +{ > > + gRT->ConvertPointer (0, (VOID **)&mPolicyTable); > > + gRT->ConvertPointer (0, (VOID **)&mGetVariableHelper); > > + mIsVirtualAddrConverted =3D TRUE; > > +} > > + > > + > > +/** > > + An extra init hook that enables the RuntimeDxe library instance to > > + register VirtualAddress change callbacks. Among other things. > > + > > + @retval EFI_SUCCESS Everything is good. Continue with init. > > + @retval Others Uh... don't continue. > > + > > +**/ > > +EFI_STATUS > > +VariablePolicyExtraInit ( > > + VOID > > + ) > > +{ > > + return gBS->CreateEventEx (EVT_NOTIFY_SIGNAL, > > + TPL_NOTIFY, > > + VariablePolicyLibVirtualAddressCallback, > > + NULL, > > + &gEfiEventVirtualAddressChangeGuid, > > + &mVariablePolicyLibVirtualAddressChangeEv= ent); > > +} > > + > > + > > +/** > > + An extra deinit hook that enables the RuntimeDxe library instance to > > + register VirtualAddress change callbacks. Among other things. > > + > > + @retval EFI_SUCCESS Everything is good. Continue with deinit. > > + @retval Others Uh... don't continue. > > + > > +**/ > > +EFI_STATUS > > +VariablePolicyExtraDeinit ( > > + VOID > > + ) > > +{ > > + EFI_STATUS Status; > > + > > + Status =3D EFI_SUCCESS; > > + if (mIsVirtualAddrConverted) { > > + Status =3D gBS->CloseEvent > (mVariablePolicyLibVirtualAddressChangeEvent); > > + } > > + else { > > + Status =3D EFI_SUCCESS; > > + } > > + > > + return Status; > > +} > > diff --git a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c > b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c > new file mode 100644 > index 000000000000..84c794adaed9 > --- /dev/null > +++ b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c > @@ -0,0 +1,816 @@ > +/** @file -- VariablePolicyLib.c > > +Business logic for Variable Policy enforcement. > > + > > +Copyright (c) Microsoft Corporation. > > +SPDX-License-Identifier: BSD-2-Clause-Patent > > + > > +**/ > > + > > +#include > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +#include > > +#include > > + > > + > > +// IMPORTANT NOTE: This library is currently rife with multiple return > statements > > +// for error handling. A refactor should remove these a= t some point. > > + > > +// > > +// This library was designed with advanced unit-test features. > > +// This define handles the configuration. > > +#ifdef INTERNAL_UNIT_TEST > > +#undef STATIC > > +#define STATIC // Nothing... > > +#endif > > + > > +// An abstracted GetVariable interface that enables configuration > regardless of the environment. > > +EFI_GET_VARIABLE mGetVariableHelper =3D NULL; > > + > > +// Master switch to lock this entire interface. Does not stop enforceme= nt, > > +// just prevents the configuration from being changed for the rest of t= he > boot. > > +STATIC BOOLEAN mInterfaceLocked =3D FALSE; > > + > > +// Master switch to disable the entire interface for a single boot. > > +// This will disable all policy enforcement for the duration of the boo= t. > > +STATIC BOOLEAN mProtectionDisabled =3D FALSE; > > + > > +// Table to hold all the current policies. > > +UINT8 *mPolicyTable =3D NULL; > > +STATIC UINT32 mCurrentTableSize =3D 0; > > +STATIC UINT32 mCurrentTableUsage =3D 0; > > +STATIC UINT32 mCurrentTableCount =3D 0; > > + > > +#define POLICY_TABLE_STEP_SIZE 0x1000 > > + > > +// NOTE: DO NOT USE THESE MACROS on any structure that has not been > validated. > > +// Current table data has already been sanitized. > > +#define GET_NEXT_POLICY(CurPolicy) > (VARIABLE_POLICY_ENTRY*)((UINT8*)CurPolicy + CurPolicy->Size) > > +#define GET_POLICY_NAME(CurPolicy) (CHAR16*)((UINTN)CurPolicy + > CurPolicy->OffsetToName) > > + > > +#define MATCH_PRIORITY_EXACT 0 > > +#define MATCH_PRIORITY_MAX MATCH_PRIORITY_EXACT > > +#define MATCH_PRIORITY_MIN MAX_UINT8 > > + > > +// ExtraInit/ExtraDeinit functions allow RuntimeDxe to register > VirtualAddress callbacks. > > +EFI_STATUS > > +VariablePolicyExtraInit ( > > + VOID > > + ); > > + > > +EFI_STATUS > > +VariablePolicyExtraDeinit ( > > + VOID > > + ); 1. [Dandan]: Please also add comments for above two functions. Please also pay attention to the coding style issue in other files. > > + > > + > > +/** > > + This helper function determines whether the structure of an incoming > policy > > + is valid and internally consistent. > > + > > + @param[in] NewPolicy Pointer to the incoming policy structure. > > + > > + @retval TRUE > > + @retval FALSE Pointer is NULL, size is wrong, strings are empty= , or > > + substructures overlap. > > + > > +**/ > > +STATIC > > +BOOLEAN > > +IsValidVariablePolicyStructure ( > > + IN CONST VARIABLE_POLICY_ENTRY *NewPolicy > > + ) > > +{ > > + EFI_STATUS Status; > > + UINTN EntryEnd; > > + CHAR16 *CheckChar; > > + UINTN WildcardCount; > > + > > + // Sanitize some quick values. > > + if (NewPolicy =3D=3D NULL || NewPolicy->Size =3D=3D 0 || > > + // Structure size should be at least as long as the minumum struc= ture and > a NULL string. > > + NewPolicy->Size < sizeof(VARIABLE_POLICY_ENTRY) || > > + // Check for the known revision. > > + NewPolicy->Version !=3D VARIABLE_POLICY_ENTRY_REVISION) { > > + return FALSE; > > + } > > + > > + // Calculate the theoretical end of the structure and make sure > > + // that the structure can fit in memory. > > + Status =3D SafeUintnAdd( (UINTN)NewPolicy, NewPolicy->Size, &EntryEnd= ); > > + if (EFI_ERROR( Status )) { > > + return FALSE; > > + } > > + > > + // Check for a valid Max Size. > > + if (NewPolicy->MaxSize =3D=3D 0) { > > + return FALSE; > > + } > > + > > + // Check for the valid list of lock policies. > > + if (NewPolicy->LockPolicyType !=3D VARIABLE_POLICY_TYPE_NO_LOCK && > > + NewPolicy->LockPolicyType !=3D VARIABLE_POLICY_TYPE_LOCK_NOW && > > + NewPolicy->LockPolicyType !=3D > VARIABLE_POLICY_TYPE_LOCK_ON_CREATE && > > + NewPolicy->LockPolicyType !=3D > VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE) > > + { > > + return FALSE; > > + } > > + > > + // If the policy type is VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE, > make sure that the matching state variable Name > > + // terminates before the OffsetToName for the matching policy variabl= e > Name. > > + if (NewPolicy->LockPolicyType =3D=3D > VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE) { > > + // Adjust CheckChar to the offset of the LockPolicy->Name. > > + Status =3D SafeUintnAdd( (UINTN)NewPolicy + > sizeof(VARIABLE_POLICY_ENTRY), > > + sizeof(VARIABLE_LOCK_ON_VAR_STATE_POLICY), > > + (UINTN*)&CheckChar ); > > + if (EFI_ERROR( Status ) || EntryEnd <=3D (UINTN)CheckChar) { > > + return FALSE; > > + } > > + while (*CheckChar !=3D CHAR_NULL) { > > + if (EntryEnd <=3D (UINTN)CheckChar) { > > + return FALSE; > > + } > > + CheckChar++; > > + } > > + // At this point we should have either exeeded the structure or be > pointing at the last char in LockPolicy->Name. > > + // We should check to make sure that the policy Name comes > immediately after this charcter. > > + if ((UINTN)++CheckChar !=3D (UINTN)NewPolicy + NewPolicy- > >OffsetToName) { > > + return FALSE; > > + } > > + } > > + // If the policy type is any other value, make sure that the LockPoli= cy > structure has a zero length. > > + else { > > + if (NewPolicy->OffsetToName !=3D sizeof(VARIABLE_POLICY_ENTRY)) { > > + return FALSE; > > + } > > + } > > + > > + // Check to make sure that the name has a terminating character > > + // before the end of the structure. > > + // We've already checked that the name is within the bounds of the > structure. > > + if (NewPolicy->Size !=3D NewPolicy->OffsetToName) { > > + CheckChar =3D (CHAR16*)((UINTN)NewPolicy + NewPolicy- > >OffsetToName); > > + WildcardCount =3D 0; > > + while (*CheckChar !=3D CHAR_NULL) { > > + // Make sure there aren't excessive wildcards. > > + if (*CheckChar =3D=3D '#') { > > + WildcardCount++; > > + if (WildcardCount > MATCH_PRIORITY_MIN) { > > + return FALSE; > > + } > > + } > > + // Make sure you're still within the bounds of the policy structu= re. > > + if (EntryEnd <=3D (UINTN)CheckChar) { > > + return FALSE; > > + } > > + CheckChar++; > > + } > > + > > + // Finally, we should be pointed at the very last character in Name= , so we > should be right > > + // up against the end of the structure. > > + if ((UINTN)++CheckChar !=3D EntryEnd) { > > + return FALSE; > > + } > > + } > > + > > + return TRUE; > > +} > > + > > + > > +/** > > + This helper function evaluates a policy and determines whether it mat= ches > the target > > + variable. If matched, will also return a value corresponding to the p= riority > of the match. > > + > > + The rules for "best match" are listed in the Variable Policy Spec. > > + Perfect name matches will return 0. > > + Single wildcard characters will return the number of wildcard charact= ers. > > + Full namespaces will return MAX_UINT8. > > + > > + @param[in] EvalEntry Pointer to the policy entry being evalu= ated. > > + @param[in] VariableName Same as EFI_SET_VARIABLE. > > + @param[in] VendorGuid Same as EFI_SET_VARIABLE. > > + @param[out] MatchPriority [Optional] On finding a match, this val= ue > contains the priority of the match. > > + Lower number =3D=3D higher priority. On= ly valid if a match found. > > + > > + @retval TRUE Current entry matches the target variable. > > + @retval FALSE Current entry does not match at all. > > + > > +**/ > > +STATIC > > +BOOLEAN > > +EvaluatePolicyMatch ( > > + IN CONST VARIABLE_POLICY_ENTRY *EvalEntry, > > + IN CONST CHAR16 *VariableName, > > + IN CONST EFI_GUID *VendorGuid, > > + OUT UINT8 *MatchPriority OPTIONAL > > + ) > > +{ > > + BOOLEAN Result; > > + CHAR16 *PolicyName; > > + UINT8 CalculatedPriority; > > + UINTN Index; > > + > > + Result =3D FALSE; > > + CalculatedPriority =3D MATCH_PRIORITY_EXACT; > > + > > + // Step 1: If the GUID doesn't match, we're done. No need to evaluate > anything else. > > + if (!CompareGuid( &EvalEntry->Namespace, VendorGuid )) { > > + goto Exit; > > + } > > + > > + // If the GUID matches, check to see whether there is a Name associat= ed > > + // with the policy. If not, this policy matches the entire namespace. > > + // Missing Name is indicated by size being equal to name. > > + if (EvalEntry->Size =3D=3D EvalEntry->OffsetToName) { > > + CalculatedPriority =3D MATCH_PRIORITY_MIN; > > + Result =3D TRUE; > > + goto Exit; > > + } > > + > > + // Now that we know the name exists, get it. > > + PolicyName =3D GET_POLICY_NAME( EvalEntry ); > > + > > + // Evaluate the name against the policy name and check for a match. > > + // Account for any wildcards. > > + Index =3D 0; > > + Result =3D TRUE; > > + // Keep going until the end of both strings. > > + while (PolicyName[Index] !=3D CHAR_NULL || VariableName[Index] !=3D > CHAR_NULL) { > > + // If we don't have a match... > > + if (PolicyName[Index] !=3D VariableName[Index] || PolicyName[Index]= =3D=3D > '#') { > > + // If this is a numerical wildcard, we can consider > > + // it a match if we alter the priority. > > + if (PolicyName[Index] =3D=3D L'#' && > > + (L'0' <=3D VariableName[Index] && VariableName[Index] <=3D L'= 9')) { > > + if (CalculatedPriority < MATCH_PRIORITY_MIN) { > > + CalculatedPriority++; > > + } > > + } > > + // Otherwise, not a match. > > + else { 2. [Dandan]: About the coding style, could we make the" } " and "else {" a= t the same line? Which is aligned with current edk2 style. > > + Result =3D FALSE; > > + goto Exit; > > + } > > + } > > + Index++; > > + } > > + > > +Exit: > > + if (Result && MatchPriority !=3D NULL) { > > + *MatchPriority =3D CalculatedPriority; > > + } > > + return Result; > > +} > > + > > + > > +/** > > + This helper function walks the current policy table and returns a poi= nter > > + to the best match, if any are found. Leverages EvaluatePolicyMatch() = to > > + determine "best". > > + > > + @param[in] VariableName Same as EFI_SET_VARIABLE. > > + @param[in] VendorGuid Same as EFI_SET_VARIABLE. > > + @param[out] ReturnPriority [Optional] If pointer is provided, ret= urn the > > + priority of the match. Same as Evaluat= ePolicyMatch(). > > + Only valid if a match is returned. > > + > > + @retval VARIABLE_POLICY_ENTRY* Best match that was found. > > + @retval NULL No match was found. > > + > > +**/ > > +STATIC > > +VARIABLE_POLICY_ENTRY* > > +GetBestPolicyMatch ( > > + IN CONST CHAR16 *VariableName, > > + IN CONST EFI_GUID *VendorGuid, > > + OUT UINT8 *ReturnPriority OPTIONAL > > + ) > > +{ > > + VARIABLE_POLICY_ENTRY *BestResult; > > + VARIABLE_POLICY_ENTRY *CurrentEntry; > > + UINT8 MatchPriority; > > + UINT8 CurrentPriority; > > + UINTN Index; > > + > > + BestResult =3D NULL; > > + > > + // Walk all entries in the table, looking for matches. > > + CurrentEntry =3D (VARIABLE_POLICY_ENTRY*)mPolicyTable; > > + for (Index =3D 0; Index < mCurrentTableCount; Index++) { > > + // Check for a match. > > + if (EvaluatePolicyMatch( CurrentEntry, VariableName, VendorGuid, > &CurrentPriority )) { > > + // If match is better, take it. > > + if (BestResult =3D=3D NULL || CurrentPriority < MatchPriority) { 3. [Dandan]: MatchPriority seems not be initialized but used here. > > + BestResult =3D CurrentEntry; > > + MatchPriority =3D CurrentPriority; > > + } > > + > > + // If you've hit the highest-priority match, can exit now. > > + if (MatchPriority =3D=3D 0) { > > + break; > > + } > > + } > > + > > + // If we're still in the loop, move to the next entry. > > + CurrentEntry =3D GET_NEXT_POLICY( CurrentEntry ); > > + } > > + > > + // If a return priority was requested, return it. > > + if (ReturnPriority !=3D NULL) { > > + *ReturnPriority =3D MatchPriority; > > + } > > + > > + return BestResult; > > +} > > + > > + > > +/** > > + This API function validates and registers a new policy with > > + the policy enforcement engine. > > + > > + @param[in] NewPolicy Pointer to the incoming policy structure. > > + > > + @retval EFI_SUCCESS > > + @retval EFI_INVALID_PARAMETER NewPolicy is NULL or is internall= y > inconsistent. > > + @retval EFI_ALREADY_STARTED An identical matching policy alre= ady > exists. > > + @retval EFI_WRITE_PROTECTED The interface has been locked unt= il > the next reboot. > > + @retval EFI_UNSUPPORTED Policy enforcement has been disab= led. > No reason to add more policies. > > + @retval EFI_ABORTED A calculation error has prevented= this > function from completing. > > + @retval EFI_OUT_OF_RESOURCES Cannot grow the table to hold any > more policies. > > + @retval EFI_NOT_READY Library has not yet been initiali= zed. > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +RegisterVariablePolicy ( > > + IN CONST VARIABLE_POLICY_ENTRY *NewPolicy > > + ) > > +{ > > + EFI_STATUS Status; > > + VARIABLE_POLICY_ENTRY *MatchPolicy; > > + UINT8 MatchPriority; > > + UINT32 NewSize; > > + UINT8 *NewTable; > > + > > + if (!IsVariablePolicyLibInitialized()) { > > + return EFI_NOT_READY; > > + } > > + if (mInterfaceLocked) { > > + return EFI_WRITE_PROTECTED; > > + } > > + > > + if (!IsValidVariablePolicyStructure( NewPolicy )) { > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + // Check to see whether an exact matching policy already exists. > > + MatchPolicy =3D GetBestPolicyMatch( GET_POLICY_NAME( NewPolicy ), > > + &NewPolicy->Namespace, > > + &MatchPriority ); > > + if (MatchPolicy !=3D NULL && MatchPriority =3D=3D MATCH_PRIORITY_EXAC= T) { > > + return EFI_ALREADY_STARTED; > > + } > > + > > + // If none exists, create it. > > + // If we need more space, allocate that now. > > + Status =3D SafeUint32Add( mCurrentTableUsage, NewPolicy->Size, > &NewSize ); > > + if (EFI_ERROR( Status )) { > > + return EFI_ABORTED; > > + } > > + if (NewSize > mCurrentTableSize) { > > + // Use NewSize to calculate the new table size in units of > POLICY_TABLE_STEP_SIZE. > > + NewSize =3D (NewSize % POLICY_TABLE_STEP_SIZE) > 0 ? > > + (NewSize / POLICY_TABLE_STEP_SIZE) + 1 : > > + (NewSize / POLICY_TABLE_STEP_SIZE); > > + // Calculate the new table size in absolute bytes. > > + Status =3D SafeUint32Mult( NewSize, POLICY_TABLE_STEP_SIZE, > &NewSize ); > > + if (EFI_ERROR( Status )) { > > + return EFI_ABORTED; > > + } > > + > > + // Reallocate and copy the table. > > + NewTable =3D AllocatePool( NewSize ); > > + if (NewTable =3D=3D NULL) { > > + return EFI_OUT_OF_RESOURCES; > > + } > > + CopyMem( NewTable, mPolicyTable, mCurrentTableUsage ); > > + mCurrentTableSize =3D NewSize; > > + if (mPolicyTable !=3D NULL) { > > + FreePool( mPolicyTable ); > > + } > > + mPolicyTable =3D NewTable; > > + } > > + // Copy the policy into the table. > > + CopyMem( mPolicyTable + mCurrentTableUsage, NewPolicy, NewPolicy- > >Size ); > > + mCurrentTableUsage +=3D NewPolicy->Size; > > + mCurrentTableCount +=3D 1; > > + > > + // We're done here. > > + > > + return EFI_SUCCESS; > > +} > > + > > + > > +/** > > + This API function checks to see whether the parameters to SetVariable > would > > + be allowed according to the current variable policies. > > + > > + @param[in] VariableName Same as EFI_SET_VARIABLE. > > + @param[in] VendorGuid Same as EFI_SET_VARIABLE. > > + @param[in] Attributes Same as EFI_SET_VARIABLE. > > + @param[in] DataSize Same as EFI_SET_VARIABLE. > > + @param[in] Data Same as EFI_SET_VARIABLE. > > + > > + @retval EFI_SUCCESS A matching policy allows this upd= ate. > > + @retval EFI_SUCCESS There are currently no policies t= hat restrict > this update. > > + @retval EFI_SUCCESS The protections have been disable= until the > next reboot. > > + @retval EFI_WRITE_PROTECTED Variable is currently locked. > > + @retval EFI_INVALID_PARAMETER Attributes or size are invalid. > > + @retval EFI_ABORTED A lock policy exists, but an erro= r prevented > evaluation. > > + @retval EFI_NOT_READY Library has not been initialized. > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +ValidateSetVariable ( > > + IN CHAR16 *VariableName, > > + IN EFI_GUID *VendorGuid, > > + IN UINT32 Attributes, > > + IN UINTN DataSize, > > + IN VOID *Data > > + ) > > +{ > > + BOOLEAN IsDel; > > + VARIABLE_POLICY_ENTRY *ActivePolicy; > > + EFI_STATUS Status; > > + EFI_STATUS ReturnStatus; > > + VARIABLE_LOCK_ON_VAR_STATE_POLICY *StateVarPolicy; > > + CHAR16 *StateVarName; > > + UINTN StateVarSize; > > + UINT8 StateVar; > > + > > + ReturnStatus =3D EFI_SUCCESS; > > + > > + if (!IsVariablePolicyLibInitialized()) { > > + ReturnStatus =3D EFI_NOT_READY; > > + goto Exit; > > + } > > + > > + // Bail if the protections are currently disabled. > > + if (mProtectionDisabled) { > > + ReturnStatus =3D EFI_SUCCESS; > > + goto Exit; > > + } > > + > > + // Determine whether this is a delete operation. > > + // If so, it will affect which tests are applied. > > + if ((DataSize =3D=3D 0) && ((Attributes & EFI_VARIABLE_APPEND_WRITE) = = =3D=3D 0)) > { > > + IsDel =3D TRUE; > > + } > > + else { > > + IsDel =3D FALSE; > > + } > > + > > + // Find an active policy if one exists. > > + ActivePolicy =3D GetBestPolicyMatch( VariableName, VendorGuid, NULL )= ; > > + > > + // If we have an active policy, check it against the incoming data. > > + if (ActivePolicy !=3D NULL) { > > + // > > + // Only enforce size and attribute constraints when updating data, = not > deleting. > > + if (!IsDel) { > > + // Check for size constraints. > > + if ((ActivePolicy->MinSize > 0 && DataSize < ActivePolicy->MinSiz= e) || > > + (ActivePolicy->MaxSize > 0 && DataSize > ActivePolicy->MaxSiz= e)) { > > + ReturnStatus =3D EFI_INVALID_PARAMETER; > > + DEBUG(( DEBUG_VERBOSE, "%a - Bad Size. 0x%X <> 0x%X-0x%X\n", > __FUNCTION__, > > + DataSize, ActivePolicy->MinSize, ActivePolicy->MaxSize = )); > > + goto Exit; > > + } > > + > > + // Check for attribute constraints. > > + if ((ActivePolicy->AttributesMustHave & Attributes) !=3D ActivePo= licy- > >AttributesMustHave || > > + (ActivePolicy->AttributesCantHave & Attributes) !=3D 0) { > > + ReturnStatus =3D EFI_INVALID_PARAMETER; > > + DEBUG(( DEBUG_VERBOSE, "%a - Bad Attributes. 0x%X <> > 0x%X:0x%X\n", __FUNCTION__, > > + Attributes, ActivePolicy->AttributesMustHave, ActivePol= icy- > >AttributesCantHave )); > > + goto Exit; > > + } > > + } > > + > > + // > > + // Lock policy check. > > + // > > + // Check for immediate lock. > > + if (ActivePolicy->LockPolicyType =3D=3D VARIABLE_POLICY_TYPE_LOCK_N= OW) > { > > + ReturnStatus =3D EFI_WRITE_PROTECTED; > > + goto Exit; > > + } > > + // Check for lock on create. > > + else if (ActivePolicy->LockPolicyType =3D=3D > VARIABLE_POLICY_TYPE_LOCK_ON_CREATE) { > > + StateVarSize =3D 0; > > + Status =3D mGetVariableHelper( VariableName, > > + VendorGuid, > > + NULL, > > + &StateVarSize, > > + NULL ); > > + if (Status =3D=3D EFI_BUFFER_TOO_SMALL) { > > + ReturnStatus =3D EFI_WRITE_PROTECTED; > > + goto Exit; > > + } > > + } > > + // Check for lock on state variable. > > + else if (ActivePolicy->LockPolicyType =3D=3D > VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE) { > > + StateVarPolicy =3D > (VARIABLE_LOCK_ON_VAR_STATE_POLICY*)((UINT8*)ActivePolicy + > sizeof(VARIABLE_POLICY_ENTRY)); > > + StateVarName =3D (CHAR16*)((UINT8*)StateVarPolicy + > sizeof(VARIABLE_LOCK_ON_VAR_STATE_POLICY)); > > + StateVarSize =3D sizeof(StateVar); > > + Status =3D mGetVariableHelper( StateVarName, > > + &StateVarPolicy->Namespace, > > + NULL, > > + &StateVarSize, > > + &StateVar ); > > + > > + // If the variable was found, check the state. If matched, this v= ariable is > locked. > > + if (!EFI_ERROR( Status )) { > > + if (StateVar =3D=3D StateVarPolicy->Value) { > > + ReturnStatus =3D EFI_WRITE_PROTECTED; > > + goto Exit; > > + } > > + } > > + // EFI_NOT_FOUND and EFI_BUFFER_TOO_SMALL indicate that the > state doesn't match. > > + else if (Status !=3D EFI_NOT_FOUND && Status !=3D > EFI_BUFFER_TOO_SMALL) { > > + // We don't know what happened, but it isn't good. > > + ReturnStatus =3D EFI_ABORTED; > > + goto Exit; > > + } > > + } > > + } > > + > > +Exit: > > + DEBUG(( DEBUG_VERBOSE, "%a - Variable (%g:%s) returning %r.\n", > __FUNCTION__, VendorGuid, VariableName, ReturnStatus )); > > + return ReturnStatus; > > +} > > + > > + > > +/** > > + This API function disables the variable policy enforcement. If it's > > + already been called once, will return EFI_ALREADY_STARTED. > > + > > + @retval EFI_SUCCESS > > + @retval EFI_ALREADY_STARTED Has already been called once this b= oot. > > + @retval EFI_WRITE_PROTECTED Interface has been locked until reb= oot. > > + @retval EFI_WRITE_PROTECTED Interface option is disabled by pla= tform > PCD. > > + @retval EFI_NOT_READY Library has not yet been initialize= d. > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +DisableVariablePolicy ( > > + VOID > > + ) > > +{ > > + if (!IsVariablePolicyLibInitialized()) { > > + return EFI_NOT_READY; > > + } > > + if (mProtectionDisabled) { > > + return EFI_ALREADY_STARTED; > > + } > > + if (mInterfaceLocked) { > > + return EFI_WRITE_PROTECTED; > > + } > > + if (!PcdGetBool (PcdAllowVariablePolicyEnforcementDisable)) { > > + return EFI_WRITE_PROTECTED; > > + } > > + mProtectionDisabled =3D TRUE; > > + return EFI_SUCCESS; > > +} > > + > > + > > +/** > > + This API function will dump the entire contents of the variable polic= y table. > > + > > + Similar to GetVariable, the first call can be made with a 0 size and = it will > return > > + the size of the buffer required to hold the entire table. > > + > > + @param[out] Policy Pointer to the policy buffer. Can be NULL if = Size is 0. > > + @param[in,out] Size On input, the size of the output buffer. On o= utput, > the size > > + of the data returned. > > + > > + @retval EFI_SUCCESS Policy data is in the output buff= er and Size > has been updated. > > + @retval EFI_INVALID_PARAMETER Size is NULL, or Size is non-zero= and > Policy is NULL. > > + @retval EFI_BUFFER_TOO_SMALL Size is insufficient to hold poli= cy. Size > updated with required size. > > + @retval EFI_NOT_READY Library has not yet been initiali= zed. > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +DumpVariablePolicy ( > > + OUT UINT8 *Policy, > > + IN OUT UINT32 *Size > > + ) > > +{ > > + if (!IsVariablePolicyLibInitialized()) { > > + return EFI_NOT_READY; > > + } > > + > > + // Check the parameters. > > + if (Size =3D=3D NULL || (*Size > 0 && Policy =3D=3D NULL)) { > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + // Make sure the size is sufficient to hold the policy table. > > + if (*Size < mCurrentTableUsage) { > > + *Size =3D mCurrentTableUsage; > > + return EFI_BUFFER_TOO_SMALL; > > + } > > + > > + // If we're still here, copy the table and bounce. > > + CopyMem( Policy, mPolicyTable, mCurrentTableUsage ); > > + *Size =3D mCurrentTableUsage; > > + > > + return EFI_SUCCESS; > > +} > > + > > + > > +/** > > + This API function returns whether or not the policy engine is > > + currently being enforced. > > + > > + @retval TRUE > > + @retval FALSE > > + @retval FALSE Library has not yet been initialized. > > + > > +**/ > > +BOOLEAN > > +EFIAPI > > +IsVariablePolicyEnabled ( > > + VOID > > + ) > > +{ > > + if (!IsVariablePolicyLibInitialized()) { > > + return FALSE; > > + } > > + return !mProtectionDisabled; > > +} > > + > > + > > +/** > > + This API function locks the interface so that no more policy updates > > + can be performed or changes made to the enforcement until the next > boot. > > + > > + @retval EFI_SUCCESS > > + @retval EFI_NOT_READY Library has not yet been initialized. > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +LockVariablePolicy ( > > + VOID > > + ) > > +{ > > + if (!IsVariablePolicyLibInitialized()) { > > + return EFI_NOT_READY; > > + } > > + if (mInterfaceLocked) { > > + return EFI_WRITE_PROTECTED; > > + } > > + mInterfaceLocked =3D TRUE; > > + return EFI_SUCCESS; > > +} > > + > > + > > +/** > > + This API function returns whether or not the policy interface is lock= ed > > + for the remainder of the boot. > > + > > + @retval TRUE > > + @retval FALSE > > + @retval FALSE Library has not yet been initialized. > > + > > +**/ > > +BOOLEAN > > +EFIAPI > > +IsVariablePolicyInterfaceLocked ( > > + VOID > > + ) > > +{ > > + if (!IsVariablePolicyLibInitialized()) { > > + return FALSE; > > + } > > + return mInterfaceLocked; > > +} > > + > > + > > +/** > > + This helper function initializes the library and sets > > + up any required internal structures or handlers. > > + > > + Also registers the internal pointer for the GetVariable helper. > > + > > + @param[in] GetVariableHelper A function pointer matching the > EFI_GET_VARIABLE prototype that will be used to > > + check policy criteria that involve the existence of o= ther variables. > > + > > + @retval EFI_SUCCESS > > + @retval EFI_ALREADY_STARTED The initialize function has been ca= lled > more than once without a call to > > + deinitialize. > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +InitVariablePolicyLib ( > > + IN EFI_GET_VARIABLE GetVariableHelper > > + ) > > +{ > > + EFI_STATUS Status; > > + > > + Status =3D EFI_SUCCESS; > > + if (mGetVariableHelper !=3D NULL) { > > + Status =3D EFI_ALREADY_STARTED; 4. [Dandan]: Could we return directly here? > > + } > > + > > + if (!EFI_ERROR( Status )) { > > + Status =3D VariablePolicyExtraInit(); > > + } > > + > > + if (!EFI_ERROR( Status )) { > > + // Save an internal pointer to the GetVariableHelper. > > + mGetVariableHelper =3D GetVariableHelper; > > + > > + // Initialize the global state. > > + mInterfaceLocked =3D FALSE; > > + mProtectionDisabled =3D FALSE; > > + mPolicyTable =3D NULL; > > + mCurrentTableSize =3D 0; > > + mCurrentTableUsage =3D 0; > > + mCurrentTableCount =3D 0; > > + } > > + > > + return Status; > > +} > > + > > + > > +/** > > + This helper function returns whether or not the library is currently > initialized. > > + > > + @retval TRUE > > + @retval FALSE > > + > > +**/ > > +BOOLEAN > > +EFIAPI > > +IsVariablePolicyLibInitialized ( > > + VOID > > + ) > > +{ > > + return (mGetVariableHelper !=3D NULL); > > +} > > + > > + > > +/** > > + This helper function tears down the library. > > + > > + Should generally only be used for test harnesses. > > + > > + @retval EFI_SUCCESS > > + @retval EFI_NOT_READY Deinitialize was called without first c= alling > initialize. > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +DeinitVariablePolicyLib ( > > + VOID > > + ) > > +{ > > + EFI_STATUS Status; > > + > > + Status =3D EFI_SUCCESS; > > + > > + if (mGetVariableHelper =3D=3D NULL) { > > + Status =3D EFI_NOT_READY; > > + } > > + > > + if (!EFI_ERROR( Status )) { > > + Status =3D VariablePolicyExtraDeinit(); > > + } > > + > > + if (!EFI_ERROR( Status )) { > > + mGetVariableHelper =3D NULL; > > + mInterfaceLocked =3D FALSE; > > + mProtectionDisabled =3D FALSE; > > + mCurrentTableSize =3D 0; > > + mCurrentTableUsage =3D 0; > > + mCurrentTableCount =3D 0; > > + > > + if (mPolicyTable !=3D NULL) { > > + FreePool( mPolicyTable ); > > + mPolicyTable =3D NULL; > > + } > > + } > > + > > + return Status; > > +} > > diff --git > a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/Variable > PolicyUnitTest.c > b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/Variable > PolicyUnitTest.c > new file mode 100644 > index 000000000000..f133f2f30e36 > --- /dev/null > +++ > b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/Variable > PolicyUnitTest.c > @@ -0,0 +1,2436 @@ > +/** @file -- VariablePolicyUnitTest.c > > +UnitTest for... > > +Business logic for Variable Policy enforcement. > > + > > +Copyright (c) Microsoft Corporation. > > +SPDX-License-Identifier: BSD-2-Clause-Patent > > + > > +**/ > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +#include > > + > > +#include > > +#include > > + > > +// MU_CHANGE - Turn this off for now. Try to turn it back on with extra > build options. > > +// #ifndef INTERNAL_UNIT_TEST > > +// #error Make sure to build thie with INTERNAL_UNIT_TEST enabled! > Otherwise, some important tests may be skipped! > > +// #endif > > + > > + > > +#define UNIT_TEST_NAME "UEFI Variable Policy UnitTest" > > +#define UNIT_TEST_VERSION "0.5" > > + > > +///=3D=3D=3D TEST DATA > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > > + > > +#pragma pack(push, 1) > > +typedef struct _SIMPLE_VARIABLE_POLICY_ENTRY { > > + VARIABLE_POLICY_ENTRY Header; > > + CHAR16 Name[]; > > +} SIMPLE_VARIABLE_POLICY_ENTRY; > > +#define EXPANDED_VARIABLE_POLICY_ENTRY_VAR_NAME_LENGTH 1001 > // 1000 characters + terminator. > > +#define EXPANDED_VARIABLE_POLICY_ENTRY_VAR_NAME_SIZE > (EXPANDED_VARIABLE_POLICY_ENTRY_VAR_NAME_LENGTH * > sizeof(CHAR16)) > > +typedef struct _EXPANDED_VARIABLE_POLICY_ENTRY { > > + VARIABLE_POLICY_ENTRY Header; > > + VARIABLE_LOCK_ON_VAR_STATE_POLICY StatePolicy; > > + CHAR16 > StateName[EXPANDED_VARIABLE_POLICY_ENTRY_VAR_NAME_LENGTH]; > > + CHAR16 > Name[EXPANDED_VARIABLE_POLICY_ENTRY_VAR_NAME_LENGTH]; > > +} EXPANDED_VARIABLE_POLICY_ENTRY; > > +#pragma pack(pop) > > + > > +// {F955BA2D-4A2C-480C-BFD1-3CC522610592} > > +#define TEST_GUID_1 { 0xf955ba2d, 0x4a2c, 0x480c, { 0xbf, 0xd1, 0x3c, 0= xc5, > 0x22, 0x61, 0x5, 0x92 } } > > +EFI_GUID mTestGuid1 =3D TEST_GUID_1; > > +// {2DEA799E-5E73-43B9-870E-C945CE82AF3A} > > +#define TEST_GUID_2 { 0x2dea799e, 0x5e73, 0x43b9, { 0x87, 0xe, 0xc9, 0x= 45, > 0xce, 0x82, 0xaf, 0x3a } } > > +EFI_GUID mTestGuid2 =3D TEST_GUID_2; > > +// {698A2BFD-A616-482D-B88C-7100BD6682A9} > > +#define TEST_GUID_3 { 0x698a2bfd, 0xa616, 0x482d, { 0xb8, 0x8c, 0x71, 0= x0, > 0xbd, 0x66, 0x82, 0xa9 } } > > +EFI_GUID mTestGuid3 =3D TEST_GUID_3; > > + > > +#define TEST_VAR_1_NAME L"TestVar1" > > +#define TEST_VAR_2_NAME L"TestVar2" > > +#define TEST_VAR_3_NAME L"TestVar3" > > + > > +#define TEST_POLICY_ATTRIBUTES_NULL 0 > > +#define TEST_POLICY_MIN_SIZE_NULL 0 > > +#define TEST_POLICY_MAX_SIZE_NULL MAX_UINT32 > > + > > +#define TEST_POLICY_MIN_SIZE_10 10 > > +#define TEST_POLICY_MAX_SIZE_200 200 > > + > > +#define TEST_300_HASHES_STRING > L"##################################################"\ > > + > "##################################################"\ > > + > "##################################################"\ > > + > "##################################################"\ > > + > "##################################################"\ > > + > "##################################################" > > + > > + > > +///=3D=3D=3D HELPER FUNCTIONS > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > > + > > +/** > > + Helper function to initialize a VARIABLE_POLICY_ENTRY structure with = a > Name and StateName. > > + > > + Takes care of all the messy packing. > > + > > + @param[in,out] Entry > > + @param[in] Name [Optional] > > + @param[in] StateName [Optional] > > + > > + @retval TRUE > > + @retval FALSE > > + > > +**/ > > +STATIC > > +BOOLEAN > > +InitExpVarPolicyStrings ( > > + EXPANDED_VARIABLE_POLICY_ENTRY *Entry, > > + CHAR16 *Name, OPTIONAL > > + CHAR16 *StateName OPTIONAL > > + ) > > +{ > > + UINTN NameSize; > > + UINTN StateNameSize; > > + > > + NameSize =3D Name =3D=3D NULL ? 0 : StrSize( Name ); > > + StateNameSize =3D StateName =3D=3D NULL ? 0 : StrSize( StateName ); > > + > > + if (NameSize > EXPANDED_VARIABLE_POLICY_ENTRY_VAR_NAME_SIZE || > NameSize > MAX_UINT16 || > > + StateNameSize > > EXPANDED_VARIABLE_POLICY_ENTRY_VAR_NAME_SIZE || StateNameSize > > MAX_UINT16) { > > + return FALSE; > > + } > > + > > + Entry->Header.OffsetToName =3D sizeof(VARIABLE_POLICY_ENTRY); > > + if (StateName !=3D NULL) { > > + Entry->Header.OffsetToName +=3D > (UINT16)sizeof(VARIABLE_LOCK_ON_VAR_STATE_POLICY) + > (UINT16)StateNameSize; > > + } > > + Entry->Header.Size =3D Entry->Header.OffsetToName + (UINT16)NameSize; > > + > > + CopyMem( (UINT8*)Entry + Entry->Header.OffsetToName, Name, > NameSize ); > > + if (StateName !=3D NULL) { > > + CopyMem( (UINT8*)Entry + sizeof(VARIABLE_POLICY_ENTRY) + > sizeof(VARIABLE_LOCK_ON_VAR_STATE_POLICY), StateName, > StateNameSize ); > > + } > > + > > + return TRUE; > > +} > > + > > +/** > > + Mocked version of GetVariable, for testing. > > +**/ > > +EFI_STATUS > > +EFIAPI > > +StubGetVariableNull ( > > + IN CHAR16 *VariableName, > > + IN EFI_GUID *VendorGuid, > > + OUT UINT32 *Attributes, OPTIONAL > > + IN OUT UINTN *DataSize, > > + OUT VOID *Data OPTIONAL > > + ) > > +{ > > + UINT32 MockedAttr; > > + UINTN MockedDataSize; > > + VOID *MockedData; > > + EFI_STATUS MockedReturn; > > + > > + check_expected_ptr( VariableName ); > > + check_expected_ptr( VendorGuid ); > > + check_expected_ptr( DataSize ); > > + > > + MockedAttr =3D (UINT32)mock(); > > + MockedDataSize =3D (UINTN)mock(); > > + MockedData =3D (VOID*)mock(); > > + MockedReturn =3D (EFI_STATUS)mock(); > > + > > + if (Attributes !=3D NULL) { > > + *Attributes =3D MockedAttr; > > + } > > + if (Data !=3D NULL && !EFI_ERROR(MockedReturn)) { > > + CopyMem( Data, MockedData, MockedDataSize ); > > + } > > + > > + *DataSize =3D MockedDataSize; > > + > > + return MockedReturn; > > +} > > + > > +// > > +// Anything you think might be helpful that isn't a test itself. > > +// > > + > > +/** > > + This is a common setup function that will ensure the library is alway= s > initialized > > + with the stubbed GetVariable. > > + > > + Not used by all test cases, but by most. > > +**/ > > +STATIC > > +UNIT_TEST_STATUS > > +LibInitMocked ( > > + IN UNIT_TEST_CONTEXT Context > > + ) > > +{ > > + return EFI_ERROR(InitVariablePolicyLib( StubGetVariableNull )) ? > UNIT_TEST_ERROR_PREREQUISITE_NOT_MET : UNIT_TEST_PASSED; > > +} > > + > > +/** > > + Common cleanup function to make sure that the library is always de- > initialized prior > > + to the next test case. > > +*/ > > +STATIC > > +VOID > > +LibCleanup ( > > + IN UNIT_TEST_CONTEXT Context > > + ) > > +{ > > + DeinitVariablePolicyLib(); > > +} > > + > > + > > +///=3D=3D=3D TEST CASES > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > > + > > +///=3D=3D=3D=3D=3D ARCHITECTURAL SUITE > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D > > + > > +/** > > + Test Case > > +*/ > > +UNIT_TEST_STATUS > > +EFIAPI > > +ShouldBeAbleToInitAndDeinitTheLibrary ( > > + IN UNIT_TEST_CONTEXT Context > > + ) > > +{ > > + EFI_STATUS Status; > > + Status =3D InitVariablePolicyLib( StubGetVariableNull ); > > + UT_ASSERT_NOT_EFI_ERROR( Status ); > > + > > + UT_ASSERT_TRUE( IsVariablePolicyLibInitialized() ); > > + > > + Status =3D DeinitVariablePolicyLib(); > > + UT_ASSERT_NOT_EFI_ERROR( Status ); > > + > > + UT_ASSERT_FALSE( IsVariablePolicyLibInitialized() ); > > + > > + return UNIT_TEST_PASSED; > > +} > > + > > +/** > > + Test Case > > +*/ > > +UNIT_TEST_STATUS > > +EFIAPI > > +ShouldNotBeAbleToInitializeTheLibraryTwice ( > > + IN UNIT_TEST_CONTEXT Context > > + ) > > +{ > > + EFI_STATUS Status; > > + Status =3D InitVariablePolicyLib( StubGetVariableNull ); > > + UT_ASSERT_NOT_EFI_ERROR( Status ); > > + Status =3D InitVariablePolicyLib( StubGetVariableNull ); > > + UT_ASSERT_TRUE( EFI_ERROR( Status ) ); > > + return UNIT_TEST_PASSED; > > +} > > + > > +/** > > + Test Case > > +*/ > > +UNIT_TEST_STATUS > > +EFIAPI > > +ShouldFailDeinitWithoutInit ( > > + IN UNIT_TEST_CONTEXT Context > > + ) > > +{ > > + EFI_STATUS Status; > > + Status =3D DeinitVariablePolicyLib(); > > + UT_ASSERT_TRUE( EFI_ERROR( Status ) ); > > + return UNIT_TEST_PASSED; > > +} > > + > > +/** > > + Test Case > > +*/ > > +UNIT_TEST_STATUS > > +EFIAPI > > +ApiCommandsShouldNotRespondIfLibIsUninitialized ( > > + IN UNIT_TEST_CONTEXT Context > > + ) > > +{ > > + SIMPLE_VARIABLE_POLICY_ENTRY TestPolicy =3D { > > + { > > + VARIABLE_POLICY_ENTRY_REVISION, > > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME), > > + sizeof(VARIABLE_POLICY_ENTRY), > > + TEST_GUID_1, > > + TEST_POLICY_MIN_SIZE_NULL, > > + TEST_POLICY_MAX_SIZE_NULL, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + VARIABLE_POLICY_TYPE_NO_LOCK > > + }, > > + TEST_VAR_1_NAME > > + }; > > + UINT8 DummyData[8]; > > + UINT32 DummyDataSize =3D sizeof(DummyData); > > + > > + // This test should not start with an initialized library. > > + > > + // Verify that all API commands fail. > > + UT_ASSERT_TRUE( EFI_ERROR( LockVariablePolicy() ) ); > > + UT_ASSERT_TRUE( EFI_ERROR( DisableVariablePolicy() ) ); > > + > UT_ASSERT_TRUE( EFI_ERROR( RegisterVariablePolicy( &TestPolicy.Header ) > ) ); > > + UT_ASSERT_TRUE( EFI_ERROR( DumpVariablePolicy( DummyData, > &DummyDataSize ) ) ); > > + UT_ASSERT_FALSE( IsVariablePolicyInterfaceLocked() ); > > + UT_ASSERT_FALSE( IsVariablePolicyEnabled() ); > > + UT_ASSERT_TRUE( EFI_ERROR( ValidateSetVariable( TEST_VAR_1_NAME, > > + &mTestGuid1, > > + VARIABLE_ATTRIBUTE_NV_= BS, > > + sizeof(DummyData), > > + DummyData ) ) ); > > + > > + return UNIT_TEST_PASSED; > > +} > > + > > + > > +///=3D=3D=3D=3D=3D INTERNAL FUNCTION SUITE > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > > + > > +#ifdef INTERNAL_UNIT_TEST > > + > > +BOOLEAN > > +EvaluatePolicyMatch ( > > + IN CONST VARIABLE_POLICY_ENTRY *EvalEntry, > > + IN CONST CHAR16 *VariableName, > > + IN CONST EFI_GUID *VendorGuid, > > + OUT UINT8 *MatchPriority OPTIONAL > > + ); > > + > > +/** > > + Test Case > > +*/ > > +UNIT_TEST_STATUS > > +EFIAPI > > +PoliciesShouldMatchByNameAndGuid ( > > + IN UNIT_TEST_CONTEXT Context > > + ) > > +{ > > + SIMPLE_VARIABLE_POLICY_ENTRY MatchCheckPolicy =3D { > > + { > > + VARIABLE_POLICY_ENTRY_REVISION, > > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME), > > + sizeof(VARIABLE_POLICY_ENTRY), > > + TEST_GUID_1, > > + TEST_POLICY_MIN_SIZE_NULL, > > + TEST_POLICY_MAX_SIZE_NULL, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + VARIABLE_POLICY_TYPE_NO_LOCK > > + }, > > + TEST_VAR_1_NAME > > + }; > > + CHAR16 *CheckVar1Name =3D TEST_VAR_1_NAME; > > + CHAR16 *CheckVar2Name =3D TEST_VAR_2_NAME; > > + > > + // Make sure that a different name does not match. > > + UT_ASSERT_FALSE( EvaluatePolicyMatch( &MatchCheckPolicy.Header, > CheckVar2Name, &mTestGuid1, NULL ) ); > > + > > + // Make sure that a different GUID does not match. > > + UT_ASSERT_FALSE( EvaluatePolicyMatch( &MatchCheckPolicy.Header, > CheckVar1Name, &mTestGuid2, NULL ) ); > > + > > + // Make sure that the same name and GUID match. > > + UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolicy.Header, > CheckVar1Name, &mTestGuid1, NULL ) ); > > + > > + return UNIT_TEST_PASSED; > > +} > > + > > +/** > > + Test Case > > +*/ > > +UNIT_TEST_STATUS > > +EFIAPI > > +WildcardPoliciesShouldMatchDigits ( > > + IN UNIT_TEST_CONTEXT Context > > + ) > > +{ > > + SIMPLE_VARIABLE_POLICY_ENTRY MatchCheckPolicy =3D { > > + { > > + VARIABLE_POLICY_ENTRY_REVISION, > > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(L"Wildcard#VarName##"), > > + sizeof(VARIABLE_POLICY_ENTRY), > > + TEST_GUID_1, > > + TEST_POLICY_MIN_SIZE_NULL, > > + TEST_POLICY_MAX_SIZE_NULL, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + VARIABLE_POLICY_TYPE_NO_LOCK > > + }, > > + L"Wildcard#VarName##" > > + }; > > + CHAR16 *CheckVar1Name =3D L"Wildcard1VarName12"; > > + CHAR16 *CheckVar2Name =3D L"Wildcard2VarName34"; > > + CHAR16 *CheckVarBName =3D L"WildcardBVarName56"; > > + CHAR16 *CheckVarHName =3D L"Wildcard#VarName56"; > > + > > + // Make sure that two different sets of wildcard numbers match. > > + UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolicy.Header, > CheckVar1Name, &mTestGuid1, NULL ) ); > > + UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolicy.Header, > CheckVar2Name, &mTestGuid1, NULL ) ); > > + > > + // Make sure that the non-number charaters don't match. > > + UT_ASSERT_FALSE( EvaluatePolicyMatch( &MatchCheckPolicy.Header, > CheckVarBName, &mTestGuid1, NULL ) ); > > + > > + // Make sure that '#' signs don't match. > > + UT_ASSERT_FALSE( EvaluatePolicyMatch( &MatchCheckPolicy.Header, > CheckVarHName, &mTestGuid1, NULL ) ); > > + > > + return UNIT_TEST_PASSED; > > +} > > + > > +/** > > + Test Case > > +*/ > > +UNIT_TEST_STATUS > > +EFIAPI > > +WildcardPoliciesShouldMatchDigitsAdvanced ( > > + IN UNIT_TEST_CONTEXT Context > > + ) > > +{ > > + SIMPLE_VARIABLE_POLICY_ENTRY MatchCheckPolicy =3D { > > + { > > + VARIABLE_POLICY_ENTRY_REVISION, > > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_300_HASHES_STRING), > > + sizeof(VARIABLE_POLICY_ENTRY), > > + TEST_GUID_1, > > + TEST_POLICY_MIN_SIZE_NULL, > > + TEST_POLICY_MAX_SIZE_NULL, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + VARIABLE_POLICY_TYPE_NO_LOCK > > + }, > > + TEST_300_HASHES_STRING > > + }; > > + CHAR16 *CheckShorterString =3D > L"01234567890123456789012345678901234567890123456789"; > > + CHAR16 *CheckValidString =3D > L"01234567890123456789012345678901234567890123456789"\ > > + > "01234567890123456789012345678901234567890123456789"\ > > + > "01234567890123456789012345678901234567890123456789"\ > > + > "01234567890123456789012345678901234567890123456789"\ > > + > "01234567890123456789012345678901234567890123456789"\ > > + > "01234567890123456789012345678901234567890123456789"; > > + CHAR16 *CheckLongerString =3D > L"01234567890123456789012345678901234567890123456789"\ > > + > "01234567890123456789012345678901234567890123456789"\ > > + > "01234567890123456789012345678901234567890123456789"\ > > + > "01234567890123456789012345678901234567890123456789"\ > > + > "01234567890123456789012345678901234567890123456789"\ > > + > "01234567890123456789012345678901234567890123456789"\ > > + > "01234567890123456789012345678901234567890123456789"; > > + UINT8 MatchPriority; > > + > > + // Make sure that the shorter and the longer do not match. > > + UT_ASSERT_FALSE( EvaluatePolicyMatch( &MatchCheckPolicy.Header, > CheckShorterString, &mTestGuid1, NULL ) ); > > + UT_ASSERT_FALSE( EvaluatePolicyMatch( &MatchCheckPolicy.Header, > CheckLongerString, &mTestGuid1, NULL ) ); > > + > > + // Make sure that the valid one matches and has the expected priority= . > > + UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolicy.Header, > CheckValidString, &mTestGuid1, &MatchPriority ) ); > > + UT_ASSERT_EQUAL( MatchPriority, MAX_UINT8 ); > > + > > + return UNIT_TEST_PASSED; > > +} > > + > > +/** > > + Test Case > > +*/ > > +UNIT_TEST_STATUS > > +EFIAPI > > +WildcardPoliciesShouldMatchNamespaces ( > > + IN UNIT_TEST_CONTEXT Context > > + ) > > +{ > > + VARIABLE_POLICY_ENTRY MatchCheckPolicy =3D { > > + VARIABLE_POLICY_ENTRY_REVISION, > > + sizeof(VARIABLE_POLICY_ENTRY), > > + sizeof(VARIABLE_POLICY_ENTRY), > > + TEST_GUID_1, > > + TEST_POLICY_MIN_SIZE_NULL, > > + TEST_POLICY_MAX_SIZE_NULL, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + VARIABLE_POLICY_TYPE_NO_LOCK > > + }; > > + CHAR16 *CheckVar1Name =3D L"Wildcard1VarName12"; > > + CHAR16 *CheckVar2Name =3D L"Wildcard2VarName34"; > > + CHAR16 *CheckVarBName =3D L"WildcardBVarName56"; > > + CHAR16 *CheckVarHName =3D L"Wildcard#VarName56"; > > + > > + // Make sure that all names in the same namespace match. > > + UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolicy, > CheckVar1Name, &mTestGuid1, NULL ) ); > > + UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolicy, > CheckVar2Name, &mTestGuid1, NULL ) ); > > + UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolicy, > CheckVarBName, &mTestGuid1, NULL ) ); > > + UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolicy, > CheckVarHName, &mTestGuid1, NULL ) ); > > + > > + // Make sure that different namespace doesn't match. > > + UT_ASSERT_FALSE( EvaluatePolicyMatch( &MatchCheckPolicy, > CheckVar1Name, &mTestGuid2, NULL ) ); > > + > > + > > + return UNIT_TEST_PASSED; > > +} > > + > > +/** > > + Test Case > > +*/ > > +UNIT_TEST_STATUS > > +EFIAPI > > +MatchPrioritiesShouldFollowRules ( > > + IN UNIT_TEST_CONTEXT Context > > + ) > > +{ > > + SIMPLE_VARIABLE_POLICY_ENTRY MatchCheckPolicy =3D { > > + { > > + VARIABLE_POLICY_ENTRY_REVISION, > > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(L"Wildcard1VarName12"), > > + sizeof(VARIABLE_POLICY_ENTRY), > > + TEST_GUID_1, > > + TEST_POLICY_MIN_SIZE_NULL, > > + TEST_POLICY_MAX_SIZE_NULL, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + VARIABLE_POLICY_TYPE_NO_LOCK > > + }, > > + L"Wildcard1VarName12" > > + }; > > + CHAR16 CheckVar1Name[] =3D L"Wildcard1VarName12"; > > + CHAR16 MatchVar1Name[] =3D L"Wildcard1VarName12"; > > + CHAR16 MatchVar2Name[] =3D L"Wildcard#VarName12"; > > + CHAR16 MatchVar3Name[] =3D L"Wildcard#VarName#2"; > > + CHAR16 MatchVar4Name[] =3D L"Wildcard#VarName##"; > > + UINT8 MatchPriority; > > + > > + // Check with a perfect match. > > + CopyMem( &MatchCheckPolicy.Name, MatchVar1Name, > sizeof(MatchVar1Name) ); > > + UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolicy.Header, > CheckVar1Name, &mTestGuid1, &MatchPriority ) ); > > + UT_ASSERT_EQUAL( MatchPriority, 0 ); > > + > > + // Check with progressively lower priority matches. > > + CopyMem( &MatchCheckPolicy.Name, MatchVar2Name, > sizeof(MatchVar2Name) ); > > + UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolicy.Header, > CheckVar1Name, &mTestGuid1, &MatchPriority ) ); > > + UT_ASSERT_EQUAL( MatchPriority, 1 ); > > + CopyMem( &MatchCheckPolicy.Name, MatchVar3Name, > sizeof(MatchVar3Name) ); > > + UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolicy.Header, > CheckVar1Name, &mTestGuid1, &MatchPriority ) ); > > + UT_ASSERT_EQUAL( MatchPriority, 2 ); > > + CopyMem( &MatchCheckPolicy.Name, MatchVar4Name, > sizeof(MatchVar4Name) ); > > + UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolicy.Header, > CheckVar1Name, &mTestGuid1, &MatchPriority ) ); > > + UT_ASSERT_EQUAL( MatchPriority, 3 ); > > + > > + // Check against the entire namespace. > > + MatchCheckPolicy.Header.Size =3D sizeof(VARIABLE_POLICY_ENTRY); > > + UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolicy.Header, > CheckVar1Name, &mTestGuid1, &MatchPriority ) ); > > + UT_ASSERT_EQUAL( MatchPriority, MAX_UINT8 ); > > + > > + return UNIT_TEST_PASSED; > > +} > > + > > +#endif // INTERNAL_UNIT_TEST > > + > > + > > +///=3D=3D=3D POLICY MANIPULATION SUITE > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > > + > > +/** > > + Test Case > > +*/ > > +UNIT_TEST_STATUS > > +EFIAPI > > +RegisterShouldAllowNamespaceWildcards ( > > + IN UNIT_TEST_CONTEXT Context > > + ) > > +{ > > + SIMPLE_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { > > + { > > + VARIABLE_POLICY_ENTRY_REVISION, > > + sizeof(VARIABLE_POLICY_ENTRY), > > + sizeof(VARIABLE_POLICY_ENTRY), > > + TEST_GUID_1, > > + TEST_POLICY_MIN_SIZE_NULL, > > + TEST_POLICY_MAX_SIZE_NULL, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + VARIABLE_POLICY_TYPE_NO_LOCK > > + }, > > + L"" > > + }; > > + > > + > UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea > der ) ); > > + > > + return UNIT_TEST_PASSED; > > +} > > + > > +/** > > + Test Case > > +*/ > > +UNIT_TEST_STATUS > > +EFIAPI > > +RegisterShouldAllowStateVarsForNamespaces ( > > + IN UNIT_TEST_CONTEXT Context > > + ) > > +{ > > + EXPANDED_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { > > + { > > + VARIABLE_POLICY_ENTRY_REVISION, > > + 0, // Will be populated by init helper. > > + 0, // Will be populated by init helper. > > + TEST_GUID_1, > > + TEST_POLICY_MIN_SIZE_NULL, > > + TEST_POLICY_MAX_SIZE_NULL, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE > > + }, > > + { > > + TEST_GUID_2, > > + 1, // Value > > + 0 // Padding > > + }, > > + L"", > > + L"" > > + }; > > + UT_ASSERT_TRUE( InitExpVarPolicyStrings( &ValidationPolicy, NULL, > TEST_VAR_2_NAME ) ); > > + > > + > UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea > der ) ); > > + > > + return UNIT_TEST_PASSED; > > +} > > + > > +/** > > + Test Case > > +*/ > > +UNIT_TEST_STATUS > > +EFIAPI > > +RegisterShouldRejectNullPointers ( > > + IN UNIT_TEST_CONTEXT Context > > + ) > > +{ > > + UT_ASSERT_EQUAL( RegisterVariablePolicy( NULL ), > EFI_INVALID_PARAMETER ); > > + return UNIT_TEST_PASSED; > > +} > > + > > +/** > > + Test Case > > +*/ > > +UNIT_TEST_STATUS > > +EFIAPI > > +RegisterShouldRejectBadRevisions ( > > + IN UNIT_TEST_CONTEXT Context > > + ) > > +{ > > + SIMPLE_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { > > + { > > + VARIABLE_POLICY_ENTRY_REVISION, > > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME), > > + sizeof(VARIABLE_POLICY_ENTRY), > > + TEST_GUID_1, > > + TEST_POLICY_MIN_SIZE_NULL, > > + TEST_POLICY_MAX_SIZE_NULL, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + VARIABLE_POLICY_TYPE_NO_LOCK > > + }, > > + TEST_VAR_1_NAME > > + }; > > + > > + ValidationPolicy.Header.Version =3D MAX_UINT32; > > + UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), > EFI_INVALID_PARAMETER ); > > + > > + return UNIT_TEST_PASSED; > > +} > > + > > +/** > > + Test Case > > +*/ > > +UNIT_TEST_STATUS > > +EFIAPI > > +RegisterShouldRejectBadSizes ( > > + IN UNIT_TEST_CONTEXT Context > > + ) > > +{ > > + SIMPLE_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { > > + { > > + VARIABLE_POLICY_ENTRY_REVISION, > > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME), > > + sizeof(VARIABLE_POLICY_ENTRY), > > + TEST_GUID_1, > > + TEST_POLICY_MIN_SIZE_NULL, > > + TEST_POLICY_MAX_SIZE_NULL, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + VARIABLE_POLICY_TYPE_NO_LOCK > > + }, > > + TEST_VAR_1_NAME > > + }; > > + > > + ValidationPolicy.Header.Size =3D sizeof(VARIABLE_POLICY_ENTRY) - 2; > > + UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), > EFI_INVALID_PARAMETER ); > > + > > + return UNIT_TEST_PASSED; > > +} > > + > > +/** > > + Test Case > > +*/ > > +UNIT_TEST_STATUS > > +EFIAPI > > +RegisterShouldRejectBadOffsets ( > > + IN UNIT_TEST_CONTEXT Context > > + ) > > +{ > > + EXPANDED_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { > > + { > > + VARIABLE_POLICY_ENTRY_REVISION, > > + 0, // Will be populated by init helper. > > + 0, // Will be populated by init helper. > > + TEST_GUID_1, > > + TEST_POLICY_MIN_SIZE_NULL, > > + TEST_POLICY_MAX_SIZE_NULL, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE > > + }, > > + { > > + TEST_GUID_2, > > + 1, // Value > > + 0 // Padding > > + }, > > + L"", > > + L"" > > + }; > > + UT_ASSERT_TRUE( InitExpVarPolicyStrings( &ValidationPolicy, > TEST_VAR_1_NAME, TEST_VAR_2_NAME ) ); > > + > > + // Check for an offset outside the size bounds. > > + ValidationPolicy.Header.OffsetToName =3D ValidationPolicy.Header.Size= + 1; > > + UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), > EFI_INVALID_PARAMETER ); > > + > > + // Check for an offset inside the policy header. > > + ValidationPolicy.Header.OffsetToName =3D sizeof(VARIABLE_POLICY_ENTRY= ) > - 2; > > + UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), > EFI_INVALID_PARAMETER ); > > + > > + // Check for an offset inside the state policy header. > > + ValidationPolicy.Header.OffsetToName =3D sizeof(VARIABLE_POLICY_ENTRY= ) > + 2; > > + UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), > EFI_INVALID_PARAMETER ); > > + > > + // Check for a ridiculous offset. > > + ValidationPolicy.Header.OffsetToName =3D MAX_UINT16; > > + UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), > EFI_INVALID_PARAMETER ); > > + > > + return UNIT_TEST_PASSED; > > +} > > + > > +/** > > + Test Case > > +*/ > > +UNIT_TEST_STATUS > > +EFIAPI > > +RegisterShouldRejectMissingStateStrings ( > > + IN UNIT_TEST_CONTEXT Context > > + ) > > +{ > > + EXPANDED_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { > > + { > > + VARIABLE_POLICY_ENTRY_REVISION, > > + 0, // Will be populated by init helper. > > + 0, // Will be populated by init helper. > > + TEST_GUID_1, > > + TEST_POLICY_MIN_SIZE_NULL, > > + TEST_POLICY_MAX_SIZE_NULL, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE > > + }, > > + { > > + TEST_GUID_2, > > + 1, // Value > > + 0 // Padding > > + }, > > + L"", > > + L"" > > + }; > > + UT_ASSERT_TRUE( InitExpVarPolicyStrings( &ValidationPolicy, > TEST_VAR_1_NAME, TEST_VAR_2_NAME ) ); > > + > > + // Remove the state string and copy the Name into it's place. > > + // Also adjust the offset. > > + ValidationPolicy.Header.Size =3D sizeof(VARIABLE_POLICY_ENTR= Y) + > sizeof(VARIABLE_LOCK_ON_VAR_STATE_POLICY) + > sizeof(TEST_VAR_1_NAME); > > + ValidationPolicy.Header.OffsetToName =3D sizeof(VARIABLE_POLICY_ENTR= Y) > + sizeof(VARIABLE_LOCK_ON_VAR_STATE_POLICY); > > + CopyMem( (UINT8*)&ValidationPolicy + > ValidationPolicy.Header.OffsetToName, TEST_VAR_1_NAME, > sizeof(TEST_VAR_1_NAME) ); > > + > > + // Make sure that this structure fails. > > + UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), > EFI_INVALID_PARAMETER ); > > + > > + return UNIT_TEST_PASSED; > > +} > > + > > +/** > > + Test Case > > +*/ > > +UNIT_TEST_STATUS > > +EFIAPI > > +RegisterShouldRejectStringsMissingNull ( > > + IN UNIT_TEST_CONTEXT Context > > + ) > > +{ > > + EXPANDED_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { > > + { > > + VARIABLE_POLICY_ENTRY_REVISION, > > + 0, // Will be populated by init helper. > > + 0, // Will be populated by init helper. > > + TEST_GUID_1, > > + TEST_POLICY_MIN_SIZE_NULL, > > + TEST_POLICY_MAX_SIZE_NULL, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE > > + }, > > + { > > + TEST_GUID_2, > > + 1, // Value > > + 0 // Padding > > + }, > > + L"", > > + L"" > > + }; > > + UT_ASSERT_TRUE( InitExpVarPolicyStrings( &ValidationPolicy, > TEST_VAR_1_NAME, TEST_VAR_2_NAME ) ); > > + > > + // Removing the NULL from the Name should fail. > > + ValidationPolicy.Header.Size =3D ValidationPolicy.Header.Size - > sizeof(CHAR16); > > + UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), > EFI_INVALID_PARAMETER ); > > + > > + // Removing the NULL from the State Name is a little trickier. > > + // Copy the Name up one byte. > > + ValidationPolicy.Header.OffsetToName =3D > ValidationPolicy.Header.OffsetToName - sizeof(CHAR16); > > + CopyMem( (UINT8*)&ValidationPolicy + > ValidationPolicy.Header.OffsetToName, TEST_VAR_1_NAME, > sizeof(TEST_VAR_1_NAME) ); > > + UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), > EFI_INVALID_PARAMETER ); > > + > > + return UNIT_TEST_PASSED; > > +} > > + > > +/** > > + Test Case > > +*/ > > +UNIT_TEST_STATUS > > +EFIAPI > > +RegisterShouldRejectMalformedStrings ( > > + IN UNIT_TEST_CONTEXT Context > > + ) > > +{ > > + EXPANDED_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { > > + { > > + VARIABLE_POLICY_ENTRY_REVISION, > > + 0, // Will be populated by init helper. > > + 0, // Will be populated by init helper. > > + TEST_GUID_1, > > + TEST_POLICY_MIN_SIZE_NULL, > > + TEST_POLICY_MAX_SIZE_NULL, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE > > + }, > > + { > > + TEST_GUID_2, > > + 1, // Value > > + 0 // Padding > > + }, > > + L"", > > + L"" > > + }; > > + UT_ASSERT_TRUE( InitExpVarPolicyStrings( &ValidationPolicy, > TEST_VAR_1_NAME, TEST_VAR_2_NAME ) ); > > + > > + // Bisecting the NULL from the Name should fail. > > + ValidationPolicy.Header.Size =3D ValidationPolicy.Header.Size - 1; > > + UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), > EFI_INVALID_PARAMETER ); > > + > > + // Bisecting the NULL from the State Name is a little trickier. > > + // Copy the Name up one byte. > > + ValidationPolicy.Header.OffsetToName =3D > ValidationPolicy.Header.OffsetToName - 1; > > + CopyMem( (UINT8*)&ValidationPolicy + > ValidationPolicy.Header.OffsetToName, TEST_VAR_1_NAME, > sizeof(TEST_VAR_1_NAME) ); > > + UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), > EFI_INVALID_PARAMETER ); > > + > > + return UNIT_TEST_PASSED; > > +} > > + > > +/** > > + Test Case > > +*/ > > +UNIT_TEST_STATUS > > +EFIAPI > > +RegisterShouldRejectUnpackedPolicies ( > > + IN UNIT_TEST_CONTEXT Context > > + ) > > +{ > > + EXPANDED_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { > > + { > > + VARIABLE_POLICY_ENTRY_REVISION, > > + 0, // Will be populated by init helper. > > + 0, // Will be populated by init helper. > > + TEST_GUID_1, > > + TEST_POLICY_MIN_SIZE_NULL, > > + TEST_POLICY_MAX_SIZE_NULL, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE > > + }, > > + { > > + TEST_GUID_2, > > + 1, // Value > > + 0 // Padding > > + }, > > + L"", > > + L"" > > + }; > > + UT_ASSERT_TRUE( InitExpVarPolicyStrings( &ValidationPolicy, > TEST_VAR_1_NAME, TEST_VAR_2_NAME ) ); > > + > > + // Increase the size and move the Name out a bit. > > + ValidationPolicy.Header.Size =3D ValidationPolicy.Header.Size + > sizeof(CHAR16); > > + ValidationPolicy.Header.OffsetToName =3D > ValidationPolicy.Header.OffsetToName + sizeof(CHAR16); > > + CopyMem( (UINT8*)&ValidationPolicy + > ValidationPolicy.Header.OffsetToName, TEST_VAR_1_NAME, > sizeof(TEST_VAR_1_NAME) ); > > + UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), > EFI_INVALID_PARAMETER ); > > + > > + // Reintialize without the state policy and try the same test. > > + ValidationPolicy.Header.LockPolicyType =3D > VARIABLE_POLICY_TYPE_NO_LOCK; > > + UT_ASSERT_TRUE( InitExpVarPolicyStrings( &ValidationPolicy, > TEST_VAR_1_NAME, NULL ) ); > > + ValidationPolicy.Header.Size =3D ValidationPolicy.Header.Size + > sizeof(CHAR16); > > + ValidationPolicy.Header.OffsetToName =3D > ValidationPolicy.Header.OffsetToName + sizeof(CHAR16); > > + CopyMem( (UINT8*)&ValidationPolicy + > ValidationPolicy.Header.OffsetToName, TEST_VAR_1_NAME, > sizeof(TEST_VAR_1_NAME) ); > > + UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), > EFI_INVALID_PARAMETER ); > > + > > + return UNIT_TEST_PASSED; > > +} > > + > > +/** > > + Test Case > > +*/ > > +UNIT_TEST_STATUS > > +EFIAPI > > +RegisterShouldRejectInvalidNameCharacters ( > > + IN UNIT_TEST_CONTEXT Context > > + ) > > +{ > > + // EXPANDED_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { > > + // { > > + // VARIABLE_POLICY_ENTRY_REVISION, > > + // 0, // Will be populated by init helper. > > + // 0, // Will be populated by init helper. > > + // TEST_GUID_1, > > + // TEST_POLICY_MIN_SIZE_NULL, > > + // TEST_POLICY_MAX_SIZE_NULL, > > + // TEST_POLICY_ATTRIBUTES_NULL, > > + // TEST_POLICY_ATTRIBUTES_NULL, > > + // VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE > > + // }, > > + // { > > + // TEST_GUID_2, > > + // 1, // Value > > + // 0 // Padding > > + // }, > > + // L"", > > + // L"" > > + // }; > > + > > + // Currently, there are no known invalid characters. > > + // '#' in LockPolicy->Name are taken as literal. > > + > > + return UNIT_TEST_PASSED; > > +} > > + > > +/** > > + Test Case > > +*/ > > +UNIT_TEST_STATUS > > +EFIAPI > > +RegisterShouldRejectBadPolicyConstraints ( > > + IN UNIT_TEST_CONTEXT Context > > + ) > > +{ > > + SIMPLE_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { > > + { > > + VARIABLE_POLICY_ENTRY_REVISION, > > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME), > > + sizeof(VARIABLE_POLICY_ENTRY), > > + TEST_GUID_1, > > + TEST_POLICY_MIN_SIZE_NULL, > > + TEST_POLICY_MAX_SIZE_NULL, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + VARIABLE_POLICY_TYPE_NO_LOCK > > + }, > > + TEST_VAR_1_NAME > > + }; > > + > > + // Make sure that invalid MAXes are rejected. > > + ValidationPolicy.Header.MaxSize =3D 0; > > + UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), > EFI_INVALID_PARAMETER ); > > + > > + return UNIT_TEST_PASSED; > > +} > > + > > +/** > > + Test Case > > +*/ > > +UNIT_TEST_STATUS > > +EFIAPI > > +RegisterShouldRejectUnknownLockPolicies ( > > + IN UNIT_TEST_CONTEXT Context > > + ) > > +{ > > + SIMPLE_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { > > + { > > + VARIABLE_POLICY_ENTRY_REVISION, > > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME), > > + sizeof(VARIABLE_POLICY_ENTRY), > > + TEST_GUID_1, > > + TEST_POLICY_MIN_SIZE_NULL, > > + TEST_POLICY_MAX_SIZE_NULL, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + VARIABLE_POLICY_TYPE_NO_LOCK > > + }, > > + TEST_VAR_1_NAME > > + }; > > + > > + ValidationPolicy.Header.LockPolicyType =3D > VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE + 1; > > + UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), > EFI_INVALID_PARAMETER ); > > + ValidationPolicy.Header.LockPolicyType =3D > VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE + 1; > > + UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), > EFI_INVALID_PARAMETER ); > > + > > + return UNIT_TEST_PASSED; > > +} > > + > > +/** > > + Test Case > > +*/ > > +UNIT_TEST_STATUS > > +EFIAPI > > +RegisterShouldRejectPolicesWithTooManyWildcards ( > > + IN UNIT_TEST_CONTEXT Context > > + ) > > +{ > > + SIMPLE_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { > > + { > > + VARIABLE_POLICY_ENTRY_REVISION, > > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_300_HASHES_STRING), > > + sizeof(VARIABLE_POLICY_ENTRY), > > + TEST_GUID_1, > > + TEST_POLICY_MIN_SIZE_NULL, > > + TEST_POLICY_MAX_SIZE_NULL, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + VARIABLE_POLICY_TYPE_NO_LOCK > > + }, > > + TEST_300_HASHES_STRING > > + }; > > + > > + // 300 Hashes is currently larger than the possible maximum match pri= ority. > > + UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), > EFI_INVALID_PARAMETER ); > > + > > + return UNIT_TEST_PASSED; > > +} > > + > > +/** > > + Test Case > > +*/ > > +UNIT_TEST_STATUS > > +EFIAPI > > +RegisterShouldRejectDuplicatePolicies ( > > + IN UNIT_TEST_CONTEXT Context > > + ) > > +{ > > + SIMPLE_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { > > + { > > + VARIABLE_POLICY_ENTRY_REVISION, > > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME), > > + sizeof(VARIABLE_POLICY_ENTRY), > > + TEST_GUID_1, > > + TEST_POLICY_MIN_SIZE_NULL, > > + TEST_POLICY_MAX_SIZE_NULL, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + VARIABLE_POLICY_TYPE_NO_LOCK > > + }, > > + TEST_VAR_1_NAME > > + }; > > + > > + > UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea > der ) ); > > + > UT_ASSERT_STATUS_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Head > er ), EFI_ALREADY_STARTED ); > > + > > + return UNIT_TEST_PASSED; > > +} > > + > > +/** > > + Test Case > > +*/ > > +UNIT_TEST_STATUS > > +EFIAPI > > +MinAndMaxSizePoliciesShouldBeHonored ( > > + IN UNIT_TEST_CONTEXT Context > > + ) > > +{ > > + SIMPLE_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { > > + { > > + VARIABLE_POLICY_ENTRY_REVISION, > > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME), > > + sizeof(VARIABLE_POLICY_ENTRY), > > + TEST_GUID_1, > > + TEST_POLICY_MIN_SIZE_10, > > + TEST_POLICY_MAX_SIZE_200, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + VARIABLE_POLICY_TYPE_NO_LOCK > > + }, > > + TEST_VAR_1_NAME > > + }; > > + EFI_STATUS PolicyCheck; > > + UINT8 DummyData[TEST_POLICY_MAX_SIZE_200+1]; > > + > > + > > + // Without a policy, there should be no constraints on variable creat= ion. > > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > > + &mTestGuid1, > > + VARIABLE_ATTRIBUTE_NV_BS, > > + TEST_POLICY_MAX_SIZE_200+1, > > + DummyData ); > > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); > > + > > + // Set a policy to test against. > > + > UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea > der ) ); > > + > > + // With a policy, make sure that sizes outsize the target range fail. > > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > > + &mTestGuid1, > > + VARIABLE_ATTRIBUTE_NV_BS, > > + TEST_POLICY_MAX_SIZE_200+1, > > + DummyData ); > > + UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) ); > > + > > + // With a policy, make sure that sizes outsize the target range fail. > > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > > + &mTestGuid1, > > + VARIABLE_ATTRIBUTE_NV_BS, > > + TEST_POLICY_MIN_SIZE_10-1, > > + DummyData ); > > + UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) ); > > + > > + // With a policy, make sure a valid variable is still valid. > > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > > + &mTestGuid1, > > + VARIABLE_ATTRIBUTE_NV_BS, > > + TEST_POLICY_MIN_SIZE_10+1, > > + DummyData ); > > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); > > + > > + return UNIT_TEST_PASSED; > > +} > > + > > +/** > > + Test Case > > +*/ > > +UNIT_TEST_STATUS > > +EFIAPI > > +AttributeMustPoliciesShouldBeHonored ( > > + IN UNIT_TEST_CONTEXT Context > > + ) > > +{ > > + SIMPLE_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { > > + { > > + VARIABLE_POLICY_ENTRY_REVISION, > > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME), > > + sizeof(VARIABLE_POLICY_ENTRY), > > + TEST_GUID_1, > > + TEST_POLICY_MIN_SIZE_NULL, > > + TEST_POLICY_MAX_SIZE_NULL, > > + VARIABLE_ATTRIBUTE_NV_BS_RT, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + VARIABLE_POLICY_TYPE_NO_LOCK > > + }, > > + TEST_VAR_1_NAME > > + }; > > + EFI_STATUS PolicyCheck; > > + UINT8 DummyData[12]; > > + > > + > > + // Without a policy, there should be no constraints on variable creat= ion. > > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > > + &mTestGuid1, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + sizeof(DummyData), > > + DummyData ); > > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); > > + > > + // Set a policy to test against. > > + > UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea > der ) ); > > + > > + // With a policy, make sure that no attributes fail. > > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > > + &mTestGuid1, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + sizeof(DummyData), > > + DummyData ); > > + UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) ); > > + > > + // With a policy, make sure that some -- but not all -- attributes fa= il. > > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > > + &mTestGuid1, > > + VARIABLE_ATTRIBUTE_BS_RT_AT, > > + sizeof(DummyData), > > + DummyData ); > > + UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) ); > > + > > + // With a policy, make sure that all attributes pass. > > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > > + &mTestGuid1, > > + VARIABLE_ATTRIBUTE_NV_BS_RT, > > + sizeof(DummyData), > > + DummyData ); > > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); > > + > > + // With a policy, make sure that all attributes -- plus some -- pass. > > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > > + &mTestGuid1, > > + VARIABLE_ATTRIBUTE_NV_BS_RT_AT, > > + sizeof(DummyData), > > + DummyData ); > > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); > > + > > + return UNIT_TEST_PASSED; > > +} > > + > > +/** > > + Test Case > > +*/ > > +UNIT_TEST_STATUS > > +EFIAPI > > +AttributeCantPoliciesShouldBeHonored ( > > + IN UNIT_TEST_CONTEXT Context > > + ) > > +{ > > + SIMPLE_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { > > + { > > + VARIABLE_POLICY_ENTRY_REVISION, > > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME), > > + sizeof(VARIABLE_POLICY_ENTRY), > > + TEST_GUID_1, > > + TEST_POLICY_MIN_SIZE_NULL, > > + TEST_POLICY_MAX_SIZE_NULL, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS, > > + VARIABLE_POLICY_TYPE_NO_LOCK > > + }, > > + TEST_VAR_1_NAME > > + }; > > + EFI_STATUS PolicyCheck; > > + UINT8 DummyData[12]; > > + > > + > > + // Without a policy, there should be no constraints on variable creat= ion. > > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > > + &mTestGuid1, > > + VARIABLE_ATTRIBUTE_BS_RT_AT, > > + sizeof(DummyData), > > + DummyData ); > > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); > > + > > + // Set a policy to test against. > > + > UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea > der ) ); > > + > > + // With a policy, make sure that forbidden attributes fail. > > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > > + &mTestGuid1, > > + > EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS, > > + sizeof(DummyData), > > + DummyData ); > > + UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) ); > > + > > + // With a policy, make sure that a mixture of attributes -- including= the > forbidden -- fail. > > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > > + &mTestGuid1, > > + VARIABLE_ATTRIBUTE_BS_RT_AT, > > + sizeof(DummyData), > > + DummyData ); > > + UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) ); > > + > > + // With a policy, make sure that attributes without the forbidden pas= s. > > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > > + &mTestGuid1, > > + VARIABLE_ATTRIBUTE_NV_BS_RT, > > + sizeof(DummyData), > > + DummyData ); > > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); > > + > > + return UNIT_TEST_PASSED; > > +} > > + > > +/** > > + Test Case > > +*/ > > +UNIT_TEST_STATUS > > +EFIAPI > > +VariablesShouldBeDeletableRegardlessOfSize ( > > + IN UNIT_TEST_CONTEXT Context > > + ) > > +{ > > + SIMPLE_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { > > + { > > + VARIABLE_POLICY_ENTRY_REVISION, > > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME), > > + sizeof(VARIABLE_POLICY_ENTRY), > > + TEST_GUID_1, > > + TEST_POLICY_MIN_SIZE_10, > > + TEST_POLICY_MAX_SIZE_NULL, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS, > > + VARIABLE_POLICY_TYPE_NO_LOCK > > + }, > > + TEST_VAR_1_NAME > > + }; > > + EFI_STATUS PolicyCheck; > > + UINT8 DummyData[TEST_POLICY_MAX_SIZE_200+1]; > > + > > + // Create a policy enforcing a minimum variable size. > > + > UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea > der ) ); > > + > > + // Make sure that a normal set would fail. > > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > > + &mTestGuid1, > > + VARIABLE_ATTRIBUTE_NV_BS, > > + TEST_POLICY_MIN_SIZE_10-1, > > + DummyData ); > > + UT_ASSERT_STATUS_EQUAL( PolicyCheck, EFI_INVALID_PARAMETER ); > > + > > + // Now make sure that a delete would succeed. > > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > > + &mTestGuid1, > > + VARIABLE_ATTRIBUTE_NV_BS, > > + 0, > > + NULL ); > > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); > > + > > + return UNIT_TEST_PASSED; > > +} > > + > > +/** > > + Test Case > > +*/ > > +UNIT_TEST_STATUS > > +EFIAPI > > +LockNowPoliciesShouldBeHonored ( > > + IN UNIT_TEST_CONTEXT Context > > + ) > > +{ > > + SIMPLE_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { > > + { > > + VARIABLE_POLICY_ENTRY_REVISION, > > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME), > > + sizeof(VARIABLE_POLICY_ENTRY), > > + TEST_GUID_1, > > + TEST_POLICY_MIN_SIZE_NULL, > > + TEST_POLICY_MAX_SIZE_NULL, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + VARIABLE_POLICY_TYPE_LOCK_NOW > > + }, > > + TEST_VAR_1_NAME > > + }; > > + EFI_STATUS PolicyCheck; > > + UINT8 DummyData[12]; > > + > > + > > + // Without a policy, there should be no constraints on variable creat= ion. > > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > > + &mTestGuid1, > > + VARIABLE_ATTRIBUTE_BS_RT_AT, > > + sizeof(DummyData), > > + DummyData ); > > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); > > + > > + // Set a policy to test against. > > + > UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea > der ) ); > > + > > + // With a policy, make sure that writes immediately fail. > > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > > + &mTestGuid1, > > + VARIABLE_ATTRIBUTE_BS_RT_AT, > > + sizeof(DummyData), > > + DummyData ); > > + UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) ); > > + > > + return UNIT_TEST_PASSED; > > +} > > + > > +/** > > + Test Case > > +*/ > > +UNIT_TEST_STATUS > > +EFIAPI > > +LockOnCreatePoliciesShouldBeHonored ( > > + IN UNIT_TEST_CONTEXT Context > > + ) > > +{ > > + SIMPLE_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { > > + { > > + VARIABLE_POLICY_ENTRY_REVISION, > > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME), > > + sizeof(VARIABLE_POLICY_ENTRY), > > + TEST_GUID_1, > > + TEST_POLICY_MIN_SIZE_NULL, > > + TEST_POLICY_MAX_SIZE_NULL, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + VARIABLE_POLICY_TYPE_LOCK_ON_CREATE > > + }, > > + TEST_VAR_1_NAME > > + }; > > + EFI_STATUS PolicyCheck; > > + UINT8 DummyData[12]; > > + UINTN ExpectedDataSize; > > + > > + > > + // Without a policy, there should be no constraints on variable creat= ion. > > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > > + &mTestGuid1, > > + VARIABLE_ATTRIBUTE_BS_RT_AT, > > + sizeof(DummyData), > > + DummyData ); > > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); > > + > > + // Set a policy to test against. > > + > UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea > der ) ); > > + > > + // Set consistent expectations on what the calls are looking for. > > + expect_memory_count( StubGetVariableNull, VariableName, > TEST_VAR_1_NAME, sizeof(TEST_VAR_1_NAME), 2 ); > > + expect_memory_count( StubGetVariableNull, VendorGuid, &mTestGuid1, > sizeof(mTestGuid1), 2 ); > > + ExpectedDataSize =3D 0; > > + expect_memory_count( StubGetVariableNull, DataSize, > &ExpectedDataSize, sizeof(ExpectedDataSize), 2 ); > > + > > + // With a policy, make sure that writes still work, since the variabl= e doesn't > exist. > > + will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL ); /= / > Attributes > > + will_return( StubGetVariableNull, 0 ); /= / Size > > + will_return( StubGetVariableNull, NULL ); /= / DataPtr > > + will_return( StubGetVariableNull, EFI_NOT_FOUND ); /= / Status > > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > > + &mTestGuid1, > > + VARIABLE_ATTRIBUTE_BS_RT_AT, > > + sizeof(DummyData), > > + DummyData ); > > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); > > + > > + // With a policy, make sure that a call with an "existing" variable f= ails. > > + will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL ); /= / > Attributes > > + will_return( StubGetVariableNull, 10 ); /= / Size > > + will_return( StubGetVariableNull, NULL ); /= / DataPtr > > + will_return( StubGetVariableNull, EFI_BUFFER_TOO_SMALL ); /= / > Status > > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > > + &mTestGuid1, > > + VARIABLE_ATTRIBUTE_BS_RT_AT, > > + sizeof(DummyData), > > + DummyData ); > > + UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) ); > > + > > + return UNIT_TEST_PASSED; > > +} > > + > > +/** > > + Test Case > > +*/ > > +UNIT_TEST_STATUS > > +EFIAPI > > +LockOnStatePoliciesShouldBeHonored ( > > + IN UNIT_TEST_CONTEXT Context > > + ) > > +{ > > + EXPANDED_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { > > + { > > + VARIABLE_POLICY_ENTRY_REVISION, > > + 0, // Will be populated by init helper. > > + 0, // Will be populated by init helper. > > + TEST_GUID_1, > > + TEST_POLICY_MIN_SIZE_NULL, > > + TEST_POLICY_MAX_SIZE_NULL, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE > > + }, > > + { > > + TEST_GUID_2, > > + 20, // Value > > + 0 // Padding > > + }, > > + L"", > > + L"" > > + }; > > + EFI_STATUS PolicyCheck; > > + UINT8 DummyData[12]; > > + UINT8 ValidationStateVar; > > + UINTN ExpectedDataSize; > > + UT_ASSERT_TRUE( InitExpVarPolicyStrings( &ValidationPolicy, > TEST_VAR_1_NAME, TEST_VAR_2_NAME ) ); > > + > > + > > + // Without a policy, there should be no constraints on variable creat= ion. > > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > > + &mTestGuid1, > > + VARIABLE_ATTRIBUTE_BS_RT_AT, > > + sizeof(DummyData), > > + DummyData ); > > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); > > + > > + // Set a policy to test against. > > + > UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea > der ) ); > > + > > + // Set consistent expectations on what the calls are looking for. > > + expect_memory_count( StubGetVariableNull, VariableName, > TEST_VAR_2_NAME, sizeof(TEST_VAR_2_NAME), 5 ); > > + expect_memory_count( StubGetVariableNull, VendorGuid, &mTestGuid2, > sizeof(mTestGuid2), 5 ); > > + ExpectedDataSize =3D 1; > > + expect_memory_count( StubGetVariableNull, DataSize, > &ExpectedDataSize, sizeof(ExpectedDataSize), 5 ); > > + > > + // With a policy, make sure that writes still work, since the variabl= e doesn't > exist. > > + will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL ); /= / > Attributes > > + will_return( StubGetVariableNull, 0 ); /= / Size > > + will_return( StubGetVariableNull, NULL ); /= / DataPtr > > + will_return( StubGetVariableNull, EFI_NOT_FOUND ); /= / Status > > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > > + &mTestGuid1, > > + VARIABLE_ATTRIBUTE_BS_RT_AT, > > + sizeof(DummyData), > > + DummyData ); > > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); > > + > > + // With a policy, make sure that a state variable that's too large do= esn't lock > the variable. > > + will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL ); /= / > Attributes > > + will_return( StubGetVariableNull, 10 ); /= / Size > > + will_return( StubGetVariableNull, NULL ); /= / DataPtr > > + will_return( StubGetVariableNull, EFI_BUFFER_TOO_SMALL ); /= / > Status > > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > > + &mTestGuid1, > > + VARIABLE_ATTRIBUTE_BS_RT_AT, > > + sizeof(DummyData), > > + DummyData ); > > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); > > + > > + // With a policy, check a state variable with the wrong value. > > + ValidationStateVar =3D 0; > > + will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL ); /= / > Attributes > > + will_return( StubGetVariableNull, sizeof(ValidationStateVar) ); /= / Size > > + will_return( StubGetVariableNull, &ValidationStateVar ); /= / DataPtr > > + will_return( StubGetVariableNull, EFI_SUCCESS ); /= / Status > > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > > + &mTestGuid1, > > + VARIABLE_ATTRIBUTE_BS_RT_AT, > > + sizeof(DummyData), > > + DummyData ); > > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); > > + > > + // With a policy, check a state variable with another wrong value. > > + ValidationStateVar =3D 10; > > + will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL ); /= / > Attributes > > + will_return( StubGetVariableNull, sizeof(ValidationStateVar) ); /= / Size > > + will_return( StubGetVariableNull, &ValidationStateVar ); /= / DataPtr > > + will_return( StubGetVariableNull, EFI_SUCCESS ); /= / Status > > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > > + &mTestGuid1, > > + VARIABLE_ATTRIBUTE_BS_RT_AT, > > + sizeof(DummyData), > > + DummyData ); > > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); > > + > > + // With a policy, make sure that a call with a correct state variable= fails. > > + ValidationStateVar =3D 20; > > + will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL ); /= / > Attributes > > + will_return( StubGetVariableNull, sizeof(ValidationStateVar) ); /= / Size > > + will_return( StubGetVariableNull, &ValidationStateVar ); /= / DataPtr > > + will_return( StubGetVariableNull, EFI_SUCCESS ); /= / Status > > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > > + &mTestGuid1, > > + VARIABLE_ATTRIBUTE_BS_RT_AT, > > + sizeof(DummyData), > > + DummyData ); > > + UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) ); > > + > > + return UNIT_TEST_PASSED; > > +} > > + > > +/** > > + Test Case > > +*/ > > +UNIT_TEST_STATUS > > +EFIAPI > > +LockOnStatePoliciesShouldApplyToNamespaces ( > > + IN UNIT_TEST_CONTEXT Context > > + ) > > +{ > > + EXPANDED_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { > > + { > > + VARIABLE_POLICY_ENTRY_REVISION, > > + 0, // Will be populated by init helper. > > + 0, // Will be populated by init helper. > > + TEST_GUID_1, > > + TEST_POLICY_MIN_SIZE_NULL, > > + TEST_POLICY_MAX_SIZE_NULL, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE > > + }, > > + { > > + TEST_GUID_2, > > + 20, // Value > > + 0 // Padding > > + }, > > + L"", > > + L"" > > + }; > > + EFI_STATUS PolicyCheck; > > + UINT8 DummyData[12]; > > + UINT8 ValidationStateVar; > > + UINTN ExpectedDataSize; > > + UT_ASSERT_TRUE( InitExpVarPolicyStrings( &ValidationPolicy, NULL, > TEST_VAR_2_NAME ) ); > > + > > + > > + // Without a policy, there should be no constraints on variable creat= ion. > > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > > + &mTestGuid1, > > + VARIABLE_ATTRIBUTE_BS_RT_AT, > > + sizeof(DummyData), > > + DummyData ); > > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); > > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_3_NAME, > > + &mTestGuid1, > > + VARIABLE_ATTRIBUTE_BS_RT_AT, > > + sizeof(DummyData), > > + DummyData ); > > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); > > + > > + // Set a policy to test against. > > + > UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea > der ) ); > > + > > + // Set consistent expectations on what the calls are looking for. > > + expect_memory_count( StubGetVariableNull, VariableName, > TEST_VAR_2_NAME, sizeof(TEST_VAR_2_NAME), 4 ); > > + expect_memory_count( StubGetVariableNull, VendorGuid, &mTestGuid2, > sizeof(mTestGuid2), 4 ); > > + ExpectedDataSize =3D 1; > > + expect_memory_count( StubGetVariableNull, DataSize, > &ExpectedDataSize, sizeof(ExpectedDataSize), 4 ); > > + > > + // With a policy, make sure that writes still work, since the variabl= e doesn't > exist. > > + will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL ); /= / > Attributes > > + will_return( StubGetVariableNull, 0 ); /= / Size > > + will_return( StubGetVariableNull, NULL ); /= / DataPtr > > + will_return( StubGetVariableNull, EFI_NOT_FOUND ); /= / Status > > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > > + &mTestGuid1, > > + VARIABLE_ATTRIBUTE_BS_RT_AT, > > + sizeof(DummyData), > > + DummyData ); > > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); > > + will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL ); /= / > Attributes > > + will_return( StubGetVariableNull, 0 ); /= / Size > > + will_return( StubGetVariableNull, NULL ); /= / DataPtr > > + will_return( StubGetVariableNull, EFI_NOT_FOUND ); /= / Status > > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_3_NAME, > > + &mTestGuid1, > > + VARIABLE_ATTRIBUTE_BS_RT_AT, > > + sizeof(DummyData), > > + DummyData ); > > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); > > + > > + // With a policy, make sure that a call with a correct state variable= fails. > > + ValidationStateVar =3D 20; > > + will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL ); /= / > Attributes > > + will_return( StubGetVariableNull, sizeof(ValidationStateVar) ); /= / Size > > + will_return( StubGetVariableNull, &ValidationStateVar ); /= / DataPtr > > + will_return( StubGetVariableNull, EFI_SUCCESS ); /= / Status > > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > > + &mTestGuid1, > > + VARIABLE_ATTRIBUTE_BS_RT_AT, > > + sizeof(DummyData), > > + DummyData ); > > + UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) ); > > + will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL ); /= / > Attributes > > + will_return( StubGetVariableNull, sizeof(ValidationStateVar) ); /= / Size > > + will_return( StubGetVariableNull, &ValidationStateVar ); /= / DataPtr > > + will_return( StubGetVariableNull, EFI_SUCCESS ); /= / Status > > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_3_NAME, > > + &mTestGuid1, > > + VARIABLE_ATTRIBUTE_BS_RT_AT, > > + sizeof(DummyData), > > + DummyData ); > > + UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) ); > > + > > + return UNIT_TEST_PASSED; > > +} > > + > > +/** > > + Test Case > > +*/ > > +UNIT_TEST_STATUS > > +EFIAPI > > +LockOnStateShouldHandleErrorsGracefully ( > > + IN UNIT_TEST_CONTEXT Context > > + ) > > +{ > > + EXPANDED_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { > > + { > > + VARIABLE_POLICY_ENTRY_REVISION, > > + 0, // Will be populated by init helper. > > + 0, // Will be populated by init helper. > > + TEST_GUID_1, > > + TEST_POLICY_MIN_SIZE_NULL, > > + TEST_POLICY_MAX_SIZE_NULL, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE > > + }, > > + { > > + TEST_GUID_2, > > + 20, // Value > > + 0 // Padding > > + }, > > + L"", > > + L"" > > + }; > > + EFI_STATUS PolicyCheck; > > + UINT8 DummyData[12]; > > + UT_ASSERT_TRUE( InitExpVarPolicyStrings( &ValidationPolicy, > TEST_VAR_1_NAME, TEST_VAR_2_NAME ) ); > > + > > + > > + // Without a policy, there should be no constraints on variable creat= ion. > > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > > + &mTestGuid1, > > + VARIABLE_ATTRIBUTE_BS_RT_AT, > > + sizeof(DummyData), > > + DummyData ); > > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); > > + > > + // Set a policy to test against. > > + > UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea > der ) ); > > + > > + // Configure the stub to not care about parameters. We're testing err= ors. > > + expect_any_always( StubGetVariableNull, VariableName ); > > + expect_any_always( StubGetVariableNull, VendorGuid ); > > + expect_any_always( StubGetVariableNull, DataSize ); > > + > > + // With a policy, make sure that writes still work, since the variabl= e doesn't > exist. > > + will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL ); /= / > Attributes > > + will_return( StubGetVariableNull, 0 ); /= / Size > > + will_return( StubGetVariableNull, NULL ); /= / DataPtr > > + will_return( StubGetVariableNull, EFI_NOT_FOUND ); /= / Status > > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > > + &mTestGuid1, > > + VARIABLE_ATTRIBUTE_BS_RT_AT, > > + sizeof(DummyData), > > + DummyData ); > > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); > > + > > + // Verify that state variables that are the wrong size won't lock the= variable. > > + will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL ); /= / > Attributes > > + will_return( StubGetVariableNull, 0 ); /= / Size > > + will_return( StubGetVariableNull, NULL ); /= / DataPtr > > + will_return( StubGetVariableNull, EFI_BUFFER_TOO_SMALL ); /= / > Status > > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > > + &mTestGuid1, > > + VARIABLE_ATTRIBUTE_BS_RT_AT, > > + sizeof(DummyData), > > + DummyData ); > > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); > > + > > + // Verify that unexpected errors default to locked. > > + will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL ); /= / > Attributes > > + will_return( StubGetVariableNull, 0 ); /= / Size > > + will_return( StubGetVariableNull, NULL ); /= / DataPtr > > + will_return( StubGetVariableNull, EFI_UNSUPPORTED ); /= / Status > > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > > + &mTestGuid1, > > + VARIABLE_ATTRIBUTE_BS_RT_AT, > > + sizeof(DummyData), > > + DummyData ); > > + UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) ); > > + > > + will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL ); /= / > Attributes > > + will_return( StubGetVariableNull, 0 ); /= / Size > > + will_return( StubGetVariableNull, NULL ); /= / DataPtr > > + will_return( StubGetVariableNull, EFI_NOT_READY ); /= / Status > > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > > + &mTestGuid1, > > + VARIABLE_ATTRIBUTE_BS_RT_AT, > > + sizeof(DummyData), > > + DummyData ); > > + UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) ); > > + > > + return UNIT_TEST_PASSED; > > +} > > + > > +/** > > + Test Case > > +*/ > > +UNIT_TEST_STATUS > > +EFIAPI > > +BestMatchPriorityShouldBeObeyed ( > > + IN UNIT_TEST_CONTEXT Context > > + ) > > +{ > > + SIMPLE_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { > > + { > > + VARIABLE_POLICY_ENTRY_REVISION, > > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(L"Wild12Card34Placeholder"= ), > > + sizeof(VARIABLE_POLICY_ENTRY), > > + TEST_GUID_1, > > + TEST_POLICY_MIN_SIZE_NULL, > > + TEST_POLICY_MAX_SIZE_NULL, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + VARIABLE_POLICY_TYPE_NO_LOCK > > + }, > > + L"Wild12Card34Placeholder" > > + }; > > + EFI_STATUS PolicyCheck; > > + UINT8 DummyData[70]; > > + CHAR16 *PolicyName =3D (CHAR16*)((UINT8*)&ValidationPolicy + > sizeof(VARIABLE_POLICY_ENTRY)); > > + UINTN PolicyNameSize =3D sizeof(L"Wild12Card34Placeholder"); > > + CHAR16 *FourWildcards =3D L"Wild##Card##Placeholder"; > > + CHAR16 *ThreeWildcards =3D L"Wild##Card#4Placeholder"; > > + CHAR16 *TwoWildcards =3D L"Wild##Card34Placeholder"; > > + CHAR16 *OneWildcard =3D L"Wild#2Card34Placeholder"; > > + CHAR16 *NoWildcards =3D L"Wild12Card34Placeholder"; > > + > > + // Create all of the policies from least restrictive to most restrict= ive. > > + // NoWildcards should be the most restrictive. > > + ValidationPolicy.Header.MaxSize =3D 60; > > + ValidationPolicy.Header.Size =3D ValidationPolicy.Header.OffsetToName= ; > > + > UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea > der ) ); > > + ValidationPolicy.Header.Size +=3D (UINT16)PolicyNameSize; > > + ValidationPolicy.Header.MaxSize =3D 50; > > + CopyMem( PolicyName, FourWildcards, PolicyNameSize ); > > + > UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea > der ) ); > > + ValidationPolicy.Header.MaxSize =3D 40; > > + CopyMem( PolicyName, ThreeWildcards, PolicyNameSize ); > > + > UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea > der ) ); > > + ValidationPolicy.Header.MaxSize =3D 30; > > + CopyMem( PolicyName, TwoWildcards, PolicyNameSize ); > > + > UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea > der ) ); > > + ValidationPolicy.Header.MaxSize =3D 20; > > + CopyMem( PolicyName, OneWildcard, PolicyNameSize ); > > + > UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea > der ) ); > > + ValidationPolicy.Header.MaxSize =3D 10; > > + CopyMem( PolicyName, NoWildcards, PolicyNameSize ); > > + > UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea > der ) ); > > + > > + // Verify that variables only matching the namespace have the most > flexible policy. > > + PolicyCheck =3D ValidateSetVariable( L"ArbitraryName", > > + &mTestGuid1, > > + VARIABLE_ATTRIBUTE_BS_RT_AT, > > + 65, > > + DummyData ); > > + UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) ); > > + PolicyCheck =3D ValidateSetVariable( L"ArbitraryName", > > + &mTestGuid1, > > + VARIABLE_ATTRIBUTE_BS_RT_AT, > > + 55, > > + DummyData ); > > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); > > + > > + // Verify that variables matching increasing characters get increasin= g policy > restrictions. > > + PolicyCheck =3D ValidateSetVariable( L"Wild77Card77Placeholder", > > + &mTestGuid1, > > + VARIABLE_ATTRIBUTE_BS_RT_AT, > > + 55, > > + DummyData ); > > + UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) ); > > + PolicyCheck =3D ValidateSetVariable( L"Wild77Card77Placeholder", > > + &mTestGuid1, > > + VARIABLE_ATTRIBUTE_BS_RT_AT, > > + 45, > > + DummyData ); > > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); > > + > > + PolicyCheck =3D ValidateSetVariable( L"Wild77Card74Placeholder", > > + &mTestGuid1, > > + VARIABLE_ATTRIBUTE_BS_RT_AT, > > + 45, > > + DummyData ); > > + UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) ); > > + PolicyCheck =3D ValidateSetVariable( L"Wild77Card74Placeholder", > > + &mTestGuid1, > > + VARIABLE_ATTRIBUTE_BS_RT_AT, > > + 35, > > + DummyData ); > > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); > > + > > + PolicyCheck =3D ValidateSetVariable( L"Wild77Card34Placeholder", > > + &mTestGuid1, > > + VARIABLE_ATTRIBUTE_BS_RT_AT, > > + 35, > > + DummyData ); > > + UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) ); > > + PolicyCheck =3D ValidateSetVariable( L"Wild77Card34Placeholder", > > + &mTestGuid1, > > + VARIABLE_ATTRIBUTE_BS_RT_AT, > > + 25, > > + DummyData ); > > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); > > + > > + PolicyCheck =3D ValidateSetVariable( L"Wild72Card34Placeholder", > > + &mTestGuid1, > > + VARIABLE_ATTRIBUTE_BS_RT_AT, > > + 25, > > + DummyData ); > > + UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) ); > > + PolicyCheck =3D ValidateSetVariable( L"Wild72Card34Placeholder", > > + &mTestGuid1, > > + VARIABLE_ATTRIBUTE_BS_RT_AT, > > + 15, > > + DummyData ); > > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); > > + > > + PolicyCheck =3D ValidateSetVariable( L"Wild12Card34Placeholder", > > + &mTestGuid1, > > + VARIABLE_ATTRIBUTE_BS_RT_AT, > > + 15, > > + DummyData ); > > + UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) ); > > + PolicyCheck =3D ValidateSetVariable( L"Wild12Card34Placeholder", > > + &mTestGuid1, > > + VARIABLE_ATTRIBUTE_BS_RT_AT, > > + 5, > > + DummyData ); > > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); > > + > > + return UNIT_TEST_PASSED; > > +} > > + > > + > > +///=3D=3D=3D POLICY UTILITY SUITE > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D > > + > > +/** > > + Test Case > > +*/ > > +UNIT_TEST_STATUS > > +EFIAPI > > +ShouldBeAbleToLockInterface ( > > + IN UNIT_TEST_CONTEXT Context > > + ) > > +{ > > + SIMPLE_VARIABLE_POLICY_ENTRY TestPolicy =3D { > > + { > > + VARIABLE_POLICY_ENTRY_REVISION, > > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME), > > + sizeof(VARIABLE_POLICY_ENTRY), > > + TEST_GUID_1, > > + TEST_POLICY_MIN_SIZE_NULL, > > + TEST_POLICY_MAX_SIZE_NULL, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + VARIABLE_POLICY_TYPE_NO_LOCK > > + }, > > + TEST_VAR_1_NAME > > + }; > > + > > + // Make sure it's not already locked. > > + UT_ASSERT_FALSE( IsVariablePolicyInterfaceLocked() ); > > + // Lock it. > > + UT_ASSERT_NOT_EFI_ERROR( LockVariablePolicy() ); > > + // Verify that it's locked. > > + UT_ASSERT_TRUE( IsVariablePolicyInterfaceLocked() ); > > + > > + // Verify that all state-changing commands fail. > > + UT_ASSERT_TRUE( EFI_ERROR( LockVariablePolicy() ) ); > > + UT_ASSERT_TRUE( EFI_ERROR( DisableVariablePolicy() ) ); > > + > UT_ASSERT_TRUE( EFI_ERROR( RegisterVariablePolicy( &TestPolicy.Header ) > ) ); > > + > > + return UNIT_TEST_PASSED; > > +} > > + > > +/** > > + Test Case > > +*/ > > +UNIT_TEST_STATUS > > +EFIAPI > > +ShouldBeAbleToDisablePolicyEnforcement ( > > + IN UNIT_TEST_CONTEXT Context > > + ) > > +{ > > + SIMPLE_VARIABLE_POLICY_ENTRY TestPolicy =3D { > > + { > > + VARIABLE_POLICY_ENTRY_REVISION, > > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME), > > + sizeof(VARIABLE_POLICY_ENTRY), > > + TEST_GUID_1, > > + TEST_POLICY_MIN_SIZE_10, > > + TEST_POLICY_MAX_SIZE_200, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + VARIABLE_POLICY_TYPE_NO_LOCK > > + }, > > + TEST_VAR_1_NAME > > + }; > > + EFI_STATUS PolicyCheck; > > + UINT8 DummyData[TEST_POLICY_MIN_SIZE_10-1]; > > + > > + // Make sure that the policy enforcement is currently enabled. > > + UT_ASSERT_TRUE( IsVariablePolicyEnabled() ); > > + // Add a policy before it's disabled. > > + > UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &TestPolicy.Header ) ); > > + // Disable the policy enforcement. > > + UT_ASSERT_NOT_EFI_ERROR( DisableVariablePolicy() ); > > + // Make sure that the policy enforcement is currently disabled. > > + UT_ASSERT_FALSE( IsVariablePolicyEnabled() ); > > + > > + // Check to make sure that a policy violation still passes. > > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > > + &mTestGuid1, > > + VARIABLE_ATTRIBUTE_NV_BS, > > + sizeof(DummyData), > > + DummyData ); > > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); > > + > > + return UNIT_TEST_PASSED; > > +} > > + > > +/** > > + Test Case > > +*/ > > +UNIT_TEST_STATUS > > +EFIAPI > > +ShouldNotBeAbleToDisablePoliciesTwice ( > > + IN UNIT_TEST_CONTEXT Context > > + ) > > +{ > > + // Make sure that the policy enforcement is currently enabled. > > + UT_ASSERT_TRUE( IsVariablePolicyEnabled() ); > > + // Disable the policy enforcement. > > + UT_ASSERT_NOT_EFI_ERROR( DisableVariablePolicy() ); > > + // Make sure that the policy enforcement is currently disabled. > > + UT_ASSERT_FALSE( IsVariablePolicyEnabled() ); > > + // Try to disable again and verify failure. > > + UT_ASSERT_TRUE( EFI_ERROR( DisableVariablePolicy() ) ); > > + > > + return UNIT_TEST_PASSED; > > +} > > + > > +/** > > + Test Case > > +*/ > > +UNIT_TEST_STATUS > > +EFIAPI > > +ShouldBeAbleToAddNewPoliciesAfterDisabled ( > > + IN UNIT_TEST_CONTEXT Context > > + ) > > +{ > > + SIMPLE_VARIABLE_POLICY_ENTRY TestPolicy =3D { > > + { > > + VARIABLE_POLICY_ENTRY_REVISION, > > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME), > > + sizeof(VARIABLE_POLICY_ENTRY), > > + TEST_GUID_1, > > + TEST_POLICY_MIN_SIZE_10, > > + TEST_POLICY_MAX_SIZE_200, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + VARIABLE_POLICY_TYPE_NO_LOCK > > + }, > > + TEST_VAR_1_NAME > > + }; > > + EFI_STATUS PolicyCheck; > > + > > + // Make sure that the policy enforcement is currently enabled. > > + UT_ASSERT_TRUE( IsVariablePolicyEnabled() ); > > + // Disable the policy enforcement. > > + UT_ASSERT_NOT_EFI_ERROR( DisableVariablePolicy() ); > > + > > + // Make sure that new policy creation still works, it just won't be e= nforced. > > + PolicyCheck =3D RegisterVariablePolicy( &TestPolicy.Header ); > > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); > > + > > + return UNIT_TEST_PASSED; > > +} > > + > > +/** > > + Test Case > > +*/ > > +UNIT_TEST_STATUS > > +EFIAPI > > +ShouldBeAbleToLockAfterDisabled ( > > + IN UNIT_TEST_CONTEXT Context > > + ) > > +{ > > + // Make sure that the policy enforcement is currently enabled. > > + UT_ASSERT_TRUE( IsVariablePolicyEnabled() ); > > + // Disable the policy enforcement. > > + UT_ASSERT_NOT_EFI_ERROR( DisableVariablePolicy() ); > > + > > + // Make sure that we can lock in this state. > > + UT_ASSERT_FALSE( IsVariablePolicyInterfaceLocked() ); > > + UT_ASSERT_NOT_EFI_ERROR( LockVariablePolicy() ); > > + UT_ASSERT_TRUE( IsVariablePolicyInterfaceLocked() ); > > + > > + return UNIT_TEST_PASSED; > > +} > > + > > +/** > > + Test Case > > +*/ > > +UNIT_TEST_STATUS > > +EFIAPI > > +ShouldBeAbleToDumpThePolicyTable ( > > + IN UNIT_TEST_CONTEXT Context > > + ) > > +{ > > + SIMPLE_VARIABLE_POLICY_ENTRY TestPolicy =3D { > > + { > > + VARIABLE_POLICY_ENTRY_REVISION, > > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME), > > + sizeof(VARIABLE_POLICY_ENTRY), > > + TEST_GUID_1, > > + TEST_POLICY_MIN_SIZE_10, > > + TEST_POLICY_MAX_SIZE_200, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + VARIABLE_POLICY_TYPE_NO_LOCK > > + }, > > + TEST_VAR_1_NAME > > + }; > > + EFI_STATUS PolicyCheck; > > + UINT32 DumpSize; > > + UINT32 BufferSize; > > + VOID *DumpBuffer; > > + > > + // For good measure, test some parameter validation. > > + UT_ASSERT_STATUS_EQUAL( DumpVariablePolicy( NULL, NULL ), > EFI_INVALID_PARAMETER ); > > + DumpSize =3D 10; > > + UT_ASSERT_STATUS_EQUAL( DumpVariablePolicy( NULL, &DumpSize ), > EFI_INVALID_PARAMETER ); > > + > > + // Now for the actual test case. > > + > > + // Allocate a buffer to hold the output. > > + BufferSize =3D sizeof(VARIABLE_POLICY_ENTRY) + > sizeof(TEST_VAR_1_NAME); > > + DumpBuffer =3D AllocatePool( BufferSize ); > > + UT_ASSERT_NOT_EQUAL( DumpBuffer, NULL ); > > + > > + // Verify that the current table size is 0. > > + DumpSize =3D BufferSize; > > + UT_ASSERT_NOT_EFI_ERROR( DumpVariablePolicy( DumpBuffer, > &DumpSize ) ); > > + UT_ASSERT_EQUAL( DumpSize, 0 ); > > + > > + // Now, set a new policy. > > + > UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &TestPolicy.Header ) ); > > + > > + // Make sure that the new return is non-zero and fails as expected. > > + DumpSize =3D 0; > > + PolicyCheck =3D DumpVariablePolicy( NULL, &DumpSize ); > > + UT_ASSERT_STATUS_EQUAL( PolicyCheck, EFI_BUFFER_TOO_SMALL ); > > + UT_ASSERT_EQUAL( DumpSize, BufferSize ); > > + > > + // Now verify that we can fetch the dump. > > + DumpSize =3D BufferSize; > > + UT_ASSERT_NOT_EFI_ERROR( DumpVariablePolicy( DumpBuffer, > &DumpSize ) ); > > + UT_ASSERT_EQUAL( DumpSize, BufferSize ); > > + UT_ASSERT_MEM_EQUAL( &TestPolicy, DumpBuffer, BufferSize ); > > + > > + // Always put away your toys. > > + FreePool( DumpBuffer ); > > + > > + return UNIT_TEST_PASSED; > > +} > > + > > +/** > > + Test Case > > +*/ > > +UNIT_TEST_STATUS > > +EFIAPI > > +ShouldBeAbleToDumpThePolicyTableAfterDisabled ( > > + IN UNIT_TEST_CONTEXT Context > > + ) > > +{ > > + SIMPLE_VARIABLE_POLICY_ENTRY TestPolicy =3D { > > + { > > + VARIABLE_POLICY_ENTRY_REVISION, > > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME), > > + sizeof(VARIABLE_POLICY_ENTRY), > > + TEST_GUID_1, > > + TEST_POLICY_MIN_SIZE_10, > > + TEST_POLICY_MAX_SIZE_200, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + VARIABLE_POLICY_TYPE_NO_LOCK > > + }, > > + TEST_VAR_1_NAME > > + }; > > + SIMPLE_VARIABLE_POLICY_ENTRY TestPolicy2 =3D { > > + { > > + VARIABLE_POLICY_ENTRY_REVISION, > > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_2_NAME), > > + sizeof(VARIABLE_POLICY_ENTRY), > > + TEST_GUID_2, > > + TEST_POLICY_MIN_SIZE_10, > > + TEST_POLICY_MAX_SIZE_200, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + TEST_POLICY_ATTRIBUTES_NULL, > > + VARIABLE_POLICY_TYPE_NO_LOCK > > + }, > > + TEST_VAR_2_NAME > > + }; > > + EFI_STATUS PolicyCheck; > > + UINT32 DumpSize; > > + VOID *DumpBuffer; > > + > > + DumpBuffer =3D NULL; > > + DumpSize =3D 0; > > + > > + // Register a new policy. > > + > UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &TestPolicy.Header ) ); > > + // Make sure that we can dump the policy. > > + PolicyCheck =3D DumpVariablePolicy( DumpBuffer, &DumpSize ); > > + UT_ASSERT_STATUS_EQUAL( PolicyCheck, EFI_BUFFER_TOO_SMALL ); > > + DumpBuffer =3D AllocatePool( DumpSize ); > > + UT_ASSERT_NOT_EFI_ERROR( DumpVariablePolicy( DumpBuffer, > &DumpSize ) ); > > + UT_ASSERT_MEM_EQUAL( DumpBuffer, &TestPolicy, DumpSize ); > > + > > + // Clean up from this step. > > + FreePool( DumpBuffer ); > > + DumpBuffer =3D NULL; > > + DumpSize =3D 0; > > + > > + // Now disable the engine. > > + DisableVariablePolicy(); > > + > > + // Now register a new policy and make sure that both can be dumped. > > + > UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &TestPolicy2.Header ) > ); > > + // Make sure that we can dump the policy. > > + PolicyCheck =3D DumpVariablePolicy( DumpBuffer, &DumpSize ); > > + UT_ASSERT_STATUS_EQUAL( PolicyCheck, EFI_BUFFER_TOO_SMALL ); > > + DumpBuffer =3D AllocatePool( DumpSize ); > > + UT_ASSERT_NOT_EFI_ERROR( DumpVariablePolicy( DumpBuffer, > &DumpSize ) ); > > + > > + // Finally, make sure that both policies are in the dump. > > + UT_ASSERT_MEM_EQUAL( DumpBuffer, &TestPolicy, > TestPolicy.Header.Size ); > > + UT_ASSERT_MEM_EQUAL( (UINT8*)DumpBuffer + TestPolicy.Header.Size, > > + &TestPolicy2, > > + TestPolicy2.Header.Size ); > > + > > + // Always put away your toys. > > + FreePool( DumpBuffer ); > > + > > + return UNIT_TEST_PASSED; > > +} > > + > > + > > +///=3D=3D=3D TEST ENGINE > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > > + > > +/** > > + SampleUnitTestApp > > + > > + @param[in] ImageHandle The firmware allocated handle for the EFI ima= ge. > > + @param[in] SystemTable A pointer to the EFI System Table. > > + > > + @retval EFI_SUCCESS The entry point executed successfully. > > + @retval other Some error occured when executing this entry = point. > > + > > +**/ > > +int > > +main ( > > + ) > > +{ > > + EFI_STATUS Status; > > + UNIT_TEST_FRAMEWORK_HANDLE Framework =3D NULL; > > + UNIT_TEST_SUITE_HANDLE ArchTests; > > + UNIT_TEST_SUITE_HANDLE PolicyTests; > > + UNIT_TEST_SUITE_HANDLE UtilityTests; > > +#ifdef INTERNAL_UNIT_TEST > > + UNIT_TEST_SUITE_HANDLE InternalTests; > > +#endif // INTERNAL_UNIT_TEST > > + > > + DEBUG(( DEBUG_INFO, "%a v%a\n", UNIT_TEST_NAME, > UNIT_TEST_VERSION )); > > + > > + // > > + // Start setting up the test framework for running the tests. > > + // > > + Status =3D InitUnitTestFramework( &Framework, UNIT_TEST_NAME, > gEfiCallerBaseName, UNIT_TEST_VERSION ); > > + if (EFI_ERROR( Status )) > > + { > > + DEBUG((DEBUG_ERROR, "Failed in InitUnitTestFramework. Status =3D %r= \n", > Status)); > > + goto EXIT; > > + } > > + > > + > > + // > > + // Add all test suites and tests. > > + // > > + Status =3D CreateUnitTestSuite( &ArchTests, Framework, "Variable Poli= cy > Architectural Tests", "VarPolicy.Arch", NULL, NULL ); > > + if (EFI_ERROR( Status )) > > + { > > + DEBUG((DEBUG_ERROR, "Failed in CreateUnitTestSuite for > ArchTests\n")); > > + Status =3D EFI_OUT_OF_RESOURCES; > > + goto EXIT; > > + } > > + AddTestCase( ArchTests, > > + "Deinitialization should fail if not previously initial= ized", > "VarPolicy.Arch.OnlyDeinit", > > + ShouldFailDeinitWithoutInit, NULL, NULL, NULL ); > > + AddTestCase( ArchTests, > > + "Initialization followed by deinitialization should suc= ceed", > "VarPolicy.Arch.InitDeinit", > > + ShouldBeAbleToInitAndDeinitTheLibrary, NULL, NULL, NULL= ); > > + AddTestCase( ArchTests, > > + "The initialization function fail if called twice witho= ut a deinit", > "VarPolicy.Arch.InitTwice", > > + ShouldNotBeAbleToInitializeTheLibraryTwice, NULL, LibCl= eanup, > NULL ); > > + AddTestCase( ArchTests, > > + "API functions should be unavailable until library is i= nitialized", > "VarPolicy.Arch.UninitApiOff", > > + ApiCommandsShouldNotRespondIfLibIsUninitialized, NULL, > LibCleanup, NULL ); > > + > > +#ifdef INTERNAL_UNIT_TEST > > + Status =3D CreateUnitTestSuite( &InternalTests, Framework, "Variable = Policy > Internal Tests", "VarPolicy.Internal", NULL, NULL ); > > + if (EFI_ERROR( Status )) > > + { > > + DEBUG((DEBUG_ERROR, "Failed in CreateUnitTestSuite for > InternalTests\n")); > > + Status =3D EFI_OUT_OF_RESOURCES; > > + goto EXIT; > > + } > > + AddTestCase( InternalTests, > > + "Policy matching should use name and GUID", > "VarPolicy.Internal.NameGuid", > > + PoliciesShouldMatchByNameAndGuid, LibInitMocked, LibCle= anup, > NULL ); > > + AddTestCase( InternalTests, > > + "# sign wildcards should match digits", > "VarPolicy.Internal.WildDigits", > > + WildcardPoliciesShouldMatchDigits, LibInitMocked, LibCl= eanup, > NULL ); > > + AddTestCase( InternalTests, > > + "Digit wildcards should check edge cases", > "VarPolicy.Internal.WildDigitsAdvanced", > > + WildcardPoliciesShouldMatchDigitsAdvanced, LibInitMocke= d, > LibCleanup, NULL ); > > + AddTestCase( InternalTests, > > + "Empty names should match an entire namespace", > "VarPolicy.Internal.WildNamespace", > > + WildcardPoliciesShouldMatchNamespaces, LibInitMocked, > LibCleanup, NULL ); > > + AddTestCase( InternalTests, > > + "Match priority should weight correctly based on wildca= rds", > "VarPolicy.Internal.Priorities", > > + MatchPrioritiesShouldFollowRules, LibInitMocked, LibCle= anup, > NULL ); > > +#endif // INTERNAL_UNIT_TEST > > + > > + Status =3D CreateUnitTestSuite( &PolicyTests, Framework, "Variable Po= licy > Manipulation Tests", "VarPolicy.Policy", NULL, NULL ); > > + if (EFI_ERROR( Status )) > > + { > > + DEBUG((DEBUG_ERROR, "Failed in CreateUnitTestSuite for > PolicyTests\n")); > > + Status =3D EFI_OUT_OF_RESOURCES; > > + goto EXIT; > > + } > > + AddTestCase( PolicyTests, > > + "RegisterShouldAllowNamespaceWildcards", > "VarPolicy.Policy.AllowNamespace", > > + RegisterShouldAllowNamespaceWildcards, LibInitMocked, > LibCleanup, NULL ); > > + AddTestCase( PolicyTests, > > + "RegisterShouldAllowStateVarsForNamespaces", > "VarPolicy.Policy.AllowStateNamespace", > > + RegisterShouldAllowStateVarsForNamespaces, LibInitMocke= d, > LibCleanup, NULL ); > > + AddTestCase( PolicyTests, > > + "RegisterShouldRejectNullPointers", "VarPolicy.Policy.N= ullPointers", > > + RegisterShouldRejectNullPointers, LibInitMocked, LibCle= anup, > NULL ); > > + AddTestCase( PolicyTests, > > + "RegisterShouldRejectBadRevisions", > "VarPolicy.Policy.BadRevisions", > > + RegisterShouldRejectBadRevisions, LibInitMocked, LibCle= anup, > NULL ); > > + AddTestCase( PolicyTests, > > + "RegisterShouldRejectBadSizes", "VarPolicy.Policy.BadSi= zes", > > + RegisterShouldRejectBadSizes, LibInitMocked, LibCleanup= , NULL ); > > + AddTestCase( PolicyTests, > > + "RegisterShouldRejectBadOffsets", "VarPolicy.Policy.Bad= Offsets", > > + RegisterShouldRejectBadOffsets, LibInitMocked, LibClean= up, NULL ); > > + AddTestCase( PolicyTests, > > + "RegisterShouldRejectMissingStateStrings", > "VarPolicy.Policy.MissingStateString", > > + RegisterShouldRejectMissingStateStrings, LibInitMocked, > LibCleanup, NULL ); > > + AddTestCase( PolicyTests, > > + "RegisterShouldRejectStringsMissingNull", > "VarPolicy.Policy.MissingNull", > > + RegisterShouldRejectStringsMissingNull, LibInitMocked, = LibCleanup, > NULL ); > > + AddTestCase( PolicyTests, > > + "RegisterShouldRejectMalformedStrings", > "VarPolicy.Policy.MalformedStrings", > > + RegisterShouldRejectMalformedStrings, LibInitMocked, Li= bCleanup, > NULL ); > > + AddTestCase( PolicyTests, > > + "RegisterShouldRejectUnpackedPolicies", > "VarPolicy.Policy.PolicyPacking", > > + RegisterShouldRejectUnpackedPolicies, LibInitMocked, Li= bCleanup, > NULL ); > > + AddTestCase( PolicyTests, > > + "RegisterShouldRejectInvalidNameCharacters", > "VarPolicy.Policy.InvalidCharacters", > > + RegisterShouldRejectInvalidNameCharacters, LibInitMocke= d, > LibCleanup, NULL ); > > + AddTestCase( PolicyTests, > > + "RegisterShouldRejectBadPolicyConstraints", > "VarPolicy.Policy.BadConstraints", > > + RegisterShouldRejectBadPolicyConstraints, LibInitMocked= , > LibCleanup, NULL ); > > + AddTestCase( PolicyTests, > > + "RegisterShouldRejectUnknownLockPolicies", > "VarPolicy.Policy.BadLocks", > > + RegisterShouldRejectUnknownLockPolicies, LibInitMocked, > LibCleanup, NULL ); > > + AddTestCase( PolicyTests, > > + "RegisterShouldRejectPolicesWithTooManyWildcards", > "VarPolicy.Policy.TooManyWildcards", > > + RegisterShouldRejectPolicesWithTooManyWildcards, LibIni= tMocked, > LibCleanup, NULL ); > > + AddTestCase( PolicyTests, > > + "RegisterShouldRejectDuplicatePolicies", > "VarPolicy.Policy.DuplicatePolicies", > > + RegisterShouldRejectDuplicatePolicies, LibInitMocked, L= ibCleanup, > NULL ); > > + AddTestCase( PolicyTests, > > + "Variables that exceed min or max sizes should be rejec= ted", > "VarPolicy.Policy.MinMax", > > + MinAndMaxSizePoliciesShouldBeHonored, LibInitMocked, > LibCleanup, NULL ); > > + AddTestCase( PolicyTests, > > + "AttributeMustPoliciesShouldBeHonored", > "VarPolicy.Policy.AttrMust", > > + AttributeMustPoliciesShouldBeHonored, LibInitMocked, Li= bCleanup, > NULL ); > > + AddTestCase( PolicyTests, > > + "AttributeCantPoliciesShouldBeHonored", > "VarPolicy.Policy.AttrCant", > > + AttributeCantPoliciesShouldBeHonored, LibInitMocked, Li= bCleanup, > NULL ); > > + AddTestCase( PolicyTests, > > + "VariablesShouldBeDeletableRegardlessOfSize", > "VarPolicy.Policy.DeleteIgnoreSize", > > + VariablesShouldBeDeletableRegardlessOfSize, LibInitMock= ed, > LibCleanup, NULL ); > > + AddTestCase( PolicyTests, > > + "LockNowPoliciesShouldBeHonored", > "VarPolicy.Policy.VARIABLE_POLICY_TYPE_LOCK_NOW", > > + LockNowPoliciesShouldBeHonored, LibInitMocked, LibClean= up, > NULL ); > > + AddTestCase( PolicyTests, > > + "LockOnCreatePoliciesShouldBeHonored", > "VarPolicy.Policy.VARIABLE_POLICY_TYPE_LOCK_ON_CREATE", > > + LockOnCreatePoliciesShouldBeHonored, LibInitMocked, Lib= Cleanup, > NULL ); > > + AddTestCase( PolicyTests, > > + "LockOnStatePoliciesShouldBeHonored", > "VarPolicy.Policy.LockState", > > + LockOnStatePoliciesShouldBeHonored, LibInitMocked, LibC= leanup, > NULL ); > > + AddTestCase( PolicyTests, > > + "LockOnStatePoliciesShouldApplyToNamespaces", > "VarPolicy.Policy.NamespaceLockState", > > + LockOnStatePoliciesShouldApplyToNamespaces, LibInitMock= ed, > LibCleanup, NULL ); > > + AddTestCase( PolicyTests, > > + "LockOnStateShouldHandleErrorsGracefully", > "VarPolicy.Policy.LockStateErrors", > > + LockOnStateShouldHandleErrorsGracefully, LibInitMocked, > LibCleanup, NULL ); > > + AddTestCase( PolicyTests, > > + "BestMatchPriorityShouldBeObeyed", "VarPolicy.Policy.Be= stMatch", > > + BestMatchPriorityShouldBeObeyed, LibInitMocked, LibClea= nup, > NULL ); > > + > > + Status =3D CreateUnitTestSuite( &UtilityTests, Framework, "Variable P= olicy > Utility Tests", "VarPolicy.Utility", NULL, NULL ); > > + if (EFI_ERROR( Status )) > > + { > > + DEBUG((DEBUG_ERROR, "Failed in CreateUnitTestSuite for > UtilityTests\n")); > > + Status =3D EFI_OUT_OF_RESOURCES; > > + goto EXIT; > > + } > > + AddTestCase( UtilityTests, > > + "API commands that change state should not respond afte= r > interface is locked", "VarPolicy.Utility.InterfaceLock", > > + ShouldBeAbleToLockInterface, LibInitMocked, LibCleanup,= NULL ); > > + AddTestCase( UtilityTests, > > + "All policies should pass once enforcement is disabled"= , > "VarPolicy.Utility.DisableEnforcement", > > + ShouldBeAbleToDisablePolicyEnforcement, LibInitMocked, > LibCleanup, NULL ); > > + AddTestCase( UtilityTests, > > + "Disabling enforcement twice should produce an error", > "VarPolicy.Utility.DisableEnforcementTwice", > > + ShouldNotBeAbleToDisablePoliciesTwice, LibInitMocked, > LibCleanup, NULL ); > > + AddTestCase( UtilityTests, > > + "ShouldBeAbleToAddNewPoliciesAfterDisabled", > "VarPolicy.Utility.AddAfterDisable", > > + ShouldBeAbleToAddNewPoliciesAfterDisabled, LibInitMocke= d, > LibCleanup, NULL ); > > + AddTestCase( UtilityTests, > > + "ShouldBeAbleToLockAfterDisabled", > "VarPolicy.Utility.LockAfterDisable", > > + ShouldBeAbleToLockAfterDisabled, LibInitMocked, LibClea= nup, > NULL ); > > + AddTestCase( UtilityTests, > > + "Should be able to dump the policy table", > "VarPolicy.Utility.DumpTable", > > + ShouldBeAbleToDumpThePolicyTable, LibInitMocked, LibCle= anup, > NULL ); > > + AddTestCase( UtilityTests, > > + "ShouldBeAbleToDumpThePolicyTableAfterDisabled", > "VarPolicy.Utility.DumpTableAfterDisable", > > + ShouldBeAbleToDumpThePolicyTableAfterDisabled, LibInitM= ocked, > LibCleanup, NULL ); > > + > > + > > + // > > + // Execute the tests. > > + // > > + Status =3D RunAllTestSuites( Framework ); > > + > > +EXIT: > > + if (Framework !=3D NULL) > > + { > > + FreeUnitTestFramework( Framework ); > > + } > > + > > + return Status; > > +} > > diff --git a/MdeModulePkg/Include/Library/VariablePolicyLib.h > b/MdeModulePkg/Include/Library/VariablePolicyLib.h > new file mode 100644 > index 000000000000..efd1840112ec > --- /dev/null > +++ b/MdeModulePkg/Include/Library/VariablePolicyLib.h > @@ -0,0 +1,207 @@ > +/** @file -- VariablePolicyLib.h > > +Business logic for Variable Policy enforcement. > > + > > +Copyright (c) Microsoft Corporation. > > +SPDX-License-Identifier: BSD-2-Clause-Patent > > + > > +**/ > > + > > +#ifndef _VARIABLE_POLICY_LIB_H_ > > +#define _VARIABLE_POLICY_LIB_H_ > > + > > +#include > > + > > +/** > > + This API function validates and registers a new policy with > > + the policy enforcement engine. > > + > > + @param[in] NewPolicy Pointer to the incoming policy structure. > > + > > + @retval EFI_SUCCESS > > + @retval EFI_INVALID_PARAMETER NewPolicy is NULL or is internall= y > inconsistent. > > + @retval EFI_ALREADY_STARTED An identical matching policy alre= ady > exists. > > + @retval EFI_WRITE_PROTECTED The interface has been locked unt= il > the next reboot. > > + @retval EFI_UNSUPPORTED Policy enforcement has been disab= led. > No reason to add more policies. > > + @retval EFI_ABORTED A calculation error has prevented= this > function from completing. > > + @retval EFI_OUT_OF_RESOURCES Cannot grow the table to hold any > more policies. > > + @retval EFI_NOT_READY Library has not yet been initiali= zed. > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +RegisterVariablePolicy ( > > + IN CONST VARIABLE_POLICY_ENTRY *NewPolicy > > + ); > > + > > + > > +/** > > + This API function checks to see whether the parameters to SetVariable > would > > + be allowed according to the current variable policies. > > + > > + @param[in] VariableName Same as EFI_SET_VARIABLE. > > + @param[in] VendorGuid Same as EFI_SET_VARIABLE. > > + @param[in] Attributes Same as EFI_SET_VARIABLE. > > + @param[in] DataSize Same as EFI_SET_VARIABLE. > > + @param[in] Data Same as EFI_SET_VARIABLE. > > + > > + @retval EFI_SUCCESS A matching policy allows this upd= ate. > > + @retval EFI_SUCCESS There are currently no policies t= hat restrict > this update. > > + @retval EFI_SUCCESS The protections have been disable= until the > next reboot. > > + @retval EFI_WRITE_PROTECTED Variable is currently locked. > > + @retval EFI_INVALID_PARAMETER Attributes or size are invalid. > > + @retval EFI_ABORTED A lock policy exists, but an erro= r prevented > evaluation. > > + @retval EFI_NOT_READY Library has not been initialized. > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +ValidateSetVariable ( > > + IN CHAR16 *VariableName, > > + IN EFI_GUID *VendorGuid, > > + IN UINT32 Attributes, > > + IN UINTN DataSize, > > + IN VOID *Data > > + ); > > + > > + > > +/** > > + This API function disables the variable policy enforcement. If it's > > + already been called once, will return EFI_ALREADY_STARTED. > > + > > + @retval EFI_SUCCESS > > + @retval EFI_ALREADY_STARTED Has already been called once this b= oot. > > + @retval EFI_WRITE_PROTECTED Interface has been locked until reb= oot. > > + @retval EFI_WRITE_PROTECTED Interface option is disabled by pla= tform > PCD. > > + @retval EFI_NOT_READY Library has not yet been initialized. > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +DisableVariablePolicy ( > > + VOID > > + ); > > + > > + > > +/** > > + This API function will dump the entire contents of the variable polic= y table. > > + > > + Similar to GetVariable, the first call can be made with a 0 size and = it will > return > > + the size of the buffer required to hold the entire table. > > + > > + @param[out] Policy Pointer to the policy buffer. Can be NULL if = Size is 0. > > + @param[in,out] Size On input, the size of the output buffer. On o= utput, > the size > > + of the data returned. > > + > > + @retval EFI_SUCCESS Policy data is in the output buff= er and Size > has been updated. > > + @retval EFI_INVALID_PARAMETER Size is NULL, or Size is non-zero= and > Policy is NULL. > > + @retval EFI_BUFFER_TOO_SMALL Size is insufficient to hold poli= cy. Size > updated with required size. > > + @retval EFI_NOT_READY Library has not yet been initiali= zed. > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +DumpVariablePolicy ( > > + OUT UINT8 *Policy, > > + IN OUT UINT32 *Size > > + ); > > + > > + > > +/** > > + This API function returns whether or not the policy engine is > > + currently being enforced. > > + > > + @retval TRUE > > + @retval FALSE > > + @retval FALSE Library has not yet been initialized. > > + > > +**/ > > +BOOLEAN > > +EFIAPI > > +IsVariablePolicyEnabled ( > > + VOID > > + ); > > + > > + > > +/** > > + This API function locks the interface so that no more policy updates > > + can be performed or changes made to the enforcement until the next > boot. > > + > > + @retval EFI_SUCCESS > > + @retval EFI_NOT_READY Library has not yet been initialized. > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +LockVariablePolicy ( > > + VOID > > + ); > > + > > + > > +/** > > + This API function returns whether or not the policy interface is lock= ed > > + for the remainder of the boot. > > + > > + @retval TRUE > > + @retval FALSE > > + @retval FALSE Library has not yet been initialized. > > + > > +**/ > > +BOOLEAN > > +EFIAPI > > +IsVariablePolicyInterfaceLocked ( > > + VOID > > + ); > > + > > + > > +/** > > + This helper function initializes the library and sets > > + up any required internal structures or handlers. > > + > > + Also registers the internal pointer for the GetVariable helper. > > + > > + @param[in] GetVariableHelper A function pointer matching the > EFI_GET_VARIABLE prototype that will be used to > > + check policy criteria that involve the existence of o= ther variables. > > + > > + @retval EFI_SUCCESS > > + @retval EFI_ALREADY_STARTED The initialize function has been ca= lled > more than once without a call to > > + deinitialize. > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +InitVariablePolicyLib ( > > + IN EFI_GET_VARIABLE GetVariableHelper > > + ); > > + > > + > > +/** > > + This helper function returns whether or not the library is currently > initialized. > > + > > + @retval TRUE > > + @retval FALSE > > + > > +**/ > > +BOOLEAN > > +EFIAPI > > +IsVariablePolicyLibInitialized ( > > + VOID > > + ); > > + > > + > > +/** > > + This helper function tears down the library. > > + > > + Should generally only be used for test harnesses. > > + > > + @retval EFI_SUCCESS > > + @retval EFI_NOT_READY Deinitialize was called without first c= alling > initialize. > > + > > +**/ > > +EFI_STATUS > > +EFIAPI > > +DeinitVariablePolicyLib ( > > + VOID > > + ); > > + > > + > > +#endif // _VARIABLE_POLICY_LIB_H_ > > diff --git a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.in= f > b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf > new file mode 100644 > index 000000000000..f4a879d5382f > --- /dev/null > +++ b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf > @@ -0,0 +1,44 @@ > +## @file VariablePolicyLib.inf > > +# Business logic for Variable Policy enforcement. > > +# > > +## > > +# Copyright (c) Microsoft Corporation. > > +# SPDX-License-Identifier: BSD-2-Clause-Patent > > +## > > + > > + > > +[Defines] > > + INF_VERSION =3D 0x00010017 > > + BASE_NAME =3D VariablePolicyLib > > + FILE_GUID =3D E9ECD342-159A-4F24-9FDF-65724027C594 > > + VERSION_STRING =3D 1.0 > > + MODULE_TYPE =3D DXE_DRIVER > > + LIBRARY_CLASS =3D VariablePolicyLib|DXE_DRIVER DXE_SMM_DRIVER > MM_STANDALONE > > + > > +# > > +# The following information is for reference only and not required by t= he > build tools. > > +# > > +# VALID_ARCHITECTURES =3D ANY > > +# > > + > > + > > +[Sources] > > + VariablePolicyLib.c > > + VariablePolicyExtraInitNull.c > > + > > + > > +[Packages] > > + MdePkg/MdePkg.dec > > + MdeModulePkg/MdeModulePkg.dec > > + > > + > > +[LibraryClasses] > > + DebugLib > > + BaseMemoryLib > > + MemoryAllocationLib > > + SafeIntLib > > + PcdLib > > + > > + > > +[Pcd] > > + > gEfiMdeModulePkgTokenSpaceGuid.PcdAllowVariablePolicyEnforcementDis > able ## CONSUMES > > diff --git a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.un= i > b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.uni > new file mode 100644 > index 000000000000..2227ec427828 > --- /dev/null > +++ b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.uni > @@ -0,0 +1,12 @@ > +// /** @file > > +// VariablePolicyLib.uni > > +// > > +// Copyright (c) Microsoft Corporation. > > +// SPDX-License-Identifier: BSD-2-Clause-Patent > > +// > > +// **/ > > + > > + > > +#string STR_MODULE_ABSTRACT #language en-US "Library contai= ning > the business logic for the VariablePolicy engine" > > + > > +#string STR_MODULE_DESCRIPTION #language en-US "Library > containing the business logic for the VariablePolicy engine" > > diff --git > a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.in > f > b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.in > f > new file mode 100644 > index 000000000000..8b8365741864 > --- /dev/null > +++ > b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.in > f > @@ -0,0 +1,51 @@ > +## @file VariablePolicyLibRuntimeDxe.inf > > +# Business logic for Variable Policy enforcement. > > +# This instance is specifically for RuntimeDxe and contains > > +# extra routines to register for VirtualAddressChangeEvents. > > +# > > +# Copyright (c) Microsoft Corporation. > > +# SPDX-License-Identifier: BSD-2-Clause-Patent > > +## > > + > > + > > +[Defines] > > + INF_VERSION =3D 0x00010017 > > + BASE_NAME =3D VariablePolicyLibRuntimeDxe > > + FILE_GUID =3D 205F7F0E-8EAC-4914-8390-1B90DD7E2A27 > > + VERSION_STRING =3D 1.0 > > + MODULE_TYPE =3D DXE_RUNTIME_DRIVER > > + LIBRARY_CLASS =3D VariablePolicyLib|DXE_RUNTIME_DRIVER > > + > > +# > > +# The following information is for reference only and not required by t= he > build tools. > > +# > > +# VALID_ARCHITECTURES =3D ANY > > +# > > + > > + > > +[Sources] > > + VariablePolicyLib.c > > + VariablePolicyExtraInitRuntimeDxe.c > > + > > + > > +[Packages] > > + MdePkg/MdePkg.dec > > + MdeModulePkg/MdeModulePkg.dec > > + > > + > > +[LibraryClasses] > > + DebugLib > > + BaseMemoryLib > > + MemoryAllocationLib > > + SafeIntLib > > + UefiBootServicesTableLib > > + UefiRuntimeServicesTableLib > > + PcdLib > > + > > + > > +[Pcd] > > + > gEfiMdeModulePkgTokenSpaceGuid.PcdAllowVariablePolicyEnforcementDis > able ## CONSUMES > > + > > + > > +[Guids] > > + gEfiEventVirtualAddressChangeGuid > > diff --git > a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/Variable > PolicyUnitTest.inf > b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/Variable > PolicyUnitTest.inf > new file mode 100644 > index 000000000000..ccc04bb600d6 > --- /dev/null > +++ > b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/Variable > PolicyUnitTest.inf > @@ -0,0 +1,40 @@ > +## @file VariablePolicyUnitTest.inf > > +# UnitTest for... > > +# Business logic for Variable Policy enforcement. > > +# > > +# Copyright (c) Microsoft Corporation. > > +# SPDX-License-Identifier: BSD-2-Clause-Patent > > +## > > + > > + > > +[Defines] > > + INF_VERSION =3D 0x00010006 > > + BASE_NAME =3D VariablePolicyUnitTest > > + FILE_GUID =3D 1200A2E4-D756-418C-9768-528C2D181A= 98 > > + MODULE_TYPE =3D HOST_APPLICATION > > + VERSION_STRING =3D 1.0 > > + > > +# > > +# The following information is for reference only and not required by t= he > build tools. > > +# > > +# VALID_ARCHITECTURES =3D IA32 X64 ARM AARCH64 > > +# > > + > > +[Sources] > > + VariablePolicyUnitTest.c > > + > > + > > +[Packages] > > + MdePkg/MdePkg.dec > > + MdeModulePkg/MdeModulePkg.dec > > + UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec > > + > > + > > +[LibraryClasses] > > + BaseLib > > + DebugLib > > + UnitTestLib > > + PrintLib > > + VariablePolicyLib > > + BaseMemoryLib > > + MemoryAllocationLib > > diff --git a/MdeModulePkg/MdeModulePkg.dec > b/MdeModulePkg/MdeModulePkg.dec > index 05d8ad4931f9..0b58c14e4747 100644 > --- a/MdeModulePkg/MdeModulePkg.dec > +++ b/MdeModulePkg/MdeModulePkg.dec > @@ -31,6 +31,9 @@ [LibraryClasses] > ## @libraryclass Defines a set of methods to reset whole system. > > ResetSystemLib|Include/Library/ResetSystemLib.h > > > > + ## @libraryclass Business logic for storing and testing variable po= licies > > + VariablePolicyLib|Include/Library/VariablePolicyLib.h > > + > > ## @libraryclass Defines a set of helper functions for resetting th= e system. > > ResetUtilityLib|Include/Library/ResetUtilityLib.h > > > > diff --git a/MdeModulePkg/MdeModulePkg.dsc > b/MdeModulePkg/MdeModulePkg.dsc > index 25aea3e2a481..14b6ed536962 100644 > --- a/MdeModulePkg/MdeModulePkg.dsc > +++ b/MdeModulePkg/MdeModulePkg.dsc > @@ -3,6 +3,7 @@ > # > > # (C) Copyright 2014 Hewlett-Packard Development Company, L.P.
> > # Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved. > > +# Copyright (c) Microsoft Corporation. > > # > > # SPDX-License-Identifier: BSD-2-Clause-Patent > > # > > @@ -58,6 +59,7 @@ [LibraryClasses] > DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf > > > DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTabl > eLib.inf > > > UefiBootManagerLib|MdeModulePkg/Library/UefiBootManagerLib/UefiBoo > tManagerLib.inf > > + > VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyL= i > b.inf > > # > > # Generic Modules > > # > > @@ -129,6 +131,7 @@ [LibraryClasses.common.DXE_RUNTIME_DRIVER] > DebugLib|MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf > > > LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxDxeLib.in > f > > > CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsule > Lib.inf > > + > VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyL= i > bRuntimeDxe.inf > > > > [LibraryClasses.common.SMM_CORE] > > HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf > > @@ -306,6 +309,8 @@ [Components] > MdeModulePkg/Library/BootLogoLib/BootLogoLib.inf > > > MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull > .inf > > MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf > > + MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf > > + > MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf > > MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf > > MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLib.inf > > MdeModulePkg/Library/VarCheckPcdLib/VarCheckPcdLib.inf > > diff --git a/MdeModulePkg/Test/MdeModulePkgHostTest.dsc > b/MdeModulePkg/Test/MdeModulePkgHostTest.dsc > index 72a119db4568..095e613f1be1 100644 > --- a/MdeModulePkg/Test/MdeModulePkgHostTest.dsc > +++ b/MdeModulePkg/Test/MdeModulePkgHostTest.dsc > @@ -19,12 +19,23 @@ [Defines] > > > !include UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc > > > > +[LibraryClasses] > > + SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf > > + > > [Components] > > > MdeModulePkg/Library/DxeResetSystemLib/UnitTest/MockUefiRuntimeSer > vicesTableLib.inf > > > > # > > # Build MdeModulePkg HOST_APPLICATION Tests > > # > > + > MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePo > licyUnitTest.inf { > > + > > + > VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyL= i > b.inf > > + > > + > > + > gEfiMdeModulePkgTokenSpaceGuid.PcdAllowVariablePolicyEnforcementDis > able|TRUE > > + } > > + > > > MdeModulePkg/Library/DxeResetSystemLib/UnitTest/DxeResetSystemLibU > nitTestHost.inf { > > > > > ResetSystemLib|MdeModulePkg/Library/DxeResetSystemLib/DxeResetSyst > emLib.inf > > -- > 2.26.2.windows.1.8.g01c50adf56.20200515075929 > > > -=3D-=3D-=3D-=3D-=3D-=3D > Groups.io Links: You receive all messages sent to this group. > > View/Reply Online (#61588): https://nam06.safelinks.protection.outlook.c= om/?url=3Dhttps%3A%2F%2Fedk2.groups.io%2Fg%2Fdevel%2Fmessage%2F61588&da= ta=3D02%7C01%7Cbret.barkelew%40microsoft.com%7C4ff781c598384282187708d81e2d= 8858%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637292528218892203&sd= ata=3DLU1JPSqqPVToubD2UJd8JT34dvLGJ6QSi7oA7s%2FyiqY%3D&reserved=3D0 > Mute This Topic: https://nam06.safelinks.protection.outlook.com/?url=3Dh= ttps%3A%2F%2Fgroups.io%2Fmt%2F75057697%2F1768738&data=3D02%7C01%7Cbret.= barkelew%40microsoft.com%7C4ff781c598384282187708d81e2d8858%7C72f988bf86f14= 1af91ab2d7cd011db47%7C1%7C0%7C637292528218892203&sdata=3DY%2BAVPkeX7Clj= 7g0E0ENKDcJQwVksMtp%2FbZjBgDdz%2B1A%3D&reserved=3D0 > Group Owner: devel+owner@edk2.groups.io > Unsubscribe: https://nam06.safelinks.protection.outlook.com/?url=3Dhttps= %3A%2F%2Fedk2.groups.io%2Fg%2Fdevel%2Funsub&data=3D02%7C01%7Cbret.barke= lew%40microsoft.com%7C4ff781c598384282187708d81e2d8858%7C72f988bf86f141af91= ab2d7cd011db47%7C1%7C0%7C637292528218892203&sdata=3DQzd%2FXa8ldydS45UAI= yd7PaGORBzcESMWbNT1oUNEZm4%3D&reserved=3D0 [dandan.bi@intel.com] > -=3D-=3D-=3D-=3D-=3D-=3D --_000_CY4PR21MB074399EFFD54FE103EF7B5B8EF6D0CY4PR21MB0743namp_ Content-Type: text/html; charset="Windows-1252" Content-Transfer-Encoding: quoted-printable
  1. Done
  2. Done
  3. BestResult can=92t be anything but NULL if MatchPriority isn=92t initializ= ed, so the second half of this will never be evaluated, but I see your poin= t. I=92ve added a default initialization for the variable.
  4. <= li class=3D"MsoListParagraph" style=3D"color:red;margin-left:0in;mso-list:l= 0 level1 lfo1"> Done

 <= /p>

Thanks!=

 

- Bret

 

From: Dandan Bi via groups.io<= br> Sent: Wednesday, July 1, 2020 7:13 PM
To: devel@edk2.groups.io; bret@corthon.com
Cc: Wang, Jian J; Wu, Hao A; liming.gao
Subject: [EXTERNAL] Re: [edk2-devel] [PATCH v6 02/14] MdeModulePkg:= Define the VariablePolicyLib

 

4 comments inline, p= lease check.

Thanks,
Dandan
> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of = Bret
> Barkelew
> Sent: Tuesday, June 23, 2020 2:41 PM
> To: devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.w= u@intel.com>;
> Gao, Liming <liming.gao@intel.com>
> Subject: [edk2-devel] [PATCH v6 02/14] MdeModulePkg: Define the
> VariablePolicyLib
>
> https://nam06.safelinks.protection.outlook.com/?url=3Dhttps%3A%2F%2Fbugzil= la.tianocore.org%2Fshow_bug.cgi%3Fid%3D2522&amp;data=3D02%7C01%7Cbret.b= arkelew%40microsoft.com%7C4ff781c598384282187708d81e2d8858%7C72f988bf86f141= af91ab2d7cd011db47%7C1%7C0%7C637292528218882209&amp;sdata=3Dcw75EiZAUXP= o9iwbbkXrZwoLpuv1F7rHZIiDDHSToDA%3D&amp;reserved=3D0
>
> VariablePolicy is an updated interface to
> replace VarLock and VarCheckProtocol.
>
> Add the VariablePolicyLib library that implements
> the portable business logic for the VariablePolicy
> engine.
>
> Also add host-based CI test cases for the lib.
>
> Cc: Jian J Wang <jian.j.wang@intel.com>
> Cc: Hao A Wu <hao.a.wu@intel.com>
> Cc: Liming Gao <liming.gao@intel.com>
> Cc: Bret Barkelew <brbarkel@microsoft.com>
> Signed-off-by: Bret Barkelew <brbarkel@microsoft.com>
> ---
>  MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitN= ull.c
> |   46 +
>
> MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitRuntime= Dx
> e.c           =     |   85 +
>  MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c
> |  816 +++++++
>
> MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/Variabl= ePo
> licyUnitTest.c   | 2436 +++++++= +++++++++++++
>  MdeModulePkg/Include/Library/VariablePolicyLib.h  &nb= sp;            =             &nb= sp;            = |
> 207 ++
>  MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf > |   44 +
>  MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.uni > |   12 +
>  MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntime= Dxe.inf
> |   51 +
>
> MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/Variabl= ePo
> licyUnitTest.inf |   40 +
>  MdeModulePkg/MdeModulePkg.dec     &nbs= p;            &= nbsp;           &nbs= p;            &= nbsp;           &nbs= p;    |    3 +
>  MdeModulePkg/MdeModulePkg.dsc     &nbs= p;            &= nbsp;           &nbs= p;            &= nbsp;           &nbs= p;    |    5 +
>  MdeModulePkg/Test/MdeModulePkgHostTest.dsc   &nb= sp;            =             &nb= sp;            =       |
> 11 +
>  12 files changed, 3756 insertions(+)
>
> diff --git
> a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitNull.= c
> b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitNull.= c
> new file mode 100644
> index 000000000000..ad2ee0b2fb8f
> --- /dev/null
> +++
> b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitNull.= c
> @@ -0,0 +1,46 @@
> +/** @file -- VariablePolicyExtraInitNull.c
>
> +This file contains extra init and deinit routines that don't do = anything
>
> +extra.
>
> +
>
> +Copyright (c) Microsoft Corporation.
>
> +SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +
>
> +**/
>
> +
>
> +#include <Library/UefiRuntimeServicesTableLib.h>
>
> +
>
> +
>
> +/**
>
> +  An extra init hook that enables the RuntimeDxe library in= stance to
>
> +  register VirtualAddress change callbacks. Among other thi= ngs.
>
> +
>
> +  @retval     EFI_SUCCESS   E= verything is good. Continue with init.
>
> +  @retval     Others   &= nbsp;    Uh... don't continue.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +VariablePolicyExtraInit (
>
> +  VOID
>
> +  )
>
> +{
>
> +  // NULL implementation.
>
> +  return EFI_SUCCESS;
>
> +}
>
> +
>
> +
>
> +/**
>
> +  An extra deinit hook that enables the RuntimeDxe library = instance to
>
> +  register VirtualAddress change callbacks. Among other thi= ngs.
>
> +
>
> +  @retval     EFI_SUCCESS   E= verything is good. Continue with deinit.
>
> +  @retval     Others   &= nbsp;    Uh... don't continue.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +VariablePolicyExtraDeinit (
>
> +  VOID
>
> +  )
>
> +{
>
> +  // NULL implementation.
>
> +  return EFI_SUCCESS;
>
> +}
>
> diff --git
> a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitRunti= meD
> xe.c
> b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitRunti= me
> Dxe.c
> new file mode 100644
> index 000000000000..3ca87048b14b
> --- /dev/null
> +++
> b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitRunti= me
> Dxe.c
> @@ -0,0 +1,85 @@
> +/** @file -- VariablePolicyExtraInitRuntimeDxe.c
>
> +This file contains extra init and deinit routines that register = and unregister
>
> +VariableAddressChange callbacks.
>
> +
>
> +Copyright (c) Microsoft Corporation.
>
> +SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +
>
> +**/
>
> +
>
> +#include <Library/UefiBootServicesTableLib.h>
>
> +#include <Library/UefiRuntimeServicesTableLib.h>
>
> +
>
> +extern EFI_GET_VARIABLE   mGetVariableHelper;
>
> +extern UINT8        &nbs= p;     *mPolicyTable;
>
> +STATIC BOOLEAN        &n= bsp;   mIsVirtualAddrConverted;
>
> +STATIC EFI_EVENT        =   mVariablePolicyLibVirtualAddressChangeEvent  =3D
> NULL;
>
> +
>
> +/**
>
> +  For the RuntimeDxe version of this lib, convert internal = pointer addresses
> to virtual addresses.
>
> +
>
> +  @param[in] Event      Event whos= e notification function is being invoked.
>
> +  @param[in] Context    The pointer to the n= otification function's context,
> which
>
> +          &nbs= p;             = is implementation-dependent.
>
> +**/
>
> +STATIC
>
> +VOID
>
> +EFIAPI
>
> +VariablePolicyLibVirtualAddressCallback (
>
> +  IN  EFI_EVENT   Event,
>
> +  IN  VOID        *= Context
>
> +  )
>
> +{
>
> +  gRT->ConvertPointer (0, (VOID **)&mPolicyTable); >
> +  gRT->ConvertPointer (0, (VOID **)&mGetVariableHelp= er);
>
> +  mIsVirtualAddrConverted =3D TRUE;
>
> +}
>
> +
>
> +
>
> +/**
>
> +  An extra init hook that enables the RuntimeDxe library in= stance to
>
> +  register VirtualAddress change callbacks. Among other thi= ngs.
>
> +
>
> +  @retval     EFI_SUCCESS   E= verything is good. Continue with init.
>
> +  @retval     Others   &= nbsp;    Uh... don't continue.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +VariablePolicyExtraInit (
>
> +  VOID
>
> +  )
>
> +{
>
> +  return gBS->CreateEventEx (EVT_NOTIFY_SIGNAL,
>
> +          &nbs= p;            &= nbsp;      TPL_NOTIFY,
>
> +          &nbs= p;            &= nbsp;      VariablePolicyLibVirtualAddressCallback= ,
>
> +          &nbs= p;            &= nbsp;      NULL,
>
> +          &nbs= p;            &= nbsp;      &gEfiEventVirtualAddressChangeGuid,=
>
> +          &nbs= p;            &= nbsp;      &mVariablePolicyLibVirtualAddressCh= angeEvent);
>
> +}
>
> +
>
> +
>
> +/**
>
> +  An extra deinit hook that enables the RuntimeDxe library = instance to
>
> +  register VirtualAddress change callbacks. Among other thi= ngs.
>
> +
>
> +  @retval     EFI_SUCCESS   E= verything is good. Continue with deinit.
>
> +  @retval     Others   &= nbsp;    Uh... don't continue.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +VariablePolicyExtraDeinit (
>
> +  VOID
>
> +  )
>
> +{
>
> +  EFI_STATUS  Status;
>
> +
>
> +  Status =3D EFI_SUCCESS;
>
> +  if (mIsVirtualAddrConverted) {
>
> +    Status =3D gBS->CloseEvent
> (mVariablePolicyLibVirtualAddressChangeEvent);
>
> +  }
>
> +  else {
>
> +    Status =3D EFI_SUCCESS;
>
> +  }
>
> +
>
> +  return Status;
>
> +}
>
> diff --git a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib= .c
> b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c
> new file mode 100644
> index 000000000000..84c794adaed9
> --- /dev/null
> +++ b/MdeModulePkg/Library/VariablePolicyLib/VariablePoli= cyLib.c
> @@ -0,0 +1,816 @@
> +/** @file -- VariablePolicyLib.c
>
> +Business logic for Variable Policy enforcement.
>
> +
>
> +Copyright (c) Microsoft Corporation.
>
> +SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +
>
> +**/
>
> +
>
> +#include <Uefi.h>
>
> +
>
> +#include <Library/SafeIntLib.h>
>
> +#include <Library/MemoryAllocationLib.h>
>
> +#include <Library/BaseMemoryLib.h>
>
> +#include <Library/DebugLib.h>
>
> +#include <Library/PcdLib.h>
>
> +
>
> +#include <Protocol/VariablePolicy.h>
>
> +#include <Library/VariablePolicyLib.h>
>
> +
>
> +
>
> +// IMPORTANT NOTE: This library is currently rife with multiple = return
> statements
>
> +//          &n= bsp;      for error handling. A refactor should re= move these at some point.
>
> +
>
> +//
>
> +// This library was designed with advanced unit-test features. >
> +// This define handles the configuration.
>
> +#ifdef INTERNAL_UNIT_TEST
>
> +#undef STATIC
>
> +#define STATIC    // Nothing...
>
> +#endif
>
> +
>
> +// An abstracted GetVariable interface that enables configuratio= n
> regardless of the environment.
>
> +EFI_GET_VARIABLE        =     mGetVariableHelper =3D NULL;
>
> +
>
> +// Master switch to lock this entire interface. Does not stop en= forcement,
>
> +// just prevents the configuration from being changed for the re= st of the
> boot.
>
> +STATIC  BOOLEAN       &n= bsp;     mInterfaceLocked =3D FALSE;
>
> +
>
> +// Master switch to disable the entire interface for a single bo= ot.
>
> +// This will disable all policy enforcement for the duration of = the boot.
>
> +STATIC  BOOLEAN       &n= bsp;     mProtectionDisabled =3D FALSE;
>
> +
>
> +// Table to hold all the current policies.
>
> +UINT8          = ;             *= mPolicyTable =3D NULL;
>
> +STATIC  UINT32       &nb= sp;      mCurrentTableSize =3D 0;
>
> +STATIC  UINT32       &nb= sp;      mCurrentTableUsage =3D 0;
>
> +STATIC  UINT32       &nb= sp;      mCurrentTableCount =3D 0;
>
> +
>
> +#define POLICY_TABLE_STEP_SIZE     &nbs= p;  0x1000
>
> +
>
> +// NOTE: DO NOT USE THESE MACROS on any structure that has not b= een
> validated.
>
> +//       Current table data has al= ready been sanitized.
>
> +#define GET_NEXT_POLICY(CurPolicy)
> (VARIABLE_POLICY_ENTRY*)((UINT8*)CurPolicy + CurPolicy->Size)<= br> >
> +#define GET_POLICY_NAME(CurPolicy)    (CHAR16*)((= UINTN)CurPolicy +
> CurPolicy->OffsetToName)
>
> +
>
> +#define MATCH_PRIORITY_EXACT    0
>
> +#define MATCH_PRIORITY_MAX      MATCH_P= RIORITY_EXACT
>
> +#define MATCH_PRIORITY_MIN      MAX_UIN= T8
>
> +
>
> +// ExtraInit/ExtraDeinit functions allow RuntimeDxe to register<= br> > VirtualAddress callbacks.
>
> +EFI_STATUS
>
> +VariablePolicyExtraInit (
>
> +  VOID
>
> +  );
>
> +
>
> +EFI_STATUS
>
> +VariablePolicyExtraDeinit (
>
> +  VOID
>
> +  );

1. [Dandan]: Please also add comments for above two functions.
Please also pay attention to the coding style issue in other files.

>
> +
>
> +
>
> +/**
>
> +  This helper function determines whether the structure of = an incoming
> policy
>
> +  is valid and internally consistent.
>
> +
>
> +  @param[in]  NewPolicy     Pointe= r to the incoming policy structure.
>
> +
>
> +  @retval     TRUE
>
> +  @retval     FALSE   Pointer= is NULL, size is wrong, strings are empty, or
>
> +          &nbs= p;           substructure= s overlap.
>
> +
>
> +**/
>
> +STATIC
>
> +BOOLEAN
>
> +IsValidVariablePolicyStructure (
>
> +  IN CONST VARIABLE_POLICY_ENTRY    *NewPoli= cy
>
> +  )
>
> +{
>
> +  EFI_STATUS    Status;
>
> +  UINTN         Ent= ryEnd;
>
> +  CHAR16        *CheckCh= ar;
>
> +  UINTN         Wil= dcardCount;
>
> +
>
> +  // Sanitize some quick values.
>
> +  if (NewPolicy =3D=3D NULL || NewPolicy->Size =3D=3D 0 = ||
>
> +      // Structure size should be at le= ast as long as the minumum structure and
> a NULL string.
>
> +      NewPolicy->Size < sizeof(VA= RIABLE_POLICY_ENTRY) ||
>
> +      // Check for the known revision.<= br> >
> +      NewPolicy->Version !=3D VARIAB= LE_POLICY_ENTRY_REVISION) {
>
> +    return FALSE;
>
> +  }
>
> +
>
> +  // Calculate the theoretical end of the structure and mak= e sure
>
> +  // that the structure can fit in memory.
>
> +  Status =3D SafeUintnAdd( (UINTN)NewPolicy, NewPolicy->= Size, &EntryEnd );
>
> +  if (EFI_ERROR( Status )) {
>
> +    return FALSE;
>
> +  }
>
> +
>
> +  // Check for a valid Max Size.
>
> +  if (NewPolicy->MaxSize =3D=3D 0) {
>
> +    return FALSE;
>
> +  }
>
> +
>
> +  // Check for the valid list of lock policies.
>
> +  if (NewPolicy->LockPolicyType !=3D VARIABLE_POLICY_TYP= E_NO_LOCK &&
>
> +      NewPolicy->LockPolicyType !=3D= VARIABLE_POLICY_TYPE_LOCK_NOW &&
>
> +      NewPolicy->LockPolicyType !=3D=
> VARIABLE_POLICY_TYPE_LOCK_ON_CREATE &&
>
> +      NewPolicy->LockPolicyType !=3D=
> VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE)
>
> +  {
>
> +    return FALSE;
>
> +  }
>
> +
>
> +  // If the policy type is VARIABLE_POLICY_TYPE_LOCK_ON_VAR= _STATE,
> make sure that the matching state variable Name
>
> +  // terminates before the OffsetToName for the matching po= licy variable
> Name.
>
> +  if (NewPolicy->LockPolicyType =3D=3D
> VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE) {
>
> +    // Adjust CheckChar to the offset of the Lock= Policy->Name.
>
> +    Status =3D SafeUintnAdd( (UINTN)NewPolicy = 3;
> sizeof(VARIABLE_POLICY_ENTRY),
>
> +          &nbs= p;            &= nbsp;    sizeof(VARIABLE_LOCK_ON_VAR_STATE_POLICY),
>
> +          &nbs= p;            &= nbsp;    (UINTN*)&CheckChar );
>
> +    if (EFI_ERROR( Status ) || EntryEnd <=3D (= UINTN)CheckChar) {
>
> +      return FALSE;
>
> +    }
>
> +    while (*CheckChar !=3D CHAR_NULL) {
>
> +      if (EntryEnd <=3D (UINTN)Check= Char) {
>
> +        return FALSE;
>
> +      }
>
> +      CheckChar++;
>
> +    }
>
> +    // At this point we should have either exeede= d the structure or be
> pointing at the last char in LockPolicy->Name.
>
> +    // We should check to make sure that the poli= cy Name comes
> immediately after this charcter.
>
> +    if ((UINTN)++CheckChar !=3D (UINTN)Ne= wPolicy + NewPolicy-
> >OffsetToName) {
>
> +      return FALSE;
>
> +    }
>
> +  }
>
> +  // If the policy type is any other value, make sure that = the LockPolicy
> structure has a zero length.
>
> +  else {
>
> +    if (NewPolicy->OffsetToName !=3D sizeof(VA= RIABLE_POLICY_ENTRY)) {
>
> +      return FALSE;
>
> +    }
>
> +  }
>
> +
>
> +  // Check to make sure that the name has a terminating cha= racter
>
> +  // before the end of the structure.
>
> +  // We've already checked that the name is within the boun= ds of the
> structure.
>
> +  if (NewPolicy->Size !=3D NewPolicy->OffsetToName) {=
>
> +    CheckChar =3D (CHAR16*)((UINTN)NewPolicy += ; NewPolicy-
> >OffsetToName);
>
> +    WildcardCount =3D 0;
>
> +    while (*CheckChar !=3D CHAR_NULL) {
>
> +      // Make sure there aren't excessi= ve wildcards.
>
> +      if (*CheckChar =3D=3D '#') {
>
> +        WildcardCount+= 3;;
>
> +        if (WildcardCount >= ; MATCH_PRIORITY_MIN) {
>
> +          return FA= LSE;
>
> +        }
>
> +      }
>
> +      // Make sure you're still within = the bounds of the policy structure.
>
> +      if (EntryEnd <=3D (UINTN)Check= Char) {
>
> +        return FALSE;
>
> +      }
>
> +      CheckChar++;
>
> +    }
>
> +
>
> +    // Finally, we should be pointed at the very = last character in Name, so we
> should be right
>
> +    // up against the end of the structure.
>
> +    if ((UINTN)++CheckChar !=3D EntryEnd)= {
>
> +      return FALSE;
>
> +    }
>
> +  }
>
> +
>
> +  return TRUE;
>
> +}
>
> +
>
> +
>
> +/**
>
> +  This helper function evaluates a policy and determines wh= ether it matches
> the target
>
> +  variable. If matched, will also return a value correspond= ing to the priority
> of the match.
>
> +
>
> +  The rules for "best match" are listed in the Va= riable Policy Spec.
>
> +  Perfect name matches will return 0.
>
> +  Single wildcard characters will return the number of wild= card characters.
>
> +  Full namespaces will return MAX_UINT8.
>
> +
>
> +  @param[in]  EvalEntry     &= nbsp;   Pointer to the policy entry being evaluated.
>
> +  @param[in]  VariableName    &nbs= p; Same as EFI_SET_VARIABLE.
>
> +  @param[in]  VendorGuid     =    Same as EFI_SET_VARIABLE.
>
> +  @param[out] MatchPriority     [Option= al] On finding a match, this value
> contains the priority of the match.
>
> +          &nbs= p;            &= nbsp;        Lower number =3D=3D higher = priority. Only valid if a match found.
>
> +
>
> +  @retval     TRUE   &nb= sp;      Current entry matches the target variable= .
>
> +  @retval     FALSE   &n= bsp;     Current entry does not match at all.
>
> +
>
> +**/
>
> +STATIC
>
> +BOOLEAN
>
> +EvaluatePolicyMatch (
>
> +  IN CONST  VARIABLE_POLICY_ENTRY   *EvalEnt= ry,
>
> +  IN CONST  CHAR16      =             *Variabl= eName,
>
> +  IN CONST  EFI_GUID     &nbs= p;          *VendorGuid,
>
> +  OUT       UINT8  =             &nb= sp;    *MatchPriority    OPTIONAL
>
> +  )
>
> +{
>
> +  BOOLEAN     Result;
>
> +  CHAR16      *PolicyName;
>
> +  UINT8       CalculatedPrior= ity;
>
> +  UINTN       Index;
>
> +
>
> +  Result =3D FALSE;
>
> +  CalculatedPriority =3D MATCH_PRIORITY_EXACT;
>
> +
>
> +  // Step 1: If the GUID doesn't match, we're done. No need= to evaluate
> anything else.
>
> +  if (!CompareGuid( &EvalEntry->Namespace, VendorGui= d )) {
>
> +    goto Exit;
>
> +  }
>
> +
>
> +  // If the GUID matches, check to see whether there is a N= ame associated
>
> +  // with the policy. If not, this policy matches the entir= e namespace.
>
> +  // Missing Name is indicated by size being equal to name.=
>
> +  if (EvalEntry->Size =3D=3D EvalEntry->OffsetToName)= {
>
> +    CalculatedPriority =3D MATCH_PRIORITY_MIN; >
> +    Result =3D TRUE;
>
> +    goto Exit;
>
> +  }
>
> +
>
> +  // Now that we know the name exists, get it.
>
> +  PolicyName =3D GET_POLICY_NAME( EvalEntry );
>
> +
>
> +  // Evaluate the name against the policy name and check fo= r a match.
>
> +  // Account for any wildcards.
>
> +  Index =3D 0;
>
> +  Result =3D TRUE;
>
> +  // Keep going until the end of both strings.
>
> +  while (PolicyName[Index] !=3D CHAR_NULL || VariableName[I= ndex] !=3D
> CHAR_NULL) {
>
> +    // If we don't have a match...
>
> +    if (PolicyName[Index] !=3D VariableName[Index= ] || PolicyName[Index] =3D=3D
> '#') {
>
> +      // If this is a numerical wildcar= d, we can consider
>
> +      // it a match if we alter the pri= ority.
>
> +      if (PolicyName[Index] =3D=3D L'#'= &&
>
> +          (L'0' <= ;=3D VariableName[Index] && VariableName[Index] <=3D L'9')) { >
> +        if (CalculatedPriorit= y < MATCH_PRIORITY_MIN) {
>
> +          Calculate= dPriority++;
>
> +        }
>
> +      }
>
> +      // Otherwise, not a match.
>
> +      else {
2. [Dandan]: About the coding style, could we make the" } " and = "else {" at the same line? Which is aligned with current edk2 sty= le.
>
> +        Result =3D FALSE;
>
> +        goto Exit;
>
> +      }
>
> +    }
>
> +    Index++;
>
> +  }
>
> +
>
> +Exit:
>
> +  if (Result && MatchPriority !=3D NULL) {
>
> +    *MatchPriority =3D CalculatedPriority;
>
> +  }
>
> +  return Result;
>
> +}
>
> +
>
> +
>
> +/**
>
> +  This helper function walks the current policy table and r= eturns a pointer
>
> +  to the best match, if any are found. Leverages EvaluatePo= licyMatch() to
>
> +  determine "best".
>
> +
>
> +  @param[in]  VariableName    &nbs= p;  Same as EFI_SET_VARIABLE.
>
> +  @param[in]  VendorGuid     =     Same as EFI_SET_VARIABLE.
>
> +  @param[out] ReturnPriority     [Optio= nal] If pointer is provided, return the
>
> +          &nbs= p;            &= nbsp;         priority of the match= . Same as EvaluatePolicyMatch().
>
> +          &nbs= p;            &= nbsp;         Only valid if a match= is returned.
>
> +
>
> +  @retval     VARIABLE_POLICY_ENTRY*&nb= sp;   Best match that was found.
>
> +  @retval     NULL   &nb= sp;            =       No match was found.
>
> +
>
> +**/
>
> +STATIC
>
> +VARIABLE_POLICY_ENTRY*
>
> +GetBestPolicyMatch (
>
> +  IN CONST  CHAR16      =       *VariableName,
>
> +  IN CONST  EFI_GUID     &nbs= p;    *VendorGuid,
>
> +  OUT       UINT8  =            *ReturnPriorit= y  OPTIONAL
>
> +  )
>
> +{
>
> +  VARIABLE_POLICY_ENTRY   *BestResult;
>
> +  VARIABLE_POLICY_ENTRY   *CurrentEntry;
>
> +  UINT8        &nbs= p;          MatchPriority;
>
> +  UINT8        &nbs= p;          CurrentPriority; >
> +  UINTN        &nbs= p;          Index;
>
> +
>
> +  BestResult =3D NULL;
>
> +
>
> +  // Walk all entries in the table, looking for matches. >
> +  CurrentEntry =3D (VARIABLE_POLICY_ENTRY*)mPolicyTable; >
> +  for (Index =3D 0; Index < mCurrentTableCount; Index= 3;+) {
>
> +    // Check for a match.
>
> +    if (EvaluatePolicyMatch( CurrentEntry, Variab= leName, VendorGuid,
> &CurrentPriority )) {
>
> +      // If match is better, take it. >
> +      if (BestResult =3D=3D NULL || Cur= rentPriority < MatchPriority) {

3. [Dandan]: MatchPriority seems not be initialized but used here.

>
> +        BestResult =3D Curren= tEntry;
>
> +        MatchPriority =3D Cur= rentPriority;
>
> +      }
>
> +
>
> +      // If you've hit the highest-prio= rity match, can exit now.
>
> +      if (MatchPriority =3D=3D 0) {
>
> +        break;
>
> +      }
>
> +    }
>
> +
>
> +    // If we're still in the loop, move to the ne= xt entry.
>
> +    CurrentEntry =3D GET_NEXT_POLICY( CurrentEntr= y );
>
> +  }
>
> +
>
> +  // If a return priority was requested, return it.
>
> +  if (ReturnPriority !=3D NULL) {
>
> +    *ReturnPriority =3D MatchPriority;
>
> +  }
>
> +
>
> +  return BestResult;
>
> +}
>
> +
>
> +
>
> +/**
>
> +  This API function validates and registers a new policy wi= th
>
> +  the policy enforcement engine.
>
> +
>
> +  @param[in]  NewPolicy     Pointe= r to the incoming policy structure.
>
> +
>
> +  @retval     EFI_SUCCESS
>
> +  @retval     EFI_INVALID_PARAMETER&nbs= p;  NewPolicy is NULL or is internally
> inconsistent.
>
> +  @retval     EFI_ALREADY_STARTED =     An identical matching policy already
> exists.
>
> +  @retval     EFI_WRITE_PROTECTED =     The interface has been locked until
> the next reboot.
>
> +  @retval     EFI_UNSUPPORTED &nbs= p;       Policy enforcement has been disabled= .
> No reason to add more policies.
>
> +  @retval     EFI_ABORTED  &n= bsp;          A calculation er= ror has prevented this
> function from completing.
>
> +  @retval     EFI_OUT_OF_RESOURCES = ;   Cannot grow the table to hold any
> more policies.
>
> +  @retval     EFI_NOT_READY  =          Library has not yet been i= nitialized.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +RegisterVariablePolicy (
>
> +  IN CONST VARIABLE_POLICY_ENTRY    *NewPoli= cy
>
> +  )
>
> +{
>
> +  EFI_STATUS        = ;        Status;
>
> +  VARIABLE_POLICY_ENTRY     *MatchPolic= y;
>
> +  UINT8        &nbs= p;            MatchP= riority;
>
> +  UINT32        &nb= sp;           NewSize; >
> +  UINT8        &nbs= p;            *NewTa= ble;
>
> +
>
> +  if (!IsVariablePolicyLibInitialized()) {
>
> +    return EFI_NOT_READY;
>
> +  }
>
> +  if (mInterfaceLocked) {
>
> +    return EFI_WRITE_PROTECTED;
>
> +  }
>
> +
>
> +  if (!IsValidVariablePolicyStructure( NewPolicy )) {
>
> +    return EFI_INVALID_PARAMETER;
>
> +  }
>
> +
>
> +  // Check to see whether an exact matching policy already = exists.
>
> +  MatchPolicy =3D GetBestPolicyMatch( GET_POLICY_NAME( NewP= olicy ),
>
> +          &nbs= p;            &= nbsp;            &am= p;NewPolicy->Namespace,
>
> +          &nbs= p;            &= nbsp;            &am= p;MatchPriority );
>
> +  if (MatchPolicy !=3D NULL && MatchPriority =3D=3D= MATCH_PRIORITY_EXACT) {
>
> +    return EFI_ALREADY_STARTED;
>
> +  }
>
> +
>
> +  // If none exists, create it.
>
> +  // If we need more space, allocate that now.
>
> +  Status =3D SafeUint32Add( mCurrentTableUsage, NewPolicy-&= gt;Size,
> &NewSize );
>
> +  if (EFI_ERROR( Status )) {
>
> +    return EFI_ABORTED;
>
> +  }
>
> +  if (NewSize > mCurrentTableSize) {
>
> +    // Use NewSize to calculate the new table siz= e in units of
> POLICY_TABLE_STEP_SIZE.
>
> +    NewSize =3D (NewSize % POLICY_TABLE_STEP_SIZE= ) > 0 ?
>
> +          &nbs= p;     (NewSize / POLICY_TABLE_STEP_SIZE) + 1 :
>
> +          &nbs= p;     (NewSize / POLICY_TABLE_STEP_SIZE);
>
> +    // Calculate the new table size in absolute b= ytes.
>
> +    Status =3D SafeUint32Mult( NewSize, POLICY_TA= BLE_STEP_SIZE,
> &NewSize );
>
> +    if (EFI_ERROR( Status )) {
>
> +      return EFI_ABORTED;
>
> +    }
>
> +
>
> +    // Reallocate and copy the table.
>
> +    NewTable =3D AllocatePool( NewSize );
>
> +    if (NewTable =3D=3D NULL) {
>
> +      return EFI_OUT_OF_RESOURCES;
>
> +    }
>
> +    CopyMem( NewTable, mPolicyTable, mCurrentTabl= eUsage );
>
> +    mCurrentTableSize =3D NewSize;
>
> +    if (mPolicyTable !=3D NULL) {
>
> +      FreePool( mPolicyTable );
>
> +    }
>
> +    mPolicyTable =3D NewTable;
>
> +  }
>
> +  // Copy the policy into the table.
>
> +  CopyMem( mPolicyTable + mCurrentTableUsage, NewPolicy= , NewPolicy-
> >Size );
>
> +  mCurrentTableUsage +=3D NewPolicy->Size;
>
> +  mCurrentTableCount +=3D 1;
>
> +
>
> +  // We're done here.
>
> +
>
> +  return EFI_SUCCESS;
>
> +}
>
> +
>
> +
>
> +/**
>
> +  This API function checks to see whether the parameters to= SetVariable
> would
>
> +  be allowed according to the current variable policies. >
> +
>
> +  @param[in]  VariableName    &nbs= p;  Same as EFI_SET_VARIABLE.
>
> +  @param[in]  VendorGuid     =     Same as EFI_SET_VARIABLE.
>
> +  @param[in]  Attributes     =     Same as EFI_SET_VARIABLE.
>
> +  @param[in]  DataSize     &n= bsp;     Same as EFI_SET_VARIABLE.
>
> +  @param[in]  Data      =          Same as EFI_SET_VARIABLE.<= br> >
> +
>
> +  @retval     EFI_SUCCESS  &n= bsp;          A matching polic= y allows this update.
>
> +  @retval     EFI_SUCCESS  &n= bsp;          There are curren= tly no policies that restrict
> this update.
>
> +  @retval     EFI_SUCCESS  &n= bsp;          The protections = have been disable until the
> next reboot.
>
> +  @retval     EFI_WRITE_PROTECTED =     Variable is currently locked.
>
> +  @retval     EFI_INVALID_PARAMETER&nbs= p;  Attributes or size are invalid.
>
> +  @retval     EFI_ABORTED  &n= bsp;          A lock policy ex= ists, but an error prevented
> evaluation.
>
> +  @retval     EFI_NOT_READY  =          Library has not been initi= alized.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +ValidateSetVariable (
>
> +  IN  CHAR16       =             &nb= sp;   *VariableName,
>
> +  IN  EFI_GUID      &nbs= p;            &= nbsp; *VendorGuid,
>
> +  IN  UINT32       =             &nb= sp;   Attributes,
>
> +  IN  UINTN       &= nbsp;           &nbs= p;    DataSize,
>
> +  IN  VOID       &n= bsp;            = ;     *Data
>
> +  )
>
> +{
>
> +  BOOLEAN        &n= bsp;            = ;        IsDel;
>
> +  VARIABLE_POLICY_ENTRY      =          *ActivePolicy;
>
> +  EFI_STATUS        = ;            &n= bsp;     Status;
>
> +  EFI_STATUS        = ;            &n= bsp;     ReturnStatus;
>
> +  VARIABLE_LOCK_ON_VAR_STATE_POLICY   *StateVarPo= licy;
>
> +  CHAR16        &nb= sp;            =          *StateVarName;
>
> +  UINTN        &nbs= p;            &= nbsp;         StateVarSize;
>
> +  UINT8        &nbs= p;            &= nbsp;         StateVar;
>
> +
>
> +  ReturnStatus =3D EFI_SUCCESS;
>
> +
>
> +  if (!IsVariablePolicyLibInitialized()) {
>
> +    ReturnStatus =3D EFI_NOT_READY;
>
> +    goto Exit;
>
> +  }
>
> +
>
> +  // Bail if the protections are currently disabled.
>
> +  if (mProtectionDisabled) {
>
> +    ReturnStatus =3D EFI_SUCCESS;
>
> +    goto Exit;
>
> +  }
>
> +
>
> +  // Determine whether this is a delete operation.
>
> +  // If so, it will affect which tests are applied.
>
> +  if ((DataSize =3D=3D 0) && ((Attributes & EFI= _VARIABLE_APPEND_WRITE) =3D=3D 0))
> {
>
> +    IsDel =3D TRUE;
>
> +  }
>
> +  else {
>
> +    IsDel =3D FALSE;
>
> +  }
>
> +
>
> +  // Find an active policy if one exists.
>
> +  ActivePolicy =3D GetBestPolicyMatch( VariableName, Vendor= Guid, NULL );
>
> +
>
> +  // If we have an active policy, check it against the inco= ming data.
>
> +  if (ActivePolicy !=3D NULL) {
>
> +    //
>
> +    // Only enforce size and attribute constraint= s when updating data, not
> deleting.
>
> +    if (!IsDel) {
>
> +      // Check for size constraints. >
> +      if ((ActivePolicy->MinSize >= ; 0 && DataSize < ActivePolicy->MinSize) ||
>
> +          (ActivePo= licy->MaxSize > 0 && DataSize > ActivePolicy->MaxSize))= {
>
> +        ReturnStatus =3D EFI_= INVALID_PARAMETER;
>
> +        DEBUG(( DEBUG_VERBOSE= , "%a - Bad Size. 0x%X <> 0x%X-0x%X\n",
> __FUNCTION__,
>
> +          &nbs= p;     DataSize, ActivePolicy->MinSize, ActivePolicy= ->MaxSize ));
>
> +        goto Exit;
>
> +      }
>
> +
>
> +      // Check for attribute constraint= s.
>
> +      if ((ActivePolicy->AttributesM= ustHave & Attributes) !=3D ActivePolicy-
> >AttributesMustHave ||
>
> +          (ActivePo= licy->AttributesCantHave & Attributes) !=3D 0) {
>
> +        ReturnStatus =3D EFI_= INVALID_PARAMETER;
>
> +        DEBUG(( DEBUG_VERBOSE= , "%a - Bad Attributes. 0x%X <>
> 0x%X:0x%X\n", __FUNCTION__,
>
> +          &nbs= p;     Attributes, ActivePolicy->AttributesMustHave,= ActivePolicy-
> >AttributesCantHave ));
>
> +        goto Exit;
>
> +      }
>
> +    }
>
> +
>
> +    //
>
> +    // Lock policy check.
>
> +    //
>
> +    // Check for immediate lock.
>
> +    if (ActivePolicy->LockPolicyType =3D=3D VA= RIABLE_POLICY_TYPE_LOCK_NOW)
> {
>
> +      ReturnStatus =3D EFI_WRITE_PROTEC= TED;
>
> +      goto Exit;
>
> +    }
>
> +    // Check for lock on create.
>
> +    else if (ActivePolicy->LockPolicyType =3D= =3D
> VARIABLE_POLICY_TYPE_LOCK_ON_CREATE) {
>
> +      StateVarSize =3D 0;
>
> +      Status =3D mGetVariableHelper( Va= riableName,
>
> +          &nbs= p;            &= nbsp;           VendorGui= d,
>
> +          &nbs= p;            &= nbsp;           NULL,
>
> +          &nbs= p;            &= nbsp;           &Stat= eVarSize,
>
> +          &nbs= p;            &= nbsp;           NULL ); >
> +      if (Status =3D=3D EFI_BUFFER_TOO_= SMALL) {
>
> +        ReturnStatus =3D EFI_= WRITE_PROTECTED;
>
> +        goto Exit;
>
> +      }
>
> +    }
>
> +    // Check for lock on state variable.
>
> +    else if (ActivePolicy->LockPolicyType =3D= =3D
> VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE) {
>
> +      StateVarPolicy =3D
> (VARIABLE_LOCK_ON_VAR_STATE_POLICY*)((UINT8*)ActivePolicy +
> sizeof(VARIABLE_POLICY_ENTRY));
>
> +      StateVarName =3D (CHAR16*)((UINT8= *)StateVarPolicy +
> sizeof(VARIABLE_LOCK_ON_VAR_STATE_POLICY));
>
> +      StateVarSize =3D sizeof(StateVar)= ;
>
> +      Status =3D mGetVariableHelper( St= ateVarName,
>
> +          &nbs= p;            &= nbsp;           &Stat= eVarPolicy->Namespace,
>
> +          &nbs= p;            &= nbsp;           NULL,
>
> +          &nbs= p;            &= nbsp;           &Stat= eVarSize,
>
> +          &nbs= p;            &= nbsp;           &Stat= eVar );
>
> +
>
> +      // If the variable was found, che= ck the state. If matched, this variable is
> locked.
>
> +      if (!EFI_ERROR( Status )) {
>
> +        if (StateVar =3D=3D S= tateVarPolicy->Value) {
>
> +          ReturnSta= tus =3D EFI_WRITE_PROTECTED;
>
> +          goto Exit= ;
>
> +        }
>
> +      }
>
> +      // EFI_NOT_FOUND and EFI_BUFFER_T= OO_SMALL indicate that the
> state doesn't match.
>
> +      else if (Status !=3D EFI_NOT_FOUN= D && Status !=3D
> EFI_BUFFER_TOO_SMALL) {
>
> +        // We don't know what= happened, but it isn't good.
>
> +        ReturnStatus =3D EFI_= ABORTED;
>
> +        goto Exit;
>
> +      }
>
> +    }
>
> +  }
>
> +
>
> +Exit:
>
> +  DEBUG(( DEBUG_VERBOSE, "%a - Variable (%g:%s) return= ing %r.\n",
> __FUNCTION__, VendorGuid, VariableName, ReturnStatus ));
>
> +  return ReturnStatus;
>
> +}
>
> +
>
> +
>
> +/**
>
> +  This API function disables the variable policy enforcemen= t. If it's
>
> +  already been called once, will return EFI_ALREADY_STARTED= .
>
> +
>
> +  @retval     EFI_SUCCESS
>
> +  @retval     EFI_ALREADY_STARTED =   Has already been called once this boot.
>
> +  @retval     EFI_WRITE_PROTECTED =   Interface has been locked until reboot.
>
> +  @retval     EFI_WRITE_PROTECTED =   Interface option is disabled by platform
> PCD.
>
> +  @retval     EFI_NOT_READY  =        Library has not yet been initialized.<= br> >
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +DisableVariablePolicy (
>
> +  VOID
>
> +  )
>
> +{
>
> +  if (!IsVariablePolicyLibInitialized()) {
>
> +    return EFI_NOT_READY;
>
> +  }
>
> +  if (mProtectionDisabled) {
>
> +    return EFI_ALREADY_STARTED;
>
> +  }
>
> +  if (mInterfaceLocked) {
>
> +    return EFI_WRITE_PROTECTED;
>
> +  }
>
> +  if (!PcdGetBool (PcdAllowVariablePolicyEnforcementDisable= )) {
>
> +    return EFI_WRITE_PROTECTED;
>
> +  }
>
> +  mProtectionDisabled =3D TRUE;
>
> +  return EFI_SUCCESS;
>
> +}
>
> +
>
> +
>
> +/**
>
> +  This API function will dump the entire contents of the va= riable policy table.
>
> +
>
> +  Similar to GetVariable, the first call can be made with a= 0 size and it will
> return
>
> +  the size of the buffer required to hold the entire table.=
>
> +
>
> +  @param[out]     Policy  Pointer = to the policy buffer. Can be NULL if Size is 0.
>
> +  @param[in,out]  Size    On input, the= size of the output buffer. On output,
> the size
>
> +          &nbs= p;            &= nbsp;  of the data returned.
>
> +
>
> +  @retval     EFI_SUCCESS  &n= bsp;          Policy data is i= n the output buffer and Size
> has been updated.
>
> +  @retval     EFI_INVALID_PARAMETER&nbs= p;  Size is NULL, or Size is non-zero and
> Policy is NULL.
>
> +  @retval     EFI_BUFFER_TOO_SMALL = ;   Size is insufficient to hold policy. Size
> updated with required size.
>
> +  @retval     EFI_NOT_READY  =          Library has not yet been i= nitialized.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +DumpVariablePolicy (
>
> +  OUT     UINT8    =      *Policy,
>
> +  IN OUT  UINT32      &n= bsp; *Size
>
> +  )
>
> +{
>
> +  if (!IsVariablePolicyLibInitialized()) {
>
> +    return EFI_NOT_READY;
>
> +  }
>
> +
>
> +  // Check the parameters.
>
> +  if (Size =3D=3D NULL || (*Size > 0 && Policy = =3D=3D NULL)) {
>
> +    return EFI_INVALID_PARAMETER;
>
> +  }
>
> +
>
> +  // Make sure the size is sufficient to hold the policy ta= ble.
>
> +  if (*Size < mCurrentTableUsage) {
>
> +    *Size =3D mCurrentTableUsage;
>
> +    return EFI_BUFFER_TOO_SMALL;
>
> +  }
>
> +
>
> +  // If we're still here, copy the table and bounce.
>
> +  CopyMem( Policy, mPolicyTable, mCurrentTableUsage );
>
> +  *Size =3D mCurrentTableUsage;
>
> +
>
> +  return EFI_SUCCESS;
>
> +}
>
> +
>
> +
>
> +/**
>
> +  This API function returns whether or not the policy engin= e is
>
> +  currently being enforced.
>
> +
>
> +  @retval     TRUE
>
> +  @retval     FALSE
>
> +  @retval     FALSE   &n= bsp;     Library has not yet been initialized.
>
> +
>
> +**/
>
> +BOOLEAN
>
> +EFIAPI
>
> +IsVariablePolicyEnabled (
>
> +  VOID
>
> +  )
>
> +{
>
> +  if (!IsVariablePolicyLibInitialized()) {
>
> +    return FALSE;
>
> +  }
>
> +  return !mProtectionDisabled;
>
> +}
>
> +
>
> +
>
> +/**
>
> +  This API function locks the interface so that no more pol= icy updates
>
> +  can be performed or changes made to the enforcement until= the next
> boot.
>
> +
>
> +  @retval     EFI_SUCCESS
>
> +  @retval     EFI_NOT_READY  = Library has not yet been initialized.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +LockVariablePolicy (
>
> +  VOID
>
> +  )
>
> +{
>
> +  if (!IsVariablePolicyLibInitialized()) {
>
> +    return EFI_NOT_READY;
>
> +  }
>
> +  if (mInterfaceLocked) {
>
> +    return EFI_WRITE_PROTECTED;
>
> +  }
>
> +  mInterfaceLocked =3D TRUE;
>
> +  return EFI_SUCCESS;
>
> +}
>
> +
>
> +
>
> +/**
>
> +  This API function returns whether or not the policy inter= face is locked
>
> +  for the remainder of the boot.
>
> +
>
> +  @retval     TRUE
>
> +  @retval     FALSE
>
> +  @retval     FALSE   &n= bsp;     Library has not yet been initialized.
>
> +
>
> +**/
>
> +BOOLEAN
>
> +EFIAPI
>
> +IsVariablePolicyInterfaceLocked (
>
> +  VOID
>
> +  )
>
> +{
>
> +  if (!IsVariablePolicyLibInitialized()) {
>
> +    return FALSE;
>
> +  }
>
> +  return mInterfaceLocked;
>
> +}
>
> +
>
> +
>
> +/**
>
> +  This helper function initializes the library and sets
>
> +  up any required internal structures or handlers.
>
> +
>
> +  Also registers the internal pointer for the GetVariable h= elper.
>
> +
>
> +  @param[in]  GetVariableHelper A function pointer mat= ching the
> EFI_GET_VARIABLE prototype that will be used to
>
> +          &nbs= p;       check policy criteria that involve t= he existence of other variables.
>
> +
>
> +  @retval     EFI_SUCCESS
>
> +  @retval     EFI_ALREADY_STARTED =   The initialize function has been called
> more than once without a call to
>
> +          &nbs= p;            &= nbsp;            dei= nitialize.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +InitVariablePolicyLib (
>
> +  IN  EFI_GET_VARIABLE    GetVariableHe= lper
>
> +  )
>
> +{
>
> +  EFI_STATUS    Status;
>
> +
>
> +  Status =3D EFI_SUCCESS;
>
> +  if (mGetVariableHelper !=3D NULL) {
>
> +    Status =3D EFI_ALREADY_STARTED;

4. [Dandan]: Could we return directly here?

>
> +  }
>
> +
>
> +  if (!EFI_ERROR( Status )) {
>
> +    Status =3D VariablePolicyExtraInit();
>
> +  }
>
> +
>
> +  if (!EFI_ERROR( Status )) {
>
> +    // Save an internal pointer to the GetVariabl= eHelper.
>
> +    mGetVariableHelper =3D GetVariableHelper;
>
> +
>
> +    // Initialize the global state.
>
> +    mInterfaceLocked =3D FALSE;
>
> +    mProtectionDisabled =3D FALSE;
>
> +    mPolicyTable =3D NULL;
>
> +    mCurrentTableSize =3D 0;
>
> +    mCurrentTableUsage =3D 0;
>
> +    mCurrentTableCount =3D 0;
>
> +  }
>
> +
>
> +  return Status;
>
> +}
>
> +
>
> +
>
> +/**
>
> +  This helper function returns whether or not the library i= s currently
> initialized.
>
> +
>
> +  @retval     TRUE
>
> +  @retval     FALSE
>
> +
>
> +**/
>
> +BOOLEAN
>
> +EFIAPI
>
> +IsVariablePolicyLibInitialized (
>
> +  VOID
>
> +  )
>
> +{
>
> +  return (mGetVariableHelper !=3D NULL);
>
> +}
>
> +
>
> +
>
> +/**
>
> +  This helper function tears down  the library.
>
> +
>
> +  Should generally only be used for test harnesses.
>
> +
>
> +  @retval     EFI_SUCCESS
>
> +  @retval     EFI_NOT_READY  =    Deinitialize was called without first calling
> initialize.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +DeinitVariablePolicyLib (
>
> +  VOID
>
> +  )
>
> +{
>
> +  EFI_STATUS    Status;
>
> +
>
> +  Status =3D EFI_SUCCESS;
>
> +
>
> +  if (mGetVariableHelper =3D=3D NULL) {
>
> +    Status =3D EFI_NOT_READY;
>
> +  }
>
> +
>
> +  if (!EFI_ERROR( Status )) {
>
> +    Status =3D VariablePolicyExtraDeinit();
>
> +  }
>
> +
>
> +  if (!EFI_ERROR( Status )) {
>
> +    mGetVariableHelper =3D NULL;
>
> +    mInterfaceLocked =3D FALSE;
>
> +    mProtectionDisabled =3D FALSE;
>
> +    mCurrentTableSize =3D 0;
>
> +    mCurrentTableUsage =3D 0;
>
> +    mCurrentTableCount =3D 0;
>
> +
>
> +    if (mPolicyTable !=3D NULL) {
>
> +      FreePool( mPolicyTable );
>
> +      mPolicyTable =3D NULL;
>
> +    }
>
> +  }
>
> +
>
> +  return Status;
>
> +}
>
> diff --git
> a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/Varia= ble
> PolicyUnitTest.c
> b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/Varia= ble
> PolicyUnitTest.c
> new file mode 100644
> index 000000000000..f133f2f30e36
> --- /dev/null
> +++
> b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/Varia= ble
> PolicyUnitTest.c
> @@ -0,0 +1,2436 @@
> +/** @file -- VariablePolicyUnitTest.c
>
> +UnitTest for...
>
> +Business logic for Variable Policy enforcement.
>
> +
>
> +Copyright (c) Microsoft Corporation.
>
> +SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +
>
> +**/
>
> +
>
> +#include <stdio.h>
>
> +#include <string.h>
>
> +#include <stdarg.h>
>
> +#include <stddef.h>
>
> +#include <setjmp.h>
>
> +#include <cmocka.h>
>
> +
>
> +#include <Uefi.h>
>
> +#include <Library/PrintLib.h>
>
> +#include <Library/DebugLib.h>
>
> +#include <Library/UnitTestLib.h>
>
> +#include <Library/BaseMemoryLib.h>
>
> +#include <Library/MemoryAllocationLib.h>
>
> +#include <Library/BaseLib.h>
>
> +
>
> +#include <Guid/VariableFormat.h>
>
> +
>
> +#include <Protocol/VariablePolicy.h>
>
> +#include <Library/VariablePolicyLib.h>
>
> +
>
> +// MU_CHANGE - Turn this off for now. Try to turn it back on wit= h extra
> build options.
>
> +// #ifndef INTERNAL_UNIT_TEST
>
> +// #error Make sure to build thie with INTERNAL_UNIT_TEST enable= d!
> Otherwise, some important tests may be skipped!
>
> +// #endif
>
> +
>
> +
>
> +#define UNIT_TEST_NAME       = "UEFI Variable Policy UnitTest"
>
> +#define UNIT_TEST_VERSION     "0.5"= ;
>
> +
>
> +///=3D=3D=3D TEST DATA
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= = =3D
>
> +
>
> +#pragma pack(push, 1)
>
> +typedef struct _SIMPLE_VARIABLE_POLICY_ENTRY {
>
> +  VARIABLE_POLICY_ENTRY     Header;
>
> +  CHAR16        &nb= sp;           Name[];
>
> +} SIMPLE_VARIABLE_POLICY_ENTRY;
>
> +#define EXPANDED_VARIABLE_POLICY_ENTRY_VAR_NAME_LENGTH  100= 1
> // 1000 characters + terminator.
>
> +#define EXPANDED_VARIABLE_POLICY_ENTRY_VAR_NAME_SIZE
> (EXPANDED_VARIABLE_POLICY_ENTRY_VAR_NAME_LENGTH *
> sizeof(CHAR16))
>
> +typedef struct _EXPANDED_VARIABLE_POLICY_ENTRY {
>
> +  VARIABLE_POLICY_ENTRY      =          Header;
>
> +  VARIABLE_LOCK_ON_VAR_STATE_POLICY   StatePolicy= ;
>
> +  CHAR16
> StateName[EXPANDED_VARIABLE_POLICY_ENTRY_VAR_NAME_LENGTH];
>
> +  CHAR16
> Name[EXPANDED_VARIABLE_POLICY_ENTRY_VAR_NAME_LENGTH];
>
> +} EXPANDED_VARIABLE_POLICY_ENTRY;
>
> +#pragma pack(pop)
>
> +
>
> +// {F955BA2D-4A2C-480C-BFD1-3CC522610592}
>
> +#define TEST_GUID_1 { 0xf955ba2d, 0x4a2c, 0x480c, { 0xbf, 0xd1, = 0x3c, 0xc5,
> 0x22, 0x61, 0x5, 0x92 } }
>
> +EFI_GUID    mTestGuid1 =3D TEST_GUID_1;
>
> +// {2DEA799E-5E73-43B9-870E-C945CE82AF3A}
>
> +#define TEST_GUID_2 { 0x2dea799e, 0x5e73, 0x43b9, { 0x87, 0xe, 0= xc9, 0x45,
> 0xce, 0x82, 0xaf, 0x3a } }
>
> +EFI_GUID    mTestGuid2 =3D TEST_GUID_2;
>
> +// {698A2BFD-A616-482D-B88C-7100BD6682A9}
>
> +#define TEST_GUID_3 { 0x698a2bfd, 0xa616, 0x482d, { 0xb8, 0x8c, = 0x71, 0x0,
> 0xbd, 0x66, 0x82, 0xa9 } }
>
> +EFI_GUID    mTestGuid3 =3D TEST_GUID_3;
>
> +
>
> +#define   TEST_VAR_1_NAME     = ;            L"= TestVar1"
>
> +#define   TEST_VAR_2_NAME     = ;            L"= TestVar2"
>
> +#define   TEST_VAR_3_NAME     = ;            L"= TestVar3"
>
> +
>
> +#define   TEST_POLICY_ATTRIBUTES_NULL   = ;  0
>
> +#define   TEST_POLICY_MIN_SIZE_NULL   &= nbsp;   0
>
> +#define   TEST_POLICY_MAX_SIZE_NULL   &= nbsp;   MAX_UINT32
>
> +
>
> +#define   TEST_POLICY_MIN_SIZE_10   &nb= sp;     10
>
> +#define   TEST_POLICY_MAX_SIZE_200   &n= bsp;    200
>
> +
>
> +#define TEST_300_HASHES_STRING
> L"##################################################"\
>
> +
> "##################################################"\
>
> +
> "##################################################"\
>
> +
> "##################################################"\
>
> +
> "##################################################"\
>
> +
> "##################################################"
>
> +
>
> +
>
> +///=3D=3D=3D HELPER FUNCTIONS
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
>
> +
>
> +/**
>
> +  Helper function to initialize a VARIABLE_POLICY_ENTRY str= ucture with a
> Name and StateName.
>
> +
>
> +  Takes care of all the messy packing.
>
> +
>
> +  @param[in,out]  Entry
>
> +  @param[in]      Name  =       [Optional]
>
> +  @param[in]      StateName &= nbsp; [Optional]
>
> +
>
> +  @retval     TRUE
>
> +  @retval     FALSE
>
> +
>
> +**/
>
> +STATIC
>
> +BOOLEAN
>
> +InitExpVarPolicyStrings (
>
> +  EXPANDED_VARIABLE_POLICY_ENTRY    &nb= sp; *Entry,
>
> +  CHAR16        &nb= sp;            =          *Name,   &n= bsp;  OPTIONAL
>
> +  CHAR16        &nb= sp;            =          *StateName  OPTIONAL<= br> >
> +  )
>
> +{
>
> +  UINTN     NameSize;
>
> +  UINTN     StateNameSize;
>
> +
>
> +  NameSize =3D Name =3D=3D NULL ? 0 : StrSize( Name );
>
> +  StateNameSize =3D StateName =3D=3D NULL ? 0 : StrSize( St= ateName );
>
> +
>
> +  if (NameSize > EXPANDED_VARIABLE_POLICY_ENTRY_VAR_NAME= _SIZE ||
> NameSize > MAX_UINT16 ||
>
> +      StateNameSize >
> EXPANDED_VARIABLE_POLICY_ENTRY_VAR_NAME_SIZE || StateNameSize > > MAX_UINT16) {
>
> +    return FALSE;
>
> +  }
>
> +
>
> +  Entry->Header.OffsetToName =3D sizeof(VARIABLE_POLICY_= ENTRY);
>
> +  if (StateName !=3D NULL) {
>
> +    Entry->Header.OffsetToName +=3D
> (UINT16)sizeof(VARIABLE_LOCK_ON_VAR_STATE_POLICY) +
> (UINT16)StateNameSize;
>
> +  }
>
> +  Entry->Header.Size =3D Entry->Header.OffsetToName &= #43; (UINT16)NameSize;
>
> +
>
> +  CopyMem( (UINT8*)Entry + Entry->Header.OffsetToNam= e, Name,
> NameSize );
>
> +  if (StateName !=3D NULL) {
>
> +    CopyMem( (UINT8*)Entry + sizeof(VARIABLE_= POLICY_ENTRY) +
> sizeof(VARIABLE_LOCK_ON_VAR_STATE_POLICY), StateName,
> StateNameSize );
>
> +  }
>
> +
>
> +  return TRUE;
>
> +}
>
> +
>
> +/**
>
> +  Mocked version of GetVariable, for testing.
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +StubGetVariableNull (
>
> +  IN     CHAR16    =             &nb= sp;     *VariableName,
>
> +  IN     EFI_GUID   &nbs= p;            &= nbsp;   *VendorGuid,
>
> +  OUT    UINT32     = ;            &n= bsp;    *Attributes,    OPTIONAL
>
> +  IN OUT UINTN       &nb= sp;            =    *DataSize,
>
> +  OUT    VOID     &= nbsp;           &nbs= p;      *Data      &= nbsp;    OPTIONAL
>
> +  )
>
> +{
>
> +  UINT32      MockedAttr;
>
> +  UINTN       MockedDataSize;=
>
> +  VOID        *MockedDat= a;
>
> +  EFI_STATUS  MockedReturn;
>
> +
>
> +  check_expected_ptr( VariableName );
>
> +  check_expected_ptr( VendorGuid );
>
> +  check_expected_ptr( DataSize );
>
> +
>
> +  MockedAttr =3D (UINT32)mock();
>
> +  MockedDataSize =3D (UINTN)mock();
>
> +  MockedData =3D (VOID*)mock();
>
> +  MockedReturn =3D (EFI_STATUS)mock();
>
> +
>
> +  if (Attributes !=3D NULL) {
>
> +    *Attributes =3D MockedAttr;
>
> +  }
>
> +  if (Data !=3D NULL && !EFI_ERROR(MockedReturn)) {=
>
> +    CopyMem( Data, MockedData, MockedDataSize );<= br> >
> +  }
>
> +
>
> +  *DataSize =3D MockedDataSize;
>
> +
>
> +  return MockedReturn;
>
> +}
>
> +
>
> +//
>
> +// Anything you think might be helpful that isn't a test itself.=
>
> +//
>
> +
>
> +/**
>
> +  This is a common setup function that will ensure the libr= ary is always
> initialized
>
> +  with the stubbed GetVariable.
>
> +
>
> +  Not used by all test cases, but by most.
>
> +**/
>
> +STATIC
>
> +UNIT_TEST_STATUS
>
> +LibInitMocked (
>
> +  IN UNIT_TEST_CONTEXT      Contex= t
>
> +  )
>
> +{
>
> +  return EFI_ERROR(InitVariablePolicyLib( StubGetVariableNu= ll )) ?
> UNIT_TEST_ERROR_PREREQUISITE_NOT_MET : UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> +  Common cleanup function to make sure that the library is = always de-
> initialized prior
>
> +  to the next test case.
>
> +*/
>
> +STATIC
>
> +VOID
>
> +LibCleanup (
>
> +  IN UNIT_TEST_CONTEXT      Contex= t
>
> +  )
>
> +{
>
> +  DeinitVariablePolicyLib();
>
> +}
>
> +
>
> +
>
> +///=3D=3D=3D TEST CASES
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
>
> +
>
> +///=3D=3D=3D=3D=3D ARCHITECTURAL SUITE
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +ShouldBeAbleToInitAndDeinitTheLibrary (
>
> +  IN UNIT_TEST_CONTEXT      Contex= t
>
> +  )
>
> +{
>
> +  EFI_STATUS    Status;
>
> +  Status =3D InitVariablePolicyLib( StubGetVariableNull );<= br> >
> +  UT_ASSERT_NOT_EFI_ERROR( Status );
>
> +
>
> +  UT_ASSERT_TRUE( IsVariablePolicyLibInitialized() );
>
> +
>
> +  Status =3D DeinitVariablePolicyLib();
>
> +  UT_ASSERT_NOT_EFI_ERROR( Status );
>
> +
>
> +  UT_ASSERT_FALSE( IsVariablePolicyLibInitialized() );
>
> +
>
> +  return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +ShouldNotBeAbleToInitializeTheLibraryTwice (
>
> +  IN UNIT_TEST_CONTEXT      Contex= t
>
> +  )
>
> +{
>
> +  EFI_STATUS    Status;
>
> +  Status =3D InitVariablePolicyLib( StubGetVariableNull );<= br> >
> +  UT_ASSERT_NOT_EFI_ERROR( Status );
>
> +  Status =3D InitVariablePolicyLib( StubGetVariableNull );<= br> >
> +  UT_ASSERT_TRUE( EFI_ERROR( Status ) );
>
> +  return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +ShouldFailDeinitWithoutInit (
>
> +  IN UNIT_TEST_CONTEXT      Contex= t
>
> +  )
>
> +{
>
> +  EFI_STATUS    Status;
>
> +  Status =3D DeinitVariablePolicyLib();
>
> +  UT_ASSERT_TRUE( EFI_ERROR( Status ) );
>
> +  return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +ApiCommandsShouldNotRespondIfLibIsUninitialized (
>
> +  IN UNIT_TEST_CONTEXT      Contex= t
>
> +  )
>
> +{
>
> +  SIMPLE_VARIABLE_POLICY_ENTRY   TestPolicy =3D {=
>
> +    {
>
> +      VARIABLE_POLICY_ENTRY_REVISION, >
> +      sizeof(VARIABLE_POLICY_ENTRY) = 3; sizeof(TEST_VAR_1_NAME),
>
> +      sizeof(VARIABLE_POLICY_ENTRY), >
> +      TEST_GUID_1,
>
> +      TEST_POLICY_MIN_SIZE_NULL,
>
> +      TEST_POLICY_MAX_SIZE_NULL,
>
> +      TEST_POLICY_ATTRIBUTES_NULL,
>
> +      TEST_POLICY_ATTRIBUTES_NULL,
>
> +      VARIABLE_POLICY_TYPE_NO_LOCK
>
> +    },
>
> +    TEST_VAR_1_NAME
>
> +  };
>
> +  UINT8     DummyData[8];
>
> +  UINT32    DummyDataSize =3D sizeof(DummyDa= ta);
>
> +
>
> +  // This test should not start with an initialized library= .
>
> +
>
> +  // Verify that all API commands fail.
>
> +  UT_ASSERT_TRUE( EFI_ERROR( LockVariablePolicy() ) );
>
> +  UT_ASSERT_TRUE( EFI_ERROR( DisableVariablePolicy() ) ); >
> +
> UT_ASSERT_TRUE( EFI_ERROR( RegisterVariablePolicy( &TestPolicy.He= ader )
> ) );
>
> +  UT_ASSERT_TRUE( EFI_ERROR( DumpVariablePolicy( DummyData,=
> &DummyDataSize ) ) );
>
> +  UT_ASSERT_FALSE( IsVariablePolicyInterfaceLocked() );
>
> +  UT_ASSERT_FALSE( IsVariablePolicyEnabled() );
>
> +  UT_ASSERT_TRUE( EFI_ERROR( ValidateSetVariable( TEST_VAR_= 1_NAME,
>
> +          &nbs= p;            &= nbsp;           &nbs= p;             = &mTestGuid1,
>
> +          &nbs= p;            &= nbsp;           &nbs= p;             = VARIABLE_ATTRIBUTE_NV_BS,
>
> +          &nbs= p;            &= nbsp;           &nbs= p;             = sizeof(DummyData),
>
> +          &nbs= p;            &= nbsp;           &nbs= p;             = DummyData ) ) );
>
> +
>
> +  return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +
>
> +///=3D=3D=3D=3D=3D INTERNAL FUNCTION SUITE
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
>
> +
>
> +#ifdef INTERNAL_UNIT_TEST
>
> +
>
> +BOOLEAN
>
> +EvaluatePolicyMatch (
>
> +  IN CONST  VARIABLE_POLICY_ENTRY   *EvalEnt= ry,
>
> +  IN CONST  CHAR16      =             *Variabl= eName,
>
> +  IN CONST  EFI_GUID     &nbs= p;          *VendorGuid,
>
> +  OUT       UINT8  =             &nb= sp;    *MatchPriority    OPTIONAL
>
> +  );
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +PoliciesShouldMatchByNameAndGuid (
>
> +  IN UNIT_TEST_CONTEXT      Contex= t
>
> +  )
>
> +{
>
> +  SIMPLE_VARIABLE_POLICY_ENTRY   MatchCheckPolicy= =3D {
>
> +    {
>
> +      VARIABLE_POLICY_ENTRY_REVISION, >
> +      sizeof(VARIABLE_POLICY_ENTRY) = 3; sizeof(TEST_VAR_1_NAME),
>
> +      sizeof(VARIABLE_POLICY_ENTRY), >
> +      TEST_GUID_1,
>
> +      TEST_POLICY_MIN_SIZE_NULL,
>
> +      TEST_POLICY_MAX_SIZE_NULL,
>
> +      TEST_POLICY_ATTRIBUTES_NULL,
>
> +      TEST_POLICY_ATTRIBUTES_NULL,
>
> +      VARIABLE_POLICY_TYPE_NO_LOCK
>
> +    },
>
> +    TEST_VAR_1_NAME
>
> +  };
>
> +  CHAR16        *CheckVa= r1Name =3D TEST_VAR_1_NAME;
>
> +  CHAR16        *CheckVa= r2Name =3D TEST_VAR_2_NAME;
>
> +
>
> +  // Make sure that a different name does not match.
>
> +  UT_ASSERT_FALSE( EvaluatePolicyMatch( &MatchCheckPoli= cy.Header,
> CheckVar2Name, &mTestGuid1, NULL ) );
>
> +
>
> +  // Make sure that a different GUID does not match.
>
> +  UT_ASSERT_FALSE( EvaluatePolicyMatch( &MatchCheckPoli= cy.Header,
> CheckVar1Name, &mTestGuid2, NULL ) );
>
> +
>
> +  // Make sure that the same name and GUID match.
>
> +  UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolic= y.Header,
> CheckVar1Name, &mTestGuid1, NULL ) );
>
> +
>
> +  return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +WildcardPoliciesShouldMatchDigits (
>
> +  IN UNIT_TEST_CONTEXT      Contex= t
>
> +  )
>
> +{
>
> +  SIMPLE_VARIABLE_POLICY_ENTRY   MatchCheckPolicy= =3D {
>
> +    {
>
> +      VARIABLE_POLICY_ENTRY_REVISION, >
> +      sizeof(VARIABLE_POLICY_ENTRY) = 3; sizeof(L"Wildcard#VarName##"),
>
> +      sizeof(VARIABLE_POLICY_ENTRY), >
> +      TEST_GUID_1,
>
> +      TEST_POLICY_MIN_SIZE_NULL,
>
> +      TEST_POLICY_MAX_SIZE_NULL,
>
> +      TEST_POLICY_ATTRIBUTES_NULL,
>
> +      TEST_POLICY_ATTRIBUTES_NULL,
>
> +      VARIABLE_POLICY_TYPE_NO_LOCK
>
> +    },
>
> +    L"Wildcard#VarName##"
>
> +  };
>
> +  CHAR16        *CheckVa= r1Name =3D L"Wildcard1VarName12";
>
> +  CHAR16        *CheckVa= r2Name =3D L"Wildcard2VarName34";
>
> +  CHAR16        *CheckVa= rBName =3D L"WildcardBVarName56";
>
> +  CHAR16        *CheckVa= rHName =3D L"Wildcard#VarName56";
>
> +
>
> +  // Make sure that two different sets of wildcard numbers = match.
>
> +  UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolic= y.Header,
> CheckVar1Name, &mTestGuid1, NULL ) );
>
> +  UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolic= y.Header,
> CheckVar2Name, &mTestGuid1, NULL ) );
>
> +
>
> +  // Make sure that the non-number charaters don't match. >
> +  UT_ASSERT_FALSE( EvaluatePolicyMatch( &MatchCheckPoli= cy.Header,
> CheckVarBName, &mTestGuid1, NULL ) );
>
> +
>
> +  // Make sure that '#' signs don't match.
>
> +  UT_ASSERT_FALSE( EvaluatePolicyMatch( &MatchCheckPoli= cy.Header,
> CheckVarHName, &mTestGuid1, NULL ) );
>
> +
>
> +  return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +WildcardPoliciesShouldMatchDigitsAdvanced (
>
> +  IN UNIT_TEST_CONTEXT      Contex= t
>
> +  )
>
> +{
>
> +  SIMPLE_VARIABLE_POLICY_ENTRY   MatchCheckPolicy= =3D {
>
> +    {
>
> +      VARIABLE_POLICY_ENTRY_REVISION, >
> +      sizeof(VARIABLE_POLICY_ENTRY) = 3; sizeof(TEST_300_HASHES_STRING),
>
> +      sizeof(VARIABLE_POLICY_ENTRY), >
> +      TEST_GUID_1,
>
> +      TEST_POLICY_MIN_SIZE_NULL,
>
> +      TEST_POLICY_MAX_SIZE_NULL,
>
> +      TEST_POLICY_ATTRIBUTES_NULL,
>
> +      TEST_POLICY_ATTRIBUTES_NULL,
>
> +      VARIABLE_POLICY_TYPE_NO_LOCK
>
> +    },
>
> +    TEST_300_HASHES_STRING
>
> +  };
>
> +  CHAR16        *CheckSh= orterString =3D
> L"01234567890123456789012345678901234567890123456789";
>
> +  CHAR16        *CheckVa= lidString =3D
> L"01234567890123456789012345678901234567890123456789"\
>
> +
> "01234567890123456789012345678901234567890123456789"\
>
> +
> "01234567890123456789012345678901234567890123456789"\
>
> +
> "01234567890123456789012345678901234567890123456789"\
>
> +
> "01234567890123456789012345678901234567890123456789"\
>
> +
> "01234567890123456789012345678901234567890123456789";
>
> +  CHAR16        *CheckLo= ngerString =3D
> L"01234567890123456789012345678901234567890123456789"\
>
> +
> "01234567890123456789012345678901234567890123456789"\
>
> +
> "01234567890123456789012345678901234567890123456789"\
>
> +
> "01234567890123456789012345678901234567890123456789"\
>
> +
> "01234567890123456789012345678901234567890123456789"\
>
> +
> "01234567890123456789012345678901234567890123456789"\
>
> +
> "01234567890123456789012345678901234567890123456789";
>
> +  UINT8         Mat= chPriority;
>
> +
>
> +  // Make sure that the shorter and the longer do not match= .
>
> +  UT_ASSERT_FALSE( EvaluatePolicyMatch( &MatchCheckPoli= cy.Header,
> CheckShorterString, &mTestGuid1, NULL ) );
>
> +  UT_ASSERT_FALSE( EvaluatePolicyMatch( &MatchCheckPoli= cy.Header,
> CheckLongerString, &mTestGuid1, NULL ) );
>
> +
>
> +  // Make sure that the valid one matches and has the expec= ted priority.
>
> +  UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolic= y.Header,
> CheckValidString, &mTestGuid1, &MatchPriority ) );
>
> +  UT_ASSERT_EQUAL( MatchPriority, MAX_UINT8 );
>
> +
>
> +  return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +WildcardPoliciesShouldMatchNamespaces (
>
> +  IN UNIT_TEST_CONTEXT      Contex= t
>
> +  )
>
> +{
>
> +  VARIABLE_POLICY_ENTRY   MatchCheckPolicy =3D {<= br> >
> +    VARIABLE_POLICY_ENTRY_REVISION,
>
> +    sizeof(VARIABLE_POLICY_ENTRY),
>
> +    sizeof(VARIABLE_POLICY_ENTRY),
>
> +    TEST_GUID_1,
>
> +    TEST_POLICY_MIN_SIZE_NULL,
>
> +    TEST_POLICY_MAX_SIZE_NULL,
>
> +    TEST_POLICY_ATTRIBUTES_NULL,
>
> +    TEST_POLICY_ATTRIBUTES_NULL,
>
> +    VARIABLE_POLICY_TYPE_NO_LOCK
>
> +  };
>
> +  CHAR16        *CheckVa= r1Name =3D L"Wildcard1VarName12";
>
> +  CHAR16        *CheckVa= r2Name =3D L"Wildcard2VarName34";
>
> +  CHAR16        *CheckVa= rBName =3D L"WildcardBVarName56";
>
> +  CHAR16        *CheckVa= rHName =3D L"Wildcard#VarName56";
>
> +
>
> +  // Make sure that all names in the same namespace match.<= br> >
> +  UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolic= y,
> CheckVar1Name, &mTestGuid1, NULL ) );
>
> +  UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolic= y,
> CheckVar2Name, &mTestGuid1, NULL ) );
>
> +  UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolic= y,
> CheckVarBName, &mTestGuid1, NULL ) );
>
> +  UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolic= y,
> CheckVarHName, &mTestGuid1, NULL ) );
>
> +
>
> +  // Make sure that different namespace doesn't match.
>
> +  UT_ASSERT_FALSE( EvaluatePolicyMatch( &MatchCheckPoli= cy,
> CheckVar1Name, &mTestGuid2, NULL ) );
>
> +
>
> +
>
> +  return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +MatchPrioritiesShouldFollowRules (
>
> +  IN UNIT_TEST_CONTEXT      Contex= t
>
> +  )
>
> +{
>
> +  SIMPLE_VARIABLE_POLICY_ENTRY   MatchCheckPolicy= =3D {
>
> +    {
>
> +      VARIABLE_POLICY_ENTRY_REVISION, >
> +      sizeof(VARIABLE_POLICY_ENTRY) = 3; sizeof(L"Wildcard1VarName12"),
>
> +      sizeof(VARIABLE_POLICY_ENTRY), >
> +      TEST_GUID_1,
>
> +      TEST_POLICY_MIN_SIZE_NULL,
>
> +      TEST_POLICY_MAX_SIZE_NULL,
>
> +      TEST_POLICY_ATTRIBUTES_NULL,
>
> +      TEST_POLICY_ATTRIBUTES_NULL,
>
> +      VARIABLE_POLICY_TYPE_NO_LOCK
>
> +    },
>
> +    L"Wildcard1VarName12"
>
> +  };
>
> +  CHAR16        CheckVar= 1Name[] =3D L"Wildcard1VarName12";
>
> +  CHAR16        MatchVar= 1Name[] =3D L"Wildcard1VarName12";
>
> +  CHAR16        MatchVar= 2Name[] =3D L"Wildcard#VarName12";
>
> +  CHAR16        MatchVar= 3Name[] =3D L"Wildcard#VarName#2";
>
> +  CHAR16        MatchVar= 4Name[] =3D L"Wildcard#VarName##";
>
> +  UINT8         Mat= chPriority;
>
> +
>
> +  // Check with a perfect match.
>
> +  CopyMem( &MatchCheckPolicy.Name, MatchVar1Name,
> sizeof(MatchVar1Name) );
>
> +  UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolic= y.Header,
> CheckVar1Name, &mTestGuid1, &MatchPriority ) );
>
> +  UT_ASSERT_EQUAL( MatchPriority, 0 );
>
> +
>
> +  // Check with progressively lower priority matches.
>
> +  CopyMem( &MatchCheckPolicy.Name, MatchVar2Name,
> sizeof(MatchVar2Name) );
>
> +  UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolic= y.Header,
> CheckVar1Name, &mTestGuid1, &MatchPriority ) );
>
> +  UT_ASSERT_EQUAL( MatchPriority, 1 );
>
> +  CopyMem( &MatchCheckPolicy.Name, MatchVar3Name,
> sizeof(MatchVar3Name) );
>
> +  UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolic= y.Header,
> CheckVar1Name, &mTestGuid1, &MatchPriority ) );
>
> +  UT_ASSERT_EQUAL( MatchPriority, 2 );
>
> +  CopyMem( &MatchCheckPolicy.Name, MatchVar4Name,
> sizeof(MatchVar4Name) );
>
> +  UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolic= y.Header,
> CheckVar1Name, &mTestGuid1, &MatchPriority ) );
>
> +  UT_ASSERT_EQUAL( MatchPriority, 3 );
>
> +
>
> +  // Check against the entire namespace.
>
> +  MatchCheckPolicy.Header.Size =3D sizeof(VARIABLE_POLICY_E= NTRY);
>
> +  UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolic= y.Header,
> CheckVar1Name, &mTestGuid1, &MatchPriority ) );
>
> +  UT_ASSERT_EQUAL( MatchPriority, MAX_UINT8 );
>
> +
>
> +  return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +#endif // INTERNAL_UNIT_TEST
>
> +
>
> +
>
> +///=3D=3D=3D POLICY MANIPULATION SUITE
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +RegisterShouldAllowNamespaceWildcards (
>
> +  IN UNIT_TEST_CONTEXT      Contex= t
>
> +  )
>
> +{
>
> +  SIMPLE_VARIABLE_POLICY_ENTRY   ValidationPolicy= =3D {
>
> +    {
>
> +      VARIABLE_POLICY_ENTRY_REVISION, >
> +      sizeof(VARIABLE_POLICY_ENTRY), >
> +      sizeof(VARIABLE_POLICY_ENTRY), >
> +      TEST_GUID_1,
>
> +      TEST_POLICY_MIN_SIZE_NULL,
>
> +      TEST_POLICY_MAX_SIZE_NULL,
>
> +      TEST_POLICY_ATTRIBUTES_NULL,
>
> +      TEST_POLICY_ATTRIBUTES_NULL,
>
> +      VARIABLE_POLICY_TYPE_NO_LOCK
>
> +    },
>
> +    L""
>
> +  };
>
> +
>
> +
> UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolic= y.Hea
> der ) );
>
> +
>
> +  return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +RegisterShouldAllowStateVarsForNamespaces (
>
> +  IN UNIT_TEST_CONTEXT      Contex= t
>
> +  )
>
> +{
>
> +  EXPANDED_VARIABLE_POLICY_ENTRY   ValidationPoli= cy =3D {
>
> +    {
>
> +      VARIABLE_POLICY_ENTRY_REVISION, >
> +      0,    // Will be p= opulated by init helper.
>
> +      0,    // Will be p= opulated by init helper.
>
> +      TEST_GUID_1,
>
> +      TEST_POLICY_MIN_SIZE_NULL,
>
> +      TEST_POLICY_MAX_SIZE_NULL,
>
> +      TEST_POLICY_ATTRIBUTES_NULL,
>
> +      TEST_POLICY_ATTRIBUTES_NULL,
>
> +      VARIABLE_POLICY_TYPE_LOCK_ON_VAR_= STATE
>
> +    },
>
> +    {
>
> +      TEST_GUID_2,
>
> +      1,     &= nbsp;      // Value
>
> +      0     &n= bsp;       // Padding
>
> +    },
>
> +    L"",
>
> +    L""
>
> +  };
>
> +  UT_ASSERT_TRUE( InitExpVarPolicyStrings( &ValidationP= olicy, NULL,
> TEST_VAR_2_NAME ) );
>
> +
>
> +
> UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolic= y.Hea
> der ) );
>
> +
>
> +  return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +RegisterShouldRejectNullPointers (
>
> +  IN UNIT_TEST_CONTEXT      Contex= t
>
> +  )
>
> +{
>
> +  UT_ASSERT_EQUAL( RegisterVariablePolicy( NULL ),
> EFI_INVALID_PARAMETER );
>
> +  return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +RegisterShouldRejectBadRevisions (
>
> +  IN UNIT_TEST_CONTEXT      Contex= t
>
> +  )
>
> +{
>
> +  SIMPLE_VARIABLE_POLICY_ENTRY   ValidationPolicy= =3D {
>
> +    {
>
> +      VARIABLE_POLICY_ENTRY_REVISION, >
> +      sizeof(VARIABLE_POLICY_ENTRY) = 3; sizeof(TEST_VAR_1_NAME),
>
> +      sizeof(VARIABLE_POLICY_ENTRY), >
> +      TEST_GUID_1,
>
> +      TEST_POLICY_MIN_SIZE_NULL,
>
> +      TEST_POLICY_MAX_SIZE_NULL,
>
> +      TEST_POLICY_ATTRIBUTES_NULL,
>
> +      TEST_POLICY_ATTRIBUTES_NULL,
>
> +      VARIABLE_POLICY_TYPE_NO_LOCK
>
> +    },
>
> +    TEST_VAR_1_NAME
>
> +  };
>
> +
>
> +  ValidationPolicy.Header.Version =3D MAX_UINT32;
>
> +  UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationP= olicy.Header ),
> EFI_INVALID_PARAMETER );
>
> +
>
> +  return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +RegisterShouldRejectBadSizes (
>
> +  IN UNIT_TEST_CONTEXT      Contex= t
>
> +  )
>
> +{
>
> +  SIMPLE_VARIABLE_POLICY_ENTRY   ValidationPolicy= =3D {
>
> +    {
>
> +      VARIABLE_POLICY_ENTRY_REVISION, >
> +      sizeof(VARIABLE_POLICY_ENTRY) = 3; sizeof(TEST_VAR_1_NAME),
>
> +      sizeof(VARIABLE_POLICY_ENTRY), >
> +      TEST_GUID_1,
>
> +      TEST_POLICY_MIN_SIZE_NULL,
>
> +      TEST_POLICY_MAX_SIZE_NULL,
>
> +      TEST_POLICY_ATTRIBUTES_NULL,
>
> +      TEST_POLICY_ATTRIBUTES_NULL,
>
> +      VARIABLE_POLICY_TYPE_NO_LOCK
>
> +    },
>
> +    TEST_VAR_1_NAME
>
> +  };
>
> +
>
> +  ValidationPolicy.Header.Size =3D sizeof(VARIABLE_POLICY_E= NTRY) - 2;
>
> +  UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationP= olicy.Header ),
> EFI_INVALID_PARAMETER );
>
> +
>
> +  return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +RegisterShouldRejectBadOffsets (
>
> +  IN UNIT_TEST_CONTEXT      Contex= t
>
> +  )
>
> +{
>
> +  EXPANDED_VARIABLE_POLICY_ENTRY   ValidationPoli= cy =3D {
>
> +    {
>
> +      VARIABLE_POLICY_ENTRY_REVISION, >
> +      0,    // Will be p= opulated by init helper.
>
> +      0,    // Will be p= opulated by init helper.
>
> +      TEST_GUID_1,
>
> +      TEST_POLICY_MIN_SIZE_NULL,
>
> +      TEST_POLICY_MAX_SIZE_NULL,
>
> +      TEST_POLICY_ATTRIBUTES_NULL,
>
> +      TEST_POLICY_ATTRIBUTES_NULL,
>
> +      VARIABLE_POLICY_TYPE_LOCK_ON_VAR_= STATE
>
> +    },
>
> +    {
>
> +      TEST_GUID_2,
>
> +      1,     &= nbsp;      // Value
>
> +      0     &n= bsp;       // Padding
>
> +    },
>
> +    L"",
>
> +    L""
>
> +  };
>
> +  UT_ASSERT_TRUE( InitExpVarPolicyStrings( &ValidationP= olicy,
> TEST_VAR_1_NAME, TEST_VAR_2_NAME ) );
>
> +
>
> +  // Check for an offset outside the size bounds.
>
> +  ValidationPolicy.Header.OffsetToName =3D ValidationPolicy= .Header.Size + 1;
>
> +  UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationP= olicy.Header ),
> EFI_INVALID_PARAMETER );
>
> +
>
> +  // Check for an offset inside the policy header.
>
> +  ValidationPolicy.Header.OffsetToName =3D sizeof(VARIABLE_= POLICY_ENTRY)
> - 2;
>
> +  UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationP= olicy.Header ),
> EFI_INVALID_PARAMETER );
>
> +
>
> +  // Check for an offset inside the state policy header. >
> +  ValidationPolicy.Header.OffsetToName =3D sizeof(VARIABLE_= POLICY_ENTRY)
> + 2;
>
> +  UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationP= olicy.Header ),
> EFI_INVALID_PARAMETER );
>
> +
>
> +  // Check for a ridiculous offset.
>
> +  ValidationPolicy.Header.OffsetToName =3D MAX_UINT16;
>
> +  UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationP= olicy.Header ),
> EFI_INVALID_PARAMETER );
>
> +
>
> +  return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +RegisterShouldRejectMissingStateStrings (
>
> +  IN UNIT_TEST_CONTEXT      Contex= t
>
> +  )
>
> +{
>
> +  EXPANDED_VARIABLE_POLICY_ENTRY   ValidationPoli= cy =3D {
>
> +    {
>
> +      VARIABLE_POLICY_ENTRY_REVISION, >
> +      0,    // Will be p= opulated by init helper.
>
> +      0,    // Will be p= opulated by init helper.
>
> +      TEST_GUID_1,
>
> +      TEST_POLICY_MIN_SIZE_NULL,
>
> +      TEST_POLICY_MAX_SIZE_NULL,
>
> +      TEST_POLICY_ATTRIBUTES_NULL,
>
> +      TEST_POLICY_ATTRIBUTES_NULL,
>
> +      VARIABLE_POLICY_TYPE_LOCK_ON_VAR_= STATE
>
> +    },
>
> +    {
>
> +      TEST_GUID_2,
>
> +      1,     &= nbsp;      // Value
>
> +      0     &n= bsp;       // Padding
>
> +    },
>
> +    L"",
>
> +    L""
>
> +  };
>
> +  UT_ASSERT_TRUE( InitExpVarPolicyStrings( &ValidationP= olicy,
> TEST_VAR_1_NAME, TEST_VAR_2_NAME ) );
>
> +
>
> +  // Remove the state string and copy the Name into it's pl= ace.
>
> +  // Also adjust the offset.
>
> +  ValidationPolicy.Header.Size     = ;     =3D sizeof(VARIABLE_POLICY_ENTRY) +
> sizeof(VARIABLE_LOCK_ON_VAR_STATE_POLICY) +
> sizeof(TEST_VAR_1_NAME);
>
> +  ValidationPolicy.Header.OffsetToName  =3D sizeof(VAR= IABLE_POLICY_ENTRY)
> + sizeof(VARIABLE_LOCK_ON_VAR_STATE_POLICY);
>
> +  CopyMem( (UINT8*)&ValidationPolicy +
> ValidationPolicy.Header.OffsetToName, TEST_VAR_1_NAME,
> sizeof(TEST_VAR_1_NAME) );
>
> +
>
> +  // Make sure that this structure fails.
>
> +  UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationP= olicy.Header ),
> EFI_INVALID_PARAMETER );
>
> +
>
> +  return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +RegisterShouldRejectStringsMissingNull (
>
> +  IN UNIT_TEST_CONTEXT      Contex= t
>
> +  )
>
> +{
>
> +  EXPANDED_VARIABLE_POLICY_ENTRY   ValidationPoli= cy =3D {
>
> +    {
>
> +      VARIABLE_POLICY_ENTRY_REVISION, >
> +      0,    // Will be p= opulated by init helper.
>
> +      0,    // Will be p= opulated by init helper.
>
> +      TEST_GUID_1,
>
> +      TEST_POLICY_MIN_SIZE_NULL,
>
> +      TEST_POLICY_MAX_SIZE_NULL,
>
> +      TEST_POLICY_ATTRIBUTES_NULL,
>
> +      TEST_POLICY_ATTRIBUTES_NULL,
>
> +      VARIABLE_POLICY_TYPE_LOCK_ON_VAR_= STATE
>
> +    },
>
> +    {
>
> +      TEST_GUID_2,
>
> +      1,     &= nbsp;      // Value
>
> +      0     &n= bsp;       // Padding
>
> +    },
>
> +    L"",
>
> +    L""
>
> +  };
>
> +  UT_ASSERT_TRUE( InitExpVarPolicyStrings( &ValidationP= olicy,
> TEST_VAR_1_NAME, TEST_VAR_2_NAME ) );
>
> +
>
> +  // Removing the NULL from the Name should fail.
>
> +  ValidationPolicy.Header.Size =3D ValidationPolicy.Header.= Size -
> sizeof(CHAR16);
>
> +  UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationP= olicy.Header ),
> EFI_INVALID_PARAMETER );
>
> +
>
> +  // Removing the NULL from the State Name is a little tric= kier.
>
> +  // Copy the Name up one byte.
>
> +  ValidationPolicy.Header.OffsetToName =3D
> ValidationPolicy.Header.OffsetToName - sizeof(CHAR16);
>
> +  CopyMem( (UINT8*)&ValidationPolicy +
> ValidationPolicy.Header.OffsetToName, TEST_VAR_1_NAME,
> sizeof(TEST_VAR_1_NAME) );
>
> +  UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationP= olicy.Header ),
> EFI_INVALID_PARAMETER );
>
> +
>
> +  return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +RegisterShouldRejectMalformedStrings (
>
> +  IN UNIT_TEST_CONTEXT      Contex= t
>
> +  )
>
> +{
>
> +  EXPANDED_VARIABLE_POLICY_ENTRY   ValidationPoli= cy =3D {
>
> +    {
>
> +      VARIABLE_POLICY_ENTRY_REVISION, >
> +      0,    // Will be p= opulated by init helper.
>
> +      0,    // Will be p= opulated by init helper.
>
> +      TEST_GUID_1,
>
> +      TEST_POLICY_MIN_SIZE_NULL,
>
> +      TEST_POLICY_MAX_SIZE_NULL,
>
> +      TEST_POLICY_ATTRIBUTES_NULL,
>
> +      TEST_POLICY_ATTRIBUTES_NULL,
>
> +      VARIABLE_POLICY_TYPE_LOCK_ON_VAR_= STATE
>
> +    },
>
> +    {
>
> +      TEST_GUID_2,
>
> +      1,     &= nbsp;      // Value
>
> +      0     &n= bsp;       // Padding
>
> +    },
>
> +    L"",
>
> +    L""
>
> +  };
>
> +  UT_ASSERT_TRUE( InitExpVarPolicyStrings( &ValidationP= olicy,
> TEST_VAR_1_NAME, TEST_VAR_2_NAME ) );
>
> +
>
> +  // Bisecting the NULL from the Name should fail.
>
> +  ValidationPolicy.Header.Size =3D ValidationPolicy.Header.= Size - 1;
>
> +  UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationP= olicy.Header ),
> EFI_INVALID_PARAMETER );
>
> +
>
> +  // Bisecting the NULL from the State Name is a little tri= ckier.
>
> +  // Copy the Name up one byte.
>
> +  ValidationPolicy.Header.OffsetToName =3D
> ValidationPolicy.Header.OffsetToName - 1;
>
> +  CopyMem( (UINT8*)&ValidationPolicy +
> ValidationPolicy.Header.OffsetToName, TEST_VAR_1_NAME,
> sizeof(TEST_VAR_1_NAME) );
>
> +  UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationP= olicy.Header ),
> EFI_INVALID_PARAMETER );
>
> +
>
> +  return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +RegisterShouldRejectUnpackedPolicies (
>
> +  IN UNIT_TEST_CONTEXT      Contex= t
>
> +  )
>
> +{
>
> +  EXPANDED_VARIABLE_POLICY_ENTRY   ValidationPoli= cy =3D {
>
> +    {
>
> +      VARIABLE_POLICY_ENTRY_REVISION, >
> +      0,    // Will be p= opulated by init helper.
>
> +      0,    // Will be p= opulated by init helper.
>
> +      TEST_GUID_1,
>
> +      TEST_POLICY_MIN_SIZE_NULL,
>
> +      TEST_POLICY_MAX_SIZE_NULL,
>
> +      TEST_POLICY_ATTRIBUTES_NULL,
>
> +      TEST_POLICY_ATTRIBUTES_NULL,
>
> +      VARIABLE_POLICY_TYPE_LOCK_ON_VAR_= STATE
>
> +    },
>
> +    {
>
> +      TEST_GUID_2,
>
> +      1,     &= nbsp;      // Value
>
> +      0     &n= bsp;       // Padding
>
> +    },
>
> +    L"",
>
> +    L""
>
> +  };
>
> +  UT_ASSERT_TRUE( InitExpVarPolicyStrings( &ValidationP= olicy,
> TEST_VAR_1_NAME, TEST_VAR_2_NAME ) );
>
> +
>
> +  // Increase the size and move the Name out a bit.
>
> +  ValidationPolicy.Header.Size =3D ValidationPolicy.Header.= Size +
> sizeof(CHAR16);
>
> +  ValidationPolicy.Header.OffsetToName =3D
> ValidationPolicy.Header.OffsetToName + sizeof(CHAR16);
>
> +  CopyMem( (UINT8*)&ValidationPolicy +
> ValidationPolicy.Header.OffsetToName, TEST_VAR_1_NAME,
> sizeof(TEST_VAR_1_NAME) );
>
> +  UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationP= olicy.Header ),
> EFI_INVALID_PARAMETER );
>
> +
>
> +  // Reintialize without the state policy and try the same = test.
>
> +  ValidationPolicy.Header.LockPolicyType =3D
> VARIABLE_POLICY_TYPE_NO_LOCK;
>
> +  UT_ASSERT_TRUE( InitExpVarPolicyStrings( &ValidationP= olicy,
> TEST_VAR_1_NAME, NULL ) );
>
> +  ValidationPolicy.Header.Size =3D ValidationPolicy.Header.= Size +
> sizeof(CHAR16);
>
> +  ValidationPolicy.Header.OffsetToName =3D
> ValidationPolicy.Header.OffsetToName + sizeof(CHAR16);
>
> +  CopyMem( (UINT8*)&ValidationPolicy +
> ValidationPolicy.Header.OffsetToName, TEST_VAR_1_NAME,
> sizeof(TEST_VAR_1_NAME) );
>
> +  UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationP= olicy.Header ),
> EFI_INVALID_PARAMETER );
>
> +
>
> +  return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +RegisterShouldRejectInvalidNameCharacters (
>
> +  IN UNIT_TEST_CONTEXT      Contex= t
>
> +  )
>
> +{
>
> +  // EXPANDED_VARIABLE_POLICY_ENTRY   ValidationP= olicy =3D {
>
> +  //   {
>
> +  //     VARIABLE_POLICY_ENTRY_REVISION= ,
>
> +  //     0,    // Will b= e populated by init helper.
>
> +  //     0,    // Will b= e populated by init helper.
>
> +  //     TEST_GUID_1,
>
> +  //     TEST_POLICY_MIN_SIZE_NULL,
>
> +  //     TEST_POLICY_MAX_SIZE_NULL,
>
> +  //     TEST_POLICY_ATTRIBUTES_NULL, >
> +  //     TEST_POLICY_ATTRIBUTES_NULL, >
> +  //     VARIABLE_POLICY_TYPE_LOCK_ON_V= AR_STATE
>
> +  //   },
>
> +  //   {
>
> +  //     TEST_GUID_2,
>
> +  //     1,    &nbs= p;       // Value
>
> +  //     0     = ;        // Padding
>
> +  //   },
>
> +  //   L"",
>
> +  //   L""
>
> +  // };
>
> +
>
> +  // Currently, there are no known invalid characters.
>
> +  // '#' in LockPolicy->Name are taken as literal.
>
> +
>
> +  return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +RegisterShouldRejectBadPolicyConstraints (
>
> +  IN UNIT_TEST_CONTEXT      Contex= t
>
> +  )
>
> +{
>
> +  SIMPLE_VARIABLE_POLICY_ENTRY   ValidationPolicy= =3D {
>
> +    {
>
> +      VARIABLE_POLICY_ENTRY_REVISION, >
> +      sizeof(VARIABLE_POLICY_ENTRY) = 3; sizeof(TEST_VAR_1_NAME),
>
> +      sizeof(VARIABLE_POLICY_ENTRY), >
> +      TEST_GUID_1,
>
> +      TEST_POLICY_MIN_SIZE_NULL,
>
> +      TEST_POLICY_MAX_SIZE_NULL,
>
> +      TEST_POLICY_ATTRIBUTES_NULL,
>
> +      TEST_POLICY_ATTRIBUTES_NULL,
>
> +      VARIABLE_POLICY_TYPE_NO_LOCK
>
> +    },
>
> +    TEST_VAR_1_NAME
>
> +  };
>
> +
>
> +  // Make sure that invalid MAXes are rejected.
>
> +  ValidationPolicy.Header.MaxSize =3D 0;
>
> +  UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationP= olicy.Header ),
> EFI_INVALID_PARAMETER );
>
> +
>
> +  return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +RegisterShouldRejectUnknownLockPolicies (
>
> +  IN UNIT_TEST_CONTEXT      Contex= t
>
> +  )
>
> +{
>
> +  SIMPLE_VARIABLE_POLICY_ENTRY   ValidationPolicy= =3D {
>
> +    {
>
> +      VARIABLE_POLICY_ENTRY_REVISION, >
> +      sizeof(VARIABLE_POLICY_ENTRY) = 3; sizeof(TEST_VAR_1_NAME),
>
> +      sizeof(VARIABLE_POLICY_ENTRY), >
> +      TEST_GUID_1,
>
> +      TEST_POLICY_MIN_SIZE_NULL,
>
> +      TEST_POLICY_MAX_SIZE_NULL,
>
> +      TEST_POLICY_ATTRIBUTES_NULL,
>
> +      TEST_POLICY_ATTRIBUTES_NULL,
>
> +      VARIABLE_POLICY_TYPE_NO_LOCK
>
> +    },
>
> +    TEST_VAR_1_NAME
>
> +  };
>
> +
>
> +  ValidationPolicy.Header.LockPolicyType =3D
> VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE + 1;
>
> +  UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationP= olicy.Header ),
> EFI_INVALID_PARAMETER );
>
> +  ValidationPolicy.Header.LockPolicyType =3D
> VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE + 1;
>
> +  UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationP= olicy.Header ),
> EFI_INVALID_PARAMETER );
>
> +
>
> +  return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +RegisterShouldRejectPolicesWithTooManyWildcards (
>
> +  IN UNIT_TEST_CONTEXT      Contex= t
>
> +  )
>
> +{
>
> +  SIMPLE_VARIABLE_POLICY_ENTRY   ValidationPolicy= =3D {
>
> +    {
>
> +      VARIABLE_POLICY_ENTRY_REVISION, >
> +      sizeof(VARIABLE_POLICY_ENTRY) = 3; sizeof(TEST_300_HASHES_STRING),
>
> +      sizeof(VARIABLE_POLICY_ENTRY), >
> +      TEST_GUID_1,
>
> +      TEST_POLICY_MIN_SIZE_NULL,
>
> +      TEST_POLICY_MAX_SIZE_NULL,
>
> +      TEST_POLICY_ATTRIBUTES_NULL,
>
> +      TEST_POLICY_ATTRIBUTES_NULL,
>
> +      VARIABLE_POLICY_TYPE_NO_LOCK
>
> +    },
>
> +    TEST_300_HASHES_STRING
>
> +  };
>
> +
>
> +  // 300 Hashes is currently larger than the possible maxim= um match priority.
>
> +  UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationP= olicy.Header ),
> EFI_INVALID_PARAMETER );
>
> +
>
> +  return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +RegisterShouldRejectDuplicatePolicies (
>
> +  IN UNIT_TEST_CONTEXT      Contex= t
>
> +  )
>
> +{
>
> +  SIMPLE_VARIABLE_POLICY_ENTRY   ValidationPolicy= =3D {
>
> +    {
>
> +      VARIABLE_POLICY_ENTRY_REVISION, >
> +      sizeof(VARIABLE_POLICY_ENTRY) = 3; sizeof(TEST_VAR_1_NAME),
>
> +      sizeof(VARIABLE_POLICY_ENTRY), >
> +      TEST_GUID_1,
>
> +      TEST_POLICY_MIN_SIZE_NULL,
>
> +      TEST_POLICY_MAX_SIZE_NULL,
>
> +      TEST_POLICY_ATTRIBUTES_NULL,
>
> +      TEST_POLICY_ATTRIBUTES_NULL,
>
> +      VARIABLE_POLICY_TYPE_NO_LOCK
>
> +    },
>
> +    TEST_VAR_1_NAME
>
> +  };
>
> +
>
> +
> UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolic= y.Hea
> der ) );
>
> +
> UT_ASSERT_STATUS_EQUAL( RegisterVariablePolicy( &ValidationPolicy= .Head
> er ), EFI_ALREADY_STARTED );
>
> +
>
> +  return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +MinAndMaxSizePoliciesShouldBeHonored (
>
> +  IN UNIT_TEST_CONTEXT      Contex= t
>
> +  )
>
> +{
>
> +  SIMPLE_VARIABLE_POLICY_ENTRY   ValidationPolicy= =3D {
>
> +    {
>
> +      VARIABLE_POLICY_ENTRY_REVISION, >
> +      sizeof(VARIABLE_POLICY_ENTRY) = 3; sizeof(TEST_VAR_1_NAME),
>
> +      sizeof(VARIABLE_POLICY_ENTRY), >
> +      TEST_GUID_1,
>
> +      TEST_POLICY_MIN_SIZE_10,
>
> +      TEST_POLICY_MAX_SIZE_200,
>
> +      TEST_POLICY_ATTRIBUTES_NULL,
>
> +      TEST_POLICY_ATTRIBUTES_NULL,
>
> +      VARIABLE_POLICY_TYPE_NO_LOCK
>
> +    },
>
> +    TEST_VAR_1_NAME
>
> +  };
>
> +  EFI_STATUS  PolicyCheck;
>
> +  UINT8       DummyData[TEST_= POLICY_MAX_SIZE_200+1];
>
> +
>
> +
>
> +  // Without a policy, there should be no constraints on va= riable creation.
>
> +  PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,
>
> +          &nbs= p;            &= nbsp;            &am= p;mTestGuid1,
>
> +          &nbs= p;            &= nbsp;            VAR= IABLE_ATTRIBUTE_NV_BS,
>
> +          &nbs= p;            &= nbsp;            TES= T_POLICY_MAX_SIZE_200+1,
>
> +          &nbs= p;            &= nbsp;            Dum= myData );
>
> +  UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );
>
> +
>
> +  // Set a policy to test against.
>
> +
> UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolic= y.Hea
> der ) );
>
> +
>
> +  // With a policy, make sure that sizes outsize the target= range fail.
>
> +  PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,
>
> +          &nbs= p;            &= nbsp;            &am= p;mTestGuid1,
>
> +          &nbs= p;            &= nbsp;            VAR= IABLE_ATTRIBUTE_NV_BS,
>
> +          &nbs= p;            &= nbsp;            TES= T_POLICY_MAX_SIZE_200+1,
>
> +          &nbs= p;            &= nbsp;            Dum= myData );
>
> +  UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) );
>
> +
>
> +  // With a policy, make sure that sizes outsize the target= range fail.
>
> +  PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,
>
> +          &nbs= p;            &= nbsp;            &am= p;mTestGuid1,
>
> +          &nbs= p;            &= nbsp;            VAR= IABLE_ATTRIBUTE_NV_BS,
>
> +          &nbs= p;            &= nbsp;            TES= T_POLICY_MIN_SIZE_10-1,
>
> +          &nbs= p;            &= nbsp;            Dum= myData );
>
> +  UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) );
>
> +
>
> +  // With a policy, make sure a valid variable is still val= id.
>
> +  PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,
>
> +          &nbs= p;            &= nbsp;            &am= p;mTestGuid1,
>
> +          &nbs= p;            &= nbsp;            VAR= IABLE_ATTRIBUTE_NV_BS,
>
> +          &nbs= p;            &= nbsp;            TES= T_POLICY_MIN_SIZE_10+1,
>
> +          &nbs= p;            &= nbsp;            Dum= myData );
>
> +  UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );
>
> +
>
> +  return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +AttributeMustPoliciesShouldBeHonored (
>
> +  IN UNIT_TEST_CONTEXT      Contex= t
>
> +  )
>
> +{
>
> +  SIMPLE_VARIABLE_POLICY_ENTRY   ValidationPolicy= =3D {
>
> +    {
>
> +      VARIABLE_POLICY_ENTRY_REVISION, >
> +      sizeof(VARIABLE_POLICY_ENTRY) = 3; sizeof(TEST_VAR_1_NAME),
>
> +      sizeof(VARIABLE_POLICY_ENTRY), >
> +      TEST_GUID_1,
>
> +      TEST_POLICY_MIN_SIZE_NULL,
>
> +      TEST_POLICY_MAX_SIZE_NULL,
>
> +      VARIABLE_ATTRIBUTE_NV_BS_RT,
>
> +      TEST_POLICY_ATTRIBUTES_NULL,
>
> +      VARIABLE_POLICY_TYPE_NO_LOCK
>
> +    },
>
> +    TEST_VAR_1_NAME
>
> +  };
>
> +  EFI_STATUS  PolicyCheck;
>
> +  UINT8       DummyData[12];<= br> >
> +
>
> +
>
> +  // Without a policy, there should be no constraints on va= riable creation.
>
> +  PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,
>
> +          &nbs= p;            &= nbsp;            &am= p;mTestGuid1,
>
> +          &nbs= p;            &= nbsp;            TES= T_POLICY_ATTRIBUTES_NULL,
>
> +          &nbs= p;            &= nbsp;            siz= eof(DummyData),
>
> +          &nbs= p;            &= nbsp;            Dum= myData );
>
> +  UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );
>
> +
>
> +  // Set a policy to test against.
>
> +
> UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolic= y.Hea
> der ) );
>
> +
>
> +  // With a policy, make sure that no attributes fail.
>
> +  PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,
>
> +          &nbs= p;            &= nbsp;            &am= p;mTestGuid1,
>
> +          &nbs= p;            &= nbsp;            TES= T_POLICY_ATTRIBUTES_NULL,
>
> +          &nbs= p;            &= nbsp;            siz= eof(DummyData),
>
> +          &nbs= p;            &= nbsp;            Dum= myData );
>
> +  UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) );
>
> +
>
> +  // With a policy, make sure that some -- but not all -- a= ttributes fail.
>
> +  PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,
>
> +          &nbs= p;            &= nbsp;            &am= p;mTestGuid1,
>
> +          &nbs= p;            &= nbsp;            VAR= IABLE_ATTRIBUTE_BS_RT_AT,
>
> +          &nbs= p;            &= nbsp;            siz= eof(DummyData),
>
> +          &nbs= p;            &= nbsp;            Dum= myData );
>
> +  UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) );
>
> +
>
> +  // With a policy, make sure that all attributes pass.
>
> +  PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,
>
> +          &nbs= p;            &= nbsp;            &am= p;mTestGuid1,
>
> +          &nbs= p;            &= nbsp;            VAR= IABLE_ATTRIBUTE_NV_BS_RT,
>
> +          &nbs= p;            &= nbsp;            siz= eof(DummyData),
>
> +          &nbs= p;            &= nbsp;            Dum= myData );
>
> +  UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );
>
> +
>
> +  // With a policy, make sure that all attributes -- plus s= ome -- pass.
>
> +  PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,
>
> +          &nbs= p;            &= nbsp;            &am= p;mTestGuid1,
>
> +          &nbs= p;            &= nbsp;            VAR= IABLE_ATTRIBUTE_NV_BS_RT_AT,
>
> +          &nbs= p;            &= nbsp;            siz= eof(DummyData),
>
> +          &nbs= p;            &= nbsp;            Dum= myData );
>
> +  UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );
>
> +
>
> +  return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +AttributeCantPoliciesShouldBeHonored (
>
> +  IN UNIT_TEST_CONTEXT      Contex= t
>
> +  )
>
> +{
>
> +  SIMPLE_VARIABLE_POLICY_ENTRY   ValidationPolicy= =3D {
>
> +    {
>
> +      VARIABLE_POLICY_ENTRY_REVISION, >
> +      sizeof(VARIABLE_POLICY_ENTRY) = 3; sizeof(TEST_VAR_1_NAME),
>
> +      sizeof(VARIABLE_POLICY_ENTRY), >
> +      TEST_GUID_1,
>
> +      TEST_POLICY_MIN_SIZE_NULL,
>
> +      TEST_POLICY_MAX_SIZE_NULL,
>
> +      TEST_POLICY_ATTRIBUTES_NULL,
>
> +      EFI_VARIABLE_TIME_BASED_AUTHENTIC= ATED_WRITE_ACCESS,
>
> +      VARIABLE_POLICY_TYPE_NO_LOCK
>
> +    },
>
> +    TEST_VAR_1_NAME
>
> +  };
>
> +  EFI_STATUS  PolicyCheck;
>
> +  UINT8       DummyData[12];<= br> >
> +
>
> +
>
> +  // Without a policy, there should be no constraints on va= riable creation.
>
> +  PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,
>
> +          &nbs= p;            &= nbsp;            &am= p;mTestGuid1,
>
> +          &nbs= p;            &= nbsp;            VAR= IABLE_ATTRIBUTE_BS_RT_AT,
>
> +          &nbs= p;            &= nbsp;            siz= eof(DummyData),
>
> +          &nbs= p;            &= nbsp;            Dum= myData );
>
> +  UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );
>
> +
>
> +  // Set a policy to test against.
>
> +
> UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolic= y.Hea
> der ) );
>
> +
>
> +  // With a policy, make sure that forbidden attributes fai= l.
>
> +  PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,
>
> +          &nbs= p;            &= nbsp;            &am= p;mTestGuid1,
>
> +
> EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS,
>
> +          &nbs= p;            &= nbsp;            siz= eof(DummyData),
>
> +          &nbs= p;            &= nbsp;            Dum= myData );
>
> +  UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) );
>
> +
>
> +  // With a policy, make sure that a mixture of attributes = -- including the
> forbidden -- fail.
>
> +  PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,
>
> +          &nbs= p;            &= nbsp;            &am= p;mTestGuid1,
>
> +          &nbs= p;            &= nbsp;            VAR= IABLE_ATTRIBUTE_BS_RT_AT,
>
> +          &nbs= p;            &= nbsp;            siz= eof(DummyData),
>
> +          &nbs= p;            &= nbsp;            Dum= myData );
>
> +  UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) );
>
> +
>
> +  // With a policy, make sure that attributes without the f= orbidden pass.
>
> +  PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,
>
> +          &nbs= p;            &= nbsp;            &am= p;mTestGuid1,
>
> +          &nbs= p;            &= nbsp;            VAR= IABLE_ATTRIBUTE_NV_BS_RT,
>
> +          &nbs= p;            &= nbsp;            siz= eof(DummyData),
>
> +          &nbs= p;            &= nbsp;            Dum= myData );
>
> +  UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );
>
> +
>
> +  return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +VariablesShouldBeDeletableRegardlessOfSize (
>
> +  IN UNIT_TEST_CONTEXT      Contex= t
>
> +  )
>
> +{
>
> +  SIMPLE_VARIABLE_POLICY_ENTRY   ValidationPolicy= =3D {
>
> +    {
>
> +      VARIABLE_POLICY_ENTRY_REVISION, >
> +      sizeof(VARIABLE_POLICY_ENTRY) = 3; sizeof(TEST_VAR_1_NAME),
>
> +      sizeof(VARIABLE_POLICY_ENTRY), >
> +      TEST_GUID_1,
>
> +      TEST_POLICY_MIN_SIZE_10,
>
> +      TEST_POLICY_MAX_SIZE_NULL,
>
> +      TEST_POLICY_ATTRIBUTES_NULL,
>
> +      EFI_VARIABLE_TIME_BASED_AUTHENTIC= ATED_WRITE_ACCESS,
>
> +      VARIABLE_POLICY_TYPE_NO_LOCK
>
> +    },
>
> +    TEST_VAR_1_NAME
>
> +  };
>
> +  EFI_STATUS  PolicyCheck;
>
> +  UINT8       DummyData[TEST_= POLICY_MAX_SIZE_200+1];
>
> +
>
> +  // Create a policy enforcing a minimum variable size.
>
> +
> UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolic= y.Hea
> der ) );
>
> +
>
> +  // Make sure that a normal set would fail.
>
> +  PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,
>
> +          &nbs= p;            &= nbsp;            &am= p;mTestGuid1,
>
> +          &nbs= p;            &= nbsp;            VAR= IABLE_ATTRIBUTE_NV_BS,
>
> +          &nbs= p;            &= nbsp;            TES= T_POLICY_MIN_SIZE_10-1,
>
> +          &nbs= p;            &= nbsp;            Dum= myData );
>
> +  UT_ASSERT_STATUS_EQUAL( PolicyCheck, EFI_INVALID_PARAMETE= R );
>
> +
>
> +  // Now make sure that a delete would succeed.
>
> +  PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,
>
> +          &nbs= p;            &= nbsp;            &am= p;mTestGuid1,
>
> +          &nbs= p;            &= nbsp;            VAR= IABLE_ATTRIBUTE_NV_BS,
>
> +          &nbs= p;            &= nbsp;            0,<= br> >
> +          &nbs= p;            &= nbsp;            NUL= L );
>
> +  UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );
>
> +
>
> +  return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +LockNowPoliciesShouldBeHonored (
>
> +  IN UNIT_TEST_CONTEXT      Contex= t
>
> +  )
>
> +{
>
> +  SIMPLE_VARIABLE_POLICY_ENTRY   ValidationPolicy= =3D {
>
> +    {
>
> +      VARIABLE_POLICY_ENTRY_REVISION, >
> +      sizeof(VARIABLE_POLICY_ENTRY) = 3; sizeof(TEST_VAR_1_NAME),
>
> +      sizeof(VARIABLE_POLICY_ENTRY), >
> +      TEST_GUID_1,
>
> +      TEST_POLICY_MIN_SIZE_NULL,
>
> +      TEST_POLICY_MAX_SIZE_NULL,
>
> +      TEST_POLICY_ATTRIBUTES_NULL,
>
> +      TEST_POLICY_ATTRIBUTES_NULL,
>
> +      VARIABLE_POLICY_TYPE_LOCK_NOW
>
> +    },
>
> +    TEST_VAR_1_NAME
>
> +  };
>
> +  EFI_STATUS  PolicyCheck;
>
> +  UINT8       DummyData[12];<= br> >
> +
>
> +
>
> +  // Without a policy, there should be no constraints on va= riable creation.
>
> +  PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,
>
> +          &nbs= p;            &= nbsp;            &am= p;mTestGuid1,
>
> +          &nbs= p;            &= nbsp;            VAR= IABLE_ATTRIBUTE_BS_RT_AT,
>
> +          &nbs= p;            &= nbsp;            siz= eof(DummyData),
>
> +          &nbs= p;            &= nbsp;            Dum= myData );
>
> +  UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );
>
> +
>
> +  // Set a policy to test against.
>
> +
> UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolic= y.Hea
> der ) );
>
> +
>
> +  // With a policy, make sure that writes immediately fail.=
>
> +  PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,
>
> +          &nbs= p;            &= nbsp;            &am= p;mTestGuid1,
>
> +          &nbs= p;            &= nbsp;            VAR= IABLE_ATTRIBUTE_BS_RT_AT,
>
> +          &nbs= p;            &= nbsp;            siz= eof(DummyData),
>
> +          &nbs= p;            &= nbsp;            Dum= myData );
>
> +  UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) );
>
> +
>
> +  return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +LockOnCreatePoliciesShouldBeHonored (
>
> +  IN UNIT_TEST_CONTEXT      Contex= t
>
> +  )
>
> +{
>
> +  SIMPLE_VARIABLE_POLICY_ENTRY   ValidationPolicy= =3D {
>
> +    {
>
> +      VARIABLE_POLICY_ENTRY_REVISION, >
> +      sizeof(VARIABLE_POLICY_ENTRY) = 3; sizeof(TEST_VAR_1_NAME),
>
> +      sizeof(VARIABLE_POLICY_ENTRY), >
> +      TEST_GUID_1,
>
> +      TEST_POLICY_MIN_SIZE_NULL,
>
> +      TEST_POLICY_MAX_SIZE_NULL,
>
> +      TEST_POLICY_ATTRIBUTES_NULL,
>
> +      TEST_POLICY_ATTRIBUTES_NULL,
>
> +      VARIABLE_POLICY_TYPE_LOCK_ON_CREA= TE
>
> +    },
>
> +    TEST_VAR_1_NAME
>
> +  };
>
> +  EFI_STATUS  PolicyCheck;
>
> +  UINT8       DummyData[12];<= br> >
> +  UINTN       ExpectedDataSiz= e;
>
> +
>
> +
>
> +  // Without a policy, there should be no constraints on va= riable creation.
>
> +  PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,
>
> +          &nbs= p;            &= nbsp;            &am= p;mTestGuid1,
>
> +          &nbs= p;            &= nbsp;            VAR= IABLE_ATTRIBUTE_BS_RT_AT,
>
> +          &nbs= p;            &= nbsp;            siz= eof(DummyData),
>
> +          &nbs= p;            &= nbsp;            Dum= myData );
>
> +  UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );
>
> +
>
> +  // Set a policy to test against.
>
> +
> UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolic= y.Hea
> der ) );
>
> +
>
> +  // Set consistent expectations on what the calls are look= ing for.
>
> +  expect_memory_count( StubGetVariableNull, VariableName, > TEST_VAR_1_NAME, sizeof(TEST_VAR_1_NAME), 2 );
>
> +  expect_memory_count( StubGetVariableNull, VendorGuid, &am= p;mTestGuid1,
> sizeof(mTestGuid1), 2 );
>
> +  ExpectedDataSize =3D 0;
>
> +  expect_memory_count( StubGetVariableNull, DataSize,
> &ExpectedDataSize, sizeof(ExpectedDataSize), 2 );
>
> +
>
> +  // With a policy, make sure that writes still work, since= the variable doesn't
> exist.
>
> +  will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_= NULL );    //
> Attributes
>
> +  will_return( StubGetVariableNull, 0 );   &= nbsp;           &nbs= p;            &= nbsp; // Size
>
> +  will_return( StubGetVariableNull, NULL );  &nbs= p;            &= nbsp;           // DataPt= r
>
> +  will_return( StubGetVariableNull, EFI_NOT_FOUND ); &= nbsp;           &nbs= p;    // Status
>
> +  PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,
>
> +          &nbs= p;            &= nbsp;            &am= p;mTestGuid1,
>
> +          &nbs= p;            &= nbsp;            VAR= IABLE_ATTRIBUTE_BS_RT_AT,
>
> +          &nbs= p;            &= nbsp;            siz= eof(DummyData),
>
> +          &nbs= p;            &= nbsp;            Dum= myData );
>
> +  UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );
>
> +
>
> +  // With a policy, make sure that a call with an "exi= sting" variable fails.
>
> +  will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_= NULL );    //
> Attributes
>
> +  will_return( StubGetVariableNull, 10 );   =             &nb= sp;            = // Size
>
> +  will_return( StubGetVariableNull, NULL );  &nbs= p;            &= nbsp;           // DataPt= r
>
> +  will_return( StubGetVariableNull, EFI_BUFFER_TOO_SMALL );=            //
> Status
>
> +  PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,
>
> +          &nbs= p;            &= nbsp;            &am= p;mTestGuid1,
>
> +          &nbs= p;            &= nbsp;            VAR= IABLE_ATTRIBUTE_BS_RT_AT,
>
> +          &nbs= p;            &= nbsp;            siz= eof(DummyData),
>
> +          &nbs= p;            &= nbsp;            Dum= myData );
>
> +  UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) );
>
> +
>
> +  return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +LockOnStatePoliciesShouldBeHonored (
>
> +  IN UNIT_TEST_CONTEXT      Contex= t
>
> +  )
>
> +{
>
> +  EXPANDED_VARIABLE_POLICY_ENTRY   ValidationPoli= cy =3D {
>
> +    {
>
> +      VARIABLE_POLICY_ENTRY_REVISION, >
> +      0,    // Will be p= opulated by init helper.
>
> +      0,    // Will be p= opulated by init helper.
>
> +      TEST_GUID_1,
>
> +      TEST_POLICY_MIN_SIZE_NULL,
>
> +      TEST_POLICY_MAX_SIZE_NULL,
>
> +      TEST_POLICY_ATTRIBUTES_NULL,
>
> +      TEST_POLICY_ATTRIBUTES_NULL,
>
> +      VARIABLE_POLICY_TYPE_LOCK_ON_VAR_= STATE
>
> +    },
>
> +    {
>
> +      TEST_GUID_2,
>
> +      20,     =       // Value
>
> +      0     &n= bsp;       // Padding
>
> +    },
>
> +    L"",
>
> +    L""
>
> +  };
>
> +  EFI_STATUS  PolicyCheck;
>
> +  UINT8       DummyData[12];<= br> >
> +  UINT8       ValidationState= Var;
>
> +  UINTN       ExpectedDataSiz= e;
>
> +  UT_ASSERT_TRUE( InitExpVarPolicyStrings( &ValidationP= olicy,
> TEST_VAR_1_NAME, TEST_VAR_2_NAME ) );
>
> +
>
> +
>
> +  // Without a policy, there should be no constraints on va= riable creation.
>
> +  PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,
>
> +          &nbs= p;            &= nbsp;            &am= p;mTestGuid1,
>
> +          &nbs= p;            &= nbsp;            VAR= IABLE_ATTRIBUTE_BS_RT_AT,
>
> +          &nbs= p;            &= nbsp;            siz= eof(DummyData),
>
> +          &nbs= p;            &= nbsp;            Dum= myData );
>
> +  UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );
>
> +
>
> +  // Set a policy to test against.
>
> +
> UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolic= y.Hea
> der ) );
>
> +
>
> +  // Set consistent expectations on what the calls are look= ing for.
>
> +  expect_memory_count( StubGetVariableNull, VariableName, > TEST_VAR_2_NAME, sizeof(TEST_VAR_2_NAME), 5 );
>
> +  expect_memory_count( StubGetVariableNull, VendorGuid, &am= p;mTestGuid2,
> sizeof(mTestGuid2), 5 );
>
> +  ExpectedDataSize =3D 1;
>
> +  expect_memory_count( StubGetVariableNull, DataSize,
> &ExpectedDataSize, sizeof(ExpectedDataSize), 5 );
>
> +
>
> +  // With a policy, make sure that writes still work, since= the variable doesn't
> exist.
>
> +  will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_= NULL );    //
> Attributes
>
> +  will_return( StubGetVariableNull, 0 );   &= nbsp;           &nbs= p;            &= nbsp; // Size
>
> +  will_return( StubGetVariableNull, NULL );  &nbs= p;            &= nbsp;           // DataPt= r
>
> +  will_return( StubGetVariableNull, EFI_NOT_FOUND ); &= nbsp;           &nbs= p;    // Status
>
> +  PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,
>
> +          &nbs= p;            &= nbsp;            &am= p;mTestGuid1,
>
> +          &nbs= p;            &= nbsp;            VAR= IABLE_ATTRIBUTE_BS_RT_AT,
>
> +          &nbs= p;            &= nbsp;            siz= eof(DummyData),
>
> +          &nbs= p;            &= nbsp;            Dum= myData );
>
> +  UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );
>
> +
>
> +  // With a policy, make sure that a state variable that's = too large doesn't lock
> the variable.
>
> +  will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_= NULL );    //
> Attributes
>
> +  will_return( StubGetVariableNull, 10 );   =             &nb= sp;            = // Size
>
> +  will_return( StubGetVariableNull, NULL );  &nbs= p;            &= nbsp;           // DataPt= r
>
> +  will_return( StubGetVariableNull, EFI_BUFFER_TOO_SMALL );=            //
> Status
>
> +  PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,
>
> +          &nbs= p;            &= nbsp;            &am= p;mTestGuid1,
>
> +          &nbs= p;            &= nbsp;            VAR= IABLE_ATTRIBUTE_BS_RT_AT,
>
> +          &nbs= p;            &= nbsp;            siz= eof(DummyData),
>
> +          &nbs= p;            &= nbsp;            Dum= myData );
>
> +  UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );
>
> +
>
> +  // With a policy, check a state variable with the wrong v= alue.
>
> +  ValidationStateVar =3D 0;
>
> +  will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_= NULL );    //
> Attributes
>
> +  will_return( StubGetVariableNull, sizeof(ValidationStateV= ar) );     // Size
>
> +  will_return( StubGetVariableNull, &ValidationStateVar= );            // Da= taPtr
>
> +  will_return( StubGetVariableNull, EFI_SUCCESS ); &nb= sp;            =       // Status
>
> +  PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,
>
> +          &nbs= p;            &= nbsp;            &am= p;mTestGuid1,
>
> +          &nbs= p;            &= nbsp;            VAR= IABLE_ATTRIBUTE_BS_RT_AT,
>
> +          &nbs= p;            &= nbsp;            siz= eof(DummyData),
>
> +          &nbs= p;            &= nbsp;            Dum= myData );
>
> +  UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );
>
> +
>
> +  // With a policy, check a state variable with another wro= ng value.
>
> +  ValidationStateVar =3D 10;
>
> +  will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_= NULL );    //
> Attributes
>
> +  will_return( StubGetVariableNull, sizeof(ValidationStateV= ar) );     // Size
>
> +  will_return( StubGetVariableNull, &ValidationStateVar= );            // Da= taPtr
>
> +  will_return( StubGetVariableNull, EFI_SUCCESS ); &nb= sp;            =       // Status
>
> +  PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,
>
> +          &nbs= p;            &= nbsp;            &am= p;mTestGuid1,
>
> +          &nbs= p;            &= nbsp;            VAR= IABLE_ATTRIBUTE_BS_RT_AT,
>
> +          &nbs= p;            &= nbsp;            siz= eof(DummyData),
>
> +          &nbs= p;            &= nbsp;            Dum= myData );
>
> +  UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );
>
> +
>
> +  // With a policy, make sure that a call with a correct st= ate variable fails.
>
> +  ValidationStateVar =3D 20;
>
> +  will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_= NULL );    //
> Attributes
>
> +  will_return( StubGetVariableNull, sizeof(ValidationStateV= ar) );     // Size
>
> +  will_return( StubGetVariableNull, &ValidationStateVar= );            // Da= taPtr
>
> +  will_return( StubGetVariableNull, EFI_SUCCESS ); &nb= sp;            =       // Status
>
> +  PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,
>
> +          &nbs= p;            &= nbsp;            &am= p;mTestGuid1,
>
> +          &nbs= p;            &= nbsp;            VAR= IABLE_ATTRIBUTE_BS_RT_AT,
>
> +          &nbs= p;            &= nbsp;            siz= eof(DummyData),
>
> +          &nbs= p;            &= nbsp;            Dum= myData );
>
> +  UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) );
>
> +
>
> +  return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +LockOnStatePoliciesShouldApplyToNamespaces (
>
> +  IN UNIT_TEST_CONTEXT      Contex= t
>
> +  )
>
> +{
>
> +  EXPANDED_VARIABLE_POLICY_ENTRY   ValidationPoli= cy =3D {
>
> +    {
>
> +      VARIABLE_POLICY_ENTRY_REVISION, >
> +      0,    // Will be p= opulated by init helper.
>
> +      0,    // Will be p= opulated by init helper.
>
> +      TEST_GUID_1,
>
> +      TEST_POLICY_MIN_SIZE_NULL,
>
> +      TEST_POLICY_MAX_SIZE_NULL,
>
> +      TEST_POLICY_ATTRIBUTES_NULL,
>
> +      TEST_POLICY_ATTRIBUTES_NULL,
>
> +      VARIABLE_POLICY_TYPE_LOCK_ON_VAR_= STATE
>
> +    },
>
> +    {
>
> +      TEST_GUID_2,
>
> +      20,     =       // Value
>
> +      0     &n= bsp;       // Padding
>
> +    },
>
> +    L"",
>
> +    L""
>
> +  };
>
> +  EFI_STATUS  PolicyCheck;
>
> +  UINT8       DummyData[12];<= br> >
> +  UINT8       ValidationState= Var;
>
> +  UINTN       ExpectedDataSiz= e;
>
> +  UT_ASSERT_TRUE( InitExpVarPolicyStrings( &ValidationP= olicy, NULL,
> TEST_VAR_2_NAME ) );
>
> +
>
> +
>
> +  // Without a policy, there should be no constraints on va= riable creation.
>
> +  PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,
>
> +          &nbs= p;            &= nbsp;            &am= p;mTestGuid1,
>
> +          &nbs= p;            &= nbsp;            VAR= IABLE_ATTRIBUTE_BS_RT_AT,
>
> +          &nbs= p;            &= nbsp;            siz= eof(DummyData),
>
> +          &nbs= p;            &= nbsp;            Dum= myData );
>
> +  UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );
>
> +  PolicyCheck =3D ValidateSetVariable( TEST_VAR_3_NAME,
>
> +          &nbs= p;            &= nbsp;            &am= p;mTestGuid1,
>
> +          &nbs= p;            &= nbsp;            VAR= IABLE_ATTRIBUTE_BS_RT_AT,
>
> +          &nbs= p;            &= nbsp;            siz= eof(DummyData),
>
> +          &nbs= p;            &= nbsp;            Dum= myData );
>
> +  UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );
>
> +
>
> +  // Set a policy to test against.
>
> +
> UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolic= y.Hea
> der ) );
>
> +
>
> +  // Set consistent expectations on what the calls are look= ing for.
>
> +  expect_memory_count( StubGetVariableNull, VariableName, > TEST_VAR_2_NAME, sizeof(TEST_VAR_2_NAME), 4 );
>
> +  expect_memory_count( StubGetVariableNull, VendorGuid, &am= p;mTestGuid2,
> sizeof(mTestGuid2), 4 );
>
> +  ExpectedDataSize =3D 1;
>
> +  expect_memory_count( StubGetVariableNull, DataSize,
> &ExpectedDataSize, sizeof(ExpectedDataSize), 4 );
>
> +
>
> +  // With a policy, make sure that writes still work, since= the variable doesn't
> exist.
>
> +  will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_= NULL );    //
> Attributes
>
> +  will_return( StubGetVariableNull, 0 );   &= nbsp;           &nbs= p;            &= nbsp; // Size
>
> +  will_return( StubGetVariableNull, NULL );  &nbs= p;            &= nbsp;           // DataPt= r
>
> +  will_return( StubGetVariableNull, EFI_NOT_FOUND ); &= nbsp;           &nbs= p;    // Status
>
> +  PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,
>
> +          &nbs= p;            &= nbsp;            &am= p;mTestGuid1,
>
> +          &nbs= p;            &= nbsp;            VAR= IABLE_ATTRIBUTE_BS_RT_AT,
>
> +          &nbs= p;            &= nbsp;            siz= eof(DummyData),
>
> +          &nbs= p;            &= nbsp;            Dum= myData );
>
> +  UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );
>
> +  will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_= NULL );    //
> Attributes
>
> +  will_return( StubGetVariableNull, 0 );   &= nbsp;           &nbs= p;            &= nbsp; // Size
>
> +  will_return( StubGetVariableNull, NULL );  &nbs= p;            &= nbsp;           // DataPt= r
>
> +  will_return( StubGetVariableNull, EFI_NOT_FOUND ); &= nbsp;           &nbs= p;    // Status
>
> +  PolicyCheck =3D ValidateSetVariable( TEST_VAR_3_NAME,
>
> +          &nbs= p;            &= nbsp;            &am= p;mTestGuid1,
>
> +          &nbs= p;            &= nbsp;            VAR= IABLE_ATTRIBUTE_BS_RT_AT,
>
> +          &nbs= p;            &= nbsp;            siz= eof(DummyData),
>
> +          &nbs= p;            &= nbsp;            Dum= myData );
>
> +  UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );
>
> +
>
> +  // With a policy, make sure that a call with a correct st= ate variable fails.
>
> +  ValidationStateVar =3D 20;
>
> +  will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_= NULL );    //
> Attributes
>
> +  will_return( StubGetVariableNull, sizeof(ValidationStateV= ar) );     // Size
>
> +  will_return( StubGetVariableNull, &ValidationStateVar= );            // Da= taPtr
>
> +  will_return( StubGetVariableNull, EFI_SUCCESS ); &nb= sp;            =       // Status
>
> +  PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,
>
> +          &nbs= p;            &= nbsp;            &am= p;mTestGuid1,
>
> +          &nbs= p;            &= nbsp;            VAR= IABLE_ATTRIBUTE_BS_RT_AT,
>
> +          &nbs= p;            &= nbsp;            siz= eof(DummyData),
>
> +          &nbs= p;            &= nbsp;            Dum= myData );
>
> +  UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) );
>
> +  will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_= NULL );    //
> Attributes
>
> +  will_return( StubGetVariableNull, sizeof(ValidationStateV= ar) );     // Size
>
> +  will_return( StubGetVariableNull, &ValidationStateVar= );            // Da= taPtr
>
> +  will_return( StubGetVariableNull, EFI_SUCCESS ); &nb= sp;            =       // Status
>
> +  PolicyCheck =3D ValidateSetVariable( TEST_VAR_3_NAME,
>
> +          &nbs= p;            &= nbsp;            &am= p;mTestGuid1,
>
> +          &nbs= p;            &= nbsp;            VAR= IABLE_ATTRIBUTE_BS_RT_AT,
>
> +          &nbs= p;            &= nbsp;            siz= eof(DummyData),
>
> +          &nbs= p;            &= nbsp;            Dum= myData );
>
> +  UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) );
>
> +
>
> +  return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +LockOnStateShouldHandleErrorsGracefully (
>
> +  IN UNIT_TEST_CONTEXT      Contex= t
>
> +  )
>
> +{
>
> +  EXPANDED_VARIABLE_POLICY_ENTRY   ValidationPoli= cy =3D {
>
> +    {
>
> +      VARIABLE_POLICY_ENTRY_REVISION, >
> +      0,    // Will be p= opulated by init helper.
>
> +      0,    // Will be p= opulated by init helper.
>
> +      TEST_GUID_1,
>
> +      TEST_POLICY_MIN_SIZE_NULL,
>
> +      TEST_POLICY_MAX_SIZE_NULL,
>
> +      TEST_POLICY_ATTRIBUTES_NULL,
>
> +      TEST_POLICY_ATTRIBUTES_NULL,
>
> +      VARIABLE_POLICY_TYPE_LOCK_ON_VAR_= STATE
>
> +    },
>
> +    {
>
> +      TEST_GUID_2,
>
> +      20,     =       // Value
>
> +      0     &n= bsp;       // Padding
>
> +    },
>
> +    L"",
>
> +    L""
>
> +  };
>
> +  EFI_STATUS  PolicyCheck;
>
> +  UINT8       DummyData[12];<= br> >
> +  UT_ASSERT_TRUE( InitExpVarPolicyStrings( &ValidationP= olicy,
> TEST_VAR_1_NAME, TEST_VAR_2_NAME ) );
>
> +
>
> +
>
> +  // Without a policy, there should be no constraints on va= riable creation.
>
> +  PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,
>
> +          &nbs= p;            &= nbsp;            &am= p;mTestGuid1,
>
> +          &nbs= p;            &= nbsp;            VAR= IABLE_ATTRIBUTE_BS_RT_AT,
>
> +          &nbs= p;            &= nbsp;            siz= eof(DummyData),
>
> +          &nbs= p;            &= nbsp;            Dum= myData );
>
> +  UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );
>
> +
>
> +  // Set a policy to test against.
>
> +
> UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolic= y.Hea
> der ) );
>
> +
>
> +  // Configure the stub to not care about parameters. We're= testing errors.
>
> +  expect_any_always( StubGetVariableNull, VariableName ); >
> +  expect_any_always( StubGetVariableNull, VendorGuid );
>
> +  expect_any_always( StubGetVariableNull, DataSize );
>
> +
>
> +  // With a policy, make sure that writes still work, since= the variable doesn't
> exist.
>
> +  will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_= NULL );    //
> Attributes
>
> +  will_return( StubGetVariableNull, 0 );   &= nbsp;           &nbs= p;            &= nbsp; // Size
>
> +  will_return( StubGetVariableNull, NULL );  &nbs= p;            &= nbsp;           // DataPt= r
>
> +  will_return( StubGetVariableNull, EFI_NOT_FOUND ); &= nbsp;           &nbs= p;    // Status
>
> +  PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,
>
> +          &nbs= p;            &= nbsp;            &am= p;mTestGuid1,
>
> +          &nbs= p;            &= nbsp;            VAR= IABLE_ATTRIBUTE_BS_RT_AT,
>
> +          &nbs= p;            &= nbsp;            siz= eof(DummyData),
>
> +          &nbs= p;            &= nbsp;            Dum= myData );
>
> +  UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );
>
> +
>
> +  // Verify that state variables that are the wrong size wo= n't lock the variable.
>
> +  will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_= NULL );    //
> Attributes
>
> +  will_return( StubGetVariableNull, 0 );   &= nbsp;           &nbs= p;            &= nbsp; // Size
>
> +  will_return( StubGetVariableNull, NULL );  &nbs= p;            &= nbsp;           // DataPt= r
>
> +  will_return( StubGetVariableNull, EFI_BUFFER_TOO_SMALL );=            //
> Status
>
> +  PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,
>
> +          &nbs= p;            &= nbsp;            &am= p;mTestGuid1,
>
> +          &nbs= p;            &= nbsp;            VAR= IABLE_ATTRIBUTE_BS_RT_AT,
>
> +          &nbs= p;            &= nbsp;            siz= eof(DummyData),
>
> +          &nbs= p;            &= nbsp;            Dum= myData );
>
> +  UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );
>
> +
>
> +  // Verify that unexpected errors default to locked.
>
> +  will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_= NULL );    //
> Attributes
>
> +  will_return( StubGetVariableNull, 0 );   &= nbsp;           &nbs= p;            &= nbsp; // Size
>
> +  will_return( StubGetVariableNull, NULL );  &nbs= p;            &= nbsp;           // DataPt= r
>
> +  will_return( StubGetVariableNull, EFI_UNSUPPORTED ); = ;            &n= bsp;  // Status
>
> +  PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,
>
> +          &nbs= p;            &= nbsp;            &am= p;mTestGuid1,
>
> +          &nbs= p;            &= nbsp;            VAR= IABLE_ATTRIBUTE_BS_RT_AT,
>
> +          &nbs= p;            &= nbsp;            siz= eof(DummyData),
>
> +          &nbs= p;            &= nbsp;            Dum= myData );
>
> +  UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) );
>
> +
>
> +  will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_= NULL );    //
> Attributes
>
> +  will_return( StubGetVariableNull, 0 );   &= nbsp;           &nbs= p;            &= nbsp; // Size
>
> +  will_return( StubGetVariableNull, NULL );  &nbs= p;            &= nbsp;           // DataPt= r
>
> +  will_return( StubGetVariableNull, EFI_NOT_READY ); &= nbsp;           &nbs= p;    // Status
>
> +  PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,
>
> +          &nbs= p;            &= nbsp;            &am= p;mTestGuid1,
>
> +          &nbs= p;            &= nbsp;            VAR= IABLE_ATTRIBUTE_BS_RT_AT,
>
> +          &nbs= p;            &= nbsp;            siz= eof(DummyData),
>
> +          &nbs= p;            &= nbsp;            Dum= myData );
>
> +  UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) );
>
> +
>
> +  return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +BestMatchPriorityShouldBeObeyed (
>
> +  IN UNIT_TEST_CONTEXT      Contex= t
>
> +  )
>
> +{
>
> +  SIMPLE_VARIABLE_POLICY_ENTRY   ValidationPolicy= =3D {
>
> +    {
>
> +      VARIABLE_POLICY_ENTRY_REVISION, >
> +      sizeof(VARIABLE_POLICY_ENTRY) = 3; sizeof(L"Wild12Card34Placeholder"),
>
> +      sizeof(VARIABLE_POLICY_ENTRY), >
> +      TEST_GUID_1,
>
> +      TEST_POLICY_MIN_SIZE_NULL,
>
> +      TEST_POLICY_MAX_SIZE_NULL,
>
> +      TEST_POLICY_ATTRIBUTES_NULL,
>
> +      TEST_POLICY_ATTRIBUTES_NULL,
>
> +      VARIABLE_POLICY_TYPE_NO_LOCK
>
> +    },
>
> +    L"Wild12Card34Placeholder"
>
> +  };
>
> +  EFI_STATUS  PolicyCheck;
>
> +  UINT8       DummyData[70];<= br> >
> +  CHAR16      *PolicyName =3D (CHA= R16*)((UINT8*)&ValidationPolicy +
> sizeof(VARIABLE_POLICY_ENTRY));
>
> +  UINTN       PolicyNameSize = = =3D sizeof(L"Wild12Card34Placeholder");
>
> +  CHAR16      *FourWildcards =3D L= "Wild##Card##Placeholder";
>
> +  CHAR16      *ThreeWildcards =3D = L"Wild##Card#4Placeholder";
>
> +  CHAR16      *TwoWildcards =3D L&= quot;Wild##Card34Placeholder";
>
> +  CHAR16      *OneWildcard =3D L&q= uot;Wild#2Card34Placeholder";
>
> +  CHAR16      *NoWildcards =3D L&q= uot;Wild12Card34Placeholder";
>
> +
>
> +  // Create all of the policies from least restrictive to m= ost restrictive.
>
> +  // NoWildcards should be the most restrictive.
>
> +  ValidationPolicy.Header.MaxSize =3D 60;
>
> +  ValidationPolicy.Header.Size =3D ValidationPolicy.Header.= OffsetToName;
>
> +
> UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolic= y.Hea
> der ) );
>
> +  ValidationPolicy.Header.Size +=3D (UINT16)PolicyNameS= ize;
>
> +  ValidationPolicy.Header.MaxSize =3D 50;
>
> +  CopyMem( PolicyName, FourWildcards, PolicyNameSize );
>
> +
> UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolic= y.Hea
> der ) );
>
> +  ValidationPolicy.Header.MaxSize =3D 40;
>
> +  CopyMem( PolicyName, ThreeWildcards, PolicyNameSize ); >
> +
> UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolic= y.Hea
> der ) );
>
> +  ValidationPolicy.Header.MaxSize =3D 30;
>
> +  CopyMem( PolicyName, TwoWildcards, PolicyNameSize );
>
> +
> UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolic= y.Hea
> der ) );
>
> +  ValidationPolicy.Header.MaxSize =3D 20;
>
> +  CopyMem( PolicyName, OneWildcard, PolicyNameSize );
>
> +
> UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolic= y.Hea
> der ) );
>
> +  ValidationPolicy.Header.MaxSize =3D 10;
>
> +  CopyMem( PolicyName, NoWildcards, PolicyNameSize );
>
> +
> UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolic= y.Hea
> der ) );
>
> +
>
> +  // Verify that variables only matching the namespace have= the most
> flexible policy.
>
> +  PolicyCheck =3D ValidateSetVariable( L"ArbitraryName= ",
>
> +          &nbs= p;            &= nbsp;           &nbs= p; &mTestGuid1,
>
> +          &nbs= p;            &= nbsp;           &nbs= p; VARIABLE_ATTRIBUTE_BS_RT_AT,
>
> +          &nbs= p;            &= nbsp;           &nbs= p; 65,
>
> +          &nbs= p;            &= nbsp;           &nbs= p; DummyData );
>
> +  UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) );
>
> +  PolicyCheck =3D ValidateSetVariable( L"ArbitraryName= ",
>
> +          &nbs= p;            &= nbsp;           &nbs= p; &mTestGuid1,
>
> +          &nbs= p;            &= nbsp;           &nbs= p; VARIABLE_ATTRIBUTE_BS_RT_AT,
>
> +          &nbs= p;            &= nbsp;           &nbs= p; 55,
>
> +          &nbs= p;            &= nbsp;           &nbs= p; DummyData );
>
> +  UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );
>
> +
>
> +  // Verify that variables matching increasing characters g= et increasing policy
> restrictions.
>
> +  PolicyCheck =3D ValidateSetVariable( L"Wild77Card77P= laceholder",
>
> +          &nbs= p;            &= nbsp;           &nbs= p; &mTestGuid1,
>
> +          &nbs= p;            &= nbsp;           &nbs= p; VARIABLE_ATTRIBUTE_BS_RT_AT,
>
> +          &nbs= p;            &= nbsp;           &nbs= p; 55,
>
> +          &nbs= p;            &= nbsp;           &nbs= p; DummyData );
>
> +  UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) );
>
> +  PolicyCheck =3D ValidateSetVariable( L"Wild77Card77P= laceholder",
>
> +          &nbs= p;            &= nbsp;           &nbs= p; &mTestGuid1,
>
> +          &nbs= p;            &= nbsp;           &nbs= p; VARIABLE_ATTRIBUTE_BS_RT_AT,
>
> +          &nbs= p;            &= nbsp;           &nbs= p; 45,
>
> +          &nbs= p;            &= nbsp;           &nbs= p; DummyData );
>
> +  UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );
>
> +
>
> +  PolicyCheck =3D ValidateSetVariable( L"Wild77Card74P= laceholder",
>
> +          &nbs= p;            &= nbsp;           &nbs= p; &mTestGuid1,
>
> +          &nbs= p;            &= nbsp;           &nbs= p; VARIABLE_ATTRIBUTE_BS_RT_AT,
>
> +          &nbs= p;            &= nbsp;           &nbs= p; 45,
>
> +          &nbs= p;            &= nbsp;           &nbs= p; DummyData );
>
> +  UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) );
>
> +  PolicyCheck =3D ValidateSetVariable( L"Wild77Card74P= laceholder",
>
> +          &nbs= p;            &= nbsp;           &nbs= p; &mTestGuid1,
>
> +          &nbs= p;            &= nbsp;           &nbs= p; VARIABLE_ATTRIBUTE_BS_RT_AT,
>
> +          &nbs= p;            &= nbsp;           &nbs= p; 35,
>
> +          &nbs= p;            &= nbsp;           &nbs= p; DummyData );
>
> +  UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );
>
> +
>
> +  PolicyCheck =3D ValidateSetVariable( L"Wild77Card34P= laceholder",
>
> +          &nbs= p;            &= nbsp;           &nbs= p; &mTestGuid1,
>
> +          &nbs= p;            &= nbsp;           &nbs= p; VARIABLE_ATTRIBUTE_BS_RT_AT,
>
> +          &nbs= p;            &= nbsp;           &nbs= p; 35,
>
> +          &nbs= p;            &= nbsp;           &nbs= p; DummyData );
>
> +  UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) );
>
> +  PolicyCheck =3D ValidateSetVariable( L"Wild77Card34P= laceholder",
>
> +          &nbs= p;            &= nbsp;           &nbs= p; &mTestGuid1,
>
> +          &nbs= p;            &= nbsp;           &nbs= p; VARIABLE_ATTRIBUTE_BS_RT_AT,
>
> +          &nbs= p;            &= nbsp;           &nbs= p; 25,
>
> +          &nbs= p;            &= nbsp;           &nbs= p; DummyData );
>
> +  UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );
>
> +
>
> +  PolicyCheck =3D ValidateSetVariable( L"Wild72Card34P= laceholder",
>
> +          &nbs= p;            &= nbsp;           &nbs= p; &mTestGuid1,
>
> +          &nbs= p;            &= nbsp;           &nbs= p; VARIABLE_ATTRIBUTE_BS_RT_AT,
>
> +          &nbs= p;            &= nbsp;           &nbs= p; 25,
>
> +          &nbs= p;            &= nbsp;           &nbs= p; DummyData );
>
> +  UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) );
>
> +  PolicyCheck =3D ValidateSetVariable( L"Wild72Card34P= laceholder",
>
> +          &nbs= p;            &= nbsp;           &nbs= p; &mTestGuid1,
>
> +          &nbs= p;            &= nbsp;           &nbs= p; VARIABLE_ATTRIBUTE_BS_RT_AT,
>
> +          &nbs= p;            &= nbsp;           &nbs= p; 15,
>
> +          &nbs= p;            &= nbsp;           &nbs= p; DummyData );
>
> +  UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );
>
> +
>
> +  PolicyCheck =3D ValidateSetVariable( L"Wild12Card34P= laceholder",
>
> +          &nbs= p;            &= nbsp;           &nbs= p; &mTestGuid1,
>
> +          &nbs= p;            &= nbsp;           &nbs= p; VARIABLE_ATTRIBUTE_BS_RT_AT,
>
> +          &nbs= p;            &= nbsp;           &nbs= p; 15,
>
> +          &nbs= p;            &= nbsp;           &nbs= p; DummyData );
>
> +  UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) );
>
> +  PolicyCheck =3D ValidateSetVariable( L"Wild12Card34P= laceholder",
>
> +          &nbs= p;            &= nbsp;           &nbs= p; &mTestGuid1,
>
> +          &nbs= p;            &= nbsp;           &nbs= p; VARIABLE_ATTRIBUTE_BS_RT_AT,
>
> +          &nbs= p;            &= nbsp;           &nbs= p; 5,
>
> +          &nbs= p;            &= nbsp;           &nbs= p; DummyData );
>
> +  UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );
>
> +
>
> +  return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +
>
> +///=3D=3D=3D POLICY UTILITY SUITE
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +ShouldBeAbleToLockInterface (
>
> +  IN UNIT_TEST_CONTEXT      Contex= t
>
> +  )
>
> +{
>
> +  SIMPLE_VARIABLE_POLICY_ENTRY   TestPolicy =3D {=
>
> +    {
>
> +      VARIABLE_POLICY_ENTRY_REVISION, >
> +      sizeof(VARIABLE_POLICY_ENTRY) = 3; sizeof(TEST_VAR_1_NAME),
>
> +      sizeof(VARIABLE_POLICY_ENTRY), >
> +      TEST_GUID_1,
>
> +      TEST_POLICY_MIN_SIZE_NULL,
>
> +      TEST_POLICY_MAX_SIZE_NULL,
>
> +      TEST_POLICY_ATTRIBUTES_NULL,
>
> +      TEST_POLICY_ATTRIBUTES_NULL,
>
> +      VARIABLE_POLICY_TYPE_NO_LOCK
>
> +    },
>
> +    TEST_VAR_1_NAME
>
> +  };
>
> +
>
> +  // Make sure it's not already locked.
>
> +  UT_ASSERT_FALSE( IsVariablePolicyInterfaceLocked() );
>
> +  // Lock it.
>
> +  UT_ASSERT_NOT_EFI_ERROR( LockVariablePolicy() );
>
> +  // Verify that it's locked.
>
> +  UT_ASSERT_TRUE( IsVariablePolicyInterfaceLocked() );
>
> +
>
> +  // Verify that all state-changing commands fail.
>
> +  UT_ASSERT_TRUE( EFI_ERROR( LockVariablePolicy() ) );
>
> +  UT_ASSERT_TRUE( EFI_ERROR( DisableVariablePolicy() ) ); >
> +
> UT_ASSERT_TRUE( EFI_ERROR( RegisterVariablePolicy( &TestPolicy.He= ader )
> ) );
>
> +
>
> +  return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +ShouldBeAbleToDisablePolicyEnforcement (
>
> +  IN UNIT_TEST_CONTEXT      Contex= t
>
> +  )
>
> +{
>
> +  SIMPLE_VARIABLE_POLICY_ENTRY   TestPolicy =3D {=
>
> +    {
>
> +      VARIABLE_POLICY_ENTRY_REVISION, >
> +      sizeof(VARIABLE_POLICY_ENTRY) = 3; sizeof(TEST_VAR_1_NAME),
>
> +      sizeof(VARIABLE_POLICY_ENTRY), >
> +      TEST_GUID_1,
>
> +      TEST_POLICY_MIN_SIZE_10,
>
> +      TEST_POLICY_MAX_SIZE_200,
>
> +      TEST_POLICY_ATTRIBUTES_NULL,
>
> +      TEST_POLICY_ATTRIBUTES_NULL,
>
> +      VARIABLE_POLICY_TYPE_NO_LOCK
>
> +    },
>
> +    TEST_VAR_1_NAME
>
> +  };
>
> +  EFI_STATUS  PolicyCheck;
>
> +  UINT8       DummyData[TEST_= POLICY_MIN_SIZE_10-1];
>
> +
>
> +  // Make sure that the policy enforcement is currently ena= bled.
>
> +  UT_ASSERT_TRUE( IsVariablePolicyEnabled() );
>
> +  // Add a policy before it's disabled.
>
> +
> UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &TestPolicy.Head= er ) );
>
> +  // Disable the policy enforcement.
>
> +  UT_ASSERT_NOT_EFI_ERROR( DisableVariablePolicy() );
>
> +  // Make sure that the policy enforcement is currently dis= abled.
>
> +  UT_ASSERT_FALSE( IsVariablePolicyEnabled() );
>
> +
>
> +  // Check to make sure that a policy violation still passe= s.
>
> +  PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,
>
> +          &nbs= p;            &= nbsp;            &am= p;mTestGuid1,
>
> +          &nbs= p;            &= nbsp;            VAR= IABLE_ATTRIBUTE_NV_BS,
>
> +          &nbs= p;            &= nbsp;            siz= eof(DummyData),
>
> +          &nbs= p;            &= nbsp;            Dum= myData );
>
> +  UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );
>
> +
>
> +  return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +ShouldNotBeAbleToDisablePoliciesTwice (
>
> +  IN UNIT_TEST_CONTEXT      Contex= t
>
> +  )
>
> +{
>
> +  // Make sure that the policy enforcement is currently ena= bled.
>
> +  UT_ASSERT_TRUE( IsVariablePolicyEnabled() );
>
> +  // Disable the policy enforcement.
>
> +  UT_ASSERT_NOT_EFI_ERROR( DisableVariablePolicy() );
>
> +  // Make sure that the policy enforcement is currently dis= abled.
>
> +  UT_ASSERT_FALSE( IsVariablePolicyEnabled() );
>
> +  // Try to disable again and verify failure.
>
> +  UT_ASSERT_TRUE( EFI_ERROR( DisableVariablePolicy() ) ); >
> +
>
> +  return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +ShouldBeAbleToAddNewPoliciesAfterDisabled (
>
> +  IN UNIT_TEST_CONTEXT      Contex= t
>
> +  )
>
> +{
>
> +  SIMPLE_VARIABLE_POLICY_ENTRY   TestPolicy =3D {=
>
> +    {
>
> +      VARIABLE_POLICY_ENTRY_REVISION, >
> +      sizeof(VARIABLE_POLICY_ENTRY) = 3; sizeof(TEST_VAR_1_NAME),
>
> +      sizeof(VARIABLE_POLICY_ENTRY), >
> +      TEST_GUID_1,
>
> +      TEST_POLICY_MIN_SIZE_10,
>
> +      TEST_POLICY_MAX_SIZE_200,
>
> +      TEST_POLICY_ATTRIBUTES_NULL,
>
> +      TEST_POLICY_ATTRIBUTES_NULL,
>
> +      VARIABLE_POLICY_TYPE_NO_LOCK
>
> +    },
>
> +    TEST_VAR_1_NAME
>
> +  };
>
> +  EFI_STATUS  PolicyCheck;
>
> +
>
> +  // Make sure that the policy enforcement is currently ena= bled.
>
> +  UT_ASSERT_TRUE( IsVariablePolicyEnabled() );
>
> +  // Disable the policy enforcement.
>
> +  UT_ASSERT_NOT_EFI_ERROR( DisableVariablePolicy() );
>
> +
>
> +  // Make sure that new policy creation still works, it jus= t won't be enforced.
>
> +  PolicyCheck =3D RegisterVariablePolicy( &TestPolicy.H= eader );
>
> +  UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );
>
> +
>
> +  return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +ShouldBeAbleToLockAfterDisabled (
>
> +  IN UNIT_TEST_CONTEXT      Contex= t
>
> +  )
>
> +{
>
> +  // Make sure that the policy enforcement is currently ena= bled.
>
> +  UT_ASSERT_TRUE( IsVariablePolicyEnabled() );
>
> +  // Disable the policy enforcement.
>
> +  UT_ASSERT_NOT_EFI_ERROR( DisableVariablePolicy() );
>
> +
>
> +  // Make sure that we can lock in this state.
>
> +  UT_ASSERT_FALSE( IsVariablePolicyInterfaceLocked() );
>
> +  UT_ASSERT_NOT_EFI_ERROR( LockVariablePolicy() );
>
> +  UT_ASSERT_TRUE( IsVariablePolicyInterfaceLocked() );
>
> +
>
> +  return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +ShouldBeAbleToDumpThePolicyTable (
>
> +  IN UNIT_TEST_CONTEXT      Contex= t
>
> +  )
>
> +{
>
> +  SIMPLE_VARIABLE_POLICY_ENTRY   TestPolicy =3D {=
>
> +    {
>
> +      VARIABLE_POLICY_ENTRY_REVISION, >
> +      sizeof(VARIABLE_POLICY_ENTRY) = 3; sizeof(TEST_VAR_1_NAME),
>
> +      sizeof(VARIABLE_POLICY_ENTRY), >
> +      TEST_GUID_1,
>
> +      TEST_POLICY_MIN_SIZE_10,
>
> +      TEST_POLICY_MAX_SIZE_200,
>
> +      TEST_POLICY_ATTRIBUTES_NULL,
>
> +      TEST_POLICY_ATTRIBUTES_NULL,
>
> +      VARIABLE_POLICY_TYPE_NO_LOCK
>
> +    },
>
> +    TEST_VAR_1_NAME
>
> +  };
>
> +  EFI_STATUS  PolicyCheck;
>
> +  UINT32      DumpSize;
>
> +  UINT32      BufferSize;
>
> +  VOID        *DumpBuffe= r;
>
> +
>
> +  // For good measure, test some parameter validation.
>
> +  UT_ASSERT_STATUS_EQUAL( DumpVariablePolicy( NULL, NULL ),=
> EFI_INVALID_PARAMETER );
>
> +  DumpSize =3D 10;
>
> +  UT_ASSERT_STATUS_EQUAL( DumpVariablePolicy( NULL, &Du= mpSize ),
> EFI_INVALID_PARAMETER );
>
> +
>
> +  // Now for the actual test case.
>
> +
>
> +  // Allocate a buffer to hold the output.
>
> +  BufferSize =3D sizeof(VARIABLE_POLICY_ENTRY) +
> sizeof(TEST_VAR_1_NAME);
>
> +  DumpBuffer =3D AllocatePool( BufferSize );
>
> +  UT_ASSERT_NOT_EQUAL( DumpBuffer, NULL );
>
> +
>
> +  // Verify that the current table size is 0.
>
> +  DumpSize =3D BufferSize;
>
> +  UT_ASSERT_NOT_EFI_ERROR( DumpVariablePolicy( DumpBuffer,<= br> > &DumpSize ) );
>
> +  UT_ASSERT_EQUAL( DumpSize, 0 );
>
> +
>
> +  // Now, set a new policy.
>
> +
> UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &TestPolicy.Head= er ) );
>
> +
>
> +  // Make sure that the new return is non-zero and fails as= expected.
>
> +  DumpSize =3D 0;
>
> +  PolicyCheck =3D DumpVariablePolicy( NULL, &DumpSize )= ;
>
> +  UT_ASSERT_STATUS_EQUAL( PolicyCheck, EFI_BUFFER_TOO_SMALL= );
>
> +  UT_ASSERT_EQUAL( DumpSize, BufferSize );
>
> +
>
> +  // Now verify that we can fetch the dump.
>
> +  DumpSize =3D BufferSize;
>
> +  UT_ASSERT_NOT_EFI_ERROR( DumpVariablePolicy( DumpBuffer,<= br> > &DumpSize ) );
>
> +  UT_ASSERT_EQUAL( DumpSize, BufferSize );
>
> +  UT_ASSERT_MEM_EQUAL( &TestPolicy, DumpBuffer, BufferS= ize );
>
> +
>
> +  // Always put away your toys.
>
> +  FreePool( DumpBuffer );
>
> +
>
> +  return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +ShouldBeAbleToDumpThePolicyTableAfterDisabled (
>
> +  IN UNIT_TEST_CONTEXT      Contex= t
>
> +  )
>
> +{
>
> +  SIMPLE_VARIABLE_POLICY_ENTRY   TestPolicy =3D {=
>
> +    {
>
> +      VARIABLE_POLICY_ENTRY_REVISION, >
> +      sizeof(VARIABLE_POLICY_ENTRY) = 3; sizeof(TEST_VAR_1_NAME),
>
> +      sizeof(VARIABLE_POLICY_ENTRY), >
> +      TEST_GUID_1,
>
> +      TEST_POLICY_MIN_SIZE_10,
>
> +      TEST_POLICY_MAX_SIZE_200,
>
> +      TEST_POLICY_ATTRIBUTES_NULL,
>
> +      TEST_POLICY_ATTRIBUTES_NULL,
>
> +      VARIABLE_POLICY_TYPE_NO_LOCK
>
> +    },
>
> +    TEST_VAR_1_NAME
>
> +  };
>
> +  SIMPLE_VARIABLE_POLICY_ENTRY   TestPolicy2 =3D = {
>
> +    {
>
> +      VARIABLE_POLICY_ENTRY_REVISION, >
> +      sizeof(VARIABLE_POLICY_ENTRY) = 3; sizeof(TEST_VAR_2_NAME),
>
> +      sizeof(VARIABLE_POLICY_ENTRY), >
> +      TEST_GUID_2,
>
> +      TEST_POLICY_MIN_SIZE_10,
>
> +      TEST_POLICY_MAX_SIZE_200,
>
> +      TEST_POLICY_ATTRIBUTES_NULL,
>
> +      TEST_POLICY_ATTRIBUTES_NULL,
>
> +      VARIABLE_POLICY_TYPE_NO_LOCK
>
> +    },
>
> +    TEST_VAR_2_NAME
>
> +  };
>
> +  EFI_STATUS  PolicyCheck;
>
> +  UINT32      DumpSize;
>
> +  VOID        *DumpBuffe= r;
>
> +
>
> +  DumpBuffer =3D NULL;
>
> +  DumpSize =3D 0;
>
> +
>
> +  // Register a new policy.
>
> +
> UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &TestPolicy.Head= er ) );
>
> +  // Make sure that we can dump the policy.
>
> +  PolicyCheck =3D DumpVariablePolicy( DumpBuffer, &Dump= Size );
>
> +  UT_ASSERT_STATUS_EQUAL( PolicyCheck, EFI_BUFFER_TOO_SMALL= );
>
> +  DumpBuffer =3D AllocatePool( DumpSize );
>
> +  UT_ASSERT_NOT_EFI_ERROR( DumpVariablePolicy( DumpBuffer,<= br> > &DumpSize ) );
>
> +  UT_ASSERT_MEM_EQUAL( DumpBuffer, &TestPolicy, DumpSiz= e );
>
> +
>
> +  // Clean up from this step.
>
> +  FreePool( DumpBuffer );
>
> +  DumpBuffer =3D NULL;
>
> +  DumpSize =3D 0;
>
> +
>
> +  // Now disable the engine.
>
> +  DisableVariablePolicy();
>
> +
>
> +  // Now register a new policy and make sure that both can = be dumped.
>
> +
> UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &TestPolicy2.Hea= der )
> );
>
> +  // Make sure that we can dump the policy.
>
> +  PolicyCheck =3D DumpVariablePolicy( DumpBuffer, &Dump= Size );
>
> +  UT_ASSERT_STATUS_EQUAL( PolicyCheck, EFI_BUFFER_TOO_SMALL= );
>
> +  DumpBuffer =3D AllocatePool( DumpSize );
>
> +  UT_ASSERT_NOT_EFI_ERROR( DumpVariablePolicy( DumpBuffer,<= br> > &DumpSize ) );
>
> +
>
> +  // Finally, make sure that both policies are in the dump.=
>
> +  UT_ASSERT_MEM_EQUAL( DumpBuffer, &TestPolicy,
> TestPolicy.Header.Size );
>
> +  UT_ASSERT_MEM_EQUAL( (UINT8*)DumpBuffer + TestPolicy.= Header.Size,
>
> +          &nbs= p;             = &TestPolicy2,
>
> +          &nbs= p;             = TestPolicy2.Header.Size );
>
> +
>
> +  // Always put away your toys.
>
> +  FreePool( DumpBuffer );
>
> +
>
> +  return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +
>
> +///=3D=3D=3D TEST ENGINE
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D >
> +
>
> +/**
>
> +  SampleUnitTestApp
>
> +
>
> +  @param[in] ImageHandle  The firmware allocated handl= e for the EFI image.
>
> +  @param[in] SystemTable  A pointer to the EFI System = Table.
>
> +
>
> +  @retval EFI_SUCCESS     The entry poi= nt executed successfully.
>
> +  @retval other       &n= bsp;   Some error occured when executing this entry point.
>
> +
>
> +**/
>
> +int
>
> +main (
>
> +  )
>
> +{
>
> +  EFI_STATUS        = ;          Status;
>
> +  UNIT_TEST_FRAMEWORK_HANDLE  Framework =3D NULL;
>
> +  UNIT_TEST_SUITE_HANDLE      Arch= Tests;
>
> +  UNIT_TEST_SUITE_HANDLE      Poli= cyTests;
>
> +  UNIT_TEST_SUITE_HANDLE      Util= ityTests;
>
> +#ifdef INTERNAL_UNIT_TEST
>
> +  UNIT_TEST_SUITE_HANDLE      Inte= rnalTests;
>
> +#endif // INTERNAL_UNIT_TEST
>
> +
>
> +  DEBUG(( DEBUG_INFO, "%a v%a\n", UNIT_TEST_NAME,=
> UNIT_TEST_VERSION ));
>
> +
>
> +  //
>
> +  // Start setting up the test framework for running the te= sts.
>
> +  //
>
> +  Status =3D InitUnitTestFramework( &Framework, UNIT_TE= ST_NAME,
> gEfiCallerBaseName, UNIT_TEST_VERSION );
>
> +  if (EFI_ERROR( Status ))
>
> +  {
>
> +    DEBUG((DEBUG_ERROR, "Failed in InitUnitT= estFramework. Status =3D %r\n",
> Status));
>
> +    goto EXIT;
>
> +  }
>
> +
>
> +
>
> +  //
>
> +  // Add all test suites and tests.
>
> +  //
>
> +  Status =3D CreateUnitTestSuite( &ArchTests, Framework= , "Variable Policy
> Architectural Tests", "VarPolicy.Arch", NULL, NULL );<= br> >
> +  if (EFI_ERROR( Status ))
>
> +  {
>
> +    DEBUG((DEBUG_ERROR, "Failed in CreateUni= tTestSuite for
> ArchTests\n"));
>
> +    Status =3D EFI_OUT_OF_RESOURCES;
>
> +    goto EXIT;
>
> +  }
>
> +  AddTestCase( ArchTests,
>
> +          &nbs= p;     "Deinitialization should fail if not previo= usly initialized",
> "VarPolicy.Arch.OnlyDeinit",
>
> +          &nbs= p;     ShouldFailDeinitWithoutInit, NULL, NULL, NULL );=
>
> +  AddTestCase( ArchTests,
>
> +          &nbs= p;     "Initialization followed by deinitializatio= n should succeed",
> "VarPolicy.Arch.InitDeinit",
>
> +          &nbs= p;     ShouldBeAbleToInitAndDeinitTheLibrary, NULL, NUL= L, NULL );
>
> +  AddTestCase( ArchTests,
>
> +          &nbs= p;     "The initialization function fail if called= twice without a deinit",
> "VarPolicy.Arch.InitTwice",
>
> +          &nbs= p;     ShouldNotBeAbleToInitializeTheLibraryTwice, NULL= , LibCleanup,
> NULL );
>
> +  AddTestCase( ArchTests,
>
> +          &nbs= p;     "API functions should be unavailable until = library is initialized",
> "VarPolicy.Arch.UninitApiOff",
>
> +          &nbs= p;     ApiCommandsShouldNotRespondIfLibIsUninitialized,= NULL,
> LibCleanup, NULL );
>
> +
>
> +#ifdef INTERNAL_UNIT_TEST
>
> +  Status =3D CreateUnitTestSuite( &InternalTests, Frame= work, "Variable Policy
> Internal Tests", "VarPolicy.Internal", NULL, NULL ); >
> +  if (EFI_ERROR( Status ))
>
> +  {
>
> +    DEBUG((DEBUG_ERROR, "Failed in CreateUni= tTestSuite for
> InternalTests\n"));
>
> +    Status =3D EFI_OUT_OF_RESOURCES;
>
> +    goto EXIT;
>
> +  }
>
> +  AddTestCase( InternalTests,
>
> +          &nbs= p;     "Policy matching should use name and GUID&q= uot;,
> "VarPolicy.Internal.NameGuid",
>
> +          &nbs= p;     PoliciesShouldMatchByNameAndGuid, LibInitMocked,= LibCleanup,
> NULL );
>
> +  AddTestCase( InternalTests,
>
> +          &nbs= p;     "# sign wildcards should match digits"= ,
> "VarPolicy.Internal.WildDigits",
>
> +          &nbs= p;     WildcardPoliciesShouldMatchDigits, LibInitMocked= , LibCleanup,
> NULL );
>
> +  AddTestCase( InternalTests,
>
> +          &nbs= p;     "Digit wildcards should check edge cases&qu= ot;,
> "VarPolicy.Internal.WildDigitsAdvanced",
>
> +          &nbs= p;     WildcardPoliciesShouldMatchDigitsAdvanced, LibIn= itMocked,
> LibCleanup, NULL );
>
> +  AddTestCase( InternalTests,
>
> +          &nbs= p;     "Empty names should match an entire namespa= ce",
> "VarPolicy.Internal.WildNamespace",
>
> +          &nbs= p;     WildcardPoliciesShouldMatchNamespaces, LibInitMo= cked,
> LibCleanup, NULL );
>
> +  AddTestCase( InternalTests,
>
> +          &nbs= p;     "Match priority should weight correctly bas= ed on wildcards",
> "VarPolicy.Internal.Priorities",
>
> +          &nbs= p;     MatchPrioritiesShouldFollowRules, LibInitMocked,= LibCleanup,
> NULL );
>
> +#endif // INTERNAL_UNIT_TEST
>
> +
>
> +  Status =3D CreateUnitTestSuite( &PolicyTests, Framewo= rk, "Variable Policy
> Manipulation Tests", "VarPolicy.Policy", NULL, NULL );=
>
> +  if (EFI_ERROR( Status ))
>
> +  {
>
> +    DEBUG((DEBUG_ERROR, "Failed in CreateUni= tTestSuite for
> PolicyTests\n"));
>
> +    Status =3D EFI_OUT_OF_RESOURCES;
>
> +    goto EXIT;
>
> +  }
>
> +  AddTestCase( PolicyTests,
>
> +          &nbs= p;     "RegisterShouldAllowNamespaceWildcards"= ;,
> "VarPolicy.Policy.AllowNamespace",
>
> +          &nbs= p;     RegisterShouldAllowNamespaceWildcards, LibInitMo= cked,
> LibCleanup, NULL );
>
> +  AddTestCase( PolicyTests,
>
> +          &nbs= p;     "RegisterShouldAllowStateVarsForNamespaces&= quot;,
> "VarPolicy.Policy.AllowStateNamespace",
>
> +          &nbs= p;     RegisterShouldAllowStateVarsForNamespaces, LibIn= itMocked,
> LibCleanup, NULL );
>
> +  AddTestCase( PolicyTests,
>
> +          &nbs= p;     "RegisterShouldRejectNullPointers", &q= uot;VarPolicy.Policy.NullPointers",
>
> +          &nbs= p;     RegisterShouldRejectNullPointers, LibInitMocked,= LibCleanup,
> NULL );
>
> +  AddTestCase( PolicyTests,
>
> +          &nbs= p;     "RegisterShouldRejectBadRevisions", > "VarPolicy.Policy.BadRevisions",
>
> +          &nbs= p;     RegisterShouldRejectBadRevisions, LibInitMocked,= LibCleanup,
> NULL );
>
> +  AddTestCase( PolicyTests,
>
> +          &nbs= p;     "RegisterShouldRejectBadSizes", "= VarPolicy.Policy.BadSizes",
>
> +          &nbs= p;     RegisterShouldRejectBadSizes, LibInitMocked, Lib= Cleanup, NULL );
>
> +  AddTestCase( PolicyTests,
>
> +          &nbs= p;     "RegisterShouldRejectBadOffsets", &quo= t;VarPolicy.Policy.BadOffsets",
>
> +          &nbs= p;     RegisterShouldRejectBadOffsets, LibInitMocked, L= ibCleanup, NULL );
>
> +  AddTestCase( PolicyTests,
>
> +          &nbs= p;     "RegisterShouldRejectMissingStateStrings&qu= ot;,
> "VarPolicy.Policy.MissingStateString",
>
> +          &nbs= p;     RegisterShouldRejectMissingStateStrings, LibInit= Mocked,
> LibCleanup, NULL );
>
> +  AddTestCase( PolicyTests,
>
> +          &nbs= p;     "RegisterShouldRejectStringsMissingNull&quo= t;,
> "VarPolicy.Policy.MissingNull",
>
> +          &nbs= p;     RegisterShouldRejectStringsMissingNull, LibInitM= ocked, LibCleanup,
> NULL );
>
> +  AddTestCase( PolicyTests,
>
> +          &nbs= p;     "RegisterShouldRejectMalformedStrings"= ,
> "VarPolicy.Policy.MalformedStrings",
>
> +          &nbs= p;     RegisterShouldRejectMalformedStrings, LibInitMoc= ked, LibCleanup,
> NULL );
>
> +  AddTestCase( PolicyTests,
>
> +          &nbs= p;     "RegisterShouldRejectUnpackedPolicies"= ,
> "VarPolicy.Policy.PolicyPacking",
>
> +          &nbs= p;     RegisterShouldRejectUnpackedPolicies, LibInitMoc= ked, LibCleanup,
> NULL );
>
> +  AddTestCase( PolicyTests,
>
> +          &nbs= p;     "RegisterShouldRejectInvalidNameCharacters&= quot;,
> "VarPolicy.Policy.InvalidCharacters",
>
> +          &nbs= p;     RegisterShouldRejectInvalidNameCharacters, LibIn= itMocked,
> LibCleanup, NULL );
>
> +  AddTestCase( PolicyTests,
>
> +          &nbs= p;     "RegisterShouldRejectBadPolicyConstraints&q= uot;,
> "VarPolicy.Policy.BadConstraints",
>
> +          &nbs= p;     RegisterShouldRejectBadPolicyConstraints, LibIni= tMocked,
> LibCleanup, NULL );
>
> +  AddTestCase( PolicyTests,
>
> +          &nbs= p;     "RegisterShouldRejectUnknownLockPolicies&qu= ot;,
> "VarPolicy.Policy.BadLocks",
>
> +          &nbs= p;     RegisterShouldRejectUnknownLockPolicies, LibInit= Mocked,
> LibCleanup, NULL );
>
> +  AddTestCase( PolicyTests,
>
> +          &nbs= p;     "RegisterShouldRejectPolicesWithTooManyWild= cards",
> "VarPolicy.Policy.TooManyWildcards",
>
> +          &nbs= p;     RegisterShouldRejectPolicesWithTooManyWildcards,= LibInitMocked,
> LibCleanup, NULL );
>
> +  AddTestCase( PolicyTests,
>
> +          &nbs= p;     "RegisterShouldRejectDuplicatePolicies"= ;,
> "VarPolicy.Policy.DuplicatePolicies",
>
> +          &nbs= p;     RegisterShouldRejectDuplicatePolicies, LibInitMo= cked, LibCleanup,
> NULL );
>
> +  AddTestCase( PolicyTests,
>
> +          &nbs= p;     "Variables that exceed min or max sizes sho= uld be rejected",
> "VarPolicy.Policy.MinMax",
>
> +          &nbs= p;     MinAndMaxSizePoliciesShouldBeHonored, LibInitMoc= ked,
> LibCleanup, NULL );
>
> +  AddTestCase( PolicyTests,
>
> +          &nbs= p;     "AttributeMustPoliciesShouldBeHonored"= ,
> "VarPolicy.Policy.AttrMust",
>
> +          &nbs= p;     AttributeMustPoliciesShouldBeHonored, LibInitMoc= ked, LibCleanup,
> NULL );
>
> +  AddTestCase( PolicyTests,
>
> +          &nbs= p;     "AttributeCantPoliciesShouldBeHonored"= ,
> "VarPolicy.Policy.AttrCant",
>
> +          &nbs= p;     AttributeCantPoliciesShouldBeHonored, LibInitMoc= ked, LibCleanup,
> NULL );
>
> +  AddTestCase( PolicyTests,
>
> +          &nbs= p;     "VariablesShouldBeDeletableRegardlessOfSize= ",
> "VarPolicy.Policy.DeleteIgnoreSize",
>
> +          &nbs= p;     VariablesShouldBeDeletableRegardlessOfSize, LibI= nitMocked,
> LibCleanup, NULL );
>
> +  AddTestCase( PolicyTests,
>
> +          &nbs= p;     "LockNowPoliciesShouldBeHonored",
> "VarPolicy.Policy.VARIABLE_POLICY_TYPE_LOCK_NOW",
>
> +          &nbs= p;     LockNowPoliciesShouldBeHonored, LibInitMocked, L= ibCleanup,
> NULL );
>
> +  AddTestCase( PolicyTests,
>
> +          &nbs= p;     "LockOnCreatePoliciesShouldBeHonored",=
> "VarPolicy.Policy.VARIABLE_POLICY_TYPE_LOCK_ON_CREATE",
>
> +          &nbs= p;     LockOnCreatePoliciesShouldBeHonored, LibInitMock= ed, LibCleanup,
> NULL );
>
> +  AddTestCase( PolicyTests,
>
> +          &nbs= p;     "LockOnStatePoliciesShouldBeHonored",<= br> > "VarPolicy.Policy.LockState",
>
> +          &nbs= p;     LockOnStatePoliciesShouldBeHonored, LibInitMocke= d, LibCleanup,
> NULL );
>
> +  AddTestCase( PolicyTests,
>
> +          &nbs= p;     "LockOnStatePoliciesShouldApplyToNamespaces= ",
> "VarPolicy.Policy.NamespaceLockState",
>
> +          &nbs= p;     LockOnStatePoliciesShouldApplyToNamespaces, LibI= nitMocked,
> LibCleanup, NULL );
>
> +  AddTestCase( PolicyTests,
>
> +          &nbs= p;     "LockOnStateShouldHandleErrorsGracefully&qu= ot;,
> "VarPolicy.Policy.LockStateErrors",
>
> +          &nbs= p;     LockOnStateShouldHandleErrorsGracefully, LibInit= Mocked,
> LibCleanup, NULL );
>
> +  AddTestCase( PolicyTests,
>
> +          &nbs= p;     "BestMatchPriorityShouldBeObeyed", &qu= ot;VarPolicy.Policy.BestMatch",
>
> +          &nbs= p;     BestMatchPriorityShouldBeObeyed, LibInitMocked, = LibCleanup,
> NULL );
>
> +
>
> +  Status =3D CreateUnitTestSuite( &UtilityTests, Framew= ork, "Variable Policy
> Utility Tests", "VarPolicy.Utility", NULL, NULL );
>
> +  if (EFI_ERROR( Status ))
>
> +  {
>
> +    DEBUG((DEBUG_ERROR, "Failed in CreateUni= tTestSuite for
> UtilityTests\n"));
>
> +    Status =3D EFI_OUT_OF_RESOURCES;
>
> +    goto EXIT;
>
> +  }
>
> +  AddTestCase( UtilityTests,
>
> +          &nbs= p;     "API commands that change state should not = respond after
> interface is locked", "VarPolicy.Utility.InterfaceLock"= ;,
>
> +          &nbs= p;     ShouldBeAbleToLockInterface, LibInitMocked, LibC= leanup, NULL );
>
> +  AddTestCase( UtilityTests,
>
> +          &nbs= p;     "All policies should pass once enforcement = is disabled",
> "VarPolicy.Utility.DisableEnforcement",
>
> +          &nbs= p;     ShouldBeAbleToDisablePolicyEnforcement, LibInitM= ocked,
> LibCleanup, NULL );
>
> +  AddTestCase( UtilityTests,
>
> +          &nbs= p;     "Disabling enforcement twice should produce= an error",
> "VarPolicy.Utility.DisableEnforcementTwice",
>
> +          &nbs= p;     ShouldNotBeAbleToDisablePoliciesTwice, LibInitMo= cked,
> LibCleanup, NULL );
>
> +  AddTestCase( UtilityTests,
>
> +          &nbs= p;     "ShouldBeAbleToAddNewPoliciesAfterDisabled&= quot;,
> "VarPolicy.Utility.AddAfterDisable",
>
> +          &nbs= p;     ShouldBeAbleToAddNewPoliciesAfterDisabled, LibIn= itMocked,
> LibCleanup, NULL );
>
> +  AddTestCase( UtilityTests,
>
> +          &nbs= p;     "ShouldBeAbleToLockAfterDisabled",
> "VarPolicy.Utility.LockAfterDisable",
>
> +          &nbs= p;     ShouldBeAbleToLockAfterDisabled, LibInitMocked, = LibCleanup,
> NULL );
>
> +  AddTestCase( UtilityTests,
>
> +          &nbs= p;     "Should be able to dump the policy table&qu= ot;,
> "VarPolicy.Utility.DumpTable",
>
> +          &nbs= p;     ShouldBeAbleToDumpThePolicyTable, LibInitMocked,= LibCleanup,
> NULL );
>
> +  AddTestCase( UtilityTests,
>
> +          &nbs= p;     "ShouldBeAbleToDumpThePolicyTableAfterDisab= led",
> "VarPolicy.Utility.DumpTableAfterDisable",
>
> +          &nbs= p;     ShouldBeAbleToDumpThePolicyTableAfterDisabled, L= ibInitMocked,
> LibCleanup, NULL );
>
> +
>
> +
>
> +  //
>
> +  // Execute the tests.
>
> +  //
>
> +  Status =3D RunAllTestSuites( Framework );
>
> +
>
> +EXIT:
>
> +  if (Framework !=3D NULL)
>
> +  {
>
> +    FreeUnitTestFramework( Framework );
>
> +  }
>
> +
>
> +  return Status;
>
> +}
>
> diff --git a/MdeModulePkg/Include/Library/VariablePolicyLib.h
> b/MdeModulePkg/Include/Library/VariablePolicyLib.h
> new file mode 100644
> index 000000000000..efd1840112ec
> --- /dev/null
> +++ b/MdeModulePkg/Include/Library/VariablePolicyLib.h > @@ -0,0 +1,207 @@
> +/** @file -- VariablePolicyLib.h
>
> +Business logic for Variable Policy enforcement.
>
> +
>
> +Copyright (c) Microsoft Corporation.
>
> +SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +
>
> +**/
>
> +
>
> +#ifndef _VARIABLE_POLICY_LIB_H_
>
> +#define _VARIABLE_POLICY_LIB_H_
>
> +
>
> +#include <Protocol/VariablePolicy.h>
>
> +
>
> +/**
>
> +  This API function validates and registers a new policy wi= th
>
> +  the policy enforcement engine.
>
> +
>
> +  @param[in]  NewPolicy     Pointe= r to the incoming policy structure.
>
> +
>
> +  @retval     EFI_SUCCESS
>
> +  @retval     EFI_INVALID_PARAMETER&nbs= p;  NewPolicy is NULL or is internally
> inconsistent.
>
> +  @retval     EFI_ALREADY_STARTED =     An identical matching policy already
> exists.
>
> +  @retval     EFI_WRITE_PROTECTED =     The interface has been locked until
> the next reboot.
>
> +  @retval     EFI_UNSUPPORTED &nbs= p;       Policy enforcement has been disabled= .
> No reason to add more policies.
>
> +  @retval     EFI_ABORTED  &n= bsp;          A calculation er= ror has prevented this
> function from completing.
>
> +  @retval     EFI_OUT_OF_RESOURCES = ;   Cannot grow the table to hold any
> more policies.
>
> +  @retval     EFI_NOT_READY  =          Library has not yet been i= nitialized.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +RegisterVariablePolicy (
>
> +  IN CONST VARIABLE_POLICY_ENTRY    *NewPoli= cy
>
> +  );
>
> +
>
> +
>
> +/**
>
> +  This API function checks to see whether the parameters to= SetVariable
> would
>
> +  be allowed according to the current variable policies. >
> +
>
> +  @param[in]  VariableName    &nbs= p;  Same as EFI_SET_VARIABLE.
>
> +  @param[in]  VendorGuid     =     Same as EFI_SET_VARIABLE.
>
> +  @param[in]  Attributes     =     Same as EFI_SET_VARIABLE.
>
> +  @param[in]  DataSize     &n= bsp;     Same as EFI_SET_VARIABLE.
>
> +  @param[in]  Data      =          Same as EFI_SET_VARIABLE.<= br> >
> +
>
> +  @retval     EFI_SUCCESS  &n= bsp;          A matching polic= y allows this update.
>
> +  @retval     EFI_SUCCESS  &n= bsp;          There are curren= tly no policies that restrict
> this update.
>
> +  @retval     EFI_SUCCESS  &n= bsp;          The protections = have been disable until the
> next reboot.
>
> +  @retval     EFI_WRITE_PROTECTED =     Variable is currently locked.
>
> +  @retval     EFI_INVALID_PARAMETER&nbs= p;  Attributes or size are invalid.
>
> +  @retval     EFI_ABORTED  &n= bsp;          A lock policy ex= ists, but an error prevented
> evaluation.
>
> +  @retval     EFI_NOT_READY  =          Library has not been initi= alized.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +ValidateSetVariable (
>
> +  IN  CHAR16       =             &nb= sp;   *VariableName,
>
> +  IN  EFI_GUID      &nbs= p;            &= nbsp; *VendorGuid,
>
> +  IN  UINT32       =             &nb= sp;   Attributes,
>
> +  IN  UINTN       &= nbsp;           &nbs= p;    DataSize,
>
> +  IN  VOID       &n= bsp;            = ;     *Data
>
> +  );
>
> +
>
> +
>
> +/**
>
> +  This API function disables the variable policy enforcemen= t. If it's
>
> +  already been called once, will return EFI_ALREADY_STARTED= .
>
> +
>
> +  @retval     EFI_SUCCESS
>
> +  @retval     EFI_ALREADY_STARTED =   Has already been called once this boot.
>
> +  @retval     EFI_WRITE_PROTECTED =   Interface has been locked until reboot.
>
> +  @retval     EFI_WRITE_PROTECTED =   Interface option is disabled by platform
> PCD.
>
> +  @retval     EFI_NOT_READY  = Library has not yet been initialized.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +DisableVariablePolicy (
>
> +  VOID
>
> +  );
>
> +
>
> +
>
> +/**
>
> +  This API function will dump the entire contents of the va= riable policy table.
>
> +
>
> +  Similar to GetVariable, the first call can be made with a= 0 size and it will
> return
>
> +  the size of the buffer required to hold the entire table.=
>
> +
>
> +  @param[out]     Policy  Pointer = to the policy buffer. Can be NULL if Size is 0.
>
> +  @param[in,out]  Size    On input, the= size of the output buffer. On output,
> the size
>
> +          &nbs= p;            &= nbsp;  of the data returned.
>
> +
>
> +  @retval     EFI_SUCCESS  &n= bsp;          Policy data is i= n the output buffer and Size
> has been updated.
>
> +  @retval     EFI_INVALID_PARAMETER&nbs= p;  Size is NULL, or Size is non-zero and
> Policy is NULL.
>
> +  @retval     EFI_BUFFER_TOO_SMALL = ;   Size is insufficient to hold policy. Size
> updated with required size.
>
> +  @retval     EFI_NOT_READY  =          Library has not yet been i= nitialized.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +DumpVariablePolicy (
>
> +  OUT     UINT8    =      *Policy,
>
> +  IN OUT  UINT32      &n= bsp; *Size
>
> +  );
>
> +
>
> +
>
> +/**
>
> +  This API function returns whether or not the policy engin= e is
>
> +  currently being enforced.
>
> +
>
> +  @retval     TRUE
>
> +  @retval     FALSE
>
> +  @retval     FALSE   &n= bsp;     Library has not yet been initialized.
>
> +
>
> +**/
>
> +BOOLEAN
>
> +EFIAPI
>
> +IsVariablePolicyEnabled (
>
> +  VOID
>
> +  );
>
> +
>
> +
>
> +/**
>
> +  This API function locks the interface so that no more pol= icy updates
>
> +  can be performed or changes made to the enforcement until= the next
> boot.
>
> +
>
> +  @retval     EFI_SUCCESS
>
> +  @retval     EFI_NOT_READY  = Library has not yet been initialized.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +LockVariablePolicy (
>
> +  VOID
>
> +  );
>
> +
>
> +
>
> +/**
>
> +  This API function returns whether or not the policy inter= face is locked
>
> +  for the remainder of the boot.
>
> +
>
> +  @retval     TRUE
>
> +  @retval     FALSE
>
> +  @retval     FALSE   &n= bsp;     Library has not yet been initialized.
>
> +
>
> +**/
>
> +BOOLEAN
>
> +EFIAPI
>
> +IsVariablePolicyInterfaceLocked (
>
> +  VOID
>
> +  );
>
> +
>
> +
>
> +/**
>
> +  This helper function initializes the library and sets
>
> +  up any required internal structures or handlers.
>
> +
>
> +  Also registers the internal pointer for the GetVariable h= elper.
>
> +
>
> +  @param[in]  GetVariableHelper A function pointer mat= ching the
> EFI_GET_VARIABLE prototype that will be used to
>
> +          &nbs= p;       check policy criteria that involve t= he existence of other variables.
>
> +
>
> +  @retval     EFI_SUCCESS
>
> +  @retval     EFI_ALREADY_STARTED =   The initialize function has been called
> more than once without a call to
>
> +          &nbs= p;            &= nbsp;            dei= nitialize.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +InitVariablePolicyLib (
>
> +  IN  EFI_GET_VARIABLE    GetVariableHe= lper
>
> +  );
>
> +
>
> +
>
> +/**
>
> +  This helper function returns whether or not the library i= s currently
> initialized.
>
> +
>
> +  @retval     TRUE
>
> +  @retval     FALSE
>
> +
>
> +**/
>
> +BOOLEAN
>
> +EFIAPI
>
> +IsVariablePolicyLibInitialized (
>
> +  VOID
>
> +  );
>
> +
>
> +
>
> +/**
>
> +  This helper function tears down  the library.
>
> +
>
> +  Should generally only be used for test harnesses.
>
> +
>
> +  @retval     EFI_SUCCESS
>
> +  @retval     EFI_NOT_READY  =    Deinitialize was called without first calling
> initialize.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +DeinitVariablePolicyLib (
>
> +  VOID
>
> +  );
>
> +
>
> +
>
> +#endif // _VARIABLE_POLICY_LIB_H_
>
> diff --git a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib= .inf
> b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf
> new file mode 100644
> index 000000000000..f4a879d5382f
> --- /dev/null
> +++ b/MdeModulePkg/Library/VariablePolicyLib/VariablePoli= cyLib.inf
> @@ -0,0 +1,44 @@
> +## @file VariablePolicyLib.inf
>
> +# Business logic for Variable Policy enforcement.
>
> +#
>
> +##
>
> +# Copyright (c) Microsoft Corporation.
>
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +##
>
> +
>
> +
>
> +[Defines]
>
> +  INF_VERSION       &nbs= p; =3D 0x00010017
>
> +  BASE_NAME        =    =3D VariablePolicyLib
>
> +  FILE_GUID        =    =3D E9ECD342-159A-4F24-9FDF-65724027C594
>
> +  VERSION_STRING      =3D 1.0
>
> +  MODULE_TYPE       &nbs= p; =3D DXE_DRIVER
>
> +  LIBRARY_CLASS       =3D Var= iablePolicyLib|DXE_DRIVER DXE_SMM_DRIVER
> MM_STANDALONE
>
> +
>
> +#
>
> +# The following information is for reference only and not requir= ed by the
> build tools.
>
> +#
>
> +#  VALID_ARCHITECTURES      &= nbsp;    =3D ANY
>
> +#
>
> +
>
> +
>
> +[Sources]
>
> +  VariablePolicyLib.c
>
> +  VariablePolicyExtraInitNull.c
>
> +
>
> +
>
> +[Packages]
>
> +  MdePkg/MdePkg.dec
>
> +  MdeModulePkg/MdeModulePkg.dec
>
> +
>
> +
>
> +[LibraryClasses]
>
> +  DebugLib
>
> +  BaseMemoryLib
>
> +  MemoryAllocationLib
>
> +  SafeIntLib
>
> +  PcdLib
>
> +
>
> +
>
> +[Pcd]
>
> +
> gEfiMdeModulePkgTokenSpaceGuid.PcdAllowVariablePolicyEnforcementDis > able     ## CONSUMES
>
> diff --git a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib= .uni
> b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.uni
> new file mode 100644
> index 000000000000..2227ec427828
> --- /dev/null
> +++ b/MdeModulePkg/Library/VariablePolicyLib/VariablePoli= cyLib.uni
> @@ -0,0 +1,12 @@
> +// /** @file
>
> +// VariablePolicyLib.uni
>
> +//
>
> +// Copyright (c) Microsoft Corporation.
>
> +// SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +//
>
> +// **/
>
> +
>
> +
>
> +#string STR_MODULE_ABSTRACT      &= nbsp;      #language en-US "Library containin= g
> the business logic for the VariablePolicy engine"
>
> +
>
> +#string STR_MODULE_DESCRIPTION     &nbs= p;    #language en-US "Library
> containing the business logic for the VariablePolicy engine"
>
> diff --git
> a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.= in
> f
> b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.= in
> f
> new file mode 100644
> index 000000000000..8b8365741864
> --- /dev/null
> +++
> b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.= in
> f
> @@ -0,0 +1,51 @@
> +## @file VariablePolicyLibRuntimeDxe.inf
>
> +# Business logic for Variable Policy enforcement.
>
> +# This instance is specifically for RuntimeDxe and contains
>
> +# extra routines to register for VirtualAddressChangeEvents.
>
> +#
>
> +# Copyright (c) Microsoft Corporation.
>
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +##
>
> +
>
> +
>
> +[Defines]
>
> +  INF_VERSION       &nbs= p; =3D 0x00010017
>
> +  BASE_NAME        =    =3D VariablePolicyLibRuntimeDxe
>
> +  FILE_GUID        =    =3D 205F7F0E-8EAC-4914-8390-1B90DD7E2A27
>
> +  VERSION_STRING      =3D 1.0
>
> +  MODULE_TYPE       &nbs= p; =3D DXE_RUNTIME_DRIVER
>
> +  LIBRARY_CLASS       =3D Var= iablePolicyLib|DXE_RUNTIME_DRIVER
>
> +
>
> +#
>
> +# The following information is for reference only and not requir= ed by the
> build tools.
>
> +#
>
> +#  VALID_ARCHITECTURES      &= nbsp;    =3D ANY
>
> +#
>
> +
>
> +
>
> +[Sources]
>
> +  VariablePolicyLib.c
>
> +  VariablePolicyExtraInitRuntimeDxe.c
>
> +
>
> +
>
> +[Packages]
>
> +  MdePkg/MdePkg.dec
>
> +  MdeModulePkg/MdeModulePkg.dec
>
> +
>
> +
>
> +[LibraryClasses]
>
> +  DebugLib
>
> +  BaseMemoryLib
>
> +  MemoryAllocationLib
>
> +  SafeIntLib
>
> +  UefiBootServicesTableLib
>
> +  UefiRuntimeServicesTableLib
>
> +  PcdLib
>
> +
>
> +
>
> +[Pcd]
>
> +
> gEfiMdeModulePkgTokenSpaceGuid.PcdAllowVariablePolicyEnforcementDis > able     ## CONSUMES
>
> +
>
> +
>
> +[Guids]
>
> +  gEfiEventVirtualAddressChangeGuid
>
> diff --git
> a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/Varia= ble
> PolicyUnitTest.inf
> b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/Varia= ble
> PolicyUnitTest.inf
> new file mode 100644
> index 000000000000..ccc04bb600d6
> --- /dev/null
> +++
> b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/Varia= ble
> PolicyUnitTest.inf
> @@ -0,0 +1,40 @@
> +## @file VariablePolicyUnitTest.inf
>
> +# UnitTest for...
>
> +# Business logic for Variable Policy enforcement.
>
> +#
>
> +# Copyright (c) Microsoft Corporation.
>
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +##
>
> +
>
> +
>
> +[Defines]
>
> +  INF_VERSION       &nbs= p;            =3D 0x= 00010006
>
> +  BASE_NAME        =             &nb= sp; =3D VariablePolicyUnitTest
>
> +  FILE_GUID        =             &nb= sp; =3D 1200A2E4-D756-418C-9768-528C2D181A98
>
> +  MODULE_TYPE       &nbs= p;            =3D HO= ST_APPLICATION
>
> +  VERSION_STRING       &= nbsp;         =3D 1.0
>
> +
>
> +#
>
> +# The following information is for reference only and not requir= ed by the
> build tools.
>
> +#
>
> +#  VALID_ARCHITECTURES      &= nbsp;    =3D IA32 X64 ARM AARCH64
>
> +#
>
> +
>
> +[Sources]
>
> +  VariablePolicyUnitTest.c
>
> +
>
> +
>
> +[Packages]
>
> +  MdePkg/MdePkg.dec
>
> +  MdeModulePkg/MdeModulePkg.dec
>
> +  UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
>
> +
>
> +
>
> +[LibraryClasses]
>
> +  BaseLib
>
> +  DebugLib
>
> +  UnitTestLib
>
> +  PrintLib
>
> +  VariablePolicyLib
>
> +  BaseMemoryLib
>
> +  MemoryAllocationLib
>
> diff --git a/MdeModulePkg/MdeModulePkg.dec
> b/MdeModulePkg/MdeModulePkg.dec
> index 05d8ad4931f9..0b58c14e4747 100644
> --- a/MdeModulePkg/MdeModulePkg.dec
> +++ b/MdeModulePkg/MdeModulePkg.dec
> @@ -31,6 +31,9 @@ [LibraryClasses]
>    ##  @libraryclass  Defines a set of metho= ds to reset whole system.
>
>    ResetSystemLib|Include/Library/ResetSystemLib.h
>
>
>
> +  ##  @libraryclass  Business logic for storing a= nd testing variable policies
>
> +  VariablePolicyLib|Include/Library/VariablePolicyLib.h
>
> +
>
>    ##  @libraryclass  Defines a set of helpe= r functions for resetting the system.
>
>    ResetUtilityLib|Include/Library/ResetUtilityLib.h >
>
>
> diff --git a/MdeModulePkg/MdeModulePkg.dsc
> b/MdeModulePkg/MdeModulePkg.dsc
> index 25aea3e2a481..14b6ed536962 100644
> --- a/MdeModulePkg/MdeModulePkg.dsc
> +++ b/MdeModulePkg/MdeModulePkg.dsc
> @@ -3,6 +3,7 @@
>  #
>
>  # (C) Copyright 2014 Hewlett-Packard Development Company, L.P.&= lt;BR>
>
>  # Copyright (c) 2007 - 2019, Intel Corporation. All rights rese= rved.<BR>
>
> +# Copyright (c) Microsoft Corporation.
>
>  #
>
>  #    SPDX-License-Identifier: BSD-2-Clause-Paten= t
>
>  #
>
> @@ -58,6 +59,7 @@ [LibraryClasses]
>    DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeSer= vicesLib.inf
>
>
> DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTab= l
> eLib.inf
>
>
> UefiBootManagerLib|MdeModulePkg/Library/UefiBootManagerLib/UefiBoo > tManagerLib.inf
>
> +
> VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePoli= cyLi
> b.inf
>
>    #
>
>    # Generic Modules
>
>    #
>
> @@ -129,6 +131,7 @@ [LibraryClasses.common.DXE_RUNTIME_DRIVER] >    DebugLib|MdePkg/Library/UefiDebugLibConOut/UefiDebu= gLibConOut.inf
>
>
> LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxDxeLib.in
> f
>
>
> CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsule > Lib.inf
>
> +
> VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePoli= cyLi
> bRuntimeDxe.inf
>
>
>
>  [LibraryClasses.common.SMM_CORE]
>
>    HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
>
> @@ -306,6 +309,8 @@ [Components]
>    MdeModulePkg/Library/BootLogoLib/BootLogoLib.inf >
>
> MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull
> .inf
>
>    MdeModulePkg/Library/AuthVariableLibNull/AuthVariab= leLibNull.inf
>
> +  MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.= inf
>
> +
> MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.in= f
>
>    MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf >
>    MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLib.= inf
>
>    MdeModulePkg/Library/VarCheckPcdLib/VarCheckPcdLib.= inf
>
> diff --git a/MdeModulePkg/Test/MdeModulePkgHostTest.dsc
> b/MdeModulePkg/Test/MdeModulePkgHostTest.dsc
> index 72a119db4568..095e613f1be1 100644
> --- a/MdeModulePkg/Test/MdeModulePkgHostTest.dsc
> +++ b/MdeModulePkg/Test/MdeModulePkgHostTest.dsc
> @@ -19,12 +19,23 @@ [Defines]
>
>
>  !include UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc<= br> >
>
>
> +[LibraryClasses]
>
> +  SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.i= nf
>
> +
>
>  [Components]
>
>
> MdeModulePkg/Library/DxeResetSystemLib/UnitTest/MockUefiRuntimeSer > vicesTableLib.inf
>
>
>
>    #
>
>    # Build MdeModulePkg HOST_APPLICATION Tests
>
>    #
>
> +
> MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/Variabl= ePo
> licyUnitTest.inf {
>
> +    <LibraryClasses>
>
> +
> VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePoli= cyLi
> b.inf
>
> +
>
> +    <PcdsFixedAtBuild>
>
> +
> gEfiMdeModulePkgTokenSpaceGuid.PcdAllowVariablePolicyEnforcementDis > able|TRUE
>
> +  }
>
> +
>
>
> MdeModulePkg/Library/DxeResetSystemLib/UnitTest/DxeResetSystemLibU > nitTestHost.inf {
>
>      <LibraryClasses>
>
>
> ResetSystemLib|MdeModulePkg/Library/DxeResetSystemLib/DxeResetSyst > emLib.inf
>
> --
> 2.26.2.windows.1.8.g01c50adf56.20200515075929
>
>
> -=3D-=3D-=3D-=3D-=3D-=3D
> Groups.io Links: You receive all messages sent to this group.
>
> View/Reply Online (#61588): https://nam06.safelinks.protection.outlook.com/?url=3Dhttps%3A%2F%2Fedk2.g= roups.io%2Fg%2Fdevel%2Fmessage%2F61588&amp;data=3D02%7C01%7Cbret.barkel= ew%40microsoft.com%7C4ff781c598384282187708d81e2d8858%7C72f988bf86f141af91a= b2d7cd011db47%7C1%7C0%7C637292528218892203&amp;sdata=3DLU1JPSqqPVToubD2= UJd8JT34dvLGJ6QSi7oA7s%2FyiqY%3D&amp;reserved=3D0
> Mute This Topic: https://nam06.safelinks.protection.outlook.com/?url=3Dhttps%3A%2F%2Fgroups= .io%2Fmt%2F75057697%2F1768738&amp;data=3D02%7C01%7Cbret.barkelew%40micr= osoft.com%7C4ff781c598384282187708d81e2d8858%7C72f988bf86f141af91ab2d7cd011= db47%7C1%7C0%7C637292528218892203&amp;sdata=3DY%2BAVPkeX7Clj7g0E0ENKDcJ= QwVksMtp%2FbZjBgDdz%2B1A%3D&amp;reserved=3D0
> Group Owner: devel+owner@edk2.groups.io
> Unsubscribe: https://nam06.safelinks.protection.outlook.com/?url=3Dhttps%3A%2F%2Fedk2.g= roups.io%2Fg%2Fdevel%2Funsub&amp;data=3D02%7C01%7Cbret.barkelew%40micro= soft.com%7C4ff781c598384282187708d81e2d8858%7C72f988bf86f141af91ab2d7cd011d= b47%7C1%7C0%7C637292528218892203&amp;sdata=3DQzd%2FXa8ldydS45UAIyd7PaGO= RBzcESMWbNT1oUNEZm4%3D&amp;reserved=3D0  [dandan.bi@intel.com]
> -=3D-=3D-=3D-=3D-=3D-=3D


 

--_000_CY4PR21MB074399EFFD54FE103EF7B5B8EF6D0CY4PR21MB0743namp_--