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>
diff --git a/StandaloneMmPkg/Drivers/MmCommunicationDxe/MmCommunicationDxe.c b/StandaloneMmPkg/Drivers/MmCommunicationDxe/MmCommunicationDxe.c
index 7b1e063..ba0b2ec 100644
--- a/StandaloneMmPkg/Drivers/MmCommunicationDxe/MmCommunicationDxe.c
+++ b/StandaloneMmPkg/Drivers/MmCommunicationDxe/MmCommunicationDxe.c
@@ -10,6 +10,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

 //

 EFI_MM_COMMUNICATION2_PROTOCOL  mMmCommunication2 = {

@@ -260,10 +267,11 @@
   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 @@
   }

 

   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);

@@ -323,6 +340,38 @@
 

   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.

+

+  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.

@@ -435,6 +484,14 @@
   Handle = NULL;

   Status = gBS->InstallProtocolInterface (

                   &Handle,

+                  &gEfiMmCommunication3ProtocolGuid,

+                  EFI_NATIVE_INTERFACE,

+                  &mMmCommunication3

+                  );

+  ASSERT_EFI_ERROR (Status);

+

+  Status = gBS->InstallProtocolInterface (

+                  &Handle,

                   &gEfiMmCommunication2ProtocolGuid,

                   EFI_NATIVE_INTERFACE,

                   &mMmCommunication2

diff --git a/StandaloneMmPkg/Drivers/MmCommunicationDxe/MmCommunicationDxe.h b/StandaloneMmPkg/Drivers/MmCommunicationDxe/MmCommunicationDxe.h
index d84d821..3b399da 100644
--- a/StandaloneMmPkg/Drivers/MmCommunicationDxe/MmCommunicationDxe.h
+++ b/StandaloneMmPkg/Drivers/MmCommunicationDxe/MmCommunicationDxe.h
@@ -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>

@@ -54,6 +55,35 @@
 

   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.

+

+  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.

diff --git a/StandaloneMmPkg/Drivers/MmCommunicationDxe/MmCommunicationDxe.inf b/StandaloneMmPkg/Drivers/MmCommunicationDxe/MmCommunicationDxe.inf
index 821df02..dd5a0b1 100644
--- a/StandaloneMmPkg/Drivers/MmCommunicationDxe/MmCommunicationDxe.inf
+++ b/StandaloneMmPkg/Drivers/MmCommunicationDxe/MmCommunicationDxe.inf
@@ -44,8 +44,10 @@
   gEfiEventVirtualAddressChangeGuid

   gEfiEndOfDxeEventGroupGuid

   gEfiEventExitBootServicesGuid

+  gEfiMmCommunicateHeaderV3Guid

 

 [Protocols]

+  gEfiMmCommunication3ProtocolGuid

   gEfiMmCommunication2ProtocolGuid

   gEfiSmmControl2ProtocolGuid

   gEfiMmCommunicationProtocolGuid