//\r
// The package level header files this module uses\r
//\r
+#include <IndustryStandard/Q35MchIch9.h>\r
#include <PiPei.h>\r
\r
//\r
// The Library classes this module consumes\r
//\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/PeimEntryPoint.h>\r
#include <Library/ResourcePublicationLib.h>\r
#include <Library/MtrrLib.h>\r
VOID\r
)\r
{\r
- mQ35TsegMbytes = PcdGet16 (PcdQ35TsegMbytes);\r
+ UINT16 ExtendedTsegMbytes;\r
+ RETURN_STATUS PcdStatus;\r
+\r
+ if (mHostBridgeDevId != INTEL_Q35_MCH_DEVICE_ID) {\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "%a: no TSEG (SMRAM) on host bridge DID=0x%04x; "\r
+ "only DID=0x%04x (Q35) is supported\n",\r
+ __FUNCTION__,\r
+ mHostBridgeDevId,\r
+ INTEL_Q35_MCH_DEVICE_ID\r
+ ));\r
+ ASSERT (FALSE);\r
+ CpuDeadLoop ();\r
+ }\r
+\r
+ //\r
+ // Check if QEMU offers an extended TSEG.\r
+ //\r
+ // This can be seen from writing MCH_EXT_TSEG_MB_QUERY to the MCH_EXT_TSEG_MB\r
+ // register, and reading back the register.\r
+ //\r
+ // On a QEMU machine type that does not offer an extended TSEG, the initial\r
+ // write overwrites whatever value a malicious guest OS may have placed in\r
+ // the (unimplemented) register, before entering S3 or rebooting.\r
+ // Subsequently, the read returns MCH_EXT_TSEG_MB_QUERY unchanged.\r
+ //\r
+ // On a QEMU machine type that offers an extended TSEG, the initial write\r
+ // triggers an update to the register. Subsequently, the value read back\r
+ // (which is guaranteed to differ from MCH_EXT_TSEG_MB_QUERY) tells us the\r
+ // number of megabytes.\r
+ //\r
+ PciWrite16 (DRAMC_REGISTER_Q35 (MCH_EXT_TSEG_MB), MCH_EXT_TSEG_MB_QUERY);\r
+ ExtendedTsegMbytes = PciRead16 (DRAMC_REGISTER_Q35 (MCH_EXT_TSEG_MB));\r
+ if (ExtendedTsegMbytes == MCH_EXT_TSEG_MB_QUERY) {\r
+ mQ35TsegMbytes = PcdGet16 (PcdQ35TsegMbytes);\r
+ return;\r
+ }\r
+\r
+ DEBUG ((\r
+ DEBUG_INFO,\r
+ "%a: QEMU offers an extended TSEG (%d MB)\n",\r
+ __FUNCTION__,\r
+ ExtendedTsegMbytes\r
+ ));\r
+ PcdStatus = PcdSet16S (PcdQ35TsegMbytes, ExtendedTsegMbytes);\r
+ ASSERT_RETURN_ERROR (PcdStatus);\r
+ mQ35TsegMbytes = ExtendedTsegMbytes;\r
}\r
\r
\r
AddressWidthInitialization ();\r
MaxCpuCountInitialization ();\r
\r
+ //\r
+ // Query Host Bridge DID\r
+ //\r
+ mHostBridgeDevId = PciRead16 (OVMF_HOSTBRIDGE_DID);\r
+\r
if (FeaturePcdGet (PcdSmmSmramRequire)) {\r
Q35TsegMbytesInitialization ();\r
}\r
InitializeXen ();\r
}\r
\r
- //\r
- // Query Host Bridge DID\r
- //\r
- mHostBridgeDevId = PciRead16 (OVMF_HOSTBRIDGE_DID);\r
-\r
if (mBootMode != BOOT_ON_S3_RESUME) {\r
if (!FeaturePcdGet (PcdSmmSmramRequire)) {\r
ReserveEmuVariableNvStore ();\r