public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH v1 0/2] Support MM based variable services in PEI for ARM
@ 2023-06-08 20:44 Kun Qin
  2023-06-08 20:44 ` [PATCH v1 1/2] ArmPkg: MmCommunicationPei: Introduce MM communicate in PEI Kun Qin
  2023-06-08 20:44 ` [PATCH v1 2/2] MdeModulePkg: Variable: Introduce MM based variable read service " Kun Qin
  0 siblings, 2 replies; 8+ messages in thread
From: Kun Qin @ 2023-06-08 20:44 UTC (permalink / raw)
  To: devel
  Cc: Hao A Wu, Liming Gao, Jian J Wang, Leif Lindholm, Ard Biesheuvel,
	Sami Mujawar

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

As of today, there has been a void in the variable service in PEI phase
on ARM systems that support PEI phase and standalone MM hosted variable
service.

This change adds the support through:
1. Add MM communication services in PEI phase for ARM platforms. This
module is based on SMC calls to standalone MM environments, similar to
"ArmPkg/Drivers/MmCommunicationDxe".

2. A service module that installs `gEfiPeiReadOnlyVariable2PpiGuid` based
on step 1. Note that this driver will not have special dependency on ARM
specific code, thus will be ideally added to MdeModulePkg.

Patch v1 branch: https://github.com/kuqin12/edk2/tree/arm_var_pei_v1

Cc: Hao A Wu <hao.a.wu@intel.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Leif Lindholm <quic_llindhol@quicinc.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Sami Mujawar <sami.mujawar@arm.com>

Kun Qin (2):
  ArmPkg: MmCommunicationPei: Introduce MM communicate in PEI
  MdeModulePkg: Variable: Introduce MM based variable read service in
    PEI

 ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.c          | 178 +++++++++
 MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.c   | 381 ++++++++++++++++++++
 ArmPkg/ArmPkg.dsc                                               |   2 +
 ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.h          |  76 ++++
 ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.inf        |  41 +++
 MdeModulePkg/MdeModulePkg.dsc                                   |   1 +
 MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.h   | 134 +++++++
 MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.inf |  43 +++
 8 files changed, 856 insertions(+)
 create mode 100644 ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.c
 create mode 100644 MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.c
 create mode 100644 ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.h
 create mode 100644 ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.inf
 create mode 100644 MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.h
 create mode 100644 MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.inf

-- 
2.40.1.windows.1


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH v1 1/2] ArmPkg: MmCommunicationPei: Introduce MM communicate in PEI
  2023-06-08 20:44 [PATCH v1 0/2] Support MM based variable services in PEI for ARM Kun Qin
@ 2023-06-08 20:44 ` Kun Qin
  2023-06-22 19:17   ` Sami Mujawar
  2023-06-08 20:44 ` [PATCH v1 2/2] MdeModulePkg: Variable: Introduce MM based variable read service " Kun Qin
  1 sibling, 1 reply; 8+ messages in thread
From: Kun Qin @ 2023-06-08 20:44 UTC (permalink / raw)
  To: devel
  Cc: Leif Lindholm, Ard Biesheuvel, Sami Mujawar, Ronny Hansen,
	Shriram Masanamuthu Chinnathurai, Preshit Harlikar

From: Kun Qin <kuqin@microsoft.com>

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

This change introduced the MM communicate support in PEI phase for ARM
based platforms. Similar to the DXE counterpart, `PcdMmBufferBase` is
used as communicate buffer and SMC will be invoked to communicate to
TrustZone when MMI is requested.

Cc: Leif Lindholm <quic_llindhol@quicinc.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Sami Mujawar <sami.mujawar@arm.com>

Co-authored-by: Ronny Hansen <hansen.ronny@microsoft.com>
Co-authored-by: Shriram Masanamuthu Chinnathurai <shriramma@microsoft.com>
Co-authored-by: Preshit Harlikar <pharlikar@microsoft.com>
Signed-off-by: Kun Qin <kuqin@microsoft.com>
---
 ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.c   | 178 ++++++++++++++++++++
 ArmPkg/ArmPkg.dsc                                        |   2 +
 ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.h   |  76 +++++++++
 ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.inf |  41 +++++
 4 files changed, 297 insertions(+)

diff --git a/ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.c b/ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.c
new file mode 100644
index 000000000000..0f1f763a347d
--- /dev/null
+++ b/ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.c
@@ -0,0 +1,178 @@
+/** @file -- MmCommunicationPei.c
+  Provides an interface to send MM request in PEI
+
+  Copyright (c) 2016-2021, Arm Limited. All rights reserved.<BR>
+  Copyright (c) Microsoft Corporation.
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "MmCommunicationPei.h"
+
+//
+// Module globals
+//
+EFI_PEI_MM_COMMUNICATION_PPI  mPeiMmCommunication = {
+  MmCommunicationPeim
+};
+
+EFI_PEI_PPI_DESCRIPTOR  mPeiMmCommunicationPpi = {
+  (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+  &gEfiPeiMmCommunicationPpiGuid,
+  &mPeiMmCommunication
+};
+
+/**
+  Entry point of PEI MM Communication driver
+
+  @param  FileHandle   Handle of the file being invoked.
+                       Type EFI_PEI_FILE_HANDLE is defined in FfsFindNextFile().
+  @param  PeiServices  General purpose services available to every PEIM.
+
+  @retval EFI_SUCCESS  If the interface could be successfully installed
+  @retval Others       Returned from PeiServicesInstallPpi()
+**/
+EFI_STATUS
+EFIAPI
+MmCommunicationPeiInitialize (
+  IN       EFI_PEI_FILE_HANDLE  FileHandle,
+  IN CONST EFI_PEI_SERVICES     **PeiServices
+  )
+{
+  return PeiServicesInstallPpi (&mPeiMmCommunicationPpi);
+}
+
+/**
+  MmCommunicationPeim
+  Communicates with a registered handler.
+  This function provides a service to send and receive messages from a registered UEFI service during PEI.
+
+  @param[in]      This            The EFI_PEI_MM_COMMUNICATION_PPI instance.
+  @param[in, out] CommBuffer      Pointer to the data buffer
+  @param[in, out] CommSize        The size of the data buffer being passed in. On exit, the
+                                  size of data being returned. Zero if the handler does not
+                                  wish to reply with any data.
+
+  @retval EFI_SUCCESS             The message was successfully posted.
+  @retval EFI_INVALID_PARAMETER   CommBuffer was NULL or *CommSize does not match
+                                  MessageLength + sizeof (EFI_MM_COMMUNICATE_HEADER).
+  @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
+MmCommunicationPeim (
+  IN CONST EFI_PEI_MM_COMMUNICATION_PPI  *This,
+  IN OUT VOID                            *CommBuffer,
+  IN OUT UINTN                           *CommSize
+  )
+{
+  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 that our static buffer is looking good.
+  // We are using PcdMmBufferBase to transfer variable data.
+  // We are not using the full size of the buffer since there is a cost
+  // of copying data between Normal and Secure World.
+  ASSERT (PcdGet64 (PcdMmBufferSize) > 0 && PcdGet64 (PcdMmBufferBase) != 0);
+
+  //
+  // Check parameters
+  //
+  if (CommBuffer == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // If the length of the CommBuffer is 0 then return the expected length.
+  // 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 != NULL) && \
+      ((*CommSize == 0) || (*CommSize > (UINTN)PcdGet64 (PcdMmBufferSize))))
+  {
+    *CommSize = (UINTN)PcdGet64 (PcdMmBufferSize);
+    return EFI_BAD_BUFFER_SIZE;
+  }
+
+  CommunicateHeader = (EFI_MM_COMMUNICATE_HEADER *)(UINTN)(PcdGet64 (PcdMmBufferBase));
+
+  CopyMem ((VOID *)CommunicateHeader, CommBuffer, *CommSize);
+
+  // 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 CommSize is supplied it must match MessageLength + sizeof (EFI_MM_COMMUNICATE_HEADER);
+  //
+  if ((CommSize != NULL) && (*CommSize != BufferSize)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // SMC Function ID
+  CommunicateSmcArgs.Arg0 = ARM_SMC_ID_MM_COMMUNICATE_AARCH64;
+
+  // Cookie
+  CommunicateSmcArgs.Arg1 = 0;
+
+  // comm_buffer_address (64-bit physical address)
+  CommunicateSmcArgs.Arg2 = (UINTN)CommunicateHeader;
+
+  // 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:
+      // On successful return, the size of data being returned is inferred from
+      // MessageLength + Header.
+      BufferSize = CommunicateHeader->MessageLength +
+                   sizeof (CommunicateHeader->HeaderGuid) +
+                   sizeof (CommunicateHeader->MessageLength);
+      CopyMem (CommBuffer, (VOID *)CommunicateHeader, BufferSize);
+      if (CommSize != NULL) {
+        *CommSize = 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;
+}
diff --git a/ArmPkg/ArmPkg.dsc b/ArmPkg/ArmPkg.dsc
index 6b938ce8b671..4939b3d59b7f 100644
--- a/ArmPkg/ArmPkg.dsc
+++ b/ArmPkg/ArmPkg.dsc
@@ -162,6 +162,8 @@ [Components.common]
   ArmPkg/Universal/Smbios/SmbiosMiscDxe/SmbiosMiscDxe.inf
   ArmPkg/Universal/Smbios/OemMiscLibNull/OemMiscLibNull.inf
 
+  ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.inf
+
 [Components.AARCH64]
   ArmPkg/Drivers/ArmPsciMpServicesDxe/ArmPsciMpServicesDxe.inf
   ArmPkg/Drivers/MmCommunicationDxe/MmCommunication.inf
diff --git a/ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.h b/ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.h
new file mode 100644
index 000000000000..a99baa2496a9
--- /dev/null
+++ b/ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.h
@@ -0,0 +1,76 @@
+/** @file -- MmCommunicationPei.h
+  Provides an interface to send MM request in PEI
+
+  Copyright (c) Microsoft Corporation.
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef MM_COMMUNICATION_PEI_H_
+#define MM_COMMUNICATION_PEI_H_
+
+#include <PiPei.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/ArmSmcLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PeimEntryPoint.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/HobLib.h>
+
+#include <Protocol/MmCommunication.h>
+
+#include <IndustryStandard/ArmStdSmc.h>
+
+#include <Ppi/MmCommunication.h>
+
+/**
+  Entry point of PEI MM Communication driver
+
+  @param  FileHandle   Handle of the file being invoked.
+                       Type EFI_PEI_FILE_HANDLE is defined in FfsFindNextFile().
+  @param  PeiServices  General purpose services available to every PEIM.
+
+  @retval EFI_SUCCESS  If the interface could be successfully installed
+  @retval Others       Returned from PeiServicesInstallPpi()
+**/
+EFI_STATUS
+EFIAPI
+MmCommunicationPeiInitialize (
+  IN       EFI_PEI_FILE_HANDLE  FileHandle,
+  IN CONST EFI_PEI_SERVICES     **PeiServices
+  );
+
+/**
+  MmCommunicationPeim
+  Communicates with a registered handler.
+  This function provides a service to send and receive messages from a registered UEFI service during PEI.
+
+  @param[in]      This            The EFI_PEI_MM_COMMUNICATION_PPI instance.
+  @param[in, out] CommBuffer      Pointer to the data buffer
+  @param[in, out] CommSize        The size of the data buffer being passed in. On exit, the
+                                  size of data being returned. Zero if the handler does not
+                                  wish to reply with any data.
+
+  @retval EFI_SUCCESS             The message was successfully posted.
+  @retval EFI_INVALID_PARAMETER   CommBuffer was NULL or *CommSize does not match
+                                  MessageLength + sizeof (EFI_MM_COMMUNICATE_HEADER).
+  @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
+MmCommunicationPeim (
+  IN CONST EFI_PEI_MM_COMMUNICATION_PPI  *This,
+  IN OUT VOID                            *CommBuffer,
+  IN OUT UINTN                           *CommSize
+  );
+
+#endif /* MM_COMMUNICATION_PEI_H_ */
diff --git a/ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.inf b/ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.inf
new file mode 100644
index 000000000000..f4e359dafd75
--- /dev/null
+++ b/ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.inf
@@ -0,0 +1,41 @@
+## @file -- MmCommunicationPei.inf
+#  PEI MM Communicate driver
+#
+#  Copyright (c) 2016 - 2021, Arm Limited. All rights reserved.<BR>
+#  Copyright (c) Microsoft Corporation.
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = MmCommunicationPei
+  FILE_GUID                      = 58FFB346-1B75-42C7-AD69-37C652423C1A
+  MODULE_TYPE                    = PEIM
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = MmCommunicationPeiInitialize
+
+[Sources]
+  MmCommunicationPei.c
+  MmCommunicationPei.h
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  ArmPkg/ArmPkg.dec
+
+[LibraryClasses]
+  DebugLib
+  ArmSmcLib
+  PeimEntryPoint
+  PeiServicesLib
+  HobLib
+
+[Pcd]
+  gArmTokenSpaceGuid.PcdMmBufferBase
+  gArmTokenSpaceGuid.PcdMmBufferSize
+
+[Ppis]
+  gEfiPeiMmCommunicationPpiGuid     ## PRODUCES
+
+[Depex]
+  TRUE
-- 
2.40.1.windows.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v1 2/2] MdeModulePkg: Variable: Introduce MM based variable read service in PEI
  2023-06-08 20:44 [PATCH v1 0/2] Support MM based variable services in PEI for ARM Kun Qin
  2023-06-08 20:44 ` [PATCH v1 1/2] ArmPkg: MmCommunicationPei: Introduce MM communicate in PEI Kun Qin
@ 2023-06-08 20:44 ` Kun Qin
  2023-06-25  2:23   ` 回复: [edk2-devel] " gaoliming
  1 sibling, 1 reply; 8+ messages in thread
From: Kun Qin @ 2023-06-08 20:44 UTC (permalink / raw)
  To: devel
  Cc: Hao A Wu, Liming Gao, Jian J Wang, Ronny Hansen,
	Shriram Masanamuthu Chinnathurai, Preshit Harlikar

From: Kun Qin <kuqin@microsoft.com>

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

This change introduced the Standalone MM based variable read capability
in PEI phase for applicable platforms (such as ARM platforms).

Similar to the x86 counterpart, MM communicate PPI is used to request
variable information from Standalone MM environment.

Cc: Hao A Wu <hao.a.wu@intel.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Jian J Wang <jian.j.wang@intel.com>

Co-authored-by: Ronny Hansen <hansen.ronny@microsoft.com>
Co-authored-by: Shriram Masanamuthu Chinnathurai <shriramma@microsoft.com>
Co-authored-by: Preshit Harlikar <pharlikar@microsoft.com>
Signed-off-by: Kun Qin <kuqin@microsoft.com>
---
 MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.c   | 381 ++++++++++++++++++++
 MdeModulePkg/MdeModulePkg.dsc                                   |   1 +
 MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.h   | 134 +++++++
 MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.inf |  43 +++
 4 files changed, 559 insertions(+)

