[PATCH v5 02/14] MdeModulePkg: Define the VariablePolicyLib


Bret Barkelew
 

https://bugzilla.tianocore.org/show_bug.cgi?id=3D2522

VariablePolicy is an updated interface to
replace VarLock and VarCheckProtocol.

Add the VariablePolicyLib library that implements
the portable business logic for the VariablePolicy
engine.

Also add host-based CI test cases for the lib.

Cc: Jian J Wang <jian.j.wang@...>
Cc: Hao A Wu <hao.a.wu@...>
Cc: Liming Gao <liming.gao@...>
Cc: Bret Barkelew <brbarkel@...>
Signed-off-by: Bret Barkelew <brbarkel@...>
---
MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitNull.c =
| 46 +
MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitRuntimeDxe.c=
| 85 +
MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c =
| 813 +++++++
MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePoli=
cyUnitTest.c | 2436 ++++++++++++++++++++
MdeModulePkg/Include/Library/VariablePolicyLib.h =
| 207 ++
MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf =
| 44 +
MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.uni =
| 12 +
MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf =
| 51 +
MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePoli=
cyUnitTest.inf | 40 +
MdeModulePkg/MdeModulePkg.dec =
| 3 +
MdeModulePkg/MdeModulePkg.dsc =
| 5 +
MdeModulePkg/Test/MdeModulePkgHostTest.dsc =
| 11 +
12 files changed, 3753 insertions(+)

