audk/ArmVirtPkg/XenAcpiPlatformDxe/XenAcpiPlatformDxe.c

256 lines
7.6 KiB
C

/** @file
Xen ARM ACPI Platform Driver using Xen ARM multiboot protocol
Copyright (C) 2016, Linaro Ltd. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include <Library/BaseLib.h>
#include <Library/DebugLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiDriverEntryPoint.h>
#include <Protocol/AcpiTable.h>
#include <Protocol/FdtClient.h>
#include <IndustryStandard/Acpi.h>
/**
Get the address of Xen ACPI Root System Description Pointer (RSDP)
structure.
@param RsdpStructurePtr Return pointer to RSDP structure
@return EFI_SUCCESS Find Xen RSDP structure successfully.
@return EFI_NOT_FOUND Don't find Xen RSDP structure.
@return EFI_ABORTED Find Xen RSDP structure, but it's not integrated.
**/
STATIC
EFI_STATUS
EFIAPI
GetXenArmAcpiRsdp (
OUT EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER **RsdpPtr
)
{
EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *RsdpStructurePtr;
EFI_STATUS Status;
FDT_CLIENT_PROTOCOL *FdtClient;
CONST UINT64 *Reg;
UINT32 RegSize;
UINTN AddressCells, SizeCells;
UINT64 RegBase;
UINT8 Sum;
RsdpStructurePtr = NULL;
FdtClient = NULL;
//
// Get the RSDP structure address from DeviceTree
//
Status = gBS->LocateProtocol (
&gFdtClientProtocolGuid,
NULL,
(VOID **)&FdtClient
);
ASSERT_EFI_ERROR (Status);
Status = FdtClient->FindCompatibleNodeReg (
FdtClient,
"xen,guest-acpi",
(CONST VOID **)&Reg,
&AddressCells,
&SizeCells,
&RegSize
);
if (EFI_ERROR (Status)) {
DEBUG ((
DEBUG_WARN,
"%a: No 'xen,guest-acpi' compatible DT node found\n",
__FUNCTION__
));
return EFI_NOT_FOUND;
}
ASSERT (AddressCells == 2);
ASSERT (SizeCells == 2);
ASSERT (RegSize == 2 * sizeof (UINT64));
RegBase = SwapBytes64 (Reg[0]);
RsdpStructurePtr =
(EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)(UINTN)RegBase;
if (RsdpStructurePtr && (RsdpStructurePtr->Revision >= 2)) {
Sum = CalculateSum8 (
(CONST UINT8 *)RsdpStructurePtr,
sizeof (EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER)
);
if (Sum != 0) {
return EFI_ABORTED;
}
}
*RsdpPtr = RsdpStructurePtr;
return EFI_SUCCESS;
}
/**
Get Xen Acpi tables from the RSDP structure. And installs Xen ACPI tables
into the RSDT/XSDT using InstallAcpiTable. Some signature of the installed
ACPI tables are: FACP, APIC, GTDT, DSDT.
@param AcpiProtocol Protocol instance pointer.
@return EFI_SUCCESS The table was successfully inserted.
@return EFI_INVALID_PARAMETER Either AcpiTableBuffer is NULL, TableHandle is
NULL, or AcpiTableBufferSize and the size
field embedded in the ACPI table pointed to
by AcpiTableBuffer are not in sync.
@return EFI_OUT_OF_RESOURCES Insufficient resources exist to complete the request.
**/
STATIC
EFI_STATUS
EFIAPI
InstallXenArmTables (
IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol
)
{
EFI_STATUS Status;
UINTN TableHandle;
VOID *CurrentTableEntry;
UINTN CurrentTablePointer;
EFI_ACPI_DESCRIPTION_HEADER *CurrentTable;
UINTN Index;
UINTN NumberOfTableEntries;
EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *XenAcpiRsdpStructurePtr;
EFI_ACPI_DESCRIPTION_HEADER *Xsdt;
EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *FadtTable;
EFI_ACPI_DESCRIPTION_HEADER *DsdtTable;
XenAcpiRsdpStructurePtr = NULL;
FadtTable = NULL;
DsdtTable = NULL;
TableHandle = 0;
NumberOfTableEntries = 0;
//
// Try to find Xen ARM ACPI tables
//
Status = GetXenArmAcpiRsdp (&XenAcpiRsdpStructurePtr);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "%a: No RSDP table found\n", __FUNCTION__));
return Status;
}
//
// If XSDT table is find, just install its tables.
//
if (XenAcpiRsdpStructurePtr->XsdtAddress) {
//
// Retrieve the addresses of XSDT and
// calculate the number of its table entries.
//
Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)
XenAcpiRsdpStructurePtr->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)) {
return Status;
}
//
// Get the FACS and DSDT table address from the table FADT
//
if (!AsciiStrnCmp ((CHAR8 *)&CurrentTable->Signature, "FACP", 4)) {
FadtTable = (EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *)
(UINTN)CurrentTablePointer;
DsdtTable = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)FadtTable->Dsdt;
}
}
}
//
// Install DSDT table.
//
Status = AcpiProtocol->InstallAcpiTable (
AcpiProtocol,
DsdtTable,
DsdtTable->Length,
&TableHandle
);
if (EFI_ERROR (Status)) {
return Status;
}
return EFI_SUCCESS;
}
STATIC
EFI_ACPI_TABLE_PROTOCOL *
FindAcpiTableProtocol (
VOID
)
{
EFI_STATUS Status;
EFI_ACPI_TABLE_PROTOCOL *AcpiTable;
AcpiTable = NULL;
Status = gBS->LocateProtocol (
&gEfiAcpiTableProtocolGuid,
NULL,
(VOID **)&AcpiTable
);
ASSERT_EFI_ERROR (Status);
return AcpiTable;
}
/**
Entrypoint of Xen ARM Acpi Platform driver.
@param ImageHandle
@param SystemTable
@return EFI_SUCCESS
@return EFI_LOAD_ERROR
@return EFI_OUT_OF_RESOURCES
**/
EFI_STATUS
EFIAPI
XenAcpiPlatformEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
Status = InstallXenArmTables (FindAcpiTableProtocol ());
return Status;
}