diff --git a/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.c b/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.c
new file mode 100644
index 000000000000..4f937e22e89e
--- /dev/null
+++ b/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.c
@@ -0,0 +1,381 @@
+/** @file -- MmVariablePei.c
+  Provides interface for reading Secure System Variables during PEI.
+
+  Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) Microsoft Corporation.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "MmVariablePei.h"
+
+#define MM_VARIABLE_COMM_BUFFER_OFFSET  (SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE)
+
+//
+// Module globals
+//
+EFI_PEI_READ_ONLY_VARIABLE2_PPI  mPeiSecureVariableRead = {
+  PeiMmGetVariable,
+  PeiMmGetNextVariableName
+};
+
+EFI_PEI_PPI_DESCRIPTOR  mPeiMmVariablePpi = {
+  (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+  &gEfiPeiReadOnlyVariable2PpiGuid,
+  &mPeiSecureVariableRead
+};
+
+/**
+  Entry point of PEI Secure Variable read driver
+
+  @param  FileHandle   Handle of the file being invoked.
+                       Type EFI_PEI_FILE_HANDLE is defined in FfsFindNextFile().
+  @param  PeiServices  General purpose services available to every PEIM.
+
+  @retval EFI_SUCCESS  If the interface could be successfully installed
+  @retval Others       Returned from PeiServicesInstallPpi()
+**/
+EFI_STATUS
+EFIAPI
+PeiMmVariableInitialize (
+  IN       EFI_PEI_FILE_HANDLE  FileHandle,
+  IN CONST EFI_PEI_SERVICES     **PeiServices
+  )
+{
+  return PeiServicesInstallPpi (&mPeiMmVariablePpi);
+}
+
+/**
+  Helper function to populate MM communicate header and variable communicate header
+  and then communicate to PEI.
+
+  @param[in, out] CommunicateBuffer       Size of the variable name.
+  @param[in]      CommunicateBufferSize   The entire buffer size to be sent to MM.
+  @param[in]      Function                The MM variable function value.
+
+  @retval EFI_INVALID_PARAMETER      Invalid parameter.
+  @retval EFI_SUCCESS                Find the specified variable.
+  @retval Others                     Errors returned by MM communicate or variable service.
+
+**/
+EFI_STATUS
+PopulateHeaderAndCommunicate (
+  IN OUT  UINT8  *CommunicateBuffer,
+  IN UINTN       CommunicateBufferSize,
+  IN UINTN       Function
+  )
+{
+  EFI_STATUS                       Status;
+  EFI_PEI_MM_COMMUNICATION_PPI     *MmCommunicationPpi;
+  EFI_MM_COMMUNICATE_HEADER        *MmCommunicateHeader;
+  SMM_VARIABLE_COMMUNICATE_HEADER  *MmVarCommsHeader;
+
+  // Minimal sanity check
+  if ((CommunicateBuffer == NULL) ||
+      (CommunicateBufferSize < MM_VARIABLE_COMM_BUFFER_OFFSET))
+  {
+    Status = EFI_INVALID_PARAMETER;
+    DEBUG ((DEBUG_ERROR, "%a: Invalid incoming parameters: %p and 0x%x\n", __func__, CommunicateBuffer, CommunicateBufferSize));
+    goto Exit;
+  }
+
+  if ((Function != SMM_VARIABLE_FUNCTION_GET_NEXT_VARIABLE_NAME) &&
+      (Function != SMM_VARIABLE_FUNCTION_GET_VARIABLE))
+  {
+    Status = EFI_INVALID_PARAMETER;
+    DEBUG ((DEBUG_ERROR, "%a: Invalid function value: 0x%x\n", __func__, Function));
+    goto Exit;
+  }
+
+  Status = PeiServicesLocatePpi (&gEfiPeiMmCommunicationPpiGuid, 0, NULL, (VOID **)&MmCommunicationPpi);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a: Failed to locate PEI MM Communication PPI: %r\n", __func__, Status));
+    goto Exit;
+  }
+
+  // Zero the entire Communication Buffer Header
+  MmCommunicateHeader = (EFI_MM_COMMUNICATE_HEADER *)CommunicateBuffer;
+
+  ZeroMem (MmCommunicateHeader, SMM_COMMUNICATE_HEADER_SIZE);
+
+  // Use gEfiSmmVariableProtocolGuid to request the MM variable service in Standalone MM
+  CopyMem ((VOID *)&MmCommunicateHeader->HeaderGuid, &gEfiSmmVariableProtocolGuid, sizeof (GUID));
+
+  // Program the MM header size
+  MmCommunicateHeader->MessageLength = CommunicateBufferSize - SMM_COMMUNICATE_HEADER_SIZE;
+
+  MmVarCommsHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *)(CommunicateBuffer + SMM_COMMUNICATE_HEADER_SIZE);
+
+  // We are only supporting GetVariable and GetNextVariableName
+  MmVarCommsHeader->Function = Function;
+
+  // Send the MM request using MmCommunicationPei
+  Status = MmCommunicationPpi->Communicate (MmCommunicationPpi, CommunicateBuffer, &CommunicateBufferSize);
+  if (EFI_ERROR (Status)) {
+    // Received an error from MM interface.
+    DEBUG ((DEBUG_ERROR, "%a - MM Interface Error: %r\n", __func__, Status));
+    goto Exit;
+  }
+
+  // MM request was successfully handled by the framework.
+  // Set status to the Variable Service Status Code
+  Status = MmVarCommsHeader->ReturnStatus;
+  if (EFI_ERROR (Status)) {
+    // We received an error from Variable Service.
+    // We cant do anymore so return Status
+    if (Status != EFI_BUFFER_TOO_SMALL) {
+      DEBUG ((DEBUG_ERROR, "%a - Variable Service Error: %r\n", __func__, Status));
+    }
+
+    goto Exit;
+  }
+
+Exit:
+  return Status;
+}
+
+/**
+  This service retrieves a variable's value using its name and GUID.
+
+  This function is using the Secure Variable Store. If the Data
+  buffer is too small to hold the contents of the variable, the error
+  EFI_BUFFER_TOO_SMALL is returned and DataSize is set to the required buffer
+  size to obtain the data.
+
+  @param  This                  A pointer to this instance of the EFI_PEI_READ_ONLY_VARIABLE2_PPI.
+  @param  VariableName          A pointer to a null-terminated string that is the variable's name.
+  @param  VariableGuid          A pointer to an EFI_GUID that is the variable's GUID. The combination of
+                                VariableGuid and VariableName must be unique.
+  @param  Attributes            If non-NULL, on return, points to the variable's attributes.
+  @param  DataSize              On entry, points to the size in bytes of the Data buffer.
+                                On return, points to the size of the data returned in Data.
+  @param  Data                  Points to the buffer which will hold the returned variable value.
+                                May be NULL with a zero DataSize in order to determine the size of the buffer needed.
+
+  @retval EFI_SUCCESS           The variable was read successfully.
+  @retval EFI_NOT_FOUND         The variable was not found.
+  @retval EFI_BUFFER_TOO_SMALL  The DataSize is too small for the resulting data.
+                                DataSize is updated with the size required for
+                                the specified variable.
+  @retval EFI_INVALID_PARAMETER VariableName, VariableGuid, DataSize or Data is NULL.
+  @retval EFI_DEVICE_ERROR      The variable could not be retrieved because of a device error.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiMmGetVariable (
+  IN CONST  EFI_PEI_READ_ONLY_VARIABLE2_PPI *This,
+  IN CONST  CHAR16 *VariableName,
+  IN CONST  EFI_GUID *VariableGuid,
+  OUT       UINT32 *Attributes, OPTIONAL
+  IN OUT    UINTN                            *DataSize,
+  OUT       VOID                             *Data OPTIONAL
+  )
+{
+  EFI_STATUS                                Status;
+  UINTN                                     MessageSize;
+  SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE  *MmVarAccessHeader;
+  UINT8                                     *MmCommunicateBuffer;
+  UINTN                                     RequiredPages;
+
+  // Check input parameters
+  if ((VariableName == NULL) || (VariableGuid == NULL) || (DataSize == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (VariableName[0] == 0) {
+    return EFI_NOT_FOUND;
+  }
+
+  if ((*DataSize > 0) && (Data == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // Allocate required pages to send MM request
+  MessageSize = MM_VARIABLE_COMM_BUFFER_OFFSET +
+                OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) +
+                StrSize (VariableName) + *DataSize;
+
+  RequiredPages       = EFI_SIZE_TO_PAGES (MessageSize);
+  MmCommunicateBuffer = (UINT8 *)AllocatePages (RequiredPages);
+
+  if (MmCommunicateBuffer == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    DEBUG ((DEBUG_ERROR, "%a: Failed to allocate memory: %r\n", __func__, Status));
+    return Status;
+  }
+
+  // Zero the entire Communication Buffer
+  ZeroMem (MmCommunicateBuffer, (RequiredPages * EFI_PAGE_SIZE));
+
+  //
+  // Program all payload structure contents
+  //
+  MmVarAccessHeader = (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *)(MmCommunicateBuffer + MM_VARIABLE_COMM_BUFFER_OFFSET);
+
+  // Variable GUID
+  CopyMem ((VOID *)&MmVarAccessHeader->Guid, VariableGuid, sizeof (GUID));
+
+  // Program the max amount of data we accept.
+  MmVarAccessHeader->DataSize = *DataSize;
+
+  // Get size of the variable name
+  MmVarAccessHeader->NameSize = StrSize (VariableName);
+
+  // Populate incoming variable name
+  CopyMem ((VOID *)&MmVarAccessHeader->Name, VariableName, MmVarAccessHeader->NameSize);
+
+  Status = PopulateHeaderAndCommunicate (MmCommunicateBuffer, MessageSize, SMM_VARIABLE_FUNCTION_GET_VARIABLE);
+  if (EFI_ERROR (Status)) {
+    // We received an error from either communicate or Variable Service.
+    if (Status != EFI_BUFFER_TOO_SMALL) {
+      DEBUG ((DEBUG_ERROR, "%a - Communite to MM for variable service errored: %r\n", __func__, Status));
+    }
+
+    goto Exit;
+  }
+
+  Status = EFI_SUCCESS;
+
+  // User provided buffer is too small
+  if (*DataSize < MmVarAccessHeader->DataSize) {
+    Status = EFI_BUFFER_TOO_SMALL;
+  }
+
+Exit:
+  // Check if we need to set Attributes
+  if (Attributes != NULL) {
+    *Attributes = MmVarAccessHeader->Attributes;
+  }
+
+  *DataSize = MmVarAccessHeader->DataSize;
+
+  if (Status == EFI_SUCCESS) {
+    CopyMem ((VOID *)Data, (UINT8 *)MmVarAccessHeader->Name + MmVarAccessHeader->NameSize, *DataSize);
+  }
+
+  // Free the Communication Buffer
+  if (MmCommunicateBuffer != NULL) {
+    FreePages (MmCommunicateBuffer, RequiredPages);
+  }
+
+  return Status;
+}
+
+/**
+  Return the next variable name and GUID.
+
+  This function is called multiple times to retrieve the VariableName
+  and VariableGuid of all variables currently available in the system.
+  On each call, the previous results are passed into the interface,
+  and, on return, the interface returns the data for the next
+  interface. When the entire variable list has been returned,
+  EFI_NOT_FOUND is returned.
+
+  @param  This              A pointer to this instance of the EFI_PEI_READ_ONLY_VARIABLE2_PPI.
+
+  @param  VariableNameSize  On entry, points to the size of the buffer pointed to by VariableName.
+                            On return, the size of the variable name buffer.
+  @param  VariableName      On entry, a pointer to a null-terminated string that is the variable's name.
+                            On return, points to the next variable's null-terminated name string.
+
+  @param  VariableGuid      On entry, a pointer to an EFI_GUID that is the variable's GUID.
+                            On return, a pointer to the next variable's GUID.
+
+  @retval EFI_SUCCESS           The variable was read successfully.
+  @retval EFI_NOT_FOUND         The variable could not be found.
+  @retval EFI_BUFFER_TOO_SMALL  The VariableNameSize is too small for the resulting
+                                data. VariableNameSize is updated with the size
+                                required for the specified variable.
+  @retval EFI_INVALID_PARAMETER VariableName, VariableGuid or
+                                VariableNameSize is NULL.
+  @retval EFI_DEVICE_ERROR      The variable could not be retrieved because of a device error.
+**/
+EFI_STATUS
+EFIAPI
+PeiMmGetNextVariableName (
+  IN CONST  EFI_PEI_READ_ONLY_VARIABLE2_PPI  *This,
+  IN OUT UINTN                               *VariableNameSize,
+  IN OUT CHAR16                              *VariableName,
+  IN OUT EFI_GUID                            *VariableGuid
+  )
+{
+  EFI_STATUS                                       Status;
+  UINTN                                            MessageSize;
+  UINT8                                            *MmCommunicateBuffer;
+  SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME  *MmVarGetNextVarHeader;
+  UINTN                                            RequiredPages;
+
+  // Check input parameters
+  if ((VariableName == NULL) ||
+      (VariableGuid == NULL) ||
+      (VariableNameSize == NULL) ||
+      (*VariableNameSize == 0))
+  {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // Allocate required pages to send MM request
+  MessageSize = MM_VARIABLE_COMM_BUFFER_OFFSET +
+                OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) +
+                StrSize (VariableName) + *VariableNameSize;
+
+  RequiredPages       = EFI_SIZE_TO_PAGES (MessageSize);
+  MmCommunicateBuffer = (UINT8 *)AllocatePages (RequiredPages);
+
+  if (MmCommunicateBuffer == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    DEBUG ((DEBUG_ERROR, "%a: Failed to allocate memory: %r\n", __func__, Status));
+    return Status;
+  }
+
+  // Zero the entire Communication Buffer
+  ZeroMem (MmCommunicateBuffer, (RequiredPages * EFI_PAGE_SIZE));
+
+  //
+  // Program all payload structure contents
+  //
+  MmVarGetNextVarHeader = (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME *)(MmCommunicateBuffer + MM_VARIABLE_COMM_BUFFER_OFFSET);
+
+  // Variable GUID
+  CopyMem ((VOID *)&MmVarGetNextVarHeader->Guid, VariableGuid, sizeof (GUID));
+
+  // Program the maximal length of name we can accept.
+  MmVarGetNextVarHeader->NameSize = *VariableNameSize;
+
+  // Populate incoming variable name
+  CopyMem ((VOID *)&MmVarGetNextVarHeader->Name, VariableName, MmVarGetNextVarHeader->NameSize);
+
+  // Send the MM request using MmCommunicationPei
+  Status = PopulateHeaderAndCommunicate (MmCommunicateBuffer, MessageSize, SMM_VARIABLE_FUNCTION_GET_NEXT_VARIABLE_NAME);
+  if (EFI_ERROR (Status)) {
+    // We received an error from either communicate or Variable Service.
+    if (Status != EFI_BUFFER_TOO_SMALL) {
+      DEBUG ((DEBUG_ERROR, "%a - Communite to MM for variable service errored: %r\n", __func__, Status));
+    }
+
+    goto Exit;
+  }
+
+  Status = EFI_SUCCESS;
+
+  // User provided buffer is too small
+  if (*VariableNameSize < MmVarGetNextVarHeader->NameSize) {
+    Status = EFI_BUFFER_TOO_SMALL;
+  }
+
+Exit:
+  // Update the name size to be returned
+  *VariableNameSize = MmVarGetNextVarHeader->NameSize;
+
+  if (Status == EFI_SUCCESS) {
+    CopyMem ((VOID *)VariableName, (UINT8 *)MmVarGetNextVarHeader->Name, *VariableNameSize);
+    CopyMem ((VOID *)VariableGuid, (UINT8 *)&(MmVarGetNextVarHeader->Guid), sizeof (EFI_GUID));
+  }
+
+  // Free the Communication Buffer
+  if (MmCommunicateBuffer != NULL) {
+    FreePages (MmCommunicateBuffer, RequiredPages);
+  }
+
+  return Status;
+}
diff --git a/MdeModulePkg/MdeModulePkg.dsc b/MdeModulePkg/MdeModulePkg.dsc
index 5b1f50e9c084..1aedfe280ae1 100644
--- a/MdeModulePkg/MdeModulePkg.dsc
+++ b/MdeModulePkg/MdeModulePkg.dsc
@@ -400,6 +400,7 @@ [Components]
   MdeModulePkg/Application/VariableInfo/VariableInfo.inf
   MdeModulePkg/Universal/FaultTolerantWritePei/FaultTolerantWritePei.inf
   MdeModulePkg/Universal/Variable/Pei/VariablePei.inf
+  MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.inf
   MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
   MdeModulePkg/Universal/TimestampDxe/TimestampDxe.inf
   MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf
diff --git a/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.h b/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.h
new file mode 100644
index 000000000000..0feed8cd1cb6
--- /dev/null
+++ b/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.h
@@ -0,0 +1,134 @@
+/** @file -- MmVariablePei.h
+  Provides interface for reading Secure System Variables during PEI.
+
+  Copyright (c) Microsoft Corporation.
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef PEI_MM_VARIABLE_LIB_H_
+#define PEI_MM_VARIABLE_LIB_H_
+
+#include <PiPei.h>
+#include <Uefi/UefiSpec.h>
+
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PeimEntryPoint.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/HobLib.h>
+
+#include <Guid/SmmVariableCommon.h>
+
+#include <Ppi/ReadOnlyVariable2.h>
+#include <Ppi/MmCommunication.h>
+
+#include <Protocol/SmmVariable.h>
+#include <Protocol/MmCommunication.h>
+
+/**
+  Entry point of PEI Secure Variable read driver
+
+  @param  FileHandle   Handle of the file being invoked.
+                       Type EFI_PEI_FILE_HANDLE is defined in FfsFindNextFile().
+  @param  PeiServices  General purpose services available to every PEIM.
+
+  @retval EFI_SUCCESS  If the interface could be successfully installed
+  @retval Others       Returned from PeiServicesInstallPpi()
+**/
+EFI_STATUS
+EFIAPI
+PeiMmVariableInitialize (
+  IN       EFI_PEI_FILE_HANDLE  FileHandle,
+  IN CONST EFI_PEI_SERVICES     **PeiServices
+  );
+
+/**
+
+  This function enables the read of Secure Variables during PEI.
+
+  This function is using the Secure Variable Store.If the Data
+  buffer is too small to hold the contents of the variable, the error
+  EFI_BUFFER_TOO_SMALL is returned and DataSize is set to the required buffer
+  size to obtain the data.
+
+  The function performs the following:
+
+  1) Creates an MM request
+  2) Fills out the following data structures for the Secure Variable Service
+      SMM_VARIABLE_COMMUNICATE_HEADER/SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE
+  3) Adds the MM data structures to the MM request.
+  4) Sends the MM request to EL3 using MmCommunicationPeiLib.
+  5) The MM request is sent to S-EL0.
+  6) The MM request is then handled by the registered handler with GUID: gEfiSmmVariableProtocolGuid
+
+  @param  This                  A pointer to this instance of the EFI_PEI_READ_ONLY_VARIABLE2_PPI.
+  @param  VariableName          A pointer to a null-terminated string that is the variable's name.
+  @param  VariableGuid          A pointer to an EFI_GUID that is the variable's GUID. The combination of
+                                VariableGuid and VariableName must be unique.
+  @param  Attributes            If non-NULL, on return, points to the variable's attributes.
+  @param  DataSize              On entry, points to the size in bytes of the Data buffer.
+                                On return, points to the size of the data returned in Data.
+  @param  Data                  Points to the buffer which will hold the returned variable value.
+                                May be NULL with a zero DataSize in order to determine the size of the buffer needed.
+
+  @retval EFI_SUCCESS           The variable was read successfully.
+  @retval EFI_NOT_FOUND         The variable was not found.
+  @retval EFI_BUFFER_TOO_SMALL  The DataSize is too small for the resulting data.
+                                DataSize is updated with the size required for
+                                the specified variable.
+  @retval EFI_INVALID_PARAMETER VariableName, VariableGuid, DataSize or Data is NULL.
+  @retval EFI_DEVICE_ERROR      The variable could not be retrieved because of a device error.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiMmGetVariable (
+  IN CONST  EFI_PEI_READ_ONLY_VARIABLE2_PPI  *This,
+  IN CONST  CHAR16                           *VariableName,
+  IN CONST  EFI_GUID                         *VariableGuid,
+  OUT       UINT32                           *Attributes,
+  IN OUT    UINTN                            *DataSize,
+  OUT       VOID                             *Data OPTIONAL
+  );
+
+/**
+  Return the next variable name and GUID.
+
+  This function is called multiple times to retrieve the VariableName
+  and VariableGuid of all variables currently available in the system.
+  On each call, the previous results are passed into the interface,
+  and, on return, the interface returns the data for the next
+  interface. When the entire variable list has been returned,
+  EFI_NOT_FOUND is returned.
+
+  @param  This              A pointer to this instance of the EFI_PEI_READ_ONLY_VARIABLE2_PPI.
+
+  @param  VariableNameSize  On entry, points to the size of the buffer pointed to by VariableName.
+                            On return, the size of the variable name buffer.
+  @param  VariableName      On entry, a pointer to a null-terminated string that is the variable's name.
+                            On return, points to the next variable's null-terminated name string.
+
+  @param  VariableGuid      On entry, a pointer to an EFI_GUID that is the variable's GUID.
+                            On return, a pointer to the next variable's GUID.
+
+  @retval EFI_SUCCESS           The variable was read successfully.
+  @retval EFI_NOT_FOUND         The variable could not be found.
+  @retval EFI_BUFFER_TOO_SMALL  The VariableNameSize is too small for the resulting
+                                data. VariableNameSize is updated with the size
+                                required for the specified variable.
+  @retval EFI_INVALID_PARAMETER VariableName, VariableGuid or
+                                VariableNameSize is NULL.
+  @retval EFI_DEVICE_ERROR      The variable could not be retrieved because of a device error.
+**/
+EFI_STATUS
+EFIAPI
+PeiMmGetNextVariableName (
+  IN CONST  EFI_PEI_READ_ONLY_VARIABLE2_PPI  *This,
+  IN OUT UINTN                               *VariableNameSize,
+  IN OUT CHAR16                              *VariableName,
+  IN OUT EFI_GUID                            *VariableGuid
+  );
+
+#endif /* PEI_MM_VARIABLE_LIB_H_ */
diff --git a/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.inf b/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.inf
new file mode 100644
index 000000000000..d122703e9b5d
--- /dev/null
+++ b/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.inf
@@ -0,0 +1,43 @@
+## @file -- MmVariablePei.inf
+# Provides interface for reading Secure System Variables during PEI.
+#
+# Copyright (c) Microsoft Corporation.
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = MmVariablePei
+  FILE_GUID                      = CD660A87-454B-4346-A35C-3D89BF8ECFAF
+  MODULE_TYPE                    = PEIM
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = PeiMmVariableInitialize
+
+[Sources]
+  MmVariablePei.c
+  MmVariablePei.h
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+  PcdLib
+  PeiServicesLib
+  PeimEntryPoint
+  MemoryAllocationLib
+  HobLib
+
+[Pcd]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize
+
+[Protocols]
+  gEfiSmmVariableProtocolGuid             ## CONSUMES
+
+[Ppis]
+  gEfiPeiReadOnlyVariable2PpiGuid         ## PRODUCES
+  gEfiPeiMmCommunicationPpiGuid           ## CONSUMES
+
+[Depex]
+  gEfiPeiMmCommunicationPpiGuid
-- 
2.40.1.windows.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH v1 1/2] ArmPkg: MmCommunicationPei: Introduce MM communicate in PEI
  2023-06-08 20:44 ` [PATCH v1 1/2] ArmPkg: MmCommunicationPei: Introduce MM communicate in PEI Kun Qin
@ 2023-06-22 19:17   ` Sami Mujawar
  2023-06-26 20:07     ` Kun Qin
  0 siblings, 1 reply; 8+ messages in thread
From: Sami Mujawar @ 2023-06-22 19:17 UTC (permalink / raw)
  To: Kun Qin, devel
  Cc: Leif Lindholm, Ard Biesheuvel, Ronny Hansen,
	Shriram Masanamuthu Chinnathurai, Preshit Harlikar, nd@arm.com

[-- Attachment #1: Type: text/plain, Size: 14979 bytes --]

Hi Kun,

Thank you for this patch.

Please find my response inline marked [SAMI].

Regards,

Sami Mujawar

On 08/06/2023 09:44 pm, Kun Qin wrote:
> From: Kun Qin<kuqin@microsoft.com>
>
> REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4464
>
> This change introduced the MM communicate support in PEI phase for ARM
> based platforms. Similar to the DXE counterpart, `PcdMmBufferBase` is
> used as communicate buffer and SMC will be invoked to communicate to
> TrustZone when MMI is requested.
>
> Cc: Leif Lindholm<quic_llindhol@quicinc.com>
> Cc: Ard Biesheuvel<ardb+tianocore@kernel.org>
> Cc: Sami Mujawar<sami.mujawar@arm.com>
>
> Co-authored-by: Ronny Hansen<hansen.ronny@microsoft.com>
> Co-authored-by: Shriram Masanamuthu Chinnathurai<shriramma@microsoft.com>
> Co-authored-by: Preshit Harlikar<pharlikar@microsoft.com>
> Signed-off-by: Kun Qin<kuqin@microsoft.com>
> ---
>   ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.c   | 178 ++++++++++++++++++++
>   ArmPkg/ArmPkg.dsc                                        |   2 +
>   ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.h   |  76 +++++++++
>   ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.inf |  41 +++++
>   4 files changed, 297 insertions(+)
>
> diff --git a/ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.c b/ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.c
> new file mode 100644
> index 000000000000..0f1f763a347d
> --- /dev/null
> +++ b/ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.c
> @@ -0,0 +1,178 @@
> +/** @file -- MmCommunicationPei.c
>
> +  Provides an interface to send MM request in PEI
>
> +
>
> +  Copyright (c) 2016-2021, Arm Limited. All rights reserved.<BR>
>
> +  Copyright (c) Microsoft Corporation.
>
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +**/
>
> +
>
> +#include "MmCommunicationPei.h"
>
> +
>
> +//
>
> +// Module globals
>
> +//
>
> +EFI_PEI_MM_COMMUNICATION_PPI  mPeiMmCommunication = {
>
> +  MmCommunicationPeim
>
> +};
>
> +
>
> +EFI_PEI_PPI_DESCRIPTOR  mPeiMmCommunicationPpi = {
>
> +  (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
>
> +  &gEfiPeiMmCommunicationPpiGuid,
>
> +  &mPeiMmCommunication
>
> +};
>
> +
>
> +/**
>
> +  Entry point of PEI MM Communication driver
>
> +
>
> +  @param  FileHandle   Handle of the file being invoked.
>
> +                       Type EFI_PEI_FILE_HANDLE is defined in FfsFindNextFile().
>
> +  @param  PeiServices  General purpose services available to every PEIM.
>
> +
>
> +  @retval EFI_SUCCESS  If the interface could be successfully installed
>
> +  @retval Others       Returned from PeiServicesInstallPpi()
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +MmCommunicationPeiInitialize (
>
> +  IN       EFI_PEI_FILE_HANDLE  FileHandle,
>
> +  IN CONST EFI_PEI_SERVICES     **PeiServices
>
> +  )
>
> +{
>
> +  return PeiServicesInstallPpi (&mPeiMmCommunicationPpi);
>
> +}
>
> +
>
> +/**
>
> +  MmCommunicationPeim
>
> +  Communicates with a registered handler.
>
> +  This function provides a service to send and receive messages from a registered UEFI service during PEI.
>
> +
>
> +  @param[in]      This            The EFI_PEI_MM_COMMUNICATION_PPI instance.
>
> +  @param[in, out] CommBuffer      Pointer to the data buffer
>
> +  @param[in, out] CommSize        The size of the data buffer being passed in. On exit, the
>
> +                                  size of data being returned. Zero if the handler does not
>
> +                                  wish to reply with any data.
>
> +
>
> +  @retval EFI_SUCCESS             The message was successfully posted.
>
> +  @retval EFI_INVALID_PARAMETER   CommBuffer was NULL or *CommSize does not match
>
> +                                  MessageLength + sizeof (EFI_MM_COMMUNICATE_HEADER).
>
> +  @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
>
> +MmCommunicationPeim (
>
> +  IN CONST EFI_PEI_MM_COMMUNICATION_PPI  *This,
>
> +  IN OUT VOID                            *CommBuffer,
>
> +  IN OUT UINTN                           *CommSize
>
> +  )
>
> +{
>
> +  EFI_MM_COMMUNICATE_HEADER  *CommunicateHeader;
>
> +  ARM_SMC_ARGS               CommunicateSmcArgs;
>
> +  EFI_STATUS                 Status;
>
> +  UINTN                      BufferSize;
>
> +
>
> +  Status     = EFI_ACCESS_DENIED;
>
> +  BufferSize = 0;
[SAMI] Minor optimisation: The above initialisations are probably not 
required.
>
> +
>
> +  ZeroMem (&CommunicateSmcArgs, sizeof (ARM_SMC_ARGS));
>
> +
>
> +  // Check that our static buffer is looking good.
>
> +  // We are using PcdMmBufferBase to transfer variable data.
>
> +  // We are not using the full size of the buffer since there is a cost
>
> +  // of copying data between Normal and Secure World.
>
> +  ASSERT (PcdGet64 (PcdMmBufferSize) > 0 && PcdGet64 (PcdMmBufferBase) != 0);
>
> +
>
> +  //
>
> +  // Check parameters
>
> +  //
>
> +  if (CommBuffer == NULL) {
>
> +    return EFI_INVALID_PARAMETER;
>
> +  }
[SAMI] Should there be a check for CommSize as well? Otherwise the code 
will crash a few lines below when doing CopyMem().
> +
>
> +  // If the length of the CommBuffer is 0 then return the expected length.
>
> +  // 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 != NULL) && \
>
> +      ((*CommSize == 0) || (*CommSize > (UINTN)PcdGet64 (PcdMmBufferSize))))
>
> +  {
>
> +    *CommSize = (UINTN)PcdGet64 (PcdMmBufferSize);
>
> +    return EFI_BAD_BUFFER_SIZE;
>
> +  }
>
> +
>
> +  CommunicateHeader = (EFI_MM_COMMUNICATE_HEADER *)(UINTN)(PcdGet64 (PcdMmBufferBase));
>
> +
>
> +  CopyMem ((VOID *)CommunicateHeader, CommBuffer, *CommSize);
[SAMI] If CommSize is NULL, the above the above line will result in a 
crash, right?
>
> +
>
> +  // 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 CommSize is supplied it must match MessageLength + sizeof (EFI_MM_COMMUNICATE_HEADER);
>
> +  //
>
> +  if ((CommSize != NULL) && (*CommSize != BufferSize)) {
>
> +    return EFI_INVALID_PARAMETER;
>
> +  }
[SAMI] It may be better to do this check earlier in the code by casting 
CommBuffer to EFI_MM_COMMUNICATE_HEADER * and calculating the 
BufferSize. That way the CopyMem() above can be avoided if the above 
test fails.
>
> +
>
> +  // SMC Function ID
>
> +  CommunicateSmcArgs.Arg0 = ARM_SMC_ID_MM_COMMUNICATE_AARCH64;
>
> +
>
> +  // Cookie
>
> +  CommunicateSmcArgs.Arg1 = 0;
>
> +
>
> +  // comm_buffer_address (64-bit physical address)
>
> +  CommunicateSmcArgs.Arg2 = (UINTN)CommunicateHeader;
>
> +
>
> +  // 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:
>
> +      // On successful return, the size of data being returned is inferred from
>
> +      // MessageLength + Header.
>
> +      BufferSize = CommunicateHeader->MessageLength +
>
> +                   sizeof (CommunicateHeader->HeaderGuid) +
>
> +                   sizeof (CommunicateHeader->MessageLength);
>
> +      CopyMem (CommBuffer, (VOID *)CommunicateHeader, BufferSize);

[SAMI] Can there be a case where the returned MessageLength results in 
the CommBuffer size being smaller, i.e. BufferSize returned > *CommSize ?

I expect  ARM_SMC_MM_RET_NO_MEMORY to have been returned in the first 
place, but it may be worth adding a check to avoid potential issues. 
What do you think?

>
> +      if (CommSize != NULL) {
>
> +        *CommSize = 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;
>
> +}
>
> diff --git a/ArmPkg/ArmPkg.dsc b/ArmPkg/ArmPkg.dsc
> index 6b938ce8b671..4939b3d59b7f 100644
> --- a/ArmPkg/ArmPkg.dsc
> +++ b/ArmPkg/ArmPkg.dsc
> @@ -162,6 +162,8 @@ [Components.common]
>     ArmPkg/Universal/Smbios/SmbiosMiscDxe/SmbiosMiscDxe.inf
>
>     ArmPkg/Universal/Smbios/OemMiscLibNull/OemMiscLibNull.inf
>
>   
>
> +  ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.inf
>
> +
>
>   [Components.AARCH64]
>
>     ArmPkg/Drivers/ArmPsciMpServicesDxe/ArmPsciMpServicesDxe.inf
>
>     ArmPkg/Drivers/MmCommunicationDxe/MmCommunication.inf
>
> diff --git a/ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.h b/ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.h
> new file mode 100644
> index 000000000000..a99baa2496a9
> --- /dev/null
> +++ b/ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.h
> @@ -0,0 +1,76 @@
> +/** @file -- MmCommunicationPei.h
>
> +  Provides an interface to send MM request in PEI
>
> +
>
> +  Copyright (c) Microsoft Corporation.
>
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +**/
>
> +
>
> +#ifndef MM_COMMUNICATION_PEI_H_
>
> +#define MM_COMMUNICATION_PEI_H_
>
> +
>
> +#include <PiPei.h>
>
> +
>
> +#include <Library/BaseLib.h>
>
> +#include <Library/BaseMemoryLib.h>
>
> +#include <Library/ArmSmcLib.h>
>
> +#include <Library/DebugLib.h>
>
> +#include <Library/PcdLib.h>
>
> +#include <Library/PeimEntryPoint.h>
>
> +#include <Library/PeiServicesLib.h>
>
> +#include <Library/HobLib.h>
>
> +
>
> +#include <Protocol/MmCommunication.h>
>
> +
>
> +#include <IndustryStandard/ArmStdSmc.h>
>
> +
>
> +#include <Ppi/MmCommunication.h>
>
> +
>
> +/**
>
> +  Entry point of PEI MM Communication driver
>
> +
>
> +  @param  FileHandle   Handle of the file being invoked.
>
> +                       Type EFI_PEI_FILE_HANDLE is defined in FfsFindNextFile().
>
> +  @param  PeiServices  General purpose services available to every PEIM.
>
> +
>
> +  @retval EFI_SUCCESS  If the interface could be successfully installed
>
> +  @retval Others       Returned from PeiServicesInstallPpi()
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +MmCommunicationPeiInitialize (
>
> +  IN       EFI_PEI_FILE_HANDLE  FileHandle,
>
> +  IN CONST EFI_PEI_SERVICES     **PeiServices
>
> +  );
>
> +
>
> +/**
>
> +  MmCommunicationPeim
>
> +  Communicates with a registered handler.
>
> +  This function provides a service to send and receive messages from a registered UEFI service during PEI.
>
> +
>
> +  @param[in]      This            The EFI_PEI_MM_COMMUNICATION_PPI instance.
>
> +  @param[in, out] CommBuffer      Pointer to the data buffer
>
> +  @param[in, out] CommSize        The size of the data buffer being passed in. On exit, the
>
> +                                  size of data being returned. Zero if the handler does not
>
> +                                  wish to reply with any data.
>
> +
>
> +  @retval EFI_SUCCESS             The message was successfully posted.
>
> +  @retval EFI_INVALID_PARAMETER   CommBuffer was NULL or *CommSize does not match
>
> +                                  MessageLength + sizeof (EFI_MM_COMMUNICATE_HEADER).
>
> +  @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
>
> +MmCommunicationPeim (
>
> +  IN CONST EFI_PEI_MM_COMMUNICATION_PPI  *This,
>
> +  IN OUT VOID                            *CommBuffer,
>
> +  IN OUT UINTN                           *CommSize
>
> +  );
>
> +
>
> +#endif /* MM_COMMUNICATION_PEI_H_ */
>
> diff --git a/ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.inf b/ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.inf
> new file mode 100644
> index 000000000000..f4e359dafd75
> --- /dev/null
> +++ b/ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.inf
> @@ -0,0 +1,41 @@
> +## @file -- MmCommunicationPei.inf
>
> +#  PEI MM Communicate driver
>
> +#
>
> +#  Copyright (c) 2016 - 2021, Arm Limited. All rights reserved.<BR>
>
> +#  Copyright (c) Microsoft Corporation.
>
> +#  SPDX-License-Identifier: BSD-2-Clause-Patent
>
> +##
>
> +
>
> +[Defines]
>
> +  INF_VERSION                    = 0x00010005
[SAMI] The version should be |0x0001001B. See 
https://github.com/tianocore-docs/edk2-InfSpecification/blob/master/3_edk_ii_inf_file_format/34_%5Bdefines%5D_section.md
|
>
> +  BASE_NAME                      = MmCommunicationPei
>
> +  FILE_GUID                      = 58FFB346-1B75-42C7-AD69-37C652423C1A
>
> +  MODULE_TYPE                    = PEIM
>
> +  VERSION_STRING                 = 1.0
>
> +  ENTRY_POINT                    = MmCommunicationPeiInitialize
>
> +
>
> +[Sources]
>
> +  MmCommunicationPei.c
>
> +  MmCommunicationPei.h
>
> +
>
> +[Packages]
>
> +  MdePkg/MdePkg.dec
>
> +  MdeModulePkg/MdeModulePkg.dec
>
> +  ArmPkg/ArmPkg.dec
>
> +
>
> +[LibraryClasses]
>
> +  DebugLib
>
> +  ArmSmcLib
>
> +  PeimEntryPoint
>
> +  PeiServicesLib
>
> +  HobLib
>
> +
>
> +[Pcd]
>
> +  gArmTokenSpaceGuid.PcdMmBufferBase
>
> +  gArmTokenSpaceGuid.PcdMmBufferSize
>
> +
>
> +[Ppis]
>
> +  gEfiPeiMmCommunicationPpiGuid     ## PRODUCES
>
> +
>
> +[Depex]
>
> +  TRUE
>

[-- Attachment #2: Type: text/html, Size: 16433 bytes --]

^ permalink raw reply	[flat|nested] 8+ messages in thread

* 回复: [edk2-devel] [PATCH v1 2/2] MdeModulePkg: Variable: Introduce MM based variable read service in PEI
  2023-06-08 20:44 ` [PATCH v1 2/2] MdeModulePkg: Variable: Introduce MM based variable read service " Kun Qin
