Skip to content

Commit

Permalink
Introduce Standalone MM Policy Service (#390)
Browse files Browse the repository at this point in the history
## Description

Introduces the service modules, test, and library implementation for a
standalone MM policy service.

- [x] Impacts functionality?
- [ ] Impacts security?
- [ ] Breaking change?
- [x] Includes tests?
- [x] Includes documentation?

## How This Was Tested

Tested using the test module for MM and regression tested PEI and DXE.

## Integration Instructions

PolicyDxe was moved to the DxeMm folder. Consumers should update their
DSCs.

(cherry picked from commit a296f04)
  • Loading branch information
cfernald authored and kenlautner committed Dec 18, 2023
1 parent c149b3f commit a8dee78
Show file tree
Hide file tree
Showing 18 changed files with 839 additions and 160 deletions.
21 changes: 21 additions & 0 deletions PolicyServicePkg/Include/Protocol/MmPolicy.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/** @file
This protocol provides services to publish, update, and retrieve general policies in the MM
environment.
Copyright (c) Microsoft Corporation
SPDX-License-Identifier: BSD-2-Clause-Patent
**/

#ifndef _MM_POLICY_PROTOCOL_H_
#define _MM_POLICY_PROTOCOL_H_

#include <PolicyInterface.h>

#define MM_POLICY_PROTOCOL_GUID { 0xe55ad3a1, 0xbd34, 0x46f4, { 0xbb, 0x6e, 0x72, 0x28, 0x0b, 0xdc, 0xbf, 0xd9 } }

typedef struct _POLICY_INTERFACE MM_POLICY_PROTOCOL;

extern EFI_GUID gMmPolicyProtocolGuid;

#endif
53 changes: 53 additions & 0 deletions PolicyServicePkg/Library/MmPolicyLib/MmPolicy.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/** @file
Implementation of the Verified Policy library for MM.
Copyright (c) Microsoft Corporation
SPDX-License-Identifier: BSD-2-Clause-Patent
**/

#include <Uefi.h>
#include <Library/MmServicesTableLib.h>
#include <Library/DebugLib.h>
#include <Library/BaseLib.h>

#include <Protocol/MmPolicy.h>
#include <Library/VerifiedPolicy.h>

#include "../PolicyLibCommon.h"

/**
A private helper function to retrieve the policy service protocol.
@param[out] PolicyInterface Returns with the pointer to the protocol.
@retval EFI_SUCCESS Policy protocol was found.
@retval EFI_NOT_FOUND Policy protocol was not found.
**/
EFI_STATUS
GetPolicyInterface (
OUT POLICY_INTERFACE **PolicyInterface
)
{
EFI_STATUS Status;
STATIC MM_POLICY_PROTOCOL *mPolicyProtocol = NULL;

Status = EFI_SUCCESS;
if (mPolicyProtocol == NULL) {
Status = gMmst->MmLocateProtocol (
&gMmPolicyProtocolGuid,
NULL,
(VOID **)&mPolicyProtocol
);

if (EFI_ERROR (Status)) {
mPolicyProtocol = NULL;
}
}

if (mPolicyProtocol != NULL) {
*PolicyInterface = mPolicyProtocol;
}

return Status;
}
36 changes: 36 additions & 0 deletions PolicyServicePkg/Library/MmPolicyLib/MmPolicyLib.inf
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
## @file
# MM instance of verified policy library.
#
# Copyright (c) Microsoft Corporation.
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##

[Defines]
INF_VERSION = 1.26
PI_SPECIFICATION_VERSION = 0x00010032
BASE_NAME = MmPolicyLib
FILE_GUID = C2A9C781-8D58-46DA-BC39-5385AB8D5C8A
MODULE_TYPE = MM_STANDALONE
VERSION_STRING = 1.0
LIBRARY_CLASS = PolicyLib | MM_STANDALONE

[Sources]
../PolicyLibCommon.c
../PolicyLibCommon.h
MmPolicy.c

[Packages]
MdePkg/MdePkg.dec
PolicyServicePkg/PolicyServicePkg.dec

[LibraryClasses]
BaseLib
DebugLib
MmServicesTableLib

[Protocols]
gMmPolicyProtocolGuid ## CONSUMES

[Pcd]
Original file line number Diff line number Diff line change
@@ -1,60 +1,16 @@
/** @file
Implements the DXE policy protocol, providing services to publish and access
system policy.
Common function implementations for storing and finding policies for the DXE/MM
policy service modules.
Copyright (c) Microsoft Corporation
SPDX-License-Identifier: BSD-2-Clause-Patent
**/

#include "PolicyDxe.h"
#include "PolicyCommon.h"
#include "PolicyInterface.h"

STATIC LIST_ENTRY mPolicyListHead = INITIALIZE_LIST_HEAD_VARIABLE (mPolicyListHead);
STATIC EFI_LOCK mPolicyListLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY);
STATIC EFI_HANDLE mImageHandle = NULL;

