public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH V2 0/2] IntelSiliconPkg: Add Pre-Memory DMA protection in PEI
@ 2017-10-27  5:40 Jiewen Yao
  2017-10-27  5:40 ` [PATCH V2 1/2] IntelSiliconPkg/VtdPmrPei: Add premem support Jiewen Yao
  2017-10-27  5:40 ` [PATCH V2 2/2] IntelSiliconPkg/VtdPeiSample: " Jiewen Yao
  0 siblings, 2 replies; 7+ messages in thread
From: Jiewen Yao @ 2017-10-27  5:40 UTC (permalink / raw)
  To: edk2-devel; +Cc: Star Zeng

============ V2 =============
Minor enhancement:
Replace IsDmaProtectionEnabled() by GetDmaProtectionEnabledEngineMask(),
for better code management.

============ V1 =============
This series patch adds Pre-Memory DMA protection in PEI.
The purpose is to make sure when the system memory is initialized, the DMA
protection takes effect immediately.

The IntelVTdPmrPei driver is updated to remove the global variable and
add VTD_INFO_PPI notification.

The VTdInfoSample driver is updated to install the initial
VTD_INFO_PPI before memory init, and add more content after memory init
by reinstalling VTD_INFO_PPI.

This patch is validated on one Intel Client kabylake platform.

Cc: Star Zeng <star.zeng@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>

Jiewen Yao (2):
  IntelSiliconPkg/VtdPmrPei: Add premem support.
  IntelSiliconPkg/VtdPeiSample: Add premem support.

 IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/DmarTable.c                            | 580 ++++++++++++++
 IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmr.c                          | 130 ++-
 IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.c                       | 846 +++++++-------------
 IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.h                       |  93 +++
 IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.inf                     |  11 +-
 IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/VtdReg.c                               | 293 +++++++
 IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.c   | 234 +++++-
 IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.inf |   2 +-
 8 files changed, 1558 insertions(+), 631 deletions(-)
 create mode 100644 IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/DmarTable.c
 create mode 100644 IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/VtdReg.c

-- 
2.7.4.windows.1



^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH V2 1/2] IntelSiliconPkg/VtdPmrPei: Add premem support.
  2017-10-27  5:40 [PATCH V2 0/2] IntelSiliconPkg: Add Pre-Memory DMA protection in PEI Jiewen Yao
@ 2017-10-27  5:40 ` Jiewen Yao
  2017-10-27  6:53   ` Zeng, Star
  2017-10-27  5:40 ` [PATCH V2 2/2] IntelSiliconPkg/VtdPeiSample: " Jiewen Yao
  1 sibling, 1 reply; 7+ messages in thread
From: Jiewen Yao @ 2017-10-27  5:40 UTC (permalink / raw)
  To: edk2-devel; +Cc: Star Zeng

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        | 580 ++++++++++++++
 IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmr.c      | 130 ++-
 IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.c   | 846 +++++++-------------
 IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.h   |  93 +++
 IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.inf |  11 +-
 IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/VtdReg.c           | 293 +++++++
 6 files changed, 1356 insertions(+), 597 deletions(-)

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



^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH V2 2/2] IntelSiliconPkg/VtdPeiSample: Add premem support.
  2017-10-27  5:40 [PATCH V2 0/2] IntelSiliconPkg: Add Pre-Memory DMA protection in PEI Jiewen Yao
  2017-10-27  5:40 ` [PATCH V2 1/2] IntelSiliconPkg/VtdPmrPei: Add premem support Jiewen Yao
@ 2017-10-27  5:40 ` Jiewen Yao
  2017-10-27  6:55   ` Zeng, Star
  1 sibling, 1 reply; 7+ messages in thread
From: Jiewen Yao @ 2017-10-27  5:40 UTC (permalink / raw)
  To: edk2-devel; +Cc: Star Zeng

Before memory is ready, this sample produces one VTd engine.
After memory and silicon is initialized, this sample produces
both IGD VTd engine and all-rest VTd engine by reinstall the
FV_INFO_PPI.

This update is to demonstrate how to support pre-mem VTd usage.

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/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.c   | 234 +++++++++++++++++---
 IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.inf |   2 +-
 2 files changed, 202 insertions(+), 34 deletions(-)

diff --git a/IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.c b/IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.c
index 6267da7..921daef 100644
--- a/IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.c
+++ b/IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.c
@@ -20,6 +20,7 @@
 #include <Library/DebugLib.h>
 #include <Library/PciLib.h>
 #include <Library/IoLib.h>
+#include <Library/MemoryAllocationLib.h>
 
 #define R_SA_MCHBAR               (0x48)
 #define R_SA_GGC                  (0x50)
@@ -33,6 +34,8 @@
 #define R_SA_MCHBAR_VTD1_OFFSET  0x5400  ///< HW UNIT for IGD
 #define R_SA_MCHBAR_VTD2_OFFSET  0x5410  ///< HW UNIT for all other - PEG, USB, SATA etc
 
+EFI_GUID gEdkiiSiliconInitializedPpiGuid = {0x82a72dc8, 0x61ec, 0x403e, {0xb1, 0x5a, 0x8d, 0x7a, 0x3a, 0x71, 0x84, 0x98}};
+
 typedef struct {
   EFI_ACPI_DMAR_HEADER                         DmarHeader;
   //
@@ -131,50 +134,190 @@ EFI_PEI_PPI_DESCRIPTOR mPlatformVTdInfoSampleDesc = {
   &mPlatformVTdSample
 };
 
+typedef struct {
+  EFI_ACPI_DMAR_HEADER                         DmarHeader;
+  //
+  // VTd engine 2 - all rest
+  //
+  EFI_ACPI_DMAR_DRHD_HEADER                    Drhd2;
+} MY_VTD_INFO_NO_IGD_PPI;
+
+MY_VTD_INFO_NO_IGD_PPI  mPlatformVTdNoIgdSample = {
+  { // DmarHeader
+    { // Header
+      EFI_ACPI_4_0_DMA_REMAPPING_TABLE_SIGNATURE,
+      sizeof(MY_VTD_INFO_PPI),
+      EFI_ACPI_DMAR_REVISION,
+    },
+    0x26, // HostAddressWidth
+  },
+
+  { // Drhd2
+    { // Header
+      EFI_ACPI_DMAR_TYPE_DRHD,
+      sizeof(EFI_ACPI_DMAR_DRHD_HEADER)
+    },
+    EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL, // Flags
+    0, // Reserved
+    0, // SegmentNumber
+    0xFED91000 // RegisterBaseAddress -- TO BE PATCHED
+  },
+};
+
+EFI_PEI_PPI_DESCRIPTOR mPlatformVTdNoIgdInfoSampleDesc = {
+  (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+  &gEdkiiVTdInfoPpiGuid,
+  &mPlatformVTdNoIgdSample
+};
+
 /**
   Patch Graphic UMA address in RMRR and base address.
 **/
 VOID
-PatchDmar (
+InitDmar (
   VOID
   )
 {
   UINT32              MchBar;
-  UINT16              IgdMode;
-  UINT16              GttMode;
-  UINT32              IgdMemSize;
-  UINT32              GttMemSize;
-
-  ///
-  /// Calculate IGD memsize
-  ///
-  IgdMode = ((PciRead16 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_GGC)) & B_SKL_SA_GGC_GMS_MASK) >> N_SKL_SA_GGC_GMS_OFFSET) & 0xFF;
-  if (IgdMode < 0xF0) {
-    IgdMemSize = IgdMode * 32 * (1024) * (1024);
+
+  DEBUG ((DEBUG_INFO, "InitDmar\n"));
+
+  MchBar = PciRead32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_MCHBAR)) & ~BIT0;
+  DEBUG ((DEBUG_INFO, "MchBar - %x\n", MchBar));
+
+  PciWrite32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_MCHBAR), 0xFED10000 | BIT0);
+  DEBUG ((DEBUG_INFO, "MchBar - %x\n", MchBar));
+
+  DEBUG ((DEBUG_INFO, "VTd2 - %x\n", (MmioRead32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET) &~1)));
+  MmioWrite32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET, (UINT32)mPlatformVTdSample.Drhd2.RegisterBaseAddress | 1);
+  DEBUG ((DEBUG_INFO, "VTd2 - %x\n", (MmioRead32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET) &~1)));
+}
+
+/**
+  Patch Graphic UMA address in RMRR and base address.
+**/
+EFI_PEI_PPI_DESCRIPTOR *
+PatchDmar (
+  VOID
+  )
+{
+  UINT32                  MchBar;
+  UINT16                  IgdMode;
+  UINT16                  GttMode;
+  UINT32                  IgdMemSize;
+  UINT32                  GttMemSize;
+  MY_VTD_INFO_PPI         *PlatformVTdSample;
+  EFI_PEI_PPI_DESCRIPTOR  *PlatformVTdInfoSampleDesc;
+  MY_VTD_INFO_NO_IGD_PPI  *PlatformVTdNoIgdSample;
+  EFI_PEI_PPI_DESCRIPTOR  *PlatformVTdNoIgdInfoSampleDesc;
+
+  DEBUG ((DEBUG_INFO, "PatchDmar\n"));
+
+  if (PciRead16 (PCI_LIB_ADDRESS(0, 2, 0, 0)) != 0xFFFF) {
+    PlatformVTdSample = AllocateCopyPool (sizeof(MY_VTD_INFO_PPI), &mPlatformVTdSample);
+    ASSERT(PlatformVTdSample != NULL);
+    PlatformVTdInfoSampleDesc = AllocateCopyPool (sizeof(EFI_PEI_PPI_DESCRIPTOR), &mPlatformVTdInfoSampleDesc);
+    ASSERT(PlatformVTdInfoSampleDesc != NULL);
+    PlatformVTdInfoSampleDesc->Ppi = PlatformVTdSample;
+
+    ///
+    /// Calculate IGD memsize
+    ///
+    IgdMode = ((PciRead16 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_GGC)) & B_SKL_SA_GGC_GMS_MASK) >> N_SKL_SA_GGC_GMS_OFFSET) & 0xFF;
+    if (IgdMode < 0xF0) {
+      IgdMemSize = IgdMode * 32 * (1024) * (1024);
+    } else {
+      IgdMemSize = 4 * (IgdMode - 0xF0 + 1) * (1024) * (1024);
+    }
+
+    ///
+    /// Calculate GTT mem size
+    ///
+    GttMemSize = 0;
+    GttMode = (PciRead16 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_GGC)) & B_SKL_SA_GGC_GGMS_MASK) >> N_SKL_SA_GGC_GGMS_OFFSET;
+    if (GttMode <= V_SKL_SA_GGC_GGMS_8MB) {
+      GttMemSize = (1 << GttMode) * (1024) * (1024);
+    }
+
+    PlatformVTdSample->Rmrr1.ReservedMemoryRegionBaseAddress  = (PciRead32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_TOLUD)) & ~(0x01)) - IgdMemSize - GttMemSize;
+    PlatformVTdSample->Rmrr1.ReservedMemoryRegionLimitAddress = PlatformVTdSample->Rmrr1.ReservedMemoryRegionBaseAddress + IgdMemSize + GttMemSize - 1;
+
+    ///
+    /// Update DRHD structures of DmarTable
+    ///
+    MchBar = PciRead32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_MCHBAR)) & ~BIT0;
+
+    DEBUG ((DEBUG_INFO, "VTd1 - %x\n", (MmioRead32 (MchBar + R_SA_MCHBAR_VTD1_OFFSET))));
+    if ((MmioRead32 (MchBar + R_SA_MCHBAR_VTD1_OFFSET) &~1) != 0) {
+      PlatformVTdSample->Drhd1.RegisterBaseAddress = (MmioRead32 (MchBar + R_SA_MCHBAR_VTD1_OFFSET) &~1);
+    } else {
+      MmioWrite32 (MchBar + R_SA_MCHBAR_VTD1_OFFSET, (UINT32)PlatformVTdSample->Drhd1.RegisterBaseAddress | 1);
+    }
+
+    DEBUG ((DEBUG_INFO, "VTd2 - %x\n", (MmioRead32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET))));
+    if ((MmioRead32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET) &~1) != 0) {
+      PlatformVTdSample->Drhd2.RegisterBaseAddress = (MmioRead32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET) &~1);
+    } else {
+      MmioWrite32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET, (UINT32)PlatformVTdSample->Drhd2.RegisterBaseAddress | 1);
+    }
+
+    return PlatformVTdInfoSampleDesc;
   } else {
-    IgdMemSize = 4 * (IgdMode - 0xF0 + 1) * (1024) * (1024);
-  }
+    PlatformVTdNoIgdSample = AllocateCopyPool (sizeof(MY_VTD_INFO_NO_IGD_PPI), &mPlatformVTdNoIgdSample);
+    ASSERT(PlatformVTdNoIgdSample != NULL);
+    PlatformVTdNoIgdInfoSampleDesc = AllocateCopyPool (sizeof(EFI_PEI_PPI_DESCRIPTOR), &mPlatformVTdNoIgdInfoSampleDesc);
+    ASSERT(PlatformVTdNoIgdInfoSampleDesc != NULL);
+    PlatformVTdNoIgdInfoSampleDesc->Ppi = PlatformVTdNoIgdSample;
+
+    ///
+    /// Update DRHD structures of DmarTable
+    ///
+    MchBar = PciRead32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_MCHBAR)) & ~BIT0;
 
