/** @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
#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
return EFI_OUT_OF_RESOURCES;\r
}\r
\r
- Madt->Header = *(EFI_ACPI_DESCRIPTION_HEADER *) AcpiTableBuffer;\r
- Madt->Header.Length = NewBufferSize;\r
+ CopyMem (&(Madt->Header), AcpiTableBuffer, sizeof (EFI_ACPI_DESCRIPTION_HEADER));\r
+ Madt->Header.Length = (UINT32) NewBufferSize;\r
Madt->LocalApicAddress = PcdGet32 (PcdCpuLocalApicBaseAddress);\r
Madt->Flags = EFI_ACPI_1_0_PCAT_COMPAT;\r
Ptr = Madt + 1;\r
for (Loop = 0; Loop < CpuCount; ++Loop) {\r
LocalApic->Type = EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC;\r
LocalApic->Length = sizeof (*LocalApic);\r
- LocalApic->AcpiProcessorId = Loop;\r
- LocalApic->ApicId = Loop;\r
+ LocalApic->AcpiProcessorId = (UINT8) Loop;\r
+ LocalApic->ApicId = (UINT8) Loop;\r
LocalApic->Flags = 1; // enabled\r
++LocalApic;\r
}\r
IoApic = Ptr;\r
IoApic->Type = EFI_ACPI_1_0_IO_APIC;\r
IoApic->Length = sizeof (*IoApic);\r
- IoApic->IoApicId = CpuCount;\r
+ IoApic->IoApicId = (UINT8) CpuCount;\r
IoApic->Reserved = EFI_ACPI_RESERVED_BYTE;\r
IoApic->IoApicAddress = 0xFEC00000;\r
IoApic->SystemVectorBase = 0x00000000;\r
Iso->Type = EFI_ACPI_1_0_INTERRUPT_SOURCE_OVERRIDE;\r
Iso->Length = sizeof (*Iso);\r
Iso->Bus = 0x00; // ISA\r
- Iso->Source = Loop;\r
- Iso->GlobalSystemInterruptVector = Loop;\r
+ Iso->Source = (UINT8) Loop;\r
+ Iso->GlobalSystemInterruptVector = (UINT32) Loop;\r
Iso->Flags = 0x000D; // Level-tiggered, Active High\r
++Iso;\r
}\r
ASSERT (\r
- Iso - (EFI_ACPI_1_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE *)Ptr ==\r
+ (UINTN) (Iso - (EFI_ACPI_1_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE *)Ptr) ==\r
1 + PciLinkIsoCount\r
);\r
Ptr = Iso;\r
LocalApicNmi->LocalApicInti = 0x01;\r
Ptr = LocalApicNmi + 1;\r
\r
- ASSERT ((UINT8 *)Ptr - (UINT8 *)Madt == NewBufferSize);\r
+ ASSERT ((UINTN) ((UINT8 *)Ptr - (UINT8 *)Madt) == NewBufferSize);\r
Status = InstallAcpiTable (AcpiProtocol, Madt, NewBufferSize, TableKey);\r
\r
FreePool (Madt);\r
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
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
}\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
\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
*(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
TableKey\r
);\r
}\r
-\r