]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Pci/UhciPei/DmaMem.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / UhciPei / DmaMem.c
1 /** @file
2 The DMA memory help functions.
3
4 Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
5
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 **/
9
10 #include "UhcPeim.h"
11
12 /**
13 Provides the controller-specific addresses required to access system memory from a
14 DMA bus master.
15
16 @param IoMmu Pointer to IOMMU PPI.
17 @param Operation Indicates if the bus master is going to read or write to system memory.
18 @param HostAddress The system memory address to map to the PCI controller.
19 @param NumberOfBytes On input the number of bytes to map. On output the number of bytes
20 that were mapped.
21 @param DeviceAddress The resulting map address for the bus master PCI controller to use to
22 access the hosts HostAddress.
23 @param Mapping A resulting value to pass to Unmap().
24
25 @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes.
26 @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common buffer.
27 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
28 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
29 @retval EFI_DEVICE_ERROR The system hardware could not map the requested address.
30
31 **/
32 EFI_STATUS
33 IoMmuMap (
34 IN EDKII_IOMMU_PPI *IoMmu,
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 (IoMmu != NULL) {
46 Status = IoMmu->Map (
47 IoMmu,
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) {
59 case EdkiiIoMmuOperationBusMasterRead:
60 case EdkiiIoMmuOperationBusMasterRead64:
61 Attribute = EDKII_IOMMU_ACCESS_READ;
62 break;
63 case EdkiiIoMmuOperationBusMasterWrite:
64 case EdkiiIoMmuOperationBusMasterWrite64:
65 Attribute = EDKII_IOMMU_ACCESS_WRITE;
66 break;
67 case EdkiiIoMmuOperationBusMasterCommonBuffer:
68 case EdkiiIoMmuOperationBusMasterCommonBuffer64:
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 = IoMmu->SetAttribute (
77 IoMmu,
78 *Mapping,
79 Attribute
80 );
81 if (EFI_ERROR (Status)) {
82 IoMmu->Unmap (IoMmu, Mapping);
83 *Mapping = NULL;
84 return Status;
85 }
86 } else {
87 *DeviceAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress;
88 *Mapping = NULL;
89 Status = EFI_SUCCESS;
90 }
91
92 return Status;
93 }
94
95 /**
96 Completes the Map() operation and releases any corresponding resources.
97
98 @param IoMmu Pointer to IOMMU PPI.
99 @param Mapping The mapping value returned from Map().
100
101 **/
102 VOID
103 IoMmuUnmap (
104 IN EDKII_IOMMU_PPI *IoMmu,
105 IN VOID *Mapping
106 )
107 {
108 if (IoMmu != NULL) {
109 IoMmu->SetAttribute (IoMmu, Mapping, 0);
110 IoMmu->Unmap (IoMmu, Mapping);
111 }
112 }
113
114 /**
115 Allocates pages that are suitable for an OperationBusMasterCommonBuffer or
116 OperationBusMasterCommonBuffer64 mapping.
117
118 @param IoMmu Pointer to IOMMU PPI.
119 @param Pages The number of pages to allocate.
120 @param HostAddress A pointer to store the base system memory address of the
121 allocated range.
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().
125
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.
131
132 **/
133 EFI_STATUS
134 IoMmuAllocateBuffer (
135 IN EDKII_IOMMU_PPI *IoMmu,
136 IN UINTN Pages,
137 OUT VOID **HostAddress,
138 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
139 OUT VOID **Mapping
140 )
141 {
142 EFI_STATUS Status;
143 UINTN NumberOfBytes;
144 EFI_PHYSICAL_ADDRESS HostPhyAddress;
145
146 *HostAddress = NULL;
147 *DeviceAddress = 0;
148 *Mapping = NULL;
149
150 if (IoMmu != NULL) {
151 Status = IoMmu->AllocateBuffer (
152 IoMmu,
153 EfiBootServicesData,
154 Pages,
155 HostAddress,
156 0
157 );
158 if (EFI_ERROR (Status)) {
159 return EFI_OUT_OF_RESOURCES;
160 }
161
162 NumberOfBytes = EFI_PAGES_TO_SIZE (Pages);
163 Status = IoMmu->Map (
164 IoMmu,
165 EdkiiIoMmuOperationBusMasterCommonBuffer,
166 *HostAddress,
167 &NumberOfBytes,
168 DeviceAddress,
169 Mapping
170 );
171 if (EFI_ERROR (Status)) {
172 IoMmu->FreeBuffer (IoMmu, Pages, *HostAddress);
173 *HostAddress = NULL;
174 return EFI_OUT_OF_RESOURCES;
175 }
176
177 Status = IoMmu->SetAttribute (
178 IoMmu,
179 *Mapping,
180 EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE
181 );
182 if (EFI_ERROR (Status)) {
183 IoMmu->Unmap (IoMmu, *Mapping);
184 IoMmu->FreeBuffer (IoMmu, Pages, *HostAddress);
185 *Mapping = NULL;
186 *HostAddress = NULL;
187 return Status;
188 }
189 } else {
190 Status = PeiServicesAllocatePages (
191 EfiBootServicesData,
192 Pages,
193 &HostPhyAddress
194 );
195 if (EFI_ERROR (Status)) {
196 return EFI_OUT_OF_RESOURCES;
197 }
198
199 *HostAddress = (VOID *)(UINTN)HostPhyAddress;
200 *DeviceAddress = HostPhyAddress;
201 *Mapping = NULL;
202 }
203
204 return Status;
205 }
206
207 /**
208 Initialize IOMMU.
209
210 @param IoMmu Pointer to pointer to IOMMU PPI.
211
212 **/
213 VOID
214 IoMmuInit (
215 OUT EDKII_IOMMU_PPI **IoMmu
216 )
217 {
218 *IoMmu = NULL;
219 PeiServicesLocatePpi (
220 &gEdkiiIoMmuPpiGuid,
221 0,
222 NULL,
223 (VOID **)IoMmu
224 );
225 }