-  ///
-  /// Calculate GTT mem size
-  ///
-  GttMemSize = 0;
-  GttMode = (PciRead16 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_GGC)) & B_SKL_SA_GGC_GGMS_MASK) >> N_SKL_SA_GGC_GGMS_OFFSET;
-  if (GttMode <= V_SKL_SA_GGC_GGMS_8MB) {
-    GttMemSize = (1 << GttMode) * (1024) * (1024);
+    DEBUG ((DEBUG_INFO, "VTd2 - %x\n", (MmioRead32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET))));
+    if ((MmioRead32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET) &~1) != 0) {
+      PlatformVTdNoIgdSample->Drhd2.RegisterBaseAddress = (MmioRead32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET) &~1);
+    } else {
+      MmioWrite32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET, (UINT32)PlatformVTdNoIgdSample->Drhd2.RegisterBaseAddress | 1);
+    }
+
+    return PlatformVTdNoIgdInfoSampleDesc;
   }
+}
 
-  mPlatformVTdSample.Rmrr1.ReservedMemoryRegionBaseAddress  = (PciRead32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_TOLUD)) & ~(0x01)) - IgdMemSize - GttMemSize;
-  mPlatformVTdSample.Rmrr1.ReservedMemoryRegionLimitAddress = mPlatformVTdSample.Rmrr1.ReservedMemoryRegionBaseAddress + IgdMemSize + GttMemSize - 1;
+/**
+  Install Firmware Volume Hob's once there is main memory
 
-  ///
-  /// Update DRHD structures of DmarTable
-  ///
-  MchBar = PciRead32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_MCHBAR)) & ~BIT0;
-  mPlatformVTdSample.Drhd1.RegisterBaseAddress = (MmioRead32 (MchBar + R_SA_MCHBAR_VTD1_OFFSET) &~1);
-  mPlatformVTdSample.Drhd2.RegisterBaseAddress = (MmioRead32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET) &~1);
+  @param[in]  PeiServices       General purpose services available to every PEIM.
+  @param[in]  NotifyDescriptor  Notify that this module published.
+  @param[in]  Ppi               PPI that was installed.
+
+  @retval     EFI_SUCCESS       The function completed successfully.
+**/
+EFI_STATUS
+EFIAPI
+SiliconInitializedPpiNotifyCallback (
+  IN CONST EFI_PEI_SERVICES     **PeiServices,
+  IN EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDescriptor,
+  IN VOID                       *Ppi
+  )
+{
+  EFI_STATUS               Status;
+  EFI_PEI_PPI_DESCRIPTOR   *PpiDesc;
+
+  PpiDesc = PatchDmar ();
+
+  Status = PeiServicesReInstallPpi (&mPlatformVTdNoIgdInfoSampleDesc, PpiDesc);
+  ASSERT_EFI_ERROR (Status);
+  return EFI_SUCCESS;
 }
 
