/** @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;
|
}
|