StandaloneMmPkg: MmCommunicationDxe: Add EFI_MM_COMMUNICATION3_PROTOCOL

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3398
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3430

This change added support of installing `EFI_MM_COMMUNICATION3_PROTOCOL`.

MmCommunicate v3 routine will no longer need to supply buffer length in
the input parameters but instead inference from the returned communicate
buffer.

Signed-off-by: Kun Qin <kuqin12@gmail.com>
This commit is contained in:
Kun Qin 2025-04-04 17:16:56 -07:00 committed by mergify[bot]
parent bed033dbf7
commit f3e02ae545
3 changed files with 94 additions and 5 deletions

View file

@ -9,6 +9,13 @@
#include "MmCommunicationDxe.h"
//
// PI 1.9 MM Communication Protocol 3 instance
//
EFI_MM_COMMUNICATION3_PROTOCOL mMmCommunication3 = {
MmCommunicate3
};
//
// PI 1.7 MM Communication Protocol 2 instance
//
@ -260,10 +267,11 @@ ProcessCommunicationBuffer (
IN OUT UINTN *CommSize OPTIONAL
)
{
EFI_STATUS Status;
EFI_MM_COMMUNICATE_HEADER *CommunicateHeader;
MM_COMM_BUFFER_STATUS *CommonBufferStatus;
UINTN BufferSize;
EFI_STATUS Status;
EFI_MM_COMMUNICATE_HEADER *CommunicateHeader;
EFI_MM_COMMUNICATE_HEADER_V3 *CommunicateHeaderV3;
MM_COMM_BUFFER_STATUS *CommonBufferStatus;
UINTN BufferSize;
//
// Check parameters
@ -273,7 +281,16 @@ ProcessCommunicationBuffer (
}
CommunicateHeader = (EFI_MM_COMMUNICATE_HEADER *)CommBuffer;
BufferSize = OFFSET_OF (EFI_MM_COMMUNICATE_HEADER, Data) + CommunicateHeader->MessageLength;
if (CompareGuid (&CommunicateHeader->HeaderGuid, &gEfiMmCommunicateHeaderV3Guid)) {
CommunicateHeaderV3 = (EFI_MM_COMMUNICATE_HEADER_V3 *)CommBuffer;
if (CommunicateHeaderV3->BufferSize < sizeof (EFI_MM_COMMUNICATE_HEADER_V3) + CommunicateHeaderV3->MessageSize) {
return EFI_INVALID_PARAMETER;
}
BufferSize = ((EFI_MM_COMMUNICATE_HEADER_V3 *)CommBuffer)->BufferSize;
} else {
BufferSize = OFFSET_OF (EFI_MM_COMMUNICATE_HEADER, Data) + CommunicateHeader->MessageLength;
}
if (CommSize != NULL) {
ASSERT (*CommSize == BufferSize);
@ -318,6 +335,38 @@ ProcessCommunicationBuffer (
return CommonBufferStatus->ReturnStatus;
}
/**
Communicates with a registered handler.
This function provides a service to send and receive messages from a registered UEFI service.
@param[in] This The EFI_MM_COMMUNICATION3_PROTOCOL instance.
@param[in, out] CommBufferPhysical Physical address of the MM communication buffer, of which content must
start with EFI_MM_COMMUNICATE_HEADER_V3.
@param[in, out] CommBufferVirtual Virtual address of the MM communication buffer, of which content must
start with EFI_MM_COMMUNICATE_HEADER_V3.
@retval EFI_SUCCESS The message was successfully posted.
@retval EFI_INVALID_PARAMETER CommBufferPhysical was NULL or CommBufferVirtual was NULL.
@retval EFI_BAD_BUFFER_SIZE The buffer is too large for the MM implementation.
If this error is returned, the MessageSize field
in the CommBuffer header, are updated to reflect
the maximum payload size the implementation can accommodate.
@retval EFI_ACCESS_DENIED The CommunicateBuffer parameter are in address range
that cannot be accessed by the MM environment.
**/
EFI_STATUS
EFIAPI
MmCommunicate3 (
IN CONST EFI_MM_COMMUNICATION3_PROTOCOL *This,
IN OUT VOID *CommBufferPhysical,
IN OUT VOID *CommBufferVirtual
)
{
return ProcessCommunicationBuffer (CommBufferVirtual, NULL);
}
/**
Communicates with a registered handler.
@ -433,6 +482,14 @@ MmCommunicationEntryPoint (
ASSERT_EFI_ERROR (Status);
Handle = NULL;
Status = gBS->InstallProtocolInterface (
&Handle,
&gEfiMmCommunication3ProtocolGuid,
EFI_NATIVE_INTERFACE,
&mMmCommunication3
);
ASSERT_EFI_ERROR (Status);
Status = gBS->InstallProtocolInterface (
&Handle,
&gEfiMmCommunication2ProtocolGuid,

View file

@ -22,6 +22,7 @@
#include <Library/ReportStatusCodeLib.h>
#include <Protocol/SmmControl2.h>
#include <Protocol/MmCommunication3.h>
#include <Protocol/MmCommunication2.h>
#include <Protocol/MmCommunication.h>
#include <Protocol/DxeMmReadyToLock.h>
@ -49,6 +50,35 @@ typedef struct {
EFI_EVENT Event;
} MM_EVENT_NOTIFICATION;
/**
Communicates with a registered handler.
This function provides a service to send and receive messages from a registered UEFI service.
@param[in] This The EFI_MM_COMMUNICATION3_PROTOCOL instance.
@param[in, out] CommBufferPhysical Physical address of the MM communication buffer, of which content must
start with EFI_MM_COMMUNICATE_HEADER_V3.
@param[in, out] CommBufferVirtual Virtual address of the MM communication buffer, of which content must
start with EFI_MM_COMMUNICATE_HEADER_V3.
@retval EFI_SUCCESS The message was successfully posted.
@retval EFI_INVALID_PARAMETER CommBufferPhysical was NULL or CommBufferVirtual was NULL.
@retval EFI_BAD_BUFFER_SIZE The buffer is too large for the MM implementation.
If this error is returned, the MessageSize field
in the CommBuffer header, are updated to reflect
the maximum payload size the implementation can accommodate.
@retval EFI_ACCESS_DENIED The CommunicateBuffer parameter are in address range
that cannot be accessed by the MM environment.
**/
EFI_STATUS
EFIAPI
MmCommunicate3 (
IN CONST EFI_MM_COMMUNICATION3_PROTOCOL *This,
IN OUT VOID *CommBufferPhysical,
IN OUT VOID *CommBufferVirtual
);
/**
Communicates with a registered handler.

View file

@ -44,8 +44,10 @@
gEfiEventVirtualAddressChangeGuid
gEfiEndOfDxeEventGroupGuid
gEfiEventExitBootServicesGuid
gEfiMmCommunicateHeaderV3Guid
[Protocols]
gEfiMmCommunication3ProtocolGuid
gEfiMmCommunication2ProtocolGuid
gEfiSmmControl2ProtocolGuid
gEfiMmCommunicationProtocolGuid