public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Guomin Jiang" <guomin.jiang@intel.com>
To: "devel@edk2.groups.io" <devel@edk2.groups.io>,
	"michael.kubacki@outlook.com" <michael.kubacki@outlook.com>
Cc: "Wang, Jian J" <jian.j.wang@intel.com>,
	"Wu, Hao A" <hao.a.wu@intel.com>,
	"Gao, Liming" <liming.gao@intel.com>
Subject: Re: [edk2-devel] [PATCH v1 2/9] MdeModulePkg: Define the VariablePolicyLib
Date: Wed, 22 Apr 2020 09:14:20 +0000	[thread overview]
Message-ID: <DM6PR11MB29556BAE8C569D5A7EF236CC9DD20@DM6PR11MB2955.namprd11.prod.outlook.com> (raw)
In-Reply-To: <MWHPR07MB3440440D1E801A4F7E352BD7E9DE0@MWHPR07MB3440.namprd07.prod.outlook.com>

It is better that pay more attention to code style, for example
Replace
NewTable = AllocatePool( NewSize );
With space
NewTable = AllocatePool (NewSize);

Refer https://github.com/tianocore/tianocore.github.io/wiki/Code-Style-C for simple principle and https://edk2-docs.gitbooks.io/edk-ii-c-coding-standards-specification/content/ for detail principle.

Below code can be optimized

