From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) by mx.groups.io with SMTP id smtpd.web10.2890.1587546868267566007 for ; Wed, 22 Apr 2020 02:14:28 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@intel.onmicrosoft.com header.s=selector2-intel-onmicrosoft-com header.b=fSpF6O9X; spf=pass (domain: intel.com, ip: 192.55.52.93, mailfrom: guomin.jiang@intel.com) IronPort-SDR: f6+U1AyvUXNDH/SX5JuZDP6c9vBO7sqljqgbbhWuwv2RVl6iHRSYLgOhE7ui86lsreOXGmVwsn aEjrsRfQJVZw== X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga001.jf.intel.com ([10.7.209.18]) by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Apr 2020 02:14:27 -0700 IronPort-SDR: TvQba+cSMMBEgT89BQohFTqK6Is3E++yln2hb1srzc02C5jWgrV/l1jTJFrqjjit9o0LHN55HL zkgp+yjE0sFQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.72,413,1580803200"; d="scan'208";a="334560525" Received: from orsmsx102.amr.corp.intel.com ([10.22.225.129]) by orsmga001.jf.intel.com with ESMTP; 22 Apr 2020 02:14:27 -0700 Received: from orsmsx125.amr.corp.intel.com (10.22.240.125) by ORSMSX102.amr.corp.intel.com (10.22.225.129) with Microsoft SMTP Server (TLS) id 14.3.439.0; Wed, 22 Apr 2020 02:14:26 -0700 Received: from ORSEDG002.ED.cps.intel.com (10.7.248.5) by ORSMSX125.amr.corp.intel.com (10.22.240.125) with Microsoft SMTP Server (TLS) id 14.3.439.0; Wed, 22 Apr 2020 02:14:27 -0700 Received: from NAM10-DM6-obe.outbound.protection.outlook.com (104.47.58.106) by edgegateway.intel.com (134.134.137.101) with Microsoft SMTP Server (TLS) id 14.3.439.0; Wed, 22 Apr 2020 02:14:26 -0700 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=GQ33T0dvdo9KPB6pgtIToI7LM5tB+1CFsF23zZcJPTShDwr0eZkgkn6bsk7wjdCWniOyIraiSaj61RWlOGi4hWCDMs43o+p0b9909Zya3gZcGFe7EEceP4IpUPyaAaBuzO+uSKi/xQWj7ECd9HB3V+ZyaUUuK6MWiHv1qhoEBPLL4TbJ1O1C6D2Z1/t9bLqc+wmWgPZDgZMDaYTCmP3qnU9wIXIg549AVBi2abM4e9TZ0QalyZrXZTpxDNs2hvja5WN0ODs2CKqGKPoNsp7POyOrgwK8iAyxzkE/dLu5DjVOqhWXIvsOARbK/gjk7KQsUqhHJhCSJ1UEU47OqgSPHA== 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=ic8bbB0Xt8/t9WO1OeNvQErk7OfIBkWHY9C4arflQTQ=; b=j/EwOrrJvCLnYrcERCxJltc3uadlnokvRhs4qMiEjBciTcqgaBhl62+jXvMjsM1pDsTWuaF4Wx+oiAEdSHbkjnStn1ecCa/UyajDjpXzGmuJxJBurQYPccf0IbT8IS99NlGqVQaf9s/s/ERtr+dHE9i0EPDwihplvotO+KwPgvKtyzKVTu2XdaiGKqJ3csOa735sdiHASLbWmM3CpG9GyWII2mCUjVaC/5jnS457o3n5zyNwob1FOSiBHQEtL+vlLGztXtVKVT6zrPBCSJ57jf1cyRTeISGgOhXvAm6vfFSk8veaQ7zbp3ezFt50CPJ4A3YKCfwX1Er9oGKv3K2kaQ== 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=ic8bbB0Xt8/t9WO1OeNvQErk7OfIBkWHY9C4arflQTQ=; b=fSpF6O9XG5hkrQ5MDec9MDzT9uLuvY5NzJNXRZUl+UyHM6Ai9C37ciVgs1K/lZLWv4Akm0lU2DZBaFb6MEYHWJngq3mRmhR0OdlVKUR+GIRy1yRSB+jC0eWx+R87CLcp77YBfpV4m3sthNGDJ6AOHtvrPW5rcglC/Glo6EQRbzM= Received: from DM6PR11MB2955.namprd11.prod.outlook.com (2603:10b6:5:65::31) by DM6PR11MB2762.namprd11.prod.outlook.com (2603:10b6:5:c8::13) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.2921.29; Wed, 22 Apr 2020 09:14:24 +0000 Received: from DM6PR11MB2955.namprd11.prod.outlook.com ([fe80::ccd4:4b0d:535a:58be]) by DM6PR11MB2955.namprd11.prod.outlook.com ([fe80::ccd4:4b0d:535a:58be%7]) with mapi id 15.20.2921.030; Wed, 22 Apr 2020 09:14:24 +0000 From: "Guomin Jiang" To: "devel@edk2.groups.io" , "michael.kubacki@outlook.com" CC: "Wang, Jian J" , "Wu, Hao A" , "Gao, Liming" Subject: Re: [edk2-devel] [PATCH v1 2/9] MdeModulePkg: Define the VariablePolicyLib Thread-Topic: [edk2-devel] [PATCH v1 2/9] MdeModulePkg: Define the VariablePolicyLib Thread-Index: AQHWD2dQdy5XFdOM8EGEuf/EZ/29qKiE6iTw Date: Wed, 22 Apr 2020 09:14:20 +0000 Message-ID: References: <20200410183802.21192-1-michael.kubacki@outlook.com> In-Reply-To: Accept-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: dlp-version: 11.2.0.6 dlp-product: dlpe-windows dlp-reaction: no-action authentication-results: spf=none (sender IP is ) smtp.mailfrom=guomin.jiang@intel.com; x-originating-ip: [192.55.52.205] x-ms-publictraffictype: Email x-ms-office365-filtering-correlation-id: ff5a409f-7f42-45b6-7c31-08d7e69d8d10 x-ms-traffictypediagnostic: DM6PR11MB2762: x-ld-processed: 46c98d88-e344-4ed4-8496-4ed7712e255d,ExtAddr x-ms-exchange-transport-forked: True x-microsoft-antispam-prvs: x-ms-oob-tlc-oobclassifiers: OLM:9508; x-forefront-prvs: 03818C953D x-forefront-antispam-report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:DM6PR11MB2955.namprd11.prod.outlook.com;PTR:;CAT:NONE;SFTY:;SFS:(10019020)(376002)(366004)(39860400002)(396003)(136003)(346002)(33656002)(53546011)(55016002)(316002)(6666004)(6506007)(8936002)(26005)(54906003)(110136005)(4326008)(81156014)(7696005)(107886003)(86362001)(478600001)(45080400002)(966005)(2906002)(30864003)(8676002)(19627235002)(186003)(5660300002)(9686003)(71200400001)(66556008)(66476007)(66446008)(66946007)(52536014)(64756008)(76116006)(559001)(579004)(569008);DIR:OUT;SFP:1102; x-ms-exchange-senderadcheck: 1 x-microsoft-antispam: BCL:0; x-microsoft-antispam-message-info: PzIsNHvdrw/4R9HGe7U3iYk37E/8PSMg/684QNbAi9jBltNSGjx6GYgFI2TGsD6MD7mO+UqWioNi1aZGxJJZnXdNIQ7bxByL/8dUpFTRFOYsROLu0qVtFlwP9yCjMUcJy8Zpg3fvgX0FzjSNdkg6Gmx57Pxby4i28dL1qqiFtyBTPcvi6LkGVEBOmq04NWaJdAZ3PVjyIPqDFQ0ftGswNx+Jgnjw6yvGUCQG+XLU1P2x+KXwntUEY7sJO3kzFg4+ZViUapJOvkU8dCevKr96JkV89muMHsoMJm4rz5yHD5mEBABrLB0r9BuZ4eARcXlcSr0CDBuAdN5jUD/560oRf5pPPPqN1sb9SxWUjZdGD9ntbUB4I6cI6yDbZlXlLrYRsUspvj5ZOoxKEgt/bTX/Y14V7rCwMF8ZZN54yQhRGSsdCWFMbvnUfFoL27uKvMpP3lvENBGgPVESuzpd6wu5xdY4sxqrGWuQz0gwMrkJUt3VnMkobs58XsebYqP7o3HV0wZHtEk31Cm+W+yH+MBCYJIH6z+3OKTqSa7V0PW+eOBByIK8EgPTtRedcWxnqWFu x-ms-exchange-antispam-messagedata: 7V/pTGbsJsNRC8nGSHtHOgPtxQ8OKro/p7CgDMh9sEJ+tyJg2EZjiDSHjKrJurtz/RnPRvVdNCB6nSKVAPcgb5GdguKYWAc1mPq3mwKbuMsUSww5jwOTGcScfU5fHylMByiFGm/CQilEE6HvWAgGaQ== MIME-Version: 1.0 X-MS-Exchange-CrossTenant-Network-Message-Id: ff5a409f-7f42-45b6-7c31-08d7e69d8d10 X-MS-Exchange-CrossTenant-originalarrivaltime: 22 Apr 2020 09:14:20.2182 (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: 55IOeItNLCcJ82E0qm42VexH1lMJmRvCLJVYxPOCdpIRaT8xKaS63Ax3Ok1KSssSaU3CErz+85ZnQOnB963RTQ== X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM6PR11MB2762 Return-Path: guomin.jiang@intel.com X-OriginatorOrg: intel.com Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable It is better that pay more attention to code style, for example Replace NewTable =3D AllocatePool( NewSize ); With space NewTable =3D AllocatePool (NewSize); Refer https://github.com/tianocore/tianocore.github.io/wiki/Code-Style-C f= or simple principle and https://edk2-docs.gitbooks.io/edk-ii-c-coding-stand= ards-specification/content/ for detail principle. Below code can be optimized diff --git a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c b/= MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c index 52e025f2d0..35bc70970b 100644 --- a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c +++ b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c @@ -337,7 +337,6 @@ RegisterVariablePolicy ( VARIABLE_POLICY_ENTRY *MatchPolicy; UINT8 MatchPriority; UINT32 NewSize; - UINT8 *NewTable; if (!IsVariablePolicyLibInitialized()) { return EFI_NOT_READY; @@ -376,16 +375,11 @@ RegisterVariablePolicy ( } // Reallocate and copy the table. - NewTable =3D AllocatePool( NewSize ); - if (NewTable =3D=3D NULL) { + mPolicyTable =3D ReallocatePool (mCurrentTableUsage, NewSize, mPolicy= Table); + if (mPolicyTable =3D=3D NULL) { return EFI_OUT_OF_RESOURCES; } - CopyMem( NewTable, mPolicyTable, mCurrentTableUsage ); mCurrentTableSize =3D NewSize; - if (mPolicyTable !=3D NULL) { - FreePool( mPolicyTable ); - } - mPolicyTable =3D NewTable; } // Copy the policy into the table. CopyMem( mPolicyTable + mCurrentTableUsage, NewPolicy, NewPolicy->Size = ); > -----Original Message----- > From: devel@edk2.groups.io On Behalf Of Michael > Kubacki > Sent: Saturday, April 11, 2020 2:38 AM > To: devel@edk2.groups.io > Cc: Wang, Jian J ; Wu, Hao A = ; > Gao, Liming > Subject: [edk2-devel] [PATCH v1 2/9] MdeModulePkg: Define the > VariablePolicyLib >=20 > From: Bret Barkelew >=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 > Signed-off-by: Bret Barkelew > Signed-off-by: Michael Kubacki > --- > MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c > | 773 +++++++ >=20 > MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePo > licyUnitTest.c | 2285 ++++++++++++++++++++ > MdeModulePkg/Include/Library/VariablePolicyLib.h = | > 206 ++ > MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf > | 38 + > MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.uni > | 12 + >=20 > MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePo > licyUnitTest.inf | 41 + > MdeModulePkg/MdeModulePkg.dec = | 3 + > MdeModulePkg/MdeModulePkg.dsc = | 3 + > MdeModulePkg/Test/MdeModulePkgHostTest.dsc = | > 8 + > 9 files changed, 3369 insertions(+) >=20 > diff --git a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c > b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c > new file mode 100644 > index 000000000000..52e025f2d0cf > --- /dev/null > +++ b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c > @@ -0,0 +1,773 @@ > +/** @file -- VariablePolicyLib.c > +Business logic for Variable Policy enforcement. > + > +Copyright (c) Microsoft Corporation. > +SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#include > + > +#include > +#include > +#include > +#include > +#include > + > +#include > + > +// IMPORTANT NOTE: This library is currently rife with multiple return > statements > +// for error handling. A refactor should remove these a= t some point. > + > +// > +// This library was designed with advanced unit-test features. > +// This define handles the configuration. > +#ifdef INTERNAL_UNIT_TEST > +#undef STATIC > +#define STATIC // Nothing... > +#endif > + > +// An abstracted GetVariable interface that enables configuration > regardless of the environment. > +STATIC EFI_GET_VARIABLE mGetVariableHelper =3D NULL; > + > +// Master switch to lock this entire interface. Does not stop enforceme= nt, > +// just prevents the configuration from being changed for the rest of t= he > boot. > +STATIC BOOLEAN mInterfaceLocked =3D FALSE; > + > +// Master switch to disable the entire interface for a single boot. > +// This will disable all policy enforcement for the duration of the boo= t. > +STATIC BOOLEAN mProtectionDisabled =3D FALSE; > + > +// Table to hold all the current policies. > +STATIC UINT8 *mPolicyTable =3D NULL; > +STATIC UINT32 mCurrentTableSize =3D 0; > +STATIC UINT32 mCurrentTableUsage =3D 0; > +STATIC UINT32 mCurrentTableCount =3D 0; > + > +#define POLICY_TABLE_STEP_SIZE 0x1000 > + > +// NOTE: DO NOT USE THESE MACROS on any structure that has not been > validated. > +// Current table data has already been sanitized. > +#define GET_NEXT_POLICY(CurPolicy) > (VARIABLE_POLICY_ENTRY*)((UINT8*)CurPolicy + CurPolicy->Size) > +#define GET_POLICY_NAME(CurPolicy) (CHAR16*)((UINTN)CurPolicy + > CurPolicy->OffsetToName) > + > +#define MATCH_PRIORITY_EXACT 0 > +#define MATCH_PRIORITY_MAX MATCH_PRIORITY_EXACT > +#define MATCH_PRIORITY_MIN MAX_UINT8 > + > + > +/** > + This helper function determines whether the structure of an incoming > policy > + is valid and internally consistent. > + > + @param[in] NewPolicy Pointer to the incoming policy structure. > + > + @retval TRUE > + @retval FALSE Pointer is NULL, size is wrong, strings are empty= , or > + substructures overlap. > + > +**/ > +STATIC > +BOOLEAN > +IsValidVariablePolicyStructure ( > + IN CONST VARIABLE_POLICY_ENTRY *NewPolicy > + ) > +{ > + EFI_STATUS Status; > + UINTN EntryEnd; > + CHAR16 *CheckChar; > + UINTN WildcardCount; > + > + // Sanitize some quick values. > + if (NewPolicy =3D=3D NULL || NewPolicy->Size =3D=3D 0 || > + // Structure size should be at least as long as the minumum struc= ture and > a NULL string. > + NewPolicy->Size < sizeof(VARIABLE_POLICY_ENTRY) || > + // Check for the known revision. > + NewPolicy->Version !=3D VARIABLE_POLICY_ENTRY_REVISION) { > + return FALSE; > + } > + > + // Calculate the theoretical end of the structure and make sure > + // that the structure can fit in memory. > + Status =3D SafeUintnAdd( (UINTN)NewPolicy, NewPolicy->Size, &EntryEnd= ); > + if (EFI_ERROR( Status )) { > + return FALSE; > + } > + > + // Check for a valid Max Size. > + if (NewPolicy->MaxSize =3D=3D 0) { > + return FALSE; > + } > + > + // Check for the valid list of lock policies. > + if (NewPolicy->LockPolicyType !=3D VARIABLE_POLICY_TYPE_NO_LOCK && > + NewPolicy->LockPolicyType !=3D VARIABLE_POLICY_TYPE_LOCK_NOW && > + NewPolicy->LockPolicyType !=3D > VARIABLE_POLICY_TYPE_LOCK_ON_CREATE && > + NewPolicy->LockPolicyType !=3D > VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE) > + { > + return FALSE; > + } > + > + // If the policy type is VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE, > make sure that the matching state variable Name > + // terminates before the OffsetToName for the matching policy variabl= e > Name. > + if (NewPolicy->LockPolicyType =3D=3D > VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE) { > + // Adjust CheckChar to the offset of the LockPolicy->Name. > + Status =3D SafeUintnAdd( (UINTN)NewPolicy + > sizeof(VARIABLE_POLICY_ENTRY), > + sizeof(VARIABLE_LOCK_ON_VAR_STATE_POLICY), > + (UINTN*)&CheckChar ); > + if (EFI_ERROR( Status ) || EntryEnd <=3D (UINTN)CheckChar) { > + return FALSE; > + } > + while (*CheckChar !=3D CHAR_NULL) { > + if (EntryEnd <=3D (UINTN)CheckChar) { > + return FALSE; > + } > + CheckChar++; > + } > + // At this point we should have either exeeded the structure or be > pointing at the last char in LockPolicy->Name. > + // We should check to make sure that the policy Name comes > immediately after this charcter. > + if ((UINTN)++CheckChar !=3D (UINTN)NewPolicy + NewPolicy- > >OffsetToName) { > + return FALSE; > + } > + } > + // If the policy type is any other value, make sure that the LockPoli= cy > structure has a zero length. > + else { > + if (NewPolicy->OffsetToName !=3D sizeof(VARIABLE_POLICY_ENTRY)) { > + return FALSE; > + } > + } > + > + // Check to make sure that the name has a terminating character > + // before the end of the structure. > + // We've already checked that the name is within the bounds of the > structure. > + if (NewPolicy->Size !=3D NewPolicy->OffsetToName) { > + CheckChar =3D (CHAR16*)((UINTN)NewPolicy + NewPolicy- > >OffsetToName); > + WildcardCount =3D 0; > + while (*CheckChar !=3D CHAR_NULL) { > + // Make sure there aren't excessive wildcards. > + if (*CheckChar =3D=3D '#') { > + WildcardCount++; > + if (WildcardCount > MATCH_PRIORITY_MIN) { > + return FALSE; > + } > + } > + // Make sure you're still within the bounds of the policy structu= re. > + if (EntryEnd <=3D (UINTN)CheckChar) { > + return FALSE; > + } > + CheckChar++; > + } > + > + // Finally, we should be pointed at the very last character in Name= , so we > should be right > + // up against the end of the structure. > + if ((UINTN)++CheckChar !=3D EntryEnd) { > + return FALSE; > + } > + } > + > + return TRUE; > +} > + > + > +/** > + This helper function evaluates a policy and determines whether it mat= ches > the target > + variable. If matched, will also return a value corresponding to the p= riority > of the match. > + > + The rules for "best match" are listed in the Variable Policy Spec. > + Perfect name matches will return 0. > + Single wildcard characters will return the number of wildcard charact= ers. > + Full namespaces will return MAX_UINT8. > + > + @param[in] EvalEntry Pointer to the policy entry being evalu= ated. > + @param[in] VariableName Same as EFI_SET_VARIABLE. > + @param[in] VendorGuid Same as EFI_SET_VARIABLE. > + @param[out] MatchPriority [Optional] On finding a match, this val= ue > contains the priority of the match. > + Lower number =3D=3D higher priority. On= ly valid if a match found. > + > + @retval TRUE Current entry matches the target variable. > + @retval FALSE Current entry does not match at all. > + > +**/ > +STATIC > +BOOLEAN > +EvaluatePolicyMatch ( > + IN CONST VARIABLE_POLICY_ENTRY *EvalEntry, > + IN CONST CHAR16 *VariableName, > + IN CONST EFI_GUID *VendorGuid, > + OUT UINT8 *MatchPriority OPTIONAL > + ) > +{ > + BOOLEAN Result =3D FALSE; > + CHAR16 *PolicyName; > + UINT8 CalculatedPriority =3D MATCH_PRIORITY_EXACT; > + UINTN Index; > + > + // Step 1: If the GUID doesn't match, we're done. No need to evaluate > anything else. > + if (!CompareGuid( &EvalEntry->Namespace, VendorGuid )) { > + goto Exit; > + } > + > + // If the GUID matches, check to see whether there is a Name associat= ed > + // with the policy. If not, this policy matches the entire namespace. > + // Missing Name is indicated by size being equal to name. > + if (EvalEntry->Size =3D=3D EvalEntry->OffsetToName) { > + CalculatedPriority =3D MATCH_PRIORITY_MIN; > + Result =3D TRUE; > + goto Exit; > + } > + > + // Now that we know the name exists, get it. > + PolicyName =3D GET_POLICY_NAME( EvalEntry ); > + > + // Evaluate the name against the policy name and check for a match. > + // Account for any wildcards. > + Index =3D 0; > + Result =3D TRUE; > + // Keep going until the end of both strings. > + while (PolicyName[Index] !=3D CHAR_NULL || VariableName[Index] !=3D > CHAR_NULL) { > + // If we don't have a match... > + if (PolicyName[Index] !=3D VariableName[Index] || PolicyName[Index]= =3D=3D > '#') { > + // If this is a numerical wildcard, we can consider > + // it a match if we alter the priority. > + if (PolicyName[Index] =3D=3D L'#' && > + (L'0' <=3D VariableName[Index] && VariableName[Index] <=3D L'= 9')) { > + if (CalculatedPriority < MATCH_PRIORITY_MIN) { > + CalculatedPriority++; > + } > + } > + // Otherwise, not a match. > + else { > + Result =3D FALSE; > + goto Exit; > + } > + } > + Index++; > + } > + > +Exit: > + if (Result && MatchPriority !=3D NULL) { > + *MatchPriority =3D CalculatedPriority; > + } > + return Result; > +} > + > + > +/** > + This helper function walks the current policy table and returns a poi= nter > + to the best match, if any are found. Leverages EvaluatePolicyMatch() = to > + determine "best". > + > + @param[in] VariableName Same as EFI_SET_VARIABLE. > + @param[in] VendorGuid Same as EFI_SET_VARIABLE. > + @param[out] ReturnPriority [Optional] If pointer is provided, ret= urn the > + priority of the match. Same as Evaluat= ePolicyMatch(). > + Only valid if a match is returned. > + > + @retval VARIABLE_POLICY_ENTRY* Best match that was found. > + @retval NULL No match was found. > + > +**/ > +STATIC > +VARIABLE_POLICY_ENTRY* > +GetBestPolicyMatch ( > + IN CONST CHAR16 *VariableName, > + IN CONST EFI_GUID *VendorGuid, > + OUT UINT8 *ReturnPriority OPTIONAL > + ) > +{ > + VARIABLE_POLICY_ENTRY *BestResult =3D NULL; > + VARIABLE_POLICY_ENTRY *CurrentEntry; > + UINT8 MatchPriority; > + UINT8 CurrentPriority; > + UINTN Index; > + > + // Walk all entries in the table, looking for matches. > + CurrentEntry =3D (VARIABLE_POLICY_ENTRY*)mPolicyTable; > + for (Index =3D 0; Index < mCurrentTableCount; Index++) { > + // Check for a match. > + if (EvaluatePolicyMatch( CurrentEntry, VariableName, VendorGuid, > &CurrentPriority ) =3D=3D TRUE) { > + // If match is better, take it. > + if (BestResult =3D=3D NULL || CurrentPriority < MatchPriority) { > + BestResult =3D CurrentEntry; > + MatchPriority =3D CurrentPriority; > + } > + > + // If you've hit the highest-priority match, can exit now. > + if (MatchPriority =3D=3D 0) { > + break; > + } > + } > + > + // If we're still in the loop, move to the next entry. > + CurrentEntry =3D GET_NEXT_POLICY( CurrentEntry ); > + } > + > + // If a return priority was requested, return it. > + if (ReturnPriority !=3D NULL) { > + *ReturnPriority =3D MatchPriority; > + } > + > + return BestResult; > +} > + > + > +/** > + This API function validates and registers a new policy with > + the policy enforcement engine. > + > + @param[in] NewPolicy Pointer to the incoming policy structure. > + > + @retval EFI_SUCCESS > + @retval EFI_INVALID_PARAMETER NewPolicy is NULL or is internall= y > inconsistent. > + @retval EFI_ALREADY_STARTED An identical matching policy alre= ady > exists. > + @retval EFI_WRITE_PROTECTED The interface has been locked unt= il > the next reboot. > + @retval EFI_UNSUPPORTED Policy enforcement has been disab= led. > No reason to add more policies. > + @retval EFI_ABORTED A calculation error has prevented= this > function from completing. > + @retval EFI_OUT_OF_RESOURCES Cannot grow the table to hold any > more policies. > + @retval EFI_NOT_READY Library has not yet been initiali= zed. > + > +**/ > +EFI_STATUS > +EFIAPI > +RegisterVariablePolicy ( > + IN CONST VARIABLE_POLICY_ENTRY *NewPolicy > + ) > +{ > + EFI_STATUS Status; > + VARIABLE_POLICY_ENTRY *MatchPolicy; > + UINT8 MatchPriority; > + UINT32 NewSize; > + UINT8 *NewTable; > + > + if (!IsVariablePolicyLibInitialized()) { > + return EFI_NOT_READY; > + } > + if (mInterfaceLocked) { > + return EFI_WRITE_PROTECTED; > + } > + > + if (!IsValidVariablePolicyStructure( NewPolicy )) { > + return EFI_INVALID_PARAMETER; > + } > + > + // Check to see whether an exact matching policy already exists. > + MatchPolicy =3D GetBestPolicyMatch( GET_POLICY_NAME( NewPolicy ), > + &NewPolicy->Namespace, > + &MatchPriority ); > + if (MatchPolicy !=3D NULL && MatchPriority =3D=3D MATCH_PRIORITY_EXAC= T) { > + return EFI_ALREADY_STARTED; > + } > + > + // If none exists, create it. > + // If we need more space, allocate that now. > + Status =3D SafeUint32Add( mCurrentTableUsage, NewPolicy->Size, > &NewSize ); > + if (EFI_ERROR( Status )) { > + return EFI_ABORTED; > + } > + if (NewSize > mCurrentTableSize) { > + // Use NewSize to calculate the new table size in units of > POLICY_TABLE_STEP_SIZE. > + NewSize =3D (NewSize % POLICY_TABLE_STEP_SIZE) > 0 ? > + (NewSize / POLICY_TABLE_STEP_SIZE) + 1 : > + (NewSize / POLICY_TABLE_STEP_SIZE); > + // Calculate the new table size in absolute bytes. > + Status =3D SafeUint32Mult( NewSize, POLICY_TABLE_STEP_SIZE, > &NewSize ); > + if (EFI_ERROR( Status )) { > + return EFI_ABORTED; > + } > + > + // Reallocate and copy the table. > + NewTable =3D AllocatePool( NewSize ); > + if (NewTable =3D=3D NULL) { > + return EFI_OUT_OF_RESOURCES; > + } > + CopyMem( NewTable, mPolicyTable, mCurrentTableUsage ); > + mCurrentTableSize =3D NewSize; > + if (mPolicyTable !=3D NULL) { > + FreePool( mPolicyTable ); > + } > + mPolicyTable =3D NewTable; > + } > + // Copy the policy into the table. > + CopyMem( mPolicyTable + mCurrentTableUsage, NewPolicy, NewPolicy- > >Size ); > + mCurrentTableUsage +=3D NewPolicy->Size; > + mCurrentTableCount +=3D 1; > + > + // We're done here. > + > + return EFI_SUCCESS; > +} > + > + > +/** > + This API function checks to see whether the parameters to SetVariable > would > + be allowed according to the current variable policies. > + > + @param[in] VariableName Same as EFI_SET_VARIABLE. > + @param[in] VendorGuid Same as EFI_SET_VARIABLE. > + @param[in] Attributes Same as EFI_SET_VARIABLE. > + @param[in] DataSize Same as EFI_SET_VARIABLE. > + @param[in] Data Same as EFI_SET_VARIABLE. > + > + @retval EFI_SUCCESS A matching policy allows this upd= ate. > + @retval EFI_SUCCESS There are currently no policies t= hat restrict > this update. > + @retval EFI_SUCCESS The protections have been disable= until the > next reboot. > + @retval EFI_WRITE_PROTECTED Variable is currently locked. > + @retval EFI_INVALID_PARAMETER Attributes or size are invalid. > + @retval EFI_ABORTED A lock policy exists, but an erro= r prevented > evaluation. > + @retval EFI_NOT_READY Library has not been initialized. > + > +**/ > +EFI_STATUS > +EFIAPI > +ValidateSetVariable ( > + IN CHAR16 *VariableName, > + IN EFI_GUID *VendorGuid, > + IN UINT32 Attributes, > + IN UINTN DataSize, > + IN VOID *Data > + ) > +{ > + BOOLEAN IsDel; > + VARIABLE_POLICY_ENTRY *ActivePolicy; > + EFI_STATUS Status; > + EFI_STATUS ReturnStatus =3D EFI_SUCCESS; > + VARIABLE_LOCK_ON_VAR_STATE_POLICY *StateVarPolicy; > + CHAR16 *StateVarName; > + UINTN StateVarSize; > + UINT8 StateVar; > + > + if (!IsVariablePolicyLibInitialized()) { > + ReturnStatus =3D EFI_NOT_READY; > + goto Exit; > + } > + > + // Bail if the protections are currently disabled. > + if (mProtectionDisabled =3D=3D TRUE) { > + ReturnStatus =3D EFI_SUCCESS; > + goto Exit; > + } > + > + // Determine whether this is a delete operation. > + // If so, it will affect which tests are applied. > + if ((DataSize =3D=3D 0) && ((Attributes & EFI_VARIABLE_APPEND_WRITE) = = =3D=3D 0)) > { > + IsDel =3D TRUE; > + } > + else { > + IsDel =3D FALSE; > + } > + > + // Find an active policy if one exists. > + ActivePolicy =3D GetBestPolicyMatch( VariableName, VendorGuid, NULL )= ; > + > + // If we have an active policy, check it against the incoming data. > + if (ActivePolicy !=3D NULL) { > + // > + // Only enforce size and attribute constraints when updating data, = not > deleting. > + if (!IsDel) { > + // Check for size constraints. > + if ((ActivePolicy->MinSize > 0 && DataSize < ActivePolicy->MinSiz= e) || > + (ActivePolicy->MaxSize > 0 && DataSize > ActivePolicy->MaxSiz= e)) { > + ReturnStatus =3D EFI_INVALID_PARAMETER; > + DEBUG(( DEBUG_VERBOSE, "%a - Bad Size. 0x%X <> 0x%X-0x%X\n", > __FUNCTION__, > + DataSize, ActivePolicy->MinSize, ActivePolicy->MaxSize = )); > + goto Exit; > + } > + > + // Check for attribute constraints. > + if ((ActivePolicy->AttributesMustHave & Attributes) !=3D ActivePo= licy- > >AttributesMustHave || > + (ActivePolicy->AttributesCantHave & Attributes) !=3D 0) { > + ReturnStatus =3D EFI_INVALID_PARAMETER; > + DEBUG(( DEBUG_VERBOSE, "%a - Bad Attributes. 0x%X <> > 0x%X:0x%X\n", __FUNCTION__, > + Attributes, ActivePolicy->AttributesMustHave, ActivePol= icy- > >AttributesCantHave )); > + goto Exit; > + } > + } > + > + // > + // Lock policy check. > + // > + // Check for immediate lock. > + if (ActivePolicy->LockPolicyType =3D=3D VARIABLE_POLICY_TYPE_LOCK_N= OW) > { > + ReturnStatus =3D EFI_WRITE_PROTECTED; > + goto Exit; > + } > + // Check for lock on create. > + else if (ActivePolicy->LockPolicyType =3D=3D > VARIABLE_POLICY_TYPE_LOCK_ON_CREATE) { > + StateVarSize =3D 0; > + Status =3D mGetVariableHelper( VariableName, > + VendorGuid, > + NULL, > + &StateVarSize, > + NULL ); > + if (Status =3D=3D EFI_BUFFER_TOO_SMALL) { > + ReturnStatus =3D EFI_WRITE_PROTECTED; > + goto Exit; > + } > + } > + // Check for lock on state variable. > + else if (ActivePolicy->LockPolicyType =3D=3D > VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE) { > + StateVarPolicy =3D > (VARIABLE_LOCK_ON_VAR_STATE_POLICY*)((UINT8*)ActivePolicy + > sizeof(VARIABLE_POLICY_ENTRY)); > + StateVarName =3D (CHAR16*)((UINT8*)StateVarPolicy + > sizeof(VARIABLE_LOCK_ON_VAR_STATE_POLICY)); > + StateVarSize =3D sizeof(StateVar); > + Status =3D mGetVariableHelper( StateVarName, > + &StateVarPolicy->Namespace, > + NULL, > + &StateVarSize, > + &StateVar ); > + > + // If the variable was found, check the state. If matched, this v= ariable is > locked. > + if (!EFI_ERROR( Status )) { > + if (StateVar =3D=3D StateVarPolicy->Value) { > + ReturnStatus =3D EFI_WRITE_PROTECTED; > + goto Exit; > + } > + } > + // EFI_NOT_FOUND and EFI_BUFFER_TOO_SMALL indicate that the > state doesn't match. > + else if (Status !=3D EFI_NOT_FOUND && Status !=3D > EFI_BUFFER_TOO_SMALL) { > + // We don't know what happened, but it isn't good. > + ReturnStatus =3D EFI_ABORTED; > + goto Exit; > + } > + } > + } > + > +Exit: > + DEBUG(( DEBUG_VERBOSE, "%a - Variable (%g:%s) returning %r.\n", > __FUNCTION__, VendorGuid, VariableName, ReturnStatus )); > + return ReturnStatus; > +} > + > + > +/** > + This API function disables the variable policy enforcement. If it's > + already been called once, will return EFI_ALREADY_STARTED. > + > + @retval EFI_SUCCESS > + @retval EFI_ALREADY_STARTED Has already been called once this b= oot. > + @retval EFI_WRITE_PROTECTED Interface has been locked until reb= oot. > + @retval EFI_NOT_READY Library has not yet been initialize= d. > + > +**/ > +EFI_STATUS > +EFIAPI > +DisableVariablePolicy ( > + VOID > + ) > +{ > + if (!IsVariablePolicyLibInitialized()) { > + return EFI_NOT_READY; > + } > + if (mProtectionDisabled) { > + return EFI_ALREADY_STARTED; > + } > + if (mInterfaceLocked) { > + return EFI_WRITE_PROTECTED; > + } > + mProtectionDisabled =3D TRUE; > + return EFI_SUCCESS; > +} > + > + > +/** > + This API function will dump the entire contents of the variable polic= y table. > + > + Similar to GetVariable, the first call can be made with a 0 size and = it will > return > + the size of the buffer required to hold the entire table. > + > + @param[out] Policy Pointer to the policy buffer. Can be NULL if = Size is 0. > + @param[in,out] Size On input, the size of the output buffer. On o= utput, > the size > + of the data returned. > + > + @retval EFI_SUCCESS Policy data is in the output buff= er and Size > has been updated. > + @retval EFI_INVALID_PARAMETER Size is NULL, or Size is non-zero= and > Policy is NULL. > + @retval EFI_BUFFER_TOO_SMALL Size is insufficient to hold poli= cy. Size > updated with required size. > + @retval EFI_NOT_READY Library has not yet been initiali= zed. > + > +**/ > +EFI_STATUS > +EFIAPI > +DumpVariablePolicy ( > + OUT UINT8 *Policy, > + IN OUT UINT32 *Size > + ) > +{ > + if (!IsVariablePolicyLibInitialized()) { > + return EFI_NOT_READY; > + } > + > + // Check the parameters. > + if (Size =3D=3D NULL || (*Size > 0 && Policy =3D=3D NULL)) { > + return EFI_INVALID_PARAMETER; > + } > + > + // Make sure the size is sufficient to hold the policy table. > + if (*Size < mCurrentTableUsage) { > + *Size =3D mCurrentTableUsage; > + return EFI_BUFFER_TOO_SMALL; > + } > + > + // If we're still here, copy the table and bounce. > + CopyMem( Policy, mPolicyTable, mCurrentTableUsage ); > + *Size =3D mCurrentTableUsage; > + > + return EFI_SUCCESS; > +} > + > + > +/** > + This API function returns whether or not the policy engine is > + currently being enforced. > + > + @retval TRUE > + @retval FALSE > + @retval FALSE Library has not yet been initialized. > + > +**/ > +BOOLEAN > +EFIAPI > +IsVariablePolicyEnabled ( > + VOID > + ) > +{ > + if (!IsVariablePolicyLibInitialized()) { > + return FALSE; > + } > + return !mProtectionDisabled; > +} > + > + > +/** > + This API function locks the interface so that no more policy updates > + can be performed or changes made to the enforcement until the next > boot. > + > + @retval EFI_SUCCESS > + @retval EFI_NOT_READY Library has not yet been initialized. > + > +**/ > +EFI_STATUS > +EFIAPI > +LockVariablePolicy ( > + VOID > + ) > +{ > + if (!IsVariablePolicyLibInitialized()) { > + return EFI_NOT_READY; > + } > + if (mInterfaceLocked) { > + return EFI_WRITE_PROTECTED; > + } > + mInterfaceLocked =3D TRUE; > + return EFI_SUCCESS; > +} > + > + > +/** > + This API function returns whether or not the policy interface is lock= ed > + for the remainder of the boot. > + > + @retval TRUE > + @retval FALSE > + @retval FALSE Library has not yet been initialized. > + > +**/ > +BOOLEAN > +EFIAPI > +IsVariablePolicyInterfaceLocked ( > + VOID > + ) > +{ > + if (!IsVariablePolicyLibInitialized()) { > + return FALSE; > + } > + return mInterfaceLocked; > +} > + > + > +/** > + This helper function initializes the library and sets > + up any required internal structures or handlers. > + > + Also registers the internal pointer for the GetVariable helper. > + > + @param[in] GetVariableHelper A function pointer matching the > EFI_GET_VARIABLE prototype that will be used to > + check policy criteria that involve the existence of o= ther variables. > + > + @retval EFI_SUCCESS > + @retval EFI_ALREADY_STARTED The initialize function has been ca= lled > more than once without a call to > + deinitialize. > + > +**/ > +EFI_STATUS > +EFIAPI > +InitVariablePolicyLib ( > + IN EFI_GET_VARIABLE GetVariableHelper > + ) > +{ > + if (mGetVariableHelper !=3D NULL) { > + return EFI_ALREADY_STARTED; > + } > + > + // Save an internal pointer to the GetVariableHelper. > + mGetVariableHelper =3D GetVariableHelper; > + > + // Initialize the global state. > + mInterfaceLocked =3D FALSE; > + mProtectionDisabled =3D FALSE; > + mPolicyTable =3D NULL; > + mCurrentTableSize =3D 0; > + mCurrentTableUsage =3D 0; > + mCurrentTableCount =3D 0; > + > + return EFI_SUCCESS; > +} > + > + > +/** > + This helper function returns whether or not the library is currently > initialized. > + > + @retval TRUE > + @retval FALSE > + > +**/ > +BOOLEAN > +EFIAPI > +IsVariablePolicyLibInitialized ( > + VOID > + ) > +{ > + return (mGetVariableHelper !=3D NULL); > +} > + > + > +/** > + This helper function tears down the library. > + > + Should generally only be used for test harnesses. > + > + @retval EFI_SUCCESS > + @retval EFI_NOT_READY Deinitialize was called without first c= alling > initialize. > + > +**/ > +EFI_STATUS > +EFIAPI > +DeinitVariablePolicyLib ( > + VOID > + ) > +{ > + if (mGetVariableHelper =3D=3D NULL) { > + return EFI_NOT_READY; > + } > + > + mGetVariableHelper =3D NULL; > + mInterfaceLocked =3D FALSE; > + mProtectionDisabled =3D FALSE; > + mCurrentTableSize =3D 0; > + mCurrentTableUsage =3D 0; > + mCurrentTableCount =3D 0; > + > + if (mPolicyTable !=3D NULL) { > + FreePool( mPolicyTable ); > + mPolicyTable =3D NULL; > + } > + > + return EFI_SUCCESS; > +} > diff --git > a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/Variable > PolicyUnitTest.c > b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/Variable > PolicyUnitTest.c > new file mode 100644 > index 000000000000..3214bff09091 > --- /dev/null > +++ > b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/Variable > PolicyUnitTest.c > @@ -0,0 +1,2285 @@ > +/** @file -- VariablePolicyUnitTest.c > +UnitTest for... > +Business logic for Variable Policy enforcement. > + > +Copyright (c) Microsoft Corporation. > +SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include > + > +#include > +#include > + > +// MU_CHANGE - Turn this off for now. Try to turn it back on with extra > build options. > +// #ifndef INTERNAL_UNIT_TEST > +// #error Make sure to build thie with INTERNAL_UNIT_TEST enabled! > Otherwise, some important tests may be skipped! > +// #endif > + > + > +#define UNIT_TEST_NAME "UEFI Variable Policy UnitTest" > +#define UNIT_TEST_VERSION "0.5" > + > +///=3D=3D=3D TEST DATA > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > + > +#pragma pack(push, 1) > +typedef struct _SIMPLE_VARIABLE_POLICY_ENTRY { > + VARIABLE_POLICY_ENTRY Header; > + CHAR16 Name[]; > +} SIMPLE_VARIABLE_POLICY_ENTRY; > +#define EXPANDED_VARIABLE_POLICY_ENTRY_VAR_NAME_LENGTH 1001 > // 1000 characters + terminator. > +#define EXPANDED_VARIABLE_POLICY_ENTRY_VAR_NAME_SIZE > (EXPANDED_VARIABLE_POLICY_ENTRY_VAR_NAME_LENGTH * > sizeof(CHAR16)) > +typedef struct _EXPANDED_VARIABLE_POLICY_ENTRY { > + VARIABLE_POLICY_ENTRY Header; > + VARIABLE_LOCK_ON_VAR_STATE_POLICY StatePolicy; > + CHAR16 > StateName[EXPANDED_VARIABLE_POLICY_ENTRY_VAR_NAME_LENGTH]; > + CHAR16 > Name[EXPANDED_VARIABLE_POLICY_ENTRY_VAR_NAME_LENGTH]; > +} EXPANDED_VARIABLE_POLICY_ENTRY; > +#pragma pack(pop) > + > +// {F955BA2D-4A2C-480C-BFD1-3CC522610592} > +#define TEST_GUID_1 { 0xf955ba2d, 0x4a2c, 0x480c, { 0xbf, 0xd1, 0x3c, 0= xc5, > 0x22, 0x61, 0x5, 0x92 } } > +EFI_GUID mTestGuid1 =3D TEST_GUID_1; > +// {2DEA799E-5E73-43B9-870E-C945CE82AF3A} > +#define TEST_GUID_2 { 0x2dea799e, 0x5e73, 0x43b9, { 0x87, 0xe, 0xc9, 0x= 45, > 0xce, 0x82, 0xaf, 0x3a } } > +EFI_GUID mTestGuid2 =3D TEST_GUID_2; > +// {698A2BFD-A616-482D-B88C-7100BD6682A9} > +#define TEST_GUID_3 { 0x698a2bfd, 0xa616, 0x482d, { 0xb8, 0x8c, 0x71, 0= x0, > 0xbd, 0x66, 0x82, 0xa9 } } > +EFI_GUID mTestGuid3 =3D TEST_GUID_3; > + > +#define TEST_VAR_1_NAME L"TestVar1" > +#define TEST_VAR_2_NAME L"TestVar2" > +#define TEST_VAR_3_NAME L"TestVar3" > + > +#define TEST_POLICY_ATTRIBUTES_NULL 0 > +#define TEST_POLICY_MIN_SIZE_NULL 0 > +#define TEST_POLICY_MAX_SIZE_NULL MAX_UINT32 > + > +#define TEST_POLICY_MIN_SIZE_10 10 > +#define TEST_POLICY_MAX_SIZE_200 200 > + > +#define TEST_300_HASHES_STRING > L"##################################################"\ > + > "##################################################"\ > + > "##################################################"\ > + > "##################################################"\ > + > "##################################################"\ > + > "##################################################" > + > + > +///=3D=3D=3D HELPER FUNCTIONS > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > + > +STATIC > +BOOLEAN > +InitExpVarPolicyStrings ( > + EXPANDED_VARIABLE_POLICY_ENTRY *Entry, > + CHAR16 *Name, OPTIONAL > + CHAR16 *StateName OPTIONAL > + ) > +{ > + UINTN NameSize; > + UINTN StateNameSize; > + > + NameSize =3D Name =3D=3D NULL ? 0 : StrSize( Name ); > + StateNameSize =3D StateName =3D=3D NULL ? 0 : StrSize( StateName ); > + > + if (NameSize > EXPANDED_VARIABLE_POLICY_ENTRY_VAR_NAME_SIZE || > NameSize > MAX_UINT16 || > + StateNameSize > > EXPANDED_VARIABLE_POLICY_ENTRY_VAR_NAME_SIZE || StateNameSize > > MAX_UINT16) { > + return FALSE; > + } > + > + Entry->Header.OffsetToName =3D sizeof(VARIABLE_POLICY_ENTRY); > + if (StateName !=3D NULL) { > + Entry->Header.OffsetToName +=3D > (UINT16)sizeof(VARIABLE_LOCK_ON_VAR_STATE_POLICY) + > (UINT16)StateNameSize; > + } > + Entry->Header.Size =3D Entry->Header.OffsetToName + (UINT16)NameSize; > + > + CopyMem( (UINT8*)Entry + Entry->Header.OffsetToName, Name, > NameSize ); > + if (StateName !=3D NULL) { > + CopyMem( (UINT8*)Entry + sizeof(VARIABLE_POLICY_ENTRY) + > sizeof(VARIABLE_LOCK_ON_VAR_STATE_POLICY), StateName, > StateNameSize ); > + } > + > + return TRUE; > +} > + > +EFI_STATUS > +EFIAPI > +StubGetVariableNull ( > + IN CHAR16 *VariableName, > + IN EFI_GUID *VendorGuid, > + OUT UINT32 *Attributes, OPTIONAL > + IN OUT UINTN *DataSize, > + OUT VOID *Data OPTIONAL > + ) > +{ > + UINT32 MockedAttr; > + UINTN MockedDataSize; > + VOID *MockedData; > + EFI_STATUS MockedReturn; > + > + check_expected_ptr( VariableName ); > + check_expected_ptr( VendorGuid ); > + check_expected_ptr( DataSize ); > + > + MockedAttr =3D (UINT32)mock(); > + MockedDataSize =3D (UINTN)mock(); > + MockedData =3D (VOID*)mock(); > + MockedReturn =3D (EFI_STATUS)mock(); > + > + if (Attributes) { > + *Attributes =3D MockedAttr; > + } > + if (Data && !EFI_ERROR(MockedReturn)) { > + CopyMem( Data, MockedData, MockedDataSize ); > + } > + > + *DataSize =3D MockedDataSize; > + > + return MockedReturn; > +} > + > +// > +// Anything you think might be helpful that isn't a test itself. > +// > + > +STATIC > +UNIT_TEST_STATUS > +LibInitMocked ( > + IN UNIT_TEST_CONTEXT Context > + ) > +{ > + return EFI_ERROR(InitVariablePolicyLib( StubGetVariableNull )) ? > UNIT_TEST_ERROR_PREREQUISITE_NOT_MET : UNIT_TEST_PASSED; > +} > + > +STATIC > +VOID > +LibCleanup ( > + IN UNIT_TEST_CONTEXT Context > + ) > +{ > + DeinitVariablePolicyLib(); > +} > + > + > +///=3D=3D=3D TEST CASES > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > + > +///=3D=3D=3D=3D=3D ARCHITECTURAL SUITE > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D > + > +UNIT_TEST_STATUS > +EFIAPI > +ShouldBeAbleToInitAndDeinitTheLibrary ( > + IN UNIT_TEST_CONTEXT Context > + ) > +{ > + EFI_STATUS Status; > + Status =3D InitVariablePolicyLib( StubGetVariableNull ); > + UT_ASSERT_NOT_EFI_ERROR( Status ); > + > + UT_ASSERT_TRUE( IsVariablePolicyLibInitialized() ); > + > + Status =3D DeinitVariablePolicyLib(); > + UT_ASSERT_NOT_EFI_ERROR( Status ); > + > + UT_ASSERT_FALSE( IsVariablePolicyLibInitialized() ); > + > + return UNIT_TEST_PASSED; > +} > + > +UNIT_TEST_STATUS > +EFIAPI > +ShouldNotBeAbleToInitializeTheLibraryTwice ( > + IN UNIT_TEST_CONTEXT Context > + ) > +{ > + EFI_STATUS Status; > + Status =3D InitVariablePolicyLib( StubGetVariableNull ); > + UT_ASSERT_NOT_EFI_ERROR( Status ); > + Status =3D InitVariablePolicyLib( StubGetVariableNull ); > + UT_ASSERT_TRUE( EFI_ERROR( Status ) ); > + return UNIT_TEST_PASSED; > +} > + > +UNIT_TEST_STATUS > +EFIAPI > +ShouldFailDeinitWithoutInit ( > + IN UNIT_TEST_CONTEXT Context > + ) > +{ > + EFI_STATUS Status; > + Status =3D DeinitVariablePolicyLib(); > + UT_ASSERT_TRUE( EFI_ERROR( Status ) ); > + return UNIT_TEST_PASSED; > +} > + > +UNIT_TEST_STATUS > +EFIAPI > +ApiCommandsShouldNotRespondIfLibIsUninitialized ( > + IN UNIT_TEST_CONTEXT Context > + ) > +{ > + SIMPLE_VARIABLE_POLICY_ENTRY TestPolicy =3D { > + { > + VARIABLE_POLICY_ENTRY_REVISION, > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME), > + sizeof(VARIABLE_POLICY_ENTRY), > + TEST_GUID_1, > + TEST_POLICY_MIN_SIZE_NULL, > + TEST_POLICY_MAX_SIZE_NULL, > + TEST_POLICY_ATTRIBUTES_NULL, > + TEST_POLICY_ATTRIBUTES_NULL, > + VARIABLE_POLICY_TYPE_NO_LOCK > + }, > + TEST_VAR_1_NAME > + }; > + UINT8 DummyData[8]; > + UINT32 DummyDataSize =3D sizeof(DummyData); > + > + // This test should not start with an initialized library. > + > + // Verify that all API commands fail. > + UT_ASSERT_TRUE( EFI_ERROR( LockVariablePolicy() ) ); > + UT_ASSERT_TRUE( EFI_ERROR( DisableVariablePolicy() ) ); > + > UT_ASSERT_TRUE( EFI_ERROR( RegisterVariablePolicy( &TestPolicy.Header ) > ) ); > + UT_ASSERT_TRUE( EFI_ERROR( DumpVariablePolicy( DummyData, > &DummyDataSize ) ) ); > + UT_ASSERT_FALSE( IsVariablePolicyInterfaceLocked() ); > + UT_ASSERT_FALSE( IsVariablePolicyEnabled() ); > + UT_ASSERT_TRUE( EFI_ERROR( ValidateSetVariable( TEST_VAR_1_NAME, > + &mTestGuid1, > + VARIABLE_ATTRIBUTE_NV_= BS, > + sizeof(DummyData), > + DummyData ) ) ); > + > + return UNIT_TEST_PASSED; > +} > + > + > +///=3D=3D=3D=3D=3D INTERNAL FUNCTION SUITE > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > + > +#ifdef INTERNAL_UNIT_TEST > + > +BOOLEAN > +EvaluatePolicyMatch ( > + IN CONST VARIABLE_POLICY_ENTRY *EvalEntry, > + IN CONST CHAR16 *VariableName, > + IN CONST EFI_GUID *VendorGuid, > + OUT UINT8 *MatchPriority OPTIONAL > + ); > + > +UNIT_TEST_STATUS > +EFIAPI > +PoliciesShouldMatchByNameAndGuid ( > + IN UNIT_TEST_CONTEXT Context > + ) > +{ > + SIMPLE_VARIABLE_POLICY_ENTRY MatchCheckPolicy =3D { > + { > + VARIABLE_POLICY_ENTRY_REVISION, > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME), > + sizeof(VARIABLE_POLICY_ENTRY), > + TEST_GUID_1, > + TEST_POLICY_MIN_SIZE_NULL, > + TEST_POLICY_MAX_SIZE_NULL, > + TEST_POLICY_ATTRIBUTES_NULL, > + TEST_POLICY_ATTRIBUTES_NULL, > + VARIABLE_POLICY_TYPE_NO_LOCK > + }, > + TEST_VAR_1_NAME > + }; > + CHAR16 *CheckVar1Name =3D TEST_VAR_1_NAME; > + CHAR16 *CheckVar2Name =3D TEST_VAR_2_NAME; > + > + // Make sure that a different name does not match. > + UT_ASSERT_FALSE( EvaluatePolicyMatch( &MatchCheckPolicy.Header, > CheckVar2Name, &mTestGuid1, NULL ) ); > + > + // Make sure that a different GUID does not match. > + UT_ASSERT_FALSE( EvaluatePolicyMatch( &MatchCheckPolicy.Header, > CheckVar1Name, &mTestGuid2, NULL ) ); > + > + // Make sure that the same name and GUID match. > + UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolicy.Header, > CheckVar1Name, &mTestGuid1, NULL ) ); > + > + return UNIT_TEST_PASSED; > +} > + > +UNIT_TEST_STATUS > +EFIAPI > +WildcardPoliciesShouldMatchDigits ( > + IN UNIT_TEST_CONTEXT Context > + ) > +{ > + SIMPLE_VARIABLE_POLICY_ENTRY MatchCheckPolicy =3D { > + { > + VARIABLE_POLICY_ENTRY_REVISION, > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(L"Wildcard#VarName##"), > + sizeof(VARIABLE_POLICY_ENTRY), > + TEST_GUID_1, > + TEST_POLICY_MIN_SIZE_NULL, > + TEST_POLICY_MAX_SIZE_NULL, > + TEST_POLICY_ATTRIBUTES_NULL, > + TEST_POLICY_ATTRIBUTES_NULL, > + VARIABLE_POLICY_TYPE_NO_LOCK > + }, > + L"Wildcard#VarName##" > + }; > + CHAR16 *CheckVar1Name =3D L"Wildcard1VarName12"; > + CHAR16 *CheckVar2Name =3D L"Wildcard2VarName34"; > + CHAR16 *CheckVarBName =3D L"WildcardBVarName56"; > + CHAR16 *CheckVarHName =3D L"Wildcard#VarName56"; > + > + // Make sure that two different sets of wildcard numbers match. > + UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolicy.Header, > CheckVar1Name, &mTestGuid1, NULL ) ); > + UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolicy.Header, > CheckVar2Name, &mTestGuid1, NULL ) ); > + > + // Make sure that the non-number charaters don't match. > + UT_ASSERT_FALSE( EvaluatePolicyMatch( &MatchCheckPolicy.Header, > CheckVarBName, &mTestGuid1, NULL ) ); > + > + // Make sure that '#' signs don't match. > + UT_ASSERT_FALSE( EvaluatePolicyMatch( &MatchCheckPolicy.Header, > CheckVarHName, &mTestGuid1, NULL ) ); > + > + return UNIT_TEST_PASSED; > +} > + > +UNIT_TEST_STATUS > +EFIAPI > +WildcardPoliciesShouldMatchDigitsAdvanced ( > + IN UNIT_TEST_CONTEXT Context > + ) > +{ > + SIMPLE_VARIABLE_POLICY_ENTRY MatchCheckPolicy =3D { > + { > + VARIABLE_POLICY_ENTRY_REVISION, > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_300_HASHES_STRING), > + sizeof(VARIABLE_POLICY_ENTRY), > + TEST_GUID_1, > + TEST_POLICY_MIN_SIZE_NULL, > + TEST_POLICY_MAX_SIZE_NULL, > + TEST_POLICY_ATTRIBUTES_NULL, > + TEST_POLICY_ATTRIBUTES_NULL, > + VARIABLE_POLICY_TYPE_NO_LOCK > + }, > + TEST_300_HASHES_STRING > + }; > + CHAR16 *CheckShorterString =3D > L"01234567890123456789012345678901234567890123456789"; > + CHAR16 *CheckValidString =3D > L"01234567890123456789012345678901234567890123456789"\ > + > "01234567890123456789012345678901234567890123456789"\ > + > "01234567890123456789012345678901234567890123456789"\ > + > "01234567890123456789012345678901234567890123456789"\ > + > "01234567890123456789012345678901234567890123456789"\ > + > "01234567890123456789012345678901234567890123456789"; > + CHAR16 *CheckLongerString =3D > L"01234567890123456789012345678901234567890123456789"\ > + > "01234567890123456789012345678901234567890123456789"\ > + > "01234567890123456789012345678901234567890123456789"\ > + > "01234567890123456789012345678901234567890123456789"\ > + > "01234567890123456789012345678901234567890123456789"\ > + > "01234567890123456789012345678901234567890123456789"\ > + > "01234567890123456789012345678901234567890123456789"; > + UINT8 MatchPriority; > + > + // Make sure that the shorter and the longer do not match. > + UT_ASSERT_FALSE( EvaluatePolicyMatch( &MatchCheckPolicy.Header, > CheckShorterString, &mTestGuid1, NULL ) ); > + UT_ASSERT_FALSE( EvaluatePolicyMatch( &MatchCheckPolicy.Header, > CheckLongerString, &mTestGuid1, NULL ) ); > + > + // Make sure that the valid one matches and has the expected priority= . > + UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolicy.Header, > CheckValidString, &mTestGuid1, &MatchPriority ) ); > + UT_ASSERT_EQUAL( MatchPriority, MAX_UINT8 ); > + > + return UNIT_TEST_PASSED; > +} > + > +UNIT_TEST_STATUS > +EFIAPI > +WildcardPoliciesShouldMatchNamespaces ( > + IN UNIT_TEST_CONTEXT Context > + ) > +{ > + VARIABLE_POLICY_ENTRY MatchCheckPolicy =3D { > + VARIABLE_POLICY_ENTRY_REVISION, > + sizeof(VARIABLE_POLICY_ENTRY), > + sizeof(VARIABLE_POLICY_ENTRY), > + TEST_GUID_1, > + TEST_POLICY_MIN_SIZE_NULL, > + TEST_POLICY_MAX_SIZE_NULL, > + TEST_POLICY_ATTRIBUTES_NULL, > + TEST_POLICY_ATTRIBUTES_NULL, > + VARIABLE_POLICY_TYPE_NO_LOCK > + }; > + CHAR16 *CheckVar1Name =3D L"Wildcard1VarName12"; > + CHAR16 *CheckVar2Name =3D L"Wildcard2VarName34"; > + CHAR16 *CheckVarBName =3D L"WildcardBVarName56"; > + CHAR16 *CheckVarHName =3D L"Wildcard#VarName56"; > + > + // Make sure that all names in the same namespace match. > + UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolicy, > CheckVar1Name, &mTestGuid1, NULL ) ); > + UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolicy, > CheckVar2Name, &mTestGuid1, NULL ) ); > + UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolicy, > CheckVarBName, &mTestGuid1, NULL ) ); > + UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolicy, > CheckVarHName, &mTestGuid1, NULL ) ); > + > + // Make sure that different namespace doesn't match. > + UT_ASSERT_FALSE( EvaluatePolicyMatch( &MatchCheckPolicy, > CheckVar1Name, &mTestGuid2, NULL ) ); > + > + > + return UNIT_TEST_PASSED; > +} > + > +UNIT_TEST_STATUS > +EFIAPI > +MatchPrioritiesShouldFollowRules ( > + IN UNIT_TEST_CONTEXT Context > + ) > +{ > + SIMPLE_VARIABLE_POLICY_ENTRY MatchCheckPolicy =3D { > + { > + VARIABLE_POLICY_ENTRY_REVISION, > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(L"Wildcard1VarName12"), > + sizeof(VARIABLE_POLICY_ENTRY), > + TEST_GUID_1, > + TEST_POLICY_MIN_SIZE_NULL, > + TEST_POLICY_MAX_SIZE_NULL, > + TEST_POLICY_ATTRIBUTES_NULL, > + TEST_POLICY_ATTRIBUTES_NULL, > + VARIABLE_POLICY_TYPE_NO_LOCK > + }, > + L"Wildcard1VarName12" > + }; > + CHAR16 CheckVar1Name[] =3D L"Wildcard1VarName12"; > + CHAR16 MatchVar1Name[] =3D L"Wildcard1VarName12"; > + CHAR16 MatchVar2Name[] =3D L"Wildcard#VarName12"; > + CHAR16 MatchVar3Name[] =3D L"Wildcard#VarName#2"; > + CHAR16 MatchVar4Name[] =3D L"Wildcard#VarName##"; > + UINT8 MatchPriority; > + > + // Check with a perfect match. > + CopyMem( &MatchCheckPolicy.Name, MatchVar1Name, > sizeof(MatchVar1Name) ); > + UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolicy.Header, > CheckVar1Name, &mTestGuid1, &MatchPriority ) ); > + UT_ASSERT_EQUAL( MatchPriority, 0 ); > + > + // Check with progressively lower priority matches. > + CopyMem( &MatchCheckPolicy.Name, MatchVar2Name, > sizeof(MatchVar2Name) ); > + UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolicy.Header, > CheckVar1Name, &mTestGuid1, &MatchPriority ) ); > + UT_ASSERT_EQUAL( MatchPriority, 1 ); > + CopyMem( &MatchCheckPolicy.Name, MatchVar3Name, > sizeof(MatchVar3Name) ); > + UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolicy.Header, > CheckVar1Name, &mTestGuid1, &MatchPriority ) ); > + UT_ASSERT_EQUAL( MatchPriority, 2 ); > + CopyMem( &MatchCheckPolicy.Name, MatchVar4Name, > sizeof(MatchVar4Name) ); > + UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolicy.Header, > CheckVar1Name, &mTestGuid1, &MatchPriority ) ); > + UT_ASSERT_EQUAL( MatchPriority, 3 ); > + > + // Check against the entire namespace. > + MatchCheckPolicy.Header.Size =3D sizeof(VARIABLE_POLICY_ENTRY); > + UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolicy.Header, > CheckVar1Name, &mTestGuid1, &MatchPriority ) ); > + UT_ASSERT_EQUAL( MatchPriority, MAX_UINT8 ); > + > + return UNIT_TEST_PASSED; > +} > + > +#endif // INTERNAL_UNIT_TEST > + > + > +///=3D=3D=3D POLICY MANIPULATION SUITE > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > + > +UNIT_TEST_STATUS > +EFIAPI > +RegisterShouldAllowNamespaceWildcards ( > + IN UNIT_TEST_CONTEXT Context > + ) > +{ > + SIMPLE_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { > + { > + VARIABLE_POLICY_ENTRY_REVISION, > + sizeof(VARIABLE_POLICY_ENTRY), > + sizeof(VARIABLE_POLICY_ENTRY), > + TEST_GUID_1, > + TEST_POLICY_MIN_SIZE_NULL, > + TEST_POLICY_MAX_SIZE_NULL, > + TEST_POLICY_ATTRIBUTES_NULL, > + TEST_POLICY_ATTRIBUTES_NULL, > + VARIABLE_POLICY_TYPE_NO_LOCK > + }, > + L"" > + }; > + > + > UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea > der ) ); > + > + return UNIT_TEST_PASSED; > +} > + > +UNIT_TEST_STATUS > +EFIAPI > +RegisterShouldAllowStateVarsForNamespaces ( > + IN UNIT_TEST_CONTEXT Context > + ) > +{ > + EXPANDED_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { > + { > + VARIABLE_POLICY_ENTRY_REVISION, > + 0, // Will be populated by init helper. > + 0, // Will be populated by init helper. > + TEST_GUID_1, > + TEST_POLICY_MIN_SIZE_NULL, > + TEST_POLICY_MAX_SIZE_NULL, > + TEST_POLICY_ATTRIBUTES_NULL, > + TEST_POLICY_ATTRIBUTES_NULL, > + VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE > + }, > + { > + TEST_GUID_2, > + 1, // Value > + 0 // Padding > + }, > + L"", > + L"" > + }; > + UT_ASSERT_TRUE( InitExpVarPolicyStrings( &ValidationPolicy, NULL, > TEST_VAR_2_NAME ) ); > + > + > UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea > der ) ); > + > + return UNIT_TEST_PASSED; > +} > + > +UNIT_TEST_STATUS > +EFIAPI > +RegisterShouldRejectNullPointers ( > + IN UNIT_TEST_CONTEXT Context > + ) > +{ > + UT_ASSERT_EQUAL( RegisterVariablePolicy( NULL ), > EFI_INVALID_PARAMETER ); > + return UNIT_TEST_PASSED; > +} > + > +UNIT_TEST_STATUS > +EFIAPI > +RegisterShouldRejectBadRevisions ( > + IN UNIT_TEST_CONTEXT Context > + ) > +{ > + SIMPLE_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { > + { > + VARIABLE_POLICY_ENTRY_REVISION, > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME), > + sizeof(VARIABLE_POLICY_ENTRY), > + TEST_GUID_1, > + TEST_POLICY_MIN_SIZE_NULL, > + TEST_POLICY_MAX_SIZE_NULL, > + TEST_POLICY_ATTRIBUTES_NULL, > + TEST_POLICY_ATTRIBUTES_NULL, > + VARIABLE_POLICY_TYPE_NO_LOCK > + }, > + TEST_VAR_1_NAME > + }; > + > + ValidationPolicy.Header.Version =3D MAX_UINT32; > + UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), > EFI_INVALID_PARAMETER ); > + > + return UNIT_TEST_PASSED; > +} > + > +UNIT_TEST_STATUS > +EFIAPI > +RegisterShouldRejectBadSizes ( > + IN UNIT_TEST_CONTEXT Context > + ) > +{ > + SIMPLE_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { > + { > + VARIABLE_POLICY_ENTRY_REVISION, > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME), > + sizeof(VARIABLE_POLICY_ENTRY), > + TEST_GUID_1, > + TEST_POLICY_MIN_SIZE_NULL, > + TEST_POLICY_MAX_SIZE_NULL, > + TEST_POLICY_ATTRIBUTES_NULL, > + TEST_POLICY_ATTRIBUTES_NULL, > + VARIABLE_POLICY_TYPE_NO_LOCK > + }, > + TEST_VAR_1_NAME > + }; > + > + ValidationPolicy.Header.Size =3D sizeof(VARIABLE_POLICY_ENTRY) - 2; > + UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), > EFI_INVALID_PARAMETER ); > + > + return UNIT_TEST_PASSED; > +} > + > +UNIT_TEST_STATUS > +EFIAPI > +RegisterShouldRejectBadOffsets ( > + IN UNIT_TEST_CONTEXT Context > + ) > +{ > + EXPANDED_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { > + { > + VARIABLE_POLICY_ENTRY_REVISION, > + 0, // Will be populated by init helper. > + 0, // Will be populated by init helper. > + TEST_GUID_1, > + TEST_POLICY_MIN_SIZE_NULL, > + TEST_POLICY_MAX_SIZE_NULL, > + TEST_POLICY_ATTRIBUTES_NULL, > + TEST_POLICY_ATTRIBUTES_NULL, > + VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE > + }, > + { > + TEST_GUID_2, > + 1, // Value > + 0 // Padding > + }, > + L"", > + L"" > + }; > + UT_ASSERT_TRUE( InitExpVarPolicyStrings( &ValidationPolicy, > TEST_VAR_1_NAME, TEST_VAR_2_NAME ) ); > + > + // Check for an offset outside the size bounds. > + ValidationPolicy.Header.OffsetToName =3D ValidationPolicy.Header.Size= + 1; > + UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), > EFI_INVALID_PARAMETER ); > + > + // Check for an offset inside the policy header. > + ValidationPolicy.Header.OffsetToName =3D sizeof(VARIABLE_POLICY_ENTRY= ) > - 2; > + UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), > EFI_INVALID_PARAMETER ); > + > + // Check for an offset inside the state policy header. > + ValidationPolicy.Header.OffsetToName =3D sizeof(VARIABLE_POLICY_ENTRY= ) > + 2; > + UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), > EFI_INVALID_PARAMETER ); > + > + // Check for a ridiculous offset. > + ValidationPolicy.Header.OffsetToName =3D MAX_UINT16; > + UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), > EFI_INVALID_PARAMETER ); > + > + return UNIT_TEST_PASSED; > +} > + > +UNIT_TEST_STATUS > +EFIAPI > +RegisterShouldRejectMissingStateStrings ( > + IN UNIT_TEST_CONTEXT Context > + ) > +{ > + EXPANDED_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { > + { > + VARIABLE_POLICY_ENTRY_REVISION, > + 0, // Will be populated by init helper. > + 0, // Will be populated by init helper. > + TEST_GUID_1, > + TEST_POLICY_MIN_SIZE_NULL, > + TEST_POLICY_MAX_SIZE_NULL, > + TEST_POLICY_ATTRIBUTES_NULL, > + TEST_POLICY_ATTRIBUTES_NULL, > + VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE > + }, > + { > + TEST_GUID_2, > + 1, // Value > + 0 // Padding > + }, > + L"", > + L"" > + }; > + UT_ASSERT_TRUE( InitExpVarPolicyStrings( &ValidationPolicy, > TEST_VAR_1_NAME, TEST_VAR_2_NAME ) ); > + > + // Remove the state string and copy the Name into it's place. > + // Also adjust the offset. > + ValidationPolicy.Header.Size =3D sizeof(VARIABLE_POLICY_ENTR= Y) + > sizeof(VARIABLE_LOCK_ON_VAR_STATE_POLICY) + > sizeof(TEST_VAR_1_NAME); > + ValidationPolicy.Header.OffsetToName =3D sizeof(VARIABLE_POLICY_ENTR= Y) > + sizeof(VARIABLE_LOCK_ON_VAR_STATE_POLICY); > + CopyMem( (UINT8*)&ValidationPolicy + > ValidationPolicy.Header.OffsetToName, TEST_VAR_1_NAME, > sizeof(TEST_VAR_1_NAME) ); > + > + // Make sure that this structure fails. > + UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), > EFI_INVALID_PARAMETER ); > + > + return UNIT_TEST_PASSED; > +} > + > +UNIT_TEST_STATUS > +EFIAPI > +RegisterShouldRejectStringsMissingNull ( > + IN UNIT_TEST_CONTEXT Context > + ) > +{ > + EXPANDED_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { > + { > + VARIABLE_POLICY_ENTRY_REVISION, > + 0, // Will be populated by init helper. > + 0, // Will be populated by init helper. > + TEST_GUID_1, > + TEST_POLICY_MIN_SIZE_NULL, > + TEST_POLICY_MAX_SIZE_NULL, > + TEST_POLICY_ATTRIBUTES_NULL, > + TEST_POLICY_ATTRIBUTES_NULL, > + VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE > + }, > + { > + TEST_GUID_2, > + 1, // Value > + 0 // Padding > + }, > + L"", > + L"" > + }; > + UT_ASSERT_TRUE( InitExpVarPolicyStrings( &ValidationPolicy, > TEST_VAR_1_NAME, TEST_VAR_2_NAME ) ); > + > + // Removing the NULL from the Name should fail. > + ValidationPolicy.Header.Size =3D ValidationPolicy.Header.Size - > sizeof(CHAR16); > + UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), > EFI_INVALID_PARAMETER ); > + > + // Removing the NULL from the State Name is a little trickier. > + // Copy the Name up one byte. > + ValidationPolicy.Header.OffsetToName =3D > ValidationPolicy.Header.OffsetToName - sizeof(CHAR16); > + CopyMem( (UINT8*)&ValidationPolicy + > ValidationPolicy.Header.OffsetToName, TEST_VAR_1_NAME, > sizeof(TEST_VAR_1_NAME) ); > + UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), > EFI_INVALID_PARAMETER ); > + > + return UNIT_TEST_PASSED; > +} > + > +UNIT_TEST_STATUS > +EFIAPI > +RegisterShouldRejectMalformedStrings ( > + IN UNIT_TEST_CONTEXT Context > + ) > +{ > + EXPANDED_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { > + { > + VARIABLE_POLICY_ENTRY_REVISION, > + 0, // Will be populated by init helper. > + 0, // Will be populated by init helper. > + TEST_GUID_1, > + TEST_POLICY_MIN_SIZE_NULL, > + TEST_POLICY_MAX_SIZE_NULL, > + TEST_POLICY_ATTRIBUTES_NULL, > + TEST_POLICY_ATTRIBUTES_NULL, > + VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE > + }, > + { > + TEST_GUID_2, > + 1, // Value > + 0 // Padding > + }, > + L"", > + L"" > + }; > + UT_ASSERT_TRUE( InitExpVarPolicyStrings( &ValidationPolicy, > TEST_VAR_1_NAME, TEST_VAR_2_NAME ) ); > + > + // Bisecting the NULL from the Name should fail. > + ValidationPolicy.Header.Size =3D ValidationPolicy.Header.Size - 1; > + UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), > EFI_INVALID_PARAMETER ); > + > + // Bisecting the NULL from the State Name is a little trickier. > + // Copy the Name up one byte. > + ValidationPolicy.Header.OffsetToName =3D > ValidationPolicy.Header.OffsetToName - 1; > + CopyMem( (UINT8*)&ValidationPolicy + > ValidationPolicy.Header.OffsetToName, TEST_VAR_1_NAME, > sizeof(TEST_VAR_1_NAME) ); > + UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), > EFI_INVALID_PARAMETER ); > + > + return UNIT_TEST_PASSED; > +} > + > +UNIT_TEST_STATUS > +EFIAPI > +RegisterShouldRejectUnpackedPolicies ( > + IN UNIT_TEST_CONTEXT Context > + ) > +{ > + EXPANDED_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { > + { > + VARIABLE_POLICY_ENTRY_REVISION, > + 0, // Will be populated by init helper. > + 0, // Will be populated by init helper. > + TEST_GUID_1, > + TEST_POLICY_MIN_SIZE_NULL, > + TEST_POLICY_MAX_SIZE_NULL, > + TEST_POLICY_ATTRIBUTES_NULL, > + TEST_POLICY_ATTRIBUTES_NULL, > + VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE > + }, > + { > + TEST_GUID_2, > + 1, // Value > + 0 // Padding > + }, > + L"", > + L"" > + }; > + UT_ASSERT_TRUE( InitExpVarPolicyStrings( &ValidationPolicy, > TEST_VAR_1_NAME, TEST_VAR_2_NAME ) ); > + > + // Increase the size and move the Name out a bit. > + ValidationPolicy.Header.Size =3D ValidationPolicy.Header.Size + > sizeof(CHAR16); > + ValidationPolicy.Header.OffsetToName =3D > ValidationPolicy.Header.OffsetToName + sizeof(CHAR16); > + CopyMem( (UINT8*)&ValidationPolicy + > ValidationPolicy.Header.OffsetToName, TEST_VAR_1_NAME, > sizeof(TEST_VAR_1_NAME) ); > + UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), > EFI_INVALID_PARAMETER ); > + > + // Reintialize without the state policy and try the same test. > + ValidationPolicy.Header.LockPolicyType =3D > VARIABLE_POLICY_TYPE_NO_LOCK; > + UT_ASSERT_TRUE( InitExpVarPolicyStrings( &ValidationPolicy, > TEST_VAR_1_NAME, NULL ) ); > + ValidationPolicy.Header.Size =3D ValidationPolicy.Header.Size + > sizeof(CHAR16); > + ValidationPolicy.Header.OffsetToName =3D > ValidationPolicy.Header.OffsetToName + sizeof(CHAR16); > + CopyMem( (UINT8*)&ValidationPolicy + > ValidationPolicy.Header.OffsetToName, TEST_VAR_1_NAME, > sizeof(TEST_VAR_1_NAME) ); > + UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), > EFI_INVALID_PARAMETER ); > + > + return UNIT_TEST_PASSED; > +} > + > +UNIT_TEST_STATUS > +EFIAPI > +RegisterShouldRejectInvalidNameCharacters ( > + IN UNIT_TEST_CONTEXT Context > + ) > +{ > + // EXPANDED_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { > + // { > + // VARIABLE_POLICY_ENTRY_REVISION, > + // 0, // Will be populated by init helper. > + // 0, // Will be populated by init helper. > + // TEST_GUID_1, > + // TEST_POLICY_MIN_SIZE_NULL, > + // TEST_POLICY_MAX_SIZE_NULL, > + // TEST_POLICY_ATTRIBUTES_NULL, > + // TEST_POLICY_ATTRIBUTES_NULL, > + // VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE > + // }, > + // { > + // TEST_GUID_2, > + // 1, // Value > + // 0 // Padding > + // }, > + // L"", > + // L"" > + // }; > + > + // Currently, there are no known invalid characters. > + // '#' in LockPolicy->Name are taken as literal. > + > + return UNIT_TEST_PASSED; > +} > + > +UNIT_TEST_STATUS > +EFIAPI > +RegisterShouldRejectBadPolicyConstraints ( > + IN UNIT_TEST_CONTEXT Context > + ) > +{ > + SIMPLE_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { > + { > + VARIABLE_POLICY_ENTRY_REVISION, > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME), > + sizeof(VARIABLE_POLICY_ENTRY), > + TEST_GUID_1, > + TEST_POLICY_MIN_SIZE_NULL, > + TEST_POLICY_MAX_SIZE_NULL, > + TEST_POLICY_ATTRIBUTES_NULL, > + TEST_POLICY_ATTRIBUTES_NULL, > + VARIABLE_POLICY_TYPE_NO_LOCK > + }, > + TEST_VAR_1_NAME > + }; > + > + // Make sure that invalid MAXes are rejected. > + ValidationPolicy.Header.MaxSize =3D 0; > + UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), > EFI_INVALID_PARAMETER ); > + > + return UNIT_TEST_PASSED; > +} > + > +UNIT_TEST_STATUS > +EFIAPI > +RegisterShouldRejectUnknownLockPolicies ( > + IN UNIT_TEST_CONTEXT Context > + ) > +{ > + SIMPLE_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { > + { > + VARIABLE_POLICY_ENTRY_REVISION, > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME), > + sizeof(VARIABLE_POLICY_ENTRY), > + TEST_GUID_1, > + TEST_POLICY_MIN_SIZE_NULL, > + TEST_POLICY_MAX_SIZE_NULL, > + TEST_POLICY_ATTRIBUTES_NULL, > + TEST_POLICY_ATTRIBUTES_NULL, > + VARIABLE_POLICY_TYPE_NO_LOCK > + }, > + TEST_VAR_1_NAME > + }; > + > + ValidationPolicy.Header.LockPolicyType =3D > VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE + 1; > + UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), > EFI_INVALID_PARAMETER ); > + ValidationPolicy.Header.LockPolicyType =3D > VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE + 1; > + UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), > EFI_INVALID_PARAMETER ); > + > + return UNIT_TEST_PASSED; > +} > + > +UNIT_TEST_STATUS > +EFIAPI > +RegisterShouldRejectPolicesWithTooManyWildcards ( > + IN UNIT_TEST_CONTEXT Context > + ) > +{ > + SIMPLE_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { > + { > + VARIABLE_POLICY_ENTRY_REVISION, > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_300_HASHES_STRING), > + sizeof(VARIABLE_POLICY_ENTRY), > + TEST_GUID_1, > + TEST_POLICY_MIN_SIZE_NULL, > + TEST_POLICY_MAX_SIZE_NULL, > + TEST_POLICY_ATTRIBUTES_NULL, > + TEST_POLICY_ATTRIBUTES_NULL, > + VARIABLE_POLICY_TYPE_NO_LOCK > + }, > + TEST_300_HASHES_STRING > + }; > + > + // 300 Hashes is currently larger than the possible maximum match pri= ority. > + UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), > EFI_INVALID_PARAMETER ); > + > + return UNIT_TEST_PASSED; > +} > + > +UNIT_TEST_STATUS > +EFIAPI > +RegisterShouldRejectDuplicatePolicies ( > + IN UNIT_TEST_CONTEXT Context > + ) > +{ > + SIMPLE_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { > + { > + VARIABLE_POLICY_ENTRY_REVISION, > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME), > + sizeof(VARIABLE_POLICY_ENTRY), > + TEST_GUID_1, > + TEST_POLICY_MIN_SIZE_NULL, > + TEST_POLICY_MAX_SIZE_NULL, > + TEST_POLICY_ATTRIBUTES_NULL, > + TEST_POLICY_ATTRIBUTES_NULL, > + VARIABLE_POLICY_TYPE_NO_LOCK > + }, > + TEST_VAR_1_NAME > + }; > + > + > UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea > der ) ); > + > UT_ASSERT_STATUS_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Head > er ), EFI_ALREADY_STARTED ); > + > + return UNIT_TEST_PASSED; > +} > + > +UNIT_TEST_STATUS > +EFIAPI > +MinAndMaxSizePoliciesShouldBeHonored ( > + IN UNIT_TEST_CONTEXT Context > + ) > +{ > + SIMPLE_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { > + { > + VARIABLE_POLICY_ENTRY_REVISION, > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME), > + sizeof(VARIABLE_POLICY_ENTRY), > + TEST_GUID_1, > + TEST_POLICY_MIN_SIZE_10, > + TEST_POLICY_MAX_SIZE_200, > + TEST_POLICY_ATTRIBUTES_NULL, > + TEST_POLICY_ATTRIBUTES_NULL, > + VARIABLE_POLICY_TYPE_NO_LOCK > + }, > + TEST_VAR_1_NAME > + }; > + EFI_STATUS PolicyCheck; > + UINT8 DummyData[TEST_POLICY_MAX_SIZE_200+1]; > + > + > + // Without a policy, there should be no constraints on variable creat= ion. > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > + &mTestGuid1, > + VARIABLE_ATTRIBUTE_NV_BS, > + TEST_POLICY_MAX_SIZE_200+1, > + DummyData ); > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); > + > + // Set a policy to test against. > + > UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea > der ) ); > + > + // With a policy, make sure that sizes outsize the target range fail. > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > + &mTestGuid1, > + VARIABLE_ATTRIBUTE_NV_BS, > + TEST_POLICY_MAX_SIZE_200+1, > + DummyData ); > + UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) ); > + > + // With a policy, make sure that sizes outsize the target range fail. > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > + &mTestGuid1, > + VARIABLE_ATTRIBUTE_NV_BS, > + TEST_POLICY_MIN_SIZE_10-1, > + DummyData ); > + UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) ); > + > + // With a policy, make sure a valid variable is still valid. > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > + &mTestGuid1, > + VARIABLE_ATTRIBUTE_NV_BS, > + TEST_POLICY_MIN_SIZE_10+1, > + DummyData ); > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); > + > + return UNIT_TEST_PASSED; > +} > + > +UNIT_TEST_STATUS > +EFIAPI > +AttributeMustPoliciesShouldBeHonored ( > + IN UNIT_TEST_CONTEXT Context > + ) > +{ > + SIMPLE_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { > + { > + VARIABLE_POLICY_ENTRY_REVISION, > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME), > + sizeof(VARIABLE_POLICY_ENTRY), > + TEST_GUID_1, > + TEST_POLICY_MIN_SIZE_NULL, > + TEST_POLICY_MAX_SIZE_NULL, > + VARIABLE_ATTRIBUTE_NV_BS_RT, > + TEST_POLICY_ATTRIBUTES_NULL, > + VARIABLE_POLICY_TYPE_NO_LOCK > + }, > + TEST_VAR_1_NAME > + }; > + EFI_STATUS PolicyCheck; > + UINT8 DummyData[12]; > + > + > + // Without a policy, there should be no constraints on variable creat= ion. > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > + &mTestGuid1, > + TEST_POLICY_ATTRIBUTES_NULL, > + sizeof(DummyData), > + DummyData ); > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); > + > + // Set a policy to test against. > + > UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea > der ) ); > + > + // With a policy, make sure that no attributes fail. > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > + &mTestGuid1, > + TEST_POLICY_ATTRIBUTES_NULL, > + sizeof(DummyData), > + DummyData ); > + UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) ); > + > + // With a policy, make sure that some -- but not all -- attributes fa= il. > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > + &mTestGuid1, > + VARIABLE_ATTRIBUTE_BS_RT_AT, > + sizeof(DummyData), > + DummyData ); > + UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) ); > + > + // With a policy, make sure that all attributes pass. > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > + &mTestGuid1, > + VARIABLE_ATTRIBUTE_NV_BS_RT, > + sizeof(DummyData), > + DummyData ); > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); > + > + // With a policy, make sure that all attributes -- plus some -- pass. > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > + &mTestGuid1, > + VARIABLE_ATTRIBUTE_NV_BS_RT_AT, > + sizeof(DummyData), > + DummyData ); > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); > + > + return UNIT_TEST_PASSED; > +} > + > +UNIT_TEST_STATUS > +EFIAPI > +AttributeCantPoliciesShouldBeHonored ( > + IN UNIT_TEST_CONTEXT Context > + ) > +{ > + SIMPLE_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { > + { > + VARIABLE_POLICY_ENTRY_REVISION, > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME), > + sizeof(VARIABLE_POLICY_ENTRY), > + TEST_GUID_1, > + TEST_POLICY_MIN_SIZE_NULL, > + TEST_POLICY_MAX_SIZE_NULL, > + TEST_POLICY_ATTRIBUTES_NULL, > + EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS, > + VARIABLE_POLICY_TYPE_NO_LOCK > + }, > + TEST_VAR_1_NAME > + }; > + EFI_STATUS PolicyCheck; > + UINT8 DummyData[12]; > + > + > + // Without a policy, there should be no constraints on variable creat= ion. > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > + &mTestGuid1, > + VARIABLE_ATTRIBUTE_BS_RT_AT, > + sizeof(DummyData), > + DummyData ); > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); > + > + // Set a policy to test against. > + > UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea > der ) ); > + > + // With a policy, make sure that forbidden attributes fail. > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > + &mTestGuid1, > + > EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS, > + sizeof(DummyData), > + DummyData ); > + UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) ); > + > + // With a policy, make sure that a mixture of attributes -- including= the > forbidden -- fail. > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > + &mTestGuid1, > + VARIABLE_ATTRIBUTE_BS_RT_AT, > + sizeof(DummyData), > + DummyData ); > + UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) ); > + > + // With a policy, make sure that attributes without the forbidden pas= s. > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > + &mTestGuid1, > + VARIABLE_ATTRIBUTE_NV_BS_RT, > + sizeof(DummyData), > + DummyData ); > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); > + > + return UNIT_TEST_PASSED; > +} > + > +UNIT_TEST_STATUS > +EFIAPI > +VariablesShouldBeDeletableRegardlessOfSize ( > + IN UNIT_TEST_CONTEXT Context > + ) > +{ > + SIMPLE_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { > + { > + VARIABLE_POLICY_ENTRY_REVISION, > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME), > + sizeof(VARIABLE_POLICY_ENTRY), > + TEST_GUID_1, > + TEST_POLICY_MIN_SIZE_10, > + TEST_POLICY_MAX_SIZE_NULL, > + TEST_POLICY_ATTRIBUTES_NULL, > + EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS, > + VARIABLE_POLICY_TYPE_NO_LOCK > + }, > + TEST_VAR_1_NAME > + }; > + EFI_STATUS PolicyCheck; > + UINT8 DummyData[TEST_POLICY_MAX_SIZE_200+1]; > + > + // Create a policy enforcing a minimum variable size. > + > UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea > der ) ); > + > + // Make sure that a normal set would fail. > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > + &mTestGuid1, > + VARIABLE_ATTRIBUTE_NV_BS, > + TEST_POLICY_MIN_SIZE_10-1, > + DummyData ); > + UT_ASSERT_STATUS_EQUAL( PolicyCheck, EFI_INVALID_PARAMETER ); > + > + // Now make sure that a delete would succeed. > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > + &mTestGuid1, > + VARIABLE_ATTRIBUTE_NV_BS, > + 0, > + NULL ); > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); > + > + return UNIT_TEST_PASSED; > +} > + > +UNIT_TEST_STATUS > +EFIAPI > +LockNowPoliciesShouldBeHonored ( > + IN UNIT_TEST_CONTEXT Context > + ) > +{ > + SIMPLE_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { > + { > + VARIABLE_POLICY_ENTRY_REVISION, > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME), > + sizeof(VARIABLE_POLICY_ENTRY), > + TEST_GUID_1, > + TEST_POLICY_MIN_SIZE_NULL, > + TEST_POLICY_MAX_SIZE_NULL, > + TEST_POLICY_ATTRIBUTES_NULL, > + TEST_POLICY_ATTRIBUTES_NULL, > + VARIABLE_POLICY_TYPE_LOCK_NOW > + }, > + TEST_VAR_1_NAME > + }; > + EFI_STATUS PolicyCheck; > + UINT8 DummyData[12]; > + > + > + // Without a policy, there should be no constraints on variable creat= ion. > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > + &mTestGuid1, > + VARIABLE_ATTRIBUTE_BS_RT_AT, > + sizeof(DummyData), > + DummyData ); > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); > + > + // Set a policy to test against. > + > UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea > der ) ); > + > + // With a policy, make sure that writes immediately fail. > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > + &mTestGuid1, > + VARIABLE_ATTRIBUTE_BS_RT_AT, > + sizeof(DummyData), > + DummyData ); > + UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) ); > + > + return UNIT_TEST_PASSED; > +} > + > +UNIT_TEST_STATUS > +EFIAPI > +LockOnCreatePoliciesShouldBeHonored ( > + IN UNIT_TEST_CONTEXT Context > + ) > +{ > + SIMPLE_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { > + { > + VARIABLE_POLICY_ENTRY_REVISION, > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME), > + sizeof(VARIABLE_POLICY_ENTRY), > + TEST_GUID_1, > + TEST_POLICY_MIN_SIZE_NULL, > + TEST_POLICY_MAX_SIZE_NULL, > + TEST_POLICY_ATTRIBUTES_NULL, > + TEST_POLICY_ATTRIBUTES_NULL, > + VARIABLE_POLICY_TYPE_LOCK_ON_CREATE > + }, > + TEST_VAR_1_NAME > + }; > + EFI_STATUS PolicyCheck; > + UINT8 DummyData[12]; > + UINTN ExpectedDataSize; > + > + > + // Without a policy, there should be no constraints on variable creat= ion. > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > + &mTestGuid1, > + VARIABLE_ATTRIBUTE_BS_RT_AT, > + sizeof(DummyData), > + DummyData ); > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); > + > + // Set a policy to test against. > + > UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea > der ) ); > + > + // Set consistent expectations on what the calls are looking for. > + expect_memory_count( StubGetVariableNull, VariableName, > TEST_VAR_1_NAME, sizeof(TEST_VAR_1_NAME), 2 ); > + expect_memory_count( StubGetVariableNull, VendorGuid, &mTestGuid1, > sizeof(mTestGuid1), 2 ); > + ExpectedDataSize =3D 0; > + expect_memory_count( StubGetVariableNull, DataSize, > &ExpectedDataSize, sizeof(ExpectedDataSize), 2 ); > + > + // With a policy, make sure that writes still work, since the variabl= e doesn't > exist. > + will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL ); /= / > Attributes > + will_return( StubGetVariableNull, 0 ); /= / Size > + will_return( StubGetVariableNull, NULL ); /= / DataPtr > + will_return( StubGetVariableNull, EFI_NOT_FOUND ); /= / Status > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > + &mTestGuid1, > + VARIABLE_ATTRIBUTE_BS_RT_AT, > + sizeof(DummyData), > + DummyData ); > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); > + > + // With a policy, make sure that a call with an "existing" variable f= ails. > + will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL ); /= / > Attributes > + will_return( StubGetVariableNull, 10 ); /= / Size > + will_return( StubGetVariableNull, NULL ); /= / DataPtr > + will_return( StubGetVariableNull, EFI_BUFFER_TOO_SMALL ); /= / > Status > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > + &mTestGuid1, > + VARIABLE_ATTRIBUTE_BS_RT_AT, > + sizeof(DummyData), > + DummyData ); > + UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) ); > + > + return UNIT_TEST_PASSED; > +} > + > +UNIT_TEST_STATUS > +EFIAPI > +LockOnStatePoliciesShouldBeHonored ( > + IN UNIT_TEST_CONTEXT Context > + ) > +{ > + EXPANDED_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { > + { > + VARIABLE_POLICY_ENTRY_REVISION, > + 0, // Will be populated by init helper. > + 0, // Will be populated by init helper. > + TEST_GUID_1, > + TEST_POLICY_MIN_SIZE_NULL, > + TEST_POLICY_MAX_SIZE_NULL, > + TEST_POLICY_ATTRIBUTES_NULL, > + TEST_POLICY_ATTRIBUTES_NULL, > + VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE > + }, > + { > + TEST_GUID_2, > + 20, // Value > + 0 // Padding > + }, > + L"", > + L"" > + }; > + EFI_STATUS PolicyCheck; > + UINT8 DummyData[12]; > + UINT8 ValidationStateVar; > + UINTN ExpectedDataSize; > + UT_ASSERT_TRUE( InitExpVarPolicyStrings( &ValidationPolicy, > TEST_VAR_1_NAME, TEST_VAR_2_NAME ) ); > + > + > + // Without a policy, there should be no constraints on variable creat= ion. > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > + &mTestGuid1, > + VARIABLE_ATTRIBUTE_BS_RT_AT, > + sizeof(DummyData), > + DummyData ); > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); > + > + // Set a policy to test against. > + > UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea > der ) ); > + > + // Set consistent expectations on what the calls are looking for. > + expect_memory_count( StubGetVariableNull, VariableName, > TEST_VAR_2_NAME, sizeof(TEST_VAR_2_NAME), 5 ); > + expect_memory_count( StubGetVariableNull, VendorGuid, &mTestGuid2, > sizeof(mTestGuid2), 5 ); > + ExpectedDataSize =3D 1; > + expect_memory_count( StubGetVariableNull, DataSize, > &ExpectedDataSize, sizeof(ExpectedDataSize), 5 ); > + > + // With a policy, make sure that writes still work, since the variabl= e doesn't > exist. > + will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL ); /= / > Attributes > + will_return( StubGetVariableNull, 0 ); /= / Size > + will_return( StubGetVariableNull, NULL ); /= / DataPtr > + will_return( StubGetVariableNull, EFI_NOT_FOUND ); /= / Status > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > + &mTestGuid1, > + VARIABLE_ATTRIBUTE_BS_RT_AT, > + sizeof(DummyData), > + DummyData ); > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); > + > + // With a policy, make sure that a state variable that's too large do= esn't lock > the variable. > + will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL ); /= / > Attributes > + will_return( StubGetVariableNull, 10 ); /= / Size > + will_return( StubGetVariableNull, NULL ); /= / DataPtr > + will_return( StubGetVariableNull, EFI_BUFFER_TOO_SMALL ); /= / > Status > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > + &mTestGuid1, > + VARIABLE_ATTRIBUTE_BS_RT_AT, > + sizeof(DummyData), > + DummyData ); > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); > + > + // With a policy, check a state variable with the wrong value. > + ValidationStateVar =3D 0; > + will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL ); /= / > Attributes > + will_return( StubGetVariableNull, sizeof(ValidationStateVar) ); /= / Size > + will_return( StubGetVariableNull, &ValidationStateVar ); /= / DataPtr > + will_return( StubGetVariableNull, EFI_SUCCESS ); /= / Status > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > + &mTestGuid1, > + VARIABLE_ATTRIBUTE_BS_RT_AT, > + sizeof(DummyData), > + DummyData ); > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); > + > + // With a policy, check a state variable with another wrong value. > + ValidationStateVar =3D 10; > + will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL ); /= / > Attributes > + will_return( StubGetVariableNull, sizeof(ValidationStateVar) ); /= / Size > + will_return( StubGetVariableNull, &ValidationStateVar ); /= / DataPtr > + will_return( StubGetVariableNull, EFI_SUCCESS ); /= / Status > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > + &mTestGuid1, > + VARIABLE_ATTRIBUTE_BS_RT_AT, > + sizeof(DummyData), > + DummyData ); > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); > + > + // With a policy, make sure that a call with a correct state variable= fails. > + ValidationStateVar =3D 20; > + will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL ); /= / > Attributes > + will_return( StubGetVariableNull, sizeof(ValidationStateVar) ); /= / Size > + will_return( StubGetVariableNull, &ValidationStateVar ); /= / DataPtr > + will_return( StubGetVariableNull, EFI_SUCCESS ); /= / Status > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > + &mTestGuid1, > + VARIABLE_ATTRIBUTE_BS_RT_AT, > + sizeof(DummyData), > + DummyData ); > + UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) ); > + > + return UNIT_TEST_PASSED; > +} > + > +UNIT_TEST_STATUS > +EFIAPI > +LockOnStatePoliciesShouldApplyToNamespaces ( > + IN UNIT_TEST_CONTEXT Context > + ) > +{ > + EXPANDED_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { > + { > + VARIABLE_POLICY_ENTRY_REVISION, > + 0, // Will be populated by init helper. > + 0, // Will be populated by init helper. > + TEST_GUID_1, > + TEST_POLICY_MIN_SIZE_NULL, > + TEST_POLICY_MAX_SIZE_NULL, > + TEST_POLICY_ATTRIBUTES_NULL, > + TEST_POLICY_ATTRIBUTES_NULL, > + VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE > + }, > + { > + TEST_GUID_2, > + 20, // Value > + 0 // Padding > + }, > + L"", > + L"" > + }; > + EFI_STATUS PolicyCheck; > + UINT8 DummyData[12]; > + UINT8 ValidationStateVar; > + UINTN ExpectedDataSize; > + UT_ASSERT_TRUE( InitExpVarPolicyStrings( &ValidationPolicy, NULL, > TEST_VAR_2_NAME ) ); > + > + > + // Without a policy, there should be no constraints on variable creat= ion. > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > + &mTestGuid1, > + VARIABLE_ATTRIBUTE_BS_RT_AT, > + sizeof(DummyData), > + DummyData ); > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_3_NAME, > + &mTestGuid1, > + VARIABLE_ATTRIBUTE_BS_RT_AT, > + sizeof(DummyData), > + DummyData ); > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); > + > + // Set a policy to test against. > + > UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea > der ) ); > + > + // Set consistent expectations on what the calls are looking for. > + expect_memory_count( StubGetVariableNull, VariableName, > TEST_VAR_2_NAME, sizeof(TEST_VAR_2_NAME), 4 ); > + expect_memory_count( StubGetVariableNull, VendorGuid, &mTestGuid2, > sizeof(mTestGuid2), 4 ); > + ExpectedDataSize =3D 1; > + expect_memory_count( StubGetVariableNull, DataSize, > &ExpectedDataSize, sizeof(ExpectedDataSize), 4 ); > + > + // With a policy, make sure that writes still work, since the variabl= e doesn't > exist. > + will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL ); /= / > Attributes > + will_return( StubGetVariableNull, 0 ); /= / Size > + will_return( StubGetVariableNull, NULL ); /= / DataPtr > + will_return( StubGetVariableNull, EFI_NOT_FOUND ); /= / Status > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > + &mTestGuid1, > + VARIABLE_ATTRIBUTE_BS_RT_AT, > + sizeof(DummyData), > + DummyData ); > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); > + will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL ); /= / > Attributes > + will_return( StubGetVariableNull, 0 ); /= / Size > + will_return( StubGetVariableNull, NULL ); /= / DataPtr > + will_return( StubGetVariableNull, EFI_NOT_FOUND ); /= / Status > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_3_NAME, > + &mTestGuid1, > + VARIABLE_ATTRIBUTE_BS_RT_AT, > + sizeof(DummyData), > + DummyData ); > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); > + > + // With a policy, make sure that a call with a correct state variable= fails. > + ValidationStateVar =3D 20; > + will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL ); /= / > Attributes > + will_return( StubGetVariableNull, sizeof(ValidationStateVar) ); /= / Size > + will_return( StubGetVariableNull, &ValidationStateVar ); /= / DataPtr > + will_return( StubGetVariableNull, EFI_SUCCESS ); /= / Status > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > + &mTestGuid1, > + VARIABLE_ATTRIBUTE_BS_RT_AT, > + sizeof(DummyData), > + DummyData ); > + UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) ); > + will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL ); /= / > Attributes > + will_return( StubGetVariableNull, sizeof(ValidationStateVar) ); /= / Size > + will_return( StubGetVariableNull, &ValidationStateVar ); /= / DataPtr > + will_return( StubGetVariableNull, EFI_SUCCESS ); /= / Status > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_3_NAME, > + &mTestGuid1, > + VARIABLE_ATTRIBUTE_BS_RT_AT, > + sizeof(DummyData), > + DummyData ); > + UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) ); > + > + return UNIT_TEST_PASSED; > +} > + > +UNIT_TEST_STATUS > +EFIAPI > +LockOnStateShouldHandleErrorsGracefully ( > + IN UNIT_TEST_CONTEXT Context > + ) > +{ > + EXPANDED_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { > + { > + VARIABLE_POLICY_ENTRY_REVISION, > + 0, // Will be populated by init helper. > + 0, // Will be populated by init helper. > + TEST_GUID_1, > + TEST_POLICY_MIN_SIZE_NULL, > + TEST_POLICY_MAX_SIZE_NULL, > + TEST_POLICY_ATTRIBUTES_NULL, > + TEST_POLICY_ATTRIBUTES_NULL, > + VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE > + }, > + { > + TEST_GUID_2, > + 20, // Value > + 0 // Padding > + }, > + L"", > + L"" > + }; > + EFI_STATUS PolicyCheck; > + UINT8 DummyData[12]; > + UT_ASSERT_TRUE( InitExpVarPolicyStrings( &ValidationPolicy, > TEST_VAR_1_NAME, TEST_VAR_2_NAME ) ); > + > + > + // Without a policy, there should be no constraints on variable creat= ion. > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > + &mTestGuid1, > + VARIABLE_ATTRIBUTE_BS_RT_AT, > + sizeof(DummyData), > + DummyData ); > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); > + > + // Set a policy to test against. > + > UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea > der ) ); > + > + // Configure the stub to not care about parameters. We're testing err= ors. > + expect_any_always( StubGetVariableNull, VariableName ); > + expect_any_always( StubGetVariableNull, VendorGuid ); > + expect_any_always( StubGetVariableNull, DataSize ); > + > + // With a policy, make sure that writes still work, since the variabl= e doesn't > exist. > + will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL ); /= / > Attributes > + will_return( StubGetVariableNull, 0 ); /= / Size > + will_return( StubGetVariableNull, NULL ); /= / DataPtr > + will_return( StubGetVariableNull, EFI_NOT_FOUND ); /= / Status > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > + &mTestGuid1, > + VARIABLE_ATTRIBUTE_BS_RT_AT, > + sizeof(DummyData), > + DummyData ); > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); > + > + // Verify that state variables that are the wrong size won't lock the= variable. > + will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL ); /= / > Attributes > + will_return( StubGetVariableNull, 0 ); /= / Size > + will_return( StubGetVariableNull, NULL ); /= / DataPtr > + will_return( StubGetVariableNull, EFI_BUFFER_TOO_SMALL ); /= / > Status > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > + &mTestGuid1, > + VARIABLE_ATTRIBUTE_BS_RT_AT, > + sizeof(DummyData), > + DummyData ); > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); > + > + // Verify that unexpected errors default to locked. > + will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL ); /= / > Attributes > + will_return( StubGetVariableNull, 0 ); /= / Size > + will_return( StubGetVariableNull, NULL ); /= / DataPtr > + will_return( StubGetVariableNull, EFI_UNSUPPORTED ); /= / Status > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > + &mTestGuid1, > + VARIABLE_ATTRIBUTE_BS_RT_AT, > + sizeof(DummyData), > + DummyData ); > + UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) ); > + > + will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL ); /= / > Attributes > + will_return( StubGetVariableNull, 0 ); /= / Size > + will_return( StubGetVariableNull, NULL ); /= / DataPtr > + will_return( StubGetVariableNull, EFI_NOT_READY ); /= / Status > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > + &mTestGuid1, > + VARIABLE_ATTRIBUTE_BS_RT_AT, > + sizeof(DummyData), > + DummyData ); > + UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) ); > + > + return UNIT_TEST_PASSED; > +} > + > +UNIT_TEST_STATUS > +EFIAPI > +BestMatchPriorityShouldBeObeyed ( > + IN UNIT_TEST_CONTEXT Context > + ) > +{ > + SIMPLE_VARIABLE_POLICY_ENTRY ValidationPolicy =3D { > + { > + VARIABLE_POLICY_ENTRY_REVISION, > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(L"Wild12Card34Placeholder"= ), > + sizeof(VARIABLE_POLICY_ENTRY), > + TEST_GUID_1, > + TEST_POLICY_MIN_SIZE_NULL, > + TEST_POLICY_MAX_SIZE_NULL, > + TEST_POLICY_ATTRIBUTES_NULL, > + TEST_POLICY_ATTRIBUTES_NULL, > + VARIABLE_POLICY_TYPE_NO_LOCK > + }, > + L"Wild12Card34Placeholder" > + }; > + EFI_STATUS PolicyCheck; > + UINT8 DummyData[70]; > + CHAR16 *PolicyName =3D (CHAR16*)((UINT8*)&ValidationPolicy + > sizeof(VARIABLE_POLICY_ENTRY)); > + UINTN PolicyNameSize =3D sizeof(L"Wild12Card34Placeholder"); > + CHAR16 *FourWildcards =3D L"Wild##Card##Placeholder"; > + CHAR16 *ThreeWildcards =3D L"Wild##Card#4Placeholder"; > + CHAR16 *TwoWildcards =3D L"Wild##Card34Placeholder"; > + CHAR16 *OneWildcard =3D L"Wild#2Card34Placeholder"; > + CHAR16 *NoWildcards =3D L"Wild12Card34Placeholder"; > + > + // Create all of the policies from least restrictive to most restrict= ive. > + // NoWildcards should be the most restrictive. > + ValidationPolicy.Header.MaxSize =3D 60; > + ValidationPolicy.Header.Size =3D ValidationPolicy.Header.OffsetToName= ; > + > UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea > der ) ); > + ValidationPolicy.Header.Size +=3D (UINT16)PolicyNameSize; > + ValidationPolicy.Header.MaxSize =3D 50; > + CopyMem( PolicyName, FourWildcards, PolicyNameSize ); > + > UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea > der ) ); > + ValidationPolicy.Header.MaxSize =3D 40; > + CopyMem( PolicyName, ThreeWildcards, PolicyNameSize ); > + > UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea > der ) ); > + ValidationPolicy.Header.MaxSize =3D 30; > + CopyMem( PolicyName, TwoWildcards, PolicyNameSize ); > + > UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea > der ) ); > + ValidationPolicy.Header.MaxSize =3D 20; > + CopyMem( PolicyName, OneWildcard, PolicyNameSize ); > + > UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea > der ) ); > + ValidationPolicy.Header.MaxSize =3D 10; > + CopyMem( PolicyName, NoWildcards, PolicyNameSize ); > + > UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea > der ) ); > + > + // Verify that variables only matching the namespace have the most > flexible policy. > + PolicyCheck =3D ValidateSetVariable( L"ArbitraryName", > + &mTestGuid1, > + VARIABLE_ATTRIBUTE_BS_RT_AT, > + 65, > + DummyData ); > + UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) ); > + PolicyCheck =3D ValidateSetVariable( L"ArbitraryName", > + &mTestGuid1, > + VARIABLE_ATTRIBUTE_BS_RT_AT, > + 55, > + DummyData ); > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); > + > + // Verify that variables matching increasing characters get increasin= g policy > restrictions. > + PolicyCheck =3D ValidateSetVariable( L"Wild77Card77Placeholder", > + &mTestGuid1, > + VARIABLE_ATTRIBUTE_BS_RT_AT, > + 55, > + DummyData ); > + UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) ); > + PolicyCheck =3D ValidateSetVariable( L"Wild77Card77Placeholder", > + &mTestGuid1, > + VARIABLE_ATTRIBUTE_BS_RT_AT, > + 45, > + DummyData ); > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); > + > + PolicyCheck =3D ValidateSetVariable( L"Wild77Card74Placeholder", > + &mTestGuid1, > + VARIABLE_ATTRIBUTE_BS_RT_AT, > + 45, > + DummyData ); > + UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) ); > + PolicyCheck =3D ValidateSetVariable( L"Wild77Card74Placeholder", > + &mTestGuid1, > + VARIABLE_ATTRIBUTE_BS_RT_AT, > + 35, > + DummyData ); > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); > + > + PolicyCheck =3D ValidateSetVariable( L"Wild77Card34Placeholder", > + &mTestGuid1, > + VARIABLE_ATTRIBUTE_BS_RT_AT, > + 35, > + DummyData ); > + UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) ); > + PolicyCheck =3D ValidateSetVariable( L"Wild77Card34Placeholder", > + &mTestGuid1, > + VARIABLE_ATTRIBUTE_BS_RT_AT, > + 25, > + DummyData ); > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); > + > + PolicyCheck =3D ValidateSetVariable( L"Wild72Card34Placeholder", > + &mTestGuid1, > + VARIABLE_ATTRIBUTE_BS_RT_AT, > + 25, > + DummyData ); > + UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) ); > + PolicyCheck =3D ValidateSetVariable( L"Wild72Card34Placeholder", > + &mTestGuid1, > + VARIABLE_ATTRIBUTE_BS_RT_AT, > + 15, > + DummyData ); > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); > + > + PolicyCheck =3D ValidateSetVariable( L"Wild12Card34Placeholder", > + &mTestGuid1, > + VARIABLE_ATTRIBUTE_BS_RT_AT, > + 15, > + DummyData ); > + UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) ); > + PolicyCheck =3D ValidateSetVariable( L"Wild12Card34Placeholder", > + &mTestGuid1, > + VARIABLE_ATTRIBUTE_BS_RT_AT, > + 5, > + DummyData ); > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); > + > + return UNIT_TEST_PASSED; > +} > + > + > +///=3D=3D=3D POLICY UTILITY SUITE > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D > + > +UNIT_TEST_STATUS > +EFIAPI > +ShouldBeAbleToLockInterface ( > + IN UNIT_TEST_CONTEXT Context > + ) > +{ > + SIMPLE_VARIABLE_POLICY_ENTRY TestPolicy =3D { > + { > + VARIABLE_POLICY_ENTRY_REVISION, > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME), > + sizeof(VARIABLE_POLICY_ENTRY), > + TEST_GUID_1, > + TEST_POLICY_MIN_SIZE_NULL, > + TEST_POLICY_MAX_SIZE_NULL, > + TEST_POLICY_ATTRIBUTES_NULL, > + TEST_POLICY_ATTRIBUTES_NULL, > + VARIABLE_POLICY_TYPE_NO_LOCK > + }, > + TEST_VAR_1_NAME > + }; > + > + // Make sure it's not already locked. > + UT_ASSERT_FALSE( IsVariablePolicyInterfaceLocked() ); > + // Lock it. > + UT_ASSERT_NOT_EFI_ERROR( LockVariablePolicy() ); > + // Verify that it's locked. > + UT_ASSERT_TRUE( IsVariablePolicyInterfaceLocked() ); > + > + // Verify that all state-changing commands fail. > + UT_ASSERT_TRUE( EFI_ERROR( LockVariablePolicy() ) ); > + UT_ASSERT_TRUE( EFI_ERROR( DisableVariablePolicy() ) ); > + > UT_ASSERT_TRUE( EFI_ERROR( RegisterVariablePolicy( &TestPolicy.Header ) > ) ); > + > + return UNIT_TEST_PASSED; > +} > + > +UNIT_TEST_STATUS > +EFIAPI > +ShouldBeAbleToDisablePolicyEnforcement ( > + IN UNIT_TEST_CONTEXT Context > + ) > +{ > + SIMPLE_VARIABLE_POLICY_ENTRY TestPolicy =3D { > + { > + VARIABLE_POLICY_ENTRY_REVISION, > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME), > + sizeof(VARIABLE_POLICY_ENTRY), > + TEST_GUID_1, > + TEST_POLICY_MIN_SIZE_10, > + TEST_POLICY_MAX_SIZE_200, > + TEST_POLICY_ATTRIBUTES_NULL, > + TEST_POLICY_ATTRIBUTES_NULL, > + VARIABLE_POLICY_TYPE_NO_LOCK > + }, > + TEST_VAR_1_NAME > + }; > + EFI_STATUS PolicyCheck; > + UINT8 DummyData[TEST_POLICY_MIN_SIZE_10-1]; > + > + // Make sure that the policy enforcement is currently enabled. > + UT_ASSERT_TRUE( IsVariablePolicyEnabled() ); > + // Add a policy before it's disabled. > + > UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &TestPolicy.Header ) ); > + // Disable the policy enforcement. > + UT_ASSERT_NOT_EFI_ERROR( DisableVariablePolicy() ); > + // Make sure that the policy enforcement is currently disabled. > + UT_ASSERT_FALSE( IsVariablePolicyEnabled() ); > + > + // Check to make sure that a policy violation still passes. > + PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME, > + &mTestGuid1, > + VARIABLE_ATTRIBUTE_NV_BS, > + sizeof(DummyData), > + DummyData ); > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); > + > + return UNIT_TEST_PASSED; > +} > + > +UNIT_TEST_STATUS > +EFIAPI > +ShouldNotBeAbleToDisablePoliciesTwice ( > + IN UNIT_TEST_CONTEXT Context > + ) > +{ > + // Make sure that the policy enforcement is currently enabled. > + UT_ASSERT_TRUE( IsVariablePolicyEnabled() ); > + // Disable the policy enforcement. > + UT_ASSERT_NOT_EFI_ERROR( DisableVariablePolicy() ); > + // Make sure that the policy enforcement is currently disabled. > + UT_ASSERT_FALSE( IsVariablePolicyEnabled() ); > + // Try to disable again and verify failure. > + UT_ASSERT_TRUE( EFI_ERROR( DisableVariablePolicy() ) ); > + > + return UNIT_TEST_PASSED; > +} > + > +UNIT_TEST_STATUS > +EFIAPI > +ShouldBeAbleToAddNewPoliciesAfterDisabled ( > + IN UNIT_TEST_CONTEXT Context > + ) > +{ > + SIMPLE_VARIABLE_POLICY_ENTRY TestPolicy =3D { > + { > + VARIABLE_POLICY_ENTRY_REVISION, > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME), > + sizeof(VARIABLE_POLICY_ENTRY), > + TEST_GUID_1, > + TEST_POLICY_MIN_SIZE_10, > + TEST_POLICY_MAX_SIZE_200, > + TEST_POLICY_ATTRIBUTES_NULL, > + TEST_POLICY_ATTRIBUTES_NULL, > + VARIABLE_POLICY_TYPE_NO_LOCK > + }, > + TEST_VAR_1_NAME > + }; > + EFI_STATUS PolicyCheck; > + > + // Make sure that the policy enforcement is currently enabled. > + UT_ASSERT_TRUE( IsVariablePolicyEnabled() ); > + // Disable the policy enforcement. > + UT_ASSERT_NOT_EFI_ERROR( DisableVariablePolicy() ); > + > + // Make sure that new policy creation still works, it just won't be e= nforced. > + PolicyCheck =3D RegisterVariablePolicy( &TestPolicy.Header ); > + UT_ASSERT_NOT_EFI_ERROR( PolicyCheck ); > + > + return UNIT_TEST_PASSED; > +} > + > +UNIT_TEST_STATUS > +EFIAPI > +ShouldBeAbleToLockAfterDisabled ( > + IN UNIT_TEST_CONTEXT Context > + ) > +{ > + // Make sure that the policy enforcement is currently enabled. > + UT_ASSERT_TRUE( IsVariablePolicyEnabled() ); > + // Disable the policy enforcement. > + UT_ASSERT_NOT_EFI_ERROR( DisableVariablePolicy() ); > + > + // Make sure that we can lock in this state. > + UT_ASSERT_FALSE( IsVariablePolicyInterfaceLocked() ); > + UT_ASSERT_NOT_EFI_ERROR( LockVariablePolicy() ); > + UT_ASSERT_TRUE( IsVariablePolicyInterfaceLocked() ); > + > + return UNIT_TEST_PASSED; > +} > + > +UNIT_TEST_STATUS > +EFIAPI > +ShouldBeAbleToDumpThePolicyTable ( > + IN UNIT_TEST_CONTEXT Context > + ) > +{ > + SIMPLE_VARIABLE_POLICY_ENTRY TestPolicy =3D { > + { > + VARIABLE_POLICY_ENTRY_REVISION, > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME), > + sizeof(VARIABLE_POLICY_ENTRY), > + TEST_GUID_1, > + TEST_POLICY_MIN_SIZE_10, > + TEST_POLICY_MAX_SIZE_200, > + TEST_POLICY_ATTRIBUTES_NULL, > + TEST_POLICY_ATTRIBUTES_NULL, > + VARIABLE_POLICY_TYPE_NO_LOCK > + }, > + TEST_VAR_1_NAME > + }; > + EFI_STATUS PolicyCheck; > + UINT32 DumpSize; > + UINT32 BufferSize; > + VOID *DumpBuffer; > + > + // For good measure, test some parameter validation. > + UT_ASSERT_STATUS_EQUAL( DumpVariablePolicy( NULL, NULL ), > EFI_INVALID_PARAMETER ); > + DumpSize =3D 10; > + UT_ASSERT_STATUS_EQUAL( DumpVariablePolicy( NULL, &DumpSize ), > EFI_INVALID_PARAMETER ); > + > + // Now for the actual test case. > + > + // Allocate a buffer to hold the output. > + BufferSize =3D sizeof(VARIABLE_POLICY_ENTRY) + > sizeof(TEST_VAR_1_NAME); > + DumpBuffer =3D AllocatePool( BufferSize ); > + UT_ASSERT_NOT_EQUAL( DumpBuffer, NULL ); > + > + // Verify that the current table size is 0. > + DumpSize =3D BufferSize; > + UT_ASSERT_NOT_EFI_ERROR( DumpVariablePolicy( DumpBuffer, > &DumpSize ) ); > + UT_ASSERT_EQUAL( DumpSize, 0 ); > + > + // Now, set a new policy. > + > UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &TestPolicy.Header ) ); > + > + // Make sure that the new return is non-zero and fails as expected. > + DumpSize =3D 0; > + PolicyCheck =3D DumpVariablePolicy( NULL, &DumpSize ); > + UT_ASSERT_STATUS_EQUAL( PolicyCheck, EFI_BUFFER_TOO_SMALL ); > + UT_ASSERT_EQUAL( DumpSize, BufferSize ); > + > + // Now verify that we can fetch the dump. > + DumpSize =3D BufferSize; > + UT_ASSERT_NOT_EFI_ERROR( DumpVariablePolicy( DumpBuffer, > &DumpSize ) ); > + UT_ASSERT_EQUAL( DumpSize, BufferSize ); > + UT_ASSERT_MEM_EQUAL( &TestPolicy, DumpBuffer, BufferSize ); > + > + // Always put away your toys. > + FreePool( DumpBuffer ); > + > + return UNIT_TEST_PASSED; > +} > + > +UNIT_TEST_STATUS > +EFIAPI > +ShouldBeAbleToDumpThePolicyTableAfterDisabled ( > + IN UNIT_TEST_CONTEXT Context > + ) > +{ > + SIMPLE_VARIABLE_POLICY_ENTRY TestPolicy =3D { > + { > + VARIABLE_POLICY_ENTRY_REVISION, > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME), > + sizeof(VARIABLE_POLICY_ENTRY), > + TEST_GUID_1, > + TEST_POLICY_MIN_SIZE_10, > + TEST_POLICY_MAX_SIZE_200, > + TEST_POLICY_ATTRIBUTES_NULL, > + TEST_POLICY_ATTRIBUTES_NULL, > + VARIABLE_POLICY_TYPE_NO_LOCK > + }, > + TEST_VAR_1_NAME > + }; > + SIMPLE_VARIABLE_POLICY_ENTRY TestPolicy2 =3D { > + { > + VARIABLE_POLICY_ENTRY_REVISION, > + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_2_NAME), > + sizeof(VARIABLE_POLICY_ENTRY), > + TEST_GUID_2, > + TEST_POLICY_MIN_SIZE_10, > + TEST_POLICY_MAX_SIZE_200, > + TEST_POLICY_ATTRIBUTES_NULL, > + TEST_POLICY_ATTRIBUTES_NULL, > + VARIABLE_POLICY_TYPE_NO_LOCK > + }, > + TEST_VAR_2_NAME > + }; > + EFI_STATUS PolicyCheck; > + UINT32 DumpSize; > + VOID *DumpBuffer; > + > + DumpBuffer =3D NULL; > + DumpSize =3D 0; > + > + // Register a new policy. > + > UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &TestPolicy.Header ) ); > + // Make sure that we can dump the policy. > + PolicyCheck =3D DumpVariablePolicy( DumpBuffer, &DumpSize ); > + UT_ASSERT_STATUS_EQUAL( PolicyCheck, EFI_BUFFER_TOO_SMALL ); > + DumpBuffer =3D AllocatePool( DumpSize ); > + UT_ASSERT_NOT_EFI_ERROR( DumpVariablePolicy( DumpBuffer, > &DumpSize ) ); > + UT_ASSERT_MEM_EQUAL( DumpBuffer, &TestPolicy, DumpSize ); > + > + // Clean up from this step. > + FreePool( DumpBuffer ); > + DumpBuffer =3D NULL; > + DumpSize =3D 0; > + > + // Now disable the engine. > + DisableVariablePolicy(); > + > + // Now register a new policy and make sure that both can be dumped. > + > UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &TestPolicy2.Header ) > ); > + // Make sure that we can dump the policy. > + PolicyCheck =3D DumpVariablePolicy( DumpBuffer, &DumpSize ); > + UT_ASSERT_STATUS_EQUAL( PolicyCheck, EFI_BUFFER_TOO_SMALL ); > + DumpBuffer =3D AllocatePool( DumpSize ); > + UT_ASSERT_NOT_EFI_ERROR( DumpVariablePolicy( DumpBuffer, > &DumpSize ) ); > + > + // Finally, make sure that both policies are in the dump. > + UT_ASSERT_MEM_EQUAL( DumpBuffer, &TestPolicy, > TestPolicy.Header.Size ); > + UT_ASSERT_MEM_EQUAL( (UINT8*)DumpBuffer + TestPolicy.Header.Size, > + &TestPolicy2, > + TestPolicy2.Header.Size ); > + > + // Always put away your toys. > + FreePool( DumpBuffer ); > + > + return UNIT_TEST_PASSED; > +} > + > + > +///=3D=3D=3D TEST ENGINE > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > + > +/** > + SampleUnitTestApp > + > + @param[in] ImageHandle The firmware allocated handle for the EFI ima= ge. > + @param[in] SystemTable A pointer to the EFI System Table. > + > + @retval EFI_SUCCESS The entry point executed successfully. > + @retval other Some error occured when executing this entry = point. > + > +**/ > +int main () > +{ > + EFI_STATUS Status; > + UNIT_TEST_FRAMEWORK_HANDLE Framework =3D NULL; > + UNIT_TEST_SUITE_HANDLE ArchTests; > + UNIT_TEST_SUITE_HANDLE PolicyTests; > + UNIT_TEST_SUITE_HANDLE UtilityTests; > +#ifdef INTERNAL_UNIT_TEST > + UNIT_TEST_SUITE_HANDLE InternalTests; > +#endif // INTERNAL_UNIT_TEST > + > + DEBUG(( DEBUG_INFO, "%a v%a\n", UNIT_TEST_NAME, > UNIT_TEST_VERSION )); > + > + // > + // Start setting up the test framework for running the tests. > + // > + Status =3D InitUnitTestFramework( &Framework, UNIT_TEST_NAME, > gEfiCallerBaseName, UNIT_TEST_VERSION ); > + if (EFI_ERROR( Status )) > + { > + DEBUG((DEBUG_ERROR, "Failed in InitUnitTestFramework. Status =3D %r= \n", > Status)); > + goto EXIT; > + } > + > + > + // > + // Add all test suites and tests. > + // > + Status =3D CreateUnitTestSuite( &ArchTests, Framework, "Variable Poli= cy > Architectural Tests", "VarPolicy.Arch", NULL, NULL ); > + if (EFI_ERROR( Status )) > + { > + DEBUG((DEBUG_ERROR, "Failed in CreateUnitTestSuite for > ArchTests\n")); > + Status =3D EFI_OUT_OF_RESOURCES; > + goto EXIT; > + } > + AddTestCase( ArchTests, > + "Deinitialization should fail if not previously initial= ized", > "VarPolicy.Arch.OnlyDeinit", > + ShouldFailDeinitWithoutInit, NULL, NULL, NULL ); > + AddTestCase( ArchTests, > + "Initialization followed by deinitialization should suc= ceed", > "VarPolicy.Arch.InitDeinit", > + ShouldBeAbleToInitAndDeinitTheLibrary, NULL, NULL, NULL= ); > + AddTestCase( ArchTests, > + "The initialization function fail if called twice witho= ut a deinit", > "VarPolicy.Arch.InitTwice", > + ShouldNotBeAbleToInitializeTheLibraryTwice, NULL, LibCl= eanup, > NULL ); > + AddTestCase( ArchTests, > + "API functions should be unavailable until library is i= nitialized", > "VarPolicy.Arch.UninitApiOff", > + ApiCommandsShouldNotRespondIfLibIsUninitialized, NULL, > LibCleanup, NULL ); > + > +#ifdef INTERNAL_UNIT_TEST > + Status =3D CreateUnitTestSuite( &InternalTests, Framework, "Variable = Policy > Internal Tests", "VarPolicy.Internal", NULL, NULL ); > + if (EFI_ERROR( Status )) > + { > + DEBUG((DEBUG_ERROR, "Failed in CreateUnitTestSuite for > InternalTests\n")); > + Status =3D EFI_OUT_OF_RESOURCES; > + goto EXIT; > + } > + AddTestCase( InternalTests, > + "Policy matching should use name and GUID", > "VarPolicy.Internal.NameGuid", > + PoliciesShouldMatchByNameAndGuid, LibInitMocked, LibCle= anup, > NULL ); > + AddTestCase( InternalTests, > + "# sign wildcards should match digits", > "VarPolicy.Internal.WildDigits", > + WildcardPoliciesShouldMatchDigits, LibInitMocked, LibCl= eanup, > NULL ); > + AddTestCase( InternalTests, > + "Digit wildcards should check edge cases", > "VarPolicy.Internal.WildDigitsAdvanced", > + WildcardPoliciesShouldMatchDigitsAdvanced, LibInitMocke= d, > LibCleanup, NULL ); > + AddTestCase( InternalTests, > + "Empty names should match an entire namespace", > "VarPolicy.Internal.WildNamespace", > + WildcardPoliciesShouldMatchNamespaces, LibInitMocked, > LibCleanup, NULL ); > + AddTestCase( InternalTests, > + "Match priority should weight correctly based on wildca= rds", > "VarPolicy.Internal.Priorities", > + MatchPrioritiesShouldFollowRules, LibInitMocked, LibCle= anup, > NULL ); > +#endif // INTERNAL_UNIT_TEST > + > + Status =3D CreateUnitTestSuite( &PolicyTests, Framework, "Variable Po= licy > Manipulation Tests", "VarPolicy.Policy", NULL, NULL ); > + if (EFI_ERROR( Status )) > + { > + DEBUG((DEBUG_ERROR, "Failed in CreateUnitTestSuite for > PolicyTests\n")); > + Status =3D EFI_OUT_OF_RESOURCES; > + goto EXIT; > + } > + AddTestCase( PolicyTests, > + "RegisterShouldAllowNamespaceWildcards", > "VarPolicy.Policy.AllowNamespace", > + RegisterShouldAllowNamespaceWildcards, LibInitMocked, > LibCleanup, NULL ); > + AddTestCase( PolicyTests, > + "RegisterShouldAllowStateVarsForNamespaces", > "VarPolicy.Policy.AllowStateNamespace", > + RegisterShouldAllowStateVarsForNamespaces, LibInitMocke= d, > LibCleanup, NULL ); > + AddTestCase( PolicyTests, > + "RegisterShouldRejectNullPointers", "VarPolicy.Policy.N= ullPointers", > + RegisterShouldRejectNullPointers, LibInitMocked, LibCle= anup, > NULL ); > + AddTestCase( PolicyTests, > + "RegisterShouldRejectBadRevisions", > "VarPolicy.Policy.BadRevisions", > + RegisterShouldRejectBadRevisions, LibInitMocked, LibCle= anup, > NULL ); > + AddTestCase( PolicyTests, > + "RegisterShouldRejectBadSizes", "VarPolicy.Policy.BadSi= zes", > + RegisterShouldRejectBadSizes, LibInitMocked, LibCleanup= , NULL ); > + AddTestCase( PolicyTests, > + "RegisterShouldRejectBadOffsets", "VarPolicy.Policy.Bad= Offsets", > + RegisterShouldRejectBadOffsets, LibInitMocked, LibClean= up, NULL ); > + AddTestCase( PolicyTests, > + "RegisterShouldRejectMissingStateStrings", > "VarPolicy.Policy.MissingStateString", > + RegisterShouldRejectMissingStateStrings, LibInitMocked, > LibCleanup, NULL ); > + AddTestCase( PolicyTests, > + "RegisterShouldRejectStringsMissingNull", > "VarPolicy.Policy.MissingNull", > + RegisterShouldRejectStringsMissingNull, LibInitMocked, = LibCleanup, > NULL ); > + AddTestCase( PolicyTests, > + "RegisterShouldRejectMalformedStrings", > "VarPolicy.Policy.MalformedStrings", > + RegisterShouldRejectMalformedStrings, LibInitMocked, Li= bCleanup, > NULL ); > + AddTestCase( PolicyTests, > + "RegisterShouldRejectUnpackedPolicies", > "VarPolicy.Policy.PolicyPacking", > + RegisterShouldRejectUnpackedPolicies, LibInitMocked, Li= bCleanup, > NULL ); > + AddTestCase( PolicyTests, > + "RegisterShouldRejectInvalidNameCharacters", > "VarPolicy.Policy.InvalidCharacters", > + RegisterShouldRejectInvalidNameCharacters, LibInitMocke= d, > LibCleanup, NULL ); > + AddTestCase( PolicyTests, > + "RegisterShouldRejectBadPolicyConstraints", > "VarPolicy.Policy.BadConstraints", > + RegisterShouldRejectBadPolicyConstraints, LibInitMocked= , > LibCleanup, NULL ); > + AddTestCase( PolicyTests, > + "RegisterShouldRejectUnknownLockPolicies", > "VarPolicy.Policy.BadLocks", > + RegisterShouldRejectUnknownLockPolicies, LibInitMocked, > LibCleanup, NULL ); > + AddTestCase( PolicyTests, > + "RegisterShouldRejectPolicesWithTooManyWildcards", > "VarPolicy.Policy.TooManyWildcards", > + RegisterShouldRejectPolicesWithTooManyWildcards, LibIni= tMocked, > LibCleanup, NULL ); > + AddTestCase( PolicyTests, > + "RegisterShouldRejectDuplicatePolicies", > "VarPolicy.Policy.DuplicatePolicies", > + RegisterShouldRejectDuplicatePolicies, LibInitMocked, L= ibCleanup, > NULL ); > + AddTestCase( PolicyTests, > + "Variables that exceed min or max sizes should be rejec= ted", > "VarPolicy.Policy.MinMax", > + MinAndMaxSizePoliciesShouldBeHonored, LibInitMocked, > LibCleanup, NULL ); > + AddTestCase( PolicyTests, > + "AttributeMustPoliciesShouldBeHonored", > "VarPolicy.Policy.AttrMust", > + AttributeMustPoliciesShouldBeHonored, LibInitMocked, Li= bCleanup, > NULL ); > + AddTestCase( PolicyTests, > + "AttributeCantPoliciesShouldBeHonored", > "VarPolicy.Policy.AttrCant", > + AttributeCantPoliciesShouldBeHonored, LibInitMocked, Li= bCleanup, > NULL ); > + AddTestCase( PolicyTests, > + "VariablesShouldBeDeletableRegardlessOfSize", > "VarPolicy.Policy.DeleteIgnoreSize", > + VariablesShouldBeDeletableRegardlessOfSize, LibInitMock= ed, > LibCleanup, NULL ); > + AddTestCase( PolicyTests, > + "LockNowPoliciesShouldBeHonored", > "VarPolicy.Policy.VARIABLE_POLICY_TYPE_LOCK_NOW", > + LockNowPoliciesShouldBeHonored, LibInitMocked, LibClean= up, > NULL ); > + AddTestCase( PolicyTests, > + "LockOnCreatePoliciesShouldBeHonored", > "VarPolicy.Policy.VARIABLE_POLICY_TYPE_LOCK_ON_CREATE", > + LockOnCreatePoliciesShouldBeHonored, LibInitMocked, Lib= Cleanup, > NULL ); > + AddTestCase( PolicyTests, > + "LockOnStatePoliciesShouldBeHonored", > "VarPolicy.Policy.LockState", > + LockOnStatePoliciesShouldBeHonored, LibInitMocked, LibC= leanup, > NULL ); > + AddTestCase( PolicyTests, > + "LockOnStatePoliciesShouldApplyToNamespaces", > "VarPolicy.Policy.NamespaceLockState", > + LockOnStatePoliciesShouldApplyToNamespaces, LibInitMock= ed, > LibCleanup, NULL ); > + AddTestCase( PolicyTests, > + "LockOnStateShouldHandleErrorsGracefully", > "VarPolicy.Policy.LockStateErrors", > + LockOnStateShouldHandleErrorsGracefully, LibInitMocked, > LibCleanup, NULL ); > + AddTestCase( PolicyTests, > + "BestMatchPriorityShouldBeObeyed", "VarPolicy.Policy.Be= stMatch", > + BestMatchPriorityShouldBeObeyed, LibInitMocked, LibClea= nup, > NULL ); > + > + Status =3D CreateUnitTestSuite( &UtilityTests, Framework, "Variable P= olicy > Utility Tests", "VarPolicy.Utility", NULL, NULL ); > + if (EFI_ERROR( Status )) > + { > + DEBUG((DEBUG_ERROR, "Failed in CreateUnitTestSuite for > UtilityTests\n")); > + Status =3D EFI_OUT_OF_RESOURCES; > + goto EXIT; > + } > + AddTestCase( UtilityTests, > + "API commands that change state should not respond afte= r > interface is locked", "VarPolicy.Utility.InterfaceLock", > + ShouldBeAbleToLockInterface, LibInitMocked, LibCleanup,= NULL ); > + AddTestCase( UtilityTests, > + "All policies should pass once enforcement is disabled"= , > "VarPolicy.Utility.DisableEnforcement", > + ShouldBeAbleToDisablePolicyEnforcement, LibInitMocked, > LibCleanup, NULL ); > + AddTestCase( UtilityTests, > + "Disabling enforcement twice should produce an error", > "VarPolicy.Utility.DisableEnforcementTwice", > + ShouldNotBeAbleToDisablePoliciesTwice, LibInitMocked, > LibCleanup, NULL ); > + AddTestCase( UtilityTests, > + "ShouldBeAbleToAddNewPoliciesAfterDisabled", > "VarPolicy.Utility.AddAfterDisable", > + ShouldBeAbleToAddNewPoliciesAfterDisabled, LibInitMocke= d, > LibCleanup, NULL ); > + AddTestCase( UtilityTests, > + "ShouldBeAbleToLockAfterDisabled", > "VarPolicy.Utility.LockAfterDisable", > + ShouldBeAbleToLockAfterDisabled, LibInitMocked, LibClea= nup, > NULL ); > + AddTestCase( UtilityTests, > + "Should be able to dump the policy table", > "VarPolicy.Utility.DumpTable", > + ShouldBeAbleToDumpThePolicyTable, LibInitMocked, LibCle= anup, > NULL ); > + AddTestCase( UtilityTests, > + "ShouldBeAbleToDumpThePolicyTableAfterDisabled", > "VarPolicy.Utility.DumpTableAfterDisable", > + ShouldBeAbleToDumpThePolicyTableAfterDisabled, LibInitM= ocked, > LibCleanup, NULL ); > + > + > + // > + // Execute the tests. > + // > + Status =3D RunAllTestSuites( Framework ); > + > +EXIT: > + if (Framework) > + { > + FreeUnitTestFramework( Framework ); > + } > + > + return Status; > +} > diff --git a/MdeModulePkg/Include/Library/VariablePolicyLib.h > b/MdeModulePkg/Include/Library/VariablePolicyLib.h > new file mode 100644 > index 000000000000..6be16fdd8f24 > --- /dev/null > +++ b/MdeModulePkg/Include/Library/VariablePolicyLib.h > @@ -0,0 +1,206 @@ > +/** @file -- VariablePolicyLib.h > +Business logic for Variable Policy enforcement. > + > +Copyright (c) Microsoft Corporation. > +SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#ifndef _VARIABLE_POLICY_LIB_H_ > +#define _VARIABLE_POLICY_LIB_H_ > + > +#include > + > +/** > + This API function validates and registers a new policy with > + the policy enforcement engine. > + > + @param[in] NewPolicy Pointer to the incoming policy structure. > + > + @retval EFI_SUCCESS > + @retval EFI_INVALID_PARAMETER NewPolicy is NULL or is internall= y > inconsistent. > + @retval EFI_ALREADY_STARTED An identical matching policy alre= ady > exists. > + @retval EFI_WRITE_PROTECTED The interface has been locked unt= il > the next reboot. > + @retval EFI_UNSUPPORTED Policy enforcement has been disab= led. > No reason to add more policies. > + @retval EFI_ABORTED A calculation error has prevented= this > function from completing. > + @retval EFI_OUT_OF_RESOURCES Cannot grow the table to hold any > more policies. > + @retval EFI_NOT_READY Library has not yet been initiali= zed. > + > +**/ > +EFI_STATUS > +EFIAPI > +RegisterVariablePolicy ( > + IN CONST VARIABLE_POLICY_ENTRY *NewPolicy > + ); > + > + > +/** > + This API function checks to see whether the parameters to SetVariable > would > + be allowed according to the current variable policies. > + > + @param[in] VariableName Same as EFI_SET_VARIABLE. > + @param[in] VendorGuid Same as EFI_SET_VARIABLE. > + @param[in] Attributes Same as EFI_SET_VARIABLE. > + @param[in] DataSize Same as EFI_SET_VARIABLE. > + @param[in] Data Same as EFI_SET_VARIABLE. > + > + @retval EFI_SUCCESS A matching policy allows this upd= ate. > + @retval EFI_SUCCESS There are currently no policies t= hat restrict > this update. > + @retval EFI_SUCCESS The protections have been disable= until the > next reboot. > + @retval EFI_WRITE_PROTECTED Variable is currently locked. > + @retval EFI_INVALID_PARAMETER Attributes or size are invalid. > + @retval EFI_ABORTED A lock policy exists, but an erro= r prevented > evaluation. > + @retval EFI_NOT_READY Library has not been initialized. > + > +**/ > +EFI_STATUS > +EFIAPI > +ValidateSetVariable ( > + IN CHAR16 *VariableName, > + IN EFI_GUID *VendorGuid, > + IN UINT32 Attributes, > + IN UINTN DataSize, > + IN VOID *Data > + ); > + > + > +/** > + This API function disables the variable policy enforcement. If it's > + already been called once, will return EFI_ALREADY_STARTED. > + > + @retval EFI_SUCCESS > + @retval EFI_ALREADY_STARTED Has already been called once this b= oot. > + @retval EFI_WRITE_PROTECTED Interface has been locked until reb= oot. > + @retval EFI_NOT_READY Library has not yet been initialized. > + > +**/ > +EFI_STATUS > +EFIAPI > +DisableVariablePolicy ( > + VOID > + ); > + > + > +/** > + This API function will dump the entire contents of the variable polic= y table. > + > + Similar to GetVariable, the first call can be made with a 0 size and = it will > return > + the size of the buffer required to hold the entire table. > + > + @param[out] Policy Pointer to the policy buffer. Can be NULL if = Size is 0. > + @param[in,out] Size On input, the size of the output buffer. On o= utput, > the size > + of the data returned. > + > + @retval EFI_SUCCESS Policy data is in the output buff= er and Size > has been updated. > + @retval EFI_INVALID_PARAMETER Size is NULL, or Size is non-zero= and > Policy is NULL. > + @retval EFI_BUFFER_TOO_SMALL Size is insufficient to hold poli= cy. Size > updated with required size. > + @retval EFI_NOT_READY Library has not yet been initiali= zed. > + > +**/ > +EFI_STATUS > +EFIAPI > +DumpVariablePolicy ( > + OUT UINT8 *Policy, > + IN OUT UINT32 *Size > + ); > + > + > +/** > + This API function returns whether or not the policy engine is > + currently being enforced. > + > + @retval TRUE > + @retval FALSE > + @retval FALSE Library has not yet been initialized. > + > +**/ > +BOOLEAN > +EFIAPI > +IsVariablePolicyEnabled ( > + VOID > + ); > + > + > +/** > + This API function locks the interface so that no more policy updates > + can be performed or changes made to the enforcement until the next > boot. > + > + @retval EFI_SUCCESS > + @retval EFI_NOT_READY Library has not yet been initialized. > + > +**/ > +EFI_STATUS > +EFIAPI > +LockVariablePolicy ( > + VOID > + ); > + > + > +/** > + This API function returns whether or not the policy interface is lock= ed > + for the remainder of the boot. > + > + @retval TRUE > + @retval FALSE > + @retval FALSE Library has not yet been initialized. > + > +**/ > +BOOLEAN > +EFIAPI > +IsVariablePolicyInterfaceLocked ( > + VOID > + ); > + > + > +/** > + This helper function initializes the library and sets > + up any required internal structures or handlers. > + > + Also registers the internal pointer for the GetVariable helper. > + > + @param[in] GetVariableHelper A function pointer matching the > EFI_GET_VARIABLE prototype that will be used to > + check policy criteria that involve the existence of o= ther variables. > + > + @retval EFI_SUCCESS > + @retval EFI_ALREADY_STARTED The initialize function has been ca= lled > more than once without a call to > + deinitialize. > + > +**/ > +EFI_STATUS > +EFIAPI > +InitVariablePolicyLib ( > + IN EFI_GET_VARIABLE GetVariableHelper > + ); > + > + > +/** > + This helper function returns whether or not the library is currently > initialized. > + > + @retval TRUE > + @retval FALSE > + > +**/ > +BOOLEAN > +EFIAPI > +IsVariablePolicyLibInitialized ( > + VOID > + ); > + > + > +/** > + This helper function tears down the library. > + > + Should generally only be used for test harnesses. > + > + @retval EFI_SUCCESS > + @retval EFI_NOT_READY Deinitialize was called without first c= alling > initialize. > + > +**/ > +EFI_STATUS > +EFIAPI > +DeinitVariablePolicyLib ( > + VOID > + ); > + > + > +#endif // _VARIABLE_POLICY_LIB_H_ > diff --git a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.in= f > b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf > new file mode 100644 > index 000000000000..340d5e8793fe > --- /dev/null > +++ b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf > @@ -0,0 +1,38 @@ > +## @file VariablePolicyLib.inf > +# Business logic for Variable Policy enforcement. > +# > +## > +# Copyright (c) Microsoft Corporation. > +# SPDX-License-Identifier: BSD-2-Clause-Patent > +## > + > + > +[Defines] > + INF_VERSION =3D 0x00010017 > + BASE_NAME =3D VariablePolicyLib > + FILE_GUID =3D E9ECD342-159A-4F24-9FDF-65724027C594 > + VERSION_STRING =3D 1.0 > + MODULE_TYPE =3D BASE > + LIBRARY_CLASS =3D VariablePolicyLib > + > +# > +# The following information is for reference only and not required by t= he > build tools. > +# > +# VALID_ARCHITECTURES =3D ANY > +# > + > + > +[Sources] > + VariablePolicyLib.c > + > + > +[Packages] > + MdePkg/MdePkg.dec > + MdeModulePkg/MdeModulePkg.dec > + > + > +[LibraryClasses] > + DebugLib > + BaseMemoryLib > + MemoryAllocationLib > + SafeIntLib > diff --git a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.un= i > b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.uni > new file mode 100644 > index 000000000000..2227ec427828 > --- /dev/null > +++ b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.uni > @@ -0,0 +1,12 @@ > +// /** @file > +// VariablePolicyLib.uni > +// > +// Copyright (c) Microsoft Corporation. > +// SPDX-License-Identifier: BSD-2-Clause-Patent > +// > +// **/ > + > + > +#string STR_MODULE_ABSTRACT #language en-US "Library contai= ning > the business logic for the VariablePolicy engine" > + > +#string STR_MODULE_DESCRIPTION #language en-US "Library > containing the business logic for the VariablePolicy engine" > diff --git > a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/Variable > PolicyUnitTest.inf > b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/Variable > PolicyUnitTest.inf > new file mode 100644 > index 000000000000..c7c636eabde3 > --- /dev/null > +++ > b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/Variable > PolicyUnitTest.inf > @@ -0,0 +1,41 @@ > +## @file VariablePolicyUnitTest.inf > +# UnitTest for... > +# Business logic for Variable Policy enforcement. > +# > +## > +# Copyright (c) Microsoft Corporation. > +# SPDX-License-Identifier: BSD-2-Clause-Patent > +## > + > + > +[Defines] > + INF_VERSION =3D 0x00010006 > + BASE_NAME =3D VariablePolicyUnitTest > + FILE_GUID =3D 1200A2E4-D756-418C-9768-528C2D181A= 98 > + MODULE_TYPE =3D HOST_APPLICATION > + VERSION_STRING =3D 1.0 > + > +# > +# The following information is for reference only and not required by t= he > build tools. > +# > +# VALID_ARCHITECTURES =3D IA32 X64 ARM AARCH64 > +# > + > +[Sources] > + VariablePolicyUnitTest.c > + > + > +[Packages] > + MdePkg/MdePkg.dec > + MdeModulePkg/MdeModulePkg.dec > + UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec > + > + > +[LibraryClasses] > + BaseLib > + DebugLib > + UnitTestLib > + PrintLib > + VariablePolicyLib > + BaseMemoryLib > + MemoryAllocationLib > diff --git a/MdeModulePkg/MdeModulePkg.dec > b/MdeModulePkg/MdeModulePkg.dec > index 956276e30a72..990e23b07a08 100644 > --- a/MdeModulePkg/MdeModulePkg.dec > +++ b/MdeModulePkg/MdeModulePkg.dec > @@ -29,6 +29,9 @@ > ## @libraryclass Defines a set of methods to reset whole system. > ResetSystemLib|Include/Library/ResetSystemLib.h >=20 > + ## @libraryclass Business logic for storing and testing variable po= licies > + VariablePolicyLib|Include/Library/VariablePolicyLib.h > + > ## @libraryclass Defines a set of helper functions for resetting th= e system. > ResetUtilityLib|Include/Library/ResetUtilityLib.h >=20 > diff --git a/MdeModulePkg/MdeModulePkg.dsc > b/MdeModulePkg/MdeModulePkg.dsc > index f7dbb27ce25d..8501dae88eb1 100644 > --- a/MdeModulePkg/MdeModulePkg.dsc > +++ b/MdeModulePkg/MdeModulePkg.dsc > @@ -3,6 +3,7 @@ > # > # (C) Copyright 2014 Hewlett-Packard Development Company, L.P.
> # Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved. > +# Copyright (c) Microsoft Corporation. > # > # SPDX-License-Identifier: BSD-2-Clause-Patent > # > @@ -58,6 +59,7 @@ > DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf >=20 > DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTabl > eLib.inf >=20 > UefiBootManagerLib|MdeModulePkg/Library/UefiBootManagerLib/UefiBoo > tManagerLib.inf > + > VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyL= i > b.inf > # > # Generic Modules > # > @@ -306,6 +308,7 @@ > MdeModulePkg/Library/BootLogoLib/BootLogoLib.inf >=20 > MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull > .inf > MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf > + MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf > MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf > MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLib.inf > MdeModulePkg/Library/VarCheckPcdLib/VarCheckPcdLib.inf > diff --git a/MdeModulePkg/Test/MdeModulePkgHostTest.dsc > b/MdeModulePkg/Test/MdeModulePkgHostTest.dsc > index 72a119db4568..058ef7dcef11 100644 > --- a/MdeModulePkg/Test/MdeModulePkgHostTest.dsc > +++ b/MdeModulePkg/Test/MdeModulePkgHostTest.dsc > @@ -19,12 +19,20 @@ >=20 > !include UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc >=20 > +[LibraryClasses] > + SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf > + > [Components] >=20 > MdeModulePkg/Library/DxeResetSystemLib/UnitTest/MockUefiRuntimeSer > vicesTableLib.inf >=20 > # > # Build MdeModulePkg HOST_APPLICATION Tests > # > + > MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePo > licyUnitTest.inf { > + > + > VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyL= i > b.inf > + } > + >=20 > MdeModulePkg/Library/DxeResetSystemLib/UnitTest/DxeResetSystemLibU > nitTestHost.inf { > >=20 > ResetSystemLib|MdeModulePkg/Library/DxeResetSystemLib/DxeResetSyst > emLib.inf > -- > 2.16.3.windows.1 >=20 >=20 >=20