| /** @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 | |
| ); | |
| } |