/** @file Copyright (c) 2017, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include #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 ); CHAR8 *mDmarTypeString[] = { "DRHD ", "RMRR ", "ATSR ", "RHSA ", "ANDD ", }; STATIC CHAR8 mUnknownStr[11]; CHAR8 * ShortNameOfDmarType( IN UINT16 Type ) { if (Type < sizeof(mDmarTypeString) / sizeof(mDmarTypeString[0])) { return mDmarTypeString[Type]; } else { AsciiSPrint(mUnknownStr, sizeof(mUnknownStr), "[%04x]", Type); return mUnknownStr; } } CHAR8 *mDmarDeviceTypeString[] = { "[00]", "PCI", "P2P", "IOAPIC", "HPET", "ACPI", }; CHAR8 * ShortNameOfDmarDeviceType( IN UINT8 Type ) { if (Type < sizeof(mDmarDeviceTypeString) / sizeof(mDmarDeviceTypeString[0])) { return mDmarDeviceTypeString[Type]; } else { AsciiSPrint(mUnknownStr, sizeof(mUnknownStr), "[%02x]", Type); return mUnknownStr; } } VOID DumpDmarDeviceScope ( IN EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDeviceScope, IN UINTN Size ) { EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *Device; EFI_ACPI_DMAR_PCI_PATH *PciPathScope; EFI_ACPI_DMAR_PCI_PATH *PciPath; UINTN PciPathSize; Device = DmarDeviceScope; while ((UINTN)Device < (UINTN)DmarDeviceScope + Size) { DEBUG ((DEBUG_INFO, " (")); DEBUG ((DEBUG_INFO, ShortNameOfDmarDeviceType(Device->Type))); DEBUG ((DEBUG_INFO, ": [0x%02x]", Device->Type)); DEBUG ((DEBUG_INFO, " EnumId=0x%02x", Device->EnumerationId)); DEBUG ((DEBUG_INFO, " Bus=0x%02x", Device->StartBusNumber)); PciPathScope = (EFI_ACPI_DMAR_PCI_PATH *)(DmarDeviceScope + 1); PciPathSize = Device->Length - sizeof(EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER); PciPath = PciPathScope; while ((UINTN)PciPath < (UINTN)PciPathScope + PciPathSize) { DEBUG ((DEBUG_INFO, " Pci=0x%02x/0x%02x", PciPath->Device, PciPath->Function)); PciPath ++; } DEBUG ((DEBUG_INFO, ")")); Device = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)Device + Device->Length); } } VOID DumpAcpiDmar ( IN EFI_ACPI_DMAR_HEADER *Dmar ) { EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarStructHeader; INTN DmarLen; EFI_ACPI_DMAR_DRHD_HEADER *Drhd; EFI_ACPI_DMAR_RMRR_HEADER *Rmrr; EFI_ACPI_DMAR_ATSR_HEADER *Atsr; EFI_ACPI_DMAR_RHSA_HEADER *Rhsa; EFI_ACPI_DMAR_ANDD_HEADER *Andd; DumpAcpiTableHeader (&Dmar->Header); DEBUG ((DEBUG_INFO, " ")); DEBUG ((DEBUG_INFO, " HostAddressWidth=0x%02x Flags=0x%02x\n", Dmar->HostAddressWidth, Dmar->Flags)); // // Sub table // DmarLen = Dmar->Header.Length - sizeof(EFI_ACPI_DMAR_HEADER); DmarStructHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)(Dmar + 1); while (DmarLen > 0) { switch (DmarStructHeader->Type) { case EFI_ACPI_DMAR_TYPE_DRHD: Drhd = (EFI_ACPI_DMAR_DRHD_HEADER *)DmarStructHeader; DEBUG ((DEBUG_INFO, " ")); DEBUG ((DEBUG_INFO, " ")); DEBUG ((DEBUG_INFO, ShortNameOfDmarType(DmarStructHeader->Type))); DEBUG ((DEBUG_INFO, ": [0x%04x]", DmarStructHeader->Type)); DEBUG ((DEBUG_INFO, " Flags=0x%02x", Drhd->Flags)); DEBUG ((DEBUG_INFO, " Segment=0x%04x", Drhd->SegmentNumber)); DEBUG ((DEBUG_INFO, " Register=0x%016lx", Drhd->RegisterBaseAddress)); if ((Drhd->Flags & EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL) != 0) { DEBUG ((DEBUG_INFO, " (INCLUDE_PCI_ALL)")); } else { DumpDmarDeviceScope ((EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)(Drhd + 1), Drhd->Header.Length - sizeof(EFI_ACPI_DMAR_DRHD_HEADER)); } DEBUG ((DEBUG_INFO, "\n")); break; case EFI_ACPI_DMAR_TYPE_RMRR: Rmrr = (EFI_ACPI_DMAR_RMRR_HEADER *)DmarStructHeader; DEBUG ((DEBUG_INFO, " ")); DEBUG ((DEBUG_INFO, " ")); DEBUG ((DEBUG_INFO, ShortNameOfDmarType(DmarStructHeader->Type))); DEBUG ((DEBUG_INFO, ": [0x%04x]", DmarStructHeader->Type)); DEBUG ((DEBUG_INFO, " Segment=0x%04x", Rmrr->SegmentNumber)); DEBUG ((DEBUG_INFO, " Reserved=(0x%016lx-0x%016lx)", Rmrr->ReservedMemoryRegionBaseAddress, Rmrr->ReservedMemoryRegionLimitAddress)); DumpDmarDeviceScope ((EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)(Rmrr + 1), Rmrr->Header.Length - sizeof(EFI_ACPI_DMAR_RMRR_HEADER)); DEBUG ((DEBUG_INFO, "\n")); break; case EFI_ACPI_DMAR_TYPE_ATSR: Atsr = (EFI_ACPI_DMAR_ATSR_HEADER *)DmarStructHeader; DEBUG ((DEBUG_INFO, " ")); DEBUG ((DEBUG_INFO, " ")); DEBUG ((DEBUG_INFO, ShortNameOfDmarType(DmarStructHeader->Type))); DEBUG ((DEBUG_INFO, ": [0x%04x]", DmarStructHeader->Type)); DEBUG ((DEBUG_INFO, " Flags=0x%02x", Atsr->Flags)); DEBUG ((DEBUG_INFO, " Segment=0x%04x", Atsr->SegmentNumber)); if ((Atsr->Flags & EFI_ACPI_DMAR_ATSR_FLAGS_ALL_PORTS) != 0) { DEBUG ((DEBUG_INFO, " (ALL_PORTS)")); } else { DumpDmarDeviceScope ((EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)(Atsr + 1), Atsr->Header.Length - sizeof(EFI_ACPI_DMAR_ATSR_HEADER)); } DEBUG ((DEBUG_INFO, "\n")); break; case EFI_ACPI_DMAR_TYPE_RHSA: Rhsa = (EFI_ACPI_DMAR_RHSA_HEADER *)DmarStructHeader; DEBUG ((DEBUG_INFO, " ")); DEBUG ((DEBUG_INFO, " ")); DEBUG ((DEBUG_INFO, ShortNameOfDmarType(DmarStructHeader->Type))); DEBUG ((DEBUG_INFO, ": [0x%04x]", DmarStructHeader->Type)); DEBUG ((DEBUG_INFO, " Register=0x%016lx", Rhsa->RegisterBaseAddress)); DEBUG ((DEBUG_INFO, " ProximityDomain=0x%08x", Rhsa->ProximityDomain)); DEBUG ((DEBUG_INFO, "\n")); break; case EFI_ACPI_DMAR_TYPE_ANDD: Andd = (EFI_ACPI_DMAR_ANDD_HEADER *)DmarStructHeader; DEBUG ((DEBUG_INFO, " ")); DEBUG ((DEBUG_INFO, " ")); DEBUG ((DEBUG_INFO, ShortNameOfDmarType(DmarStructHeader->Type))); DEBUG ((DEBUG_INFO, ": [0x%04x]", DmarStructHeader->Type)); DEBUG ((DEBUG_INFO, " DeviceNumber=0x%02x", Andd->AcpiDeviceNumber)); DEBUG ((DEBUG_INFO, " ObjectName=%a", Andd + 1)); DEBUG ((DEBUG_INFO, "\n")); break; default: DEBUG ((DEBUG_INFO, " ")); DEBUG ((DEBUG_INFO, " ")); DEBUG ((DEBUG_INFO, ShortNameOfDmarType(DmarStructHeader->Type))); DEBUG ((DEBUG_INFO, "\n")); break; } DmarStructHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINT8 *)DmarStructHeader + DmarStructHeader->Length); DmarLen -= DmarStructHeader->Length; } } EFI_STATUS CheckAcpiDmar ( IN EFI_ACPI_DMAR_HEADER *Dmar ) { EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarStructHeader; INTN DmarLen; EFI_ACPI_DMAR_DRHD_HEADER *Drhd; DmarLen = Dmar->Header.Length - sizeof(EFI_ACPI_DMAR_HEADER); DmarStructHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)(Dmar + 1); while (DmarLen > 0) { switch (DmarStructHeader->Type) { case EFI_ACPI_DMAR_TYPE_DRHD: Drhd = (EFI_ACPI_DMAR_DRHD_HEADER *)DmarStructHeader; if (!IsMmioExit (Drhd->RegisterBaseAddress, SIZE_4KB, TRUE)) { DEBUG ((DEBUG_ERROR, "DMAR.DRHD resource (0x%x) is not reported correctly.\n", Drhd->RegisterBaseAddress)); return EFI_NOT_STARTED; } break; default: break; } DmarStructHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINT8 *)DmarStructHeader + DmarStructHeader->Length); DmarLen -= DmarStructHeader->Length; } return EFI_SUCCESS; }