]> git.proxmox.com Git - mirror_edk2.git/blobdiff - OvmfPkg/AcpiPlatformDxe/Qemu.c
UefiPayloadPkg: Enhance UEFI payload for coreboot and Slim Bootloader
[mirror_edk2.git] / OvmfPkg / AcpiPlatformDxe / Qemu.c
index 5ab89aa6c6f091091489bfb68784fba4da76ecef..f60e00f58af3b72fc153ae497a605ab8e7670cee 100644 (file)
@@ -1,14 +1,11 @@
 /** @file\r
   OVMF ACPI QEMU support\r
 \r
-  Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>\r
-  This program and the accompanying materials\r
-  are licensed and made available under the terms and conditions of the BSD License\r
-  which accompanies this distribution.  The full text of the license may be found at\r
-  http://opensource.org/licenses/bsd-license.php\r
+  Copyright (c) 2008 - 2014, Intel Corporation. All rights reserved.<BR>\r
 \r
-  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+  Copyright (C) 2012-2014, Red Hat, Inc.\r
+\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
@@ -18,6 +15,7 @@
 #include <Library/QemuFwCfgLib.h>\r
 #include <Library/DxeServicesTableLib.h>\r
 #include <Library/PcdLib.h>\r
+#include <Library/OrderedCollectionLib.h>\r
 #include <IndustryStandard/Acpi.h>\r
 \r
 BOOLEAN\r
@@ -196,6 +194,23 @@ typedef struct {
   PCI_WINDOW PciWindow64;\r
 } FIRMWARE_DATA;\r
 \r
+typedef struct {\r
+  UINT8 BytePrefix;\r
+  UINT8 ByteValue;\r
+} AML_BYTE;\r
+\r
+typedef struct {\r
+  UINT8    NameOp;\r
+  UINT8    RootChar;\r
+  UINT8    NameChar[4];\r
+  UINT8    PackageOp;\r
+  UINT8    PkgLength;\r
+  UINT8    NumElements;\r
+  AML_BYTE Pm1aCntSlpTyp;\r
+  AML_BYTE Pm1bCntSlpTyp;\r
+  AML_BYTE Reserved[2];\r
+} SYSTEM_STATE_PACKAGE;\r
+\r
 #pragma pack()\r
 \r
 \r
@@ -230,7 +245,7 @@ PopulateFwData(
       Desc = &AllDesc[CurDesc];\r
       ExclTop = Desc->BaseAddress + Desc->Length;\r
 \r
-      if (ExclTop <= BASE_4GB) {\r
+      if (ExclTop <= (UINT64) PcdGet32 (PcdOvmfFdBaseAddress)) {\r
         switch (Desc->GcdMemoryType) {\r
           case EfiGcdMemoryTypeNonExistent:\r
             break;\r
@@ -295,6 +310,86 @@ PopulateFwData(
 }\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
+}\r
+\r
+\r
 STATIC\r
 EFI_STATUS\r
 EFIAPI\r
@@ -312,10 +407,16 @@ QemuInstallAcpiSsdtTable (
 \r
   FwData = AllocateReservedPool (sizeof (*FwData));\r
   if (FwData != NULL) {\r
-    UINTN SsdtSize;\r
-    UINT8 *Ssdt;\r
-\r
-    SsdtSize = AcpiTableBufferSize + 17;\r
+    UINTN                SuspendToRamSize;\r
+    SYSTEM_STATE_PACKAGE SuspendToRam;\r
+    UINTN                SuspendToDiskSize;\r
+    SYSTEM_STATE_PACKAGE SuspendToDisk;\r
+    UINTN                SsdtSize;\r
+    UINT8                *Ssdt;\r
+\r
+    GetSuspendStates (&SuspendToRamSize,  &SuspendToRam,\r
+                      &SuspendToDiskSize, &SuspendToDisk);\r
+    SsdtSize = AcpiTableBufferSize + 17 + SuspendToRamSize + SuspendToDiskSize;\r
     Ssdt = AllocatePool (SsdtSize);\r
 \r
     if (Ssdt != NULL) {\r
@@ -352,6 +453,14 @@ QemuInstallAcpiSsdtTable (
         *(UINT32*) SsdtPtr = sizeof (*FwData);\r
         SsdtPtr += 4;\r
 \r
+        //\r
+        // add suspend system states\r
+        //\r
+        CopyMem (SsdtPtr, &SuspendToRam, SuspendToRamSize);\r
+        SsdtPtr += SuspendToRamSize;\r
+        CopyMem (SsdtPtr, &SuspendToDisk, SuspendToDiskSize);\r
+        SsdtPtr += SuspendToDiskSize;\r
+\r
         ASSERT((UINTN) (SsdtPtr - Ssdt) == SsdtSize);\r
         ((EFI_ACPI_DESCRIPTION_HEADER *) Ssdt)->Length = (UINT32) SsdtSize;\r
         Status = InstallAcpiTable (AcpiProtocol, Ssdt, SsdtSize, TableKey);\r
@@ -400,4 +509,3 @@ QemuInstallAcpiTable (
            TableKey\r
            );\r
 }\r
-\r