MdeModulePkg: Refactor MM Services Tables linked in MM Core Perf Lib

The code used a `MmServicesTableLib` dependency for both the
Standalone MM and Traditional MM instances and shared code between
those. There is not a readily available `MmServicesTable` lib
instance for Traditional SMM (that can link to `PiSmmCore`). To ease
integration and prevent creating an instance just for this case, this
change uses `SmmServicesTableLib` in the Traditional SMM instance and
`MmServicesTableLib` in the Standalone MM instance and moves code as
necessary to accommodate this.

For general reference, there are two available instances of
`MmServicesTableLib`:

- MdePkg/MmServicesTableLib - only supports DXE_SMM drivers.
- MdePkg/StandaloneMmServicesTableLib - supports both MM drivers and
  MM cores.

Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com>
This commit is contained in:
Michael Kubacki
2025-05-28 15:58:14 -04:00
committed by mergify[bot]
parent d297c699c9
commit 1b26c4b73b
5 changed files with 155 additions and 67 deletions

View File

@@ -42,13 +42,6 @@ UINT32 mCachedLength = 0;
UINT32 mBootRecordSize = 0;
BOOLEAN mPerformanceMeasurementEnabled;
//
// Interfaces for SMM PerformanceMeasurement Protocol.
//
EDKII_PERFORMANCE_MEASUREMENT_PROTOCOL mPerformanceMeasurementInterface = {
CreatePerformanceMeasurement,
};
/**
Return the module name and optionally module GUID for a given handle.
@@ -914,62 +907,6 @@ SmmCorePerformanceLibExitBootServicesCallback (
return EFI_SUCCESS;
}
/**
Common initialization code for the MM Core Performance Library.
@param[in] ExitBootServicesProtocolGuid The GUID of the ExitBootServices protocol.
@retval EFI_SUCCESS The MM Core Performance Library was initialized successfully.
@retval Others The MM Core Performance Library was not initialized successfully.
**/
EFI_STATUS
InitializeMmCorePerformanceLibCommon (
IN CONST EFI_GUID *ExitBootServicesProtocolGuid
)
{
EFI_STATUS Status;
EFI_HANDLE Handle;
EFI_HANDLE MmiHandle;
VOID *Registration;
//
// Initialize spin lock
//
InitializeSpinLock (&mSmmFpdtLock);
//
// Install the protocol interfaces for MM performance library instance.
//
Handle = NULL;
Status = gMmst->MmInstallProtocolInterface (
&Handle,
&gEdkiiSmmPerformanceMeasurementProtocolGuid,
EFI_NATIVE_INTERFACE,
&mPerformanceMeasurementInterface
);
ASSERT_EFI_ERROR (Status);
//
// Register MMI handler.
//
MmiHandle = NULL;
Status = gMmst->MmiHandlerRegister (FpdtSmiHandler, &gEfiFirmwarePerformanceGuid, &MmiHandle);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Register callback function for ExitBootServices event.
//
Status = gMmst->MmRegisterProtocolNotify (
ExitBootServicesProtocolGuid,
SmmCorePerformanceLibExitBootServicesCallback,
&Registration
);
return Status;
}
/**
Create performance record with event description and a timestamp.

View File

@@ -26,6 +26,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <Library/DxeServicesLib.h>
#include <Library/SmmMemLib.h>
#include <Library/SmmServicesTableLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiLib.h>
#include <Protocol/SmmBase2.h>
@@ -33,6 +34,12 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
PERFORMANCE_PROPERTY mPerformanceProperty;
extern SPIN_LOCK mSmmFpdtLock;
EDKII_PERFORMANCE_MEASUREMENT_PROTOCOL mPerformanceMeasurementInterface = {
CreatePerformanceMeasurement,
};
/**
A library internal MM-instance specific implementation to check if a buffer outside MM is valid.
@@ -192,10 +199,43 @@ InitializeSmmCorePerformanceLib (
{
EFI_STATUS Status;
PERFORMANCE_PROPERTY *PerformanceProperty;
EFI_HANDLE Handle;
EFI_HANDLE MmiHandle;
VOID *Registration;
Status = InitializeMmCorePerformanceLibCommon (&gEdkiiSmmExitBootServicesProtocolGuid);
//
// Initialize spin lock
//
InitializeSpinLock (&mSmmFpdtLock);
//
// Install the protocol interfaces for MM performance library instance.
//
Handle = NULL;
Status = gSmst->SmmInstallProtocolInterface (
&Handle,
&gEdkiiSmmPerformanceMeasurementProtocolGuid,
EFI_NATIVE_INTERFACE,
&mPerformanceMeasurementInterface
);
ASSERT_EFI_ERROR (Status);
//
// Register MMI handler.
//
MmiHandle = NULL;
Status = gSmst->SmiHandlerRegister (FpdtSmiHandler, &gEfiFirmwarePerformanceGuid, &MmiHandle);
ASSERT_EFI_ERROR (Status);
//
// Register callback function for ExitBootServices event.
//
Status = gSmst->SmmRegisterProtocolNotify (
&gEdkiiSmmExitBootServicesProtocolGuid,
SmmCorePerformanceLibExitBootServicesCallback,
&Registration
);
Status = EfiGetSystemConfigurationTable (&gPerformanceProtocolGuid, (VOID **)&PerformanceProperty);
if (EFI_ERROR (Status)) {
//

View File

@@ -47,10 +47,10 @@
DebugLib
DxeServicesLib
MemoryAllocationLib
MmServicesTableLib
PcdLib
PeCoffGetEntryPointLib
SmmMemLib
SmmServicesTableLib
SynchronizationLib
TimerLib
UefiBootServicesTableLib

View File

@@ -24,7 +24,6 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/MmServicesTableLib.h>
#include <Library/PcdLib.h>
#include <Library/PeCoffGetEntryPointLib.h>
#include <Library/PerformanceLib.h>
@@ -45,6 +44,57 @@ extern BOOLEAN mPerformanceMeasurementEnabled;
// Library internal function declarations
//
/**
Communication service SMI Handler entry.
This SMI handler provides services for report MM boot records.
Caution: This function may receive untrusted input.
Communicate buffer and buffer size are external input, so this function will do basic validation.
@param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
@param[in] RegisterContext Points to an optional handler context which was specified when the
handler was registered.
@param[in, out] CommBuffer A pointer to a collection of data in memory that will
be conveyed from a non-MM environment into an MM environment.
@param[in, out] CommBufferSize The size of the CommBuffer.
@retval EFI_SUCCESS The interrupt was handled and quiesced. No other handlers
should still be called.
@retval EFI_WARN_INTERRUPT_SOURCE_QUIESCED The interrupt has been quiesced but other handlers should
still be called.
@retval EFI_WARN_INTERRUPT_SOURCE_PENDING The interrupt is still pending and other handlers should still
be called.
@retval EFI_INTERRUPT_PENDING The interrupt could not be quiesced.
**/
EFI_STATUS
EFIAPI
FpdtSmiHandler (
IN EFI_HANDLE DispatchHandle,
IN CONST VOID *RegisterContext,
IN OUT VOID *CommBuffer,
IN OUT UINTN *CommBufferSize
);
/**
This is the Event call back function is triggered in SMM to notify the Library
the system is entering runtime phase.
@param[in] Protocol Points to the protocol's unique identifier
@param[in] Interface Points to the interface instance
@param[in] Handle The handle on which the interface was installed
@retval EFI_SUCCESS SmmAtRuntimeCallBack runs successfully
**/
EFI_STATUS
EFIAPI
SmmCorePerformanceLibExitBootServicesCallback (
IN CONST EFI_GUID *Protocol,
IN VOID *Interface,
IN EFI_HANDLE Handle
);
/**
Return a pointer to the loaded image protocol for the given handle.

View File

@@ -17,8 +17,15 @@
#include "SmmCorePerformanceLibInternal.h"
#include <Guid/EventGroup.h>
#include <Library/MmServicesTableLib.h>
#include <Library/StandaloneMmMemLib.h>
extern SPIN_LOCK mSmmFpdtLock;
EDKII_PERFORMANCE_MEASUREMENT_PROTOCOL mPerformanceMeasurementInterface = {
CreatePerformanceMeasurement,
};
/**
A library internal MM-instance specific implementation to check if a buffer outside MM is valid.
@@ -109,6 +116,60 @@ GetNameFromUiSection (
return EFI_NOT_FOUND;
}
/**
Initializes the MM Core Performance library.
@retval EFI_SUCCESS The performance library was initialized successfully.
@retval Other An error occurred during initialization.
**/
EFI_STATUS
EFIAPI
InitializeStandaloneMmCorePerformanceLib (
VOID
)
{
EFI_STATUS Status;
EFI_HANDLE Handle;
EFI_HANDLE MmiHandle;
VOID *Registration;
//
// Initialize spin lock
//
InitializeSpinLock (&mSmmFpdtLock);
//
// Install the protocol interfaces for MM performance library instance.
//
Handle = NULL;
Status = gMmst->MmInstallProtocolInterface (
&Handle,
&gEdkiiSmmPerformanceMeasurementProtocolGuid,
EFI_NATIVE_INTERFACE,
&mPerformanceMeasurementInterface
);
ASSERT_EFI_ERROR (Status);
//
// Register MMI handler.
//
MmiHandle = NULL;
Status = gMmst->MmiHandlerRegister (FpdtSmiHandler, &gEfiFirmwarePerformanceGuid, &MmiHandle);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Register callback function for ExitBootServices event.
//
Status = gMmst->MmRegisterProtocolNotify (
&gEfiEventExitBootServicesGuid,
SmmCorePerformanceLibExitBootServicesCallback,
&Registration
);
return Status;
}
/**
The constructor function initializes the Standalone MM Core performance library.
@@ -140,7 +201,7 @@ StandaloneMmCorePerformanceLibConstructor (
return EFI_SUCCESS;
}
Status = InitializeMmCorePerformanceLibCommon (&gEfiEventExitBootServicesGuid);
Status = InitializeStandaloneMmCorePerformanceLib ();
ASSERT_EFI_ERROR (Status);
return EFI_SUCCESS;