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