Laszlo,

For the EFI_PEI_COMMUNICATION_PPI, is there a reason you are not using 
UefiCpuPkg\PiSmmCommunication\PiSmmCommunicationPei.inf to produce that PPI?

Thanks,

Mike

>-----Original Message-----
>From: Laszlo Ersek [mailto:ler...@redhat.com]
>Sent: Tuesday, November 03, 2015 1:01 PM
>To: edk2-de...@ml01.01.org
>Cc: Kinney, Michael D; Justen, Jordan L
>Subject: [PATCH v4 07/41] OvmfPkg: add PEIM for providing TSEG-as-SMRAM
>during PEI
>
>"MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxPeiLib.inf" is the library
>instance that implements the LockBoxLib library class with SMRAM access
>for the PEI phase.
>
>Introduce a PEIM that produces the EFI_PEI_SMM_COMMUNICATION_PPI and
>PEI_SMM_ACCESS_PPI interfaces, enabling SmmLockBoxPeiLib to work.
>
>Said library instance can parse and access LockBox data itself (without
>additional LockBox drivers) if the
>EFI_PEI_SMM_COMMUNICATION_PPI.Communicate() function returns
>EFI_NOT_STARTED to it. However it requires that
>EFI_PEI_SMM_COMMUNICATION_PPI exist at least. Also,
>PEI_SMM_ACCESS_PPI
>must exist and work.
>
>The load / installation order of S3Resume2Pei and SmmAccessPei is
>indifferent. SmmAccessPei produces the GUIDed HOB during its installation
>(which happens during PEI), but S3Resume2Pei accesses the HOB only when
>the DXE IPL calls its S3RestoreConfig2 PPI member, as last act of PEI.
>
>MCH_SMRAM_D_LCK and MCH_ESMRAMC_T_EN are masked out the way
>they are, in
>SmmAccessPeiEntryPoint() and SmramAccessOpen() respectively, in order to
>prevent VS20xx from warning about the (otherwise fully intentional)
>truncation in the UINT8 casts. (Warnings reported by Michael Kinney.)
>
>Cc: Michael Kinney <michael.d.kin...@intel.com>
>Cc: Jordan Justen <jordan.l.jus...@intel.com>
>Contributed-under: TianoCore Contribution Agreement 1.0
>Signed-off-by: Laszlo Ersek <ler...@redhat.com>
>---
>
>Notes:
>    v3:
>    - update bit-neg expressions to silence VS20xx warnings [Mike]
>
> OvmfPkg/OvmfPkgIa32.dsc            |   6 +
> OvmfPkg/OvmfPkgIa32X64.dsc         |   6 +
> OvmfPkg/OvmfPkgX64.dsc             |   6 +
> OvmfPkg/OvmfPkgIa32.fdf            |   3 +
> OvmfPkg/OvmfPkgIa32X64.fdf         |   3 +
> OvmfPkg/OvmfPkgX64.fdf             |   3 +
> OvmfPkg/SmmAccess/SmmAccessPei.inf |  70 +++
> OvmfPkg/SmmAccess/SmramInternal.h  |  89 ++++
> OvmfPkg/SmmAccess/SmmAccessPei.c   | 446 ++++++++++++++++++++
> OvmfPkg/SmmAccess/SmramInternal.c  | 188 +++++++++
> 10 files changed, 820 insertions(+)
>
>diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc
>index c6850ff..0b729ca 100644
>--- a/OvmfPkg/OvmfPkgIa32.dsc
>+++ b/OvmfPkg/OvmfPkgIa32.dsc
>@@ -445,6 +445,12 @@ [Components]
>     <LibraryClasses>
>       PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
>   }
>+!if $(SMM_REQUIRE) == TRUE
>+  OvmfPkg/SmmAccess/SmmAccessPei.inf {
>+    <LibraryClasses>
>+      PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
>+  }
>+!endif
>
>   #
>   # DXE Phase modules
>diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc
>index dd65bf9..7f672d9 100644
>--- a/OvmfPkg/OvmfPkgIa32X64.dsc
>+++ b/OvmfPkg/OvmfPkgIa32X64.dsc
>@@ -451,6 +451,12 @@ [Components.IA32]
>     <LibraryClasses>
>       PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
>   }
>+!if $(SMM_REQUIRE) == TRUE
>+  OvmfPkg/SmmAccess/SmmAccessPei.inf {
>+    <LibraryClasses>
>+      PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
>+  }
>+!endif
>
> [Components.X64]
>   #
>diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc
>index 0de3c85..986c019 100644
>--- a/OvmfPkg/OvmfPkgX64.dsc
>+++ b/OvmfPkg/OvmfPkgX64.dsc
>@@ -450,6 +450,12 @@ [Components]
>     <LibraryClasses>
>       PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
>   }
>+!if $(SMM_REQUIRE) == TRUE
>+  OvmfPkg/SmmAccess/SmmAccessPei.inf {
>+    <LibraryClasses>
>+      PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
>+  }
>+!endif
>
>   #
>   # DXE Phase modules
>diff --git a/OvmfPkg/OvmfPkgIa32.fdf b/OvmfPkg/OvmfPkgIa32.fdf
>index 44e4a92..650dab1 100644
>--- a/OvmfPkg/OvmfPkgIa32.fdf
>+++ b/OvmfPkg/OvmfPkgIa32.fdf
>@@ -171,6 +171,9 @@ [FV.PEIFV]
> INF  OvmfPkg/PlatformPei/PlatformPei.inf
> INF  MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
> INF  UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf
>+!if $(SMM_REQUIRE) == TRUE
>+INF  OvmfPkg/SmmAccess/SmmAccessPei.inf
>+!endif
>
>
>#################################################################
>###############
>
>diff --git a/OvmfPkg/OvmfPkgIa32X64.fdf b/OvmfPkg/OvmfPkgIa32X64.fdf
>index 67bfbe7..5830401 100644
>--- a/OvmfPkg/OvmfPkgIa32X64.fdf
>+++ b/OvmfPkg/OvmfPkgIa32X64.fdf
>@@ -171,6 +171,9 @@ [FV.PEIFV]
> INF  OvmfPkg/PlatformPei/PlatformPei.inf
> INF  MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
> INF  UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf
>+!if $(SMM_REQUIRE) == TRUE
>+INF  OvmfPkg/SmmAccess/SmmAccessPei.inf
>+!endif
>
>
>#################################################################
>###############
>
>diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf
>index 6624789..9dd6171 100644
>--- a/OvmfPkg/OvmfPkgX64.fdf
>+++ b/OvmfPkg/OvmfPkgX64.fdf
>@@ -171,6 +171,9 @@ [FV.PEIFV]
> INF  OvmfPkg/PlatformPei/PlatformPei.inf
> INF  MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
> INF  UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf
>+!if $(SMM_REQUIRE) == TRUE
>+INF  OvmfPkg/SmmAccess/SmmAccessPei.inf
>+!endif
>
>
>#################################################################
>###############
>
>diff --git a/OvmfPkg/SmmAccess/SmmAccessPei.inf
>b/OvmfPkg/SmmAccess/SmmAccessPei.inf
>new file mode 100644
>index 0000000..94eb6c9
>--- /dev/null
>+++ b/OvmfPkg/SmmAccess/SmmAccessPei.inf
>@@ -0,0 +1,70 @@
>+## @file
>+# A PEIM with the following responsibilities:
>+#
>+# - provide SMRAM access by producing PEI_SMM_ACCESS_PPI,
>+# - provide a simple EFI_PEI_SMM_COMMUNICATION_PPI (always returning
>+#   EFI_NOT_STARTED),
>+# - verify & configure the Q35 TSEG in the entry point,
>+# - set aside the SMM_S3_RESUME_STATE object at the bottom of TSEG, and
>expose
>+#   it via the gEfiAcpiVariableGuid GUIDed HOB.
>+#
>+# Copyright (C) 2013, 2015, Red Hat, Inc.
>+#
>+# This program and the accompanying materials are licensed and made
>available
>+# under the terms and conditions of the BSD License which accompanies this
>+# distribution. The full text of the license may be found at
>+# http://opensource.org/licenses/bsd-license.php
>+#
>+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
>BASIS, WITHOUT
>+# WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR
>IMPLIED.
>+#
>+##
>+
>+[Defines]
>+  INF_VERSION                    = 0x00010005
>+  BASE_NAME                      = SmmAccessPei
>+  FILE_GUID                      = 6C0E75B4-B0B9-44D1-8210-3377D7B4E066
>+  MODULE_TYPE                    = PEIM
>+  VERSION_STRING                 = 1.0
>+  ENTRY_POINT                    = SmmAccessPeiEntryPoint
>+
>+#
>+# The following information is for reference only and not required by the
>build tools.
>+#
>+#  VALID_ARCHITECTURES           = IA32 X64
>+#
>+
>+[Sources]
>+  SmmAccessPei.c
>+  SmramInternal.c
>+
>+[Packages]
>+  MdeModulePkg/MdeModulePkg.dec
>+  MdePkg/MdePkg.dec
>+  OvmfPkg/OvmfPkg.dec
>+
>+[Guids]
>+  gEfiAcpiVariableGuid
>+
>+[LibraryClasses]
>+  BaseMemoryLib
>+  DebugLib
>+  HobLib
>+  IoLib
>+  PcdLib
>+  PciLib
>+  PeiServicesLib
>+  PeimEntryPoint
>+
>+[FeaturePcd]
>+  gUefiOvmfPkgTokenSpaceGuid.PcdSmmSmramRequire
>+
>+[FixedPcd]
>+  gUefiOvmfPkgTokenSpaceGuid.PcdQ35TsegMbytes
>+
>+[Ppis]
>+  gEfiPeiSmmCommunicationPpiGuid # PPI ALWAYS_PRODUCED
>+  gPeiSmmAccessPpiGuid           # PPI ALWAYS_PRODUCED
>+
>+[Depex]
>+  TRUE
>diff --git a/OvmfPkg/SmmAccess/SmramInternal.h
>b/OvmfPkg/SmmAccess/SmramInternal.h
>new file mode 100644
>index 0000000..4e9ac05
>--- /dev/null
>+++ b/OvmfPkg/SmmAccess/SmramInternal.h
>@@ -0,0 +1,89 @@
>+/** @file
>+
>+  Functions and types shared by the SMM accessor PEI and DXE modules.
>+
>+  Copyright (C) 2015, Red Hat, Inc.
>+
>+  This program and the accompanying materials are licensed and made
>available
>+  under the terms and conditions of the BSD License which accompanies this
>+  distribution. The full text of the license may be found at
>+  http://opensource.org/licenses/bsd-license.php
>+
>+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
>BASIS, WITHOUT
>+  WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR
>IMPLIED.
>+
>+**/
>+
>+#include <Pi/PiMultiPhase.h>
>+
>+//
>+// We'll have two SMRAM ranges.
>+//
>+// The first is a tiny one that hosts an SMM_S3_RESUME_STATE object, to be
>+// filled in by the CPU SMM driver during normal boot, for the PEI instance
>of
>+// the LockBox library (which will rely on the object during S3 resume).
>+//
>+// The other SMRAM range is the main one, for the SMM core and the SMM
>drivers.
>+//
>+typedef enum {
>+  DescIdxSmmS3ResumeState = 0,
>+  DescIdxMain             = 1,
>+  DescIdxCount            = 2
>+} DESCRIPTOR_INDEX;
>+
>+/**
>+  Read the MCH_SMRAM and ESMRAMC registers, and update the LockState
>and
>+  OpenState fields in the PEI_SMM_ACCESS_PPI /
>EFI_SMM_ACCESS2_PROTOCOL object,
>+  from the D_LCK and T_EN bits.
>+
>+  PEI_SMM_ACCESS_PPI and EFI_SMM_ACCESS2_PROTOCOL member
>functions can rely on
>+  the LockState and OpenState fields being up-to-date on entry, and they
>need
>+  to restore the same invariant on exit, if they touch the bits in question.
>+
>+  @param[out] LockState  Reflects the D_LCK bit on output; TRUE iff SMRAM
>is
>+                         locked.
>+  @param[out] OpenState  Reflects the inverse of the T_EN bit on output;
>TRUE
>+                         iff SMRAM is open.
>+**/
>+VOID
>+GetStates (
>+  OUT BOOLEAN *LockState,
>+  OUT BOOLEAN *OpenState
>+  );
>+
>+//
>+// The functions below follow the PEI_SMM_ACCESS_PPI and
>+// EFI_SMM_ACCESS2_PROTOCOL member declarations. The PeiServices and
>This
>+// pointers are removed (TSEG doesn't depend on them), and so is the
>+// DescriptorIndex parameter (TSEG doesn't support range-wise locking).
>+//
>+// The LockState and OpenState members that are common to both
>+// PEI_SMM_ACCESS_PPI and EFI_SMM_ACCESS2_PROTOCOL are taken and
>updated in
>+// isolation from the rest of the (non-shared) members.
>+//
>+
>+EFI_STATUS
>+SmramAccessOpen (
>+  OUT BOOLEAN *LockState,
>+  OUT BOOLEAN *OpenState
>+  );
>+
>+EFI_STATUS
>+SmramAccessClose (
>+  OUT BOOLEAN *LockState,
>+  OUT BOOLEAN *OpenState
>+  );
>+
>+EFI_STATUS
>+SmramAccessLock (
>+  OUT    BOOLEAN *LockState,
>+  IN OUT BOOLEAN *OpenState
>+  );
>+
>+EFI_STATUS
>+SmramAccessGetCapabilities (
>+  IN BOOLEAN                  LockState,
>+  IN BOOLEAN                  OpenState,
>+  IN OUT UINTN                *SmramMapSize,
>+  IN OUT EFI_SMRAM_DESCRIPTOR *SmramMap
>+  );
>diff --git a/OvmfPkg/SmmAccess/SmmAccessPei.c
>b/OvmfPkg/SmmAccess/SmmAccessPei.c
>new file mode 100644
>index 0000000..8de4e4f
>--- /dev/null
>+++ b/OvmfPkg/SmmAccess/SmmAccessPei.c
>@@ -0,0 +1,446 @@
>+/** @file
>+
>+  A PEIM with the following responsibilities:
>+
>+  - verify & configure the Q35 TSEG in the entry point,
>+  - provide SMRAM access by producing PEI_SMM_ACCESS_PPI,
>+  - provide a simple EFI_PEI_SMM_COMMUNICATION_PPI (always returning
>+    EFI_NOT_STARTED),
>+  - set aside the SMM_S3_RESUME_STATE object at the bottom of TSEG, and
>expose
>+    it via the gEfiAcpiVariableGuid GUID HOB.
>+
>+  This PEIM runs from RAM, so we can write to variables with static storage
>+  duration.
>+
>+  Copyright (C) 2013, 2015, Red Hat, Inc.<BR>
>+  Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
>+
>+  This program and the accompanying materials are licensed and made
>available
>+  under the terms and conditions of the BSD License which accompanies this
>+  distribution. The full text of the license may be found at
>+  http://opensource.org/licenses/bsd-license.php
>+
>+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
>BASIS, WITHOUT
>+  WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR
>IMPLIED.
>+
>+**/
>+
>+#include <Guid/AcpiS3Context.h>
>+#include <Library/BaseMemoryLib.h>
>+#include <Library/DebugLib.h>
>+#include <Library/HobLib.h>
>+#include <Library/IoLib.h>
>+#include <Library/PcdLib.h>
>+#include <Library/PciLib.h>
>+#include <Library/PeiServicesLib.h>
>+#include <Ppi/SmmAccess.h>
>+#include <Ppi/SmmCommunication.h>
>+
>+#include <OvmfPlatforms.h>
>+
>+#include "SmramInternal.h"
>+
>+//
>+// EFI_PEI_SMM_COMMUNICATION_PPI implementation.
>+//
>+
>+/**
>+  Communicates with a registered handler.
>+
>+  This function provides a service to send and receive messages from a
>+  registered UEFI service.
>+
>+  @param[in] This                The EFI_PEI_SMM_COMMUNICATION_PPI
>instance.
>+  @param[in] CommBuffer          A pointer to the buffer to convey into
>SMRAM.
>+  @param[in] 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  The CommBuffer was NULL.
>+**/
>+STATIC
>+EFI_STATUS
>+EFIAPI
>+SmmCommunicate (
>+  IN CONST EFI_PEI_SMM_COMMUNICATION_PPI   *This,
>+  IN OUT VOID                              *CommBuffer,
>+  IN OUT UINTN                             *CommSize
>+  )
>+{
>+  //
>+  // This return status is not documented, but it causes
>+  // "MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxPeiLib.c" to look
>for the
>+  // LockBox in SMRAM itself. It allows us to avoid implementing
>+  // EFI_PEI_SMM_COMMUNICATION_PPI with real functionality, plus we can
>+  // completely skip PEI_SMM_CONTROL_PPI (which the former would
>arguably rely
>+  // on).
>+  //
>+  return EFI_NOT_STARTED;
>+}
>+
>+STATIC EFI_PEI_SMM_COMMUNICATION_PPI mCommunication = {
>+  &SmmCommunicate
>+};
>+
>+
>+//
>+// PEI_SMM_ACCESS_PPI implementation.
>+//
>+
>+/**
>+  Opens the SMRAM area to be accessible by a PEIM driver.
>+
>+  This function "opens" SMRAM so that it is visible while not inside of SMM.
>+  The function should return EFI_UNSUPPORTED if the hardware does not
>support
>+  hiding of SMRAM. The function should return EFI_DEVICE_ERROR if the
>SMRAM
>+  configuration is locked.
>+
>+  @param  PeiServices            General purpose services available to every
>+                                 PEIM.
>+  @param  This                   The pointer to the SMM Access Interface.
>+  @param  DescriptorIndex        The region of SMRAM to Open.
>+
>+  @retval EFI_SUCCESS            The region was successfully opened.
>+  @retval EFI_DEVICE_ERROR       The region could not be opened because
>locked
>+                                 by chipset.
>+  @retval EFI_INVALID_PARAMETER  The descriptor index was out of bounds.
>+
>+**/
>+STATIC
>+EFI_STATUS
>+EFIAPI
>+SmmAccessPeiOpen (
>+  IN EFI_PEI_SERVICES                **PeiServices,
>+  IN PEI_SMM_ACCESS_PPI              *This,
>+  IN UINTN                           DescriptorIndex
>+  )
>+{
>+  if (DescriptorIndex >= DescIdxCount) {
>+    return EFI_INVALID_PARAMETER;
>+  }
>+
>+  //
>+  // According to current practice, DescriptorIndex is not considered at all,
>+  // beyond validating it.
>+  //
>+  return SmramAccessOpen (&This->LockState, &This->OpenState);
>+}
>+
>+/**
>+  Inhibits access to the SMRAM.
>+
>+  This function "closes" SMRAM so that it is not visible while outside of SMM.
>+  The function should return EFI_UNSUPPORTED if the hardware does not
>support
>+  hiding of SMRAM.
>+
>+  @param  PeiServices              General purpose services available to every
>+                                   PEIM.
>+  @param  This                     The pointer to the SMM Access Interface.
>+  @param  DescriptorIndex          The region of SMRAM to Close.
>+
>+  @retval EFI_SUCCESS              The region was successfully closed.
>+  @retval EFI_DEVICE_ERROR         The region could not be closed because
>+                                   locked by chipset.
>+  @retval EFI_INVALID_PARAMETER    The descriptor index was out of
>bounds.
>+
>+**/
>+STATIC
>+EFI_STATUS
>+EFIAPI
>+SmmAccessPeiClose (
>+  IN EFI_PEI_SERVICES                **PeiServices,
>+  IN PEI_SMM_ACCESS_PPI              *This,
>+  IN UINTN                           DescriptorIndex
>+  )
>+{
>+  if (DescriptorIndex >= DescIdxCount) {
>+    return EFI_INVALID_PARAMETER;
>+  }
>+
>+  //
>+  // According to current practice, DescriptorIndex is not considered at all,
>+  // beyond validating it.
>+  //
>+  return SmramAccessClose (&This->LockState, &This->OpenState);
>+}
>+
>+/**
>+  Inhibits access to the SMRAM.
>+
>+  This function prohibits access to the SMRAM region.  This function is
>usually
>+  implemented such that it is a write-once operation.
>+
>+  @param  PeiServices              General purpose services available to every
>+                                   PEIM.
>+  @param  This                     The pointer to the SMM Access Interface.
>+  @param  DescriptorIndex          The region of SMRAM to Close.
>+
>+  @retval EFI_SUCCESS            The region was successfully locked.
>+  @retval EFI_DEVICE_ERROR       The region could not be locked because at
>+                                 least one range is still open.
>+  @retval EFI_INVALID_PARAMETER  The descriptor index was out of bounds.
>+
>+**/
>+STATIC
>+EFI_STATUS
>+EFIAPI
>+SmmAccessPeiLock (
>+  IN EFI_PEI_SERVICES                **PeiServices,
>+  IN PEI_SMM_ACCESS_PPI              *This,
>+  IN UINTN                           DescriptorIndex
>+  )
>+{
>+  if (DescriptorIndex >= DescIdxCount) {
>+    return EFI_INVALID_PARAMETER;
>+  }
>+
>+  //
>+  // According to current practice, DescriptorIndex is not considered at all,
>+  // beyond validating it.
>+  //
>+  return SmramAccessLock (&This->LockState, &This->OpenState);
>+}
>+
>+/**
>+  Queries the memory controller for the possible regions that will support
>+  SMRAM.
>+
>+  @param  PeiServices           General purpose services available to every
>+                                PEIM.
>+  @param This                   The pointer to the SmmAccessPpi Interface.
>+  @param SmramMapSize           The pointer to the variable containing size
>of
>+                                the buffer to contain the description
>+                                information.
>+  @param SmramMap               The buffer containing the data describing the
>+                                Smram region descriptors.
>+
>+  @retval EFI_BUFFER_TOO_SMALL  The user did not provide a sufficient
>buffer.
>+  @retval EFI_SUCCESS           The user provided a sufficiently-sized buffer.
>+
>+**/
>+STATIC
>+EFI_STATUS
>+EFIAPI
>+SmmAccessPeiGetCapabilities (
>+  IN EFI_PEI_SERVICES                **PeiServices,
>+  IN PEI_SMM_ACCESS_PPI              *This,
>+  IN OUT UINTN                       *SmramMapSize,
>+  IN OUT EFI_SMRAM_DESCRIPTOR        *SmramMap
>+  )
>+{
>+  return SmramAccessGetCapabilities (This->LockState, This->OpenState,
>+           SmramMapSize, SmramMap);
>+}
>+
>+//
>+// LockState and OpenState will be filled in by the entry point.
>+//
>+STATIC PEI_SMM_ACCESS_PPI mAccess = {
>+  &SmmAccessPeiOpen,
>+  &SmmAccessPeiClose,
>+  &SmmAccessPeiLock,
>+  &SmmAccessPeiGetCapabilities
>+};
>+
>+
>+STATIC EFI_PEI_PPI_DESCRIPTOR mPpiList[] = {
>+  {
>+    EFI_PEI_PPI_DESCRIPTOR_PPI,
>+    &gEfiPeiSmmCommunicationPpiGuid, &mCommunication
>+  },
>+  {
>+    EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
>+    &gPeiSmmAccessPpiGuid, &mAccess
>+  }
>+};
>+
>+
>+//
>+// Utility functions.
>+//
>+STATIC
>+UINT8
>+CmosRead8 (
>+  IN UINT8 Index
>+  )
>+{
>+  IoWrite8 (0x70, Index);
>+  return IoRead8 (0x71);
>+}
>+
>+STATIC
>+UINT32
>+GetSystemMemorySizeBelow4gb (
>+  VOID
>+  )
>+{
>+  UINT32 Cmos0x34;
>+  UINT32 Cmos0x35;
>+
>+  Cmos0x34 = CmosRead8 (0x34);
>+  Cmos0x35 = CmosRead8 (0x35);
>+
>+  return ((Cmos0x35 << 8 | Cmos0x34) << 16) + SIZE_16MB;
>+}
>+
>+
>+//
>+// Entry point of this driver.
>+//
>+EFI_STATUS
>+EFIAPI
>+SmmAccessPeiEntryPoint (
>+  IN       EFI_PEI_FILE_HANDLE  FileHandle,
>+  IN CONST EFI_PEI_SERVICES     **PeiServices
>+  )
>+{
>+  UINT16               HostBridgeDevId;
>+  UINT8                EsmramcVal;
>+  UINT8                RegMask8;
>+  UINT32               TopOfLowRam, TopOfLowRamMb;
>+  EFI_STATUS           Status;
>+  UINTN                SmramMapSize;
>+  EFI_SMRAM_DESCRIPTOR SmramMap[DescIdxCount];
>+  VOID                 *GuidHob;
>+
>+  //
>+  // This module should only be included if SMRAM support is required.
>+  //
>+  ASSERT (FeaturePcdGet (PcdSmmSmramRequire));
>+
>+  //
>+  // Verify if we're running on a Q35 machine type.
>+  //
>+  HostBridgeDevId = PciRead16 (OVMF_HOSTBRIDGE_DID);
>+  if (HostBridgeDevId != INTEL_Q35_MCH_DEVICE_ID) {
>+    DEBUG ((EFI_D_ERROR, "%a: no SMRAM with host bridge DID=0x%04x;
>only "
>+      "DID=0x%04x (Q35) is supported\n", __FUNCTION__, HostBridgeDevId,
>+      INTEL_Q35_MCH_DEVICE_ID));
>+    goto WrongConfig;
>+  }
>+
>+  //
>+  // Confirm if QEMU supports SMRAM.
>+  //
>+  // With no support for it, the ESMRAMC (Extended System Management
>RAM
>+  // Control) register reads as zero. If there is support, the cache-enable
>+  // bits are hard-coded as 1 by QEMU.
>+  //
>+  EsmramcVal = PciRead8 (DRAMC_REGISTER_Q35 (MCH_ESMRAMC));
>+  RegMask8 = MCH_ESMRAMC_SM_CACHE | MCH_ESMRAMC_SM_L1 |
>MCH_ESMRAMC_SM_L2;
>+  if ((EsmramcVal & RegMask8) != RegMask8) {
>+    DEBUG ((EFI_D_ERROR, "%a: this Q35 implementation lacks SMRAM\n",
>+      __FUNCTION__));
>+    goto WrongConfig;
>+  }
>+
>+  TopOfLowRam = GetSystemMemorySizeBelow4gb ();
>+  ASSERT ((TopOfLowRam & (SIZE_1MB - 1)) == 0);
>+  TopOfLowRamMb = TopOfLowRam >> 20;
>+
>+  //
>+  // Some of the following registers are no-ops for QEMU at the moment, but
>it
>+  // is recommended to set them correctly, since the ESMRAMC that we
>ultimately
>+  // care about is in the same set of registers.
>+  //
>+  // First, we disable the integrated VGA, and set both the GTT Graphics
>Memory
>+  // Size and the Graphics Mode Select memory pre-allocation fields to zero.
>+  // This takes just one write to the Graphics Control Register.
>+  //
>+  PciWrite16 (DRAMC_REGISTER_Q35 (MCH_GGC), MCH_GGC_IVD);
>+
>+  //
>+  // Set Top of Low Usable DRAM.
>+  //
>+  PciWrite16 (DRAMC_REGISTER_Q35 (MCH_TOLUD),
>+    (UINT16)(TopOfLowRamMb << MCH_TOLUD_MB_SHIFT));
>+
>+  //
>+  // Given the zero graphics memory sizes configured above, set the
>+  // graphics-related stolen memory bases to the same as TOLUD.
>+  //
>+  PciWrite32 (DRAMC_REGISTER_Q35 (MCH_GBSM),
>+    TopOfLowRamMb << MCH_GBSM_MB_SHIFT);
>+  PciWrite32 (DRAMC_REGISTER_Q35 (MCH_BGSM),
>+    TopOfLowRamMb << MCH_BGSM_MB_SHIFT);
>+
>+  //
>+  // Set TSEG Memory Base.
>+  //
>+  PciWrite32 (DRAMC_REGISTER_Q35 (MCH_TSEGMB),
>+    (TopOfLowRamMb - FixedPcdGet8 (PcdQ35TsegMbytes)) <<
>MCH_TSEGMB_MB_SHIFT);
>+
>+  //
>+  // Set TSEG size, and disable TSEG visibility outside of SMM. Note that the
>+  // T_EN bit has inverse meaning; when T_EN is set, then TSEG visibility is
>+  // *restricted* to SMM.
>+  //
>+  EsmramcVal &= ~(UINT32)MCH_ESMRAMC_TSEG_MASK;
>+  EsmramcVal |= FixedPcdGet8 (PcdQ35TsegMbytes) == 8 ?
>MCH_ESMRAMC_TSEG_8MB :
>+                FixedPcdGet8 (PcdQ35TsegMbytes) == 2 ?
>MCH_ESMRAMC_TSEG_2MB :
>+                MCH_ESMRAMC_TSEG_1MB;
>+  EsmramcVal |= MCH_ESMRAMC_T_EN;
>+  PciWrite8 (DRAMC_REGISTER_Q35 (MCH_ESMRAMC), EsmramcVal);
>+
>+  //
>+  // TSEG should be closed (see above), but unlocked, initially. Set
>G_SMRAME
>+  // (Global SMRAM Enable) too, as both D_LCK and T_EN depend on it.
>+  //
>+  PciAndThenOr8 (DRAMC_REGISTER_Q35 (MCH_SMRAM),
>+    (UINT8)((~(UINT32)MCH_SMRAM_D_LCK) & 0xff),
>MCH_SMRAM_G_SMRAME);
>+
>+  //
>+  // Create the GUID HOB and point it to the first SMRAM range.
>+  //
>+  GetStates (&mAccess.LockState, &mAccess.OpenState);
>+  SmramMapSize = sizeof SmramMap;
>+  Status = SmramAccessGetCapabilities (mAccess.LockState,
>mAccess.OpenState,
>+             &SmramMapSize, SmramMap);
>+  ASSERT_EFI_ERROR (Status);
>+
>+  DEBUG_CODE_BEGIN ();
>+  {
>+    UINTN Count;
>+    UINTN Idx;
>+
>+    Count = SmramMapSize / sizeof SmramMap[0];
>+    DEBUG ((EFI_D_VERBOSE, "%a: SMRAM map follows, %d entries\n",
>__FUNCTION__,
>+      (INT32)Count));
>+    DEBUG ((EFI_D_VERBOSE, "% 20a % 20a % 20a % 20a\n",
>"PhysicalStart(0x)",
>+      "PhysicalSize(0x)", "CpuStart(0x)", "RegionState(0x)"));
>+    for (Idx = 0; Idx < Count; ++Idx) {
>+      DEBUG ((EFI_D_VERBOSE, "% 20Lx % 20Lx % 20Lx % 20Lx\n",
>+        SmramMap[Idx].PhysicalStart, SmramMap[Idx].PhysicalSize,
>+        SmramMap[Idx].CpuStart, SmramMap[Idx].RegionState));
>+    }
>+  }
>+  DEBUG_CODE_END ();
>+
>+  GuidHob = BuildGuidHob (&gEfiAcpiVariableGuid,
>+    sizeof SmramMap[DescIdxSmmS3ResumeState]);
>+  if (GuidHob == NULL) {
>+    return EFI_OUT_OF_RESOURCES;
>+  }
>+
>+  CopyMem (GuidHob, &SmramMap[DescIdxSmmS3ResumeState],
>+    sizeof SmramMap[DescIdxSmmS3ResumeState]);
>+
>+  //
>+  // We're done. The next step should succeed, but even if it fails, we can't
>+  // roll back the above BuildGuidHob() allocation, because PEI doesn't
>support
>+  // releasing memory.
>+  //
>+  return PeiServicesInstallPpi (mPpiList);
>+
>+WrongConfig:
>+  //
>+  // We really don't want to continue in this case.
>+  //
>+  // _ASSERT() is never compiled out, and it respects PcdDebugPropertyMask
>(ie.
>+  // prevent further execution with CPU breakpoint vs. dead loop).
>+  //
>+  _ASSERT (FALSE);
>+  return EFI_UNSUPPORTED;
>+}
>diff --git a/OvmfPkg/SmmAccess/SmramInternal.c
>b/OvmfPkg/SmmAccess/SmramInternal.c
>new file mode 100644
>index 0000000..c3267ca
>--- /dev/null
>+++ b/OvmfPkg/SmmAccess/SmramInternal.c
>@@ -0,0 +1,188 @@
>+/** @file
>+
>+  Functions and types shared by the SMM accessor PEI and DXE modules.
>+
>+  Copyright (C) 2015, Red Hat, Inc.
>+
>+  This program and the accompanying materials are licensed and made
>available
>+  under the terms and conditions of the BSD License which accompanies this
>+  distribution. The full text of the license may be found at
>+  http://opensource.org/licenses/bsd-license.php
>+
>+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
>BASIS, WITHOUT
>+  WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR
>IMPLIED.
>+
>+**/
>+
>+#include <Guid/AcpiS3Context.h>
>+#include <IndustryStandard/Q35MchIch9.h>
>+#include <Library/DebugLib.h>
>+#include <Library/PciLib.h>
>+
>+#include "SmramInternal.h"
>+
>+/**
>+  Read the MCH_SMRAM and ESMRAMC registers, and update the LockState
>and
>+  OpenState fields in the PEI_SMM_ACCESS_PPI /
>EFI_SMM_ACCESS2_PROTOCOL object,
>+  from the D_LCK and T_EN bits.
>+
>+  PEI_SMM_ACCESS_PPI and EFI_SMM_ACCESS2_PROTOCOL member
>functions can rely on
>+  the LockState and OpenState fields being up-to-date on entry, and they
>need
>+  to restore the same invariant on exit, if they touch the bits in question.
>+
>+  @param[out] LockState  Reflects the D_LCK bit on output; TRUE iff SMRAM
>is
>+                         locked.
>+  @param[out] OpenState  Reflects the inverse of the T_EN bit on output;
>TRUE
>+                         iff SMRAM is open.
>+**/
>+VOID
>+GetStates (
>+  OUT BOOLEAN *LockState,
>+  OUT BOOLEAN *OpenState
>+)
>+{
>+  UINT8 SmramVal, EsmramcVal;
>+
>+  SmramVal   = PciRead8 (DRAMC_REGISTER_Q35 (MCH_SMRAM));
>+  EsmramcVal = PciRead8 (DRAMC_REGISTER_Q35 (MCH_ESMRAMC));
>+
>+  *LockState = !!(SmramVal & MCH_SMRAM_D_LCK);
>+  *OpenState = !(EsmramcVal & MCH_ESMRAMC_T_EN);
>+}
>+
>+//
>+// The functions below follow the PEI_SMM_ACCESS_PPI and
>+// EFI_SMM_ACCESS2_PROTOCOL member declarations. The PeiServices and
>This
>+// pointers are removed (TSEG doesn't depend on them), and so is the
>+// DescriptorIndex parameter (TSEG doesn't support range-wise locking).
>+//
>+// The LockState and OpenState members that are common to both
>+// PEI_SMM_ACCESS_PPI and EFI_SMM_ACCESS2_PROTOCOL are taken and
>updated in
>+// isolation from the rest of the (non-shared) members.
>+//
>+
>+EFI_STATUS
>+SmramAccessOpen (
>+  OUT BOOLEAN *LockState,
>+  OUT BOOLEAN *OpenState
>+  )
>+{
>+  //
>+  // Open TSEG by clearing T_EN.
>+  //
>+  PciAnd8 (DRAMC_REGISTER_Q35 (MCH_ESMRAMC),
>+    (UINT8)((~(UINT32)MCH_ESMRAMC_T_EN) & 0xff));
>+
>+  GetStates (LockState, OpenState);
>+  if (!*OpenState) {
>+    return EFI_DEVICE_ERROR;
>+  }
>+  return EFI_SUCCESS;
>+}
>+
>+EFI_STATUS
>+SmramAccessClose (
>+  OUT BOOLEAN *LockState,
>+  OUT BOOLEAN *OpenState
>+  )
>+{
>+  //
>+  // Close TSEG by setting T_EN.
>+  //
>+  PciOr8 (DRAMC_REGISTER_Q35 (MCH_ESMRAMC), MCH_ESMRAMC_T_EN);
>+
>+  GetStates (LockState, OpenState);
>+  if (*OpenState) {
>+    return EFI_DEVICE_ERROR;
>+  }
>+  return EFI_SUCCESS;
>+}
>+
>+EFI_STATUS
>+SmramAccessLock (
>+  OUT    BOOLEAN *LockState,
>+  IN OUT BOOLEAN *OpenState
>+  )
>+{
>+  if (*OpenState) {
>+    return EFI_DEVICE_ERROR;
>+  }
>+
>+  //
>+  // Close & lock TSEG by setting T_EN and D_LCK.
>+  //
>+  PciOr8 (DRAMC_REGISTER_Q35 (MCH_ESMRAMC), MCH_ESMRAMC_T_EN);
>+  PciOr8 (DRAMC_REGISTER_Q35 (MCH_SMRAM),   MCH_SMRAM_D_LCK);
>+
>+  GetStates (LockState, OpenState);
>+  if (*OpenState || !*LockState) {
>+    return EFI_DEVICE_ERROR;
>+  }
>+  return EFI_SUCCESS;
>+}
>+
>+EFI_STATUS
>+SmramAccessGetCapabilities (
>+  IN BOOLEAN                  LockState,
>+  IN BOOLEAN                  OpenState,
>+  IN OUT UINTN                *SmramMapSize,
>+  IN OUT EFI_SMRAM_DESCRIPTOR *SmramMap
>+  )
>+{
>+  UINTN  OriginalSize;
>+  UINT32 TsegMemoryBaseMb, TsegMemoryBase;
>+  UINT64 CommonRegionState;
>+  UINT8  TsegSizeBits;
>+
>+  OriginalSize  = *SmramMapSize;
>+  *SmramMapSize = DescIdxCount * sizeof *SmramMap;
>+  if (OriginalSize < *SmramMapSize) {
>+    return EFI_BUFFER_TOO_SMALL;
>+  }
>+
>+  //
>+  // Read the TSEG Memory Base register.
>+  //
>+  TsegMemoryBaseMb = PciRead32 (DRAMC_REGISTER_Q35 (MCH_TSEGMB));
>+  TsegMemoryBase = (TsegMemoryBaseMb >> MCH_TSEGMB_MB_SHIFT) <<
>20;
>+
>+  //
>+  // Precompute the region state bits that will be set for all regions.
>+  //
>+  CommonRegionState = (OpenState ? EFI_SMRAM_OPEN :
>EFI_SMRAM_CLOSED) |
>+                      (LockState ? EFI_SMRAM_LOCKED : 0) |
>+                      EFI_CACHEABLE;
>+
>+  //
>+  // The first region hosts an SMM_S3_RESUME_STATE object. It is located at
>the
>+  // start of TSEG. We round up the size to whole pages, and we report it as
>+  // EFI_ALLOCATED, so that the SMM_CORE stays away from it.
>+  //
>+  SmramMap[DescIdxSmmS3ResumeState].PhysicalStart = TsegMemoryBase;
>+  SmramMap[DescIdxSmmS3ResumeState].CpuStart      = TsegMemoryBase;
>+  SmramMap[DescIdxSmmS3ResumeState].PhysicalSize  =
>+    EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (sizeof
>(SMM_S3_RESUME_STATE)));
>+  SmramMap[DescIdxSmmS3ResumeState].RegionState   =
>+    CommonRegionState | EFI_ALLOCATED;
>+
>+  //
>+  // Get the TSEG size bits from the ESMRAMC register.
>+  //
>+  TsegSizeBits = PciRead8 (DRAMC_REGISTER_Q35 (MCH_ESMRAMC)) &
>+                 MCH_ESMRAMC_TSEG_MASK;
>+
>+  //
>+  // The second region is the main one, following the first.
>+  //
>+  SmramMap[DescIdxMain].PhysicalStart =
>+    SmramMap[DescIdxSmmS3ResumeState].PhysicalStart +
>+    SmramMap[DescIdxSmmS3ResumeState].PhysicalSize;
>+  SmramMap[DescIdxMain].CpuStart =
>SmramMap[DescIdxMain].PhysicalStart;
>+  SmramMap[DescIdxMain].PhysicalSize =
>+    (TsegSizeBits == MCH_ESMRAMC_TSEG_8MB ? SIZE_8MB :
>+     TsegSizeBits == MCH_ESMRAMC_TSEG_2MB ? SIZE_2MB :
>+     SIZE_1MB) - SmramMap[DescIdxSmmS3ResumeState].PhysicalSize;
>+  SmramMap[DescIdxMain].RegionState = CommonRegionState;
>+
>+  return EFI_SUCCESS;
>+}
>--
>1.8.3.1
>

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to