diff options
Diffstat (limited to 'SourceLevelDebugPkg/Library/DebugCommunicationLibUsb3/DebugCommunicationLibUsb3Dxe.c')
| -rw-r--r-- | SourceLevelDebugPkg/Library/DebugCommunicationLibUsb3/DebugCommunicationLibUsb3Dxe.c | 1072 |
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; +} |
