[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@...>
Cc: Hao A Wu <hao.a.wu@...>
Cc: Liming Gao <liming.gao@...>
Cc: Bret Barkelew <brbarkel@...>
Signed-off-by: Bret Barkelew <brbarkel@...>
---
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

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