/** @file Install Acpi tables for Cloud Hypervisor Copyright (c) 2021, Arm Limited. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include #include #include #include #include #include #include /** 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", __func__)); 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", __func__, Status )); CpuDeadLoop (); } return EFI_SUCCESS; }