From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) by mx.groups.io with SMTP id smtpd.web11.23.1632347002370419652 for ; Wed, 22 Sep 2021 14:43:23 -0700 Authentication-Results: mx.groups.io; dkim=missing; spf=pass (domain: intel.com, ip: 192.55.52.93, mailfrom: isaac.w.oram@intel.com) X-IronPort-AV: E=McAfee;i="6200,9189,10115"; a="220511297" X-IronPort-AV: E=Sophos;i="5.85,315,1624345200"; d="scan'208";a="220511297" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Sep 2021 14:43:20 -0700 X-IronPort-AV: E=Sophos;i="5.85,315,1624345200"; d="scan'208";a="484738743" Received: from iworam-desk.amr.corp.intel.com ([10.7.150.79]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Sep 2021 14:43:20 -0700 From: "Oram, Isaac W" To: devel@edk2.groups.io Cc: Nate DeSimone , Chasel Chiu Subject: [edk2-devel][edk2-platforms][PATCH V1 1/1] WhitleyOpenBoardPkg: Enable VT-D support Date: Wed, 22 Sep 2021 14:43:14 -0700 Message-Id: X-Mailer: git-send-email 2.27.0.windows.1 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 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 Cc: Chasel Chiu Signed-off-by: Isaac Oram --- 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.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +// +// Statements that include other files +// +#include +#include +#include +#include +#include +#include + +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.
+# +# 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.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef _ACPI_VTD_H +#define _ACPI_VTD_H + +// +// Statements that include other files +// +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// +// 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.
+ + 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 { 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