/** @file | |
ACPI table parser | |
Copyright (c) 2016 - 2020, ARM Limited. All rights reserved. | |
SPDX-License-Identifier: BSD-2-Clause-Patent | |
@par Glossary: | |
- Sbbr or SBBR - Server Base Boot Requirements | |
@par Reference(s): | |
- Arm Server Base Boot Requirements 1.2, September 2019 | |
**/ | |
#include <Uefi.h> | |
#include <IndustryStandard/Acpi.h> | |
#include <Library/UefiLib.h> | |
#include "AcpiParser.h" | |
#include "AcpiTableParser.h" | |
#include "AcpiView.h" | |
#include "AcpiViewConfig.h" | |
#if defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64) | |
#include "Arm/SbbrValidator.h" | |
#endif | |
/** | |
A list of registered ACPI table parsers. | |
**/ | |
STATIC ACPI_TABLE_PARSER mTableParserList[MAX_ACPI_TABLE_PARSERS]; | |
/** | |
Register the ACPI table Parser | |
This function registers the ACPI table parser. | |
@param [in] Signature The ACPI table signature. | |
@param [in] ParserProc The ACPI table parser. | |
@retval EFI_SUCCESS The parser is registered. | |
@retval EFI_INVALID_PARAMETER A parameter is invalid. | |
@retval EFI_ALREADY_STARTED The parser for the Table | |
was already registered. | |
@retval EFI_OUT_OF_RESOURCES No space to register the | |
parser. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
RegisterParser ( | |
IN UINT32 Signature, | |
IN PARSE_ACPI_TABLE_PROC ParserProc | |
) | |
{ | |
UINT32 Index; | |
if ((ParserProc == NULL) || (Signature == ACPI_PARSER_SIGNATURE_NULL)) { | |
return EFI_INVALID_PARAMETER; | |
} | |
// Search if a parser is already installed | |
for (Index = 0; | |
Index < (sizeof (mTableParserList) / sizeof (mTableParserList[0])); | |
Index++) | |
{ | |
if (Signature == mTableParserList[Index].Signature) { | |
if (mTableParserList[Index].Parser != NULL) { | |
return EFI_ALREADY_STARTED; | |
} | |
} | |
} | |
// Find the first free slot and register the parser | |
for (Index = 0; | |
Index < (sizeof (mTableParserList) / sizeof (mTableParserList[0])); | |
Index++) | |
{ | |
if (mTableParserList[Index].Signature == ACPI_PARSER_SIGNATURE_NULL) { | |
mTableParserList[Index].Signature = Signature; | |
mTableParserList[Index].Parser = ParserProc; | |
return EFI_SUCCESS; | |
} | |
} | |
// No free slot found | |
return EFI_OUT_OF_RESOURCES; | |
} | |
/** | |
Deregister the ACPI table Parser | |
This function deregisters the ACPI table parser. | |
@param [in] Signature The ACPI table signature. | |
@retval EFI_SUCCESS The parser was deregistered. | |
@retval EFI_INVALID_PARAMETER A parameter is invalid. | |
@retval EFI_NOT_FOUND A registered parser was not found. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
DeregisterParser ( | |
IN UINT32 Signature | |
) | |
{ | |
UINT32 Index; | |
if (Signature == ACPI_PARSER_SIGNATURE_NULL) { | |
return EFI_INVALID_PARAMETER; | |
} | |
for (Index = 0; | |
Index < (sizeof (mTableParserList) / sizeof (mTableParserList[0])); | |
Index++) | |
{ | |
if (Signature == mTableParserList[Index].Signature) { | |
mTableParserList[Index].Signature = ACPI_PARSER_SIGNATURE_NULL; | |
mTableParserList[Index].Parser = NULL; | |
return EFI_SUCCESS; | |
} | |
} | |
// No matching registered parser found. | |
return EFI_NOT_FOUND; | |
} | |
/** | |
Get the ACPI table Parser | |
This function returns the ACPI table parser proc from the list of | |
registered parsers. | |
@param [in] Signature The ACPI table signature. | |
@param [out] ParserProc Pointer to a ACPI table parser proc. | |
@retval EFI_SUCCESS The parser was returned successfully. | |
@retval EFI_INVALID_PARAMETER A parameter is invalid. | |
@retval EFI_NOT_FOUND A registered parser was not found. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
GetParser ( | |
IN UINT32 Signature, | |
OUT PARSE_ACPI_TABLE_PROC *ParserProc | |
) | |
{ | |
UINT32 Index; | |
if ((ParserProc == NULL) || (Signature == ACPI_PARSER_SIGNATURE_NULL)) { | |
return EFI_INVALID_PARAMETER; | |
} | |
for (Index = 0; | |
Index < (sizeof (mTableParserList) / sizeof (mTableParserList[0])); | |
Index++) | |
{ | |
if (Signature == mTableParserList[Index].Signature) { | |
*ParserProc = mTableParserList[Index].Parser; | |
return EFI_SUCCESS; | |
} | |
} | |
// No matching registered parser found. | |
return EFI_NOT_FOUND; | |
} | |
/** | |
This function processes the ACPI tables. | |
This function calls ProcessTableReportOptions() to list the ACPI | |
tables, perform binary dump of the tables and determine if the | |
ACPI fields should be traced. | |
This function also invokes the parser for the ACPI tables. | |
This function also performs a RAW dump of the ACPI table including | |
the unknown/unparsed ACPI tables and validates the checksum. | |
@param [in] Ptr Pointer to the start of the ACPI | |
table data buffer. | |
**/ | |
VOID | |
EFIAPI | |
ProcessAcpiTable ( | |
IN UINT8 *Ptr | |
) | |
{ | |
EFI_STATUS Status; | |
BOOLEAN Trace; | |
CONST UINT32 *AcpiTableSignature; | |
CONST UINT32 *AcpiTableLength; | |
CONST UINT8 *AcpiTableRevision; | |
CONST UINT8 *SignaturePtr; | |
PARSE_ACPI_TABLE_PROC ParserProc; | |
ParseAcpiHeader ( | |
Ptr, | |
&AcpiTableSignature, | |
&AcpiTableLength, | |
&AcpiTableRevision | |
); | |
Trace = ProcessTableReportOptions ( | |
*AcpiTableSignature, | |
Ptr, | |
*AcpiTableLength | |
); | |
if (Trace) { | |
DumpRaw (Ptr, *AcpiTableLength); | |
// Do not process the ACPI table any further if the table length read | |
// is invalid. The ACPI table should at least contain the table header. | |
if (*AcpiTableLength < sizeof (EFI_ACPI_DESCRIPTION_HEADER)) { | |
SignaturePtr = (CONST UINT8 *)AcpiTableSignature; | |
IncrementErrorCount (); | |
Print ( | |
L"ERROR: Invalid %c%c%c%c table length. Length = %d\n", | |
SignaturePtr[0], | |
SignaturePtr[1], | |
SignaturePtr[2], | |
SignaturePtr[3], | |
*AcpiTableLength | |
); | |
return; | |
} | |
if (GetConsistencyChecking ()) { | |
VerifyChecksum (TRUE, Ptr, *AcpiTableLength); | |
} | |
} | |
#if defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64) | |
if (GetMandatoryTableValidate ()) { | |
ArmSbbrIncrementTableCount (*AcpiTableSignature); | |
} | |
#endif | |
Status = GetParser (*AcpiTableSignature, &ParserProc); | |
if (EFI_ERROR (Status)) { | |
// No registered parser found, do default handling. | |
if (Trace) { | |
DumpAcpiHeader (Ptr); | |
} | |
return; | |
} | |
ParserProc ( | |
Trace, | |
Ptr, | |
*AcpiTableLength, | |
*AcpiTableRevision | |
); | |
} |