POLICY_PROTOCOL mPolicyProtocol = {
DxeSetPolicy,
DxeGetPolicy,
DxeRemovePolicy
};

/**
Creates and emptry protocol for a given GUID to notify or dispatch consumers of
this policy GUID. If the protocol already exists it will be reinstalled.
@param[in] PolicyGuid The policy GUID used for the protocol.
@retval EFI_SUCCESS The protocol was installed or reinstalled.
**/
EFI_STATUS
EFIAPI
DxeInstallPolicyIndicatorProtocol (
IN CONST EFI_GUID *PolicyGuid
)
{
EFI_STATUS Status;
VOID *Interface;

Status = gBS->LocateProtocol ((EFI_GUID *)PolicyGuid, NULL, &Interface);
if (EFI_ERROR (Status)) {
Status = gBS->InstallMultipleProtocolInterfaces (
&mImageHandle,
PolicyGuid,
NULL,
NULL
);
} else {
Status = gBS->ReinstallProtocolInterface (
mImageHandle,
(EFI_GUID *)PolicyGuid,
NULL,
NULL
);
}

return Status;
}

/**
Retrieves the policy descriptor, buffer, and size for a given policy GUID.
Expand All @@ -72,7 +28,7 @@ DxeInstallPolicyIndicatorProtocol (
**/
EFI_STATUS
EFIAPI
DxeGetPolicyEntry (
GetPolicyEntry (
IN CONST EFI_GUID *PolicyGuid,
OUT POLICY_ENTRY **PolicyEntry
)
Expand Down Expand Up @@ -102,13 +58,13 @@ DxeGetPolicyEntry (
**/
BOOLEAN
EFIAPI
DxeCheckPolicyExists (
CheckPolicyExists (
IN CONST EFI_GUID *PolicyGuid
)
{
POLICY_ENTRY *Entry;

return !EFI_ERROR (DxeGetPolicyEntry (PolicyGuid, &Entry));
return !EFI_ERROR (GetPolicyEntry (PolicyGuid, &Entry));
}

/**
Expand All @@ -126,7 +82,7 @@ DxeCheckPolicyExists (
**/
EFI_STATUS
EFIAPI
DxeGetPolicy (
GetPolicy (
IN CONST EFI_GUID *PolicyGuid,
OUT UINT64 *Attributes OPTIONAL,
OUT VOID *Policy,
Expand All @@ -143,8 +99,8 @@ DxeGetPolicy (
return EFI_INVALID_PARAMETER;
}

EfiAcquireLock (&mPolicyListLock);
Status = DxeGetPolicyEntry (PolicyGuid, &Entry);
PolicyLockAcquire ();
Status = GetPolicyEntry (PolicyGuid, &Entry);
if (EFI_ERROR (Status)) {
goto Exit;
}
Expand All @@ -163,7 +119,7 @@ DxeGetPolicy (
*PolicySize = Entry->PolicySize;

Exit:
EfiReleaseLock (&mPolicyListLock);
PolicyLockRelease ();
return Status;
}

Expand All @@ -187,7 +143,7 @@ IngestPoliciesFromHob (

PolicyCount = 0;
Status = EFI_SUCCESS;
EfiAcquireLock (&mPolicyListLock);
PolicyLockAcquire ();
for (GuidHob = GetFirstGuidHob (&gPolicyHobGuid);
GuidHob != NULL;
GuidHob = GetNextGuidHob (&gPolicyHobGuid, GET_NEXT_HOB (GuidHob)))
Expand All @@ -201,7 +157,7 @@ IngestPoliciesFromHob (
continue;
}

ASSERT (!DxeCheckPolicyExists (&PolicyHob->PolicyGuid));
ASSERT (!CheckPolicyExists (&PolicyHob->PolicyGuid));

PolicyEntry = AllocatePool (sizeof (POLICY_ENTRY));
if (PolicyEntry == NULL) {
Expand All @@ -220,7 +176,7 @@ IngestPoliciesFromHob (
InsertTailList (&mPolicyListHead, &PolicyEntry->Link);
PolicyCount++;

Status = DxeInstallPolicyIndicatorProtocol (&PolicyEntry->PolicyGuid);
Status = InstallPolicyIndicatorProtocol (&PolicyEntry->PolicyGuid);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "%a: Failed to install notification protocol. (%r)\n", __FUNCTION__, Status));
}
Expand All @@ -230,7 +186,7 @@ IngestPoliciesFromHob (
DEBUG ((DEBUG_INFO, "Found %d active policies in HOBs.\n", PolicyCount));
}

EfiReleaseLock (&mPolicyListLock);
PolicyLockRelease ();
return Status;
}

Expand All @@ -245,7 +201,7 @@ IngestPoliciesFromHob (
**/
EFI_STATUS
EFIAPI
DxeRemovePolicy (
RemovePolicy (
IN CONST EFI_GUID *PolicyGuid
)
{
Expand All @@ -256,8 +212,8 @@ DxeRemovePolicy (
return EFI_INVALID_PARAMETER;
}

EfiAcquireLock (&mPolicyListLock);
Status = DxeGetPolicyEntry (PolicyGuid, &Entry);
PolicyLockAcquire ();
Status = GetPolicyEntry (PolicyGuid, &Entry);
if (!EFI_ERROR (Status)) {
RemoveEntryList (&Entry->Link);
if (!Entry->FromHob) {
Expand All @@ -267,7 +223,7 @@ DxeRemovePolicy (
FreePool (Entry);
}

EfiReleaseLock (&mPolicyListLock);
PolicyLockRelease ();
return Status;
}

Expand All @@ -287,7 +243,7 @@ DxeRemovePolicy (
**/
EFI_STATUS
EFIAPI
DxeSetPolicy (
SetPolicy (
IN CONST EFI_GUID *PolicyGuid,
IN UINT64 Attributes,
IN VOID *Policy,
Expand All @@ -302,8 +258,8 @@ DxeSetPolicy (
return EFI_INVALID_PARAMETER;
}

EfiAcquireLock (&mPolicyListLock);
Status = DxeGetPolicyEntry (PolicyGuid, &Entry);
PolicyLockAcquire ();
Status = GetPolicyEntry (PolicyGuid, &Entry);
if (!EFI_ERROR (Status)) {
if (Entry->Attributes & POLICY_ATTRIBUTE_FINALIZED) {
Status = EFI_ACCESS_DENIED;
Expand Down Expand Up @@ -357,48 +313,13 @@ DxeSetPolicy (
InsertTailList (&mPolicyListHead, &Entry->Link);
}

Status = DxeInstallPolicyIndicatorProtocol (PolicyGuid);
Status = InstallPolicyIndicatorProtocol (PolicyGuid);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "%a: Failed to install notification protocol. (%r)\n", __FUNCTION__, Status));
goto Exit;
}

Exit:
EfiReleaseLock (&mPolicyListLock);
PolicyLockRelease ();
return Status;
}

/**
DXE policy driver entry point. Initialized the policy store from the HOB list
and install the DXE policy protocol.
@param[in] ImageHandle The firmware allocated handle for the EFI image.
@param[in] SystemTable UNUSED.
@retval EFI_SUCCESS Policy store initialized and protocol installed.
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory for policy and global structures.
**/
EFI_STATUS
EFIAPI
DxePolicyEntry (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;

// Process the HOBs to consume any existing policies.
mImageHandle = ImageHandle;
Status = IngestPoliciesFromHob ();
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "%a: Failed to ingest HOB policies. (%r)\n", __FUNCTION__, Status));
return Status;
}

return gBS->InstallMultipleProtocolInterfaces (
&ImageHandle,
&gPolicyProtocolGuid,
&mPolicyProtocol,
NULL
);
}
Loading

0 comments on commit a8dee78

Please sign in to comment.