/** @file\r
- OVMF ACPI QEMU support\r
+ OVMF ACPI Xen 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) 2012, Bei Guan <gbtju85@gmail.com>\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
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/ \r
\r
#include "AcpiPlatform.h"\r
#include <Library/HobLib.h>\r
#include <Guid/XenInfo.h>\r
+#include <Library/BaseLib.h>\r
\r
+#define XEN_ACPI_PHYSICAL_ADDRESS 0x000EA020\r
+#define XEN_BIOS_PHYSICAL_END 0x000FFFFF\r
\r
+EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *XenAcpiRsdpStructurePtr = NULL;\r
+\r
+/**\r
+ This function detects if OVMF is running on Xen.\r
+\r
+**/\r
BOOLEAN\r
XenDetected (\r
VOID\r
return TRUE;\r
}\r
\r
+/**\r
+ Get the address of Xen ACPI Root System Description Pointer (RSDP)\r
+ structure.\r
+\r
+ @param RsdpStructurePtr Return pointer to RSDP structure\r
+\r
+ @return EFI_SUCCESS Find Xen RSDP structure successfully.\r
+ @return EFI_NOT_FOUND Don't find Xen RSDP structure.\r
+ @return EFI_ABORTED Find Xen RSDP structure, but it's not integrated.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GetXenAcpiRsdp (\r
+ OUT EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER **RsdpPtr\r
+ )\r
+{\r
+ EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *RsdpStructurePtr;\r
+ UINT8 *XenAcpiPtr;\r
+ UINT8 Sum;\r
+\r
+ //\r
+ // Detect the RSDP structure\r
+ //\r
+ for (XenAcpiPtr = (UINT8*)(UINTN) XEN_ACPI_PHYSICAL_ADDRESS;\r
+ XenAcpiPtr < (UINT8*)(UINTN) XEN_BIOS_PHYSICAL_END;\r
+ XenAcpiPtr += 0x10) {\r
+\r
+ RsdpStructurePtr = (EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)\r
+ (UINTN) XenAcpiPtr;\r
+\r
+ if (!AsciiStrnCmp ((CHAR8 *) &RsdpStructurePtr->Signature, "RSD PTR ", 8)) {\r
+ //\r
+ // RSDP ACPI 1.0 checksum for 1.0/2.0/3.0 table.\r
+ // This is only the first 20 bytes of the structure\r
+ //\r
+ Sum = CalculateSum8 (\r
+ (CONST UINT8 *)RsdpStructurePtr,\r
+ sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER)\r
+ );\r
+ if (Sum != 0) {\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ if (RsdpStructurePtr->Revision >= 2) {\r
+ //\r
+ // RSDP ACPI 2.0/3.0 checksum, this is the entire table\r
+ //\r
+ Sum = CalculateSum8 (\r
+ (CONST UINT8 *)RsdpStructurePtr,\r
+ sizeof (EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER)\r
+ );\r
+ if (Sum != 0) {\r
+ return EFI_ABORTED;\r
+ }\r
+ }\r
+ *RsdpPtr = RsdpStructurePtr;\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
+/**\r
+ Get Xen Acpi tables from the RSDP structure. And installs Xen ACPI tables\r
+ into the RSDT/XSDT using InstallAcpiTable. Some signature of the installed\r
+ ACPI tables are: FACP, APIC, HPET, WAET, SSDT, FACS, DSDT.\r
+\r
+ @param AcpiProtocol Protocol instance pointer.\r
\r
+ @return EFI_SUCCESS The table was successfully inserted.\r
+ @return EFI_INVALID_PARAMETER Either AcpiTableBuffer is NULL, TableHandle is\r
+ NULL, or AcpiTableBufferSize and the size\r
+ field embedded in the ACPI table pointed to\r
+ by AcpiTableBuffer are not in sync.\r
+ @return EFI_OUT_OF_RESOURCES Insufficient resources exist to complete the request.\r
+\r
+**/\r
EFI_STATUS\r
EFIAPI\r
-XenInstallAcpiTable (\r
- IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol,\r
- IN VOID *AcpiTableBuffer,\r
- IN UINTN AcpiTableBufferSize,\r
- OUT UINTN *TableKey\r
+InstallXenTables (\r
+ IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol\r
)\r
{\r
- return InstallAcpiTable(\r
- AcpiProtocol,\r
- AcpiTableBuffer,\r
- AcpiTableBufferSize,\r
- TableKey\r
- );\r
+ EFI_STATUS Status;\r
+ UINTN TableHandle;\r
+\r
+ EFI_ACPI_DESCRIPTION_HEADER *Rsdt;\r
+ EFI_ACPI_DESCRIPTION_HEADER *Xsdt;\r
+ VOID *CurrentTableEntry;\r
+ UINTN CurrentTablePointer;\r
+ EFI_ACPI_DESCRIPTION_HEADER *CurrentTable;\r
+ UINTN Index;\r
+ UINTN NumberOfTableEntries;\r
+ EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt2Table;\r
+ EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt1Table;\r
+ EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs2Table;\r
+ EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs1Table;\r
+ EFI_ACPI_DESCRIPTION_HEADER *DsdtTable;\r
+\r
+ Fadt2Table = NULL;\r
+ Fadt1Table = NULL;\r
+ Facs2Table = NULL;\r
+ Facs1Table = NULL;\r
+ DsdtTable = NULL;\r
+ TableHandle = 0;\r
+ NumberOfTableEntries = 0;\r
+\r
+ //\r
+ // Try to find Xen ACPI tables\r
+ //\r
+ Status = GetXenAcpiRsdp (&XenAcpiRsdpStructurePtr);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // If XSDT table is find, just install its tables. \r
+ // Otherwise, try to find and install the RSDT tables.\r
+ //\r
+ if (XenAcpiRsdpStructurePtr->XsdtAddress) {\r
+ //\r
+ // Retrieve the addresses of XSDT and \r
+ // calculate the number of its table entries.\r
+ //\r
+ Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN)\r
+ XenAcpiRsdpStructurePtr->XsdtAddress;\r
+ NumberOfTableEntries = (Xsdt->Length -\r
+ sizeof (EFI_ACPI_DESCRIPTION_HEADER)) /\r
+ sizeof (UINT64);\r
+\r
+ //\r
+ // Install ACPI tables found in XSDT.\r
+ //\r
+ for (Index = 0; Index < NumberOfTableEntries; Index++) {\r
+ //\r
+ // Get the table entry from XSDT\r
+ //\r
+ CurrentTableEntry = (VOID *) ((UINT8 *) Xsdt +\r
+ sizeof (EFI_ACPI_DESCRIPTION_HEADER) +\r
+ Index * sizeof (UINT64));\r
+ CurrentTablePointer = (UINTN) *(UINT64 *)CurrentTableEntry;\r
+ CurrentTable = (EFI_ACPI_DESCRIPTION_HEADER *) CurrentTablePointer;\r
+\r
+ //\r
+ // Install the XSDT tables\r
+ //\r
+ Status = InstallAcpiTable (\r
+ AcpiProtocol,\r
+ CurrentTable,\r
+ CurrentTable->Length,\r
+ &TableHandle\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Get the FACS and DSDT table address from the table FADT\r
+ //\r
+ if (!AsciiStrnCmp ((CHAR8 *) &CurrentTable->Signature, "FACP", 4)) {\r
+ Fadt2Table = (EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *)\r
+ (UINTN) CurrentTablePointer;\r
+ Facs2Table = (EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *)\r
+ (UINTN) Fadt2Table->FirmwareCtrl;\r
+ DsdtTable = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN) Fadt2Table->Dsdt;\r
+ }\r
+ }\r
+ }\r
+ else if (XenAcpiRsdpStructurePtr->RsdtAddress) {\r
+ //\r
+ // Retrieve the addresses of RSDT and\r
+ // calculate the number of its table entries.\r
+ //\r
+ Rsdt = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN)\r
+ XenAcpiRsdpStructurePtr->RsdtAddress;\r
+ NumberOfTableEntries = (Rsdt->Length -\r
+ sizeof (EFI_ACPI_DESCRIPTION_HEADER)) / \r
+ sizeof (UINT32);\r
+\r
+ //\r
+ // Install ACPI tables found in XSDT.\r
+ //\r
+ for (Index = 0; Index < NumberOfTableEntries; Index++) {\r
+ //\r
+ // Get the table entry from RSDT\r
+ //\r
+ CurrentTableEntry = (UINT32 *) ((UINT8 *) Rsdt +\r
+ sizeof (EFI_ACPI_DESCRIPTION_HEADER) +\r
+ Index * sizeof (UINT32));\r
+ CurrentTablePointer = *(UINT32 *)CurrentTableEntry;\r
+ CurrentTable = (EFI_ACPI_DESCRIPTION_HEADER *) CurrentTablePointer;\r
+\r
+ //\r
+ // Install the RSDT tables\r
+ //\r
+ Status = InstallAcpiTable (\r
+ AcpiProtocol,\r
+ CurrentTable,\r
+ CurrentTable->Length,\r
+ &TableHandle\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Get the FACS and DSDT table address from the table FADT\r
+ //\r
+ if (!AsciiStrnCmp ((CHAR8 *) &CurrentTable->Signature, "FACP", 4)) {\r
+ Fadt1Table = (EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE *)\r
+ (UINTN) CurrentTablePointer;\r
+ Facs1Table = (EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *)\r
+ (UINTN) Fadt1Table->FirmwareCtrl;\r
+ DsdtTable = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN) Fadt1Table->Dsdt;\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // Install the FACS table.\r
+ //\r
+ if (Fadt2Table) {\r
+ //\r
+ // FACS 2.0\r
+ //\r
+ Status = InstallAcpiTable (\r
+ AcpiProtocol,\r
+ Facs2Table,\r
+ Facs2Table->Length,\r
+ &TableHandle\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+ else if (Fadt1Table) {\r
+ //\r
+ // FACS 1.0\r
+ //\r
+ Status = InstallAcpiTable (\r
+ AcpiProtocol,\r
+ Facs1Table,\r
+ Facs1Table->Length,\r
+ &TableHandle\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Install DSDT table. If we reached this point without finding the DSDT,\r
+ // then we're out of sync with the hypervisor, and cannot continue.\r
+ //\r
+ if (DsdtTable == NULL) {\r
+ DEBUG ((DEBUG_ERROR, "%a: no DSDT found\n", __FUNCTION__));\r
+ ASSERT (FALSE);\r
+ CpuDeadLoop ();\r
+ }\r
+\r
+ Status = InstallAcpiTable (\r
+ AcpiProtocol,\r
+ DsdtTable,\r
+ DsdtTable->Length,\r
+ &TableHandle\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
}\r
\r