diff --git a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c
index 52e025f2d0..35bc70970b 100644
--- a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c
+++ b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c
@@ -337,7 +337,6 @@ RegisterVariablePolicy (
   VARIABLE_POLICY_ENTRY     *MatchPolicy;
   UINT8                     MatchPriority;
   UINT32                    NewSize;
-  UINT8                     *NewTable;

   if (!IsVariablePolicyLibInitialized()) {
     return EFI_NOT_READY;
@@ -376,16 +375,11 @@ RegisterVariablePolicy (
     }

     // Reallocate and copy the table.
-    NewTable = AllocatePool( NewSize );
-    if (NewTable == NULL) {
+    mPolicyTable = ReallocatePool (mCurrentTableUsage, NewSize, mPolicyTable);
+    if (mPolicyTable == NULL) {
       return EFI_OUT_OF_RESOURCES;
     }
-    CopyMem( NewTable, mPolicyTable, mCurrentTableUsage );
     mCurrentTableSize = NewSize;
-    if (mPolicyTable != NULL) {
-      FreePool( mPolicyTable );
-    }
-    mPolicyTable = NewTable;
   }
   // Copy the policy into the table.
   CopyMem( mPolicyTable + mCurrentTableUsage, NewPolicy, NewPolicy->Size );

> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Michael
> Kubacki
> Sent: Saturday, April 11, 2020 2:38 AM
> To: devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>;
> Gao, Liming <liming.gao@intel.com>
> Subject: [edk2-devel] [PATCH v1 2/9] MdeModulePkg: Define the
> VariablePolicyLib
> 
> From: Bret Barkelew <brbarkel@microsoft.com>
> 
> https://bugzilla.tianocore.org/show_bug.cgi?id=2522
> 
> VariablePolicy is an updated interface to
> replace VarLock and VarCheckProtocol.
> 
> Add the VariablePolicyLib library that implements
> the portable business logic for the VariablePolicy
> engine.
> 
> Also add host-based CI test cases for the lib.
> 
> Cc: Jian J Wang <jian.j.wang@intel.com>
> Cc: Hao A Wu <hao.a.wu@intel.com>
> Cc: Liming Gao <liming.gao@intel.com>
> Signed-off-by: Bret Barkelew <brbarkel@microsoft.com>
> Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com>
> ---
>  MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c
> |  773 +++++++
> 
> MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePo
> licyUnitTest.c   | 2285 ++++++++++++++++++++
>  MdeModulePkg/Include/Library/VariablePolicyLib.h                                         |
> 206 ++
>  MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf
> |   38 +
>  MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.uni
> |   12 +
> 
> MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePo
> licyUnitTest.inf |   41 +
>  MdeModulePkg/MdeModulePkg.dec                                                            |    3 +
>  MdeModulePkg/MdeModulePkg.dsc                                                            |    3 +
>  MdeModulePkg/Test/MdeModulePkgHostTest.dsc                                               |
> 8 +
>  9 files changed, 3369 insertions(+)
> 
> diff --git a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c
> b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c
> new file mode 100644
> index 000000000000..52e025f2d0cf
> --- /dev/null
> +++ b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c
> @@ -0,0 +1,773 @@
> +/** @file -- VariablePolicyLib.c
> +Business logic for Variable Policy enforcement.
> +
> +Copyright (c) Microsoft Corporation.
> +SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include <Uefi.h>
> +
> +#include <Library/SafeIntLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Protocol/VariablePolicy.h>
> +#include <Library/VariablePolicyLib.h>
> +
> +#include <Library/DebugLib.h>
> +
> +// IMPORTANT NOTE: This library is currently rife with multiple return
> statements
> +//                 for error handling. A refactor should remove these at some point.
> +
> +//
> +// This library was designed with advanced unit-test features.
> +// This define handles the configuration.
> +#ifdef INTERNAL_UNIT_TEST
> +#undef STATIC
> +#define STATIC    // Nothing...
> +#endif
> +
> +// An abstracted GetVariable interface that enables configuration
> regardless of the environment.
> +STATIC  EFI_GET_VARIABLE    mGetVariableHelper = NULL;
> +
> +// Master switch to lock this entire interface. Does not stop enforcement,
> +// just prevents the configuration from being changed for the rest of the
> boot.
> +STATIC  BOOLEAN             mInterfaceLocked = FALSE;
> +
> +// Master switch to disable the entire interface for a single boot.
> +// This will disable all policy enforcement for the duration of the boot.
> +STATIC  BOOLEAN             mProtectionDisabled = FALSE;
> +
> +// Table to hold all the current policies.
> +STATIC  UINT8               *mPolicyTable = NULL;
> +STATIC  UINT32              mCurrentTableSize = 0;
> +STATIC  UINT32              mCurrentTableUsage = 0;
> +STATIC  UINT32              mCurrentTableCount = 0;
> +
> +#define POLICY_TABLE_STEP_SIZE        0x1000
> +
> +// NOTE: DO NOT USE THESE MACROS on any structure that has not been
> validated.
> +//       Current table data has already been sanitized.
> +#define GET_NEXT_POLICY(CurPolicy)
> (VARIABLE_POLICY_ENTRY*)((UINT8*)CurPolicy + CurPolicy->Size)
> +#define GET_POLICY_NAME(CurPolicy)    (CHAR16*)((UINTN)CurPolicy +
> CurPolicy->OffsetToName)
> +
> +#define MATCH_PRIORITY_EXACT    0
> +#define MATCH_PRIORITY_MAX      MATCH_PRIORITY_EXACT
> +#define MATCH_PRIORITY_MIN      MAX_UINT8
> +
> +
> +/**
> +  This helper function determines whether the structure of an incoming
> policy
> +  is valid and internally consistent.
> +
> +  @param[in]  NewPolicy     Pointer to the incoming policy structure.
> +
> +  @retval     TRUE
> +  @retval     FALSE   Pointer is NULL, size is wrong, strings are empty, or
> +                      substructures overlap.
> +
> +**/
> +STATIC
> +BOOLEAN
> +IsValidVariablePolicyStructure (
> +  IN CONST VARIABLE_POLICY_ENTRY    *NewPolicy
> +  )
> +{
> +  EFI_STATUS    Status;
> +  UINTN         EntryEnd;
> +  CHAR16        *CheckChar;
> +  UINTN         WildcardCount;
> +
> +  // Sanitize some quick values.
> +  if (NewPolicy == NULL || NewPolicy->Size == 0 ||
> +      // Structure size should be at least as long as the minumum structure and
> a NULL string.
> +      NewPolicy->Size < sizeof(VARIABLE_POLICY_ENTRY) ||
> +      // Check for the known revision.
> +      NewPolicy->Version != VARIABLE_POLICY_ENTRY_REVISION) {
> +    return FALSE;
> +  }
> +
> +  // Calculate the theoretical end of the structure and make sure
> +  // that the structure can fit in memory.
> +  Status = SafeUintnAdd( (UINTN)NewPolicy, NewPolicy->Size, &EntryEnd );
> +  if (EFI_ERROR( Status )) {
> +    return FALSE;
> +  }
> +
> +  // Check for a valid Max Size.
> +  if (NewPolicy->MaxSize == 0) {
> +    return FALSE;
> +  }
> +
> +  // Check for the valid list of lock policies.
> +  if (NewPolicy->LockPolicyType != VARIABLE_POLICY_TYPE_NO_LOCK &&
> +      NewPolicy->LockPolicyType != VARIABLE_POLICY_TYPE_LOCK_NOW &&
> +      NewPolicy->LockPolicyType !=
> VARIABLE_POLICY_TYPE_LOCK_ON_CREATE &&
> +      NewPolicy->LockPolicyType !=
> VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE)
> +  {
> +    return FALSE;
> +  }
> +
> +  // If the policy type is VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE,
> make sure that the matching state variable Name
> +  // terminates before the OffsetToName for the matching policy variable
> Name.
> +  if (NewPolicy->LockPolicyType ==
> VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE) {
> +    // Adjust CheckChar to the offset of the LockPolicy->Name.
> +    Status = SafeUintnAdd( (UINTN)NewPolicy +
> sizeof(VARIABLE_POLICY_ENTRY),
> +                            sizeof(VARIABLE_LOCK_ON_VAR_STATE_POLICY),
> +                            (UINTN*)&CheckChar );
> +    if (EFI_ERROR( Status ) || EntryEnd <= (UINTN)CheckChar) {
> +      return FALSE;
> +    }
> +    while (*CheckChar != CHAR_NULL) {
> +      if (EntryEnd <= (UINTN)CheckChar) {
> +        return FALSE;
> +      }
> +      CheckChar++;
> +    }
> +    // At this point we should have either exeeded the structure or be
> pointing at the last char in LockPolicy->Name.
> +    // We should check to make sure that the policy Name comes
> immediately after this charcter.
> +    if ((UINTN)++CheckChar != (UINTN)NewPolicy + NewPolicy-
> >OffsetToName) {
> +      return FALSE;
> +    }
> +  }
> +  // If the policy type is any other value, make sure that the LockPolicy
> structure has a zero length.
> +  else {
> +    if (NewPolicy->OffsetToName != sizeof(VARIABLE_POLICY_ENTRY)) {
> +      return FALSE;
> +    }
> +  }
> +
> +  // Check to make sure that the name has a terminating character
> +  // before the end of the structure.
> +  // We've already checked that the name is within the bounds of the
> structure.
> +  if (NewPolicy->Size != NewPolicy->OffsetToName) {
> +    CheckChar = (CHAR16*)((UINTN)NewPolicy + NewPolicy-
> >OffsetToName);
> +    WildcardCount = 0;
> +    while (*CheckChar != CHAR_NULL) {
> +      // Make sure there aren't excessive wildcards.
> +      if (*CheckChar == '#') {
> +        WildcardCount++;
> +        if (WildcardCount > MATCH_PRIORITY_MIN) {
> +          return FALSE;
> +        }
> +      }
> +      // Make sure you're still within the bounds of the policy structure.
> +      if (EntryEnd <= (UINTN)CheckChar) {
> +        return FALSE;
> +      }
> +      CheckChar++;
> +    }
> +
> +    // Finally, we should be pointed at the very last character in Name, so we
> should be right
> +    // up against the end of the structure.
> +    if ((UINTN)++CheckChar != EntryEnd) {
> +      return FALSE;
> +    }
> +  }
> +
> +  return TRUE;
> +}
> +
> +
> +/**
> +  This helper function evaluates a policy and determines whether it matches
> the target
> +  variable. If matched, will also return a value corresponding to the priority
> of the match.
> +
> +  The rules for "best match" are listed in the Variable Policy Spec.
> +  Perfect name matches will return 0.
> +  Single wildcard characters will return the number of wildcard characters.
> +  Full namespaces will return MAX_UINT8.
> +
> +  @param[in]  EvalEntry         Pointer to the policy entry being evaluated.
> +  @param[in]  VariableName      Same as EFI_SET_VARIABLE.
> +  @param[in]  VendorGuid        Same as EFI_SET_VARIABLE.
> +  @param[out] MatchPriority     [Optional] On finding a match, this value
> contains the priority of the match.
> +                                Lower number == higher priority. Only valid if a match found.
> +
> +  @retval     TRUE          Current entry matches the target variable.
> +  @retval     FALSE         Current entry does not match at all.
> +
> +**/
> +STATIC
> +BOOLEAN
> +EvaluatePolicyMatch (
> +  IN CONST  VARIABLE_POLICY_ENTRY   *EvalEntry,
> +  IN CONST  CHAR16                  *VariableName,
> +  IN CONST  EFI_GUID                *VendorGuid,
> +  OUT       UINT8                   *MatchPriority    OPTIONAL
> +  )
> +{
> +  BOOLEAN     Result = FALSE;
> +  CHAR16      *PolicyName;
> +  UINT8       CalculatedPriority = MATCH_PRIORITY_EXACT;
> +  UINTN       Index;
> +
> +  // Step 1: If the GUID doesn't match, we're done. No need to evaluate
> anything else.
> +  if (!CompareGuid( &EvalEntry->Namespace, VendorGuid )) {
> +    goto Exit;
> +  }
> +
> +  // If the GUID matches, check to see whether there is a Name associated
> +  // with the policy. If not, this policy matches the entire namespace.
> +  // Missing Name is indicated by size being equal to name.
> +  if (EvalEntry->Size == EvalEntry->OffsetToName) {
> +    CalculatedPriority = MATCH_PRIORITY_MIN;
> +    Result = TRUE;
> +    goto Exit;
> +  }
> +
> +  // Now that we know the name exists, get it.
> +  PolicyName = GET_POLICY_NAME( EvalEntry );
> +
> +  // Evaluate the name against the policy name and check for a match.
> +  // Account for any wildcards.
> +  Index = 0;
> +  Result = TRUE;
> +  // Keep going until the end of both strings.
> +  while (PolicyName[Index] != CHAR_NULL || VariableName[Index] !=
> CHAR_NULL) {
> +    // If we don't have a match...
> +    if (PolicyName[Index] != VariableName[Index] || PolicyName[Index] ==
> '#') {
> +      // If this is a numerical wildcard, we can consider
> +      // it a match if we alter the priority.
> +      if (PolicyName[Index] == L'#' &&
> +          (L'0' <= VariableName[Index] && VariableName[Index] <= L'9')) {
> +        if (CalculatedPriority < MATCH_PRIORITY_MIN) {
> +          CalculatedPriority++;
> +        }
> +      }
> +      // Otherwise, not a match.
> +      else {
> +        Result = FALSE;
> +        goto Exit;
> +      }
> +    }
> +    Index++;
> +  }
> +
> +Exit:
> +  if (Result && MatchPriority != NULL) {
> +    *MatchPriority = CalculatedPriority;
> +  }
> +  return Result;
> +}
> +
> +
> +/**
> +  This helper function walks the current policy table and returns a pointer
> +  to the best match, if any are found. Leverages EvaluatePolicyMatch() to
> +  determine "best".
> +
> +  @param[in]  VariableName       Same as EFI_SET_VARIABLE.
> +  @param[in]  VendorGuid         Same as EFI_SET_VARIABLE.
> +  @param[out] ReturnPriority     [Optional] If pointer is provided, return the
> +                                 priority of the match. Same as EvaluatePolicyMatch().
> +                                 Only valid if a match is returned.
> +
> +  @retval     VARIABLE_POLICY_ENTRY*    Best match that was found.
> +  @retval     NULL                      No match was found.
> +
> +**/
> +STATIC
> +VARIABLE_POLICY_ENTRY*
> +GetBestPolicyMatch (
> +  IN CONST  CHAR16            *VariableName,
> +  IN CONST  EFI_GUID          *VendorGuid,
> +  OUT       UINT8             *ReturnPriority  OPTIONAL
> +  )
> +{
> +  VARIABLE_POLICY_ENTRY   *BestResult = NULL;
> +  VARIABLE_POLICY_ENTRY   *CurrentEntry;
> +  UINT8                   MatchPriority;
> +  UINT8                   CurrentPriority;
> +  UINTN                   Index;
> +
> +  // Walk all entries in the table, looking for matches.
> +  CurrentEntry = (VARIABLE_POLICY_ENTRY*)mPolicyTable;
> +  for (Index = 0; Index < mCurrentTableCount; Index++) {
> +    // Check for a match.
> +    if (EvaluatePolicyMatch( CurrentEntry, VariableName, VendorGuid,
> &CurrentPriority ) == TRUE) {
> +      // If match is better, take it.
> +      if (BestResult == NULL || CurrentPriority < MatchPriority) {
> +        BestResult = CurrentEntry;
> +        MatchPriority = CurrentPriority;
> +      }
> +
> +      // If you've hit the highest-priority match, can exit now.
> +      if (MatchPriority == 0) {
> +        break;
> +      }
> +    }
> +
> +    // If we're still in the loop, move to the next entry.
> +    CurrentEntry = GET_NEXT_POLICY( CurrentEntry );
> +  }
> +
> +  // If a return priority was requested, return it.
> +  if (ReturnPriority != NULL) {
> +    *ReturnPriority = MatchPriority;
> +  }
> +
> +  return BestResult;
> +}
> +
> +
> +/**
> +  This API function validates and registers a new policy with
> +  the policy enforcement engine.
> +
> +  @param[in]  NewPolicy     Pointer to the incoming policy structure.
> +
> +  @retval     EFI_SUCCESS
> +  @retval     EFI_INVALID_PARAMETER   NewPolicy is NULL or is internally
> inconsistent.
> +  @retval     EFI_ALREADY_STARTED     An identical matching policy already
> exists.
> +  @retval     EFI_WRITE_PROTECTED     The interface has been locked until
> the next reboot.
> +  @retval     EFI_UNSUPPORTED         Policy enforcement has been disabled.
> No reason to add more policies.
> +  @retval     EFI_ABORTED             A calculation error has prevented this
> function from completing.
> +  @retval     EFI_OUT_OF_RESOURCES    Cannot grow the table to hold any
> more policies.
> +  @retval     EFI_NOT_READY           Library has not yet been initialized.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +RegisterVariablePolicy (
> +  IN CONST VARIABLE_POLICY_ENTRY    *NewPolicy
> +  )
> +{
> +  EFI_STATUS                Status;
> +  VARIABLE_POLICY_ENTRY     *MatchPolicy;
> +  UINT8                     MatchPriority;
> +  UINT32                    NewSize;
> +  UINT8                     *NewTable;
> +
> +  if (!IsVariablePolicyLibInitialized()) {
> +    return EFI_NOT_READY;
> +  }
> +  if (mInterfaceLocked) {
> +    return EFI_WRITE_PROTECTED;
> +  }
> +
> +  if (!IsValidVariablePolicyStructure( NewPolicy )) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  // Check to see whether an exact matching policy already exists.
> +  MatchPolicy = GetBestPolicyMatch( GET_POLICY_NAME( NewPolicy ),
> +                                    &NewPolicy->Namespace,
> +                                    &MatchPriority );
> +  if (MatchPolicy != NULL && MatchPriority == MATCH_PRIORITY_EXACT) {
> +    return EFI_ALREADY_STARTED;
> +  }
> +
> +  // If none exists, create it.
> +  // If we need more space, allocate that now.
> +  Status = SafeUint32Add( mCurrentTableUsage, NewPolicy->Size,
> &NewSize );
> +  if (EFI_ERROR( Status )) {
> +    return EFI_ABORTED;
> +  }
> +  if (NewSize > mCurrentTableSize) {
> +    // Use NewSize to calculate the new table size in units of
> POLICY_TABLE_STEP_SIZE.
> +    NewSize = (NewSize % POLICY_TABLE_STEP_SIZE) > 0 ?
> +                (NewSize / POLICY_TABLE_STEP_SIZE) + 1 :
> +                (NewSize / POLICY_TABLE_STEP_SIZE);
> +    // Calculate the new table size in absolute bytes.
> +    Status = SafeUint32Mult( NewSize, POLICY_TABLE_STEP_SIZE,
> &NewSize );
> +    if (EFI_ERROR( Status )) {
> +      return EFI_ABORTED;
> +    }
> +
> +    // Reallocate and copy the table.
> +    NewTable = AllocatePool( NewSize );
> +    if (NewTable == NULL) {
> +      return EFI_OUT_OF_RESOURCES;
> +    }
> +    CopyMem( NewTable, mPolicyTable, mCurrentTableUsage );
> +    mCurrentTableSize = NewSize;
> +    if (mPolicyTable != NULL) {
> +      FreePool( mPolicyTable );
> +    }
> +    mPolicyTable = NewTable;
> +  }
> +  // Copy the policy into the table.
> +  CopyMem( mPolicyTable + mCurrentTableUsage, NewPolicy, NewPolicy-
> >Size );
> +  mCurrentTableUsage += NewPolicy->Size;
> +  mCurrentTableCount += 1;
> +
> +  // We're done here.
> +
> +  return EFI_SUCCESS;
> +}
> +
> +
> +/**
> +  This API function checks to see whether the parameters to SetVariable
> would
> +  be allowed according to the current variable policies.
> +
> +  @param[in]  VariableName       Same as EFI_SET_VARIABLE.
> +  @param[in]  VendorGuid         Same as EFI_SET_VARIABLE.
> +  @param[in]  Attributes         Same as EFI_SET_VARIABLE.
> +  @param[in]  DataSize           Same as EFI_SET_VARIABLE.
> +  @param[in]  Data               Same as EFI_SET_VARIABLE.
> +
> +  @retval     EFI_SUCCESS             A matching policy allows this update.
> +  @retval     EFI_SUCCESS             There are currently no policies that restrict
> this update.
> +  @retval     EFI_SUCCESS             The protections have been disable until the
> next reboot.
> +  @retval     EFI_WRITE_PROTECTED     Variable is currently locked.
> +  @retval     EFI_INVALID_PARAMETER   Attributes or size are invalid.
> +  @retval     EFI_ABORTED             A lock policy exists, but an error prevented
> evaluation.
> +  @retval     EFI_NOT_READY           Library has not been initialized.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +ValidateSetVariable (
> +  IN  CHAR16                       *VariableName,
> +  IN  EFI_GUID                     *VendorGuid,
> +  IN  UINT32                       Attributes,
> +  IN  UINTN                        DataSize,
> +  IN  VOID                         *Data
> +  )
> +{
> +  BOOLEAN                             IsDel;
> +  VARIABLE_POLICY_ENTRY               *ActivePolicy;
> +  EFI_STATUS                          Status;
> +  EFI_STATUS                          ReturnStatus = EFI_SUCCESS;
> +  VARIABLE_LOCK_ON_VAR_STATE_POLICY   *StateVarPolicy;
> +  CHAR16                              *StateVarName;
> +  UINTN                               StateVarSize;
> +  UINT8                               StateVar;
> +
> +  if (!IsVariablePolicyLibInitialized()) {
> +    ReturnStatus = EFI_NOT_READY;
> +    goto Exit;
> +  }
> +
> +  // Bail if the protections are currently disabled.
> +  if (mProtectionDisabled == TRUE) {
> +    ReturnStatus = EFI_SUCCESS;
> +    goto Exit;
> +  }
> +
> +  // Determine whether this is a delete operation.
> +  // If so, it will affect which tests are applied.
> +  if ((DataSize == 0) && ((Attributes & EFI_VARIABLE_APPEND_WRITE) == 0))
> {
> +    IsDel = TRUE;
> +  }
> +  else {
> +    IsDel = FALSE;
> +  }
> +
> +  // Find an active policy if one exists.
> +  ActivePolicy = GetBestPolicyMatch( VariableName, VendorGuid, NULL );
> +
> +  // If we have an active policy, check it against the incoming data.
> +  if (ActivePolicy != NULL) {
> +    //
> +    // Only enforce size and attribute constraints when updating data, not
> deleting.
> +    if (!IsDel) {
> +      // Check for size constraints.
> +      if ((ActivePolicy->MinSize > 0 && DataSize < ActivePolicy->MinSize) ||
> +          (ActivePolicy->MaxSize > 0 && DataSize > ActivePolicy->MaxSize)) {
> +        ReturnStatus = EFI_INVALID_PARAMETER;
> +        DEBUG(( DEBUG_VERBOSE, "%a - Bad Size. 0x%X <> 0x%X-0x%X\n",
> __FUNCTION__,
> +                DataSize, ActivePolicy->MinSize, ActivePolicy->MaxSize ));
> +        goto Exit;
> +      }
> +
> +      // Check for attribute constraints.
> +      if ((ActivePolicy->AttributesMustHave & Attributes) != ActivePolicy-
> >AttributesMustHave ||
> +          (ActivePolicy->AttributesCantHave & Attributes) != 0) {
> +        ReturnStatus = EFI_INVALID_PARAMETER;
> +        DEBUG(( DEBUG_VERBOSE, "%a - Bad Attributes. 0x%X <>
> 0x%X:0x%X\n", __FUNCTION__,
> +                Attributes, ActivePolicy->AttributesMustHave, ActivePolicy-
> >AttributesCantHave ));
> +        goto Exit;
> +      }
> +    }
> +
> +    //
> +    // Lock policy check.
> +    //
> +    // Check for immediate lock.
> +    if (ActivePolicy->LockPolicyType == VARIABLE_POLICY_TYPE_LOCK_NOW)
> {
> +      ReturnStatus = EFI_WRITE_PROTECTED;
> +      goto Exit;
> +    }
> +    // Check for lock on create.
> +    else if (ActivePolicy->LockPolicyType ==
> VARIABLE_POLICY_TYPE_LOCK_ON_CREATE) {
> +      StateVarSize = 0;
> +      Status = mGetVariableHelper( VariableName,
> +                                   VendorGuid,
> +                                   NULL,
> +                                   &StateVarSize,
> +                                   NULL );
> +      if (Status == EFI_BUFFER_TOO_SMALL) {
> +        ReturnStatus = EFI_WRITE_PROTECTED;
> +        goto Exit;
> +      }
> +    }
> +    // Check for lock on state variable.
> +    else if (ActivePolicy->LockPolicyType ==
> VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE) {
> +      StateVarPolicy =
> (VARIABLE_LOCK_ON_VAR_STATE_POLICY*)((UINT8*)ActivePolicy +
> sizeof(VARIABLE_POLICY_ENTRY));
> +      StateVarName = (CHAR16*)((UINT8*)StateVarPolicy +
> sizeof(VARIABLE_LOCK_ON_VAR_STATE_POLICY));
> +      StateVarSize = sizeof(StateVar);
> +      Status = mGetVariableHelper( StateVarName,
> +                                   &StateVarPolicy->Namespace,
> +                                   NULL,
> +                                   &StateVarSize,
> +                                   &StateVar );
> +
> +      // If the variable was found, check the state. If matched, this variable is
> locked.
> +      if (!EFI_ERROR( Status )) {
> +        if (StateVar == StateVarPolicy->Value) {
> +          ReturnStatus = EFI_WRITE_PROTECTED;
> +          goto Exit;
> +        }
> +      }
> +      // EFI_NOT_FOUND and EFI_BUFFER_TOO_SMALL indicate that the
> state doesn't match.
> +      else if (Status != EFI_NOT_FOUND && Status !=
> EFI_BUFFER_TOO_SMALL) {
> +        // We don't know what happened, but it isn't good.
> +        ReturnStatus = EFI_ABORTED;
> +        goto Exit;
> +      }
> +    }
> +  }
> +
> +Exit:
> +  DEBUG(( DEBUG_VERBOSE, "%a - Variable (%g:%s) returning %r.\n",
> __FUNCTION__, VendorGuid, VariableName, ReturnStatus ));
> +  return ReturnStatus;
> +}
> +
> +
> +/**
> +  This API function disables the variable policy enforcement. If it's
> +  already been called once, will return EFI_ALREADY_STARTED.
> +
> +  @retval     EFI_SUCCESS
> +  @retval     EFI_ALREADY_STARTED   Has already been called once this boot.
> +  @retval     EFI_WRITE_PROTECTED   Interface has been locked until reboot.
> +  @retval     EFI_NOT_READY         Library has not yet been initialized.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +DisableVariablePolicy (
> +  VOID
> +  )
> +{
> +  if (!IsVariablePolicyLibInitialized()) {
> +    return EFI_NOT_READY;
> +  }
> +  if (mProtectionDisabled) {
> +    return EFI_ALREADY_STARTED;
> +  }
> +  if (mInterfaceLocked) {
> +    return EFI_WRITE_PROTECTED;
> +  }
> +  mProtectionDisabled = TRUE;
> +  return EFI_SUCCESS;
> +}
> +
> +
> +/**
> +  This API function will dump the entire contents of the variable policy table.
> +
> +  Similar to GetVariable, the first call can be made with a 0 size and it will
> return
> +  the size of the buffer required to hold the entire table.
> +
> +  @param[out]     Policy  Pointer to the policy buffer. Can be NULL if Size is 0.
> +  @param[in,out]  Size    On input, the size of the output buffer. On output,
> the size
> +                          of the data returned.
> +
> +  @retval     EFI_SUCCESS             Policy data is in the output buffer and Size
> has been updated.
> +  @retval     EFI_INVALID_PARAMETER   Size is NULL, or Size is non-zero and
> Policy is NULL.
> +  @retval     EFI_BUFFER_TOO_SMALL    Size is insufficient to hold policy. Size
> updated with required size.
> +  @retval     EFI_NOT_READY           Library has not yet been initialized.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +DumpVariablePolicy (
> +  OUT     UINT8         *Policy,
> +  IN OUT  UINT32        *Size
> +  )
> +{
> +  if (!IsVariablePolicyLibInitialized()) {
> +    return EFI_NOT_READY;
> +  }
> +
> +  // Check the parameters.
> +  if (Size == NULL || (*Size > 0 && Policy == NULL)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  // Make sure the size is sufficient to hold the policy table.
> +  if (*Size < mCurrentTableUsage) {
> +    *Size = mCurrentTableUsage;
> +    return EFI_BUFFER_TOO_SMALL;
> +  }
> +
> +  // If we're still here, copy the table and bounce.
> +  CopyMem( Policy, mPolicyTable, mCurrentTableUsage );
> +  *Size = mCurrentTableUsage;
> +
> +  return EFI_SUCCESS;
> +}
> +
> +
> +/**
> +  This API function returns whether or not the policy engine is
> +  currently being enforced.
> +
> +  @retval     TRUE
> +  @retval     FALSE
> +  @retval     FALSE         Library has not yet been initialized.
> +
> +**/
> +BOOLEAN
> +EFIAPI
> +IsVariablePolicyEnabled (
> +  VOID
> +  )
> +{
> +  if (!IsVariablePolicyLibInitialized()) {
> +    return FALSE;
> +  }
> +  return !mProtectionDisabled;
> +}
> +
> +
> +/**
> +  This API function locks the interface so that no more policy updates
> +  can be performed or changes made to the enforcement until the next
> boot.
> +
> +  @retval     EFI_SUCCESS
> +  @retval     EFI_NOT_READY   Library has not yet been initialized.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +LockVariablePolicy (
> +  VOID
> +  )
> +{
> +  if (!IsVariablePolicyLibInitialized()) {
> +    return EFI_NOT_READY;
> +  }
> +  if (mInterfaceLocked) {
> +    return EFI_WRITE_PROTECTED;
> +  }
> +  mInterfaceLocked = TRUE;
> +  return EFI_SUCCESS;
> +}
> +
> +
> +/**
> +  This API function returns whether or not the policy interface is locked
> +  for the remainder of the boot.
> +
> +  @retval     TRUE
> +  @retval     FALSE
> +  @retval     FALSE         Library has not yet been initialized.
> +
> +**/
> +BOOLEAN
> +EFIAPI
> +IsVariablePolicyInterfaceLocked (
> +  VOID
> +  )
> +{
> +  if (!IsVariablePolicyLibInitialized()) {
> +    return FALSE;
> +  }
> +  return mInterfaceLocked;
> +}
> +
> +
> +/**
> +  This helper function initializes the library and sets
> +  up any required internal structures or handlers.
> +
> +  Also registers the internal pointer for the GetVariable helper.
> +
> +  @param[in]  GetVariableHelper A function pointer matching the
> EFI_GET_VARIABLE prototype that will be used to
> +                  check policy criteria that involve the existence of other variables.
> +
> +  @retval     EFI_SUCCESS
> +  @retval     EFI_ALREADY_STARTED   The initialize function has been called
> more than once without a call to
> +                                    deinitialize.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +InitVariablePolicyLib (
> +  IN  EFI_GET_VARIABLE    GetVariableHelper
> +  )
> +{
> +  if (mGetVariableHelper != NULL) {
> +    return EFI_ALREADY_STARTED;
> +  }
> +
> +  // Save an internal pointer to the GetVariableHelper.
> +  mGetVariableHelper = GetVariableHelper;
> +
> +  // Initialize the global state.
> +  mInterfaceLocked = FALSE;
> +  mProtectionDisabled = FALSE;
> +  mPolicyTable = NULL;
> +  mCurrentTableSize = 0;
> +  mCurrentTableUsage = 0;
> +  mCurrentTableCount = 0;
> +
> +  return EFI_SUCCESS;
> +}
> +
> +
> +/**
> +  This helper function returns whether or not the library is currently
> initialized.
> +
> +  @retval     TRUE
> +  @retval     FALSE
> +
> +**/
> +BOOLEAN
> +EFIAPI
> +IsVariablePolicyLibInitialized (
> +  VOID
> +  )
> +{
> +  return (mGetVariableHelper != NULL);
> +}
> +
> +
> +/**
> +  This helper function tears down  the library.
> +
> +  Should generally only be used for test harnesses.
> +
> +  @retval     EFI_SUCCESS
> +  @retval     EFI_NOT_READY     Deinitialize was called without first calling
> initialize.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +DeinitVariablePolicyLib (
> +  VOID
> +  )
> +{
> +  if (mGetVariableHelper == NULL) {
> +    return EFI_NOT_READY;
> +  }
> +
> +  mGetVariableHelper = NULL;
> +  mInterfaceLocked = FALSE;
> +  mProtectionDisabled = FALSE;
> +  mCurrentTableSize = 0;
> +  mCurrentTableUsage = 0;
> +  mCurrentTableCount = 0;
> +
> +  if (mPolicyTable != NULL) {
> +    FreePool( mPolicyTable );
> +    mPolicyTable = NULL;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> diff --git
> a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/Variable
> PolicyUnitTest.c
> b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/Variable
> PolicyUnitTest.c
> new file mode 100644
> index 000000000000..3214bff09091
> --- /dev/null
> +++
> b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/Variable
> PolicyUnitTest.c
> @@ -0,0 +1,2285 @@
> +/** @file -- VariablePolicyUnitTest.c
> +UnitTest for...
> +Business logic for Variable Policy enforcement.
> +
> +Copyright (c) Microsoft Corporation.
> +SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include <stdio.h>
> +#include <string.h>
> +#include <stdarg.h>
> +#include <stddef.h>
> +#include <setjmp.h>
> +#include <cmocka.h>
> +
> +#include <Uefi.h>
> +#include <Library/PrintLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/UnitTestLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/BaseLib.h>
> +
> +#include <Guid/VariableFormat.h>
> +
> +#include <Protocol/VariablePolicy.h>
> +#include <Library/VariablePolicyLib.h>
> +
> +// MU_CHANGE - Turn this off for now. Try to turn it back on with extra
> build options.
> +// #ifndef INTERNAL_UNIT_TEST
> +// #error Make sure to build thie with INTERNAL_UNIT_TEST enabled!
> Otherwise, some important tests may be skipped!
> +// #endif
> +
> +
> +#define UNIT_TEST_NAME        "UEFI Variable Policy UnitTest"
> +#define UNIT_TEST_VERSION     "0.5"
> +
> +///=== TEST DATA
> ==========================================================
> ========================
> +
> +#pragma pack(push, 1)
> +typedef struct _SIMPLE_VARIABLE_POLICY_ENTRY {
> +  VARIABLE_POLICY_ENTRY     Header;
> +  CHAR16                    Name[];
> +} SIMPLE_VARIABLE_POLICY_ENTRY;
> +#define EXPANDED_VARIABLE_POLICY_ENTRY_VAR_NAME_LENGTH  1001
> // 1000 characters + terminator.
> +#define EXPANDED_VARIABLE_POLICY_ENTRY_VAR_NAME_SIZE
> (EXPANDED_VARIABLE_POLICY_ENTRY_VAR_NAME_LENGTH *
> sizeof(CHAR16))
> +typedef struct _EXPANDED_VARIABLE_POLICY_ENTRY {
> +  VARIABLE_POLICY_ENTRY               Header;
> +  VARIABLE_LOCK_ON_VAR_STATE_POLICY   StatePolicy;
> +  CHAR16
> StateName[EXPANDED_VARIABLE_POLICY_ENTRY_VAR_NAME_LENGTH];
> +  CHAR16
> Name[EXPANDED_VARIABLE_POLICY_ENTRY_VAR_NAME_LENGTH];
> +} EXPANDED_VARIABLE_POLICY_ENTRY;
> +#pragma pack(pop)
> +
> +// {F955BA2D-4A2C-480C-BFD1-3CC522610592}
> +#define TEST_GUID_1 { 0xf955ba2d, 0x4a2c, 0x480c, { 0xbf, 0xd1, 0x3c, 0xc5,
> 0x22, 0x61, 0x5, 0x92 } }
> +EFI_GUID    mTestGuid1 = TEST_GUID_1;
> +// {2DEA799E-5E73-43B9-870E-C945CE82AF3A}
> +#define TEST_GUID_2 { 0x2dea799e, 0x5e73, 0x43b9, { 0x87, 0xe, 0xc9, 0x45,
> 0xce, 0x82, 0xaf, 0x3a } }
> +EFI_GUID    mTestGuid2 = TEST_GUID_2;
> +// {698A2BFD-A616-482D-B88C-7100BD6682A9}
> +#define TEST_GUID_3 { 0x698a2bfd, 0xa616, 0x482d, { 0xb8, 0x8c, 0x71, 0x0,
> 0xbd, 0x66, 0x82, 0xa9 } }
> +EFI_GUID    mTestGuid3 = TEST_GUID_3;
> +
> +#define   TEST_VAR_1_NAME                 L"TestVar1"
> +#define   TEST_VAR_2_NAME                 L"TestVar2"
> +#define   TEST_VAR_3_NAME                 L"TestVar3"
> +
> +#define   TEST_POLICY_ATTRIBUTES_NULL     0
> +#define   TEST_POLICY_MIN_SIZE_NULL       0
> +#define   TEST_POLICY_MAX_SIZE_NULL       MAX_UINT32
> +
> +#define   TEST_POLICY_MIN_SIZE_10         10
> +#define   TEST_POLICY_MAX_SIZE_200        200
> +
> +#define TEST_300_HASHES_STRING
> L"##################################################"\
> +
> "##################################################"\
> +
> "##################################################"\
> +
> "##################################################"\
> +
> "##################################################"\
> +
> "##################################################"
> +
> +
> +///=== HELPER FUNCTIONS
> ==========================================================
> =================
> +
> +STATIC
> +BOOLEAN
> +InitExpVarPolicyStrings (
> +  EXPANDED_VARIABLE_POLICY_ENTRY      *Entry,
> +  CHAR16                              *Name,      OPTIONAL
> +  CHAR16                              *StateName  OPTIONAL
> +  )
> +{
> +  UINTN     NameSize;
> +  UINTN     StateNameSize;
> +
> +  NameSize = Name == NULL ? 0 : StrSize( Name );
> +  StateNameSize = StateName == NULL ? 0 : StrSize( StateName );
> +
> +  if (NameSize > EXPANDED_VARIABLE_POLICY_ENTRY_VAR_NAME_SIZE ||
> NameSize > MAX_UINT16 ||
> +      StateNameSize >
> EXPANDED_VARIABLE_POLICY_ENTRY_VAR_NAME_SIZE || StateNameSize >
> MAX_UINT16) {
> +    return FALSE;
> +  }
> +
> +  Entry->Header.OffsetToName = sizeof(VARIABLE_POLICY_ENTRY);
> +  if (StateName != NULL) {
> +    Entry->Header.OffsetToName +=
> (UINT16)sizeof(VARIABLE_LOCK_ON_VAR_STATE_POLICY) +
> (UINT16)StateNameSize;
> +  }
> +  Entry->Header.Size = Entry->Header.OffsetToName + (UINT16)NameSize;
> +
> +  CopyMem( (UINT8*)Entry + Entry->Header.OffsetToName, Name,
> NameSize );
> +  if (StateName != NULL) {
> +    CopyMem( (UINT8*)Entry + sizeof(VARIABLE_POLICY_ENTRY) +
> sizeof(VARIABLE_LOCK_ON_VAR_STATE_POLICY), StateName,
> StateNameSize );
> +  }
> +
> +  return TRUE;
> +}
> +
> +EFI_STATUS
> +EFIAPI
> +StubGetVariableNull (
> +  IN     CHAR16                      *VariableName,
> +  IN     EFI_GUID                    *VendorGuid,
> +  OUT    UINT32                      *Attributes,    OPTIONAL
> +  IN OUT UINTN                       *DataSize,
> +  OUT    VOID                        *Data           OPTIONAL
> +  )
> +{
> +  UINT32      MockedAttr;
> +  UINTN       MockedDataSize;
> +  VOID        *MockedData;
> +  EFI_STATUS  MockedReturn;
> +
> +  check_expected_ptr( VariableName );
> +  check_expected_ptr( VendorGuid );
> +  check_expected_ptr( DataSize );
> +
> +  MockedAttr = (UINT32)mock();
> +  MockedDataSize = (UINTN)mock();
> +  MockedData = (VOID*)mock();
> +  MockedReturn = (EFI_STATUS)mock();
> +
> +  if (Attributes) {
> +    *Attributes = MockedAttr;
> +  }
> +  if (Data && !EFI_ERROR(MockedReturn)) {
> +    CopyMem( Data, MockedData, MockedDataSize );
> +  }
> +
> +  *DataSize = MockedDataSize;
> +
> +  return MockedReturn;
> +}
> +
> +//
> +// Anything you think might be helpful that isn't a test itself.
> +//
> +
> +STATIC
> +UNIT_TEST_STATUS
> +LibInitMocked (
> +  IN UNIT_TEST_CONTEXT      Context
> +  )
> +{
> +  return EFI_ERROR(InitVariablePolicyLib( StubGetVariableNull )) ?
> UNIT_TEST_ERROR_PREREQUISITE_NOT_MET : UNIT_TEST_PASSED;
> +}
> +
> +STATIC
> +VOID
> +LibCleanup (
> +  IN UNIT_TEST_CONTEXT      Context
> +  )
> +{
> +  DeinitVariablePolicyLib();
> +}
> +
> +
> +///=== TEST CASES
> ==========================================================
> =======================
> +
> +///===== ARCHITECTURAL SUITE
> ==================================================
> +
> +UNIT_TEST_STATUS
> +EFIAPI
> +ShouldBeAbleToInitAndDeinitTheLibrary (
> +  IN UNIT_TEST_CONTEXT      Context
> +  )
> +{
> +  EFI_STATUS    Status;
> +  Status = InitVariablePolicyLib( StubGetVariableNull );
> +  UT_ASSERT_NOT_EFI_ERROR( Status );
> +
> +  UT_ASSERT_TRUE( IsVariablePolicyLibInitialized() );
> +
> +  Status = DeinitVariablePolicyLib();
> +  UT_ASSERT_NOT_EFI_ERROR( Status );
> +
> +  UT_ASSERT_FALSE( IsVariablePolicyLibInitialized() );
> +
> +  return UNIT_TEST_PASSED;
> +}
> +
> +UNIT_TEST_STATUS
> +EFIAPI
> +ShouldNotBeAbleToInitializeTheLibraryTwice (
> +  IN UNIT_TEST_CONTEXT      Context
> +  )
> +{
> +  EFI_STATUS    Status;
> +  Status = InitVariablePolicyLib( StubGetVariableNull );
> +  UT_ASSERT_NOT_EFI_ERROR( Status );
> +  Status = InitVariablePolicyLib( StubGetVariableNull );
> +  UT_ASSERT_TRUE( EFI_ERROR( Status ) );
> +  return UNIT_TEST_PASSED;
> +}
> +
> +UNIT_TEST_STATUS
> +EFIAPI
> +ShouldFailDeinitWithoutInit (
> +  IN UNIT_TEST_CONTEXT      Context
> +  )
> +{
> +  EFI_STATUS    Status;
> +  Status = DeinitVariablePolicyLib();
> +  UT_ASSERT_TRUE( EFI_ERROR( Status ) );
> +  return UNIT_TEST_PASSED;
> +}
> +
> +UNIT_TEST_STATUS
> +EFIAPI
> +ApiCommandsShouldNotRespondIfLibIsUninitialized (
> +  IN UNIT_TEST_CONTEXT      Context
> +  )
> +{
> +  SIMPLE_VARIABLE_POLICY_ENTRY   TestPolicy = {
> +    {
> +      VARIABLE_POLICY_ENTRY_REVISION,
> +      sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME),
> +      sizeof(VARIABLE_POLICY_ENTRY),
> +      TEST_GUID_1,
> +      TEST_POLICY_MIN_SIZE_NULL,
> +      TEST_POLICY_MAX_SIZE_NULL,
> +      TEST_POLICY_ATTRIBUTES_NULL,
> +      TEST_POLICY_ATTRIBUTES_NULL,
> +      VARIABLE_POLICY_TYPE_NO_LOCK
> +    },
> +    TEST_VAR_1_NAME
> +  };
> +  UINT8     DummyData[8];
> +  UINT32    DummyDataSize = sizeof(DummyData);
> +
> +  // This test should not start with an initialized library.
> +
> +  // Verify that all API commands fail.
> +  UT_ASSERT_TRUE( EFI_ERROR( LockVariablePolicy() ) );
> +  UT_ASSERT_TRUE( EFI_ERROR( DisableVariablePolicy() ) );
> +
> UT_ASSERT_TRUE( EFI_ERROR( RegisterVariablePolicy( &TestPolicy.Header )
> ) );
> +  UT_ASSERT_TRUE( EFI_ERROR( DumpVariablePolicy( DummyData,
> &DummyDataSize ) ) );
> +  UT_ASSERT_FALSE( IsVariablePolicyInterfaceLocked() );
> +  UT_ASSERT_FALSE( IsVariablePolicyEnabled() );
> +  UT_ASSERT_TRUE( EFI_ERROR( ValidateSetVariable( TEST_VAR_1_NAME,
> +                                                 &mTestGuid1,
> +                                                 VARIABLE_ATTRIBUTE_NV_BS,
> +                                                 sizeof(DummyData),
> +                                                 DummyData ) ) );
> +
> +  return UNIT_TEST_PASSED;
> +}
> +
> +
> +///===== INTERNAL FUNCTION SUITE
> ==============================================
> +
> +#ifdef INTERNAL_UNIT_TEST
> +
> +BOOLEAN
> +EvaluatePolicyMatch (
> +  IN CONST  VARIABLE_POLICY_ENTRY   *EvalEntry,
> +  IN CONST  CHAR16                  *VariableName,
> +  IN CONST  EFI_GUID                *VendorGuid,
> +  OUT       UINT8                   *MatchPriority    OPTIONAL
> +  );
> +
> +UNIT_TEST_STATUS
> +EFIAPI
> +PoliciesShouldMatchByNameAndGuid (
> +  IN UNIT_TEST_CONTEXT      Context
> +  )
> +{
> +  SIMPLE_VARIABLE_POLICY_ENTRY   MatchCheckPolicy = {
> +    {
> +      VARIABLE_POLICY_ENTRY_REVISION,
> +      sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME),
> +      sizeof(VARIABLE_POLICY_ENTRY),
> +      TEST_GUID_1,
> +      TEST_POLICY_MIN_SIZE_NULL,
> +      TEST_POLICY_MAX_SIZE_NULL,
> +      TEST_POLICY_ATTRIBUTES_NULL,
> +      TEST_POLICY_ATTRIBUTES_NULL,
> +      VARIABLE_POLICY_TYPE_NO_LOCK
> +    },
> +    TEST_VAR_1_NAME
> +  };
> +  CHAR16        *CheckVar1Name = TEST_VAR_1_NAME;
> +  CHAR16        *CheckVar2Name = TEST_VAR_2_NAME;
> +
> +  // Make sure that a different name does not match.
> +  UT_ASSERT_FALSE( EvaluatePolicyMatch( &MatchCheckPolicy.Header,
> CheckVar2Name, &mTestGuid1, NULL ) );
> +
> +  // Make sure that a different GUID does not match.
> +  UT_ASSERT_FALSE( EvaluatePolicyMatch( &MatchCheckPolicy.Header,
> CheckVar1Name, &mTestGuid2, NULL ) );
> +
> +  // Make sure that the same name and GUID match.
> +  UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolicy.Header,
> CheckVar1Name, &mTestGuid1, NULL ) );
> +
> +  return UNIT_TEST_PASSED;
> +}
> +
> +UNIT_TEST_STATUS
> +EFIAPI
> +WildcardPoliciesShouldMatchDigits (
> +  IN UNIT_TEST_CONTEXT      Context
> +  )
> +{
> +  SIMPLE_VARIABLE_POLICY_ENTRY   MatchCheckPolicy = {
> +    {
> +      VARIABLE_POLICY_ENTRY_REVISION,
> +      sizeof(VARIABLE_POLICY_ENTRY) + sizeof(L"Wildcard#VarName##"),
> +      sizeof(VARIABLE_POLICY_ENTRY),
> +      TEST_GUID_1,
> +      TEST_POLICY_MIN_SIZE_NULL,
> +      TEST_POLICY_MAX_SIZE_NULL,
> +      TEST_POLICY_ATTRIBUTES_NULL,
> +      TEST_POLICY_ATTRIBUTES_NULL,
> +      VARIABLE_POLICY_TYPE_NO_LOCK
> +    },
> +    L"Wildcard#VarName##"
> +  };
> +  CHAR16        *CheckVar1Name = L"Wildcard1VarName12";
> +  CHAR16        *CheckVar2Name = L"Wildcard2VarName34";
> +  CHAR16        *CheckVarBName = L"WildcardBVarName56";
> +  CHAR16        *CheckVarHName = L"Wildcard#VarName56";
> +
> +  // Make sure that two different sets of wildcard numbers match.
> +  UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolicy.Header,
> CheckVar1Name, &mTestGuid1, NULL ) );
> +  UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolicy.Header,
> CheckVar2Name, &mTestGuid1, NULL ) );
> +
> +  // Make sure that the non-number charaters don't match.
> +  UT_ASSERT_FALSE( EvaluatePolicyMatch( &MatchCheckPolicy.Header,
> CheckVarBName, &mTestGuid1, NULL ) );
> +
> +  // Make sure that '#' signs don't match.
> +  UT_ASSERT_FALSE( EvaluatePolicyMatch( &MatchCheckPolicy.Header,
> CheckVarHName, &mTestGuid1, NULL ) );
> +
> +  return UNIT_TEST_PASSED;
> +}
> +
> +UNIT_TEST_STATUS
> +EFIAPI
> +WildcardPoliciesShouldMatchDigitsAdvanced (
> +  IN UNIT_TEST_CONTEXT      Context
> +  )
> +{
> +  SIMPLE_VARIABLE_POLICY_ENTRY   MatchCheckPolicy = {
> +    {
> +      VARIABLE_POLICY_ENTRY_REVISION,
> +      sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_300_HASHES_STRING),
> +      sizeof(VARIABLE_POLICY_ENTRY),
> +      TEST_GUID_1,
> +      TEST_POLICY_MIN_SIZE_NULL,
> +      TEST_POLICY_MAX_SIZE_NULL,
> +      TEST_POLICY_ATTRIBUTES_NULL,
> +      TEST_POLICY_ATTRIBUTES_NULL,
> +      VARIABLE_POLICY_TYPE_NO_LOCK
> +    },
> +    TEST_300_HASHES_STRING
> +  };
> +  CHAR16        *CheckShorterString =
> L"01234567890123456789012345678901234567890123456789";
> +  CHAR16        *CheckValidString =
> L"01234567890123456789012345678901234567890123456789"\
> +
> "01234567890123456789012345678901234567890123456789"\
> +
> "01234567890123456789012345678901234567890123456789"\
> +
> "01234567890123456789012345678901234567890123456789"\
> +
> "01234567890123456789012345678901234567890123456789"\
> +
> "01234567890123456789012345678901234567890123456789";
> +  CHAR16        *CheckLongerString =
> L"01234567890123456789012345678901234567890123456789"\
> +
> "01234567890123456789012345678901234567890123456789"\
> +
> "01234567890123456789012345678901234567890123456789"\
> +
> "01234567890123456789012345678901234567890123456789"\
> +
> "01234567890123456789012345678901234567890123456789"\
> +
> "01234567890123456789012345678901234567890123456789"\
> +
> "01234567890123456789012345678901234567890123456789";
> +  UINT8         MatchPriority;
> +
> +  // Make sure that the shorter and the longer do not match.
> +  UT_ASSERT_FALSE( EvaluatePolicyMatch( &MatchCheckPolicy.Header,
> CheckShorterString, &mTestGuid1, NULL ) );
> +  UT_ASSERT_FALSE( EvaluatePolicyMatch( &MatchCheckPolicy.Header,
> CheckLongerString, &mTestGuid1, NULL ) );
> +
> +  // Make sure that the valid one matches and has the expected priority.
> +  UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolicy.Header,
> CheckValidString, &mTestGuid1, &MatchPriority ) );
> +  UT_ASSERT_EQUAL( MatchPriority, MAX_UINT8 );
> +
> +  return UNIT_TEST_PASSED;
> +}
> +
> +UNIT_TEST_STATUS
> +EFIAPI
> +WildcardPoliciesShouldMatchNamespaces (
> +  IN UNIT_TEST_CONTEXT      Context
> +  )
> +{
> +  VARIABLE_POLICY_ENTRY   MatchCheckPolicy = {
> +    VARIABLE_POLICY_ENTRY_REVISION,
> +    sizeof(VARIABLE_POLICY_ENTRY),
> +    sizeof(VARIABLE_POLICY_ENTRY),
> +    TEST_GUID_1,
> +    TEST_POLICY_MIN_SIZE_NULL,
> +    TEST_POLICY_MAX_SIZE_NULL,
> +    TEST_POLICY_ATTRIBUTES_NULL,
> +    TEST_POLICY_ATTRIBUTES_NULL,
> +    VARIABLE_POLICY_TYPE_NO_LOCK
> +  };
> +  CHAR16        *CheckVar1Name = L"Wildcard1VarName12";
> +  CHAR16        *CheckVar2Name = L"Wildcard2VarName34";
> +  CHAR16        *CheckVarBName = L"WildcardBVarName56";
> +  CHAR16        *CheckVarHName = L"Wildcard#VarName56";
> +
> +  // Make sure that all names in the same namespace match.
> +  UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolicy,
> CheckVar1Name, &mTestGuid1, NULL ) );
> +  UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolicy,
> CheckVar2Name, &mTestGuid1, NULL ) );
> +  UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolicy,
> CheckVarBName, &mTestGuid1, NULL ) );
> +  UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolicy,
> CheckVarHName, &mTestGuid1, NULL ) );
> +
> +  // Make sure that different namespace doesn't match.
> +  UT_ASSERT_FALSE( EvaluatePolicyMatch( &MatchCheckPolicy,
> CheckVar1Name, &mTestGuid2, NULL ) );
> +
> +
> +  return UNIT_TEST_PASSED;
> +}
> +
> +UNIT_TEST_STATUS
> +EFIAPI
> +MatchPrioritiesShouldFollowRules (
> +  IN UNIT_TEST_CONTEXT      Context
> +  )
> +{
> +  SIMPLE_VARIABLE_POLICY_ENTRY   MatchCheckPolicy = {
> +    {
> +      VARIABLE_POLICY_ENTRY_REVISION,
> +      sizeof(VARIABLE_POLICY_ENTRY) + sizeof(L"Wildcard1VarName12"),
> +      sizeof(VARIABLE_POLICY_ENTRY),
> +      TEST_GUID_1,
> +      TEST_POLICY_MIN_SIZE_NULL,
> +      TEST_POLICY_MAX_SIZE_NULL,
> +      TEST_POLICY_ATTRIBUTES_NULL,
> +      TEST_POLICY_ATTRIBUTES_NULL,
> +      VARIABLE_POLICY_TYPE_NO_LOCK
> +    },
> +    L"Wildcard1VarName12"
> +  };
> +  CHAR16        CheckVar1Name[] = L"Wildcard1VarName12";
> +  CHAR16        MatchVar1Name[] = L"Wildcard1VarName12";
> +  CHAR16        MatchVar2Name[] = L"Wildcard#VarName12";
> +  CHAR16        MatchVar3Name[] = L"Wildcard#VarName#2";
> +  CHAR16        MatchVar4Name[] = L"Wildcard#VarName##";
> +  UINT8         MatchPriority;
> +
> +  // Check with a perfect match.
> +  CopyMem( &MatchCheckPolicy.Name, MatchVar1Name,
> sizeof(MatchVar1Name) );
> +  UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolicy.Header,
> CheckVar1Name, &mTestGuid1, &MatchPriority ) );
> +  UT_ASSERT_EQUAL( MatchPriority, 0 );
> +
> +  // Check with progressively lower priority matches.
> +  CopyMem( &MatchCheckPolicy.Name, MatchVar2Name,
> sizeof(MatchVar2Name) );
> +  UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolicy.Header,
> CheckVar1Name, &mTestGuid1, &MatchPriority ) );
> +  UT_ASSERT_EQUAL( MatchPriority, 1 );
> +  CopyMem( &MatchCheckPolicy.Name, MatchVar3Name,
> sizeof(MatchVar3Name) );
> +  UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolicy.Header,
> CheckVar1Name, &mTestGuid1, &MatchPriority ) );
> +  UT_ASSERT_EQUAL( MatchPriority, 2 );
> +  CopyMem( &MatchCheckPolicy.Name, MatchVar4Name,
> sizeof(MatchVar4Name) );
> +  UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolicy.Header,
> CheckVar1Name, &mTestGuid1, &MatchPriority ) );
> +  UT_ASSERT_EQUAL( MatchPriority, 3 );
> +
> +  // Check against the entire namespace.
> +  MatchCheckPolicy.Header.Size = sizeof(VARIABLE_POLICY_ENTRY);
> +  UT_ASSERT_TRUE( EvaluatePolicyMatch( &MatchCheckPolicy.Header,
> CheckVar1Name, &mTestGuid1, &MatchPriority ) );
> +  UT_ASSERT_EQUAL( MatchPriority, MAX_UINT8 );
> +
> +  return UNIT_TEST_PASSED;
> +}
> +
> +#endif // INTERNAL_UNIT_TEST
> +
> +
> +///=== POLICY MANIPULATION SUITE
> ==============================================
> +
> +UNIT_TEST_STATUS
> +EFIAPI
> +RegisterShouldAllowNamespaceWildcards (
> +  IN UNIT_TEST_CONTEXT      Context
> +  )
> +{
> +  SIMPLE_VARIABLE_POLICY_ENTRY   ValidationPolicy = {
> +    {
> +      VARIABLE_POLICY_ENTRY_REVISION,
> +      sizeof(VARIABLE_POLICY_ENTRY),
> +      sizeof(VARIABLE_POLICY_ENTRY),
> +      TEST_GUID_1,
> +      TEST_POLICY_MIN_SIZE_NULL,
> +      TEST_POLICY_MAX_SIZE_NULL,
> +      TEST_POLICY_ATTRIBUTES_NULL,
> +      TEST_POLICY_ATTRIBUTES_NULL,
> +      VARIABLE_POLICY_TYPE_NO_LOCK
> +    },
> +    L""
> +  };
> +
> +
> UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea
> der ) );
> +
> +  return UNIT_TEST_PASSED;
> +}
> +
> +UNIT_TEST_STATUS
> +EFIAPI
> +RegisterShouldAllowStateVarsForNamespaces (
> +  IN UNIT_TEST_CONTEXT      Context
> +  )
> +{
> +  EXPANDED_VARIABLE_POLICY_ENTRY   ValidationPolicy = {
> +    {
> +      VARIABLE_POLICY_ENTRY_REVISION,
> +      0,    // Will be populated by init helper.
> +      0,    // Will be populated by init helper.
> +      TEST_GUID_1,
> +      TEST_POLICY_MIN_SIZE_NULL,
> +      TEST_POLICY_MAX_SIZE_NULL,
> +      TEST_POLICY_ATTRIBUTES_NULL,
> +      TEST_POLICY_ATTRIBUTES_NULL,
> +      VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE
> +    },
> +    {
> +      TEST_GUID_2,
> +      1,            // Value
> +      0             // Padding
> +    },
> +    L"",
> +    L""
> +  };
> +  UT_ASSERT_TRUE( InitExpVarPolicyStrings( &ValidationPolicy, NULL,
> TEST_VAR_2_NAME ) );
> +
> +
> UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea
> der ) );
> +
> +  return UNIT_TEST_PASSED;
> +}
> +
> +UNIT_TEST_STATUS
> +EFIAPI
> +RegisterShouldRejectNullPointers (
> +  IN UNIT_TEST_CONTEXT      Context
> +  )
> +{
> +  UT_ASSERT_EQUAL( RegisterVariablePolicy( NULL ),
> EFI_INVALID_PARAMETER );
> +  return UNIT_TEST_PASSED;
> +}
> +
> +UNIT_TEST_STATUS
> +EFIAPI
> +RegisterShouldRejectBadRevisions (
> +  IN UNIT_TEST_CONTEXT      Context
> +  )
> +{
> +  SIMPLE_VARIABLE_POLICY_ENTRY   ValidationPolicy = {
> +    {
> +      VARIABLE_POLICY_ENTRY_REVISION,
> +      sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME),
> +      sizeof(VARIABLE_POLICY_ENTRY),
> +      TEST_GUID_1,
> +      TEST_POLICY_MIN_SIZE_NULL,
> +      TEST_POLICY_MAX_SIZE_NULL,
> +      TEST_POLICY_ATTRIBUTES_NULL,
> +      TEST_POLICY_ATTRIBUTES_NULL,
> +      VARIABLE_POLICY_TYPE_NO_LOCK
> +    },
> +    TEST_VAR_1_NAME
> +  };
> +
> +  ValidationPolicy.Header.Version = MAX_UINT32;
> +  UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ),
> EFI_INVALID_PARAMETER );
> +
> +  return UNIT_TEST_PASSED;
> +}
> +
> +UNIT_TEST_STATUS
> +EFIAPI
> +RegisterShouldRejectBadSizes (
> +  IN UNIT_TEST_CONTEXT      Context
> +  )
> +{
> +  SIMPLE_VARIABLE_POLICY_ENTRY   ValidationPolicy = {
> +    {
> +      VARIABLE_POLICY_ENTRY_REVISION,
> +      sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME),
> +      sizeof(VARIABLE_POLICY_ENTRY),
> +      TEST_GUID_1,
> +      TEST_POLICY_MIN_SIZE_NULL,
> +      TEST_POLICY_MAX_SIZE_NULL,
> +      TEST_POLICY_ATTRIBUTES_NULL,
> +      TEST_POLICY_ATTRIBUTES_NULL,
> +      VARIABLE_POLICY_TYPE_NO_LOCK
> +    },
> +    TEST_VAR_1_NAME
> +  };
> +
> +  ValidationPolicy.Header.Size = sizeof(VARIABLE_POLICY_ENTRY) - 2;
> +  UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ),
> EFI_INVALID_PARAMETER );
> +
> +  return UNIT_TEST_PASSED;
> +}
> +
> +UNIT_TEST_STATUS
> +EFIAPI
> +RegisterShouldRejectBadOffsets (
> +  IN UNIT_TEST_CONTEXT      Context
> +  )
> +{
> +  EXPANDED_VARIABLE_POLICY_ENTRY   ValidationPolicy = {
> +    {
> +      VARIABLE_POLICY_ENTRY_REVISION,
> +      0,    // Will be populated by init helper.
> +      0,    // Will be populated by init helper.
> +      TEST_GUID_1,
> +      TEST_POLICY_MIN_SIZE_NULL,
> +      TEST_POLICY_MAX_SIZE_NULL,
> +      TEST_POLICY_ATTRIBUTES_NULL,
> +      TEST_POLICY_ATTRIBUTES_NULL,
> +      VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE
> +    },
> +    {
> +      TEST_GUID_2,
> +      1,            // Value
> +      0             // Padding
> +    },
> +    L"",
> +    L""
> +  };
> +  UT_ASSERT_TRUE( InitExpVarPolicyStrings( &ValidationPolicy,
> TEST_VAR_1_NAME, TEST_VAR_2_NAME ) );
> +
> +  // Check for an offset outside the size bounds.
> +  ValidationPolicy.Header.OffsetToName = ValidationPolicy.Header.Size + 1;
> +  UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ),
> EFI_INVALID_PARAMETER );
> +
> +  // Check for an offset inside the policy header.
> +  ValidationPolicy.Header.OffsetToName = sizeof(VARIABLE_POLICY_ENTRY)
> - 2;
> +  UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ),
> EFI_INVALID_PARAMETER );
> +
> +  // Check for an offset inside the state policy header.
> +  ValidationPolicy.Header.OffsetToName = sizeof(VARIABLE_POLICY_ENTRY)
> + 2;
> +  UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ),
> EFI_INVALID_PARAMETER );
> +
> +  // Check for a ridiculous offset.
> +  ValidationPolicy.Header.OffsetToName = MAX_UINT16;
> +  UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ),
> EFI_INVALID_PARAMETER );
> +
> +  return UNIT_TEST_PASSED;
> +}
> +
> +UNIT_TEST_STATUS
> +EFIAPI
> +RegisterShouldRejectMissingStateStrings (
> +  IN UNIT_TEST_CONTEXT      Context
> +  )
> +{
> +  EXPANDED_VARIABLE_POLICY_ENTRY   ValidationPolicy = {
> +    {
> +      VARIABLE_POLICY_ENTRY_REVISION,
> +      0,    // Will be populated by init helper.
> +      0,    // Will be populated by init helper.
> +      TEST_GUID_1,
> +      TEST_POLICY_MIN_SIZE_NULL,
> +      TEST_POLICY_MAX_SIZE_NULL,
> +      TEST_POLICY_ATTRIBUTES_NULL,
> +      TEST_POLICY_ATTRIBUTES_NULL,
> +      VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE
> +    },
> +    {
> +      TEST_GUID_2,
> +      1,            // Value
> +      0             // Padding
> +    },
> +    L"",
> +    L""
> +  };
> +  UT_ASSERT_TRUE( InitExpVarPolicyStrings( &ValidationPolicy,
> TEST_VAR_1_NAME, TEST_VAR_2_NAME ) );
> +
> +  // Remove the state string and copy the Name into it's place.
> +  // Also adjust the offset.
> +  ValidationPolicy.Header.Size          = sizeof(VARIABLE_POLICY_ENTRY) +
> sizeof(VARIABLE_LOCK_ON_VAR_STATE_POLICY) +
> sizeof(TEST_VAR_1_NAME);
> +  ValidationPolicy.Header.OffsetToName  = sizeof(VARIABLE_POLICY_ENTRY)
> + sizeof(VARIABLE_LOCK_ON_VAR_STATE_POLICY);
> +  CopyMem( (UINT8*)&ValidationPolicy +
> ValidationPolicy.Header.OffsetToName, TEST_VAR_1_NAME,
> sizeof(TEST_VAR_1_NAME) );
> +
> +  // Make sure that this structure fails.
> +  UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ),
> EFI_INVALID_PARAMETER );
> +
> +  return UNIT_TEST_PASSED;
> +}
> +
> +UNIT_TEST_STATUS
> +EFIAPI
> +RegisterShouldRejectStringsMissingNull (
> +  IN UNIT_TEST_CONTEXT      Context
> +  )
> +{
> +  EXPANDED_VARIABLE_POLICY_ENTRY   ValidationPolicy = {
> +    {
> +      VARIABLE_POLICY_ENTRY_REVISION,
> +      0,    // Will be populated by init helper.
> +      0,    // Will be populated by init helper.
> +      TEST_GUID_1,
> +      TEST_POLICY_MIN_SIZE_NULL,
> +      TEST_POLICY_MAX_SIZE_NULL,
> +      TEST_POLICY_ATTRIBUTES_NULL,
> +      TEST_POLICY_ATTRIBUTES_NULL,
> +      VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE
> +    },
> +    {
> +      TEST_GUID_2,
> +      1,            // Value
> +      0             // Padding
> +    },
> +    L"",
> +    L""
> +  };
> +  UT_ASSERT_TRUE( InitExpVarPolicyStrings( &ValidationPolicy,
> TEST_VAR_1_NAME, TEST_VAR_2_NAME ) );
> +
> +  // Removing the NULL from the Name should fail.
> +  ValidationPolicy.Header.Size = ValidationPolicy.Header.Size -
> sizeof(CHAR16);
> +  UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ),
> EFI_INVALID_PARAMETER );
> +
> +  // Removing the NULL from the State Name is a little trickier.
> +  // Copy the Name up one byte.
> +  ValidationPolicy.Header.OffsetToName =
> ValidationPolicy.Header.OffsetToName - sizeof(CHAR16);
> +  CopyMem( (UINT8*)&ValidationPolicy +
> ValidationPolicy.Header.OffsetToName, TEST_VAR_1_NAME,
> sizeof(TEST_VAR_1_NAME) );
> +  UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ),
> EFI_INVALID_PARAMETER );
> +
> +  return UNIT_TEST_PASSED;
> +}
> +
> +UNIT_TEST_STATUS
> +EFIAPI
> +RegisterShouldRejectMalformedStrings (
> +  IN UNIT_TEST_CONTEXT      Context
> +  )
> +{
> +  EXPANDED_VARIABLE_POLICY_ENTRY   ValidationPolicy = {
> +    {
> +      VARIABLE_POLICY_ENTRY_REVISION,
> +      0,    // Will be populated by init helper.
> +      0,    // Will be populated by init helper.
> +      TEST_GUID_1,
> +      TEST_POLICY_MIN_SIZE_NULL,
> +      TEST_POLICY_MAX_SIZE_NULL,
> +      TEST_POLICY_ATTRIBUTES_NULL,
> +      TEST_POLICY_ATTRIBUTES_NULL,
> +      VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE
> +    },
> +    {
> +      TEST_GUID_2,
> +      1,            // Value
> +      0             // Padding
> +    },
> +    L"",
> +    L""
> +  };
> +  UT_ASSERT_TRUE( InitExpVarPolicyStrings( &ValidationPolicy,
> TEST_VAR_1_NAME, TEST_VAR_2_NAME ) );
> +
> +  // Bisecting the NULL from the Name should fail.
> +  ValidationPolicy.Header.Size = ValidationPolicy.Header.Size - 1;
> +  UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ),
> EFI_INVALID_PARAMETER );
> +
> +  // Bisecting the NULL from the State Name is a little trickier.
> +  // Copy the Name up one byte.
> +  ValidationPolicy.Header.OffsetToName =
> ValidationPolicy.Header.OffsetToName - 1;
> +  CopyMem( (UINT8*)&ValidationPolicy +
> ValidationPolicy.Header.OffsetToName, TEST_VAR_1_NAME,
> sizeof(TEST_VAR_1_NAME) );
> +  UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ),
> EFI_INVALID_PARAMETER );
> +
> +  return UNIT_TEST_PASSED;
> +}
> +
> +UNIT_TEST_STATUS
> +EFIAPI
> +RegisterShouldRejectUnpackedPolicies (
> +  IN UNIT_TEST_CONTEXT      Context
> +  )
> +{
> +  EXPANDED_VARIABLE_POLICY_ENTRY   ValidationPolicy = {
> +    {
> +      VARIABLE_POLICY_ENTRY_REVISION,
> +      0,    // Will be populated by init helper.
> +      0,    // Will be populated by init helper.
> +      TEST_GUID_1,
> +      TEST_POLICY_MIN_SIZE_NULL,
> +      TEST_POLICY_MAX_SIZE_NULL,
> +      TEST_POLICY_ATTRIBUTES_NULL,
> +      TEST_POLICY_ATTRIBUTES_NULL,
> +      VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE
> +    },
> +    {
> +      TEST_GUID_2,
> +      1,            // Value
> +      0             // Padding
> +    },
> +    L"",
> +    L""
> +  };
> +  UT_ASSERT_TRUE( InitExpVarPolicyStrings( &ValidationPolicy,
> TEST_VAR_1_NAME, TEST_VAR_2_NAME ) );
> +
> +  // Increase the size and move the Name out a bit.
> +  ValidationPolicy.Header.Size = ValidationPolicy.Header.Size +
> sizeof(CHAR16);
> +  ValidationPolicy.Header.OffsetToName =
> ValidationPolicy.Header.OffsetToName + sizeof(CHAR16);
> +  CopyMem( (UINT8*)&ValidationPolicy +
> ValidationPolicy.Header.OffsetToName, TEST_VAR_1_NAME,
> sizeof(TEST_VAR_1_NAME) );
> +  UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ),
> EFI_INVALID_PARAMETER );
> +
> +  // Reintialize without the state policy and try the same test.
> +  ValidationPolicy.Header.LockPolicyType =
> VARIABLE_POLICY_TYPE_NO_LOCK;
> +  UT_ASSERT_TRUE( InitExpVarPolicyStrings( &ValidationPolicy,
> TEST_VAR_1_NAME, NULL ) );
> +  ValidationPolicy.Header.Size = ValidationPolicy.Header.Size +
> sizeof(CHAR16);
> +  ValidationPolicy.Header.OffsetToName =
> ValidationPolicy.Header.OffsetToName + sizeof(CHAR16);
> +  CopyMem( (UINT8*)&ValidationPolicy +
> ValidationPolicy.Header.OffsetToName, TEST_VAR_1_NAME,
> sizeof(TEST_VAR_1_NAME) );
> +  UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ),
> EFI_INVALID_PARAMETER );
> +
> +  return UNIT_TEST_PASSED;
> +}
> +
> +UNIT_TEST_STATUS
> +EFIAPI
> +RegisterShouldRejectInvalidNameCharacters (
> +  IN UNIT_TEST_CONTEXT      Context
> +  )
> +{
> +  // EXPANDED_VARIABLE_POLICY_ENTRY   ValidationPolicy = {
> +  //   {
> +  //     VARIABLE_POLICY_ENTRY_REVISION,
> +  //     0,    // Will be populated by init helper.
> +  //     0,    // Will be populated by init helper.
> +  //     TEST_GUID_1,
> +  //     TEST_POLICY_MIN_SIZE_NULL,
> +  //     TEST_POLICY_MAX_SIZE_NULL,
> +  //     TEST_POLICY_ATTRIBUTES_NULL,
> +  //     TEST_POLICY_ATTRIBUTES_NULL,
> +  //     VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE
> +  //   },
> +  //   {
> +  //     TEST_GUID_2,
> +  //     1,            // Value
> +  //     0             // Padding
> +  //   },
> +  //   L"",
> +  //   L""
> +  // };
> +
> +  // Currently, there are no known invalid characters.
> +  // '#' in LockPolicy->Name are taken as literal.
> +
> +  return UNIT_TEST_PASSED;
> +}
> +
> +UNIT_TEST_STATUS
> +EFIAPI
> +RegisterShouldRejectBadPolicyConstraints (
> +  IN UNIT_TEST_CONTEXT      Context
> +  )
> +{
> +  SIMPLE_VARIABLE_POLICY_ENTRY   ValidationPolicy = {
> +    {
> +      VARIABLE_POLICY_ENTRY_REVISION,
> +      sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME),
> +      sizeof(VARIABLE_POLICY_ENTRY),
> +      TEST_GUID_1,
> +      TEST_POLICY_MIN_SIZE_NULL,
> +      TEST_POLICY_MAX_SIZE_NULL,
> +      TEST_POLICY_ATTRIBUTES_NULL,
> +      TEST_POLICY_ATTRIBUTES_NULL,
> +      VARIABLE_POLICY_TYPE_NO_LOCK
> +    },
> +    TEST_VAR_1_NAME
> +  };
> +
> +  // Make sure that invalid MAXes are rejected.
> +  ValidationPolicy.Header.MaxSize = 0;
> +  UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ),
> EFI_INVALID_PARAMETER );
> +
> +  return UNIT_TEST_PASSED;
> +}
> +
> +UNIT_TEST_STATUS
> +EFIAPI
> +RegisterShouldRejectUnknownLockPolicies (
> +  IN UNIT_TEST_CONTEXT      Context
> +  )
> +{
> +  SIMPLE_VARIABLE_POLICY_ENTRY   ValidationPolicy = {
> +    {
> +      VARIABLE_POLICY_ENTRY_REVISION,
> +      sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME),
> +      sizeof(VARIABLE_POLICY_ENTRY),
> +      TEST_GUID_1,
> +      TEST_POLICY_MIN_SIZE_NULL,
> +      TEST_POLICY_MAX_SIZE_NULL,
> +      TEST_POLICY_ATTRIBUTES_NULL,
> +      TEST_POLICY_ATTRIBUTES_NULL,
> +      VARIABLE_POLICY_TYPE_NO_LOCK
> +    },
> +    TEST_VAR_1_NAME
> +  };
> +
> +  ValidationPolicy.Header.LockPolicyType =
> VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE + 1;
> +  UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ),
> EFI_INVALID_PARAMETER );
> +  ValidationPolicy.Header.LockPolicyType =
> VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE + 1;
> +  UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ),
> EFI_INVALID_PARAMETER );
> +
> +  return UNIT_TEST_PASSED;
> +}
> +
> +UNIT_TEST_STATUS
> +EFIAPI
> +RegisterShouldRejectPolicesWithTooManyWildcards (
> +  IN UNIT_TEST_CONTEXT      Context
> +  )
> +{
> +  SIMPLE_VARIABLE_POLICY_ENTRY   ValidationPolicy = {
> +    {
> +      VARIABLE_POLICY_ENTRY_REVISION,
> +      sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_300_HASHES_STRING),
> +      sizeof(VARIABLE_POLICY_ENTRY),
> +      TEST_GUID_1,
> +      TEST_POLICY_MIN_SIZE_NULL,
> +      TEST_POLICY_MAX_SIZE_NULL,
> +      TEST_POLICY_ATTRIBUTES_NULL,
> +      TEST_POLICY_ATTRIBUTES_NULL,
> +      VARIABLE_POLICY_TYPE_NO_LOCK
> +    },
> +    TEST_300_HASHES_STRING
> +  };
> +
> +  // 300 Hashes is currently larger than the possible maximum match priority.
> +  UT_ASSERT_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ),
> EFI_INVALID_PARAMETER );
> +
> +  return UNIT_TEST_PASSED;
> +}
> +
> +UNIT_TEST_STATUS
> +EFIAPI
> +RegisterShouldRejectDuplicatePolicies (
> +  IN UNIT_TEST_CONTEXT      Context
> +  )
> +{
> +  SIMPLE_VARIABLE_POLICY_ENTRY   ValidationPolicy = {
> +    {
> +      VARIABLE_POLICY_ENTRY_REVISION,
> +      sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME),
> +      sizeof(VARIABLE_POLICY_ENTRY),
> +      TEST_GUID_1,
> +      TEST_POLICY_MIN_SIZE_NULL,
> +      TEST_POLICY_MAX_SIZE_NULL,
> +      TEST_POLICY_ATTRIBUTES_NULL,
> +      TEST_POLICY_ATTRIBUTES_NULL,
> +      VARIABLE_POLICY_TYPE_NO_LOCK
> +    },
> +    TEST_VAR_1_NAME
> +  };
> +
> +
> UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea
> der ) );
> +
> UT_ASSERT_STATUS_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Head
> er ), EFI_ALREADY_STARTED );
> +
> +  return UNIT_TEST_PASSED;
> +}
> +
> +UNIT_TEST_STATUS
> +EFIAPI
> +MinAndMaxSizePoliciesShouldBeHonored (
> +  IN UNIT_TEST_CONTEXT      Context
> +  )
> +{
> +  SIMPLE_VARIABLE_POLICY_ENTRY   ValidationPolicy = {
> +    {
> +      VARIABLE_POLICY_ENTRY_REVISION,
> +      sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME),
> +      sizeof(VARIABLE_POLICY_ENTRY),
> +      TEST_GUID_1,
> +      TEST_POLICY_MIN_SIZE_10,
> +      TEST_POLICY_MAX_SIZE_200,
> +      TEST_POLICY_ATTRIBUTES_NULL,
> +      TEST_POLICY_ATTRIBUTES_NULL,
> +      VARIABLE_POLICY_TYPE_NO_LOCK
> +    },
> +    TEST_VAR_1_NAME
> +  };
> +  EFI_STATUS  PolicyCheck;
> +  UINT8       DummyData[TEST_POLICY_MAX_SIZE_200+1];
> +
> +
> +  // Without a policy, there should be no constraints on variable creation.
> +  PolicyCheck = ValidateSetVariable( TEST_VAR_1_NAME,
> +                                    &mTestGuid1,
> +                                    VARIABLE_ATTRIBUTE_NV_BS,
> +                                    TEST_POLICY_MAX_SIZE_200+1,
> +                                    DummyData );
> +  UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );
> +
> +  // Set a policy to test against.
> +
> UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea
> der ) );
> +
> +  // With a policy, make sure that sizes outsize the target range fail.
> +  PolicyCheck = ValidateSetVariable( TEST_VAR_1_NAME,
> +                                    &mTestGuid1,
> +                                    VARIABLE_ATTRIBUTE_NV_BS,
> +                                    TEST_POLICY_MAX_SIZE_200+1,
> +                                    DummyData );
> +  UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) );
> +
> +  // With a policy, make sure that sizes outsize the target range fail.
> +  PolicyCheck = ValidateSetVariable( TEST_VAR_1_NAME,
> +                                    &mTestGuid1,
> +                                    VARIABLE_ATTRIBUTE_NV_BS,
> +                                    TEST_POLICY_MIN_SIZE_10-1,
> +                                    DummyData );
> +  UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) );
> +
> +  // With a policy, make sure a valid variable is still valid.
> +  PolicyCheck = ValidateSetVariable( TEST_VAR_1_NAME,
> +                                    &mTestGuid1,
> +                                    VARIABLE_ATTRIBUTE_NV_BS,
> +                                    TEST_POLICY_MIN_SIZE_10+1,
> +                                    DummyData );
> +  UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );
> +
> +  return UNIT_TEST_PASSED;
> +}
> +
> +UNIT_TEST_STATUS
> +EFIAPI
> +AttributeMustPoliciesShouldBeHonored (
> +  IN UNIT_TEST_CONTEXT      Context
> +  )
> +{
> +  SIMPLE_VARIABLE_POLICY_ENTRY   ValidationPolicy = {
> +    {
> +      VARIABLE_POLICY_ENTRY_REVISION,
> +      sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME),
> +      sizeof(VARIABLE_POLICY_ENTRY),
> +      TEST_GUID_1,
> +      TEST_POLICY_MIN_SIZE_NULL,
> +      TEST_POLICY_MAX_SIZE_NULL,
> +      VARIABLE_ATTRIBUTE_NV_BS_RT,
> +      TEST_POLICY_ATTRIBUTES_NULL,
> +      VARIABLE_POLICY_TYPE_NO_LOCK
> +    },
> +    TEST_VAR_1_NAME
> +  };
> +  EFI_STATUS  PolicyCheck;
> +  UINT8       DummyData[12];
> +
> +
> +  // Without a policy, there should be no constraints on variable creation.
> +  PolicyCheck = ValidateSetVariable( TEST_VAR_1_NAME,
> +                                    &mTestGuid1,
> +                                    TEST_POLICY_ATTRIBUTES_NULL,
> +                                    sizeof(DummyData),
> +                                    DummyData );
> +  UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );
> +
> +  // Set a policy to test against.
> +
> UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea
> der ) );
> +
> +  // With a policy, make sure that no attributes fail.
> +  PolicyCheck = ValidateSetVariable( TEST_VAR_1_NAME,
> +                                    &mTestGuid1,
> +                                    TEST_POLICY_ATTRIBUTES_NULL,
> +                                    sizeof(DummyData),
> +                                    DummyData );
> +  UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) );
> +
> +  // With a policy, make sure that some -- but not all -- attributes fail.
> +  PolicyCheck = ValidateSetVariable( TEST_VAR_1_NAME,
> +                                    &mTestGuid1,
> +                                    VARIABLE_ATTRIBUTE_BS_RT_AT,
> +                                    sizeof(DummyData),
> +                                    DummyData );
> +  UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) );
> +
> +  // With a policy, make sure that all attributes pass.
> +  PolicyCheck = ValidateSetVariable( TEST_VAR_1_NAME,
> +                                    &mTestGuid1,
> +                                    VARIABLE_ATTRIBUTE_NV_BS_RT,
> +                                    sizeof(DummyData),
> +                                    DummyData );
> +  UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );
> +
> +  // With a policy, make sure that all attributes -- plus some -- pass.
> +  PolicyCheck = ValidateSetVariable( TEST_VAR_1_NAME,
> +                                    &mTestGuid1,
> +                                    VARIABLE_ATTRIBUTE_NV_BS_RT_AT,
> +                                    sizeof(DummyData),
> +                                    DummyData );
> +  UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );
> +
> +  return UNIT_TEST_PASSED;
> +}
> +
> +UNIT_TEST_STATUS
> +EFIAPI
> +AttributeCantPoliciesShouldBeHonored (
> +  IN UNIT_TEST_CONTEXT      Context
> +  )
> +{
> +  SIMPLE_VARIABLE_POLICY_ENTRY   ValidationPolicy = {
> +    {
> +      VARIABLE_POLICY_ENTRY_REVISION,
> +      sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME),
> +      sizeof(VARIABLE_POLICY_ENTRY),
> +      TEST_GUID_1,
> +      TEST_POLICY_MIN_SIZE_NULL,
> +      TEST_POLICY_MAX_SIZE_NULL,
> +      TEST_POLICY_ATTRIBUTES_NULL,
> +      EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS,
> +      VARIABLE_POLICY_TYPE_NO_LOCK
> +    },
> +    TEST_VAR_1_NAME
> +  };
> +  EFI_STATUS  PolicyCheck;
> +  UINT8       DummyData[12];
> +
> +
> +  // Without a policy, there should be no constraints on variable creation.
> +  PolicyCheck = ValidateSetVariable( TEST_VAR_1_NAME,
> +                                    &mTestGuid1,
> +                                    VARIABLE_ATTRIBUTE_BS_RT_AT,
> +                                    sizeof(DummyData),
> +                                    DummyData );
> +  UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );
> +
> +  // Set a policy to test against.
> +
> UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea
> der ) );
> +
> +  // With a policy, make sure that forbidden attributes fail.
> +  PolicyCheck = ValidateSetVariable( TEST_VAR_1_NAME,
> +                                    &mTestGuid1,
> +
> EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS,
> +                                    sizeof(DummyData),
> +                                    DummyData );
> +  UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) );
> +
> +  // With a policy, make sure that a mixture of attributes -- including the
> forbidden -- fail.
> +  PolicyCheck = ValidateSetVariable( TEST_VAR_1_NAME,
> +                                    &mTestGuid1,
> +                                    VARIABLE_ATTRIBUTE_BS_RT_AT,
> +                                    sizeof(DummyData),
> +                                    DummyData );
> +  UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) );
> +
> +  // With a policy, make sure that attributes without the forbidden pass.
> +  PolicyCheck = ValidateSetVariable( TEST_VAR_1_NAME,
> +                                    &mTestGuid1,
> +                                    VARIABLE_ATTRIBUTE_NV_BS_RT,
> +                                    sizeof(DummyData),
> +                                    DummyData );
> +  UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );
> +
> +  return UNIT_TEST_PASSED;
> +}
> +
> +UNIT_TEST_STATUS
> +EFIAPI
> +VariablesShouldBeDeletableRegardlessOfSize (
> +  IN UNIT_TEST_CONTEXT      Context
> +  )
> +{
> +  SIMPLE_VARIABLE_POLICY_ENTRY   ValidationPolicy = {
> +    {
> +      VARIABLE_POLICY_ENTRY_REVISION,
> +      sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME),
> +      sizeof(VARIABLE_POLICY_ENTRY),
> +      TEST_GUID_1,
> +      TEST_POLICY_MIN_SIZE_10,
> +      TEST_POLICY_MAX_SIZE_NULL,
> +      TEST_POLICY_ATTRIBUTES_NULL,
> +      EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS,
> +      VARIABLE_POLICY_TYPE_NO_LOCK
> +    },
> +    TEST_VAR_1_NAME
> +  };
> +  EFI_STATUS  PolicyCheck;
> +  UINT8       DummyData[TEST_POLICY_MAX_SIZE_200+1];
> +
> +  // Create a policy enforcing a minimum variable size.
> +
> UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea
> der ) );
> +
> +  // Make sure that a normal set would fail.
> +  PolicyCheck = ValidateSetVariable( TEST_VAR_1_NAME,
> +                                    &mTestGuid1,
> +                                    VARIABLE_ATTRIBUTE_NV_BS,
> +                                    TEST_POLICY_MIN_SIZE_10-1,
> +                                    DummyData );
> +  UT_ASSERT_STATUS_EQUAL( PolicyCheck, EFI_INVALID_PARAMETER );
> +
> +  // Now make sure that a delete would succeed.
> +  PolicyCheck = ValidateSetVariable( TEST_VAR_1_NAME,
> +                                    &mTestGuid1,
> +                                    VARIABLE_ATTRIBUTE_NV_BS,
> +                                    0,
> +                                    NULL );
> +  UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );
> +
> +  return UNIT_TEST_PASSED;
> +}
> +
> +UNIT_TEST_STATUS
> +EFIAPI
> +LockNowPoliciesShouldBeHonored (
> +  IN UNIT_TEST_CONTEXT      Context
> +  )
> +{
> +  SIMPLE_VARIABLE_POLICY_ENTRY   ValidationPolicy = {
> +    {
> +      VARIABLE_POLICY_ENTRY_REVISION,
> +      sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME),
> +      sizeof(VARIABLE_POLICY_ENTRY),
> +      TEST_GUID_1,
> +      TEST_POLICY_MIN_SIZE_NULL,
> +      TEST_POLICY_MAX_SIZE_NULL,
> +      TEST_POLICY_ATTRIBUTES_NULL,
> +      TEST_POLICY_ATTRIBUTES_NULL,
> +      VARIABLE_POLICY_TYPE_LOCK_NOW
> +    },
> +    TEST_VAR_1_NAME
> +  };
> +  EFI_STATUS  PolicyCheck;
> +  UINT8       DummyData[12];
> +
> +
> +  // Without a policy, there should be no constraints on variable creation.
> +  PolicyCheck = ValidateSetVariable( TEST_VAR_1_NAME,
> +                                    &mTestGuid1,
> +                                    VARIABLE_ATTRIBUTE_BS_RT_AT,
> +                                    sizeof(DummyData),
> +                                    DummyData );
> +  UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );
> +
> +  // Set a policy to test against.
> +
> UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea
> der ) );
> +
> +  // With a policy, make sure that writes immediately fail.
> +  PolicyCheck = ValidateSetVariable( TEST_VAR_1_NAME,
> +                                    &mTestGuid1,
> +                                    VARIABLE_ATTRIBUTE_BS_RT_AT,
> +                                    sizeof(DummyData),
> +                                    DummyData );
> +  UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) );
> +
> +  return UNIT_TEST_PASSED;
> +}
> +
> +UNIT_TEST_STATUS
> +EFIAPI
> +LockOnCreatePoliciesShouldBeHonored (
> +  IN UNIT_TEST_CONTEXT      Context
> +  )
> +{
> +  SIMPLE_VARIABLE_POLICY_ENTRY   ValidationPolicy = {
> +    {
> +      VARIABLE_POLICY_ENTRY_REVISION,
> +      sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME),
> +      sizeof(VARIABLE_POLICY_ENTRY),
> +      TEST_GUID_1,
> +      TEST_POLICY_MIN_SIZE_NULL,
> +      TEST_POLICY_MAX_SIZE_NULL,
> +      TEST_POLICY_ATTRIBUTES_NULL,
> +      TEST_POLICY_ATTRIBUTES_NULL,
> +      VARIABLE_POLICY_TYPE_LOCK_ON_CREATE
> +    },
> +    TEST_VAR_1_NAME
> +  };
> +  EFI_STATUS  PolicyCheck;
> +  UINT8       DummyData[12];
> +  UINTN       ExpectedDataSize;
> +
> +
> +  // Without a policy, there should be no constraints on variable creation.
> +  PolicyCheck = ValidateSetVariable( TEST_VAR_1_NAME,
> +                                    &mTestGuid1,
> +                                    VARIABLE_ATTRIBUTE_BS_RT_AT,
> +                                    sizeof(DummyData),
> +                                    DummyData );
> +  UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );
> +
> +  // Set a policy to test against.
> +
> UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea
> der ) );
> +
> +  // Set consistent expectations on what the calls are looking for.
> +  expect_memory_count( StubGetVariableNull, VariableName,
> TEST_VAR_1_NAME, sizeof(TEST_VAR_1_NAME), 2 );
> +  expect_memory_count( StubGetVariableNull, VendorGuid, &mTestGuid1,
> sizeof(mTestGuid1), 2 );
> +  ExpectedDataSize = 0;
> +  expect_memory_count( StubGetVariableNull, DataSize,
> &ExpectedDataSize, sizeof(ExpectedDataSize), 2 );
> +
> +  // With a policy, make sure that writes still work, since the variable doesn't
> exist.
> +  will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL );    //
> Attributes
> +  will_return( StubGetVariableNull, 0 );                              // Size
> +  will_return( StubGetVariableNull, NULL );                           // DataPtr
> +  will_return( StubGetVariableNull, EFI_NOT_FOUND );                  // Status
> +  PolicyCheck = ValidateSetVariable( TEST_VAR_1_NAME,
> +                                    &mTestGuid1,
> +                                    VARIABLE_ATTRIBUTE_BS_RT_AT,
> +                                    sizeof(DummyData),
> +                                    DummyData );
> +  UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );
> +
> +  // With a policy, make sure that a call with an "existing" variable fails.
> +  will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL );    //
> Attributes
> +  will_return( StubGetVariableNull, 10 );                             // Size
> +  will_return( StubGetVariableNull, NULL );                           // DataPtr
> +  will_return( StubGetVariableNull, EFI_BUFFER_TOO_SMALL );           //
> Status
> +  PolicyCheck = ValidateSetVariable( TEST_VAR_1_NAME,
> +                                    &mTestGuid1,
> +                                    VARIABLE_ATTRIBUTE_BS_RT_AT,
> +                                    sizeof(DummyData),
> +                                    DummyData );
> +  UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) );
> +
> +  return UNIT_TEST_PASSED;
> +}
> +
> +UNIT_TEST_STATUS
> +EFIAPI
> +LockOnStatePoliciesShouldBeHonored (
> +  IN UNIT_TEST_CONTEXT      Context
> +  )
> +{
> +  EXPANDED_VARIABLE_POLICY_ENTRY   ValidationPolicy = {
> +    {
> +      VARIABLE_POLICY_ENTRY_REVISION,
> +      0,    // Will be populated by init helper.
> +      0,    // Will be populated by init helper.
> +      TEST_GUID_1,
> +      TEST_POLICY_MIN_SIZE_NULL,
> +      TEST_POLICY_MAX_SIZE_NULL,
> +      TEST_POLICY_ATTRIBUTES_NULL,
> +      TEST_POLICY_ATTRIBUTES_NULL,
> +      VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE
> +    },
> +    {
> +      TEST_GUID_2,
> +      20,           // Value
> +      0             // Padding
> +    },
> +    L"",
> +    L""
> +  };
> +  EFI_STATUS  PolicyCheck;
> +  UINT8       DummyData[12];
> +  UINT8       ValidationStateVar;
> +  UINTN       ExpectedDataSize;
> +  UT_ASSERT_TRUE( InitExpVarPolicyStrings( &ValidationPolicy,
> TEST_VAR_1_NAME, TEST_VAR_2_NAME ) );
> +
> +
> +  // Without a policy, there should be no constraints on variable creation.
> +  PolicyCheck = ValidateSetVariable( TEST_VAR_1_NAME,
> +                                    &mTestGuid1,
> +                                    VARIABLE_ATTRIBUTE_BS_RT_AT,
> +                                    sizeof(DummyData),
> +                                    DummyData );
> +  UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );
> +
> +  // Set a policy to test against.
> +
> UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea
> der ) );
> +
> +  // Set consistent expectations on what the calls are looking for.
> +  expect_memory_count( StubGetVariableNull, VariableName,
> TEST_VAR_2_NAME, sizeof(TEST_VAR_2_NAME), 5 );
> +  expect_memory_count( StubGetVariableNull, VendorGuid, &mTestGuid2,
> sizeof(mTestGuid2), 5 );
> +  ExpectedDataSize = 1;
> +  expect_memory_count( StubGetVariableNull, DataSize,
> &ExpectedDataSize, sizeof(ExpectedDataSize), 5 );
> +
> +  // With a policy, make sure that writes still work, since the variable doesn't
> exist.
> +  will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL );    //
> Attributes
> +  will_return( StubGetVariableNull, 0 );                              // Size
> +  will_return( StubGetVariableNull, NULL );                           // DataPtr
> +  will_return( StubGetVariableNull, EFI_NOT_FOUND );                  // Status
> +  PolicyCheck = ValidateSetVariable( TEST_VAR_1_NAME,
> +                                    &mTestGuid1,
> +                                    VARIABLE_ATTRIBUTE_BS_RT_AT,
> +                                    sizeof(DummyData),
> +                                    DummyData );
> +  UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );
> +
> +  // With a policy, make sure that a state variable that's too large doesn't lock
> the variable.
> +  will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL );    //
> Attributes
> +  will_return( StubGetVariableNull, 10 );                             // Size
> +  will_return( StubGetVariableNull, NULL );                           // DataPtr
> +  will_return( StubGetVariableNull, EFI_BUFFER_TOO_SMALL );           //
> Status
> +  PolicyCheck = ValidateSetVariable( TEST_VAR_1_NAME,
> +                                    &mTestGuid1,
> +                                    VARIABLE_ATTRIBUTE_BS_RT_AT,
> +                                    sizeof(DummyData),
> +                                    DummyData );
> +  UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );
> +
> +  // With a policy, check a state variable with the wrong value.
> +  ValidationStateVar = 0;
> +  will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL );    //
> Attributes
> +  will_return( StubGetVariableNull, sizeof(ValidationStateVar) );     // Size
> +  will_return( StubGetVariableNull, &ValidationStateVar );            // DataPtr
> +  will_return( StubGetVariableNull, EFI_SUCCESS );                    // Status
> +  PolicyCheck = ValidateSetVariable( TEST_VAR_1_NAME,
> +                                    &mTestGuid1,
> +                                    VARIABLE_ATTRIBUTE_BS_RT_AT,
> +                                    sizeof(DummyData),
> +                                    DummyData );
> +  UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );
> +
> +  // With a policy, check a state variable with another wrong value.
> +  ValidationStateVar = 10;
> +  will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL );    //
> Attributes
> +  will_return( StubGetVariableNull, sizeof(ValidationStateVar) );     // Size
> +  will_return( StubGetVariableNull, &ValidationStateVar );            // DataPtr
> +  will_return( StubGetVariableNull, EFI_SUCCESS );                    // Status
> +  PolicyCheck = ValidateSetVariable( TEST_VAR_1_NAME,
> +                                    &mTestGuid1,
> +                                    VARIABLE_ATTRIBUTE_BS_RT_AT,
> +                                    sizeof(DummyData),
> +                                    DummyData );
> +  UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );
> +
> +  // With a policy, make sure that a call with a correct state variable fails.
> +  ValidationStateVar = 20;
> +  will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL );    //
> Attributes
> +  will_return( StubGetVariableNull, sizeof(ValidationStateVar) );     // Size
> +  will_return( StubGetVariableNull, &ValidationStateVar );            // DataPtr
> +  will_return( StubGetVariableNull, EFI_SUCCESS );                    // Status
> +  PolicyCheck = ValidateSetVariable( TEST_VAR_1_NAME,
> +                                    &mTestGuid1,
> +                                    VARIABLE_ATTRIBUTE_BS_RT_AT,
> +                                    sizeof(DummyData),
> +                                    DummyData );
> +  UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) );
> +
> +  return UNIT_TEST_PASSED;
> +}
> +
> +UNIT_TEST_STATUS
> +EFIAPI
> +LockOnStatePoliciesShouldApplyToNamespaces (
> +  IN UNIT_TEST_CONTEXT      Context
> +  )
> +{
> +  EXPANDED_VARIABLE_POLICY_ENTRY   ValidationPolicy = {
> +    {
> +      VARIABLE_POLICY_ENTRY_REVISION,
> +      0,    // Will be populated by init helper.
> +      0,    // Will be populated by init helper.
> +      TEST_GUID_1,
> +      TEST_POLICY_MIN_SIZE_NULL,
> +      TEST_POLICY_MAX_SIZE_NULL,
> +      TEST_POLICY_ATTRIBUTES_NULL,
> +      TEST_POLICY_ATTRIBUTES_NULL,
> +      VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE
> +    },
> +    {
> +      TEST_GUID_2,
> +      20,           // Value
> +      0             // Padding
> +    },
> +    L"",
> +    L""
> +  };
> +  EFI_STATUS  PolicyCheck;
> +  UINT8       DummyData[12];
> +  UINT8       ValidationStateVar;
> +  UINTN       ExpectedDataSize;
> +  UT_ASSERT_TRUE( InitExpVarPolicyStrings( &ValidationPolicy, NULL,
> TEST_VAR_2_NAME ) );
> +
> +
> +  // Without a policy, there should be no constraints on variable creation.
> +  PolicyCheck = ValidateSetVariable( TEST_VAR_1_NAME,
> +                                    &mTestGuid1,
> +                                    VARIABLE_ATTRIBUTE_BS_RT_AT,
> +                                    sizeof(DummyData),
> +                                    DummyData );
> +  UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );
> +  PolicyCheck = ValidateSetVariable( TEST_VAR_3_NAME,
> +                                    &mTestGuid1,
> +                                    VARIABLE_ATTRIBUTE_BS_RT_AT,
> +                                    sizeof(DummyData),
> +                                    DummyData );
> +  UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );
> +
> +  // Set a policy to test against.
> +
> UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea
> der ) );
> +
> +  // Set consistent expectations on what the calls are looking for.
> +  expect_memory_count( StubGetVariableNull, VariableName,
> TEST_VAR_2_NAME, sizeof(TEST_VAR_2_NAME), 4 );
> +  expect_memory_count( StubGetVariableNull, VendorGuid, &mTestGuid2,
> sizeof(mTestGuid2), 4 );
> +  ExpectedDataSize = 1;
> +  expect_memory_count( StubGetVariableNull, DataSize,
> &ExpectedDataSize, sizeof(ExpectedDataSize), 4 );
> +
> +  // With a policy, make sure that writes still work, since the variable doesn't
> exist.
> +  will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL );    //
> Attributes
> +  will_return( StubGetVariableNull, 0 );                              // Size
> +  will_return( StubGetVariableNull, NULL );                           // DataPtr
> +  will_return( StubGetVariableNull, EFI_NOT_FOUND );                  // Status
> +  PolicyCheck = ValidateSetVariable( TEST_VAR_1_NAME,
> +                                    &mTestGuid1,
> +                                    VARIABLE_ATTRIBUTE_BS_RT_AT,
> +                                    sizeof(DummyData),
> +                                    DummyData );
> +  UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );
> +  will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL );    //
> Attributes
> +  will_return( StubGetVariableNull, 0 );                              // Size
> +  will_return( StubGetVariableNull, NULL );                           // DataPtr
> +  will_return( StubGetVariableNull, EFI_NOT_FOUND );                  // Status
> +  PolicyCheck = ValidateSetVariable( TEST_VAR_3_NAME,
> +                                    &mTestGuid1,
> +                                    VARIABLE_ATTRIBUTE_BS_RT_AT,
> +                                    sizeof(DummyData),
> +                                    DummyData );
> +  UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );
> +
> +  // With a policy, make sure that a call with a correct state variable fails.
> +  ValidationStateVar = 20;
> +  will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL );    //
> Attributes
> +  will_return( StubGetVariableNull, sizeof(ValidationStateVar) );     // Size
> +  will_return( StubGetVariableNull, &ValidationStateVar );            // DataPtr
> +  will_return( StubGetVariableNull, EFI_SUCCESS );                    // Status
> +  PolicyCheck = ValidateSetVariable( TEST_VAR_1_NAME,
> +                                    &mTestGuid1,
> +                                    VARIABLE_ATTRIBUTE_BS_RT_AT,
> +                                    sizeof(DummyData),
> +                                    DummyData );
> +  UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) );
> +  will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL );    //
> Attributes
> +  will_return( StubGetVariableNull, sizeof(ValidationStateVar) );     // Size
> +  will_return( StubGetVariableNull, &ValidationStateVar );            // DataPtr
> +  will_return( StubGetVariableNull, EFI_SUCCESS );                    // Status
> +  PolicyCheck = ValidateSetVariable( TEST_VAR_3_NAME,
> +                                    &mTestGuid1,
> +                                    VARIABLE_ATTRIBUTE_BS_RT_AT,
> +                                    sizeof(DummyData),
> +                                    DummyData );
> +  UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) );
> +
> +  return UNIT_TEST_PASSED;
> +}
> +
> +UNIT_TEST_STATUS
> +EFIAPI
> +LockOnStateShouldHandleErrorsGracefully (
> +  IN UNIT_TEST_CONTEXT      Context
> +  )
> +{
> +  EXPANDED_VARIABLE_POLICY_ENTRY   ValidationPolicy = {
> +    {
> +      VARIABLE_POLICY_ENTRY_REVISION,
> +      0,    // Will be populated by init helper.
> +      0,    // Will be populated by init helper.
> +      TEST_GUID_1,
> +      TEST_POLICY_MIN_SIZE_NULL,
> +      TEST_POLICY_MAX_SIZE_NULL,
> +      TEST_POLICY_ATTRIBUTES_NULL,
> +      TEST_POLICY_ATTRIBUTES_NULL,
> +      VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE
> +    },
> +    {
> +      TEST_GUID_2,
> +      20,           // Value
> +      0             // Padding
> +    },
> +    L"",
> +    L""
> +  };
> +  EFI_STATUS  PolicyCheck;
> +  UINT8       DummyData[12];
> +  UT_ASSERT_TRUE( InitExpVarPolicyStrings( &ValidationPolicy,
> TEST_VAR_1_NAME, TEST_VAR_2_NAME ) );
> +
> +
> +  // Without a policy, there should be no constraints on variable creation.
> +  PolicyCheck = ValidateSetVariable( TEST_VAR_1_NAME,
> +                                    &mTestGuid1,
> +                                    VARIABLE_ATTRIBUTE_BS_RT_AT,
> +                                    sizeof(DummyData),
> +                                    DummyData );
> +  UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );
> +
> +  // Set a policy to test against.
> +
> UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea
> der ) );
> +
> +  // Configure the stub to not care about parameters. We're testing errors.
> +  expect_any_always( StubGetVariableNull, VariableName );
> +  expect_any_always( StubGetVariableNull, VendorGuid );
> +  expect_any_always( StubGetVariableNull, DataSize );
> +
> +  // With a policy, make sure that writes still work, since the variable doesn't
> exist.
> +  will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL );    //
> Attributes
> +  will_return( StubGetVariableNull, 0 );                              // Size
> +  will_return( StubGetVariableNull, NULL );                           // DataPtr
> +  will_return( StubGetVariableNull, EFI_NOT_FOUND );                  // Status
> +  PolicyCheck = ValidateSetVariable( TEST_VAR_1_NAME,
> +                                    &mTestGuid1,
> +                                    VARIABLE_ATTRIBUTE_BS_RT_AT,
> +                                    sizeof(DummyData),
> +                                    DummyData );
> +  UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );
> +
> +  // Verify that state variables that are the wrong size won't lock the variable.
> +  will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL );    //
> Attributes
> +  will_return( StubGetVariableNull, 0 );                              // Size
> +  will_return( StubGetVariableNull, NULL );                           // DataPtr
> +  will_return( StubGetVariableNull, EFI_BUFFER_TOO_SMALL );           //
> Status
> +  PolicyCheck = ValidateSetVariable( TEST_VAR_1_NAME,
> +                                    &mTestGuid1,
> +                                    VARIABLE_ATTRIBUTE_BS_RT_AT,
> +                                    sizeof(DummyData),
> +                                    DummyData );
> +  UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );
> +
> +  // Verify that unexpected errors default to locked.
> +  will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL );    //
> Attributes
> +  will_return( StubGetVariableNull, 0 );                              // Size
> +  will_return( StubGetVariableNull, NULL );                           // DataPtr
> +  will_return( StubGetVariableNull, EFI_UNSUPPORTED );                // Status
> +  PolicyCheck = ValidateSetVariable( TEST_VAR_1_NAME,
> +                                    &mTestGuid1,
> +                                    VARIABLE_ATTRIBUTE_BS_RT_AT,
> +                                    sizeof(DummyData),
> +                                    DummyData );
> +  UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) );
> +
> +  will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL );    //
> Attributes
> +  will_return( StubGetVariableNull, 0 );                              // Size
> +  will_return( StubGetVariableNull, NULL );                           // DataPtr
> +  will_return( StubGetVariableNull, EFI_NOT_READY );                  // Status
> +  PolicyCheck = ValidateSetVariable( TEST_VAR_1_NAME,
> +                                    &mTestGuid1,
> +                                    VARIABLE_ATTRIBUTE_BS_RT_AT,
> +                                    sizeof(DummyData),
> +                                    DummyData );
> +  UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) );
> +
> +  return UNIT_TEST_PASSED;
> +}
> +
> +UNIT_TEST_STATUS
> +EFIAPI
> +BestMatchPriorityShouldBeObeyed (
> +  IN UNIT_TEST_CONTEXT      Context
> +  )
> +{
> +  SIMPLE_VARIABLE_POLICY_ENTRY   ValidationPolicy = {
> +    {
> +      VARIABLE_POLICY_ENTRY_REVISION,
> +      sizeof(VARIABLE_POLICY_ENTRY) + sizeof(L"Wild12Card34Placeholder"),
> +      sizeof(VARIABLE_POLICY_ENTRY),
> +      TEST_GUID_1,
> +      TEST_POLICY_MIN_SIZE_NULL,
> +      TEST_POLICY_MAX_SIZE_NULL,
> +      TEST_POLICY_ATTRIBUTES_NULL,
> +      TEST_POLICY_ATTRIBUTES_NULL,
> +      VARIABLE_POLICY_TYPE_NO_LOCK
> +    },
> +    L"Wild12Card34Placeholder"
> +  };
> +  EFI_STATUS  PolicyCheck;
> +  UINT8       DummyData[70];
> +  CHAR16      *PolicyName = (CHAR16*)((UINT8*)&ValidationPolicy +
> sizeof(VARIABLE_POLICY_ENTRY));
> +  UINTN       PolicyNameSize = sizeof(L"Wild12Card34Placeholder");
> +  CHAR16      *FourWildcards = L"Wild##Card##Placeholder";
> +  CHAR16      *ThreeWildcards = L"Wild##Card#4Placeholder";
> +  CHAR16      *TwoWildcards = L"Wild##Card34Placeholder";
> +  CHAR16      *OneWildcard = L"Wild#2Card34Placeholder";
> +  CHAR16      *NoWildcards = L"Wild12Card34Placeholder";
> +
> +  // Create all of the policies from least restrictive to most restrictive.
> +  // NoWildcards should be the most restrictive.
> +  ValidationPolicy.Header.MaxSize = 60;
> +  ValidationPolicy.Header.Size = ValidationPolicy.Header.OffsetToName;
> +
> UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea
> der ) );
> +  ValidationPolicy.Header.Size += (UINT16)PolicyNameSize;
> +  ValidationPolicy.Header.MaxSize = 50;
> +  CopyMem( PolicyName, FourWildcards, PolicyNameSize );
> +
> UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea
> der ) );
> +  ValidationPolicy.Header.MaxSize = 40;
> +  CopyMem( PolicyName, ThreeWildcards, PolicyNameSize );
> +
> UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea
> der ) );
> +  ValidationPolicy.Header.MaxSize = 30;
> +  CopyMem( PolicyName, TwoWildcards, PolicyNameSize );
> +
> UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea
> der ) );
> +  ValidationPolicy.Header.MaxSize = 20;
> +  CopyMem( PolicyName, OneWildcard, PolicyNameSize );
> +
> UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea
> der ) );
> +  ValidationPolicy.Header.MaxSize = 10;
> +  CopyMem( PolicyName, NoWildcards, PolicyNameSize );
> +
> UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Hea
> der ) );
> +
> +  // Verify that variables only matching the namespace have the most
> flexible policy.
> +  PolicyCheck = ValidateSetVariable( L"ArbitraryName",
> +                                     &mTestGuid1,
> +                                     VARIABLE_ATTRIBUTE_BS_RT_AT,
> +                                     65,
> +                                     DummyData );
> +  UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) );
> +  PolicyCheck = ValidateSetVariable( L"ArbitraryName",
> +                                     &mTestGuid1,
> +                                     VARIABLE_ATTRIBUTE_BS_RT_AT,
> +                                     55,
> +                                     DummyData );
> +  UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );
> +
> +  // Verify that variables matching increasing characters get increasing policy
> restrictions.
> +  PolicyCheck = ValidateSetVariable( L"Wild77Card77Placeholder",
> +                                     &mTestGuid1,
> +                                     VARIABLE_ATTRIBUTE_BS_RT_AT,
> +                                     55,
> +                                     DummyData );
> +  UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) );
> +  PolicyCheck = ValidateSetVariable( L"Wild77Card77Placeholder",
> +                                     &mTestGuid1,
> +                                     VARIABLE_ATTRIBUTE_BS_RT_AT,
> +                                     45,
> +                                     DummyData );
> +  UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );
> +
> +  PolicyCheck = ValidateSetVariable( L"Wild77Card74Placeholder",
> +                                     &mTestGuid1,
> +                                     VARIABLE_ATTRIBUTE_BS_RT_AT,
> +                                     45,
> +                                     DummyData );
> +  UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) );
> +  PolicyCheck = ValidateSetVariable( L"Wild77Card74Placeholder",
> +                                     &mTestGuid1,
> +                                     VARIABLE_ATTRIBUTE_BS_RT_AT,
> +                                     35,
> +                                     DummyData );
> +  UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );
> +
> +  PolicyCheck = ValidateSetVariable( L"Wild77Card34Placeholder",
> +                                     &mTestGuid1,
> +                                     VARIABLE_ATTRIBUTE_BS_RT_AT,
> +                                     35,
> +                                     DummyData );
> +  UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) );
> +  PolicyCheck = ValidateSetVariable( L"Wild77Card34Placeholder",
> +                                     &mTestGuid1,
> +                                     VARIABLE_ATTRIBUTE_BS_RT_AT,
> +                                     25,
> +                                     DummyData );
> +  UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );
> +
> +  PolicyCheck = ValidateSetVariable( L"Wild72Card34Placeholder",
> +                                     &mTestGuid1,
> +                                     VARIABLE_ATTRIBUTE_BS_RT_AT,
> +                                     25,
> +                                     DummyData );
> +  UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) );
> +  PolicyCheck = ValidateSetVariable( L"Wild72Card34Placeholder",
> +                                     &mTestGuid1,
> +                                     VARIABLE_ATTRIBUTE_BS_RT_AT,
> +                                     15,
> +                                     DummyData );
> +  UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );
> +
> +  PolicyCheck = ValidateSetVariable( L"Wild12Card34Placeholder",
> +                                     &mTestGuid1,
> +                                     VARIABLE_ATTRIBUTE_BS_RT_AT,
> +                                     15,
> +                                     DummyData );
> +  UT_ASSERT_TRUE( EFI_ERROR( PolicyCheck ) );
> +  PolicyCheck = ValidateSetVariable( L"Wild12Card34Placeholder",
> +                                     &mTestGuid1,
> +                                     VARIABLE_ATTRIBUTE_BS_RT_AT,
> +                                     5,
> +                                     DummyData );
> +  UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );
> +
> +  return UNIT_TEST_PASSED;
> +}
> +
> +
> +///=== POLICY UTILITY SUITE
> ===================================================
> +
> +UNIT_TEST_STATUS
> +EFIAPI
> +ShouldBeAbleToLockInterface (
> +  IN UNIT_TEST_CONTEXT      Context
> +  )
> +{
> +  SIMPLE_VARIABLE_POLICY_ENTRY   TestPolicy = {
> +    {
> +      VARIABLE_POLICY_ENTRY_REVISION,
> +      sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME),
> +      sizeof(VARIABLE_POLICY_ENTRY),
> +      TEST_GUID_1,
> +      TEST_POLICY_MIN_SIZE_NULL,
> +      TEST_POLICY_MAX_SIZE_NULL,
> +      TEST_POLICY_ATTRIBUTES_NULL,
> +      TEST_POLICY_ATTRIBUTES_NULL,
> +      VARIABLE_POLICY_TYPE_NO_LOCK
> +    },
> +    TEST_VAR_1_NAME
> +  };
> +
> +  // Make sure it's not already locked.
> +  UT_ASSERT_FALSE( IsVariablePolicyInterfaceLocked() );
> +  // Lock it.
> +  UT_ASSERT_NOT_EFI_ERROR( LockVariablePolicy() );
> +  // Verify that it's locked.
> +  UT_ASSERT_TRUE( IsVariablePolicyInterfaceLocked() );
> +
> +  // Verify that all state-changing commands fail.
> +  UT_ASSERT_TRUE( EFI_ERROR( LockVariablePolicy() ) );
> +  UT_ASSERT_TRUE( EFI_ERROR( DisableVariablePolicy() ) );
> +
> UT_ASSERT_TRUE( EFI_ERROR( RegisterVariablePolicy( &TestPolicy.Header )
> ) );
> +
> +  return UNIT_TEST_PASSED;
> +}
> +
> +UNIT_TEST_STATUS
> +EFIAPI
> +ShouldBeAbleToDisablePolicyEnforcement (
> +  IN UNIT_TEST_CONTEXT      Context
> +  )
> +{
> +  SIMPLE_VARIABLE_POLICY_ENTRY   TestPolicy = {
> +    {
> +      VARIABLE_POLICY_ENTRY_REVISION,
> +      sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME),
> +      sizeof(VARIABLE_POLICY_ENTRY),
> +      TEST_GUID_1,
> +      TEST_POLICY_MIN_SIZE_10,
> +      TEST_POLICY_MAX_SIZE_200,
> +      TEST_POLICY_ATTRIBUTES_NULL,
> +      TEST_POLICY_ATTRIBUTES_NULL,
> +      VARIABLE_POLICY_TYPE_NO_LOCK
> +    },
> +    TEST_VAR_1_NAME
> +  };
> +  EFI_STATUS  PolicyCheck;
> +  UINT8       DummyData[TEST_POLICY_MIN_SIZE_10-1];
> +
> +  // Make sure that the policy enforcement is currently enabled.
> +  UT_ASSERT_TRUE( IsVariablePolicyEnabled() );
> +  // Add a policy before it's disabled.
> +
> UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &TestPolicy.Header ) );
> +  // Disable the policy enforcement.
> +  UT_ASSERT_NOT_EFI_ERROR( DisableVariablePolicy() );
> +  // Make sure that the policy enforcement is currently disabled.
> +  UT_ASSERT_FALSE( IsVariablePolicyEnabled() );
> +
> +  // Check to make sure that a policy violation still passes.
> +  PolicyCheck = ValidateSetVariable( TEST_VAR_1_NAME,
> +                                    &mTestGuid1,
> +                                    VARIABLE_ATTRIBUTE_NV_BS,
> +                                    sizeof(DummyData),
> +                                    DummyData );
> +  UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );
> +
> +  return UNIT_TEST_PASSED;
> +}
> +
> +UNIT_TEST_STATUS
> +EFIAPI
> +ShouldNotBeAbleToDisablePoliciesTwice (
> +  IN UNIT_TEST_CONTEXT      Context
> +  )
> +{
> +  // Make sure that the policy enforcement is currently enabled.
> +  UT_ASSERT_TRUE( IsVariablePolicyEnabled() );
> +  // Disable the policy enforcement.
> +  UT_ASSERT_NOT_EFI_ERROR( DisableVariablePolicy() );
> +  // Make sure that the policy enforcement is currently disabled.
> +  UT_ASSERT_FALSE( IsVariablePolicyEnabled() );
> +  // Try to disable again and verify failure.
> +  UT_ASSERT_TRUE( EFI_ERROR( DisableVariablePolicy() ) );
> +
> +  return UNIT_TEST_PASSED;
> +}
> +
> +UNIT_TEST_STATUS
> +EFIAPI
> +ShouldBeAbleToAddNewPoliciesAfterDisabled (
> +  IN UNIT_TEST_CONTEXT      Context
> +  )
> +{
> +  SIMPLE_VARIABLE_POLICY_ENTRY   TestPolicy = {
> +    {
> +      VARIABLE_POLICY_ENTRY_REVISION,
> +      sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME),
> +      sizeof(VARIABLE_POLICY_ENTRY),
> +      TEST_GUID_1,
> +      TEST_POLICY_MIN_SIZE_10,
> +      TEST_POLICY_MAX_SIZE_200,
> +      TEST_POLICY_ATTRIBUTES_NULL,
> +      TEST_POLICY_ATTRIBUTES_NULL,
> +      VARIABLE_POLICY_TYPE_NO_LOCK
> +    },
> +    TEST_VAR_1_NAME
> +  };
> +  EFI_STATUS  PolicyCheck;
> +
> +  // Make sure that the policy enforcement is currently enabled.
> +  UT_ASSERT_TRUE( IsVariablePolicyEnabled() );
> +  // Disable the policy enforcement.
> +  UT_ASSERT_NOT_EFI_ERROR( DisableVariablePolicy() );
> +
> +  // Make sure that new policy creation still works, it just won't be enforced.
> +  PolicyCheck = RegisterVariablePolicy( &TestPolicy.Header );
> +  UT_ASSERT_NOT_EFI_ERROR( PolicyCheck );
> +
> +  return UNIT_TEST_PASSED;
> +}
> +
> +UNIT_TEST_STATUS
> +EFIAPI
> +ShouldBeAbleToLockAfterDisabled (
> +  IN UNIT_TEST_CONTEXT      Context
> +  )
> +{
> +  // Make sure that the policy enforcement is currently enabled.
> +  UT_ASSERT_TRUE( IsVariablePolicyEnabled() );
> +  // Disable the policy enforcement.
> +  UT_ASSERT_NOT_EFI_ERROR( DisableVariablePolicy() );
> +
> +  // Make sure that we can lock in this state.
> +  UT_ASSERT_FALSE( IsVariablePolicyInterfaceLocked() );
> +  UT_ASSERT_NOT_EFI_ERROR( LockVariablePolicy() );
> +  UT_ASSERT_TRUE( IsVariablePolicyInterfaceLocked() );
> +
> +  return UNIT_TEST_PASSED;
> +}
> +
> +UNIT_TEST_STATUS
> +EFIAPI
> +ShouldBeAbleToDumpThePolicyTable (
> +  IN UNIT_TEST_CONTEXT      Context
> +  )
> +{
> +  SIMPLE_VARIABLE_POLICY_ENTRY   TestPolicy = {
> +    {
> +      VARIABLE_POLICY_ENTRY_REVISION,
> +      sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME),
> +      sizeof(VARIABLE_POLICY_ENTRY),
> +      TEST_GUID_1,
> +      TEST_POLICY_MIN_SIZE_10,
> +      TEST_POLICY_MAX_SIZE_200,
> +      TEST_POLICY_ATTRIBUTES_NULL,
> +      TEST_POLICY_ATTRIBUTES_NULL,
> +      VARIABLE_POLICY_TYPE_NO_LOCK
> +    },
> +    TEST_VAR_1_NAME
> +  };
> +  EFI_STATUS  PolicyCheck;
> +  UINT32      DumpSize;
> +  UINT32      BufferSize;
> +  VOID        *DumpBuffer;
> +
> +  // For good measure, test some parameter validation.
> +  UT_ASSERT_STATUS_EQUAL( DumpVariablePolicy( NULL, NULL ),
> EFI_INVALID_PARAMETER );
> +  DumpSize = 10;
> +  UT_ASSERT_STATUS_EQUAL( DumpVariablePolicy( NULL, &DumpSize ),
> EFI_INVALID_PARAMETER );
> +
> +  // Now for the actual test case.
> +
> +  // Allocate a buffer to hold the output.
> +  BufferSize = sizeof(VARIABLE_POLICY_ENTRY) +
> sizeof(TEST_VAR_1_NAME);
> +  DumpBuffer = AllocatePool( BufferSize );
> +  UT_ASSERT_NOT_EQUAL( DumpBuffer, NULL );
> +
> +  // Verify that the current table size is 0.
> +  DumpSize = BufferSize;
> +  UT_ASSERT_NOT_EFI_ERROR( DumpVariablePolicy( DumpBuffer,
> &DumpSize ) );
> +  UT_ASSERT_EQUAL( DumpSize, 0 );
> +
> +  // Now, set a new policy.
> +
> UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &TestPolicy.Header ) );
> +
> +  // Make sure that the new return is non-zero and fails as expected.
> +  DumpSize = 0;
> +  PolicyCheck = DumpVariablePolicy( NULL, &DumpSize );
> +  UT_ASSERT_STATUS_EQUAL( PolicyCheck, EFI_BUFFER_TOO_SMALL );
> +  UT_ASSERT_EQUAL( DumpSize, BufferSize );
> +
> +  // Now verify that we can fetch the dump.
> +  DumpSize = BufferSize;
> +  UT_ASSERT_NOT_EFI_ERROR( DumpVariablePolicy( DumpBuffer,
> &DumpSize ) );
> +  UT_ASSERT_EQUAL( DumpSize, BufferSize );
> +  UT_ASSERT_MEM_EQUAL( &TestPolicy, DumpBuffer, BufferSize );
> +
> +  // Always put away your toys.
> +  FreePool( DumpBuffer );
> +
> +  return UNIT_TEST_PASSED;
> +}
> +
> +UNIT_TEST_STATUS
> +EFIAPI
> +ShouldBeAbleToDumpThePolicyTableAfterDisabled (
> +  IN UNIT_TEST_CONTEXT      Context
> +  )
> +{
> +  SIMPLE_VARIABLE_POLICY_ENTRY   TestPolicy = {
> +    {
> +      VARIABLE_POLICY_ENTRY_REVISION,
> +      sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_1_NAME),
> +      sizeof(VARIABLE_POLICY_ENTRY),
> +      TEST_GUID_1,
> +      TEST_POLICY_MIN_SIZE_10,
> +      TEST_POLICY_MAX_SIZE_200,
> +      TEST_POLICY_ATTRIBUTES_NULL,
> +      TEST_POLICY_ATTRIBUTES_NULL,
> +      VARIABLE_POLICY_TYPE_NO_LOCK
> +    },
> +    TEST_VAR_1_NAME
> +  };
> +  SIMPLE_VARIABLE_POLICY_ENTRY   TestPolicy2 = {
> +    {
> +      VARIABLE_POLICY_ENTRY_REVISION,
> +      sizeof(VARIABLE_POLICY_ENTRY) + sizeof(TEST_VAR_2_NAME),
> +      sizeof(VARIABLE_POLICY_ENTRY),
> +      TEST_GUID_2,
> +      TEST_POLICY_MIN_SIZE_10,
> +      TEST_POLICY_MAX_SIZE_200,
> +      TEST_POLICY_ATTRIBUTES_NULL,
> +      TEST_POLICY_ATTRIBUTES_NULL,
> +      VARIABLE_POLICY_TYPE_NO_LOCK
> +    },
> +    TEST_VAR_2_NAME
> +  };
> +  EFI_STATUS  PolicyCheck;
> +  UINT32      DumpSize;
> +  VOID        *DumpBuffer;
> +
> +  DumpBuffer = NULL;
> +  DumpSize = 0;
> +
> +  // Register a new policy.
> +
> UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &TestPolicy.Header ) );
> +  // Make sure that we can dump the policy.
> +  PolicyCheck = DumpVariablePolicy( DumpBuffer, &DumpSize );
> +  UT_ASSERT_STATUS_EQUAL( PolicyCheck, EFI_BUFFER_TOO_SMALL );
> +  DumpBuffer = AllocatePool( DumpSize );
> +  UT_ASSERT_NOT_EFI_ERROR( DumpVariablePolicy( DumpBuffer,
> &DumpSize ) );
> +  UT_ASSERT_MEM_EQUAL( DumpBuffer, &TestPolicy, DumpSize );
> +
> +  // Clean up from this step.
> +  FreePool( DumpBuffer );
> +  DumpBuffer = NULL;
> +  DumpSize = 0;
> +
> +  // Now disable the engine.
> +  DisableVariablePolicy();
> +
> +  // Now register a new policy and make sure that both can be dumped.
> +
> UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &TestPolicy2.Header )
> );
> +  // Make sure that we can dump the policy.
> +  PolicyCheck = DumpVariablePolicy( DumpBuffer, &DumpSize );
> +  UT_ASSERT_STATUS_EQUAL( PolicyCheck, EFI_BUFFER_TOO_SMALL );
> +  DumpBuffer = AllocatePool( DumpSize );
> +  UT_ASSERT_NOT_EFI_ERROR( DumpVariablePolicy( DumpBuffer,
> &DumpSize ) );
> +
> +  // Finally, make sure that both policies are in the dump.
> +  UT_ASSERT_MEM_EQUAL( DumpBuffer, &TestPolicy,
> TestPolicy.Header.Size );
> +  UT_ASSERT_MEM_EQUAL( (UINT8*)DumpBuffer + TestPolicy.Header.Size,
> +                        &TestPolicy2,
> +                        TestPolicy2.Header.Size );
> +
> +  // Always put away your toys.
> +  FreePool( DumpBuffer );
> +
> +  return UNIT_TEST_PASSED;
> +}
> +
> +
> +///=== TEST ENGINE
> ==========================================================
> ======================
> +
> +/**
> +  SampleUnitTestApp
> +
> +  @param[in] ImageHandle  The firmware allocated handle for the EFI image.
> +  @param[in] SystemTable  A pointer to the EFI System Table.
> +
> +  @retval EFI_SUCCESS     The entry point executed successfully.
> +  @retval other           Some error occured when executing this entry point.
> +
> +**/
> +int main ()
> +{
> +  EFI_STATUS                  Status;
> +  UNIT_TEST_FRAMEWORK_HANDLE  Framework = NULL;
> +  UNIT_TEST_SUITE_HANDLE      ArchTests;
> +  UNIT_TEST_SUITE_HANDLE      PolicyTests;
> +  UNIT_TEST_SUITE_HANDLE      UtilityTests;
> +#ifdef INTERNAL_UNIT_TEST
> +  UNIT_TEST_SUITE_HANDLE      InternalTests;
> +#endif // INTERNAL_UNIT_TEST
> +
> +  DEBUG(( DEBUG_INFO, "%a v%a\n", UNIT_TEST_NAME,
> UNIT_TEST_VERSION ));
> +
> +  //
> +  // Start setting up the test framework for running the tests.
> +  //
> +  Status = InitUnitTestFramework( &Framework, UNIT_TEST_NAME,
> gEfiCallerBaseName, UNIT_TEST_VERSION );
> +  if (EFI_ERROR( Status ))
> +  {
> +    DEBUG((DEBUG_ERROR, "Failed in InitUnitTestFramework. Status = %r\n",
> Status));
> +    goto EXIT;
> +  }
> +
> +
> +  //
> +  // Add all test suites and tests.
> +  //
> +  Status = CreateUnitTestSuite( &ArchTests, Framework, "Variable Policy
> Architectural Tests", "VarPolicy.Arch", NULL, NULL );
> +  if (EFI_ERROR( Status ))
> +  {
> +    DEBUG((DEBUG_ERROR, "Failed in CreateUnitTestSuite for
> ArchTests\n"));
> +    Status = EFI_OUT_OF_RESOURCES;
> +    goto EXIT;
> +  }
> +  AddTestCase( ArchTests,
> +                "Deinitialization should fail if not previously initialized",
> "VarPolicy.Arch.OnlyDeinit",
> +                ShouldFailDeinitWithoutInit, NULL, NULL, NULL );
> +  AddTestCase( ArchTests,
> +                "Initialization followed by deinitialization should succeed",
> "VarPolicy.Arch.InitDeinit",
> +                ShouldBeAbleToInitAndDeinitTheLibrary, NULL, NULL, NULL );
> +  AddTestCase( ArchTests,
> +                "The initialization function fail if called twice without a deinit",
> "VarPolicy.Arch.InitTwice",
> +                ShouldNotBeAbleToInitializeTheLibraryTwice, NULL, LibCleanup,
> NULL );
> +  AddTestCase( ArchTests,
> +                "API functions should be unavailable until library is initialized",
> "VarPolicy.Arch.UninitApiOff",
> +                ApiCommandsShouldNotRespondIfLibIsUninitialized, NULL,
> LibCleanup, NULL );
> +
> +#ifdef INTERNAL_UNIT_TEST
> +  Status = CreateUnitTestSuite( &InternalTests, Framework, "Variable Policy
> Internal Tests", "VarPolicy.Internal", NULL, NULL );
> +  if (EFI_ERROR( Status ))
> +  {
> +    DEBUG((DEBUG_ERROR, "Failed in CreateUnitTestSuite for
> InternalTests\n"));
> +    Status = EFI_OUT_OF_RESOURCES;
> +    goto EXIT;
> +  }
> +  AddTestCase( InternalTests,
> +                "Policy matching should use name and GUID",
> "VarPolicy.Internal.NameGuid",
> +                PoliciesShouldMatchByNameAndGuid, LibInitMocked, LibCleanup,
> NULL );
> +  AddTestCase( InternalTests,
> +                "# sign wildcards should match digits",
> "VarPolicy.Internal.WildDigits",
> +                WildcardPoliciesShouldMatchDigits, LibInitMocked, LibCleanup,
> NULL );
> +  AddTestCase( InternalTests,
> +                "Digit wildcards should check edge cases",
> "VarPolicy.Internal.WildDigitsAdvanced",
> +                WildcardPoliciesShouldMatchDigitsAdvanced, LibInitMocked,
> LibCleanup, NULL );
> +  AddTestCase( InternalTests,
> +                "Empty names should match an entire namespace",
> "VarPolicy.Internal.WildNamespace",
> +                WildcardPoliciesShouldMatchNamespaces, LibInitMocked,
> LibCleanup, NULL );
> +  AddTestCase( InternalTests,
> +                "Match priority should weight correctly based on wildcards",
> "VarPolicy.Internal.Priorities",
> +                MatchPrioritiesShouldFollowRules, LibInitMocked, LibCleanup,
> NULL );
> +#endif // INTERNAL_UNIT_TEST
> +
> +  Status = CreateUnitTestSuite( &PolicyTests, Framework, "Variable Policy
> Manipulation Tests", "VarPolicy.Policy", NULL, NULL );
> +  if (EFI_ERROR( Status ))
> +  {
> +    DEBUG((DEBUG_ERROR, "Failed in CreateUnitTestSuite for
> PolicyTests\n"));
> +    Status = EFI_OUT_OF_RESOURCES;
> +    goto EXIT;
> +  }
> +  AddTestCase( PolicyTests,
> +                "RegisterShouldAllowNamespaceWildcards",
> "VarPolicy.Policy.AllowNamespace",
> +                RegisterShouldAllowNamespaceWildcards, LibInitMocked,
> LibCleanup, NULL );
> +  AddTestCase( PolicyTests,
> +                "RegisterShouldAllowStateVarsForNamespaces",
> "VarPolicy.Policy.AllowStateNamespace",
> +                RegisterShouldAllowStateVarsForNamespaces, LibInitMocked,
> LibCleanup, NULL );
> +  AddTestCase( PolicyTests,
> +                "RegisterShouldRejectNullPointers", "VarPolicy.Policy.NullPointers",
> +                RegisterShouldRejectNullPointers, LibInitMocked, LibCleanup,
> NULL );
> +  AddTestCase( PolicyTests,
> +                "RegisterShouldRejectBadRevisions",
> "VarPolicy.Policy.BadRevisions",
> +                RegisterShouldRejectBadRevisions, LibInitMocked, LibCleanup,
> NULL );
> +  AddTestCase( PolicyTests,
> +                "RegisterShouldRejectBadSizes", "VarPolicy.Policy.BadSizes",
> +                RegisterShouldRejectBadSizes, LibInitMocked, LibCleanup, NULL );
> +  AddTestCase( PolicyTests,
> +                "RegisterShouldRejectBadOffsets", "VarPolicy.Policy.BadOffsets",
> +                RegisterShouldRejectBadOffsets, LibInitMocked, LibCleanup, NULL );
> +  AddTestCase( PolicyTests,
> +                "RegisterShouldRejectMissingStateStrings",
> "VarPolicy.Policy.MissingStateString",
> +                RegisterShouldRejectMissingStateStrings, LibInitMocked,
> LibCleanup, NULL );
> +  AddTestCase( PolicyTests,
> +                "RegisterShouldRejectStringsMissingNull",
> "VarPolicy.Policy.MissingNull",
> +                RegisterShouldRejectStringsMissingNull, LibInitMocked, LibCleanup,
> NULL );
> +  AddTestCase( PolicyTests,
> +                "RegisterShouldRejectMalformedStrings",
> "VarPolicy.Policy.MalformedStrings",
> +                RegisterShouldRejectMalformedStrings, LibInitMocked, LibCleanup,
> NULL );
> +  AddTestCase( PolicyTests,
> +                "RegisterShouldRejectUnpackedPolicies",
> "VarPolicy.Policy.PolicyPacking",
> +                RegisterShouldRejectUnpackedPolicies, LibInitMocked, LibCleanup,
> NULL );
> +  AddTestCase( PolicyTests,
> +                "RegisterShouldRejectInvalidNameCharacters",
> "VarPolicy.Policy.InvalidCharacters",
> +                RegisterShouldRejectInvalidNameCharacters, LibInitMocked,
> LibCleanup, NULL );
> +  AddTestCase( PolicyTests,
> +                "RegisterShouldRejectBadPolicyConstraints",
> "VarPolicy.Policy.BadConstraints",
> +                RegisterShouldRejectBadPolicyConstraints, LibInitMocked,
> LibCleanup, NULL );
> +  AddTestCase( PolicyTests,
> +                "RegisterShouldRejectUnknownLockPolicies",
> "VarPolicy.Policy.BadLocks",
> +                RegisterShouldRejectUnknownLockPolicies, LibInitMocked,
> LibCleanup, NULL );
> +  AddTestCase( PolicyTests,
> +                "RegisterShouldRejectPolicesWithTooManyWildcards",
> "VarPolicy.Policy.TooManyWildcards",
> +                RegisterShouldRejectPolicesWithTooManyWildcards, LibInitMocked,
> LibCleanup, NULL );
> +  AddTestCase( PolicyTests,
> +                "RegisterShouldRejectDuplicatePolicies",
> "VarPolicy.Policy.DuplicatePolicies",
> +                RegisterShouldRejectDuplicatePolicies, LibInitMocked, LibCleanup,
> NULL );
> +  AddTestCase( PolicyTests,
> +                "Variables that exceed min or max sizes should be rejected",
> "VarPolicy.Policy.MinMax",
> +                MinAndMaxSizePoliciesShouldBeHonored, LibInitMocked,
> LibCleanup, NULL );
> +  AddTestCase( PolicyTests,
> +                "AttributeMustPoliciesShouldBeHonored",
> "VarPolicy.Policy.AttrMust",
> +                AttributeMustPoliciesShouldBeHonored, LibInitMocked, LibCleanup,
> NULL );
> +  AddTestCase( PolicyTests,
> +                "AttributeCantPoliciesShouldBeHonored",
> "VarPolicy.Policy.AttrCant",
> +                AttributeCantPoliciesShouldBeHonored, LibInitMocked, LibCleanup,
> NULL );
> +  AddTestCase( PolicyTests,
> +                "VariablesShouldBeDeletableRegardlessOfSize",
> "VarPolicy.Policy.DeleteIgnoreSize",
> +                VariablesShouldBeDeletableRegardlessOfSize, LibInitMocked,
> LibCleanup, NULL );
> +  AddTestCase( PolicyTests,
> +                "LockNowPoliciesShouldBeHonored",
> "VarPolicy.Policy.VARIABLE_POLICY_TYPE_LOCK_NOW",
> +                LockNowPoliciesShouldBeHonored, LibInitMocked, LibCleanup,
> NULL );
> +  AddTestCase( PolicyTests,
> +                "LockOnCreatePoliciesShouldBeHonored",
> "VarPolicy.Policy.VARIABLE_POLICY_TYPE_LOCK_ON_CREATE",
> +                LockOnCreatePoliciesShouldBeHonored, LibInitMocked, LibCleanup,
> NULL );
> +  AddTestCase( PolicyTests,
> +                "LockOnStatePoliciesShouldBeHonored",
> "VarPolicy.Policy.LockState",
> +                LockOnStatePoliciesShouldBeHonored, LibInitMocked, LibCleanup,
> NULL );
> +  AddTestCase( PolicyTests,
> +                "LockOnStatePoliciesShouldApplyToNamespaces",
> "VarPolicy.Policy.NamespaceLockState",
> +                LockOnStatePoliciesShouldApplyToNamespaces, LibInitMocked,
> LibCleanup, NULL );
> +  AddTestCase( PolicyTests,
> +                "LockOnStateShouldHandleErrorsGracefully",
> "VarPolicy.Policy.LockStateErrors",
> +                LockOnStateShouldHandleErrorsGracefully, LibInitMocked,
> LibCleanup, NULL );
> +  AddTestCase( PolicyTests,
> +                "BestMatchPriorityShouldBeObeyed", "VarPolicy.Policy.BestMatch",
> +                BestMatchPriorityShouldBeObeyed, LibInitMocked, LibCleanup,
> NULL );
> +
> +  Status = CreateUnitTestSuite( &UtilityTests, Framework, "Variable Policy
> Utility Tests", "VarPolicy.Utility", NULL, NULL );
> +  if (EFI_ERROR( Status ))
> +  {
> +    DEBUG((DEBUG_ERROR, "Failed in CreateUnitTestSuite for
> UtilityTests\n"));
> +    Status = EFI_OUT_OF_RESOURCES;
> +    goto EXIT;
> +  }
> +  AddTestCase( UtilityTests,
> +                "API commands that change state should not respond after
> interface is locked", "VarPolicy.Utility.InterfaceLock",
> +                ShouldBeAbleToLockInterface, LibInitMocked, LibCleanup, NULL );
> +  AddTestCase( UtilityTests,
> +                "All policies should pass once enforcement is disabled",
> "VarPolicy.Utility.DisableEnforcement",
> +                ShouldBeAbleToDisablePolicyEnforcement, LibInitMocked,
> LibCleanup, NULL );
> +  AddTestCase( UtilityTests,
> +                "Disabling enforcement twice should produce an error",
> "VarPolicy.Utility.DisableEnforcementTwice",
> +                ShouldNotBeAbleToDisablePoliciesTwice, LibInitMocked,
> LibCleanup, NULL );
> +  AddTestCase( UtilityTests,
> +                "ShouldBeAbleToAddNewPoliciesAfterDisabled",
> "VarPolicy.Utility.AddAfterDisable",
> +                ShouldBeAbleToAddNewPoliciesAfterDisabled, LibInitMocked,
> LibCleanup, NULL );
> +  AddTestCase( UtilityTests,
> +                "ShouldBeAbleToLockAfterDisabled",
> "VarPolicy.Utility.LockAfterDisable",
> +                ShouldBeAbleToLockAfterDisabled, LibInitMocked, LibCleanup,
> NULL );
> +  AddTestCase( UtilityTests,
> +                "Should be able to dump the policy table",
> "VarPolicy.Utility.DumpTable",
> +                ShouldBeAbleToDumpThePolicyTable, LibInitMocked, LibCleanup,
> NULL );
> +  AddTestCase( UtilityTests,
> +                "ShouldBeAbleToDumpThePolicyTableAfterDisabled",
> "VarPolicy.Utility.DumpTableAfterDisable",
> +                ShouldBeAbleToDumpThePolicyTableAfterDisabled, LibInitMocked,
> LibCleanup, NULL );
> +
> +
> +  //
> +  // Execute the tests.
> +  //
> +  Status = RunAllTestSuites( Framework );
> +
> +EXIT:
> +  if (Framework)
> +  {
> +    FreeUnitTestFramework( Framework );
> +  }
> +
> +  return Status;
> +}
> diff --git a/MdeModulePkg/Include/Library/VariablePolicyLib.h
> b/MdeModulePkg/Include/Library/VariablePolicyLib.h
> new file mode 100644
> index 000000000000..6be16fdd8f24
> --- /dev/null
> +++ b/MdeModulePkg/Include/Library/VariablePolicyLib.h
> @@ -0,0 +1,206 @@
> +/** @file -- VariablePolicyLib.h
> +Business logic for Variable Policy enforcement.
> +
> +Copyright (c) Microsoft Corporation.
> +SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#ifndef _VARIABLE_POLICY_LIB_H_
> +#define _VARIABLE_POLICY_LIB_H_
> +
> +#include <Protocol/VariablePolicy.h>
> +
> +/**
> +  This API function validates and registers a new policy with
> +  the policy enforcement engine.
> +
> +  @param[in]  NewPolicy     Pointer to the incoming policy structure.
> +
> +  @retval     EFI_SUCCESS
> +  @retval     EFI_INVALID_PARAMETER   NewPolicy is NULL or is internally
> inconsistent.
> +  @retval     EFI_ALREADY_STARTED     An identical matching policy already
> exists.
> +  @retval     EFI_WRITE_PROTECTED     The interface has been locked until
> the next reboot.
> +  @retval     EFI_UNSUPPORTED         Policy enforcement has been disabled.
> No reason to add more policies.
> +  @retval     EFI_ABORTED             A calculation error has prevented this
> function from completing.
> +  @retval     EFI_OUT_OF_RESOURCES    Cannot grow the table to hold any
> more policies.
> +  @retval     EFI_NOT_READY           Library has not yet been initialized.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +RegisterVariablePolicy (
> +  IN CONST VARIABLE_POLICY_ENTRY    *NewPolicy
> +  );
> +
> +
> +/**
> +  This API function checks to see whether the parameters to SetVariable
> would
> +  be allowed according to the current variable policies.
> +
> +  @param[in]  VariableName       Same as EFI_SET_VARIABLE.
> +  @param[in]  VendorGuid         Same as EFI_SET_VARIABLE.
> +  @param[in]  Attributes         Same as EFI_SET_VARIABLE.
> +  @param[in]  DataSize           Same as EFI_SET_VARIABLE.
> +  @param[in]  Data               Same as EFI_SET_VARIABLE.
> +
> +  @retval     EFI_SUCCESS             A matching policy allows this update.
> +  @retval     EFI_SUCCESS             There are currently no policies that restrict
> this update.
> +  @retval     EFI_SUCCESS             The protections have been disable until the
> next reboot.
> +  @retval     EFI_WRITE_PROTECTED     Variable is currently locked.
> +  @retval     EFI_INVALID_PARAMETER   Attributes or size are invalid.
> +  @retval     EFI_ABORTED             A lock policy exists, but an error prevented
> evaluation.
> +  @retval     EFI_NOT_READY           Library has not been initialized.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +ValidateSetVariable (
> +  IN  CHAR16                       *VariableName,
> +  IN  EFI_GUID                     *VendorGuid,
> +  IN  UINT32                       Attributes,
> +  IN  UINTN                        DataSize,
> +  IN  VOID                         *Data
> +  );
> +
> +
> +/**
> +  This API function disables the variable policy enforcement. If it's
> +  already been called once, will return EFI_ALREADY_STARTED.
> +
> +  @retval     EFI_SUCCESS
> +  @retval     EFI_ALREADY_STARTED   Has already been called once this boot.
> +  @retval     EFI_WRITE_PROTECTED   Interface has been locked until reboot.
> +  @retval     EFI_NOT_READY   Library has not yet been initialized.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +DisableVariablePolicy (
> +  VOID
> +  );
> +
> +
> +/**
> +  This API function will dump the entire contents of the variable policy table.
> +
> +  Similar to GetVariable, the first call can be made with a 0 size and it will
> return
> +  the size of the buffer required to hold the entire table.
> +
> +  @param[out]     Policy  Pointer to the policy buffer. Can be NULL if Size is 0.
> +  @param[in,out]  Size    On input, the size of the output buffer. On output,
> the size
> +                          of the data returned.
> +
> +  @retval     EFI_SUCCESS             Policy data is in the output buffer and Size
> has been updated.
> +  @retval     EFI_INVALID_PARAMETER   Size is NULL, or Size is non-zero and
> Policy is NULL.
> +  @retval     EFI_BUFFER_TOO_SMALL    Size is insufficient to hold policy. Size
> updated with required size.
> +  @retval     EFI_NOT_READY           Library has not yet been initialized.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +DumpVariablePolicy (
> +  OUT     UINT8         *Policy,
> +  IN OUT  UINT32        *Size
> +  );
> +
> +
> +/**
> +  This API function returns whether or not the policy engine is
> +  currently being enforced.
> +
> +  @retval     TRUE
> +  @retval     FALSE
> +  @retval     FALSE         Library has not yet been initialized.
> +
> +**/
> +BOOLEAN
> +EFIAPI
> +IsVariablePolicyEnabled (
> +  VOID
> +  );
> +
> +
> +/**
> +  This API function locks the interface so that no more policy updates
> +  can be performed or changes made to the enforcement until the next
> boot.
> +
> +  @retval     EFI_SUCCESS
> +  @retval     EFI_NOT_READY   Library has not yet been initialized.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +LockVariablePolicy (
> +  VOID
> +  );
> +
> +
> +/**
> +  This API function returns whether or not the policy interface is locked
> +  for the remainder of the boot.
> +
> +  @retval     TRUE
> +  @retval     FALSE
> +  @retval     FALSE         Library has not yet been initialized.
> +
> +**/
> +BOOLEAN
> +EFIAPI
> +IsVariablePolicyInterfaceLocked (
> +  VOID
> +  );
> +
> +
> +/**
> +  This helper function initializes the library and sets
> +  up any required internal structures or handlers.
> +
> +  Also registers the internal pointer for the GetVariable helper.
> +
> +  @param[in]  GetVariableHelper A function pointer matching the
> EFI_GET_VARIABLE prototype that will be used to
> +                  check policy criteria that involve the existence of other variables.
> +
> +  @retval     EFI_SUCCESS
> +  @retval     EFI_ALREADY_STARTED   The initialize function has been called
> more than once without a call to
> +                                    deinitialize.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +InitVariablePolicyLib (
> +  IN  EFI_GET_VARIABLE    GetVariableHelper
> +  );
> +
> +
> +/**
> +  This helper function returns whether or not the library is currently
> initialized.
> +
> +  @retval     TRUE
> +  @retval     FALSE
> +
> +**/
> +BOOLEAN
> +EFIAPI
> +IsVariablePolicyLibInitialized (
> +  VOID
> +  );
> +
> +
> +/**
> +  This helper function tears down  the library.
> +
> +  Should generally only be used for test harnesses.
> +
> +  @retval     EFI_SUCCESS
> +  @retval     EFI_NOT_READY     Deinitialize was called without first calling
> initialize.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +DeinitVariablePolicyLib (
> +  VOID
> +  );
> +
> +
> +#endif // _VARIABLE_POLICY_LIB_H_
> diff --git a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf
> b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf
> new file mode 100644
> index 000000000000..340d5e8793fe
> --- /dev/null
> +++ b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf
> @@ -0,0 +1,38 @@
> +## @file VariablePolicyLib.inf
> +# Business logic for Variable Policy enforcement.
> +#
> +##
> +# Copyright (c) Microsoft Corporation.
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +##
> +
> +
> +[Defines]
> +  INF_VERSION         = 0x00010017
> +  BASE_NAME           = VariablePolicyLib
> +  FILE_GUID           = E9ECD342-159A-4F24-9FDF-65724027C594
> +  VERSION_STRING      = 1.0
> +  MODULE_TYPE         = BASE
> +  LIBRARY_CLASS       = VariablePolicyLib
> +
> +#
> +# The following information is for reference only and not required by the
> build tools.
> +#
> +#  VALID_ARCHITECTURES           = ANY
> +#
> +
> +
> +[Sources]
> +  VariablePolicyLib.c
> +
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +
> +
> +[LibraryClasses]
> +  DebugLib
> +  BaseMemoryLib
> +  MemoryAllocationLib
> +  SafeIntLib
> 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
> +// VariablePolicyLib.uni
> +//
> +// Copyright (c) Microsoft Corporation.
> +// SPDX-License-Identifier: BSD-2-Clause-Patent
> +//
> +// **/
> +
> +
> +#string STR_MODULE_ABSTRACT             #language en-US "Library containing
> the business logic for the VariablePolicy engine"
> +
> +#string STR_MODULE_DESCRIPTION          #language en-US "Library
> containing the business logic for the VariablePolicy engine"
> diff --git
> a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/Variable
> PolicyUnitTest.inf
> b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/Variable
> PolicyUnitTest.inf
> new file mode 100644
> index 000000000000..c7c636eabde3
> --- /dev/null
> +++
> b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/Variable
> PolicyUnitTest.inf
> @@ -0,0 +1,41 @@
> +## @file VariablePolicyUnitTest.inf
> +# UnitTest for...
> +# Business logic for Variable Policy enforcement.
> +#
> +##
> +# Copyright (c) Microsoft Corporation.
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +##
> +
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010006
> +  BASE_NAME                      = VariablePolicyUnitTest
> +  FILE_GUID                      = 1200A2E4-D756-418C-9768-528C2D181A98
> +  MODULE_TYPE                    = HOST_APPLICATION
> +  VERSION_STRING                 = 1.0
> +
> +#
> +# The following information is for reference only and not required by the
> build tools.
> +#
> +#  VALID_ARCHITECTURES           = IA32 X64 ARM AARCH64
> +#
> +
> +[Sources]
> +  VariablePolicyUnitTest.c
> +
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
> +
> +
> +[LibraryClasses]
> +  BaseLib
> +  DebugLib
> +  UnitTestLib
> +  PrintLib
> +  VariablePolicyLib
> +  BaseMemoryLib
> +  MemoryAllocationLib
> diff --git a/MdeModulePkg/MdeModulePkg.dec
> b/MdeModulePkg/MdeModulePkg.dec
> index 956276e30a72..990e23b07a08 100644
> --- a/MdeModulePkg/MdeModulePkg.dec
> +++ b/MdeModulePkg/MdeModulePkg.dec
> @@ -29,6 +29,9 @@
>    ##  @libraryclass  Defines a set of methods to reset whole system.
>    ResetSystemLib|Include/Library/ResetSystemLib.h
> 
> +  ##  @libraryclass  Business logic for storing and testing variable policies
> +  VariablePolicyLib|Include/Library/VariablePolicyLib.h
> +
>    ##  @libraryclass  Defines a set of helper functions for resetting the system.
>    ResetUtilityLib|Include/Library/ResetUtilityLib.h
> 
> diff --git a/MdeModulePkg/MdeModulePkg.dsc
> b/MdeModulePkg/MdeModulePkg.dsc
> index f7dbb27ce25d..8501dae88eb1 100644
> --- a/MdeModulePkg/MdeModulePkg.dsc
> +++ b/MdeModulePkg/MdeModulePkg.dsc
> @@ -3,6 +3,7 @@
>  #
>  # (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>
>  # Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved.<BR>
> +# Copyright (c) Microsoft Corporation.
>  #
>  #    SPDX-License-Identifier: BSD-2-Clause-Patent
>  #
> @@ -58,6 +59,7 @@
>    DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf
> 
> DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTabl
> eLib.inf
> 
> UefiBootManagerLib|MdeModulePkg/Library/UefiBootManagerLib/UefiBoo
> tManagerLib.inf
> +
> VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLi
> b.inf
>    #
>    # Generic Modules
>    #
> @@ -306,6 +308,7 @@
>    MdeModulePkg/Library/BootLogoLib/BootLogoLib.inf
> 
> MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull
> .inf
>    MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf
> +  MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf
>    MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf
>    MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLib.inf
>    MdeModulePkg/Library/VarCheckPcdLib/VarCheckPcdLib.inf
> diff --git a/MdeModulePkg/Test/MdeModulePkgHostTest.dsc
> b/MdeModulePkg/Test/MdeModulePkgHostTest.dsc
> index 72a119db4568..058ef7dcef11 100644
> --- a/MdeModulePkg/Test/MdeModulePkgHostTest.dsc
> +++ b/MdeModulePkg/Test/MdeModulePkgHostTest.dsc
> @@ -19,12 +19,20 @@
> 
>  !include UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc
> 
> +[LibraryClasses]
> +  SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf
> +
>  [Components]
> 
> MdeModulePkg/Library/DxeResetSystemLib/UnitTest/MockUefiRuntimeSer
> vicesTableLib.inf
> 
>    #
>    # Build MdeModulePkg HOST_APPLICATION Tests
>    #
> +
> MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePo
> licyUnitTest.inf {
> +    <LibraryClasses>
> +
> VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLi
> b.inf
> +  }
> +
> 
> MdeModulePkg/Library/DxeResetSystemLib/UnitTest/DxeResetSystemLibU
> nitTestHost.inf {
>      <LibraryClasses>
> 
> ResetSystemLib|MdeModulePkg/Library/DxeResetSystemLib/DxeResetSyst
> emLib.inf
> --
> 2.16.3.windows.1
> 
> 
> 


  reply	other threads:[~2020-04-22  9:14 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <20200410183802.21192-1-michael.kubacki@outlook.com>
2020-04-10 18:37 ` [PATCH v1 2/9] MdeModulePkg: Define the VariablePolicyLib Michael Kubacki
2020-04-22  9:14   ` Guomin Jiang [this message]
2020-04-10 18:37 ` [PATCH v1 3/9] MdeModulePkg: Define the VariablePolicyHelperLib Michael Kubacki
2020-04-26  2:03   ` [edk2-devel] " Guomin Jiang
2020-04-10 18:37 ` [PATCH v1 4/9] MdeModulePkg: Define the VarCheckPolicyLib and SMM interface Michael Kubacki
2020-04-10 18:37 ` [PATCH v1 5/9] MdeModulePkg: Connect VariablePolicy business logic to VariableServices Michael Kubacki
2020-04-10 18:37 ` [PATCH v1 6/9] MdeModulePkg: Allow VariablePolicy state to delete protected variables Michael Kubacki
2020-04-10 18:38 ` [PATCH v1 7/9] SecurityPkg: Allow VariablePolicy state to delete authenticated variables Michael Kubacki
2020-04-10 18:38 ` [PATCH v1 8/9] MdeModulePkg: Change TCG MOR variables to use VariablePolicy Michael Kubacki
2020-04-10 18:38 ` [PATCH v1 9/9] MdeModulePkg: Drop VarLock from RuntimeDxe variable driver Michael Kubacki

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=DM6PR11MB29556BAE8C569D5A7EF236CC9DD20@DM6PR11MB2955.namprd11.prod.outlook.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox