summaryrefslogtreecommitdiffstats
path: root/MdeModulePkg
diff options
context:
space:
mode:
authorArd Biesheuvel <ard.biesheuvel@linaro.org>2016-09-05 09:55:16 +0100
committerArd Biesheuvel <ard.biesheuvel@linaro.org>2016-09-06 15:46:38 +0100
commite58a71d9c50ba641b5ab19f5ce2cbf772187de4d (patch)
treed6926b29ec202ba6bd623d781b83feceff30617e /MdeModulePkg
parent5c1b371a8839f970a45df3342529d034524f2507 (diff)
downloadedk2-e58a71d9c50ba641b5ab19f5ce2cbf772187de4d.tar.gz
edk2-e58a71d9c50ba641b5ab19f5ce2cbf772187de4d.tar.bz2
edk2-e58a71d9c50ba641b5ab19f5ce2cbf772187de4d.zip
MdeModulePkg/PciHostBridgeDxe: restrict 64-bit DMA to devices that support it
Currently, the EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE attribute is completely ignored by the PCI host bridge driver, which means that, on an implementation that supports DMA above 4 GB, allocations above 4 GB may be provided to devices that have not expressed support for it. So in addition to checking 'RootBridge->DmaAbove4G' to establish whether the root bridge itself supports DMA above 4 GB, we must also take into account the operation type (EfiPciOperationBusMaster{Read|Write|CommonBuffer}64), and the EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE attribute, when mapping and allocating DMA memory, respectively. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> Reviewed-by: Ruiyu Ni <Ruiyu.ni@intel.com>
Diffstat (limited to 'MdeModulePkg')
-rw-r--r--MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c14
1 files changed, 10 insertions, 4 deletions
diff --git a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c
index b2d76d67af..8af131b0af 100644
--- a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c
+++ b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c
@@ -1073,10 +1073,15 @@ RootBridgeIoMap (
RootBridge = ROOT_BRIDGE_FROM_THIS (This);
PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress;
- if (!RootBridge->DmaAbove4G && ((PhysicalAddress + *NumberOfBytes) > SIZE_4GB)) {
+ if ((!RootBridge->DmaAbove4G ||
+ (Operation != EfiPciOperationBusMasterRead64 &&
+ Operation != EfiPciOperationBusMasterWrite64 &&
+ Operation != EfiPciOperationBusMasterCommonBuffer64)) &&
+ ((PhysicalAddress + *NumberOfBytes) > SIZE_4GB)) {
+
//
- // If the root bridge can not handle performing DMA above 4GB but
- // any part of the DMA transfer being mapped is above 4GB, then
+ // If the root bridge or the device cannot handle performing DMA above
+ // 4GB but any part of the DMA transfer being mapped is above 4GB, then
// map the DMA transfer to a buffer below 4GB.
//
@@ -1308,7 +1313,8 @@ RootBridgeIoAllocateBuffer (
RootBridge = ROOT_BRIDGE_FROM_THIS (This);
AllocateType = AllocateAnyPages;
- if (!RootBridge->DmaAbove4G) {
+ if (!RootBridge->DmaAbove4G ||
+ (Attributes & EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE) == 0) {
//
// Limit allocations to memory below 4GB
//