]> git.proxmox.com Git - mirror_edk2.git/blame - SourceLevelDebugPkg/Library/DebugCommunicationLibUsb3/DebugCommunicationLibUsb3Pei.c
SourceLevelDebugPkg DebugUsb3: Support IOMMU
[mirror_edk2.git] / SourceLevelDebugPkg / Library / DebugCommunicationLibUsb3 / DebugCommunicationLibUsb3Pei.c
CommitLineData
2cb6eabe
EL
1/** @file\r
2 Debug Port Library implementation based on usb3 debug port.\r
3\r
de8373fa 4 Copyright (c) 2014 - 2018, Intel Corporation. All rights reserved.<BR>\r
2cb6eabe
EL
5 This program and the accompanying materials\r
6 are licensed and made available under the terms and conditions of the BSD License\r
7 which accompanies this distribution. The full text of the license may be found at\r
8 http://opensource.org/licenses/bsd-license.php.\r
9\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include <PiPei.h>\r
16#include <Library/PeiServicesLib.h>\r
de8373fa 17#include <Library/HobLib.h>\r
364f63c0 18#include <Ppi/MemoryDiscovered.h>\r
de8373fa 19#include <Ppi/IoMmu.h>\r
2cb6eabe
EL
20#include "DebugCommunicationLibUsb3Internal.h"\r
21\r
de8373fa
SZ
22GUID gUsb3DbgGuid = USB3_DBG_GUID;\r
23\r
24/**\r
25 USB3 IOMMU PPI notify.\r
26\r
27 @param[in] PeiServices Pointer to PEI Services Table.\r
28 @param[in] NotifyDesc Pointer to the descriptor for the Notification event that\r
29 caused this function to execute.\r
30 @param[in] Ppi Pointer to the PPI data associated with this function.\r
31\r
32 @retval EFI_STATUS Always return EFI_SUCCESS\r
33**/\r
34EFI_STATUS\r
35EFIAPI\r
36Usb3IoMmuPpiNotify (\r
37 IN EFI_PEI_SERVICES **PeiServices,\r
38 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc,\r
39 IN VOID *Ppi\r
40 )\r
41{\r
42 USB3_DEBUG_PORT_HANDLE *Instance;\r
43\r
44 DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));\r
45\r
46 Instance = GetUsb3DebugPortInstance ();\r
47 ASSERT (Instance != NULL);\r
48\r
49 Instance->InNotify = TRUE;\r
50\r
51 //\r
52 // Reinitialize USB3 debug port with granted DMA buffer from IOMMU PPI.\r
53 //\r
54 InitializeUsbDebugHardware (Instance);\r
55\r
56 //\r
57 // Wait some time for host to be ready after re-initialization.\r
58 //\r
59 MicroSecondDelay (1000000);\r
60\r
61 Instance->InNotify = FALSE;\r
62\r
63 return EFI_SUCCESS;\r
64}\r
65\r
66EFI_PEI_NOTIFY_DESCRIPTOR mUsb3IoMmuPpiNotifyDesc = {\r
67 (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
68 &gEdkiiIoMmuPpiGuid,\r
69 Usb3IoMmuPpiNotify\r
70};\r
71\r
72/**\r
73 Allocates pages that are suitable for an OperationBusMasterCommonBuffer or\r
74 OperationBusMasterCommonBuffer64 mapping.\r
75\r
76 @param IoMmu Pointer to IOMMU PPI.\r
77 @param Pages The number of pages to allocate.\r
78 @param HostAddress A pointer to store the base system memory address of the\r
79 allocated range.\r
80 @param DeviceAddress The resulting map address for the bus master PCI controller to use to\r
81 access the hosts HostAddress.\r
82 @param Mapping A resulting value to pass to Unmap().\r
83\r
84 @retval EFI_SUCCESS The requested memory pages were allocated.\r
85 @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal attribute bits are\r
86 MEMORY_WRITE_COMBINE and MEMORY_CACHED.\r
87 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
88 @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.\r
89\r
90**/\r
91EFI_STATUS\r
92IoMmuAllocateBuffer (\r
93 IN EDKII_IOMMU_PPI *IoMmu,\r
94 IN UINTN Pages,\r
95 OUT VOID **HostAddress,\r
96 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,\r
97 OUT VOID **Mapping\r
98 )\r
99{\r
100 EFI_STATUS Status;\r
101 UINTN NumberOfBytes;\r
102\r
103 *HostAddress = NULL;\r
104 *DeviceAddress = 0;\r
105 *Mapping = NULL;\r
106\r
107 Status = IoMmu->AllocateBuffer (\r
108 IoMmu,\r
109 EfiBootServicesData,\r
110 Pages,\r
111 HostAddress,\r
112 0\r
113 );\r
114 if (EFI_ERROR (Status)) {\r
115 return EFI_OUT_OF_RESOURCES;\r
116 }\r
117\r
118 NumberOfBytes = EFI_PAGES_TO_SIZE (Pages);\r
119 Status = IoMmu->Map (\r
120 IoMmu,\r
121 EdkiiIoMmuOperationBusMasterCommonBuffer,\r
122 *HostAddress,\r
123 &NumberOfBytes,\r
124 DeviceAddress,\r
125 Mapping\r
126 );\r
127 if (EFI_ERROR (Status)) {\r
128 IoMmu->FreeBuffer (IoMmu, Pages, *HostAddress);\r
129 *HostAddress = NULL;\r
130 return EFI_OUT_OF_RESOURCES;\r
131 }\r
132 Status = IoMmu->SetAttribute (\r
133 IoMmu,\r
134 *Mapping,\r
135 EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE\r
136 );\r
137 if (EFI_ERROR (Status)) {\r
138 IoMmu->Unmap (IoMmu, *Mapping);\r
139 IoMmu->FreeBuffer (IoMmu, Pages, *HostAddress);\r
140 *Mapping = NULL;\r
141 *HostAddress = NULL;\r
142 return Status;\r
143 }\r
144\r
145 return Status;\r
146}\r
147\r
148/**\r
149 USB3 get IOMMU PPI.\r
150\r
151 @return Pointer to IOMMU PPI.\r
152\r
153**/\r
154EDKII_IOMMU_PPI *\r
155Usb3GetIoMmu (\r
156 VOID\r
157 )\r
158{\r
159 EFI_STATUS Status;\r
160 EDKII_IOMMU_PPI *IoMmu;\r
161\r
162 IoMmu = NULL;\r
163 Status = PeiServicesLocatePpi (\r
164 &gEdkiiIoMmuPpiGuid,\r
165 0,\r
166 NULL,\r
167 (VOID **) &IoMmu\r
168 );\r
169 if (!EFI_ERROR (Status) && (IoMmu != NULL)) {\r
170 return IoMmu;\r
171 }\r
172\r
173 return NULL;\r
174}\r
175\r
176/**\r
177 Return USB3 debug instance address.\r
178\r
179**/ \r
180USB3_DEBUG_PORT_HANDLE *\r
181GetUsb3DebugPortInstance (\r
182 VOID\r
183 )\r
184{\r
185 USB3_DEBUG_PORT_HANDLE *Instance;\r
186 EFI_PEI_HOB_POINTERS Hob;\r
187 EFI_STATUS Status;\r
188\r
189 Hob.Raw = GetFirstGuidHob (&gUsb3DbgGuid);\r
190 if (Hob.Raw == NULL) {\r
191 //\r
192 // Save Instance into HOB\r
193 //\r
194 Instance = BuildGuidHob (\r
195 &gUsb3DbgGuid,\r
196 sizeof (USB3_DEBUG_PORT_HANDLE)\r
197 );\r
198 ASSERT (Instance != NULL);\r
199 ZeroMem (Instance, sizeof (USB3_DEBUG_PORT_HANDLE));\r
200\r
201 Instance->FromHob = TRUE;\r
202 Instance->Initialized = USB3DBG_UNINITIALIZED;\r
203 } else {\r
204 Instance = GET_GUID_HOB_DATA (Hob.Guid);\r
205 }\r
206\r
207 if (!Instance->InNotify) {\r
208 DiscoverInitializeUsbDebugPort (Instance);\r
209 }\r
210\r
211 if (Instance->Ready &&\r
212 !Instance->PpiNotifyRegistered &&\r
213 (Usb3GetIoMmu () == NULL)) {\r
214 Status = PeiServicesNotifyPpi (&mUsb3IoMmuPpiNotifyDesc);\r
215 ASSERT_EFI_ERROR (Status);\r
216 Instance->PpiNotifyRegistered = TRUE;\r
217 }\r
218\r
219 return Instance;\r
220}\r
221\r
2cb6eabe
EL
222/**\r
223 Allocate aligned memory for XHC's usage.\r
224\r
de8373fa 225 @param BufferSize The size, in bytes, of the Buffer.\r
2cb6eabe
EL
226 \r
227 @return A pointer to the allocated buffer or NULL if allocation fails.\r
228\r
229**/\r
230VOID*\r
231AllocateAlignBuffer (\r
232 IN UINTN BufferSize\r
233 )\r
234{\r
235 VOID *Buf;\r
236 EFI_PHYSICAL_ADDRESS Address;\r
237 EFI_STATUS Status;\r
364f63c0 238 VOID *MemoryDiscoveredPpi;\r
de8373fa
SZ
239 EDKII_IOMMU_PPI *IoMmu;\r
240 VOID *HostAddress;\r
241 VOID *Mapping;\r
364f63c0
SZ
242\r
243 Buf = NULL;\r
244\r
245 //\r
246 // Make sure the allocated memory is physical memory.\r
247 //\r
248 Status = PeiServicesLocatePpi (\r
249 &gEfiPeiMemoryDiscoveredPpiGuid,\r
250 0,\r
251 NULL,\r
252 (VOID **) &MemoryDiscoveredPpi\r
253 );\r
254 if (!EFI_ERROR (Status)) {\r
de8373fa
SZ
255 IoMmu = Usb3GetIoMmu ();\r
256 if (IoMmu != NULL) {\r
257 Status = IoMmuAllocateBuffer (\r
258 IoMmu,\r
259 EFI_SIZE_TO_PAGES (BufferSize),\r
260 &HostAddress,\r
261 &Address,\r
262 &Mapping\r
263 );\r
264 if (!EFI_ERROR (Status)) {\r
265 ASSERT (Address == ((EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress));\r
266 Buf = (VOID *)(UINTN) Address;\r
267 }\r
268 } else {\r
269 Status = PeiServicesAllocatePages (\r
270 EfiACPIMemoryNVS,\r
271 EFI_SIZE_TO_PAGES (BufferSize),\r
272 &Address\r
273 );\r
274 if (!EFI_ERROR (Status)) {\r
275 Buf = (VOID *)(UINTN) Address;\r
276 }\r
364f63c0 277 }\r
2cb6eabe
EL
278 }\r
279 return Buf;\r
280}\r
281\r