mirror of
https://github.com/acidanthera/audk.git
synced 2025-07-30 17:14:07 +02:00
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>
This commit is contained in:
parent
a2a8558958
commit
d64766bde6
@ -25,6 +25,189 @@ EFI_MM_COMMUNICATION_PROTOCOL mMmCommunication = {
|
|||||||
|
|
||||||
MM_COMM_BUFFER mMmCommonBuffer;
|
MM_COMM_BUFFER mMmCommonBuffer;
|
||||||
EFI_SMM_CONTROL2_PROTOCOL *mSmmControl2;
|
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.
|
Notification function of EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE.
|
||||||
@ -226,6 +409,8 @@ MmCommunicationEntryPoint (
|
|||||||
EFI_HANDLE Handle;
|
EFI_HANDLE Handle;
|
||||||
EFI_HOB_GUID_TYPE *GuidHob;
|
EFI_HOB_GUID_TYPE *GuidHob;
|
||||||
MM_COMM_BUFFER *MmCommonBuffer;
|
MM_COMM_BUFFER *MmCommonBuffer;
|
||||||
|
UINTN Index;
|
||||||
|
VOID *Registration;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Locate gMmCommBufferHobGuid and cache the content
|
// Locate gMmCommBufferHobGuid and cache the content
|
||||||
@ -241,6 +426,12 @@ MmCommunicationEntryPoint (
|
|||||||
Status = gBS->LocateProtocol (&gEfiSmmControl2ProtocolGuid, NULL, (VOID **)&mSmmControl2);
|
Status = gBS->LocateProtocol (&gEfiSmmControl2ProtocolGuid, NULL, (VOID **)&mSmmControl2);
|
||||||
ASSERT_EFI_ERROR (Status);
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Get SMM Access Protocol
|
||||||
|
//
|
||||||
|
Status = gBS->LocateProtocol (&gEfiSmmAccess2ProtocolGuid, NULL, (VOID **)&mSmmAccess);
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
|
||||||
Handle = NULL;
|
Handle = NULL;
|
||||||
Status = gBS->InstallProtocolInterface (
|
Status = gBS->InstallProtocolInterface (
|
||||||
&Handle,
|
&Handle,
|
||||||
@ -259,17 +450,29 @@ MmCommunicationEntryPoint (
|
|||||||
ASSERT_EFI_ERROR (Status);
|
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 (
|
for (Index = 0; mMmEvents[Index].NotificationType != EndNotify; Index++) {
|
||||||
EVT_NOTIFY_SIGNAL,
|
if (mMmEvents[Index].NotificationType == ProtocolNotify) {
|
||||||
TPL_NOTIFY,
|
mMmEvents[Index].Event = EfiCreateProtocolNotifyEvent (
|
||||||
MmVirtualAddressChangeEvent,
|
mMmEvents[Index].Guid,
|
||||||
NULL,
|
TPL_CALLBACK,
|
||||||
&gEfiEventVirtualAddressChangeGuid,
|
mMmEvents[Index].NotifyFunction,
|
||||||
NULL
|
mMmEvents[Index].NotifyContext,
|
||||||
);
|
&Registration
|
||||||
ASSERT_EFI_ERROR (Status);
|
);
|
||||||
|
} 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;
|
return EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -19,14 +19,36 @@
|
|||||||
#include <Library/BaseMemoryLib.h>
|
#include <Library/BaseMemoryLib.h>
|
||||||
#include <Library/MemoryAllocationLib.h>
|
#include <Library/MemoryAllocationLib.h>
|
||||||
#include <Library/UefiRuntimeLib.h>
|
#include <Library/UefiRuntimeLib.h>
|
||||||
|
#include <Library/ReportStatusCodeLib.h>
|
||||||
|
|
||||||
#include <Protocol/SmmControl2.h>
|
#include <Protocol/SmmControl2.h>
|
||||||
#include <Protocol/MmCommunication2.h>
|
#include <Protocol/MmCommunication2.h>
|
||||||
#include <Protocol/MmCommunication.h>
|
#include <Protocol/MmCommunication.h>
|
||||||
|
#include <Protocol/DxeMmReadyToLock.h>
|
||||||
|
#include <Protocol/SmmAccess2.h>
|
||||||
|
|
||||||
#include <Guid/MmCommBuffer.h>
|
#include <Guid/MmCommBuffer.h>
|
||||||
#include <Guid/EventGroup.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.
|
Communicates with a registered handler.
|
||||||
|
|
||||||
@ -91,4 +113,64 @@ MmCommunicate (
|
|||||||
IN OUT UINTN *CommSize OPTIONAL
|
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
|
#endif
|
||||||
|
@ -37,15 +37,20 @@
|
|||||||
UefiBootServicesTableLib
|
UefiBootServicesTableLib
|
||||||
UefiLib
|
UefiLib
|
||||||
UefiRuntimeLib
|
UefiRuntimeLib
|
||||||
|
ReportStatusCodeLib
|
||||||
|
|
||||||
[Guids]
|
[Guids]
|
||||||
gMmCommBufferHobGuid
|
gMmCommBufferHobGuid
|
||||||
gEfiEventVirtualAddressChangeGuid
|
gEfiEventVirtualAddressChangeGuid
|
||||||
|
gEfiEndOfDxeEventGroupGuid
|
||||||
|
gEfiEventExitBootServicesGuid
|
||||||
|
|
||||||
[Protocols]
|
[Protocols]
|
||||||
gEfiMmCommunication2ProtocolGuid
|
gEfiMmCommunication2ProtocolGuid
|
||||||
gEfiSmmControl2ProtocolGuid
|
gEfiSmmControl2ProtocolGuid
|
||||||
gEfiMmCommunicationProtocolGuid
|
gEfiMmCommunicationProtocolGuid
|
||||||
|
gEfiDxeMmReadyToLockProtocolGuid
|
||||||
|
gEfiSmmAccess2ProtocolGuid
|
||||||
|
|
||||||
[Depex]
|
[Depex]
|
||||||
gEfiSmmControl2ProtocolGuid
|
gEfiSmmAccess2ProtocolGuid AND gEfiSmmControl2ProtocolGuid
|
||||||
|
Loading…
x
Reference in New Issue
Block a user