Laszlo,

Minor comments included below.  I know from later items in this thread that 
SMM_COMMUNICATE has already been removed in your local branch.

Reviewed-by: Michael Kinney <michael.d.kin...@intel.com>

Mike

> -----Original Message-----
> From: Laszlo Ersek [mailto:ler...@redhat.com]
> Sent: Tuesday, November 3, 2015 1:01 PM
> To: edk2-de...@ml01.01.org
> Cc: Kinney, Michael D <michael.d.kin...@intel.com>; Justen, Jordan L 
> <jordan.l.jus...@intel.com>
> 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

Missing source file SmramInternal.h


> +
> +[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

Comment should be:      ## PRODUCES

> +
> +[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

Recommend removing 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

Recommend removing 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

Recommend removing 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

Recommend removing 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
> +};

Recommend removing STATIC
Global variables should be before function implementations

> +
> +
> +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
> +  }
> +};

Recommend removing STATIC

> +
> +
> +//
> +// Utility functions.
> +//
> +STATIC

Recommend removing STATIC

> +UINT8
> +CmosRead8 (
> +  IN UINT8 Index
> +  )
> +{
> +  IoWrite8 (0x70, Index);
> +  return IoRead8 (0x71);
> +}
> +
> +STATIC

Recommend removing 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