https://bugzilla.tianocore.org/show_bug.cgi?id=1373 Replace BSD 2-Clause License with BSD+Patent License. This change is based on the following emails: https://lists.01.org/pipermail/edk2-devel/2019-February/036260.html https://lists.01.org/pipermail/edk2-devel/2018-October/030385.html RFCs with detailed process for the license change: V3: https://lists.01.org/pipermail/edk2-devel/2019-March/038116.html V2: https://lists.01.org/pipermail/edk2-devel/2019-March/037669.html V1: https://lists.01.org/pipermail/edk2-devel/2019-March/037500.html Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com> Reviewed-by: Hao Wu <hao.a.wu@intel.com> Reviewed-by: Jian J Wang <jian.j.wang@intel.com>
		
			
				
	
	
		
			243 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			243 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  The DMA memory help function.
 | 
						|
 | 
						|
  Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
 | 
						|
 | 
						|
  SPDX-License-Identifier: BSD-2-Clause-Patent
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#include "EmmcBlockIoPei.h"
 | 
						|
 | 
						|
EDKII_IOMMU_PPI  *mIoMmu;
 | 
						|
 | 
						|
/**
 | 
						|
  Provides the controller-specific addresses required to access system memory from a
 | 
						|
  DMA bus master.
 | 
						|
 | 
						|
  @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.
 | 
						|
 | 
						|
**/
 | 
						|
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 != NULL) {
 | 
						|
    Status = mIoMmu->Map (
 | 
						|
                       mIoMmu,
 | 
						|
                       Operation,
 | 
						|
                       HostAddress,
 | 
						|
                       NumberOfBytes,
 | 
						|
                       DeviceAddress,
 | 
						|
                       Mapping
 | 
						|
                       );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      return EFI_OUT_OF_RESOURCES;
 | 
						|
    }
 | 
						|
    switch (Operation) {
 | 
						|
    case EdkiiIoMmuOperationBusMasterRead:
 | 
						|
    case EdkiiIoMmuOperationBusMasterRead64:
 | 
						|
      Attribute = EDKII_IOMMU_ACCESS_READ;
 | 
						|
      break;
 | 
						|
    case EdkiiIoMmuOperationBusMasterWrite:
 | 
						|
    case EdkiiIoMmuOperationBusMasterWrite64:
 | 
						|
      Attribute = EDKII_IOMMU_ACCESS_WRITE;
 | 
						|
      break;
 | 
						|
    case EdkiiIoMmuOperationBusMasterCommonBuffer:
 | 
						|
    case EdkiiIoMmuOperationBusMasterCommonBuffer64:
 | 
						|
      Attribute = EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE;
 | 
						|
      break;
 | 
						|
    default:
 | 
						|
      ASSERT(FALSE);
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
    Status = mIoMmu->SetAttribute (
 | 
						|
                       mIoMmu,
 | 
						|
                       *Mapping,
 | 
						|
                       Attribute
 | 
						|
                       );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    *DeviceAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress;
 | 
						|
    *Mapping = NULL;
 | 
						|
    Status = 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 by Map().
 | 
						|
  @retval EFI_DEVICE_ERROR      The data was not committed to the target system memory.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
IoMmuUnmap (
 | 
						|
  IN VOID                  *Mapping
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
 | 
						|
  if (mIoMmu != NULL) {
 | 
						|
    Status = mIoMmu->SetAttribute (mIoMmu, Mapping, 0);
 | 
						|
    Status = mIoMmu->Unmap (mIoMmu, Mapping);
 | 
						|
  } else {
 | 
						|
    Status = 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 master 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 = NULL;
 | 
						|
  *DeviceAddress = 0;
 | 
						|
 | 
						|
  if (mIoMmu != NULL) {
 | 
						|
    Status = mIoMmu->AllocateBuffer (
 | 
						|
                       mIoMmu,
 | 
						|
                       EfiBootServicesData,
 | 
						|
                       Pages,
 | 
						|
                       HostAddress,
 | 
						|
                       0
 | 
						|
                       );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      return EFI_OUT_OF_RESOURCES;
 | 
						|
    }
 | 
						|
 | 
						|
    NumberOfBytes = EFI_PAGES_TO_SIZE(Pages);
 | 
						|
    Status = mIoMmu->Map (
 | 
						|
                       mIoMmu,
 | 
						|
                       EdkiiIoMmuOperationBusMasterCommonBuffer,
 | 
						|
                       *HostAddress,
 | 
						|
                       &NumberOfBytes,
 | 
						|
                       DeviceAddress,
 | 
						|
                       Mapping
 | 
						|
                       );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      return EFI_OUT_OF_RESOURCES;
 | 
						|
    }
 | 
						|
    Status = mIoMmu->SetAttribute (
 | 
						|
                       mIoMmu,
 | 
						|
                       *Mapping,
 | 
						|
                       EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE
 | 
						|
                       );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    Status = PeiServicesAllocatePages (
 | 
						|
               EfiBootServicesData,
 | 
						|
               Pages,
 | 
						|
               &HostPhyAddress
 | 
						|
               );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      return EFI_OUT_OF_RESOURCES;
 | 
						|
    }
 | 
						|
    *HostAddress = (VOID *)(UINTN)HostPhyAddress;
 | 
						|
    *DeviceAddress = HostPhyAddress;
 | 
						|
    *Mapping = 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 allocated 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 != NULL) {
 | 
						|
    Status = mIoMmu->SetAttribute (mIoMmu, Mapping, 0);
 | 
						|
    Status = mIoMmu->Unmap (mIoMmu, Mapping);
 | 
						|
    Status = mIoMmu->FreeBuffer (mIoMmu, Pages, HostAddress);
 | 
						|
  } else {
 | 
						|
    Status = EFI_SUCCESS;
 | 
						|
  }
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Initialize IOMMU.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
IoMmuInit (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  PeiServicesLocatePpi (
 | 
						|
    &gEdkiiIoMmuPpiGuid,
 | 
						|
    0,
 | 
						|
    NULL,
 | 
						|
    (VOID **)&mIoMmu
 | 
						|
    );
 | 
						|
}
 | 
						|
 |