TianoCore EDK2 master
Loading...
Searching...
No Matches
DebugCommunicationLibUsb3Dxe.c
Go to the documentation of this file.
1
9#include <Base.h>
10#include <PiDxe.h>
12#include <Library/HobLib.h>
13#include <Protocol/PciIo.h>
14#include <Protocol/IoMmu.h>
17
18GUID gUsb3DbgGuid = USB3_DBG_GUID;
19
20USB3_DEBUG_PORT_HANDLE mUsb3Instance = { USB3DBG_UNINITIALIZED };
21EFI_PHYSICAL_ADDRESS mUsb3InstanceAddr = 0;
22EFI_PHYSICAL_ADDRESS *mUsb3InstanceAddrPtr = NULL;
23EFI_PCI_IO_PROTOCOL *mUsb3PciIo = NULL;
24
43EFIAPI
45 IN CONST EFI_GUID *Name,
46 IN EFI_TPL NotifyTpl,
48 IN EFI_EVENT *Event
49 )
50{
51 EFI_STATUS Status;
52 VOID *RegistrationLocal;
53
54 ASSERT (Name != NULL);
55 ASSERT (NotifyFunction != NULL);
56 ASSERT (NotifyTpl <= TPL_HIGH_LEVEL);
57
58 //
59 // Create event
60 //
61 Status = gBS->CreateEvent (
62 EVT_NOTIFY_SIGNAL,
63 NotifyTpl,
65 NULL,
66 Event
67 );
68 ASSERT_EFI_ERROR (Status);
69
70 //
71 // Register for an installation of protocol interface
72 //
73 Status = gBS->RegisterProtocolNotify (
74 (EFI_GUID *)Name,
75 *Event,
76 &RegistrationLocal
77 );
78 ASSERT_EFI_ERROR (Status);
79
80 return Status;
81}
82
91VOID
95 IN UINTN NumberOfBytes
96 )
97{
98 EFI_STATUS Status;
99 VOID *HostAddress;
100 EFI_PHYSICAL_ADDRESS DeviceAddress;
101 VOID *Mapping;
102
103 HostAddress = (VOID *)(UINTN)Address;
104 Status = PciIo->Map (
105 PciIo,
107 HostAddress,
108 &NumberOfBytes,
109 &DeviceAddress,
110 &Mapping
111 );
112 ASSERT_EFI_ERROR (Status);
113 ASSERT (DeviceAddress == ((EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress));
114}
115
123VOID
125 IN USB3_DEBUG_PORT_HANDLE *Instance,
127 )
128{
130 PciIo,
131 Instance->UrbIn.Data,
132 XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE * 2 + USB3_DEBUG_PORT_WRITE_MAX_PACKET_SIZE
133 );
134
136 PciIo,
137 Instance->TransferRingIn.RingSeg0,
138 sizeof (TRB_TEMPLATE) * TR_RING_TRB_NUMBER
139 );
140
142 PciIo,
143 Instance->TransferRingOut.RingSeg0,
144 sizeof (TRB_TEMPLATE) * TR_RING_TRB_NUMBER
145 );
146
148 PciIo,
149 Instance->EventRing.EventRingSeg0,
150 sizeof (TRB_TEMPLATE) * EVENT_RING_TRB_NUMBER
151 );
152
154 PciIo,
155 Instance->EventRing.ERSTBase,
156 sizeof (EVENT_RING_SEG_TABLE_ENTRY) * ERST_NUMBER
157 );
158
160 PciIo,
161 Instance->DebugCapabilityContext,
162 sizeof (XHC_DC_CONTEXT)
163 );
164
166 PciIo,
167 ((XHC_DC_CONTEXT *)(UINTN)Instance->DebugCapabilityContext)->DbcInfoContext.String0DescAddress,
168 STRING0_DESC_LEN + MANU_DESC_LEN + PRODUCT_DESC_LEN + SERIAL_DESC_LEN
169 );
170}
171
180VOID
181EFIAPI
183 IN EFI_EVENT Event,
184 IN VOID *Context
185 )
186{
187 USB3_DEBUG_PORT_HANDLE *Instance;
188
189 DEBUG ((DEBUG_INFO, "%a()\n", __func__));
190
191 Instance = GetUsb3DebugPortInstance ();
192 ASSERT (Instance != NULL);
193
194 Instance->InNotify = TRUE;
195
196 //
197 // For the case that the USB3 debug port instance and DMA buffers are
198 // from PEI HOB with IOMMU enabled.
199 // Reinitialize USB3 debug port with granted DXE DMA buffer accessible
200 // by SMM environment.
201 //
203
204 //
205 // Wait some time for host to be ready after re-initialization.
206 //
207 MicroSecondDelay (1000000);
208
209 Instance->InNotify = FALSE;
210 gBS->CloseEvent (Event);
211}
212
221 VOID
222 )
223{
224 EFI_STATUS Status;
226
227 IoMmu = NULL;
228 Status = gBS->LocateProtocol (
230 NULL,
231 (VOID **)&IoMmu
232 );
233 if (!EFI_ERROR (Status) && (IoMmu != NULL)) {
234 return IoMmu;
235 }
236
237 return NULL;
238}
239
248VOID
249EFIAPI
251 IN EFI_EVENT Event,
252 IN VOID *Context
253 )
254{
255 EFI_STATUS Status;
256 UINTN PciIoHandleCount;
257 EFI_HANDLE *PciIoHandleBuffer;
258 UINTN Index;
259 EFI_PCI_IO_PROTOCOL *PciIo;
260 UINTN PciSegment;
261 UINTN PciBusNumber;
262 UINTN PciDeviceNumber;
263 UINTN PciFunctionNumber;
264 UINT32 PciAddress;
265 USB3_DEBUG_PORT_HANDLE *Instance;
266 EFI_EVENT SmmReadyToLockEvent;
267
268 Status = gBS->LocateHandleBuffer (
270 &gEfiPciIoProtocolGuid,
271 NULL,
272 &PciIoHandleCount,
273 &PciIoHandleBuffer
274 );
275 if (!EFI_ERROR (Status) &&
276 (PciIoHandleBuffer != NULL) &&
277 (PciIoHandleCount != 0))
278 {
279 for (Index = 0; Index < PciIoHandleCount; Index++) {
280 Status = gBS->HandleProtocol (
281 PciIoHandleBuffer[Index],
282 &gEfiPciIoProtocolGuid,
283 (VOID **)&PciIo
284 );
285 ASSERT_EFI_ERROR (Status);
286 Status = PciIo->GetLocation (PciIo, &PciSegment, &PciBusNumber, &PciDeviceNumber, &PciFunctionNumber);
287 ASSERT_EFI_ERROR (Status);
288 PciAddress = (UINT32)((PciBusNumber << 20) | (PciDeviceNumber << 15) | (PciFunctionNumber << 12));
289 if (PciAddress == PcdGet32 (PcdUsbXhciPciAddress)) {
290 //
291 // Found the PciIo for USB3 debug port.
292 //
293 DEBUG ((DEBUG_INFO, "%a()\n", __func__));
294 if (Usb3GetIoMmu () != NULL) {
295 Instance = GetUsb3DebugPortInstance ();
296 ASSERT (Instance != NULL);
297 if (Instance->Ready) {
298 Instance->InNotify = TRUE;
299 Usb3MapDmaBuffers (Instance, PciIo);
300 Instance->InNotify = FALSE;
301
302 if (Instance->FromHob) {
303 mUsb3PciIo = PciIo;
305 &gEfiDxeSmmReadyToLockProtocolGuid,
306 TPL_NOTIFY,
308 &SmmReadyToLockEvent
309 );
310 }
311 }
312 }
313
314 gBS->CloseEvent (Event);
315 break;
316 }
317 }
318
319 gBS->FreePool (PciIoHandleBuffer);
320 }
321}
322
329 VOID
330 )
331{
332 if (mUsb3InstanceAddrPtr == NULL) {
333 //
334 // Use the local variables temporarily.
335 //
336 mUsb3InstanceAddr = (EFI_PHYSICAL_ADDRESS)(UINTN)&mUsb3Instance;
337 mUsb3InstanceAddrPtr = &mUsb3InstanceAddr;
338 }
339
340 return mUsb3InstanceAddrPtr;
341}
342
361 IN EFI_PCI_IO_PROTOCOL *PciIo,
362 IN UINTN Pages,
363 OUT VOID **Address
364 )
365{
366 EFI_STATUS Status;
367
368 *Address = NULL;
369 Status = PciIo->AllocateBuffer (
370 PciIo,
373 Pages,
374 Address,
375 0
376 );
377 if (!EFI_ERROR (Status)) {
379 PciIo,
380 (EFI_PHYSICAL_ADDRESS)(UINTN)*Address,
381 EFI_PAGES_TO_SIZE (Pages)
382 );
383 }
384
385 return Status;
386}
387
396VOID *
398 IN UINTN BufferSize
399 )
400{
401 EFI_PHYSICAL_ADDRESS TmpAddr;
402 EFI_STATUS Status;
403 VOID *Buf;
404
405 Buf = NULL;
406
407 if (gBS != NULL) {
408 if (mUsb3PciIo != NULL) {
410 mUsb3PciIo,
411 EFI_SIZE_TO_PAGES (BufferSize),
412 &Buf
413 );
414 } else {
415 TmpAddr = 0xFFFFFFFF;
416 Status = gBS->AllocatePages (
419 EFI_SIZE_TO_PAGES (BufferSize),
420 &TmpAddr
421 );
422 if (!EFI_ERROR (Status)) {
423 Buf = (VOID *)(UINTN)TmpAddr;
424 }
425 }
426 }
427
428 return Buf;
429}
430
441EFIAPI
443 IN EFI_HANDLE ImageHandle,
444 IN EFI_SYSTEM_TABLE *SystemTable
445 )
446{
447 EFI_PHYSICAL_ADDRESS *AddrPtr;
448 USB3_DEBUG_PORT_HANDLE *Instance;
449 EFI_PHYSICAL_ADDRESS Address;
450 EFI_STATUS Status;
451 EFI_EVENT Event;
452
453 Status = EfiGetSystemConfigurationTable (&gUsb3DbgGuid, (VOID **)&AddrPtr);
454 if (EFI_ERROR (Status) || (AddrPtr == NULL)) {
455 //
456 // Instead of using local variables, install system configuration table for
457 // the local instance and the buffer to save instance address pointer.
458 //
459 Address = SIZE_4GB;
460 Status = gBS->AllocatePages (
464 &Address
465 );
466 if (EFI_ERROR (Status)) {
467 return Status;
468 }
469
470 AddrPtr = (EFI_PHYSICAL_ADDRESS *)(UINTN)Address;
471 ZeroMem (AddrPtr, sizeof (EFI_PHYSICAL_ADDRESS) + sizeof (USB3_DEBUG_PORT_HANDLE));
472 Instance = (USB3_DEBUG_PORT_HANDLE *)(AddrPtr + 1);
473 CopyMem (Instance, &mUsb3Instance, sizeof (USB3_DEBUG_PORT_HANDLE));
474 *AddrPtr = (EFI_PHYSICAL_ADDRESS)(UINTN)Instance;
475
476 Status = gBS->InstallConfigurationTable (&gUsb3DbgGuid, AddrPtr);
477 if (EFI_ERROR (Status)) {
478 return Status;
479 }
480 }
481
482 if (mUsb3InstanceAddrPtr != NULL) {
483 *AddrPtr = *mUsb3InstanceAddrPtr;
484 }
485
486 mUsb3InstanceAddrPtr = AddrPtr;
487
488 Instance = GetUsb3DebugPortInstance ();
489 ASSERT (Instance != NULL);
490
491 if (Instance->PciIoEvent == 0) {
492 Status = Usb3NamedEventListen (
493 &gEfiPciIoProtocolGuid,
494 TPL_NOTIFY,
496 &Event
497 );
498 if (!EFI_ERROR (Status)) {
499 Instance->PciIoEvent = (EFI_PHYSICAL_ADDRESS)(UINTN)Event;
500 }
501 }
502
503 return EFI_SUCCESS;
504}
505
516EFIAPI
518 IN EFI_HANDLE ImageHandle,
519 IN EFI_SYSTEM_TABLE *SystemTable
520 )
521{
522 USB3_DEBUG_PORT_HANDLE *Instance;
523
524 Instance = GetUsb3DebugPortInstance ();
525 ASSERT (Instance != NULL);
526
527 if (Instance->PciIoEvent != 0) {
528 //
529 // Close the event created.
530 //
531 gBS->CloseEvent ((EFI_EVENT)(UINTN)Instance->PciIoEvent);
532 Instance->PciIoEvent = 0;
533 }
534
535 return EFI_SUCCESS;
536}
UINT64 UINTN
UINTN EFIAPI MicroSecondDelay(IN UINTN MicroSeconds)
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
USB3_DEBUG_PORT_HANDLE * GetUsb3DebugPortInstance(VOID)
VOID Usb3MapDmaBuffers(IN USB3_DEBUG_PORT_HANDLE *Instance, IN EFI_PCI_IO_PROTOCOL *PciIo)
VOID * AllocateAlignBuffer(IN UINTN BufferSize)
EDKII_IOMMU_PROTOCOL * Usb3GetIoMmu(VOID)
EFI_PHYSICAL_ADDRESS * GetUsb3DebugPortInstanceAddrPtr(VOID)
VOID Usb3MapOneDmaBuffer(IN EFI_PCI_IO_PROTOCOL *PciIo, IN EFI_PHYSICAL_ADDRESS Address, IN UINTN NumberOfBytes)
VOID EFIAPI Usb3PciIoNotify(IN EFI_EVENT Event, IN VOID *Context)
EFI_STATUS Usb3AllocateDmaBuffer(IN EFI_PCI_IO_PROTOCOL *PciIo, IN UINTN Pages, OUT VOID **Address)
VOID EFIAPI Usb3DxeSmmReadyToLockNotify(IN EFI_EVENT Event, IN VOID *Context)
EFI_STATUS EFIAPI Usb3NamedEventListen(IN CONST EFI_GUID *Name, IN EFI_TPL NotifyTpl, IN EFI_EVENT_NOTIFY NotifyFunction, IN EFI_EVENT *Event)
EFI_STATUS EFIAPI DebugCommunicationUsb3DxeConstructor(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
EFI_STATUS EFIAPI DebugCommunicationUsb3DxeDestructor(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
RETURN_STATUS EFIAPI InitializeUsbDebugHardware(IN USB_DEBUG_PORT_HANDLE *Handle)
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
#define DEBUG(Expression)
Definition: DebugLib.h:434
@ EfiPciIoOperationBusMasterCommonBuffer
Definition: PciIo.h:90
#define PcdGet32(TokenName)
Definition: PcdLib.h:362
EFI_GUID gEdkiiIoMmuProtocolGuid
VOID EFIAPI NotifyFunction(IN EFI_EVENT Event, IN VOID *Context)
Definition: ScsiBus.c:1492
UINT64 EFI_PHYSICAL_ADDRESS
Definition: UefiBaseType.h:50
#define EFI_PAGES_TO_SIZE(Pages)
Definition: UefiBaseType.h:213
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_EVENT
Definition: UefiBaseType.h:37
UINTN EFI_TPL
Definition: UefiBaseType.h:41
#define EFI_SIZE_TO_PAGES(Size)
Definition: UefiBaseType.h:200
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS
EFI_STATUS EFIAPI EfiGetSystemConfigurationTable(IN EFI_GUID *TableGuid, OUT VOID **Table)
Definition: UefiLib.c:82
@ EfiACPIMemoryNVS
@ EfiRuntimeServicesData
VOID(EFIAPI * EFI_EVENT_NOTIFY)(IN EFI_EVENT Event, IN VOID *Context)
Definition: UefiSpec.h:463
@ ByProtocol
Definition: UefiSpec.h:1518
@ AllocateMaxAddress
Definition: UefiSpec.h:38
@ AllocateAnyPages
Definition: UefiSpec.h:33
Definition: Base.h:213