mirror of https://github.com/acidanthera/audk.git
423 lines
13 KiB
C
423 lines
13 KiB
C
/** @file
|
|
This module provides help function for finding ACPI table.
|
|
|
|
Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
|
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
|
|
**/
|
|
|
|
#include "UefiLibInternal.h"
|
|
#include <IndustryStandard/Acpi.h>
|
|
#include <Guid/Acpi.h>
|
|
|
|
/**
|
|
This function scans ACPI table in XSDT/RSDT.
|
|
|
|
@param Sdt ACPI XSDT/RSDT.
|
|
@param TablePointerSize Size of table pointer: 8(XSDT) or 4(RSDT).
|
|
@param Signature ACPI table signature.
|
|
@param PreviousTable Pointer to previous returned table to locate
|
|
next table, or NULL to locate first table.
|
|
@param PreviousTableLocated Pointer to the indicator about whether the
|
|
previous returned table could be located, or
|
|
NULL if PreviousTable is NULL.
|
|
|
|
If PreviousTable is NULL and PreviousTableLocated is not NULL, then ASSERT().
|
|
If PreviousTable is not NULL and PreviousTableLocated is NULL, then ASSERT().
|
|
|
|
@return ACPI table or NULL if not found.
|
|
|
|
**/
|
|
EFI_ACPI_COMMON_HEADER *
|
|
ScanTableInSDT (
|
|
IN EFI_ACPI_DESCRIPTION_HEADER *Sdt,
|
|
IN UINTN TablePointerSize,
|
|
IN UINT32 Signature,
|
|
IN EFI_ACPI_COMMON_HEADER *PreviousTable, OPTIONAL
|
|
OUT BOOLEAN *PreviousTableLocated OPTIONAL
|
|
)
|
|
{
|
|
UINTN Index;
|
|
UINTN EntryCount;
|
|
UINT64 EntryPtr;
|
|
UINTN BasePtr;
|
|
EFI_ACPI_COMMON_HEADER *Table;
|
|
|
|
if (PreviousTableLocated != NULL) {
|
|
ASSERT (PreviousTable != NULL);
|
|
*PreviousTableLocated = FALSE;
|
|
} else {
|
|
ASSERT (PreviousTable == NULL);
|
|
}
|
|
|
|
if (Sdt == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
EntryCount = (Sdt->Length - sizeof (EFI_ACPI_DESCRIPTION_HEADER)) / TablePointerSize;
|
|
|
|
BasePtr = (UINTN)(Sdt + 1);
|
|
for (Index = 0; Index < EntryCount; Index ++) {
|
|
EntryPtr = 0;
|
|
CopyMem (&EntryPtr, (VOID *)(BasePtr + Index * TablePointerSize), TablePointerSize);
|
|
Table = (EFI_ACPI_COMMON_HEADER *)((UINTN)(EntryPtr));
|
|
if ((Table != NULL) && (Table->Signature == Signature)) {
|
|
if (PreviousTable != NULL) {
|
|
if (Table == PreviousTable) {
|
|
*PreviousTableLocated = TRUE;
|
|
} else if (*PreviousTableLocated) {
|
|
//
|
|
// Return next table.
|
|
//
|
|
return Table;
|
|
}
|
|
} else {
|
|
//
|
|
// Return first table.
|
|
//
|
|
return Table;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
To locate FACS in FADT.
|
|
|
|
@param Fadt FADT table pointer.
|
|
|
|
@return FACS table pointer or NULL if not found.
|
|
|
|
**/
|
|
EFI_ACPI_COMMON_HEADER *
|
|
LocateAcpiFacsFromFadt (
|
|
IN EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt
|
|
)
|
|
{
|
|
EFI_ACPI_COMMON_HEADER *Facs;
|
|
UINT64 Data64;
|
|
|
|
if (Fadt == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if (Fadt->Header.Revision < EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION) {
|
|
Facs = (EFI_ACPI_COMMON_HEADER *)(UINTN)Fadt->FirmwareCtrl;
|
|
} else {
|
|
CopyMem (&Data64, &Fadt->XFirmwareCtrl, sizeof(UINT64));
|
|
if (Data64 != 0) {
|
|
Facs = (EFI_ACPI_COMMON_HEADER *)(UINTN)Data64;
|
|
} else {
|
|
Facs = (EFI_ACPI_COMMON_HEADER *)(UINTN)Fadt->FirmwareCtrl;
|
|
}
|
|
}
|
|
return Facs;
|
|
}
|
|
|
|
/**
|
|
To locate DSDT in FADT.
|
|
|
|
@param Fadt FADT table pointer.
|
|
|
|
@return DSDT table pointer or NULL if not found.
|
|
|
|
**/
|
|
EFI_ACPI_COMMON_HEADER *
|
|
LocateAcpiDsdtFromFadt (
|
|
IN EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt
|
|
)
|
|
{
|
|
EFI_ACPI_COMMON_HEADER *Dsdt;
|
|
UINT64 Data64;
|
|
|
|
if (Fadt == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if (Fadt->Header.Revision < EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION) {
|
|
Dsdt = (EFI_ACPI_COMMON_HEADER *)(UINTN)Fadt->Dsdt;
|
|
} else {
|
|
CopyMem (&Data64, &Fadt->XDsdt, sizeof(UINT64));
|
|
if (Data64 != 0) {
|
|
Dsdt = (EFI_ACPI_COMMON_HEADER *)(UINTN)Data64;
|
|
} else {
|
|
Dsdt = (EFI_ACPI_COMMON_HEADER *)(UINTN)Fadt->Dsdt;
|
|
}
|
|
}
|
|
return Dsdt;
|
|
}
|
|
|
|
/**
|
|
To locate ACPI table in ACPI ConfigurationTable.
|
|
|
|
@param AcpiGuid The GUID used to get ACPI ConfigurationTable.
|
|
@param Signature ACPI table signature.
|
|
@param PreviousTable Pointer to previous returned table to locate
|
|
next table, or NULL to locate first table.
|
|
@param PreviousTableLocated Pointer to the indicator to return whether the
|
|
previous returned table could be located or not,
|
|
or NULL if PreviousTable is NULL.
|
|
|
|
If PreviousTable is NULL and PreviousTableLocated is not NULL, then ASSERT().
|
|
If PreviousTable is not NULL and PreviousTableLocated is NULL, then ASSERT().
|
|
If AcpiGuid is NULL, then ASSERT().
|
|
|
|
@return ACPI table or NULL if not found.
|
|
|
|
**/
|
|
EFI_ACPI_COMMON_HEADER *
|
|
LocateAcpiTableInAcpiConfigurationTable (
|
|
IN EFI_GUID *AcpiGuid,
|
|
IN UINT32 Signature,
|
|
IN EFI_ACPI_COMMON_HEADER *PreviousTable, OPTIONAL
|
|
OUT BOOLEAN *PreviousTableLocated OPTIONAL
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_ACPI_COMMON_HEADER *Table;
|
|
EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp;
|
|
EFI_ACPI_DESCRIPTION_HEADER *Rsdt;
|
|
EFI_ACPI_DESCRIPTION_HEADER *Xsdt;
|
|
EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt;
|
|
|
|
if (PreviousTableLocated != NULL) {
|
|
ASSERT (PreviousTable != NULL);
|
|
*PreviousTableLocated = FALSE;
|
|
} else {
|
|
ASSERT (PreviousTable == NULL);
|
|
}
|
|
|
|
Rsdp = NULL;
|
|
//
|
|
// Get ACPI ConfigurationTable (RSD_PTR)
|
|
//
|
|
Status = EfiGetSystemConfigurationTable(AcpiGuid, (VOID **)&Rsdp);
|
|
if (EFI_ERROR (Status) || (Rsdp == NULL)) {
|
|
return NULL;
|
|
}
|
|
|
|
Table = NULL;
|
|
|
|
//
|
|
// Search XSDT
|
|
//
|
|
if (Rsdp->Revision >= EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER_REVISION) {
|
|
Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN) Rsdp->XsdtAddress;
|
|
if (Signature == EFI_ACPI_2_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) {
|
|
ASSERT (PreviousTable == NULL);
|
|
//
|
|
// It is to locate DSDT,
|
|
// need to locate FADT first.
|
|
//
|
|
Fadt = (EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *) ScanTableInSDT (
|
|
Xsdt,
|
|
sizeof (UINT64),
|
|
EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE,
|
|
NULL,
|
|
NULL
|
|
);
|
|
Table = LocateAcpiDsdtFromFadt (Fadt);
|
|
} else if (Signature == EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE) {
|
|
ASSERT (PreviousTable == NULL);
|
|
//
|
|
// It is to locate FACS,
|
|
// need to locate FADT first.
|
|
//
|
|
Fadt = (EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *) ScanTableInSDT (
|
|
Xsdt,
|
|
sizeof (UINT64),
|
|
EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE,
|
|
NULL,
|
|
NULL
|
|
);
|
|
Table = LocateAcpiFacsFromFadt (Fadt);
|
|
} else {
|
|
Table = ScanTableInSDT (
|
|
Xsdt,
|
|
sizeof (UINT64),
|
|
Signature,
|
|
PreviousTable,
|
|
PreviousTableLocated
|
|
);
|
|
}
|
|
}
|
|
|
|
if (Table != NULL) {
|
|
return Table;
|
|
} else if ((PreviousTableLocated != NULL) &&
|
|
*PreviousTableLocated) {
|
|
//
|
|
// PreviousTable could be located in XSDT,
|
|
// but next table could not be located in XSDT.
|
|
//
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// Search RSDT
|
|
//
|
|
Rsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN) Rsdp->RsdtAddress;
|
|
if (Signature == EFI_ACPI_2_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) {
|
|
ASSERT (PreviousTable == NULL);
|
|
//
|
|
// It is to locate DSDT,
|
|
// need to locate FADT first.
|
|
//
|
|
Fadt = (EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *) ScanTableInSDT (
|
|
Rsdt,
|
|
sizeof (UINT32),
|
|
EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE,
|
|
NULL,
|
|
NULL
|
|
);
|
|
Table = LocateAcpiDsdtFromFadt (Fadt);
|
|
} else if (Signature == EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE) {
|
|
ASSERT (PreviousTable == NULL);
|
|
//
|
|
// It is to locate FACS,
|
|
// need to locate FADT first.
|
|
//
|
|
Fadt = (EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *) ScanTableInSDT (
|
|
Rsdt,
|
|
sizeof (UINT32),
|
|
EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE,
|
|
NULL,
|
|
NULL
|
|
);
|
|
Table = LocateAcpiFacsFromFadt (Fadt);
|
|
} else {
|
|
Table = ScanTableInSDT (
|
|
Rsdt,
|
|
sizeof (UINT32),
|
|
Signature,
|
|
PreviousTable,
|
|
PreviousTableLocated
|
|
);
|
|
}
|
|
|
|
return Table;
|
|
}
|
|
|
|
/**
|
|
This function locates next ACPI table in XSDT/RSDT based on Signature and
|
|
previous returned Table.
|
|
|
|
If PreviousTable is NULL:
|
|
This function will locate the first ACPI table in XSDT/RSDT based on
|
|
Signature in gEfiAcpi20TableGuid system configuration table first, and then
|
|
gEfiAcpi10TableGuid system configuration table.
|
|
This function will locate in XSDT first, and then RSDT.
|
|
For DSDT, this function will locate XDsdt in FADT first, and then Dsdt in
|
|
FADT.
|
|
For FACS, this function will locate XFirmwareCtrl in FADT first, and then
|
|
FirmwareCtrl in FADT.
|
|
|
|
If PreviousTable is not NULL:
|
|
1. If it could be located in XSDT in gEfiAcpi20TableGuid system configuration
|
|
table, then this function will just locate next table in XSDT in
|
|
gEfiAcpi20TableGuid system configuration table.
|
|
2. If it could be located in RSDT in gEfiAcpi20TableGuid system configuration
|
|
table, then this function will just locate next table in RSDT in
|
|
gEfiAcpi20TableGuid system configuration table.
|
|
3. If it could be located in RSDT in gEfiAcpi10TableGuid system configuration
|
|
table, then this function will just locate next table in RSDT in
|
|
gEfiAcpi10TableGuid system configuration table.
|
|
|
|
It's not supported that PreviousTable is not NULL but PreviousTable->Signature
|
|
is not same with Signature, NULL will be returned.
|
|
|
|
@param Signature ACPI table signature.
|
|
@param PreviousTable Pointer to previous returned table to locate next
|
|
table, or NULL to locate first table.
|
|
|
|
@return Next ACPI table or NULL if not found.
|
|
|
|
**/
|
|
EFI_ACPI_COMMON_HEADER *
|
|
EFIAPI
|
|
EfiLocateNextAcpiTable (
|
|
IN UINT32 Signature,
|
|
IN EFI_ACPI_COMMON_HEADER *PreviousTable OPTIONAL
|
|
)
|
|
{
|
|
EFI_ACPI_COMMON_HEADER *Table;
|
|
BOOLEAN TempPreviousTableLocated;
|
|
BOOLEAN *PreviousTableLocated;
|
|
|
|
if (PreviousTable != NULL) {
|
|
if (PreviousTable->Signature != Signature) {
|
|
//
|
|
// PreviousTable->Signature is not same with Signature.
|
|
//
|
|
return NULL;
|
|
} else if ((Signature == EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE) ||
|
|
(Signature == EFI_ACPI_2_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) ||
|
|
(Signature == EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE)) {
|
|
//
|
|
// There is only one FADT/DSDT/FACS table,
|
|
// so don't try to locate next one.
|
|
//
|
|
return NULL;
|
|
}
|
|
|
|
PreviousTableLocated = &TempPreviousTableLocated;
|
|
*PreviousTableLocated = FALSE;
|
|
} else {
|
|
PreviousTableLocated = NULL;
|
|
}
|
|
|
|
Table = LocateAcpiTableInAcpiConfigurationTable (
|
|
&gEfiAcpi20TableGuid,
|
|
Signature,
|
|
PreviousTable,
|
|
PreviousTableLocated
|
|
);
|
|
if (Table != NULL) {
|
|
return Table;
|
|
} else if ((PreviousTableLocated != NULL) &&
|
|
*PreviousTableLocated) {
|
|
//
|
|
// PreviousTable could be located in gEfiAcpi20TableGuid system
|
|
// configuration table, but next table could not be located in
|
|
// gEfiAcpi20TableGuid system configuration table.
|
|
//
|
|
return NULL;
|
|
}
|
|
|
|
return LocateAcpiTableInAcpiConfigurationTable (
|
|
&gEfiAcpi10TableGuid,
|
|
Signature,
|
|
PreviousTable,
|
|
PreviousTableLocated
|
|
);
|
|
}
|
|
|
|
/**
|
|
This function locates first ACPI table in XSDT/RSDT based on Signature.
|
|
|
|
This function will locate the first ACPI table in XSDT/RSDT based on
|
|
Signature in gEfiAcpi20TableGuid system configuration table first, and then
|
|
gEfiAcpi10TableGuid system configuration table.
|
|
This function will locate in XSDT first, and then RSDT.
|
|
For DSDT, this function will locate XDsdt in FADT first, and then Dsdt in
|
|
FADT.
|
|
For FACS, this function will locate XFirmwareCtrl in FADT first, and then
|
|
FirmwareCtrl in FADT.
|
|
|
|
@param Signature ACPI table signature.
|
|
|
|
@return First ACPI table or NULL if not found.
|
|
|
|
**/
|
|
EFI_ACPI_COMMON_HEADER *
|
|
EFIAPI
|
|
EfiLocateFirstAcpiTable (
|
|
IN UINT32 Signature
|
|
)
|
|
{
|
|
return EfiLocateNextAcpiTable (Signature, NULL);
|
|
}
|