public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [edk2-devel][edk2-platforms][PATCH V1 1/1] WhitleyOpenBoardPkg: Enable VT-D support
@ 2021-09-22 21:43 Oram, Isaac W
  0 siblings, 0 replies; only message in thread
From: Oram, Isaac W @ 2021-09-22 21:43 UTC (permalink / raw)
  To: devel; +Cc: Nate DeSimone, Chasel Chiu

Implements VT-D DMAR table functionality.
VT-D is currently implemented as an OpenBoardPkg feature.
More work would be needed to promote to an Advanced Feature.
Specifically reducing dependencies and improving API and integration
with OpenBoardPkg ACPI implementation.

Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>
Cc: Chasel Chiu <chasel.chiu@intel.com>
Signed-off-by: Isaac Oram <isaac.w.oram@intel.com>
---
 Platform/Intel/WhitleyOpenBoardPkg/Features/AcpiVtd/AcpiVTD.c   | 604 ++++++++++++++++++++
 Platform/Intel/WhitleyOpenBoardPkg/Features/AcpiVtd/AcpiVTD.inf |  66 +++
 Platform/Intel/WhitleyOpenBoardPkg/Include/AcpiVTD.h            |  53 ++
 Platform/Intel/WhitleyOpenBoardPkg/Include/Protocol/DmaRemap.h  | 108 ++++
 Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.dec              |   4 +
 Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.dsc              |   2 +
 Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.fdf              |   2 +-
 Silicon/Intel/WhitleySiliconPkg/Include/IioSetupDefinitions.h   |   4 +
 8 files changed, 842 insertions(+), 1 deletion(-)

diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Features/AcpiVtd/AcpiVTD.c b/Platform/Intel/WhitleyOpenBoardPkg/Features/AcpiVtd/AcpiVTD.c
new file mode 100644
index 0000000000..310d15b9ad
--- /dev/null
+++ b/Platform/Intel/WhitleyOpenBoardPkg/Features/AcpiVtd/AcpiVTD.c
@@ -0,0 +1,604 @@
+/** @file AcpiVtd.c
+
+  @copyright
+  Copyright 1996 - 2021 Intel Corporation. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+//
+// Statements that include other files
+//
+#include <AcpiVtd.h>
+#include <Library/SetupLib.h>
+#include <IioRegs.h>
+#include <IioSetupDefinitions.h>
+#include <Protocol/Tcg2Protocol.h>
+#include <Library/TpmMeasurementLib.h>
+
+VTD_SUPPORT_INSTANCE mPrivateData;
+
+#define MAX_BUS_ADDR_WIDTH 45
+
+/**
+
+  Add DMAR entry
+
+  @param This        - DMA Remap protocol pointer
+  @param RemapType   - Type of DMA remapping structure to add
+  @param RemapEntry  - Entry to add
+
+  @retval EFI_INVALID_PARAMETER - DMA remapping support not initialized or entry is malformed
+  @retval EFI_UNSUPPORTED       - Adding entries is not supported
+  @retval EFI_SUCCESS           - The entry was inserted successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+InsertDmaRemap (
+  IN  DMA_REMAP_PROTOCOL                *This,
+  IN  REMAP_TYPE                        RemapType,
+  IN  VOID                              *RemapEntry
+  )
+{
+  UINTN                                                       DevIndex;
+  EFI_ACPI_DMAR_HEADER                                        *Dmar;
+  EFI_ACPI_DMAR_DRHD_HEADER                                   *Drhd;
+  EFI_ACPI_DMAR_RMRR_HEADER                                   *Rmrr;
+  EFI_ACPI_DMAR_SATC_HEADER                                   *Atsr;
+  EFI_ACPI_DMAR_RHSA_HEADER                                   *Rhsa;
+  EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER                 *DevScope;
+  DMAR_DRHD                                                   *DmaRemap;
+  DMAR_RMRR                                                   *RevMemRegion;
+  DMAR_ATSR                                                   *AtsrRegion;
+  DMAR_RHSA                                                   *RhsaRegion;
+  EFI_ACPI_DMAR_PCI_PATH                                      *PciPath;
+  EFI_ACPI_DMAR_PCI_PATH                                      *PciInputPath;
+
+  if (mPrivateData.Dmar == NULL) {
+      ASSERT (FALSE);
+      return EFI_INVALID_PARAMETER;
+  }
+
+  Dmar = mPrivateData.Dmar;
+  if (((UINT8 *) Dmar + Dmar->Header.Length) == NULL) {
+      ASSERT (FALSE);
+      return EFI_INVALID_PARAMETER;
+  }
+
+  if (RemapType == DrhdType) {
+    DmaRemap = (DMAR_DRHD *) RemapEntry;
+    ASSERT (DmaRemap->Signature == DRHD_SIGNATURE);
+    Drhd = (EFI_ACPI_DMAR_DRHD_HEADER *) ((UINT8 *) Dmar + Dmar->Header.Length);
+    if (Drhd == NULL) {
+      ASSERT (FALSE);
+      return EFI_INVALID_PARAMETER;
+    }
+
+    if (DmaRemap->RegisterBase == 0) {
+      return EFI_UNSUPPORTED;
+    }
+
+    Drhd->Header.Type         = EFI_ACPI_DMAR_TYPE_DRHD;
+    Drhd->Header.Length       = sizeof (EFI_ACPI_DMAR_DRHD_HEADER);
+    Drhd->Flags               = DmaRemap->Flags;
+    Drhd->SegmentNumber       = DmaRemap->SegmentNumber;
+    Drhd->RegisterBaseAddress = DmaRemap->RegisterBase;
+    DevScope                  = NULL;
+
+    for (DevIndex = 0; DevIndex < DmaRemap->DeviceScopeNumber; DevIndex++) {
+      if (((UINT8 *) Drhd + Drhd->Header.Length) == NULL) {
+          ASSERT (FALSE);
+          return EFI_INVALID_PARAMETER;
+      }
+
+      DevScope = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *) ((UINT8 *) Drhd + Drhd->Header.Length);
+      if (DevScope != NULL) {
+        DevScope->Type              = DmaRemap->DeviceScope[DevIndex].DeviceType;
+        DevScope->Length            = sizeof (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER);
+        DevScope->EnumerationId     = DmaRemap->DeviceScope[DevIndex].EnumerationID;
+        DevScope->StartBusNumber    = DmaRemap->DeviceScope[DevIndex].StartBusNumber;
+        if (((UINT8 *) DevScope + DevScope->Length) == NULL) {
+          ASSERT (FALSE);
+          return EFI_INVALID_PARAMETER;
+        }
+
+        PciPath = (EFI_ACPI_DMAR_PCI_PATH *) ((UINT8 *) DevScope + DevScope->Length);
+        PciInputPath = (EFI_ACPI_DMAR_PCI_PATH *) DmaRemap->DeviceScope[DevIndex].PciNode;
+        while (*(UINT8 *) PciInputPath != (UINT8) -1) {
+          CopyMem(PciPath, PciInputPath, sizeof (EFI_ACPI_DMAR_PCI_PATH));
+          DevScope->Length += sizeof (EFI_ACPI_DMAR_PCI_PATH);
+          PciInputPath++;
+          PciPath++;
+        }
+        Drhd->Header.Length = Drhd->Header.Length + (UINT16) DevScope->Length;
+      } else {
+        DEBUG ((DEBUG_ERROR, "DevScope Error. Invalid pointer.\n"));
+      }
+    }
+
+    Dmar->Header.Length += Drhd->Header.Length;
+
+  } else if (RemapType == RmrrType) {
+    RevMemRegion = (DMAR_RMRR *) RemapEntry;
+    ASSERT (RevMemRegion->Signature == RMRR_SIGNATURE);
+    Rmrr = (EFI_ACPI_DMAR_RMRR_HEADER *) ((UINT8 *) Dmar + Dmar->Header.Length);
+    if (Rmrr == NULL) {
+      ASSERT (FALSE);
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Rmrr->Header.Type                       = EFI_ACPI_DMAR_TYPE_RMRR;
+    Rmrr->Header.Length                     = sizeof (EFI_ACPI_DMAR_RMRR_HEADER);
+    Rmrr->SegmentNumber                     = RevMemRegion->SegmentNumber;
+    Rmrr->ReservedMemoryRegionBaseAddress   = RevMemRegion->RsvdMemBase;
+    Rmrr->ReservedMemoryRegionLimitAddress  = RevMemRegion->RsvdMemLimit;
+
+    DevScope = NULL;
+    for (DevIndex = 0; DevIndex < RevMemRegion->DeviceScopeNumber; DevIndex++) {
+      if (((UINT8 *) Rmrr + Rmrr->Header.Length) == NULL) {
+        ASSERT (FALSE);
+        return EFI_INVALID_PARAMETER;
+      }
+
+      DevScope                        = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *) ((UINT8 *) Rmrr + Rmrr->Header.Length);
+      if (DevScope != NULL) {
+        DevScope->Type                  = RevMemRegion->DeviceScope[DevIndex].DeviceType;
+        DevScope->StartBusNumber        = RevMemRegion->DeviceScope[DevIndex].StartBusNumber;
+        DevScope->Length                = sizeof (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER);
+        if (((UINT8 *) DevScope + DevScope->Length) == NULL) {
+          ASSERT (FALSE);
+          return EFI_INVALID_PARAMETER;
+        }
+
+        PciPath                         = (EFI_ACPI_DMAR_PCI_PATH *) ((UINT8 *) DevScope + DevScope->Length);
+        PciInputPath                    = (EFI_ACPI_DMAR_PCI_PATH *) RevMemRegion->DeviceScope[DevIndex].PciNode;
+        while (*(UINT8 *) PciInputPath != (UINT8) -1) {
+          CopyMem (PciPath, PciInputPath, sizeof (EFI_ACPI_DMAR_PCI_PATH));
+          DevScope->Length += sizeof (EFI_ACPI_DMAR_PCI_PATH);
+          PciInputPath++;
+          PciPath++;
+        }
+        Rmrr->Header.Length = Rmrr->Header.Length + (UINT16) DevScope->Length;
+      } else {
+        DEBUG ((DEBUG_ERROR, "DevScope Error. Invalid pointer.\n"));
+      }
+    }
+
+    Dmar->Header.Length += Rmrr->Header.Length;
+
+  } else if (RemapType == AtsrType) {
+    AtsrRegion = (DMAR_ATSR *) RemapEntry;
+    ASSERT (AtsrRegion->Signature == ATSR_SIGNATURE);
+    Atsr = (EFI_ACPI_DMAR_SATC_HEADER *) ((UINT8 *) Dmar + Dmar->Header.Length);
+    if (Atsr == NULL) {
+      ASSERT (FALSE);
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Atsr->Header.Type   = EFI_ACPI_DMAR_TYPE_ATSR;
+    Atsr->Flags         = AtsrRegion->Flags;
+    Atsr->SegmentNumber = AtsrRegion->SegmentNumber;
+    Atsr->Header.Length = sizeof (EFI_ACPI_DMAR_SATC_HEADER);
+
+    DevScope = NULL;
+    for (DevIndex = 0; DevIndex < AtsrRegion->DeviceScopeNumber; DevIndex++) {
+      if ((AtsrRegion->ATSRPresentBit & (01 << DevIndex)) == 00) {
+        continue;
+      }
+      if (((UINT8 *) Atsr + Atsr->Header.Length) == NULL) {
+        ASSERT (FALSE);
+        return EFI_INVALID_PARAMETER;
+      }
+
+      DevScope = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *) ((UINT8 *) Atsr + Atsr->Header.Length);
+      if (DevScope != NULL) {
+        DevScope->Type              = AtsrRegion->DeviceScope[DevIndex].DeviceType;
+        DevScope->StartBusNumber    = AtsrRegion->DeviceScope[DevIndex].StartBusNumber;
+        DevScope->Length            = sizeof (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER);
+        if (((UINT8 *) DevScope + DevScope->Length) == NULL) {
+          ASSERT (FALSE);
+          return EFI_INVALID_PARAMETER;
+        }
+
+        PciPath = (EFI_ACPI_DMAR_PCI_PATH *) ((UINT8 *) DevScope + DevScope->Length);
+        PciInputPath = (EFI_ACPI_DMAR_PCI_PATH *) AtsrRegion->DeviceScope[DevIndex].PciNode;
+        while (*(UINT8 *) PciInputPath != (UINT8) -1) {
+          CopyMem(PciPath, PciInputPath, sizeof (EFI_ACPI_DMAR_PCI_PATH));
+          DevScope->Length += sizeof (EFI_ACPI_DMAR_PCI_PATH);
+          PciInputPath++;
+          PciPath++;
+        }
+
+        Atsr->Header.Length = Atsr->Header.Length + (UINT16) DevScope->Length;
+
+      } else {
+        DEBUG ((DEBUG_ERROR, "DevScope Error. Invalid pointer.\n"));
+      }
+    }
+
+    Dmar->Header.Length += Atsr->Header.Length;
+
+  } else if (RemapType == RhsaType) {
+    RhsaRegion = (DMAR_RHSA *) RemapEntry;
+    ASSERT (RhsaRegion->Signature == RHSA_SIGNATURE);
+
+    Rhsa                        = (EFI_ACPI_DMAR_RHSA_HEADER *) ((UINT8 *) Dmar + Dmar->Header.Length);
+    Rhsa->Header.Type           = EFI_ACPI_DMAR_TYPE_RHSA;
+    Rhsa->ProximityDomain       = RhsaRegion->Domian;
+    Rhsa->RegisterBaseAddress   = RhsaRegion->RegisterBase;
+    Rhsa->Header.Length         = sizeof (EFI_ACPI_DMAR_RHSA_HEADER);
+    Dmar->Header.Length         += Rhsa->Header.Length;
+  } else {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  ASSERT (Dmar->Header.Length < TABLE_SIZE);
+  return EFI_SUCCESS;
+}
+
+/**
+
+    Returns info about the provided entry
+
+    @param Entry      - DMA remapping entry
+    @param Type       - DMA remapping type
+    @param IncludeAll - Include all or all root port ASTR
+    @param Length     - GC_TODO: add arg description
+
+    @retval EFI_INVALID_PARAMETER - Null input pointer
+    @retval EFI_SUCCESS           - Table info updated
+
+**/
+EFI_STATUS
+GetTablesInfo (
+  IN     UINT8       *Entry,
+  IN OUT REMAP_TYPE  *Type,
+  IN OUT BOOLEAN     *IncludeAll,
+  IN OUT UINTN       *Length
+  )
+{
+  EFI_ACPI_DMAR_DRHD_HEADER  *Comm;
+
+  if (!Entry || !Type || !IncludeAll || !Length) {
+    ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Comm    = (EFI_ACPI_DMAR_DRHD_HEADER *) Entry;
+  *Length = Comm->Header.Length;
+
+  if (Comm->Header.Type == EFI_ACPI_DMAR_TYPE_RMRR) {
+    *Type = RmrrType;
+  } else if (Comm->Header.Type == EFI_ACPI_DMAR_TYPE_DRHD) {
+    *Type = DrhdType;
+  } else if (Comm->Header.Type == EFI_ACPI_DMAR_TYPE_ATSR) {
+    *Type = AtsrType;
+  } else if (Comm->Header.Type == EFI_ACPI_DMAR_TYPE_RHSA) {
+    *Type = RhsaType;
+  } else {
+    *Type = 0xFF;
+  }
+
+  if (Comm->Flags & EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL) {
+    *IncludeAll = TRUE;
+  } else {
+    *IncludeAll = FALSE;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+
+    Reorder the table entries
+
+    @param None
+
+    @retval EFI_SUCCESS - The table entries are ordered
+
+**/
+EFI_STATUS
+ReorderTables (
+  VOID
+  )
+{
+  REMAP_TYPE  Type;
+  BOOLEAN     IncludeAll;
+  UINTN       Length;
+  UINTN       CurrLength;
+  UINTN       TableLength;
+  UINT8       *Ptr;
+  UINT8       *PtrOrder;
+
+  Ptr       = (UINT8 *) mPrivateData.Dmar;
+  PtrOrder  = (UINT8 *) mPrivateData.DmarOrder;
+
+  CopyMem (PtrOrder, Ptr, sizeof (EFI_ACPI_DMAR_HEADER));
+  PtrOrder += sizeof (EFI_ACPI_DMAR_HEADER);
+
+  TableLength = mPrivateData.Dmar->Header.Length;
+
+  CurrLength  = sizeof (EFI_ACPI_DMAR_HEADER);
+  Ptr         = (UINT8 *) mPrivateData.Dmar + CurrLength;
+  while (CurrLength < TableLength) {
+    GetTablesInfo (Ptr, &Type, &IncludeAll, &Length);
+    if (Type == DrhdType && !IncludeAll) {
+      CopyMem (PtrOrder, Ptr, Length);
+      PtrOrder += Length;
+    }
+
+    Ptr += Length;
+    CurrLength += Length;
+  }
+
+  CurrLength  = sizeof (EFI_ACPI_DMAR_HEADER);
+  Ptr         = (UINT8 *) mPrivateData.Dmar + CurrLength;
+  while (CurrLength < TableLength) {
+    GetTablesInfo (Ptr, &Type, &IncludeAll, &Length);
+    if (Type == DrhdType && IncludeAll) {
+      CopyMem (PtrOrder, Ptr, Length);
+      PtrOrder += Length;
+    }
+
+    Ptr += Length;
+    CurrLength += Length;
+  }
+
+  CurrLength  = sizeof (EFI_ACPI_DMAR_HEADER);
+  Ptr         = (UINT8 *) mPrivateData.Dmar + CurrLength;
+  while (CurrLength < TableLength) {
+    GetTablesInfo (Ptr, &Type, &IncludeAll, &Length);
+    if (Type == RmrrType && !IncludeAll) {
+      CopyMem (PtrOrder, Ptr, Length);
+      PtrOrder += Length;
+    }
+
+    Ptr += Length;
+    CurrLength += Length;
+  }
+
+  CurrLength  = sizeof (EFI_ACPI_DMAR_HEADER);
+  Ptr         = (UINT8 *) mPrivateData.Dmar + CurrLength;
+  while (CurrLength < TableLength) {
+    GetTablesInfo (Ptr, &Type, &IncludeAll, &Length);
+    if (Type == AtsrType && !IncludeAll) {
+      CopyMem (PtrOrder, Ptr, Length);
+      PtrOrder += Length;
+    }
+
+    Ptr += Length;
+    CurrLength += Length;
+  }
+
+  CurrLength  = sizeof (EFI_ACPI_DMAR_HEADER);
+  Ptr         = (UINT8 *) mPrivateData.Dmar + CurrLength;
+  while (CurrLength < TableLength) {
+    GetTablesInfo (Ptr, &Type, &IncludeAll, &Length);
+    if (Type == RhsaType) {
+      CopyMem (PtrOrder, Ptr, Length);
+      PtrOrder += Length;
+    }
+
+    Ptr += Length;
+    CurrLength += Length;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+
+  Return a reordered version of the DMAR table provided on input
+
+  @param[in]      This      - DMA remap protocol
+  @param[in][out] DmarTable - DMAR table
+
+  @retval EFI_INVALID_PARAMETER - DmarTable NULL
+  @retval EFI_UNSUPPORTED       - DMAR table length doesn't meet expected value
+  @retval EFI_SUCCESS           - Updated DMAR table returned
+
+**/
+EFI_STATUS
+EFIAPI
+GetDmarTable (
+  IN     DMA_REMAP_PROTOCOL                *This,
+  IN OUT VOID                              **DmarTable
+  )
+{
+  if (DmarTable == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (mPrivateData.Dmar->Header.Length <= sizeof (EFI_ACPI_DMAR_HEADER)) {
+    return EFI_UNSUPPORTED;
+  }
+
+  ReorderTables ();
+  *DmarTable = mPrivateData.DmarOrder;
+  return EFI_SUCCESS;
+}
+
+#define TBT_SECURITY_EVENT_STRING      "DMA Protection Disabled"
+#define TBT_SECURITY_EVENT_STRING_LEN  (sizeof (TBT_SECURITY_EVENT_STRING) - 1)
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_EVENT                         EndOfDxeEvent;
+
+/**
+  Security EndOfDxe CallBack Function
+  If the firmware/BIOS has an option to enable and disable DMA protections via a VT-d switch in BIOS options, then the shipping configuration must be with VT-d protection enabled.
+  On every boot where VT-d/DMA protection is disabled, or will be disabled, or configured to a lower security state, and a platform has a TPM enabled, then the platform SHALL
+  extend an EV_EFI_ACTION event into PCR[7] before enabling external DMA
+  The event string SHALL be "DMA Protection Disabled". The platform firmware MUST log this measurement in the event log using the string "DMA Protection Disabled" for the Event Data.
+  Measure and log launch of TBT Security, and extend the measurement result into a specific PCR.
+  Extend an EV_EFI_ACTION event into PCR[7] before enabling external DMA. The event string SHALL be "DMA Protection Disabled". The platform firmware MUST log this measurement
+  in the event log using the string "DMA Protection Disabled" for the Event Data.
+
+  @param[in] Event     - A pointer to the Event that triggered the callback.
+  @param[in] Context   - A pointer to private data registered with the callback function.
+**/
+VOID
+EFIAPI
+ExtendPCR7CallBack (
+  IN EFI_EVENT          Event,
+  IN VOID               *Context
+  )
+{
+  UINTN                 Status;
+  UINT64                HashDataLen;
+
+  DEBUG ((DEBUG_INFO, "ExtendPCR7CallBack START\n"));
+
+  //
+  // When VT-d/DMA protection is disabled and a platform has a TPM enabled,
+  // the platform SHALL extend an EV_EFI_ACTION event into PCR[7].
+  //
+  HashDataLen = TBT_SECURITY_EVENT_STRING_LEN;
+
+  Status = TpmMeasureAndLogData (
+             7,
+             EV_EFI_ACTION,
+             TBT_SECURITY_EVENT_STRING,
+             (UINT32) HashDataLen,
+             TBT_SECURITY_EVENT_STRING,
+             HashDataLen
+             );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "TpmMeasureAndLogData Status: %r\n", Status));
+  } else {
+    DEBUG ((DEBUG_INFO, "TpmMeasureAndLogData Successfully\n"));
+  }
+
+  DEBUG ((DEBUG_INFO, "ExtendPCR7CallBack END\n"));
+}
+
+/**
+  Register an End of DXE event for extended a TPM log to PCR[7] when vtd is diable
+  This feature is introduced by TBT Security requirment
+**/
+VOID
+RegisterExtendPCR7CallBack (
+  VOID
+  )
+{
+  EFI_STATUS Status = EFI_SUCCESS;
+
+  //
+  // Register an End of DXE event for extended a TPM log to PCR[7].
+  //
+  DEBUG ((DEBUG_INFO, "Register an End of DXE event for extended a TPM log to PCR[7] when VTd/DMA protection is disabled.\n"));
+  Status = gBS->CreateEventEx (
+                  EVT_NOTIFY_SIGNAL,
+                  TPL_NOTIFY,
+                  ExtendPCR7CallBack,
+                  NULL,
+                  &gEfiEndOfDxeEventGroupGuid,
+                  &EndOfDxeEvent
+                  );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Failed to Register an End of DXE event for extended a TPM log to PCR[7], Status: %r\n", Status));
+  }
+}
+
+/**
+
+  VT-D Driver entry point
+
+  @param ImageHandle     The image handle.
+  @param SystemTable     The system table.
+
+  @retval Status - If not EFI_SUCCESS then an error occurred during initialization.
+
+**/
+EFI_STATUS
+EFIAPI
+VtdTableEntryPoint (
+  IN EFI_HANDLE                         ImageHandle,
+  IN EFI_SYSTEM_TABLE                   *SystemTable
+  )
+{
+  EFI_STATUS                            Status = EFI_SUCCESS;
+  EFI_ACPI_DMAR_HEADER                  *Dmar;
+  UINT64                                TempOemTableId;
+  UINT8                                 VTdSupport;
+  UINT8                                 DmaCtrlOptIn;
+  UINT8                                 InterruptRemap;
+  UINT8                                 X2ApicOptOut;
+  UINT8                                 ATS;
+  UINTN                                 Dmarlength;
+  UINT8                                 ControlIommu;
+
+  //
+  // Initialize our protocol
+  //
+  ZeroMem (&mPrivateData, sizeof (VTD_SUPPORT_INSTANCE));
+
+  Status = GetOptionData (&gEfiSocketIioVariableGuid, OFFSET_OF (SOCKET_IIO_CONFIGURATION, VTdSupport), &VTdSupport, sizeof (VTdSupport));
+  Status |= GetOptionData (&gEfiSocketIioVariableGuid, OFFSET_OF (SOCKET_IIO_CONFIGURATION, DmaCtrlOptIn), &DmaCtrlOptIn, sizeof (DmaCtrlOptIn));
+  Status |= GetOptionData (&gEfiSocketIioVariableGuid, OFFSET_OF (SOCKET_IIO_CONFIGURATION, InterruptRemap), &InterruptRemap, sizeof (InterruptRemap));
+  Status |= GetOptionData (&gEfiSocketIioVariableGuid, OFFSET_OF (SOCKET_IIO_CONFIGURATION, ATS), &ATS, sizeof (ATS));
+  Status |= GetOptionData (&gEfiSocketIioVariableGuid, OFFSET_OF (SOCKET_IIO_CONFIGURATION, X2ApicOptOut), &X2ApicOptOut, sizeof (X2ApicOptOut));
+
+  if (!EFI_ERROR (Status)) {
+    mPrivateData.DmaRemapProt.VTdSupport      = VTdSupport;
+    mPrivateData.DmaRemapProt.DmaCtrlOptIn    = DmaCtrlOptIn;
+    mPrivateData.DmaRemapProt.InterruptRemap  = VTdSupport && (InterruptRemap != IIO_OPTION_DISABLE);
+    mPrivateData.DmaRemapProt.ATS             = ATS;
+    mPrivateData.DmaRemapProt.X2ApicOptOut    = X2ApicOptOut;
+  }
+
+  Status = GetOptionData (&gEfiSocketIioVariableGuid, OFFSET_OF (SOCKET_IIO_CONFIGURATION, ControlIommu), &ControlIommu, sizeof (ControlIommu));
+  if (EFI_ERROR (Status)) {
+    ControlIommu = 0;
+  }
+
+  mPrivateData.Signature = EFI_ACPI_6_4_DMA_REMAPPING_TABLE_SIGNATURE;
+
+  Dmarlength = MAX_SOCKET * NUMBER_PORTS_PER_SOCKET * ( sizeof (EFI_ACPI_DMAR_HEADER) + sizeof (EFI_ACPI_DMAR_DRHD_HEADER) +
+                    sizeof (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER) + sizeof (EFI_ACPI_DMAR_PCI_PATH));
+
+  mPrivateData.Dmar = (EFI_ACPI_DMAR_HEADER *) AllocateZeroPool (Dmarlength);
+
+  mPrivateData.DmarOrder = (EFI_ACPI_DMAR_HEADER *) AllocateZeroPool (Dmarlength);
+
+  mPrivateData.DmaRemapProt.InsertDmaRemap = InsertDmaRemap;
+  mPrivateData.DmaRemapProt.GetDmarTable = GetDmarTable;
+
+  if (mPrivateData.Dmar != NULL) {
+    Dmar                          = mPrivateData.Dmar;
+    Dmar->Header.Length           = sizeof (EFI_ACPI_DMAR_HEADER);
+    Dmar->Header.Signature        = EFI_ACPI_6_4_DMA_REMAPPING_TABLE_SIGNATURE;
+    Dmar->Header.Revision         = EFI_ACPI_DMAR_REVISION;
+    Dmar->Header.OemRevision      = ACPI_DMAR_OEM_REVISION;
+    Dmar->Header.CreatorId        = ACPI_DMAR_OEM_CREATOR_ID;
+    Dmar->Header.CreatorRevision  = ACPI_DMAR_OEM_CREATOR_REVISION;
+    Dmar->HostAddressWidth        = MAX_BUS_ADDR_WIDTH;
+
+    TempOemTableId = PcdGet64 (PcdAcpiDefaultOemTableId);
+
+    CopyMem (Dmar->Header.OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (Dmar->Header.OemId));
+    CopyMem (&Dmar->Header.OemTableId, &TempOemTableId, sizeof (Dmar->Header.OemTableId));
+
+    Status = gBS->InstallProtocolInterface (
+                    &mPrivateData.Handle,
+                    &gDmaRemapProtocolGuid,
+                    EFI_NATIVE_INTERFACE,
+                    &mPrivateData.DmaRemapProt
+                    );
+  } else {
+
+    ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
+    Status = EFI_OUT_OF_RESOURCES;
+  }
+
+  if (FixedPcdGetBool (PcdConditionallyExtendPcr7)) {
+    if (!VTdSupport || !DmaCtrlOptIn || (ControlIommu == 0)) {
+      //
+      // Inform OS by TPM PCR7 when VTd/DMA protection is disabled.
+      //
+      RegisterExtendPCR7CallBack ();
+    }
+  }
+
+  return Status;
+}
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Features/AcpiVtd/AcpiVTD.inf b/Platform/Intel/WhitleyOpenBoardPkg/Features/AcpiVtd/AcpiVTD.inf
new file mode 100644
index 0000000000..a60deb9e9a
--- /dev/null
+++ b/Platform/Intel/WhitleyOpenBoardPkg/Features/AcpiVtd/AcpiVTD.inf
@@ -0,0 +1,66 @@
+## @file
+#
+# @copyright
+# Copyright 2009 - 2021 Intel Corporation. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = AcpiVtd
+  FILE_GUID                      = 64A11188-5B86-4f59-A702-73365896E65E
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = VtdTableEntryPoint
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64
+#
+
+[Sources]
+  AcpiVtd.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  WhitleyOpenBoardPkg/PlatformPkg.dec
+  WhitleySiliconPkg/SiliconPkg.dec
+  WhitleySiliconPkg/CpRcPkg.dec
+
+[LibraryClasses]
+  UefiDriverEntryPoint
+  IoLib
+  BaseMemoryLib
+  DebugLib
+  UefiRuntimeServicesTableLib
+  UefiBootServicesTableLib
+  DevicePathLib
+  HobLib
+  SetupLib
+  TpmMeasurementLib
+
+[Protocols]
+  gDmaRemapProtocolGuid                         ## CONSUMES
+
+[Guids]
+  gEfiHobListGuid                               ## CONSUMES
+  gEfiSocketIioVariableGuid                     ## CONSUMES
+  gEfiEndOfDxeEventGroupGuid                    ## CONSUMES
+
+[Pcd]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemId
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemTableId
+  gPlatformTokenSpaceGuid.PcdConditionallyExtendPcr7
+
+[FixedPcd]
+  gEfiCpRcPkgTokenSpaceGuid.PcdMaxCpuSocketCount
+  gEfiCpRcPkgTokenSpaceGuid.PcdMaxCpuCoreCount
+
+[Depex]
+  gEfiVariableArchProtocolGuid AND
+  gEfiIioUdsProtocolGuid AND
+  gEfiIioSystemProtocolGuid
+
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Include/AcpiVTD.h b/Platform/Intel/WhitleyOpenBoardPkg/Include/AcpiVTD.h
new file mode 100644
index 0000000000..d3ad4d7918
--- /dev/null
+++ b/Platform/Intel/WhitleyOpenBoardPkg/Include/AcpiVTD.h
@@ -0,0 +1,53 @@
+/** @file
+  This file describes the contents of the VTD ACPI Support
+
+  @copyright
+  Copyright 1996 - 2021 Intel Corporation. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _ACPI_VTD_H
+#define _ACPI_VTD_H
+
+//
+// Statements that include other files
+//
+#include <PiDxe.h>
+#include <Library/UefiLib.h>
+#include <Library/DxeServicesLib.h>
+#include <Library/PcdLib.h>
+#include <Library/IoLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/DevicePathLib.h>
+#include <Library/HobLib.h>
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/DmaRemappingReportingTable.h>
+#include <Protocol/DmaRemap.h>
+#include <Guid/HobList.h>
+#include <Guid/PlatformInfo.h>
+#include <Guid/SocketVariable.h>
+
+//
+// equates used in DMAR Table.
+//
+#define ACPI_DMAR_OEM_REVISION          0x01
+#define ACPI_DMAR_OEM_CREATOR_ID        0x01
+#define ACPI_DMAR_OEM_CREATOR_REVISION  0x01
+
+#define TABLE_SIZE                      4 * 1024
+
+typedef struct {
+  UINT32                                Signature;
+  EFI_HANDLE                            Handle;
+  DMA_REMAP_PROTOCOL                    DmaRemapProt;
+  EFI_ACPI_DMAR_HEADER                  *Dmar;
+  EFI_ACPI_DMAR_HEADER                  *DmarOrder;
+} VTD_SUPPORT_INSTANCE;
+
+#endif
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/Include/Protocol/DmaRemap.h b/Platform/Intel/WhitleyOpenBoardPkg/Include/Protocol/DmaRemap.h
new file mode 100644
index 0000000000..f784923953
--- /dev/null
+++ b/Platform/Intel/WhitleyOpenBoardPkg/Include/Protocol/DmaRemap.h
@@ -0,0 +1,108 @@
+/** @file
+  Protocol used to support ACPI VT-d DMA remapping reporting
+
+  @copyright
+  Copyright 2006 - 2021 Intel Corporation. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef __DMA_REMAP_H__
+#define __DMA_REMAP_H__
+
+//
+// Protocol for GUID.
+//
+typedef struct _DMA_REMAP_PROTOCOL DMA_REMAP_PROTOCOL;
+
+#define  DRHD_SIGNATURE  SIGNATURE_32 ('D', 'R', 'H', 'D')
+#define  RMRR_SIGNATURE  SIGNATURE_32 ('R', 'M', 'R', 'R')
+#define  ATSR_SIGNATURE  SIGNATURE_32 ('A', 'T', 'S', 'R')
+#define  RHSA_SIGNATURE  SIGNATURE_32 ('A', 'S', 'H', 'R')
+
+typedef enum {
+  DrhdType,
+  RmrrType,
+  AtsrType,
+  RhsaType
+} REMAP_TYPE;
+
+typedef enum {
+  PciEndpoint = 1,
+  PciBridge   = 2
+} PCI_DEV_TYPE;
+
+typedef struct {
+  UINT8         Device;
+  UINT8         Function;
+} PCI_NODE;
+
+typedef struct {
+  UINT8         DeviceType;
+  UINT8         EnumerationID;
+  UINT8         StartBusNumber;
+  PCI_NODE      *PciNode;
+} DEVICE_SCOPE;
+
+typedef struct {
+  UINT32        Signature;
+  UINT8         Flags;
+  UINT16        SegmentNumber;
+  UINT64        RegisterBase;
+  UINTN         DeviceScopeNumber;
+  DEVICE_SCOPE  *DeviceScope;
+} DMAR_DRHD;
+
+typedef struct {
+  UINT32        Signature;
+  UINT16        SegmentNumber;
+  UINT64        RsvdMemBase;
+  UINT64        RsvdMemLimit;
+  UINTN         DeviceScopeNumber;
+  DEVICE_SCOPE  *DeviceScope;
+} DMAR_RMRR;
+
+typedef struct {
+  UINT32        Signature;
+  UINT8         Flags;
+  UINT16        SegmentNumber;
+  UINTN         DeviceScopeNumber;
+  UINT32        ATSRPresentBit;
+  DEVICE_SCOPE  *DeviceScope;
+} DMAR_ATSR;
+
+typedef struct {
+  UINT32        Signature;
+  UINT64        RegisterBase;
+  UINT32        Domian;
+  UINT16        RhsaCount;
+} DMAR_RHSA;
+
+typedef
+EFI_STATUS
+(EFIAPI *INSERT_DMA_REMAP) (
+  IN  DMA_REMAP_PROTOCOL                                        *This,
+  IN  REMAP_TYPE                                                RemapType,
+  IN  VOID                                                      *RemapEntry
+  );
+
+typedef
+EFI_STATUS
+(EFIAPI *GET_DMAR_TABLE) (
+  IN  DMA_REMAP_PROTOCOL                                        *This,
+  IN  VOID                                                      **DmarTable
+  );
+
+typedef struct _DMA_REMAP_PROTOCOL {
+  BOOLEAN                   VTdSupport;
+  BOOLEAN                   DmaCtrlOptIn;
+  BOOLEAN                   InterruptRemap;
+  BOOLEAN                   X2ApicOptOut;
+  BOOLEAN                   ATS;
+  INSERT_DMA_REMAP          InsertDmaRemap;
+  GET_DMAR_TABLE            GetDmarTable;
+} DMA_REMAP_PROTOCOL;
+
+extern EFI_GUID gDmaRemapProtocolGuid;
+
+#endif
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.dec b/Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.dec
index 8e0b674505..1c25078044 100644
--- a/Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.dec
+++ b/Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.dec
@@ -152,6 +152,7 @@
   gEfiIpmiBootGuid                                    = { 0x5c9b75ec, 0x8ec7, 0x45f2, { 0x8f, 0x8f, 0xc1, 0xd8, 0x8f, 0x3b, 0x93, 0x45 } }
   gEfiGenericIpmiDriverInstalledGuid                  = { 0x7cdad61a, 0x3df8, 0x4425, { 0x96, 0x8c, 0x66, 0x28, 0xc8, 0x35, 0xff, 0xce } }
 
+  gDmaRemapProtocolGuid                            = { 0x4e873773, 0x8391, 0x4e47, { 0xb7, 0xf4, 0xca, 0xfb, 0xdc, 0xc4, 0xb2, 0x04 } }
 
 [PcdsFixedAtBuild]
 
@@ -210,6 +211,9 @@
   gCpPlatFlashTokenSpaceGuid.PcdFlashCfrRegionSize|0x01000000|UINT32|0xF00000B0
   gCpPlatFlashTokenSpaceGuid.PcdFlashCfrRegionBase|0xFF900000|UINT32|0xF00000B1
 
+  #If True, extend PCR7 when VT-d disabled.
+  gPlatformTokenSpaceGuid.PcdConditionallyExtendPcr7|FALSE|BOOLEAN|0xE0000045
+
 [PcdsFixedAtBuild, PcdsPatchableInModule]
   gPlatformTokenSpaceGuid.PcdShellFile|{ 0xB7, 0xD6, 0x7A, 0xC5, 0x15, 0x05, 0xA8, 0x40, 0x9D, 0x21, 0x55, 0x16, 0x52, 0x85, 0x4E, 0x37 }|VOID*|0x40000004
   ## Specify memory size with page number for a pre-allocated reserved memory to be used
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.dsc b/Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.dsc
index dc3dd0e026..22dee04ee8 100644
--- a/Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.dsc
+++ b/Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.dsc
@@ -745,6 +745,8 @@
       BoardAcpiTableLib|$(RP_PKG)/Library/BoardAcpiLib/DxeBoardAcpiTableLib.inf
   }
 
+  $(RP_PKG)/Features/AcpiVtd/AcpiVtd.inf
+
   $(PLATFORM_PKG)/Acpi/AcpiSmm/AcpiSmm.inf {
     <LibraryClasses>
       BoardAcpiEnableLib|$(RP_PKG)/Library/BoardAcpiLib/SmmBoardAcpiEnableLib.inf
diff --git a/Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.fdf b/Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.fdf
index d128f61b9d..20cfb47fdd 100644
--- a/Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.fdf
+++ b/Platform/Intel/WhitleyOpenBoardPkg/PlatformPkg.fdf
@@ -673,7 +673,7 @@ SET gMinPlatformPkgTokenSpaceGuid.PcdFlashAreaSize         = 0x01000000
   INF  MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf
 
   INF  MinPlatformPkg/Acpi/AcpiTables/AcpiPlatform.inf
-
+  INF  WhitleyOpenBoardPkg/Features/AcpiVtd/AcpiVtd.inf
   INF  MinPlatformPkg/Acpi/AcpiSmm/AcpiSmm.inf
 
 [FV.FvOsBoot]
diff --git a/Silicon/Intel/WhitleySiliconPkg/Include/IioSetupDefinitions.h b/Silicon/Intel/WhitleySiliconPkg/Include/IioSetupDefinitions.h
index 55496e60d4..b23d817205 100644
--- a/Silicon/Intel/WhitleySiliconPkg/Include/IioSetupDefinitions.h
+++ b/Silicon/Intel/WhitleySiliconPkg/Include/IioSetupDefinitions.h
@@ -57,4 +57,8 @@
 #define IIO_BIFURCATE_x2x2x2x2x2x2x2x2  0x19
 #define IIO_BIFURCATE_AUTO              0xFF
 
+#define IIO_OPTION_AUTO    2
+#define IIO_OPTION_ENABLE  1
+#define IIO_OPTION_DISABLE 0
+
 #endif /* _IIOSETUPDEFINITIONS_H_ */
-- 
2.27.0.windows.1


^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2021-09-22 21:43 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2021-09-22 21:43 [edk2-devel][edk2-platforms][PATCH V1 1/1] WhitleyOpenBoardPkg: Enable VT-D support Oram, Isaac W

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