]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Pci/NvmExpressPei/DmaMem.c
MdeModulePkg/PciBusDxe: Fix small memory leak in FreePciDevice
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / NvmExpressPei / DmaMem.c
CommitLineData
b8b69433
HW
1/** @file\r
2 The DMA memory help function.\r
3\r
4 Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>\r
5\r
6 This program and the accompanying materials\r
7 are licensed and made available under the terms and conditions\r
8 of the BSD License which accompanies this distribution. The\r
9 full text of the license may be found at\r
10 http://opensource.org/licenses/bsd-license.php\r
11\r
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
14\r
15**/\r
16\r
17#include "NvmExpressPei.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