]> git.proxmox.com Git - mirror_edk2.git/blobdiff - IntelSiliconPkg/IntelVTdDxe/DmarAcpiTable.c
IntelSiliconPkg: Add VTd driver.
[mirror_edk2.git] / IntelSiliconPkg / IntelVTdDxe / DmarAcpiTable.c
diff --git a/IntelSiliconPkg/IntelVTdDxe/DmarAcpiTable.c b/IntelSiliconPkg/IntelVTdDxe/DmarAcpiTable.c
new file mode 100644 (file)
index 0000000..84b5485
--- /dev/null
@@ -0,0 +1,998 @@
+/** @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