Understanding how DXE triggers and communicates with SMM
Memory regions involved in DXE-SMM communication
Understanding how platforms transition into Management Mode
Step-by-step walkthrough of DXE-SMM communication
Understanding the EFI_MM_COMMUNICATE_HEADER structure
EFI_MM_COMMUNICATE_HEADER { HeaderGuid, MessageLength, Data[] }
How SMM/MM drivers register handlers for dispatch
Understanding the differences
Core SMM communication implementation in EDK2
// MdeModulePkg/Core/PiSmmIpl/PiSmmIpl.c
EFI_STATUS
EFIAPI
SmmCommunicationCommunicate (
IN CONST EFI_SMM_COMMUNICATION_PROTOCOL *This,
IN OUT VOID *CommBuffer,
IN OUT UINTN *CommSize OPTIONAL
)
{
//
// Validate CommBuffer and CommSize
//
CommunicateHeader = (EFI_MM_COMMUNICATE_HEADER *)CommBuffer;
...
//
// Save the comm buffer pointer in a well-known secure location
// so MM Core can find it after Trap
//
gSmmCorePrivate->CommunicationBuffer = CommBuffer;
gSmmCorePrivate->BufferSize = TempCommSize;
//
// Trigger Hardware Trap (e.g. Software SMI via 0xB2 or SMC)
//
IoWrite8 (0xB2, gSmmCorePrivate->SwSmiValue); // x86 specific
// For ARM: ArmCallSmc (SMC_ARG_SMM_COMMUNICATE...)
//
// After RSM / SMC return, execution resumes here
// Return status is already in CommBuffer
//
return gSmmCorePrivate->ReturnStatus;
}
// MdeModulePkg/Core/PiSmmCore/PiSmmCore.c (or StandaloneMmCore)
VOID
EFIAPI
SmmEntryPoint (
IN CONST EFI_SMM_ENTRY_CONTEXT *SmmEntryContext
)
{
//
// Check if this trap was triggered by Communicate()
//
if (gSmmCorePrivate->CommunicationBuffer != NULL) {
CommunicateHeader = (EFI_MM_COMMUNICATE_HEADER *)
gSmmCorePrivate->CommunicationBuffer;
//
// Validate buffer is outside Secure Memory
//
BufferSize = GetCommBufferSize (CommunicateHeader);
if (!SmmIsBufferOutsideSmmValid (
(UINTN)CommunicateHeader, BufferSize)) {
gSmmCorePrivate->ReturnStatus = EFI_ACCESS_DENIED;
return;
}
//
// Dispatch to registered handler by GUID
//
gSmmCorePrivate->ReturnStatus = SmiManage ( // Or MmiManage
&CommunicateHeader->HeaderGuid,
NULL,
CommunicateHeader->Data,
&CommunicateHeader->MessageLength
);
}
//
// Also dispatch root MM handlers (NULL GUID)
//
SmiManage (NULL, NULL, NULL, NULL); // Or MmiManage
}
// MdeModulePkg/Core/PiSmmCore/Smi.c (or StandaloneMmPkg Mmi.c)
EFI_STATUS
EFIAPI
SmiManage ( // Or MmiManage
IN CONST EFI_GUID *HandlerType,
IN CONST VOID *Context OPTIONAL,
IN OUT VOID *CommBuffer OPTIONAL,
IN OUT UINTN *CommBufferSize OPTIONAL
)
{
//
// Find the handler list for this GUID
//
List = MmCoreFindSmiEntry (HandlerType);
if (List == NULL) {
return EFI_NOT_FOUND;
}
//
// Walk through all registered handlers
//
for (Link = List->SmiHandlers.ForwardLink;
Link != &List->SmiHandlers;
Link = Link->ForwardLink) {
SmiHandler = CR (Link, SMI_HANDLER, Link, SMI_HANDLER_SIGNATURE);
Status = SmiHandler->Handler (
SmiHandler->DispatchHandle,
Context,
CommBuffer,
CommBufferSize
);
if (Status != EFI_WARN_INTERRUPT_SOURCE_QUIESCED) {
SuccessReturn = TRUE;
}
}
return SuccessReturn ? EFI_SUCCESS : EFI_INTERRUPT_PENDING;
}
// Example MM Driver registering a communication handler
#include <Protocol/MmCommunication.h>
EFI_GUID gMyHandlerGuid = { 0x12345678, 0xABCD, ... };
EFI_HANDLE mDispatchHandle = NULL;
EFI_STATUS
EFIAPI
MyMmHandler (
IN EFI_HANDLE DispatchHandle,
IN CONST VOID *Context OPTIONAL,
IN OUT VOID *CommBuffer OPTIONAL,
IN OUT UINTN *CommBufferSize OPTIONAL
)
{
MY_REQUEST *Request;
if (CommBuffer == NULL || CommBufferSize == NULL) {
return EFI_SUCCESS;
}
//
// Validate buffer is outside Secure Memory
//
if (!MmIsBufferOutsideMmValid ((UINTN)CommBuffer, *CommBufferSize)) {
return EFI_ACCESS_DENIED;
}
Request = (MY_REQUEST *)CommBuffer;
//
// Process request and write response
//
switch (Request->Operation) {
case OP_READ:
Request->Status = DoSecureRead (Request);
break;
case OP_WRITE:
Request->Status = DoSecureWrite (Request);
break;
}
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
MyDriverEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
//
// Register GUID-based MM handler
//
gMmst->MmiHandlerRegister ( // Or gSmst->SmiHandlerRegister
MyMmHandler,
&gMyHandlerGuid,
&mDispatchHandle
);
return EFI_SUCCESS;
}
Resources for deeper learning