This makes the function reuseable by bhyve. Signed-off-by: Corvin Köhne <corvink@FreeBSD.org> Reviewed-by: Anthony PERARD <anthony.perard@citrix.com> Acked-by: Gerd Hoffmann <kraxel@redhat.com>
		
			
				
	
	
		
			253 lines
		
	
	
		
			7.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			253 lines
		
	
	
		
			7.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  OVMF ACPI support
 | 
						|
 | 
						|
  Copyright (C) 2021, Red Hat, Inc.
 | 
						|
  Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>
 | 
						|
  Copyright (c) 2012, Bei Guan <gbtju85@gmail.com>
 | 
						|
 | 
						|
  SPDX-License-Identifier: BSD-2-Clause-Patent
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#include <Library/AcpiPlatformLib.h>
 | 
						|
#include <Library/BaseLib.h>
 | 
						|
#include <Library/DebugLib.h>
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
GetAcpiRsdpFromMemory (
 | 
						|
  IN UINTN                                            StartAddress,
 | 
						|
  IN UINTN                                            EndAddress,
 | 
						|
  OUT   EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER  **RsdpPtr
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER  *RsdpStructurePtr;
 | 
						|
  UINT8                                         *AcpiPtr;
 | 
						|
  UINT8                                         Sum;
 | 
						|
 | 
						|
  for (AcpiPtr = (UINT8 *)StartAddress;
 | 
						|
       AcpiPtr < (UINT8 *)EndAddress;
 | 
						|
       AcpiPtr += 0x10)
 | 
						|
  {
 | 
						|
    RsdpStructurePtr = (EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)
 | 
						|
                       (UINTN)AcpiPtr;
 | 
						|
 | 
						|
    if (!AsciiStrnCmp ((CHAR8 *)&RsdpStructurePtr->Signature, "RSD PTR ", 8)) {
 | 
						|
      //
 | 
						|
      // RSDP ACPI 1.0 checksum for 1.0/2.0/3.0 table.
 | 
						|
      // This is only the first 20 bytes of the structure
 | 
						|
      //
 | 
						|
      Sum = CalculateSum8 (
 | 
						|
              (CONST UINT8 *)RsdpStructurePtr,
 | 
						|
              sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER)
 | 
						|
              );
 | 
						|
      if (Sum != 0) {
 | 
						|
        return EFI_ABORTED;
 | 
						|
      }
 | 
						|
 | 
						|
      if (RsdpStructurePtr->Revision >= 2) {
 | 
						|
        //
 | 
						|
        // RSDP ACPI 2.0/3.0 checksum, this is the entire table
 | 
						|
        //
 | 
						|
        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;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_NOT_FOUND;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
InstallAcpiTablesFromRsdp (
 | 
						|
  IN EFI_ACPI_TABLE_PROTOCOL                       *AcpiProtocol,
 | 
						|
  IN EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER  *Rsdp
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
  UINTN       TableHandle;
 | 
						|
 | 
						|
  EFI_ACPI_DESCRIPTION_HEADER                   *Rsdt;
 | 
						|
  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_1_0_FIXED_ACPI_DESCRIPTION_TABLE     *Fadt1Table;
 | 
						|
  EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE  *Facs2Table;
 | 
						|
  EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE  *Facs1Table;
 | 
						|
  EFI_ACPI_DESCRIPTION_HEADER                   *DsdtTable;
 | 
						|
 | 
						|
  Fadt2Table           = NULL;
 | 
						|
  Fadt1Table           = NULL;
 | 
						|
  Facs2Table           = NULL;
 | 
						|
  Facs1Table           = NULL;
 | 
						|
  DsdtTable            = NULL;
 | 
						|
  TableHandle          = 0;
 | 
						|
  NumberOfTableEntries = 0;
 | 
						|
 | 
						|
  //
 | 
						|
  // If XSDT table is find, just install its tables.
 | 
						|
  // Otherwise, try to find and install the RSDT tables.
 | 
						|
  //
 | 
						|
  if (Rsdp->XsdtAddress) {
 | 
						|
    //
 | 
						|
    // Retrieve the addresses of XSDT and
 | 
						|
    // calculate the number of its table entries.
 | 
						|
    //
 | 
						|
    Xsdt                 = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)Rsdp->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)) {
 | 
						|
        Fadt2Table = (EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *)(UINTN)
 | 
						|
                     CurrentTablePointer;
 | 
						|
        Facs2Table = (EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *)(UINTN)
 | 
						|
                     Fadt2Table->FirmwareCtrl;
 | 
						|
        DsdtTable = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)Fadt2Table->Dsdt;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  } else if (Rsdp->RsdtAddress) {
 | 
						|
    //
 | 
						|
    // Retrieve the addresses of RSDT and
 | 
						|
    // calculate the number of its table entries.
 | 
						|
    //
 | 
						|
    Rsdt                 = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)Rsdp->RsdtAddress;
 | 
						|
    NumberOfTableEntries =
 | 
						|
      (Rsdt->Length - sizeof (EFI_ACPI_DESCRIPTION_HEADER)) / sizeof (UINT32);
 | 
						|
 | 
						|
    //
 | 
						|
    // Install ACPI tables found in XSDT.
 | 
						|
    //
 | 
						|
    for (Index = 0; Index < NumberOfTableEntries; Index++) {
 | 
						|
      //
 | 
						|
      // Get the table entry from RSDT
 | 
						|
      //
 | 
						|
      CurrentTableEntry =
 | 
						|
        (UINT32 *)((UINT8 *)Rsdt + sizeof (EFI_ACPI_DESCRIPTION_HEADER) +
 | 
						|
                   Index * sizeof (UINT32));
 | 
						|
      CurrentTablePointer = *(UINT32 *)CurrentTableEntry;
 | 
						|
      CurrentTable        = (EFI_ACPI_DESCRIPTION_HEADER *)CurrentTablePointer;
 | 
						|
 | 
						|
      //
 | 
						|
      // Install the RSDT 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)) {
 | 
						|
        Fadt1Table = (EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE *)(UINTN)
 | 
						|
                     CurrentTablePointer;
 | 
						|
        Facs1Table = (EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *)(UINTN)
 | 
						|
                     Fadt1Table->FirmwareCtrl;
 | 
						|
        DsdtTable = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)Fadt1Table->Dsdt;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Install the FACS table.
 | 
						|
  //
 | 
						|
  if (Fadt2Table) {
 | 
						|
    //
 | 
						|
    // FACS 2.0
 | 
						|
    //
 | 
						|
    Status = AcpiProtocol->InstallAcpiTable (
 | 
						|
                             AcpiProtocol,
 | 
						|
                             Facs2Table,
 | 
						|
                             Facs2Table->Length,
 | 
						|
                             &TableHandle
 | 
						|
                             );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
  } else if (Fadt1Table) {
 | 
						|
    //
 | 
						|
    // FACS 1.0
 | 
						|
    //
 | 
						|
    Status = AcpiProtocol->InstallAcpiTable (
 | 
						|
                             AcpiProtocol,
 | 
						|
                             Facs1Table,
 | 
						|
                             Facs1Table->Length,
 | 
						|
                             &TableHandle
 | 
						|
                             );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // 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)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 |