From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-it0-x22f.google.com (mail-it0-x22f.google.com [IPv6:2607:f8b0:4001:c0b::22f]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id A667B203BF103 for ; Wed, 24 May 2017 06:20:37 -0700 (PDT) Received: by mail-it0-x22f.google.com with SMTP id o5so38062007ith.1 for ; Wed, 24 May 2017 06:20:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc; bh=H8B/fMsJhetrtghYmZImAWQ3+bCSdjYXS44GppY7lFg=; b=jGF+BrckbMIVJ01LJzkAjbwkk0uB6NgRg+W3xG52kBotgxNy9J4fGKNtasConIjbqp vcLOSCsu/oj2wWlc8nKmHSPq3gdCWSjF6MfInPPDqmlT6DFnpv43ej0pSJzKeUrk7Kjp snKmgW9S3DePyNVl8/nLag590a1G0p9s6qqIQ= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc; bh=H8B/fMsJhetrtghYmZImAWQ3+bCSdjYXS44GppY7lFg=; b=PIEjRAIrYmRmY5uSLJL4MmTFZ4DiIgzzmclNgnHAXN8HMxll4A6w0Ua8FdVs3hM5xI ETPpvfkmJms3z4lUSnz8GKpUEBMKNQd41w+Az82QoBHju1IsmA0n9xfL5xpkkSEhTWet AKqws61KGJp/IBhDgV9VGgfed7tou3ks6HbQIEe61Kg1lqlB6SHf2j/7GX/XP9wWSXdp SBbA1FnqhVZS3Zsao08NSxgN1GHQW6O4+1NwXKnSbWw4qLo5Q4X+FAYWK2NMasxrvTjo hHWq975Tcz4kbzNur5lZCN8jk4Gv3EJvdJOIUbUsALHxigJl71HSj3bYUSFSbDxzfc3Q t93w== X-Gm-Message-State: AODbwcB68vNuBRsf24hpOYQoloG3PNpf6BT8L/SPU1cJOFHF/QkGM9im xhEpUWuLfOzNDXgwRGVm9yZj173WPrIK X-Received: by 10.36.224.133 with SMTP id c127mr8585771ith.73.1495632036090; Wed, 24 May 2017 06:20:36 -0700 (PDT) MIME-Version: 1.0 Received: by 10.107.164.24 with HTTP; Wed, 24 May 2017 06:20:35 -0700 (PDT) In-Reply-To: <20170524103058.GC32240@bivouac.eciton.net> References: <20170502103202.4943-1-ard.biesheuvel@linaro.org> <20170522134956.GG1657@bivouac.eciton.net> <20170524103058.GC32240@bivouac.eciton.net> From: Ard Biesheuvel Date: Wed, 24 May 2017 06:20:35 -0700 Message-ID: To: Leif Lindholm Cc: "edk2-devel@lists.01.org" , "Duran, Leo" , "Yao, Jiewen" , Alexander Graf Subject: Re: [RFC PATCH] ArmPkg: implement generic SMMU driver to remap DRAM for 32-bit PCI DMA X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 24 May 2017 13:20:38 -0000 Content-Type: text/plain; charset="UTF-8" On 24 May 2017 at 03:30, Leif Lindholm wrote: > On Tue, May 23, 2017 at 03:36:24AM -0700, Ard Biesheuvel wrote: >> On 22 May 2017 at 06:49, Leif Lindholm wrote: >> > On Tue, May 02, 2017 at 11:32:02AM +0100, Ard Biesheuvel wrote: >> >> This implements a driver that uses any SMMU compatible with the generic >> >> ARM SMMU architecture to remap the lowest 4 GB of DRAM in a way that >> >> makes it accessible to PCI masters that are only 32-bit DMA capable. >> >> >> >> Note that this driver goes a bit beyond what is strictly necessary to >> >> support 32-bit DMA, given that it also creates an identity map of the >> >> lowest 4 GB of DRAM. This is intended for interoperability with external >> >> drivers that may use the PCI I/O protocol incorrectly (or not at all) >> >> and program host addresses into the DMA registers and/or rings without >> >> any regard for translation or address size. If a platform's base of DRAM >> >> is a power of 2, and if the platform runs UEFI entirely in the lowest >> >> 4 GB of DRAM, any host address access by a PCI master will hit the ID >> >> mapped window, and any truncation that may occur will convert the host >> >> address into the device address. >> >> >> >> Signed-off-by: Ard Biesheuvel >> >> --- >> >> >> >> This is based on Jiewen Yao's IOMMU protocol support series, v4. >> >> >> >> https://lists.01.org/pipermail/edk2-devel/2017-April/010330.html >> >> >> >> Tested with AMD Seattle, which has no DRAM below 4 GB. >> >> >> >> ArmPkg/ArmPkg.dec | 7 + >> >> ArmPkg/ArmPkg.dsc | 1 + >> >> ArmPkg/Drivers/GenericSmmuStaticPciDmaDxe/BmDma.c | 467 ++++++++++++++++++++ >> >> ArmPkg/Drivers/GenericSmmuStaticPciDmaDxe/GenericSmmuStaticPciDmaDxe.c | 323 ++++++++++++++ >> >> ArmPkg/Drivers/GenericSmmuStaticPciDmaDxe/GenericSmmuStaticPciDmaDxe.inf | 62 +++ >> >> 5 files changed, 860 insertions(+) >> >> >> >> diff --git a/ArmPkg/ArmPkg.dec b/ArmPkg/ArmPkg.dec >> >> index c4b4da2f95bb..96913e3c0713 100644 >> >> --- a/ArmPkg/ArmPkg.dec >> >> +++ b/ArmPkg/ArmPkg.dec >> >> @@ -322,3 +322,10 @@ [PcdsFixedAtBuild.common, PcdsDynamic.common] >> >> # >> >> gArmTokenSpaceGuid.PcdPciBusMin|0x0|UINT32|0x00000059 >> >> gArmTokenSpaceGuid.PcdPciBusMax|0x0|UINT32|0x0000005A >> >> + >> >> + # >> >> + # Base address and context interrupt of the generic SMMU that >> >> + # translates memory accesses made by PCI masters >> >> + # >> >> + gArmTokenSpaceGuid.PcdPciGenericSmmuBase|0x0|UINT64|0x0000005B >> >> + gArmTokenSpaceGuid.PcdPciGenericSmmuContextInterrupt|0x0|UINT16|0x0000005C >> >> diff --git a/ArmPkg/ArmPkg.dsc b/ArmPkg/ArmPkg.dsc >> >> index 9144334cb821..9bbc71fa2479 100644 >> >> --- a/ArmPkg/ArmPkg.dsc >> >> +++ b/ArmPkg/ArmPkg.dsc >> >> @@ -127,6 +127,7 @@ [Components.common] >> >> ArmPkg/Drivers/ArmGic/ArmGicDxe.inf >> >> ArmPkg/Drivers/ArmGic/ArmGicLib.inf >> >> ArmPkg/Drivers/ArmGic/ArmGicSecLib.inf >> >> + ArmPkg/Drivers/GenericSmmuStaticPciDmaDxe/GenericSmmuStaticPciDmaDxe.inf >> >> ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdogDxe.inf >> >> ArmPkg/Drivers/TimerDxe/TimerDxe.inf >> >> >> >> diff --git a/ArmPkg/Drivers/GenericSmmuStaticPciDmaDxe/BmDma.c b/ArmPkg/Drivers/GenericSmmuStaticPciDmaDxe/BmDma.c >> >> new file mode 100644 >> >> index 000000000000..629209e335e5 >> >> --- /dev/null >> >> +++ b/ArmPkg/Drivers/GenericSmmuStaticPciDmaDxe/BmDma.c >> >> @@ -0,0 +1,467 @@ >> >> +/** @file >> >> + BmDma related function >> >> + >> >> + Copyright (c) 2017, Intel Corporation. All rights reserved.
>> >> + Copyright (c) 2017, Linaro Ltd. All rights reserved.
>> >> + >> >> + This program and the accompanying materials >> >> + are licensed and made available under the terms and conditions of the BSD License >> >> + which accompanies this distribution. The full text of the license may be found at >> >> + http://opensource.org/licenses/bsd-license.php >> >> + >> >> + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, >> >> + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. >> >> + >> >> +**/ >> >> + >> >> +#include >> >> + >> >> +#include >> >> + >> >> +#include >> >> +#include >> >> +#include >> >> +#include >> >> +#include >> >> + >> >> +STATIC CONST UINT64 mTranslationBase = FixedPcdGet64 (PcdSystemMemoryBase); >> > >> > So, here is the only objection I have to the patch (apart from a >> > question below). I am _really_ not happy about the ARM-specific >> > PcdSystemMemoryBase (in general), although it is less evil than >> > PcdSystemMemorySize. >> > >> > Maybe I'm missing something, but I don't see anything ARM-specific >> > about this driver. If PcdSystemMemoryBase is the reason for placing it >> > under ArmPkg, can we migrate that option across somewhere else? >> > >> >> Of course it is ARM specific. SMMUs only exist on ARM systems, > > SMMUs, yes. IOMMUs, no. > >> and the >> driver reuses ArmMmuLib defines to populate the page table entries. > > Ah, managed to miss that bit. > The remainder of the code looks completely generic. > >> In general, I agree with the tendency to keep code out of ArmPkg, but >> in this case, I think it really belongs there. > > I'll concede it makes sense to keep it in ArmPkg for now, and > re-engineering it for complete portability when there are no other > potential users is a bit premature. > Indeed. Especially because the issue it addresses (i.e., all DRAM above 4 GB) is not equally likely to occur on other architectures. >> > Seems an added shame to put two new generic config options >> > (PcdPciGenericSmmuBase/PcdPciGenericSmmuContextInterrupt) under an >> > architecture-specific directory. >> > >> >> + >> >> +#define MAP_INFO_SIGNATURE SIGNATURE_32 ('D', 'M', 'A', 'P') >> >> +typedef struct { >> >> + UINT32 Signature; >> >> + LIST_ENTRY Link; >> >> + EDKII_IOMMU_OPERATION Operation; >> >> + UINTN NumberOfBytes; >> >> + UINTN NumberOfPages; >> >> + EFI_PHYSICAL_ADDRESS HostAddress; >> >> + EFI_PHYSICAL_ADDRESS MappedHostAddress; >> >> +} MAP_INFO; >> >> +#define MAP_INFO_FROM_LINK(a) CR (a, MAP_INFO, Link, MAP_INFO_SIGNATURE) >> >> + >> >> +STATIC LIST_ENTRY mMaps = INITIALIZE_LIST_HEAD_VARIABLE(mMaps); >> >> + >> >> +/** >> >> + Provides the controller-specific addresses required to access system memory from a >> >> + DMA bus master. >> >> + >> >> + @param This The protocol instance pointer. >> >> + @param Operation Indicates if the bus master is going to read or write to system memory. >> >> + @param HostAddress The system memory address to map to the PCI controller. >> >> + @param NumberOfBytes On input the number of bytes to map. On output the number of bytes >> >> + that were mapped. >> >> + @param DeviceAddress The resulting map address for the bus master PCI controller to use to >> >> + access the hosts HostAddress. >> >> + @param Mapping A resulting value to pass to Unmap(). >> >> + >> >> + @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes. >> >> + @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common buffer. >> >> + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. >> >> + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. >> >> + @retval EFI_DEVICE_ERROR The system hardware could not map the requested address. >> >> + >> >> +**/ >> >> +STATIC >> >> +EFI_STATUS >> >> +EFIAPI >> >> +IoMmuMap ( >> >> + IN EDKII_IOMMU_PROTOCOL *This, >> >> + IN EDKII_IOMMU_OPERATION Operation, >> >> + IN VOID *HostAddress, >> >> + IN OUT UINTN *NumberOfBytes, >> >> + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, >> >> + OUT VOID **Mapping >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + EFI_PHYSICAL_ADDRESS PhysicalAddress; >> >> + MAP_INFO *MapInfo; >> >> + BOOLEAN NeedRemap; >> >> + >> >> + if (HostAddress == NULL || NumberOfBytes == NULL || DeviceAddress == NULL || >> >> + Mapping == NULL) { >> >> + return EFI_INVALID_PARAMETER; >> >> + } >> >> + >> >> + // >> >> + // Make sure that Operation is valid >> >> + // >> >> + if ((UINT32) Operation >= EdkiiIoMmuOperationMaximum) { >> >> + return EFI_INVALID_PARAMETER; >> >> + } >> >> + >> >> + NeedRemap = FALSE; >> >> + PhysicalAddress = (UINTN)HostAddress; >> >> + >> >> + if ((PhysicalAddress + *NumberOfBytes) > mTranslationBase + SIZE_4GB) { >> >> + // >> >> + // 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. >> >> + // >> > >> > Request for clarification: is this because this driver is only invoked >> > where the root bridge is incapable? (The test looks unconditional.) >> > >> >> No, the root bridge driver always invokes the IOMMU protocol if there is one. >> >> Here we test whether the mapped buffer already lives in the first 4 GB >> of DRAM, otherwise we will use a bounce buffer. This driver never maps >> anything dynamically in the SMMU, it just allocates a bounce buffer >> from the 32-bit addressable range if required. > > Right, so could the comment be updated to say something more like > > // > // If any part of the DMA transfer being mapped is above 4GB, then > // map the DMA transfer to a buffer below 4GB. > // > > ? > To be pedantic, it should say 'to a buffer that is 32-bit addressable from the PCI side'. Will add that > The remainder of the comment is also useful, but would it not make > more sense in the function header? > Tbh I took Jiewen's code and added the SMMU/ARM bits. But I will change it nonetheless. > With that: > Reviewed-by: Leif Lindholm > Thanks >> >> + NeedRemap = TRUE; >> >> + } >> >> + >> >> + if ((Operation == EdkiiIoMmuOperationBusMasterCommonBuffer || >> >> + Operation == EdkiiIoMmuOperationBusMasterCommonBuffer64) && >> >> + NeedRemap) { >> >> + // >> >> + // Common Buffer operations can not be remapped. If the common buffer >> >> + // if above 4GB, then it is not possible to generate a mapping, so return >> >> + // an error. >> >> + // >> >> + return EFI_UNSUPPORTED; >> >> + } >> >> + >> >> + // >> >> + // Allocate a MAP_INFO structure to remember the mapping when Unmap() is >> >> + // called later. >> >> + // >> >> + MapInfo = AllocatePool (sizeof (MAP_INFO)); >> >> + if (MapInfo == NULL) { >> >> + *NumberOfBytes = 0; >> >> + return EFI_OUT_OF_RESOURCES; >> >> + } >> >> + >> >> + // >> >> + // Initialize the MAP_INFO structure >> >> + // >> >> + MapInfo->Signature = MAP_INFO_SIGNATURE; >> >> + MapInfo->Operation = Operation; >> >> + MapInfo->NumberOfBytes = *NumberOfBytes; >> >> + MapInfo->NumberOfPages = EFI_SIZE_TO_PAGES (MapInfo->NumberOfBytes); >> >> + MapInfo->HostAddress = PhysicalAddress; >> >> + MapInfo->MappedHostAddress = (EFI_PHYSICAL_ADDRESS)-1; >> >> + >> >> + // >> >> + // Allocate a buffer below 4GB to map the transfer to. >> >> + // >> >> + if (NeedRemap) { >> >> + MapInfo->MappedHostAddress = mTranslationBase + SIZE_4GB - 1; >> >> + Status = gBS->AllocatePages ( >> >> + AllocateMaxAddress, >> >> + EfiBootServicesData, >> >> + MapInfo->NumberOfPages, >> >> + &MapInfo->MappedHostAddress >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + FreePool (MapInfo); >> >> + *NumberOfBytes = 0; >> >> + return Status; >> >> + } >> >> + >> >> + // >> >> + // If this is a read operation from the Bus Master's point of view, >> >> + // then copy the contents of the real buffer into the mapped buffer >> >> + // so the Bus Master can read the contents of the real buffer. >> >> + // >> >> + if (Operation == EdkiiIoMmuOperationBusMasterRead || >> >> + Operation == EdkiiIoMmuOperationBusMasterRead64) { >> >> + CopyMem ( >> >> + (VOID *)(UINTN)MapInfo->MappedHostAddress, >> >> + (VOID *)(UINTN)MapInfo->HostAddress, >> >> + MapInfo->NumberOfBytes >> >> + ); >> >> + } >> >> + } else { >> >> + MapInfo->MappedHostAddress = MapInfo->HostAddress; >> >> + } >> >> + >> >> + InsertTailList (&mMaps, &MapInfo->Link); >> >> + >> >> + // >> >> + // The DeviceAddress is the address of the maped buffer below 4GB >> >> + // >> >> + *DeviceAddress = MapInfo->MappedHostAddress - mTranslationBase; >> >> + >> >> + // >> >> + // Return a pointer to the MAP_INFO structure in Mapping >> >> + // >> >> + *Mapping = MapInfo; >> >> + >> >> + return EFI_SUCCESS; >> >> +} >> >> + >> >> +/** >> >> + Completes the Map() operation and releases any corresponding resources. >> >> + >> >> + @param This The protocol instance pointer. >> >> + @param Mapping The mapping value returned from Map(). >> >> + >> >> + @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. >> >> +**/ >> >> +STATIC >> >> +EFI_STATUS >> >> +EFIAPI >> >> +IoMmuUnmap ( >> >> + IN EDKII_IOMMU_PROTOCOL *This, >> >> + IN VOID *Mapping >> >> + ) >> >> +{ >> >> + MAP_INFO *MapInfo; >> >> + LIST_ENTRY *Link; >> >> + >> >> + if (Mapping == NULL) { >> >> + return EFI_INVALID_PARAMETER; >> >> + } >> >> + >> >> + MapInfo = NULL; >> >> + for (Link = GetFirstNode (&mMaps) >> >> + ; !IsNull (&mMaps, Link) >> >> + ; Link = GetNextNode (&mMaps, Link) >> >> + ) { >> >> + MapInfo = MAP_INFO_FROM_LINK (Link); >> >> + if (MapInfo == Mapping) { >> >> + break; >> >> + } >> >> + } >> >> + // >> >> + // Mapping is not a valid value returned by Map() >> >> + // >> >> + if (MapInfo != Mapping) { >> >> + return EFI_INVALID_PARAMETER; >> >> + } >> >> + RemoveEntryList (&MapInfo->Link); >> >> + >> >> + if (MapInfo->MappedHostAddress != MapInfo->HostAddress) { >> >> + // >> >> + // If this is a write operation from the Bus Master's point of view, >> >> + // then copy the contents of the mapped buffer into the real buffer >> >> + // so the processor can read the contents of the real buffer. >> >> + // >> >> + if (MapInfo->Operation == EdkiiIoMmuOperationBusMasterWrite || >> >> + MapInfo->Operation == EdkiiIoMmuOperationBusMasterWrite64) { >> >> + CopyMem ( >> >> + (VOID *)(UINTN)MapInfo->HostAddress, >> >> + (VOID *)(UINTN)MapInfo->MappedHostAddress, >> >> + MapInfo->NumberOfBytes >> >> + ); >> >> + } >> >> + >> >> + // >> >> + // Free the mapped buffer and the MAP_INFO structure. >> >> + // >> >> + gBS->FreePages (MapInfo->MappedHostAddress, MapInfo->NumberOfPages); >> >> + } >> >> + >> >> + FreePool (Mapping); >> >> + return EFI_SUCCESS; >> >> +} >> >> + >> >> +/** >> >> + Allocates pages that are suitable for an OperationBusMasterCommonBuffer or >> >> + OperationBusMasterCommonBuffer64 mapping. >> >> + >> >> + @param This The protocol instance pointer. >> >> + @param Type This parameter is not used and must be ignored. >> >> + @param MemoryType The type of memory to allocate, EfiBootServicesData or >> >> + EfiRuntimeServicesData. >> >> + @param Pages The number of pages to allocate. >> >> + @param HostAddress A pointer to store the base system memory address of the >> >> + allocated range. >> >> + @param Attributes The requested bit mask of attributes for the allocated range. >> >> + >> >> + @retval EFI_SUCCESS The requested memory pages were allocated. >> >> + @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal attribute bits are >> >> + MEMORY_WRITE_COMBINE and MEMORY_CACHED. >> >> + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. >> >> + @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated. >> >> + >> >> +**/ >> >> +STATIC >> >> +EFI_STATUS >> >> +EFIAPI >> >> +IoMmuAllocateBuffer ( >> >> + IN EDKII_IOMMU_PROTOCOL *This, >> >> + IN EFI_ALLOCATE_TYPE Type, >> >> + IN EFI_MEMORY_TYPE MemoryType, >> >> + IN UINTN Pages, >> >> + IN OUT VOID **HostAddress, >> >> + IN UINT64 Attributes >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + EFI_PHYSICAL_ADDRESS PhysicalAddress; >> >> + >> >> + // >> >> + // Validate Attributes >> >> + // >> >> + if ((Attributes & EDKII_IOMMU_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER) != 0) { >> >> + return EFI_UNSUPPORTED; >> >> + } >> >> + >> >> + // >> >> + // Check for invalid inputs >> >> + // >> >> + if (HostAddress == NULL) { >> >> + return EFI_INVALID_PARAMETER; >> >> + } >> >> + >> >> + // >> >> + // The only valid memory types are EfiBootServicesData and >> >> + // EfiRuntimeServicesData >> >> + // >> >> + if (MemoryType != EfiBootServicesData && >> >> + MemoryType != EfiRuntimeServicesData) { >> >> + return EFI_INVALID_PARAMETER; >> >> + } >> >> + >> >> + // >> >> + // Limit allocations to memory covered by the remapped window. >> >> + // >> >> + PhysicalAddress = mTranslationBase + SIZE_4GB - 1; >> >> + Status = gBS->AllocatePages ( >> >> + AllocateMaxAddress, >> >> + MemoryType, >> >> + Pages, >> >> + &PhysicalAddress >> >> + ); >> >> + if (!EFI_ERROR (Status)) { >> >> + *HostAddress = (VOID *)(UINTN)PhysicalAddress; >> >> + } >> >> + >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Frees memory that was allocated with AllocateBuffer(). >> >> + >> >> + @param This The protocol instance pointer. >> >> + @param Pages The number of pages to free. >> >> + @param HostAddress The base system memory address of the allocated range. >> >> + >> >> + @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(). >> >> + >> >> +**/ >> >> +STATIC >> >> +EFI_STATUS >> >> +EFIAPI >> >> +IoMmuFreeBuffer ( >> >> + IN EDKII_IOMMU_PROTOCOL *This, >> >> + IN UINTN Pages, >> >> + IN VOID *HostAddress >> >> + ) >> >> +{ >> >> + return gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress, Pages); >> >> +} >> >> + >> >> +/** >> >> + Set IOMMU attribute for a system memory. >> >> + >> >> + If the IOMMU protocol exists, the system memory cannot be used >> >> + for DMA by default. >> >> + >> >> + When a device requests a DMA access for a system memory, >> >> + the device driver need use SetAttribute() to update the IOMMU >> >> + attribute to request DMA access (read and/or write). >> >> + >> >> + The DeviceHandle is used to identify which device submits the request. >> >> + The IOMMU implementation need translate the device path to an IOMMU device ID, >> >> + and set IOMMU hardware register accordingly. >> >> + 1) DeviceHandle can be a standard PCI device. >> >> + The memory for BusMasterRead need set EDKII_IOMMU_ACCESS_READ. >> >> + The memory for BusMasterWrite need set EDKII_IOMMU_ACCESS_WRITE. >> >> + The memory for BusMasterCommonBuffer need set EDKII_IOMMU_ACCESS_READ|EDKII_IOMMU_ACCESS_WRITE. >> >> + After the memory is used, the memory need set 0 to keep it being protected. >> >> + 2) DeviceHandle can be an ACPI device (ISA, I2C, SPI, etc). >> >> + The memory for DMA access need set EDKII_IOMMU_ACCESS_READ and/or EDKII_IOMMU_ACCESS_WRITE. >> >> + >> >> + @param[in] This The protocol instance pointer. >> >> + @param[in] DeviceHandle The device who initiates the DMA access request. >> >> + @param[in] DeviceAddress The base of device memory address to be used as the DMA memory. >> >> + @param[in] Length The length of device memory address to be used as the DMA memory. >> >> + @param[in] IoMmuAccess The IOMMU access. >> >> + >> >> + @retval EFI_SUCCESS The IoMmuAccess is set for the memory range specified by DeviceAddress and Length. >> >> + @retval EFI_INVALID_PARAMETER DeviceHandle is an invalid handle. >> >> + @retval EFI_INVALID_PARAMETER DeviceAddress is not IoMmu Page size aligned. >> >> + @retval EFI_INVALID_PARAMETER Length is not IoMmu Page size aligned. >> >> + @retval EFI_INVALID_PARAMETER Length is 0. >> >> + @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combination of access. >> >> + @retval EFI_UNSUPPORTED DeviceHandle is unknown by the IOMMU. >> >> + @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not supported by the IOMMU. >> >> + @retval EFI_UNSUPPORTED The IOMMU does not support the memory range specified by DeviceAddress and Length. >> >> + @retval EFI_OUT_OF_RESOURCES There are not enough resources available to modify the IOMMU access. >> >> + @retval EFI_DEVICE_ERROR The IOMMU device reported an error while attempting the operation. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +IoMmuSetAttribute ( >> >> + IN EDKII_IOMMU_PROTOCOL *This, >> >> + IN EFI_HANDLE DeviceHandle, >> >> + IN EFI_PHYSICAL_ADDRESS DeviceAddress, >> >> + IN UINT64 Length, >> >> + IN UINT64 IoMmuAccess >> >> + ) >> >> +{ >> >> + return EFI_UNSUPPORTED; >> >> +} >> >> + >> >> +/** >> >> + Set IOMMU attribute for a system memory. >> >> + >> >> + If the IOMMU protocol exists, the system memory cannot be used >> >> + for DMA by default. >> >> + >> >> + When a device requests a DMA access for a system memory, >> >> + the device driver need use SetAttribute() to update the IOMMU >> >> + attribute to request DMA access (read and/or write). >> >> + >> >> + The DeviceHandle is used to identify which device submits the request. >> >> + The IOMMU implementation need translate the device path to an IOMMU device ID, >> >> + and set IOMMU hardware register accordingly. >> >> + 1) DeviceHandle can be a standard PCI device. >> >> + The memory for BusMasterRead need set EDKII_IOMMU_ACCESS_READ. >> >> + The memory for BusMasterWrite need set EDKII_IOMMU_ACCESS_WRITE. >> >> + The memory for BusMasterCommonBuffer need set EDKII_IOMMU_ACCESS_READ|EDKII_IOMMU_ACCESS_WRITE. >> >> + After the memory is used, the memory need set 0 to keep it being protected. >> >> + 2) DeviceHandle can be an ACPI device (ISA, I2C, SPI, etc). >> >> + The memory for DMA access need set EDKII_IOMMU_ACCESS_READ and/or EDKII_IOMMU_ACCESS_WRITE. >> >> + >> >> + @param[in] This The protocol instance pointer. >> >> + @param[in] DeviceHandle The device who initiates the DMA access request. >> >> + @param[in] Mapping The mapping value returned from Map(). >> >> + @param[in] IoMmuAccess The IOMMU access. >> >> + >> >> + @retval EFI_SUCCESS The IoMmuAccess is set for the memory range specified by DeviceAddress and Length. >> >> + @retval EFI_INVALID_PARAMETER DeviceHandle is an invalid handle. >> >> + @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by Map(). >> >> + @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combination of access. >> >> + @retval EFI_UNSUPPORTED DeviceHandle is unknown by the IOMMU. >> >> + @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not supported by the IOMMU. >> >> + @retval EFI_UNSUPPORTED The IOMMU does not support the memory range specified by Mapping. >> >> + @retval EFI_OUT_OF_RESOURCES There are not enough resources available to modify the IOMMU access. >> >> + @retval EFI_DEVICE_ERROR The IOMMU device reported an error while attempting the operation. >> >> + >> >> +**/ >> >> +STATIC >> >> +EFI_STATUS >> >> +EFIAPI >> >> +IoMmuSetMappingAttribute ( >> >> + IN EDKII_IOMMU_PROTOCOL *This, >> >> + IN EFI_HANDLE DeviceHandle, >> >> + IN VOID *Mapping, >> >> + IN UINT64 IoMmuAccess >> >> + ) >> >> +{ >> >> + // >> >> + // We only support a static remapping of DRAM into the PCI address space >> >> + // so there is nothing we need to do to handle invocations of this protocol >> >> + // method. >> >> + // >> >> + return EFI_SUCCESS; >> >> +} >> >> + >> >> +EDKII_IOMMU_PROTOCOL mGenericSmmuIommuProtocol = { >> >> + EDKII_IOMMU_PROTOCOL_REVISION, >> >> + IoMmuSetAttribute, >> >> + IoMmuMap, >> >> + IoMmuUnmap, >> >> + IoMmuAllocateBuffer, >> >> + IoMmuFreeBuffer, >> >> + IoMmuSetMappingAttribute, >> >> +}; >> >> diff --git a/ArmPkg/Drivers/GenericSmmuStaticPciDmaDxe/GenericSmmuStaticPciDmaDxe.c b/ArmPkg/Drivers/GenericSmmuStaticPciDmaDxe/GenericSmmuStaticPciDmaDxe.c >> >> new file mode 100644 >> >> index 000000000000..8f5093af14ea >> >> --- /dev/null >> >> +++ b/ArmPkg/Drivers/GenericSmmuStaticPciDmaDxe/GenericSmmuStaticPciDmaDxe.c >> >> @@ -0,0 +1,323 @@ >> >> +/** @file >> >> + >> >> + Copyright (c) 2017, Linaro Ltd. All rights reserved.
>> >> + >> >> + This program and the accompanying materials >> >> + are licensed and made available under the terms and conditions of the BSD License >> >> + which accompanies this distribution. The full text of the license may be found at >> >> + http://opensource.org/licenses/bsd-license.php >> >> + >> >> + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, >> >> + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. >> >> + >> >> +**/ >> >> + >> >> +#include >> >> +#include >> >> +#include >> >> +#include >> >> +#include >> >> + >> >> +#include >> >> +#include >> >> +#include >> >> + >> >> +#include >> >> + >> >> +#define GL_CR0 0x0 >> >> +#define GL_CR0_CLIENTPD BIT0 >> >> + >> >> +#define GL_IDR0 0x20 >> >> +#define GL_IDR1 0x24 >> >> +#define GL_STLBIALL 0x60 >> >> +#define GL_TLBIALLNSNH 0x68 >> >> +#define GL_SMR0 0x800 >> >> +#define GL_S2CR0 0xc00 >> >> +#define GL_CBA2R0 0x1800 >> >> + >> >> +#define GL_IDR0_NUMSMRG_MASK 0xff >> >> + >> >> +#define GL_IDR1_NUMPAGENDXB_MASK 0x7 >> >> +#define GL_IDR1_NUMPAGENDXB_SHIFT 28 >> >> +#define GL_IDR1_PAGE_SIZE_64KB BIT31 >> >> + >> >> +#define CB_BASE(i) (mContextBankOffset + ((i) * SIZE_4KB)) >> >> + >> >> +#define CB_SCTLR_OFFSET 0x0 >> >> +#define CB_TTBR0_OFFSET 0x20 >> >> +#define CB_TTBCR_OFFSET 0x30 >> >> + >> >> +#define CB_FAR 0x60 >> >> +#define CB_FSR 0x58 >> >> +#define CB_FSYNR0 0x68 >> >> +#define CB_FSYNR1 0x6c >> >> + >> >> +#define TT_S2_MEMATTR_CACHED (0xF << 2) >> >> +#define TT_S2_AP_READ_WRITE (0x3 << 6) >> >> + >> >> +#define TT_ENTRY_ATTRIBUTES (TT_TYPE_BLOCK_ENTRY | \ >> >> + TT_SH_INNER_SHAREABLE | \ >> >> + TT_S2_AP_READ_WRITE | \ >> >> + TT_S2_MEMATTR_CACHED | \ >> >> + TT_AF) >> >> + >> >> +#define TCR_T0SZ(bits) ((UINT32)(32 - (bits)) & 0x3f) >> >> +#define TCR_SL0_LEVEL1 BIT6 >> >> +#define TCR_SL0_LEVEL2 0 >> >> + >> >> +#define SCTLR_M_ENABLE BIT0 >> >> +#define SCTLR_TR_ENABLE BIT1 >> >> +#define SCTLR_AF_ENABLE BIT2 >> >> +#define SCTLR_CTX_FAULT_ENABLE BIT5 >> >> +#define SCTLR_CTX_INT_ENABLE BIT6 >> >> + >> >> +#define DRAM_BASE FixedPcdGet64 (PcdSystemMemoryBase) >> >> + >> >> +extern EDKII_IOMMU_PROTOCOL mGenericSmmuIommuProtocol; >> >> + >> >> +// >> >> +// Create a static stage 2 mapping of the first 4 GB of DRAM in the start >> >> +// of the IOVA space, and as an ID mapping at the original offset. >> >> +// >> >> +STATIC CONST UINT64 mPciTranslation[1024] __attribute__((aligned(SIZE_8KB))) = { >> >> + [0] = TT_ENTRY_ATTRIBUTES | (DRAM_BASE), >> >> + [1] = TT_ENTRY_ATTRIBUTES | (DRAM_BASE + SIZE_1GB), >> >> + [2] = TT_ENTRY_ATTRIBUTES | (DRAM_BASE + SIZE_1GB * 2UL), >> >> + [3] = TT_ENTRY_ATTRIBUTES | (DRAM_BASE + SIZE_1GB * 3UL), >> >> + >> >> + // >> >> + // The ID mapping of the first 4 GB of DRAM is a workaround for buggy >> >> + // drivers that violate the UEFI spec by ignoring the device address >> >> + // returned by the PCI I/O map/unmap routines, and program host >> >> + // addresses into the DMA h/w registers or rings instead. >> >> + // >> >> + [(DRAM_BASE >> 30)] = TT_ENTRY_ATTRIBUTES | (DRAM_BASE), >> >> + [(DRAM_BASE >> 30) + 1] = TT_ENTRY_ATTRIBUTES | (DRAM_BASE + SIZE_1GB), >> >> + [(DRAM_BASE >> 30) + 2] = TT_ENTRY_ATTRIBUTES | (DRAM_BASE + SIZE_1GB * 2UL), >> >> + [(DRAM_BASE >> 30) + 3] = TT_ENTRY_ATTRIBUTES | (DRAM_BASE + SIZE_1GB * 3UL), >> >> +}; >> >> + >> >> +STATIC EFI_HARDWARE_INTERRUPT_PROTOCOL *mInterrupt; >> >> +STATIC EFI_EVENT mEfiExitBootServicesEvent; >> >> +STATIC UINTN mContextBankOffset; >> >> + >> >> +STATIC >> >> +UINT32 >> >> +ReadGlobalReg32 ( >> >> + IN UINT64 Offset >> >> + ) >> >> +{ >> >> + return MmioRead32 (FixedPcdGet64 (PcdPciGenericSmmuBase) + Offset); >> >> +} >> >> + >> >> +STATIC >> >> +VOID >> >> +WriteGlobalReg32 ( >> >> + IN UINT64 Offset, >> >> + IN UINT64 Value >> >> + ) >> >> +{ >> >> + MmioWrite32 (FixedPcdGet64 (PcdPciGenericSmmuBase) + Offset, Value); >> >> +} >> >> + >> >> +STATIC >> >> +UINT32 >> >> +ReadCbReg32 ( >> >> + IN UINTN Bank, >> >> + IN UINT64 Offset >> >> + ) >> >> +{ >> >> + return MmioRead32 (FixedPcdGet64 (PcdPciGenericSmmuBase) + CB_BASE(Bank) + >> >> + Offset); >> >> +} >> >> + >> >> +STATIC >> >> +VOID >> >> +WriteCbReg32 ( >> >> + IN UINTN Bank, >> >> + IN UINT64 Offset, >> >> + IN UINT32 Value >> >> + ) >> >> +{ >> >> + MmioWrite32 (FixedPcdGet64 (PcdPciGenericSmmuBase) + CB_BASE(Bank) + Offset, >> >> + Value); >> >> +} >> >> + >> >> +STATIC >> >> +UINT64 >> >> +ReadCbReg64 ( >> >> + IN UINTN Bank, >> >> + IN UINT64 Offset >> >> + ) >> >> +{ >> >> + return MmioRead64 (FixedPcdGet64 (PcdPciGenericSmmuBase) + CB_BASE(Bank) + >> >> + Offset); >> >> +} >> >> + >> >> +STATIC >> >> +VOID >> >> +WriteCbReg64 ( >> >> + IN UINTN Bank, >> >> + IN UINT64 Offset, >> >> + IN UINT64 Value >> >> + ) >> >> +{ >> >> + MmioWrite64 (FixedPcdGet64 (PcdPciGenericSmmuBase) + CB_BASE(Bank) + Offset, >> >> + Value); >> >> +} >> >> + >> >> +STATIC >> >> +VOID >> >> +EFIAPI >> >> +ContextInterruptHandler ( >> >> + IN HARDWARE_INTERRUPT_SOURCE Source, >> >> + IN EFI_SYSTEM_CONTEXT SystemContext >> >> + ) >> >> +{ >> >> + // >> >> + // Dump the SMMU context fault registers when taking a context interrupt >> >> + // >> >> + DEBUG ((DEBUG_WARN, >> >> + "Context interrupt asserted by SMMU:\n\n" >> >> + "SMMU_CB0_FAR 0x%016llx \n" >> >> + "SMMU_CB0_FSR 0x%08llx \n" >> >> + "SMMU_CB0_FSYNR0 0x%08llx \n" >> >> + "SMMU_CB0_FSYNR1 0x%08llx \n", >> >> + ReadCbReg64 (0, CB_FAR), >> >> + ReadCbReg32 (0, CB_FSR), >> >> + ReadCbReg32 (0, CB_FSYNR0), >> >> + ReadCbReg32 (0, CB_FSYNR1))); >> >> + >> >> + mInterrupt->EndOfInterrupt (mInterrupt, Source); >> >> +} >> >> + >> >> +STATIC >> >> +VOID >> >> +EFIAPI >> >> +ExitBootServicesEvent ( >> >> + IN EFI_EVENT Event, >> >> + IN VOID *Context >> >> + ) >> >> +{ >> >> + // >> >> + // Put the SMMU back into bypass mode >> >> + // >> >> + MmioOr32 (FixedPcdGet64 (PcdPciGenericSmmuBase) + GL_CR0, GL_CR0_CLIENTPD); >> >> +} >> >> + >> >> +EFI_STATUS >> >> +GenericSmmuStaticPciDmaDxeInitialize ( >> >> + IN EFI_HANDLE ImageHandle, >> >> + IN EFI_SYSTEM_TABLE *SystemTable >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + UINTN Idx; >> >> + UINT32 IdVal; >> >> + UINTN NumStreamMappingRegisters; >> >> + >> >> + // >> >> + // The static mapping uses 1 GB block mappings, whose VAs and PAs should >> >> + // be equal modulo the block size. >> >> + // >> >> + ASSERT ((DRAM_BASE % SIZE_1GB) == 0); >> >> + >> >> + if ((DRAM_BASE & (DRAM_BASE - 1)) != 0) { >> >> + // >> >> + // Buggy drivers that use truncated host addresses instead of device >> >> + // addresses for DMA may still work correctly if such truncation is >> >> + // guaranteed to produce the remapped alias. This is the case if >> >> + // DRAM_BASE is a power of 2. >> >> + // >> >> + DEBUG ((DEBUG_WARN, >> >> + "%a: this driver will work better if DRAM_BASE is a power of 2!\n", >> >> + __FUNCTION__)); >> >> + } >> >> + >> >> + Status = gBS->LocateProtocol (&gHardwareInterruptProtocolGuid, NULL, >> >> + (VOID **)&mInterrupt); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + Status = mInterrupt->RegisterInterruptSource (mInterrupt, >> >> + PcdGet16 (PcdPciGenericSmmuContextInterrupt), >> >> + ContextInterruptHandler); >> >> + ASSERT_EFI_ERROR (Status); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + Status = gBS->CreateEvent (EVT_SIGNAL_EXIT_BOOT_SERVICES, >> >> + TPL_NOTIFY, ExitBootServicesEvent, NULL, >> >> + &mEfiExitBootServicesEvent); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + Status = gBS->InstallMultipleProtocolInterfaces ( >> >> + &ImageHandle, >> >> + &gEdkiiIoMmuProtocolGuid, &mGenericSmmuIommuProtocol, >> >> + NULL >> >> + ); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + IdVal = ReadGlobalReg32 (GL_IDR1); >> >> + mContextBankOffset = (IdVal & GL_IDR1_PAGE_SIZE_64KB) ? SIZE_64KB : SIZE_4KB; >> >> + mContextBankOffset <<= (1 + ((IdVal >> GL_IDR1_NUMPAGENDXB_SHIFT) & >> >> + GL_IDR1_NUMPAGENDXB_MASK)); >> >> + >> >> + // >> >> + // Clear all stream mappings >> >> + // >> >> + NumStreamMappingRegisters = ReadGlobalReg32 (GL_IDR0) & GL_IDR0_NUMSMRG_MASK; >> >> + for (Idx = 0; Idx < NumStreamMappingRegisters; Idx++) { >> >> + WriteGlobalReg32 (GL_SMR0 + Idx * sizeof(UINT32), 0x0); >> >> + WriteGlobalReg32 (GL_S2CR0 + Idx * sizeof(UINT32), 0x0); >> >> + } >> >> + >> >> + // >> >> + // Set stream match register 0 to match all streams, and map onto >> >> + // context bank 0 >> >> + // >> >> + WriteGlobalReg32 (GL_SMR0, 0xffff0000); >> >> + WriteGlobalReg32 (GL_S2CR0, 0x0); >> >> + >> >> + // >> >> + // Disable the context bank >> >> + // >> >> + WriteCbReg32 (0, CB_SCTLR_OFFSET, 0); >> >> + >> >> + // >> >> + // Assign the translation base register for context bank 0 >> >> + // >> >> + WriteCbReg64 (0, CB_TTBR0_OFFSET, (UINTN)mPciTranslation); >> >> + >> >> + // >> >> + // Flush TLBS. >> >> + // >> >> + WriteGlobalReg32 (GL_STLBIALL, 0); >> >> + WriteGlobalReg32 (GL_TLBIALLNSNH, 0); >> >> + >> >> + // >> >> + // Configure the size of the translation space, the number of levels, >> >> + // and the cacheability attributes of the PTW memory accesses. >> >> + // >> >> + WriteCbReg32 (0, CB_TTBCR_OFFSET, TCR_T0SZ(40) | >> >> + TCR_SH_INNER_SHAREABLE | >> >> + TCR_RGN_INNER_WRITE_BACK_NO_ALLOC | >> >> + TCR_RGN_OUTER_WRITE_BACK_NO_ALLOC | >> >> + TCR_SL0_LEVEL1); >> >> + >> >> + // >> >> + // Enable the context bank >> >> + // >> >> + WriteCbReg32 (0, CB_SCTLR_OFFSET, SCTLR_TR_ENABLE | >> >> + SCTLR_AF_ENABLE | >> >> + SCTLR_CTX_INT_ENABLE | >> >> + SCTLR_CTX_FAULT_ENABLE | >> >> + SCTLR_M_ENABLE); >> >> + >> >> + // >> >> + // Get the SMMU out of bypass mode >> >> + // >> >> + MmioAnd32 (FixedPcdGet64 (PcdPciGenericSmmuBase) + GL_CR0, ~GL_CR0_CLIENTPD); >> >> + >> >> + return EFI_SUCCESS; >> >> +} >> >> diff --git a/ArmPkg/Drivers/GenericSmmuStaticPciDmaDxe/GenericSmmuStaticPciDmaDxe.inf b/ArmPkg/Drivers/GenericSmmuStaticPciDmaDxe/GenericSmmuStaticPciDmaDxe.inf >> >> new file mode 100644 >> >> index 000000000000..02c17e755c4a >> >> --- /dev/null >> >> +++ b/ArmPkg/Drivers/GenericSmmuStaticPciDmaDxe/GenericSmmuStaticPciDmaDxe.inf >> >> @@ -0,0 +1,62 @@ >> >> +## @file >> >> +# >> >> +# Copyright (c) 2017, Linaro Ltd. All rights reserved.
>> >> +# >> >> +# This program and the accompanying materials >> >> +# are licensed and made available under the terms and conditions of the BSD License >> >> +# which accompanies this distribution. The full text of the license may be found at >> >> +# http://opensource.org/licenses/bsd-license.php >> >> +# >> >> +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, >> >> +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. >> >> +# >> >> +## >> >> + >> >> +[Defines] >> >> + INF_VERSION = 0x00010019 >> >> + BASE_NAME = GenericSmmuStaticPciDmaDxe >> >> + FILE_GUID = 59b5e69f-88b7-4632-a2ab-6abe6bdedda2 >> >> + MODULE_TYPE = DXE_DRIVER >> >> + VERSION_STRING = 1.0 >> >> + ENTRY_POINT = GenericSmmuStaticPciDmaDxeInitialize >> >> + >> >> +# >> >> +# The following information is for reference only and not required by the build tools. >> >> +# >> >> +# VALID_ARCHITECTURES = ARM AARCH64 >> >> +# >> >> +# >> >> + >> >> +[Sources] >> >> + GenericSmmuStaticPciDmaDxe.c >> >> + BmDma.c >> >> + >> >> +[Packages] >> >> + ArmPkg/ArmPkg.dec >> >> + EmbeddedPkg/EmbeddedPkg.dec >> >> + MdeModulePkg/MdeModulePkg.dec >> >> + MdePkg/MdePkg.dec >> >> + >> >> +[LibraryClasses] >> >> + DebugLib >> >> + BaseLib >> >> + BaseMemoryLib >> >> + IoLib >> >> + MemoryAllocationLib >> >> + UefiBootServicesTableLib >> >> + UefiDriverEntryPoint >> >> + >> >> +[Protocols] >> >> + gEdkiiIoMmuProtocolGuid ## PRODUCES >> >> + gEfiPciIoProtocolGuid ## CONSUMES >> >> + gHardwareInterruptProtocolGuid ## CONSUMES >> >> + >> >> +[Pcd] >> >> + gArmTokenSpaceGuid.PcdPciGenericSmmuBase >> >> + gArmTokenSpaceGuid.PcdPciGenericSmmuContextInterrupt >> >> + >> >> +[FixedPcd] >> >> + gArmTokenSpaceGuid.PcdSystemMemoryBase >> >> + >> >> +[Depex] >> >> + gHardwareInterruptProtocolGuid >> >> -- >> >> 2.9.3 >> >>