]> git.proxmox.com Git - mirror_edk2.git/blame - SourceLevelDebugPkg/Library/DebugCommunicationLibUsb3/DebugCommunicationLibUsb3Pei.c
SourceLevelDebugPkg DebugUsb3: Re-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
75787f65 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
75787f65 17#include <Library/HobLib.h>\r
364f63c0 18#include <Ppi/MemoryDiscovered.h>\r
75787f65 19#include <Ppi/IoMmu.h>\r
2cb6eabe
EL
20#include "DebugCommunicationLibUsb3Internal.h"\r
21\r
75787f65
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 if (!Instance->Ready) {\r
49 return EFI_SUCCESS;\r
50 }\r
51\r
52 Instance->InNotify = TRUE;\r
53\r
54 //\r
55 // Reinitialize USB3 debug port with granted DMA buffer from IOMMU PPI.\r
56 //\r
57 InitializeUsbDebugHardware (Instance);\r
58\r
59 //\r
60 // Wait some time for host to be ready after re-initialization.\r
61 //\r
62 MicroSecondDelay (1000000);\r
63\r
64 Instance->InNotify = FALSE;\r
65\r
66 return EFI_SUCCESS;\r
67}\r
68\r
69EFI_PEI_NOTIFY_DESCRIPTOR mUsb3IoMmuPpiNotifyDesc = {\r
70 (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
71 &gEdkiiIoMmuPpiGuid,\r
72 Usb3IoMmuPpiNotify\r
73};\r
74\r
75/**\r
76 Allocates pages that are suitable for an OperationBusMasterCommonBuffer or\r
77 OperationBusMasterCommonBuffer64 mapping.\r
78\r
79 @param IoMmu Pointer to IOMMU PPI.\r
80 @param Pages The number of pages to allocate.\r
81 @param HostAddress A pointer to store the base system memory address of the\r
82 allocated range.\r
83 @param DeviceAddress The resulting map address for the bus master PCI controller to use to\r
84 access the hosts HostAddress.\r
85 @param Mapping A resulting value to pass to Unmap().\r
86\r
87 @retval EFI_SUCCESS The requested memory pages were allocated.\r
88 @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal attribute bits are\r
89 MEMORY_WRITE_COMBINE and MEMORY_CACHED.\r
90 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
91 @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.\r
92\r
93**/\r
94EFI_STATUS\r
95IoMmuAllocateBuffer (\r
96 IN EDKII_IOMMU_PPI *IoMmu,\r
97 IN UINTN Pages,\r
98 OUT VOID **HostAddress,\r
99 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,\r
100 OUT VOID **Mapping\r
101 )\r
102{\r
103 EFI_STATUS Status;\r
104 UINTN NumberOfBytes;\r
105\r
106 *HostAddress = NULL;\r
107 *DeviceAddress = 0;\r
108 *Mapping = NULL;\r
109\r
110 Status = IoMmu->AllocateBuffer (\r
111 IoMmu,\r
112 EfiRuntimeServicesData,\r
113 Pages,\r
114 HostAddress,\r
115 0\r
116 );\r
117 if (EFI_ERROR (Status)) {\r
118 return EFI_OUT_OF_RESOURCES;\r
119 }\r
120\r
121 NumberOfBytes = EFI_PAGES_TO_SIZE (Pages);\r
122 Status = IoMmu->Map (\r
123 IoMmu,\r
124 EdkiiIoMmuOperationBusMasterCommonBuffer,\r
125 *HostAddress,\r
126 &NumberOfBytes,\r
127 DeviceAddress,\r
128 Mapping\r
129 );\r
130 if (EFI_ERROR (Status)) {\r
131 IoMmu->FreeBuffer (IoMmu, Pages, *HostAddress);\r
132 *HostAddress = NULL;\r
133 return EFI_OUT_OF_RESOURCES;\r
134 }\r
135 Status = IoMmu->SetAttribute (\r
136 IoMmu,\r
137 *Mapping,\r
138 EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE\r
139 );\r
140 if (EFI_ERROR (Status)) {\r
141 IoMmu->Unmap (IoMmu, *Mapping);\r
142 IoMmu->FreeBuffer (IoMmu, Pages, *HostAddress);\r
143 *Mapping = NULL;\r
144 *HostAddress = NULL;\r
145 return Status;\r
146 }\r
147\r
148 return Status;\r
149}\r
150\r
151/**\r
152 USB3 get IOMMU PPI.\r
153\r
154 @return Pointer to IOMMU PPI.\r
155\r
156**/\r
157EDKII_IOMMU_PPI *\r
158Usb3GetIoMmu (\r
159 VOID\r
160 )\r
161{\r
162 EFI_STATUS Status;\r
163 EDKII_IOMMU_PPI *IoMmu;\r
164\r
165 IoMmu = NULL;\r
166 Status = PeiServicesLocatePpi (\r
167 &gEdkiiIoMmuPpiGuid,\r
168 0,\r
169 NULL,\r
170 (VOID **) &IoMmu\r
171 );\r
172 if (!EFI_ERROR (Status) && (IoMmu != NULL)) {\r
173 return IoMmu;\r
174 }\r
175\r
176 return NULL;\r
177}\r
178\r
179/**\r
180 Return USB3 debug instance address pointer.\r
181\r
182**/ \r
183EFI_PHYSICAL_ADDRESS *\r
184GetUsb3DebugPortInstanceAddrPtr (\r
185 VOID\r
186 )\r
187{\r
188 USB3_DEBUG_PORT_HANDLE *Instance;\r
189 EFI_PHYSICAL_ADDRESS *AddrPtr;\r
190 EFI_PEI_HOB_POINTERS Hob;\r
191 EFI_STATUS Status;\r
192\r
193 Hob.Raw = GetFirstGuidHob (&gUsb3DbgGuid);\r
194 if (Hob.Raw == NULL) {\r
195 //\r
196 // Build HOB for the local instance and the buffer to save instance address pointer.\r
197 // Use the local instance in HOB temporarily.\r
198 //\r
199 AddrPtr = BuildGuidHob (\r
200 &gUsb3DbgGuid,\r
201 sizeof (EFI_PHYSICAL_ADDRESS) + sizeof (USB3_DEBUG_PORT_HANDLE)\r
202 );\r
203 ASSERT (AddrPtr != NULL);\r
204 ZeroMem (AddrPtr, sizeof (EFI_PHYSICAL_ADDRESS) + sizeof (USB3_DEBUG_PORT_HANDLE));\r
205 Instance = (USB3_DEBUG_PORT_HANDLE *) (AddrPtr + 1);\r
206 *AddrPtr = (EFI_PHYSICAL_ADDRESS) (UINTN) Instance;\r
207 Instance->FromHob = TRUE;\r
208 Instance->Initialized = USB3DBG_UNINITIALIZED;\r
209 if (Usb3GetIoMmu () == NULL) {\r
210 Status = PeiServicesNotifyPpi (&mUsb3IoMmuPpiNotifyDesc);\r
211 ASSERT_EFI_ERROR (Status);\r
212 }\r
213 } else {\r
214 AddrPtr = GET_GUID_HOB_DATA (Hob.Guid);\r
215 }\r
216\r
217 return AddrPtr;\r
218}\r
219\r
2cb6eabe
EL
220/**\r
221 Allocate aligned memory for XHC's usage.\r
222\r
75787f65 223 @param BufferSize The size, in bytes, of the Buffer.\r
2cb6eabe
EL
224 \r
225 @return A pointer to the allocated buffer or NULL if allocation fails.\r
226\r
227**/\r
228VOID*\r
229AllocateAlignBuffer (\r
230 IN UINTN BufferSize\r
231 )\r
232{\r
233 VOID *Buf;\r
234 EFI_PHYSICAL_ADDRESS Address;\r
235 EFI_STATUS Status;\r
364f63c0 236 VOID *MemoryDiscoveredPpi;\r
75787f65
SZ
237 EDKII_IOMMU_PPI *IoMmu;\r
238 VOID *HostAddress;\r
239 VOID *Mapping;\r
364f63c0
SZ
240\r
241 Buf = NULL;\r
242\r
243 //\r
244 // Make sure the allocated memory is physical memory.\r
245 //\r
246 Status = PeiServicesLocatePpi (\r
247 &gEfiPeiMemoryDiscoveredPpiGuid,\r
248 0,\r
249 NULL,\r
250 (VOID **) &MemoryDiscoveredPpi\r
251 );\r
252 if (!EFI_ERROR (Status)) {\r
75787f65
SZ
253 IoMmu = Usb3GetIoMmu ();\r
254 if (IoMmu != NULL) {\r
255 Status = IoMmuAllocateBuffer (\r
256 IoMmu,\r
257 EFI_SIZE_TO_PAGES (BufferSize),\r
258 &HostAddress,\r
259 &Address,\r
260 &Mapping\r
261 );\r
262 if (!EFI_ERROR (Status)) {\r
263 ASSERT (Address == ((EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress));\r
264 Buf = (VOID *)(UINTN) Address;\r
265 }\r
266 } else {\r
267 Status = PeiServicesAllocatePages (\r
268 EfiACPIMemoryNVS,\r
269 EFI_SIZE_TO_PAGES (BufferSize),\r
270 &Address\r
271 );\r
272 if (!EFI_ERROR (Status)) {\r
273 Buf = (VOID *)(UINTN) Address;\r
274 }\r
364f63c0 275 }\r
2cb6eabe
EL
276 }\r
277 return Buf;\r
278}\r
279\r