TianoCore EDK2 master
Loading...
Searching...
No Matches
DmaMem.c
Go to the documentation of this file.
1
10#include "XhcPeim.h"
11
12EDKII_IOMMU_PPI *mIoMmu;
13
35 IN EDKII_IOMMU_OPERATION Operation,
36 IN VOID *HostAddress,
37 IN OUT UINTN *NumberOfBytes,
38 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
39 OUT VOID **Mapping
40 )
41{
42 EFI_STATUS Status;
43 UINT64 Attribute;
44
45 if (mIoMmu != NULL) {
46 Status = mIoMmu->Map (
47 mIoMmu,
48 Operation,
49 HostAddress,
50 NumberOfBytes,
51 DeviceAddress,
52 Mapping
53 );
54 if (EFI_ERROR (Status)) {
55 return EFI_OUT_OF_RESOURCES;
56 }
57
58 switch (Operation) {
61 Attribute = EDKII_IOMMU_ACCESS_READ;
62 break;
65 Attribute = EDKII_IOMMU_ACCESS_WRITE;
66 break;
69 Attribute = EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE;
70 break;
71 default:
72 ASSERT (FALSE);
73 return EFI_INVALID_PARAMETER;
74 }
75
76 Status = mIoMmu->SetAttribute (
77 mIoMmu,
78 *Mapping,
79 Attribute
80 );
81 if (EFI_ERROR (Status)) {
82 return Status;
83 }
84 } else {
85 *DeviceAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress;
86 *Mapping = NULL;
87 Status = EFI_SUCCESS;
88 }
89
90 return Status;
91}
92
104 IN VOID *Mapping
105 )
106{
107 EFI_STATUS Status;
108
109 if (mIoMmu != NULL) {
110 Status = mIoMmu->SetAttribute (mIoMmu, Mapping, 0);
111 Status = mIoMmu->Unmap (mIoMmu, Mapping);
112 } else {
113 Status = EFI_SUCCESS;
114 }
115
116 return Status;
117}
118
139 IN UINTN Pages,
140 OUT VOID **HostAddress,
141 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
142 OUT VOID **Mapping
143 )
144{
145 EFI_STATUS Status;
146 UINTN NumberOfBytes;
147 EFI_PHYSICAL_ADDRESS HostPhyAddress;
148
149 *HostAddress = NULL;
150 *DeviceAddress = 0;
151
152 if (mIoMmu != NULL) {
153 Status = mIoMmu->AllocateBuffer (
154 mIoMmu,
156 Pages,
157 HostAddress,
158 0
159 );
160 if (EFI_ERROR (Status)) {
161 return EFI_OUT_OF_RESOURCES;
162 }
163
164 NumberOfBytes = EFI_PAGES_TO_SIZE (Pages);
165 Status = mIoMmu->Map (
166 mIoMmu,
168 *HostAddress,
169 &NumberOfBytes,
170 DeviceAddress,
171 Mapping
172 );
173 if (EFI_ERROR (Status)) {
174 return EFI_OUT_OF_RESOURCES;
175 }
176
177 Status = mIoMmu->SetAttribute (
178 mIoMmu,
179 *Mapping,
180 EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE
181 );
182 if (EFI_ERROR (Status)) {
183 return Status;
184 }
185 } else {
186 Status = PeiServicesAllocatePages (
188 Pages,
189 &HostPhyAddress
190 );
191 if (EFI_ERROR (Status)) {
192 return EFI_OUT_OF_RESOURCES;
193 }
194
195 *HostAddress = (VOID *)(UINTN)HostPhyAddress;
196 *DeviceAddress = HostPhyAddress;
197 *Mapping = NULL;
198 }
199
200 return Status;
201}
202
217 IN UINTN Pages,
218 IN VOID *HostAddress,
219 IN VOID *Mapping
220 )
221{
222 EFI_STATUS Status;
223
224 if (mIoMmu != NULL) {
225 Status = mIoMmu->SetAttribute (mIoMmu, Mapping, 0);
226 Status = mIoMmu->Unmap (mIoMmu, Mapping);
227 Status = mIoMmu->FreeBuffer (mIoMmu, Pages, HostAddress);
228 } else {
229 Status = EFI_SUCCESS;
230 }
231
232 return Status;
233}
234
256 IN UINTN Pages,
257 IN UINTN Alignment,
258 OUT VOID **HostAddress,
259 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
260 OUT VOID **Mapping
261 )
262{
263 EFI_STATUS Status;
264 VOID *Memory;
265 UINTN AlignedMemory;
266 UINTN AlignmentMask;
267 UINTN UnalignedPages;
268 UINTN RealPages;
269 UINTN NumberOfBytes;
270 EFI_PHYSICAL_ADDRESS HostPhyAddress;
271
272 *HostAddress = NULL;
273 *DeviceAddress = 0;
274 AlignmentMask = Alignment - 1;
275
276 //
277 // Calculate the total number of pages since alignment is larger than page size.
278 //
279 RealPages = Pages + EFI_SIZE_TO_PAGES (Alignment);
280
281 //
282 // Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not overflow.
283 //
284 ASSERT (RealPages > Pages);
285
286 if (mIoMmu != NULL) {
287 Status = mIoMmu->AllocateBuffer (
288 mIoMmu,
290 RealPages,
291 HostAddress,
292 0
293 );
294 if (EFI_ERROR (Status)) {
295 return EFI_OUT_OF_RESOURCES;
296 }
297
298 Memory = *HostAddress;
299 AlignedMemory = ((UINTN)Memory + AlignmentMask) & ~AlignmentMask;
300 UnalignedPages = EFI_SIZE_TO_PAGES (AlignedMemory - (UINTN)Memory);
301 if (UnalignedPages > 0) {
302 //
303 // Free first unaligned page(s).
304 //
305 Status = mIoMmu->FreeBuffer (
306 mIoMmu,
307 UnalignedPages,
308 Memory
309 );
310 if (EFI_ERROR (Status)) {
311 return Status;
312 }
313 }
314
315 Memory = (VOID *)(UINTN)(AlignedMemory + EFI_PAGES_TO_SIZE (Pages));
316 UnalignedPages = RealPages - Pages - UnalignedPages;
317 if (UnalignedPages > 0) {
318 //
319 // Free last unaligned page(s).
320 //
321 Status = mIoMmu->FreeBuffer (
322 mIoMmu,
323 UnalignedPages,
324 Memory
325 );
326 if (EFI_ERROR (Status)) {
327 return Status;
328 }
329 }
330
331 *HostAddress = (VOID *)AlignedMemory;
332 NumberOfBytes = EFI_PAGES_TO_SIZE (Pages);
333 Status = mIoMmu->Map (
334 mIoMmu,
336 *HostAddress,
337 &NumberOfBytes,
338 DeviceAddress,
339 Mapping
340 );
341 if (EFI_ERROR (Status)) {
342 return EFI_OUT_OF_RESOURCES;
343 }
344
345 Status = mIoMmu->SetAttribute (
346 mIoMmu,
347 *Mapping,
348 EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE
349 );
350 if (EFI_ERROR (Status)) {
351 return Status;
352 }
353 } else {
354 Status = PeiServicesAllocatePages (
356 RealPages,
357 &HostPhyAddress
358 );
359 if (EFI_ERROR (Status)) {
360 return EFI_OUT_OF_RESOURCES;
361 }
362
363 *HostAddress = (VOID *)(((UINTN)HostPhyAddress + AlignmentMask) & ~AlignmentMask);
364 *DeviceAddress = ((UINTN)HostPhyAddress + AlignmentMask) & ~AlignmentMask;
365 *Mapping = NULL;
366 }
367
368 return Status;
369}
370
374VOID
376 VOID
377 )
378{
381 0,
382 NULL,
383 (VOID **)&mIoMmu
384 );
385}
UINT64 UINTN
EFI_STATUS IoMmuUnmap(IN VOID *Mapping)
Definition: DmaMem.c:132
EFI_STATUS IoMmuAllocateBuffer(IN UINTN Pages, OUT VOID **HostAddress, OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, OUT VOID **Mapping)
Definition: DmaMem.c:170
EFI_STATUS IoMmuMap(IN EDKII_IOMMU_OPERATION Operation, IN VOID *HostAddress, IN OUT UINTN *NumberOfBytes, OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, OUT VOID **Mapping)
Definition: DmaMem.c:60
EFI_STATUS IoMmuFreeBuffer(IN UINTN Pages, IN VOID *HostAddress, IN VOID *Mapping)
Definition: DmaMem.c:251
EFI_STATUS EFIAPI PeiServicesLocatePpi(IN CONST EFI_GUID *Guid, IN UINTN Instance, IN OUT EFI_PEI_PPI_DESCRIPTOR **PpiDescriptor, IN OUT VOID **Ppi)
EFI_STATUS EFIAPI PeiServicesAllocatePages(IN EFI_MEMORY_TYPE MemoryType, IN UINTN Pages, OUT EFI_PHYSICAL_ADDRESS *Memory)
#define NULL
Definition: Base.h:319
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
VOID IoMmuInit(OUT EDKII_IOMMU_PPI **IoMmu)
Definition: DmaMem.c:238
EFI_STATUS IoMmuAllocateAlignedBuffer(IN UINTN Pages, IN UINTN Alignment, OUT VOID **HostAddress, OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, OUT VOID **Mapping)
Definition: DmaMem.c:255
EFI_GUID gEdkiiIoMmuPpiGuid
EDKII_IOMMU_OPERATION
Definition: IoMmu.h:44
@ EdkiiIoMmuOperationBusMasterWrite
Definition: IoMmu.h:54
@ EdkiiIoMmuOperationBusMasterWrite64
Definition: IoMmu.h:69
@ EdkiiIoMmuOperationBusMasterCommonBuffer
Definition: IoMmu.h:59
@ EdkiiIoMmuOperationBusMasterRead64
Definition: IoMmu.h:64
@ EdkiiIoMmuOperationBusMasterRead
Definition: IoMmu.h:49
@ EdkiiIoMmuOperationBusMasterCommonBuffer64
Definition: IoMmu.h:74
UINT64 EFI_PHYSICAL_ADDRESS
Definition: UefiBaseType.h:50
#define EFI_PAGES_TO_SIZE(Pages)
Definition: UefiBaseType.h:213
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SIZE_TO_PAGES(Size)
Definition: UefiBaseType.h:200
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
@ EfiBootServicesData