StandaloneMmPkg: StandaloneMmIplPei: Add EFI_PEI_MM_COMMUNICATION3_PPI

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_PEI_MM_COMMUNICATION3_PPI`.

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/StandaloneMmIplPei/StandaloneMmIplPei.c b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.c
index 4a71871..b496c7c 100644
--- a/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.c
+++ b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.c
@@ -8,12 +8,20 @@
 

 #include "StandaloneMmIplPei.h"

 

-EFI_PEI_MM_COMMUNICATION_PPI  mMmCommunicationPpi = { Communicate };

+EFI_PEI_MM_COMMUNICATION_PPI   mMmCommunicationPpi  = { Communicate };

+EFI_PEI_MM_COMMUNICATION3_PPI  mMmCommunication3Ppi = { Communicate3 };

 

-EFI_PEI_PPI_DESCRIPTOR  mPpiList = {

-  (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),

-  &gEfiPeiMmCommunicationPpiGuid,

-  &mMmCommunicationPpi

+EFI_PEI_PPI_DESCRIPTOR  mPpiList[] = {

+  {

+    EFI_PEI_PPI_DESCRIPTOR_PPI,

+    &gEfiPeiMmCommunicationPpiGuid,

+    &mMmCommunicationPpi

+  },

+  {

+    (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),

+    &gEfiPeiMmCommunication3PpiGuid,

+    &mMmCommunication3Ppi

+  }

 };

 

 EFI_PEI_NOTIFY_DESCRIPTOR  mNotifyList = {

@@ -128,6 +136,120 @@
 }

 

 /**

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

+  @param[in, out] CommBuffer     A pointer to the buffer to convey into MMRAM.

+

+  @retval EFI_SUCCESS            The message was successfully posted.

+  @retval EFI_INVALID_PARAMETER  The CommBuffer was NULL.

+**/

+EFI_STATUS

+EFIAPI

+Communicate3 (

+  IN CONST EFI_PEI_MM_COMMUNICATION3_PPI  *This,

+  IN OUT VOID                             *CommBuffer

+  )

+{

+  EFI_STATUS                    Status;

+  EFI_PEI_MM_CONTROL_PPI        *MmControl;

+  UINT8                         SmiCommand;

+  UINTN                         Size;

+  UINTN                         TempCommSize;

+  EFI_HOB_GUID_TYPE             *GuidHob;

+  MM_COMM_BUFFER                *MmCommBuffer;

+  MM_COMM_BUFFER_STATUS         *MmCommBufferStatus;

+  EFI_MM_COMMUNICATE_HEADER_V3  *CommunicateHeader;

+

+  DEBUG ((DEBUG_INFO, "StandaloneMmIpl Communicate Enter\n"));

+

+  GuidHob = GetFirstGuidHob (&gMmCommBufferHobGuid);

+  if (GuidHob != NULL) {

+    MmCommBuffer       = GET_GUID_HOB_DATA (GuidHob);

+    MmCommBufferStatus = (MM_COMM_BUFFER_STATUS *)(UINTN)MmCommBuffer->Status;

+  } else {

+    DEBUG ((DEBUG_ERROR, "MmCommBuffer is not existed !!!\n"));

+    ASSERT (GuidHob != NULL);

+    return EFI_NOT_FOUND;

+  }

+

+  SmiCommand = 0;

+  Size       = sizeof (SmiCommand);

+

+  //

+  // Check parameters

+  //

+  if (CommBuffer == NULL) {

+    return EFI_INVALID_PARAMETER;

+  } else {

+    CommunicateHeader = (EFI_MM_COMMUNICATE_HEADER_V3 *)CommBuffer;

+    //

+    // Check if the HeaderGuid is valid

+    //

+    if (CompareGuid (&CommunicateHeader->HeaderGuid, &gEfiMmCommunicateHeaderV3Guid)) {

+      DEBUG ((DEBUG_ERROR, "HeaderGuid is not valid!\n"));

+      return EFI_INVALID_PARAMETER;

+    }

+

+    TempCommSize = CommunicateHeader->BufferSize;

+    //

+    // CommSize must hold HeaderGuid and MessageLength

+    //

+    if (TempCommSize < sizeof (EFI_MM_COMMUNICATE_HEADER_V3)) {

+      DEBUG ((DEBUG_ERROR, "Communicate buffer size (%d) is less than minimum size (%d)!", TempCommSize, sizeof (EFI_MM_COMMUNICATE_HEADER_V3)));

+      return EFI_INVALID_PARAMETER;

+    }

+  }

+

+  if (TempCommSize > EFI_PAGES_TO_SIZE (MmCommBuffer->NumberOfPages)) {

+    DEBUG ((DEBUG_ERROR, "Communicate buffer size (%d) is over MAX (%d) size!", TempCommSize, EFI_PAGES_TO_SIZE (MmCommBuffer->NumberOfPages)));

+    return EFI_INVALID_PARAMETER;

+  }

+

+  CopyMem ((VOID *)(UINTN)MmCommBuffer->PhysicalStart, CommBuffer, TempCommSize);

+  MmCommBufferStatus->IsCommBufferValid = TRUE;

+

+  //

+  // Generate Software SMI

+  //

+  Status = PeiServicesLocatePpi (&gEfiPeiMmControlPpiGuid, 0, NULL, (VOID **)&MmControl);

+  ASSERT_EFI_ERROR (Status);

+

+  Status = MmControl->Trigger (

+                        (EFI_PEI_SERVICES **)GetPeiServicesTablePointer (),

+                        MmControl,

+                        (INT8 *)&SmiCommand,

+                        &Size,

+                        FALSE,

+                        0

+                        );

+  ASSERT_EFI_ERROR (Status);

+

+  //

+  // Return status from software SMI

+  //

+  TempCommSize = (UINTN)MmCommBufferStatus->ReturnBufferSize;

+

+  //

+  // Copy the returned data to the non-mmram buffer (CommBuffer)

+  //

+  CopyMem (CommBuffer, (VOID *)(MmCommBuffer->PhysicalStart), TempCommSize);

+

+  CommunicateHeader->BufferSize = TempCommSize;

+

+  Status = (EFI_STATUS)MmCommBufferStatus->ReturnStatus;

+  if (Status != EFI_SUCCESS) {

+    DEBUG ((DEBUG_ERROR, "StandaloneMmIpl Communicate failed (%r)\n", Status));

+  } else {

+    MmCommBufferStatus->IsCommBufferValid = FALSE;

+  }

+

+  return Status;

+}

+

+/**

   Search all the available firmware volumes for MM Core driver.

 

   @param  MmFvBase             Base address of FV which included MM Core driver.

@@ -817,7 +939,7 @@
   //

   // Install MmCommunicationPpi

   //

-  Status = PeiServicesInstallPpi (&mPpiList);

+  Status = PeiServicesInstallPpi (mPpiList);

   ASSERT_EFI_ERROR (Status);

 

   //

diff --git a/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.h b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.h
index c5d5987..01b947c 100644
--- a/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.h
+++ b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.h
@@ -23,6 +23,7 @@
 #include <Library/PeiServicesTablePointerLib.h>

 #include <Ppi/MmControl.h>

 #include <Ppi/MmCommunication.h>

+#include <Ppi/MmCommunication3.h>

 #include <Ppi/MmCoreFvLocationPpi.h>

 #include <Protocol/MmCommunication.h>

 #include <Library/MmPlatformHobProducerLib.h>

@@ -50,6 +51,24 @@
   );

 

 /**

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

+  @param[in, out] CommBuffer     A pointer to the buffer to convey into MMRAM.

+

+  @retval EFI_SUCCESS            The message was successfully posted.

+  @retval EFI_INVALID_PARAMETER  The CommBuffer was NULL.

+**/

+EFI_STATUS

+EFIAPI

+Communicate3 (

+  IN CONST EFI_PEI_MM_COMMUNICATION3_PPI  *This,

+  IN OUT VOID                             *CommBuffer

+  );

+

+/**

   This is the callback function on end of PEI.

 

   This callback is used for call MmEndOfPeiHandler in standalone MM core.

diff --git a/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.inf b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.inf
index 0341a98..9f446e8 100644
--- a/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.inf
+++ b/StandaloneMmPkg/Drivers/StandaloneMmIplPei/StandaloneMmIplPei.inf
@@ -57,10 +57,12 @@
   gMmProfileDataHobGuid

   gMmUnblockRegionHobGuid

   gMmStatusCodeUseSerialHobGuid

+  gEfiMmCommunicateHeaderV3Guid

 

 [Ppis]

   gEfiPeiMmControlPpiGuid

   gEfiPeiMmCommunicationPpiGuid

+  gEfiPeiMmCommunication3PpiGuid

   gEfiEndOfPeiSignalPpiGuid

   gMmCoreFvLocationPpiGuid