From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mga03.intel.com (mga03.intel.com [134.134.136.65]) by mx.groups.io with SMTP id smtpd.web11.3211.1593656016661705518 for ; Wed, 01 Jul 2020 19:13:36 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@intel.onmicrosoft.com header.s=selector2-intel-onmicrosoft-com header.b=l9/cnCgJ; spf=pass (domain: intel.com, ip: 134.134.136.65, mailfrom: dandan.bi@intel.com) IronPort-SDR: cR34qUJ+GC4U61GuX1GO+PLYVU0T1iSs3MrLyPhZriY9r+ByVsPVyxDwBxWHVdQraPETp03bTs wTCQ2X4RhZPA== X-IronPort-AV: E=McAfee;i="6000,8403,9669"; a="146751349" X-IronPort-AV: E=Sophos;i="5.75,302,1589266800"; d="scan'208";a="146751349" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga005.fm.intel.com ([10.253.24.32]) by orsmga103.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 01 Jul 2020 19:13:35 -0700 IronPort-SDR: X4vYm8e10HGK7ZNzkGREVNeOUYp4cZef38pbdkLAu1925iakW6dQVxAo0YRyBdLMbCIx31qGdU 398fKScoGz/Q== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.75,302,1589266800"; d="scan'208";a="481824002" Received: from fmsmsx108.amr.corp.intel.com ([10.18.124.206]) by fmsmga005.fm.intel.com with ESMTP; 01 Jul 2020 19:13:35 -0700 Received: from fmsmsx607.amr.corp.intel.com (10.18.126.87) by FMSMSX108.amr.corp.intel.com (10.18.124.206) with Microsoft SMTP Server (TLS) id 14.3.439.0; Wed, 1 Jul 2020 19:13:34 -0700 Received: from fmsmsx607.amr.corp.intel.com (10.18.126.87) by fmsmsx607.amr.corp.intel.com (10.18.126.87) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.1713.5; Wed, 1 Jul 2020 19:13:33 -0700 Received: from FMSEDG002.ED.cps.intel.com (10.1.192.134) by fmsmsx607.amr.corp.intel.com (10.18.126.87) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) id 15.1.1713.5 via Frontend Transport; Wed, 1 Jul 2020 19:13:33 -0700 Received: from NAM10-MW2-obe.outbound.protection.outlook.com (104.47.55.106) by edgegateway.intel.com (192.55.55.69) with Microsoft SMTP Server (TLS) id 14.3.439.0; Wed, 1 Jul 2020 19:13:33 -0700 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=P56ebE5EawxUKzD7G0EDtpQS3fNNi8tf1f+o++x+h3PFcdviobMn9cwSYyxHL2EZEJP04c/uYolt5rwx2nVUIVMCGSYF1RR+le+zl4TUmk0RZ4cIGOGAgc+HGEQkTdv3HgzsclIrCm/kSr9HUn8Gl3+nRxgpzpwOwIkL+uWDN3DKqUeg+ihZq85IeoxE3mIIkvZpF436tdkaDix9DJZhaZPR2Do9PRmsbuHrxfyxxeBFzZcu7y7Om4wbZB2+3qKvTWRASIxKina+XigXE+Ht++8W+gG6mz0sgrO96ps2UxTw2pmvW5re3DZZh/cQQnP+IjXyxlCD/tyjIcR4idZwFw== 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=A75yAS7LqiktisjIlogvY9jUJIlIyTkY00wtbCwUJBU=; b=Pu/mH9TaTLNqr0PNQQhOhzmInaURWq4YpzC3NFheUyEQwjZ1rKPP1ld5U+WcrbZdlIUI0Uy+4Rvs1tMAMfwGW+OWtNr45hNP414VVOaK58ApKamYIZ67eSkEuWyWCjlKOn/1/FlT+BP99yqUTIgIYfrMEKFQuWmLIt6rC2wXmdIpe+s3q+UafsdhNhtcwKHjFlcwowVH7OmtXXZXhwYEviV7LNbFYewxavTtkyBabdHPuJ+Rr33O1itLerVppZ4OcUht3HkfP0lv0+EE1hTjYrDK3D83cnVfIYxDnW5KXyBouc1vfj7Y5RK2wXI6yosRe1ZWpLJhF37wU6zfg7oe5A== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=intel.com; dmarc=pass action=none header.from=intel.com; dkim=pass header.d=intel.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=intel.onmicrosoft.com; s=selector2-intel-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=A75yAS7LqiktisjIlogvY9jUJIlIyTkY00wtbCwUJBU=; b=l9/cnCgJDAgDcjO8maeR19Og8k42UcrYiXic95gWFCEtNE5qbIOSqwIkg3sHtSKf3JmtfmKNktWfpvn12d3FP1C/CTA/pfGoaHht/Fgy/JutgNPl/8VSJMd4IjDunj+tCNmM828jM1jRGeuEzL4X0HsyZHEq5jGlQjgrgptxkP0= Received: from BN6PR11MB1393.namprd11.prod.outlook.com (2603:10b6:404:3c::12) by BN8PR11MB3812.namprd11.prod.outlook.com (2603:10b6:408:90::11) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3131.21; Thu, 2 Jul 2020 02:13:30 +0000 Received: from BN6PR11MB1393.namprd11.prod.outlook.com ([fe80::a1f4:15d6:9a79:de03]) by BN6PR11MB1393.namprd11.prod.outlook.com ([fe80::a1f4:15d6:9a79:de03%11]) with mapi id 15.20.3153.024; Thu, 2 Jul 2020 02:13:30 +0000 From: "Dandan Bi" To: "devel@edk2.groups.io" , "bret@corthon.com" CC: "Wang, Jian J" , "Wu, Hao A" , "Gao, Liming" 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: AQHWSVAeTDJF11D3LE2NMcwGL3fkh6jybluw Date: Thu, 2 Jul 2020 02:13:30 +0000 Message-ID: References: <20200623064104.1908-1-brbarkel@microsoft.com> <20200623064104.1908-3-brbarkel@microsoft.com> In-Reply-To: <20200623064104.1908-3-brbarkel@microsoft.com> Accept-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: authentication-results: edk2.groups.io; dkim=none (message not signed) header.d=none;edk2.groups.io; dmarc=none action=none header.from=intel.com; x-originating-ip: [192.102.204.38] x-ms-publictraffictype: Email x-ms-office365-filtering-correlation-id: 6930584c-2940-409e-b8c3-08d81e2d83bc x-ms-traffictypediagnostic: BN8PR11MB3812: x-ms-exchange-transport-forked: True x-microsoft-antispam-prvs: x-ms-oob-tlc-oobclassifiers: OLM:10000; x-forefront-prvs: 0452022BE1 x-ms-exchange-senderadcheck: 1 x-microsoft-antispam: BCL:0; x-microsoft-antispam-message-info: o0fBaVONzehoaeRhVzw1W8fECwveMEJ7lOs2GVUwJYMR4DDKkkzJ5upIDqwtQdZxfY3xuvfokwVb4DyBxw+eXp8GYTVJvFCWmg8Et9Z8OfpNLfELuo1o5dVnKXCgX4Gd2fkoVDlLxbNB8gdIxkEGCNENMU0+rGQuJG1u4mFZxp+bqo0hvt9UNXac4CqMmP2YDz1UhV1hw7cxmtEU2mWlAncvI5JINy+F3Kz/xP0LDcvg+mRnixUhUiuJ+THTD7wmQQb0RElpuZQj5dz1xv0eZ5zFK2ymmT1g/+7KlmXFC/606y8WY5VGawMEH0mHE7gJ4aClNOMUSS6AvuXlYaP+XU6My7icqq1XLXzEdboSnUfk4HzuR7tzAWD7bm2dv4NGpkE0bZdNyApzSXzNm8M7hfcs6s7uT7mKGUmREVWz0gL1hXfXMa0ennTZ4Xn9tWhN x-forefront-antispam-report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:BN6PR11MB1393.namprd11.prod.outlook.com;PTR:;CAT:NONE;SFTY:;SFS:(4636009)(366004)(136003)(39860400002)(396003)(346002)(376002)(76116006)(8936002)(316002)(966005)(55016002)(30864003)(110136005)(33656002)(9686003)(4326008)(107886003)(19627235002)(54906003)(8676002)(83380400001)(2906002)(66946007)(45080400002)(66556008)(64756008)(478600001)(66476007)(86362001)(66446008)(71200400001)(53546011)(6506007)(186003)(5660300002)(7696005)(52536014)(26005)(559001)(579004)(569008);DIR:OUT;SFP:1102; x-ms-exchange-antispam-messagedata: biRd0nFPfm+wTgvHw2lgTdV+J0Vr3BzSiibQQ5qj2ny8hExR7OzSN9o+JN9g+uJZqT7Of99F/Y8UeCDHQtrqgrGFEVEUvsfsJ77SYpV5WIp8qax+iuTdxsg3eVU+o0hMaHl2iq44F6lRfphFERiWPgvUnBQpvfiKScwkyG3fmRmzZY+8wFgy0p7iS6FOFxFoX/FWf3Cgecbqkbx2nQ6TskhghHjsSgqPbBC6Vp8tWrcdhnWaMOm/a7UDcxQr/JckEN/PbcuTa2BRnedzKsAl+Dqgf18Gb+Ob0G3tbD9OZ6WssI4FbN4OqVAwm3JI+utQl1zszsoc+yIsuojAgIqvTeHEwahQVS/zJOHtGYt/JvBGdEUOCesapRQG+9bJHmJj6KYAjjn7L27x/k8rNo31Iu7+quRHrCEiemmicg1A9r+M60UcBhE9Lee2IKxBg7/bKY7d2uDHsKcfj1LFgQQITdRm1PI9pOqjlQc7s7HhlRGoK7OuJbm1fHYVIn+0BhAP MIME-Version: 1.0 X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-AuthSource: BN6PR11MB1393.namprd11.prod.outlook.com X-MS-Exchange-CrossTenant-Network-Message-Id: 6930584c-2940-409e-b8c3-08d81e2d83bc X-MS-Exchange-CrossTenant-originalarrivaltime: 02 Jul 2020 02:13:30.3311 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 46c98d88-e344-4ed4-8496-4ed7712e255d X-MS-Exchange-CrossTenant-mailboxtype: HOSTED X-MS-Exchange-CrossTenant-userprincipalname: ix11laClapaEnyI9aqGUbRJQkEXwRH1xKNILWrq7gFKTWKdPA+c28aW2mbDbzyqXIvZ3FASXOXtcOl6FZb+gCQ== X-MS-Exchange-Transport-CrossTenantHeadersStamped: BN8PR11MB3812 Return-Path: dandan.bi@intel.com X-OriginatorOrg: intel.com Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable 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 >=20 > https://bugzilla.tianocore.org/show_bug.cgi?id=3D2522 >=20 > VariablePolicy is an updated interface to > replace VarLock and VarCheckProtocol. >=20 > Add the VariablePolicyLib library that implements > the portable business logic for the VariablePolicy > engine. >=20 > Also add host-based CI test cases for the lib. >=20 > 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 + >=20 > MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitRuntimeDx > e.c | 85 + > MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c > | 816 +++++++ >=20 > 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 + >=20 > 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(+) >=20 > 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 >=20 > +This file contains extra init and deinit routines that don't do anything >=20 > +extra. >=20 > + >=20 > +Copyright (c) Microsoft Corporation. >=20 > +SPDX-License-Identifier: BSD-2-Clause-Patent >=20 > + >=20 > +**/ >=20 > + >=20 > +#include >=20 > + >=20 > + >=20 > +/** >=20 > + An extra init hook that enables the RuntimeDxe library instance to >=20 > + register VirtualAddress change callbacks. Among other things. >=20 > + >=20 > + @retval EFI_SUCCESS Everything is good. Continue with init. >=20 > + @retval Others Uh... don't continue. >=20 > + >=20 > +**/ >=20 > +EFI_STATUS >=20 > +VariablePolicyExtraInit ( >=20 > + VOID >=20 > + ) >=20 > +{ >=20 > + // NULL implementation. >=20 > + return EFI_SUCCESS; >=20 > +} >=20 > + >=20 > + >=20 > +/** >=20 > + An extra deinit hook that enables the RuntimeDxe library instance to >=20 > + register VirtualAddress change callbacks. Among other things. >=20 > + >=20 > + @retval EFI_SUCCESS Everything is good. Continue with deinit. >=20 > + @retval Others Uh... don't continue. >=20 > + >=20 > +**/ >=20 > +EFI_STATUS >=20 > +VariablePolicyExtraDeinit ( >=20 > + VOID >=20 > + ) >=20 > +{ >=20 > + // NULL implementation. >=20 > + return EFI_SUCCESS; >=20 > +} >=20 > 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 >=20 > +This file contains extra init and deinit routines that register and unre= gister >=20 > +VariableAddressChange callbacks. >=20 > + >=20 > +Copyright (c) Microsoft Corporation. >=20 > +SPDX-License-Identifier: BSD-2-Clause-Patent >=20 > + >=20 > +**/ >=20 > + >=20 > +#include >=20 > +#include >=20 > + >=20 > +extern EFI_GET_VARIABLE mGetVariableHelper; >=20 > +extern UINT8 *mPolicyTable; >=20 > +STATIC BOOLEAN mIsVirtualAddrConverted; >=20 > +STATIC EFI_EVENT mVariablePolicyLibVirtualAddressChangeEvent = =3D > NULL; >=20 > + >=20 > +/** >=20 > + For the RuntimeDxe version of this lib, convert internal pointer addre= sses > to virtual addresses. >=20 > + >=20 > + @param[in] Event Event whose notification function is being invok= ed. >=20 > + @param[in] Context The pointer to the notification function's conte= xt, > which >=20 > + is implementation-dependent. >=20 > +**/ >=20 > +STATIC >=20 > +VOID >=20 > +EFIAPI >=20 > +VariablePolicyLibVirtualAddressCallback ( >=20 > + IN EFI_EVENT Event, >=20 > + IN VOID *Context >=20 > + ) >=20 > +{ >=20 > + gRT->ConvertPointer (0, (VOID **)&mPolicyTable); >=20 > + gRT->ConvertPointer (0, (VOID **)&mGetVariableHelper); >=20 > + mIsVirtualAddrConverted =3D TRUE; >=20 > +} >=20 > + >=20 > + >=20 > +/** >=20 > + An extra init hook that enables the RuntimeDxe library instance to >=20 > + register VirtualAddress change callbacks. Among other things. >=20 > + >=20 > + @retval EFI_SUCCESS Everything is good. Continue with init. >=20 > + @retval Others Uh... don't continue. >=20 > + >=20 > +**/ >=20 > +EFI_STATUS >=20 > +VariablePolicyExtraInit ( >=20 > + VOID >=20 > + ) >=20 > +{ >=20 > + return gBS->CreateEventEx (EVT_NOTIFY_SIGNAL, >=20 > + TPL_NOTIFY, >=20 > + VariablePolicyLibVirtualAddressCallback, >=20 > + NULL, >=20 > + &gEfiEventVirtualAddressChangeGuid, >=20 > + &mVariablePolicyLibVirtualAddressChangeEve= nt); >=20 > +} >=20 > + >=20 > + >=20 > +/** >=20 > + An extra deinit hook that enables the RuntimeDxe library instance to >=20 > + register VirtualAddress change callbacks. Among other things. >=20 > + >=20 > + @retval EFI_SUCCESS Everything is good. Continue with deinit. >=20 > + @retval Others Uh... don't continue. >=20 > + >=20 > +**/ >=20 > +EFI_STATUS >=20 > +VariablePolicyExtraDeinit ( >=20 > + VOID >=20 > + ) >=20 > +{ >=20 > + EFI_STATUS Status; >=20 > + >=20 > + Status =3D EFI_SUCCESS; >=20 > + if (mIsVirtualAddrConverted) { >=20 > + Status =3D gBS->CloseEvent > (mVariablePolicyLibVirtualAddressChangeEvent); >=20 > + } >=20 > + else { >=20 > + Status =3D EFI_SUCCESS; >=20 > + } >=20 > + >=20 > + return Status; >=20 > +} >=20 > 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 >=20 > +Business logic for Variable Policy enforcement. >=20 > + >=20 > +Copyright (c) Microsoft Corporation. >=20 > +SPDX-License-Identifier: BSD-2-Clause-Patent >=20 > + >=20 > +**/ >=20 > + >=20 > +#include >=20 > + >=20 > +#include >=20 > +#include >=20 > +#include >=20 > +#include >=20 > +#include >=20 > + >=20 > +#include >=20 > +#include >=20 > + >=20 > + >=20 > +// IMPORTANT NOTE: This library is currently rife with multiple return > statements >=20 > +// for error handling. A refactor should remove these at= some point. >=20 > + >=20 > +// >=20 > +// This library was designed with advanced unit-test features. >=20 > +// This define handles the configuration. >=20 > +#ifdef INTERNAL_UNIT_TEST >=20 > +#undef STATIC >=20 > +#define STATIC // Nothing... >=20 > +#endif >=20 > + >=20 > +// An abstracted GetVariable interface that enables configuration > regardless of the environment. >=20 > +EFI_GET_VARIABLE mGetVariableHelper =3D NULL; >=20 > + >=20 > +// Master switch to lock this entire interface. Does not stop enforcemen= t, >=20 > +// just prevents the configuration from being changed for the rest of th= e > boot. >=20 > +STATIC BOOLEAN mInterfaceLocked =3D FALSE; >=20 > + >=20 > +// Master switch to disable the entire interface for a single boot. >=20 > +// This will disable all policy enforcement for the duration of the boot= . >=20 > +STATIC BOOLEAN mProtectionDisabled =3D FALSE; >=20 > + >=20 > +// Table to hold all the current policies. >=20 > +UINT8 *mPolicyTable =3D NULL; >=20 > +STATIC UINT32 mCurrentTableSize =3D 0; >=20 > +STATIC UINT32 mCurrentTableUsage =3D 0; >=20 > +STATIC UINT32 mCurrentTableCount =3D 0; >=20 > + >=20 > +#define POLICY_TABLE_STEP_SIZE 0x1000 >=20 > + >=20 > +// NOTE: DO NOT USE THESE MACROS on any structure that has not been > validated. >=20 > +// Current table data has already been sanitized. >=20 > +#define GET_NEXT_POLICY(CurPolicy) > (VARIABLE_POLICY_ENTRY*)((UINT8*)CurPolicy + CurPolicy->Size) >=20 > +#define GET_POLICY_NAME(CurPolicy) (CHAR16*)((UINTN)CurPolicy + > CurPolicy->OffsetToName) >=20 > + >=20 > +#define MATCH_PRIORITY_EXACT 0 >=20 > +#define MATCH_PRIORITY_MAX MATCH_PRIORITY_EXACT >=20 > +#define MATCH_PRIORITY_MIN MAX_UINT8 >=20 > + >=20 > +// ExtraInit/ExtraDeinit functions allow RuntimeDxe to register > VirtualAddress callbacks. >=20 > +EFI_STATUS >=20 > +VariablePolicyExtraInit ( >=20 > + VOID >=20 > + ); >=20 > + >=20 > +EFI_STATUS >=20 > +VariablePolicyExtraDeinit ( >=20 > + VOID >=20 > + ); 1. [Dandan]: Please also add comments for above two functions.=20 Please also pay attention to the coding style issue in other files. >=20 > + >=20 > + >=20 > +/** >=20 > + This helper function determines whether the structure of an incoming > policy >=20 > + is valid and internally consistent. >=20 > + >=20 > + @param[in] NewPolicy Pointer to the incoming policy structure. >=20 > + >=20 > + @retval TRUE >=20 > + @retval FALSE Pointer is NULL, size is wrong, strings are empty,= or >=20 > + substructures overlap. >=20 > + >=20 > +**/ >=20 > +STATIC >=20 > +BOOLEAN >=20 > +IsValidVariablePolicyStructure ( >=20 > + IN CONST VARIABLE_POLICY_ENTRY *NewPolicy >=20 > + ) >=20 > +{ >=20 > + EFI_STATUS Status; >=20 > + UINTN EntryEnd; >=20 > + CHAR16 *CheckChar; >=20 > + UINTN WildcardCount; >=20 > + >=20 > + // Sanitize some quick values. >=20 > + if (NewPolicy =3D=3D NULL || NewPolicy->Size =3D=3D 0 || >=20 > + // Structure size should be at least as long as the minumum struct= ure and > a NULL string. >=20 > + NewPolicy->Size < sizeof(VARIABLE_POLICY_ENTRY) || >=20 > + // Check for the known revision. >=20 > + NewPolicy->Version !=3D VARIABLE_POLICY_ENTRY_REVISION) { >=20 > + return FALSE; >=20 > + } >=20 > + >=20 > + // Calculate the theoretical end of the structure and make sure >=20 > + // that the structure can fit in memory. >=20 > + Status =3D SafeUintnAdd( (UINTN)NewPolicy, NewPolicy->Size, &EntryEnd = ); >=20 > + if (EFI_ERROR( Status )) { >=20 > + return FALSE; >=20 > + } >=20 > + >=20 > + // Check for a valid Max Size. >=20 > + if (NewPolicy->MaxSize =3D=3D 0) { >=20 > + return FALSE; >=20 > + } >=20 > + >=20 > + // Check for the valid list of lock policies. >=20 > + if (NewPolicy->LockPolicyType !=3D VARIABLE_POLICY_TYPE_NO_LOCK && >=20 > + NewPolicy->LockPolicyType !=3D VARIABLE_POLICY_TYPE_LOCK_NOW && >=20 > + NewPolicy->LockPolicyType !=3D > VARIABLE_POLICY_TYPE_LOCK_ON_CREATE && >=20 > + NewPolicy->LockPolicyType !=3D > VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE) >=20 > + { >=20 > + return FALSE; >=20 > + } >=20 > + >=20 > + // If the policy type is VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE, > make sure that the matching state variable Name >=20 > + // terminates before the OffsetToName for the matching policy variable > Name. >=20 > + if (NewPolicy->LockPolicyType =3D=3D > VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE) { >=20 > + // Adjust CheckChar to the offset of the LockPolicy->Name. >=20 > + Status =3D SafeUintnAdd( (UINTN)NewPolicy + > sizeof(VARIABLE_POLICY_ENTRY), >=20 > + sizeof(VARIABLE_LOCK_ON_VAR_STATE_POLICY), >=20 > + (UINTN*)&CheckChar ); >=20 > + if (EFI_ERROR( Status ) || EntryEnd <=3D (UINTN)CheckChar) { >=20 > + return FALSE; >=20 > + } >=20 > + while (*CheckChar !=3D CHAR_NULL) { >=20 > + if (EntryEnd <=3D (UINTN)CheckChar) { >=20 > + return FALSE; >=20 > + } >=20 > + CheckChar++; >=20 > + } >=20 > + // At this point we should have either exeeded the structure or be > pointing at the last char in LockPolicy->Name. >=20 > + // We should check to make sure that the policy Name comes > immediately after this charcter. >=20 > + if ((UINTN)++CheckChar !=3D (UINTN)NewPolicy + NewPolicy- > >OffsetToName) { >=20 > + return FALSE; >=20 > + } >=20 > + } >=20 > + // If the policy type is any other value, make sure that the LockPolic= y > structure has a zero length. >=20 > + else { >=20 > + if (NewPolicy->OffsetToName !=3D sizeof(VARIABLE_POLICY_ENTRY)) { >=20 > + return FALSE; >=20 > + } >=20 > + } >=20 > + >=20 > + // Check to make sure that the name has a terminating character >=20 > + // before the end of the structure. >=20 > + // We've already checked that the name is within the bounds of the > structure. >=20 > + if (NewPolicy->Size !=3D NewPolicy->OffsetToName) { >=20 > + CheckChar =3D (CHAR16*)((UINTN)NewPolicy + NewPolicy- > >OffsetToName); >=20 > + WildcardCount =3D 0; >=20 > + while (*CheckChar !=3D CHAR_NULL) { >=20 > + // Make sure there aren't excessive wildcards. >=20 > + if (*CheckChar =3D=3D '#') { >=20 > + WildcardCount++; >=20 > + if (WildcardCount > MATCH_PRIORITY_MIN) { >=20 > + return FALSE; >=20 > + } >=20 > + } >=20 > + // Make sure you're still within the bounds of the policy structur= e. >=20 > + if (EntryEnd <=3D (UINTN)CheckChar) { >=20 > + return FALSE; >=20 > + } >=20 > + CheckChar++; >=20 > + } >=20 > + >=20 > + // Finally, we should be pointed at the very last character in Name,= so we > should be right >=20 > + // up against the end of the structure. >=20 > + if ((UINTN)++CheckChar !=3D EntryEnd) { >=20 > + return FALSE; >=20 > + } >=20 > + } >=20 > + >=20 > + return TRUE; >=20 > +} >=20 > + >=20 > + >=20 > +/** >=20 > + This helper function evaluates a policy and determines whether it matc= hes > the target >=20 > + variable. If matched, will also return a value corresponding to the pr= iority > of the match. >=20 > + >=20 > + The rules for "best match" are listed in the Variable Policy Spec. >=20 > + Perfect name matches will return 0. >=20 > + Single wildcard characters will return the number of wildcard characte= rs. >=20 > + Full namespaces will return MAX_UINT8. >=20 > + >=20 > + @param[in] EvalEntry Pointer to the policy entry being evalua= ted. >=20 > + @param[in] VariableName Same as EFI_SET_VARIABLE. >=20 > + @param[in] VendorGuid Same as EFI_SET_VARIABLE. >=20 > + @param[out] MatchPriority [Optional] On finding a match, this valu= e > contains the priority of the match. >=20 > + Lower number =3D=3D higher priority. Onl= y valid if a match found. >=20 > + >=20 > + @retval TRUE Current entry matches the target variable. >=20 > + @retval FALSE Current entry does not match at all. >=20 > + >=20 > +**/ >=20 > +STATIC >=20 > +BOOLEAN >=20 > +EvaluatePolicyMatch ( >=20 > + IN CONST VARIABLE_POLICY_ENTRY *EvalEntry, >=20 > + IN CONST CHAR16 *VariableName, >=20 > + IN CONST EFI_GUID *VendorGuid, >=20 > + OUT UINT8 *MatchPriority OPTIONAL >=20 > + ) >=20 > +{ >=20 > + BOOLEAN Result; >=20 > + CHAR16 *PolicyName; >=20 > + UINT8 CalculatedPriority; >=20 > + UINTN Index; >=20 > + >=20 > + Result =3D FALSE; >=20 > + CalculatedPriority =3D MATCH_PRIORITY_EXACT; >=20 > + >=20 > + // Step 1: If the GUID doesn't match, we're done. No need to evaluate > anything else. >=20 > + if (!CompareGuid( &EvalEntry->Namespace, VendorGuid )) { >=20 > + goto Exit; >=20 > + } >=20 > + >=20 > + // If the GUID matches, check to see whether there is a Name associate= d >=20 > + // with the policy. If not, this policy matches the entire namespace. >=20 > + // Missing Name is indicated by size being equal to name. >=20 > + if (EvalEntry->Size =3D=3D EvalEntry->OffsetToName) { >=20 > + CalculatedPriority =3D MATCH_PRIORITY_MIN; >=20 > + Result =3D TRUE; >=20 > + goto Exit; >=20 > + } >=20 > + >=20 > + // Now that we know the name exists, get it. >=20 > + PolicyName =3D GET_POLICY_NAME( EvalEntry ); >=20 > + >=20 > + // Evaluate the name against the policy name and check for a match. >=20 > + // Account for any wildcards. >=20 > + Index =3D 0; >=20 > + Result =3D TRUE; >=20 > + // Keep going until the end of both strings. >=20 > + while (PolicyName[Index] !=3D CHAR_NULL || VariableName[Index] !=3D > CHAR_NULL) { >=20 > + // If we don't have a match... >=20 > + if (PolicyName[Index] !=3D VariableName[Index] || PolicyName[Index] = =3D=3D > '#') { >=20 > + // If this is a numerical wildcard, we can consider >=20 > + // it a match if we alter the priority. >=20 > + if (PolicyName[Index] =3D=3D L'#' && >=20 > + (L'0' <=3D VariableName[Index] && VariableName[Index] <=3D L'9= ')) { >=20 > + if (CalculatedPriority < MATCH_PRIORITY_MIN) { >=20 > + CalculatedPriority++; >=20 > + } >=20 > + } >=20 > + // Otherwise, not a match. >=20 > + else { 2. [Dandan]: About the coding style, could we make the" } " and "else {" at= the same line? Which is aligned with current edk2 style. >=20 > + Result =3D FALSE; >=20 > + goto Exit; >=20 > + } >=20 > + } >=20 > + Index++; >=20 > + } >=20 > + >=20 > +Exit: >=20 > + if (Result && MatchPriority !=3D NULL) { >=20 > + *MatchPriority =3D CalculatedPriority; >=20 > + } >=20 > + return Result; >=20 > +} >=20 > + >=20 > + >=20 > +/** >=20 > + This helper function walks the current policy table and returns a poin= ter >=20 > + to the best match, if any are found. Leverages EvaluatePolicyMatch() t= o >=20 > + determine "best". >=20 > + >=20 > + @param[in] VariableName Same as EFI_SET_VARIABLE. >=20 > + @param[in] VendorGuid Same as EFI_SET_VARIABLE. >=20 > + @param[out] ReturnPriority [Optional] If pointer is provided, retu= rn the >=20 > + priority of the match. Same as Evaluate= PolicyMatch(). >=20 > + Only valid if a match is returned. >=20 > + >=20 > + @retval VARIABLE_POLICY_ENTRY* Best match that was found. >=20 > + @retval NULL No match was found. >=20 > + >=20 > +**/ >=20 > +STATIC >=20 > +VARIABLE_POLICY_ENTRY* >=20 > +GetBestPolicyMatch ( >=20 > + IN CONST CHAR16 *VariableName, >=20 > + IN CONST EFI_GUID *VendorGuid, >=20 > + OUT UINT8 *ReturnPriority OPTIONAL >=20 > + ) >=20 > +{ >=20 > + VARIABLE_POLICY_ENTRY *BestResult; >=20 > + VARIABLE_POLICY_ENTRY *CurrentEntry; >=20 > + UINT8 MatchPriority; >=20 > + UINT8 CurrentPriority; >=20 > + UINTN Index; >=20 > + >=20 > + BestResult =3D NULL; >=20 > + >=20 > + // Walk all entries in the table, looking for matches. >=20 > + CurrentEntry =3D (VARIABLE_POLICY_ENTRY*)mPolicyTable; >=20 > + for (Index =3D 0; Index < mCurrentTableCount; Index++) { >=20 > + // Check for a match. >=20 > + if (EvaluatePolicyMatch( CurrentEntry, VariableName, VendorGuid, > &CurrentPriority )) { >=20 > + // If match is better, take it. >=20 > + if (BestResult =3D=3D NULL || CurrentPriority < MatchPriority) { 3. [Dandan]: MatchPriority seems not be initialized but used here. >=20 > + BestResult =3D CurrentEntry; >=20 > + MatchPriority =3D CurrentPriority; >=20 > + } >=20 > + >=20 > + // If you've hit the highest-priority match, can exit now. >=20 > + if (MatchPriority =3D=3D 0) { >=20 > + break; >=20 > + } >=20 > + } >=20 > + >=20 > + // If we're still in the loop, move to the next entry. >=20 > + CurrentEntry =3D GET_NEXT_POLICY( CurrentEntry ); >=20 > + } >=20 > + >=20 > + // If a return priority was requested, return it. >=20 > + if (ReturnPriority !=3D NULL) { >=20 > + *ReturnPriority =3D MatchPriority; >=20 > + } >=20 > + >=20 > + return BestResult; >=20 > +} >=20 > + >=20 > + >=20 > +/** >=20 > + This API function validates and registers a new policy with >=20 > + the policy enforcement engine. >=20 > + >=20 > + @param[in] NewPolicy Pointer to the incoming policy structure. >=20 > + >=20 > + @retval EFI_SUCCESS >=20 > + @retval EFI_INVALID_PARAMETER NewPolicy is NULL or is internally > inconsistent. >=20 > + @retval EFI_ALREADY_STARTED An identical matching policy alrea= dy > exists. >=20 > + @retval EFI_WRITE_PROTECTED The interface has been locked unti= l > the next reboot. >=20 > + @retval EFI_UNSUPPORTED Policy enforcement has been disabl= ed. > No reason to add more policies. >=20 > + @retval EFI_ABORTED A calculation error has prevented = this > function from completing. >=20 > + @retval EFI_OUT_OF_RESOURCES Cannot grow the table to hold any > more policies. >=20 > + @retval EFI_NOT_READY Library has not yet been initializ= ed. >=20 > + >=20 > +**/ >=20 > +EFI_STATUS >=20 > +EFIAPI >=20 > +RegisterVariablePolicy ( >=20 > + IN CONST VARIABLE_POLICY_ENTRY *NewPolicy >=20 > + ) >=20 > +{ >=20 > + EFI_STATUS Status; >=20 > + VARIABLE_POLICY_ENTRY *MatchPolicy; >=20 > + UINT8 MatchPriority; >=20 > + UINT32 NewSize; >=20 > + UINT8 *NewTable; >=20 > + >=20 > + if (!IsVariablePolicyLibInitialized()) { >=20 > + return EFI_NOT_READY; >=20 > + } >=20 > + if (mInterfaceLocked) { >=20 > + return EFI_WRITE_PROTECTED; >=20 > + } >=20 > + >=20 > + if (!IsValidVariablePolicyStructure( NewPolicy )) { >=20 > + return EFI_INVALID_PARAMETER; >=20 > + } >=20 > + >=20 > + // Check to see whether an exact matching policy already exists. >=20 > + MatchPolicy =3D GetBestPolicyMatch( GET_POLICY_NAME( NewPolicy ), >=20 > + &NewPolicy->Namespace, >=20 > + &MatchPriority ); >=20 > + if (MatchPolicy !=3D NULL && MatchPriority =3D=3D MATCH_PRIORITY_EXACT= ) { >=20 > + return EFI_ALREADY_STARTED; >=20 > + } >=20 > + >=20 > + // If none exists, create it. >=20 > + // If we need more space, allocate that now. >=20 > + Status =3D SafeUint32Add( mCurrentTableUsage, NewPolicy->Size, > &NewSize ); >=20 > + if (EFI_ERROR( Status )) { >=20 > + return EFI_ABORTED; >=20 > + } >=20 > + if (NewSize > mCurrentTableSize) { >=20 > + // Use NewSize to calculate the new table size in units of > POLICY_TABLE_STEP_SIZE. >=20 > + NewSize =3D (NewSize % POLICY_TABLE_STEP_SIZE) > 0 ? >=20 > + (NewSize / POLICY_TABLE_STEP_SIZE) + 1 : >=20 > + (NewSize / POLICY_TABLE_STEP_SIZE); >=20 > + // Calculate the new table size in absolute bytes. >=20 > + Status =3D SafeUint32Mult( NewSize, POLICY_TABLE_STEP_SIZE, > &NewSize ); >=20 > + if (EFI_ERROR( Status )) { >=20 > + return EFI_ABORTED; >=20 > + } >=20 > + >=20 > + // Reallocate and copy the table. >=20 > + NewTable =3D AllocatePool( NewSize ); >=20 > + if (NewTable =3D=3D NULL) { >=20 > + return EFI_OUT_OF_RESOURCES; >=20 > + } >=20 > + CopyMem( NewTable, mPolicyTable, mCurrentTableUsage ); >=20 > + mCurrentTableSize =3D NewSize; >=20 > + if (mPolicyTable !=3D NULL) { >=20 > + FreePool( mPolicyTable ); >=20 > + } >=20 > + mPolicyTable =3D NewTable; >=20 > + } >=20 > + // Copy the policy into the table. >=20 > + CopyMem( mPolicyTable + mCurrentTableUsage, NewPolicy, NewPolicy- > >Size ); >=20 > + mCurrentTableUsage +=3D NewPolicy->Size; >=20 > + mCurrentTableCount +=3D 1; >=20 > + >=20 > + // We're done here. >=20 > + >=20 > + return EFI_SUCCESS; >=20 > +} >=20 > + >=20 > + >=20 > +/** >=20 > + This API function checks to see whether the parameters to SetVariable > would >=20 > + be allowed according to the current variable policies. >=20 > + >=20 > + @param[in] VariableName Same as EFI_SET_VARIABLE. >=20 > + @param[in] VendorGuid Same as EFI_SET_VARIABLE. >=20 > + @param[in] Attributes Same as EFI_SET_VARIABLE. >=20 > + @param[in] DataSize Same as EFI_SET_VARIABLE. >=20 > + @param[in] Data Same as EFI_SET_VARIABLE. >=20 > + >=20 > + @retval EFI_SUCCESS A matching policy allows this upda= te. >=20 > + @retval EFI_SUCCESS There are currently no policies th= at restrict > this update. >=20 > + @retval EFI_SUCCESS The protections have been disable = until the > next reboot. >=20 > + @retval EFI_WRITE_PROTECTED Variable is currently locked. >=20 > + @retval EFI_INVALID_PARAMETER Attributes or size are invalid. >=20 > + @retval EFI_ABORTED A lock policy exists, but an error= prevented > evaluation. >=20 > + @retval EFI_NOT_READY Library has not been initialized. >=20 > + >=20 > +**/ >=20 > +EFI_STATUS >=20 > +EFIAPI >=20 > +ValidateSetVariable ( >=20 > + IN CHAR16 *VariableName, >=20 > + IN EFI_GUID *VendorGuid, >=20 > + IN UINT32 Attributes, >=20 > + IN UINTN DataSize, >=20 > + IN VOID *Data >=20 > + ) >=20 > +{ >=20 > + BOOLEAN IsDel; >=20 > + VARIABLE_POLICY_ENTRY *ActivePolicy; >=20 > + EFI_STATUS Status; >=20 > + EFI_STATUS ReturnStatus; >=20 > + VARIABLE_LOCK_ON_VAR_STATE_POLICY *StateVarPolicy; >=20 > + CHAR16 *StateVarName; >=20 > + UINTN StateVarSize; >=20 > + UINT8 StateVar; >=20 > + >=20 > + ReturnStatus =3D EFI_SUCCESS; >=20 > + >=20 > + if (!IsVariablePolicyLibInitialized()) { >=20 > + ReturnStatus =3D EFI_NOT_READY; >=20 > + goto Exit; >=20 > + } >=20 > + >=20 > + // Bail if the protections are currently disabled. >=20 > + if (mProtectionDisabled) { >=20 > + ReturnStatus =3D EFI_SUCCESS; >=20 > + goto Exit; >=20 > + } >=20 > + >=20 > + // Determine whether this is a delete operation. >=20 > + // If so, it will affect which tests are applied. >=20 > + if ((DataSize =3D=3D 0) && ((Attributes & EFI_VARIABLE_APPEND_WRITE) = =3D=3D 0)) > { >=20 > + IsDel =3D TRUE; >=20 > + } >=20 > + else { >=20 > + IsDel =3D FALSE; >=20 > + } >=20 > + >=20 > + // Find an active policy if one exists. >=20 > + ActivePolicy =3D GetBestPolicyMatch( VariableName, VendorGuid, NULL ); >=20 > + >=20 > + // If we have an active policy, check it against the incoming data. >=20 > + if (ActivePolicy !=3D NULL) { >=20 > + // >=20 > + // Only enforce size and attribute constraints when updating data, n= ot > deleting. >=20 > + if (!IsDel) { >=20 > + // Check for size constraints. >=20 > + if ((ActivePolicy->MinSize > 0 && DataSize < ActivePolicy->MinSize= ) || >=20 > + (ActivePolicy->MaxSize > 0 && DataSize > ActivePolicy->MaxSize= )) { >=20 > + ReturnStatus =3D EFI_INVALID_PARAMETER; >=20 > + DEBUG(( DEBUG_VERBOSE, "%a - Bad Size. 0x%X <> 0x%X-0x%X\n", > __FUNCTION__, >=20 > + DataSize, ActivePolicy->MinSize, ActivePolicy->MaxSize )= ); >=20 > + goto Exit; >=20 > + } >=20 > + >=20 > + // Check for attribute constraints. >=20 > + if ((ActivePolicy->AttributesMustHave & Attributes) !=3D ActivePol= icy- > >AttributesMustHave || >=20 > + (ActivePolicy->AttributesCantHave & Attributes) !=3D 0) { >=20 > + ReturnStatus =3D EFI_INVALID_PARAMETER; >=20 > + DEBUG(( DEBUG_VERBOSE, "%a - Bad Attributes. 0x%X <> > 0x%X:0x%X\n", __FUNCTION__, >=20 > + Attributes, ActivePolicy->AttributesMustHave, ActivePoli= cy- > >AttributesCantHave )); >=20 > + goto Exit; >=20 > + } >=20 > + } >=20 > + >=20 > + // >=20 > + // Lock policy check. >=20 > + // >=20 > + // Check for immediate lock. >=20 > + if (ActivePolicy->LockPolicyType =3D=3D VARIABLE_POLICY_TYPE_LOCK_NO= W) > { >=20 > + ReturnStatus =3D EFI_WRITE_PROTECTED; >=20 > + goto Exit; >=20 > + } >=20 > + // Check for lock on create. >=20 > + else if (ActivePolicy->LockPolicyType =3D=3D > VARIABLE_POLICY_TYPE_LOCK_ON_CREATE) { >=20 > + StateVarSize =3D 0; >=20 > + Status =3D mGetVariableHelper( VariableName, >=20 > + VendorGuid, >=20 > + NULL, >=20 > + &StateVarSize, >=20 > + NULL ); >=20 > + if (Status =3D=3D EFI_BUFFER_TOO_SMALL) { >=20 > + ReturnStatus =3D EFI_WRITE_PROTECTED; >=20 > + goto Exit; >=20 > + } >=20 > + } >=20 > + // Check for lock on state variable. >=20 > + else if (ActivePolicy->LockPolicyType =3D=3D > VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE) { >=20 > + StateVarPolicy =3D > (VARIABLE_LOCK_ON_VAR_STATE_POLICY*)((UINT8*)ActivePolicy + > sizeof(VARIABLE_POLICY_ENTRY)); >=20 > + StateVarName =3D (CHAR16*)((UINT8*)StateVarPolicy + > sizeof(VARIABLE_LOCK_ON_VAR_STATE_POLICY)); >=20 > + StateVarSize =3D sizeof(StateVar); >=20 > + Status =3D mGetVariableHelper( StateVarName, >=20 > + &StateVarPolicy->Namespace, >=20 > + NULL, >=20 > + &StateVarSize, >=20 > + &StateVar ); >=20 > + >=20 > + // If the variable was found, check the state. If matched, this va= riable is > locked. >=20 > + if (!EFI_ERROR( Status )) { >=20 > + if (StateVar =3D=3D StateVarPolicy->Value) { >=20 > + ReturnStatus =3D EFI_WRITE_PROTECTED; >=20 > + goto Exit; >=20 > + } >=20 > + } >=20 > + // EFI_NOT_FOUND and EFI_BUFFER_TOO_SMALL indicate that the > state doesn't match. >=20 > + else if (Status !=3D EFI_NOT_FOUND && Status !=3D > EFI_BUFFER_TOO_SMALL) { >=20 > + // We don't know what happened, but it isn't good. >=20 > + ReturnStatus =3D EFI_ABORTED; >=20 > + goto Exit; >=20 > + } >=20 > + } >=20 > + } >=20 > + >=20 > +Exit: >=20 > + DEBUG(( DEBUG_VERBOSE, "%a - Variable (%g:%s) returning %r.\n", > __FUNCTION__, VendorGuid, VariableName, ReturnStatus )); >=20 > + return ReturnStatus; >=20 > +} >=20 > + >=20 > + >=20 > +/** >=20 > + This API function disables the variable policy enforcement. If it's >=20 > + already been called once, will return EFI_ALREADY_STARTED. >=20 > + >=20 > + @retval EFI_SUCCESS >=20 > + @retval EFI_ALREADY_STARTED Has already been called once this bo= ot. >=20 > + @retval EFI_WRITE_PROTECTED Interface has been locked until rebo= ot. >=20 > + @retval EFI_WRITE_PROTECTED Interface option is disabled by plat= form > PCD. >=20 > + @retval EFI_NOT_READY Library has not yet been initialized= . >=20 > + >=20 > +**/ >=20 > +EFI_STATUS >=20 > +EFIAPI >=20 > +DisableVariablePolicy ( >=20 > + VOID >=20 > + ) >=20 > +{ >=20 > + if (!IsVariablePolicyLibInitialized()) { >=20 > + return EFI_NOT_READY; >=20 > + } >=20 > + if (mProtectionDisabled) { >=20 > + return EFI_ALREADY_STARTED; >=20 > + } >=20 > + if (mInterfaceLocked) { >=20 > + return EFI_WRITE_PROTECTED; >=20 > + } >=20 > + if (!PcdGetBool (PcdAllowVariablePolicyEnforcementDisable)) { >=20 > + return EFI_WRITE_PROTECTED; >=20 > + } >=20 > + mProtectionDisabled =3D TRUE; >=20 > + return EFI_SUCCESS; >=20 > +} >=20 > + >=20 > + >=20 > +/** >=20 > + This API function will dump the entire contents of the variable policy= table. >=20 > + >=20 > + Similar to GetVariable, the first call can be made with a 0 size and i= t will > return >=20 > + the size of the buffer required to hold the entire table. >=20 > + >=20 > + @param[out] Policy Pointer to the policy buffer. Can be NULL if S= ize is 0. >=20 > + @param[in,out] Size On input, the size of the output buffer. On ou= tput, > the size >=20 > + of the data returned. >=20 > + >=20 > + @retval EFI_SUCCESS Policy data is in the output buffe= r and Size > has been updated. >=20 > + @retval EFI_INVALID_PARAMETER Size is NULL, or Size is non-zero = and > Policy is NULL. >=20 > + @retval EFI_BUFFER_TOO_SMALL Size is insufficient to hold polic= y. Size > updated with required size. >=20 > + @retval EFI_NOT_READY Library has not yet been initializ= ed. >=20 > + >=20 > +**/ >=20 > +EFI_STATUS >=20 > +EFIAPI >=20 > +DumpVariablePolicy ( >=20 > + OUT UINT8 *Policy, >=20 > + IN OUT UINT32 *Size >=20 > + ) >=20 > +{ >=20 > + if (!IsVariablePolicyLibInitialized()) { >=20 > + return EFI_NOT_READY; >=20 > + } >=20 > + >=20 > + // Check the parameters. >=20 > + if (Size =3D=3D NULL || (*Size > 0 && Policy =3D=3D NULL)) { >=20 > + return EFI_INVALID_PARAMETER; >=20 > + } >=20 > + >=20 > + // Make sure the size is sufficient to hold the policy table. >=20 > + if (*Size < mCurrentTableUsage) { >=20 > + *Size =3D mCurrentTableUsage; >=20 > + return EFI_BUFFER_TOO_SMALL; >=20 > + } >=20 > + >=20 > + // If we're still here, copy the table and bounce. >=20 > + CopyMem( Policy, mPolicyTable, mCurrentTableUsage ); >=20 > + *Size =3D mCurrentTableUsage; >=20 > + >=20 > + return EFI_SUCCESS; >=20 > +} >=20 > + >=20 > + >=20 > +/** >=20 > + This API function returns whether or not the policy engine is >=20 > + currently being enforced. >=20 > + >=20 > + @retval TRUE >=20 > + @retval FALSE >=20 > + @retval FALSE Library has not yet been initialized. >=20 > + >=20 > +**/ >=20 > +BOOLEAN >=20 > +EFIAPI >=20 > +IsVariablePolicyEnabled ( >=20 > + VOID >=20 > + ) >=20 > +{ >=20 > + if (!IsVariablePolicyLibInitialized()) { >=20 > + return FALSE; >=20 > + } >=20 > + return !mProtectionDisabled; >=20 > +} >=20 > + >=20 > + >=20 > +/** >=20 > + This API function locks the interface so that no more policy updates >=20 > + can be performed or changes made to the enforcement until the next > boot. >=20 > + >=20 > + @retval EFI_SUCCESS >=20 > + @retval EFI_NOT_READY Library has not yet been initialized. >=20 > + >=20 > +**/ >=20 > +EFI_STATUS >=20 > +EFIAPI >=20 > +LockVariablePolicy ( >=20 > + VOID >=20 > + ) >=20 > +{ >=20 > + if (!IsVariablePolicyLibInitialized()) { >=20 > + return EFI_NOT_READY; >=20 > + } >=20 > + if (mInterfaceLocked) { >=20 > + return EFI_WRITE_PROTECTED; >=20 > + } >=20 > + mInterfaceLocked =3D TRUE; >=20 > + return EFI_SUCCESS; >=20 > +} >=20 > + >=20 > + >=20 > +/** >=20 > + This API function returns whether or not the policy interface is locke= d >=20 > + for the remainder of the boot. >=20 > + >=20 > + @retval TRUE >=20 > + @retval FALSE >=20 > + @retval FALSE Library has not yet been initialized. >=20 > + >=20 > +**/ >=20 > +BOOLEAN >=20 > +EFIAPI >=20 > +IsVariablePolicyInterfaceLocked ( >=20 > + VOID >=20 > + ) >=20 > +{ >=20 > + if (!IsVariablePolicyLibInitialized()) { >=20 > + return FALSE; >=20 > + } >=20 > + return mInterfaceLocked; >=20 > +} >=20 > + >=20 > + >=20 > +/** >=20 > + This helper function initializes the library and sets >=20 > + up any required internal structures or handlers. >=20 > + >=20 > + Also registers the internal pointer for the GetVariable helper. >=20 > + >=20 > + @param[in] GetVariableHelper A function pointer matching the > EFI_GET_VARIABLE prototype that will be used to >=20 > + check policy criteria that involve the existence of ot= her variables. >=20 > + >=20 > + @retval EFI_SUCCESS >=20 > + @retval EFI_ALREADY_STARTED The initialize function has been cal= led > more than once without a call to >=20 > + deinitialize. >=20 > + >=20 > +**/ >=20 > +EFI_STATUS >=20 > +EFIAPI >=20 > +InitVariablePolicyLib ( >=20 > + IN EFI_GET_VARIABLE GetVariableHelper >=20 > + ) >=20 > +{ >=20 > + EFI_STATUS Status; >=20 > + >=20 > + Status =3D EFI_SUCCESS; >=20 > + if (mGetVariableHelper !=3D NULL) { >=20 > + Status =3D EFI_ALREADY_STARTED; 4. [Dandan]: Could we return directly here? >=20 > + } >=20 > + >=20 > + if (!EFI_ERROR( Status )) { >=20 > + Status =3D VariablePolicyExtraInit(); >=20 > + } >=20 > + >=20 > + if (!EFI_ERROR( Status )) { >=20 > + // Save an internal pointer to the GetVariableHelper. >=20 > + mGetVariableHelper =3D GetVariableHelper; >=20 > + >=20 > + // Initialize the global state. >=20 > + mInterfaceLocked =3D FALSE; >=20 > + mProtectionDisabled =3D FALSE; >=20 > + mPolicyTable =3D NULL; >=20 > + mCurrentTableSize =3D 0; >=20 > + mCurrentTableUsage =3D 0; >=20 > + mCurrentTableCount =3D 0; >=20 > + } >=20 > + >=20 > + return Status; >=20 > +} >=20 > + >=20 > + >=20 > +/** >=20 > + This helper function returns whether or not the library is currently > initialized. >=20 > + >=20 > + @retval TRUE >=20 > + @retval FALSE >=20 > + >=20 > +**/ >=20 > +BOOLEAN >=20 > +EFIAPI >=20 > +IsVariablePolicyLibInitialized ( >=20 > + VOID >=20 > + ) >=20 > +{ >=20 > + return (mGetVariableHelper !=3D NULL); >=20 > +} >=20 > + >=20 > + >=20 > +/** >=20 > + This helper function tears down the library. >=20 > + >=20 > + Should generally only be used for test harnesses. >=20 > + >=20 > + @retval EFI_SUCCESS >=20 > + @retval EFI_NOT_READY Deinitialize was called without first ca= lling > initialize. >=20 > + >=20 > +**/ >=20 > +EFI_STATUS >=20 > +EFIAPI >=20 > +DeinitVariablePolicyLib ( >=20 > + VOID >=20 > + ) >=20 > +{ >=20 > + EFI_STATUS Status; >=20 > + >=20 > + Status =3D EFI_SUCCESS; >=20 > + >=20 > + if (mGetVariableHelper =3D=3D NULL) { >=20 > + Status =3D EFI_NOT_READY; >=20 > + } >=20 > + >=20 > + if (!EFI_ERROR( Status )) { >=20 > + Status =3D VariablePolicyExtraDeinit(); >=20 > + } >=20 > + >=20 > + if (!EFI_ERROR( Status )) { >=20 > + mGetVariableHelper =3D NULL; >=20 > + mInterfaceLocked =3D FALSE; >=20 > + mProtectionDisabled =3D FALSE; >=20 > + mCurrentTableSize =3D 0; >=20 > + mCurrentTableUsage =3D 0; >=20 > + mCurrentTableCount =3D 0; >=20 > + >=20 > + if (mPolicyTable !=3D NULL) { >=20 > + FreePool( mPolicyTable ); >=20 > + mPolicyTable =3D NULL; >=20 > + } >=20 > + } >=20 > + >=20 > + return Status; >=20 > +} >=20 > 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 >=20 > +UnitTest for... >=20 > +Business logic for Variable Policy enforcement. >=20 > + >=20 > +Copyright (c) Microsoft Corporation. >=20 > +SPDX-License-Identifier: BSD-2-Clause-Patent >=20 > + >=20 > +**/ >=20 > + >=20 > +#include >=20 > +#include >=20 > +#include >=20 > +#include >=20 > +#include >=20 > +#include >=20 > + >=20 > +#include >=20 > +#include >=20 > +#include >=20 > +#include >=20 > +#include >=20 > +#include >=20 > +#include >=20 > + >=20 > +#include >=20 > + >=20 > +#include >=20 > +#include >=20 > + >=20 > +// MU_CHANGE - Turn this off for now. Try to turn it back on with extra > build options. >=20 > +// #ifndef INTERNAL_UNIT_TEST >=20 > +// #error Make sure to build thie with INTERNAL_UNIT_TEST enabled! > Otherwise, some important tests may be skipped! >=20 > +// #endif >=20 > + >=20 > + >=20 > +#define UNIT_TEST_NAME "UEFI Variable Policy UnitTest" >=20 > +#define UNIT_TEST_VERSION "0.5" >=20 > + >=20 > +///=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 >=20 > + >=20 > +#pragma pack(push, 1) >=20 > +typedef struct _SIMPLE_VARIABLE_POLICY_ENTRY { >=20 > + VARIABLE_POLICY_ENTRY Header; >=20 > + CHAR16 Name[]; >=20 > +} SIMPLE_VARIABLE_POLICY_ENTRY; >=20 > +#define EXPANDED_VARIABLE_POLICY_ENTRY_VAR_NAME_LENGTH 1001 > // 1000 characters + terminator. >=20 > +#define EXPANDED_VARIABLE_POLICY_ENTRY_VAR_NAME_SIZE > (EXPANDED_VARIABLE_POLICY_ENTRY_VAR_NAME_LENGTH * > sizeof(CHAR16)) >=20 > +typedef struct _EXPANDED_VARIABLE_POLICY_ENTRY { >=20 > + VARIABLE_POLICY_ENTRY Header; >=20 > + VARIABLE_LOCK_ON_VAR_STATE_POLICY StatePolicy; >=20 > + CHAR16 > StateName[EXPANDED_VARIABLE_POLICY_ENTRY_VAR_NAME_LENGTH]; >=20 > + CHAR16 > Name[EXPANDED_VARIABLE_POLICY_ENTRY_VAR_NAME_LENGTH]; >=20 > +} EXPANDED_VARIABLE_POLICY_ENTRY; >=20 > +#pragma pack(pop) >=20 > + >=20 > +// {F955BA2D-4A2C-480C-BFD1-3CC522610592} >=20 > +#define TEST_GUID_1 { 0xf955ba2d, 0x4a2c, 0x480c, { 0xbf, 0xd1, 0x3c, 0x= c5, > 0x22, 0x61, 0x5, 0x92 } } >=20 > +EFI_GUID mTestGuid1 =3D TEST_GUID_1; >=20 > +// {2DEA799E-5E73-43B9-870E-C945CE82AF3A} >=20 > +#define TEST_GUID_2 { 0x2dea799e, 0x5e73, 0x43b9, { 0x87, 0xe, 0xc9, 0x4= 5, > 0xce, 0x82, 0xaf, 0x3a } } >=20 > +EFI_GUID mTestGuid2 =3D TEST_GUID_2; >=20 > +// {698A2BFD-A616-482D-B88C-7100BD6682A9} >=20 > +#define TEST_GUID_3 { 0x698a2bfd, 0xa616, 0x482d, { 0xb8, 0x8c, 0x71, 0x= 0, > 0xbd, 0x66, 0x82, 0xa9 } } >=20 > +EFI_GUID mTestGuid3 =3D TEST_GUID_3; >=20 > + >=20 > +#define TEST_VAR_1_NAME L"TestVar1" >=20 > +#define TEST_VAR_2_NAME L"TestVar2" >=20 > +#define TEST_VAR_3_NAME L"TestVar3" >=20 > + >=20 > +#define TEST_POLICY_ATTRIBUTES_NULL 0 >=20 > +#define TEST_POLICY_MIN_SIZE_NULL 0 >=20 > +#define TEST_POLICY_MAX_SIZE_NULL MAX_UINT32 >=20 > + >=20 > +#define TEST_POLICY_MIN_SIZE_10 10 >=20 > +#define TEST_POLICY_MAX_SIZE_200 200 >=20 > + >=20 > +#define TEST_300_HASHES_STRING > L"##################################################"\ >=20 > + > "##################################################"\ >=20 > + > "##################################################"\ >=20 > + > "##################################################"\ >=20 > + > "##################################################"\ >=20 > + > "##################################################" >=20 > + >=20 > + >=20 > +///=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 >=20 > + >=20 > +/** >=20 > + Helper function to initialize a VARIABLE_POLICY_ENTRY structure with a > Name and StateName. >=20 > + >=20 > + Takes care of all the messy packing. >=20 > + >=20 > + @param[in,out] Entry >=20 > + @param[in] Name [Optional] >=20 > + @param[in] StateName [Optional] >=20 > + >=20 > + @retval TRUE >=20 > + @retval FALSE >=20 > + >=20 > +**/ >=20 > +STATIC >=20 > +BOOLEAN >=20 > +InitExpVarPolicyStrings ( >=20 > + EXPANDED_VARIABLE_POLICY_ENTRY *Entry, >=20 > + CHAR16 *Name, OPTIONAL >=20 > + CHAR16 *StateName OPTIONAL >=20 > + ) >=20 > +{ >=20 > + UINTN NameSize; >=20 > + UINTN StateNameSize; >=20 > + >=20 > + NameSize =3D Name =3D=3D NULL ? 0 : StrSize( Name ); >=20 > + StateNameSize =3D StateName =3D=3D NULL ? 0 : StrSize( StateName ); >=20 > + >=20 > + if (NameSize > EXPANDED_VARIABLE_POLICY_ENTRY_VAR_NAME_SIZE || > NameSize > MAX_UINT16 || >=20 > + StateNameSize > > EXPANDED_VARIABLE_POLICY_ENTRY_VAR_NAME_SIZE || StateNameSize > > MAX_UINT16) { >=20 > + return FALSE; >=20 > + } >=20 > + >=20 > + Entry->Header.OffsetToName =3D sizeof(VARIABLE_POLICY_ENTRY); >=20 > + if (StateName !=3D NULL) { >=20 > + Entry->Header.OffsetToName +=3D > (UINT16)sizeof(VARIABLE_LOCK_ON_VAR_STATE_POLICY) + > (UINT16)StateNameSize; >=20 > + } >=20 > + Entry->Header.Size =3D Entry->Header.OffsetToName + (UINT16)NameSize; >=20 > + >=20 > + CopyMem( (UINT8*)Entry + Entry->Header.OffsetToName, Name, > NameSize ); >=20 > + if (StateName !=3D NULL) { >=20 > + CopyMem( (UINT8*)Entry + sizeof(VARIABLE_POLICY_ENTRY) + > sizeof(VARIABLE_LOCK_ON_VAR_STATE_POLICY), StateName, > StateNameSize ); >=20 > + } >=20 > + >=20 > + return TRUE; >=20 > +} >=20 > + >=20 > +/** >=20 > + Mocked version of GetVariable, for testing. >=20 > +**/ >=20 > +EFI_STATUS >=20 > +EFIAPI >=20 > +StubGetVariableNull ( >=20 > + IN CHAR16 *VariableName, >=20 > + IN EFI_GUID *VendorGuid, >=20 > + OUT UINT32 *Attributes, OPTIONAL >=20 > + IN OUT UINTN *DataSize, >=20 > + OUT VOID *Data OPTIONAL >=20 > + ) >=20 > +{ >=20 > + UINT32 MockedAttr; >=20 > + UINTN MockedDataSize; >=20 > + VOID *MockedData; >=20 > + EFI_STATUS MockedReturn; >=20 > + >=20 > + check_expected_ptr( VariableName ); >=20 > + check_expected_ptr( VendorGuid ); >=20 > + check_expected_ptr( DataSize ); >=20 > + >=20 > + MockedAttr =3D (UINT32)mock(); >=20 > + MockedDataSize =3D (UINTN)mock(); >=20 > + MockedData =3D (VOID*)mock(); >=20 > + MockedReturn =3D (EFI_STATUS)mock(); >=20 > + >=20 > + if (Attributes !=3D NULL) { >=20 > + *Attributes =3D MockedAttr; >=20 > + } >=20 > + if (Data !=3D NULL && !EFI_ERROR(MockedReturn)) { >=20 > + CopyMem( Data, MockedData, MockedDataSize ); >=20 > + } >=20 > + >=20 > + *DataSize =3D MockedDataSize; >=20 > + >=20 > + return MockedReturn; >=20 > +} >=20 > + >=20 > +// >=20 > +// Anything you think might be helpful that isn't a test itself. >=20 > +// >=20 > + >=20 > +/** >=20 > + This is a common setup function that will ensure the library is always > initialized >=20 > + with the stubbed GetVariable. >=20 > + >=20 > + Not used by all test cases, but by most. >=20 > +**/ >=20 > +STATIC >=20 > +UNIT_TEST_STATUS >=20 > +LibInitMocked ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + return EFI_ERROR(InitVariablePolicyLib( StubGetVariableNull )) ? > UNIT_TEST_ERROR_PREREQUISITE_NOT_MET : UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Common cleanup function to make sure that the library is always de- > initialized prior >=20 > + to the next test case. >=20 > +*/ >=20 > +STATIC >=20 > +VOID >=20 > +LibCleanup ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + DeinitVariablePolicyLib(); >=20 > +} >=20 > + >=20 > + >=20 > +///=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 >=20 > + >=20 > +///=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 >=20 > + >=20 > +/** >=20 > + Test Case >=20 > +*/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +ShouldBeAbleToInitAndDeinitTheLibrary ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + EFI_STATUS Status; >=20 > + Status =3D InitVariablePolicyLib( StubGetVariableNull ); >=20 > + UT_ASSERT_NOT_EFI_ERROR( Status ); >=20 > + >=20 > + UT_ASSERT_TRUE( IsVariablePolicyLibInitialized() ); >=20 > + >=20 > + Status =3D DeinitVariablePolicyLib(); >=20 > + UT_ASSERT_NOT_EFI_ERROR( Status ); >=20 > + >=20 > + UT_ASSERT_FALSE( IsVariablePolicyLibInitialized() ); >=20 > + >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Test Case >=20 > +*/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +ShouldNotBeAbleToInitializeTheLibraryTwice ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + EFI_STATUS Status; >=20 > + Status =3D InitVariablePolicyLib( StubGetVariableNull ); >=20 > + UT_ASSERT_NOT_EFI_ERROR( Status ); >=20 > + Status =3D InitVariablePolicyLib( StubGetVariableNull ); >=20 > + UT_ASSERT_TRUE( EFI_ERROR( Status ) ); >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Test Case >=20 > +*/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +ShouldFailDeinitWithoutInit ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + EFI_STATUS Status; >=20 > + Status =3D DeinitVariablePolicyLib(); >=20 > + UT_ASSERT_TRUE( EFI_ERROR( Status ) ); >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Test Case >=20 > +*/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +ApiCommandsShouldNotRespondIfLibIsUninitialized ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + SIMPLE_VARIABLE_POLICY_ENTRY TestPolicy =3D { >=20 > + { >=20 > + VARIABLE_POLICY_ENTRY_REVISION, >=20 > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME), >=20 > + sizeof(VARIABLE_POLICY_ENTRY), >=20 > + TEST_GUID_1, >=20 > + TEST_POLICY_MIN_SIZE_NULL, >=20 > + TEST_POLICY_MAX_SIZE_NULL, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + VARIABLE_POLICY_TYPE_NO_LOCK >=20 > + }, >=20 > + TEST_VAR_1_NAME >=20 > + }; >=20 > + UINT8 DummyData[8]; >=20 > + UINT32 DummyDataSize =3D sizeof(DummyData); >=20 > + >=20 > + // This test should not start with an initialized library. >=20 > + >=20 > + // Verify that all API commands fail. >=20 > + UT_ASSERT_TRUE( EFI_ERROR( LockVariablePolicy() ) ); >=20 > + UT_ASSERT_TRUE( EFI_ERROR( DisableVariablePolicy() ) ); >=20 > + > UT_ASSERT_TRUE( EFI_ERROR( RegisterVariablePolicy( &TestPolicy.Header ) > ) ); >=20 > + UT_ASSERT_TRUE( EFI_ERROR( DumpVariablePolicy( DummyData, > &DummyDataSize ) ) ); >=20 > + UT_ASSERT_FALSE( IsVariablePolicyInterfaceLocked() ); >=20 > + UT_ASSERT_FALSE( IsVariablePolicyEnabled() ); >=20 > + UT_ASSERT_TRUE( EFI_ERROR( ValidateSetVariable( TEST_VAR_1_NAME, >=20 > + &mTestGuid1, >=20 > + VARIABLE_ATTRIBUTE_NV_B= S, >=20 > + sizeof(DummyData), >=20 > + DummyData ) ) ); >=20 > + >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > + >=20 > +///=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 >=20 > + >=20 > +#ifdef INTERNAL_UNIT_TEST >=20 > + >=20 > +BOOLEAN >=20 > +EvaluatePolicyMatch ( >=20 > + IN CONST VARIABLE_POLICY_ENTRY *EvalEntry, >=20 > + IN CONST CHAR16 *VariableName, >=20 > + IN CONST EFI_GUID *VendorGuid, >=20 > + OUT UINT8 *MatchPriority OPTIONAL >=20 > + ); >=20 > + >=20 > +/** >=20 > + Test Case >=20 > +*/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +PoliciesShouldMatchByNameAndGuid ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + SIMPLE_VARIABLE_POLICY_ENTRY MatchCheckPolicy =3D { >=20 > + { >=20 > + VARIABLE_POLICY_ENTRY_REVISION, >=20 > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME), >=20 > + sizeof(VARIABLE_POLICY_ENTRY), >=20 > + TEST_GUID_1, >=20 > + TEST_POLICY_MIN_SIZE_NULL, >=20 > + TEST_POLICY_MAX_SIZE_NULL, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + VARIABLE_POLICY_TYPE_NO_LOCK >=20 > + }, >=20 > + TEST_VAR_1_NAME >=20 > + }; >=20 > + CHAR16 *CheckVar1Name =3D TEST_VAR_1_NAME; >=20 > + CHAR16 *CheckVar2Name =3D TEST_VAR_2_NAME; >=20 > + >=20 > + // Make sure that a different name does not match. >=20 > + UT_ASSERT_FALSE( EvaluatePolicyMatch( &MatchCheckPolicy.Header, > CheckVar2Name, &mTestGuid1, NULL ) ); >=20 > + >=20 > + // Make sure that a different GUID does not match. >=20 > + UT_ASSERT_FALSE( EvaluatePolicyMatch( &MatchCheckPolicy.Header, > CheckVar1Name, &mTestGuid2, NULL ) ); >=20 > + >=20 > + // Make sure that the same name and GUID match. >=20 > + UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolicy.Header, > CheckVar1Name, &mTestGuid1, NULL ) ); >=20 > + >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Test Case >=20 > +*/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +WildcardPoliciesShouldMatchDigits ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + SIMPLE_VARIABLE_POLICY_ENTRY MatchCheckPolicy =3D { >=20 > + { >=20 > + VARIABLE_POLICY_ENTRY_REVISION, >=20 > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(L"Wildcard#VarName##"), >=20 > + sizeof(VARIABLE_POLICY_ENTRY), >=20 > + TEST_GUID_1, >=20 > + TEST_POLICY_MIN_SIZE_NULL, >=20 > + TEST_POLICY_MAX_SIZE_NULL, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + VARIABLE_POLICY_TYPE_NO_LOCK >=20 > + }, >=20 > + L"Wildcard#VarName##" >=20 > + }; >=20 > + CHAR16 *CheckVar1Name =3D L"Wildcard1VarName12"; >=20 > + CHAR16 *CheckVar2Name =3D L"Wildcard2VarName34"; >=20 > + CHAR16 *CheckVarBName =3D L"WildcardBVarName56"; >=20 > + CHAR16 *CheckVarHName =3D L"Wildcard#VarName56"; >=20 > + >=20 > + // Make sure that two different sets of wildcard numbers match. >=20 > + UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolicy.Header, > CheckVar1Name, &mTestGuid1, NULL ) ); >=20 > + UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolicy.Header, > CheckVar2Name, &mTestGuid1, NULL ) ); >=20 > + >=20 > + // Make sure that the non-number charaters don't match. >=20 > + UT_ASSERT_FALSE( EvaluatePolicyMatch( &MatchCheckPolicy.Header, > CheckVarBName, &mTestGuid1, NULL ) ); >=20 > + >=20 > + // Make sure that '#' signs don't match. >=20 > + UT_ASSERT_FALSE( EvaluatePolicyMatch( &MatchCheckPolicy.Header, > CheckVarHName, &mTestGuid1, NULL ) ); >=20 > + >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Test Case >=20 > +*/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +WildcardPoliciesShouldMatchDigitsAdvanced ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + SIMPLE_VARIABLE_POLICY_ENTRY MatchCheckPolicy =3D { >=20 > + { >=20 > + VARIABLE_POLICY_ENTRY_REVISION, >=20 > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_300_HASHES_STRING), >=20 > + sizeof(VARIABLE_POLICY_ENTRY), >=20 > + TEST_GUID_1, >=20 > + TEST_POLICY_MIN_SIZE_NULL, >=20 > + TEST_POLICY_MAX_SIZE_NULL, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + VARIABLE_POLICY_TYPE_NO_LOCK >=20 > + }, >=20 > + TEST_300_HASHES_STRING >=20 > + }; >=20 > + CHAR16 *CheckShorterString =3D > L"01234567890123456789012345678901234567890123456789"; >=20 > + CHAR16 *CheckValidString =3D > L"01234567890123456789012345678901234567890123456789"\ >=20 > + > "01234567890123456789012345678901234567890123456789"\ >=20 > + > "01234567890123456789012345678901234567890123456789"\ >=20 > + > "01234567890123456789012345678901234567890123456789"\ >=20 > + > "01234567890123456789012345678901234567890123456789"\ >=20 > + > "01234567890123456789012345678901234567890123456789"; >=20 > + CHAR16 *CheckLongerString =3D > L"01234567890123456789012345678901234567890123456789"\ >=20 > + > "01234567890123456789012345678901234567890123456789"\ >=20 > + > "01234567890123456789012345678901234567890123456789"\ >=20 > + > "01234567890123456789012345678901234567890123456789"\ >=20 > + > "01234567890123456789012345678901234567890123456789"\ >=20 > + > "01234567890123456789012345678901234567890123456789"\ >=20 > + > "01234567890123456789012345678901234567890123456789"; >=20 > + UINT8 MatchPriority; >=20 > + >=20 > + // Make sure that the shorter and the longer do not match. >=20 > + UT_ASSERT_FALSE( EvaluatePolicyMatch( &MatchCheckPolicy.Header, > CheckShorterString, &mTestGuid1, NULL ) ); >=20 > + UT_ASSERT_FALSE( EvaluatePolicyMatch( &MatchCheckPolicy.Header, > CheckLongerString, &mTestGuid1, NULL ) ); >=20 > + >=20 > + // Make sure that the valid one matches and has the expected priority. >=20 > + UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolicy.Header, > CheckValidString, &mTestGuid1, &MatchPriority ) ); >=20 > + UT_ASSERT_EQUAL( MatchPriority, MAX_UINT8 ); >=20 > + >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Test Case >=20 > +*/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +WildcardPoliciesShouldMatchNamespaces ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + VARIABLE_POLICY_ENTRY MatchCheckPolicy =3D { >=20 > + VARIABLE_POLICY_ENTRY_REVISION, >=20 > + sizeof(VARIABLE_POLICY_ENTRY), >=20 > + sizeof(VARIABLE_POLICY_ENTRY), >=20 > + TEST_GUID_1, >=20 > + TEST_POLICY_MIN_SIZE_NULL, >=20 > + TEST_POLICY_MAX_SIZE_NULL, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + VARIABLE_POLICY_TYPE_NO_LOCK >=20 > + }; >=20 > + CHAR16 *CheckVar1Name =3D L"Wildcard1VarName12"; >=20 > + CHAR16 *CheckVar2Name =3D L"Wildcard2VarName34"; >=20 > + CHAR16 *CheckVarBName =3D L"WildcardBVarName56"; >=20 > + CHAR16 *CheckVarHName =3D L"Wildcard#VarName56"; >=20 > + >=20 > + // Make sure that all names in the same namespace match. >=20 > + UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolicy, > CheckVar1Name, &mTestGuid1, NULL ) ); >=20 > + UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolicy, > CheckVar2Name, &mTestGuid1, NULL ) ); >=20 > + UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolicy, > CheckVarBName, &mTestGuid1, NULL ) ); >=20 > + UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolicy, > CheckVarHName, &mTestGuid1, NULL ) ); >=20 > + >=20 > + // Make sure that different namespace doesn't match. >=20 > + UT_ASSERT_FALSE( EvaluatePolicyMatch( &MatchCheckPolicy, > CheckVar1Name, &mTestGuid2, NULL ) ); >=20 > + >=20 > + >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Test Case >=20 > +*/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +MatchPrioritiesShouldFollowRules ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + SIMPLE_VARIABLE_POLICY_ENTRY MatchCheckPolicy =3D { >=20 > + { >=20 > + VARIABLE_POLICY_ENTRY_REVISION, >=20 > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(L"Wildcard1VarName12"), >=20 > + sizeof(VARIABLE_POLICY_ENTRY), >=20 > + TEST_GUID_1, >=20 > + TEST_POLICY_MIN_SIZE_NULL, >=20 > + TEST_POLICY_MAX_SIZE_NULL, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + VARIABLE_POLICY_TYPE_NO_LOCK >=20 > + }, >=20 > + L"Wildcard1VarName12" >=20 > + }; >=20 > + CHAR16 CheckVar1Name[] =3D L"Wildcard1VarName12"; >=20 > + CHAR16 MatchVar1Name[] =3D L"Wildcard1VarName12"; >=20 > + CHAR16 MatchVar2Name[] =3D L"Wildcard#VarName12"; >=20 > + CHAR16 MatchVar3Name[] =3D L"Wildcard#VarName#2"; >=20 > + CHAR16 MatchVar4Name[] =3D L"Wildcard#VarName##"; >=20 > + UINT8 MatchPriority; >=20 > + >=20 > + // Check with a perfect match. >=20 > + CopyMem( &MatchCheckPolicy.Name, MatchVar1Name, > sizeof(MatchVar1Name) ); >=20 > + UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolicy.Header, > CheckVar1Name, &mTestGuid1, &MatchPriority ) ); >=20 > + UT_ASSERT_EQUAL( MatchPriority, 0 ); >=20 > + >=20 > + // Check with progressively lower priority matches. >=20 > + CopyMem( &MatchCheckPolicy.Name, MatchVar2Name, > sizeof(MatchVar2Name) ); >=20 > + UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolicy.Header, > CheckVar1Name, &mTestGuid1, &MatchPriority ) ); >=20 > + UT_ASSERT_EQUAL( MatchPriority, 1 ); >=20 > + CopyMem( &MatchCheckPolicy.Name, MatchVar3Name, > sizeof(MatchVar3Name) ); >=20 > + UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolicy.Header, > CheckVar1Name, &mTestGuid1, &MatchPriority ) ); >=20 > + UT_ASSERT_EQUAL( MatchPriority, 2 ); >=20 > + CopyMem( &MatchCheckPolicy.Name, MatchVar4Name, > sizeof(MatchVar4Name) ); >=20 > + UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolicy.Header, > CheckVar1Name, &mTestGuid1, &MatchPriority ) ); >=20 > + UT_ASSERT_EQUAL( MatchPriority, 3 ); >=20 > + >=20 > + // Check against the entire namespace. >=20 > + MatchCheckPolicy.Header.Size =3D sizeof(VARIABLE_POLICY_ENTRY); >=20 > + UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolicy.Header, > CheckVar1Name, &mTestGuid1, &MatchPriority ) ); >=20 > + UT_ASSERT_EQUAL( MatchPriority, MAX_UINT8 ); >=20 > + >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +#endif // INTERNAL_UNIT_TEST >=20 > + >=20 > + >=20 > +///=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 >=20 > + >=20 > +/** >=20 > + Test Case >=20 > +*/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +RegisterShouldAllowNamespaceWildcards ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + SIMPLE_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { >=20 > + { >=20 > + VARIABLE_POLICY_ENTRY_REVISION, >=20 > + sizeof(VARIABLE_POLICY_ENTRY), >=20 > + sizeof(VARIABLE_POLICY_ENTRY), >=20 > + TEST_GUID_1, >=20 > + TEST_POLICY_MIN_SIZE_NULL, >=20 > + TEST_POLICY_MAX_SIZE_NULL, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + VARIABLE_POLICY_TYPE_NO_LOCK >=20 > + }, >=20 > + L"" >=20 > + }; >=20 > + >=20 > + > UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea > der ) ); >=20 > + >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Test Case >=20 > +*/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +RegisterShouldAllowStateVarsForNamespaces ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + EXPANDED_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { >=20 > + { >=20 > + VARIABLE_POLICY_ENTRY_REVISION, >=20 > + 0, // Will be populated by init helper. >=20 > + 0, // Will be populated by init helper. >=20 > + TEST_GUID_1, >=20 > + TEST_POLICY_MIN_SIZE_NULL, >=20 > + TEST_POLICY_MAX_SIZE_NULL, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE >=20 > + }, >=20 > + { >=20 > + TEST_GUID_2, >=20 > + 1, // Value >=20 > + 0 // Padding >=20 > + }, >=20 > + L"", >=20 > + L"" >=20 > + }; >=20 > + UT_ASSERT_TRUE( InitExpVarPolicyStrings( &ValidationPolicy, NULL, > TEST_VAR_2_NAME ) ); >=20 > + >=20 > + > UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea > der ) ); >=20 > + >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Test Case >=20 > +*/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +RegisterShouldRejectNullPointers ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + UT_ASSERT_EQUAL( RegisterVariablePolicy( NULL ), > EFI_INVALID_PARAMETER ); >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Test Case >=20 > +*/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +RegisterShouldRejectBadRevisions ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + SIMPLE_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { >=20 > + { >=20 > + VARIABLE_POLICY_ENTRY_REVISION, >=20 > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME), >=20 > + sizeof(VARIABLE_POLICY_ENTRY), >=20 > + TEST_GUID_1, >=20 > + TEST_POLICY_MIN_SIZE_NULL, >=20 > + TEST_POLICY_MAX_SIZE_NULL, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + VARIABLE_POLICY_TYPE_NO_LOCK >=20 > + }, >=20 > + TEST_VAR_1_NAME >=20 > + }; >=20 > + >=20 > + ValidationPolicy.Header.Version =3D MAX_UINT32; >=20 > + UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), > EFI_INVALID_PARAMETER ); >=20 > + >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Test Case >=20 > +*/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +RegisterShouldRejectBadSizes ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + SIMPLE_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { >=20 > + { >=20 > + VARIABLE_POLICY_ENTRY_REVISION, >=20 > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME), >=20 > + sizeof(VARIABLE_POLICY_ENTRY), >=20 > + TEST_GUID_1, >=20 > + TEST_POLICY_MIN_SIZE_NULL, >=20 > + TEST_POLICY_MAX_SIZE_NULL, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + VARIABLE_POLICY_TYPE_NO_LOCK >=20 > + }, >=20 > + TEST_VAR_1_NAME >=20 > + }; >=20 > + >=20 > + ValidationPolicy.Header.Size =3D sizeof(VARIABLE_POLICY_ENTRY) - 2; >=20 > + UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), > EFI_INVALID_PARAMETER ); >=20 > + >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Test Case >=20 > +*/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +RegisterShouldRejectBadOffsets ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + EXPANDED_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { >=20 > + { >=20 > + VARIABLE_POLICY_ENTRY_REVISION, >=20 > + 0, // Will be populated by init helper. >=20 > + 0, // Will be populated by init helper. >=20 > + TEST_GUID_1, >=20 > + TEST_POLICY_MIN_SIZE_NULL, >=20 > + TEST_POLICY_MAX_SIZE_NULL, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE >=20 > + }, >=20 > + { >=20 > + TEST_GUID_2, >=20 > + 1, // Value >=20 > + 0 // Padding >=20 > + }, >=20 > + L"", >=20 > + L"" >=20 > + }; >=20 > + UT_ASSERT_TRUE( InitExpVarPolicyStrings( &ValidationPolicy, > TEST_VAR_1_NAME, TEST_VAR_2_NAME ) ); >=20 > + >=20 > + // Check for an offset outside the size bounds. >=20 > + ValidationPolicy.Header.OffsetToName =3D ValidationPolicy.Header.Size = + 1; >=20 > + UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), > EFI_INVALID_PARAMETER ); >=20 > + >=20 > + // Check for an offset inside the policy header. >=20 > + ValidationPolicy.Header.OffsetToName =3D sizeof(VARIABLE_POLICY_ENTRY) > - 2; >=20 > + UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), > EFI_INVALID_PARAMETER ); >=20 > + >=20 > + // Check for an offset inside the state policy header. >=20 > + ValidationPolicy.Header.OffsetToName =3D sizeof(VARIABLE_POLICY_ENTRY) > + 2; >=20 > + UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), > EFI_INVALID_PARAMETER ); >=20 > + >=20 > + // Check for a ridiculous offset. >=20 > + ValidationPolicy.Header.OffsetToName =3D MAX_UINT16; >=20 > + UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), > EFI_INVALID_PARAMETER ); >=20 > + >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Test Case >=20 > +*/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +RegisterShouldRejectMissingStateStrings ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + EXPANDED_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { >=20 > + { >=20 > + VARIABLE_POLICY_ENTRY_REVISION, >=20 > + 0, // Will be populated by init helper. >=20 > + 0, // Will be populated by init helper. >=20 > + TEST_GUID_1, >=20 > + TEST_POLICY_MIN_SIZE_NULL, >=20 > + TEST_POLICY_MAX_SIZE_NULL, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE >=20 > + }, >=20 > + { >=20 > + TEST_GUID_2, >=20 > + 1, // Value >=20 > + 0 // Padding >=20 > + }, >=20 > + L"", >=20 > + L"" >=20 > + }; >=20 > + UT_ASSERT_TRUE( InitExpVarPolicyStrings( &ValidationPolicy, > TEST_VAR_1_NAME, TEST_VAR_2_NAME ) ); >=20 > + >=20 > + // Remove the state string and copy the Name into it's place. >=20 > + // Also adjust the offset. >=20 > + ValidationPolicy.Header.Size =3D sizeof(VARIABLE_POLICY_ENTRY= ) + > sizeof(VARIABLE_LOCK_ON_VAR_STATE_POLICY) + > sizeof(TEST_VAR_1_NAME); >=20 > + ValidationPolicy.Header.OffsetToName =3D sizeof(VARIABLE_POLICY_ENTRY= ) > + sizeof(VARIABLE_LOCK_ON_VAR_STATE_POLICY); >=20 > + CopyMem( (UINT8*)&ValidationPolicy + > ValidationPolicy.Header.OffsetToName, TEST_VAR_1_NAME, > sizeof(TEST_VAR_1_NAME) ); >=20 > + >=20 > + // Make sure that this structure fails. >=20 > + UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), > EFI_INVALID_PARAMETER ); >=20 > + >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Test Case >=20 > +*/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +RegisterShouldRejectStringsMissingNull ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + EXPANDED_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { >=20 > + { >=20 > + VARIABLE_POLICY_ENTRY_REVISION, >=20 > + 0, // Will be populated by init helper. >=20 > + 0, // Will be populated by init helper. >=20 > + TEST_GUID_1, >=20 > + TEST_POLICY_MIN_SIZE_NULL, >=20 > + TEST_POLICY_MAX_SIZE_NULL, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE >=20 > + }, >=20 > + { >=20 > + TEST_GUID_2, >=20 > + 1, // Value >=20 > + 0 // Padding >=20 > + }, >=20 > + L"", >=20 > + L"" >=20 > + }; >=20 > + UT_ASSERT_TRUE( InitExpVarPolicyStrings( &ValidationPolicy, > TEST_VAR_1_NAME, TEST_VAR_2_NAME ) ); >=20 > + >=20 > + // Removing the NULL from the Name should fail. >=20 > + ValidationPolicy.Header.Size =3D ValidationPolicy.Header.Size - > sizeof(CHAR16); >=20 > + UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), > EFI_INVALID_PARAMETER ); >=20 > + >=20 > + // Removing the NULL from the State Name is a little trickier. >=20 > + // Copy the Name up one byte. >=20 > + ValidationPolicy.Header.OffsetToName =3D > ValidationPolicy.Header.OffsetToName - sizeof(CHAR16); >=20 > + CopyMem( (UINT8*)&ValidationPolicy + > ValidationPolicy.Header.OffsetToName, TEST_VAR_1_NAME, > sizeof(TEST_VAR_1_NAME) ); >=20 > + UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), > EFI_INVALID_PARAMETER ); >=20 > + >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Test Case >=20 > +*/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +RegisterShouldRejectMalformedStrings ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + EXPANDED_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { >=20 > + { >=20 > + VARIABLE_POLICY_ENTRY_REVISION, >=20 > + 0, // Will be populated by init helper. >=20 > + 0, // Will be populated by init helper. >=20 > + TEST_GUID_1, >=20 > + TEST_POLICY_MIN_SIZE_NULL, >=20 > + TEST_POLICY_MAX_SIZE_NULL, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE >=20 > + }, >=20 > + { >=20 > + TEST_GUID_2, >=20 > + 1, // Value >=20 > + 0 // Padding >=20 > + }, >=20 > + L"", >=20 > + L"" >=20 > + }; >=20 > + UT_ASSERT_TRUE( InitExpVarPolicyStrings( &ValidationPolicy, > TEST_VAR_1_NAME, TEST_VAR_2_NAME ) ); >=20 > + >=20 > + // Bisecting the NULL from the Name should fail. >=20 > + ValidationPolicy.Header.Size =3D ValidationPolicy.Header.Size - 1; >=20 > + UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), > EFI_INVALID_PARAMETER ); >=20 > + >=20 > + // Bisecting the NULL from the State Name is a little trickier. >=20 > + // Copy the Name up one byte. >=20 > + ValidationPolicy.Header.OffsetToName =3D > ValidationPolicy.Header.OffsetToName - 1; >=20 > + CopyMem( (UINT8*)&ValidationPolicy + > ValidationPolicy.Header.OffsetToName, TEST_VAR_1_NAME, > sizeof(TEST_VAR_1_NAME) ); >=20 > + UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), > EFI_INVALID_PARAMETER ); >=20 > + >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Test Case >=20 > +*/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +RegisterShouldRejectUnpackedPolicies ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + EXPANDED_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { >=20 > + { >=20 > + VARIABLE_POLICY_ENTRY_REVISION, >=20 > + 0, // Will be populated by init helper. >=20 > + 0, // Will be populated by init helper. >=20 > + TEST_GUID_1, >=20 > + TEST_POLICY_MIN_SIZE_NULL, >=20 > + TEST_POLICY_MAX_SIZE_NULL, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE >=20 > + }, >=20 > + { >=20 > + TEST_GUID_2, >=20 > + 1, // Value >=20 > + 0 // Padding >=20 > + }, >=20 > + L"", >=20 > + L"" >=20 > + }; >=20 > + UT_ASSERT_TRUE( InitExpVarPolicyStrings( &ValidationPolicy, > TEST_VAR_1_NAME, TEST_VAR_2_NAME ) ); >=20 > + >=20 > + // Increase the size and move the Name out a bit. >=20 > + ValidationPolicy.Header.Size =3D ValidationPolicy.Header.Size + > sizeof(CHAR16); >=20 > + ValidationPolicy.Header.OffsetToName =3D > ValidationPolicy.Header.OffsetToName + sizeof(CHAR16); >=20 > + CopyMem( (UINT8*)&ValidationPolicy + > ValidationPolicy.Header.OffsetToName, TEST_VAR_1_NAME, > sizeof(TEST_VAR_1_NAME) ); >=20 > + UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), > EFI_INVALID_PARAMETER ); >=20 > + >=20 > + // Reintialize without the state policy and try the same test. >=20 > + ValidationPolicy.Header.LockPolicyType =3D > VARIABLE_POLICY_TYPE_NO_LOCK; >=20 > + UT_ASSERT_TRUE( InitExpVarPolicyStrings( &ValidationPolicy, > TEST_VAR_1_NAME, NULL ) ); >=20 > + ValidationPolicy.Header.Size =3D ValidationPolicy.Header.Size + > sizeof(CHAR16); >=20 > + ValidationPolicy.Header.OffsetToName =3D > ValidationPolicy.Header.OffsetToName + sizeof(CHAR16); >=20 > + CopyMem( (UINT8*)&ValidationPolicy + > ValidationPolicy.Header.OffsetToName, TEST_VAR_1_NAME, > sizeof(TEST_VAR_1_NAME) ); >=20 > + UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), > EFI_INVALID_PARAMETER ); >=20 > + >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Test Case >=20 > +*/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +RegisterShouldRejectInvalidNameCharacters ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + // EXPANDED_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { >=20 > + // { >=20 > + // VARIABLE_POLICY_ENTRY_REVISION, >=20 > + // 0, // Will be populated by init helper. >=20 > + // 0, // Will be populated by init helper. >=20 > + // TEST_GUID_1, >=20 > + // TEST_POLICY_MIN_SIZE_NULL, >=20 > + // TEST_POLICY_MAX_SIZE_NULL, >=20 > + // TEST_POLICY_ATTRIBUTES_NULL, >=20 > + // TEST_POLICY_ATTRIBUTES_NULL, >=20 > + // VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE >=20 > + // }, >=20 > + // { >=20 > + // TEST_GUID_2, >=20 > + // 1, // Value >=20 > + // 0 // Padding >=20 > + // }, >=20 > + // L"", >=20 > + // L"" >=20 > + // }; >=20 > + >=20 > + // Currently, there are no known invalid characters. >=20 > + // '#' in LockPolicy->Name are taken as literal. >=20 > + >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Test Case >=20 > +*/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +RegisterShouldRejectBadPolicyConstraints ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + SIMPLE_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { >=20 > + { >=20 > + VARIABLE_POLICY_ENTRY_REVISION, >=20 > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME), >=20 > + sizeof(VARIABLE_POLICY_ENTRY), >=20 > + TEST_GUID_1, >=20 > + TEST_POLICY_MIN_SIZE_NULL, >=20 > + TEST_POLICY_MAX_SIZE_NULL, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + VARIABLE_POLICY_TYPE_NO_LOCK >=20 > + }, >=20 > + TEST_VAR_1_NAME >=20 > + }; >=20 > + >=20 > + // Make sure that invalid MAXes are rejected. >=20 > + ValidationPolicy.Header.MaxSize =3D 0; >=20 > + UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), > EFI_INVALID_PARAMETER ); >=20 > + >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Test Case >=20 > +*/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +RegisterShouldRejectUnknownLockPolicies ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + SIMPLE_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { >=20 > + { >=20 > + VARIABLE_POLICY_ENTRY_REVISION, >=20 > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME), >=20 > + sizeof(VARIABLE_POLICY_ENTRY), >=20 > + TEST_GUID_1, >=20 > + TEST_POLICY_MIN_SIZE_NULL, >=20 > + TEST_POLICY_MAX_SIZE_NULL, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + VARIABLE_POLICY_TYPE_NO_LOCK >=20 > + }, >=20 > + TEST_VAR_1_NAME >=20 > + }; >=20 > + >=20 > + ValidationPolicy.Header.LockPolicyType =3D > VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE + 1; >=20 > + UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), > EFI_INVALID_PARAMETER ); >=20 > + ValidationPolicy.Header.LockPolicyType =3D > VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE + 1; >=20 > + UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), > EFI_INVALID_PARAMETER ); >=20 > + >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Test Case >=20 > +*/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +RegisterShouldRejectPolicesWithTooManyWildcards ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + SIMPLE_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { >=20 > + { >=20 > + VARIABLE_POLICY_ENTRY_REVISION, >=20 > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_300_HASHES_STRING), >=20 > + sizeof(VARIABLE_POLICY_ENTRY), >=20 > + TEST_GUID_1, >=20 > + TEST_POLICY_MIN_SIZE_NULL, >=20 > + TEST_POLICY_MAX_SIZE_NULL, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + VARIABLE_POLICY_TYPE_NO_LOCK >=20 > + }, >=20 > + TEST_300_HASHES_STRING >=20 > + }; >=20 > + >=20 > + // 300 Hashes is currently larger than the possible maximum match prio= rity. >=20 > + UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), > EFI_INVALID_PARAMETER ); >=20 > + >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Test Case >=20 > +*/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +RegisterShouldRejectDuplicatePolicies ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + SIMPLE_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { >=20 > + { >=20 > + VARIABLE_POLICY_ENTRY_REVISION, >=20 > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME), >=20 > + sizeof(VARIABLE_POLICY_ENTRY), >=20 > + TEST_GUID_1, >=20 > + TEST_POLICY_MIN_SIZE_NULL, >=20 > + TEST_POLICY_MAX_SIZE_NULL, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + VARIABLE_POLICY_TYPE_NO_LOCK >=20 > + }, >=20 > + TEST_VAR_1_NAME >=20 > + }; >=20 > + >=20 > + > UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea > der ) ); >=20 > + > UT_ASSERT_STATUS_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Head > er ), EFI_ALREADY_STARTED ); >=20 > + >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Test Case >=20 > +*/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +MinAndMaxSizePoliciesShouldBeHonored ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + SIMPLE_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { >=20 > + { >=20 > + VARIABLE_POLICY_ENTRY_REVISION, >=20 > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME), >=20 > + sizeof(VARIABLE_POLICY_ENTRY), >=20 > + TEST_GUID_1, >=20 > + TEST_POLICY_MIN_SIZE_10, >=20 > + TEST_POLICY_MAX_SIZE_200, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + VARIABLE_POLICY_TYPE_NO_LOCK >=20 > + }, >=20 > + TEST_VAR_1_NAME >=20 > + }; >=20 > + EFI_STATUS PolicyCheck; >=20 > + UINT8 DummyData[TEST_POLICY_MAX_SIZE_200+1]; >=20 > + >=20 > + >=20 > + // Without a policy, there should be no constraints on variable creati= on. >=20 > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, >=20 > + &mTestGuid1, >=20 > + VARIABLE_ATTRIBUTE_NV_BS, >=20 > + TEST_POLICY_MAX_SIZE_200+1, >=20 > + DummyData ); >=20 > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); >=20 > + >=20 > + // Set a policy to test against. >=20 > + > UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea > der ) ); >=20 > + >=20 > + // With a policy, make sure that sizes outsize the target range fail. >=20 > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, >=20 > + &mTestGuid1, >=20 > + VARIABLE_ATTRIBUTE_NV_BS, >=20 > + TEST_POLICY_MAX_SIZE_200+1, >=20 > + DummyData ); >=20 > + UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) ); >=20 > + >=20 > + // With a policy, make sure that sizes outsize the target range fail. >=20 > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, >=20 > + &mTestGuid1, >=20 > + VARIABLE_ATTRIBUTE_NV_BS, >=20 > + TEST_POLICY_MIN_SIZE_10-1, >=20 > + DummyData ); >=20 > + UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) ); >=20 > + >=20 > + // With a policy, make sure a valid variable is still valid. >=20 > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, >=20 > + &mTestGuid1, >=20 > + VARIABLE_ATTRIBUTE_NV_BS, >=20 > + TEST_POLICY_MIN_SIZE_10+1, >=20 > + DummyData ); >=20 > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); >=20 > + >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Test Case >=20 > +*/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +AttributeMustPoliciesShouldBeHonored ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + SIMPLE_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { >=20 > + { >=20 > + VARIABLE_POLICY_ENTRY_REVISION, >=20 > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME), >=20 > + sizeof(VARIABLE_POLICY_ENTRY), >=20 > + TEST_GUID_1, >=20 > + TEST_POLICY_MIN_SIZE_NULL, >=20 > + TEST_POLICY_MAX_SIZE_NULL, >=20 > + VARIABLE_ATTRIBUTE_NV_BS_RT, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + VARIABLE_POLICY_TYPE_NO_LOCK >=20 > + }, >=20 > + TEST_VAR_1_NAME >=20 > + }; >=20 > + EFI_STATUS PolicyCheck; >=20 > + UINT8 DummyData[12]; >=20 > + >=20 > + >=20 > + // Without a policy, there should be no constraints on variable creati= on. >=20 > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, >=20 > + &mTestGuid1, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + sizeof(DummyData), >=20 > + DummyData ); >=20 > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); >=20 > + >=20 > + // Set a policy to test against. >=20 > + > UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea > der ) ); >=20 > + >=20 > + // With a policy, make sure that no attributes fail. >=20 > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, >=20 > + &mTestGuid1, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + sizeof(DummyData), >=20 > + DummyData ); >=20 > + UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) ); >=20 > + >=20 > + // With a policy, make sure that some -- but not all -- attributes fai= l. >=20 > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, >=20 > + &mTestGuid1, >=20 > + VARIABLE_ATTRIBUTE_BS_RT_AT, >=20 > + sizeof(DummyData), >=20 > + DummyData ); >=20 > + UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) ); >=20 > + >=20 > + // With a policy, make sure that all attributes pass. >=20 > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, >=20 > + &mTestGuid1, >=20 > + VARIABLE_ATTRIBUTE_NV_BS_RT, >=20 > + sizeof(DummyData), >=20 > + DummyData ); >=20 > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); >=20 > + >=20 > + // With a policy, make sure that all attributes -- plus some -- pass. >=20 > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, >=20 > + &mTestGuid1, >=20 > + VARIABLE_ATTRIBUTE_NV_BS_RT_AT, >=20 > + sizeof(DummyData), >=20 > + DummyData ); >=20 > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); >=20 > + >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Test Case >=20 > +*/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +AttributeCantPoliciesShouldBeHonored ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + SIMPLE_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { >=20 > + { >=20 > + VARIABLE_POLICY_ENTRY_REVISION, >=20 > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME), >=20 > + sizeof(VARIABLE_POLICY_ENTRY), >=20 > + TEST_GUID_1, >=20 > + TEST_POLICY_MIN_SIZE_NULL, >=20 > + TEST_POLICY_MAX_SIZE_NULL, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS, >=20 > + VARIABLE_POLICY_TYPE_NO_LOCK >=20 > + }, >=20 > + TEST_VAR_1_NAME >=20 > + }; >=20 > + EFI_STATUS PolicyCheck; >=20 > + UINT8 DummyData[12]; >=20 > + >=20 > + >=20 > + // Without a policy, there should be no constraints on variable creati= on. >=20 > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, >=20 > + &mTestGuid1, >=20 > + VARIABLE_ATTRIBUTE_BS_RT_AT, >=20 > + sizeof(DummyData), >=20 > + DummyData ); >=20 > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); >=20 > + >=20 > + // Set a policy to test against. >=20 > + > UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea > der ) ); >=20 > + >=20 > + // With a policy, make sure that forbidden attributes fail. >=20 > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, >=20 > + &mTestGuid1, >=20 > + > EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS, >=20 > + sizeof(DummyData), >=20 > + DummyData ); >=20 > + UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) ); >=20 > + >=20 > + // With a policy, make sure that a mixture of attributes -- including = the > forbidden -- fail. >=20 > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, >=20 > + &mTestGuid1, >=20 > + VARIABLE_ATTRIBUTE_BS_RT_AT, >=20 > + sizeof(DummyData), >=20 > + DummyData ); >=20 > + UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) ); >=20 > + >=20 > + // With a policy, make sure that attributes without the forbidden pass= . >=20 > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, >=20 > + &mTestGuid1, >=20 > + VARIABLE_ATTRIBUTE_NV_BS_RT, >=20 > + sizeof(DummyData), >=20 > + DummyData ); >=20 > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); >=20 > + >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Test Case >=20 > +*/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +VariablesShouldBeDeletableRegardlessOfSize ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + SIMPLE_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { >=20 > + { >=20 > + VARIABLE_POLICY_ENTRY_REVISION, >=20 > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME), >=20 > + sizeof(VARIABLE_POLICY_ENTRY), >=20 > + TEST_GUID_1, >=20 > + TEST_POLICY_MIN_SIZE_10, >=20 > + TEST_POLICY_MAX_SIZE_NULL, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS, >=20 > + VARIABLE_POLICY_TYPE_NO_LOCK >=20 > + }, >=20 > + TEST_VAR_1_NAME >=20 > + }; >=20 > + EFI_STATUS PolicyCheck; >=20 > + UINT8 DummyData[TEST_POLICY_MAX_SIZE_200+1]; >=20 > + >=20 > + // Create a policy enforcing a minimum variable size. >=20 > + > UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea > der ) ); >=20 > + >=20 > + // Make sure that a normal set would fail. >=20 > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, >=20 > + &mTestGuid1, >=20 > + VARIABLE_ATTRIBUTE_NV_BS, >=20 > + TEST_POLICY_MIN_SIZE_10-1, >=20 > + DummyData ); >=20 > + UT_ASSERT_STATUS_EQUAL( PolicyCheck, EFI_INVALID_PARAMETER ); >=20 > + >=20 > + // Now make sure that a delete would succeed. >=20 > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, >=20 > + &mTestGuid1, >=20 > + VARIABLE_ATTRIBUTE_NV_BS, >=20 > + 0, >=20 > + NULL ); >=20 > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); >=20 > + >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Test Case >=20 > +*/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +LockNowPoliciesShouldBeHonored ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + SIMPLE_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { >=20 > + { >=20 > + VARIABLE_POLICY_ENTRY_REVISION, >=20 > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME), >=20 > + sizeof(VARIABLE_POLICY_ENTRY), >=20 > + TEST_GUID_1, >=20 > + TEST_POLICY_MIN_SIZE_NULL, >=20 > + TEST_POLICY_MAX_SIZE_NULL, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + VARIABLE_POLICY_TYPE_LOCK_NOW >=20 > + }, >=20 > + TEST_VAR_1_NAME >=20 > + }; >=20 > + EFI_STATUS PolicyCheck; >=20 > + UINT8 DummyData[12]; >=20 > + >=20 > + >=20 > + // Without a policy, there should be no constraints on variable creati= on. >=20 > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, >=20 > + &mTestGuid1, >=20 > + VARIABLE_ATTRIBUTE_BS_RT_AT, >=20 > + sizeof(DummyData), >=20 > + DummyData ); >=20 > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); >=20 > + >=20 > + // Set a policy to test against. >=20 > + > UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea > der ) ); >=20 > + >=20 > + // With a policy, make sure that writes immediately fail. >=20 > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, >=20 > + &mTestGuid1, >=20 > + VARIABLE_ATTRIBUTE_BS_RT_AT, >=20 > + sizeof(DummyData), >=20 > + DummyData ); >=20 > + UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) ); >=20 > + >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Test Case >=20 > +*/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +LockOnCreatePoliciesShouldBeHonored ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + SIMPLE_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { >=20 > + { >=20 > + VARIABLE_POLICY_ENTRY_REVISION, >=20 > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME), >=20 > + sizeof(VARIABLE_POLICY_ENTRY), >=20 > + TEST_GUID_1, >=20 > + TEST_POLICY_MIN_SIZE_NULL, >=20 > + TEST_POLICY_MAX_SIZE_NULL, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + VARIABLE_POLICY_TYPE_LOCK_ON_CREATE >=20 > + }, >=20 > + TEST_VAR_1_NAME >=20 > + }; >=20 > + EFI_STATUS PolicyCheck; >=20 > + UINT8 DummyData[12]; >=20 > + UINTN ExpectedDataSize; >=20 > + >=20 > + >=20 > + // Without a policy, there should be no constraints on variable creati= on. >=20 > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, >=20 > + &mTestGuid1, >=20 > + VARIABLE_ATTRIBUTE_BS_RT_AT, >=20 > + sizeof(DummyData), >=20 > + DummyData ); >=20 > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); >=20 > + >=20 > + // Set a policy to test against. >=20 > + > UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea > der ) ); >=20 > + >=20 > + // Set consistent expectations on what the calls are looking for. >=20 > + expect_memory_count( StubGetVariableNull, VariableName, > TEST_VAR_1_NAME, sizeof(TEST_VAR_1_NAME), 2 ); >=20 > + expect_memory_count( StubGetVariableNull, VendorGuid, &mTestGuid1, > sizeof(mTestGuid1), 2 ); >=20 > + ExpectedDataSize =3D 0; >=20 > + expect_memory_count( StubGetVariableNull, DataSize, > &ExpectedDataSize, sizeof(ExpectedDataSize), 2 ); >=20 > + >=20 > + // With a policy, make sure that writes still work, since the variable= doesn't > exist. >=20 > + will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL ); // > Attributes >=20 > + will_return( StubGetVariableNull, 0 ); //= Size >=20 > + will_return( StubGetVariableNull, NULL ); //= DataPtr >=20 > + will_return( StubGetVariableNull, EFI_NOT_FOUND ); //= Status >=20 > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, >=20 > + &mTestGuid1, >=20 > + VARIABLE_ATTRIBUTE_BS_RT_AT, >=20 > + sizeof(DummyData), >=20 > + DummyData ); >=20 > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); >=20 > + >=20 > + // With a policy, make sure that a call with an "existing" variable fa= ils. >=20 > + will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL ); // > Attributes >=20 > + will_return( StubGetVariableNull, 10 ); //= Size >=20 > + will_return( StubGetVariableNull, NULL ); //= DataPtr >=20 > + will_return( StubGetVariableNull, EFI_BUFFER_TOO_SMALL ); // > Status >=20 > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, >=20 > + &mTestGuid1, >=20 > + VARIABLE_ATTRIBUTE_BS_RT_AT, >=20 > + sizeof(DummyData), >=20 > + DummyData ); >=20 > + UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) ); >=20 > + >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Test Case >=20 > +*/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +LockOnStatePoliciesShouldBeHonored ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + EXPANDED_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { >=20 > + { >=20 > + VARIABLE_POLICY_ENTRY_REVISION, >=20 > + 0, // Will be populated by init helper. >=20 > + 0, // Will be populated by init helper. >=20 > + TEST_GUID_1, >=20 > + TEST_POLICY_MIN_SIZE_NULL, >=20 > + TEST_POLICY_MAX_SIZE_NULL, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE >=20 > + }, >=20 > + { >=20 > + TEST_GUID_2, >=20 > + 20, // Value >=20 > + 0 // Padding >=20 > + }, >=20 > + L"", >=20 > + L"" >=20 > + }; >=20 > + EFI_STATUS PolicyCheck; >=20 > + UINT8 DummyData[12]; >=20 > + UINT8 ValidationStateVar; >=20 > + UINTN ExpectedDataSize; >=20 > + UT_ASSERT_TRUE( InitExpVarPolicyStrings( &ValidationPolicy, > TEST_VAR_1_NAME, TEST_VAR_2_NAME ) ); >=20 > + >=20 > + >=20 > + // Without a policy, there should be no constraints on variable creati= on. >=20 > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, >=20 > + &mTestGuid1, >=20 > + VARIABLE_ATTRIBUTE_BS_RT_AT, >=20 > + sizeof(DummyData), >=20 > + DummyData ); >=20 > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); >=20 > + >=20 > + // Set a policy to test against. >=20 > + > UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea > der ) ); >=20 > + >=20 > + // Set consistent expectations on what the calls are looking for. >=20 > + expect_memory_count( StubGetVariableNull, VariableName, > TEST_VAR_2_NAME, sizeof(TEST_VAR_2_NAME), 5 ); >=20 > + expect_memory_count( StubGetVariableNull, VendorGuid, &mTestGuid2, > sizeof(mTestGuid2), 5 ); >=20 > + ExpectedDataSize =3D 1; >=20 > + expect_memory_count( StubGetVariableNull, DataSize, > &ExpectedDataSize, sizeof(ExpectedDataSize), 5 ); >=20 > + >=20 > + // With a policy, make sure that writes still work, since the variable= doesn't > exist. >=20 > + will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL ); // > Attributes >=20 > + will_return( StubGetVariableNull, 0 ); //= Size >=20 > + will_return( StubGetVariableNull, NULL ); //= DataPtr >=20 > + will_return( StubGetVariableNull, EFI_NOT_FOUND ); //= Status >=20 > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, >=20 > + &mTestGuid1, >=20 > + VARIABLE_ATTRIBUTE_BS_RT_AT, >=20 > + sizeof(DummyData), >=20 > + DummyData ); >=20 > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); >=20 > + >=20 > + // With a policy, make sure that a state variable that's too large doe= sn't lock > the variable. >=20 > + will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL ); // > Attributes >=20 > + will_return( StubGetVariableNull, 10 ); //= Size >=20 > + will_return( StubGetVariableNull, NULL ); //= DataPtr >=20 > + will_return( StubGetVariableNull, EFI_BUFFER_TOO_SMALL ); // > Status >=20 > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, >=20 > + &mTestGuid1, >=20 > + VARIABLE_ATTRIBUTE_BS_RT_AT, >=20 > + sizeof(DummyData), >=20 > + DummyData ); >=20 > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); >=20 > + >=20 > + // With a policy, check a state variable with the wrong value. >=20 > + ValidationStateVar =3D 0; >=20 > + will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL ); // > Attributes >=20 > + will_return( StubGetVariableNull, sizeof(ValidationStateVar) ); //= Size >=20 > + will_return( StubGetVariableNull, &ValidationStateVar ); //= DataPtr >=20 > + will_return( StubGetVariableNull, EFI_SUCCESS ); //= Status >=20 > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, >=20 > + &mTestGuid1, >=20 > + VARIABLE_ATTRIBUTE_BS_RT_AT, >=20 > + sizeof(DummyData), >=20 > + DummyData ); >=20 > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); >=20 > + >=20 > + // With a policy, check a state variable with another wrong value. >=20 > + ValidationStateVar =3D 10; >=20 > + will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL ); // > Attributes >=20 > + will_return( StubGetVariableNull, sizeof(ValidationStateVar) ); //= Size >=20 > + will_return( StubGetVariableNull, &ValidationStateVar ); //= DataPtr >=20 > + will_return( StubGetVariableNull, EFI_SUCCESS ); //= Status >=20 > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, >=20 > + &mTestGuid1, >=20 > + VARIABLE_ATTRIBUTE_BS_RT_AT, >=20 > + sizeof(DummyData), >=20 > + DummyData ); >=20 > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); >=20 > + >=20 > + // With a policy, make sure that a call with a correct state variable = fails. >=20 > + ValidationStateVar =3D 20; >=20 > + will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL ); // > Attributes >=20 > + will_return( StubGetVariableNull, sizeof(ValidationStateVar) ); //= Size >=20 > + will_return( StubGetVariableNull, &ValidationStateVar ); //= DataPtr >=20 > + will_return( StubGetVariableNull, EFI_SUCCESS ); //= Status >=20 > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, >=20 > + &mTestGuid1, >=20 > + VARIABLE_ATTRIBUTE_BS_RT_AT, >=20 > + sizeof(DummyData), >=20 > + DummyData ); >=20 > + UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) ); >=20 > + >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Test Case >=20 > +*/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +LockOnStatePoliciesShouldApplyToNamespaces ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + EXPANDED_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { >=20 > + { >=20 > + VARIABLE_POLICY_ENTRY_REVISION, >=20 > + 0, // Will be populated by init helper. >=20 > + 0, // Will be populated by init helper. >=20 > + TEST_GUID_1, >=20 > + TEST_POLICY_MIN_SIZE_NULL, >=20 > + TEST_POLICY_MAX_SIZE_NULL, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE >=20 > + }, >=20 > + { >=20 > + TEST_GUID_2, >=20 > + 20, // Value >=20 > + 0 // Padding >=20 > + }, >=20 > + L"", >=20 > + L"" >=20 > + }; >=20 > + EFI_STATUS PolicyCheck; >=20 > + UINT8 DummyData[12]; >=20 > + UINT8 ValidationStateVar; >=20 > + UINTN ExpectedDataSize; >=20 > + UT_ASSERT_TRUE( InitExpVarPolicyStrings( &ValidationPolicy, NULL, > TEST_VAR_2_NAME ) ); >=20 > + >=20 > + >=20 > + // Without a policy, there should be no constraints on variable creati= on. >=20 > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, >=20 > + &mTestGuid1, >=20 > + VARIABLE_ATTRIBUTE_BS_RT_AT, >=20 > + sizeof(DummyData), >=20 > + DummyData ); >=20 > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); >=20 > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_3_NAME, >=20 > + &mTestGuid1, >=20 > + VARIABLE_ATTRIBUTE_BS_RT_AT, >=20 > + sizeof(DummyData), >=20 > + DummyData ); >=20 > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); >=20 > + >=20 > + // Set a policy to test against. >=20 > + > UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea > der ) ); >=20 > + >=20 > + // Set consistent expectations on what the calls are looking for. >=20 > + expect_memory_count( StubGetVariableNull, VariableName, > TEST_VAR_2_NAME, sizeof(TEST_VAR_2_NAME), 4 ); >=20 > + expect_memory_count( StubGetVariableNull, VendorGuid, &mTestGuid2, > sizeof(mTestGuid2), 4 ); >=20 > + ExpectedDataSize =3D 1; >=20 > + expect_memory_count( StubGetVariableNull, DataSize, > &ExpectedDataSize, sizeof(ExpectedDataSize), 4 ); >=20 > + >=20 > + // With a policy, make sure that writes still work, since the variable= doesn't > exist. >=20 > + will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL ); // > Attributes >=20 > + will_return( StubGetVariableNull, 0 ); //= Size >=20 > + will_return( StubGetVariableNull, NULL ); //= DataPtr >=20 > + will_return( StubGetVariableNull, EFI_NOT_FOUND ); //= Status >=20 > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, >=20 > + &mTestGuid1, >=20 > + VARIABLE_ATTRIBUTE_BS_RT_AT, >=20 > + sizeof(DummyData), >=20 > + DummyData ); >=20 > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); >=20 > + will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL ); // > Attributes >=20 > + will_return( StubGetVariableNull, 0 ); //= Size >=20 > + will_return( StubGetVariableNull, NULL ); //= DataPtr >=20 > + will_return( StubGetVariableNull, EFI_NOT_FOUND ); //= Status >=20 > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_3_NAME, >=20 > + &mTestGuid1, >=20 > + VARIABLE_ATTRIBUTE_BS_RT_AT, >=20 > + sizeof(DummyData), >=20 > + DummyData ); >=20 > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); >=20 > + >=20 > + // With a policy, make sure that a call with a correct state variable = fails. >=20 > + ValidationStateVar =3D 20; >=20 > + will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL ); // > Attributes >=20 > + will_return( StubGetVariableNull, sizeof(ValidationStateVar) ); //= Size >=20 > + will_return( StubGetVariableNull, &ValidationStateVar ); //= DataPtr >=20 > + will_return( StubGetVariableNull, EFI_SUCCESS ); //= Status >=20 > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, >=20 > + &mTestGuid1, >=20 > + VARIABLE_ATTRIBUTE_BS_RT_AT, >=20 > + sizeof(DummyData), >=20 > + DummyData ); >=20 > + UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) ); >=20 > + will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL ); // > Attributes >=20 > + will_return( StubGetVariableNull, sizeof(ValidationStateVar) ); //= Size >=20 > + will_return( StubGetVariableNull, &ValidationStateVar ); //= DataPtr >=20 > + will_return( StubGetVariableNull, EFI_SUCCESS ); //= Status >=20 > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_3_NAME, >=20 > + &mTestGuid1, >=20 > + VARIABLE_ATTRIBUTE_BS_RT_AT, >=20 > + sizeof(DummyData), >=20 > + DummyData ); >=20 > + UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) ); >=20 > + >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Test Case >=20 > +*/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +LockOnStateShouldHandleErrorsGracefully ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + EXPANDED_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { >=20 > + { >=20 > + VARIABLE_POLICY_ENTRY_REVISION, >=20 > + 0, // Will be populated by init helper. >=20 > + 0, // Will be populated by init helper. >=20 > + TEST_GUID_1, >=20 > + TEST_POLICY_MIN_SIZE_NULL, >=20 > + TEST_POLICY_MAX_SIZE_NULL, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE >=20 > + }, >=20 > + { >=20 > + TEST_GUID_2, >=20 > + 20, // Value >=20 > + 0 // Padding >=20 > + }, >=20 > + L"", >=20 > + L"" >=20 > + }; >=20 > + EFI_STATUS PolicyCheck; >=20 > + UINT8 DummyData[12]; >=20 > + UT_ASSERT_TRUE( InitExpVarPolicyStrings( &ValidationPolicy, > TEST_VAR_1_NAME, TEST_VAR_2_NAME ) ); >=20 > + >=20 > + >=20 > + // Without a policy, there should be no constraints on variable creati= on. >=20 > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, >=20 > + &mTestGuid1, >=20 > + VARIABLE_ATTRIBUTE_BS_RT_AT, >=20 > + sizeof(DummyData), >=20 > + DummyData ); >=20 > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); >=20 > + >=20 > + // Set a policy to test against. >=20 > + > UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea > der ) ); >=20 > + >=20 > + // Configure the stub to not care about parameters. We're testing erro= rs. >=20 > + expect_any_always( StubGetVariableNull, VariableName ); >=20 > + expect_any_always( StubGetVariableNull, VendorGuid ); >=20 > + expect_any_always( StubGetVariableNull, DataSize ); >=20 > + >=20 > + // With a policy, make sure that writes still work, since the variable= doesn't > exist. >=20 > + will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL ); // > Attributes >=20 > + will_return( StubGetVariableNull, 0 ); //= Size >=20 > + will_return( StubGetVariableNull, NULL ); //= DataPtr >=20 > + will_return( StubGetVariableNull, EFI_NOT_FOUND ); //= Status >=20 > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, >=20 > + &mTestGuid1, >=20 > + VARIABLE_ATTRIBUTE_BS_RT_AT, >=20 > + sizeof(DummyData), >=20 > + DummyData ); >=20 > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); >=20 > + >=20 > + // Verify that state variables that are the wrong size won't lock the = variable. >=20 > + will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL ); // > Attributes >=20 > + will_return( StubGetVariableNull, 0 ); //= Size >=20 > + will_return( StubGetVariableNull, NULL ); //= DataPtr >=20 > + will_return( StubGetVariableNull, EFI_BUFFER_TOO_SMALL ); // > Status >=20 > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, >=20 > + &mTestGuid1, >=20 > + VARIABLE_ATTRIBUTE_BS_RT_AT, >=20 > + sizeof(DummyData), >=20 > + DummyData ); >=20 > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); >=20 > + >=20 > + // Verify that unexpected errors default to locked. >=20 > + will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL ); // > Attributes >=20 > + will_return( StubGetVariableNull, 0 ); //= Size >=20 > + will_return( StubGetVariableNull, NULL ); //= DataPtr >=20 > + will_return( StubGetVariableNull, EFI_UNSUPPORTED ); //= Status >=20 > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, >=20 > + &mTestGuid1, >=20 > + VARIABLE_ATTRIBUTE_BS_RT_AT, >=20 > + sizeof(DummyData), >=20 > + DummyData ); >=20 > + UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) ); >=20 > + >=20 > + will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL ); // > Attributes >=20 > + will_return( StubGetVariableNull, 0 ); //= Size >=20 > + will_return( StubGetVariableNull, NULL ); //= DataPtr >=20 > + will_return( StubGetVariableNull, EFI_NOT_READY ); //= Status >=20 > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, >=20 > + &mTestGuid1, >=20 > + VARIABLE_ATTRIBUTE_BS_RT_AT, >=20 > + sizeof(DummyData), >=20 > + DummyData ); >=20 > + UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) ); >=20 > + >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Test Case >=20 > +*/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +BestMatchPriorityShouldBeObeyed ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + SIMPLE_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { >=20 > + { >=20 > + VARIABLE_POLICY_ENTRY_REVISION, >=20 > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(L"Wild12Card34Placeholder")= , >=20 > + sizeof(VARIABLE_POLICY_ENTRY), >=20 > + TEST_GUID_1, >=20 > + TEST_POLICY_MIN_SIZE_NULL, >=20 > + TEST_POLICY_MAX_SIZE_NULL, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + VARIABLE_POLICY_TYPE_NO_LOCK >=20 > + }, >=20 > + L"Wild12Card34Placeholder" >=20 > + }; >=20 > + EFI_STATUS PolicyCheck; >=20 > + UINT8 DummyData[70]; >=20 > + CHAR16 *PolicyName =3D (CHAR16*)((UINT8*)&ValidationPolicy + > sizeof(VARIABLE_POLICY_ENTRY)); >=20 > + UINTN PolicyNameSize =3D sizeof(L"Wild12Card34Placeholder"); >=20 > + CHAR16 *FourWildcards =3D L"Wild##Card##Placeholder"; >=20 > + CHAR16 *ThreeWildcards =3D L"Wild##Card#4Placeholder"; >=20 > + CHAR16 *TwoWildcards =3D L"Wild##Card34Placeholder"; >=20 > + CHAR16 *OneWildcard =3D L"Wild#2Card34Placeholder"; >=20 > + CHAR16 *NoWildcards =3D L"Wild12Card34Placeholder"; >=20 > + >=20 > + // Create all of the policies from least restrictive to most restricti= ve. >=20 > + // NoWildcards should be the most restrictive. >=20 > + ValidationPolicy.Header.MaxSize =3D 60; >=20 > + ValidationPolicy.Header.Size =3D ValidationPolicy.Header.OffsetToName; >=20 > + > UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea > der ) ); >=20 > + ValidationPolicy.Header.Size +=3D (UINT16)PolicyNameSize; >=20 > + ValidationPolicy.Header.MaxSize =3D 50; >=20 > + CopyMem( PolicyName, FourWildcards, PolicyNameSize ); >=20 > + > UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea > der ) ); >=20 > + ValidationPolicy.Header.MaxSize =3D 40; >=20 > + CopyMem( PolicyName, ThreeWildcards, PolicyNameSize ); >=20 > + > UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea > der ) ); >=20 > + ValidationPolicy.Header.MaxSize =3D 30; >=20 > + CopyMem( PolicyName, TwoWildcards, PolicyNameSize ); >=20 > + > UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea > der ) ); >=20 > + ValidationPolicy.Header.MaxSize =3D 20; >=20 > + CopyMem( PolicyName, OneWildcard, PolicyNameSize ); >=20 > + > UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea > der ) ); >=20 > + ValidationPolicy.Header.MaxSize =3D 10; >=20 > + CopyMem( PolicyName, NoWildcards, PolicyNameSize ); >=20 > + > UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea > der ) ); >=20 > + >=20 > + // Verify that variables only matching the namespace have the most > flexible policy. >=20 > + PolicyCheck =3D ValidateSetVariable( L"ArbitraryName", >=20 > + &mTestGuid1, >=20 > + VARIABLE_ATTRIBUTE_BS_RT_AT, >=20 > + 65, >=20 > + DummyData ); >=20 > + UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) ); >=20 > + PolicyCheck =3D ValidateSetVariable( L"ArbitraryName", >=20 > + &mTestGuid1, >=20 > + VARIABLE_ATTRIBUTE_BS_RT_AT, >=20 > + 55, >=20 > + DummyData ); >=20 > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); >=20 > + >=20 > + // Verify that variables matching increasing characters get increasing= policy > restrictions. >=20 > + PolicyCheck =3D ValidateSetVariable( L"Wild77Card77Placeholder", >=20 > + &mTestGuid1, >=20 > + VARIABLE_ATTRIBUTE_BS_RT_AT, >=20 > + 55, >=20 > + DummyData ); >=20 > + UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) ); >=20 > + PolicyCheck =3D ValidateSetVariable( L"Wild77Card77Placeholder", >=20 > + &mTestGuid1, >=20 > + VARIABLE_ATTRIBUTE_BS_RT_AT, >=20 > + 45, >=20 > + DummyData ); >=20 > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); >=20 > + >=20 > + PolicyCheck =3D ValidateSetVariable( L"Wild77Card74Placeholder", >=20 > + &mTestGuid1, >=20 > + VARIABLE_ATTRIBUTE_BS_RT_AT, >=20 > + 45, >=20 > + DummyData ); >=20 > + UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) ); >=20 > + PolicyCheck =3D ValidateSetVariable( L"Wild77Card74Placeholder", >=20 > + &mTestGuid1, >=20 > + VARIABLE_ATTRIBUTE_BS_RT_AT, >=20 > + 35, >=20 > + DummyData ); >=20 > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); >=20 > + >=20 > + PolicyCheck =3D ValidateSetVariable( L"Wild77Card34Placeholder", >=20 > + &mTestGuid1, >=20 > + VARIABLE_ATTRIBUTE_BS_RT_AT, >=20 > + 35, >=20 > + DummyData ); >=20 > + UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) ); >=20 > + PolicyCheck =3D ValidateSetVariable( L"Wild77Card34Placeholder", >=20 > + &mTestGuid1, >=20 > + VARIABLE_ATTRIBUTE_BS_RT_AT, >=20 > + 25, >=20 > + DummyData ); >=20 > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); >=20 > + >=20 > + PolicyCheck =3D ValidateSetVariable( L"Wild72Card34Placeholder", >=20 > + &mTestGuid1, >=20 > + VARIABLE_ATTRIBUTE_BS_RT_AT, >=20 > + 25, >=20 > + DummyData ); >=20 > + UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) ); >=20 > + PolicyCheck =3D ValidateSetVariable( L"Wild72Card34Placeholder", >=20 > + &mTestGuid1, >=20 > + VARIABLE_ATTRIBUTE_BS_RT_AT, >=20 > + 15, >=20 > + DummyData ); >=20 > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); >=20 > + >=20 > + PolicyCheck =3D ValidateSetVariable( L"Wild12Card34Placeholder", >=20 > + &mTestGuid1, >=20 > + VARIABLE_ATTRIBUTE_BS_RT_AT, >=20 > + 15, >=20 > + DummyData ); >=20 > + UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) ); >=20 > + PolicyCheck =3D ValidateSetVariable( L"Wild12Card34Placeholder", >=20 > + &mTestGuid1, >=20 > + VARIABLE_ATTRIBUTE_BS_RT_AT, >=20 > + 5, >=20 > + DummyData ); >=20 > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); >=20 > + >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > + >=20 > +///=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 >=20 > + >=20 > +/** >=20 > + Test Case >=20 > +*/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +ShouldBeAbleToLockInterface ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + SIMPLE_VARIABLE_POLICY_ENTRY TestPolicy =3D { >=20 > + { >=20 > + VARIABLE_POLICY_ENTRY_REVISION, >=20 > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME), >=20 > + sizeof(VARIABLE_POLICY_ENTRY), >=20 > + TEST_GUID_1, >=20 > + TEST_POLICY_MIN_SIZE_NULL, >=20 > + TEST_POLICY_MAX_SIZE_NULL, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + VARIABLE_POLICY_TYPE_NO_LOCK >=20 > + }, >=20 > + TEST_VAR_1_NAME >=20 > + }; >=20 > + >=20 > + // Make sure it's not already locked. >=20 > + UT_ASSERT_FALSE( IsVariablePolicyInterfaceLocked() ); >=20 > + // Lock it. >=20 > + UT_ASSERT_NOT_EFI_ERROR( LockVariablePolicy() ); >=20 > + // Verify that it's locked. >=20 > + UT_ASSERT_TRUE( IsVariablePolicyInterfaceLocked() ); >=20 > + >=20 > + // Verify that all state-changing commands fail. >=20 > + UT_ASSERT_TRUE( EFI_ERROR( LockVariablePolicy() ) ); >=20 > + UT_ASSERT_TRUE( EFI_ERROR( DisableVariablePolicy() ) ); >=20 > + > UT_ASSERT_TRUE( EFI_ERROR( RegisterVariablePolicy( &TestPolicy.Header ) > ) ); >=20 > + >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Test Case >=20 > +*/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +ShouldBeAbleToDisablePolicyEnforcement ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + SIMPLE_VARIABLE_POLICY_ENTRY TestPolicy =3D { >=20 > + { >=20 > + VARIABLE_POLICY_ENTRY_REVISION, >=20 > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME), >=20 > + sizeof(VARIABLE_POLICY_ENTRY), >=20 > + TEST_GUID_1, >=20 > + TEST_POLICY_MIN_SIZE_10, >=20 > + TEST_POLICY_MAX_SIZE_200, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + VARIABLE_POLICY_TYPE_NO_LOCK >=20 > + }, >=20 > + TEST_VAR_1_NAME >=20 > + }; >=20 > + EFI_STATUS PolicyCheck; >=20 > + UINT8 DummyData[TEST_POLICY_MIN_SIZE_10-1]; >=20 > + >=20 > + // Make sure that the policy enforcement is currently enabled. >=20 > + UT_ASSERT_TRUE( IsVariablePolicyEnabled() ); >=20 > + // Add a policy before it's disabled. >=20 > + > UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &TestPolicy.Header ) ); >=20 > + // Disable the policy enforcement. >=20 > + UT_ASSERT_NOT_EFI_ERROR( DisableVariablePolicy() ); >=20 > + // Make sure that the policy enforcement is currently disabled. >=20 > + UT_ASSERT_FALSE( IsVariablePolicyEnabled() ); >=20 > + >=20 > + // Check to make sure that a policy violation still passes. >=20 > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, >=20 > + &mTestGuid1, >=20 > + VARIABLE_ATTRIBUTE_NV_BS, >=20 > + sizeof(DummyData), >=20 > + DummyData ); >=20 > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); >=20 > + >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Test Case >=20 > +*/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +ShouldNotBeAbleToDisablePoliciesTwice ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + // Make sure that the policy enforcement is currently enabled. >=20 > + UT_ASSERT_TRUE( IsVariablePolicyEnabled() ); >=20 > + // Disable the policy enforcement. >=20 > + UT_ASSERT_NOT_EFI_ERROR( DisableVariablePolicy() ); >=20 > + // Make sure that the policy enforcement is currently disabled. >=20 > + UT_ASSERT_FALSE( IsVariablePolicyEnabled() ); >=20 > + // Try to disable again and verify failure. >=20 > + UT_ASSERT_TRUE( EFI_ERROR( DisableVariablePolicy() ) ); >=20 > + >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Test Case >=20 > +*/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +ShouldBeAbleToAddNewPoliciesAfterDisabled ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + SIMPLE_VARIABLE_POLICY_ENTRY TestPolicy =3D { >=20 > + { >=20 > + VARIABLE_POLICY_ENTRY_REVISION, >=20 > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME), >=20 > + sizeof(VARIABLE_POLICY_ENTRY), >=20 > + TEST_GUID_1, >=20 > + TEST_POLICY_MIN_SIZE_10, >=20 > + TEST_POLICY_MAX_SIZE_200, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + VARIABLE_POLICY_TYPE_NO_LOCK >=20 > + }, >=20 > + TEST_VAR_1_NAME >=20 > + }; >=20 > + EFI_STATUS PolicyCheck; >=20 > + >=20 > + // Make sure that the policy enforcement is currently enabled. >=20 > + UT_ASSERT_TRUE( IsVariablePolicyEnabled() ); >=20 > + // Disable the policy enforcement. >=20 > + UT_ASSERT_NOT_EFI_ERROR( DisableVariablePolicy() ); >=20 > + >=20 > + // Make sure that new policy creation still works, it just won't be en= forced. >=20 > + PolicyCheck =3D RegisterVariablePolicy( &TestPolicy.Header ); >=20 > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); >=20 > + >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Test Case >=20 > +*/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +ShouldBeAbleToLockAfterDisabled ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + // Make sure that the policy enforcement is currently enabled. >=20 > + UT_ASSERT_TRUE( IsVariablePolicyEnabled() ); >=20 > + // Disable the policy enforcement. >=20 > + UT_ASSERT_NOT_EFI_ERROR( DisableVariablePolicy() ); >=20 > + >=20 > + // Make sure that we can lock in this state. >=20 > + UT_ASSERT_FALSE( IsVariablePolicyInterfaceLocked() ); >=20 > + UT_ASSERT_NOT_EFI_ERROR( LockVariablePolicy() ); >=20 > + UT_ASSERT_TRUE( IsVariablePolicyInterfaceLocked() ); >=20 > + >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Test Case >=20 > +*/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +ShouldBeAbleToDumpThePolicyTable ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + SIMPLE_VARIABLE_POLICY_ENTRY TestPolicy =3D { >=20 > + { >=20 > + VARIABLE_POLICY_ENTRY_REVISION, >=20 > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME), >=20 > + sizeof(VARIABLE_POLICY_ENTRY), >=20 > + TEST_GUID_1, >=20 > + TEST_POLICY_MIN_SIZE_10, >=20 > + TEST_POLICY_MAX_SIZE_200, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + VARIABLE_POLICY_TYPE_NO_LOCK >=20 > + }, >=20 > + TEST_VAR_1_NAME >=20 > + }; >=20 > + EFI_STATUS PolicyCheck; >=20 > + UINT32 DumpSize; >=20 > + UINT32 BufferSize; >=20 > + VOID *DumpBuffer; >=20 > + >=20 > + // For good measure, test some parameter validation. >=20 > + UT_ASSERT_STATUS_EQUAL( DumpVariablePolicy( NULL, NULL ), > EFI_INVALID_PARAMETER ); >=20 > + DumpSize =3D 10; >=20 > + UT_ASSERT_STATUS_EQUAL( DumpVariablePolicy( NULL, &DumpSize ), > EFI_INVALID_PARAMETER ); >=20 > + >=20 > + // Now for the actual test case. >=20 > + >=20 > + // Allocate a buffer to hold the output. >=20 > + BufferSize =3D sizeof(VARIABLE_POLICY_ENTRY) + > sizeof(TEST_VAR_1_NAME); >=20 > + DumpBuffer =3D AllocatePool( BufferSize ); >=20 > + UT_ASSERT_NOT_EQUAL( DumpBuffer, NULL ); >=20 > + >=20 > + // Verify that the current table size is 0. >=20 > + DumpSize =3D BufferSize; >=20 > + UT_ASSERT_NOT_EFI_ERROR( DumpVariablePolicy( DumpBuffer, > &DumpSize ) ); >=20 > + UT_ASSERT_EQUAL( DumpSize, 0 ); >=20 > + >=20 > + // Now, set a new policy. >=20 > + > UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &TestPolicy.Header ) ); >=20 > + >=20 > + // Make sure that the new return is non-zero and fails as expected. >=20 > + DumpSize =3D 0; >=20 > + PolicyCheck =3D DumpVariablePolicy( NULL, &DumpSize ); >=20 > + UT_ASSERT_STATUS_EQUAL( PolicyCheck, EFI_BUFFER_TOO_SMALL ); >=20 > + UT_ASSERT_EQUAL( DumpSize, BufferSize ); >=20 > + >=20 > + // Now verify that we can fetch the dump. >=20 > + DumpSize =3D BufferSize; >=20 > + UT_ASSERT_NOT_EFI_ERROR( DumpVariablePolicy( DumpBuffer, > &DumpSize ) ); >=20 > + UT_ASSERT_EQUAL( DumpSize, BufferSize ); >=20 > + UT_ASSERT_MEM_EQUAL( &TestPolicy, DumpBuffer, BufferSize ); >=20 > + >=20 > + // Always put away your toys. >=20 > + FreePool( DumpBuffer ); >=20 > + >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Test Case >=20 > +*/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +ShouldBeAbleToDumpThePolicyTableAfterDisabled ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + SIMPLE_VARIABLE_POLICY_ENTRY TestPolicy =3D { >=20 > + { >=20 > + VARIABLE_POLICY_ENTRY_REVISION, >=20 > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME), >=20 > + sizeof(VARIABLE_POLICY_ENTRY), >=20 > + TEST_GUID_1, >=20 > + TEST_POLICY_MIN_SIZE_10, >=20 > + TEST_POLICY_MAX_SIZE_200, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + VARIABLE_POLICY_TYPE_NO_LOCK >=20 > + }, >=20 > + TEST_VAR_1_NAME >=20 > + }; >=20 > + SIMPLE_VARIABLE_POLICY_ENTRY TestPolicy2 =3D { >=20 > + { >=20 > + VARIABLE_POLICY_ENTRY_REVISION, >=20 > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_2_NAME), >=20 > + sizeof(VARIABLE_POLICY_ENTRY), >=20 > + TEST_GUID_2, >=20 > + TEST_POLICY_MIN_SIZE_10, >=20 > + TEST_POLICY_MAX_SIZE_200, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + TEST_POLICY_ATTRIBUTES_NULL, >=20 > + VARIABLE_POLICY_TYPE_NO_LOCK >=20 > + }, >=20 > + TEST_VAR_2_NAME >=20 > + }; >=20 > + EFI_STATUS PolicyCheck; >=20 > + UINT32 DumpSize; >=20 > + VOID *DumpBuffer; >=20 > + >=20 > + DumpBuffer =3D NULL; >=20 > + DumpSize =3D 0; >=20 > + >=20 > + // Register a new policy. >=20 > + > UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &TestPolicy.Header ) ); >=20 > + // Make sure that we can dump the policy. >=20 > + PolicyCheck =3D DumpVariablePolicy( DumpBuffer, &DumpSize ); >=20 > + UT_ASSERT_STATUS_EQUAL( PolicyCheck, EFI_BUFFER_TOO_SMALL ); >=20 > + DumpBuffer =3D AllocatePool( DumpSize ); >=20 > + UT_ASSERT_NOT_EFI_ERROR( DumpVariablePolicy( DumpBuffer, > &DumpSize ) ); >=20 > + UT_ASSERT_MEM_EQUAL( DumpBuffer, &TestPolicy, DumpSize ); >=20 > + >=20 > + // Clean up from this step. >=20 > + FreePool( DumpBuffer ); >=20 > + DumpBuffer =3D NULL; >=20 > + DumpSize =3D 0; >=20 > + >=20 > + // Now disable the engine. >=20 > + DisableVariablePolicy(); >=20 > + >=20 > + // Now register a new policy and make sure that both can be dumped. >=20 > + > UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &TestPolicy2.Header ) > ); >=20 > + // Make sure that we can dump the policy. >=20 > + PolicyCheck =3D DumpVariablePolicy( DumpBuffer, &DumpSize ); >=20 > + UT_ASSERT_STATUS_EQUAL( PolicyCheck, EFI_BUFFER_TOO_SMALL ); >=20 > + DumpBuffer =3D AllocatePool( DumpSize ); >=20 > + UT_ASSERT_NOT_EFI_ERROR( DumpVariablePolicy( DumpBuffer, > &DumpSize ) ); >=20 > + >=20 > + // Finally, make sure that both policies are in the dump. >=20 > + UT_ASSERT_MEM_EQUAL( DumpBuffer, &TestPolicy, > TestPolicy.Header.Size ); >=20 > + UT_ASSERT_MEM_EQUAL( (UINT8*)DumpBuffer + TestPolicy.Header.Size, >=20 > + &TestPolicy2, >=20 > + TestPolicy2.Header.Size ); >=20 > + >=20 > + // Always put away your toys. >=20 > + FreePool( DumpBuffer ); >=20 > + >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > + >=20 > +///=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 >=20 > + >=20 > +/** >=20 > + SampleUnitTestApp >=20 > + >=20 > + @param[in] ImageHandle The firmware allocated handle for the EFI imag= e. >=20 > + @param[in] SystemTable A pointer to the EFI System Table. >=20 > + >=20 > + @retval EFI_SUCCESS The entry point executed successfully. >=20 > + @retval other Some error occured when executing this entry p= oint. >=20 > + >=20 > +**/ >=20 > +int >=20 > +main ( >=20 > + ) >=20 > +{ >=20 > + EFI_STATUS Status; >=20 > + UNIT_TEST_FRAMEWORK_HANDLE Framework =3D NULL; >=20 > + UNIT_TEST_SUITE_HANDLE ArchTests; >=20 > + UNIT_TEST_SUITE_HANDLE PolicyTests; >=20 > + UNIT_TEST_SUITE_HANDLE UtilityTests; >=20 > +#ifdef INTERNAL_UNIT_TEST >=20 > + UNIT_TEST_SUITE_HANDLE InternalTests; >=20 > +#endif // INTERNAL_UNIT_TEST >=20 > + >=20 > + DEBUG(( DEBUG_INFO, "%a v%a\n", UNIT_TEST_NAME, > UNIT_TEST_VERSION )); >=20 > + >=20 > + // >=20 > + // Start setting up the test framework for running the tests. >=20 > + // >=20 > + Status =3D InitUnitTestFramework( &Framework, UNIT_TEST_NAME, > gEfiCallerBaseName, UNIT_TEST_VERSION ); >=20 > + if (EFI_ERROR( Status )) >=20 > + { >=20 > + DEBUG((DEBUG_ERROR, "Failed in InitUnitTestFramework. Status =3D %r\= n", > Status)); >=20 > + goto EXIT; >=20 > + } >=20 > + >=20 > + >=20 > + // >=20 > + // Add all test suites and tests. >=20 > + // >=20 > + Status =3D CreateUnitTestSuite( &ArchTests, Framework, "Variable Polic= y > Architectural Tests", "VarPolicy.Arch", NULL, NULL ); >=20 > + if (EFI_ERROR( Status )) >=20 > + { >=20 > + DEBUG((DEBUG_ERROR, "Failed in CreateUnitTestSuite for > ArchTests\n")); >=20 > + Status =3D EFI_OUT_OF_RESOURCES; >=20 > + goto EXIT; >=20 > + } >=20 > + AddTestCase( ArchTests, >=20 > + "Deinitialization should fail if not previously initiali= zed", > "VarPolicy.Arch.OnlyDeinit", >=20 > + ShouldFailDeinitWithoutInit, NULL, NULL, NULL ); >=20 > + AddTestCase( ArchTests, >=20 > + "Initialization followed by deinitialization should succ= eed", > "VarPolicy.Arch.InitDeinit", >=20 > + ShouldBeAbleToInitAndDeinitTheLibrary, NULL, NULL, NULL = ); >=20 > + AddTestCase( ArchTests, >=20 > + "The initialization function fail if called twice withou= t a deinit", > "VarPolicy.Arch.InitTwice", >=20 > + ShouldNotBeAbleToInitializeTheLibraryTwice, NULL, LibCle= anup, > NULL ); >=20 > + AddTestCase( ArchTests, >=20 > + "API functions should be unavailable until library is in= itialized", > "VarPolicy.Arch.UninitApiOff", >=20 > + ApiCommandsShouldNotRespondIfLibIsUninitialized, NULL, > LibCleanup, NULL ); >=20 > + >=20 > +#ifdef INTERNAL_UNIT_TEST >=20 > + Status =3D CreateUnitTestSuite( &InternalTests, Framework, "Variable P= olicy > Internal Tests", "VarPolicy.Internal", NULL, NULL ); >=20 > + if (EFI_ERROR( Status )) >=20 > + { >=20 > + DEBUG((DEBUG_ERROR, "Failed in CreateUnitTestSuite for > InternalTests\n")); >=20 > + Status =3D EFI_OUT_OF_RESOURCES; >=20 > + goto EXIT; >=20 > + } >=20 > + AddTestCase( InternalTests, >=20 > + "Policy matching should use name and GUID", > "VarPolicy.Internal.NameGuid", >=20 > + PoliciesShouldMatchByNameAndGuid, LibInitMocked, LibClea= nup, > NULL ); >=20 > + AddTestCase( InternalTests, >=20 > + "# sign wildcards should match digits", > "VarPolicy.Internal.WildDigits", >=20 > + WildcardPoliciesShouldMatchDigits, LibInitMocked, LibCle= anup, > NULL ); >=20 > + AddTestCase( InternalTests, >=20 > + "Digit wildcards should check edge cases", > "VarPolicy.Internal.WildDigitsAdvanced", >=20 > + WildcardPoliciesShouldMatchDigitsAdvanced, LibInitMocked= , > LibCleanup, NULL ); >=20 > + AddTestCase( InternalTests, >=20 > + "Empty names should match an entire namespace", > "VarPolicy.Internal.WildNamespace", >=20 > + WildcardPoliciesShouldMatchNamespaces, LibInitMocked, > LibCleanup, NULL ); >=20 > + AddTestCase( InternalTests, >=20 > + "Match priority should weight correctly based on wildcar= ds", > "VarPolicy.Internal.Priorities", >=20 > + MatchPrioritiesShouldFollowRules, LibInitMocked, LibClea= nup, > NULL ); >=20 > +#endif // INTERNAL_UNIT_TEST >=20 > + >=20 > + Status =3D CreateUnitTestSuite( &PolicyTests, Framework, "Variable Pol= icy > Manipulation Tests", "VarPolicy.Policy", NULL, NULL ); >=20 > + if (EFI_ERROR( Status )) >=20 > + { >=20 > + DEBUG((DEBUG_ERROR, "Failed in CreateUnitTestSuite for > PolicyTests\n")); >=20 > + Status =3D EFI_OUT_OF_RESOURCES; >=20 > + goto EXIT; >=20 > + } >=20 > + AddTestCase( PolicyTests, >=20 > + "RegisterShouldAllowNamespaceWildcards", > "VarPolicy.Policy.AllowNamespace", >=20 > + RegisterShouldAllowNamespaceWildcards, LibInitMocked, > LibCleanup, NULL ); >=20 > + AddTestCase( PolicyTests, >=20 > + "RegisterShouldAllowStateVarsForNamespaces", > "VarPolicy.Policy.AllowStateNamespace", >=20 > + RegisterShouldAllowStateVarsForNamespaces, LibInitMocked= , > LibCleanup, NULL ); >=20 > + AddTestCase( PolicyTests, >=20 > + "RegisterShouldRejectNullPointers", "VarPolicy.Policy.Nu= llPointers", >=20 > + RegisterShouldRejectNullPointers, LibInitMocked, LibClea= nup, > NULL ); >=20 > + AddTestCase( PolicyTests, >=20 > + "RegisterShouldRejectBadRevisions", > "VarPolicy.Policy.BadRevisions", >=20 > + RegisterShouldRejectBadRevisions, LibInitMocked, LibClea= nup, > NULL ); >=20 > + AddTestCase( PolicyTests, >=20 > + "RegisterShouldRejectBadSizes", "VarPolicy.Policy.BadSiz= es", >=20 > + RegisterShouldRejectBadSizes, LibInitMocked, LibCleanup,= NULL ); >=20 > + AddTestCase( PolicyTests, >=20 > + "RegisterShouldRejectBadOffsets", "VarPolicy.Policy.BadO= ffsets", >=20 > + RegisterShouldRejectBadOffsets, LibInitMocked, LibCleanu= p, NULL ); >=20 > + AddTestCase( PolicyTests, >=20 > + "RegisterShouldRejectMissingStateStrings", > "VarPolicy.Policy.MissingStateString", >=20 > + RegisterShouldRejectMissingStateStrings, LibInitMocked, > LibCleanup, NULL ); >=20 > + AddTestCase( PolicyTests, >=20 > + "RegisterShouldRejectStringsMissingNull", > "VarPolicy.Policy.MissingNull", >=20 > + RegisterShouldRejectStringsMissingNull, LibInitMocked, L= ibCleanup, > NULL ); >=20 > + AddTestCase( PolicyTests, >=20 > + "RegisterShouldRejectMalformedStrings", > "VarPolicy.Policy.MalformedStrings", >=20 > + RegisterShouldRejectMalformedStrings, LibInitMocked, Lib= Cleanup, > NULL ); >=20 > + AddTestCase( PolicyTests, >=20 > + "RegisterShouldRejectUnpackedPolicies", > "VarPolicy.Policy.PolicyPacking", >=20 > + RegisterShouldRejectUnpackedPolicies, LibInitMocked, Lib= Cleanup, > NULL ); >=20 > + AddTestCase( PolicyTests, >=20 > + "RegisterShouldRejectInvalidNameCharacters", > "VarPolicy.Policy.InvalidCharacters", >=20 > + RegisterShouldRejectInvalidNameCharacters, LibInitMocked= , > LibCleanup, NULL ); >=20 > + AddTestCase( PolicyTests, >=20 > + "RegisterShouldRejectBadPolicyConstraints", > "VarPolicy.Policy.BadConstraints", >=20 > + RegisterShouldRejectBadPolicyConstraints, LibInitMocked, > LibCleanup, NULL ); >=20 > + AddTestCase( PolicyTests, >=20 > + "RegisterShouldRejectUnknownLockPolicies", > "VarPolicy.Policy.BadLocks", >=20 > + RegisterShouldRejectUnknownLockPolicies, LibInitMocked, > LibCleanup, NULL ); >=20 > + AddTestCase( PolicyTests, >=20 > + "RegisterShouldRejectPolicesWithTooManyWildcards", > "VarPolicy.Policy.TooManyWildcards", >=20 > + RegisterShouldRejectPolicesWithTooManyWildcards, LibInit= Mocked, > LibCleanup, NULL ); >=20 > + AddTestCase( PolicyTests, >=20 > + "RegisterShouldRejectDuplicatePolicies", > "VarPolicy.Policy.DuplicatePolicies", >=20 > + RegisterShouldRejectDuplicatePolicies, LibInitMocked, Li= bCleanup, > NULL ); >=20 > + AddTestCase( PolicyTests, >=20 > + "Variables that exceed min or max sizes should be reject= ed", > "VarPolicy.Policy.MinMax", >=20 > + MinAndMaxSizePoliciesShouldBeHonored, LibInitMocked, > LibCleanup, NULL ); >=20 > + AddTestCase( PolicyTests, >=20 > + "AttributeMustPoliciesShouldBeHonored", > "VarPolicy.Policy.AttrMust", >=20 > + AttributeMustPoliciesShouldBeHonored, LibInitMocked, Lib= Cleanup, > NULL ); >=20 > + AddTestCase( PolicyTests, >=20 > + "AttributeCantPoliciesShouldBeHonored", > "VarPolicy.Policy.AttrCant", >=20 > + AttributeCantPoliciesShouldBeHonored, LibInitMocked, Lib= Cleanup, > NULL ); >=20 > + AddTestCase( PolicyTests, >=20 > + "VariablesShouldBeDeletableRegardlessOfSize", > "VarPolicy.Policy.DeleteIgnoreSize", >=20 > + VariablesShouldBeDeletableRegardlessOfSize, LibInitMocke= d, > LibCleanup, NULL ); >=20 > + AddTestCase( PolicyTests, >=20 > + "LockNowPoliciesShouldBeHonored", > "VarPolicy.Policy.VARIABLE_POLICY_TYPE_LOCK_NOW", >=20 > + LockNowPoliciesShouldBeHonored, LibInitMocked, LibCleanu= p, > NULL ); >=20 > + AddTestCase( PolicyTests, >=20 > + "LockOnCreatePoliciesShouldBeHonored", > "VarPolicy.Policy.VARIABLE_POLICY_TYPE_LOCK_ON_CREATE", >=20 > + LockOnCreatePoliciesShouldBeHonored, LibInitMocked, LibC= leanup, > NULL ); >=20 > + AddTestCase( PolicyTests, >=20 > + "LockOnStatePoliciesShouldBeHonored", > "VarPolicy.Policy.LockState", >=20 > + LockOnStatePoliciesShouldBeHonored, LibInitMocked, LibCl= eanup, > NULL ); >=20 > + AddTestCase( PolicyTests, >=20 > + "LockOnStatePoliciesShouldApplyToNamespaces", > "VarPolicy.Policy.NamespaceLockState", >=20 > + LockOnStatePoliciesShouldApplyToNamespaces, LibInitMocke= d, > LibCleanup, NULL ); >=20 > + AddTestCase( PolicyTests, >=20 > + "LockOnStateShouldHandleErrorsGracefully", > "VarPolicy.Policy.LockStateErrors", >=20 > + LockOnStateShouldHandleErrorsGracefully, LibInitMocked, > LibCleanup, NULL ); >=20 > + AddTestCase( PolicyTests, >=20 > + "BestMatchPriorityShouldBeObeyed", "VarPolicy.Policy.Bes= tMatch", >=20 > + BestMatchPriorityShouldBeObeyed, LibInitMocked, LibClean= up, > NULL ); >=20 > + >=20 > + Status =3D CreateUnitTestSuite( &UtilityTests, Framework, "Variable Po= licy > Utility Tests", "VarPolicy.Utility", NULL, NULL ); >=20 > + if (EFI_ERROR( Status )) >=20 > + { >=20 > + DEBUG((DEBUG_ERROR, "Failed in CreateUnitTestSuite for > UtilityTests\n")); >=20 > + Status =3D EFI_OUT_OF_RESOURCES; >=20 > + goto EXIT; >=20 > + } >=20 > + AddTestCase( UtilityTests, >=20 > + "API commands that change state should not respond after > interface is locked", "VarPolicy.Utility.InterfaceLock", >=20 > + ShouldBeAbleToLockInterface, LibInitMocked, LibCleanup, = NULL ); >=20 > + AddTestCase( UtilityTests, >=20 > + "All policies should pass once enforcement is disabled", > "VarPolicy.Utility.DisableEnforcement", >=20 > + ShouldBeAbleToDisablePolicyEnforcement, LibInitMocked, > LibCleanup, NULL ); >=20 > + AddTestCase( UtilityTests, >=20 > + "Disabling enforcement twice should produce an error", > "VarPolicy.Utility.DisableEnforcementTwice", >=20 > + ShouldNotBeAbleToDisablePoliciesTwice, LibInitMocked, > LibCleanup, NULL ); >=20 > + AddTestCase( UtilityTests, >=20 > + "ShouldBeAbleToAddNewPoliciesAfterDisabled", > "VarPolicy.Utility.AddAfterDisable", >=20 > + ShouldBeAbleToAddNewPoliciesAfterDisabled, LibInitMocked= , > LibCleanup, NULL ); >=20 > + AddTestCase( UtilityTests, >=20 > + "ShouldBeAbleToLockAfterDisabled", > "VarPolicy.Utility.LockAfterDisable", >=20 > + ShouldBeAbleToLockAfterDisabled, LibInitMocked, LibClean= up, > NULL ); >=20 > + AddTestCase( UtilityTests, >=20 > + "Should be able to dump the policy table", > "VarPolicy.Utility.DumpTable", >=20 > + ShouldBeAbleToDumpThePolicyTable, LibInitMocked, LibClea= nup, > NULL ); >=20 > + AddTestCase( UtilityTests, >=20 > + "ShouldBeAbleToDumpThePolicyTableAfterDisabled", > "VarPolicy.Utility.DumpTableAfterDisable", >=20 > + ShouldBeAbleToDumpThePolicyTableAfterDisabled, LibInitMo= cked, > LibCleanup, NULL ); >=20 > + >=20 > + >=20 > + // >=20 > + // Execute the tests. >=20 > + // >=20 > + Status =3D RunAllTestSuites( Framework ); >=20 > + >=20 > +EXIT: >=20 > + if (Framework !=3D NULL) >=20 > + { >=20 > + FreeUnitTestFramework( Framework ); >=20 > + } >=20 > + >=20 > + return Status; >=20 > +} >=20 > 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 >=20 > +Business logic for Variable Policy enforcement. >=20 > + >=20 > +Copyright (c) Microsoft Corporation. >=20 > +SPDX-License-Identifier: BSD-2-Clause-Patent >=20 > + >=20 > +**/ >=20 > + >=20 > +#ifndef _VARIABLE_POLICY_LIB_H_ >=20 > +#define _VARIABLE_POLICY_LIB_H_ >=20 > + >=20 > +#include >=20 > + >=20 > +/** >=20 > + This API function validates and registers a new policy with >=20 > + the policy enforcement engine. >=20 > + >=20 > + @param[in] NewPolicy Pointer to the incoming policy structure. >=20 > + >=20 > + @retval EFI_SUCCESS >=20 > + @retval EFI_INVALID_PARAMETER NewPolicy is NULL or is internally > inconsistent. >=20 > + @retval EFI_ALREADY_STARTED An identical matching policy alrea= dy > exists. >=20 > + @retval EFI_WRITE_PROTECTED The interface has been locked unti= l > the next reboot. >=20 > + @retval EFI_UNSUPPORTED Policy enforcement has been disabl= ed. > No reason to add more policies. >=20 > + @retval EFI_ABORTED A calculation error has prevented = this > function from completing. >=20 > + @retval EFI_OUT_OF_RESOURCES Cannot grow the table to hold any > more policies. >=20 > + @retval EFI_NOT_READY Library has not yet been initializ= ed. >=20 > + >=20 > +**/ >=20 > +EFI_STATUS >=20 > +EFIAPI >=20 > +RegisterVariablePolicy ( >=20 > + IN CONST VARIABLE_POLICY_ENTRY *NewPolicy >=20 > + ); >=20 > + >=20 > + >=20 > +/** >=20 > + This API function checks to see whether the parameters to SetVariable > would >=20 > + be allowed according to the current variable policies. >=20 > + >=20 > + @param[in] VariableName Same as EFI_SET_VARIABLE. >=20 > + @param[in] VendorGuid Same as EFI_SET_VARIABLE. >=20 > + @param[in] Attributes Same as EFI_SET_VARIABLE. >=20 > + @param[in] DataSize Same as EFI_SET_VARIABLE. >=20 > + @param[in] Data Same as EFI_SET_VARIABLE. >=20 > + >=20 > + @retval EFI_SUCCESS A matching policy allows this upda= te. >=20 > + @retval EFI_SUCCESS There are currently no policies th= at restrict > this update. >=20 > + @retval EFI_SUCCESS The protections have been disable = until the > next reboot. >=20 > + @retval EFI_WRITE_PROTECTED Variable is currently locked. >=20 > + @retval EFI_INVALID_PARAMETER Attributes or size are invalid. >=20 > + @retval EFI_ABORTED A lock policy exists, but an error= prevented > evaluation. >=20 > + @retval EFI_NOT_READY Library has not been initialized. >=20 > + >=20 > +**/ >=20 > +EFI_STATUS >=20 > +EFIAPI >=20 > +ValidateSetVariable ( >=20 > + IN CHAR16 *VariableName, >=20 > + IN EFI_GUID *VendorGuid, >=20 > + IN UINT32 Attributes, >=20 > + IN UINTN DataSize, >=20 > + IN VOID *Data >=20 > + ); >=20 > + >=20 > + >=20 > +/** >=20 > + This API function disables the variable policy enforcement. If it's >=20 > + already been called once, will return EFI_ALREADY_STARTED. >=20 > + >=20 > + @retval EFI_SUCCESS >=20 > + @retval EFI_ALREADY_STARTED Has already been called once this bo= ot. >=20 > + @retval EFI_WRITE_PROTECTED Interface has been locked until rebo= ot. >=20 > + @retval EFI_WRITE_PROTECTED Interface option is disabled by plat= form > PCD. >=20 > + @retval EFI_NOT_READY Library has not yet been initialized. >=20 > + >=20 > +**/ >=20 > +EFI_STATUS >=20 > +EFIAPI >=20 > +DisableVariablePolicy ( >=20 > + VOID >=20 > + ); >=20 > + >=20 > + >=20 > +/** >=20 > + This API function will dump the entire contents of the variable policy= table. >=20 > + >=20 > + Similar to GetVariable, the first call can be made with a 0 size and i= t will > return >=20 > + the size of the buffer required to hold the entire table. >=20 > + >=20 > + @param[out] Policy Pointer to the policy buffer. Can be NULL if S= ize is 0. >=20 > + @param[in,out] Size On input, the size of the output buffer. On ou= tput, > the size >=20 > + of the data returned. >=20 > + >=20 > + @retval EFI_SUCCESS Policy data is in the output buffe= r and Size > has been updated. >=20 > + @retval EFI_INVALID_PARAMETER Size is NULL, or Size is non-zero = and > Policy is NULL. >=20 > + @retval EFI_BUFFER_TOO_SMALL Size is insufficient to hold polic= y. Size > updated with required size. >=20 > + @retval EFI_NOT_READY Library has not yet been initializ= ed. >=20 > + >=20 > +**/ >=20 > +EFI_STATUS >=20 > +EFIAPI >=20 > +DumpVariablePolicy ( >=20 > + OUT UINT8 *Policy, >=20 > + IN OUT UINT32 *Size >=20 > + ); >=20 > + >=20 > + >=20 > +/** >=20 > + This API function returns whether or not the policy engine is >=20 > + currently being enforced. >=20 > + >=20 > + @retval TRUE >=20 > + @retval FALSE >=20 > + @retval FALSE Library has not yet been initialized. >=20 > + >=20 > +**/ >=20 > +BOOLEAN >=20 > +EFIAPI >=20 > +IsVariablePolicyEnabled ( >=20 > + VOID >=20 > + ); >=20 > + >=20 > + >=20 > +/** >=20 > + This API function locks the interface so that no more policy updates >=20 > + can be performed or changes made to the enforcement until the next > boot. >=20 > + >=20 > + @retval EFI_SUCCESS >=20 > + @retval EFI_NOT_READY Library has not yet been initialized. >=20 > + >=20 > +**/ >=20 > +EFI_STATUS >=20 > +EFIAPI >=20 > +LockVariablePolicy ( >=20 > + VOID >=20 > + ); >=20 > + >=20 > + >=20 > +/** >=20 > + This API function returns whether or not the policy interface is locke= d >=20 > + for the remainder of the boot. >=20 > + >=20 > + @retval TRUE >=20 > + @retval FALSE >=20 > + @retval FALSE Library has not yet been initialized. >=20 > + >=20 > +**/ >=20 > +BOOLEAN >=20 > +EFIAPI >=20 > +IsVariablePolicyInterfaceLocked ( >=20 > + VOID >=20 > + ); >=20 > + >=20 > + >=20 > +/** >=20 > + This helper function initializes the library and sets >=20 > + up any required internal structures or handlers. >=20 > + >=20 > + Also registers the internal pointer for the GetVariable helper. >=20 > + >=20 > + @param[in] GetVariableHelper A function pointer matching the > EFI_GET_VARIABLE prototype that will be used to >=20 > + check policy criteria that involve the existence of ot= her variables. >=20 > + >=20 > + @retval EFI_SUCCESS >=20 > + @retval EFI_ALREADY_STARTED The initialize function has been cal= led > more than once without a call to >=20 > + deinitialize. >=20 > + >=20 > +**/ >=20 > +EFI_STATUS >=20 > +EFIAPI >=20 > +InitVariablePolicyLib ( >=20 > + IN EFI_GET_VARIABLE GetVariableHelper >=20 > + ); >=20 > + >=20 > + >=20 > +/** >=20 > + This helper function returns whether or not the library is currently > initialized. >=20 > + >=20 > + @retval TRUE >=20 > + @retval FALSE >=20 > + >=20 > +**/ >=20 > +BOOLEAN >=20 > +EFIAPI >=20 > +IsVariablePolicyLibInitialized ( >=20 > + VOID >=20 > + ); >=20 > + >=20 > + >=20 > +/** >=20 > + This helper function tears down the library. >=20 > + >=20 > + Should generally only be used for test harnesses. >=20 > + >=20 > + @retval EFI_SUCCESS >=20 > + @retval EFI_NOT_READY Deinitialize was called without first ca= lling > initialize. >=20 > + >=20 > +**/ >=20 > +EFI_STATUS >=20 > +EFIAPI >=20 > +DeinitVariablePolicyLib ( >=20 > + VOID >=20 > + ); >=20 > + >=20 > + >=20 > +#endif // _VARIABLE_POLICY_LIB_H_ >=20 > 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/VariablePolicyLib.inf > @@ -0,0 +1,44 @@ > +## @file VariablePolicyLib.inf >=20 > +# Business logic for Variable Policy enforcement. >=20 > +# >=20 > +## >=20 > +# Copyright (c) Microsoft Corporation. >=20 > +# SPDX-License-Identifier: BSD-2-Clause-Patent >=20 > +## >=20 > + >=20 > + >=20 > +[Defines] >=20 > + INF_VERSION =3D 0x00010017 >=20 > + BASE_NAME =3D VariablePolicyLib >=20 > + FILE_GUID =3D E9ECD342-159A-4F24-9FDF-65724027C594 >=20 > + VERSION_STRING =3D 1.0 >=20 > + MODULE_TYPE =3D DXE_DRIVER >=20 > + LIBRARY_CLASS =3D VariablePolicyLib|DXE_DRIVER DXE_SMM_DRIVER > MM_STANDALONE >=20 > + >=20 > +# >=20 > +# The following information is for reference only and not required by th= e > build tools. >=20 > +# >=20 > +# VALID_ARCHITECTURES =3D ANY >=20 > +# >=20 > + >=20 > + >=20 > +[Sources] >=20 > + VariablePolicyLib.c >=20 > + VariablePolicyExtraInitNull.c >=20 > + >=20 > + >=20 > +[Packages] >=20 > + MdePkg/MdePkg.dec >=20 > + MdeModulePkg/MdeModulePkg.dec >=20 > + >=20 > + >=20 > +[LibraryClasses] >=20 > + DebugLib >=20 > + BaseMemoryLib >=20 > + MemoryAllocationLib >=20 > + SafeIntLib >=20 > + PcdLib >=20 > + >=20 > + >=20 > +[Pcd] >=20 > + > gEfiMdeModulePkgTokenSpaceGuid.PcdAllowVariablePolicyEnforcementDis > able ## CONSUMES >=20 > 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/VariablePolicyLib.uni > @@ -0,0 +1,12 @@ > +// /** @file >=20 > +// VariablePolicyLib.uni >=20 > +// >=20 > +// Copyright (c) Microsoft Corporation. >=20 > +// SPDX-License-Identifier: BSD-2-Clause-Patent >=20 > +// >=20 > +// **/ >=20 > + >=20 > + >=20 > +#string STR_MODULE_ABSTRACT #language en-US "Library contain= ing > the business logic for the VariablePolicy engine" >=20 > + >=20 > +#string STR_MODULE_DESCRIPTION #language en-US "Library > containing the business logic for the VariablePolicy engine" >=20 > 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 >=20 > +# Business logic for Variable Policy enforcement. >=20 > +# This instance is specifically for RuntimeDxe and contains >=20 > +# extra routines to register for VirtualAddressChangeEvents. >=20 > +# >=20 > +# Copyright (c) Microsoft Corporation. >=20 > +# SPDX-License-Identifier: BSD-2-Clause-Patent >=20 > +## >=20 > + >=20 > + >=20 > +[Defines] >=20 > + INF_VERSION =3D 0x00010017 >=20 > + BASE_NAME =3D VariablePolicyLibRuntimeDxe >=20 > + FILE_GUID =3D 205F7F0E-8EAC-4914-8390-1B90DD7E2A27 >=20 > + VERSION_STRING =3D 1.0 >=20 > + MODULE_TYPE =3D DXE_RUNTIME_DRIVER >=20 > + LIBRARY_CLASS =3D VariablePolicyLib|DXE_RUNTIME_DRIVER >=20 > + >=20 > +# >=20 > +# The following information is for reference only and not required by th= e > build tools. >=20 > +# >=20 > +# VALID_ARCHITECTURES =3D ANY >=20 > +# >=20 > + >=20 > + >=20 > +[Sources] >=20 > + VariablePolicyLib.c >=20 > + VariablePolicyExtraInitRuntimeDxe.c >=20 > + >=20 > + >=20 > +[Packages] >=20 > + MdePkg/MdePkg.dec >=20 > + MdeModulePkg/MdeModulePkg.dec >=20 > + >=20 > + >=20 > +[LibraryClasses] >=20 > + DebugLib >=20 > + BaseMemoryLib >=20 > + MemoryAllocationLib >=20 > + SafeIntLib >=20 > + UefiBootServicesTableLib >=20 > + UefiRuntimeServicesTableLib >=20 > + PcdLib >=20 > + >=20 > + >=20 > +[Pcd] >=20 > + > gEfiMdeModulePkgTokenSpaceGuid.PcdAllowVariablePolicyEnforcementDis > able ## CONSUMES >=20 > + >=20 > + >=20 > +[Guids] >=20 > + gEfiEventVirtualAddressChangeGuid >=20 > 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 >=20 > +# UnitTest for... >=20 > +# Business logic for Variable Policy enforcement. >=20 > +# >=20 > +# Copyright (c) Microsoft Corporation. >=20 > +# SPDX-License-Identifier: BSD-2-Clause-Patent >=20 > +## >=20 > + >=20 > + >=20 > +[Defines] >=20 > + INF_VERSION =3D 0x00010006 >=20 > + BASE_NAME =3D VariablePolicyUnitTest >=20 > + FILE_GUID =3D 1200A2E4-D756-418C-9768-528C2D181A9= 8 >=20 > + MODULE_TYPE =3D HOST_APPLICATION >=20 > + VERSION_STRING =3D 1.0 >=20 > + >=20 > +# >=20 > +# The following information is for reference only and not required by th= e > build tools. >=20 > +# >=20 > +# VALID_ARCHITECTURES =3D IA32 X64 ARM AARCH64 >=20 > +# >=20 > + >=20 > +[Sources] >=20 > + VariablePolicyUnitTest.c >=20 > + >=20 > + >=20 > +[Packages] >=20 > + MdePkg/MdePkg.dec >=20 > + MdeModulePkg/MdeModulePkg.dec >=20 > + UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec >=20 > + >=20 > + >=20 > +[LibraryClasses] >=20 > + BaseLib >=20 > + DebugLib >=20 > + UnitTestLib >=20 > + PrintLib >=20 > + VariablePolicyLib >=20 > + BaseMemoryLib >=20 > + MemoryAllocationLib >=20 > 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. >=20 > ResetSystemLib|Include/Library/ResetSystemLib.h >=20 >=20 >=20 > + ## @libraryclass Business logic for storing and testing variable pol= icies >=20 > + VariablePolicyLib|Include/Library/VariablePolicyLib.h >=20 > + >=20 > ## @libraryclass Defines a set of helper functions for resetting the= system. >=20 > ResetUtilityLib|Include/Library/ResetUtilityLib.h >=20 >=20 >=20 > 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 @@ > # >=20 > # (C) Copyright 2014 Hewlett-Packard Development Company, L.P.
>=20 > # Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved.
>=20 > +# Copyright (c) Microsoft Corporation. >=20 > # >=20 > # SPDX-License-Identifier: BSD-2-Clause-Patent >=20 > # >=20 > @@ -58,6 +59,7 @@ [LibraryClasses] > DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf >=20 >=20 > DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTabl > eLib.inf >=20 >=20 > UefiBootManagerLib|MdeModulePkg/Library/UefiBootManagerLib/UefiBoo > tManagerLib.inf >=20 > + > VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLi > b.inf >=20 > # >=20 > # Generic Modules >=20 > # >=20 > @@ -129,6 +131,7 @@ [LibraryClasses.common.DXE_RUNTIME_DRIVER] > DebugLib|MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf >=20 >=20 > LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxDxeLib.in > f >=20 >=20 > CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsule > Lib.inf >=20 > + > VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLi > bRuntimeDxe.inf >=20 >=20 >=20 > [LibraryClasses.common.SMM_CORE] >=20 > HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf >=20 > @@ -306,6 +309,8 @@ [Components] > MdeModulePkg/Library/BootLogoLib/BootLogoLib.inf >=20 >=20 > MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull > .inf >=20 > MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf >=20 > + MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf >=20 > + > MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf >=20 > MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf >=20 > MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLib.inf >=20 > MdeModulePkg/Library/VarCheckPcdLib/VarCheckPcdLib.inf >=20 > 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] >=20 >=20 > !include UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc >=20 >=20 >=20 > +[LibraryClasses] >=20 > + SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf >=20 > + >=20 > [Components] >=20 >=20 > MdeModulePkg/Library/DxeResetSystemLib/UnitTest/MockUefiRuntimeSer > vicesTableLib.inf >=20 >=20 >=20 > # >=20 > # Build MdeModulePkg HOST_APPLICATION Tests >=20 > # >=20 > + > MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePo > licyUnitTest.inf { >=20 > + >=20 > + > VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLi > b.inf >=20 > + >=20 > + >=20 > + > gEfiMdeModulePkgTokenSpaceGuid.PcdAllowVariablePolicyEnforcementDis > able|TRUE >=20 > + } >=20 > + >=20 >=20 > MdeModulePkg/Library/DxeResetSystemLib/UnitTest/DxeResetSystemLibU > nitTestHost.inf { >=20 > >=20 >=20 > ResetSystemLib|MdeModulePkg/Library/DxeResetSystemLib/DxeResetSyst > emLib.inf >=20 > -- > 2.26.2.windows.1.8.g01c50adf56.20200515075929 >=20 >=20 > -=3D-=3D-=3D-=3D-=3D-=3D > Groups.io Links: You receive all messages sent to this group. >=20 > View/Reply Online (#61588): https://edk2.groups.io/g/devel/message/61588 > Mute This Topic: https://groups.io/mt/75057697/1768738 > Group Owner: devel+owner@edk2.groups.io > Unsubscribe: https://edk2.groups.io/g/devel/unsub [dandan.bi@intel.com] > -=3D-=3D-=3D-=3D-=3D-=3D