+EFI_PEI_NOTIFY_DESCRIPTOR mSiliconInitializedNotifyList = {
+  (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+  &gEdkiiSiliconInitializedPpiGuid,
+  (EFI_PEIM_NOTIFY_ENTRY_POINT) SiliconInitializedPpiNotifyCallback
+};
+
 /**
   Platform VTd Info sample driver.
 
@@ -190,12 +333,37 @@ PlatformVTdInfoSampleInitialize (
   IN CONST EFI_PEI_SERVICES     **PeiServices
   )
 {
-  EFI_STATUS  Status;
+  EFI_STATUS               Status;
+  BOOLEAN                  SiliconInitialized;
+  VOID                     *SiliconInitializedPpi;
+  EFI_PEI_PPI_DESCRIPTOR   *PpiDesc;
+
+  SiliconInitialized = FALSE;
+  //
+  // Check if silicon is initialized.
+  //
+  Status = PeiServicesLocatePpi (
+             &gEdkiiSiliconInitializedPpiGuid,
+             0,
+             NULL,
+             &SiliconInitializedPpi
+             );
+  if (!EFI_ERROR(Status)) {
+    SiliconInitialized = TRUE;
+  }
+  DEBUG ((DEBUG_INFO, "SiliconInitialized - %x\n", SiliconInitialized));
+  if (!SiliconInitialized) {
+    Status = PeiServicesNotifyPpi (&mSiliconInitializedNotifyList);
+    InitDmar ();
 
-  PatchDmar ();
+    Status = PeiServicesInstallPpi (&mPlatformVTdNoIgdInfoSampleDesc);
+    ASSERT_EFI_ERROR (Status);
+  } else {
+    PpiDesc = PatchDmar ();
 
-  Status = PeiServicesInstallPpi (&mPlatformVTdInfoSampleDesc);
-  ASSERT_EFI_ERROR (Status);
+    Status = PeiServicesInstallPpi (PpiDesc);
+    ASSERT_EFI_ERROR (Status);
+  }
 
   return Status;
 }
diff --git a/IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.inf b/IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.inf
index 96adb70..a4ffe51 100644
--- a/IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.inf
+++ b/IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.inf
@@ -47,7 +47,7 @@
   gEdkiiVTdInfoPpiGuid         ## PRODUCES
 
 [Depex]
-  gEfiPeiMemoryDiscoveredPpiGuid
+  gEfiPeiMasterBootModePpiGuid
 
 [UserExtensions.TianoCore."ExtraFiles"]
   PlatformVTdInfoSamplePeiExtra.uni
-- 
2.7.4.windows.1



^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH V2 1/2] IntelSiliconPkg/VtdPmrPei: Add premem support.
  2017-10-27  5:40 ` [PATCH V2 1/2] IntelSiliconPkg/VtdPmrPei: Add premem support Jiewen Yao
@ 2017-10-27  6:53   ` Zeng, Star
  0 siblings, 0 replies; 7+ messages in thread
From: Zeng, Star @ 2017-10-27  6:53 UTC (permalink / raw)
  To: Yao, Jiewen, edk2-devel@lists.01.org; +Cc: Zeng, Star

Reviewed-by: Star Zeng <star.zeng@intel.com>

-----Original Message-----
From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Jiewen Yao
Sent: Friday, October 27, 2017 1:40 PM
To: edk2-devel@lists.01.org
Cc: Zeng, Star <star.zeng@intel.com>
Subject: [edk2] [PATCH V2 1/2] IntelSiliconPkg/VtdPmrPei: Add premem support.

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        | 580 ++++++++++++++
 IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmr.c      | 130 ++-
 IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.c   | 846 +++++++-------------
 IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.h   |  93 +++
 IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.inf |  11 +-
 IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/VtdReg.c           | 293 +++++++
 6 files changed, 1356 insertions(+), 597 deletions(-)

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

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH V2 2/2] IntelSiliconPkg/VtdPeiSample: Add premem support.
  2017-10-27  5:40 ` [PATCH V2 2/2] IntelSiliconPkg/VtdPeiSample: " Jiewen Yao
@ 2017-10-27  6:55   ` Zeng, Star
  2017-10-27  8:47     ` Zeng, Star
  0 siblings, 1 reply; 7+ messages in thread
From: Zeng, Star @ 2017-10-27  6:55 UTC (permalink / raw)
  To: Yao, Jiewen, edk2-devel@lists.01.org; +Cc: Zeng, Star

Could you update the function comments of InitDmar() and SiliconInitializedPpiNotifyCallback()?
There are two lines of " DEBUG ((DEBUG_INFO, "MchBar - %x\n", MchBar)) " in InitDmar(), are they added on purpose?

Thanks,
Star
-----Original Message-----
From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Jiewen Yao
Sent: Friday, October 27, 2017 1:41 PM
To: edk2-devel@lists.01.org
Cc: Zeng, Star <star.zeng@intel.com>
Subject: [edk2] [PATCH V2 2/2] IntelSiliconPkg/VtdPeiSample: Add premem support.

Before memory is ready, this sample produces one VTd engine.
After memory and silicon is initialized, this sample produces both IGD VTd engine and all-rest VTd engine by reinstall the FV_INFO_PPI.

This update is to demonstrate how to support pre-mem VTd usage.

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/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.c   | 234 +++++++++++++++++---
 IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.inf |   2 +-
 2 files changed, 202 insertions(+), 34 deletions(-)

diff --git a/IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.c b/IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.c
index 6267da7..921daef 100644
--- a/IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.c
+++ b/IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdIn
+++ foSamplePei.c
@@ -20,6 +20,7 @@
 #include <Library/DebugLib.h>
 #include <Library/PciLib.h>
 #include <Library/IoLib.h>
+#include <Library/MemoryAllocationLib.h>
 
 #define R_SA_MCHBAR               (0x48)
 #define R_SA_GGC                  (0x50)
@@ -33,6 +34,8 @@
 #define R_SA_MCHBAR_VTD1_OFFSET  0x5400  ///< HW UNIT for IGD  #define R_SA_MCHBAR_VTD2_OFFSET  0x5410  ///< HW UNIT for all other - PEG, USB, SATA etc
 
+EFI_GUID gEdkiiSiliconInitializedPpiGuid = {0x82a72dc8, 0x61ec, 0x403e, 
+{0xb1, 0x5a, 0x8d, 0x7a, 0x3a, 0x71, 0x84, 0x98}};
+
 typedef struct {
   EFI_ACPI_DMAR_HEADER                         DmarHeader;
   //
@@ -131,50 +134,190 @@ EFI_PEI_PPI_DESCRIPTOR mPlatformVTdInfoSampleDesc = {
   &mPlatformVTdSample
 };
 
+typedef struct {
+  EFI_ACPI_DMAR_HEADER                         DmarHeader;
+  //
+  // VTd engine 2 - all rest
+  //
+  EFI_ACPI_DMAR_DRHD_HEADER                    Drhd2;
+} MY_VTD_INFO_NO_IGD_PPI;
+
+MY_VTD_INFO_NO_IGD_PPI  mPlatformVTdNoIgdSample = {
+  { // DmarHeader
+    { // Header
+      EFI_ACPI_4_0_DMA_REMAPPING_TABLE_SIGNATURE,
+      sizeof(MY_VTD_INFO_PPI),
+      EFI_ACPI_DMAR_REVISION,
+    },
+    0x26, // HostAddressWidth
+  },
+
+  { // Drhd2
+    { // Header
+      EFI_ACPI_DMAR_TYPE_DRHD,
+      sizeof(EFI_ACPI_DMAR_DRHD_HEADER)
+    },
+    EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL, // Flags
+    0, // Reserved
+    0, // SegmentNumber
+    0xFED91000 // RegisterBaseAddress -- TO BE PATCHED
+  },
+};
+
+EFI_PEI_PPI_DESCRIPTOR mPlatformVTdNoIgdInfoSampleDesc = {
+  (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+  &gEdkiiVTdInfoPpiGuid,
+  &mPlatformVTdNoIgdSample
+};
+
 /**
   Patch Graphic UMA address in RMRR and base address.
 **/
 VOID
-PatchDmar (
+InitDmar (
   VOID
   )
 {
   UINT32              MchBar;
-  UINT16              IgdMode;
-  UINT16              GttMode;
-  UINT32              IgdMemSize;
-  UINT32              GttMemSize;
-
-  ///
-  /// Calculate IGD memsize
-  ///
-  IgdMode = ((PciRead16 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_GGC)) & B_SKL_SA_GGC_GMS_MASK) >> N_SKL_SA_GGC_GMS_OFFSET) & 0xFF;
-  if (IgdMode < 0xF0) {
-    IgdMemSize = IgdMode * 32 * (1024) * (1024);
+
+  DEBUG ((DEBUG_INFO, "InitDmar\n"));
+
+  MchBar = PciRead32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_MCHBAR)) & ~BIT0;  
+ DEBUG ((DEBUG_INFO, "MchBar - %x\n", MchBar));
+
+  PciWrite32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_MCHBAR), 0xFED10000 | 
+ BIT0);  DEBUG ((DEBUG_INFO, "MchBar - %x\n", MchBar));
+
+  DEBUG ((DEBUG_INFO, "VTd2 - %x\n", (MmioRead32 (MchBar + 
+R_SA_MCHBAR_VTD2_OFFSET) &~1)));
+  MmioWrite32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET, 
+(UINT32)mPlatformVTdSample.Drhd2.RegisterBaseAddress | 1);
+  DEBUG ((DEBUG_INFO, "VTd2 - %x\n", (MmioRead32 (MchBar + 
+R_SA_MCHBAR_VTD2_OFFSET) &~1))); }
+
+/**
+  Patch Graphic UMA address in RMRR and base address.
+**/
+EFI_PEI_PPI_DESCRIPTOR *
+PatchDmar (
+  VOID
+  )
+{
+  UINT32                  MchBar;
+  UINT16                  IgdMode;
+  UINT16                  GttMode;
+  UINT32                  IgdMemSize;
+  UINT32                  GttMemSize;
+  MY_VTD_INFO_PPI         *PlatformVTdSample;
+  EFI_PEI_PPI_DESCRIPTOR  *PlatformVTdInfoSampleDesc;
+  MY_VTD_INFO_NO_IGD_PPI  *PlatformVTdNoIgdSample;
+  EFI_PEI_PPI_DESCRIPTOR  *PlatformVTdNoIgdInfoSampleDesc;
+
+  DEBUG ((DEBUG_INFO, "PatchDmar\n"));
+
+  if (PciRead16 (PCI_LIB_ADDRESS(0, 2, 0, 0)) != 0xFFFF) {
+    PlatformVTdSample = AllocateCopyPool (sizeof(MY_VTD_INFO_PPI), &mPlatformVTdSample);
+    ASSERT(PlatformVTdSample != NULL);
+    PlatformVTdInfoSampleDesc = AllocateCopyPool (sizeof(EFI_PEI_PPI_DESCRIPTOR), &mPlatformVTdInfoSampleDesc);
+    ASSERT(PlatformVTdInfoSampleDesc != NULL);
+    PlatformVTdInfoSampleDesc->Ppi = PlatformVTdSample;
+
+    ///
+    /// Calculate IGD memsize
+    ///
+    IgdMode = ((PciRead16 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_GGC)) & B_SKL_SA_GGC_GMS_MASK) >> N_SKL_SA_GGC_GMS_OFFSET) & 0xFF;
+    if (IgdMode < 0xF0) {
+      IgdMemSize = IgdMode * 32 * (1024) * (1024);
+    } else {
+      IgdMemSize = 4 * (IgdMode - 0xF0 + 1) * (1024) * (1024);
+    }
+
+    ///
+    /// Calculate GTT mem size
+    ///
+    GttMemSize = 0;
+    GttMode = (PciRead16 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_GGC)) & B_SKL_SA_GGC_GGMS_MASK) >> N_SKL_SA_GGC_GGMS_OFFSET;
+    if (GttMode <= V_SKL_SA_GGC_GGMS_8MB) {
+      GttMemSize = (1 << GttMode) * (1024) * (1024);
+    }
+
+    PlatformVTdSample->Rmrr1.ReservedMemoryRegionBaseAddress  = (PciRead32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_TOLUD)) & ~(0x01)) - IgdMemSize - GttMemSize;
+    PlatformVTdSample->Rmrr1.ReservedMemoryRegionLimitAddress = 
+ PlatformVTdSample->Rmrr1.ReservedMemoryRegionBaseAddress + IgdMemSize 
+ + GttMemSize - 1;
+
+    ///
+    /// Update DRHD structures of DmarTable
+    ///
+    MchBar = PciRead32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_MCHBAR)) & ~BIT0;
+
+    DEBUG ((DEBUG_INFO, "VTd1 - %x\n", (MmioRead32 (MchBar + R_SA_MCHBAR_VTD1_OFFSET))));
+    if ((MmioRead32 (MchBar + R_SA_MCHBAR_VTD1_OFFSET) &~1) != 0) {
+      PlatformVTdSample->Drhd1.RegisterBaseAddress = (MmioRead32 (MchBar + R_SA_MCHBAR_VTD1_OFFSET) &~1);
+    } else {
+      MmioWrite32 (MchBar + R_SA_MCHBAR_VTD1_OFFSET, (UINT32)PlatformVTdSample->Drhd1.RegisterBaseAddress | 1);
+    }
+
+    DEBUG ((DEBUG_INFO, "VTd2 - %x\n", (MmioRead32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET))));
+    if ((MmioRead32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET) &~1) != 0) {
+      PlatformVTdSample->Drhd2.RegisterBaseAddress = (MmioRead32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET) &~1);
+    } else {
+      MmioWrite32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET, (UINT32)PlatformVTdSample->Drhd2.RegisterBaseAddress | 1);
+    }
+
+    return PlatformVTdInfoSampleDesc;
   } else {
-    IgdMemSize = 4 * (IgdMode - 0xF0 + 1) * (1024) * (1024);
-  }
+    PlatformVTdNoIgdSample = AllocateCopyPool (sizeof(MY_VTD_INFO_NO_IGD_PPI), &mPlatformVTdNoIgdSample);
+    ASSERT(PlatformVTdNoIgdSample != NULL);
+    PlatformVTdNoIgdInfoSampleDesc = AllocateCopyPool (sizeof(EFI_PEI_PPI_DESCRIPTOR), &mPlatformVTdNoIgdInfoSampleDesc);
+    ASSERT(PlatformVTdNoIgdInfoSampleDesc != NULL);
+    PlatformVTdNoIgdInfoSampleDesc->Ppi = PlatformVTdNoIgdSample;
+
+    ///
+    /// Update DRHD structures of DmarTable
+    ///
+    MchBar = PciRead32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_MCHBAR)) & ~BIT0;
 
