[edk2-devel] [edk2-platforms][PATCH v2 02/32] AmpereAltraPkg: Add MmCommunication modules

Nhi Pham via groups.io posted 32 patches 4 years, 8 months ago
There is a newer version of this series
[edk2-devel] [edk2-platforms][PATCH v2 02/32] AmpereAltraPkg: Add MmCommunication modules
Posted by Nhi Pham via groups.io 4 years, 8 months ago
From: Vu Nguyen <vunguyen@os.amperecomputing.com>

The MmCommunicationDxe module is derived from
ArmPkg/Drivers/MmCommunicationDxe/MmCommunication.inf.

The MmCommunication PEI and DXE modules implement the MM Communication
protocol (EFI_MM_COMMUNICATION_PROTOCOL) as defined in the PI 1.5
specification for the interface between UEFI and MM services in the
secure world.

Cc: Thang Nguyen <thang@os.amperecomputing.com>
Cc: Chuong Tran <chuong@os.amperecomputing.com>
Cc: Phong Vo <phong@os.amperecomputing.com>
Cc: Leif Lindholm <leif@nuviainc.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>

Signed-off-by: Vu Nguyen <vunguyen@os.amperecomputing.com>
---
 Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec                                |   3 +
 Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc                            |   2 +
 Platform/Ampere/JadePkg/Jade.fdf                                                |   3 +
 Silicon/Ampere/AmpereAltraPkg/Drivers/MmCommunicationDxe/MmCommunication.inf    |  57 +++
 Silicon/Ampere/AmpereAltraPkg/Drivers/MmCommunicationPei/MmCommunicationPei.inf |  34 ++
 Silicon/Ampere/AmpereAltraPkg/Drivers/MmCommunicationDxe/MmCommunicate.h        |  22 +
 Silicon/Ampere/AmpereAltraPkg/Drivers/MmCommunicationDxe/MmCommunication.c      | 454 ++++++++++++++++++++
 Silicon/Ampere/AmpereAltraPkg/Drivers/MmCommunicationPei/MmCommunicationPei.c   |  37 ++
 8 files changed, 612 insertions(+)

diff --git a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec
index f0a5bd04ec22..73097afaf841 100644
--- a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec
+++ b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec
@@ -38,5 +38,8 @@ [Guids]
   ## NVParam MM GUID
   gNVParamMmGuid               = { 0xE4AC5024, 0x29BE, 0x4ADC, { 0x93, 0x36, 0x87, 0xB5, 0xA0, 0x76, 0x23, 0x2D } }
 
+  ## SPI NOR Proxy MM GUID
+  gSpiNorMmGuid                = { 0xC8D76438, 0x4D3C, 0x4BEA, { 0xBF, 0x86, 0x92, 0x6B, 0x83, 0x07, 0xA2, 0x39 } }
+
   ## Include/Guid/PlatformInfoHobGuid.h
   gPlatformHobGuid             = { 0x7f73e372, 0x7183, 0x4022, { 0xb3, 0x76, 0x78, 0x30, 0x32, 0x6d, 0x79, 0xb4 } }
diff --git a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc
index af66c27822a3..0332473b59b0 100755
--- a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc
+++ b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc
@@ -517,6 +517,7 @@ [Components.common]
   ArmPlatformPkg/PlatformPei/PlatformPeim.inf
   Silicon/Ampere/AmpereAltraPkg/Drivers/ATFHobPei/ATFHobPeim.inf
   Silicon/Ampere/AmpereAltraPkg/Drivers/MemoryInitPeim/MemoryInitPeim.inf
+  Silicon/Ampere/AmpereAltraPkg/Drivers/MmCommunicationPei/MmCommunicationPei.inf
   ArmPkg/Drivers/CpuPei/CpuPei.inf
   UefiCpuPkg/CpuIoPei/CpuIoPei.inf
   MdeModulePkg/Universal/Variable/Pei/VariablePei.inf
@@ -565,6 +566,7 @@ [Components.common]
   EmbeddedPkg/ResetRuntimeDxe/ResetRuntimeDxe.inf
   EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClockRuntimeDxe.inf
   EmbeddedPkg/MetronomeDxe/MetronomeDxe.inf
+  Silicon/Ampere/AmpereAltraPkg/Drivers/MmCommunicationDxe/MmCommunication.inf
 
   #
   # Environment Variables Protocol
diff --git a/Platform/Ampere/JadePkg/Jade.fdf b/Platform/Ampere/JadePkg/Jade.fdf
index 8ed6df381aed..905289844378 100755
--- a/Platform/Ampere/JadePkg/Jade.fdf
+++ b/Platform/Ampere/JadePkg/Jade.fdf
@@ -101,6 +101,7 @@ [FV.FVMAIN_COMPACT]
   INF ArmPlatformPkg/PlatformPei/PlatformPeim.inf
   INF Silicon/Ampere/AmpereAltraPkg/Drivers/ATFHobPei/ATFHobPeim.inf
   INF Silicon/Ampere/AmpereAltraPkg/Drivers/MemoryInitPeim/MemoryInitPeim.inf
+  INF Silicon/Ampere/AmpereAltraPkg/Drivers/MmCommunicationPei/MmCommunicationPei.inf
   INF ArmPkg/Drivers/CpuPei/CpuPei.inf
   INF MdeModulePkg/Universal/PCD/Pei/Pcd.inf
   INF MdeModulePkg/Universal/Variable/Pei/VariablePei.inf
@@ -141,6 +142,7 @@ [FV.FvMain]
   INF MdeModulePkg/Universal/PCD/Dxe/Pcd.inf
   INF MdeModulePkg/Universal/ReportStatusCodeRouter/RuntimeDxe/ReportStatusCodeRouterRuntimeDxe.inf
   INF MdeModulePkg/Universal/StatusCodeHandler/RuntimeDxe/StatusCodeHandlerRuntimeDxe.inf
+  INF Silicon/Ampere/AmpereAltraPkg/Drivers/MmCommunicationDxe/MmCommunication.inf
 }
 
   INF MdeModulePkg/Core/Dxe/DxeMain.inf
@@ -163,6 +165,7 @@ [FV.FvMain]
   INF EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClockRuntimeDxe.inf
   INF EmbeddedPkg/MetronomeDxe/MetronomeDxe.inf
   INF MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf
+  INF Silicon/Ampere/AmpereAltraPkg/Drivers/MmCommunicationDxe/MmCommunication.inf
 
   #
   # Environment Variables Protocol
diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/MmCommunicationDxe/MmCommunication.inf b/Silicon/Ampere/AmpereAltraPkg/Drivers/MmCommunicationDxe/MmCommunication.inf
new file mode 100644
index 000000000000..3efff142944f
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/MmCommunicationDxe/MmCommunication.inf
@@ -0,0 +1,57 @@
+#/** @file
+#
+#  This module implements the MM Communication Protocol (EFI_MM_COMMUNICATION_PROTOCOL)
+#  as defined in the PI 1.5 specification.
+#
+#  Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#**/
+
+[Defines]
+  INF_VERSION                    = 0x0001001B
+  BASE_NAME                      = ArmMmCommunication
+  FILE_GUID                      = 09EE81D3-F15E-43F4-85B4-CB9873DA5D6B
+  MODULE_TYPE                    = DXE_RUNTIME_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = MmCommunicationInitialize
+
+#
+# The following is for reference only and not required by
+# build tools
+#
+# VALID_ARCHITECTURES            = AARCH64
+#
+
+[Sources.AARCH64]
+  MmCommunicate.h
+  MmCommunication.c
+
+[Packages]
+  ArmPkg/ArmPkg.dec
+  MdePkg/MdePkg.dec
+
+[LibraryClasses]
+  ArmLib
+  ArmSmcLib
+  BaseMemoryLib
+  DebugLib
+  DxeServicesTableLib
+  HobLib
+  UefiDriverEntryPoint
+
+[Protocols]
+  gEfiMmCommunicationProtocolGuid              ## PRODUCES
+
+[Guids]
+  gEfiEndOfDxeEventGroupGuid
+  gEfiEventExitBootServicesGuid
+  gEfiEventReadyToBootGuid
+
+[Pcd.common]
+  gArmTokenSpaceGuid.PcdMmBufferBase
+  gArmTokenSpaceGuid.PcdMmBufferSize
+
+[Depex]
+  gEfiCpuArchProtocolGuid
diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/MmCommunicationPei/MmCommunicationPei.inf b/Silicon/Ampere/AmpereAltraPkg/Drivers/MmCommunicationPei/MmCommunicationPei.inf
new file mode 100755
index 000000000000..3a985840a0a0
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/MmCommunicationPei/MmCommunicationPei.inf
@@ -0,0 +1,34 @@
+## @file
+#
+# Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x0001001B
+  BASE_NAME                      = MmCommunicationPei
+  FILE_GUID                      = B5AE0F80-DF81-11EA-8B6E-0800200C9A66
+  MODULE_TYPE                    = PEIM
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = MmCommunicationPeiEntryPoint
+
+[Sources]
+  MmCommunicationPei.c
+
+[Packages]
+  ArmPkg/ArmPkg.dec
+  MdePkg/MdePkg.dec
+
+[LibraryClasses]
+  HobLib
+  PcdLib
+  PeimEntryPoint
+
+[Pcd]
+  gArmTokenSpaceGuid.PcdMmBufferBase
+  gArmTokenSpaceGuid.PcdMmBufferSize
+
+[Depex]
+  TRUE
diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/MmCommunicationDxe/MmCommunicate.h b/Silicon/Ampere/AmpereAltraPkg/Drivers/MmCommunicationDxe/MmCommunicate.h
new file mode 100644
index 000000000000..804ba58afb72
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/MmCommunicationDxe/MmCommunicate.h
@@ -0,0 +1,22 @@
+/** @file
+
+  Copyright (c) 2016-2018, ARM Limited. All rights reserved.
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef MM_COMMUNICATE_H_
+#define MM_COMMUNICATE_H_
+
+#define MM_MAJOR_VER_MASK        0xEFFF0000
+#define MM_MINOR_VER_MASK        0x0000FFFF
+#define MM_MAJOR_VER_SHIFT       16
+
+#define MM_MAJOR_VER(x) (((x) & MM_MAJOR_VER_MASK) >> MM_MAJOR_VER_SHIFT)
+#define MM_MINOR_VER(x) ((x) & MM_MINOR_VER_MASK)
+
+#define MM_CALLER_MAJOR_VER      0x1UL
+#define MM_CALLER_MINOR_VER      0x0
+
+#endif /* MM_COMMUNICATE_H_ */
diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/MmCommunicationDxe/MmCommunication.c b/Silicon/Ampere/AmpereAltraPkg/Drivers/MmCommunicationDxe/MmCommunication.c
new file mode 100644
index 000000000000..271fc755548f
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/MmCommunicationDxe/MmCommunication.c
@@ -0,0 +1,454 @@
+/** @file
+
+  Copyright (c) 2020, Ampere Computing LLC
+  Copyright (c) 2016-2018, ARM Limited. All rights reserved.
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <IndustryStandard/ArmStdSmc.h>
+#include <Library/ArmLib.h>
+#include <Library/ArmSmcLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/HobLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Protocol/MmCommunication.h>
+
+#include "MmCommunicate.h"
+
+#define MM_EARLY_MEM_ALLOCATE 1
+
+//
+// Address, Length of the pre-allocated buffer for communication with the secure
+// world.
+//
+STATIC ARM_MEMORY_REGION_DESCRIPTOR mNsCommBuffMemRegion;
+
+// Notification event when virtual address map is set.
+STATIC EFI_EVENT mSetVirtualAddressMapEvent;
+
+//
+// Handle to install the MM Communication Protocol
+//
+STATIC EFI_HANDLE mMmCommunicateHandle;
+
+/**
+  Communicates with a registered handler.
+
+  This function provides an interface to send and receive messages to the
+  Standalone MM environment on behalf of UEFI services.  This function is part
+  of the MM Communication Protocol that may be called in physical mode prior to
+  SetVirtualAddressMap() and in virtual mode after SetVirtualAddressMap().
+
+  @param[in]      This                The EFI_MM_COMMUNICATION_PROTOCOL
+                                      instance.
+  @param[in, out] CommBuffer          A pointer to the buffer to convey
+                                      into MMRAM.
+  @param[in, out] CommSize            The size of the data buffer being
+                                      passed in. This is optional.
+
+  @retval EFI_SUCCESS                 The message was successfully posted.
+  @retval EFI_INVALID_PARAMETER       The CommBuffer was NULL.
+  @retval EFI_BAD_BUFFER_SIZE         The buffer size is incorrect 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
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+MmCommunicationCommunicate (
+  IN CONST EFI_MM_COMMUNICATION_PROTOCOL *This,
+  IN OUT   VOID                          *CommBuffer,
+  IN OUT   UINTN                         *CommSize OPTIONAL
+  )
+{
+  EFI_MM_COMMUNICATE_HEADER *CommunicateHeader;
+  ARM_SMC_ARGS              CommunicateSmcArgs;
+  EFI_STATUS                Status;
+  UINTN                     BufferSize;
+
+  Status = EFI_ACCESS_DENIED;
+  BufferSize = 0;
+
+  ZeroMem (&CommunicateSmcArgs, sizeof (ARM_SMC_ARGS));
+
+  //
+  // Check parameters
+  //
+  if (CommBuffer == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  CommunicateHeader = CommBuffer;
+  // CommBuffer is a mandatory parameter. Hence, rely on
+  // MessageLength + Header to ascertain the
+  // total size of the communication payload rather than
+  // relying on optional CommSize parameter
+  BufferSize = CommunicateHeader->MessageLength +
+               sizeof (CommunicateHeader->HeaderGuid) +
+               sizeof (CommunicateHeader->MessageLength);
+
+  // If the length of the CommBuffer is 0 then return the expected length.
+  if (CommSize != NULL) {
+    // This case can be used by the consumer of this driver to find out the
+    // max size that can be used for allocating CommBuffer.
+    if ((*CommSize == 0) ||
+        (*CommSize > mNsCommBuffMemRegion.Length))
+    {
+      *CommSize = mNsCommBuffMemRegion.Length;
+      return EFI_BAD_BUFFER_SIZE;
+    }
+    //
+    // CommSize must match MessageLength + sizeof (EFI_MM_COMMUNICATE_HEADER);
+    //
+    if (*CommSize != BufferSize) {
+      return EFI_INVALID_PARAMETER;
+    }
+  }
+
+  //
+  // If the buffer size is 0 or greater than what can be tolerated by the MM
+  // environment then return the expected size.
+  //
+  if ((BufferSize == 0) ||
+      (BufferSize > mNsCommBuffMemRegion.Length))
+  {
+    CommunicateHeader->MessageLength = mNsCommBuffMemRegion.Length -
+                                       sizeof (CommunicateHeader->HeaderGuid) -
+                                       sizeof (CommunicateHeader->MessageLength);
+    return EFI_BAD_BUFFER_SIZE;
+  }
+
+  // SMC Function ID
+  CommunicateSmcArgs.Arg0 = ARM_SMC_ID_MM_COMMUNICATE_AARCH64;
+
+  // Cookie
+  CommunicateSmcArgs.Arg1 = 0;
+
+  // Copy Communication Payload
+  CopyMem ((VOID *)mNsCommBuffMemRegion.VirtualBase, CommBuffer, BufferSize);
+
+  // comm_buffer_address (64-bit physical address)
+  CommunicateSmcArgs.Arg2 = (UINTN)mNsCommBuffMemRegion.PhysicalBase;
+
+  // comm_size_address (not used, indicated by setting to zero)
+  CommunicateSmcArgs.Arg3 = 0;
+
+  // Call the Standalone MM environment.
+  ArmCallSmc (&CommunicateSmcArgs);
+
+  switch (CommunicateSmcArgs.Arg0) {
+  case ARM_SMC_MM_RET_SUCCESS:
+    ZeroMem (CommBuffer, BufferSize);
+    // 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);
+
+    CopyMem (
+      CommBuffer,
+      (VOID *)mNsCommBuffMemRegion.VirtualBase,
+      BufferSize
+      );
+    Status = EFI_SUCCESS;
+    break;
+
+  case ARM_SMC_MM_RET_INVALID_PARAMS:
+    Status = EFI_INVALID_PARAMETER;
+    break;
+
+  case ARM_SMC_MM_RET_DENIED:
+    Status = EFI_ACCESS_DENIED;
+    break;
+
+  case ARM_SMC_MM_RET_NO_MEMORY:
+    // Unexpected error since the CommSize was checked for zero length
+    // prior to issuing the SMC
+    Status = EFI_OUT_OF_RESOURCES;
+    ASSERT (0);
+    break;
+
+  default:
+    Status = EFI_ACCESS_DENIED;
+    ASSERT (0);
+  }
+
+  return Status;
+}
+
+//
+// MM Communication Protocol instance
+//
+EFI_MM_COMMUNICATION_PROTOCOL mMmCommunication = {
+  MmCommunicationCommunicate
+};
+
+/**
+  Notification callback on SetVirtualAddressMap event.
+
+  This function notifies the MM communication protocol interface on
+  SetVirtualAddressMap event and converts pointers used in this driver
+  from physical to virtual address.
+
+  @param  Event          SetVirtualAddressMap event.
+  @param  Context        A context when the SetVirtualAddressMap triggered.
+
+  @retval EFI_SUCCESS    The function executed successfully.
+  @retval Other          Some error occurred when executing this function.
+
+**/
+STATIC
+VOID
+EFIAPI
+NotifySetVirtualAddressMap (
+  IN EFI_EVENT Event,
+  IN VOID      *Context
+  )
+{
+  EFI_STATUS Status;
+
+  Status = gRT->ConvertPointer (
+                  EFI_OPTIONAL_PTR,
+                  (VOID **)&mNsCommBuffMemRegion.VirtualBase
+                  );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "%a: Unable to convert MM runtime pointer. Status:0x%r\n",
+      __FUNCTION__,
+      Status
+      ));
+  }
+
+}
+
+STATIC
+EFI_STATUS
+GetMmCompatibility ()
+{
+  EFI_STATUS   Status;
+  UINT32       MmVersion;
+  ARM_SMC_ARGS MmVersionArgs;
+
+  // MM_VERSION uses SMC32 calling conventions
+  MmVersionArgs.Arg0 = ARM_SMC_ID_MM_VERSION_AARCH32;
+
+  ArmCallSmc (&MmVersionArgs);
+
+  MmVersion = MmVersionArgs.Arg0;
+
+  if ((MM_MAJOR_VER (MmVersion) == MM_CALLER_MAJOR_VER) &&
+      (MM_MINOR_VER (MmVersion) >= MM_CALLER_MINOR_VER))
+  {
+    DEBUG ((
+      DEBUG_INFO,
+      "MM Version: Major=0x%x, Minor=0x%x\n",
+      MM_MAJOR_VER (MmVersion),
+      MM_MINOR_VER (MmVersion)
+      ));
+    Status = EFI_SUCCESS;
+  } else {
+    DEBUG ((
+      DEBUG_ERROR,
+      "Incompatible MM Versions.\n Current Version: Major=0x%x, "
+      "Minor=0x%x.\n Expected: Major=0x%x, Minor>=0x%x.\n",
+      MM_MAJOR_VER (MmVersion),
+      MM_MINOR_VER (MmVersion),
+      MM_CALLER_MAJOR_VER,
+      MM_CALLER_MINOR_VER
+      ));
+    Status = EFI_UNSUPPORTED;
+  }
+
+  return Status;
+}
+
+STATIC EFI_GUID *CONST mGuidedEventGuid[] = {
+  &gEfiEndOfDxeEventGroupGuid,
+  &gEfiEventExitBootServicesGuid,
+  &gEfiEventReadyToBootGuid,
+};
+
+STATIC EFI_EVENT mGuidedEvent[ARRAY_SIZE (mGuidedEventGuid)];
+
+/**
+  Event notification that is fired when GUIDed Event Group is signaled.
+
+  @param  Event                 The Event that is being processed, not used.
+  @param  Context               Event Context, not used.
+
+**/
+STATIC
+VOID
+EFIAPI
+MmGuidedEventNotify (
+  IN EFI_EVENT Event,
+  IN VOID      *Context
+  )
+{
+  EFI_MM_COMMUNICATE_HEADER Header;
+  UINTN                     Size;
+
+  //
+  // Use Guid to initialize EFI_SMM_COMMUNICATE_HEADER structure
+  //
+  CopyGuid (&Header.HeaderGuid, Context);
+  Header.MessageLength = 1;
+  Header.Data[0] = 0;
+
+  Size = sizeof (Header);
+  MmCommunicationCommunicate (&mMmCommunication, &Header, &Size);
+}
+
+/**
+  The Entry Point for MM Communication
+
+  This function installs the MM communication protocol interface and finds out
+  what type of buffer management will be required prior to invoking the
+  communication SMC.
+
+  @param  ImageHandle    The firmware allocated handle for the EFI image.
+  @param  SystemTable    A pointer to the EFI System Table.
+
+  @retval EFI_SUCCESS    The entry point is executed successfully.
+  @retval Other          Some error occurred when executing this entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+MmCommunicationInitialize (
+  IN EFI_HANDLE       ImageHandle,
+  IN EFI_SYSTEM_TABLE *SystemTable
+  )
+{
+  EFI_STATUS Status;
+  UINTN      Index;
+
+  // Check if we can make the MM call
+  Status = GetMmCompatibility ();
+  if (EFI_ERROR (Status)) {
+    goto ReturnErrorStatus;
+  }
+
+  mNsCommBuffMemRegion.PhysicalBase = PcdGet64 (PcdMmBufferBase);
+  // During boot, virtual and physical are same
+  mNsCommBuffMemRegion.VirtualBase = mNsCommBuffMemRegion.PhysicalBase;
+  mNsCommBuffMemRegion.Length = PcdGet64 (PcdMmBufferSize);
+
+  ASSERT (mNsCommBuffMemRegion.PhysicalBase != 0);
+
+  ASSERT (mNsCommBuffMemRegion.Length != 0);
+
+#if !defined(MM_EARLY_MEM_ALLOCATE)
+  Status = gDS->AddMemorySpace (
+                  EfiGcdMemoryTypeReserved,
+                  mNsCommBuffMemRegion.PhysicalBase,
+                  mNsCommBuffMemRegion.Length,
+                  EFI_MEMORY_WB |
+                  EFI_MEMORY_XP |
+                  EFI_MEMORY_RUNTIME
+                  );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "%a: Failed to add MM-NS Buffer Memory Space\n",
+      __FUNCTION__
+      ));
+    goto ReturnErrorStatus;
+  }
+
+  Status = gDS->SetMemorySpaceAttributes (
+                  mNsCommBuffMemRegion.PhysicalBase,
+                  mNsCommBuffMemRegion.Length,
+                  EFI_MEMORY_WB | EFI_MEMORY_XP | EFI_MEMORY_RUNTIME
+                  );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "%a: Failed to set MM-NS Buffer Memory attributes\n",
+      __FUNCTION__
+      ));
+    goto CleanAddedMemorySpace;
+  }
+#endif
+
+  // Install the communication protocol
+  Status = gBS->InstallProtocolInterface (
+                  &mMmCommunicateHandle,
+                  &gEfiMmCommunicationProtocolGuid,
+                  EFI_NATIVE_INTERFACE,
+                  &mMmCommunication
+                  );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "%a: Failed to install MM communication protocol\n",
+      __FUNCTION__
+      ));
+    goto CleanAddedMemorySpace;
+  }
+
+  // Register notification callback when virtual address is associated
+  // with the physical address.
+  // Create a Set Virtual Address Map event.
+  Status = gBS->CreateEvent (
+                  EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE,
+                  TPL_NOTIFY,
+                  NotifySetVirtualAddressMap,
+                  NULL,
+                  &mSetVirtualAddressMapEvent
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  for (Index = 0; Index < ARRAY_SIZE (mGuidedEventGuid); Index++) {
+    Status = gBS->CreateEventEx (
+                    EVT_NOTIFY_SIGNAL,
+                    TPL_CALLBACK,
+                    MmGuidedEventNotify,
+                    mGuidedEventGuid[Index],
+                    mGuidedEventGuid[Index],
+                    &mGuidedEvent[Index]
+                    );
+    ASSERT_EFI_ERROR (Status);
+    if (EFI_ERROR (Status)) {
+      while (Index-- > 0) {
+        gBS->CloseEvent (mGuidedEvent[Index]);
+      }
+      goto UninstallProtocol;
+    }
+  }
+  return EFI_SUCCESS;
+
+UninstallProtocol:
+  gBS->UninstallProtocolInterface (
+         mMmCommunicateHandle,
+         &gEfiMmCommunicationProtocolGuid,
+         &mMmCommunication
+         );
+
+CleanAddedMemorySpace:
+#if !defined(MM_EARLY_MEM_ALLOCATE)
+  gDS->RemoveMemorySpace (
+         mNsCommBuffMemRegion.PhysicalBase,
+         mNsCommBuffMemRegion.Length
+         );
+#endif
+
+ReturnErrorStatus:
+  return EFI_INVALID_PARAMETER;
+}
diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/MmCommunicationPei/MmCommunicationPei.c b/Silicon/Ampere/AmpereAltraPkg/Drivers/MmCommunicationPei/MmCommunicationPei.c
new file mode 100644
index 000000000000..d3925015612f
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/MmCommunicationPei/MmCommunicationPei.c
@@ -0,0 +1,37 @@
+/** @file
+
+  Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiPei.h>
+#include <Uefi/UefiSpec.h>
+
+#include <Library/HobLib.h>
+#include <Library/PeimEntryPoint.h>
+
+/**
+  Entry point function for the PEIM
+
+  @param FileHandle      Handle of the file being invoked.
+  @param PeiServices     Describes the list of possible PEI Services.
+
+  @return EFI_SUCCESS    If we installed our PPI
+
+**/
+EFI_STATUS
+EFIAPI
+MmCommunicationPeiEntryPoint (
+  IN       EFI_PEI_FILE_HANDLE FileHandle,
+  IN CONST EFI_PEI_SERVICES    **PeiServices
+  )
+{
+  EFI_PHYSICAL_ADDRESS MmBufferBase = PcdGet64 (PcdMmBufferBase);
+  UINT64               MmBufferSize = PcdGet64 (PcdMmBufferSize);
+
+  BuildMemoryAllocationHob (MmBufferBase, MmBufferSize, EfiRuntimeServicesData);
+
+  return EFI_SUCCESS;
+}
-- 
2.17.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#75610): https://edk2.groups.io/g/devel/message/75610
Mute This Topic: https://groups.io/mt/83097095/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-


Re: [edk2-devel] [edk2-platforms][PATCH v2 02/32] AmpereAltraPkg: Add MmCommunication modules
Posted by Leif Lindholm 4 years, 8 months ago
On Wed, May 26, 2021 at 17:06:54 +0700, Nhi Pham wrote:
> From: Vu Nguyen <vunguyen@os.amperecomputing.com>
> 
> The MmCommunicationDxe module is derived from
> ArmPkg/Drivers/MmCommunicationDxe/MmCommunication.inf.
> 
> The MmCommunication PEI and DXE modules implement the MM Communication
> protocol (EFI_MM_COMMUNICATION_PROTOCOL) as defined in the PI 1.5
> specification for the interface between UEFI and MM services in the
> secure world.
> 
> Cc: Thang Nguyen <thang@os.amperecomputing.com>
> Cc: Chuong Tran <chuong@os.amperecomputing.com>
> Cc: Phong Vo <phong@os.amperecomputing.com>
> Cc: Leif Lindholm <leif@nuviainc.com>
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
> Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
> 
> Signed-off-by: Vu Nguyen <vunguyen@os.amperecomputing.com>

Reviewed-by: Leif Lindholm <leif@nuviainc.com>

> ---
>  Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec                                |   3 +
>  Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc                            |   2 +
>  Platform/Ampere/JadePkg/Jade.fdf                                                |   3 +
>  Silicon/Ampere/AmpereAltraPkg/Drivers/MmCommunicationDxe/MmCommunication.inf    |  57 +++
>  Silicon/Ampere/AmpereAltraPkg/Drivers/MmCommunicationPei/MmCommunicationPei.inf |  34 ++
>  Silicon/Ampere/AmpereAltraPkg/Drivers/MmCommunicationDxe/MmCommunicate.h        |  22 +
>  Silicon/Ampere/AmpereAltraPkg/Drivers/MmCommunicationDxe/MmCommunication.c      | 454 ++++++++++++++++++++
>  Silicon/Ampere/AmpereAltraPkg/Drivers/MmCommunicationPei/MmCommunicationPei.c   |  37 ++
>  8 files changed, 612 insertions(+)
> 
> diff --git a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec
> index f0a5bd04ec22..73097afaf841 100644
> --- a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec
> +++ b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec
> @@ -38,5 +38,8 @@ [Guids]
>    ## NVParam MM GUID
>    gNVParamMmGuid               = { 0xE4AC5024, 0x29BE, 0x4ADC, { 0x93, 0x36, 0x87, 0xB5, 0xA0, 0x76, 0x23, 0x2D } }
>  
> +  ## SPI NOR Proxy MM GUID
> +  gSpiNorMmGuid                = { 0xC8D76438, 0x4D3C, 0x4BEA, { 0xBF, 0x86, 0x92, 0x6B, 0x83, 0x07, 0xA2, 0x39 } }
> +
>    ## Include/Guid/PlatformInfoHobGuid.h
>    gPlatformHobGuid             = { 0x7f73e372, 0x7183, 0x4022, { 0xb3, 0x76, 0x78, 0x30, 0x32, 0x6d, 0x79, 0xb4 } }
> diff --git a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc
> index af66c27822a3..0332473b59b0 100755
> --- a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc
> +++ b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc
> @@ -517,6 +517,7 @@ [Components.common]
>    ArmPlatformPkg/PlatformPei/PlatformPeim.inf
>    Silicon/Ampere/AmpereAltraPkg/Drivers/ATFHobPei/ATFHobPeim.inf
>    Silicon/Ampere/AmpereAltraPkg/Drivers/MemoryInitPeim/MemoryInitPeim.inf
> +  Silicon/Ampere/AmpereAltraPkg/Drivers/MmCommunicationPei/MmCommunicationPei.inf
>    ArmPkg/Drivers/CpuPei/CpuPei.inf
>    UefiCpuPkg/CpuIoPei/CpuIoPei.inf
>    MdeModulePkg/Universal/Variable/Pei/VariablePei.inf
> @@ -565,6 +566,7 @@ [Components.common]
>    EmbeddedPkg/ResetRuntimeDxe/ResetRuntimeDxe.inf
>    EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClockRuntimeDxe.inf
>    EmbeddedPkg/MetronomeDxe/MetronomeDxe.inf
> +  Silicon/Ampere/AmpereAltraPkg/Drivers/MmCommunicationDxe/MmCommunication.inf
>  
>    #
>    # Environment Variables Protocol
> diff --git a/Platform/Ampere/JadePkg/Jade.fdf b/Platform/Ampere/JadePkg/Jade.fdf
> index 8ed6df381aed..905289844378 100755
> --- a/Platform/Ampere/JadePkg/Jade.fdf
> +++ b/Platform/Ampere/JadePkg/Jade.fdf
> @@ -101,6 +101,7 @@ [FV.FVMAIN_COMPACT]
>    INF ArmPlatformPkg/PlatformPei/PlatformPeim.inf
>    INF Silicon/Ampere/AmpereAltraPkg/Drivers/ATFHobPei/ATFHobPeim.inf
>    INF Silicon/Ampere/AmpereAltraPkg/Drivers/MemoryInitPeim/MemoryInitPeim.inf
> +  INF Silicon/Ampere/AmpereAltraPkg/Drivers/MmCommunicationPei/MmCommunicationPei.inf
>    INF ArmPkg/Drivers/CpuPei/CpuPei.inf
>    INF MdeModulePkg/Universal/PCD/Pei/Pcd.inf
>    INF MdeModulePkg/Universal/Variable/Pei/VariablePei.inf
> @@ -141,6 +142,7 @@ [FV.FvMain]
>    INF MdeModulePkg/Universal/PCD/Dxe/Pcd.inf
>    INF MdeModulePkg/Universal/ReportStatusCodeRouter/RuntimeDxe/ReportStatusCodeRouterRuntimeDxe.inf
>    INF MdeModulePkg/Universal/StatusCodeHandler/RuntimeDxe/StatusCodeHandlerRuntimeDxe.inf
> +  INF Silicon/Ampere/AmpereAltraPkg/Drivers/MmCommunicationDxe/MmCommunication.inf
>  }
>  
>    INF MdeModulePkg/Core/Dxe/DxeMain.inf
> @@ -163,6 +165,7 @@ [FV.FvMain]
>    INF EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClockRuntimeDxe.inf
>    INF EmbeddedPkg/MetronomeDxe/MetronomeDxe.inf
>    INF MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf
> +  INF Silicon/Ampere/AmpereAltraPkg/Drivers/MmCommunicationDxe/MmCommunication.inf
>  
>    #
>    # Environment Variables Protocol
> diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/MmCommunicationDxe/MmCommunication.inf b/Silicon/Ampere/AmpereAltraPkg/Drivers/MmCommunicationDxe/MmCommunication.inf
> new file mode 100644
> index 000000000000..3efff142944f
> --- /dev/null
> +++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/MmCommunicationDxe/MmCommunication.inf
> @@ -0,0 +1,57 @@
> +#/** @file
> +#
> +#  This module implements the MM Communication Protocol (EFI_MM_COMMUNICATION_PROTOCOL)
> +#  as defined in the PI 1.5 specification.
> +#
> +#  Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.
> +#
> +#  SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +#**/
> +
> +[Defines]
> +  INF_VERSION                    = 0x0001001B
> +  BASE_NAME                      = ArmMmCommunication
> +  FILE_GUID                      = 09EE81D3-F15E-43F4-85B4-CB9873DA5D6B
> +  MODULE_TYPE                    = DXE_RUNTIME_DRIVER
> +  VERSION_STRING                 = 1.0
> +  ENTRY_POINT                    = MmCommunicationInitialize
> +
> +#
> +# The following is for reference only and not required by
> +# build tools
> +#
> +# VALID_ARCHITECTURES            = AARCH64
> +#
> +
> +[Sources.AARCH64]
> +  MmCommunicate.h
> +  MmCommunication.c
> +
> +[Packages]
> +  ArmPkg/ArmPkg.dec
> +  MdePkg/MdePkg.dec
> +
> +[LibraryClasses]
> +  ArmLib
> +  ArmSmcLib
> +  BaseMemoryLib
> +  DebugLib
> +  DxeServicesTableLib
> +  HobLib
> +  UefiDriverEntryPoint
> +
> +[Protocols]
> +  gEfiMmCommunicationProtocolGuid              ## PRODUCES
> +
> +[Guids]
> +  gEfiEndOfDxeEventGroupGuid
> +  gEfiEventExitBootServicesGuid
> +  gEfiEventReadyToBootGuid
> +
> +[Pcd.common]
> +  gArmTokenSpaceGuid.PcdMmBufferBase
> +  gArmTokenSpaceGuid.PcdMmBufferSize
> +
> +[Depex]
> +  gEfiCpuArchProtocolGuid
> diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/MmCommunicationPei/MmCommunicationPei.inf b/Silicon/Ampere/AmpereAltraPkg/Drivers/MmCommunicationPei/MmCommunicationPei.inf
> new file mode 100755
> index 000000000000..3a985840a0a0
> --- /dev/null
> +++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/MmCommunicationPei/MmCommunicationPei.inf
> @@ -0,0 +1,34 @@
> +## @file
> +#
> +# Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x0001001B
> +  BASE_NAME                      = MmCommunicationPei
> +  FILE_GUID                      = B5AE0F80-DF81-11EA-8B6E-0800200C9A66
> +  MODULE_TYPE                    = PEIM
> +  VERSION_STRING                 = 1.0
> +  ENTRY_POINT                    = MmCommunicationPeiEntryPoint
> +
> +[Sources]
> +  MmCommunicationPei.c
> +
> +[Packages]
> +  ArmPkg/ArmPkg.dec
> +  MdePkg/MdePkg.dec
> +
> +[LibraryClasses]
> +  HobLib
> +  PcdLib
> +  PeimEntryPoint
> +
> +[Pcd]
> +  gArmTokenSpaceGuid.PcdMmBufferBase
> +  gArmTokenSpaceGuid.PcdMmBufferSize
> +
> +[Depex]
> +  TRUE
> diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/MmCommunicationDxe/MmCommunicate.h b/Silicon/Ampere/AmpereAltraPkg/Drivers/MmCommunicationDxe/MmCommunicate.h
> new file mode 100644
> index 000000000000..804ba58afb72
> --- /dev/null
> +++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/MmCommunicationDxe/MmCommunicate.h
> @@ -0,0 +1,22 @@
> +/** @file
> +
> +  Copyright (c) 2016-2018, ARM Limited. All rights reserved.
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#ifndef MM_COMMUNICATE_H_
> +#define MM_COMMUNICATE_H_
> +
> +#define MM_MAJOR_VER_MASK        0xEFFF0000
> +#define MM_MINOR_VER_MASK        0x0000FFFF
> +#define MM_MAJOR_VER_SHIFT       16
> +
> +#define MM_MAJOR_VER(x) (((x) & MM_MAJOR_VER_MASK) >> MM_MAJOR_VER_SHIFT)
> +#define MM_MINOR_VER(x) ((x) & MM_MINOR_VER_MASK)
> +
> +#define MM_CALLER_MAJOR_VER      0x1UL
> +#define MM_CALLER_MINOR_VER      0x0
> +
> +#endif /* MM_COMMUNICATE_H_ */
> diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/MmCommunicationDxe/MmCommunication.c b/Silicon/Ampere/AmpereAltraPkg/Drivers/MmCommunicationDxe/MmCommunication.c
> new file mode 100644
> index 000000000000..271fc755548f
> --- /dev/null
> +++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/MmCommunicationDxe/MmCommunication.c
> @@ -0,0 +1,454 @@
> +/** @file
> +
> +  Copyright (c) 2020, Ampere Computing LLC
> +  Copyright (c) 2016-2018, ARM Limited. All rights reserved.
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include <IndustryStandard/ArmStdSmc.h>
> +#include <Library/ArmLib.h>
> +#include <Library/ArmSmcLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/DxeServicesTableLib.h>
> +#include <Library/HobLib.h>
> +#include <Library/PcdLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiRuntimeServicesTableLib.h>
> +#include <Protocol/MmCommunication.h>
> +
> +#include "MmCommunicate.h"
> +
> +#define MM_EARLY_MEM_ALLOCATE 1
> +
> +//
> +// Address, Length of the pre-allocated buffer for communication with the secure
> +// world.
> +//
> +STATIC ARM_MEMORY_REGION_DESCRIPTOR mNsCommBuffMemRegion;
> +
> +// Notification event when virtual address map is set.
> +STATIC EFI_EVENT mSetVirtualAddressMapEvent;
> +
> +//
> +// Handle to install the MM Communication Protocol
> +//
> +STATIC EFI_HANDLE mMmCommunicateHandle;
> +
> +/**
> +  Communicates with a registered handler.
> +
> +  This function provides an interface to send and receive messages to the
> +  Standalone MM environment on behalf of UEFI services.  This function is part
> +  of the MM Communication Protocol that may be called in physical mode prior to
> +  SetVirtualAddressMap() and in virtual mode after SetVirtualAddressMap().
> +
> +  @param[in]      This                The EFI_MM_COMMUNICATION_PROTOCOL
> +                                      instance.
> +  @param[in, out] CommBuffer          A pointer to the buffer to convey
> +                                      into MMRAM.
> +  @param[in, out] CommSize            The size of the data buffer being
> +                                      passed in. This is optional.
> +
> +  @retval EFI_SUCCESS                 The message was successfully posted.
> +  @retval EFI_INVALID_PARAMETER       The CommBuffer was NULL.
> +  @retval EFI_BAD_BUFFER_SIZE         The buffer size is incorrect 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
> +**/
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +MmCommunicationCommunicate (
> +  IN CONST EFI_MM_COMMUNICATION_PROTOCOL *This,
> +  IN OUT   VOID                          *CommBuffer,
> +  IN OUT   UINTN                         *CommSize OPTIONAL
> +  )
> +{
> +  EFI_MM_COMMUNICATE_HEADER *CommunicateHeader;
> +  ARM_SMC_ARGS              CommunicateSmcArgs;
> +  EFI_STATUS                Status;
> +  UINTN                     BufferSize;
> +
> +  Status = EFI_ACCESS_DENIED;
> +  BufferSize = 0;
> +
> +  ZeroMem (&CommunicateSmcArgs, sizeof (ARM_SMC_ARGS));
> +
> +  //
> +  // Check parameters
> +  //
> +  if (CommBuffer == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  CommunicateHeader = CommBuffer;
> +  // CommBuffer is a mandatory parameter. Hence, rely on
> +  // MessageLength + Header to ascertain the
> +  // total size of the communication payload rather than
> +  // relying on optional CommSize parameter
> +  BufferSize = CommunicateHeader->MessageLength +
> +               sizeof (CommunicateHeader->HeaderGuid) +
> +               sizeof (CommunicateHeader->MessageLength);
> +
> +  // If the length of the CommBuffer is 0 then return the expected length.
> +  if (CommSize != NULL) {
> +    // This case can be used by the consumer of this driver to find out the
> +    // max size that can be used for allocating CommBuffer.
> +    if ((*CommSize == 0) ||
> +        (*CommSize > mNsCommBuffMemRegion.Length))
> +    {
> +      *CommSize = mNsCommBuffMemRegion.Length;
> +      return EFI_BAD_BUFFER_SIZE;
> +    }
> +    //
> +    // CommSize must match MessageLength + sizeof (EFI_MM_COMMUNICATE_HEADER);
> +    //
> +    if (*CommSize != BufferSize) {
> +      return EFI_INVALID_PARAMETER;
> +    }
> +  }
> +
> +  //
> +  // If the buffer size is 0 or greater than what can be tolerated by the MM
> +  // environment then return the expected size.
> +  //
> +  if ((BufferSize == 0) ||
> +      (BufferSize > mNsCommBuffMemRegion.Length))
> +  {
> +    CommunicateHeader->MessageLength = mNsCommBuffMemRegion.Length -
> +                                       sizeof (CommunicateHeader->HeaderGuid) -
> +                                       sizeof (CommunicateHeader->MessageLength);
> +    return EFI_BAD_BUFFER_SIZE;
> +  }
> +
> +  // SMC Function ID
> +  CommunicateSmcArgs.Arg0 = ARM_SMC_ID_MM_COMMUNICATE_AARCH64;
> +
> +  // Cookie
> +  CommunicateSmcArgs.Arg1 = 0;
> +
> +  // Copy Communication Payload
> +  CopyMem ((VOID *)mNsCommBuffMemRegion.VirtualBase, CommBuffer, BufferSize);
> +
> +  // comm_buffer_address (64-bit physical address)
> +  CommunicateSmcArgs.Arg2 = (UINTN)mNsCommBuffMemRegion.PhysicalBase;
> +
> +  // comm_size_address (not used, indicated by setting to zero)
> +  CommunicateSmcArgs.Arg3 = 0;
> +
> +  // Call the Standalone MM environment.
> +  ArmCallSmc (&CommunicateSmcArgs);
> +
> +  switch (CommunicateSmcArgs.Arg0) {
> +  case ARM_SMC_MM_RET_SUCCESS:
> +    ZeroMem (CommBuffer, BufferSize);
> +    // 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);
> +
> +    CopyMem (
> +      CommBuffer,
> +      (VOID *)mNsCommBuffMemRegion.VirtualBase,
> +      BufferSize
> +      );
> +    Status = EFI_SUCCESS;
> +    break;
> +
> +  case ARM_SMC_MM_RET_INVALID_PARAMS:
> +    Status = EFI_INVALID_PARAMETER;
> +    break;
> +
> +  case ARM_SMC_MM_RET_DENIED:
> +    Status = EFI_ACCESS_DENIED;
> +    break;
> +
> +  case ARM_SMC_MM_RET_NO_MEMORY:
> +    // Unexpected error since the CommSize was checked for zero length
> +    // prior to issuing the SMC
> +    Status = EFI_OUT_OF_RESOURCES;
> +    ASSERT (0);
> +    break;
> +
> +  default:
> +    Status = EFI_ACCESS_DENIED;
> +    ASSERT (0);
> +  }
> +
> +  return Status;
> +}
> +
> +//
> +// MM Communication Protocol instance
> +//
> +EFI_MM_COMMUNICATION_PROTOCOL mMmCommunication = {
> +  MmCommunicationCommunicate
> +};
> +
> +/**
> +  Notification callback on SetVirtualAddressMap event.
> +
> +  This function notifies the MM communication protocol interface on
> +  SetVirtualAddressMap event and converts pointers used in this driver
> +  from physical to virtual address.
> +
> +  @param  Event          SetVirtualAddressMap event.
> +  @param  Context        A context when the SetVirtualAddressMap triggered.
> +
> +  @retval EFI_SUCCESS    The function executed successfully.
> +  @retval Other          Some error occurred when executing this function.
> +
> +**/
> +STATIC
> +VOID
> +EFIAPI
> +NotifySetVirtualAddressMap (
> +  IN EFI_EVENT Event,
> +  IN VOID      *Context
> +  )
> +{
> +  EFI_STATUS Status;
> +
> +  Status = gRT->ConvertPointer (
> +                  EFI_OPTIONAL_PTR,
> +                  (VOID **)&mNsCommBuffMemRegion.VirtualBase
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "%a: Unable to convert MM runtime pointer. Status:0x%r\n",
> +      __FUNCTION__,
> +      Status
> +      ));
> +  }
> +
> +}
> +
> +STATIC
> +EFI_STATUS
> +GetMmCompatibility ()
> +{
> +  EFI_STATUS   Status;
> +  UINT32       MmVersion;
> +  ARM_SMC_ARGS MmVersionArgs;
> +
> +  // MM_VERSION uses SMC32 calling conventions
> +  MmVersionArgs.Arg0 = ARM_SMC_ID_MM_VERSION_AARCH32;
> +
> +  ArmCallSmc (&MmVersionArgs);
> +
> +  MmVersion = MmVersionArgs.Arg0;
> +
> +  if ((MM_MAJOR_VER (MmVersion) == MM_CALLER_MAJOR_VER) &&
> +      (MM_MINOR_VER (MmVersion) >= MM_CALLER_MINOR_VER))
> +  {
> +    DEBUG ((
> +      DEBUG_INFO,
> +      "MM Version: Major=0x%x, Minor=0x%x\n",
> +      MM_MAJOR_VER (MmVersion),
> +      MM_MINOR_VER (MmVersion)
> +      ));
> +    Status = EFI_SUCCESS;
> +  } else {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "Incompatible MM Versions.\n Current Version: Major=0x%x, "
> +      "Minor=0x%x.\n Expected: Major=0x%x, Minor>=0x%x.\n",
> +      MM_MAJOR_VER (MmVersion),
> +      MM_MINOR_VER (MmVersion),
> +      MM_CALLER_MAJOR_VER,
> +      MM_CALLER_MINOR_VER
> +      ));
> +    Status = EFI_UNSUPPORTED;
> +  }
> +
> +  return Status;
> +}
> +
> +STATIC EFI_GUID *CONST mGuidedEventGuid[] = {
> +  &gEfiEndOfDxeEventGroupGuid,
> +  &gEfiEventExitBootServicesGuid,
> +  &gEfiEventReadyToBootGuid,
> +};
> +
> +STATIC EFI_EVENT mGuidedEvent[ARRAY_SIZE (mGuidedEventGuid)];
> +
> +/**
> +  Event notification that is fired when GUIDed Event Group is signaled.
> +
> +  @param  Event                 The Event that is being processed, not used.
> +  @param  Context               Event Context, not used.
> +
> +**/
> +STATIC
> +VOID
> +EFIAPI
> +MmGuidedEventNotify (
> +  IN EFI_EVENT Event,
> +  IN VOID      *Context
> +  )
> +{
> +  EFI_MM_COMMUNICATE_HEADER Header;
> +  UINTN                     Size;
> +
> +  //
> +  // Use Guid to initialize EFI_SMM_COMMUNICATE_HEADER structure
> +  //
> +  CopyGuid (&Header.HeaderGuid, Context);
> +  Header.MessageLength = 1;
> +  Header.Data[0] = 0;
> +
> +  Size = sizeof (Header);
> +  MmCommunicationCommunicate (&mMmCommunication, &Header, &Size);
> +}
> +
> +/**
> +  The Entry Point for MM Communication
> +
> +  This function installs the MM communication protocol interface and finds out
> +  what type of buffer management will be required prior to invoking the
> +  communication SMC.
> +
> +  @param  ImageHandle    The firmware allocated handle for the EFI image.
> +  @param  SystemTable    A pointer to the EFI System Table.
> +
> +  @retval EFI_SUCCESS    The entry point is executed successfully.
> +  @retval Other          Some error occurred when executing this entry point.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +MmCommunicationInitialize (
> +  IN EFI_HANDLE       ImageHandle,
> +  IN EFI_SYSTEM_TABLE *SystemTable
> +  )
> +{
> +  EFI_STATUS Status;
> +  UINTN      Index;
> +
> +  // Check if we can make the MM call
> +  Status = GetMmCompatibility ();
> +  if (EFI_ERROR (Status)) {
> +    goto ReturnErrorStatus;
> +  }
> +
> +  mNsCommBuffMemRegion.PhysicalBase = PcdGet64 (PcdMmBufferBase);
> +  // During boot, virtual and physical are same
> +  mNsCommBuffMemRegion.VirtualBase = mNsCommBuffMemRegion.PhysicalBase;
> +  mNsCommBuffMemRegion.Length = PcdGet64 (PcdMmBufferSize);
> +
> +  ASSERT (mNsCommBuffMemRegion.PhysicalBase != 0);
> +
> +  ASSERT (mNsCommBuffMemRegion.Length != 0);
> +
> +#if !defined(MM_EARLY_MEM_ALLOCATE)
> +  Status = gDS->AddMemorySpace (
> +                  EfiGcdMemoryTypeReserved,
> +                  mNsCommBuffMemRegion.PhysicalBase,
> +                  mNsCommBuffMemRegion.Length,
> +                  EFI_MEMORY_WB |
> +                  EFI_MEMORY_XP |
> +                  EFI_MEMORY_RUNTIME
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "%a: Failed to add MM-NS Buffer Memory Space\n",
> +      __FUNCTION__
> +      ));
> +    goto ReturnErrorStatus;
> +  }
> +
> +  Status = gDS->SetMemorySpaceAttributes (
> +                  mNsCommBuffMemRegion.PhysicalBase,
> +                  mNsCommBuffMemRegion.Length,
> +                  EFI_MEMORY_WB | EFI_MEMORY_XP | EFI_MEMORY_RUNTIME
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "%a: Failed to set MM-NS Buffer Memory attributes\n",
> +      __FUNCTION__
> +      ));
> +    goto CleanAddedMemorySpace;
> +  }
> +#endif
> +
> +  // Install the communication protocol
> +  Status = gBS->InstallProtocolInterface (
> +                  &mMmCommunicateHandle,
> +                  &gEfiMmCommunicationProtocolGuid,
> +                  EFI_NATIVE_INTERFACE,
> +                  &mMmCommunication
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((
> +      DEBUG_ERROR,
> +      "%a: Failed to install MM communication protocol\n",
> +      __FUNCTION__
> +      ));
> +    goto CleanAddedMemorySpace;
> +  }
> +
> +  // Register notification callback when virtual address is associated
> +  // with the physical address.
> +  // Create a Set Virtual Address Map event.
> +  Status = gBS->CreateEvent (
> +                  EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE,
> +                  TPL_NOTIFY,
> +                  NotifySetVirtualAddressMap,
> +                  NULL,
> +                  &mSetVirtualAddressMapEvent
> +                  );
> +  ASSERT_EFI_ERROR (Status);
> +
> +  for (Index = 0; Index < ARRAY_SIZE (mGuidedEventGuid); Index++) {
> +    Status = gBS->CreateEventEx (
> +                    EVT_NOTIFY_SIGNAL,
> +                    TPL_CALLBACK,
> +                    MmGuidedEventNotify,
> +                    mGuidedEventGuid[Index],
> +                    mGuidedEventGuid[Index],
> +                    &mGuidedEvent[Index]
> +                    );
> +    ASSERT_EFI_ERROR (Status);
> +    if (EFI_ERROR (Status)) {
> +      while (Index-- > 0) {
> +        gBS->CloseEvent (mGuidedEvent[Index]);
> +      }
> +      goto UninstallProtocol;
> +    }
> +  }
> +  return EFI_SUCCESS;
> +
> +UninstallProtocol:
> +  gBS->UninstallProtocolInterface (
> +         mMmCommunicateHandle,
> +         &gEfiMmCommunicationProtocolGuid,
> +         &mMmCommunication
> +         );
> +
> +CleanAddedMemorySpace:
> +#if !defined(MM_EARLY_MEM_ALLOCATE)
> +  gDS->RemoveMemorySpace (
> +         mNsCommBuffMemRegion.PhysicalBase,
> +         mNsCommBuffMemRegion.Length
> +         );
> +#endif
> +
> +ReturnErrorStatus:
> +  return EFI_INVALID_PARAMETER;
> +}
> diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/MmCommunicationPei/MmCommunicationPei.c b/Silicon/Ampere/AmpereAltraPkg/Drivers/MmCommunicationPei/MmCommunicationPei.c
> new file mode 100644
> index 000000000000..d3925015612f
> --- /dev/null
> +++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/MmCommunicationPei/MmCommunicationPei.c
> @@ -0,0 +1,37 @@
> +/** @file
> +
> +  Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include <PiPei.h>
> +#include <Uefi/UefiSpec.h>
> +
> +#include <Library/HobLib.h>
> +#include <Library/PeimEntryPoint.h>
> +
> +/**
> +  Entry point function for the PEIM
> +
> +  @param FileHandle      Handle of the file being invoked.
> +  @param PeiServices     Describes the list of possible PEI Services.
> +
> +  @return EFI_SUCCESS    If we installed our PPI
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +MmCommunicationPeiEntryPoint (
> +  IN       EFI_PEI_FILE_HANDLE FileHandle,
> +  IN CONST EFI_PEI_SERVICES    **PeiServices
> +  )
> +{
> +  EFI_PHYSICAL_ADDRESS MmBufferBase = PcdGet64 (PcdMmBufferBase);
> +  UINT64               MmBufferSize = PcdGet64 (PcdMmBufferSize);
> +
> +  BuildMemoryAllocationHob (MmBufferBase, MmBufferSize, EfiRuntimeServicesData);
> +
> +  return EFI_SUCCESS;
> +}
> -- 
> 2.17.1
> 


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#76083): https://edk2.groups.io/g/devel/message/76083
Mute This Topic: https://groups.io/mt/83097095/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-