2 The DMA memory help function.
4 Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
12 EDKII_IOMMU_PPI
*mIoMmu
;
15 Provides the controller-specific addresses required to access system memory from a
18 @param Operation Indicates if the bus master is going to read or write to system memory.
19 @param HostAddress The system memory address to map to the PCI controller.
20 @param NumberOfBytes On input the number of bytes to map. On output the number of bytes
22 @param DeviceAddress The resulting map address for the bus master PCI controller to use to
23 access the hosts HostAddress.
24 @param Mapping A resulting value to pass to Unmap().
26 @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes.
27 @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common buffer.
28 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
29 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
30 @retval EFI_DEVICE_ERROR The system hardware could not map the requested address.
35 IN EDKII_IOMMU_OPERATION Operation
,
37 IN OUT UINTN
*NumberOfBytes
,
38 OUT EFI_PHYSICAL_ADDRESS
*DeviceAddress
,
46 Status
= mIoMmu
->Map (
54 if (EFI_ERROR (Status
)) {
55 return EFI_OUT_OF_RESOURCES
;
58 case EdkiiIoMmuOperationBusMasterRead
:
59 case EdkiiIoMmuOperationBusMasterRead64
:
60 Attribute
= EDKII_IOMMU_ACCESS_READ
;
62 case EdkiiIoMmuOperationBusMasterWrite
:
63 case EdkiiIoMmuOperationBusMasterWrite64
:
64 Attribute
= EDKII_IOMMU_ACCESS_WRITE
;
66 case EdkiiIoMmuOperationBusMasterCommonBuffer
:
67 case EdkiiIoMmuOperationBusMasterCommonBuffer64
:
68 Attribute
= EDKII_IOMMU_ACCESS_READ
| EDKII_IOMMU_ACCESS_WRITE
;
72 return EFI_INVALID_PARAMETER
;
74 Status
= mIoMmu
->SetAttribute (
79 if (EFI_ERROR (Status
)) {
83 *DeviceAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)HostAddress
;
91 Completes the Map() operation and releases any corresponding resources.
93 @param Mapping The mapping value returned from Map().
95 @retval EFI_SUCCESS The range was unmapped.
96 @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by Map().
97 @retval EFI_DEVICE_ERROR The data was not committed to the target system memory.
106 if (mIoMmu
!= NULL
) {
107 Status
= mIoMmu
->SetAttribute (mIoMmu
, Mapping
, 0);
108 Status
= mIoMmu
->Unmap (mIoMmu
, Mapping
);
110 Status
= EFI_SUCCESS
;
116 Allocates pages that are suitable for an OperationBusMasterCommonBuffer or
117 OperationBusMasterCommonBuffer64 mapping.
119 @param Pages The number of pages to allocate.
120 @param HostAddress A pointer to store the base system memory address of the
122 @param DeviceAddress The resulting map address for the bus master PCI controller to use to
123 access the hosts HostAddress.
124 @param Mapping A resulting value to pass to Unmap().
126 @retval EFI_SUCCESS The requested memory pages were allocated.
127 @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal attribute bits are
128 MEMORY_WRITE_COMBINE and MEMORY_CACHED.
129 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
130 @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
134 IoMmuAllocateBuffer (
136 OUT VOID
**HostAddress
,
137 OUT EFI_PHYSICAL_ADDRESS
*DeviceAddress
,
143 EFI_PHYSICAL_ADDRESS HostPhyAddress
;
148 if (mIoMmu
!= NULL
) {
149 Status
= mIoMmu
->AllocateBuffer (
156 if (EFI_ERROR (Status
)) {
157 return EFI_OUT_OF_RESOURCES
;
160 NumberOfBytes
= EFI_PAGES_TO_SIZE(Pages
);
161 Status
= mIoMmu
->Map (
163 EdkiiIoMmuOperationBusMasterCommonBuffer
,
169 if (EFI_ERROR (Status
)) {
170 return EFI_OUT_OF_RESOURCES
;
172 Status
= mIoMmu
->SetAttribute (
175 EDKII_IOMMU_ACCESS_READ
| EDKII_IOMMU_ACCESS_WRITE
177 if (EFI_ERROR (Status
)) {
181 Status
= PeiServicesAllocatePages (
186 if (EFI_ERROR (Status
)) {
187 return EFI_OUT_OF_RESOURCES
;
189 *HostAddress
= (VOID
*)(UINTN
)HostPhyAddress
;
190 *DeviceAddress
= HostPhyAddress
;
197 Frees memory that was allocated with AllocateBuffer().
199 @param Pages The number of pages to free.
200 @param HostAddress The base system memory address of the allocated range.
201 @param Mapping The mapping value returned from Map().
203 @retval EFI_SUCCESS The requested memory pages were freed.
204 @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and Pages
205 was not allocated with AllocateBuffer().
211 IN VOID
*HostAddress
,
217 if (mIoMmu
!= NULL
) {
218 Status
= mIoMmu
->SetAttribute (mIoMmu
, Mapping
, 0);
219 Status
= mIoMmu
->Unmap (mIoMmu
, Mapping
);
220 Status
= mIoMmu
->FreeBuffer (mIoMmu
, Pages
, HostAddress
);
222 Status
= EFI_SUCCESS
;
228 Allocates aligned pages that are suitable for an OperationBusMasterCommonBuffer or
229 OperationBusMasterCommonBuffer64 mapping.
231 @param Pages The number of pages to allocate.
232 @param Alignment The requested alignment of the allocation. Must be a power of two.
233 @param HostAddress A pointer to store the base system memory address of the
235 @param DeviceAddress The resulting map address for the bus master PCI controller to use to
236 access the hosts HostAddress.
237 @param Mapping A resulting value to pass to Unmap().
239 @retval EFI_SUCCESS The requested memory pages were allocated.
240 @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal attribute bits are
241 MEMORY_WRITE_COMBINE and MEMORY_CACHED.
242 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
243 @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
247 IoMmuAllocateAlignedBuffer (
250 OUT VOID
**HostAddress
,
251 OUT EFI_PHYSICAL_ADDRESS
*DeviceAddress
,
259 UINTN UnalignedPages
;
262 EFI_PHYSICAL_ADDRESS HostPhyAddress
;
266 AlignmentMask
= Alignment
- 1;
269 // Calculate the total number of pages since alignment is larger than page size.
271 RealPages
= Pages
+ EFI_SIZE_TO_PAGES (Alignment
);
274 // Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not overflow.
276 ASSERT (RealPages
> Pages
);
278 if (mIoMmu
!= NULL
) {
279 Status
= mIoMmu
->AllocateBuffer (
286 if (EFI_ERROR (Status
)) {
287 return EFI_OUT_OF_RESOURCES
;
289 Memory
= *HostAddress
;
290 AlignedMemory
= ((UINTN
) Memory
+ AlignmentMask
) & ~AlignmentMask
;
291 UnalignedPages
= EFI_SIZE_TO_PAGES (AlignedMemory
- (UINTN
) Memory
);
292 if (UnalignedPages
> 0) {
294 // Free first unaligned page(s).
296 Status
= mIoMmu
->FreeBuffer (
300 if (EFI_ERROR (Status
)) {
304 Memory
= (VOID
*)(UINTN
)(AlignedMemory
+ EFI_PAGES_TO_SIZE (Pages
));
305 UnalignedPages
= RealPages
- Pages
- UnalignedPages
;
306 if (UnalignedPages
> 0) {
308 // Free last unaligned page(s).
310 Status
= mIoMmu
->FreeBuffer (
314 if (EFI_ERROR (Status
)) {
318 *HostAddress
= (VOID
*) AlignedMemory
;
319 NumberOfBytes
= EFI_PAGES_TO_SIZE(Pages
);
320 Status
= mIoMmu
->Map (
322 EdkiiIoMmuOperationBusMasterCommonBuffer
,
328 if (EFI_ERROR (Status
)) {
329 return EFI_OUT_OF_RESOURCES
;
331 Status
= mIoMmu
->SetAttribute (
334 EDKII_IOMMU_ACCESS_READ
| EDKII_IOMMU_ACCESS_WRITE
336 if (EFI_ERROR (Status
)) {
340 Status
= PeiServicesAllocatePages (
345 if (EFI_ERROR (Status
)) {
346 return EFI_OUT_OF_RESOURCES
;
348 *HostAddress
= (VOID
*)(((UINTN
) HostPhyAddress
+ AlignmentMask
) & ~AlignmentMask
);
349 *DeviceAddress
= ((UINTN
) HostPhyAddress
+ AlignmentMask
) & ~AlignmentMask
;
363 PeiServicesLocatePpi (