-  ///
-  /// Calculate GTT mem size
-  ///
-  GttMemSize = 0;
-  GttMode = (PciRead16 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_GGC)) & B_SKL_SA_GGC_GGMS_MASK) >> N_SKL_SA_GGC_GGMS_OFFSET;
-  if (GttMode <= V_SKL_SA_GGC_GGMS_8MB) {
-    GttMemSize = (1 << GttMode) * (1024) * (1024);
+    DEBUG ((DEBUG_INFO, "VTd2 - %x\n", (MmioRead32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET))));
+    if ((MmioRead32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET) &~1) != 0) {
+      PlatformVTdNoIgdSample->Drhd2.RegisterBaseAddress = (MmioRead32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET) &~1);
+    } else {
+      MmioWrite32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET, (UINT32)PlatformVTdNoIgdSample->Drhd2.RegisterBaseAddress | 1);
+    }
+
+    return PlatformVTdNoIgdInfoSampleDesc;
   }
+}
 
-  mPlatformVTdSample.Rmrr1.ReservedMemoryRegionBaseAddress  = (PciRead32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_TOLUD)) & ~(0x01)) - IgdMemSize - GttMemSize;
-  mPlatformVTdSample.Rmrr1.ReservedMemoryRegionLimitAddress = mPlatformVTdSample.Rmrr1.ReservedMemoryRegionBaseAddress + IgdMemSize + GttMemSize - 1;
+/**
+  Install Firmware Volume Hob's once there is main memory
 
-  ///
-  /// Update DRHD structures of DmarTable
-  ///
-  MchBar = PciRead32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_MCHBAR)) & ~BIT0;
-  mPlatformVTdSample.Drhd1.RegisterBaseAddress = (MmioRead32 (MchBar + R_SA_MCHBAR_VTD1_OFFSET) &~1);
-  mPlatformVTdSample.Drhd2.RegisterBaseAddress = (MmioRead32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET) &~1);
+  @param[in]  PeiServices       General purpose services available to every PEIM.
+  @param[in]  NotifyDescriptor  Notify that this module published.
+  @param[in]  Ppi               PPI that was installed.
+
+  @retval     EFI_SUCCESS       The function completed successfully.
+**/
+EFI_STATUS
+EFIAPI
+SiliconInitializedPpiNotifyCallback (
+  IN CONST EFI_PEI_SERVICES     **PeiServices,
+  IN EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDescriptor,
+  IN VOID                       *Ppi
+  )
+{
+  EFI_STATUS               Status;
+  EFI_PEI_PPI_DESCRIPTOR   *PpiDesc;
+
+  PpiDesc = PatchDmar ();
+
+  Status = PeiServicesReInstallPpi (&mPlatformVTdNoIgdInfoSampleDesc, 
+ PpiDesc);  ASSERT_EFI_ERROR (Status);  return EFI_SUCCESS;
 }
 
