Laszlo,

Thanks for the details.  Your implementation looks good.

I will discuss this further with Jiewen to see if it makes sense to provide 
additional implementations of this PPI that could be shared by multiple 
platforms.

Thanks,

Mike

>-----Original Message-----
>From: edk2-devel [mailto:edk2-devel-boun...@lists.01.org] On Behalf Of
>Laszlo Ersek
>Sent: Thursday, November 05, 2015 3:15 AM
>To: Kinney, Michael D; edk2-de...@ml01.01.org
>Cc: Justen, Jordan L
>Subject: Re: [edk2] [PATCH v4 07/41] OvmfPkg: add PEIM for providing TSEG-
>as-SMRAM during PEI
>
>On 11/05/15 02:32, Kinney, Michael D wrote:
>> Laszlo,
>>
>> For the EFI_PEI_COMMUNICATION_PPI, is there a reason you are not using
>> UefiCpuPkg\PiSmmCommunication\PiSmmCommunicationPei.inf to produce
>that PPI?
>
>Yes.
>
>When I wrote this patch originally on April 27th and the days after,
>there was no EFI_PEI_COMMUNICATION_PPI implementation in edk2; neither
>were plans known to add one.
>
>In addition, we had discussed the behavior of SmmLockBoxPeiLib at
>length, in an off-list thread that you had been CC'd on. Please search
>your archives for the message with the following metadata, and the
>sub-thread rooted in it:
>
>Message-ID: <553f96cc.9050...@redhat.com>
>Date:       Tue, 28 Apr 2015 16:18:52 +0200
>From:       Laszlo Ersek <ler...@redhat.com>
>To:         Yao, Jiewen <jiewen....@intel.com>
>CC:         Justen, Jordan L <jordan.l.jus...@intel.com>,
>            Zimmer, Vincent <vincent.zim...@intel.com>,
>            Kinney, Michael D <michael.d.kin...@intel.com>,
>            Paolo Bonzini <pbonz...@redhat.com>,
>            Gerd Hoffmann <kra...@redhat.com>,
>            Michael S. Tsirkin <m...@redhat.com>
>Subject:    Re: open-sourcing Intel's "IA32FamilyCpuPkg/PiSmmCpuDxeSmm"
>
>In that message, I asked:
>
>> In the whitepaper entitled "A Tour Beyond BIOS: Implementing S3 Resume
>> with EDKII", page 25 says, under the heading "PEI Instance":
>>
>> The PEI instance of SmmLockboxLib has two ways to communicate with
>> the LockBox in SMRAM.
>>
>> 1) It uses the SMM_COMMUNICATION PPI to communicate the SmmLockbox
>> service provider, similar as DXE instance.
>> 2) When the PEI instance is used before SMM ready, the
>> SMM_COMMUNICATION PPI will return EFI_NOT_STARTED. In this case,
>> PEI SmmLockBoxLib needs to search the SMRAM region directly to
>> find LockBox content.
>>
>> The question is why a platform would choose option (1), ever.
>>
>> Namely, option (1) depends on additional drivers:
>> - SMM_COMMUNICATION_PPI that actually works
>> - (which might further depend on PEI_SMM_CONTROL_PPI)
>> - a PEIM driver that implements the privileged (SMM) half of lockbox
>>
>> Whereas, option (2) is much simpler for the platform. It just needs to
>> provide a minimal SMM_COMMUNICATION_PPI where it always returns
>> EFI_NOT_STARTED. Then the lockbox library will do everything (and
>> depend only on PEI_SMM_ACCESS_PPI).
>>
>> So, the question is: why would a platform ever pick (1), given that it
>> is much more work to implement, for (as far as I can see) no benefit?
>
>And Jiewen replied (the same day),
>
>> Ah, I see. The only reason is that: A PEIM might need to restore
>> lockbox data *before* SMM rebase happen. Then it has to use #2.
>>
>> A PEIM might need to restore lockbox data *after* SMM rebase happen.
>> Then it has to use #1. (Scanning SMRAM does not work at that moment,
>> which is enforced by SMRR)
>
>I couldn't see any grounds from Jiewen's answer to abandon option (2).
>Option (2) actually worked, plus it was actually the *only* possibility
>to make SmmLockboxLib work in OVMF (see above).
>
>I would like to stick with this approach.
>
>Thanks
>Laszlo
>
>>
>> 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
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to