From nobody Mon Apr 29 13:23:12 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) smtp.mailfrom=edk2-devel-bounces@lists.01.org Return-Path: Received: from ml01.01.org (ml01.01.org [198.145.21.10]) by mx.zohomail.com with SMTPS id 1509423517806354.2687926766157; Mon, 30 Oct 2017 21:18:37 -0700 (PDT) Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id 1AF6B2034AB2D; Mon, 30 Oct 2017 21:14:45 -0700 (PDT) Received: from mga04.intel.com (mga04.intel.com [192.55.52.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 268822034AB1B for ; Mon, 30 Oct 2017 21:14:43 -0700 (PDT) Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by fmsmga104.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 30 Oct 2017 21:18:34 -0700 Received: from shwdeopenpsi014.ccr.corp.intel.com ([10.239.9.13]) by fmsmga002.fm.intel.com with ESMTP; 30 Oct 2017 21:18:32 -0700 X-Original-To: edk2-devel@lists.01.org Received-SPF: none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) client-ip=198.145.21.10; envelope-from=edk2-devel-bounces@lists.01.org; helo=ml01.01.org; Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=192.55.52.120; helo=mga04.intel.com; envelope-from=hao.a.wu@intel.com; receiver=edk2-devel@lists.01.org X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.44,322,1505804400"; d="scan'208";a="1237536560" From: Hao Wu To: edk2-devel@lists.01.org Date: Tue, 31 Oct 2017 12:16:40 +0800 Message-Id: <20171031041641.20216-2-hao.a.wu@intel.com> X-Mailer: git-send-email 2.12.0.windows.1 In-Reply-To: <20171031041641.20216-1-hao.a.wu@intel.com> References: <20171031041641.20216-1-hao.a.wu@intel.com> Subject: [edk2] [PATCH 1/2] MdeModulePkg/EmmcBlockIoPei: Support IoMmu 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: , Cc: Hao Wu , Jiewen Yao , Star Zeng MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Errors-To: edk2-devel-bounces@lists.01.org Sender: "edk2-devel" X-ZohoMail: RSF_4 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" Update the EmmcBlockIoPei driver to consume IOMMU_PPI to allocate DMA buffer. If no IOMMU_PPI exists, this driver still calls PEI service to allocate DMA buffer, with assumption that DRAM=3D=3DDMA. This is a compatible change. Cc: Star Zeng Cc: Jiewen Yao Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Hao Wu --- MdeModulePkg/Bus/Sd/EmmcBlockIoPei/DmaMem.c | 249 ++++++++++++++= ++++++ MdeModulePkg/Bus/Sd/EmmcBlockIoPei/EmmcBlockIoPei.c | 44 +++- MdeModulePkg/Bus/Sd/EmmcBlockIoPei/EmmcBlockIoPei.h | 141 ++++++++++- MdeModulePkg/Bus/Sd/EmmcBlockIoPei/EmmcBlockIoPei.inf | 5 +- MdeModulePkg/Bus/Sd/EmmcBlockIoPei/EmmcHcMem.c | 23 +- MdeModulePkg/Bus/Sd/EmmcBlockIoPei/EmmcHcMem.h | 4 +- MdeModulePkg/Bus/Sd/EmmcBlockIoPei/EmmcHci.c | 36 ++- 7 files changed, 483 insertions(+), 19 deletions(-) diff --git a/MdeModulePkg/Bus/Sd/EmmcBlockIoPei/DmaMem.c b/MdeModulePkg/Bus= /Sd/EmmcBlockIoPei/DmaMem.c new file mode 100644 index 0000000000..29fb37c225 --- /dev/null +++ b/MdeModulePkg/Bus/Sd/EmmcBlockIoPei/DmaMem.c @@ -0,0 +1,249 @@ +/** @file + The DMA memory help function. + + Copyright (c) 2017, Intel Corporation. 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 IMP= LIED. + +**/ + +#include "EmmcBlockIoPei.h" + +EDKII_IOMMU_PPI *mIoMmu; + +/** + Provides the controller-specific addresses required to access system mem= ory from a + DMA bus master. + + @param Operation Indicates if the bus master is going to re= ad or write to system memory. + @param HostAddress The system memory address to map to the PC= I controller. + @param NumberOfBytes On input the number of bytes to map. On ou= tput the number of bytes + that were mapped. + @param DeviceAddress The resulting map address for the bus mast= er 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 Numb= erOfBytes. + @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a comm= on 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 requ= ested address. + +**/ +EFI_STATUS +IoMmuMap ( + IN EDKII_IOMMU_OPERATION Operation, + IN VOID *HostAddress, + IN OUT UINTN *NumberOfBytes, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ) +{ + EFI_STATUS Status; + UINT64 Attribute; + + if (mIoMmu !=3D NULL) { + Status =3D mIoMmu->Map ( + mIoMmu, + Operation, + HostAddress, + NumberOfBytes, + DeviceAddress, + Mapping + ); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + switch (Operation) { + case EdkiiIoMmuOperationBusMasterRead: + case EdkiiIoMmuOperationBusMasterRead64: + Attribute =3D EDKII_IOMMU_ACCESS_READ; + break; + case EdkiiIoMmuOperationBusMasterWrite: + case EdkiiIoMmuOperationBusMasterWrite64: + Attribute =3D EDKII_IOMMU_ACCESS_WRITE; + break; + case EdkiiIoMmuOperationBusMasterCommonBuffer: + case EdkiiIoMmuOperationBusMasterCommonBuffer64: + Attribute =3D EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE; + break; + default: + ASSERT(FALSE); + return EFI_INVALID_PARAMETER; + } + Status =3D mIoMmu->SetAttribute ( + mIoMmu, + *Mapping, + Attribute + ); + if (EFI_ERROR (Status)) { + return Status; + } + } else { + *DeviceAddress =3D (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress; + *Mapping =3D NULL; + Status =3D EFI_SUCCESS; + } + return Status; +} + +/** + Completes the Map() operation and releases any corresponding resources. + + @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 b= y Map(). + @retval EFI_DEVICE_ERROR The data was not committed to the target s= ystem memory. +**/ +EFI_STATUS +IoMmuUnmap ( + IN VOID *Mapping + ) +{ + EFI_STATUS Status; + + if (mIoMmu !=3D NULL) { + Status =3D mIoMmu->SetAttribute (mIoMmu, Mapping, 0); + Status =3D mIoMmu->Unmap (mIoMmu, Mapping); + } else { + Status =3D EFI_SUCCESS; + } + return Status; +} + +/** + Allocates pages that are suitable for an OperationBusMasterCommonBuffer = or + OperationBusMasterCommonBuffer64 mapping. + + @param Pages The number of pages to allocate. + @param HostAddress A pointer to store the base system memory = address of the + allocated range. + @param DeviceAddress The resulting map address for the bus mast= er PCI controller to use to + access the hosts HostAddress. + @param Mapping A resulting value to pass to Unmap(). + + @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. + +**/ +EFI_STATUS +IoMmuAllocateBuffer ( + IN UINTN Pages, + OUT VOID **HostAddress, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ) +{ + EFI_STATUS Status; + UINTN NumberOfBytes; + EFI_PHYSICAL_ADDRESS HostPhyAddress; + + *HostAddress =3D NULL; + *DeviceAddress =3D 0; + + if (mIoMmu !=3D NULL) { + Status =3D mIoMmu->AllocateBuffer ( + mIoMmu, + EfiBootServicesData, + Pages, + HostAddress, + 0 + ); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + + NumberOfBytes =3D EFI_PAGES_TO_SIZE(Pages); + Status =3D mIoMmu->Map ( + mIoMmu, + EdkiiIoMmuOperationBusMasterCommonBuffer, + *HostAddress, + &NumberOfBytes, + DeviceAddress, + Mapping + ); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + Status =3D mIoMmu->SetAttribute ( + mIoMmu, + *Mapping, + EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE + ); + if (EFI_ERROR (Status)) { + return Status; + } + } else { + Status =3D PeiServicesAllocatePages ( + EfiBootServicesData, + Pages, + &HostPhyAddress + ); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + *HostAddress =3D (VOID *)(UINTN)HostPhyAddress; + *DeviceAddress =3D HostPhyAddress; + *Mapping =3D NULL; + } + return Status; +} + +/** + Frees memory that was allocated with AllocateBuffer(). + + @param Pages The number of pages to free. + @param HostAddress The base system memory address of the allo= cated range. + @param Mapping The mapping value returned from Map(). + + @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(). + +**/ +EFI_STATUS +IoMmuFreeBuffer ( + IN UINTN Pages, + IN VOID *HostAddress, + IN VOID *Mapping + ) +{ + EFI_STATUS Status; + + if (mIoMmu !=3D NULL) { + Status =3D mIoMmu->SetAttribute (mIoMmu, Mapping, 0); + Status =3D mIoMmu->Unmap (mIoMmu, Mapping); + Status =3D mIoMmu->FreeBuffer (mIoMmu, Pages, HostAddress); + } else { + Status =3D EFI_SUCCESS; + } + return Status; +} + +/** + Initialize IOMMU. +**/ +VOID +IoMmuInit ( + VOID + ) +{ + PeiServicesLocatePpi ( + &gEdkiiIoMmuPpiGuid, + 0, + NULL, + (VOID **)&mIoMmu + ); +} + diff --git a/MdeModulePkg/Bus/Sd/EmmcBlockIoPei/EmmcBlockIoPei.c b/MdeModul= ePkg/Bus/Sd/EmmcBlockIoPei/EmmcBlockIoPei.c index 004670cb28..0d1760cb76 100644 --- a/MdeModulePkg/Bus/Sd/EmmcBlockIoPei/EmmcBlockIoPei.c +++ b/MdeModulePkg/Bus/Sd/EmmcBlockIoPei/EmmcBlockIoPei.c @@ -1,6 +1,6 @@ /** @file =20 - Copyright (c) 2015, Intel Corporation. All rights reserved.
+ Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BS= D License which accompanies this distribution. The full text of the license may b= e found at @@ -136,6 +136,11 @@ EMMC_PEIM_HC_PRIVATE_DATA gEmmcHcPrivateTemplate =3D { &gEfiPeiVirtualBlockIo2PpiGuid, NULL }, + { // EndOfPeiNotifyList + (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMI= NATE_LIST), + &gEfiEndOfPeiSignalPpiGuid, + EmmcBlockIoPeimEndOfPei + }, { // Slot { 0, @@ -619,6 +624,36 @@ EmmcBlockIoPeimReadBlocks2 ( } =20 /** + One notified function to cleanup the allocated DMA buffers at the end of= PEI. + + @param[in] PeiServices Pointer to PEI Services Table. + @param[in] NotifyDescriptor Pointer to the descriptor for the Notific= ation + event that caused this function to execut= e. + @param[in] Ppi Pointer to the PPI data associated with t= his function. + + @retval EFI_SUCCESS The function completes successfully + +**/ +EFI_STATUS +EFIAPI +EmmcBlockIoPeimEndOfPei ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ) +{ + EMMC_PEIM_HC_PRIVATE_DATA *Private; + + Private =3D GET_EMMC_PEIM_HC_PRIVATE_DATA_FROM_THIS_NOTIFY (NotifyDescri= ptor); + + if ((Private->Pool !=3D NULL) && (Private->Pool->Head !=3D NULL)) { + EmmcPeimFreeMemPool (Private->Pool); + } + + return EFI_SUCCESS; +} + +/** The user code starts with this function. =20 @param FileHandle Handle of the file being invoked. @@ -659,6 +694,8 @@ InitializeEmmcBlockIoPeim ( return EFI_SUCCESS; } =20 + IoMmuInit (); + // // locate Emmc host controller PPI // @@ -800,6 +837,11 @@ InitializeEmmcBlockIoPeim ( =20 if (!EFI_ERROR (Status)) { PeiServicesInstallPpi (&Private->BlkIoPpiList); + PeiServicesNotifyPpi (&Private->EndOfPeiNotifyList); + } else { + if (Private->Pool->Head !=3D NULL) { + EmmcPeimFreeMemPool (Private->Pool); + } } } =20 diff --git a/MdeModulePkg/Bus/Sd/EmmcBlockIoPei/EmmcBlockIoPei.h b/MdeModul= ePkg/Bus/Sd/EmmcBlockIoPei/EmmcBlockIoPei.h index 5c8b740e4f..b89db8a03f 100644 --- a/MdeModulePkg/Bus/Sd/EmmcBlockIoPei/EmmcBlockIoPei.h +++ b/MdeModulePkg/Bus/Sd/EmmcBlockIoPei/EmmcBlockIoPei.h @@ -1,6 +1,6 @@ /** @file =20 - Copyright (c) 2015, Intel Corporation. All rights reserved.
+ Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BS= D License which accompanies this distribution. The full text of the license may b= e found at @@ -19,6 +19,8 @@ #include #include #include +#include +#include =20 #include #include @@ -64,6 +66,12 @@ struct _EMMC_PEIM_HC_PRIVATE_DATA { EFI_PEI_RECOVERY_BLOCK_IO2_PPI BlkIo2Ppi; EFI_PEI_PPI_DESCRIPTOR BlkIoPpiList; EFI_PEI_PPI_DESCRIPTOR BlkIo2PpiList; + + // + // EndOfPei callback is used to do the cleanups before exit of PEI phase. + // + EFI_PEI_NOTIFY_DESCRIPTOR EndOfPeiNotifyList; + EMMC_PEIM_HC_SLOT Slot[EMMC_PEIM_MAX_SLOTS]; UINT8 SlotNum; UINT8 TotalBlkIoDevices; @@ -72,6 +80,7 @@ struct _EMMC_PEIM_HC_PRIVATE_DATA { #define EMMC_TIMEOUT MultU64x32((UINT64)(3), 1000000) #define GET_EMMC_PEIM_HC_PRIVATE_DATA_FROM_THIS(a) CR (a, EMMC_PEIM_HC_PRI= VATE_DATA, BlkIoPpi, EMMC_PEIM_SIG) #define GET_EMMC_PEIM_HC_PRIVATE_DATA_FROM_THIS2(a) CR (a, EMMC_PEIM_HC_PR= IVATE_DATA, BlkIo2Ppi, EMMC_PEIM_SIG) +#define GET_EMMC_PEIM_HC_PRIVATE_DATA_FROM_THIS_NOTIFY(a) CR (a, EMMC_PEIM= _HC_PRIVATE_DATA, EndOfPeiNotifyList, EMMC_PEIM_SIG) =20 struct _EMMC_TRB { EMMC_PEIM_HC_SLOT *Slot; @@ -81,6 +90,8 @@ struct _EMMC_TRB { VOID *Data; UINT32 DataLen; BOOLEAN Read; + EFI_PHYSICAL_ADDRESS DataPhy; + VOID *DataMap; EMMC_HC_TRANSFER_MODE Mode; =20 UINT64 Timeout; @@ -348,6 +359,20 @@ EmmcPeimInitMemPool ( ); =20 /** + Release the memory management pool. + + @param Pool The memory pool to free. + + @retval EFI_DEVICE_ERROR Fail to free the memory pool. + @retval EFI_SUCCESS The memory pool is freed. + +**/ +EFI_STATUS +EmmcPeimFreeMemPool ( + IN EMMC_PEIM_MEM_POOL *Pool + ); + +/** Allocate some memory from the host controller's memory pool which can be used to communicate with host controller. =20 @@ -378,4 +403,118 @@ EmmcPeimFreeMem ( IN UINTN Size ); =20 +/** + Initialize IOMMU. +**/ +VOID +IoMmuInit ( + VOID + ); + +/** + Provides the controller-specific addresses required to access system mem= ory from a + DMA bus master. + + @param Operation Indicates if the bus master is going to re= ad or write to system memory. + @param HostAddress The system memory address to map to the PC= I controller. + @param NumberOfBytes On input the number of bytes to map. On ou= tput the number of bytes + that were mapped. + @param DeviceAddress The resulting map address for the bus mast= er 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 Numb= erOfBytes. + @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a comm= on 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 requ= ested address. + +**/ +EFI_STATUS +IoMmuMap ( + IN EDKII_IOMMU_OPERATION Operation, + IN VOID *HostAddress, + IN OUT UINTN *NumberOfBytes, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ); + +/** + Completes the Map() operation and releases any corresponding resources. + + @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 b= y Map(). + @retval EFI_DEVICE_ERROR The data was not committed to the target s= ystem memory. +**/ +EFI_STATUS +IoMmuUnmap ( + IN VOID *Mapping + ); + +/** + Allocates pages that are suitable for an OperationBusMasterCommonBuffer = or + OperationBusMasterCommonBuffer64 mapping. + + @param Pages The number of pages to allocate. + @param HostAddress A pointer to store the base system memory = address of the + allocated range. + @param DeviceAddress The resulting map address for the bus mast= er PCI controller to use to + access the hosts HostAddress. + @param Mapping A resulting value to pass to Unmap(). + + @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. + +**/ +EFI_STATUS +IoMmuAllocateBuffer ( + IN UINTN Pages, + OUT VOID **HostAddress, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ); + +/** + Frees memory that was allocated with AllocateBuffer(). + + @param Pages The number of pages to free. + @param HostAddress The base system memory address of the allo= cated range. + @param Mapping The mapping value returned from Map(). + + @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(). + +**/ +EFI_STATUS +IoMmuFreeBuffer ( + IN UINTN Pages, + IN VOID *HostAddress, + IN VOID *Mapping + ); + +/** + One notified function to cleanup the allocated DMA buffers at the end of= PEI. + + @param[in] PeiServices Pointer to PEI Services Table. + @param[in] NotifyDescriptor Pointer to the descriptor for the Notific= ation + event that caused this function to execut= e. + @param[in] Ppi Pointer to the PPI data associated with t= his function. + + @retval EFI_SUCCESS The function completes successfully + +**/ +EFI_STATUS +EFIAPI +EmmcBlockIoPeimEndOfPei ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ); + #endif diff --git a/MdeModulePkg/Bus/Sd/EmmcBlockIoPei/EmmcBlockIoPei.inf b/MdeMod= ulePkg/Bus/Sd/EmmcBlockIoPei/EmmcBlockIoPei.inf index 4163b528b8..b4127b791d 100644 --- a/MdeModulePkg/Bus/Sd/EmmcBlockIoPei/EmmcBlockIoPei.inf +++ b/MdeModulePkg/Bus/Sd/EmmcBlockIoPei/EmmcBlockIoPei.inf @@ -1,7 +1,7 @@ ## @file # Description file for the Embedded MMC (eMMC) Peim driver. # -# Copyright (c) 2015, Intel Corporation. All rights reserved.
+# Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.
# # This program and the accompanying materials # are licensed and made available under the terms and conditions of the B= SD License @@ -36,6 +36,7 @@ EmmcHci.h EmmcHcMem.c EmmcHcMem.h + DmaMem.c =20 [Packages] MdePkg/MdePkg.dec @@ -53,6 +54,8 @@ gEfiPeiVirtualBlockIoPpiGuid ## PRODUCES gEfiPeiVirtualBlockIo2PpiGuid ## PRODUCES gEdkiiPeiSdMmcHostControllerPpiGuid ## CONSUMES + gEdkiiIoMmuPpiGuid ## CONSUMES + gEfiEndOfPeiSignalPpiGuid ## CONSUMES =20 [Depex] gEfiPeiMemoryDiscoveredPpiGuid AND gEdkiiPeiSdMmcHostControllerPpiGuid diff --git a/MdeModulePkg/Bus/Sd/EmmcBlockIoPei/EmmcHcMem.c b/MdeModulePkg/= Bus/Sd/EmmcBlockIoPei/EmmcHcMem.c index 0708fab047..a6f188f385 100644 --- a/MdeModulePkg/Bus/Sd/EmmcBlockIoPei/EmmcHcMem.c +++ b/MdeModulePkg/Bus/Sd/EmmcBlockIoPei/EmmcHcMem.c @@ -1,6 +1,6 @@ /** @file =20 -Copyright (c) 2016, Intel Corporation. All rights reserved.
+Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.
=20 This program and the accompanying materials are licensed and made available under the terms and conditions @@ -29,9 +29,11 @@ EmmcPeimAllocMemBlock ( ) { EMMC_PEIM_MEM_BLOCK *Block; + VOID *BufHost; + VOID *Mapping; + EFI_PHYSICAL_ADDRESS MappedAddr; EFI_STATUS Status; VOID *TempPtr; - EFI_PHYSICAL_ADDRESS Address; =20 TempPtr =3D NULL; Block =3D NULL; @@ -62,19 +64,22 @@ EmmcPeimAllocMemBlock ( =20 Block->Bits =3D (UINT8*)(UINTN)TempPtr; =20 - Status =3D PeiServicesAllocatePages ( - EfiBootServicesCode, + Status =3D IoMmuAllocateBuffer ( Pages, - &Address + &BufHost, + &MappedAddr, + &Mapping ); if (EFI_ERROR (Status)) { return NULL; } =20 - ZeroMem ((VOID*)(UINTN)Address, EFI_PAGES_TO_SIZE (Pages)); + ZeroMem ((VOID*)(UINTN)BufHost, EFI_PAGES_TO_SIZE (Pages)); =20 - Block->Buf =3D (UINT8*)((UINTN)Address); - Block->Next =3D NULL; + Block->BufHost =3D (UINT8 *) (UINTN) BufHost; + Block->Buf =3D (UINT8 *) (UINTN) MappedAddr; + Block->Mapping =3D Mapping; + Block->Next =3D NULL; =20 return Block; } @@ -93,6 +98,8 @@ EmmcPeimFreeMemBlock ( ) { ASSERT ((Pool !=3D NULL) && (Block !=3D NULL)); + + IoMmuFreeBuffer (EFI_SIZE_TO_PAGES (Block->BufLen), Block->BufHost, Bloc= k->Mapping); } =20 /** diff --git a/MdeModulePkg/Bus/Sd/EmmcBlockIoPei/EmmcHcMem.h b/MdeModulePkg/= Bus/Sd/EmmcBlockIoPei/EmmcHcMem.h index af0c93c610..026064479e 100644 --- a/MdeModulePkg/Bus/Sd/EmmcBlockIoPei/EmmcHcMem.h +++ b/MdeModulePkg/Bus/Sd/EmmcBlockIoPei/EmmcHcMem.h @@ -1,6 +1,6 @@ /** @file =20 -Copyright (c) 2015, Intel Corporation. All rights reserved.
+Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.
=20 This program and the accompanying materials are licensed and made available under the terms and conditions @@ -27,7 +27,9 @@ struct _EMMC_PEIM_MEM_BLOCK { UINT8 *Bits; // Bit array to record which unit is a= llocated UINTN BitsLen; UINT8 *Buf; + UINT8 *BufHost; UINTN BufLen; // Memory size in bytes + VOID *Mapping; EMMC_PEIM_MEM_BLOCK *Next; }; =20 diff --git a/MdeModulePkg/Bus/Sd/EmmcBlockIoPei/EmmcHci.c b/MdeModulePkg/Bu= s/Sd/EmmcBlockIoPei/EmmcHci.c index 7c40892da0..97b8dac8f5 100644 --- a/MdeModulePkg/Bus/Sd/EmmcBlockIoPei/EmmcHci.c +++ b/MdeModulePkg/Bus/Sd/EmmcBlockIoPei/EmmcHci.c @@ -929,7 +929,7 @@ BuildAdmaDescTable ( UINT64 Remaining; UINT32 Address; =20 - Data =3D (EFI_PHYSICAL_ADDRESS)(UINTN)Trb->Data; + Data =3D Trb->DataPhy; DataLen =3D Trb->DataLen; // // Only support 32bit ADMA Descriptor Table @@ -998,6 +998,8 @@ EmmcPeimCreateTrb ( EMMC_TRB *Trb; EFI_STATUS Status; EMMC_HC_SLOT_CAP Capability; + EDKII_IOMMU_OPERATION MapOp; + UINTN MapLength; =20 // // Calculate a divisor for SD clock frequency @@ -1007,7 +1009,7 @@ EmmcPeimCreateTrb ( return NULL; } =20 - Trb =3D EmmcPeimAllocateMem (Slot->Private->Pool, sizeof (EMMC_TRB)); + Trb =3D AllocateZeroPool (sizeof (EMMC_TRB)); if (Trb =3D=3D NULL) { return NULL; } @@ -1039,6 +1041,22 @@ EmmcPeimCreateTrb ( if (Packet->EmmcCmdBlk->CommandIndex =3D=3D EMMC_SEND_TUNING_BLOCK) { Trb->Mode =3D EmmcPioMode; } else { + if (Trb->Read) { + MapOp =3D EdkiiIoMmuOperationBusMasterWrite; + } else { + MapOp =3D EdkiiIoMmuOperationBusMasterRead; + } + + if (Trb->DataLen !=3D 0) { + MapLength =3D Trb->DataLen; + Status =3D IoMmuMap (MapOp, Trb->Data, &MapLength, &Trb->DataPhy, &T= rb->DataMap); + + if (EFI_ERROR (Status) || (MapLength !=3D Trb->DataLen)) { + DEBUG ((DEBUG_ERROR, "EmmcPeimCreateTrb: Fail to map data buffer.\= n")); + goto Error; + } + } + if (Trb->DataLen =3D=3D 0) { Trb->Mode =3D EmmcNoData; } else if (Capability.Adma2 !=3D 0) { @@ -1071,12 +1089,16 @@ EmmcPeimFreeTrb ( IN EMMC_TRB *Trb ) { + if ((Trb !=3D NULL) && (Trb->DataMap !=3D NULL)) { + IoMmuUnmap (Trb->DataMap); + } + if ((Trb !=3D NULL) && (Trb->AdmaDesc !=3D NULL)) { EmmcPeimFreeMem (Trb->Slot->Private->Pool, Trb->AdmaDesc, Trb->AdmaDes= cSize); } =20 if (Trb !=3D NULL) { - EmmcPeimFreeMem (Trb->Slot->Private->Pool, Trb, sizeof (EMMC_TRB)); + FreePool (Trb); } return; } @@ -1241,11 +1263,11 @@ EmmcPeimExecTrb ( EmmcPeimHcLedOnOff (Bar, TRUE); =20 if (Trb->Mode =3D=3D EmmcSdmaMode) { - if ((UINT64)(UINTN)Trb->Data >=3D 0x100000000ul) { + if ((UINT64)(UINTN)Trb->DataPhy >=3D 0x100000000ul) { return EFI_INVALID_PARAMETER; } =20 - SdmaAddr =3D (UINT32)(UINTN)Trb->Data; + SdmaAddr =3D (UINT32)(UINTN)Trb->DataPhy; Status =3D EmmcPeimHcRwMmio (Bar + EMMC_HC_SDMA_ADDR, FALSE, sizeof = (SdmaAddr), &SdmaAddr); if (EFI_ERROR (Status)) { return Status; @@ -1480,7 +1502,7 @@ EmmcPeimCheckTrbResult ( // // Update SDMA Address register. // - SdmaAddr =3D EMMC_SDMA_ROUND_UP ((UINT32)(UINTN)Trb->Data, EMMC_SDMA_B= OUNDARY); + SdmaAddr =3D EMMC_SDMA_ROUND_UP ((UINT32)(UINTN)Trb->DataPhy, EMMC_SDM= A_BOUNDARY); Status =3D EmmcPeimHcRwMmio ( Bar + EMMC_HC_SDMA_ADDR, FALSE, @@ -1490,7 +1512,7 @@ EmmcPeimCheckTrbResult ( if (EFI_ERROR (Status)) { goto Done; } - Trb->Data =3D (VOID*)(UINTN)SdmaAddr; + Trb->DataPhy =3D (UINT32)(UINTN)SdmaAddr; } =20 if ((Packet->EmmcCmdBlk->CommandType !=3D EmmcCommandTypeAdtc) && --=20 2.12.0.windows.1 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel From nobody Mon Apr 29 13:23:12 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) smtp.mailfrom=edk2-devel-bounces@lists.01.org Return-Path: Received: from ml01.01.org (ml01.01.org [198.145.21.10]) by mx.zohomail.com with SMTPS id 1509423519231739.5712431768629; Mon, 30 Oct 2017 21:18:39 -0700 (PDT) Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id 5D1F02034AB33; Mon, 30 Oct 2017 21:14:46 -0700 (PDT) Received: from mga04.intel.com (mga04.intel.com [192.55.52.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 3F9612034AB31 for ; Mon, 30 Oct 2017 21:14:45 -0700 (PDT) Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by fmsmga104.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 30 Oct 2017 21:18:36 -0700 Received: from shwdeopenpsi014.ccr.corp.intel.com ([10.239.9.13]) by fmsmga002.fm.intel.com with ESMTP; 30 Oct 2017 21:18:35 -0700 X-Original-To: edk2-devel@lists.01.org Received-SPF: none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) client-ip=198.145.21.10; envelope-from=edk2-devel-bounces@lists.01.org; helo=ml01.01.org; Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=192.55.52.120; helo=mga04.intel.com; envelope-from=hao.a.wu@intel.com; receiver=edk2-devel@lists.01.org X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.44,322,1505804400"; d="scan'208";a="1237536567" From: Hao Wu To: edk2-devel@lists.01.org Date: Tue, 31 Oct 2017 12:16:41 +0800 Message-Id: <20171031041641.20216-3-hao.a.wu@intel.com> X-Mailer: git-send-email 2.12.0.windows.1 In-Reply-To: <20171031041641.20216-1-hao.a.wu@intel.com> References: <20171031041641.20216-1-hao.a.wu@intel.com> Subject: [edk2] [PATCH 2/2] MdeModulePkg/SdBlockIoPei: Support IoMmu 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: , Cc: Hao Wu , Jiewen Yao , Star Zeng MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Errors-To: edk2-devel-bounces@lists.01.org Sender: "edk2-devel" X-ZohoMail: RSF_4 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" Update the SdBlockIoPei driver to consume IOMMU_PPI to allocate DMA buffer. If no IOMMU_PPI exists, this driver still calls PEI service to allocate DMA buffer, with assumption that DRAM=3D=3DDMA. This is a compatible change. Cc: Star Zeng Cc: Jiewen Yao Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Hao Wu --- MdeModulePkg/Bus/Sd/SdBlockIoPei/DmaMem.c | 249 ++++++++++++++++++= ++ MdeModulePkg/Bus/Sd/SdBlockIoPei/SdBlockIoPei.c | 44 +++- MdeModulePkg/Bus/Sd/SdBlockIoPei/SdBlockIoPei.h | 141 ++++++++++- MdeModulePkg/Bus/Sd/SdBlockIoPei/SdBlockIoPei.inf | 5 +- MdeModulePkg/Bus/Sd/SdBlockIoPei/SdHcMem.c | 23 +- MdeModulePkg/Bus/Sd/SdBlockIoPei/SdHcMem.h | 4 +- MdeModulePkg/Bus/Sd/SdBlockIoPei/SdHci.c | 36 ++- 7 files changed, 483 insertions(+), 19 deletions(-) diff --git a/MdeModulePkg/Bus/Sd/SdBlockIoPei/DmaMem.c b/MdeModulePkg/Bus/S= d/SdBlockIoPei/DmaMem.c new file mode 100644 index 0000000000..0dc2711ed1 --- /dev/null +++ b/MdeModulePkg/Bus/Sd/SdBlockIoPei/DmaMem.c @@ -0,0 +1,249 @@ +/** @file + The DMA memory help function. + + Copyright (c) 2017, Intel Corporation. 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 IMP= LIED. + +**/ + +#include "SdBlockIoPei.h" + +EDKII_IOMMU_PPI *mIoMmu; + +/** + Provides the controller-specific addresses required to access system mem= ory from a + DMA bus master. + + @param Operation Indicates if the bus master is going to re= ad or write to system memory. + @param HostAddress The system memory address to map to the PC= I controller. + @param NumberOfBytes On input the number of bytes to map. On ou= tput the number of bytes + that were mapped. + @param DeviceAddress The resulting map address for the bus mast= er 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 Numb= erOfBytes. + @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a comm= on 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 requ= ested address. + +**/ +EFI_STATUS +IoMmuMap ( + IN EDKII_IOMMU_OPERATION Operation, + IN VOID *HostAddress, + IN OUT UINTN *NumberOfBytes, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ) +{ + EFI_STATUS Status; + UINT64 Attribute; + + if (mIoMmu !=3D NULL) { + Status =3D mIoMmu->Map ( + mIoMmu, + Operation, + HostAddress, + NumberOfBytes, + DeviceAddress, + Mapping + ); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + switch (Operation) { + case EdkiiIoMmuOperationBusMasterRead: + case EdkiiIoMmuOperationBusMasterRead64: + Attribute =3D EDKII_IOMMU_ACCESS_READ; + break; + case EdkiiIoMmuOperationBusMasterWrite: + case EdkiiIoMmuOperationBusMasterWrite64: + Attribute =3D EDKII_IOMMU_ACCESS_WRITE; + break; + case EdkiiIoMmuOperationBusMasterCommonBuffer: + case EdkiiIoMmuOperationBusMasterCommonBuffer64: + Attribute =3D EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE; + break; + default: + ASSERT(FALSE); + return EFI_INVALID_PARAMETER; + } + Status =3D mIoMmu->SetAttribute ( + mIoMmu, + *Mapping, + Attribute + ); + if (EFI_ERROR (Status)) { + return Status; + } + } else { + *DeviceAddress =3D (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress; + *Mapping =3D NULL; + Status =3D EFI_SUCCESS; + } + return Status; +} + +/** + Completes the Map() operation and releases any corresponding resources. + + @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 b= y Map(). + @retval EFI_DEVICE_ERROR The data was not committed to the target s= ystem memory. +**/ +EFI_STATUS +IoMmuUnmap ( + IN VOID *Mapping + ) +{ + EFI_STATUS Status; + + if (mIoMmu !=3D NULL) { + Status =3D mIoMmu->SetAttribute (mIoMmu, Mapping, 0); + Status =3D mIoMmu->Unmap (mIoMmu, Mapping); + } else { + Status =3D EFI_SUCCESS; + } + return Status; +} + +/** + Allocates pages that are suitable for an OperationBusMasterCommonBuffer = or + OperationBusMasterCommonBuffer64 mapping. + + @param Pages The number of pages to allocate. + @param HostAddress A pointer to store the base system memory = address of the + allocated range. + @param DeviceAddress The resulting map address for the bus mast= er PCI controller to use to + access the hosts HostAddress. + @param Mapping A resulting value to pass to Unmap(). + + @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. + +**/ +EFI_STATUS +IoMmuAllocateBuffer ( + IN UINTN Pages, + OUT VOID **HostAddress, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ) +{ + EFI_STATUS Status; + UINTN NumberOfBytes; + EFI_PHYSICAL_ADDRESS HostPhyAddress; + + *HostAddress =3D NULL; + *DeviceAddress =3D 0; + + if (mIoMmu !=3D NULL) { + Status =3D mIoMmu->AllocateBuffer ( + mIoMmu, + EfiBootServicesData, + Pages, + HostAddress, + 0 + ); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + + NumberOfBytes =3D EFI_PAGES_TO_SIZE(Pages); + Status =3D mIoMmu->Map ( + mIoMmu, + EdkiiIoMmuOperationBusMasterCommonBuffer, + *HostAddress, + &NumberOfBytes, + DeviceAddress, + Mapping + ); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + Status =3D mIoMmu->SetAttribute ( + mIoMmu, + *Mapping, + EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE + ); + if (EFI_ERROR (Status)) { + return Status; + } + } else { + Status =3D PeiServicesAllocatePages ( + EfiBootServicesData, + Pages, + &HostPhyAddress + ); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + *HostAddress =3D (VOID *)(UINTN)HostPhyAddress; + *DeviceAddress =3D HostPhyAddress; + *Mapping =3D NULL; + } + return Status; +} + +/** + Frees memory that was allocated with AllocateBuffer(). + + @param Pages The number of pages to free. + @param HostAddress The base system memory address of the allo= cated range. + @param Mapping The mapping value returned from Map(). + + @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(). + +**/ +EFI_STATUS +IoMmuFreeBuffer ( + IN UINTN Pages, + IN VOID *HostAddress, + IN VOID *Mapping + ) +{ + EFI_STATUS Status; + + if (mIoMmu !=3D NULL) { + Status =3D mIoMmu->SetAttribute (mIoMmu, Mapping, 0); + Status =3D mIoMmu->Unmap (mIoMmu, Mapping); + Status =3D mIoMmu->FreeBuffer (mIoMmu, Pages, HostAddress); + } else { + Status =3D EFI_SUCCESS; + } + return Status; +} + +/** + Initialize IOMMU. +**/ +VOID +IoMmuInit ( + VOID + ) +{ + PeiServicesLocatePpi ( + &gEdkiiIoMmuPpiGuid, + 0, + NULL, + (VOID **)&mIoMmu + ); +} + diff --git a/MdeModulePkg/Bus/Sd/SdBlockIoPei/SdBlockIoPei.c b/MdeModulePkg= /Bus/Sd/SdBlockIoPei/SdBlockIoPei.c index 6dc343edbd..63222228c3 100644 --- a/MdeModulePkg/Bus/Sd/SdBlockIoPei/SdBlockIoPei.c +++ b/MdeModulePkg/Bus/Sd/SdBlockIoPei/SdBlockIoPei.c @@ -1,6 +1,6 @@ /** @file =20 - Copyright (c) 2015, Intel Corporation. All rights reserved.
+ Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BS= D License which accompanies this distribution. The full text of the license may b= e found at @@ -64,6 +64,11 @@ SD_PEIM_HC_PRIVATE_DATA gSdHcPrivateTemplate =3D { &gEfiPeiVirtualBlockIo2PpiGuid, NULL }, + { + (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMI= NATE_LIST), + &gEfiEndOfPeiSignalPpiGuid, + SdBlockIoPeimEndOfPei + }, { // Slot { 0, @@ -466,6 +471,36 @@ SdBlockIoPeimReadBlocks2 ( } =20 /** + One notified function to cleanup the allocated DMA buffers at the end of= PEI. + + @param[in] PeiServices Pointer to PEI Services Table. + @param[in] NotifyDescriptor Pointer to the descriptor for the Notific= ation + event that caused this function to execut= e. + @param[in] Ppi Pointer to the PPI data associated with t= his function. + + @retval EFI_SUCCESS The function completes successfully + +**/ +EFI_STATUS +EFIAPI +SdBlockIoPeimEndOfPei ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ) +{ + SD_PEIM_HC_PRIVATE_DATA *Private; + + Private =3D GET_SD_PEIM_HC_PRIVATE_DATA_FROM_THIS_NOTIFY (NotifyDescript= or); + + if ((Private->Pool !=3D NULL) && (Private->Pool->Head !=3D NULL)) { + SdPeimFreeMemPool (Private->Pool); + } + + return EFI_SUCCESS; +} + +/** The user code starts with this function. =20 @param FileHandle Handle of the file being invoked. @@ -506,6 +541,8 @@ InitializeSdBlockIoPeim ( return EFI_SUCCESS; } =20 + IoMmuInit (); + // // locate Sd host controller PPI // @@ -610,6 +647,11 @@ InitializeSdBlockIoPeim ( Controller++; if (!EFI_ERROR (Status)) { PeiServicesInstallPpi (&Private->BlkIoPpiList); + PeiServicesNotifyPpi (&Private->EndOfPeiNotifyList); + } else { + if (Private->Pool->Head !=3D NULL) { + SdPeimFreeMemPool (Private->Pool); + } } } =20 diff --git a/MdeModulePkg/Bus/Sd/SdBlockIoPei/SdBlockIoPei.h b/MdeModulePkg= /Bus/Sd/SdBlockIoPei/SdBlockIoPei.h index b2491bb3cb..87b2f00923 100644 --- a/MdeModulePkg/Bus/Sd/SdBlockIoPei/SdBlockIoPei.h +++ b/MdeModulePkg/Bus/Sd/SdBlockIoPei/SdBlockIoPei.h @@ -1,6 +1,6 @@ /** @file =20 - Copyright (c) 2015, Intel Corporation. All rights reserved.
+ Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BS= D License which accompanies this distribution. The full text of the license may b= e found at @@ -19,6 +19,8 @@ #include #include #include +#include +#include =20 #include #include @@ -60,6 +62,12 @@ struct _SD_PEIM_HC_PRIVATE_DATA { EFI_PEI_RECOVERY_BLOCK_IO2_PPI BlkIo2Ppi; EFI_PEI_PPI_DESCRIPTOR BlkIoPpiList; EFI_PEI_PPI_DESCRIPTOR BlkIo2PpiList; + + // + // EndOfPei callback is used to do the cleanups before exit of PEI phase. + // + EFI_PEI_NOTIFY_DESCRIPTOR EndOfPeiNotifyList; + SD_PEIM_HC_SLOT Slot[SD_PEIM_MAX_SLOTS]; UINT8 SlotNum; UINT8 TotalBlkIoDevices; @@ -68,6 +76,7 @@ struct _SD_PEIM_HC_PRIVATE_DATA { #define SD_TIMEOUT MultU64x32((UINT64)(3), 1000000) #define GET_SD_PEIM_HC_PRIVATE_DATA_FROM_THIS(a) CR (a, SD_PEIM_HC_PRIVATE= _DATA, BlkIoPpi, SD_PEIM_SIG) #define GET_SD_PEIM_HC_PRIVATE_DATA_FROM_THIS2(a) CR (a, SD_PEIM_HC_PRIVAT= E_DATA, BlkIo2Ppi, SD_PEIM_SIG) +#define GET_SD_PEIM_HC_PRIVATE_DATA_FROM_THIS_NOTIFY(a) CR (a, SD_PEIM_HC_= PRIVATE_DATA, EndOfPeiNotifyList, SD_PEIM_SIG) =20 struct _SD_TRB { SD_PEIM_HC_SLOT *Slot; @@ -77,6 +86,8 @@ struct _SD_TRB { VOID *Data; UINT32 DataLen; BOOLEAN Read; + EFI_PHYSICAL_ADDRESS DataPhy; + VOID *DataMap; SD_HC_TRANSFER_MODE Mode; =20 UINT64 Timeout; @@ -344,6 +355,20 @@ SdPeimInitMemPool ( ); =20 /** + Release the memory management pool. + + @param Pool The memory pool to free. + + @retval EFI_DEVICE_ERROR Fail to free the memory pool. + @retval EFI_SUCCESS The memory pool is freed. + +**/ +EFI_STATUS +SdPeimFreeMemPool ( + IN SD_PEIM_MEM_POOL *Pool + ); + +/** Allocate some memory from the host controller's memory pool which can be used to communicate with host controller. =20 @@ -374,4 +399,118 @@ SdPeimFreeMem ( IN UINTN Size ); =20 +/** + Initialize IOMMU. +**/ +VOID +IoMmuInit ( + VOID + ); + +/** + Provides the controller-specific addresses required to access system mem= ory from a + DMA bus master. + + @param Operation Indicates if the bus master is going to re= ad or write to system memory. + @param HostAddress The system memory address to map to the PC= I controller. + @param NumberOfBytes On input the number of bytes to map. On ou= tput the number of bytes + that were mapped. + @param DeviceAddress The resulting map address for the bus mast= er 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 Numb= erOfBytes. + @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a comm= on 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 requ= ested address. + +**/ +EFI_STATUS +IoMmuMap ( + IN EDKII_IOMMU_OPERATION Operation, + IN VOID *HostAddress, + IN OUT UINTN *NumberOfBytes, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ); + +/** + Completes the Map() operation and releases any corresponding resources. + + @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 b= y Map(). + @retval EFI_DEVICE_ERROR The data was not committed to the target s= ystem memory. +**/ +EFI_STATUS +IoMmuUnmap ( + IN VOID *Mapping + ); + +/** + Allocates pages that are suitable for an OperationBusMasterCommonBuffer = or + OperationBusMasterCommonBuffer64 mapping. + + @param Pages The number of pages to allocate. + @param HostAddress A pointer to store the base system memory = address of the + allocated range. + @param DeviceAddress The resulting map address for the bus mast= er PCI controller to use to + access the hosts HostAddress. + @param Mapping A resulting value to pass to Unmap(). + + @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. + +**/ +EFI_STATUS +IoMmuAllocateBuffer ( + IN UINTN Pages, + OUT VOID **HostAddress, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ); + +/** + Frees memory that was allocated with AllocateBuffer(). + + @param Pages The number of pages to free. + @param HostAddress The base system memory address of the allo= cated range. + @param Mapping The mapping value returned from Map(). + + @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(). + +**/ +EFI_STATUS +IoMmuFreeBuffer ( + IN UINTN Pages, + IN VOID *HostAddress, + IN VOID *Mapping + ); + +/** + One notified function to cleanup the allocated DMA buffers at the end of= PEI. + + @param[in] PeiServices Pointer to PEI Services Table. + @param[in] NotifyDescriptor Pointer to the descriptor for the Notific= ation + event that caused this function to execut= e. + @param[in] Ppi Pointer to the PPI data associated with t= his function. + + @retval EFI_SUCCESS The function completes successfully + +**/ +EFI_STATUS +EFIAPI +SdBlockIoPeimEndOfPei ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ); + #endif diff --git a/MdeModulePkg/Bus/Sd/SdBlockIoPei/SdBlockIoPei.inf b/MdeModuleP= kg/Bus/Sd/SdBlockIoPei/SdBlockIoPei.inf index ca4c39b65f..1530f1efdb 100644 --- a/MdeModulePkg/Bus/Sd/SdBlockIoPei/SdBlockIoPei.inf +++ b/MdeModulePkg/Bus/Sd/SdBlockIoPei/SdBlockIoPei.inf @@ -1,7 +1,7 @@ ## @file # Description file for the SD memory card Peim driver. # -# Copyright (c) 2015, Intel Corporation. All rights reserved.
+# Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.
# # This program and the accompanying materials # are licensed and made available under the terms and conditions of the B= SD License @@ -36,6 +36,7 @@ SdHci.h SdHcMem.c SdHcMem.h + DmaMem.c =20 [Packages] MdePkg/MdePkg.dec @@ -53,6 +54,8 @@ gEfiPeiVirtualBlockIoPpiGuid ## PRODUCES gEfiPeiVirtualBlockIo2PpiGuid ## PRODUCES gEdkiiPeiSdMmcHostControllerPpiGuid ## CONSUMES + gEdkiiIoMmuPpiGuid ## CONSUMES + gEfiEndOfPeiSignalPpiGuid ## CONSUMES =20 [Depex] gEfiPeiMemoryDiscoveredPpiGuid AND gEdkiiPeiSdMmcHostControllerPpiGuid diff --git a/MdeModulePkg/Bus/Sd/SdBlockIoPei/SdHcMem.c b/MdeModulePkg/Bus/= Sd/SdBlockIoPei/SdHcMem.c index f390a636dc..24ad3dc6c2 100644 --- a/MdeModulePkg/Bus/Sd/SdBlockIoPei/SdHcMem.c +++ b/MdeModulePkg/Bus/Sd/SdBlockIoPei/SdHcMem.c @@ -1,6 +1,6 @@ /** @file =20 -Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.
+Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.
=20 This program and the accompanying materials are licensed and made available under the terms and conditions @@ -29,9 +29,11 @@ SdPeimAllocMemBlock ( ) { SD_PEIM_MEM_BLOCK *Block; + VOID *BufHost; + VOID *Mapping; + EFI_PHYSICAL_ADDRESS MappedAddr; EFI_STATUS Status; VOID *TempPtr; - EFI_PHYSICAL_ADDRESS Address; =20 TempPtr =3D NULL; Block =3D NULL; @@ -62,19 +64,22 @@ SdPeimAllocMemBlock ( =20 Block->Bits =3D (UINT8*)(UINTN)TempPtr; =20 - Status =3D PeiServicesAllocatePages ( - EfiBootServicesCode, + Status =3D IoMmuAllocateBuffer ( Pages, - &Address + &BufHost, + &MappedAddr, + &Mapping ); if (EFI_ERROR (Status)) { return NULL; } =20 - ZeroMem ((VOID*)(UINTN)Address, EFI_PAGES_TO_SIZE (Pages)); + ZeroMem ((VOID*)(UINTN)BufHost, EFI_PAGES_TO_SIZE (Pages)); =20 - Block->Buf =3D (UINT8*)((UINTN)Address); - Block->Next =3D NULL; + Block->BufHost =3D (UINT8 *) (UINTN) BufHost; + Block->Buf =3D (UINT8 *) (UINTN) MappedAddr; + Block->Mapping =3D Mapping; + Block->Next =3D NULL; =20 return Block; } @@ -93,6 +98,8 @@ SdPeimFreeMemBlock ( ) { ASSERT ((Pool !=3D NULL) && (Block !=3D NULL)); + + IoMmuFreeBuffer (EFI_SIZE_TO_PAGES (Block->BufLen), Block->BufHost, Bloc= k->Mapping); } =20 /** diff --git a/MdeModulePkg/Bus/Sd/SdBlockIoPei/SdHcMem.h b/MdeModulePkg/Bus/= Sd/SdBlockIoPei/SdHcMem.h index 096b625f98..e293631680 100644 --- a/MdeModulePkg/Bus/Sd/SdBlockIoPei/SdHcMem.h +++ b/MdeModulePkg/Bus/Sd/SdBlockIoPei/SdHcMem.h @@ -1,6 +1,6 @@ /** @file =20 -Copyright (c) 2015, Intel Corporation. All rights reserved.
+Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.
=20 This program and the accompanying materials are licensed and made available under the terms and conditions @@ -27,7 +27,9 @@ struct _SD_PEIM_MEM_BLOCK { UINT8 *Bits; // Bit array to record which unit is a= llocated UINTN BitsLen; UINT8 *Buf; + UINT8 *BufHost; UINTN BufLen; // Memory size in bytes + VOID *Mapping; SD_PEIM_MEM_BLOCK *Next; }; =20 diff --git a/MdeModulePkg/Bus/Sd/SdBlockIoPei/SdHci.c b/MdeModulePkg/Bus/Sd= /SdBlockIoPei/SdHci.c index eebadd79bc..228c343f9d 100644 --- a/MdeModulePkg/Bus/Sd/SdBlockIoPei/SdHci.c +++ b/MdeModulePkg/Bus/Sd/SdBlockIoPei/SdHci.c @@ -929,7 +929,7 @@ BuildAdmaDescTable ( UINT64 Remaining; UINT32 Address; =20 - Data =3D (EFI_PHYSICAL_ADDRESS)(UINTN)Trb->Data; + Data =3D Trb->DataPhy; DataLen =3D Trb->DataLen; // // Only support 32bit ADMA Descriptor Table @@ -998,6 +998,8 @@ SdPeimCreateTrb ( SD_TRB *Trb; EFI_STATUS Status; SD_HC_SLOT_CAP Capability; + EDKII_IOMMU_OPERATION MapOp; + UINTN MapLength; =20 // // Calculate a divisor for SD clock frequency @@ -1007,7 +1009,7 @@ SdPeimCreateTrb ( return NULL; } =20 - Trb =3D SdPeimAllocateMem (Slot->Private->Pool, sizeof (SD_TRB)); + Trb =3D AllocateZeroPool (sizeof (SD_TRB)); if (Trb =3D=3D NULL) { return NULL; } @@ -1039,6 +1041,22 @@ SdPeimCreateTrb ( if (Packet->SdCmdBlk->CommandIndex =3D=3D SD_SEND_TUNING_BLOCK) { Trb->Mode =3D SdPioMode; } else { + if (Trb->Read) { + MapOp =3D EdkiiIoMmuOperationBusMasterWrite; + } else { + MapOp =3D EdkiiIoMmuOperationBusMasterRead; + } + + if (Trb->DataLen !=3D 0) { + MapLength =3D Trb->DataLen; + Status =3D IoMmuMap (MapOp, Trb->Data, &MapLength, &Trb->DataPhy, &T= rb->DataMap); + + if (EFI_ERROR (Status) || (MapLength !=3D Trb->DataLen)) { + DEBUG ((DEBUG_ERROR, "SdPeimCreateTrb: Fail to map data buffer.\n"= )); + goto Error; + } + } + if (Trb->DataLen =3D=3D 0) { Trb->Mode =3D SdNoData; } else if (Capability.Adma2 !=3D 0) { @@ -1071,12 +1089,16 @@ SdPeimFreeTrb ( IN SD_TRB *Trb ) { + if ((Trb !=3D NULL) && (Trb->DataMap !=3D NULL)) { + IoMmuUnmap (Trb->DataMap); + } + if ((Trb !=3D NULL) && (Trb->AdmaDesc !=3D NULL)) { SdPeimFreeMem (Trb->Slot->Private->Pool, Trb->AdmaDesc, Trb->AdmaDescS= ize); } =20 if (Trb !=3D NULL) { - SdPeimFreeMem (Trb->Slot->Private->Pool, Trb, sizeof (SD_TRB)); + FreePool (Trb); } return; } @@ -1241,11 +1263,11 @@ SdPeimExecTrb ( SdPeimHcLedOnOff (Bar, TRUE); =20 if (Trb->Mode =3D=3D SdSdmaMode) { - if ((UINT64)(UINTN)Trb->Data >=3D 0x100000000ul) { + if ((UINT64)(UINTN)Trb->DataPhy >=3D 0x100000000ul) { return EFI_INVALID_PARAMETER; } =20 - SdmaAddr =3D (UINT32)(UINTN)Trb->Data; + SdmaAddr =3D (UINT32)(UINTN)Trb->DataPhy; Status =3D SdPeimHcRwMmio (Bar + SD_HC_SDMA_ADDR, FALSE, sizeof (Sdm= aAddr), &SdmaAddr); if (EFI_ERROR (Status)) { return Status; @@ -1485,7 +1507,7 @@ SdPeimCheckTrbResult ( // // Update SDMA Address register. // - SdmaAddr =3D SD_SDMA_ROUND_UP ((UINT32)(UINTN)Trb->Data, SD_SDMA_BOUND= ARY); + SdmaAddr =3D SD_SDMA_ROUND_UP ((UINT32)(UINTN)Trb->DataPhy, SD_SDMA_BO= UNDARY); Status =3D SdPeimHcRwMmio ( Bar + SD_HC_SDMA_ADDR, FALSE, @@ -1495,7 +1517,7 @@ SdPeimCheckTrbResult ( if (EFI_ERROR (Status)) { goto Done; } - Trb->Data =3D (VOID*)(UINTN)SdmaAddr; + Trb->DataPhy =3D (UINT32)(UINTN)SdmaAddr; } =20 if ((Packet->SdCmdBlk->CommandType !=3D SdCommandTypeAdtc) && --=20 2.12.0.windows.1 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel