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

Unfortunately, when SmmLockBoxPeiLib does the parsing itself, it needs a
pointer to the SMST. SMM data is strongly protected from non-SMM drivers
-- the intent is that SMM data cannot be fetched from the outside, except
through the validated Communication interfaces (DXE protocol or PPI).

Hence, both ways SmmLockBoxPeiLib could work are rough -- either a full
EFI_PEI_SMM_COMMUNICATION_PPI infrastructure would have to be built (edk2
contains none) that switches diligently between trusted SMM and untrusted
third party PEIMs, or SmmLockBoxPeiLib needs access to the SMST saved from
before S3 Suspend (which expressly conflicts with the intent of SMM).

This driver retrieves the address of the SMST leaked by the
DiscloseSmstSmm driver, and passes it as a GUIDed HOB to S3Resume2Pei
(added later in the series). S3Resume2Pei is the PEIM that exercises
SmmLockBoxPeiLib.

The load / installation order of S3Resume2Pei and EmuSmmPei is
indifferent. EmuSmmPei 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.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <ler...@redhat.com>
---
 OvmfPkg/EmuSmmPei/EmuSmmPei.inf |  60 +++++++++
 OvmfPkg/EmuSmmPei/EmuSmmPei.c   | 285 ++++++++++++++++++++++++++++++++++++++++
 OvmfPkg/OvmfPkgX64.dsc          |   4 +
 OvmfPkg/OvmfPkgX64.fdf          |   1 +
 4 files changed, 350 insertions(+)
 create mode 100644 OvmfPkg/EmuSmmPei/EmuSmmPei.inf
 create mode 100644 OvmfPkg/EmuSmmPei/EmuSmmPei.c

