--- /dev/null
+/** @file\r
+\r
+ A PEIM with the following responsibilities:\r
+\r
+ - verify & configure the Q35 TSEG in the entry point,\r
+ - provide SMRAM access by producing PEI_SMM_ACCESS_PPI,\r
+ - set aside the SMM_S3_RESUME_STATE object at the bottom of TSEG, and expose\r
+ it via the gEfiAcpiVariableGuid GUID HOB.\r
+\r
+ This PEIM runs from RAM, so we can write to variables with static storage\r
+ duration.\r
+\r
+ Copyright (C) 2013, 2015, Red Hat, Inc.<BR>\r
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+\r
+ This program and the accompanying materials are licensed and made available\r
+ under the terms and conditions of the BSD License which accompanies this\r
+ distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT\r
+ WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <Guid/AcpiS3Context.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/HobLib.h>\r
+#include <Library/IoLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/PciLib.h>\r
+#include <Library/PeiServicesLib.h>\r
+#include <Ppi/SmmAccess.h>\r
+\r
+#include <OvmfPlatforms.h>\r
+\r
+#include "SmramInternal.h"\r
+\r
+//\r
+// PEI_SMM_ACCESS_PPI implementation.\r
+//\r
+\r
+/**\r
+ Opens the SMRAM area to be accessible by a PEIM driver.\r
+\r
+ This function "opens" SMRAM so that it is visible while not inside of SMM.\r
+ The function should return EFI_UNSUPPORTED if the hardware does not support\r
+ hiding of SMRAM. The function should return EFI_DEVICE_ERROR if the SMRAM\r
+ configuration is locked.\r
+\r
+ @param PeiServices General purpose services available to every\r
+ PEIM.\r
+ @param This The pointer to the SMM Access Interface.\r
+ @param DescriptorIndex The region of SMRAM to Open.\r
+\r
+ @retval EFI_SUCCESS The region was successfully opened.\r
+ @retval EFI_DEVICE_ERROR The region could not be opened because locked\r
+ by chipset.\r
+ @retval EFI_INVALID_PARAMETER The descriptor index was out of bounds.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+SmmAccessPeiOpen (\r
+ IN EFI_PEI_SERVICES **PeiServices,\r
+ IN PEI_SMM_ACCESS_PPI *This,\r
+ IN UINTN DescriptorIndex\r
+ )\r
+{\r
+ if (DescriptorIndex >= DescIdxCount) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // According to current practice, DescriptorIndex is not considered at all,\r
+ // beyond validating it.\r
+ //\r
+ return SmramAccessOpen (&This->LockState, &This->OpenState);\r
+}\r
+\r
+/**\r
+ Inhibits access to the SMRAM.\r
+\r
+ This function "closes" SMRAM so that it is not visible while outside of SMM.\r
+ The function should return EFI_UNSUPPORTED if the hardware does not support\r
+ hiding of SMRAM.\r
+\r
+ @param PeiServices General purpose services available to every\r
+ PEIM.\r
+ @param This The pointer to the SMM Access Interface.\r
+ @param DescriptorIndex The region of SMRAM to Close.\r
+\r
+ @retval EFI_SUCCESS The region was successfully closed.\r
+ @retval EFI_DEVICE_ERROR The region could not be closed because\r
+ locked by chipset.\r
+ @retval EFI_INVALID_PARAMETER The descriptor index was out of bounds.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+SmmAccessPeiClose (\r
+ IN EFI_PEI_SERVICES **PeiServices,\r
+ IN PEI_SMM_ACCESS_PPI *This,\r
+ IN UINTN DescriptorIndex\r
+ )\r
+{\r
+ if (DescriptorIndex >= DescIdxCount) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // According to current practice, DescriptorIndex is not considered at all,\r
+ // beyond validating it.\r
+ //\r
+ return SmramAccessClose (&This->LockState, &This->OpenState);\r
+}\r
+\r
+/**\r
+ Inhibits access to the SMRAM.\r
+\r
+ This function prohibits access to the SMRAM region. This function is usually\r
+ implemented such that it is a write-once operation.\r
+\r
+ @param PeiServices General purpose services available to every\r
+ PEIM.\r
+ @param This The pointer to the SMM Access Interface.\r
+ @param DescriptorIndex The region of SMRAM to Close.\r
+\r
+ @retval EFI_SUCCESS The region was successfully locked.\r
+ @retval EFI_DEVICE_ERROR The region could not be locked because at\r
+ least one range is still open.\r
+ @retval EFI_INVALID_PARAMETER The descriptor index was out of bounds.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+SmmAccessPeiLock (\r
+ IN EFI_PEI_SERVICES **PeiServices,\r
+ IN PEI_SMM_ACCESS_PPI *This,\r
+ IN UINTN DescriptorIndex\r
+ )\r
+{\r
+ if (DescriptorIndex >= DescIdxCount) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // According to current practice, DescriptorIndex is not considered at all,\r
+ // beyond validating it.\r
+ //\r
+ return SmramAccessLock (&This->LockState, &This->OpenState);\r
+}\r
+\r
+/**\r
+ Queries the memory controller for the possible regions that will support\r
+ SMRAM.\r
+\r
+ @param PeiServices General purpose services available to every\r
+ PEIM.\r
+ @param This The pointer to the SmmAccessPpi Interface.\r
+ @param SmramMapSize The pointer to the variable containing size of\r
+ the buffer to contain the description\r
+ information.\r
+ @param SmramMap The buffer containing the data describing the\r
+ Smram region descriptors.\r
+\r
+ @retval EFI_BUFFER_TOO_SMALL The user did not provide a sufficient buffer.\r
+ @retval EFI_SUCCESS The user provided a sufficiently-sized buffer.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+SmmAccessPeiGetCapabilities (\r
+ IN EFI_PEI_SERVICES **PeiServices,\r
+ IN PEI_SMM_ACCESS_PPI *This,\r
+ IN OUT UINTN *SmramMapSize,\r
+ IN OUT EFI_SMRAM_DESCRIPTOR *SmramMap\r
+ )\r
+{\r
+ return SmramAccessGetCapabilities (This->LockState, This->OpenState,\r
+ SmramMapSize, SmramMap);\r
+}\r
+\r
+//\r
+// LockState and OpenState will be filled in by the entry point.\r
+//\r
+STATIC PEI_SMM_ACCESS_PPI mAccess = {\r
+ &SmmAccessPeiOpen,\r
+ &SmmAccessPeiClose,\r
+ &SmmAccessPeiLock,\r
+ &SmmAccessPeiGetCapabilities\r
+};\r
+\r
+\r
+STATIC EFI_PEI_PPI_DESCRIPTOR mPpiList[] = {\r
+ {\r
+ EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,\r
+ &gPeiSmmAccessPpiGuid, &mAccess\r
+ }\r
+};\r
+\r
+\r
+//\r
+// Utility functions.\r
+//\r
+STATIC\r
+UINT8\r
+CmosRead8 (\r
+ IN UINT8 Index\r
+ )\r
+{\r
+ IoWrite8 (0x70, Index);\r
+ return IoRead8 (0x71);\r
+}\r
+\r
+STATIC\r
+UINT32\r
+GetSystemMemorySizeBelow4gb (\r
+ VOID\r
+ )\r
+{\r
+ UINT32 Cmos0x34;\r
+ UINT32 Cmos0x35;\r
+\r
+ Cmos0x34 = CmosRead8 (0x34);\r
+ Cmos0x35 = CmosRead8 (0x35);\r
+\r
+ return ((Cmos0x35 << 8 | Cmos0x34) << 16) + SIZE_16MB;\r
+}\r
+\r
+\r
+//\r
+// Entry point of this driver.\r
+//\r
+EFI_STATUS\r
+EFIAPI\r
+SmmAccessPeiEntryPoint (\r
+ IN EFI_PEI_FILE_HANDLE FileHandle,\r
+ IN CONST EFI_PEI_SERVICES **PeiServices\r
+ )\r
+{\r
+ UINT16 HostBridgeDevId;\r
+ UINT8 EsmramcVal;\r
+ UINT8 RegMask8;\r
+ UINT32 TopOfLowRam, TopOfLowRamMb;\r
+ EFI_STATUS Status;\r
+ UINTN SmramMapSize;\r
+ EFI_SMRAM_DESCRIPTOR SmramMap[DescIdxCount];\r
+ VOID *GuidHob;\r
+\r
+ //\r
+ // This module should only be included if SMRAM support is required.\r
+ //\r
+ ASSERT (FeaturePcdGet (PcdSmmSmramRequire));\r
+\r
+ //\r
+ // Verify if we're running on a Q35 machine type.\r
+ //\r
+ HostBridgeDevId = PciRead16 (OVMF_HOSTBRIDGE_DID);\r
+ if (HostBridgeDevId != INTEL_Q35_MCH_DEVICE_ID) {\r
+ DEBUG ((EFI_D_ERROR, "%a: no SMRAM with host bridge DID=0x%04x; only "\r
+ "DID=0x%04x (Q35) is supported\n", __FUNCTION__, HostBridgeDevId,\r
+ INTEL_Q35_MCH_DEVICE_ID));\r
+ goto WrongConfig;\r
+ }\r
+\r
+ //\r
+ // Confirm if QEMU supports SMRAM.\r
+ //\r
+ // With no support for it, the ESMRAMC (Extended System Management RAM\r
+ // Control) register reads as zero. If there is support, the cache-enable\r
+ // bits are hard-coded as 1 by QEMU.\r
+ //\r
+ EsmramcVal = PciRead8 (DRAMC_REGISTER_Q35 (MCH_ESMRAMC));\r
+ RegMask8 = MCH_ESMRAMC_SM_CACHE | MCH_ESMRAMC_SM_L1 | MCH_ESMRAMC_SM_L2;\r
+ if ((EsmramcVal & RegMask8) != RegMask8) {\r
+ DEBUG ((EFI_D_ERROR, "%a: this Q35 implementation lacks SMRAM\n",\r
+ __FUNCTION__));\r
+ goto WrongConfig;\r
+ }\r
+\r
+ TopOfLowRam = GetSystemMemorySizeBelow4gb ();\r
+ ASSERT ((TopOfLowRam & (SIZE_1MB - 1)) == 0);\r
+ TopOfLowRamMb = TopOfLowRam >> 20;\r
+\r
+ //\r
+ // Some of the following registers are no-ops for QEMU at the moment, but it\r
+ // is recommended to set them correctly, since the ESMRAMC that we ultimately\r
+ // care about is in the same set of registers.\r
+ //\r
+ // First, we disable the integrated VGA, and set both the GTT Graphics Memory\r
+ // Size and the Graphics Mode Select memory pre-allocation fields to zero.\r
+ // This takes just one write to the Graphics Control Register.\r
+ //\r
+ PciWrite16 (DRAMC_REGISTER_Q35 (MCH_GGC), MCH_GGC_IVD);\r
+\r
+ //\r
+ // Set Top of Low Usable DRAM.\r
+ //\r
+ PciWrite16 (DRAMC_REGISTER_Q35 (MCH_TOLUD),\r
+ (UINT16)(TopOfLowRamMb << MCH_TOLUD_MB_SHIFT));\r
+\r
+ //\r
+ // Given the zero graphics memory sizes configured above, set the\r
+ // graphics-related stolen memory bases to the same as TOLUD.\r
+ //\r
+ PciWrite32 (DRAMC_REGISTER_Q35 (MCH_GBSM),\r
+ TopOfLowRamMb << MCH_GBSM_MB_SHIFT);\r
+ PciWrite32 (DRAMC_REGISTER_Q35 (MCH_BGSM),\r
+ TopOfLowRamMb << MCH_BGSM_MB_SHIFT);\r
+\r
+ //\r
+ // Set TSEG Memory Base.\r
+ //\r
+ PciWrite32 (DRAMC_REGISTER_Q35 (MCH_TSEGMB),\r
+ (TopOfLowRamMb - FixedPcdGet8 (PcdQ35TsegMbytes)) << MCH_TSEGMB_MB_SHIFT);\r
+\r
+ //\r
+ // Set TSEG size, and disable TSEG visibility outside of SMM. Note that the\r
+ // T_EN bit has inverse meaning; when T_EN is set, then TSEG visibility is\r
+ // *restricted* to SMM.\r
+ //\r
+ EsmramcVal &= ~(UINT32)MCH_ESMRAMC_TSEG_MASK;\r
+ EsmramcVal |= FixedPcdGet8 (PcdQ35TsegMbytes) == 8 ? MCH_ESMRAMC_TSEG_8MB :\r
+ FixedPcdGet8 (PcdQ35TsegMbytes) == 2 ? MCH_ESMRAMC_TSEG_2MB :\r
+ MCH_ESMRAMC_TSEG_1MB;\r
+ EsmramcVal |= MCH_ESMRAMC_T_EN;\r
+ PciWrite8 (DRAMC_REGISTER_Q35 (MCH_ESMRAMC), EsmramcVal);\r
+\r
+ //\r
+ // TSEG should be closed (see above), but unlocked, initially. Set G_SMRAME\r
+ // (Global SMRAM Enable) too, as both D_LCK and T_EN depend on it.\r
+ //\r
+ PciAndThenOr8 (DRAMC_REGISTER_Q35 (MCH_SMRAM),\r
+ (UINT8)((~(UINT32)MCH_SMRAM_D_LCK) & 0xff), MCH_SMRAM_G_SMRAME);\r
+\r
+ //\r
+ // Create the GUID HOB and point it to the first SMRAM range.\r
+ //\r
+ GetStates (&mAccess.LockState, &mAccess.OpenState);\r
+ SmramMapSize = sizeof SmramMap;\r
+ Status = SmramAccessGetCapabilities (mAccess.LockState, mAccess.OpenState,\r
+ &SmramMapSize, SmramMap);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ DEBUG_CODE_BEGIN ();\r
+ {\r
+ UINTN Count;\r
+ UINTN Idx;\r
+\r
+ Count = SmramMapSize / sizeof SmramMap[0];\r
+ DEBUG ((EFI_D_VERBOSE, "%a: SMRAM map follows, %d entries\n", __FUNCTION__,\r
+ (INT32)Count));\r
+ DEBUG ((EFI_D_VERBOSE, "% 20a % 20a % 20a % 20a\n", "PhysicalStart(0x)",\r
+ "PhysicalSize(0x)", "CpuStart(0x)", "RegionState(0x)"));\r
+ for (Idx = 0; Idx < Count; ++Idx) {\r
+ DEBUG ((EFI_D_VERBOSE, "% 20Lx % 20Lx % 20Lx % 20Lx\n",\r
+ SmramMap[Idx].PhysicalStart, SmramMap[Idx].PhysicalSize,\r
+ SmramMap[Idx].CpuStart, SmramMap[Idx].RegionState));\r
+ }\r
+ }\r
+ DEBUG_CODE_END ();\r
+\r
+ GuidHob = BuildGuidHob (&gEfiAcpiVariableGuid,\r
+ sizeof SmramMap[DescIdxSmmS3ResumeState]);\r
+ if (GuidHob == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ CopyMem (GuidHob, &SmramMap[DescIdxSmmS3ResumeState],\r
+ sizeof SmramMap[DescIdxSmmS3ResumeState]);\r
+\r
+ //\r
+ // We're done. The next step should succeed, but even if it fails, we can't\r
+ // roll back the above BuildGuidHob() allocation, because PEI doesn't support\r
+ // releasing memory.\r
+ //\r
+ return PeiServicesInstallPpi (mPpiList);\r
+\r
+WrongConfig:\r
+ //\r
+ // We really don't want to continue in this case.\r
+ //\r
+ ASSERT (FALSE);\r
+ CpuDeadLoop ();\r
+ return EFI_UNSUPPORTED;\r
+}\r
--- /dev/null
+/** @file\r
+\r
+ Functions and types shared by the SMM accessor PEI and DXE modules.\r
+\r
+ Copyright (C) 2015, Red Hat, Inc.\r
+\r
+ This program and the accompanying materials are licensed and made available\r
+ under the terms and conditions of the BSD License which accompanies this\r
+ distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT\r
+ WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <Guid/AcpiS3Context.h>\r
+#include <IndustryStandard/Q35MchIch9.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/PciLib.h>\r
+\r
+#include "SmramInternal.h"\r
+\r
+/**\r
+ Read the MCH_SMRAM and ESMRAMC registers, and update the LockState and\r
+ OpenState fields in the PEI_SMM_ACCESS_PPI / EFI_SMM_ACCESS2_PROTOCOL object,\r
+ from the D_LCK and T_EN bits.\r
+\r
+ PEI_SMM_ACCESS_PPI and EFI_SMM_ACCESS2_PROTOCOL member functions can rely on\r
+ the LockState and OpenState fields being up-to-date on entry, and they need\r
+ to restore the same invariant on exit, if they touch the bits in question.\r
+\r
+ @param[out] LockState Reflects the D_LCK bit on output; TRUE iff SMRAM is\r
+ locked.\r
+ @param[out] OpenState Reflects the inverse of the T_EN bit on output; TRUE\r
+ iff SMRAM is open.\r
+**/\r
+VOID\r
+GetStates (\r
+ OUT BOOLEAN *LockState,\r
+ OUT BOOLEAN *OpenState\r
+)\r
+{\r
+ UINT8 SmramVal, EsmramcVal;\r
+\r
+ SmramVal = PciRead8 (DRAMC_REGISTER_Q35 (MCH_SMRAM));\r
+ EsmramcVal = PciRead8 (DRAMC_REGISTER_Q35 (MCH_ESMRAMC));\r
+\r
+ *LockState = !!(SmramVal & MCH_SMRAM_D_LCK);\r
+ *OpenState = !(EsmramcVal & MCH_ESMRAMC_T_EN);\r
+}\r
+\r
+//\r
+// The functions below follow the PEI_SMM_ACCESS_PPI and\r
+// EFI_SMM_ACCESS2_PROTOCOL member declarations. The PeiServices and This\r
+// pointers are removed (TSEG doesn't depend on them), and so is the\r
+// DescriptorIndex parameter (TSEG doesn't support range-wise locking).\r
+//\r
+// The LockState and OpenState members that are common to both\r
+// PEI_SMM_ACCESS_PPI and EFI_SMM_ACCESS2_PROTOCOL are taken and updated in\r
+// isolation from the rest of the (non-shared) members.\r
+//\r
+\r
+EFI_STATUS\r
+SmramAccessOpen (\r
+ OUT BOOLEAN *LockState,\r
+ OUT BOOLEAN *OpenState\r
+ )\r
+{\r
+ //\r
+ // Open TSEG by clearing T_EN.\r
+ //\r
+ PciAnd8 (DRAMC_REGISTER_Q35 (MCH_ESMRAMC),\r
+ (UINT8)((~(UINT32)MCH_ESMRAMC_T_EN) & 0xff));\r
+\r
+ GetStates (LockState, OpenState);\r
+ if (!*OpenState) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+SmramAccessClose (\r
+ OUT BOOLEAN *LockState,\r
+ OUT BOOLEAN *OpenState\r
+ )\r
+{\r
+ //\r
+ // Close TSEG by setting T_EN.\r
+ //\r
+ PciOr8 (DRAMC_REGISTER_Q35 (MCH_ESMRAMC), MCH_ESMRAMC_T_EN);\r
+\r
+ GetStates (LockState, OpenState);\r
+ if (*OpenState) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+SmramAccessLock (\r
+ OUT BOOLEAN *LockState,\r
+ IN OUT BOOLEAN *OpenState\r
+ )\r
+{\r
+ if (*OpenState) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ //\r
+ // Close & lock TSEG by setting T_EN and D_LCK.\r
+ //\r
+ PciOr8 (DRAMC_REGISTER_Q35 (MCH_ESMRAMC), MCH_ESMRAMC_T_EN);\r
+ PciOr8 (DRAMC_REGISTER_Q35 (MCH_SMRAM), MCH_SMRAM_D_LCK);\r
+\r
+ GetStates (LockState, OpenState);\r
+ if (*OpenState || !*LockState) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+SmramAccessGetCapabilities (\r
+ IN BOOLEAN LockState,\r
+ IN BOOLEAN OpenState,\r
+ IN OUT UINTN *SmramMapSize,\r
+ IN OUT EFI_SMRAM_DESCRIPTOR *SmramMap\r
+ )\r
+{\r
+ UINTN OriginalSize;\r
+ UINT32 TsegMemoryBaseMb, TsegMemoryBase;\r
+ UINT64 CommonRegionState;\r
+ UINT8 TsegSizeBits;\r
+\r
+ OriginalSize = *SmramMapSize;\r
+ *SmramMapSize = DescIdxCount * sizeof *SmramMap;\r
+ if (OriginalSize < *SmramMapSize) {\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+\r
+ //\r
+ // Read the TSEG Memory Base register.\r
+ //\r
+ TsegMemoryBaseMb = PciRead32 (DRAMC_REGISTER_Q35 (MCH_TSEGMB));\r
+ TsegMemoryBase = (TsegMemoryBaseMb >> MCH_TSEGMB_MB_SHIFT) << 20;\r
+\r
+ //\r
+ // Precompute the region state bits that will be set for all regions.\r
+ //\r
+ CommonRegionState = (OpenState ? EFI_SMRAM_OPEN : EFI_SMRAM_CLOSED) |\r
+ (LockState ? EFI_SMRAM_LOCKED : 0) |\r
+ EFI_CACHEABLE;\r
+\r
+ //\r
+ // The first region hosts an SMM_S3_RESUME_STATE object. It is located at the\r
+ // start of TSEG. We round up the size to whole pages, and we report it as\r
+ // EFI_ALLOCATED, so that the SMM_CORE stays away from it.\r
+ //\r
+ SmramMap[DescIdxSmmS3ResumeState].PhysicalStart = TsegMemoryBase;\r
+ SmramMap[DescIdxSmmS3ResumeState].CpuStart = TsegMemoryBase;\r
+ SmramMap[DescIdxSmmS3ResumeState].PhysicalSize =\r
+ EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (sizeof (SMM_S3_RESUME_STATE)));\r
+ SmramMap[DescIdxSmmS3ResumeState].RegionState =\r
+ CommonRegionState | EFI_ALLOCATED;\r
+\r
+ //\r
+ // Get the TSEG size bits from the ESMRAMC register.\r
+ //\r
+ TsegSizeBits = PciRead8 (DRAMC_REGISTER_Q35 (MCH_ESMRAMC)) &\r
+ MCH_ESMRAMC_TSEG_MASK;\r
+\r
+ //\r
+ // The second region is the main one, following the first.\r
+ //\r
+ SmramMap[DescIdxMain].PhysicalStart =\r
+ SmramMap[DescIdxSmmS3ResumeState].PhysicalStart +\r
+ SmramMap[DescIdxSmmS3ResumeState].PhysicalSize;\r
+ SmramMap[DescIdxMain].CpuStart = SmramMap[DescIdxMain].PhysicalStart;\r
+ SmramMap[DescIdxMain].PhysicalSize =\r
+ (TsegSizeBits == MCH_ESMRAMC_TSEG_8MB ? SIZE_8MB :\r
+ TsegSizeBits == MCH_ESMRAMC_TSEG_2MB ? SIZE_2MB :\r
+ SIZE_1MB) - SmramMap[DescIdxSmmS3ResumeState].PhysicalSize;\r
+ SmramMap[DescIdxMain].RegionState = CommonRegionState;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
--- /dev/null
+/** @file\r
+\r
+ Functions and types shared by the SMM accessor PEI and DXE modules.\r
+\r
+ Copyright (C) 2015, Red Hat, Inc.\r
+\r
+ This program and the accompanying materials are licensed and made available\r
+ under the terms and conditions of the BSD License which accompanies this\r
+ distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT\r
+ WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <Pi/PiMultiPhase.h>\r
+\r
+//\r
+// We'll have two SMRAM ranges.\r
+//\r
+// The first is a tiny one that hosts an SMM_S3_RESUME_STATE object, to be\r
+// filled in by the CPU SMM driver during normal boot, for the PEI instance of\r
+// the LockBox library (which will rely on the object during S3 resume).\r
+//\r
+// The other SMRAM range is the main one, for the SMM core and the SMM drivers.\r
+//\r
+typedef enum {\r
+ DescIdxSmmS3ResumeState = 0,\r
+ DescIdxMain = 1,\r
+ DescIdxCount = 2\r
+} DESCRIPTOR_INDEX;\r
+\r
+/**\r
+ Read the MCH_SMRAM and ESMRAMC registers, and update the LockState and\r
+ OpenState fields in the PEI_SMM_ACCESS_PPI / EFI_SMM_ACCESS2_PROTOCOL object,\r
+ from the D_LCK and T_EN bits.\r
+\r
+ PEI_SMM_ACCESS_PPI and EFI_SMM_ACCESS2_PROTOCOL member functions can rely on\r
+ the LockState and OpenState fields being up-to-date on entry, and they need\r
+ to restore the same invariant on exit, if they touch the bits in question.\r
+\r
+ @param[out] LockState Reflects the D_LCK bit on output; TRUE iff SMRAM is\r
+ locked.\r
+ @param[out] OpenState Reflects the inverse of the T_EN bit on output; TRUE\r
+ iff SMRAM is open.\r
+**/\r
+VOID\r
+GetStates (\r
+ OUT BOOLEAN *LockState,\r
+ OUT BOOLEAN *OpenState\r
+ );\r
+\r
+//\r
+// The functions below follow the PEI_SMM_ACCESS_PPI and\r
+// EFI_SMM_ACCESS2_PROTOCOL member declarations. The PeiServices and This\r
+// pointers are removed (TSEG doesn't depend on them), and so is the\r
+// DescriptorIndex parameter (TSEG doesn't support range-wise locking).\r
+//\r
+// The LockState and OpenState members that are common to both\r
+// PEI_SMM_ACCESS_PPI and EFI_SMM_ACCESS2_PROTOCOL are taken and updated in\r
+// isolation from the rest of the (non-shared) members.\r
+//\r
+\r
+EFI_STATUS\r
+SmramAccessOpen (\r
+ OUT BOOLEAN *LockState,\r
+ OUT BOOLEAN *OpenState\r
+ );\r
+\r
+EFI_STATUS\r
+SmramAccessClose (\r
+ OUT BOOLEAN *LockState,\r
+ OUT BOOLEAN *OpenState\r
+ );\r
+\r
+EFI_STATUS\r
+SmramAccessLock (\r
+ OUT BOOLEAN *LockState,\r
+ IN OUT BOOLEAN *OpenState\r
+ );\r
+\r
+EFI_STATUS\r
+SmramAccessGetCapabilities (\r
+ IN BOOLEAN LockState,\r
+ IN BOOLEAN OpenState,\r
+ IN OUT UINTN *SmramMapSize,\r
+ IN OUT EFI_SMRAM_DESCRIPTOR *SmramMap\r
+ );\r