--- /dev/null
+/** @file\r
+ OVMF ACPI Cloud Hypervisor support\r
+\r
+ Copyright (c) 2021, Intel Corporation. All rights reserved.\r
+\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#include <IndustryStandard/CloudHv.h> // CLOUDHV_RSDP_ADDRESS\r
+#include <Library/BaseLib.h> // CpuDeadLoop()\r
+#include <Library/DebugLib.h> // DEBUG()\r
+\r
+#include "AcpiPlatform.h"\r
+\r
+// Get the ACPI tables from EBDA start\r
+EFI_STATUS\r
+EFIAPI\r
+InstallCloudHvTables (\r
+ IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN TableHandle;\r
+\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_DESCRIPTION_HEADER *DsdtTable;\r
+\r
+ Fadt2Table = NULL;\r
+ DsdtTable = NULL;\r
+ TableHandle = 0;\r
+ NumberOfTableEntries = 0;\r
+ EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *AcpiRsdpStructurePtr = (VOID *)CLOUDHV_RSDP_ADDRESS;\r
+\r
+ // If XSDT table is found, just install its tables.\r
+ // Otherwise, try to find and install the RSDT tables.\r
+ //\r
+ if (AcpiRsdpStructurePtr->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
+ AcpiRsdpStructurePtr->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 = AcpiProtocol->InstallAcpiTable (\r
+ AcpiProtocol,\r
+ CurrentTable,\r
+ CurrentTable->Length,\r
+ &TableHandle\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ ASSERT_EFI_ERROR (Status);\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Get the X-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
+ DsdtTable = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)Fadt2Table->XDsdt;\r
+ }\r
+ }\r
+ } else {\r
+ return EFI_NOT_FOUND;\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 = AcpiProtocol->InstallAcpiTable (\r
+ AcpiProtocol,\r
+ DsdtTable,\r
+ DsdtTable->Length,\r
+ &TableHandle\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ ASSERT_EFI_ERROR (Status);\r
+ return Status;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r