IntelSiliconPkg/IntelVTdPmrPei: Parse RMRR table.
[mirror_edk2.git] / IntelSiliconPkg / Feature / VTd / IntelVTdPmrPei / IntelVTdPmrPei.c
index 6a19c88..e768274 100644 (file)
@@ -29,7 +29,9 @@
 \r
 #define  TOTAL_DMA_BUFFER_SIZE    SIZE_4MB\r
 \r
-EDKII_VTD_INFO_PPI                *mVTdInfoPpi;\r
+EFI_ACPI_DMAR_HEADER              *mAcpiDmarTable;\r
+VTD_INFO                          *mVTdInfo;\r
+UINT64                            mEngineMask;\r
 UINTN                             mDmaBufferBase;\r
 UINTN                             mDmaBufferSize = TOTAL_DMA_BUFFER_SIZE;\r
 UINTN                             mDmaBufferCurrentTop;\r
@@ -48,15 +50,19 @@ typedef struct {
 \r
   PEI Memory Layout:\r
 \r
+              +------------------+ <=============== PHMR.Limit (Top of memory)\r
+              |   Mem Resource   |\r
+              |                  |\r
+\r
               +------------------+ <------- EfiMemoryTop\r
               |   PEI allocated  |\r
-  =========== +==================+\r
+  =========== +==================+ <=============== PHMR.Base\r
        ^      |    Commom Buf    |\r
        |      |  --------------  |\r
   DMA Buffer  |   * DMA FREE *   |\r
        |      |  --------------  |\r
        V      |  Read/Write Buf  |\r
-  =========== +==================+\r
+  =========== +==================+ <=============== PLMR.Limit\r
               |   PEI allocated  |\r
               |  --------------  | <------- EfiFreeMemoryTop\r
               |   * PEI FREE *   |\r
@@ -70,6 +76,9 @@ typedef struct {
               |   Mem Alloc Hob  |\r
               +------------------+\r
 \r
+              |                  |\r
+              |   Mem Resource   |\r
+              +------------------+ <=============== PLMR.Base (0)\r
 **/\r
 \r
 \r
@@ -457,20 +466,21 @@ DumpPhitHob (
 /**\r
   Get the highest memory.\r
 \r
-  @param HobList  the HOB list.\r
-\r
   @return the highest memory.\r
 **/\r
 UINT64\r
 GetTopMemory (\r
-  IN VOID                        *HobList\r
+  VOID\r
   )\r
 {\r
+  VOID                        *HobList;\r
   EFI_PEI_HOB_POINTERS        Hob;\r
   EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;\r
   UINT64                      TopMemory;\r
   UINT64                      ResourceTop;\r
 \r
+  HobList = GetHobList ();\r
+\r
   TopMemory = 0;\r
   for (Hob.Raw = HobList; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {\r
     if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {\r
@@ -525,8 +535,8 @@ InitDmaProtection (
 \r
   ASSERT (PhitHob->EfiMemoryBottom < PhitHob->EfiMemoryTop);\r
 \r
-  LowMemoryAlignment = GetLowMemoryAlignment ();\r
-  HighMemoryAlignment = GetHighMemoryAlignment ();\r
+  LowMemoryAlignment = GetLowMemoryAlignment (mEngineMask);\r
+  HighMemoryAlignment = GetHighMemoryAlignment (mEngineMask);\r
   if (LowMemoryAlignment < HighMemoryAlignment) {\r
     MemoryAlignment = (UINTN)HighMemoryAlignment;\r
   } else {\r
@@ -542,9 +552,10 @@ InitDmaProtection (
   LowBottom = 0;\r
   LowTop = *DmaBufferBase;\r
   HighBottom = *DmaBufferBase + DmaBufferSize;\r
-  HighTop = GetTopMemory (HobList);\r
+  HighTop = GetTopMemory ();\r
 \r
   Status = SetDmaProtectedRange (\r
+               mEngineMask,\r
                (UINT32)LowBottom,\r
                (UINT32)(LowTop - LowBottom),\r
                HighBottom,\r
@@ -558,6 +569,541 @@ InitDmaProtection (
   return Status;\r
 }\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
+    ));\r
+  DEBUG ((DEBUG_INFO,\r
+    "    *       DMA-Remapping Device Scope Entry Structure                      *\n"\r
+    ));\r
+  DEBUG ((DEBUG_INFO,\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
+  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 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
+    ));\r
+  DEBUG ((DEBUG_INFO,\r
+    "  *       Reserved Memory Region Reporting Structure                        *\n"\r
+    ));\r
+  DEBUG ((DEBUG_INFO,\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
+    ));\r
+  DEBUG ((DEBUG_INFO,\r
+    "  *       DMA-Remapping Hardware Definition Structure                       *\n"\r
+    ));\r
+  DEBUG ((DEBUG_INFO,\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
+    ));\r
+  DEBUG ((DEBUG_INFO,\r
+    "*         DMAR Table                                                        *\n"\r
+    ));\r
+  DEBUG ((DEBUG_INFO,\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
+    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
+  Get VTd engine number.\r
+\r
+  @return the 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
+  Process DMAR DHRD table.\r
+\r
+  @param[in]  VtdIndex  The index of VTd engine.\r
+  @param[in]  DmarDrhd  The DRHD table.\r
+**/\r
+VOID\r
+ProcessDhrd (\r
+  IN UINTN                      VtdIndex,\r
+  IN EFI_ACPI_DMAR_DRHD_HEADER  *DmarDrhd\r
+  )\r
+{\r
+  DEBUG ((DEBUG_INFO,"  VTD (%d) BaseAddress -  0x%016lx\n", VtdIndex, DmarDrhd->RegisterBaseAddress));\r
+  mVTdInfo->VTdEngineAddress[VtdIndex] = DmarDrhd->RegisterBaseAddress;\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
+  UINTN                                             VtdUnitNumber;\r
+  UINTN                                             VtdIndex;\r
+\r
+  VtdUnitNumber = GetVtdEngineNumber ();\r
+  if (VtdUnitNumber == 0) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  mVTdInfo = AllocateZeroPool (sizeof(VTD_INFO) + (VtdUnitNumber - 1) * sizeof(UINT64));\r
+  if (mVTdInfo == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  mVTdInfo->HostAddressWidth = mAcpiDmarTable->HostAddressWidth;\r
+  mVTdInfo->VTdEngineCount   = VtdUnitNumber;\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 < VtdUnitNumber);\r
+      ProcessDhrd (VtdIndex, (EFI_ACPI_DMAR_DRHD_HEADER *)DmarHeader);\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 == VtdUnitNumber);\r
+\r
+  //\r
+  // Initialize the engine mask to all.\r
+  //\r
+  mEngineMask = LShiftU64 (1, VtdUnitNumber) - 1;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Return the VTd engine index according to the Segment and DevScopeEntry.\r
+\r
+  @param Segment         The segment of the VTd engine\r
+  @param DevScopeEntry   The DevScopeEntry of the VTd engine\r
+\r
+  @return The VTd engine index according to the Segment and DevScopeEntry.\r
+  @retval -1  The VTd engine is not found.\r
+**/\r
+UINTN\r
+GetVTdEngineFromDevScopeEntry (\r
+  IN  UINT16                                      Segment,\r
+  IN  EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DevScopeEntry\r
+  )\r
+{\r
+  EFI_ACPI_DMAR_STRUCTURE_HEADER                    *DmarHeader;\r
+  UINTN                                             VtdIndex;\r
+  EFI_ACPI_DMAR_DRHD_HEADER                         *DmarDrhd;\r
+  EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER       *ThisDevScopeEntry;\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
+      DmarDrhd = (EFI_ACPI_DMAR_DRHD_HEADER *)DmarHeader;\r
+      if (DmarDrhd->SegmentNumber != Segment) {\r
+        // Mismatch\r
+        break;\r
+      }\r
+      if ((DmarDrhd->Header.Length == sizeof(EFI_ACPI_DMAR_DRHD_HEADER)) ||\r
+          ((DmarDrhd->Flags & EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL) != 0)) {\r
+        // No DevScopeEntry\r
+        // Do not handle PCI_ALL\r
+        break;\r
+      }\r
+      ThisDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)(DmarDrhd + 1));\r
+      while ((UINTN)ThisDevScopeEntry < (UINTN)DmarDrhd + DmarDrhd->Header.Length) {\r
+        if ((ThisDevScopeEntry->Length == DevScopeEntry->Length) &&\r
+            (CompareMem (ThisDevScopeEntry, DevScopeEntry, DevScopeEntry->Length) == 0)) {\r
+          return VtdIndex;\r
+        }\r
+        ThisDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)ThisDevScopeEntry + ThisDevScopeEntry->Length);\r
+      }\r
+      break;\r
+    default:\r
+      break;\r
+    }\r
+    DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);\r
+  }\r
+  return (UINTN)-1;\r
+}\r
+\r
+/**\r
+  Process DMAR RMRR table.\r
+\r
+  @param[in]  DmarRmrr  The RMRR table.\r
+**/\r
+VOID\r
+ProcessRmrr (\r
+  IN EFI_ACPI_DMAR_RMRR_HEADER  *DmarRmrr\r
+  )\r
+{\r
+  EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER       *DmarDevScopeEntry;\r
+  UINTN                                             VTdIndex;\r
+  UINT64                                            RmrrMask;\r
+  UINTN                                             LowBottom;\r
+  UINTN                                             LowTop;\r
+  UINTN                                             HighBottom;\r
+  UINT64                                            HighTop;\r
+\r
+  DEBUG ((DEBUG_INFO,"  RMRR (Base 0x%016lx, Limit 0x%016lx)\n", DmarRmrr->ReservedMemoryRegionBaseAddress, DmarRmrr->ReservedMemoryRegionLimitAddress));\r
+\r
+  if ((DmarRmrr->ReservedMemoryRegionBaseAddress == 0) ||\r
+      (DmarRmrr->ReservedMemoryRegionLimitAddress == 0)) {\r
+    return ;\r
+  }\r
+\r
+  DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)(DmarRmrr + 1));\r
+  while ((UINTN)DmarDevScopeEntry < (UINTN)DmarRmrr + DmarRmrr->Header.Length) {\r
+    ASSERT (DmarDevScopeEntry->Type == EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT);\r
+\r
+    VTdIndex = GetVTdEngineFromDevScopeEntry (DmarRmrr->SegmentNumber, DmarDevScopeEntry);\r
+    if (VTdIndex != (UINTN)-1) {\r
+      RmrrMask = LShiftU64 (1, VTdIndex);\r
+\r
+      LowBottom = 0;\r
+      LowTop = (UINTN)DmarRmrr->ReservedMemoryRegionBaseAddress;\r
+      HighBottom = (UINTN)DmarRmrr->ReservedMemoryRegionLimitAddress + 1;\r
+      HighTop = GetTopMemory ();\r
+\r
+      SetDmaProtectedRange (\r
+        RmrrMask,\r
+        0,\r
+        (UINT32)(LowTop - LowBottom),\r
+        HighBottom,\r
+        HighTop - HighBottom\r
+        );\r
+\r
+      //\r
+      // Remove the engine from the engine mask.\r
+      // The assumption is that any other PEI driver does not access\r
+      // the device covered by this engine.\r
+      //\r
+      mEngineMask = mEngineMask & (~RmrrMask);\r
+    }\r
+\r
+    DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)DmarDevScopeEntry + DmarDevScopeEntry->Length);\r
+  }\r
+}\r
+\r
+/**\r
+  Parse DMAR DRHD table.\r
+**/\r
+VOID\r
+ParseDmarAcpiTableRmrr (\r
+  VOID\r
+  )\r
+{\r
+  EFI_ACPI_DMAR_STRUCTURE_HEADER                    *DmarHeader;\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
+      ProcessRmrr ((EFI_ACPI_DMAR_RMRR_HEADER *)DmarHeader);\r
+      break;\r
+    default:\r
+      break;\r
+    }\r
+    DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);\r
+  }\r
+}\r
+\r
 /**\r
   Initializes the Intel VTd PMR PEIM.\r
 \r
@@ -585,10 +1131,25 @@ IntelVTdPmrInitialize (
              &gEdkiiVTdInfoPpiGuid,\r
              0,\r
              NULL,\r
-             (VOID **)&mVTdInfoPpi\r
+             (VOID **)&mAcpiDmarTable\r
              );\r
   ASSERT_EFI_ERROR(Status);\r
 \r
+  DumpAcpiDMAR (mAcpiDmarTable);\r
+\r
+  //\r
+  // Get DMAR information to local VTdInfo\r
+  //\r
+  Status = ParseDmarAcpiTableDrhd ();\r
+  if (EFI_ERROR(Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // If there is RMRR memory, parse it here.\r
+  //\r
+  ParseDmarAcpiTableRmrr ();\r
+\r
   //\r
   // Find a pre-memory in resource hob as DMA buffer\r
   // Mark PEI memory to be DMA protected.\r