diff options
author | Dun Tan <dun.tan@intel.com> | 2024-06-11 11:40:24 +0800 |
---|---|---|
committer | mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> | 2024-08-28 15:25:27 +0000 |
commit | d64766bde654a57e3e329e8e6a906e993df6a58c (patch) | |
tree | cf1e077725d4f4f6dcf976b2c94b108c1bd9cc7d | |
parent | a2a8558958cee97efd132361a2b29f2ee8339d91 (diff) | |
download | edk2-d64766bde654a57e3e329e8e6a906e993df6a58c.tar.gz |
StandaloneMmPkg: Create some notification of protocol and Event
Create the notifications of some protocols and event that
the Standalone Mm requires in MmCommunicationDxe:
gEfiDxeMmReadyToLockProtocolGuid
gEfiEventExitBootServicesGuid
gEfiEventVirtualAddressChangeGuid
gEfiEndOfDxeEventGroupGuid
gEfiEventReadyToBootGuid
Signed-off-by: Dun Tan <dun.tan@intel.com>
3 files changed, 301 insertions, 11 deletions
diff --git a/StandaloneMmPkg/Drivers/MmCommunicationDxe/MmCommunicationDxe.c b/StandaloneMmPkg/Drivers/MmCommunicationDxe/MmCommunicationDxe.c index b4c634db77..7b1e0636ff 100644 --- a/StandaloneMmPkg/Drivers/MmCommunicationDxe/MmCommunicationDxe.c +++ b/StandaloneMmPkg/Drivers/MmCommunicationDxe/MmCommunicationDxe.c @@ -25,6 +25,189 @@ EFI_MM_COMMUNICATION_PROTOCOL mMmCommunication = { MM_COMM_BUFFER mMmCommonBuffer;
EFI_SMM_CONTROL2_PROTOCOL *mSmmControl2;
+EFI_SMM_ACCESS2_PROTOCOL *mSmmAccess;
+BOOLEAN mSmmLocked = FALSE;
+BOOLEAN mEndOfDxe = FALSE;
+
+//
+// Table of Protocol notification and GUIDed Event notifications that the Standalone Mm requires
+//
+MM_EVENT_NOTIFICATION mMmEvents[] = {
+ //
+ // Declare protocol notification on DxeMmReadyToLock protocols. When this notification is established,
+ // the associated event is immediately signalled, so the notification function will be executed and the
+ // DXE Mm Ready To Lock Protocol will be found if it is already in the handle database.
+ //
+ { ProtocolNotify, TRUE, &gEfiDxeMmReadyToLockProtocolGuid, MmReadyToLockEventNotify, &gEfiDxeMmReadyToLockProtocolGuid, NULL },
+ //
+ // Declare event notification on Ready To Boot Event Group. This is an extra event notification that is
+ // used to make sure SMRAM is locked before any boot options are processed.
+ //
+ { EventNotify, TRUE, &gEfiEventReadyToBootGuid, MmReadyToLockEventNotify, &gEfiEventReadyToBootGuid, NULL },
+ //
+ // Declare event notification on Ready To Boot Event Group. This is used to inform the MM Core
+ // to notify MM driver that system enter ready to boot.
+ //
+ { EventNotify, FALSE, &gEfiEventReadyToBootGuid, MmGuidedEventNotify, &gEfiEventReadyToBootGuid, NULL },
+ //
+ // Declare event notification on EndOfDxe event. When this notification is established,
+ // the associated event is immediately signalled, so the notification function will be executed and the
+ // End Of Dxe Protocol will be found if it is already in the handle database.
+ //
+ { EventNotify, TRUE, &gEfiEndOfDxeEventGroupGuid, MmGuidedEventNotify, &gEfiEndOfDxeEventGroupGuid, NULL },
+ //
+ // Declare event notification on EndOfDxe event. This is used to set EndOfDxe event signaled flag.
+ //
+ { EventNotify, TRUE, &gEfiEndOfDxeEventGroupGuid, MmEndOfDxeEventNotify, &gEfiEndOfDxeEventGroupGuid, NULL },
+ //
+ // Declare event notification on Exit Boot Services Event Group. This is used to inform the MM Core
+ // to notify MM driver that system enter exit boot services.
+ //
+ { EventNotify, FALSE, &gEfiEventExitBootServicesGuid, MmGuidedEventNotify, &gEfiEventExitBootServicesGuid, NULL },
+ //
+ // Declare event notification on SetVirtualAddressMap() Event Group. This is used to convert fixed MM communication buffer
+ // and MM_COMM_BUFFER_STATUS in mMmCommonBuffer, mSmmControl2 from physical addresses to virtual addresses.
+ //
+ { EventNotify, FALSE, &gEfiEventVirtualAddressChangeGuid, MmVirtualAddressChangeEvent, NULL, NULL },
+ //
+ // Terminate the table of event notifications
+ //
+ { EndNotify, FALSE, NULL, NULL, NULL, NULL }
+};
+
+/**
+ Event notification that is fired when GUIDed Event Group is signaled.
+
+ @param Event The Event that is being processed, not used.
+ @param Context Event Context, not used.
+
+**/
+VOID
+EFIAPI
+MmGuidedEventNotify (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ UINTN Size;
+ EFI_MM_COMMUNICATE_HEADER *CommunicateHeader;
+
+ CommunicateHeader = (EFI_MM_COMMUNICATE_HEADER *)(UINTN)mMmCommonBuffer.PhysicalStart;
+
+ //
+ // Use Guid to initialize EFI_MM_COMMUNICATE_HEADER structure
+ //
+ CopyGuid (&CommunicateHeader->HeaderGuid, (EFI_GUID *)Context);
+ CommunicateHeader->MessageLength = 1;
+ CommunicateHeader->Data[0] = 0;
+
+ //
+ // Generate the Software SMI and return the result
+ //
+ Size = sizeof (EFI_MM_COMMUNICATE_HEADER);
+ MmCommunicate2 (&mMmCommunication2, CommunicateHeader, CommunicateHeader, &Size);
+}
+
+/**
+ Event notification that is fired every time a DxeSmmReadyToLock protocol is added
+ or if gEfiEventReadyToBootGuid is signaled.
+
+ @param Event The Event that is being processed, not used.
+ @param Context Event Context, not used.
+
+**/
+VOID
+EFIAPI
+MmReadyToLockEventNotify (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ VOID *Interface;
+ UINTN Index;
+
+ //
+ // See if we are already locked
+ //
+ if (mSmmLocked) {
+ return;
+ }
+
+ //
+ // Make sure this notification is for this handler
+ //
+ if (CompareGuid ((EFI_GUID *)Context, &gEfiDxeMmReadyToLockProtocolGuid)) {
+ Status = gBS->LocateProtocol (&gEfiDxeMmReadyToLockProtocolGuid, NULL, &Interface);
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+ } else {
+ //
+ // If MM is not locked yet and we got here from gEfiEventReadyToBootGuid being
+ // signaled, then gEfiDxeMmReadyToLockProtocolGuid was not installed as expected.
+ // Print a warning on debug builds.
+ //
+ DEBUG ((DEBUG_WARN, "DXE Mm Ready To Lock Protocol not installed before Ready To Boot signal\n"));
+ }
+
+ if (!mEndOfDxe) {
+ DEBUG ((DEBUG_ERROR, "EndOfDxe Event must be signaled before DxeSmmReadyToLock Protocol installation!\n"));
+ REPORT_STATUS_CODE (
+ EFI_ERROR_CODE | EFI_ERROR_UNRECOVERED,
+ (EFI_SOFTWARE_SMM_DRIVER | EFI_SW_EC_ILLEGAL_SOFTWARE_STATE)
+ );
+ ASSERT (FALSE);
+ }
+
+ //
+ // Lock the SMRAM (Note: Locking SMRAM may not be supported on all platforms)
+ //
+ mSmmAccess->Lock (mSmmAccess);
+
+ //
+ // Close protocol and event notification events that do not apply after the
+ // DXE MM Ready To Lock Protocol has been installed or the Ready To Boot
+ // event has been signalled.
+ //
+ for (Index = 0; mMmEvents[Index].NotifyFunction != NULL; Index++) {
+ if (mMmEvents[Index].CloseOnLock) {
+ gBS->CloseEvent (mMmEvents[Index].Event);
+ }
+ }
+
+ //
+ // Inform MM Core that the DxeSmmReadyToLock protocol was installed
+ //
+ MmGuidedEventNotify (Event, (VOID *)&gEfiDxeMmReadyToLockProtocolGuid);
+
+ //
+ // Print debug message that the SMRAM window is now locked.
+ //
+ DEBUG ((DEBUG_INFO, "MmCommunicationDxe locked SMRAM window\n"));
+
+ //
+ // Set flag so this operation will not be performed again
+ //
+ mSmmLocked = TRUE;
+}
+
+/**
+ Event notification that is fired when EndOfDxe Event Group is signaled.
+
+ @param Event The Event that is being processed, not used.
+ @param Context Event Context, not used.
+
+**/
+VOID
+EFIAPI
+MmEndOfDxeEventNotify (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ mEndOfDxe = TRUE;
+}
/**
Notification function of EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE.
@@ -226,6 +409,8 @@ MmCommunicationEntryPoint ( EFI_HANDLE Handle;
EFI_HOB_GUID_TYPE *GuidHob;
MM_COMM_BUFFER *MmCommonBuffer;
+ UINTN Index;
+ VOID *Registration;
//
// Locate gMmCommBufferHobGuid and cache the content
@@ -241,6 +426,12 @@ MmCommunicationEntryPoint ( Status = gBS->LocateProtocol (&gEfiSmmControl2ProtocolGuid, NULL, (VOID **)&mSmmControl2);
ASSERT_EFI_ERROR (Status);
+ //
+ // Get SMM Access Protocol
+ //
+ Status = gBS->LocateProtocol (&gEfiSmmAccess2ProtocolGuid, NULL, (VOID **)&mSmmAccess);
+ ASSERT_EFI_ERROR (Status);
+
Handle = NULL;
Status = gBS->InstallProtocolInterface (
&Handle,
@@ -259,17 +450,29 @@ MmCommunicationEntryPoint ( ASSERT_EFI_ERROR (Status);
//
- // Register the event to convert the pointer for runtime.
+ // Create the set of protocol and event notifications that the Standalone Mm requires
//
- Status = gBS->CreateEventEx (
- EVT_NOTIFY_SIGNAL,
- TPL_NOTIFY,
- MmVirtualAddressChangeEvent,
- NULL,
- &gEfiEventVirtualAddressChangeGuid,
- NULL
- );
- ASSERT_EFI_ERROR (Status);
+ for (Index = 0; mMmEvents[Index].NotificationType != EndNotify; Index++) {
+ if (mMmEvents[Index].NotificationType == ProtocolNotify) {
+ mMmEvents[Index].Event = EfiCreateProtocolNotifyEvent (
+ mMmEvents[Index].Guid,
+ TPL_CALLBACK,
+ mMmEvents[Index].NotifyFunction,
+ mMmEvents[Index].NotifyContext,
+ &Registration
+ );
+ } else {
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ mMmEvents[Index].NotifyFunction,
+ mMmEvents[Index].NotifyContext,
+ mMmEvents[Index].Guid,
+ &mMmEvents[Index].Event
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+ }
return EFI_SUCCESS;
}
diff --git a/StandaloneMmPkg/Drivers/MmCommunicationDxe/MmCommunicationDxe.h b/StandaloneMmPkg/Drivers/MmCommunicationDxe/MmCommunicationDxe.h index 603cc7691c..d84d8218ec 100644 --- a/StandaloneMmPkg/Drivers/MmCommunicationDxe/MmCommunicationDxe.h +++ b/StandaloneMmPkg/Drivers/MmCommunicationDxe/MmCommunicationDxe.h @@ -19,14 +19,36 @@ #include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/UefiRuntimeLib.h>
+#include <Library/ReportStatusCodeLib.h>
#include <Protocol/SmmControl2.h>
#include <Protocol/MmCommunication2.h>
#include <Protocol/MmCommunication.h>
+#include <Protocol/DxeMmReadyToLock.h>
+#include <Protocol/SmmAccess2.h>
#include <Guid/MmCommBuffer.h>
#include <Guid/EventGroup.h>
+typedef enum {
+ EventNotify,
+ ProtocolNotify,
+ EndNotify,
+} NOTIFICATION_TYPE;
+
+//
+// Data structure used to declare a table of protocol notifications and event
+// notifications required by the Standalone Mm environment
+//
+typedef struct {
+ NOTIFICATION_TYPE NotificationType;
+ BOOLEAN CloseOnLock;
+ EFI_GUID *Guid;
+ EFI_EVENT_NOTIFY NotifyFunction;
+ VOID *NotifyContext;
+ EFI_EVENT Event;
+} MM_EVENT_NOTIFICATION;
+
/**
Communicates with a registered handler.
@@ -91,4 +113,64 @@ MmCommunicate ( IN OUT UINTN *CommSize OPTIONAL
);
+/**
+ Event notification that is fired every time a DxeSmmReadyToLock protocol is added
+ or if gEfiEventReadyToBootGuid is signaled.
+
+ @param Event The Event that is being processed, not used.
+ @param Context Event Context, not used.
+
+**/
+VOID
+EFIAPI
+MmReadyToLockEventNotify (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+/**
+ Event notification that is fired when GUIDed Event Group is signaled.
+
+ @param Event The Event that is being processed, not used.
+ @param Context Event Context, not used.
+
+**/
+VOID
+EFIAPI
+MmGuidedEventNotify (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+/**
+ Event notification that is fired when EndOfDxe Event Group is signaled.
+
+ @param Event The Event that is being processed, not used.
+ @param Context Event Context, not used.
+
+**/
+VOID
+EFIAPI
+MmEndOfDxeEventNotify (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+/**
+ Notification function of EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE.
+
+ This is a notification function registered on EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.
+ It convers pointer to new virtual address.
+
+ @param[in] Event Event whose notification function is being invoked.
+ @param[in] Context Pointer to the notification function's context.
+
+**/
+VOID
+EFIAPI
+MmVirtualAddressChangeEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
#endif
diff --git a/StandaloneMmPkg/Drivers/MmCommunicationDxe/MmCommunicationDxe.inf b/StandaloneMmPkg/Drivers/MmCommunicationDxe/MmCommunicationDxe.inf index c46a3ba8bb..821df02fdc 100644 --- a/StandaloneMmPkg/Drivers/MmCommunicationDxe/MmCommunicationDxe.inf +++ b/StandaloneMmPkg/Drivers/MmCommunicationDxe/MmCommunicationDxe.inf @@ -37,15 +37,20 @@ UefiBootServicesTableLib
UefiLib
UefiRuntimeLib
+ ReportStatusCodeLib
[Guids]
gMmCommBufferHobGuid
gEfiEventVirtualAddressChangeGuid
+ gEfiEndOfDxeEventGroupGuid
+ gEfiEventExitBootServicesGuid
[Protocols]
gEfiMmCommunication2ProtocolGuid
gEfiSmmControl2ProtocolGuid
gEfiMmCommunicationProtocolGuid
+ gEfiDxeMmReadyToLockProtocolGuid
+ gEfiSmmAccess2ProtocolGuid
[Depex]
- gEfiSmmControl2ProtocolGuid
+ gEfiSmmAccess2ProtocolGuid AND gEfiSmmControl2ProtocolGuid
|