|
@@ -0,0 +1,160 @@
|
|
|
+/** @file
|
|
|
+ Install Acpi tables for Cloud Hypervisor
|
|
|
+
|
|
|
+ Copyright (c) 2021, Arm Limited. All rights reserved.<BR>
|
|
|
+
|
|
|
+ SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
|
+**/
|
|
|
+
|
|
|
+#include <Library/BaseLib.h>
|
|
|
+#include <Library/MemoryAllocationLib.h>
|
|
|
+#include <IndustryStandard/Acpi63.h>
|
|
|
+#include <Protocol/AcpiTable.h>
|
|
|
+#include <Library/UefiBootServicesTableLib.h>
|
|
|
+#include <Library/UefiDriverEntryPoint.h>
|
|
|
+#include <Library/DebugLib.h>
|
|
|
+
|
|
|
+/**
|
|
|
+ Find Acpi table Protocol and return it
|
|
|
+
|
|
|
+ @return AcpiTable Protocol, which is used to handle Acpi Table, on SUCCESS or NULL on FAILURE.
|
|
|
+
|
|
|
+**/
|
|
|
+STATIC
|
|
|
+EFI_ACPI_TABLE_PROTOCOL *
|
|
|
+FindAcpiTableProtocol (
|
|
|
+ VOID
|
|
|
+ )
|
|
|
+{
|
|
|
+ EFI_STATUS Status;
|
|
|
+ EFI_ACPI_TABLE_PROTOCOL *AcpiTable;
|
|
|
+
|
|
|
+ Status = gBS->LocateProtocol (
|
|
|
+ &gEfiAcpiTableProtocolGuid,
|
|
|
+ NULL,
|
|
|
+ (VOID**)&AcpiTable
|
|
|
+ );
|
|
|
+ ASSERT_EFI_ERROR (Status);
|
|
|
+ return AcpiTable;
|
|
|
+}
|
|
|
+
|
|
|
+/** Install Acpi tables for Cloud Hypervisor
|
|
|
+
|
|
|
+ @param [in] AcpiProtocol Acpi Protocol which is used to install Acpi tables
|
|
|
+
|
|
|
+ @return EFI_SUCCESS The table was successfully inserted.
|
|
|
+ @return EFI_INVALID_PARAMETER Either AcpiProtocol, AcpiTablePtr or DsdtPtr is NULL
|
|
|
+ and the size field embedded in the ACPI table pointed
|
|
|
+ by AcpiTablePtr or DsdtPtr are not in sync.
|
|
|
+ @return EFI_OUT_OF_RESOURCES Insufficient resources exist to complete the request.
|
|
|
+ @return EFI_NOT_FOUND DSDT table not found.
|
|
|
+**/
|
|
|
+EFI_STATUS
|
|
|
+EFIAPI
|
|
|
+InstallCloudHvAcpiTables (
|
|
|
+ IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol
|
|
|
+ )
|
|
|
+{
|
|
|
+ UINTN InstalledKey;
|
|
|
+ UINTN TableSize;
|
|
|
+ UINTN AcpiTableLength;
|
|
|
+ UINT64 RsdpPtr;
|
|
|
+ UINT64 XsdtPtr;
|
|
|
+ UINT64 TableOffset;
|
|
|
+ UINT64 AcpiTablePtr;
|
|
|
+ UINT64 *DsdtPtr;
|
|
|
+ EFI_STATUS Status;
|
|
|
+
|
|
|
+ if (AcpiProtocol == NULL) {
|
|
|
+ return EFI_INVALID_PARAMETER;
|
|
|
+ }
|
|
|
+
|
|
|
+ RsdpPtr = PcdGet64 (PcdCloudHvAcpiRsdpBaseAddress);
|
|
|
+ XsdtPtr = ((EFI_ACPI_6_3_ROOT_SYSTEM_DESCRIPTION_POINTER *)RsdpPtr)->XsdtAddress;
|
|
|
+ AcpiTableLength = ((EFI_ACPI_COMMON_HEADER *)XsdtPtr)->Length;
|
|
|
+ TableOffset = sizeof (EFI_ACPI_DESCRIPTION_HEADER);
|
|
|
+ DsdtPtr = NULL;
|
|
|
+
|
|
|
+ while (TableOffset < AcpiTableLength) {
|
|
|
+ AcpiTablePtr = *(UINT64 *)(XsdtPtr + TableOffset);
|
|
|
+ TableSize = ((EFI_ACPI_COMMON_HEADER *)AcpiTablePtr)->Length;
|
|
|
+
|
|
|
+ //
|
|
|
+ // Install ACPI tables from XSDT
|
|
|
+ //
|
|
|
+ Status = AcpiProtocol->InstallAcpiTable (
|
|
|
+ AcpiProtocol,
|
|
|
+ (VOID *)AcpiTablePtr,
|
|
|
+ TableSize,
|
|
|
+ &InstalledKey
|
|
|
+ );
|
|
|
+ if (EFI_ERROR (Status)) {
|
|
|
+ return Status;
|
|
|
+ }
|
|
|
+
|
|
|
+ //
|
|
|
+ // Get DSDT from FADT
|
|
|
+ //
|
|
|
+ if ((DsdtPtr == NULL) &&
|
|
|
+ (EFI_ACPI_6_3_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE ==
|
|
|
+ ((EFI_ACPI_COMMON_HEADER *)AcpiTablePtr)->Signature)) {
|
|
|
+ DsdtPtr = (UINT64 *)((EFI_ACPI_6_3_FIXED_ACPI_DESCRIPTION_TABLE *)AcpiTablePtr)->XDsdt;
|
|
|
+ }
|
|
|
+
|
|
|
+ TableOffset += sizeof (UINT64);
|
|
|
+ } // while
|
|
|
+
|
|
|
+ if (DsdtPtr == NULL) {
|
|
|
+ DEBUG ((DEBUG_ERROR, "%a: no DSDT found\n", __FUNCTION__));
|
|
|
+ return EFI_NOT_FOUND;
|
|
|
+ }
|
|
|
+
|
|
|
+ //
|
|
|
+ // Install DSDT table
|
|
|
+ //
|
|
|
+ TableSize = ((EFI_ACPI_COMMON_HEADER *)DsdtPtr)->Length;
|
|
|
+ Status = AcpiProtocol->InstallAcpiTable (
|
|
|
+ AcpiProtocol,
|
|
|
+ DsdtPtr,
|
|
|
+ TableSize,
|
|
|
+ &InstalledKey
|
|
|
+ );
|
|
|
+
|
|
|
+ return Status;
|
|
|
+}
|
|
|
+
|
|
|
+/** Entry point for Cloud Hypervisor Platform Dxe
|
|
|
+
|
|
|
+ @param [in] ImageHandle Handle for this image.
|
|
|
+ @param [in] SystemTable Pointer to the EFI system table.
|
|
|
+
|
|
|
+ @return EFI_SUCCESS The table was successfully inserted.
|
|
|
+ @return EFI_INVALID_PARAMETER Either AcpiProtocol, AcpiTablePtr or DsdtPtr is NULL
|
|
|
+ and the size field embedded in the ACPI table pointed to
|
|
|
+ by AcpiTablePtr or DsdtPtr are not in sync.
|
|
|
+ @return EFI_OUT_OF_RESOURCES Insufficient resources exist to complete the request.
|
|
|
+ @return EFI_NOT_FOUND DSDT table not found
|
|
|
+**/
|
|
|
+EFI_STATUS
|
|
|
+EFIAPI
|
|
|
+CloudHvAcpiPlatformEntryPoint (
|
|
|
+ IN EFI_HANDLE ImageHandle,
|
|
|
+ IN EFI_SYSTEM_TABLE *SystemTable
|
|
|
+ )
|
|
|
+{
|
|
|
+ EFI_STATUS Status;
|
|
|
+
|
|
|
+ Status = InstallCloudHvAcpiTables (FindAcpiTableProtocol ());
|
|
|
+
|
|
|
+ if (EFI_ERROR (Status)) {
|
|
|
+ DEBUG ((
|
|
|
+ DEBUG_ERROR,
|
|
|
+ "%a: Fail to install Acpi table: %r\n",
|
|
|
+ __FUNCTION__,
|
|
|
+ Status
|
|
|
+ ));
|
|
|
+ CpuDeadLoop ();
|
|
|
+ }
|
|
|
+
|
|
|
+ return EFI_SUCCESS;
|
|
|
+}
|