OvmfPkg: add PEIM for providing TSEG-as-SMRAM during PEI
"MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxPeiLib.inf" is the
LockBoxLib instance with SMRAM access for the PEI phase.
Said library instance must, and can, access the LockBox data in SMRAM
directly if it is invoked before SMBASE relocation / SMI handler
installation. In that case, it only needs PEI_SMM_ACCESS_PPI from the
platform, and it doesn't depend on EFI_PEI_SMM_COMMUNICATION_PPI.
OVMF satisfies the description in SVN r18823 ("MdeModulePkg:
SmmLockBoxPeiLib: work without EFI_PEI_SMM_COMMUNICATION_PPI"): in OVMF,
only S3Resume2Pei links against SmmLockBoxPeiLib.
Therefore, introduce a PEIM that produces the PEI_SMM_ACCESS_PPI
interface, enabling SmmLockBoxPeiLib to work; we can omit including
"UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationPei.inf".
The load / installation order of S3Resume2Pei and SmmAccessPei is
indifferent. SmmAccessPei produces the gEfiAcpiVariableGuid 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.kinney@intel.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Michael Kinney <michael.d.kinney@intel.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@19040 6f19259b-4bc3-4df7-8a09-765794883524
2015-11-30 19:41:38 +01:00
|
|
|
/** @file
|
|
|
|
|
|
|
|
Functions and types shared by the SMM accessor PEI and DXE modules.
|
|
|
|
|
|
|
|
Copyright (C) 2015, Red Hat, Inc.
|
|
|
|
|
2019-04-04 01:06:33 +02:00
|
|
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
OvmfPkg: add PEIM for providing TSEG-as-SMRAM during PEI
"MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxPeiLib.inf" is the
LockBoxLib instance with SMRAM access for the PEI phase.
Said library instance must, and can, access the LockBox data in SMRAM
directly if it is invoked before SMBASE relocation / SMI handler
installation. In that case, it only needs PEI_SMM_ACCESS_PPI from the
platform, and it doesn't depend on EFI_PEI_SMM_COMMUNICATION_PPI.
OVMF satisfies the description in SVN r18823 ("MdeModulePkg:
SmmLockBoxPeiLib: work without EFI_PEI_SMM_COMMUNICATION_PPI"): in OVMF,
only S3Resume2Pei links against SmmLockBoxPeiLib.
Therefore, introduce a PEIM that produces the PEI_SMM_ACCESS_PPI
interface, enabling SmmLockBoxPeiLib to work; we can omit including
"UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationPei.inf".
The load / installation order of S3Resume2Pei and SmmAccessPei is
indifferent. SmmAccessPei produces the gEfiAcpiVariableGuid 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.kinney@intel.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Michael Kinney <michael.d.kinney@intel.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@19040 6f19259b-4bc3-4df7-8a09-765794883524
2015-11-30 19:41:38 +01:00
|
|
|
|
|
|
|
**/
|
|
|
|
|
|
|
|
#include <Guid/AcpiS3Context.h>
|
|
|
|
#include <IndustryStandard/Q35MchIch9.h>
|
|
|
|
#include <Library/DebugLib.h>
|
2017-07-04 13:16:39 +02:00
|
|
|
#include <Library/PcdLib.h>
|
OvmfPkg: add PEIM for providing TSEG-as-SMRAM during PEI
"MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxPeiLib.inf" is the
LockBoxLib instance with SMRAM access for the PEI phase.
Said library instance must, and can, access the LockBox data in SMRAM
directly if it is invoked before SMBASE relocation / SMI handler
installation. In that case, it only needs PEI_SMM_ACCESS_PPI from the
platform, and it doesn't depend on EFI_PEI_SMM_COMMUNICATION_PPI.
OVMF satisfies the description in SVN r18823 ("MdeModulePkg:
SmmLockBoxPeiLib: work without EFI_PEI_SMM_COMMUNICATION_PPI"): in OVMF,
only S3Resume2Pei links against SmmLockBoxPeiLib.
Therefore, introduce a PEIM that produces the PEI_SMM_ACCESS_PPI
interface, enabling SmmLockBoxPeiLib to work; we can omit including
"UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationPei.inf".
The load / installation order of S3Resume2Pei and SmmAccessPei is
indifferent. SmmAccessPei produces the gEfiAcpiVariableGuid 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.kinney@intel.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Michael Kinney <michael.d.kinney@intel.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@19040 6f19259b-4bc3-4df7-8a09-765794883524
2015-11-30 19:41:38 +01:00
|
|
|
#include <Library/PciLib.h>
|
|
|
|
|
|
|
|
#include "SmramInternal.h"
|
|
|
|
|
2017-07-04 13:16:39 +02:00
|
|
|
//
|
|
|
|
// The value of PcdQ35TsegMbytes is saved into this variable at module startup.
|
|
|
|
//
|
|
|
|
UINT16 mQ35TsegMbytes;
|
|
|
|
|
|
|
|
/**
|
|
|
|
Save PcdQ35TsegMbytes into mQ35TsegMbytes.
|
|
|
|
**/
|
|
|
|
VOID
|
|
|
|
InitQ35TsegMbytes (
|
|
|
|
VOID
|
|
|
|
)
|
|
|
|
{
|
|
|
|
mQ35TsegMbytes = PcdGet16 (PcdQ35TsegMbytes);
|
|
|
|
}
|
|
|
|
|
OvmfPkg: add PEIM for providing TSEG-as-SMRAM during PEI
"MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxPeiLib.inf" is the
LockBoxLib instance with SMRAM access for the PEI phase.
Said library instance must, and can, access the LockBox data in SMRAM
directly if it is invoked before SMBASE relocation / SMI handler
installation. In that case, it only needs PEI_SMM_ACCESS_PPI from the
platform, and it doesn't depend on EFI_PEI_SMM_COMMUNICATION_PPI.
OVMF satisfies the description in SVN r18823 ("MdeModulePkg:
SmmLockBoxPeiLib: work without EFI_PEI_SMM_COMMUNICATION_PPI"): in OVMF,
only S3Resume2Pei links against SmmLockBoxPeiLib.
Therefore, introduce a PEIM that produces the PEI_SMM_ACCESS_PPI
interface, enabling SmmLockBoxPeiLib to work; we can omit including
"UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationPei.inf".
The load / installation order of S3Resume2Pei and SmmAccessPei is
indifferent. SmmAccessPei produces the gEfiAcpiVariableGuid 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.kinney@intel.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Michael Kinney <michael.d.kinney@intel.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@19040 6f19259b-4bc3-4df7-8a09-765794883524
2015-11-30 19:41:38 +01:00
|
|
|
/**
|
|
|
|
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 :
|
OvmfPkg/SmmAccess: support extended TSEG size
In SmmAccessPeiEntryPoint(), map TSEG megabyte counts different from 1, 2
and 8 to the MCH_ESMRAMC_TSEG_EXT bit pattern (introduced in the previous
patch), for the ESMRAMC.TSEG_SZ bit-field register. (Suggested by Jordan.)
In SmramAccessGetCapabilities() -- backing both
PEI_SMM_ACCESS_PPI.GetCapabilities() and
EFI_SMM_ACCESS2_PROTOCOL.GetCapabilities() --, map the
MCH_ESMRAMC_TSEG_EXT bit pattern found in the ESMRAMC.TSEG_SZ bit-field
register to a byte count of (mQ35TsegMbytes * SIZE_1MB).
(MCH_ESMRAMC_TSEG_EXT is the only possible pattern if none of
MCH_ESMRAMC_TSEG_1MB, MCH_ESMRAMC_TSEG_2MB, and MCH_ESMRAMC_TSEG_8MB
match.)
The new code paths are not exercised just yet; for that, PlatformPei is
going to have to set PcdQ35TsegMbytes (and consequently, SmramInternal's
"mQ35TsegMbytes") to a value different from 1, 2, and 8.
Cc: Jordan Justen <jordan.l.justen@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
2017-07-04 14:27:19 +02:00
|
|
|
TsegSizeBits == MCH_ESMRAMC_TSEG_1MB ? SIZE_1MB :
|
|
|
|
mQ35TsegMbytes * SIZE_1MB) -
|
|
|
|
SmramMap[DescIdxSmmS3ResumeState].PhysicalSize;
|
OvmfPkg: add PEIM for providing TSEG-as-SMRAM during PEI
"MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxPeiLib.inf" is the
LockBoxLib instance with SMRAM access for the PEI phase.
Said library instance must, and can, access the LockBox data in SMRAM
directly if it is invoked before SMBASE relocation / SMI handler
installation. In that case, it only needs PEI_SMM_ACCESS_PPI from the
platform, and it doesn't depend on EFI_PEI_SMM_COMMUNICATION_PPI.
OVMF satisfies the description in SVN r18823 ("MdeModulePkg:
SmmLockBoxPeiLib: work without EFI_PEI_SMM_COMMUNICATION_PPI"): in OVMF,
only S3Resume2Pei links against SmmLockBoxPeiLib.
Therefore, introduce a PEIM that produces the PEI_SMM_ACCESS_PPI
interface, enabling SmmLockBoxPeiLib to work; we can omit including
"UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationPei.inf".
The load / installation order of S3Resume2Pei and SmmAccessPei is
indifferent. SmmAccessPei produces the gEfiAcpiVariableGuid 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.kinney@intel.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Michael Kinney <michael.d.kinney@intel.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@19040 6f19259b-4bc3-4df7-8a09-765794883524
2015-11-30 19:41:38 +01:00
|
|
|
SmramMap[DescIdxMain].RegionState = CommonRegionState;
|
|
|
|
|
|
|
|
return EFI_SUCCESS;
|
|
|
|
}
|