public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH v6 00/14] Add the VariablePolicy feature
@ 2020-06-23  6:40 bret
  2020-06-23  6:40 ` [PATCH v6 01/14] MdeModulePkg: Define the VariablePolicy protocol interface Bret Barkelew
                   ` (16 more replies)
  0 siblings, 17 replies; 48+ messages in thread
From: bret @ 2020-06-23  6:40 UTC (permalink / raw)
  To: devel
  Cc: Jiewen Yao, Chao Zhang, Jian J Wang, Hao A Wu, Liming Gao,
	Jordan Justen, Laszlo Ersek, Ard Biesheuvel, Andrew Fish, Ray Ni

REF:https://bugzilla.tianocore.org/show_bug.cgi?id=2522

The 14 patches in this series add the VariablePolicy feature to the core,
deprecate Edk2VarLock (while adding a compatibility layer to reduce code
churn), and integrate the VariablePolicy libraries and protocols into
Variable Services.

Since the integration requires multiple changes, including adding libraries,
a protocol, an SMI communication handler, and VariableServices integration,
the patches are broken up by individual library additions and then a final
integration. Security-sensitive changes like bypassing Authenticated
Variable enforcement are also broken out into individual patches so that
attention can be called directly to them.

Platform porting instructions are described in this wiki entry:
https://github.com/tianocore/tianocore.github.io/wiki/VariablePolicy-Protocol---Enhanced-Method-for-Managing-Variables#platform-porting

Discussion of the feature can be found in multiple places throughout
the last year on the RFC channel, staging branches, and in devel.

Most recently, this subject was discussed in this thread:
https://edk2.groups.io/g/devel/message/53712
(the code branches shared in that discussion are now out of date, but the
whitepapers and discussion are relevant).

Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Hao A Wu <hao.a.wu@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
Cc: Andrew Fish <afish@apple.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Bret Barkelew <brbarkel@microsoft.com>
Signed-off-by: Bret Barkelew <brbarkel@microsoft.com>

v6 changes:
* Fix an issue with uninitialized Status in InitVariablePolicyLib() and DeinitVariablePolicyLib()
* Fix GCC building in shell-based functional test
* Rebase on latest origin/master

v5 changes:
* Fix the CONST mismatch in VariablePolicy.h and VariablePolicySmmDxe.c
* Fix EFIAPI mismatches in the functional unittest
* Rebase on latest origin/master

v4 changes:
* Remove Optional PcdAllowVariablePolicyEnforcementDisable PCD from platforms
* Rebase on master
* Migrate to new MmCommunicate2 protocol
* Fix an oversight in the default return value for InitMmCommonCommBuffer
* Fix in VariablePolicyLib to allow ExtraInitRuntimeDxe to consume variables

V3 changes:
* Address all non-unittest issues with ECC
* Make additional style changes
* Include section name in hunk headers in "ini-style" files
* Remove requirement for the EdkiiPiSmmCommunicationsRegionTable driver
  (now allocates its own buffer)
* Change names from VARIABLE_POLICY_PROTOCOL and gVariablePolicyProtocolGuid
  to EDKII_VARIABLE_POLICY_PROTOCOL and gEdkiiVariablePolicyProtocolGuid
* Fix GCC warning about initializing externs
* Add UNI strings for new PCD
* Add patches for ArmVirtPkg, OvmfXen, and UefiPayloadPkg
* Reorder patches according to Liming's feedback about adding to platforms
  before changing variable driver

V2 changes:
* Fixed implementation for RuntimeDxe
* Add PCD to block DisableVariablePolicy
* Fix the DumpVariablePolicy pagination in SMM

Bret Barkelew (14):
  MdeModulePkg: Define the VariablePolicy protocol interface
  MdeModulePkg: Define the VariablePolicyLib
  MdeModulePkg: Define the VariablePolicyHelperLib
  MdeModulePkg: Define the VarCheckPolicyLib and SMM interface
  OvmfPkg: Add VariablePolicy engine to OvmfPkg platform
  EmulatorPkg: Add VariablePolicy engine to EmulatorPkg platform
  ArmVirtPkg: Add VariablePolicy engine to ArmVirtPkg platform
  UefiPayloadPkg: Add VariablePolicy engine to UefiPayloadPkg platform
  MdeModulePkg: Connect VariablePolicy business logic to
    VariableServices
  MdeModulePkg: Allow VariablePolicy state to delete protected variables
  SecurityPkg: Allow VariablePolicy state to delete authenticated
    variables
  MdeModulePkg: Change TCG MOR variables to use VariablePolicy
  MdeModulePkg: Drop VarLock from RuntimeDxe variable driver
  MdeModulePkg: Add a shell-based functional test for VariablePolicy

 MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.c                               |  320 +++
 MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.c                   |  396 ++++
 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitNull.c                     |   46 +
 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitRuntimeDxe.c               |   85 +
 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c                               |  816 +++++++
 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePolicyUnitTest.c   | 2440 ++++++++++++++++++++
 MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/VariablePolicyFuncTestApp.c        | 1978 ++++++++++++++++
 MdeModulePkg/Universal/Variable/RuntimeDxe/TcgMorLockDxe.c                               |   52 +-
 MdeModulePkg/Universal/Variable/RuntimeDxe/TcgMorLockSmm.c                               |   60 +-
 MdeModulePkg/Universal/Variable/RuntimeDxe/VarCheck.c                                    |   49 +-
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c                                 |   53 +
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableLockRequstToLock.c                    |   71 +
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariablePolicySmmDxe.c                        |  642 +++++
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c                       |   14 +
 SecurityPkg/Library/AuthVariableLib/AuthService.c                                        |   22 +-
 ArmVirtPkg/ArmVirt.dsc.inc                                                               |    4 +
 EmulatorPkg/EmulatorPkg.dsc                                                              |    3 +
 MdeModulePkg/Include/Guid/VarCheckPolicyMmi.h                                            |   54 +
 MdeModulePkg/Include/Library/VariablePolicyHelperLib.h                                   |  164 ++
 MdeModulePkg/Include/Library/VariablePolicyLib.h                                         |  207 ++
 MdeModulePkg/Include/Protocol/VariablePolicy.h                                           |  157 ++
 MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.inf                             |   42 +
 MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.uni                             |   12 +
 MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf                 |   35 +
 MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.uni                 |   12 +
 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf                             |   44 +
 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.uni                             |   12 +
 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf                   |   51 +
 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePolicyUnitTest.inf |   40 +
 MdeModulePkg/MdeModulePkg.ci.yaml                                                        |    4 +-
 MdeModulePkg/MdeModulePkg.dec                                                            |   26 +-
 MdeModulePkg/MdeModulePkg.dsc                                                            |   15 +
 MdeModulePkg/MdeModulePkg.uni                                                            |    7 +
 MdeModulePkg/Test/MdeModulePkgHostTest.dsc                                               |   11 +
 MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/Readme.md                          |   55 +
 MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/VariablePolicyFuncTestApp.inf      |   42 +
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf                        |    5 +
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf                               |    4 +
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf                     |   10 +
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf                      |    4 +
 OvmfPkg/OvmfPkgIa32.dsc                                                                  |    5 +
 OvmfPkg/OvmfPkgIa32X64.dsc                                                               |    5 +
 OvmfPkg/OvmfPkgX64.dsc                                                                   |    5 +
 OvmfPkg/OvmfXen.dsc                                                                      |    4 +
 SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf                                  |    2 +
 UefiPayloadPkg/UefiPayloadPkgIa32.dsc                                                    |    4 +
 UefiPayloadPkg/UefiPayloadPkgIa32X64.dsc                                                 |    4 +
 47 files changed, 8015 insertions(+), 78 deletions(-)
 create mode 100644 MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.c
 create mode 100644 MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.c
 create mode 100644 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitNull.c
 create mode 100644 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitRuntimeDxe.c
 create mode 100644 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c
 create mode 100644 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePolicyUnitTest.c
 create mode 100644 MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/VariablePolicyFuncTestApp.c
 create mode 100644 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableLockRequstToLock.c
 create mode 100644 MdeModulePkg/Universal/Variable/RuntimeDxe/VariablePolicySmmDxe.c
 create mode 100644 MdeModulePkg/Include/Guid/VarCheckPolicyMmi.h
 create mode 100644 MdeModulePkg/Include/Library/VariablePolicyHelperLib.h
 create mode 100644 MdeModulePkg/Include/Library/VariablePolicyLib.h
 create mode 100644 MdeModulePkg/Include/Protocol/VariablePolicy.h
 create mode 100644 MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.inf
 create mode 100644 MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.uni
 create mode 100644 MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf
 create mode 100644 MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.uni
 create mode 100644 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf
 create mode 100644 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.uni
 create mode 100644 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf
 create mode 100644 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePolicyUnitTest.inf
 create mode 100644 MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/Readme.md
 create mode 100644 MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/VariablePolicyFuncTestApp.inf

-- 
2.26.2.windows.1.8.g01c50adf56.20200515075929


^ permalink raw reply	[flat|nested] 48+ messages in thread

* [PATCH v6 01/14] MdeModulePkg: Define the VariablePolicy protocol interface
  2020-06-23  6:40 [PATCH v6 00/14] Add the VariablePolicy feature bret
@ 2020-06-23  6:40 ` Bret Barkelew
  2020-06-23  6:40 ` [PATCH v6 02/14] MdeModulePkg: Define the VariablePolicyLib Bret Barkelew
                   ` (15 subsequent siblings)
  16 siblings, 0 replies; 48+ messages in thread
From: Bret Barkelew @ 2020-06-23  6:40 UTC (permalink / raw)
  To: devel; +Cc: Jian J Wang, Hao A Wu, Liming Gao

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

VariablePolicy is an updated interface to
replace VarLock and VarCheckProtocol.

Add the VariablePolicy protocol interface
header and add to the MdeModulePkg.dec file.

Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Hao A Wu <hao.a.wu@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Bret Barkelew <brbarkel@microsoft.com>
Signed-off-by: Bret Barkelew <brbarkel@microsoft.com>
---
 MdeModulePkg/Include/Protocol/VariablePolicy.h | 157 ++++++++++++++++++++
 MdeModulePkg/MdeModulePkg.dec                  |  14 +-
 MdeModulePkg/MdeModulePkg.uni                  |   7 +
 3 files changed, 177 insertions(+), 1 deletion(-)

diff --git a/MdeModulePkg/Include/Protocol/VariablePolicy.h b/MdeModulePkg/Include/Protocol/VariablePolicy.h
new file mode 100644
index 000000000000..8226c187a77b
--- /dev/null
+++ b/MdeModulePkg/Include/Protocol/VariablePolicy.h
@@ -0,0 +1,157 @@
+/** @file -- VariablePolicy.h
+
+This protocol allows communication with Variable Policy Engine.
+
+Copyright (c) Microsoft Corporation.
+SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef __EDKII_VARIABLE_POLICY_PROTOCOL__
+#define __EDKII_VARIABLE_POLICY_PROTOCOL__
+
+#define EDKII_VARIABLE_POLICY_PROTOCOL_REVISION   0x0000000000010000
+
+#define EDKII_VARIABLE_POLICY_PROTOCOL_GUID \
+  { \
+    0x81D1675C, 0x86F6, 0x48DF, { 0xBD, 0x95, 0x9A, 0x6E, 0x4F, 0x09, 0x25, 0xC3 } \
+  }
+
+#define VARIABLE_POLICY_ENTRY_REVISION      0x00010000
+
+#pragma pack(push, 1)
+typedef struct {
+  UINT32   Version;
+  UINT16   Size;
+  UINT16   OffsetToName;
+  EFI_GUID Namespace;
+  UINT32   MinSize;
+  UINT32   MaxSize;
+  UINT32   AttributesMustHave;
+  UINT32   AttributesCantHave;
+  UINT8    LockPolicyType;
+  UINT8    Padding[3];
+  // UINT8    LockPolicy[];     // Variable Length Field
+  // CHAR16   Name[]            // Variable Length Field
+} VARIABLE_POLICY_ENTRY;
+
+#define     VARIABLE_POLICY_NO_MIN_SIZE             0
+#define     VARIABLE_POLICY_NO_MAX_SIZE             MAX_UINT32
+#define     VARIABLE_POLICY_NO_MUST_ATTR            0
+#define     VARIABLE_POLICY_NO_CANT_ATTR            0
+
+#define     VARIABLE_POLICY_TYPE_NO_LOCK            0
+#define     VARIABLE_POLICY_TYPE_LOCK_NOW           1
+#define     VARIABLE_POLICY_TYPE_LOCK_ON_CREATE     2
+#define     VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE  3
+
+typedef struct {
+  EFI_GUID Namespace;
+  UINT8    Value;
+  UINT8    Padding;
+  // CHAR16   Name[];           // Variable Length Field
+} VARIABLE_LOCK_ON_VAR_STATE_POLICY;
+#pragma pack(pop)
+
+/**
+  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_WRITE_PROTECTED   Interface option is disabled by platform PCD.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *DISABLE_VARIABLE_POLICY)(
+  VOID
+  );
+
+/**
+  This API function returns whether or not the policy engine is
+  currently being enforced.
+
+  @param[out]   State       Pointer to a return value for whether the policy enforcement
+                            is currently enabled.
+
+  @retval     EFI_SUCCESS
+  @retval     Others        An error has prevented this command from completing.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *IS_VARIABLE_POLICY_ENABLED)(
+  OUT BOOLEAN *State
+  );
+
+/**
+  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_ABORTED             A calculation error has prevented this function from completing.
+  @retval     EFI_OUT_OF_RESOURCES    Cannot grow the table to hold any more policies.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *REGISTER_VARIABLE_POLICY)(
+  IN CONST VARIABLE_POLICY_ENTRY  *PolicyEntry
+  );
+
+/**
+  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.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *DUMP_VARIABLE_POLICY)(
+  IN OUT UINT8  *Policy,
+  IN OUT UINT32 *Size
+  );
+
+/**
+  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     Others        An error has prevented this command from completing.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *LOCK_VARIABLE_POLICY)(
+  VOID
+  );
+
+typedef struct {
+  UINT64                     Revision;
+  DISABLE_VARIABLE_POLICY    DisableVariablePolicy;
+  IS_VARIABLE_POLICY_ENABLED IsVariablePolicyEnabled;
+  REGISTER_VARIABLE_POLICY   RegisterVariablePolicy;
+  DUMP_VARIABLE_POLICY       DumpVariablePolicy;
+  LOCK_VARIABLE_POLICY       LockVariablePolicy;
+} _EDKII_VARIABLE_POLICY_PROTOCOL;
+
+typedef _EDKII_VARIABLE_POLICY_PROTOCOL EDKII_VARIABLE_POLICY_PROTOCOL;
+
+extern EFI_GUID gEdkiiVariablePolicyProtocolGuid;
+
+#endif
diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec
index 843e963ad34b..05d8ad4931f9 100644
--- a/MdeModulePkg/MdeModulePkg.dec
+++ b/MdeModulePkg/MdeModulePkg.dec
@@ -8,7 +8,7 @@
 # Copyright (c) 2016, Linaro Ltd. All rights reserved.<BR>
 # (C) Copyright 2016 - 2019 Hewlett Packard Enterprise Development LP<BR>
 # Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
-# Copyright (c) 2016, Microsoft Corporation<BR>
+# Copyright (c) Microsoft Corporation.<BR>
 # SPDX-License-Identifier: BSD-2-Clause-Patent
 #
 ##
@@ -624,6 +624,9 @@ [Protocols]
 #   0x80000006 | Incorrect error code provided.
 #
 
+  ## Include/Protocol/VariablePolicy.h
+  gEdkiiVariablePolicyProtocolGuid = { 0x81D1675C, 0x86F6, 0x48DF, { 0xBD, 0x95, 0x9A, 0x6E, 0x4F, 0x09, 0x25, 0xC3 } }
+
 [PcdsFeatureFlag]
   ## Indicates if the platform can support update capsule across a system reset.<BR><BR>
   #   TRUE  - Supports update capsule across a system reset.<BR>
@@ -1116,6 +1119,15 @@ [PcdsFixedAtBuild, PcdsPatchableInModule]
   # @Prompt Variable storage size.
   gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize|0x10000|UINT32|0x30000005
 
+  ## Toggle for whether the VariablePolicy engine should allow disabling.
+  # The engine is enabled at power-on, but the interface allows the platform to
+  # disable enforcement for servicing flexibility. If this PCD is disabled, it will block the ability to
+  # disable the enforcement and VariablePolicy enforcement will always be ON.
+  #   TRUE - VariablePolicy can be disabled by request through the interface (until interface is locked)
+  #   FALSE - VariablePolicy interface will not accept requests to disable and is ALWAYS ON
+  # @Prompt Allow VariablePolicy enforcement to be disabled.
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAllowVariablePolicyEnforcementDisable|FALSE|BOOLEAN|0x30000020
+
   ## FFS filename to find the ACPI tables.
   # @Prompt FFS name of ACPI tables storage.
   gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiTableStorageFile|{ 0x25, 0x4e, 0x37, 0x7e, 0x01, 0x8e, 0xee, 0x4f, 0x87, 0xf2, 0x39, 0xc, 0x23, 0xc6, 0x6, 0xcd }|VOID*|0x30000016
diff --git a/MdeModulePkg/MdeModulePkg.uni b/MdeModulePkg/MdeModulePkg.uni
index 2007e0596c4f..b64e7f351cda 100644
--- a/MdeModulePkg/MdeModulePkg.uni
+++ b/MdeModulePkg/MdeModulePkg.uni
@@ -129,6 +129,13 @@
 
 #string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdVariableStoreSize_HELP  #language en-US "The size of volatile buffer. This buffer is used to store VOLATILE attribute variables."
 
+#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdAllowVariablePolicyEnforcementDisable_PROMPT  #language en-US "Allow VariablePolicy enforcement to be disabled."
+
+#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdAllowVariablePolicyEnforcementDisable_HELP  #language en-US "If this PCD is disabled, it will block the ability to<BR>\n"
+                                                                                                          "disable the enforcement and VariablePolicy enforcement will always be ON.<BR>\n"
+                                                                                                          "TRUE - VariablePolicy can be disabled by request through the interface (until interface is locked)<BR>\n"
+                                                                                                          "FALSE - VariablePolicy interface will not accept requests to disable and is ALWAYS ON<BR>\n"
+
 #string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdAcpiTableStorageFile_PROMPT  #language en-US "FFS name of ACPI tables storage"
 
 #string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdAcpiTableStorageFile_HELP  #language en-US "FFS filename to find the ACPI tables."
-- 
2.26.2.windows.1.8.g01c50adf56.20200515075929


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH v6 02/14] MdeModulePkg: Define the VariablePolicyLib
  2020-06-23  6:40 [PATCH v6 00/14] Add the VariablePolicy feature bret
  2020-06-23  6:40 ` [PATCH v6 01/14] MdeModulePkg: Define the VariablePolicy protocol interface Bret Barkelew
@ 2020-06-23  6:40 ` Bret Barkelew
  2020-07-02  2:13   ` [edk2-devel] " Dandan Bi
  2020-06-23  6:40 ` [PATCH v6 03/14] MdeModulePkg: Define the VariablePolicyHelperLib Bret Barkelew
                   ` (14 subsequent siblings)
  16 siblings, 1 reply; 48+ messages in thread
From: Bret Barkelew @ 2020-06-23  6:40 UTC (permalink / raw)
  To: devel; +Cc: Jian J Wang, Hao A Wu, Liming Gao

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>
Cc: Bret Barkelew <brbarkel@microsoft.com>
Signed-off-by: Bret Barkelew <brbarkel@microsoft.com>
---
 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitNull.c                     |   46 +
 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitRuntimeDxe.c               |   85 +
 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c                               |  816 +++++++
 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePolicyUnitTest.c   | 2436 ++++++++++++++++++++
 MdeModulePkg/Include/Library/VariablePolicyLib.h                                         |  207 ++
 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf                             |   44 +
 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.uni                             |   12 +
 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf                   |   51 +
 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePolicyUnitTest.inf |   40 +
 MdeModulePkg/MdeModulePkg.dec                                                            |    3 +
 MdeModulePkg/MdeModulePkg.dsc                                                            |    5 +
 MdeModulePkg/Test/MdeModulePkgHostTest.dsc                                               |   11 +
 12 files changed, 3756 insertions(+)

diff --git a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitNull.c b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitNull.c
new file mode 100644
index 000000000000..ad2ee0b2fb8f
--- /dev/null
+++ b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitNull.c
@@ -0,0 +1,46 @@
+/** @file -- VariablePolicyExtraInitNull.c
+This file contains extra init and deinit routines that don't do anything
+extra.
+
+Copyright (c) Microsoft Corporation.
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/UefiRuntimeServicesTableLib.h>
+
+
+/**
+  An extra init hook that enables the RuntimeDxe library instance to
+  register VirtualAddress change callbacks. Among other things.
+
+  @retval     EFI_SUCCESS   Everything is good. Continue with init.
+  @retval     Others        Uh... don't continue.
+
+**/
+EFI_STATUS
+VariablePolicyExtraInit (
+  VOID
+  )
+{
+  // NULL implementation.
+  return EFI_SUCCESS;
+}
+
+
+/**
+  An extra deinit hook that enables the RuntimeDxe library instance to
+  register VirtualAddress change callbacks. Among other things.
+
+  @retval     EFI_SUCCESS   Everything is good. Continue with deinit.
+  @retval     Others        Uh... don't continue.
+
+**/
+EFI_STATUS
+VariablePolicyExtraDeinit (
+  VOID
+  )
+{
+  // NULL implementation.
+  return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitRuntimeDxe.c b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitRuntimeDxe.c
new file mode 100644
index 000000000000..3ca87048b14b
--- /dev/null
+++ b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitRuntimeDxe.c
@@ -0,0 +1,85 @@
+/** @file -- VariablePolicyExtraInitRuntimeDxe.c
+This file contains extra init and deinit routines that register and unregister
+VariableAddressChange callbacks.
+
+Copyright (c) Microsoft Corporation.
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+
+extern EFI_GET_VARIABLE   mGetVariableHelper;
+extern UINT8              *mPolicyTable;
+STATIC BOOLEAN            mIsVirtualAddrConverted;
+STATIC EFI_EVENT          mVariablePolicyLibVirtualAddressChangeEvent  = NULL;
+
+/**
+  For the RuntimeDxe version of this lib, convert internal pointer addresses to virtual addresses.
+
+  @param[in] Event      Event whose notification function is being invoked.
+  @param[in] Context    The pointer to the notification function's context, which
+                        is implementation-dependent.
+**/
+STATIC
+VOID
+EFIAPI
+VariablePolicyLibVirtualAddressCallback (
+  IN  EFI_EVENT   Event,
+  IN  VOID        *Context
+  )
+{
+  gRT->ConvertPointer (0, (VOID **)&mPolicyTable);
+  gRT->ConvertPointer (0, (VOID **)&mGetVariableHelper);
+  mIsVirtualAddrConverted = TRUE;
+}
+
+
+/**
+  An extra init hook that enables the RuntimeDxe library instance to
+  register VirtualAddress change callbacks. Among other things.
+
+  @retval     EFI_SUCCESS   Everything is good. Continue with init.
+  @retval     Others        Uh... don't continue.
+
+**/
+EFI_STATUS
+VariablePolicyExtraInit (
+  VOID
+  )
+{
+  return gBS->CreateEventEx (EVT_NOTIFY_SIGNAL,
+                              TPL_NOTIFY,
+                              VariablePolicyLibVirtualAddressCallback,
+                              NULL,
+                              &gEfiEventVirtualAddressChangeGuid,
+                              &mVariablePolicyLibVirtualAddressChangeEvent);
+}
+
+
+/**
+  An extra deinit hook that enables the RuntimeDxe library instance to
+  register VirtualAddress change callbacks. Among other things.
+
+  @retval     EFI_SUCCESS   Everything is good. Continue with deinit.
+  @retval     Others        Uh... don't continue.
+
+**/
+EFI_STATUS
+VariablePolicyExtraDeinit (
+  VOID
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = EFI_SUCCESS;
+  if (mIsVirtualAddrConverted) {
+    Status = gBS->CloseEvent (mVariablePolicyLibVirtualAddressChangeEvent);
+  }
+  else {
+    Status = EFI_SUCCESS;
+  }
+
+  return Status;
+}
diff --git a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c
new file mode 100644
index 000000000000..84c794adaed9
--- /dev/null
+++ b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c
@@ -0,0 +1,816 @@
+/** @file -- VariablePolicyLib.c
+Business logic for Variable Policy enforcement.
+
+Copyright (c) Microsoft Corporation.
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+
+#include <Library/SafeIntLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+
+#include <Protocol/VariablePolicy.h>
+#include <Library/VariablePolicyLib.h>
+
+
+// IMPORTANT NOTE: This library is currently rife with multiple return statements
+//                 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.
+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.
+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
+
+// ExtraInit/ExtraDeinit functions allow RuntimeDxe to register VirtualAddress callbacks.
+EFI_STATUS
+VariablePolicyExtraInit (
+  VOID
+  );
+
+EFI_STATUS
+VariablePolicyExtraDeinit (
+  VOID
+  );
+
+
+/**
+  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;
+  CHAR16      *PolicyName;
+  UINT8       CalculatedPriority;
+  UINTN       Index;
+
+  Result = FALSE;
+  CalculatedPriority = MATCH_PRIORITY_EXACT;
+
+  // Step 1: If the GUID doesn't match, we're done. No need to evaluate anything else.
+  if (!CompareGuid( &EvalEntry->Namespace, VendorGuid )) {
+    goto Exit;
+  }
+
+  // If the GUID matches, check to see whether there is a Name 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;
+  VARIABLE_POLICY_ENTRY   *CurrentEntry;
+  UINT8                   MatchPriority;
+  UINT8                   CurrentPriority;
+  UINTN                   Index;
+
+  BestResult = NULL;
+
+  // 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 )) {
+      // 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;
+  VARIABLE_LOCK_ON_VAR_STATE_POLICY   *StateVarPolicy;
+  CHAR16                              *StateVarName;
+  UINTN                               StateVarSize;
+  UINT8                               StateVar;
+
+  ReturnStatus = EFI_SUCCESS;
+
+  if (!IsVariablePolicyLibInitialized()) {
+    ReturnStatus = EFI_NOT_READY;
+    goto Exit;
+  }
+
+  // Bail if the protections are currently disabled.
+  if (mProtectionDisabled) {
+    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_WRITE_PROTECTED   Interface option is disabled by platform PCD.
+  @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;
+  }
+  if (!PcdGetBool (PcdAllowVariablePolicyEnforcementDisable)) {
+    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
+  )
+{
+  EFI_STATUS    Status;
+
+  Status = EFI_SUCCESS;
+  if (mGetVariableHelper != NULL) {
+    Status = EFI_ALREADY_STARTED;
+  }
+
+  if (!EFI_ERROR( Status )) {
+    Status = VariablePolicyExtraInit();
+  }
+
+  if (!EFI_ERROR( Status )) {
+    // 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 Status;
+}
+
+
+/**
+  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
+  )
+{
+  EFI_STATUS    Status;
+
+  Status = EFI_SUCCESS;
+
+  if (mGetVariableHelper == NULL) {
+    Status = EFI_NOT_READY;
+  }
+
+  if (!EFI_ERROR( Status )) {
+    Status = VariablePolicyExtraDeinit();
+  }
+
+  if (!EFI_ERROR( Status )) {
+    mGetVariableHelper = NULL;
+    mInterfaceLocked = FALSE;
+    mProtectionDisabled = FALSE;
+    mCurrentTableSize = 0;
+    mCurrentTableUsage = 0;
+    mCurrentTableCount = 0;
+
+    if (mPolicyTable != NULL) {
+      FreePool( mPolicyTable );
+      mPolicyTable = NULL;
+    }
+  }
+
+  return Status;
+}
diff --git a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePolicyUnitTest.c b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePolicyUnitTest.c
new file mode 100644
index 000000000000..f133f2f30e36
--- /dev/null
+++ b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePolicyUnitTest.c
@@ -0,0 +1,2436 @@
+/** @file -- VariablePolicyUnitTest.c
+UnitTest for...
+Business logic for Variable Policy enforcement.
+
+Copyright (c) Microsoft Corporation.
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <cmocka.h>
+
+#include <Uefi.h>
+#include <Library/PrintLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UnitTestLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseLib.h>
+
+#include <Guid/VariableFormat.h>
+
+#include <Protocol/VariablePolicy.h>
+#include <Library/VariablePolicyLib.h>
+
+// MU_CHANGE - Turn this off for now. Try to turn it back on 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 ===========================================================================
+
+/**
+  Helper function to initialize a VARIABLE_POLICY_ENTRY structure with a Name and StateName.
+
+  Takes care of all the messy packing.
+
+  @param[in,out]  Entry
+  @param[in]      Name        [Optional]
+  @param[in]      StateName   [Optional]
+
+  @retval     TRUE
+  @retval     FALSE
+
+**/
+STATIC
+BOOLEAN
+InitExpVarPolicyStrings (
+  EXPANDED_VARIABLE_POLICY_ENTRY      *Entry,
+  CHAR16                              *Name,      OPTIONAL
+  CHAR16                              *StateName  OPTIONAL
+  )
+{
+  UINTN     NameSize;
+  UINTN     StateNameSize;
+
+  NameSize = 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;
+}
+
+/**
+  Mocked version of GetVariable, for testing.
+**/
+EFI_STATUS
+EFIAPI
+StubGetVariableNull (
+  IN     CHAR16                      *VariableName,
+  IN     EFI_GUID                    *VendorGuid,
+  OUT    UINT32                      *Attributes,    OPTIONAL
+  IN OUT UINTN                       *DataSize,
+  OUT    VOID                        *Data           OPTIONAL
+  )
+{
+  UINT32      MockedAttr;
+  UINTN       MockedDataSize;
+  VOID        *MockedData;
+  EFI_STATUS  MockedReturn;
+
+  check_expected_ptr( VariableName );
+  check_expected_ptr( VendorGuid );
+  check_expected_ptr( DataSize );
+
+  MockedAttr = (UINT32)mock();
+  MockedDataSize = (UINTN)mock();
+  MockedData = (VOID*)mock();
+  MockedReturn = (EFI_STATUS)mock();
+
+  if (Attributes != NULL) {
+    *Attributes = MockedAttr;
+  }
+  if (Data != NULL && !EFI_ERROR(MockedReturn)) {
+    CopyMem( Data, MockedData, MockedDataSize );
+  }
+
+  *DataSize = MockedDataSize;
+
+  return MockedReturn;
+}
+
+//
+// Anything you think might be helpful that isn't a test itself.
+//
+
+/**
+  This is a common setup function that will ensure the library is always initialized
+  with the stubbed GetVariable.
+
+  Not used by all test cases, but by most.
+**/
+STATIC
+UNIT_TEST_STATUS
+LibInitMocked (
+  IN UNIT_TEST_CONTEXT      Context
+  )
+{
+  return EFI_ERROR(InitVariablePolicyLib( StubGetVariableNull )) ? UNIT_TEST_ERROR_PREREQUISITE_NOT_MET : UNIT_TEST_PASSED;
+}
+
+/**
+  Common cleanup function to make sure that the library is always de-initialized prior
+  to the next test case.
+*/
+STATIC
+VOID
+LibCleanup (
+  IN UNIT_TEST_CONTEXT      Context
+  )
+{
+  DeinitVariablePolicyLib();
+}
+
+
+///=== TEST CASES =================================================================================
+
+///===== ARCHITECTURAL SUITE ==================================================
+
+/**
+  Test Case
+*/
+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;
+}
+
+/**
+  Test Case
+*/
+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;
+}
+
+/**
+  Test Case
+*/
+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;
+}
+
+/**
+  Test Case
+*/
+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
+  );
+
+/**
+  Test Case
+*/
+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;
+}
+
+/**
+  Test Case
+*/
+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;
+}
+
+/**
+  Test Case
+*/
+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;
+}
+
+/**
+  Test Case
+*/
+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;
+}
+
+/**
+  Test Case
+*/
+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 ==============================================
+
+/**
+  Test Case
+*/
+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.Header ) );
+
+  return UNIT_TEST_PASSED;
+}
+
+/**
+  Test Case
+*/
+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.Header ) );
+
+  return UNIT_TEST_PASSED;
+}
+
+/**
+  Test Case
+*/
+UNIT_TEST_STATUS
+EFIAPI
+RegisterShouldRejectNullPointers (
+  IN UNIT_TEST_CONTEXT      Context
+  )
+{
+  UT_ASSERT_EQUAL( RegisterVariablePolicy( NULL ), EFI_INVALID_PARAMETER );
+  return UNIT_TEST_PASSED;
+}
+
+/**
+  Test Case
+*/
+UNIT_TEST_STATUS
+EFIAPI
+RegisterShouldRejectBadRevisions (
+  IN UNIT_TEST_CONTEXT      Context
+  )
+{
+  SIMPLE_VARIABLE_POLICY_ENTRY   ValidationPolicy = {
+    {
+      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;
+}
+
+/**
+  Test Case
+*/
+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;
+}
+
+/**
+  Test Case
+*/
+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;
+}
+
+/**
+  Test Case
+*/
+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;
+}
+
+/**
+  Test Case
+*/
+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;
+}
+
+/**
+  Test Case
+*/
+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;
+}
+
+/**
+  Test Case
+*/
+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;
+}
+
+/**
+  Test Case
+*/
+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;
+}
+
+/**
+  Test Case
+*/
+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;
+}
+
+/**
+  Test Case
+*/
+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;
+}
+
+/**
+  Test Case
+*/
+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;
+}
+
+/**
+  Test Case
+*/
+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.Header ) );
+  UT_ASSERT_STATUS_EQUAL( RegisterVariablePolicy( &ValidationPolicy.Header ), EFI_ALREADY_STARTED );
+
+  return UNIT_TEST_PASSED;
+}
+
+/**
+  Test Case
+*/
+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.Header ) );
+
+  // 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;
+}
+
+/**
+  Test Case
+*/
+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.Header ) );
+
+  // 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;
+}
+
+/**
+  Test Case
+*/
+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.Header ) );
+
+  // 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;
+}
+
+/**
+  Test Case
+*/
+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.Header ) );
+
+  // 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;
+}
+
+/**
+  Test Case
+*/
+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.Header ) );
+
+  // 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;
+}
+
+/**
+  Test Case
+*/
+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.Header ) );
+
+  // 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;
+}
+
+/**
+  Test Case
+*/
+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.Header ) );
+
+  // 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;
+}
+
+/**
+  Test Case
+*/
+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.Header ) );
+
+  // 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;
+}
+
+/**
+  Test Case
+*/
+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.Header ) );
+
+  // 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;
+}
+
+/**
+  Test Case
+*/
+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.Header ) );
+  ValidationPolicy.Header.Size += (UINT16)PolicyNameSize;
+  ValidationPolicy.Header.MaxSize = 50;
+  CopyMem( PolicyName, FourWildcards, PolicyNameSize );
+  UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Header ) );
+  ValidationPolicy.Header.MaxSize = 40;
+  CopyMem( PolicyName, ThreeWildcards, PolicyNameSize );
+  UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Header ) );
+  ValidationPolicy.Header.MaxSize = 30;
+  CopyMem( PolicyName, TwoWildcards, PolicyNameSize );
+  UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Header ) );
+  ValidationPolicy.Header.MaxSize = 20;
+  CopyMem( PolicyName, OneWildcard, PolicyNameSize );
+  UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Header ) );
+  ValidationPolicy.Header.MaxSize = 10;
+  CopyMem( PolicyName, NoWildcards, PolicyNameSize );
+  UT_ASSERT_NOT_EFI_ERROR( RegisterVariablePolicy( &ValidationPolicy.Header ) );
+
+  // 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 ===================================================
+
+/**
+  Test Case
+*/
+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;
+}
+
+/**
+  Test Case
+*/
+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;
+}
+
+/**
+  Test Case
+*/
+UNIT_TEST_STATUS
+EFIAPI
+ShouldNotBeAbleToDisablePoliciesTwice (
+  IN UNIT_TEST_CONTEXT      Context
+  )
+{
+  // Make sure that the policy enforcement is currently enabled.
+  UT_ASSERT_TRUE( IsVariablePolicyEnabled() );
+  // Disable the policy enforcement.
+  UT_ASSERT_NOT_EFI_ERROR( DisableVariablePolicy() );
+  // Make sure that the policy enforcement is currently disabled.
+  UT_ASSERT_FALSE( IsVariablePolicyEnabled() );
+  // Try to disable again and verify failure.
+  UT_ASSERT_TRUE( EFI_ERROR( DisableVariablePolicy() ) );
+
+  return UNIT_TEST_PASSED;
+}
+
+/**
+  Test Case
+*/
+UNIT_TEST_STATUS
+EFIAPI
+ShouldBeAbleToAddNewPoliciesAfterDisabled (
+  IN UNIT_TEST_CONTEXT      Context
+  )
+{
+  SIMPLE_VARIABLE_POLICY_ENTRY   TestPolicy = {
+    {
+      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;
+}
+
+/**
+  Test Case
+*/
+UNIT_TEST_STATUS
+EFIAPI
+ShouldBeAbleToLockAfterDisabled (
+  IN UNIT_TEST_CONTEXT      Context
+  )
+{
+  // Make sure that the policy enforcement is currently enabled.
+  UT_ASSERT_TRUE( IsVariablePolicyEnabled() );
+  // Disable the policy enforcement.
+  UT_ASSERT_NOT_EFI_ERROR( DisableVariablePolicy() );
+
+  // Make sure that we can lock in this state.
+  UT_ASSERT_FALSE( IsVariablePolicyInterfaceLocked() );
+  UT_ASSERT_NOT_EFI_ERROR( LockVariablePolicy() );
+  UT_ASSERT_TRUE( IsVariablePolicyInterfaceLocked() );
+
+  return UNIT_TEST_PASSED;
+}
+
+/**
+  Test Case
+*/
+UNIT_TEST_STATUS
+EFIAPI
+ShouldBeAbleToDumpThePolicyTable (
+  IN UNIT_TEST_CONTEXT      Context
+  )
+{
+  SIMPLE_VARIABLE_POLICY_ENTRY   TestPolicy = {
+    {
+      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;
+}
+
+/**
+  Test Case
+*/
+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 != NULL)
+  {
+    FreeUnitTestFramework( Framework );
+  }
+
+  return Status;
+}
diff --git a/MdeModulePkg/Include/Library/VariablePolicyLib.h b/MdeModulePkg/Include/Library/VariablePolicyLib.h
new file mode 100644
index 000000000000..efd1840112ec
--- /dev/null
+++ b/MdeModulePkg/Include/Library/VariablePolicyLib.h
@@ -0,0 +1,207 @@
+/** @file -- VariablePolicyLib.h
+Business logic for Variable Policy enforcement.
+
+Copyright (c) Microsoft Corporation.
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _VARIABLE_POLICY_LIB_H_
+#define _VARIABLE_POLICY_LIB_H_
+
+#include <Protocol/VariablePolicy.h>
+
+/**
+  This API function validates and registers a new policy 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_WRITE_PROTECTED   Interface option is disabled by platform PCD.
+  @retval     EFI_NOT_READY   Library has not yet been initialized.
+
+**/
+EFI_STATUS
+EFIAPI
+DisableVariablePolicy (
+  VOID
+  );
+
+
+/**
+  This API function will dump the entire contents of the 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..f4a879d5382f
--- /dev/null
+++ b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf
@@ -0,0 +1,44 @@
+## @file VariablePolicyLib.inf
+# Business logic for Variable Policy enforcement.
+#
+##
+# Copyright (c) Microsoft Corporation.
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+
+[Defines]
+  INF_VERSION         = 0x00010017
+  BASE_NAME           = VariablePolicyLib
+  FILE_GUID           = E9ECD342-159A-4F24-9FDF-65724027C594
+  VERSION_STRING      = 1.0
+  MODULE_TYPE         = DXE_DRIVER
+  LIBRARY_CLASS       = VariablePolicyLib|DXE_DRIVER DXE_SMM_DRIVER MM_STANDALONE
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = ANY
+#
+
+
+[Sources]
+  VariablePolicyLib.c
+  VariablePolicyExtraInitNull.c
+
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+
+
+[LibraryClasses]
+  DebugLib
+  BaseMemoryLib
+  MemoryAllocationLib
+  SafeIntLib
+  PcdLib
+
+
+[Pcd]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAllowVariablePolicyEnforcementDisable     ## CONSUMES
diff --git a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.uni b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.uni
new file mode 100644
index 000000000000..2227ec427828
--- /dev/null
+++ b/MdeModulePkg/Library/VariablePolicyLib/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/VariablePolicyLibRuntimeDxe.inf b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf
new file mode 100644
index 000000000000..8b8365741864
--- /dev/null
+++ b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf
@@ -0,0 +1,51 @@
+## @file VariablePolicyLibRuntimeDxe.inf
+# Business logic for Variable Policy enforcement.
+# This instance is specifically for RuntimeDxe and contains
+# extra routines to register for VirtualAddressChangeEvents.
+#
+# Copyright (c) Microsoft Corporation.
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+
+[Defines]
+  INF_VERSION         = 0x00010017
+  BASE_NAME           = VariablePolicyLibRuntimeDxe
+  FILE_GUID           = 205F7F0E-8EAC-4914-8390-1B90DD7E2A27
+  VERSION_STRING      = 1.0
+  MODULE_TYPE         = DXE_RUNTIME_DRIVER
+  LIBRARY_CLASS       = VariablePolicyLib|DXE_RUNTIME_DRIVER
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = ANY
+#
+
+
+[Sources]
+  VariablePolicyLib.c
+  VariablePolicyExtraInitRuntimeDxe.c
+
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+
+
+[LibraryClasses]
+  DebugLib
+  BaseMemoryLib
+  MemoryAllocationLib
+  SafeIntLib
+  UefiBootServicesTableLib
+  UefiRuntimeServicesTableLib
+  PcdLib
+
+
+[Pcd]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAllowVariablePolicyEnforcementDisable     ## CONSUMES
+
+
+[Guids]
+  gEfiEventVirtualAddressChangeGuid
diff --git a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePolicyUnitTest.inf b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePolicyUnitTest.inf
new file mode 100644
index 000000000000..ccc04bb600d6
--- /dev/null
+++ b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePolicyUnitTest.inf
@@ -0,0 +1,40 @@
+## @file VariablePolicyUnitTest.inf
+# UnitTest for...
+# Business logic for Variable Policy enforcement.
+#
+# Copyright (c) Microsoft Corporation.
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+
+[Defines]
+  INF_VERSION                    = 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 05d8ad4931f9..0b58c14e4747 100644
--- a/MdeModulePkg/MdeModulePkg.dec
+++ b/MdeModulePkg/MdeModulePkg.dec
@@ -31,6 +31,9 @@ [LibraryClasses]
   ##  @libraryclass  Defines a set of methods to reset whole system.
   ResetSystemLib|Include/Library/ResetSystemLib.h
 
+  ##  @libraryclass  Business logic for storing and testing variable 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 25aea3e2a481..14b6ed536962 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 @@ [LibraryClasses]
   DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf
   DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf
   UefiBootManagerLib|MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf
+  VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf
   #
   # Generic Modules
   #
@@ -129,6 +131,7 @@ [LibraryClasses.common.DXE_RUNTIME_DRIVER]
   DebugLib|MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf
   LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxDxeLib.inf
   CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf
+  VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf
 
 [LibraryClasses.common.SMM_CORE]
   HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
@@ -306,6 +309,8 @@ [Components]
   MdeModulePkg/Library/BootLogoLib/BootLogoLib.inf
   MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf
   MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf
+  MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf
+  MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf
   MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf
   MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLib.inf
   MdeModulePkg/Library/VarCheckPcdLib/VarCheckPcdLib.inf
diff --git a/MdeModulePkg/Test/MdeModulePkgHostTest.dsc b/MdeModulePkg/Test/MdeModulePkgHostTest.dsc
index 72a119db4568..095e613f1be1 100644
--- a/MdeModulePkg/Test/MdeModulePkgHostTest.dsc
+++ b/MdeModulePkg/Test/MdeModulePkgHostTest.dsc
@@ -19,12 +19,23 @@ [Defines]
 
 !include UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc
 
+[LibraryClasses]
+  SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf
+
 [Components]
   MdeModulePkg/Library/DxeResetSystemLib/UnitTest/MockUefiRuntimeServicesTableLib.inf
 
   #
   # Build MdeModulePkg HOST_APPLICATION Tests
   #
+  MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePolicyUnitTest.inf {
+    <LibraryClasses>
+      VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf
+
+    <PcdsFixedAtBuild>
+      gEfiMdeModulePkgTokenSpaceGuid.PcdAllowVariablePolicyEnforcementDisable|TRUE
+  }
+
   MdeModulePkg/Library/DxeResetSystemLib/UnitTest/DxeResetSystemLibUnitTestHost.inf {
     <LibraryClasses>
       ResetSystemLib|MdeModulePkg/Library/DxeResetSystemLib/DxeResetSystemLib.inf
-- 
2.26.2.windows.1.8.g01c50adf56.20200515075929


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH v6 03/14] MdeModulePkg: Define the VariablePolicyHelperLib
  2020-06-23  6:40 [PATCH v6 00/14] Add the VariablePolicy feature bret
  2020-06-23  6:40 ` [PATCH v6 01/14] MdeModulePkg: Define the VariablePolicy protocol interface Bret Barkelew
  2020-06-23  6:40 ` [PATCH v6 02/14] MdeModulePkg: Define the VariablePolicyLib Bret Barkelew
@ 2020-06-23  6:40 ` Bret Barkelew
  2020-06-23  6:40 ` [PATCH v6 04/14] MdeModulePkg: Define the VarCheckPolicyLib and SMM interface Bret Barkelew
                   ` (13 subsequent siblings)
  16 siblings, 0 replies; 48+ messages in thread
From: Bret Barkelew @ 2020-06-23  6:40 UTC (permalink / raw)
  To: devel; +Cc: Jian J Wang, Hao A Wu, Liming Gao

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

VariablePolicy is an updated interface to
replace VarLock and VarCheckProtocol.

Add the VariablePolicyHelperLib library, containing
several functions to help with the repetitive process
of creating a correctly structured and packed
VariablePolicy entry.

Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Hao A Wu <hao.a.wu@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Bret Barkelew <brbarkel@microsoft.com>
Signed-off-by: Bret Barkelew <brbarkel@microsoft.com>
---
 MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.c   | 396 ++++++++++++++++++++
 MdeModulePkg/Include/Library/VariablePolicyHelperLib.h                   | 164 ++++++++
 MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf |  35 ++
 MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.uni |  12 +
 MdeModulePkg/MdeModulePkg.dec                                            |   5 +
 MdeModulePkg/MdeModulePkg.dsc                                            |   2 +
 6 files changed, 614 insertions(+)

diff --git a/MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.c b/MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.c
new file mode 100644
index 000000000000..0c9299c8b0e1
--- /dev/null
+++ b/MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.c
@@ -0,0 +1,396 @@
+/** @file -- VariablePolicyHelperLib.c
+This library contains helper functions for marshalling and registering
+new policies with the VariablePolicy infrastructure.
+
+This library is currently written against VariablePolicy revision 0x00010000.
+
+Copyright (c) Microsoft Corporation.
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+#include <Protocol/VariablePolicy.h>
+
+/**
+  This internal helper function populates the header structure,
+  all common fields, and takes care of fix-ups.
+
+  NOTE: Only use this internally. Assumes correctly-sized buffers.
+
+  @param[out] EntPtr      Pointer to the buffer to be populated.
+  @param[in]  Namespace   Pointer to an EFI_GUID for the target variable namespace that this policy will protect.
+  @param[in]  MinSize     MinSize for the VariablePolicy.
+  @param[in]  MaxSize     MaxSize for the VariablePolicy.
+  @param[in]  AttributesMustHave    AttributesMustHave for the VariablePolicy.
+  @param[in]  AttributesCantHave    AttributesCantHave for the VariablePolicy.
+  @param[in]  LockPolicyType        LockPolicyType for the VariablePolicy.
+
+**/
+STATIC
+VOID
+PopulateCommonData (
+  OUT VARIABLE_POLICY_ENTRY   *EntPtr,
+  IN CONST  EFI_GUID          *Namespace,
+  IN        UINT32            MinSize,
+  IN        UINT32            MaxSize,
+  IN        UINT32            AttributesMustHave,
+  IN        UINT32            AttributesCantHave,
+  IN        UINT8             LockPolicyType
+  )
+{
+  EntPtr->Version             = VARIABLE_POLICY_ENTRY_REVISION;
+  CopyGuid( &EntPtr->Namespace, Namespace );
+  EntPtr->MinSize             = MinSize;
+  EntPtr->MaxSize             = MaxSize;
+  EntPtr->AttributesMustHave  = AttributesMustHave;
+  EntPtr->AttributesCantHave  = AttributesCantHave;
+  EntPtr->LockPolicyType      = LockPolicyType;
+
+  // NOTE: As a heler, fix up MaxSize for compatibility with the old model.
+  if (EntPtr->MaxSize == 0) {
+    EntPtr->MaxSize = VARIABLE_POLICY_NO_MAX_SIZE;
+  }
+
+  return;
+}
+
+
+/**
+  This helper function will allocate and populate a new VariablePolicy
+  structure for a policy that does not contain any sub-structures (such as
+  VARIABLE_LOCK_ON_VAR_STATE_POLICY).
+
+  NOTE: Caller will need to free structure once finished.
+
+  @param[in]  Namespace   Pointer to an EFI_GUID for the target variable namespace that this policy will protect.
+  @param[in]  Name        [Optional] If provided, a pointer to the CHAR16 array for the target variable name.
+                          Otherwise, will create a policy that targets an entire namespace.
+  @param[in]  MinSize     MinSize for the VariablePolicy.
+  @param[in]  MaxSize     MaxSize for the VariablePolicy.
+  @param[in]  AttributesMustHave    AttributesMustHave for the VariablePolicy.
+  @param[in]  AttributesCantHave    AttributesCantHave for the VariablePolicy.
+  @param[in]  LockPolicyType        LockPolicyType for the VariablePolicy.
+  @param[out] NewEntry    If successful, will be set to a pointer to the allocated buffer containing the
+                          new policy.
+
+  @retval     EFI_SUCCESS             Operation completed successfully and structure is populated.
+  @retval     EFI_INVALID_PARAMETER   Namespace is NULL.
+  @retval     EFI_INVALID_PARAMETER   LockPolicyType is invalid for a basic structure.
+  @retval     EFI_BUFFER_TOO_SMALL    Finished structure would not fit in UINT16 size.
+  @retval     EFI_OUT_OF_RESOURCES    Could not allocate sufficient space for structure.
+
+**/
+EFI_STATUS
+EFIAPI
+CreateBasicVariablePolicy (
+  IN CONST  EFI_GUID          *Namespace,
+  IN CONST  CHAR16            *Name OPTIONAL,
+  IN        UINT32            MinSize,
+  IN        UINT32            MaxSize,
+  IN        UINT32            AttributesMustHave,
+  IN        UINT32            AttributesCantHave,
+  IN        UINT8             LockPolicyType,
+  OUT VARIABLE_POLICY_ENTRY   **NewEntry
+  )
+{
+  UINTN                   TotalSize;
+  UINTN                   NameSize;
+  VARIABLE_POLICY_ENTRY   *EntPtr;
+  CHAR16                  *CopyName;
+
+  // Check some initial invalid parameters for this function.
+  if (Namespace == NULL || NewEntry == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+  if (LockPolicyType != VARIABLE_POLICY_TYPE_NO_LOCK &&
+      LockPolicyType != VARIABLE_POLICY_TYPE_LOCK_NOW &&
+      LockPolicyType != VARIABLE_POLICY_TYPE_LOCK_ON_CREATE) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // Now we've gotta determine the total size of the buffer required for
+  // the VariablePolicy structure.
+  TotalSize = sizeof( VARIABLE_POLICY_ENTRY );
+  if (Name != NULL) {
+    NameSize = StrnSizeS( Name, MAX_UINT16 );
+    TotalSize += NameSize;
+  }
+  // Make sure the size fits within a VARIABLE_POLICY_ENTRY.Size.
+  ASSERT( TotalSize <= MAX_UINT16 );
+  if (TotalSize > MAX_UINT16) {
+    return EFI_BUFFER_TOO_SMALL;
+  }
+
+  // Allocate a buffer to hold all the data. We're on the home stretch.
+  *NewEntry = AllocatePool( TotalSize );
+  if (*NewEntry == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  // If we're still here, we're basically done.
+  // Copy the data and GET... OUT....
+  EntPtr = *NewEntry;
+  PopulateCommonData ( EntPtr,
+                       Namespace,
+                       MinSize,
+                       MaxSize,
+                       AttributesMustHave,
+                       AttributesCantHave,
+                       LockPolicyType );
+  EntPtr->Size                = (UINT16)TotalSize;      // This is safe because we've already checked.
+  EntPtr->OffsetToName        = sizeof(VARIABLE_POLICY_ENTRY);
+  if (Name != NULL) {
+    CopyName = (CHAR16*)((UINT8*)EntPtr + EntPtr->OffsetToName);
+    CopyMem( CopyName, Name, NameSize );
+  }
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  This helper function will allocate and populate a new VariablePolicy
+  structure for a policy with a lock type of VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE.
+
+  NOTE: Caller will need to free structure once finished.
+
+  @param[in]  Namespace   Pointer to an EFI_GUID for the target variable namespace that this policy will protect.
+  @param[in]  Name        [Optional] If provided, a pointer to the CHAR16 array for the target variable name.
+                          Otherwise, will create a policy that targets an entire namespace.
+  @param[in]  MinSize     MinSize for the VariablePolicy.
+  @param[in]  MaxSize     MaxSize for the VariablePolicy.
+  @param[in]  AttributesMustHave    AttributesMustHave for the VariablePolicy.
+  @param[in]  AttributesCantHave    AttributesCantHave for the VariablePolicy.
+  @param[in]  VarStateNamespace     Pointer to the EFI_GUID for the VARIABLE_LOCK_ON_VAR_STATE_POLICY.Namespace.
+  @param[in]  VarStateValue         Value for the VARIABLE_LOCK_ON_VAR_STATE_POLICY.Value.
+  @param[in]  VarStateName          Pointer to the CHAR16 array for the VARIABLE_LOCK_ON_VAR_STATE_POLICY.Name.
+  @param[out] NewEntry    If successful, will be set to a pointer to the allocated buffer containing the
+                          new policy.
+
+  @retval     EFI_SUCCESS             Operation completed successfully and structure is populated.
+  @retval     EFI_INVALID_PARAMETER   Namespace, VarStateNamespace, VarStateName is NULL.
+  @retval     EFI_BUFFER_TOO_SMALL    Finished structure would not fit in UINT16 size.
+  @retval     EFI_OUT_OF_RESOURCES    Could not allocate sufficient space for structure.
+
+**/
+EFI_STATUS
+EFIAPI
+CreateVarStateVariablePolicy (
+  IN CONST  EFI_GUID          *Namespace,
+  IN CONST  CHAR16            *Name OPTIONAL,
+  IN        UINT32            MinSize,
+  IN        UINT32            MaxSize,
+  IN        UINT32            AttributesMustHave,
+  IN        UINT32            AttributesCantHave,
+  IN CONST  EFI_GUID          *VarStateNamespace,
+  IN        UINT8             VarStateValue,
+  IN CONST  CHAR16            *VarStateName,
+  OUT VARIABLE_POLICY_ENTRY   **NewEntry
+  )
+{
+  UINTN                   TotalSize;
+  UINTN                   NameSize;
+  UINTN                   VarStateNameSize;
+  VARIABLE_POLICY_ENTRY   *EntPtr;
+  CHAR16                  *CopyName;
+  VARIABLE_LOCK_ON_VAR_STATE_POLICY *CopyPolicy;
+
+  // Check some initial invalid parameters for this function.
+  if (Namespace == NULL || VarStateNamespace == NULL ||
+      VarStateName == NULL || NewEntry == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // Now we've gotta determine the total size of the buffer required for
+  // the VariablePolicy structure.
+  VarStateNameSize = StrnSizeS( VarStateName, MAX_UINT16 );
+  TotalSize = sizeof( VARIABLE_POLICY_ENTRY ) +
+                sizeof(VARIABLE_LOCK_ON_VAR_STATE_POLICY) +
+                VarStateNameSize;
+  if (Name != NULL) {
+    NameSize = StrnSizeS( Name, MAX_UINT16 );
+    TotalSize += NameSize;
+  }
+  // Make sure the size fits within a VARIABLE_POLICY_ENTRY.Size.
+  ASSERT( TotalSize <= MAX_UINT16 );
+  if (TotalSize > MAX_UINT16) {
+    return EFI_BUFFER_TOO_SMALL;
+  }
+
+  // Allocate a buffer to hold all the data. We're on the home stretch.
+  *NewEntry = AllocatePool( TotalSize );
+  if (*NewEntry == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  // If we're still here, we're basically done.
+  // Copy the data and GET... OUT....
+  EntPtr = *NewEntry;
+  PopulateCommonData ( EntPtr,
+                       Namespace,
+                       MinSize,
+                       MaxSize,
+                       AttributesMustHave,
+                       AttributesCantHave,
+                       VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE );
+  EntPtr->Size                = (UINT16)TotalSize;      // This is safe because we've already checked.
+  EntPtr->OffsetToName        = sizeof(VARIABLE_POLICY_ENTRY) +
+                                sizeof(VARIABLE_LOCK_ON_VAR_STATE_POLICY) +
+                                (UINT16)VarStateNameSize;
+
+  CopyPolicy = (VARIABLE_LOCK_ON_VAR_STATE_POLICY*)((UINT8*)EntPtr + sizeof(VARIABLE_POLICY_ENTRY));
+  CopyName = (CHAR16*)((UINT8*)CopyPolicy + sizeof(VARIABLE_LOCK_ON_VAR_STATE_POLICY));
+  CopyGuid( &CopyPolicy->Namespace, VarStateNamespace );
+  CopyPolicy->Value = VarStateValue;
+  CopyMem( CopyName, VarStateName, VarStateNameSize );
+
+  if (Name != NULL) {
+    CopyName = (CHAR16*)((UINT8*)EntPtr + EntPtr->OffsetToName);
+    CopyMem( CopyName, Name, NameSize );
+  }
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  This helper function does everything that CreateBasicVariablePolicy() does, but also
+  uses the passed in protocol to register the policy with the infrastructure.
+  Does not return a buffer, does not require the caller to free anything.
+
+  @param[in]  VariablePolicy  Pointer to a valid instance of the VariablePolicy protocol.
+  @param[in]  Namespace   Pointer to an EFI_GUID for the target variable namespace that this policy will protect.
+  @param[in]  Name        [Optional] If provided, a pointer to the CHAR16 array for the target variable name.
+                          Otherwise, will create a policy that targets an entire namespace.
+  @param[in]  MinSize     MinSize for the VariablePolicy.
+  @param[in]  MaxSize     MaxSize for the VariablePolicy.
+  @param[in]  AttributesMustHave    AttributesMustHave for the VariablePolicy.
+  @param[in]  AttributesCantHave    AttributesCantHave for the VariablePolicy.
+  @param[in]  LockPolicyType        LockPolicyType for the VariablePolicy.
+
+  @retval     EFI_INVALID_PARAMETER VariablePolicy pointer is NULL.
+  @retval     EFI_STATUS            Status returned by CreateBasicVariablePolicy() or RegisterVariablePolicy().
+
+**/
+EFI_STATUS
+EFIAPI
+RegisterBasicVariablePolicy (
+  IN        EDKII_VARIABLE_POLICY_PROTOCOL  *VariablePolicy,
+  IN CONST  EFI_GUID                        *Namespace,
+  IN CONST  CHAR16                          *Name OPTIONAL,
+  IN        UINT32                          MinSize,
+  IN        UINT32                          MaxSize,
+  IN        UINT32                          AttributesMustHave,
+  IN        UINT32                          AttributesCantHave,
+  IN        UINT8                           LockPolicyType
+  )
+{
+  VARIABLE_POLICY_ENTRY   *NewEntry;
+  EFI_STATUS              Status;
+
+  // Check the simple things.
+  if (VariablePolicy == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // Create the new entry and make sure that everything worked.
+  NewEntry = NULL;
+  Status = CreateBasicVariablePolicy( Namespace,
+                                      Name,
+                                      MinSize,
+                                      MaxSize,
+                                      AttributesMustHave,
+                                      AttributesCantHave,
+                                      LockPolicyType,
+                                      &NewEntry );
+
+  // If that was successful, attempt to register the new policy.
+  if (!EFI_ERROR( Status )) {
+    Status = VariablePolicy->RegisterVariablePolicy( NewEntry );
+  }
+
+  // If we allocated the buffer, free the buffer.
+  if (NewEntry != NULL) {
+    FreePool( NewEntry );
+  }
+
+  return Status;
+}
+
+
+/**
+  This helper function does everything that CreateBasicVariablePolicy() does, but also
+  uses the passed in protocol to register the policy with the infrastructure.
+  Does not return a buffer, does not require the caller to free anything.
+
+  @param[in]  VariablePolicy  Pointer to a valid instance of the VariablePolicy protocol.
+  @param[in]  Namespace   Pointer to an EFI_GUID for the target variable namespace that this policy will protect.
+  @param[in]  Name        [Optional] If provided, a pointer to the CHAR16 array for the target variable name.
+                          Otherwise, will create a policy that targets an entire namespace.
+  @param[in]  MinSize     MinSize for the VariablePolicy.
+  @param[in]  MaxSize     MaxSize for the VariablePolicy.
+  @param[in]  AttributesMustHave    AttributesMustHave for the VariablePolicy.
+  @param[in]  AttributesCantHave    AttributesCantHave for the VariablePolicy.
+  @param[in]  VarStateNamespace     Pointer to the EFI_GUID for the VARIABLE_LOCK_ON_VAR_STATE_POLICY.Namespace.
+  @param[in]  VarStateName          Pointer to the CHAR16 array for the VARIABLE_LOCK_ON_VAR_STATE_POLICY.Name.
+  @param[in]  VarStateValue         Value for the VARIABLE_LOCK_ON_VAR_STATE_POLICY.Value.
+
+  @retval     EFI_INVALID_PARAMETER VariablePolicy pointer is NULL.
+  @retval     EFI_STATUS    Status returned by CreateBasicVariablePolicy() or RegisterVariablePolicy().
+
+**/
+EFI_STATUS
+EFIAPI
+RegisterVarStateVariablePolicy (
+  IN        EDKII_VARIABLE_POLICY_PROTOCOL  *VariablePolicy,
+  IN CONST  EFI_GUID                        *Namespace,
+  IN CONST  CHAR16                          *Name OPTIONAL,
+  IN        UINT32                          MinSize,
+  IN        UINT32                          MaxSize,
+  IN        UINT32                          AttributesMustHave,
+  IN        UINT32                          AttributesCantHave,
+  IN CONST  EFI_GUID                        *VarStateNamespace,
+  IN CONST  CHAR16                          *VarStateName,
+  IN        UINT8                           VarStateValue
+  )
+{
+  VARIABLE_POLICY_ENTRY   *NewEntry;
+  EFI_STATUS              Status;
+
+  // Check the simple things.
+  if (VariablePolicy == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // Create the new entry and make sure that everything worked.
+  NewEntry = NULL;
+  Status = CreateVarStateVariablePolicy( Namespace,
+                                         Name,
+                                         MinSize,
+                                         MaxSize,
+                                         AttributesMustHave,
+                                         AttributesCantHave,
+                                         VarStateNamespace,
+                                         VarStateValue,
+                                         VarStateName,
+                                         &NewEntry );
+
+  // If that was successful, attempt to register the new policy.
+  if (!EFI_ERROR( Status )) {
+    Status = VariablePolicy->RegisterVariablePolicy( NewEntry );
+  }
+
+  // If we allocated the buffer, free the buffer.
+  if (NewEntry != NULL) {
+    FreePool( NewEntry );
+  }
+
+  return Status;
+}
diff --git a/MdeModulePkg/Include/Library/VariablePolicyHelperLib.h b/MdeModulePkg/Include/Library/VariablePolicyHelperLib.h
new file mode 100644
index 000000000000..3b75e9786094
--- /dev/null
+++ b/MdeModulePkg/Include/Library/VariablePolicyHelperLib.h
@@ -0,0 +1,164 @@
+/** @file -- VariablePolicyHelperLib.h
+This library contains helper functions for marshalling and registering
+new policies with the VariablePolicy infrastructure.
+
+Copyright (c) Microsoft Corporation.
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _EDKII_VARIABLE_POLICY_HELPER_LIB_H_
+#define _EDKII_VARIABLE_POLICY_HELPER_LIB_H_
+
+#include <Protocol/VariablePolicy.h>
+
+/**
+  This helper function will allocate and populate a new VariablePolicy
+  structure for a policy that does not contain any sub-structures (such as
+  VARIABLE_LOCK_ON_VAR_STATE_POLICY).
+
+  NOTE: Caller will need to free structure once finished.
+
+  @param[in]  Namespace   Pointer to an EFI_GUID for the target variable namespace that this policy will protect.
+  @param[in]  Name        [Optional] If provided, a pointer to the CHAR16 array for the target variable name.
+                          Otherwise, will create a policy that targets an entire namespace.
+  @param[in]  MinSize     MinSize for the VariablePolicy.
+  @param[in]  MaxSize     MaxSize for the VariablePolicy.
+  @param[in]  AttributesMustHave    AttributesMustHave for the VariablePolicy.
+  @param[in]  AttributesCantHave    AttributesCantHave for the VariablePolicy.
+  @param[in]  LockPolicyType        LockPolicyType for the VariablePolicy.
+  @param[out] NewEntry    If successful, will be set to a pointer to the allocated buffer containing the
+                          new policy.
+
+  @retval     EFI_SUCCESS             Operation completed successfully and structure is populated.
+  @retval     EFI_INVALID_PARAMETER   Namespace is NULL.
+  @retval     EFI_INVALID_PARAMETER   LockPolicyType is invalid for a basic structure.
+  @retval     EFI_BUFFER_TOO_SMALL    Finished structure would not fit in UINT16 size.
+  @retval     EFI_OUT_OF_RESOURCES    Could not allocate sufficient space for structure.
+
+**/
+EFI_STATUS
+EFIAPI
+CreateBasicVariablePolicy (
+  IN CONST  EFI_GUID          *Namespace,
+  IN CONST  CHAR16            *Name OPTIONAL,
+  IN        UINT32            MinSize,
+  IN        UINT32            MaxSize,
+  IN        UINT32            AttributesMustHave,
+  IN        UINT32            AttributesCantHave,
+  IN        UINT8             LockPolicyType,
+  OUT VARIABLE_POLICY_ENTRY   **NewEntry
+  );
+
+
+/**
+  This helper function will allocate and populate a new VariablePolicy
+  structure for a policy with a lock type of VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE.
+
+  NOTE: Caller will need to free structure once finished.
+
+  @param[in]  Namespace   Pointer to an EFI_GUID for the target variable namespace that this policy will protect.
+  @param[in]  Name        [Optional] If provided, a pointer to the CHAR16 array for the target variable name.
+                          Otherwise, will create a policy that targets an entire namespace.
+  @param[in]  MinSize     MinSize for the VariablePolicy.
+  @param[in]  MaxSize     MaxSize for the VariablePolicy.
+  @param[in]  AttributesMustHave    AttributesMustHave for the VariablePolicy.
+  @param[in]  AttributesCantHave    AttributesCantHave for the VariablePolicy.
+  @param[in]  VarStateNamespace     Pointer to the EFI_GUID for the VARIABLE_LOCK_ON_VAR_STATE_POLICY.Namespace.
+  @param[in]  VarStateValue         Value for the VARIABLE_LOCK_ON_VAR_STATE_POLICY.Value.
+  @param[in]  VarStateName          Pointer to the CHAR16 array for the VARIABLE_LOCK_ON_VAR_STATE_POLICY.Name.
+  @param[out] NewEntry    If successful, will be set to a pointer to the allocated buffer containing the
+                          new policy.
+
+  @retval     EFI_SUCCESS             Operation completed successfully and structure is populated.
+  @retval     EFI_INVALID_PARAMETER   Namespace, VarStateNamespace, VarStateName is NULL.
+  @retval     EFI_BUFFER_TOO_SMALL    Finished structure would not fit in UINT16 size.
+  @retval     EFI_OUT_OF_RESOURCES    Could not allocate sufficient space for structure.
+
+**/
+EFI_STATUS
+EFIAPI
+CreateVarStateVariablePolicy (
+  IN CONST  EFI_GUID          *Namespace,
+  IN CONST  CHAR16            *Name OPTIONAL,
+  IN        UINT32            MinSize,
+  IN        UINT32            MaxSize,
+  IN        UINT32            AttributesMustHave,
+  IN        UINT32            AttributesCantHave,
+  IN CONST  EFI_GUID          *VarStateNamespace,
+  IN        UINT8             VarStateValue,
+  IN CONST  CHAR16            *VarStateName,
+  OUT VARIABLE_POLICY_ENTRY   **NewEntry
+  );
+
+
+/**
+  This helper function does everything that CreateBasicVariablePolicy() does, but also
+  uses the passed in protocol to register the policy with the infrastructure.
+  Does not return a buffer, does not require the caller to free anything.
+
+  @param[in]  VariablePolicy  Pointer to a valid instance of the VariablePolicy protocol.
+  @param[in]  Namespace   Pointer to an EFI_GUID for the target variable namespace that this policy will protect.
+  @param[in]  Name        [Optional] If provided, a pointer to the CHAR16 array for the target variable name.
+                          Otherwise, will create a policy that targets an entire namespace.
+  @param[in]  MinSize     MinSize for the VariablePolicy.
+  @param[in]  MaxSize     MaxSize for the VariablePolicy.
+  @param[in]  AttributesMustHave    AttributesMustHave for the VariablePolicy.
+  @param[in]  AttributesCantHave    AttributesCantHave for the VariablePolicy.
+  @param[in]  LockPolicyType        LockPolicyType for the VariablePolicy.
+
+  @retval     EFI_INVALID_PARAMETER VariablePolicy pointer is NULL.
+  @retval     EFI_STATUS            Status returned by CreateBasicVariablePolicy() or RegisterVariablePolicy().
+
+**/
+EFI_STATUS
+EFIAPI
+RegisterBasicVariablePolicy (
+  IN        EDKII_VARIABLE_POLICY_PROTOCOL  *VariablePolicy,
+  IN CONST  EFI_GUID                        *Namespace,
+  IN CONST  CHAR16                          *Name OPTIONAL,
+  IN        UINT32                          MinSize,
+  IN        UINT32                          MaxSize,
+  IN        UINT32                          AttributesMustHave,
+  IN        UINT32                          AttributesCantHave,
+  IN        UINT8                           LockPolicyType
+  );
+
+
+/**
+  This helper function does everything that CreateBasicVariablePolicy() does, but also
+  uses the passed in protocol to register the policy with the infrastructure.
+  Does not return a buffer, does not require the caller to free anything.
+
+  @param[in]  VariablePolicy  Pointer to a valid instance of the VariablePolicy protocol.
+  @param[in]  Namespace   Pointer to an EFI_GUID for the target variable namespace that this policy will protect.
+  @param[in]  Name        [Optional] If provided, a pointer to the CHAR16 array for the target variable name.
+                          Otherwise, will create a policy that targets an entire namespace.
+  @param[in]  MinSize     MinSize for the VariablePolicy.
+  @param[in]  MaxSize     MaxSize for the VariablePolicy.
+  @param[in]  AttributesMustHave    AttributesMustHave for the VariablePolicy.
+  @param[in]  AttributesCantHave    AttributesCantHave for the VariablePolicy.
+  @param[in]  VarStateNamespace     Pointer to the EFI_GUID for the VARIABLE_LOCK_ON_VAR_STATE_POLICY.Namespace.
+  @param[in]  VarStateName          Pointer to the CHAR16 array for the VARIABLE_LOCK_ON_VAR_STATE_POLICY.Name.
+  @param[in]  VarStateValue         Value for the VARIABLE_LOCK_ON_VAR_STATE_POLICY.Value.
+
+  @retval     EFI_INVALID_PARAMETER VariablePolicy pointer is NULL.
+  @retval     EFI_STATUS    Status returned by CreateBasicVariablePolicy() or RegisterVariablePolicy().
+
+**/
+EFI_STATUS
+EFIAPI
+RegisterVarStateVariablePolicy (
+  IN        EDKII_VARIABLE_POLICY_PROTOCOL  *VariablePolicy,
+  IN CONST  EFI_GUID                        *Namespace,
+  IN CONST  CHAR16                          *Name OPTIONAL,
+  IN        UINT32                          MinSize,
+  IN        UINT32                          MaxSize,
+  IN        UINT32                          AttributesMustHave,
+  IN        UINT32                          AttributesCantHave,
+  IN CONST  EFI_GUID                        *VarStateNamespace,
+  IN CONST  CHAR16                          *VarStateName,
+  IN        UINT8                           VarStateValue
+  );
+
+#endif // _EDKII_VARIABLE_POLICY_HELPER_LIB_H_
diff --git a/MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf b/MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf
new file mode 100644
index 000000000000..506abf580e94
--- /dev/null
+++ b/MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf
@@ -0,0 +1,35 @@
+## @file VariablePolicyHelperLib.inf
+# This library contains helper functions for marshalling and registering
+# new policies with the VariablePolicy infrastructure.
+#
+# This library is currently written against VariablePolicy revision 0x00010000.
+#
+# Copyright (c) Microsoft Corporation.
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+
+[Defines]
+  INF_VERSION         = 0x00010017
+  BASE_NAME           = VariablePolicyHelperLib
+  # MODULE_UNI_FILE   = VariablePolicyHelperLib.uni
+  FILE_GUID           = B3C2206B-FDD1-4AED-8352-FC5EC34C5630
+  VERSION_STRING      = 1.0
+  MODULE_TYPE         = BASE
+  LIBRARY_CLASS       = VariablePolicyHelperLib
+
+
+[Sources]
+  VariablePolicyHelperLib.c
+
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+
+
+[LibraryClasses]
+  BaseLib
+  DebugLib
+  MemoryAllocationLib
+  BaseMemoryLib
diff --git a/MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.uni b/MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.uni
new file mode 100644
index 000000000000..39cbf11a4ce9
--- /dev/null
+++ b/MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.uni
@@ -0,0 +1,12 @@
+// /** @file
+// VariablePolicyHelperLib.uni
+//
+// Copyright (c) Microsoft Corporation.
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT             #language en-US "Library containing helper functions for marshalling and registering new policies with the VariablePolicy infrastructure"
+
+#string STR_MODULE_DESCRIPTION          #language en-US "Library containing helper functions for marshalling and registering new policies with the VariablePolicy infrastructure"
diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec
index 0b58c14e4747..b21cd78c8787 100644
--- a/MdeModulePkg/MdeModulePkg.dec
+++ b/MdeModulePkg/MdeModulePkg.dec
@@ -149,6 +149,11 @@ [LibraryClasses]
   #
   DisplayUpdateProgressLib|Include/Library/DisplayUpdateProgressLib.h
 
+  ##  @libraryclass  This library contains helper functions for marshalling and
+  #   registering new policies with the VariablePolicy infrastructure.
+  #
+  VariablePolicyHelperLib|Include/Library/VariablePolicyHelperLib.h
+
 [Guids]
   ## MdeModule package token space guid
   # Include/Guid/MdeModulePkgTokenSpace.h
diff --git a/MdeModulePkg/MdeModulePkg.dsc b/MdeModulePkg/MdeModulePkg.dsc
index 14b6ed536962..37795b9e4f58 100644
--- a/MdeModulePkg/MdeModulePkg.dsc
+++ b/MdeModulePkg/MdeModulePkg.dsc
@@ -99,6 +99,7 @@ [LibraryClasses]
   BmpSupportLib|MdeModulePkg/Library/BaseBmpSupportLib/BaseBmpSupportLib.inf
   SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf
   DisplayUpdateProgressLib|MdeModulePkg/Library/DisplayUpdateProgressLibGraphics/DisplayUpdateProgressLibGraphics.inf
+  VariablePolicyHelperLib|MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf
 
 [LibraryClasses.EBC.PEIM]
   IoLib|MdePkg/Library/PeiIoLibCpuIo/PeiIoLibCpuIo.inf
@@ -225,6 +226,7 @@ [Components]
   MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf
   MdeModulePkg/Library/BaseHobLibNull/BaseHobLibNull.inf
   MdeModulePkg/Library/BaseMemoryAllocationLibNull/BaseMemoryAllocationLibNull.inf
+  MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf
 
   MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
   MdeModulePkg/Bus/Pci/PciSioSerialDxe/PciSioSerialDxe.inf
-- 
2.26.2.windows.1.8.g01c50adf56.20200515075929


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH v6 04/14] MdeModulePkg: Define the VarCheckPolicyLib and SMM interface
  2020-06-23  6:40 [PATCH v6 00/14] Add the VariablePolicy feature bret
                   ` (2 preceding siblings ...)
  2020-06-23  6:40 ` [PATCH v6 03/14] MdeModulePkg: Define the VariablePolicyHelperLib Bret Barkelew
@ 2020-06-23  6:40 ` Bret Barkelew
  2020-07-02  2:13   ` [edk2-devel] " Dandan Bi
  2020-06-23  6:40 ` [PATCH v6 05/14] OvmfPkg: Add VariablePolicy engine to OvmfPkg platform Bret Barkelew
                   ` (12 subsequent siblings)
  16 siblings, 1 reply; 48+ messages in thread
From: Bret Barkelew @ 2020-06-23  6:40 UTC (permalink / raw)
  To: devel; +Cc: Jian J Wang, Hao A Wu, Liming Gao

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

VariablePolicy is an updated interface to
replace VarLock and VarCheckProtocol.

This is an instance of a VarCheckLib that is backed by the
VariablePolicyLib business logic. It also publishes the SMM
calling interface for messages from the DXE protocol.

Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Hao A Wu <hao.a.wu@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Bret Barkelew <brbarkel@microsoft.com>
Signed-off-by: Bret Barkelew <brbarkel@microsoft.com>
---
 MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.c   | 320 ++++++++++++++++++++
 MdeModulePkg/Include/Guid/VarCheckPolicyMmi.h                |  54 ++++
 MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.inf |  42 +++
 MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.uni |  12 +
 MdeModulePkg/MdeModulePkg.dec                                |   4 +
 MdeModulePkg/MdeModulePkg.dsc                                |   2 +
 6 files changed, 434 insertions(+)

diff --git a/MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.c b/MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.c
new file mode 100644
index 000000000000..b64fc5f45332
--- /dev/null
+++ b/MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.c
@@ -0,0 +1,320 @@
+/** @file -- VarCheckPolicyLib.c
+This is an instance of a VarCheck lib that leverages the business logic behind
+the VariablePolicy code to make its decisions.
+
+Copyright (c) Microsoft Corporation.
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/VarCheckLib.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/SafeIntLib.h>
+#include <Library/MmServicesTableLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+#include <Protocol/MmCommunication.h>
+
+#include <Protocol/VariablePolicy.h>
+#include <Library/VariablePolicyLib.h>
+
+#include <Guid/VarCheckPolicyMmi.h>
+
+//================================================
+// As a VarCheck library, we're linked into the VariableServices
+// and may not be able to call them indirectly. To get around this,
+// use the internal GetVariable function to query the variable store.
+//================================================
+EFI_STATUS
+EFIAPI
+VariableServiceGetVariable (
+  IN      CHAR16            *VariableName,
+  IN      EFI_GUID          *VendorGuid,
+  OUT     UINT32            *Attributes OPTIONAL,
+  IN OUT  UINTN             *DataSize,
+  OUT     VOID              *Data
+  );
+
+
+/**
+  MM Communication Handler to recieve commands from the DXE protocol for
+  Variable Policies. This communication channel is used to register new policies
+  and poll and toggle the enforcement of variable policies.
+
+  @param[in]      DispatchHandle      All parameters standard to MM communications convention.
+  @param[in]      RegisterContext     All parameters standard to MM communications convention.
+  @param[in,out]  CommBuffer          All parameters standard to MM communications convention.
+  @param[in,out]  CommBufferSize      All parameters standard to MM communications convention.
+
+  @retval     EFI_SUCCESS
+  @retval     EFI_INVALID_PARAMETER   CommBuffer or CommBufferSize is null pointer.
+  @retval     EFI_INVALID_PARAMETER   CommBuffer size is wrong.
+  @retval     EFI_INVALID_PARAMETER   Revision or signature don't match.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+VarCheckPolicyLibMmiHandler (
+  IN     EFI_HANDLE                   DispatchHandle,
+  IN     CONST VOID                   *RegisterContext,
+  IN OUT VOID                         *CommBuffer,
+  IN OUT UINTN                        *CommBufferSize
+  )
+{
+  EFI_STATUS                                Status;
+  EFI_STATUS                                SubCommandStatus;
+  VAR_CHECK_POLICY_COMM_HEADER              *PolicyCommmHeader;
+  VAR_CHECK_POLICY_COMM_IS_ENABLED_PARAMS   *IsEnabledParams;
+  VAR_CHECK_POLICY_COMM_DUMP_PARAMS         *DumpParams;
+  UINT8                                     *DumpInputBuffer;
+  UINT8                                     *DumpOutputBuffer;
+  UINTN                                     DumpTotalPages;
+  VARIABLE_POLICY_ENTRY                     *PolicyEntry;
+  UINTN                                     ExpectedSize;
+  // Pagination Cache Variables
+  static UINT8                              *PaginationCache = NULL;
+  static UINTN                              PaginationCacheSize = 0;
+  static UINT32                             CurrentPaginationCommand = 0;
+
+  Status = EFI_SUCCESS;
+
+  //
+  // Validate some input parameters.
+  //
+  // If either of the pointers are NULL, we can't proceed.
+  if (CommBuffer == NULL || CommBufferSize == NULL) {
+    DEBUG(( DEBUG_INFO, "%a - Invalid comm buffer pointers!\n", __FUNCTION__ ));
+    return EFI_INVALID_PARAMETER;
+  }
+  // If the size does not meet a minimum threshold, we cannot proceed.
+  ExpectedSize = sizeof(VAR_CHECK_POLICY_COMM_HEADER);
+  if (*CommBufferSize < ExpectedSize) {
+    DEBUG(( DEBUG_INFO, "%a - Bad comm buffer size! %d < %d\n", __FUNCTION__, *CommBufferSize, ExpectedSize ));
+    return EFI_INVALID_PARAMETER;
+  }
+  // Check the revision and the signature of the comm header.
+  PolicyCommmHeader = CommBuffer;
+  if (PolicyCommmHeader->Signature != VAR_CHECK_POLICY_COMM_SIG ||
+      PolicyCommmHeader->Revision != VAR_CHECK_POLICY_COMM_REVISION) {
+    DEBUG(( DEBUG_INFO, "%a - Signature or revision are incorrect!\n", __FUNCTION__ ));
+    // We have verified the buffer is not null and have enough size to hold Result field.
+    PolicyCommmHeader->Result = EFI_INVALID_PARAMETER;
+    return EFI_SUCCESS;
+  }
+
+  // If we're in the middle of a paginated dump and any other command is sent,
+  // pagination cache must be cleared.
+  if (PaginationCache != NULL && PolicyCommmHeader->Command != CurrentPaginationCommand) {
+    FreePool (PaginationCache);
+    PaginationCache = NULL;
+    PaginationCacheSize = 0;
+    CurrentPaginationCommand = 0;
+  }
+
+  //
+  // Now we can process the command as it was sent.
+  //
+  PolicyCommmHeader->Result = EFI_ABORTED;    // Set a default return for incomplete commands.
+  switch(PolicyCommmHeader->Command) {
+    case VAR_CHECK_POLICY_COMMAND_DISABLE:
+      PolicyCommmHeader->Result = DisableVariablePolicy();
+      break;
+
+    case VAR_CHECK_POLICY_COMMAND_IS_ENABLED:
+      // Make sure that we're dealing with a reasonable size.
+      // This add should be safe because these are fixed sizes so far.
+      ExpectedSize += sizeof(VAR_CHECK_POLICY_COMM_IS_ENABLED_PARAMS);
+      if (*CommBufferSize < ExpectedSize) {
+        DEBUG(( DEBUG_INFO, "%a - Bad comm buffer size! %d < %d\n", __FUNCTION__, *CommBufferSize, ExpectedSize ));
+        PolicyCommmHeader->Result = EFI_INVALID_PARAMETER;
+        break;
+      }
+
+      // Now that we know we've got a valid size, we can fill in the rest of the data.
+      IsEnabledParams = (VAR_CHECK_POLICY_COMM_IS_ENABLED_PARAMS*)((UINT8*)CommBuffer + sizeof(VAR_CHECK_POLICY_COMM_HEADER));
+      IsEnabledParams->State = IsVariablePolicyEnabled();
+      PolicyCommmHeader->Result = EFI_SUCCESS;
+      break;
+
+    case VAR_CHECK_POLICY_COMMAND_REGISTER:
+      // Make sure that we're dealing with a reasonable size.
+      // This add should be safe because these are fixed sizes so far.
+      ExpectedSize += sizeof(VARIABLE_POLICY_ENTRY);
+      if (*CommBufferSize < ExpectedSize) {
+        DEBUG(( DEBUG_INFO, "%a - Bad comm buffer size! %d < %d\n", __FUNCTION__, *CommBufferSize, ExpectedSize ));
+        PolicyCommmHeader->Result = EFI_INVALID_PARAMETER;
+        break;
+      }
+
+      // At the very least, we can assume that we're working with a valid policy entry.
+      // Time to compare its internal size.
+      PolicyEntry = (VARIABLE_POLICY_ENTRY*)((UINT8*)CommBuffer + sizeof(VAR_CHECK_POLICY_COMM_HEADER));
+      if (PolicyEntry->Version != VARIABLE_POLICY_ENTRY_REVISION ||
+          PolicyEntry->Size < sizeof(VARIABLE_POLICY_ENTRY) ||
+          EFI_ERROR(SafeUintnAdd(sizeof(VAR_CHECK_POLICY_COMM_HEADER), PolicyEntry->Size, &ExpectedSize)) ||
+          *CommBufferSize < ExpectedSize) {
+        DEBUG(( DEBUG_INFO, "%a - Bad policy entry contents!\n", __FUNCTION__ ));
+        PolicyCommmHeader->Result = EFI_INVALID_PARAMETER;
+        break;
+      }
+
+      PolicyCommmHeader->Result = RegisterVariablePolicy( PolicyEntry );
+      break;
+
+    case VAR_CHECK_POLICY_COMMAND_DUMP:
+      // Make sure that we're dealing with a reasonable size.
+      // This add should be safe because these are fixed sizes so far.
+      ExpectedSize += sizeof(VAR_CHECK_POLICY_COMM_DUMP_PARAMS) + VAR_CHECK_POLICY_MM_DUMP_BUFFER_SIZE;
+      if (*CommBufferSize < ExpectedSize) {
+        DEBUG(( DEBUG_INFO, "%a - Bad comm buffer size! %d < %d\n", __FUNCTION__, *CommBufferSize, ExpectedSize ));
+        PolicyCommmHeader->Result = EFI_INVALID_PARAMETER;
+        break;
+      }
+
+      // Now that we know we've got a valid size, we can fill in the rest of the data.
+      DumpParams = (VAR_CHECK_POLICY_COMM_DUMP_PARAMS*)(PolicyCommmHeader + 1);
+
+      // If we're requesting the first page, initialize the cache and get the sizes.
+      if (DumpParams->PageRequested == 0) {
+        if (PaginationCache != NULL) {
+          FreePool (PaginationCache);
+          PaginationCache = NULL;
+        }
+
+        // Determine what the required size is going to be.
+        DumpParams->TotalSize = 0;
+        DumpParams->PageSize = 0;
+        DumpParams->HasMore = FALSE;
+        SubCommandStatus = DumpVariablePolicy (NULL, &DumpParams->TotalSize);
+        if (SubCommandStatus == EFI_BUFFER_TOO_SMALL && DumpParams->TotalSize > 0) {
+          CurrentPaginationCommand = VAR_CHECK_POLICY_COMMAND_DUMP;
+          PaginationCacheSize = DumpParams->TotalSize;
+          PaginationCache = AllocatePool (PaginationCacheSize);
+          if (PaginationCache == NULL) {
+            SubCommandStatus = EFI_OUT_OF_RESOURCES;
+          }
+        }
+
+        // If we've allocated our pagination cache, we're good to cache.
+        if (PaginationCache != NULL) {
+          SubCommandStatus = DumpVariablePolicy (PaginationCache, &DumpParams->TotalSize);
+        }
+
+        // Populate the remaining fields and we can boogie.
+        if (!EFI_ERROR (SubCommandStatus) && PaginationCache != NULL) {
+          DumpParams->HasMore = TRUE;
+        }
+      }
+      else if (PaginationCache != NULL) {
+        DumpParams->TotalSize = (UINT32)PaginationCacheSize;
+        DumpParams->PageSize = VAR_CHECK_POLICY_MM_DUMP_BUFFER_SIZE;
+        DumpOutputBuffer = (UINT8*)(DumpParams + 1);
+
+        // Make sure that we don't over-index the cache.
+        DumpTotalPages = PaginationCacheSize / DumpParams->PageSize;
+        if (PaginationCacheSize % DumpParams->PageSize) DumpTotalPages++;
+        if (DumpParams->PageRequested > DumpTotalPages) {
+          SubCommandStatus = EFI_INVALID_PARAMETER;
+        }
+        else {
+          // Figure out how far into the page cache we need to go for our next page.
+          // We know the blind subtraction won't be bad because we already checked for page 0.
+          DumpInputBuffer = &PaginationCache[DumpParams->PageSize * (DumpParams->PageRequested - 1)];
+          // If we're getting the last page, adjust the PageSize.
+          if (DumpParams->PageRequested == DumpTotalPages) {
+            DumpParams->PageSize = PaginationCacheSize % DumpParams->PageSize;
+          }
+          CopyMem (DumpOutputBuffer, DumpInputBuffer, DumpParams->PageSize);
+          // If we just got the last page, settle up the cache.
+          if (DumpParams->PageRequested == DumpTotalPages) {
+            DumpParams->HasMore = FALSE;
+            FreePool (PaginationCache);
+            PaginationCache = NULL;
+            PaginationCacheSize = 0;
+            CurrentPaginationCommand = 0;
+          }
+          // Otherwise, we could do more here.
+          else {
+            DumpParams->HasMore = TRUE;
+          }
+
+          // If we made it this far, we're basically good.
+          SubCommandStatus = EFI_SUCCESS;
+        }
+      }
+      // If we've requested any other page than 0 and the cache is empty, we must have timed out.
+      else {
+        DumpParams->TotalSize = 0;
+        DumpParams->PageSize = 0;
+        DumpParams->HasMore = FALSE;
+        SubCommandStatus = EFI_TIMEOUT;
+      }
+
+      // There's currently no use for this, but it shouldn't be hard to implement.
+      PolicyCommmHeader->Result = SubCommandStatus;
+      break;
+
+    case VAR_CHECK_POLICY_COMMAND_LOCK:
+      PolicyCommmHeader->Result = LockVariablePolicy();
+      break;
+
+    default:
+      // Mark unknown requested command as EFI_UNSUPPORTED.
+      DEBUG(( DEBUG_INFO, "%a - Invalid command requested! %d\n", __FUNCTION__, PolicyCommmHeader->Command ));
+      PolicyCommmHeader->Result = EFI_UNSUPPORTED;
+      break;
+  }
+
+  DEBUG(( DEBUG_VERBOSE, "%a - Command %d returning %r.\n", __FUNCTION__,
+          PolicyCommmHeader->Command, PolicyCommmHeader->Result ));
+
+  return Status;
+}
+
+
+/**
+  Constructor function of VarCheckPolicyLib to register VarCheck handler and
+  SW MMI handlers.
+
+  @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 constructor executed correctly.
+
+**/
+EFI_STATUS
+EFIAPI
+VarCheckPolicyLibConstructor (
+  IN EFI_HANDLE             ImageHandle,
+  IN EFI_SYSTEM_TABLE       *SystemTable
+  )
+{
+  EFI_STATUS    Status;
+  EFI_HANDLE    DiscardedHandle;
+
+  // Initialize the business logic with the internal GetVariable handler.
+  Status = InitVariablePolicyLib( VariableServiceGetVariable );
+
+  // Only proceed with init if the business logic could be initialized.
+  if (!EFI_ERROR( Status )) {
+    // Register the VarCheck handler for SetVariable filtering.
+    // Forward the check to the business logic of the library.
+    VarCheckLibRegisterSetVariableCheckHandler( ValidateSetVariable );
+
+    // Register the MMI handlers for receiving policy commands.
+    DiscardedHandle = NULL;
+    Status = gMmst->MmiHandlerRegister( VarCheckPolicyLibMmiHandler,
+                                        &gVarCheckPolicyLibMmiHandlerGuid,
+                                        &DiscardedHandle );
+  }
+  // Otherwise, there's not much we can do.
+  else {
+    DEBUG(( DEBUG_ERROR, "%a - Cannot Initialize VariablePolicyLib! %r\n", __FUNCTION__, Status ));
+    ASSERT_EFI_ERROR( Status );
+  }
+
+  return Status;
+}
diff --git a/MdeModulePkg/Include/Guid/VarCheckPolicyMmi.h b/MdeModulePkg/Include/Guid/VarCheckPolicyMmi.h
new file mode 100644
index 000000000000..77bcc62f3ccf
--- /dev/null
+++ b/MdeModulePkg/Include/Guid/VarCheckPolicyMmi.h
@@ -0,0 +1,54 @@
+/** @file -- VarCheckPolicyMmiCommon.h
+This header contains communication definitions that are shared between DXE
+and the MM component of VarCheckPolicy.
+
+Copyright (c) Microsoft Corporation.
+SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _VAR_CHECK_POLICY_MMI_COMMON_H_
+#define _VAR_CHECK_POLICY_MMI_COMMON_H_
+
+#define   VAR_CHECK_POLICY_COMM_SIG       SIGNATURE_32('V', 'C', 'P', 'C')
+#define   VAR_CHECK_POLICY_COMM_REVISION  1
+
+#pragma pack(push, 1)
+
+typedef struct _VAR_CHECK_POLICY_COMM_HEADER {
+  UINT32      Signature;
+  UINT32      Revision;
+  UINT32      Command;
+  EFI_STATUS  Result;
+} VAR_CHECK_POLICY_COMM_HEADER;
+
+typedef struct _VAR_CHECK_POLICY_COMM_IS_ENABLED_PARAMS {
+  BOOLEAN     State;
+} VAR_CHECK_POLICY_COMM_IS_ENABLED_PARAMS;
+
+typedef struct _VAR_CHECK_POLICY_COMM_DUMP_PARAMS {
+  UINT32      PageRequested;
+  UINT32      TotalSize;
+  UINT32      PageSize;
+  BOOLEAN     HasMore;
+} VAR_CHECK_POLICY_COMM_DUMP_PARAMS;
+
+#pragma pack(pop)
+
+// Make sure that we will hold at least the headers.
+#define   VAR_CHECK_POLICY_MM_COMM_BUFFER_SIZE  MAX((OFFSET_OF(EFI_MM_COMMUNICATE_HEADER, Data) + sizeof (VAR_CHECK_POLICY_COMM_HEADER) + EFI_PAGES_TO_SIZE(1)), EFI_PAGES_TO_SIZE(4))
+#define   VAR_CHECK_POLICY_MM_DUMP_BUFFER_SIZE  (VAR_CHECK_POLICY_MM_COMM_BUFFER_SIZE - \
+                                                    (OFFSET_OF(EFI_MM_COMMUNICATE_HEADER, Data) + \
+                                                      sizeof(VAR_CHECK_POLICY_COMM_HEADER) + \
+                                                      sizeof(VAR_CHECK_POLICY_COMM_DUMP_PARAMS)))
+STATIC_ASSERT (
+  VAR_CHECK_POLICY_MM_DUMP_BUFFER_SIZE < VAR_CHECK_POLICY_MM_COMM_BUFFER_SIZE,
+  "an integer underflow may have occurred calculating VAR_CHECK_POLICY_MM_DUMP_BUFFER_SIZE"
+  );
+
+#define   VAR_CHECK_POLICY_COMMAND_DISABLE      0x0001
+#define   VAR_CHECK_POLICY_COMMAND_IS_ENABLED   0x0002
+#define   VAR_CHECK_POLICY_COMMAND_REGISTER     0x0003
+#define   VAR_CHECK_POLICY_COMMAND_DUMP         0x0004
+#define   VAR_CHECK_POLICY_COMMAND_LOCK         0x0005
+
+#endif // _VAR_CHECK_POLICY_MMI_COMMON_H_
diff --git a/MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.inf b/MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.inf
new file mode 100644
index 000000000000..077bcc8990ca
--- /dev/null
+++ b/MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.inf
@@ -0,0 +1,42 @@
+## @file VarCheckPolicyLib.inf
+# This is an instance of a VarCheck lib that leverages the business logic behind
+# the VariablePolicy code to make its decisions.
+#
+# Copyright (c) Microsoft Corporation.
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = VarCheckPolicyLib
+  FILE_GUID                      = 9C28A48F-C884-4B1F-8B95-DEF125448023
+  MODULE_TYPE                    = DXE_RUNTIME_DRIVER
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = NULL|DXE_RUNTIME_DRIVER DXE_SMM_DRIVER
+  CONSTRUCTOR                    = VarCheckPolicyLibConstructor
+
+
+[Sources]
+  VarCheckPolicyLib.c
+
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+
+
+[LibraryClasses]
+  BaseLib
+  DebugLib
+  BaseMemoryLib
+  DxeServicesLib
+  MemoryAllocationLib
+  VarCheckLib
+  VariablePolicyLib
+  VariablePolicyHelperLib
+  SafeIntLib
+  MmServicesTableLib
+
+
+[Guids]
+  gVarCheckPolicyLibMmiHandlerGuid        ## CONSUME ## Used to register for MM Communication events.
diff --git a/MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.uni b/MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.uni
new file mode 100644
index 000000000000..eedeeed15d31
--- /dev/null
+++ b/MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.uni
@@ -0,0 +1,12 @@
+// /** @file
+// VarCheckPolicyLib.uni
+//
+// Copyright (c) Microsoft Corporation.
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT             #language en-US "NULL library implementation that conforms to the VarCheck interface to allow VariablePolicy engine to enforce policies"
+
+#string STR_MODULE_DESCRIPTION          #language en-US "NULL library implementation that conforms to the VarCheck interface to allow VariablePolicy engine to enforce policies"
diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec
index b21cd78c8787..9a3c9fe642d3 100644
--- a/MdeModulePkg/MdeModulePkg.dec
+++ b/MdeModulePkg/MdeModulePkg.dec
@@ -385,6 +385,10 @@ [Guids]
   ## Include/Guid/EndofS3Resume.h
   gEdkiiEndOfS3ResumeGuid = { 0x96f5296d, 0x05f7, 0x4f3c, {0x84, 0x67, 0xe4, 0x56, 0x89, 0x0e, 0x0c, 0xb5 } }
 
+  ## Used (similar to Variable Services) to communicate policies to the enforcement engine.
+  # {DA1B0D11-D1A7-46C4-9DC9-F3714875C6EB}
+  gVarCheckPolicyLibMmiHandlerGuid = { 0xda1b0d11, 0xd1a7, 0x46c4, { 0x9d, 0xc9, 0xf3, 0x71, 0x48, 0x75, 0xc6, 0xeb }}
+
   ## Include/Guid/S3SmmInitDone.h
   gEdkiiS3SmmInitDoneGuid = { 0x8f9d4825, 0x797d, 0x48fc, { 0x84, 0x71, 0x84, 0x50, 0x25, 0x79, 0x2e, 0xf6 } }
 
diff --git a/MdeModulePkg/MdeModulePkg.dsc b/MdeModulePkg/MdeModulePkg.dsc
index 37795b9e4f58..f0a75a3b337b 100644
--- a/MdeModulePkg/MdeModulePkg.dsc
+++ b/MdeModulePkg/MdeModulePkg.dsc
@@ -313,6 +313,7 @@ [Components]
   MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf
   MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf
   MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf
+  MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.inf
   MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf
   MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLib.inf
   MdeModulePkg/Library/VarCheckPcdLib/VarCheckPcdLib.inf
@@ -458,6 +459,7 @@ [Components.IA32, Components.X64]
   MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf
   MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf {
     <LibraryClasses>
+      NULL|MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.inf
       NULL|MdeModulePkg/Library/VarCheckUefiLib/VarCheckUefiLib.inf
       NULL|MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLib.inf
       NULL|MdeModulePkg/Library/VarCheckPcdLib/VarCheckPcdLib.inf
-- 
2.26.2.windows.1.8.g01c50adf56.20200515075929


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH v6 05/14] OvmfPkg: Add VariablePolicy engine to OvmfPkg platform
  2020-06-23  6:40 [PATCH v6 00/14] Add the VariablePolicy feature bret
                   ` (3 preceding siblings ...)
  2020-06-23  6:40 ` [PATCH v6 04/14] MdeModulePkg: Define the VarCheckPolicyLib and SMM interface Bret Barkelew
@ 2020-06-23  6:40 ` Bret Barkelew
  2020-06-23  6:40 ` [PATCH v6 06/14] EmulatorPkg: Add VariablePolicy engine to EmulatorPkg platform Bret Barkelew
                   ` (11 subsequent siblings)
  16 siblings, 0 replies; 48+ messages in thread
From: Bret Barkelew @ 2020-06-23  6:40 UTC (permalink / raw)
  To: devel; +Cc: Jordan Justen, Laszlo Ersek, Ard Biesheuvel

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

Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
Cc: Bret Barkelew <brbarkel@microsoft.com>
Signed-off-by: Bret Barkelew <brbarkel@microsoft.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
---
 OvmfPkg/OvmfPkgIa32.dsc    | 5 +++++
 OvmfPkg/OvmfPkgIa32X64.dsc | 5 +++++
 OvmfPkg/OvmfPkgX64.dsc     | 5 +++++
 OvmfPkg/OvmfXen.dsc        | 4 ++++
 4 files changed, 19 insertions(+)

diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc
index b4ee7376791b..c26c4045fa86 100644
--- a/OvmfPkg/OvmfPkgIa32.dsc
+++ b/OvmfPkg/OvmfPkgIa32.dsc
@@ -3,6 +3,7 @@
 #
 #  Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.<BR>
 #  (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
+#  Copyright (c) Microsoft Corporation.
 #
 #  SPDX-License-Identifier: BSD-2-Clause-Patent
 #
@@ -196,6 +197,8 @@ [LibraryClasses]
   AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf
 !endif
   VarCheckLib|MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf
+  VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf
+  VariablePolicyHelperLib|MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf
 
 
   #
@@ -334,6 +337,7 @@ [LibraryClasses.common.DXE_RUNTIME_DRIVER]
   BaseCryptLib|CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf
   PciLib|OvmfPkg/Library/DxePciLibI440FxQ35/DxePciLibI440FxQ35.inf
   QemuFwCfgS3Lib|OvmfPkg/Library/QemuFwCfgS3Lib/DxeQemuFwCfgS3LibFwCfg.inf
+  VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf
 
 [LibraryClasses.common.UEFI_DRIVER]
   PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
@@ -953,6 +957,7 @@ [Components]
   MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf {
     <LibraryClasses>
       NULL|MdeModulePkg/Library/VarCheckUefiLib/VarCheckUefiLib.inf
+      NULL|MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.inf
   }
   MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf
 
diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc
index ed68b080f2a2..724010e9a567 100644
--- a/OvmfPkg/OvmfPkgIa32X64.dsc
+++ b/OvmfPkg/OvmfPkgIa32X64.dsc
@@ -3,6 +3,7 @@
 #
 #  Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.<BR>
 #  (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
+#  Copyright (c) Microsoft Corporation.
 #
 #  SPDX-License-Identifier: BSD-2-Clause-Patent
 #
@@ -200,6 +201,8 @@ [LibraryClasses]
   AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf
 !endif
   VarCheckLib|MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf
+  VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf
+  VariablePolicyHelperLib|MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf
 
 
   #
@@ -338,6 +341,7 @@ [LibraryClasses.common.DXE_RUNTIME_DRIVER]
   BaseCryptLib|CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf
   PciLib|OvmfPkg/Library/DxePciLibI440FxQ35/DxePciLibI440FxQ35.inf
   QemuFwCfgS3Lib|OvmfPkg/Library/QemuFwCfgS3Lib/DxeQemuFwCfgS3LibFwCfg.inf
+  VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf
 
 [LibraryClasses.common.UEFI_DRIVER]
   PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
@@ -968,6 +972,7 @@ [Components.X64]
   MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf {
     <LibraryClasses>
       NULL|MdeModulePkg/Library/VarCheckUefiLib/VarCheckUefiLib.inf
+      NULL|MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.inf
   }
   MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf
 
diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc
index cb7e8068a3d8..1ca9a6845160 100644
--- a/OvmfPkg/OvmfPkgX64.dsc
+++ b/OvmfPkg/OvmfPkgX64.dsc
@@ -3,6 +3,7 @@
 #
 #  Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.<BR>
 #  (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
+#  Copyright (c) Microsoft Corporation.
 #
 #  SPDX-License-Identifier: BSD-2-Clause-Patent
 #
@@ -200,6 +201,8 @@ [LibraryClasses]
   AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf
 !endif
   VarCheckLib|MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf
+  VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf
+  VariablePolicyHelperLib|MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf
 
 
   #
@@ -338,6 +341,7 @@ [LibraryClasses.common.DXE_RUNTIME_DRIVER]
   BaseCryptLib|CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf
   PciLib|OvmfPkg/Library/DxePciLibI440FxQ35/DxePciLibI440FxQ35.inf
   QemuFwCfgS3Lib|OvmfPkg/Library/QemuFwCfgS3Lib/DxeQemuFwCfgS3LibFwCfg.inf
+  VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf
 
 [LibraryClasses.common.UEFI_DRIVER]
   PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
@@ -964,6 +968,7 @@ [Components]
   MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf {
     <LibraryClasses>
       NULL|MdeModulePkg/Library/VarCheckUefiLib/VarCheckUefiLib.inf
+      NULL|MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.inf
   }
   MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf
 
diff --git a/OvmfPkg/OvmfXen.dsc b/OvmfPkg/OvmfXen.dsc
index 782803cb2787..b43284f10b45 100644
--- a/OvmfPkg/OvmfXen.dsc
+++ b/OvmfPkg/OvmfXen.dsc
@@ -4,6 +4,7 @@
 #  Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.<BR>
 #  (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
 #  Copyright (c) 2019, Citrix Systems, Inc.
+#  Copyright (c) Microsoft Corporation.
 #
 #  SPDX-License-Identifier: BSD-2-Clause-Patent
 #
@@ -182,6 +183,8 @@ [LibraryClasses]
 
   AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf
   VarCheckLib|MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf
+  VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf
+  VariablePolicyHelperLib|MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf
 
 
   #
@@ -289,6 +292,7 @@ [LibraryClasses.common.DXE_RUNTIME_DRIVER]
   BaseCryptLib|CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf
   PciLib|OvmfPkg/Library/DxePciLibI440FxQ35/DxePciLibI440FxQ35.inf
   QemuFwCfgS3Lib|OvmfPkg/Library/QemuFwCfgS3Lib/DxeQemuFwCfgS3LibFwCfg.inf
+  VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf
 
 [LibraryClasses.common.UEFI_DRIVER]
   PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
-- 
2.26.2.windows.1.8.g01c50adf56.20200515075929


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH v6 06/14] EmulatorPkg: Add VariablePolicy engine to EmulatorPkg platform
  2020-06-23  6:40 [PATCH v6 00/14] Add the VariablePolicy feature bret
                   ` (4 preceding siblings ...)
  2020-06-23  6:40 ` [PATCH v6 05/14] OvmfPkg: Add VariablePolicy engine to OvmfPkg platform Bret Barkelew
@ 2020-06-23  6:40 ` Bret Barkelew
  2020-06-23  6:40 ` [PATCH v6 07/14] ArmVirtPkg: Add VariablePolicy engine to ArmVirtPkg platform Bret Barkelew
                   ` (10 subsequent siblings)
  16 siblings, 0 replies; 48+ messages in thread
From: Bret Barkelew @ 2020-06-23  6:40 UTC (permalink / raw)
  To: devel; +Cc: Jordan Justen, Andrew Fish, Ray Ni

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

Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Andrew Fish <afish@apple.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Bret Barkelew <brbarkel@microsoft.com>
Signed-off-by: Bret Barkelew <brbarkel@microsoft.com>
---
 EmulatorPkg/EmulatorPkg.dsc | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/EmulatorPkg/EmulatorPkg.dsc b/EmulatorPkg/EmulatorPkg.dsc
index 86a62717353b..3bb6e0373ca8 100644
--- a/EmulatorPkg/EmulatorPkg.dsc
+++ b/EmulatorPkg/EmulatorPkg.dsc
@@ -6,6 +6,7 @@
 #
 # Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.<BR>
 # Portions copyright (c) 2010 - 2011, Apple Inc. All rights reserved.<BR>
+# Copyright (c) Microsoft Corporation.
 #
 # SPDX-License-Identifier: BSD-2-Clause-Patent
 #
@@ -108,6 +109,8 @@ [LibraryClasses]
   TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf
   AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf
   VarCheckLib|MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf
+  VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf
+  VariablePolicyHelperLib|MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf
   SortLib|MdeModulePkg/Library/BaseSortLib/BaseSortLib.inf
   ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf
   FileHandleLib|MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf
-- 
2.26.2.windows.1.8.g01c50adf56.20200515075929


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH v6 07/14] ArmVirtPkg: Add VariablePolicy engine to ArmVirtPkg platform
  2020-06-23  6:40 [PATCH v6 00/14] Add the VariablePolicy feature bret
                   ` (5 preceding siblings ...)
  2020-06-23  6:40 ` [PATCH v6 06/14] EmulatorPkg: Add VariablePolicy engine to EmulatorPkg platform Bret Barkelew
@ 2020-06-23  6:40 ` Bret Barkelew
  2020-06-23  6:40 ` [PATCH v6 08/14] UefiPayloadPkg: Add VariablePolicy engine to UefiPayloadPkg platform Bret Barkelew
                   ` (9 subsequent siblings)
  16 siblings, 0 replies; 48+ messages in thread
From: Bret Barkelew @ 2020-06-23  6:40 UTC (permalink / raw)
  To: devel; +Cc: Laszlo Ersek, Ard Biesheuvel, Leif Lindholm

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

Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
Cc: Leif Lindholm <leif@nuviainc.com>
Cc: Bret Barkelew <brbarkel@microsoft.com>
Signed-off-by: Bret Barkelew <brbarkel@microsoft.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
---
 ArmVirtPkg/ArmVirt.dsc.inc | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/ArmVirtPkg/ArmVirt.dsc.inc b/ArmVirtPkg/ArmVirt.dsc.inc
index cf44fc73890b..0af6d839cf11 100644
--- a/ArmVirtPkg/ArmVirt.dsc.inc
+++ b/ArmVirtPkg/ArmVirt.dsc.inc
@@ -2,6 +2,7 @@
 #  Copyright (c) 2011-2015, ARM Limited. All rights reserved.
 #  Copyright (c) 2014, Linaro Limited. All rights reserved.
 #  Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.
+#  Copyright (c) Microsoft Corporation.
 #
 #  SPDX-License-Identifier: BSD-2-Clause-Patent
 #
@@ -173,6 +174,8 @@ [LibraryClasses.common]
   AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf
 !endif
   VarCheckLib|MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf
+  VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf
+  VariablePolicyHelperLib|MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf
   UefiBootManagerLib|MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf
 
   ReportStatusCodeLib|MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf
@@ -246,6 +249,7 @@ [LibraryClasses.common.DXE_RUNTIME_DRIVER]
 !if $(TARGET) != RELEASE
   DebugLib|MdePkg/Library/DxeRuntimeDebugLibSerialPort/DxeRuntimeDebugLibSerialPort.inf
 !endif
+  VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf
 
 !if $(SECURE_BOOT_ENABLE) == TRUE
   BaseCryptLib|CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf
-- 
2.26.2.windows.1.8.g01c50adf56.20200515075929


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH v6 08/14] UefiPayloadPkg: Add VariablePolicy engine to UefiPayloadPkg platform
  2020-06-23  6:40 [PATCH v6 00/14] Add the VariablePolicy feature bret
                   ` (6 preceding siblings ...)
  2020-06-23  6:40 ` [PATCH v6 07/14] ArmVirtPkg: Add VariablePolicy engine to ArmVirtPkg platform Bret Barkelew
@ 2020-06-23  6:40 ` Bret Barkelew
  2020-06-23 16:45   ` Ma, Maurice
  2020-06-23  6:40 ` [PATCH v6 09/14] MdeModulePkg: Connect VariablePolicy business logic to VariableServices Bret Barkelew
                   ` (8 subsequent siblings)
  16 siblings, 1 reply; 48+ messages in thread
From: Bret Barkelew @ 2020-06-23  6:40 UTC (permalink / raw)
  To: devel; +Cc: Maurice Ma, Guo Dong, Benjamin You

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

Cc: Maurice Ma <maurice.ma@intel.com>
Cc: Guo Dong <guo.dong@intel.com>
Cc: Benjamin You <benjamin.you@intel.com>
Cc: Bret Barkelew <brbarkel@microsoft.com>
Signed-off-by: Bret Barkelew <brbarkel@microsoft.com>
Reviewed-by: Maurice Ma <maurice.ma@intel.com>
---
 UefiPayloadPkg/UefiPayloadPkgIa32.dsc    | 4 ++++
 UefiPayloadPkg/UefiPayloadPkgIa32X64.dsc | 4 ++++
 2 files changed, 8 insertions(+)

diff --git a/UefiPayloadPkg/UefiPayloadPkgIa32.dsc b/UefiPayloadPkg/UefiPayloadPkgIa32.dsc
index c6c47833871b..4bed6aaa78d0 100644
--- a/UefiPayloadPkg/UefiPayloadPkgIa32.dsc
+++ b/UefiPayloadPkg/UefiPayloadPkgIa32.dsc
@@ -4,6 +4,7 @@
 # Provides drivers and definitions to create uefi payload for bootloaders.
 #
 # Copyright (c) 2014 - 2020, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) Microsoft Corporation.
 # SPDX-License-Identifier: BSD-2-Clause-Patent
 #
 ##
@@ -204,6 +205,8 @@ [LibraryClasses]
   AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf
   TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf
   VarCheckLib|MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf
+  VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf
+  VariablePolicyHelperLib|MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf
 
 [LibraryClasses.IA32.SEC]
   DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
@@ -251,6 +254,7 @@ [LibraryClasses.common.DXE_RUNTIME_DRIVER]
   HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
   MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
   ReportStatusCodeLib|MdeModulePkg/Library/RuntimeDxeReportStatusCodeLib/RuntimeDxeReportStatusCodeLib.inf
+  VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf
 
 [LibraryClasses.common.UEFI_DRIVER,LibraryClasses.common.UEFI_APPLICATION]
   PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
diff --git a/UefiPayloadPkg/UefiPayloadPkgIa32X64.dsc b/UefiPayloadPkg/UefiPayloadPkgIa32X64.dsc
index 5559b1258521..6e07dd866acd 100644
--- a/UefiPayloadPkg/UefiPayloadPkgIa32X64.dsc
+++ b/UefiPayloadPkg/UefiPayloadPkgIa32X64.dsc
@@ -4,6 +4,7 @@
 # Provides drivers and definitions to create uefi payload for bootloaders.
 #
 # Copyright (c) 2014 - 2020, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) Microsoft Corporation.
 # SPDX-License-Identifier: BSD-2-Clause-Patent
 #
 ##
@@ -205,6 +206,8 @@ [LibraryClasses]
   AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf
   TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf
   VarCheckLib|MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf
+  VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf
+  VariablePolicyHelperLib|MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf
 
 [LibraryClasses.IA32.SEC]
   DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
@@ -252,6 +255,7 @@ [LibraryClasses.common.DXE_RUNTIME_DRIVER]
   HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
   MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
   ReportStatusCodeLib|MdeModulePkg/Library/RuntimeDxeReportStatusCodeLib/RuntimeDxeReportStatusCodeLib.inf
+  VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf
 
 [LibraryClasses.common.UEFI_DRIVER,LibraryClasses.common.UEFI_APPLICATION]
   PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
-- 
2.26.2.windows.1.8.g01c50adf56.20200515075929


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH v6 09/14] MdeModulePkg: Connect VariablePolicy business logic to VariableServices
  2020-06-23  6:40 [PATCH v6 00/14] Add the VariablePolicy feature bret
                   ` (7 preceding siblings ...)
  2020-06-23  6:40 ` [PATCH v6 08/14] UefiPayloadPkg: Add VariablePolicy engine to UefiPayloadPkg platform Bret Barkelew
@ 2020-06-23  6:40 ` Bret Barkelew
  2020-07-02  2:13   ` [edk2-devel] " Dandan Bi
  2020-06-23  6:41 ` [PATCH v6 10/14] MdeModulePkg: Allow VariablePolicy state to delete protected variables Bret Barkelew
                   ` (7 subsequent siblings)
  16 siblings, 1 reply; 48+ messages in thread
From: Bret Barkelew @ 2020-06-23  6:40 UTC (permalink / raw)
  To: devel; +Cc: Jian J Wang, Hao A Wu, Liming Gao

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

VariablePolicy is an updated interface to
replace VarLock and VarCheckProtocol.

Add connective code to publish the VariablePolicy protocol
and wire it to either the SMM communication interface
or directly into the VariablePolicyLib business logic.

Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Hao A Wu <hao.a.wu@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Bret Barkelew <brbarkel@microsoft.com>
Signed-off-by: Bret Barkelew <brbarkel@microsoft.com>
---
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c             |  53 ++
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariablePolicySmmDxe.c    | 642 ++++++++++++++++++++
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c   |  14 +
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf    |   2 +
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf           |   3 +
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf |  10 +
 6 files changed, 724 insertions(+)

diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c
index 7d2b6c8e1fad..d404d4763e54 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c
@@ -5,18 +5,34 @@
 Copyright (C) 2013, Red Hat, Inc.
 Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
 (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
+Copyright (c) Microsoft Corporation.
 SPDX-License-Identifier: BSD-2-Clause-Patent
 
 **/
 
 #include "Variable.h"
 
+#include <Protocol/VariablePolicy.h>
+#include <Library/VariablePolicyLib.h>
+
+EFI_STATUS
+EFIAPI
+ProtocolIsVariablePolicyEnabled (
+  OUT BOOLEAN *State
+  );
+
 EFI_HANDLE                          mHandle                    = NULL;
 EFI_EVENT                           mVirtualAddressChangeEvent = NULL;
 VOID                                *mFtwRegistration          = NULL;
 VOID                                ***mVarCheckAddressPointer = NULL;
 UINTN                               mVarCheckAddressPointerCount = 0;
 EDKII_VARIABLE_LOCK_PROTOCOL        mVariableLock              = { VariableLockRequestToLock };
+EDKII_VARIABLE_POLICY_PROTOCOL      mVariablePolicyProtocol    = { EDKII_VARIABLE_POLICY_PROTOCOL_REVISION,
+                                                                    DisableVariablePolicy,
+                                                                    ProtocolIsVariablePolicyEnabled,
+                                                                    RegisterVariablePolicy,
+                                                                    DumpVariablePolicy,
+                                                                    LockVariablePolicy };
 EDKII_VAR_CHECK_PROTOCOL            mVarCheck                  = { VarCheckRegisterSetVariableCheckHandler,
                                                                     VarCheckVariablePropertySet,
                                                                     VarCheckVariablePropertyGet };
@@ -303,6 +319,8 @@ OnReadyToBoot (
     }
   }
 
+  ASSERT_EFI_ERROR (LockVariablePolicy ());
+
   gBS->CloseEvent (Event);
 }
 
@@ -466,6 +484,28 @@ FtwNotificationEvent (
 }
 
 
+/**
+  This API function returns whether or not the policy engine is
+  currently being enforced.
+
+  @param[out]   State       Pointer to a return value for whether the policy enforcement
+                            is currently enabled.
+
+  @retval     EFI_SUCCESS
+  @retval     Others        An error has prevented this command from completing.
+
+**/
+EFI_STATUS
+EFIAPI
+ProtocolIsVariablePolicyEnabled (
+  OUT BOOLEAN *State
+  )
+{
+  *State = IsVariablePolicyEnabled ();
+  return EFI_SUCCESS;
+}
+
+
 /**
   Variable Driver main entry point. The Variable driver places the 4 EFI
   runtime services in the EFI System Table and installs arch protocols
@@ -576,6 +616,19 @@ VariableServiceInitialize (
                   );
   ASSERT_EFI_ERROR (Status);
 
+  // Register and initialize the VariablePolicy engine.
+  Status = InitVariablePolicyLib (VariableServiceGetVariable);
+  ASSERT_EFI_ERROR (Status);
+  Status = VarCheckRegisterSetVariableCheckHandler (ValidateSetVariable);
+  ASSERT_EFI_ERROR (Status);
+  Status = gBS->InstallMultipleProtocolInterfaces (
+                    &mHandle,
+                    &gEdkiiVariablePolicyProtocolGuid,
+                    &mVariablePolicyProtocol,
+                    NULL
+                    );
+  ASSERT_EFI_ERROR (Status);
+
   return EFI_SUCCESS;
 }
 
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariablePolicySmmDxe.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariablePolicySmmDxe.c
new file mode 100644
index 000000000000..e2d4cf4cec1a
--- /dev/null
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariablePolicySmmDxe.c
@@ -0,0 +1,642 @@
+/** @file -- VariablePolicySmmDxe.c
+This protocol allows communication with Variable Policy Engine.
+
+Copyright (c) Microsoft Corporation.
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/BaseLib.h>
+#include <Library/UefiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/SafeIntLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+#include <Protocol/VariablePolicy.h>
+#include <Protocol/MmCommunication2.h>
+
+#include <Guid/VarCheckPolicyMmi.h>
+
+#include "Variable.h"
+
+EDKII_VARIABLE_POLICY_PROTOCOL  mVariablePolicyProtocol;
+EFI_MM_COMMUNICATION2_PROTOCOL  *mMmCommunication;
+
+VOID      *mMmCommunicationBuffer;
+UINTN     mMmCommunicationBufferSize;
+EFI_LOCK  mMmCommunicationLock;
+
+/**
+  Internal helper function to consolidate communication method.
+
+  @param[in,out]  CommBuffer
+  @param[in,out]  CommSize    Size of the CommBuffer.
+
+  @retval   EFI_STATUS    Result from communication method.
+
+**/
+STATIC
+EFI_STATUS
+InternalMmCommunicate (
+  IN OUT VOID             *CommBuffer,
+  IN OUT UINTN            *CommSize
+  )
+{
+  EFI_STATUS    Status;
+  if (CommBuffer == NULL || CommSize == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+  Status = mMmCommunication->Communicate (mMmCommunication, CommBuffer, CommBuffer, CommSize);
+  return Status;
+}
+
+
+/**
+  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_WRITE_PROTECTED   Interface option is disabled by platform PCD.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+ProtocolDisableVariablePolicy (
+  VOID
+  )
+{
+  EFI_STATUS                    Status;
+  EFI_MM_COMMUNICATE_HEADER     *CommHeader;
+  VAR_CHECK_POLICY_COMM_HEADER  *PolicyHeader;
+  UINTN                         BufferSize;
+
+  // Check the PCD for convenience.
+  // This would also be rejected by the lib, but why go to MM if we don't have to?
+  if (!PcdGetBool (PcdAllowVariablePolicyEnforcementDisable)) {
+    return EFI_WRITE_PROTECTED;
+  }
+
+  AcquireLockOnlyAtBootTime (&mMmCommunicationLock);
+
+  // Set up the MM communication.
+  BufferSize    = mMmCommunicationBufferSize;
+  CommHeader    = mMmCommunicationBuffer;
+  PolicyHeader  = (VAR_CHECK_POLICY_COMM_HEADER*)&CommHeader->Data;
+  CopyGuid( &CommHeader->HeaderGuid, &gVarCheckPolicyLibMmiHandlerGuid );
+  CommHeader->MessageLength = BufferSize;
+  PolicyHeader->Signature   = VAR_CHECK_POLICY_COMM_SIG;
+  PolicyHeader->Revision    = VAR_CHECK_POLICY_COMM_REVISION;
+  PolicyHeader->Command     = VAR_CHECK_POLICY_COMMAND_DISABLE;
+
+  Status = InternalMmCommunicate (CommHeader, &BufferSize);
+  DEBUG(( DEBUG_VERBOSE, "%a - MmCommunication returned %r.\n", __FUNCTION__, Status ));
+
+  ReleaseLockOnlyAtBootTime (&mMmCommunicationLock);
+
+  return (EFI_ERROR( Status )) ? Status : PolicyHeader->Result;
+}
+
+
+/**
+  This API function returns whether or not the policy engine is
+  currently being enforced.
+
+  @param[out]   State       Pointer to a return value for whether the policy enforcement
+                            is currently enabled.
+
+  @retval     EFI_SUCCESS
+  @retval     Others        An error has prevented this command from completing.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+ProtocolIsVariablePolicyEnabled (
+  OUT BOOLEAN     *State
+  )
+{
+  EFI_STATUS                                Status;
+  EFI_MM_COMMUNICATE_HEADER                 *CommHeader;
+  VAR_CHECK_POLICY_COMM_HEADER              *PolicyHeader;
+  VAR_CHECK_POLICY_COMM_IS_ENABLED_PARAMS   *CommandParams;
+  UINTN                                     BufferSize;
+
+  if (State == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  AcquireLockOnlyAtBootTime (&mMmCommunicationLock);
+
+  // Set up the MM communication.
+  BufferSize    = mMmCommunicationBufferSize;
+  CommHeader    = mMmCommunicationBuffer;
+  PolicyHeader  = (VAR_CHECK_POLICY_COMM_HEADER*)&CommHeader->Data;
+  CommandParams = (VAR_CHECK_POLICY_COMM_IS_ENABLED_PARAMS*)(PolicyHeader + 1);
+  CopyGuid( &CommHeader->HeaderGuid, &gVarCheckPolicyLibMmiHandlerGuid );
+  CommHeader->MessageLength = BufferSize;
+  PolicyHeader->Signature   = VAR_CHECK_POLICY_COMM_SIG;
+  PolicyHeader->Revision    = VAR_CHECK_POLICY_COMM_REVISION;
+  PolicyHeader->Command     = VAR_CHECK_POLICY_COMMAND_IS_ENABLED;
+
+  Status = InternalMmCommunicate (CommHeader, &BufferSize);
+  DEBUG(( DEBUG_VERBOSE, "%a - MmCommunication returned %r.\n", __FUNCTION__, Status ));
+
+  if (!EFI_ERROR( Status )) {
+    Status = PolicyHeader->Result;
+    *State = CommandParams->State;
+  }
+
+  ReleaseLockOnlyAtBootTime (&mMmCommunicationLock);
+
+  return Status;
+}
+
+
+/**
+  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.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+ProtocolRegisterVariablePolicy (
+  IN CONST VARIABLE_POLICY_ENTRY    *NewPolicy
+  )
+{
+  EFI_STATUS                                Status;
+  EFI_MM_COMMUNICATE_HEADER                 *CommHeader;
+  VAR_CHECK_POLICY_COMM_HEADER              *PolicyHeader;
+  VOID                                      *PolicyBuffer;
+  UINTN                                     BufferSize;
+  UINTN                                     RequiredSize;
+
+  if (NewPolicy == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // First, make sure that the required size does not exceed the capabilities
+  // of the MmCommunication buffer.
+  RequiredSize = OFFSET_OF(EFI_MM_COMMUNICATE_HEADER, Data) + sizeof(VAR_CHECK_POLICY_COMM_HEADER);
+  Status = SafeUintnAdd( RequiredSize, NewPolicy->Size, &RequiredSize );
+  if (EFI_ERROR( Status ) || RequiredSize > mMmCommunicationBufferSize) {
+    DEBUG(( DEBUG_ERROR, "%a - Policy too large for buffer! %r, %d > %d \n", __FUNCTION__,
+            Status, RequiredSize, mMmCommunicationBufferSize ));
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  AcquireLockOnlyAtBootTime (&mMmCommunicationLock);
+
+  // Set up the MM communication.
+  BufferSize    = mMmCommunicationBufferSize;
+  CommHeader    = mMmCommunicationBuffer;
+  PolicyHeader  = (VAR_CHECK_POLICY_COMM_HEADER*)&CommHeader->Data;
+  PolicyBuffer  = (VOID*)(PolicyHeader + 1);
+  CopyGuid( &CommHeader->HeaderGuid, &gVarCheckPolicyLibMmiHandlerGuid );
+  CommHeader->MessageLength = BufferSize;
+  PolicyHeader->Signature   = VAR_CHECK_POLICY_COMM_SIG;
+  PolicyHeader->Revision    = VAR_CHECK_POLICY_COMM_REVISION;
+  PolicyHeader->Command     = VAR_CHECK_POLICY_COMMAND_REGISTER;
+
+  // Copy the policy into place. This copy is safe because we've already tested above.
+  CopyMem( PolicyBuffer, NewPolicy, NewPolicy->Size );
+
+  Status = InternalMmCommunicate (CommHeader, &BufferSize);
+  DEBUG(( DEBUG_VERBOSE, "%a - MmCommunication returned %r.\n", __FUNCTION__, Status ));
+
+  ReleaseLockOnlyAtBootTime (&mMmCommunicationLock);
+
+  return (EFI_ERROR( Status )) ? Status : PolicyHeader->Result;
+}
+
+
+/**
+  This helper function takes care of the overhead of formatting, sending, and interpreting
+  the results for a single DumpVariablePolicy request.
+
+  @param[in]      PageRequested   The page of the paginated results from MM. 0 for metadata.
+  @param[out]     TotalSize       The total size of the entire buffer. Returned as part of metadata.
+  @param[out]     PageSize        The size of the current page being returned. Not valid as part of metadata.
+  @param[out]     HasMore         A flag indicating whether there are more pages after this one.
+  @param[out]     Buffer          The start of the current page from MM.
+
+  @retval     EFI_SUCCESS             Output params have been updated (either metadata or dump page).
+  @retval     EFI_INVALID_PARAMETER   One of the output params is NULL.
+  @retval     Others                  Response from MM handler.
+
+**/
+STATIC
+EFI_STATUS
+DumpVariablePolicyHelper (
+  IN  UINT32        PageRequested,
+  OUT UINT32        *TotalSize,
+  OUT UINT32        *PageSize,
+  OUT BOOLEAN       *HasMore,
+  OUT UINT8         **Buffer
+  )
+{
+  EFI_STATUS                              Status;
+  EFI_MM_COMMUNICATE_HEADER               *CommHeader;
+  VAR_CHECK_POLICY_COMM_HEADER            *PolicyHeader;
+  VAR_CHECK_POLICY_COMM_DUMP_PARAMS       *CommandParams;
+  UINTN                                   BufferSize;
+
+  if (TotalSize == NULL || PageSize == NULL || HasMore == NULL || Buffer == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // Set up the MM communication.
+  BufferSize    = mMmCommunicationBufferSize;
+  CommHeader    = mMmCommunicationBuffer;
+  PolicyHeader  = (VAR_CHECK_POLICY_COMM_HEADER*)&CommHeader->Data;
+  CommandParams = (VAR_CHECK_POLICY_COMM_DUMP_PARAMS*)(PolicyHeader + 1);
+  CopyGuid( &CommHeader->HeaderGuid, &gVarCheckPolicyLibMmiHandlerGuid );
+  CommHeader->MessageLength = BufferSize;
+  PolicyHeader->Signature   = VAR_CHECK_POLICY_COMM_SIG;
+  PolicyHeader->Revision    = VAR_CHECK_POLICY_COMM_REVISION;
+  PolicyHeader->Command     = VAR_CHECK_POLICY_COMMAND_DUMP;
+
+  CommandParams->PageRequested = PageRequested;
+
+  Status = InternalMmCommunicate (CommHeader, &BufferSize);
+  DEBUG(( DEBUG_VERBOSE, "%a - MmCommunication returned %r.\n", __FUNCTION__, Status ));
+
+  if (!EFI_ERROR( Status )) {
+    Status = PolicyHeader->Result;
+    *TotalSize = CommandParams->TotalSize;
+    *PageSize = CommandParams->PageSize;
+    *HasMore = CommandParams->HasMore;
+    *Buffer = (UINT8*)(CommandParams + 1);
+  }
+
+  return Status;
+}
+
+
+/**
+  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.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+ProtocolDumpVariablePolicy (
+  OUT UINT8             *Policy OPTIONAL,
+  IN OUT UINT32         *Size
+  )
+{
+  EFI_STATUS    Status;
+  UINT8         *Source;
+  UINT8         *Destination;
+  UINT32        PolicySize;
+  UINT32        PageSize;
+  BOOLEAN       HasMore;
+  UINT32        PageIndex;
+
+  if (Size == NULL || (*Size > 0 && Policy == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  AcquireLockOnlyAtBootTime (&mMmCommunicationLock);
+
+  // Repeat this whole process until we either have a failure case or get the entire buffer.
+  do {
+    // First, we must check the zero page to determine the buffer size and
+    // reset the internal state.
+    PolicySize = 0;
+    PageSize = 0;
+    HasMore = FALSE;
+    Status = DumpVariablePolicyHelper (0, &PolicySize, &PageSize, &HasMore, &Source);
+    if (EFI_ERROR (Status)) {
+      break;
+    }
+
+    // If we're good, we can at least check the required size now.
+    if (*Size < PolicySize) {
+      *Size = PolicySize;
+      Status = EFI_BUFFER_TOO_SMALL;
+      break;
+    }
+
+    // On further thought, let's update the size either way.
+    *Size = PolicySize;
+    // And get ready to ROCK.
+    Destination = Policy;
+
+    // Keep looping and copying until we're either done or freak out.
+    for (PageIndex = 1; !EFI_ERROR (Status) && HasMore && PageIndex < MAX_UINT32; PageIndex++) {
+      Status = DumpVariablePolicyHelper (PageIndex, &PolicySize, &PageSize, &HasMore, &Source);
+      if (!EFI_ERROR (Status)) {
+        CopyMem (Destination, Source, PageSize);
+        Destination += PageSize;
+      }
+    }
+
+    // Next, we check to see whether
+  } while (Status == EFI_TIMEOUT);
+
+  ReleaseLockOnlyAtBootTime (&mMmCommunicationLock);
+
+  // There's currently no use for this, but it shouldn't be hard to implement.
+  return Status;
+}
+
+
+/**
+  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     Others        An error has prevented this command from completing.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+ProtocolLockVariablePolicy (
+  VOID
+  )
+{
+  EFI_STATUS                    Status;
+  EFI_MM_COMMUNICATE_HEADER     *CommHeader;
+  VAR_CHECK_POLICY_COMM_HEADER  *PolicyHeader;
+  UINTN                         BufferSize;
+
+  AcquireLockOnlyAtBootTime (&mMmCommunicationLock);
+
+  // Set up the MM communication.
+  BufferSize    = mMmCommunicationBufferSize;
+  CommHeader    = mMmCommunicationBuffer;
+  PolicyHeader  = (VAR_CHECK_POLICY_COMM_HEADER*)&CommHeader->Data;
+  CopyGuid( &CommHeader->HeaderGuid, &gVarCheckPolicyLibMmiHandlerGuid );
+  CommHeader->MessageLength = BufferSize;
+  PolicyHeader->Signature   = VAR_CHECK_POLICY_COMM_SIG;
+  PolicyHeader->Revision    = VAR_CHECK_POLICY_COMM_REVISION;
+  PolicyHeader->Command     = VAR_CHECK_POLICY_COMMAND_LOCK;
+
+  Status = InternalMmCommunicate (CommHeader, &BufferSize);
+  DEBUG(( DEBUG_VERBOSE, "%a - MmCommunication returned %r.\n", __FUNCTION__, Status ));
+
+  ReleaseLockOnlyAtBootTime (&mMmCommunicationLock);
+
+  return (EFI_ERROR( Status )) ? Status : PolicyHeader->Result;
+}
+
+
+/**
+  This helper function locates the shared comm buffer and assigns it to input pointers.
+
+  @param[in,out]  BufferSize      On input, the minimum buffer size required INCLUDING the MM communicate header.
+                                  On output, the size of the matching buffer found.
+  @param[out]     LocatedBuffer   A pointer to the matching buffer.
+
+  @retval     EFI_SUCCESS
+  @retval     EFI_INVALID_PARAMETER   One of the output pointers was NULL.
+  @retval     EFI_OUT_OF_RESOURCES    Not enough memory to allocate a comm buffer.
+
+**/
+STATIC
+EFI_STATUS
+InitMmCommonCommBuffer (
+  IN OUT  UINTN       *BufferSize,
+  OUT     VOID        **LocatedBuffer
+  )
+{
+  EFI_STATUS                  Status;
+
+  Status = EFI_SUCCESS;
+
+  // Make sure that we're working with good pointers.
+  if (BufferSize == NULL || LocatedBuffer == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // Allocate the runtime memory for the comm buffer.
+  *LocatedBuffer = AllocateRuntimePool (*BufferSize);
+  if (*LocatedBuffer == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    *BufferSize = 0;
+  }
+
+  EfiInitializeLock (&mMmCommunicationLock, TPL_NOTIFY);
+
+  return Status;
+}
+
+
+/**
+  This helper is responsible for telemetry and any other actions that
+  need to be taken if the VariablePolicy fails to lock.
+
+  NOTE: It's possible that parts of this handling will need to become
+        part of a platform policy.
+
+  @param[in]  FailureStatus   The failure that was reported by LockVariablePolicy
+
+**/
+STATIC
+VOID
+VariablePolicyHandleFailureToLock (
+  IN  EFI_STATUS      FailureStatus
+  )
+{
+  // For now, there's no agreed-upon policy for this.
+  return;
+}
+
+
+/**
+  ReadyToBoot Callback
+  Lock the VariablePolicy interface if it hasn't already been locked.
+
+  @param[in]  Event     Event whose notification function is being invoked
+  @param[in]  Context   Pointer to the notification function's context
+
+**/
+STATIC
+VOID
+EFIAPI
+LockPolicyInterfaceAtReadyToBoot (
+  IN      EFI_EVENT                 Event,
+  IN      VOID                      *Context
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = ProtocolLockVariablePolicy();
+
+  if (EFI_ERROR( Status )) {
+    VariablePolicyHandleFailureToLock( Status );
+  }
+  else {
+    gBS->CloseEvent( Event );
+  }
+
+}
+
+
+/**
+  Convert internal pointer addresses to virtual addresses.
+
+  @param[in] Event      Event whose notification function is being invoked.
+  @param[in] Context    The pointer to the notification function's context, which
+                        is implementation-dependent.
+**/
+STATIC
+VOID
+EFIAPI
+VariablePolicyVirtualAddressCallback (
+  IN  EFI_EVENT   Event,
+  IN  VOID        *Context
+  )
+{
+  EfiConvertPointer (0, (VOID **)&mMmCommunication);
+  EfiConvertPointer (0, (VOID **)&mMmCommunicationBuffer);
+}
+
+
+/**
+  The driver's entry point.
+
+  @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.
+
+**/
+EFI_STATUS
+EFIAPI
+VariablePolicySmmDxeMain (
+  IN    EFI_HANDLE                  ImageHandle,
+  IN    EFI_SYSTEM_TABLE            *SystemTable
+  )
+{
+  EFI_STATUS              Status;
+  BOOLEAN                 ProtocolInstalled;
+  BOOLEAN                 CallbackRegistered;
+  BOOLEAN                 VirtualAddressChangeRegistered;
+  EFI_EVENT               ReadyToBootEvent;
+  EFI_EVENT               VirtualAddressChangeEvent;
+
+  Status = EFI_SUCCESS;
+  ProtocolInstalled = FALSE;
+  CallbackRegistered = FALSE;
+  VirtualAddressChangeRegistered = FALSE;
+
+  // Update the minimum buffer size.
+  mMmCommunicationBufferSize = VAR_CHECK_POLICY_MM_COMM_BUFFER_SIZE;
+  // Locate the shared comm buffer to use for sending MM commands.
+  Status = InitMmCommonCommBuffer( &mMmCommunicationBufferSize, &mMmCommunicationBuffer );
+  if (EFI_ERROR( Status )) {
+    DEBUG((DEBUG_ERROR, "%a - Failed to locate a viable MM comm buffer! %r\n", __FUNCTION__, Status));
+    ASSERT_EFI_ERROR( Status );
+    return Status;
+  }
+
+  // Locate the MmCommunication protocol.
+  Status = gBS->LocateProtocol( &gEfiMmCommunication2ProtocolGuid, NULL, (VOID**)&mMmCommunication );
+  if (EFI_ERROR( Status )) {
+    DEBUG((DEBUG_ERROR, "%a - Failed to locate MmCommunication protocol! %r\n", __FUNCTION__, Status));
+    ASSERT_EFI_ERROR( Status );
+    return Status;
+  }
+
+  // Configure the VariablePolicy protocol structure.
+  mVariablePolicyProtocol.Revision                = EDKII_VARIABLE_POLICY_PROTOCOL_REVISION;
+  mVariablePolicyProtocol.DisableVariablePolicy   = ProtocolDisableVariablePolicy;
+  mVariablePolicyProtocol.IsVariablePolicyEnabled = ProtocolIsVariablePolicyEnabled;
+  mVariablePolicyProtocol.RegisterVariablePolicy  = ProtocolRegisterVariablePolicy;
+  mVariablePolicyProtocol.DumpVariablePolicy      = ProtocolDumpVariablePolicy;
+  mVariablePolicyProtocol.LockVariablePolicy      = ProtocolLockVariablePolicy;
+
+  // Register all the protocols and return the status.
+  Status = gBS->InstallMultipleProtocolInterfaces( &ImageHandle,
+                                                   &gEdkiiVariablePolicyProtocolGuid, &mVariablePolicyProtocol,
+                                                   NULL );
+  if (EFI_ERROR( Status )) {
+    DEBUG(( DEBUG_ERROR, "%a - Failed to install protocol! %r\n", __FUNCTION__, Status ));
+    goto Exit;
+  }
+  else {
+    ProtocolInstalled = TRUE;
+  }
+
+  //
+  // Register a callback for ReadyToBoot so that the interface is at least locked before
+  // dispatching any bootloaders or UEFI apps.
+  Status = gBS->CreateEventEx( EVT_NOTIFY_SIGNAL,
+                               TPL_CALLBACK,
+                               LockPolicyInterfaceAtReadyToBoot,
+                               NULL,
+                               &gEfiEventReadyToBootGuid,
+                               &ReadyToBootEvent );
+  if (EFI_ERROR( Status )) {
+    DEBUG(( DEBUG_ERROR, "%a - Failed to create ReadyToBoot event! %r\n", __FUNCTION__, Status ));
+    goto Exit;
+  }
+  else {
+    CallbackRegistered = TRUE;
+  }
+
+  //
+  // Register a VirtualAddressChange callback for the MmComm protocol and Comm buffer.
+  Status = gBS->CreateEventEx (EVT_NOTIFY_SIGNAL,
+                                TPL_NOTIFY,
+                                VariablePolicyVirtualAddressCallback,
+                                NULL,
+                                &gEfiEventVirtualAddressChangeGuid,
+                                &VirtualAddressChangeEvent);
+  if (EFI_ERROR( Status )) {
+    DEBUG(( DEBUG_ERROR, "%a - Failed to create VirtualAddressChange event! %r\n", __FUNCTION__, Status ));
+    goto Exit;
+  }
+  else {
+    VirtualAddressChangeRegistered = TRUE;
+  }
+
+
+Exit:
+  //
+  // If we're about to return a failed status (and unload this driver), we must first undo anything that
+  // has been successfully done.
+  if (EFI_ERROR( Status )) {
+    if (ProtocolInstalled) {
+      gBS->UninstallProtocolInterface( &ImageHandle, &gEdkiiVariablePolicyProtocolGuid, &mVariablePolicyProtocol );
+    }
+    if (CallbackRegistered) {
+      gBS->CloseEvent( ReadyToBootEvent );
+    }
+    if (VirtualAddressChangeRegistered) {
+      gBS->CloseEvent( VirtualAddressChangeEvent );
+    }
+  }
+
+  return Status;
+}
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c
index 663a1aaa128f..c47e614d81f4 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c
@@ -65,6 +65,17 @@ EFI_LOCK                         mVariableServicesLock;
 EDKII_VARIABLE_LOCK_PROTOCOL     mVariableLock;
 EDKII_VAR_CHECK_PROTOCOL         mVarCheck;
 
+/**
+  The logic to initialize the VariablePolicy engine is in its own file.
+
+**/
+EFI_STATUS
+EFIAPI
+VariablePolicySmmDxeMain (
+  IN    EFI_HANDLE                  ImageHandle,
+  IN    EFI_SYSTEM_TABLE            *SystemTable
+  );
+
 /**
   Some Secure Boot Policy Variable may update following other variable changes(SecureBoot follows PK change, etc).
   Record their initial State when variable write service is ready.
@@ -1796,6 +1807,9 @@ VariableSmmRuntimeInitialize (
          &mVirtualAddressChangeEvent
          );
 
+  // Initialize the VariablePolicy protocol and engine.
+  VariablePolicySmmDxeMain (ImageHandle, SystemTable);
+
   return EFI_SUCCESS;
 }
 
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
index ceea5d1ff9ac..48ac167906f7 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
@@ -10,6 +10,7 @@
 #  buffer overflow or integer overflow.
 #
 # Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) Microsoft Corporation.
 # SPDX-License-Identifier: BSD-2-Clause-Patent
 #
 ##
@@ -69,6 +70,7 @@ [LibraryClasses]
   TpmMeasurementLib
   AuthVariableLib
   VarCheckLib
+  VariablePolicyLib
 
 [Protocols]
   gEfiFirmwareVolumeBlockProtocolGuid           ## CONSUMES
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf
index bc3033588d40..bbc8d2080193 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf
@@ -19,6 +19,7 @@
 #  the authentication service provided in this driver will be broken, and the behavior is undefined.
 #
 # Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) Microsoft Corporation.
 # SPDX-License-Identifier: BSD-2-Clause-Patent
 #
 ##
@@ -78,6 +79,8 @@ [LibraryClasses]
   AuthVariableLib
   VarCheckLib
   UefiBootServicesTableLib
+  VariablePolicyLib
+  VariablePolicyHelperLib
 
 [Protocols]
   gEfiSmmFirmwareVolumeBlockProtocolGuid        ## CONSUMES
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf
index 01564e4c5068..f217530b2985 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf
@@ -14,6 +14,7 @@
 #  the authentication service provided in this driver will be broken, and the behavior is undefined.
 #
 # Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) Microsoft Corporation.<BR>
 # SPDX-License-Identifier: BSD-2-Clause-Patent
 #
 ##
@@ -42,6 +43,7 @@ [Sources]
   VariableParsing.c
   VariableParsing.h
   Variable.h
+  VariablePolicySmmDxe.c
 
 [Packages]
   MdePkg/MdePkg.dec
@@ -56,6 +58,8 @@ [LibraryClasses]
   DxeServicesTableLib
   UefiDriverEntryPoint
   TpmMeasurementLib
+  SafeIntLib
+  PcdLib
 
 [Protocols]
   gEfiVariableWriteArchProtocolGuid             ## PRODUCES
@@ -67,11 +71,15 @@ [Protocols]
   gEfiSmmVariableProtocolGuid
   gEdkiiVariableLockProtocolGuid                ## PRODUCES
   gEdkiiVarCheckProtocolGuid                    ## PRODUCES
+  gEdkiiVariablePolicyProtocolGuid              ## PRODUCES
 
 [FeaturePcd]
   gEfiMdeModulePkgTokenSpaceGuid.PcdEnableVariableRuntimeCache           ## CONSUMES
   gEfiMdeModulePkgTokenSpaceGuid.PcdVariableCollectStatistics            ## CONSUMES
 
+[Pcd]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAllowVariablePolicyEnforcementDisable     ## CONSUMES
+
 [Guids]
   ## PRODUCES             ## GUID # Signature of Variable store header
   ## CONSUMES             ## GUID # Signature of Variable store header
@@ -99,6 +107,8 @@ [Guids]
   ## SOMETIMES_CONSUMES   ## Variable:L"dbt"
   gEfiImageSecurityDatabaseGuid
 
+  gVarCheckPolicyLibMmiHandlerGuid
+
 [Depex]
   gEfiMmCommunication2ProtocolGuid
 
-- 
2.26.2.windows.1.8.g01c50adf56.20200515075929


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH v6 10/14] MdeModulePkg: Allow VariablePolicy state to delete protected variables
  2020-06-23  6:40 [PATCH v6 00/14] Add the VariablePolicy feature bret
                   ` (8 preceding siblings ...)
  2020-06-23  6:40 ` [PATCH v6 09/14] MdeModulePkg: Connect VariablePolicy business logic to VariableServices Bret Barkelew
@ 2020-06-23  6:41 ` Bret Barkelew
  2020-06-23  6:41 ` [PATCH v6 11/14] SecurityPkg: Allow VariablePolicy state to delete authenticated variables Bret Barkelew
                   ` (6 subsequent siblings)
  16 siblings, 0 replies; 48+ messages in thread
From: Bret Barkelew @ 2020-06-23  6:41 UTC (permalink / raw)
  To: devel; +Cc: Jian J Wang, Hao A Wu, Liming Gao

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

TcgMorLockSmm provides special protections for
the TCG MOR variables. This will check
IsVariablePolicyEnabled() before enforcing
them to allow variable deletion when policy
engine is disabled.

Only allows deletion, not modification.

Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Hao A Wu <hao.a.wu@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Bret Barkelew <brbarkel@microsoft.com>
Signed-off-by: Bret Barkelew <brbarkel@microsoft.com>
---
 MdeModulePkg/Universal/Variable/RuntimeDxe/TcgMorLockSmm.c          | 10 ++++++++++
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf |  2 ++
 2 files changed, 12 insertions(+)

diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/TcgMorLockSmm.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/TcgMorLockSmm.c
index 6d80eb64341a..085f82035f4b 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/TcgMorLockSmm.c
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/TcgMorLockSmm.c
@@ -5,6 +5,7 @@
   This module adds Variable Hook and check MemoryOverwriteRequestControlLock.
 
 Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) Microsoft Corporation.
 SPDX-License-Identifier: BSD-2-Clause-Patent
 
 **/
@@ -17,6 +18,10 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 #include <Library/BaseMemoryLib.h>
 #include "Variable.h"
 
+#include <Protocol/VariablePolicy.h>
+
+#include <Library/VariablePolicyLib.h>
+
 typedef struct {
   CHAR16                                 *VariableName;
   EFI_GUID                               *VendorGuid;
@@ -341,6 +346,11 @@ SetVariableCheckHandlerMor (
     return EFI_SUCCESS;
   }
 
+  // Permit deletion when policy is disabled.
+  if (!IsVariablePolicyEnabled() && ((Attributes == 0) || (DataSize == 0))) {
+    return EFI_SUCCESS;
+  }
+
   //
   // MorLock variable
   //
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf
index 6e17f6cdf588..d8f480be27cc 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf
@@ -20,6 +20,7 @@
 #
 # Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.<BR>
 # Copyright (c) 2018, Linaro, Ltd. All rights reserved.<BR>
+# Copyright (c) Microsoft Corporation.
 # SPDX-License-Identifier: BSD-2-Clause-Patent
 #
 ##
@@ -74,6 +75,7 @@ [LibraryClasses]
   StandaloneMmDriverEntryPoint
   SynchronizationLib
   VarCheckLib
+  VariablePolicyLib
 
 [Protocols]
   gEfiSmmFirmwareVolumeBlockProtocolGuid        ## CONSUMES
-- 
2.26.2.windows.1.8.g01c50adf56.20200515075929


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH v6 11/14] SecurityPkg: Allow VariablePolicy state to delete authenticated variables
  2020-06-23  6:40 [PATCH v6 00/14] Add the VariablePolicy feature bret
                   ` (9 preceding siblings ...)
  2020-06-23  6:41 ` [PATCH v6 10/14] MdeModulePkg: Allow VariablePolicy state to delete protected variables Bret Barkelew
@ 2020-06-23  6:41 ` Bret Barkelew
  2020-06-23  6:41 ` [PATCH v6 12/14] MdeModulePkg: Change TCG MOR variables to use VariablePolicy Bret Barkelew
                   ` (5 subsequent siblings)
  16 siblings, 0 replies; 48+ messages in thread
From: Bret Barkelew @ 2020-06-23  6:41 UTC (permalink / raw)
  To: devel; +Cc: Jiewen Yao, Jian J Wang, Chao Zhang

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

Causes AuthService to check
IsVariablePolicyEnabled() before enforcing
write protections to allow variable deletion
when policy engine is disabled.

Only allows deletion, not modification.

Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Cc: Bret Barkelew <brbarkel@microsoft.com>
Signed-off-by: Bret Barkelew <brbarkel@microsoft.com>
---
 SecurityPkg/Library/AuthVariableLib/AuthService.c       | 22 ++++++++++++++++----
 SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf |  2 ++
 2 files changed, 20 insertions(+), 4 deletions(-)

diff --git a/SecurityPkg/Library/AuthVariableLib/AuthService.c b/SecurityPkg/Library/AuthVariableLib/AuthService.c
index 2f60331f2c04..aca9a5620c28 100644
--- a/SecurityPkg/Library/AuthVariableLib/AuthService.c
+++ b/SecurityPkg/Library/AuthVariableLib/AuthService.c
@@ -19,12 +19,16 @@
   to verify the signature.
 
 Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.<BR>
+Copyright (c) Microsoft Corporation.
 SPDX-License-Identifier: BSD-2-Clause-Patent
 
 **/
 
 #include "AuthServiceInternal.h"
 
+#include <Protocol/VariablePolicy.h>
+#include <Library/VariablePolicyLib.h>
+
 //
 // Public Exponent of RSA Key.
 //
@@ -217,9 +221,12 @@ NeedPhysicallyPresent(
   IN     EFI_GUID       *VendorGuid
   )
 {
-  if ((CompareGuid (VendorGuid, &gEfiSecureBootEnableDisableGuid) && (StrCmp (VariableName, EFI_SECURE_BOOT_ENABLE_NAME) == 0))
-    || (CompareGuid (VendorGuid, &gEfiCustomModeEnableGuid) && (StrCmp (VariableName, EFI_CUSTOM_MODE_NAME) == 0))) {
-    return TRUE;
+  // If the VariablePolicy engine is disabled, allow deletion of any authenticated variables.
+  if (IsVariablePolicyEnabled()) {
+    if ((CompareGuid (VendorGuid, &gEfiSecureBootEnableDisableGuid) && (StrCmp (VariableName, EFI_SECURE_BOOT_ENABLE_NAME) == 0))
+      || (CompareGuid (VendorGuid, &gEfiCustomModeEnableGuid) && (StrCmp (VariableName, EFI_CUSTOM_MODE_NAME) == 0))) {
+      return TRUE;
+    }
   }
 
   return FALSE;
@@ -842,7 +849,8 @@ ProcessVariable (
              &OrgVariableInfo
              );
 
-  if ((!EFI_ERROR (Status)) && IsDeleteAuthVariable (OrgVariableInfo.Attributes, Data, DataSize, Attributes) && UserPhysicalPresent()) {
+  // If the VariablePolicy engine is disabled, allow deletion of any authenticated variables.
+  if ((!EFI_ERROR (Status)) && IsDeleteAuthVariable (OrgVariableInfo.Attributes, Data, DataSize, Attributes) && (UserPhysicalPresent() || !IsVariablePolicyEnabled())) {
     //
     // Allow the delete operation of common authenticated variable(AT or AW) at user physical presence.
     //
@@ -1960,6 +1968,12 @@ VerifyTimeBasedPayload (
 
   CopyMem (Buffer, PayloadPtr, PayloadSize);
 
+  // If the VariablePolicy engine is disabled, allow deletion of any authenticated variables.
+  if (PayloadSize == 0 && (Attributes & EFI_VARIABLE_APPEND_WRITE) == 0 && !IsVariablePolicyEnabled()) {
+    VerifyStatus = TRUE;
+    goto Exit;
+  }
+
   if (AuthVarType == AuthVarTypePk) {
     //
     // Verify that the signature has been made with the current Platform Key (no chaining for PK).
diff --git a/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf b/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf
index 8d4ce14df494..8eadeebcebd7 100644
--- a/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf
+++ b/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf
@@ -3,6 +3,7 @@
 #
 #  Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
 #  Copyright (c) 2018, ARM Limited. All rights reserved.<BR>
+#  Copyright (c) Microsoft Corporation.
 #
 #  SPDX-License-Identifier: BSD-2-Clause-Patent
 #
@@ -41,6 +42,7 @@ [LibraryClasses]
   MemoryAllocationLib
   BaseCryptLib
   PlatformSecureLib
+  VariablePolicyLib
 
 [Guids]
   ## CONSUMES            ## Variable:L"SetupMode"
-- 
2.26.2.windows.1.8.g01c50adf56.20200515075929


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH v6 12/14] MdeModulePkg: Change TCG MOR variables to use VariablePolicy
  2020-06-23  6:40 [PATCH v6 00/14] Add the VariablePolicy feature bret
                   ` (10 preceding siblings ...)
  2020-06-23  6:41 ` [PATCH v6 11/14] SecurityPkg: Allow VariablePolicy state to delete authenticated variables Bret Barkelew
@ 2020-06-23  6:41 ` Bret Barkelew
  2020-06-23  6:41 ` [PATCH v6 13/14] MdeModulePkg: Drop VarLock from RuntimeDxe variable driver Bret Barkelew
                   ` (4 subsequent siblings)
  16 siblings, 0 replies; 48+ messages in thread
From: Bret Barkelew @ 2020-06-23  6:41 UTC (permalink / raw)
  To: devel; +Cc: Jian J Wang, Hao A Wu, Liming Gao

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

These were previously using VarLock, which is
being deprecated.

Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Hao A Wu <hao.a.wu@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Bret Barkelew <brbarkel@microsoft.com>
Signed-off-by: Bret Barkelew <brbarkel@microsoft.com>
---
 MdeModulePkg/Universal/Variable/RuntimeDxe/TcgMorLockDxe.c          | 52 ++++++++++++++------
 MdeModulePkg/Universal/Variable/RuntimeDxe/TcgMorLockSmm.c          | 52 +++++++++++++++-----
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf   |  2 +
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf |  1 +
 4 files changed, 82 insertions(+), 25 deletions(-)

diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/TcgMorLockDxe.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/TcgMorLockDxe.c
index e7accf4ed806..b85f08c48c11 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/TcgMorLockDxe.c
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/TcgMorLockDxe.c
@@ -5,6 +5,7 @@
   MOR lock control unsupported.
 
 Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+Copyright (c) Microsoft Corporation.
 SPDX-License-Identifier: BSD-2-Clause-Patent
 
 **/
@@ -17,7 +18,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 #include <Library/BaseMemoryLib.h>
 #include "Variable.h"
 
-extern EDKII_VARIABLE_LOCK_PROTOCOL     mVariableLock;
+#include <Protocol/VariablePolicy.h>
+#include <Library/VariablePolicyHelperLib.h>
 
 /**
   This service is an MOR/MorLock checker handler for the SetVariable().
@@ -77,11 +79,6 @@ MorLockInit (
     NULL                                        // Data
     );
 
-  //
-  // Need set this variable to be read-only to prevent other module set it.
-  //
-  VariableLockRequestToLock (&mVariableLock, MEMORY_OVERWRITE_REQUEST_CONTROL_LOCK_NAME, &gEfiMemoryOverwriteRequestControlLockGuid);
-
   //
   // The MOR variable can effectively improve platform security only when the
   // MorLock variable protects the MOR variable. In turn MorLock cannot be made
@@ -99,11 +96,6 @@ MorLockInit (
     0,                                      // DataSize
     NULL                                    // Data
     );
-  VariableLockRequestToLock (
-    &mVariableLock,
-    MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME,
-    &gEfiMemoryOverwriteControlDataGuid
-    );
 
   return EFI_SUCCESS;
 }
@@ -118,7 +110,39 @@ MorLockInitAtEndOfDxe (
   VOID
   )
 {
-  //
-  // Do nothing.
-  //
+  EFI_STATUS                        Status;
+  EDKII_VARIABLE_POLICY_PROTOCOL    *VariablePolicy;
+
+  // First, we obviously need to locate the VariablePolicy protocol.
+  Status = gBS->LocateProtocol( &gEdkiiVariablePolicyProtocolGuid, NULL, (VOID**)&VariablePolicy );
+  if (EFI_ERROR( Status )) {
+    DEBUG(( DEBUG_ERROR, "%a - Could not locate VariablePolicy protocol! %r\n", __FUNCTION__, Status ));
+    return;
+  }
+
+  // If we're successful, go ahead and set the policies to protect the target variables.
+  Status = RegisterBasicVariablePolicy( VariablePolicy,
+                                        &gEfiMemoryOverwriteRequestControlLockGuid,
+                                        MEMORY_OVERWRITE_REQUEST_CONTROL_LOCK_NAME,
+                                        VARIABLE_POLICY_NO_MIN_SIZE,
+                                        VARIABLE_POLICY_NO_MAX_SIZE,
+                                        VARIABLE_POLICY_NO_MUST_ATTR,
+                                        VARIABLE_POLICY_NO_CANT_ATTR,
+                                        VARIABLE_POLICY_TYPE_LOCK_NOW );
+  if (EFI_ERROR( Status )) {
+    DEBUG(( DEBUG_ERROR, "%a - Could not lock variable %s! %r\n", __FUNCTION__, MEMORY_OVERWRITE_REQUEST_CONTROL_LOCK_NAME, Status ));
+  }
+  Status = RegisterBasicVariablePolicy( VariablePolicy,
+                                        &gEfiMemoryOverwriteControlDataGuid,
+                                        MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME,
+                                        VARIABLE_POLICY_NO_MIN_SIZE,
+                                        VARIABLE_POLICY_NO_MAX_SIZE,
+                                        VARIABLE_POLICY_NO_MUST_ATTR,
+                                        VARIABLE_POLICY_NO_CANT_ATTR,
+                                        VARIABLE_POLICY_TYPE_LOCK_NOW );
+  if (EFI_ERROR( Status )) {
+    DEBUG(( DEBUG_ERROR, "%a - Could not lock variable %s! %r\n", __FUNCTION__, MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME, Status ));
+  }
+
+  return;
 }
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/TcgMorLockSmm.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/TcgMorLockSmm.c
index 085f82035f4b..ee37942a6b0c 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/TcgMorLockSmm.c
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/TcgMorLockSmm.c
@@ -19,7 +19,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 #include "Variable.h"
 
 #include <Protocol/VariablePolicy.h>
-
+#include <Library/VariablePolicyHelperLib.h>
 #include <Library/VariablePolicyLib.h>
 
 typedef struct {
@@ -422,6 +422,8 @@ MorLockInitAtEndOfDxe (
 {
   UINTN      MorSize;
   EFI_STATUS MorStatus;
+  EFI_STATUS              Status;
+  VARIABLE_POLICY_ENTRY   *NewPolicy;
 
   if (!mMorLockInitializationRequired) {
     //
@@ -494,11 +496,25 @@ MorLockInitAtEndOfDxe (
   // The MOR variable is absent; the platform firmware does not support it.
   // Lock the variable so that no other module may create it.
   //
-  VariableLockRequestToLock (
-    NULL,                                   // This
-    MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME,
-    &gEfiMemoryOverwriteControlDataGuid
-    );
+  NewPolicy = NULL;
+  Status = CreateBasicVariablePolicy( &gEfiMemoryOverwriteControlDataGuid,
+                                      MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME,
+                                      VARIABLE_POLICY_NO_MIN_SIZE,
+                                      VARIABLE_POLICY_NO_MAX_SIZE,
+                                      VARIABLE_POLICY_NO_MUST_ATTR,
+                                      VARIABLE_POLICY_NO_CANT_ATTR,
+                                      VARIABLE_POLICY_TYPE_LOCK_NOW,
+                                      &NewPolicy );
+  if (!EFI_ERROR( Status )) {
+    Status = RegisterVariablePolicy( NewPolicy );
+  }
+  if (EFI_ERROR( Status )) {
+    DEBUG(( DEBUG_ERROR, "%a - Failed to lock variable %s! %r\n", __FUNCTION__, MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME, Status ));
+    ASSERT_EFI_ERROR( Status );
+  }
+  if (NewPolicy != NULL) {
+    FreePool( NewPolicy );
+  }
 
   //
   // Delete the MOR Control Lock variable too (should it exists for some
@@ -514,9 +530,23 @@ MorLockInitAtEndOfDxe (
     );
   mMorLockPassThru = FALSE;
 
-  VariableLockRequestToLock (
-    NULL,                                       // This
-    MEMORY_OVERWRITE_REQUEST_CONTROL_LOCK_NAME,
-    &gEfiMemoryOverwriteRequestControlLockGuid
-    );
+  NewPolicy = NULL;
+  Status = CreateBasicVariablePolicy( &gEfiMemoryOverwriteRequestControlLockGuid,
+                                      MEMORY_OVERWRITE_REQUEST_CONTROL_LOCK_NAME,
+                                      VARIABLE_POLICY_NO_MIN_SIZE,
+                                      VARIABLE_POLICY_NO_MAX_SIZE,
+                                      VARIABLE_POLICY_NO_MUST_ATTR,
+                                      VARIABLE_POLICY_NO_CANT_ATTR,
+                                      VARIABLE_POLICY_TYPE_LOCK_NOW,
+                                      &NewPolicy );
+  if (!EFI_ERROR( Status )) {
+    Status = RegisterVariablePolicy( NewPolicy );
+  }
+  if (EFI_ERROR( Status )) {
+    DEBUG(( DEBUG_ERROR, "%a - Failed to lock variable %s! %r\n", __FUNCTION__, MEMORY_OVERWRITE_REQUEST_CONTROL_LOCK_NAME, Status ));
+    ASSERT_EFI_ERROR( Status );
+  }
+  if (NewPolicy != NULL) {
+    FreePool( NewPolicy );
+  }
 }
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
index 48ac167906f7..8debc560e6dc 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
@@ -71,6 +71,7 @@ [LibraryClasses]
   AuthVariableLib
   VarCheckLib
   VariablePolicyLib
+  VariablePolicyHelperLib
 
 [Protocols]
   gEfiFirmwareVolumeBlockProtocolGuid           ## CONSUMES
@@ -80,6 +81,7 @@ [Protocols]
   gEfiVariableWriteArchProtocolGuid             ## PRODUCES
   gEfiVariableArchProtocolGuid                  ## PRODUCES
   gEdkiiVariableLockProtocolGuid                ## PRODUCES
+  gEdkiiVariablePolicyProtocolGuid              ## CONSUMES
   gEdkiiVarCheckProtocolGuid                    ## PRODUCES
 
 [Guids]
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf
index d8f480be27cc..62f2f9252f43 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf
@@ -76,6 +76,7 @@ [LibraryClasses]
   SynchronizationLib
   VarCheckLib
   VariablePolicyLib
+  VariablePolicyHelperLib
 
 [Protocols]
   gEfiSmmFirmwareVolumeBlockProtocolGuid        ## CONSUMES
-- 
2.26.2.windows.1.8.g01c50adf56.20200515075929


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH v6 13/14] MdeModulePkg: Drop VarLock from RuntimeDxe variable driver
  2020-06-23  6:40 [PATCH v6 00/14] Add the VariablePolicy feature bret
                   ` (11 preceding siblings ...)
  2020-06-23  6:41 ` [PATCH v6 12/14] MdeModulePkg: Change TCG MOR variables to use VariablePolicy Bret Barkelew
@ 2020-06-23  6:41 ` Bret Barkelew
  2020-07-02  2:13   ` [edk2-devel] " Dandan Bi
  2020-06-23  6:41 ` [PATCH v6 14/14] MdeModulePkg: Add a shell-based functional test for VariablePolicy Bret Barkelew
                   ` (3 subsequent siblings)
  16 siblings, 1 reply; 48+ messages in thread
From: Bret Barkelew @ 2020-06-23  6:41 UTC (permalink / raw)
  To: devel; +Cc: Jian J Wang, Hao A Wu, Liming Gao

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

Now that everything should be moved to
VariablePolicy, drop support for the
deprecated VarLock SMI interface and
associated functions from variable RuntimeDxe.

Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Hao A Wu <hao.a.wu@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Bret Barkelew <brbarkel@microsoft.com>
Signed-off-by: Bret Barkelew <brbarkel@microsoft.com>
---
 MdeModulePkg/Universal/Variable/RuntimeDxe/VarCheck.c                 | 49 +-------------
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableLockRequstToLock.c | 71 ++++++++++++++++++++
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf     |  1 +
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf            |  1 +
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf   |  1 +
 5 files changed, 75 insertions(+), 48 deletions(-)

diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VarCheck.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/VarCheck.c
index f15219df5eb8..486d85b022e1 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VarCheck.c
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VarCheck.c
@@ -3,60 +3,13 @@
   and variable lock protocol based on VarCheckLib.
 
 Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+Copyright (c) Microsoft Corporation.
 SPDX-License-Identifier: BSD-2-Clause-Patent
 
 **/
 
 #include "Variable.h"
 
-/**
-  Mark a variable that will become read-only after leaving the DXE phase of execution.
-  Write request coming from SMM environment through EFI_SMM_VARIABLE_PROTOCOL is allowed.
-
-  @param[in] This          The VARIABLE_LOCK_PROTOCOL instance.
-  @param[in] VariableName  A pointer to the variable name that will be made read-only subsequently.
-  @param[in] VendorGuid    A pointer to the vendor GUID that will be made read-only subsequently.
-
-  @retval EFI_SUCCESS           The variable specified by the VariableName and the VendorGuid was marked
-                                as pending to be read-only.
-  @retval EFI_INVALID_PARAMETER VariableName or VendorGuid is NULL.
-                                Or VariableName is an empty string.
-  @retval EFI_ACCESS_DENIED     EFI_END_OF_DXE_EVENT_GROUP_GUID or EFI_EVENT_GROUP_READY_TO_BOOT has
-                                already been signaled.
-  @retval EFI_OUT_OF_RESOURCES  There is not enough resource to hold the lock request.
-**/
-EFI_STATUS
-EFIAPI
-VariableLockRequestToLock (
-  IN CONST EDKII_VARIABLE_LOCK_PROTOCOL *This,
-  IN       CHAR16                       *VariableName,
-  IN       EFI_GUID                     *VendorGuid
-  )
-{
-  EFI_STATUS                    Status;
-  VAR_CHECK_VARIABLE_PROPERTY   Property;
-
-  AcquireLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
-
-  Status = VarCheckLibVariablePropertyGet (VariableName, VendorGuid, &Property);
-  if (!EFI_ERROR (Status)) {
-    Property.Property |= VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY;
-  } else {
-    Property.Revision = VAR_CHECK_VARIABLE_PROPERTY_REVISION;
-    Property.Property = VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY;
-    Property.Attributes = 0;
-    Property.MinSize = 1;
-    Property.MaxSize = MAX_UINTN;
-  }
-  Status = VarCheckLibVariablePropertySet (VariableName, VendorGuid, &Property);
-
-  DEBUG ((EFI_D_INFO, "[Variable] Lock: %g:%s %r\n", VendorGuid, VariableName, Status));
-
-  ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
-
-  return Status;
-}
-
 /**
   Register SetVariable check handler.
 
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableLockRequstToLock.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableLockRequstToLock.c
new file mode 100644
index 000000000000..1f7f0b7ef06c
--- /dev/null
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableLockRequstToLock.c
@@ -0,0 +1,71 @@
+/** @file -- VariableLockRequstToLock.c
+Temporary location of the RequestToLock shim code while
+projects are moved to VariablePolicy. Should be removed when deprecated.
+
+Copyright (c) Microsoft Corporation.
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+#include <Protocol/VariableLock.h>
+
+#include <Protocol/VariablePolicy.h>
+#include <Library/VariablePolicyLib.h>
+#include <Library/VariablePolicyHelperLib.h>
+
+
+/**
+  DEPRECATED. THIS IS ONLY HERE AS A CONVENIENCE WHILE PORTING.
+  Mark a variable that will become read-only after leaving the DXE phase of execution.
+  Write request coming from SMM environment through EFI_SMM_VARIABLE_PROTOCOL is allowed.
+
+  @param[in] This          The VARIABLE_LOCK_PROTOCOL instance.
+  @param[in] VariableName  A pointer to the variable name that will be made read-only subsequently.
+  @param[in] VendorGuid    A pointer to the vendor GUID that will be made read-only subsequently.
+
+  @retval EFI_SUCCESS           The variable specified by the VariableName and the VendorGuid was marked
+                                as pending to be read-only.
+  @retval EFI_INVALID_PARAMETER VariableName or VendorGuid is NULL.
+                                Or VariableName is an empty string.
+  @retval EFI_ACCESS_DENIED     EFI_END_OF_DXE_EVENT_GROUP_GUID or EFI_EVENT_GROUP_READY_TO_BOOT has
+                                already been signaled.
+  @retval EFI_OUT_OF_RESOURCES  There is not enough resource to hold the lock request.
+**/
+EFI_STATUS
+EFIAPI
+VariableLockRequestToLock (
+  IN CONST EDKII_VARIABLE_LOCK_PROTOCOL *This,
+  IN       CHAR16                       *VariableName,
+  IN       EFI_GUID                     *VendorGuid
+  )
+{
+  EFI_STATUS              Status;
+  VARIABLE_POLICY_ENTRY   *NewPolicy;
+
+  NewPolicy = NULL;
+  Status = CreateBasicVariablePolicy( VendorGuid,
+                                      VariableName,
+                                      VARIABLE_POLICY_NO_MIN_SIZE,
+                                      VARIABLE_POLICY_NO_MAX_SIZE,
+                                      VARIABLE_POLICY_NO_MUST_ATTR,
+                                      VARIABLE_POLICY_NO_CANT_ATTR,
+                                      VARIABLE_POLICY_TYPE_LOCK_NOW,
+                                      &NewPolicy );
+  if (!EFI_ERROR( Status )) {
+    Status = RegisterVariablePolicy( NewPolicy );
+  }
+  if (EFI_ERROR( Status )) {
+    DEBUG(( DEBUG_ERROR, "%a - Failed to lock variable %s! %r\n", __FUNCTION__, VariableName, Status ));
+    ASSERT_EFI_ERROR( Status );
+  }
+  if (NewPolicy != NULL) {
+    FreePool( NewPolicy );
+  }
+
+  return Status;
+}
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
index 8debc560e6dc..3005e9617423 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
@@ -49,6 +49,7 @@ [Sources]
   VarCheck.c
   VariableExLib.c
   SpeculationBarrierDxe.c
+  VariableLockRequstToLock.c
 
 [Packages]
   MdePkg/MdePkg.dec
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf
index bbc8d2080193..26fbad97339f 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf
@@ -58,6 +58,7 @@ [Sources]
   VariableExLib.c
   TcgMorLockSmm.c
   SpeculationBarrierSmm.c
+  VariableLockRequstToLock.c
 
 [Packages]
   MdePkg/MdePkg.dec
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf
index 62f2f9252f43..7c6fdf4d65fd 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf
@@ -58,6 +58,7 @@ [Sources]
   VariableExLib.c
   TcgMorLockSmm.c
   SpeculationBarrierSmm.c
+  VariableLockRequstToLock.c
 
 [Packages]
   MdePkg/MdePkg.dec
-- 
2.26.2.windows.1.8.g01c50adf56.20200515075929


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [PATCH v6 14/14] MdeModulePkg: Add a shell-based functional test for VariablePolicy
  2020-06-23  6:40 [PATCH v6 00/14] Add the VariablePolicy feature bret
                   ` (12 preceding siblings ...)
  2020-06-23  6:41 ` [PATCH v6 13/14] MdeModulePkg: Drop VarLock from RuntimeDxe variable driver Bret Barkelew
@ 2020-06-23  6:41 ` Bret Barkelew
  2020-07-02  2:13 ` [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature Dandan Bi
                   ` (2 subsequent siblings)
  16 siblings, 0 replies; 48+ messages in thread
From: Bret Barkelew @ 2020-06-23  6:41 UTC (permalink / raw)
  To: devel; +Cc: Jian J Wang, Hao A Wu, Liming Gao

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

To verify that VariablePolicy is correctly integrated
on platforms, add a Shell-based functional test to
confirm expected behavior.

NOTE: This test assumes that VariablePolicy is built
with PcdAllowVariablePolicyEnforcementDisable set to
TRUE.

Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Hao A Wu <hao.a.wu@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Bret Barkelew <brbarkel@microsoft.com>
Signed-off-by: Bret Barkelew <brbarkel@microsoft.com>
---
 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePolicyUnitTest.c |    6 +-
 MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/VariablePolicyFuncTestApp.c      | 1978 ++++++++++++++++++++
 MdeModulePkg/MdeModulePkg.ci.yaml                                                      |    4 +-
 MdeModulePkg/MdeModulePkg.dsc                                                          |    6 +
 MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/Readme.md                        |   55 +
 MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/VariablePolicyFuncTestApp.inf    |   42 +
 6 files changed, 2089 insertions(+), 2 deletions(-)

diff --git a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePolicyUnitTest.c b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePolicyUnitTest.c
index f133f2f30e36..809817a4823e 100644
--- a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePolicyUnitTest.c
+++ b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePolicyUnitTest.c
@@ -39,9 +39,11 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 ///=== TEST DATA ==================================================================================
 
 #pragma pack(push, 1)
+#define SIMPLE_VARIABLE_POLICY_ENTRY_VAR_NAME_LENGTH  1001    // 1000 characters + terminator.
+#define SIMPLE_VARIABLE_POLICY_ENTRY_VAR_NAME_SIZE    (SIMPLE_VARIABLE_POLICY_ENTRY_VAR_NAME_LENGTH * sizeof(CHAR16))
 typedef struct _SIMPLE_VARIABLE_POLICY_ENTRY {
   VARIABLE_POLICY_ENTRY     Header;
-  CHAR16                    Name[];
+  CHAR16                    Name[SIMPLE_VARIABLE_POLICY_ENTRY_VAR_NAME_LENGTH];
 } 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))
@@ -181,6 +183,7 @@ StubGetVariableNull (
 **/
 STATIC
 UNIT_TEST_STATUS
+EFIAPI
 LibInitMocked (
   IN UNIT_TEST_CONTEXT      Context
   )
@@ -194,6 +197,7 @@ LibInitMocked (
 */
 STATIC
 VOID
+EFIAPI
 LibCleanup (
   IN UNIT_TEST_CONTEXT      Context
   )
diff --git a/MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/VariablePolicyFuncTestApp.c b/MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/VariablePolicyFuncTestApp.c
new file mode 100644
index 000000000000..719323ac1b88
--- /dev/null
+++ b/MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/VariablePolicyFuncTestApp.c
@@ -0,0 +1,1978 @@
+/** @file
+UEFI Shell based application for unit testing the Variable Policy Protocol.
+
+Copyright (c) Microsoft Corporation.
+SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Uefi.h>
+#include <Library/UefiLib.h>
+#include <Library/PrintLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UnitTestLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Protocol/VariablePolicy.h>
+#include <Library/VariablePolicyHelperLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+// TODO: Need to add to the UnitTestFrameworkPkg
+// #include <Library/UnitTestBootLib.h>
+
+#define UNIT_TEST_APP_NAME        "Variable Policy Unit Test Application"
+#define UNIT_TEST_APP_VERSION     "0.1"
+
+// TODO: Need to add to the UnitTestFrameworkPkg
+UNIT_TEST_FRAMEWORK_HANDLE
+GetActiveFrameworkHandle (
+  VOID
+  );
+
+EDKII_VARIABLE_POLICY_PROTOCOL  *mVarPol = NULL;
+
+
+EFI_GUID mTestNamespaceGuid1 = { 0x3b389299, 0xabaf, 0x433b, { 0xa4, 0xa9, 0x23, 0xc8, 0x44, 0x02, 0xfc, 0xad } };
+EFI_GUID mTestNamespaceGuid2 = { 0x4c49a3aa, 0xbcb0, 0x544c, { 0xb5, 0xba, 0x34, 0xd9, 0x55, 0x13, 0x0d, 0xbe } };
+EFI_GUID mTestNamespaceGuid3 = { 0x5d5ab4bb, 0xcdc1, 0x655d, { 0xc6, 0xcb, 0x45, 0xea, 0x66, 0x24, 0x1e, 0xcf } };
+
+/**
+  Prerequisite for most test cases.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+LocateVarPolicyPreReq (
+  IN UNIT_TEST_CONTEXT           Context
+  )
+{
+  EFI_STATUS Status;
+
+  if (mVarPol == NULL) {
+    Status = gBS->LocateProtocol (&gEdkiiVariablePolicyProtocolGuid,
+                                  NULL,
+                                  (VOID **) &mVarPol);
+    UT_ASSERT_NOT_EFI_ERROR (Status);
+    UT_ASSERT_NOT_NULL (mVarPol);
+  }
+
+  return UNIT_TEST_PASSED;
+
+} // LocateVarPolicyPreReq
+
+/**
+  Getting Started tests.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+CheckVpEnabled (
+  IN UNIT_TEST_CONTEXT           Context
+  )
+{
+  EFI_STATUS Status;
+  BOOLEAN State;
+
+  Status = mVarPol->IsVariablePolicyEnabled (&State);
+
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+  UT_ASSERT_EQUAL (State, TRUE);
+
+  return UNIT_TEST_PASSED;
+} // CheckVpEnabled
+
+UNIT_TEST_STATUS
+EFIAPI
+CheckVpRevision (
+  IN UNIT_TEST_CONTEXT           Context
+  )
+{
+  UT_ASSERT_NOT_EQUAL (mVarPol->Revision, 0);
+  UT_LOG_INFO ("VP Revision: 0x%x\n", mVarPol->Revision);
+
+  return UNIT_TEST_PASSED;
+} // CheckVpRevision
+
+/**
+  NoLock Policy tests.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+TestMinSizeNoLock (
+  IN UNIT_TEST_CONTEXT           Context
+  )
+{
+  EFI_STATUS Status;
+  UINT8      Value1;
+  UINT32     Value2;
+  UINT8     *Buffer;
+
+  Status = RegisterBasicVariablePolicy (mVarPol,
+                                        &mTestNamespaceGuid1,
+                                        L"MinSizeNoLockVar",
+                                        4,
+                                        VARIABLE_POLICY_NO_MAX_SIZE,
+                                        VARIABLE_POLICY_NO_MUST_ATTR,
+                                        VARIABLE_POLICY_NO_CANT_ATTR,
+                                        VARIABLE_POLICY_TYPE_NO_LOCK);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  //
+  // Try to write a var that is smaller than minsize
+  //
+  Value1 = 0x12;
+  Status = gRT->SetVariable (L"MinSizeNoLockVar",
+                             &mTestNamespaceGuid1,
+                             (EFI_VARIABLE_NON_VOLATILE  | EFI_VARIABLE_BOOTSERVICE_ACCESS),
+                             sizeof (Value1),
+                             &Value1);
+  UT_ASSERT_TRUE ((Status == EFI_WRITE_PROTECTED) || (Status == EFI_INVALID_PARAMETER));
+
+  //
+  // Try to write a var of size that matches minsize
+  //
+  Value2 = 0xa1b2c3d4;
+  Status = gRT->SetVariable (L"MinSizeNoLockVar",
+                             &mTestNamespaceGuid1,
+                             (EFI_VARIABLE_NON_VOLATILE  | EFI_VARIABLE_BOOTSERVICE_ACCESS),
+                             sizeof (Value2),
+                             &Value2);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  //
+  // Should be able to delete the var
+  //
+  Status = gRT->SetVariable (L"MinSizeNoLockVar",
+                             &mTestNamespaceGuid1,
+                             0,
+                             0,
+                             NULL);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  //
+  // Try to write a var of size larger than minsize
+  //
+  Buffer = AllocateZeroPool (40);
+  UT_ASSERT_NOT_NULL (Buffer);
+  Status = gRT->SetVariable (L"MinSizeNoLockVar",
+                             &mTestNamespaceGuid1,
+                             (EFI_VARIABLE_NON_VOLATILE  | EFI_VARIABLE_BOOTSERVICE_ACCESS),
+                             40,
+                             Buffer);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  //
+  // Delete the variable
+  //
+  Status = gRT->SetVariable (L"MinSizeNoLockVar",
+                             &mTestNamespaceGuid1,
+                             0,
+                             0,
+                             NULL);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  FreePool (Buffer);
+
+  return UNIT_TEST_PASSED;
+} // TestMinSizeNoLock
+
+UNIT_TEST_STATUS
+EFIAPI
+TestMaxSizeNoLock (
+  IN UNIT_TEST_CONTEXT           Context
+  )
+{
+  EFI_STATUS Status;
+  UINT8      Value1;
+  UINT32     Value2;
+  UINT8     *Buffer;
+
+  Status = RegisterBasicVariablePolicy (mVarPol,
+                                        &mTestNamespaceGuid1,
+                                        L"MaxSizeNoLockVar",
+                                        VARIABLE_POLICY_NO_MIN_SIZE,
+                                        4,
+                                        VARIABLE_POLICY_NO_MUST_ATTR,
+                                        VARIABLE_POLICY_NO_CANT_ATTR,
+                                        VARIABLE_POLICY_TYPE_NO_LOCK);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  //
+  // Try to write a var that is smaller than maxsize
+  //
+  Value1 = 0x34;
+  Status = gRT->SetVariable (L"MaxSizeNoLockVar",
+                             &mTestNamespaceGuid1,
+                             (EFI_VARIABLE_NON_VOLATILE  | EFI_VARIABLE_BOOTSERVICE_ACCESS),
+                             sizeof (Value1),
+                             &Value1);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  //
+  // Should be able to delete the var
+  //
+  Status = gRT->SetVariable (L"MaxSizeNoLockVar",
+                             &mTestNamespaceGuid1,
+                             0,
+                             0,
+                             NULL);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  //
+  // Try to write a var of size that matches maxsize
+  //
+  Value2 = 0xa1b2c3d4;
+  Status = gRT->SetVariable (L"MaxSizeNoLockVar",
+                             &mTestNamespaceGuid1,
+                             (EFI_VARIABLE_NON_VOLATILE  | EFI_VARIABLE_BOOTSERVICE_ACCESS),
+                             sizeof (Value2),
+                             &Value2);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  //
+  // Should be able to delete the var
+  //
+  Status = gRT->SetVariable (L"MaxSizeNoLockVar",
+                             &mTestNamespaceGuid1,
+                             0,
+                             0,
+                             NULL);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  //
+  // Try to write a var of size larger than maxsize
+  //
+  Buffer = AllocateZeroPool (40);
+  UT_ASSERT_NOT_NULL (Buffer);
+  Status = gRT->SetVariable (L"MaxSizeNoLockVar",
+                             &mTestNamespaceGuid1,
+                             (EFI_VARIABLE_NON_VOLATILE  | EFI_VARIABLE_BOOTSERVICE_ACCESS),
+                             40,
+                             Buffer);
+  UT_ASSERT_TRUE ((Status == EFI_WRITE_PROTECTED) || (Status == EFI_INVALID_PARAMETER));
+
+  FreePool (Buffer);
+
+  return UNIT_TEST_PASSED;
+} // TestMaxSizeNoLock
+
+UNIT_TEST_STATUS
+EFIAPI
+TestMustHaveAttrNoLock (
+  IN UNIT_TEST_CONTEXT           Context
+  )
+{
+  EFI_STATUS Status;
+  UINT8      Value;
+
+  Status = RegisterBasicVariablePolicy (mVarPol,
+                                        &mTestNamespaceGuid1,
+                                        L"MustHaveAttrNoLockVar",
+                                        VARIABLE_POLICY_NO_MIN_SIZE,
+                                        VARIABLE_POLICY_NO_MAX_SIZE,
+                                        (EFI_VARIABLE_NON_VOLATILE  | EFI_VARIABLE_BOOTSERVICE_ACCESS),
+                                        VARIABLE_POLICY_NO_CANT_ATTR,
+                                        VARIABLE_POLICY_TYPE_NO_LOCK);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  //
+  // Try to write a var that doesn't have the must-have attributes
+  //
+  Value = 0x56;
+  Status = gRT->SetVariable (L"MustHaveAttrNoLockVar",
+                             &mTestNamespaceGuid1,
+                             EFI_VARIABLE_BOOTSERVICE_ACCESS,
+                             sizeof (Value),
+                             &Value);
+  UT_ASSERT_TRUE ((Status == EFI_WRITE_PROTECTED) || (Status == EFI_INVALID_PARAMETER));
+
+  //
+  // Try to write a var that has exactly the required attributes
+  //
+  Status = gRT->SetVariable (L"MustHaveAttrNoLockVar",
+                             &mTestNamespaceGuid1,
+                             (EFI_VARIABLE_NON_VOLATILE  | EFI_VARIABLE_BOOTSERVICE_ACCESS),
+                             sizeof (Value),
+                             &Value);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  //
+  // Should be able to delete the var
+  // NOTE: some implementations of VP will require the musthave attributes to be passed even when deleting
+  //
+  Status = gRT->SetVariable (L"MustHaveAttrNoLockVar",
+                             &mTestNamespaceGuid1,
+                             0,
+                             0,
+                             NULL);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  //
+  // Try to write a var that has the required attributes and one extra attribute
+  //
+  Status = gRT->SetVariable (L"MustHaveAttrNoLockVar",
+                             &mTestNamespaceGuid1,
+                             (EFI_VARIABLE_NON_VOLATILE  | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS),
+                             sizeof (Value),
+                             &Value);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  //
+  // Should be able to delete the var
+  // NOTE: some implementations of VP will require the musthave attributes to be passed even when deleting
+  //
+  Status = gRT->SetVariable (L"MustHaveAttrNoLockVar",
+                             &mTestNamespaceGuid1,
+                             0,
+                             0,
+                             NULL);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+  return UNIT_TEST_PASSED;
+} // TestMustHaveAttrNoLock
+
+UNIT_TEST_STATUS
+EFIAPI
+TestCantHaveAttrNoLock (
+  IN UNIT_TEST_CONTEXT           Context
+  )
+{
+  EFI_STATUS Status;
+  UINT8      Value;
+
+  Status = RegisterBasicVariablePolicy (mVarPol,
+                                        &mTestNamespaceGuid1,
+                                        L"CantHaveAttrNoLockVar",
+                                        VARIABLE_POLICY_NO_MIN_SIZE,
+                                        VARIABLE_POLICY_NO_MAX_SIZE,
+                                        VARIABLE_POLICY_NO_MUST_ATTR,
+                                        EFI_VARIABLE_NON_VOLATILE,
+                                        VARIABLE_POLICY_TYPE_NO_LOCK);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  //
+  // Try to write a var that has a can't have attr
+  //
+  Value = 0x78;
+  Status = gRT->SetVariable (L"CantHaveAttrNoLockVar",
+                             &mTestNamespaceGuid1,
+                             (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE),
+                             sizeof (Value),
+                             &Value);
+  UT_ASSERT_TRUE ((Status == EFI_WRITE_PROTECTED) || (Status == EFI_INVALID_PARAMETER));
+
+  //
+  // Try to write a var that satisfies the can't have requirement
+  //
+  Status = gRT->SetVariable (L"CantHaveAttrNoLockVar",
+                             &mTestNamespaceGuid1,
+                             EFI_VARIABLE_BOOTSERVICE_ACCESS,
+                             sizeof (Value),
+                             &Value);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  //
+  // Should be able to delete the var
+  //
+  Status = gRT->SetVariable (L"CantHaveAttrNoLockVar",
+                             &mTestNamespaceGuid1,
+                             0,
+                             0,
+                             NULL);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  return UNIT_TEST_PASSED;
+} // TestCantHaveAttrNoLock
+
+UNIT_TEST_STATUS
+EFIAPI
+TestMaxSizeNamespaceNoLock (
+  IN UNIT_TEST_CONTEXT           Context
+  )
+{
+  EFI_STATUS Status;
+  UINT8      Value1;
+  UINT32     Value2;
+  UINT8     *Buffer;
+
+  //
+  // Register a namespace-wide policy limiting max size to 4 bytes
+  //
+  Status = RegisterBasicVariablePolicy (mVarPol,
+                                        &mTestNamespaceGuid2,
+                                        NULL,
+                                        VARIABLE_POLICY_NO_MIN_SIZE,
+                                        4,
+                                        VARIABLE_POLICY_NO_MUST_ATTR,
+                                        VARIABLE_POLICY_NO_CANT_ATTR,
+                                        VARIABLE_POLICY_TYPE_NO_LOCK);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  //
+  // Try to write a var that is smaller than maxsize
+  //
+  Value1 = 0x34;
+  Status = gRT->SetVariable (L"MaxSizeNoLockVar",
+                             &mTestNamespaceGuid2,
+                             (EFI_VARIABLE_NON_VOLATILE  | EFI_VARIABLE_BOOTSERVICE_ACCESS),
+                             sizeof (Value1),
+                             &Value1);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  //
+  // Should be able to delete the var
+  //
+  Status = gRT->SetVariable (L"MaxSizeNoLockVar",
+                             &mTestNamespaceGuid2,
+                             0,
+                             0,
+                             NULL);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  //
+  // Try to write a var of size that matches maxsize
+  //
+  Value2 = 0xa1b2c3d4;
+  Status = gRT->SetVariable (L"MaxSizeNoLockVar",
+                             &mTestNamespaceGuid2,
+                             (EFI_VARIABLE_NON_VOLATILE  | EFI_VARIABLE_BOOTSERVICE_ACCESS),
+                             sizeof (Value2),
+                             &Value2);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  //
+  // Should be able to delete the var
+  //
+  Status = gRT->SetVariable (L"MaxSizeNoLockVar",
+                             &mTestNamespaceGuid2,
+                             0,
+                             0,
+                             NULL);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  //
+  // Try to write a var of size larger than maxsize
+  //
+  Buffer = AllocateZeroPool (40);
+  UT_ASSERT_NOT_NULL (Buffer);
+  Status = gRT->SetVariable (L"MaxSizeNoLockVar",
+                             &mTestNamespaceGuid2,
+                             (EFI_VARIABLE_NON_VOLATILE  | EFI_VARIABLE_BOOTSERVICE_ACCESS),
+                             40,
+                             Buffer);
+  UT_ASSERT_TRUE ((Status == EFI_WRITE_PROTECTED) || (Status == EFI_INVALID_PARAMETER));
+
+  FreePool (Buffer);
+
+  return UNIT_TEST_PASSED;
+} // TestMaxSizeNamespaceNoLock
+
+UNIT_TEST_STATUS
+EFIAPI
+TestMustHaveAttrWildcardNoLock (
+  IN UNIT_TEST_CONTEXT           Context
+  )
+{
+  EFI_STATUS Status;
+  UINT8      Value;
+
+  Status = RegisterBasicVariablePolicy (mVarPol,
+                                        &mTestNamespaceGuid1,
+                                        L"MustHaveAttrWildcardNoLockVar####",
+                                        VARIABLE_POLICY_NO_MIN_SIZE,
+                                        VARIABLE_POLICY_NO_MAX_SIZE,
+                                        (EFI_VARIABLE_NON_VOLATILE  | EFI_VARIABLE_BOOTSERVICE_ACCESS),
+                                        VARIABLE_POLICY_NO_CANT_ATTR,
+                                        VARIABLE_POLICY_TYPE_NO_LOCK);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  //
+  // Try to write a var that doesn't have the must-have attributes
+  //
+  Value = 0x56;
+  Status = gRT->SetVariable (L"MustHaveAttrWildcardNoLockVar1573",
+                             &mTestNamespaceGuid1,
+                             EFI_VARIABLE_BOOTSERVICE_ACCESS,
+                             sizeof (Value),
+                             &Value);
+  UT_ASSERT_TRUE ((Status == EFI_WRITE_PROTECTED) || (Status == EFI_INVALID_PARAMETER));
+
+  //
+  // Try to write a var that has exactly the required attributes
+  //
+  Status = gRT->SetVariable (L"MustHaveAttrWildcardNoLockVar1234",
+                             &mTestNamespaceGuid1,
+                             (EFI_VARIABLE_NON_VOLATILE  | EFI_VARIABLE_BOOTSERVICE_ACCESS),
+                             sizeof (Value),
+                             &Value);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  //
+  // Should be able to delete the var
+  // NOTE: some implementations of VP will require the musthave attributes to be passed even when deleting
+  //
+  Status = gRT->SetVariable (L"MustHaveAttrWildcardNoLockVar1234",
+                             &mTestNamespaceGuid1,
+                             0,
+                             0,
+                             NULL);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  //
+  // Try to write a var that has the required attributes and one extra attribute
+  //
+  Status = gRT->SetVariable (L"MustHaveAttrWildcardNoLockVar5612",
+                             &mTestNamespaceGuid1,
+                             (EFI_VARIABLE_NON_VOLATILE  | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS),
+                             sizeof (Value),
+                             &Value);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  //
+  // Should be able to delete the var
+  // NOTE: some implementations of VP will require the musthave attributes to be passed even when deleting
+  //
+  Status = gRT->SetVariable (L"MustHaveAttrWildcardNoLockVar5612",
+                             &mTestNamespaceGuid1,
+                             0,
+                             0,
+                             NULL);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  return UNIT_TEST_PASSED;
+} // TestMustHaveAttrWildcardNoLock
+
+UNIT_TEST_STATUS
+EFIAPI
+TestPolicyprioritizationNoLock (
+  IN UNIT_TEST_CONTEXT           Context
+  )
+{
+  EFI_STATUS Status;
+  UINT8      Value8;
+  UINT16     Value16;
+  UINT32     Value32;
+  UINT64     Value64;
+
+  //
+  // Register a policy targeting the specific var
+  //
+  Status = RegisterBasicVariablePolicy (mVarPol,
+                                        &mTestNamespaceGuid3,
+                                        L"PolicyPriorityTestVar123",
+                                        8, // min size of UINT64
+                                        VARIABLE_POLICY_NO_MAX_SIZE,
+                                        VARIABLE_POLICY_NO_MUST_ATTR,
+                                        VARIABLE_POLICY_NO_CANT_ATTR,
+                                        VARIABLE_POLICY_TYPE_NO_LOCK);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  //
+  // Register a policy with wildcards in the name
+  //
+  Status = RegisterBasicVariablePolicy (mVarPol,
+                                        &mTestNamespaceGuid3,
+                                        L"PolicyPriorityTestVar###",
+                                        4, // min size of UINT32
+                                        VARIABLE_POLICY_NO_MAX_SIZE,
+                                        VARIABLE_POLICY_NO_MUST_ATTR,
+                                        VARIABLE_POLICY_NO_CANT_ATTR,
+                                        VARIABLE_POLICY_TYPE_NO_LOCK);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  //
+  // Register a policy with wildcards in the name
+  //
+  Status = RegisterBasicVariablePolicy (mVarPol,
+                                        &mTestNamespaceGuid3,
+                                        NULL,
+                                        2, // min size of UINT16
+                                        VARIABLE_POLICY_NO_MAX_SIZE,
+                                        VARIABLE_POLICY_NO_MUST_ATTR,
+                                        VARIABLE_POLICY_NO_CANT_ATTR,
+                                        VARIABLE_POLICY_TYPE_NO_LOCK);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  //
+  // The idea is that the most specific policy is applied:
+  //   For varname "TestVar", the namespace-wide one should apply: UINT16 minimum
+  //   For varname "PolicyPriorityTestVar567" the wildcard policy should apply: UINT32 minimum
+  //   For varname "PolicyPriorityTestVar123" the var-specific policy should apply: UINT64 minimum
+  //
+
+  //
+  // Let's confirm the namespace-wide policy enforcement
+  //
+  Value8 = 0x78;
+  Status = gRT->SetVariable (L"TestVar",
+                             &mTestNamespaceGuid3,
+                             (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE),
+                             sizeof (Value8),
+                             &Value8);
+  UT_ASSERT_TRUE ((Status == EFI_WRITE_PROTECTED) || (Status == EFI_INVALID_PARAMETER));
+
+  Value16 = 0x6543;
+  Status = gRT->SetVariable (L"TestVar",
+                             &mTestNamespaceGuid3,
+                             (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE),
+                             sizeof (Value16),
+                             &Value16);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  //
+  // Let's confirm the wildcard policy enforcement
+  //
+  Value16 = 0xabba;
+  Status = gRT->SetVariable (L"PolicyPriorityTestVar567",
+                             &mTestNamespaceGuid3,
+                             (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE),
+                             sizeof (Value16),
+                             &Value16);
+  UT_ASSERT_TRUE ((Status == EFI_WRITE_PROTECTED) || (Status == EFI_INVALID_PARAMETER));
+
+  Value32 = 0xfedcba98;
+  Status = gRT->SetVariable (L"PolicyPriorityTestVar567",
+                             &mTestNamespaceGuid3,
+                             (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE),
+                             sizeof (Value32),
+                             &Value32);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  //
+  // Let's confirm the var-specific policy enforcement
+  //
+  Value32 = 0x8d3f627c;
+  Status = gRT->SetVariable (L"PolicyPriorityTestVar123",
+                             &mTestNamespaceGuid3,
+                             (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE),
+                             sizeof (Value32),
+                             &Value32);
+  UT_ASSERT_TRUE ((Status == EFI_WRITE_PROTECTED) || (Status == EFI_INVALID_PARAMETER));
+
+  Value64 = 0xbebecdcdafaf6767;
+  Status = gRT->SetVariable (L"PolicyPriorityTestVar123",
+                             &mTestNamespaceGuid3,
+                             (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE),
+                             sizeof (Value64),
+                             &Value64);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  return UNIT_TEST_PASSED;
+} // TestPolicyprioritizationNoLock
+
+/**
+  LockNow Policy tests.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+TestExistingVarLockNow (
+  IN UNIT_TEST_CONTEXT           Context
+  )
+{
+  EFI_STATUS Status;
+  UINT8      Value;
+
+  //
+  // Write a var that we'll protect next
+  //
+  Value = 0x78;
+  Status = gRT->SetVariable (L"ExistingLockNowVar",
+                             &mTestNamespaceGuid1,
+                             (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE),
+                             sizeof (Value),
+                             &Value);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  //
+  // Register a LockNow policy targeting the var
+  //
+  Status = RegisterBasicVariablePolicy (mVarPol,
+                                        &mTestNamespaceGuid1,
+                                        L"ExistingLockNowVar",
+                                        VARIABLE_POLICY_NO_MIN_SIZE,
+                                        VARIABLE_POLICY_NO_MAX_SIZE,
+                                        VARIABLE_POLICY_NO_MUST_ATTR,
+                                        VARIABLE_POLICY_NO_CANT_ATTR,
+                                        VARIABLE_POLICY_TYPE_LOCK_NOW);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  //
+  // Attempt to modify the locked var
+  //
+  Value = 0xA5;
+  Status = gRT->SetVariable (L"ExistingLockNowVar",
+                             &mTestNamespaceGuid1,
+                             (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE),
+                             sizeof (Value),
+                             &Value);
+  UT_ASSERT_STATUS_EQUAL (Status, EFI_WRITE_PROTECTED);
+
+  //
+  // Attempt to delete the locked var
+  //
+  Status = gRT->SetVariable (L"ExistingLockNowVar",
+                             &mTestNamespaceGuid1,
+                             0,
+                             0,
+                             NULL);
+  UT_ASSERT_STATUS_EQUAL (Status, EFI_WRITE_PROTECTED);
+
+  //
+  // This variable is deleted in final cleanup.
+  //
+
+  return UNIT_TEST_PASSED;
+} // TestExistingVarLockNow
+
+UNIT_TEST_STATUS
+EFIAPI
+TestNonexistentVarLockNow (
+  IN UNIT_TEST_CONTEXT           Context
+  )
+{
+  EFI_STATUS Status;
+  UINT8      Value;
+  UINTN      Size;
+
+  //
+  // Make sure the variable we're about to create the policy for doesn't exist
+  //
+  Size = 0;
+  Status = gRT->GetVariable (L"NonexistentLockNowVar",
+                             &mTestNamespaceGuid1,
+                             NULL,
+                             &Size,
+                             NULL);
+  UT_ASSERT_STATUS_EQUAL (Status, EFI_NOT_FOUND);
+
+  //
+  // Register a LockNow policy targeting the var
+  //
+  Status = RegisterBasicVariablePolicy (mVarPol,
+                                        &mTestNamespaceGuid1,
+                                        L"NonexistentLockNowVar",
+                                        VARIABLE_POLICY_NO_MIN_SIZE,
+                                        VARIABLE_POLICY_NO_MAX_SIZE,
+                                        VARIABLE_POLICY_NO_MUST_ATTR,
+                                        VARIABLE_POLICY_NO_CANT_ATTR,
+                                        VARIABLE_POLICY_TYPE_LOCK_NOW);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  //
+  // Attempt to create the locked var
+  //
+  Value = 0xA5;
+  Status = gRT->SetVariable (L"NonexistentLockNowVar",
+                             &mTestNamespaceGuid1,
+                             (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE),
+                             sizeof (Value),
+                             &Value);
+  UT_ASSERT_STATUS_EQUAL (Status, EFI_WRITE_PROTECTED);
+
+  return UNIT_TEST_PASSED;
+} // TestNonexistentVarLockNow
+
+/**
+  LockOnCreate Policy tests.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+TestExistingVarLockOnCreate (
+  IN UNIT_TEST_CONTEXT           Context
+  )
+{
+  EFI_STATUS Status;
+  UINT8      Value;
+
+  //
+  // Write a var that we'll protect later
+  //
+  Value = 0x78;
+  Status = gRT->SetVariable (L"ExistingLockOnCreateVar",
+                             &mTestNamespaceGuid1,
+                             (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE),
+                             sizeof (Value),
+                             &Value);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  //
+  // Register a LockNow policy targeting the var
+  //
+  Status = RegisterBasicVariablePolicy (mVarPol,
+                                        &mTestNamespaceGuid1,
+                                        L"ExistingLockOnCreateVar",
+                                        VARIABLE_POLICY_NO_MIN_SIZE,
+                                        VARIABLE_POLICY_NO_MAX_SIZE,
+                                        VARIABLE_POLICY_NO_MUST_ATTR,
+                                        VARIABLE_POLICY_NO_CANT_ATTR,
+                                        VARIABLE_POLICY_TYPE_LOCK_ON_CREATE);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  //
+  // Attempt to modify the locked var
+  //
+  Value = 0xA5;
+  Status = gRT->SetVariable (L"ExistingLockOnCreateVar",
+                             &mTestNamespaceGuid1,
+                             (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE),
+                             sizeof (Value),
+                             &Value);
+  UT_ASSERT_STATUS_EQUAL (Status, EFI_WRITE_PROTECTED);
+
+  //
+  // Attempt to delete the locked var
+  //
+  Status = gRT->SetVariable (L"ExistingLockOnCreateVar",
+                             &mTestNamespaceGuid1,
+                             0,
+                             0,
+                             NULL);
+  UT_ASSERT_STATUS_EQUAL (Status, EFI_WRITE_PROTECTED);
+
+  //
+  // This variable is deleted in final cleanup.
+  //
+
+  return UNIT_TEST_PASSED;
+} // TestExistingVarLockOnCreate
+
+UNIT_TEST_STATUS
+EFIAPI
+TestNonexistentVarLockOnCreate (
+  IN UNIT_TEST_CONTEXT           Context
+  )
+{
+  EFI_STATUS Status;
+  UINT8      Value1;
+  UINT32     Value2;
+  UINTN      Size;
+
+  //
+  // Make sure the variable we're about to create the policy for doesn't exist
+  //
+  Size = 0;
+  Status = gRT->GetVariable (L"NonexistentLockOnCreateVar",
+                             &mTestNamespaceGuid1,
+                             NULL,
+                             &Size,
+                             NULL);
+  UT_ASSERT_STATUS_EQUAL (Status, EFI_NOT_FOUND);
+
+  //
+  // Register a LockOnCreate policy targeting the var
+  //
+  Status = RegisterBasicVariablePolicy (mVarPol,
+                                        &mTestNamespaceGuid1,
+                                        L"NonexistentLockOnCreateVar",
+                                        2, // min size of 2 bytes, UINT16+
+                                        VARIABLE_POLICY_NO_MAX_SIZE,
+                                        EFI_VARIABLE_RUNTIME_ACCESS, // must have RT attr
+                                        VARIABLE_POLICY_NO_CANT_ATTR,
+                                        VARIABLE_POLICY_TYPE_LOCK_ON_CREATE);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  //
+  // Attempt to create the var, but smaller than min size
+  //
+  Value1 = 0xA5;
+  Status = gRT->SetVariable (L"NonexistentLockOnCreateVar",
+                             &mTestNamespaceGuid1,
+                             (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE),
+                             sizeof (Value1),
+                             &Value1);
+  UT_ASSERT_TRUE ((Status == EFI_WRITE_PROTECTED) || (Status == EFI_INVALID_PARAMETER));
+
+  //
+  // Now let's make sure attribute req is enforced
+  //
+  Value2 = 0x43218765;
+  Status = gRT->SetVariable (L"NonexistentLockOnCreateVar",
+                             &mTestNamespaceGuid1,
+                             (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE),
+                             sizeof (Value2),
+                             &Value2);
+  UT_ASSERT_TRUE ((Status == EFI_WRITE_PROTECTED) || (Status == EFI_INVALID_PARAMETER));
+
+  //
+  // Now let's create a valid variable
+  //
+  Value2 = 0x43218765;
+  Status = gRT->SetVariable (L"NonexistentLockOnCreateVar",
+                             &mTestNamespaceGuid1,
+                             (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE),
+                             sizeof (Value2),
+                             &Value2);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  //
+  // Let's make sure we can't modify it
+  //
+  Value2 = 0xa5a5b6b6;
+  Status = gRT->SetVariable (L"NonexistentLockOnCreateVar",
+                             &mTestNamespaceGuid1,
+                             (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE),
+                             sizeof (Value2),
+                             &Value2);
+  UT_ASSERT_STATUS_EQUAL (Status, EFI_WRITE_PROTECTED);
+
+  //
+  // Finally, let's make sure we can't delete it
+  //
+  Status = gRT->SetVariable (L"NonexistentLockOnCreateVar",
+                             &mTestNamespaceGuid1,
+                             0,
+                             0,
+                             NULL);
+  UT_ASSERT_STATUS_EQUAL (Status, EFI_WRITE_PROTECTED);
+
+  //
+  // This variable is deleted in final cleanup.
+  //
+
+  return UNIT_TEST_PASSED;
+} // TestNonexistentVarLockOnCreate
+
+/**
+  LockOnVarState Policy tests.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+TestLockOnVarStateBeforeCreate (
+  IN UNIT_TEST_CONTEXT           Context
+  )
+{
+  EFI_STATUS Status;
+  UINTN      Size;
+  UINT8      Value;
+
+  //
+  // First of all, let's make sure the var we're trying to protect doesn't exist
+  //
+  Size = 0;
+  Status = gRT->GetVariable (L"NonexistentLockOnVarStateVar",
+                             &mTestNamespaceGuid1,
+                             NULL,
+                             &Size,
+                             NULL);
+  UT_ASSERT_STATUS_EQUAL (Status, EFI_NOT_FOUND);
+
+  //
+  // Good, now let's create a policy
+  //
+  Status = RegisterVarStateVariablePolicy (mVarPol,
+                                           &mTestNamespaceGuid1,
+                                           L"NonexistentLockOnVarStateVar",
+                                           VARIABLE_POLICY_NO_MIN_SIZE,
+                                           VARIABLE_POLICY_NO_MAX_SIZE,
+                                           VARIABLE_POLICY_NO_MUST_ATTR,
+                                           VARIABLE_POLICY_NO_CANT_ATTR,
+                                           &mTestNamespaceGuid1,
+                                           L"Trigger1",
+                                           0x7E);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  //
+  // Now we write the trigger var
+  //
+  Value = 0x7E;
+  Status = gRT->SetVariable (L"Trigger1",
+                             &mTestNamespaceGuid1,
+                             (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE),
+                             sizeof (Value),
+                             &Value);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  //
+  // Ok, now we attempt to write a var protected by the trigger
+  //
+  Value = 0xFA;
+  Status = gRT->SetVariable (L"NonexistentLockOnVarStateVar",
+                             &mTestNamespaceGuid1,
+                             (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE),
+                             sizeof (Value),
+                             &Value);
+  UT_ASSERT_STATUS_EQUAL (Status, EFI_WRITE_PROTECTED);
+
+  //
+  // Let's modify the trigger var and "untrigger" the policy
+  //
+  Value = 0x38;
+  Status = gRT->SetVariable (L"Trigger1",
+                             &mTestNamespaceGuid1,
+                             (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE),
+                             sizeof (Value),
+                             &Value);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  //
+  // Now we should be able to create the var targeted by the policy
+  //
+  Value = 0x23;
+  Status = gRT->SetVariable (L"NonexistentLockOnVarStateVar",
+                             &mTestNamespaceGuid1,
+                             (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE),
+                             sizeof (Value),
+                             &Value);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  //
+  // Cleanup: delete the trigger and the protected var
+  //
+  Status = gRT->SetVariable (L"Trigger1",
+                             &mTestNamespaceGuid1,
+                             0,
+                             0,
+                             NULL);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  Status = gRT->SetVariable (L"NonexistentLockOnVarStateVar",
+                             &mTestNamespaceGuid1,
+                             0,
+                             0,
+                             NULL);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  return UNIT_TEST_PASSED;
+} // TestLockOnVarStateBeforeCreate
+
+UNIT_TEST_STATUS
+EFIAPI
+TestLockOnVarStateAfterCreate (
+  IN UNIT_TEST_CONTEXT           Context
+  )
+{
+  EFI_STATUS Status;
+  UINT8      Value;
+
+  //
+  // Let's create a policy
+  //
+  Status = RegisterVarStateVariablePolicy (mVarPol,
+                                           &mTestNamespaceGuid1,
+                                           L"ExistingLockOnVarStateVar",
+                                           VARIABLE_POLICY_NO_MIN_SIZE,
+                                           VARIABLE_POLICY_NO_MAX_SIZE,
+                                           VARIABLE_POLICY_NO_MUST_ATTR,
+                                           VARIABLE_POLICY_NO_CANT_ATTR,
+                                           &mTestNamespaceGuid1,
+                                           L"Trigger2",
+                                           0x5C);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  //
+  // Should be able to write targeted var since the policy isn't active yet.
+  //
+  Value = 0x17;
+  Status = gRT->SetVariable (L"ExistingLockOnVarStateVar",
+                             &mTestNamespaceGuid1,
+                             (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE),
+                             sizeof (Value),
+                             &Value);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  //
+  // Let's modify the var to make sure the policy isn't acting like a lock-on-create one
+  //
+  Value = 0x30;
+  Status = gRT->SetVariable (L"ExistingLockOnVarStateVar",
+                             &mTestNamespaceGuid1,
+                             (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE),
+                             sizeof (Value),
+                             &Value);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  //
+  // Now we trigger the policy
+  //
+  Value = 0x5C;
+  Status = gRT->SetVariable (L"Trigger2",
+                             &mTestNamespaceGuid1,
+                             (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE),
+                             sizeof (Value),
+                             &Value);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  //
+  // Let's now verify the variable is protected
+  //
+  Value = 0xB9;
+  Status = gRT->SetVariable (L"ExistingLockOnVarStateVar",
+                             &mTestNamespaceGuid1,
+                             (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE),
+                             sizeof (Value),
+                             &Value);
+  UT_ASSERT_STATUS_EQUAL (Status, EFI_WRITE_PROTECTED);
+
+  //
+  // Ok, to clean up, we need to remove the trigger var, so delete it, and then delete the target var
+  //
+  Status = gRT->SetVariable (L"Trigger2",
+                             &mTestNamespaceGuid1,
+                             0,
+                             0,
+                             NULL);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  Status = gRT->SetVariable (L"ExistingLockOnVarStateVar",
+                             &mTestNamespaceGuid1,
+                             0,
+                             0,
+                             NULL);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  return UNIT_TEST_PASSED;
+} // TestLockOnVarStateAfterCreate
+
+UNIT_TEST_STATUS
+EFIAPI
+TestLockOnVarStateInvalidLargeTrigger (
+  IN UNIT_TEST_CONTEXT           Context
+  )
+{
+  EFI_STATUS Status;
+  UINT16     Value;
+
+  //
+  // First let's create a variable policy
+  //
+  Status = RegisterVarStateVariablePolicy (mVarPol,
+                                           &mTestNamespaceGuid1,
+                                           L"InvalidLargeTriggerLockOnVarStateVar",
+                                           VARIABLE_POLICY_NO_MIN_SIZE,
+                                           VARIABLE_POLICY_NO_MAX_SIZE,
+                                           VARIABLE_POLICY_NO_MUST_ATTR,
+                                           VARIABLE_POLICY_NO_CANT_ATTR,
+                                           &mTestNamespaceGuid1,
+                                           L"Trigger3",
+                                           0x5C);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  //
+  // Now attempt to trigger the lock but with a variable larger than one byte
+  //
+  Value = 0x8085;
+  Status = gRT->SetVariable (L"Trigger3",
+                             &mTestNamespaceGuid1,
+                             (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE),
+                             sizeof (Value),
+                             &Value);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  //
+  // Should still be able to create the targeted var
+  //
+  Value = 0x1234;
+  Status = gRT->SetVariable (L"InvalidLargeTriggerLockOnVarStateVar",
+                             &mTestNamespaceGuid1,
+                             (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE),
+                             sizeof (Value),
+                             &Value);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  //
+  // Let's clean up by deleting the invalid trigger and the targeted var
+  //
+  Status = gRT->SetVariable (L"Trigger3",
+                             &mTestNamespaceGuid1,
+                             0,
+                             0,
+                             NULL);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  Status = gRT->SetVariable (L"InvalidLargeTriggerLockOnVarStateVar",
+                             &mTestNamespaceGuid1,
+                             0,
+                             0,
+                             NULL);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  return UNIT_TEST_PASSED;
+} // TestLockOnVarStateInvalidLargeTrigger
+
+UNIT_TEST_STATUS
+EFIAPI
+TestLockOnVarStateWrongValueTrigger (
+  IN UNIT_TEST_CONTEXT           Context
+  )
+{
+  EFI_STATUS Status;
+  UINT8      Value;
+
+  //
+  // First let's create a variable policy
+  //
+  Status = RegisterVarStateVariablePolicy (mVarPol,
+                                           &mTestNamespaceGuid1,
+                                           L"WrongValueTriggerLockOnVarStateVar",
+                                           VARIABLE_POLICY_NO_MIN_SIZE,
+                                           VARIABLE_POLICY_NO_MAX_SIZE,
+                                           VARIABLE_POLICY_NO_MUST_ATTR,
+                                           VARIABLE_POLICY_NO_CANT_ATTR,
+                                           &mTestNamespaceGuid1,
+                                           L"Trigger4",
+                                           0xCA);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  //
+  // Now attempt to trigger the lock but with a wrong value
+  //
+  Value = 0x80;
+  Status = gRT->SetVariable (L"Trigger4",
+                             &mTestNamespaceGuid1,
+                             (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE),
+                             sizeof (Value),
+                             &Value);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  //
+  // Should still be able to create the targeted var
+  //
+  Value = 0x14;
+  Status = gRT->SetVariable (L"WrongValueTriggerLockOnVarStateVar",
+                             &mTestNamespaceGuid1,
+                             (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE),
+                             sizeof (Value),
+                             &Value);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  //
+  // Let's clean up by deleting the invalid trigger and the targeted var
+  //
+  Status = gRT->SetVariable (L"Trigger4",
+                             &mTestNamespaceGuid1,
+                             0,
+                             0,
+                             NULL);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  Status = gRT->SetVariable (L"WrongValueTriggerLockOnVarStateVar",
+                             &mTestNamespaceGuid1,
+                             0,
+                             0,
+                             NULL);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  return UNIT_TEST_PASSED;
+} // TestLockOnVarStateWrongValueTrigger
+
+/**
+  Invalid policy tests.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+TestInvalidAttributesPolicy (
+  IN UNIT_TEST_CONTEXT           Context
+  )
+{
+  EFI_STATUS Status;
+
+  //
+  // The only must/can't have attributes supported by VPE are NV, BS, and RT. They are 1, 2, and 4, respectively.
+  // Let's try some bits higher than that?
+  //
+
+  //
+  // Trying must have attribute 0x8 which is EFI_VARIABLE_HARDWARE_ERROR_RECORD
+  //
+  Status = RegisterBasicVariablePolicy (mVarPol,
+                                        &mTestNamespaceGuid1,
+                                        L"InvalidMustHaveAttributesPolicyVar1",
+                                        VARIABLE_POLICY_NO_MIN_SIZE,
+                                        VARIABLE_POLICY_NO_MAX_SIZE,
+                                        EFI_VARIABLE_HARDWARE_ERROR_RECORD,
+                                        VARIABLE_POLICY_NO_CANT_ATTR,
+                                        VARIABLE_POLICY_TYPE_NO_LOCK);
+  UT_LOG_INFO ("Setting must have attr to EFI_VARIABLE_HARDWARE_ERROR_RECORD returned %r\n", Status);
+
+  //
+  // Let's try 0x10 - EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS, a deprecated attribute
+  //
+  Status = RegisterBasicVariablePolicy (mVarPol,
+                                        &mTestNamespaceGuid1,
+                                        L"InvalidMustHaveAttributesPolicyVar2",
+                                        VARIABLE_POLICY_NO_MIN_SIZE,
+                                        VARIABLE_POLICY_NO_MAX_SIZE,
+                                        EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS,
+                                        VARIABLE_POLICY_NO_CANT_ATTR,
+                                        VARIABLE_POLICY_TYPE_NO_LOCK);
+  UT_LOG_INFO ("Setting must have attr to EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS returned %r\n", Status);
+
+  //
+  // Let's try 0x20 - EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
+  //
+  Status = RegisterBasicVariablePolicy (mVarPol,
+                                        &mTestNamespaceGuid1,
+                                        L"InvalidMustHaveAttributesPolicyVar3",
+                                        VARIABLE_POLICY_NO_MIN_SIZE,
+                                        VARIABLE_POLICY_NO_MAX_SIZE,
+                                        EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS,
+                                        VARIABLE_POLICY_NO_CANT_ATTR,
+                                        VARIABLE_POLICY_TYPE_NO_LOCK);
+  UT_LOG_INFO ("Setting must have attr to EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS returned %r\n", Status);
+
+  //
+  // Let's try something wild, like 0x4000
+  //
+  Status = RegisterBasicVariablePolicy (mVarPol,
+                                        &mTestNamespaceGuid1,
+                                        L"InvalidMustHaveAttributesPolicyVar4",
+                                        VARIABLE_POLICY_NO_MIN_SIZE,
+                                        VARIABLE_POLICY_NO_MAX_SIZE,
+                                        0x4000,
+                                        VARIABLE_POLICY_NO_CANT_ATTR,
+                                        VARIABLE_POLICY_TYPE_NO_LOCK);
+  UT_LOG_INFO ("Setting must have attr to 0x4000 returned %r\n", Status);
+
+  //
+  // Now repeat the same tests, but for the can't-have param
+  //
+  Status = RegisterBasicVariablePolicy (mVarPol,
+                                        &mTestNamespaceGuid1,
+                                        L"InvalidCantHaveAttributesPolicyVar1",
+                                        VARIABLE_POLICY_NO_MIN_SIZE,
+                                        VARIABLE_POLICY_NO_MAX_SIZE,
+                                        VARIABLE_POLICY_NO_MUST_ATTR,
+                                        EFI_VARIABLE_HARDWARE_ERROR_RECORD,
+                                        VARIABLE_POLICY_TYPE_NO_LOCK);
+  UT_LOG_INFO ("Setting cant have attr to EFI_VARIABLE_HARDWARE_ERROR_RECORD returned %r\n", Status);
+
+  Status = RegisterBasicVariablePolicy (mVarPol,
+                                        &mTestNamespaceGuid1,
+                                        L"InvalidCantHaveAttributesPolicyVar2",
+                                        VARIABLE_POLICY_NO_MIN_SIZE,
+                                        VARIABLE_POLICY_NO_MAX_SIZE,
+                                        VARIABLE_POLICY_NO_MUST_ATTR,
+                                        EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS,
+                                        VARIABLE_POLICY_TYPE_NO_LOCK);
+  UT_LOG_INFO ("Setting cant have attr to EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS returned %r\n", Status);
+
+  Status = RegisterBasicVariablePolicy (mVarPol,
+                                        &mTestNamespaceGuid1,
+                                        L"InvalidCantHaveAttributesPolicyVar3",
+                                        VARIABLE_POLICY_NO_MIN_SIZE,
+                                        VARIABLE_POLICY_NO_MAX_SIZE,
+                                        VARIABLE_POLICY_NO_MUST_ATTR,
+                                        EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS,
+                                        VARIABLE_POLICY_TYPE_NO_LOCK);
+  UT_LOG_INFO ("Setting cant have attr to EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS returned %r\n", Status);
+
+  Status = RegisterBasicVariablePolicy (mVarPol,
+                                        &mTestNamespaceGuid1,
+                                        L"InvalidCantHaveAttributesPolicyVar4",
+                                        VARIABLE_POLICY_NO_MIN_SIZE,
+                                        VARIABLE_POLICY_NO_MAX_SIZE,
+                                        VARIABLE_POLICY_NO_MUST_ATTR,
+                                        0x4000,
+                                        VARIABLE_POLICY_TYPE_NO_LOCK);
+  UT_LOG_INFO ("Setting cant have attr to 0x4000 returned %r\n", Status);
+
+  return UNIT_TEST_PASSED;
+} // TestInvalidAttributesPolicy
+
+UNIT_TEST_STATUS
+EFIAPI
+TestLargeMinSizePolicy (
+  IN UNIT_TEST_CONTEXT           Context
+  )
+{
+  EFI_STATUS Status;
+
+  //
+  // Let's set the min size to 2GB and see what happens
+  //
+  Status = RegisterBasicVariablePolicy (mVarPol,
+                                        &mTestNamespaceGuid1,
+                                        L"LargeMinSizeInvalidPolicyVar",
+                                        0x80000000,
+                                        VARIABLE_POLICY_NO_MAX_SIZE,
+                                        VARIABLE_POLICY_NO_MUST_ATTR,
+                                        VARIABLE_POLICY_NO_CANT_ATTR,
+                                        VARIABLE_POLICY_TYPE_NO_LOCK);
+
+  UT_LOG_INFO ("Setting min size to 0x80000000 returned %r\n", Status);
+
+  return UNIT_TEST_PASSED;
+} // TestLargeMinSizePolicy
+
+UNIT_TEST_STATUS
+EFIAPI
+TestZeroMaxSizePolicy (
+  IN UNIT_TEST_CONTEXT           Context
+  )
+{
+  EFI_STATUS Status;
+
+  //
+  // Let's set the max size to 0 and see what happens
+  //
+  Status = RegisterBasicVariablePolicy (mVarPol,
+                                        &mTestNamespaceGuid1,
+                                        L"ZeroMinSizeInvalidPolicyVar",
+                                        VARIABLE_POLICY_NO_MIN_SIZE,
+                                        0,
+                                        VARIABLE_POLICY_NO_MUST_ATTR,
+                                        VARIABLE_POLICY_NO_CANT_ATTR,
+                                        VARIABLE_POLICY_TYPE_NO_LOCK);
+  //UT_ASSERT_NOT_EQUAL (Status, EFI_SUCCESS); // this fails on QC. Real bug? Do we care?
+  UT_LOG_INFO ("Setting max size to 0 returned %r\n", Status);
+
+  return UNIT_TEST_PASSED;
+} // TestZeroMaxSizePolicy
+
+UNIT_TEST_STATUS
+EFIAPI
+TestInvalidPolicyTypePolicy (
+  IN UNIT_TEST_CONTEXT           Context
+  )
+{
+  EFI_STATUS Status;
+
+  //
+  // Let's set policy type to an invalid value and see what happens
+  // Valid ones are:
+  //        VARIABLE_POLICY_TYPE_NO_LOCK            0
+  //        VARIABLE_POLICY_TYPE_LOCK_NOW           1
+  //        VARIABLE_POLICY_TYPE_LOCK_ON_CREATE     2
+  //        VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE  3
+  //
+  Status = RegisterBasicVariablePolicy (mVarPol,
+                                        &mTestNamespaceGuid1,
+                                        L"InvalidPolicyTypePolicyVar",
+                                        VARIABLE_POLICY_NO_MIN_SIZE,
+                                        VARIABLE_POLICY_NO_MAX_SIZE,
+                                        VARIABLE_POLICY_NO_MUST_ATTR,
+                                        VARIABLE_POLICY_NO_CANT_ATTR,
+                                        4);
+  UT_ASSERT_NOT_EQUAL (Status, EFI_SUCCESS);
+
+  Status = RegisterBasicVariablePolicy (mVarPol,
+                                        &mTestNamespaceGuid1,
+                                        L"InvalidPolicyTypePolicyVar",
+                                        VARIABLE_POLICY_NO_MIN_SIZE,
+                                        VARIABLE_POLICY_NO_MAX_SIZE,
+                                        VARIABLE_POLICY_NO_MUST_ATTR,
+                                        VARIABLE_POLICY_NO_CANT_ATTR,
+                                        147);
+  UT_ASSERT_NOT_EQUAL (Status, EFI_SUCCESS);
+
+  return UNIT_TEST_PASSED;
+} // TestInvalidPolicyTypePolicy
+
+/**
+  Test dumping policy.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+TestDumpPolicy (
+  IN UNIT_TEST_CONTEXT           Context
+  )
+{
+  EFI_STATUS Status;
+  UINT8*     Buffer;
+  UINT32     Size;
+
+  //
+  // First let's call DumpVariablePolicy with null buffer to get size
+  //
+  Size = 0;
+  Status = mVarPol->DumpVariablePolicy (NULL, &Size);
+  UT_ASSERT_STATUS_EQUAL (Status, EFI_BUFFER_TOO_SMALL);
+
+  //
+  // Now we allocate the buffer for the dump
+  //
+  Buffer = NULL;
+  Buffer = AllocatePool (Size);
+  UT_ASSERT_NOT_NULL (Buffer);
+
+  //
+  // Now we get the dump. In this test we will not analyze the dump.
+  //
+  Status = mVarPol->DumpVariablePolicy (Buffer, &Size);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  return UNIT_TEST_PASSED;
+} // TestDumpPolicy
+
+/**
+  Test policy version.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+TestPolicyVersion (
+  IN UNIT_TEST_CONTEXT           Context
+  )
+{
+  EFI_STATUS             Status;
+  VARIABLE_POLICY_ENTRY  *NewEntry;
+
+  //
+  // Create the new entry using a helper lib
+  //
+  NewEntry = NULL;
+  Status = CreateBasicVariablePolicy (&mTestNamespaceGuid1,
+                                      L"PolicyVersionTestNoLockVar",
+                                      VARIABLE_POLICY_NO_MIN_SIZE,
+                                      4, // max size of 4 bytes
+                                      VARIABLE_POLICY_NO_MUST_ATTR,
+                                      VARIABLE_POLICY_NO_CANT_ATTR,
+                                      VARIABLE_POLICY_TYPE_NO_LOCK,
+                                      &NewEntry);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  NewEntry->Version = 0x1234;
+  Status = mVarPol->RegisterVariablePolicy (NewEntry);
+  UT_LOG_INFO ("Registering policy entry with an unknown version status: %r\n", Status);
+
+  FreePool (NewEntry);
+
+  return UNIT_TEST_PASSED;
+} // TestPolicyVersion
+
+/**
+  Lock Policy Tests.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+LockPolicyEngineTests (
+  IN UNIT_TEST_CONTEXT           Context
+  )
+{
+  EFI_STATUS  Status;
+  UINT16      Value;
+  UINT64      Value64;
+  BOOLEAN     State;
+
+  //
+  // First let's register a policy that we'll test after VPE lock
+  //
+  Status = RegisterBasicVariablePolicy (mVarPol,
+                                        &mTestNamespaceGuid1,
+                                        L"BeforeVpeLockNoLockPolicyVar",
+                                        VARIABLE_POLICY_NO_MIN_SIZE,
+                                        4, // max size of 4 bytes
+                                        VARIABLE_POLICY_NO_MUST_ATTR,
+                                        VARIABLE_POLICY_NO_CANT_ATTR,
+                                        VARIABLE_POLICY_TYPE_LOCK_ON_CREATE);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  //
+  // Now, lock VPE!
+  //
+  Status = mVarPol->LockVariablePolicy ();
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  //
+  // See if we can lock it again?
+  //
+  Status = mVarPol->LockVariablePolicy ();
+  UT_LOG_INFO ("Locking VPE for second time returned %r\n", Status);
+
+  //
+  // Let's confirm one of the policies from prior test suites is still enforced
+  // Attempt to delete a locked var
+  //
+  Status = gRT->SetVariable (L"ExistingLockNowVar",
+                             &mTestNamespaceGuid1,
+                             0,
+                             0,
+                             NULL);
+  UT_ASSERT_STATUS_EQUAL (Status, EFI_WRITE_PROTECTED);
+
+  //
+  // We'll make sure the policy from earlier in this test case is actively filtering out by size
+  //
+  Value64 = 0x3829fed212345678;
+  Status = gRT->SetVariable (L"BeforeVpeLockNoLockPolicyVar",
+                             &mTestNamespaceGuid1,
+                             (EFI_VARIABLE_NON_VOLATILE  | EFI_VARIABLE_BOOTSERVICE_ACCESS),
+                             sizeof (Value64),
+                             &Value64);
+  UT_ASSERT_TRUE ((Status == EFI_WRITE_PROTECTED) || (Status == EFI_INVALID_PARAMETER));
+
+  //
+  // Let's create the variable from the policy now
+  //
+  Value = 0x323f;
+  Status = gRT->SetVariable (L"BeforeVpeLockNoLockPolicyVar",
+                             &mTestNamespaceGuid1,
+                             (EFI_VARIABLE_NON_VOLATILE  | EFI_VARIABLE_BOOTSERVICE_ACCESS),
+                             sizeof (Value),
+                             &Value);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  //
+  // Now confirm that the var is locked after creation
+  //
+  Value = 0x1212;
+  Status = gRT->SetVariable (L"BeforeVpeLockNoLockPolicyVar",
+                             &mTestNamespaceGuid1,
+                             (EFI_VARIABLE_NON_VOLATILE  | EFI_VARIABLE_BOOTSERVICE_ACCESS),
+                             sizeof (Value),
+                             &Value);
+  UT_ASSERT_STATUS_EQUAL (Status, EFI_WRITE_PROTECTED);
+
+  //
+  // Let's attempt to register a new policy, it should fail
+  //
+  Status = RegisterBasicVariablePolicy (mVarPol,
+                                        &mTestNamespaceGuid1,
+                                        L"AfterVpeLockNowPolicyVar",
+                                        VARIABLE_POLICY_NO_MIN_SIZE,
+                                        VARIABLE_POLICY_NO_MAX_SIZE,
+                                        VARIABLE_POLICY_NO_MUST_ATTR,
+                                        VARIABLE_POLICY_NO_CANT_ATTR,
+                                        VARIABLE_POLICY_TYPE_LOCK_NOW);
+  UT_ASSERT_NOT_EQUAL (Status, EFI_SUCCESS);
+
+  //
+  // Make sure VPE is enabled
+  //
+  Status = mVarPol->IsVariablePolicyEnabled (&State);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+  UT_ASSERT_EQUAL (State, TRUE);
+
+  //
+  // Finally, make sure we can't disable VPE
+  //
+  Status = mVarPol->DisableVariablePolicy ();
+  UT_ASSERT_NOT_EQUAL (Status, EFI_SUCCESS);
+
+  return UNIT_TEST_PASSED;
+} // LockPolicyEngineTests
+
+/**
+  Save context and reboot after the lock policy test suite.
+**/
+STATIC
+VOID
+EFIAPI
+SaveContextAndReboot (
+  IN UNIT_TEST_CONTEXT           Context
+  )
+{
+  EFI_STATUS Status;
+
+  //
+  // Now, save all the data associated with this framework.
+  // TODO: Need to add to the UnitTestFrameworkPkg
+  Status = SaveFrameworkState( NULL, 0 );
+
+  //
+  // If we're all good, let's book...
+  if (!EFI_ERROR( Status ))
+  {
+    //
+    // Next, we want to update the BootNext variable to USB
+    // so that we have a fighting chance of coming back here.
+    //
+    // TODO: Need to add to the UnitTestFrameworkPkg
+    // SetBootNextDevice();
+
+    //
+    // Reset
+    DEBUG(( DEBUG_INFO, "%a - Rebooting! Launch this test again once booted.\n", __FUNCTION__ ));
+    gRT->ResetSystem( EfiResetCold, EFI_SUCCESS, 0, NULL );
+    DEBUG(( DEBUG_ERROR, "%a - Unit test failed to quit! Framework can no longer be used!\n", __FUNCTION__ ));
+
+    //
+    // We REALLY shouldn't be here.
+    Status = EFI_ABORTED;
+  }
+
+  return;
+} // SaveContextAndReboot
+
+/**
+  Disable policy tests.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+DisablePolicyEngineTests (
+  IN UNIT_TEST_CONTEXT           Context
+  )
+{
+  EFI_STATUS  Status;
+  BOOLEAN     State;
+  UINT8       Value;
+
+  //
+  // First, we disable the variable policy
+  //
+  Status = mVarPol->DisableVariablePolicy ();
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  //
+  // Confirm it's disabled
+  //
+  Status = mVarPol->IsVariablePolicyEnabled (&State);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+  UT_ASSERT_EQUAL (State, FALSE);
+
+  //
+  // Try locking it?
+  //
+  Status = mVarPol->LockVariablePolicy ();
+  UT_LOG_INFO ("Locking VP after disabling it status: %r\n", Status);
+
+  //
+  // Try modifying the var from TestExistingVarLockNow
+  //
+  Value = 0xB5;
+  Status = gRT->SetVariable (L"ExistingLockNowVar",
+                             &mTestNamespaceGuid1,
+                             (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE),
+                             sizeof (Value),
+                             &Value);
+  UT_ASSERT_NOT_EFI_ERROR (Status);
+
+  return UNIT_TEST_PASSED;
+} // DisablePolicyEngineTests
+
+/**
+  Final Cleanup: delete some variables earlier test cases created.
+**/
+STATIC
+VOID
+EFIAPI
+FinalCleanup (
+  IN UNIT_TEST_CONTEXT           Context
+  )
+{
+  EFI_STATUS Status;
+
+  Status = gRT->SetVariable (L"ExistingLockNowVar",
+                             &mTestNamespaceGuid1,
+                             0,
+                             0,
+                             NULL);
+  UT_LOG_INFO ("Delete ExistingLockNowVar status: %r\n", Status);
+
+  Status = gRT->SetVariable (L"ExistingLockOnCreateVar",
+                             &mTestNamespaceGuid1,
+                             0,
+                             0,
+                             NULL);
+  UT_LOG_INFO ("Delete ExistingLockOnCreateVar status: %r\n", Status);
+
+  Status = gRT->SetVariable (L"NonexistentLockOnCreateVar",
+                             &mTestNamespaceGuid1,
+                             0,
+                             0,
+                             NULL);
+  UT_LOG_INFO ("Delete NonexistentLockOnCreateVar status: %r\n", Status);
+
+  Status = gRT->SetVariable (L"NonexistentLockNowVar",
+                             &mTestNamespaceGuid1,
+                             0,
+                             0,
+                             NULL);
+  UT_LOG_INFO ("Delete NonexistentLockNowVar status: %r\n", Status);
+
+  Status = gRT->SetVariable (L"CantHaveAttrNoLockVar",
+                             &mTestNamespaceGuid1,
+                             0,
+                             0,
+                             NULL);
+  UT_LOG_INFO ("Delete CantHaveAttrNoLockVar status: %r\n", Status);
+
+  Status = gRT->SetVariable (L"NonexistentLockOnVarStateVar",
+                             &mTestNamespaceGuid1,
+                             0,
+                             0,
+                             NULL);
+  UT_LOG_INFO ("Delete NonexistentLockOnVarStateVar status: %r\n", Status);
+
+  Status = gRT->SetVariable (L"ExistingLockOnVarStateVar",
+                             &mTestNamespaceGuid1,
+                             0,
+                             0,
+                             NULL);
+  UT_LOG_INFO ("Delete ExistingLockOnVarStateVar status: %r\n", Status);
+} // FinalCleanup
+
+/**
+
+  Main fuction sets up the unit test environment.
+
+**/
+EFI_STATUS
+EFIAPI
+UefiMain (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE* SystemTable)
+{
+  EFI_STATUS                  Status;
+  UNIT_TEST_FRAMEWORK_HANDLE  Framework;
+  UNIT_TEST_SUITE_HANDLE      GettingStartedTestSuite;
+  UNIT_TEST_SUITE_HANDLE      NoLockPoliciesTestSuite;
+  UNIT_TEST_SUITE_HANDLE      LockNowPoliciesTestSuite;
+  UNIT_TEST_SUITE_HANDLE      LockOnCreatePoliciesTestSuite;
+  UNIT_TEST_SUITE_HANDLE      LockOnVarStatePoliciesTestSuite;
+  UNIT_TEST_SUITE_HANDLE      InvalidPoliciesTestSuite;
+  UNIT_TEST_SUITE_HANDLE      DumpPolicyTestSuite;
+  UNIT_TEST_SUITE_HANDLE      PolicyVersionTestSuite;
+  UNIT_TEST_SUITE_HANDLE      LockPolicyTestSuite;
+  UNIT_TEST_SUITE_HANDLE      DisablePolicyTestSuite;
+
+  Framework = NULL;
+  GettingStartedTestSuite = NULL;
+  NoLockPoliciesTestSuite = NULL;
+  LockNowPoliciesTestSuite = NULL;
+  LockOnCreatePoliciesTestSuite = NULL;
+  LockOnVarStatePoliciesTestSuite = NULL;
+  InvalidPoliciesTestSuite = NULL;
+  DumpPolicyTestSuite = NULL;
+  PolicyVersionTestSuite = NULL;
+  LockPolicyTestSuite = NULL;
+  DisablePolicyTestSuite = NULL;
+
+  DEBUG ((DEBUG_INFO, "%a v%a\n", UNIT_TEST_APP_NAME, UNIT_TEST_APP_VERSION));
+
+  //
+  // Start setting up the test framework for running the tests.
+  //
+  Status = InitUnitTestFramework (&Framework, UNIT_TEST_APP_NAME, gEfiCallerBaseName, UNIT_TEST_APP_VERSION);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Failed in InitUnitTestFramework. Status = %r\n", Status));
+    goto EXIT;
+  }
+
+  //
+  // Test suite 1: Getting Started. Get VP protocol, check state, log revision
+  //
+  Status = CreateUnitTestSuite (&GettingStartedTestSuite, Framework, "Getting Started", "Common.VP.GettingStarted", NULL, NULL);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for the Getting Started Test Suite\n"));
+    Status = EFI_OUT_OF_RESOURCES;
+    goto EXIT;
+  }
+  AddTestCase (GettingStartedTestSuite, "Confirm VP is enabled", "Common.VP.GettingStarted.CheckVpEnabled", CheckVpEnabled, LocateVarPolicyPreReq, NULL, NULL);
+  AddTestCase (GettingStartedTestSuite, "Check VP revision", "Common.VP.GettingStarted.CheckVpRevision", CheckVpRevision, LocateVarPolicyPreReq, NULL, NULL);
+
+  //
+  // Test suite 2: Test NoLock Policies
+  //
+  Status = CreateUnitTestSuite (&NoLockPoliciesTestSuite, Framework, "Exercise NoLock Policies", "Common.VP.NoLockPolicies", NULL, NULL);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for the NoLock Policies Test Suite\n"));
+    Status = EFI_OUT_OF_RESOURCES;
+    goto EXIT;
+  }
+  AddTestCase (NoLockPoliciesTestSuite, "Test Min Size enforcement in NoLock policy", "Common.VP.NoLockPolicies.TestMinSizeNoLock", TestMinSizeNoLock, LocateVarPolicyPreReq, NULL, NULL);
+  AddTestCase (NoLockPoliciesTestSuite, "Test Max Size enforcement in NoLock policy", "Common.VP.NoLockPolicies.TestMaxSizeNoLock", TestMaxSizeNoLock, LocateVarPolicyPreReq, NULL, NULL);
+  AddTestCase (NoLockPoliciesTestSuite, "Test Must Have Attribute enforcement in NoLock policy", "Common.VP.NoLockPolicies.TestMustHaveAttrNoLock", TestMustHaveAttrNoLock, LocateVarPolicyPreReq, NULL, NULL);
+  AddTestCase (NoLockPoliciesTestSuite, "Test Can't Have Attribute enforcement in NoLock policy", "Common.VP.NoLockPolicies.TestCantHaveAttrNoLock", TestCantHaveAttrNoLock, LocateVarPolicyPreReq, NULL, NULL);
+  AddTestCase (NoLockPoliciesTestSuite, "Test Max Size enforcement in NoLock policy for entire namespace", "Common.VP.NoLockPolicies.TestMaxSizeNamespaceNoLock", TestMaxSizeNamespaceNoLock, LocateVarPolicyPreReq, NULL, NULL);
+  AddTestCase (NoLockPoliciesTestSuite, "Test Must Have Attribute enforcement in NoLock policy with wildcards", "Common.VP.NoLockPolicies.TestMustHaveAttrWildcardNoLock", TestMustHaveAttrWildcardNoLock, LocateVarPolicyPreReq, NULL, NULL);
+  AddTestCase (NoLockPoliciesTestSuite, "Test policy prioritization between namespace-wide, wildcard, and var-specific policies", "Common.VP.NoLockPolicies.TestPolicyprioritizationNoLock", TestPolicyprioritizationNoLock, LocateVarPolicyPreReq, NULL, NULL);
+
+  //
+  // Test suite 3: Test LockNow policies
+  //
+  Status = CreateUnitTestSuite (&LockNowPoliciesTestSuite, Framework, "Exercise LockNow Policies", "Common.VP.LockNowPolicies", NULL, NULL);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for the LockNow Policies Test Suite\n"));
+    Status = EFI_OUT_OF_RESOURCES;
+    goto EXIT;
+  }
+  AddTestCase (LockNowPoliciesTestSuite, "Test LockNow policy for a pre-existing variable", "Common.VP.LockNowPolicies.TestExistingVarLockNow", TestExistingVarLockNow, LocateVarPolicyPreReq, NULL, NULL);
+  AddTestCase (LockNowPoliciesTestSuite, "Test LockNow policy for a nonexistent variable", "Common.VP.LockNowPolicies.TestNonexistentVarLockNow", TestNonexistentVarLockNow, LocateVarPolicyPreReq, NULL, NULL);
+
+  //
+  // Test suite 4: Test LockOnCreate policies
+  //
+  Status = CreateUnitTestSuite (&LockOnCreatePoliciesTestSuite, Framework, "Exercise LockOnCreate Policies", "Common.VP.LockOnCreate", NULL, NULL);
+  if (EFI_ERROR (Status))
+  {
+    DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for the LockOnCreate Policies Test Suite\n"));
+    Status = EFI_OUT_OF_RESOURCES;
+    goto EXIT;
+  }
+  AddTestCase (LockOnCreatePoliciesTestSuite, "Test LockOnCreate policy for a pre-existing variable", "Common.VP.LockOnCreate.TestExistingVarLockOnCreate", TestExistingVarLockOnCreate, LocateVarPolicyPreReq, NULL, NULL);
+  AddTestCase (LockOnCreatePoliciesTestSuite, "Test LockOnCreate policy for a nonexistent variable", "Common.VP.LockOnCreate.TestNonexistentVarLockOnCreate", TestNonexistentVarLockOnCreate, LocateVarPolicyPreReq, NULL, NULL);
+
+  //
+  // Test suite 5: Test LockOnVarState policies
+  //
+  Status = CreateUnitTestSuite (&LockOnVarStatePoliciesTestSuite, Framework, "Exercise LockOnVarState Policies", "Common.VP.LockOnVarState", NULL, NULL);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for the LockOnVarState Policies Test Suite\n"));
+    Status = EFI_OUT_OF_RESOURCES;
+    goto EXIT;
+  }
+  AddTestCase (LockOnVarStatePoliciesTestSuite, "Test LockOnVarState policy for a nonexistent variable", "Common.VP.LockOnVarState.TestLockOnVarStateBeforeCreate", TestLockOnVarStateBeforeCreate, LocateVarPolicyPreReq, NULL, NULL);
+  AddTestCase (LockOnVarStatePoliciesTestSuite, "Test LockOnVarState policy for a pre-existing variable", "Common.VP.LockOnVarState.TestLockOnVarStateAfterCreate", TestLockOnVarStateAfterCreate, LocateVarPolicyPreReq, NULL, NULL);
+  AddTestCase (LockOnVarStatePoliciesTestSuite, "Test LockOnVarState policy triggered by invalid-size variable", "Common.VP.LockOnVarState.TestLockOnVarStateInvalidLargeTrigger", TestLockOnVarStateInvalidLargeTrigger, LocateVarPolicyPreReq, NULL, NULL);
+  AddTestCase (LockOnVarStatePoliciesTestSuite, "Test LockOnVarState policy triggered by invalid-value variable", "Common.VP.LockOnVarState.TestLockOnVarStateWrongValueTrigger", TestLockOnVarStateWrongValueTrigger, LocateVarPolicyPreReq, NULL, NULL);
+
+  //
+  // Test suite 6: Test registering invalid policies
+  //
+  Status = CreateUnitTestSuite (&InvalidPoliciesTestSuite, Framework, "Attempt registering invalid policies", "Common.VP.InvalidPolicies", NULL, NULL);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for the Invalid Policies Test Suite\n"));
+    Status = EFI_OUT_OF_RESOURCES;
+    goto EXIT;
+  }
+  AddTestCase (InvalidPoliciesTestSuite, "Test policy with invalid must-have attributes", "Common.VP.InvalidPolicies.TestInvalidAttributesPolicy", TestInvalidAttributesPolicy, LocateVarPolicyPreReq, NULL, NULL);
+  AddTestCase (InvalidPoliciesTestSuite, "Test policy with invalid attributes", "Common.VP.InvalidPolicies.TestLargeMinSizePolicy", TestLargeMinSizePolicy, LocateVarPolicyPreReq, NULL, NULL);
+  AddTestCase (InvalidPoliciesTestSuite, "Test policy with invalid attributes", "Common.VP.InvalidPolicies.TestZeroMaxSizePolicy", TestZeroMaxSizePolicy, LocateVarPolicyPreReq, NULL, NULL);
+  AddTestCase (InvalidPoliciesTestSuite, "Test policy with invalid type", "Common.VP.InvalidPolicies.TestInvalidPolicyTypePolicy", TestInvalidPolicyTypePolicy, LocateVarPolicyPreReq, NULL, NULL);
+
+  //
+  // Test suite 7: Test dumping the policy
+  //
+  Status = CreateUnitTestSuite (&DumpPolicyTestSuite, Framework, "Attempt dumping policy", "Common.VP.DumpPolicy", NULL, NULL);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for the Dump Policy Test Suite\n"));
+    Status = EFI_OUT_OF_RESOURCES;
+    goto EXIT;
+  }
+  AddTestCase (DumpPolicyTestSuite, "Test dumping policy", "Common.VP.DumpPolicy.TestDumpPolicy", TestDumpPolicy, LocateVarPolicyPreReq, NULL, NULL);
+
+  //
+  // Test suite 8: Test policy version
+  //
+  Status = CreateUnitTestSuite (&PolicyVersionTestSuite, Framework, "Use non-zero policy version", "Common.VP.PolicyVersion", NULL, NULL);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for the Policy Version Test Suite\n"));
+    Status = EFI_OUT_OF_RESOURCES;
+    goto EXIT;
+  }
+  AddTestCase (PolicyVersionTestSuite, "Test policy version", "Common.VP.DumpPolicy.TestPolicyVersion", TestPolicyVersion, LocateVarPolicyPreReq, NULL, NULL);
+
+  //
+  // Test suite 9: Lock VPE and test implications
+  //
+  Status = CreateUnitTestSuite (&LockPolicyTestSuite, Framework, "Lock policy, test it", "Common.VP.LockPolicyTests", NULL, NULL);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for the Lock Policy Test Suite\n"));
+    Status = EFI_OUT_OF_RESOURCES;
+    goto EXIT;
+  }
+  AddTestCase (LockPolicyTestSuite, "Test locking policy", "Common.VP.LockPolicyTests.LockPolicyEngineTests", LockPolicyEngineTests, LocateVarPolicyPreReq, NULL, NULL);
+  AddTestCase (LockPolicyTestSuite, "Test locking policy", "Common.VP.LockPolicyTests.LockPolicyEngineTests", LockPolicyEngineTests, LocateVarPolicyPreReq, SaveContextAndReboot, NULL);
+
+  //
+  // Test suite 10: Disable var policy and confirm expected behavior
+  //
+  Status = CreateUnitTestSuite (&DisablePolicyTestSuite, Framework, "Disable policy, test it", "Common.VP.DisablePolicyTests", NULL, NULL);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for the Disable Policy Test Suite\n"));
+    Status = EFI_OUT_OF_RESOURCES;
+    goto EXIT;
+  }
+  AddTestCase (DisablePolicyTestSuite, "Confirm VP is enabled", "Common.VP.DisablePolicyTests.CheckVpEnabled", CheckVpEnabled, LocateVarPolicyPreReq, NULL, NULL);
+  AddTestCase (DisablePolicyTestSuite, "Test LockNow policy for a pre-existing variable", "Common.VP.DisablePolicyTests.TestExistingVarLockNow", TestExistingVarLockNow, LocateVarPolicyPreReq, NULL, NULL);
+  AddTestCase (DisablePolicyTestSuite, "Test disabling policy", "Common.VP.DisablePolicyTests.DisablePolicyEngineTests", DisablePolicyEngineTests, LocateVarPolicyPreReq, FinalCleanup, NULL);
+
+  //
+  // Execute the tests.
+  //
+  Status = RunAllTestSuites (Framework);
+
+EXIT:
+  if (Framework != NULL) {
+    FreeUnitTestFramework (Framework);
+  }
+
+  return Status;
+} // UefiMain
diff --git a/MdeModulePkg/MdeModulePkg.ci.yaml b/MdeModulePkg/MdeModulePkg.ci.yaml
index 1cfc1328390e..88a192d0e2a8 100644
--- a/MdeModulePkg/MdeModulePkg.ci.yaml
+++ b/MdeModulePkg/MdeModulePkg.ci.yaml
@@ -35,7 +35,9 @@
             "UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec"
         ],
         # For UEFI shell based apps
-        "AcceptableDependencies-UEFI_APPLICATION":[],
+        "AcceptableDependencies-UEFI_APPLICATION":[
+            "UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec"
+        ],
         "IgnoreInf": []
     },
 
diff --git a/MdeModulePkg/MdeModulePkg.dsc b/MdeModulePkg/MdeModulePkg.dsc
index f0a75a3b337b..414a6c62dfdb 100644
--- a/MdeModulePkg/MdeModulePkg.dsc
+++ b/MdeModulePkg/MdeModulePkg.dsc
@@ -19,6 +19,8 @@ [Defines]
   BUILD_TARGETS                  = DEBUG|RELEASE|NOOPT
   SKUID_IDENTIFIER               = DEFAULT
 
+!include UnitTestFrameworkPkg/UnitTestFrameworkPkgTarget.dsc.inc
+
 [LibraryClasses]
   #
   # Entry point
@@ -314,6 +316,10 @@ [Components]
   MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf
   MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf
   MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.inf
+  MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/VariablePolicyFuncTestApp.inf {
+    <LibraryClasses>
+      UnitTestBootLib|UnitTestFrameworkPkg/Library/UnitTestBootLibNull/UnitTestBootLibNull.inf
+  }
   MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf
   MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLib.inf
   MdeModulePkg/Library/VarCheckPcdLib/VarCheckPcdLib.inf
diff --git a/MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/Readme.md b/MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/Readme.md
new file mode 100644
index 000000000000..804ad4173a5f
--- /dev/null
+++ b/MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/Readme.md
@@ -0,0 +1,55 @@
+# variable Policy Unit Tests
+
+## &#x1F539; Copyright
+Copyright (C) Microsoft Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+## About This Test
+This test verifies functionality of the Variable Policy Protocol by registering various variable policies and exercising them, as well as tests locking the policy, disabling it, and dumping the policy entries.
+
+Only policies that are created as a part of this test will be tested.
+1. Try getting test context, if empty then get VP protocol, confirm that VP is not disabled by calling IsVariablePolicyEnabled. Log VP revision.
+2. "No lock" policies:
+    * check minsize enforcement
+    * check maxsize enforcement
+    * check musthave attr enforcement
+    * check canthave attr enforcement
+    * check one of the above with empty string policy i.e. name wildcard
+    * check another one of the above with a "#" containing policy string
+    * check policy prioritization by having a namespace-wide policy, a policy with a # wildcard, and a one-var specific policy and testing which one is enforced
+3. "Lock now" policies (means if the var doesn't exist, it won't be created; if one exists, it can't be updated):
+    * test a policy for an already existing variable, verify we can't write into that variable
+    * create a policy for a non-existing variable and attempt to register such var
+4. "Lock on create" policies (means the var can still be created, but no updates later, existing vars can't be updated):
+    * create a var, lock it with LockOnCreate, attempt to update its contents
+    * create LockOnCreate VP, attempt to create var with invalid size, then invalid attr, then create valid var, attempt to update its contents
+5. "Lock on var state" policies (means the var protected by this policy can't be created or updated once the trigger is set)
+    * create VP, trigger lock with a valid var, attempt to create a locked var, then modify the trigger var, create locked var
+    * create VP, create targeted var, modify it, trigger lock, attempt to modify var
+    * create VP, trigger lock with invalid (larger than one byte) var, see if VPE allows creation of the locked var (it should allow)
+    * create VP, set locking var with wrong value, see if VPE allows creation of the locked var (should allow)
+6. Attempt registering invalid policy entries
+    * invalid required and banned attributes
+    * large min size - let's say 2GB
+    * max size equal to 0
+    * invalid policy type
+7. Exercise dumping policy. No need to check the validity of the dump blob.
+8. Test registering a policy with a random version.
+9. Lock VPE, make sure old policies are enforced, new ones can't be registered.
+    * Register a LockOnCreate policy
+    * Lock VPE
+    * Test locking it again.
+    * Verify one of the prior policies is enforced
+    * Make sure we can create variables even if those are protected by LockOnCreate policy, after locking the VPE
+    * Attempt to register new policies
+    * Make sure can't disable VPE
+    * Cleanup: save context and reboot
+10. Disable variable policy and try some things
+    * Locate Variable Policy Protocol
+    * Make sure VP is enabled
+    * Register a policy
+    * Disable VPE
+    * Call IsVariablePolicyEnabled to confirm it's disabled.
+    * Make sure can't lock policy
+    * Make sure the policy from a is no longer enforced
+    * Final cleanup: delete vars that were created in some earlier test suites
diff --git a/MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/VariablePolicyFuncTestApp.inf b/MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/VariablePolicyFuncTestApp.inf
new file mode 100644
index 000000000000..9ad277a547c2
--- /dev/null
+++ b/MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/VariablePolicyFuncTestApp.inf
@@ -0,0 +1,42 @@
+## @file
+# Uefi Shell based Application that unit tests the Variable Policy Protocol
+#
+# Copyright (c) Microsoft Corporation.
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = VariablePolicyFuncTestApp
+  FILE_GUID                      = B653C4C3-3FCC-4B6C-8051-5F692AEAECBA
+  MODULE_TYPE                    = UEFI_APPLICATION
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = UefiMain
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = X64 AARCH64
+#
+
+[Sources]
+  VariablePolicyFuncTestApp.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
+
+[LibraryClasses]
+  UefiApplicationEntryPoint
+  BaseLib
+  UnitTestLib
+  UnitTestBootLib
+  PrintLib
+  UefiBootServicesTableLib
+  UefiRuntimeServicesTableLib
+  MemoryAllocationLib
+  VariablePolicyHelperLib
+
+[Protocols]
+  gEdkiiVariablePolicyProtocolGuid
-- 
2.26.2.windows.1.8.g01c50adf56.20200515075929


^ permalink raw reply related	[flat|nested] 48+ messages in thread

* Re: [PATCH v6 08/14] UefiPayloadPkg: Add VariablePolicy engine to UefiPayloadPkg platform
  2020-06-23  6:40 ` [PATCH v6 08/14] UefiPayloadPkg: Add VariablePolicy engine to UefiPayloadPkg platform Bret Barkelew
@ 2020-06-23 16:45   ` Ma, Maurice
  0 siblings, 0 replies; 48+ messages in thread
From: Ma, Maurice @ 2020-06-23 16:45 UTC (permalink / raw)
  To: Bret Barkelew, devel@edk2.groups.io; +Cc: Dong, Guo, You, Benjamin

Reviewed-by: Maurice Ma <maurice.ma@intel.com>


> -----Original Message-----
> From: Bret Barkelew <bret@corthon.com>
> Sent: Monday, June 22, 2020 23:41
> To: devel@edk2.groups.io
> Cc: Ma, Maurice <maurice.ma@intel.com>; Dong, Guo <guo.dong@intel.com>;
> You, Benjamin <benjamin.you@intel.com>
> Subject: [PATCH v6 08/14] UefiPayloadPkg: Add VariablePolicy engine to
> UefiPayloadPkg platform
> 
> https://bugzilla.tianocore.org/show_bug.cgi?id=2522
> 
> Cc: Maurice Ma <maurice.ma@intel.com>
> Cc: Guo Dong <guo.dong@intel.com>
> Cc: Benjamin You <benjamin.you@intel.com>
> Cc: Bret Barkelew <brbarkel@microsoft.com>
> Signed-off-by: Bret Barkelew <brbarkel@microsoft.com>
> Reviewed-by: Maurice Ma <maurice.ma@intel.com>
> ---
>  UefiPayloadPkg/UefiPayloadPkgIa32.dsc    | 4 ++++
>  UefiPayloadPkg/UefiPayloadPkgIa32X64.dsc | 4 ++++
>  2 files changed, 8 insertions(+)
> 
> diff --git a/UefiPayloadPkg/UefiPayloadPkgIa32.dsc
> b/UefiPayloadPkg/UefiPayloadPkgIa32.dsc
> index c6c47833871b..4bed6aaa78d0 100644
> --- a/UefiPayloadPkg/UefiPayloadPkgIa32.dsc
> +++ b/UefiPayloadPkg/UefiPayloadPkgIa32.dsc
> @@ -4,6 +4,7 @@
>  # Provides drivers and definitions to create uefi payload for bootloaders.
> 
>  #
> 
>  # Copyright (c) 2014 - 2020, Intel Corporation. All rights reserved.<BR>
> 
> +# Copyright (c) Microsoft Corporation.
> 
>  # SPDX-License-Identifier: BSD-2-Clause-Patent
> 
>  #
> 
>  ##
> 
> @@ -204,6 +205,8 @@ [LibraryClasses]
> 
> AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLib
> Null.inf
> 
> 
> TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmM
> easurementLibNull.inf
> 
>    VarCheckLib|MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf
> 
> +
> VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.i
> nf
> 
> +
> VariablePolicyHelperLib|MdeModulePkg/Library/VariablePolicyHelperLib/Varia
> blePolicyHelperLib.inf
> 
> 
> 
>  [LibraryClasses.IA32.SEC]
> 
>    DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
> 
> @@ -251,6 +254,7 @@ [LibraryClasses.common.DXE_RUNTIME_DRIVER]
>    HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
> 
> 
> MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemory
> AllocationLib.inf
> 
> 
> ReportStatusCodeLib|MdeModulePkg/Library/RuntimeDxeReportStatusCodeLib
> /RuntimeDxeReportStatusCodeLib.inf
> 
> +
> VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibR
> untimeDxe.inf
> 
> 
> 
> 
> [LibraryClasses.common.UEFI_DRIVER,LibraryClasses.common.UEFI_APPLICATI
> ON]
> 
>    PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
> 
> diff --git a/UefiPayloadPkg/UefiPayloadPkgIa32X64.dsc
> b/UefiPayloadPkg/UefiPayloadPkgIa32X64.dsc
> index 5559b1258521..6e07dd866acd 100644
> --- a/UefiPayloadPkg/UefiPayloadPkgIa32X64.dsc
> +++ b/UefiPayloadPkg/UefiPayloadPkgIa32X64.dsc
> @@ -4,6 +4,7 @@
>  # Provides drivers and definitions to create uefi payload for bootloaders.
> 
>  #
> 
>  # Copyright (c) 2014 - 2020, Intel Corporation. All rights reserved.<BR>
> 
> +# Copyright (c) Microsoft Corporation.
> 
>  # SPDX-License-Identifier: BSD-2-Clause-Patent
> 
>  #
> 
>  ##
> 
> @@ -205,6 +206,8 @@ [LibraryClasses]
> 
> AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLib
> Null.inf
> 
> 
> TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmM
> easurementLibNull.inf
> 
>    VarCheckLib|MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf
> 
> +
> VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.i
> nf
> 
> +
> VariablePolicyHelperLib|MdeModulePkg/Library/VariablePolicyHelperLib/Varia
> blePolicyHelperLib.inf
> 
> 
> 
>  [LibraryClasses.IA32.SEC]
> 
>    DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
> 
> @@ -252,6 +255,7 @@ [LibraryClasses.common.DXE_RUNTIME_DRIVER]
>    HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
> 
> 
> MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemory
> AllocationLib.inf
> 
> 
> ReportStatusCodeLib|MdeModulePkg/Library/RuntimeDxeReportStatusCodeLib
> /RuntimeDxeReportStatusCodeLib.inf
> 
> +
> VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibR
> untimeDxe.inf
> 
> 
> 
> 
> [LibraryClasses.common.UEFI_DRIVER,LibraryClasses.common.UEFI_APPLICATI
> ON]
> 
>    PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
> 
> --
> 2.26.2.windows.1.8.g01c50adf56.20200515075929


^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [edk2-devel] [PATCH v6 13/14] MdeModulePkg: Drop VarLock from RuntimeDxe variable driver
  2020-06-23  6:41 ` [PATCH v6 13/14] MdeModulePkg: Drop VarLock from RuntimeDxe variable driver Bret Barkelew
@ 2020-07-02  2:13   ` Dandan Bi
  2020-07-02  6:36     ` Bret Barkelew
  0 siblings, 1 reply; 48+ messages in thread
From: Dandan Bi @ 2020-07-02  2:13 UTC (permalink / raw)
  To: devel@edk2.groups.io, bret@corthon.com
  Cc: Wang, Jian J, Wu, Hao A, Gao, Liming

1 comment inline, please check.


Thanks,
Dandan
> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Bret
> Barkelew
> Sent: Tuesday, June 23, 2020 2:41 PM
> To: devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>;
> Gao, Liming <liming.gao@intel.com>
> Subject: [edk2-devel] [PATCH v6 13/14] MdeModulePkg: Drop VarLock from
> RuntimeDxe variable driver
> 
> https://bugzilla.tianocore.org/show_bug.cgi?id=2522
> 
> Now that everything should be moved to
> VariablePolicy, drop support for the
> deprecated VarLock SMI interface and
> associated functions from variable RuntimeDxe.
> 
> Cc: Jian J Wang <jian.j.wang@intel.com>
> Cc: Hao A Wu <hao.a.wu@intel.com>
> Cc: Liming Gao <liming.gao@intel.com>
> Cc: Bret Barkelew <brbarkel@microsoft.com>
> Signed-off-by: Bret Barkelew <brbarkel@microsoft.com>
> ---
>  MdeModulePkg/Universal/Variable/RuntimeDxe/VarCheck.c                 | 49 +-
> ------------
> 
> MdeModulePkg/Universal/Variable/RuntimeDxe/VariableLockRequstToLock
> .c | 71 ++++++++++++++++++++
>  MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
> |  1 +
>  MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf            |  1
> +
> 
> MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf
> |  1 +
>  5 files changed, 75 insertions(+), 48 deletions(-)
> 
> diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VarCheck.c
> b/MdeModulePkg/Universal/Variable/RuntimeDxe/VarCheck.c
> index f15219df5eb8..486d85b022e1 100644
> --- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VarCheck.c
> +++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VarCheck.c
> @@ -3,60 +3,13 @@
>    and variable lock protocol based on VarCheckLib.
> 
> 
> 
>  Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
> 
> +Copyright (c) Microsoft Corporation.
> 
>  SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> 
> 
>  **/
> 
> 
> 
>  #include "Variable.h"
> 
> 
> 
> -/**
> 
> -  Mark a variable that will become read-only after leaving the DXE phase of
> execution.
> 
> -  Write request coming from SMM environment through
> EFI_SMM_VARIABLE_PROTOCOL is allowed.
> 
> -
> 
> -  @param[in] This          The VARIABLE_LOCK_PROTOCOL instance.
> 
> -  @param[in] VariableName  A pointer to the variable name that will be
> made read-only subsequently.
> 
> -  @param[in] VendorGuid    A pointer to the vendor GUID that will be made
> read-only subsequently.
> 
> -
> 
> -  @retval EFI_SUCCESS           The variable specified by the VariableName and
> the VendorGuid was marked
> 
> -                                as pending to be read-only.
> 
> -  @retval EFI_INVALID_PARAMETER VariableName or VendorGuid is NULL.
> 
> -                                Or VariableName is an empty string.
> 
> -  @retval EFI_ACCESS_DENIED     EFI_END_OF_DXE_EVENT_GROUP_GUID
> or EFI_EVENT_GROUP_READY_TO_BOOT has
> 
> -                                already been signaled.
> 
> -  @retval EFI_OUT_OF_RESOURCES  There is not enough resource to hold
> the lock request.
> 
> -**/
> 
> -EFI_STATUS
> 
> -EFIAPI
> 
> -VariableLockRequestToLock (
> 
> -  IN CONST EDKII_VARIABLE_LOCK_PROTOCOL *This,
> 
> -  IN       CHAR16                       *VariableName,
> 
> -  IN       EFI_GUID                     *VendorGuid
> 
> -  )
> 
> -{
> 
> -  EFI_STATUS                    Status;
> 
> -  VAR_CHECK_VARIABLE_PROPERTY   Property;
> 
> -
> 
> -  AcquireLockOnlyAtBootTime (&mVariableModuleGlobal-
> >VariableGlobal.VariableServicesLock);
> 
> -
> 
> -  Status = VarCheckLibVariablePropertyGet (VariableName, VendorGuid,
> &Property);
> 
> -  if (!EFI_ERROR (Status)) {
> 
> -    Property.Property |= VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY;
> 
> -  } else {
> 
> -    Property.Revision = VAR_CHECK_VARIABLE_PROPERTY_REVISION;
> 
> -    Property.Property = VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY;
> 
> -    Property.Attributes = 0;
> 
> -    Property.MinSize = 1;
> 
> -    Property.MaxSize = MAX_UINTN;
> 
> -  }
> 
> -  Status = VarCheckLibVariablePropertySet (VariableName, VendorGuid,
> &Property);
> 
> -
> 
> -  DEBUG ((EFI_D_INFO, "[Variable] Lock: %g:%s %r\n", VendorGuid,
> VariableName, Status));
> 
> -
> 
> -  ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal-
> >VariableGlobal.VariableServicesLock);
> 
> -
> 
> -  return Status;
> 
> -}
> 
> -
> 
>  /**
> 
>    Register SetVariable check handler.
> 
> 
> 
> diff --git
> a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableLockRequstToLo
> ck.c
> b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableLockRequstToLo
> ck.c
> new file mode 100644
> index 000000000000..1f7f0b7ef06c
> --- /dev/null
> +++
> b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableLockRequstToLo
> ck.c
> @@ -0,0 +1,71 @@
> +/** @file -- VariableLockRequstToLock.c
> 
> +Temporary location of the RequestToLock shim code while
> 
> +projects are moved to VariablePolicy. Should be removed when deprecated.
> 
> +
> 
> +Copyright (c) Microsoft Corporation.
> 
> +SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +
> 
> +**/
> 
> +
> 
> +#include <Uefi.h>
> 
> +
> 
> +#include <Library/DebugLib.h>
> 
> +#include <Library/MemoryAllocationLib.h>
> 
> +
> 
> +#include <Protocol/VariableLock.h>
> 
> +
> 
> +#include <Protocol/VariablePolicy.h>
> 
> +#include <Library/VariablePolicyLib.h>
> 
> +#include <Library/VariablePolicyHelperLib.h>
> 
> +
> 
> +
> 
> +/**
> 
> +  DEPRECATED. THIS IS ONLY HERE AS A CONVENIENCE WHILE PORTING.
1.[Dandan]: You mentioned that this API is deprecated. So, you will retire VarLock protocol and this API, and update caller to use VariablePolicy protocol later, right?
And I also see that VariablePolicy is an updated interface to replace VarLock and VarCheckProtocol, so will you also retire VarCheckProtocol later? But in patch 9 VarCheckRegisterSetVariableCheckHandler seem still be used to register SetVariable handler to do SetVariable check based on Variable Policy.

> 
> +  Mark a variable that will become read-only after leaving the DXE phase of
> execution.
> 
> +  Write request coming from SMM environment through
> EFI_SMM_VARIABLE_PROTOCOL is allowed.
> 
> +
> 
> +  @param[in] This          The VARIABLE_LOCK_PROTOCOL instance.
> 
> +  @param[in] VariableName  A pointer to the variable name that will be
> made read-only subsequently.
> 
> +  @param[in] VendorGuid    A pointer to the vendor GUID that will be made
> read-only subsequently.
> 
> +
> 
> +  @retval EFI_SUCCESS           The variable specified by the VariableName and
> the VendorGuid was marked
> 
> +                                as pending to be read-only.
> 
> +  @retval EFI_INVALID_PARAMETER VariableName or VendorGuid is NULL.
> 
> +                                Or VariableName is an empty string.
> 
> +  @retval EFI_ACCESS_DENIED     EFI_END_OF_DXE_EVENT_GROUP_GUID
> or EFI_EVENT_GROUP_READY_TO_BOOT has
> 
> +                                already been signaled.
> 
> +  @retval EFI_OUT_OF_RESOURCES  There is not enough resource to hold
> the lock request.
> 
> +**/
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +VariableLockRequestToLock (
> 
> +  IN CONST EDKII_VARIABLE_LOCK_PROTOCOL *This,
> 
> +  IN       CHAR16                       *VariableName,
> 
> +  IN       EFI_GUID                     *VendorGuid
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS              Status;
> 
> +  VARIABLE_POLICY_ENTRY   *NewPolicy;
> 
> +
> 
> +  NewPolicy = NULL;
> 
> +  Status = CreateBasicVariablePolicy( VendorGuid,
> 
> +                                      VariableName,
> 
> +                                      VARIABLE_POLICY_NO_MIN_SIZE,
> 
> +                                      VARIABLE_POLICY_NO_MAX_SIZE,
> 
> +                                      VARIABLE_POLICY_NO_MUST_ATTR,
> 
> +                                      VARIABLE_POLICY_NO_CANT_ATTR,
> 
> +                                      VARIABLE_POLICY_TYPE_LOCK_NOW,
> 
> +                                      &NewPolicy );
> 
> +  if (!EFI_ERROR( Status )) {
> 
> +    Status = RegisterVariablePolicy( NewPolicy );
> 
> +  }
> 
> +  if (EFI_ERROR( Status )) {
> 
> +    DEBUG(( DEBUG_ERROR, "%a - Failed to lock variable %s! %r\n",
> __FUNCTION__, VariableName, Status ));
> 
> +    ASSERT_EFI_ERROR( Status );
> 
> +  }
> 
> +  if (NewPolicy != NULL) {
> 
> +    FreePool( NewPolicy );
> 
> +  }
> 
> +
> 
> +  return Status;
> 
> +}
> 
> diff --git
> a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
> b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
> index 8debc560e6dc..3005e9617423 100644
> ---
> a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
> +++
> b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
> @@ -49,6 +49,7 @@ [Sources]
>    VarCheck.c
> 
>    VariableExLib.c
> 
>    SpeculationBarrierDxe.c
> 
> +  VariableLockRequstToLock.c
> 
> 
> 
>  [Packages]
> 
>    MdePkg/MdePkg.dec
> 
> diff --git
> a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf
> b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf
> index bbc8d2080193..26fbad97339f 100644
> --- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf
> +++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf
> @@ -58,6 +58,7 @@ [Sources]
>    VariableExLib.c
> 
>    TcgMorLockSmm.c
> 
>    SpeculationBarrierSmm.c
> 
> +  VariableLockRequstToLock.c
> 
> 
> 
>  [Packages]
> 
>    MdePkg/MdePkg.dec
> 
> diff --git
> a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.i
> nf
> b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.
> inf
> index 62f2f9252f43..7c6fdf4d65fd 100644
> ---
> a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.i
> nf
> +++
> b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.
> inf
> @@ -58,6 +58,7 @@ [Sources]
>    VariableExLib.c
> 
>    TcgMorLockSmm.c
> 
>    SpeculationBarrierSmm.c
> 
> +  VariableLockRequstToLock.c
> 
> 
> 
>  [Packages]
> 
>    MdePkg/MdePkg.dec
> 
> --
> 2.26.2.windows.1.8.g01c50adf56.20200515075929
> 
> 
> -=-=-=-=-=-=
> Groups.io Links: You receive all messages sent to this group.
> 
> View/Reply Online (#61587): https://edk2.groups.io/g/devel/message/61587
> Mute This Topic: https://groups.io/mt/75057696/1768738
> Group Owner: devel+owner@edk2.groups.io
> Unsubscribe: https://edk2.groups.io/g/devel/unsub  [dandan.bi@intel.com]
> -=-=-=-=-=-=


^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [edk2-devel] [PATCH v6 09/14] MdeModulePkg: Connect VariablePolicy business logic to VariableServices
  2020-06-23  6:40 ` [PATCH v6 09/14] MdeModulePkg: Connect VariablePolicy business logic to VariableServices Bret Barkelew
@ 2020-07-02  2:13   ` Dandan Bi
  2020-07-02  6:40     ` Bret Barkelew
  0 siblings, 1 reply; 48+ messages in thread
From: Dandan Bi @ 2020-07-02  2:13 UTC (permalink / raw)
  To: devel@edk2.groups.io, bret@corthon.com
  Cc: Wang, Jian J, Wu, Hao A, Gao, Liming


1 comment inline, please check.


Thanks,
Dandan
> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Bret
> Barkelew
> Sent: Tuesday, June 23, 2020 2:41 PM
> To: devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>;
> Gao, Liming <liming.gao@intel.com>
> Subject: [edk2-devel] [PATCH v6 09/14] MdeModulePkg: Connect
> VariablePolicy business logic to VariableServices
> 
> https://bugzilla.tianocore.org/show_bug.cgi?id=2522
> 
> VariablePolicy is an updated interface to
> replace VarLock and VarCheckProtocol.
> 
> Add connective code to publish the VariablePolicy protocol
> and wire it to either the SMM communication interface
> or directly into the VariablePolicyLib business logic.
> 
> Cc: Jian J Wang <jian.j.wang@intel.com>
> Cc: Hao A Wu <hao.a.wu@intel.com>
> Cc: Liming Gao <liming.gao@intel.com>
> Cc: Bret Barkelew <brbarkel@microsoft.com>
> Signed-off-by: Bret Barkelew <brbarkel@microsoft.com>
> ---
>  MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c             |  53
> ++
>  MdeModulePkg/Universal/Variable/RuntimeDxe/VariablePolicySmmDxe.c
> | 642 ++++++++++++++++++++
> 
> MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.
> c   |  14 +
>  MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
> |   2 +
>  MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf           |   3
> +
> 
> MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.i
> nf |  10 +
>  6 files changed, 724 insertions(+)
> 
> diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c
> b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c
> index 7d2b6c8e1fad..d404d4763e54 100644
> --- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c
> +++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c
> @@ -5,18 +5,34 @@
>  Copyright (C) 2013, Red Hat, Inc.
> 
>  Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
> 
>  (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
> 
> +Copyright (c) Microsoft Corporation.
> 
>  SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> 
> 
>  **/
> 
> 
> 
>  #include "Variable.h"
> 
> 
> 
> +#include <Protocol/VariablePolicy.h>
> 
> +#include <Library/VariablePolicyLib.h>
> 
> +
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +ProtocolIsVariablePolicyEnabled (
> 
> +  OUT BOOLEAN *State
> 
> +  );
> 
> +
> 
>  EFI_HANDLE                          mHandle                    = NULL;
> 
>  EFI_EVENT                           mVirtualAddressChangeEvent = NULL;
> 
>  VOID                                *mFtwRegistration          = NULL;
> 
>  VOID                                ***mVarCheckAddressPointer = NULL;
> 
>  UINTN                               mVarCheckAddressPointerCount = 0;
> 
>  EDKII_VARIABLE_LOCK_PROTOCOL        mVariableLock              =
> { VariableLockRequestToLock };
> 
> +EDKII_VARIABLE_POLICY_PROTOCOL      mVariablePolicyProtocol    =
> { EDKII_VARIABLE_POLICY_PROTOCOL_REVISION,
> 
> +                                                                    DisableVariablePolicy,
> 
> +                                                                    ProtocolIsVariablePolicyEnabled,
> 
> +                                                                    RegisterVariablePolicy,
> 
> +                                                                    DumpVariablePolicy,
> 
> +                                                                    LockVariablePolicy };
> 
>  EDKII_VAR_CHECK_PROTOCOL            mVarCheck                  =
> { VarCheckRegisterSetVariableCheckHandler,
> 
>                                                                      VarCheckVariablePropertySet,
> 
>                                                                      VarCheckVariablePropertyGet };
> 
> @@ -303,6 +319,8 @@ OnReadyToBoot (
>      }
> 
>    }
> 
> 
> 
> +  ASSERT_EFI_ERROR (LockVariablePolicy ());
> 
> +
> 
>    gBS->CloseEvent (Event);
> 
>  }
> 
> 
> 
> @@ -466,6 +484,28 @@ FtwNotificationEvent (
>  }
> 
> 
> 
> 
> 
> +/**
> 
> +  This API function returns whether or not the policy engine is
> 
> +  currently being enforced.
> 
> +
> 
> +  @param[out]   State       Pointer to a return value for whether the policy
> enforcement
> 
> +                            is currently enabled.
> 
> +
> 
> +  @retval     EFI_SUCCESS
> 
> +  @retval     Others        An error has prevented this command from
> completing.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +ProtocolIsVariablePolicyEnabled (
> 
> +  OUT BOOLEAN *State
> 
> +  )
> 
> +{
> 
> +  *State = IsVariablePolicyEnabled ();
> 
> +  return EFI_SUCCESS;
> 
> +}

1. [Dandan]: I see other APIs in the VariablePolicyProtocol are using the APIs in VariablePolicyLib directly, expect this one.
Could we make the IsVariablePolicyEnabled API aligned in protocol and Lib?

> 
> +
> 
> +
> 
>  /**
> 
>    Variable Driver main entry point. The Variable driver places the 4 EFI
> 
>    runtime services in the EFI System Table and installs arch protocols
> 
> @@ -576,6 +616,19 @@ VariableServiceInitialize (
>                    );
> 
>    ASSERT_EFI_ERROR (Status);
> 
> 
> 
> +  // Register and initialize the VariablePolicy engine.
> 
> +  Status = InitVariablePolicyLib (VariableServiceGetVariable);
> 
> +  ASSERT_EFI_ERROR (Status);
> 
> +  Status = VarCheckRegisterSetVariableCheckHandler (ValidateSetVariable);
> 
> +  ASSERT_EFI_ERROR (Status);
> 
> +  Status = gBS->InstallMultipleProtocolInterfaces (
> 
> +                    &mHandle,
> 
> +                    &gEdkiiVariablePolicyProtocolGuid,
> 
> +                    &mVariablePolicyProtocol,
> 
> +                    NULL
> 
> +                    );
> 
> +  ASSERT_EFI_ERROR (Status);
> 
> +
> 
>    return EFI_SUCCESS;
> 
>  }
> 
> 
> 
> diff --git
> a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariablePolicySmmDxe.c
> b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariablePolicySmmDxe.c
> new file mode 100644
> index 000000000000..e2d4cf4cec1a
> --- /dev/null
> +++
> b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariablePolicySmmDxe.c
> @@ -0,0 +1,642 @@
> +/** @file -- VariablePolicySmmDxe.c
> 
> +This protocol allows communication with Variable Policy Engine.
> 
> +
> 
> +Copyright (c) Microsoft Corporation.
> 
> +SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +
> 
> +**/
> 
> +
> 
> +#include <Library/BaseLib.h>
> 
> +#include <Library/UefiLib.h>
> 
> +#include <Library/DebugLib.h>
> 
> +#include <Library/SafeIntLib.h>
> 
> +#include <Library/UefiBootServicesTableLib.h>
> 
> +#include <Library/BaseMemoryLib.h>
> 
> +#include <Library/MemoryAllocationLib.h>
> 
> +
> 
> +#include <Protocol/VariablePolicy.h>
> 
> +#include <Protocol/MmCommunication2.h>
> 
> +
> 
> +#include <Guid/VarCheckPolicyMmi.h>
> 
> +
> 
> +#include "Variable.h"
> 
> +
> 
> +EDKII_VARIABLE_POLICY_PROTOCOL  mVariablePolicyProtocol;
> 
> +EFI_MM_COMMUNICATION2_PROTOCOL  *mMmCommunication;
> 
> +
> 
> +VOID      *mMmCommunicationBuffer;
> 
> +UINTN     mMmCommunicationBufferSize;
> 
> +EFI_LOCK  mMmCommunicationLock;
> 
> +
> 
> +/**
> 
> +  Internal helper function to consolidate communication method.
> 
> +
> 
> +  @param[in,out]  CommBuffer
> 
> +  @param[in,out]  CommSize    Size of the CommBuffer.
> 
> +
> 
> +  @retval   EFI_STATUS    Result from communication method.
> 
> +
> 
> +**/
> 
> +STATIC
> 
> +EFI_STATUS
> 
> +InternalMmCommunicate (
> 
> +  IN OUT VOID             *CommBuffer,
> 
> +  IN OUT UINTN            *CommSize
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS    Status;
> 
> +  if (CommBuffer == NULL || CommSize == NULL) {
> 
> +    return EFI_INVALID_PARAMETER;
> 
> +  }
> 
> +  Status = mMmCommunication->Communicate (mMmCommunication,
> CommBuffer, CommBuffer, CommSize);
> 
> +  return Status;
> 
> +}
> 
> +
> 
> +
> 
> +/**
> 
> +  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_WRITE_PROTECTED   Interface option is disabled by platform
> PCD.
> 
> +
> 
> +**/
> 
> +STATIC
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +ProtocolDisableVariablePolicy (
> 
> +  VOID
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS                    Status;
> 
> +  EFI_MM_COMMUNICATE_HEADER     *CommHeader;
> 
> +  VAR_CHECK_POLICY_COMM_HEADER  *PolicyHeader;
> 
> +  UINTN                         BufferSize;
> 
> +
> 
> +  // Check the PCD for convenience.
> 
> +  // This would also be rejected by the lib, but why go to MM if we don't
> have to?
> 
> +  if (!PcdGetBool (PcdAllowVariablePolicyEnforcementDisable)) {
> 
> +    return EFI_WRITE_PROTECTED;
> 
> +  }
> 
> +
> 
> +  AcquireLockOnlyAtBootTime (&mMmCommunicationLock);
> 
> +
> 
> +  // Set up the MM communication.
> 
> +  BufferSize    = mMmCommunicationBufferSize;
> 
> +  CommHeader    = mMmCommunicationBuffer;
> 
> +  PolicyHeader  = (VAR_CHECK_POLICY_COMM_HEADER*)&CommHeader-
> >Data;
> 
> +  CopyGuid( &CommHeader->HeaderGuid,
> &gVarCheckPolicyLibMmiHandlerGuid );
> 
> +  CommHeader->MessageLength = BufferSize;
> 
> +  PolicyHeader->Signature   = VAR_CHECK_POLICY_COMM_SIG;
> 
> +  PolicyHeader->Revision    = VAR_CHECK_POLICY_COMM_REVISION;
> 
> +  PolicyHeader->Command     = VAR_CHECK_POLICY_COMMAND_DISABLE;
> 
> +
> 
> +  Status = InternalMmCommunicate (CommHeader, &BufferSize);
> 
> +  DEBUG(( DEBUG_VERBOSE, "%a - MmCommunication returned %r.\n",
> __FUNCTION__, Status ));
> 
> +
> 
> +  ReleaseLockOnlyAtBootTime (&mMmCommunicationLock);
> 
> +
> 
> +  return (EFI_ERROR( Status )) ? Status : PolicyHeader->Result;
> 
> +}
> 
> +
> 
> +
> 
> +/**
> 
> +  This API function returns whether or not the policy engine is
> 
> +  currently being enforced.
> 
> +
> 
> +  @param[out]   State       Pointer to a return value for whether the policy
> enforcement
> 
> +                            is currently enabled.
> 
> +
> 
> +  @retval     EFI_SUCCESS
> 
> +  @retval     Others        An error has prevented this command from
> completing.
> 
> +
> 
> +**/
> 
> +STATIC
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +ProtocolIsVariablePolicyEnabled (
> 
> +  OUT BOOLEAN     *State
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS                                Status;
> 
> +  EFI_MM_COMMUNICATE_HEADER                 *CommHeader;
> 
> +  VAR_CHECK_POLICY_COMM_HEADER              *PolicyHeader;
> 
> +  VAR_CHECK_POLICY_COMM_IS_ENABLED_PARAMS   *CommandParams;
> 
> +  UINTN                                     BufferSize;
> 
> +
> 
> +  if (State == NULL) {
> 
> +    return EFI_INVALID_PARAMETER;
> 
> +  }
> 
> +
> 
> +  AcquireLockOnlyAtBootTime (&mMmCommunicationLock);
> 
> +
> 
> +  // Set up the MM communication.
> 
> +  BufferSize    = mMmCommunicationBufferSize;
> 
> +  CommHeader    = mMmCommunicationBuffer;
> 
> +  PolicyHeader  = (VAR_CHECK_POLICY_COMM_HEADER*)&CommHeader-
> >Data;
> 
> +  CommandParams =
> (VAR_CHECK_POLICY_COMM_IS_ENABLED_PARAMS*)(PolicyHeader + 1);
> 
> +  CopyGuid( &CommHeader->HeaderGuid,
> &gVarCheckPolicyLibMmiHandlerGuid );
> 
> +  CommHeader->MessageLength = BufferSize;
> 
> +  PolicyHeader->Signature   = VAR_CHECK_POLICY_COMM_SIG;
> 
> +  PolicyHeader->Revision    = VAR_CHECK_POLICY_COMM_REVISION;
> 
> +  PolicyHeader->Command     =
> VAR_CHECK_POLICY_COMMAND_IS_ENABLED;
> 
> +
> 
> +  Status = InternalMmCommunicate (CommHeader, &BufferSize);
> 
> +  DEBUG(( DEBUG_VERBOSE, "%a - MmCommunication returned %r.\n",
> __FUNCTION__, Status ));
> 
> +
> 
> +  if (!EFI_ERROR( Status )) {
> 
> +    Status = PolicyHeader->Result;
> 
> +    *State = CommandParams->State;
> 
> +  }
> 
> +
> 
> +  ReleaseLockOnlyAtBootTime (&mMmCommunicationLock);
> 
> +
> 
> +  return Status;
> 
> +}
> 
> +
> 
> +
> 
> +/**
> 
> +  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.
> 
> +
> 
> +**/
> 
> +STATIC
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +ProtocolRegisterVariablePolicy (
> 
> +  IN CONST VARIABLE_POLICY_ENTRY    *NewPolicy
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS                                Status;
> 
> +  EFI_MM_COMMUNICATE_HEADER                 *CommHeader;
> 
> +  VAR_CHECK_POLICY_COMM_HEADER              *PolicyHeader;
> 
> +  VOID                                      *PolicyBuffer;
> 
> +  UINTN                                     BufferSize;
> 
> +  UINTN                                     RequiredSize;
> 
> +
> 
> +  if (NewPolicy == NULL) {
> 
> +    return EFI_INVALID_PARAMETER;
> 
> +  }
> 
> +
> 
> +  // First, make sure that the required size does not exceed the capabilities
> 
> +  // of the MmCommunication buffer.
> 
> +  RequiredSize = OFFSET_OF(EFI_MM_COMMUNICATE_HEADER, Data) +
> sizeof(VAR_CHECK_POLICY_COMM_HEADER);
> 
> +  Status = SafeUintnAdd( RequiredSize, NewPolicy->Size, &RequiredSize );
> 
> +  if (EFI_ERROR( Status ) || RequiredSize > mMmCommunicationBufferSize)
> {
> 
> +    DEBUG(( DEBUG_ERROR, "%a - Policy too large for buffer! %r, %d > %d
> \n", __FUNCTION__,
> 
> +            Status, RequiredSize, mMmCommunicationBufferSize ));
> 
> +    return EFI_OUT_OF_RESOURCES;
> 
> +  }
> 
> +
> 
> +  AcquireLockOnlyAtBootTime (&mMmCommunicationLock);
> 
> +
> 
> +  // Set up the MM communication.
> 
> +  BufferSize    = mMmCommunicationBufferSize;
> 
> +  CommHeader    = mMmCommunicationBuffer;
> 
> +  PolicyHeader  = (VAR_CHECK_POLICY_COMM_HEADER*)&CommHeader-
> >Data;
> 
> +  PolicyBuffer  = (VOID*)(PolicyHeader + 1);
> 
> +  CopyGuid( &CommHeader->HeaderGuid,
> &gVarCheckPolicyLibMmiHandlerGuid );
> 
> +  CommHeader->MessageLength = BufferSize;
> 
> +  PolicyHeader->Signature   = VAR_CHECK_POLICY_COMM_SIG;
> 
> +  PolicyHeader->Revision    = VAR_CHECK_POLICY_COMM_REVISION;
> 
> +  PolicyHeader->Command     = VAR_CHECK_POLICY_COMMAND_REGISTER;
> 
> +
> 
> +  // Copy the policy into place. This copy is safe because we've already
> tested above.
> 
> +  CopyMem( PolicyBuffer, NewPolicy, NewPolicy->Size );
> 
> +
> 
> +  Status = InternalMmCommunicate (CommHeader, &BufferSize);
> 
> +  DEBUG(( DEBUG_VERBOSE, "%a - MmCommunication returned %r.\n",
> __FUNCTION__, Status ));
> 
> +
> 
> +  ReleaseLockOnlyAtBootTime (&mMmCommunicationLock);
> 
> +
> 
> +  return (EFI_ERROR( Status )) ? Status : PolicyHeader->Result;
> 
> +}
> 
> +
> 
> +
> 
> +/**
> 
> +  This helper function takes care of the overhead of formatting, sending,
> and interpreting
> 
> +  the results for a single DumpVariablePolicy request.
> 
> +
> 
> +  @param[in]      PageRequested   The page of the paginated results from
> MM. 0 for metadata.
> 
> +  @param[out]     TotalSize       The total size of the entire buffer. Returned as
> part of metadata.
> 
> +  @param[out]     PageSize        The size of the current page being returned.
> Not valid as part of metadata.
> 
> +  @param[out]     HasMore         A flag indicating whether there are more
> pages after this one.
> 
> +  @param[out]     Buffer          The start of the current page from MM.
> 
> +
> 
> +  @retval     EFI_SUCCESS             Output params have been updated (either
> metadata or dump page).
> 
> +  @retval     EFI_INVALID_PARAMETER   One of the output params is NULL.
> 
> +  @retval     Others                  Response from MM handler.
> 
> +
> 
> +**/
> 
> +STATIC
> 
> +EFI_STATUS
> 
> +DumpVariablePolicyHelper (
> 
> +  IN  UINT32        PageRequested,
> 
> +  OUT UINT32        *TotalSize,
> 
> +  OUT UINT32        *PageSize,
> 
> +  OUT BOOLEAN       *HasMore,
> 
> +  OUT UINT8         **Buffer
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS                              Status;
> 
> +  EFI_MM_COMMUNICATE_HEADER               *CommHeader;
> 
> +  VAR_CHECK_POLICY_COMM_HEADER            *PolicyHeader;
> 
> +  VAR_CHECK_POLICY_COMM_DUMP_PARAMS       *CommandParams;
> 
> +  UINTN                                   BufferSize;
> 
> +
> 
> +  if (TotalSize == NULL || PageSize == NULL || HasMore == NULL || Buffer
> == NULL) {
> 
> +    return EFI_INVALID_PARAMETER;
> 
> +  }
> 
> +
> 
> +  // Set up the MM communication.
> 
> +  BufferSize    = mMmCommunicationBufferSize;
> 
> +  CommHeader    = mMmCommunicationBuffer;
> 
> +  PolicyHeader  = (VAR_CHECK_POLICY_COMM_HEADER*)&CommHeader-
> >Data;
> 
> +  CommandParams =
> (VAR_CHECK_POLICY_COMM_DUMP_PARAMS*)(PolicyHeader + 1);
> 
> +  CopyGuid( &CommHeader->HeaderGuid,
> &gVarCheckPolicyLibMmiHandlerGuid );
> 
> +  CommHeader->MessageLength = BufferSize;
> 
> +  PolicyHeader->Signature   = VAR_CHECK_POLICY_COMM_SIG;
> 
> +  PolicyHeader->Revision    = VAR_CHECK_POLICY_COMM_REVISION;
> 
> +  PolicyHeader->Command     = VAR_CHECK_POLICY_COMMAND_DUMP;
> 
> +
> 
> +  CommandParams->PageRequested = PageRequested;
> 
> +
> 
> +  Status = InternalMmCommunicate (CommHeader, &BufferSize);
> 
> +  DEBUG(( DEBUG_VERBOSE, "%a - MmCommunication returned %r.\n",
> __FUNCTION__, Status ));
> 
> +
> 
> +  if (!EFI_ERROR( Status )) {
> 
> +    Status = PolicyHeader->Result;
> 
> +    *TotalSize = CommandParams->TotalSize;
> 
> +    *PageSize = CommandParams->PageSize;
> 
> +    *HasMore = CommandParams->HasMore;
> 
> +    *Buffer = (UINT8*)(CommandParams + 1);
> 
> +  }
> 
> +
> 
> +  return Status;
> 
> +}
> 
> +
> 
> +
> 
> +/**
> 
> +  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.
> 
> +
> 
> +**/
> 
> +STATIC
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +ProtocolDumpVariablePolicy (
> 
> +  OUT UINT8             *Policy OPTIONAL,
> 
> +  IN OUT UINT32         *Size
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS    Status;
> 
> +  UINT8         *Source;
> 
> +  UINT8         *Destination;
> 
> +  UINT32        PolicySize;
> 
> +  UINT32        PageSize;
> 
> +  BOOLEAN       HasMore;
> 
> +  UINT32        PageIndex;
> 
> +
> 
> +  if (Size == NULL || (*Size > 0 && Policy == NULL)) {
> 
> +    return EFI_INVALID_PARAMETER;
> 
> +  }
> 
> +
> 
> +  AcquireLockOnlyAtBootTime (&mMmCommunicationLock);
> 
> +
> 
> +  // Repeat this whole process until we either have a failure case or get the
> entire buffer.
> 
> +  do {
> 
> +    // First, we must check the zero page to determine the buffer size and
> 
> +    // reset the internal state.
> 
> +    PolicySize = 0;
> 
> +    PageSize = 0;
> 
> +    HasMore = FALSE;
> 
> +    Status = DumpVariablePolicyHelper (0, &PolicySize, &PageSize, &HasMore,
> &Source);
> 
> +    if (EFI_ERROR (Status)) {
> 
> +      break;
> 
> +    }
> 
> +
> 
> +    // If we're good, we can at least check the required size now.
> 
> +    if (*Size < PolicySize) {
> 
> +      *Size = PolicySize;
> 
> +      Status = EFI_BUFFER_TOO_SMALL;
> 
> +      break;
> 
> +    }
> 
> +
> 
> +    // On further thought, let's update the size either way.
> 
> +    *Size = PolicySize;
> 
> +    // And get ready to ROCK.
> 
> +    Destination = Policy;
> 
> +
> 
> +    // Keep looping and copying until we're either done or freak out.
> 
> +    for (PageIndex = 1; !EFI_ERROR (Status) && HasMore && PageIndex <
> MAX_UINT32; PageIndex++) {
> 
> +      Status = DumpVariablePolicyHelper (PageIndex, &PolicySize, &PageSize,
> &HasMore, &Source);
> 
> +      if (!EFI_ERROR (Status)) {
> 
> +        CopyMem (Destination, Source, PageSize);
> 
> +        Destination += PageSize;
> 
> +      }
> 
> +    }
> 
> +
> 
> +    // Next, we check to see whether
> 
> +  } while (Status == EFI_TIMEOUT);
> 
> +
> 
> +  ReleaseLockOnlyAtBootTime (&mMmCommunicationLock);
> 
> +
> 
> +  // There's currently no use for this, but it shouldn't be hard to implement.
> 
> +  return Status;
> 
> +}
> 
> +
> 
> +
> 
> +/**
> 
> +  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     Others        An error has prevented this command from
> completing.
> 
> +
> 
> +**/
> 
> +STATIC
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +ProtocolLockVariablePolicy (
> 
> +  VOID
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS                    Status;
> 
> +  EFI_MM_COMMUNICATE_HEADER     *CommHeader;
> 
> +  VAR_CHECK_POLICY_COMM_HEADER  *PolicyHeader;
> 
> +  UINTN                         BufferSize;
> 
> +
> 
> +  AcquireLockOnlyAtBootTime (&mMmCommunicationLock);
> 
> +
> 
> +  // Set up the MM communication.
> 
> +  BufferSize    = mMmCommunicationBufferSize;
> 
> +  CommHeader    = mMmCommunicationBuffer;
> 
> +  PolicyHeader  = (VAR_CHECK_POLICY_COMM_HEADER*)&CommHeader-
> >Data;
> 
> +  CopyGuid( &CommHeader->HeaderGuid,
> &gVarCheckPolicyLibMmiHandlerGuid );
> 
> +  CommHeader->MessageLength = BufferSize;
> 
> +  PolicyHeader->Signature   = VAR_CHECK_POLICY_COMM_SIG;
> 
> +  PolicyHeader->Revision    = VAR_CHECK_POLICY_COMM_REVISION;
> 
> +  PolicyHeader->Command     = VAR_CHECK_POLICY_COMMAND_LOCK;
> 
> +
> 
> +  Status = InternalMmCommunicate (CommHeader, &BufferSize);
> 
> +  DEBUG(( DEBUG_VERBOSE, "%a - MmCommunication returned %r.\n",
> __FUNCTION__, Status ));
> 
> +
> 
> +  ReleaseLockOnlyAtBootTime (&mMmCommunicationLock);
> 
> +
> 
> +  return (EFI_ERROR( Status )) ? Status : PolicyHeader->Result;
> 
> +}
> 
> +
> 
> +
> 
> +/**
> 
> +  This helper function locates the shared comm buffer and assigns it to input
> pointers.
> 
> +
> 
> +  @param[in,out]  BufferSize      On input, the minimum buffer size required
> INCLUDING the MM communicate header.
> 
> +                                  On output, the size of the matching buffer found.
> 
> +  @param[out]     LocatedBuffer   A pointer to the matching buffer.
> 
> +
> 
> +  @retval     EFI_SUCCESS
> 
> +  @retval     EFI_INVALID_PARAMETER   One of the output pointers was
> NULL.
> 
> +  @retval     EFI_OUT_OF_RESOURCES    Not enough memory to allocate a
> comm buffer.
> 
> +
> 
> +**/
> 
> +STATIC
> 
> +EFI_STATUS
> 
> +InitMmCommonCommBuffer (
> 
> +  IN OUT  UINTN       *BufferSize,
> 
> +  OUT     VOID        **LocatedBuffer
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS                  Status;
> 
> +
> 
> +  Status = EFI_SUCCESS;
> 
> +
> 
> +  // Make sure that we're working with good pointers.
> 
> +  if (BufferSize == NULL || LocatedBuffer == NULL) {
> 
> +    return EFI_INVALID_PARAMETER;
> 
> +  }
> 
> +
> 
> +  // Allocate the runtime memory for the comm buffer.
> 
> +  *LocatedBuffer = AllocateRuntimePool (*BufferSize);
> 
> +  if (*LocatedBuffer == NULL) {
> 
> +    Status = EFI_OUT_OF_RESOURCES;
> 
> +    *BufferSize = 0;
> 
> +  }
> 
> +
> 
> +  EfiInitializeLock (&mMmCommunicationLock, TPL_NOTIFY);
> 
> +
> 
> +  return Status;
> 
> +}
> 
> +
> 
> +
> 
> +/**
> 
> +  This helper is responsible for telemetry and any other actions that
> 
> +  need to be taken if the VariablePolicy fails to lock.
> 
> +
> 
> +  NOTE: It's possible that parts of this handling will need to become
> 
> +        part of a platform policy.
> 
> +
> 
> +  @param[in]  FailureStatus   The failure that was reported by
> LockVariablePolicy
> 
> +
> 
> +**/
> 
> +STATIC
> 
> +VOID
> 
> +VariablePolicyHandleFailureToLock (
> 
> +  IN  EFI_STATUS      FailureStatus
> 
> +  )
> 
> +{
> 
> +  // For now, there's no agreed-upon policy for this.
> 
> +  return;
> 
> +}
> 
> +
> 
> +
> 
> +/**
> 
> +  ReadyToBoot Callback
> 
> +  Lock the VariablePolicy interface if it hasn't already been locked.
> 
> +
> 
> +  @param[in]  Event     Event whose notification function is being invoked
> 
> +  @param[in]  Context   Pointer to the notification function's context
> 
> +
> 
> +**/
> 
> +STATIC
> 
> +VOID
> 
> +EFIAPI
> 
> +LockPolicyInterfaceAtReadyToBoot (
> 
> +  IN      EFI_EVENT                 Event,
> 
> +  IN      VOID                      *Context
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS  Status;
> 
> +
> 
> +  Status = ProtocolLockVariablePolicy();
> 
> +
> 
> +  if (EFI_ERROR( Status )) {
> 
> +    VariablePolicyHandleFailureToLock( Status );
> 
> +  }
> 
> +  else {
> 
> +    gBS->CloseEvent( Event );
> 
> +  }
> 
> +
> 
> +}
> 
> +
> 
> +
> 
> +/**
> 
> +  Convert internal pointer addresses to virtual addresses.
> 
> +
> 
> +  @param[in] Event      Event whose notification function is being invoked.
> 
> +  @param[in] Context    The pointer to the notification function's context,
> which
> 
> +                        is implementation-dependent.
> 
> +**/
> 
> +STATIC
> 
> +VOID
> 
> +EFIAPI
> 
> +VariablePolicyVirtualAddressCallback (
> 
> +  IN  EFI_EVENT   Event,
> 
> +  IN  VOID        *Context
> 
> +  )
> 
> +{
> 
> +  EfiConvertPointer (0, (VOID **)&mMmCommunication);
> 
> +  EfiConvertPointer (0, (VOID **)&mMmCommunicationBuffer);
> 
> +}
> 
> +
> 
> +
> 
> +/**
> 
> +  The driver's entry point.
> 
> +
> 
> +  @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.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +VariablePolicySmmDxeMain (
> 
> +  IN    EFI_HANDLE                  ImageHandle,
> 
> +  IN    EFI_SYSTEM_TABLE            *SystemTable
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS              Status;
> 
> +  BOOLEAN                 ProtocolInstalled;
> 
> +  BOOLEAN                 CallbackRegistered;
> 
> +  BOOLEAN                 VirtualAddressChangeRegistered;
> 
> +  EFI_EVENT               ReadyToBootEvent;
> 
> +  EFI_EVENT               VirtualAddressChangeEvent;
> 
> +
> 
> +  Status = EFI_SUCCESS;
> 
> +  ProtocolInstalled = FALSE;
> 
> +  CallbackRegistered = FALSE;
> 
> +  VirtualAddressChangeRegistered = FALSE;
> 
> +
> 
> +  // Update the minimum buffer size.
> 
> +  mMmCommunicationBufferSize =
> VAR_CHECK_POLICY_MM_COMM_BUFFER_SIZE;
> 
> +  // Locate the shared comm buffer to use for sending MM commands.
> 
> +  Status = InitMmCommonCommBuffer( &mMmCommunicationBufferSize,
> &mMmCommunicationBuffer );
> 
> +  if (EFI_ERROR( Status )) {
> 
> +    DEBUG((DEBUG_ERROR, "%a - Failed to locate a viable MM comm
> buffer! %r\n", __FUNCTION__, Status));
> 
> +    ASSERT_EFI_ERROR( Status );
> 
> +    return Status;
> 
> +  }
> 
> +
> 
> +  // Locate the MmCommunication protocol.
> 
> +  Status = gBS->LocateProtocol( &gEfiMmCommunication2ProtocolGuid,
> NULL, (VOID**)&mMmCommunication );
> 
> +  if (EFI_ERROR( Status )) {
> 
> +    DEBUG((DEBUG_ERROR, "%a - Failed to locate MmCommunication
> protocol! %r\n", __FUNCTION__, Status));
> 
> +    ASSERT_EFI_ERROR( Status );
> 
> +    return Status;
> 
> +  }
> 
> +
> 
> +  // Configure the VariablePolicy protocol structure.
> 
> +  mVariablePolicyProtocol.Revision                =
> EDKII_VARIABLE_POLICY_PROTOCOL_REVISION;
> 
> +  mVariablePolicyProtocol.DisableVariablePolicy   =
> ProtocolDisableVariablePolicy;
> 
> +  mVariablePolicyProtocol.IsVariablePolicyEnabled =
> ProtocolIsVariablePolicyEnabled;
> 
> +  mVariablePolicyProtocol.RegisterVariablePolicy  =
> ProtocolRegisterVariablePolicy;
> 
> +  mVariablePolicyProtocol.DumpVariablePolicy      =
> ProtocolDumpVariablePolicy;
> 
> +  mVariablePolicyProtocol.LockVariablePolicy      = ProtocolLockVariablePolicy;
> 
> +
> 
> +  // Register all the protocols and return the status.
> 
> +  Status = gBS->InstallMultipleProtocolInterfaces( &ImageHandle,
> 
> +                                                   &gEdkiiVariablePolicyProtocolGuid,
> &mVariablePolicyProtocol,
> 
> +                                                   NULL );
> 
> +  if (EFI_ERROR( Status )) {
> 
> +    DEBUG(( DEBUG_ERROR, "%a - Failed to install protocol! %r\n",
> __FUNCTION__, Status ));
> 
> +    goto Exit;
> 
> +  }
> 
> +  else {
> 
> +    ProtocolInstalled = TRUE;
> 
> +  }
> 
> +
> 
> +  //
> 
> +  // Register a callback for ReadyToBoot so that the interface is at least
> locked before
> 
> +  // dispatching any bootloaders or UEFI apps.
> 
> +  Status = gBS->CreateEventEx( EVT_NOTIFY_SIGNAL,
> 
> +                               TPL_CALLBACK,
> 
> +                               LockPolicyInterfaceAtReadyToBoot,
> 
> +                               NULL,
> 
> +                               &gEfiEventReadyToBootGuid,
> 
> +                               &ReadyToBootEvent );
> 
> +  if (EFI_ERROR( Status )) {
> 
> +    DEBUG(( DEBUG_ERROR, "%a - Failed to create ReadyToBoot
> event! %r\n", __FUNCTION__, Status ));
> 
> +    goto Exit;
> 
> +  }
> 
> +  else {
> 
> +    CallbackRegistered = TRUE;
> 
> +  }
> 
> +
> 
> +  //
> 
> +  // Register a VirtualAddressChange callback for the MmComm protocol
> and Comm buffer.
> 
> +  Status = gBS->CreateEventEx (EVT_NOTIFY_SIGNAL,
> 
> +                                TPL_NOTIFY,
> 
> +                                VariablePolicyVirtualAddressCallback,
> 
> +                                NULL,
> 
> +                                &gEfiEventVirtualAddressChangeGuid,
> 
> +                                &VirtualAddressChangeEvent);
> 
> +  if (EFI_ERROR( Status )) {
> 
> +    DEBUG(( DEBUG_ERROR, "%a - Failed to create VirtualAddressChange
> event! %r\n", __FUNCTION__, Status ));
> 
> +    goto Exit;
> 
> +  }
> 
> +  else {
> 
> +    VirtualAddressChangeRegistered = TRUE;
> 
> +  }
> 
> +
> 
> +
> 
> +Exit:
> 
> +  //
> 
> +  // If we're about to return a failed status (and unload this driver), we must
> first undo anything that
> 
> +  // has been successfully done.
> 
> +  if (EFI_ERROR( Status )) {
> 
> +    if (ProtocolInstalled) {
> 
> +      gBS->UninstallProtocolInterface( &ImageHandle,
> &gEdkiiVariablePolicyProtocolGuid, &mVariablePolicyProtocol );
> 
> +    }
> 
> +    if (CallbackRegistered) {
> 
> +      gBS->CloseEvent( ReadyToBootEvent );
> 
> +    }
> 
> +    if (VirtualAddressChangeRegistered) {
> 
> +      gBS->CloseEvent( VirtualAddressChangeEvent );
> 
> +    }
> 
> +  }
> 
> +
> 
> +  return Status;
> 
> +}
> 
> diff --git
> a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDx
> e.c
> b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDx
> e.c
> index 663a1aaa128f..c47e614d81f4 100644
> ---
> a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDx
> e.c
> +++
> b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDx
> e.c
> @@ -65,6 +65,17 @@ EFI_LOCK                         mVariableServicesLock;
>  EDKII_VARIABLE_LOCK_PROTOCOL     mVariableLock;
> 
>  EDKII_VAR_CHECK_PROTOCOL         mVarCheck;
> 
> 
> 
> +/**
> 
> +  The logic to initialize the VariablePolicy engine is in its own file.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +VariablePolicySmmDxeMain (
> 
> +  IN    EFI_HANDLE                  ImageHandle,
> 
> +  IN    EFI_SYSTEM_TABLE            *SystemTable
> 
> +  );
> 
> +
> 
>  /**
> 
>    Some Secure Boot Policy Variable may update following other variable
> changes(SecureBoot follows PK change, etc).
> 
>    Record their initial State when variable write service is ready.
> 
> @@ -1796,6 +1807,9 @@ VariableSmmRuntimeInitialize (
>           &mVirtualAddressChangeEvent
> 
>           );
> 
> 
> 
> +  // Initialize the VariablePolicy protocol and engine.
> 
> +  VariablePolicySmmDxeMain (ImageHandle, SystemTable);
> 
> +
> 
>    return EFI_SUCCESS;
> 
>  }
> 
> 
> 
> diff --git
> a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
> b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
> index ceea5d1ff9ac..48ac167906f7 100644
> ---
> a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
> +++
> b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
> @@ -10,6 +10,7 @@
>  #  buffer overflow or integer overflow.
> 
>  #
> 
>  # Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
> 
> +# Copyright (c) Microsoft Corporation.
> 
>  # SPDX-License-Identifier: BSD-2-Clause-Patent
> 
>  #
> 
>  ##
> 
> @@ -69,6 +70,7 @@ [LibraryClasses]
>    TpmMeasurementLib
> 
>    AuthVariableLib
> 
>    VarCheckLib
> 
> +  VariablePolicyLib
> 
> 
> 
>  [Protocols]
> 
>    gEfiFirmwareVolumeBlockProtocolGuid           ## CONSUMES
> 
> diff --git
> a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf
> b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf
> index bc3033588d40..bbc8d2080193 100644
> --- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf
> +++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf
> @@ -19,6 +19,7 @@
>  #  the authentication service provided in this driver will be broken, and the
> behavior is undefined.
> 
>  #
> 
>  # Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.<BR>
> 
> +# Copyright (c) Microsoft Corporation.
> 
>  # SPDX-License-Identifier: BSD-2-Clause-Patent
> 
>  #
> 
>  ##
> 
> @@ -78,6 +79,8 @@ [LibraryClasses]
>    AuthVariableLib
> 
>    VarCheckLib
> 
>    UefiBootServicesTableLib
> 
> +  VariablePolicyLib
> 
> +  VariablePolicyHelperLib
> 
> 
> 
>  [Protocols]
> 
>    gEfiSmmFirmwareVolumeBlockProtocolGuid        ## CONSUMES
> 
> diff --git
> a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDx
> e.inf
> b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDx
> e.inf
> index 01564e4c5068..f217530b2985 100644
> ---
> a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDx
> e.inf
> +++
> b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDx
> e.inf
> @@ -14,6 +14,7 @@
>  #  the authentication service provided in this driver will be broken, and the
> behavior is undefined.
> 
>  #
> 
>  # Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.<BR>
> 
> +# Copyright (c) Microsoft Corporation.<BR>
> 
>  # SPDX-License-Identifier: BSD-2-Clause-Patent
> 
>  #
> 
>  ##
> 
> @@ -42,6 +43,7 @@ [Sources]
>    VariableParsing.c
> 
>    VariableParsing.h
> 
>    Variable.h
> 
> +  VariablePolicySmmDxe.c
> 
> 
> 
>  [Packages]
> 
>    MdePkg/MdePkg.dec
> 
> @@ -56,6 +58,8 @@ [LibraryClasses]
>    DxeServicesTableLib
> 
>    UefiDriverEntryPoint
> 
>    TpmMeasurementLib
> 
> +  SafeIntLib
> 
> +  PcdLib
> 
> 
> 
>  [Protocols]
> 
>    gEfiVariableWriteArchProtocolGuid             ## PRODUCES
> 
> @@ -67,11 +71,15 @@ [Protocols]
>    gEfiSmmVariableProtocolGuid
> 
>    gEdkiiVariableLockProtocolGuid                ## PRODUCES
> 
>    gEdkiiVarCheckProtocolGuid                    ## PRODUCES
> 
> +  gEdkiiVariablePolicyProtocolGuid              ## PRODUCES
> 
> 
> 
>  [FeaturePcd]
> 
>    gEfiMdeModulePkgTokenSpaceGuid.PcdEnableVariableRuntimeCache
> ## CONSUMES
> 
>    gEfiMdeModulePkgTokenSpaceGuid.PcdVariableCollectStatistics            ##
> CONSUMES
> 
> 
> 
> +[Pcd]
> 
> +
> gEfiMdeModulePkgTokenSpaceGuid.PcdAllowVariablePolicyEnforcementDis
> able     ## CONSUMES
> 
> +
> 
>  [Guids]
> 
>    ## PRODUCES             ## GUID # Signature of Variable store header
> 
>    ## CONSUMES             ## GUID # Signature of Variable store header
> 
> @@ -99,6 +107,8 @@ [Guids]
>    ## SOMETIMES_CONSUMES   ## Variable:L"dbt"
> 
>    gEfiImageSecurityDatabaseGuid
> 
> 
> 
> +  gVarCheckPolicyLibMmiHandlerGuid
> 
> +
> 
>  [Depex]
> 
>    gEfiMmCommunication2ProtocolGuid
> 
> 
> 
> --
> 2.26.2.windows.1.8.g01c50adf56.20200515075929
> 
> 
> -=-=-=-=-=-=
> Groups.io Links: You receive all messages sent to this group.
> 
> View/Reply Online (#61585): https://edk2.groups.io/g/devel/message/61585
> Mute This Topic: https://groups.io/mt/75057694/1768738
> Group Owner: devel+owner@edk2.groups.io
> Unsubscribe: https://edk2.groups.io/g/devel/unsub  [dandan.bi@intel.com]
> -=-=-=-=-=-=


^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [edk2-devel] [PATCH v6 04/14] MdeModulePkg: Define the VarCheckPolicyLib and SMM interface
  2020-06-23  6:40 ` [PATCH v6 04/14] MdeModulePkg: Define the VarCheckPolicyLib and SMM interface Bret Barkelew
@ 2020-07-02  2:13   ` Dandan Bi
  2020-07-02  6:41     ` Bret Barkelew
  0 siblings, 1 reply; 48+ messages in thread
From: Dandan Bi @ 2020-07-02  2:13 UTC (permalink / raw)
  To: devel@edk2.groups.io, bret@corthon.com
  Cc: Wang, Jian J, Wu, Hao A, Gao, Liming

1 comment inline, please check.



Thanks,
Dandan
> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Bret
> Barkelew
> Sent: Tuesday, June 23, 2020 2:41 PM
> To: devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>;
> Gao, Liming <liming.gao@intel.com>
> Subject: [edk2-devel] [PATCH v6 04/14] MdeModulePkg: Define the
> VarCheckPolicyLib and SMM interface
> 
> https://bugzilla.tianocore.org/show_bug.cgi?id=2522
> 
> VariablePolicy is an updated interface to
> replace VarLock and VarCheckProtocol.
> 
> This is an instance of a VarCheckLib that is backed by the
> VariablePolicyLib business logic. It also publishes the SMM
> calling interface for messages from the DXE protocol.
> 
> Cc: Jian J Wang <jian.j.wang@intel.com>
> Cc: Hao A Wu <hao.a.wu@intel.com>
> Cc: Liming Gao <liming.gao@intel.com>
> Cc: Bret Barkelew <brbarkel@microsoft.com>
> Signed-off-by: Bret Barkelew <brbarkel@microsoft.com>
> ---
>  MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.c   | 320
> ++++++++++++++++++++
>  MdeModulePkg/Include/Guid/VarCheckPolicyMmi.h                |  54 ++++
>  MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.inf |  42 +++
>  MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.uni |  12 +
>  MdeModulePkg/MdeModulePkg.dec                                |   4 +
>  MdeModulePkg/MdeModulePkg.dsc                                |   2 +
>  6 files changed, 434 insertions(+)
> 
> diff --git a/MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.c
> b/MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.c
> new file mode 100644
> index 000000000000..b64fc5f45332
> --- /dev/null
> +++ b/MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.c
> @@ -0,0 +1,320 @@
> +/** @file -- VarCheckPolicyLib.c
> 
> +This is an instance of a VarCheck lib that leverages the business logic behind
1.[Dandan]: This should be a NULL class library, not an instance of VarCheck Lib.

> 
> +the VariablePolicy code to make its decisions.
> 
> +
> 
> +Copyright (c) Microsoft Corporation.
> 
> +SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +
> 
> +**/
> 
> +
> 
> +#include <Library/VarCheckLib.h>
> 
> +#include <Library/BaseLib.h>
> 
> +#include <Library/DebugLib.h>
> 
> +#include <Library/SafeIntLib.h>
> 
> +#include <Library/MmServicesTableLib.h>
> 
> +#include <Library/BaseMemoryLib.h>
> 
> +#include <Library/MemoryAllocationLib.h>
> 
> +
> 
> +#include <Protocol/MmCommunication.h>
> 
> +
> 
> +#include <Protocol/VariablePolicy.h>
> 
> +#include <Library/VariablePolicyLib.h>
> 
> +
> 
> +#include <Guid/VarCheckPolicyMmi.h>
> 
> +
> 
> +//================================================
> 
> +// As a VarCheck library, we're linked into the VariableServices
> 
> +// and may not be able to call them indirectly. To get around this,
> 
> +// use the internal GetVariable function to query the variable store.
> 
> +//================================================
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +VariableServiceGetVariable (
> 
> +  IN      CHAR16            *VariableName,
> 
> +  IN      EFI_GUID          *VendorGuid,
> 
> +  OUT     UINT32            *Attributes OPTIONAL,
> 
> +  IN OUT  UINTN             *DataSize,
> 
> +  OUT     VOID              *Data
> 
> +  );
> 
> +
> 
> +
> 
> +/**
> 
> +  MM Communication Handler to recieve commands from the DXE protocol
> for
> 
> +  Variable Policies. This communication channel is used to register new
> policies
> 
> +  and poll and toggle the enforcement of variable policies.
> 
> +
> 
> +  @param[in]      DispatchHandle      All parameters standard to MM
> communications convention.
> 
> +  @param[in]      RegisterContext     All parameters standard to MM
> communications convention.
> 
> +  @param[in,out]  CommBuffer          All parameters standard to MM
> communications convention.
> 
> +  @param[in,out]  CommBufferSize      All parameters standard to MM
> communications convention.
> 
> +
> 
> +  @retval     EFI_SUCCESS
> 
> +  @retval     EFI_INVALID_PARAMETER   CommBuffer or CommBufferSize is
> null pointer.
> 
> +  @retval     EFI_INVALID_PARAMETER   CommBuffer size is wrong.
> 
> +  @retval     EFI_INVALID_PARAMETER   Revision or signature don't match.
> 
> +
> 
> +**/
> 
> +STATIC
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +VarCheckPolicyLibMmiHandler (
> 
> +  IN     EFI_HANDLE                   DispatchHandle,
> 
> +  IN     CONST VOID                   *RegisterContext,
> 
> +  IN OUT VOID                         *CommBuffer,
> 
> +  IN OUT UINTN                        *CommBufferSize
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS                                Status;
> 
> +  EFI_STATUS                                SubCommandStatus;
> 
> +  VAR_CHECK_POLICY_COMM_HEADER              *PolicyCommmHeader;
> 
> +  VAR_CHECK_POLICY_COMM_IS_ENABLED_PARAMS   *IsEnabledParams;
> 
> +  VAR_CHECK_POLICY_COMM_DUMP_PARAMS         *DumpParams;
> 
> +  UINT8                                     *DumpInputBuffer;
> 
> +  UINT8                                     *DumpOutputBuffer;
> 
> +  UINTN                                     DumpTotalPages;
> 
> +  VARIABLE_POLICY_ENTRY                     *PolicyEntry;
> 
> +  UINTN                                     ExpectedSize;
> 
> +  // Pagination Cache Variables
> 
> +  static UINT8                              *PaginationCache = NULL;
> 
> +  static UINTN                              PaginationCacheSize = 0;
> 
> +  static UINT32                             CurrentPaginationCommand = 0;
> 
> +
> 
> +  Status = EFI_SUCCESS;
> 
> +
> 
> +  //
> 
> +  // Validate some input parameters.
> 
> +  //
> 
> +  // If either of the pointers are NULL, we can't proceed.
> 
> +  if (CommBuffer == NULL || CommBufferSize == NULL) {
> 
> +    DEBUG(( DEBUG_INFO, "%a - Invalid comm buffer pointers!\n",
> __FUNCTION__ ));
> 
> +    return EFI_INVALID_PARAMETER;
> 
> +  }
> 
> +  // If the size does not meet a minimum threshold, we cannot proceed.
> 
> +  ExpectedSize = sizeof(VAR_CHECK_POLICY_COMM_HEADER);
> 
> +  if (*CommBufferSize < ExpectedSize) {
> 
> +    DEBUG(( DEBUG_INFO, "%a - Bad comm buffer size! %d < %d\n",
> __FUNCTION__, *CommBufferSize, ExpectedSize ));
> 
> +    return EFI_INVALID_PARAMETER;
> 
> +  }
> 
> +  // Check the revision and the signature of the comm header.
> 
> +  PolicyCommmHeader = CommBuffer;
> 
> +  if (PolicyCommmHeader->Signature != VAR_CHECK_POLICY_COMM_SIG
> ||
> 
> +      PolicyCommmHeader->Revision !=
> VAR_CHECK_POLICY_COMM_REVISION) {
> 
> +    DEBUG(( DEBUG_INFO, "%a - Signature or revision are incorrect!\n",
> __FUNCTION__ ));
> 
> +    // We have verified the buffer is not null and have enough size to hold
> Result field.
> 
> +    PolicyCommmHeader->Result = EFI_INVALID_PARAMETER;
> 
> +    return EFI_SUCCESS;
> 
> +  }
> 
> +
> 
> +  // If we're in the middle of a paginated dump and any other command is
> sent,
> 
> +  // pagination cache must be cleared.
> 
> +  if (PaginationCache != NULL && PolicyCommmHeader->Command !=
> CurrentPaginationCommand) {
> 
> +    FreePool (PaginationCache);
> 
> +    PaginationCache = NULL;
> 
> +    PaginationCacheSize = 0;
> 
> +    CurrentPaginationCommand = 0;
> 
> +  }
> 
> +
> 
> +  //
> 
> +  // Now we can process the command as it was sent.
> 
> +  //
> 
> +  PolicyCommmHeader->Result = EFI_ABORTED;    // Set a default return for
> incomplete commands.
> 
> +  switch(PolicyCommmHeader->Command) {
> 
> +    case VAR_CHECK_POLICY_COMMAND_DISABLE:
> 
> +      PolicyCommmHeader->Result = DisableVariablePolicy();
> 
> +      break;
> 
> +
> 
> +    case VAR_CHECK_POLICY_COMMAND_IS_ENABLED:
> 
> +      // Make sure that we're dealing with a reasonable size.
> 
> +      // This add should be safe because these are fixed sizes so far.
> 
> +      ExpectedSize +=
> sizeof(VAR_CHECK_POLICY_COMM_IS_ENABLED_PARAMS);
> 
> +      if (*CommBufferSize < ExpectedSize) {
> 
> +        DEBUG(( DEBUG_INFO, "%a - Bad comm buffer size! %d < %d\n",
> __FUNCTION__, *CommBufferSize, ExpectedSize ));
> 
> +        PolicyCommmHeader->Result = EFI_INVALID_PARAMETER;
> 
> +        break;
> 
> +      }
> 
> +
> 
> +      // Now that we know we've got a valid size, we can fill in the rest of the
> data.
> 
> +      IsEnabledParams =
> (VAR_CHECK_POLICY_COMM_IS_ENABLED_PARAMS*)((UINT8*)CommBuff
> er + sizeof(VAR_CHECK_POLICY_COMM_HEADER));
> 
> +      IsEnabledParams->State = IsVariablePolicyEnabled();
> 
> +      PolicyCommmHeader->Result = EFI_SUCCESS;
> 
> +      break;
> 
> +
> 
> +    case VAR_CHECK_POLICY_COMMAND_REGISTER:
> 
> +      // Make sure that we're dealing with a reasonable size.
> 
> +      // This add should be safe because these are fixed sizes so far.
> 
> +      ExpectedSize += sizeof(VARIABLE_POLICY_ENTRY);
> 
> +      if (*CommBufferSize < ExpectedSize) {
> 
> +        DEBUG(( DEBUG_INFO, "%a - Bad comm buffer size! %d < %d\n",
> __FUNCTION__, *CommBufferSize, ExpectedSize ));
> 
> +        PolicyCommmHeader->Result = EFI_INVALID_PARAMETER;
> 
> +        break;
> 
> +      }
> 
> +
> 
> +      // At the very least, we can assume that we're working with a valid policy
> entry.
> 
> +      // Time to compare its internal size.
> 
> +      PolicyEntry = (VARIABLE_POLICY_ENTRY*)((UINT8*)CommBuffer +
> sizeof(VAR_CHECK_POLICY_COMM_HEADER));
> 
> +      if (PolicyEntry->Version != VARIABLE_POLICY_ENTRY_REVISION ||
> 
> +          PolicyEntry->Size < sizeof(VARIABLE_POLICY_ENTRY) ||
> 
> +
> EFI_ERROR(SafeUintnAdd(sizeof(VAR_CHECK_POLICY_COMM_HEADER),
> PolicyEntry->Size, &ExpectedSize)) ||
> 
> +          *CommBufferSize < ExpectedSize) {
> 
> +        DEBUG(( DEBUG_INFO, "%a - Bad policy entry contents!\n",
> __FUNCTION__ ));
> 
> +        PolicyCommmHeader->Result = EFI_INVALID_PARAMETER;
> 
> +        break;
> 
> +      }
> 
> +
> 
> +      PolicyCommmHeader->Result = RegisterVariablePolicy( PolicyEntry );
> 
> +      break;
> 
> +
> 
> +    case VAR_CHECK_POLICY_COMMAND_DUMP:
> 
> +      // Make sure that we're dealing with a reasonable size.
> 
> +      // This add should be safe because these are fixed sizes so far.
> 
> +      ExpectedSize += sizeof(VAR_CHECK_POLICY_COMM_DUMP_PARAMS)
> + VAR_CHECK_POLICY_MM_DUMP_BUFFER_SIZE;
> 
> +      if (*CommBufferSize < ExpectedSize) {
> 
> +        DEBUG(( DEBUG_INFO, "%a - Bad comm buffer size! %d < %d\n",
> __FUNCTION__, *CommBufferSize, ExpectedSize ));
> 
> +        PolicyCommmHeader->Result = EFI_INVALID_PARAMETER;
> 
> +        break;
> 
> +      }
> 
> +
> 
> +      // Now that we know we've got a valid size, we can fill in the rest of the
> data.
> 
> +      DumpParams =
> (VAR_CHECK_POLICY_COMM_DUMP_PARAMS*)(PolicyCommmHeader + 1);
> 
> +
> 
> +      // If we're requesting the first page, initialize the cache and get the sizes.
> 
> +      if (DumpParams->PageRequested == 0) {
> 
> +        if (PaginationCache != NULL) {
> 
> +          FreePool (PaginationCache);
> 
> +          PaginationCache = NULL;
> 
> +        }
> 
> +
> 
> +        // Determine what the required size is going to be.
> 
> +        DumpParams->TotalSize = 0;
> 
> +        DumpParams->PageSize = 0;
> 
> +        DumpParams->HasMore = FALSE;
> 
> +        SubCommandStatus = DumpVariablePolicy (NULL, &DumpParams-
> >TotalSize);
> 
> +        if (SubCommandStatus == EFI_BUFFER_TOO_SMALL && DumpParams-
> >TotalSize > 0) {
> 
> +          CurrentPaginationCommand =
> VAR_CHECK_POLICY_COMMAND_DUMP;
> 
> +          PaginationCacheSize = DumpParams->TotalSize;
> 
> +          PaginationCache = AllocatePool (PaginationCacheSize);
> 
> +          if (PaginationCache == NULL) {
> 
> +            SubCommandStatus = EFI_OUT_OF_RESOURCES;
> 
> +          }
> 
> +        }
> 
> +
> 
> +        // If we've allocated our pagination cache, we're good to cache.
> 
> +        if (PaginationCache != NULL) {
> 
> +          SubCommandStatus = DumpVariablePolicy (PaginationCache,
> &DumpParams->TotalSize);
> 
> +        }
> 
> +
> 
> +        // Populate the remaining fields and we can boogie.
> 
> +        if (!EFI_ERROR (SubCommandStatus) && PaginationCache != NULL) {
> 
> +          DumpParams->HasMore = TRUE;
> 
> +        }
> 
> +      }
> 
> +      else if (PaginationCache != NULL) {
> 
> +        DumpParams->TotalSize = (UINT32)PaginationCacheSize;
> 
> +        DumpParams->PageSize =
> VAR_CHECK_POLICY_MM_DUMP_BUFFER_SIZE;
> 
> +        DumpOutputBuffer = (UINT8*)(DumpParams + 1);
> 
> +
> 
> +        // Make sure that we don't over-index the cache.
> 
> +        DumpTotalPages = PaginationCacheSize / DumpParams->PageSize;
> 
> +        if (PaginationCacheSize % DumpParams->PageSize) DumpTotalPages++;
> 
> +        if (DumpParams->PageRequested > DumpTotalPages) {
> 
> +          SubCommandStatus = EFI_INVALID_PARAMETER;
> 
> +        }
> 
> +        else {
> 
> +          // Figure out how far into the page cache we need to go for our next
> page.
> 
> +          // We know the blind subtraction won't be bad because we already
> checked for page 0.
> 
> +          DumpInputBuffer = &PaginationCache[DumpParams->PageSize *
> (DumpParams->PageRequested - 1)];
> 
> +          // If we're getting the last page, adjust the PageSize.
> 
> +          if (DumpParams->PageRequested == DumpTotalPages) {
> 
> +            DumpParams->PageSize = PaginationCacheSize % DumpParams-
> >PageSize;
> 
> +          }
> 
> +          CopyMem (DumpOutputBuffer, DumpInputBuffer, DumpParams-
> >PageSize);
> 
> +          // If we just got the last page, settle up the cache.
> 
> +          if (DumpParams->PageRequested == DumpTotalPages) {
> 
> +            DumpParams->HasMore = FALSE;
> 
> +            FreePool (PaginationCache);
> 
> +            PaginationCache = NULL;
> 
> +            PaginationCacheSize = 0;
> 
> +            CurrentPaginationCommand = 0;
> 
> +          }
> 
> +          // Otherwise, we could do more here.
> 
> +          else {
> 
> +            DumpParams->HasMore = TRUE;
> 
> +          }
> 
> +
> 
> +          // If we made it this far, we're basically good.
> 
> +          SubCommandStatus = EFI_SUCCESS;
> 
> +        }
> 
> +      }
> 
> +      // If we've requested any other page than 0 and the cache is empty, we
> must have timed out.
> 
> +      else {
> 
> +        DumpParams->TotalSize = 0;
> 
> +        DumpParams->PageSize = 0;
> 
> +        DumpParams->HasMore = FALSE;
> 
> +        SubCommandStatus = EFI_TIMEOUT;
> 
> +      }
> 
> +
> 
> +      // There's currently no use for this, but it shouldn't be hard to implement.
> 
> +      PolicyCommmHeader->Result = SubCommandStatus;
> 
> +      break;
> 
> +
> 
> +    case VAR_CHECK_POLICY_COMMAND_LOCK:
> 
> +      PolicyCommmHeader->Result = LockVariablePolicy();
> 
> +      break;
> 
> +
> 
> +    default:
> 
> +      // Mark unknown requested command as EFI_UNSUPPORTED.
> 
> +      DEBUG(( DEBUG_INFO, "%a - Invalid command requested! %d\n",
> __FUNCTION__, PolicyCommmHeader->Command ));
> 
> +      PolicyCommmHeader->Result = EFI_UNSUPPORTED;
> 
> +      break;
> 
> +  }
> 
> +
> 
> +  DEBUG(( DEBUG_VERBOSE, "%a - Command %d returning %r.\n",
> __FUNCTION__,
> 
> +          PolicyCommmHeader->Command, PolicyCommmHeader->Result ));
> 
> +
> 
> +  return Status;
> 
> +}
> 
> +
> 
> +
> 
> +/**
> 
> +  Constructor function of VarCheckPolicyLib to register VarCheck handler
> and
> 
> +  SW MMI handlers.
> 
> +
> 
> +  @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 constructor executed correctly.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +VarCheckPolicyLibConstructor (
> 
> +  IN EFI_HANDLE             ImageHandle,
> 
> +  IN EFI_SYSTEM_TABLE       *SystemTable
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS    Status;
> 
> +  EFI_HANDLE    DiscardedHandle;
> 
> +
> 
> +  // Initialize the business logic with the internal GetVariable handler.
> 
> +  Status = InitVariablePolicyLib( VariableServiceGetVariable );
> 
> +
> 
> +  // Only proceed with init if the business logic could be initialized.
> 
> +  if (!EFI_ERROR( Status )) {
> 
> +    // Register the VarCheck handler for SetVariable filtering.
> 
> +    // Forward the check to the business logic of the library.
> 
> +    VarCheckLibRegisterSetVariableCheckHandler( ValidateSetVariable );
> 
> +
> 
> +    // Register the MMI handlers for receiving policy commands.
> 
> +    DiscardedHandle = NULL;
> 
> +    Status = gMmst->MmiHandlerRegister( VarCheckPolicyLibMmiHandler,
> 
> +                                        &gVarCheckPolicyLibMmiHandlerGuid,
> 
> +                                        &DiscardedHandle );
> 
> +  }
> 
> +  // Otherwise, there's not much we can do.
> 
> +  else {
> 
> +    DEBUG(( DEBUG_ERROR, "%a - Cannot Initialize VariablePolicyLib! %r\n",
> __FUNCTION__, Status ));
> 
> +    ASSERT_EFI_ERROR( Status );
> 
> +  }
> 
> +
> 
> +  return Status;
> 
> +}
> 
> diff --git a/MdeModulePkg/Include/Guid/VarCheckPolicyMmi.h
> b/MdeModulePkg/Include/Guid/VarCheckPolicyMmi.h
> new file mode 100644
> index 000000000000..77bcc62f3ccf
> --- /dev/null
> +++ b/MdeModulePkg/Include/Guid/VarCheckPolicyMmi.h
> @@ -0,0 +1,54 @@
> +/** @file -- VarCheckPolicyMmiCommon.h
> 
> +This header contains communication definitions that are shared between
> DXE
> 
> +and the MM component of VarCheckPolicy.
> 
> +
> 
> +Copyright (c) Microsoft Corporation.
> 
> +SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +**/
> 
> +
> 
> +#ifndef _VAR_CHECK_POLICY_MMI_COMMON_H_
> 
> +#define _VAR_CHECK_POLICY_MMI_COMMON_H_
> 
> +
> 
> +#define   VAR_CHECK_POLICY_COMM_SIG       SIGNATURE_32('V', 'C', 'P', 'C')
> 
> +#define   VAR_CHECK_POLICY_COMM_REVISION  1
> 
> +
> 
> +#pragma pack(push, 1)
> 
> +
> 
> +typedef struct _VAR_CHECK_POLICY_COMM_HEADER {
> 
> +  UINT32      Signature;
> 
> +  UINT32      Revision;
> 
> +  UINT32      Command;
> 
> +  EFI_STATUS  Result;
> 
> +} VAR_CHECK_POLICY_COMM_HEADER;
> 
> +
> 
> +typedef struct _VAR_CHECK_POLICY_COMM_IS_ENABLED_PARAMS {
> 
> +  BOOLEAN     State;
> 
> +} VAR_CHECK_POLICY_COMM_IS_ENABLED_PARAMS;
> 
> +
> 
> +typedef struct _VAR_CHECK_POLICY_COMM_DUMP_PARAMS {
> 
> +  UINT32      PageRequested;
> 
> +  UINT32      TotalSize;
> 
> +  UINT32      PageSize;
> 
> +  BOOLEAN     HasMore;
> 
> +} VAR_CHECK_POLICY_COMM_DUMP_PARAMS;
> 
> +
> 
> +#pragma pack(pop)
> 
> +
> 
> +// Make sure that we will hold at least the headers.
> 
> +#define   VAR_CHECK_POLICY_MM_COMM_BUFFER_SIZE
> MAX((OFFSET_OF(EFI_MM_COMMUNICATE_HEADER, Data) + sizeof
> (VAR_CHECK_POLICY_COMM_HEADER) + EFI_PAGES_TO_SIZE(1)),
> EFI_PAGES_TO_SIZE(4))
> 
> +#define   VAR_CHECK_POLICY_MM_DUMP_BUFFER_SIZE
> (VAR_CHECK_POLICY_MM_COMM_BUFFER_SIZE - \
> 
> +                                                    (OFFSET_OF(EFI_MM_COMMUNICATE_HEADER,
> Data) + \
> 
> +                                                      sizeof(VAR_CHECK_POLICY_COMM_HEADER) + \
> 
> +
> sizeof(VAR_CHECK_POLICY_COMM_DUMP_PARAMS)))
> 
> +STATIC_ASSERT (
> 
> +  VAR_CHECK_POLICY_MM_DUMP_BUFFER_SIZE <
> VAR_CHECK_POLICY_MM_COMM_BUFFER_SIZE,
> 
> +  "an integer underflow may have occurred calculating
> VAR_CHECK_POLICY_MM_DUMP_BUFFER_SIZE"
> 
> +  );
> 
> +
> 
> +#define   VAR_CHECK_POLICY_COMMAND_DISABLE      0x0001
> 
> +#define   VAR_CHECK_POLICY_COMMAND_IS_ENABLED   0x0002
> 
> +#define   VAR_CHECK_POLICY_COMMAND_REGISTER     0x0003
> 
> +#define   VAR_CHECK_POLICY_COMMAND_DUMP         0x0004
> 
> +#define   VAR_CHECK_POLICY_COMMAND_LOCK         0x0005
> 
> +
> 
> +#endif // _VAR_CHECK_POLICY_MMI_COMMON_H_
> 
> diff --git a/MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.inf
> b/MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.inf
> new file mode 100644
> index 000000000000..077bcc8990ca
> --- /dev/null
> +++ b/MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.inf
> @@ -0,0 +1,42 @@
> +## @file VarCheckPolicyLib.inf
> 
> +# This is an instance of a VarCheck lib that leverages the business logic
> behind
> 
> +# the VariablePolicy code to make its decisions.
> 
> +#
> 
> +# Copyright (c) Microsoft Corporation.
> 
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +##
> 
> +
> 
> +[Defines]
> 
> +  INF_VERSION                    = 0x00010005
> 
> +  BASE_NAME                      = VarCheckPolicyLib
> 
> +  FILE_GUID                      = 9C28A48F-C884-4B1F-8B95-DEF125448023
> 
> +  MODULE_TYPE                    = DXE_RUNTIME_DRIVER
> 
> +  VERSION_STRING                 = 1.0
> 
> +  LIBRARY_CLASS                  = NULL|DXE_RUNTIME_DRIVER
> DXE_SMM_DRIVER
> 
> +  CONSTRUCTOR                    = VarCheckPolicyLibConstructor
> 
> +
> 
> +
> 
> +[Sources]
> 
> +  VarCheckPolicyLib.c
> 
> +
> 
> +
> 
> +[Packages]
> 
> +  MdePkg/MdePkg.dec
> 
> +  MdeModulePkg/MdeModulePkg.dec
> 
> +
> 
> +
> 
> +[LibraryClasses]
> 
> +  BaseLib
> 
> +  DebugLib
> 
> +  BaseMemoryLib
> 
> +  DxeServicesLib
> 
> +  MemoryAllocationLib
> 
> +  VarCheckLib
> 
> +  VariablePolicyLib
> 
> +  VariablePolicyHelperLib
> 
> +  SafeIntLib
> 
> +  MmServicesTableLib
> 
> +
> 
> +
> 
> +[Guids]
> 
> +  gVarCheckPolicyLibMmiHandlerGuid        ## CONSUME ## Used to register
> for MM Communication events.
> 
> diff --git a/MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.uni
> b/MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.uni
> new file mode 100644
> index 000000000000..eedeeed15d31
> --- /dev/null
> +++ b/MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.uni
> @@ -0,0 +1,12 @@
> +// /** @file
> 
> +// VarCheckPolicyLib.uni
> 
> +//
> 
> +// Copyright (c) Microsoft Corporation.
> 
> +// SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +//
> 
> +// **/
> 
> +
> 
> +
> 
> +#string STR_MODULE_ABSTRACT             #language en-US "NULL library
> implementation that conforms to the VarCheck interface to allow
> VariablePolicy engine to enforce policies"
> 
> +
> 
> +#string STR_MODULE_DESCRIPTION          #language en-US "NULL library
> implementation that conforms to the VarCheck interface to allow
> VariablePolicy engine to enforce policies"
> 
> diff --git a/MdeModulePkg/MdeModulePkg.dec
> b/MdeModulePkg/MdeModulePkg.dec
> index b21cd78c8787..9a3c9fe642d3 100644
> --- a/MdeModulePkg/MdeModulePkg.dec
> +++ b/MdeModulePkg/MdeModulePkg.dec
> @@ -385,6 +385,10 @@ [Guids]
>    ## Include/Guid/EndofS3Resume.h
> 
>    gEdkiiEndOfS3ResumeGuid = { 0x96f5296d, 0x05f7, 0x4f3c, {0x84, 0x67, 0xe4,
> 0x56, 0x89, 0x0e, 0x0c, 0xb5 } }
> 
> 
> 
> +  ## Used (similar to Variable Services) to communicate policies to the
> enforcement engine.
> 
> +  # {DA1B0D11-D1A7-46C4-9DC9-F3714875C6EB}
> 
> +  gVarCheckPolicyLibMmiHandlerGuid = { 0xda1b0d11, 0xd1a7, 0x46c4,
> { 0x9d, 0xc9, 0xf3, 0x71, 0x48, 0x75, 0xc6, 0xeb }}
> 
> +
> 
>    ## Include/Guid/S3SmmInitDone.h
> 
>    gEdkiiS3SmmInitDoneGuid = { 0x8f9d4825, 0x797d, 0x48fc, { 0x84, 0x71,
> 0x84, 0x50, 0x25, 0x79, 0x2e, 0xf6 } }
> 
> 
> 
> diff --git a/MdeModulePkg/MdeModulePkg.dsc
> b/MdeModulePkg/MdeModulePkg.dsc
> index 37795b9e4f58..f0a75a3b337b 100644
> --- a/MdeModulePkg/MdeModulePkg.dsc
> +++ b/MdeModulePkg/MdeModulePkg.dsc
> @@ -313,6 +313,7 @@ [Components]
>    MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf
> 
>    MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf
> 
>    MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf
> 
> +  MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.inf
> 
>    MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf
> 
>    MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLib.inf
> 
>    MdeModulePkg/Library/VarCheckPcdLib/VarCheckPcdLib.inf
> 
> @@ -458,6 +459,7 @@ [Components.IA32, Components.X64]
>    MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf
> 
>    MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf {
> 
>      <LibraryClasses>
> 
> +      NULL|MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.inf
> 
>        NULL|MdeModulePkg/Library/VarCheckUefiLib/VarCheckUefiLib.inf
> 
>        NULL|MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLib.inf
> 
>        NULL|MdeModulePkg/Library/VarCheckPcdLib/VarCheckPcdLib.inf
> 
> --
> 2.26.2.windows.1.8.g01c50adf56.20200515075929
> 
> 
> -=-=-=-=-=-=
> Groups.io Links: You receive all messages sent to this group.
> 
> View/Reply Online (#61590): https://edk2.groups.io/g/devel/message/61590
> Mute This Topic: https://groups.io/mt/75057699/1768738
> Group Owner: devel+owner@edk2.groups.io
> Unsubscribe: https://edk2.groups.io/g/devel/unsub  [dandan.bi@intel.com]
> -=-=-=-=-=-=


^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [edk2-devel] [PATCH v6 02/14] MdeModulePkg: Define the VariablePolicyLib
  2020-06-23  6:40 ` [PATCH v6 02/14] MdeModulePkg: Define the VariablePolicyLib Bret Barkelew
@ 2020-07-02  2:13   ` Dandan Bi
  2020-07-02  7:16     ` Bret Barkelew
  0 siblings, 1 reply; 48+ messages in thread
From: Dandan Bi @ 2020-07-02  2:13 UTC (permalink / raw)
  To: devel@edk2.groups.io, bret@corthon.com
  Cc: Wang, Jian J, Wu, Hao A, Gao, Liming

4 comments inline, please check.

Thanks,
Dandan
> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Bret
> Barkelew
> Sent: Tuesday, June 23, 2020 2:41 PM
> To: devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>;
> Gao, Liming <liming.gao@intel.com>
> Subject: [edk2-devel] [PATCH v6 02/14] MdeModulePkg: Define the
> VariablePolicyLib
> 
> 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>
> Cc: Bret Barkelew <brbarkel@microsoft.com>
> Signed-off-by: Bret Barkelew <brbarkel@microsoft.com>
> ---
>  MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitNull.c
> |   46 +
> 
> MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitRuntimeDx
> e.c               |   85 +
>  MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c
> |  816 +++++++
> 
> MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePo
> licyUnitTest.c   | 2436 ++++++++++++++++++++
>  MdeModulePkg/Include/Library/VariablePolicyLib.h                                         |
> 207 ++
>  MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf
> |   44 +
>  MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.uni
> |   12 +
>  MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf
> |   51 +
> 
> MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePo
> licyUnitTest.inf |   40 +
>  MdeModulePkg/MdeModulePkg.dec                                                            |    3 +
>  MdeModulePkg/MdeModulePkg.dsc                                                            |    5 +
>  MdeModulePkg/Test/MdeModulePkgHostTest.dsc                                               |
> 11 +
>  12 files changed, 3756 insertions(+)
> 
> diff --git
> a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitNull.c
> b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitNull.c
> new file mode 100644
> index 000000000000..ad2ee0b2fb8f
> --- /dev/null
> +++
> b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitNull.c
> @@ -0,0 +1,46 @@
> +/** @file -- VariablePolicyExtraInitNull.c
> 
> +This file contains extra init and deinit routines that don't do anything
> 
> +extra.
> 
> +
> 
> +Copyright (c) Microsoft Corporation.
> 
> +SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +
> 
> +**/
> 
> +
> 
> +#include <Library/UefiRuntimeServicesTableLib.h>
> 
> +
> 
> +
> 
> +/**
> 
> +  An extra init hook that enables the RuntimeDxe library instance to
> 
> +  register VirtualAddress change callbacks. Among other things.
> 
> +
> 
> +  @retval     EFI_SUCCESS   Everything is good. Continue with init.
> 
> +  @retval     Others        Uh... don't continue.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +VariablePolicyExtraInit (
> 
> +  VOID
> 
> +  )
> 
> +{
> 
> +  // NULL implementation.
> 
> +  return EFI_SUCCESS;
> 
> +}
> 
> +
> 
> +
> 
> +/**
> 
> +  An extra deinit hook that enables the RuntimeDxe library instance to
> 
> +  register VirtualAddress change callbacks. Among other things.
> 
> +
> 
> +  @retval     EFI_SUCCESS   Everything is good. Continue with deinit.
> 
> +  @retval     Others        Uh... don't continue.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +VariablePolicyExtraDeinit (
> 
> +  VOID
> 
> +  )
> 
> +{
> 
> +  // NULL implementation.
> 
> +  return EFI_SUCCESS;
> 
> +}
> 
> diff --git
> a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitRuntimeD
> xe.c
> b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitRuntime
> Dxe.c
> new file mode 100644
> index 000000000000..3ca87048b14b
> --- /dev/null
> +++
> b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitRuntime
> Dxe.c
> @@ -0,0 +1,85 @@
> +/** @file -- VariablePolicyExtraInitRuntimeDxe.c
> 
> +This file contains extra init and deinit routines that register and unregister
> 
> +VariableAddressChange callbacks.
> 
> +
> 
> +Copyright (c) Microsoft Corporation.
> 
> +SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +
> 
> +**/
> 
> +
> 
> +#include <Library/UefiBootServicesTableLib.h>
> 
> +#include <Library/UefiRuntimeServicesTableLib.h>
> 
> +
> 
> +extern EFI_GET_VARIABLE   mGetVariableHelper;
> 
> +extern UINT8              *mPolicyTable;
> 
> +STATIC BOOLEAN            mIsVirtualAddrConverted;
> 
> +STATIC EFI_EVENT          mVariablePolicyLibVirtualAddressChangeEvent  =
> NULL;
> 
> +
> 
> +/**
> 
> +  For the RuntimeDxe version of this lib, convert internal pointer addresses
> to virtual addresses.
> 
> +
> 
> +  @param[in] Event      Event whose notification function is being invoked.
> 
> +  @param[in] Context    The pointer to the notification function's context,
> which
> 
> +                        is implementation-dependent.
> 
> +**/
> 
> +STATIC
> 
> +VOID
> 
> +EFIAPI
> 
> +VariablePolicyLibVirtualAddressCallback (
> 
> +  IN  EFI_EVENT   Event,
> 
> +  IN  VOID        *Context
> 
> +  )
> 
> +{
> 
> +  gRT->ConvertPointer (0, (VOID **)&mPolicyTable);
> 
> +  gRT->ConvertPointer (0, (VOID **)&mGetVariableHelper);
> 
> +  mIsVirtualAddrConverted = TRUE;
> 
> +}
> 
> +
> 
> +
> 
> +/**
> 
> +  An extra init hook that enables the RuntimeDxe library instance to
> 
> +  register VirtualAddress change callbacks. Among other things.
> 
> +
> 
> +  @retval     EFI_SUCCESS   Everything is good. Continue with init.
> 
> +  @retval     Others        Uh... don't continue.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +VariablePolicyExtraInit (
> 
> +  VOID
> 
> +  )
> 
> +{
> 
> +  return gBS->CreateEventEx (EVT_NOTIFY_SIGNAL,
> 
> +                              TPL_NOTIFY,
> 
> +                              VariablePolicyLibVirtualAddressCallback,
> 
> +                              NULL,
> 
> +                              &gEfiEventVirtualAddressChangeGuid,
> 
> +                              &mVariablePolicyLibVirtualAddressChangeEvent);
> 
> +}
> 
> +
> 
> +
> 
> +/**
> 
> +  An extra deinit hook that enables the RuntimeDxe library instance to
> 
> +  register VirtualAddress change callbacks. Among other things.
> 
> +
> 
> +  @retval     EFI_SUCCESS   Everything is good. Continue with deinit.
> 
> +  @retval     Others        Uh... don't continue.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +VariablePolicyExtraDeinit (
> 
> +  VOID
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS  Status;
> 
> +
> 
> +  Status = EFI_SUCCESS;
> 
> +  if (mIsVirtualAddrConverted) {
> 
> +    Status = gBS->CloseEvent
> (mVariablePolicyLibVirtualAddressChangeEvent);
> 
> +  }
> 
> +  else {
> 
> +    Status = EFI_SUCCESS;
> 
> +  }
> 
> +
> 
> +  return Status;
> 
> +}
> 
> diff --git a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c
> b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c
> new file mode 100644
> index 000000000000..84c794adaed9
> --- /dev/null
> +++ b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c
> @@ -0,0 +1,816 @@
> +/** @file -- VariablePolicyLib.c
> 
> +Business logic for Variable Policy enforcement.
> 
> +
> 
> +Copyright (c) Microsoft Corporation.
> 
> +SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +
> 
> +**/
> 
> +
> 
> +#include <Uefi.h>
> 
> +
> 
> +#include <Library/SafeIntLib.h>
> 
> +#include <Library/MemoryAllocationLib.h>
> 
> +#include <Library/BaseMemoryLib.h>
> 
> +#include <Library/DebugLib.h>
> 
> +#include <Library/PcdLib.h>
> 
> +
> 
> +#include <Protocol/VariablePolicy.h>
> 
> +#include <Library/VariablePolicyLib.h>
> 
> +
> 
> +
> 
> +// IMPORTANT NOTE: This library is currently rife with multiple return
> statements
> 
> +//                 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.
> 
> +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.
> 
> +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
> 
> +
> 
> +// ExtraInit/ExtraDeinit functions allow RuntimeDxe to register
> VirtualAddress callbacks.
> 
> +EFI_STATUS
> 
> +VariablePolicyExtraInit (
> 
> +  VOID
> 
> +  );
> 
> +
> 
> +EFI_STATUS
> 
> +VariablePolicyExtraDeinit (
> 
> +  VOID
> 
> +  );

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

> 
> +
> 
> +
> 
> +/**
> 
> +  This helper function determines whether the structure of an incoming
> policy
> 
> +  is valid and internally consistent.
> 
> +
> 
> +  @param[in]  NewPolicy     Pointer to the incoming policy structure.
> 
> +
> 
> +  @retval     TRUE
> 
> +  @retval     FALSE   Pointer is NULL, size is wrong, strings are empty, or
> 
> +                      substructures overlap.
> 
> +
> 
> +**/
> 
> +STATIC
> 
> +BOOLEAN
> 
> +IsValidVariablePolicyStructure (
> 
> +  IN CONST VARIABLE_POLICY_ENTRY    *NewPolicy
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS    Status;
> 
> +  UINTN         EntryEnd;
> 
> +  CHAR16        *CheckChar;
> 
> +  UINTN         WildcardCount;
> 
> +
> 
> +  // Sanitize some quick values.
> 
> +  if (NewPolicy == 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;
> 
> +  CHAR16      *PolicyName;
> 
> +  UINT8       CalculatedPriority;
> 
> +  UINTN       Index;
> 
> +
> 
> +  Result = FALSE;
> 
> +  CalculatedPriority = MATCH_PRIORITY_EXACT;
> 
> +
> 
> +  // Step 1: If the GUID doesn't match, we're done. No need to evaluate
> anything else.
> 
> +  if (!CompareGuid( &EvalEntry->Namespace, VendorGuid )) {
> 
> +    goto Exit;
> 
> +  }
> 
> +
> 
> +  // If the GUID matches, check to see whether there is a Name 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 {
2. [Dandan]: About the coding style, could we make the" } " and "else {" at the same line? Which is aligned with current edk2 style.
> 
> +        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;
> 
> +  VARIABLE_POLICY_ENTRY   *CurrentEntry;
> 
> +  UINT8                   MatchPriority;
> 
> +  UINT8                   CurrentPriority;
> 
> +  UINTN                   Index;
> 
> +
> 
> +  BestResult = NULL;
> 
> +
> 
> +  // 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 )) {
> 
> +      // If match is better, take it.
> 
> +      if (BestResult == NULL || CurrentPriority < MatchPriority) {

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

> 
> +        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;
> 
> +  VARIABLE_LOCK_ON_VAR_STATE_POLICY   *StateVarPolicy;
> 
> +  CHAR16                              *StateVarName;
> 
> +  UINTN                               StateVarSize;
> 
> +  UINT8                               StateVar;
> 
> +
> 
> +  ReturnStatus = EFI_SUCCESS;
> 
> +
> 
> +  if (!IsVariablePolicyLibInitialized()) {
> 
> +    ReturnStatus = EFI_NOT_READY;
> 
> +    goto Exit;
> 
> +  }
> 
> +
> 
> +  // Bail if the protections are currently disabled.
> 
> +  if (mProtectionDisabled) {
> 
> +    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_WRITE_PROTECTED   Interface option is disabled by platform
> PCD.
> 
> +  @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;
> 
> +  }
> 
> +  if (!PcdGetBool (PcdAllowVariablePolicyEnforcementDisable)) {
> 
> +    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
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS    Status;
> 
> +
> 
> +  Status = EFI_SUCCESS;
> 
> +  if (mGetVariableHelper != NULL) {
> 
> +    Status = EFI_ALREADY_STARTED;

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

> 
> +  }
> 
> +
> 
> +  if (!EFI_ERROR( Status )) {
> 
> +    Status = VariablePolicyExtraInit();
> 
> +  }
> 
> +
> 
> +  if (!EFI_ERROR( Status )) {
> 
> +    // 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 Status;
> 
> +}
> 
> +
> 
> +
> 
> +/**
> 
> +  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
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS    Status;
> 
> +
> 
> +  Status = EFI_SUCCESS;
> 
> +
> 
> +  if (mGetVariableHelper == NULL) {
> 
> +    Status = EFI_NOT_READY;
> 
> +  }
> 
> +
> 
> +  if (!EFI_ERROR( Status )) {
> 
> +    Status = VariablePolicyExtraDeinit();
> 
> +  }
> 
> +
> 
> +  if (!EFI_ERROR( Status )) {
> 
> +    mGetVariableHelper = NULL;
> 
> +    mInterfaceLocked = FALSE;
> 
> +    mProtectionDisabled = FALSE;
> 
> +    mCurrentTableSize = 0;
> 
> +    mCurrentTableUsage = 0;
> 
> +    mCurrentTableCount = 0;
> 
> +
> 
> +    if (mPolicyTable != NULL) {
> 
> +      FreePool( mPolicyTable );
> 
> +      mPolicyTable = NULL;
> 
> +    }
> 
> +  }
> 
> +
> 
> +  return Status;
> 
> +}
> 
> diff --git
> a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/Variable
> PolicyUnitTest.c
> b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/Variable
> PolicyUnitTest.c
> new file mode 100644
> index 000000000000..f133f2f30e36
> --- /dev/null
> +++
> b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/Variable
> PolicyUnitTest.c
> @@ -0,0 +1,2436 @@
> +/** @file -- VariablePolicyUnitTest.c
> 
> +UnitTest for...
> 
> +Business logic for Variable Policy enforcement.
> 
> +
> 
> +Copyright (c) Microsoft Corporation.
> 
> +SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +
> 
> +**/
> 
> +
> 
> +#include <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
> ==========================================================
> =================
> 
> +
> 
> +/**
> 
> +  Helper function to initialize a VARIABLE_POLICY_ENTRY structure with a
> Name and StateName.
> 
> +
> 
> +  Takes care of all the messy packing.
> 
> +
> 
> +  @param[in,out]  Entry
> 
> +  @param[in]      Name        [Optional]
> 
> +  @param[in]      StateName   [Optional]
> 
> +
> 
> +  @retval     TRUE
> 
> +  @retval     FALSE
> 
> +
> 
> +**/
> 
> +STATIC
> 
> +BOOLEAN
> 
> +InitExpVarPolicyStrings (
> 
> +  EXPANDED_VARIABLE_POLICY_ENTRY      *Entry,
> 
> +  CHAR16                              *Name,      OPTIONAL
> 
> +  CHAR16                              *StateName  OPTIONAL
> 
> +  )
> 
> +{
> 
> +  UINTN     NameSize;
> 
> +  UINTN     StateNameSize;
> 
> +
> 
> +  NameSize = 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;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Mocked version of GetVariable, for testing.
> 
> +**/
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +StubGetVariableNull (
> 
> +  IN     CHAR16                      *VariableName,
> 
> +  IN     EFI_GUID                    *VendorGuid,
> 
> +  OUT    UINT32                      *Attributes,    OPTIONAL
> 
> +  IN OUT UINTN                       *DataSize,
> 
> +  OUT    VOID                        *Data           OPTIONAL
> 
> +  )
> 
> +{
> 
> +  UINT32      MockedAttr;
> 
> +  UINTN       MockedDataSize;
> 
> +  VOID        *MockedData;
> 
> +  EFI_STATUS  MockedReturn;
> 
> +
> 
> +  check_expected_ptr( VariableName );
> 
> +  check_expected_ptr( VendorGuid );
> 
> +  check_expected_ptr( DataSize );
> 
> +
> 
> +  MockedAttr = (UINT32)mock();
> 
> +  MockedDataSize = (UINTN)mock();
> 
> +  MockedData = (VOID*)mock();
> 
> +  MockedReturn = (EFI_STATUS)mock();
> 
> +
> 
> +  if (Attributes != NULL) {
> 
> +    *Attributes = MockedAttr;
> 
> +  }
> 
> +  if (Data != NULL && !EFI_ERROR(MockedReturn)) {
> 
> +    CopyMem( Data, MockedData, MockedDataSize );
> 
> +  }
> 
> +
> 
> +  *DataSize = MockedDataSize;
> 
> +
> 
> +  return MockedReturn;
> 
> +}
> 
> +
> 
> +//
> 
> +// Anything you think might be helpful that isn't a test itself.
> 
> +//
> 
> +
> 
> +/**
> 
> +  This is a common setup function that will ensure the library is always
> initialized
> 
> +  with the stubbed GetVariable.
> 
> +
> 
> +  Not used by all test cases, but by most.
> 
> +**/
> 
> +STATIC
> 
> +UNIT_TEST_STATUS
> 
> +LibInitMocked (
> 
> +  IN UNIT_TEST_CONTEXT      Context
> 
> +  )
> 
> +{
> 
> +  return EFI_ERROR(InitVariablePolicyLib( StubGetVariableNull )) ?
> UNIT_TEST_ERROR_PREREQUISITE_NOT_MET : UNIT_TEST_PASSED;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Common cleanup function to make sure that the library is always de-
> initialized prior
> 
> +  to the next test case.
> 
> +*/
> 
> +STATIC
> 
> +VOID
> 
> +LibCleanup (
> 
> +  IN UNIT_TEST_CONTEXT      Context
> 
> +  )
> 
> +{
> 
> +  DeinitVariablePolicyLib();
> 
> +}
> 
> +
> 
> +
> 
> +///=== TEST CASES
> ==========================================================
> =======================
> 
> +
> 
> +///===== ARCHITECTURAL SUITE
> ==================================================
> 
> +
> 
> +/**
> 
> +  Test Case
> 
> +*/
> 
> +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;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Test Case
> 
> +*/
> 
> +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;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Test Case
> 
> +*/
> 
> +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;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Test Case
> 
> +*/
> 
> +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
> 
> +  );
> 
> +
> 
> +/**
> 
> +  Test Case
> 
> +*/
> 
> +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;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Test Case
> 
> +*/
> 
> +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;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Test Case
> 
> +*/
> 
> +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;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Test Case
> 
> +*/
> 
> +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;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Test Case
> 
> +*/
> 
> +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
> ==============================================
> 
> +
> 
> +/**
> 
> +  Test Case
> 
> +*/
> 
> +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;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Test Case
> 
> +*/
> 
> +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;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Test Case
> 
> +*/
> 
> +UNIT_TEST_STATUS
> 
> +EFIAPI
> 
> +RegisterShouldRejectNullPointers (
> 
> +  IN UNIT_TEST_CONTEXT      Context
> 
> +  )
> 
> +{
> 
> +  UT_ASSERT_EQUAL( RegisterVariablePolicy( NULL ),
> EFI_INVALID_PARAMETER );
> 
> +  return UNIT_TEST_PASSED;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Test Case
> 
> +*/
> 
> +UNIT_TEST_STATUS
> 
> +EFIAPI
> 
> +RegisterShouldRejectBadRevisions (
> 
> +  IN UNIT_TEST_CONTEXT      Context
> 
> +  )
> 
> +{
> 
> +  SIMPLE_VARIABLE_POLICY_ENTRY   ValidationPolicy = {
> 
> +    {
> 
> +      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;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Test Case
> 
> +*/
> 
> +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;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Test Case
> 
> +*/
> 
> +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;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Test Case
> 
> +*/
> 
> +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;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Test Case
> 
> +*/
> 
> +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;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Test Case
> 
> +*/
> 
> +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;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Test Case
> 
> +*/
> 
> +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;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Test Case
> 
> +*/
> 
> +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;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Test Case
> 
> +*/
> 
> +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;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Test Case
> 
> +*/
> 
> +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;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Test Case
> 
> +*/
> 
> +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;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Test Case
> 
> +*/
> 
> +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;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Test Case
> 
> +*/
> 
> +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;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Test Case
> 
> +*/
> 
> +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;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Test Case
> 
> +*/
> 
> +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;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Test Case
> 
> +*/
> 
> +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;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Test Case
> 
> +*/
> 
> +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;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Test Case
> 
> +*/
> 
> +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;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Test Case
> 
> +*/
> 
> +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;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Test Case
> 
> +*/
> 
> +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;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Test Case
> 
> +*/
> 
> +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;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Test Case
> 
> +*/
> 
> +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
> ===================================================
> 
> +
> 
> +/**
> 
> +  Test Case
> 
> +*/
> 
> +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;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Test Case
> 
> +*/
> 
> +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;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Test Case
> 
> +*/
> 
> +UNIT_TEST_STATUS
> 
> +EFIAPI
> 
> +ShouldNotBeAbleToDisablePoliciesTwice (
> 
> +  IN UNIT_TEST_CONTEXT      Context
> 
> +  )
> 
> +{
> 
> +  // Make sure that the policy enforcement is currently enabled.
> 
> +  UT_ASSERT_TRUE( IsVariablePolicyEnabled() );
> 
> +  // Disable the policy enforcement.
> 
> +  UT_ASSERT_NOT_EFI_ERROR( DisableVariablePolicy() );
> 
> +  // Make sure that the policy enforcement is currently disabled.
> 
> +  UT_ASSERT_FALSE( IsVariablePolicyEnabled() );
> 
> +  // Try to disable again and verify failure.
> 
> +  UT_ASSERT_TRUE( EFI_ERROR( DisableVariablePolicy() ) );
> 
> +
> 
> +  return UNIT_TEST_PASSED;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Test Case
> 
> +*/
> 
> +UNIT_TEST_STATUS
> 
> +EFIAPI
> 
> +ShouldBeAbleToAddNewPoliciesAfterDisabled (
> 
> +  IN UNIT_TEST_CONTEXT      Context
> 
> +  )
> 
> +{
> 
> +  SIMPLE_VARIABLE_POLICY_ENTRY   TestPolicy = {
> 
> +    {
> 
> +      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;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Test Case
> 
> +*/
> 
> +UNIT_TEST_STATUS
> 
> +EFIAPI
> 
> +ShouldBeAbleToLockAfterDisabled (
> 
> +  IN UNIT_TEST_CONTEXT      Context
> 
> +  )
> 
> +{
> 
> +  // Make sure that the policy enforcement is currently enabled.
> 
> +  UT_ASSERT_TRUE( IsVariablePolicyEnabled() );
> 
> +  // Disable the policy enforcement.
> 
> +  UT_ASSERT_NOT_EFI_ERROR( DisableVariablePolicy() );
> 
> +
> 
> +  // Make sure that we can lock in this state.
> 
> +  UT_ASSERT_FALSE( IsVariablePolicyInterfaceLocked() );
> 
> +  UT_ASSERT_NOT_EFI_ERROR( LockVariablePolicy() );
> 
> +  UT_ASSERT_TRUE( IsVariablePolicyInterfaceLocked() );
> 
> +
> 
> +  return UNIT_TEST_PASSED;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Test Case
> 
> +*/
> 
> +UNIT_TEST_STATUS
> 
> +EFIAPI
> 
> +ShouldBeAbleToDumpThePolicyTable (
> 
> +  IN UNIT_TEST_CONTEXT      Context
> 
> +  )
> 
> +{
> 
> +  SIMPLE_VARIABLE_POLICY_ENTRY   TestPolicy = {
> 
> +    {
> 
> +      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;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Test Case
> 
> +*/
> 
> +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 != NULL)
> 
> +  {
> 
> +    FreeUnitTestFramework( Framework );
> 
> +  }
> 
> +
> 
> +  return Status;
> 
> +}
> 
> diff --git a/MdeModulePkg/Include/Library/VariablePolicyLib.h
> b/MdeModulePkg/Include/Library/VariablePolicyLib.h
> new file mode 100644
> index 000000000000..efd1840112ec
> --- /dev/null
> +++ b/MdeModulePkg/Include/Library/VariablePolicyLib.h
> @@ -0,0 +1,207 @@
> +/** @file -- VariablePolicyLib.h
> 
> +Business logic for Variable Policy enforcement.
> 
> +
> 
> +Copyright (c) Microsoft Corporation.
> 
> +SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +
> 
> +**/
> 
> +
> 
> +#ifndef _VARIABLE_POLICY_LIB_H_
> 
> +#define _VARIABLE_POLICY_LIB_H_
> 
> +
> 
> +#include <Protocol/VariablePolicy.h>
> 
> +
> 
> +/**
> 
> +  This API function validates and registers a new policy 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_WRITE_PROTECTED   Interface option is disabled by platform
> PCD.
> 
> +  @retval     EFI_NOT_READY   Library has not yet been initialized.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +DisableVariablePolicy (
> 
> +  VOID
> 
> +  );
> 
> +
> 
> +
> 
> +/**
> 
> +  This API function will dump the entire contents of the 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..f4a879d5382f
> --- /dev/null
> +++ b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf
> @@ -0,0 +1,44 @@
> +## @file VariablePolicyLib.inf
> 
> +# Business logic for Variable Policy enforcement.
> 
> +#
> 
> +##
> 
> +# Copyright (c) Microsoft Corporation.
> 
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +##
> 
> +
> 
> +
> 
> +[Defines]
> 
> +  INF_VERSION         = 0x00010017
> 
> +  BASE_NAME           = VariablePolicyLib
> 
> +  FILE_GUID           = E9ECD342-159A-4F24-9FDF-65724027C594
> 
> +  VERSION_STRING      = 1.0
> 
> +  MODULE_TYPE         = DXE_DRIVER
> 
> +  LIBRARY_CLASS       = VariablePolicyLib|DXE_DRIVER DXE_SMM_DRIVER
> MM_STANDALONE
> 
> +
> 
> +#
> 
> +# The following information is for reference only and not required by the
> build tools.
> 
> +#
> 
> +#  VALID_ARCHITECTURES           = ANY
> 
> +#
> 
> +
> 
> +
> 
> +[Sources]
> 
> +  VariablePolicyLib.c
> 
> +  VariablePolicyExtraInitNull.c
> 
> +
> 
> +
> 
> +[Packages]
> 
> +  MdePkg/MdePkg.dec
> 
> +  MdeModulePkg/MdeModulePkg.dec
> 
> +
> 
> +
> 
> +[LibraryClasses]
> 
> +  DebugLib
> 
> +  BaseMemoryLib
> 
> +  MemoryAllocationLib
> 
> +  SafeIntLib
> 
> +  PcdLib
> 
> +
> 
> +
> 
> +[Pcd]
> 
> +
> gEfiMdeModulePkgTokenSpaceGuid.PcdAllowVariablePolicyEnforcementDis
> able     ## CONSUMES
> 
> diff --git a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.uni
> b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.uni
> new file mode 100644
> index 000000000000..2227ec427828
> --- /dev/null
> +++ b/MdeModulePkg/Library/VariablePolicyLib/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/VariablePolicyLibRuntimeDxe.in
> f
> b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.in
> f
> new file mode 100644
> index 000000000000..8b8365741864
> --- /dev/null
> +++
> b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.in
> f
> @@ -0,0 +1,51 @@
> +## @file VariablePolicyLibRuntimeDxe.inf
> 
> +# Business logic for Variable Policy enforcement.
> 
> +# This instance is specifically for RuntimeDxe and contains
> 
> +# extra routines to register for VirtualAddressChangeEvents.
> 
> +#
> 
> +# Copyright (c) Microsoft Corporation.
> 
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +##
> 
> +
> 
> +
> 
> +[Defines]
> 
> +  INF_VERSION         = 0x00010017
> 
> +  BASE_NAME           = VariablePolicyLibRuntimeDxe
> 
> +  FILE_GUID           = 205F7F0E-8EAC-4914-8390-1B90DD7E2A27
> 
> +  VERSION_STRING      = 1.0
> 
> +  MODULE_TYPE         = DXE_RUNTIME_DRIVER
> 
> +  LIBRARY_CLASS       = VariablePolicyLib|DXE_RUNTIME_DRIVER
> 
> +
> 
> +#
> 
> +# The following information is for reference only and not required by the
> build tools.
> 
> +#
> 
> +#  VALID_ARCHITECTURES           = ANY
> 
> +#
> 
> +
> 
> +
> 
> +[Sources]
> 
> +  VariablePolicyLib.c
> 
> +  VariablePolicyExtraInitRuntimeDxe.c
> 
> +
> 
> +
> 
> +[Packages]
> 
> +  MdePkg/MdePkg.dec
> 
> +  MdeModulePkg/MdeModulePkg.dec
> 
> +
> 
> +
> 
> +[LibraryClasses]
> 
> +  DebugLib
> 
> +  BaseMemoryLib
> 
> +  MemoryAllocationLib
> 
> +  SafeIntLib
> 
> +  UefiBootServicesTableLib
> 
> +  UefiRuntimeServicesTableLib
> 
> +  PcdLib
> 
> +
> 
> +
> 
> +[Pcd]
> 
> +
> gEfiMdeModulePkgTokenSpaceGuid.PcdAllowVariablePolicyEnforcementDis
> able     ## CONSUMES
> 
> +
> 
> +
> 
> +[Guids]
> 
> +  gEfiEventVirtualAddressChangeGuid
> 
> diff --git
> a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/Variable
> PolicyUnitTest.inf
> b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/Variable
> PolicyUnitTest.inf
> new file mode 100644
> index 000000000000..ccc04bb600d6
> --- /dev/null
> +++
> b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/Variable
> PolicyUnitTest.inf
> @@ -0,0 +1,40 @@
> +## @file VariablePolicyUnitTest.inf
> 
> +# UnitTest for...
> 
> +# Business logic for Variable Policy enforcement.
> 
> +#
> 
> +# Copyright (c) Microsoft Corporation.
> 
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +##
> 
> +
> 
> +
> 
> +[Defines]
> 
> +  INF_VERSION                    = 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 05d8ad4931f9..0b58c14e4747 100644
> --- a/MdeModulePkg/MdeModulePkg.dec
> +++ b/MdeModulePkg/MdeModulePkg.dec
> @@ -31,6 +31,9 @@ [LibraryClasses]
>    ##  @libraryclass  Defines a set of methods to reset whole system.
> 
>    ResetSystemLib|Include/Library/ResetSystemLib.h
> 
> 
> 
> +  ##  @libraryclass  Business logic for storing and testing variable 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 25aea3e2a481..14b6ed536962 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 @@ [LibraryClasses]
>    DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf
> 
> 
> DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTabl
> eLib.inf
> 
> 
> UefiBootManagerLib|MdeModulePkg/Library/UefiBootManagerLib/UefiBoo
> tManagerLib.inf
> 
> +
> VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLi
> b.inf
> 
>    #
> 
>    # Generic Modules
> 
>    #
> 
> @@ -129,6 +131,7 @@ [LibraryClasses.common.DXE_RUNTIME_DRIVER]
>    DebugLib|MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf
> 
> 
> LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxDxeLib.in
> f
> 
> 
> CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsule
> Lib.inf
> 
> +
> VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLi
> bRuntimeDxe.inf
> 
> 
> 
>  [LibraryClasses.common.SMM_CORE]
> 
>    HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
> 
> @@ -306,6 +309,8 @@ [Components]
>    MdeModulePkg/Library/BootLogoLib/BootLogoLib.inf
> 
> 
> MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull
> .inf
> 
>    MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf
> 
> +  MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf
> 
> +
> MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf
> 
>    MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf
> 
>    MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLib.inf
> 
>    MdeModulePkg/Library/VarCheckPcdLib/VarCheckPcdLib.inf
> 
> diff --git a/MdeModulePkg/Test/MdeModulePkgHostTest.dsc
> b/MdeModulePkg/Test/MdeModulePkgHostTest.dsc
> index 72a119db4568..095e613f1be1 100644
> --- a/MdeModulePkg/Test/MdeModulePkgHostTest.dsc
> +++ b/MdeModulePkg/Test/MdeModulePkgHostTest.dsc
> @@ -19,12 +19,23 @@ [Defines]
> 
> 
>  !include UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc
> 
> 
> 
> +[LibraryClasses]
> 
> +  SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf
> 
> +
> 
>  [Components]
> 
> 
> MdeModulePkg/Library/DxeResetSystemLib/UnitTest/MockUefiRuntimeSer
> vicesTableLib.inf
> 
> 
> 
>    #
> 
>    # Build MdeModulePkg HOST_APPLICATION Tests
> 
>    #
> 
> +
> MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePo
> licyUnitTest.inf {
> 
> +    <LibraryClasses>
> 
> +
> VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLi
> b.inf
> 
> +
> 
> +    <PcdsFixedAtBuild>
> 
> +
> gEfiMdeModulePkgTokenSpaceGuid.PcdAllowVariablePolicyEnforcementDis
> able|TRUE
> 
> +  }
> 
> +
> 
> 
> MdeModulePkg/Library/DxeResetSystemLib/UnitTest/DxeResetSystemLibU
> nitTestHost.inf {
> 
>      <LibraryClasses>
> 
> 
> ResetSystemLib|MdeModulePkg/Library/DxeResetSystemLib/DxeResetSyst
> emLib.inf
> 
> --
> 2.26.2.windows.1.8.g01c50adf56.20200515075929
> 
> 
> -=-=-=-=-=-=
> Groups.io Links: You receive all messages sent to this group.
> 
> View/Reply Online (#61588): https://edk2.groups.io/g/devel/message/61588
> Mute This Topic: https://groups.io/mt/75057697/1768738
> Group Owner: devel+owner@edk2.groups.io
> Unsubscribe: https://edk2.groups.io/g/devel/unsub  [dandan.bi@intel.com]
> -=-=-=-=-=-=


^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature
  2020-06-23  6:40 [PATCH v6 00/14] Add the VariablePolicy feature bret
                   ` (13 preceding siblings ...)
  2020-06-23  6:41 ` [PATCH v6 14/14] MdeModulePkg: Add a shell-based functional test for VariablePolicy Bret Barkelew
@ 2020-07-02  2:13 ` Dandan Bi
  2020-07-02  6:45   ` Bret Barkelew
  2020-07-29 19:56 ` [EXTERNAL] " Bret Barkelew
       [not found] ` <161DCDB779DB4B3C.30988@groups.io>
  16 siblings, 1 reply; 48+ messages in thread
From: Dandan Bi @ 2020-07-02  2:13 UTC (permalink / raw)
  To: devel@edk2.groups.io, bret@corthon.com
  Cc: Yao, Jiewen, Zhang, Chao B, Wang, Jian J, Wu, Hao A, Gao, Liming,
	Justen, Jordan L, Laszlo Ersek, Ard Biesheuvel, Andrew Fish,
	Ni, Ray

Hi Bret,

Thanks for the contribution.

I have taken an overview of this patch series and have some small comments in the related patches, please check in sub-patch.

I will review the patch series more in details and bring more comments back if have. Do you have a branch for these patches in GitHub? Which should be easy for review.


Thanks,
Dandan

> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Bret
> Barkelew
> Sent: Tuesday, June 23, 2020 2:41 PM
> To: devel@edk2.groups.io
> Cc: Yao, Jiewen <jiewen.yao@intel.com>; Zhang, Chao B
> <chao.b.zhang@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao
> A <hao.a.wu@intel.com>; Gao, Liming <liming.gao@intel.com>; Justen,
> Jordan L <jordan.l.justen@intel.com>; Laszlo Ersek <lersek@redhat.com>;
> Ard Biesheuvel <ard.biesheuvel@arm.com>; Andrew Fish
> <afish@apple.com>; Ni, Ray <ray.ni@intel.com>
> Subject: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature
> 
> REF:https://bugzilla.tianocore.org/show_bug.cgi?id=2522
> 
> The 14 patches in this series add the VariablePolicy feature to the core,
> deprecate Edk2VarLock (while adding a compatibility layer to reduce code
> churn), and integrate the VariablePolicy libraries and protocols into Variable
> Services.
> 
> Since the integration requires multiple changes, including adding libraries, a
> protocol, an SMI communication handler, and VariableServices integration,
> the patches are broken up by individual library additions and then a final
> integration. Security-sensitive changes like bypassing Authenticated Variable
> enforcement are also broken out into individual patches so that attention can
> be called directly to them.
> 
> Platform porting instructions are described in this wiki entry:
> https://github.com/tianocore/tianocore.github.io/wiki/VariablePolicy-
> Protocol---Enhanced-Method-for-Managing-Variables#platform-porting
> 
> Discussion of the feature can be found in multiple places throughout the last
> year on the RFC channel, staging branches, and in devel.
> 
> Most recently, this subject was discussed in this thread:
> https://edk2.groups.io/g/devel/message/53712
> (the code branches shared in that discussion are now out of date, but the
> whitepapers and discussion are relevant).
> 
> Cc: Jiewen Yao <jiewen.yao@intel.com>
> Cc: Chao Zhang <chao.b.zhang@intel.com>
> Cc: Jian J Wang <jian.j.wang@intel.com>
> Cc: Hao A Wu <hao.a.wu@intel.com>
> Cc: Liming Gao <liming.gao@intel.com>
> Cc: Jordan Justen <jordan.l.justen@intel.com>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
> Cc: Andrew Fish <afish@apple.com>
> Cc: Ray Ni <ray.ni@intel.com>
> Cc: Bret Barkelew <brbarkel@microsoft.com>
> Signed-off-by: Bret Barkelew <brbarkel@microsoft.com>
> 
> v6 changes:
> * Fix an issue with uninitialized Status in InitVariablePolicyLib() and
> DeinitVariablePolicyLib()
> * Fix GCC building in shell-based functional test
> * Rebase on latest origin/master
> 
> v5 changes:
> * Fix the CONST mismatch in VariablePolicy.h and VariablePolicySmmDxe.c
> * Fix EFIAPI mismatches in the functional unittest
> * Rebase on latest origin/master
> 
> v4 changes:
> * Remove Optional PcdAllowVariablePolicyEnforcementDisable PCD from
> platforms
> * Rebase on master
> * Migrate to new MmCommunicate2 protocol
> * Fix an oversight in the default return value for
> InitMmCommonCommBuffer
> * Fix in VariablePolicyLib to allow ExtraInitRuntimeDxe to consume variables
> 
> V3 changes:
> * Address all non-unittest issues with ECC
> * Make additional style changes
> * Include section name in hunk headers in "ini-style" files
> * Remove requirement for the EdkiiPiSmmCommunicationsRegionTable
> driver
>   (now allocates its own buffer)
> * Change names from VARIABLE_POLICY_PROTOCOL and
> gVariablePolicyProtocolGuid
>   to EDKII_VARIABLE_POLICY_PROTOCOL and
> gEdkiiVariablePolicyProtocolGuid
> * Fix GCC warning about initializing externs
> * Add UNI strings for new PCD
> * Add patches for ArmVirtPkg, OvmfXen, and UefiPayloadPkg
> * Reorder patches according to Liming's feedback about adding to platforms
>   before changing variable driver
> 
> V2 changes:
> * Fixed implementation for RuntimeDxe
> * Add PCD to block DisableVariablePolicy
> * Fix the DumpVariablePolicy pagination in SMM
> 
> Bret Barkelew (14):
>   MdeModulePkg: Define the VariablePolicy protocol interface
>   MdeModulePkg: Define the VariablePolicyLib
>   MdeModulePkg: Define the VariablePolicyHelperLib
>   MdeModulePkg: Define the VarCheckPolicyLib and SMM interface
>   OvmfPkg: Add VariablePolicy engine to OvmfPkg platform
>   EmulatorPkg: Add VariablePolicy engine to EmulatorPkg platform
>   ArmVirtPkg: Add VariablePolicy engine to ArmVirtPkg platform
>   UefiPayloadPkg: Add VariablePolicy engine to UefiPayloadPkg platform
>   MdeModulePkg: Connect VariablePolicy business logic to
>     VariableServices
>   MdeModulePkg: Allow VariablePolicy state to delete protected variables
>   SecurityPkg: Allow VariablePolicy state to delete authenticated
>     variables
>   MdeModulePkg: Change TCG MOR variables to use VariablePolicy
>   MdeModulePkg: Drop VarLock from RuntimeDxe variable driver
>   MdeModulePkg: Add a shell-based functional test for VariablePolicy
> 
>  MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.c
> |  320 +++
>  MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.c
> |  396 ++++
>  MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitNull.c
> |   46 +
> 
> MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitRuntimeDx
> e.c               |   85 +
>  MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c
> |  816 +++++++
> 
> MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePo
> licyUnitTest.c   | 2440 ++++++++++++++++++++
> 
> MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/VariablePolicyFu
> ncTestApp.c        | 1978 ++++++++++++++++
>  MdeModulePkg/Universal/Variable/RuntimeDxe/TcgMorLockDxe.c
> |   52 +-
>  MdeModulePkg/Universal/Variable/RuntimeDxe/TcgMorLockSmm.c
> |   60 +-
>  MdeModulePkg/Universal/Variable/RuntimeDxe/VarCheck.c
> |   49 +-
>  MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c
> |   53 +
> 
> MdeModulePkg/Universal/Variable/RuntimeDxe/VariableLockRequstToLock
> .c                    |   71 +
>  MdeModulePkg/Universal/Variable/RuntimeDxe/VariablePolicySmmDxe.c
> |  642 +++++
> 
> MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.
> c                       |   14 +
>  SecurityPkg/Library/AuthVariableLib/AuthService.c                                        |   22
> +-
>  ArmVirtPkg/ArmVirt.dsc.inc                                                               |    4 +
>  EmulatorPkg/EmulatorPkg.dsc                                                              |    3 +
>  MdeModulePkg/Include/Guid/VarCheckPolicyMmi.h                                            |
> 54 +
>  MdeModulePkg/Include/Library/VariablePolicyHelperLib.h
> |  164 ++
>  MdeModulePkg/Include/Library/VariablePolicyLib.h                                         |
> 207 ++
>  MdeModulePkg/Include/Protocol/VariablePolicy.h                                           |
> 157 ++
>  MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.inf
> |   42 +
>  MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.uni
> |   12 +
>  MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf
> |   35 +
>  MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.uni
> |   12 +
>  MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf
> |   44 +
>  MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.uni
> |   12 +
>  MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf
> |   51 +
> 
> MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePo
> licyUnitTest.inf |   40 +
>  MdeModulePkg/MdeModulePkg.ci.yaml                                                        |    4 +-
>  MdeModulePkg/MdeModulePkg.dec                                                            |   26 +-
>  MdeModulePkg/MdeModulePkg.dsc                                                            |   15 +
>  MdeModulePkg/MdeModulePkg.uni                                                            |    7 +
>  MdeModulePkg/Test/MdeModulePkgHostTest.dsc                                               |
> 11 +
>  MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/Readme.md
> |   55 +
> 
> MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/VariablePolicyFu
> ncTestApp.inf      |   42 +
>  MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
> |    5 +
>  MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf
> |    4 +
> 
> MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.i
> nf                     |   10 +
> 
> MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf
> |    4 +
>  OvmfPkg/OvmfPkgIa32.dsc                                                                  |    5 +
>  OvmfPkg/OvmfPkgIa32X64.dsc                                                               |    5 +
>  OvmfPkg/OvmfPkgX64.dsc                                                                   |    5 +
>  OvmfPkg/OvmfXen.dsc                                                                      |    4 +
>  SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf                                  |
> 2 +
>  UefiPayloadPkg/UefiPayloadPkgIa32.dsc                                                    |    4 +
>  UefiPayloadPkg/UefiPayloadPkgIa32X64.dsc                                                 |    4 +
>  47 files changed, 8015 insertions(+), 78 deletions(-)  create mode 100644
> MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.c
>  create mode 100644
> MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.c
>  create mode 100644
> MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitNull.c
>  create mode 100644
> MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitRuntimeDx
> e.c
>  create mode 100644
> MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c
>  create mode 100644
> MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePo
> licyUnitTest.c
>  create mode 100644
> MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/VariablePolicyFu
> ncTestApp.c
>  create mode 100644
> MdeModulePkg/Universal/Variable/RuntimeDxe/VariableLockRequstToLock
> .c
>  create mode 100644
> MdeModulePkg/Universal/Variable/RuntimeDxe/VariablePolicySmmDxe.c
>  create mode 100644 MdeModulePkg/Include/Guid/VarCheckPolicyMmi.h
>  create mode 100644
> MdeModulePkg/Include/Library/VariablePolicyHelperLib.h
>  create mode 100644 MdeModulePkg/Include/Library/VariablePolicyLib.h
>  create mode 100644 MdeModulePkg/Include/Protocol/VariablePolicy.h
>  create mode 100644
> MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.inf
>  create mode 100644
> MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.uni
>  create mode 100644
> MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf
>  create mode 100644
> MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.uni
>  create mode 100644
> MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf
>  create mode 100644
> MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.uni
>  create mode 100644
> MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf
>  create mode 100644
> MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePo
> licyUnitTest.inf
>  create mode 100644
> MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/Readme.md
>  create mode 100644
> MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/VariablePolicyFu
> ncTestApp.inf
> 
> --
> 2.26.2.windows.1.8.g01c50adf56.20200515075929
> 
> 
> 


^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [edk2-devel] [PATCH v6 13/14] MdeModulePkg: Drop VarLock from RuntimeDxe variable driver
  2020-07-02  2:13   ` [edk2-devel] " Dandan Bi
@ 2020-07-02  6:36     ` Bret Barkelew
  0 siblings, 0 replies; 48+ messages in thread
From: Bret Barkelew @ 2020-07-02  6:36 UTC (permalink / raw)
  To: devel@edk2.groups.io, dandan.bi@intel.com, bret@corthon.com
  Cc: Wang, Jian J, Wu, Hao A, liming.gao

[-- Attachment #1: Type: text/plain, Size: 13326 bytes --]

1.[Dandan]: You mentioned that this API is deprecated. So, you will retire VarLock protocol and this API, and update caller to use VariablePolicy protocol later, right?
Yes, the ultimate plan is to retire VarLock once the references in the core are moved to VariablePolicy.

And I also see that VariablePolicy is an updated interface to replace VarLock and VarCheckProtocol, so will you also retire VarCheckProtocol later? But in patch 9 VarCheckRegisterSetVariableCheckHandler seem still be used to register SetVariable handler to do SetVariable check based on Variable Policy.
I think that yes, the goal is to also get rid of VarCheckProtocol, but the VarCheck library interface is still used and useful for things like MOR and UefiGlobalVars.
I was planning on leaving the library interface because it seemed useful. Would be willing to discuss an architecture that would do away with the library interface as well, but would prefer to leave this implementation as close to current functionality as possible since we’ve had significant testing hours on it.

- Bret

From: Dandan Bi via groups.io<mailto:dandan.bi=intel.com@groups.io>
Sent: Wednesday, July 1, 2020 7:13 PM
To: devel@edk2.groups.io<mailto:devel@edk2.groups.io>; bret@corthon.com<mailto:bret@corthon.com>
Cc: Wang, Jian J<mailto:jian.j.wang@intel.com>; Wu, Hao A<mailto:hao.a.wu@intel.com>; liming.gao<mailto:liming.gao@intel.com>
Subject: [EXTERNAL] Re: [edk2-devel] [PATCH v6 13/14] MdeModulePkg: Drop VarLock from RuntimeDxe variable driver

1 comment inline, please check.


Thanks,
Dandan
> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Bret
> Barkelew
> Sent: Tuesday, June 23, 2020 2:41 PM
> To: devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>;
> Gao, Liming <liming.gao@intel.com>
> Subject: [edk2-devel] [PATCH v6 13/14] MdeModulePkg: Drop VarLock from
> RuntimeDxe variable driver
>
> https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fbugzilla.tianocore.org%2Fshow_bug.cgi%3Fid%3D2522&amp;data=02%7C01%7Cbret.barkelew%40microsoft.com%7Cf9e4108a0dd543ed78dc08d81e2d7a6d%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637292527963905085&amp;sdata=9Gqld4XSrVmEWJk02FkZRdi2YYX6iy3Uo%2FxZB1bi80Y%3D&amp;reserved=0
>
> Now that everything should be moved to
> VariablePolicy, drop support for the
> deprecated VarLock SMI interface and
> associated functions from variable RuntimeDxe.
>
> Cc: Jian J Wang <jian.j.wang@intel.com>
> Cc: Hao A Wu <hao.a.wu@intel.com>
> Cc: Liming Gao <liming.gao@intel.com>
> Cc: Bret Barkelew <brbarkel@microsoft.com>
> Signed-off-by: Bret Barkelew <brbarkel@microsoft.com>
> ---
>  MdeModulePkg/Universal/Variable/RuntimeDxe/VarCheck.c                 | 49 +-
> ------------
>
> MdeModulePkg/Universal/Variable/RuntimeDxe/VariableLockRequstToLock
> .c | 71 ++++++++++++++++++++
>  MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
> |  1 +
>  MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf            |  1
> +
>
> MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf
> |  1 +
>  5 files changed, 75 insertions(+), 48 deletions(-)
>
> diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VarCheck.c
> b/MdeModulePkg/Universal/Variable/RuntimeDxe/VarCheck.c
> index f15219df5eb8..486d85b022e1 100644
> --- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VarCheck.c
> +++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VarCheck.c
> @@ -3,60 +3,13 @@
>    and variable lock protocol based on VarCheckLib.
>
>
>
>  Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
>
> +Copyright (c) Microsoft Corporation.
>
>  SPDX-License-Identifier: BSD-2-Clause-Patent
>
>
>
>  **/
>
>
>
>  #include "Variable.h"
>
>
>
> -/**
>
> -  Mark a variable that will become read-only after leaving the DXE phase of
> execution.
>
> -  Write request coming from SMM environment through
> EFI_SMM_VARIABLE_PROTOCOL is allowed.
>
> -
>
> -  @param[in] This          The VARIABLE_LOCK_PROTOCOL instance.
>
> -  @param[in] VariableName  A pointer to the variable name that will be
> made read-only subsequently.
>
> -  @param[in] VendorGuid    A pointer to the vendor GUID that will be made
> read-only subsequently.
>
> -
>
> -  @retval EFI_SUCCESS           The variable specified by the VariableName and
> the VendorGuid was marked
>
> -                                as pending to be read-only.
>
> -  @retval EFI_INVALID_PARAMETER VariableName or VendorGuid is NULL.
>
> -                                Or VariableName is an empty string.
>
> -  @retval EFI_ACCESS_DENIED     EFI_END_OF_DXE_EVENT_GROUP_GUID
> or EFI_EVENT_GROUP_READY_TO_BOOT has
>
> -                                already been signaled.
>
> -  @retval EFI_OUT_OF_RESOURCES  There is not enough resource to hold
> the lock request.
>
> -**/
>
> -EFI_STATUS
>
> -EFIAPI
>
> -VariableLockRequestToLock (
>
> -  IN CONST EDKII_VARIABLE_LOCK_PROTOCOL *This,
>
> -  IN       CHAR16                       *VariableName,
>
> -  IN       EFI_GUID                     *VendorGuid
>
> -  )
>
> -{
>
> -  EFI_STATUS                    Status;
>
> -  VAR_CHECK_VARIABLE_PROPERTY   Property;
>
> -
>
> -  AcquireLockOnlyAtBootTime (&mVariableModuleGlobal-
> >VariableGlobal.VariableServicesLock);
>
> -
>
> -  Status = VarCheckLibVariablePropertyGet (VariableName, VendorGuid,
> &Property);
>
> -  if (!EFI_ERROR (Status)) {
>
> -    Property.Property |= VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY;
>
> -  } else {
>
> -    Property.Revision = VAR_CHECK_VARIABLE_PROPERTY_REVISION;
>
> -    Property.Property = VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY;
>
> -    Property.Attributes = 0;
>
> -    Property.MinSize = 1;
>
> -    Property.MaxSize = MAX_UINTN;
>
> -  }
>
> -  Status = VarCheckLibVariablePropertySet (VariableName, VendorGuid,
> &Property);
>
> -
>
> -  DEBUG ((EFI_D_INFO, "[Variable] Lock: %g:%s %r\n", VendorGuid,
> VariableName, Status));
>
> -
>
> -  ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal-
> >VariableGlobal.VariableServicesLock);
>
> -
>
> -  return Status;
>
> -}
>
> -
>
>  /**
>
>    Register SetVariable check handler.
>
>
>
> diff --git
> a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableLockRequstToLo
> ck.c
> b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableLockRequstToLo
> ck.c
> new file mode 100644
> index 000000000000..1f7f0b7ef06c
> --- /dev/null
> +++
> b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableLockRequstToLo
> ck.c
> @@ -0,0 +1,71 @@
> +/** @file -- VariableLockRequstToLock.c
>
> +Temporary location of the RequestToLock shim code while
>
> +projects are moved to VariablePolicy. Should be removed when deprecated.
>
> +
>
> +Copyright (c) Microsoft Corporation.
>
> +SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +
>
> +**/
>
> +
>
> +#include <Uefi.h>
>
> +
>
> +#include <Library/DebugLib.h>
>
> +#include <Library/MemoryAllocationLib.h>
>
> +
>
> +#include <Protocol/VariableLock.h>
>
> +
>
> +#include <Protocol/VariablePolicy.h>
>
> +#include <Library/VariablePolicyLib.h>
>
> +#include <Library/VariablePolicyHelperLib.h>
>
> +
>
> +
>
> +/**
>
> +  DEPRECATED. THIS IS ONLY HERE AS A CONVENIENCE WHILE PORTING.
1.[Dandan]: You mentioned that this API is deprecated. So, you will retire VarLock protocol and this API, and update caller to use VariablePolicy protocol later, right?
And I also see that VariablePolicy is an updated interface to replace VarLock and VarCheckProtocol, so will you also retire VarCheckProtocol later? But in patch 9 VarCheckRegisterSetVariableCheckHandler seem still be used to register SetVariable handler to do SetVariable check based on Variable Policy.

>
> +  Mark a variable that will become read-only after leaving the DXE phase of
> execution.
>
> +  Write request coming from SMM environment through
> EFI_SMM_VARIABLE_PROTOCOL is allowed.
>
> +
>
> +  @param[in] This          The VARIABLE_LOCK_PROTOCOL instance.
>
> +  @param[in] VariableName  A pointer to the variable name that will be
> made read-only subsequently.
>
> +  @param[in] VendorGuid    A pointer to the vendor GUID that will be made
> read-only subsequently.
>
> +
>
> +  @retval EFI_SUCCESS           The variable specified by the VariableName and
> the VendorGuid was marked
>
> +                                as pending to be read-only.
>
> +  @retval EFI_INVALID_PARAMETER VariableName or VendorGuid is NULL.
>
> +                                Or VariableName is an empty string.
>
> +  @retval EFI_ACCESS_DENIED     EFI_END_OF_DXE_EVENT_GROUP_GUID
> or EFI_EVENT_GROUP_READY_TO_BOOT has
>
> +                                already been signaled.
>
> +  @retval EFI_OUT_OF_RESOURCES  There is not enough resource to hold
> the lock request.
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +VariableLockRequestToLock (
>
> +  IN CONST EDKII_VARIABLE_LOCK_PROTOCOL *This,
>
> +  IN       CHAR16                       *VariableName,
>
> +  IN       EFI_GUID                     *VendorGuid
>
> +  )
>
> +{
>
> +  EFI_STATUS              Status;
>
> +  VARIABLE_POLICY_ENTRY   *NewPolicy;
>
> +
>
> +  NewPolicy = NULL;
>
> +  Status = CreateBasicVariablePolicy( VendorGuid,
>
> +                                      VariableName,
>
> +                                      VARIABLE_POLICY_NO_MIN_SIZE,
>
> +                                      VARIABLE_POLICY_NO_MAX_SIZE,
>
> +                                      VARIABLE_POLICY_NO_MUST_ATTR,
>
> +                                      VARIABLE_POLICY_NO_CANT_ATTR,
>
> +                                      VARIABLE_POLICY_TYPE_LOCK_NOW,
>
> +                                      &NewPolicy );
>
> +  if (!EFI_ERROR( Status )) {
>
> +    Status = RegisterVariablePolicy( NewPolicy );
>
> +  }
>
> +  if (EFI_ERROR( Status )) {
>
> +    DEBUG(( DEBUG_ERROR, "%a - Failed to lock variable %s! %r\n",
> __FUNCTION__, VariableName, Status ));
>
> +    ASSERT_EFI_ERROR( Status );
>
> +  }
>
> +  if (NewPolicy != NULL) {
>
> +    FreePool( NewPolicy );
>
> +  }
>
> +
>
> +  return Status;
>
> +}
>
> diff --git
> a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
> b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
> index 8debc560e6dc..3005e9617423 100644
> ---
> a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
> +++
> b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
> @@ -49,6 +49,7 @@ [Sources]
>    VarCheck.c
>
>    VariableExLib.c
>
>    SpeculationBarrierDxe.c
>
> +  VariableLockRequstToLock.c
>
>
>
>  [Packages]
>
>    MdePkg/MdePkg.dec
>
> diff --git
> a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf
> b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf
> index bbc8d2080193..26fbad97339f 100644
> --- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf
> +++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf
> @@ -58,6 +58,7 @@ [Sources]
>    VariableExLib.c
>
>    TcgMorLockSmm.c
>
>    SpeculationBarrierSmm.c
>
> +  VariableLockRequstToLock.c
>
>
>
>  [Packages]
>
>    MdePkg/MdePkg.dec
>
> diff --git
> a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.i
> nf
> b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.
> inf
> index 62f2f9252f43..7c6fdf4d65fd 100644
> ---
> a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.i
> nf
> +++
> b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.
> inf
> @@ -58,6 +58,7 @@ [Sources]
>    VariableExLib.c
>
>    TcgMorLockSmm.c
>
>    SpeculationBarrierSmm.c
>
> +  VariableLockRequstToLock.c
>
>
>
>  [Packages]
>
>    MdePkg/MdePkg.dec
>
> --
> 2.26.2.windows.1.8.g01c50adf56.20200515075929
>
>
> -=-=-=-=-=-=
> Groups.io Links: You receive all messages sent to this group.
>
> View/Reply Online (#61587): https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fedk2.groups.io%2Fg%2Fdevel%2Fmessage%2F61587&amp;data=02%7C01%7Cbret.barkelew%40microsoft.com%7Cf9e4108a0dd543ed78dc08d81e2d7a6d%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637292527963905085&amp;sdata=Yi9Gph8o5bYQLXQSIQXEoQOnwxQzaNUY5gva8eSA4fM%3D&amp;reserved=0
> Mute This Topic: https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgroups.io%2Fmt%2F75057696%2F1768738&amp;data=02%7C01%7Cbret.barkelew%40microsoft.com%7Cf9e4108a0dd543ed78dc08d81e2d7a6d%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637292527963905085&amp;sdata=dMe0I355RiX4B%2BvIxpwE27TDvPuLnpwDa9Zrn9%2Frk60%3D&amp;reserved=0
> Group Owner: devel+owner@edk2.groups.io
> Unsubscribe: https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fedk2.groups.io%2Fg%2Fdevel%2Funsub&amp;data=02%7C01%7Cbret.barkelew%40microsoft.com%7Cf9e4108a0dd543ed78dc08d81e2d7a6d%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637292527963905085&amp;sdata=QcKjWaEqx7465u4jZSGz2TBQEQoubdLsl0DmeHWA9%2FQ%3D&amp;reserved=0  [dandan.bi@intel.com]
> -=-=-=-=-=-=





[-- Attachment #2: Type: text/html, Size: 24762 bytes --]

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [edk2-devel] [PATCH v6 09/14] MdeModulePkg: Connect VariablePolicy business logic to VariableServices
  2020-07-02  2:13   ` [edk2-devel] " Dandan Bi
@ 2020-07-02  6:40     ` Bret Barkelew
  0 siblings, 0 replies; 48+ messages in thread
From: Bret Barkelew @ 2020-07-02  6:40 UTC (permalink / raw)
  To: devel@edk2.groups.io, dandan.bi@intel.com, bret@corthon.com
  Cc: Wang, Jian J, Wu, Hao A, liming.gao

[-- Attachment #1: Type: text/plain, Size: 40228 bytes --]

  1.  [Dandan]: I see other APIs in the VariablePolicyProtocol are using the APIs in VariablePolicyLib directly, expect this one.
Could we make the IsVariablePolicyEnabled API aligned in protocol and Lib?
This is because of an incongruity between the protocol definition and the library definition. For a simpler interface the library returns a BOOLEAN, but the Protocol returns EFI_STATUS (to align with the majority of Protocol calls). Could update the library to match the protocol, if it’s important, but it would touch a number of places.

- Bret

From: Dandan Bi via groups.io<mailto:dandan.bi=intel.com@groups.io>
Sent: Wednesday, July 1, 2020 7:13 PM
To: devel@edk2.groups.io<mailto:devel@edk2.groups.io>; bret@corthon.com<mailto:bret@corthon.com>
Cc: Wang, Jian J<mailto:jian.j.wang@intel.com>; Wu, Hao A<mailto:hao.a.wu@intel.com>; liming.gao<mailto:liming.gao@intel.com>
Subject: [EXTERNAL] Re: [edk2-devel] [PATCH v6 09/14] MdeModulePkg: Connect VariablePolicy business logic to VariableServices


1 comment inline, please check.


Thanks,
Dandan
> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Bret
> Barkelew
> Sent: Tuesday, June 23, 2020 2:41 PM
> To: devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>;
> Gao, Liming <liming.gao@intel.com>
> Subject: [edk2-devel] [PATCH v6 09/14] MdeModulePkg: Connect
> VariablePolicy business logic to VariableServices
>
> https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fbugzilla.tianocore.org%2Fshow_bug.cgi%3Fid%3D2522&amp;data=02%7C01%7CBret.Barkelew%40microsoft.com%7C3cebf618dafa4cfee99d08d81e2d7eea%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637292528041413678&amp;sdata=MqZbcBcrPmvajnjVnc8Ohmvq1s3u4OaUQB0d1wrdvLw%3D&amp;reserved=0
>
> VariablePolicy is an updated interface to
> replace VarLock and VarCheckProtocol.
>
> Add connective code to publish the VariablePolicy protocol
> and wire it to either the SMM communication interface
> or directly into the VariablePolicyLib business logic.
>
> Cc: Jian J Wang <jian.j.wang@intel.com>
> Cc: Hao A Wu <hao.a.wu@intel.com>
> Cc: Liming Gao <liming.gao@intel.com>
> Cc: Bret Barkelew <brbarkel@microsoft.com>
> Signed-off-by: Bret Barkelew <brbarkel@microsoft.com>
> ---
>  MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c             |  53
> ++
>  MdeModulePkg/Universal/Variable/RuntimeDxe/VariablePolicySmmDxe.c
> | 642 ++++++++++++++++++++
>
> MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.
> c   |  14 +
>  MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
> |   2 +
>  MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf           |   3
> +
>
> MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.i
> nf |  10 +
>  6 files changed, 724 insertions(+)
>
> diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c
> b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c
> index 7d2b6c8e1fad..d404d4763e54 100644
> --- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c
> +++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c
> @@ -5,18 +5,34 @@
>  Copyright (C) 2013, Red Hat, Inc.
>
>  Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
>
>  (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
>
> +Copyright (c) Microsoft Corporation.
>
>  SPDX-License-Identifier: BSD-2-Clause-Patent
>
>
>
>  **/
>
>
>
>  #include "Variable.h"
>
>
>
> +#include <Protocol/VariablePolicy.h>
>
> +#include <Library/VariablePolicyLib.h>
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +ProtocolIsVariablePolicyEnabled (
>
> +  OUT BOOLEAN *State
>
> +  );
>
> +
>
>  EFI_HANDLE                          mHandle                    = NULL;
>
>  EFI_EVENT                           mVirtualAddressChangeEvent = NULL;
>
>  VOID                                *mFtwRegistration          = NULL;
>
>  VOID                                ***mVarCheckAddressPointer = NULL;
>
>  UINTN                               mVarCheckAddressPointerCount = 0;
>
>  EDKII_VARIABLE_LOCK_PROTOCOL        mVariableLock              =
> { VariableLockRequestToLock };
>
> +EDKII_VARIABLE_POLICY_PROTOCOL      mVariablePolicyProtocol    =
> { EDKII_VARIABLE_POLICY_PROTOCOL_REVISION,
>
> +                                                                    DisableVariablePolicy,
>
> +                                                                    ProtocolIsVariablePolicyEnabled,
>
> +                                                                    RegisterVariablePolicy,
>
> +                                                                    DumpVariablePolicy,
>
> +                                                                    LockVariablePolicy };
>
>  EDKII_VAR_CHECK_PROTOCOL            mVarCheck                  =
> { VarCheckRegisterSetVariableCheckHandler,
>
>                                                                      VarCheckVariablePropertySet,
>
>                                                                      VarCheckVariablePropertyGet };
>
> @@ -303,6 +319,8 @@ OnReadyToBoot (
>      }
>
>    }
>
>
>
> +  ASSERT_EFI_ERROR (LockVariablePolicy ());
>
> +
>
>    gBS->CloseEvent (Event);
>
>  }
>
>
>
> @@ -466,6 +484,28 @@ FtwNotificationEvent (
>  }
>
>
>
>
>
> +/**
>
> +  This API function returns whether or not the policy engine is
>
> +  currently being enforced.
>
> +
>
> +  @param[out]   State       Pointer to a return value for whether the policy
> enforcement
>
> +                            is currently enabled.
>
> +
>
> +  @retval     EFI_SUCCESS
>
> +  @retval     Others        An error has prevented this command from
> completing.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +ProtocolIsVariablePolicyEnabled (
>
> +  OUT BOOLEAN *State
>
> +  )
>
> +{
>
> +  *State = IsVariablePolicyEnabled ();
>
> +  return EFI_SUCCESS;
>
> +}

1. [Dandan]: I see other APIs in the VariablePolicyProtocol are using the APIs in VariablePolicyLib directly, expect this one.
Could we make the IsVariablePolicyEnabled API aligned in protocol and Lib?

>
> +
>
> +
>
>  /**
>
>    Variable Driver main entry point. The Variable driver places the 4 EFI
>
>    runtime services in the EFI System Table and installs arch protocols
>
> @@ -576,6 +616,19 @@ VariableServiceInitialize (
>                    );
>
>    ASSERT_EFI_ERROR (Status);
>
>
>
> +  // Register and initialize the VariablePolicy engine.
>
> +  Status = InitVariablePolicyLib (VariableServiceGetVariable);
>
> +  ASSERT_EFI_ERROR (Status);
>
> +  Status = VarCheckRegisterSetVariableCheckHandler (ValidateSetVariable);
>
> +  ASSERT_EFI_ERROR (Status);
>
> +  Status = gBS->InstallMultipleProtocolInterfaces (
>
> +                    &mHandle,
>
> +                    &gEdkiiVariablePolicyProtocolGuid,
>
> +                    &mVariablePolicyProtocol,
>
> +                    NULL
>
> +                    );
>
> +  ASSERT_EFI_ERROR (Status);
>
> +
>
>    return EFI_SUCCESS;
>
>  }
>
>
>
> diff --git
> a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariablePolicySmmDxe.c
> b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariablePolicySmmDxe.c
> new file mode 100644
> index 000000000000..e2d4cf4cec1a
> --- /dev/null
> +++
> b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariablePolicySmmDxe.c
> @@ -0,0 +1,642 @@
> +/** @file -- VariablePolicySmmDxe.c
>
> +This protocol allows communication with Variable Policy Engine.
>
> +
>
> +Copyright (c) Microsoft Corporation.
>
> +SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +
>
> +**/
>
> +
>
> +#include <Library/BaseLib.h>
>
> +#include <Library/UefiLib.h>
>
> +#include <Library/DebugLib.h>
>
> +#include <Library/SafeIntLib.h>
>
> +#include <Library/UefiBootServicesTableLib.h>
>
> +#include <Library/BaseMemoryLib.h>
>
> +#include <Library/MemoryAllocationLib.h>
>
> +
>
> +#include <Protocol/VariablePolicy.h>
>
> +#include <Protocol/MmCommunication2.h>
>
> +
>
> +#include <Guid/VarCheckPolicyMmi.h>
>
> +
>
> +#include "Variable.h"
>
> +
>
> +EDKII_VARIABLE_POLICY_PROTOCOL  mVariablePolicyProtocol;
>
> +EFI_MM_COMMUNICATION2_PROTOCOL  *mMmCommunication;
>
> +
>
> +VOID      *mMmCommunicationBuffer;
>
> +UINTN     mMmCommunicationBufferSize;
>
> +EFI_LOCK  mMmCommunicationLock;
>
> +
>
> +/**
>
> +  Internal helper function to consolidate communication method.
>
> +
>
> +  @param[in,out]  CommBuffer
>
> +  @param[in,out]  CommSize    Size of the CommBuffer.
>
> +
>
> +  @retval   EFI_STATUS    Result from communication method.
>
> +
>
> +**/
>
> +STATIC
>
> +EFI_STATUS
>
> +InternalMmCommunicate (
>
> +  IN OUT VOID             *CommBuffer,
>
> +  IN OUT UINTN            *CommSize
>
> +  )
>
> +{
>
> +  EFI_STATUS    Status;
>
> +  if (CommBuffer == NULL || CommSize == NULL) {
>
> +    return EFI_INVALID_PARAMETER;
>
> +  }
>
> +  Status = mMmCommunication->Communicate (mMmCommunication,
> CommBuffer, CommBuffer, CommSize);
>
> +  return Status;
>
> +}
>
> +
>
> +
>
> +/**
>
> +  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_WRITE_PROTECTED   Interface option is disabled by platform
> PCD.
>
> +
>
> +**/
>
> +STATIC
>
> +EFI_STATUS
>
> +EFIAPI
>
> +ProtocolDisableVariablePolicy (
>
> +  VOID
>
> +  )
>
> +{
>
> +  EFI_STATUS                    Status;
>
> +  EFI_MM_COMMUNICATE_HEADER     *CommHeader;
>
> +  VAR_CHECK_POLICY_COMM_HEADER  *PolicyHeader;
>
> +  UINTN                         BufferSize;
>
> +
>
> +  // Check the PCD for convenience.
>
> +  // This would also be rejected by the lib, but why go to MM if we don't
> have to?
>
> +  if (!PcdGetBool (PcdAllowVariablePolicyEnforcementDisable)) {
>
> +    return EFI_WRITE_PROTECTED;
>
> +  }
>
> +
>
> +  AcquireLockOnlyAtBootTime (&mMmCommunicationLock);
>
> +
>
> +  // Set up the MM communication.
>
> +  BufferSize    = mMmCommunicationBufferSize;
>
> +  CommHeader    = mMmCommunicationBuffer;
>
> +  PolicyHeader  = (VAR_CHECK_POLICY_COMM_HEADER*)&CommHeader-
> >Data;
>
> +  CopyGuid( &CommHeader->HeaderGuid,
> &gVarCheckPolicyLibMmiHandlerGuid );
>
> +  CommHeader->MessageLength = BufferSize;
>
> +  PolicyHeader->Signature   = VAR_CHECK_POLICY_COMM_SIG;
>
> +  PolicyHeader->Revision    = VAR_CHECK_POLICY_COMM_REVISION;
>
> +  PolicyHeader->Command     = VAR_CHECK_POLICY_COMMAND_DISABLE;
>
> +
>
> +  Status = InternalMmCommunicate (CommHeader, &BufferSize);
>
> +  DEBUG(( DEBUG_VERBOSE, "%a - MmCommunication returned %r.\n",
> __FUNCTION__, Status ));
>
> +
>
> +  ReleaseLockOnlyAtBootTime (&mMmCommunicationLock);
>
> +
>
> +  return (EFI_ERROR( Status )) ? Status : PolicyHeader->Result;
>
> +}
>
> +
>
> +
>
> +/**
>
> +  This API function returns whether or not the policy engine is
>
> +  currently being enforced.
>
> +
>
> +  @param[out]   State       Pointer to a return value for whether the policy
> enforcement
>
> +                            is currently enabled.
>
> +
>
> +  @retval     EFI_SUCCESS
>
> +  @retval     Others        An error has prevented this command from
> completing.
>
> +
>
> +**/
>
> +STATIC
>
> +EFI_STATUS
>
> +EFIAPI
>
> +ProtocolIsVariablePolicyEnabled (
>
> +  OUT BOOLEAN     *State
>
> +  )
>
> +{
>
> +  EFI_STATUS                                Status;
>
> +  EFI_MM_COMMUNICATE_HEADER                 *CommHeader;
>
> +  VAR_CHECK_POLICY_COMM_HEADER              *PolicyHeader;
>
> +  VAR_CHECK_POLICY_COMM_IS_ENABLED_PARAMS   *CommandParams;
>
> +  UINTN                                     BufferSize;
>
> +
>
> +  if (State == NULL) {
>
> +    return EFI_INVALID_PARAMETER;
>
> +  }
>
> +
>
> +  AcquireLockOnlyAtBootTime (&mMmCommunicationLock);
>
> +
>
> +  // Set up the MM communication.
>
> +  BufferSize    = mMmCommunicationBufferSize;
>
> +  CommHeader    = mMmCommunicationBuffer;
>
> +  PolicyHeader  = (VAR_CHECK_POLICY_COMM_HEADER*)&CommHeader-
> >Data;
>
> +  CommandParams =
> (VAR_CHECK_POLICY_COMM_IS_ENABLED_PARAMS*)(PolicyHeader + 1);
>
> +  CopyGuid( &CommHeader->HeaderGuid,
> &gVarCheckPolicyLibMmiHandlerGuid );
>
> +  CommHeader->MessageLength = BufferSize;
>
> +  PolicyHeader->Signature   = VAR_CHECK_POLICY_COMM_SIG;
>
> +  PolicyHeader->Revision    = VAR_CHECK_POLICY_COMM_REVISION;
>
> +  PolicyHeader->Command     =
> VAR_CHECK_POLICY_COMMAND_IS_ENABLED;
>
> +
>
> +  Status = InternalMmCommunicate (CommHeader, &BufferSize);
>
> +  DEBUG(( DEBUG_VERBOSE, "%a - MmCommunication returned %r.\n",
> __FUNCTION__, Status ));
>
> +
>
> +  if (!EFI_ERROR( Status )) {
>
> +    Status = PolicyHeader->Result;
>
> +    *State = CommandParams->State;
>
> +  }
>
> +
>
> +  ReleaseLockOnlyAtBootTime (&mMmCommunicationLock);
>
> +
>
> +  return Status;
>
> +}
>
> +
>
> +
>
> +/**
>
> +  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.
>
> +
>
> +**/
>
> +STATIC
>
> +EFI_STATUS
>
> +EFIAPI
>
> +ProtocolRegisterVariablePolicy (
>
> +  IN CONST VARIABLE_POLICY_ENTRY    *NewPolicy
>
> +  )
>
> +{
>
> +  EFI_STATUS                                Status;
>
> +  EFI_MM_COMMUNICATE_HEADER                 *CommHeader;
>
> +  VAR_CHECK_POLICY_COMM_HEADER              *PolicyHeader;
>
> +  VOID                                      *PolicyBuffer;
>
> +  UINTN                                     BufferSize;
>
> +  UINTN                                     RequiredSize;
>
> +
>
> +  if (NewPolicy == NULL) {
>
> +    return EFI_INVALID_PARAMETER;
>
> +  }
>
> +
>
> +  // First, make sure that the required size does not exceed the capabilities
>
> +  // of the MmCommunication buffer.
>
> +  RequiredSize = OFFSET_OF(EFI_MM_COMMUNICATE_HEADER, Data) +
> sizeof(VAR_CHECK_POLICY_COMM_HEADER);
>
> +  Status = SafeUintnAdd( RequiredSize, NewPolicy->Size, &RequiredSize );
>
> +  if (EFI_ERROR( Status ) || RequiredSize > mMmCommunicationBufferSize)
> {
>
> +    DEBUG(( DEBUG_ERROR, "%a - Policy too large for buffer! %r, %d > %d
> \n", __FUNCTION__,
>
> +            Status, RequiredSize, mMmCommunicationBufferSize ));
>
> +    return EFI_OUT_OF_RESOURCES;
>
> +  }
>
> +
>
> +  AcquireLockOnlyAtBootTime (&mMmCommunicationLock);
>
> +
>
> +  // Set up the MM communication.
>
> +  BufferSize    = mMmCommunicationBufferSize;
>
> +  CommHeader    = mMmCommunicationBuffer;
>
> +  PolicyHeader  = (VAR_CHECK_POLICY_COMM_HEADER*)&CommHeader-
> >Data;
>
> +  PolicyBuffer  = (VOID*)(PolicyHeader + 1);
>
> +  CopyGuid( &CommHeader->HeaderGuid,
> &gVarCheckPolicyLibMmiHandlerGuid );
>
> +  CommHeader->MessageLength = BufferSize;
>
> +  PolicyHeader->Signature   = VAR_CHECK_POLICY_COMM_SIG;
>
> +  PolicyHeader->Revision    = VAR_CHECK_POLICY_COMM_REVISION;
>
> +  PolicyHeader->Command     = VAR_CHECK_POLICY_COMMAND_REGISTER;
>
> +
>
> +  // Copy the policy into place. This copy is safe because we've already
> tested above.
>
> +  CopyMem( PolicyBuffer, NewPolicy, NewPolicy->Size );
>
> +
>
> +  Status = InternalMmCommunicate (CommHeader, &BufferSize);
>
> +  DEBUG(( DEBUG_VERBOSE, "%a - MmCommunication returned %r.\n",
> __FUNCTION__, Status ));
>
> +
>
> +  ReleaseLockOnlyAtBootTime (&mMmCommunicationLock);
>
> +
>
> +  return (EFI_ERROR( Status )) ? Status : PolicyHeader->Result;
>
> +}
>
> +
>
> +
>
> +/**
>
> +  This helper function takes care of the overhead of formatting, sending,
> and interpreting
>
> +  the results for a single DumpVariablePolicy request.
>
> +
>
> +  @param[in]      PageRequested   The page of the paginated results from
> MM. 0 for metadata.
>
> +  @param[out]     TotalSize       The total size of the entire buffer. Returned as
> part of metadata.
>
> +  @param[out]     PageSize        The size of the current page being returned.
> Not valid as part of metadata.
>
> +  @param[out]     HasMore         A flag indicating whether there are more
> pages after this one.
>
> +  @param[out]     Buffer          The start of the current page from MM.
>
> +
>
> +  @retval     EFI_SUCCESS             Output params have been updated (either
> metadata or dump page).
>
> +  @retval     EFI_INVALID_PARAMETER   One of the output params is NULL.
>
> +  @retval     Others                  Response from MM handler.
>
> +
>
> +**/
>
> +STATIC
>
> +EFI_STATUS
>
> +DumpVariablePolicyHelper (
>
> +  IN  UINT32        PageRequested,
>
> +  OUT UINT32        *TotalSize,
>
> +  OUT UINT32        *PageSize,
>
> +  OUT BOOLEAN       *HasMore,
>
> +  OUT UINT8         **Buffer
>
> +  )
>
> +{
>
> +  EFI_STATUS                              Status;
>
> +  EFI_MM_COMMUNICATE_HEADER               *CommHeader;
>
> +  VAR_CHECK_POLICY_COMM_HEADER            *PolicyHeader;
>
> +  VAR_CHECK_POLICY_COMM_DUMP_PARAMS       *CommandParams;
>
> +  UINTN                                   BufferSize;
>
> +
>
> +  if (TotalSize == NULL || PageSize == NULL || HasMore == NULL || Buffer
> == NULL) {
>
> +    return EFI_INVALID_PARAMETER;
>
> +  }
>
> +
>
> +  // Set up the MM communication.
>
> +  BufferSize    = mMmCommunicationBufferSize;
>
> +  CommHeader    = mMmCommunicationBuffer;
>
> +  PolicyHeader  = (VAR_CHECK_POLICY_COMM_HEADER*)&CommHeader-
> >Data;
>
> +  CommandParams =
> (VAR_CHECK_POLICY_COMM_DUMP_PARAMS*)(PolicyHeader + 1);
>
> +  CopyGuid( &CommHeader->HeaderGuid,
> &gVarCheckPolicyLibMmiHandlerGuid );
>
> +  CommHeader->MessageLength = BufferSize;
>
> +  PolicyHeader->Signature   = VAR_CHECK_POLICY_COMM_SIG;
>
> +  PolicyHeader->Revision    = VAR_CHECK_POLICY_COMM_REVISION;
>
> +  PolicyHeader->Command     = VAR_CHECK_POLICY_COMMAND_DUMP;
>
> +
>
> +  CommandParams->PageRequested = PageRequested;
>
> +
>
> +  Status = InternalMmCommunicate (CommHeader, &BufferSize);
>
> +  DEBUG(( DEBUG_VERBOSE, "%a - MmCommunication returned %r.\n",
> __FUNCTION__, Status ));
>
> +
>
> +  if (!EFI_ERROR( Status )) {
>
> +    Status = PolicyHeader->Result;
>
> +    *TotalSize = CommandParams->TotalSize;
>
> +    *PageSize = CommandParams->PageSize;
>
> +    *HasMore = CommandParams->HasMore;
>
> +    *Buffer = (UINT8*)(CommandParams + 1);
>
> +  }
>
> +
>
> +  return Status;
>
> +}
>
> +
>
> +
>
> +/**
>
> +  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.
>
> +
>
> +**/
>
> +STATIC
>
> +EFI_STATUS
>
> +EFIAPI
>
> +ProtocolDumpVariablePolicy (
>
> +  OUT UINT8             *Policy OPTIONAL,
>
> +  IN OUT UINT32         *Size
>
> +  )
>
> +{
>
> +  EFI_STATUS    Status;
>
> +  UINT8         *Source;
>
> +  UINT8         *Destination;
>
> +  UINT32        PolicySize;
>
> +  UINT32        PageSize;
>
> +  BOOLEAN       HasMore;
>
> +  UINT32        PageIndex;
>
> +
>
> +  if (Size == NULL || (*Size > 0 && Policy == NULL)) {
>
> +    return EFI_INVALID_PARAMETER;
>
> +  }
>
> +
>
> +  AcquireLockOnlyAtBootTime (&mMmCommunicationLock);
>
> +
>
> +  // Repeat this whole process until we either have a failure case or get the
> entire buffer.
>
> +  do {
>
> +    // First, we must check the zero page to determine the buffer size and
>
> +    // reset the internal state.
>
> +    PolicySize = 0;
>
> +    PageSize = 0;
>
> +    HasMore = FALSE;
>
> +    Status = DumpVariablePolicyHelper (0, &PolicySize, &PageSize, &HasMore,
> &Source);
>
> +    if (EFI_ERROR (Status)) {
>
> +      break;
>
> +    }
>
> +
>
> +    // If we're good, we can at least check the required size now.
>
> +    if (*Size < PolicySize) {
>
> +      *Size = PolicySize;
>
> +      Status = EFI_BUFFER_TOO_SMALL;
>
> +      break;
>
> +    }
>
> +
>
> +    // On further thought, let's update the size either way.
>
> +    *Size = PolicySize;
>
> +    // And get ready to ROCK.
>
> +    Destination = Policy;
>
> +
>
> +    // Keep looping and copying until we're either done or freak out.
>
> +    for (PageIndex = 1; !EFI_ERROR (Status) && HasMore && PageIndex <
> MAX_UINT32; PageIndex++) {
>
> +      Status = DumpVariablePolicyHelper (PageIndex, &PolicySize, &PageSize,
> &HasMore, &Source);
>
> +      if (!EFI_ERROR (Status)) {
>
> +        CopyMem (Destination, Source, PageSize);
>
> +        Destination += PageSize;
>
> +      }
>
> +    }
>
> +
>
> +    // Next, we check to see whether
>
> +  } while (Status == EFI_TIMEOUT);
>
> +
>
> +  ReleaseLockOnlyAtBootTime (&mMmCommunicationLock);
>
> +
>
> +  // There's currently no use for this, but it shouldn't be hard to implement.
>
> +  return Status;
>
> +}
>
> +
>
> +
>
> +/**
>
> +  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     Others        An error has prevented this command from
> completing.
>
> +
>
> +**/
>
> +STATIC
>
> +EFI_STATUS
>
> +EFIAPI
>
> +ProtocolLockVariablePolicy (
>
> +  VOID
>
> +  )
>
> +{
>
> +  EFI_STATUS                    Status;
>
> +  EFI_MM_COMMUNICATE_HEADER     *CommHeader;
>
> +  VAR_CHECK_POLICY_COMM_HEADER  *PolicyHeader;
>
> +  UINTN                         BufferSize;
>
> +
>
> +  AcquireLockOnlyAtBootTime (&mMmCommunicationLock);
>
> +
>
> +  // Set up the MM communication.
>
> +  BufferSize    = mMmCommunicationBufferSize;
>
> +  CommHeader    = mMmCommunicationBuffer;
>
> +  PolicyHeader  = (VAR_CHECK_POLICY_COMM_HEADER*)&CommHeader-
> >Data;
>
> +  CopyGuid( &CommHeader->HeaderGuid,
> &gVarCheckPolicyLibMmiHandlerGuid );
>
> +  CommHeader->MessageLength = BufferSize;
>
> +  PolicyHeader->Signature   = VAR_CHECK_POLICY_COMM_SIG;
>
> +  PolicyHeader->Revision    = VAR_CHECK_POLICY_COMM_REVISION;
>
> +  PolicyHeader->Command     = VAR_CHECK_POLICY_COMMAND_LOCK;
>
> +
>
> +  Status = InternalMmCommunicate (CommHeader, &BufferSize);
>
> +  DEBUG(( DEBUG_VERBOSE, "%a - MmCommunication returned %r.\n",
> __FUNCTION__, Status ));
>
> +
>
> +  ReleaseLockOnlyAtBootTime (&mMmCommunicationLock);
>
> +
>
> +  return (EFI_ERROR( Status )) ? Status : PolicyHeader->Result;
>
> +}
>
> +
>
> +
>
> +/**
>
> +  This helper function locates the shared comm buffer and assigns it to input
> pointers.
>
> +
>
> +  @param[in,out]  BufferSize      On input, the minimum buffer size required
> INCLUDING the MM communicate header.
>
> +                                  On output, the size of the matching buffer found.
>
> +  @param[out]     LocatedBuffer   A pointer to the matching buffer.
>
> +
>
> +  @retval     EFI_SUCCESS
>
> +  @retval     EFI_INVALID_PARAMETER   One of the output pointers was
> NULL.
>
> +  @retval     EFI_OUT_OF_RESOURCES    Not enough memory to allocate a
> comm buffer.
>
> +
>
> +**/
>
> +STATIC
>
> +EFI_STATUS
>
> +InitMmCommonCommBuffer (
>
> +  IN OUT  UINTN       *BufferSize,
>
> +  OUT     VOID        **LocatedBuffer
>
> +  )
>
> +{
>
> +  EFI_STATUS                  Status;
>
> +
>
> +  Status = EFI_SUCCESS;
>
> +
>
> +  // Make sure that we're working with good pointers.
>
> +  if (BufferSize == NULL || LocatedBuffer == NULL) {
>
> +    return EFI_INVALID_PARAMETER;
>
> +  }
>
> +
>
> +  // Allocate the runtime memory for the comm buffer.
>
> +  *LocatedBuffer = AllocateRuntimePool (*BufferSize);
>
> +  if (*LocatedBuffer == NULL) {
>
> +    Status = EFI_OUT_OF_RESOURCES;
>
> +    *BufferSize = 0;
>
> +  }
>
> +
>
> +  EfiInitializeLock (&mMmCommunicationLock, TPL_NOTIFY);
>
> +
>
> +  return Status;
>
> +}
>
> +
>
> +
>
> +/**
>
> +  This helper is responsible for telemetry and any other actions that
>
> +  need to be taken if the VariablePolicy fails to lock.
>
> +
>
> +  NOTE: It's possible that parts of this handling will need to become
>
> +        part of a platform policy.
>
> +
>
> +  @param[in]  FailureStatus   The failure that was reported by
> LockVariablePolicy
>
> +
>
> +**/
>
> +STATIC
>
> +VOID
>
> +VariablePolicyHandleFailureToLock (
>
> +  IN  EFI_STATUS      FailureStatus
>
> +  )
>
> +{
>
> +  // For now, there's no agreed-upon policy for this.
>
> +  return;
>
> +}
>
> +
>
> +
>
> +/**
>
> +  ReadyToBoot Callback
>
> +  Lock the VariablePolicy interface if it hasn't already been locked.
>
> +
>
> +  @param[in]  Event     Event whose notification function is being invoked
>
> +  @param[in]  Context   Pointer to the notification function's context
>
> +
>
> +**/
>
> +STATIC
>
> +VOID
>
> +EFIAPI
>
> +LockPolicyInterfaceAtReadyToBoot (
>
> +  IN      EFI_EVENT                 Event,
>
> +  IN      VOID                      *Context
>
> +  )
>
> +{
>
> +  EFI_STATUS  Status;
>
> +
>
> +  Status = ProtocolLockVariablePolicy();
>
> +
>
> +  if (EFI_ERROR( Status )) {
>
> +    VariablePolicyHandleFailureToLock( Status );
>
> +  }
>
> +  else {
>
> +    gBS->CloseEvent( Event );
>
> +  }
>
> +
>
> +}
>
> +
>
> +
>
> +/**
>
> +  Convert internal pointer addresses to virtual addresses.
>
> +
>
> +  @param[in] Event      Event whose notification function is being invoked.
>
> +  @param[in] Context    The pointer to the notification function's context,
> which
>
> +                        is implementation-dependent.
>
> +**/
>
> +STATIC
>
> +VOID
>
> +EFIAPI
>
> +VariablePolicyVirtualAddressCallback (
>
> +  IN  EFI_EVENT   Event,
>
> +  IN  VOID        *Context
>
> +  )
>
> +{
>
> +  EfiConvertPointer (0, (VOID **)&mMmCommunication);
>
> +  EfiConvertPointer (0, (VOID **)&mMmCommunicationBuffer);
>
> +}
>
> +
>
> +
>
> +/**
>
> +  The driver's entry point.
>
> +
>
> +  @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.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +VariablePolicySmmDxeMain (
>
> +  IN    EFI_HANDLE                  ImageHandle,
>
> +  IN    EFI_SYSTEM_TABLE            *SystemTable
>
> +  )
>
> +{
>
> +  EFI_STATUS              Status;
>
> +  BOOLEAN                 ProtocolInstalled;
>
> +  BOOLEAN                 CallbackRegistered;
>
> +  BOOLEAN                 VirtualAddressChangeRegistered;
>
> +  EFI_EVENT               ReadyToBootEvent;
>
> +  EFI_EVENT               VirtualAddressChangeEvent;
>
> +
>
> +  Status = EFI_SUCCESS;
>
> +  ProtocolInstalled = FALSE;
>
> +  CallbackRegistered = FALSE;
>
> +  VirtualAddressChangeRegistered = FALSE;
>
> +
>
> +  // Update the minimum buffer size.
>
> +  mMmCommunicationBufferSize =
> VAR_CHECK_POLICY_MM_COMM_BUFFER_SIZE;
>
> +  // Locate the shared comm buffer to use for sending MM commands.
>
> +  Status = InitMmCommonCommBuffer( &mMmCommunicationBufferSize,
> &mMmCommunicationBuffer );
>
> +  if (EFI_ERROR( Status )) {
>
> +    DEBUG((DEBUG_ERROR, "%a - Failed to locate a viable MM comm
> buffer! %r\n", __FUNCTION__, Status));
>
> +    ASSERT_EFI_ERROR( Status );
>
> +    return Status;
>
> +  }
>
> +
>
> +  // Locate the MmCommunication protocol.
>
> +  Status = gBS->LocateProtocol( &gEfiMmCommunication2ProtocolGuid,
> NULL, (VOID**)&mMmCommunication );
>
> +  if (EFI_ERROR( Status )) {
>
> +    DEBUG((DEBUG_ERROR, "%a - Failed to locate MmCommunication
> protocol! %r\n", __FUNCTION__, Status));
>
> +    ASSERT_EFI_ERROR( Status );
>
> +    return Status;
>
> +  }
>
> +
>
> +  // Configure the VariablePolicy protocol structure.
>
> +  mVariablePolicyProtocol.Revision                =
> EDKII_VARIABLE_POLICY_PROTOCOL_REVISION;
>
> +  mVariablePolicyProtocol.DisableVariablePolicy   =
> ProtocolDisableVariablePolicy;
>
> +  mVariablePolicyProtocol.IsVariablePolicyEnabled =
> ProtocolIsVariablePolicyEnabled;
>
> +  mVariablePolicyProtocol.RegisterVariablePolicy  =
> ProtocolRegisterVariablePolicy;
>
> +  mVariablePolicyProtocol.DumpVariablePolicy      =
> ProtocolDumpVariablePolicy;
>
> +  mVariablePolicyProtocol.LockVariablePolicy      = ProtocolLockVariablePolicy;
>
> +
>
> +  // Register all the protocols and return the status.
>
> +  Status = gBS->InstallMultipleProtocolInterfaces( &ImageHandle,
>
> +                                                   &gEdkiiVariablePolicyProtocolGuid,
> &mVariablePolicyProtocol,
>
> +                                                   NULL );
>
> +  if (EFI_ERROR( Status )) {
>
> +    DEBUG(( DEBUG_ERROR, "%a - Failed to install protocol! %r\n",
> __FUNCTION__, Status ));
>
> +    goto Exit;
>
> +  }
>
> +  else {
>
> +    ProtocolInstalled = TRUE;
>
> +  }
>
> +
>
> +  //
>
> +  // Register a callback for ReadyToBoot so that the interface is at least
> locked before
>
> +  // dispatching any bootloaders or UEFI apps.
>
> +  Status = gBS->CreateEventEx( EVT_NOTIFY_SIGNAL,
>
> +                               TPL_CALLBACK,
>
> +                               LockPolicyInterfaceAtReadyToBoot,
>
> +                               NULL,
>
> +                               &gEfiEventReadyToBootGuid,
>
> +                               &ReadyToBootEvent );
>
> +  if (EFI_ERROR( Status )) {
>
> +    DEBUG(( DEBUG_ERROR, "%a - Failed to create ReadyToBoot
> event! %r\n", __FUNCTION__, Status ));
>
> +    goto Exit;
>
> +  }
>
> +  else {
>
> +    CallbackRegistered = TRUE;
>
> +  }
>
> +
>
> +  //
>
> +  // Register a VirtualAddressChange callback for the MmComm protocol
> and Comm buffer.
>
> +  Status = gBS->CreateEventEx (EVT_NOTIFY_SIGNAL,
>
> +                                TPL_NOTIFY,
>
> +                                VariablePolicyVirtualAddressCallback,
>
> +                                NULL,
>
> +                                &gEfiEventVirtualAddressChangeGuid,
>
> +                                &VirtualAddressChangeEvent);
>
> +  if (EFI_ERROR( Status )) {
>
> +    DEBUG(( DEBUG_ERROR, "%a - Failed to create VirtualAddressChange
> event! %r\n", __FUNCTION__, Status ));
>
> +    goto Exit;
>
> +  }
>
> +  else {
>
> +    VirtualAddressChangeRegistered = TRUE;
>
> +  }
>
> +
>
> +
>
> +Exit:
>
> +  //
>
> +  // If we're about to return a failed status (and unload this driver), we must
> first undo anything that
>
> +  // has been successfully done.
>
> +  if (EFI_ERROR( Status )) {
>
> +    if (ProtocolInstalled) {
>
> +      gBS->UninstallProtocolInterface( &ImageHandle,
> &gEdkiiVariablePolicyProtocolGuid, &mVariablePolicyProtocol );
>
> +    }
>
> +    if (CallbackRegistered) {
>
> +      gBS->CloseEvent( ReadyToBootEvent );
>
> +    }
>
> +    if (VirtualAddressChangeRegistered) {
>
> +      gBS->CloseEvent( VirtualAddressChangeEvent );
>
> +    }
>
> +  }
>
> +
>
> +  return Status;
>
> +}
>
> diff --git
> a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDx
> e.c
> b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDx
> e.c
> index 663a1aaa128f..c47e614d81f4 100644
> ---
> a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDx
> e.c
> +++
> b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDx
> e.c
> @@ -65,6 +65,17 @@ EFI_LOCK                         mVariableServicesLock;
>  EDKII_VARIABLE_LOCK_PROTOCOL     mVariableLock;
>
>  EDKII_VAR_CHECK_PROTOCOL         mVarCheck;
>
>
>
> +/**
>
> +  The logic to initialize the VariablePolicy engine is in its own file.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +VariablePolicySmmDxeMain (
>
> +  IN    EFI_HANDLE                  ImageHandle,
>
> +  IN    EFI_SYSTEM_TABLE            *SystemTable
>
> +  );
>
> +
>
>  /**
>
>    Some Secure Boot Policy Variable may update following other variable
> changes(SecureBoot follows PK change, etc).
>
>    Record their initial State when variable write service is ready.
>
> @@ -1796,6 +1807,9 @@ VariableSmmRuntimeInitialize (
>           &mVirtualAddressChangeEvent
>
>           );
>
>
>
> +  // Initialize the VariablePolicy protocol and engine.
>
> +  VariablePolicySmmDxeMain (ImageHandle, SystemTable);
>
> +
>
>    return EFI_SUCCESS;
>
>  }
>
>
>
> diff --git
> a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
> b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
> index ceea5d1ff9ac..48ac167906f7 100644
> ---
> a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
> +++
> b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
> @@ -10,6 +10,7 @@
>  #  buffer overflow or integer overflow.
>
>  #
>
>  # Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
>
> +# Copyright (c) Microsoft Corporation.
>
>  # SPDX-License-Identifier: BSD-2-Clause-Patent
>
>  #
>
>  ##
>
> @@ -69,6 +70,7 @@ [LibraryClasses]
>    TpmMeasurementLib
>
>    AuthVariableLib
>
>    VarCheckLib
>
> +  VariablePolicyLib
>
>
>
>  [Protocols]
>
>    gEfiFirmwareVolumeBlockProtocolGuid           ## CONSUMES
>
> diff --git
> a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf
> b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf
> index bc3033588d40..bbc8d2080193 100644
> --- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf
> +++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf
> @@ -19,6 +19,7 @@
>  #  the authentication service provided in this driver will be broken, and the
> behavior is undefined.
>
>  #
>
>  # Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.<BR>
>
> +# Copyright (c) Microsoft Corporation.
>
>  # SPDX-License-Identifier: BSD-2-Clause-Patent
>
>  #
>
>  ##
>
> @@ -78,6 +79,8 @@ [LibraryClasses]
>    AuthVariableLib
>
>    VarCheckLib
>
>    UefiBootServicesTableLib
>
> +  VariablePolicyLib
>
> +  VariablePolicyHelperLib
>
>
>
>  [Protocols]
>
>    gEfiSmmFirmwareVolumeBlockProtocolGuid        ## CONSUMES
>
> diff --git
> a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDx
> e.inf
> b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDx
> e.inf
> index 01564e4c5068..f217530b2985 100644
> ---
> a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDx
> e.inf
> +++
> b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDx
> e.inf
> @@ -14,6 +14,7 @@
>  #  the authentication service provided in this driver will be broken, and the
> behavior is undefined.
>
>  #
>
>  # Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.<BR>
>
> +# Copyright (c) Microsoft Corporation.<BR>
>
>  # SPDX-License-Identifier: BSD-2-Clause-Patent
>
>  #
>
>  ##
>
> @@ -42,6 +43,7 @@ [Sources]
>    VariableParsing.c
>
>    VariableParsing.h
>
>    Variable.h
>
> +  VariablePolicySmmDxe.c
>
>
>
>  [Packages]
>
>    MdePkg/MdePkg.dec
>
> @@ -56,6 +58,8 @@ [LibraryClasses]
>    DxeServicesTableLib
>
>    UefiDriverEntryPoint
>
>    TpmMeasurementLib
>
> +  SafeIntLib
>
> +  PcdLib
>
>
>
>  [Protocols]
>
>    gEfiVariableWriteArchProtocolGuid             ## PRODUCES
>
> @@ -67,11 +71,15 @@ [Protocols]
>    gEfiSmmVariableProtocolGuid
>
>    gEdkiiVariableLockProtocolGuid                ## PRODUCES
>
>    gEdkiiVarCheckProtocolGuid                    ## PRODUCES
>
> +  gEdkiiVariablePolicyProtocolGuid              ## PRODUCES
>
>
>
>  [FeaturePcd]
>
>    gEfiMdeModulePkgTokenSpaceGuid.PcdEnableVariableRuntimeCache
> ## CONSUMES
>
>    gEfiMdeModulePkgTokenSpaceGuid.PcdVariableCollectStatistics            ##
> CONSUMES
>
>
>
> +[Pcd]
>
> +
> gEfiMdeModulePkgTokenSpaceGuid.PcdAllowVariablePolicyEnforcementDis
> able     ## CONSUMES
>
> +
>
>  [Guids]
>
>    ## PRODUCES             ## GUID # Signature of Variable store header
>
>    ## CONSUMES             ## GUID # Signature of Variable store header
>
> @@ -99,6 +107,8 @@ [Guids]
>    ## SOMETIMES_CONSUMES   ## Variable:L"dbt"
>
>    gEfiImageSecurityDatabaseGuid
>
>
>
> +  gVarCheckPolicyLibMmiHandlerGuid
>
> +
>
>  [Depex]
>
>    gEfiMmCommunication2ProtocolGuid
>
>
>
> --
> 2.26.2.windows.1.8.g01c50adf56.20200515075929
>
>
> -=-=-=-=-=-=
> Groups.io Links: You receive all messages sent to this group.
>
> View/Reply Online (#61585): https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fedk2.groups.io%2Fg%2Fdevel%2Fmessage%2F61585&amp;data=02%7C01%7CBret.Barkelew%40microsoft.com%7C3cebf618dafa4cfee99d08d81e2d7eea%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637292528041413678&amp;sdata=d0mbjucYGj4RQ6pyhU%2FpZE85T2Ld1diULIEM5FzGvkI%3D&amp;reserved=0
> Mute This Topic: https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgroups.io%2Fmt%2F75057694%2F1768738&amp;data=02%7C01%7CBret.Barkelew%40microsoft.com%7C3cebf618dafa4cfee99d08d81e2d7eea%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637292528041413678&amp;sdata=eh0sawMbAEMwIlZhyqx1S65ZaFRvAvHVe7qLhbSETnk%3D&amp;reserved=0
> Group Owner: devel+owner@edk2.groups.io
> Unsubscribe: https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fedk2.groups.io%2Fg%2Fdevel%2Funsub&amp;data=02%7C01%7CBret.Barkelew%40microsoft.com%7C3cebf618dafa4cfee99d08d81e2d7eea%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637292528041413678&amp;sdata=T96gQ%2FoxHniDVgXpO5%2Bw0c62FXIDRe%2FKcYUtEc%2BMZ8g%3D&amp;reserved=0  [dandan.bi@intel.com]
> -=-=-=-=-=-=





[-- Attachment #2: Type: text/html, Size: 81602 bytes --]

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [edk2-devel] [PATCH v6 04/14] MdeModulePkg: Define the VarCheckPolicyLib and SMM interface
  2020-07-02  2:13   ` [edk2-devel] " Dandan Bi
@ 2020-07-02  6:41     ` Bret Barkelew
  0 siblings, 0 replies; 48+ messages in thread
From: Bret Barkelew @ 2020-07-02  6:41 UTC (permalink / raw)
  To: devel@edk2.groups.io, dandan.bi@intel.com, bret@corthon.com
  Cc: Wang, Jian J, Wu, Hao A, liming.gao

[-- Attachment #1: Type: text/plain, Size: 26904 bytes --]

1.[Dandan]: This should be a NULL class library, not an instance of VarCheck Lib.

Agreed. Will update.

- Bret

From: Dandan Bi via groups.io<mailto:dandan.bi=intel.com@groups.io>
Sent: Wednesday, July 1, 2020 7:13 PM
To: devel@edk2.groups.io<mailto:devel@edk2.groups.io>; bret@corthon.com<mailto:bret@corthon.com>
Cc: Wang, Jian J<mailto:jian.j.wang@intel.com>; Wu, Hao A<mailto:hao.a.wu@intel.com>; liming.gao<mailto:liming.gao@intel.com>
Subject: [EXTERNAL] Re: [edk2-devel] [PATCH v6 04/14] MdeModulePkg: Define the VarCheckPolicyLib and SMM interface

1 comment inline, please check.



Thanks,
Dandan
> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Bret
> Barkelew
> Sent: Tuesday, June 23, 2020 2:41 PM
> To: devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>;
> Gao, Liming <liming.gao@intel.com>
> Subject: [edk2-devel] [PATCH v6 04/14] MdeModulePkg: Define the
> VarCheckPolicyLib and SMM interface
>
> https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fbugzilla.tianocore.org%2Fshow_bug.cgi%3Fid%3D2522&amp;data=02%7C01%7CBret.Barkelew%40microsoft.com%7Cc2c1537a2d7f41247b0308d81e2d8238%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637292528098010318&amp;sdata=yj3Z6JZariiNwPNLzp1Phb7bQHvtPYPA7U%2BjFkQMJ3k%3D&amp;reserved=0
>
> VariablePolicy is an updated interface to
> replace VarLock and VarCheckProtocol.
>
> This is an instance of a VarCheckLib that is backed by the
> VariablePolicyLib business logic. It also publishes the SMM
> calling interface for messages from the DXE protocol.
>
> Cc: Jian J Wang <jian.j.wang@intel.com>
> Cc: Hao A Wu <hao.a.wu@intel.com>
> Cc: Liming Gao <liming.gao@intel.com>
> Cc: Bret Barkelew <brbarkel@microsoft.com>
> Signed-off-by: Bret Barkelew <brbarkel@microsoft.com>
> ---
>  MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.c   | 320
> ++++++++++++++++++++
>  MdeModulePkg/Include/Guid/VarCheckPolicyMmi.h                |  54 ++++
>  MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.inf |  42 +++
>  MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.uni |  12 +
>  MdeModulePkg/MdeModulePkg.dec                                |   4 +
>  MdeModulePkg/MdeModulePkg.dsc                                |   2 +
>  6 files changed, 434 insertions(+)
>
> diff --git a/MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.c
> b/MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.c
> new file mode 100644
> index 000000000000..b64fc5f45332
> --- /dev/null
> +++ b/MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.c
> @@ -0,0 +1,320 @@
> +/** @file -- VarCheckPolicyLib.c
>
> +This is an instance of a VarCheck lib that leverages the business logic behind
1.[Dandan]: This should be a NULL class library, not an instance of VarCheck Lib.

>
> +the VariablePolicy code to make its decisions.
>
> +
>
> +Copyright (c) Microsoft Corporation.
>
> +SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +
>
> +**/
>
> +
>
> +#include <Library/VarCheckLib.h>
>
> +#include <Library/BaseLib.h>
>
> +#include <Library/DebugLib.h>
>
> +#include <Library/SafeIntLib.h>
>
> +#include <Library/MmServicesTableLib.h>
>
> +#include <Library/BaseMemoryLib.h>
>
> +#include <Library/MemoryAllocationLib.h>
>
> +
>
> +#include <Protocol/MmCommunication.h>
>
> +
>
> +#include <Protocol/VariablePolicy.h>
>
> +#include <Library/VariablePolicyLib.h>
>
> +
>
> +#include <Guid/VarCheckPolicyMmi.h>
>
> +
>
> +//================================================
>
> +// As a VarCheck library, we're linked into the VariableServices
>
> +// and may not be able to call them indirectly. To get around this,
>
> +// use the internal GetVariable function to query the variable store.
>
> +//================================================
>
> +EFI_STATUS
>
> +EFIAPI
>
> +VariableServiceGetVariable (
>
> +  IN      CHAR16            *VariableName,
>
> +  IN      EFI_GUID          *VendorGuid,
>
> +  OUT     UINT32            *Attributes OPTIONAL,
>
> +  IN OUT  UINTN             *DataSize,
>
> +  OUT     VOID              *Data
>
> +  );
>
> +
>
> +
>
> +/**
>
> +  MM Communication Handler to recieve commands from the DXE protocol
> for
>
> +  Variable Policies. This communication channel is used to register new
> policies
>
> +  and poll and toggle the enforcement of variable policies.
>
> +
>
> +  @param[in]      DispatchHandle      All parameters standard to MM
> communications convention.
>
> +  @param[in]      RegisterContext     All parameters standard to MM
> communications convention.
>
> +  @param[in,out]  CommBuffer          All parameters standard to MM
> communications convention.
>
> +  @param[in,out]  CommBufferSize      All parameters standard to MM
> communications convention.
>
> +
>
> +  @retval     EFI_SUCCESS
>
> +  @retval     EFI_INVALID_PARAMETER   CommBuffer or CommBufferSize is
> null pointer.
>
> +  @retval     EFI_INVALID_PARAMETER   CommBuffer size is wrong.
>
> +  @retval     EFI_INVALID_PARAMETER   Revision or signature don't match.
>
> +
>
> +**/
>
> +STATIC
>
> +EFI_STATUS
>
> +EFIAPI
>
> +VarCheckPolicyLibMmiHandler (
>
> +  IN     EFI_HANDLE                   DispatchHandle,
>
> +  IN     CONST VOID                   *RegisterContext,
>
> +  IN OUT VOID                         *CommBuffer,
>
> +  IN OUT UINTN                        *CommBufferSize
>
> +  )
>
> +{
>
> +  EFI_STATUS                                Status;
>
> +  EFI_STATUS                                SubCommandStatus;
>
> +  VAR_CHECK_POLICY_COMM_HEADER              *PolicyCommmHeader;
>
> +  VAR_CHECK_POLICY_COMM_IS_ENABLED_PARAMS   *IsEnabledParams;
>
> +  VAR_CHECK_POLICY_COMM_DUMP_PARAMS         *DumpParams;
>
> +  UINT8                                     *DumpInputBuffer;
>
> +  UINT8                                     *DumpOutputBuffer;
>
> +  UINTN                                     DumpTotalPages;
>
> +  VARIABLE_POLICY_ENTRY                     *PolicyEntry;
>
> +  UINTN                                     ExpectedSize;
>
> +  // Pagination Cache Variables
>
> +  static UINT8                              *PaginationCache = NULL;
>
> +  static UINTN                              PaginationCacheSize = 0;
>
> +  static UINT32                             CurrentPaginationCommand = 0;
>
> +
>
> +  Status = EFI_SUCCESS;
>
> +
>
> +  //
>
> +  // Validate some input parameters.
>
> +  //
>
> +  // If either of the pointers are NULL, we can't proceed.
>
> +  if (CommBuffer == NULL || CommBufferSize == NULL) {
>
> +    DEBUG(( DEBUG_INFO, "%a - Invalid comm buffer pointers!\n",
> __FUNCTION__ ));
>
> +    return EFI_INVALID_PARAMETER;
>
> +  }
>
> +  // If the size does not meet a minimum threshold, we cannot proceed.
>
> +  ExpectedSize = sizeof(VAR_CHECK_POLICY_COMM_HEADER);
>
> +  if (*CommBufferSize < ExpectedSize) {
>
> +    DEBUG(( DEBUG_INFO, "%a - Bad comm buffer size! %d < %d\n",
> __FUNCTION__, *CommBufferSize, ExpectedSize ));
>
> +    return EFI_INVALID_PARAMETER;
>
> +  }
>
> +  // Check the revision and the signature of the comm header.
>
> +  PolicyCommmHeader = CommBuffer;
>
> +  if (PolicyCommmHeader->Signature != VAR_CHECK_POLICY_COMM_SIG
> ||
>
> +      PolicyCommmHeader->Revision !=
> VAR_CHECK_POLICY_COMM_REVISION) {
>
> +    DEBUG(( DEBUG_INFO, "%a - Signature or revision are incorrect!\n",
> __FUNCTION__ ));
>
> +    // We have verified the buffer is not null and have enough size to hold
> Result field.
>
> +    PolicyCommmHeader->Result = EFI_INVALID_PARAMETER;
>
> +    return EFI_SUCCESS;
>
> +  }
>
> +
>
> +  // If we're in the middle of a paginated dump and any other command is
> sent,
>
> +  // pagination cache must be cleared.
>
> +  if (PaginationCache != NULL && PolicyCommmHeader->Command !=
> CurrentPaginationCommand) {
>
> +    FreePool (PaginationCache);
>
> +    PaginationCache = NULL;
>
> +    PaginationCacheSize = 0;
>
> +    CurrentPaginationCommand = 0;
>
> +  }
>
> +
>
> +  //
>
> +  // Now we can process the command as it was sent.
>
> +  //
>
> +  PolicyCommmHeader->Result = EFI_ABORTED;    // Set a default return for
> incomplete commands.
>
> +  switch(PolicyCommmHeader->Command) {
>
> +    case VAR_CHECK_POLICY_COMMAND_DISABLE:
>
> +      PolicyCommmHeader->Result = DisableVariablePolicy();
>
> +      break;
>
> +
>
> +    case VAR_CHECK_POLICY_COMMAND_IS_ENABLED:
>
> +      // Make sure that we're dealing with a reasonable size.
>
> +      // This add should be safe because these are fixed sizes so far.
>
> +      ExpectedSize +=
> sizeof(VAR_CHECK_POLICY_COMM_IS_ENABLED_PARAMS);
>
> +      if (*CommBufferSize < ExpectedSize) {
>
> +        DEBUG(( DEBUG_INFO, "%a - Bad comm buffer size! %d < %d\n",
> __FUNCTION__, *CommBufferSize, ExpectedSize ));
>
> +        PolicyCommmHeader->Result = EFI_INVALID_PARAMETER;
>
> +        break;
>
> +      }
>
> +
>
> +      // Now that we know we've got a valid size, we can fill in the rest of the
> data.
>
> +      IsEnabledParams =
> (VAR_CHECK_POLICY_COMM_IS_ENABLED_PARAMS*)((UINT8*)CommBuff
> er + sizeof(VAR_CHECK_POLICY_COMM_HEADER));
>
> +      IsEnabledParams->State = IsVariablePolicyEnabled();
>
> +      PolicyCommmHeader->Result = EFI_SUCCESS;
>
> +      break;
>
> +
>
> +    case VAR_CHECK_POLICY_COMMAND_REGISTER:
>
> +      // Make sure that we're dealing with a reasonable size.
>
> +      // This add should be safe because these are fixed sizes so far.
>
> +      ExpectedSize += sizeof(VARIABLE_POLICY_ENTRY);
>
> +      if (*CommBufferSize < ExpectedSize) {
>
> +        DEBUG(( DEBUG_INFO, "%a - Bad comm buffer size! %d < %d\n",
> __FUNCTION__, *CommBufferSize, ExpectedSize ));
>
> +        PolicyCommmHeader->Result = EFI_INVALID_PARAMETER;
>
> +        break;
>
> +      }
>
> +
>
> +      // At the very least, we can assume that we're working with a valid policy
> entry.
>
> +      // Time to compare its internal size.
>
> +      PolicyEntry = (VARIABLE_POLICY_ENTRY*)((UINT8*)CommBuffer +
> sizeof(VAR_CHECK_POLICY_COMM_HEADER));
>
> +      if (PolicyEntry->Version != VARIABLE_POLICY_ENTRY_REVISION ||
>
> +          PolicyEntry->Size < sizeof(VARIABLE_POLICY_ENTRY) ||
>
> +
> EFI_ERROR(SafeUintnAdd(sizeof(VAR_CHECK_POLICY_COMM_HEADER),
> PolicyEntry->Size, &ExpectedSize)) ||
>
> +          *CommBufferSize < ExpectedSize) {
>
> +        DEBUG(( DEBUG_INFO, "%a - Bad policy entry contents!\n",
> __FUNCTION__ ));
>
> +        PolicyCommmHeader->Result = EFI_INVALID_PARAMETER;
>
> +        break;
>
> +      }
>
> +
>
> +      PolicyCommmHeader->Result = RegisterVariablePolicy( PolicyEntry );
>
> +      break;
>
> +
>
> +    case VAR_CHECK_POLICY_COMMAND_DUMP:
>
> +      // Make sure that we're dealing with a reasonable size.
>
> +      // This add should be safe because these are fixed sizes so far.
>
> +      ExpectedSize += sizeof(VAR_CHECK_POLICY_COMM_DUMP_PARAMS)
> + VAR_CHECK_POLICY_MM_DUMP_BUFFER_SIZE;
>
> +      if (*CommBufferSize < ExpectedSize) {
>
> +        DEBUG(( DEBUG_INFO, "%a - Bad comm buffer size! %d < %d\n",
> __FUNCTION__, *CommBufferSize, ExpectedSize ));
>
> +        PolicyCommmHeader->Result = EFI_INVALID_PARAMETER;
>
> +        break;
>
> +      }
>
> +
>
> +      // Now that we know we've got a valid size, we can fill in the rest of the
> data.
>
> +      DumpParams =
> (VAR_CHECK_POLICY_COMM_DUMP_PARAMS*)(PolicyCommmHeader + 1);
>
> +
>
> +      // If we're requesting the first page, initialize the cache and get the sizes.
>
> +      if (DumpParams->PageRequested == 0) {
>
> +        if (PaginationCache != NULL) {
>
> +          FreePool (PaginationCache);
>
> +          PaginationCache = NULL;
>
> +        }
>
> +
>
> +        // Determine what the required size is going to be.
>
> +        DumpParams->TotalSize = 0;
>
> +        DumpParams->PageSize = 0;
>
> +        DumpParams->HasMore = FALSE;
>
> +        SubCommandStatus = DumpVariablePolicy (NULL, &DumpParams-
> >TotalSize);
>
> +        if (SubCommandStatus == EFI_BUFFER_TOO_SMALL && DumpParams-
> >TotalSize > 0) {
>
> +          CurrentPaginationCommand =
> VAR_CHECK_POLICY_COMMAND_DUMP;
>
> +          PaginationCacheSize = DumpParams->TotalSize;
>
> +          PaginationCache = AllocatePool (PaginationCacheSize);
>
> +          if (PaginationCache == NULL) {
>
> +            SubCommandStatus = EFI_OUT_OF_RESOURCES;
>
> +          }
>
> +        }
>
> +
>
> +        // If we've allocated our pagination cache, we're good to cache.
>
> +        if (PaginationCache != NULL) {
>
> +          SubCommandStatus = DumpVariablePolicy (PaginationCache,
> &DumpParams->TotalSize);
>
> +        }
>
> +
>
> +        // Populate the remaining fields and we can boogie.
>
> +        if (!EFI_ERROR (SubCommandStatus) && PaginationCache != NULL) {
>
> +          DumpParams->HasMore = TRUE;
>
> +        }
>
> +      }
>
> +      else if (PaginationCache != NULL) {
>
> +        DumpParams->TotalSize = (UINT32)PaginationCacheSize;
>
> +        DumpParams->PageSize =
> VAR_CHECK_POLICY_MM_DUMP_BUFFER_SIZE;
>
> +        DumpOutputBuffer = (UINT8*)(DumpParams + 1);
>
> +
>
> +        // Make sure that we don't over-index the cache.
>
> +        DumpTotalPages = PaginationCacheSize / DumpParams->PageSize;
>
> +        if (PaginationCacheSize % DumpParams->PageSize) DumpTotalPages++;
>
> +        if (DumpParams->PageRequested > DumpTotalPages) {
>
> +          SubCommandStatus = EFI_INVALID_PARAMETER;
>
> +        }
>
> +        else {
>
> +          // Figure out how far into the page cache we need to go for our next
> page.
>
> +          // We know the blind subtraction won't be bad because we already
> checked for page 0.
>
> +          DumpInputBuffer = &PaginationCache[DumpParams->PageSize *
> (DumpParams->PageRequested - 1)];
>
> +          // If we're getting the last page, adjust the PageSize.
>
> +          if (DumpParams->PageRequested == DumpTotalPages) {
>
> +            DumpParams->PageSize = PaginationCacheSize % DumpParams-
> >PageSize;
>
> +          }
>
> +          CopyMem (DumpOutputBuffer, DumpInputBuffer, DumpParams-
> >PageSize);
>
> +          // If we just got the last page, settle up the cache.
>
> +          if (DumpParams->PageRequested == DumpTotalPages) {
>
> +            DumpParams->HasMore = FALSE;
>
> +            FreePool (PaginationCache);
>
> +            PaginationCache = NULL;
>
> +            PaginationCacheSize = 0;
>
> +            CurrentPaginationCommand = 0;
>
> +          }
>
> +          // Otherwise, we could do more here.
>
> +          else {
>
> +            DumpParams->HasMore = TRUE;
>
> +          }
>
> +
>
> +          // If we made it this far, we're basically good.
>
> +          SubCommandStatus = EFI_SUCCESS;
>
> +        }
>
> +      }
>
> +      // If we've requested any other page than 0 and the cache is empty, we
> must have timed out.
>
> +      else {
>
> +        DumpParams->TotalSize = 0;
>
> +        DumpParams->PageSize = 0;
>
> +        DumpParams->HasMore = FALSE;
>
> +        SubCommandStatus = EFI_TIMEOUT;
>
> +      }
>
> +
>
> +      // There's currently no use for this, but it shouldn't be hard to implement.
>
> +      PolicyCommmHeader->Result = SubCommandStatus;
>
> +      break;
>
> +
>
> +    case VAR_CHECK_POLICY_COMMAND_LOCK:
>
> +      PolicyCommmHeader->Result = LockVariablePolicy();
>
> +      break;
>
> +
>
> +    default:
>
> +      // Mark unknown requested command as EFI_UNSUPPORTED.
>
> +      DEBUG(( DEBUG_INFO, "%a - Invalid command requested! %d\n",
> __FUNCTION__, PolicyCommmHeader->Command ));
>
> +      PolicyCommmHeader->Result = EFI_UNSUPPORTED;
>
> +      break;
>
> +  }
>
> +
>
> +  DEBUG(( DEBUG_VERBOSE, "%a - Command %d returning %r.\n",
> __FUNCTION__,
>
> +          PolicyCommmHeader->Command, PolicyCommmHeader->Result ));
>
> +
>
> +  return Status;
>
> +}
>
> +
>
> +
>
> +/**
>
> +  Constructor function of VarCheckPolicyLib to register VarCheck handler
> and
>
> +  SW MMI handlers.
>
> +
>
> +  @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 constructor executed correctly.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +VarCheckPolicyLibConstructor (
>
> +  IN EFI_HANDLE             ImageHandle,
>
> +  IN EFI_SYSTEM_TABLE       *SystemTable
>
> +  )
>
> +{
>
> +  EFI_STATUS    Status;
>
> +  EFI_HANDLE    DiscardedHandle;
>
> +
>
> +  // Initialize the business logic with the internal GetVariable handler.
>
> +  Status = InitVariablePolicyLib( VariableServiceGetVariable );
>
> +
>
> +  // Only proceed with init if the business logic could be initialized.
>
> +  if (!EFI_ERROR( Status )) {
>
> +    // Register the VarCheck handler for SetVariable filtering.
>
> +    // Forward the check to the business logic of the library.
>
> +    VarCheckLibRegisterSetVariableCheckHandler( ValidateSetVariable );
>
> +
>
> +    // Register the MMI handlers for receiving policy commands.
>
> +    DiscardedHandle = NULL;
>
> +    Status = gMmst->MmiHandlerRegister( VarCheckPolicyLibMmiHandler,
>
> +                                        &gVarCheckPolicyLibMmiHandlerGuid,
>
> +                                        &DiscardedHandle );
>
> +  }
>
> +  // Otherwise, there's not much we can do.
>
> +  else {
>
> +    DEBUG(( DEBUG_ERROR, "%a - Cannot Initialize VariablePolicyLib! %r\n",
> __FUNCTION__, Status ));
>
> +    ASSERT_EFI_ERROR( Status );
>
> +  }
>
> +
>
> +  return Status;
>
> +}
>
> diff --git a/MdeModulePkg/Include/Guid/VarCheckPolicyMmi.h
> b/MdeModulePkg/Include/Guid/VarCheckPolicyMmi.h
> new file mode 100644
> index 000000000000..77bcc62f3ccf
> --- /dev/null
> +++ b/MdeModulePkg/Include/Guid/VarCheckPolicyMmi.h
> @@ -0,0 +1,54 @@
> +/** @file -- VarCheckPolicyMmiCommon.h
>
> +This header contains communication definitions that are shared between
> DXE
>
> +and the MM component of VarCheckPolicy.
>
> +
>
> +Copyright (c) Microsoft Corporation.
>
> +SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +**/
>
> +
>
> +#ifndef _VAR_CHECK_POLICY_MMI_COMMON_H_
>
> +#define _VAR_CHECK_POLICY_MMI_COMMON_H_
>
> +
>
> +#define   VAR_CHECK_POLICY_COMM_SIG       SIGNATURE_32('V', 'C', 'P', 'C')
>
> +#define   VAR_CHECK_POLICY_COMM_REVISION  1
>
> +
>
> +#pragma pack(push, 1)
>
> +
>
> +typedef struct _VAR_CHECK_POLICY_COMM_HEADER {
>
> +  UINT32      Signature;
>
> +  UINT32      Revision;
>
> +  UINT32      Command;
>
> +  EFI_STATUS  Result;
>
> +} VAR_CHECK_POLICY_COMM_HEADER;
>
> +
>
> +typedef struct _VAR_CHECK_POLICY_COMM_IS_ENABLED_PARAMS {
>
> +  BOOLEAN     State;
>
> +} VAR_CHECK_POLICY_COMM_IS_ENABLED_PARAMS;
>
> +
>
> +typedef struct _VAR_CHECK_POLICY_COMM_DUMP_PARAMS {
>
> +  UINT32      PageRequested;
>
> +  UINT32      TotalSize;
>
> +  UINT32      PageSize;
>
> +  BOOLEAN     HasMore;
>
> +} VAR_CHECK_POLICY_COMM_DUMP_PARAMS;
>
> +
>
> +#pragma pack(pop)
>
> +
>
> +// Make sure that we will hold at least the headers.
>
> +#define   VAR_CHECK_POLICY_MM_COMM_BUFFER_SIZE
> MAX((OFFSET_OF(EFI_MM_COMMUNICATE_HEADER, Data) + sizeof
> (VAR_CHECK_POLICY_COMM_HEADER) + EFI_PAGES_TO_SIZE(1)),
> EFI_PAGES_TO_SIZE(4))
>
> +#define   VAR_CHECK_POLICY_MM_DUMP_BUFFER_SIZE
> (VAR_CHECK_POLICY_MM_COMM_BUFFER_SIZE - \
>
> +                                                    (OFFSET_OF(EFI_MM_COMMUNICATE_HEADER,
> Data) + \
>
> +                                                      sizeof(VAR_CHECK_POLICY_COMM_HEADER) + \
>
> +
> sizeof(VAR_CHECK_POLICY_COMM_DUMP_PARAMS)))
>
> +STATIC_ASSERT (
>
> +  VAR_CHECK_POLICY_MM_DUMP_BUFFER_SIZE <
> VAR_CHECK_POLICY_MM_COMM_BUFFER_SIZE,
>
> +  "an integer underflow may have occurred calculating
> VAR_CHECK_POLICY_MM_DUMP_BUFFER_SIZE"
>
> +  );
>
> +
>
> +#define   VAR_CHECK_POLICY_COMMAND_DISABLE      0x0001
>
> +#define   VAR_CHECK_POLICY_COMMAND_IS_ENABLED   0x0002
>
> +#define   VAR_CHECK_POLICY_COMMAND_REGISTER     0x0003
>
> +#define   VAR_CHECK_POLICY_COMMAND_DUMP         0x0004
>
> +#define   VAR_CHECK_POLICY_COMMAND_LOCK         0x0005
>
> +
>
> +#endif // _VAR_CHECK_POLICY_MMI_COMMON_H_
>
> diff --git a/MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.inf
> b/MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.inf
> new file mode 100644
> index 000000000000..077bcc8990ca
> --- /dev/null
> +++ b/MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.inf
> @@ -0,0 +1,42 @@
> +## @file VarCheckPolicyLib.inf
>
> +# This is an instance of a VarCheck lib that leverages the business logic
> behind
>
> +# the VariablePolicy code to make its decisions.
>
> +#
>
> +# Copyright (c) Microsoft Corporation.
>
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +##
>
> +
>
> +[Defines]
>
> +  INF_VERSION                    = 0x00010005
>
> +  BASE_NAME                      = VarCheckPolicyLib
>
> +  FILE_GUID                      = 9C28A48F-C884-4B1F-8B95-DEF125448023
>
> +  MODULE_TYPE                    = DXE_RUNTIME_DRIVER
>
> +  VERSION_STRING                 = 1.0
>
> +  LIBRARY_CLASS                  = NULL|DXE_RUNTIME_DRIVER
> DXE_SMM_DRIVER
>
> +  CONSTRUCTOR                    = VarCheckPolicyLibConstructor
>
> +
>
> +
>
> +[Sources]
>
> +  VarCheckPolicyLib.c
>
> +
>
> +
>
> +[Packages]
>
> +  MdePkg/MdePkg.dec
>
> +  MdeModulePkg/MdeModulePkg.dec
>
> +
>
> +
>
> +[LibraryClasses]
>
> +  BaseLib
>
> +  DebugLib
>
> +  BaseMemoryLib
>
> +  DxeServicesLib
>
> +  MemoryAllocationLib
>
> +  VarCheckLib
>
> +  VariablePolicyLib
>
> +  VariablePolicyHelperLib
>
> +  SafeIntLib
>
> +  MmServicesTableLib
>
> +
>
> +
>
> +[Guids]
>
> +  gVarCheckPolicyLibMmiHandlerGuid        ## CONSUME ## Used to register
> for MM Communication events.
>
> diff --git a/MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.uni
> b/MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.uni
> new file mode 100644
> index 000000000000..eedeeed15d31
> --- /dev/null
> +++ b/MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.uni
> @@ -0,0 +1,12 @@
> +// /** @file
>
> +// VarCheckPolicyLib.uni
>
> +//
>
> +// Copyright (c) Microsoft Corporation.
>
> +// SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +//
>
> +// **/
>
> +
>
> +
>
> +#string STR_MODULE_ABSTRACT             #language en-US "NULL library
> implementation that conforms to the VarCheck interface to allow
> VariablePolicy engine to enforce policies"
>
> +
>
> +#string STR_MODULE_DESCRIPTION          #language en-US "NULL library
> implementation that conforms to the VarCheck interface to allow
> VariablePolicy engine to enforce policies"
>
> diff --git a/MdeModulePkg/MdeModulePkg.dec
> b/MdeModulePkg/MdeModulePkg.dec
> index b21cd78c8787..9a3c9fe642d3 100644
> --- a/MdeModulePkg/MdeModulePkg.dec
> +++ b/MdeModulePkg/MdeModulePkg.dec
> @@ -385,6 +385,10 @@ [Guids]
>    ## Include/Guid/EndofS3Resume.h
>
>    gEdkiiEndOfS3ResumeGuid = { 0x96f5296d, 0x05f7, 0x4f3c, {0x84, 0x67, 0xe4,
> 0x56, 0x89, 0x0e, 0x0c, 0xb5 } }
>
>
>
> +  ## Used (similar to Variable Services) to communicate policies to the
> enforcement engine.
>
> +  # {DA1B0D11-D1A7-46C4-9DC9-F3714875C6EB}
>
> +  gVarCheckPolicyLibMmiHandlerGuid = { 0xda1b0d11, 0xd1a7, 0x46c4,
> { 0x9d, 0xc9, 0xf3, 0x71, 0x48, 0x75, 0xc6, 0xeb }}
>
> +
>
>    ## Include/Guid/S3SmmInitDone.h
>
>    gEdkiiS3SmmInitDoneGuid = { 0x8f9d4825, 0x797d, 0x48fc, { 0x84, 0x71,
> 0x84, 0x50, 0x25, 0x79, 0x2e, 0xf6 } }
>
>
>
> diff --git a/MdeModulePkg/MdeModulePkg.dsc
> b/MdeModulePkg/MdeModulePkg.dsc
> index 37795b9e4f58..f0a75a3b337b 100644
> --- a/MdeModulePkg/MdeModulePkg.dsc
> +++ b/MdeModulePkg/MdeModulePkg.dsc
> @@ -313,6 +313,7 @@ [Components]
>    MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf
>
>    MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf
>
>    MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf
>
> +  MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.inf
>
>    MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf
>
>    MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLib.inf
>
>    MdeModulePkg/Library/VarCheckPcdLib/VarCheckPcdLib.inf
>
> @@ -458,6 +459,7 @@ [Components.IA32, Components.X64]
>    MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf
>
>    MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf {
>
>      <LibraryClasses>
>
> +      NULL|MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.inf
>
>        NULL|MdeModulePkg/Library/VarCheckUefiLib/VarCheckUefiLib.inf
>
>        NULL|MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLib.inf
>
>        NULL|MdeModulePkg/Library/VarCheckPcdLib/VarCheckPcdLib.inf
>
> --
> 2.26.2.windows.1.8.g01c50adf56.20200515075929
>
>
> -=-=-=-=-=-=
> Groups.io Links: You receive all messages sent to this group.
>
> View/Reply Online (#61590): https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fedk2.groups.io%2Fg%2Fdevel%2Fmessage%2F61590&amp;data=02%7C01%7CBret.Barkelew%40microsoft.com%7Cc2c1537a2d7f41247b0308d81e2d8238%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637292528098010318&amp;sdata=XkVKxTN1iXFWsCvsgFYmCWO2JZrIUu1NqKikSIEiBS8%3D&amp;reserved=0
> Mute This Topic: https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgroups.io%2Fmt%2F75057699%2F1768738&amp;data=02%7C01%7CBret.Barkelew%40microsoft.com%7Cc2c1537a2d7f41247b0308d81e2d8238%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637292528098010318&amp;sdata=rnMmHC3VAKP3h0X461RptcvVE79kmZdOV3j7N66gHkQ%3D&amp;reserved=0
> Group Owner: devel+owner@edk2.groups.io
> Unsubscribe: https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fedk2.groups.io%2Fg%2Fdevel%2Funsub&amp;data=02%7C01%7CBret.Barkelew%40microsoft.com%7Cc2c1537a2d7f41247b0308d81e2d8238%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637292528098010318&amp;sdata=1VhBeVczCZ4xGGrq2aQFW4r1EtI7jebdgOX0EtFTTKc%3D&amp;reserved=0  [dandan.bi@intel.com]
> -=-=-=-=-=-=





[-- Attachment #2: Type: text/html, Size: 52078 bytes --]

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature
  2020-07-02  2:13 ` [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature Dandan Bi
@ 2020-07-02  6:45   ` Bret Barkelew
  2020-07-02  6:47     ` Bret Barkelew
  0 siblings, 1 reply; 48+ messages in thread
From: Bret Barkelew @ 2020-07-02  6:45 UTC (permalink / raw)
  To: devel@edk2.groups.io, dandan.bi@intel.com, bret@corthon.com
  Cc: Yao, Jiewen, Zhang, Chao B, Wang, Jian J, Wu, Hao A, liming.gao,
	Justen, Jordan L, Laszlo Ersek, Ard Biesheuvel, Andrew Fish,
	Ni, Ray

[-- Attachment #1: Type: text/plain, Size: 13933 bytes --]

Certainly do:
https://github.com/corthon/edk2/tree/var_policy_dev_submission_v6

I’ve already made a change from some of your feedback in that branch and will restructure the patches for v7 once all feedback is in.
Thanks!

- Bret

From: Dandan Bi via groups.io<mailto:dandan.bi=intel.com@groups.io>
Sent: Wednesday, July 1, 2020 7:13 PM
To: devel@edk2.groups.io<mailto:devel@edk2.groups.io>; bret@corthon.com<mailto:bret@corthon.com>
Cc: Yao, Jiewen<mailto:jiewen.yao@intel.com>; Zhang, Chao B<mailto:chao.b.zhang@intel.com>; Wang, Jian J<mailto:jian.j.wang@intel.com>; Wu, Hao A<mailto:hao.a.wu@intel.com>; liming.gao<mailto:liming.gao@intel.com>; Justen, Jordan L<mailto:jordan.l.justen@intel.com>; Laszlo Ersek<mailto:lersek@redhat.com>; Ard Biesheuvel<mailto:ard.biesheuvel@arm.com>; Andrew Fish<mailto:afish@apple.com>; Ni, Ray<mailto:ray.ni@intel.com>
Subject: [EXTERNAL] Re: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature

Hi Bret,

Thanks for the contribution.

I have taken an overview of this patch series and have some small comments in the related patches, please check in sub-patch.

I will review the patch series more in details and bring more comments back if have. Do you have a branch for these patches in GitHub? Which should be easy for review.


Thanks,
Dandan

> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Bret
> Barkelew
> Sent: Tuesday, June 23, 2020 2:41 PM
> To: devel@edk2.groups.io
> Cc: Yao, Jiewen <jiewen.yao@intel.com>; Zhang, Chao B
> <chao.b.zhang@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao
> A <hao.a.wu@intel.com>; Gao, Liming <liming.gao@intel.com>; Justen,
> Jordan L <jordan.l.justen@intel.com>; Laszlo Ersek <lersek@redhat.com>;
> Ard Biesheuvel <ard.biesheuvel@arm.com>; Andrew Fish
> <afish@apple.com>; Ni, Ray <ray.ni@intel.com>
> Subject: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature
>
> REF:https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fbugzilla.tianocore.org%2Fshow_bug.cgi%3Fid%3D2522&amp;data=02%7C01%7Cbret.barkelew%40microsoft.com%7C3fb90fd337a24d2c965d08d81e2d9081%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637292528333631839&amp;sdata=7hyxOuoJb08Ncpj6Ww4ABCFx48tdOUKmGZq5uCxLHjo%3D&amp;reserved=0
>
> The 14 patches in this series add the VariablePolicy feature to the core,
> deprecate Edk2VarLock (while adding a compatibility layer to reduce code
> churn), and integrate the VariablePolicy libraries and protocols into Variable
> Services.
>
> Since the integration requires multiple changes, including adding libraries, a
> protocol, an SMI communication handler, and VariableServices integration,
> the patches are broken up by individual library additions and then a final
> integration. Security-sensitive changes like bypassing Authenticated Variable
> enforcement are also broken out into individual patches so that attention can
> be called directly to them.
>
> Platform porting instructions are described in this wiki entry:
> https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Ftianocore%2Ftianocore.github.io%2Fwiki%2FVariablePolicy-&amp;data=02%7C01%7Cbret.barkelew%40microsoft.com%7C3fb90fd337a24d2c965d08d81e2d9081%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637292528333631839&amp;sdata=B%2Bl%2F43l6xTTzvLw00gyXElHqUlu%2BfwhuUJOIEh%2BHN6g%3D&amp;reserved=0
> Protocol---Enhanced-Method-for-Managing-Variables#platform-porting
>
> Discussion of the feature can be found in multiple places throughout the last
> year on the RFC channel, staging branches, and in devel.
>
> Most recently, this subject was discussed in this thread:
> https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fedk2.groups.io%2Fg%2Fdevel%2Fmessage%2F53712&amp;data=02%7C01%7Cbret.barkelew%40microsoft.com%7C3fb90fd337a24d2c965d08d81e2d9081%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637292528333631839&amp;sdata=UMEtJ5hxVBmvcWPSLRwDZ6P6bOaE8N3v5sEgdzyPffw%3D&amp;reserved=0
> (the code branches shared in that discussion are now out of date, but the
> whitepapers and discussion are relevant).
>
> Cc: Jiewen Yao <jiewen.yao@intel.com>
> Cc: Chao Zhang <chao.b.zhang@intel.com>
> Cc: Jian J Wang <jian.j.wang@intel.com>
> Cc: Hao A Wu <hao.a.wu@intel.com>
> Cc: Liming Gao <liming.gao@intel.com>
> Cc: Jordan Justen <jordan.l.justen@intel.com>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
> Cc: Andrew Fish <afish@apple.com>
> Cc: Ray Ni <ray.ni@intel.com>
> Cc: Bret Barkelew <brbarkel@microsoft.com>
> Signed-off-by: Bret Barkelew <brbarkel@microsoft.com>
>
> v6 changes:
> * Fix an issue with uninitialized Status in InitVariablePolicyLib() and
> DeinitVariablePolicyLib()
> * Fix GCC building in shell-based functional test
> * Rebase on latest origin/master
>
> v5 changes:
> * Fix the CONST mismatch in VariablePolicy.h and VariablePolicySmmDxe.c
> * Fix EFIAPI mismatches in the functional unittest
> * Rebase on latest origin/master
>
> v4 changes:
> * Remove Optional PcdAllowVariablePolicyEnforcementDisable PCD from
> platforms
> * Rebase on master
> * Migrate to new MmCommunicate2 protocol
> * Fix an oversight in the default return value for
> InitMmCommonCommBuffer
> * Fix in VariablePolicyLib to allow ExtraInitRuntimeDxe to consume variables
>
> V3 changes:
> * Address all non-unittest issues with ECC
> * Make additional style changes
> * Include section name in hunk headers in "ini-style" files
> * Remove requirement for the EdkiiPiSmmCommunicationsRegionTable
> driver
>   (now allocates its own buffer)
> * Change names from VARIABLE_POLICY_PROTOCOL and
> gVariablePolicyProtocolGuid
>   to EDKII_VARIABLE_POLICY_PROTOCOL and
> gEdkiiVariablePolicyProtocolGuid
> * Fix GCC warning about initializing externs
> * Add UNI strings for new PCD
> * Add patches for ArmVirtPkg, OvmfXen, and UefiPayloadPkg
> * Reorder patches according to Liming's feedback about adding to platforms
>   before changing variable driver
>
> V2 changes:
> * Fixed implementation for RuntimeDxe
> * Add PCD to block DisableVariablePolicy
> * Fix the DumpVariablePolicy pagination in SMM
>
> Bret Barkelew (14):
>   MdeModulePkg: Define the VariablePolicy protocol interface
>   MdeModulePkg: Define the VariablePolicyLib
>   MdeModulePkg: Define the VariablePolicyHelperLib
>   MdeModulePkg: Define the VarCheckPolicyLib and SMM interface
>   OvmfPkg: Add VariablePolicy engine to OvmfPkg platform
>   EmulatorPkg: Add VariablePolicy engine to EmulatorPkg platform
>   ArmVirtPkg: Add VariablePolicy engine to ArmVirtPkg platform
>   UefiPayloadPkg: Add VariablePolicy engine to UefiPayloadPkg platform
>   MdeModulePkg: Connect VariablePolicy business logic to
>     VariableServices
>   MdeModulePkg: Allow VariablePolicy state to delete protected variables
>   SecurityPkg: Allow VariablePolicy state to delete authenticated
>     variables
>   MdeModulePkg: Change TCG MOR variables to use VariablePolicy
>   MdeModulePkg: Drop VarLock from RuntimeDxe variable driver
>   MdeModulePkg: Add a shell-based functional test for VariablePolicy
>
>  MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.c
> |  320 +++
>  MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.c
> |  396 ++++
>  MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitNull.c
> |   46 +
>
> MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitRuntimeDx
> e.c               |   85 +
>  MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c
> |  816 +++++++
>
> MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePo
> licyUnitTest.c   | 2440 ++++++++++++++++++++
>
> MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/VariablePolicyFu
> ncTestApp.c        | 1978 ++++++++++++++++
>  MdeModulePkg/Universal/Variable/RuntimeDxe/TcgMorLockDxe.c
> |   52 +-
>  MdeModulePkg/Universal/Variable/RuntimeDxe/TcgMorLockSmm.c
> |   60 +-
>  MdeModulePkg/Universal/Variable/RuntimeDxe/VarCheck.c
> |   49 +-
>  MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c
> |   53 +
>
> MdeModulePkg/Universal/Variable/RuntimeDxe/VariableLockRequstToLock
> .c                    |   71 +
>  MdeModulePkg/Universal/Variable/RuntimeDxe/VariablePolicySmmDxe.c
> |  642 +++++
>
> MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.
> c                       |   14 +
>  SecurityPkg/Library/AuthVariableLib/AuthService.c                                        |   22
> +-
>  ArmVirtPkg/ArmVirt.dsc.inc                                                               |    4 +
>  EmulatorPkg/EmulatorPkg.dsc                                                              |    3 +
>  MdeModulePkg/Include/Guid/VarCheckPolicyMmi.h                                            |
> 54 +
>  MdeModulePkg/Include/Library/VariablePolicyHelperLib.h
> |  164 ++
>  MdeModulePkg/Include/Library/VariablePolicyLib.h                                         |
> 207 ++
>  MdeModulePkg/Include/Protocol/VariablePolicy.h                                           |
> 157 ++
>  MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.inf
> |   42 +
>  MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.uni
> |   12 +
>  MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf
> |   35 +
>  MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.uni
> |   12 +
>  MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf
> |   44 +
>  MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.uni
> |   12 +
>  MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf
> |   51 +
>
> MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePo
> licyUnitTest.inf |   40 +
>  MdeModulePkg/MdeModulePkg.ci.yaml                                                        |    4 +-
>  MdeModulePkg/MdeModulePkg.dec                                                            |   26 +-
>  MdeModulePkg/MdeModulePkg.dsc                                                            |   15 +
>  MdeModulePkg/MdeModulePkg.uni                                                            |    7 +
>  MdeModulePkg/Test/MdeModulePkgHostTest.dsc                                               |
> 11 +
>  MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/Readme.md
> |   55 +
>
> MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/VariablePolicyFu
> ncTestApp.inf      |   42 +
>  MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
> |    5 +
>  MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf
> |    4 +
>
> MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.i
> nf                     |   10 +
>
> MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf
> |    4 +
>  OvmfPkg/OvmfPkgIa32.dsc                                                                  |    5 +
>  OvmfPkg/OvmfPkgIa32X64.dsc                                                               |    5 +
>  OvmfPkg/OvmfPkgX64.dsc                                                                   |    5 +
>  OvmfPkg/OvmfXen.dsc                                                                      |    4 +
>  SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf                                  |
> 2 +
>  UefiPayloadPkg/UefiPayloadPkgIa32.dsc                                                    |    4 +
>  UefiPayloadPkg/UefiPayloadPkgIa32X64.dsc                                                 |    4 +
>  47 files changed, 8015 insertions(+), 78 deletions(-)  create mode 100644
> MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.c
>  create mode 100644
> MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.c
>  create mode 100644
> MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitNull.c
>  create mode 100644
> MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitRuntimeDx
> e.c
>  create mode 100644
> MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c
>  create mode 100644
> MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePo
> licyUnitTest.c
>  create mode 100644
> MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/VariablePolicyFu
> ncTestApp.c
>  create mode 100644
> MdeModulePkg/Universal/Variable/RuntimeDxe/VariableLockRequstToLock
> .c
>  create mode 100644
> MdeModulePkg/Universal/Variable/RuntimeDxe/VariablePolicySmmDxe.c
>  create mode 100644 MdeModulePkg/Include/Guid/VarCheckPolicyMmi.h
>  create mode 100644
> MdeModulePkg/Include/Library/VariablePolicyHelperLib.h
>  create mode 100644 MdeModulePkg/Include/Library/VariablePolicyLib.h
>  create mode 100644 MdeModulePkg/Include/Protocol/VariablePolicy.h
>  create mode 100644
> MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.inf
>  create mode 100644
> MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.uni
>  create mode 100644
> MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf
>  create mode 100644
> MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.uni
>  create mode 100644
> MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf
>  create mode 100644
> MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.uni
>  create mode 100644
> MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf
>  create mode 100644
> MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePo
> licyUnitTest.inf
>  create mode 100644
> MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/Readme.md
>  create mode 100644
> MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/VariablePolicyFu
> ncTestApp.inf
>
> --
> 2.26.2.windows.1.8.g01c50adf56.20200515075929
>
>
>





[-- Attachment #2: Type: text/html, Size: 25486 bytes --]

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature
  2020-07-02  6:45   ` Bret Barkelew
@ 2020-07-02  6:47     ` Bret Barkelew
  2020-07-02 11:06       ` Laszlo Ersek
  0 siblings, 1 reply; 48+ messages in thread
From: Bret Barkelew @ 2020-07-02  6:47 UTC (permalink / raw)
  To: devel@edk2.groups.io, dandan.bi@intel.com, bret@corthon.com
  Cc: Yao, Jiewen, Zhang, Chao B, Wang, Jian J, Wu, Hao A, liming.gao,
	Justen, Jordan L, Laszlo Ersek, Ard Biesheuvel, Andrew Fish,
	Ni, Ray


[-- Attachment #1.1: Type: text/plain, Size: 15911 bytes --]

Actually, if you want to leave feedback in the CI test PR that I made for this version, I’m happy to discuss there as well.
https://github.com/tianocore/edk2/pull/718/files

- Bret

From: Bret Barkelew via groups.io<mailto:bret.barkelew=microsoft.com@groups.io>
Sent: Wednesday, July 1, 2020 11:46 PM
To: devel@edk2.groups.io<mailto:devel@edk2.groups.io>; dandan.bi@intel.com<mailto:dandan.bi@intel.com>; bret@corthon.com<mailto:bret@corthon.com>
Cc: Yao, Jiewen<mailto:jiewen.yao@intel.com>; Zhang, Chao B<mailto:chao.b.zhang@intel.com>; Wang, Jian J<mailto:jian.j.wang@intel.com>; Wu, Hao A<mailto:hao.a.wu@intel.com>; liming.gao<mailto:liming.gao@intel.com>; Justen, Jordan L<mailto:jordan.l.justen@intel.com>; Laszlo Ersek<mailto:lersek@redhat.com>; Ard Biesheuvel<mailto:ard.biesheuvel@arm.com>; Andrew Fish<mailto:afish@apple.com>; Ni, Ray<mailto:ray.ni@intel.com>
Subject: [EXTERNAL] Re: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature

Certainly do:
https://github.com/corthon/edk2/tree/var_policy_dev_submission_v6<https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fcorthon%2Fedk2%2Ftree%2Fvar_policy_dev_submission_v6&data=02%7C01%7CBret.Barkelew%40microsoft.com%7Cb17b461b222e43cd5bf208d81e5393b6%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637292691604096534&sdata=SRGyTajaFs777zq411m9Xjnyqv7lV6uZ0FSkv0le9ug%3D&reserved=0>

I’ve already made a change from some of your feedback in that branch and will restructure the patches for v7 once all feedback is in.
Thanks!

- Bret

From: Dandan Bi via groups.io<mailto:dandan.bi=intel.com@groups.io>
Sent: Wednesday, July 1, 2020 7:13 PM
To: devel@edk2.groups.io<mailto:devel@edk2.groups.io>; bret@corthon.com<mailto:bret@corthon.com>
Cc: Yao, Jiewen<mailto:jiewen.yao@intel.com>; Zhang, Chao B<mailto:chao.b.zhang@intel.com>; Wang, Jian J<mailto:jian.j.wang@intel.com>; Wu, Hao A<mailto:hao.a.wu@intel.com>; liming.gao<mailto:liming.gao@intel.com>; Justen, Jordan L<mailto:jordan.l.justen@intel.com>; Laszlo Ersek<mailto:lersek@redhat.com>; Ard Biesheuvel<mailto:ard.biesheuvel@arm.com>; Andrew Fish<mailto:afish@apple.com>; Ni, Ray<mailto:ray.ni@intel.com>
Subject: [EXTERNAL] Re: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature

Hi Bret,

Thanks for the contribution.

I have taken an overview of this patch series and have some small comments in the related patches, please check in sub-patch.

I will review the patch series more in details and bring more comments back if have. Do you have a branch for these patches in GitHub? Which should be easy for review.


Thanks,
Dandan

> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Bret
> Barkelew
> Sent: Tuesday, June 23, 2020 2:41 PM
> To: devel@edk2.groups.io
> Cc: Yao, Jiewen <jiewen.yao@intel.com>; Zhang, Chao B
> <chao.b.zhang@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao
> A <hao.a.wu@intel.com>; Gao, Liming <liming.gao@intel.com>; Justen,
> Jordan L <jordan.l.justen@intel.com>; Laszlo Ersek <lersek@redhat.com>;
> Ard Biesheuvel <ard.biesheuvel@arm.com>; Andrew Fish
> <afish@apple.com>; Ni, Ray <ray.ni@intel.com>
> Subject: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature
>
> REF:https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fbugzilla.tianocore.org%2Fshow_bug.cgi%3Fid%3D2522&amp;data=02%7C01%7Cbret.barkelew%40microsoft.com%7C3fb90fd337a24d2c965d08d81e2d9081%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637292528333631839&amp;sdata=7hyxOuoJb08Ncpj6Ww4ABCFx48tdOUKmGZq5uCxLHjo%3D&amp;reserved=0
>
> The 14 patches in this series add the VariablePolicy feature to the core,
> deprecate Edk2VarLock (while adding a compatibility layer to reduce code
> churn), and integrate the VariablePolicy libraries and protocols into Variable
> Services.
>
> Since the integration requires multiple changes, including adding libraries, a
> protocol, an SMI communication handler, and VariableServices integration,
> the patches are broken up by individual library additions and then a final
> integration. Security-sensitive changes like bypassing Authenticated Variable
> enforcement are also broken out into individual patches so that attention can
> be called directly to them.
>
> Platform porting instructions are described in this wiki entry:
> https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Ftianocore%2Ftianocore.github.io%2Fwiki%2FVariablePolicy-&amp;data=02%7C01%7Cbret.barkelew%40microsoft.com%7C3fb90fd337a24d2c965d08d81e2d9081%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637292528333631839&amp;sdata=B%2Bl%2F43l6xTTzvLw00gyXElHqUlu%2BfwhuUJOIEh%2BHN6g%3D&amp;reserved=0<https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Ftianocore%2Ftianocore.github.io%2Fwiki%2FVariablePolicy-&data=02%7C01%7CBret.Barkelew%40microsoft.com%7Cb17b461b222e43cd5bf208d81e5393b6%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637292691604096534&sdata=xPoLF1MpgNZQSH8GieCss7mkV%2BTZwskpwPliwlw6L7E%3D&reserved=0>
> Protocol---Enhanced-Method-for-Managing-Variables#platform-porting
>
> Discussion of the feature can be found in multiple places throughout the last
> year on the RFC channel, staging branches, and in devel.
>
> Most recently, this subject was discussed in this thread:
> https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fedk2.groups.io%2Fg%2Fdevel%2Fmessage%2F53712&amp;data=02%7C01%7Cbret.barkelew%40microsoft.com%7C3fb90fd337a24d2c965d08d81e2d9081%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637292528333631839&amp;sdata=UMEtJ5hxVBmvcWPSLRwDZ6P6bOaE8N3v5sEgdzyPffw%3D&amp;reserved=0<https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fedk2.groups.io%2Fg%2Fdevel%2Fmessage%2F53712&data=02%7C01%7CBret.Barkelew%40microsoft.com%7Cb17b461b222e43cd5bf208d81e5393b6%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637292691604106492&sdata=tukW1pNO%2F2BirYSWIKwSTWuOIvm9JoD3IY7mCraT12k%3D&reserved=0>
> (the code branches shared in that discussion are now out of date, but the
> whitepapers and discussion are relevant).
>
> Cc: Jiewen Yao <jiewen.yao@intel.com>
> Cc: Chao Zhang <chao.b.zhang@intel.com>
> Cc: Jian J Wang <jian.j.wang@intel.com>
> Cc: Hao A Wu <hao.a.wu@intel.com>
> Cc: Liming Gao <liming.gao@intel.com>
> Cc: Jordan Justen <jordan.l.justen@intel.com>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
> Cc: Andrew Fish <afish@apple.com>
> Cc: Ray Ni <ray.ni@intel.com>
> Cc: Bret Barkelew <brbarkel@microsoft.com>
> Signed-off-by: Bret Barkelew <brbarkel@microsoft.com>
>
> v6 changes:
> * Fix an issue with uninitialized Status in InitVariablePolicyLib() and
> DeinitVariablePolicyLib()
> * Fix GCC building in shell-based functional test
> * Rebase on latest origin/master
>
> v5 changes:
> * Fix the CONST mismatch in VariablePolicy.h and VariablePolicySmmDxe.c
> * Fix EFIAPI mismatches in the functional unittest
> * Rebase on latest origin/master
>
> v4 changes:
> * Remove Optional PcdAllowVariablePolicyEnforcementDisable PCD from
> platforms
> * Rebase on master
> * Migrate to new MmCommunicate2 protocol
> * Fix an oversight in the default return value for
> InitMmCommonCommBuffer
> * Fix in VariablePolicyLib to allow ExtraInitRuntimeDxe to consume variables
>
> V3 changes:
> * Address all non-unittest issues with ECC
> * Make additional style changes
> * Include section name in hunk headers in "ini-style" files
> * Remove requirement for the EdkiiPiSmmCommunicationsRegionTable
> driver
>   (now allocates its own buffer)
> * Change names from VARIABLE_POLICY_PROTOCOL and
> gVariablePolicyProtocolGuid
>   to EDKII_VARIABLE_POLICY_PROTOCOL and
> gEdkiiVariablePolicyProtocolGuid
> * Fix GCC warning about initializing externs
> * Add UNI strings for new PCD
> * Add patches for ArmVirtPkg, OvmfXen, and UefiPayloadPkg
> * Reorder patches according to Liming's feedback about adding to platforms
>   before changing variable driver
>
> V2 changes:
> * Fixed implementation for RuntimeDxe
> * Add PCD to block DisableVariablePolicy
> * Fix the DumpVariablePolicy pagination in SMM
>
> Bret Barkelew (14):
>   MdeModulePkg: Define the VariablePolicy protocol interface
>   MdeModulePkg: Define the VariablePolicyLib
>   MdeModulePkg: Define the VariablePolicyHelperLib
>   MdeModulePkg: Define the VarCheckPolicyLib and SMM interface
>   OvmfPkg: Add VariablePolicy engine to OvmfPkg platform
>   EmulatorPkg: Add VariablePolicy engine to EmulatorPkg platform
>   ArmVirtPkg: Add VariablePolicy engine to ArmVirtPkg platform
>   UefiPayloadPkg: Add VariablePolicy engine to UefiPayloadPkg platform
>   MdeModulePkg: Connect VariablePolicy business logic to
>     VariableServices
>   MdeModulePkg: Allow VariablePolicy state to delete protected variables
>   SecurityPkg: Allow VariablePolicy state to delete authenticated
>     variables
>   MdeModulePkg: Change TCG MOR variables to use VariablePolicy
>   MdeModulePkg: Drop VarLock from RuntimeDxe variable driver
>   MdeModulePkg: Add a shell-based functional test for VariablePolicy
>
>  MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.c
> |  320 +++
>  MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.c
> |  396 ++++
>  MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitNull.c
> |   46 +
>
> MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitRuntimeDx
> e.c               |   85 +
>  MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c
> |  816 +++++++
>
> MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePo
> licyUnitTest.c   | 2440 ++++++++++++++++++++
>
> MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/VariablePolicyFu
> ncTestApp.c        | 1978 ++++++++++++++++
>  MdeModulePkg/Universal/Variable/RuntimeDxe/TcgMorLockDxe.c
> |   52 +-
>  MdeModulePkg/Universal/Variable/RuntimeDxe/TcgMorLockSmm.c
> |   60 +-
>  MdeModulePkg/Universal/Variable/RuntimeDxe/VarCheck.c
> |   49 +-
>  MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c
> |   53 +
>
> MdeModulePkg/Universal/Variable/RuntimeDxe/VariableLockRequstToLock
> .c                    |   71 +
>  MdeModulePkg/Universal/Variable/RuntimeDxe/VariablePolicySmmDxe.c
> |  642 +++++
>
> MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.
> c                       |   14 +
>  SecurityPkg/Library/AuthVariableLib/AuthService.c                                        |   22
> +-
>  ArmVirtPkg/ArmVirt.dsc.inc                                                               |    4 +
>  EmulatorPkg/EmulatorPkg.dsc                                                              |    3 +
>  MdeModulePkg/Include/Guid/VarCheckPolicyMmi.h                                            |
> 54 +
>  MdeModulePkg/Include/Library/VariablePolicyHelperLib.h
> |  164 ++
>  MdeModulePkg/Include/Library/VariablePolicyLib.h                                         |
> 207 ++
>  MdeModulePkg/Include/Protocol/VariablePolicy.h                                           |
> 157 ++
>  MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.inf
> |   42 +
>  MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.uni
> |   12 +
>  MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf
> |   35 +
>  MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.uni
> |   12 +
>  MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf
> |   44 +
>  MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.uni
> |   12 +
>  MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf
> |   51 +
>
> MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePo
> licyUnitTest.inf |   40 +
>  MdeModulePkg/MdeModulePkg.ci.yaml                                                        |    4 +-
>  MdeModulePkg/MdeModulePkg.dec                                                            |   26 +-
>  MdeModulePkg/MdeModulePkg.dsc                                                            |   15 +
>  MdeModulePkg/MdeModulePkg.uni                                                            |    7 +
>  MdeModulePkg/Test/MdeModulePkgHostTest.dsc                                               |
> 11 +
>  MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/Readme.md
> |   55 +
>
> MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/VariablePolicyFu
> ncTestApp.inf      |   42 +
>  MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
> |    5 +
>  MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf
> |    4 +
>
> MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.i
> nf                     |   10 +
>
> MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf
> |    4 +
>  OvmfPkg/OvmfPkgIa32.dsc                                                                  |    5 +
>  OvmfPkg/OvmfPkgIa32X64.dsc                                                               |    5 +
>  OvmfPkg/OvmfPkgX64.dsc                                                                   |    5 +
>  OvmfPkg/OvmfXen.dsc                                                                      |    4 +
>  SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf                                  |
> 2 +
>  UefiPayloadPkg/UefiPayloadPkgIa32.dsc                                                    |    4 +
>  UefiPayloadPkg/UefiPayloadPkgIa32X64.dsc                                                 |    4 +
>  47 files changed, 8015 insertions(+), 78 deletions(-)  create mode 100644
> MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.c
>  create mode 100644
> MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.c
>  create mode 100644
> MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitNull.c
>  create mode 100644
> MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitRuntimeDx
> e.c
>  create mode 100644
> MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c
>  create mode 100644
> MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePo
> licyUnitTest.c
>  create mode 100644
> MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/VariablePolicyFu
> ncTestApp.c
>  create mode 100644
> MdeModulePkg/Universal/Variable/RuntimeDxe/VariableLockRequstToLock
> .c
>  create mode 100644
> MdeModulePkg/Universal/Variable/RuntimeDxe/VariablePolicySmmDxe.c
>  create mode 100644 MdeModulePkg/Include/Guid/VarCheckPolicyMmi.h
>  create mode 100644
> MdeModulePkg/Include/Library/VariablePolicyHelperLib.h
>  create mode 100644 MdeModulePkg/Include/Library/VariablePolicyLib.h
>  create mode 100644 MdeModulePkg/Include/Protocol/VariablePolicy.h
>  create mode 100644
> MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.inf
>  create mode 100644
> MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.uni
>  create mode 100644
> MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf
>  create mode 100644
> MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.uni
>  create mode 100644
> MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf
>  create mode 100644
> MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.uni
>  create mode 100644
> MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf
>  create mode 100644
> MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePo
> licyUnitTest.inf
>  create mode 100644
> MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/Readme.md
>  create mode 100644
> MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/VariablePolicyFu
> ncTestApp.inf
>
> --
> 2.26.2.windows.1.8.g01c50adf56.20200515075929
>
>
>





[-- Attachment #1.2: Type: text/html, Size: 27683 bytes --]

[-- Attachment #2: BE354566C465460E984C3B86778F621D.png --]
[-- Type: image/png, Size: 140 bytes --]

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [edk2-devel] [PATCH v6 02/14] MdeModulePkg: Define the VariablePolicyLib
  2020-07-02  2:13   ` [edk2-devel] " Dandan Bi
@ 2020-07-02  7:16     ` Bret Barkelew
  0 siblings, 0 replies; 48+ messages in thread
From: Bret Barkelew @ 2020-07-02  7:16 UTC (permalink / raw)
  To: devel@edk2.groups.io, dandan.bi@intel.com, bret@corthon.com
  Cc: Wang, Jian J, Wu, Hao A, liming.gao

[-- Attachment #1: Type: text/plain, Size: 164673 bytes --]

  1.  Done
  2.  Done
  3.  BestResult can’t be anything but NULL if MatchPriority isn’t initialized, so the second half of this will never be evaluated, but I see your point. I’ve added a default initialization for the variable.
  4.  Done

Thanks!

- Bret

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

4 comments inline, please check.

Thanks,
Dandan
> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Bret
> Barkelew
> Sent: Tuesday, June 23, 2020 2:41 PM
> To: devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>;
> Gao, Liming <liming.gao@intel.com>
> Subject: [edk2-devel] [PATCH v6 02/14] MdeModulePkg: Define the
> VariablePolicyLib
>
> https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fbugzilla.tianocore.org%2Fshow_bug.cgi%3Fid%3D2522&amp;data=02%7C01%7Cbret.barkelew%40microsoft.com%7C4ff781c598384282187708d81e2d8858%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637292528218882209&amp;sdata=cw75EiZAUXPo9iwbbkXrZwoLpuv1F7rHZIiDDHSToDA%3D&amp;reserved=0
>
> VariablePolicy is an updated interface to
> replace VarLock and VarCheckProtocol.
>
> Add the VariablePolicyLib library that implements
> the portable business logic for the VariablePolicy
> engine.
>
> Also add host-based CI test cases for the lib.
>
> Cc: Jian J Wang <jian.j.wang@intel.com>
> Cc: Hao A Wu <hao.a.wu@intel.com>
> Cc: Liming Gao <liming.gao@intel.com>
> Cc: Bret Barkelew <brbarkel@microsoft.com>
> Signed-off-by: Bret Barkelew <brbarkel@microsoft.com>
> ---
>  MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitNull.c
> |   46 +
>
> MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitRuntimeDx
> e.c               |   85 +
>  MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c
> |  816 +++++++
>
> MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePo
> licyUnitTest.c   | 2436 ++++++++++++++++++++
>  MdeModulePkg/Include/Library/VariablePolicyLib.h                                         |
> 207 ++
>  MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf
> |   44 +
>  MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.uni
> |   12 +
>  MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf
> |   51 +
>
> MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePo
> licyUnitTest.inf |   40 +
>  MdeModulePkg/MdeModulePkg.dec                                                            |    3 +
>  MdeModulePkg/MdeModulePkg.dsc                                                            |    5 +
>  MdeModulePkg/Test/MdeModulePkgHostTest.dsc                                               |
> 11 +
>  12 files changed, 3756 insertions(+)
>
> diff --git
> a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitNull.c
> b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitNull.c
> new file mode 100644
> index 000000000000..ad2ee0b2fb8f
> --- /dev/null
> +++
> b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitNull.c
> @@ -0,0 +1,46 @@
> +/** @file -- VariablePolicyExtraInitNull.c
>
> +This file contains extra init and deinit routines that don't do anything
>
> +extra.
>
> +
>
> +Copyright (c) Microsoft Corporation.
>
> +SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +
>
> +**/
>
> +
>
> +#include <Library/UefiRuntimeServicesTableLib.h>
>
> +
>
> +
>
> +/**
>
> +  An extra init hook that enables the RuntimeDxe library instance to
>
> +  register VirtualAddress change callbacks. Among other things.
>
> +
>
> +  @retval     EFI_SUCCESS   Everything is good. Continue with init.
>
> +  @retval     Others        Uh... don't continue.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +VariablePolicyExtraInit (
>
> +  VOID
>
> +  )
>
> +{
>
> +  // NULL implementation.
>
> +  return EFI_SUCCESS;
>
> +}
>
> +
>
> +
>
> +/**
>
> +  An extra deinit hook that enables the RuntimeDxe library instance to
>
> +  register VirtualAddress change callbacks. Among other things.
>
> +
>
> +  @retval     EFI_SUCCESS   Everything is good. Continue with deinit.
>
> +  @retval     Others        Uh... don't continue.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +VariablePolicyExtraDeinit (
>
> +  VOID
>
> +  )
>
> +{
>
> +  // NULL implementation.
>
> +  return EFI_SUCCESS;
>
> +}
>
> diff --git
> a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitRuntimeD
> xe.c
> b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitRuntime
> Dxe.c
> new file mode 100644
> index 000000000000..3ca87048b14b
> --- /dev/null
> +++
> b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitRuntime
> Dxe.c
> @@ -0,0 +1,85 @@
> +/** @file -- VariablePolicyExtraInitRuntimeDxe.c
>
> +This file contains extra init and deinit routines that register and unregister
>
> +VariableAddressChange callbacks.
>
> +
>
> +Copyright (c) Microsoft Corporation.
>
> +SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +
>
> +**/
>
> +
>
> +#include <Library/UefiBootServicesTableLib.h>
>
> +#include <Library/UefiRuntimeServicesTableLib.h>
>
> +
>
> +extern EFI_GET_VARIABLE   mGetVariableHelper;
>
> +extern UINT8              *mPolicyTable;
>
> +STATIC BOOLEAN            mIsVirtualAddrConverted;
>
> +STATIC EFI_EVENT          mVariablePolicyLibVirtualAddressChangeEvent  =
> NULL;
>
> +
>
> +/**
>
> +  For the RuntimeDxe version of this lib, convert internal pointer addresses
> to virtual addresses.
>
> +
>
> +  @param[in] Event      Event whose notification function is being invoked.
>
> +  @param[in] Context    The pointer to the notification function's context,
> which
>
> +                        is implementation-dependent.
>
> +**/
>
> +STATIC
>
> +VOID
>
> +EFIAPI
>
> +VariablePolicyLibVirtualAddressCallback (
>
> +  IN  EFI_EVENT   Event,
>
> +  IN  VOID        *Context
>
> +  )
>
> +{
>
> +  gRT->ConvertPointer (0, (VOID **)&mPolicyTable);
>
> +  gRT->ConvertPointer (0, (VOID **)&mGetVariableHelper);
>
> +  mIsVirtualAddrConverted = TRUE;
>
> +}
>
> +
>
> +
>
> +/**
>
> +  An extra init hook that enables the RuntimeDxe library instance to
>
> +  register VirtualAddress change callbacks. Among other things.
>
> +
>
> +  @retval     EFI_SUCCESS   Everything is good. Continue with init.
>
> +  @retval     Others        Uh... don't continue.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +VariablePolicyExtraInit (
>
> +  VOID
>
> +  )
>
> +{
>
> +  return gBS->CreateEventEx (EVT_NOTIFY_SIGNAL,
>
> +                              TPL_NOTIFY,
>
> +                              VariablePolicyLibVirtualAddressCallback,
>
> +                              NULL,
>
> +                              &gEfiEventVirtualAddressChangeGuid,
>
> +                              &mVariablePolicyLibVirtualAddressChangeEvent);
>
> +}
>
> +
>
> +
>
> +/**
>
> +  An extra deinit hook that enables the RuntimeDxe library instance to
>
> +  register VirtualAddress change callbacks. Among other things.
>
> +
>
> +  @retval     EFI_SUCCESS   Everything is good. Continue with deinit.
>
> +  @retval     Others        Uh... don't continue.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +VariablePolicyExtraDeinit (
>
> +  VOID
>
> +  )
>
> +{
>
> +  EFI_STATUS  Status;
>
> +
>
> +  Status = EFI_SUCCESS;
>
> +  if (mIsVirtualAddrConverted) {
>
> +    Status = gBS->CloseEvent
> (mVariablePolicyLibVirtualAddressChangeEvent);
>
> +  }
>
> +  else {
>
> +    Status = EFI_SUCCESS;
>
> +  }
>
> +
>
> +  return Status;
>
> +}
>
> diff --git a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c
> b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c
> new file mode 100644
> index 000000000000..84c794adaed9
> --- /dev/null
> +++ b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c
> @@ -0,0 +1,816 @@
> +/** @file -- VariablePolicyLib.c
>
> +Business logic for Variable Policy enforcement.
>
> +
>
> +Copyright (c) Microsoft Corporation.
>
> +SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +
>
> +**/
>
> +
>
> +#include <Uefi.h>
>
> +
>
> +#include <Library/SafeIntLib.h>
>
> +#include <Library/MemoryAllocationLib.h>
>
> +#include <Library/BaseMemoryLib.h>
>
> +#include <Library/DebugLib.h>
>
> +#include <Library/PcdLib.h>
>
> +
>
> +#include <Protocol/VariablePolicy.h>
>
> +#include <Library/VariablePolicyLib.h>
>
> +
>
> +
>
> +// IMPORTANT NOTE: This library is currently rife with multiple return
> statements
>
> +//                 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.
>
> +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.
>
> +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
>
> +
>
> +// ExtraInit/ExtraDeinit functions allow RuntimeDxe to register
> VirtualAddress callbacks.
>
> +EFI_STATUS
>
> +VariablePolicyExtraInit (
>
> +  VOID
>
> +  );
>
> +
>
> +EFI_STATUS
>
> +VariablePolicyExtraDeinit (
>
> +  VOID
>
> +  );

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

>
> +
>
> +
>
> +/**
>
> +  This helper function determines whether the structure of an incoming
> policy
>
> +  is valid and internally consistent.
>
> +
>
> +  @param[in]  NewPolicy     Pointer to the incoming policy structure.
>
> +
>
> +  @retval     TRUE
>
> +  @retval     FALSE   Pointer is NULL, size is wrong, strings are empty, or
>
> +                      substructures overlap.
>
> +
>
> +**/
>
> +STATIC
>
> +BOOLEAN
>
> +IsValidVariablePolicyStructure (
>
> +  IN CONST VARIABLE_POLICY_ENTRY    *NewPolicy
>
> +  )
>
> +{
>
> +  EFI_STATUS    Status;
>
> +  UINTN         EntryEnd;
>
> +  CHAR16        *CheckChar;
>
> +  UINTN         WildcardCount;
>
> +
>
> +  // Sanitize some quick values.
>
> +  if (NewPolicy == 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;
>
> +  CHAR16      *PolicyName;
>
> +  UINT8       CalculatedPriority;
>
> +  UINTN       Index;
>
> +
>
> +  Result = FALSE;
>
> +  CalculatedPriority = MATCH_PRIORITY_EXACT;
>
> +
>
> +  // Step 1: If the GUID doesn't match, we're done. No need to evaluate
> anything else.
>
> +  if (!CompareGuid( &EvalEntry->Namespace, VendorGuid )) {
>
> +    goto Exit;
>
> +  }
>
> +
>
> +  // If the GUID matches, check to see whether there is a Name 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 {
2. [Dandan]: About the coding style, could we make the" } " and "else {" at the same line? Which is aligned with current edk2 style.
>
> +        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;
>
> +  VARIABLE_POLICY_ENTRY   *CurrentEntry;
>
> +  UINT8                   MatchPriority;
>
> +  UINT8                   CurrentPriority;
>
> +  UINTN                   Index;
>
> +
>
> +  BestResult = NULL;
>
> +
>
> +  // 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 )) {
>
> +      // If match is better, take it.
>
> +      if (BestResult == NULL || CurrentPriority < MatchPriority) {

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

>
> +        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;
>
> +  VARIABLE_LOCK_ON_VAR_STATE_POLICY   *StateVarPolicy;
>
> +  CHAR16                              *StateVarName;
>
> +  UINTN                               StateVarSize;
>
> +  UINT8                               StateVar;
>
> +
>
> +  ReturnStatus = EFI_SUCCESS;
>
> +
>
> +  if (!IsVariablePolicyLibInitialized()) {
>
> +    ReturnStatus = EFI_NOT_READY;
>
> +    goto Exit;
>
> +  }
>
> +
>
> +  // Bail if the protections are currently disabled.
>
> +  if (mProtectionDisabled) {
>
> +    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_WRITE_PROTECTED   Interface option is disabled by platform
> PCD.
>
> +  @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;
>
> +  }
>
> +  if (!PcdGetBool (PcdAllowVariablePolicyEnforcementDisable)) {
>
> +    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
>
> +  )
>
> +{
>
> +  EFI_STATUS    Status;
>
> +
>
> +  Status = EFI_SUCCESS;
>
> +  if (mGetVariableHelper != NULL) {
>
> +    Status = EFI_ALREADY_STARTED;

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

>
> +  }
>
> +
>
> +  if (!EFI_ERROR( Status )) {
>
> +    Status = VariablePolicyExtraInit();
>
> +  }
>
> +
>
> +  if (!EFI_ERROR( Status )) {
>
> +    // 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 Status;
>
> +}
>
> +
>
> +
>
> +/**
>
> +  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
>
> +  )
>
> +{
>
> +  EFI_STATUS    Status;
>
> +
>
> +  Status = EFI_SUCCESS;
>
> +
>
> +  if (mGetVariableHelper == NULL) {
>
> +    Status = EFI_NOT_READY;
>
> +  }
>
> +
>
> +  if (!EFI_ERROR( Status )) {
>
> +    Status = VariablePolicyExtraDeinit();
>
> +  }
>
> +
>
> +  if (!EFI_ERROR( Status )) {
>
> +    mGetVariableHelper = NULL;
>
> +    mInterfaceLocked = FALSE;
>
> +    mProtectionDisabled = FALSE;
>
> +    mCurrentTableSize = 0;
>
> +    mCurrentTableUsage = 0;
>
> +    mCurrentTableCount = 0;
>
> +
>
> +    if (mPolicyTable != NULL) {
>
> +      FreePool( mPolicyTable );
>
> +      mPolicyTable = NULL;
>
> +    }
>
> +  }
>
> +
>
> +  return Status;
>
> +}
>
> diff --git
> a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/Variable
> PolicyUnitTest.c
> b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/Variable
> PolicyUnitTest.c
> new file mode 100644
> index 000000000000..f133f2f30e36
> --- /dev/null
> +++
> b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/Variable
> PolicyUnitTest.c
> @@ -0,0 +1,2436 @@
> +/** @file -- VariablePolicyUnitTest.c
>
> +UnitTest for...
>
> +Business logic for Variable Policy enforcement.
>
> +
>
> +Copyright (c) Microsoft Corporation.
>
> +SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +
>
> +**/
>
> +
>
> +#include <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
> ==========================================================
> =================
>
> +
>
> +/**
>
> +  Helper function to initialize a VARIABLE_POLICY_ENTRY structure with a
> Name and StateName.
>
> +
>
> +  Takes care of all the messy packing.
>
> +
>
> +  @param[in,out]  Entry
>
> +  @param[in]      Name        [Optional]
>
> +  @param[in]      StateName   [Optional]
>
> +
>
> +  @retval     TRUE
>
> +  @retval     FALSE
>
> +
>
> +**/
>
> +STATIC
>
> +BOOLEAN
>
> +InitExpVarPolicyStrings (
>
> +  EXPANDED_VARIABLE_POLICY_ENTRY      *Entry,
>
> +  CHAR16                              *Name,      OPTIONAL
>
> +  CHAR16                              *StateName  OPTIONAL
>
> +  )
>
> +{
>
> +  UINTN     NameSize;
>
> +  UINTN     StateNameSize;
>
> +
>
> +  NameSize = 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;
>
> +}
>
> +
>
> +/**
>
> +  Mocked version of GetVariable, for testing.
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +StubGetVariableNull (
>
> +  IN     CHAR16                      *VariableName,
>
> +  IN     EFI_GUID                    *VendorGuid,
>
> +  OUT    UINT32                      *Attributes,    OPTIONAL
>
> +  IN OUT UINTN                       *DataSize,
>
> +  OUT    VOID                        *Data           OPTIONAL
>
> +  )
>
> +{
>
> +  UINT32      MockedAttr;
>
> +  UINTN       MockedDataSize;
>
> +  VOID        *MockedData;
>
> +  EFI_STATUS  MockedReturn;
>
> +
>
> +  check_expected_ptr( VariableName );
>
> +  check_expected_ptr( VendorGuid );
>
> +  check_expected_ptr( DataSize );
>
> +
>
> +  MockedAttr = (UINT32)mock();
>
> +  MockedDataSize = (UINTN)mock();
>
> +  MockedData = (VOID*)mock();
>
> +  MockedReturn = (EFI_STATUS)mock();
>
> +
>
> +  if (Attributes != NULL) {
>
> +    *Attributes = MockedAttr;
>
> +  }
>
> +  if (Data != NULL && !EFI_ERROR(MockedReturn)) {
>
> +    CopyMem( Data, MockedData, MockedDataSize );
>
> +  }
>
> +
>
> +  *DataSize = MockedDataSize;
>
> +
>
> +  return MockedReturn;
>
> +}
>
> +
>
> +//
>
> +// Anything you think might be helpful that isn't a test itself.
>
> +//
>
> +
>
> +/**
>
> +  This is a common setup function that will ensure the library is always
> initialized
>
> +  with the stubbed GetVariable.
>
> +
>
> +  Not used by all test cases, but by most.
>
> +**/
>
> +STATIC
>
> +UNIT_TEST_STATUS
>
> +LibInitMocked (
>
> +  IN UNIT_TEST_CONTEXT      Context
>
> +  )
>
> +{
>
> +  return EFI_ERROR(InitVariablePolicyLib( StubGetVariableNull )) ?
> UNIT_TEST_ERROR_PREREQUISITE_NOT_MET : UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> +  Common cleanup function to make sure that the library is always de-
> initialized prior
>
> +  to the next test case.
>
> +*/
>
> +STATIC
>
> +VOID
>
> +LibCleanup (
>
> +  IN UNIT_TEST_CONTEXT      Context
>
> +  )
>
> +{
>
> +  DeinitVariablePolicyLib();
>
> +}
>
> +
>
> +
>
> +///=== TEST CASES
> ==========================================================
> =======================
>
> +
>
> +///===== ARCHITECTURAL SUITE
> ==================================================
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +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;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +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;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +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;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +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
>
> +  );
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +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;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +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;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +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;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +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;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +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
> ==============================================
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +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;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +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;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +RegisterShouldRejectNullPointers (
>
> +  IN UNIT_TEST_CONTEXT      Context
>
> +  )
>
> +{
>
> +  UT_ASSERT_EQUAL( RegisterVariablePolicy( NULL ),
> EFI_INVALID_PARAMETER );
>
> +  return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +RegisterShouldRejectBadRevisions (
>
> +  IN UNIT_TEST_CONTEXT      Context
>
> +  )
>
> +{
>
> +  SIMPLE_VARIABLE_POLICY_ENTRY   ValidationPolicy = {
>
> +    {
>
> +      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;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +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;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +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;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +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;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +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;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +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;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +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;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +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;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +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;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +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;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +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;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +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;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +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;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +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;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +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;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +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;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +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;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +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;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +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;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +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;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +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;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +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
> ===================================================
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +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;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +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;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +ShouldNotBeAbleToDisablePoliciesTwice (
>
> +  IN UNIT_TEST_CONTEXT      Context
>
> +  )
>
> +{
>
> +  // Make sure that the policy enforcement is currently enabled.
>
> +  UT_ASSERT_TRUE( IsVariablePolicyEnabled() );
>
> +  // Disable the policy enforcement.
>
> +  UT_ASSERT_NOT_EFI_ERROR( DisableVariablePolicy() );
>
> +  // Make sure that the policy enforcement is currently disabled.
>
> +  UT_ASSERT_FALSE( IsVariablePolicyEnabled() );
>
> +  // Try to disable again and verify failure.
>
> +  UT_ASSERT_TRUE( EFI_ERROR( DisableVariablePolicy() ) );
>
> +
>
> +  return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +ShouldBeAbleToAddNewPoliciesAfterDisabled (
>
> +  IN UNIT_TEST_CONTEXT      Context
>
> +  )
>
> +{
>
> +  SIMPLE_VARIABLE_POLICY_ENTRY   TestPolicy = {
>
> +    {
>
> +      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;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +ShouldBeAbleToLockAfterDisabled (
>
> +  IN UNIT_TEST_CONTEXT      Context
>
> +  )
>
> +{
>
> +  // Make sure that the policy enforcement is currently enabled.
>
> +  UT_ASSERT_TRUE( IsVariablePolicyEnabled() );
>
> +  // Disable the policy enforcement.
>
> +  UT_ASSERT_NOT_EFI_ERROR( DisableVariablePolicy() );
>
> +
>
> +  // Make sure that we can lock in this state.
>
> +  UT_ASSERT_FALSE( IsVariablePolicyInterfaceLocked() );
>
> +  UT_ASSERT_NOT_EFI_ERROR( LockVariablePolicy() );
>
> +  UT_ASSERT_TRUE( IsVariablePolicyInterfaceLocked() );
>
> +
>
> +  return UNIT_TEST_PASSED;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +UNIT_TEST_STATUS
>
> +EFIAPI
>
> +ShouldBeAbleToDumpThePolicyTable (
>
> +  IN UNIT_TEST_CONTEXT      Context
>
> +  )
>
> +{
>
> +  SIMPLE_VARIABLE_POLICY_ENTRY   TestPolicy = {
>
> +    {
>
> +      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;
>
> +}
>
> +
>
> +/**
>
> +  Test Case
>
> +*/
>
> +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 != NULL)
>
> +  {
>
> +    FreeUnitTestFramework( Framework );
>
> +  }
>
> +
>
> +  return Status;
>
> +}
>
> diff --git a/MdeModulePkg/Include/Library/VariablePolicyLib.h
> b/MdeModulePkg/Include/Library/VariablePolicyLib.h
> new file mode 100644
> index 000000000000..efd1840112ec
> --- /dev/null
> +++ b/MdeModulePkg/Include/Library/VariablePolicyLib.h
> @@ -0,0 +1,207 @@
> +/** @file -- VariablePolicyLib.h
>
> +Business logic for Variable Policy enforcement.
>
> +
>
> +Copyright (c) Microsoft Corporation.
>
> +SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +
>
> +**/
>
> +
>
> +#ifndef _VARIABLE_POLICY_LIB_H_
>
> +#define _VARIABLE_POLICY_LIB_H_
>
> +
>
> +#include <Protocol/VariablePolicy.h>
>
> +
>
> +/**
>
> +  This API function validates and registers a new policy 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_WRITE_PROTECTED   Interface option is disabled by platform
> PCD.
>
> +  @retval     EFI_NOT_READY   Library has not yet been initialized.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +DisableVariablePolicy (
>
> +  VOID
>
> +  );
>
> +
>
> +
>
> +/**
>
> +  This API function will dump the entire contents of the 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..f4a879d5382f
> --- /dev/null
> +++ b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf
> @@ -0,0 +1,44 @@
> +## @file VariablePolicyLib.inf
>
> +# Business logic for Variable Policy enforcement.
>
> +#
>
> +##
>
> +# Copyright (c) Microsoft Corporation.
>
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +##
>
> +
>
> +
>
> +[Defines]
>
> +  INF_VERSION         = 0x00010017
>
> +  BASE_NAME           = VariablePolicyLib
>
> +  FILE_GUID           = E9ECD342-159A-4F24-9FDF-65724027C594
>
> +  VERSION_STRING      = 1.0
>
> +  MODULE_TYPE         = DXE_DRIVER
>
> +  LIBRARY_CLASS       = VariablePolicyLib|DXE_DRIVER DXE_SMM_DRIVER
> MM_STANDALONE
>
> +
>
> +#
>
> +# The following information is for reference only and not required by the
> build tools.
>
> +#
>
> +#  VALID_ARCHITECTURES           = ANY
>
> +#
>
> +
>
> +
>
> +[Sources]
>
> +  VariablePolicyLib.c
>
> +  VariablePolicyExtraInitNull.c
>
> +
>
> +
>
> +[Packages]
>
> +  MdePkg/MdePkg.dec
>
> +  MdeModulePkg/MdeModulePkg.dec
>
> +
>
> +
>
> +[LibraryClasses]
>
> +  DebugLib
>
> +  BaseMemoryLib
>
> +  MemoryAllocationLib
>
> +  SafeIntLib
>
> +  PcdLib
>
> +
>
> +
>
> +[Pcd]
>
> +
> gEfiMdeModulePkgTokenSpaceGuid.PcdAllowVariablePolicyEnforcementDis
> able     ## CONSUMES
>
> diff --git a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.uni
> b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.uni
> new file mode 100644
> index 000000000000..2227ec427828
> --- /dev/null
> +++ b/MdeModulePkg/Library/VariablePolicyLib/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/VariablePolicyLibRuntimeDxe.in
> f
> b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.in
> f
> new file mode 100644
> index 000000000000..8b8365741864
> --- /dev/null
> +++
> b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.in
> f
> @@ -0,0 +1,51 @@
> +## @file VariablePolicyLibRuntimeDxe.inf
>
> +# Business logic for Variable Policy enforcement.
>
> +# This instance is specifically for RuntimeDxe and contains
>
> +# extra routines to register for VirtualAddressChangeEvents.
>
> +#
>
> +# Copyright (c) Microsoft Corporation.
>
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +##
>
> +
>
> +
>
> +[Defines]
>
> +  INF_VERSION         = 0x00010017
>
> +  BASE_NAME           = VariablePolicyLibRuntimeDxe
>
> +  FILE_GUID           = 205F7F0E-8EAC-4914-8390-1B90DD7E2A27
>
> +  VERSION_STRING      = 1.0
>
> +  MODULE_TYPE         = DXE_RUNTIME_DRIVER
>
> +  LIBRARY_CLASS       = VariablePolicyLib|DXE_RUNTIME_DRIVER
>
> +
>
> +#
>
> +# The following information is for reference only and not required by the
> build tools.
>
> +#
>
> +#  VALID_ARCHITECTURES           = ANY
>
> +#
>
> +
>
> +
>
> +[Sources]
>
> +  VariablePolicyLib.c
>
> +  VariablePolicyExtraInitRuntimeDxe.c
>
> +
>
> +
>
> +[Packages]
>
> +  MdePkg/MdePkg.dec
>
> +  MdeModulePkg/MdeModulePkg.dec
>
> +
>
> +
>
> +[LibraryClasses]
>
> +  DebugLib
>
> +  BaseMemoryLib
>
> +  MemoryAllocationLib
>
> +  SafeIntLib
>
> +  UefiBootServicesTableLib
>
> +  UefiRuntimeServicesTableLib
>
> +  PcdLib
>
> +
>
> +
>
> +[Pcd]
>
> +
> gEfiMdeModulePkgTokenSpaceGuid.PcdAllowVariablePolicyEnforcementDis
> able     ## CONSUMES
>
> +
>
> +
>
> +[Guids]
>
> +  gEfiEventVirtualAddressChangeGuid
>
> diff --git
> a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/Variable
> PolicyUnitTest.inf
> b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/Variable
> PolicyUnitTest.inf
> new file mode 100644
> index 000000000000..ccc04bb600d6
> --- /dev/null
> +++
> b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/Variable
> PolicyUnitTest.inf
> @@ -0,0 +1,40 @@
> +## @file VariablePolicyUnitTest.inf
>
> +# UnitTest for...
>
> +# Business logic for Variable Policy enforcement.
>
> +#
>
> +# Copyright (c) Microsoft Corporation.
>
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +##
>
> +
>
> +
>
> +[Defines]
>
> +  INF_VERSION                    = 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 05d8ad4931f9..0b58c14e4747 100644
> --- a/MdeModulePkg/MdeModulePkg.dec
> +++ b/MdeModulePkg/MdeModulePkg.dec
> @@ -31,6 +31,9 @@ [LibraryClasses]
>    ##  @libraryclass  Defines a set of methods to reset whole system.
>
>    ResetSystemLib|Include/Library/ResetSystemLib.h
>
>
>
> +  ##  @libraryclass  Business logic for storing and testing variable 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 25aea3e2a481..14b6ed536962 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 @@ [LibraryClasses]
>    DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf
>
>
> DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTabl
> eLib.inf
>
>
> UefiBootManagerLib|MdeModulePkg/Library/UefiBootManagerLib/UefiBoo
> tManagerLib.inf
>
> +
> VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLi
> b.inf
>
>    #
>
>    # Generic Modules
>
>    #
>
> @@ -129,6 +131,7 @@ [LibraryClasses.common.DXE_RUNTIME_DRIVER]
>    DebugLib|MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf
>
>
> LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxDxeLib.in
> f
>
>
> CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsule
> Lib.inf
>
> +
> VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLi
> bRuntimeDxe.inf
>
>
>
>  [LibraryClasses.common.SMM_CORE]
>
>    HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
>
> @@ -306,6 +309,8 @@ [Components]
>    MdeModulePkg/Library/BootLogoLib/BootLogoLib.inf
>
>
> MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull
> .inf
>
>    MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf
>
> +  MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf
>
> +
> MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf
>
>    MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf
>
>    MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLib.inf
>
>    MdeModulePkg/Library/VarCheckPcdLib/VarCheckPcdLib.inf
>
> diff --git a/MdeModulePkg/Test/MdeModulePkgHostTest.dsc
> b/MdeModulePkg/Test/MdeModulePkgHostTest.dsc
> index 72a119db4568..095e613f1be1 100644
> --- a/MdeModulePkg/Test/MdeModulePkgHostTest.dsc
> +++ b/MdeModulePkg/Test/MdeModulePkgHostTest.dsc
> @@ -19,12 +19,23 @@ [Defines]
>
>
>  !include UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc
>
>
>
> +[LibraryClasses]
>
> +  SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf
>
> +
>
>  [Components]
>
>
> MdeModulePkg/Library/DxeResetSystemLib/UnitTest/MockUefiRuntimeSer
> vicesTableLib.inf
>
>
>
>    #
>
>    # Build MdeModulePkg HOST_APPLICATION Tests
>
>    #
>
> +
> MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePo
> licyUnitTest.inf {
>
> +    <LibraryClasses>
>
> +
> VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLi
> b.inf
>
> +
>
> +    <PcdsFixedAtBuild>
>
> +
> gEfiMdeModulePkgTokenSpaceGuid.PcdAllowVariablePolicyEnforcementDis
> able|TRUE
>
> +  }
>
> +
>
>
> MdeModulePkg/Library/DxeResetSystemLib/UnitTest/DxeResetSystemLibU
> nitTestHost.inf {
>
>      <LibraryClasses>
>
>
> ResetSystemLib|MdeModulePkg/Library/DxeResetSystemLib/DxeResetSyst
> emLib.inf
>
> --
> 2.26.2.windows.1.8.g01c50adf56.20200515075929
>
>
> -=-=-=-=-=-=
> Groups.io Links: You receive all messages sent to this group.
>
> View/Reply Online (#61588): https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fedk2.groups.io%2Fg%2Fdevel%2Fmessage%2F61588&amp;data=02%7C01%7Cbret.barkelew%40microsoft.com%7C4ff781c598384282187708d81e2d8858%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637292528218892203&amp;sdata=LU1JPSqqPVToubD2UJd8JT34dvLGJ6QSi7oA7s%2FyiqY%3D&amp;reserved=0
> Mute This Topic: https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgroups.io%2Fmt%2F75057697%2F1768738&amp;data=02%7C01%7Cbret.barkelew%40microsoft.com%7C4ff781c598384282187708d81e2d8858%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637292528218892203&amp;sdata=Y%2BAVPkeX7Clj7g0E0ENKDcJQwVksMtp%2FbZjBgDdz%2B1A%3D&amp;reserved=0
> Group Owner: devel+owner@edk2.groups.io
> Unsubscribe: https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fedk2.groups.io%2Fg%2Fdevel%2Funsub&amp;data=02%7C01%7Cbret.barkelew%40microsoft.com%7C4ff781c598384282187708d81e2d8858%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637292528218892203&amp;sdata=Qzd%2FXa8ldydS45UAIyd7PaGORBzcESMWbNT1oUNEZm4%3D&amp;reserved=0  [dandan.bi@intel.com]
> -=-=-=-=-=-=





[-- Attachment #2: Type: text/html, Size: 344612 bytes --]

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature
  2020-07-02  6:47     ` Bret Barkelew
@ 2020-07-02 11:06       ` Laszlo Ersek
  2020-07-02 18:26         ` [EXTERNAL] " Bret Barkelew
  0 siblings, 1 reply; 48+ messages in thread
From: Laszlo Ersek @ 2020-07-02 11:06 UTC (permalink / raw)
  To: Bret Barkelew, devel@edk2.groups.io, dandan.bi@intel.com,
	bret@corthon.com
  Cc: Yao, Jiewen, Zhang, Chao B, Wang, Jian J, Wu, Hao A, liming.gao,
	Justen, Jordan L, Ard Biesheuvel, Andrew Fish, Ni, Ray

On 07/02/20 08:47, Bret Barkelew wrote:
> Actually, if you want to leave feedback in the CI test PR that I made for this version, I’m happy to discuss there as well.
> https://github.com/tianocore/edk2/pull/718/files

Please let's not do that just yet. Once we have a flag day, we should
have review discussions exclusively in github. Before that day, the
mailing list should carry the review comments however.

Thanks
Laszlo


^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [EXTERNAL] Re: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature
  2020-07-02 11:06       ` Laszlo Ersek
@ 2020-07-02 18:26         ` Bret Barkelew
  0 siblings, 0 replies; 48+ messages in thread
From: Bret Barkelew @ 2020-07-02 18:26 UTC (permalink / raw)
  To: Laszlo Ersek, devel@edk2.groups.io, dandan.bi@intel.com,
	bret@corthon.com
  Cc: Yao, Jiewen, Zhang, Chao B, Wang, Jian J, Wu, Hao A, liming.gao,
	Justen, Jordan L, Ard Biesheuvel, Andrew Fish, Ni, Ray

[-- Attachment #1: Type: text/plain, Size: 1683 bytes --]

That’s also fine.
Note that this is not the only place where I receive feedback, however. Some people bring up things over happy hour, too. 😉

Laszlo… whiskey Wednesday?

- Bret

From: Laszlo Ersek<mailto:lersek@redhat.com>
Sent: Thursday, July 2, 2020 4:06 AM
To: Bret Barkelew<mailto:Bret.Barkelew@microsoft.com>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; dandan.bi@intel.com<mailto:dandan.bi@intel.com>; bret@corthon.com<mailto:bret@corthon.com>
Cc: Yao, Jiewen<mailto:jiewen.yao@intel.com>; Zhang, Chao B<mailto:chao.b.zhang@intel.com>; Wang, Jian J<mailto:jian.j.wang@intel.com>; Wu, Hao A<mailto:hao.a.wu@intel.com>; liming.gao<mailto:liming.gao@intel.com>; Justen, Jordan L<mailto:jordan.l.justen@intel.com>; Ard Biesheuvel<mailto:ard.biesheuvel@arm.com>; Andrew Fish<mailto:afish@apple.com>; Ni, Ray<mailto:ray.ni@intel.com>
Subject: [EXTERNAL] Re: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature

On 07/02/20 08:47, Bret Barkelew wrote:
> Actually, if you want to leave feedback in the CI test PR that I made for this version, I’m happy to discuss there as well.
> https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Ftianocore%2Fedk2%2Fpull%2F718%2Ffiles&amp;data=02%7C01%7Cbret.barkelew%40microsoft.com%7Cf6e2bb7fb829461fd5dc08d81e77fbd5%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637292847963929407&amp;sdata=0%2BFsslPtFLb0QlI8eL2i7m8FP3vV5wdDjGq6JWLnbL4%3D&amp;reserved=0

Please let's not do that just yet. Once we have a flag day, we should
have review discussions exclusively in github. Before that day, the
mailing list should carry the review comments however.

Thanks
Laszlo


[-- Attachment #2: Type: text/html, Size: 4210 bytes --]

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [EXTERNAL] [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature
  2020-06-23  6:40 [PATCH v6 00/14] Add the VariablePolicy feature bret
                   ` (14 preceding siblings ...)
  2020-07-02  2:13 ` [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature Dandan Bi
@ 2020-07-29 19:56 ` Bret Barkelew
  2020-07-30  1:36   ` Liming Gao
       [not found] ` <161DCDB779DB4B3C.30988@groups.io>
  16 siblings, 1 reply; 48+ messages in thread
From: Bret Barkelew @ 2020-07-29 19:56 UTC (permalink / raw)
  To: devel@edk2.groups.io, bret@corthon.com
  Cc: Yao, Jiewen, Chao Zhang, Jian J Wang, Hao A Wu, liming.gao,
	Jordan Justen, Laszlo Ersek, Ard Biesheuvel, Andrew Fish, Ni, Ray

[-- Attachment #1: Type: text/plain, Size: 12892 bytes --]

Still waiting on some R-bs.

Have a new doc that will make it into a v7, if it helps anyone with their review…
https://github.com/microsoft/mu_basecore/blob/release/202005/MdeModulePkg/Universal/Variable/UefiVariablePolicy/ReadMe.md

Thanks!

- Bret

From: Bret Barkelew via groups.io<mailto:bret=corthon.com@groups.io>
Sent: Tuesday, June 23, 2020 4:19 AM
To: devel@edk2.groups.io<mailto:devel@edk2.groups.io>
Cc: Yao, Jiewen<mailto:jiewen.yao@intel.com>; Chao Zhang<mailto:chao.b.zhang@intel.com>; Jian J Wang<mailto:jian.j.wang@intel.com>; Hao A Wu<mailto:hao.a.wu@intel.com>; liming.gao<mailto:liming.gao@intel.com>; Jordan Justen<mailto:jordan.l.justen@intel.com>; Laszlo Ersek<mailto:lersek@redhat.com>; Ard Biesheuvel<mailto:ard.biesheuvel@arm.com>; Andrew Fish<mailto:afish@apple.com>; Ni, Ray<mailto:ray.ni@intel.com>
Subject: [EXTERNAL] [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature

REF:https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fbugzilla.tianocore.org%2Fshow_bug.cgi%3Fid%3D2522&amp;data=02%7C01%7Cbret.barkelew%40microsoft.com%7Cdf2ee1dbc25a4810f5ce08d817674112%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637285079522114249&amp;sdata=1%2F3MkPm5HuXeG%2FEaQgl%2F%2F8Tqu3UvgDs6Ich2ezXgjuY%3D&amp;reserved=0

The 14 patches in this series add the VariablePolicy feature to the core,
deprecate Edk2VarLock (while adding a compatibility layer to reduce code
churn), and integrate the VariablePolicy libraries and protocols into
Variable Services.

Since the integration requires multiple changes, including adding libraries,
a protocol, an SMI communication handler, and VariableServices integration,
the patches are broken up by individual library additions and then a final
integration. Security-sensitive changes like bypassing Authenticated
Variable enforcement are also broken out into individual patches so that
attention can be called directly to them.

Platform porting instructions are described in this wiki entry:
https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Ftianocore%2Ftianocore.github.io%2Fwiki%2FVariablePolicy-Protocol---Enhanced-Method-for-Managing-Variables%23platform-porting&amp;data=02%7C01%7Cbret.barkelew%40microsoft.com%7Cdf2ee1dbc25a4810f5ce08d817674112%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637285079522114249&amp;sdata=b%2FFdg6Sy2pdxbk3C%2FgVzXvoOWOxW6Z60QXRQ%2BVxGfFs%3D&amp;reserved=0

Discussion of the feature can be found in multiple places throughout
the last year on the RFC channel, staging branches, and in devel.

Most recently, this subject was discussed in this thread:
https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fedk2.groups.io%2Fg%2Fdevel%2Fmessage%2F53712&amp;data=02%7C01%7Cbret.barkelew%40microsoft.com%7Cdf2ee1dbc25a4810f5ce08d817674112%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637285079522114249&amp;sdata=epDJobMGos0As5T2JSwhs2PTy1IDt52oLqXkxEPJWLg%3D&amp;reserved=0
(the code branches shared in that discussion are now out of date, but the
whitepapers and discussion are relevant).

Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Hao A Wu <hao.a.wu@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
Cc: Andrew Fish <afish@apple.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Bret Barkelew <brbarkel@microsoft.com>
Signed-off-by: Bret Barkelew <brbarkel@microsoft.com>

v6 changes:
* Fix an issue with uninitialized Status in InitVariablePolicyLib() and DeinitVariablePolicyLib()
* Fix GCC building in shell-based functional test
* Rebase on latest origin/master

v5 changes:
* Fix the CONST mismatch in VariablePolicy.h and VariablePolicySmmDxe.c
* Fix EFIAPI mismatches in the functional unittest
* Rebase on latest origin/master

v4 changes:
* Remove Optional PcdAllowVariablePolicyEnforcementDisable PCD from platforms
* Rebase on master
* Migrate to new MmCommunicate2 protocol
* Fix an oversight in the default return value for InitMmCommonCommBuffer
* Fix in VariablePolicyLib to allow ExtraInitRuntimeDxe to consume variables

V3 changes:
* Address all non-unittest issues with ECC
* Make additional style changes
* Include section name in hunk headers in "ini-style" files
* Remove requirement for the EdkiiPiSmmCommunicationsRegionTable driver
  (now allocates its own buffer)
* Change names from VARIABLE_POLICY_PROTOCOL and gVariablePolicyProtocolGuid
  to EDKII_VARIABLE_POLICY_PROTOCOL and gEdkiiVariablePolicyProtocolGuid
* Fix GCC warning about initializing externs
* Add UNI strings for new PCD
* Add patches for ArmVirtPkg, OvmfXen, and UefiPayloadPkg
* Reorder patches according to Liming's feedback about adding to platforms
  before changing variable driver

V2 changes:
* Fixed implementation for RuntimeDxe
* Add PCD to block DisableVariablePolicy
* Fix the DumpVariablePolicy pagination in SMM

Bret Barkelew (14):
  MdeModulePkg: Define the VariablePolicy protocol interface
  MdeModulePkg: Define the VariablePolicyLib
  MdeModulePkg: Define the VariablePolicyHelperLib
  MdeModulePkg: Define the VarCheckPolicyLib and SMM interface
  OvmfPkg: Add VariablePolicy engine to OvmfPkg platform
  EmulatorPkg: Add VariablePolicy engine to EmulatorPkg platform
  ArmVirtPkg: Add VariablePolicy engine to ArmVirtPkg platform
  UefiPayloadPkg: Add VariablePolicy engine to UefiPayloadPkg platform
  MdeModulePkg: Connect VariablePolicy business logic to
    VariableServices
  MdeModulePkg: Allow VariablePolicy state to delete protected variables
  SecurityPkg: Allow VariablePolicy state to delete authenticated
    variables
  MdeModulePkg: Change TCG MOR variables to use VariablePolicy
  MdeModulePkg: Drop VarLock from RuntimeDxe variable driver
  MdeModulePkg: Add a shell-based functional test for VariablePolicy

 MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.c                               |  320 +++
 MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.c                   |  396 ++++
 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitNull.c                     |   46 +
 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitRuntimeDxe.c               |   85 +
 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c                               |  816 +++++++
 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePolicyUnitTest.c   | 2440 ++++++++++++++++++++
 MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/VariablePolicyFuncTestApp.c        | 1978 ++++++++++++++++
 MdeModulePkg/Universal/Variable/RuntimeDxe/TcgMorLockDxe.c                               |   52 +-
 MdeModulePkg/Universal/Variable/RuntimeDxe/TcgMorLockSmm.c                               |   60 +-
 MdeModulePkg/Universal/Variable/RuntimeDxe/VarCheck.c                                    |   49 +-
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c                                 |   53 +
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableLockRequstToLock.c                    |   71 +
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariablePolicySmmDxe.c                        |  642 +++++
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c                       |   14 +
 SecurityPkg/Library/AuthVariableLib/AuthService.c                                        |   22 +-
 ArmVirtPkg/ArmVirt.dsc.inc                                                               |    4 +
 EmulatorPkg/EmulatorPkg.dsc                                                              |    3 +
 MdeModulePkg/Include/Guid/VarCheckPolicyMmi.h                                            |   54 +
 MdeModulePkg/Include/Library/VariablePolicyHelperLib.h                                   |  164 ++
 MdeModulePkg/Include/Library/VariablePolicyLib.h                                         |  207 ++
 MdeModulePkg/Include/Protocol/VariablePolicy.h                                           |  157 ++
 MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.inf                             |   42 +
 MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.uni                             |   12 +
 MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf                 |   35 +
 MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.uni                 |   12 +
 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf                             |   44 +
 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.uni                             |   12 +
 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf                   |   51 +
 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePolicyUnitTest.inf |   40 +
 MdeModulePkg/MdeModulePkg.ci.yaml                                                        |    4 +-
 MdeModulePkg/MdeModulePkg.dec                                                            |   26 +-
 MdeModulePkg/MdeModulePkg.dsc                                                            |   15 +
 MdeModulePkg/MdeModulePkg.uni                                                            |    7 +
 MdeModulePkg/Test/MdeModulePkgHostTest.dsc                                               |   11 +
 MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/Readme.md                          |   55 +
 MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/VariablePolicyFuncTestApp.inf      |   42 +
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf                        |    5 +
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf                               |    4 +
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf                     |   10 +
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf                      |    4 +
 OvmfPkg/OvmfPkgIa32.dsc                                                                  |    5 +
 OvmfPkg/OvmfPkgIa32X64.dsc                                                               |    5 +
 OvmfPkg/OvmfPkgX64.dsc                                                                   |    5 +
 OvmfPkg/OvmfXen.dsc                                                                      |    4 +
 SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf                                  |    2 +
 UefiPayloadPkg/UefiPayloadPkgIa32.dsc                                                    |    4 +
 UefiPayloadPkg/UefiPayloadPkgIa32X64.dsc                                                 |    4 +
 47 files changed, 8015 insertions(+), 78 deletions(-)
 create mode 100644 MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.c
 create mode 100644 MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.c
 create mode 100644 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitNull.c
 create mode 100644 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitRuntimeDxe.c
 create mode 100644 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c
 create mode 100644 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePolicyUnitTest.c
 create mode 100644 MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/VariablePolicyFuncTestApp.c
 create mode 100644 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableLockRequstToLock.c
 create mode 100644 MdeModulePkg/Universal/Variable/RuntimeDxe/VariablePolicySmmDxe.c
 create mode 100644 MdeModulePkg/Include/Guid/VarCheckPolicyMmi.h
 create mode 100644 MdeModulePkg/Include/Library/VariablePolicyHelperLib.h
 create mode 100644 MdeModulePkg/Include/Library/VariablePolicyLib.h
 create mode 100644 MdeModulePkg/Include/Protocol/VariablePolicy.h
 create mode 100644 MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.inf
 create mode 100644 MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.uni
 create mode 100644 MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf
 create mode 100644 MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.uni
 create mode 100644 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf
 create mode 100644 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.uni
 create mode 100644 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf
 create mode 100644 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePolicyUnitTest.inf
 create mode 100644 MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/Readme.md
 create mode 100644 MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/VariablePolicyFuncTestApp.inf

--
2.26.2.windows.1.8.g01c50adf56.20200515075929





[-- Attachment #2: Type: text/html, Size: 25592 bytes --]

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [EXTERNAL] [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature
  2020-07-29 19:56 ` [EXTERNAL] " Bret Barkelew
@ 2020-07-30  1:36   ` Liming Gao
  2020-07-30  1:43     ` Bret Barkelew
  0 siblings, 1 reply; 48+ messages in thread
From: Liming Gao @ 2020-07-30  1:36 UTC (permalink / raw)
  To: devel@edk2.groups.io, bret.barkelew@microsoft.com,
	bret@corthon.com, Leif Lindholm
  Cc: Yao, Jiewen, Wang, Jian J, Wu, Hao A, Justen, Jordan L,
	Laszlo Ersek, Ard Biesheuvel, Andrew Fish, Ni, Ray

[-- Attachment #1: Type: text/plain, Size: 14059 bytes --]

Include Leif. This change adds new library class dependency for the variable driver. So, it requires to update the platform DSC file. It will impact ARM platforms.

Thanks
Liming
From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Bret Barkelew via groups.io
Sent: 2020年7月30日 3:56
To: devel@edk2.groups.io; bret@corthon.com
Cc: Yao, Jiewen <jiewen.yao@intel.com>; Chao Zhang <chao.b.zhang@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>; Gao, Liming <liming.gao@intel.com>; Justen, Jordan L <jordan.l.justen@intel.com>; Laszlo Ersek <lersek@redhat.com>; Ard Biesheuvel <ard.biesheuvel@arm.com>; Andrew Fish <afish@apple.com>; Ni, Ray <ray.ni@intel.com>
Subject: Re: [EXTERNAL] [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature

Still waiting on some R-bs.

Have a new doc that will make it into a v7, if it helps anyone with their review…
https://github.com/microsoft/mu_basecore/blob/release/202005/MdeModulePkg/Universal/Variable/UefiVariablePolicy/ReadMe.md

Thanks!

- Bret

From: Bret Barkelew via groups.io<mailto:bret=corthon.com@groups.io>
Sent: Tuesday, June 23, 2020 4:19 AM
To: devel@edk2.groups.io<mailto:devel@edk2.groups.io>
Cc: Yao, Jiewen<mailto:jiewen.yao@intel.com>; Chao Zhang<mailto:chao.b.zhang@intel.com>; Jian J Wang<mailto:jian.j.wang@intel.com>; Hao A Wu<mailto:hao.a.wu@intel.com>; liming.gao<mailto:liming.gao@intel.com>; Jordan Justen<mailto:jordan.l.justen@intel.com>; Laszlo Ersek<mailto:lersek@redhat.com>; Ard Biesheuvel<mailto:ard.biesheuvel@arm.com>; Andrew Fish<mailto:afish@apple.com>; Ni, Ray<mailto:ray.ni@intel.com>
Subject: [EXTERNAL] [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature

REF:https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fbugzilla.tianocore.org%2Fshow_bug.cgi%3Fid%3D2522&amp;data=02%7C01%7Cbret.barkelew%40microsoft.com%7Cdf2ee1dbc25a4810f5ce08d817674112%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637285079522114249&amp;sdata=1%2F3MkPm5HuXeG%2FEaQgl%2F%2F8Tqu3UvgDs6Ich2ezXgjuY%3D&amp;reserved=0

The 14 patches in this series add the VariablePolicy feature to the core,
deprecate Edk2VarLock (while adding a compatibility layer to reduce code
churn), and integrate the VariablePolicy libraries and protocols into
Variable Services.

Since the integration requires multiple changes, including adding libraries,
a protocol, an SMI communication handler, and VariableServices integration,
the patches are broken up by individual library additions and then a final
integration. Security-sensitive changes like bypassing Authenticated
Variable enforcement are also broken out into individual patches so that
attention can be called directly to them.

Platform porting instructions are described in this wiki entry:
https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Ftianocore%2Ftianocore.github.io%2Fwiki%2FVariablePolicy-Protocol---Enhanced-Method-for-Managing-Variables%23platform-porting&amp;data=02%7C01%7Cbret.barkelew%40microsoft.com%7Cdf2ee1dbc25a4810f5ce08d817674112%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637285079522114249&amp;sdata=b%2FFdg6Sy2pdxbk3C%2FgVzXvoOWOxW6Z60QXRQ%2BVxGfFs%3D&amp;reserved=0

Discussion of the feature can be found in multiple places throughout
the last year on the RFC channel, staging branches, and in devel.

Most recently, this subject was discussed in this thread:
https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fedk2.groups.io%2Fg%2Fdevel%2Fmessage%2F53712&amp;data=02%7C01%7Cbret.barkelew%40microsoft.com%7Cdf2ee1dbc25a4810f5ce08d817674112%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637285079522114249&amp;sdata=epDJobMGos0As5T2JSwhs2PTy1IDt52oLqXkxEPJWLg%3D&amp;reserved=0
(the code branches shared in that discussion are now out of date, but the
whitepapers and discussion are relevant).

Cc: Jiewen Yao <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>
Cc: Chao Zhang <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>
Cc: Jian J Wang <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>
Cc: Hao A Wu <hao.a.wu@intel.com<mailto:hao.a.wu@intel.com>>
Cc: Liming Gao <liming.gao@intel.com<mailto:liming.gao@intel.com>>
Cc: Jordan Justen <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>
Cc: Laszlo Ersek <lersek@redhat.com<mailto:lersek@redhat.com>>
Cc: Ard Biesheuvel <ard.biesheuvel@arm.com<mailto:ard.biesheuvel@arm.com>>
Cc: Andrew Fish <afish@apple.com<mailto:afish@apple.com>>
Cc: Ray Ni <ray.ni@intel.com<mailto:ray.ni@intel.com>>
Cc: Bret Barkelew <brbarkel@microsoft.com<mailto:brbarkel@microsoft.com>>
Signed-off-by: Bret Barkelew <brbarkel@microsoft.com<mailto:brbarkel@microsoft.com>>

v6 changes:
* Fix an issue with uninitialized Status in InitVariablePolicyLib() and DeinitVariablePolicyLib()
* Fix GCC building in shell-based functional test
* Rebase on latest origin/master

v5 changes:
* Fix the CONST mismatch in VariablePolicy.h and VariablePolicySmmDxe.c
* Fix EFIAPI mismatches in the functional unittest
* Rebase on latest origin/master

v4 changes:
* Remove Optional PcdAllowVariablePolicyEnforcementDisable PCD from platforms
* Rebase on master
* Migrate to new MmCommunicate2 protocol
* Fix an oversight in the default return value for InitMmCommonCommBuffer
* Fix in VariablePolicyLib to allow ExtraInitRuntimeDxe to consume variables

V3 changes:
* Address all non-unittest issues with ECC
* Make additional style changes
* Include section name in hunk headers in "ini-style" files
* Remove requirement for the EdkiiPiSmmCommunicationsRegionTable driver
  (now allocates its own buffer)
* Change names from VARIABLE_POLICY_PROTOCOL and gVariablePolicyProtocolGuid
  to EDKII_VARIABLE_POLICY_PROTOCOL and gEdkiiVariablePolicyProtocolGuid
* Fix GCC warning about initializing externs
* Add UNI strings for new PCD
* Add patches for ArmVirtPkg, OvmfXen, and UefiPayloadPkg
* Reorder patches according to Liming's feedback about adding to platforms
  before changing variable driver

V2 changes:
* Fixed implementation for RuntimeDxe
* Add PCD to block DisableVariablePolicy
* Fix the DumpVariablePolicy pagination in SMM

Bret Barkelew (14):
  MdeModulePkg: Define the VariablePolicy protocol interface
  MdeModulePkg: Define the VariablePolicyLib
  MdeModulePkg: Define the VariablePolicyHelperLib
  MdeModulePkg: Define the VarCheckPolicyLib and SMM interface
  OvmfPkg: Add VariablePolicy engine to OvmfPkg platform
  EmulatorPkg: Add VariablePolicy engine to EmulatorPkg platform
  ArmVirtPkg: Add VariablePolicy engine to ArmVirtPkg platform
  UefiPayloadPkg: Add VariablePolicy engine to UefiPayloadPkg platform
  MdeModulePkg: Connect VariablePolicy business logic to
    VariableServices
  MdeModulePkg: Allow VariablePolicy state to delete protected variables
  SecurityPkg: Allow VariablePolicy state to delete authenticated
    variables
  MdeModulePkg: Change TCG MOR variables to use VariablePolicy
  MdeModulePkg: Drop VarLock from RuntimeDxe variable driver
  MdeModulePkg: Add a shell-based functional test for VariablePolicy

 MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.c                               |  320 +++
 MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.c                   |  396 ++++
 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitNull.c                     |   46 +
 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitRuntimeDxe.c               |   85 +
 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c                               |  816 +++++++
 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePolicyUnitTest.c   | 2440 ++++++++++++++++++++
 MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/VariablePolicyFuncTestApp.c        | 1978 ++++++++++++++++
 MdeModulePkg/Universal/Variable/RuntimeDxe/TcgMorLockDxe.c                               |   52 +-
 MdeModulePkg/Universal/Variable/RuntimeDxe/TcgMorLockSmm.c                               |   60 +-
 MdeModulePkg/Universal/Variable/RuntimeDxe/VarCheck.c                                    |   49 +-
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c                                 |   53 +
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableLockRequstToLock.c                    |   71 +
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariablePolicySmmDxe.c                        |  642 +++++
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c                       |   14 +
 SecurityPkg/Library/AuthVariableLib/AuthService.c                                        |   22 +-
 ArmVirtPkg/ArmVirt.dsc.inc                                                               |    4 +
 EmulatorPkg/EmulatorPkg.dsc                                                              |    3 +
 MdeModulePkg/Include/Guid/VarCheckPolicyMmi.h                                            |   54 +
 MdeModulePkg/Include/Library/VariablePolicyHelperLib.h                                   |  164 ++
 MdeModulePkg/Include/Library/VariablePolicyLib.h                                         |  207 ++
 MdeModulePkg/Include/Protocol/VariablePolicy.h                                           |  157 ++
 MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.inf                             |   42 +
 MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.uni                             |   12 +
 MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf                 |   35 +
 MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.uni                 |   12 +
 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf                             |   44 +
 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.uni                             |   12 +
 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf                   |   51 +
 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePolicyUnitTest.inf |   40 +
 MdeModulePkg/MdeModulePkg.ci.yaml                                                        |    4 +-
 MdeModulePkg/MdeModulePkg.dec                                                            |   26 +-
 MdeModulePkg/MdeModulePkg.dsc                                                            |   15 +
 MdeModulePkg/MdeModulePkg.uni                                                            |    7 +
 MdeModulePkg/Test/MdeModulePkgHostTest.dsc                                               |   11 +
 MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/Readme.md                          |   55 +
 MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/VariablePolicyFuncTestApp.inf      |   42 +
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf                        |    5 +
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf                               |    4 +
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf                     |   10 +
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf                      |    4 +
 OvmfPkg/OvmfPkgIa32.dsc                                                                  |    5 +
 OvmfPkg/OvmfPkgIa32X64.dsc                                                               |    5 +
 OvmfPkg/OvmfPkgX64.dsc                                                                   |    5 +
 OvmfPkg/OvmfXen.dsc                                                                      |    4 +
 SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf                                  |    2 +
 UefiPayloadPkg/UefiPayloadPkgIa32.dsc                                                    |    4 +
 UefiPayloadPkg/UefiPayloadPkgIa32X64.dsc                                                 |    4 +
 47 files changed, 8015 insertions(+), 78 deletions(-)
 create mode 100644 MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.c
 create mode 100644 MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.c
 create mode 100644 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitNull.c
 create mode 100644 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitRuntimeDxe.c
 create mode 100644 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c
 create mode 100644 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePolicyUnitTest.c
 create mode 100644 MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/VariablePolicyFuncTestApp.c
 create mode 100644 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableLockRequstToLock.c
 create mode 100644 MdeModulePkg/Universal/Variable/RuntimeDxe/VariablePolicySmmDxe.c
 create mode 100644 MdeModulePkg/Include/Guid/VarCheckPolicyMmi.h
 create mode 100644 MdeModulePkg/Include/Library/VariablePolicyHelperLib.h
 create mode 100644 MdeModulePkg/Include/Library/VariablePolicyLib.h
 create mode 100644 MdeModulePkg/Include/Protocol/VariablePolicy.h
 create mode 100644 MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.inf
 create mode 100644 MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.uni
 create mode 100644 MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf
 create mode 100644 MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.uni
 create mode 100644 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf
 create mode 100644 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.uni
 create mode 100644 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf
 create mode 100644 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePolicyUnitTest.inf
 create mode 100644 MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/Readme.md
 create mode 100644 MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/VariablePolicyFuncTestApp.inf

--
2.26.2.windows.1.8.g01c50adf56.20200515075929




[-- Attachment #2: Type: text/html, Size: 28948 bytes --]

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [EXTERNAL] [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature
  2020-07-30  1:36   ` Liming Gao
@ 2020-07-30  1:43     ` Bret Barkelew
  0 siblings, 0 replies; 48+ messages in thread
From: Bret Barkelew @ 2020-07-30  1:43 UTC (permalink / raw)
  To: liming.gao, devel@edk2.groups.io, bret@corthon.com, Leif Lindholm
  Cc: Yao, Jiewen, Wang, Jian J, Wu, Hao A, Justen, Jordan L,
	Laszlo Ersek, Ard Biesheuvel, Andrew Fish, Ni, Ray


[-- Attachment #1.1: Type: text/plain, Size: 16172 bytes --]

I believe the ARM platforms already have the change. At least the ArmVirt does and some of the edk2-platforms.

This is not news. It’s been broadcast repeatedly for the last 3 months. And the last 6 months. And the last 15 months.

- Bret

From: Gao, Liming<mailto:liming.gao@intel.com>
Sent: Wednesday, July 29, 2020 6:36 PM
To: devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Bret Barkelew<mailto:Bret.Barkelew@microsoft.com>; bret@corthon.com<mailto:bret@corthon.com>; Leif Lindholm<mailto:leif@nuviainc.com>
Cc: Yao, Jiewen<mailto:jiewen.yao@intel.com>; Wang, Jian J<mailto:jian.j.wang@intel.com>; Wu, Hao A<mailto:hao.a.wu@intel.com>; Justen, Jordan L<mailto:jordan.l.justen@intel.com>; Laszlo Ersek<mailto:lersek@redhat.com>; Ard Biesheuvel<mailto:ard.biesheuvel@arm.com>; Andrew Fish<mailto:afish@apple.com>; Ni, Ray<mailto:ray.ni@intel.com>
Subject: RE: [EXTERNAL] [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature

Include Leif. This change adds new library class dependency for the variable driver. So, it requires to update the platform DSC file. It will impact ARM platforms.

Thanks
Liming
From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Bret Barkelew via groups.io
Sent: 2020年7月30日 3:56
To: devel@edk2.groups.io; bret@corthon.com
Cc: Yao, Jiewen <jiewen.yao@intel.com>; Chao Zhang <chao.b.zhang@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>; Gao, Liming <liming.gao@intel.com>; Justen, Jordan L <jordan.l.justen@intel.com>; Laszlo Ersek <lersek@redhat.com>; Ard Biesheuvel <ard.biesheuvel@arm.com>; Andrew Fish <afish@apple.com>; Ni, Ray <ray.ni@intel.com>
Subject: Re: [EXTERNAL] [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature

Still waiting on some R-bs.

Have a new doc that will make it into a v7, if it helps anyone with their review…
https://github.com/microsoft/mu_basecore/blob/release/202005/MdeModulePkg/Universal/Variable/UefiVariablePolicy/ReadMe.md<https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fmicrosoft%2Fmu_basecore%2Fblob%2Frelease%2F202005%2FMdeModulePkg%2FUniversal%2FVariable%2FUefiVariablePolicy%2FReadMe.md&data=02%7C01%7Cbret.barkelew%40microsoft.com%7C4460189461a24b88baf008d83428f56f%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637316697813662165&sdata=B0OhR3dFCCE8oh2D02yAV3wv7%2FznN4YfBqFXMrGcrfA%3D&reserved=0>

Thanks!

- Bret

From: Bret Barkelew via groups.io<mailto:bret=corthon.com@groups.io>
Sent: Tuesday, June 23, 2020 4:19 AM
To: devel@edk2.groups.io<mailto:devel@edk2.groups.io>
Cc: Yao, Jiewen<mailto:jiewen.yao@intel.com>; Chao Zhang<mailto:chao.b.zhang@intel.com>; Jian J Wang<mailto:jian.j.wang@intel.com>; Hao A Wu<mailto:hao.a.wu@intel.com>; liming.gao<mailto:liming.gao@intel.com>; Jordan Justen<mailto:jordan.l.justen@intel.com>; Laszlo Ersek<mailto:lersek@redhat.com>; Ard Biesheuvel<mailto:ard.biesheuvel@arm.com>; Andrew Fish<mailto:afish@apple.com>; Ni, Ray<mailto:ray.ni@intel.com>
Subject: [EXTERNAL] [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature

REF:https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fbugzilla.tianocore.org%2Fshow_bug.cgi%3Fid%3D2522&amp;data=02%7C01%7Cbret.barkelew%40microsoft.com%7Cdf2ee1dbc25a4810f5ce08d817674112%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637285079522114249&amp;sdata=1%2F3MkPm5HuXeG%2FEaQgl%2F%2F8Tqu3UvgDs6Ich2ezXgjuY%3D&amp;reserved=0

The 14 patches in this series add the VariablePolicy feature to the core,
deprecate Edk2VarLock (while adding a compatibility layer to reduce code
churn), and integrate the VariablePolicy libraries and protocols into
Variable Services.

Since the integration requires multiple changes, including adding libraries,
a protocol, an SMI communication handler, and VariableServices integration,
the patches are broken up by individual library additions and then a final
integration. Security-sensitive changes like bypassing Authenticated
Variable enforcement are also broken out into individual patches so that
attention can be called directly to them.

Platform porting instructions are described in this wiki entry:
https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Ftianocore%2Ftianocore.github.io%2Fwiki%2FVariablePolicy-Protocol---Enhanced-Method-for-Managing-Variables%23platform-porting&amp;data=02%7C01%7Cbret.barkelew%40microsoft.com%7Cdf2ee1dbc25a4810f5ce08d817674112%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637285079522114249&amp;sdata=b%2FFdg6Sy2pdxbk3C%2FgVzXvoOWOxW6Z60QXRQ%2BVxGfFs%3D&amp;reserved=0<https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Ftianocore%2Ftianocore.github.io%2Fwiki%2FVariablePolicy-Protocol---Enhanced-Method-for-Managing-Variables%23platform-porting&data=02%7C01%7Cbret.barkelew%40microsoft.com%7C4460189461a24b88baf008d83428f56f%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637316697813662165&sdata=DS3OTIAEGm%2FgE9a%2FM87ILjkYuKdvFJg%2FI8nN1tSXP04%3D&reserved=0>

Discussion of the feature can be found in multiple places throughout
the last year on the RFC channel, staging branches, and in devel.

Most recently, this subject was discussed in this thread:
https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fedk2.groups.io%2Fg%2Fdevel%2Fmessage%2F53712&amp;data=02%7C01%7Cbret.barkelew%40microsoft.com%7Cdf2ee1dbc25a4810f5ce08d817674112%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637285079522114249&amp;sdata=epDJobMGos0As5T2JSwhs2PTy1IDt52oLqXkxEPJWLg%3D&amp;reserved=0<https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fedk2.groups.io%2Fg%2Fdevel%2Fmessage%2F53712&data=02%7C01%7Cbret.barkelew%40microsoft.com%7C4460189461a24b88baf008d83428f56f%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637316697813672160&sdata=LFhKgiz%2FK0queAWZK43BTiyGpvIZu82HOY636oPi2p4%3D&reserved=0>
(the code branches shared in that discussion are now out of date, but the
whitepapers and discussion are relevant).

Cc: Jiewen Yao <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>
Cc: Chao Zhang <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>
Cc: Jian J Wang <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>
Cc: Hao A Wu <hao.a.wu@intel.com<mailto:hao.a.wu@intel.com>>
Cc: Liming Gao <liming.gao@intel.com<mailto:liming.gao@intel.com>>
Cc: Jordan Justen <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>
Cc: Laszlo Ersek <lersek@redhat.com<mailto:lersek@redhat.com>>
Cc: Ard Biesheuvel <ard.biesheuvel@arm.com<mailto:ard.biesheuvel@arm.com>>
Cc: Andrew Fish <afish@apple.com<mailto:afish@apple.com>>
Cc: Ray Ni <ray.ni@intel.com<mailto:ray.ni@intel.com>>
Cc: Bret Barkelew <brbarkel@microsoft.com<mailto:brbarkel@microsoft.com>>
Signed-off-by: Bret Barkelew <brbarkel@microsoft.com<mailto:brbarkel@microsoft.com>>

v6 changes:
* Fix an issue with uninitialized Status in InitVariablePolicyLib() and DeinitVariablePolicyLib()
* Fix GCC building in shell-based functional test
* Rebase on latest origin/master

v5 changes:
* Fix the CONST mismatch in VariablePolicy.h and VariablePolicySmmDxe.c
* Fix EFIAPI mismatches in the functional unittest
* Rebase on latest origin/master

v4 changes:
* Remove Optional PcdAllowVariablePolicyEnforcementDisable PCD from platforms
* Rebase on master
* Migrate to new MmCommunicate2 protocol
* Fix an oversight in the default return value for InitMmCommonCommBuffer
* Fix in VariablePolicyLib to allow ExtraInitRuntimeDxe to consume variables

V3 changes:
* Address all non-unittest issues with ECC
* Make additional style changes
* Include section name in hunk headers in "ini-style" files
* Remove requirement for the EdkiiPiSmmCommunicationsRegionTable driver
  (now allocates its own buffer)
* Change names from VARIABLE_POLICY_PROTOCOL and gVariablePolicyProtocolGuid
  to EDKII_VARIABLE_POLICY_PROTOCOL and gEdkiiVariablePolicyProtocolGuid
* Fix GCC warning about initializing externs
* Add UNI strings for new PCD
* Add patches for ArmVirtPkg, OvmfXen, and UefiPayloadPkg
* Reorder patches according to Liming's feedback about adding to platforms
  before changing variable driver

V2 changes:
* Fixed implementation for RuntimeDxe
* Add PCD to block DisableVariablePolicy
* Fix the DumpVariablePolicy pagination in SMM

Bret Barkelew (14):
  MdeModulePkg: Define the VariablePolicy protocol interface
  MdeModulePkg: Define the VariablePolicyLib
  MdeModulePkg: Define the VariablePolicyHelperLib
  MdeModulePkg: Define the VarCheckPolicyLib and SMM interface
  OvmfPkg: Add VariablePolicy engine to OvmfPkg platform
  EmulatorPkg: Add VariablePolicy engine to EmulatorPkg platform
  ArmVirtPkg: Add VariablePolicy engine to ArmVirtPkg platform
  UefiPayloadPkg: Add VariablePolicy engine to UefiPayloadPkg platform
  MdeModulePkg: Connect VariablePolicy business logic to
    VariableServices
  MdeModulePkg: Allow VariablePolicy state to delete protected variables
  SecurityPkg: Allow VariablePolicy state to delete authenticated
    variables
  MdeModulePkg: Change TCG MOR variables to use VariablePolicy
  MdeModulePkg: Drop VarLock from RuntimeDxe variable driver
  MdeModulePkg: Add a shell-based functional test for VariablePolicy

 MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.c                               |  320 +++
 MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.c                   |  396 ++++
 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitNull.c                     |   46 +
 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitRuntimeDxe.c               |   85 +
 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c                               |  816 +++++++
 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePolicyUnitTest.c   | 2440 ++++++++++++++++++++
 MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/VariablePolicyFuncTestApp.c        | 1978 ++++++++++++++++
 MdeModulePkg/Universal/Variable/RuntimeDxe/TcgMorLockDxe.c                               |   52 +-
 MdeModulePkg/Universal/Variable/RuntimeDxe/TcgMorLockSmm.c                               |   60 +-
 MdeModulePkg/Universal/Variable/RuntimeDxe/VarCheck.c                                    |   49 +-
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c                                 |   53 +
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableLockRequstToLock.c                    |   71 +
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariablePolicySmmDxe.c                        |  642 +++++
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c                       |   14 +
 SecurityPkg/Library/AuthVariableLib/AuthService.c                                        |   22 +-
 ArmVirtPkg/ArmVirt.dsc.inc                                                               |    4 +
 EmulatorPkg/EmulatorPkg.dsc                                                              |    3 +
 MdeModulePkg/Include/Guid/VarCheckPolicyMmi.h                                            |   54 +
 MdeModulePkg/Include/Library/VariablePolicyHelperLib.h                                   |  164 ++
 MdeModulePkg/Include/Library/VariablePolicyLib.h                                         |  207 ++
 MdeModulePkg/Include/Protocol/VariablePolicy.h                                           |  157 ++
 MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.inf                             |   42 +
 MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.uni                             |   12 +
 MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf                 |   35 +
 MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.uni                 |   12 +
 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf                             |   44 +
 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.uni                             |   12 +
 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf                   |   51 +
 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePolicyUnitTest.inf |   40 +
 MdeModulePkg/MdeModulePkg.ci.yaml                                                        |    4 +-
 MdeModulePkg/MdeModulePkg.dec                                                            |   26 +-
 MdeModulePkg/MdeModulePkg.dsc                                                            |   15 +
 MdeModulePkg/MdeModulePkg.uni                                                            |    7 +
 MdeModulePkg/Test/MdeModulePkgHostTest.dsc                                               |   11 +
 MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/Readme.md                          |   55 +
 MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/VariablePolicyFuncTestApp.inf      |   42 +
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf                        |    5 +
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf                               |    4 +
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf                     |   10 +
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf                      |    4 +
 OvmfPkg/OvmfPkgIa32.dsc                                                                  |    5 +
 OvmfPkg/OvmfPkgIa32X64.dsc                                                               |    5 +
 OvmfPkg/OvmfPkgX64.dsc                                                                   |    5 +
 OvmfPkg/OvmfXen.dsc                                                                      |    4 +
 SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf                                  |    2 +
 UefiPayloadPkg/UefiPayloadPkgIa32.dsc                                                    |    4 +
 UefiPayloadPkg/UefiPayloadPkgIa32X64.dsc                                                 |    4 +
 47 files changed, 8015 insertions(+), 78 deletions(-)
 create mode 100644 MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.c
 create mode 100644 MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.c
 create mode 100644 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitNull.c
 create mode 100644 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitRuntimeDxe.c
 create mode 100644 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c
 create mode 100644 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePolicyUnitTest.c
 create mode 100644 MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/VariablePolicyFuncTestApp.c
 create mode 100644 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableLockRequstToLock.c
 create mode 100644 MdeModulePkg/Universal/Variable/RuntimeDxe/VariablePolicySmmDxe.c
 create mode 100644 MdeModulePkg/Include/Guid/VarCheckPolicyMmi.h
 create mode 100644 MdeModulePkg/Include/Library/VariablePolicyHelperLib.h
 create mode 100644 MdeModulePkg/Include/Library/VariablePolicyLib.h
 create mode 100644 MdeModulePkg/Include/Protocol/VariablePolicy.h
 create mode 100644 MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.inf
 create mode 100644 MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.uni
 create mode 100644 MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf
 create mode 100644 MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.uni
 create mode 100644 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf
 create mode 100644 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.uni
 create mode 100644 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf
 create mode 100644 MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePolicyUnitTest.inf
 create mode 100644 MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/Readme.md
 create mode 100644 MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/VariablePolicyFuncTestApp.inf

--
2.26.2.windows.1.8.g01c50adf56.20200515075929






[-- Attachment #1.2: Type: text/html, Size: 30210 bytes --]

[-- Attachment #2: C91A1AC82CAD4CAF87A9F26E74F492D4.png --]
[-- Type: image/png, Size: 151 bytes --]

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature
       [not found] ` <161DCDB779DB4B3C.30988@groups.io>
@ 2020-08-11 13:52   ` Dandan Bi
  2020-08-18  5:24     ` Bret Barkelew
       [not found]     ` <162C456ABCC01019.19371@groups.io>
  0 siblings, 2 replies; 48+ messages in thread
From: Dandan Bi @ 2020-08-11 13:52 UTC (permalink / raw)
  To: devel@edk2.groups.io, Bi, Dandan, bret@corthon.com
  Cc: Yao, Jiewen, Zhang, Chao B, Wang, Jian J, Wu, Hao A, Gao, Liming,
	Justen, Jordan L, Laszlo Ersek, Ard Biesheuvel, Andrew Fish,
	Ni, Ray

Hi Bret,

Sorry for the delayed response.

Some more comments here:

1. Currently I see the LockVaribePolicy is called at ReadyToBoot by variable driver, could we update it to be called at EndOfDxe? We should prevent malicious code registering policy after EndOfDxe for security concern. And could we also add the test case to check the variable policy is locked at EndofDxe?

2. For patch 4, the SMM communication,  some general guidelines for SMI handler:
a)  Check whether the communication buffer is outside SMM and valid.
For this feature, please double check whether the communication buffer is checked, if all the range in communication buffer has already been checked within existing edk2 core infrastructure, please also add the comments in the code to mention that it has been checked.

b) Should copy the communication buffer to SMRAM before checking the data fields to avoid TOC/TOU attac
For this feature, for example, when dump variable policy, if malicious code updates the DumpParams->TotalSize in communication buffer to smaller one to allocate the PaginationCache buffer, and then update it the correct one and dump the variable policy data into the PaginationCache buffer, it will cause buffer overflow in this case.  So please double check the code and copy the communication buffer into SMRAM to avoid such kind issue. 

3. Did you do any security test for this feature?

4. Currently, LockVariablePolicy can prevent RegisterVariablePolicy and DisableVariablePolicy. So in SMI hander, could we check the variable policy is locked or not firstly and then decide whether need to check and execution for VAR_CHECK_POLICY_COMMAND_REGISTER and VAR_CHECK_POLICY_COMMAND_DISABLE?

5. Since there is the logic when variable policy is disabled, it will permit deletion of auth/protected variables. Could we add some comments in code to mention that variable policy should always be enabled for security concern to avoid giving bad example?


Thanks,
Dandan
> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Dandan
> Bi
> Sent: Thursday, July 2, 2020 10:14 AM
> To: devel@edk2.groups.io; bret@corthon.com
> Cc: Yao, Jiewen <jiewen.yao@intel.com>; Zhang, Chao B
> <chao.b.zhang@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao
> A <hao.a.wu@intel.com>; Gao, Liming <liming.gao@intel.com>; Justen,
> Jordan L <jordan.l.justen@intel.com>; Laszlo Ersek <lersek@redhat.com>;
> Ard Biesheuvel <ard.biesheuvel@arm.com>; Andrew Fish
> <afish@apple.com>; Ni, Ray <ray.ni@intel.com>
> Subject: Re: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature
> 
> Hi Bret,
> 
> Thanks for the contribution.
> 
> I have taken an overview of this patch series and have some small comments
> in the related patches, please check in sub-patch.
> 
> I will review the patch series more in details and bring more comments back
> if have. Do you have a branch for these patches in GitHub? Which should be
> easy for review.
> 
> 
> Thanks,
> Dandan
> 
> > -----Original Message-----
> > From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Bret
> > Barkelew
> > Sent: Tuesday, June 23, 2020 2:41 PM
> > To: devel@edk2.groups.io
> > Cc: Yao, Jiewen <jiewen.yao@intel.com>; Zhang, Chao B
> > <chao.b.zhang@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Wu,
> > Hao A <hao.a.wu@intel.com>; Gao, Liming <liming.gao@intel.com>;
> > Justen, Jordan L <jordan.l.justen@intel.com>; Laszlo Ersek
> > <lersek@redhat.com>; Ard Biesheuvel <ard.biesheuvel@arm.com>;
> Andrew
> > Fish <afish@apple.com>; Ni, Ray <ray.ni@intel.com>
> > Subject: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature
> >
> > REF:https://bugzilla.tianocore.org/show_bug.cgi?id=2522
> >
> > The 14 patches in this series add the VariablePolicy feature to the
> > core, deprecate Edk2VarLock (while adding a compatibility layer to
> > reduce code churn), and integrate the VariablePolicy libraries and
> > protocols into Variable Services.
> >
> > Since the integration requires multiple changes, including adding
> > libraries, a protocol, an SMI communication handler, and
> > VariableServices integration, the patches are broken up by individual
> > library additions and then a final integration. Security-sensitive
> > changes like bypassing Authenticated Variable enforcement are also
> > broken out into individual patches so that attention can be called directly to
> them.
> >
> > Platform porting instructions are described in this wiki entry:
> > https://github.com/tianocore/tianocore.github.io/wiki/VariablePolicy-
> > Protocol---Enhanced-Method-for-Managing-Variables#platform-porting
> >
> > Discussion of the feature can be found in multiple places throughout
> > the last year on the RFC channel, staging branches, and in devel.
> >
> > Most recently, this subject was discussed in this thread:
> > https://edk2.groups.io/g/devel/message/53712
> > (the code branches shared in that discussion are now out of date, but
> > the whitepapers and discussion are relevant).
> >
> > Cc: Jiewen Yao <jiewen.yao@intel.com>
> > Cc: Chao Zhang <chao.b.zhang@intel.com>
> > Cc: Jian J Wang <jian.j.wang@intel.com>
> > Cc: Hao A Wu <hao.a.wu@intel.com>
> > Cc: Liming Gao <liming.gao@intel.com>
> > Cc: Jordan Justen <jordan.l.justen@intel.com>
> > Cc: Laszlo Ersek <lersek@redhat.com>
> > Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
> > Cc: Andrew Fish <afish@apple.com>
> > Cc: Ray Ni <ray.ni@intel.com>
> > Cc: Bret Barkelew <brbarkel@microsoft.com>
> > Signed-off-by: Bret Barkelew <brbarkel@microsoft.com>
> >
> > v6 changes:
> > * Fix an issue with uninitialized Status in InitVariablePolicyLib()
> > and
> > DeinitVariablePolicyLib()
> > * Fix GCC building in shell-based functional test
> > * Rebase on latest origin/master
> >
> > v5 changes:
> > * Fix the CONST mismatch in VariablePolicy.h and
> > VariablePolicySmmDxe.c
> > * Fix EFIAPI mismatches in the functional unittest
> > * Rebase on latest origin/master
> >
> > v4 changes:
> > * Remove Optional PcdAllowVariablePolicyEnforcementDisable PCD from
> > platforms
> > * Rebase on master
> > * Migrate to new MmCommunicate2 protocol
> > * Fix an oversight in the default return value for
> > InitMmCommonCommBuffer
> > * Fix in VariablePolicyLib to allow ExtraInitRuntimeDxe to consume
> > variables
> >
> > V3 changes:
> > * Address all non-unittest issues with ECC
> > * Make additional style changes
> > * Include section name in hunk headers in "ini-style" files
> > * Remove requirement for the EdkiiPiSmmCommunicationsRegionTable
> > driver
> >   (now allocates its own buffer)
> > * Change names from VARIABLE_POLICY_PROTOCOL and
> > gVariablePolicyProtocolGuid
> >   to EDKII_VARIABLE_POLICY_PROTOCOL and
> > gEdkiiVariablePolicyProtocolGuid
> > * Fix GCC warning about initializing externs
> > * Add UNI strings for new PCD
> > * Add patches for ArmVirtPkg, OvmfXen, and UefiPayloadPkg
> > * Reorder patches according to Liming's feedback about adding to
> platforms
> >   before changing variable driver
> >
> > V2 changes:
> > * Fixed implementation for RuntimeDxe
> > * Add PCD to block DisableVariablePolicy
> > * Fix the DumpVariablePolicy pagination in SMM
> >
> > Bret Barkelew (14):
> >   MdeModulePkg: Define the VariablePolicy protocol interface
> >   MdeModulePkg: Define the VariablePolicyLib
> >   MdeModulePkg: Define the VariablePolicyHelperLib
> >   MdeModulePkg: Define the VarCheckPolicyLib and SMM interface
> >   OvmfPkg: Add VariablePolicy engine to OvmfPkg platform
> >   EmulatorPkg: Add VariablePolicy engine to EmulatorPkg platform
> >   ArmVirtPkg: Add VariablePolicy engine to ArmVirtPkg platform
> >   UefiPayloadPkg: Add VariablePolicy engine to UefiPayloadPkg platform
> >   MdeModulePkg: Connect VariablePolicy business logic to
> >     VariableServices
> >   MdeModulePkg: Allow VariablePolicy state to delete protected variables
> >   SecurityPkg: Allow VariablePolicy state to delete authenticated
> >     variables
> >   MdeModulePkg: Change TCG MOR variables to use VariablePolicy
> >   MdeModulePkg: Drop VarLock from RuntimeDxe variable driver
> >   MdeModulePkg: Add a shell-based functional test for VariablePolicy
> >
> >  MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.c
> > |  320 +++
> >
> > MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.c
> > |  396 ++++
> >  MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitNull.c
> > |   46 +
> >
> >
> MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitRuntimeDx
> > e.c               |   85 +
> >  MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c
> > |  816 +++++++
> >
> >
> MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePo
> > licyUnitTest.c   | 2440 ++++++++++++++++++++
> >
> >
> MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/VariablePolicyFu
> > ncTestApp.c        | 1978 ++++++++++++++++
> >  MdeModulePkg/Universal/Variable/RuntimeDxe/TcgMorLockDxe.c
> > |   52 +-
> >  MdeModulePkg/Universal/Variable/RuntimeDxe/TcgMorLockSmm.c
> > |   60 +-
> >  MdeModulePkg/Universal/Variable/RuntimeDxe/VarCheck.c
> > |   49 +-
> >  MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c
> > |   53 +
> >
> >
> MdeModulePkg/Universal/Variable/RuntimeDxe/VariableLockRequstToLock
> > .c                    |   71 +
> >  MdeModulePkg/Universal/Variable/RuntimeDxe/VariablePolicySmmDxe.c
> > |  642 +++++
> >
> >
> MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.
> > c                       |   14 +
> >  SecurityPkg/Library/AuthVariableLib/AuthService.c                                        |
> 22
> > +-
> >  ArmVirtPkg/ArmVirt.dsc.inc                                                               |    4 +
> >  EmulatorPkg/EmulatorPkg.dsc                                                              |    3 +
> >  MdeModulePkg/Include/Guid/VarCheckPolicyMmi.h
> |
> > 54 +
> >  MdeModulePkg/Include/Library/VariablePolicyHelperLib.h
> > |  164 ++
> >  MdeModulePkg/Include/Library/VariablePolicyLib.h                                         |
> > 207 ++
> >  MdeModulePkg/Include/Protocol/VariablePolicy.h                                           |
> > 157 ++
> >  MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.inf
> > |   42 +
> >  MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.uni
> > |   12 +
> >
> > MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.i
> > nf
> > |   35 +
> >
> > MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.u
> > ni
> > |   12 +
> >  MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf
> > |   44 +
> >  MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.uni
> > |   12 +
> >
> > MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf
> > |   51 +
> >
> >
> MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePo
> > licyUnitTest.inf |   40 +
> >  MdeModulePkg/MdeModulePkg.ci.yaml                                                        |    4
> +-
> >  MdeModulePkg/MdeModulePkg.dec                                                            |   26 +-
> >  MdeModulePkg/MdeModulePkg.dsc                                                            |   15 +
> >  MdeModulePkg/MdeModulePkg.uni                                                            |    7 +
> >  MdeModulePkg/Test/MdeModulePkgHostTest.dsc
> |
> > 11 +
> >  MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/Readme.md
> > |   55 +
> >
> >
> MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/VariablePolicyFu
> > ncTestApp.inf      |   42 +
> >  MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
> > |    5 +
> >  MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf
> > |    4 +
> >
> >
> MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.i
> > nf                     |   10 +
> >
> >
> MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf
> > |    4 +
> >  OvmfPkg/OvmfPkgIa32.dsc                                                                  |    5 +
> >  OvmfPkg/OvmfPkgIa32X64.dsc                                                               |    5 +
> >  OvmfPkg/OvmfPkgX64.dsc                                                                   |    5 +
> >  OvmfPkg/OvmfXen.dsc                                                                      |    4 +
> >  SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf                                  |
> > 2 +
> >  UefiPayloadPkg/UefiPayloadPkgIa32.dsc                                                    |    4 +
> >  UefiPayloadPkg/UefiPayloadPkgIa32X64.dsc                                                 |    4 +
> >  47 files changed, 8015 insertions(+), 78 deletions(-)  create mode
> > 100644 MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.c
> >  create mode 100644
> > MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.c
> >  create mode 100644
> > MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitNull.c
> >  create mode 100644
> > MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitRuntimeD
> > x
> > e.c
> >  create mode 100644
> > MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c
> >  create mode 100644
> > MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/Variable
> > Po
> > licyUnitTest.c
> >  create mode 100644
> >
> MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/VariablePolicyFu
> > ncTestApp.c
> >  create mode 100644
> >
> MdeModulePkg/Universal/Variable/RuntimeDxe/VariableLockRequstToLock
> > .c
> >  create mode 100644
> > MdeModulePkg/Universal/Variable/RuntimeDxe/VariablePolicySmmDxe.c
> >  create mode 100644 MdeModulePkg/Include/Guid/VarCheckPolicyMmi.h
> >  create mode 100644
> > MdeModulePkg/Include/Library/VariablePolicyHelperLib.h
> >  create mode 100644 MdeModulePkg/Include/Library/VariablePolicyLib.h
> >  create mode 100644 MdeModulePkg/Include/Protocol/VariablePolicy.h
> >  create mode 100644
> > MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.inf
> >  create mode 100644
> > MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.uni
> >  create mode 100644
> > MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.i
> > nf
> >  create mode 100644
> > MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.u
> > ni
> >  create mode 100644
> > MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf
> >  create mode 100644
> > MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.uni
> >  create mode 100644
> > MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf
> >  create mode 100644
> > MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/Variable
> > Po
> > licyUnitTest.inf
> >  create mode 100644
> > MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/Readme.md
> >  create mode 100644
> >
> MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/VariablePolicyFu
> > ncTestApp.inf
> >
> > --
> > 2.26.2.windows.1.8.g01c50adf56.20200515075929
> >
> >
> >
> 
> 
> 


^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature
  2020-08-11 13:52   ` Dandan Bi
@ 2020-08-18  5:24     ` Bret Barkelew
       [not found]     ` <162C456ABCC01019.19371@groups.io>
  1 sibling, 0 replies; 48+ messages in thread
From: Bret Barkelew @ 2020-08-18  5:24 UTC (permalink / raw)
  To: devel@edk2.groups.io, dandan.bi@intel.com, bret@corthon.com
  Cc: Yao, Jiewen, Zhang, Chao B, Wang, Jian J, Wu, Hao A, liming.gao,
	Justen, Jordan L, Laszlo Ersek, Ard Biesheuvel, Andrew Fish,
	Ni, Ray

[-- Attachment #1: Type: text/plain, Size: 18113 bytes --]

Responses below…

- Bret

From: Dandan Bi via groups.io<mailto:dandan.bi=intel.com@groups.io>
Sent: Tuesday, August 11, 2020 6:52 AM
To: devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Bi, Dandan<mailto:dandan.bi@intel.com>; bret@corthon.com<mailto:bret@corthon.com>
Cc: Yao, Jiewen<mailto:jiewen.yao@intel.com>; Zhang, Chao B<mailto:chao.b.zhang@intel.com>; Wang, Jian J<mailto:jian.j.wang@intel.com>; Wu, Hao A<mailto:hao.a.wu@intel.com>; liming.gao<mailto:liming.gao@intel.com>; Justen, Jordan L<mailto:jordan.l.justen@intel.com>; Laszlo Ersek<mailto:lersek@redhat.com>; Ard Biesheuvel<mailto:ard.biesheuvel@arm.com>; Andrew Fish<mailto:afish@apple.com>; Ni, Ray<mailto:ray.ni@intel.com>
Subject: [EXTERNAL] Re: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature

Hi Bret,

Sorry for the delayed response.

Some more comments here:

1. Currently I see the LockVaribePolicy is called at ReadyToBoot by variable driver, could we update it to be called at EndOfDxe? We should prevent malicious code registering policy after EndOfDxe for security concern. And could we also add the test case to check the variable policy is locked at EndofDxe?
We could. Right now it’s at ReadyToBoot because it’s just there as a safety net and the platform could lock it earlier. Would it work to have a PCD for which EventGroup GUID the platform should lock on?

2. For patch 4, the SMM communication,  some general guidelines for SMI handler:
a)  Check whether the communication buffer is outside SMM and valid.
For this feature, please double check whether the communication buffer is checked, if all the range in communication buffer has already been checked within existing edk2 core infrastructure, please also add the comments in the code to mention that it has been checked.
I checked this, but I will recheck (since there’ve been a few revisions in the patches) and update the comments.

b) Should copy the communication buffer to SMRAM before checking the data fields to avoid TOC/TOU attac
For this feature, for example, when dump variable policy, if malicious code updates the DumpParams->TotalSize in communication buffer to smaller one to allocate the PaginationCache buffer, and then update it the correct one and dump the variable policy data into the PaginationCache buffer, it will cause buffer overflow in this case.  So please double check the code and copy the communication buffer into SMRAM to avoid such kind issue.
Will also check for this.

3. Did you do any security test for this feature?
Such as? There are both unit tests and integration tests to ensure correct functionality and that the disable and lock interfaces work as expected. I haven’t fuzzed it or anything that involved.

4. Currently, LockVariablePolicy can prevent RegisterVariablePolicy and DisableVariablePolicy. So in SMI hander, could we check the variable policy is locked or not firstly and then decide whether need to check and execution for VAR_CHECK_POLICY_COMMAND_REGISTER and VAR_CHECK_POLICY_COMMAND_DISABLE?
I’ll take a look, but my gut says this may be an unnecessary complication.

5. Since there is the logic when variable policy is disabled, it will permit deletion of auth/protected variables. Could we add some comments in code to mention that variable policy should always be enabled for security concern to avoid giving bad example?
I’m happy to think about how to document this, but I’m not immediately inclined to outright say it shouldn’t be disabled. I’d be happy to say that it shouldn’t be disabled in “normal, production configuration”, but it’s entirely reasonable to be disabled in a Manufacturing or R&R environment and we would actually prefer this be used because it would at least be consistent across platforms, rather than being something done ad hoc by each platform that needs it. Would that be sufficient?

Thanks,
Dandan
> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Dandan
> Bi
> Sent: Thursday, July 2, 2020 10:14 AM
> To: devel@edk2.groups.io; bret@corthon.com
> Cc: Yao, Jiewen <jiewen.yao@intel.com>; Zhang, Chao B
> <chao.b.zhang@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao
> A <hao.a.wu@intel.com>; Gao, Liming <liming.gao@intel.com>; Justen,
> Jordan L <jordan.l.justen@intel.com>; Laszlo Ersek <lersek@redhat.com>;
> Ard Biesheuvel <ard.biesheuvel@arm.com>; Andrew Fish
> <afish@apple.com>; Ni, Ray <ray.ni@intel.com>
> Subject: Re: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature
>
> Hi Bret,
>
> Thanks for the contribution.
>
> I have taken an overview of this patch series and have some small comments
> in the related patches, please check in sub-patch.
>
> I will review the patch series more in details and bring more comments back
> if have. Do you have a branch for these patches in GitHub? Which should be
> easy for review.
>
>
> Thanks,
> Dandan
>
> > -----Original Message-----
> > From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Bret
> > Barkelew
> > Sent: Tuesday, June 23, 2020 2:41 PM
> > To: devel@edk2.groups.io
> > Cc: Yao, Jiewen <jiewen.yao@intel.com>; Zhang, Chao B
> > <chao.b.zhang@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Wu,
> > Hao A <hao.a.wu@intel.com>; Gao, Liming <liming.gao@intel.com>;
> > Justen, Jordan L <jordan.l.justen@intel.com>; Laszlo Ersek
> > <lersek@redhat.com>; Ard Biesheuvel <ard.biesheuvel@arm.com>;
> Andrew
> > Fish <afish@apple.com>; Ni, Ray <ray.ni@intel.com>
> > Subject: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature
> >
> > REF:https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fbugzilla.tianocore.org%2Fshow_bug.cgi%3Fid%3D2522&amp;data=02%7C01%7CBret.Barkelew%40microsoft.com%7C91eed7c4a0d54e2eff6008d83dfdc4ec%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637327507431539442&amp;sdata=cLpx7VZsG%2F6r6GCXmiCS4DmmgOH4iKfX3VSAAYUOU00%3D&amp;reserved=0
> >
> > The 14 patches in this series add the VariablePolicy feature to the
> > core, deprecate Edk2VarLock (while adding a compatibility layer to
> > reduce code churn), and integrate the VariablePolicy libraries and
> > protocols into Variable Services.
> >
> > Since the integration requires multiple changes, including adding
> > libraries, a protocol, an SMI communication handler, and
> > VariableServices integration, the patches are broken up by individual
> > library additions and then a final integration. Security-sensitive
> > changes like bypassing Authenticated Variable enforcement are also
> > broken out into individual patches so that attention can be called directly to
> them.
> >
> > Platform porting instructions are described in this wiki entry:
> > https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Ftianocore%2Ftianocore.github.io%2Fwiki%2FVariablePolicy-&amp;data=02%7C01%7CBret.Barkelew%40microsoft.com%7C91eed7c4a0d54e2eff6008d83dfdc4ec%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637327507431539442&amp;sdata=%2FYNgK7yixA5Gi7E9bHw3LIUNAQpZMh9ykTUqCqv2SRY%3D&amp;reserved=0
> > Protocol---Enhanced-Method-for-Managing-Variables#platform-porting
> >
> > Discussion of the feature can be found in multiple places throughout
> > the last year on the RFC channel, staging branches, and in devel.
> >
> > Most recently, this subject was discussed in this thread:
> > https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fedk2.groups.io%2Fg%2Fdevel%2Fmessage%2F53712&amp;data=02%7C01%7CBret.Barkelew%40microsoft.com%7C91eed7c4a0d54e2eff6008d83dfdc4ec%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637327507431539442&amp;sdata=i7qaO6eZT8%2BzCT0satTptMWwCNspDz%2BS05eJmGGR628%3D&amp;reserved=0
> > (the code branches shared in that discussion are now out of date, but
> > the whitepapers and discussion are relevant).
> >
> > Cc: Jiewen Yao <jiewen.yao@intel.com>
> > Cc: Chao Zhang <chao.b.zhang@intel.com>
> > Cc: Jian J Wang <jian.j.wang@intel.com>
> > Cc: Hao A Wu <hao.a.wu@intel.com>
> > Cc: Liming Gao <liming.gao@intel.com>
> > Cc: Jordan Justen <jordan.l.justen@intel.com>
> > Cc: Laszlo Ersek <lersek@redhat.com>
> > Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
> > Cc: Andrew Fish <afish@apple.com>
> > Cc: Ray Ni <ray.ni@intel.com>
> > Cc: Bret Barkelew <brbarkel@microsoft.com>
> > Signed-off-by: Bret Barkelew <brbarkel@microsoft.com>
> >
> > v6 changes:
> > * Fix an issue with uninitialized Status in InitVariablePolicyLib()
> > and
> > DeinitVariablePolicyLib()
> > * Fix GCC building in shell-based functional test
> > * Rebase on latest origin/master
> >
> > v5 changes:
> > * Fix the CONST mismatch in VariablePolicy.h and
> > VariablePolicySmmDxe.c
> > * Fix EFIAPI mismatches in the functional unittest
> > * Rebase on latest origin/master
> >
> > v4 changes:
> > * Remove Optional PcdAllowVariablePolicyEnforcementDisable PCD from
> > platforms
> > * Rebase on master
> > * Migrate to new MmCommunicate2 protocol
> > * Fix an oversight in the default return value for
> > InitMmCommonCommBuffer
> > * Fix in VariablePolicyLib to allow ExtraInitRuntimeDxe to consume
> > variables
> >
> > V3 changes:
> > * Address all non-unittest issues with ECC
> > * Make additional style changes
> > * Include section name in hunk headers in "ini-style" files
> > * Remove requirement for the EdkiiPiSmmCommunicationsRegionTable
> > driver
> >   (now allocates its own buffer)
> > * Change names from VARIABLE_POLICY_PROTOCOL and
> > gVariablePolicyProtocolGuid
> >   to EDKII_VARIABLE_POLICY_PROTOCOL and
> > gEdkiiVariablePolicyProtocolGuid
> > * Fix GCC warning about initializing externs
> > * Add UNI strings for new PCD
> > * Add patches for ArmVirtPkg, OvmfXen, and UefiPayloadPkg
> > * Reorder patches according to Liming's feedback about adding to
> platforms
> >   before changing variable driver
> >
> > V2 changes:
> > * Fixed implementation for RuntimeDxe
> > * Add PCD to block DisableVariablePolicy
> > * Fix the DumpVariablePolicy pagination in SMM
> >
> > Bret Barkelew (14):
> >   MdeModulePkg: Define the VariablePolicy protocol interface
> >   MdeModulePkg: Define the VariablePolicyLib
> >   MdeModulePkg: Define the VariablePolicyHelperLib
> >   MdeModulePkg: Define the VarCheckPolicyLib and SMM interface
> >   OvmfPkg: Add VariablePolicy engine to OvmfPkg platform
> >   EmulatorPkg: Add VariablePolicy engine to EmulatorPkg platform
> >   ArmVirtPkg: Add VariablePolicy engine to ArmVirtPkg platform
> >   UefiPayloadPkg: Add VariablePolicy engine to UefiPayloadPkg platform
> >   MdeModulePkg: Connect VariablePolicy business logic to
> >     VariableServices
> >   MdeModulePkg: Allow VariablePolicy state to delete protected variables
> >   SecurityPkg: Allow VariablePolicy state to delete authenticated
> >     variables
> >   MdeModulePkg: Change TCG MOR variables to use VariablePolicy
> >   MdeModulePkg: Drop VarLock from RuntimeDxe variable driver
> >   MdeModulePkg: Add a shell-based functional test for VariablePolicy
> >
> >  MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.c
> > |  320 +++
> >
> > MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.c
> > |  396 ++++
> >  MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitNull.c
> > |   46 +
> >
> >
> MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitRuntimeDx
> > e.c               |   85 +
> >  MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c
> > |  816 +++++++
> >
> >
> MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePo
> > licyUnitTest.c   | 2440 ++++++++++++++++++++
> >
> >
> MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/VariablePolicyFu
> > ncTestApp.c        | 1978 ++++++++++++++++
> >  MdeModulePkg/Universal/Variable/RuntimeDxe/TcgMorLockDxe.c
> > |   52 +-
> >  MdeModulePkg/Universal/Variable/RuntimeDxe/TcgMorLockSmm.c
> > |   60 +-
> >  MdeModulePkg/Universal/Variable/RuntimeDxe/VarCheck.c
> > |   49 +-
> >  MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c
> > |   53 +
> >
> >
> MdeModulePkg/Universal/Variable/RuntimeDxe/VariableLockRequstToLock
> > .c                    |   71 +
> >  MdeModulePkg/Universal/Variable/RuntimeDxe/VariablePolicySmmDxe.c
> > |  642 +++++
> >
> >
> MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.
> > c                       |   14 +
> >  SecurityPkg/Library/AuthVariableLib/AuthService.c                                        |
> 22
> > +-
> >  ArmVirtPkg/ArmVirt.dsc.inc                                                               |    4 +
> >  EmulatorPkg/EmulatorPkg.dsc                                                              |    3 +
> >  MdeModulePkg/Include/Guid/VarCheckPolicyMmi.h
> |
> > 54 +
> >  MdeModulePkg/Include/Library/VariablePolicyHelperLib.h
> > |  164 ++
> >  MdeModulePkg/Include/Library/VariablePolicyLib.h                                         |
> > 207 ++
> >  MdeModulePkg/Include/Protocol/VariablePolicy.h                                           |
> > 157 ++
> >  MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.inf
> > |   42 +
> >  MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.uni
> > |   12 +
> >
> > MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.i
> > nf
> > |   35 +
> >
> > MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.u
> > ni
> > |   12 +
> >  MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf
> > |   44 +
> >  MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.uni
> > |   12 +
> >
> > MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf
> > |   51 +
> >
> >
> MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePo
> > licyUnitTest.inf |   40 +
> >  MdeModulePkg/MdeModulePkg.ci.yaml                                                        |    4
> +-
> >  MdeModulePkg/MdeModulePkg.dec                                                            |   26 +-
> >  MdeModulePkg/MdeModulePkg.dsc                                                            |   15 +
> >  MdeModulePkg/MdeModulePkg.uni                                                            |    7 +
> >  MdeModulePkg/Test/MdeModulePkgHostTest.dsc
> |
> > 11 +
> >  MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/Readme.md
> > |   55 +
> >
> >
> MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/VariablePolicyFu
> > ncTestApp.inf      |   42 +
> >  MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
> > |    5 +
> >  MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf
> > |    4 +
> >
> >
> MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.i
> > nf                     |   10 +
> >
> >
> MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf
> > |    4 +
> >  OvmfPkg/OvmfPkgIa32.dsc                                                                  |    5 +
> >  OvmfPkg/OvmfPkgIa32X64.dsc                                                               |    5 +
> >  OvmfPkg/OvmfPkgX64.dsc                                                                   |    5 +
> >  OvmfPkg/OvmfXen.dsc                                                                      |    4 +
> >  SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf                                  |
> > 2 +
> >  UefiPayloadPkg/UefiPayloadPkgIa32.dsc                                                    |    4 +
> >  UefiPayloadPkg/UefiPayloadPkgIa32X64.dsc                                                 |    4 +
> >  47 files changed, 8015 insertions(+), 78 deletions(-)  create mode
> > 100644 MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.c
> >  create mode 100644
> > MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.c
> >  create mode 100644
> > MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitNull.c
> >  create mode 100644
> > MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitRuntimeD
> > x
> > e.c
> >  create mode 100644
> > MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c
> >  create mode 100644
> > MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/Variable
> > Po
> > licyUnitTest.c
> >  create mode 100644
> >
> MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/VariablePolicyFu
> > ncTestApp.c
> >  create mode 100644
> >
> MdeModulePkg/Universal/Variable/RuntimeDxe/VariableLockRequstToLock
> > .c
> >  create mode 100644
> > MdeModulePkg/Universal/Variable/RuntimeDxe/VariablePolicySmmDxe.c
> >  create mode 100644 MdeModulePkg/Include/Guid/VarCheckPolicyMmi.h
> >  create mode 100644
> > MdeModulePkg/Include/Library/VariablePolicyHelperLib.h
> >  create mode 100644 MdeModulePkg/Include/Library/VariablePolicyLib.h
> >  create mode 100644 MdeModulePkg/Include/Protocol/VariablePolicy.h
> >  create mode 100644
> > MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.inf
> >  create mode 100644
> > MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.uni
> >  create mode 100644
> > MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.i
> > nf
> >  create mode 100644
> > MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.u
> > ni
> >  create mode 100644
> > MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf
> >  create mode 100644
> > MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.uni
> >  create mode 100644
> > MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf
> >  create mode 100644
> > MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/Variable
> > Po
> > licyUnitTest.inf
> >  create mode 100644
> > MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/Readme.md
> >  create mode 100644
> >
> MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/VariablePolicyFu
> > ncTestApp.inf
> >
> > --
> > 2.26.2.windows.1.8.g01c50adf56.20200515075929
> >
> >
> >
>
>
>





[-- Attachment #2: Type: text/html, Size: 30594 bytes --]

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature
       [not found]     ` <162C456ABCC01019.19371@groups.io>
@ 2020-08-26  6:49       ` Bret Barkelew
       [not found]       ` <162EBEB1FCE1A80C.27554@groups.io>
  1 sibling, 0 replies; 48+ messages in thread
From: Bret Barkelew @ 2020-08-26  6:49 UTC (permalink / raw)
  To: devel@edk2.groups.io, dandan.bi@intel.com, bret@corthon.com
  Cc: Yao, Jiewen, Zhang, Chao B, Wang, Jian J, Wu, Hao A, liming.gao,
	Justen, Jordan L, Laszlo Ersek, Ard Biesheuvel, Andrew Fish,
	Ni, Ray


[-- Attachment #1.1: Type: text/plain, Size: 19924 bytes --]

Dandan,

I’ve addressed points 1-3 in this commit:
https://github.com/corthon/edk2/tree/var_policy_dev_submission_v7

I’ve also added a note to the new ReadMe about point #6:
https://github.com/corthon/edk2/tree/var_policy_dev_submission_v7/MdeModulePkg/Library/VariablePolicyLib#disablevariablepolicy

Will put up a v7 of patches this week.

- Bret

From: Bret Barkelew via groups.io<mailto:bret.barkelew=microsoft.com@groups.io>
Sent: Monday, August 17, 2020 10:24 PM
To: devel@edk2.groups.io<mailto:devel@edk2.groups.io>; dandan.bi@intel.com<mailto:dandan.bi@intel.com>; bret@corthon.com<mailto:bret@corthon.com>
Cc: Yao, Jiewen<mailto:jiewen.yao@intel.com>; Zhang, Chao B<mailto:chao.b.zhang@intel.com>; Wang, Jian J<mailto:jian.j.wang@intel.com>; Wu, Hao A<mailto:hao.a.wu@intel.com>; liming.gao<mailto:liming.gao@intel.com>; Justen, Jordan L<mailto:jordan.l.justen@intel.com>; Laszlo Ersek<mailto:lersek@redhat.com>; Ard Biesheuvel<mailto:ard.biesheuvel@arm.com>; Andrew Fish<mailto:afish@apple.com>; Ni, Ray<mailto:ray.ni@intel.com>
Subject: [EXTERNAL] Re: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature

Responses below…

- Bret

From: Dandan Bi via groups.io<mailto:dandan.bi=intel.com@groups.io>
Sent: Tuesday, August 11, 2020 6:52 AM
To: devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Bi, Dandan<mailto:dandan.bi@intel.com>; bret@corthon.com<mailto:bret@corthon.com>
Cc: Yao, Jiewen<mailto:jiewen.yao@intel.com>; Zhang, Chao B<mailto:chao.b.zhang@intel.com>; Wang, Jian J<mailto:jian.j.wang@intel.com>; Wu, Hao A<mailto:hao.a.wu@intel.com>; liming.gao<mailto:liming.gao@intel.com>; Justen, Jordan L<mailto:jordan.l.justen@intel.com>; Laszlo Ersek<mailto:lersek@redhat.com>; Ard Biesheuvel<mailto:ard.biesheuvel@arm.com>; Andrew Fish<mailto:afish@apple.com>; Ni, Ray<mailto:ray.ni@intel.com>
Subject: [EXTERNAL] Re: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature

Hi Bret,

Sorry for the delayed response.

Some more comments here:

1. Currently I see the LockVaribePolicy is called at ReadyToBoot by variable driver, could we update it to be called at EndOfDxe? We should prevent malicious code registering policy after EndOfDxe for security concern. And could we also add the test case to check the variable policy is locked at EndofDxe?
We could. Right now it’s at ReadyToBoot because it’s just there as a safety net and the platform could lock it earlier. Would it work to have a PCD for which EventGroup GUID the platform should lock on?

2. For patch 4, the SMM communication,  some general guidelines for SMI handler:
a)  Check whether the communication buffer is outside SMM and valid.
For this feature, please double check whether the communication buffer is checked, if all the range in communication buffer has already been checked within existing edk2 core infrastructure, please also add the comments in the code to mention that it has been checked.
I checked this, but I will recheck (since there’ve been a few revisions in the patches) and update the comments.

b) Should copy the communication buffer to SMRAM before checking the data fields to avoid TOC/TOU attac
For this feature, for example, when dump variable policy, if malicious code updates the DumpParams->TotalSize in communication buffer to smaller one to allocate the PaginationCache buffer, and then update it the correct one and dump the variable policy data into the PaginationCache buffer, it will cause buffer overflow in this case.  So please double check the code and copy the communication buffer into SMRAM to avoid such kind issue.
Will also check for this.

3. Did you do any security test for this feature?
Such as? There are both unit tests and integration tests to ensure correct functionality and that the disable and lock interfaces work as expected. I haven’t fuzzed it or anything that involved.

4. Currently, LockVariablePolicy can prevent RegisterVariablePolicy and DisableVariablePolicy. So in SMI hander, could we check the variable policy is locked or not firstly and then decide whether need to check and execution for VAR_CHECK_POLICY_COMMAND_REGISTER and VAR_CHECK_POLICY_COMMAND_DISABLE?
I’ll take a look, but my gut says this may be an unnecessary complication.

5. Since there is the logic when variable policy is disabled, it will permit deletion of auth/protected variables. Could we add some comments in code to mention that variable policy should always be enabled for security concern to avoid giving bad example?
I’m happy to think about how to document this, but I’m not immediately inclined to outright say it shouldn’t be disabled. I’d be happy to say that it shouldn’t be disabled in “normal, production configuration”, but it’s entirely reasonable to be disabled in a Manufacturing or R&R environment and we would actually prefer this be used because it would at least be consistent across platforms, rather than being something done ad hoc by each platform that needs it. Would that be sufficient?

Thanks,
Dandan
> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Dandan
> Bi
> Sent: Thursday, July 2, 2020 10:14 AM
> To: devel@edk2.groups.io; bret@corthon.com
> Cc: Yao, Jiewen <jiewen.yao@intel.com>; Zhang, Chao B
> <chao.b.zhang@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao
> A <hao.a.wu@intel.com>; Gao, Liming <liming.gao@intel.com>; Justen,
> Jordan L <jordan.l.justen@intel.com>; Laszlo Ersek <lersek@redhat.com>;
> Ard Biesheuvel <ard.biesheuvel@arm.com>; Andrew Fish
> <afish@apple.com>; Ni, Ray <ray.ni@intel.com>
> Subject: Re: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature
>
> Hi Bret,
>
> Thanks for the contribution.
>
> I have taken an overview of this patch series and have some small comments
> in the related patches, please check in sub-patch.
>
> I will review the patch series more in details and bring more comments back
> if have. Do you have a branch for these patches in GitHub? Which should be
> easy for review.
>
>
> Thanks,
> Dandan
>
> > -----Original Message-----
> > From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Bret
> > Barkelew
> > Sent: Tuesday, June 23, 2020 2:41 PM
> > To: devel@edk2.groups.io
> > Cc: Yao, Jiewen <jiewen.yao@intel.com>; Zhang, Chao B
> > <chao.b.zhang@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Wu,
> > Hao A <hao.a.wu@intel.com>; Gao, Liming <liming.gao@intel.com>;
> > Justen, Jordan L <jordan.l.justen@intel.com>; Laszlo Ersek
> > <lersek@redhat.com>; Ard Biesheuvel <ard.biesheuvel@arm.com>;
> Andrew
> > Fish <afish@apple.com>; Ni, Ray <ray.ni@intel.com>
> > Subject: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature
> >
> > REF:https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fbugzilla.tianocore.org%2Fshow_bug.cgi%3Fid%3D2522&amp;data=02%7C01%7CBret.Barkelew%40microsoft.com%7C91eed7c4a0d54e2eff6008d83dfdc4ec%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637327507431539442&amp;sdata=cLpx7VZsG%2F6r6GCXmiCS4DmmgOH4iKfX3VSAAYUOU00%3D&amp;reserved=0
> >
> > The 14 patches in this series add the VariablePolicy feature to the
> > core, deprecate Edk2VarLock (while adding a compatibility layer to
> > reduce code churn), and integrate the VariablePolicy libraries and
> > protocols into Variable Services.
> >
> > Since the integration requires multiple changes, including adding
> > libraries, a protocol, an SMI communication handler, and
> > VariableServices integration, the patches are broken up by individual
> > library additions and then a final integration. Security-sensitive
> > changes like bypassing Authenticated Variable enforcement are also
> > broken out into individual patches so that attention can be called directly to
> them.
> >
> > Platform porting instructions are described in this wiki entry:
> > https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Ftianocore%2Ftianocore.github.io%2Fwiki%2FVariablePolicy-&amp;data=02%7C01%7CBret.Barkelew%40microsoft.com%7C91eed7c4a0d54e2eff6008d83dfdc4ec%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637327507431539442&amp;sdata=%2FYNgK7yixA5Gi7E9bHw3LIUNAQpZMh9ykTUqCqv2SRY%3D&amp;reserved=0<https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Ftianocore%2Ftianocore.github.io%2Fwiki%2FVariablePolicy-&data=02%7C01%7Cbret.barkelew%40microsoft.com%7C51274073e4134461747308d843370a1b%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637333250980602108&sdata=fR%2F3c27FBmYi0SxMyBgY20asvdiur4kOtASBBZt5iTg%3D&reserved=0>
> > Protocol---Enhanced-Method-for-Managing-Variables#platform-porting
> >
> > Discussion of the feature can be found in multiple places throughout
> > the last year on the RFC channel, staging branches, and in devel.
> >
> > Most recently, this subject was discussed in this thread:
> > https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fedk2.groups.io%2Fg%2Fdevel%2Fmessage%2F53712&amp;data=02%7C01%7CBret.Barkelew%40microsoft.com%7C91eed7c4a0d54e2eff6008d83dfdc4ec%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637327507431539442&amp;sdata=i7qaO6eZT8%2BzCT0satTptMWwCNspDz%2BS05eJmGGR628%3D&amp;reserved=0<https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fedk2.groups.io%2Fg%2Fdevel%2Fmessage%2F53712&data=02%7C01%7Cbret.barkelew%40microsoft.com%7C51274073e4134461747308d843370a1b%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637333250980612106&sdata=fRMoSDlZ0tyrL3fGqowQlipsVdn31LGn1gRQXRKa3pQ%3D&reserved=0>
> > (the code branches shared in that discussion are now out of date, but
> > the whitepapers and discussion are relevant).
> >
> > Cc: Jiewen Yao <jiewen.yao@intel.com>
> > Cc: Chao Zhang <chao.b.zhang@intel.com>
> > Cc: Jian J Wang <jian.j.wang@intel.com>
> > Cc: Hao A Wu <hao.a.wu@intel.com>
> > Cc: Liming Gao <liming.gao@intel.com>
> > Cc: Jordan Justen <jordan.l.justen@intel.com>
> > Cc: Laszlo Ersek <lersek@redhat.com>
> > Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
> > Cc: Andrew Fish <afish@apple.com>
> > Cc: Ray Ni <ray.ni@intel.com>
> > Cc: Bret Barkelew <brbarkel@microsoft.com>
> > Signed-off-by: Bret Barkelew <brbarkel@microsoft.com>
> >
> > v6 changes:
> > * Fix an issue with uninitialized Status in InitVariablePolicyLib()
> > and
> > DeinitVariablePolicyLib()
> > * Fix GCC building in shell-based functional test
> > * Rebase on latest origin/master
> >
> > v5 changes:
> > * Fix the CONST mismatch in VariablePolicy.h and
> > VariablePolicySmmDxe.c
> > * Fix EFIAPI mismatches in the functional unittest
> > * Rebase on latest origin/master
> >
> > v4 changes:
> > * Remove Optional PcdAllowVariablePolicyEnforcementDisable PCD from
> > platforms
> > * Rebase on master
> > * Migrate to new MmCommunicate2 protocol
> > * Fix an oversight in the default return value for
> > InitMmCommonCommBuffer
> > * Fix in VariablePolicyLib to allow ExtraInitRuntimeDxe to consume
> > variables
> >
> > V3 changes:
> > * Address all non-unittest issues with ECC
> > * Make additional style changes
> > * Include section name in hunk headers in "ini-style" files
> > * Remove requirement for the EdkiiPiSmmCommunicationsRegionTable
> > driver
> >   (now allocates its own buffer)
> > * Change names from VARIABLE_POLICY_PROTOCOL and
> > gVariablePolicyProtocolGuid
> >   to EDKII_VARIABLE_POLICY_PROTOCOL and
> > gEdkiiVariablePolicyProtocolGuid
> > * Fix GCC warning about initializing externs
> > * Add UNI strings for new PCD
> > * Add patches for ArmVirtPkg, OvmfXen, and UefiPayloadPkg
> > * Reorder patches according to Liming's feedback about adding to
> platforms
> >   before changing variable driver
> >
> > V2 changes:
> > * Fixed implementation for RuntimeDxe
> > * Add PCD to block DisableVariablePolicy
> > * Fix the DumpVariablePolicy pagination in SMM
> >
> > Bret Barkelew (14):
> >   MdeModulePkg: Define the VariablePolicy protocol interface
> >   MdeModulePkg: Define the VariablePolicyLib
> >   MdeModulePkg: Define the VariablePolicyHelperLib
> >   MdeModulePkg: Define the VarCheckPolicyLib and SMM interface
> >   OvmfPkg: Add VariablePolicy engine to OvmfPkg platform
> >   EmulatorPkg: Add VariablePolicy engine to EmulatorPkg platform
> >   ArmVirtPkg: Add VariablePolicy engine to ArmVirtPkg platform
> >   UefiPayloadPkg: Add VariablePolicy engine to UefiPayloadPkg platform
> >   MdeModulePkg: Connect VariablePolicy business logic to
> >     VariableServices
> >   MdeModulePkg: Allow VariablePolicy state to delete protected variables
> >   SecurityPkg: Allow VariablePolicy state to delete authenticated
> >     variables
> >   MdeModulePkg: Change TCG MOR variables to use VariablePolicy
> >   MdeModulePkg: Drop VarLock from RuntimeDxe variable driver
> >   MdeModulePkg: Add a shell-based functional test for VariablePolicy
> >
> >  MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.c
> > |  320 +++
> >
> > MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.c
> > |  396 ++++
> >  MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitNull.c
> > |   46 +
> >
> >
> MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitRuntimeDx
> > e.c               |   85 +
> >  MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c
> > |  816 +++++++
> >
> >
> MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePo
> > licyUnitTest.c   | 2440 ++++++++++++++++++++
> >
> >
> MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/VariablePolicyFu
> > ncTestApp.c        | 1978 ++++++++++++++++
> >  MdeModulePkg/Universal/Variable/RuntimeDxe/TcgMorLockDxe.c
> > |   52 +-
> >  MdeModulePkg/Universal/Variable/RuntimeDxe/TcgMorLockSmm.c
> > |   60 +-
> >  MdeModulePkg/Universal/Variable/RuntimeDxe/VarCheck.c
> > |   49 +-
> >  MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c
> > |   53 +
> >
> >
> MdeModulePkg/Universal/Variable/RuntimeDxe/VariableLockRequstToLock
> > .c                    |   71 +
> >  MdeModulePkg/Universal/Variable/RuntimeDxe/VariablePolicySmmDxe.c
> > |  642 +++++
> >
> >
> MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.
> > c                       |   14 +
> >  SecurityPkg/Library/AuthVariableLib/AuthService.c                                        |
> 22
> > +-
> >  ArmVirtPkg/ArmVirt.dsc.inc                                                               |    4 +
> >  EmulatorPkg/EmulatorPkg.dsc                                                              |    3 +
> >  MdeModulePkg/Include/Guid/VarCheckPolicyMmi.h
> |
> > 54 +
> >  MdeModulePkg/Include/Library/VariablePolicyHelperLib.h
> > |  164 ++
> >  MdeModulePkg/Include/Library/VariablePolicyLib.h                                         |
> > 207 ++
> >  MdeModulePkg/Include/Protocol/VariablePolicy.h                                           |
> > 157 ++
> >  MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.inf
> > |   42 +
> >  MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.uni
> > |   12 +
> >
> > MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.i
> > nf
> > |   35 +
> >
> > MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.u
> > ni
> > |   12 +
> >  MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf
> > |   44 +
> >  MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.uni
> > |   12 +
> >
> > MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf
> > |   51 +
> >
> >
> MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePo
> > licyUnitTest.inf |   40 +
> >  MdeModulePkg/MdeModulePkg.ci.yaml                                                        |    4
> +-
> >  MdeModulePkg/MdeModulePkg.dec                                                            |   26 +-
> >  MdeModulePkg/MdeModulePkg.dsc                                                            |   15 +
> >  MdeModulePkg/MdeModulePkg.uni                                                            |    7 +
> >  MdeModulePkg/Test/MdeModulePkgHostTest.dsc
> |
> > 11 +
> >  MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/Readme.md
> > |   55 +
> >
> >
> MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/VariablePolicyFu
> > ncTestApp.inf      |   42 +
> >  MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
> > |    5 +
> >  MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf
> > |    4 +
> >
> >
> MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.i
> > nf                     |   10 +
> >
> >
> MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf
> > |    4 +
> >  OvmfPkg/OvmfPkgIa32.dsc                                                                  |    5 +
> >  OvmfPkg/OvmfPkgIa32X64.dsc                                                               |    5 +
> >  OvmfPkg/OvmfPkgX64.dsc                                                                   |    5 +
> >  OvmfPkg/OvmfXen.dsc                                                                      |    4 +
> >  SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf                                  |
> > 2 +
> >  UefiPayloadPkg/UefiPayloadPkgIa32.dsc                                                    |    4 +
> >  UefiPayloadPkg/UefiPayloadPkgIa32X64.dsc                                                 |    4 +
> >  47 files changed, 8015 insertions(+), 78 deletions(-)  create mode
> > 100644 MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.c
> >  create mode 100644
> > MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.c
> >  create mode 100644
> > MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitNull.c
> >  create mode 100644
> > MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitRuntimeD
> > x
> > e.c
> >  create mode 100644
> > MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c
> >  create mode 100644
> > MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/Variable
> > Po
> > licyUnitTest.c
> >  create mode 100644
> >
> MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/VariablePolicyFu
> > ncTestApp.c
> >  create mode 100644
> >
> MdeModulePkg/Universal/Variable/RuntimeDxe/VariableLockRequstToLock
> > .c
> >  create mode 100644
> > MdeModulePkg/Universal/Variable/RuntimeDxe/VariablePolicySmmDxe.c
> >  create mode 100644 MdeModulePkg/Include/Guid/VarCheckPolicyMmi.h
> >  create mode 100644
> > MdeModulePkg/Include/Library/VariablePolicyHelperLib.h
> >  create mode 100644 MdeModulePkg/Include/Library/VariablePolicyLib.h
> >  create mode 100644 MdeModulePkg/Include/Protocol/VariablePolicy.h
> >  create mode 100644
> > MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.inf
> >  create mode 100644
> > MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.uni
> >  create mode 100644
> > MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.i
> > nf
> >  create mode 100644
> > MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.u
> > ni
> >  create mode 100644
> > MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf
> >  create mode 100644
> > MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.uni
> >  create mode 100644
> > MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf
> >  create mode 100644
> > MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/Variable
> > Po
> > licyUnitTest.inf
> >  create mode 100644
> > MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/Readme.md
> >  create mode 100644
> >
> MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/VariablePolicyFu
> > ncTestApp.inf
> >
> > --
> > 2.26.2.windows.1.8.g01c50adf56.20200515075929
> >
> >
> >
>
>
>





[-- Attachment #1.2: Type: text/html, Size: 32951 bytes --]

[-- Attachment #2: BCB12B7394CE43AF8F019622CD7591E5.png --]
[-- Type: image/png, Size: 140 bytes --]

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature
       [not found]       ` <162EBEB1FCE1A80C.27554@groups.io>
@ 2020-09-08 22:20         ` Bret Barkelew
  2020-09-09  0:41           ` 回复: " gaoliming
       [not found]         ` <1632EF0542479E7A.4657@groups.io>
  1 sibling, 1 reply; 48+ messages in thread
From: Bret Barkelew @ 2020-09-08 22:20 UTC (permalink / raw)
  To: devel@edk2.groups.io, bret@corthon.com
  Cc: Yao, Jiewen, Zhang, Chao B, Wang, Jian J, Wu, Hao A, liming.gao,
	Justen, Jordan L, Laszlo Ersek, Ard Biesheuvel, Andrew Fish,
	Ni, Ray, liming.gao

[-- Attachment #1: Type: text/plain, Size: 646 bytes --]

Now that 2008 is labelled and everyone can take a breather… I still need reviews on the following patches (v7)…
Patch(es) 01, 02, 03,06,09,10,11,12,13,14

As such, the following email addresses may or may not be subscribed to CatFacts™ within the next 14 days if I get no responses:
Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Hao A Wu <hao.a.wu@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Andrew Fish <afish@apple.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>

May God have mercy on your inboxes.

- Bret


[-- Attachment #2: Type: text/html, Size: 2146 bytes --]

^ permalink raw reply	[flat|nested] 48+ messages in thread

* 回复: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature
  2020-09-08 22:20         ` Bret Barkelew
@ 2020-09-09  0:41           ` gaoliming
  0 siblings, 0 replies; 48+ messages in thread
From: gaoliming @ 2020-09-09  0:41 UTC (permalink / raw)
  To: devel, bret.barkelew, bret
  Cc: 'Yao, Jiewen', 'Zhang, Chao B',
	'Wang, Jian J', 'Wu, Hao A', 'liming.gao',
	'Justen, Jordan L', 'Laszlo Ersek',
	'Ard Biesheuvel', 'Andrew Fish',
	'Ni, Ray'

[-- Attachment #1: Type: text/plain, Size: 1790 bytes --]

Bret:

 I have given my reviewed-by for the changes in MdeModulePkg. Please see
https://edk2.groups.io/g/devel/message/65117

 

Thanks

Liming

发件人: bounce+27952+65144+4905953+8761045@groups.io
<bounce+27952+65144+4905953+8761045@groups.io> 代表 Bret Barkelew via
groups.io
发送时间: 2020年9月9日 6:20
收件人: devel@edk2.groups.io; bret@corthon.com
抄送: Yao, Jiewen <jiewen.yao@intel.com>; Zhang, Chao B <chao.b.zhang@intel.
com>; Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>;
liming.gao <liming.gao@intel.com>; Justen, Jordan L
<jordan.l.justen@intel.com>; Laszlo Ersek <lersek@redhat.com>; Ard
Biesheuvel <ard.biesheuvel@arm.com>; Andrew Fish <afish@apple.com>; Ni, Ray
<ray.ni@intel.com>; liming.gao <liming.gao@intel.com>
主题: Re: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature

 

Now that 2008 is labelled and everyone can take a breather… I still need
reviews on the following patches (v7)…

Patch(es) 01, 02, 03,06,09,10,11,12,13,14

 

As such, the following email addresses may or may not be subscribed to
CatFacts(tm) within the next 14 days if I get no responses:

Cc: Jian J Wang <jian.j.wang@intel.com <mailto:jian.j.wang@intel.com> >
Cc: Hao A Wu <hao.a.wu@intel.com <mailto:hao.a.wu@intel.com> >
Cc: Liming Gao <liming.gao@intel.com <mailto:liming.gao@intel.com> >

Cc: Jordan Justen <jordan.l.justen@intel.com
<mailto:jordan.l.justen@intel.com> >
Cc: Andrew Fish <afish@apple.com <mailto:afish@apple.com> >
Cc: Ray Ni <ray.ni@intel.com <mailto:ray.ni@intel.com> >

Cc: Jiewen Yao <jiewen.yao@intel.com <mailto:jiewen.yao@intel.com> >

Cc: Chao Zhang <chao.b.zhang@intel.com <mailto:chao.b.zhang@intel.com> >

 

May God have mercy on your inboxes.

 

- Bret 

 




[-- Attachment #2: Type: text/html, Size: 5917 bytes --]

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature
       [not found]         ` <1632EF0542479E7A.4657@groups.io>
@ 2020-09-11 15:18           ` Bret Barkelew
  2020-09-11 16:43             ` Laszlo Ersek
  2020-09-14  6:42             ` Wang, Jian J
  0 siblings, 2 replies; 48+ messages in thread
From: Bret Barkelew @ 2020-09-11 15:18 UTC (permalink / raw)
  To: devel@edk2.groups.io, bret@corthon.com, Wang, Jian J
  Cc: Yao, Jiewen, Zhang, Chao B, Wang, Jian J, Wu, Hao A, liming.gao,
	Justen, Jordan L, Laszlo Ersek, Ard Biesheuvel, Andrew Fish,
	Ni, Ray


[-- Attachment #1.1: Type: text/plain, Size: 1689 bytes --]

11 Days to go. I will single out an email every day…

Jian, today is your day.
How’s it going? Life good? Yeah, I know. Things are crazy here, too. Seattle is covered in smoke.
You know what would brighten things up, though? A nice “reviewed by”.

- Bret

From: Bret Barkelew via groups.io<mailto:bret.barkelew=microsoft.com@groups.io>
Sent: Tuesday, September 8, 2020 3:20 PM
To: devel@edk2.groups.io<mailto:devel@edk2.groups.io>; bret@corthon.com<mailto:bret@corthon.com>
Cc: Yao, Jiewen<mailto:jiewen.yao@intel.com>; Zhang, Chao B<mailto:chao.b.zhang@intel.com>; Wang, Jian J<mailto:jian.j.wang@intel.com>; Wu, Hao A<mailto:hao.a.wu@intel.com>; liming.gao<mailto:liming.gao@intel.com>; Justen, Jordan L<mailto:jordan.l.justen@intel.com>; Laszlo Ersek<mailto:lersek@redhat.com>; Ard Biesheuvel<mailto:ard.biesheuvel@arm.com>; Andrew Fish<mailto:afish@apple.com>; Ni, Ray<mailto:ray.ni@intel.com>; liming.gao<mailto:liming.gao@intel.com>
Subject: [EXTERNAL] Re: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature

Now that 2008 is labelled and everyone can take a breather… I still need reviews on the following patches (v7)…
Patch(es) 01, 02, 03,06,09,10,11,12,13,14

As such, the following email addresses may or may not be subscribed to CatFacts™ within the next 14 days if I get no responses:
Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Hao A Wu <hao.a.wu@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Andrew Fish <afish@apple.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>

May God have mercy on your inboxes.

- Bret




[-- Attachment #1.2: Type: text/html, Size: 4357 bytes --]

[-- Attachment #2: 4667CDD4C28F4015A1BBFC2268B9DC6B.png --]
[-- Type: image/png, Size: 140 bytes --]

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature
  2020-09-11 15:18           ` Bret Barkelew
@ 2020-09-11 16:43             ` Laszlo Ersek
  2020-09-14  6:42             ` Wang, Jian J
  1 sibling, 0 replies; 48+ messages in thread
From: Laszlo Ersek @ 2020-09-11 16:43 UTC (permalink / raw)
  To: Bret Barkelew, devel@edk2.groups.io, bret@corthon.com,
	Wang, Jian J
  Cc: Yao, Jiewen, Zhang, Chao B, Wu, Hao A, liming.gao,
	Justen, Jordan L, Ard Biesheuvel, Andrew Fish, Ni, Ray,
	Leif Lindholm (Nuvia address), Michael Kinney, Mark Doran,
	Leendert van Doorn

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=WINDOWS-1252, Size: 2420 bytes --]

On 09/11/20 17:18, Bret Barkelew wrote:
> 11 Days to go. I will single out an email every day…
> 
>  
> 
> Jian, today is your day.
> How’s it going? Life good? Yeah, I know. Things are crazy here, too.
> Seattle is covered in smoke.
> You know what would brighten things up, though? A nice “reviewed by”.

I think we should discuss the review / maintenance status of core
subsystems in edk2 on the next stewards' call (in October).

A maintainer has power to block contributions by simply doing nothing.
Because of this, maintainership is a big responsibility, and
responsiveness is critical. If there is regularly no maintainer
feedback, then the affected subsystem should be considered orphaned,
and/or new co-maintainers should be added. It is not pleasant, but it
does occur over time. In particular, with a fine-grained
"Maintainers.txt", it's possible to assign reviewership / maintenance to
feature areas / groups of subsystems.

The edk2 project has to decide whether it encourages / values
contributions, or if it prefers contributors to fork and go their own
way. We should be clear and open about this. Whoever is willing to pony
up the resources needed for maintenance gets to be maintainer. Maybe not
in the orginal project but in a fork; but that's not a huge difference
from this perspective -- over time, the old project can wither and the
fork can take over.

I'm not sure if that was the original intent with Project Mu, but when
Project Mu was launched (as I perceived it), the edk2-devel list used to
be *way* more lively than it is now. Displacing upstream edk2 looked
unthinkable -- and like a really bad idea -- back then. But now this
list, if it's not dead, smells funny.

I would support adding Microsoft engineers as reviewers to core
subsystems. We could do that gradually. And until we switch over to
github.com completely, I'd be happy to help with merging patch sets for
core subsystems that have been reviewed. (Assuming the project does not
want to hand out more push access rights, in the time remaining until we
switch over to github.com.)

Bret, I'm really sorry it's taking so long; I know first hand it's
maddening. I'm especially embarrassed, on behalf of the project, because
there have been several Microsoft contributions lately, all using the
mailing list based workflow correctly and natively -- and such efforts
*deserve* timely feedback from maintainers.

Laszlo


^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature
  2020-09-11 15:18           ` Bret Barkelew
  2020-09-11 16:43             ` Laszlo Ersek
@ 2020-09-14  6:42             ` Wang, Jian J
  2020-09-15 20:51               ` Bret Barkelew
       [not found]               ` <16351037402D5209.16285@groups.io>
  1 sibling, 2 replies; 48+ messages in thread
From: Wang, Jian J @ 2020-09-14  6:42 UTC (permalink / raw)
  To: Bret Barkelew, devel@edk2.groups.io, bret@corthon.com, Bi, Dandan
  Cc: Yao, Jiewen, Wu, Hao A, Gao, Liming, Justen, Jordan L,
	Laszlo Ersek, Ard Biesheuvel, Andrew Fish, Ni, Ray


[-- Attachment #1.1: Type: text/plain, Size: 3453 bytes --]

Hi Bret,

Sorry to hear the Seattle's situation. I've been there for several times and love the city very much. Hope everything goes back normal soon.

And sorry for slow response. This patch series have been delegated to Dandan to review by Liming. She has completed security review from Intel perspective, and given back comments to you. It seems that you forgot to include her in the CC-list. Sorry I didn't notice it and told her to do review in time. She'll give comments ASAP.

Since MdeModulePkg is a huge package, I cannot do detail review for each patch for this package. And we have already modules reviewers designated . I think, usually, they should do the detailed review first. The package maintainer will do gate-keeper works as the last step. Correct me if any misunderstanding here.

Removed Chao from cc-list (his email is not valid) and added Dandan in loop.

Regards,
Jian

From: Bret Barkelew <Bret.Barkelew@microsoft.com>
Sent: Friday, September 11, 2020 11:18 PM
To: devel@edk2.groups.io; bret@corthon.com; Wang, Jian J <jian.j.wang@intel.com>
Cc: Yao, Jiewen <jiewen.yao@intel.com>; Zhang, Chao B <chao.b.zhang@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>; Gao, Liming <liming.gao@intel.com>; Justen, Jordan L <jordan.l.justen@intel.com>; Laszlo Ersek <lersek@redhat.com>; Ard Biesheuvel <ard.biesheuvel@arm.com>; Andrew Fish <afish@apple.com>; Ni, Ray <ray.ni@intel.com>
Subject: RE: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature

11 Days to go. I will single out an email every day...

Jian, today is your day.
How's it going? Life good? Yeah, I know. Things are crazy here, too. Seattle is covered in smoke.
You know what would brighten things up, though? A nice "reviewed by".

- Bret

From: Bret Barkelew via groups.io<mailto:bret.barkelew=microsoft.com@groups.io>
Sent: Tuesday, September 8, 2020 3:20 PM
To: devel@edk2.groups.io<mailto:devel@edk2.groups.io>; bret@corthon.com<mailto:bret@corthon.com>
Cc: Yao, Jiewen<mailto:jiewen.yao@intel.com>; Zhang, Chao B<mailto:chao.b.zhang@intel.com>; Wang, Jian J<mailto:jian.j.wang@intel.com>; Wu, Hao A<mailto:hao.a.wu@intel.com>; liming.gao<mailto:liming.gao@intel.com>; Justen, Jordan L<mailto:jordan.l.justen@intel.com>; Laszlo Ersek<mailto:lersek@redhat.com>; Ard Biesheuvel<mailto:ard.biesheuvel@arm.com>; Andrew Fish<mailto:afish@apple.com>; Ni, Ray<mailto:ray.ni@intel.com>; liming.gao<mailto:liming.gao@intel.com>
Subject: [EXTERNAL] Re: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature

Now that 2008 is labelled and everyone can take a breather... I still need reviews on the following patches (v7)...
Patch(es) 01, 02, 03,06,09,10,11,12,13,14

As such, the following email addresses may or may not be subscribed to CatFacts(tm) within the next 14 days if I get no responses:
Cc: Jian J Wang <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>
Cc: Hao A Wu <hao.a.wu@intel.com<mailto:hao.a.wu@intel.com>>
Cc: Liming Gao <liming.gao@intel.com<mailto:liming.gao@intel.com>>
Cc: Jordan Justen <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>
Cc: Andrew Fish <afish@apple.com<mailto:afish@apple.com>>
Cc: Ray Ni <ray.ni@intel.com<mailto:ray.ni@intel.com>>
Cc: Jiewen Yao <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>
Cc: Chao Zhang <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>

May God have mercy on your inboxes.

- Bret




[-- Attachment #1.2: Type: text/html, Size: 7747 bytes --]

[-- Attachment #2: image002.png --]
[-- Type: image/png, Size: 160 bytes --]

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature
  2020-09-14  6:42             ` Wang, Jian J
@ 2020-09-15 20:51               ` Bret Barkelew
  2020-09-16  0:54                 ` 回复: " gaoliming
       [not found]               ` <16351037402D5209.16285@groups.io>
  1 sibling, 1 reply; 48+ messages in thread
From: Bret Barkelew @ 2020-09-15 20:51 UTC (permalink / raw)
  To: Wang, Jian J, devel@edk2.groups.io, bret@corthon.com, Bi, Dandan
  Cc: Yao, Jiewen, Wu, Hao A, liming.gao, Justen, Jordan L,
	Laszlo Ersek, Ard Biesheuvel, Andrew Fish, Ni, Ray


[-- Attachment #1.1: Type: text/plain, Size: 4684 bytes --]

Thanks for the update, Jian. Dandan has submitted RBs on another thread.

That leaves patches 06 and 11.

Next up, Jordan Justen. How’s it going, Jordan. We’ve never spoken directly (to my knowledge) and that’s a shame.
If you had to eat a single food for the rest of your life, what would it be and can I have a Reviewed-by?
Keep in mind that you probably don’t want it to be particularly strong flavors; it’s going to get disgusting eventually.
I’d probably go with some simple red beans and rice or something.

- Bret

From: Wang, Jian J<mailto:jian.j.wang@intel.com>
Sent: Sunday, September 13, 2020 11:42 PM
To: Bret Barkelew<mailto:Bret.Barkelew@microsoft.com>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; bret@corthon.com<mailto:bret@corthon.com>; Bi, Dandan<mailto:dandan.bi@intel.com>
Cc: Yao, Jiewen<mailto:jiewen.yao@intel.com>; Wu, Hao A<mailto:hao.a.wu@intel.com>; liming.gao<mailto:liming.gao@intel.com>; Justen, Jordan L<mailto:jordan.l.justen@intel.com>; Laszlo Ersek<mailto:lersek@redhat.com>; Ard Biesheuvel<mailto:ard.biesheuvel@arm.com>; Andrew Fish<mailto:afish@apple.com>; Ni, Ray<mailto:ray.ni@intel.com>
Subject: [EXTERNAL] RE: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature

Hi Bret,

Sorry to hear the Seattle’s situation. I’ve been there for several times and love the city very much. Hope everything goes back normal soon.

And sorry for slow response. This patch series have been delegated to Dandan to review by Liming. She has completed security review from Intel perspective, and given back comments to you. It seems that you forgot to include her in the CC-list. Sorry I didn’t notice it and told her to do review in time. She’ll give comments ASAP.

Since MdeModulePkg is a huge package, I cannot do detail review for each patch for this package. And we have already modules reviewers designated . I think, usually, they should do the detailed review first. The package maintainer will do gate-keeper works as the last step. Correct me if any misunderstanding here.

Removed Chao from cc-list (his email is not valid) and added Dandan in loop.

Regards,
Jian

From: Bret Barkelew <Bret.Barkelew@microsoft.com>
Sent: Friday, September 11, 2020 11:18 PM
To: devel@edk2.groups.io; bret@corthon.com; Wang, Jian J <jian.j.wang@intel.com>
Cc: Yao, Jiewen <jiewen.yao@intel.com>; Zhang, Chao B <chao.b.zhang@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>; Gao, Liming <liming.gao@intel.com>; Justen, Jordan L <jordan.l.justen@intel.com>; Laszlo Ersek <lersek@redhat.com>; Ard Biesheuvel <ard.biesheuvel@arm.com>; Andrew Fish <afish@apple.com>; Ni, Ray <ray.ni@intel.com>
Subject: RE: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature

11 Days to go. I will single out an email every day…

Jian, today is your day.
How’s it going? Life good? Yeah, I know. Things are crazy here, too. Seattle is covered in smoke.
You know what would brighten things up, though? A nice “reviewed by”.

- Bret

From: Bret Barkelew via groups.io<mailto:bret.barkelew=microsoft.com@groups.io>
Sent: Tuesday, September 8, 2020 3:20 PM
To: devel@edk2.groups.io<mailto:devel@edk2.groups.io>; bret@corthon.com<mailto:bret@corthon.com>
Cc: Yao, Jiewen<mailto:jiewen.yao@intel.com>; Zhang, Chao B<mailto:chao.b.zhang@intel.com>; Wang, Jian J<mailto:jian.j.wang@intel.com>; Wu, Hao A<mailto:hao.a.wu@intel.com>; liming.gao<mailto:liming.gao@intel.com>; Justen, Jordan L<mailto:jordan.l.justen@intel.com>; Laszlo Ersek<mailto:lersek@redhat.com>; Ard Biesheuvel<mailto:ard.biesheuvel@arm.com>; Andrew Fish<mailto:afish@apple.com>; Ni, Ray<mailto:ray.ni@intel.com>; liming.gao<mailto:liming.gao@intel.com>
Subject: [EXTERNAL] Re: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature

Now that 2008 is labelled and everyone can take a breather… I still need reviews on the following patches (v7)…
Patch(es) 01, 02, 03,06,09,10,11,12,13,14

As such, the following email addresses may or may not be subscribed to CatFacts™ within the next 14 days if I get no responses:
Cc: Jian J Wang <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>
Cc: Hao A Wu <hao.a.wu@intel.com<mailto:hao.a.wu@intel.com>>
Cc: Liming Gao <liming.gao@intel.com<mailto:liming.gao@intel.com>>
Cc: Jordan Justen <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>
Cc: Andrew Fish <afish@apple.com<mailto:afish@apple.com>>
Cc: Ray Ni <ray.ni@intel.com<mailto:ray.ni@intel.com>>
Cc: Jiewen Yao <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>
Cc: Chao Zhang <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>

May God have mercy on your inboxes.

- Bret





[-- Attachment #1.2: Type: text/html, Size: 9259 bytes --]

[-- Attachment #2: 8BB733C9B617427B9D731D2A2D510B44.png --]
[-- Type: image/png, Size: 140 bytes --]

^ permalink raw reply	[flat|nested] 48+ messages in thread

* 回复: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature
  2020-09-15 20:51               ` Bret Barkelew
@ 2020-09-16  0:54                 ` gaoliming
  2020-09-16  1:05                   ` Yao, Jiewen
  0 siblings, 1 reply; 48+ messages in thread
From: gaoliming @ 2020-09-16  0:54 UTC (permalink / raw)
  To: devel, bret.barkelew, 'Wang, Jian J', bret,
	'Bi, Dandan'
  Cc: 'Yao, Jiewen', 'Wu, Hao A', 'liming.gao',
	'Justen, Jordan L', 'Laszlo Ersek',
	'Ard Biesheuvel', 'Andrew Fish',
	'Ni, Ray'

[-- Attachment #1: Type: text/plain, Size: 6258 bytes --]

Bret:

 Patch 06 is for EmulatorPkg. Ray, Andrew are also the reviewers for this
package. 

 

Patch 11 is for SecurityPkg. Jian and Jiewen are the reviewer for this
package. 

 

Thanks

Liming

发件人: bounce+27952+65284+4905953+8761045@groups.io
<bounce+27952+65284+4905953+8761045@groups.io> 代表 Bret Barkelew via
groups.io
发送时间: 2020年9月16日 4:51
收件人: Wang, Jian J <jian.j.wang@intel.com>; devel@edk2.groups.io;
bret@corthon.com; Bi, Dandan <dandan.bi@intel.com>
抄送: Yao, Jiewen <jiewen.yao@intel.com>; Wu, Hao A <hao.a.wu@intel.com>;
liming.gao <liming.gao@intel.com>; Justen, Jordan L
<jordan.l.justen@intel.com>; Laszlo Ersek <lersek@redhat.com>; Ard
Biesheuvel <ard.biesheuvel@arm.com>; Andrew Fish <afish@apple.com>; Ni, Ray
<ray.ni@intel.com>
主题: Re: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature

 

Thanks for the update, Jian. Dandan has submitted RBs on another thread.

 

That leaves patches 06 and 11.

 

Next up, Jordan Justen. How’s it going, Jordan. We’ve never spoken
directly (to my knowledge) and that’s a shame.

If you had to eat a single food for the rest of your life, what would it be
and can I have a Reviewed-by?

Keep in mind that you probably don’t want it to be particularly strong
flavors; it’s going to get disgusting eventually.

I’d probably go with some simple red beans and rice or something.

 

- Bret 

 

From: Wang, Jian J <mailto:jian.j.wang@intel.com> 
Sent: Sunday, September 13, 2020 11:42 PM
To: Bret Barkelew <mailto:Bret.Barkelew@microsoft.com> ;
devel@edk2.groups.io <mailto:devel@edk2.groups.io> ; bret@corthon.com
<mailto:bret@corthon.com> ; Bi, Dandan <mailto:dandan.bi@intel.com> 
Cc: Yao, Jiewen <mailto:jiewen.yao@intel.com> ; Wu, Hao A
<mailto:hao.a.wu@intel.com> ; liming.gao <mailto:liming.gao@intel.com> ;
Justen, Jordan L <mailto:jordan.l.justen@intel.com> ; Laszlo Ersek
<mailto:lersek@redhat.com> ; Ard Biesheuvel <mailto:ard.biesheuvel@arm.com>
; Andrew Fish <mailto:afish@apple.com> ; Ni, Ray <mailto:ray.ni@intel.com> 
Subject: [EXTERNAL] RE: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy
feature

 

Hi Bret,

 

Sorry to hear the Seattle’s situation. I’ve been there for several times
and love the city very much. Hope everything goes back normal soon.

 

And sorry for slow response. This patch series have been delegated to Dandan
to review by Liming. She has completed security review from Intel
perspective, and given back comments to you. It seems that you forgot to
include her in the CC-list. Sorry I didn’t notice it and told her to do
review in time. She’ll give comments ASAP. 

 

Since MdeModulePkg is a huge package, I cannot do detail review for each
patch for this package. And we have already modules reviewers designated . I
think, usually, they should do the detailed review first. The package
maintainer will do gate-keeper works as the last step. Correct me if any
misunderstanding here.

 

Removed Chao from cc-list (his email is not valid) and added Dandan in loop.

 

Regards,

Jian

 

From: Bret Barkelew <Bret.Barkelew@microsoft.com
<mailto:Bret.Barkelew@microsoft.com> > 
Sent: Friday, September 11, 2020 11:18 PM
To: devel@edk2.groups.io <mailto:devel@edk2.groups.io> ; bret@corthon.com
<mailto:bret@corthon.com> ; Wang, Jian J <jian.j.wang@intel.com
<mailto:jian.j.wang@intel.com> >
Cc: Yao, Jiewen <jiewen.yao@intel.com <mailto:jiewen.yao@intel.com> >;
Zhang, Chao B <chao.b.zhang@intel.com <mailto:chao.b.zhang@intel.com> >;
Wang, Jian J <jian.j.wang@intel.com <mailto:jian.j.wang@intel.com> >; Wu,
Hao A <hao.a.wu@intel.com <mailto:hao.a.wu@intel.com> >; Gao, Liming
<liming.gao@intel.com <mailto:liming.gao@intel.com> >; Justen, Jordan L
<jordan.l.justen@intel.com <mailto:jordan.l.justen@intel.com> >; Laszlo
Ersek <lersek@redhat.com <mailto:lersek@redhat.com> >; Ard Biesheuvel
<ard.biesheuvel@arm.com <mailto:ard.biesheuvel@arm.com> >; Andrew Fish
<afish@apple.com <mailto:afish@apple.com> >; Ni, Ray <ray.ni@intel.com
<mailto:ray.ni@intel.com> >
Subject: RE: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature

 

11 Days to go. I will single out an email every day…

 

Jian, today is your day.

How’s it going? Life good? Yeah, I know. Things are crazy here, too.
Seattle is covered in smoke.

You know what would brighten things up, though? A nice “reviewed by”.

 

- Bret 

 

From: Bret Barkelew via groups.io
<mailto:bret.barkelew=microsoft.com@groups.io> 
Sent: Tuesday, September 8, 2020 3:20 PM
To: devel@edk2.groups.io <mailto:devel@edk2.groups.io> ; bret@corthon.com
<mailto:bret@corthon.com> 
Cc: Yao, Jiewen <mailto:jiewen.yao@intel.com> ; Zhang, Chao B
<mailto:chao.b.zhang@intel.com> ; Wang, Jian J
<mailto:jian.j.wang@intel.com> ; Wu, Hao A <mailto:hao.a.wu@intel.com> ;
liming.gao <mailto:liming.gao@intel.com> ; Justen, Jordan L
<mailto:jordan.l.justen@intel.com> ; Laszlo Ersek <mailto:lersek@redhat.com>
; Ard Biesheuvel <mailto:ard.biesheuvel@arm.com> ; Andrew Fish
<mailto:afish@apple.com> ; Ni, Ray <mailto:ray.ni@intel.com> ; liming.gao
<mailto:liming.gao@intel.com> 
Subject: [EXTERNAL] Re: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy
feature

 

Now that 2008 is labelled and everyone can take a breather… I still need
reviews on the following patches (v7)…

Patch(es) 01, 02, 03,06,09,10,11,12,13,14

 

As such, the following email addresses may or may not be subscribed to
CatFacts(tm) within the next 14 days if I get no responses:

Cc: Jian J Wang <jian.j.wang@intel.com <mailto:jian.j.wang@intel.com> >
Cc: Hao A Wu <hao.a.wu@intel.com <mailto:hao.a.wu@intel.com> >
Cc: Liming Gao <liming.gao@intel.com <mailto:liming.gao@intel.com> >

Cc: Jordan Justen <jordan.l.justen@intel.com
<mailto:jordan.l.justen@intel.com> >
Cc: Andrew Fish <afish@apple.com <mailto:afish@apple.com> >
Cc: Ray Ni <ray.ni@intel.com <mailto:ray.ni@intel.com> >

Cc: Jiewen Yao <jiewen.yao@intel.com <mailto:jiewen.yao@intel.com> >

Cc: Chao Zhang <chao.b.zhang@intel.com <mailto:chao.b.zhang@intel.com> >

 

May God have mercy on your inboxes.

 

- Bret 

 

 

 




[-- Attachment #2: Type: text/html, Size: 13882 bytes --]

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature
  2020-09-16  0:54                 ` 回复: " gaoliming
@ 2020-09-16  1:05                   ` Yao, Jiewen
  2020-09-16  1:37                     ` 回复: " gaoliming
  0 siblings, 1 reply; 48+ messages in thread
From: Yao, Jiewen @ 2020-09-16  1:05 UTC (permalink / raw)
  To: devel@edk2.groups.io, gaoliming@byosoft.com.cn,
	bret.barkelew@microsoft.com, Wang, Jian J, bret@corthon.com,
	Bi, Dandan
  Cc: Wu, Hao A, Gao, Liming, Justen, Jordan L, 'Laszlo Ersek',
	'Ard Biesheuvel', 'Andrew Fish', Ni, Ray

[-- Attachment #1: Type: text/plain, Size: 7350 bytes --]

Hi Bret/Liming
I checked my email and found that I have 9/14, 10/14, then 12/14, 13/14.
I don’t have 11/14 in my mailbox. That’s weird and embarrassing.

Could any of you forward 11/14 to me, so that I can review?
I apologize for the inconvenience.

Thank you
Yao Jiewen

From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of gaoliming
Sent: Wednesday, September 16, 2020 8:55 AM
To: devel@edk2.groups.io; bret.barkelew@microsoft.com; Wang, Jian J <jian.j.wang@intel.com>; bret@corthon.com; Bi, Dandan <dandan.bi@intel.com>
Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wu, Hao A <hao.a.wu@intel.com>; Gao, Liming <liming.gao@intel.com>; Justen, Jordan L <jordan.l.justen@intel.com>; 'Laszlo Ersek' <lersek@redhat.com>; 'Ard Biesheuvel' <ard.biesheuvel@arm.com>; 'Andrew Fish' <afish@apple.com>; Ni, Ray <ray.ni@intel.com>
Subject: 回复: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature

Bret:
 Patch 06 is for EmulatorPkg. Ray, Andrew are also the reviewers for this package.

Patch 11 is for SecurityPkg. Jian and Jiewen are the reviewer for this package.

Thanks
Liming
发件人: bounce+27952+65284+4905953+8761045@groups.io<mailto:bounce+27952+65284+4905953+8761045@groups.io> <bounce+27952+65284+4905953+8761045@groups.io<mailto:bounce+27952+65284+4905953+8761045@groups.io>> 代表 Bret Barkelew via groups.io
发送时间: 2020年9月16日 4:51
收件人: Wang, Jian J <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; bret@corthon.com<mailto:bret@corthon.com>; Bi, Dandan <dandan.bi@intel.com<mailto:dandan.bi@intel.com>>
抄送: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wu, Hao A <hao.a.wu@intel.com<mailto:hao.a.wu@intel.com>>; liming.gao <liming.gao@intel.com<mailto:liming.gao@intel.com>>; Justen, Jordan L <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>; Laszlo Ersek <lersek@redhat.com<mailto:lersek@redhat.com>>; Ard Biesheuvel <ard.biesheuvel@arm.com<mailto:ard.biesheuvel@arm.com>>; Andrew Fish <afish@apple.com<mailto:afish@apple.com>>; Ni, Ray <ray.ni@intel.com<mailto:ray.ni@intel.com>>
主题: Re: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature

Thanks for the update, Jian. Dandan has submitted RBs on another thread.

That leaves patches 06 and 11.

Next up, Jordan Justen. How’s it going, Jordan. We’ve never spoken directly (to my knowledge) and that’s a shame.
If you had to eat a single food for the rest of your life, what would it be and can I have a Reviewed-by?
Keep in mind that you probably don’t want it to be particularly strong flavors; it’s going to get disgusting eventually.
I’d probably go with some simple red beans and rice or something.

- Bret

From: Wang, Jian J<mailto:jian.j.wang@intel.com>
Sent: Sunday, September 13, 2020 11:42 PM
To: Bret Barkelew<mailto:Bret.Barkelew@microsoft.com>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; bret@corthon.com<mailto:bret@corthon.com>; Bi, Dandan<mailto:dandan.bi@intel.com>
Cc: Yao, Jiewen<mailto:jiewen.yao@intel.com>; Wu, Hao A<mailto:hao.a.wu@intel.com>; liming.gao<mailto:liming.gao@intel.com>; Justen, Jordan L<mailto:jordan.l.justen@intel.com>; Laszlo Ersek<mailto:lersek@redhat.com>; Ard Biesheuvel<mailto:ard.biesheuvel@arm.com>; Andrew Fish<mailto:afish@apple.com>; Ni, Ray<mailto:ray.ni@intel.com>
Subject: [EXTERNAL] RE: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature

Hi Bret,

Sorry to hear the Seattle’s situation. I’ve been there for several times and love the city very much. Hope everything goes back normal soon.

And sorry for slow response. This patch series have been delegated to Dandan to review by Liming. She has completed security review from Intel perspective, and given back comments to you. It seems that you forgot to include her in the CC-list. Sorry I didn’t notice it and told her to do review in time. She’ll give comments ASAP.

Since MdeModulePkg is a huge package, I cannot do detail review for each patch for this package. And we have already modules reviewers designated . I think, usually, they should do the detailed review first. The package maintainer will do gate-keeper works as the last step. Correct me if any misunderstanding here.

Removed Chao from cc-list (his email is not valid) and added Dandan in loop.

Regards,
Jian

From: Bret Barkelew <Bret.Barkelew@microsoft.com<mailto:Bret.Barkelew@microsoft.com>>
Sent: Friday, September 11, 2020 11:18 PM
To: devel@edk2.groups.io<mailto:devel@edk2.groups.io>; bret@corthon.com<mailto:bret@corthon.com>; Wang, Jian J <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>
Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Zhang, Chao B <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>; Wang, Jian J <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Wu, Hao A <hao.a.wu@intel.com<mailto:hao.a.wu@intel.com>>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com>>; Justen, Jordan L <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>; Laszlo Ersek <lersek@redhat.com<mailto:lersek@redhat.com>>; Ard Biesheuvel <ard.biesheuvel@arm.com<mailto:ard.biesheuvel@arm.com>>; Andrew Fish <afish@apple.com<mailto:afish@apple.com>>; Ni, Ray <ray.ni@intel.com<mailto:ray.ni@intel.com>>
Subject: RE: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature

11 Days to go. I will single out an email every day…

Jian, today is your day.
How’s it going? Life good? Yeah, I know. Things are crazy here, too. Seattle is covered in smoke.
You know what would brighten things up, though? A nice “reviewed by”.

- Bret

From: Bret Barkelew via groups.io<mailto:bret.barkelew=microsoft.com@groups.io>
Sent: Tuesday, September 8, 2020 3:20 PM
To: devel@edk2.groups.io<mailto:devel@edk2.groups.io>; bret@corthon.com<mailto:bret@corthon.com>
Cc: Yao, Jiewen<mailto:jiewen.yao@intel.com>; Zhang, Chao B<mailto:chao.b.zhang@intel.com>; Wang, Jian J<mailto:jian.j.wang@intel.com>; Wu, Hao A<mailto:hao.a.wu@intel.com>; liming.gao<mailto:liming.gao@intel.com>; Justen, Jordan L<mailto:jordan.l.justen@intel.com>; Laszlo Ersek<mailto:lersek@redhat.com>; Ard Biesheuvel<mailto:ard.biesheuvel@arm.com>; Andrew Fish<mailto:afish@apple.com>; Ni, Ray<mailto:ray.ni@intel.com>; liming.gao<mailto:liming.gao@intel.com>
Subject: [EXTERNAL] Re: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature

Now that 2008 is labelled and everyone can take a breather… I still need reviews on the following patches (v7)…
Patch(es) 01, 02, 03,06,09,10,11,12,13,14

As such, the following email addresses may or may not be subscribed to CatFacts™ within the next 14 days if I get no responses:
Cc: Jian J Wang <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>
Cc: Hao A Wu <hao.a.wu@intel.com<mailto:hao.a.wu@intel.com>>
Cc: Liming Gao <liming.gao@intel.com<mailto:liming.gao@intel.com>>
Cc: Jordan Justen <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>
Cc: Andrew Fish <afish@apple.com<mailto:afish@apple.com>>
Cc: Ray Ni <ray.ni@intel.com<mailto:ray.ni@intel.com>>
Cc: Jiewen Yao <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>
Cc: Chao Zhang <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>

May God have mercy on your inboxes.

- Bret





[-- Attachment #2: Type: text/html, Size: 15120 bytes --]

^ permalink raw reply	[flat|nested] 48+ messages in thread

* 回复: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature
  2020-09-16  1:05                   ` Yao, Jiewen
@ 2020-09-16  1:37                     ` gaoliming
  2020-09-16  1:43                       ` Yao, Jiewen
  0 siblings, 1 reply; 48+ messages in thread
From: gaoliming @ 2020-09-16  1:37 UTC (permalink / raw)
  To: devel, jiewen.yao, bret.barkelew, 'Wang, Jian J', bret,
	'Bi, Dandan'
  Cc: 'Wu, Hao A', 'Gao, Liming',
	'Justen, Jordan L', 'Laszlo Ersek',
	'Ard Biesheuvel', 'Andrew Fish',
	'Ni, Ray'

[-- Attachment #1: Type: text/plain, Size: 8971 bytes --]

Jiewen:

 I just forward the patch to your email address. Another way is to find the mail in web https://edk2.groups.io/g/devel/messages

 

Thanks

Liming

发件人: bounce+27952+65298+4905953+8761045@groups.io <bounce+27952+65298+4905953+8761045@groups.io> 代表 Yao, Jiewen
发送时间: 2020年9月16日 9:05
收件人: devel@edk2.groups.io; gaoliming@byosoft.com.cn; bret.barkelew@microsoft.com; Wang, Jian J <jian.j.wang@intel.com>; bret@corthon.com; Bi, Dandan <dandan.bi@intel.com>
抄送: Wu, Hao A <hao.a.wu@intel.com>; Gao, Liming <liming.gao@intel.com>; Justen, Jordan L <jordan.l.justen@intel.com>; 'Laszlo Ersek' <lersek@redhat.com>; 'Ard Biesheuvel' <ard.biesheuvel@arm.com>; 'Andrew Fish' <afish@apple.com>; Ni, Ray <ray.ni@intel.com>
主题: Re: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature

 

Hi Bret/Liming

I checked my email and found that I have 9/14, 10/14, then 12/14, 13/14.

I don’t have 11/14 in my mailbox. That’s weird and embarrassing.

 

Could any of you forward 11/14 to me, so that I can review?

I apologize for the inconvenience.

 

Thank you

Yao Jiewen

 

From: devel@edk2.groups.io <mailto:devel@edk2.groups.io>  <devel@edk2.groups.io <mailto:devel@edk2.groups.io> > On Behalf Of gaoliming
Sent: Wednesday, September 16, 2020 8:55 AM
To: devel@edk2.groups.io <mailto:devel@edk2.groups.io> ; bret.barkelew@microsoft.com <mailto:bret.barkelew@microsoft.com> ; Wang, Jian J <jian.j.wang@intel.com <mailto:jian.j.wang@intel.com> >; bret@corthon.com <mailto:bret@corthon.com> ; Bi, Dandan <dandan.bi@intel.com <mailto:dandan.bi@intel.com> >
Cc: Yao, Jiewen <jiewen.yao@intel.com <mailto:jiewen.yao@intel.com> >; Wu, Hao A <hao.a.wu@intel.com <mailto:hao.a.wu@intel.com> >; Gao, Liming <liming.gao@intel.com <mailto:liming.gao@intel.com> >; Justen, Jordan L <jordan.l.justen@intel.com <mailto:jordan.l.justen@intel.com> >; 'Laszlo Ersek' <lersek@redhat.com <mailto:lersek@redhat.com> >; 'Ard Biesheuvel' <ard.biesheuvel@arm.com <mailto:ard.biesheuvel@arm.com> >; 'Andrew Fish' <afish@apple.com <mailto:afish@apple.com> >; Ni, Ray <ray.ni@intel.com <mailto:ray.ni@intel.com> >
Subject: 回复: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature

 

Bret:

 Patch 06 is for EmulatorPkg. Ray, Andrew are also the reviewers for this package. 

 

Patch 11 is for SecurityPkg. Jian and Jiewen are the reviewer for this package. 

 

Thanks

Liming

发件人: bounce+27952+65284+4905953+8761045@groups.io <mailto:bounce+27952+65284+4905953+8761045@groups.io>  <bounce+27952+65284+4905953+8761045@groups.io <mailto:bounce+27952+65284+4905953+8761045@groups.io> > 代表 Bret Barkelew via groups.io
发送时间: 2020年9月16日 4:51
收件人: Wang, Jian J <jian.j.wang@intel.com <mailto:jian.j.wang@intel.com> >; devel@edk2.groups.io <mailto:devel@edk2.groups.io> ; bret@corthon.com <mailto:bret@corthon.com> ; Bi, Dandan <dandan.bi@intel.com <mailto:dandan.bi@intel.com> >
抄送: Yao, Jiewen <jiewen.yao@intel.com <mailto:jiewen.yao@intel.com> >; Wu, Hao A <hao.a.wu@intel.com <mailto:hao.a.wu@intel.com> >; liming.gao <liming.gao@intel.com <mailto:liming.gao@intel.com> >; Justen, Jordan L <jordan.l.justen@intel.com <mailto:jordan.l.justen@intel.com> >; Laszlo Ersek <lersek@redhat.com <mailto:lersek@redhat.com> >; Ard Biesheuvel <ard.biesheuvel@arm.com <mailto:ard.biesheuvel@arm.com> >; Andrew Fish <afish@apple.com <mailto:afish@apple.com> >; Ni, Ray <ray.ni@intel.com <mailto:ray.ni@intel.com> >
主题: Re: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature

 

Thanks for the update, Jian. Dandan has submitted RBs on another thread.

 

That leaves patches 06 and 11.

 

Next up, Jordan Justen. How’s it going, Jordan. We’ve never spoken directly (to my knowledge) and that’s a shame.

If you had to eat a single food for the rest of your life, what would it be and can I have a Reviewed-by?

Keep in mind that you probably don’t want it to be particularly strong flavors; it’s going to get disgusting eventually.

I’d probably go with some simple red beans and rice or something.

 

- Bret 

 

From: Wang, Jian J <mailto:jian.j.wang@intel.com> 
Sent: Sunday, September 13, 2020 11:42 PM
To: Bret Barkelew <mailto:Bret.Barkelew@microsoft.com> ; devel@edk2.groups.io <mailto:devel@edk2.groups.io> ; bret@corthon.com <mailto:bret@corthon.com> ; Bi, Dandan <mailto:dandan.bi@intel.com> 
Cc: Yao, Jiewen <mailto:jiewen.yao@intel.com> ; Wu, Hao A <mailto:hao.a.wu@intel.com> ; liming.gao <mailto:liming.gao@intel.com> ; Justen, Jordan L <mailto:jordan.l.justen@intel.com> ; Laszlo Ersek <mailto:lersek@redhat.com> ; Ard Biesheuvel <mailto:ard.biesheuvel@arm.com> ; Andrew Fish <mailto:afish@apple.com> ; Ni, Ray <mailto:ray.ni@intel.com> 
Subject: [EXTERNAL] RE: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature

 

Hi Bret,

 

Sorry to hear the Seattle’s situation. I’ve been there for several times and love the city very much. Hope everything goes back normal soon.

 

And sorry for slow response. This patch series have been delegated to Dandan to review by Liming. She has completed security review from Intel perspective, and given back comments to you. It seems that you forgot to include her in the CC-list. Sorry I didn’t notice it and told her to do review in time. She’ll give comments ASAP. 

 

Since MdeModulePkg is a huge package, I cannot do detail review for each patch for this package. And we have already modules reviewers designated . I think, usually, they should do the detailed review first. The package maintainer will do gate-keeper works as the last step. Correct me if any misunderstanding here.

 

Removed Chao from cc-list (his email is not valid) and added Dandan in loop.

 

Regards,

Jian

 

From: Bret Barkelew <Bret.Barkelew@microsoft.com <mailto:Bret.Barkelew@microsoft.com> > 
Sent: Friday, September 11, 2020 11:18 PM
To: devel@edk2.groups.io <mailto:devel@edk2.groups.io> ; bret@corthon.com <mailto:bret@corthon.com> ; Wang, Jian J <jian.j.wang@intel.com <mailto:jian.j.wang@intel.com> >
Cc: Yao, Jiewen <jiewen.yao@intel.com <mailto:jiewen.yao@intel.com> >; Zhang, Chao B <chao.b.zhang@intel.com <mailto:chao.b.zhang@intel.com> >; Wang, Jian J <jian.j.wang@intel.com <mailto:jian.j.wang@intel.com> >; Wu, Hao A <hao.a.wu@intel.com <mailto:hao.a.wu@intel.com> >; Gao, Liming <liming.gao@intel.com <mailto:liming.gao@intel.com> >; Justen, Jordan L <jordan.l.justen@intel.com <mailto:jordan.l.justen@intel.com> >; Laszlo Ersek <lersek@redhat.com <mailto:lersek@redhat.com> >; Ard Biesheuvel <ard.biesheuvel@arm.com <mailto:ard.biesheuvel@arm.com> >; Andrew Fish <afish@apple.com <mailto:afish@apple.com> >; Ni, Ray <ray.ni@intel.com <mailto:ray.ni@intel.com> >
Subject: RE: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature

 

11 Days to go. I will single out an email every day…

 

Jian, today is your day.

How’s it going? Life good? Yeah, I know. Things are crazy here, too. Seattle is covered in smoke.

You know what would brighten things up, though? A nice “reviewed by”.

 

- Bret 

 

From: Bret Barkelew via groups.io <mailto:bret.barkelew=microsoft.com@groups.io> 
Sent: Tuesday, September 8, 2020 3:20 PM
To: devel@edk2.groups.io <mailto:devel@edk2.groups.io> ; bret@corthon.com <mailto:bret@corthon.com> 
Cc: Yao, Jiewen <mailto:jiewen.yao@intel.com> ; Zhang, Chao B <mailto:chao.b.zhang@intel.com> ; Wang, Jian J <mailto:jian.j.wang@intel.com> ; Wu, Hao A <mailto:hao.a.wu@intel.com> ; liming.gao <mailto:liming.gao@intel.com> ; Justen, Jordan L <mailto:jordan.l.justen@intel.com> ; Laszlo Ersek <mailto:lersek@redhat.com> ; Ard Biesheuvel <mailto:ard.biesheuvel@arm.com> ; Andrew Fish <mailto:afish@apple.com> ; Ni, Ray <mailto:ray.ni@intel.com> ; liming.gao <mailto:liming.gao@intel.com> 
Subject: [EXTERNAL] Re: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature

 

Now that 2008 is labelled and everyone can take a breather… I still need reviews on the following patches (v7)…

Patch(es) 01, 02, 03,06,09,10,11,12,13,14

 

As such, the following email addresses may or may not be subscribed to CatFacts™ within the next 14 days if I get no responses:

Cc: Jian J Wang <jian.j.wang@intel.com <mailto:jian.j.wang@intel.com> >
Cc: Hao A Wu <hao.a.wu@intel.com <mailto:hao.a.wu@intel.com> >
Cc: Liming Gao <liming.gao@intel.com <mailto:liming.gao@intel.com> >

Cc: Jordan Justen <jordan.l.justen@intel.com <mailto:jordan.l.justen@intel.com> >
Cc: Andrew Fish <afish@apple.com <mailto:afish@apple.com> >
Cc: Ray Ni <ray.ni@intel.com <mailto:ray.ni@intel.com> >

Cc: Jiewen Yao <jiewen.yao@intel.com <mailto:jiewen.yao@intel.com> >

Cc: Chao Zhang <chao.b.zhang@intel.com <mailto:chao.b.zhang@intel.com> >

 

May God have mercy on your inboxes.

 

- Bret 

 

 

 




[-- Attachment #2: Type: text/html, Size: 19606 bytes --]

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature
  2020-09-16  1:37                     ` 回复: " gaoliming
@ 2020-09-16  1:43                       ` Yao, Jiewen
  2020-09-16  1:44                         ` Bret Barkelew
  0 siblings, 1 reply; 48+ messages in thread
From: Yao, Jiewen @ 2020-09-16  1:43 UTC (permalink / raw)
  To: gaoliming, devel@edk2.groups.io, bret.barkelew@microsoft.com,
	Wang, Jian J, bret@corthon.com, Bi, Dandan
  Cc: Wu, Hao A, Gao, Liming, Justen, Jordan L, 'Laszlo Ersek',
	'Ard Biesheuvel', 'Andrew Fish', Ni, Ray

[-- Attachment #1: Type: text/plain, Size: 9724 bytes --]

Got it. Thanks!

From: gaoliming <gaoliming@byosoft.com.cn>
Sent: Wednesday, September 16, 2020 9:37 AM
To: devel@edk2.groups.io; Yao, Jiewen <jiewen.yao@intel.com>; bret.barkelew@microsoft.com; Wang, Jian J <jian.j.wang@intel.com>; bret@corthon.com; Bi, Dandan <dandan.bi@intel.com>
Cc: Wu, Hao A <hao.a.wu@intel.com>; Gao, Liming <liming.gao@intel.com>; Justen, Jordan L <jordan.l.justen@intel.com>; 'Laszlo Ersek' <lersek@redhat.com>; 'Ard Biesheuvel' <ard.biesheuvel@arm.com>; 'Andrew Fish' <afish@apple.com>; Ni, Ray <ray.ni@intel.com>
Subject: 回复: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature

Jiewen:
 I just forward the patch to your email address. Another way is to find the mail in web https://edk2.groups.io/g/devel/messages

Thanks
Liming
发件人: bounce+27952+65298+4905953+8761045@groups.io<mailto:bounce+27952+65298+4905953+8761045@groups.io> <bounce+27952+65298+4905953+8761045@groups.io<mailto:bounce+27952+65298+4905953+8761045@groups.io>> 代表 Yao, Jiewen
发送时间: 2020年9月16日 9:05
收件人: devel@edk2.groups.io<mailto:devel@edk2.groups.io>; gaoliming@byosoft.com.cn<mailto:gaoliming@byosoft.com.cn>; bret.barkelew@microsoft.com<mailto:bret.barkelew@microsoft.com>; Wang, Jian J <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; bret@corthon.com<mailto:bret@corthon.com>; Bi, Dandan <dandan.bi@intel.com<mailto:dandan.bi@intel.com>>
抄送: Wu, Hao A <hao.a.wu@intel.com<mailto:hao.a.wu@intel.com>>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com>>; Justen, Jordan L <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>; 'Laszlo Ersek' <lersek@redhat.com<mailto:lersek@redhat.com>>; 'Ard Biesheuvel' <ard.biesheuvel@arm.com<mailto:ard.biesheuvel@arm.com>>; 'Andrew Fish' <afish@apple.com<mailto:afish@apple.com>>; Ni, Ray <ray.ni@intel.com<mailto:ray.ni@intel.com>>
主题: Re: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature

Hi Bret/Liming
I checked my email and found that I have 9/14, 10/14, then 12/14, 13/14.
I don’t have 11/14 in my mailbox. That’s weird and embarrassing.

Could any of you forward 11/14 to me, so that I can review?
I apologize for the inconvenience.

Thank you
Yao Jiewen

From: devel@edk2.groups.io<mailto:devel@edk2.groups.io> <devel@edk2.groups.io<mailto:devel@edk2.groups.io>> On Behalf Of gaoliming
Sent: Wednesday, September 16, 2020 8:55 AM
To: devel@edk2.groups.io<mailto:devel@edk2.groups.io>; bret.barkelew@microsoft.com<mailto:bret.barkelew@microsoft.com>; Wang, Jian J <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; bret@corthon.com<mailto:bret@corthon.com>; Bi, Dandan <dandan.bi@intel.com<mailto:dandan.bi@intel.com>>
Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wu, Hao A <hao.a.wu@intel.com<mailto:hao.a.wu@intel.com>>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com>>; Justen, Jordan L <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>; 'Laszlo Ersek' <lersek@redhat.com<mailto:lersek@redhat.com>>; 'Ard Biesheuvel' <ard.biesheuvel@arm.com<mailto:ard.biesheuvel@arm.com>>; 'Andrew Fish' <afish@apple.com<mailto:afish@apple.com>>; Ni, Ray <ray.ni@intel.com<mailto:ray.ni@intel.com>>
Subject: 回复: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature

Bret:
 Patch 06 is for EmulatorPkg. Ray, Andrew are also the reviewers for this package.

Patch 11 is for SecurityPkg. Jian and Jiewen are the reviewer for this package.

Thanks
Liming
发件人: bounce+27952+65284+4905953+8761045@groups.io<mailto:bounce+27952+65284+4905953+8761045@groups.io> <bounce+27952+65284+4905953+8761045@groups.io<mailto:bounce+27952+65284+4905953+8761045@groups.io>> 代表 Bret Barkelew via groups.io
发送时间: 2020年9月16日 4:51
收件人: Wang, Jian J <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; bret@corthon.com<mailto:bret@corthon.com>; Bi, Dandan <dandan.bi@intel.com<mailto:dandan.bi@intel.com>>
抄送: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wu, Hao A <hao.a.wu@intel.com<mailto:hao.a.wu@intel.com>>; liming.gao <liming.gao@intel.com<mailto:liming.gao@intel.com>>; Justen, Jordan L <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>; Laszlo Ersek <lersek@redhat.com<mailto:lersek@redhat.com>>; Ard Biesheuvel <ard.biesheuvel@arm.com<mailto:ard.biesheuvel@arm.com>>; Andrew Fish <afish@apple.com<mailto:afish@apple.com>>; Ni, Ray <ray.ni@intel.com<mailto:ray.ni@intel.com>>
主题: Re: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature

Thanks for the update, Jian. Dandan has submitted RBs on another thread.

That leaves patches 06 and 11.

Next up, Jordan Justen. How’s it going, Jordan. We’ve never spoken directly (to my knowledge) and that’s a shame.
If you had to eat a single food for the rest of your life, what would it be and can I have a Reviewed-by?
Keep in mind that you probably don’t want it to be particularly strong flavors; it’s going to get disgusting eventually.
I’d probably go with some simple red beans and rice or something.

- Bret

From: Wang, Jian J<mailto:jian.j.wang@intel.com>
Sent: Sunday, September 13, 2020 11:42 PM
To: Bret Barkelew<mailto:Bret.Barkelew@microsoft.com>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; bret@corthon.com<mailto:bret@corthon.com>; Bi, Dandan<mailto:dandan.bi@intel.com>
Cc: Yao, Jiewen<mailto:jiewen.yao@intel.com>; Wu, Hao A<mailto:hao.a.wu@intel.com>; liming.gao<mailto:liming.gao@intel.com>; Justen, Jordan L<mailto:jordan.l.justen@intel.com>; Laszlo Ersek<mailto:lersek@redhat.com>; Ard Biesheuvel<mailto:ard.biesheuvel@arm.com>; Andrew Fish<mailto:afish@apple.com>; Ni, Ray<mailto:ray.ni@intel.com>
Subject: [EXTERNAL] RE: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature

Hi Bret,

Sorry to hear the Seattle’s situation. I’ve been there for several times and love the city very much. Hope everything goes back normal soon.

And sorry for slow response. This patch series have been delegated to Dandan to review by Liming. She has completed security review from Intel perspective, and given back comments to you. It seems that you forgot to include her in the CC-list. Sorry I didn’t notice it and told her to do review in time. She’ll give comments ASAP.

Since MdeModulePkg is a huge package, I cannot do detail review for each patch for this package. And we have already modules reviewers designated . I think, usually, they should do the detailed review first. The package maintainer will do gate-keeper works as the last step. Correct me if any misunderstanding here.

Removed Chao from cc-list (his email is not valid) and added Dandan in loop.

Regards,
Jian

From: Bret Barkelew <Bret.Barkelew@microsoft.com<mailto:Bret.Barkelew@microsoft.com>>
Sent: Friday, September 11, 2020 11:18 PM
To: devel@edk2.groups.io<mailto:devel@edk2.groups.io>; bret@corthon.com<mailto:bret@corthon.com>; Wang, Jian J <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>
Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Zhang, Chao B <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>; Wang, Jian J <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Wu, Hao A <hao.a.wu@intel.com<mailto:hao.a.wu@intel.com>>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com>>; Justen, Jordan L <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>; Laszlo Ersek <lersek@redhat.com<mailto:lersek@redhat.com>>; Ard Biesheuvel <ard.biesheuvel@arm.com<mailto:ard.biesheuvel@arm.com>>; Andrew Fish <afish@apple.com<mailto:afish@apple.com>>; Ni, Ray <ray.ni@intel.com<mailto:ray.ni@intel.com>>
Subject: RE: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature

11 Days to go. I will single out an email every day…

Jian, today is your day.
How’s it going? Life good? Yeah, I know. Things are crazy here, too. Seattle is covered in smoke.
You know what would brighten things up, though? A nice “reviewed by”.

- Bret

From: Bret Barkelew via groups.io<mailto:bret.barkelew=microsoft.com@groups.io>
Sent: Tuesday, September 8, 2020 3:20 PM
To: devel@edk2.groups.io<mailto:devel@edk2.groups.io>; bret@corthon.com<mailto:bret@corthon.com>
Cc: Yao, Jiewen<mailto:jiewen.yao@intel.com>; Zhang, Chao B<mailto:chao.b.zhang@intel.com>; Wang, Jian J<mailto:jian.j.wang@intel.com>; Wu, Hao A<mailto:hao.a.wu@intel.com>; liming.gao<mailto:liming.gao@intel.com>; Justen, Jordan L<mailto:jordan.l.justen@intel.com>; Laszlo Ersek<mailto:lersek@redhat.com>; Ard Biesheuvel<mailto:ard.biesheuvel@arm.com>; Andrew Fish<mailto:afish@apple.com>; Ni, Ray<mailto:ray.ni@intel.com>; liming.gao<mailto:liming.gao@intel.com>
Subject: [EXTERNAL] Re: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature

Now that 2008 is labelled and everyone can take a breather… I still need reviews on the following patches (v7)…
Patch(es) 01, 02, 03,06,09,10,11,12,13,14

As such, the following email addresses may or may not be subscribed to CatFacts™ within the next 14 days if I get no responses:
Cc: Jian J Wang <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>
Cc: Hao A Wu <hao.a.wu@intel.com<mailto:hao.a.wu@intel.com>>
Cc: Liming Gao <liming.gao@intel.com<mailto:liming.gao@intel.com>>
Cc: Jordan Justen <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>
Cc: Andrew Fish <afish@apple.com<mailto:afish@apple.com>>
Cc: Ray Ni <ray.ni@intel.com<mailto:ray.ni@intel.com>>
Cc: Jiewen Yao <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>
Cc: Chao Zhang <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>

May God have mercy on your inboxes.

- Bret





[-- Attachment #2: Type: text/html, Size: 19790 bytes --]

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature
  2020-09-16  1:43                       ` Yao, Jiewen
@ 2020-09-16  1:44                         ` Bret Barkelew
  0 siblings, 0 replies; 48+ messages in thread
From: Bret Barkelew @ 2020-09-16  1:44 UTC (permalink / raw)
  To: Yao, Jiewen, gaoliming, devel@edk2.groups.io, Wang, Jian J,
	bret@corthon.com, Bi, Dandan
  Cc: Wu, Hao A, liming.gao, Justen, Jordan L, 'Laszlo Ersek',
	'Ard Biesheuvel', 'Andrew Fish', Ni, Ray


[-- Attachment #1.1: Type: text/plain, Size: 10934 bytes --]

Ha! I was *just* about to click the button to send the patch again. Glad you found it.
Let me know if you have any questions!

- Bret

From: Yao, Jiewen<mailto:jiewen.yao@intel.com>
Sent: Tuesday, September 15, 2020 6:44 PM
To: gaoliming<mailto:gaoliming@byosoft.com.cn>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Bret Barkelew<mailto:Bret.Barkelew@microsoft.com>; Wang, Jian J<mailto:jian.j.wang@intel.com>; bret@corthon.com<mailto:bret@corthon.com>; Bi, Dandan<mailto:dandan.bi@intel.com>
Cc: Wu, Hao A<mailto:hao.a.wu@intel.com>; liming.gao<mailto:liming.gao@intel.com>; Justen, Jordan L<mailto:jordan.l.justen@intel.com>; 'Laszlo Ersek'<mailto:lersek@redhat.com>; 'Ard Biesheuvel'<mailto:ard.biesheuvel@arm.com>; 'Andrew Fish'<mailto:afish@apple.com>; Ni, Ray<mailto:ray.ni@intel.com>
Subject: [EXTERNAL] RE: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature

Got it. Thanks!

From: gaoliming <gaoliming@byosoft.com.cn>
Sent: Wednesday, September 16, 2020 9:37 AM
To: devel@edk2.groups.io; Yao, Jiewen <jiewen.yao@intel.com>; bret.barkelew@microsoft.com; Wang, Jian J <jian.j.wang@intel.com>; bret@corthon.com; Bi, Dandan <dandan.bi@intel.com>
Cc: Wu, Hao A <hao.a.wu@intel.com>; Gao, Liming <liming.gao@intel.com>; Justen, Jordan L <jordan.l.justen@intel.com>; 'Laszlo Ersek' <lersek@redhat.com>; 'Ard Biesheuvel' <ard.biesheuvel@arm.com>; 'Andrew Fish' <afish@apple.com>; Ni, Ray <ray.ni@intel.com>
Subject: 回复: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature

Jiewen:
 I just forward the patch to your email address. Another way is to find the mail in web https://edk2.groups.io/g/devel/messages<https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fedk2.groups.io%2Fg%2Fdevel%2Fmessages&data=02%7C01%7Cbret.barkelew%40microsoft.com%7Cf0fbd40bdbe547876f4408d859e1fa7e%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637358174404880079&sdata=te9XcjnOdJl4o9KWwuFu4Aup5D410oYHzVkSTIknX1M%3D&reserved=0>

Thanks
Liming
发件人: bounce+27952+65298+4905953+8761045@groups.io<mailto:bounce+27952+65298+4905953+8761045@groups.io> <bounce+27952+65298+4905953+8761045@groups.io<mailto:bounce+27952+65298+4905953+8761045@groups.io>> 代表 Yao, Jiewen
发送时间: 2020年9月16日 9:05
收件人: devel@edk2.groups.io<mailto:devel@edk2.groups.io>; gaoliming@byosoft.com.cn<mailto:gaoliming@byosoft.com.cn>; bret.barkelew@microsoft.com<mailto:bret.barkelew@microsoft.com>; Wang, Jian J <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; bret@corthon.com<mailto:bret@corthon.com>; Bi, Dandan <dandan.bi@intel.com<mailto:dandan.bi@intel.com>>
抄送: Wu, Hao A <hao.a.wu@intel.com<mailto:hao.a.wu@intel.com>>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com>>; Justen, Jordan L <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>; 'Laszlo Ersek' <lersek@redhat.com<mailto:lersek@redhat.com>>; 'Ard Biesheuvel' <ard.biesheuvel@arm.com<mailto:ard.biesheuvel@arm.com>>; 'Andrew Fish' <afish@apple.com<mailto:afish@apple.com>>; Ni, Ray <ray.ni@intel.com<mailto:ray.ni@intel.com>>
主题: Re: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature

Hi Bret/Liming
I checked my email and found that I have 9/14, 10/14, then 12/14, 13/14.
I don’t have 11/14 in my mailbox. That’s weird and embarrassing.

Could any of you forward 11/14 to me, so that I can review?
I apologize for the inconvenience.

Thank you
Yao Jiewen

From: devel@edk2.groups.io<mailto:devel@edk2.groups.io> <devel@edk2.groups.io<mailto:devel@edk2.groups.io>> On Behalf Of gaoliming
Sent: Wednesday, September 16, 2020 8:55 AM
To: devel@edk2.groups.io<mailto:devel@edk2.groups.io>; bret.barkelew@microsoft.com<mailto:bret.barkelew@microsoft.com>; Wang, Jian J <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; bret@corthon.com<mailto:bret@corthon.com>; Bi, Dandan <dandan.bi@intel.com<mailto:dandan.bi@intel.com>>
Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wu, Hao A <hao.a.wu@intel.com<mailto:hao.a.wu@intel.com>>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com>>; Justen, Jordan L <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>; 'Laszlo Ersek' <lersek@redhat.com<mailto:lersek@redhat.com>>; 'Ard Biesheuvel' <ard.biesheuvel@arm.com<mailto:ard.biesheuvel@arm.com>>; 'Andrew Fish' <afish@apple.com<mailto:afish@apple.com>>; Ni, Ray <ray.ni@intel.com<mailto:ray.ni@intel.com>>
Subject: 回复: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature

Bret:
 Patch 06 is for EmulatorPkg. Ray, Andrew are also the reviewers for this package.

Patch 11 is for SecurityPkg. Jian and Jiewen are the reviewer for this package.

Thanks
Liming
发件人: bounce+27952+65284+4905953+8761045@groups.io<mailto:bounce+27952+65284+4905953+8761045@groups.io> <bounce+27952+65284+4905953+8761045@groups.io<mailto:bounce+27952+65284+4905953+8761045@groups.io>> 代表 Bret Barkelew via groups.io
发送时间: 2020年9月16日 4:51
收件人: Wang, Jian J <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; bret@corthon.com<mailto:bret@corthon.com>; Bi, Dandan <dandan.bi@intel.com<mailto:dandan.bi@intel.com>>
抄送: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Wu, Hao A <hao.a.wu@intel.com<mailto:hao.a.wu@intel.com>>; liming.gao <liming.gao@intel.com<mailto:liming.gao@intel.com>>; Justen, Jordan L <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>; Laszlo Ersek <lersek@redhat.com<mailto:lersek@redhat.com>>; Ard Biesheuvel <ard.biesheuvel@arm.com<mailto:ard.biesheuvel@arm.com>>; Andrew Fish <afish@apple.com<mailto:afish@apple.com>>; Ni, Ray <ray.ni@intel.com<mailto:ray.ni@intel.com>>
主题: Re: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature

Thanks for the update, Jian. Dandan has submitted RBs on another thread.

That leaves patches 06 and 11.

Next up, Jordan Justen. How’s it going, Jordan. We’ve never spoken directly (to my knowledge) and that’s a shame.
If you had to eat a single food for the rest of your life, what would it be and can I have a Reviewed-by?
Keep in mind that you probably don’t want it to be particularly strong flavors; it’s going to get disgusting eventually.
I’d probably go with some simple red beans and rice or something.

- Bret

From: Wang, Jian J<mailto:jian.j.wang@intel.com>
Sent: Sunday, September 13, 2020 11:42 PM
To: Bret Barkelew<mailto:Bret.Barkelew@microsoft.com>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; bret@corthon.com<mailto:bret@corthon.com>; Bi, Dandan<mailto:dandan.bi@intel.com>
Cc: Yao, Jiewen<mailto:jiewen.yao@intel.com>; Wu, Hao A<mailto:hao.a.wu@intel.com>; liming.gao<mailto:liming.gao@intel.com>; Justen, Jordan L<mailto:jordan.l.justen@intel.com>; Laszlo Ersek<mailto:lersek@redhat.com>; Ard Biesheuvel<mailto:ard.biesheuvel@arm.com>; Andrew Fish<mailto:afish@apple.com>; Ni, Ray<mailto:ray.ni@intel.com>
Subject: [EXTERNAL] RE: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature

Hi Bret,

Sorry to hear the Seattle’s situation. I’ve been there for several times and love the city very much. Hope everything goes back normal soon.

And sorry for slow response. This patch series have been delegated to Dandan to review by Liming. She has completed security review from Intel perspective, and given back comments to you. It seems that you forgot to include her in the CC-list. Sorry I didn’t notice it and told her to do review in time. She’ll give comments ASAP.

Since MdeModulePkg is a huge package, I cannot do detail review for each patch for this package. And we have already modules reviewers designated . I think, usually, they should do the detailed review first. The package maintainer will do gate-keeper works as the last step. Correct me if any misunderstanding here.

Removed Chao from cc-list (his email is not valid) and added Dandan in loop.

Regards,
Jian

From: Bret Barkelew <Bret.Barkelew@microsoft.com<mailto:Bret.Barkelew@microsoft.com>>
Sent: Friday, September 11, 2020 11:18 PM
To: devel@edk2.groups.io<mailto:devel@edk2.groups.io>; bret@corthon.com<mailto:bret@corthon.com>; Wang, Jian J <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>
Cc: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Zhang, Chao B <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>; Wang, Jian J <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Wu, Hao A <hao.a.wu@intel.com<mailto:hao.a.wu@intel.com>>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com>>; Justen, Jordan L <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>; Laszlo Ersek <lersek@redhat.com<mailto:lersek@redhat.com>>; Ard Biesheuvel <ard.biesheuvel@arm.com<mailto:ard.biesheuvel@arm.com>>; Andrew Fish <afish@apple.com<mailto:afish@apple.com>>; Ni, Ray <ray.ni@intel.com<mailto:ray.ni@intel.com>>
Subject: RE: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature

11 Days to go. I will single out an email every day…

Jian, today is your day.
How’s it going? Life good? Yeah, I know. Things are crazy here, too. Seattle is covered in smoke.
You know what would brighten things up, though? A nice “reviewed by”.

- Bret

From: Bret Barkelew via groups.io<mailto:bret.barkelew=microsoft.com@groups.io>
Sent: Tuesday, September 8, 2020 3:20 PM
To: devel@edk2.groups.io<mailto:devel@edk2.groups.io>; bret@corthon.com<mailto:bret@corthon.com>
Cc: Yao, Jiewen<mailto:jiewen.yao@intel.com>; Zhang, Chao B<mailto:chao.b.zhang@intel.com>; Wang, Jian J<mailto:jian.j.wang@intel.com>; Wu, Hao A<mailto:hao.a.wu@intel.com>; liming.gao<mailto:liming.gao@intel.com>; Justen, Jordan L<mailto:jordan.l.justen@intel.com>; Laszlo Ersek<mailto:lersek@redhat.com>; Ard Biesheuvel<mailto:ard.biesheuvel@arm.com>; Andrew Fish<mailto:afish@apple.com>; Ni, Ray<mailto:ray.ni@intel.com>; liming.gao<mailto:liming.gao@intel.com>
Subject: [EXTERNAL] Re: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature

Now that 2008 is labelled and everyone can take a breather… I still need reviews on the following patches (v7)…
Patch(es) 01, 02, 03,06,09,10,11,12,13,14

As such, the following email addresses may or may not be subscribed to CatFacts™ within the next 14 days if I get no responses:
Cc: Jian J Wang <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>
Cc: Hao A Wu <hao.a.wu@intel.com<mailto:hao.a.wu@intel.com>>
Cc: Liming Gao <liming.gao@intel.com<mailto:liming.gao@intel.com>>
Cc: Jordan Justen <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>
Cc: Andrew Fish <afish@apple.com<mailto:afish@apple.com>>
Cc: Ray Ni <ray.ni@intel.com<mailto:ray.ni@intel.com>>
Cc: Jiewen Yao <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>
Cc: Chao Zhang <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>

May God have mercy on your inboxes.

- Bret






[-- Attachment #1.2: Type: text/html, Size: 23344 bytes --]

[-- Attachment #2: 2FF2464EDF294F4CA1DEE70B407BA30D.png --]
[-- Type: image/png, Size: 151 bytes --]

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature
       [not found]               ` <16351037402D5209.16285@groups.io>
@ 2020-09-18  6:55                 ` Bret Barkelew
       [not found]                 ` <1635CE5BD52DF579.6413@groups.io>
  1 sibling, 0 replies; 48+ messages in thread
From: Bret Barkelew @ 2020-09-18  6:55 UTC (permalink / raw)
  To: devel@edk2.groups.io, Wang, Jian J, bret@corthon.com, Bi, Dandan
  Cc: Yao, Jiewen, Wu, Hao A, liming.gao, Justen, Jordan L,
	Laszlo Ersek, Ard Biesheuvel, Andrew Fish, Ni, Ray


[-- Attachment #1.1: Type: text/plain, Size: 5906 bytes --]

Hmmm…. no response from Jordan. Maybe he’s still trying dishes to see what he doesn’t get sick of. It’s good to be thorough.

So, I’ll turn to you, Mr. Fish – if that is your real name and not your supervillain pseudonym.
While you’ve always struck me as a gentle soul, and likely not resistant to learning more about anything, let alone our feline cohabitants, do you REALLY want to deal with a CatFacts subscription? Over a small, teensy, little code review? Reaaaaaaally?

- Bret

From: Bret Barkelew via groups.io<mailto:bret.barkelew=microsoft.com@groups.io>
Sent: Tuesday, September 15, 2020 1:51 PM
To: Wang, Jian J<mailto:jian.j.wang@intel.com>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; bret@corthon.com<mailto:bret@corthon.com>; Bi, Dandan<mailto:dandan.bi@intel.com>
Cc: Yao, Jiewen<mailto:jiewen.yao@intel.com>; Wu, Hao A<mailto:hao.a.wu@intel.com>; liming.gao<mailto:liming.gao@intel.com>; Justen, Jordan L<mailto:jordan.l.justen@intel.com>; Laszlo Ersek<mailto:lersek@redhat.com>; Ard Biesheuvel<mailto:ard.biesheuvel@arm.com>; Andrew Fish<mailto:afish@apple.com>; Ni, Ray<mailto:ray.ni@intel.com>
Subject: [EXTERNAL] Re: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature

Thanks for the update, Jian. Dandan has submitted RBs on another thread.

That leaves patches 06 and 11.

Next up, Jordan Justen. How’s it going, Jordan. We’ve never spoken directly (to my knowledge) and that’s a shame.
If you had to eat a single food for the rest of your life, what would it be and can I have a Reviewed-by?
Keep in mind that you probably don’t want it to be particularly strong flavors; it’s going to get disgusting eventually.
I’d probably go with some simple red beans and rice or something.

- Bret

From: Wang, Jian J<mailto:jian.j.wang@intel.com>
Sent: Sunday, September 13, 2020 11:42 PM
To: Bret Barkelew<mailto:Bret.Barkelew@microsoft.com>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; bret@corthon.com<mailto:bret@corthon.com>; Bi, Dandan<mailto:dandan.bi@intel.com>
Cc: Yao, Jiewen<mailto:jiewen.yao@intel.com>; Wu, Hao A<mailto:hao.a.wu@intel.com>; liming.gao<mailto:liming.gao@intel.com>; Justen, Jordan L<mailto:jordan.l.justen@intel.com>; Laszlo Ersek<mailto:lersek@redhat.com>; Ard Biesheuvel<mailto:ard.biesheuvel@arm.com>; Andrew Fish<mailto:afish@apple.com>; Ni, Ray<mailto:ray.ni@intel.com>
Subject: [EXTERNAL] RE: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature

Hi Bret,

Sorry to hear the Seattle’s situation. I’ve been there for several times and love the city very much. Hope everything goes back normal soon.

And sorry for slow response. This patch series have been delegated to Dandan to review by Liming. She has completed security review from Intel perspective, and given back comments to you. It seems that you forgot to include her in the CC-list. Sorry I didn’t notice it and told her to do review in time. She’ll give comments ASAP.

Since MdeModulePkg is a huge package, I cannot do detail review for each patch for this package. And we have already modules reviewers designated . I think, usually, they should do the detailed review first. The package maintainer will do gate-keeper works as the last step. Correct me if any misunderstanding here.

Removed Chao from cc-list (his email is not valid) and added Dandan in loop.

Regards,
Jian

From: Bret Barkelew <Bret.Barkelew@microsoft.com>
Sent: Friday, September 11, 2020 11:18 PM
To: devel@edk2.groups.io; bret@corthon.com; Wang, Jian J <jian.j.wang@intel.com>
Cc: Yao, Jiewen <jiewen.yao@intel.com>; Zhang, Chao B <chao.b.zhang@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>; Gao, Liming <liming.gao@intel.com>; Justen, Jordan L <jordan.l.justen@intel.com>; Laszlo Ersek <lersek@redhat.com>; Ard Biesheuvel <ard.biesheuvel@arm.com>; Andrew Fish <afish@apple.com>; Ni, Ray <ray.ni@intel.com>
Subject: RE: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature

11 Days to go. I will single out an email every day…

Jian, today is your day.
How’s it going? Life good? Yeah, I know. Things are crazy here, too. Seattle is covered in smoke.
You know what would brighten things up, though? A nice “reviewed by”.

- Bret

From: Bret Barkelew via groups.io<mailto:bret.barkelew=microsoft.com@groups.io>
Sent: Tuesday, September 8, 2020 3:20 PM
To: devel@edk2.groups.io<mailto:devel@edk2.groups.io>; bret@corthon.com<mailto:bret@corthon.com>
Cc: Yao, Jiewen<mailto:jiewen.yao@intel.com>; Zhang, Chao B<mailto:chao.b.zhang@intel.com>; Wang, Jian J<mailto:jian.j.wang@intel.com>; Wu, Hao A<mailto:hao.a.wu@intel.com>; liming.gao<mailto:liming.gao@intel.com>; Justen, Jordan L<mailto:jordan.l.justen@intel.com>; Laszlo Ersek<mailto:lersek@redhat.com>; Ard Biesheuvel<mailto:ard.biesheuvel@arm.com>; Andrew Fish<mailto:afish@apple.com>; Ni, Ray<mailto:ray.ni@intel.com>; liming.gao<mailto:liming.gao@intel.com>
Subject: [EXTERNAL] Re: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature

Now that 2008 is labelled and everyone can take a breather… I still need reviews on the following patches (v7)…
Patch(es) 01, 02, 03,06,09,10,11,12,13,14

As such, the following email addresses may or may not be subscribed to CatFacts™ within the next 14 days if I get no responses:
Cc: Jian J Wang <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>
Cc: Hao A Wu <hao.a.wu@intel.com<mailto:hao.a.wu@intel.com>>
Cc: Liming Gao <liming.gao@intel.com<mailto:liming.gao@intel.com>>
Cc: Jordan Justen <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>
Cc: Andrew Fish <afish@apple.com<mailto:afish@apple.com>>
Cc: Ray Ni <ray.ni@intel.com<mailto:ray.ni@intel.com>>
Cc: Jiewen Yao <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>
Cc: Chao Zhang <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>

May God have mercy on your inboxes.

- Bret






[-- Attachment #1.2: Type: text/html, Size: 11230 bytes --]

[-- Attachment #2: 08FC972F6C9246C1B4C977A015C7C6C3.png --]
[-- Type: image/png, Size: 140 bytes --]

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature
       [not found]                 ` <1635CE5BD52DF579.6413@groups.io>
@ 2020-09-22  2:50                   ` Bret Barkelew
  0 siblings, 0 replies; 48+ messages in thread
From: Bret Barkelew @ 2020-09-22  2:50 UTC (permalink / raw)
  To: devel@edk2.groups.io, Wang, Jian J, bret@corthon.com, Bi, Dandan
  Cc: Yao, Jiewen, Wu, Hao A, liming.gao, Justen, Jordan L,
	Laszlo Ersek, Ard Biesheuvel, Andrew Fish, Ni, Ray


[-- Attachment #1.1: Type: text/plain, Size: 6807 bytes --]

24 hours before Andrew Fish, Jordan Justen, and Ray Ni are enrolled in CatFacts.
You’ll learn things you never knew! (That’s the definition of learning.)

- Bret

From: Bret Barkelew via groups.io<mailto:bret.barkelew=microsoft.com@groups.io>
Sent: Thursday, September 17, 2020 11:55 PM
To: devel@edk2.groups.io<mailto:devel@edk2.groups.io>; Wang, Jian J<mailto:jian.j.wang@intel.com>; bret@corthon.com<mailto:bret@corthon.com>; Bi, Dandan<mailto:dandan.bi@intel.com>
Cc: Yao, Jiewen<mailto:jiewen.yao@intel.com>; Wu, Hao A<mailto:hao.a.wu@intel.com>; liming.gao<mailto:liming.gao@intel.com>; Justen, Jordan L<mailto:jordan.l.justen@intel.com>; Laszlo Ersek<mailto:lersek@redhat.com>; Ard Biesheuvel<mailto:ard.biesheuvel@arm.com>; Andrew Fish<mailto:afish@apple.com>; Ni, Ray<mailto:ray.ni@intel.com>
Subject: [EXTERNAL] Re: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature

Hmmm…. no response from Jordan. Maybe he’s still trying dishes to see what he doesn’t get sick of. It’s good to be thorough.

So, I’ll turn to you, Mr. Fish – if that is your real name and not your supervillain pseudonym.
While you’ve always struck me as a gentle soul, and likely not resistant to learning more about anything, let alone our feline cohabitants, do you REALLY want to deal with a CatFacts subscription? Over a small, teensy, little code review? Reaaaaaaally?

- Bret

From: Bret Barkelew via groups.io<mailto:bret.barkelew=microsoft.com@groups.io>
Sent: Tuesday, September 15, 2020 1:51 PM
To: Wang, Jian J<mailto:jian.j.wang@intel.com>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; bret@corthon.com<mailto:bret@corthon.com>; Bi, Dandan<mailto:dandan.bi@intel.com>
Cc: Yao, Jiewen<mailto:jiewen.yao@intel.com>; Wu, Hao A<mailto:hao.a.wu@intel.com>; liming.gao<mailto:liming.gao@intel.com>; Justen, Jordan L<mailto:jordan.l.justen@intel.com>; Laszlo Ersek<mailto:lersek@redhat.com>; Ard Biesheuvel<mailto:ard.biesheuvel@arm.com>; Andrew Fish<mailto:afish@apple.com>; Ni, Ray<mailto:ray.ni@intel.com>
Subject: [EXTERNAL] Re: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature

Thanks for the update, Jian. Dandan has submitted RBs on another thread.

That leaves patches 06 and 11.

Next up, Jordan Justen. How’s it going, Jordan. We’ve never spoken directly (to my knowledge) and that’s a shame.
If you had to eat a single food for the rest of your life, what would it be and can I have a Reviewed-by?
Keep in mind that you probably don’t want it to be particularly strong flavors; it’s going to get disgusting eventually.
I’d probably go with some simple red beans and rice or something.

- Bret

From: Wang, Jian J<mailto:jian.j.wang@intel.com>
Sent: Sunday, September 13, 2020 11:42 PM
To: Bret Barkelew<mailto:Bret.Barkelew@microsoft.com>; devel@edk2.groups.io<mailto:devel@edk2.groups.io>; bret@corthon.com<mailto:bret@corthon.com>; Bi, Dandan<mailto:dandan.bi@intel.com>
Cc: Yao, Jiewen<mailto:jiewen.yao@intel.com>; Wu, Hao A<mailto:hao.a.wu@intel.com>; liming.gao<mailto:liming.gao@intel.com>; Justen, Jordan L<mailto:jordan.l.justen@intel.com>; Laszlo Ersek<mailto:lersek@redhat.com>; Ard Biesheuvel<mailto:ard.biesheuvel@arm.com>; Andrew Fish<mailto:afish@apple.com>; Ni, Ray<mailto:ray.ni@intel.com>
Subject: [EXTERNAL] RE: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature

Hi Bret,

Sorry to hear the Seattle’s situation. I’ve been there for several times and love the city very much. Hope everything goes back normal soon.

And sorry for slow response. This patch series have been delegated to Dandan to review by Liming. She has completed security review from Intel perspective, and given back comments to you. It seems that you forgot to include her in the CC-list. Sorry I didn’t notice it and told her to do review in time. She’ll give comments ASAP.

Since MdeModulePkg is a huge package, I cannot do detail review for each patch for this package. And we have already modules reviewers designated . I think, usually, they should do the detailed review first. The package maintainer will do gate-keeper works as the last step. Correct me if any misunderstanding here.

Removed Chao from cc-list (his email is not valid) and added Dandan in loop.

Regards,
Jian

From: Bret Barkelew <Bret.Barkelew@microsoft.com>
Sent: Friday, September 11, 2020 11:18 PM
To: devel@edk2.groups.io; bret@corthon.com; Wang, Jian J <jian.j.wang@intel.com>
Cc: Yao, Jiewen <jiewen.yao@intel.com>; Zhang, Chao B <chao.b.zhang@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>; Gao, Liming <liming.gao@intel.com>; Justen, Jordan L <jordan.l.justen@intel.com>; Laszlo Ersek <lersek@redhat.com>; Ard Biesheuvel <ard.biesheuvel@arm.com>; Andrew Fish <afish@apple.com>; Ni, Ray <ray.ni@intel.com>
Subject: RE: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature

11 Days to go. I will single out an email every day…

Jian, today is your day.
How’s it going? Life good? Yeah, I know. Things are crazy here, too. Seattle is covered in smoke.
You know what would brighten things up, though? A nice “reviewed by”.

- Bret

From: Bret Barkelew via groups.io<mailto:bret.barkelew=microsoft.com@groups.io>
Sent: Tuesday, September 8, 2020 3:20 PM
To: devel@edk2.groups.io<mailto:devel@edk2.groups.io>; bret@corthon.com<mailto:bret@corthon.com>
Cc: Yao, Jiewen<mailto:jiewen.yao@intel.com>; Zhang, Chao B<mailto:chao.b.zhang@intel.com>; Wang, Jian J<mailto:jian.j.wang@intel.com>; Wu, Hao A<mailto:hao.a.wu@intel.com>; liming.gao<mailto:liming.gao@intel.com>; Justen, Jordan L<mailto:jordan.l.justen@intel.com>; Laszlo Ersek<mailto:lersek@redhat.com>; Ard Biesheuvel<mailto:ard.biesheuvel@arm.com>; Andrew Fish<mailto:afish@apple.com>; Ni, Ray<mailto:ray.ni@intel.com>; liming.gao<mailto:liming.gao@intel.com>
Subject: [EXTERNAL] Re: [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature

Now that 2008 is labelled and everyone can take a breather… I still need reviews on the following patches (v7)…
Patch(es) 01, 02, 03,06,09,10,11,12,13,14

As such, the following email addresses may or may not be subscribed to CatFacts™ within the next 14 days if I get no responses:
Cc: Jian J Wang <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>
Cc: Hao A Wu <hao.a.wu@intel.com<mailto:hao.a.wu@intel.com>>
Cc: Liming Gao <liming.gao@intel.com<mailto:liming.gao@intel.com>>
Cc: Jordan Justen <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>
Cc: Andrew Fish <afish@apple.com<mailto:afish@apple.com>>
Cc: Ray Ni <ray.ni@intel.com<mailto:ray.ni@intel.com>>
Cc: Jiewen Yao <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>
Cc: Chao Zhang <chao.b.zhang@intel.com<mailto:chao.b.zhang@intel.com>>

May God have mercy on your inboxes.

- Bret







[-- Attachment #1.2: Type: text/html, Size: 12794 bytes --]

[-- Attachment #2: 41D97E8D48EB4CD084E87F39D68372A6.png --]
[-- Type: image/png, Size: 140 bytes --]

^ permalink raw reply	[flat|nested] 48+ messages in thread

end of thread, other threads:[~2020-09-22  2:50 UTC | newest]

Thread overview: 48+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2020-06-23  6:40 [PATCH v6 00/14] Add the VariablePolicy feature bret
2020-06-23  6:40 ` [PATCH v6 01/14] MdeModulePkg: Define the VariablePolicy protocol interface Bret Barkelew
2020-06-23  6:40 ` [PATCH v6 02/14] MdeModulePkg: Define the VariablePolicyLib Bret Barkelew
2020-07-02  2:13   ` [edk2-devel] " Dandan Bi
2020-07-02  7:16     ` Bret Barkelew
2020-06-23  6:40 ` [PATCH v6 03/14] MdeModulePkg: Define the VariablePolicyHelperLib Bret Barkelew
2020-06-23  6:40 ` [PATCH v6 04/14] MdeModulePkg: Define the VarCheckPolicyLib and SMM interface Bret Barkelew
2020-07-02  2:13   ` [edk2-devel] " Dandan Bi
2020-07-02  6:41     ` Bret Barkelew
2020-06-23  6:40 ` [PATCH v6 05/14] OvmfPkg: Add VariablePolicy engine to OvmfPkg platform Bret Barkelew
2020-06-23  6:40 ` [PATCH v6 06/14] EmulatorPkg: Add VariablePolicy engine to EmulatorPkg platform Bret Barkelew
2020-06-23  6:40 ` [PATCH v6 07/14] ArmVirtPkg: Add VariablePolicy engine to ArmVirtPkg platform Bret Barkelew
2020-06-23  6:40 ` [PATCH v6 08/14] UefiPayloadPkg: Add VariablePolicy engine to UefiPayloadPkg platform Bret Barkelew
2020-06-23 16:45   ` Ma, Maurice
2020-06-23  6:40 ` [PATCH v6 09/14] MdeModulePkg: Connect VariablePolicy business logic to VariableServices Bret Barkelew
2020-07-02  2:13   ` [edk2-devel] " Dandan Bi
2020-07-02  6:40     ` Bret Barkelew
2020-06-23  6:41 ` [PATCH v6 10/14] MdeModulePkg: Allow VariablePolicy state to delete protected variables Bret Barkelew
2020-06-23  6:41 ` [PATCH v6 11/14] SecurityPkg: Allow VariablePolicy state to delete authenticated variables Bret Barkelew
2020-06-23  6:41 ` [PATCH v6 12/14] MdeModulePkg: Change TCG MOR variables to use VariablePolicy Bret Barkelew
2020-06-23  6:41 ` [PATCH v6 13/14] MdeModulePkg: Drop VarLock from RuntimeDxe variable driver Bret Barkelew
2020-07-02  2:13   ` [edk2-devel] " Dandan Bi
2020-07-02  6:36     ` Bret Barkelew
2020-06-23  6:41 ` [PATCH v6 14/14] MdeModulePkg: Add a shell-based functional test for VariablePolicy Bret Barkelew
2020-07-02  2:13 ` [edk2-devel] [PATCH v6 00/14] Add the VariablePolicy feature Dandan Bi
2020-07-02  6:45   ` Bret Barkelew
2020-07-02  6:47     ` Bret Barkelew
2020-07-02 11:06       ` Laszlo Ersek
2020-07-02 18:26         ` [EXTERNAL] " Bret Barkelew
2020-07-29 19:56 ` [EXTERNAL] " Bret Barkelew
2020-07-30  1:36   ` Liming Gao
2020-07-30  1:43     ` Bret Barkelew
     [not found] ` <161DCDB779DB4B3C.30988@groups.io>
2020-08-11 13:52   ` Dandan Bi
2020-08-18  5:24     ` Bret Barkelew
     [not found]     ` <162C456ABCC01019.19371@groups.io>
2020-08-26  6:49       ` Bret Barkelew
     [not found]       ` <162EBEB1FCE1A80C.27554@groups.io>
2020-09-08 22:20         ` Bret Barkelew
2020-09-09  0:41           ` 回复: " gaoliming
     [not found]         ` <1632EF0542479E7A.4657@groups.io>
2020-09-11 15:18           ` Bret Barkelew
2020-09-11 16:43             ` Laszlo Ersek
2020-09-14  6:42             ` Wang, Jian J
2020-09-15 20:51               ` Bret Barkelew
2020-09-16  0:54                 ` 回复: " gaoliming
2020-09-16  1:05                   ` Yao, Jiewen
2020-09-16  1:37                     ` 回复: " gaoliming
2020-09-16  1:43                       ` Yao, Jiewen
2020-09-16  1:44                         ` Bret Barkelew
     [not found]               ` <16351037402D5209.16285@groups.io>
2020-09-18  6:55                 ` Bret Barkelew
     [not found]                 ` <1635CE5BD52DF579.6413@groups.io>
2020-09-22  2:50                   ` Bret Barkelew

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox