summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKun Qin <kuqin@microsoft.com>2025-05-13 14:37:49 -0700
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>2025-06-26 21:43:56 +0000
commit6eed57a0aaa4a69fb33c39eb00acaae5c0d44e3f (patch)
treeadda535c5224a3b727b5795566d5b33629b3f493
parent4fa354b11628a488fa2a227ecd231034cf74e4ea (diff)
downloadedk2-6eed57a0aaa4a69fb33c39eb00acaae5c0d44e3f.zip
edk2-6eed57a0aaa4a69fb33c39eb00acaae5c0d44e3f.tar.gz
edk2-6eed57a0aaa4a69fb33c39eb00acaae5c0d44e3f.tar.bz2
ArmPkg: MmCommunicationDxe: Add MM communicate v3
As MM cores start to support MM communciate v3. This change moves the MM communicate driver to produce MM communicate v3 protocol. Signed-off-by: Kun Qin <kun.qin@microsoft.com>
-rw-r--r--ArmPkg/Drivers/MmCommunicationDxe/MmCommunication.c157
-rw-r--r--ArmPkg/Drivers/MmCommunicationDxe/MmCommunication.inf2
2 files changed, 134 insertions, 25 deletions
diff --git a/ArmPkg/Drivers/MmCommunicationDxe/MmCommunication.c b/ArmPkg/Drivers/MmCommunicationDxe/MmCommunication.c
index 2d5e362..188fd32 100644
--- a/ArmPkg/Drivers/MmCommunicationDxe/MmCommunication.c
+++ b/ArmPkg/Drivers/MmCommunicationDxe/MmCommunication.c
@@ -18,6 +18,7 @@
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Protocol/MmCommunication2.h>
+#include <Protocol/MmCommunication3.h>
#include <IndustryStandard/ArmStdSmc.h>
#include <IndustryStandard/ArmFfaSvc.h>
@@ -148,7 +149,6 @@ SendSpmMmCommunicate (
This function provides a service to send and receive messages from a registered UEFI service.
- @param[in] This The EFI_MM_COMMUNICATION_PROTOCOL instance.
@param[in, out] CommBufferPhysical Physical address of the MM communication buffer
@param[in, out] CommBufferVirtual Virtual address of the MM communication buffer
@param[in, out] CommSize The size of the data buffer being passed in. On input,
@@ -173,18 +173,21 @@ SendSpmMmCommunicate (
accessed by the MM environment.
**/
+STATIC
EFI_STATUS
EFIAPI
-MmCommunication2Communicate (
- IN CONST EFI_MM_COMMUNICATION2_PROTOCOL *This,
- IN OUT VOID *CommBufferPhysical,
- IN OUT VOID *CommBufferVirtual,
- IN OUT UINTN *CommSize OPTIONAL
+MmCommunicationCommon (
+ IN OUT VOID *CommBufferPhysical,
+ IN OUT VOID *CommBufferVirtual,
+ IN OUT UINTN *CommSize OPTIONAL
)
{
- EFI_MM_COMMUNICATE_HEADER *CommunicateHeader;
- UINTN BufferSize;
- EFI_STATUS Status;
+ EFI_MM_COMMUNICATE_HEADER *CommunicateHeader;
+ EFI_MM_COMMUNICATE_HEADER_V3 *CommunicateHeaderV3;
+ UINTN BufferSize;
+ UINTN *MessageSize;
+ UINTN HeaderSize;
+ EFI_STATUS Status;
Status = EFI_ACCESS_DENIED;
BufferSize = 0;
@@ -196,15 +199,30 @@ MmCommunication2Communicate (
return EFI_INVALID_PARAMETER;
}
- Status = EFI_SUCCESS;
- CommunicateHeader = CommBufferVirtual;
+ Status = EFI_SUCCESS;
+ CommunicateHeader = CommBufferVirtual;
+ CommunicateHeaderV3 = NULL;
// CommBuffer is a mandatory parameter. Hence, Rely on
// MessageLength + Header to ascertain the
// total size of the communication payload rather than
// rely on optional CommSize parameter
- BufferSize = CommunicateHeader->MessageLength +
- sizeof (CommunicateHeader->HeaderGuid) +
- sizeof (CommunicateHeader->MessageLength);
+ if (CompareGuid (
+ &CommunicateHeader->HeaderGuid,
+ &gEfiMmCommunicateHeaderV3Guid
+ ))
+ {
+ CommunicateHeaderV3 = (EFI_MM_COMMUNICATE_HEADER_V3 *)CommBufferVirtual;
+ BufferSize = CommunicateHeaderV3->BufferSize;
+ MessageSize = &CommunicateHeaderV3->MessageSize;
+ HeaderSize = sizeof (EFI_MM_COMMUNICATE_HEADER_V3);
+ } else {
+ BufferSize = CommunicateHeader->MessageLength +
+ sizeof (CommunicateHeader->HeaderGuid) +
+ sizeof (CommunicateHeader->MessageLength);
+ MessageSize = &CommunicateHeader->MessageLength;
+ HeaderSize = sizeof (CommunicateHeader->HeaderGuid) +
+ sizeof (CommunicateHeader->MessageLength);
+ }
// If CommSize is not omitted, perform size inspection before proceeding.
if (CommSize != NULL) {
@@ -229,13 +247,11 @@ MmCommunication2Communicate (
// If the message length is 0 or greater than what can be tolerated by the MM
// environment then return the expected size.
//
- if ((CommunicateHeader->MessageLength == 0) ||
+ if ((*MessageSize == 0) ||
(BufferSize > mNsCommBuffMemRegion.Length))
{
- CommunicateHeader->MessageLength = mNsCommBuffMemRegion.Length -
- sizeof (CommunicateHeader->HeaderGuid) -
- sizeof (CommunicateHeader->MessageLength);
- Status = EFI_BAD_BUFFER_SIZE;
+ *MessageSize = mNsCommBuffMemRegion.Length - HeaderSize;
+ Status = EFI_BAD_BUFFER_SIZE;
}
// MessageLength or CommSize check has failed, return here.
@@ -257,9 +273,30 @@ MmCommunication2Communicate (
// On successful return, the size of data being returned is inferred from
// MessageLength + Header.
CommunicateHeader = (EFI_MM_COMMUNICATE_HEADER *)mNsCommBuffMemRegion.VirtualBase;
- BufferSize = CommunicateHeader->MessageLength +
- sizeof (CommunicateHeader->HeaderGuid) +
- sizeof (CommunicateHeader->MessageLength);
+ if ((CommunicateHeaderV3 != NULL) && !CompareGuid (
+ &CommunicateHeader->HeaderGuid,
+ &gEfiMmCommunicateHeaderV3Guid
+ ))
+ {
+ // Sanity check to make sure we are still using v3
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a Expected v3 header, but got v1 header! %g\n",
+ __func__,
+ &CommunicateHeader->HeaderGuid
+ ));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (CommunicateHeaderV3 != NULL) {
+ CommunicateHeaderV3 = (EFI_MM_COMMUNICATE_HEADER_V3 *)CommunicateHeader;
+ BufferSize = CommunicateHeaderV3->BufferSize;
+ } else {
+ BufferSize = CommunicateHeader->MessageLength +
+ sizeof (CommunicateHeader->HeaderGuid) +
+ sizeof (CommunicateHeader->MessageLength);
+ }
+
if (BufferSize > mNsCommBuffMemRegion.Length) {
// Something bad has happened, we should have landed in ARM_SMC_MM_RET_NO_MEMORY
Status = EFI_BAD_BUFFER_SIZE;
@@ -282,6 +319,67 @@ MmCommunication2Communicate (
return Status;
}
+/**
+ 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_COMMUNICATION_PROTOCOL instance.
+ @param[in, out] CommBufferPhysical Physical address of the MM communication buffer
+ @param[in, out] CommBufferVirtual Virtual address of the MM communication buffer
+ @param[in, out] CommSize The size of the data buffer being passed in. On input,
+ when not omitted, the buffer should cover EFI_MM_COMMUNICATE_HEADER
+ and the value of MessageLength field. On exit, the size
+ of data being returned. Zero if the handler does not
+ wish to reply with any data. This parameter is optional
+ and may be NULL.
+
+ @retval EFI_SUCCESS The message was successfully posted.
+ @retval EFI_INVALID_PARAMETER CommBufferPhysical or CommBufferVirtual was NULL, or
+ integer value pointed by CommSize does not cover
+ EFI_MM_COMMUNICATE_HEADER and the value of MessageLength
+ field.
+ @retval EFI_BAD_BUFFER_SIZE The buffer is too large for the MM implementation.
+ If this error is returned, the MessageLength field
+ in the CommBuffer header or the integer pointed by
+ CommSize, are updated to reflect the maximum payload
+ size the implementation can accommodate.
+ @retval EFI_ACCESS_DENIED The CommunicateBuffer parameter or CommSize parameter,
+ if not omitted, are in address range that cannot be
+ accessed by the MM environment.
+
+**/
+EFI_STATUS
+EFIAPI
+MmCommunication2Communicate (
+ IN CONST EFI_MM_COMMUNICATION2_PROTOCOL *This,
+ IN OUT VOID *CommBufferPhysical,
+ IN OUT VOID *CommBufferVirtual,
+ IN OUT UINTN *CommSize OPTIONAL
+ )
+{
+ return MmCommunicationCommon (
+ CommBufferPhysical,
+ CommBufferVirtual,
+ CommSize
+ );
+}
+
+EFI_STATUS
+EFIAPI
+MmCommunication3Communicate (
+ IN CONST EFI_MM_COMMUNICATION3_PROTOCOL *This,
+ IN OUT VOID *CommBufferPhysical,
+ IN OUT VOID *CommBufferVirtual
+ )
+{
+ return MmCommunicationCommon (
+ CommBufferPhysical,
+ CommBufferVirtual,
+ NULL
+ );
+}
+
//
// MM Communication Protocol instance
//
@@ -289,6 +387,13 @@ STATIC EFI_MM_COMMUNICATION2_PROTOCOL mMmCommunication2 = {
MmCommunication2Communicate
};
+//
+// MM Communication Protocol instance
+//
+STATIC EFI_MM_COMMUNICATION3_PROTOCOL mMmCommunication3 = {
+ MmCommunication3Communicate
+};
+
/**
Notification callback on SetVirtualAddressMap event.
@@ -682,11 +787,13 @@ MmCommunication2Initialize (
}
// Install the communication protocol
- Status = gBS->InstallProtocolInterface (
+ Status = gBS->InstallMultipleProtocolInterfaces (
&mMmCommunicateHandle,
&gEfiMmCommunication2ProtocolGuid,
- EFI_NATIVE_INTERFACE,
- &mMmCommunication2
+ &mMmCommunication2,
+ &gEfiMmCommunication3ProtocolGuid,
+ &mMmCommunication3,
+ NULL
);
if (EFI_ERROR (Status)) {
DEBUG ((
diff --git a/ArmPkg/Drivers/MmCommunicationDxe/MmCommunication.inf b/ArmPkg/Drivers/MmCommunicationDxe/MmCommunication.inf
index 6a57f0c..c9d37d8 100644
--- a/ArmPkg/Drivers/MmCommunicationDxe/MmCommunication.inf
+++ b/ArmPkg/Drivers/MmCommunicationDxe/MmCommunication.inf
@@ -43,11 +43,13 @@
[Protocols]
gEfiDxeMmReadyToLockProtocolGuid ## UNDEFINED # SmiHandlerRegister
gEfiMmCommunication2ProtocolGuid ## PRODUCES
+ gEfiMmCommunication3ProtocolGuid ## PRODUCES
[Guids]
gEfiEndOfDxeEventGroupGuid
gEfiEventExitBootServicesGuid
gEfiEventReadyToBootGuid
+ gEfiMmCommunicateHeaderV3Guid
[Pcd.common]
gArmTokenSpaceGuid.PcdMmBufferBase