mirror of https://github.com/acidanthera/audk.git
203 lines
7.2 KiB
C
203 lines
7.2 KiB
C
/** @file
|
|
|
|
|
|
Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
|
|
|
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
|
|
**/
|
|
|
|
#include "UefiPayloadEntry.h"
|
|
|
|
|
|
/**
|
|
Find the board related info from ACPI table
|
|
|
|
@param AcpiTableBase ACPI table start address in memory
|
|
@param AcpiBoardInfo Pointer to the acpi board info strucutre
|
|
|
|
@retval RETURN_SUCCESS Successfully find out all the required information.
|
|
@retval RETURN_NOT_FOUND Failed to find the required info.
|
|
|
|
**/
|
|
RETURN_STATUS
|
|
ParseAcpiInfo (
|
|
IN UINT64 AcpiTableBase,
|
|
OUT ACPI_BOARD_INFO *AcpiBoardInfo
|
|
)
|
|
{
|
|
EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp;
|
|
EFI_ACPI_DESCRIPTION_HEADER *Rsdt;
|
|
UINT32 *Entry32;
|
|
UINTN Entry32Num;
|
|
EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt;
|
|
EFI_ACPI_DESCRIPTION_HEADER *Xsdt;
|
|
UINT64 *Entry64;
|
|
UINTN Entry64Num;
|
|
UINTN Idx;
|
|
UINT32 *Signature;
|
|
EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEADER *MmCfgHdr;
|
|
EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE *MmCfgBase;
|
|
|
|
Rsdp = (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)(UINTN)AcpiTableBase;
|
|
DEBUG ((DEBUG_INFO, "Rsdp at 0x%p\n", Rsdp));
|
|
DEBUG ((DEBUG_INFO, "Rsdt at 0x%x, Xsdt at 0x%lx\n", Rsdp->RsdtAddress, Rsdp->XsdtAddress));
|
|
|
|
//
|
|
// Search Rsdt First
|
|
//
|
|
Fadt = NULL;
|
|
MmCfgHdr = NULL;
|
|
Rsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)(Rsdp->RsdtAddress);
|
|
if (Rsdt != NULL) {
|
|
Entry32 = (UINT32 *)(Rsdt + 1);
|
|
Entry32Num = (Rsdt->Length - sizeof(EFI_ACPI_DESCRIPTION_HEADER)) >> 2;
|
|
for (Idx = 0; Idx < Entry32Num; Idx++) {
|
|
Signature = (UINT32 *)(UINTN)Entry32[Idx];
|
|
if (*Signature == EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE) {
|
|
Fadt = (EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *)Signature;
|
|
DEBUG ((DEBUG_INFO, "Found Fadt in Rsdt\n"));
|
|
}
|
|
|
|
if (*Signature == EFI_ACPI_5_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE) {
|
|
MmCfgHdr = (EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEADER *)Signature;
|
|
DEBUG ((DEBUG_INFO, "Found MM config address in Rsdt\n"));
|
|
}
|
|
|
|
if ((Fadt != NULL) && (MmCfgHdr != NULL)) {
|
|
goto Done;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Search Xsdt Second
|
|
//
|
|
Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)(Rsdp->XsdtAddress);
|
|
if (Xsdt != NULL) {
|
|
Entry64 = (UINT64 *)(Xsdt + 1);
|
|
Entry64Num = (Xsdt->Length - sizeof(EFI_ACPI_DESCRIPTION_HEADER)) >> 3;
|
|
for (Idx = 0; Idx < Entry64Num; Idx++) {
|
|
Signature = (UINT32 *)(UINTN)Entry64[Idx];
|
|
if (*Signature == EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE) {
|
|
Fadt = (EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *)Signature;
|
|
DEBUG ((DEBUG_INFO, "Found Fadt in Xsdt\n"));
|
|
}
|
|
|
|
if (*Signature == EFI_ACPI_5_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE) {
|
|
MmCfgHdr = (EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEADER *)Signature;
|
|
DEBUG ((DEBUG_INFO, "Found MM config address in Xsdt\n"));
|
|
}
|
|
|
|
if ((Fadt != NULL) && (MmCfgHdr != NULL)) {
|
|
goto Done;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (Fadt == NULL) {
|
|
return RETURN_NOT_FOUND;
|
|
}
|
|
|
|
Done:
|
|
|
|
AcpiBoardInfo->PmCtrlRegBase = Fadt->Pm1aCntBlk;
|
|
AcpiBoardInfo->PmTimerRegBase = Fadt->PmTmrBlk;
|
|
AcpiBoardInfo->ResetRegAddress = Fadt->ResetReg.Address;
|
|
AcpiBoardInfo->ResetValue = Fadt->ResetValue;
|
|
AcpiBoardInfo->PmEvtBase = Fadt->Pm1aEvtBlk;
|
|
AcpiBoardInfo->PmGpeEnBase = Fadt->Gpe0Blk + Fadt->Gpe0BlkLen / 2;
|
|
|
|
if (MmCfgHdr != NULL) {
|
|
MmCfgBase = (EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE *)((UINT8*) MmCfgHdr + sizeof (*MmCfgHdr));
|
|
AcpiBoardInfo->PcieBaseAddress = MmCfgBase->BaseAddress;
|
|
AcpiBoardInfo->PcieBaseSize = (MmCfgBase->EndBusNumber + 1 - MmCfgBase->StartBusNumber) * 4096 * 32 * 8;
|
|
} else {
|
|
AcpiBoardInfo->PcieBaseAddress = 0;
|
|
AcpiBoardInfo->PcieBaseSize = 0;
|
|
}
|
|
DEBUG ((DEBUG_INFO, "PmCtrl Reg 0x%lx\n", AcpiBoardInfo->PmCtrlRegBase));
|
|
DEBUG ((DEBUG_INFO, "PmTimer Reg 0x%lx\n", AcpiBoardInfo->PmTimerRegBase));
|
|
DEBUG ((DEBUG_INFO, "Reset Reg 0x%lx\n", AcpiBoardInfo->ResetRegAddress));
|
|
DEBUG ((DEBUG_INFO, "Reset Value 0x%x\n", AcpiBoardInfo->ResetValue));
|
|
DEBUG ((DEBUG_INFO, "PmEvt Reg 0x%lx\n", AcpiBoardInfo->PmEvtBase));
|
|
DEBUG ((DEBUG_INFO, "PmGpeEn Reg 0x%lx\n", AcpiBoardInfo->PmGpeEnBase));
|
|
DEBUG ((DEBUG_INFO, "PcieBaseAddr 0x%lx\n", AcpiBoardInfo->PcieBaseAddress));
|
|
DEBUG ((DEBUG_INFO, "PcieBaseSize 0x%lx\n", AcpiBoardInfo->PcieBaseSize));
|
|
|
|
//
|
|
// Verify values for proper operation
|
|
//
|
|
ASSERT(Fadt->Pm1aCntBlk != 0);
|
|
ASSERT(Fadt->PmTmrBlk != 0);
|
|
ASSERT(Fadt->ResetReg.Address != 0);
|
|
ASSERT(Fadt->Pm1aEvtBlk != 0);
|
|
ASSERT(Fadt->Gpe0Blk != 0);
|
|
|
|
DEBUG_CODE_BEGIN ();
|
|
BOOLEAN SciEnabled;
|
|
|
|
//
|
|
// Check the consistency of SCI enabling
|
|
//
|
|
|
|
//
|
|
// Get SCI_EN value
|
|
//
|
|
if (Fadt->Pm1CntLen == 4) {
|
|
SciEnabled = (IoRead32 (Fadt->Pm1aCntBlk) & BIT0)? TRUE : FALSE;
|
|
} else {
|
|
//
|
|
// if (Pm1CntLen == 2), use 16 bit IO read;
|
|
// if (Pm1CntLen != 2 && Pm1CntLen != 4), use 16 bit IO read as a fallback
|
|
//
|
|
SciEnabled = (IoRead16 (Fadt->Pm1aCntBlk) & BIT0)? TRUE : FALSE;
|
|
}
|
|
|
|
if (!(Fadt->Flags & EFI_ACPI_5_0_HW_REDUCED_ACPI) &&
|
|
(Fadt->SmiCmd == 0) &&
|
|
!SciEnabled) {
|
|
//
|
|
// The ACPI enabling status is inconsistent: SCI is not enabled but ACPI
|
|
// table does not provide a means to enable it through FADT->SmiCmd
|
|
//
|
|
DEBUG ((DEBUG_ERROR, "ERROR: The ACPI enabling status is inconsistent: SCI is not"
|
|
" enabled but the ACPI table does not provide a means to enable it through FADT->SmiCmd."
|
|
" This may cause issues in OS.\n"));
|
|
}
|
|
DEBUG_CODE_END ();
|
|
|
|
return RETURN_SUCCESS;
|
|
}
|
|
|
|
|
|
/**
|
|
Build ACPI board info HOB using infomation from ACPI table
|
|
|
|
@param AcpiTableBase ACPI table start address in memory
|
|
|
|
@retval A pointer to ACPI board HOB ACPI_BOARD_INFO. Null if build HOB failure.
|
|
**/
|
|
ACPI_BOARD_INFO *
|
|
BuildHobFromAcpi (
|
|
IN UINT64 AcpiTableBase
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
ACPI_BOARD_INFO AcpiBoardInfo;
|
|
ACPI_BOARD_INFO *NewAcpiBoardInfo;
|
|
|
|
NewAcpiBoardInfo = NULL;
|
|
Status = ParseAcpiInfo (AcpiTableBase, &AcpiBoardInfo);
|
|
ASSERT_EFI_ERROR (Status);
|
|
if (!EFI_ERROR (Status)) {
|
|
NewAcpiBoardInfo = BuildGuidHob (&gUefiAcpiBoardInfoGuid, sizeof (ACPI_BOARD_INFO));
|
|
ASSERT (NewAcpiBoardInfo != NULL);
|
|
CopyMem (NewAcpiBoardInfo, &AcpiBoardInfo, sizeof (ACPI_BOARD_INFO));
|
|
DEBUG ((DEBUG_INFO, "Create acpi board info guid hob\n"));
|
|
}
|
|
return NewAcpiBoardInfo;
|
|
}
|
|
|
|
|