Skip to content
Permalink
Browse files

Merged PR 1300: Require IOMMU protocol install before DMA access.

Add a PCD (gEfiMdeModulePkgTokenSpaceGuid.PcdRequireIommu) and support code to enable a platform to require that the IOMMU be present before allowing PCI DMA operations.
  • Loading branch information
Bret Barkelew authored and matthewfcarlson committed Jul 9, 2019
1 parent fbd4bb6 commit 602c7663d30b2db0af2c0efb5f2923202b4ecb52
@@ -998,6 +998,16 @@ PciIoMap (
);
}

// MU_CHANGE [BEGIN] - Re-attempt to locate IoMmu protocol, if missing.
if (mIoMmuProtocol == NULL) {
gBS->LocateProtocol (
&gEdkiiIoMmuProtocolGuid,
NULL,
(VOID **) &mIoMmuProtocol
);
}
// MU_CHANGE [END]

if (mIoMmuProtocol != NULL) {
if (!EFI_ERROR (Status)) {
switch (Operation) {
@@ -1048,6 +1058,16 @@ PciIoUnmap (

PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);

// MU_CHANGE [BEGIN] - Re-attempt to locate IoMmu protocol, if missing.
if (mIoMmuProtocol == NULL) {
gBS->LocateProtocol (
&gEdkiiIoMmuProtocolGuid,
NULL,
(VOID **) &mIoMmuProtocol
);
}
// MU_CHANGE [END]

if (mIoMmuProtocol != NULL) {
mIoMmuProtocol->SetAttribute (
mIoMmuProtocol,
@@ -39,6 +39,11 @@
UefiLib
PciHostBridgeLib
TimerLib
PcdLib ## MU_CHANGE
ReportStatusCodeLib ## MU_CHANGE

[FeaturePcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdRequireIommu ## MU_CHANGE

[Protocols]
gEfiCpuIo2ProtocolGuid ## CONSUMES
@@ -11,10 +11,17 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include "PciRootBridge.h"
#include "PciHostResource.h"

// MU_CHANGE - Allow platform to disallow unprotected DMA access when done before IOMMU install.
#include <Library/ReportStatusCodeLib.h>

#define NO_MAPPING (VOID *) (UINTN) -1

#define RESOURCE_VALID(Resource) ((Resource)->Base <= (Resource)->Limit)

// MU_CHANGE - Allow platform to disallow unprotected DMA access when done before IOMMU install.
#define PCI_DMA_ORDERING_ERROR_STATUS_TYPE (EFI_ERROR_MAJOR | EFI_ERROR_CODE)
#define PCI_DMA_ORDERING_ERROR_CODE (EFI_IO_BUS_PCI | EFI_IOB_EC_NOT_CONFIGURED)

//
// Lookup table for increment values based on transfer widths
//
@@ -1230,6 +1237,7 @@ RootBridgeIoPciWrite (
@retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common buffer.
@retval EFI_DEVICE_ERROR The System hardware could not map the requested address.
@retval EFI_OUT_OF_RESOURCES The request could not be completed due to lack of resources.
@retval EFI_NOT_READY Require IOMMU PCD has been set and request happens before IOMMU protocol install. MU_CHANGE
**/
EFI_STATUS
EFIAPI
@@ -1261,6 +1269,15 @@ RootBridgeIoMap (

RootBridge = ROOT_BRIDGE_FROM_THIS (This);

// MU_CHANGE [BEGIN] - Allow platform to disallow unprotected DMA access when done before IOMMU install.
if (FeaturePcdGet (PcdRequireIommu) && mIoMmu == NULL) {
DEBUG ((DEBUG_ERROR, "%a - mIoMmuProtocol is NULL!\n", __FUNCTION__));
ASSERT (mIoMmu != NULL);
ReportStatusCode (PCI_DMA_ORDERING_ERROR_STATUS_TYPE, PCI_DMA_ORDERING_ERROR_CODE);
return EFI_NOT_READY;
}
// MU_CHANGE [END]

if (mIoMmu != NULL) {
if (!RootBridge->DmaAbove4G) {
//
@@ -1392,6 +1409,7 @@ RootBridgeIoMap (
@retval EFI_SUCCESS The range was unmapped.
@retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by Map().
@retval EFI_DEVICE_ERROR The data was not committed to the target system memory.
@retval EFI_NOT_READY Require IOMMU PCD has been set and request happens before IOMMU protocol install. MU_CHANGE
**/
EFI_STATUS
EFIAPI
@@ -1405,6 +1423,15 @@ RootBridgeIoUnmap (
PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
EFI_STATUS Status;

// MU_CHANGE [BEGIN] - Allow platform to disallow unprotected DMA access when done before IOMMU install.
if (FeaturePcdGet (PcdRequireIommu) && mIoMmu == NULL) {
DEBUG ((DEBUG_ERROR, "%a - mIoMmuProtocol is NULL!\n", __FUNCTION__ ));
ASSERT (mIoMmu != NULL);
ReportStatusCode (PCI_DMA_ORDERING_ERROR_STATUS_TYPE, PCI_DMA_ORDERING_ERROR_CODE);
return EFI_NOT_READY;
}
// MU_CHANGE [END]

if (mIoMmu != NULL) {
Status = mIoMmu->Unmap (
mIoMmu,
@@ -1489,6 +1516,7 @@ RootBridgeIoUnmap (
attribute bits are MEMORY_WRITE_COMBINE,
MEMORY_CACHED, and DUAL_ADDRESS_CYCLE.
@retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
@retval EFI_NOT_READY Require IOMMU PCD has been set and request happens before IOMMU protocol install. MU_CHANGE
**/
EFI_STATUS
EFIAPI
@@ -1531,6 +1559,15 @@ RootBridgeIoAllocateBuffer (

RootBridge = ROOT_BRIDGE_FROM_THIS (This);

// MU_CHANGE [BEGIN] - Allow platform to disallow unprotected DMA access when done before IOMMU install.
if (FeaturePcdGet (PcdRequireIommu) && mIoMmu == NULL) {
DEBUG ((DEBUG_ERROR, "%a - mIoMmuProtocol is NULL!\n", __FUNCTION__));
ASSERT (mIoMmu != NULL);
ReportStatusCode (PCI_DMA_ORDERING_ERROR_STATUS_TYPE, PCI_DMA_ORDERING_ERROR_CODE);
return EFI_NOT_READY;
}
// MU_CHANGE [END]

if (mIoMmu != NULL) {
if (!RootBridge->DmaAbove4G) {
//
@@ -1584,6 +1621,7 @@ RootBridgeIoAllocateBuffer (
@retval EFI_SUCCESS The requested memory pages were freed.
@retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and
Pages was not allocated with AllocateBuffer().
@retval EFI_NOT_READY Require IOMMU PCD has been set and request happens before IOMMU protocol install. MU_CHANGE
**/
EFI_STATUS
EFIAPI
@@ -1595,6 +1633,15 @@ RootBridgeIoFreeBuffer (
{
EFI_STATUS Status;

// MU_CHANGE [BEGIN] - Allow platform to disallow unprotected DMA access when done before IOMMU install.
if (FeaturePcdGet (PcdRequireIommu) && mIoMmu == NULL) {
DEBUG ((DEBUG_ERROR, "%a - mIoMmuProtocol is NULL!\n", __FUNCTION__));
ASSERT (mIoMmu != NULL);
ReportStatusCode (PCI_DMA_ORDERING_ERROR_STATUS_TYPE, PCI_DMA_ORDERING_ERROR_CODE);
return EFI_NOT_READY;
}
// MU_CHANGE [END]

if (mIoMmu != NULL) {
Status = mIoMmu->FreeBuffer (
mIoMmu,
@@ -941,6 +941,14 @@
# @Prompt Disable BME on Exit Boot Services
gEfiMdeModulePkgTokenSpaceGuid.PcdDisableBMEonEBS|TRUE|BOOLEAN|0x30002051

## MU_CHANGE
## Indicates if DMA is allowed before IOMMU protocol install
# If enabled, device wil assert and return EFI_DEVICE_ERROR on any DMA access before IOMMU Protocol Install.<BR><BR>
# TRUE - IOMMU protocol required for DMA access.<BR>
# FALSE - DMA Access can happen before IOMMU protocol install.<BR>
# @Prompt Enable DMA before IOMMU protocol.
gEfiMdeModulePkgTokenSpaceGuid.PcdRequireIommu|TRUE|BOOLEAN|0x30001057

[PcdsFeatureFlag.IA32, PcdsFeatureFlag.ARM, PcdsFeatureFlag.AARCH64]
gEfiMdeModulePkgTokenSpaceGuid.PcdPciDegradeResourceForOptionRom|FALSE|BOOLEAN|0x0001003a

0 comments on commit 602c766

Please sign in to comment.
You can’t perform that action at this time.