+ EFI_STATUS Status;\r
+ UINTN NumDesc;\r
+ EFI_GCD_MEMORY_SPACE_DESCRIPTOR *AllDesc;\r
+\r
+ Status = gDS->GetMemorySpaceMap (&NumDesc, &AllDesc);\r
+ if (Status == EFI_SUCCESS) {\r
+ UINT64 NonMmio32MaxExclTop;\r
+ UINT64 Mmio32MinBase;\r
+ UINT64 Mmio32MaxExclTop;\r
+ UINTN CurDesc;\r
+\r
+ Status = EFI_UNSUPPORTED;\r
+\r
+ NonMmio32MaxExclTop = 0;\r
+ Mmio32MinBase = BASE_4GB;\r
+ Mmio32MaxExclTop = 0;\r
+\r
+ for (CurDesc = 0; CurDesc < NumDesc; ++CurDesc) {\r
+ CONST EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Desc;\r
+ UINT64 ExclTop;\r
+\r
+ Desc = &AllDesc[CurDesc];\r
+ ExclTop = Desc->BaseAddress + Desc->Length;\r
+\r
+ if (ExclTop <= (UINT64) PcdGet32 (PcdOvmfFdBaseAddress)) {\r
+ switch (Desc->GcdMemoryType) {\r
+ case EfiGcdMemoryTypeNonExistent:\r
+ break;\r
+\r
+ case EfiGcdMemoryTypeReserved:\r
+ case EfiGcdMemoryTypeSystemMemory:\r
+ if (NonMmio32MaxExclTop < ExclTop) {\r
+ NonMmio32MaxExclTop = ExclTop;\r
+ }\r
+ break;\r
+\r
+ case EfiGcdMemoryTypeMemoryMappedIo:\r
+ if (Mmio32MinBase > Desc->BaseAddress) {\r
+ Mmio32MinBase = Desc->BaseAddress;\r
+ }\r
+ if (Mmio32MaxExclTop < ExclTop) {\r
+ Mmio32MaxExclTop = ExclTop;\r
+ }\r
+ break;\r
+\r
+ default:\r
+ ASSERT(0);\r
+ }\r
+ }\r
+ }\r
+\r
+ if (Mmio32MinBase < NonMmio32MaxExclTop) {\r
+ Mmio32MinBase = NonMmio32MaxExclTop;\r
+ }\r
+\r
+ if (Mmio32MinBase < Mmio32MaxExclTop) {\r
+ FwData->PciWindow32.Base = Mmio32MinBase;\r
+ FwData->PciWindow32.End = Mmio32MaxExclTop - 1;\r
+ FwData->PciWindow32.Length = Mmio32MaxExclTop - Mmio32MinBase;\r
+\r
+ FwData->PciWindow64.Base = 0;\r
+ FwData->PciWindow64.End = 0;\r
+ FwData->PciWindow64.Length = 0;\r
+\r
+ Status = EFI_SUCCESS;\r
+ }\r
+\r
+ FreePool (AllDesc);\r
+ }\r
+\r
+ DEBUG ((\r
+ DEBUG_INFO,\r
+ "ACPI PciWindow32: Base=0x%08lx End=0x%08lx Length=0x%08lx\n",\r
+ FwData->PciWindow32.Base,\r
+ FwData->PciWindow32.End,\r
+ FwData->PciWindow32.Length\r
+ ));\r
+ DEBUG ((\r
+ DEBUG_INFO,\r
+ "ACPI PciWindow64: Base=0x%08lx End=0x%08lx Length=0x%08lx\n",\r
+ FwData->PciWindow64.Base,\r
+ FwData->PciWindow64.End,\r
+ FwData->PciWindow64.Length\r
+ ));\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+STATIC\r
+VOID\r
+EFIAPI\r
+GetSuspendStates (\r
+ UINTN *SuspendToRamSize,\r
+ SYSTEM_STATE_PACKAGE *SuspendToRam,\r
+ UINTN *SuspendToDiskSize,\r
+ SYSTEM_STATE_PACKAGE *SuspendToDisk\r
+ )\r
+{\r
+ STATIC CONST SYSTEM_STATE_PACKAGE Template = {\r
+ 0x08, // NameOp\r
+ '\\', // RootChar\r
+ { '_', 'S', 'x', '_' }, // NameChar[4]\r
+ 0x12, // PackageOp\r
+ 0x0A, // PkgLength\r
+ 0x04, // NumElements\r
+ { 0x0A, 0x00 }, // Pm1aCntSlpTyp\r
+ { 0x0A, 0x00 }, // Pm1bCntSlpTyp -- we don't support it\r
+ { // Reserved[2]\r
+ { 0x0A, 0x00 },\r
+ { 0x0A, 0x00 }\r
+ }\r
+ };\r
+ RETURN_STATUS Status;\r
+ FIRMWARE_CONFIG_ITEM FwCfgItem;\r
+ UINTN FwCfgSize;\r
+ UINT8 SystemStates[6];\r
+\r
+ //\r
+ // configure defaults\r
+ //\r
+ *SuspendToRamSize = sizeof Template;\r
+ CopyMem (SuspendToRam, &Template, sizeof Template);\r
+ SuspendToRam->NameChar[2] = '3'; // S3\r
+ SuspendToRam->Pm1aCntSlpTyp.ByteValue = 1; // PIIX4: STR\r
+\r
+ *SuspendToDiskSize = sizeof Template;\r
+ CopyMem (SuspendToDisk, &Template, sizeof Template);\r
+ SuspendToDisk->NameChar[2] = '4'; // S4\r
+ SuspendToDisk->Pm1aCntSlpTyp.ByteValue = 2; // PIIX4: POSCL\r
+\r
+ //\r
+ // check for overrides\r
+ //\r
+ Status = QemuFwCfgFindFile ("etc/system-states", &FwCfgItem, &FwCfgSize);\r
+ if (Status != RETURN_SUCCESS || FwCfgSize != sizeof SystemStates) {\r
+ DEBUG ((DEBUG_INFO, "ACPI using S3/S4 defaults\n"));\r
+ return;\r
+ }\r
+ QemuFwCfgSelectItem (FwCfgItem);\r
+ QemuFwCfgReadBytes (sizeof SystemStates, SystemStates);\r
+\r
+ //\r
+ // Each byte corresponds to a system state. In each byte, the MSB tells us\r
+ // whether the given state is enabled. If so, the three LSBs specify the\r
+ // value to be written to the PM control register's SUS_TYP bits.\r
+ //\r
+ if (SystemStates[3] & BIT7) {\r
+ SuspendToRam->Pm1aCntSlpTyp.ByteValue =\r
+ SystemStates[3] & (BIT2 | BIT1 | BIT0);\r
+ DEBUG ((DEBUG_INFO, "ACPI S3 value: %d\n",\r
+ SuspendToRam->Pm1aCntSlpTyp.ByteValue));\r
+ } else {\r
+ *SuspendToRamSize = 0;\r
+ DEBUG ((DEBUG_INFO, "ACPI S3 disabled\n"));\r
+ }\r
+\r
+ if (SystemStates[4] & BIT7) {\r
+ SuspendToDisk->Pm1aCntSlpTyp.ByteValue =\r
+ SystemStates[4] & (BIT2 | BIT1 | BIT0);\r
+ DEBUG ((DEBUG_INFO, "ACPI S4 value: %d\n",\r
+ SuspendToDisk->Pm1aCntSlpTyp.ByteValue));\r
+ } else {\r
+ *SuspendToDiskSize = 0;\r
+ DEBUG ((DEBUG_INFO, "ACPI S4 disabled\n"));\r
+ }\r