DmaMem.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. /** @file
  2. The DMA memory help function.
  3. Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
  4. Copyright (c) 1985 - 2022, American Megatrends International LLC. <BR>
  5. SPDX-License-Identifier: BSD-2-Clause-Patent
  6. **/
  7. #include "UfsBlockIoPei.h"
  8. EDKII_IOMMU_PPI *mIoMmu;
  9. /**
  10. Provides the controller-specific addresses required to access system memory from a
  11. DMA bus master.
  12. @param Operation Indicates if the bus master is going to read or write to system memory.
  13. @param HostAddress The system memory address to map to the PCI controller.
  14. @param NumberOfBytes On input the number of bytes to map. On output the number of bytes
  15. that were mapped.
  16. @param DeviceAddress The resulting map address for the bus master PCI controller to use to
  17. access the hosts HostAddress.
  18. @param Mapping A resulting value to pass to Unmap().
  19. @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes.
  20. @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common buffer.
  21. @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
  22. @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
  23. @retval EFI_DEVICE_ERROR The system hardware could not map the requested address.
  24. **/
  25. EFI_STATUS
  26. IoMmuMap (
  27. IN EDKII_IOMMU_OPERATION Operation,
  28. IN VOID *HostAddress,
  29. IN OUT UINTN *NumberOfBytes,
  30. OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
  31. OUT VOID **Mapping
  32. )
  33. {
  34. EFI_STATUS Status;
  35. UINT64 Attribute;
  36. if (mIoMmu != NULL) {
  37. Status = mIoMmu->Map (
  38. mIoMmu,
  39. Operation,
  40. HostAddress,
  41. NumberOfBytes,
  42. DeviceAddress,
  43. Mapping
  44. );
  45. if (EFI_ERROR (Status)) {
  46. return EFI_OUT_OF_RESOURCES;
  47. }
  48. switch (Operation) {
  49. case EdkiiIoMmuOperationBusMasterRead:
  50. case EdkiiIoMmuOperationBusMasterRead64:
  51. Attribute = EDKII_IOMMU_ACCESS_READ;
  52. break;
  53. case EdkiiIoMmuOperationBusMasterWrite:
  54. case EdkiiIoMmuOperationBusMasterWrite64:
  55. Attribute = EDKII_IOMMU_ACCESS_WRITE;
  56. break;
  57. case EdkiiIoMmuOperationBusMasterCommonBuffer:
  58. case EdkiiIoMmuOperationBusMasterCommonBuffer64:
  59. Attribute = EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE;
  60. break;
  61. default:
  62. ASSERT (FALSE);
  63. return EFI_INVALID_PARAMETER;
  64. }
  65. Status = mIoMmu->SetAttribute (
  66. mIoMmu,
  67. *Mapping,
  68. Attribute
  69. );
  70. if (EFI_ERROR (Status)) {
  71. return Status;
  72. }
  73. } else {
  74. *DeviceAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress;
  75. *Mapping = NULL;
  76. Status = EFI_SUCCESS;
  77. }
  78. return Status;
  79. }
  80. /**
  81. Completes the Map() operation and releases any corresponding resources.
  82. @param Mapping The mapping value returned from Map().
  83. @retval EFI_SUCCESS The range was unmapped.
  84. @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by Map().
  85. @retval EFI_DEVICE_ERROR The data was not committed to the target system memory.
  86. **/
  87. EFI_STATUS
  88. IoMmuUnmap (
  89. IN VOID *Mapping
  90. )
  91. {
  92. EFI_STATUS Status;
  93. if (mIoMmu != NULL) {
  94. Status = mIoMmu->SetAttribute (mIoMmu, Mapping, 0);
  95. Status = mIoMmu->Unmap (mIoMmu, Mapping);
  96. } else {
  97. Status = EFI_SUCCESS;
  98. }
  99. return Status;
  100. }
  101. /**
  102. Allocates pages that are suitable for an OperationBusMasterCommonBuffer or
  103. OperationBusMasterCommonBuffer64 mapping.
  104. @param Pages The number of pages to allocate.
  105. @param HostAddress A pointer to store the base system memory address of the
  106. allocated range.
  107. @param DeviceAddress The resulting map address for the bus master PCI controller to use to
  108. access the hosts HostAddress.
  109. @param Mapping A resulting value to pass to Unmap().
  110. @retval EFI_SUCCESS The requested memory pages were allocated.
  111. @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal attribute bits are
  112. MEMORY_WRITE_COMBINE and MEMORY_CACHED.
  113. @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
  114. @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
  115. **/
  116. EFI_STATUS
  117. IoMmuAllocateBuffer (
  118. IN UINTN Pages,
  119. OUT VOID **HostAddress,
  120. OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
  121. OUT VOID **Mapping
  122. )
  123. {
  124. EFI_STATUS Status;
  125. UINTN NumberOfBytes;
  126. EFI_PHYSICAL_ADDRESS HostPhyAddress;
  127. *HostAddress = NULL;
  128. *DeviceAddress = 0;
  129. if (mIoMmu != NULL) {
  130. Status = mIoMmu->AllocateBuffer (
  131. mIoMmu,
  132. EfiBootServicesData,
  133. Pages,
  134. HostAddress,
  135. 0
  136. );
  137. if (EFI_ERROR (Status)) {
  138. return EFI_OUT_OF_RESOURCES;
  139. }
  140. NumberOfBytes = EFI_PAGES_TO_SIZE (Pages);
  141. Status = mIoMmu->Map (
  142. mIoMmu,
  143. EdkiiIoMmuOperationBusMasterCommonBuffer,
  144. *HostAddress,
  145. &NumberOfBytes,
  146. DeviceAddress,
  147. Mapping
  148. );
  149. if (EFI_ERROR (Status)) {
  150. return EFI_OUT_OF_RESOURCES;
  151. }
  152. Status = mIoMmu->SetAttribute (
  153. mIoMmu,
  154. *Mapping,
  155. EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE
  156. );
  157. if (EFI_ERROR (Status)) {
  158. return Status;
  159. }
  160. } else {
  161. Status = PeiServicesAllocatePages (
  162. EfiBootServicesData,
  163. Pages,
  164. &HostPhyAddress
  165. );
  166. if (EFI_ERROR (Status)) {
  167. return EFI_OUT_OF_RESOURCES;
  168. }
  169. *HostAddress = (VOID *)(UINTN)HostPhyAddress;
  170. *DeviceAddress = HostPhyAddress;
  171. *Mapping = NULL;
  172. }
  173. return Status;
  174. }
  175. /**
  176. Frees memory that was allocated with AllocateBuffer().
  177. @param Pages The number of pages to free.
  178. @param HostAddress The base system memory address of the allocated range.
  179. @param Mapping The mapping value returned from Map().
  180. @retval EFI_SUCCESS The requested memory pages were freed.
  181. @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and Pages
  182. was not allocated with AllocateBuffer().
  183. **/
  184. EFI_STATUS
  185. IoMmuFreeBuffer (
  186. IN UINTN Pages,
  187. IN VOID *HostAddress,
  188. IN VOID *Mapping
  189. )
  190. {
  191. EFI_STATUS Status;
  192. if (mIoMmu != NULL) {
  193. Status = mIoMmu->SetAttribute (mIoMmu, Mapping, 0);
  194. Status = mIoMmu->Unmap (mIoMmu, Mapping);
  195. Status = mIoMmu->FreeBuffer (mIoMmu, Pages, HostAddress);
  196. } else {
  197. Status = EFI_SUCCESS;
  198. }
  199. return Status;
  200. }
  201. /**
  202. Initialize IOMMU.
  203. **/
  204. VOID
  205. IoMmuInit (
  206. VOID
  207. )
  208. {
  209. EFI_STATUS Status;
  210. Status = PeiServicesLocatePpi (
  211. &gEdkiiIoMmuPpiGuid,
  212. 0,
  213. NULL,
  214. (VOID **)&mIoMmu
  215. );
  216. if (EFI_ERROR (Status)) {
  217. DEBUG ((DEBUG_INFO, "Locate mIoMmu Ppi is failed!!!\n"));
  218. }
  219. }