--- /dev/null
+/** @file\r
+\r
+ Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php.\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "DmaProtection.h"\r
+\r
+#pragma pack(1)\r
+\r
+typedef struct {\r
+ EFI_ACPI_DESCRIPTION_HEADER Header;\r
+ UINT32 Entry;\r
+} RSDT_TABLE;\r
+\r
+typedef struct {\r
+ EFI_ACPI_DESCRIPTION_HEADER Header;\r
+ UINT64 Entry;\r
+} XSDT_TABLE;\r
+\r
+#pragma pack()\r
+\r
+EFI_ACPI_DMAR_HEADER *mAcpiDmarTable;\r
+\r
+/**\r
+ Dump DMAR DeviceScopeEntry.\r
+\r
+ @param[in] DmarDeviceScopeEntry DMAR DeviceScopeEntry\r
+**/\r
+VOID\r
+DumpDmarDeviceScopeEntry (\r
+ IN EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDeviceScopeEntry\r
+ )\r
+{\r
+ UINTN PciPathNumber;\r
+ UINTN PciPathIndex;\r
+ EFI_ACPI_DMAR_PCI_PATH *PciPath;\r
+\r
+ if (DmarDeviceScopeEntry == NULL) {\r
+ return;\r
+ }\r
+\r
+ DEBUG ((DEBUG_INFO,\r
+ " *************************************************************************\n"\r
+ " * DMA-Remapping Device Scope Entry Structure *\n"\r
+ " *************************************************************************\n"\r
+ ));\r
+ DEBUG ((DEBUG_INFO,\r
+ (sizeof(UINTN) == sizeof(UINT64)) ?\r
+ " DMAR Device Scope Entry address ...................... 0x%016lx\n" :\r
+ " DMAR Device Scope Entry address ...................... 0x%08x\n",\r
+ DmarDeviceScopeEntry\r
+ ));\r
+ DEBUG ((DEBUG_INFO,\r
+ " Device Scope Entry Type ............................ 0x%02x\n",\r
+ DmarDeviceScopeEntry->Type\r
+ ));\r
+ switch (DmarDeviceScopeEntry->Type) {\r
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT:\r
+ DEBUG ((DEBUG_INFO,\r
+ " PCI Endpoint Device\n"\r
+ ));\r
+ break;\r
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE:\r
+ DEBUG ((DEBUG_INFO,\r
+ " PCI Sub-hierachy\n"\r
+ ));\r
+ break;\r
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_IOAPIC:\r
+ DEBUG ((DEBUG_INFO,\r
+ " IOAPIC\n"\r
+ ));\r
+ break;\r
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_MSI_CAPABLE_HPET:\r
+ DEBUG ((DEBUG_INFO,\r
+ " MSI Capable HPET\n"\r
+ ));\r
+ break;\r
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_ACPI_NAMESPACE_DEVICE:\r
+ DEBUG ((DEBUG_INFO,\r
+ " ACPI Namespace Device\n"\r
+ ));\r
+ break;\r
+ default:\r
+ break;\r
+ }\r
+ DEBUG ((DEBUG_INFO,\r
+ " Length ............................................. 0x%02x\n",\r
+ DmarDeviceScopeEntry->Length\r
+ ));\r
+ DEBUG ((DEBUG_INFO,\r
+ " Enumeration ID ..................................... 0x%02x\n",\r
+ DmarDeviceScopeEntry->EnumerationId\r
+ ));\r
+ DEBUG ((DEBUG_INFO,\r
+ " Starting Bus Number ................................ 0x%02x\n",\r
+ DmarDeviceScopeEntry->StartBusNumber\r
+ ));\r
+\r
+ PciPathNumber = (DmarDeviceScopeEntry->Length - sizeof(EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER)) / sizeof(EFI_ACPI_DMAR_PCI_PATH);\r
+ PciPath = (EFI_ACPI_DMAR_PCI_PATH *)(DmarDeviceScopeEntry + 1);\r
+ for (PciPathIndex = 0; PciPathIndex < PciPathNumber; PciPathIndex++) {\r
+ DEBUG ((DEBUG_INFO,\r
+ " Device ............................................. 0x%02x\n",\r
+ PciPath[PciPathIndex].Device\r
+ ));\r
+ DEBUG ((DEBUG_INFO,\r
+ " Function ........................................... 0x%02x\n",\r
+ PciPath[PciPathIndex].Function\r
+ ));\r
+ }\r
+\r
+ DEBUG ((DEBUG_INFO,\r
+ " *************************************************************************\n\n"\r
+ ));\r
+\r
+ return;\r
+}\r
+\r
+/**\r
+ Dump DMAR ANDD table.\r
+\r
+ @param[in] Andd DMAR ANDD table\r
+**/\r
+VOID\r
+DumpDmarAndd (\r
+ IN EFI_ACPI_DMAR_ANDD_HEADER *Andd\r
+ )\r
+{\r
+ if (Andd == NULL) {\r
+ return;\r
+ }\r
+\r
+ DEBUG ((DEBUG_INFO,\r
+ " ***************************************************************************\n"\r
+ " * ACPI Name-space Device Declaration Structure *\n"\r
+ " ***************************************************************************\n"\r
+ ));\r
+ DEBUG ((DEBUG_INFO,\r
+ (sizeof(UINTN) == sizeof(UINT64)) ?\r
+ " ANDD address ........................................... 0x%016lx\n" :\r
+ " ANDD address ........................................... 0x%08x\n",\r
+ Andd\r
+ ));\r
+ DEBUG ((DEBUG_INFO,\r
+ " Type ................................................. 0x%04x\n",\r
+ Andd->Header.Type\r
+ ));\r
+ DEBUG ((DEBUG_INFO,\r
+ " Length ............................................... 0x%04x\n",\r
+ Andd->Header.Length\r
+ ));\r
+ DEBUG ((DEBUG_INFO,\r
+ " ACPI Device Number ................................... 0x%02x\n",\r
+ Andd->AcpiDeviceNumber\r
+ ));\r
+ DEBUG ((DEBUG_INFO,\r
+ " ACPI Object Name ..................................... '%a'\n",\r
+ (Andd + 1)\r
+ ));\r
+\r
+ DEBUG ((DEBUG_INFO,\r
+ " ***************************************************************************\n\n"\r
+ ));\r
+\r
+ return;\r
+}\r
+\r
+/**\r
+ Dump DMAR RHSA table.\r
+\r
+ @param[in] Rhsa DMAR RHSA table\r
+**/\r
+VOID\r
+DumpDmarRhsa (\r
+ IN EFI_ACPI_DMAR_RHSA_HEADER *Rhsa\r
+ )\r
+{\r
+ if (Rhsa == NULL) {\r
+ return;\r
+ }\r
+\r
+ DEBUG ((DEBUG_INFO,\r
+ " ***************************************************************************\n"\r
+ " * Remapping Hardware Status Affinity Structure *\n"\r
+ " ***************************************************************************\n"\r
+ ));\r
+ DEBUG ((DEBUG_INFO,\r
+ (sizeof(UINTN) == sizeof(UINT64)) ?\r
+ " RHSA address ........................................... 0x%016lx\n" :\r
+ " RHSA address ........................................... 0x%08x\n",\r
+ Rhsa\r
+ ));\r
+ DEBUG ((DEBUG_INFO,\r
+ " Type ................................................. 0x%04x\n",\r
+ Rhsa->Header.Type\r
+ ));\r
+ DEBUG ((DEBUG_INFO,\r
+ " Length ............................................... 0x%04x\n",\r
+ Rhsa->Header.Length\r
+ ));\r
+ DEBUG ((DEBUG_INFO,\r
+ " Register Base Address ................................ 0x%016lx\n",\r
+ Rhsa->RegisterBaseAddress\r
+ ));\r
+ DEBUG ((DEBUG_INFO,\r
+ " Proximity Domain ..................................... 0x%08x\n",\r
+ Rhsa->ProximityDomain\r
+ ));\r
+\r
+ DEBUG ((DEBUG_INFO,\r
+ " ***************************************************************************\n\n"\r
+ ));\r
+\r
+ return;\r
+}\r
+\r
+/**\r
+ Dump DMAR ATSR table.\r
+\r
+ @param[in] Atsr DMAR ATSR table\r
+**/\r
+VOID\r
+DumpDmarAtsr (\r
+ IN EFI_ACPI_DMAR_ATSR_HEADER *Atsr\r
+ )\r
+{\r
+ EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDeviceScopeEntry;\r
+ INTN AtsrLen;\r
+\r
+ if (Atsr == NULL) {\r
+ return;\r
+ }\r
+\r
+ DEBUG ((DEBUG_INFO,\r
+ " ***************************************************************************\n"\r
+ " * Root Port ATS Capability Reporting Structure *\n"\r
+ " ***************************************************************************\n"\r
+ ));\r
+ DEBUG ((DEBUG_INFO,\r
+ (sizeof(UINTN) == sizeof(UINT64)) ?\r
+ " ATSR address ........................................... 0x%016lx\n" :\r
+ " ATSR address ........................................... 0x%08x\n",\r
+ Atsr\r
+ ));\r
+ DEBUG ((DEBUG_INFO,\r
+ " Type ................................................. 0x%04x\n",\r
+ Atsr->Header.Type\r
+ ));\r
+ DEBUG ((DEBUG_INFO,\r
+ " Length ............................................... 0x%04x\n",\r
+ Atsr->Header.Length\r
+ ));\r
+ DEBUG ((DEBUG_INFO,\r
+ " Flags ................................................ 0x%02x\n",\r
+ Atsr->Flags\r
+ ));\r
+ DEBUG ((DEBUG_INFO,\r
+ " ALL_PORTS .......................................... 0x%02x\n",\r
+ Atsr->Flags & EFI_ACPI_DMAR_ATSR_FLAGS_ALL_PORTS\r
+ ));\r
+ DEBUG ((DEBUG_INFO,\r
+ " Segment Number ....................................... 0x%04x\n",\r
+ Atsr->SegmentNumber\r
+ ));\r
+\r
+ AtsrLen = Atsr->Header.Length - sizeof(EFI_ACPI_DMAR_ATSR_HEADER);\r
+ DmarDeviceScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)(Atsr + 1);\r
+ while (AtsrLen > 0) {\r
+ DumpDmarDeviceScopeEntry (DmarDeviceScopeEntry);\r
+ AtsrLen -= DmarDeviceScopeEntry->Length;\r
+ DmarDeviceScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)DmarDeviceScopeEntry + DmarDeviceScopeEntry->Length);\r
+ }\r
+\r
+ DEBUG ((DEBUG_INFO,\r
+ " ***************************************************************************\n\n"\r
+ ));\r
+\r
+ return;\r
+}\r
+\r
+/**\r
+ Dump DMAR RMRR table.\r
+\r
+ @param[in] Rmrr DMAR RMRR table\r
+**/\r
+VOID\r
+DumpDmarRmrr (\r
+ IN EFI_ACPI_DMAR_RMRR_HEADER *Rmrr\r
+ )\r
+{\r
+ EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDeviceScopeEntry;\r
+ INTN RmrrLen;\r
+\r
+ if (Rmrr == NULL) {\r
+ return;\r
+ }\r
+\r
+ DEBUG ((DEBUG_INFO,\r
+ " ***************************************************************************\n"\r
+ " * Reserved Memory Region Reporting Structure *\n"\r
+ " ***************************************************************************\n"\r
+ ));\r
+ DEBUG ((DEBUG_INFO,\r
+ (sizeof(UINTN) == sizeof(UINT64)) ?\r
+ " RMRR address ........................................... 0x%016lx\n" :\r
+ " RMRR address ........................................... 0x%08x\n",\r
+ Rmrr\r
+ ));\r
+ DEBUG ((DEBUG_INFO,\r
+ " Type ................................................. 0x%04x\n",\r
+ Rmrr->Header.Type\r
+ ));\r
+ DEBUG ((DEBUG_INFO,\r
+ " Length ............................................... 0x%04x\n",\r
+ Rmrr->Header.Length\r
+ ));\r
+ DEBUG ((DEBUG_INFO,\r
+ " Segment Number ....................................... 0x%04x\n",\r
+ Rmrr->SegmentNumber\r
+ ));\r
+ DEBUG ((DEBUG_INFO,\r
+ " Reserved Memory Region Base Address .................. 0x%016lx\n",\r
+ Rmrr->ReservedMemoryRegionBaseAddress\r
+ ));\r
+ DEBUG ((DEBUG_INFO,\r
+ " Reserved Memory Region Limit Address ................. 0x%016lx\n",\r
+ Rmrr->ReservedMemoryRegionLimitAddress\r
+ ));\r
+\r
+ RmrrLen = Rmrr->Header.Length - sizeof(EFI_ACPI_DMAR_RMRR_HEADER);\r
+ DmarDeviceScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)(Rmrr + 1);\r
+ while (RmrrLen > 0) {\r
+ DumpDmarDeviceScopeEntry (DmarDeviceScopeEntry);\r
+ RmrrLen -= DmarDeviceScopeEntry->Length;\r
+ DmarDeviceScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)DmarDeviceScopeEntry + DmarDeviceScopeEntry->Length);\r
+ }\r
+\r
+ DEBUG ((DEBUG_INFO,\r
+ " ***************************************************************************\n\n"\r
+ ));\r
+\r
+ return;\r
+}\r
+\r
+/**\r
+ Dump DMAR DRHD table.\r
+\r
+ @param[in] Drhd DMAR DRHD table\r
+**/\r
+VOID\r
+DumpDmarDrhd (\r
+ IN EFI_ACPI_DMAR_DRHD_HEADER *Drhd\r
+ )\r
+{\r
+ EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDeviceScopeEntry;\r
+ INTN DrhdLen;\r
+\r
+ if (Drhd == NULL) {\r
+ return;\r
+ }\r
+\r
+ DEBUG ((DEBUG_INFO,\r
+ " ***************************************************************************\n"\r
+ " * DMA-Remapping Hardware Definition Structure *\n"\r
+ " ***************************************************************************\n"\r
+ ));\r
+ DEBUG ((DEBUG_INFO,\r
+ (sizeof(UINTN) == sizeof(UINT64)) ?\r
+ " DRHD address ........................................... 0x%016lx\n" :\r
+ " DRHD address ........................................... 0x%08x\n",\r
+ Drhd\r
+ ));\r
+ DEBUG ((DEBUG_INFO,\r
+ " Type ................................................. 0x%04x\n",\r
+ Drhd->Header.Type\r
+ ));\r
+ DEBUG ((DEBUG_INFO,\r
+ " Length ............................................... 0x%04x\n",\r
+ Drhd->Header.Length\r
+ ));\r
+ DEBUG ((DEBUG_INFO,\r
+ " Flags ................................................ 0x%02x\n",\r
+ Drhd->Flags\r
+ ));\r
+ DEBUG ((DEBUG_INFO,\r
+ " INCLUDE_PCI_ALL .................................... 0x%02x\n",\r
+ Drhd->Flags & EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL\r
+ ));\r
+ DEBUG ((DEBUG_INFO,\r
+ " Segment Number ....................................... 0x%04x\n",\r
+ Drhd->SegmentNumber\r
+ ));\r
+ DEBUG ((DEBUG_INFO,\r
+ " Register Base Address ................................ 0x%016lx\n",\r
+ Drhd->RegisterBaseAddress\r
+ ));\r
+\r
+ DrhdLen = Drhd->Header.Length - sizeof(EFI_ACPI_DMAR_DRHD_HEADER);\r
+ DmarDeviceScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)(Drhd + 1);\r
+ while (DrhdLen > 0) {\r
+ DumpDmarDeviceScopeEntry (DmarDeviceScopeEntry);\r
+ DrhdLen -= DmarDeviceScopeEntry->Length;\r
+ DmarDeviceScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)DmarDeviceScopeEntry + DmarDeviceScopeEntry->Length);\r
+ }\r
+\r
+ DEBUG ((DEBUG_INFO,\r
+ " ***************************************************************************\n\n"\r
+ ));\r
+\r
+ return;\r
+}\r
+\r
+/**\r
+ Dump DMAR ACPI table.\r
+\r
+ @param[in] Dmar DMAR ACPI table\r
+**/\r
+VOID\r
+DumpAcpiDMAR (\r
+ IN EFI_ACPI_DMAR_HEADER *Dmar\r
+ )\r
+{\r
+ EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;\r
+ INTN DmarLen;\r
+\r
+ if (Dmar == NULL) {\r
+ return;\r
+ }\r
+\r
+ //\r
+ // Dump Dmar table\r
+ //\r
+ DEBUG ((DEBUG_INFO,\r
+ "*****************************************************************************\n"\r
+ "* DMAR Table *\n"\r
+ "*****************************************************************************\n"\r
+ ));\r
+\r
+ DEBUG ((DEBUG_INFO,\r
+ (sizeof(UINTN) == sizeof(UINT64)) ?\r
+ "DMAR address ............................................. 0x%016lx\n" :\r
+ "DMAR address ............................................. 0x%08x\n",\r
+ Dmar\r
+ ));\r
+\r
+ DEBUG ((DEBUG_INFO,\r
+ " Table Contents:\n"\r
+ ));\r
+ DEBUG ((DEBUG_INFO,\r
+ " Host Address Width ................................... 0x%02x\n",\r
+ Dmar->HostAddressWidth\r
+ ));\r
+ DEBUG ((DEBUG_INFO,\r
+ " Flags ................................................ 0x%02x\n",\r
+ Dmar->Flags\r
+ ));\r
+ DEBUG ((DEBUG_INFO,\r
+ " INTR_REMAP ......................................... 0x%02x\n",\r
+ Dmar->Flags & EFI_ACPI_DMAR_FLAGS_INTR_REMAP\r
+ ));\r
+ DEBUG ((DEBUG_INFO,\r
+ " X2APIC_OPT_OUT_SET ................................. 0x%02x\n",\r
+ Dmar->Flags & EFI_ACPI_DMAR_FLAGS_X2APIC_OPT_OUT\r
+ ));\r
+\r
+ DmarLen = Dmar->Header.Length - sizeof(EFI_ACPI_DMAR_HEADER);\r
+ DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)(Dmar + 1);\r
+ while (DmarLen > 0) {\r
+ switch (DmarHeader->Type) {\r
+ case EFI_ACPI_DMAR_TYPE_DRHD:\r
+ DumpDmarDrhd ((EFI_ACPI_DMAR_DRHD_HEADER *)DmarHeader);\r
+ break;\r
+ case EFI_ACPI_DMAR_TYPE_RMRR:\r
+ DumpDmarRmrr ((EFI_ACPI_DMAR_RMRR_HEADER *)DmarHeader);\r
+ break;\r
+ case EFI_ACPI_DMAR_TYPE_ATSR:\r
+ DumpDmarAtsr ((EFI_ACPI_DMAR_ATSR_HEADER *)DmarHeader);\r
+ break;\r
+ case EFI_ACPI_DMAR_TYPE_RHSA:\r
+ DumpDmarRhsa ((EFI_ACPI_DMAR_RHSA_HEADER *)DmarHeader);\r
+ break;\r
+ case EFI_ACPI_DMAR_TYPE_ANDD:\r
+ DumpDmarAndd ((EFI_ACPI_DMAR_ANDD_HEADER *)DmarHeader);\r
+ break;\r
+ default:\r
+ break;\r
+ }\r
+ DmarLen -= DmarHeader->Length;\r
+ DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);\r
+ }\r
+\r
+ DEBUG ((DEBUG_INFO,\r
+ "*****************************************************************************\n\n"\r
+ ));\r
+\r
+ return;\r
+}\r
+\r
+/**\r
+ Dump DMAR ACPI table.\r
+**/\r
+VOID\r
+VtdDumpDmarTable (\r
+ VOID\r
+ )\r
+{\r
+ DumpAcpiDMAR ((EFI_ACPI_DMAR_HEADER *)(UINTN)mAcpiDmarTable);\r
+}\r
+\r
+/**\r
+ Get PCI device information from DMAR DevScopeEntry.\r
+\r
+ @param[in] Segment The segment number.\r
+ @param[in] DmarDevScopeEntry DMAR DevScopeEntry\r
+ @param[out] Bus The bus number.\r
+ @param[out] Device The device number.\r
+ @param[out] Function The function number.\r
+\r
+ @retval EFI_SUCCESS The PCI device information is returned.\r
+**/\r
+EFI_STATUS\r
+GetPciBusDeviceFunction (\r
+ IN UINT16 Segment,\r
+ IN EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDevScopeEntry,\r
+ OUT UINT8 *Bus,\r
+ OUT UINT8 *Device,\r
+ OUT UINT8 *Function\r
+ )\r
+{\r
+ EFI_ACPI_DMAR_PCI_PATH *DmarPciPath;\r
+ UINT8 MyBus;\r
+ UINT8 MyDevice;\r
+ UINT8 MyFunction;\r
+\r
+ DmarPciPath = (EFI_ACPI_DMAR_PCI_PATH *)((UINTN)(DmarDevScopeEntry + 1));\r
+ MyBus = DmarDevScopeEntry->StartBusNumber;\r
+ MyDevice = DmarPciPath->Device;\r
+ MyFunction = DmarPciPath->Function;\r
+\r
+ switch (DmarDevScopeEntry->Type) {\r
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT:\r
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE:\r
+ while ((UINTN)DmarPciPath < (UINTN)DmarDevScopeEntry + DmarDevScopeEntry->Length) {\r
+ MyBus = PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS(Segment, MyBus, MyDevice, MyFunction, PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET));\r
+ MyDevice = DmarPciPath->Device;\r
+ MyFunction = DmarPciPath->Function;\r
+ DmarPciPath ++;\r
+ }\r
+ break;\r
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_IOAPIC:\r
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_MSI_CAPABLE_HPET:\r
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_ACPI_NAMESPACE_DEVICE:\r
+ break;\r
+ }\r
+\r
+ *Bus = MyBus;\r
+ *Device = MyDevice;\r
+ *Function = MyFunction;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Process DMAR DHRD table.\r
+\r
+ @param[in] VtdIndex The index of VTd engine.\r
+ @param[in] DmarDrhd The DRHD table.\r
+\r
+ @retval EFI_SUCCESS The DRHD table is processed.\r
+**/\r
+EFI_STATUS\r
+ProcessDhrd (\r
+ IN UINTN VtdIndex,\r
+ IN EFI_ACPI_DMAR_DRHD_HEADER *DmarDrhd\r
+ )\r
+{\r
+ EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDevScopeEntry;\r
+ UINT8 Bus;\r
+ UINT8 Device;\r
+ UINT8 Function;\r
+ UINT8 SecondaryBusNumber;\r
+ EFI_STATUS Status;\r
+ VTD_SOURCE_ID SourceId;\r
+ BOOLEAN IsRealPciDevice;\r
+\r
+ mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress = (UINTN)DmarDrhd->RegisterBaseAddress;\r
+ DEBUG ((DEBUG_INFO," VTD (%d) BaseAddress - 0x%016lx\n", VtdIndex, DmarDrhd->RegisterBaseAddress));\r
+\r
+ mVtdUnitInformation[VtdIndex].Segment = DmarDrhd->SegmentNumber;\r
+\r
+ if ((DmarDrhd->Flags & EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL) != 0) {\r
+ mVtdUnitInformation[VtdIndex].PciDeviceInfo.IncludeAllFlag = TRUE;\r
+ DEBUG ((DEBUG_INFO," ProcessDhrd: with INCLUDE ALL\n"));\r
+\r
+ Status = ScanPciBus(VtdIndex, DmarDrhd->SegmentNumber, 0);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ } else {\r
+ mVtdUnitInformation[VtdIndex].PciDeviceInfo.IncludeAllFlag = FALSE;\r
+ DEBUG ((DEBUG_INFO," ProcessDhrd: without INCLUDE ALL\n"));\r
+ }\r
+\r
+ DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)(DmarDrhd + 1));\r
+ while ((UINTN)DmarDevScopeEntry < (UINTN)DmarDrhd + DmarDrhd->Header.Length) {\r
+\r
+ Status = GetPciBusDeviceFunction (DmarDrhd->SegmentNumber, DmarDevScopeEntry, &Bus, &Device, &Function);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ switch (DmarDevScopeEntry->Type) {\r
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT:\r
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE:\r
+ IsRealPciDevice = TRUE;\r
+ break;\r
+ default:\r
+ IsRealPciDevice = FALSE;\r
+ break;\r
+ }\r
+\r
+ DEBUG ((DEBUG_INFO," ProcessDhrd: "));\r
+ switch (DmarDevScopeEntry->Type) {\r
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT:\r
+ DEBUG ((DEBUG_INFO,"PCI Endpoint"));\r
+ break;\r
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE:\r
+ DEBUG ((DEBUG_INFO,"PCI-PCI bridge"));\r
+ break;\r
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_IOAPIC:\r
+ DEBUG ((DEBUG_INFO,"IOAPIC"));\r
+ break;\r
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_MSI_CAPABLE_HPET:\r
+ DEBUG ((DEBUG_INFO,"MSI Capable HPET"));\r
+ break;\r
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_ACPI_NAMESPACE_DEVICE:\r
+ DEBUG ((DEBUG_INFO,"ACPI Namespace Device"));\r
+ break;\r
+ }\r
+ DEBUG ((DEBUG_INFO," S%04x B%02x D%02x F%02x\n", DmarDrhd->SegmentNumber, Bus, Device, Function));\r
+\r
+ SourceId.Bits.Bus = Bus;\r
+ SourceId.Bits.Device = Device;\r
+ SourceId.Bits.Function = Function;\r
+\r
+ Status = RegisterPciDevice (VtdIndex, DmarDrhd->SegmentNumber, SourceId, IsRealPciDevice, TRUE);\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // There might be duplication for special device other than standard PCI device.\r
+ //\r
+ switch (DmarDevScopeEntry->Type) {\r
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT:\r
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE:\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ switch (DmarDevScopeEntry->Type) {\r
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE:\r
+ SecondaryBusNumber = PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS(DmarDrhd->SegmentNumber, Bus, Device, Function, PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET));\r
+ Status = ScanPciBus (VtdIndex, DmarDrhd->SegmentNumber, SecondaryBusNumber);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ break;\r
+ default:\r
+ break;\r
+ }\r
+\r
+ DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)DmarDevScopeEntry + DmarDevScopeEntry->Length);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Process DMAR RMRR table.\r
+\r
+ @param[in] DmarRmrr The RMRR table.\r
+\r
+ @retval EFI_SUCCESS The RMRR table is processed.\r
+**/\r
+EFI_STATUS\r
+ProcessRmrr (\r
+ IN EFI_ACPI_DMAR_RMRR_HEADER *DmarRmrr\r
+ )\r
+{\r
+ EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDevScopeEntry;\r
+ UINT8 Bus;\r
+ UINT8 Device;\r
+ UINT8 Function;\r
+ EFI_STATUS Status;\r
+ VTD_SOURCE_ID SourceId;\r
+\r
+ DEBUG ((DEBUG_INFO," RMRR (Base 0x%016lx, Limit 0x%016lx)\n", DmarRmrr->ReservedMemoryRegionBaseAddress, DmarRmrr->ReservedMemoryRegionLimitAddress));\r
+\r
+ DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)(DmarRmrr + 1));\r
+ while ((UINTN)DmarDevScopeEntry < (UINTN)DmarRmrr + DmarRmrr->Header.Length) {\r
+ if (DmarDevScopeEntry->Type != EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT) {\r
+ DEBUG ((DEBUG_INFO,"RMRR DevScopeEntryType is not endpoint, type[0x%x] \n", DmarDevScopeEntry->Type));\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ Status = GetPciBusDeviceFunction (DmarRmrr->SegmentNumber, DmarDevScopeEntry, &Bus, &Device, &Function);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ DEBUG ((DEBUG_INFO,"RMRR S%04x B%02x D%02x F%02x\n", DmarRmrr->SegmentNumber, Bus, Device, Function));\r
+\r
+ SourceId.Bits.Bus = Bus;\r
+ SourceId.Bits.Device = Device;\r
+ SourceId.Bits.Function = Function;\r
+ Status = SetAccessAttribute (\r
+ DmarRmrr->SegmentNumber,\r
+ SourceId,\r
+ DmarRmrr->ReservedMemoryRegionBaseAddress,\r
+ DmarRmrr->ReservedMemoryRegionLimitAddress + 1 - DmarRmrr->ReservedMemoryRegionBaseAddress,\r
+ EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)DmarDevScopeEntry + DmarDevScopeEntry->Length);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Get VTd engine number.\r
+**/\r
+UINTN\r
+GetVtdEngineNumber (\r
+ VOID\r
+ )\r
+{\r
+ EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;\r
+ UINTN VtdIndex;\r
+\r
+ VtdIndex = 0;\r
+ DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)(mAcpiDmarTable + 1));\r
+ while ((UINTN)DmarHeader < (UINTN)mAcpiDmarTable + mAcpiDmarTable->Header.Length) {\r
+ switch (DmarHeader->Type) {\r
+ case EFI_ACPI_DMAR_TYPE_DRHD:\r
+ VtdIndex++;\r
+ break;\r
+ default:\r
+ break;\r
+ }\r
+ DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);\r
+ }\r
+ return VtdIndex ;\r
+}\r
+\r
+/**\r
+ Parse DMAR DRHD table.\r
+\r
+ @return EFI_SUCCESS The DMAR DRHD table is parsed.\r
+**/\r
+EFI_STATUS\r
+ParseDmarAcpiTableDrhd (\r
+ VOID\r
+ )\r
+{\r
+ EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;\r
+ EFI_STATUS Status;\r
+ UINTN VtdIndex;\r
+\r
+ mVtdUnitNumber = GetVtdEngineNumber ();\r
+ DEBUG ((DEBUG_INFO," VtdUnitNumber - %d\n", mVtdUnitNumber));\r
+ ASSERT (mVtdUnitNumber > 0);\r
+ if (mVtdUnitNumber == 0) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ mVtdUnitInformation = AllocateZeroPool (sizeof(*mVtdUnitInformation) * mVtdUnitNumber);\r
+ ASSERT (mVtdUnitInformation != NULL);\r
+ if (mVtdUnitInformation == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ mVtdHostAddressWidthMask = LShiftU64 (1ull, mAcpiDmarTable->HostAddressWidth) - 1;\r
+\r
+ VtdIndex = 0;\r
+ DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)(mAcpiDmarTable + 1));\r
+ while ((UINTN)DmarHeader < (UINTN)mAcpiDmarTable + mAcpiDmarTable->Header.Length) {\r
+ switch (DmarHeader->Type) {\r
+ case EFI_ACPI_DMAR_TYPE_DRHD:\r
+ ASSERT (VtdIndex < mVtdUnitNumber);\r
+ Status = ProcessDhrd (VtdIndex, (EFI_ACPI_DMAR_DRHD_HEADER *)DmarHeader);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ VtdIndex++;\r
+\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+ DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);\r
+ }\r
+ ASSERT (VtdIndex == mVtdUnitNumber);\r
+\r
+ for (VtdIndex = 0; VtdIndex < mVtdUnitNumber; VtdIndex++) {\r
+ DumpPciDeviceInfo (VtdIndex);\r
+ }\r
+ return EFI_SUCCESS ;\r
+}\r
+\r
+/**\r
+ Parse DMAR DRHD table.\r
+\r
+ @return EFI_SUCCESS The DMAR DRHD table is parsed.\r
+**/\r
+EFI_STATUS\r
+ParseDmarAcpiTableRmrr (\r
+ VOID\r
+ )\r
+{\r
+ EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;\r
+ EFI_STATUS Status;\r
+\r
+ DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)(mAcpiDmarTable + 1));\r
+ while ((UINTN)DmarHeader < (UINTN)mAcpiDmarTable + mAcpiDmarTable->Header.Length) {\r
+ switch (DmarHeader->Type) {\r
+ case EFI_ACPI_DMAR_TYPE_RMRR:\r
+ Status = ProcessRmrr ((EFI_ACPI_DMAR_RMRR_HEADER *)DmarHeader);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ break;\r
+ default:\r
+ break;\r
+ }\r
+ DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);\r
+ }\r
+ return EFI_SUCCESS ;\r
+}\r
+\r
+/**\r
+ This function scan ACPI table in RSDT.\r
+\r
+ @param[in] Rsdt ACPI RSDT\r
+ @param[in] Signature ACPI table signature\r
+\r
+ @return ACPI table\r
+**/\r
+VOID *\r
+ScanTableInRSDT (\r
+ IN RSDT_TABLE *Rsdt,\r
+ IN UINT32 Signature\r
+ )\r
+{\r
+ UINTN Index;\r
+ UINT32 EntryCount;\r
+ UINT32 *EntryPtr;\r
+ EFI_ACPI_DESCRIPTION_HEADER *Table;\r
+\r
+ EntryCount = (Rsdt->Header.Length - sizeof (EFI_ACPI_DESCRIPTION_HEADER)) / sizeof(UINT32);\r
+\r
+ EntryPtr = &Rsdt->Entry;\r
+ for (Index = 0; Index < EntryCount; Index ++, EntryPtr ++) {\r
+ Table = (EFI_ACPI_DESCRIPTION_HEADER*)((UINTN)(*EntryPtr));\r
+ if (Table->Signature == Signature) {\r
+ return Table;\r
+ }\r
+ }\r
+\r
+ return NULL;\r
+}\r
+\r
+/**\r
+ This function scan ACPI table in XSDT.\r
+\r
+ @param[in] Xsdt ACPI XSDT\r
+ @param[in] Signature ACPI table signature\r
+\r
+ @return ACPI table\r
+**/\r
+VOID *\r
+ScanTableInXSDT (\r
+ IN XSDT_TABLE *Xsdt,\r
+ IN UINT32 Signature\r
+ )\r
+{\r
+ UINTN Index;\r
+ UINT32 EntryCount;\r
+ UINT64 EntryPtr;\r
+ UINTN BasePtr;\r
+ EFI_ACPI_DESCRIPTION_HEADER *Table;\r
+\r
+ EntryCount = (Xsdt->Header.Length - sizeof (EFI_ACPI_DESCRIPTION_HEADER)) / sizeof(UINT64);\r
+\r
+ BasePtr = (UINTN)(&(Xsdt->Entry));\r
+ for (Index = 0; Index < EntryCount; Index ++) {\r
+ CopyMem (&EntryPtr, (VOID *)(BasePtr + Index * sizeof(UINT64)), sizeof(UINT64));\r
+ Table = (EFI_ACPI_DESCRIPTION_HEADER*)((UINTN)(EntryPtr));\r
+ if (Table->Signature == Signature) {\r
+ return Table;\r
+ }\r
+ }\r
+\r
+ return NULL;\r
+}\r
+\r
+/**\r
+ This function scan ACPI table in RSDP.\r
+\r
+ @param[in] Rsdp ACPI RSDP\r
+ @param[in] Signature ACPI table signature\r
+\r
+ @return ACPI table\r
+**/\r
+VOID *\r
+FindAcpiPtr (\r
+ IN EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp,\r
+ IN UINT32 Signature\r
+ )\r
+{\r
+ EFI_ACPI_DESCRIPTION_HEADER *AcpiTable;\r
+ RSDT_TABLE *Rsdt;\r
+ XSDT_TABLE *Xsdt;\r
+\r
+ AcpiTable = NULL;\r
+\r
+ //\r
+ // Check ACPI2.0 table\r
+ //\r
+ Rsdt = (RSDT_TABLE *)(UINTN)Rsdp->RsdtAddress;\r
+ Xsdt = NULL;\r
+ if ((Rsdp->Revision >= 2) && (Rsdp->XsdtAddress < (UINT64)(UINTN)-1)) {\r
+ Xsdt = (XSDT_TABLE *)(UINTN)Rsdp->XsdtAddress;\r
+ }\r
+ //\r
+ // Check Xsdt\r
+ //\r
+ if (Xsdt != NULL) {\r
+ AcpiTable = ScanTableInXSDT (Xsdt, Signature);\r
+ }\r
+ //\r
+ // Check Rsdt\r
+ //\r
+ if ((AcpiTable == NULL) && (Rsdt != NULL)) {\r
+ AcpiTable = ScanTableInRSDT (Rsdt, Signature);\r
+ }\r
+\r
+ return AcpiTable;\r
+}\r
+\r
+/**\r
+ Get the DMAR ACPI table.\r
+\r
+ @retval EFI_SUCCESS The DMAR ACPI table is got.\r
+ @retval EFI_NOT_FOUND The DMAR ACPI table is not found.\r
+**/\r
+EFI_STATUS\r
+GetDmarAcpiTable (\r
+ VOID\r
+ )\r
+{\r
+ VOID *AcpiTable;\r
+ EFI_STATUS Status;\r
+\r
+ AcpiTable = NULL;\r
+ Status = EfiGetSystemConfigurationTable (\r
+ &gEfiAcpi20TableGuid,\r
+ &AcpiTable\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ Status = EfiGetSystemConfigurationTable (\r
+ &gEfiAcpiTableGuid,\r
+ &AcpiTable\r
+ );\r
+ }\r
+ ASSERT (AcpiTable != NULL);\r
+\r
+ mAcpiDmarTable = FindAcpiPtr (\r
+ (EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)AcpiTable,\r
+ EFI_ACPI_4_0_DMA_REMAPPING_TABLE_SIGNATURE\r
+ );\r
+ DEBUG ((DEBUG_INFO,"DMAR Table - 0x%08x\n", mAcpiDmarTable));\r
+ if (mAcpiDmarTable == NULL) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ VtdDumpDmarTable();\r
+\r
+ return EFI_SUCCESS;\r
+}\r