mirror of https://github.com/acidanthera/audk.git
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;
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -37,15 +37,20 @@
|
|||
UefiBootServicesTableLib
|
||||
UefiLib
|
||||
UefiRuntimeLib
|
||||
ReportStatusCodeLib
|
||||
|
||||
[Guids]
|
||||
gMmCommBufferHobGuid
|
||||
gEfiEventVirtualAddressChangeGuid
|
||||
gEfiEndOfDxeEventGroupGuid
|
||||
gEfiEventExitBootServicesGuid
|
||||
|
||||
[Protocols]
|
||||
gEfiMmCommunication2ProtocolGuid
|
||||
gEfiSmmControl2ProtocolGuid
|
||||
gEfiMmCommunicationProtocolGuid
|
||||
gEfiDxeMmReadyToLockProtocolGuid
|
||||
gEfiSmmAccess2ProtocolGuid
|
||||
|
||||
[Depex]
|
||||
gEfiSmmControl2ProtocolGuid
|
||||
gEfiSmmAccess2ProtocolGuid AND gEfiSmmControl2ProtocolGuid
|
||||
|
|
Loading…
Reference in New Issue