+EFI_PEI_NOTIFY_DESCRIPTOR mSiliconInitializedNotifyList = {
+  (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | 
+EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+  &gEdkiiSiliconInitializedPpiGuid,
+  (EFI_PEIM_NOTIFY_ENTRY_POINT) SiliconInitializedPpiNotifyCallback
+};
+
 /**
   Platform VTd Info sample driver.
 
@@ -190,12 +333,37 @@ PlatformVTdInfoSampleInitialize (
   IN CONST EFI_PEI_SERVICES     **PeiServices
   )
 {
-  EFI_STATUS  Status;
+  EFI_STATUS               Status;
+  BOOLEAN                  SiliconInitialized;
+  VOID                     *SiliconInitializedPpi;
+  EFI_PEI_PPI_DESCRIPTOR   *PpiDesc;
+
+  SiliconInitialized = FALSE;
+  //
+  // Check if silicon is initialized.
+  //
+  Status = PeiServicesLocatePpi (
+             &gEdkiiSiliconInitializedPpiGuid,
+             0,
+             NULL,
+             &SiliconInitializedPpi
+             );
+  if (!EFI_ERROR(Status)) {
+    SiliconInitialized = TRUE;
+  }
+  DEBUG ((DEBUG_INFO, "SiliconInitialized - %x\n", 
+ SiliconInitialized));  if (!SiliconInitialized) {
+    Status = PeiServicesNotifyPpi (&mSiliconInitializedNotifyList);
+    InitDmar ();
 
-  PatchDmar ();
+    Status = PeiServicesInstallPpi (&mPlatformVTdNoIgdInfoSampleDesc);
+    ASSERT_EFI_ERROR (Status);
+  } else {
+    PpiDesc = PatchDmar ();
 
-  Status = PeiServicesInstallPpi (&mPlatformVTdInfoSampleDesc);
-  ASSERT_EFI_ERROR (Status);
+    Status = PeiServicesInstallPpi (PpiDesc);
+    ASSERT_EFI_ERROR (Status);
+  }
 
   return Status;
 }
diff --git a/IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.inf b/IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.inf
index 96adb70..a4ffe51 100644
--- a/IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.inf
+++ b/IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdIn
+++ foSamplePei.inf
@@ -47,7 +47,7 @@
   gEdkiiVTdInfoPpiGuid         ## PRODUCES
 
 [Depex]
-  gEfiPeiMemoryDiscoveredPpiGuid
+  gEfiPeiMasterBootModePpiGuid
 
 [UserExtensions.TianoCore."ExtraFiles"]
   PlatformVTdInfoSamplePeiExtra.uni
--
2.7.4.windows.1

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH V2 2/2] IntelSiliconPkg/VtdPeiSample: Add premem support.
  2017-10-27  6:55   ` Zeng, Star
@ 2017-10-27  8:47     ` Zeng, Star
  2017-10-27 12:30       ` Yao, Jiewen
  0 siblings, 1 reply; 7+ messages in thread
From: Zeng, Star @ 2017-10-27  8:47 UTC (permalink / raw)
  To: Yao, Jiewen, edk2-devel@lists.01.org; +Cc: Zeng, Star

Another comment.

sizeof(MY_VTD_INFO_PPI) is used in mPlatformVTdNoIgdSample, that seems wrong and should be sizeof(MY_VTD_INFO_NO_IGD_PPI), right?
Why it does not cause problem with the code.


Thanks,
Star
-----Original Message-----
From: Zeng, Star 
Sent: Friday, October 27, 2017 2:56 PM
To: Yao, Jiewen <jiewen.yao@intel.com>; edk2-devel@lists.01.org
Cc: Zeng, Star <star.zeng@intel.com>
Subject: RE: [edk2] [PATCH V2 2/2] IntelSiliconPkg/VtdPeiSample: Add premem support.

Could you update the function comments of InitDmar() and SiliconInitializedPpiNotifyCallback()?
There are two lines of " DEBUG ((DEBUG_INFO, "MchBar - %x\n", MchBar)) " in InitDmar(), are they added on purpose?

Thanks,
Star
-----Original Message-----
From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Jiewen Yao
Sent: Friday, October 27, 2017 1:41 PM
To: edk2-devel@lists.01.org
Cc: Zeng, Star <star.zeng@intel.com>
Subject: [edk2] [PATCH V2 2/2] IntelSiliconPkg/VtdPeiSample: Add premem support.

Before memory is ready, this sample produces one VTd engine.
After memory and silicon is initialized, this sample produces both IGD VTd engine and all-rest VTd engine by reinstall the FV_INFO_PPI.

This update is to demonstrate how to support pre-mem VTd usage.

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/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.c   | 234 +++++++++++++++++---
 IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.inf |   2 +-
 2 files changed, 202 insertions(+), 34 deletions(-)

diff --git a/IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.c b/IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.c
index 6267da7..921daef 100644
--- a/IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.c
+++ b/IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdIn
+++ foSamplePei.c
@@ -20,6 +20,7 @@
 #include <Library/DebugLib.h>
 #include <Library/PciLib.h>
 #include <Library/IoLib.h>
+#include <Library/MemoryAllocationLib.h>
 
 #define R_SA_MCHBAR               (0x48)
 #define R_SA_GGC                  (0x50)
@@ -33,6 +34,8 @@
 #define R_SA_MCHBAR_VTD1_OFFSET  0x5400  ///< HW UNIT for IGD  #define R_SA_MCHBAR_VTD2_OFFSET  0x5410  ///< HW UNIT for all other - PEG, USB, SATA etc
 
+EFI_GUID gEdkiiSiliconInitializedPpiGuid = {0x82a72dc8, 0x61ec, 0x403e, 
+{0xb1, 0x5a, 0x8d, 0x7a, 0x3a, 0x71, 0x84, 0x98}};
+
 typedef struct {
   EFI_ACPI_DMAR_HEADER                         DmarHeader;
   //
@@ -131,50 +134,190 @@ EFI_PEI_PPI_DESCRIPTOR mPlatformVTdInfoSampleDesc = {
   &mPlatformVTdSample
 };
 
+typedef struct {
+  EFI_ACPI_DMAR_HEADER                         DmarHeader;
+  //
+  // VTd engine 2 - all rest
+  //
+  EFI_ACPI_DMAR_DRHD_HEADER                    Drhd2;
+} MY_VTD_INFO_NO_IGD_PPI;
+
+MY_VTD_INFO_NO_IGD_PPI  mPlatformVTdNoIgdSample = {
+  { // DmarHeader
+    { // Header
+      EFI_ACPI_4_0_DMA_REMAPPING_TABLE_SIGNATURE,
+      sizeof(MY_VTD_INFO_PPI),
+      EFI_ACPI_DMAR_REVISION,
+    },
+    0x26, // HostAddressWidth
+  },
+
+  { // Drhd2
+    { // Header
+      EFI_ACPI_DMAR_TYPE_DRHD,
+      sizeof(EFI_ACPI_DMAR_DRHD_HEADER)
+    },
+    EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL, // Flags
+    0, // Reserved
+    0, // SegmentNumber
+    0xFED91000 // RegisterBaseAddress -- TO BE PATCHED
+  },
+};
+
+EFI_PEI_PPI_DESCRIPTOR mPlatformVTdNoIgdInfoSampleDesc = {
+  (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+  &gEdkiiVTdInfoPpiGuid,
+  &mPlatformVTdNoIgdSample
+};
+
 /**
   Patch Graphic UMA address in RMRR and base address.
 **/
 VOID
-PatchDmar (
+InitDmar (
   VOID
   )
 {
   UINT32              MchBar;
-  UINT16              IgdMode;
-  UINT16              GttMode;
-  UINT32              IgdMemSize;
-  UINT32              GttMemSize;
-
-  ///
-  /// Calculate IGD memsize
-  ///
-  IgdMode = ((PciRead16 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_GGC)) & B_SKL_SA_GGC_GMS_MASK) >> N_SKL_SA_GGC_GMS_OFFSET) & 0xFF;
-  if (IgdMode < 0xF0) {
-    IgdMemSize = IgdMode * 32 * (1024) * (1024);
+
+  DEBUG ((DEBUG_INFO, "InitDmar\n"));
+
+  MchBar = PciRead32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_MCHBAR)) & ~BIT0; 
+ DEBUG ((DEBUG_INFO, "MchBar - %x\n", MchBar));
+
+  PciWrite32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_MCHBAR), 0xFED10000 | 
+ BIT0);  DEBUG ((DEBUG_INFO, "MchBar - %x\n", MchBar));
+
+  DEBUG ((DEBUG_INFO, "VTd2 - %x\n", (MmioRead32 (MchBar +
+R_SA_MCHBAR_VTD2_OFFSET) &~1)));
+  MmioWrite32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET, 
+(UINT32)mPlatformVTdSample.Drhd2.RegisterBaseAddress | 1);
+  DEBUG ((DEBUG_INFO, "VTd2 - %x\n", (MmioRead32 (MchBar +
+R_SA_MCHBAR_VTD2_OFFSET) &~1))); }
+
+/**
+  Patch Graphic UMA address in RMRR and base address.
+**/
+EFI_PEI_PPI_DESCRIPTOR *
+PatchDmar (
+  VOID
+  )
+{
+  UINT32                  MchBar;
+  UINT16                  IgdMode;
+  UINT16                  GttMode;
+  UINT32                  IgdMemSize;
+  UINT32                  GttMemSize;
+  MY_VTD_INFO_PPI         *PlatformVTdSample;
+  EFI_PEI_PPI_DESCRIPTOR  *PlatformVTdInfoSampleDesc;
+  MY_VTD_INFO_NO_IGD_PPI  *PlatformVTdNoIgdSample;
+  EFI_PEI_PPI_DESCRIPTOR  *PlatformVTdNoIgdInfoSampleDesc;
+
+  DEBUG ((DEBUG_INFO, "PatchDmar\n"));
+
+  if (PciRead16 (PCI_LIB_ADDRESS(0, 2, 0, 0)) != 0xFFFF) {
+    PlatformVTdSample = AllocateCopyPool (sizeof(MY_VTD_INFO_PPI), &mPlatformVTdSample);
+    ASSERT(PlatformVTdSample != NULL);
+    PlatformVTdInfoSampleDesc = AllocateCopyPool (sizeof(EFI_PEI_PPI_DESCRIPTOR), &mPlatformVTdInfoSampleDesc);
+    ASSERT(PlatformVTdInfoSampleDesc != NULL);
+    PlatformVTdInfoSampleDesc->Ppi = PlatformVTdSample;
+
+    ///
+    /// Calculate IGD memsize
+    ///
+    IgdMode = ((PciRead16 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_GGC)) & B_SKL_SA_GGC_GMS_MASK) >> N_SKL_SA_GGC_GMS_OFFSET) & 0xFF;
+    if (IgdMode < 0xF0) {
+      IgdMemSize = IgdMode * 32 * (1024) * (1024);
+    } else {
+      IgdMemSize = 4 * (IgdMode - 0xF0 + 1) * (1024) * (1024);
+    }
+
+    ///
+    /// Calculate GTT mem size
+    ///
+    GttMemSize = 0;
+    GttMode = (PciRead16 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_GGC)) & B_SKL_SA_GGC_GGMS_MASK) >> N_SKL_SA_GGC_GGMS_OFFSET;
+    if (GttMode <= V_SKL_SA_GGC_GGMS_8MB) {
+      GttMemSize = (1 << GttMode) * (1024) * (1024);
+    }
+
+    PlatformVTdSample->Rmrr1.ReservedMemoryRegionBaseAddress  = (PciRead32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_TOLUD)) & ~(0x01)) - IgdMemSize - GttMemSize;
+    PlatformVTdSample->Rmrr1.ReservedMemoryRegionLimitAddress =
+ PlatformVTdSample->Rmrr1.ReservedMemoryRegionBaseAddress + IgdMemSize
+ + GttMemSize - 1;
+
+    ///
+    /// Update DRHD structures of DmarTable
+    ///
+    MchBar = PciRead32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_MCHBAR)) & ~BIT0;
+
+    DEBUG ((DEBUG_INFO, "VTd1 - %x\n", (MmioRead32 (MchBar + R_SA_MCHBAR_VTD1_OFFSET))));
+    if ((MmioRead32 (MchBar + R_SA_MCHBAR_VTD1_OFFSET) &~1) != 0) {
+      PlatformVTdSample->Drhd1.RegisterBaseAddress = (MmioRead32 (MchBar + R_SA_MCHBAR_VTD1_OFFSET) &~1);
+    } else {
+      MmioWrite32 (MchBar + R_SA_MCHBAR_VTD1_OFFSET, (UINT32)PlatformVTdSample->Drhd1.RegisterBaseAddress | 1);
+    }
+
+    DEBUG ((DEBUG_INFO, "VTd2 - %x\n", (MmioRead32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET))));
+    if ((MmioRead32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET) &~1) != 0) {
+      PlatformVTdSample->Drhd2.RegisterBaseAddress = (MmioRead32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET) &~1);
+    } else {
+      MmioWrite32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET, (UINT32)PlatformVTdSample->Drhd2.RegisterBaseAddress | 1);
+    }
+
+    return PlatformVTdInfoSampleDesc;
   } else {
-    IgdMemSize = 4 * (IgdMode - 0xF0 + 1) * (1024) * (1024);
-  }
+    PlatformVTdNoIgdSample = AllocateCopyPool (sizeof(MY_VTD_INFO_NO_IGD_PPI), &mPlatformVTdNoIgdSample);
+    ASSERT(PlatformVTdNoIgdSample != NULL);
+    PlatformVTdNoIgdInfoSampleDesc = AllocateCopyPool (sizeof(EFI_PEI_PPI_DESCRIPTOR), &mPlatformVTdNoIgdInfoSampleDesc);
+    ASSERT(PlatformVTdNoIgdInfoSampleDesc != NULL);
+    PlatformVTdNoIgdInfoSampleDesc->Ppi = PlatformVTdNoIgdSample;
+
+    ///
+    /// Update DRHD structures of DmarTable
+    ///
+    MchBar = PciRead32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_MCHBAR)) & ~BIT0;
 
