123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546 |
- /** @file
- MADT table parser
- Copyright (c) 2016 - 2020, ARM Limited. All rights reserved.
- Copyright (c) 2022, AMD Incorporated. All rights reserved.
- SPDX-License-Identifier: BSD-2-Clause-Patent
- @par Reference(s):
- - ACPI 6.3 Specification - January 2019
- - Arm Generic Interrupt Controller Architecture Specification,
- GIC architecture version 3 and version 4, issue E
- - Arm Server Base System Architecture 5.0
- **/
- #include <IndustryStandard/Acpi.h>
- #include <Library/UefiLib.h>
- #include "AcpiParser.h"
- #include "AcpiTableParser.h"
- #include "AcpiViewConfig.h"
- #include "MadtParser.h"
- // Local Variables
- STATIC CONST UINT8 *MadtInterruptControllerType;
- STATIC CONST UINT8 *MadtInterruptControllerLength;
- STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo;
- /**
- This function validates the System Vector Base in the GICD.
- @param [in] Ptr Pointer to the start of the field data.
- @param [in] Context Pointer to context specific information e.g. this
- could be a pointer to the ACPI table header.
- **/
- STATIC
- VOID
- EFIAPI
- ValidateGICDSystemVectorBase (
- IN UINT8 *Ptr,
- IN VOID *Context
- )
- {
- if (*(UINT32 *)Ptr != 0) {
- IncrementErrorCount ();
- Print (
- L"\nERROR: System Vector Base must be zero."
- );
- }
- }
- /**
- This function validates the SPE Overflow Interrupt in the GICC.
- @param [in] Ptr Pointer to the start of the field data.
- @param [in] Context Pointer to context specific information e.g. this
- could be a pointer to the ACPI table header.
- **/
- STATIC
- VOID
- EFIAPI
- ValidateSpeOverflowInterrupt (
- IN UINT8 *Ptr,
- IN VOID *Context
- )
- {
- UINT16 SpeOverflowInterrupt;
- SpeOverflowInterrupt = *(UINT16 *)Ptr;
- // SPE not supported by this processor
- if (SpeOverflowInterrupt == 0) {
- return;
- }
- if ((SpeOverflowInterrupt < ARM_PPI_ID_MIN) ||
- ((SpeOverflowInterrupt > ARM_PPI_ID_MAX) &&
- (SpeOverflowInterrupt < ARM_PPI_ID_EXTENDED_MIN)) ||
- (SpeOverflowInterrupt > ARM_PPI_ID_EXTENDED_MAX))
- {
- IncrementErrorCount ();
- Print (
- L"\nERROR: SPE Overflow Interrupt ID of %d is not in the allowed PPI ID "
- L"ranges of %d-%d or %d-%d (for GICv3.1 or later).",
- SpeOverflowInterrupt,
- ARM_PPI_ID_MIN,
- ARM_PPI_ID_MAX,
- ARM_PPI_ID_EXTENDED_MIN,
- ARM_PPI_ID_EXTENDED_MAX
- );
- } else if (SpeOverflowInterrupt != ARM_PPI_ID_PMBIRQ) {
- IncrementWarningCount ();
- Print (
- L"\nWARNING: SPE Overflow Interrupt ID of %d is not compliant with SBSA "
- L"Level 3 PPI ID assignment: %d.",
- SpeOverflowInterrupt,
- ARM_PPI_ID_PMBIRQ
- );
- }
- }
- /**
- An ACPI_PARSER array describing the GICC Interrupt Controller Structure.
- **/
- STATIC CONST ACPI_PARSER GicCParser[] = {
- { L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL },
- { L"Length", 1, 1, L"%d", NULL, NULL, NULL, NULL },
- { L"Reserved", 2, 2, L"0x%x", NULL, NULL, NULL, NULL },
- { L"CPU Interface Number", 4, 4, L"0x%x", NULL, NULL, NULL, NULL },
- { L"ACPI Processor UID", 4, 8, L"0x%x", NULL, NULL, NULL, NULL },
- { L"Flags", 4, 12, L"0x%x", NULL, NULL, NULL, NULL },
- { L"Parking Protocol Version", 4, 16, L"0x%x", NULL, NULL, NULL, NULL },
- { L"Performance Interrupt GSIV", 4, 20, L"0x%x", NULL, NULL, NULL, NULL },
- { L"Parked Address", 8, 24, L"0x%lx", NULL, NULL, NULL, NULL },
- { L"Physical Base Address", 8, 32, L"0x%lx", NULL, NULL, NULL, NULL },
- { L"GICV", 8, 40, L"0x%lx", NULL, NULL, NULL, NULL },
- { L"GICH", 8, 48, L"0x%lx", NULL, NULL, NULL, NULL },
- { L"VGIC Maintenance interrupt", 4, 56, L"0x%x", NULL, NULL, NULL, NULL },
- { L"GICR Base Address", 8, 60, L"0x%lx", NULL, NULL, NULL, NULL },
- { L"MPIDR", 8, 68, L"0x%lx", NULL, NULL, NULL, NULL },
- { L"Processor Power Efficiency Class", 1, 76, L"0x%x", NULL, NULL, NULL,
- NULL },
- { L"Reserved", 1, 77, L"0x%x", NULL, NULL, NULL, NULL },
- { L"SPE overflow Interrupt", 2, 78, L"0x%x", NULL, NULL,
- ValidateSpeOverflowInterrupt, NULL }
- };
- /**
- An ACPI_PARSER array describing the GICD Interrupt Controller Structure.
- **/
- STATIC CONST ACPI_PARSER GicDParser[] = {
- { L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL },
- { L"Length", 1, 1, L"%d", NULL, NULL, NULL, NULL },
- { L"Reserved", 2, 2, L"0x%x", NULL, NULL, NULL, NULL },
- { L"GIC ID", 4, 4, L"0x%x", NULL, NULL, NULL, NULL },
- { L"Physical Base Address", 8, 8, L"0x%lx", NULL, NULL, NULL, NULL },
- { L"System Vector Base", 4, 16, L"0x%x", NULL, NULL,
- ValidateGICDSystemVectorBase, NULL },
- { L"GIC Version", 1, 20, L"%d", NULL, NULL, NULL, NULL },
- { L"Reserved", 3, 21, L"%x %x %x", Dump3Chars, NULL, NULL, NULL }
- };
- /**
- An ACPI_PARSER array describing the MSI Frame Interrupt Controller Structure.
- **/
- STATIC CONST ACPI_PARSER GicMSIFrameParser[] = {
- { L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL },
- { L"Length", 1, 1, L"%d", NULL, NULL, NULL, NULL },
- { L"Reserved", 2, 2, L"0x%x", NULL, NULL, NULL, NULL },
- { L"MSI Frame ID", 4, 4, L"0x%x", NULL, NULL, NULL, NULL },
- { L"Physical Base Address", 8, 8, L"0x%lx", NULL, NULL, NULL, NULL },
- { L"Flags", 4, 16, L"0x%x", NULL, NULL, NULL, NULL },
- { L"SPI Count", 2, 20, L"%d", NULL, NULL, NULL, NULL },
- { L"SPI Base", 2, 22, L"0x%x", NULL, NULL, NULL, NULL }
- };
- /**
- An ACPI_PARSER array describing the GICR Interrupt Controller Structure.
- **/
- STATIC CONST ACPI_PARSER GicRParser[] = {
- { L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL },
- { L"Length", 1, 1, L"%d", NULL, NULL, NULL, NULL },
- { L"Reserved", 2, 2, L"0x%x", NULL, NULL, NULL, NULL },
- { L"Discovery Range Base Address", 8, 4, L"0x%lx", NULL, NULL, NULL,
- NULL },
- { L"Discovery Range Length", 4, 12, L"0x%x", NULL, NULL, NULL, NULL }
- };
- /**
- An ACPI_PARSER array describing the GIC ITS Interrupt Controller Structure.
- **/
- STATIC CONST ACPI_PARSER GicITSParser[] = {
- { L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL },
- { L"Length", 1, 1, L"%d", NULL, NULL, NULL, NULL },
- { L"Reserved", 2, 2, L"0x%x", NULL, NULL, NULL, NULL },
- { L"GIC ITS ID", 4, 4, L"0x%x", NULL, NULL, NULL, NULL },
- { L"Physical Base Address", 8, 8, L"0x%lx", NULL, NULL, NULL, NULL },
- { L"Reserved", 4, 16, L"0x%x", NULL, NULL, NULL, NULL }
- };
- /**
- An ACPI_PARSER array describing the IO APIC Structure.
- **/
- STATIC CONST ACPI_PARSER IoApic[] = {
- { L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL },
- { L"Length", 1, 1, L"%d", NULL, NULL, NULL, NULL },
- { L"I/O APIC ID", 1, 2, L"0x%x", NULL, NULL, NULL, NULL },
- { L"Reserved", 1, 3, L"0x%x", NULL, NULL, NULL, NULL },
- { L"I/O APIC Address", 4, 4, L"0x%x", NULL, NULL, NULL, NULL },
- { L"Global System Interrupt Base", 4, 8, L"0x%x", NULL, NULL, NULL, NULL }
- };
- /**
- An ACPI_PARSER array describing the Interrupt Source Override Structure.
- **/
- STATIC CONST ACPI_PARSER InterruptSourceOverride[] = {
- { L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL },
- { L"Length", 1, 1, L"%d", NULL, NULL, NULL, NULL },
- { L"Bus", 1, 2, L"0x%x", NULL, NULL, NULL, NULL },
- { L"Source", 1, 3, L"0x%x", NULL, NULL, NULL, NULL },
- { L"Global System Interrupt", 4, 4, L"0x%x", NULL, NULL, NULL, NULL },
- { L"Flags", 2, 8, L"0x%x", NULL, NULL, NULL, NULL }
- };
- STATIC CONST ACPI_PARSER LocalApicFlags[] = {
- { L"Enabled", 1, 0, L"%d", NULL, NULL, NULL, NULL },
- { L"Online Capable", 1, 1, L"%d", NULL, NULL, NULL, NULL },
- { L"Reserved", 30, 2, L"%d", NULL, NULL, NULL, NULL }
- };
- /**
- This function traces Bit Flags fields.
- If no format string is specified the Format must be NULL.
- @param [in] Format Optional format string for tracing the data.
- @param [in] Ptr Pointer to the start of the buffer.
- **/
- VOID
- EFIAPI
- DumpLocalApicBitFlags (
- IN CONST CHAR16 *Format OPTIONAL,
- IN UINT8 *Ptr
- )
- {
- if (Format != NULL) {
- Print (Format, *(UINT32 *)Ptr);
- return;
- }
- Print (L"0x%X\n", *(UINT32 *)Ptr);
- ParseAcpiBitFields (
- TRUE,
- 2,
- NULL,
- Ptr,
- 4,
- PARSER_PARAMS (LocalApicFlags)
- );
- }
- /**
- An ACPI_PARSER array describing the Processor Local APIC Structure.
- **/
- STATIC CONST ACPI_PARSER ProcessorLocalApic[] = {
- { L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL },
- { L"Length", 1, 1, L"%d", NULL, NULL, NULL, NULL },
- { L"ACPI Processor UID", 1, 2, L"0x%x", NULL, NULL, NULL, NULL },
- { L"APIC ID", 1, 3, L"0x%x", NULL, NULL, NULL, NULL },
- { L"Flags", 4, 4, NULL, DumpLocalApicBitFlags, NULL, NULL, NULL }
- };
- /**
- An ACPI_PARSER array describing the Processor Local x2APIC Structure.
- **/
- STATIC CONST ACPI_PARSER ProcessorLocalX2Apic[] = {
- { L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL },
- { L"Length", 1, 1, L"%d", NULL, NULL, NULL, NULL },
- { L"Reserved", 2, 2, L"0x%x", NULL, NULL, NULL, NULL },
- { L"X2APIC ID", 4, 4, L"0x%x", NULL, NULL, NULL, NULL },
- { L"Flags", 4, 8, NULL, DumpLocalApicBitFlags, NULL, NULL, NULL },
- { L"ACPI Processor UID", 4, 12, L"0x%x", NULL, NULL, NULL, NULL }
- };
- /**
- An ACPI_PARSER array describing the Local x2APIC NMI Structure.
- **/
- STATIC CONST ACPI_PARSER LocalX2ApicNmi[] = {
- { L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL },
- { L"Length", 1, 1, L"%d", NULL, NULL, NULL, NULL },
- { L"Flags", 2, 2, L"0x%x", NULL, NULL, NULL, NULL },
- { L"ACPI Processor UID", 4, 4, L"0x%x", NULL, NULL, NULL, NULL },
- { L"Local x2APIC LINT#", 1, 8, L"0x%x", NULL, NULL, NULL, NULL },
- { L"Reserved", 3, 9, L"0x%x%x%x", Dump3Chars, NULL, NULL, NULL }
- };
- /**
- An ACPI_PARSER array describing the ACPI MADT Table.
- **/
- STATIC CONST ACPI_PARSER MadtParser[] = {
- PARSE_ACPI_HEADER (&AcpiHdrInfo),
- { L"Local Interrupt Controller Address",4, 36, L"0x%x", NULL, NULL, NULL,
- NULL },
- { L"Flags", 4, 40, L"0x%x", NULL, NULL, NULL,NULL}
- };
- /**
- An ACPI_PARSER array describing the MADT Interrupt Controller Structure Header Structure.
- **/
- STATIC CONST ACPI_PARSER MadtInterruptControllerHeaderParser[] = {
- { NULL, 1, 0, NULL, NULL, (VOID **)&MadtInterruptControllerType, NULL, NULL },
- { L"Length", 1, 1, NULL, NULL, (VOID **)&MadtInterruptControllerLength, NULL,
- NULL },
- { L"Reserved", 2, 2, NULL, NULL, NULL, NULL, NULL }
- };
- /**
- This function parses the ACPI MADT table.
- When trace is enabled this function parses the MADT table and
- traces the ACPI table fields.
- This function currently parses the following Interrupt Controller
- Structures:
- - GICC
- - GICD
- - GIC MSI Frame
- - GICR
- - GIC ITS
- This function also performs validation of the ACPI table fields.
- @param [in] Trace If TRUE, trace the ACPI fields.
- @param [in] Ptr Pointer to the start of the buffer.
- @param [in] AcpiTableLength Length of the ACPI table.
- @param [in] AcpiTableRevision Revision of the ACPI table.
- **/
- VOID
- EFIAPI
- ParseAcpiMadt (
- IN BOOLEAN Trace,
- IN UINT8 *Ptr,
- IN UINT32 AcpiTableLength,
- IN UINT8 AcpiTableRevision
- )
- {
- UINT32 Offset;
- UINT8 *InterruptContollerPtr;
- UINT32 GICDCount;
- GICDCount = 0;
- if (!Trace) {
- return;
- }
- Offset = ParseAcpi (
- TRUE,
- 0,
- "MADT",
- Ptr,
- AcpiTableLength,
- PARSER_PARAMS (MadtParser)
- );
- InterruptContollerPtr = Ptr + Offset;
- while (Offset < AcpiTableLength) {
- // Parse Interrupt Controller Structure to obtain Length.
- ParseAcpi (
- FALSE,
- 0,
- NULL,
- InterruptContollerPtr,
- AcpiTableLength - Offset,
- PARSER_PARAMS (MadtInterruptControllerHeaderParser)
- );
- // Check if the values used to control the parsing logic have been
- // successfully read.
- if ((MadtInterruptControllerType == NULL) ||
- (MadtInterruptControllerLength == NULL))
- {
- IncrementErrorCount ();
- Print (
- L"ERROR: Insufficient remaining table buffer length to read the " \
- L"Interrupt Controller Structure header. Length = %d.\n",
- AcpiTableLength - Offset
- );
- return;
- }
- // Validate Interrupt Controller Structure length
- if ((*MadtInterruptControllerLength == 0) ||
- ((Offset + (*MadtInterruptControllerLength)) > AcpiTableLength))
- {
- IncrementErrorCount ();
- Print (
- L"ERROR: Invalid Interrupt Controller Structure length. " \
- L"Length = %d. Offset = %d. AcpiTableLength = %d.\n",
- *MadtInterruptControllerLength,
- Offset,
- AcpiTableLength
- );
- return;
- }
- switch (*MadtInterruptControllerType) {
- case EFI_ACPI_6_3_GIC:
- {
- ParseAcpi (
- TRUE,
- 2,
- "GICC",
- InterruptContollerPtr,
- *MadtInterruptControllerLength,
- PARSER_PARAMS (GicCParser)
- );
- break;
- }
- case EFI_ACPI_6_3_GICD:
- {
- if (++GICDCount > 1) {
- IncrementErrorCount ();
- Print (
- L"ERROR: Only one GICD must be present,"
- L" GICDCount = %d\n",
- GICDCount
- );
- }
- ParseAcpi (
- TRUE,
- 2,
- "GICD",
- InterruptContollerPtr,
- *MadtInterruptControllerLength,
- PARSER_PARAMS (GicDParser)
- );
- break;
- }
- case EFI_ACPI_6_3_GIC_MSI_FRAME:
- {
- ParseAcpi (
- TRUE,
- 2,
- "GIC MSI Frame",
- InterruptContollerPtr,
- *MadtInterruptControllerLength,
- PARSER_PARAMS (GicMSIFrameParser)
- );
- break;
- }
- case EFI_ACPI_6_3_GICR:
- {
- ParseAcpi (
- TRUE,
- 2,
- "GICR",
- InterruptContollerPtr,
- *MadtInterruptControllerLength,
- PARSER_PARAMS (GicRParser)
- );
- break;
- }
- case EFI_ACPI_6_3_GIC_ITS:
- {
- ParseAcpi (
- TRUE,
- 2,
- "GIC ITS",
- InterruptContollerPtr,
- *MadtInterruptControllerLength,
- PARSER_PARAMS (GicITSParser)
- );
- break;
- }
- case EFI_ACPI_6_3_IO_APIC:
- {
- ParseAcpi (
- TRUE,
- 2,
- "IO APIC",
- InterruptContollerPtr,
- *MadtInterruptControllerLength,
- PARSER_PARAMS (IoApic)
- );
- break;
- }
- case EFI_ACPI_6_3_INTERRUPT_SOURCE_OVERRIDE:
- {
- ParseAcpi (
- TRUE,
- 2,
- "INTERRUPT SOURCE OVERRIDE",
- InterruptContollerPtr,
- *MadtInterruptControllerLength,
- PARSER_PARAMS (InterruptSourceOverride)
- );
- break;
- }
- case EFI_ACPI_6_3_PROCESSOR_LOCAL_APIC:
- {
- ParseAcpi (
- TRUE,
- 2,
- "PROCESSOR LOCAL APIC",
- InterruptContollerPtr,
- *MadtInterruptControllerLength,
- PARSER_PARAMS (ProcessorLocalApic)
- );
- break;
- }
- case EFI_ACPI_6_3_PROCESSOR_LOCAL_X2APIC:
- {
- ParseAcpi (
- TRUE,
- 2,
- "PROCESSOR LOCAL X2APIC",
- InterruptContollerPtr,
- *MadtInterruptControllerLength,
- PARSER_PARAMS (ProcessorLocalX2Apic)
- );
- break;
- }
- case EFI_ACPI_6_3_LOCAL_X2APIC_NMI:
- {
- ParseAcpi (
- TRUE,
- 2,
- "LOCAL x2APIC NMI",
- InterruptContollerPtr,
- *MadtInterruptControllerLength,
- PARSER_PARAMS (LocalX2ApicNmi)
- );
- break;
- }
- default:
- {
- IncrementErrorCount ();
- Print (
- L"ERROR: Unknown Interrupt Controller Structure,"
- L" Type = %d, Length = %d\n",
- *MadtInterruptControllerType,
- *MadtInterruptControllerLength
- );
- }
- } // switch
- InterruptContollerPtr += *MadtInterruptControllerLength;
- Offset += *MadtInterruptControllerLength;
- } // while
- }
|