mirror of https://github.com/acidanthera/audk.git
228 lines
7.3 KiB
C
228 lines
7.3 KiB
C
/** @file
|
|
OVMF ACPI Cloud Hypervisor support
|
|
|
|
Copyright (c) 2021, Intel Corporation. All rights reserved.
|
|
|
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
|
|
**/
|
|
|
|
#include <IndustryStandard/Acpi.h> // EFI_ACPI_DESCRIPTION_HEADER
|
|
#include <IndustryStandard/CloudHv.h> // CLOUDHV_RSDP_ADDRESS
|
|
#include <IndustryStandard/Xen/arch-x86/hvm/start_info.h> // hvm_start_info
|
|
#include <Library/BaseLib.h> // CpuDeadLoop()
|
|
#include <Library/DebugLib.h> // DEBUG()
|
|
#include <Library/PcdLib.h> // PcdGet32()
|
|
#include <Library/HobLib.h> // GetFirstGuidHob(), GetNextGuidHob()
|
|
#include <Library/UefiBootServicesTableLib.h> // gBS
|
|
#include <Protocol/AcpiSystemDescriptionTable.h>
|
|
#include <Protocol/AcpiTable.h>
|
|
|
|
#include "AcpiPlatform.h"
|
|
|
|
EFI_STATUS
|
|
EFIAPI
|
|
InstallCloudHvTablesTdx (
|
|
IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINTN TableHandle;
|
|
EFI_HANDLE ChAcpiHandle;
|
|
|
|
EFI_PEI_HOB_POINTERS Hob;
|
|
EFI_ACPI_DESCRIPTION_HEADER *CurrentTable;
|
|
EFI_ACPI_DESCRIPTION_HEADER *DsdtTable;
|
|
|
|
DsdtTable = NULL;
|
|
TableHandle = 0;
|
|
|
|
Hob.Guid = (EFI_HOB_GUID_TYPE *)GetFirstGuidHob (&gUefiOvmfPkgTdxAcpiHobGuid);
|
|
|
|
while (Hob.Guid != NULL) {
|
|
CurrentTable = (EFI_ACPI_DESCRIPTION_HEADER *)(&Hob.Guid->Name + 1);
|
|
if (!AsciiStrnCmp ((CHAR8 *)&CurrentTable->Signature, "DSDT", 4)) {
|
|
DsdtTable = CurrentTable;
|
|
} else {
|
|
//
|
|
// Install the tables
|
|
//
|
|
Status = AcpiProtocol->InstallAcpiTable (
|
|
AcpiProtocol,
|
|
CurrentTable,
|
|
CurrentTable->Length,
|
|
&TableHandle
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT_EFI_ERROR (Status);
|
|
return Status;
|
|
}
|
|
|
|
for (UINTN i = 0; i < CurrentTable->Length; i++) {
|
|
DEBUG ((DEBUG_INFO, " %x", *((UINT8 *)CurrentTable + i)));
|
|
}
|
|
|
|
DEBUG ((DEBUG_INFO, "\n"));
|
|
}
|
|
|
|
Hob.Raw = GET_NEXT_HOB (Hob.Raw);
|
|
Hob.Guid = (EFI_HOB_GUID_TYPE *)GetNextGuidHob (&gUefiOvmfPkgTdxAcpiHobGuid, Hob.Raw);
|
|
}
|
|
|
|
//
|
|
// Install DSDT table. If we reached this point without finding the DSDT,
|
|
// then we're out of sync with the hypervisor, and cannot continue.
|
|
//
|
|
if (DsdtTable == NULL) {
|
|
DEBUG ((DEBUG_ERROR, "%a: no DSDT found\n", __func__));
|
|
ASSERT (FALSE);
|
|
CpuDeadLoop ();
|
|
}
|
|
|
|
Status = AcpiProtocol->InstallAcpiTable (
|
|
AcpiProtocol,
|
|
DsdtTable,
|
|
DsdtTable->Length,
|
|
&TableHandle
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT_EFI_ERROR (Status);
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Install a protocol to notify that the ACPI table provided by CH is
|
|
// ready.
|
|
//
|
|
ChAcpiHandle = NULL;
|
|
Status = gBS->InstallProtocolInterface (
|
|
&ChAcpiHandle,
|
|
&gQemuAcpiTableNotifyProtocolGuid,
|
|
EFI_NATIVE_INTERFACE,
|
|
NULL
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT_EFI_ERROR (Status);
|
|
return Status;
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
// Get the ACPI tables from EBDA start
|
|
EFI_STATUS
|
|
EFIAPI
|
|
InstallCloudHvTables (
|
|
IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINTN TableHandle;
|
|
|
|
EFI_ACPI_DESCRIPTION_HEADER *Xsdt;
|
|
VOID *CurrentTableEntry;
|
|
UINTN CurrentTablePointer;
|
|
EFI_ACPI_DESCRIPTION_HEADER *CurrentTable;
|
|
UINTN Index;
|
|
UINTN NumberOfTableEntries;
|
|
EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt2Table;
|
|
EFI_ACPI_DESCRIPTION_HEADER *DsdtTable;
|
|
EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *AcpiRsdpStructurePtr;
|
|
UINT32 *PVHResetVectorData;
|
|
struct hvm_start_info *pvh_start_info;
|
|
|
|
Fadt2Table = NULL;
|
|
DsdtTable = NULL;
|
|
TableHandle = 0;
|
|
NumberOfTableEntries = 0;
|
|
AcpiRsdpStructurePtr = NULL;
|
|
PVHResetVectorData = NULL;
|
|
pvh_start_info = NULL;
|
|
|
|
PVHResetVectorData = (VOID *)(UINTN)PcdGet32 (PcdXenPvhStartOfDayStructPtr);
|
|
if (PVHResetVectorData == 0) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
pvh_start_info = (struct hvm_start_info *)(UINTN)PVHResetVectorData[0];
|
|
AcpiRsdpStructurePtr = (EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)(UINTN)pvh_start_info->rsdp_paddr;
|
|
|
|
// If XSDT table is found, just install its tables.
|
|
// Otherwise, try to find and install the RSDT tables.
|
|
//
|
|
if (AcpiRsdpStructurePtr->XsdtAddress) {
|
|
//
|
|
// Retrieve the addresses of XSDT and
|
|
// calculate the number of its table entries.
|
|
//
|
|
Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)
|
|
AcpiRsdpStructurePtr->XsdtAddress;
|
|
NumberOfTableEntries = (Xsdt->Length -
|
|
sizeof (EFI_ACPI_DESCRIPTION_HEADER)) /
|
|
sizeof (UINT64);
|
|
|
|
//
|
|
// Install ACPI tables found in XSDT.
|
|
//
|
|
for (Index = 0; Index < NumberOfTableEntries; Index++) {
|
|
//
|
|
// Get the table entry from XSDT
|
|
//
|
|
CurrentTableEntry = (VOID *)((UINT8 *)Xsdt +
|
|
sizeof (EFI_ACPI_DESCRIPTION_HEADER) +
|
|
Index * sizeof (UINT64));
|
|
CurrentTablePointer = (UINTN)*(UINT64 *)CurrentTableEntry;
|
|
CurrentTable = (EFI_ACPI_DESCRIPTION_HEADER *)CurrentTablePointer;
|
|
|
|
//
|
|
// Install the XSDT tables
|
|
//
|
|
Status = AcpiProtocol->InstallAcpiTable (
|
|
AcpiProtocol,
|
|
CurrentTable,
|
|
CurrentTable->Length,
|
|
&TableHandle
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT_EFI_ERROR (Status);
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Get the X-DSDT table address from the table FADT
|
|
//
|
|
if (!AsciiStrnCmp ((CHAR8 *)&CurrentTable->Signature, "FACP", 4)) {
|
|
Fadt2Table = (EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *)
|
|
(UINTN)CurrentTablePointer;
|
|
DsdtTable = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)Fadt2Table->XDsdt;
|
|
}
|
|
}
|
|
} else {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
//
|
|
// Install DSDT table. If we reached this point without finding the DSDT,
|
|
// then we're out of sync with the hypervisor, and cannot continue.
|
|
//
|
|
if (DsdtTable == NULL) {
|
|
DEBUG ((DEBUG_ERROR, "%a: no DSDT found\n", __func__));
|
|
ASSERT (FALSE);
|
|
CpuDeadLoop ();
|
|
}
|
|
|
|
Status = AcpiProtocol->InstallAcpiTable (
|
|
AcpiProtocol,
|
|
DsdtTable,
|
|
DsdtTable->Length,
|
|
&TableHandle
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT_EFI_ERROR (Status);
|
|
return Status;
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|