-  ///
-  /// Calculate GTT mem size
-  ///
-  GttMemSize = 0;
-  GttMode = (PciRead16 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_GGC)) & B_SKL_SA_GGC_GGMS_MASK) >> N_SKL_SA_GGC_GGMS_OFFSET;
-  if (GttMode <= V_SKL_SA_GGC_GGMS_8MB) {
-    GttMemSize = (1 << GttMode) * (1024) * (1024);
+    DEBUG ((DEBUG_INFO, "VTd2 - %x\n", (MmioRead32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET))));
+    if ((MmioRead32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET) &~1) != 0) {
+      PlatformVTdNoIgdSample->Drhd2.RegisterBaseAddress = (MmioRead32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET) &~1);
+    } else {
+      MmioWrite32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET, (UINT32)PlatformVTdNoIgdSample->Drhd2.RegisterBaseAddress | 1);
+    }
+
+    return PlatformVTdNoIgdInfoSampleDesc;
   }
+}
 
-  mPlatformVTdSample.Rmrr1.ReservedMemoryRegionBaseAddress  = (PciRead32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_TOLUD)) & ~(0x01)) - IgdMemSize - GttMemSize;
-  mPlatformVTdSample.Rmrr1.ReservedMemoryRegionLimitAddress = mPlatformVTdSample.Rmrr1.ReservedMemoryRegionBaseAddress + IgdMemSize + GttMemSize - 1;
+/**
+  Install Firmware Volume Hob's once there is main memory
 
-  ///
-  /// Update DRHD structures of DmarTable
-  ///
-  MchBar = PciRead32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_MCHBAR)) & ~BIT0;
-  mPlatformVTdSample.Drhd1.RegisterBaseAddress = (MmioRead32 (MchBar + R_SA_MCHBAR_VTD1_OFFSET) &~1);
-  mPlatformVTdSample.Drhd2.RegisterBaseAddress = (MmioRead32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET) &~1);
+  @param[in]  PeiServices       General purpose services available to every PEIM.
+  @param[in]  NotifyDescriptor  Notify that this module published.
+  @param[in]  Ppi               PPI that was installed.
+
+  @retval     EFI_SUCCESS       The function completed successfully.
+**/
+EFI_STATUS
+EFIAPI
+SiliconInitializedPpiNotifyCallback (
+  IN CONST EFI_PEI_SERVICES     **PeiServices,
+  IN EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDescriptor,
+  IN VOID                       *Ppi
+  )
+{
+  EFI_STATUS               Status;
+  EFI_PEI_PPI_DESCRIPTOR   *PpiDesc;
+
+  PpiDesc = PatchDmar ();
+
+  Status = PeiServicesReInstallPpi (&mPlatformVTdNoIgdInfoSampleDesc,
+ PpiDesc);  ASSERT_EFI_ERROR (Status);  return EFI_SUCCESS;
 }
 