diff --git a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInit=
Null.c b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitNull=
.c
new file mode 100644
index 000000000000..ad2ee0b2fb8f
--- /dev/null
+++ b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitNull.c
@@ -0,0 +1,46 @@
+/** @file -- VariablePolicyExtraInitNull.c=0D
+This file contains extra init and deinit routines that don't do anything=0D
+extra.=0D
+=0D
+Copyright (c) Microsoft Corporation.=0D
+SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+=0D
+**/=0D
+=0D
+#include <Library/UefiRuntimeServicesTableLib.h>=0D
+=0D
+=0D
+/**=0D
+ An extra init hook that enables the RuntimeDxe library instance to=0D
+ register VirtualAddress change callbacks. Among other things.=0D
+=0D
+ @retval EFI_SUCCESS Everything is good. Continue with init.=0D
+ @retval Others Uh... don't continue.=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+VariablePolicyExtraInit (=0D
+ VOID=0D
+ )=0D
+{=0D
+ // NULL implementation.=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+=0D
+/**=0D
+ An extra deinit hook that enables the RuntimeDxe library instance to=0D
+ register VirtualAddress change callbacks. Among other things.=0D
+=0D
+ @retval EFI_SUCCESS Everything is good. Continue with deinit.=0D
+ @retval Others Uh... don't continue.=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+VariablePolicyExtraDeinit (=0D
+ VOID=0D
+ )=0D
+{=0D
+ // NULL implementation.=0D
+ return EFI_SUCCESS;=0D
+}=0D
diff --git a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInit=
RuntimeDxe.c b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraIn=
itRuntimeDxe.c
new file mode 100644
index 000000000000..3ca87048b14b
--- /dev/null
+++ b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitRuntime=
Dxe.c
@@ -0,0 +1,85 @@
+/** @file -- VariablePolicyExtraInitRuntimeDxe.c=0D
+This file contains extra init and deinit routines that register and unregi=
ster=0D
+VariableAddressChange callbacks.=0D
+=0D
+Copyright (c) Microsoft Corporation.=0D
+SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+=0D
+**/=0D
+=0D
+#include <Library/UefiBootServicesTableLib.h>=0D
+#include <Library/UefiRuntimeServicesTableLib.h>=0D
+=0D
+extern EFI_GET_VARIABLE mGetVariableHelper;=0D
+extern UINT8 *mPolicyTable;=0D
+STATIC BOOLEAN mIsVirtualAddrConverted;=0D
+STATIC EFI_EVENT mVariablePolicyLibVirtualAddressChangeEvent =3D=
NULL;=0D
+=0D
+/**=0D
+ For the RuntimeDxe version of this lib, convert internal pointer address=
es to virtual addresses.=0D
+=0D
+ @param[in] Event Event whose notification function is being invoked=
.=0D
+ @param[in] Context The pointer to the notification function's context=
, which=0D
+ is implementation-dependent.=0D
+**/=0D
+STATIC=0D
+VOID=0D
+EFIAPI=0D
+VariablePolicyLibVirtualAddressCallback (=0D
+ IN EFI_EVENT Event,=0D
+ IN VOID *Context=0D
+ )=0D
+{=0D
+ gRT->ConvertPointer (0, (VOID **)&mPolicyTable);=0D
+ gRT->ConvertPointer (0, (VOID **)&mGetVariableHelper);=0D
+ mIsVirtualAddrConverted =3D TRUE;=0D
+}=0D
+=0D
+=0D
+/**=0D
+ An extra init hook that enables the RuntimeDxe library instance to=0D
+ register VirtualAddress change callbacks. Among other things.=0D
+=0D
+ @retval EFI_SUCCESS Everything is good. Continue with init.=0D
+ @retval Others Uh... don't continue.=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+VariablePolicyExtraInit (=0D
+ VOID=0D
+ )=0D
+{=0D
+ return gBS->CreateEventEx (EVT_NOTIFY_SIGNAL,=0D
+ TPL_NOTIFY,=0D
+ VariablePolicyLibVirtualAddressCallback,=0D
+ NULL,=0D
+ &gEfiEventVirtualAddressChangeGuid,=0D
+ &mVariablePolicyLibVirtualAddressChangeEvent=
);=0D
+}=0D
+=0D
+=0D
+/**=0D
+ An extra deinit hook that enables the RuntimeDxe library instance to=0D
+ register VirtualAddress change callbacks. Among other things.=0D
+=0D
+ @retval EFI_SUCCESS Everything is good. Continue with deinit.=0D
+ @retval Others Uh... don't continue.=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+VariablePolicyExtraDeinit (=0D
+ VOID=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+=0D
+ Status =3D EFI_SUCCESS;=0D
+ if (mIsVirtualAddrConverted) {=0D
+ Status =3D gBS->CloseEvent (mVariablePolicyLibVirtualAddressChangeEven=
t);=0D
+ }=0D
+ else {=0D
+ Status =3D EFI_SUCCESS;=0D
+ }=0D
+=0D
+ return Status;=0D
+}=0D
diff --git a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c b/M=
deModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c
new file mode 100644
index 000000000000..c63807ef8531
--- /dev/null
+++ b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c
@@ -0,0 +1,813 @@
+/** @file -- VariablePolicyLib.c=0D
+Business logic for Variable Policy enforcement.=0D
+=0D
+Copyright (c) Microsoft Corporation.=0D
+SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+=0D
+**/=0D
+=0D
+#include <Uefi.h>=0D
+=0D
+#include <Library/SafeIntLib.h>=0D
+#include <Library/MemoryAllocationLib.h>=0D
+#include <Library/BaseMemoryLib.h>=0D
+#include <Library/DebugLib.h>=0D
+#include <Library/PcdLib.h>=0D
+=0D
+#include <Protocol/VariablePolicy.h>=0D
+#include <Library/VariablePolicyLib.h>=0D
+=0D
+=0D
+// IMPORTANT NOTE: This library is currently rife with multiple return sta=
tements=0D
+// for error handling. A refactor should remove these at s=
ome point.=0D
+=0D
+//=0D
+// This library was designed with advanced unit-test features.=0D
+// This define handles the configuration.=0D
+#ifdef INTERNAL_UNIT_TEST=0D
+#undef STATIC=0D
+#define STATIC // Nothing...=0D
+#endif=0D
+=0D
+// An abstracted GetVariable interface that enables configuration regardle=
ss of the environment.=0D
+EFI_GET_VARIABLE mGetVariableHelper =3D NULL;=0D
+=0D
+// Master switch to lock this entire interface. Does not stop enforcement,=
=0D
+// just prevents the configuration from being changed for the rest of the =
boot.=0D
+STATIC BOOLEAN mInterfaceLocked =3D FALSE;=0D
+=0D
+// Master switch to disable the entire interface for a single boot.=0D
+// This will disable all policy enforcement for the duration of the boot.=
=0D
+STATIC BOOLEAN mProtectionDisabled =3D FALSE;=0D
+=0D
+// Table to hold all the current policies.=0D
+UINT8 *mPolicyTable =3D NULL;=0D
+STATIC UINT32 mCurrentTableSize =3D 0;=0D
+STATIC UINT32 mCurrentTableUsage =3D 0;=0D
+STATIC UINT32 mCurrentTableCount =3D 0;=0D
+=0D
+#define POLICY_TABLE_STEP_SIZE 0x1000=0D
+=0D
+// NOTE: DO NOT USE THESE MACROS on any structure that has not been valida=
ted.=0D
+// Current table data has already been sanitized.=0D
+#define GET_NEXT_POLICY(CurPolicy) (VARIABLE_POLICY_ENTRY*)((UINT8*)Cur=
Policy + CurPolicy->Size)=0D
+#define GET_POLICY_NAME(CurPolicy) (CHAR16*)((UINTN)CurPolicy + CurPoli=
cy->OffsetToName)=0D
+=0D
+#define MATCH_PRIORITY_EXACT 0=0D
+#define MATCH_PRIORITY_MAX MATCH_PRIORITY_EXACT=0D
+#define MATCH_PRIORITY_MIN MAX_UINT8=0D
+=0D
+// ExtraInit/ExtraDeinit functions allow RuntimeDxe to register VirtualAdd=
ress callbacks.=0D
+EFI_STATUS=0D
+VariablePolicyExtraInit (=0D
+ VOID=0D
+ );=0D
+=0D
+EFI_STATUS=0D
+VariablePolicyExtraDeinit (=0D
+ VOID=0D
+ );=0D
+=0D
+=0D
+/**=0D
+ This helper function determines whether the structure of an incoming pol=
icy=0D
+ is valid and internally consistent.=0D
+=0D
+ @param[in] NewPolicy Pointer to the incoming policy structure.=0D
+=0D
+ @retval TRUE=0D
+ @retval FALSE Pointer is NULL, size is wrong, strings are empty, o=
r=0D
+ substructures overlap.=0D
+=0D
+**/=0D
+STATIC=0D
+BOOLEAN=0D
+IsValidVariablePolicyStructure (=0D
+ IN CONST VARIABLE_POLICY_ENTRY *NewPolicy=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ UINTN EntryEnd;=0D
+ CHAR16 *CheckChar;=0D
+ UINTN WildcardCount;=0D
+=0D
+ // Sanitize some quick values.=0D
+ if (NewPolicy =3D=3D NULL || NewPolicy->Size =3D=3D 0 ||=0D
+ // Structure size should be at least as long as the minumum structur=
e and a NULL string.=0D
+ NewPolicy->Size < sizeof(VARIABLE_POLICY_ENTRY) ||=0D
+ // Check for the known revision.=0D
+ NewPolicy->Version !=3D VARIABLE_POLICY_ENTRY_REVISION) {=0D
+ return FALSE;=0D
+ }=0D
+=0D
+ // Calculate the theoretical end of the structure and make sure=0D
+ // that the structure can fit in memory.=0D
+ Status =3D SafeUintnAdd( (UINTN)NewPolicy, NewPolicy->Size, &EntryEnd );=
=0D
+ if (EFI_ERROR( Status )) {=0D
+ return FALSE;=0D
+ }=0D
+=0D
+ // Check for a valid Max Size.=0D
+ if (NewPolicy->MaxSize =3D=3D 0) {=0D
+ return FALSE;=0D
+ }=0D
+=0D
+ // Check for the valid list of lock policies.=0D
+ if (NewPolicy->LockPolicyType !=3D VARIABLE_POLICY_TYPE_NO_LOCK &&=0D
+ NewPolicy->LockPolicyType !=3D VARIABLE_POLICY_TYPE_LOCK_NOW &&=0D
+ NewPolicy->LockPolicyType !=3D VARIABLE_POLICY_TYPE_LOCK_ON_CREATE &=
&=0D
+ NewPolicy->LockPolicyType !=3D VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STAT=
E)=0D
+ {=0D
+ return FALSE;=0D
+ }=0D
+=0D
+ // If the policy type is VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE, make su=
re that the matching state variable Name=0D
+ // terminates before the OffsetToName for the matching policy variable N=
ame.=0D
+ if (NewPolicy->LockPolicyType =3D=3D VARIABLE_POLICY_TYPE_LOCK_ON_VAR_ST=
ATE) {=0D
+ // Adjust CheckChar to the offset of the LockPolicy->Name.=0D
+ Status =3D SafeUintnAdd( (UINTN)NewPolicy + sizeof(VARIABLE_POLICY_ENT=
RY),=0D
+ sizeof(VARIABLE_LOCK_ON_VAR_STATE_POLICY),=0D
+ (UINTN*)&CheckChar );=0D
+ if (EFI_ERROR( Status ) || EntryEnd <=3D (UINTN)CheckChar) {=0D
+ return FALSE;=0D
+ }=0D
+ while (*CheckChar !=3D CHAR_NULL) {=0D
+ if (EntryEnd <=3D (UINTN)CheckChar) {=0D
+ return FALSE;=0D
+ }=0D
+ CheckChar++;=0D
+ }=0D
+ // At this point we should have either exeeded the structure or be poi=
nting at the last char in LockPolicy->Name.=0D
+ // We should check to make sure that the policy Name comes immediately=
after this charcter.=0D
+ if ((UINTN)++CheckChar !=3D (UINTN)NewPolicy + NewPolicy->OffsetToName=
) {=0D
+ return FALSE;=0D
+ }=0D
+ }=0D
+ // If the policy type is any other value, make sure that the LockPolicy =
structure has a zero length.=0D
+ else {=0D
+ if (NewPolicy->OffsetToName !=3D sizeof(VARIABLE_POLICY_ENTRY)) {=0D
+ return FALSE;=0D
+ }=0D
+ }=0D
+=0D
+ // Check to make sure that the name has a terminating character=0D
+ // before the end of the structure.=0D
+ // We've already checked that the name is within the bounds of the struc=
ture.=0D
+ if (NewPolicy->Size !=3D NewPolicy->OffsetToName) {=0D
+ CheckChar =3D (CHAR16*)((UINTN)NewPolicy + NewPolicy->OffsetToName);=0D
+ WildcardCount =3D 0;=0D
+ while (*CheckChar !=3D CHAR_NULL) {=0D
+ // Make sure there aren't excessive wildcards.=0D
+ if (*CheckChar =3D=3D '#') {=0D
+ WildcardCount++;=0D
+ if (WildcardCount > MATCH_PRIORITY_MIN) {=0D
+ return FALSE;=0D
+ }=0D
+ }=0D
+ // Make sure you're still within the bounds of the policy structure.=
=0D
+ if (EntryEnd <=3D (UINTN)CheckChar) {=0D
+ return FALSE;=0D
+ }=0D
+ CheckChar++;=0D
+ }=0D
+=0D
+ // Finally, we should be pointed at the very last character in Name, s=
o we should be right=0D
+ // up against the end of the structure.=0D
+ if ((UINTN)++CheckChar !=3D EntryEnd) {=0D
+ return FALSE;=0D
+ }=0D
+ }=0D
+=0D
+ return TRUE;=0D
+}=0D
+=0D
+=0D
+/**=0D
+ This helper function evaluates a policy and determines whether it matche=
s the target=0D
+ variable. If matched, will also return a value corresponding to the prio=
rity of the match.=0D
+=0D
+ The rules for "best match" are listed in the Variable Policy Spec.=0D
+ Perfect name matches will return 0.=0D
+ Single wildcard characters will return the number of wildcard characters=
.=0D
+ Full namespaces will return MAX_UINT8.=0D
+=0D
+ @param[in] EvalEntry Pointer to the policy entry being evaluate=
d.=0D
+ @param[in] VariableName Same as EFI_SET_VARIABLE.=0D
+ @param[in] VendorGuid Same as EFI_SET_VARIABLE.=0D
+ @param[out] MatchPriority [Optional] On finding a match, this value =
contains the priority of the match.=0D
+ Lower number =3D=3D higher priority. Only =
valid if a match found.=0D
+=0D
+ @retval TRUE Current entry matches the target variable.=0D
+ @retval FALSE Current entry does not match at all.=0D
+=0D
+**/=0D
+STATIC=0D
+BOOLEAN=0D
+EvaluatePolicyMatch (=0D
+ IN CONST VARIABLE_POLICY_ENTRY *EvalEntry,=0D
+ IN CONST CHAR16 *VariableName,=0D
+ IN CONST EFI_GUID *VendorGuid,=0D
+ OUT UINT8 *MatchPriority OPTIONAL=0D
+ )=0D
+{=0D
+ BOOLEAN Result;=0D
+ CHAR16 *PolicyName;=0D
+ UINT8 CalculatedPriority;=0D
+ UINTN Index;=0D
+=0D
+ Result =3D FALSE;=0D
+ CalculatedPriority =3D MATCH_PRIORITY_EXACT;=0D
+=0D
+ // Step 1: If the GUID doesn't match, we're done. No need to evaluate an=
ything else.=0D
+ if (!CompareGuid( &EvalEntry->Namespace, VendorGuid )) {=0D
+ goto Exit;=0D
+ }=0D
+=0D
+ // If the GUID matches, check to see whether there is a Name associated=
=0D
+ // with the policy. If not, this policy matches the entire namespace.=0D
+ // Missing Name is indicated by size being equal to name.=0D
+ if (EvalEntry->Size =3D=3D EvalEntry->OffsetToName) {=0D
+ CalculatedPriority =3D MATCH_PRIORITY_MIN;=0D
+ Result =3D TRUE;=0D
+ goto Exit;=0D
+ }=0D
+=0D
+ // Now that we know the name exists, get it.=0D
+ PolicyName =3D GET_POLICY_NAME( EvalEntry );=0D
+=0D
+ // Evaluate the name against the policy name and check for a match.=0D
+ // Account for any wildcards.=0D
+ Index =3D 0;=0D
+ Result =3D TRUE;=0D
+ // Keep going until the end of both strings.=0D
+ while (PolicyName[Index] !=3D CHAR_NULL || VariableName[Index] !=3D CHAR=
_NULL) {=0D
+ // If we don't have a match...=0D
+ if (PolicyName[Index] !=3D VariableName[Index] || PolicyName[Index] =
=3D=3D '#') {=0D
+ // If this is a numerical wildcard, we can consider=0D
+ // it a match if we alter the priority.=0D
+ if (PolicyName[Index] =3D=3D L'#' &&=0D
+ (L'0' <=3D VariableName[Index] && VariableName[Index] <=3D L'9')=
) {=0D
+ if (CalculatedPriority < MATCH_PRIORITY_MIN) {=0D
+ CalculatedPriority++;=0D
+ }=0D
+ }=0D
+ // Otherwise, not a match.=0D
+ else {=0D
+ Result =3D FALSE;=0D
+ goto Exit;=0D
+ }=0D
+ }=0D
+ Index++;=0D
+ }=0D
+=0D
+Exit:=0D
+ if (Result && MatchPriority !=3D NULL) {=0D
+ *MatchPriority =3D CalculatedPriority;=0D
+ }=0D
+ return Result;=0D
+}=0D
+=0D
+=0D
+/**=0D
+ This helper function walks the current policy table and returns a pointe=
r=0D
+ to the best match, if any are found. Leverages EvaluatePolicyMatch() to=
=0D
+ determine "best".=0D
+=0D
+ @param[in] VariableName Same as EFI_SET_VARIABLE.=0D
+ @param[in] VendorGuid Same as EFI_SET_VARIABLE.=0D
+ @param[out] ReturnPriority [Optional] If pointer is provided, return=
the=0D
+ priority of the match. Same as EvaluatePo=
licyMatch().=0D
+ Only valid if a match is returned.=0D
+=0D
+ @retval VARIABLE_POLICY_ENTRY* Best match that was found.=0D
+ @retval NULL No match was found.=0D
+=0D
+**/=0D
+STATIC=0D
+VARIABLE_POLICY_ENTRY*=0D
+GetBestPolicyMatch (=0D
+ IN CONST CHAR16 *VariableName,=0D
+ IN CONST EFI_GUID *VendorGuid,=0D
+ OUT UINT8 *ReturnPriority OPTIONAL=0D
+ )=0D
+{=0D
+ VARIABLE_POLICY_ENTRY *BestResult;=0D
+ VARIABLE_POLICY_ENTRY *CurrentEntry;=0D
+ UINT8 MatchPriority;=0D
+ UINT8 CurrentPriority;=0D
+ UINTN Index;=0D
+=0D
+ BestResult =3D NULL;=0D
+=0D
+ // Walk all entries in the table, looking for matches.=0D
+ CurrentEntry =3D (VARIABLE_POLICY_ENTRY*)mPolicyTable;=0D
+ for (Index =3D 0; Index < mCurrentTableCount; Index++) {=0D
+ // Check for a match.=0D
+ if (EvaluatePolicyMatch( CurrentEntry, VariableName, VendorGuid, &Curr=
entPriority )) {=0D
+ // If match is better, take it.=0D
+ if (BestResult =3D=3D NULL || CurrentPriority < MatchPriority) {=0D
+ BestResult =3D CurrentEntry;=0D
+ MatchPriority =3D CurrentPriority;=0D
+ }=0D
+=0D
+ // If you've hit the highest-priority match, can exit now.=0D
+ if (MatchPriority =3D=3D 0) {=0D
+ break;=0D
+ }=0D
+ }=0D
+=0D
+ // If we're still in the loop, move to the next entry.=0D
+ CurrentEntry =3D GET_NEXT_POLICY( CurrentEntry );=0D
+ }=0D
+=0D
+ // If a return priority was requested, return it.=0D
+ if (ReturnPriority !=3D NULL) {=0D
+ *ReturnPriority =3D MatchPriority;=0D
+ }=0D
+=0D
+ return BestResult;=0D
+}=0D
+=0D
+=0D
+/**=0D
+ This API function validates and registers a new policy with=0D
+ the policy enforcement engine.=0D
+=0D
+ @param[in] NewPolicy Pointer to the incoming policy structure.=0D
+=0D
+ @retval EFI_SUCCESS=0D
+ @retval EFI_INVALID_PARAMETER NewPolicy is NULL or is internally i=
nconsistent.=0D
+ @retval EFI_ALREADY_STARTED An identical matching policy already=
exists.=0D
+ @retval EFI_WRITE_PROTECTED The interface has been locked until =
the next reboot.=0D
+ @retval EFI_UNSUPPORTED Policy enforcement has been disabled=
. No reason to add more policies.=0D
+ @retval EFI_ABORTED A calculation error has prevented th=
is function from completing.=0D
+ @retval EFI_OUT_OF_RESOURCES Cannot grow the table to hold any mo=
re policies.=0D
+ @retval EFI_NOT_READY Library has not yet been initialized=
.=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+RegisterVariablePolicy (=0D
+ IN CONST VARIABLE_POLICY_ENTRY *NewPolicy=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ VARIABLE_POLICY_ENTRY *MatchPolicy;=0D
+ UINT8 MatchPriority;=0D
+ UINT32 NewSize;=0D
+ UINT8 *NewTable;=0D
+=0D
+ if (!IsVariablePolicyLibInitialized()) {=0D
+ return EFI_NOT_READY;=0D
+ }=0D
+ if (mInterfaceLocked) {=0D
+ return EFI_WRITE_PROTECTED;=0D
+ }=0D
+=0D
+ if (!IsValidVariablePolicyStructure( NewPolicy )) {=0D
+ return EFI_INVALID_PARAMETER;=0D
+ }=0D
+=0D
+ // Check to see whether an exact matching policy already exists.=0D
+ MatchPolicy =3D GetBestPolicyMatch( GET_POLICY_NAME( NewPolicy ),=0D
+ &NewPolicy->Namespace,=0D
+ &MatchPriority );=0D
+ if (MatchPolicy !=3D NULL && MatchPriority =3D=3D MATCH_PRIORITY_EXACT) =
{=0D
+ return EFI_ALREADY_STARTED;=0D
+ }=0D
+=0D
+ // If none exists, create it.=0D
+ // If we need more space, allocate that now.=0D
+ Status =3D SafeUint32Add( mCurrentTableUsage, NewPolicy->Size, &NewSize =
);=0D
+ if (EFI_ERROR( Status )) {=0D
+ return EFI_ABORTED;=0D
+ }=0D
+ if (NewSize > mCurrentTableSize) {=0D
+ // Use NewSize to calculate the new table size in units of POLICY_TABL=
E_STEP_SIZE.=0D
+ NewSize =3D (NewSize % POLICY_TABLE_STEP_SIZE) > 0 ?=0D
+ (NewSize / POLICY_TABLE_STEP_SIZE) + 1 :=0D
+ (NewSize / POLICY_TABLE_STEP_SIZE);=0D
+ // Calculate the new table size in absolute bytes.=0D
+ Status =3D SafeUint32Mult( NewSize, POLICY_TABLE_STEP_SIZE, &NewSize )=
;=0D
+ if (EFI_ERROR( Status )) {=0D
+ return EFI_ABORTED;=0D
+ }=0D
+=0D
+ // Reallocate and copy the table.=0D
+ NewTable =3D AllocatePool( NewSize );=0D
+ if (NewTable =3D=3D NULL) {=0D
+ return EFI_OUT_OF_RESOURCES;=0D
+ }=0D
+ CopyMem( NewTable, mPolicyTable, mCurrentTableUsage );=0D
+ mCurrentTableSize =3D NewSize;=0D
+ if (mPolicyTable !=3D NULL) {=0D
+ FreePool( mPolicyTable );=0D
+ }=0D
+ mPolicyTable =3D NewTable;=0D
+ }=0D
+ // Copy the policy into the table.=0D
+ CopyMem( mPolicyTable + mCurrentTableUsage, NewPolicy, NewPolicy->Size )=
;=0D
+ mCurrentTableUsage +=3D NewPolicy->Size;=0D
+ mCurrentTableCount +=3D 1;=0D
+=0D
+ // We're done here.=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+=0D
+/**=0D
+ This API function checks to see whether the parameters to SetVariable wo=
uld=0D
+ be allowed according to the current variable policies.=0D
+=0D
+ @param[in] VariableName Same as EFI_SET_VARIABLE.=0D
+ @param[in] VendorGuid Same as EFI_SET_VARIABLE.=0D
+ @param[in] Attributes Same as EFI_SET_VARIABLE.=0D
+ @param[in] DataSize Same as EFI_SET_VARIABLE.=0D
+ @param[in] Data Same as EFI_SET_VARIABLE.=0D
+=0D
+ @retval EFI_SUCCESS A matching policy allows this update=
.=0D
+ @retval EFI_SUCCESS There are currently no policies that=
restrict this update.=0D
+ @retval EFI_SUCCESS The protections have been disable un=
til the next reboot.=0D
+ @retval EFI_WRITE_PROTECTED Variable is currently locked.=0D
+ @retval EFI_INVALID_PARAMETER Attributes or size are invalid.=0D
+ @retval EFI_ABORTED A lock policy exists, but an error p=
revented evaluation.=0D
+ @retval EFI_NOT_READY Library has not been initialized.=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+ValidateSetVariable (=0D
+ IN CHAR16 *VariableName,=0D
+ IN EFI_GUID *VendorGuid,=0D
+ IN UINT32 Attributes,=0D
+ IN UINTN DataSize,=0D
+ IN VOID *Data=0D
+ )=0D
+{=0D
+ BOOLEAN IsDel;=0D
+ VARIABLE_POLICY_ENTRY *ActivePolicy;=0D
+ EFI_STATUS Status;=0D
+ EFI_STATUS ReturnStatus;=0D
+ VARIABLE_LOCK_ON_VAR_STATE_POLICY *StateVarPolicy;=0D
+ CHAR16 *StateVarName;=0D
+ UINTN StateVarSize;=0D
+ UINT8 StateVar;=0D
+=0D
+ ReturnStatus =3D EFI_SUCCESS;=0D
+=0D
+ if (!IsVariablePolicyLibInitialized()) {=0D
+ ReturnStatus =3D EFI_NOT_READY;=0D
+ goto Exit;=0D
+ }=0D
+=0D
+ // Bail if the protections are currently disabled.=0D
+ if (mProtectionDisabled) {=0D
+ ReturnStatus =3D EFI_SUCCESS;=0D
+ goto Exit;=0D
+ }=0D
+=0D
+ // Determine whether this is a delete operation.=0D
+ // If so, it will affect which tests are applied.=0D
+ if ((DataSize =3D=3D 0) && ((Attributes & EFI_VARIABLE_APPEND_WRITE) =3D=
=3D 0)) {=0D
+ IsDel =3D TRUE;=0D
+ }=0D
+ else {=0D
+ IsDel =3D FALSE;=0D
+ }=0D
+=0D
+ // Find an active policy if one exists.=0D
+ ActivePolicy =3D GetBestPolicyMatch( VariableName, VendorGuid, NULL );=0D
+=0D
+ // If we have an active policy, check it against the incoming data.=0D
+ if (ActivePolicy !=3D NULL) {=0D
+ //=0D
+ // Only enforce size and attribute constraints when updating data, not=
deleting.=0D
+ if (!IsDel) {=0D
+ // Check for size constraints.=0D
+ if ((ActivePolicy->MinSize > 0 && DataSize < ActivePolicy->MinSize) =
||=0D
+ (ActivePolicy->MaxSize > 0 && DataSize > ActivePolicy->MaxSize))=
{=0D
+ ReturnStatus =3D EFI_INVALID_PARAMETER;=0D
+ DEBUG(( DEBUG_VERBOSE, "%a - Bad Size. 0x%X <> 0x%X-0x%X\n", __FUN=
CTION__,=0D
+ DataSize, ActivePolicy->MinSize, ActivePolicy->MaxSize ));=
=0D
+ goto Exit;=0D
+ }=0D
+=0D
+ // Check for attribute constraints.=0D
+ if ((ActivePolicy->AttributesMustHave & Attributes) !=3D ActivePolic=
y->AttributesMustHave ||=0D
+ (ActivePolicy->AttributesCantHave & Attributes) !=3D 0) {=0D
+ ReturnStatus =3D EFI_INVALID_PARAMETER;=0D
+ DEBUG(( DEBUG_VERBOSE, "%a - Bad Attributes. 0x%X <> 0x%X:0x%X\n",=
__FUNCTION__,=0D
+ Attributes, ActivePolicy->AttributesMustHave, ActivePolicy=
->AttributesCantHave ));=0D
+ goto Exit;=0D
+ }=0D
+ }=0D
+=0D
+ //=0D
+ // Lock policy check.=0D
+ //=0D
+ // Check for immediate lock.=0D
+ if (ActivePolicy->LockPolicyType =3D=3D VARIABLE_POLICY_TYPE_LOCK_NOW)=
{=0D
+ ReturnStatus =3D EFI_WRITE_PROTECTED;=0D
+ goto Exit;=0D
+ }=0D
+ // Check for lock on create.=0D
+ else if (ActivePolicy->LockPolicyType =3D=3D VARIABLE_POLICY_TYPE_LOCK=
_ON_CREATE) {=0D
+ StateVarSize =3D 0;=0D
+ Status =3D mGetVariableHelper( VariableName,=0D
+ VendorGuid,=0D
+ NULL,=0D
+ &StateVarSize,=0D
+ NULL );=0D
+ if (Status =3D=3D EFI_BUFFER_TOO_SMALL) {=0D
+ ReturnStatus =3D EFI_WRITE_PROTECTED;=0D
+ goto Exit;=0D
+ }=0D
+ }=0D
+ // Check for lock on state variable.=0D
+ else if (ActivePolicy->LockPolicyType =3D=3D VARIABLE_POLICY_TYPE_LOCK=
_ON_VAR_STATE) {=0D
+ StateVarPolicy =3D (VARIABLE_LOCK_ON_VAR_STATE_POLICY*)((UINT8*)Acti=
vePolicy + sizeof(VARIABLE_POLICY_ENTRY));=0D
+ StateVarName =3D (CHAR16*)((UINT8*)StateVarPolicy + sizeof(VARIABLE_=
LOCK_ON_VAR_STATE_POLICY));=0D
+ StateVarSize =3D sizeof(StateVar);=0D
+ Status =3D mGetVariableHelper( StateVarName,=0D
+ &StateVarPolicy->Namespace,=0D
+ NULL,=0D
+ &StateVarSize,=0D
+ &StateVar );=0D
+=0D
+ // If the variable was found, check the state. If matched, this vari=
able is locked.=0D
+ if (!EFI_ERROR( Status )) {=0D
+ if (StateVar =3D=3D StateVarPolicy->Value) {=0D
+ ReturnStatus =3D EFI_WRITE_PROTECTED;=0D
+ goto Exit;=0D
+ }=0D
+ }=0D
+ // EFI_NOT_FOUND and EFI_BUFFER_TOO_SMALL indicate that the state do=
esn't match.=0D
+ else if (Status !=3D EFI_NOT_FOUND && Status !=3D EFI_BUFFER_TOO_SMA=
LL) {=0D
+ // We don't know what happened, but it isn't good.=0D
+ ReturnStatus =3D EFI_ABORTED;=0D
+ goto Exit;=0D
+ }=0D
+ }=0D
+ }=0D
+=0D
+Exit:=0D
+ DEBUG(( DEBUG_VERBOSE, "%a - Variable (%g:%s) returning %r.\n", __FUNCTI=
ON__, VendorGuid, VariableName, ReturnStatus ));=0D
+ return ReturnStatus;=0D
+}=0D
+=0D
+=0D
+/**=0D
+ This API function disables the variable policy enforcement. If it's=0D
+ already been called once, will return EFI_ALREADY_STARTED.=0D
+=0D
+ @retval EFI_SUCCESS=0D
+ @retval EFI_ALREADY_STARTED Has already been called once this boot=
.=0D
+ @retval EFI_WRITE_PROTECTED Interface has been locked until reboot=
.=0D
+ @retval EFI_WRITE_PROTECTED Interface option is disabled by platfo=
rm PCD.=0D
+ @retval EFI_NOT_READY Library has not yet been initialized.=
=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+DisableVariablePolicy (=0D
+ VOID=0D
+ )=0D
+{=0D
+ if (!IsVariablePolicyLibInitialized()) {=0D
+ return EFI_NOT_READY;=0D
+ }=0D
+ if (mProtectionDisabled) {=0D
+ return EFI_ALREADY_STARTED;=0D
+ }=0D
+ if (mInterfaceLocked) {=0D
+ return EFI_WRITE_PROTECTED;=0D
+ }=0D
+ if (!PcdGetBool (PcdAllowVariablePolicyEnforcementDisable)) {=0D
+ return EFI_WRITE_PROTECTED;=0D
+ }=0D
+ mProtectionDisabled =3D TRUE;=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+=0D
+/**=0D
+ This API function will dump the entire contents of the variable policy t=
able.=0D
+=0D
+ Similar to GetVariable, the first call can be made with a 0 size and it =
will return=0D
+ the size of the buffer required to hold the entire table.=0D
+=0D
+ @param[out] Policy Pointer to the policy buffer. Can be NULL if Siz=
e is 0.=0D
+ @param[in,out] Size On input, the size of the output buffer. On outp=
ut, the size=0D
+ of the data returned.=0D
+=0D
+ @retval EFI_SUCCESS Policy data is in the output buffer =
and Size has been updated.=0D
+ @retval EFI_INVALID_PARAMETER Size is NULL, or Size is non-zero an=
d Policy is NULL.=0D
+ @retval EFI_BUFFER_TOO_SMALL Size is insufficient to hold policy.=
Size updated with required size.=0D
+ @retval EFI_NOT_READY Library has not yet been initialized=
.=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+DumpVariablePolicy (=0D
+ OUT UINT8 *Policy,=0D
+ IN OUT UINT32 *Size=0D
+ )=0D
+{=0D
+ if (!IsVariablePolicyLibInitialized()) {=0D
+ return EFI_NOT_READY;=0D
+ }=0D
+=0D
+ // Check the parameters.=0D
+ if (Size =3D=3D NULL || (*Size > 0 && Policy =3D=3D NULL)) {=0D
+ return EFI_INVALID_PARAMETER;=0D
+ }=0D
+=0D
+ // Make sure the size is sufficient to hold the policy table.=0D
+ if (*Size < mCurrentTableUsage) {=0D
+ *Size =3D mCurrentTableUsage;=0D
+ return EFI_BUFFER_TOO_SMALL;=0D
+ }=0D
+=0D
+ // If we're still here, copy the table and bounce.=0D
+ CopyMem( Policy, mPolicyTable, mCurrentTableUsage );=0D
+ *Size =3D mCurrentTableUsage;=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+=0D
+/**=0D
+ This API function returns whether or not the policy engine is=0D
+ currently being enforced.=0D
+=0D
+ @retval TRUE=0D
+ @retval FALSE=0D
+ @retval FALSE Library has not yet been initialized.=0D
+=0D
+**/=0D
+BOOLEAN=0D
+EFIAPI=0D
+IsVariablePolicyEnabled (=0D
+ VOID=0D
+ )=0D
+{=0D
+ if (!IsVariablePolicyLibInitialized()) {=0D
+ return FALSE;=0D
+ }=0D
+ return !mProtectionDisabled;=0D
+}=0D
+=0D
+=0D
+/**=0D
+ This API function locks the interface so that no more policy updates=0D
+ can be performed or changes made to the enforcement until the next boot.=
=0D
+=0D
+ @retval EFI_SUCCESS=0D
+ @retval EFI_NOT_READY Library has not yet been initialized.=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+LockVariablePolicy (=0D
+ VOID=0D
+ )=0D
+{=0D
+ if (!IsVariablePolicyLibInitialized()) {=0D
+ return EFI_NOT_READY;=0D
+ }=0D
+ if (mInterfaceLocked) {=0D
+ return EFI_WRITE_PROTECTED;=0D
+ }=0D
+ mInterfaceLocked =3D TRUE;=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+=0D
+/**=0D
+ This API function returns whether or not the policy interface is locked=
=0D
+ for the remainder of the boot.=0D
+=0D
+ @retval TRUE=0D
+ @retval FALSE=0D
+ @retval FALSE Library has not yet been initialized.=0D
+=0D
+**/=0D
+BOOLEAN=0D
+EFIAPI=0D
+IsVariablePolicyInterfaceLocked (=0D
+ VOID=0D
+ )=0D
+{=0D
+ if (!IsVariablePolicyLibInitialized()) {=0D
+ return FALSE;=0D
+ }=0D
+ return mInterfaceLocked;=0D
+}=0D
+=0D
+=0D
+/**=0D
+ This helper function initializes the library and sets=0D
+ up any required internal structures or handlers.=0D
+=0D
+ Also registers the internal pointer for the GetVariable helper.=0D
+=0D
+ @param[in] GetVariableHelper A function pointer matching the EFI_GET_VA=
RIABLE prototype that will be used to=0D
+ check policy criteria that involve the existence of othe=
r variables.=0D
+=0D
+ @retval EFI_SUCCESS=0D
+ @retval EFI_ALREADY_STARTED The initialize function has been calle=
d more than once without a call to=0D
+ deinitialize.=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+InitVariablePolicyLib (=0D
+ IN EFI_GET_VARIABLE GetVariableHelper=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+=0D
+ if (mGetVariableHelper !=3D NULL) {=0D
+ Status =3D EFI_ALREADY_STARTED;=0D
+ }=0D
+=0D
+ if (!EFI_ERROR( Status )) {=0D
+ Status =3D VariablePolicyExtraInit();=0D
+ }=0D
+=0D
+ if (!EFI_ERROR( Status )) {=0D
+ // Save an internal pointer to the GetVariableHelper.=0D
+ mGetVariableHelper =3D GetVariableHelper;=0D
+=0D
+ // Initialize the global state.=0D
+ mInterfaceLocked =3D FALSE;=0D
+ mProtectionDisabled =3D FALSE;=0D
+ mPolicyTable =3D NULL;=0D
+ mCurrentTableSize =3D 0;=0D
+ mCurrentTableUsage =3D 0;=0D
+ mCurrentTableCount =3D 0;=0D
+ }=0D
+=0D
+ return Status;=0D
+}=0D
+=0D
+=0D
+/**=0D
+ This helper function returns whether or not the library is currently ini=
tialized.=0D
+=0D
+ @retval TRUE=0D
+ @retval FALSE=0D
+=0D
+**/=0D
+BOOLEAN=0D
+EFIAPI=0D
+IsVariablePolicyLibInitialized (=0D
+ VOID=0D
+ )=0D
+{=0D
+ return (mGetVariableHelper !=3D NULL);=0D
+}=0D
+=0D
+=0D
+/**=0D
+ This helper function tears down the library.=0D
+=0D
+ Should generally only be used for test harnesses.=0D
+=0D
+ @retval EFI_SUCCESS=0D
+ @retval EFI_NOT_READY Deinitialize was called without first call=
ing initialize.=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+DeinitVariablePolicyLib (=0D
+ VOID=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+=0D
+ if (mGetVariableHelper =3D=3D NULL) {=0D
+ Status =3D EFI_NOT_READY;=0D
+ }=0D
+=0D
+ if (!EFI_ERROR( Status )) {=0D
+ Status =3D VariablePolicyExtraDeinit();=0D
+ }=0D
+=0D
+ if (!EFI_ERROR( Status )) {=0D
+ mGetVariableHelper =3D NULL;=0D
+ mInterfaceLocked =3D FALSE;=0D
+ mProtectionDisabled =3D FALSE;=0D
+ mCurrentTableSize =3D 0;=0D
+ mCurrentTableUsage =3D 0;=0D
+ mCurrentTableCount =3D 0;=0D
+=0D
+ if (mPolicyTable !=3D NULL) {=0D
+ FreePool( mPolicyTable );=0D
+ mPolicyTable =3D NULL;=0D
+ }=0D
+ }=0D
+=0D
+ return Status;=0D
+}=0D
diff --git a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/=
VariablePolicyUnitTest.c b/MdeModulePkg/Library/VariablePolicyLib/VariableP=
olicyUnitTest/VariablePolicyUnitTest.c
new file mode 100644
index 000000000000..f133f2f30e36
--- /dev/null
+++ b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/Variabl=
ePolicyUnitTest.c
@@ -0,0 +1,2436 @@
+/** @file -- VariablePolicyUnitTest.c=0D
+UnitTest for...=0D
+Business logic for Variable Policy enforcement.=0D
+=0D
+Copyright (c) Microsoft Corporation.=0D
+SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+=0D
+**/=0D
+=0D
+#include <stdio.h>=0D
+#include <string.h>=0D
+#include <stdarg.h>=0D
+#include <stddef.h>=0D
+#include <setjmp.h>=0D
+#include <cmocka.h>=0D
+=0D
+#include <Uefi.h>=0D
+#include <Library/PrintLib.h>=0D
+#include <Library/DebugLib.h>=0D
+#include <Library/UnitTestLib.h>=0D
+#include <Library/BaseMemoryLib.h>=0D
+#include <Library/MemoryAllocationLib.h>=0D
+#include <Library/BaseLib.h>=0D
+=0D
+#include <Guid/VariableFormat.h>=0D
+=0D
+#include <Protocol/VariablePolicy.h>=0D
+#include <Library/VariablePolicyLib.h>=0D
+=0D
+// MU_CHANGE - Turn this off for now. Try to turn it back on with extra bu=
ild options.=0D
+// #ifndef INTERNAL_UNIT_TEST=0D
+// #error Make sure to build thie with INTERNAL_UNIT_TEST enabled! Otherwi=
se, some important tests may be skipped!=0D
+// #endif=0D
+=0D
+=0D
+#define UNIT_TEST_NAME "UEFI Variable Policy UnitTest"=0D
+#define UNIT_TEST_VERSION "0.5"=0D
+=0D
+///=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=0D
+=0D
+#pragma pack(push, 1)=0D
+typedef struct _SIMPLE_VARIABLE_POLICY_ENTRY {=0D
+ VARIABLE_POLICY_ENTRY Header;=0D
+ CHAR16 Name[];=0D
+} SIMPLE_VARIABLE_POLICY_ENTRY;=0D
+#define EXPANDED_VARIABLE_POLICY_ENTRY_VAR_NAME_LENGTH 1001 // 1000 ch=
aracters + terminator.=0D
+#define EXPANDED_VARIABLE_POLICY_ENTRY_VAR_NAME_SIZE (EXPANDED_VARIABLE=
_POLICY_ENTRY_VAR_NAME_LENGTH * sizeof(CHAR16))=0D
+typedef struct _EXPANDED_VARIABLE_POLICY_ENTRY {=0D
+ VARIABLE_POLICY_ENTRY Header;=0D
+ VARIABLE_LOCK_ON_VAR_STATE_POLICY StatePolicy;=0D
+ CHAR16 StateName[EXPANDED_VARIABLE_POLICY_E=
NTRY_VAR_NAME_LENGTH];=0D
+ CHAR16 Name[EXPANDED_VARIABLE_POLICY_ENTRY_=
VAR_NAME_LENGTH];=0D
+} EXPANDED_VARIABLE_POLICY_ENTRY;=0D
+#pragma pack(pop)=0D
+=0D
+// {F955BA2D-4A2C-480C-BFD1-3CC522610592}=0D
+#define TEST_GUID_1 { 0xf955ba2d, 0x4a2c, 0x480c, { 0xbf, 0xd1, 0x3c, 0xc5=
, 0x22, 0x61, 0x5, 0x92 } }=0D
+EFI_GUID mTestGuid1 =3D TEST_GUID_1;=0D
+// {2DEA799E-5E73-43B9-870E-C945CE82AF3A}=0D
+#define TEST_GUID_2 { 0x2dea799e, 0x5e73, 0x43b9, { 0x87, 0xe, 0xc9, 0x45,=
0xce, 0x82, 0xaf, 0x3a } }=0D
+EFI_GUID mTestGuid2 =3D TEST_GUID_2;=0D
+// {698A2BFD-A616-482D-B88C-7100BD6682A9}=0D
+#define TEST_GUID_3 { 0x698a2bfd, 0xa616, 0x482d, { 0xb8, 0x8c, 0x71, 0x0,=
0xbd, 0x66, 0x82, 0xa9 } }=0D
+EFI_GUID mTestGuid3 =3D TEST_GUID_3;=0D
+=0D
+#define TEST_VAR_1_NAME L"TestVar1"=0D
+#define TEST_VAR_2_NAME L"TestVar2"=0D
+#define TEST_VAR_3_NAME L"TestVar3"=0D
+=0D
+#define TEST_POLICY_ATTRIBUTES_NULL 0=0D
+#define TEST_POLICY_MIN_SIZE_NULL 0=0D
+#define TEST_POLICY_MAX_SIZE_NULL MAX_UINT32=0D
+=0D
+#define TEST_POLICY_MIN_SIZE_10 10=0D
+#define TEST_POLICY_MAX_SIZE_200 200=0D
+=0D
+#define TEST_300_HASHES_STRING L"####################################=
##############"\=0D
+ "###################################=
###############"\=0D
+ "###################################=
###############"\=0D
+ "###################################=
###############"\=0D
+ "###################################=
###############"\=0D
+ "###################################=
###############"=0D
+=0D
+=0D
+///=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=0D
+=0D
+/**=0D
+ Helper function to initialize a VARIABLE_POLICY_ENTRY structure with a N=
ame and StateName.=0D
+=0D
+ Takes care of all the messy packing.=0D
+=0D
+ @param[in,out] Entry=0D
+ @param[in] Name [Optional]=0D
+ @param[in] StateName [Optional]=0D
+=0D
+ @retval TRUE=0D
+ @retval FALSE=0D
+=0D
+**/=0D
+STATIC=0D
+BOOLEAN=0D
+InitExpVarPolicyStrings (=0D
+ EXPANDED_VARIABLE_POLICY_ENTRY *Entry,=0D
+ CHAR16 *Name, OPTIONAL=0D
+ CHAR16 *StateName OPTIONAL=0D
+ )=0D
+{=0D
+ UINTN NameSize;=0D
+ UINTN StateNameSize;=0D
+=0D
+ NameSize =3D Name =3D=3D NULL ? 0 : StrSize( Name );=0D
+ StateNameSize =3D StateName =3D=3D NULL ? 0 : StrSize( StateName );=0D
+=0D
+ if (NameSize > EXPANDED_VARIABLE_POLICY_ENTRY_VAR_NAME_SIZE || NameSize =
MAX_UINT16 ||=0D
+ StateNameSize > EXPANDED_VARIABLE_POLICY_ENTRY_VAR_NAME_SIZE || Stat=
eNameSize > MAX_UINT16) {=0D
+ return FALSE;=0D
+ }=0D
+=0D
+ Entry->Header.OffsetToName =3D sizeof(VARIABLE_POLICY_ENTRY);=0D
+ if (StateName !=3D NULL) {=0D
+ Entry->Header.OffsetToName +=3D (UINT16)sizeof(VARIABLE_LOCK_ON_VAR_ST=
ATE_POLICY) + (UINT16)StateNameSize;=0D
+ }=0D
+ Entry->Header.Size =3D Entry->Header.OffsetToName + (UINT16)NameSize;=0D
+=0D
+ CopyMem( (UINT8*)Entry + Entry->Header.OffsetToName, Name, NameSize );=0D
+ if (StateName !=3D NULL) {=0D
+ CopyMem( (UINT8*)Entry + sizeof(VARIABLE_POLICY_ENTRY) + sizeof(VARIAB=
LE_LOCK_ON_VAR_STATE_POLICY), StateName, StateNameSize );=0D
+ }=0D
+=0D
+ return TRUE;=0D
+}=0D
+=0D
+/**=0D
+ Mocked version of GetVariable, for testing.=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+StubGetVariableNull (=0D
+ IN CHAR16 *VariableName,=0D
+ IN EFI_GUID *VendorGuid,=0D
+ OUT UINT32 *Attributes, OPTIONAL=0D
+ IN OUT UINTN *DataSize,=0D
+ OUT VOID *Data OPTIONAL=0D
+ )=0D
+{=0D
+ UINT32 MockedAttr;=0D
+ UINTN MockedDataSize;=0D
+ VOID *MockedData;=0D
+ EFI_STATUS MockedReturn;=0D
+=0D
+ check_expected_ptr( VariableName );=0D
+ check_expected_ptr( VendorGuid );=0D
+ check_expected_ptr( DataSize );=0D
+=0D
+ MockedAttr =3D (UINT32)mock();=0D
+ MockedDataSize =3D (UINTN)mock();=0D
+ MockedData =3D (VOID*)mock();=0D
+ MockedReturn =3D (EFI_STATUS)mock();=0D
+=0D
+ if (Attributes !=3D NULL) {=0D
+ *Attributes =3D MockedAttr;=0D
+ }=0D
+ if (Data !=3D NULL && !EFI_ERROR(MockedReturn)) {=0D
+ CopyMem( Data, MockedData, MockedDataSize );=0D
+ }=0D
+=0D
+ *DataSize =3D MockedDataSize;=0D
+=0D
+ return MockedReturn;=0D
+}=0D
+=0D
+//=0D
+// Anything you think might be helpful that isn't a test itself.=0D
+//=0D
+=0D
+/**=0D
+ This is a common setup function that will ensure the library is always i=
nitialized=0D
+ with the stubbed GetVariable.=0D
+=0D
+ Not used by all test cases, but by most.=0D
+**/=0D
+STATIC=0D
+UNIT_TEST_STATUS=0D
+LibInitMocked (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ return EFI_ERROR(InitVariablePolicyLib( StubGetVariableNull )) ? UNIT_TE=
ST_ERROR_PREREQUISITE_NOT_MET : UNIT_TEST_PASSED;=0D
+}=0D
+=0D
+/**=0D
+ Common cleanup function to make sure that the library is always de-initi=
alized prior=0D
+ to the next test case.=0D
+*/=0D
+STATIC=0D
+VOID=0D
+LibCleanup (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ DeinitVariablePolicyLib();=0D
+}=0D
+=0D
+=0D
+///=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=0D
+=0D
+///=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=0D
+=0D
+/**=0D
+ Test Case=0D
+*/=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+ShouldBeAbleToInitAndDeinitTheLibrary (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ Status =3D InitVariablePolicyLib( StubGetVariableNull );=0D
+ UT_ASSERT_NOT_EFI_ERROR( Status );=0D
+=0D
+ UT_ASSERT_TRUE( IsVariablePolicyLibInitialized() );=0D
+=0D
+ Status =3D DeinitVariablePolicyLib();=0D
+ UT_ASSERT_NOT_EFI_ERROR( Status );=0D
+=0D
+ UT_ASSERT_FALSE( IsVariablePolicyLibInitialized() );=0D
+=0D
+ return UNIT_TEST_PASSED;=0D
+}=0D
+=0D
+/**=0D
+ Test Case=0D
+*/=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+ShouldNotBeAbleToInitializeTheLibraryTwice (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ Status =3D InitVariablePolicyLib( StubGetVariableNull );=0D
+ UT_ASSERT_NOT_EFI_ERROR( Status );=0D
+ Status =3D InitVariablePolicyLib( StubGetVariableNull );=0D
+ UT_ASSERT_TRUE( EFI_ERROR( Status ) );=0D
+ return UNIT_TEST_PASSED;=0D
+}=0D
+=0D
+/**=0D
+ Test Case=0D
+*/=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+ShouldFailDeinitWithoutInit (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ Status =3D DeinitVariablePolicyLib();=0D
+ UT_ASSERT_TRUE( EFI_ERROR( Status ) );=0D
+ return UNIT_TEST_PASSED;=0D
+}=0D
+=0D
+/**=0D
+ Test Case=0D
+*/=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+ApiCommandsShouldNotRespondIfLibIsUninitialized (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ SIMPLE_VARIABLE_POLICY_ENTRY TestPolicy =3D {=0D
+ {=0D
+ VARIABLE_POLICY_ENTRY_REVISION,=0D
+ sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME),=0D
+ sizeof(VARIABLE_POLICY_ENTRY),=0D
+ TEST_GUID_1,=0D
+ TEST_POLICY_MIN_SIZE_NULL,=0D
+ TEST_POLICY_MAX_SIZE_NULL,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ VARIABLE_POLICY_TYPE_NO_LOCK=0D
+ },=0D
+ TEST_VAR_1_NAME=0D
+ };=0D
+ UINT8 DummyData[8];=0D
+ UINT32 DummyDataSize =3D sizeof(DummyData);=0D
+=0D
+ // This test should not start with an initialized library.=0D
+=0D
+ // Verify that all API commands fail.=0D
+ UT_ASSERT_TRUE( EFI_ERROR( LockVariablePolicy() ) );=0D
+ UT_ASSERT_TRUE( EFI_ERROR( DisableVariablePolicy() ) );=0D
+ UT_ASSERT_TRUE( EFI_ERROR( RegisterVariablePolicy( &TestPolicy.Header ) =
) );=0D
+ UT_ASSERT_TRUE( EFI_ERROR( DumpVariablePolicy( DummyData, &DummyDataSize=
) ) );=0D
+ UT_ASSERT_FALSE( IsVariablePolicyInterfaceLocked() );=0D
+ UT_ASSERT_FALSE( IsVariablePolicyEnabled() );=0D
+ UT_ASSERT_TRUE( EFI_ERROR( ValidateSetVariable( TEST_VAR_1_NAME,=0D
+ &mTestGuid1,=0D
+ VARIABLE_ATTRIBUTE_NV_BS,=
=0D
+ sizeof(DummyData),=0D
+ DummyData ) ) );=0D
+=0D
+ return UNIT_TEST_PASSED;=0D
+}=0D
+=0D
+=0D
+///=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=0D
+=0D
+#ifdef INTERNAL_UNIT_TEST=0D
+=0D
+BOOLEAN=0D
+EvaluatePolicyMatch (=0D
+ IN CONST VARIABLE_POLICY_ENTRY *EvalEntry,=0D
+ IN CONST CHAR16 *VariableName,=0D
+ IN CONST EFI_GUID *VendorGuid,=0D
+ OUT UINT8 *MatchPriority OPTIONAL=0D
+ );=0D
+=0D
+/**=0D
+ Test Case=0D
+*/=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+PoliciesShouldMatchByNameAndGuid (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ SIMPLE_VARIABLE_POLICY_ENTRY MatchCheckPolicy =3D {=0D
+ {=0D
+ VARIABLE_POLICY_ENTRY_REVISION,=0D
+ sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME),=0D
+ sizeof(VARIABLE_POLICY_ENTRY),=0D
+ TEST_GUID_1,=0D
+ TEST_POLICY_MIN_SIZE_NULL,=0D
+ TEST_POLICY_MAX_SIZE_NULL,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ VARIABLE_POLICY_TYPE_NO_LOCK=0D
+ },=0D
+ TEST_VAR_1_NAME=0D
+ };=0D
+ CHAR16 *CheckVar1Name =3D TEST_VAR_1_NAME;=0D
+ CHAR16 *CheckVar2Name =3D TEST_VAR_2_NAME;=0D
+=0D
+ // Make sure that a different name does not match.=0D
+ UT_ASSERT_FALSE( EvaluatePolicyMatch( &MatchCheckPolicy.Header, CheckVar=
2Name, &mTestGuid1, NULL ) );=0D
+=0D
+ // Make sure that a different GUID does not match.=0D
+ UT_ASSERT_FALSE( EvaluatePolicyMatch( &MatchCheckPolicy.Header, CheckVar=
1Name, &mTestGuid2, NULL ) );=0D
+=0D
+ // Make sure that the same name and GUID match.=0D
+ UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolicy.Header, CheckVar1=
Name, &mTestGuid1, NULL ) );=0D
+=0D
+ return UNIT_TEST_PASSED;=0D
+}=0D
+=0D
+/**=0D
+ Test Case=0D
+*/=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+WildcardPoliciesShouldMatchDigits (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ SIMPLE_VARIABLE_POLICY_ENTRY MatchCheckPolicy =3D {=0D
+ {=0D
+ VARIABLE_POLICY_ENTRY_REVISION,=0D
+ sizeof(VARIABLE_POLICY_ENTRY) + sizeof(L"Wildcard#VarName##"),=0D
+ sizeof(VARIABLE_POLICY_ENTRY),=0D
+ TEST_GUID_1,=0D
+ TEST_POLICY_MIN_SIZE_NULL,=0D
+ TEST_POLICY_MAX_SIZE_NULL,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ VARIABLE_POLICY_TYPE_NO_LOCK=0D
+ },=0D
+ L"Wildcard#VarName##"=0D
+ };=0D
+ CHAR16 *CheckVar1Name =3D L"Wildcard1VarName12";=0D
+ CHAR16 *CheckVar2Name =3D L"Wildcard2VarName34";=0D
+ CHAR16 *CheckVarBName =3D L"WildcardBVarName56";=0D
+ CHAR16 *CheckVarHName =3D L"Wildcard#VarName56";=0D
+=0D
+ // Make sure that two different sets of wildcard numbers match.=0D
+ UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolicy.Header, CheckVar1=
Name, &mTestGuid1, NULL ) );=0D
+ UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolicy.Header, CheckVar2=
Name, &mTestGuid1, NULL ) );=0D
+=0D
+ // Make sure that the non-number charaters don't match.=0D
+ UT_ASSERT_FALSE( EvaluatePolicyMatch( &MatchCheckPolicy.Header, CheckVar=
BName, &mTestGuid1, NULL ) );=0D
+=0D
+ // Make sure that '#' signs don't match.=0D
+ UT_ASSERT_FALSE( EvaluatePolicyMatch( &MatchCheckPolicy.Header, CheckVar=
HName, &mTestGuid1, NULL ) );=0D
+=0D
+ return UNIT_TEST_PASSED;=0D
+}=0D
+=0D
+/**=0D
+ Test Case=0D
+*/=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+WildcardPoliciesShouldMatchDigitsAdvanced (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ SIMPLE_VARIABLE_POLICY_ENTRY MatchCheckPolicy =3D {=0D
+ {=0D
+ VARIABLE_POLICY_ENTRY_REVISION,=0D
+ sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_300_HASHES_STRING),=0D
+ sizeof(VARIABLE_POLICY_ENTRY),=0D
+ TEST_GUID_1,=0D
+ TEST_POLICY_MIN_SIZE_NULL,=0D
+ TEST_POLICY_MAX_SIZE_NULL,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ VARIABLE_POLICY_TYPE_NO_LOCK=0D
+ },=0D
+ TEST_300_HASHES_STRING=0D
+ };=0D
+ CHAR16 *CheckShorterString =3D L"01234567890123456789012345678901=
234567890123456789";=0D
+ CHAR16 *CheckValidString =3D L"0123456789012345678901234567890123=
4567890123456789"\=0D
+ "01234567890123456789012345678901234=
567890123456789"\=0D
+ "01234567890123456789012345678901234=
567890123456789"\=0D
+ "01234567890123456789012345678901234=
567890123456789"\=0D
+ "01234567890123456789012345678901234=
567890123456789"\=0D
+ "01234567890123456789012345678901234=
567890123456789";=0D
+ CHAR16 *CheckLongerString =3D L"012345678901234567890123456789012=
34567890123456789"\=0D
+ "01234567890123456789012345678901234=
567890123456789"\=0D
+ "01234567890123456789012345678901234=
567890123456789"\=0D
+ "01234567890123456789012345678901234=
567890123456789"\=0D
+ "01234567890123456789012345678901234=
567890123456789"\=0D
+ "01234567890123456789012345678901234=
567890123456789"\=0D
+ "01234567890123456789012345678901234=
567890123456789";=0D
+ UINT8 MatchPriority;=0D
+=0D
+ // Make sure that the shorter and the longer do not match.=0D
+ UT_ASSERT_FALSE( EvaluatePolicyMatch( &MatchCheckPolicy.Header, CheckSho=
rterString, &mTestGuid1, NULL ) );=0D
+ UT_ASSERT_FALSE( EvaluatePolicyMatch( &MatchCheckPolicy.Header, CheckLon=
gerString, &mTestGuid1, NULL ) );=0D
+=0D
+ // Make sure that the valid one matches and has the expected priority.=0D
+ UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolicy.Header, CheckVali=
dString, &mTestGuid1, &MatchPriority ) );=0D
+ UT_ASSERT_EQUAL( MatchPriority, MAX_UINT8 );=0D
+=0D
+ return UNIT_TEST_PASSED;=0D
+}=0D
+=0D
+/**=0D
+ Test Case=0D
+*/=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+WildcardPoliciesShouldMatchNamespaces (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ VARIABLE_POLICY_ENTRY MatchCheckPolicy =3D {=0D
+ VARIABLE_POLICY_ENTRY_REVISION,=0D
+ sizeof(VARIABLE_POLICY_ENTRY),=0D
+ sizeof(VARIABLE_POLICY_ENTRY),=0D
+ TEST_GUID_1,=0D
+ TEST_POLICY_MIN_SIZE_NULL,=0D
+ TEST_POLICY_MAX_SIZE_NULL,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ VARIABLE_POLICY_TYPE_NO_LOCK=0D
+ };=0D
+ CHAR16 *CheckVar1Name =3D L"Wildcard1VarName12";=0D
+ CHAR16 *CheckVar2Name =3D L"Wildcard2VarName34";=0D
+ CHAR16 *CheckVarBName =3D L"WildcardBVarName56";=0D
+ CHAR16 *CheckVarHName =3D L"Wildcard#VarName56";=0D
+=0D
+ // Make sure that all names in the same namespace match.=0D
+ UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolicy, CheckVar1Name, &=
mTestGuid1, NULL ) );=0D
+ UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolicy, CheckVar2Name, &=
mTestGuid1, NULL ) );=0D
+ UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolicy, CheckVarBName, &=
mTestGuid1, NULL ) );=0D
+ UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolicy, CheckVarHName, &=
mTestGuid1, NULL ) );=0D
+=0D
+ // Make sure that different namespace doesn't match.=0D
+ UT_ASSERT_FALSE( EvaluatePolicyMatch( &MatchCheckPolicy, CheckVar1Name, =
&mTestGuid2, NULL ) );=0D
+=0D
+=0D
+ return UNIT_TEST_PASSED;=0D
+}=0D
+=0D
+/**=0D
+ Test Case=0D
+*/=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+MatchPrioritiesShouldFollowRules (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ SIMPLE_VARIABLE_POLICY_ENTRY MatchCheckPolicy =3D {=0D
+ {=0D
+ VARIABLE_POLICY_ENTRY_REVISION,=0D
+ sizeof(VARIABLE_POLICY_ENTRY) + sizeof(L"Wildcard1VarName12"),=0D
+ sizeof(VARIABLE_POLICY_ENTRY),=0D
+ TEST_GUID_1,=0D
+ TEST_POLICY_MIN_SIZE_NULL,=0D
+ TEST_POLICY_MAX_SIZE_NULL,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ VARIABLE_POLICY_TYPE_NO_LOCK=0D
+ },=0D
+ L"Wildcard1VarName12"=0D
+ };=0D
+ CHAR16 CheckVar1Name[] =3D L"Wildcard1VarName12";=0D
+ CHAR16 MatchVar1Name[] =3D L"Wildcard1VarName12";=0D
+ CHAR16 MatchVar2Name[] =3D L"Wildcard#VarName12";=0D
+ CHAR16 MatchVar3Name[] =3D L"Wildcard#VarName#2";=0D
+ CHAR16 MatchVar4Name[] =3D L"Wildcard#VarName##";=0D
+ UINT8 MatchPriority;=0D
+=0D
+ // Check with a perfect match.=0D
+ CopyMem( &MatchCheckPolicy.Name, MatchVar1Name, sizeof(MatchVar1Name) );=
=0D
+ UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolicy.Header, CheckVar1=
Name, &mTestGuid1, &MatchPriority ) );=0D
+ UT_ASSERT_EQUAL( MatchPriority, 0 );=0D
+=0D
+ // Check with progressively lower priority matches.=0D
+ CopyMem( &MatchCheckPolicy.Name, MatchVar2Name, sizeof(MatchVar2Name) );=
=0D
+ UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolicy.Header, CheckVar1=
Name, &mTestGuid1, &MatchPriority ) );=0D
+ UT_ASSERT_EQUAL( MatchPriority, 1 );=0D
+ CopyMem( &MatchCheckPolicy.Name, MatchVar3Name, sizeof(MatchVar3Name) );=
=0D
+ UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolicy.Header, CheckVar1=
Name, &mTestGuid1, &MatchPriority ) );=0D
+ UT_ASSERT_EQUAL( MatchPriority, 2 );=0D
+ CopyMem( &MatchCheckPolicy.Name, MatchVar4Name, sizeof(MatchVar4Name) );=
=0D
+ UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolicy.Header, CheckVar1=
Name, &mTestGuid1, &MatchPriority ) );=0D
+ UT_ASSERT_EQUAL( MatchPriority, 3 );=0D
+=0D
+ // Check against the entire namespace.=0D
+ MatchCheckPolicy.Header.Size =3D sizeof(VARIABLE_POLICY_ENTRY);=0D
+ UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolicy.Header, CheckVar1=
Name, &mTestGuid1, &MatchPriority ) );=0D
+ UT_ASSERT_EQUAL( MatchPriority, MAX_UINT8 );=0D
+=0D
+ return UNIT_TEST_PASSED;=0D
+}=0D
+=0D
+#endif // INTERNAL_UNIT_TEST=0D
+=0D
+=0D
+///=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=0D
+=0D
+/**=0D
+ Test Case=0D
+*/=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+RegisterShouldAllowNamespaceWildcards (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ SIMPLE_VARIABLE_POLICY_ENTRY ValidationPolicy =3D {=0D
+ {=0D
+ VARIABLE_POLICY_ENTRY_REVISION,=0D
+ sizeof(VARIABLE_POLICY_ENTRY),=0D
+ sizeof(VARIABLE_POLICY_ENTRY),=0D
+ TEST_GUID_1,=0D
+ TEST_POLICY_MIN_SIZE_NULL,=0D
+ TEST_POLICY_MAX_SIZE_NULL,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ VARIABLE_POLICY_TYPE_NO_LOCK=0D
+ },=0D
+ L""=0D
+ };=0D
+=0D
+ UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Heade=
r ) );=0D
+=0D
+ return UNIT_TEST_PASSED;=0D
+}=0D
+=0D
+/**=0D
+ Test Case=0D
+*/=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+RegisterShouldAllowStateVarsForNamespaces (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ EXPANDED_VARIABLE_POLICY_ENTRY ValidationPolicy =3D {=0D
+ {=0D
+ VARIABLE_POLICY_ENTRY_REVISION,=0D
+ 0, // Will be populated by init helper.=0D
+ 0, // Will be populated by init helper.=0D
+ TEST_GUID_1,=0D
+ TEST_POLICY_MIN_SIZE_NULL,=0D
+ TEST_POLICY_MAX_SIZE_NULL,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE=0D
+ },=0D
+ {=0D
+ TEST_GUID_2,=0D
+ 1, // Value=0D
+ 0 // Padding=0D
+ },=0D
+ L"",=0D
+ L""=0D
+ };=0D
+ UT_ASSERT_TRUE( InitExpVarPolicyStrings( &ValidationPolicy, NULL, TEST_V=
AR_2_NAME ) );=0D
+=0D
+ UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Heade=
r ) );=0D
+=0D
+ return UNIT_TEST_PASSED;=0D
+}=0D
+=0D
+/**=0D
+ Test Case=0D
+*/=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+RegisterShouldRejectNullPointers (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ UT_ASSERT_EQUAL( RegisterVariablePolicy( NULL ), EFI_INVALID_PARAMETER )=
;=0D
+ return UNIT_TEST_PASSED;=0D
+}=0D
+=0D
+/**=0D
+ Test Case=0D
+*/=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+RegisterShouldRejectBadRevisions (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ SIMPLE_VARIABLE_POLICY_ENTRY ValidationPolicy =3D {=0D
+ {=0D
+ VARIABLE_POLICY_ENTRY_REVISION,=0D
+ sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME),=0D
+ sizeof(VARIABLE_POLICY_ENTRY),=0D
+ TEST_GUID_1,=0D
+ TEST_POLICY_MIN_SIZE_NULL,=0D
+ TEST_POLICY_MAX_SIZE_NULL,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ VARIABLE_POLICY_TYPE_NO_LOCK=0D
+ },=0D
+ TEST_VAR_1_NAME=0D
+ };=0D
+=0D
+ ValidationPolicy.Header.Version =3D MAX_UINT32;=0D
+ UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), EFI=
_INVALID_PARAMETER );=0D
+=0D
+ return UNIT_TEST_PASSED;=0D
+}=0D
+=0D
+/**=0D
+ Test Case=0D
+*/=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+RegisterShouldRejectBadSizes (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ SIMPLE_VARIABLE_POLICY_ENTRY ValidationPolicy =3D {=0D
+ {=0D
+ VARIABLE_POLICY_ENTRY_REVISION,=0D
+ sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME),=0D
+ sizeof(VARIABLE_POLICY_ENTRY),=0D
+ TEST_GUID_1,=0D
+ TEST_POLICY_MIN_SIZE_NULL,=0D
+ TEST_POLICY_MAX_SIZE_NULL,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ VARIABLE_POLICY_TYPE_NO_LOCK=0D
+ },=0D
+ TEST_VAR_1_NAME=0D
+ };=0D
+=0D
+ ValidationPolicy.Header.Size =3D sizeof(VARIABLE_POLICY_ENTRY) - 2;=0D
+ UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), EFI=
_INVALID_PARAMETER );=0D
+=0D
+ return UNIT_TEST_PASSED;=0D
+}=0D
+=0D
+/**=0D
+ Test Case=0D
+*/=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+RegisterShouldRejectBadOffsets (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ EXPANDED_VARIABLE_POLICY_ENTRY ValidationPolicy =3D {=0D
+ {=0D
+ VARIABLE_POLICY_ENTRY_REVISION,=0D
+ 0, // Will be populated by init helper.=0D
+ 0, // Will be populated by init helper.=0D
+ TEST_GUID_1,=0D
+ TEST_POLICY_MIN_SIZE_NULL,=0D
+ TEST_POLICY_MAX_SIZE_NULL,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE=0D
+ },=0D
+ {=0D
+ TEST_GUID_2,=0D
+ 1, // Value=0D
+ 0 // Padding=0D
+ },=0D
+ L"",=0D
+ L""=0D
+ };=0D
+ UT_ASSERT_TRUE( InitExpVarPolicyStrings( &ValidationPolicy, TEST_VAR_1_N=
AME, TEST_VAR_2_NAME ) );=0D
+=0D
+ // Check for an offset outside the size bounds.=0D
+ ValidationPolicy.Header.OffsetToName =3D ValidationPolicy.Header.Size + =
1;=0D
+ UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), EFI=
_INVALID_PARAMETER );=0D
+=0D
+ // Check for an offset inside the policy header.=0D
+ ValidationPolicy.Header.OffsetToName =3D sizeof(VARIABLE_POLICY_ENTRY) -=
2;=0D
+ UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), EFI=
_INVALID_PARAMETER );=0D
+=0D
+ // Check for an offset inside the state policy header.=0D
+ ValidationPolicy.Header.OffsetToName =3D sizeof(VARIABLE_POLICY_ENTRY) +=
2;=0D
+ UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), EFI=
_INVALID_PARAMETER );=0D
+=0D
+ // Check for a ridiculous offset.=0D
+ ValidationPolicy.Header.OffsetToName =3D MAX_UINT16;=0D
+ UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), EFI=
_INVALID_PARAMETER );=0D
+=0D
+ return UNIT_TEST_PASSED;=0D
+}=0D
+=0D
+/**=0D
+ Test Case=0D
+*/=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+RegisterShouldRejectMissingStateStrings (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ EXPANDED_VARIABLE_POLICY_ENTRY ValidationPolicy =3D {=0D
+ {=0D
+ VARIABLE_POLICY_ENTRY_REVISION,=0D
+ 0, // Will be populated by init helper.=0D
+ 0, // Will be populated by init helper.=0D
+ TEST_GUID_1,=0D
+ TEST_POLICY_MIN_SIZE_NULL,=0D
+ TEST_POLICY_MAX_SIZE_NULL,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE=0D
+ },=0D
+ {=0D
+ TEST_GUID_2,=0D
+ 1, // Value=0D
+ 0 // Padding=0D
+ },=0D
+ L"",=0D
+ L""=0D
+ };=0D
+ UT_ASSERT_TRUE( InitExpVarPolicyStrings( &ValidationPolicy, TEST_VAR_1_N=
AME, TEST_VAR_2_NAME ) );=0D
+=0D
+ // Remove the state string and copy the Name into it's place.=0D
+ // Also adjust the offset.=0D
+ ValidationPolicy.Header.Size =3D sizeof(VARIABLE_POLICY_ENTRY) =
+ sizeof(VARIABLE_LOCK_ON_VAR_STATE_POLICY) + sizeof(TEST_VAR_1_NAME);=0D
+ ValidationPolicy.Header.OffsetToName =3D sizeof(VARIABLE_POLICY_ENTRY) =
+ sizeof(VARIABLE_LOCK_ON_VAR_STATE_POLICY);=0D
+ CopyMem( (UINT8*)&ValidationPolicy + ValidationPolicy.Header.OffsetToNam=
e, TEST_VAR_1_NAME, sizeof(TEST_VAR_1_NAME) );=0D
+=0D
+ // Make sure that this structure fails.=0D
+ UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), EFI=
_INVALID_PARAMETER );=0D
+=0D
+ return UNIT_TEST_PASSED;=0D
+}=0D
+=0D
+/**=0D
+ Test Case=0D
+*/=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+RegisterShouldRejectStringsMissingNull (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ EXPANDED_VARIABLE_POLICY_ENTRY ValidationPolicy =3D {=0D
+ {=0D
+ VARIABLE_POLICY_ENTRY_REVISION,=0D
+ 0, // Will be populated by init helper.=0D
+ 0, // Will be populated by init helper.=0D
+ TEST_GUID_1,=0D
+ TEST_POLICY_MIN_SIZE_NULL,=0D
+ TEST_POLICY_MAX_SIZE_NULL,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE=0D
+ },=0D
+ {=0D
+ TEST_GUID_2,=0D
+ 1, // Value=0D
+ 0 // Padding=0D
+ },=0D
+ L"",=0D
+ L""=0D
+ };=0D
+ UT_ASSERT_TRUE( InitExpVarPolicyStrings( &ValidationPolicy, TEST_VAR_1_N=
AME, TEST_VAR_2_NAME ) );=0D
+=0D
+ // Removing the NULL from the Name should fail.=0D
+ ValidationPolicy.Header.Size =3D ValidationPolicy.Header.Size - sizeof(C=
HAR16);=0D
+ UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), EFI=
_INVALID_PARAMETER );=0D
+=0D
+ // Removing the NULL from the State Name is a little trickier.=0D
+ // Copy the Name up one byte.=0D
+ ValidationPolicy.Header.OffsetToName =3D ValidationPolicy.Header.OffsetT=
oName - sizeof(CHAR16);=0D
+ CopyMem( (UINT8*)&ValidationPolicy + ValidationPolicy.Header.OffsetToNam=
e, TEST_VAR_1_NAME, sizeof(TEST_VAR_1_NAME) );=0D
+ UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), EFI=
_INVALID_PARAMETER );=0D
+=0D
+ return UNIT_TEST_PASSED;=0D
+}=0D
+=0D
+/**=0D
+ Test Case=0D
+*/=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+RegisterShouldRejectMalformedStrings (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ EXPANDED_VARIABLE_POLICY_ENTRY ValidationPolicy =3D {=0D
+ {=0D
+ VARIABLE_POLICY_ENTRY_REVISION,=0D
+ 0, // Will be populated by init helper.=0D
+ 0, // Will be populated by init helper.=0D
+ TEST_GUID_1,=0D
+ TEST_POLICY_MIN_SIZE_NULL,=0D
+ TEST_POLICY_MAX_SIZE_NULL,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE=0D
+ },=0D
+ {=0D
+ TEST_GUID_2,=0D
+ 1, // Value=0D
+ 0 // Padding=0D
+ },=0D
+ L"",=0D
+ L""=0D
+ };=0D
+ UT_ASSERT_TRUE( InitExpVarPolicyStrings( &ValidationPolicy, TEST_VAR_1_N=
AME, TEST_VAR_2_NAME ) );=0D
+=0D
+ // Bisecting the NULL from the Name should fail.=0D
+ ValidationPolicy.Header.Size =3D ValidationPolicy.Header.Size - 1;=0D
+ UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), EFI=
_INVALID_PARAMETER );=0D
+=0D
+ // Bisecting the NULL from the State Name is a little trickier.=0D
+ // Copy the Name up one byte.=0D
+ ValidationPolicy.Header.OffsetToName =3D ValidationPolicy.Header.OffsetT=
oName - 1;=0D
+ CopyMem( (UINT8*)&ValidationPolicy + ValidationPolicy.Header.OffsetToNam=
e, TEST_VAR_1_NAME, sizeof(TEST_VAR_1_NAME) );=0D
+ UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), EFI=
_INVALID_PARAMETER );=0D
+=0D
+ return UNIT_TEST_PASSED;=0D
+}=0D
+=0D
+/**=0D
+ Test Case=0D
+*/=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+RegisterShouldRejectUnpackedPolicies (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ EXPANDED_VARIABLE_POLICY_ENTRY ValidationPolicy =3D {=0D
+ {=0D
+ VARIABLE_POLICY_ENTRY_REVISION,=0D
+ 0, // Will be populated by init helper.=0D
+ 0, // Will be populated by init helper.=0D
+ TEST_GUID_1,=0D
+ TEST_POLICY_MIN_SIZE_NULL,=0D
+ TEST_POLICY_MAX_SIZE_NULL,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE=0D
+ },=0D
+ {=0D
+ TEST_GUID_2,=0D
+ 1, // Value=0D
+ 0 // Padding=0D
+ },=0D
+ L"",=0D
+ L""=0D
+ };=0D
+ UT_ASSERT_TRUE( InitExpVarPolicyStrings( &ValidationPolicy, TEST_VAR_1_N=
AME, TEST_VAR_2_NAME ) );=0D
+=0D
+ // Increase the size and move the Name out a bit.=0D
+ ValidationPolicy.Header.Size =3D ValidationPolicy.Header.Size + sizeof(C=
HAR16);=0D
+ ValidationPolicy.Header.OffsetToName =3D ValidationPolicy.Header.OffsetT=
oName + sizeof(CHAR16);=0D
+ CopyMem( (UINT8*)&ValidationPolicy + ValidationPolicy.Header.OffsetToNam=
e, TEST_VAR_1_NAME, sizeof(TEST_VAR_1_NAME) );=0D
+ UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), EFI=
_INVALID_PARAMETER );=0D
+=0D
+ // Reintialize without the state policy and try the same test.=0D
+ ValidationPolicy.Header.LockPolicyType =3D VARIABLE_POLICY_TYPE_NO_LOCK;=
=0D
+ UT_ASSERT_TRUE( InitExpVarPolicyStrings( &ValidationPolicy, TEST_VAR_1_N=
AME, NULL ) );=0D
+ ValidationPolicy.Header.Size =3D ValidationPolicy.Header.Size + sizeof(C=
HAR16);=0D
+ ValidationPolicy.Header.OffsetToName =3D ValidationPolicy.Header.OffsetT=
oName + sizeof(CHAR16);=0D
+ CopyMem( (UINT8*)&ValidationPolicy + ValidationPolicy.Header.OffsetToNam=
e, TEST_VAR_1_NAME, sizeof(TEST_VAR_1_NAME) );=0D
+ UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), EFI=
_INVALID_PARAMETER );=0D
+=0D
+ return UNIT_TEST_PASSED;=0D
+}=0D
+=0D
+/**=0D
+ Test Case=0D
+*/=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+RegisterShouldRejectInvalidNameCharacters (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ // EXPANDED_VARIABLE_POLICY_ENTRY ValidationPolicy =3D {=0D
+ // {=0D
+ // VARIABLE_POLICY_ENTRY_REVISION,=0D
+ // 0, // Will be populated by init helper.=0D
+ // 0, // Will be populated by init helper.=0D
+ // TEST_GUID_1,=0D
+ // TEST_POLICY_MIN_SIZE_NULL,=0D
+ // TEST_POLICY_MAX_SIZE_NULL,=0D
+ // TEST_POLICY_ATTRIBUTES_NULL,=0D
+ // TEST_POLICY_ATTRIBUTES_NULL,=0D
+ // VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE=0D
+ // },=0D
+ // {=0D
+ // TEST_GUID_2,=0D
+ // 1, // Value=0D
+ // 0 // Padding=0D
+ // },=0D
+ // L"",=0D
+ // L""=0D
+ // };=0D
+=0D
+ // Currently, there are no known invalid characters.=0D
+ // '#' in LockPolicy->Name are taken as literal.=0D
+=0D
+ return UNIT_TEST_PASSED;=0D
+}=0D
+=0D
+/**=0D
+ Test Case=0D
+*/=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+RegisterShouldRejectBadPolicyConstraints (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ SIMPLE_VARIABLE_POLICY_ENTRY ValidationPolicy =3D {=0D
+ {=0D
+ VARIABLE_POLICY_ENTRY_REVISION,=0D
+ sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME),=0D
+ sizeof(VARIABLE_POLICY_ENTRY),=0D
+ TEST_GUID_1,=0D
+ TEST_POLICY_MIN_SIZE_NULL,=0D
+ TEST_POLICY_MAX_SIZE_NULL,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ VARIABLE_POLICY_TYPE_NO_LOCK=0D
+ },=0D
+ TEST_VAR_1_NAME=0D
+ };=0D
+=0D
+ // Make sure that invalid MAXes are rejected.=0D
+ ValidationPolicy.Header.MaxSize =3D 0;=0D
+ UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), EFI=
_INVALID_PARAMETER );=0D
+=0D
+ return UNIT_TEST_PASSED;=0D
+}=0D
+=0D
+/**=0D
+ Test Case=0D
+*/=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+RegisterShouldRejectUnknownLockPolicies (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ SIMPLE_VARIABLE_POLICY_ENTRY ValidationPolicy =3D {=0D
+ {=0D
+ VARIABLE_POLICY_ENTRY_REVISION,=0D
+ sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME),=0D
+ sizeof(VARIABLE_POLICY_ENTRY),=0D
+ TEST_GUID_1,=0D
+ TEST_POLICY_MIN_SIZE_NULL,=0D
+ TEST_POLICY_MAX_SIZE_NULL,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ VARIABLE_POLICY_TYPE_NO_LOCK=0D
+ },=0D
+ TEST_VAR_1_NAME=0D
+ };=0D
+=0D
+ ValidationPolicy.Header.LockPolicyType =3D VARIABLE_POLICY_TYPE_LOCK_ON_=
VAR_STATE + 1;=0D
+ UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), EFI=
_INVALID_PARAMETER );=0D
+ ValidationPolicy.Header.LockPolicyType =3D VARIABLE_POLICY_TYPE_LOCK_ON_=
VAR_STATE + 1;=0D
+ UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), EFI=
_INVALID_PARAMETER );=0D
+=0D
+ return UNIT_TEST_PASSED;=0D
+}=0D
+=0D
+/**=0D
+ Test Case=0D
+*/=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+RegisterShouldRejectPolicesWithTooManyWildcards (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ SIMPLE_VARIABLE_POLICY_ENTRY ValidationPolicy =3D {=0D
+ {=0D
+ VARIABLE_POLICY_ENTRY_REVISION,=0D
+ sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_300_HASHES_STRING),=0D
+ sizeof(VARIABLE_POLICY_ENTRY),=0D
+ TEST_GUID_1,=0D
+ TEST_POLICY_MIN_SIZE_NULL,=0D
+ TEST_POLICY_MAX_SIZE_NULL,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ VARIABLE_POLICY_TYPE_NO_LOCK=0D
+ },=0D
+ TEST_300_HASHES_STRING=0D
+ };=0D
+=0D
+ // 300 Hashes is currently larger than the possible maximum match priori=
ty.=0D
+ UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), EFI=
_INVALID_PARAMETER );=0D
+=0D
+ return UNIT_TEST_PASSED;=0D
+}=0D
+=0D
+/**=0D
+ Test Case=0D
+*/=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+RegisterShouldRejectDuplicatePolicies (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ SIMPLE_VARIABLE_POLICY_ENTRY ValidationPolicy =3D {=0D
+ {=0D
+ VARIABLE_POLICY_ENTRY_REVISION,=0D
+ sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME),=0D
+ sizeof(VARIABLE_POLICY_ENTRY),=0D
+ TEST_GUID_1,=0D
+ TEST_POLICY_MIN_SIZE_NULL,=0D
+ TEST_POLICY_MAX_SIZE_NULL,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ VARIABLE_POLICY_TYPE_NO_LOCK=0D
+ },=0D
+ TEST_VAR_1_NAME=0D
+ };=0D
+=0D
+ UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Heade=
r ) );=0D
+ UT_ASSERT_STATUS_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header=
), EFI_ALREADY_STARTED );=0D
+=0D
+ return UNIT_TEST_PASSED;=0D
+}=0D
+=0D
+/**=0D
+ Test Case=0D
+*/=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+MinAndMaxSizePoliciesShouldBeHonored (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ SIMPLE_VARIABLE_POLICY_ENTRY ValidationPolicy =3D {=0D
+ {=0D
+ VARIABLE_POLICY_ENTRY_REVISION,=0D
+ sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME),=0D
+ sizeof(VARIABLE_POLICY_ENTRY),=0D
+ TEST_GUID_1,=0D
+ TEST_POLICY_MIN_SIZE_10,=0D
+ TEST_POLICY_MAX_SIZE_200,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ VARIABLE_POLICY_TYPE_NO_LOCK=0D
+ },=0D
+ TEST_VAR_1_NAME=0D
+ };=0D
+ EFI_STATUS PolicyCheck;=0D
+ UINT8 DummyData[TEST_POLICY_MAX_SIZE_200+1];=0D
+=0D
+=0D
+ // Without a policy, there should be no constraints on variable creation=
.=0D
+ PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,=0D
+ &mTestGuid1,=0D
+ VARIABLE_ATTRIBUTE_NV_BS,=0D
+ TEST_POLICY_MAX_SIZE_200+1,=0D
+ DummyData );=0D
+ UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );=0D
+=0D
+ // Set a policy to test against.=0D
+ UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Heade=
r ) );=0D
+=0D
+ // With a policy, make sure that sizes outsize the target range fail.=0D
+ PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,=0D
+ &mTestGuid1,=0D
+ VARIABLE_ATTRIBUTE_NV_BS,=0D
+ TEST_POLICY_MAX_SIZE_200+1,=0D
+ DummyData );=0D
+ UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) );=0D
+=0D
+ // With a policy, make sure that sizes outsize the target range fail.=0D
+ PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,=0D
+ &mTestGuid1,=0D
+ VARIABLE_ATTRIBUTE_NV_BS,=0D
+ TEST_POLICY_MIN_SIZE_10-1,=0D
+ DummyData );=0D
+ UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) );=0D
+=0D
+ // With a policy, make sure a valid variable is still valid.=0D
+ PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,=0D
+ &mTestGuid1,=0D
+ VARIABLE_ATTRIBUTE_NV_BS,=0D
+ TEST_POLICY_MIN_SIZE_10+1,=0D
+ DummyData );=0D
+ UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );=0D
+=0D
+ return UNIT_TEST_PASSED;=0D
+}=0D
+=0D
+/**=0D
+ Test Case=0D
+*/=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+AttributeMustPoliciesShouldBeHonored (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ SIMPLE_VARIABLE_POLICY_ENTRY ValidationPolicy =3D {=0D
+ {=0D
+ VARIABLE_POLICY_ENTRY_REVISION,=0D
+ sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME),=0D
+ sizeof(VARIABLE_POLICY_ENTRY),=0D
+ TEST_GUID_1,=0D
+ TEST_POLICY_MIN_SIZE_NULL,=0D
+ TEST_POLICY_MAX_SIZE_NULL,=0D
+ VARIABLE_ATTRIBUTE_NV_BS_RT,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ VARIABLE_POLICY_TYPE_NO_LOCK=0D
+ },=0D
+ TEST_VAR_1_NAME=0D
+ };=0D
+ EFI_STATUS PolicyCheck;=0D
+ UINT8 DummyData[12];=0D
+=0D
+=0D
+ // Without a policy, there should be no constraints on variable creation=
.=0D
+ PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,=0D
+ &mTestGuid1,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ sizeof(DummyData),=0D
+ DummyData );=0D
+ UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );=0D
+=0D
+ // Set a policy to test against.=0D
+ UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Heade=
r ) );=0D
+=0D
+ // With a policy, make sure that no attributes fail.=0D
+ PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,=0D
+ &mTestGuid1,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ sizeof(DummyData),=0D
+ DummyData );=0D
+ UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) );=0D
+=0D
+ // With a policy, make sure that some -- but not all -- attributes fail.=
=0D
+ PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,=0D
+ &mTestGuid1,=0D
+ VARIABLE_ATTRIBUTE_BS_RT_AT,=0D
+ sizeof(DummyData),=0D
+ DummyData );=0D
+ UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) );=0D
+=0D
+ // With a policy, make sure that all attributes pass.=0D
+ PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,=0D
+ &mTestGuid1,=0D
+ VARIABLE_ATTRIBUTE_NV_BS_RT,=0D
+ sizeof(DummyData),=0D
+ DummyData );=0D
+ UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );=0D
+=0D
+ // With a policy, make sure that all attributes -- plus some -- pass.=0D
+ PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,=0D
+ &mTestGuid1,=0D
+ VARIABLE_ATTRIBUTE_NV_BS_RT_AT,=0D
+ sizeof(DummyData),=0D
+ DummyData );=0D
+ UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );=0D
+=0D
+ return UNIT_TEST_PASSED;=0D
+}=0D
+=0D
+/**=0D
+ Test Case=0D
+*/=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+AttributeCantPoliciesShouldBeHonored (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ SIMPLE_VARIABLE_POLICY_ENTRY ValidationPolicy =3D {=0D
+ {=0D
+ VARIABLE_POLICY_ENTRY_REVISION,=0D
+ sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME),=0D
+ sizeof(VARIABLE_POLICY_ENTRY),=0D
+ TEST_GUID_1,=0D
+ TEST_POLICY_MIN_SIZE_NULL,=0D
+ TEST_POLICY_MAX_SIZE_NULL,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS,=0D
+ VARIABLE_POLICY_TYPE_NO_LOCK=0D
+ },=0D
+ TEST_VAR_1_NAME=0D
+ };=0D
+ EFI_STATUS PolicyCheck;=0D
+ UINT8 DummyData[12];=0D
+=0D
+=0D
+ // Without a policy, there should be no constraints on variable creation=
.=0D
+ PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,=0D
+ &mTestGuid1,=0D
+ VARIABLE_ATTRIBUTE_BS_RT_AT,=0D
+ sizeof(DummyData),=0D
+ DummyData );=0D
+ UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );=0D
+=0D
+ // Set a policy to test against.=0D
+ UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Heade=
r ) );=0D
+=0D
+ // With a policy, make sure that forbidden attributes fail.=0D
+ PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,=0D
+ &mTestGuid1,=0D
+ EFI_VARIABLE_TIME_BASED_AUTHENTICATED_=
WRITE_ACCESS,=0D
+ sizeof(DummyData),=0D
+ DummyData );=0D
+ UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) );=0D
+=0D
+ // With a policy, make sure that a mixture of attributes -- including th=
e forbidden -- fail.=0D
+ PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,=0D
+ &mTestGuid1,=0D
+ VARIABLE_ATTRIBUTE_BS_RT_AT,=0D
+ sizeof(DummyData),=0D
+ DummyData );=0D
+ UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) );=0D
+=0D
+ // With a policy, make sure that attributes without the forbidden pass.=
=0D
+ PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,=0D
+ &mTestGuid1,=0D
+ VARIABLE_ATTRIBUTE_NV_BS_RT,=0D
+ sizeof(DummyData),=0D
+ DummyData );=0D
+ UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );=0D
+=0D
+ return UNIT_TEST_PASSED;=0D
+}=0D
+=0D
+/**=0D
+ Test Case=0D
+*/=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+VariablesShouldBeDeletableRegardlessOfSize (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ SIMPLE_VARIABLE_POLICY_ENTRY ValidationPolicy =3D {=0D
+ {=0D
+ VARIABLE_POLICY_ENTRY_REVISION,=0D
+ sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME),=0D
+ sizeof(VARIABLE_POLICY_ENTRY),=0D
+ TEST_GUID_1,=0D
+ TEST_POLICY_MIN_SIZE_10,=0D
+ TEST_POLICY_MAX_SIZE_NULL,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS,=0D
+ VARIABLE_POLICY_TYPE_NO_LOCK=0D
+ },=0D
+ TEST_VAR_1_NAME=0D
+ };=0D
+ EFI_STATUS PolicyCheck;=0D
+ UINT8 DummyData[TEST_POLICY_MAX_SIZE_200+1];=0D
+=0D
+ // Create a policy enforcing a minimum variable size.=0D
+ UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Heade=
r ) );=0D
+=0D
+ // Make sure that a normal set would fail.=0D
+ PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,=0D
+ &mTestGuid1,=0D
+ VARIABLE_ATTRIBUTE_NV_BS,=0D
+ TEST_POLICY_MIN_SIZE_10-1,=0D
+ DummyData );=0D
+ UT_ASSERT_STATUS_EQUAL( PolicyCheck, EFI_INVALID_PARAMETER );=0D
+=0D
+ // Now make sure that a delete would succeed.=0D
+ PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,=0D
+ &mTestGuid1,=0D
+ VARIABLE_ATTRIBUTE_NV_BS,=0D
+ 0,=0D
+ NULL );=0D
+ UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );=0D
+=0D
+ return UNIT_TEST_PASSED;=0D
+}=0D
+=0D
+/**=0D
+ Test Case=0D
+*/=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+LockNowPoliciesShouldBeHonored (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ SIMPLE_VARIABLE_POLICY_ENTRY ValidationPolicy =3D {=0D
+ {=0D
+ VARIABLE_POLICY_ENTRY_REVISION,=0D
+ sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME),=0D
+ sizeof(VARIABLE_POLICY_ENTRY),=0D
+ TEST_GUID_1,=0D
+ TEST_POLICY_MIN_SIZE_NULL,=0D
+ TEST_POLICY_MAX_SIZE_NULL,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ VARIABLE_POLICY_TYPE_LOCK_NOW=0D
+ },=0D
+ TEST_VAR_1_NAME=0D
+ };=0D
+ EFI_STATUS PolicyCheck;=0D
+ UINT8 DummyData[12];=0D
+=0D
+=0D
+ // Without a policy, there should be no constraints on variable creation=
.=0D
+ PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,=0D
+ &mTestGuid1,=0D
+ VARIABLE_ATTRIBUTE_BS_RT_AT,=0D
+ sizeof(DummyData),=0D
+ DummyData );=0D
+ UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );=0D
+=0D
+ // Set a policy to test against.=0D
+ UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Heade=
r ) );=0D
+=0D
+ // With a policy, make sure that writes immediately fail.=0D
+ PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,=0D
+ &mTestGuid1,=0D
+ VARIABLE_ATTRIBUTE_BS_RT_AT,=0D
+ sizeof(DummyData),=0D
+ DummyData );=0D
+ UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) );=0D
+=0D
+ return UNIT_TEST_PASSED;=0D
+}=0D
+=0D
+/**=0D
+ Test Case=0D
+*/=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+LockOnCreatePoliciesShouldBeHonored (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ SIMPLE_VARIABLE_POLICY_ENTRY ValidationPolicy =3D {=0D
+ {=0D
+ VARIABLE_POLICY_ENTRY_REVISION,=0D
+ sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME),=0D
+ sizeof(VARIABLE_POLICY_ENTRY),=0D
+ TEST_GUID_1,=0D
+ TEST_POLICY_MIN_SIZE_NULL,=0D
+ TEST_POLICY_MAX_SIZE_NULL,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ VARIABLE_POLICY_TYPE_LOCK_ON_CREATE=0D
+ },=0D
+ TEST_VAR_1_NAME=0D
+ };=0D
+ EFI_STATUS PolicyCheck;=0D
+ UINT8 DummyData[12];=0D
+ UINTN ExpectedDataSize;=0D
+=0D
+=0D
+ // Without a policy, there should be no constraints on variable creation=
.=0D
+ PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,=0D
+ &mTestGuid1,=0D
+ VARIABLE_ATTRIBUTE_BS_RT_AT,=0D
+ sizeof(DummyData),=0D
+ DummyData );=0D
+ UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );=0D
+=0D
+ // Set a policy to test against.=0D
+ UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Heade=
r ) );=0D
+=0D
+ // Set consistent expectations on what the calls are looking for.=0D
+ expect_memory_count( StubGetVariableNull, VariableName, TEST_VAR_1_NAME,=
sizeof(TEST_VAR_1_NAME), 2 );=0D
+ expect_memory_count( StubGetVariableNull, VendorGuid, &mTestGuid1, sizeo=
f(mTestGuid1), 2 );=0D
+ ExpectedDataSize =3D 0;=0D
+ expect_memory_count( StubGetVariableNull, DataSize, &ExpectedDataSize, s=
izeof(ExpectedDataSize), 2 );=0D
+=0D
+ // With a policy, make sure that writes still work, since the variable d=
oesn't exist.=0D
+ will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL ); // A=
ttributes=0D
+ will_return( StubGetVariableNull, 0 ); // S=
ize=0D
+ will_return( StubGetVariableNull, NULL ); // D=
ataPtr=0D
+ will_return( StubGetVariableNull, EFI_NOT_FOUND ); // S=
tatus=0D
+ PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,=0D
+ &mTestGuid1,=0D
+ VARIABLE_ATTRIBUTE_BS_RT_AT,=0D
+ sizeof(DummyData),=0D
+ DummyData );=0D
+ UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );=0D
+=0D
+ // With a policy, make sure that a call with an "existing" variable fail=
s.=0D
+ will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL ); // A=
ttributes=0D
+ will_return( StubGetVariableNull, 10 ); // S=
ize=0D
+ will_return( StubGetVariableNull, NULL ); // D=
ataPtr=0D
+ will_return( StubGetVariableNull, EFI_BUFFER_TOO_SMALL ); // S=
tatus=0D
+ PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,=0D
+ &mTestGuid1,=0D
+ VARIABLE_ATTRIBUTE_BS_RT_AT,=0D
+ sizeof(DummyData),=0D
+ DummyData );=0D
+ UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) );=0D
+=0D
+ return UNIT_TEST_PASSED;=0D
+}=0D
+=0D
+/**=0D
+ Test Case=0D
+*/=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+LockOnStatePoliciesShouldBeHonored (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ EXPANDED_VARIABLE_POLICY_ENTRY ValidationPolicy =3D {=0D
+ {=0D
+ VARIABLE_POLICY_ENTRY_REVISION,=0D
+ 0, // Will be populated by init helper.=0D
+ 0, // Will be populated by init helper.=0D
+ TEST_GUID_1,=0D
+ TEST_POLICY_MIN_SIZE_NULL,=0D
+ TEST_POLICY_MAX_SIZE_NULL,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE=0D
+ },=0D
+ {=0D
+ TEST_GUID_2,=0D
+ 20, // Value=0D
+ 0 // Padding=0D
+ },=0D
+ L"",=0D
+ L""=0D
+ };=0D
+ EFI_STATUS PolicyCheck;=0D
+ UINT8 DummyData[12];=0D
+ UINT8 ValidationStateVar;=0D
+ UINTN ExpectedDataSize;=0D
+ UT_ASSERT_TRUE( InitExpVarPolicyStrings( &ValidationPolicy, TEST_VAR_1_N=
AME, TEST_VAR_2_NAME ) );=0D
+=0D
+=0D
+ // Without a policy, there should be no constraints on variable creation=
.=0D
+ PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,=0D
+ &mTestGuid1,=0D
+ VARIABLE_ATTRIBUTE_BS_RT_AT,=0D
+ sizeof(DummyData),=0D
+ DummyData );=0D
+ UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );=0D
+=0D
+ // Set a policy to test against.=0D
+ UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Heade=
r ) );=0D
+=0D
+ // Set consistent expectations on what the calls are looking for.=0D
+ expect_memory_count( StubGetVariableNull, VariableName, TEST_VAR_2_NAME,=
sizeof(TEST_VAR_2_NAME), 5 );=0D
+ expect_memory_count( StubGetVariableNull, VendorGuid, &mTestGuid2, sizeo=
f(mTestGuid2), 5 );=0D
+ ExpectedDataSize =3D 1;=0D
+ expect_memory_count( StubGetVariableNull, DataSize, &ExpectedDataSize, s=
izeof(ExpectedDataSize), 5 );=0D
+=0D
+ // With a policy, make sure that writes still work, since the variable d=
oesn't exist.=0D
+ will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL ); // A=
ttributes=0D
+ will_return( StubGetVariableNull, 0 ); // S=
ize=0D
+ will_return( StubGetVariableNull, NULL ); // D=
ataPtr=0D
+ will_return( StubGetVariableNull, EFI_NOT_FOUND ); // S=
tatus=0D
+ PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,=0D
+ &mTestGuid1,=0D
+ VARIABLE_ATTRIBUTE_BS_RT_AT,=0D
+ sizeof(DummyData),=0D
+ DummyData );=0D
+ UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );=0D
+=0D
+ // With a policy, make sure that a state variable that's too large doesn=
't lock the variable.=0D
+ will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL ); // A=
ttributes=0D
+ will_return( StubGetVariableNull, 10 ); // S=
ize=0D
+ will_return( StubGetVariableNull, NULL ); // D=
ataPtr=0D
+ will_return( StubGetVariableNull, EFI_BUFFER_TOO_SMALL ); // S=
tatus=0D
+ PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,=0D
+ &mTestGuid1,=0D
+ VARIABLE_ATTRIBUTE_BS_RT_AT,=0D
+ sizeof(DummyData),=0D
+ DummyData );=0D
+ UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );=0D
+=0D
+ // With a policy, check a state variable with the wrong value.=0D
+ ValidationStateVar =3D 0;=0D
+ will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL ); // A=
ttributes=0D
+ will_return( StubGetVariableNull, sizeof(ValidationStateVar) ); // S=
ize=0D
+ will_return( StubGetVariableNull, &ValidationStateVar ); // D=
ataPtr=0D
+ will_return( StubGetVariableNull, EFI_SUCCESS ); // S=
tatus=0D
+ PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,=0D
+ &mTestGuid1,=0D
+ VARIABLE_ATTRIBUTE_BS_RT_AT,=0D
+ sizeof(DummyData),=0D
+ DummyData );=0D
+ UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );=0D
+=0D
+ // With a policy, check a state variable with another wrong value.=0D
+ ValidationStateVar =3D 10;=0D
+ will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL ); // A=
ttributes=0D
+ will_return( StubGetVariableNull, sizeof(ValidationStateVar) ); // S=
ize=0D
+ will_return( StubGetVariableNull, &ValidationStateVar ); // D=
ataPtr=0D
+ will_return( StubGetVariableNull, EFI_SUCCESS ); // S=
tatus=0D
+ PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,=0D
+ &mTestGuid1,=0D
+ VARIABLE_ATTRIBUTE_BS_RT_AT,=0D
+ sizeof(DummyData),=0D
+ DummyData );=0D
+ UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );=0D
+=0D
+ // With a policy, make sure that a call with a correct state variable fa=
ils.=0D
+ ValidationStateVar =3D 20;=0D
+ will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL ); // A=
ttributes=0D
+ will_return( StubGetVariableNull, sizeof(ValidationStateVar) ); // S=
ize=0D
+ will_return( StubGetVariableNull, &ValidationStateVar ); // D=
ataPtr=0D
+ will_return( StubGetVariableNull, EFI_SUCCESS ); // S=
tatus=0D
+ PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,=0D
+ &mTestGuid1,=0D
+ VARIABLE_ATTRIBUTE_BS_RT_AT,=0D
+ sizeof(DummyData),=0D
+ DummyData );=0D
+ UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) );=0D
+=0D
+ return UNIT_TEST_PASSED;=0D
+}=0D
+=0D
+/**=0D
+ Test Case=0D
+*/=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+LockOnStatePoliciesShouldApplyToNamespaces (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ EXPANDED_VARIABLE_POLICY_ENTRY ValidationPolicy =3D {=0D
+ {=0D
+ VARIABLE_POLICY_ENTRY_REVISION,=0D
+ 0, // Will be populated by init helper.=0D
+ 0, // Will be populated by init helper.=0D
+ TEST_GUID_1,=0D
+ TEST_POLICY_MIN_SIZE_NULL,=0D
+ TEST_POLICY_MAX_SIZE_NULL,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE=0D
+ },=0D
+ {=0D
+ TEST_GUID_2,=0D
+ 20, // Value=0D
+ 0 // Padding=0D
+ },=0D
+ L"",=0D
+ L""=0D
+ };=0D
+ EFI_STATUS PolicyCheck;=0D
+ UINT8 DummyData[12];=0D
+ UINT8 ValidationStateVar;=0D
+ UINTN ExpectedDataSize;=0D
+ UT_ASSERT_TRUE( InitExpVarPolicyStrings( &ValidationPolicy, NULL, TEST_V=
AR_2_NAME ) );=0D
+=0D
+=0D
+ // Without a policy, there should be no constraints on variable creation=
.=0D
+ PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,=0D
+ &mTestGuid1,=0D
+ VARIABLE_ATTRIBUTE_BS_RT_AT,=0D
+ sizeof(DummyData),=0D
+ DummyData );=0D
+ UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );=0D
+ PolicyCheck =3D ValidateSetVariable( TEST_VAR_3_NAME,=0D
+ &mTestGuid1,=0D
+ VARIABLE_ATTRIBUTE_BS_RT_AT,=0D
+ sizeof(DummyData),=0D
+ DummyData );=0D
+ UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );=0D
+=0D
+ // Set a policy to test against.=0D
+ UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Heade=
r ) );=0D
+=0D
+ // Set consistent expectations on what the calls are looking for.=0D
+ expect_memory_count( StubGetVariableNull, VariableName, TEST_VAR_2_NAME,=
sizeof(TEST_VAR_2_NAME), 4 );=0D
+ expect_memory_count( StubGetVariableNull, VendorGuid, &mTestGuid2, sizeo=
f(mTestGuid2), 4 );=0D
+ ExpectedDataSize =3D 1;=0D
+ expect_memory_count( StubGetVariableNull, DataSize, &ExpectedDataSize, s=
izeof(ExpectedDataSize), 4 );=0D
+=0D
+ // With a policy, make sure that writes still work, since the variable d=
oesn't exist.=0D
+ will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL ); // A=
ttributes=0D
+ will_return( StubGetVariableNull, 0 ); // S=
ize=0D
+ will_return( StubGetVariableNull, NULL ); // D=
ataPtr=0D
+ will_return( StubGetVariableNull, EFI_NOT_FOUND ); // S=
tatus=0D
+ PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,=0D
+ &mTestGuid1,=0D
+ VARIABLE_ATTRIBUTE_BS_RT_AT,=0D
+ sizeof(DummyData),=0D
+ DummyData );=0D
+ UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );=0D
+ will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL ); // A=
ttributes=0D
+ will_return( StubGetVariableNull, 0 ); // S=
ize=0D
+ will_return( StubGetVariableNull, NULL ); // D=
ataPtr=0D
+ will_return( StubGetVariableNull, EFI_NOT_FOUND ); // S=
tatus=0D
+ PolicyCheck =3D ValidateSetVariable( TEST_VAR_3_NAME,=0D
+ &mTestGuid1,=0D
+ VARIABLE_ATTRIBUTE_BS_RT_AT,=0D
+ sizeof(DummyData),=0D
+ DummyData );=0D
+ UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );=0D
+=0D
+ // With a policy, make sure that a call with a correct state variable fa=
ils.=0D
+ ValidationStateVar =3D 20;=0D
+ will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL ); // A=
ttributes=0D
+ will_return( StubGetVariableNull, sizeof(ValidationStateVar) ); // S=
ize=0D
+ will_return( StubGetVariableNull, &ValidationStateVar ); // D=
ataPtr=0D
+ will_return( StubGetVariableNull, EFI_SUCCESS ); // S=
tatus=0D
+ PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,=0D
+ &mTestGuid1,=0D
+ VARIABLE_ATTRIBUTE_BS_RT_AT,=0D
+ sizeof(DummyData),=0D
+ DummyData );=0D
+ UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) );=0D
+ will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL ); // A=
ttributes=0D
+ will_return( StubGetVariableNull, sizeof(ValidationStateVar) ); // S=
ize=0D
+ will_return( StubGetVariableNull, &ValidationStateVar ); // D=
ataPtr=0D
+ will_return( StubGetVariableNull, EFI_SUCCESS ); // S=
tatus=0D
+ PolicyCheck =3D ValidateSetVariable( TEST_VAR_3_NAME,=0D
+ &mTestGuid1,=0D
+ VARIABLE_ATTRIBUTE_BS_RT_AT,=0D
+ sizeof(DummyData),=0D
+ DummyData );=0D
+ UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) );=0D
+=0D
+ return UNIT_TEST_PASSED;=0D
+}=0D
+=0D
+/**=0D
+ Test Case=0D
+*/=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+LockOnStateShouldHandleErrorsGracefully (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ EXPANDED_VARIABLE_POLICY_ENTRY ValidationPolicy =3D {=0D
+ {=0D
+ VARIABLE_POLICY_ENTRY_REVISION,=0D
+ 0, // Will be populated by init helper.=0D
+ 0, // Will be populated by init helper.=0D
+ TEST_GUID_1,=0D
+ TEST_POLICY_MIN_SIZE_NULL,=0D
+ TEST_POLICY_MAX_SIZE_NULL,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE=0D
+ },=0D
+ {=0D
+ TEST_GUID_2,=0D
+ 20, // Value=0D
+ 0 // Padding=0D
+ },=0D
+ L"",=0D
+ L""=0D
+ };=0D
+ EFI_STATUS PolicyCheck;=0D
+ UINT8 DummyData[12];=0D
+ UT_ASSERT_TRUE( InitExpVarPolicyStrings( &ValidationPolicy, TEST_VAR_1_N=
AME, TEST_VAR_2_NAME ) );=0D
+=0D
+=0D
+ // Without a policy, there should be no constraints on variable creation=
.=0D
+ PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,=0D
+ &mTestGuid1,=0D
+ VARIABLE_ATTRIBUTE_BS_RT_AT,=0D
+ sizeof(DummyData),=0D
+ DummyData );=0D
+ UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );=0D
+=0D
+ // Set a policy to test against.=0D
+ UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Heade=
r ) );=0D
+=0D
+ // Configure the stub to not care about parameters. We're testing errors=
.=0D
+ expect_any_always( StubGetVariableNull, VariableName );=0D
+ expect_any_always( StubGetVariableNull, VendorGuid );=0D
+ expect_any_always( StubGetVariableNull, DataSize );=0D
+=0D
+ // With a policy, make sure that writes still work, since the variable d=
oesn't exist.=0D
+ will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL ); // A=
ttributes=0D
+ will_return( StubGetVariableNull, 0 ); // S=
ize=0D
+ will_return( StubGetVariableNull, NULL ); // D=
ataPtr=0D
+ will_return( StubGetVariableNull, EFI_NOT_FOUND ); // S=
tatus=0D
+ PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,=0D
+ &mTestGuid1,=0D
+ VARIABLE_ATTRIBUTE_BS_RT_AT,=0D
+ sizeof(DummyData),=0D
+ DummyData );=0D
+ UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );=0D
+=0D
+ // Verify that state variables that are the wrong size won't lock the va=
riable.=0D
+ will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL ); // A=
ttributes=0D
+ will_return( StubGetVariableNull, 0 ); // S=
ize=0D
+ will_return( StubGetVariableNull, NULL ); // D=
ataPtr=0D
+ will_return( StubGetVariableNull, EFI_BUFFER_TOO_SMALL ); // S=
tatus=0D
+ PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,=0D
+ &mTestGuid1,=0D
+ VARIABLE_ATTRIBUTE_BS_RT_AT,=0D
+ sizeof(DummyData),=0D
+ DummyData );=0D
+ UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );=0D
+=0D
+ // Verify that unexpected errors default to locked.=0D
+ will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL ); // A=
ttributes=0D
+ will_return( StubGetVariableNull, 0 ); // S=
ize=0D
+ will_return( StubGetVariableNull, NULL ); // D=
ataPtr=0D
+ will_return( StubGetVariableNull, EFI_UNSUPPORTED ); // S=
tatus=0D
+ PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,=0D
+ &mTestGuid1,=0D
+ VARIABLE_ATTRIBUTE_BS_RT_AT,=0D
+ sizeof(DummyData),=0D
+ DummyData );=0D
+ UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) );=0D
+=0D
+ will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL ); // A=
ttributes=0D
+ will_return( StubGetVariableNull, 0 ); // S=
ize=0D
+ will_return( StubGetVariableNull, NULL ); // D=
ataPtr=0D
+ will_return( StubGetVariableNull, EFI_NOT_READY ); // S=
tatus=0D
+ PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,=0D
+ &mTestGuid1,=0D
+ VARIABLE_ATTRIBUTE_BS_RT_AT,=0D
+ sizeof(DummyData),=0D
+ DummyData );=0D
+ UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) );=0D
+=0D
+ return UNIT_TEST_PASSED;=0D
+}=0D
+=0D
+/**=0D
+ Test Case=0D
+*/=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+BestMatchPriorityShouldBeObeyed (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ SIMPLE_VARIABLE_POLICY_ENTRY ValidationPolicy =3D {=0D
+ {=0D
+ VARIABLE_POLICY_ENTRY_REVISION,=0D
+ sizeof(VARIABLE_POLICY_ENTRY) + sizeof(L"Wild12Card34Placeholder"),=
=0D
+ sizeof(VARIABLE_POLICY_ENTRY),=0D
+ TEST_GUID_1,=0D
+ TEST_POLICY_MIN_SIZE_NULL,=0D
+ TEST_POLICY_MAX_SIZE_NULL,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ VARIABLE_POLICY_TYPE_NO_LOCK=0D
+ },=0D
+ L"Wild12Card34Placeholder"=0D
+ };=0D
+ EFI_STATUS PolicyCheck;=0D
+ UINT8 DummyData[70];=0D
+ CHAR16 *PolicyName =3D (CHAR16*)((UINT8*)&ValidationPolicy + sizeof=
(VARIABLE_POLICY_ENTRY));=0D
+ UINTN PolicyNameSize =3D sizeof(L"Wild12Card34Placeholder");=0D
+ CHAR16 *FourWildcards =3D L"Wild##Card##Placeholder";=0D
+ CHAR16 *ThreeWildcards =3D L"Wild##Card#4Placeholder";=0D
+ CHAR16 *TwoWildcards =3D L"Wild##Card34Placeholder";=0D
+ CHAR16 *OneWildcard =3D L"Wild#2Card34Placeholder";=0D
+ CHAR16 *NoWildcards =3D L"Wild12Card34Placeholder";=0D
+=0D
+ // Create all of the policies from least restrictive to most restrictive=
.=0D
+ // NoWildcards should be the most restrictive.=0D
+ ValidationPolicy.Header.MaxSize =3D 60;=0D
+ ValidationPolicy.Header.Size =3D ValidationPolicy.Header.OffsetToName;=0D
+ UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Heade=
r ) );=0D
+ ValidationPolicy.Header.Size +=3D (UINT16)PolicyNameSize;=0D
+ ValidationPolicy.Header.MaxSize =3D 50;=0D
+ CopyMem( PolicyName, FourWildcards, PolicyNameSize );=0D
+ UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Heade=
r ) );=0D
+ ValidationPolicy.Header.MaxSize =3D 40;=0D
+ CopyMem( PolicyName, ThreeWildcards, PolicyNameSize );=0D
+ UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Heade=
r ) );=0D
+ ValidationPolicy.Header.MaxSize =3D 30;=0D
+ CopyMem( PolicyName, TwoWildcards, PolicyNameSize );=0D
+ UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Heade=
r ) );=0D
+ ValidationPolicy.Header.MaxSize =3D 20;=0D
+ CopyMem( PolicyName, OneWildcard, PolicyNameSize );=0D
+ UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Heade=
r ) );=0D
+ ValidationPolicy.Header.MaxSize =3D 10;=0D
+ CopyMem( PolicyName, NoWildcards, PolicyNameSize );=0D
+ UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Heade=
r ) );=0D
+=0D
+ // Verify that variables only matching the namespace have the most flexi=
ble policy.=0D
+ PolicyCheck =3D ValidateSetVariable( L"ArbitraryName",=0D
+ &mTestGuid1,=0D
+ VARIABLE_ATTRIBUTE_BS_RT_AT,=0D
+ 65,=0D
+ DummyData );=0D
+ UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) );=0D
+ PolicyCheck =3D ValidateSetVariable( L"ArbitraryName",=0D
+ &mTestGuid1,=0D
+ VARIABLE_ATTRIBUTE_BS_RT_AT,=0D
+ 55,=0D
+ DummyData );=0D
+ UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );=0D
+=0D
+ // Verify that variables matching increasing characters get increasing p=
olicy restrictions.=0D
+ PolicyCheck =3D ValidateSetVariable( L"Wild77Card77Placeholder",=0D
+ &mTestGuid1,=0D
+ VARIABLE_ATTRIBUTE_BS_RT_AT,=0D
+ 55,=0D
+ DummyData );=0D
+ UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) );=0D
+ PolicyCheck =3D ValidateSetVariable( L"Wild77Card77Placeholder",=0D
+ &mTestGuid1,=0D
+ VARIABLE_ATTRIBUTE_BS_RT_AT,=0D
+ 45,=0D
+ DummyData );=0D
+ UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );=0D
+=0D
+ PolicyCheck =3D ValidateSetVariable( L"Wild77Card74Placeholder",=0D
+ &mTestGuid1,=0D
+ VARIABLE_ATTRIBUTE_BS_RT_AT,=0D
+ 45,=0D
+ DummyData );=0D
+ UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) );=0D
+ PolicyCheck =3D ValidateSetVariable( L"Wild77Card74Placeholder",=0D
+ &mTestGuid1,=0D
+ VARIABLE_ATTRIBUTE_BS_RT_AT,=0D
+ 35,=0D
+ DummyData );=0D
+ UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );=0D
+=0D
+ PolicyCheck =3D ValidateSetVariable( L"Wild77Card34Placeholder",=0D
+ &mTestGuid1,=0D
+ VARIABLE_ATTRIBUTE_BS_RT_AT,=0D
+ 35,=0D
+ DummyData );=0D
+ UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) );=0D
+ PolicyCheck =3D ValidateSetVariable( L"Wild77Card34Placeholder",=0D
+ &mTestGuid1,=0D
+ VARIABLE_ATTRIBUTE_BS_RT_AT,=0D
+ 25,=0D
+ DummyData );=0D
+ UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );=0D
+=0D
+ PolicyCheck =3D ValidateSetVariable( L"Wild72Card34Placeholder",=0D
+ &mTestGuid1,=0D
+ VARIABLE_ATTRIBUTE_BS_RT_AT,=0D
+ 25,=0D
+ DummyData );=0D
+ UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) );=0D
+ PolicyCheck =3D ValidateSetVariable( L"Wild72Card34Placeholder",=0D
+ &mTestGuid1,=0D
+ VARIABLE_ATTRIBUTE_BS_RT_AT,=0D
+ 15,=0D
+ DummyData );=0D
+ UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );=0D
+=0D
+ PolicyCheck =3D ValidateSetVariable( L"Wild12Card34Placeholder",=0D
+ &mTestGuid1,=0D
+ VARIABLE_ATTRIBUTE_BS_RT_AT,=0D
+ 15,=0D
+ DummyData );=0D
+ UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) );=0D
+ PolicyCheck =3D ValidateSetVariable( L"Wild12Card34Placeholder",=0D
+ &mTestGuid1,=0D
+ VARIABLE_ATTRIBUTE_BS_RT_AT,=0D
+ 5,=0D
+ DummyData );=0D
+ UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );=0D
+=0D
+ return UNIT_TEST_PASSED;=0D
+}=0D
+=0D
+=0D
+///=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=0D
+=0D
+/**=0D
+ Test Case=0D
+*/=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+ShouldBeAbleToLockInterface (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ SIMPLE_VARIABLE_POLICY_ENTRY TestPolicy =3D {=0D
+ {=0D
+ VARIABLE_POLICY_ENTRY_REVISION,=0D
+ sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME),=0D
+ sizeof(VARIABLE_POLICY_ENTRY),=0D
+ TEST_GUID_1,=0D
+ TEST_POLICY_MIN_SIZE_NULL,=0D
+ TEST_POLICY_MAX_SIZE_NULL,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ VARIABLE_POLICY_TYPE_NO_LOCK=0D
+ },=0D
+ TEST_VAR_1_NAME=0D
+ };=0D
+=0D
+ // Make sure it's not already locked.=0D
+ UT_ASSERT_FALSE( IsVariablePolicyInterfaceLocked() );=0D
+ // Lock it.=0D
+ UT_ASSERT_NOT_EFI_ERROR( LockVariablePolicy() );=0D
+ // Verify that it's locked.=0D
+ UT_ASSERT_TRUE( IsVariablePolicyInterfaceLocked() );=0D
+=0D
+ // Verify that all state-changing commands fail.=0D
+ UT_ASSERT_TRUE( EFI_ERROR( LockVariablePolicy() ) );=0D
+ UT_ASSERT_TRUE( EFI_ERROR( DisableVariablePolicy() ) );=0D
+ UT_ASSERT_TRUE( EFI_ERROR( RegisterVariablePolicy( &TestPolicy.Header ) =
) );=0D
+=0D
+ return UNIT_TEST_PASSED;=0D
+}=0D
+=0D
+/**=0D
+ Test Case=0D
+*/=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+ShouldBeAbleToDisablePolicyEnforcement (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ SIMPLE_VARIABLE_POLICY_ENTRY TestPolicy =3D {=0D
+ {=0D
+ VARIABLE_POLICY_ENTRY_REVISION,=0D
+ sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME),=0D
+ sizeof(VARIABLE_POLICY_ENTRY),=0D
+ TEST_GUID_1,=0D
+ TEST_POLICY_MIN_SIZE_10,=0D
+ TEST_POLICY_MAX_SIZE_200,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ VARIABLE_POLICY_TYPE_NO_LOCK=0D
+ },=0D
+ TEST_VAR_1_NAME=0D
+ };=0D
+ EFI_STATUS PolicyCheck;=0D
+ UINT8 DummyData[TEST_POLICY_MIN_SIZE_10-1];=0D
+=0D
+ // Make sure that the policy enforcement is currently enabled.=0D
+ UT_ASSERT_TRUE( IsVariablePolicyEnabled() );=0D
+ // Add a policy before it's disabled.=0D
+ UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &TestPolicy.Header ) );=
=0D
+ // Disable the policy enforcement.=0D
+ UT_ASSERT_NOT_EFI_ERROR( DisableVariablePolicy() );=0D
+ // Make sure that the policy enforcement is currently disabled.=0D
+ UT_ASSERT_FALSE( IsVariablePolicyEnabled() );=0D
+=0D
+ // Check to make sure that a policy violation still passes.=0D
+ PolicyCheck =3D ValidateSetVariable( TEST_VAR_1_NAME,=0D
+ &mTestGuid1,=0D
+ VARIABLE_ATTRIBUTE_NV_BS,=0D
+ sizeof(DummyData),=0D
+ DummyData );=0D
+ UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );=0D
+=0D
+ return UNIT_TEST_PASSED;=0D
+}=0D
+=0D
+/**=0D
+ Test Case=0D
+*/=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+ShouldNotBeAbleToDisablePoliciesTwice (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ // Make sure that the policy enforcement is currently enabled.=0D
+ UT_ASSERT_TRUE( IsVariablePolicyEnabled() );=0D
+ // Disable the policy enforcement.=0D
+ UT_ASSERT_NOT_EFI_ERROR( DisableVariablePolicy() );=0D
+ // Make sure that the policy enforcement is currently disabled.=0D
+ UT_ASSERT_FALSE( IsVariablePolicyEnabled() );=0D
+ // Try to disable again and verify failure.=0D
+ UT_ASSERT_TRUE( EFI_ERROR( DisableVariablePolicy() ) );=0D
+=0D
+ return UNIT_TEST_PASSED;=0D
+}=0D
+=0D
+/**=0D
+ Test Case=0D
+*/=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+ShouldBeAbleToAddNewPoliciesAfterDisabled (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ SIMPLE_VARIABLE_POLICY_ENTRY TestPolicy =3D {=0D
+ {=0D
+ VARIABLE_POLICY_ENTRY_REVISION,=0D
+ sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME),=0D
+ sizeof(VARIABLE_POLICY_ENTRY),=0D
+ TEST_GUID_1,=0D
+ TEST_POLICY_MIN_SIZE_10,=0D
+ TEST_POLICY_MAX_SIZE_200,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ VARIABLE_POLICY_TYPE_NO_LOCK=0D
+ },=0D
+ TEST_VAR_1_NAME=0D
+ };=0D
+ EFI_STATUS PolicyCheck;=0D
+=0D
+ // Make sure that the policy enforcement is currently enabled.=0D
+ UT_ASSERT_TRUE( IsVariablePolicyEnabled() );=0D
+ // Disable the policy enforcement.=0D
+ UT_ASSERT_NOT_EFI_ERROR( DisableVariablePolicy() );=0D
+=0D
+ // Make sure that new policy creation still works, it just won't be enfo=
rced.=0D
+ PolicyCheck =3D RegisterVariablePolicy( &TestPolicy.Header );=0D
+ UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );=0D
+=0D
+ return UNIT_TEST_PASSED;=0D
+}=0D
+=0D
+/**=0D
+ Test Case=0D
+*/=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+ShouldBeAbleToLockAfterDisabled (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ // Make sure that the policy enforcement is currently enabled.=0D
+ UT_ASSERT_TRUE( IsVariablePolicyEnabled() );=0D
+ // Disable the policy enforcement.=0D
+ UT_ASSERT_NOT_EFI_ERROR( DisableVariablePolicy() );=0D
+=0D
+ // Make sure that we can lock in this state.=0D
+ UT_ASSERT_FALSE( IsVariablePolicyInterfaceLocked() );=0D
+ UT_ASSERT_NOT_EFI_ERROR( LockVariablePolicy() );=0D
+ UT_ASSERT_TRUE( IsVariablePolicyInterfaceLocked() );=0D
+=0D
+ return UNIT_TEST_PASSED;=0D
+}=0D
+=0D
+/**=0D
+ Test Case=0D
+*/=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+ShouldBeAbleToDumpThePolicyTable (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ SIMPLE_VARIABLE_POLICY_ENTRY TestPolicy =3D {=0D
+ {=0D
+ VARIABLE_POLICY_ENTRY_REVISION,=0D
+ sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME),=0D
+ sizeof(VARIABLE_POLICY_ENTRY),=0D
+ TEST_GUID_1,=0D
+ TEST_POLICY_MIN_SIZE_10,=0D
+ TEST_POLICY_MAX_SIZE_200,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ VARIABLE_POLICY_TYPE_NO_LOCK=0D
+ },=0D
+ TEST_VAR_1_NAME=0D
+ };=0D
+ EFI_STATUS PolicyCheck;=0D
+ UINT32 DumpSize;=0D
+ UINT32 BufferSize;=0D
+ VOID *DumpBuffer;=0D
+=0D
+ // For good measure, test some parameter validation.=0D
+ UT_ASSERT_STATUS_EQUAL( DumpVariablePolicy( NULL, NULL ), EFI_INVALID_PA=
RAMETER );=0D
+ DumpSize =3D 10;=0D
+ UT_ASSERT_STATUS_EQUAL( DumpVariablePolicy( NULL, &DumpSize ), EFI_INVAL=
ID_PARAMETER );=0D
+=0D
+ // Now for the actual test case.=0D
+=0D
+ // Allocate a buffer to hold the output.=0D
+ BufferSize =3D sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME);=
=0D
+ DumpBuffer =3D AllocatePool( BufferSize );=0D
+ UT_ASSERT_NOT_EQUAL( DumpBuffer, NULL );=0D
+=0D
+ // Verify that the current table size is 0.=0D
+ DumpSize =3D BufferSize;=0D
+ UT_ASSERT_NOT_EFI_ERROR( DumpVariablePolicy( DumpBuffer, &DumpSize ) );=
=0D
+ UT_ASSERT_EQUAL( DumpSize, 0 );=0D
+=0D
+ // Now, set a new policy.=0D
+ UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &TestPolicy.Header ) );=
=0D
+=0D
+ // Make sure that the new return is non-zero and fails as expected.=0D
+ DumpSize =3D 0;=0D
+ PolicyCheck =3D DumpVariablePolicy( NULL, &DumpSize );=0D
+ UT_ASSERT_STATUS_EQUAL( PolicyCheck, EFI_BUFFER_TOO_SMALL );=0D
+ UT_ASSERT_EQUAL( DumpSize, BufferSize );=0D
+=0D
+ // Now verify that we can fetch the dump.=0D
+ DumpSize =3D BufferSize;=0D
+ UT_ASSERT_NOT_EFI_ERROR( DumpVariablePolicy( DumpBuffer, &DumpSize ) );=
=0D
+ UT_ASSERT_EQUAL( DumpSize, BufferSize );=0D
+ UT_ASSERT_MEM_EQUAL( &TestPolicy, DumpBuffer, BufferSize );=0D
+=0D
+ // Always put away your toys.=0D
+ FreePool( DumpBuffer );=0D
+=0D
+ return UNIT_TEST_PASSED;=0D
+}=0D
+=0D
+/**=0D
+ Test Case=0D
+*/=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+ShouldBeAbleToDumpThePolicyTableAfterDisabled (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ SIMPLE_VARIABLE_POLICY_ENTRY TestPolicy =3D {=0D
+ {=0D
+ VARIABLE_POLICY_ENTRY_REVISION,=0D
+ sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME),=0D
+ sizeof(VARIABLE_POLICY_ENTRY),=0D
+ TEST_GUID_1,=0D
+ TEST_POLICY_MIN_SIZE_10,=0D
+ TEST_POLICY_MAX_SIZE_200,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ VARIABLE_POLICY_TYPE_NO_LOCK=0D
+ },=0D
+ TEST_VAR_1_NAME=0D
+ };=0D
+ SIMPLE_VARIABLE_POLICY_ENTRY TestPolicy2 =3D {=0D
+ {=0D
+ VARIABLE_POLICY_ENTRY_REVISION,=0D
+ sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_2_NAME),=0D
+ sizeof(VARIABLE_POLICY_ENTRY),=0D
+ TEST_GUID_2,=0D
+ TEST_POLICY_MIN_SIZE_10,=0D
+ TEST_POLICY_MAX_SIZE_200,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ TEST_POLICY_ATTRIBUTES_NULL,=0D
+ VARIABLE_POLICY_TYPE_NO_LOCK=0D
+ },=0D
+ TEST_VAR_2_NAME=0D
+ };=0D
+ EFI_STATUS PolicyCheck;=0D
+ UINT32 DumpSize;=0D
+ VOID *DumpBuffer;=0D
+=0D
+ DumpBuffer =3D NULL;=0D
+ DumpSize =3D 0;=0D
+=0D
+ // Register a new policy.=0D
+ UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &TestPolicy.Header ) );=
=0D
+ // Make sure that we can dump the policy.=0D
+ PolicyCheck =3D DumpVariablePolicy( DumpBuffer, &DumpSize );=0D
+ UT_ASSERT_STATUS_EQUAL( PolicyCheck, EFI_BUFFER_TOO_SMALL );=0D
+ DumpBuffer =3D AllocatePool( DumpSize );=0D
+ UT_ASSERT_NOT_EFI_ERROR( DumpVariablePolicy( DumpBuffer, &DumpSize ) );=
=0D
+ UT_ASSERT_MEM_EQUAL( DumpBuffer, &TestPolicy, DumpSize );=0D
+=0D
+ // Clean up from this step.=0D
+ FreePool( DumpBuffer );=0D
+ DumpBuffer =3D NULL;=0D
+ DumpSize =3D 0;=0D
+=0D
+ // Now disable the engine.=0D
+ DisableVariablePolicy();=0D
+=0D
+ // Now register a new policy and make sure that both can be dumped.=0D
+ UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &TestPolicy2.Header ) )=
;=0D
+ // Make sure that we can dump the policy.=0D
+ PolicyCheck =3D DumpVariablePolicy( DumpBuffer, &DumpSize );=0D
+ UT_ASSERT_STATUS_EQUAL( PolicyCheck, EFI_BUFFER_TOO_SMALL );=0D
+ DumpBuffer =3D AllocatePool( DumpSize );=0D
+ UT_ASSERT_NOT_EFI_ERROR( DumpVariablePolicy( DumpBuffer, &DumpSize ) );=
=0D
+=0D
+ // Finally, make sure that both policies are in the dump.=0D
+ UT_ASSERT_MEM_EQUAL( DumpBuffer, &TestPolicy, TestPolicy.Header.Size );=
=0D
+ UT_ASSERT_MEM_EQUAL( (UINT8*)DumpBuffer + TestPolicy.Header.Size,=0D
+ &TestPolicy2,=0D
+ TestPolicy2.Header.Size );=0D
+=0D
+ // Always put away your toys.=0D
+ FreePool( DumpBuffer );=0D
+=0D
+ return UNIT_TEST_PASSED;=0D
+}=0D
+=0D
+=0D
+///=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=0D
+=0D
+/**=0D
+ SampleUnitTestApp=0D
+=0D
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.=
=0D
+ @param[in] SystemTable A pointer to the EFI System Table.=0D
+=0D
+ @retval EFI_SUCCESS The entry point executed successfully.=0D
+ @retval other Some error occured when executing this entry poi=
nt.=0D
+=0D
+**/=0D
+int=0D
+main (=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ UNIT_TEST_FRAMEWORK_HANDLE Framework =3D NULL;=0D
+ UNIT_TEST_SUITE_HANDLE ArchTests;=0D
+ UNIT_TEST_SUITE_HANDLE PolicyTests;=0D
+ UNIT_TEST_SUITE_HANDLE UtilityTests;=0D
+#ifdef INTERNAL_UNIT_TEST=0D
+ UNIT_TEST_SUITE_HANDLE InternalTests;=0D
+#endif // INTERNAL_UNIT_TEST=0D
+=0D
+ DEBUG(( DEBUG_INFO, "%a v%a\n", UNIT_TEST_NAME, UNIT_TEST_VERSION ));=0D
+=0D
+ //=0D
+ // Start setting up the test framework for running the tests.=0D
+ //=0D
+ Status =3D InitUnitTestFramework( &Framework, UNIT_TEST_NAME, gEfiCaller=
BaseName, UNIT_TEST_VERSION );=0D
+ if (EFI_ERROR( Status ))=0D
+ {=0D
+ DEBUG((DEBUG_ERROR, "Failed in InitUnitTestFramework. Status =3D %r\n"=
, Status));=0D
+ goto EXIT;=0D
+ }=0D
+=0D
+=0D
+ //=0D
+ // Add all test suites and tests.=0D
+ //=0D
+ Status =3D CreateUnitTestSuite( &ArchTests, Framework, "Variable Policy =
Architectural Tests", "VarPolicy.Arch", NULL, NULL );=0D
+ if (EFI_ERROR( Status ))=0D
+ {=0D
+ DEBUG((DEBUG_ERROR, "Failed in CreateUnitTestSuite for ArchTests\n"));=
=0D
+ Status =3D EFI_OUT_OF_RESOURCES;=0D
+ goto EXIT;=0D
+ }=0D
+ AddTestCase( ArchTests,=0D
+ "Deinitialization should fail if not previously initialize=
d", "VarPolicy.Arch.OnlyDeinit",=0D
+ ShouldFailDeinitWithoutInit, NULL, NULL, NULL );=0D
+ AddTestCase( ArchTests,=0D
+ "Initialization followed by deinitialization should succee=
d", "VarPolicy.Arch.InitDeinit",=0D
+ ShouldBeAbleToInitAndDeinitTheLibrary, NULL, NULL, NULL );=
=0D
+ AddTestCase( ArchTests,=0D
+ "The initialization function fail if called twice without =
a deinit", "VarPolicy.Arch.InitTwice",=0D
+ ShouldNotBeAbleToInitializeTheLibraryTwice, NULL, LibClean=
up, NULL );=0D
+ AddTestCase( ArchTests,=0D
+ "API functions should be unavailable until library is init=
ialized", "VarPolicy.Arch.UninitApiOff",=0D
+ ApiCommandsShouldNotRespondIfLibIsUninitialized, NULL, Lib=
Cleanup, NULL );=0D
+=0D
+#ifdef INTERNAL_UNIT_TEST=0D
+ Status =3D CreateUnitTestSuite( &InternalTests, Framework, "Variable Pol=
icy Internal Tests", "VarPolicy.Internal", NULL, NULL );=0D
+ if (EFI_ERROR( Status ))=0D
+ {=0D
+ DEBUG((DEBUG_ERROR, "Failed in CreateUnitTestSuite for InternalTests\n=
"));=0D
+ Status =3D EFI_OUT_OF_RESOURCES;=0D
+ goto EXIT;=0D
+ }=0D
+ AddTestCase( InternalTests,=0D
+ "Policy matching should use name and GUID", "VarPolicy.Int=
ernal.NameGuid",=0D
+ PoliciesShouldMatchByNameAndGuid, LibInitMocked, LibCleanu=
p, NULL );=0D
+ AddTestCase( InternalTests,=0D
+ "# sign wildcards should match digits", "VarPolicy.Interna=
l.WildDigits",=0D
+ WildcardPoliciesShouldMatchDigits, LibInitMocked, LibClean=
up, NULL );=0D
+ AddTestCase( InternalTests,=0D
+ "Digit wildcards should check edge cases", "VarPolicy.Inte=
rnal.WildDigitsAdvanced",=0D
+ WildcardPoliciesShouldMatchDigitsAdvanced, LibInitMocked, =
LibCleanup, NULL );=0D
+ AddTestCase( InternalTests,=0D
+ "Empty names should match an entire namespace", "VarPolicy=
.Internal.WildNamespace",=0D
+ WildcardPoliciesShouldMatchNamespaces, LibInitMocked, LibC=
leanup, NULL );=0D
+ AddTestCase( InternalTests,=0D
+ "Match priority should weight correctly based on wildcards=
", "VarPolicy.Internal.Priorities",=0D
+ MatchPrioritiesShouldFollowRules, LibInitMocked, LibCleanu=
p, NULL );=0D
+#endif // INTERNAL_UNIT_TEST=0D
+=0D
+ Status =3D CreateUnitTestSuite( &PolicyTests, Framework, "Variable Polic=
y Manipulation Tests", "VarPolicy.Policy", NULL, NULL );=0D
+ if (EFI_ERROR( Status ))=0D
+ {=0D
+ DEBUG((DEBUG_ERROR, "Failed in CreateUnitTestSuite for PolicyTests\n")=
);=0D
+ Status =3D EFI_OUT_OF_RESOURCES;=0D
+ goto EXIT;=0D
+ }=0D
+ AddTestCase( PolicyTests,=0D
+ "RegisterShouldAllowNamespaceWildcards", "VarPolicy.Policy=
.AllowNamespace",=0D
+ RegisterShouldAllowNamespaceWildcards, LibInitMocked, LibC=
leanup, NULL );=0D
+ AddTestCase( PolicyTests,=0D
+ "RegisterShouldAllowStateVarsForNamespaces", "VarPolicy.Po=
licy.AllowStateNamespace",=0D
+ RegisterShouldAllowStateVarsForNamespaces, LibInitMocked, =
LibCleanup, NULL );=0D
+ AddTestCase( PolicyTests,=0D
+ "RegisterShouldRejectNullPointers", "VarPolicy.Policy.Null=
Pointers",=0D
+ RegisterShouldRejectNullPointers, LibInitMocked, LibCleanu=
p, NULL );=0D
+ AddTestCase( PolicyTests,=0D
+ "RegisterShouldRejectBadRevisions", "VarPolicy.Policy.BadR=
evisions",=0D
+ RegisterShouldRejectBadRevisions, LibInitMocked, LibCleanu=
p, NULL );=0D
+ AddTestCase( PolicyTests,=0D
+ "RegisterShouldRejectBadSizes", "VarPolicy.Policy.BadSizes=
",=0D
+ RegisterShouldRejectBadSizes, LibInitMocked, LibCleanup, N=
ULL );=0D
+ AddTestCase( PolicyTests,=0D
+ "RegisterShouldRejectBadOffsets", "VarPolicy.Policy.BadOff=
sets",=0D
+ RegisterShouldRejectBadOffsets, LibInitMocked, LibCleanup,=
NULL );=0D
+ AddTestCase( PolicyTests,=0D
+ "RegisterShouldRejectMissingStateStrings", "VarPolicy.Poli=
cy.MissingStateString",=0D
+ RegisterShouldRejectMissingStateStrings, LibInitMocked, Li=
bCleanup, NULL );=0D
+ AddTestCase( PolicyTests,=0D
+ "RegisterShouldRejectStringsMissingNull", "VarPolicy.Polic=
y.MissingNull",=0D
+ RegisterShouldRejectStringsMissingNull, LibInitMocked, Lib=
Cleanup, NULL );=0D
+ AddTestCase( PolicyTests,=0D
+ "RegisterShouldRejectMalformedStrings", "VarPolicy.Policy.=
MalformedStrings",=0D
+ RegisterShouldRejectMalformedStrings, LibInitMocked, LibCl=
eanup, NULL );=0D
+ AddTestCase( PolicyTests,=0D
+ "RegisterShouldRejectUnpackedPolicies", "VarPolicy.Policy.=
PolicyPacking",=0D
+ RegisterShouldRejectUnpackedPolicies, LibInitMocked, LibCl=
eanup, NULL );=0D
+ AddTestCase( PolicyTests,=0D
+ "RegisterShouldRejectInvalidNameCharacters", "VarPolicy.Po=
licy.InvalidCharacters",=0D
+ RegisterShouldRejectInvalidNameCharacters, LibInitMocked, =
LibCleanup, NULL );=0D
+ AddTestCase( PolicyTests,=0D
+ "RegisterShouldRejectBadPolicyConstraints", "VarPolicy.Pol=
icy.BadConstraints",=0D
+ RegisterShouldRejectBadPolicyConstraints, LibInitMocked, L=
ibCleanup, NULL );=0D
+ AddTestCase( PolicyTests,=0D
+ "RegisterShouldRejectUnknownLockPolicies", "VarPolicy.Poli=
cy.BadLocks",=0D
+ RegisterShouldRejectUnknownLockPolicies, LibInitMocked, Li=
bCleanup, NULL );=0D
+ AddTestCase( PolicyTests,=0D
+ "RegisterShouldRejectPolicesWithTooManyWildcards", "VarPol=
icy.Policy.TooManyWildcards",=0D
+ RegisterShouldRejectPolicesWithTooManyWildcards, LibInitMo=
cked, LibCleanup, NULL );=0D
+ AddTestCase( PolicyTests,=0D
+ "RegisterShouldRejectDuplicatePolicies", "VarPolicy.Policy=
.DuplicatePolicies",=0D
+ RegisterShouldRejectDuplicatePolicies, LibInitMocked, LibC=
leanup, NULL );=0D
+ AddTestCase( PolicyTests,=0D
+ "Variables that exceed min or max sizes should be rejected=
", "VarPolicy.Policy.MinMax",=0D
+ MinAndMaxSizePoliciesShouldBeHonored, LibInitMocked, LibCl=
eanup, NULL );=0D
+ AddTestCase( PolicyTests,=0D
+ "AttributeMustPoliciesShouldBeHonored", "VarPolicy.Policy.=
AttrMust",=0D
+ AttributeMustPoliciesShouldBeHonored, LibInitMocked, LibCl=
eanup, NULL );=0D
+ AddTestCase( PolicyTests,=0D
+ "AttributeCantPoliciesShouldBeHonored", "VarPolicy.Policy.=
AttrCant",=0D
+ AttributeCantPoliciesShouldBeHonored, LibInitMocked, LibCl=
eanup, NULL );=0D
+ AddTestCase( PolicyTests,=0D
+ "VariablesShouldBeDeletableRegardlessOfSize", "VarPolicy.P=
olicy.DeleteIgnoreSize",=0D
+ VariablesShouldBeDeletableRegardlessOfSize, LibInitMocked,=
LibCleanup, NULL );=0D
+ AddTestCase( PolicyTests,=0D
+ "LockNowPoliciesShouldBeHonored", "VarPolicy.Policy.VARIAB=
LE_POLICY_TYPE_LOCK_NOW",=0D
+ LockNowPoliciesShouldBeHonored, LibInitMocked, LibCleanup,=
NULL );=0D
+ AddTestCase( PolicyTests,=0D
+ "LockOnCreatePoliciesShouldBeHonored", "VarPolicy.Policy.V=
ARIABLE_POLICY_TYPE_LOCK_ON_CREATE",=0D
+ LockOnCreatePoliciesShouldBeHonored, LibInitMocked, LibCle=
anup, NULL );=0D
+ AddTestCase( PolicyTests,=0D
+ "LockOnStatePoliciesShouldBeHonored", "VarPolicy.Policy.Lo=
ckState",=0D
+ LockOnStatePoliciesShouldBeHonored, LibInitMocked, LibClea=
nup, NULL );=0D
+ AddTestCase( PolicyTests,=0D
+ "LockOnStatePoliciesShouldApplyToNamespaces", "VarPolicy.P=
olicy.NamespaceLockState",=0D
+ LockOnStatePoliciesShouldApplyToNamespaces, LibInitMocked,=
LibCleanup, NULL );=0D
+ AddTestCase( PolicyTests,=0D
+ "LockOnStateShouldHandleErrorsGracefully", "VarPolicy.Poli=
cy.LockStateErrors",=0D
+ LockOnStateShouldHandleErrorsGracefully, LibInitMocked, Li=
bCleanup, NULL );=0D
+ AddTestCase( PolicyTests,=0D
+ "BestMatchPriorityShouldBeObeyed", "VarPolicy.Policy.BestM=
atch",=0D
+ BestMatchPriorityShouldBeObeyed, LibInitMocked, LibCleanup=
, NULL );=0D
+=0D
+ Status =3D CreateUnitTestSuite( &UtilityTests, Framework, "Variable Poli=
cy Utility Tests", "VarPolicy.Utility", NULL, NULL );=0D
+ if (EFI_ERROR( Status ))=0D
+ {=0D
+ DEBUG((DEBUG_ERROR, "Failed in CreateUnitTestSuite for UtilityTests\n"=
));=0D
+ Status =3D EFI_OUT_OF_RESOURCES;=0D
+ goto EXIT;=0D
+ }=0D
+ AddTestCase( UtilityTests,=0D
+ "API commands that change state should not respond after i=
nterface is locked", "VarPolicy.Utility.InterfaceLock",=0D
+ ShouldBeAbleToLockInterface, LibInitMocked, LibCleanup, NU=
LL );=0D
+ AddTestCase( UtilityTests,=0D
+ "All policies should pass once enforcement is disabled", "=
VarPolicy.Utility.DisableEnforcement",=0D
+ ShouldBeAbleToDisablePolicyEnforcement, LibInitMocked, Lib=
Cleanup, NULL );=0D
+ AddTestCase( UtilityTests,=0D
+ "Disabling enforcement twice should produce an error", "Va=
rPolicy.Utility.DisableEnforcementTwice",=0D
+ ShouldNotBeAbleToDisablePoliciesTwice, LibInitMocked, LibC=
leanup, NULL );=0D
+ AddTestCase( UtilityTests,=0D
+ "ShouldBeAbleToAddNewPoliciesAfterDisabled", "VarPolicy.Ut=
ility.AddAfterDisable",=0D
+ ShouldBeAbleToAddNewPoliciesAfterDisabled, LibInitMocked, =
LibCleanup, NULL );=0D
+ AddTestCase( UtilityTests,=0D
+ "ShouldBeAbleToLockAfterDisabled", "VarPolicy.Utility.Lock=
AfterDisable",=0D
+ ShouldBeAbleToLockAfterDisabled, LibInitMocked, LibCleanup=
, NULL );=0D
+ AddTestCase( UtilityTests,=0D
+ "Should be able to dump the policy table", "VarPolicy.Util=
ity.DumpTable",=0D
+ ShouldBeAbleToDumpThePolicyTable, LibInitMocked, LibCleanu=
p, NULL );=0D
+ AddTestCase( UtilityTests,=0D
+ "ShouldBeAbleToDumpThePolicyTableAfterDisabled", "VarPolic=
y.Utility.DumpTableAfterDisable",=0D
+ ShouldBeAbleToDumpThePolicyTableAfterDisabled, LibInitMock=
ed, LibCleanup, NULL );=0D
+=0D
+=0D
+ //=0D
+ // Execute the tests.=0D
+ //=0D
+ Status =3D RunAllTestSuites( Framework );=0D
+=0D
+EXIT:=0D
+ if (Framework !=3D NULL)=0D
+ {=0D
+ FreeUnitTestFramework( Framework );=0D
+ }=0D
+=0D
+ return Status;=0D
+}=0D
diff --git a/MdeModulePkg/Include/Library/VariablePolicyLib.h b/MdeModulePk=
g/Include/Library/VariablePolicyLib.h
new file mode 100644
index 000000000000..efd1840112ec
--- /dev/null
+++ b/MdeModulePkg/Include/Library/VariablePolicyLib.h
@@ -0,0 +1,207 @@
+/** @file -- VariablePolicyLib.h=0D
+Business logic for Variable Policy enforcement.=0D
+=0D
+Copyright (c) Microsoft Corporation.=0D
+SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+=0D
+**/=0D
+=0D
+#ifndef _VARIABLE_POLICY_LIB_H_=0D
+#define _VARIABLE_POLICY_LIB_H_=0D
+=0D
+#include <Protocol/VariablePolicy.h>=0D
+=0D
+/**=0D
+ This API function validates and registers a new policy with=0D
+ the policy enforcement engine.=0D
+=0D
+ @param[in] NewPolicy Pointer to the incoming policy structure.=0D
+=0D
+ @retval EFI_SUCCESS=0D
+ @retval EFI_INVALID_PARAMETER NewPolicy is NULL or is internally i=
nconsistent.=0D
+ @retval EFI_ALREADY_STARTED An identical matching policy already=
exists.=0D
+ @retval EFI_WRITE_PROTECTED The interface has been locked until =
the next reboot.=0D
+ @retval EFI_UNSUPPORTED Policy enforcement has been disabled=
. No reason to add more policies.=0D
+ @retval EFI_ABORTED A calculation error has prevented th=
is function from completing.=0D
+ @retval EFI_OUT_OF_RESOURCES Cannot grow the table to hold any mo=
re policies.=0D
+ @retval EFI_NOT_READY Library has not yet been initialized=
.=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+RegisterVariablePolicy (=0D
+ IN CONST VARIABLE_POLICY_ENTRY *NewPolicy=0D
+ );=0D
+=0D
+=0D
+/**=0D
+ This API function checks to see whether the parameters to SetVariable wo=
uld=0D
+ be allowed according to the current variable policies.=0D
+=0D
+ @param[in] VariableName Same as EFI_SET_VARIABLE.=0D
+ @param[in] VendorGuid Same as EFI_SET_VARIABLE.=0D
+ @param[in] Attributes Same as EFI_SET_VARIABLE.=0D
+ @param[in] DataSize Same as EFI_SET_VARIABLE.=0D
+ @param[in] Data Same as EFI_SET_VARIABLE.=0D
+=0D
+ @retval EFI_SUCCESS A matching policy allows this update=
.=0D
+ @retval EFI_SUCCESS There are currently no policies that=
restrict this update.=0D
+ @retval EFI_SUCCESS The protections have been disable un=
til the next reboot.=0D
+ @retval EFI_WRITE_PROTECTED Variable is currently locked.=0D
+ @retval EFI_INVALID_PARAMETER Attributes or size are invalid.=0D
+ @retval EFI_ABORTED A lock policy exists, but an error p=
revented evaluation.=0D
+ @retval EFI_NOT_READY Library has not been initialized.=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+ValidateSetVariable (=0D
+ IN CHAR16 *VariableName,=0D
+ IN EFI_GUID *VendorGuid,=0D
+ IN UINT32 Attributes,=0D
+ IN UINTN DataSize,=0D
+ IN VOID *Data=0D
+ );=0D
+=0D
+=0D
+/**=0D
+ This API function disables the variable policy enforcement. If it's=0D
+ already been called once, will return EFI_ALREADY_STARTED.=0D
+=0D
+ @retval EFI_SUCCESS=0D
+ @retval EFI_ALREADY_STARTED Has already been called once this boot=
.=0D
+ @retval EFI_WRITE_PROTECTED Interface has been locked until reboot=
.=0D
+ @retval EFI_WRITE_PROTECTED Interface option is disabled by platfo=
rm PCD.=0D
+ @retval EFI_NOT_READY Library has not yet been initialized.=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+DisableVariablePolicy (=0D
+ VOID=0D
+ );=0D
+=0D
+=0D
+/**=0D
+ This API function will dump the entire contents of the variable policy t=
able.=0D
+=0D
+ Similar to GetVariable, the first call can be made with a 0 size and it =
will return=0D
+ the size of the buffer required to hold the entire table.=0D
+=0D
+ @param[out] Policy Pointer to the policy buffer. Can be NULL if Siz=
e is 0.=0D
+ @param[in,out] Size On input, the size of the output buffer. On outp=
ut, the size=0D
+ of the data returned.=0D
+=0D
+ @retval EFI_SUCCESS Policy data is in the output buffer =
and Size has been updated.=0D
+ @retval EFI_INVALID_PARAMETER Size is NULL, or Size is non-zero an=
d Policy is NULL.=0D
+ @retval EFI_BUFFER_TOO_SMALL Size is insufficient to hold policy.=
Size updated with required size.=0D
+ @retval EFI_NOT_READY Library has not yet been initialized=
.=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+DumpVariablePolicy (=0D
+ OUT UINT8 *Policy,=0D
+ IN OUT UINT32 *Size=0D
+ );=0D
+=0D
+=0D
+/**=0D
+ This API function returns whether or not the policy engine is=0D
+ currently being enforced.=0D
+=0D
+ @retval TRUE=0D
+ @retval FALSE=0D
+ @retval FALSE Library has not yet been initialized.=0D
+=0D
+**/=0D
+BOOLEAN=0D
+EFIAPI=0D
+IsVariablePolicyEnabled (=0D
+ VOID=0D
+ );=0D
+=0D
+=0D
+/**=0D
+ This API function locks the interface so that no more policy updates=0D
+ can be performed or changes made to the enforcement until the next boot.=
=0D
+=0D
+ @retval EFI_SUCCESS=0D
+ @retval EFI_NOT_READY Library has not yet been initialized.=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+LockVariablePolicy (=0D
+ VOID=0D
+ );=0D
+=0D
+=0D
+/**=0D
+ This API function returns whether or not the policy interface is locked=
=0D
+ for the remainder of the boot.=0D
+=0D
+ @retval TRUE=0D
+ @retval FALSE=0D
+ @retval FALSE Library has not yet been initialized.=0D
+=0D
+**/=0D
+BOOLEAN=0D
+EFIAPI=0D
+IsVariablePolicyInterfaceLocked (=0D
+ VOID=0D
+ );=0D
+=0D
+=0D
+/**=0D
+ This helper function initializes the library and sets=0D
+ up any required internal structures or handlers.=0D
+=0D
+ Also registers the internal pointer for the GetVariable helper.=0D
+=0D
+ @param[in] GetVariableHelper A function pointer matching the EFI_GET_VA=
RIABLE prototype that will be used to=0D
+ check policy criteria that involve the existence of othe=
r variables.=0D
+=0D
+ @retval EFI_SUCCESS=0D
+ @retval EFI_ALREADY_STARTED The initialize function has been calle=
d more than once without a call to=0D
+ deinitialize.=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+InitVariablePolicyLib (=0D
+ IN EFI_GET_VARIABLE GetVariableHelper=0D
+ );=0D
+=0D
+=0D
+/**=0D
+ This helper function returns whether or not the library is currently ini=
tialized.=0D
+=0D
+ @retval TRUE=0D
+ @retval FALSE=0D
+=0D
+**/=0D
+BOOLEAN=0D
+EFIAPI=0D
+IsVariablePolicyLibInitialized (=0D
+ VOID=0D
+ );=0D
+=0D
+=0D
+/**=0D
+ This helper function tears down the library.=0D
+=0D
+ Should generally only be used for test harnesses.=0D
+=0D
+ @retval EFI_SUCCESS=0D
+ @retval EFI_NOT_READY Deinitialize was called without first call=
ing initialize.=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+DeinitVariablePolicyLib (=0D
+ VOID=0D
+ );=0D
+=0D
+=0D
+#endif // _VARIABLE_POLICY_LIB_H_=0D
diff --git a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf b=
/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf
new file mode 100644
index 000000000000..f4a879d5382f
--- /dev/null
+++ b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf
@@ -0,0 +1,44 @@
+## @file VariablePolicyLib.inf=0D
+# Business logic for Variable Policy enforcement.=0D
+#=0D
+##=0D
+# Copyright (c) Microsoft Corporation.=0D
+# SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+##=0D
+=0D
+=0D
+[Defines]=0D
+ INF_VERSION =3D 0x00010017=0D
+ BASE_NAME =3D VariablePolicyLib=0D
+ FILE_GUID =3D E9ECD342-159A-4F24-9FDF-65724027C594=0D
+ VERSION_STRING =3D 1.0=0D
+ MODULE_TYPE =3D DXE_DRIVER=0D
+ LIBRARY_CLASS =3D VariablePolicyLib|DXE_DRIVER DXE_SMM_DRIVER MM_S=
TANDALONE=0D
+=0D
+#=0D
+# The following information is for reference only and not required by the =
build tools.=0D
+#=0D
+# VALID_ARCHITECTURES =3D ANY=0D
+#=0D
+=0D
+=0D
+[Sources]=0D
+ VariablePolicyLib.c=0D
+ VariablePolicyExtraInitNull.c=0D
+=0D
+=0D
+[Packages]=0D
+ MdePkg/MdePkg.dec=0D
+ MdeModulePkg/MdeModulePkg.dec=0D
+=0D
+=0D
+[LibraryClasses]=0D
+ DebugLib=0D
+ BaseMemoryLib=0D
+ MemoryAllocationLib=0D
+ SafeIntLib=0D
+ PcdLib=0D
+=0D
+=0D
+[Pcd]=0D
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAllowVariablePolicyEnforcementDisable =
## CONSUMES=0D
diff --git a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.uni b=
/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.uni
new file mode 100644
index 000000000000..2227ec427828
--- /dev/null
+++ b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.uni
@@ -0,0 +1,12 @@
+// /** @file=0D
+// VariablePolicyLib.uni=0D
+//=0D
+// Copyright (c) Microsoft Corporation.=0D
+// SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+//=0D
+// **/=0D
+=0D
+=0D
+#string STR_MODULE_ABSTRACT #language en-US "Library containin=
g the business logic for the VariablePolicy engine"=0D
+=0D
+#string STR_MODULE_DESCRIPTION #language en-US "Library containin=
g the business logic for the VariablePolicy engine"=0D
diff --git a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntim=
eDxe.inf b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeD=
xe.inf
new file mode 100644
index 000000000000..8b8365741864
--- /dev/null
+++ b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf
@@ -0,0 +1,51 @@
+## @file VariablePolicyLibRuntimeDxe.inf=0D
+# Business logic for Variable Policy enforcement.=0D
+# This instance is specifically for RuntimeDxe and contains=0D
+# extra routines to register for VirtualAddressChangeEvents.=0D
+#=0D
+# Copyright (c) Microsoft Corporation.=0D
+# SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+##=0D
+=0D
+=0D
+[Defines]=0D
+ INF_VERSION =3D 0x00010017=0D
+ BASE_NAME =3D VariablePolicyLibRuntimeDxe=0D
+ FILE_GUID =3D 205F7F0E-8EAC-4914-8390-1B90DD7E2A27=0D
+ VERSION_STRING =3D 1.0=0D
+ MODULE_TYPE =3D DXE_RUNTIME_DRIVER=0D
+ LIBRARY_CLASS =3D VariablePolicyLib|DXE_RUNTIME_DRIVER=0D
+=0D
+#=0D
+# The following information is for reference only and not required by the =
build tools.=0D
+#=0D
+# VALID_ARCHITECTURES =3D ANY=0D
+#=0D
+=0D
+=0D
+[Sources]=0D
+ VariablePolicyLib.c=0D
+ VariablePolicyExtraInitRuntimeDxe.c=0D
+=0D
+=0D
+[Packages]=0D
+ MdePkg/MdePkg.dec=0D
+ MdeModulePkg/MdeModulePkg.dec=0D
+=0D
+=0D
+[LibraryClasses]=0D
+ DebugLib=0D
+ BaseMemoryLib=0D
+ MemoryAllocationLib=0D
+ SafeIntLib=0D
+ UefiBootServicesTableLib=0D
+ UefiRuntimeServicesTableLib=0D
+ PcdLib=0D
+=0D
+=0D
+[Pcd]=0D
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAllowVariablePolicyEnforcementDisable =
## CONSUMES=0D
+=0D
+=0D
+[Guids]=0D
+ gEfiEventVirtualAddressChangeGuid=0D
diff --git a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/=
VariablePolicyUnitTest.inf b/MdeModulePkg/Library/VariablePolicyLib/Variabl=
ePolicyUnitTest/VariablePolicyUnitTest.inf
new file mode 100644
index 000000000000..ccc04bb600d6
--- /dev/null
+++ b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/Variabl=
ePolicyUnitTest.inf
@@ -0,0 +1,40 @@
+## @file VariablePolicyUnitTest.inf=0D
+# UnitTest for...=0D
+# Business logic for Variable Policy enforcement.=0D
+#=0D
+# Copyright (c) Microsoft Corporation.=0D
+# SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+##=0D
+=0D
+=0D
+[Defines]=0D
+ INF_VERSION =3D 0x00010006=0D
+ BASE_NAME =3D VariablePolicyUnitTest=0D
+ FILE_GUID =3D 1200A2E4-D756-418C-9768-528C2D181A98=
=0D
+ MODULE_TYPE =3D HOST_APPLICATION=0D
+ VERSION_STRING =3D 1.0=0D
+=0D
+#=0D
+# The following information is for reference only and not required by the =
build tools.=0D
+#=0D
+# VALID_ARCHITECTURES =3D IA32 X64 ARM AARCH64=0D
+#=0D
+=0D
+[Sources]=0D
+ VariablePolicyUnitTest.c=0D
+=0D
+=0D
+[Packages]=0D
+ MdePkg/MdePkg.dec=0D
+ MdeModulePkg/MdeModulePkg.dec=0D
+ UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec=0D
+=0D
+=0D
+[LibraryClasses]=0D
+ BaseLib=0D
+ DebugLib=0D
+ UnitTestLib=0D
+ PrintLib=0D
+ VariablePolicyLib=0D
+ BaseMemoryLib=0D
+ MemoryAllocationLib=0D
diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec
index 2e0461b87c32..31339741b840 100644
--- a/MdeModulePkg/MdeModulePkg.dec
+++ b/MdeModulePkg/MdeModulePkg.dec
@@ -31,6 +31,9 @@ [LibraryClasses]
## @libraryclass Defines a set of methods to reset whole system.=0D
ResetSystemLib|Include/Library/ResetSystemLib.h=0D
=0D
+ ## @libraryclass Business logic for storing and testing variable polic=
ies=0D
+ VariablePolicyLib|Include/Library/VariablePolicyLib.h=0D
+=0D
## @libraryclass Defines a set of helper functions for resetting the s=
ystem.=0D
ResetUtilityLib|Include/Library/ResetUtilityLib.h=0D
=0D
diff --git a/MdeModulePkg/MdeModulePkg.dsc b/MdeModulePkg/MdeModulePkg.dsc
index 25aea3e2a481..14b6ed536962 100644
--- a/MdeModulePkg/MdeModulePkg.dsc
+++ b/MdeModulePkg/MdeModulePkg.dsc
@@ -3,6 +3,7 @@
#=0D
# (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>=0D
# Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved.<BR>=0D
+# Copyright (c) Microsoft Corporation.=0D
#=0D
# SPDX-License-Identifier: BSD-2-Clause-Patent=0D
#=0D
@@ -58,6 +59,7 @@ [LibraryClasses]
DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf=0D
DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableL=
ib.inf=0D
UefiBootManagerLib|MdeModulePkg/Library/UefiBootManagerLib/UefiBootManag=
erLib.inf=0D
+ VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyL=
ib.inf=0D
#=0D
# Generic Modules=0D
#=0D
@@ -129,6 +131,7 @@ [LibraryClasses.common.DXE_RUNTIME_DRIVER]
DebugLib|MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf=0D
LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxDxeLib.inf=0D
CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.in=
f=0D
+ VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyL=
ibRuntimeDxe.inf=0D
=0D
[LibraryClasses.common.SMM_CORE]=0D
HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf=0D
@@ -306,6 +309,8 @@ [Components]
MdeModulePkg/Library/BootLogoLib/BootLogoLib.inf=0D
MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf=0D
MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf=0D
+ MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf=0D
+ MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf=0D
MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf=0D
MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLib.inf=0D
MdeModulePkg/Library/VarCheckPcdLib/VarCheckPcdLib.inf=0D
diff --git a/MdeModulePkg/Test/MdeModulePkgHostTest.dsc b/MdeModulePkg/Test=
/MdeModulePkgHostTest.dsc
index 72a119db4568..095e613f1be1 100644
--- a/MdeModulePkg/Test/MdeModulePkgHostTest.dsc
+++ b/MdeModulePkg/Test/MdeModulePkgHostTest.dsc
@@ -19,12 +19,23 @@ [Defines]
=0D
!include UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc=0D
=0D
+[LibraryClasses]=0D
+ SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf=0D
+=0D
[Components]=0D
MdeModulePkg/Library/DxeResetSystemLib/UnitTest/MockUefiRuntimeServicesT=
ableLib.inf=0D
=0D
#=0D
# Build MdeModulePkg HOST_APPLICATION Tests=0D
#=0D
+ MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePo=
licyUnitTest.inf {=0D
+ <LibraryClasses>=0D
+ VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePol=
icyLib.inf=0D
+=0D
+ <PcdsFixedAtBuild>=0D
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAllowVariablePolicyEnforcementDisa=
ble|TRUE=0D
+ }=0D
+=0D
MdeModulePkg/Library/DxeResetSystemLib/UnitTest/DxeResetSystemLibUnitTes=
tHost.inf {=0D
<LibraryClasses>=0D
ResetSystemLib|MdeModulePkg/Library/DxeResetSystemLib/DxeResetSystem=
Lib.inf=0D
--=20
2.26.2.windows.1.8.g01c50adf56.20200515075929

Join devel@edk2.groups.io to automatically receive all group messages.