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