@ 2023-06-25  2:23   ` gaoliming
  2023-06-26 20:10     ` Kun Qin
  0 siblings, 1 reply; 8+ messages in thread
From: gaoliming @ 2023-06-25  2:23 UTC (permalink / raw)
  To: devel, kuqin12
  Cc: 'Hao A Wu', 'Jian J Wang', 'Ronny Hansen',
	'Shriram Masanamuthu Chinnathurai',
	'Preshit Harlikar'

Kun:
  Seemly, PcdMaxVariableSize is not used by this module. It can be removed. 

  And, has its functionality been verified in the real platform?

Thanks
Liming
> -----邮件原件-----
> 发件人: devel@edk2.groups.io <devel@edk2.groups.io> 代表 Kun Qin
> 发送时间: 2023年6月9日 4:45
> 收件人: devel@edk2.groups.io
> 抄送: Hao A Wu <hao.a.wu@intel.com>; Liming Gao
> <gaoliming@byosoft.com.cn>; Jian J Wang <jian.j.wang@intel.com>; Ronny
> Hansen <hansen.ronny@microsoft.com>; Shriram Masanamuthu
> Chinnathurai <shriramma@microsoft.com>; Preshit Harlikar
> <pharlikar@microsoft.com>
> 主题: [edk2-devel] [PATCH v1 2/2] MdeModulePkg: Variable: Introduce MM
> based variable read service in PEI
> 
> From: Kun Qin <kuqin@microsoft.com>
> 
> REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4464
> 
> This change introduced the Standalone MM based variable read capability
> in PEI phase for applicable platforms (such as ARM platforms).
> 
> Similar to the x86 counterpart, MM communicate PPI is used to request
> variable information from Standalone MM environment.
> 
> Cc: Hao A Wu <hao.a.wu@intel.com>
> Cc: Liming Gao <gaoliming@byosoft.com.cn>
> Cc: Jian J Wang <jian.j.wang@intel.com>
> 
> Co-authored-by: Ronny Hansen <hansen.ronny@microsoft.com>
> Co-authored-by: Shriram Masanamuthu Chinnathurai
> <shriramma@microsoft.com>
> Co-authored-by: Preshit Harlikar <pharlikar@microsoft.com>
> Signed-off-by: Kun Qin <kuqin@microsoft.com>
> ---
>  MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.c   |
> 381 ++++++++++++++++++++
>  MdeModulePkg/MdeModulePkg.dsc
> |   1 +
>  MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.h   |
> 134 +++++++
>  MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.inf |
> 43 +++
>  4 files changed, 559 insertions(+)
> 
> diff --git
> a/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.c
> b/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.c
> new file mode 100644
> index 000000000000..4f937e22e89e
> --- /dev/null
> +++ b/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.c
> @@ -0,0 +1,381 @@
> +/** @file -- MmVariablePei.c
> 
> +  Provides interface for reading Secure System Variables during PEI.
> 
> +
> 
> +  Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
> 
> +  Copyright (c) Microsoft Corporation.<BR>
> 
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +**/
> 
> +
> 
> +#include "MmVariablePei.h"
> 
> +
> 
> +#define MM_VARIABLE_COMM_BUFFER_OFFSET
> (SMM_COMMUNICATE_HEADER_SIZE +
> SMM_VARIABLE_COMMUNICATE_HEADER_SIZE)
> 
> +
> 
> +//
> 
> +// Module globals
> 
> +//
> 
> +EFI_PEI_READ_ONLY_VARIABLE2_PPI  mPeiSecureVariableRead = {
> 
> +  PeiMmGetVariable,
> 
> +  PeiMmGetNextVariableName
> 
> +};
> 
> +
> 
> +EFI_PEI_PPI_DESCRIPTOR  mPeiMmVariablePpi = {
> 
> +  (EFI_PEI_PPI_DESCRIPTOR_PPI |
> EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
> 
> +  &gEfiPeiReadOnlyVariable2PpiGuid,
> 
> +  &mPeiSecureVariableRead
> 
> +};
> 
> +
> 
> +/**
> 
> +  Entry point of PEI Secure Variable read driver
> 
> +
> 
> +  @param  FileHandle   Handle of the file being invoked.
> 
> +                       Type EFI_PEI_FILE_HANDLE is defined in
> FfsFindNextFile().
> 
> +  @param  PeiServices  General purpose services available to every
> PEIM.
> 
> +
> 
> +  @retval EFI_SUCCESS  If the interface could be successfully installed
> 
> +  @retval Others       Returned from PeiServicesInstallPpi()
> 
> +**/
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +PeiMmVariableInitialize (
> 
> +  IN       EFI_PEI_FILE_HANDLE  FileHandle,
> 
> +  IN CONST EFI_PEI_SERVICES     **PeiServices
> 
> +  )
> 
> +{
> 
> +  return PeiServicesInstallPpi (&mPeiMmVariablePpi);
> 
> +}
> 
> +
> 
> +/**
> 
> +  Helper function to populate MM communicate header and variable
> communicate header
> 
> +  and then communicate to PEI.
> 
> +
> 
> +  @param[in, out] CommunicateBuffer       Size of the variable name.
> 
> +  @param[in]      CommunicateBufferSize   The entire buffer size to be
> sent to MM.
> 
> +  @param[in]      Function                The MM variable function
> value.
> 
> +
> 
> +  @retval EFI_INVALID_PARAMETER      Invalid parameter.
> 
> +  @retval EFI_SUCCESS                Find the specified variable.
> 
> +  @retval Others                     Errors returned by MM
> communicate or variable service.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +PopulateHeaderAndCommunicate (
> 
> +  IN OUT  UINT8  *CommunicateBuffer,
> 
> +  IN UINTN       CommunicateBufferSize,
> 
> +  IN UINTN       Function
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS                       Status;
> 
> +  EFI_PEI_MM_COMMUNICATION_PPI     *MmCommunicationPpi;
> 
> +  EFI_MM_COMMUNICATE_HEADER        *MmCommunicateHeader;
> 
> +  SMM_VARIABLE_COMMUNICATE_HEADER  *MmVarCommsHeader;
> 
> +
> 
> +  // Minimal sanity check
> 
> +  if ((CommunicateBuffer == NULL) ||
> 
> +      (CommunicateBufferSize <
> MM_VARIABLE_COMM_BUFFER_OFFSET))
> 
> +  {
> 
> +    Status = EFI_INVALID_PARAMETER;
> 
> +    DEBUG ((DEBUG_ERROR, "%a: Invalid incoming parameters: %p and
> 0x%x\n", __func__, CommunicateBuffer, CommunicateBufferSize));
> 
> +    goto Exit;
> 
> +  }
> 
> +
> 
> +  if ((Function !=
> SMM_VARIABLE_FUNCTION_GET_NEXT_VARIABLE_NAME) &&
> 
> +      (Function != SMM_VARIABLE_FUNCTION_GET_VARIABLE))
> 
> +  {
> 
> +    Status = EFI_INVALID_PARAMETER;
> 
> +    DEBUG ((DEBUG_ERROR, "%a: Invalid function value: 0x%x\n",
> __func__, Function));
> 
> +    goto Exit;
> 
> +  }
> 
> +
> 
> +  Status = PeiServicesLocatePpi (&gEfiPeiMmCommunicationPpiGuid, 0,
> NULL, (VOID **)&MmCommunicationPpi);
> 
> +  if (EFI_ERROR (Status)) {
> 
> +    DEBUG ((DEBUG_ERROR, "%a: Failed to locate PEI MM Communication
> PPI: %r\n", __func__, Status));
> 
> +    goto Exit;
> 
> +  }
> 
> +
> 
> +  // Zero the entire Communication Buffer Header
> 
> +  MmCommunicateHeader = (EFI_MM_COMMUNICATE_HEADER
> *)CommunicateBuffer;
> 
> +
> 
> +  ZeroMem (MmCommunicateHeader,
> SMM_COMMUNICATE_HEADER_SIZE);
> 
> +
> 
> +  // Use gEfiSmmVariableProtocolGuid to request the MM variable service
> in Standalone MM
> 
> +  CopyMem ((VOID *)&MmCommunicateHeader->HeaderGuid,
> &gEfiSmmVariableProtocolGuid, sizeof (GUID));
> 
> +
> 
> +  // Program the MM header size
> 
> +  MmCommunicateHeader->MessageLength = CommunicateBufferSize -
> SMM_COMMUNICATE_HEADER_SIZE;
> 
> +
> 
> +  MmVarCommsHeader = (SMM_VARIABLE_COMMUNICATE_HEADER
> *)(CommunicateBuffer + SMM_COMMUNICATE_HEADER_SIZE);
> 
> +
> 
> +  // We are only supporting GetVariable and GetNextVariableName
> 
> +  MmVarCommsHeader->Function = Function;
> 
> +
> 
> +  // Send the MM request using MmCommunicationPei
> 
> +  Status = MmCommunicationPpi->Communicate (MmCommunicationPpi,
> CommunicateBuffer, &CommunicateBufferSize);
> 
> +  if (EFI_ERROR (Status)) {
> 
> +    // Received an error from MM interface.
> 
> +    DEBUG ((DEBUG_ERROR, "%a - MM Interface Error: %r\n", __func__,
> Status));
> 
> +    goto Exit;
> 
> +  }
> 
> +
> 
> +  // MM request was successfully handled by the framework.
> 
> +  // Set status to the Variable Service Status Code
> 
> +  Status = MmVarCommsHeader->ReturnStatus;
> 
> +  if (EFI_ERROR (Status)) {
> 
> +    // We received an error from Variable Service.
> 
> +    // We cant do anymore so return Status
> 
> +    if (Status != EFI_BUFFER_TOO_SMALL) {
> 
> +      DEBUG ((DEBUG_ERROR, "%a - Variable Service Error: %r\n",
> __func__, Status));
> 
> +    }
> 
> +
> 
> +    goto Exit;
> 
> +  }
> 
> +
> 
> +Exit:
> 
> +  return Status;
> 
> +}
> 
> +
> 
> +/**
> 
> +  This service retrieves a variable's value using its name and GUID.
> 
> +
> 
> +  This function is using the Secure Variable Store. If the Data
> 
> +  buffer is too small to hold the contents of the variable, the error
> 
> +  EFI_BUFFER_TOO_SMALL is returned and DataSize is set to the required
> buffer
> 
> +  size to obtain the data.
> 
> +
> 
> +  @param  This                  A pointer to this instance of the
> EFI_PEI_READ_ONLY_VARIABLE2_PPI.
> 
> +  @param  VariableName          A pointer to a null-terminated string
> that is the variable's name.
> 
> +  @param  VariableGuid          A pointer to an EFI_GUID that is the
> variable's GUID. The combination of
> 
> +                                VariableGuid and VariableName
> must be unique.
> 
> +  @param  Attributes            If non-NULL, on return, points to the
> variable's attributes.
> 
> +  @param  DataSize              On entry, points to the size in bytes
> of the Data buffer.
> 
> +                                On return, points to the size of the
> data returned in Data.
> 
> +  @param  Data                  Points to the buffer which will hold
> the returned variable value.
> 
> +                                May be NULL with a zero DataSize in
> order to determine the size of the buffer needed.
> 
> +
> 
> +  @retval EFI_SUCCESS           The variable was read successfully.
> 
> +  @retval EFI_NOT_FOUND         The variable was not found.
> 
> +  @retval EFI_BUFFER_TOO_SMALL  The DataSize is too small for the
> resulting data.
> 
> +                                DataSize is updated with the size
> required for
> 
> +                                the specified variable.
> 
> +  @retval EFI_INVALID_PARAMETER VariableName, VariableGuid, DataSize
> or Data is NULL.
> 
> +  @retval EFI_DEVICE_ERROR      The variable could not be retrieved
> because of a device error.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +PeiMmGetVariable (
> 
> +  IN CONST  EFI_PEI_READ_ONLY_VARIABLE2_PPI *This,
> 
> +  IN CONST  CHAR16 *VariableName,
> 
> +  IN CONST  EFI_GUID *VariableGuid,
> 
> +  OUT       UINT32 *Attributes, OPTIONAL
> 
> +  IN OUT    UINTN                            *DataSize,
> 
> +  OUT       VOID                             *Data OPTIONAL
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS                                Status;
> 
> +  UINTN                                     MessageSize;
> 
> +  SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE
> *MmVarAccessHeader;
> 
> +  UINT8
> *MmCommunicateBuffer;
> 
> +  UINTN                                     RequiredPages;
> 
> +
> 
> +  // Check input parameters
> 
> +  if ((VariableName == NULL) || (VariableGuid == NULL) || (DataSize ==
> NULL)) {
> 
> +    return EFI_INVALID_PARAMETER;
> 
> +  }
> 
> +
> 
> +  if (VariableName[0] == 0) {
> 
> +    return EFI_NOT_FOUND;
> 
> +  }
> 
> +
> 
> +  if ((*DataSize > 0) && (Data == NULL)) {
> 
> +    return EFI_INVALID_PARAMETER;
> 
> +  }
> 
> +
> 
> +  // Allocate required pages to send MM request
> 
> +  MessageSize = MM_VARIABLE_COMM_BUFFER_OFFSET +
> 
> +                OFFSET_OF
> (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) +
> 
> +                StrSize (VariableName) + *DataSize;
> 
> +
> 
> +  RequiredPages       = EFI_SIZE_TO_PAGES (MessageSize);
> 
> +  MmCommunicateBuffer = (UINT8 *)AllocatePages (RequiredPages);
> 
> +
> 
> +  if (MmCommunicateBuffer == NULL) {
> 
> +    Status = EFI_OUT_OF_RESOURCES;
> 
> +    DEBUG ((DEBUG_ERROR, "%a: Failed to allocate memory: %r\n",
> __func__, Status));
> 
> +    return Status;
> 
> +  }
> 
> +
> 
> +  // Zero the entire Communication Buffer
> 
> +  ZeroMem (MmCommunicateBuffer, (RequiredPages * EFI_PAGE_SIZE));
> 
> +
> 
> +  //
> 
> +  // Program all payload structure contents
> 
> +  //
> 
> +  MmVarAccessHeader =
> (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE
> *)(MmCommunicateBuffer + MM_VARIABLE_COMM_BUFFER_OFFSET);
> 
> +
> 
> +  // Variable GUID
> 
> +  CopyMem ((VOID *)&MmVarAccessHeader->Guid, VariableGuid, sizeof
> (GUID));
> 
> +
> 
> +  // Program the max amount of data we accept.
> 
> +  MmVarAccessHeader->DataSize = *DataSize;
> 
> +
> 
> +  // Get size of the variable name
> 
> +  MmVarAccessHeader->NameSize = StrSize (VariableName);
> 
> +
> 
> +  // Populate incoming variable name
> 
> +  CopyMem ((VOID *)&MmVarAccessHeader->Name, VariableName,
> MmVarAccessHeader->NameSize);
> 
> +
> 
> +  Status = PopulateHeaderAndCommunicate (MmCommunicateBuffer,
> MessageSize, SMM_VARIABLE_FUNCTION_GET_VARIABLE);
> 
> +  if (EFI_ERROR (Status)) {
> 
> +    // We received an error from either communicate or Variable Service.
> 
> +    if (Status != EFI_BUFFER_TOO_SMALL) {
> 
> +      DEBUG ((DEBUG_ERROR, "%a - Communite to MM for variable
> service errored: %r\n", __func__, Status));
> 
> +    }
> 
> +
> 
> +    goto Exit;
> 
> +  }
> 
> +
> 
> +  Status = EFI_SUCCESS;
> 
> +
> 
> +  // User provided buffer is too small
> 
> +  if (*DataSize < MmVarAccessHeader->DataSize) {
> 
> +    Status = EFI_BUFFER_TOO_SMALL;
> 
> +  }
> 
> +
> 
> +Exit:
> 
> +  // Check if we need to set Attributes
> 
> +  if (Attributes != NULL) {
> 
> +    *Attributes = MmVarAccessHeader->Attributes;
> 
> +  }
> 
> +
> 
> +  *DataSize = MmVarAccessHeader->DataSize;
> 
> +
> 
> +  if (Status == EFI_SUCCESS) {
> 
> +    CopyMem ((VOID *)Data, (UINT8 *)MmVarAccessHeader->Name +
> MmVarAccessHeader->NameSize, *DataSize);
> 
> +  }
> 
> +
> 
> +  // Free the Communication Buffer
> 
> +  if (MmCommunicateBuffer != NULL) {
> 
> +    FreePages (MmCommunicateBuffer, RequiredPages);
> 
> +  }
> 
> +
> 
> +  return Status;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Return the next variable name and GUID.
> 
> +
> 
> +  This function is called multiple times to retrieve the VariableName
> 
> +  and VariableGuid of all variables currently available in the system.
> 
> +  On each call, the previous results are passed into the interface,
> 
> +  and, on return, the interface returns the data for the next
> 
> +  interface. When the entire variable list has been returned,
> 
> +  EFI_NOT_FOUND is returned.
> 
> +
> 
> +  @param  This              A pointer to this instance of the
> EFI_PEI_READ_ONLY_VARIABLE2_PPI.
> 
> +
> 
> +  @param  VariableNameSize  On entry, points to the size of the buffer
> pointed to by VariableName.
> 
> +                            On return, the size of the variable name
> buffer.
> 
> +  @param  VariableName      On entry, a pointer to a null-terminated
> string that is the variable's name.
> 
> +                            On return, points to the next variable's
> null-terminated name string.
> 
> +
> 
> +  @param  VariableGuid      On entry, a pointer to an EFI_GUID that is
> the variable's GUID.
> 
> +                            On return, a pointer to the next variable's
> GUID.
> 
> +
> 
> +  @retval EFI_SUCCESS           The variable was read successfully.
> 
> +  @retval EFI_NOT_FOUND         The variable could not be found.
> 
> +  @retval EFI_BUFFER_TOO_SMALL  The VariableNameSize is too small
> for the resulting
> 
> +                                data. VariableNameSize is updated
> with the size
> 
> +                                required for the specified variable.
> 
> +  @retval EFI_INVALID_PARAMETER VariableName, VariableGuid or
> 
> +                                VariableNameSize is NULL.
> 
> +  @retval EFI_DEVICE_ERROR      The variable could not be retrieved
> because of a device error.
> 
> +**/
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +PeiMmGetNextVariableName (
> 
> +  IN CONST  EFI_PEI_READ_ONLY_VARIABLE2_PPI  *This,
> 
> +  IN OUT UINTN                               *VariableNameSize,
> 
> +  IN OUT CHAR16                              *VariableName,
> 
> +  IN OUT EFI_GUID                            *VariableGuid
> 
> +  )
> 
> +{
> 
> +  EFI_STATUS                                       Status;
> 
> +  UINTN
> MessageSize;
> 
> +  UINT8
> *MmCommunicateBuffer;
> 
> +  SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME
> *MmVarGetNextVarHeader;
> 
> +  UINTN
> RequiredPages;
> 
> +
> 
> +  // Check input parameters
> 
> +  if ((VariableName == NULL) ||
> 
> +      (VariableGuid == NULL) ||
> 
> +      (VariableNameSize == NULL) ||
> 
> +      (*VariableNameSize == 0))
> 
> +  {
> 
> +    return EFI_INVALID_PARAMETER;
> 
> +  }
> 
> +
> 
> +  // Allocate required pages to send MM request
> 
> +  MessageSize = MM_VARIABLE_COMM_BUFFER_OFFSET +
> 
> +                OFFSET_OF
> (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) +
> 
> +                StrSize (VariableName) + *VariableNameSize;
> 
> +
> 
> +  RequiredPages       = EFI_SIZE_TO_PAGES (MessageSize);
> 
> +  MmCommunicateBuffer = (UINT8 *)AllocatePages (RequiredPages);
> 
> +
> 
> +  if (MmCommunicateBuffer == NULL) {
> 
> +    Status = EFI_OUT_OF_RESOURCES;
> 
> +    DEBUG ((DEBUG_ERROR, "%a: Failed to allocate memory: %r\n",
> __func__, Status));
> 
> +    return Status;
> 
> +  }
> 
> +
> 
> +  // Zero the entire Communication Buffer
> 
> +  ZeroMem (MmCommunicateBuffer, (RequiredPages * EFI_PAGE_SIZE));
> 
> +
> 
> +  //
> 
> +  // Program all payload structure contents
> 
> +  //
> 
> +  MmVarGetNextVarHeader =
> (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME
> *)(MmCommunicateBuffer + MM_VARIABLE_COMM_BUFFER_OFFSET);
> 
> +
> 
> +  // Variable GUID
> 
> +  CopyMem ((VOID *)&MmVarGetNextVarHeader->Guid, VariableGuid,
> sizeof (GUID));
> 
> +
> 
> +  // Program the maximal length of name we can accept.
> 
> +  MmVarGetNextVarHeader->NameSize = *VariableNameSize;
> 
> +
> 
> +  // Populate incoming variable name
> 
> +  CopyMem ((VOID *)&MmVarGetNextVarHeader->Name, VariableName,
> MmVarGetNextVarHeader->NameSize);
> 
> +
> 
> +  // Send the MM request using MmCommunicationPei
> 
> +  Status = PopulateHeaderAndCommunicate (MmCommunicateBuffer,
> MessageSize, SMM_VARIABLE_FUNCTION_GET_NEXT_VARIABLE_NAME);
> 
> +  if (EFI_ERROR (Status)) {
> 
> +    // We received an error from either communicate or Variable Service.
> 
> +    if (Status != EFI_BUFFER_TOO_SMALL) {
> 
> +      DEBUG ((DEBUG_ERROR, "%a - Communite to MM for variable
> service errored: %r\n", __func__, Status));
> 
> +    }
> 
> +
> 
> +    goto Exit;
> 
> +  }
> 
> +
> 
> +  Status = EFI_SUCCESS;
> 
> +
> 
> +  // User provided buffer is too small
> 
> +  if (*VariableNameSize < MmVarGetNextVarHeader->NameSize) {
> 
> +    Status = EFI_BUFFER_TOO_SMALL;
> 
> +  }
> 
> +
> 
> +Exit:
> 
> +  // Update the name size to be returned
> 
> +  *VariableNameSize = MmVarGetNextVarHeader->NameSize;
> 
> +
> 
> +  if (Status == EFI_SUCCESS) {
> 
> +    CopyMem ((VOID *)VariableName, (UINT8
> *)MmVarGetNextVarHeader->Name, *VariableNameSize);
> 
> +    CopyMem ((VOID *)VariableGuid, (UINT8
> *)&(MmVarGetNextVarHeader->Guid), sizeof (EFI_GUID));
> 
> +  }
> 
> +
> 
> +  // Free the Communication Buffer
> 
> +  if (MmCommunicateBuffer != NULL) {
> 
> +    FreePages (MmCommunicateBuffer, RequiredPages);
> 
> +  }
> 
> +
> 
> +  return Status;
> 
> +}
> 
> diff --git a/MdeModulePkg/MdeModulePkg.dsc
> b/MdeModulePkg/MdeModulePkg.dsc
> index 5b1f50e9c084..1aedfe280ae1 100644
> --- a/MdeModulePkg/MdeModulePkg.dsc
> +++ b/MdeModulePkg/MdeModulePkg.dsc
> @@ -400,6 +400,7 @@ [Components]
>    MdeModulePkg/Application/VariableInfo/VariableInfo.inf
> 
> 
> MdeModulePkg/Universal/FaultTolerantWritePei/FaultTolerantWritePei.inf
> 
>    MdeModulePkg/Universal/Variable/Pei/VariablePei.inf
> 
> +  MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.inf
> 
>    MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
> 
>    MdeModulePkg/Universal/TimestampDxe/TimestampDxe.inf
> 
> 
> MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf
> 
> diff --git
> a/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.h
> b/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.h
> new file mode 100644
> index 000000000000..0feed8cd1cb6
> --- /dev/null
> +++ b/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.h
> @@ -0,0 +1,134 @@
> +/** @file -- MmVariablePei.h
> 
> +  Provides interface for reading Secure System Variables during PEI.
> 
> +
> 
> +  Copyright (c) Microsoft Corporation.
> 
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +**/
> 
> +
> 
> +#ifndef PEI_MM_VARIABLE_LIB_H_
> 
> +#define PEI_MM_VARIABLE_LIB_H_
> 
> +
> 
> +#include <PiPei.h>
> 
> +#include <Uefi/UefiSpec.h>
> 
> +
> 
> +#include <Library/DebugLib.h>
> 
> +#include <Library/PcdLib.h>
> 
> +#include <Library/BaseMemoryLib.h>
> 
> +#include <Library/PeimEntryPoint.h>
> 
> +#include <Library/PeiServicesLib.h>
> 
> +#include <Library/MemoryAllocationLib.h>
> 
> +#include <Library/HobLib.h>
> 
> +
> 
> +#include <Guid/SmmVariableCommon.h>
> 
> +
> 
> +#include <Ppi/ReadOnlyVariable2.h>
> 
> +#include <Ppi/MmCommunication.h>
> 
> +
> 
> +#include <Protocol/SmmVariable.h>
> 
> +#include <Protocol/MmCommunication.h>
> 
> +
> 
> +/**
> 
> +  Entry point of PEI Secure Variable read driver
> 
> +
> 
> +  @param  FileHandle   Handle of the file being invoked.
> 
> +                       Type EFI_PEI_FILE_HANDLE is defined in
> FfsFindNextFile().
> 
> +  @param  PeiServices  General purpose services available to every
> PEIM.
> 
> +
> 
> +  @retval EFI_SUCCESS  If the interface could be successfully installed
> 
> +  @retval Others       Returned from PeiServicesInstallPpi()
> 
> +**/
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +PeiMmVariableInitialize (
> 
> +  IN       EFI_PEI_FILE_HANDLE  FileHandle,
> 
> +  IN CONST EFI_PEI_SERVICES     **PeiServices
> 
> +  );
> 
> +
> 
> +/**
> 
> +
> 
> +  This function enables the read of Secure Variables during PEI.
> 
> +
> 
> +  This function is using the Secure Variable Store.If the Data
> 
> +  buffer is too small to hold the contents of the variable, the error
> 
> +  EFI_BUFFER_TOO_SMALL is returned and DataSize is set to the required
> buffer
> 
> +  size to obtain the data.
> 
> +
> 
> +  The function performs the following:
> 
> +
> 
> +  1) Creates an MM request
> 
> +  2) Fills out the following data structures for the Secure Variable
Service
> 
> +
> SMM_VARIABLE_COMMUNICATE_HEADER/SMM_VARIABLE_COMMUNICAT
> E_ACCESS_VARIABLE
> 
> +  3) Adds the MM data structures to the MM request.
> 
> +  4) Sends the MM request to EL3 using MmCommunicationPeiLib.
> 
> +  5) The MM request is sent to S-EL0.
> 
> +  6) The MM request is then handled by the registered handler with GUID:
> gEfiSmmVariableProtocolGuid
> 
> +
> 
> +  @param  This                  A pointer to this instance of the
> EFI_PEI_READ_ONLY_VARIABLE2_PPI.
> 
> +  @param  VariableName          A pointer to a null-terminated string
> that is the variable's name.
> 
> +  @param  VariableGuid          A pointer to an EFI_GUID that is the
> variable's GUID. The combination of
> 
> +                                VariableGuid and VariableName
> must be unique.
> 
> +  @param  Attributes            If non-NULL, on return, points to the
> variable's attributes.
> 
> +  @param  DataSize              On entry, points to the size in bytes
> of the Data buffer.
> 
> +                                On return, points to the size of the
> data returned in Data.
> 
> +  @param  Data                  Points to the buffer which will hold
> the returned variable value.
> 
> +                                May be NULL with a zero DataSize in
> order to determine the size of the buffer needed.
> 
> +
> 
> +  @retval EFI_SUCCESS           The variable was read successfully.
> 
> +  @retval EFI_NOT_FOUND         The variable was not found.
> 
> +  @retval EFI_BUFFER_TOO_SMALL  The DataSize is too small for the
> resulting data.
> 
> +                                DataSize is updated with the size
> required for
> 
> +                                the specified variable.
> 
> +  @retval EFI_INVALID_PARAMETER VariableName, VariableGuid, DataSize
> or Data is NULL.
> 
> +  @retval EFI_DEVICE_ERROR      The variable could not be retrieved
> because of a device error.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +PeiMmGetVariable (
> 
> +  IN CONST  EFI_PEI_READ_ONLY_VARIABLE2_PPI  *This,
> 
> +  IN CONST  CHAR16                           *VariableName,
> 
> +  IN CONST  EFI_GUID                         *VariableGuid,
> 
> +  OUT       UINT32                           *Attributes,
> 
> +  IN OUT    UINTN                            *DataSize,
> 
> +  OUT       VOID                             *Data OPTIONAL
> 
> +  );
> 
> +
> 
> +/**
> 
> +  Return the next variable name and GUID.
> 
> +
> 
> +  This function is called multiple times to retrieve the VariableName
> 
> +  and VariableGuid of all variables currently available in the system.
> 
> +  On each call, the previous results are passed into the interface,
> 
> +  and, on return, the interface returns the data for the next
> 
> +  interface. When the entire variable list has been returned,
> 
> +  EFI_NOT_FOUND is returned.
> 
> +
> 
> +  @param  This              A pointer to this instance of the
> EFI_PEI_READ_ONLY_VARIABLE2_PPI.
> 
> +
> 
> +  @param  VariableNameSize  On entry, points to the size of the buffer
> pointed to by VariableName.
> 
> +                            On return, the size of the variable name
> buffer.
> 
> +  @param  VariableName      On entry, a pointer to a null-terminated
> string that is the variable's name.
> 
> +                            On return, points to the next variable's
> null-terminated name string.
> 
> +
> 
> +  @param  VariableGuid      On entry, a pointer to an EFI_GUID that is
> the variable's GUID.
> 
> +                            On return, a pointer to the next variable's
> GUID.
> 
> +
> 
> +  @retval EFI_SUCCESS           The variable was read successfully.
> 
> +  @retval EFI_NOT_FOUND         The variable could not be found.
> 
> +  @retval EFI_BUFFER_TOO_SMALL  The VariableNameSize is too small
> for the resulting
> 
> +                                data. VariableNameSize is updated
> with the size
> 
> +                                required for the specified variable.
> 
> +  @retval EFI_INVALID_PARAMETER VariableName, VariableGuid or
> 
> +                                VariableNameSize is NULL.
> 
> +  @retval EFI_DEVICE_ERROR      The variable could not be retrieved
> because of a device error.
> 
> +**/
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +PeiMmGetNextVariableName (
> 
> +  IN CONST  EFI_PEI_READ_ONLY_VARIABLE2_PPI  *This,
> 
> +  IN OUT UINTN                               *VariableNameSize,
> 
> +  IN OUT CHAR16                              *VariableName,
> 
> +  IN OUT EFI_GUID                            *VariableGuid
> 
> +  );
> 
> +
> 
> +#endif /* PEI_MM_VARIABLE_LIB_H_ */
> 
> diff --git
> a/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.inf
> b/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.inf
> new file mode 100644
> index 000000000000..d122703e9b5d
> --- /dev/null
> +++ b/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.inf
> @@ -0,0 +1,43 @@
> +## @file -- MmVariablePei.inf
> 
> +# Provides interface for reading Secure System Variables during PEI.
> 
> +#
> 
> +# Copyright (c) Microsoft Corporation.
> 
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +##
> 
> +
> 
> +
> 
> +[Defines]
> 
> +  INF_VERSION                    = 0x00010005
> 
> +  BASE_NAME                      = MmVariablePei
> 
> +  FILE_GUID                      =
> CD660A87-454B-4346-A35C-3D89BF8ECFAF
> 
> +  MODULE_TYPE                    = PEIM
> 
> +  VERSION_STRING                 = 1.0
> 
> +  ENTRY_POINT                    = PeiMmVariableInitialize
> 
> +
> 
> +[Sources]
> 
> +  MmVariablePei.c
> 
> +  MmVariablePei.h
> 
> +
> 
> +[Packages]
> 
> +  MdePkg/MdePkg.dec
> 
> +  MdeModulePkg/MdeModulePkg.dec
> 
> +
> 
> +[LibraryClasses]
> 
> +  PcdLib
> 
> +  PeiServicesLib
> 
> +  PeimEntryPoint
> 
> +  MemoryAllocationLib
> 
> +  HobLib
> 
> +
> 
> +[Pcd]
> 
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize
> 
> +
> 
> +[Protocols]
> 
> +  gEfiSmmVariableProtocolGuid             ## CONSUMES
> 
> +
> 
> +[Ppis]
> 
> +  gEfiPeiReadOnlyVariable2PpiGuid         ## PRODUCES
> 
> +  gEfiPeiMmCommunicationPpiGuid           ## CONSUMES
> 
> +
> 
> +[Depex]
> 
> +  gEfiPeiMmCommunicationPpiGuid
> 
> --
> 2.40.1.windows.1
> 
> 
> 
> -=-=-=-=-=-=
> Groups.io Links: You receive all messages sent to this group.
> View/Reply Online (#105956):
> https://edk2.groups.io/g/devel/message/105956
> Mute This Topic: https://groups.io/mt/99415826/4905953
> Group Owner: devel+owner@edk2.groups.io
> Unsubscribe: https://edk2.groups.io/g/devel/unsub
> [gaoliming@byosoft.com.cn]
> -=-=-=-=-=-=
> 




^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v1 1/2] ArmPkg: MmCommunicationPei: Introduce MM communicate in PEI
  2023-06-22 19:17   ` Sami Mujawar
@ 2023-06-26 20:07     ` Kun Qin
  0 siblings, 0 replies; 8+ messages in thread
From: Kun Qin @ 2023-06-26 20:07 UTC (permalink / raw)
  To: Sami Mujawar, devel
  Cc: Leif Lindholm, Ard Biesheuvel, Ronny Hansen,
	Shriram Masanamuthu Chinnathurai, Preshit Harlikar, nd@arm.com

[-- Attachment #1: Type: text/plain, Size: 15910 bytes --]

Hi Sami,

Thank you for your feedback. I have update the code as you suggested. 
Could you
please re-review when you have a chance?

https://edk2.groups.io/g/devel/message/106372

Thanks,
Kun

On 6/22/2023 12:17 PM, Sami Mujawar wrote:
>
> Hi Kun,
>
> Thank you for this patch.
>
> Please find my response inline marked [SAMI].
>
> Regards,
>
> Sami Mujawar
>
> On 08/06/2023 09:44 pm, Kun Qin wrote:
>> From: Kun Qin<kuqin@microsoft.com>
>>
>> REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4464
>>
>> This change introduced the MM communicate support in PEI phase for ARM
>> based platforms. Similar to the DXE counterpart, `PcdMmBufferBase` is
>> used as communicate buffer and SMC will be invoked to communicate to
>> TrustZone when MMI is requested.
>>
>> Cc: Leif Lindholm<quic_llindhol@quicinc.com>
>> Cc: Ard Biesheuvel<ardb+tianocore@kernel.org>
>> Cc: Sami Mujawar<sami.mujawar@arm.com>
>>
>> Co-authored-by: Ronny Hansen<hansen.ronny@microsoft.com>
>> Co-authored-by: Shriram Masanamuthu Chinnathurai<shriramma@microsoft.com>
>> Co-authored-by: Preshit Harlikar<pharlikar@microsoft.com>
>> Signed-off-by: Kun Qin<kuqin@microsoft.com>
>> ---
>>   ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.c   | 178 ++++++++++++++++++++
>>   ArmPkg/ArmPkg.dsc                                        |   2 +
>>   ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.h   |  76 +++++++++
>>   ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.inf |  41 +++++
>>   4 files changed, 297 insertions(+)
>>
>> diff --git a/ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.c b/ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.c
>> new file mode 100644
>> index 000000000000..0f1f763a347d
>> --- /dev/null
>> +++ b/ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.c
>> @@ -0,0 +1,178 @@
>> +/** @file -- MmCommunicationPei.c
>>
>> +  Provides an interface to send MM request in PEI
>>
>> +
>>
>> +  Copyright (c) 2016-2021, Arm Limited. All rights reserved.<BR>
>>
>> +  Copyright (c) Microsoft Corporation.
>>
>> +  SPDX-License-Identifier: BSD-2-Clause-Patent
>>
>> +**/
>>
>> +
>>
>> +#include "MmCommunicationPei.h"
>>
>> +
>>
>> +//
>>
>> +// Module globals
>>
>> +//
>>
>> +EFI_PEI_MM_COMMUNICATION_PPI  mPeiMmCommunication = {
>>
>> +  MmCommunicationPeim
>>
>> +};
>>
>> +
>>
>> +EFI_PEI_PPI_DESCRIPTOR  mPeiMmCommunicationPpi = {
>>
>> +  (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
>>
>> +  &gEfiPeiMmCommunicationPpiGuid,
>>
>> +  &mPeiMmCommunication
>>
>> +};
>>
>> +
>>
>> +/**
>>
>> +  Entry point of PEI MM Communication driver
>>
>> +
>>
>> +  @param  FileHandle   Handle of the file being invoked.
>>
>> +                       Type EFI_PEI_FILE_HANDLE is defined in FfsFindNextFile().
>>
>> +  @param  PeiServices  General purpose services available to every PEIM.
>>
>> +
>>
>> +  @retval EFI_SUCCESS  If the interface could be successfully installed
>>
>> +  @retval Others       Returned from PeiServicesInstallPpi()
>>
>> +**/
>>
>> +EFI_STATUS
>>
>> +EFIAPI
>>
>> +MmCommunicationPeiInitialize (
>>
>> +  IN       EFI_PEI_FILE_HANDLE  FileHandle,
>>
>> +  IN CONST EFI_PEI_SERVICES     **PeiServices
>>
>> +  )
>>
>> +{
>>
>> +  return PeiServicesInstallPpi (&mPeiMmCommunicationPpi);
>>
>> +}
>>
>> +
>>
>> +/**
>>
>> +  MmCommunicationPeim
>>
>> +  Communicates with a registered handler.
>>
>> +  This function provides a service to send and receive messages from a registered UEFI service during PEI.
>>
>> +
>>
>> +  @param[in]      This            The EFI_PEI_MM_COMMUNICATION_PPI instance.
>>
>> +  @param[in, out] CommBuffer      Pointer to the data buffer
>>
>> +  @param[in, out] CommSize        The size of the data buffer being passed in. On exit, the
>>
>> +                                  size of data being returned. Zero if the handler does not
>>
>> +                                  wish to reply with any data.
>>
>> +
>>
>> +  @retval EFI_SUCCESS             The message was successfully posted.
>>
>> +  @retval EFI_INVALID_PARAMETER   CommBuffer was NULL or *CommSize does not match
>>
>> +                                  MessageLength + sizeof (EFI_MM_COMMUNICATE_HEADER).
>>
>> +  @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
>>
>> +MmCommunicationPeim (
>>
>> +  IN CONST EFI_PEI_MM_COMMUNICATION_PPI  *This,
>>
>> +  IN OUT VOID                            *CommBuffer,
>>
>> +  IN OUT UINTN                           *CommSize
>>
>> +  )
>>
>> +{
>>
>> +  EFI_MM_COMMUNICATE_HEADER  *CommunicateHeader;
>>
>> +  ARM_SMC_ARGS               CommunicateSmcArgs;
>>
>> +  EFI_STATUS                 Status;
>>
>> +  UINTN                      BufferSize;
>>
>> +
>>
>> +  Status     = EFI_ACCESS_DENIED;
>>
>> +  BufferSize = 0;
> [SAMI] Minor optimisation: The above initialisations are probably not 
> required.
>> +
>>
>> +  ZeroMem (&CommunicateSmcArgs, sizeof (ARM_SMC_ARGS));
>>
>> +
>>
>> +  // Check that our static buffer is looking good.
>>
>> +  // We are using PcdMmBufferBase to transfer variable data.
>>
>> +  // We are not using the full size of the buffer since there is a cost
>>
>> +  // of copying data between Normal and Secure World.
>>
>> +  ASSERT (PcdGet64 (PcdMmBufferSize) > 0 && PcdGet64 (PcdMmBufferBase) != 0);
>>
>> +
>>
>> +  //
>>
>> +  // Check parameters
>>
>> +  //
>>
>> +  if (CommBuffer == NULL) {
>>
>> +    return EFI_INVALID_PARAMETER;
>>
>> +  }
> [SAMI] Should there be a check for CommSize as well? Otherwise the 
> code will crash a few lines below when doing CopyMem().
>> +
>>
>> +  // If the length of the CommBuffer is 0 then return the expected length.
>>
>> +  // 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 != NULL) && \
>>
>> +      ((*CommSize == 0) || (*CommSize > (UINTN)PcdGet64 (PcdMmBufferSize))))
>>
>> +  {
>>
>> +    *CommSize = (UINTN)PcdGet64 (PcdMmBufferSize);
>>
>> +    return EFI_BAD_BUFFER_SIZE;
>>
>> +  }
>>
>> +
>>
>> +  CommunicateHeader = (EFI_MM_COMMUNICATE_HEADER *)(UINTN)(PcdGet64 (PcdMmBufferBase));
>>
>> +
>>
>> +  CopyMem ((VOID *)CommunicateHeader, CommBuffer, *CommSize);
> [SAMI] If CommSize is NULL, the above the above line will result in a 
> crash, right?
>> +
>>
>> +  // 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 CommSize is supplied it must match MessageLength + sizeof (EFI_MM_COMMUNICATE_HEADER);
>>
>> +  //
>>
>> +  if ((CommSize != NULL) && (*CommSize != BufferSize)) {
>>
>> +    return EFI_INVALID_PARAMETER;
>>
>> +  }
> [SAMI] It may be better to do this check earlier in the code by 
> casting CommBuffer to EFI_MM_COMMUNICATE_HEADER * and calculating the 
> BufferSize. That way the CopyMem() above can be avoided if the above 
> test fails.
>> +
>>
>> +  // SMC Function ID
>>
>> +  CommunicateSmcArgs.Arg0 = ARM_SMC_ID_MM_COMMUNICATE_AARCH64;
>>
>> +
>>
>> +  // Cookie
>>
>> +  CommunicateSmcArgs.Arg1 = 0;
>>
>> +
>>
>> +  // comm_buffer_address (64-bit physical address)
>>
>> +  CommunicateSmcArgs.Arg2 = (UINTN)CommunicateHeader;
>>
>> +
>>
>> +  // 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:
>>
>> +      // On successful return, the size of data being returned is inferred from
>>
>> +      // MessageLength + Header.
>>
>> +      BufferSize = CommunicateHeader->MessageLength +
>>
>> +                   sizeof (CommunicateHeader->HeaderGuid) +
>>
>> +                   sizeof (CommunicateHeader->MessageLength);
>>
>> +      CopyMem (CommBuffer, (VOID *)CommunicateHeader, BufferSize);
>
> [SAMI] Can there be a case where the returned MessageLength results in 
> the CommBuffer size being smaller, i.e. BufferSize returned > *CommSize ?
>
> I expect  ARM_SMC_MM_RET_NO_MEMORY to have been returned in the first 
> place, but it may be worth adding a check to avoid potential issues. 
> What do you think?
>
>> +      if (CommSize != NULL) {
>>
>> +        *CommSize = 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;
>>
>> +}
>>
>> diff --git a/ArmPkg/ArmPkg.dsc b/ArmPkg/ArmPkg.dsc
>> index 6b938ce8b671..4939b3d59b7f 100644
>> --- a/ArmPkg/ArmPkg.dsc
>> +++ b/ArmPkg/ArmPkg.dsc
>> @@ -162,6 +162,8 @@ [Components.common]
>>     ArmPkg/Universal/Smbios/SmbiosMiscDxe/SmbiosMiscDxe.inf
>>
>>     ArmPkg/Universal/Smbios/OemMiscLibNull/OemMiscLibNull.inf
>>
>>   
>>
>> +  ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.inf
>>
>> +
>>
>>   [Components.AARCH64]
>>
>>     ArmPkg/Drivers/ArmPsciMpServicesDxe/ArmPsciMpServicesDxe.inf
>>
>>     ArmPkg/Drivers/MmCommunicationDxe/MmCommunication.inf
>>
>> diff --git a/ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.h b/ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.h
>> new file mode 100644
>> index 000000000000..a99baa2496a9
>> --- /dev/null
>> +++ b/ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.h
>> @@ -0,0 +1,76 @@
>> +/** @file -- MmCommunicationPei.h
>>
>> +  Provides an interface to send MM request in PEI
>>
>> +
>>
>> +  Copyright (c) Microsoft Corporation.
>>
>> +  SPDX-License-Identifier: BSD-2-Clause-Patent
>>
>> +**/
>>
>> +
>>
>> +#ifndef MM_COMMUNICATION_PEI_H_
>>
>> +#define MM_COMMUNICATION_PEI_H_
>>
>> +
>>
>> +#include <PiPei.h>
>>
>> +
>>
>> +#include <Library/BaseLib.h>
>>
>> +#include <Library/BaseMemoryLib.h>
>>
>> +#include <Library/ArmSmcLib.h>
>>
>> +#include <Library/DebugLib.h>
>>
>> +#include <Library/PcdLib.h>
>>
>> +#include <Library/PeimEntryPoint.h>
>>
>> +#include <Library/PeiServicesLib.h>
>>
>> +#include <Library/HobLib.h>
>>
>> +
>>
>> +#include <Protocol/MmCommunication.h>
>>
>> +
>>
>> +#include <IndustryStandard/ArmStdSmc.h>
>>
>> +
>>
>> +#include <Ppi/MmCommunication.h>
>>
>> +
>>
>> +/**
>>
>> +  Entry point of PEI MM Communication driver
>>
>> +
>>
>> +  @param  FileHandle   Handle of the file being invoked.
>>
>> +                       Type EFI_PEI_FILE_HANDLE is defined in FfsFindNextFile().
>>
>> +  @param  PeiServices  General purpose services available to every PEIM.
>>
>> +
>>
>> +  @retval EFI_SUCCESS  If the interface could be successfully installed
>>
>> +  @retval Others       Returned from PeiServicesInstallPpi()
>>
>> +**/
>>
>> +EFI_STATUS
>>
>> +EFIAPI
>>
>> +MmCommunicationPeiInitialize (
>>
>> +  IN       EFI_PEI_FILE_HANDLE  FileHandle,
>>
>> +  IN CONST EFI_PEI_SERVICES     **PeiServices
>>
>> +  );
>>
>> +
>>
>> +/**
>>
>> +  MmCommunicationPeim
>>
>> +  Communicates with a registered handler.
>>
>> +  This function provides a service to send and receive messages from a registered UEFI service during PEI.
>>
>> +
>>
>> +  @param[in]      This            The EFI_PEI_MM_COMMUNICATION_PPI instance.
>>
>> +  @param[in, out] CommBuffer      Pointer to the data buffer
>>
>> +  @param[in, out] CommSize        The size of the data buffer being passed in. On exit, the
>>
>> +                                  size of data being returned. Zero if the handler does not
>>
>> +                                  wish to reply with any data.
>>
>> +
>>
>> +  @retval EFI_SUCCESS             The message was successfully posted.
>>
>> +  @retval EFI_INVALID_PARAMETER   CommBuffer was NULL or *CommSize does not match
>>
>> +                                  MessageLength + sizeof (EFI_MM_COMMUNICATE_HEADER).
>>
>> +  @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
>>
>> +MmCommunicationPeim (
>>
>> +  IN CONST EFI_PEI_MM_COMMUNICATION_PPI  *This,
>>
>> +  IN OUT VOID                            *CommBuffer,
>>
>> +  IN OUT UINTN                           *CommSize
>>
>> +  );
>>
>> +
>>
>> +#endif /* MM_COMMUNICATION_PEI_H_ */
>>
>> diff --git a/ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.inf b/ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.inf
>> new file mode 100644
>> index 000000000000..f4e359dafd75
>> --- /dev/null
>> +++ b/ArmPkg/Drivers/MmCommunicationPei/MmCommunicationPei.inf
>> @@ -0,0 +1,41 @@
>> +## @file -- MmCommunicationPei.inf
>>
>> +#  PEI MM Communicate driver
>>
>> +#
>>
>> +#  Copyright (c) 2016 - 2021, Arm Limited. All rights reserved.<BR>
>>
>> +#  Copyright (c) Microsoft Corporation.
>>
>> +#  SPDX-License-Identifier: BSD-2-Clause-Patent
>>
>> +##
>>
>> +
>>
>> +[Defines]
>>
>> +  INF_VERSION                    = 0x00010005
> [SAMI] The version should be |0x0001001B. See 
> https://github.com/tianocore-docs/edk2-InfSpecification/blob/master/3_edk_ii_inf_file_format/34_%5Bdefines%5D_section.md
> |
>> +  BASE_NAME                      = MmCommunicationPei
>>
>> +  FILE_GUID                      = 58FFB346-1B75-42C7-AD69-37C652423C1A
>>
>> +  MODULE_TYPE                    = PEIM
>>
>> +  VERSION_STRING                 = 1.0
>>
>> +  ENTRY_POINT                    = MmCommunicationPeiInitialize
>>
>> +
>>
>> +[Sources]
>>
>> +  MmCommunicationPei.c
>>
>> +  MmCommunicationPei.h
>>
>> +
>>
>> +[Packages]
>>
>> +  MdePkg/MdePkg.dec
>>
>> +  MdeModulePkg/MdeModulePkg.dec
>>
>> +  ArmPkg/ArmPkg.dec
>>
>> +
>>
>> +[LibraryClasses]
>>
>> +  DebugLib
>>
>> +  ArmSmcLib
>>
>> +  PeimEntryPoint
>>
>> +  PeiServicesLib
>>
>> +  HobLib
>>
>> +
>>
>> +[Pcd]
>>
>> +  gArmTokenSpaceGuid.PcdMmBufferBase
>>
>> +  gArmTokenSpaceGuid.PcdMmBufferSize
>>
>> +
>>
>> +[Ppis]
>>
>> +  gEfiPeiMmCommunicationPpiGuid     ## PRODUCES
>>
>> +
>>
>> +[Depex]
>>
>> +  TRUE
>>

[-- Attachment #2: Type: text/html, Size: 17492 bytes --]

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: 回复: [edk2-devel] [PATCH v1 2/2] MdeModulePkg: Variable: Introduce MM based variable read service in PEI
  2023-06-25  2:23   ` 回复: [edk2-devel] " gaoliming
@ 2023-06-26 20:10     ` Kun Qin
  2023-06-27  0:53       ` 回复: " gaoliming
  0 siblings, 1 reply; 8+ messages in thread
From: Kun Qin @ 2023-06-26 20:10 UTC (permalink / raw)
  To: devel, gaoliming
  Cc: 'Hao A Wu', 'Jian J Wang', 'Ronny Hansen',
	'Shriram Masanamuthu Chinnathurai',
	'Preshit Harlikar'

Hi Liming,

Thanks for catching that. I have removed the PCD usage and resend the 
patch here:
https://edk2.groups.io/g/devel/message/106372

Could you please let me know if you have any other feedback?

Per your functionality question, yes, the functionality was verified on 
both virtual
and physical ARM platforms. I also added this statement to the v2 cover 
letter.

Thanks,
Kun

On 6/24/2023 7:23 PM, gaoliming via groups.io wrote:
> Kun:
>    Seemly, PcdMaxVariableSize is not used by this module. It can be removed.
>
>    And, has its functionality been verified in the real platform?
>
> Thanks
> Liming
>> -----邮件原件-----
>> 发件人: devel@edk2.groups.io <devel@edk2.groups.io> 代表 Kun Qin
>> 发送时间: 2023年6月9日 4:45
>> 收件人: devel@edk2.groups.io
>> 抄送: Hao A Wu <hao.a.wu@intel.com>; Liming Gao
>> <gaoliming@byosoft.com.cn>; Jian J Wang <jian.j.wang@intel.com>; Ronny
>> Hansen <hansen.ronny@microsoft.com>; Shriram Masanamuthu
>> Chinnathurai <shriramma@microsoft.com>; Preshit Harlikar
>> <pharlikar@microsoft.com>
>> 主题: [edk2-devel] [PATCH v1 2/2] MdeModulePkg: Variable: Introduce MM
>> based variable read service in PEI
>>
>> From: Kun Qin <kuqin@microsoft.com>
>>
>> REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4464
>>
>> This change introduced the Standalone MM based variable read capability
>> in PEI phase for applicable platforms (such as ARM platforms).
>>
>> Similar to the x86 counterpart, MM communicate PPI is used to request
>> variable information from Standalone MM environment.
>>
>> Cc: Hao A Wu <hao.a.wu@intel.com>
>> Cc: Liming Gao <gaoliming@byosoft.com.cn>
>> Cc: Jian J Wang <jian.j.wang@intel.com>
>>
>> Co-authored-by: Ronny Hansen <hansen.ronny@microsoft.com>
>> Co-authored-by: Shriram Masanamuthu Chinnathurai
>> <shriramma@microsoft.com>
>> Co-authored-by: Preshit Harlikar <pharlikar@microsoft.com>
>> Signed-off-by: Kun Qin <kuqin@microsoft.com>
>> ---
>>   MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.c   |
>> 381 ++++++++++++++++++++
>>   MdeModulePkg/MdeModulePkg.dsc
>> |   1 +
>>   MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.h   |
>> 134 +++++++
>>   MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.inf |
>> 43 +++
>>   4 files changed, 559 insertions(+)
>>
>> diff --git
>> a/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.c
>> b/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.c
>> new file mode 100644
>> index 000000000000..4f937e22e89e
>> --- /dev/null
>> +++ b/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.c
>> @@ -0,0 +1,381 @@
>> +/** @file -- MmVariablePei.c
>>
>> +  Provides interface for reading Secure System Variables during PEI.
>>
>> +
>>
>> +  Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
>>
>> +  Copyright (c) Microsoft Corporation.<BR>
>>
>> +  SPDX-License-Identifier: BSD-2-Clause-Patent
>>
>> +**/
>>
>> +
>>
>> +#include "MmVariablePei.h"
>>
>> +
>>
>> +#define MM_VARIABLE_COMM_BUFFER_OFFSET
>> (SMM_COMMUNICATE_HEADER_SIZE +
>> SMM_VARIABLE_COMMUNICATE_HEADER_SIZE)
>>
>> +
>>
>> +//
>>
>> +// Module globals
>>
>> +//
>>
>> +EFI_PEI_READ_ONLY_VARIABLE2_PPI  mPeiSecureVariableRead = {
>>
>> +  PeiMmGetVariable,
>>
>> +  PeiMmGetNextVariableName
>>
>> +};
>>
>> +
>>
>> +EFI_PEI_PPI_DESCRIPTOR  mPeiMmVariablePpi = {
>>
>> +  (EFI_PEI_PPI_DESCRIPTOR_PPI |
>> EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
>>
>> +  &gEfiPeiReadOnlyVariable2PpiGuid,
>>
>> +  &mPeiSecureVariableRead
>>
>> +};
>>
>> +
>>
>> +/**
>>
>> +  Entry point of PEI Secure Variable read driver
>>
>> +
>>
>> +  @param  FileHandle   Handle of the file being invoked.
>>
>> +                       Type EFI_PEI_FILE_HANDLE is defined in
>> FfsFindNextFile().
>>
>> +  @param  PeiServices  General purpose services available to every
>> PEIM.
>>
>> +
>>
>> +  @retval EFI_SUCCESS  If the interface could be successfully installed
>>
>> +  @retval Others       Returned from PeiServicesInstallPpi()
>>
>> +**/
>>
>> +EFI_STATUS
>>
>> +EFIAPI
>>
>> +PeiMmVariableInitialize (
>>
>> +  IN       EFI_PEI_FILE_HANDLE  FileHandle,
>>
>> +  IN CONST EFI_PEI_SERVICES     **PeiServices
>>
>> +  )
>>
>> +{
>>
>> +  return PeiServicesInstallPpi (&mPeiMmVariablePpi);
>>
>> +}
>>
>> +
>>
>> +/**
>>
>> +  Helper function to populate MM communicate header and variable
>> communicate header
>>
>> +  and then communicate to PEI.
>>
>> +
>>
>> +  @param[in, out] CommunicateBuffer       Size of the variable name.
>>
>> +  @param[in]      CommunicateBufferSize   The entire buffer size to be
>> sent to MM.
>>
>> +  @param[in]      Function                The MM variable function
>> value.
>>
>> +
>>
>> +  @retval EFI_INVALID_PARAMETER      Invalid parameter.
>>
>> +  @retval EFI_SUCCESS                Find the specified variable.
>>
>> +  @retval Others                     Errors returned by MM
>> communicate or variable service.
>>
>> +
>>
>> +**/
>>
>> +EFI_STATUS
>>
>> +PopulateHeaderAndCommunicate (
>>
>> +  IN OUT  UINT8  *CommunicateBuffer,
>>
>> +  IN UINTN       CommunicateBufferSize,
>>
>> +  IN UINTN       Function
>>
>> +  )
>>
>> +{
>>
>> +  EFI_STATUS                       Status;
>>
>> +  EFI_PEI_MM_COMMUNICATION_PPI     *MmCommunicationPpi;
>>
>> +  EFI_MM_COMMUNICATE_HEADER        *MmCommunicateHeader;
>>
>> +  SMM_VARIABLE_COMMUNICATE_HEADER  *MmVarCommsHeader;
>>
>> +
>>
>> +  // Minimal sanity check
>>
>> +  if ((CommunicateBuffer == NULL) ||
>>
>> +      (CommunicateBufferSize <
>> MM_VARIABLE_COMM_BUFFER_OFFSET))
>>
>> +  {
>>
>> +    Status = EFI_INVALID_PARAMETER;
>>
>> +    DEBUG ((DEBUG_ERROR, "%a: Invalid incoming parameters: %p and
>> 0x%x\n", __func__, CommunicateBuffer, CommunicateBufferSize));
>>
>> +    goto Exit;
>>
>> +  }
>>
>> +
>>
>> +  if ((Function !=
>> SMM_VARIABLE_FUNCTION_GET_NEXT_VARIABLE_NAME) &&
>>
>> +      (Function != SMM_VARIABLE_FUNCTION_GET_VARIABLE))
>>
>> +  {
>>
>> +    Status = EFI_INVALID_PARAMETER;
>>
>> +    DEBUG ((DEBUG_ERROR, "%a: Invalid function value: 0x%x\n",
>> __func__, Function));
>>
>> +    goto Exit;
>>
>> +  }
>>
>> +
>>
>> +  Status = PeiServicesLocatePpi (&gEfiPeiMmCommunicationPpiGuid, 0,
>> NULL, (VOID **)&MmCommunicationPpi);
>>
>> +  if (EFI_ERROR (Status)) {
>>
>> +    DEBUG ((DEBUG_ERROR, "%a: Failed to locate PEI MM Communication
>> PPI: %r\n", __func__, Status));
>>
>> +    goto Exit;
>>
>> +  }
>>
>> +
>>
>> +  // Zero the entire Communication Buffer Header
>>
>> +  MmCommunicateHeader = (EFI_MM_COMMUNICATE_HEADER
>> *)CommunicateBuffer;
>>
>> +
>>
>> +  ZeroMem (MmCommunicateHeader,
>> SMM_COMMUNICATE_HEADER_SIZE);
>>
>> +
>>
>> +  // Use gEfiSmmVariableProtocolGuid to request the MM variable service
>> in Standalone MM
>>
>> +  CopyMem ((VOID *)&MmCommunicateHeader->HeaderGuid,
>> &gEfiSmmVariableProtocolGuid, sizeof (GUID));
>>
>> +
>>
>> +  // Program the MM header size
>>
>> +  MmCommunicateHeader->MessageLength = CommunicateBufferSize -
>> SMM_COMMUNICATE_HEADER_SIZE;
>>
>> +
>>
>> +  MmVarCommsHeader = (SMM_VARIABLE_COMMUNICATE_HEADER
>> *)(CommunicateBuffer + SMM_COMMUNICATE_HEADER_SIZE);
>>
>> +
>>
>> +  // We are only supporting GetVariable and GetNextVariableName
>>
>> +  MmVarCommsHeader->Function = Function;
>>
>> +
>>
>> +  // Send the MM request using MmCommunicationPei
>>
>> +  Status = MmCommunicationPpi->Communicate (MmCommunicationPpi,
>> CommunicateBuffer, &CommunicateBufferSize);
>>
>> +  if (EFI_ERROR (Status)) {
>>
>> +    // Received an error from MM interface.
>>
>> +    DEBUG ((DEBUG_ERROR, "%a - MM Interface Error: %r\n", __func__,
>> Status));
>>
>> +    goto Exit;
>>
>> +  }
>>
>> +
>>
>> +  // MM request was successfully handled by the framework.
>>
>> +  // Set status to the Variable Service Status Code
>>
>> +  Status = MmVarCommsHeader->ReturnStatus;
>>
>> +  if (EFI_ERROR (Status)) {
>>
>> +    // We received an error from Variable Service.
>>
>> +    // We cant do anymore so return Status
>>
>> +    if (Status != EFI_BUFFER_TOO_SMALL) {
>>
>> +      DEBUG ((DEBUG_ERROR, "%a - Variable Service Error: %r\n",
>> __func__, Status));
>>
>> +    }
>>
>> +
>>
>> +    goto Exit;
>>
>> +  }
>>
>> +
>>
>> +Exit:
>>
>> +  return Status;
>>
>> +}
>>
>> +
>>
>> +/**
>>
>> +  This service retrieves a variable's value using its name and GUID.
>>
>> +
>>
>> +  This function is using the Secure Variable Store. If the Data
>>
>> +  buffer is too small to hold the contents of the variable, the error
>>
>> +  EFI_BUFFER_TOO_SMALL is returned and DataSize is set to the required
>> buffer
>>
>> +  size to obtain the data.
>>
>> +
>>
>> +  @param  This                  A pointer to this instance of the
>> EFI_PEI_READ_ONLY_VARIABLE2_PPI.
>>
>> +  @param  VariableName          A pointer to a null-terminated string
>> that is the variable's name.
>>
>> +  @param  VariableGuid          A pointer to an EFI_GUID that is the
>> variable's GUID. The combination of
>>
>> +                                VariableGuid and VariableName
>> must be unique.
>>
>> +  @param  Attributes            If non-NULL, on return, points to the
>> variable's attributes.
>>
>> +  @param  DataSize              On entry, points to the size in bytes
>> of the Data buffer.
>>
>> +                                On return, points to the size of the
>> data returned in Data.
>>
>> +  @param  Data                  Points to the buffer which will hold
>> the returned variable value.
>>
>> +                                May be NULL with a zero DataSize in
>> order to determine the size of the buffer needed.
>>
>> +
>>
>> +  @retval EFI_SUCCESS           The variable was read successfully.
>>
>> +  @retval EFI_NOT_FOUND         The variable was not found.
>>
>> +  @retval EFI_BUFFER_TOO_SMALL  The DataSize is too small for the
>> resulting data.
>>
>> +                                DataSize is updated with the size
>> required for
>>
>> +                                the specified variable.
>>
>> +  @retval EFI_INVALID_PARAMETER VariableName, VariableGuid, DataSize
>> or Data is NULL.
>>
>> +  @retval EFI_DEVICE_ERROR      The variable could not be retrieved
>> because of a device error.
>>
>> +
>>
>> +**/
>>
>> +EFI_STATUS
>>
>> +EFIAPI
>>
>> +PeiMmGetVariable (
>>
>> +  IN CONST  EFI_PEI_READ_ONLY_VARIABLE2_PPI *This,
>>
>> +  IN CONST  CHAR16 *VariableName,
>>
>> +  IN CONST  EFI_GUID *VariableGuid,
>>
>> +  OUT       UINT32 *Attributes, OPTIONAL
>>
>> +  IN OUT    UINTN                            *DataSize,
>>
>> +  OUT       VOID                             *Data OPTIONAL
>>
>> +  )
>>
>> +{
>>
>> +  EFI_STATUS                                Status;
>>
>> +  UINTN                                     MessageSize;
>>
>> +  SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE
>> *MmVarAccessHeader;
>>
>> +  UINT8
>> *MmCommunicateBuffer;
>>
>> +  UINTN                                     RequiredPages;
>>
>> +
>>
>> +  // Check input parameters
>>
>> +  if ((VariableName == NULL) || (VariableGuid == NULL) || (DataSize ==
>> NULL)) {
>>
>> +    return EFI_INVALID_PARAMETER;
>>
>> +  }
>>
>> +
>>
>> +  if (VariableName[0] == 0) {
>>
>> +    return EFI_NOT_FOUND;
>>
>> +  }
>>
>> +
>>
>> +  if ((*DataSize > 0) && (Data == NULL)) {
>>
>> +    return EFI_INVALID_PARAMETER;
>>
>> +  }
>>
>> +
>>
>> +  // Allocate required pages to send MM request
>>
>> +  MessageSize = MM_VARIABLE_COMM_BUFFER_OFFSET +
>>
>> +                OFFSET_OF
>> (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) +
>>
>> +                StrSize (VariableName) + *DataSize;
>>
>> +
>>
>> +  RequiredPages       = EFI_SIZE_TO_PAGES (MessageSize);
>>
>> +  MmCommunicateBuffer = (UINT8 *)AllocatePages (RequiredPages);
>>
>> +
>>
>> +  if (MmCommunicateBuffer == NULL) {
>>
>> +    Status = EFI_OUT_OF_RESOURCES;
>>
>> +    DEBUG ((DEBUG_ERROR, "%a: Failed to allocate memory: %r\n",
>> __func__, Status));
>>
>> +    return Status;
>>
>> +  }
>>
>> +
>>
>> +  // Zero the entire Communication Buffer
>>
>> +  ZeroMem (MmCommunicateBuffer, (RequiredPages * EFI_PAGE_SIZE));
>>
>> +
>>
>> +  //
>>
>> +  // Program all payload structure contents
>>
>> +  //
>>
>> +  MmVarAccessHeader =
>> (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE
>> *)(MmCommunicateBuffer + MM_VARIABLE_COMM_BUFFER_OFFSET);
>>
>> +
>>
>> +  // Variable GUID
>>
>> +  CopyMem ((VOID *)&MmVarAccessHeader->Guid, VariableGuid, sizeof
>> (GUID));
>>
>> +
>>
>> +  // Program the max amount of data we accept.
>>
>> +  MmVarAccessHeader->DataSize = *DataSize;
>>
>> +
>>
>> +  // Get size of the variable name
>>
>> +  MmVarAccessHeader->NameSize = StrSize (VariableName);
>>
>> +
>>
>> +  // Populate incoming variable name
>>
>> +  CopyMem ((VOID *)&MmVarAccessHeader->Name, VariableName,
>> MmVarAccessHeader->NameSize);
>>
>> +
>>
>> +  Status = PopulateHeaderAndCommunicate (MmCommunicateBuffer,
>> MessageSize, SMM_VARIABLE_FUNCTION_GET_VARIABLE);
>>
>> +  if (EFI_ERROR (Status)) {
>>
>> +    // We received an error from either communicate or Variable Service.
>>
>> +    if (Status != EFI_BUFFER_TOO_SMALL) {
>>
>> +      DEBUG ((DEBUG_ERROR, "%a - Communite to MM for variable
>> service errored: %r\n", __func__, Status));
>>
>> +    }
>>
>> +
>>
>> +    goto Exit;
>>
>> +  }
>>
>> +
>>
>> +  Status = EFI_SUCCESS;
>>
>> +
>>
>> +  // User provided buffer is too small
>>
>> +  if (*DataSize < MmVarAccessHeader->DataSize) {
>>
>> +    Status = EFI_BUFFER_TOO_SMALL;
>>
>> +  }
>>
>> +
>>
>> +Exit:
>>
>> +  // Check if we need to set Attributes
>>
>> +  if (Attributes != NULL) {
>>
>> +    *Attributes = MmVarAccessHeader->Attributes;
>>
>> +  }
>>
>> +
>>
>> +  *DataSize = MmVarAccessHeader->DataSize;
>>
>> +
>>
>> +  if (Status == EFI_SUCCESS) {
>>
>> +    CopyMem ((VOID *)Data, (UINT8 *)MmVarAccessHeader->Name +
>> MmVarAccessHeader->NameSize, *DataSize);
>>
>> +  }
>>
>> +
>>
>> +  // Free the Communication Buffer
>>
>> +  if (MmCommunicateBuffer != NULL) {
>>
>> +    FreePages (MmCommunicateBuffer, RequiredPages);
>>
>> +  }
>>
>> +
>>
>> +  return Status;
>>
>> +}
>>
>> +
>>
>> +/**
>>
>> +  Return the next variable name and GUID.
>>
>> +
>>
>> +  This function is called multiple times to retrieve the VariableName
>>
>> +  and VariableGuid of all variables currently available in the system.
>>
>> +  On each call, the previous results are passed into the interface,
>>
>> +  and, on return, the interface returns the data for the next
>>
>> +  interface. When the entire variable list has been returned,
>>
>> +  EFI_NOT_FOUND is returned.
>>
>> +
>>
>> +  @param  This              A pointer to this instance of the
>> EFI_PEI_READ_ONLY_VARIABLE2_PPI.
>>
>> +
>>
>> +  @param  VariableNameSize  On entry, points to the size of the buffer
>> pointed to by VariableName.
>>
>> +                            On return, the size of the variable name
>> buffer.
>>
>> +  @param  VariableName      On entry, a pointer to a null-terminated
>> string that is the variable's name.
>>
>> +                            On return, points to the next variable's
>> null-terminated name string.
>>
>> +
>>
>> +  @param  VariableGuid      On entry, a pointer to an EFI_GUID that is
>> the variable's GUID.
>>
>> +                            On return, a pointer to the next variable's
>> GUID.
>>
>> +
>>
>> +  @retval EFI_SUCCESS           The variable was read successfully.
>>
>> +  @retval EFI_NOT_FOUND         The variable could not be found.
>>
>> +  @retval EFI_BUFFER_TOO_SMALL  The VariableNameSize is too small
>> for the resulting
>>
>> +                                data. VariableNameSize is updated
>> with the size
>>
>> +                                required for the specified variable.
>>
>> +  @retval EFI_INVALID_PARAMETER VariableName, VariableGuid or
>>
>> +                                VariableNameSize is NULL.
>>
>> +  @retval EFI_DEVICE_ERROR      The variable could not be retrieved
>> because of a device error.
>>
>> +**/
>>
>> +EFI_STATUS
>>
>> +EFIAPI
>>
>> +PeiMmGetNextVariableName (
>>
>> +  IN CONST  EFI_PEI_READ_ONLY_VARIABLE2_PPI  *This,
>>
>> +  IN OUT UINTN                               *VariableNameSize,
>>
>> +  IN OUT CHAR16                              *VariableName,
>>
>> +  IN OUT EFI_GUID                            *VariableGuid
>>
>> +  )
>>
>> +{
>>
>> +  EFI_STATUS                                       Status;
>>
>> +  UINTN
>> MessageSize;
>>
>> +  UINT8
>> *MmCommunicateBuffer;
>>
>> +  SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME
>> *MmVarGetNextVarHeader;
>>
>> +  UINTN
>> RequiredPages;
>>
>> +
>>
>> +  // Check input parameters
>>
>> +  if ((VariableName == NULL) ||
>>
>> +      (VariableGuid == NULL) ||
>>
>> +      (VariableNameSize == NULL) ||
>>
>> +      (*VariableNameSize == 0))
>>
>> +  {
>>
>> +    return EFI_INVALID_PARAMETER;
>>
>> +  }
>>
>> +
>>
>> +  // Allocate required pages to send MM request
>>
>> +  MessageSize = MM_VARIABLE_COMM_BUFFER_OFFSET +
>>
>> +                OFFSET_OF
>> (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) +
>>
>> +                StrSize (VariableName) + *VariableNameSize;
>>
>> +
>>
>> +  RequiredPages       = EFI_SIZE_TO_PAGES (MessageSize);
>>
>> +  MmCommunicateBuffer = (UINT8 *)AllocatePages (RequiredPages);
>>
>> +
>>
>> +  if (MmCommunicateBuffer == NULL) {
>>
>> +    Status = EFI_OUT_OF_RESOURCES;
>>
>> +    DEBUG ((DEBUG_ERROR, "%a: Failed to allocate memory: %r\n",
>> __func__, Status));
>>
>> +    return Status;
>>
>> +  }
>>
>> +
>>
>> +  // Zero the entire Communication Buffer
>>
>> +  ZeroMem (MmCommunicateBuffer, (RequiredPages * EFI_PAGE_SIZE));
>>
>> +
>>
>> +  //
>>
>> +  // Program all payload structure contents
>>
>> +  //
>>
>> +  MmVarGetNextVarHeader =
>> (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME
>> *)(MmCommunicateBuffer + MM_VARIABLE_COMM_BUFFER_OFFSET);
>>
>> +
>>
>> +  // Variable GUID
>>
>> +  CopyMem ((VOID *)&MmVarGetNextVarHeader->Guid, VariableGuid,
>> sizeof (GUID));
>>
>> +
>>
>> +  // Program the maximal length of name we can accept.
>>
>> +  MmVarGetNextVarHeader->NameSize = *VariableNameSize;
>>
>> +
>>
>> +  // Populate incoming variable name
>>
>> +  CopyMem ((VOID *)&MmVarGetNextVarHeader->Name, VariableName,
>> MmVarGetNextVarHeader->NameSize);
>>
>> +
>>
>> +  // Send the MM request using MmCommunicationPei
>>
>> +  Status = PopulateHeaderAndCommunicate (MmCommunicateBuffer,
>> MessageSize, SMM_VARIABLE_FUNCTION_GET_NEXT_VARIABLE_NAME);
>>
>> +  if (EFI_ERROR (Status)) {
>>
>> +    // We received an error from either communicate or Variable Service.
>>
>> +    if (Status != EFI_BUFFER_TOO_SMALL) {
>>
>> +      DEBUG ((DEBUG_ERROR, "%a - Communite to MM for variable
>> service errored: %r\n", __func__, Status));
>>
>> +    }
>>
>> +
>>
>> +    goto Exit;
>>
>> +  }
>>
>> +
>>
>> +  Status = EFI_SUCCESS;
>>
>> +
>>
>> +  // User provided buffer is too small
>>
>> +  if (*VariableNameSize < MmVarGetNextVarHeader->NameSize) {
>>
>> +    Status = EFI_BUFFER_TOO_SMALL;
>>
>> +  }
>>
>> +
>>
>> +Exit:
>>
>> +  // Update the name size to be returned
>>
>> +  *VariableNameSize = MmVarGetNextVarHeader->NameSize;
>>
>> +
>>
>> +  if (Status == EFI_SUCCESS) {
>>
>> +    CopyMem ((VOID *)VariableName, (UINT8
>> *)MmVarGetNextVarHeader->Name, *VariableNameSize);
>>
>> +    CopyMem ((VOID *)VariableGuid, (UINT8
>> *)&(MmVarGetNextVarHeader->Guid), sizeof (EFI_GUID));
>>
>> +  }
>>
>> +
>>
>> +  // Free the Communication Buffer
>>
>> +  if (MmCommunicateBuffer != NULL) {
>>
>> +    FreePages (MmCommunicateBuffer, RequiredPages);
>>
>> +  }
>>
>> +
>>
>> +  return Status;
>>
>> +}
>>
>> diff --git a/MdeModulePkg/MdeModulePkg.dsc
>> b/MdeModulePkg/MdeModulePkg.dsc
>> index 5b1f50e9c084..1aedfe280ae1 100644
>> --- a/MdeModulePkg/MdeModulePkg.dsc
>> +++ b/MdeModulePkg/MdeModulePkg.dsc
>> @@ -400,6 +400,7 @@ [Components]
>>     MdeModulePkg/Application/VariableInfo/VariableInfo.inf
>>
>>
>> MdeModulePkg/Universal/FaultTolerantWritePei/FaultTolerantWritePei.inf
>>
>>     MdeModulePkg/Universal/Variable/Pei/VariablePei.inf
>>
>> +  MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.inf
>>
>>     MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
>>
>>     MdeModulePkg/Universal/TimestampDxe/TimestampDxe.inf
>>
>>
>> MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf
>>
>> diff --git
>> a/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.h
>> b/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.h
>> new file mode 100644
>> index 000000000000..0feed8cd1cb6
>> --- /dev/null
>> +++ b/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.h
>> @@ -0,0 +1,134 @@
>> +/** @file -- MmVariablePei.h
>>
>> +  Provides interface for reading Secure System Variables during PEI.
>>
>> +
>>
>> +  Copyright (c) Microsoft Corporation.
>>
>> +  SPDX-License-Identifier: BSD-2-Clause-Patent
>>
>> +**/
>>
>> +
>>
>> +#ifndef PEI_MM_VARIABLE_LIB_H_
>>
>> +#define PEI_MM_VARIABLE_LIB_H_
>>
>> +
>>
>> +#include <PiPei.h>
>>
>> +#include <Uefi/UefiSpec.h>
>>
>> +
>>
>> +#include <Library/DebugLib.h>
>>
>> +#include <Library/PcdLib.h>
>>
>> +#include <Library/BaseMemoryLib.h>
>>
>> +#include <Library/PeimEntryPoint.h>
>>
>> +#include <Library/PeiServicesLib.h>
>>
>> +#include <Library/MemoryAllocationLib.h>
>>
>> +#include <Library/HobLib.h>
>>
>> +
>>
>> +#include <Guid/SmmVariableCommon.h>
>>
>> +
>>
>> +#include <Ppi/ReadOnlyVariable2.h>
>>
>> +#include <Ppi/MmCommunication.h>
>>
>> +
>>
>> +#include <Protocol/SmmVariable.h>
>>
>> +#include <Protocol/MmCommunication.h>
>>
>> +
>>
>> +/**
>>
>> +  Entry point of PEI Secure Variable read driver
>>
>> +
>>
>> +  @param  FileHandle   Handle of the file being invoked.
>>
>> +                       Type EFI_PEI_FILE_HANDLE is defined in
>> FfsFindNextFile().
>>
>> +  @param  PeiServices  General purpose services available to every
>> PEIM.
>>
>> +
>>
>> +  @retval EFI_SUCCESS  If the interface could be successfully installed
>>
>> +  @retval Others       Returned from PeiServicesInstallPpi()
>>
>> +**/
>>
>> +EFI_STATUS
>>
>> +EFIAPI
>>
>> +PeiMmVariableInitialize (
>>
>> +  IN       EFI_PEI_FILE_HANDLE  FileHandle,
>>
>> +  IN CONST EFI_PEI_SERVICES     **PeiServices
>>
>> +  );
>>
>> +
>>
>> +/**
>>
>> +
>>
>> +  This function enables the read of Secure Variables during PEI.
>>
>> +
>>
>> +  This function is using the Secure Variable Store.If the Data
>>
>> +  buffer is too small to hold the contents of the variable, the error
>>
>> +  EFI_BUFFER_TOO_SMALL is returned and DataSize is set to the required
>> buffer
>>
>> +  size to obtain the data.
>>
>> +
>>
>> +  The function performs the following:
>>
>> +
>>
>> +  1) Creates an MM request
>>
>> +  2) Fills out the following data structures for the Secure Variable
> Service
>> +
>> SMM_VARIABLE_COMMUNICATE_HEADER/SMM_VARIABLE_COMMUNICAT
>> E_ACCESS_VARIABLE
>>
>> +  3) Adds the MM data structures to the MM request.
>>
>> +  4) Sends the MM request to EL3 using MmCommunicationPeiLib.
>>
>> +  5) The MM request is sent to S-EL0.
>>
>> +  6) The MM request is then handled by the registered handler with GUID:
>> gEfiSmmVariableProtocolGuid
>>
>> +
>>
>> +  @param  This                  A pointer to this instance of the
>> EFI_PEI_READ_ONLY_VARIABLE2_PPI.
>>
>> +  @param  VariableName          A pointer to a null-terminated string
>> that is the variable's name.
>>
>> +  @param  VariableGuid          A pointer to an EFI_GUID that is the
>> variable's GUID. The combination of
>>
>> +                                VariableGuid and VariableName
>> must be unique.
>>
>> +  @param  Attributes            If non-NULL, on return, points to the
>> variable's attributes.
>>
>> +  @param  DataSize              On entry, points to the size in bytes
>> of the Data buffer.
>>
>> +                                On return, points to the size of the
>> data returned in Data.
>>
>> +  @param  Data                  Points to the buffer which will hold
>> the returned variable value.
>>
>> +                                May be NULL with a zero DataSize in
>> order to determine the size of the buffer needed.
>>
>> +
>>
>> +  @retval EFI_SUCCESS           The variable was read successfully.
>>
>> +  @retval EFI_NOT_FOUND         The variable was not found.
>>
>> +  @retval EFI_BUFFER_TOO_SMALL  The DataSize is too small for the
>> resulting data.
>>
>> +                                DataSize is updated with the size
>> required for
>>
>> +                                the specified variable.
>>
>> +  @retval EFI_INVALID_PARAMETER VariableName, VariableGuid, DataSize
>> or Data is NULL.
>>
>> +  @retval EFI_DEVICE_ERROR      The variable could not be retrieved
>> because of a device error.
>>
>> +
>>
>> +**/
>>
>> +EFI_STATUS
>>
>> +EFIAPI
>>
>> +PeiMmGetVariable (
>>
>> +  IN CONST  EFI_PEI_READ_ONLY_VARIABLE2_PPI  *This,
>>
>> +  IN CONST  CHAR16                           *VariableName,
>>
>> +  IN CONST  EFI_GUID                         *VariableGuid,
>>
>> +  OUT       UINT32                           *Attributes,
>>
>> +  IN OUT    UINTN                            *DataSize,
>>
>> +  OUT       VOID                             *Data OPTIONAL
>>
>> +  );
>>
>> +
>>
>> +/**
>>
>> +  Return the next variable name and GUID.
>>
>> +
>>
>> +  This function is called multiple times to retrieve the VariableName
>>
>> +  and VariableGuid of all variables currently available in the system.
>>
>> +  On each call, the previous results are passed into the interface,
>>
>> +  and, on return, the interface returns the data for the next
>>
>> +  interface. When the entire variable list has been returned,
>>
>> +  EFI_NOT_FOUND is returned.
>>
>> +
>>
>> +  @param  This              A pointer to this instance of the
>> EFI_PEI_READ_ONLY_VARIABLE2_PPI.
>>
>> +
>>
>> +  @param  VariableNameSize  On entry, points to the size of the buffer
>> pointed to by VariableName.
>>
>> +                            On return, the size of the variable name
>> buffer.
>>
>> +  @param  VariableName      On entry, a pointer to a null-terminated
>> string that is the variable's name.
>>
>> +                            On return, points to the next variable's
>> null-terminated name string.
>>
>> +
>>
>> +  @param  VariableGuid      On entry, a pointer to an EFI_GUID that is
>> the variable's GUID.
>>
>> +                            On return, a pointer to the next variable's
>> GUID.
>>
>> +
>>
>> +  @retval EFI_SUCCESS           The variable was read successfully.
>>
>> +  @retval EFI_NOT_FOUND         The variable could not be found.
>>
>> +  @retval EFI_BUFFER_TOO_SMALL  The VariableNameSize is too small
>> for the resulting
>>
>> +                                data. VariableNameSize is updated
>> with the size
>>
>> +                                required for the specified variable.
>>
>> +  @retval EFI_INVALID_PARAMETER VariableName, VariableGuid or
>>
>> +                                VariableNameSize is NULL.
>>
>> +  @retval EFI_DEVICE_ERROR      The variable could not be retrieved
>> because of a device error.
>>
>> +**/
>>
>> +EFI_STATUS
>>
>> +EFIAPI
>>
>> +PeiMmGetNextVariableName (
>>
>> +  IN CONST  EFI_PEI_READ_ONLY_VARIABLE2_PPI  *This,
>>
>> +  IN OUT UINTN                               *VariableNameSize,
>>
>> +  IN OUT CHAR16                              *VariableName,
>>
>> +  IN OUT EFI_GUID                            *VariableGuid
>>
>> +  );
>>
>> +
>>
>> +#endif /* PEI_MM_VARIABLE_LIB_H_ */
>>
>> diff --git
>> a/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.inf
>> b/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.inf
>> new file mode 100644
>> index 000000000000..d122703e9b5d
>> --- /dev/null
>> +++ b/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.inf
>> @@ -0,0 +1,43 @@
>> +## @file -- MmVariablePei.inf
>>
>> +# Provides interface for reading Secure System Variables during PEI.
>>
>> +#
>>
>> +# Copyright (c) Microsoft Corporation.
>>
>> +# SPDX-License-Identifier: BSD-2-Clause-Patent
>>
>> +##
>>
>> +
>>
>> +
>>
>> +[Defines]
>>
>> +  INF_VERSION                    = 0x00010005
>>
>> +  BASE_NAME                      = MmVariablePei
>>
>> +  FILE_GUID                      =
>> CD660A87-454B-4346-A35C-3D89BF8ECFAF
>>
>> +  MODULE_TYPE                    = PEIM
>>
>> +  VERSION_STRING                 = 1.0
>>
>> +  ENTRY_POINT                    = PeiMmVariableInitialize
>>
>> +
>>
>> +[Sources]
>>
>> +  MmVariablePei.c
>>
>> +  MmVariablePei.h
>>
>> +
>>
>> +[Packages]
>>
>> +  MdePkg/MdePkg.dec
>>
>> +  MdeModulePkg/MdeModulePkg.dec
>>
>> +
>>
>> +[LibraryClasses]
>>
>> +  PcdLib
>>
>> +  PeiServicesLib
>>
>> +  PeimEntryPoint
>>
>> +  MemoryAllocationLib
>>
>> +  HobLib
>>
>> +
>>
>> +[Pcd]
>>
>> +  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize
>>
>> +
>>
>> +[Protocols]
>>
>> +  gEfiSmmVariableProtocolGuid             ## CONSUMES
>>
>> +
>>
>> +[Ppis]
>>
>> +  gEfiPeiReadOnlyVariable2PpiGuid         ## PRODUCES
>>
>> +  gEfiPeiMmCommunicationPpiGuid           ## CONSUMES
>>
>> +
>>
>> +[Depex]
>>
>> +  gEfiPeiMmCommunicationPpiGuid
>>
>> --
>> 2.40.1.windows.1
>>
>>
>>
>> -=-=-=-=-=-=
>> Groups.io Links: You receive all messages sent to this group.
>> View/Reply Online (#105956):
>> https://edk2.groups.io/g/devel/message/105956
>> Mute This Topic: https://groups.io/mt/99415826/4905953
>> Group Owner: devel+owner@edk2.groups.io
>> Unsubscribe: https://edk2.groups.io/g/devel/unsub
>> [gaoliming@byosoft.com.cn]
>> -=-=-=-=-=-=
>>
>
>
>
>
> 
>
>

^ permalink raw reply	[flat|nested] 8+ messages in thread

* 回复: 回复: [edk2-devel] [PATCH v1 2/2] MdeModulePkg: Variable: Introduce MM based variable read service in PEI
  2023-06-26 20:10     ` Kun Qin
@ 2023-06-27  0:53       ` gaoliming
  0 siblings, 0 replies; 8+ messages in thread
From: gaoliming @ 2023-06-27  0:53 UTC (permalink / raw)
  To: devel, kuqin12
  Cc: 'Hao A Wu', 'Jian J Wang', 'Ronny Hansen',
	'Shriram Masanamuthu Chinnathurai',
	'Preshit Harlikar'

Kun:
  Thanks for your update. I have no other comments for this patch. Reviewed-by: Liming Gao <gaoliming@byosoft.com.cn>

Thanks
Liming
> -----邮件原件-----
> 发件人: devel@edk2.groups.io <devel@edk2.groups.io> 代表 Kun Qin
> 发送时间: 2023年6月27日 4:11
> 收件人: devel@edk2.groups.io; gaoliming@byosoft.com.cn
> 抄送: 'Hao A Wu' <hao.a.wu@intel.com>; 'Jian J Wang'
> <jian.j.wang@intel.com>; 'Ronny Hansen' <hansen.ronny@microsoft.com>;
> 'Shriram Masanamuthu Chinnathurai' <shriramma@microsoft.com>; 'Preshit
> Harlikar' <pharlikar@microsoft.com>
> 主题: Re: 回复: [edk2-devel] [PATCH v1 2/2] MdeModulePkg: Variable:
> Introduce MM based variable read service in PEI
> 
> Hi Liming,
> 
> Thanks for catching that. I have removed the PCD usage and resend the
> patch here:
> https://edk2.groups.io/g/devel/message/106372
> 
> Could you please let me know if you have any other feedback?
> 
> Per your functionality question, yes, the functionality was verified on
> both virtual
> and physical ARM platforms. I also added this statement to the v2 cover
> letter.
> 
> Thanks,
> Kun
> 
> On 6/24/2023 7:23 PM, gaoliming via groups.io wrote:
> > Kun:
> >    Seemly, PcdMaxVariableSize is not used by this module. It can be
> removed.
> >
> >    And, has its functionality been verified in the real platform?
> >
> > Thanks
> > Liming
> >> -----邮件原件-----
> >> 发件人: devel@edk2.groups.io <devel@edk2.groups.io> 代表 Kun Qin
> >> 发送时间: 2023年6月9日 4:45
> >> 收件人: devel@edk2.groups.io
> >> 抄送: Hao A Wu <hao.a.wu@intel.com>; Liming Gao
> >> <gaoliming@byosoft.com.cn>; Jian J Wang <jian.j.wang@intel.com>;
> Ronny
> >> Hansen <hansen.ronny@microsoft.com>; Shriram Masanamuthu
> >> Chinnathurai <shriramma@microsoft.com>; Preshit Harlikar
> >> <pharlikar@microsoft.com>
> >> 主题: [edk2-devel] [PATCH v1 2/2] MdeModulePkg: Variable: Introduce
> MM
> >> based variable read service in PEI
> >>
> >> From: Kun Qin <kuqin@microsoft.com>
> >>
> >> REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4464
> >>
> >> This change introduced the Standalone MM based variable read capability
> >> in PEI phase for applicable platforms (such as ARM platforms).
> >>
> >> Similar to the x86 counterpart, MM communicate PPI is used to request
> >> variable information from Standalone MM environment.
> >>
> >> Cc: Hao A Wu <hao.a.wu@intel.com>
> >> Cc: Liming Gao <gaoliming@byosoft.com.cn>
> >> Cc: Jian J Wang <jian.j.wang@intel.com>
> >>
> >> Co-authored-by: Ronny Hansen <hansen.ronny@microsoft.com>
> >> Co-authored-by: Shriram Masanamuthu Chinnathurai
> >> <shriramma@microsoft.com>
> >> Co-authored-by: Preshit Harlikar <pharlikar@microsoft.com>
> >> Signed-off-by: Kun Qin <kuqin@microsoft.com>
> >> ---
> >>   MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.c
> |
> >> 381 ++++++++++++++++++++
> >>   MdeModulePkg/MdeModulePkg.dsc
> >> |   1 +
> >>   MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.h
> |
> >> 134 +++++++
> >>   MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.inf
> |
> >> 43 +++
> >>   4 files changed, 559 insertions(+)
> >>
> >> diff --git
> >> a/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.c
> >> b/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.c
> >> new file mode 100644
> >> index 000000000000..4f937e22e89e
> >> --- /dev/null
> >> +++
> b/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.c
> >> @@ -0,0 +1,381 @@
> >> +/** @file -- MmVariablePei.c
> >>
> >> +  Provides interface for reading Secure System Variables during PEI.
> >>
> >> +
> >>
> >> +  Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
> >>
> >> +  Copyright (c) Microsoft Corporation.<BR>
> >>
> >> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> >>
> >> +**/
> >>
> >> +
> >>
> >> +#include "MmVariablePei.h"
> >>
> >> +
> >>
> >> +#define MM_VARIABLE_COMM_BUFFER_OFFSET
> >> (SMM_COMMUNICATE_HEADER_SIZE +
> >> SMM_VARIABLE_COMMUNICATE_HEADER_SIZE)
> >>
> >> +
> >>
> >> +//
> >>
> >> +// Module globals
> >>
> >> +//
> >>
> >> +EFI_PEI_READ_ONLY_VARIABLE2_PPI  mPeiSecureVariableRead = {
> >>
> >> +  PeiMmGetVariable,
> >>
> >> +  PeiMmGetNextVariableName
> >>
> >> +};
> >>
> >> +
> >>
> >> +EFI_PEI_PPI_DESCRIPTOR  mPeiMmVariablePpi = {
> >>
> >> +  (EFI_PEI_PPI_DESCRIPTOR_PPI |
> >> EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
> >>
> >> +  &gEfiPeiReadOnlyVariable2PpiGuid,
> >>
> >> +  &mPeiSecureVariableRead
> >>
> >> +};
> >>
> >> +
> >>
> >> +/**
> >>
> >> +  Entry point of PEI Secure Variable read driver
> >>
> >> +
> >>
> >> +  @param  FileHandle   Handle of the file being invoked.
> >>
> >> +                       Type EFI_PEI_FILE_HANDLE is defined in
> >> FfsFindNextFile().
> >>
> >> +  @param  PeiServices  General purpose services available to every
> >> PEIM.
> >>
> >> +
> >>
> >> +  @retval EFI_SUCCESS  If the interface could be successfully installed
> >>
> >> +  @retval Others       Returned from PeiServicesInstallPpi()
> >>
> >> +**/
> >>
> >> +EFI_STATUS
> >>
> >> +EFIAPI
> >>
> >> +PeiMmVariableInitialize (
> >>
> >> +  IN       EFI_PEI_FILE_HANDLE  FileHandle,
> >>
> >> +  IN CONST EFI_PEI_SERVICES     **PeiServices
> >>
> >> +  )
> >>
> >> +{
> >>
> >> +  return PeiServicesInstallPpi (&mPeiMmVariablePpi);
> >>
> >> +}
> >>
> >> +
> >>
> >> +/**
> >>
> >> +  Helper function to populate MM communicate header and variable
> >> communicate header
> >>
> >> +  and then communicate to PEI.
> >>
> >> +
> >>
> >> +  @param[in, out] CommunicateBuffer       Size of the variable
> name.
> >>
> >> +  @param[in]      CommunicateBufferSize   The entire buffer size to
> be
> >> sent to MM.
> >>
> >> +  @param[in]      Function                The MM variable
> function
> >> value.
> >>
> >> +
> >>
> >> +  @retval EFI_INVALID_PARAMETER      Invalid parameter.
> >>
> >> +  @retval EFI_SUCCESS                Find the specified variable.
> >>
> >> +  @retval Others                     Errors returned by MM
> >> communicate or variable service.
> >>
> >> +
> >>
> >> +**/
> >>
> >> +EFI_STATUS
> >>
> >> +PopulateHeaderAndCommunicate (
> >>
> >> +  IN OUT  UINT8  *CommunicateBuffer,
> >>
> >> +  IN UINTN       CommunicateBufferSize,
> >>
> >> +  IN UINTN       Function
> >>
> >> +  )
> >>
> >> +{
> >>
> >> +  EFI_STATUS                       Status;
> >>
> >> +  EFI_PEI_MM_COMMUNICATION_PPI     *MmCommunicationPpi;
> >>
> >> +  EFI_MM_COMMUNICATE_HEADER
> *MmCommunicateHeader;
> >>
> >> +  SMM_VARIABLE_COMMUNICATE_HEADER  *MmVarCommsHeader;
> >>
> >> +
> >>
> >> +  // Minimal sanity check
> >>
> >> +  if ((CommunicateBuffer == NULL) ||
> >>
> >> +      (CommunicateBufferSize <
> >> MM_VARIABLE_COMM_BUFFER_OFFSET))
> >>
> >> +  {
> >>
> >> +    Status = EFI_INVALID_PARAMETER;
> >>
> >> +    DEBUG ((DEBUG_ERROR, "%a: Invalid incoming parameters: %p and
> >> 0x%x\n", __func__, CommunicateBuffer, CommunicateBufferSize));
> >>
> >> +    goto Exit;
> >>
> >> +  }
> >>
> >> +
> >>
> >> +  if ((Function !=
> >> SMM_VARIABLE_FUNCTION_GET_NEXT_VARIABLE_NAME) &&
> >>
> >> +      (Function != SMM_VARIABLE_FUNCTION_GET_VARIABLE))
> >>
> >> +  {
> >>
> >> +    Status = EFI_INVALID_PARAMETER;
> >>
> >> +    DEBUG ((DEBUG_ERROR, "%a: Invalid function value: 0x%x\n",
> >> __func__, Function));
> >>
> >> +    goto Exit;
> >>
> >> +  }
> >>
> >> +
> >>
> >> +  Status = PeiServicesLocatePpi (&gEfiPeiMmCommunicationPpiGuid, 0,
> >> NULL, (VOID **)&MmCommunicationPpi);
> >>
> >> +  if (EFI_ERROR (Status)) {
> >>
> >> +    DEBUG ((DEBUG_ERROR, "%a: Failed to locate PEI MM
> Communication
> >> PPI: %r\n", __func__, Status));
> >>
> >> +    goto Exit;
> >>
> >> +  }
> >>
> >> +
> >>
> >> +  // Zero the entire Communication Buffer Header
> >>
> >> +  MmCommunicateHeader = (EFI_MM_COMMUNICATE_HEADER
> >> *)CommunicateBuffer;
> >>
> >> +
> >>
> >> +  ZeroMem (MmCommunicateHeader,
> >> SMM_COMMUNICATE_HEADER_SIZE);
> >>
> >> +
> >>
> >> +  // Use gEfiSmmVariableProtocolGuid to request the MM variable
> service
> >> in Standalone MM
> >>
> >> +  CopyMem ((VOID *)&MmCommunicateHeader->HeaderGuid,
> >> &gEfiSmmVariableProtocolGuid, sizeof (GUID));
> >>
> >> +
> >>
> >> +  // Program the MM header size
> >>
> >> +  MmCommunicateHeader->MessageLength = CommunicateBufferSize -
> >> SMM_COMMUNICATE_HEADER_SIZE;
> >>
> >> +
> >>
> >> +  MmVarCommsHeader = (SMM_VARIABLE_COMMUNICATE_HEADER
> >> *)(CommunicateBuffer + SMM_COMMUNICATE_HEADER_SIZE);
> >>
> >> +
> >>
> >> +  // We are only supporting GetVariable and GetNextVariableName
> >>
> >> +  MmVarCommsHeader->Function = Function;
> >>
> >> +
> >>
> >> +  // Send the MM request using MmCommunicationPei
> >>
> >> +  Status = MmCommunicationPpi->Communicate
> (MmCommunicationPpi,
> >> CommunicateBuffer, &CommunicateBufferSize);
> >>
> >> +  if (EFI_ERROR (Status)) {
> >>
> >> +    // Received an error from MM interface.
> >>
> >> +    DEBUG ((DEBUG_ERROR, "%a - MM Interface Error: %r\n",
> __func__,
> >> Status));
> >>
> >> +    goto Exit;
> >>
> >> +  }
> >>
> >> +
> >>
> >> +  // MM request was successfully handled by the framework.
> >>
> >> +  // Set status to the Variable Service Status Code
> >>
> >> +  Status = MmVarCommsHeader->ReturnStatus;
> >>
> >> +  if (EFI_ERROR (Status)) {
> >>
> >> +    // We received an error from Variable Service.
> >>
> >> +    // We cant do anymore so return Status
> >>
> >> +    if (Status != EFI_BUFFER_TOO_SMALL) {
> >>
> >> +      DEBUG ((DEBUG_ERROR, "%a - Variable Service Error: %r\n",
> >> __func__, Status));
> >>
> >> +    }
> >>
> >> +
> >>
> >> +    goto Exit;
> >>
> >> +  }
> >>
> >> +
> >>
> >> +Exit:
> >>
> >> +  return Status;
> >>
> >> +}
> >>
> >> +
> >>
> >> +/**
> >>
> >> +  This service retrieves a variable's value using its name and GUID.
> >>
> >> +
> >>
> >> +  This function is using the Secure Variable Store. If the Data
> >>
> >> +  buffer is too small to hold the contents of the variable, the error
> >>
> >> +  EFI_BUFFER_TOO_SMALL is returned and DataSize is set to the
> required
> >> buffer
> >>
> >> +  size to obtain the data.
> >>
> >> +
> >>
> >> +  @param  This                  A pointer to this instance of the
> >> EFI_PEI_READ_ONLY_VARIABLE2_PPI.
> >>
> >> +  @param  VariableName          A pointer to a null-terminated
> string
> >> that is the variable's name.
> >>
> >> +  @param  VariableGuid          A pointer to an EFI_GUID that is
> the
> >> variable's GUID. The combination of
> >>
> >> +                                VariableGuid and VariableName
> >> must be unique.
> >>
> >> +  @param  Attributes            If non-NULL, on return, points to
> the
> >> variable's attributes.
> >>
> >> +  @param  DataSize              On entry, points to the size in
> bytes
> >> of the Data buffer.
> >>
> >> +                                On return, points to the size of
> the
> >> data returned in Data.
> >>
> >> +  @param  Data                  Points to the buffer which will
> hold
> >> the returned variable value.
> >>
> >> +                                May be NULL with a zero
> DataSize in
> >> order to determine the size of the buffer needed.
> >>
> >> +
> >>
> >> +  @retval EFI_SUCCESS           The variable was read successfully.
> >>
> >> +  @retval EFI_NOT_FOUND         The variable was not found.
> >>
> >> +  @retval EFI_BUFFER_TOO_SMALL  The DataSize is too small for the
> >> resulting data.
> >>
> >> +                                DataSize is updated with the size
> >> required for
> >>
> >> +                                the specified variable.
> >>
> >> +  @retval EFI_INVALID_PARAMETER VariableName, VariableGuid,
> DataSize
> >> or Data is NULL.
> >>
> >> +  @retval EFI_DEVICE_ERROR      The variable could not be retrieved
> >> because of a device error.
> >>
> >> +
> >>
> >> +**/
> >>
> >> +EFI_STATUS
> >>
> >> +EFIAPI
> >>
> >> +PeiMmGetVariable (
> >>
> >> +  IN CONST  EFI_PEI_READ_ONLY_VARIABLE2_PPI *This,
> >>
> >> +  IN CONST  CHAR16 *VariableName,
> >>
> >> +  IN CONST  EFI_GUID *VariableGuid,
> >>
> >> +  OUT       UINT32 *Attributes, OPTIONAL
> >>
> >> +  IN OUT    UINTN                            *DataSize,
> >>
> >> +  OUT       VOID                             *Data
> OPTIONAL
> >>
> >> +  )
> >>
> >> +{
> >>
> >> +  EFI_STATUS                                Status;
> >>
> >> +  UINTN                                     MessageSize;
> >>
> >> +  SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE
> >> *MmVarAccessHeader;
> >>
> >> +  UINT8
> >> *MmCommunicateBuffer;
> >>
> >> +  UINTN                                     RequiredPages;
> >>
> >> +
> >>
> >> +  // Check input parameters
> >>
> >> +  if ((VariableName == NULL) || (VariableGuid == NULL) || (DataSize ==
> >> NULL)) {
> >>
> >> +    return EFI_INVALID_PARAMETER;
> >>
> >> +  }
> >>
> >> +
> >>
> >> +  if (VariableName[0] == 0) {
> >>
> >> +    return EFI_NOT_FOUND;
> >>
> >> +  }
> >>
> >> +
> >>
> >> +  if ((*DataSize > 0) && (Data == NULL)) {
> >>
> >> +    return EFI_INVALID_PARAMETER;
> >>
> >> +  }
> >>
> >> +
> >>
> >> +  // Allocate required pages to send MM request
> >>
> >> +  MessageSize = MM_VARIABLE_COMM_BUFFER_OFFSET +
> >>
> >> +                OFFSET_OF
> >> (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) +
> >>
> >> +                StrSize (VariableName) + *DataSize;
> >>
> >> +
> >>
> >> +  RequiredPages       = EFI_SIZE_TO_PAGES (MessageSize);
> >>
> >> +  MmCommunicateBuffer = (UINT8 *)AllocatePages (RequiredPages);
> >>
> >> +
> >>
> >> +  if (MmCommunicateBuffer == NULL) {
> >>
> >> +    Status = EFI_OUT_OF_RESOURCES;
> >>
> >> +    DEBUG ((DEBUG_ERROR, "%a: Failed to allocate memory: %r\n",
> >> __func__, Status));
> >>
> >> +    return Status;
> >>
> >> +  }
> >>
> >> +
> >>
> >> +  // Zero the entire Communication Buffer
> >>
> >> +  ZeroMem (MmCommunicateBuffer, (RequiredPages * EFI_PAGE_SIZE));
> >>
> >> +
> >>
> >> +  //
> >>
> >> +  // Program all payload structure contents
> >>
> >> +  //
> >>
> >> +  MmVarAccessHeader =
> >> (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE
> >> *)(MmCommunicateBuffer + MM_VARIABLE_COMM_BUFFER_OFFSET);
> >>
> >> +
> >>
> >> +  // Variable GUID
> >>
> >> +  CopyMem ((VOID *)&MmVarAccessHeader->Guid, VariableGuid, sizeof
> >> (GUID));
> >>
> >> +
> >>
> >> +  // Program the max amount of data we accept.
> >>
> >> +  MmVarAccessHeader->DataSize = *DataSize;
> >>
> >> +
> >>
> >> +  // Get size of the variable name
> >>
> >> +  MmVarAccessHeader->NameSize = StrSize (VariableName);
> >>
> >> +
> >>
> >> +  // Populate incoming variable name
> >>
> >> +  CopyMem ((VOID *)&MmVarAccessHeader->Name, VariableName,
> >> MmVarAccessHeader->NameSize);
> >>
> >> +
> >>
> >> +  Status = PopulateHeaderAndCommunicate (MmCommunicateBuffer,
> >> MessageSize, SMM_VARIABLE_FUNCTION_GET_VARIABLE);
> >>
> >> +  if (EFI_ERROR (Status)) {
> >>
> >> +    // We received an error from either communicate or Variable
> Service.
> >>
> >> +    if (Status != EFI_BUFFER_TOO_SMALL) {
> >>
> >> +      DEBUG ((DEBUG_ERROR, "%a - Communite to MM for variable
> >> service errored: %r\n", __func__, Status));
> >>
> >> +    }
> >>
> >> +
> >>
> >> +    goto Exit;
> >>
> >> +  }
> >>
> >> +
> >>
> >> +  Status = EFI_SUCCESS;
> >>
> >> +
> >>
> >> +  // User provided buffer is too small
> >>
> >> +  if (*DataSize < MmVarAccessHeader->DataSize) {
> >>
> >> +    Status = EFI_BUFFER_TOO_SMALL;
> >>
> >> +  }
> >>
> >> +
> >>
> >> +Exit:
> >>
> >> +  // Check if we need to set Attributes
> >>
> >> +  if (Attributes != NULL) {
> >>
> >> +    *Attributes = MmVarAccessHeader->Attributes;
> >>
> >> +  }
> >>
> >> +
> >>
> >> +  *DataSize = MmVarAccessHeader->DataSize;
> >>
> >> +
> >>
> >> +  if (Status == EFI_SUCCESS) {
> >>
> >> +    CopyMem ((VOID *)Data, (UINT8 *)MmVarAccessHeader->Name +
> >> MmVarAccessHeader->NameSize, *DataSize);
> >>
> >> +  }
> >>
> >> +
> >>
> >> +  // Free the Communication Buffer
> >>
> >> +  if (MmCommunicateBuffer != NULL) {
> >>
> >> +    FreePages (MmCommunicateBuffer, RequiredPages);
> >>
> >> +  }
> >>
> >> +
> >>
> >> +  return Status;
> >>
> >> +}
> >>
> >> +
> >>
> >> +/**
> >>
> >> +  Return the next variable name and GUID.
> >>
> >> +
> >>
> >> +  This function is called multiple times to retrieve the VariableName
> >>
> >> +  and VariableGuid of all variables currently available in the system.
> >>
> >> +  On each call, the previous results are passed into the interface,
> >>
> >> +  and, on return, the interface returns the data for the next
> >>
> >> +  interface. When the entire variable list has been returned,
> >>
> >> +  EFI_NOT_FOUND is returned.
> >>
> >> +
> >>
> >> +  @param  This              A pointer to this instance of the
> >> EFI_PEI_READ_ONLY_VARIABLE2_PPI.
> >>
> >> +
> >>
> >> +  @param  VariableNameSize  On entry, points to the size of the
> buffer
> >> pointed to by VariableName.
> >>
> >> +                            On return, the size of the variable
> name
> >> buffer.
> >>
> >> +  @param  VariableName      On entry, a pointer to a
> null-terminated
> >> string that is the variable's name.
> >>
> >> +                            On return, points to the next variable's
> >> null-terminated name string.
> >>
> >> +
> >>
> >> +  @param  VariableGuid      On entry, a pointer to an EFI_GUID that
> is
> >> the variable's GUID.
> >>
> >> +                            On return, a pointer to the next
> variable's
> >> GUID.
> >>
> >> +
> >>
> >> +  @retval EFI_SUCCESS           The variable was read successfully.
> >>
> >> +  @retval EFI_NOT_FOUND         The variable could not be found.
> >>
> >> +  @retval EFI_BUFFER_TOO_SMALL  The VariableNameSize is too
> small
> >> for the resulting
> >>
> >> +                                data. VariableNameSize is
> updated
> >> with the size
> >>
> >> +                                required for the specified
> variable.
> >>
> >> +  @retval EFI_INVALID_PARAMETER VariableName, VariableGuid or
> >>
> >> +                                VariableNameSize is NULL.
> >>
> >> +  @retval EFI_DEVICE_ERROR      The variable could not be retrieved
> >> because of a device error.
> >>
> >> +**/
> >>
> >> +EFI_STATUS
> >>
> >> +EFIAPI
> >>
> >> +PeiMmGetNextVariableName (
> >>
> >> +  IN CONST  EFI_PEI_READ_ONLY_VARIABLE2_PPI  *This,
> >>
> >> +  IN OUT UINTN
> *VariableNameSize,
> >>
> >> +  IN OUT CHAR16                              *VariableName,
> >>
> >> +  IN OUT EFI_GUID                            *VariableGuid
> >>
> >> +  )
> >>
> >> +{
> >>
> >> +  EFI_STATUS                                       Status;
> >>
> >> +  UINTN
> >> MessageSize;
> >>
> >> +  UINT8
> >> *MmCommunicateBuffer;
> >>
> >> +  SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME
> >> *MmVarGetNextVarHeader;
> >>
> >> +  UINTN
> >> RequiredPages;
> >>
> >> +
> >>
> >> +  // Check input parameters
> >>
> >> +  if ((VariableName == NULL) ||
> >>
> >> +      (VariableGuid == NULL) ||
> >>
> >> +      (VariableNameSize == NULL) ||
> >>
> >> +      (*VariableNameSize == 0))
> >>
> >> +  {
> >>
> >> +    return EFI_INVALID_PARAMETER;
> >>
> >> +  }
> >>
> >> +
> >>
> >> +  // Allocate required pages to send MM request
> >>
> >> +  MessageSize = MM_VARIABLE_COMM_BUFFER_OFFSET +
> >>
> >> +                OFFSET_OF
> >> (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) +
> >>
> >> +                StrSize (VariableName) + *VariableNameSize;
> >>
> >> +
> >>
> >> +  RequiredPages       = EFI_SIZE_TO_PAGES (MessageSize);
> >>
> >> +  MmCommunicateBuffer = (UINT8 *)AllocatePages (RequiredPages);
> >>
> >> +
> >>
> >> +  if (MmCommunicateBuffer == NULL) {
> >>
> >> +    Status = EFI_OUT_OF_RESOURCES;
> >>
> >> +    DEBUG ((DEBUG_ERROR, "%a: Failed to allocate memory: %r\n",
> >> __func__, Status));
> >>
> >> +    return Status;
> >>
> >> +  }
> >>
> >> +
> >>
> >> +  // Zero the entire Communication Buffer
> >>
> >> +  ZeroMem (MmCommunicateBuffer, (RequiredPages * EFI_PAGE_SIZE));
> >>
> >> +
> >>
> >> +  //
> >>
> >> +  // Program all payload structure contents
> >>
> >> +  //
> >>
> >> +  MmVarGetNextVarHeader =
> >> (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME
> >> *)(MmCommunicateBuffer + MM_VARIABLE_COMM_BUFFER_OFFSET);
> >>
> >> +
> >>
> >> +  // Variable GUID
> >>
> >> +  CopyMem ((VOID *)&MmVarGetNextVarHeader->Guid, VariableGuid,
> >> sizeof (GUID));
> >>
> >> +
> >>
> >> +  // Program the maximal length of name we can accept.
> >>
> >> +  MmVarGetNextVarHeader->NameSize = *VariableNameSize;
> >>
> >> +
> >>
> >> +  // Populate incoming variable name
> >>
> >> +  CopyMem ((VOID *)&MmVarGetNextVarHeader->Name,
> VariableName,
> >> MmVarGetNextVarHeader->NameSize);
> >>
> >> +
> >>
> >> +  // Send the MM request using MmCommunicationPei
> >>
> >> +  Status = PopulateHeaderAndCommunicate (MmCommunicateBuffer,
> >> MessageSize, SMM_VARIABLE_FUNCTION_GET_NEXT_VARIABLE_NAME);
> >>
> >> +  if (EFI_ERROR (Status)) {
> >>
> >> +    // We received an error from either communicate or Variable
> Service.
> >>
> >> +    if (Status != EFI_BUFFER_TOO_SMALL) {
> >>
> >> +      DEBUG ((DEBUG_ERROR, "%a - Communite to MM for variable
> >> service errored: %r\n", __func__, Status));
> >>
> >> +    }
> >>
> >> +
> >>
> >> +    goto Exit;
> >>
> >> +  }
> >>
> >> +
> >>
> >> +  Status = EFI_SUCCESS;
> >>
> >> +
> >>
> >> +  // User provided buffer is too small
> >>
> >> +  if (*VariableNameSize < MmVarGetNextVarHeader->NameSize) {
> >>
> >> +    Status = EFI_BUFFER_TOO_SMALL;
> >>
> >> +  }
> >>
> >> +
> >>
> >> +Exit:
> >>
> >> +  // Update the name size to be returned
> >>
> >> +  *VariableNameSize = MmVarGetNextVarHeader->NameSize;
> >>
> >> +
> >>
> >> +  if (Status == EFI_SUCCESS) {
> >>
> >> +    CopyMem ((VOID *)VariableName, (UINT8
> >> *)MmVarGetNextVarHeader->Name, *VariableNameSize);
> >>
> >> +    CopyMem ((VOID *)VariableGuid, (UINT8
> >> *)&(MmVarGetNextVarHeader->Guid), sizeof (EFI_GUID));
> >>
> >> +  }
> >>
> >> +
> >>
> >> +  // Free the Communication Buffer
> >>
> >> +  if (MmCommunicateBuffer != NULL) {
> >>
> >> +    FreePages (MmCommunicateBuffer, RequiredPages);
> >>
> >> +  }
> >>
> >> +
> >>
> >> +  return Status;
> >>
> >> +}
> >>
> >> diff --git a/MdeModulePkg/MdeModulePkg.dsc
> >> b/MdeModulePkg/MdeModulePkg.dsc
> >> index 5b1f50e9c084..1aedfe280ae1 100644
> >> --- a/MdeModulePkg/MdeModulePkg.dsc
> >> +++ b/MdeModulePkg/MdeModulePkg.dsc
> >> @@ -400,6 +400,7 @@ [Components]
> >>     MdeModulePkg/Application/VariableInfo/VariableInfo.inf
> >>
> >>
> >>
> MdeModulePkg/Universal/FaultTolerantWritePei/FaultTolerantWritePei.inf
> >>
> >>     MdeModulePkg/Universal/Variable/Pei/VariablePei.inf
> >>
> >> +  MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.inf
> >>
> >>     MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
> >>
> >>     MdeModulePkg/Universal/TimestampDxe/TimestampDxe.inf
> >>
> >>
> >>
> MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf
> >>
> >> diff --git
> >> a/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.h
> >> b/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.h
> >> new file mode 100644
> >> index 000000000000..0feed8cd1cb6
> >> --- /dev/null
> >> +++
> b/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.h
> >> @@ -0,0 +1,134 @@
> >> +/** @file -- MmVariablePei.h
> >>
> >> +  Provides interface for reading Secure System Variables during PEI.
> >>
> >> +
> >>
> >> +  Copyright (c) Microsoft Corporation.
> >>
> >> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> >>
> >> +**/
> >>
> >> +
> >>
> >> +#ifndef PEI_MM_VARIABLE_LIB_H_
> >>
> >> +#define PEI_MM_VARIABLE_LIB_H_
> >>
> >> +
> >>
> >> +#include <PiPei.h>
> >>
> >> +#include <Uefi/UefiSpec.h>
> >>
> >> +
> >>
> >> +#include <Library/DebugLib.h>
> >>
> >> +#include <Library/PcdLib.h>
> >>
> >> +#include <Library/BaseMemoryLib.h>
> >>
> >> +#include <Library/PeimEntryPoint.h>
> >>
> >> +#include <Library/PeiServicesLib.h>
> >>
> >> +#include <Library/MemoryAllocationLib.h>
> >>
> >> +#include <Library/HobLib.h>
> >>
> >> +
> >>
> >> +#include <Guid/SmmVariableCommon.h>
> >>
> >> +
> >>
> >> +#include <Ppi/ReadOnlyVariable2.h>
> >>
> >> +#include <Ppi/MmCommunication.h>
> >>
> >> +
> >>
> >> +#include <Protocol/SmmVariable.h>
> >>
> >> +#include <Protocol/MmCommunication.h>
> >>
> >> +
> >>
> >> +/**
> >>
> >> +  Entry point of PEI Secure Variable read driver
> >>
> >> +
> >>
> >> +  @param  FileHandle   Handle of the file being invoked.
> >>
> >> +                       Type EFI_PEI_FILE_HANDLE is defined in
> >> FfsFindNextFile().
> >>
> >> +  @param  PeiServices  General purpose services available to every
> >> PEIM.
> >>
> >> +
> >>
> >> +  @retval EFI_SUCCESS  If the interface could be successfully installed
> >>
> >> +  @retval Others       Returned from PeiServicesInstallPpi()
> >>
> >> +**/
> >>
> >> +EFI_STATUS
> >>
> >> +EFIAPI
> >>
> >> +PeiMmVariableInitialize (
> >>
> >> +  IN       EFI_PEI_FILE_HANDLE  FileHandle,
> >>
> >> +  IN CONST EFI_PEI_SERVICES     **PeiServices
> >>
> >> +  );
> >>
> >> +
> >>
> >> +/**
> >>
> >> +
> >>
> >> +  This function enables the read of Secure Variables during PEI.
> >>
> >> +
> >>
> >> +  This function is using the Secure Variable Store.If the Data
> >>
> >> +  buffer is too small to hold the contents of the variable, the error
> >>
> >> +  EFI_BUFFER_TOO_SMALL is returned and DataSize is set to the
> required
> >> buffer
> >>
> >> +  size to obtain the data.
> >>
> >> +
> >>
> >> +  The function performs the following:
> >>
> >> +
> >>
> >> +  1) Creates an MM request
> >>
> >> +  2) Fills out the following data structures for the Secure Variable
> > Service
> >> +
> >>
> SMM_VARIABLE_COMMUNICATE_HEADER/SMM_VARIABLE_COMMUNICAT
> >> E_ACCESS_VARIABLE
> >>
> >> +  3) Adds the MM data structures to the MM request.
> >>
> >> +  4) Sends the MM request to EL3 using MmCommunicationPeiLib.
> >>
> >> +  5) The MM request is sent to S-EL0.
> >>
> >> +  6) The MM request is then handled by the registered handler with
> GUID:
> >> gEfiSmmVariableProtocolGuid
> >>
> >> +
> >>
> >> +  @param  This                  A pointer to this instance of the
> >> EFI_PEI_READ_ONLY_VARIABLE2_PPI.
> >>
> >> +  @param  VariableName          A pointer to a null-terminated
> string
> >> that is the variable's name.
> >>
> >> +  @param  VariableGuid          A pointer to an EFI_GUID that is
> the
> >> variable's GUID. The combination of
> >>
> >> +                                VariableGuid and VariableName
> >> must be unique.
> >>
> >> +  @param  Attributes            If non-NULL, on return, points to
> the
> >> variable's attributes.
> >>
> >> +  @param  DataSize              On entry, points to the size in
> bytes
> >> of the Data buffer.
> >>
> >> +                                On return, points to the size of
> the
> >> data returned in Data.
> >>
> >> +  @param  Data                  Points to the buffer which will
> hold
> >> the returned variable value.
> >>
> >> +                                May be NULL with a zero
> DataSize in
> >> order to determine the size of the buffer needed.
> >>
> >> +
> >>
> >> +  @retval EFI_SUCCESS           The variable was read successfully.
> >>
> >> +  @retval EFI_NOT_FOUND         The variable was not found.
> >>
> >> +  @retval EFI_BUFFER_TOO_SMALL  The DataSize is too small for the
> >> resulting data.
> >>
> >> +                                DataSize is updated with the size
> >> required for
> >>
> >> +                                the specified variable.
> >>
> >> +  @retval EFI_INVALID_PARAMETER VariableName, VariableGuid,
> DataSize
> >> or Data is NULL.
> >>
> >> +  @retval EFI_DEVICE_ERROR      The variable could not be retrieved
> >> because of a device error.
> >>
> >> +
> >>
> >> +**/
> >>
> >> +EFI_STATUS
> >>
> >> +EFIAPI
> >>
> >> +PeiMmGetVariable (
> >>
> >> +  IN CONST  EFI_PEI_READ_ONLY_VARIABLE2_PPI  *This,
> >>
> >> +  IN CONST  CHAR16                           *VariableName,
> >>
> >> +  IN CONST  EFI_GUID                         *VariableGuid,
> >>
> >> +  OUT       UINT32                           *Attributes,
> >>
> >> +  IN OUT    UINTN                            *DataSize,
> >>
> >> +  OUT       VOID                             *Data
> OPTIONAL
> >>
> >> +  );
> >>
> >> +
> >>
> >> +/**
> >>
> >> +  Return the next variable name and GUID.
> >>
> >> +
> >>
> >> +  This function is called multiple times to retrieve the VariableName
> >>
> >> +  and VariableGuid of all variables currently available in the system.
> >>
> >> +  On each call, the previous results are passed into the interface,
> >>
> >> +  and, on return, the interface returns the data for the next
> >>
> >> +  interface. When the entire variable list has been returned,
> >>
> >> +  EFI_NOT_FOUND is returned.
> >>
> >> +
> >>
> >> +  @param  This              A pointer to this instance of the
> >> EFI_PEI_READ_ONLY_VARIABLE2_PPI.
> >>
> >> +
> >>
> >> +  @param  VariableNameSize  On entry, points to the size of the
> buffer
> >> pointed to by VariableName.
> >>
> >> +                            On return, the size of the variable
> name
> >> buffer.
> >>
> >> +  @param  VariableName      On entry, a pointer to a
> null-terminated
> >> string that is the variable's name.
> >>
> >> +                            On return, points to the next variable's
> >> null-terminated name string.
> >>
> >> +
> >>
> >> +  @param  VariableGuid      On entry, a pointer to an EFI_GUID that
> is
> >> the variable's GUID.
> >>
> >> +                            On return, a pointer to the next
> variable's
> >> GUID.
> >>
> >> +
> >>
> >> +  @retval EFI_SUCCESS           The variable was read successfully.
> >>
> >> +  @retval EFI_NOT_FOUND         The variable could not be found.
> >>
> >> +  @retval EFI_BUFFER_TOO_SMALL  The VariableNameSize is too
> small
> >> for the resulting
> >>
> >> +                                data. VariableNameSize is
> updated
> >> with the size
> >>
> >> +                                required for the specified
> variable.
> >>
> >> +  @retval EFI_INVALID_PARAMETER VariableName, VariableGuid or
> >>
> >> +                                VariableNameSize is NULL.
> >>
> >> +  @retval EFI_DEVICE_ERROR      The variable could not be retrieved
> >> because of a device error.
> >>
> >> +**/
> >>
> >> +EFI_STATUS
> >>
> >> +EFIAPI
> >>
> >> +PeiMmGetNextVariableName (
> >>
> >> +  IN CONST  EFI_PEI_READ_ONLY_VARIABLE2_PPI  *This,
> >>
> >> +  IN OUT UINTN
> *VariableNameSize,
> >>
> >> +  IN OUT CHAR16                              *VariableName,
> >>
> >> +  IN OUT EFI_GUID                            *VariableGuid
> >>
> >> +  );
> >>
> >> +
> >>
> >> +#endif /* PEI_MM_VARIABLE_LIB_H_ */
> >>
> >> diff --git
> >> a/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.inf
> >> b/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.inf
> >> new file mode 100644
> >> index 000000000000..d122703e9b5d
> >> --- /dev/null
> >> +++
> b/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.inf
> >> @@ -0,0 +1,43 @@
> >> +## @file -- MmVariablePei.inf
> >>
> >> +# Provides interface for reading Secure System Variables during PEI.
> >>
> >> +#
> >>
> >> +# Copyright (c) Microsoft Corporation.
> >>
> >> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> >>
> >> +##
> >>
> >> +
> >>
> >> +
> >>
> >> +[Defines]
> >>
> >> +  INF_VERSION                    = 0x00010005
> >>
> >> +  BASE_NAME                      = MmVariablePei
> >>
> >> +  FILE_GUID                      =
> >> CD660A87-454B-4346-A35C-3D89BF8ECFAF
> >>
> >> +  MODULE_TYPE                    = PEIM
> >>
> >> +  VERSION_STRING                 = 1.0
> >>
> >> +  ENTRY_POINT                    = PeiMmVariableInitialize
> >>
> >> +
> >>
> >> +[Sources]
> >>
> >> +  MmVariablePei.c
> >>
> >> +  MmVariablePei.h
> >>
> >> +
> >>
> >> +[Packages]
> >>
> >> +  MdePkg/MdePkg.dec
> >>
> >> +  MdeModulePkg/MdeModulePkg.dec
> >>
> >> +
> >>
> >> +[LibraryClasses]
> >>
> >> +  PcdLib
> >>
> >> +  PeiServicesLib
> >>
> >> +  PeimEntryPoint
> >>
> >> +  MemoryAllocationLib
> >>
> >> +  HobLib
> >>
> >> +
> >>
> >> +[Pcd]
> >>
> >> +  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize
> >>
> >> +
> >>
> >> +[Protocols]
> >>
> >> +  gEfiSmmVariableProtocolGuid             ## CONSUMES
> >>
> >> +
> >>
> >> +[Ppis]
> >>
> >> +  gEfiPeiReadOnlyVariable2PpiGuid         ## PRODUCES
> >>
> >> +  gEfiPeiMmCommunicationPpiGuid           ## CONSUMES
> >>
> >> +
> >>
> >> +[Depex]
> >>
> >> +  gEfiPeiMmCommunicationPpiGuid
> >>
> >> --
> >> 2.40.1.windows.1
> >>
> >>
> >>
> >> -=-=-=-=-=-=
> >> Groups.io Links: You receive all messages sent to this group.
> >> View/Reply Online (#105956):
> >> https://edk2.groups.io/g/devel/message/105956
> >> Mute This Topic: https://groups.io/mt/99415826/4905953
> >> Group Owner: devel+owner@edk2.groups.io
> >> Unsubscribe: https://edk2.groups.io/g/devel/unsub
> >> [gaoliming@byosoft.com.cn]
> >> -=-=-=-=-=-=
> >>
> >
> >
> >
> >
> >
> >
> >
> 
> 
> 
> 




^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2023-06-27  0:53 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-06-08 20:44 [PATCH v1 0/2] Support MM based variable services in PEI for ARM Kun Qin
2023-06-08 20:44 ` [PATCH v1 1/2] ArmPkg: MmCommunicationPei: Introduce MM communicate in PEI Kun Qin
2023-06-22 19:17   ` Sami Mujawar
2023-06-26 20:07     ` Kun Qin
2023-06-08 20:44 ` [PATCH v1 2/2] MdeModulePkg: Variable: Introduce MM based variable read service " Kun Qin
2023-06-25  2:23   ` 回复: [edk2-devel] " gaoliming
2023-06-26 20:10     ` Kun Qin
2023-06-27  0:53       ` 回复: " gaoliming

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox