/** @file
|
|
Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
**/
|
|
#include <Uefi.h>
|
#include <PiDxe.h>
|
#include <Library/TestPointCheckLib.h>
|
#include <Library/TestPointLib.h>
|
#include <Library/DebugLib.h>
|
#include <Library/UefiLib.h>
|
#include <Library/PrintLib.h>
|
#include <Library/BaseMemoryLib.h>
|
#include <IndustryStandard/Acpi.h>
|
|
VOID
|
DumpCharArray (
|
IN CHAR8 *Ch,
|
IN UINTN Size
|
);
|
|
VOID
|
DumpAcpiTableHeader (
|
IN EFI_ACPI_DESCRIPTION_HEADER *Table
|
);
|
|
BOOLEAN
|
IsMmioExit (
|
IN EFI_PHYSICAL_ADDRESS BaseAddress,
|
IN UINT64 Length,
|
IN BOOLEAN CheckAllocated
|
);
|
|
typedef struct {
|
UINT8 Type;
|
UINT8 Length;
|
} APIC_STRUCT_HEADER;
|
|
CHAR8 *mMadtTypeString[] = {
|
"APIC ",
|
"IO_APIC ",
|
"INT_SRC_OR",
|
"NNI_SRC ",
|
"APIC_NMI ",
|
"APIC_OR ",
|
"IO_SAPIC ",
|
"SAPIC ",
|
"PL_INT_SRC",
|
"X2APIC ",
|
"X2APIC_NMI",
|
};
|
|
STATIC CHAR8 mUnknownStr[11];
|
|
CHAR8 *
|
ShortNameOfMadtType(
|
IN UINT8 Type
|
)
|
{
|
if (Type < sizeof(mMadtTypeString) / sizeof(mMadtTypeString[0])) {
|
return mMadtTypeString[Type];
|
} else {
|
AsciiSPrint(mUnknownStr, sizeof(mUnknownStr), "[%02x] ", Type);
|
return mUnknownStr;
|
}
|
}
|
|
VOID
|
DumpAcpiMadt (
|
IN EFI_ACPI_4_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER *Madt
|
)
|
{
|
APIC_STRUCT_HEADER *ApicStructHeader;
|
INTN MadtLen;
|
EFI_ACPI_4_0_PROCESSOR_LOCAL_APIC_STRUCTURE *ProcessorLocalApic;
|
EFI_ACPI_4_0_IO_APIC_STRUCTURE *IOApic;
|
EFI_ACPI_4_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE *InterruptSourceOverride;
|
EFI_ACPI_4_0_NON_MASKABLE_INTERRUPT_SOURCE_STRUCTURE *NonMaskableInterruptSource;
|
EFI_ACPI_4_0_LOCAL_APIC_NMI_STRUCTURE *LocalApicNMI;
|
EFI_ACPI_4_0_LOCAL_APIC_ADDRESS_OVERRIDE_STRUCTURE *LocalApicAddressOverride;
|
EFI_ACPI_4_0_IO_SAPIC_STRUCTURE *IOSapic;
|
EFI_ACPI_4_0_PROCESSOR_LOCAL_SAPIC_STRUCTURE *ProcessorLocalSapic;
|
EFI_ACPI_4_0_PLATFORM_INTERRUPT_SOURCES_STRUCTURE *PlatformInterruptSource;
|
EFI_ACPI_4_0_PROCESSOR_LOCAL_X2APIC_STRUCTURE *ProcessorLocalX2Apic;
|
EFI_ACPI_4_0_LOCAL_X2APIC_NMI_STRUCTURE *LocalX2ApicNmi;
|
|
DumpAcpiTableHeader (&Madt->Header);
|
DEBUG ((DEBUG_INFO, " "));
|
DEBUG ((DEBUG_INFO, " LocalApicAddress=0x%08x\n", Madt->LocalApicAddress));
|
|
//
|
// Sub table
|
//
|
MadtLen = Madt->Header.Length - sizeof(EFI_ACPI_4_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER);
|
ApicStructHeader = (APIC_STRUCT_HEADER *)(Madt + 1);
|
while (MadtLen > 0) {
|
switch (ApicStructHeader->Type) {
|
case EFI_ACPI_4_0_PROCESSOR_LOCAL_APIC:
|
ProcessorLocalApic = (EFI_ACPI_4_0_PROCESSOR_LOCAL_APIC_STRUCTURE *)ApicStructHeader;
|
DEBUG ((DEBUG_INFO, " "));
|
DEBUG ((DEBUG_INFO, " "));
|
DEBUG ((DEBUG_INFO, ShortNameOfMadtType(ApicStructHeader->Type)));
|
DEBUG ((DEBUG_INFO, ": [0x%02x]", ApicStructHeader->Type));
|
DEBUG ((DEBUG_INFO, " ID=0x%02x", ProcessorLocalApic->AcpiProcessorId));
|
DEBUG ((DEBUG_INFO, " ApicId=0x%02x", ProcessorLocalApic->ApicId));
|
if ((ProcessorLocalApic->Flags & EFI_ACPI_4_0_LOCAL_APIC_ENABLED) != 0) {
|
DEBUG ((DEBUG_INFO, " (Enabled)"));
|
}
|
DEBUG ((DEBUG_INFO, "\n"));
|
break;
|
case EFI_ACPI_4_0_IO_APIC:
|
IOApic = (EFI_ACPI_4_0_IO_APIC_STRUCTURE *)ApicStructHeader;
|
DEBUG ((DEBUG_INFO, " "));
|
DEBUG ((DEBUG_INFO, " "));
|
DEBUG ((DEBUG_INFO, ShortNameOfMadtType(ApicStructHeader->Type)));
|
DEBUG ((DEBUG_INFO, ": [0x%02x]", ApicStructHeader->Type));
|
DEBUG ((DEBUG_INFO, " IoApicId=0x%02x", IOApic->IoApicId));
|
DEBUG ((DEBUG_INFO, " Address=0x%08x", IOApic->IoApicAddress));
|
DEBUG ((DEBUG_INFO, " InterruptBase=0x%08x", IOApic->GlobalSystemInterruptBase));
|
DEBUG ((DEBUG_INFO, "\n"));
|
break;
|
case EFI_ACPI_4_0_INTERRUPT_SOURCE_OVERRIDE:
|
InterruptSourceOverride = (EFI_ACPI_4_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE *)ApicStructHeader;
|
DEBUG ((DEBUG_INFO, " "));
|
DEBUG ((DEBUG_INFO, " "));
|
DEBUG ((DEBUG_INFO, ShortNameOfMadtType(ApicStructHeader->Type)));
|
DEBUG ((DEBUG_INFO, ": [0x%02x]", ApicStructHeader->Type));
|
DEBUG ((DEBUG_INFO, " Bus=0x%02x", InterruptSourceOverride->Bus));
|
DEBUG ((DEBUG_INFO, " Source=0x%02x", InterruptSourceOverride->Source));
|
DEBUG ((DEBUG_INFO, " Interrupt=0x%08x", InterruptSourceOverride->GlobalSystemInterrupt));
|
DEBUG ((DEBUG_INFO, " Flags=0x%04x", InterruptSourceOverride->Flags));
|
DEBUG ((DEBUG_INFO, "\n"));
|
break;
|
case EFI_ACPI_4_0_NON_MASKABLE_INTERRUPT_SOURCE:
|
NonMaskableInterruptSource = (EFI_ACPI_4_0_NON_MASKABLE_INTERRUPT_SOURCE_STRUCTURE *)ApicStructHeader;
|
DEBUG ((DEBUG_INFO, " "));
|
DEBUG ((DEBUG_INFO, " "));
|
DEBUG ((DEBUG_INFO, ShortNameOfMadtType(ApicStructHeader->Type)));
|
DEBUG ((DEBUG_INFO, ": [0x%02x]", ApicStructHeader->Type));
|
DEBUG ((DEBUG_INFO, " Interrupt=0x%08x", NonMaskableInterruptSource->GlobalSystemInterrupt));
|
DEBUG ((DEBUG_INFO, " Flags=0x%04x", NonMaskableInterruptSource->Flags));
|
DEBUG ((DEBUG_INFO, "\n"));
|
break;
|
case EFI_ACPI_4_0_LOCAL_APIC_NMI:
|
LocalApicNMI = (EFI_ACPI_4_0_LOCAL_APIC_NMI_STRUCTURE *)ApicStructHeader;
|
DEBUG ((DEBUG_INFO, " "));
|
DEBUG ((DEBUG_INFO, " "));
|
DEBUG ((DEBUG_INFO, ShortNameOfMadtType(ApicStructHeader->Type)));
|
DEBUG ((DEBUG_INFO, ": [0x%02x]", ApicStructHeader->Type));
|
DEBUG ((DEBUG_INFO, " ID=0x%02x", LocalApicNMI->AcpiProcessorId));
|
DEBUG ((DEBUG_INFO, " Lint=0x%02x", LocalApicNMI->LocalApicLint));
|
DEBUG ((DEBUG_INFO, " Flags=0x%04x", LocalApicNMI->Flags));
|
DEBUG ((DEBUG_INFO, "\n"));
|
break;
|
case EFI_ACPI_4_0_LOCAL_APIC_ADDRESS_OVERRIDE:
|
LocalApicAddressOverride = (EFI_ACPI_4_0_LOCAL_APIC_ADDRESS_OVERRIDE_STRUCTURE *)ApicStructHeader;
|
DEBUG ((DEBUG_INFO, " "));
|
DEBUG ((DEBUG_INFO, " "));
|
DEBUG ((DEBUG_INFO, ShortNameOfMadtType(ApicStructHeader->Type)));
|
DEBUG ((DEBUG_INFO, ": [0x%02x]", ApicStructHeader->Type));
|
DEBUG ((DEBUG_INFO, " LocalApicAddress=0x%016lx", LocalApicAddressOverride->LocalApicAddress));
|
DEBUG ((DEBUG_INFO, "\n"));
|
break;
|
case EFI_ACPI_4_0_IO_SAPIC:
|
IOSapic = (EFI_ACPI_4_0_IO_SAPIC_STRUCTURE *)ApicStructHeader;
|
DEBUG ((DEBUG_INFO, " "));
|
DEBUG ((DEBUG_INFO, " "));
|
DEBUG ((DEBUG_INFO, ShortNameOfMadtType(ApicStructHeader->Type)));
|
DEBUG ((DEBUG_INFO, ": [0x%02x]", ApicStructHeader->Type));
|
DEBUG ((DEBUG_INFO, " IoApicId=0x%02x", IOSapic->IoApicId));
|
DEBUG ((DEBUG_INFO, " InterruptBase=0x%08x", IOSapic->GlobalSystemInterruptBase));
|
DEBUG ((DEBUG_INFO, " IoSapicAddress=0x%016lx", IOSapic->IoSapicAddress));
|
DEBUG ((DEBUG_INFO, "\n"));
|
break;
|
case EFI_ACPI_4_0_LOCAL_SAPIC:
|
ProcessorLocalSapic = (EFI_ACPI_4_0_PROCESSOR_LOCAL_SAPIC_STRUCTURE *)ApicStructHeader;
|
DEBUG ((DEBUG_INFO, " "));
|
DEBUG ((DEBUG_INFO, " "));
|
DEBUG ((DEBUG_INFO, ShortNameOfMadtType(ApicStructHeader->Type)));
|
DEBUG ((DEBUG_INFO, ": [0x%02x]", ApicStructHeader->Type));
|
DEBUG ((DEBUG_INFO, " ID=0x%02x", ProcessorLocalSapic->AcpiProcessorId));
|
DEBUG ((DEBUG_INFO, " LocalSapicId=0x%02x", ProcessorLocalSapic->LocalSapicId));
|
DEBUG ((DEBUG_INFO, " LocalSapicEid=0x%02x", ProcessorLocalSapic->LocalSapicEid));
|
DEBUG ((DEBUG_INFO, " UID=0x%08x", ProcessorLocalSapic->ACPIProcessorUIDValue));
|
if ((ProcessorLocalSapic->Flags & EFI_ACPI_5_0_LOCAL_APIC_ENABLED) != 0) {
|
DEBUG ((DEBUG_INFO, " (Enabled)"));
|
}
|
DEBUG ((DEBUG_INFO, "\n"));
|
break;
|
case EFI_ACPI_4_0_PLATFORM_INTERRUPT_SOURCES:
|
PlatformInterruptSource = (EFI_ACPI_4_0_PLATFORM_INTERRUPT_SOURCES_STRUCTURE *)ApicStructHeader;
|
DEBUG ((DEBUG_INFO, " "));
|
DEBUG ((DEBUG_INFO, " "));
|
DEBUG ((DEBUG_INFO, ShortNameOfMadtType(ApicStructHeader->Type)));
|
DEBUG ((DEBUG_INFO, ": [0x%02x]", ApicStructHeader->Type));
|
DEBUG ((DEBUG_INFO, " Type=0x%02x", PlatformInterruptSource->InterruptType));
|
DEBUG ((DEBUG_INFO, " ID=0x%02x", PlatformInterruptSource->ProcessorId));
|
DEBUG ((DEBUG_INFO, " EID=0x%02x", PlatformInterruptSource->ProcessorEid));
|
DEBUG ((DEBUG_INFO, " IoSapicVector=0x%02x", PlatformInterruptSource->IoSapicVector));
|
DEBUG ((DEBUG_INFO, " Interrupt=0x%08x", PlatformInterruptSource->GlobalSystemInterrupt));
|
DEBUG ((DEBUG_INFO, " SourceFlags=0x%08x", PlatformInterruptSource->PlatformInterruptSourceFlags));
|
DEBUG ((DEBUG_INFO, " Flags=0x%04x", PlatformInterruptSource->Flags));
|
DEBUG ((DEBUG_INFO, "\n"));
|
break;
|
case EFI_ACPI_4_0_PROCESSOR_LOCAL_X2APIC:
|
ProcessorLocalX2Apic = (EFI_ACPI_4_0_PROCESSOR_LOCAL_X2APIC_STRUCTURE *)ApicStructHeader;
|
DEBUG ((DEBUG_INFO, " "));
|
DEBUG ((DEBUG_INFO, " "));
|
DEBUG ((DEBUG_INFO, ShortNameOfMadtType(ApicStructHeader->Type)));
|
DEBUG ((DEBUG_INFO, ": [0x%02x]", ApicStructHeader->Type));
|
DEBUG ((DEBUG_INFO, " X2ApicId=0x%08x", ProcessorLocalX2Apic->X2ApicId));
|
DEBUG ((DEBUG_INFO, " UID=0x%08x", ProcessorLocalX2Apic->AcpiProcessorUid));
|
if ((ProcessorLocalX2Apic->Flags & EFI_ACPI_5_0_LOCAL_APIC_ENABLED) != 0) {
|
DEBUG ((DEBUG_INFO, " (Enabled)"));
|
}
|
DEBUG ((DEBUG_INFO, "\n"));
|
break;
|
case EFI_ACPI_4_0_LOCAL_X2APIC_NMI:
|
LocalX2ApicNmi = (EFI_ACPI_4_0_LOCAL_X2APIC_NMI_STRUCTURE *)ApicStructHeader;
|
DEBUG ((DEBUG_INFO, " "));
|
DEBUG ((DEBUG_INFO, " "));
|
DEBUG ((DEBUG_INFO, ShortNameOfMadtType(ApicStructHeader->Type)));
|
DEBUG ((DEBUG_INFO, ": [0x%02x]", ApicStructHeader->Type));
|
DEBUG ((DEBUG_INFO, " UID=0x%08x", LocalX2ApicNmi->AcpiProcessorUid));
|
DEBUG ((DEBUG_INFO, " Lint=0x%02x", LocalX2ApicNmi->LocalX2ApicLint));
|
DEBUG ((DEBUG_INFO, " Flags=0x%04x", LocalX2ApicNmi->Flags));
|
DEBUG ((DEBUG_INFO, "\n"));
|
break;
|
default:
|
DEBUG ((DEBUG_INFO, " "));
|
DEBUG ((DEBUG_INFO, " "));
|
DEBUG ((DEBUG_INFO, ShortNameOfMadtType(ApicStructHeader->Type)));
|
DEBUG ((DEBUG_INFO, "\n"));
|
break;
|
}
|
ApicStructHeader = (APIC_STRUCT_HEADER *)((UINT8 *)ApicStructHeader + ApicStructHeader->Length);
|
MadtLen -= ApicStructHeader->Length;
|
}
|
}
|
|
EFI_STATUS
|
CheckAcpiMadt (
|
IN EFI_ACPI_4_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER *Madt
|
)
|
{
|
|
APIC_STRUCT_HEADER *ApicStructHeader;
|
INTN MadtLen;
|
EFI_ACPI_4_0_IO_APIC_STRUCTURE *IOApic;
|
EFI_ACPI_4_0_LOCAL_APIC_ADDRESS_OVERRIDE_STRUCTURE *LocalApicAddressOverride;
|
EFI_ACPI_4_0_IO_SAPIC_STRUCTURE *IOSapic;
|
#if 0
|
EFI_ACPI_4_0_PROCESSOR_LOCAL_APIC_STRUCTURE *ProcessorLocalApic;
|
EFI_ACPI_4_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE *InterruptSourceOverride;
|
EFI_ACPI_4_0_NON_MASKABLE_INTERRUPT_SOURCE_STRUCTURE *NonMaskableInterruptSource;
|
EFI_ACPI_4_0_LOCAL_APIC_NMI_STRUCTURE *LocalApicNMI;
|
EFI_ACPI_4_0_PROCESSOR_LOCAL_SAPIC_STRUCTURE *ProcessorLocalSapic;
|
EFI_ACPI_4_0_PLATFORM_INTERRUPT_SOURCES_STRUCTURE *PlatformInterruptSource;
|
EFI_ACPI_4_0_PROCESSOR_LOCAL_X2APIC_STRUCTURE *ProcessorLocalX2Apic;
|
EFI_ACPI_4_0_LOCAL_X2APIC_NMI_STRUCTURE *LocalX2ApicNmi;
|
#endif
|
|
if (!IsMmioExit (Madt->LocalApicAddress, SIZE_4KB, TRUE)) {
|
DEBUG ((DEBUG_ERROR, "MADT resource (0x%x) is not reported correctly.\n", Madt->LocalApicAddress));
|
return EFI_NOT_STARTED;
|
}
|
|
//
|
// Sub table
|
//
|
MadtLen = Madt->Header.Length - sizeof(EFI_ACPI_4_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER);
|
ApicStructHeader = (APIC_STRUCT_HEADER *)(Madt + 1);
|
while (MadtLen > 0) {
|
switch (ApicStructHeader->Type) {
|
case EFI_ACPI_4_0_IO_APIC:
|
IOApic = (EFI_ACPI_4_0_IO_APIC_STRUCTURE *)ApicStructHeader;
|
if (!IsMmioExit (IOApic->IoApicAddress, SIZE_4KB, TRUE)) {
|
DEBUG ((DEBUG_ERROR, "MADT.IOAPIC resource (0x%x) is not reported correctly.\n", IOApic->IoApicAddress));
|
return EFI_NOT_STARTED;
|
}
|
break;
|
case EFI_ACPI_4_0_LOCAL_APIC_ADDRESS_OVERRIDE:
|
LocalApicAddressOverride = (EFI_ACPI_4_0_LOCAL_APIC_ADDRESS_OVERRIDE_STRUCTURE *)ApicStructHeader;
|
if (!IsMmioExit (LocalApicAddressOverride->LocalApicAddress, SIZE_4KB, TRUE)) {
|
DEBUG ((DEBUG_ERROR, "MADT.LocalApicOverride resource (0x%x) is not reported correctly.\n", LocalApicAddressOverride->LocalApicAddress));
|
return EFI_NOT_STARTED;
|
}
|
break;
|
case EFI_ACPI_4_0_IO_SAPIC:
|
IOSapic = (EFI_ACPI_4_0_IO_SAPIC_STRUCTURE *)ApicStructHeader;
|
if (!IsMmioExit (IOSapic->IoSapicAddress, SIZE_4KB, TRUE)) {
|
DEBUG ((DEBUG_ERROR, "MADT.IOSAPIC resource (0x%x) is not reported correctly.\n", IOSapic->IoSapicAddress));
|
return EFI_NOT_STARTED;
|
}
|
break;
|
#if 0
|
case EFI_ACPI_4_0_PROCESSOR_LOCAL_APIC:
|
ProcessorLocalApic = (EFI_ACPI_4_0_PROCESSOR_LOCAL_APIC_STRUCTURE *)ApicStructHeader;
|
break;
|
case EFI_ACPI_4_0_INTERRUPT_SOURCE_OVERRIDE:
|
InterruptSourceOverride = (EFI_ACPI_4_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE *)ApicStructHeader;
|
break;
|
case EFI_ACPI_4_0_NON_MASKABLE_INTERRUPT_SOURCE:
|
NonMaskableInterruptSource = (EFI_ACPI_4_0_NON_MASKABLE_INTERRUPT_SOURCE_STRUCTURE *)ApicStructHeader;
|
break;
|
case EFI_ACPI_4_0_LOCAL_APIC_NMI:
|
LocalApicNMI = (EFI_ACPI_4_0_LOCAL_APIC_NMI_STRUCTURE *)ApicStructHeader;
|
break;
|
case EFI_ACPI_4_0_LOCAL_SAPIC:
|
ProcessorLocalSapic = (EFI_ACPI_4_0_PROCESSOR_LOCAL_SAPIC_STRUCTURE *)ApicStructHeader;
|
break;
|
case EFI_ACPI_4_0_PLATFORM_INTERRUPT_SOURCES:
|
PlatformInterruptSource = (EFI_ACPI_4_0_PLATFORM_INTERRUPT_SOURCES_STRUCTURE *)ApicStructHeader;
|
break;
|
case EFI_ACPI_4_0_PROCESSOR_LOCAL_X2APIC:
|
ProcessorLocalX2Apic = (EFI_ACPI_4_0_PROCESSOR_LOCAL_X2APIC_STRUCTURE *)ApicStructHeader;
|
break;
|
case EFI_ACPI_4_0_LOCAL_X2APIC_NMI:
|
LocalX2ApicNmi = (EFI_ACPI_4_0_LOCAL_X2APIC_NMI_STRUCTURE *)ApicStructHeader;
|
break;
|
#endif
|
default:
|
break;
|
}
|
ApicStructHeader = (APIC_STRUCT_HEADER *)((UINT8 *)ApicStructHeader + ApicStructHeader->Length);
|
MadtLen -= ApicStructHeader->Length;
|
}
|
return EFI_SUCCESS;
|
}
|