summaryrefslogtreecommitdiff
path: root/SourceLevelDebugPkg/Library/DebugCommunicationLibUsb3/DebugCommunicationLibUsb3Dxe.c
diff options
context:
space:
mode:
Diffstat (limited to 'SourceLevelDebugPkg/Library/DebugCommunicationLibUsb3/DebugCommunicationLibUsb3Dxe.c')
-rw-r--r--SourceLevelDebugPkg/Library/DebugCommunicationLibUsb3/DebugCommunicationLibUsb3Dxe.c1072
1 files changed, 536 insertions, 536 deletions
diff --git a/SourceLevelDebugPkg/Library/DebugCommunicationLibUsb3/DebugCommunicationLibUsb3Dxe.c b/SourceLevelDebugPkg/Library/DebugCommunicationLibUsb3/DebugCommunicationLibUsb3Dxe.c
index d37fb991f1..6f86ace58c 100644
--- a/SourceLevelDebugPkg/Library/DebugCommunicationLibUsb3/DebugCommunicationLibUsb3Dxe.c
+++ b/SourceLevelDebugPkg/Library/DebugCommunicationLibUsb3/DebugCommunicationLibUsb3Dxe.c
@@ -1,536 +1,536 @@
-/** @file
- Debug Port Library implementation based on usb3 debug port.
-
- Copyright (c) 2014 - 2018, Intel Corporation. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include <Base.h>
-#include <PiDxe.h>
-#include <Library/UefiBootServicesTableLib.h>
-#include <Library/HobLib.h>
-#include <Protocol/PciIo.h>
-#include <Protocol/IoMmu.h>
-#include <Protocol/DxeSmmReadyToLock.h>
-#include "DebugCommunicationLibUsb3Internal.h"
-
-GUID gUsb3DbgGuid = USB3_DBG_GUID;
-
-USB3_DEBUG_PORT_HANDLE mUsb3Instance = { USB3DBG_UNINITIALIZED };
-EFI_PHYSICAL_ADDRESS mUsb3InstanceAddr = 0;
-EFI_PHYSICAL_ADDRESS *mUsb3InstanceAddrPtr = NULL;
-EFI_PCI_IO_PROTOCOL *mUsb3PciIo = NULL;
-
-/**
- Creates a named event that can be signaled.
-
- This function creates an event using NotifyTpl, NotifyFunction.
- If Name is NULL, then ASSERT().
- If NotifyTpl is not a legal TPL value, then ASSERT().
- If NotifyFunction is NULL, then ASSERT().
-
- @param Name Supplies the GUID name of the event.
- @param NotifyTpl Supplies the task priority level of the event notifications.
- @param NotifyFunction Supplies the function to notify when the event is signaled.
- @param Event A pointer to the event created.
-
- @retval EFI_SUCCESS A named event was created.
- @retval EFI_OUT_OF_RESOURCES There are not enough resource to create the named event.
-
-**/
-EFI_STATUS
-EFIAPI
-Usb3NamedEventListen (
- IN CONST EFI_GUID *Name,
- IN EFI_TPL NotifyTpl,
- IN EFI_EVENT_NOTIFY NotifyFunction,
- IN EFI_EVENT *Event
- )
-{
- EFI_STATUS Status;
- VOID *RegistrationLocal;
-
- ASSERT (Name != NULL);
- ASSERT (NotifyFunction != NULL);
- ASSERT (NotifyTpl <= TPL_HIGH_LEVEL);
-
- //
- // Create event
- //
- Status = gBS->CreateEvent (
- EVT_NOTIFY_SIGNAL,
- NotifyTpl,
- NotifyFunction,
- NULL,
- Event
- );
- ASSERT_EFI_ERROR (Status);
-
- //
- // Register for an installation of protocol interface
- //
- Status = gBS->RegisterProtocolNotify (
- (EFI_GUID *)Name,
- *Event,
- &RegistrationLocal
- );
- ASSERT_EFI_ERROR (Status);
-
- return Status;
-}
-
-/**
- USB3 map one DMA buffer.
-
- @param PciIo Pointer to PciIo for USB3 debug port.
- @param Address DMA buffer address to be mapped.
- @param NumberOfBytes Number of bytes to be mapped.
-
-**/
-VOID
-Usb3MapOneDmaBuffer (
- IN EFI_PCI_IO_PROTOCOL *PciIo,
- IN EFI_PHYSICAL_ADDRESS Address,
- IN UINTN NumberOfBytes
- )
-{
- EFI_STATUS Status;
- VOID *HostAddress;
- EFI_PHYSICAL_ADDRESS DeviceAddress;
- VOID *Mapping;
-
- HostAddress = (VOID *)(UINTN)Address;
- Status = PciIo->Map (
- PciIo,
- EfiPciIoOperationBusMasterCommonBuffer,
- HostAddress,
- &NumberOfBytes,
- &DeviceAddress,
- &Mapping
- );
- ASSERT_EFI_ERROR (Status);
- ASSERT (DeviceAddress == ((EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress));
-}
-
-/**
- USB3 map DMA buffers.
-
- @param Instance Pointer to USB3 debug port instance.
- @param PciIo Pointer to PciIo for USB3 debug port.
-
-**/
-VOID
-Usb3MapDmaBuffers (
- IN USB3_DEBUG_PORT_HANDLE *Instance,
- IN EFI_PCI_IO_PROTOCOL *PciIo
- )
-{
- Usb3MapOneDmaBuffer (
- PciIo,
- Instance->UrbIn.Data,
- XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE * 2 + USB3_DEBUG_PORT_WRITE_MAX_PACKET_SIZE
- );
-
- Usb3MapOneDmaBuffer (
- PciIo,
- Instance->TransferRingIn.RingSeg0,
- sizeof (TRB_TEMPLATE) * TR_RING_TRB_NUMBER
- );
-
- Usb3MapOneDmaBuffer (
- PciIo,
- Instance->TransferRingOut.RingSeg0,
- sizeof (TRB_TEMPLATE) * TR_RING_TRB_NUMBER
- );
-
- Usb3MapOneDmaBuffer (
- PciIo,
- Instance->EventRing.EventRingSeg0,
- sizeof (TRB_TEMPLATE) * EVENT_RING_TRB_NUMBER
- );
-
- Usb3MapOneDmaBuffer (
- PciIo,
- Instance->EventRing.ERSTBase,
- sizeof (EVENT_RING_SEG_TABLE_ENTRY) * ERST_NUMBER
- );
-
- Usb3MapOneDmaBuffer (
- PciIo,
- Instance->DebugCapabilityContext,
- sizeof (XHC_DC_CONTEXT)
- );
-
- Usb3MapOneDmaBuffer (
- PciIo,
- ((XHC_DC_CONTEXT *)(UINTN)Instance->DebugCapabilityContext)->DbcInfoContext.String0DescAddress,
- STRING0_DESC_LEN + MANU_DESC_LEN + PRODUCT_DESC_LEN + SERIAL_DESC_LEN
- );
-}
-
-/**
- Invoke a notification event
-
- @param[in] Event Event whose notification function is being invoked.
- @param[in] Context The pointer to the notification function's context,
- which is implementation-dependent.
-
-**/
-VOID
-EFIAPI
-Usb3DxeSmmReadyToLockNotify (
- IN EFI_EVENT Event,
- IN VOID *Context
- )
-{
- USB3_DEBUG_PORT_HANDLE *Instance;
-
- DEBUG ((DEBUG_INFO, "%a()\n", __func__));
-
- Instance = GetUsb3DebugPortInstance ();
- ASSERT (Instance != NULL);
-
- Instance->InNotify = TRUE;
-
- //
- // For the case that the USB3 debug port instance and DMA buffers are
- // from PEI HOB with IOMMU enabled.
- // Reinitialize USB3 debug port with granted DXE DMA buffer accessible
- // by SMM environment.
- //
- InitializeUsbDebugHardware (Instance);
-
- //
- // Wait some time for host to be ready after re-initialization.
- //
- MicroSecondDelay (1000000);
-
- Instance->InNotify = FALSE;
- gBS->CloseEvent (Event);
-}
-
-/**
- USB3 get IOMMU protocol.
-
- @return Pointer to IOMMU protocol.
-
-**/
-EDKII_IOMMU_PROTOCOL *
-Usb3GetIoMmu (
- VOID
- )
-{
- EFI_STATUS Status;
- EDKII_IOMMU_PROTOCOL *IoMmu;
-
- IoMmu = NULL;
- Status = gBS->LocateProtocol (
- &gEdkiiIoMmuProtocolGuid,
- NULL,
- (VOID **)&IoMmu
- );
- if (!EFI_ERROR (Status) && (IoMmu != NULL)) {
- return IoMmu;
- }
-
- return NULL;
-}
-
-/**
- Invoke a notification event
-
- @param[in] Event Event whose notification function is being invoked.
- @param[in] Context The pointer to the notification function's context,
- which is implementation-dependent.
-
-**/
-VOID
-EFIAPI
-Usb3PciIoNotify (
- IN EFI_EVENT Event,
- IN VOID *Context
- )
-{
- EFI_STATUS Status;
- UINTN PciIoHandleCount;
- EFI_HANDLE *PciIoHandleBuffer;
- UINTN Index;
- EFI_PCI_IO_PROTOCOL *PciIo;
- UINTN PciSegment;
- UINTN PciBusNumber;
- UINTN PciDeviceNumber;
- UINTN PciFunctionNumber;
- UINT32 PciAddress;
- USB3_DEBUG_PORT_HANDLE *Instance;
- EFI_EVENT SmmReadyToLockEvent;
-
- Status = gBS->LocateHandleBuffer (
- ByProtocol,
- &gEfiPciIoProtocolGuid,
- NULL,
- &PciIoHandleCount,
- &PciIoHandleBuffer
- );
- if (!EFI_ERROR (Status) &&
- (PciIoHandleBuffer != NULL) &&
- (PciIoHandleCount != 0))
- {
- for (Index = 0; Index < PciIoHandleCount; Index++) {
- Status = gBS->HandleProtocol (
- PciIoHandleBuffer[Index],
- &gEfiPciIoProtocolGuid,
- (VOID **)&PciIo
- );
- ASSERT_EFI_ERROR (Status);
- Status = PciIo->GetLocation (PciIo, &PciSegment, &PciBusNumber, &PciDeviceNumber, &PciFunctionNumber);
- ASSERT_EFI_ERROR (Status);
- PciAddress = (UINT32)((PciBusNumber << 20) | (PciDeviceNumber << 15) | (PciFunctionNumber << 12));
- if (PciAddress == PcdGet32 (PcdUsbXhciPciAddress)) {
- //
- // Found the PciIo for USB3 debug port.
- //
- DEBUG ((DEBUG_INFO, "%a()\n", __func__));
- if (Usb3GetIoMmu () != NULL) {
- Instance = GetUsb3DebugPortInstance ();
- ASSERT (Instance != NULL);
- if (Instance->Ready) {
- Instance->InNotify = TRUE;
- Usb3MapDmaBuffers (Instance, PciIo);
- Instance->InNotify = FALSE;
-
- if (Instance->FromHob) {
- mUsb3PciIo = PciIo;
- Usb3NamedEventListen (
- &gEfiDxeSmmReadyToLockProtocolGuid,
- TPL_NOTIFY,
- Usb3DxeSmmReadyToLockNotify,
- &SmmReadyToLockEvent
- );
- }
- }
- }
-
- gBS->CloseEvent (Event);
- break;
- }
- }
-
- gBS->FreePool (PciIoHandleBuffer);
- }
-}
-
-/**
- Return USB3 debug instance address pointer.
-
-**/
-EFI_PHYSICAL_ADDRESS *
-GetUsb3DebugPortInstanceAddrPtr (
- VOID
- )
-{
- if (mUsb3InstanceAddrPtr == NULL) {
- //
- // Use the local variables temporarily.
- //
- mUsb3InstanceAddr = (EFI_PHYSICAL_ADDRESS)(UINTN)&mUsb3Instance;
- mUsb3InstanceAddrPtr = &mUsb3InstanceAddr;
- }
-
- return mUsb3InstanceAddrPtr;
-}
-
-/**
- Allocates pages that are suitable for an OperationBusMasterCommonBuffer or
- OperationBusMasterCommonBuffer64 mapping.
-
- @param PciIo Pointer to PciIo for USB3 debug port.
- @param Pages The number of pages to allocate.
- @param Address A pointer to store the base system memory address of the
- allocated range.
-
- @retval EFI_SUCCESS The requested memory pages were allocated.
- @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal attribute bits are
- MEMORY_WRITE_COMBINE and MEMORY_CACHED.
- @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
- @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
-
-**/
-EFI_STATUS
-Usb3AllocateDmaBuffer (
- IN EFI_PCI_IO_PROTOCOL *PciIo,
- IN UINTN Pages,
- OUT VOID **Address
- )
-{
- EFI_STATUS Status;
-
- *Address = NULL;
- Status = PciIo->AllocateBuffer (
- PciIo,
- AllocateAnyPages,
- EfiRuntimeServicesData,
- Pages,
- Address,
- 0
- );
- if (!EFI_ERROR (Status)) {
- Usb3MapOneDmaBuffer (
- PciIo,
- (EFI_PHYSICAL_ADDRESS)(UINTN)*Address,
- EFI_PAGES_TO_SIZE (Pages)
- );
- }
-
- return Status;
-}
-
-/**
- Allocate aligned memory for XHC's usage.
-
- @param BufferSize The size, in bytes, of the Buffer.
-
- @return A pointer to the allocated buffer or NULL if allocation fails.
-
-**/
-VOID *
-AllocateAlignBuffer (
- IN UINTN BufferSize
- )
-{
- EFI_PHYSICAL_ADDRESS TmpAddr;
- EFI_STATUS Status;
- VOID *Buf;
-
- Buf = NULL;
-
- if (gBS != NULL) {
- if (mUsb3PciIo != NULL) {
- Usb3AllocateDmaBuffer (
- mUsb3PciIo,
- EFI_SIZE_TO_PAGES (BufferSize),
- &Buf
- );
- } else {
- TmpAddr = 0xFFFFFFFF;
- Status = gBS->AllocatePages (
- AllocateMaxAddress,
- EfiACPIMemoryNVS,
- EFI_SIZE_TO_PAGES (BufferSize),
- &TmpAddr
- );
- if (!EFI_ERROR (Status)) {
- Buf = (VOID *)(UINTN)TmpAddr;
- }
- }
- }
-
- return Buf;
-}
-
-/**
- The constructor function initialize USB3 debug port.
-
- @param ImageHandle The firmware allocated handle for the EFI image.
- @param SystemTable A pointer to the EFI System Table.
-
- @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.
-
-**/
-EFI_STATUS
-EFIAPI
-DebugCommunicationUsb3DxeConstructor (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- )
-{
- EFI_PHYSICAL_ADDRESS *AddrPtr;
- USB3_DEBUG_PORT_HANDLE *Instance;
- EFI_PHYSICAL_ADDRESS Address;
- EFI_STATUS Status;
- EFI_EVENT Event;
-
- Status = EfiGetSystemConfigurationTable (&gUsb3DbgGuid, (VOID **)&AddrPtr);
- if (EFI_ERROR (Status) || (AddrPtr == NULL)) {
- //
- // Instead of using local variables, install system configuration table for
- // the local instance and the buffer to save instance address pointer.
- //
- Address = SIZE_4GB;
- Status = gBS->AllocatePages (
- AllocateMaxAddress,
- EfiACPIMemoryNVS,
- EFI_SIZE_TO_PAGES (sizeof (EFI_PHYSICAL_ADDRESS) + sizeof (USB3_DEBUG_PORT_HANDLE)),
- &Address
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- AddrPtr = (EFI_PHYSICAL_ADDRESS *)(UINTN)Address;
- ZeroMem (AddrPtr, sizeof (EFI_PHYSICAL_ADDRESS) + sizeof (USB3_DEBUG_PORT_HANDLE));
- Instance = (USB3_DEBUG_PORT_HANDLE *)(AddrPtr + 1);
- CopyMem (Instance, &mUsb3Instance, sizeof (USB3_DEBUG_PORT_HANDLE));
- *AddrPtr = (EFI_PHYSICAL_ADDRESS)(UINTN)Instance;
-
- Status = gBS->InstallConfigurationTable (&gUsb3DbgGuid, AddrPtr);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- }
-
- if (mUsb3InstanceAddrPtr != NULL) {
- *AddrPtr = *mUsb3InstanceAddrPtr;
- }
-
- mUsb3InstanceAddrPtr = AddrPtr;
-
- Instance = GetUsb3DebugPortInstance ();
- ASSERT (Instance != NULL);
-
- if (Instance->PciIoEvent == 0) {
- Status = Usb3NamedEventListen (
- &gEfiPciIoProtocolGuid,
- TPL_NOTIFY,
- Usb3PciIoNotify,
- &Event
- );
- if (!EFI_ERROR (Status)) {
- Instance->PciIoEvent = (EFI_PHYSICAL_ADDRESS)(UINTN)Event;
- }
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- The destructor function.
-
- @param ImageHandle The firmware allocated handle for the EFI image.
- @param SystemTable A pointer to the EFI System Table.
-
- @retval EFI_SUCCESS The destructor always returns EFI_SUCCESS.
-
-**/
-EFI_STATUS
-EFIAPI
-DebugCommunicationUsb3DxeDestructor (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- )
-{
- USB3_DEBUG_PORT_HANDLE *Instance;
-
- Instance = GetUsb3DebugPortInstance ();
- ASSERT (Instance != NULL);
-
- if (Instance->PciIoEvent != 0) {
- //
- // Close the event created.
- //
- gBS->CloseEvent ((EFI_EVENT)(UINTN)Instance->PciIoEvent);
- Instance->PciIoEvent = 0;
- }
-
- return EFI_SUCCESS;
-}
+/** @file
+ Debug Port Library implementation based on usb3 debug port.
+
+ Copyright (c) 2014 - 2018, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Base.h>
+#include <PiDxe.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/HobLib.h>
+#include <Protocol/PciIo.h>
+#include <Protocol/IoMmu.h>
+#include <Protocol/DxeSmmReadyToLock.h>
+#include "DebugCommunicationLibUsb3Internal.h"
+
+GUID gUsb3DbgGuid = USB3_DBG_GUID;
+
+USB3_DEBUG_PORT_HANDLE mUsb3Instance = { USB3DBG_UNINITIALIZED };
+EFI_PHYSICAL_ADDRESS mUsb3InstanceAddr = 0;
+EFI_PHYSICAL_ADDRESS *mUsb3InstanceAddrPtr = NULL;
+EFI_PCI_IO_PROTOCOL *mUsb3PciIo = NULL;
+
+/**
+ Creates a named event that can be signaled.
+
+ This function creates an event using NotifyTpl, NotifyFunction.
+ If Name is NULL, then ASSERT().
+ If NotifyTpl is not a legal TPL value, then ASSERT().
+ If NotifyFunction is NULL, then ASSERT().
+
+ @param Name Supplies the GUID name of the event.
+ @param NotifyTpl Supplies the task priority level of the event notifications.
+ @param NotifyFunction Supplies the function to notify when the event is signaled.
+ @param Event A pointer to the event created.
+
+ @retval EFI_SUCCESS A named event was created.
+ @retval EFI_OUT_OF_RESOURCES There are not enough resource to create the named event.
+
+**/
+EFI_STATUS
+EFIAPI
+Usb3NamedEventListen (
+ IN CONST EFI_GUID *Name,
+ IN EFI_TPL NotifyTpl,
+ IN EFI_EVENT_NOTIFY NotifyFunction,
+ IN EFI_EVENT *Event
+ )
+{
+ EFI_STATUS Status;
+ VOID *RegistrationLocal;
+
+ ASSERT (Name != NULL);
+ ASSERT (NotifyFunction != NULL);
+ ASSERT (NotifyTpl <= TPL_HIGH_LEVEL);
+
+ //
+ // Create event
+ //
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_SIGNAL,
+ NotifyTpl,
+ NotifyFunction,
+ NULL,
+ Event
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Register for an installation of protocol interface
+ //
+ Status = gBS->RegisterProtocolNotify (
+ (EFI_GUID *)Name,
+ *Event,
+ &RegistrationLocal
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+/**
+ USB3 map one DMA buffer.
+
+ @param PciIo Pointer to PciIo for USB3 debug port.
+ @param Address DMA buffer address to be mapped.
+ @param NumberOfBytes Number of bytes to be mapped.
+
+**/
+VOID
+Usb3MapOneDmaBuffer (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN EFI_PHYSICAL_ADDRESS Address,
+ IN UINTN NumberOfBytes
+ )
+{
+ EFI_STATUS Status;
+ VOID *HostAddress;
+ EFI_PHYSICAL_ADDRESS DeviceAddress;
+ VOID *Mapping;
+
+ HostAddress = (VOID *)(UINTN)Address;
+ Status = PciIo->Map (
+ PciIo,
+ EfiPciIoOperationBusMasterCommonBuffer,
+ HostAddress,
+ &NumberOfBytes,
+ &DeviceAddress,
+ &Mapping
+ );
+ ASSERT_EFI_ERROR (Status);
+ ASSERT (DeviceAddress == ((EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress));
+}
+
+/**
+ USB3 map DMA buffers.
+
+ @param Instance Pointer to USB3 debug port instance.
+ @param PciIo Pointer to PciIo for USB3 debug port.
+
+**/
+VOID
+Usb3MapDmaBuffers (
+ IN USB3_DEBUG_PORT_HANDLE *Instance,
+ IN EFI_PCI_IO_PROTOCOL *PciIo
+ )
+{
+ Usb3MapOneDmaBuffer (
+ PciIo,
+ Instance->UrbIn.Data,
+ XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE * 2 + USB3_DEBUG_PORT_WRITE_MAX_PACKET_SIZE
+ );
+
+ Usb3MapOneDmaBuffer (
+ PciIo,
+ Instance->TransferRingIn.RingSeg0,
+ sizeof (TRB_TEMPLATE) * TR_RING_TRB_NUMBER
+ );
+
+ Usb3MapOneDmaBuffer (
+ PciIo,
+ Instance->TransferRingOut.RingSeg0,
+ sizeof (TRB_TEMPLATE) * TR_RING_TRB_NUMBER
+ );
+
+ Usb3MapOneDmaBuffer (
+ PciIo,
+ Instance->EventRing.EventRingSeg0,
+ sizeof (TRB_TEMPLATE) * EVENT_RING_TRB_NUMBER
+ );
+
+ Usb3MapOneDmaBuffer (
+ PciIo,
+ Instance->EventRing.ERSTBase,
+ sizeof (EVENT_RING_SEG_TABLE_ENTRY) * ERST_NUMBER
+ );
+
+ Usb3MapOneDmaBuffer (
+ PciIo,
+ Instance->DebugCapabilityContext,
+ sizeof (XHC_DC_CONTEXT)
+ );
+
+ Usb3MapOneDmaBuffer (
+ PciIo,
+ ((XHC_DC_CONTEXT *)(UINTN)Instance->DebugCapabilityContext)->DbcInfoContext.String0DescAddress,
+ STRING0_DESC_LEN + MANU_DESC_LEN + PRODUCT_DESC_LEN + SERIAL_DESC_LEN
+ );
+}
+
+/**
+ Invoke a notification event
+
+ @param[in] Event Event whose notification function is being invoked.
+ @param[in] Context The pointer to the notification function's context,
+ which is implementation-dependent.
+
+**/
+VOID
+EFIAPI
+Usb3DxeSmmReadyToLockNotify (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ USB3_DEBUG_PORT_HANDLE *Instance;
+
+ DEBUG ((DEBUG_INFO, "%a()\n", __func__));
+
+ Instance = GetUsb3DebugPortInstance ();
+ ASSERT (Instance != NULL);
+
+ Instance->InNotify = TRUE;
+
+ //
+ // For the case that the USB3 debug port instance and DMA buffers are
+ // from PEI HOB with IOMMU enabled.
+ // Reinitialize USB3 debug port with granted DXE DMA buffer accessible
+ // by SMM environment.
+ //
+ InitializeUsbDebugHardware (Instance);
+
+ //
+ // Wait some time for host to be ready after re-initialization.
+ //
+ MicroSecondDelay (1000000);
+
+ Instance->InNotify = FALSE;
+ gBS->CloseEvent (Event);
+}
+
+/**
+ USB3 get IOMMU protocol.
+
+ @return Pointer to IOMMU protocol.
+
+**/
+EDKII_IOMMU_PROTOCOL *
+Usb3GetIoMmu (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EDKII_IOMMU_PROTOCOL *IoMmu;
+
+ IoMmu = NULL;
+ Status = gBS->LocateProtocol (
+ &gEdkiiIoMmuProtocolGuid,
+ NULL,
+ (VOID **)&IoMmu
+ );
+ if (!EFI_ERROR (Status) && (IoMmu != NULL)) {
+ return IoMmu;
+ }
+
+ return NULL;
+}
+
+/**
+ Invoke a notification event
+
+ @param[in] Event Event whose notification function is being invoked.
+ @param[in] Context The pointer to the notification function's context,
+ which is implementation-dependent.
+
+**/
+VOID
+EFIAPI
+Usb3PciIoNotify (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ UINTN PciIoHandleCount;
+ EFI_HANDLE *PciIoHandleBuffer;
+ UINTN Index;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINTN PciSegment;
+ UINTN PciBusNumber;
+ UINTN PciDeviceNumber;
+ UINTN PciFunctionNumber;
+ UINT32 PciAddress;
+ USB3_DEBUG_PORT_HANDLE *Instance;
+ EFI_EVENT SmmReadyToLockEvent;
+
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiPciIoProtocolGuid,
+ NULL,
+ &PciIoHandleCount,
+ &PciIoHandleBuffer
+ );
+ if (!EFI_ERROR (Status) &&
+ (PciIoHandleBuffer != NULL) &&
+ (PciIoHandleCount != 0))
+ {
+ for (Index = 0; Index < PciIoHandleCount; Index++) {
+ Status = gBS->HandleProtocol (
+ PciIoHandleBuffer[Index],
+ &gEfiPciIoProtocolGuid,
+ (VOID **)&PciIo
+ );
+ ASSERT_EFI_ERROR (Status);
+ Status = PciIo->GetLocation (PciIo, &PciSegment, &PciBusNumber, &PciDeviceNumber, &PciFunctionNumber);
+ ASSERT_EFI_ERROR (Status);
+ PciAddress = (UINT32)((PciBusNumber << 20) | (PciDeviceNumber << 15) | (PciFunctionNumber << 12));
+ if (PciAddress == PcdGet32 (PcdUsbXhciPciAddress)) {
+ //
+ // Found the PciIo for USB3 debug port.
+ //
+ DEBUG ((DEBUG_INFO, "%a()\n", __func__));
+ if (Usb3GetIoMmu () != NULL) {
+ Instance = GetUsb3DebugPortInstance ();
+ ASSERT (Instance != NULL);
+ if (Instance->Ready) {
+ Instance->InNotify = TRUE;
+ Usb3MapDmaBuffers (Instance, PciIo);
+ Instance->InNotify = FALSE;
+
+ if (Instance->FromHob) {
+ mUsb3PciIo = PciIo;
+ Usb3NamedEventListen (
+ &gEfiDxeSmmReadyToLockProtocolGuid,
+ TPL_NOTIFY,
+ Usb3DxeSmmReadyToLockNotify,
+ &SmmReadyToLockEvent
+ );
+ }
+ }
+ }
+
+ gBS->CloseEvent (Event);
+ break;
+ }
+ }
+
+ gBS->FreePool (PciIoHandleBuffer);
+ }
+}
+
+/**
+ Return USB3 debug instance address pointer.
+
+**/
+EFI_PHYSICAL_ADDRESS *
+GetUsb3DebugPortInstanceAddrPtr (
+ VOID
+ )
+{
+ if (mUsb3InstanceAddrPtr == NULL) {
+ //
+ // Use the local variables temporarily.
+ //
+ mUsb3InstanceAddr = (EFI_PHYSICAL_ADDRESS)(UINTN)&mUsb3Instance;
+ mUsb3InstanceAddrPtr = &mUsb3InstanceAddr;
+ }
+
+ return mUsb3InstanceAddrPtr;
+}
+
+/**
+ Allocates pages that are suitable for an OperationBusMasterCommonBuffer or
+ OperationBusMasterCommonBuffer64 mapping.
+
+ @param PciIo Pointer to PciIo for USB3 debug port.
+ @param Pages The number of pages to allocate.
+ @param Address A pointer to store the base system memory address of the
+ allocated range.
+
+ @retval EFI_SUCCESS The requested memory pages were allocated.
+ @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal attribute bits are
+ MEMORY_WRITE_COMBINE and MEMORY_CACHED.
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+ @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
+
+**/
+EFI_STATUS
+Usb3AllocateDmaBuffer (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINTN Pages,
+ OUT VOID **Address
+ )
+{
+ EFI_STATUS Status;
+
+ *Address = NULL;
+ Status = PciIo->AllocateBuffer (
+ PciIo,
+ AllocateAnyPages,
+ EfiRuntimeServicesData,
+ Pages,
+ Address,
+ 0
+ );
+ if (!EFI_ERROR (Status)) {
+ Usb3MapOneDmaBuffer (
+ PciIo,
+ (EFI_PHYSICAL_ADDRESS)(UINTN)*Address,
+ EFI_PAGES_TO_SIZE (Pages)
+ );
+ }
+
+ return Status;
+}
+
+/**
+ Allocate aligned memory for XHC's usage.
+
+ @param BufferSize The size, in bytes, of the Buffer.
+
+ @return A pointer to the allocated buffer or NULL if allocation fails.
+
+**/
+VOID *
+AllocateAlignBuffer (
+ IN UINTN BufferSize
+ )
+{
+ EFI_PHYSICAL_ADDRESS TmpAddr;
+ EFI_STATUS Status;
+ VOID *Buf;
+
+ Buf = NULL;
+
+ if (gBS != NULL) {
+ if (mUsb3PciIo != NULL) {
+ Usb3AllocateDmaBuffer (
+ mUsb3PciIo,
+ EFI_SIZE_TO_PAGES (BufferSize),
+ &Buf
+ );
+ } else {
+ TmpAddr = 0xFFFFFFFF;
+ Status = gBS->AllocatePages (
+ AllocateMaxAddress,
+ EfiACPIMemoryNVS,
+ EFI_SIZE_TO_PAGES (BufferSize),
+ &TmpAddr
+ );
+ if (!EFI_ERROR (Status)) {
+ Buf = (VOID *)(UINTN)TmpAddr;
+ }
+ }
+ }
+
+ return Buf;
+}
+
+/**
+ The constructor function initialize USB3 debug port.
+
+ @param ImageHandle The firmware allocated handle for the EFI image.
+ @param SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.
+
+**/
+EFI_STATUS
+EFIAPI
+DebugCommunicationUsb3DxeConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_PHYSICAL_ADDRESS *AddrPtr;
+ USB3_DEBUG_PORT_HANDLE *Instance;
+ EFI_PHYSICAL_ADDRESS Address;
+ EFI_STATUS Status;
+ EFI_EVENT Event;
+
+ Status = EfiGetSystemConfigurationTable (&gUsb3DbgGuid, (VOID **)&AddrPtr);
+ if (EFI_ERROR (Status) || (AddrPtr == NULL)) {
+ //
+ // Instead of using local variables, install system configuration table for
+ // the local instance and the buffer to save instance address pointer.
+ //
+ Address = SIZE_4GB;
+ Status = gBS->AllocatePages (
+ AllocateMaxAddress,
+ EfiACPIMemoryNVS,
+ EFI_SIZE_TO_PAGES (sizeof (EFI_PHYSICAL_ADDRESS) + sizeof (USB3_DEBUG_PORT_HANDLE)),
+ &Address
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ AddrPtr = (EFI_PHYSICAL_ADDRESS *)(UINTN)Address;
+ ZeroMem (AddrPtr, sizeof (EFI_PHYSICAL_ADDRESS) + sizeof (USB3_DEBUG_PORT_HANDLE));
+ Instance = (USB3_DEBUG_PORT_HANDLE *)(AddrPtr + 1);
+ CopyMem (Instance, &mUsb3Instance, sizeof (USB3_DEBUG_PORT_HANDLE));
+ *AddrPtr = (EFI_PHYSICAL_ADDRESS)(UINTN)Instance;
+
+ Status = gBS->InstallConfigurationTable (&gUsb3DbgGuid, AddrPtr);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ if (mUsb3InstanceAddrPtr != NULL) {
+ *AddrPtr = *mUsb3InstanceAddrPtr;
+ }
+
+ mUsb3InstanceAddrPtr = AddrPtr;
+
+ Instance = GetUsb3DebugPortInstance ();
+ ASSERT (Instance != NULL);
+
+ if (Instance->PciIoEvent == 0) {
+ Status = Usb3NamedEventListen (
+ &gEfiPciIoProtocolGuid,
+ TPL_NOTIFY,
+ Usb3PciIoNotify,
+ &Event
+ );
+ if (!EFI_ERROR (Status)) {
+ Instance->PciIoEvent = (EFI_PHYSICAL_ADDRESS)(UINTN)Event;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ The destructor function.
+
+ @param ImageHandle The firmware allocated handle for the EFI image.
+ @param SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The destructor always returns EFI_SUCCESS.
+
+**/
+EFI_STATUS
+EFIAPI
+DebugCommunicationUsb3DxeDestructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ USB3_DEBUG_PORT_HANDLE *Instance;
+
+ Instance = GetUsb3DebugPortInstance ();
+ ASSERT (Instance != NULL);
+
+ if (Instance->PciIoEvent != 0) {
+ //
+ // Close the event created.
+ //
+ gBS->CloseEvent ((EFI_EVENT)(UINTN)Instance->PciIoEvent);
+ Instance->PciIoEvent = 0;
+ }
+
+ return EFI_SUCCESS;
+}