IntelSiliconPkg/VtdPmrPei: Add premem support.
authorJiewen Yao <jiewen.yao@intel.com>
Sat, 23 Sep 2017 08:27:50 +0000 (16:27 +0800)
committerJiewen Yao <jiewen.yao@intel.com>
Mon, 30 Oct 2017 01:27:55 +0000 (09:27 +0800)
Remove memory discovered dependency to support both premem
VTD_INFO_PPI and postmem VTD_INFO_PPI.

If VTD_INFO_PPI is installed before memory is ready, this
driver protects all memory region.
If VTD_INFO_PPI is installed or reinstalled after memory
is ready, this driver allocates DMA buffer and protect rest.

Cc: Star Zeng <star.zeng@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/DmarTable.c [new file with mode: 0644]
IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmr.c
IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.c
IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.h
IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.inf
IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/VtdReg.c [new file with mode: 0644]

diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/DmarTable.c b/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/DmarTable.c
new file mode 100644 (file)
index 0000000..891efa6
--- /dev/null
@@ -0,0 +1,580 @@
+/** @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 <Uefi.h>\r
+#include <PiPei.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/HobLib.h>\r
+#include <IndustryStandard/Vtd.h>\r
+#include <Ppi/VtdInfo.h>\r
+\r
+#include "IntelVTdPmrPei.h"\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
+  @param[in]  AcpiDmarTable  DMAR ACPI table\r
+\r
+  @return the VTd engine number.\r
+**/\r
+UINTN\r
+GetVtdEngineNumber (\r
+  IN EFI_ACPI_DMAR_HEADER                    *AcpiDmarTable\r
+  )\r
+{\r
+  EFI_ACPI_DMAR_STRUCTURE_HEADER                    *DmarHeader;\r
+  UINTN                                             VtdIndex;\r
+\r
+  VtdIndex = 0;\r
+  DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)(AcpiDmarTable + 1));\r
+  while ((UINTN)DmarHeader < (UINTN)AcpiDmarTable + AcpiDmarTable->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]  VTdInfo   The VTd engine context information.\r
+  @param[in]  VtdIndex  The index of VTd engine.\r
+  @param[in]  DmarDrhd  The DRHD table.\r
+**/\r
+VOID\r
+ProcessDhrd (\r
+  IN VTD_INFO                   *VTdInfo,\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
+  VTdInfo->VTdEngineAddress[VtdIndex] = DmarDrhd->RegisterBaseAddress;\r
+}\r
+\r
+/**\r
+  Parse DMAR DRHD table.\r
+\r
+  @param[in]  AcpiDmarTable  DMAR ACPI table\r
+\r
+  @return EFI_SUCCESS  The DMAR DRHD table is parsed.\r
+**/\r
+EFI_STATUS\r
+ParseDmarAcpiTableDrhd (\r
+  IN EFI_ACPI_DMAR_HEADER                    *AcpiDmarTable\r
+  )\r
+{\r
+  EFI_ACPI_DMAR_STRUCTURE_HEADER                    *DmarHeader;\r
+  UINTN                                             VtdUnitNumber;\r
+  UINTN                                             VtdIndex;\r
+  VTD_INFO                                          *VTdInfo;\r
+\r
+  VtdUnitNumber = GetVtdEngineNumber (AcpiDmarTable);\r
+  if (VtdUnitNumber == 0) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  VTdInfo = BuildGuidHob (&mVTdInfoGuid, sizeof(VTD_INFO) + (VtdUnitNumber - 1) * sizeof(UINT64));\r
+  ASSERT(VTdInfo != NULL);\r
+  if (VTdInfo == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  //\r
+  // Initialize the engine mask to all.\r
+  //\r
+  VTdInfo->AcpiDmarTable    = AcpiDmarTable;\r
+  VTdInfo->EngineMask       = LShiftU64 (1, VtdUnitNumber) - 1;\r
+  VTdInfo->HostAddressWidth = AcpiDmarTable->HostAddressWidth;\r
+  VTdInfo->VTdEngineCount   = VtdUnitNumber;\r
+\r
+  VtdIndex = 0;\r
+  DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)(AcpiDmarTable + 1));\r
+  while ((UINTN)DmarHeader < (UINTN)AcpiDmarTable + AcpiDmarTable->Header.Length) {\r
+    switch (DmarHeader->Type) {\r
+    case EFI_ACPI_DMAR_TYPE_DRHD:\r
+      ASSERT (VtdIndex < VtdUnitNumber);\r
+      ProcessDhrd (VTdInfo, 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
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Return the VTd engine index according to the Segment and DevScopeEntry.\r
+\r
+  @param AcpiDmarTable   DMAR ACPI table\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  EFI_ACPI_DMAR_HEADER                        *AcpiDmarTable,\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)(AcpiDmarTable + 1));\r
+  while ((UINTN)DmarHeader < (UINTN)AcpiDmarTable + AcpiDmarTable->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]  VTdInfo   The VTd engine context information.\r
+  @param[in]  DmarRmrr  The RMRR table.\r
+**/\r
+VOID\r
+ProcessRmrr (\r
+  IN VTD_INFO                   *VTdInfo,\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
+  EFI_ACPI_DMAR_HEADER                              *AcpiDmarTable;\r
+\r
+  AcpiDmarTable = VTdInfo->AcpiDmarTable;\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 (AcpiDmarTable, 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
+        VTdInfo,\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
+      VTdInfo->EngineMask = VTdInfo->EngineMask & (~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
+  @param[in]  VTdInfo   The VTd engine context information.\r
+**/\r
+VOID\r
+ParseDmarAcpiTableRmrr (\r
+  IN VTD_INFO                    *VTdInfo\r
+  )\r
+{\r
+  EFI_ACPI_DMAR_HEADER                    *AcpiDmarTable;\r
+  EFI_ACPI_DMAR_STRUCTURE_HEADER          *DmarHeader;\r
+\r
+  AcpiDmarTable = VTdInfo->AcpiDmarTable;\r
+\r
+  DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)(AcpiDmarTable + 1));\r
+  while ((UINTN)DmarHeader < (UINTN)AcpiDmarTable + AcpiDmarTable->Header.Length) {\r
+    switch (DmarHeader->Type) {\r
+    case EFI_ACPI_DMAR_TYPE_RMRR:\r
+      ProcessRmrr (VTdInfo, (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
index 6179dfe..000a81b 100644 (file)
 \r
 #include "IntelVTdPmrPei.h"\r
 \r
-extern VTD_INFO                *mVTdInfo;\r
-\r
 /**\r
   Get protected low memory alignment.\r
 \r
+  @param HostAddressWidth   The host address width.\r
   @param VtdUnitBaseAddress The base address of the VTd engine.\r
 \r
   @return protected low memory alignment.\r
 **/\r
 UINT32\r
 GetPlmrAlignment (\r
+  IN UINT8         HostAddressWidth,\r
   IN UINTN         VtdUnitBaseAddress\r
   )\r
 {\r
@@ -48,19 +48,18 @@ GetPlmrAlignment (
 /**\r
   Get protected high memory alignment.\r
 \r
+  @param HostAddressWidth   The host address width.\r
   @param VtdUnitBaseAddress The base address of the VTd engine.\r
 \r
   @return protected high memory alignment.\r
 **/\r
 UINT64\r
 GetPhmrAlignment (\r
+  IN UINT8         HostAddressWidth,\r
   IN UINTN         VtdUnitBaseAddress\r
   )\r
 {\r
   UINT64        Data64;\r
-  UINT8         HostAddressWidth;\r
-\r
-  HostAddressWidth = mVTdInfo->HostAddressWidth;\r
 \r
   MmioWrite64 (VtdUnitBaseAddress + R_PMEN_HIGH_BASE_REG, 0xFFFFFFFFFFFFFFFF);\r
   Data64 = MmioRead64 (VtdUnitBaseAddress + R_PMEN_HIGH_BASE_REG);\r
@@ -73,12 +72,14 @@ GetPhmrAlignment (
 /**\r
   Get protected low memory alignment.\r
 \r
+  @param VTdInfo            The VTd engine context information.\r
   @param EngineMask         The mask of the VTd engine to be accessed.\r
 \r
   @return protected low memory alignment.\r
 **/\r
 UINT32\r
 GetLowMemoryAlignment (\r
+  IN VTD_INFO      *VTdInfo,\r
   IN UINT64        EngineMask\r
   )\r
 {\r
@@ -87,11 +88,11 @@ GetLowMemoryAlignment (
   UINT32        FinalAlignment;\r
 \r
   FinalAlignment = 0;\r
-  for (Index = 0; Index < mVTdInfo->VTdEngineCount; Index++) {\r
+  for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) {\r
     if ((EngineMask & LShiftU64(1, Index)) == 0) {\r
       continue;\r
     }\r
-    Alignment = GetPlmrAlignment ((UINTN)mVTdInfo->VTdEngineAddress[Index]);\r
+    Alignment = GetPlmrAlignment (VTdInfo->HostAddressWidth, (UINTN)VTdInfo->VTdEngineAddress[Index]);\r
     if (FinalAlignment < Alignment) {\r
       FinalAlignment = Alignment;\r
     }\r
@@ -102,12 +103,14 @@ GetLowMemoryAlignment (
 /**\r
   Get protected high memory alignment.\r
 \r
+  @param VTdInfo            The VTd engine context information.\r
   @param EngineMask         The mask of the VTd engine to be accessed.\r
 \r
   @return protected high memory alignment.\r
 **/\r
 UINT64\r
 GetHighMemoryAlignment (\r
+  IN VTD_INFO      *VTdInfo,\r
   IN UINT64        EngineMask\r
   )\r
 {\r
@@ -116,11 +119,11 @@ GetHighMemoryAlignment (
   UINT64        FinalAlignment;\r
 \r
   FinalAlignment = 0;\r
-  for (Index = 0; Index < mVTdInfo->VTdEngineCount; Index++) {\r
+  for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) {\r
     if ((EngineMask & LShiftU64(1, Index)) == 0) {\r
       continue;\r
     }\r
-    Alignment = GetPhmrAlignment ((UINTN)mVTdInfo->VTdEngineAddress[Index]);\r
+    Alignment = GetPhmrAlignment (VTdInfo->HostAddressWidth, (UINTN)VTdInfo->VTdEngineAddress[Index]);\r
     if (FinalAlignment < Alignment) {\r
       FinalAlignment = Alignment;\r
     }\r
@@ -144,12 +147,19 @@ EnablePmr (
   UINT32        Reg32;\r
   VTD_CAP_REG   CapReg;\r
 \r
+  DEBUG ((DEBUG_INFO, "EnablePmr - %x\n", VtdUnitBaseAddress));\r
+\r
   CapReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_CAP_REG);\r
   if (CapReg.Bits.PLMR == 0 || CapReg.Bits.PHMR == 0) {\r
     return EFI_UNSUPPORTED;\r
   }\r
 \r
   Reg32 = MmioRead32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG);\r
+  if (Reg32 == 0xFFFFFFFF) {\r
+    DEBUG ((DEBUG_ERROR, "R_PMEN_ENABLE_REG - 0x%x\n", Reg32));\r
+    ASSERT(FALSE);\r
+  }\r
+\r
   if ((Reg32 & BIT0) == 0) {\r
     MmioWrite32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG, BIT31);\r
     do {\r
@@ -157,6 +167,8 @@ EnablePmr (
     } while((Reg32 & BIT0) == 0);\r
   }\r
 \r
+  DEBUG ((DEBUG_INFO, "EnablePmr - Done\n"));\r
+\r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -182,6 +194,11 @@ DisablePmr (
   }\r
 \r
   Reg32 = MmioRead32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG);\r
+  if (Reg32 == 0xFFFFFFFF) {\r
+    DEBUG ((DEBUG_ERROR, "R_PMEN_ENABLE_REG - 0x%x\n", Reg32));\r
+    ASSERT(FALSE);\r
+  }\r
+\r
   if ((Reg32 & BIT0) != 0) {\r
     MmioWrite32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG, 0x0);\r
     do {\r
@@ -195,6 +212,7 @@ DisablePmr (
 /**\r
   Set PMR region in the VTd engine.\r
 \r
+  @param HostAddressWidth   The host address width.\r
   @param VtdUnitBaseAddress The base address of the VTd engine.\r
   @param LowMemoryBase      The protected low memory region base.\r
   @param LowMemoryLength    The protected low memory region length.\r
@@ -206,6 +224,7 @@ DisablePmr (
 **/\r
 EFI_STATUS\r
 SetPmrRegion (\r
+  IN UINT8         HostAddressWidth,\r
   IN UINTN         VtdUnitBaseAddress,\r
   IN UINT32        LowMemoryBase,\r
   IN UINT32        LowMemoryLength,\r
@@ -225,9 +244,9 @@ SetPmrRegion (
     return EFI_UNSUPPORTED;\r
   }\r
 \r
-  PlmrAlignment = GetPlmrAlignment (VtdUnitBaseAddress);\r
+  PlmrAlignment = GetPlmrAlignment (HostAddressWidth, VtdUnitBaseAddress);\r
   DEBUG ((DEBUG_INFO, "PlmrAlignment - 0x%x\n", PlmrAlignment));\r
-  PhmrAlignment = GetPhmrAlignment (VtdUnitBaseAddress);\r
+  PhmrAlignment = GetPhmrAlignment (HostAddressWidth, VtdUnitBaseAddress);\r
   DEBUG ((DEBUG_INFO, "PhmrAlignment - 0x%lx\n", PhmrAlignment));\r
 \r
   if ((LowMemoryBase    != ALIGN_VALUE(LowMemoryBase, PlmrAlignment)) ||\r
@@ -247,8 +266,10 @@ SetPmrRegion (
 \r
   MmioWrite32 (VtdUnitBaseAddress + R_PMEN_LOW_BASE_REG,    LowMemoryBase);\r
   MmioWrite32 (VtdUnitBaseAddress + R_PMEN_LOW_LIMITE_REG,  LowMemoryBase + LowMemoryLength - 1);\r
+  DEBUG ((DEBUG_INFO, "PLMR set done\n"));\r
   MmioWrite64 (VtdUnitBaseAddress + R_PMEN_HIGH_BASE_REG,   HighMemoryBase);\r
   MmioWrite64 (VtdUnitBaseAddress + R_PMEN_HIGH_LIMITE_REG, HighMemoryBase + HighMemoryLength - 1);\r
+  DEBUG ((DEBUG_INFO, "PHMR set done\n"));\r
 \r
   return EFI_SUCCESS;\r
 }\r
@@ -256,6 +277,7 @@ SetPmrRegion (
 /**\r
   Set DMA protected region.\r
 \r
+  @param VTdInfo            The VTd engine context information.\r
   @param EngineMask         The mask of the VTd engine to be accessed.\r
   @param LowMemoryBase      The protected low memory region base.\r
   @param LowMemoryLength    The protected low memory region length.\r
@@ -267,6 +289,7 @@ SetPmrRegion (
 **/\r
 EFI_STATUS\r
 SetDmaProtectedRange (\r
+  IN VTD_INFO      *VTdInfo,\r
   IN UINT64        EngineMask,\r
   IN UINT32        LowMemoryBase,\r
   IN UINT32        LowMemoryLength,\r
@@ -279,13 +302,14 @@ SetDmaProtectedRange (
 \r
   DEBUG ((DEBUG_INFO, "SetDmaProtectedRange(0x%lx) - [0x%x, 0x%x] [0x%lx, 0x%lx]\n", EngineMask, LowMemoryBase, LowMemoryLength, HighMemoryBase, HighMemoryLength));\r
 \r
-  for (Index = 0; Index < mVTdInfo->VTdEngineCount; Index++) {\r
+  for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) {\r
     if ((EngineMask & LShiftU64(1, Index)) == 0) {\r
       continue;\r
     }\r
-    DisablePmr ((UINTN)mVTdInfo->VTdEngineAddress[Index]);\r
+    DisablePmr ((UINTN)VTdInfo->VTdEngineAddress[Index]);\r
     Status = SetPmrRegion (\r
-               (UINTN)mVTdInfo->VTdEngineAddress[Index],\r
+               VTdInfo->HostAddressWidth,\r
+               (UINTN)VTdInfo->VTdEngineAddress[Index],\r
                LowMemoryBase,\r
                LowMemoryLength,\r
                HighMemoryBase,\r
@@ -294,7 +318,7 @@ SetDmaProtectedRange (
     if (EFI_ERROR(Status)) {\r
       return Status;\r
     }\r
-    Status = EnablePmr ((UINTN)mVTdInfo->VTdEngineAddress[Index]);\r
+    Status = EnablePmr ((UINTN)VTdInfo->VTdEngineAddress[Index]);\r
     if (EFI_ERROR(Status)) {\r
       return Status;\r
     }\r
@@ -306,25 +330,29 @@ SetDmaProtectedRange (
 /**\r
   Diable DMA protection.\r
 \r
+  @param VTdInfo            The VTd engine context information.\r
   @param EngineMask         The mask of the VTd engine to be accessed.\r
 \r
-  @retval DMA protection is disabled.\r
+  @retval EFI_SUCCESS DMA protection is disabled.\r
 **/\r
 EFI_STATUS\r
 DisableDmaProtection (\r
+  IN VTD_INFO      *VTdInfo,\r
   IN UINT64        EngineMask\r
   )\r
 {\r
   UINTN       Index;\r
   EFI_STATUS  Status;\r
 \r
-  DEBUG ((DEBUG_INFO, "DisableDmaProtection\n"));\r
+  DEBUG ((DEBUG_INFO, "DisableDmaProtection - 0x%lx\n", EngineMask));\r
+\r
+  for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) {\r
+    DEBUG ((DEBUG_INFO, "Disabling...%d\n", Index));\r
 \r
-  for (Index = 0; Index < mVTdInfo->VTdEngineCount; Index++) {\r
     if ((EngineMask & LShiftU64(1, Index)) == 0) {\r
       continue;\r
     }\r
-    Status = DisablePmr ((UINTN)mVTdInfo->VTdEngineAddress[Index]);\r
+    Status = DisablePmr ((UINTN)VTdInfo->VTdEngineAddress[Index]);\r
     if (EFI_ERROR(Status)) {\r
       return Status;\r
     }\r
@@ -332,3 +360,67 @@ DisableDmaProtection (
 \r
   return EFI_SUCCESS;\r
 }\r
+\r
+/**\r
+  Return if the PMR is enabled.\r
+\r
+  @param VtdUnitBaseAddress The base address of the VTd engine.\r
+\r
+  @retval TRUE  PMR is enabled.\r
+  @retval FALSE PMR is disabled or unsupported.\r
+**/\r
+BOOLEAN\r
+IsPmrEnabled (\r
+  IN UINTN         VtdUnitBaseAddress\r
+  )\r
+{\r
+  UINT32        Reg32;\r
+  VTD_CAP_REG   CapReg;\r
+\r
+  CapReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_CAP_REG);\r
+  if (CapReg.Bits.PLMR == 0 || CapReg.Bits.PHMR == 0) {\r
+    return FALSE;\r
+  }\r
+\r
+  Reg32 = MmioRead32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG);\r
+  if ((Reg32 & BIT0) == 0) {\r
+    return FALSE;\r
+  }\r
+\r
+  return TRUE;\r
+}\r
+\r
+/**\r
+  Return the mask of the VTd engine which is enabled.\r
+\r
+  @param VTdInfo            The VTd engine context information.\r
+  @param EngineMask         The mask of the VTd engine to be accessed.\r
+\r
+  @return the mask of the VTd engine which is enabled.\r
+**/\r
+UINT64\r
+GetDmaProtectionEnabledEngineMask (\r
+  IN VTD_INFO      *VTdInfo,\r
+  IN UINT64        EngineMask\r
+  )\r
+{\r
+  UINTN       Index;\r
+  BOOLEAN     Result;\r
+  UINT64      EnabledEngineMask;\r
+\r
+  DEBUG ((DEBUG_INFO, "GetDmaProtectionEnabledEngineMask - 0x%lx\n", EngineMask));\r
+\r
+  EnabledEngineMask = 0;\r
+  for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) {\r
+    if ((EngineMask & LShiftU64(1, Index)) == 0) {\r
+      continue;\r
+    }\r
+    Result = IsPmrEnabled ((UINTN)VTdInfo->VTdEngineAddress[Index]);\r
+    if (Result) {\r
+      EnabledEngineMask |= LShiftU64(1, Index);\r
+    }\r
+  }\r
+\r
+  DEBUG ((DEBUG_INFO, "EnabledEngineMask - 0x%lx\n", EnabledEngineMask));\r
+  return EnabledEngineMask;\r
+}\r
index 3fe6d65..240a6d2 100644 (file)
@@ -24,6 +24,7 @@
 #include <IndustryStandard/Vtd.h>\r
 #include <Ppi/IoMmu.h>\r
 #include <Ppi/VtdInfo.h>\r
+#include <Ppi/MemoryDiscovered.h>\r
 #include <Ppi/EndOfPeiPhase.h>\r
 \r
 #include "IntelVTdPmrPei.h"\r
 #define  TOTAL_DMA_BUFFER_SIZE    SIZE_4MB\r
 #define  TOTAL_DMA_BUFFER_SIZE_S3 SIZE_1MB\r
 \r
-EFI_ACPI_DMAR_HEADER              *mAcpiDmarTable;\r
-VTD_INFO                          *mVTdInfo;\r
-UINT64                            mEngineMask;\r
-UINTN                             mDmaBufferBase;\r
-UINTN                             mDmaBufferSize;\r
-UINTN                             mDmaBufferCurrentTop;\r
-UINTN                             mDmaBufferCurrentBottom;\r
+EFI_GUID mVTdInfoGuid = {\r
+  0x222f5e30, 0x5cd, 0x49c6, { 0x8a, 0xc, 0x36, 0xd6, 0x58, 0x41, 0xe0, 0x82 }\r
+};\r
+\r
+EFI_GUID mDmaBufferInfoGuid = {\r
+  0x7b624ec7, 0xfb67, 0x4f9c, { 0xb6, 0xb0, 0x4d, 0xfa, 0x9c, 0x88, 0x20, 0x39 }\r
+};\r
+\r
+typedef struct {\r
+  UINTN                             DmaBufferBase;\r
+  UINTN                             DmaBufferSize;\r
+  UINTN                             DmaBufferCurrentTop;\r
+  UINTN                             DmaBufferCurrentBottom;\r
+} DMA_BUFFER_INFO;\r
 \r
 #define MAP_INFO_SIGNATURE  SIGNATURE_32 ('D', 'M', 'A', 'P')\r
 typedef struct {\r
@@ -83,7 +91,6 @@ typedef struct {
               +------------------+ <=============== PLMR.Base (0)\r
 **/\r
 \r
-\r
 /**\r
   Set IOMMU attribute for a system memory.\r
 \r
@@ -149,8 +156,13 @@ PeiIoMmuMap (
   OUT    VOID                                       **Mapping\r
   )\r
 {\r
-  MAP_INFO   *MapInfo;\r
-  UINTN      Length;\r
+  MAP_INFO                    *MapInfo;\r
+  UINTN                       Length;\r
+  VOID                        *Hob;\r
+  DMA_BUFFER_INFO             *DmaBufferInfo;\r
+\r
+  Hob = GetFirstGuidHob (&mDmaBufferInfoGuid);\r
+  DmaBufferInfo = GET_GUID_HOB_DATA(Hob);\r
 \r
   if (Operation == EdkiiIoMmuOperationBusMasterCommonBuffer ||\r
       Operation == EdkiiIoMmuOperationBusMasterCommonBuffer64) {\r
@@ -160,18 +172,18 @@ PeiIoMmuMap (
   }\r
 \r
   DEBUG ((DEBUG_VERBOSE, "PeiIoMmuMap - HostAddress - 0x%x, NumberOfBytes - %x\n", HostAddress, *NumberOfBytes));\r
-  DEBUG ((DEBUG_VERBOSE, "  mDmaBufferCurrentTop - %x\n", mDmaBufferCurrentTop));\r
-  DEBUG ((DEBUG_VERBOSE, "  mDmaBufferCurrentBottom - %x\n", mDmaBufferCurrentBottom));\r
+  DEBUG ((DEBUG_VERBOSE, "  DmaBufferCurrentTop - %x\n", DmaBufferInfo->DmaBufferCurrentTop));\r
+  DEBUG ((DEBUG_VERBOSE, "  DmaBufferCurrentBottom - %x\n", DmaBufferInfo->DmaBufferCurrentBottom));\r
 \r
   Length = *NumberOfBytes + sizeof(MAP_INFO);\r
-  if (Length > mDmaBufferCurrentTop - mDmaBufferCurrentBottom) {\r
+  if (Length > DmaBufferInfo->DmaBufferCurrentTop - DmaBufferInfo->DmaBufferCurrentBottom) {\r
     DEBUG ((DEBUG_ERROR, "PeiIoMmuMap - OUT_OF_RESOURCE\n"));\r
     ASSERT (FALSE);\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
-  *DeviceAddress = mDmaBufferCurrentBottom;\r
-  mDmaBufferCurrentBottom += Length;\r
+  *DeviceAddress = DmaBufferInfo->DmaBufferCurrentBottom;\r
+  DmaBufferInfo->DmaBufferCurrentBottom += Length;\r
 \r
   MapInfo = (VOID *)(UINTN)(*DeviceAddress + *NumberOfBytes);\r
   MapInfo->Signature     = MAP_INFO_SIGNATURE;\r
@@ -216,16 +228,21 @@ PeiIoMmuUnmap (
   IN  VOID                                     *Mapping\r
   )\r
 {\r
-  MAP_INFO   *MapInfo;\r
-  UINTN      Length;\r
+  MAP_INFO                    *MapInfo;\r
+  UINTN                       Length;\r
+  VOID                        *Hob;\r
+  DMA_BUFFER_INFO             *DmaBufferInfo;\r
+\r
+  Hob = GetFirstGuidHob (&mDmaBufferInfoGuid);\r
+  DmaBufferInfo = GET_GUID_HOB_DATA(Hob);\r
 \r
   if (Mapping == NULL) {\r
     return EFI_SUCCESS;\r
   }\r
 \r
   DEBUG ((DEBUG_VERBOSE, "PeiIoMmuUnmap - Mapping - %x\n", Mapping));\r
-  DEBUG ((DEBUG_VERBOSE, "  mDmaBufferCurrentTop - %x\n", mDmaBufferCurrentTop));\r
-  DEBUG ((DEBUG_VERBOSE, "  mDmaBufferCurrentBottom - %x\n", mDmaBufferCurrentBottom));\r
+  DEBUG ((DEBUG_VERBOSE, "  DmaBufferCurrentTop - %x\n", DmaBufferInfo->DmaBufferCurrentTop));\r
+  DEBUG ((DEBUG_VERBOSE, "  DmaBufferCurrentBottom - %x\n", DmaBufferInfo->DmaBufferCurrentBottom));\r
 \r
   MapInfo = Mapping;\r
   ASSERT (MapInfo->Signature == MAP_INFO_SIGNATURE);\r
@@ -246,8 +263,8 @@ PeiIoMmuUnmap (
   }\r
 \r
   Length = MapInfo->NumberOfBytes + sizeof(MAP_INFO);\r
-  if (mDmaBufferCurrentBottom == MapInfo->DeviceAddress + Length) {\r
-    mDmaBufferCurrentBottom -= Length;\r
+  if (DmaBufferInfo->DmaBufferCurrentBottom == MapInfo->DeviceAddress + Length) {\r
+    DmaBufferInfo->DmaBufferCurrentBottom -= Length;\r
   }\r
 \r
   return EFI_SUCCESS;\r
@@ -282,20 +299,25 @@ PeiIoMmuAllocateBuffer (
   IN     UINT64                                   Attributes\r
   )\r
 {\r
-  UINTN  Length;\r
+  UINTN                       Length;\r
+  VOID                        *Hob;\r
+  DMA_BUFFER_INFO             *DmaBufferInfo;\r
+\r
+  Hob = GetFirstGuidHob (&mDmaBufferInfoGuid);\r
+  DmaBufferInfo = GET_GUID_HOB_DATA(Hob);\r
 \r
   DEBUG ((DEBUG_VERBOSE, "PeiIoMmuAllocateBuffer - page - %x\n", Pages));\r
-  DEBUG ((DEBUG_VERBOSE, "  mDmaBufferCurrentTop - %x\n", mDmaBufferCurrentTop));\r
-  DEBUG ((DEBUG_VERBOSE, "  mDmaBufferCurrentBottom - %x\n", mDmaBufferCurrentBottom));\r
+  DEBUG ((DEBUG_VERBOSE, "  DmaBufferCurrentTop - %x\n", DmaBufferInfo->DmaBufferCurrentTop));\r
+  DEBUG ((DEBUG_VERBOSE, "  DmaBufferCurrentBottom - %x\n", DmaBufferInfo->DmaBufferCurrentBottom));\r
 \r
   Length = EFI_PAGES_TO_SIZE(Pages);\r
-  if (Length > mDmaBufferCurrentTop - mDmaBufferCurrentBottom) {\r
+  if (Length > DmaBufferInfo->DmaBufferCurrentTop - DmaBufferInfo->DmaBufferCurrentBottom) {\r
     DEBUG ((DEBUG_ERROR, "PeiIoMmuAllocateBuffer - OUT_OF_RESOURCE\n"));\r
     ASSERT (FALSE);\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
-  *HostAddress = (VOID *)(UINTN)(mDmaBufferCurrentTop - Length);\r
-  mDmaBufferCurrentTop -= Length;\r
+  *HostAddress = (VOID *)(UINTN)(DmaBufferInfo->DmaBufferCurrentTop - Length);\r
+  DmaBufferInfo->DmaBufferCurrentTop -= Length;\r
 \r
   DEBUG ((DEBUG_VERBOSE, "PeiIoMmuAllocateBuffer - allocate - %x\n", *HostAddress));\r
   return EFI_SUCCESS;\r
@@ -321,15 +343,20 @@ PeiIoMmuFreeBuffer (
   IN  VOID                                     *HostAddress\r
   )\r
 {\r
-  UINTN  Length;\r
+  UINTN                       Length;\r
+  VOID                        *Hob;\r
+  DMA_BUFFER_INFO             *DmaBufferInfo;\r
+\r
+  Hob = GetFirstGuidHob (&mDmaBufferInfoGuid);\r
+  DmaBufferInfo = GET_GUID_HOB_DATA(Hob);\r
 \r
   DEBUG ((DEBUG_VERBOSE, "PeiIoMmuFreeBuffer - page - %x, HostAddr - %x\n", Pages, HostAddress));\r
-  DEBUG ((DEBUG_VERBOSE, "  mDmaBufferCurrentTop - %x\n", mDmaBufferCurrentTop));\r
-  DEBUG ((DEBUG_VERBOSE, "  mDmaBufferCurrentBottom - %x\n", mDmaBufferCurrentBottom));\r
+  DEBUG ((DEBUG_VERBOSE, "  DmaBufferCurrentTop - %x\n", DmaBufferInfo->DmaBufferCurrentTop));\r
+  DEBUG ((DEBUG_VERBOSE, "  DmaBufferCurrentBottom - %x\n", DmaBufferInfo->DmaBufferCurrentBottom));\r
 \r
   Length = EFI_PAGES_TO_SIZE(Pages);\r
-  if ((UINTN)HostAddress == mDmaBufferCurrentTop) {\r
-    mDmaBufferCurrentTop += Length;\r
+  if ((UINTN)HostAddress == DmaBufferInfo->DmaBufferCurrentTop) {\r
+    DmaBufferInfo->DmaBufferCurrentTop += Length;\r
   }\r
 \r
   return EFI_SUCCESS;\r
@@ -506,6 +533,7 @@ GetTopMemory (
 /**\r
   Initialize DMA protection.\r
 \r
+  @param VTdInfo        The VTd engine context information.\r
   @param DmaBufferSize  the DMA buffer size\r
   @param DmaBufferBase  the DMA buffer base\r
 \r
@@ -514,8 +542,9 @@ GetTopMemory (
 **/\r
 EFI_STATUS\r
 InitDmaProtection (\r
-  IN   UINTN  DmaBufferSize,\r
-  OUT  UINTN  *DmaBufferBase\r
+  IN   VTD_INFO                    *VTdInfo,\r
+  IN   UINTN                       DmaBufferSize,\r
+  OUT  UINTN                       *DmaBufferBase\r
   )\r
 {\r
   EFI_STATUS                  Status;\r
@@ -537,8 +566,8 @@ InitDmaProtection (
 \r
   ASSERT (PhitHob->EfiMemoryBottom < PhitHob->EfiMemoryTop);\r
 \r
-  LowMemoryAlignment = GetLowMemoryAlignment (mEngineMask);\r
-  HighMemoryAlignment = GetHighMemoryAlignment (mEngineMask);\r
+  LowMemoryAlignment = GetLowMemoryAlignment (VTdInfo, VTdInfo->EngineMask);\r
+  HighMemoryAlignment = GetHighMemoryAlignment (VTdInfo, VTdInfo->EngineMask);\r
   if (LowMemoryAlignment < HighMemoryAlignment) {\r
     MemoryAlignment = (UINTN)HighMemoryAlignment;\r
   } else {\r
@@ -558,12 +587,13 @@ InitDmaProtection (
   HighTop = GetTopMemory ();\r
 \r
   Status = SetDmaProtectedRange (\r
-               mEngineMask,\r
-               (UINT32)LowBottom,\r
-               (UINT32)(LowTop - LowBottom),\r
-               HighBottom,\r
-               HighTop - HighBottom\r
-               );\r
+             VTdInfo,\r
+             VTdInfo->EngineMask,\r
+             (UINT32)LowBottom,\r
+             (UINT32)(LowTop - LowBottom),\r
+             HighBottom,\r
+             HighTop - HighBottom\r
+             );\r
 \r
   if (EFI_ERROR(Status)) {\r
     FreePages ((VOID *)*DmaBufferBase, EFI_SIZE_TO_PAGES(DmaBufferSize));\r
@@ -573,542 +603,191 @@ InitDmaProtection (
 }\r
 \r
 /**\r
-  Dump DMAR DeviceScopeEntry.\r
+  Initializes the Intel VTd Info.\r
+\r
+  @retval EFI_SUCCESS            Usb bot driver is successfully initialized.\r
+  @retval EFI_OUT_OF_RESOURCES   Can't initialize the driver.\r
 \r
-  @param[in]  DmarDeviceScopeEntry  DMAR DeviceScopeEntry\r
 **/\r
-VOID\r
-DumpDmarDeviceScopeEntry (\r
-  IN EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER     *DmarDeviceScopeEntry\r
+EFI_STATUS\r
+InitVTdInfo (\r
+  VOID\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
+  EFI_STATUS                  Status;\r
+  EFI_ACPI_DMAR_HEADER        *AcpiDmarTable;\r
+  VOID                        *Hob;\r
 \r
-/**\r
-  Dump DMAR RMRR table.\r
+  Status = PeiServicesLocatePpi (\r
+             &gEdkiiVTdInfoPpiGuid,\r
+             0,\r
+             NULL,\r
+             (VOID **)&AcpiDmarTable\r
+             );\r
+  ASSERT_EFI_ERROR(Status);\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
+  DumpAcpiDMAR (AcpiDmarTable);\r
 \r
-  if (Rmrr == NULL) {\r
-    return;\r
+  //\r
+  // Clear old VTdInfo Hob.\r
+  //\r
+  Hob = GetFirstGuidHob (&mVTdInfoGuid);\r
+  if (Hob != NULL) {\r
+    ZeroMem (&((EFI_HOB_GUID_TYPE *)Hob)->Name, sizeof(EFI_GUID));\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
+  // Get DMAR information to local VTdInfo\r
+  //\r
+  Status = ParseDmarAcpiTableDrhd (AcpiDmarTable);\r
+  if (EFI_ERROR(Status)) {\r
+    return Status;\r
   }\r
 \r
-  DEBUG ((DEBUG_INFO,\r
-    "  ***************************************************************************\n\n"\r
-    ));\r
+  //\r
+  // NOTE: Do not parse RMRR here, because RMRR may cause PMR programming.\r
+  //\r
 \r
-  return;\r
+  return EFI_SUCCESS;\r
 }\r
 \r
 /**\r
-  Dump DMAR DRHD table.\r
+  Initializes the Intel VTd PMR for all memory.\r
+\r
+  @retval EFI_SUCCESS            Usb bot driver is successfully initialized.\r
+  @retval EFI_OUT_OF_RESOURCES   Can't initialize the driver.\r
 \r
-  @param[in]  Drhd  DMAR DRHD table\r
 **/\r
-VOID\r
-DumpDmarDrhd (\r
-  IN EFI_ACPI_DMAR_DRHD_HEADER *Drhd\r
+EFI_STATUS\r
+InitVTdPmrForAll (\r
+  VOID\r
   )\r
 {\r
-  EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER       *DmarDeviceScopeEntry;\r
-  INTN                                    DrhdLen;\r
+  EFI_STATUS                  Status;\r
+  VOID                        *Hob;\r
+  VTD_INFO                    *VTdInfo;\r
+  UINTN                       LowBottom;\r
+  UINTN                       LowTop;\r
+  UINTN                       HighBottom;\r
+  UINT64                      HighTop;\r
 \r
-  if (Drhd == NULL) {\r
-    return;\r
-  }\r
+  Hob = GetFirstGuidHob (&mVTdInfoGuid);\r
+  VTdInfo = GET_GUID_HOB_DATA(Hob);\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
+  LowBottom = 0;\r
+  LowTop = 0;\r
+  HighBottom = 0;\r
+  HighTop = LShiftU64 (1, VTdInfo->HostAddressWidth);\r
 \r
-  DEBUG ((DEBUG_INFO,\r
-    "  ***************************************************************************\n\n"\r
-    ));\r
+  Status = SetDmaProtectedRange (\r
+             VTdInfo,\r
+             VTdInfo->EngineMask,\r
+             (UINT32)LowBottom,\r
+             (UINT32)(LowTop - LowBottom),\r
+             HighBottom,\r
+             HighTop - HighBottom\r
+             );\r
 \r
-  return;\r
+  return Status;\r
 }\r
 \r
 /**\r
-  Dump DMAR ACPI table.\r
+  Initializes the Intel VTd PMR for DMA buffer.\r
+\r
+  @retval EFI_SUCCESS            Usb bot driver is successfully initialized.\r
+  @retval EFI_OUT_OF_RESOURCES   Can't initialize the driver.\r
 \r
-  @param[in]  Dmar  DMAR ACPI table\r
 **/\r
-VOID\r
-DumpAcpiDMAR (\r
-  IN EFI_ACPI_DMAR_HEADER  *Dmar\r
+EFI_STATUS\r
+InitVTdPmrForDma (\r
+  VOID\r
   )\r
 {\r
-  EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;\r
-  INTN                  DmarLen;\r
+  EFI_STATUS                  Status;\r
+  VOID                        *Hob;\r
+  VTD_INFO                    *VTdInfo;\r
+  DMA_BUFFER_INFO             *DmaBufferInfo;\r
 \r
-  if (Dmar == NULL) {\r
-    return;\r
-  }\r
+  Hob = GetFirstGuidHob (&mVTdInfoGuid);\r
+  VTdInfo = GET_GUID_HOB_DATA(Hob);\r
 \r
   //\r
-  // Dump Dmar table\r
+  // If there is RMRR memory, parse it here.\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
+  ParseDmarAcpiTableRmrr (VTdInfo);\r
 \r
-/**\r
-  Get VTd engine number.\r
+  Hob = GetFirstGuidHob (&mDmaBufferInfoGuid);\r
+  DmaBufferInfo = GET_GUID_HOB_DATA(Hob);\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
+  DEBUG ((DEBUG_INFO, " DmaBufferSize : 0x%x\n", DmaBufferInfo->DmaBufferSize));\r
+  //\r
+  // Find a pre-memory in resource hob as DMA buffer\r
+  // Mark PEI memory to be DMA protected.\r
+  //\r
+  Status = InitDmaProtection (VTdInfo, DmaBufferInfo->DmaBufferSize, &DmaBufferInfo->DmaBufferBase);\r
+  if (EFI_ERROR(Status)) {\r
+    return Status;\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
+  DEBUG ((DEBUG_INFO, " DmaBufferBase : 0x%x\n", DmaBufferInfo->DmaBufferBase));\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
+  DmaBufferInfo->DmaBufferCurrentTop = DmaBufferInfo->DmaBufferBase + DmaBufferInfo->DmaBufferSize;\r
+  DmaBufferInfo->DmaBufferCurrentBottom = DmaBufferInfo->DmaBufferBase;\r
 \r
   //\r
-  // Initialize the engine mask to all.\r
+  // Install PPI.\r
   //\r
-  mEngineMask = LShiftU64 (1, VtdUnitNumber) - 1;\r
+  Status = PeiServicesInstallPpi (&mIoMmuPpiList);\r
+  ASSERT_EFI_ERROR(Status);\r
 \r
-  return EFI_SUCCESS;\r
+  return Status;\r
 }\r
 \r
 /**\r
-  Return the VTd engine index according to the Segment and DevScopeEntry.\r
+  This function handles S3 resume task at the end of PEI\r
 \r
-  @param Segment         The segment of the VTd engine\r
-  @param DevScopeEntry   The DevScopeEntry of the VTd engine\r
+  @param[in] PeiServices    Pointer to PEI Services Table.\r
+  @param[in] NotifyDesc     Pointer to the descriptor for the Notification event that\r
+                            caused this function to execute.\r
+  @param[in] Ppi            Pointer to the PPI data associated with this function.\r
 \r
-  @return The VTd engine index according to the Segment and DevScopeEntry.\r
-  @retval -1  The VTd engine is not found.\r
+  @retval EFI_STATUS        Always return EFI_SUCCESS\r
 **/\r
-UINTN\r
-GetVTdEngineFromDevScopeEntry (\r
-  IN  UINT16                                      Segment,\r
-  IN  EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DevScopeEntry\r
+EFI_STATUS\r
+EFIAPI\r
+S3EndOfPeiNotify(\r
+  IN EFI_PEI_SERVICES          **PeiServices,\r
+  IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc,\r
+  IN VOID                      *Ppi\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
+  VOID                        *Hob;\r
+  VTD_INFO                    *VTdInfo;\r
+  UINT64                      EngineMask;\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
+  DEBUG((DEBUG_INFO, "VTdPmr S3EndOfPeiNotify\n"));\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
+  if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT1) == 0) {\r
+    Hob = GetFirstGuidHob (&mVTdInfoGuid);\r
+    if (Hob == NULL) {\r
+      return EFI_SUCCESS;\r
     }\r
+    VTdInfo = GET_GUID_HOB_DATA(Hob);\r
 \r
-    DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)DmarDevScopeEntry + DmarDevScopeEntry->Length);\r
+    EngineMask = LShiftU64 (1, VTdInfo->VTdEngineCount) - 1;\r
+    DisableDmaProtection (VTdInfo, EngineMask);\r
   }\r
+  return EFI_SUCCESS;\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
+EFI_PEI_NOTIFY_DESCRIPTOR mS3EndOfPeiNotifyDesc = {\r
+  (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
+  &gEfiEndOfPeiSignalPpiGuid,\r
+  S3EndOfPeiNotify\r
+};\r
 \r
 /**\r
-  This function handles S3 resume task at the end of PEI\r
+  This function handles VTd engine setup\r
 \r
   @param[in] PeiServices    Pointer to PEI Services Table.\r
   @param[in] NotifyDesc     Pointer to the descriptor for the Notification event that\r
@@ -1119,27 +798,80 @@ ParseDmarAcpiTableRmrr (
 **/\r
 EFI_STATUS\r
 EFIAPI\r
-S3EndOfPeiNotify(\r
+VTdInfoNotify (\r
   IN EFI_PEI_SERVICES          **PeiServices,\r
   IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc,\r
   IN VOID                      *Ppi\r
   )\r
 {\r
-  UINT64                      EngineMask;\r
+  EFI_STATUS                  Status;\r
+  VOID                        *MemoryDiscovered;\r
+  UINT64                      EnabledEngineMask;\r
+  VOID                        *Hob;\r
+  VTD_INFO                    *VTdInfo;\r
+  BOOLEAN                     MemoryInitialized;\r
 \r
-  DEBUG((DEBUG_INFO, "VTdPmr S3EndOfPeiNotify\n"));\r
+  DEBUG ((DEBUG_INFO, "VTdInfoNotify\n"));\r
+\r
+  //\r
+  // Check if memory is initialized.\r
+  //\r
+  MemoryInitialized = FALSE;\r
+  Status = PeiServicesLocatePpi (\r
+             &gEfiPeiMemoryDiscoveredPpiGuid,\r
+             0,\r
+             NULL,\r
+             &MemoryDiscovered\r
+             );\r
+  if (!EFI_ERROR(Status)) {\r
+    MemoryInitialized = TRUE;\r
+  }\r
+\r
+  DEBUG ((DEBUG_INFO, "MemoryInitialized - %x\n", MemoryInitialized));\r
+\r
+  if (!MemoryInitialized) {\r
+    //\r
+    // If the memory is not initialized,\r
+    // Protect all system memory\r
+    //\r
+    InitVTdInfo ();\r
+    InitVTdPmrForAll ();\r
+  } else {\r
+    //\r
+    // If the memory is initialized,\r
+    // Allocate DMA buffer and protect rest system memory\r
+    //\r
+\r
+    //\r
+    // NOTE: We need reinit VTdInfo because previous information might be overriden.\r
+    //\r
+    InitVTdInfo ();\r
+\r
+    Hob = GetFirstGuidHob (&mVTdInfoGuid);\r
+    VTdInfo = GET_GUID_HOB_DATA(Hob);\r
+\r
+    //\r
+    // NOTE: We need check if PMR is enabled or not.\r
+    //\r
+    EnabledEngineMask = GetDmaProtectionEnabledEngineMask (VTdInfo, VTdInfo->EngineMask);\r
+    if (EnabledEngineMask != 0) {\r
+      EnableVTdTranslationProtection (VTdInfo, EnabledEngineMask);\r
+      DisableDmaProtection (VTdInfo, EnabledEngineMask);\r
+    }\r
+    InitVTdPmrForDma ();\r
+    if (EnabledEngineMask != 0) {\r
+      DisableVTdTranslationProtection (VTdInfo, EnabledEngineMask);\r
+    }\r
 \r
-  if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT1) == 0) {\r
-    EngineMask = LShiftU64 (1, mVTdInfo->VTdEngineCount) - 1;\r
-    DisableDmaProtection (EngineMask);\r
   }\r
+\r
   return EFI_SUCCESS;\r
 }\r
 \r
-EFI_PEI_NOTIFY_DESCRIPTOR mS3EndOfPeiNotifyDesc = {\r
+EFI_PEI_NOTIFY_DESCRIPTOR mVTdInfoNotifyDesc = {\r
   (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
-  &gEfiEndOfPeiSignalPpiGuid,\r
-  S3EndOfPeiNotify\r
+  &gEdkiiVTdInfoPpiGuid,\r
+  VTdInfoNotify\r
 };\r
 \r
 /**\r
@@ -1161,71 +893,40 @@ IntelVTdPmrInitialize (
 {\r
   EFI_STATUS                  Status;\r
   EFI_BOOT_MODE               BootMode;\r
+  DMA_BUFFER_INFO             *DmaBufferInfo;\r
+\r
+  DEBUG ((DEBUG_INFO, "IntelVTdPmrInitialize\n"));\r
 \r
   if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT0) == 0) {\r
     return EFI_UNSUPPORTED;\r
   }\r
 \r
-  PeiServicesGetBootMode (&BootMode);\r
-\r
-  Status = PeiServicesLocatePpi (\r
-             &gEdkiiVTdInfoPpiGuid,\r
-             0,\r
-             NULL,\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
+  DmaBufferInfo = BuildGuidHob (&mDmaBufferInfoGuid, sizeof(DMA_BUFFER_INFO));\r
+  ASSERT(DmaBufferInfo != NULL);\r
+  if (DmaBufferInfo == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
   }\r
+  ZeroMem (DmaBufferInfo, sizeof(DMA_BUFFER_INFO));\r
 \r
-  //\r
-  // If there is RMRR memory, parse it here.\r
-  //\r
-  ParseDmarAcpiTableRmrr ();\r
+  PeiServicesGetBootMode (&BootMode);\r
 \r
   if (BootMode == BOOT_ON_S3_RESUME) {\r
-    mDmaBufferSize = TOTAL_DMA_BUFFER_SIZE_S3;\r
+    DmaBufferInfo->DmaBufferSize = TOTAL_DMA_BUFFER_SIZE_S3;\r
   } else {\r
-    mDmaBufferSize = TOTAL_DMA_BUFFER_SIZE;\r
-  }\r
-  DEBUG ((DEBUG_INFO, " DmaBufferSize : 0x%x\n", mDmaBufferSize));\r
-\r
-  //\r
-  // Find a pre-memory in resource hob as DMA buffer\r
-  // Mark PEI memory to be DMA protected.\r
-  //\r
-  Status = InitDmaProtection (mDmaBufferSize, &mDmaBufferBase);\r
-  if (EFI_ERROR(Status)) {\r
-    return Status;\r
+    DmaBufferInfo->DmaBufferSize = TOTAL_DMA_BUFFER_SIZE;\r
   }\r
 \r
-  DEBUG ((DEBUG_INFO, " DmaBufferBase : 0x%x\n", mDmaBufferBase));\r
-\r
-  mDmaBufferCurrentTop = mDmaBufferBase + mDmaBufferSize;\r
-  mDmaBufferCurrentBottom = mDmaBufferBase;\r
-\r
-  //\r
-  // Install PPI.\r
-  //\r
-  Status = PeiServicesInstallPpi (&mIoMmuPpiList);\r
-  ASSERT_EFI_ERROR(Status);\r
+  Status = PeiServicesNotifyPpi (&mVTdInfoNotifyDesc);\r
+  ASSERT_EFI_ERROR (Status);\r
 \r
   //\r
-  // Register EndOfPei Notify for S3 to run FSP NotifyPhase\r
+  // Register EndOfPei Notify for S3\r
   //\r
   if (BootMode == BOOT_ON_S3_RESUME) {\r
     Status = PeiServicesNotifyPpi (&mS3EndOfPeiNotifyDesc);\r
     ASSERT_EFI_ERROR (Status);\r
   }\r
 \r
-  return Status;\r
+  return EFI_SUCCESS;\r
 }\r
 \r
index 720f5d4..499119d 100644 (file)
@@ -16,6 +16,8 @@
 #define __DMA_ACCESS_LIB_H__\r
 \r
 typedef struct {\r
+  EFI_ACPI_DMAR_HEADER                    *AcpiDmarTable;\r
+  UINT64                                  EngineMask;\r
   UINT8                                   HostAddressWidth;\r
   UINTN                                   VTdEngineCount;\r
   UINT64                                  VTdEngineAddress[1];\r
@@ -24,6 +26,7 @@ typedef struct {
 /**\r
   Set DMA protected region.\r
 \r
+  @param VTdInfo            The VTd engine context information.\r
   @param EngineMask         The mask of the VTd engine to be accessed.\r
   @param LowMemoryBase      The protected low memory region base.\r
   @param LowMemoryLength    The protected low memory region length.\r
@@ -35,6 +38,7 @@ typedef struct {
 **/\r
 EFI_STATUS\r
 SetDmaProtectedRange (\r
+  IN VTD_INFO      *VTdInfo,\r
   IN UINT64        EngineMask,\r
   IN UINT32        LowMemoryBase,\r
   IN UINT32        LowMemoryLength,\r
@@ -45,38 +49,127 @@ SetDmaProtectedRange (
 /**\r
   Diable DMA protection.\r
 \r
+  @param VTdInfo            The VTd engine context information.\r
   @param EngineMask         The mask of the VTd engine to be accessed.\r
 \r
   @retval DMA protection is disabled.\r
 **/\r
 EFI_STATUS\r
 DisableDmaProtection (\r
+  IN VTD_INFO      *VTdInfo,\r
+  IN UINT64        EngineMask\r
+  );\r
+\r
+/**\r
+  Return if the DMA protection is enabled.\r
+\r
+  @param VTdInfo            The VTd engine context information.\r
+  @param EngineMask         The mask of the VTd engine to be accessed.\r
+\r
+  @retval TRUE  DMA protection is enabled in at least one VTd engine.\r
+  @retval FALSE DMA protection is disabled in all VTd engines.\r
+**/\r
+UINT64\r
+GetDmaProtectionEnabledEngineMask (\r
+  IN VTD_INFO      *VTdInfo,\r
   IN UINT64        EngineMask\r
   );\r
 \r
 /**\r
   Get protected low memory alignment.\r
 \r
+  @param VTdInfo            The VTd engine context information.\r
   @param EngineMask         The mask of the VTd engine to be accessed.\r
 \r
   @return protected low memory alignment.\r
 **/\r
 UINT32\r
 GetLowMemoryAlignment (\r
+  IN VTD_INFO      *VTdInfo,\r
   IN UINT64        EngineMask\r
   );\r
 \r
 /**\r
   Get protected high memory alignment.\r
 \r
+  @param VTdInfo            The VTd engine context information.\r
   @param EngineMask         The mask of the VTd engine to be accessed.\r
 \r
   @return protected high memory alignment.\r
 **/\r
 UINT64\r
 GetHighMemoryAlignment (\r
+  IN VTD_INFO      *VTdInfo,\r
+  IN UINT64        EngineMask\r
+  );\r
+\r
+/**\r
+  Enable VTd translation table protection.\r
+\r
+  @param VTdInfo            The VTd engine context information.\r
+  @param EngineMask         The mask of the VTd engine to be accessed.\r
+**/\r
+VOID\r
+EnableVTdTranslationProtection (\r
+  IN VTD_INFO      *VTdInfo,\r
+  IN UINT64        EngineMask\r
+  );\r
+\r
+/**\r
+  Disable VTd translation table protection.\r
+\r
+  @param VTdInfo            The VTd engine context information.\r
+  @param EngineMask         The mask of the VTd engine to be accessed.\r
+**/\r
+VOID\r
+DisableVTdTranslationProtection (\r
+  IN VTD_INFO      *VTdInfo,\r
   IN UINT64        EngineMask\r
   );\r
 \r
+/**\r
+  Parse DMAR DRHD table.\r
+\r
+  @param[in]  AcpiDmarTable  DMAR ACPI table\r
+\r
+  @return EFI_SUCCESS  The DMAR DRHD table is parsed.\r
+**/\r
+EFI_STATUS\r
+ParseDmarAcpiTableDrhd (\r
+  IN EFI_ACPI_DMAR_HEADER                    *AcpiDmarTable\r
+  );\r
+\r
+/**\r
+  Parse DMAR DRHD table.\r
+\r
+  @param VTdInfo            The VTd engine context information.\r
+**/\r
+VOID\r
+ParseDmarAcpiTableRmrr (\r
+  IN VTD_INFO                    *VTdInfo\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
+/**\r
+  Get the highest memory.\r
+\r
+  @return the highest memory.\r
+**/\r
+UINT64\r
+GetTopMemory (\r
+  VOID\r
+  );\r
+\r
+extern EFI_GUID mVTdInfoGuid;\r
+\r
 #endif\r
 \r
index 4d0e187..e6d0323 100644 (file)
@@ -33,6 +33,8 @@
   IntelVTdPmrPei.c\r
   IntelVTdPmrPei.h\r
   IntelVTdPmr.c\r
+  DmarTable.c\r
+  VtdReg.c\r
 \r
 [LibraryClasses]\r
   DebugLib\r
   PeiServicesLib\r
   HobLib\r
   IoLib\r
+  CacheMaintenanceLib\r
 \r
 [Ppis]\r
-  gEdkiiIoMmuPpiGuid            ## PRODUCES\r
-  gEdkiiVTdInfoPpiGuid          ## CONSUMES\r
-  gEfiEndOfPeiSignalPpiGuid     ## CONSUMES\r
+  gEdkiiIoMmuPpiGuid                  ## PRODUCES\r
+  gEdkiiVTdInfoPpiGuid                ## CONSUMES\r
+  gEfiPeiMemoryDiscoveredPpiGuid      ## CONSUMES\r
+  gEfiEndOfPeiSignalPpiGuid           ## CONSUMES\r
 \r
 [Pcd]\r
   gIntelSiliconPkgTokenSpaceGuid.PcdVTdPolicyPropertyMask   ## CONSUMES\r
 \r
 [Depex]\r
-  gEfiPeiMemoryDiscoveredPpiGuid AND\r
   gEfiPeiMasterBootModePpiGuid AND\r
   gEdkiiVTdInfoPpiGuid\r
 \r
diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/VtdReg.c b/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/VtdReg.c
new file mode 100644 (file)
index 0000000..888905d
--- /dev/null
@@ -0,0 +1,293 @@
+/** @file\r
+\r
+  Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>\r
+\r
+  This program and the accompanying materials are licensed and made available under\r
+  the terms and conditions of the BSD License which accompanies this distribution.\r
+  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 <PiPei.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/IoLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/CacheMaintenanceLib.h>\r
+#include <IndustryStandard/Vtd.h>\r
+#include <Ppi/VtdInfo.h>\r
+\r
+#include "IntelVTdPmrPei.h"\r
+\r
+/**\r
+  Flush VTD page table and context table memory.\r
+\r
+  This action is to make sure the IOMMU engine can get final data in memory.\r
+\r
+  @param[in]  Base              The base address of memory to be flushed.\r
+  @param[in]  Size              The size of memory in bytes to be flushed.\r
+**/\r
+VOID\r
+FlushPageTableMemory (\r
+  IN UINTN  Base,\r
+  IN UINTN  Size\r
+  )\r
+{\r
+  WriteBackDataCacheRange ((VOID *)Base, Size);\r
+}\r
+\r
+/**\r
+  Flush VTd engine write buffer.\r
+\r
+  @param VtdUnitBaseAddress The base address of the VTd engine.\r
+**/\r
+VOID\r
+FlushWriteBuffer (\r
+  IN UINTN  VtdUnitBaseAddress\r
+  )\r
+{\r
+  UINT32      Reg32;\r
+  VTD_CAP_REG CapReg;\r
+\r
+  CapReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_CAP_REG);\r
+\r
+  if (CapReg.Bits.RWBF != 0) {\r
+    Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);\r
+    MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Reg32 | B_GMCD_REG_WBF);\r
+    do {\r
+      Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);\r
+    } while ((Reg32 & B_GSTS_REG_WBF) != 0);\r
+  }\r
+}\r
+\r
+/**\r
+  Invalidate VTd context cache.\r
+\r
+  @param VtdUnitBaseAddress The base address of the VTd engine.\r
+**/\r
+EFI_STATUS\r
+InvalidateContextCache (\r
+  IN UINTN  VtdUnitBaseAddress\r
+  )\r
+{\r
+  UINT64  Reg64;\r
+\r
+  Reg64 = MmioRead64 (VtdUnitBaseAddress + R_CCMD_REG);\r
+  if ((Reg64 & B_CCMD_REG_ICC) != 0) {\r
+    DEBUG ((DEBUG_ERROR,"ERROR: InvalidateContextCache: B_CCMD_REG_ICC is set for VTD(%x)\n",VtdUnitBaseAddress));\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  Reg64 &= ((~B_CCMD_REG_ICC) & (~B_CCMD_REG_CIRG_MASK));\r
+  Reg64 |= (B_CCMD_REG_ICC | V_CCMD_REG_CIRG_GLOBAL);\r
+  MmioWrite64 (VtdUnitBaseAddress + R_CCMD_REG, Reg64);\r
+\r
+  do {\r
+    Reg64 = MmioRead64 (VtdUnitBaseAddress + R_CCMD_REG);\r
+  } while ((Reg64 & B_CCMD_REG_ICC) != 0);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Invalidate VTd IOTLB.\r
+\r
+  @param VtdUnitBaseAddress The base address of the VTd engine.\r
+**/\r
+EFI_STATUS\r
+InvalidateIOTLB (\r
+  IN UINTN  VtdUnitBaseAddress\r
+  )\r
+{\r
+  UINT64       Reg64;\r
+  VTD_ECAP_REG ECapReg;\r
+\r
+  ECapReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_ECAP_REG);\r
+\r
+  Reg64 = MmioRead64 (VtdUnitBaseAddress + (ECapReg.Bits.IRO * 16) + R_IOTLB_REG);\r
+  if ((Reg64 & B_IOTLB_REG_IVT) != 0) {\r
+    DEBUG ((DEBUG_ERROR,"ERROR: InvalidateIOTLB: B_IOTLB_REG_IVT is set for VTD(%x)\n", VtdUnitBaseAddress));\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  Reg64 &= ((~B_IOTLB_REG_IVT) & (~B_IOTLB_REG_IIRG_MASK));\r
+  Reg64 |= (B_IOTLB_REG_IVT | V_IOTLB_REG_IIRG_GLOBAL);\r
+  MmioWrite64 (VtdUnitBaseAddress + (ECapReg.Bits.IRO * 16) + R_IOTLB_REG, Reg64);\r
+\r
+  do {\r
+    Reg64 = MmioRead64 (VtdUnitBaseAddress + (ECapReg.Bits.IRO * 16) + R_IOTLB_REG);\r
+  } while ((Reg64 & B_IOTLB_REG_IVT) != 0);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Enable DMAR translation.\r
+\r
+  @param VtdUnitBaseAddress The base address of the VTd engine.\r
+  @param RootEntryTable     The address of the VTd RootEntryTable.\r
+\r
+  @retval EFI_SUCCESS           DMAR translation is enabled.\r
+  @retval EFI_DEVICE_ERROR      DMAR translation is not enabled.\r
+**/\r
+EFI_STATUS\r
+EnableDmar (\r
+  IN UINTN  VtdUnitBaseAddress,\r
+  IN UINTN  RootEntryTable\r
+  )\r
+{\r
+  UINT32    Reg32;\r
+\r
+  DEBUG((DEBUG_INFO, ">>>>>>EnableDmar() for engine [%x] \n", VtdUnitBaseAddress));\r
+\r
+  DEBUG((DEBUG_INFO, "RootEntryTable 0x%x \n", RootEntryTable));\r
+  MmioWrite64 (VtdUnitBaseAddress + R_RTADDR_REG, (UINT64)(UINTN)RootEntryTable);\r
+\r
+  MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, B_GMCD_REG_SRTP);\r
+\r
+  DEBUG((DEBUG_INFO, "EnableDmar: waiting for RTPS bit to be set... \n"));\r
+  do {\r
+    Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);\r
+  } while((Reg32 & B_GSTS_REG_RTPS) == 0);\r
+\r
+  //\r
+  // Init DMAr Fault Event and Data registers\r
+  //\r
+  Reg32 = MmioRead32 (VtdUnitBaseAddress + R_FEDATA_REG);\r
+\r
+  //\r
+  // Write Buffer Flush before invalidation\r
+  //\r
+  FlushWriteBuffer (VtdUnitBaseAddress);\r
+\r
+  //\r
+  // Invalidate the context cache\r
+  //\r
+  InvalidateContextCache (VtdUnitBaseAddress);\r
+\r
+  //\r
+  // Invalidate the IOTLB cache\r
+  //\r
+  InvalidateIOTLB (VtdUnitBaseAddress);\r
+\r
+  //\r
+  // Enable VTd\r
+  //\r
+  MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, B_GMCD_REG_TE);\r
+  DEBUG((DEBUG_INFO, "EnableDmar: Waiting B_GSTS_REG_TE ...\n"));\r
+  do {\r
+    Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);\r
+  } while ((Reg32 & B_GSTS_REG_TE) == 0);\r
+\r
+  DEBUG ((DEBUG_INFO,"VTD () enabled!<<<<<<\n"));\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Disable DMAR translation.\r
+\r
+  @param VtdUnitBaseAddress The base address of the VTd engine.\r
+\r
+  @retval EFI_SUCCESS           DMAR translation is disabled.\r
+  @retval EFI_DEVICE_ERROR      DMAR translation is not disabled.\r
+**/\r
+EFI_STATUS\r
+DisableDmar (\r
+  IN UINTN  VtdUnitBaseAddress\r
+  )\r
+{\r
+  UINT32    Reg32;\r
+\r
+  DEBUG((DEBUG_INFO, ">>>>>>DisableDmar() for engine [%x] \n", VtdUnitBaseAddress));\r
+\r
+  //\r
+  // Write Buffer Flush before invalidation\r
+  //\r
+  FlushWriteBuffer (VtdUnitBaseAddress);\r
+\r
+  //\r
+  // Disable VTd\r
+  //\r
+  MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, B_GMCD_REG_SRTP);\r
+  do {\r
+    Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);\r
+  } while((Reg32 & B_GSTS_REG_RTPS) == 0);\r
+\r
+  Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);\r
+  DEBUG((DEBUG_INFO, "DisableDmar: GSTS_REG - 0x%08x\n", Reg32));\r
+\r
+  MmioWrite64 (VtdUnitBaseAddress + R_RTADDR_REG, 0);\r
+\r
+  DEBUG ((DEBUG_INFO,"VTD () Disabled!<<<<<<\n"));\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Enable VTd translation table protection.\r
+\r
+  @param VTdInfo            The VTd engine context information.\r
+  @param EngineMask         The mask of the VTd engine to be accessed.\r
+**/\r
+VOID\r
+EnableVTdTranslationProtection (\r
+  IN VTD_INFO      *VTdInfo,\r
+  IN UINT64        EngineMask\r
+  )\r
+{\r
+  UINTN       Index;\r
+  VOID        *RootEntryTable;\r
+\r
+  DEBUG ((DEBUG_INFO, "EnableVTdTranslationProtection - 0x%lx\n", EngineMask));\r
+\r
+  RootEntryTable = AllocatePages (1);\r
+  ASSERT (RootEntryTable != NULL);\r
+  if (RootEntryTable == NULL) {\r
+    DEBUG ((DEBUG_INFO, " EnableVTdTranslationProtection : OutOfResource\n"));\r
+    return ;\r
+  }\r
+\r
+  ZeroMem (RootEntryTable, EFI_PAGES_TO_SIZE(1));\r
+  FlushPageTableMemory ((UINTN)RootEntryTable, EFI_PAGES_TO_SIZE(1));\r
+\r
+  for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) {\r
+    if ((EngineMask & LShiftU64(1, Index)) == 0) {\r
+      continue;\r
+    }\r
+    EnableDmar ((UINTN)VTdInfo->VTdEngineAddress[Index], (UINTN)RootEntryTable);\r
+  }\r
+\r
+  return ;\r
+}\r
+\r
+/**\r
+  Disable VTd translation table protection.\r
+\r
+  @param VTdInfo            The VTd engine context information.\r
+  @param EngineMask         The mask of the VTd engine to be accessed.\r
+**/\r
+VOID\r
+DisableVTdTranslationProtection (\r
+  IN VTD_INFO      *VTdInfo,\r
+  IN UINT64        EngineMask\r
+  )\r
+{\r
+  UINTN       Index;\r
+\r
+  DEBUG ((DEBUG_INFO, "DisableVTdTranslationProtection - 0x%lx\n", EngineMask));\r
+\r
+  for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) {\r
+    if ((EngineMask & LShiftU64(1, Index)) == 0) {\r
+      continue;\r
+    }\r
+    DisableDmar ((UINTN)VTdInfo->VTdEngineAddress[Index]);\r
+  }\r
+\r
+  return ;\r
+}\r