diff --git a/OvmfPkg/EmuSmmPei/EmuSmmPei.inf b/OvmfPkg/EmuSmmPei/EmuSmmPei.inf
new file mode 100644
index 0000000..bbdb5e0
--- /dev/null
+++ b/OvmfPkg/EmuSmmPei/EmuSmmPei.inf
@@ -0,0 +1,60 @@
+## @file
+# PEI module emulating SMRAM access by producing PEI_SMM_ACCESS_PPI and
+# EFI_PEI_SMM_COMMUNICATION_PPI.
+#
+# Copyright (C) 2013, 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                      = EmuSmmPei
+  FILE_GUID                      = F50DB7D2-FAD9-4E89-A8B4-BC4218C4D025
+  MODULE_TYPE                    = PEIM
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = EmuSmmPeiEntryPoint
+
+#
+# The following information is for reference only and not required by the 
build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC
+#
+
+[Sources]
+  EmuSmmPei.c
+
+[Packages]
+  MdeModulePkg/MdeModulePkg.dec
+  MdePkg/MdePkg.dec
+  OvmfPkg/OvmfPkg.dec
+
+[Guids]
+  gEfiAcpiVariableGuid
+
+[LibraryClasses]
+  BaseMemoryLib
+  DebugLib
+  HobLib
+  PcdLib
+  PeiServicesLib
+  PeimEntryPoint
+
+[Pcd]
+  gUefiOvmfPkgTokenSpaceGuid.PcdEmuSmmAreaBase
+  gUefiOvmfPkgTokenSpaceGuid.PcdEmuSmmAreaSize
+  gUefiOvmfPkgTokenSpaceGuid.PcdDiscloseSmstPtrPtr
+
+[Ppis]
+  gEfiPeiSmmCommunicationPpiGuid # PPI ALWAYS_PRODUCED
+  gPeiSmmAccessPpiGuid           # PPI ALWAYS_PRODUCED
+
+[Depex]
+  TRUE
diff --git a/OvmfPkg/EmuSmmPei/EmuSmmPei.c b/OvmfPkg/EmuSmmPei/EmuSmmPei.c
new file mode 100644
index 0000000..82ada54
--- /dev/null
+++ b/OvmfPkg/EmuSmmPei/EmuSmmPei.c
@@ -0,0 +1,285 @@
+/** @file
+
+  PEI module emulating SMRAM access by producing PEI_SMM_ACCESS_PPI and
+  EFI_PEI_SMM_COMMUNICATION_PPI.
+
+  Copyright (C) 2013, 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/PcdLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Ppi/SmmAccess.h>
+#include <Ppi/SmmCommunication.h>
+
+/**
+  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
+EmuSmmCommunicationCommunicate (
+  IN CONST EFI_PEI_SMM_COMMUNICATION_PPI   *This,
+  IN OUT VOID                              *CommBuffer,
+  IN OUT UINTN                             *CommSize
+  )
+{
+  return EFI_NOT_STARTED;
+}
+
+
+STATIC EFI_PEI_SMM_COMMUNICATION_PPI mCommunication = {
+  &EmuSmmCommunicationCommunicate
+};
+
+
+STATIC PEI_SMM_ACCESS_PPI mAccess;
+
+
+/**
+  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
+EmuSmmPeiAccessOpen (
+  IN EFI_PEI_SERVICES                **PeiServices,
+  IN PEI_SMM_ACCESS_PPI              *This,
+  IN UINTN                           DescriptorIndex
+  )
+{
+  if (DescriptorIndex > 0) {
+    return EFI_INVALID_PARAMETER;
+  }
+  if (mAccess.LockState) {
+    return EFI_DEVICE_ERROR;
+  }
+  mAccess.OpenState = TRUE;
+  return EFI_SUCCESS;
+}
+
+
+/**
+  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
+EmuSmmPeiAccessClose (
+  IN EFI_PEI_SERVICES                **PeiServices,
+  IN PEI_SMM_ACCESS_PPI              *This,
+  IN UINTN                           DescriptorIndex
+  )
+{
+  if (DescriptorIndex > 0) {
+    return EFI_INVALID_PARAMETER;
+  }
+  if (mAccess.LockState) {
+    return EFI_DEVICE_ERROR;
+  }
+  mAccess.OpenState = FALSE;
+  return EFI_SUCCESS;
+}
+
+
+/**
+  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
+EmuSmmPeiAccessLock (
+  IN EFI_PEI_SERVICES                **PeiServices,
+  IN PEI_SMM_ACCESS_PPI              *This,
+  IN UINTN                           DescriptorIndex
+  )
+{
+  if (DescriptorIndex > 0) {
+    return EFI_INVALID_PARAMETER;
+  }
+  if (mAccess.OpenState) {
+    return EFI_DEVICE_ERROR;
+  }
+  mAccess.LockState = TRUE;
+  return EFI_SUCCESS;
+}
+
+
+/**
+  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
+EmuSmmPeiAccessGetCapabilities (
+  IN EFI_PEI_SERVICES                **PeiServices,
+  IN PEI_SMM_ACCESS_PPI              *This,
+  IN OUT UINTN                       *SmramMapSize,
+  IN OUT EFI_SMRAM_DESCRIPTOR        *SmramMap
+  )
+{
+  UINTN OrigSize;
+
+  OrigSize      = *SmramMapSize;
+  *SmramMapSize = sizeof *SmramMap; // 1 record
+  if (OrigSize < *SmramMapSize) {
+    return EFI_BUFFER_TOO_SMALL;
+  }
+
+  SmramMap->PhysicalStart = PcdGet64 (PcdEmuSmmAreaBase);
+  SmramMap->CpuStart      = SmramMap->PhysicalStart;
+  SmramMap->PhysicalSize  = PcdGet32 (PcdEmuSmmAreaSize);
+  SmramMap->RegionState   = mAccess.LockState ? EFI_SMRAM_LOCKED :
+                            mAccess.OpenState ? EFI_SMRAM_OPEN :
+                            EFI_SMRAM_CLOSED;
+
+  ASSERT (SmramMap->PhysicalStart != 0);
+  DEBUG ((EFI_D_INFO, "EmuSmmPeiAccessGetCapabilities: "
+    "SMRAM Start=0x%Lx Size=0x%Lx\n",
+    SmramMap->PhysicalStart, SmramMap->PhysicalSize));
+  return EFI_SUCCESS;
+}
+
+
+STATIC PEI_SMM_ACCESS_PPI mAccess = {
+  &EmuSmmPeiAccessOpen,
+  &EmuSmmPeiAccessClose,
+  &EmuSmmPeiAccessLock,
+  &EmuSmmPeiAccessGetCapabilities,
+  FALSE,                           // initial LockState
+  TRUE                             // initial OpenState
+};
+
+
+STATIC EFI_PEI_PPI_DESCRIPTOR mPpiSmmCommunication[] = {
+  {
+    EFI_PEI_PPI_DESCRIPTOR_PPI,
+    &gEfiPeiSmmCommunicationPpiGuid, &mCommunication
+  },
+  {
+    EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
+    &gPeiSmmAccessPpiGuid, &mAccess
+  }
+};
+
+
+STATIC SMM_S3_RESUME_STATE mResumeState;
+
+
+EFI_STATUS
+EFIAPI
+EmuSmmPeiEntryPoint (
+  IN       EFI_PEI_FILE_HANDLE  FileHandle,
+  IN CONST EFI_PEI_SERVICES     **PeiServices
+  )
+{
+  UINT64               *DiscloseSmstPtrPtr;
+  EFI_SMRAM_DESCRIPTOR *SmramDesc;
+
+  if (PcdGet32 (PcdEmuSmmAreaSize) == 0) {
+    return EFI_UNSUPPORTED;
+  }
+
+  DiscloseSmstPtrPtr = (UINT64 *)(UINTN) PcdGet64 (PcdDiscloseSmstPtrPtr);
+  if (DiscloseSmstPtrPtr == NULL) {
+    return EFI_UNSUPPORTED;
+  }
+
+  mResumeState.Smst = (EFI_PHYSICAL_ADDRESS) *DiscloseSmstPtrPtr;
+
+  SmramDesc = (EFI_SMRAM_DESCRIPTOR *) BuildGuidHob (&gEfiAcpiVariableGuid,
+                                         sizeof (EFI_SMRAM_DESCRIPTOR));
+  if (SmramDesc == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+  ZeroMem (SmramDesc, sizeof *SmramDesc);
+  SmramDesc->CpuStart = (EFI_PHYSICAL_ADDRESS)(UINTN) &mResumeState;
+
+  return PeiServicesInstallPpi (mPpiSmmCommunication);
+}
diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc
index d12faee..3faccae 100644
--- a/OvmfPkg/OvmfPkgX64.dsc
+++ b/OvmfPkg/OvmfPkgX64.dsc
@@ -402,10 +402,14 @@
 
   OvmfPkg/PlatformPei/PlatformPei.inf {
     <LibraryClasses>
       PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
   }
+  OvmfPkg/EmuSmmPei/EmuSmmPei.inf {
+    <LibraryClasses>
+      PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
+  }
 
   #
   # DXE Phase modules
   #
   MdeModulePkg/Core/Dxe/DxeMain.inf {
diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf
index f7b903a..7a80330 100644
--- a/OvmfPkg/OvmfPkgX64.fdf
+++ b/OvmfPkg/OvmfPkgX64.fdf
@@ -256,10 +256,11 @@ APRIORI PEI {
 INF  MdeModulePkg/Core/Pei/PeiMain.inf
 INF  MdeModulePkg/Universal/PCD/Pei/Pcd.inf
 INF  IntelFrameworkModulePkg/Universal/StatusCode/Pei/StatusCodePei.inf
 INF  OvmfPkg/PlatformPei/PlatformPei.inf
 INF  MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
+INF  OvmfPkg/EmuSmmPei/EmuSmmPei.inf
 
 FILE FV_IMAGE = A4EF5A93-3F1B-4232-A1C4-F0910E6D1D9C {
   SECTION COMPRESS PI_NONE {
     SECTION FV_IMAGE = DXEFV
   }
-- 
1.8.3.1



------------------------------------------------------------------------------
Rapidly troubleshoot problems before they affect your business. Most IT 
organizations don't have a clear picture of how application performance 
affects their revenue. With AppDynamics, you get 100% visibility into your 
Java,.NET, & PHP application. Start your 15-day FREE TRIAL of AppDynamics Pro!
http://pubads.g.doubleclick.net/gampad/clk?id=84349351&iu=/4140/ostg.clktrk
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/edk2-devel

Reply via email to