2 Debug Port Library implementation based on usb3 debug port.
4 Copyright (c) 2014 - 2018, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php.
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 #include <Library/UefiBootServicesTableLib.h>
18 #include <Library/HobLib.h>
19 #include <Protocol/PciIo.h>
20 #include <Protocol/IoMmu.h>
21 #include "DebugCommunicationLibUsb3Internal.h"
23 GUID gUsb3DbgGuid
= USB3_DBG_GUID
;
25 USB3_DEBUG_PORT_HANDLE
*mUsb3Instance
= NULL
;
28 Creates a named event that can be signaled.
30 This function creates an event using NotifyTpl, NoifyFunction.
31 If Name is NULL, then ASSERT().
32 If NotifyTpl is not a legal TPL value, then ASSERT().
33 If NotifyFunction is NULL, then ASSERT().
35 @param Name Supplies the GUID name of the event.
36 @param NotifyTpl Supplies the task priority level of the event notifications.
37 @param NotifyFunction Supplies the function to notify when the event is signaled.
38 @param Event A pointer to the event created.
40 @retval EFI_SUCCESS A named event was created.
41 @retval EFI_OUT_OF_RESOURCES There are not enough resource to create the named event.
46 Usb3NamedEventListen (
47 IN CONST EFI_GUID
*Name
,
49 IN EFI_EVENT_NOTIFY NotifyFunction
,
54 VOID
*RegistrationLocal
;
56 ASSERT (Name
!= NULL
);
57 ASSERT (NotifyFunction
!= NULL
);
58 ASSERT (NotifyTpl
<= TPL_HIGH_LEVEL
);
63 Status
= gBS
->CreateEvent (
70 ASSERT_EFI_ERROR (Status
);
73 // Register for an installation of protocol interface
75 Status
= gBS
->RegisterProtocolNotify (
80 ASSERT_EFI_ERROR (Status
);
86 USB3 map one DMA buffer.
88 @param Instance Pointer to USB3 debug port instance.
89 @param PciIo Pointer to PciIo for USB3 debug port.
90 @param Address DMA buffer address to be mapped.
91 @param NumberOfBytes Number of bytes to be mapped.
92 @param BackupBuffer Backup buffer address.
97 IN USB3_DEBUG_PORT_HANDLE
*Instance
,
98 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
99 IN EFI_PHYSICAL_ADDRESS Address
,
100 IN UINTN NumberOfBytes
,
101 IN EFI_PHYSICAL_ADDRESS BackupBuffer
106 EFI_PHYSICAL_ADDRESS DeviceAddress
;
109 HostAddress
= (VOID
*) (UINTN
) Address
;
110 Status
= PciIo
->Map (
112 EfiPciIoOperationBusMasterCommonBuffer
,
118 ASSERT_EFI_ERROR (Status
);
119 ASSERT (DeviceAddress
== ((EFI_PHYSICAL_ADDRESS
) (UINTN
) HostAddress
));
120 if (Instance
->FromHob
) {
122 // Reallocate the DMA buffer by AllocateAddress with
123 // the memory type accessible by SMM.
125 CopyMem ((VOID
*) (UINTN
) BackupBuffer
, (VOID
*) (UINTN
) Address
, NumberOfBytes
);
126 Status
= gBS
->FreePages (Address
, EFI_SIZE_TO_PAGES (NumberOfBytes
));
127 ASSERT_EFI_ERROR (Status
);
128 Status
= gBS
->AllocatePages (
131 EFI_SIZE_TO_PAGES (NumberOfBytes
),
134 ASSERT_EFI_ERROR (Status
);
135 CopyMem ((VOID
*) (UINTN
) Address
, (VOID
*) (UINTN
) BackupBuffer
, NumberOfBytes
);
140 USB3 map DMA buffers.
142 @param Instance Pointer to USB3 debug port instance.
143 @param PciIo Pointer to PciIo for USB3 debug port.
148 IN USB3_DEBUG_PORT_HANDLE
*Instance
,
149 IN EFI_PCI_IO_PROTOCOL
*PciIo
153 EDKII_IOMMU_PROTOCOL
*IoMmu
;
154 EFI_PHYSICAL_ADDRESS BackupBuffer
;
155 UINTN BackupBufferSize
;
158 Status
= gBS
->LocateProtocol (&gEdkiiIoMmuProtocolGuid
, NULL
, (VOID
**) &IoMmu
);
159 if (EFI_ERROR (Status
) || (IoMmu
== NULL
)) {
161 // No need to map the DMA buffers.
167 // Allocate backup buffer for the case that the USB3
168 // debug port instance and DMA buffers are from PEI HOB.
169 // For this case, the DMA buffers need to be reallocated
170 // by AllocateAddress with the memory type accessible by
173 BackupBufferSize
= MAX (XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE
* 2 + USB3_DEBUG_PORT_WRITE_MAX_PACKET_SIZE
,
174 MAX (sizeof (TRB_TEMPLATE
) * TR_RING_TRB_NUMBER
,
175 MAX (sizeof (TRB_TEMPLATE
) * EVENT_RING_TRB_NUMBER
,
176 MAX (sizeof (EVENT_RING_SEG_TABLE_ENTRY
) * ERST_NUMBER
,
177 MAX (sizeof (XHC_DC_CONTEXT
),
178 STRING0_DESC_LEN
+ MANU_DESC_LEN
+ PRODUCT_DESC_LEN
+ SERIAL_DESC_LEN
)))));
180 Status
= gBS
->AllocatePages (
183 EFI_SIZE_TO_PAGES (BackupBufferSize
),
186 ASSERT_EFI_ERROR (Status
);
188 Usb3MapOneDmaBuffer (
191 Instance
->UrbIn
.Data
,
192 XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE
* 2 + USB3_DEBUG_PORT_WRITE_MAX_PACKET_SIZE
,
196 Usb3MapOneDmaBuffer (
199 Instance
->TransferRingIn
.RingSeg0
,
200 sizeof (TRB_TEMPLATE
) * TR_RING_TRB_NUMBER
,
204 Usb3MapOneDmaBuffer (
207 Instance
->TransferRingOut
.RingSeg0
,
208 sizeof (TRB_TEMPLATE
) * TR_RING_TRB_NUMBER
,
212 Usb3MapOneDmaBuffer (
215 Instance
->EventRing
.EventRingSeg0
,
216 sizeof (TRB_TEMPLATE
) * EVENT_RING_TRB_NUMBER
,
220 Usb3MapOneDmaBuffer (
223 Instance
->EventRing
.ERSTBase
,
224 sizeof (EVENT_RING_SEG_TABLE_ENTRY
) * ERST_NUMBER
,
228 Usb3MapOneDmaBuffer (
231 Instance
->DebugCapabilityContext
,
232 sizeof (XHC_DC_CONTEXT
),
236 Usb3MapOneDmaBuffer (
239 ((XHC_DC_CONTEXT
*) (UINTN
) Instance
->DebugCapabilityContext
)->DbcInfoContext
.String0DescAddress
,
240 STRING0_DESC_LEN
+ MANU_DESC_LEN
+ PRODUCT_DESC_LEN
+ SERIAL_DESC_LEN
,
244 gBS
->FreePages (BackupBuffer
, EFI_SIZE_TO_PAGES (BackupBufferSize
));
248 Invoke a notification event
250 @param[in] Event Event whose notification function is being invoked.
251 @param[in] Context The pointer to the notification function's context,
252 which is implementation-dependent.
263 UINTN PciIoHandleCount
;
264 EFI_HANDLE
*PciIoHandleBuffer
;
266 EFI_PCI_IO_PROTOCOL
*PciIo
;
269 UINTN PciDeviceNumber
;
270 UINTN PciFunctionNumber
;
273 ASSERT (mUsb3Instance
!= NULL
);
275 Status
= gBS
->LocateHandleBuffer (
277 &gEfiPciIoProtocolGuid
,
282 if (!EFI_ERROR (Status
) &&
283 (PciIoHandleBuffer
!= NULL
) &&
284 (PciIoHandleCount
!= 0)) {
285 for (Index
= 0; Index
< PciIoHandleCount
; Index
++) {
286 Status
= gBS
->HandleProtocol (
287 PciIoHandleBuffer
[Index
],
288 &gEfiPciIoProtocolGuid
,
291 ASSERT_EFI_ERROR (Status
);
292 Status
= PciIo
->GetLocation (PciIo
, &PciSegment
, &PciBusNumber
, &PciDeviceNumber
, &PciFunctionNumber
);
293 ASSERT_EFI_ERROR (Status
);
294 PciAddress
= (UINT32
) ((PciBusNumber
<< 20) | (PciDeviceNumber
<< 15) | (PciFunctionNumber
<< 12));
295 if (PciAddress
== PcdGet32(PcdUsbXhciPciAddress
)) {
297 // Found the PciIo for USB3 debug port.
299 DEBUG ((DEBUG_INFO
, "%a()\n", __FUNCTION__
));
300 mUsb3Instance
->InNotify
= TRUE
;
301 Usb3MapDmaBuffers (mUsb3Instance
, PciIo
);
302 mUsb3Instance
->InNotify
= FALSE
;
303 gBS
->CloseEvent ((EFI_EVENT
) (UINTN
) mUsb3Instance
->PciIoEvent
);
308 gBS
->FreePool (PciIoHandleBuffer
);
313 Return USB3 debug instance address.
316 USB3_DEBUG_PORT_HANDLE
*
317 GetUsb3DebugPortInstance (
321 USB3_DEBUG_PORT_HANDLE
*Instance
;
322 EFI_PEI_HOB_POINTERS Hob
;
326 if (mUsb3Instance
!= NULL
) {
327 Instance
= mUsb3Instance
;
331 Hob
.Raw
= GetFirstGuidHob (&gUsb3DbgGuid
);
332 if (Hob
.Raw
!= NULL
) {
333 Instance
= GET_GUID_HOB_DATA (Hob
.Guid
);
337 if (Instance
!= NULL
) {
338 DiscoverInitializeUsbDebugPort (Instance
);
344 Allocate aligned memory for XHC's usage.
346 @param BufferSize The size, in bytes, of the Buffer.
348 @return A pointer to the allocated buffer or NULL if allocation fails.
352 AllocateAlignBuffer (
356 EFI_PHYSICAL_ADDRESS TmpAddr
;
363 TmpAddr
= 0xFFFFFFFF;
364 Status
= gBS
->AllocatePages (
367 EFI_SIZE_TO_PAGES (BufferSize
),
370 if (!EFI_ERROR (Status
)) {
371 Buf
= (VOID
*) (UINTN
) TmpAddr
;
379 The constructor function initialize USB3 debug port.
381 @param ImageHandle The firmware allocated handle for the EFI image.
382 @param SystemTable A pointer to the EFI System Table.
384 @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.
389 DebugCommunicationUsb3DxeConstructor (
390 IN EFI_HANDLE ImageHandle
,
391 IN EFI_SYSTEM_TABLE
*SystemTable
394 USB3_DEBUG_PORT_HANDLE UsbDbg
;
395 USB3_DEBUG_PORT_HANDLE
*Instance
;
396 EFI_PHYSICAL_ADDRESS Address
;
400 Instance
= GetUsb3DebugPortInstance ();
402 Status
= EfiGetSystemConfigurationTable (&gUsb3DbgGuid
, (VOID
**) &mUsb3Instance
);
403 if (!EFI_ERROR (Status
)) {
407 if (Instance
== NULL
) {
409 // Initialize USB debug
411 ZeroMem (&UsbDbg
, sizeof (UsbDbg
));
412 UsbDbg
.Initialized
= USB3DBG_UNINITIALIZED
;
414 DiscoverInitializeUsbDebugPort (&UsbDbg
);
420 // It is first time to run DXE instance, copy Instance from Hob to ACPINvs.
423 Status
= gBS
->AllocatePages (
426 EFI_SIZE_TO_PAGES (sizeof (USB3_DEBUG_PORT_HANDLE
)),
429 if (EFI_ERROR (Status
)) {
434 (VOID
*)(UINTN
)Address
,
436 sizeof (USB3_DEBUG_PORT_HANDLE
)
438 mUsb3Instance
= (USB3_DEBUG_PORT_HANDLE
*)(UINTN
)Address
;
440 Status
= gBS
->InstallConfigurationTable (&gUsb3DbgGuid
, mUsb3Instance
);
441 if (EFI_ERROR (Status
)) {
446 if ((mUsb3Instance
!= NULL
) && mUsb3Instance
->Ready
&& (mUsb3Instance
->PciIoEvent
== 0)) {
447 Status
= Usb3NamedEventListen (
448 &gEfiPciIoProtocolGuid
,
453 if (!EFI_ERROR (Status
)) {
454 mUsb3Instance
->PciIoEvent
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) Event
;
462 The destructor function.
464 @param ImageHandle The firmware allocated handle for the EFI image.
465 @param SystemTable A pointer to the EFI System Table.
467 @retval EFI_SUCCESS The destructor always returns EFI_SUCCESS.
472 DebugCommunicationUsb3DxeDestructor (
473 IN EFI_HANDLE ImageHandle
,
474 IN EFI_SYSTEM_TABLE
*SystemTable
477 if ((mUsb3Instance
!= NULL
) && (mUsb3Instance
->PciIoEvent
!= 0)) {
479 // Close the event created.
481 gBS
->CloseEvent ((EFI_EVENT
) (UINTN
) mUsb3Instance
->PciIoEvent
);
482 mUsb3Instance
->PciIoEvent
= 0;