Date   

[PATCH v5 00/14] Add the VariablePolicy feature

Bret Barkelew <bret@...>
 

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>

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 | 813 +++++++
MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePolicyUnitTest.c | 2436 ++++++++++++++++++++
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, 8008 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


[PATCH v5 14/14] MdeModulePkg: Add a shell-based functional test for VariablePolicy

Bret Barkelew <bret@...>
 

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

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/Test/ShellTest/VariablePolicyFuncTestApp/VariablePolicyFuncTe=
stApp.c | 1978 ++++++++++++++++++++
MdeModulePkg/MdeModulePkg.ci.yaml =
| 4 +-
MdeModulePkg/MdeModulePkg.dsc =
| 6 +
MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/Readme.md =
| 55 +
MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/VariablePolicyFuncTe=
stApp.inf | 42 +
5 files changed, 2084 insertions(+), 1 deletion(-)

diff --git a/MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/Variable=
PolicyFuncTestApp.c b/MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp=
/VariablePolicyFuncTestApp.c
new file mode 100644
index 000000000000..e41b6e7a43d5
--- /dev/null
+++ b/MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/VariablePolicyF=
uncTestApp.c
@@ -0,0 +1,1978 @@
+/** @file=0D
+UEFI Shell based application for unit testing the Variable Policy Protocol=
.=0D
+=0D
+Copyright (c) Microsoft Corporation.=0D
+SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+**/=0D
+=0D
+#include <Uefi.h>=0D
+#include <Library/UefiLib.h>=0D
+#include <Library/PrintLib.h>=0D
+#include <Library/DebugLib.h>=0D
+#include <Library/MemoryAllocationLib.h>=0D
+#include <Library/UnitTestLib.h>=0D
+#include <Library/UefiBootServicesTableLib.h>=0D
+#include <Protocol/VariablePolicy.h>=0D
+#include <Library/VariablePolicyHelperLib.h>=0D
+#include <Library/UefiRuntimeServicesTableLib.h>=0D
+#include <Library/MemoryAllocationLib.h>=0D
+=0D
+// TODO: Need to add to the UnitTestFrameworkPkg=0D
+// #include <Library/UnitTestBootLib.h>=0D
+=0D
+#define UNIT_TEST_APP_NAME "Variable Policy Unit Test Application"=
=0D
+#define UNIT_TEST_APP_VERSION "0.1"=0D
+=0D
+// TODO: Need to add to the UnitTestFrameworkPkg=0D
+UNIT_TEST_FRAMEWORK_HANDLE=0D
+GetActiveFrameworkHandle (=0D
+ VOID=0D
+ );=0D
+=0D
+EDKII_VARIABLE_POLICY_PROTOCOL *mVarPol =3D NULL;=0D
+=0D
+=0D
+EFI_GUID mTestNamespaceGuid1 =3D { 0x3b389299, 0xabaf, 0x433b, { 0xa4, 0xa=
9, 0x23, 0xc8, 0x44, 0x02, 0xfc, 0xad } };=0D
+EFI_GUID mTestNamespaceGuid2 =3D { 0x4c49a3aa, 0xbcb0, 0x544c, { 0xb5, 0xb=
a, 0x34, 0xd9, 0x55, 0x13, 0x0d, 0xbe } };=0D
+EFI_GUID mTestNamespaceGuid3 =3D { 0x5d5ab4bb, 0xcdc1, 0x655d, { 0xc6, 0xc=
b, 0x45, 0xea, 0x66, 0x24, 0x1e, 0xcf } };=0D
+=0D
+/**=0D
+ Prerequisite for most test cases.=0D
+**/=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+LocateVarPolicyPreReq (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+=0D
+ if (mVarPol =3D=3D NULL) {=0D
+ Status =3D gBS->LocateProtocol (&gEdkiiVariablePolicyProtocolGuid,=0D
+ NULL,=0D
+ (VOID **) &mVarPol);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+ UT_ASSERT_NOT_NULL (mVarPol);=0D
+ }=0D
+=0D
+ return UNIT_TEST_PASSED;=0D
+=0D
+} // LocateVarPolicyPreReq=0D
+=0D
+/**=0D
+ Getting Started tests.=0D
+**/=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+CheckVpEnabled (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ BOOLEAN State;=0D
+=0D
+ Status =3D mVarPol->IsVariablePolicyEnabled (&State);=0D
+=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+ UT_ASSERT_EQUAL (State, TRUE);=0D
+=0D
+ return UNIT_TEST_PASSED;=0D
+} // CheckVpEnabled=0D
+=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+CheckVpRevision (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ UT_ASSERT_NOT_EQUAL (mVarPol->Revision, 0);=0D
+ UT_LOG_INFO ("VP Revision: 0x%x\n", mVarPol->Revision);=0D
+=0D
+ return UNIT_TEST_PASSED;=0D
+} // CheckVpRevision=0D
+=0D
+/**=0D
+ NoLock Policy tests.=0D
+**/=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+TestMinSizeNoLock (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ UINT8 Value1;=0D
+ UINT32 Value2;=0D
+ UINT8 *Buffer;=0D
+=0D
+ Status =3D RegisterBasicVariablePolicy (mVarPol,=0D
+ &mTestNamespaceGuid1,=0D
+ L"MinSizeNoLockVar",=0D
+ 4,=0D
+ VARIABLE_POLICY_NO_MAX_SIZE,=0D
+ VARIABLE_POLICY_NO_MUST_ATTR,=0D
+ VARIABLE_POLICY_NO_CANT_ATTR,=0D
+ VARIABLE_POLICY_TYPE_NO_LOCK);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ //=0D
+ // Try to write a var that is smaller than minsize=0D
+ //=0D
+ Value1 =3D 0x12;=0D
+ Status =3D gRT->SetVariable (L"MinSizeNoLockVar",=0D
+ &mTestNamespaceGuid1,=0D
+ (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BO=
OTSERVICE_ACCESS),=0D
+ sizeof (Value1),=0D
+ &Value1);=0D
+ UT_ASSERT_TRUE ((Status =3D=3D EFI_WRITE_PROTECTED) || (Status =3D=3D EF=
I_INVALID_PARAMETER));=0D
+=0D
+ //=0D
+ // Try to write a var of size that matches minsize=0D
+ //=0D
+ Value2 =3D 0xa1b2c3d4;=0D
+ Status =3D gRT->SetVariable (L"MinSizeNoLockVar",=0D
+ &mTestNamespaceGuid1,=0D
+ (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BO=
OTSERVICE_ACCESS),=0D
+ sizeof (Value2),=0D
+ &Value2);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ //=0D
+ // Should be able to delete the var=0D
+ //=0D
+ Status =3D gRT->SetVariable (L"MinSizeNoLockVar",=0D
+ &mTestNamespaceGuid1,=0D
+ 0,=0D
+ 0,=0D
+ NULL);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ //=0D
+ // Try to write a var of size larger than minsize=0D
+ //=0D
+ Buffer =3D AllocateZeroPool (40);=0D
+ UT_ASSERT_NOT_NULL (Buffer);=0D
+ Status =3D gRT->SetVariable (L"MinSizeNoLockVar",=0D
+ &mTestNamespaceGuid1,=0D
+ (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BO=
OTSERVICE_ACCESS),=0D
+ 40,=0D
+ Buffer);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ //=0D
+ // Delete the variable=0D
+ //=0D
+ Status =3D gRT->SetVariable (L"MinSizeNoLockVar",=0D
+ &mTestNamespaceGuid1,=0D
+ 0,=0D
+ 0,=0D
+ NULL);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ FreePool (Buffer);=0D
+=0D
+ return UNIT_TEST_PASSED;=0D
+} // TestMinSizeNoLock=0D
+=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+TestMaxSizeNoLock (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ UINT8 Value1;=0D
+ UINT32 Value2;=0D
+ UINT8 *Buffer;=0D
+=0D
+ Status =3D RegisterBasicVariablePolicy (mVarPol,=0D
+ &mTestNamespaceGuid1,=0D
+ L"MaxSizeNoLockVar",=0D
+ VARIABLE_POLICY_NO_MIN_SIZE,=0D
+ 4,=0D
+ VARIABLE_POLICY_NO_MUST_ATTR,=0D
+ VARIABLE_POLICY_NO_CANT_ATTR,=0D
+ VARIABLE_POLICY_TYPE_NO_LOCK);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ //=0D
+ // Try to write a var that is smaller than maxsize=0D
+ //=0D
+ Value1 =3D 0x34;=0D
+ Status =3D gRT->SetVariable (L"MaxSizeNoLockVar",=0D
+ &mTestNamespaceGuid1,=0D
+ (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BO=
OTSERVICE_ACCESS),=0D
+ sizeof (Value1),=0D
+ &Value1);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ //=0D
+ // Should be able to delete the var=0D
+ //=0D
+ Status =3D gRT->SetVariable (L"MaxSizeNoLockVar",=0D
+ &mTestNamespaceGuid1,=0D
+ 0,=0D
+ 0,=0D
+ NULL);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ //=0D
+ // Try to write a var of size that matches maxsize=0D
+ //=0D
+ Value2 =3D 0xa1b2c3d4;=0D
+ Status =3D gRT->SetVariable (L"MaxSizeNoLockVar",=0D
+ &mTestNamespaceGuid1,=0D
+ (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BO=
OTSERVICE_ACCESS),=0D
+ sizeof (Value2),=0D
+ &Value2);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ //=0D
+ // Should be able to delete the var=0D
+ //=0D
+ Status =3D gRT->SetVariable (L"MaxSizeNoLockVar",=0D
+ &mTestNamespaceGuid1,=0D
+ 0,=0D
+ 0,=0D
+ NULL);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ //=0D
+ // Try to write a var of size larger than maxsize=0D
+ //=0D
+ Buffer =3D AllocateZeroPool (40);=0D
+ UT_ASSERT_NOT_NULL (Buffer);=0D
+ Status =3D gRT->SetVariable (L"MaxSizeNoLockVar",=0D
+ &mTestNamespaceGuid1,=0D
+ (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BO=
OTSERVICE_ACCESS),=0D
+ 40,=0D
+ Buffer);=0D
+ UT_ASSERT_TRUE ((Status =3D=3D EFI_WRITE_PROTECTED) || (Status =3D=3D EF=
I_INVALID_PARAMETER));=0D
+=0D
+ FreePool (Buffer);=0D
+=0D
+ return UNIT_TEST_PASSED;=0D
+} // TestMaxSizeNoLock=0D
+=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+TestMustHaveAttrNoLock (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ UINT8 Value;=0D
+=0D
+ Status =3D RegisterBasicVariablePolicy (mVarPol,=0D
+ &mTestNamespaceGuid1,=0D
+ L"MustHaveAttrNoLockVar",=0D
+ VARIABLE_POLICY_NO_MIN_SIZE,=0D
+ VARIABLE_POLICY_NO_MAX_SIZE,=0D
+ (EFI_VARIABLE_NON_VOLATILE | EFI_=
VARIABLE_BOOTSERVICE_ACCESS),=0D
+ VARIABLE_POLICY_NO_CANT_ATTR,=0D
+ VARIABLE_POLICY_TYPE_NO_LOCK);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ //=0D
+ // Try to write a var that doesn't have the must-have attributes=0D
+ //=0D
+ Value =3D 0x56;=0D
+ Status =3D gRT->SetVariable (L"MustHaveAttrNoLockVar",=0D
+ &mTestNamespaceGuid1,=0D
+ EFI_VARIABLE_BOOTSERVICE_ACCESS,=0D
+ sizeof (Value),=0D
+ &Value);=0D
+ UT_ASSERT_TRUE ((Status =3D=3D EFI_WRITE_PROTECTED) || (Status =3D=3D EF=
I_INVALID_PARAMETER));=0D
+=0D
+ //=0D
+ // Try to write a var that has exactly the required attributes=0D
+ //=0D
+ Status =3D gRT->SetVariable (L"MustHaveAttrNoLockVar",=0D
+ &mTestNamespaceGuid1,=0D
+ (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BO=
OTSERVICE_ACCESS),=0D
+ sizeof (Value),=0D
+ &Value);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ //=0D
+ // Should be able to delete the var=0D
+ // NOTE: some implementations of VP will require the musthave attributes=
to be passed even when deleting=0D
+ //=0D
+ Status =3D gRT->SetVariable (L"MustHaveAttrNoLockVar",=0D
+ &mTestNamespaceGuid1,=0D
+ 0,=0D
+ 0,=0D
+ NULL);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ //=0D
+ // Try to write a var that has the required attributes and one extra att=
ribute=0D
+ //=0D
+ Status =3D gRT->SetVariable (L"MustHaveAttrNoLockVar",=0D
+ &mTestNamespaceGuid1,=0D
+ (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BO=
OTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS),=0D
+ sizeof (Value),=0D
+ &Value);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ //=0D
+ // Should be able to delete the var=0D
+ // NOTE: some implementations of VP will require the musthave attributes=
to be passed even when deleting=0D
+ //=0D
+ Status =3D gRT->SetVariable (L"MustHaveAttrNoLockVar",=0D
+ &mTestNamespaceGuid1,=0D
+ 0,=0D
+ 0,=0D
+ NULL);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+ return UNIT_TEST_PASSED;=0D
+} // TestMustHaveAttrNoLock=0D
+=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+TestCantHaveAttrNoLock (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ UINT8 Value;=0D
+=0D
+ Status =3D RegisterBasicVariablePolicy (mVarPol,=0D
+ &mTestNamespaceGuid1,=0D
+ L"CantHaveAttrNoLockVar",=0D
+ VARIABLE_POLICY_NO_MIN_SIZE,=0D
+ VARIABLE_POLICY_NO_MAX_SIZE,=0D
+ VARIABLE_POLICY_NO_MUST_ATTR,=0D
+ EFI_VARIABLE_NON_VOLATILE,=0D
+ VARIABLE_POLICY_TYPE_NO_LOCK);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ //=0D
+ // Try to write a var that has a can't have attr=0D
+ //=0D
+ Value =3D 0x78;=0D
+ Status =3D gRT->SetVariable (L"CantHaveAttrNoLockVar",=0D
+ &mTestNamespaceGuid1,=0D
+ (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIAB=
LE_NON_VOLATILE),=0D
+ sizeof (Value),=0D
+ &Value);=0D
+ UT_ASSERT_TRUE ((Status =3D=3D EFI_WRITE_PROTECTED) || (Status =3D=3D EF=
I_INVALID_PARAMETER));=0D
+=0D
+ //=0D
+ // Try to write a var that satisfies the can't have requirement=0D
+ //=0D
+ Status =3D gRT->SetVariable (L"CantHaveAttrNoLockVar",=0D
+ &mTestNamespaceGuid1,=0D
+ EFI_VARIABLE_BOOTSERVICE_ACCESS,=0D
+ sizeof (Value),=0D
+ &Value);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ //=0D
+ // Should be able to delete the var=0D
+ //=0D
+ Status =3D gRT->SetVariable (L"CantHaveAttrNoLockVar",=0D
+ &mTestNamespaceGuid1,=0D
+ 0,=0D
+ 0,=0D
+ NULL);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ return UNIT_TEST_PASSED;=0D
+} // TestCantHaveAttrNoLock=0D
+=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+TestMaxSizeNamespaceNoLock (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ UINT8 Value1;=0D
+ UINT32 Value2;=0D
+ UINT8 *Buffer;=0D
+=0D
+ //=0D
+ // Register a namespace-wide policy limiting max size to 4 bytes=0D
+ //=0D
+ Status =3D RegisterBasicVariablePolicy (mVarPol,=0D
+ &mTestNamespaceGuid2,=0D
+ NULL,=0D
+ VARIABLE_POLICY_NO_MIN_SIZE,=0D
+ 4,=0D
+ VARIABLE_POLICY_NO_MUST_ATTR,=0D
+ VARIABLE_POLICY_NO_CANT_ATTR,=0D
+ VARIABLE_POLICY_TYPE_NO_LOCK);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ //=0D
+ // Try to write a var that is smaller than maxsize=0D
+ //=0D
+ Value1 =3D 0x34;=0D
+ Status =3D gRT->SetVariable (L"MaxSizeNoLockVar",=0D
+ &mTestNamespaceGuid2,=0D
+ (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BO=
OTSERVICE_ACCESS),=0D
+ sizeof (Value1),=0D
+ &Value1);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ //=0D
+ // Should be able to delete the var=0D
+ //=0D
+ Status =3D gRT->SetVariable (L"MaxSizeNoLockVar",=0D
+ &mTestNamespaceGuid2,=0D
+ 0,=0D
+ 0,=0D
+ NULL);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ //=0D
+ // Try to write a var of size that matches maxsize=0D
+ //=0D
+ Value2 =3D 0xa1b2c3d4;=0D
+ Status =3D gRT->SetVariable (L"MaxSizeNoLockVar",=0D
+ &mTestNamespaceGuid2,=0D
+ (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BO=
OTSERVICE_ACCESS),=0D
+ sizeof (Value2),=0D
+ &Value2);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ //=0D
+ // Should be able to delete the var=0D
+ //=0D
+ Status =3D gRT->SetVariable (L"MaxSizeNoLockVar",=0D
+ &mTestNamespaceGuid2,=0D
+ 0,=0D
+ 0,=0D
+ NULL);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ //=0D
+ // Try to write a var of size larger than maxsize=0D
+ //=0D
+ Buffer =3D AllocateZeroPool (40);=0D
+ UT_ASSERT_NOT_NULL (Buffer);=0D
+ Status =3D gRT->SetVariable (L"MaxSizeNoLockVar",=0D
+ &mTestNamespaceGuid2,=0D
+ (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BO=
OTSERVICE_ACCESS),=0D
+ 40,=0D
+ Buffer);=0D
+ UT_ASSERT_TRUE ((Status =3D=3D EFI_WRITE_PROTECTED) || (Status =3D=3D EF=
I_INVALID_PARAMETER));=0D
+=0D
+ FreePool (Buffer);=0D
+=0D
+ return UNIT_TEST_PASSED;=0D
+} // TestMaxSizeNamespaceNoLock=0D
+=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+TestMustHaveAttrWildcardNoLock (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ UINT8 Value;=0D
+=0D
+ Status =3D RegisterBasicVariablePolicy (mVarPol,=0D
+ &mTestNamespaceGuid1,=0D
+ L"MustHaveAttrWildcardNoLockVar###=
#",=0D
+ VARIABLE_POLICY_NO_MIN_SIZE,=0D
+ VARIABLE_POLICY_NO_MAX_SIZE,=0D
+ (EFI_VARIABLE_NON_VOLATILE | EFI_=
VARIABLE_BOOTSERVICE_ACCESS),=0D
+ VARIABLE_POLICY_NO_CANT_ATTR,=0D
+ VARIABLE_POLICY_TYPE_NO_LOCK);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ //=0D
+ // Try to write a var that doesn't have the must-have attributes=0D
+ //=0D
+ Value =3D 0x56;=0D
+ Status =3D gRT->SetVariable (L"MustHaveAttrWildcardNoLockVar1573",=0D
+ &mTestNamespaceGuid1,=0D
+ EFI_VARIABLE_BOOTSERVICE_ACCESS,=0D
+ sizeof (Value),=0D
+ &Value);=0D
+ UT_ASSERT_TRUE ((Status =3D=3D EFI_WRITE_PROTECTED) || (Status =3D=3D EF=
I_INVALID_PARAMETER));=0D
+=0D
+ //=0D
+ // Try to write a var that has exactly the required attributes=0D
+ //=0D
+ Status =3D gRT->SetVariable (L"MustHaveAttrWildcardNoLockVar1234",=0D
+ &mTestNamespaceGuid1,=0D
+ (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BO=
OTSERVICE_ACCESS),=0D
+ sizeof (Value),=0D
+ &Value);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ //=0D
+ // Should be able to delete the var=0D
+ // NOTE: some implementations of VP will require the musthave attributes=
to be passed even when deleting=0D
+ //=0D
+ Status =3D gRT->SetVariable (L"MustHaveAttrWildcardNoLockVar1234",=0D
+ &mTestNamespaceGuid1,=0D
+ 0,=0D
+ 0,=0D
+ NULL);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ //=0D
+ // Try to write a var that has the required attributes and one extra att=
ribute=0D
+ //=0D
+ Status =3D gRT->SetVariable (L"MustHaveAttrWildcardNoLockVar5612",=0D
+ &mTestNamespaceGuid1,=0D
+ (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BO=
OTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS),=0D
+ sizeof (Value),=0D
+ &Value);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ //=0D
+ // Should be able to delete the var=0D
+ // NOTE: some implementations of VP will require the musthave attributes=
to be passed even when deleting=0D
+ //=0D
+ Status =3D gRT->SetVariable (L"MustHaveAttrWildcardNoLockVar5612",=0D
+ &mTestNamespaceGuid1,=0D
+ 0,=0D
+ 0,=0D
+ NULL);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ return UNIT_TEST_PASSED;=0D
+} // TestMustHaveAttrWildcardNoLock=0D
+=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+TestPolicyprioritizationNoLock (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ UINT8 Value8;=0D
+ UINT16 Value16;=0D
+ UINT32 Value32;=0D
+ UINT64 Value64;=0D
+=0D
+ //=0D
+ // Register a policy targeting the specific var=0D
+ //=0D
+ Status =3D RegisterBasicVariablePolicy (mVarPol,=0D
+ &mTestNamespaceGuid3,=0D
+ L"PolicyPriorityTestVar123",=0D
+ 8, // min size of UINT64=0D
+ VARIABLE_POLICY_NO_MAX_SIZE,=0D
+ VARIABLE_POLICY_NO_MUST_ATTR,=0D
+ VARIABLE_POLICY_NO_CANT_ATTR,=0D
+ VARIABLE_POLICY_TYPE_NO_LOCK);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ //=0D
+ // Register a policy with wildcards in the name=0D
+ //=0D
+ Status =3D RegisterBasicVariablePolicy (mVarPol,=0D
+ &mTestNamespaceGuid3,=0D
+ L"PolicyPriorityTestVar###",=0D
+ 4, // min size of UINT32=0D
+ VARIABLE_POLICY_NO_MAX_SIZE,=0D
+ VARIABLE_POLICY_NO_MUST_ATTR,=0D
+ VARIABLE_POLICY_NO_CANT_ATTR,=0D
+ VARIABLE_POLICY_TYPE_NO_LOCK);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ //=0D
+ // Register a policy with wildcards in the name=0D
+ //=0D
+ Status =3D RegisterBasicVariablePolicy (mVarPol,=0D
+ &mTestNamespaceGuid3,=0D
+ NULL,=0D
+ 2, // min size of UINT16=0D
+ VARIABLE_POLICY_NO_MAX_SIZE,=0D
+ VARIABLE_POLICY_NO_MUST_ATTR,=0D
+ VARIABLE_POLICY_NO_CANT_ATTR,=0D
+ VARIABLE_POLICY_TYPE_NO_LOCK);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ //=0D
+ // The idea is that the most specific policy is applied:=0D
+ // For varname "TestVar", the namespace-wide one should apply: UINT16 =
minimum=0D
+ // For varname "PolicyPriorityTestVar567" the wildcard policy should a=
pply: UINT32 minimum=0D
+ // For varname "PolicyPriorityTestVar123" the var-specific policy shou=
ld apply: UINT64 minimum=0D
+ //=0D
+=0D
+ //=0D
+ // Let's confirm the namespace-wide policy enforcement=0D
+ //=0D
+ Value8 =3D 0x78;=0D
+ Status =3D gRT->SetVariable (L"TestVar",=0D
+ &mTestNamespaceGuid3,=0D
+ (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIAB=
LE_NON_VOLATILE),=0D
+ sizeof (Value8),=0D
+ &Value8);=0D
+ UT_ASSERT_TRUE ((Status =3D=3D EFI_WRITE_PROTECTED) || (Status =3D=3D EF=
I_INVALID_PARAMETER));=0D
+=0D
+ Value16 =3D 0x6543;=0D
+ Status =3D gRT->SetVariable (L"TestVar",=0D
+ &mTestNamespaceGuid3,=0D
+ (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIAB=
LE_NON_VOLATILE),=0D
+ sizeof (Value16),=0D
+ &Value16);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ //=0D
+ // Let's confirm the wildcard policy enforcement=0D
+ //=0D
+ Value16 =3D 0xabba;=0D
+ Status =3D gRT->SetVariable (L"PolicyPriorityTestVar567",=0D
+ &mTestNamespaceGuid3,=0D
+ (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIAB=
LE_NON_VOLATILE),=0D
+ sizeof (Value16),=0D
+ &Value16);=0D
+ UT_ASSERT_TRUE ((Status =3D=3D EFI_WRITE_PROTECTED) || (Status =3D=3D EF=
I_INVALID_PARAMETER));=0D
+=0D
+ Value32 =3D 0xfedcba98;=0D
+ Status =3D gRT->SetVariable (L"PolicyPriorityTestVar567",=0D
+ &mTestNamespaceGuid3,=0D
+ (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIAB=
LE_NON_VOLATILE),=0D
+ sizeof (Value32),=0D
+ &Value32);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ //=0D
+ // Let's confirm the var-specific policy enforcement=0D
+ //=0D
+ Value32 =3D 0x8d3f627c;=0D
+ Status =3D gRT->SetVariable (L"PolicyPriorityTestVar123",=0D
+ &mTestNamespaceGuid3,=0D
+ (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIAB=
LE_NON_VOLATILE),=0D
+ sizeof (Value32),=0D
+ &Value32);=0D
+ UT_ASSERT_TRUE ((Status =3D=3D EFI_WRITE_PROTECTED) || (Status =3D=3D EF=
I_INVALID_PARAMETER));=0D
+=0D
+ Value64 =3D 0xbebecdcdafaf6767;=0D
+ Status =3D gRT->SetVariable (L"PolicyPriorityTestVar123",=0D
+ &mTestNamespaceGuid3,=0D
+ (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIAB=
LE_NON_VOLATILE),=0D
+ sizeof (Value64),=0D
+ &Value64);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ return UNIT_TEST_PASSED;=0D
+} // TestPolicyprioritizationNoLock=0D
+=0D
+/**=0D
+ LockNow Policy tests.=0D
+**/=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+TestExistingVarLockNow (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ UINT8 Value;=0D
+=0D
+ //=0D
+ // Write a var that we'll protect next=0D
+ //=0D
+ Value =3D 0x78;=0D
+ Status =3D gRT->SetVariable (L"ExistingLockNowVar",=0D
+ &mTestNamespaceGuid1,=0D
+ (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIAB=
LE_NON_VOLATILE),=0D
+ sizeof (Value),=0D
+ &Value);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ //=0D
+ // Register a LockNow policy targeting the var=0D
+ //=0D
+ Status =3D RegisterBasicVariablePolicy (mVarPol,=0D
+ &mTestNamespaceGuid1,=0D
+ L"ExistingLockNowVar",=0D
+ VARIABLE_POLICY_NO_MIN_SIZE,=0D
+ VARIABLE_POLICY_NO_MAX_SIZE,=0D
+ VARIABLE_POLICY_NO_MUST_ATTR,=0D
+ VARIABLE_POLICY_NO_CANT_ATTR,=0D
+ VARIABLE_POLICY_TYPE_LOCK_NOW);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ //=0D
+ // Attempt to modify the locked var=0D
+ //=0D
+ Value =3D 0xA5;=0D
+ Status =3D gRT->SetVariable (L"ExistingLockNowVar",=0D
+ &mTestNamespaceGuid1,=0D
+ (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIAB=
LE_NON_VOLATILE),=0D
+ sizeof (Value),=0D
+ &Value);=0D
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_WRITE_PROTECTED);=0D
+=0D
+ //=0D
+ // Attempt to delete the locked var=0D
+ //=0D
+ Status =3D gRT->SetVariable (L"ExistingLockNowVar",=0D
+ &mTestNamespaceGuid1,=0D
+ 0,=0D
+ 0,=0D
+ NULL);=0D
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_WRITE_PROTECTED);=0D
+=0D
+ //=0D
+ // This variable is deleted in final cleanup.=0D
+ //=0D
+=0D
+ return UNIT_TEST_PASSED;=0D
+} // TestExistingVarLockNow=0D
+=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+TestNonexistentVarLockNow (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ UINT8 Value;=0D
+ UINTN Size;=0D
+=0D
+ //=0D
+ // Make sure the variable we're about to create the policy for doesn't e=
xist=0D
+ //=0D
+ Size =3D 0;=0D
+ Status =3D gRT->GetVariable (L"NonexistentLockNowVar",=0D
+ &mTestNamespaceGuid1,=0D
+ NULL,=0D
+ &Size,=0D
+ NULL);=0D
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_NOT_FOUND);=0D
+=0D
+ //=0D
+ // Register a LockNow policy targeting the var=0D
+ //=0D
+ Status =3D RegisterBasicVariablePolicy (mVarPol,=0D
+ &mTestNamespaceGuid1,=0D
+ L"NonexistentLockNowVar",=0D
+ VARIABLE_POLICY_NO_MIN_SIZE,=0D
+ VARIABLE_POLICY_NO_MAX_SIZE,=0D
+ VARIABLE_POLICY_NO_MUST_ATTR,=0D
+ VARIABLE_POLICY_NO_CANT_ATTR,=0D
+ VARIABLE_POLICY_TYPE_LOCK_NOW);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ //=0D
+ // Attempt to create the locked var=0D
+ //=0D
+ Value =3D 0xA5;=0D
+ Status =3D gRT->SetVariable (L"NonexistentLockNowVar",=0D
+ &mTestNamespaceGuid1,=0D
+ (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIAB=
LE_NON_VOLATILE),=0D
+ sizeof (Value),=0D
+ &Value);=0D
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_WRITE_PROTECTED);=0D
+=0D
+ return UNIT_TEST_PASSED;=0D
+} // TestNonexistentVarLockNow=0D
+=0D
+/**=0D
+ LockOnCreate Policy tests.=0D
+**/=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+TestExistingVarLockOnCreate (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ UINT8 Value;=0D
+=0D
+ //=0D
+ // Write a var that we'll protect later=0D
+ //=0D
+ Value =3D 0x78;=0D
+ Status =3D gRT->SetVariable (L"ExistingLockOnCreateVar",=0D
+ &mTestNamespaceGuid1,=0D
+ (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIAB=
LE_NON_VOLATILE),=0D
+ sizeof (Value),=0D
+ &Value);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ //=0D
+ // Register a LockNow policy targeting the var=0D
+ //=0D
+ Status =3D RegisterBasicVariablePolicy (mVarPol,=0D
+ &mTestNamespaceGuid1,=0D
+ L"ExistingLockOnCreateVar",=0D
+ VARIABLE_POLICY_NO_MIN_SIZE,=0D
+ VARIABLE_POLICY_NO_MAX_SIZE,=0D
+ VARIABLE_POLICY_NO_MUST_ATTR,=0D
+ VARIABLE_POLICY_NO_CANT_ATTR,=0D
+ VARIABLE_POLICY_TYPE_LOCK_ON_CREAT=
E);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ //=0D
+ // Attempt to modify the locked var=0D
+ //=0D
+ Value =3D 0xA5;=0D
+ Status =3D gRT->SetVariable (L"ExistingLockOnCreateVar",=0D
+ &mTestNamespaceGuid1,=0D
+ (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIAB=
LE_NON_VOLATILE),=0D
+ sizeof (Value),=0D
+ &Value);=0D
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_WRITE_PROTECTED);=0D
+=0D
+ //=0D
+ // Attempt to delete the locked var=0D
+ //=0D
+ Status =3D gRT->SetVariable (L"ExistingLockOnCreateVar",=0D
+ &mTestNamespaceGuid1,=0D
+ 0,=0D
+ 0,=0D
+ NULL);=0D
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_WRITE_PROTECTED);=0D
+=0D
+ //=0D
+ // This variable is deleted in final cleanup.=0D
+ //=0D
+=0D
+ return UNIT_TEST_PASSED;=0D
+} // TestExistingVarLockOnCreate=0D
+=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+TestNonexistentVarLockOnCreate (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ UINT8 Value1;=0D
+ UINT32 Value2;=0D
+ UINTN Size;=0D
+=0D
+ //=0D
+ // Make sure the variable we're about to create the policy for doesn't e=
xist=0D
+ //=0D
+ Size =3D 0;=0D
+ Status =3D gRT->GetVariable (L"NonexistentLockOnCreateVar",=0D
+ &mTestNamespaceGuid1,=0D
+ NULL,=0D
+ &Size,=0D
+ NULL);=0D
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_NOT_FOUND);=0D
+=0D
+ //=0D
+ // Register a LockOnCreate policy targeting the var=0D
+ //=0D
+ Status =3D RegisterBasicVariablePolicy (mVarPol,=0D
+ &mTestNamespaceGuid1,=0D
+ L"NonexistentLockOnCreateVar",=0D
+ 2, // min size of 2 bytes, UINT16+=
=0D
+ VARIABLE_POLICY_NO_MAX_SIZE,=0D
+ EFI_VARIABLE_RUNTIME_ACCESS, // mu=
st have RT attr=0D
+ VARIABLE_POLICY_NO_CANT_ATTR,=0D
+ VARIABLE_POLICY_TYPE_LOCK_ON_CREAT=
E);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ //=0D
+ // Attempt to create the var, but smaller than min size=0D
+ //=0D
+ Value1 =3D 0xA5;=0D
+ Status =3D gRT->SetVariable (L"NonexistentLockOnCreateVar",=0D
+ &mTestNamespaceGuid1,=0D
+ (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIAB=
LE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE),=0D
+ sizeof (Value1),=0D
+ &Value1);=0D
+ UT_ASSERT_TRUE ((Status =3D=3D EFI_WRITE_PROTECTED) || (Status =3D=3D EF=
I_INVALID_PARAMETER));=0D
+=0D
+ //=0D
+ // Now let's make sure attribute req is enforced=0D
+ //=0D
+ Value2 =3D 0x43218765;=0D
+ Status =3D gRT->SetVariable (L"NonexistentLockOnCreateVar",=0D
+ &mTestNamespaceGuid1,=0D
+ (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIAB=
LE_NON_VOLATILE),=0D
+ sizeof (Value2),=0D
+ &Value2);=0D
+ UT_ASSERT_TRUE ((Status =3D=3D EFI_WRITE_PROTECTED) || (Status =3D=3D EF=
I_INVALID_PARAMETER));=0D
+=0D
+ //=0D
+ // Now let's create a valid variable=0D
+ //=0D
+ Value2 =3D 0x43218765;=0D
+ Status =3D gRT->SetVariable (L"NonexistentLockOnCreateVar",=0D
+ &mTestNamespaceGuid1,=0D
+ (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIAB=
LE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE),=0D
+ sizeof (Value2),=0D
+ &Value2);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ //=0D
+ // Let's make sure we can't modify it=0D
+ //=0D
+ Value2 =3D 0xa5a5b6b6;=0D
+ Status =3D gRT->SetVariable (L"NonexistentLockOnCreateVar",=0D
+ &mTestNamespaceGuid1,=0D
+ (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIAB=
LE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE),=0D
+ sizeof (Value2),=0D
+ &Value2);=0D
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_WRITE_PROTECTED);=0D
+=0D
+ //=0D
+ // Finally, let's make sure we can't delete it=0D
+ //=0D
+ Status =3D gRT->SetVariable (L"NonexistentLockOnCreateVar",=0D
+ &mTestNamespaceGuid1,=0D
+ 0,=0D
+ 0,=0D
+ NULL);=0D
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_WRITE_PROTECTED);=0D
+=0D
+ //=0D
+ // This variable is deleted in final cleanup.=0D
+ //=0D
+=0D
+ return UNIT_TEST_PASSED;=0D
+} // TestNonexistentVarLockOnCreate=0D
+=0D
+/**=0D
+ LockOnVarState Policy tests.=0D
+**/=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+TestLockOnVarStateBeforeCreate (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ UINTN Size;=0D
+ UINT8 Value;=0D
+=0D
+ //=0D
+ // First of all, let's make sure the var we're trying to protect doesn't=
exist=0D
+ //=0D
+ Size =3D 0;=0D
+ Status =3D gRT->GetVariable (L"NonexistentLockOnVarStateVar",=0D
+ &mTestNamespaceGuid1,=0D
+ NULL,=0D
+ &Size,=0D
+ NULL);=0D
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_NOT_FOUND);=0D
+=0D
+ //=0D
+ // Good, now let's create a policy=0D
+ //=0D
+ Status =3D RegisterVarStateVariablePolicy (mVarPol,=0D
+ &mTestNamespaceGuid1,=0D
+ L"NonexistentLockOnVarStateVar"=
,=0D
+ VARIABLE_POLICY_NO_MIN_SIZE,=0D
+ VARIABLE_POLICY_NO_MAX_SIZE,=0D
+ VARIABLE_POLICY_NO_MUST_ATTR,=0D
+ VARIABLE_POLICY_NO_CANT_ATTR,=0D
+ &mTestNamespaceGuid1,=0D
+ L"Trigger1",=0D
+ 0x7E);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ //=0D
+ // Now we write the trigger var=0D
+ //=0D
+ Value =3D 0x7E;=0D
+ Status =3D gRT->SetVariable (L"Trigger1",=0D
+ &mTestNamespaceGuid1,=0D
+ (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIAB=
LE_NON_VOLATILE),=0D
+ sizeof (Value),=0D
+ &Value);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ //=0D
+ // Ok, now we attempt to write a var protected by the trigger=0D
+ //=0D
+ Value =3D 0xFA;=0D
+ Status =3D gRT->SetVariable (L"NonexistentLockOnVarStateVar",=0D
+ &mTestNamespaceGuid1,=0D
+ (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIAB=
LE_NON_VOLATILE),=0D
+ sizeof (Value),=0D
+ &Value);=0D
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_WRITE_PROTECTED);=0D
+=0D
+ //=0D
+ // Let's modify the trigger var and "untrigger" the policy=0D
+ //=0D
+ Value =3D 0x38;=0D
+ Status =3D gRT->SetVariable (L"Trigger1",=0D
+ &mTestNamespaceGuid1,=0D
+ (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIAB=
LE_NON_VOLATILE),=0D
+ sizeof (Value),=0D
+ &Value);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ //=0D
+ // Now we should be able to create the var targeted by the policy=0D
+ //=0D
+ Value =3D 0x23;=0D
+ Status =3D gRT->SetVariable (L"NonexistentLockOnVarStateVar",=0D
+ &mTestNamespaceGuid1,=0D
+ (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIAB=
LE_NON_VOLATILE),=0D
+ sizeof (Value),=0D
+ &Value);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ //=0D
+ // Cleanup: delete the trigger and the protected var=0D
+ //=0D
+ Status =3D gRT->SetVariable (L"Trigger1",=0D
+ &mTestNamespaceGuid1,=0D
+ 0,=0D
+ 0,=0D
+ NULL);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ Status =3D gRT->SetVariable (L"NonexistentLockOnVarStateVar",=0D
+ &mTestNamespaceGuid1,=0D
+ 0,=0D
+ 0,=0D
+ NULL);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ return UNIT_TEST_PASSED;=0D
+} // TestLockOnVarStateBeforeCreate=0D
+=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+TestLockOnVarStateAfterCreate (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ UINT8 Value;=0D
+=0D
+ //=0D
+ // Let's create a policy=0D
+ //=0D
+ Status =3D RegisterVarStateVariablePolicy (mVarPol,=0D
+ &mTestNamespaceGuid1,=0D
+ L"ExistingLockOnVarStateVar",=0D
+ VARIABLE_POLICY_NO_MIN_SIZE,=0D
+ VARIABLE_POLICY_NO_MAX_SIZE,=0D
+ VARIABLE_POLICY_NO_MUST_ATTR,=0D
+ VARIABLE_POLICY_NO_CANT_ATTR,=0D
+ &mTestNamespaceGuid1,=0D
+ L"Trigger2",=0D
+ 0x5C);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ //=0D
+ // Should be able to write targeted var since the policy isn't active ye=
t.=0D
+ //=0D
+ Value =3D 0x17;=0D
+ Status =3D gRT->SetVariable (L"ExistingLockOnVarStateVar",=0D
+ &mTestNamespaceGuid1,=0D
+ (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIAB=
LE_NON_VOLATILE),=0D
+ sizeof (Value),=0D
+ &Value);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ //=0D
+ // Let's modify the var to make sure the policy isn't acting like a lock=
-on-create one=0D
+ //=0D
+ Value =3D 0x30;=0D
+ Status =3D gRT->SetVariable (L"ExistingLockOnVarStateVar",=0D
+ &mTestNamespaceGuid1,=0D
+ (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIAB=
LE_NON_VOLATILE),=0D
+ sizeof (Value),=0D
+ &Value);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ //=0D
+ // Now we trigger the policy=0D
+ //=0D
+ Value =3D 0x5C;=0D
+ Status =3D gRT->SetVariable (L"Trigger2",=0D
+ &mTestNamespaceGuid1,=0D
+ (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIAB=
LE_NON_VOLATILE),=0D
+ sizeof (Value),=0D
+ &Value);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ //=0D
+ // Let's now verify the variable is protected=0D
+ //=0D
+ Value =3D 0xB9;=0D
+ Status =3D gRT->SetVariable (L"ExistingLockOnVarStateVar",=0D
+ &mTestNamespaceGuid1,=0D
+ (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIAB=
LE_NON_VOLATILE),=0D
+ sizeof (Value),=0D
+ &Value);=0D
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_WRITE_PROTECTED);=0D
+=0D
+ //=0D
+ // Ok, to clean up, we need to remove the trigger var, so delete it, and=
then delete the target var=0D
+ //=0D
+ Status =3D gRT->SetVariable (L"Trigger2",=0D
+ &mTestNamespaceGuid1,=0D
+ 0,=0D
+ 0,=0D
+ NULL);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ Status =3D gRT->SetVariable (L"ExistingLockOnVarStateVar",=0D
+ &mTestNamespaceGuid1,=0D
+ 0,=0D
+ 0,=0D
+ NULL);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ return UNIT_TEST_PASSED;=0D
+} // TestLockOnVarStateAfterCreate=0D
+=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+TestLockOnVarStateInvalidLargeTrigger (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ UINT16 Value;=0D
+=0D
+ //=0D
+ // First let's create a variable policy=0D
+ //=0D
+ Status =3D RegisterVarStateVariablePolicy (mVarPol,=0D
+ &mTestNamespaceGuid1,=0D
+ L"InvalidLargeTriggerLockOnVarS=
tateVar",=0D
+ VARIABLE_POLICY_NO_MIN_SIZE,=0D
+ VARIABLE_POLICY_NO_MAX_SIZE,=0D
+ VARIABLE_POLICY_NO_MUST_ATTR,=0D
+ VARIABLE_POLICY_NO_CANT_ATTR,=0D
+ &mTestNamespaceGuid1,=0D
+ L"Trigger3",=0D
+ 0x5C);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ //=0D
+ // Now attempt to trigger the lock but with a variable larger than one b=
yte=0D
+ //=0D
+ Value =3D 0x8085;=0D
+ Status =3D gRT->SetVariable (L"Trigger3",=0D
+ &mTestNamespaceGuid1,=0D
+ (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIAB=
LE_NON_VOLATILE),=0D
+ sizeof (Value),=0D
+ &Value);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ //=0D
+ // Should still be able to create the targeted var=0D
+ //=0D
+ Value =3D 0x1234;=0D
+ Status =3D gRT->SetVariable (L"InvalidLargeTriggerLockOnVarStateVar",=0D
+ &mTestNamespaceGuid1,=0D
+ (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIAB=
LE_NON_VOLATILE),=0D
+ sizeof (Value),=0D
+ &Value);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ //=0D
+ // Let's clean up by deleting the invalid trigger and the targeted var=0D
+ //=0D
+ Status =3D gRT->SetVariable (L"Trigger3",=0D
+ &mTestNamespaceGuid1,=0D
+ 0,=0D
+ 0,=0D
+ NULL);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ Status =3D gRT->SetVariable (L"InvalidLargeTriggerLockOnVarStateVar",=0D
+ &mTestNamespaceGuid1,=0D
+ 0,=0D
+ 0,=0D
+ NULL);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ return UNIT_TEST_PASSED;=0D
+} // TestLockOnVarStateInvalidLargeTrigger=0D
+=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+TestLockOnVarStateWrongValueTrigger (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ UINT8 Value;=0D
+=0D
+ //=0D
+ // First let's create a variable policy=0D
+ //=0D
+ Status =3D RegisterVarStateVariablePolicy (mVarPol,=0D
+ &mTestNamespaceGuid1,=0D
+ L"WrongValueTriggerLockOnVarSta=
teVar",=0D
+ VARIABLE_POLICY_NO_MIN_SIZE,=0D
+ VARIABLE_POLICY_NO_MAX_SIZE,=0D
+ VARIABLE_POLICY_NO_MUST_ATTR,=0D
+ VARIABLE_POLICY_NO_CANT_ATTR,=0D
+ &mTestNamespaceGuid1,=0D
+ L"Trigger4",=0D
+ 0xCA);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ //=0D
+ // Now attempt to trigger the lock but with a wrong value=0D
+ //=0D
+ Value =3D 0x80;=0D
+ Status =3D gRT->SetVariable (L"Trigger4",=0D
+ &mTestNamespaceGuid1,=0D
+ (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIAB=
LE_NON_VOLATILE),=0D
+ sizeof (Value),=0D
+ &Value);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ //=0D
+ // Should still be able to create the targeted var=0D
+ //=0D
+ Value =3D 0x14;=0D
+ Status =3D gRT->SetVariable (L"WrongValueTriggerLockOnVarStateVar",=0D
+ &mTestNamespaceGuid1,=0D
+ (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIAB=
LE_NON_VOLATILE),=0D
+ sizeof (Value),=0D
+ &Value);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ //=0D
+ // Let's clean up by deleting the invalid trigger and the targeted var=0D
+ //=0D
+ Status =3D gRT->SetVariable (L"Trigger4",=0D
+ &mTestNamespaceGuid1,=0D
+ 0,=0D
+ 0,=0D
+ NULL);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ Status =3D gRT->SetVariable (L"WrongValueTriggerLockOnVarStateVar",=0D
+ &mTestNamespaceGuid1,=0D
+ 0,=0D
+ 0,=0D
+ NULL);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ return UNIT_TEST_PASSED;=0D
+} // TestLockOnVarStateWrongValueTrigger=0D
+=0D
+/**=0D
+ Invalid policy tests.=0D
+**/=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+TestInvalidAttributesPolicy (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+=0D
+ //=0D
+ // The only must/can't have attributes supported by VPE are NV, BS, and =
RT. They are 1, 2, and 4, respectively.=0D
+ // Let's try some bits higher than that?=0D
+ //=0D
+=0D
+ //=0D
+ // Trying must have attribute 0x8 which is EFI_VARIABLE_HARDWARE_ERROR_R=
ECORD=0D
+ //=0D
+ Status =3D RegisterBasicVariablePolicy (mVarPol,=0D
+ &mTestNamespaceGuid1,=0D
+ L"InvalidMustHaveAttributesPolicyV=
ar1",=0D
+ VARIABLE_POLICY_NO_MIN_SIZE,=0D
+ VARIABLE_POLICY_NO_MAX_SIZE,=0D
+ EFI_VARIABLE_HARDWARE_ERROR_RECORD=
,=0D
+ VARIABLE_POLICY_NO_CANT_ATTR,=0D
+ VARIABLE_POLICY_TYPE_NO_LOCK);=0D
+ UT_LOG_INFO ("Setting must have attr to EFI_VARIABLE_HARDWARE_ERROR_RECO=
RD returned %r\n", Status);=0D
+=0D
+ //=0D
+ // Let's try 0x10 - EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS, a deprecate=
d attribute=0D
+ //=0D
+ Status =3D RegisterBasicVariablePolicy (mVarPol,=0D
+ &mTestNamespaceGuid1,=0D
+ L"InvalidMustHaveAttributesPolicyV=
ar2",=0D
+ VARIABLE_POLICY_NO_MIN_SIZE,=0D
+ VARIABLE_POLICY_NO_MAX_SIZE,=0D
+ EFI_VARIABLE_AUTHENTICATED_WRITE_A=
CCESS,=0D
+ VARIABLE_POLICY_NO_CANT_ATTR,=0D
+ VARIABLE_POLICY_TYPE_NO_LOCK);=0D
+ UT_LOG_INFO ("Setting must have attr to EFI_VARIABLE_AUTHENTICATED_WRITE=
_ACCESS returned %r\n", Status);=0D
+=0D
+ //=0D
+ // Let's try 0x20 - EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS=0D
+ //=0D
+ Status =3D RegisterBasicVariablePolicy (mVarPol,=0D
+ &mTestNamespaceGuid1,=0D
+ L"InvalidMustHaveAttributesPolicyV=
ar3",=0D
+ VARIABLE_POLICY_NO_MIN_SIZE,=0D
+ VARIABLE_POLICY_NO_MAX_SIZE,=0D
+ EFI_VARIABLE_TIME_BASED_AUTHENTICA=
TED_WRITE_ACCESS,=0D
+ VARIABLE_POLICY_NO_CANT_ATTR,=0D
+ VARIABLE_POLICY_TYPE_NO_LOCK);=0D
+ UT_LOG_INFO ("Setting must have attr to EFI_VARIABLE_TIME_BASED_AUTHENTI=
CATED_WRITE_ACCESS returned %r\n", Status);=0D
+=0D
+ //=0D
+ // Let's try something wild, like 0x4000=0D
+ //=0D
+ Status =3D RegisterBasicVariablePolicy (mVarPol,=0D
+ &mTestNamespaceGuid1,=0D
+ L"InvalidMustHaveAttributesPolicyV=
ar4",=0D
+ VARIABLE_POLICY_NO_MIN_SIZE,=0D
+ VARIABLE_POLICY_NO_MAX_SIZE,=0D
+ 0x4000,=0D
+ VARIABLE_POLICY_NO_CANT_ATTR,=0D
+ VARIABLE_POLICY_TYPE_NO_LOCK);=0D
+ UT_LOG_INFO ("Setting must have attr to 0x4000 returned %r\n", Status);=
=0D
+=0D
+ //=0D
+ // Now repeat the same tests, but for the can't-have param=0D
+ //=0D
+ Status =3D RegisterBasicVariablePolicy (mVarPol,=0D
+ &mTestNamespaceGuid1,=0D
+ L"InvalidCantHaveAttributesPolicyV=
ar1",=0D
+ VARIABLE_POLICY_NO_MIN_SIZE,=0D
+ VARIABLE_POLICY_NO_MAX_SIZE,=0D
+ VARIABLE_POLICY_NO_MUST_ATTR,=0D
+ EFI_VARIABLE_HARDWARE_ERROR_RECORD=
,=0D
+ VARIABLE_POLICY_TYPE_NO_LOCK);=0D
+ UT_LOG_INFO ("Setting cant have attr to EFI_VARIABLE_HARDWARE_ERROR_RECO=
RD returned %r\n", Status);=0D
+=0D
+ Status =3D RegisterBasicVariablePolicy (mVarPol,=0D
+ &mTestNamespaceGuid1,=0D
+ L"InvalidCantHaveAttributesPolicyV=
ar2",=0D
+ VARIABLE_POLICY_NO_MIN_SIZE,=0D
+ VARIABLE_POLICY_NO_MAX_SIZE,=0D
+ VARIABLE_POLICY_NO_MUST_ATTR,=0D
+ EFI_VARIABLE_AUTHENTICATED_WRITE_A=
CCESS,=0D
+ VARIABLE_POLICY_TYPE_NO_LOCK);=0D
+ UT_LOG_INFO ("Setting cant have attr to EFI_VARIABLE_AUTHENTICATED_WRITE=
_ACCESS returned %r\n", Status);=0D
+=0D
+ Status =3D RegisterBasicVariablePolicy (mVarPol,=0D
+ &mTestNamespaceGuid1,=0D
+ L"InvalidCantHaveAttributesPolicyV=
ar3",=0D
+ VARIABLE_POLICY_NO_MIN_SIZE,=0D
+ VARIABLE_POLICY_NO_MAX_SIZE,=0D
+ VARIABLE_POLICY_NO_MUST_ATTR,=0D
+ EFI_VARIABLE_TIME_BASED_AUTHENTICA=
TED_WRITE_ACCESS,=0D
+ VARIABLE_POLICY_TYPE_NO_LOCK);=0D
+ UT_LOG_INFO ("Setting cant have attr to EFI_VARIABLE_TIME_BASED_AUTHENTI=
CATED_WRITE_ACCESS returned %r\n", Status);=0D
+=0D
+ Status =3D RegisterBasicVariablePolicy (mVarPol,=0D
+ &mTestNamespaceGuid1,=0D
+ L"InvalidCantHaveAttributesPolicyV=
ar4",=0D
+ VARIABLE_POLICY_NO_MIN_SIZE,=0D
+ VARIABLE_POLICY_NO_MAX_SIZE,=0D
+ VARIABLE_POLICY_NO_MUST_ATTR,=0D
+ 0x4000,=0D
+ VARIABLE_POLICY_TYPE_NO_LOCK);=0D
+ UT_LOG_INFO ("Setting cant have attr to 0x4000 returned %r\n", Status);=
=0D
+=0D
+ return UNIT_TEST_PASSED;=0D
+} // TestInvalidAttributesPolicy=0D
+=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+TestLargeMinSizePolicy (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+=0D
+ //=0D
+ // Let's set the min size to 2GB and see what happens=0D
+ //=0D
+ Status =3D RegisterBasicVariablePolicy (mVarPol,=0D
+ &mTestNamespaceGuid1,=0D
+ L"LargeMinSizeInvalidPolicyVar",=0D
+ 0x80000000,=0D
+ VARIABLE_POLICY_NO_MAX_SIZE,=0D
+ VARIABLE_POLICY_NO_MUST_ATTR,=0D
+ VARIABLE_POLICY_NO_CANT_ATTR,=0D
+ VARIABLE_POLICY_TYPE_NO_LOCK);=0D
+=0D
+ UT_LOG_INFO ("Setting min size to 0x80000000 returned %r\n", Status);=0D
+=0D
+ return UNIT_TEST_PASSED;=0D
+} // TestLargeMinSizePolicy=0D
+=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+TestZeroMaxSizePolicy (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+=0D
+ //=0D
+ // Let's set the max size to 0 and see what happens=0D
+ //=0D
+ Status =3D RegisterBasicVariablePolicy (mVarPol,=0D
+ &mTestNamespaceGuid1,=0D
+ L"ZeroMinSizeInvalidPolicyVar",=0D
+ VARIABLE_POLICY_NO_MIN_SIZE,=0D
+ 0,=0D
+ VARIABLE_POLICY_NO_MUST_ATTR,=0D
+ VARIABLE_POLICY_NO_CANT_ATTR,=0D
+ VARIABLE_POLICY_TYPE_NO_LOCK);=0D
+ //UT_ASSERT_NOT_EQUAL (Status, EFI_SUCCESS); // this fails on QC. Real b=
ug? Do we care?=0D
+ UT_LOG_INFO ("Setting max size to 0 returned %r\n", Status);=0D
+=0D
+ return UNIT_TEST_PASSED;=0D
+} // TestZeroMaxSizePolicy=0D
+=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+TestInvalidPolicyTypePolicy (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+=0D
+ //=0D
+ // Let's set policy type to an invalid value and see what happens=0D
+ // Valid ones are:=0D
+ // VARIABLE_POLICY_TYPE_NO_LOCK 0=0D
+ // VARIABLE_POLICY_TYPE_LOCK_NOW 1=0D
+ // VARIABLE_POLICY_TYPE_LOCK_ON_CREATE 2=0D
+ // VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE 3=0D
+ //=0D
+ Status =3D RegisterBasicVariablePolicy (mVarPol,=0D
+ &mTestNamespaceGuid1,=0D
+ L"InvalidPolicyTypePolicyVar",=0D
+ VARIABLE_POLICY_NO_MIN_SIZE,=0D
+ VARIABLE_POLICY_NO_MAX_SIZE,=0D
+ VARIABLE_POLICY_NO_MUST_ATTR,=0D
+ VARIABLE_POLICY_NO_CANT_ATTR,=0D
+ 4);=0D
+ UT_ASSERT_NOT_EQUAL (Status, EFI_SUCCESS);=0D
+=0D
+ Status =3D RegisterBasicVariablePolicy (mVarPol,=0D
+ &mTestNamespaceGuid1,=0D
+ L"InvalidPolicyTypePolicyVar",=0D
+ VARIABLE_POLICY_NO_MIN_SIZE,=0D
+ VARIABLE_POLICY_NO_MAX_SIZE,=0D
+ VARIABLE_POLICY_NO_MUST_ATTR,=0D
+ VARIABLE_POLICY_NO_CANT_ATTR,=0D
+ 147);=0D
+ UT_ASSERT_NOT_EQUAL (Status, EFI_SUCCESS);=0D
+=0D
+ return UNIT_TEST_PASSED;=0D
+} // TestInvalidPolicyTypePolicy=0D
+=0D
+/**=0D
+ Test dumping policy.=0D
+**/=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+TestDumpPolicy (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ UINT8* Buffer;=0D
+ UINT32 Size;=0D
+=0D
+ //=0D
+ // First let's call DumpVariablePolicy with null buffer to get size=0D
+ //=0D
+ Size =3D 0;=0D
+ Status =3D mVarPol->DumpVariablePolicy (NULL, &Size);=0D
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_BUFFER_TOO_SMALL);=0D
+=0D
+ //=0D
+ // Now we allocate the buffer for the dump=0D
+ //=0D
+ Buffer =3D NULL;=0D
+ Buffer =3D AllocatePool (Size);=0D
+ UT_ASSERT_NOT_NULL (Buffer);=0D
+=0D
+ //=0D
+ // Now we get the dump. In this test we will not analyze the dump.=0D
+ //=0D
+ Status =3D mVarPol->DumpVariablePolicy (Buffer, &Size);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ return UNIT_TEST_PASSED;=0D
+} // TestDumpPolicy=0D
+=0D
+/**=0D
+ Test policy version.=0D
+**/=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+TestPolicyVersion (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ VARIABLE_POLICY_ENTRY *NewEntry;=0D
+=0D
+ //=0D
+ // Create the new entry using a helper lib=0D
+ //=0D
+ NewEntry =3D NULL;=0D
+ Status =3D CreateBasicVariablePolicy (&mTestNamespaceGuid1,=0D
+ L"PolicyVersionTestNoLockVar",=0D
+ VARIABLE_POLICY_NO_MIN_SIZE,=0D
+ 4, // max size of 4 bytes=0D
+ VARIABLE_POLICY_NO_MUST_ATTR,=0D
+ VARIABLE_POLICY_NO_CANT_ATTR,=0D
+ VARIABLE_POLICY_TYPE_NO_LOCK,=0D
+ &NewEntry);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ NewEntry->Version =3D 0x1234;=0D
+ Status =3D mVarPol->RegisterVariablePolicy (NewEntry);=0D
+ UT_LOG_INFO ("Registering policy entry with an unknown version status: %=
r\n", Status);=0D
+=0D
+ FreePool (NewEntry);=0D
+=0D
+ return UNIT_TEST_PASSED;=0D
+} // TestPolicyVersion=0D
+=0D
+/**=0D
+ Lock Policy Tests.=0D
+**/=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+LockPolicyEngineTests (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ UINT16 Value;=0D
+ UINT64 Value64;=0D
+ BOOLEAN State;=0D
+=0D
+ //=0D
+ // First let's register a policy that we'll test after VPE lock=0D
+ //=0D
+ Status =3D RegisterBasicVariablePolicy (mVarPol,=0D
+ &mTestNamespaceGuid1,=0D
+ L"BeforeVpeLockNoLockPolicyVar",=0D
+ VARIABLE_POLICY_NO_MIN_SIZE,=0D
+ 4, // max size of 4 bytes=0D
+ VARIABLE_POLICY_NO_MUST_ATTR,=0D
+ VARIABLE_POLICY_NO_CANT_ATTR,=0D
+ VARIABLE_POLICY_TYPE_LOCK_ON_CREAT=
E);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ //=0D
+ // Now, lock VPE!=0D
+ //=0D
+ Status =3D mVarPol->LockVariablePolicy ();=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ //=0D
+ // See if we can lock it again?=0D
+ //=0D
+ Status =3D mVarPol->LockVariablePolicy ();=0D
+ UT_LOG_INFO ("Locking VPE for second time returned %r\n", Status);=0D
+=0D
+ //=0D
+ // Let's confirm one of the policies from prior test suites is still enf=
orced=0D
+ // Attempt to delete a locked var=0D
+ //=0D
+ Status =3D gRT->SetVariable (L"ExistingLockNowVar",=0D
+ &mTestNamespaceGuid1,=0D
+ 0,=0D
+ 0,=0D
+ NULL);=0D
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_WRITE_PROTECTED);=0D
+=0D
+ //=0D
+ // We'll make sure the policy from earlier in this test case is actively=
filtering out by size=0D
+ //=0D
+ Value64 =3D 0x3829fed212345678;=0D
+ Status =3D gRT->SetVariable (L"BeforeVpeLockNoLockPolicyVar",=0D
+ &mTestNamespaceGuid1,=0D
+ (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BO=
OTSERVICE_ACCESS),=0D
+ sizeof (Value64),=0D
+ &Value64);=0D
+ UT_ASSERT_TRUE ((Status =3D=3D EFI_WRITE_PROTECTED) || (Status =3D=3D EF=
I_INVALID_PARAMETER));=0D
+=0D
+ //=0D
+ // Let's create the variable from the policy now=0D
+ //=0D
+ Value =3D 0x323f;=0D
+ Status =3D gRT->SetVariable (L"BeforeVpeLockNoLockPolicyVar",=0D
+ &mTestNamespaceGuid1,=0D
+ (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BO=
OTSERVICE_ACCESS),=0D
+ sizeof (Value),=0D
+ &Value);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ //=0D
+ // Now confirm that the var is locked after creation=0D
+ //=0D
+ Value =3D 0x1212;=0D
+ Status =3D gRT->SetVariable (L"BeforeVpeLockNoLockPolicyVar",=0D
+ &mTestNamespaceGuid1,=0D
+ (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BO=
OTSERVICE_ACCESS),=0D
+ sizeof (Value),=0D
+ &Value);=0D
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_WRITE_PROTECTED);=0D
+=0D
+ //=0D
+ // Let's attempt to register a new policy, it should fail=0D
+ //=0D
+ Status =3D RegisterBasicVariablePolicy (mVarPol,=0D
+ &mTestNamespaceGuid1,=0D
+ L"AfterVpeLockNowPolicyVar",=0D
+ VARIABLE_POLICY_NO_MIN_SIZE,=0D
+ VARIABLE_POLICY_NO_MAX_SIZE,=0D
+ VARIABLE_POLICY_NO_MUST_ATTR,=0D
+ VARIABLE_POLICY_NO_CANT_ATTR,=0D
+ VARIABLE_POLICY_TYPE_LOCK_NOW);=0D
+ UT_ASSERT_NOT_EQUAL (Status, EFI_SUCCESS);=0D
+=0D
+ //=0D
+ // Make sure VPE is enabled=0D
+ //=0D
+ Status =3D mVarPol->IsVariablePolicyEnabled (&State);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+ UT_ASSERT_EQUAL (State, TRUE);=0D
+=0D
+ //=0D
+ // Finally, make sure we can't disable VPE=0D
+ //=0D
+ Status =3D mVarPol->DisableVariablePolicy ();=0D
+ UT_ASSERT_NOT_EQUAL (Status, EFI_SUCCESS);=0D
+=0D
+ return UNIT_TEST_PASSED;=0D
+} // LockPolicyEngineTests=0D
+=0D
+/**=0D
+ Save context and reboot after the lock policy test suite.=0D
+**/=0D
+STATIC=0D
+VOID=0D
+EFIAPI=0D
+SaveContextAndReboot (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+=0D
+ //=0D
+ // Now, save all the data associated with this framework.=0D
+ // TODO: Need to add to the UnitTestFrameworkPkg=0D
+ Status =3D SaveFrameworkState( GetActiveFrameworkHandle(), NULL, 0 );=0D
+=0D
+ //=0D
+ // If we're all good, let's book...=0D
+ if (!EFI_ERROR( Status ))=0D
+ {=0D
+ //=0D
+ // Next, we want to update the BootNext variable to USB=0D
+ // so that we have a fighting chance of coming back here.=0D
+ //=0D
+ // TODO: Need to add to the UnitTestFrameworkPkg=0D
+ // SetBootNextDevice();=0D
+=0D
+ //=0D
+ // Reset=0D
+ DEBUG(( DEBUG_INFO, "%a - Rebooting! Launch this test again once boote=
d.\n", __FUNCTION__ ));=0D
+ gRT->ResetSystem( EfiResetCold, EFI_SUCCESS, 0, NULL );=0D
+ DEBUG(( DEBUG_ERROR, "%a - Unit test failed to quit! Framework can no =
longer be used!\n", __FUNCTION__ ));=0D
+=0D
+ //=0D
+ // We REALLY shouldn't be here.=0D
+ Status =3D EFI_ABORTED;=0D
+ }=0D
+=0D
+ return;=0D
+} // SaveContextAndReboot=0D
+=0D
+/**=0D
+ Disable policy tests.=0D
+**/=0D
+UNIT_TEST_STATUS=0D
+EFIAPI=0D
+DisablePolicyEngineTests (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ BOOLEAN State;=0D
+ UINT8 Value;=0D
+=0D
+ //=0D
+ // First, we disable the variable policy=0D
+ //=0D
+ Status =3D mVarPol->DisableVariablePolicy ();=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ //=0D
+ // Confirm it's disabled=0D
+ //=0D
+ Status =3D mVarPol->IsVariablePolicyEnabled (&State);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+ UT_ASSERT_EQUAL (State, FALSE);=0D
+=0D
+ //=0D
+ // Try locking it?=0D
+ //=0D
+ Status =3D mVarPol->LockVariablePolicy ();=0D
+ UT_LOG_INFO ("Locking VP after disabling it status: %r\n", Status);=0D
+=0D
+ //=0D
+ // Try modifying the var from TestExistingVarLockNow=0D
+ //=0D
+ Value =3D 0xB5;=0D
+ Status =3D gRT->SetVariable (L"ExistingLockNowVar",=0D
+ &mTestNamespaceGuid1,=0D
+ (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIAB=
LE_NON_VOLATILE),=0D
+ sizeof (Value),=0D
+ &Value);=0D
+ UT_ASSERT_NOT_EFI_ERROR (Status);=0D
+=0D
+ return UNIT_TEST_PASSED;=0D
+} // DisablePolicyEngineTests=0D
+=0D
+/**=0D
+ Final Cleanup: delete some variables earlier test cases created.=0D
+**/=0D
+STATIC=0D
+VOID=0D
+EFIAPI=0D
+FinalCleanup (=0D
+ IN UNIT_TEST_CONTEXT Context=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+=0D
+ Status =3D gRT->SetVariable (L"ExistingLockNowVar",=0D
+ &mTestNamespaceGuid1,=0D
+ 0,=0D
+ 0,=0D
+ NULL);=0D
+ UT_LOG_INFO ("Delete ExistingLockNowVar status: %r\n", Status);=0D
+=0D
+ Status =3D gRT->SetVariable (L"ExistingLockOnCreateVar",=0D
+ &mTestNamespaceGuid1,=0D
+ 0,=0D
+ 0,=0D
+ NULL);=0D
+ UT_LOG_INFO ("Delete ExistingLockOnCreateVar status: %r\n", Status);=0D
+=0D
+ Status =3D gRT->SetVariable (L"NonexistentLockOnCreateVar",=0D
+ &mTestNamespaceGuid1,=0D
+ 0,=0D
+ 0,=0D
+ NULL);=0D
+ UT_LOG_INFO ("Delete NonexistentLockOnCreateVar status: %r\n", Status);=
=0D
+=0D
+ Status =3D gRT->SetVariable (L"NonexistentLockNowVar",=0D
+ &mTestNamespaceGuid1,=0D
+ 0,=0D
+ 0,=0D
+ NULL);=0D
+ UT_LOG_INFO ("Delete NonexistentLockNowVar status: %r\n", Status);=0D
+=0D
+ Status =3D gRT->SetVariable (L"CantHaveAttrNoLockVar",=0D
+ &mTestNamespaceGuid1,=0D
+ 0,=0D
+ 0,=0D
+ NULL);=0D
+ UT_LOG_INFO ("Delete CantHaveAttrNoLockVar status: %r\n", Status);=0D
+=0D
+ Status =3D gRT->SetVariable (L"NonexistentLockOnVarStateVar",=0D
+ &mTestNamespaceGuid1,=0D
+ 0,=0D
+ 0,=0D
+ NULL);=0D
+ UT_LOG_INFO ("Delete NonexistentLockOnVarStateVar status: %r\n", Status)=
;=0D
+=0D
+ Status =3D gRT->SetVariable (L"ExistingLockOnVarStateVar",=0D
+ &mTestNamespaceGuid1,=0D
+ 0,=0D
+ 0,=0D
+ NULL);=0D
+ UT_LOG_INFO ("Delete ExistingLockOnVarStateVar status: %r\n", Status);=0D
+} // FinalCleanup=0D
+=0D
+/**=0D
+=0D
+ Main fuction sets up the unit test environment.=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+UefiMain (=0D
+ IN EFI_HANDLE ImageHandle,=0D
+ IN EFI_SYSTEM_TABLE* SystemTable)=0D
+{=0D
+ EFI_STATUS Status;=0D
+ UNIT_TEST_FRAMEWORK_HANDLE Framework;=0D
+ UNIT_TEST_SUITE_HANDLE GettingStartedTestSuite;=0D
+ UNIT_TEST_SUITE_HANDLE NoLockPoliciesTestSuite;=0D
+ UNIT_TEST_SUITE_HANDLE LockNowPoliciesTestSuite;=0D
+ UNIT_TEST_SUITE_HANDLE LockOnCreatePoliciesTestSuite;=0D
+ UNIT_TEST_SUITE_HANDLE LockOnVarStatePoliciesTestSuite;=0D
+ UNIT_TEST_SUITE_HANDLE InvalidPoliciesTestSuite;=0D
+ UNIT_TEST_SUITE_HANDLE DumpPolicyTestSuite;=0D
+ UNIT_TEST_SUITE_HANDLE PolicyVersionTestSuite;=0D
+ UNIT_TEST_SUITE_HANDLE LockPolicyTestSuite;=0D
+ UNIT_TEST_SUITE_HANDLE DisablePolicyTestSuite;=0D
+=0D
+ Framework =3D NULL;=0D
+ GettingStartedTestSuite =3D NULL;=0D
+ NoLockPoliciesTestSuite =3D NULL;=0D
+ LockNowPoliciesTestSuite =3D NULL;=0D
+ LockOnCreatePoliciesTestSuite =3D NULL;=0D
+ LockOnVarStatePoliciesTestSuite =3D NULL;=0D
+ InvalidPoliciesTestSuite =3D NULL;=0D
+ DumpPolicyTestSuite =3D NULL;=0D
+ PolicyVersionTestSuite =3D NULL; =0D
+ LockPolicyTestSuite =3D NULL;=0D
+ DisablePolicyTestSuite =3D NULL;=0D
+=0D
+ DEBUG ((DEBUG_INFO, "%a v%a\n", UNIT_TEST_APP_NAME, UNIT_TEST_APP_VERSIO=
N));=0D
+=0D
+ //=0D
+ // Start setting up the test framework for running the tests.=0D
+ //=0D
+ Status =3D InitUnitTestFramework (&Framework, UNIT_TEST_APP_NAME, gEfiCa=
llerBaseName, UNIT_TEST_APP_VERSION);=0D
+ if (EFI_ERROR (Status)) {=0D
+ DEBUG ((DEBUG_ERROR, "Failed in InitUnitTestFramework. Status =3D %r\n=
", Status));=0D
+ goto EXIT;=0D
+ }=0D
+=0D
+ //=0D
+ // Test suite 1: Getting Started. Get VP protocol, check state, log revi=
sion=0D
+ //=0D
+ Status =3D CreateUnitTestSuite (&GettingStartedTestSuite, Framework, "Ge=
tting Started", "Common.VP.GettingStarted", NULL, NULL);=0D
+ if (EFI_ERROR (Status)) {=0D
+ DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for the Getting St=
arted Test Suite\n"));=0D
+ Status =3D EFI_OUT_OF_RESOURCES;=0D
+ goto EXIT;=0D
+ }=0D
+ AddTestCase (GettingStartedTestSuite, "Confirm VP is enabled", "Common.V=
P.GettingStarted.CheckVpEnabled", CheckVpEnabled, LocateVarPolicyPreReq, NU=
LL, NULL);=0D
+ AddTestCase (GettingStartedTestSuite, "Check VP revision", "Common.VP.Ge=
ttingStarted.CheckVpRevision", CheckVpRevision, LocateVarPolicyPreReq, NULL=
, NULL);=0D
+=0D
+ //=0D
+ // Test suite 2: Test NoLock Policies=0D
+ //=0D
+ Status =3D CreateUnitTestSuite (&NoLockPoliciesTestSuite, Framework, "Ex=
ercise NoLock Policies", "Common.VP.NoLockPolicies", NULL, NULL);=0D
+ if (EFI_ERROR (Status)) {=0D
+ DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for the NoLock Pol=
icies Test Suite\n"));=0D
+ Status =3D EFI_OUT_OF_RESOURCES;=0D
+ goto EXIT;=0D
+ }=0D
+ AddTestCase (NoLockPoliciesTestSuite, "Test Min Size enforcement in NoLo=
ck policy", "Common.VP.NoLockPolicies.TestMinSizeNoLock", TestMinSizeNoLock=
, LocateVarPolicyPreReq, NULL, NULL);=0D
+ AddTestCase (NoLockPoliciesTestSuite, "Test Max Size enforcement in NoLo=
ck policy", "Common.VP.NoLockPolicies.TestMaxSizeNoLock", TestMaxSizeNoLock=
, LocateVarPolicyPreReq, NULL, NULL);=0D
+ AddTestCase (NoLockPoliciesTestSuite, "Test Must Have Attribute enforcem=
ent in NoLock policy", "Common.VP.NoLockPolicies.TestMustHaveAttrNoLock", T=
estMustHaveAttrNoLock, LocateVarPolicyPreReq, NULL, NULL);=0D
+ AddTestCase (NoLockPoliciesTestSuite, "Test Can't Have Attribute enforce=
ment in NoLock policy", "Common.VP.NoLockPolicies.TestCantHaveAttrNoLock", =
TestCantHaveAttrNoLock, LocateVarPolicyPreReq, NULL, NULL);=0D
+ AddTestCase (NoLockPoliciesTestSuite, "Test Max Size enforcement in NoLo=
ck policy for entire namespace", "Common.VP.NoLockPolicies.TestMaxSizeNames=
paceNoLock", TestMaxSizeNamespaceNoLock, LocateVarPolicyPreReq, NULL, NULL)=
;=0D
+ AddTestCase (NoLockPoliciesTestSuite, "Test Must Have Attribute enforcem=
ent in NoLock policy with wildcards", "Common.VP.NoLockPolicies.TestMustHav=
eAttrWildcardNoLock", TestMustHaveAttrWildcardNoLock, LocateVarPolicyPreReq=
, NULL, NULL);=0D
+ AddTestCase (NoLockPoliciesTestSuite, "Test policy prioritization betwee=
n namespace-wide, wildcard, and var-specific policies", "Common.VP.NoLockPo=
licies.TestPolicyprioritizationNoLock", TestPolicyprioritizationNoLock, Loc=
ateVarPolicyPreReq, NULL, NULL);=0D
+=0D
+ //=0D
+ // Test suite 3: Test LockNow policies=0D
+ //=0D
+ Status =3D CreateUnitTestSuite (&LockNowPoliciesTestSuite, Framework, "E=
xercise LockNow Policies", "Common.VP.LockNowPolicies", NULL, NULL);=0D
+ if (EFI_ERROR (Status)) {=0D
+ DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for the LockNow Po=
licies Test Suite\n"));=0D
+ Status =3D EFI_OUT_OF_RESOURCES;=0D
+ goto EXIT;=0D
+ }=0D
+ AddTestCase (LockNowPoliciesTestSuite, "Test LockNow policy for a pre-ex=
isting variable", "Common.VP.LockNowPolicies.TestExistingVarLockNow", TestE=
xistingVarLockNow, LocateVarPolicyPreReq, NULL, NULL);=0D
+ AddTestCase (LockNowPoliciesTestSuite, "Test LockNow policy for a nonexi=
stent variable", "Common.VP.LockNowPolicies.TestNonexistentVarLockNow", Tes=
tNonexistentVarLockNow, LocateVarPolicyPreReq, NULL, NULL);=0D
+=0D
+ //=0D
+ // Test suite 4: Test LockOnCreate policies=0D
+ //=0D
+ Status =3D CreateUnitTestSuite (&LockOnCreatePoliciesTestSuite, Framewor=
k, "Exercise LockOnCreate Policies", "Common.VP.LockOnCreate", NULL, NULL);=
=0D
+ if (EFI_ERROR (Status))=0D
+ {=0D
+ DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for the LockOnCrea=
te Policies Test Suite\n"));=0D
+ Status =3D EFI_OUT_OF_RESOURCES;=0D
+ goto EXIT;=0D
+ }=0D
+ AddTestCase (LockOnCreatePoliciesTestSuite, "Test LockOnCreate policy fo=
r a pre-existing variable", "Common.VP.LockOnCreate.TestExistingVarLockOnCr=
eate", TestExistingVarLockOnCreate, LocateVarPolicyPreReq, NULL, NULL);=0D
+ AddTestCase (LockOnCreatePoliciesTestSuite, "Test LockOnCreate policy fo=
r a nonexistent variable", "Common.VP.LockOnCreate.TestNonexistentVarLockOn=
Create", TestNonexistentVarLockOnCreate, LocateVarPolicyPreReq, NULL, NULL)=
;=0D
+=0D
+ //=0D
+ // Test suite 5: Test LockOnVarState policies=0D
+ //=0D
+ Status =3D CreateUnitTestSuite (&LockOnVarStatePoliciesTestSuite, Framew=
ork, "Exercise LockOnVarState Policies", "Common.VP.LockOnVarState", NULL, =
NULL);=0D
+ if (EFI_ERROR (Status)) {=0D
+ DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for the LockOnVarS=
tate Policies Test Suite\n"));=0D
+ Status =3D EFI_OUT_OF_RESOURCES;=0D
+ goto EXIT;=0D
+ }=0D
+ AddTestCase (LockOnVarStatePoliciesTestSuite, "Test LockOnVarState polic=
y for a nonexistent variable", "Common.VP.LockOnVarState.TestLockOnVarState=
BeforeCreate", TestLockOnVarStateBeforeCreate, LocateVarPolicyPreReq, NULL,=
NULL);=0D
+ AddTestCase (LockOnVarStatePoliciesTestSuite, "Test LockOnVarState polic=
y for a pre-existing variable", "Common.VP.LockOnVarState.TestLockOnVarStat=
eAfterCreate", TestLockOnVarStateAfterCreate, LocateVarPolicyPreReq, NULL, =
NULL);=0D
+ AddTestCase (LockOnVarStatePoliciesTestSuite, "Test LockOnVarState polic=
y triggered by invalid-size variable", "Common.VP.LockOnVarState.TestLockOn=
VarStateInvalidLargeTrigger", TestLockOnVarStateInvalidLargeTrigger, Locate=
VarPolicyPreReq, NULL, NULL);=0D
+ AddTestCase (LockOnVarStatePoliciesTestSuite, "Test LockOnVarState polic=
y triggered by invalid-value variable", "Common.VP.LockOnVarState.TestLockO=
nVarStateWrongValueTrigger", TestLockOnVarStateWrongValueTrigger, LocateVar=
PolicyPreReq, NULL, NULL);=0D
+=0D
+ //=0D
+ // Test suite 6: Test registering invalid policies=0D
+ //=0D
+ Status =3D CreateUnitTestSuite (&InvalidPoliciesTestSuite, Framework, "A=
ttempt registering invalid policies", "Common.VP.InvalidPolicies", NULL, NU=
LL);=0D
+ if (EFI_ERROR (Status)) {=0D
+ DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for the Invalid Po=
licies Test Suite\n"));=0D
+ Status =3D EFI_OUT_OF_RESOURCES;=0D
+ goto EXIT;=0D
+ }=0D
+ AddTestCase (InvalidPoliciesTestSuite, "Test policy with invalid must-ha=
ve attributes", "Common.VP.InvalidPolicies.TestInvalidAttributesPolicy", Te=
stInvalidAttributesPolicy, LocateVarPolicyPreReq, NULL, NULL);=0D
+ AddTestCase (InvalidPoliciesTestSuite, "Test policy with invalid attribu=
tes", "Common.VP.InvalidPolicies.TestLargeMinSizePolicy", TestLargeMinSizeP=
olicy, LocateVarPolicyPreReq, NULL, NULL);=0D
+ AddTestCase (InvalidPoliciesTestSuite, "Test policy with invalid attribu=
tes", "Common.VP.InvalidPolicies.TestZeroMaxSizePolicy", TestZeroMaxSizePol=
icy, LocateVarPolicyPreReq, NULL, NULL);=0D
+ AddTestCase (InvalidPoliciesTestSuite, "Test policy with invalid type", =
"Common.VP.InvalidPolicies.TestInvalidPolicyTypePolicy", TestInvalidPolicyT=
ypePolicy, LocateVarPolicyPreReq, NULL, NULL);=0D
+=0D
+ //=0D
+ // Test suite 7: Test dumping the policy=0D
+ //=0D
+ Status =3D CreateUnitTestSuite (&DumpPolicyTestSuite, Framework, "Attemp=
t dumping policy", "Common.VP.DumpPolicy", NULL, NULL);=0D
+ if (EFI_ERROR (Status)) {=0D
+ DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for the Dump Polic=
y Test Suite\n"));=0D
+ Status =3D EFI_OUT_OF_RESOURCES;=0D
+ goto EXIT;=0D
+ }=0D
+ AddTestCase (DumpPolicyTestSuite, "Test dumping policy", "Common.VP.Dump=
Policy.TestDumpPolicy", TestDumpPolicy, LocateVarPolicyPreReq, NULL, NULL);=
=0D
+=0D
+ //=0D
+ // Test suite 8: Test policy version=0D
+ //=0D
+ Status =3D CreateUnitTestSuite (&PolicyVersionTestSuite, Framework, "Use=
non-zero policy version", "Common.VP.PolicyVersion", NULL, NULL);=0D
+ if (EFI_ERROR (Status)) {=0D
+ DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for the Policy Ver=
sion Test Suite\n"));=0D
+ Status =3D EFI_OUT_OF_RESOURCES;=0D
+ goto EXIT;=0D
+ }=0D
+ AddTestCase (PolicyVersionTestSuite, "Test policy version", "Common.VP.D=
umpPolicy.TestPolicyVersion", TestPolicyVersion, LocateVarPolicyPreReq, NUL=
L, NULL);=0D
+=0D
+ //=0D
+ // Test suite 9: Lock VPE and test implications=0D
+ //=0D
+ Status =3D CreateUnitTestSuite (&LockPolicyTestSuite, Framework, "Lock p=
olicy, test it", "Common.VP.LockPolicyTests", NULL, NULL);=0D
+ if (EFI_ERROR (Status)) {=0D
+ DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for the Lock Polic=
y Test Suite\n"));=0D
+ Status =3D EFI_OUT_OF_RESOURCES;=0D
+ goto EXIT;=0D
+ }=0D
+ AddTestCase (LockPolicyTestSuite, "Test locking policy", "Common.VP.Lock=
PolicyTests.LockPolicyEngineTests", LockPolicyEngineTests, LocateVarPolicyP=
reReq, NULL, NULL);=0D
+ AddTestCase (LockPolicyTestSuite, "Test locking policy", "Common.VP.Lock=
PolicyTests.LockPolicyEngineTests", LockPolicyEngineTests, LocateVarPolicyP=
reReq, SaveContextAndReboot, NULL);=0D
+=0D
+ //=0D
+ // Test suite 10: Disable var policy and confirm expected behavior=0D
+ //=0D
+ Status =3D CreateUnitTestSuite (&DisablePolicyTestSuite, Framework, "Dis=
able policy, test it", "Common.VP.DisablePolicyTests", NULL, NULL);=0D
+ if (EFI_ERROR (Status)) {=0D
+ DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for the Disable Po=
licy Test Suite\n"));=0D
+ Status =3D EFI_OUT_OF_RESOURCES;=0D
+ goto EXIT;=0D
+ }=0D
+ AddTestCase (DisablePolicyTestSuite, "Confirm VP is enabled", "Common.VP=
.DisablePolicyTests.CheckVpEnabled", CheckVpEnabled, LocateVarPolicyPreReq,=
NULL, NULL);=0D
+ AddTestCase (DisablePolicyTestSuite, "Test LockNow policy for a pre-exis=
ting variable", "Common.VP.DisablePolicyTests.TestExistingVarLockNow", Test=
ExistingVarLockNow, LocateVarPolicyPreReq, NULL, NULL);=0D
+ AddTestCase (DisablePolicyTestSuite, "Test disabling policy", "Common.VP=
.DisablePolicyTests.DisablePolicyEngineTests", DisablePolicyEngineTests, Lo=
cateVarPolicyPreReq, FinalCleanup, NULL);=0D
+=0D
+ //=0D
+ // Execute the tests.=0D
+ //=0D
+ Status =3D RunAllTestSuites (Framework);=0D
+=0D
+EXIT:=0D
+ if (Framework !=3D NULL) {=0D
+ FreeUnitTestFramework (Framework);=0D
+ }=0D
+=0D
+ return Status;=0D
+} // UefiMain=0D
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"=0D
],=0D
# For UEFI shell based apps=0D
- "AcceptableDependencies-UEFI_APPLICATION":[],=0D
+ "AcceptableDependencies-UEFI_APPLICATION":[=0D
+ "UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec"=0D
+ ],=0D
"IgnoreInf": []=0D
},=0D
=0D
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 =3D DEBUG|RELEASE|NOOPT=0D
SKUID_IDENTIFIER =3D DEFAULT=0D
=0D
+!include UnitTestFrameworkPkg/UnitTestFrameworkPkgTarget.dsc.inc=0D
+=0D
[LibraryClasses]=0D
#=0D
# Entry point=0D
@@ -314,6 +316,10 @@ [Components]
MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf=0D
MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf=0D
MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.inf=0D
+ MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/VariablePolicyFunc=
TestApp.inf {=0D
+ <LibraryClasses>=0D
+ UnitTestBootLib|UnitTestFrameworkPkg/Library/UnitTestBootLibNull/Uni=
tTestBootLibNull.inf=0D
+ }=0D
MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf=0D
MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLib.inf=0D
MdeModulePkg/Library/VarCheckPcdLib/VarCheckPcdLib.inf=0D
diff --git a/MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/Readme.m=
d 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=0D
+=0D
+## &#x1F539; Copyright=0D
+Copyright (C) Microsoft Corporation. All rights reserved.=0D
+SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+=0D
+## About This Test=0D
+This test verifies functionality of the Variable Policy Protocol by regist=
ering various variable policies and exercising them, as well as tests locki=
ng the policy, disabling it, and dumping the policy entries.=0D
+=0D
+Only policies that are created as a part of this test will be tested.=0D
+1. Try getting test context, if empty then get VP protocol, confirm that V=
P is not disabled by calling IsVariablePolicyEnabled. Log VP revision.=0D
+2. "No lock" policies:=0D
+ * check minsize enforcement=0D
+ * check maxsize enforcement=0D
+ * check musthave attr enforcement=0D
+ * check canthave attr enforcement=0D
+ * check one of the above with empty string policy i.e. name wildcard=0D
+ * check another one of the above with a "#" containing policy string=0D
+ * check policy prioritization by having a namespace-wide policy, a pol=
icy with a # wildcard, and a one-var specific policy and testing which one =
is enforced=0D
+3. "Lock now" policies (means if the var doesn't exist, it won't be create=
d; if one exists, it can't be updated):=0D
+ * test a policy for an already existing variable, verify we can't writ=
e into that variable=0D
+ * create a policy for a non-existing variable and attempt to register =
such var=0D
+4. "Lock on create" policies (means the var can still be created, but no u=
pdates later, existing vars can't be updated):=0D
+ * create a var, lock it with LockOnCreate, attempt to update its conte=
nts=0D
+ * create LockOnCreate VP, attempt to create var with invalid size, the=
n invalid attr, then create valid var, attempt to update its contents=0D
+5. "Lock on var state" policies (means the var protected by this policy ca=
n't be created or updated once the trigger is set)=0D
+ * create VP, trigger lock with a valid var, attempt to create a locked=
var, then modify the trigger var, create locked var=0D
+ * create VP, create targeted var, modify it, trigger lock, attempt to =
modify var=0D
+ * create VP, trigger lock with invalid (larger than one byte) var, see=
if VPE allows creation of the locked var (it should allow)=0D
+ * create VP, set locking var with wrong value, see if VPE allows creat=
ion of the locked var (should allow)=0D
+6. Attempt registering invalid policy entries=0D
+ * invalid required and banned attributes=0D
+ * large min size - let's say 2GB=0D
+ * max size equal to 0=0D
+ * invalid policy type=0D
+7. Exercise dumping policy. No need to check the validity of the dump blob=
.=0D
+8. Test registering a policy with a random version.=0D
+9. Lock VPE, make sure old policies are enforced, new ones can't be regist=
ered.=0D
+ * Register a LockOnCreate policy=0D
+ * Lock VPE=0D
+ * Test locking it again.=0D
+ * Verify one of the prior policies is enforced=0D
+ * Make sure we can create variables even if those are protected by Loc=
kOnCreate policy, after locking the VPE=0D
+ * Attempt to register new policies=0D
+ * Make sure can't disable VPE=0D
+ * Cleanup: save context and reboot=0D
+10. Disable variable policy and try some things=0D
+ * Locate Variable Policy Protocol=0D
+ * Make sure VP is enabled=0D
+ * Register a policy=0D
+ * Disable VPE=0D
+ * Call IsVariablePolicyEnabled to confirm it's disabled.=0D
+ * Make sure can't lock policy=0D
+ * Make sure the policy from a is no longer enforced=0D
+ * Final cleanup: delete vars that were created in some earlier test su=
ites=0D
diff --git a/MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/Variable=
PolicyFuncTestApp.inf b/MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestA=
pp/VariablePolicyFuncTestApp.inf
new file mode 100644
index 000000000000..9ad277a547c2
--- /dev/null
+++ b/MdeModulePkg/Test/ShellTest/VariablePolicyFuncTestApp/VariablePolicyF=
uncTestApp.inf
@@ -0,0 +1,42 @@
+## @file=0D
+# Uefi Shell based Application that unit tests the Variable Policy Protoco=
l=0D
+#=0D
+# Copyright (c) Microsoft Corporation.=0D
+# SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+##=0D
+=0D
+[Defines]=0D
+ INF_VERSION =3D 0x00010005=0D
+ BASE_NAME =3D VariablePolicyFuncTestApp=0D
+ FILE_GUID =3D B653C4C3-3FCC-4B6C-8051-5F692AEAECBA=
=0D
+ MODULE_TYPE =3D UEFI_APPLICATION=0D
+ VERSION_STRING =3D 1.0=0D
+ ENTRY_POINT =3D UefiMain=0D
+=0D
+#=0D
+# The following information is for reference only and not required by the =
build tools.=0D
+#=0D
+# VALID_ARCHITECTURES =3D X64 AARCH64=0D
+#=0D
+=0D
+[Sources]=0D
+ VariablePolicyFuncTestApp.c=0D
+=0D
+[Packages]=0D
+ MdePkg/MdePkg.dec=0D
+ MdeModulePkg/MdeModulePkg.dec=0D
+ UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec=0D
+=0D
+[LibraryClasses]=0D
+ UefiApplicationEntryPoint=0D
+ BaseLib=0D
+ UnitTestLib=0D
+ UnitTestBootLib=0D
+ PrintLib=0D
+ UefiBootServicesTableLib=0D
+ UefiRuntimeServicesTableLib=0D
+ MemoryAllocationLib=0D
+ VariablePolicyHelperLib=0D
+=0D
+[Protocols]=0D
+ gEdkiiVariablePolicyProtocolGuid=0D
--=20
2.26.2.windows.1.8.g01c50adf56.20200515075929


[PATCH v5 12/14] MdeModulePkg: Change TCG MOR variables to use VariablePolicy

Bret Barkelew <bret@...>
 

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

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/M=
deModulePkg/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.=0D
=0D
Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>=0D
+Copyright (c) Microsoft Corporation.=0D
SPDX-License-Identifier: BSD-2-Clause-Patent=0D
=0D
**/=0D
@@ -17,7 +18,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <Library/BaseMemoryLib.h>=0D
#include "Variable.h"=0D
=0D
-extern EDKII_VARIABLE_LOCK_PROTOCOL mVariableLock;=0D
+#include <Protocol/VariablePolicy.h>=0D
+#include <Library/VariablePolicyHelperLib.h>=0D
=0D
/**=0D
This service is an MOR/MorLock checker handler for the SetVariable().=0D
@@ -77,11 +79,6 @@ MorLockInit (
NULL // Data=0D
);=0D
=0D
- //=0D
- // Need set this variable to be read-only to prevent other module set it=
.=0D
- //=0D
- VariableLockRequestToLock (&mVariableLock, MEMORY_OVERWRITE_REQUEST_CONT=
ROL_LOCK_NAME, &gEfiMemoryOverwriteRequestControlLockGuid);=0D
-=0D
//=0D
// The MOR variable can effectively improve platform security only when =
the=0D
// MorLock variable protects the MOR variable. In turn MorLock cannot be=
made=0D
@@ -99,11 +96,6 @@ MorLockInit (
0, // DataSize=0D
NULL // Data=0D
);=0D
- VariableLockRequestToLock (=0D
- &mVariableLock,=0D
- MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME,=0D
- &gEfiMemoryOverwriteControlDataGuid=0D
- );=0D
=0D
return EFI_SUCCESS;=0D
}=0D
@@ -118,7 +110,39 @@ MorLockInitAtEndOfDxe (
VOID=0D
)=0D
{=0D
- //=0D
- // Do nothing.=0D
- //=0D
+ EFI_STATUS Status;=0D
+ EDKII_VARIABLE_POLICY_PROTOCOL *VariablePolicy;=0D
+=0D
+ // First, we obviously need to locate the VariablePolicy protocol.=0D
+ Status =3D gBS->LocateProtocol( &gEdkiiVariablePolicyProtocolGuid, NULL,=
(VOID**)&VariablePolicy );=0D
+ if (EFI_ERROR( Status )) {=0D
+ DEBUG(( DEBUG_ERROR, "%a - Could not locate VariablePolicy protocol! %=
r\n", __FUNCTION__, Status ));=0D
+ return;=0D
+ }=0D
+=0D
+ // If we're successful, go ahead and set the policies to protect the tar=
get variables.=0D
+ Status =3D RegisterBasicVariablePolicy( VariablePolicy,=0D
+ &gEfiMemoryOverwriteRequestControl=
LockGuid,=0D
+ MEMORY_OVERWRITE_REQUEST_CONTROL_L=
OCK_NAME,=0D
+ VARIABLE_POLICY_NO_MIN_SIZE,=0D
+ VARIABLE_POLICY_NO_MAX_SIZE,=0D
+ VARIABLE_POLICY_NO_MUST_ATTR,=0D
+ VARIABLE_POLICY_NO_CANT_ATTR,=0D
+ VARIABLE_POLICY_TYPE_LOCK_NOW );=0D
+ if (EFI_ERROR( Status )) {=0D
+ DEBUG(( DEBUG_ERROR, "%a - Could not lock variable %s! %r\n", __FUNCTI=
ON__, MEMORY_OVERWRITE_REQUEST_CONTROL_LOCK_NAME, Status ));=0D
+ }=0D
+ Status =3D RegisterBasicVariablePolicy( VariablePolicy,=0D
+ &gEfiMemoryOverwriteControlDataGui=
d,=0D
+ MEMORY_OVERWRITE_REQUEST_VARIABLE_=
NAME,=0D
+ VARIABLE_POLICY_NO_MIN_SIZE,=0D
+ VARIABLE_POLICY_NO_MAX_SIZE,=0D
+ VARIABLE_POLICY_NO_MUST_ATTR,=0D
+ VARIABLE_POLICY_NO_CANT_ATTR,=0D
+ VARIABLE_POLICY_TYPE_LOCK_NOW );=0D
+ if (EFI_ERROR( Status )) {=0D
+ DEBUG(( DEBUG_ERROR, "%a - Could not lock variable %s! %r\n", __FUNCTI=
ON__, MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME, Status ));=0D
+ }=0D
+=0D
+ return;=0D
}=0D
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/TcgMorLockSmm.c b/M=
deModulePkg/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"=0D
=0D
#include <Protocol/VariablePolicy.h>=0D
-=0D
+#include <Library/VariablePolicyHelperLib.h>=0D
#include <Library/VariablePolicyLib.h>=0D
=0D
typedef struct {=0D
@@ -422,6 +422,8 @@ MorLockInitAtEndOfDxe (
{=0D
UINTN MorSize;=0D
EFI_STATUS MorStatus;=0D
+ EFI_STATUS Status;=0D
+ VARIABLE_POLICY_ENTRY *NewPolicy;=0D
=0D
if (!mMorLockInitializationRequired) {=0D
//=0D
@@ -494,11 +496,25 @@ MorLockInitAtEndOfDxe (
// The MOR variable is absent; the platform firmware does not support it=
.=0D
// Lock the variable so that no other module may create it.=0D
//=0D
- VariableLockRequestToLock (=0D
- NULL, // This=0D
- MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME,=0D
- &gEfiMemoryOverwriteControlDataGuid=0D
- );=0D
+ NewPolicy =3D NULL;=0D
+ Status =3D CreateBasicVariablePolicy( &gEfiMemoryOverwriteControlDataGui=
d,=0D
+ MEMORY_OVERWRITE_REQUEST_VARIABLE_NA=
ME,=0D
+ VARIABLE_POLICY_NO_MIN_SIZE,=0D
+ VARIABLE_POLICY_NO_MAX_SIZE,=0D
+ VARIABLE_POLICY_NO_MUST_ATTR,=0D
+ VARIABLE_POLICY_NO_CANT_ATTR,=0D
+ VARIABLE_POLICY_TYPE_LOCK_NOW,=0D
+ &NewPolicy );=0D
+ if (!EFI_ERROR( Status )) {=0D
+ Status =3D RegisterVariablePolicy( NewPolicy );=0D
+ }=0D
+ if (EFI_ERROR( Status )) {=0D
+ DEBUG(( DEBUG_ERROR, "%a - Failed to lock variable %s! %r\n", __FUNCTI=
ON__, MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME, Status ));=0D
+ ASSERT_EFI_ERROR( Status );=0D
+ }=0D
+ if (NewPolicy !=3D NULL) {=0D
+ FreePool( NewPolicy );=0D
+ }=0D
=0D
//=0D
// Delete the MOR Control Lock variable too (should it exists for some=0D
@@ -514,9 +530,23 @@ MorLockInitAtEndOfDxe (
);=0D
mMorLockPassThru =3D FALSE;=0D
=0D
- VariableLockRequestToLock (=0D
- NULL, // This=0D
- MEMORY_OVERWRITE_REQUEST_CONTROL_LOCK_NAME,=0D
- &gEfiMemoryOverwriteRequestControlLockGuid=0D
- );=0D
+ NewPolicy =3D NULL;=0D
+ Status =3D CreateBasicVariablePolicy( &gEfiMemoryOverwriteRequestControl=
LockGuid,=0D
+ MEMORY_OVERWRITE_REQUEST_CONTROL_LOC=
K_NAME,=0D
+ VARIABLE_POLICY_NO_MIN_SIZE,=0D
+ VARIABLE_POLICY_NO_MAX_SIZE,=0D
+ VARIABLE_POLICY_NO_MUST_ATTR,=0D
+ VARIABLE_POLICY_NO_CANT_ATTR,=0D
+ VARIABLE_POLICY_TYPE_LOCK_NOW,=0D
+ &NewPolicy );=0D
+ if (!EFI_ERROR( Status )) {=0D
+ Status =3D RegisterVariablePolicy( NewPolicy );=0D
+ }=0D
+ if (EFI_ERROR( Status )) {=0D
+ DEBUG(( DEBUG_ERROR, "%a - Failed to lock variable %s! %r\n", __FUNCTI=
ON__, MEMORY_OVERWRITE_REQUEST_CONTROL_LOCK_NAME, Status ));=0D
+ ASSERT_EFI_ERROR( Status );=0D
+ }=0D
+ if (NewPolicy !=3D NULL) {=0D
+ FreePool( NewPolicy );=0D
+ }=0D
}=0D
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=0D
VarCheckLib=0D
VariablePolicyLib=0D
+ VariablePolicyHelperLib=0D
=0D
[Protocols]=0D
gEfiFirmwareVolumeBlockProtocolGuid ## CONSUMES=0D
@@ -80,6 +81,7 @@ [Protocols]
gEfiVariableWriteArchProtocolGuid ## PRODUCES=0D
gEfiVariableArchProtocolGuid ## PRODUCES=0D
gEdkiiVariableLockProtocolGuid ## PRODUCES=0D
+ gEdkiiVariablePolicyProtocolGuid ## CONSUMES=0D
gEdkiiVarCheckProtocolGuid ## PRODUCES=0D
=0D
[Guids]=0D
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneM=
m.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=0D
VarCheckLib=0D
VariablePolicyLib=0D
+ VariablePolicyHelperLib=0D
=0D
[Protocols]=0D
gEfiSmmFirmwareVolumeBlockProtocolGuid ## CONSUMES=0D
--=20
2.26.2.windows.1.8.g01c50adf56.20200515075929


[PATCH v5 10/14] MdeModulePkg: Allow VariablePolicy state to delete protected variables

Bret Barkelew <bret@...>
 

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

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/M=
deModulePkg/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 MemoryOverwriteRequestControlLo=
ck.=0D
=0D
Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>=0D
+Copyright (c) Microsoft Corporation.=0D
SPDX-License-Identifier: BSD-2-Clause-Patent=0D
=0D
**/=0D
@@ -17,6 +18,10 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <Library/BaseMemoryLib.h>=0D
#include "Variable.h"=0D
=0D
+#include <Protocol/VariablePolicy.h>=0D
+=0D
+#include <Library/VariablePolicyLib.h>=0D
+=0D
typedef struct {=0D
CHAR16 *VariableName;=0D
EFI_GUID *VendorGuid;=0D
@@ -341,6 +346,11 @@ SetVariableCheckHandlerMor (
return EFI_SUCCESS;=0D
}=0D
=0D
+ // Permit deletion when policy is disabled.=0D
+ if (!IsVariablePolicyEnabled() && ((Attributes =3D=3D 0) || (DataSize =
=3D=3D 0))) {=0D
+ return EFI_SUCCESS;=0D
+ }=0D
+=0D
//=0D
// MorLock variable=0D
//=0D
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneM=
m.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 @@
#=0D
# Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.<BR>=0D
# Copyright (c) 2018, Linaro, Ltd. All rights reserved.<BR>=0D
+# Copyright (c) Microsoft Corporation.=0D
# SPDX-License-Identifier: BSD-2-Clause-Patent=0D
#=0D
##=0D
@@ -74,6 +75,7 @@ [LibraryClasses]
StandaloneMmDriverEntryPoint=0D
SynchronizationLib=0D
VarCheckLib=0D
+ VariablePolicyLib=0D
=0D
[Protocols]=0D
gEfiSmmFirmwareVolumeBlockProtocolGuid ## CONSUMES=0D
--=20
2.26.2.windows.1.8.g01c50adf56.20200515075929


[PATCH v5 07/14] ArmVirtPkg: Add VariablePolicy engine to ArmVirtPkg platform

Bret Barkelew <bret@...>
 

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

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.=0D
# Copyright (c) 2014, Linaro Limited. All rights reserved.=0D
# Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.=0D
+# Copyright (c) Microsoft Corporation.=0D
#=0D
# SPDX-License-Identifier: BSD-2-Clause-Patent=0D
#=0D
@@ -173,6 +174,8 @@ [LibraryClasses.common]
AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLib=
Null.inf=0D
!endif=0D
VarCheckLib|MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf=0D
+ VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyL=
ib.inf=0D
+ VariablePolicyHelperLib|MdeModulePkg/Library/VariablePolicyHelperLib/Var=
iablePolicyHelperLib.inf=0D
UefiBootManagerLib|MdeModulePkg/Library/UefiBootManagerLib/UefiBootManag=
erLib.inf=0D
=0D
ReportStatusCodeLib|MdePkg/Library/BaseReportStatusCodeLibNull/BaseRepor=
tStatusCodeLibNull.inf=0D
@@ -246,6 +249,7 @@ [LibraryClasses.common.DXE_RUNTIME_DRIVER]
!if $(TARGET) !=3D RELEASE=0D
DebugLib|MdePkg/Library/DxeRuntimeDebugLibSerialPort/DxeRuntimeDebugLibS=
erialPort.inf=0D
!endif=0D
+ VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyL=
ibRuntimeDxe.inf=0D
=0D
!if $(SECURE_BOOT_ENABLE) =3D=3D TRUE=0D
BaseCryptLib|CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf=0D
--=20
2.26.2.windows.1.8.g01c50adf56.20200515075929


[PATCH v5 04/14] MdeModulePkg: Define the VarCheckPolicyLib and SMM interface

Bret Barkelew <bret@...>
 

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

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


[PATCH v5 03/14] MdeModulePkg: Define the VariablePolicyHelperLib

Bret Barkelew <bret@...>
 

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

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


[PATCH v5 01/14] MdeModulePkg: Define the VariablePolicy protocol interface

Bret Barkelew <bret@...>
 

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

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=0D
+=0D
+This protocol allows communication with Variable Policy Engine.=0D
+=0D
+Copyright (c) Microsoft Corporation.=0D
+SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+**/=0D
+=0D
+#ifndef __EDKII_VARIABLE_POLICY_PROTOCOL__=0D
+#define __EDKII_VARIABLE_POLICY_PROTOCOL__=0D
+=0D
+#define EDKII_VARIABLE_POLICY_PROTOCOL_REVISION 0x0000000000010000=0D
+=0D
+#define EDKII_VARIABLE_POLICY_PROTOCOL_GUID \=0D
+ { \=0D
+ 0x81D1675C, 0x86F6, 0x48DF, { 0xBD, 0x95, 0x9A, 0x6E, 0x4F, 0x09, 0x25=
, 0xC3 } \=0D
+ }=0D
+=0D
+#define VARIABLE_POLICY_ENTRY_REVISION 0x00010000=0D
+=0D
+#pragma pack(push, 1)=0D
+typedef struct {=0D
+ UINT32 Version;=0D
+ UINT16 Size;=0D
+ UINT16 OffsetToName;=0D
+ EFI_GUID Namespace;=0D
+ UINT32 MinSize;=0D
+ UINT32 MaxSize;=0D
+ UINT32 AttributesMustHave;=0D
+ UINT32 AttributesCantHave;=0D
+ UINT8 LockPolicyType;=0D
+ UINT8 Padding[3];=0D
+ // UINT8 LockPolicy[]; // Variable Length Field=0D
+ // CHAR16 Name[] // Variable Length Field=0D
+} VARIABLE_POLICY_ENTRY;=0D
+=0D
+#define VARIABLE_POLICY_NO_MIN_SIZE 0=0D
+#define VARIABLE_POLICY_NO_MAX_SIZE MAX_UINT32=0D
+#define VARIABLE_POLICY_NO_MUST_ATTR 0=0D
+#define VARIABLE_POLICY_NO_CANT_ATTR 0=0D
+=0D
+#define VARIABLE_POLICY_TYPE_NO_LOCK 0=0D
+#define VARIABLE_POLICY_TYPE_LOCK_NOW 1=0D
+#define VARIABLE_POLICY_TYPE_LOCK_ON_CREATE 2=0D
+#define VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE 3=0D
+=0D
+typedef struct {=0D
+ EFI_GUID Namespace;=0D
+ UINT8 Value;=0D
+ UINT8 Padding;=0D
+ // CHAR16 Name[]; // Variable Length Field=0D
+} VARIABLE_LOCK_ON_VAR_STATE_POLICY;=0D
+#pragma pack(pop)=0D
+=0D
+/**=0D
+ This API function disables the variable policy enforcement. If it's=0D
+ already been called once, will return EFI_ALREADY_STARTED.=0D
+=0D
+ @retval EFI_SUCCESS=0D
+ @retval EFI_ALREADY_STARTED Has already been called once this boot=
.=0D
+ @retval EFI_WRITE_PROTECTED Interface has been locked until reboot=
.=0D
+ @retval EFI_WRITE_PROTECTED Interface option is disabled by platfo=
rm PCD.=0D
+=0D
+**/=0D
+typedef=0D
+EFI_STATUS=0D
+(EFIAPI *DISABLE_VARIABLE_POLICY)(=0D
+ VOID=0D
+ );=0D
+=0D
+/**=0D
+ This API function returns whether or not the policy engine is=0D
+ currently being enforced.=0D
+=0D
+ @param[out] State Pointer to a return value for whether the poli=
cy enforcement=0D
+ is currently enabled.=0D
+=0D
+ @retval EFI_SUCCESS=0D
+ @retval Others An error has prevented this command from compl=
eting.=0D
+=0D
+**/=0D
+typedef=0D
+EFI_STATUS=0D
+(EFIAPI *IS_VARIABLE_POLICY_ENABLED)(=0D
+ OUT BOOLEAN *State=0D
+ );=0D
+=0D
+/**=0D
+ This API function validates and registers a new policy with=0D
+ the policy enforcement engine.=0D
+=0D
+ @param[in] NewPolicy Pointer to the incoming policy structure.=0D
+=0D
+ @retval EFI_SUCCESS=0D
+ @retval EFI_INVALID_PARAMETER NewPolicy is NULL or is internally i=
nconsistent.=0D
+ @retval EFI_ALREADY_STARTED An identical matching policy already=
exists.=0D
+ @retval EFI_WRITE_PROTECTED The interface has been locked until =
the next reboot.=0D
+ @retval EFI_ABORTED A calculation error has prevented th=
is function from completing.=0D
+ @retval EFI_OUT_OF_RESOURCES Cannot grow the table to hold any mo=
re policies.=0D
+=0D
+**/=0D
+typedef=0D
+EFI_STATUS=0D
+(EFIAPI *REGISTER_VARIABLE_POLICY)(=0D
+ IN CONST VARIABLE_POLICY_ENTRY *PolicyEntry=0D
+ );=0D
+=0D
+/**=0D
+ This API function will dump the entire contents of the variable policy t=
able.=0D
+=0D
+ Similar to GetVariable, the first call can be made with a 0 size and it =
will return=0D
+ the size of the buffer required to hold the entire table.=0D
+=0D
+ @param[out] Policy Pointer to the policy buffer. Can be NULL if Siz=
e is 0.=0D
+ @param[in,out] Size On input, the size of the output buffer. On outp=
ut, the size=0D
+ of the data returned.=0D
+=0D
+ @retval EFI_SUCCESS Policy data is in the output buffer =
and Size has been updated.=0D
+ @retval EFI_INVALID_PARAMETER Size is NULL, or Size is non-zero an=
d Policy is NULL.=0D
+ @retval EFI_BUFFER_TOO_SMALL Size is insufficient to hold policy.=
Size updated with required size.=0D
+=0D
+**/=0D
+typedef=0D
+EFI_STATUS=0D
+(EFIAPI *DUMP_VARIABLE_POLICY)(=0D
+ IN OUT UINT8 *Policy,=0D
+ IN OUT UINT32 *Size=0D
+ );=0D
+=0D
+/**=0D
+ This API function locks the interface so that no more policy updates=0D
+ can be performed or changes made to the enforcement until the next boot.=
=0D
+=0D
+ @retval EFI_SUCCESS=0D
+ @retval Others An error has prevented this command from compl=
eting.=0D
+=0D
+**/=0D
+typedef=0D
+EFI_STATUS=0D
+(EFIAPI *LOCK_VARIABLE_POLICY)(=0D
+ VOID=0D
+ );=0D
+=0D
+typedef struct {=0D
+ UINT64 Revision;=0D
+ DISABLE_VARIABLE_POLICY DisableVariablePolicy;=0D
+ IS_VARIABLE_POLICY_ENABLED IsVariablePolicyEnabled;=0D
+ REGISTER_VARIABLE_POLICY RegisterVariablePolicy;=0D
+ DUMP_VARIABLE_POLICY DumpVariablePolicy;=0D
+ LOCK_VARIABLE_POLICY LockVariablePolicy;=0D
+} _EDKII_VARIABLE_POLICY_PROTOCOL;=0D
+=0D
+typedef _EDKII_VARIABLE_POLICY_PROTOCOL EDKII_VARIABLE_POLICY_PROTOCOL;=0D
+=0D
+extern EFI_GUID gEdkiiVariablePolicyProtocolGuid;=0D
+=0D
+#endif=0D
diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec
index 4f44af694862..2e0461b87c32 100644
--- a/MdeModulePkg/MdeModulePkg.dec
+++ b/MdeModulePkg/MdeModulePkg.dec
@@ -8,7 +8,7 @@
# Copyright (c) 2016, Linaro Ltd. All rights reserved.<BR>=0D
# (C) Copyright 2016 - 2019 Hewlett Packard Enterprise Development LP<BR>=
=0D
# Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>=0D
-# Copyright (c) 2016, Microsoft Corporation<BR>=0D
+# Copyright (c) Microsoft Corporation.<BR>=0D
# SPDX-License-Identifier: BSD-2-Clause-Patent=0D
#=0D
##=0D
@@ -624,6 +624,9 @@ [Protocols]
# 0x80000006 | Incorrect error code provided.=0D
#=0D
=0D
+ ## Include/Protocol/VariablePolicy.h=0D
+ gEdkiiVariablePolicyProtocolGuid =3D { 0x81D1675C, 0x86F6, 0x48DF, { 0xB=
D, 0x95, 0x9A, 0x6E, 0x4F, 0x09, 0x25, 0xC3 } }=0D
+=0D
[PcdsFeatureFlag]=0D
## Indicates if the platform can support update capsule across a system =
reset.<BR><BR>=0D
# TRUE - Supports update capsule across a system reset.<BR>=0D
@@ -1129,6 +1132,15 @@ [PcdsFixedAtBuild, PcdsPatchableInModule]
# @Prompt Variable storage size.=0D
gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize|0x10000|UINT32|0x300=
00005=0D
=0D
+ ## Toggle for whether the VariablePolicy engine should allow disabling.=
=0D
+ # The engine is enabled at power-on, but the interface allows the platfo=
rm to=0D
+ # disable enforcement for servicing flexibility. If this PCD is disabled=
, it will block the ability to=0D
+ # disable the enforcement and VariablePolicy enforcement will always be =
ON.=0D
+ # TRUE - VariablePolicy can be disabled by request through the interfa=
ce (until interface is locked)=0D
+ # FALSE - VariablePolicy interface will not accept requests to disable=
and is ALWAYS ON=0D
+ # @Prompt Allow VariablePolicy enforcement to be disabled.=0D
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAllowVariablePolicyEnforcementDisable|=
FALSE|BOOLEAN|0x30000020=0D
+=0D
## FFS filename to find the ACPI tables.=0D
# @Prompt FFS name of ACPI tables storage.=0D
gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiTableStorageFile|{ 0x25, 0x4e, 0x3=
7, 0x7e, 0x01, 0x8e, 0xee, 0x4f, 0x87, 0xf2, 0x39, 0xc, 0x23, 0xc6, 0x6, 0x=
cd }|VOID*|0x30000016=0D
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 @@
=0D
#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdVariableStoreSize_HELP #lan=
guage en-US "The size of volatile buffer. This buffer is used to store VOLA=
TILE attribute variables."=0D
=0D
+#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdAllowVariablePolicyEnforceme=
ntDisable_PROMPT #language en-US "Allow VariablePolicy enforcement to be d=
isabled."=0D
+=0D
+#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdAllowVariablePolicyEnforceme=
ntDisable_HELP #language en-US "If this PCD is disabled, it will block the=
ability to<BR>\n"=0D
+ =
"disable the enforcement and VariablePolicy=
enforcement will always be ON.<BR>\n"=0D
+ =
"TRUE - VariablePolicy can be disabled by r=
equest through the interface (until interface is locked)<BR>\n"=0D
+ =
"FALSE - VariablePolicy interface will not =
accept requests to disable and is ALWAYS ON<BR>\n"=0D
+=0D
#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdAcpiTableStorageFile_PROMPT =
#language en-US "FFS name of ACPI tables storage"=0D
=0D
#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdAcpiTableStorageFile_HELP #=
language en-US "FFS filename to find the ACPI tables."=0D
--=20
2.26.2.windows.1.8.g01c50adf56.20200515075929


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

Bret Barkelew <bret@...>
 

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

VariablePolicy is an updated interface to
replace VarLock and VarCheckProtocol.

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

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

Cc: Jian J Wang <jian.j.wang@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 =
| 813 +++++++
MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePoli=
cyUnitTest.c | 2436 ++++++++++++++++++++
MdeModulePkg/Include/Library/VariablePolicyLib.h =
| 207 ++
MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf =
| 44 +
MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.uni =
| 12 +
MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf =
| 51 +
MdeModulePkg/Library/VariablePolicyLib/VariablePolicyUnitTest/VariablePoli=
cyUnitTest.inf | 40 +
MdeModulePkg/MdeModulePkg.dec =
| 3 +
MdeModulePkg/MdeModulePkg.dsc =
| 5 +
MdeModulePkg/Test/MdeModulePkgHostTest.dsc =
| 11 +
12 files changed, 3753 insertions(+)

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


[PATCH v5 09/14] MdeModulePkg: Connect VariablePolicy business logic to VariableServices

Bret Barkelew <bret@...>
 

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

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/Mde=
ModulePkg/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.=0D
Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>=0D
(C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>=0D
+Copyright (c) Microsoft Corporation.=0D
SPDX-License-Identifier: BSD-2-Clause-Patent=0D
=0D
**/=0D
=0D
#include "Variable.h"=0D
=0D
+#include <Protocol/VariablePolicy.h>=0D
+#include <Library/VariablePolicyLib.h>=0D
+=0D
+EFI_STATUS=0D
+EFIAPI=0D
+ProtocolIsVariablePolicyEnabled (=0D
+ OUT BOOLEAN *State=0D
+ );=0D
+=0D
EFI_HANDLE mHandle =3D NULL;=0D
EFI_EVENT mVirtualAddressChangeEvent =3D NULL;=0D
VOID *mFtwRegistration =3D NULL;=0D
VOID ***mVarCheckAddressPointer =3D NULL;=0D
UINTN mVarCheckAddressPointerCount =3D 0;=0D
EDKII_VARIABLE_LOCK_PROTOCOL mVariableLock =3D { Varia=
bleLockRequestToLock };=0D
+EDKII_VARIABLE_POLICY_PROTOCOL mVariablePolicyProtocol =3D { EDKII=
_VARIABLE_POLICY_PROTOCOL_REVISION,=0D
+ Disabl=
eVariablePolicy,=0D
+ Protoc=
olIsVariablePolicyEnabled,=0D
+ Regist=
erVariablePolicy,=0D
+ DumpVa=
riablePolicy,=0D
+ LockVa=
riablePolicy };=0D
EDKII_VAR_CHECK_PROTOCOL mVarCheck =3D { VarCh=
eckRegisterSetVariableCheckHandler,=0D
VarChe=
ckVariablePropertySet,=0D
VarChe=
ckVariablePropertyGet };=0D
@@ -303,6 +319,8 @@ OnReadyToBoot (
}=0D
}=0D
=0D
+ ASSERT_EFI_ERROR (LockVariablePolicy ());=0D
+=0D
gBS->CloseEvent (Event);=0D
}=0D
=0D
@@ -466,6 +484,28 @@ FtwNotificationEvent (
}=0D
=0D
=0D
+/**=0D
+ This API function returns whether or not the policy engine is=0D
+ currently being enforced.=0D
+=0D
+ @param[out] State Pointer to a return value for whether the poli=
cy enforcement=0D
+ is currently enabled.=0D
+=0D
+ @retval EFI_SUCCESS=0D
+ @retval Others An error has prevented this command from compl=
eting.=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+ProtocolIsVariablePolicyEnabled (=0D
+ OUT BOOLEAN *State=0D
+ )=0D
+{=0D
+ *State =3D IsVariablePolicyEnabled ();=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+=0D
/**=0D
Variable Driver main entry point. The Variable driver places the 4 EFI=0D
runtime services in the EFI System Table and installs arch protocols=0D
@@ -576,6 +616,19 @@ VariableServiceInitialize (
);=0D
ASSERT_EFI_ERROR (Status);=0D
=0D
+ // Register and initialize the VariablePolicy engine.=0D
+ Status =3D InitVariablePolicyLib (VariableServiceGetVariable);=0D
+ ASSERT_EFI_ERROR (Status);=0D
+ Status =3D VarCheckRegisterSetVariableCheckHandler (ValidateSetVariable)=
;=0D
+ ASSERT_EFI_ERROR (Status);=0D
+ Status =3D gBS->InstallMultipleProtocolInterfaces (=0D
+ &mHandle,=0D
+ &gEdkiiVariablePolicyProtocolGuid,=0D
+ &mVariablePolicyProtocol,=0D
+ NULL=0D
+ );=0D
+ ASSERT_EFI_ERROR (Status);=0D
+=0D
return EFI_SUCCESS;=0D
}=0D
=0D
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariablePolicySmmDx=
e.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=0D
+This protocol allows communication with Variable Policy Engine.=0D
+=0D
+Copyright (c) Microsoft Corporation.=0D
+SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+=0D
+**/=0D
+=0D
+#include <Library/BaseLib.h>=0D
+#include <Library/UefiLib.h>=0D
+#include <Library/DebugLib.h>=0D
+#include <Library/SafeIntLib.h>=0D
+#include <Library/UefiBootServicesTableLib.h>=0D
+#include <Library/BaseMemoryLib.h>=0D
+#include <Library/MemoryAllocationLib.h>=0D
+=0D
+#include <Protocol/VariablePolicy.h>=0D
+#include <Protocol/MmCommunication2.h>=0D
+=0D
+#include <Guid/VarCheckPolicyMmi.h>=0D
+=0D
+#include "Variable.h"=0D
+=0D
+EDKII_VARIABLE_POLICY_PROTOCOL mVariablePolicyProtocol;=0D
+EFI_MM_COMMUNICATION2_PROTOCOL *mMmCommunication;=0D
+=0D
+VOID *mMmCommunicationBuffer;=0D
+UINTN mMmCommunicationBufferSize;=0D
+EFI_LOCK mMmCommunicationLock;=0D
+=0D
+/**=0D
+ Internal helper function to consolidate communication method.=0D
+=0D
+ @param[in,out] CommBuffer=0D
+ @param[in,out] CommSize Size of the CommBuffer.=0D
+=0D
+ @retval EFI_STATUS Result from communication method.=0D
+=0D
+**/=0D
+STATIC=0D
+EFI_STATUS=0D
+InternalMmCommunicate (=0D
+ IN OUT VOID *CommBuffer,=0D
+ IN OUT UINTN *CommSize=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ if (CommBuffer =3D=3D NULL || CommSize =3D=3D NULL) {=0D
+ return EFI_INVALID_PARAMETER;=0D
+ }=0D
+ Status =3D mMmCommunication->Communicate (mMmCommunication, CommBuffer, =
CommBuffer, CommSize);=0D
+ return Status;=0D
+}=0D
+=0D
+=0D
+/**=0D
+ This API function disables the variable policy enforcement. If it's=0D
+ already been called once, will return EFI_ALREADY_STARTED.=0D
+=0D
+ @retval EFI_SUCCESS=0D
+ @retval EFI_ALREADY_STARTED Has already been called once this boot=
.=0D
+ @retval EFI_WRITE_PROTECTED Interface has been locked until reboot=
.=0D
+ @retval EFI_WRITE_PROTECTED Interface option is disabled by platfo=
rm PCD.=0D
+=0D
+**/=0D
+STATIC=0D
+EFI_STATUS=0D
+EFIAPI=0D
+ProtocolDisableVariablePolicy (=0D
+ VOID=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ EFI_MM_COMMUNICATE_HEADER *CommHeader;=0D
+ VAR_CHECK_POLICY_COMM_HEADER *PolicyHeader;=0D
+ UINTN BufferSize;=0D
+=0D
+ // Check the PCD for convenience.=0D
+ // This would also be rejected by the lib, but why go to MM if we don't =
have to?=0D
+ if (!PcdGetBool (PcdAllowVariablePolicyEnforcementDisable)) {=0D
+ return EFI_WRITE_PROTECTED;=0D
+ }=0D
+=0D
+ AcquireLockOnlyAtBootTime (&mMmCommunicationLock);=0D
+=0D
+ // Set up the MM communication.=0D
+ BufferSize =3D mMmCommunicationBufferSize;=0D
+ CommHeader =3D mMmCommunicationBuffer;=0D
+ PolicyHeader =3D (VAR_CHECK_POLICY_COMM_HEADER*)&CommHeader->Data;=0D
+ CopyGuid( &CommHeader->HeaderGuid, &gVarCheckPolicyLibMmiHandlerGuid );=
=0D
+ CommHeader->MessageLength =3D BufferSize;=0D
+ PolicyHeader->Signature =3D VAR_CHECK_POLICY_COMM_SIG;=0D
+ PolicyHeader->Revision =3D VAR_CHECK_POLICY_COMM_REVISION;=0D
+ PolicyHeader->Command =3D VAR_CHECK_POLICY_COMMAND_DISABLE;=0D
+=0D
+ Status =3D InternalMmCommunicate (CommHeader, &BufferSize);=0D
+ DEBUG(( DEBUG_VERBOSE, "%a - MmCommunication returned %r.\n", __FUNCTION=
__, Status ));=0D
+=0D
+ ReleaseLockOnlyAtBootTime (&mMmCommunicationLock);=0D
+=0D
+ return (EFI_ERROR( Status )) ? Status : PolicyHeader->Result;=0D
+}=0D
+=0D
+=0D
+/**=0D
+ This API function returns whether or not the policy engine is=0D
+ currently being enforced.=0D
+=0D
+ @param[out] State Pointer to a return value for whether the poli=
cy enforcement=0D
+ is currently enabled.=0D
+=0D
+ @retval EFI_SUCCESS=0D
+ @retval Others An error has prevented this command from compl=
eting.=0D
+=0D
+**/=0D
+STATIC=0D
+EFI_STATUS=0D
+EFIAPI=0D
+ProtocolIsVariablePolicyEnabled (=0D
+ OUT BOOLEAN *State=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ EFI_MM_COMMUNICATE_HEADER *CommHeader;=0D
+ VAR_CHECK_POLICY_COMM_HEADER *PolicyHeader;=0D
+ VAR_CHECK_POLICY_COMM_IS_ENABLED_PARAMS *CommandParams;=0D
+ UINTN BufferSize;=0D
+=0D
+ if (State =3D=3D NULL) {=0D
+ return EFI_INVALID_PARAMETER;=0D
+ }=0D
+=0D
+ AcquireLockOnlyAtBootTime (&mMmCommunicationLock);=0D
+=0D
+ // Set up the MM communication.=0D
+ BufferSize =3D mMmCommunicationBufferSize;=0D
+ CommHeader =3D mMmCommunicationBuffer;=0D
+ PolicyHeader =3D (VAR_CHECK_POLICY_COMM_HEADER*)&CommHeader->Data;=0D
+ CommandParams =3D (VAR_CHECK_POLICY_COMM_IS_ENABLED_PARAMS*)(PolicyHeade=
r + 1);=0D
+ CopyGuid( &CommHeader->HeaderGuid, &gVarCheckPolicyLibMmiHandlerGuid );=
=0D
+ CommHeader->MessageLength =3D BufferSize;=0D
+ PolicyHeader->Signature =3D VAR_CHECK_POLICY_COMM_SIG;=0D
+ PolicyHeader->Revision =3D VAR_CHECK_POLICY_COMM_REVISION;=0D
+ PolicyHeader->Command =3D VAR_CHECK_POLICY_COMMAND_IS_ENABLED;=0D
+=0D
+ Status =3D InternalMmCommunicate (CommHeader, &BufferSize);=0D
+ DEBUG(( DEBUG_VERBOSE, "%a - MmCommunication returned %r.\n", __FUNCTION=
__, Status ));=0D
+=0D
+ if (!EFI_ERROR( Status )) {=0D
+ Status =3D PolicyHeader->Result;=0D
+ *State =3D CommandParams->State;=0D
+ }=0D
+=0D
+ ReleaseLockOnlyAtBootTime (&mMmCommunicationLock);=0D
+=0D
+ return Status;=0D
+}=0D
+=0D
+=0D
+/**=0D
+ This API function validates and registers a new policy with=0D
+ the policy enforcement engine.=0D
+=0D
+ @param[in] NewPolicy Pointer to the incoming policy structure.=0D
+=0D
+ @retval EFI_SUCCESS=0D
+ @retval EFI_INVALID_PARAMETER NewPolicy is NULL or is internally i=
nconsistent.=0D
+ @retval EFI_ALREADY_STARTED An identical matching policy already=
exists.=0D
+ @retval EFI_WRITE_PROTECTED The interface has been locked until =
the next reboot.=0D
+ @retval EFI_UNSUPPORTED Policy enforcement has been disabled=
. No reason to add more policies.=0D
+ @retval EFI_ABORTED A calculation error has prevented th=
is function from completing.=0D
+ @retval EFI_OUT_OF_RESOURCES Cannot grow the table to hold any mo=
re policies.=0D
+=0D
+**/=0D
+STATIC=0D
+EFI_STATUS=0D
+EFIAPI=0D
+ProtocolRegisterVariablePolicy (=0D
+ IN CONST VARIABLE_POLICY_ENTRY *NewPolicy=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ EFI_MM_COMMUNICATE_HEADER *CommHeader;=0D
+ VAR_CHECK_POLICY_COMM_HEADER *PolicyHeader;=0D
+ VOID *PolicyBuffer;=0D
+ UINTN BufferSize;=0D
+ UINTN RequiredSize;=0D
+=0D
+ if (NewPolicy =3D=3D NULL) {=0D
+ return EFI_INVALID_PARAMETER;=0D
+ }=0D
+=0D
+ // First, make sure that the required size does not exceed the capabilit=
ies=0D
+ // of the MmCommunication buffer.=0D
+ RequiredSize =3D OFFSET_OF(EFI_MM_COMMUNICATE_HEADER, Data) + sizeof(VAR=
_CHECK_POLICY_COMM_HEADER);=0D
+ Status =3D SafeUintnAdd( RequiredSize, NewPolicy->Size, &RequiredSize );=
=0D
+ if (EFI_ERROR( Status ) || RequiredSize > mMmCommunicationBufferSize) {=
=0D
+ DEBUG(( DEBUG_ERROR, "%a - Policy too large for buffer! %r, %d > %d \n=
", __FUNCTION__,=0D
+ Status, RequiredSize, mMmCommunicationBufferSize ));=0D
+ return EFI_OUT_OF_RESOURCES;=0D
+ }=0D
+=0D
+ AcquireLockOnlyAtBootTime (&mMmCommunicationLock);=0D
+=0D
+ // Set up the MM communication.=0D
+ BufferSize =3D mMmCommunicationBufferSize;=0D
+ CommHeader =3D mMmCommunicationBuffer;=0D
+ PolicyHeader =3D (VAR_CHECK_POLICY_COMM_HEADER*)&CommHeader->Data;=0D
+ PolicyBuffer =3D (VOID*)(PolicyHeader + 1);=0D
+ CopyGuid( &CommHeader->HeaderGuid, &gVarCheckPolicyLibMmiHandlerGuid );=
=0D
+ CommHeader->MessageLength =3D BufferSize;=0D
+ PolicyHeader->Signature =3D VAR_CHECK_POLICY_COMM_SIG;=0D
+ PolicyHeader->Revision =3D VAR_CHECK_POLICY_COMM_REVISION;=0D
+ PolicyHeader->Command =3D VAR_CHECK_POLICY_COMMAND_REGISTER;=0D
+=0D
+ // Copy the policy into place. This copy is safe because we've already t=
ested above.=0D
+ CopyMem( PolicyBuffer, NewPolicy, NewPolicy->Size );=0D
+=0D
+ Status =3D InternalMmCommunicate (CommHeader, &BufferSize);=0D
+ DEBUG(( DEBUG_VERBOSE, "%a - MmCommunication returned %r.\n", __FUNCTION=
__, Status ));=0D
+=0D
+ ReleaseLockOnlyAtBootTime (&mMmCommunicationLock);=0D
+=0D
+ return (EFI_ERROR( Status )) ? Status : PolicyHeader->Result;=0D
+}=0D
+=0D
+=0D
+/**=0D
+ This helper function takes care of the overhead of formatting, sending, =
and interpreting=0D
+ the results for a single DumpVariablePolicy request.=0D
+=0D
+ @param[in] PageRequested The page of the paginated results from M=
M. 0 for metadata.=0D
+ @param[out] TotalSize The total size of the entire buffer. Ret=
urned as part of metadata.=0D
+ @param[out] PageSize The size of the current page being retur=
ned. Not valid as part of metadata.=0D
+ @param[out] HasMore A flag indicating whether there are more=
pages after this one.=0D
+ @param[out] Buffer The start of the current page from MM.=0D
+=0D
+ @retval EFI_SUCCESS Output params have been updated (eit=
her metadata or dump page).=0D
+ @retval EFI_INVALID_PARAMETER One of the output params is NULL.=0D
+ @retval Others Response from MM handler.=0D
+=0D
+**/=0D
+STATIC=0D
+EFI_STATUS=0D
+DumpVariablePolicyHelper (=0D
+ IN UINT32 PageRequested,=0D
+ OUT UINT32 *TotalSize,=0D
+ OUT UINT32 *PageSize,=0D
+ OUT BOOLEAN *HasMore,=0D
+ OUT UINT8 **Buffer=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ EFI_MM_COMMUNICATE_HEADER *CommHeader;=0D
+ VAR_CHECK_POLICY_COMM_HEADER *PolicyHeader;=0D
+ VAR_CHECK_POLICY_COMM_DUMP_PARAMS *CommandParams;=0D
+ UINTN BufferSize;=0D
+=0D
+ if (TotalSize =3D=3D NULL || PageSize =3D=3D NULL || HasMore =3D=3D NULL=
|| Buffer =3D=3D NULL) {=0D
+ return EFI_INVALID_PARAMETER;=0D
+ }=0D
+=0D
+ // Set up the MM communication.=0D
+ BufferSize =3D mMmCommunicationBufferSize;=0D
+ CommHeader =3D mMmCommunicationBuffer;=0D
+ PolicyHeader =3D (VAR_CHECK_POLICY_COMM_HEADER*)&CommHeader->Data;=0D
+ CommandParams =3D (VAR_CHECK_POLICY_COMM_DUMP_PARAMS*)(PolicyHeader + 1)=
;=0D
+ CopyGuid( &CommHeader->HeaderGuid, &gVarCheckPolicyLibMmiHandlerGuid );=
=0D
+ CommHeader->MessageLength =3D BufferSize;=0D
+ PolicyHeader->Signature =3D VAR_CHECK_POLICY_COMM_SIG;=0D
+ PolicyHeader->Revision =3D VAR_CHECK_POLICY_COMM_REVISION;=0D
+ PolicyHeader->Command =3D VAR_CHECK_POLICY_COMMAND_DUMP;=0D
+=0D
+ CommandParams->PageRequested =3D PageRequested;=0D
+=0D
+ Status =3D InternalMmCommunicate (CommHeader, &BufferSize);=0D
+ DEBUG(( DEBUG_VERBOSE, "%a - MmCommunication returned %r.\n", __FUNCTION=
__, Status ));=0D
+=0D
+ if (!EFI_ERROR( Status )) {=0D
+ Status =3D PolicyHeader->Result;=0D
+ *TotalSize =3D CommandParams->TotalSize;=0D
+ *PageSize =3D CommandParams->PageSize;=0D
+ *HasMore =3D CommandParams->HasMore;=0D
+ *Buffer =3D (UINT8*)(CommandParams + 1);=0D
+ }=0D
+=0D
+ return Status;=0D
+}=0D
+=0D
+=0D
+/**=0D
+ This API function will dump the entire contents of the variable policy t=
able.=0D
+=0D
+ Similar to GetVariable, the first call can be made with a 0 size and it =
will return=0D
+ the size of the buffer required to hold the entire table.=0D
+=0D
+ @param[out] Policy Pointer to the policy buffer. Can be NULL if Siz=
e is 0.=0D
+ @param[in,out] Size On input, the size of the output buffer. On outp=
ut, the size=0D
+ of the data returned.=0D
+=0D
+ @retval EFI_SUCCESS Policy data is in the output buffer =
and Size has been updated.=0D
+ @retval EFI_INVALID_PARAMETER Size is NULL, or Size is non-zero an=
d Policy is NULL.=0D
+ @retval EFI_BUFFER_TOO_SMALL Size is insufficient to hold policy.=
Size updated with required size.=0D
+=0D
+**/=0D
+STATIC=0D
+EFI_STATUS=0D
+EFIAPI=0D
+ProtocolDumpVariablePolicy (=0D
+ OUT UINT8 *Policy OPTIONAL,=0D
+ IN OUT UINT32 *Size=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ UINT8 *Source;=0D
+ UINT8 *Destination;=0D
+ UINT32 PolicySize;=0D
+ UINT32 PageSize;=0D
+ BOOLEAN HasMore;=0D
+ UINT32 PageIndex;=0D
+=0D
+ if (Size =3D=3D NULL || (*Size > 0 && Policy =3D=3D NULL)) {=0D
+ return EFI_INVALID_PARAMETER;=0D
+ }=0D
+=0D
+ AcquireLockOnlyAtBootTime (&mMmCommunicationLock);=0D
+=0D
+ // Repeat this whole process until we either have a failure case or get =
the entire buffer.=0D
+ do {=0D
+ // First, we must check the zero page to determine the buffer size and=
=0D
+ // reset the internal state.=0D
+ PolicySize =3D 0;=0D
+ PageSize =3D 0;=0D
+ HasMore =3D FALSE;=0D
+ Status =3D DumpVariablePolicyHelper (0, &PolicySize, &PageSize, &HasMo=
re, &Source);=0D
+ if (EFI_ERROR (Status)) {=0D
+ break;=0D
+ }=0D
+=0D
+ // If we're good, we can at least check the required size now.=0D
+ if (*Size < PolicySize) {=0D
+ *Size =3D PolicySize;=0D
+ Status =3D EFI_BUFFER_TOO_SMALL;=0D
+ break;=0D
+ }=0D
+=0D
+ // On further thought, let's update the size either way.=0D
+ *Size =3D PolicySize;=0D
+ // And get ready to ROCK.=0D
+ Destination =3D Policy;=0D
+=0D
+ // Keep looping and copying until we're either done or freak out.=0D
+ for (PageIndex =3D 1; !EFI_ERROR (Status) && HasMore && PageIndex < MA=
X_UINT32; PageIndex++) {=0D
+ Status =3D DumpVariablePolicyHelper (PageIndex, &PolicySize, &PageSi=
ze, &HasMore, &Source);=0D
+ if (!EFI_ERROR (Status)) {=0D
+ CopyMem (Destination, Source, PageSize);=0D
+ Destination +=3D PageSize;=0D
+ }=0D
+ }=0D
+=0D
+ // Next, we check to see whether=0D
+ } while (Status =3D=3D EFI_TIMEOUT);=0D
+=0D
+ ReleaseLockOnlyAtBootTime (&mMmCommunicationLock);=0D
+=0D
+ // There's currently no use for this, but it shouldn't be hard to implem=
ent.=0D
+ return Status;=0D
+}=0D
+=0D
+=0D
+/**=0D
+ This API function locks the interface so that no more policy updates=0D
+ can be performed or changes made to the enforcement until the next boot.=
=0D
+=0D
+ @retval EFI_SUCCESS=0D
+ @retval Others An error has prevented this command from compl=
eting.=0D
+=0D
+**/=0D
+STATIC=0D
+EFI_STATUS=0D
+EFIAPI=0D
+ProtocolLockVariablePolicy (=0D
+ VOID=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ EFI_MM_COMMUNICATE_HEADER *CommHeader;=0D
+ VAR_CHECK_POLICY_COMM_HEADER *PolicyHeader;=0D
+ UINTN BufferSize;=0D
+=0D
+ AcquireLockOnlyAtBootTime (&mMmCommunicationLock);=0D
+=0D
+ // Set up the MM communication.=0D
+ BufferSize =3D mMmCommunicationBufferSize;=0D
+ CommHeader =3D mMmCommunicationBuffer;=0D
+ PolicyHeader =3D (VAR_CHECK_POLICY_COMM_HEADER*)&CommHeader->Data;=0D
+ CopyGuid( &CommHeader->HeaderGuid, &gVarCheckPolicyLibMmiHandlerGuid );=
=0D
+ CommHeader->MessageLength =3D BufferSize;=0D
+ PolicyHeader->Signature =3D VAR_CHECK_POLICY_COMM_SIG;=0D
+ PolicyHeader->Revision =3D VAR_CHECK_POLICY_COMM_REVISION;=0D
+ PolicyHeader->Command =3D VAR_CHECK_POLICY_COMMAND_LOCK;=0D
+=0D
+ Status =3D InternalMmCommunicate (CommHeader, &BufferSize);=0D
+ DEBUG(( DEBUG_VERBOSE, "%a - MmCommunication returned %r.\n", __FUNCTION=
__, Status ));=0D
+=0D
+ ReleaseLockOnlyAtBootTime (&mMmCommunicationLock);=0D
+=0D
+ return (EFI_ERROR( Status )) ? Status : PolicyHeader->Result;=0D
+}=0D
+=0D
+=0D
+/**=0D
+ This helper function locates the shared comm buffer and assigns it to in=
put pointers.=0D
+=0D
+ @param[in,out] BufferSize On input, the minimum buffer size requir=
ed INCLUDING the MM communicate header.=0D
+ On output, the size of the matching buff=
er found.=0D
+ @param[out] LocatedBuffer A pointer to the matching buffer.=0D
+=0D
+ @retval EFI_SUCCESS=0D
+ @retval EFI_INVALID_PARAMETER One of the output pointers was NULL.=
=0D
+ @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate a comm=
buffer.=0D
+=0D
+**/=0D
+STATIC=0D
+EFI_STATUS=0D
+InitMmCommonCommBuffer (=0D
+ IN OUT UINTN *BufferSize,=0D
+ OUT VOID **LocatedBuffer=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+=0D
+ Status =3D EFI_SUCCESS;=0D
+=0D
+ // Make sure that we're working with good pointers.=0D
+ if (BufferSize =3D=3D NULL || LocatedBuffer =3D=3D NULL) {=0D
+ return EFI_INVALID_PARAMETER;=0D
+ }=0D
+=0D
+ // Allocate the runtime memory for the comm buffer.=0D
+ *LocatedBuffer =3D AllocateRuntimePool (*BufferSize);=0D
+ if (*LocatedBuffer =3D=3D NULL) {=0D
+ Status =3D EFI_OUT_OF_RESOURCES;=0D
+ *BufferSize =3D 0;=0D
+ }=0D
+=0D
+ EfiInitializeLock (&mMmCommunicationLock, TPL_NOTIFY);=0D
+=0D
+ return Status;=0D
+}=0D
+=0D
+=0D
+/**=0D
+ This helper is responsible for telemetry and any other actions that=0D
+ need to be taken if the VariablePolicy fails to lock.=0D
+=0D
+ NOTE: It's possible that parts of this handling will need to become=0D
+ part of a platform policy.=0D
+=0D
+ @param[in] FailureStatus The failure that was reported by LockVariabl=
ePolicy=0D
+=0D
+**/=0D
+STATIC=0D
+VOID=0D
+VariablePolicyHandleFailureToLock (=0D
+ IN EFI_STATUS FailureStatus=0D
+ )=0D
+{=0D
+ // For now, there's no agreed-upon policy for this.=0D
+ return;=0D
+}=0D
+=0D
+=0D
+/**=0D
+ ReadyToBoot Callback=0D
+ Lock the VariablePolicy interface if it hasn't already been locked.=0D
+=0D
+ @param[in] Event Event whose notification function is being invoked=
=0D
+ @param[in] Context Pointer to the notification function's context=0D
+=0D
+**/=0D
+STATIC=0D
+VOID=0D
+EFIAPI=0D
+LockPolicyInterfaceAtReadyToBoot (=0D
+ IN EFI_EVENT Event,=0D
+ IN VOID *Context=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+=0D
+ Status =3D ProtocolLockVariablePolicy();=0D
+=0D
+ if (EFI_ERROR( Status )) {=0D
+ VariablePolicyHandleFailureToLock( Status );=0D
+ }=0D
+ else {=0D
+ gBS->CloseEvent( Event );=0D
+ }=0D
+=0D
+}=0D
+=0D
+=0D
+/**=0D
+ Convert internal pointer addresses to virtual addresses.=0D
+=0D
+ @param[in] Event Event whose notification function is being invoked=
.=0D
+ @param[in] Context The pointer to the notification function's context=
, which=0D
+ is implementation-dependent.=0D
+**/=0D
+STATIC=0D
+VOID=0D
+EFIAPI=0D
+VariablePolicyVirtualAddressCallback (=0D
+ IN EFI_EVENT Event,=0D
+ IN VOID *Context=0D
+ )=0D
+{=0D
+ EfiConvertPointer (0, (VOID **)&mMmCommunication);=0D
+ EfiConvertPointer (0, (VOID **)&mMmCommunicationBuffer);=0D
+}=0D
+=0D
+=0D
+/**=0D
+ The driver's entry point.=0D
+=0D
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.=
=0D
+ @param[in] SystemTable A pointer to the EFI System Table.=0D
+=0D
+ @retval EFI_SUCCESS The entry point executed successfully.=0D
+ @retval other Some error occured when executing this entry poi=
nt.=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+VariablePolicySmmDxeMain (=0D
+ IN EFI_HANDLE ImageHandle,=0D
+ IN EFI_SYSTEM_TABLE *SystemTable=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ BOOLEAN ProtocolInstalled;=0D
+ BOOLEAN CallbackRegistered;=0D
+ BOOLEAN VirtualAddressChangeRegistered;=0D
+ EFI_EVENT ReadyToBootEvent;=0D
+ EFI_EVENT VirtualAddressChangeEvent;=0D
+=0D
+ Status =3D EFI_SUCCESS;=0D
+ ProtocolInstalled =3D FALSE;=0D
+ CallbackRegistered =3D FALSE;=0D
+ VirtualAddressChangeRegistered =3D FALSE;=0D
+=0D
+ // Update the minimum buffer size.=0D
+ mMmCommunicationBufferSize =3D VAR_CHECK_POLICY_MM_COMM_BUFFER_SIZE;=0D
+ // Locate the shared comm buffer to use for sending MM commands.=0D
+ Status =3D InitMmCommonCommBuffer( &mMmCommunicationBufferSize, &mMmComm=
unicationBuffer );=0D
+ if (EFI_ERROR( Status )) {=0D
+ DEBUG((DEBUG_ERROR, "%a - Failed to locate a viable MM comm buffer! %r=
\n", __FUNCTION__, Status));=0D
+ ASSERT_EFI_ERROR( Status );=0D
+ return Status;=0D
+ }=0D
+=0D
+ // Locate the MmCommunication protocol.=0D
+ Status =3D gBS->LocateProtocol( &gEfiMmCommunication2ProtocolGuid, NULL,=
(VOID**)&mMmCommunication );=0D
+ if (EFI_ERROR( Status )) {=0D
+ DEBUG((DEBUG_ERROR, "%a - Failed to locate MmCommunication protocol! %=
r\n", __FUNCTION__, Status));=0D
+ ASSERT_EFI_ERROR( Status );=0D
+ return Status;=0D
+ }=0D
+=0D
+ // Configure the VariablePolicy protocol structure.=0D
+ mVariablePolicyProtocol.Revision =3D EDKII_VARIABLE_POLIC=
Y_PROTOCOL_REVISION;=0D
+ mVariablePolicyProtocol.DisableVariablePolicy =3D ProtocolDisableVaria=
blePolicy;=0D
+ mVariablePolicyProtocol.IsVariablePolicyEnabled =3D ProtocolIsVariablePo=
licyEnabled;=0D
+ mVariablePolicyProtocol.RegisterVariablePolicy =3D ProtocolRegisterVari=
ablePolicy;=0D
+ mVariablePolicyProtocol.DumpVariablePolicy =3D ProtocolDumpVariable=
Policy;=0D
+ mVariablePolicyProtocol.LockVariablePolicy =3D ProtocolLockVariable=
Policy;=0D
+=0D
+ // Register all the protocols and return the status.=0D
+ Status =3D gBS->InstallMultipleProtocolInterfaces( &ImageHandle,=0D
+ &gEdkiiVariablePolicyPr=
otocolGuid, &mVariablePolicyProtocol,=0D
+ NULL );=0D
+ if (EFI_ERROR( Status )) {=0D
+ DEBUG(( DEBUG_ERROR, "%a - Failed to install protocol! %r\n", __FUNCTI=
ON__, Status ));=0D
+ goto Exit;=0D
+ }=0D
+ else {=0D
+ ProtocolInstalled =3D TRUE;=0D
+ }=0D
+=0D
+ //=0D
+ // Register a callback for ReadyToBoot so that the interface is at least=
locked before=0D
+ // dispatching any bootloaders or UEFI apps.=0D
+ Status =3D gBS->CreateEventEx( EVT_NOTIFY_SIGNAL,=0D
+ TPL_CALLBACK,=0D
+ LockPolicyInterfaceAtReadyToBoot,=0D
+ NULL,=0D
+ &gEfiEventReadyToBootGuid,=0D
+ &ReadyToBootEvent );=0D
+ if (EFI_ERROR( Status )) {=0D
+ DEBUG(( DEBUG_ERROR, "%a - Failed to create ReadyToBoot event! %r\n", =
__FUNCTION__, Status ));=0D
+ goto Exit;=0D
+ }=0D
+ else {=0D
+ CallbackRegistered =3D TRUE;=0D
+ }=0D
+=0D
+ //=0D
+ // Register a VirtualAddressChange callback for the MmComm protocol and =
Comm buffer.=0D
+ Status =3D gBS->CreateEventEx (EVT_NOTIFY_SIGNAL,=0D
+ TPL_NOTIFY,=0D
+ VariablePolicyVirtualAddressCallback,=0D
+ NULL,=0D
+ &gEfiEventVirtualAddressChangeGuid,=0D
+ &VirtualAddressChangeEvent);=0D
+ if (EFI_ERROR( Status )) {=0D
+ DEBUG(( DEBUG_ERROR, "%a - Failed to create VirtualAddressChange event=
! %r\n", __FUNCTION__, Status ));=0D
+ goto Exit;=0D
+ }=0D
+ else {=0D
+ VirtualAddressChangeRegistered =3D TRUE;=0D
+ }=0D
+=0D
+=0D
+Exit:=0D
+ //=0D
+ // If we're about to return a failed status (and unload this driver), we=
must first undo anything that=0D
+ // has been successfully done.=0D
+ if (EFI_ERROR( Status )) {=0D
+ if (ProtocolInstalled) {=0D
+ gBS->UninstallProtocolInterface( &ImageHandle, &gEdkiiVariablePolicy=
ProtocolGuid, &mVariablePolicyProtocol );=0D
+ }=0D
+ if (CallbackRegistered) {=0D
+ gBS->CloseEvent( ReadyToBootEvent );=0D
+ }=0D
+ if (VirtualAddressChangeRegistered) {=0D
+ gBS->CloseEvent( VirtualAddressChangeEvent );=0D
+ }=0D
+ }=0D
+=0D
+ return Status;=0D
+}=0D
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeD=
xe.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;=0D
EDKII_VAR_CHECK_PROTOCOL mVarCheck;=0D
=0D
+/**=0D
+ The logic to initialize the VariablePolicy engine is in its own file.=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+VariablePolicySmmDxeMain (=0D
+ IN EFI_HANDLE ImageHandle,=0D
+ IN EFI_SYSTEM_TABLE *SystemTable=0D
+ );=0D
+=0D
/**=0D
Some Secure Boot Policy Variable may update following other variable cha=
nges(SecureBoot follows PK change, etc).=0D
Record their initial State when variable write service is ready.=0D
@@ -1796,6 +1807,9 @@ VariableSmmRuntimeInitialize (
&mVirtualAddressChangeEvent=0D
);=0D
=0D
+ // Initialize the VariablePolicy protocol and engine.=0D
+ VariablePolicySmmDxeMain (ImageHandle, SystemTable);=0D
+=0D
return EFI_SUCCESS;=0D
}=0D
=0D
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.=0D
#=0D
# Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>=0D
+# Copyright (c) Microsoft Corporation.=0D
# SPDX-License-Identifier: BSD-2-Clause-Patent=0D
#=0D
##=0D
@@ -69,6 +70,7 @@ [LibraryClasses]
TpmMeasurementLib=0D
AuthVariableLib=0D
VarCheckLib=0D
+ VariablePolicyLib=0D
=0D
[Protocols]=0D
gEfiFirmwareVolumeBlockProtocolGuid ## CONSUMES=0D
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf b/M=
deModulePkg/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.=0D
#=0D
# Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.<BR>=0D
+# Copyright (c) Microsoft Corporation.=0D
# SPDX-License-Identifier: BSD-2-Clause-Patent=0D
#=0D
##=0D
@@ -78,6 +79,8 @@ [LibraryClasses]
AuthVariableLib=0D
VarCheckLib=0D
UefiBootServicesTableLib=0D
+ VariablePolicyLib=0D
+ VariablePolicyHelperLib=0D
=0D
[Protocols]=0D
gEfiSmmFirmwareVolumeBlockProtocolGuid ## CONSUMES=0D
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeD=
xe.inf b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.i=
nf
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.=0D
#=0D
# Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.<BR>=0D
+# Copyright (c) Microsoft Corporation.<BR>=0D
# SPDX-License-Identifier: BSD-2-Clause-Patent=0D
#=0D
##=0D
@@ -42,6 +43,7 @@ [Sources]
VariableParsing.c=0D
VariableParsing.h=0D
Variable.h=0D
+ VariablePolicySmmDxe.c=0D
=0D
[Packages]=0D
MdePkg/MdePkg.dec=0D
@@ -56,6 +58,8 @@ [LibraryClasses]
DxeServicesTableLib=0D
UefiDriverEntryPoint=0D
TpmMeasurementLib=0D
+ SafeIntLib=0D
+ PcdLib=0D
=0D
[Protocols]=0D
gEfiVariableWriteArchProtocolGuid ## PRODUCES=0D
@@ -67,11 +71,15 @@ [Protocols]
gEfiSmmVariableProtocolGuid=0D
gEdkiiVariableLockProtocolGuid ## PRODUCES=0D
gEdkiiVarCheckProtocolGuid ## PRODUCES=0D
+ gEdkiiVariablePolicyProtocolGuid ## PRODUCES=0D
=0D
[FeaturePcd]=0D
gEfiMdeModulePkgTokenSpaceGuid.PcdEnableVariableRuntimeCache #=
# CONSUMES=0D
gEfiMdeModulePkgTokenSpaceGuid.PcdVariableCollectStatistics #=
# CONSUMES=0D
=0D
+[Pcd]=0D
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAllowVariablePolicyEnforcementDisable =
## CONSUMES=0D
+=0D
[Guids]=0D
## PRODUCES ## GUID # Signature of Variable store header=0D
## CONSUMES ## GUID # Signature of Variable store header=0D
@@ -99,6 +107,8 @@ [Guids]
## SOMETIMES_CONSUMES ## Variable:L"dbt"=0D
gEfiImageSecurityDatabaseGuid=0D
=0D
+ gVarCheckPolicyLibMmiHandlerGuid=0D
+=0D
[Depex]=0D
gEfiMmCommunication2ProtocolGuid=0D
=0D
--=20
2.26.2.windows.1.8.g01c50adf56.20200515075929


[PATCH v5 08/14] UefiPayloadPkg: Add VariablePolicy engine to UefiPayloadPkg platform

Bret Barkelew <bret@...>
 

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

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>
---
UefiPayloadPkg/UefiPayloadPkgIa32.dsc | 4 ++++
UefiPayloadPkg/UefiPayloadPkgIa32X64.dsc | 4 ++++
2 files changed, 8 insertions(+)

diff --git a/UefiPayloadPkg/UefiPayloadPkgIa32.dsc b/UefiPayloadPkg/UefiPay=
loadPkgIa32.dsc
index d52945442e0e..d6b6e16f21b0 100644
--- a/UefiPayloadPkg/UefiPayloadPkgIa32.dsc
+++ b/UefiPayloadPkg/UefiPayloadPkgIa32.dsc
@@ -4,6 +4,7 @@
# Provides drivers and definitions to create uefi payload for bootloaders.=
=0D
#=0D
# Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.<BR>=0D
+# Copyright (c) Microsoft Corporation.=0D
# SPDX-License-Identifier: BSD-2-Clause-Patent=0D
#=0D
##=0D
@@ -204,6 +205,8 @@ [LibraryClasses]
AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLib=
Null.inf=0D
TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurem=
entLibNull.inf=0D
VarCheckLib|MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf=0D
+ VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyL=
ib.inf=0D
+ VariablePolicyHelperLib|MdeModulePkg/Library/VariablePolicyHelperLib/Var=
iablePolicyHelperLib.inf=0D
=0D
[LibraryClasses.IA32.SEC]=0D
DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf=0D
@@ -251,6 +254,7 @@ [LibraryClasses.common.DXE_RUNTIME_DRIVER]
HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf=0D
MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAll=
ocationLib.inf=0D
ReportStatusCodeLib|MdeModulePkg/Library/RuntimeDxeReportStatusCodeLib/R=
untimeDxeReportStatusCodeLib.inf=0D
+ VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyL=
ibRuntimeDxe.inf=0D
=0D
[LibraryClasses.common.UEFI_DRIVER,LibraryClasses.common.UEFI_APPLICATION]=
=0D
PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf=0D
diff --git a/UefiPayloadPkg/UefiPayloadPkgIa32X64.dsc b/UefiPayloadPkg/Uefi=
PayloadPkgIa32X64.dsc
index 0736cd995476..d93949fcea33 100644
--- a/UefiPayloadPkg/UefiPayloadPkgIa32X64.dsc
+++ b/UefiPayloadPkg/UefiPayloadPkgIa32X64.dsc
@@ -4,6 +4,7 @@
# Provides drivers and definitions to create uefi payload for bootloaders.=
=0D
#=0D
# Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.<BR>=0D
+# Copyright (c) Microsoft Corporation.=0D
# SPDX-License-Identifier: BSD-2-Clause-Patent=0D
#=0D
##=0D
@@ -205,6 +206,8 @@ [LibraryClasses]
AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLib=
Null.inf=0D
TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurem=
entLibNull.inf=0D
VarCheckLib|MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf=0D
+ VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyL=
ib.inf=0D
+ VariablePolicyHelperLib|MdeModulePkg/Library/VariablePolicyHelperLib/Var=
iablePolicyHelperLib.inf=0D
=0D
[LibraryClasses.IA32.SEC]=0D
DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf=0D
@@ -252,6 +255,7 @@ [LibraryClasses.common.DXE_RUNTIME_DRIVER]
HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf=0D
MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAll=
ocationLib.inf=0D
ReportStatusCodeLib|MdeModulePkg/Library/RuntimeDxeReportStatusCodeLib/R=
untimeDxeReportStatusCodeLib.inf=0D
+ VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyL=
ibRuntimeDxe.inf=0D
=0D
[LibraryClasses.common.UEFI_DRIVER,LibraryClasses.common.UEFI_APPLICATION]=
=0D
PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf=0D
--=20
2.26.2.windows.1.8.g01c50adf56.20200515075929


[PATCH v5 06/14] EmulatorPkg: Add VariablePolicy engine to EmulatorPkg platform

Bret Barkelew <bret@...>
 

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

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 1fc924ae5a16..e49deb54161a 100644
--- a/EmulatorPkg/EmulatorPkg.dsc
+++ b/EmulatorPkg/EmulatorPkg.dsc
@@ -6,6 +6,7 @@
#=0D
# Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>=0D
# Portions copyright (c) 2010 - 2011, Apple Inc. All rights reserved.<BR>=
=0D
+# Copyright (c) Microsoft Corporation.=0D
#=0D
# SPDX-License-Identifier: BSD-2-Clause-Patent=0D
#=0D
@@ -108,6 +109,8 @@ [LibraryClasses]
TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurem=
entLibNull.inf=0D
AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLib=
Null.inf=0D
VarCheckLib|MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf=0D
+ VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyL=
ibRuntimeDxe.inf=0D
+ VariablePolicyHelperLib|MdeModulePkg/Library/VariablePolicyHelperLib/Var=
iablePolicyHelperLib.inf=0D
SortLib|MdeModulePkg/Library/BaseSortLib/BaseSortLib.inf=0D
ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf=0D
FileHandleLib|MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf=0D
--=20
2.26.2.windows.1.8.g01c50adf56.20200515075929


[PATCH v5 05/14] OvmfPkg: Add VariablePolicy engine to OvmfPkg platform

Bret Barkelew <bret@...>
 

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

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 d0df9cbbfb2b..95d13250252a 100644
--- a/OvmfPkg/OvmfPkgIa32.dsc
+++ b/OvmfPkg/OvmfPkgIa32.dsc
@@ -3,6 +3,7 @@
#=0D
# Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>=
=0D
# (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>=0D
+# Copyright (c) Microsoft Corporation.=0D
#=0D
# SPDX-License-Identifier: BSD-2-Clause-Patent=0D
#=0D
@@ -196,6 +197,8 @@ [LibraryClasses]
AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLib=
Null.inf=0D
!endif=0D
VarCheckLib|MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf=0D
+ VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyL=
ib.inf=0D
+ VariablePolicyHelperLib|MdeModulePkg/Library/VariablePolicyHelperLib/Var=
iablePolicyHelperLib.inf=0D
=0D
=0D
#=0D
@@ -334,6 +337,7 @@ [LibraryClasses.common.DXE_RUNTIME_DRIVER]
BaseCryptLib|CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf=0D
PciLib|OvmfPkg/Library/DxePciLibI440FxQ35/DxePciLibI440FxQ35.inf=0D
QemuFwCfgS3Lib|OvmfPkg/Library/QemuFwCfgS3Lib/DxeQemuFwCfgS3LibFwCfg.inf=
=0D
+ VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyL=
ibRuntimeDxe.inf=0D
=0D
[LibraryClasses.common.UEFI_DRIVER]=0D
PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf=0D
@@ -957,6 +961,7 @@ [Components]
MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf {=0D
<LibraryClasses>=0D
NULL|MdeModulePkg/Library/VarCheckUefiLib/VarCheckUefiLib.inf=0D
+ NULL|MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.inf=0D
}=0D
MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf=0D
=0D
diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc
index b3ae62fee92b..25ee9da2e67d 100644
--- a/OvmfPkg/OvmfPkgIa32X64.dsc
+++ b/OvmfPkg/OvmfPkgIa32X64.dsc
@@ -3,6 +3,7 @@
#=0D
# Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>=
=0D
# (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>=0D
+# Copyright (c) Microsoft Corporation.=0D
#=0D
# SPDX-License-Identifier: BSD-2-Clause-Patent=0D
#=0D
@@ -200,6 +201,8 @@ [LibraryClasses]
AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLib=
Null.inf=0D
!endif=0D
VarCheckLib|MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf=0D
+ VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyL=
ib.inf=0D
+ VariablePolicyHelperLib|MdeModulePkg/Library/VariablePolicyHelperLib/Var=
iablePolicyHelperLib.inf=0D
=0D
=0D
#=0D
@@ -338,6 +341,7 @@ [LibraryClasses.common.DXE_RUNTIME_DRIVER]
BaseCryptLib|CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf=0D
PciLib|OvmfPkg/Library/DxePciLibI440FxQ35/DxePciLibI440FxQ35.inf=0D
QemuFwCfgS3Lib|OvmfPkg/Library/QemuFwCfgS3Lib/DxeQemuFwCfgS3LibFwCfg.inf=
=0D
+ VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyL=
ibRuntimeDxe.inf=0D
=0D
[LibraryClasses.common.UEFI_DRIVER]=0D
PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf=0D
@@ -972,6 +976,7 @@ [Components.X64]
MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf {=0D
<LibraryClasses>=0D
NULL|MdeModulePkg/Library/VarCheckUefiLib/VarCheckUefiLib.inf=0D
+ NULL|MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.inf=0D
}=0D
MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf=0D
=0D
diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc
index f7fe75ebf531..f8a4c02e495d 100644
--- a/OvmfPkg/OvmfPkgX64.dsc
+++ b/OvmfPkg/OvmfPkgX64.dsc
@@ -3,6 +3,7 @@
#=0D
# Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>=
=0D
# (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>=0D
+# Copyright (c) Microsoft Corporation.=0D
#=0D
# SPDX-License-Identifier: BSD-2-Clause-Patent=0D
#=0D
@@ -200,6 +201,8 @@ [LibraryClasses]
AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLib=
Null.inf=0D
!endif=0D
VarCheckLib|MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf=0D
+ VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyL=
ib.inf=0D
+ VariablePolicyHelperLib|MdeModulePkg/Library/VariablePolicyHelperLib/Var=
iablePolicyHelperLib.inf=0D
=0D
=0D
#=0D
@@ -338,6 +341,7 @@ [LibraryClasses.common.DXE_RUNTIME_DRIVER]
BaseCryptLib|CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf=0D
PciLib|OvmfPkg/Library/DxePciLibI440FxQ35/DxePciLibI440FxQ35.inf=0D
QemuFwCfgS3Lib|OvmfPkg/Library/QemuFwCfgS3Lib/DxeQemuFwCfgS3LibFwCfg.inf=
=0D
+ VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyL=
ibRuntimeDxe.inf=0D
=0D
[LibraryClasses.common.UEFI_DRIVER]=0D
PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf=0D
@@ -968,6 +972,7 @@ [Components]
MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf {=0D
<LibraryClasses>=0D
NULL|MdeModulePkg/Library/VarCheckUefiLib/VarCheckUefiLib.inf=0D
+ NULL|MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.inf=0D
}=0D
MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf=0D
=0D
diff --git a/OvmfPkg/OvmfXen.dsc b/OvmfPkg/OvmfXen.dsc
index 3af0ee705407..8dac706fbab0 100644
--- a/OvmfPkg/OvmfXen.dsc
+++ b/OvmfPkg/OvmfXen.dsc
@@ -4,6 +4,7 @@
# Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>=
=0D
# (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>=0D
# Copyright (c) 2019, Citrix Systems, Inc.=0D
+# Copyright (c) Microsoft Corporation.=0D
#=0D
# SPDX-License-Identifier: BSD-2-Clause-Patent=0D
#=0D
@@ -182,6 +183,8 @@ [LibraryClasses]
=0D
AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLib=
Null.inf=0D
VarCheckLib|MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf=0D
+ VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyL=
ib.inf=0D
+ VariablePolicyHelperLib|MdeModulePkg/Library/VariablePolicyHelperLib/Var=
iablePolicyHelperLib.inf=0D
=0D
=0D
#=0D
@@ -289,6 +292,7 @@ [LibraryClasses.common.DXE_RUNTIME_DRIVER]
BaseCryptLib|CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf=0D
PciLib|OvmfPkg/Library/DxePciLibI440FxQ35/DxePciLibI440FxQ35.inf=0D
QemuFwCfgS3Lib|OvmfPkg/Library/QemuFwCfgS3Lib/DxeQemuFwCfgS3LibFwCfg.inf=
=0D
+ VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyL=
ibRuntimeDxe.inf=0D
=0D
[LibraryClasses.common.UEFI_DRIVER]=0D
PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf=0D
--=20
2.26.2.windows.1.8.g01c50adf56.20200515075929


[PATCH v5 13/14] MdeModulePkg: Drop VarLock from RuntimeDxe variable driver

Bret Barkelew <bret@...>
 

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

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/MdeMod=
ulePkg/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.=0D
=0D
Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>=0D
+Copyright (c) Microsoft Corporation.=0D
SPDX-License-Identifier: BSD-2-Clause-Patent=0D
=0D
**/=0D
=0D
#include "Variable.h"=0D
=0D
-/**=0D
- Mark a variable that will become read-only after leaving the DXE phase o=
f execution.=0D
- Write request coming from SMM environment through EFI_SMM_VARIABLE_PROTO=
COL is allowed.=0D
-=0D
- @param[in] This The VARIABLE_LOCK_PROTOCOL instance.=0D
- @param[in] VariableName A pointer to the variable name that will be mad=
e read-only subsequently.=0D
- @param[in] VendorGuid A pointer to the vendor GUID that will be made =
read-only subsequently.=0D
-=0D
- @retval EFI_SUCCESS The variable specified by the VariableName=
and the VendorGuid was marked=0D
- as pending to be read-only.=0D
- @retval EFI_INVALID_PARAMETER VariableName or VendorGuid is NULL.=0D
- Or VariableName is an empty string.=0D
- @retval EFI_ACCESS_DENIED EFI_END_OF_DXE_EVENT_GROUP_GUID or EFI_EVE=
NT_GROUP_READY_TO_BOOT has=0D
- already been signaled.=0D
- @retval EFI_OUT_OF_RESOURCES There is not enough resource to hold the l=
ock request.=0D
-**/=0D
-EFI_STATUS=0D
-EFIAPI=0D
-VariableLockRequestToLock (=0D
- IN CONST EDKII_VARIABLE_LOCK_PROTOCOL *This,=0D
- IN CHAR16 *VariableName,=0D
- IN EFI_GUID *VendorGuid=0D
- )=0D
-{=0D
- EFI_STATUS Status;=0D
- VAR_CHECK_VARIABLE_PROPERTY Property;=0D
-=0D
- AcquireLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.Variab=
leServicesLock);=0D
-=0D
- Status =3D VarCheckLibVariablePropertyGet (VariableName, VendorGuid, &Pr=
operty);=0D
- if (!EFI_ERROR (Status)) {=0D
- Property.Property |=3D VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY;=0D
- } else {=0D
- Property.Revision =3D VAR_CHECK_VARIABLE_PROPERTY_REVISION;=0D
- Property.Property =3D VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY;=0D
- Property.Attributes =3D 0;=0D
- Property.MinSize =3D 1;=0D
- Property.MaxSize =3D MAX_UINTN;=0D
- }=0D
- Status =3D VarCheckLibVariablePropertySet (VariableName, VendorGuid, &Pr=
operty);=0D
-=0D
- DEBUG ((EFI_D_INFO, "[Variable] Lock: %g:%s %r\n", VendorGuid, VariableN=
ame, Status));=0D
-=0D
- ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.Variab=
leServicesLock);=0D
-=0D
- return Status;=0D
-}=0D
-=0D
/**=0D
Register SetVariable check handler.=0D
=0D
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableLockRequstT=
oLock.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableLockRequstToLo=
ck.c
new file mode 100644
index 000000000000..1f7f0b7ef06c
--- /dev/null
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableLockRequstToLock.c
@@ -0,0 +1,71 @@
+/** @file -- VariableLockRequstToLock.c=0D
+Temporary location of the RequestToLock shim code while=0D
+projects are moved to VariablePolicy. Should be removed when deprecated.=0D
+=0D
+Copyright (c) Microsoft Corporation.=0D
+SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+=0D
+**/=0D
+=0D
+#include <Uefi.h>=0D
+=0D
+#include <Library/DebugLib.h>=0D
+#include <Library/MemoryAllocationLib.h>=0D
+=0D
+#include <Protocol/VariableLock.h>=0D
+=0D
+#include <Protocol/VariablePolicy.h>=0D
+#include <Library/VariablePolicyLib.h>=0D
+#include <Library/VariablePolicyHelperLib.h>=0D
+=0D
+=0D
+/**=0D
+ DEPRECATED. THIS IS ONLY HERE AS A CONVENIENCE WHILE PORTING.=0D
+ Mark a variable that will become read-only after leaving the DXE phase o=
f execution.=0D
+ Write request coming from SMM environment through EFI_SMM_VARIABLE_PROTO=
COL is allowed.=0D
+=0D
+ @param[in] This The VARIABLE_LOCK_PROTOCOL instance.=0D
+ @param[in] VariableName A pointer to the variable name that will be mad=
e read-only subsequently.=0D
+ @param[in] VendorGuid A pointer to the vendor GUID that will be made =
read-only subsequently.=0D
+=0D
+ @retval EFI_SUCCESS The variable specified by the VariableName=
and the VendorGuid was marked=0D
+ as pending to be read-only.=0D
+ @retval EFI_INVALID_PARAMETER VariableName or VendorGuid is NULL.=0D
+ Or VariableName is an empty string.=0D
+ @retval EFI_ACCESS_DENIED EFI_END_OF_DXE_EVENT_GROUP_GUID or EFI_EVE=
NT_GROUP_READY_TO_BOOT has=0D
+ already been signaled.=0D
+ @retval EFI_OUT_OF_RESOURCES There is not enough resource to hold the l=
ock request.=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+VariableLockRequestToLock (=0D
+ IN CONST EDKII_VARIABLE_LOCK_PROTOCOL *This,=0D
+ IN CHAR16 *VariableName,=0D
+ IN EFI_GUID *VendorGuid=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ VARIABLE_POLICY_ENTRY *NewPolicy;=0D
+=0D
+ NewPolicy =3D NULL;=0D
+ Status =3D CreateBasicVariablePolicy( VendorGuid,=0D
+ VariableName,=0D
+ VARIABLE_POLICY_NO_MIN_SIZE,=0D
+ VARIABLE_POLICY_NO_MAX_SIZE,=0D
+ VARIABLE_POLICY_NO_MUST_ATTR,=0D
+ VARIABLE_POLICY_NO_CANT_ATTR,=0D
+ VARIABLE_POLICY_TYPE_LOCK_NOW,=0D
+ &NewPolicy );=0D
+ if (!EFI_ERROR( Status )) {=0D
+ Status =3D RegisterVariablePolicy( NewPolicy );=0D
+ }=0D
+ if (EFI_ERROR( Status )) {=0D
+ DEBUG(( DEBUG_ERROR, "%a - Failed to lock variable %s! %r\n", __FUNCTI=
ON__, VariableName, Status ));=0D
+ ASSERT_EFI_ERROR( Status );=0D
+ }=0D
+ if (NewPolicy !=3D NULL) {=0D
+ FreePool( NewPolicy );=0D
+ }=0D
+=0D
+ return Status;=0D
+}=0D
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=0D
VariableExLib.c=0D
SpeculationBarrierDxe.c=0D
+ VariableLockRequstToLock.c=0D
=0D
[Packages]=0D
MdePkg/MdePkg.dec=0D
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf b/M=
deModulePkg/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=0D
TcgMorLockSmm.c=0D
SpeculationBarrierSmm.c=0D
+ VariableLockRequstToLock.c=0D
=0D
[Packages]=0D
MdePkg/MdePkg.dec=0D
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneM=
m.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=0D
TcgMorLockSmm.c=0D
SpeculationBarrierSmm.c=0D
+ VariableLockRequstToLock.c=0D
=0D
[Packages]=0D
MdePkg/MdePkg.dec=0D
--=20
2.26.2.windows.1.8.g01c50adf56.20200515075929


[PATCH v5 11/14] SecurityPkg: Allow VariablePolicy state to delete authenticated variables

Bret Barkelew <bret@...>
 

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

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


[PATCH v2 5/5] MdeModulePkg/MdeModulePkg.ci.yaml: Add configuration for Ecc check

Zhang, Shenglei
 

This is a sample for users to add exceptions and ignored files for
their own use.

Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Hao A Wu <hao.a.wu@intel.com>
Signed-off-by: Shenglei Zhang <shenglei.zhang@intel.com>
---
MdeModulePkg/MdeModulePkg.ci.yaml | 8 ++++++++
1 file changed, 8 insertions(+)

diff --git a/MdeModulePkg/MdeModulePkg.ci.yaml b/MdeModulePkg/MdeModulePkg.ci.yaml
index 1cfc1328390e..8ccf667d12f3 100644
--- a/MdeModulePkg/MdeModulePkg.ci.yaml
+++ b/MdeModulePkg/MdeModulePkg.ci.yaml
@@ -5,6 +5,14 @@
# SPDX-License-Identifier: BSD-2-Clause-Patent
##
{
+ "EccCheck": {
+ "ExceptionList": [
+ "8001", "aaabbb"
+ ],
+ "IgnoreFiles": [
+ "Library/BaseBmpSupportLib/BmpSupportLib.c"
+ ]
+ },
## options defined ci/Plugin/CompilerPlugin
"CompilerPlugin": {
"DscPath": "MdeModulePkg.dsc"
--
2.18.0.windows.1


[PATCH v2 4/5] .azurepiplines: Add a pipline to check ECC issues for commits

Zhang, Shenglei
 

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=2606
Add a pipeline to run the ECC checks on Azure Pipelines agents
for edk2 open ci.

Cc: Sean Brogan <sean.brogan@microsoft.com>
Cc: Bret Barkelew <Bret.Barkelew@microsoft.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Signed-off-by: Shenglei Zhang <shenglei.zhang@intel.com>
---
.azurepipelines/Windows-EccCheck.yml | 38 ++++++++++++++++++++++++++++
1 file changed, 38 insertions(+)
create mode 100644 .azurepipelines/Windows-EccCheck.yml

diff --git a/.azurepipelines/Windows-EccCheck.yml b/.azurepipelines/Windows-EccCheck.yml
new file mode 100644
index 000000000000..0d20551efb5f
--- /dev/null
+++ b/.azurepipelines/Windows-EccCheck.yml
@@ -0,0 +1,38 @@
+## @file
+# Azure Pipielines YML file that evalues the patch series in a PR using the
+# python script BaseTools/Scripts/PatchCheck.py.
+#
+# NOTE: This example monitors pull requests against the edk2-ci branch. Most
+# environments would replace 'edk2-ci' with 'master'.
+#
+# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+# https://github.com/tianocore
+#
+##
+
+trigger: none
+
+pr:
+- master
+
+pool:
+ vmImage: 'windows-latest'
+
+steps:
+- checkout: self
+ clean: true
+
+- task: UsePythonVersion@0
+ inputs:
+ versionSpec: '3.8.x'
+ architecture: 'x64'
+
+- script: pip install -r pip-requirements.txt
+ displayName: 'Install/Upgrade pip modules'
+
+- script: |
+ git fetch origin $(System.PullRequest.TargetBranch):$(System.PullRequest.TargetBranch)
+ py -3 BaseTools/Scripts/EccCheck.py $(System.PullRequest.TargetBranch)..$(System.PullRequest.SourceCommitId)
+ displayName: 'Use EccCheck.py to verify patch series in pull request'
--
2.18.0.windows.1


[PATCH v2 3/5] pip-requirements.txt: Add Ecc required lib

Zhang, Shenglei
 

antlr4-python3-runtime is a lib to support Ecc run with Py3.x.

Cc: Sean Brogan <sean.brogan@microsoft.com>
Cc: Bret Barkelew <Bret.Barkelew@microsoft.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Signed-off-by: Shenglei Zhang <shenglei.zhang@intel.com>
---
pip-requirements.txt | 1 +
1 file changed, 1 insertion(+)

diff --git a/pip-requirements.txt b/pip-requirements.txt
index 574dac43b1a6..7e83ddd9b3c9 100644
--- a/pip-requirements.txt
+++ b/pip-requirements.txt
@@ -14,3 +14,4 @@

edk2-pytool-library==0.10.*
edk2-pytool-extensions~=0.13.3
+antlr4-python3-runtime
\ No newline at end of file
--
2.18.0.windows.1


[PATCH v2 2/5] BaseTools/Scripts: Add EccCheck.py

Zhang, Shenglei
 

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=2606
EccCheck.py is a tool to report Ecc issues for commits, which will
be run on open ci.
But note not each kind of issue could be reported out.
It can only handle the issues, whose line number in CSV report
accurately map with their code in source code files. And comment
issues can also be handled.

Its usage is similar to PatchCheck.py. Type EccCheck.py -h and then
learn how to use it.

If a patch passes EccCheck, "Ecc Pass" will show up.
Otherwise, "Ecc error detected" alerts the users and the details
are also presented.

Cc: Bob Feng <bob.c.feng@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Signed-off-by: Shenglei Zhang <shenglei.zhang@intel.com>
---

v2: Update 2/5, fix the bug that the script can't hanlde multiple commits.

BaseTools/Scripts/EccCheck.py | 433 ++++++++++++++++++++++++++++++++++
1 file changed, 433 insertions(+)
create mode 100644 BaseTools/Scripts/EccCheck.py

diff --git a/BaseTools/Scripts/EccCheck.py b/BaseTools/Scripts/EccCheck.py
new file mode 100644
index 000000000000..034a9965a79b
--- /dev/null
+++ b/BaseTools/Scripts/EccCheck.py
@@ -0,0 +1,433 @@
+## @file
+# Check a patch for various format issues
+#
+# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+
+import os
+import re
+import csv
+import subprocess
+import argparse
+import sys
+import yaml
+import xml.dom.minidom
+
+__copyright__ = "Copyright (c) 2020, Intel Corporation All rights reserved."
+ReModifyFile = re.compile(r'[B-Q,S-Z]+[\d]*\t(.*?)\n')
+FindModifyFile = re.compile(r'\+\+\+ b\/(.*)')
+LineScopePattern = (r'@@ -\d*\,*\d* \+\d*\,*\d* @@.*')
+LineNumRange = re.compile(r'@@ -\d*\,*\d* \+(\d*)\,*(\d*) @@.*')
+
+EnvList = os.environ
+GlobalSymbol = {}
+
+def AppendException(ExceptionList, ExceptionFile):
+ error_code_list = ExceptionList[::2]
+ keyword_list = ExceptionList[1::2]
+ domTree = xml.dom.minidom.parse(ExceptionFile)
+ rootNode = domTree.documentElement
+ for error_code, keyword in zip(error_code_list, keyword_list):
+ customer_node = domTree.createElement("Exception")
+ keyword_node = domTree.createElement("KeyWord")
+ keyword_node_text_value = domTree.createTextNode(keyword)
+ keyword_node.appendChild(keyword_node_text_value)
+ customer_node.appendChild(keyword_node)
+ error_code_node = domTree.createElement("ErrorID")
+ error_code_text_value = domTree.createTextNode(error_code)
+ error_code_node.appendChild(error_code_text_value)
+ customer_node.appendChild(error_code_node)
+ rootNode.appendChild(customer_node)
+
+ with open(ExceptionFile, 'w') as f:
+ domTree.writexml(f,indent='',addindent='',newl='\n',encoding='UTF-8')
+
+def GetPkgList(EnvList):
+ WORKDIR = EnvList['WORKDIR']
+ dirs = os.listdir(WORKDIR)
+ PkgList = []
+ for directory in dirs:
+ if directory.endswith('Pkg'):
+ PkgList.append(directory)
+ return PkgList
+
+def GenerateEccReport(EnvList, ModifyDirList, EccDiffRange):
+ IsECCNeed = False
+ IsTrue = True
+ PkgList = GetPkgList(EnvList)
+
+ for Line in ModifyDirList:
+ print('echo Run ECC tool for the commit in %s' % Line)
+ GlobalSymbol['GenerateEccReport'] = True
+ for Pkg in PkgList:
+ if Pkg in Line:
+ IsECCNeed = True
+ Ecc_cmd = ["ecc", "-c", "%WORKDIR%\BaseTools\Source\Python\Ecc\config.ini",
+ "-e", "%WORKDIR%\BaseTools\Source\Python\Ecc\exception.xml",
+ "-t", "%WORKDIR%\{}".format(Line),
+ "-r", "%WORKDIR%\Ecc.csv"]
+ _, _, result, return_code = ExecuteScript(Ecc_cmd, EnvList, shell=True)
+ if return_code != 0:
+ IsTrue = False
+ break
+
+ if not IsTrue:
+ print('Fail to run ECC tool')
+ GlobalSymbol['SCRIPT_ERROR'] = True
+ EndDelFile(EnvList)
+
+ if GlobalSymbol.get('GenerateEccReport'):
+ ParseEccReport(EnvList, EccDiffRange)
+ else:
+ print("Patch check tool or ECC tool don't detect error")
+
+ if IsECCNeed:
+ revert_cmd = ["git", "checkout", "--", "%WORKDIR%\BaseTools\Source\Python\Ecc\exception.xml"]
+ _, _, result, return_code = ExecuteScript(revert_cmd, EnvList, shell=True)
+ else:
+ print("Doesn't need run ECC check")
+ return
+
+def ParseEccReport(EnvList, EccDiffRange):
+ WorkDir = EnvList['WORKDIR']
+ EccLog = os.path.join(WorkDir, "Ecc.log")
+ EccsCsv = "Ecc.csv"
+ FileList = os.listdir(WorkDir)
+ rowLines = []
+ if EccsCsv in FileList:
+ with open(EccsCsv) as Csv:
+ reader = csv.reader(Csv)
+ for row in reader:
+ for ModifyFile in EccDiffRange:
+ if ModifyFile in row[3]:
+ for i in EccDiffRange[ModifyFile]:
+ LineNo = int(row[4])
+ if i[0] <= LineNo <= i[1]:
+ row[0] = '\nEFI coding style error'
+ row[1] = 'Error code: ' + row[1]
+ row[3] = 'File: ' + row[3]
+ row[4] = 'Line number: ' + row[4]
+ rowLine = '\n *'.join(row)
+ rowLines.append(rowLine)
+ break
+ break
+ if rowLines:
+ GlobalSymbol['ECC_PASS'] = False
+
+ with open(EccLog, 'a') as EccFile:
+ AllLine = '\n'.join(rowLines)
+ AllLine = AllLine + '\n'
+ EccFile.writelines(AllLine)
+
+def RemoveFile(File):
+ if os.path.exists(File):
+ os.remove(File)
+
+def ExecuteScript(command, env_variables, collect_env=False,
+ enable_std_pipe=False, shell=True):
+ """launches a process that executes a script/shell command passed to it
+
+ :param command: The command/script with its commandline
+ arguments to be executed
+ :type command: List:String
+ :param env_variables: Environment variables passed to the process
+ :type env_variables: String
+ :param collect_env: Enables the collection of evironment variables
+ when process execution is done
+ :type collect_env: Boolean
+ :param enable_std_pipe: Enables process out to be piped to
+ :type enable_std_pipe: String
+ :returns: a tuple of std_out, stderr , environment variables,
+ return code
+ :rtype: Tuple: (std_out, stderr , enVar, return_code)
+ """
+
+ env_marker = '-----env-----'
+ env = {}
+ kwarg = {"env": env_variables,
+ "universal_newlines": True,
+ "shell": shell,
+ "cwd": env_variables["WORKSPACE"]}
+
+ if enable_std_pipe or collect_env:
+ kwarg["stdout"] = subprocess.PIPE
+ kwarg["stderr"] = subprocess.PIPE
+
+ if collect_env:
+ # get the binary that prints environment variables based on os
+ if os.name == 'nt':
+ get_var_command = "set"
+ else:
+ get_var_command = "env"
+ # modify the command to print the environment variables
+ if isinstance(command, list):
+ command += ["&&", "echo", env_marker, "&&",
+ get_var_command, "&&", "echo", env_marker]
+ else:
+ command += " " + " ".join(["&&", "echo", env_marker,
+ "&&", get_var_command,
+ "&&", "echo", env_marker])
+
+ # execute the command
+ execute = subprocess.Popen(command, **kwarg)
+ std_out, stderr = execute.communicate()
+ code = execute.returncode
+
+ # wait for process to be done
+ execute.wait()
+
+ # if collect enviroment variables
+ if collect_env:
+ # get the new environment variables
+ std_out, env = GetEnvironmentVariables(std_out, env_marker)
+ return (std_out, stderr, env, code)
+
+def GetEnvironmentVariables(std_out_str, marker):
+ """Gets the environment variables from a process
+
+ :param std_out_str: The std_out pipe
+ :type std_out_str: String
+ :param marker: A begining and end mark of environment
+ variables printed to std_out
+ :type marker: String
+ :returns: The environment variables read from the process' std_out pipe
+ :rtype: Tuple
+ """
+ start_env_update = False
+ environment_vars = {}
+ out_put = ""
+ for line in std_out_str.split("\n"):
+ if start_env_update and len(line.split("=")) == 2:
+ key, value = line.split("=")
+ environment_vars[key] = value
+ else:
+ out_put += "\n" + line.replace(marker, "")
+
+ if marker in line:
+ if start_env_update:
+ start_env_update = False
+ else:
+ start_env_update = True
+ return (out_put, environment_vars)
+
+def EndDelFile(EnvList):
+ WORKDIR = EnvList['WORKDIR']
+ ModifyFileListLog = os.path.join(WORKDIR, 'PatchModifyFiles.log')
+ RemoveFile(ModifyFileListLog)
+ PatchLog = os.path.join(WORKDIR, 'PatchFile.log')
+ RemoveFile(PatchLog)
+ FileLog = os.path.join(WORKDIR, "File.log")
+ RemoveFile(FileLog)
+ if GlobalSymbol.get('GenerateEccReport'):
+ FileList = os.listdir(WORKDIR)
+ CsvList = [os.path.join(WORKDIR, File) for File in FileList if File.endswith('.csv')]
+ for Csv in CsvList:
+ RemoveFile(Csv)
+ if GlobalSymbol.get('SCRIPT_ERROR'):
+ print('ECC tool detect error')
+ exit(1)
+
+def EdksetupRebuild(EnvList, WORKDIR):
+ EnvList['WORKDIR'] = WORKDIR
+ EnvList['WORKSPACE'] = WORKDIR
+ edk2_setup_cmd = ["edksetup", "Rebuild"]
+ _, _, result, return_code = ExecuteScript(edk2_setup_cmd, EnvList, collect_env=True, shell=True)
+ if return_code == 0:
+ for Key in result:
+ EnvList[Key] = result[Key]
+ return True
+ return False
+
+def GetDiffrange(EnvList, commit):
+ WORKDIR = EnvList['WORKDIR']
+ ModifyFileListLog = EnvList['ModifyFileListLog']
+ RangeDirectory = {}
+ PatchLog = os.path.join(WORKDIR, 'PatchFile.log')
+ Format_Patch_cmd = ["git", "show", str(commit), "--unified=0", ">", PatchLog]
+ _, _, result, return_code = ExecuteScript(Format_Patch_cmd, EnvList, shell=True)
+ if return_code != 0:
+ print('Fail to run GIT')
+ GlobalSymbol['SCRIPT_ERROR'] = True
+ EndDelFile(EnvList)
+ with open(PatchLog, encoding='utf8') as PatchLogFile:
+ Filelines = PatchLogFile.readlines()
+ IsDelete = True
+ StartCheck = False
+ for line in Filelines:
+ ModifyFile = FindModifyFile.findall(line)
+ if ModifyFile and not StartCheck and os.path.isfile(ModifyFile[0]):
+ ModifyFileCommentDic = GetCommentRange(EnvList, ModifyFile[0])
+ IsDelete = False
+ StartCheck = True
+ ModifyFilieDic = ModifyFile[0]
+ ModifyFilieDic = ModifyFilieDic.replace("/","\\")
+ RangeDirectory[ModifyFilieDic] = []
+ elif line.startswith('--- '):
+ StartCheck = False
+ elif re.match(LineScopePattern, line, re.I) and not IsDelete and StartCheck:
+ startline = LineNumRange.search(line).group(1)
+ linerange = LineNumRange.search(line).group(2)
+ if not linerange:
+ linerange = '1'
+ RangeDirectory[ModifyFilieDic].append((int(startline), int(startline) + int(linerange) - 1))
+ for i in ModifyFileCommentDic:
+ if i[0] <= int(startline) <= i[1]:
+ RangeDirectory[ModifyFilieDic].append(i)
+ return RangeDirectory
+
+def GetCommentRange(EnvList, ModifyFile):
+ WORKDIR = EnvList['WORKDIR']
+ ModifyFilePath = os.path.join(WORKDIR, ModifyFile)
+ with open(ModifyFilePath) as f:
+ LineNo = 1
+ CommentRange = []
+ Start = False
+ for line in f:
+ if line.startswith('/**'):
+ startno = LineNo
+ Start = True
+ if line.startswith('**/') and Start:
+ endno = LineNo
+ Start = False
+ CommentRange.append((int(startno), int(endno)))
+ LineNo += 1
+
+ if CommentRange and CommentRange[0][0] == 1:
+ del CommentRange[0]
+ return CommentRange
+
+def GetModifyDir(EnvList, commit):
+ WORKDIR = EnvList['WORKDIR']
+ ModifyDirList = []
+ ModifyFileListLog = os.path.join(WORKDIR, 'PatchModifyFiles.log')
+ EnvList['ModifyFileListLog'] = ModifyFileListLog
+ Patch_Modify_cmd = ["git", "diff", "--name-status", str(commit), str(commit)+"~1", ">", ModifyFileListLog]
+ _, _, result, return_code = ExecuteScript(Patch_Modify_cmd, EnvList, shell=True)
+ if return_code != 0:
+ print('Fail to run GIT')
+ GlobalSymbol['SCRIPT_ERROR'] = True
+ EndDelFile(EnvList)
+ with open(ModifyFileListLog) as ModifyFile:
+ Filelines = ModifyFile.readlines()
+ for Line in Filelines:
+ FilePath = ReModifyFile.findall(Line)
+ if FilePath:
+ FileDir = os.path.dirname(FilePath[0])
+ else:
+ continue
+ PkgList = GetPkgList(EnvList)
+ if FileDir in PkgList or not FileDir:
+ continue
+ else:
+ ModifyDirList.append('%s'%FileDir)
+
+ ModifyDirList = list(set(ModifyDirList))
+ return ModifyDirList
+
+def ApplyConfig(EnvList, ModifyDirList, EccDiffRange):
+ WORKDIR = EnvList['WORKDIR']
+ ModifyPkgList = []
+ for ModifyDir in ModifyDirList:
+ ModifyPkg = ModifyDir.split("/")[0]
+ ModifyPkgList.append(ModifyPkg)
+ ModifyPkgList = list(set(ModifyPkgList))
+ for ModifyPkg in ModifyPkgList:
+ pkg_config_file = os.path.join(WORKDIR, ModifyPkg, ModifyPkg + ".ci.yaml")
+ if os.path.exists(pkg_config_file):
+ with open(pkg_config_file, 'r') as f:
+ pkg_config = yaml.safe_load(f)
+ if "EccCheck" in pkg_config:
+ EccConfig = pkg_config["EccCheck"]
+ #
+ # Add exceptions
+ #
+ ExceptionList = EccConfig["ExceptionList"]
+ ExceptionFile = os.path.join(WORKDIR, "BaseTools", "Source", "Python", "Ecc", "exception.xml")
+ if os.path.exists(ExceptionFile):
+ AppendException(ExceptionList, ExceptionFile)
+ #
+ # Exclude ignored files
+ #
+ IgnoreFilesList = EccConfig['IgnoreFiles']
+ for ignore_file in IgnoreFilesList:
+ ignore_file = ignore_file.replace("/", "\\")
+ ignore_file = os.path.join(ModifyPkg, ignore_file)
+ if ignore_file in EccDiffRange:
+ del EccDiffRange[ignore_file]
+ return
+
+def CheckOneCommit(commit):
+ WORKDIR = os.getcwd()
+ EdksetupRebuild(EnvList, WORKDIR)
+ ModifyDirList = GetModifyDir(EnvList, commit)
+ EccDiffRange = GetDiffrange(EnvList, commit)
+ ApplyConfig(EnvList, ModifyDirList, EccDiffRange)
+ GenerateEccReport(EnvList, ModifyDirList, EccDiffRange)
+ EndDelFile(EnvList)
+
+def parse_options():
+ parser = argparse.ArgumentParser(description=__copyright__)
+ parser.add_argument('commits', nargs='*',
+ help='[commit(s) ID | number of commits, like "-3" means check first 3 commits]')
+ args = parser.parse_args()
+ return args
+
+def process_one_arg(self, arg):
+ if len(arg) >= 2 and arg[0] == '-':
+ count = int(arg[1:])
+ CheckOneArg(arg, self.count).ok
+
+
+def read_commit_list_from_git(start_commit, count):
+ cmd = ['git', 'rev-list', '--abbrev-commit', '--no-walk' ]
+ if count is not None:
+ cmd.append('--max-count=' + str(count))
+ cmd.append(start_commit)
+ p = subprocess.Popen(cmd,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT)
+ result = p.communicate()
+ out = result[0].decode('utf-8', 'ignore') if result[0] and result[0].find(b"fatal")!=0 else None
+ return out.split() if out else []
+
+def ReleaseReport(EnvList):
+ WORKDIR = EnvList['WORKDIR']
+ EccLog = os.path.join(WORKDIR, "ECC.log")
+ if GlobalSymbol['ECC_PASS']:
+ print('\n===================Ecc pass===================')
+ RemoveFile(EccLog)
+ return 0
+ else:
+ print('\n===================Ecc error detected===================')
+ with open(EccLog) as output:
+ print(output.read())
+ RemoveFile(EccLog)
+ return -1
+
+def main():
+ commits = parse_options().commits
+
+ if len(commits) == 0:
+ commits = [ 'HEAD' ]
+
+ if len(commits[0]) >= 2 and commits[0][0] == '-':
+ count = int(commits[0][1:])
+ commits = read_commit_list_from_git('HEAD', count)
+
+ """
+ This 'if' block is only used for creating pull request.
+ """
+ if ".." in commits[0]:
+ commits = read_commit_list_from_git(commits[0], None)
+
+ GlobalSymbol['ECC_PASS'] = True
+ for commit in commits:
+ CheckOneCommit(commit)
+
+ retval = ReleaseReport(EnvList)
+ return retval
+
+if __name__ == "__main__":
+ sys.exit(main())
\ No newline at end of file
--
2.18.0.windows.1


[PATCH v2 1/5] BaseTools:ECC needs to update the contents of CParser4

Zhang, Shenglei
 

From: "Fan, Zhiju" <zhijux.fan@intel.com>

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

Because Ecc relies on the antlr extension package,
When the antlr version is updated, we need to change the code in it.
Currently, if you use the latest version antlr4.8, Ecc will fail

We will update the version to support the use of antlr4.8 and all
previous versions will have errors.This can be resolved by installing
the antlr4.8 version.
Installation method: pip install antlr4-python3-runtime==4.8

This patch is going to fixed this issue

Cc: Bob Feng <bob.c.feng@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Signed-off-by: Zhiju.Fan <zhijux.fan@intel.com>
---
.../Source/Python/Ecc/CParser4/CLexer.py | 6 +--
.../Source/Python/Ecc/CParser4/CListener.py | 4 +-
.../Source/Python/Ecc/CParser4/CParser.py | 38 ++++++++++---------
3 files changed, 25 insertions(+), 23 deletions(-)

diff --git a/BaseTools/Source/Python/Ecc/CParser4/CLexer.py b/BaseTools/Source/Python/Ecc/CParser4/CLexer.py
index a2cc5bf56e66..40e2afbf1a1f 100644
--- a/BaseTools/Source/Python/Ecc/CParser4/CLexer.py
+++ b/BaseTools/Source/Python/Ecc/CParser4/CLexer.py
@@ -1,4 +1,4 @@
-# Generated from C.g4 by ANTLR 4.7.1
+# Generated from C.g4 by ANTLR 4.8
from antlr4 import *
from io import StringIO
from typing.io import TextIO
@@ -12,7 +12,7 @@ import sys
# This file is generated by running:
# java org.antlr.Tool C.g
#
-# Copyright (c) 2009 - 2010, Intel Corporation All rights reserved.
+# Copyright (c) 2009 - 2020, Intel Corporation All rights reserved.
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -584,7 +584,7 @@ class CLexer(Lexer):
# @param output= sys.stdout Type: TextIO
def __init__(self,input=None,output= sys.stdout):
super().__init__(input, output)
- self.checkVersion("4.7.1")
+ self.checkVersion("4.8")
self._interp = LexerATNSimulator(self, self.atn, self.decisionsToDFA, PredictionContextCache())
self._actions = None
self._predicates = None
diff --git a/BaseTools/Source/Python/Ecc/CParser4/CListener.py b/BaseTools/Source/Python/Ecc/CParser4/CListener.py
index bb4351d9249a..ba7e70892680 100644
--- a/BaseTools/Source/Python/Ecc/CParser4/CListener.py
+++ b/BaseTools/Source/Python/Ecc/CParser4/CListener.py
@@ -1,4 +1,4 @@
-# Generated from C.g4 by ANTLR 4.7.1
+# Generated from C.g4 by ANTLR 4.8
from antlr4 import *
if __name__ is not None and "." in __name__:
from .CParser import CParser
@@ -12,7 +12,7 @@ else:
# This file is generated by running:
# java org.antlr.Tool C.g
#
-# Copyright (c) 2009 - 2010, Intel Corporation All rights reserved.
+# Copyright (c) 2009 - 2020, Intel Corporation All rights reserved.
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
diff --git a/BaseTools/Source/Python/Ecc/CParser4/CParser.py b/BaseTools/Source/Python/Ecc/CParser4/CParser.py
index 31d23d55aa57..30d70a74e669 100644
--- a/BaseTools/Source/Python/Ecc/CParser4/CParser.py
+++ b/BaseTools/Source/Python/Ecc/CParser4/CParser.py
@@ -1,10 +1,12 @@
-# Generated from C.g4 by ANTLR 4.7.1
+# Generated from C.g4 by ANTLR 4.8
# encoding: utf-8
from antlr4 import *
from io import StringIO
-from typing.io import TextIO
import sys
-
+if sys.version_info[1] > 5:
+ from typing import TextIO
+else:
+ from typing.io import TextIO

## @file
# The file defines the parser for C source files.
@@ -13,7 +15,7 @@ import sys
# This file is generated by running:
# java org.antlr.Tool C.g
#
-# Copyright (c) 2009 - 2010, Intel Corporation All rights reserved.
+# Copyright (c) 2009 - 2020, Intel Corporation All rights reserved.
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -739,7 +741,7 @@ class CParser ( Parser ):
# @param output= sys.stdout Type: TextIO
def __init__(self,input,output= sys.stdout):
super().__init__(input, output)
- self.checkVersion("4.7.1")
+ self.checkVersion("4.8")
self._interp = ParserATNSimulator(self, self.atn, self.decisionsToDFA, self.sharedContextCache)
self._predicates = None

@@ -1062,10 +1064,10 @@ class CParser ( Parser ):


if localctx.d != None:
- ModifierText = (None if localctx._declaration_specifiers is None else self._input.getText((localctx._declaration_specifiers.start,localctx._declaration_specifiers.stop)))
+ ModifierText = (None if localctx._declaration_specifiers is None else self._input.getText(localctx._declaration_specifiers.start,localctx._declaration_specifiers.stop))
else:
ModifierText = ''
- DeclText = (None if localctx._declarator is None else self._input.getText((localctx._declarator.start,localctx._declarator.stop)))
+ DeclText = (None if localctx._declarator is None else self._input.getText(localctx._declarator.start,localctx._declarator.stop))
DeclLine = (None if localctx._declarator is None else localctx._declarator.start).line
DeclOffset = (None if localctx._declarator is None else localctx._declarator.start).column
if localctx.a != None:
@@ -1245,9 +1247,9 @@ class CParser ( Parser ):
localctx.d = self.match(CParser.T__1)

if localctx.b is not None:
- self.StoreTypedefDefinition(localctx.a.line, localctx.a.column, (0 if localctx.d is None else localctx.d.line), localctx.d.column, (None if localctx.b is None else self._input.getText((localctx.b.start,localctx.b.stop))), (None if localctx.c is None else self._input.getText((localctx.c.start,localctx.c.stop))))
+ self.StoreTypedefDefinition(localctx.a.line, localctx.a.column, (0 if localctx.d is None else localctx.d.line), localctx.d.column, (None if localctx.b is None else self._input.getText(localctx.b.start,localctx.b.stop)), (None if localctx.c is None else self._input.getText(localctx.c.start,localctx.c.stop)))
else:
- self.StoreTypedefDefinition(localctx.a.line, localctx.a.column, (0 if localctx.d is None else localctx.d.line), localctx.d.column, '', (None if localctx.c is None else self._input.getText((localctx.c.start,localctx.c.stop))))
+ self.StoreTypedefDefinition(localctx.a.line, localctx.a.column, (0 if localctx.d is None else localctx.d.line), localctx.d.column, '', (None if localctx.c is None else self._input.getText(localctx.c.start,localctx.c.stop)))

pass
elif token in [CParser.T__5, CParser.T__6, CParser.T__7, CParser.T__8, CParser.T__9, CParser.T__10, CParser.T__11, CParser.T__12, CParser.T__13, CParser.T__14, CParser.T__15, CParser.T__16, CParser.T__17, CParser.T__18, CParser.T__20, CParser.T__21, CParser.T__23, CParser.T__24, CParser.T__25, CParser.T__26, CParser.T__27, CParser.T__28, CParser.T__29, CParser.T__30, CParser.T__31, CParser.T__32, CParser.T__33, CParser.T__34, CParser.T__35, CParser.T__36, CParser.IDENTIFIER]:
@@ -1266,7 +1268,7 @@ class CParser ( Parser ):
localctx.e = self.match(CParser.T__1)

if localctx.t is not None:
- self.StoreVariableDeclaration((None if localctx.s is None else localctx.s.start).line, (None if localctx.s is None else localctx.s.start).column, (None if localctx.t is None else localctx.t.start).line, (None if localctx.t is None else localctx.t.start).column, (None if localctx.s is None else self._input.getText((localctx.s.start,localctx.s.stop))), (None if localctx.t is None else self._input.getText((localctx.t.start,localctx.t.stop))))
+ self.StoreVariableDeclaration((None if localctx.s is None else localctx.s.start).line, (None if localctx.s is None else localctx.s.start).column, (None if localctx.t is None else localctx.t.start).line, (None if localctx.t is None else localctx.t.start).column, (None if localctx.s is None else self._input.getText(localctx.s.start,localctx.s.stop)), (None if localctx.t is None else self._input.getText(localctx.t.start,localctx.t.stop)))

pass
else:
@@ -1568,7 +1570,7 @@ class CParser ( Parser ):
localctx.s = self.struct_or_union_specifier()

if localctx.s.stop is not None:
- self.StoreStructUnionDefinition((None if localctx.s is None else localctx.s.start).line, (None if localctx.s is None else localctx.s.start).column, (None if localctx.s is None else localctx.s.stop).line, (None if localctx.s is None else localctx.s.stop).column, (None if localctx.s is None else self._input.getText((localctx.s.start,localctx.s.stop))))
+ self.StoreStructUnionDefinition((None if localctx.s is None else localctx.s.start).line, (None if localctx.s is None else localctx.s.start).column, (None if localctx.s is None else localctx.s.stop).line, (None if localctx.s is None else localctx.s.stop).column, (None if localctx.s is None else self._input.getText(localctx.s.start,localctx.s.stop)))

pass

@@ -1578,7 +1580,7 @@ class CParser ( Parser ):
localctx.e = self.enum_specifier()

if localctx.e.stop is not None:
- self.StoreEnumerationDefinition((None if localctx.e is None else localctx.e.start).line, (None if localctx.e is None else localctx.e.start).column, (None if localctx.e is None else localctx.e.stop).line, (None if localctx.e is None else localctx.e.stop).column, (None if localctx.e is None else self._input.getText((localctx.e.start,localctx.e.stop))))
+ self.StoreEnumerationDefinition((None if localctx.e is None else localctx.e.start).line, (None if localctx.e is None else localctx.e.start).column, (None if localctx.e is None else localctx.e.stop).line, (None if localctx.e is None else localctx.e.stop).column, (None if localctx.e is None else self._input.getText(localctx.e.start,localctx.e.stop)))

pass

@@ -4022,7 +4024,7 @@ class CParser ( Parser ):
self.enterOuterAlt(localctx, 1)
self.state = 569
localctx.p = self.primary_expression()
- self.FuncCallText += (None if localctx.p is None else self._input.getText((localctx.p.start,localctx.p.stop)))
+ self.FuncCallText += (None if localctx.p is None else self._input.getText(localctx.p.start,localctx.p.stop))
self.state = 600
self._errHandler.sync(self)
_alt = self._interp.adaptivePredict(self._input,73,self._ctx)
@@ -4055,7 +4057,7 @@ class CParser ( Parser ):
localctx.c = self.argument_expression_list()
self.state = 580
localctx.b = self.match(CParser.T__38)
- self.StoreFunctionCalling((None if localctx.p is None else localctx.p.start).line, (None if localctx.p is None else localctx.p.start).column, (0 if localctx.b is None else localctx.b.line), localctx.b.column, self.FuncCallText, (None if localctx.c is None else self._input.getText((localctx.c.start,localctx.c.stop))))
+ self.StoreFunctionCalling((None if localctx.p is None else localctx.p.start).line, (None if localctx.p is None else localctx.p.start).column, (0 if localctx.b is None else localctx.b.line), localctx.b.column, self.FuncCallText, (None if localctx.c is None else self._input.getText(localctx.c.start,localctx.c.stop)))
pass

elif la_ == 4:
@@ -4770,7 +4772,7 @@ class CParser ( Parser ):
self.match(CParser.T__22)
self.state = 674
self.conditional_expression()
- self.StorePredicateExpression((None if localctx.e is None else localctx.e.start).line, (None if localctx.e is None else localctx.e.start).column, (None if localctx.e is None else localctx.e.stop).line, (None if localctx.e is None else localctx.e.stop).column, (None if localctx.e is None else self._input.getText((localctx.e.start,localctx.e.stop))))
+ self.StorePredicateExpression((None if localctx.e is None else localctx.e.start).line, (None if localctx.e is None else localctx.e.start).column, (None if localctx.e is None else localctx.e.stop).line, (None if localctx.e is None else localctx.e.stop).column, (None if localctx.e is None else self._input.getText(localctx.e.start,localctx.e.stop)))


except RecognitionException as re:
@@ -6053,7 +6055,7 @@ class CParser ( Parser ):
localctx.e = self.expression()
self.state = 845
self.match(CParser.T__38)
- self.StorePredicateExpression((None if localctx.e is None else localctx.e.start).line, (None if localctx.e is None else localctx.e.start).column, (None if localctx.e is None else localctx.e.stop).line, (None if localctx.e is None else localctx.e.stop).column, (None if localctx.e is None else self._input.getText((localctx.e.start,localctx.e.stop))))
+ self.StorePredicateExpression((None if localctx.e is None else localctx.e.start).line, (None if localctx.e is None else localctx.e.start).column, (None if localctx.e is None else localctx.e.stop).line, (None if localctx.e is None else localctx.e.stop).column, (None if localctx.e is None else self._input.getText(localctx.e.start,localctx.e.stop)))
self.state = 847
self.statement()
self.state = 850
@@ -6144,7 +6146,7 @@ class CParser ( Parser ):
self.match(CParser.T__38)
self.state = 864
self.statement()
- self.StorePredicateExpression((None if localctx.e is None else localctx.e.start).line, (None if localctx.e is None else localctx.e.start).column, (None if localctx.e is None else localctx.e.stop).line, (None if localctx.e is None else localctx.e.stop).column, (None if localctx.e is None else self._input.getText((localctx.e.start,localctx.e.stop))))
+ self.StorePredicateExpression((None if localctx.e is None else localctx.e.start).line, (None if localctx.e is None else localctx.e.start).column, (None if localctx.e is None else localctx.e.stop).line, (None if localctx.e is None else localctx.e.stop).column, (None if localctx.e is None else self._input.getText(localctx.e.start,localctx.e.stop)))
pass
elif token in [CParser.T__87]:
self.enterOuterAlt(localctx, 2)
@@ -6162,7 +6164,7 @@ class CParser ( Parser ):
self.match(CParser.T__38)
self.state = 873
self.match(CParser.T__1)
- self.StorePredicateExpression((None if localctx.e is None else localctx.e.start).line, (None if localctx.e is None else localctx.e.start).column, (None if localctx.e is None else localctx.e.stop).line, (None if localctx.e is None else localctx.e.stop).column, (None if localctx.e is None else self._input.getText((localctx.e.start,localctx.e.stop))))
+ self.StorePredicateExpression((None if localctx.e is None else localctx.e.start).line, (None if localctx.e is None else localctx.e.start).column, (None if localctx.e is None else localctx.e.stop).line, (None if localctx.e is None else localctx.e.stop).column, (None if localctx.e is None else self._input.getText(localctx.e.start,localctx.e.stop)))
pass
else:
raise NoViableAltException(self)
--
2.18.0.windows.1