+EFI_PEI_NOTIFY_DESCRIPTOR mSiliconInitializedNotifyList = {
+  (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | 
+EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+  &gEdkiiSiliconInitializedPpiGuid,
+  (EFI_PEIM_NOTIFY_ENTRY_POINT) SiliconInitializedPpiNotifyCallback
+};
+
 /**
   Platform VTd Info sample driver.
 
@@ -190,12 +333,37 @@ PlatformVTdInfoSampleInitialize (
   IN CONST EFI_PEI_SERVICES     **PeiServices
   )
 {
-  EFI_STATUS  Status;
+  EFI_STATUS               Status;
+  BOOLEAN                  SiliconInitialized;
+  VOID                     *SiliconInitializedPpi;
+  EFI_PEI_PPI_DESCRIPTOR   *PpiDesc;
+
+  SiliconInitialized = FALSE;
+  //
+  // Check if silicon is initialized.
+  //
+  Status = PeiServicesLocatePpi (
+             &gEdkiiSiliconInitializedPpiGuid,
+             0,
+             NULL,
+             &SiliconInitializedPpi
+             );
+  if (!EFI_ERROR(Status)) {
+    SiliconInitialized = TRUE;
+  }
+  DEBUG ((DEBUG_INFO, "SiliconInitialized - %x\n", 
+ SiliconInitialized));  if (!SiliconInitialized) {
+    Status = PeiServicesNotifyPpi (&mSiliconInitializedNotifyList);
+    InitDmar ();
 
-  PatchDmar ();
+    Status = PeiServicesInstallPpi (&mPlatformVTdNoIgdInfoSampleDesc);
+    ASSERT_EFI_ERROR (Status);
+  } else {
+    PpiDesc = PatchDmar ();
 
-  Status = PeiServicesInstallPpi (&mPlatformVTdInfoSampleDesc);
-  ASSERT_EFI_ERROR (Status);
+    Status = PeiServicesInstallPpi (PpiDesc);
+    ASSERT_EFI_ERROR (Status);
+  }
 
   return Status;
 }
diff --git a/IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.inf b/IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.inf
index 96adb70..a4ffe51 100644
--- a/IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.inf
+++ b/IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdIn
+++ foSamplePei.inf
@@ -47,7 +47,7 @@
   gEdkiiVTdInfoPpiGuid         ## PRODUCES
 
 [Depex]
-  gEfiPeiMemoryDiscoveredPpiGuid
+  gEfiPeiMasterBootModePpiGuid
 
 [UserExtensions.TianoCore."ExtraFiles"]
   PlatformVTdInfoSamplePeiExtra.uni
--
2.7.4.windows.1

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH V2 2/2] IntelSiliconPkg/VtdPeiSample: Add premem support.
  2017-10-27  8:47     ` Zeng, Star
@ 2017-10-27 12:30       ` Yao, Jiewen
  0 siblings, 0 replies; 7+ messages in thread
From: Yao, Jiewen @ 2017-10-27 12:30 UTC (permalink / raw)
  To: Zeng, Star, edk2-devel@lists.01.org

Good feedback. I fixed all these in V3.

Why the wrong size does not cause problem?
The reason is that the garbage data is skipped in the while loop of DRHD or RMRR structure.

Thank you
Yao Jiewen

> -----Original Message-----
> From: Zeng, Star
> Sent: Friday, October 27, 2017 4:47 PM
> To: Yao, Jiewen <jiewen.yao@intel.com>; edk2-devel@lists.01.org
> Cc: Zeng, Star <star.zeng@intel.com>
> Subject: RE: [edk2] [PATCH V2 2/2] IntelSiliconPkg/VtdPeiSample: Add premem
> support.
> 
> Another comment.
> 
> sizeof(MY_VTD_INFO_PPI) is used in mPlatformVTdNoIgdSample, that seems
> wrong and should be sizeof(MY_VTD_INFO_NO_IGD_PPI), right?
> Why it does not cause problem with the code.
> 
> 
> Thanks,
> Star
> -----Original Message-----
> From: Zeng, Star
> Sent: Friday, October 27, 2017 2:56 PM
> To: Yao, Jiewen <jiewen.yao@intel.com>; edk2-devel@lists.01.org
> Cc: Zeng, Star <star.zeng@intel.com>
> Subject: RE: [edk2] [PATCH V2 2/2] IntelSiliconPkg/VtdPeiSample: Add premem
> support.
> 
> Could you update the function comments of InitDmar() and
> SiliconInitializedPpiNotifyCallback()?
> There are two lines of " DEBUG ((DEBUG_INFO, "MchBar - %x\n", MchBar)) " in
> InitDmar(), are they added on purpose?
> 
> Thanks,
> Star
> -----Original Message-----
> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Jiewen
> Yao
> Sent: Friday, October 27, 2017 1:41 PM
> To: edk2-devel@lists.01.org
> Cc: Zeng, Star <star.zeng@intel.com>
> Subject: [edk2] [PATCH V2 2/2] IntelSiliconPkg/VtdPeiSample: Add premem
> support.
> 
> Before memory is ready, this sample produces one VTd engine.
> After memory and silicon is initialized, this sample produces both IGD VTd engine
> and all-rest VTd engine by reinstall the FV_INFO_PPI.
> 
> This update is to demonstrate how to support pre-mem VTd usage.
> 
> 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/PlatformVTdInfoSamplePei/PlatformVTdInfoSample
> Pei.c   | 234 +++++++++++++++++---
> 
> IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSample
> Pei.inf |   2 +-
>  2 files changed, 202 insertions(+), 34 deletions(-)
> 
> diff --git
> a/IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSam
> plePei.c
> b/IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSam
> plePei.c
> index 6267da7..921daef 100644
> ---
> a/IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSam
> plePei.c
> +++ b/IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdIn
> +++ foSamplePei.c
> @@ -20,6 +20,7 @@
>  #include <Library/DebugLib.h>
>  #include <Library/PciLib.h>
>  #include <Library/IoLib.h>
> +#include <Library/MemoryAllocationLib.h>
> 
>  #define R_SA_MCHBAR               (0x48)
>  #define R_SA_GGC                  (0x50)
> @@ -33,6 +34,8 @@
>  #define R_SA_MCHBAR_VTD1_OFFSET  0x5400  ///< HW UNIT for IGD
> #define R_SA_MCHBAR_VTD2_OFFSET  0x5410  ///< HW UNIT for all other -
> PEG, USB, SATA etc
> 
> +EFI_GUID gEdkiiSiliconInitializedPpiGuid = {0x82a72dc8, 0x61ec, 0x403e,
> +{0xb1, 0x5a, 0x8d, 0x7a, 0x3a, 0x71, 0x84, 0x98}};
> +
>  typedef struct {
>    EFI_ACPI_DMAR_HEADER                         DmarHeader;
>    //
> @@ -131,50 +134,190 @@ EFI_PEI_PPI_DESCRIPTOR
> mPlatformVTdInfoSampleDesc = {
>    &mPlatformVTdSample
>  };
> 
> +typedef struct {
> +  EFI_ACPI_DMAR_HEADER                         DmarHeader;
> +  //
> +  // VTd engine 2 - all rest
> +  //
> +  EFI_ACPI_DMAR_DRHD_HEADER                    Drhd2;
> +} MY_VTD_INFO_NO_IGD_PPI;
> +
> +MY_VTD_INFO_NO_IGD_PPI  mPlatformVTdNoIgdSample = {
> +  { // DmarHeader
> +    { // Header
> +      EFI_ACPI_4_0_DMA_REMAPPING_TABLE_SIGNATURE,
> +      sizeof(MY_VTD_INFO_PPI),
> +      EFI_ACPI_DMAR_REVISION,
> +    },
> +    0x26, // HostAddressWidth
> +  },
> +
> +  { // Drhd2
> +    { // Header
> +      EFI_ACPI_DMAR_TYPE_DRHD,
> +      sizeof(EFI_ACPI_DMAR_DRHD_HEADER)
> +    },
> +    EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL, // Flags
> +    0, // Reserved
> +    0, // SegmentNumber
> +    0xFED91000 // RegisterBaseAddress -- TO BE PATCHED
> +  },
> +};
> +
> +EFI_PEI_PPI_DESCRIPTOR mPlatformVTdNoIgdInfoSampleDesc = {
> +  (EFI_PEI_PPI_DESCRIPTOR_PPI |
> EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
> +  &gEdkiiVTdInfoPpiGuid,
> +  &mPlatformVTdNoIgdSample
> +};
> +
>  /**
>    Patch Graphic UMA address in RMRR and base address.
>  **/
>  VOID
> -PatchDmar (
> +InitDmar (
>    VOID
>    )
>  {
>    UINT32              MchBar;
> -  UINT16              IgdMode;
> -  UINT16              GttMode;
> -  UINT32              IgdMemSize;
> -  UINT32              GttMemSize;
> -
> -  ///
> -  /// Calculate IGD memsize
> -  ///
> -  IgdMode = ((PciRead16 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_GGC)) &
> B_SKL_SA_GGC_GMS_MASK) >> N_SKL_SA_GGC_GMS_OFFSET) & 0xFF;
> -  if (IgdMode < 0xF0) {
> -    IgdMemSize = IgdMode * 32 * (1024) * (1024);
> +
> +  DEBUG ((DEBUG_INFO, "InitDmar\n"));
> +
> +  MchBar = PciRead32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_MCHBAR)) & ~BIT0;
> + DEBUG ((DEBUG_INFO, "MchBar - %x\n", MchBar));
> +
> +  PciWrite32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_MCHBAR), 0xFED10000 |
> + BIT0);  DEBUG ((DEBUG_INFO, "MchBar - %x\n", MchBar));
> +
> +  DEBUG ((DEBUG_INFO, "VTd2 - %x\n", (MmioRead32 (MchBar +
> +R_SA_MCHBAR_VTD2_OFFSET) &~1)));
> +  MmioWrite32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET,
> +(UINT32)mPlatformVTdSample.Drhd2.RegisterBaseAddress | 1);
> +  DEBUG ((DEBUG_INFO, "VTd2 - %x\n", (MmioRead32 (MchBar +
> +R_SA_MCHBAR_VTD2_OFFSET) &~1))); }
> +
> +/**
> +  Patch Graphic UMA address in RMRR and base address.
> +**/
> +EFI_PEI_PPI_DESCRIPTOR *
> +PatchDmar (
> +  VOID
> +  )
> +{
> +  UINT32                  MchBar;
> +  UINT16                  IgdMode;
> +  UINT16                  GttMode;
> +  UINT32                  IgdMemSize;
> +  UINT32                  GttMemSize;
> +  MY_VTD_INFO_PPI         *PlatformVTdSample;
> +  EFI_PEI_PPI_DESCRIPTOR  *PlatformVTdInfoSampleDesc;
> +  MY_VTD_INFO_NO_IGD_PPI  *PlatformVTdNoIgdSample;
> +  EFI_PEI_PPI_DESCRIPTOR  *PlatformVTdNoIgdInfoSampleDesc;
> +
> +  DEBUG ((DEBUG_INFO, "PatchDmar\n"));
> +
> +  if (PciRead16 (PCI_LIB_ADDRESS(0, 2, 0, 0)) != 0xFFFF) {
> +    PlatformVTdSample = AllocateCopyPool (sizeof(MY_VTD_INFO_PPI),
> &mPlatformVTdSample);
> +    ASSERT(PlatformVTdSample != NULL);
> +    PlatformVTdInfoSampleDesc = AllocateCopyPool
> (sizeof(EFI_PEI_PPI_DESCRIPTOR), &mPlatformVTdInfoSampleDesc);
> +    ASSERT(PlatformVTdInfoSampleDesc != NULL);
> +    PlatformVTdInfoSampleDesc->Ppi = PlatformVTdSample;
> +
> +    ///
> +    /// Calculate IGD memsize
> +    ///
> +    IgdMode = ((PciRead16 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_GGC)) &
> B_SKL_SA_GGC_GMS_MASK) >> N_SKL_SA_GGC_GMS_OFFSET) & 0xFF;
> +    if (IgdMode < 0xF0) {
> +      IgdMemSize = IgdMode * 32 * (1024) * (1024);
> +    } else {
> +      IgdMemSize = 4 * (IgdMode - 0xF0 + 1) * (1024) * (1024);
> +    }
> +
> +    ///
> +    /// Calculate GTT mem size
> +    ///
> +    GttMemSize = 0;
> +    GttMode = (PciRead16 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_GGC)) &
> B_SKL_SA_GGC_GGMS_MASK) >> N_SKL_SA_GGC_GGMS_OFFSET;
> +    if (GttMode <= V_SKL_SA_GGC_GGMS_8MB) {
> +      GttMemSize = (1 << GttMode) * (1024) * (1024);
> +    }
> +
> +    PlatformVTdSample->Rmrr1.ReservedMemoryRegionBaseAddress  =
> (PciRead32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_TOLUD)) & ~(0x01)) - IgdMemSize -
> GttMemSize;
> +    PlatformVTdSample->Rmrr1.ReservedMemoryRegionLimitAddress =
> + PlatformVTdSample->Rmrr1.ReservedMemoryRegionBaseAddress +
> IgdMemSize
> + + GttMemSize - 1;
> +
> +    ///
> +    /// Update DRHD structures of DmarTable
> +    ///
> +    MchBar = PciRead32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_MCHBAR)) & ~BIT0;
> +
> +    DEBUG ((DEBUG_INFO, "VTd1 - %x\n", (MmioRead32 (MchBar +
> R_SA_MCHBAR_VTD1_OFFSET))));
> +    if ((MmioRead32 (MchBar + R_SA_MCHBAR_VTD1_OFFSET) &~1) != 0) {
> +      PlatformVTdSample->Drhd1.RegisterBaseAddress = (MmioRead32
> (MchBar + R_SA_MCHBAR_VTD1_OFFSET) &~1);
> +    } else {
> +      MmioWrite32 (MchBar + R_SA_MCHBAR_VTD1_OFFSET,
> (UINT32)PlatformVTdSample->Drhd1.RegisterBaseAddress | 1);
> +    }
> +
> +    DEBUG ((DEBUG_INFO, "VTd2 - %x\n", (MmioRead32 (MchBar +
> R_SA_MCHBAR_VTD2_OFFSET))));
> +    if ((MmioRead32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET) &~1) != 0) {
> +      PlatformVTdSample->Drhd2.RegisterBaseAddress = (MmioRead32
> (MchBar + R_SA_MCHBAR_VTD2_OFFSET) &~1);
> +    } else {
> +      MmioWrite32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET,
> (UINT32)PlatformVTdSample->Drhd2.RegisterBaseAddress | 1);
> +    }
> +
> +    return PlatformVTdInfoSampleDesc;
>    } else {
> -    IgdMemSize = 4 * (IgdMode - 0xF0 + 1) * (1024) * (1024);
> -  }
> +    PlatformVTdNoIgdSample = AllocateCopyPool
> (sizeof(MY_VTD_INFO_NO_IGD_PPI), &mPlatformVTdNoIgdSample);
> +    ASSERT(PlatformVTdNoIgdSample != NULL);
> +    PlatformVTdNoIgdInfoSampleDesc = AllocateCopyPool
> (sizeof(EFI_PEI_PPI_DESCRIPTOR), &mPlatformVTdNoIgdInfoSampleDesc);
> +    ASSERT(PlatformVTdNoIgdInfoSampleDesc != NULL);
> +    PlatformVTdNoIgdInfoSampleDesc->Ppi = PlatformVTdNoIgdSample;
> +
> +    ///
> +    /// Update DRHD structures of DmarTable
> +    ///
> +    MchBar = PciRead32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_MCHBAR)) & ~BIT0;
> 
> -  ///
> -  /// Calculate GTT mem size
> -  ///
> -  GttMemSize = 0;
> -  GttMode = (PciRead16 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_GGC)) &
> B_SKL_SA_GGC_GGMS_MASK) >> N_SKL_SA_GGC_GGMS_OFFSET;
> -  if (GttMode <= V_SKL_SA_GGC_GGMS_8MB) {
> -    GttMemSize = (1 << GttMode) * (1024) * (1024);
> +    DEBUG ((DEBUG_INFO, "VTd2 - %x\n", (MmioRead32 (MchBar +
> R_SA_MCHBAR_VTD2_OFFSET))));
> +    if ((MmioRead32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET) &~1) != 0) {
> +      PlatformVTdNoIgdSample->Drhd2.RegisterBaseAddress = (MmioRead32
> (MchBar + R_SA_MCHBAR_VTD2_OFFSET) &~1);
> +    } else {
> +      MmioWrite32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET,
> (UINT32)PlatformVTdNoIgdSample->Drhd2.RegisterBaseAddress | 1);
> +    }
> +
> +    return PlatformVTdNoIgdInfoSampleDesc;
>    }
> +}
> 
> -  mPlatformVTdSample.Rmrr1.ReservedMemoryRegionBaseAddress  =
> (PciRead32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_TOLUD)) & ~(0x01)) - IgdMemSize -
> GttMemSize;
> -  mPlatformVTdSample.Rmrr1.ReservedMemoryRegionLimitAddress =
> mPlatformVTdSample.Rmrr1.ReservedMemoryRegionBaseAddress +
> IgdMemSize + GttMemSize - 1;
> +/**
> +  Install Firmware Volume Hob's once there is main memory
> 
> -  ///
> -  /// Update DRHD structures of DmarTable
> -  ///
> -  MchBar = PciRead32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_MCHBAR)) & ~BIT0;
> -  mPlatformVTdSample.Drhd1.RegisterBaseAddress = (MmioRead32 (MchBar +
> R_SA_MCHBAR_VTD1_OFFSET) &~1);
> -  mPlatformVTdSample.Drhd2.RegisterBaseAddress = (MmioRead32 (MchBar +
> R_SA_MCHBAR_VTD2_OFFSET) &~1);
> +  @param[in]  PeiServices       General purpose services available to every
> PEIM.
> +  @param[in]  NotifyDescriptor  Notify that this module published.
> +  @param[in]  Ppi               PPI that was installed.
> +
> +  @retval     EFI_SUCCESS       The function completed successfully.
> +**/
> +EFI_STATUS
> +EFIAPI
> +SiliconInitializedPpiNotifyCallback (
> +  IN CONST EFI_PEI_SERVICES     **PeiServices,
> +  IN EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDescriptor,
> +  IN VOID                       *Ppi
> +  )
> +{
> +  EFI_STATUS               Status;
> +  EFI_PEI_PPI_DESCRIPTOR   *PpiDesc;
> +
> +  PpiDesc = PatchDmar ();
> +
> +  Status = PeiServicesReInstallPpi (&mPlatformVTdNoIgdInfoSampleDesc,
> + PpiDesc);  ASSERT_EFI_ERROR (Status);  return EFI_SUCCESS;
>  }
> 
> +EFI_PEI_NOTIFY_DESCRIPTOR mSiliconInitializedNotifyList = {
> +  (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK |
> +EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
> +  &gEdkiiSiliconInitializedPpiGuid,
> +  (EFI_PEIM_NOTIFY_ENTRY_POINT) SiliconInitializedPpiNotifyCallback
> +};
> +
>  /**
>    Platform VTd Info sample driver.
> 
> @@ -190,12 +333,37 @@ PlatformVTdInfoSampleInitialize (
>    IN CONST EFI_PEI_SERVICES     **PeiServices
>    )
>  {
> -  EFI_STATUS  Status;
> +  EFI_STATUS               Status;
> +  BOOLEAN                  SiliconInitialized;
> +  VOID                     *SiliconInitializedPpi;
> +  EFI_PEI_PPI_DESCRIPTOR   *PpiDesc;
> +
> +  SiliconInitialized = FALSE;
> +  //
> +  // Check if silicon is initialized.
> +  //
> +  Status = PeiServicesLocatePpi (
> +             &gEdkiiSiliconInitializedPpiGuid,
> +             0,
> +             NULL,
> +             &SiliconInitializedPpi
> +             );
> +  if (!EFI_ERROR(Status)) {
> +    SiliconInitialized = TRUE;
> +  }
> +  DEBUG ((DEBUG_INFO, "SiliconInitialized - %x\n",
> + SiliconInitialized));  if (!SiliconInitialized) {
> +    Status = PeiServicesNotifyPpi (&mSiliconInitializedNotifyList);
> +    InitDmar ();
> 
> -  PatchDmar ();
> +    Status = PeiServicesInstallPpi (&mPlatformVTdNoIgdInfoSampleDesc);
> +    ASSERT_EFI_ERROR (Status);
> +  } else {
> +    PpiDesc = PatchDmar ();
> 
> -  Status = PeiServicesInstallPpi (&mPlatformVTdInfoSampleDesc);
> -  ASSERT_EFI_ERROR (Status);
> +    Status = PeiServicesInstallPpi (PpiDesc);
> +    ASSERT_EFI_ERROR (Status);
> +  }
> 
>    return Status;
>  }
> diff --git
> a/IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSam
> plePei.inf
> b/IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSam
> plePei.inf
> index 96adb70..a4ffe51 100644
> ---
> a/IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSam
> plePei.inf
> +++ b/IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdIn
> +++ foSamplePei.inf
> @@ -47,7 +47,7 @@
>    gEdkiiVTdInfoPpiGuid         ## PRODUCES
> 
>  [Depex]
> -  gEfiPeiMemoryDiscoveredPpiGuid
> +  gEfiPeiMasterBootModePpiGuid
> 
>  [UserExtensions.TianoCore."ExtraFiles"]
>    PlatformVTdInfoSamplePeiExtra.uni
> --
> 2.7.4.windows.1
> 
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel


^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2017-10-27 12:26 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-10-27  5:40 [PATCH V2 0/2] IntelSiliconPkg: Add Pre-Memory DMA protection in PEI Jiewen Yao
2017-10-27  5:40 ` [PATCH V2 1/2] IntelSiliconPkg/VtdPmrPei: Add premem support Jiewen Yao
2017-10-27  6:53   ` Zeng, Star
2017-10-27  5:40 ` [PATCH V2 2/2] IntelSiliconPkg/VtdPeiSample: " Jiewen Yao
2017-10-27  6:55   ` Zeng, Star
2017-10-27  8:47     ` Zeng, Star
2017-10-27 12:30       ` Yao, Jiewen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox