StandaloneMmPkg/Core: Introduce MM Communication Buffer

Get the MM Communication context from the MM Communication Buffer,
instead of the pointer inside gMmCorePrivate.
In the MmEntryPoint, check IsCommBufferValid from MM_COMM_BUFFER to
decide whether the MMI is Synchronous MMI or Asynchronous MMI. If it
is a Synchronous MMI, MM Core shadows the communication buffer into
a internal copy, then invokes the MMI handlers, lastly copies data
back to the MM Communication Buffer and set the return status.

Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Sami Mujawar <sami.mujawar@arm.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Jiaxin Wu <jiaxin.wu@intel.com>
Signed-off-by: Wei6 Xu <wei6.xu@intel.com>
This commit is contained in:
Wei6 Xu 2024-05-13 23:51:45 +08:00 committed by mergify[bot]
parent 68487b4736
commit 24e41d1fa3
3 changed files with 120 additions and 24 deletions

View File

@ -88,6 +88,8 @@ MM_CORE_MMI_HANDLERS mMmCoreMmiHandlers[] = {
UINTN mMmramRangeCount; UINTN mMmramRangeCount;
EFI_MMRAM_DESCRIPTOR *mMmramRanges; EFI_MMRAM_DESCRIPTOR *mMmramRanges;
MM_COMM_BUFFER *mMmCommunicationBuffer;
VOID *mInternalCommBufferCopy;
/** /**
Place holder function until all the MM System Table Service are available. Place holder function until all the MM System Table Service are available.
@ -397,6 +399,62 @@ MmCoreInstallLoadedImage (
ASSERT_EFI_ERROR (Status); ASSERT_EFI_ERROR (Status);
} }
/**
Prepare communication buffer for MMI.
**/
VOID
MmCorePrepareCommunicationBuffer (
VOID
)
{
EFI_STATUS Status;
EFI_HOB_GUID_TYPE *GuidHob;
EFI_PHYSICAL_ADDRESS Buffer;
mMmCommunicationBuffer = NULL;
mInternalCommBufferCopy = NULL;
GuidHob = GetFirstGuidHob (&gMmCommBufferHobGuid);
ASSERT (GuidHob != NULL);
if (GuidHob == NULL) {
return;
}
mMmCommunicationBuffer = (MM_COMM_BUFFER *)GET_GUID_HOB_DATA (GuidHob);
DEBUG ((
DEBUG_INFO,
"MM Communication Buffer is at %x, number of pages is %x\n",
mMmCommunicationBuffer->PhysicalStart,
mMmCommunicationBuffer->NumberOfPages
));
ASSERT (mMmCommunicationBuffer->PhysicalStart != 0 && mMmCommunicationBuffer->NumberOfPages != 0);
if (!MmIsBufferOutsideMmValid (
mMmCommunicationBuffer->PhysicalStart,
EFI_PAGES_TO_SIZE (mMmCommunicationBuffer->NumberOfPages)
))
{
mMmCommunicationBuffer = NULL;
DEBUG ((DEBUG_ERROR, "MM Communication Buffer is invalid!\n"));
ASSERT (FALSE);
return;
}
Status = MmAllocatePages (
AllocateAnyPages,
EfiRuntimeServicesData,
mMmCommunicationBuffer->NumberOfPages,
&Buffer
);
ASSERT_EFI_ERROR (Status);
if (EFI_ERROR (Status)) {
return;
}
mInternalCommBufferCopy = (VOID *)(UINTN)Buffer;
DEBUG ((DEBUG_INFO, "Internal Communication Buffer Copy is at %p\n", mInternalCommBufferCopy));
}
/** /**
The main entry point to MM Foundation. The main entry point to MM Foundation.
@ -414,6 +472,8 @@ MmEntryPoint (
{ {
EFI_STATUS Status; EFI_STATUS Status;
EFI_MM_COMMUNICATE_HEADER *CommunicateHeader; EFI_MM_COMMUNICATE_HEADER *CommunicateHeader;
MM_COMM_BUFFER_STATUS *CommunicationStatus;
UINTN BufferSize;
DEBUG ((DEBUG_INFO, "MmEntryPoint ...\n")); DEBUG ((DEBUG_INFO, "MmEntryPoint ...\n"));
@ -440,34 +500,66 @@ MmEntryPoint (
// Check to see if this is a Synchronous MMI sent through the MM Communication // Check to see if this is a Synchronous MMI sent through the MM Communication
// Protocol or an Asynchronous MMI // Protocol or an Asynchronous MMI
// //
if (gMmCorePrivate->CommunicationBuffer != 0) { if ((mMmCommunicationBuffer != NULL) && (mInternalCommBufferCopy != NULL)) {
CommunicationStatus = (MM_COMM_BUFFER_STATUS *)(UINTN)mMmCommunicationBuffer->Status;
if (CommunicationStatus->IsCommBufferValid) {
// //
// Synchronous MMI for MM Core or request from Communicate protocol // Synchronous MMI for MM Core or request from Communicate protocol
// //
if (!MmIsBufferOutsideMmValid ((UINTN)gMmCorePrivate->CommunicationBuffer, gMmCorePrivate->BufferSize)) { CommunicateHeader = (EFI_MM_COMMUNICATE_HEADER *)(UINTN)mMmCommunicationBuffer->PhysicalStart;
BufferSize = OFFSET_OF (EFI_MM_COMMUNICATE_HEADER, Data) + CommunicateHeader->MessageLength;
if (BufferSize <= EFI_PAGES_TO_SIZE (mMmCommunicationBuffer->NumberOfPages)) {
// //
// If CommunicationBuffer is not in valid address scope, return EFI_INVALID_PARAMETER // Shadow the data from MM Communication Buffer to internal buffer
// //
gMmCorePrivate->CommunicationBuffer = 0; CopyMem (
gMmCorePrivate->ReturnStatus = EFI_INVALID_PARAMETER; mInternalCommBufferCopy,
} else { (VOID *)(UINTN)mMmCommunicationBuffer->PhysicalStart,
CommunicateHeader = (EFI_MM_COMMUNICATE_HEADER *)(UINTN)gMmCorePrivate->CommunicationBuffer; BufferSize
gMmCorePrivate->BufferSize -= OFFSET_OF (EFI_MM_COMMUNICATE_HEADER, Data); );
ZeroMem (
(UINT8 *)mInternalCommBufferCopy + BufferSize,
EFI_PAGES_TO_SIZE (mMmCommunicationBuffer->NumberOfPages) - BufferSize
);
CommunicateHeader = (EFI_MM_COMMUNICATE_HEADER *)mInternalCommBufferCopy;
BufferSize = CommunicateHeader->MessageLength;
Status = MmiManage ( Status = MmiManage (
&CommunicateHeader->HeaderGuid, &CommunicateHeader->HeaderGuid,
NULL, NULL,
CommunicateHeader->Data, CommunicateHeader->Data,
(UINTN *)&gMmCorePrivate->BufferSize &BufferSize
); );
BufferSize = BufferSize + OFFSET_OF (EFI_MM_COMMUNICATE_HEADER, Data);
if (BufferSize <= EFI_PAGES_TO_SIZE (mMmCommunicationBuffer->NumberOfPages)) {
//
// Copy the data back to MM Communication Buffer
//
CopyMem (
(VOID *)(UINTN)mMmCommunicationBuffer->PhysicalStart,
mInternalCommBufferCopy,
BufferSize
);
} else {
DEBUG ((DEBUG_ERROR, "Returned buffer size is larger than the size of MM Communication Buffer\n"));
ASSERT (FALSE);
}
// //
// Update CommunicationBuffer, BufferSize and ReturnStatus // Update CommunicationBuffer, BufferSize and ReturnStatus
// Communicate service finished, reset the pointer to CommBuffer to NULL // Communicate service finished, reset the pointer to CommBuffer to NULL
// //
gMmCorePrivate->BufferSize += OFFSET_OF (EFI_MM_COMMUNICATE_HEADER, Data); CommunicationStatus->ReturnBufferSize = BufferSize;
gMmCorePrivate->CommunicationBuffer = 0; CommunicationStatus->ReturnStatus = (Status == EFI_SUCCESS) ? EFI_SUCCESS : EFI_NOT_FOUND;
gMmCorePrivate->ReturnStatus = (Status == EFI_SUCCESS) ? EFI_SUCCESS : EFI_NOT_FOUND; } else {
DEBUG ((DEBUG_ERROR, "Input buffer size is larger than the size of MM Communication Buffer\n"));
ASSERT (FALSE);
} }
} }
} else {
DEBUG ((DEBUG_ERROR, "No valid communication buffer, no Synchronous MMI will be processed\n"));
}
// //
// Process Asynchronous MMI sources // Process Asynchronous MMI sources
@ -738,6 +830,8 @@ StandaloneMmMain (
DEBUG ((DEBUG_INFO, "MmiHandlerRegister - GUID %g - Status %d\n", mMmCoreMmiHandlers[Index].HandlerType, Status)); DEBUG ((DEBUG_INFO, "MmiHandlerRegister - GUID %g - Status %d\n", mMmCoreMmiHandlers[Index].HandlerType, Status));
} }
MmCorePrepareCommunicationBuffer ();
// //
// Install Loaded Image Protocol form MM Core // Install Loaded Image Protocol form MM Core
// //

View File

@ -30,6 +30,7 @@
#include <Guid/HobList.h> #include <Guid/HobList.h>
#include <Guid/MmFvDispatch.h> #include <Guid/MmFvDispatch.h>
#include <Guid/MmramMemoryReserve.h> #include <Guid/MmramMemoryReserve.h>
#include <Guid/MmCommBuffer.h>
#include <Library/StandaloneMmCoreEntryPoint.h> #include <Library/StandaloneMmCoreEntryPoint.h>
#include <Library/BaseLib.h> #include <Library/BaseLib.h>

View File

@ -76,6 +76,7 @@
gEfiEventLegacyBootGuid gEfiEventLegacyBootGuid
gEfiEventExitBootServicesGuid gEfiEventExitBootServicesGuid
gEfiEventReadyToBootGuid gEfiEventReadyToBootGuid
gMmCommBufferHobGuid
[Pcd] [Pcd]
gStandaloneMmPkgTokenSpaceGuid.PcdFwVolMmMaxEncapsulationDepth ##CONSUMES gStandaloneMmPkgTokenSpaceGuid.PcdFwVolMmMaxEncapsulationDepth ##CONSUMES