/** @file Copyright (c) 2017, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License that accompanies this distribution. The full text of the license may be found at http://opensource.org/licenses/bsd-license.php. THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. **/ #include #include #include #include #include #include #include #include #include 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_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; 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_PROCESSOR_LOCAL_APIC: ProcessorLocalApic = (EFI_ACPI_4_0_PROCESSOR_LOCAL_APIC_STRUCTURE *)ApicStructHeader; break; 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_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_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; 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; default: break; } ApicStructHeader = (APIC_STRUCT_HEADER *)((UINT8 *)ApicStructHeader + ApicStructHeader->Length); MadtLen -= ApicStructHeader->Length; } return EFI_SUCCESS; }