For PEI, allocate granted DMA buffer from IOMMU PPI.
For DXE, map DMA buffer by PciIo.
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Ruiyu Ni <ruiyu.ni@intel.com>
Cc: Hao Wu <hao.a.wu@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Star Zeng <star.zeng@intel.com>
Reviewed-by: Ruiyu Ni <ruiyu.ni@intel.com>
(cherry picked from commit de8373fa07)
		
	
		
			
				
	
	
		
			487 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			487 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  Debug Port Library implementation based on usb3 debug port.
 | 
						|
 | 
						|
  Copyright (c) 2014 - 2018, Intel Corporation. All rights reserved.<BR>
 | 
						|
  This program and the accompanying materials
 | 
						|
  are licensed and made available under the terms and conditions of the BSD License
 | 
						|
  which accompanies this distribution.  The full text of the license may be found at
 | 
						|
  http://opensource.org/licenses/bsd-license.php.
 | 
						|
 | 
						|
  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | 
						|
  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#include <Base.h>
 | 
						|
#include <PiDxe.h>
 | 
						|
#include <Library/UefiBootServicesTableLib.h>
 | 
						|
#include <Library/HobLib.h>
 | 
						|
#include <Protocol/PciIo.h>
 | 
						|
#include <Protocol/IoMmu.h>
 | 
						|
#include "DebugCommunicationLibUsb3Internal.h"
 | 
						|
 | 
						|
GUID                        gUsb3DbgGuid =  USB3_DBG_GUID;
 | 
						|
 | 
						|
USB3_DEBUG_PORT_HANDLE      *mUsb3Instance = NULL;
 | 
						|
 | 
						|
/**
 | 
						|
  Creates a named event that can be signaled.
 | 
						|
 | 
						|
  This function creates an event using NotifyTpl, NoifyFunction.
 | 
						|
  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 Instance       Pointer to USB3 debug port instance.
 | 
						|
  @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.
 | 
						|
  @param BackupBuffer   Backup buffer address.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
Usb3MapOneDmaBuffer (
 | 
						|
  IN USB3_DEBUG_PORT_HANDLE     *Instance,
 | 
						|
  IN EFI_PCI_IO_PROTOCOL        *PciIo,
 | 
						|
  IN EFI_PHYSICAL_ADDRESS       Address,
 | 
						|
  IN UINTN                      NumberOfBytes,
 | 
						|
  IN EFI_PHYSICAL_ADDRESS       BackupBuffer
 | 
						|
  )
 | 
						|
{
 | 
						|
  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));
 | 
						|
  if (Instance->FromHob) {
 | 
						|
    //
 | 
						|
    // Reallocate the DMA buffer by AllocateAddress with
 | 
						|
    // the memory type accessible by SMM.
 | 
						|
    //
 | 
						|
    CopyMem ((VOID *) (UINTN) BackupBuffer, (VOID *) (UINTN) Address, NumberOfBytes);
 | 
						|
    Status = gBS->FreePages (Address, EFI_SIZE_TO_PAGES (NumberOfBytes));
 | 
						|
    ASSERT_EFI_ERROR (Status);
 | 
						|
    Status = gBS->AllocatePages (
 | 
						|
                    AllocateAddress,
 | 
						|
                    EfiACPIMemoryNVS,
 | 
						|
                    EFI_SIZE_TO_PAGES (NumberOfBytes),
 | 
						|
                    &Address
 | 
						|
                    );
 | 
						|
    ASSERT_EFI_ERROR (Status);
 | 
						|
    CopyMem ((VOID *) (UINTN) Address, (VOID *) (UINTN) BackupBuffer, NumberOfBytes);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  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
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                    Status;
 | 
						|
  EDKII_IOMMU_PROTOCOL          *IoMmu;
 | 
						|
  EFI_PHYSICAL_ADDRESS          BackupBuffer;
 | 
						|
  UINTN                         BackupBufferSize;
 | 
						|
 | 
						|
  IoMmu = NULL;
 | 
						|
  Status = gBS->LocateProtocol (&gEdkiiIoMmuProtocolGuid, NULL, (VOID **) &IoMmu);
 | 
						|
  if (EFI_ERROR (Status) || (IoMmu == NULL)) {
 | 
						|
    //
 | 
						|
    // No need to map the DMA buffers.
 | 
						|
    //
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Allocate backup buffer for the case that the USB3
 | 
						|
  // debug port instance and DMA buffers are from PEI HOB.
 | 
						|
  // For this case, the DMA buffers need to be reallocated
 | 
						|
  // by AllocateAddress with the memory type accessible by
 | 
						|
  // SMM.
 | 
						|
  //
 | 
						|
  BackupBufferSize = MAX (XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE * 2 + USB3_DEBUG_PORT_WRITE_MAX_PACKET_SIZE,
 | 
						|
                          MAX (sizeof (TRB_TEMPLATE) * TR_RING_TRB_NUMBER,
 | 
						|
                               MAX (sizeof (TRB_TEMPLATE) * EVENT_RING_TRB_NUMBER,
 | 
						|
                                    MAX (sizeof (EVENT_RING_SEG_TABLE_ENTRY) * ERST_NUMBER,
 | 
						|
                                         MAX (sizeof (XHC_DC_CONTEXT),
 | 
						|
                                              STRING0_DESC_LEN + MANU_DESC_LEN + PRODUCT_DESC_LEN + SERIAL_DESC_LEN)))));
 | 
						|
 | 
						|
  Status = gBS->AllocatePages (
 | 
						|
                  AllocateAnyPages,
 | 
						|
                  EfiBootServicesData,
 | 
						|
                  EFI_SIZE_TO_PAGES (BackupBufferSize),
 | 
						|
                  &BackupBuffer
 | 
						|
                  );
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
  Usb3MapOneDmaBuffer (
 | 
						|
    Instance,
 | 
						|
    PciIo,
 | 
						|
    Instance->UrbIn.Data,
 | 
						|
    XHCI_DEBUG_DEVICE_MAX_PACKET_SIZE * 2 + USB3_DEBUG_PORT_WRITE_MAX_PACKET_SIZE,
 | 
						|
    BackupBuffer
 | 
						|
    );
 | 
						|
 | 
						|
  Usb3MapOneDmaBuffer (
 | 
						|
    Instance,
 | 
						|
    PciIo,
 | 
						|
    Instance->TransferRingIn.RingSeg0,
 | 
						|
    sizeof (TRB_TEMPLATE) * TR_RING_TRB_NUMBER,
 | 
						|
    BackupBuffer
 | 
						|
    );
 | 
						|
 | 
						|
  Usb3MapOneDmaBuffer (
 | 
						|
    Instance,
 | 
						|
    PciIo,
 | 
						|
    Instance->TransferRingOut.RingSeg0,
 | 
						|
    sizeof (TRB_TEMPLATE) * TR_RING_TRB_NUMBER,
 | 
						|
    BackupBuffer
 | 
						|
    );
 | 
						|
 | 
						|
  Usb3MapOneDmaBuffer (
 | 
						|
    Instance,
 | 
						|
    PciIo,
 | 
						|
    Instance->EventRing.EventRingSeg0,
 | 
						|
    sizeof (TRB_TEMPLATE) * EVENT_RING_TRB_NUMBER,
 | 
						|
    BackupBuffer
 | 
						|
    );
 | 
						|
 | 
						|
  Usb3MapOneDmaBuffer (
 | 
						|
    Instance,
 | 
						|
    PciIo,
 | 
						|
    Instance->EventRing.ERSTBase,
 | 
						|
    sizeof (EVENT_RING_SEG_TABLE_ENTRY) * ERST_NUMBER,
 | 
						|
    BackupBuffer
 | 
						|
    );
 | 
						|
 | 
						|
  Usb3MapOneDmaBuffer (
 | 
						|
    Instance,
 | 
						|
    PciIo,
 | 
						|
    Instance->DebugCapabilityContext,
 | 
						|
    sizeof (XHC_DC_CONTEXT),
 | 
						|
    BackupBuffer
 | 
						|
    );
 | 
						|
 | 
						|
  Usb3MapOneDmaBuffer (
 | 
						|
    Instance,
 | 
						|
    PciIo,
 | 
						|
    ((XHC_DC_CONTEXT *) (UINTN) Instance->DebugCapabilityContext)->DbcInfoContext.String0DescAddress,
 | 
						|
    STRING0_DESC_LEN + MANU_DESC_LEN + PRODUCT_DESC_LEN + SERIAL_DESC_LEN,
 | 
						|
    BackupBuffer
 | 
						|
    );
 | 
						|
 | 
						|
  gBS->FreePages (BackupBuffer, EFI_SIZE_TO_PAGES (BackupBufferSize));
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  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;
 | 
						|
 | 
						|
  ASSERT (mUsb3Instance != NULL);
 | 
						|
 | 
						|
  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", __FUNCTION__));
 | 
						|
        mUsb3Instance->InNotify = TRUE;
 | 
						|
        Usb3MapDmaBuffers (mUsb3Instance, PciIo);
 | 
						|
        mUsb3Instance->InNotify = FALSE;
 | 
						|
        gBS->CloseEvent ((EFI_EVENT) (UINTN) mUsb3Instance->PciIoEvent);
 | 
						|
        break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    gBS->FreePool (PciIoHandleBuffer);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Return USB3 debug instance address.
 | 
						|
 | 
						|
**/  
 | 
						|
USB3_DEBUG_PORT_HANDLE *
 | 
						|
GetUsb3DebugPortInstance (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  USB3_DEBUG_PORT_HANDLE          *Instance;
 | 
						|
  EFI_PEI_HOB_POINTERS            Hob;
 | 
						|
 | 
						|
  Instance = NULL;
 | 
						|
 | 
						|
  if (mUsb3Instance != NULL) {
 | 
						|
    Instance = mUsb3Instance;
 | 
						|
    goto Done;
 | 
						|
  }
 | 
						|
 | 
						|
  Hob.Raw = GetFirstGuidHob (&gUsb3DbgGuid);
 | 
						|
  if (Hob.Raw != NULL) {
 | 
						|
    Instance = GET_GUID_HOB_DATA (Hob.Guid);
 | 
						|
  }
 | 
						|
 | 
						|
Done:
 | 
						|
  if (Instance != NULL) {
 | 
						|
    DiscoverInitializeUsbDebugPort (Instance);
 | 
						|
  }
 | 
						|
  return Instance;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  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) {
 | 
						|
    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
 | 
						|
  )
 | 
						|
{
 | 
						|
  USB3_DEBUG_PORT_HANDLE        UsbDbg;
 | 
						|
  USB3_DEBUG_PORT_HANDLE        *Instance;
 | 
						|
  EFI_PHYSICAL_ADDRESS          Address;
 | 
						|
  EFI_STATUS                    Status;
 | 
						|
  EFI_EVENT                     Event;
 | 
						|
 | 
						|
  Instance = GetUsb3DebugPortInstance ();
 | 
						|
 | 
						|
  Status = EfiGetSystemConfigurationTable (&gUsb3DbgGuid, (VOID **) &mUsb3Instance);
 | 
						|
  if (!EFI_ERROR (Status)) {
 | 
						|
    goto Done;
 | 
						|
  }
 | 
						|
 | 
						|
  if (Instance == NULL) {
 | 
						|
    //
 | 
						|
    // Initialize USB debug
 | 
						|
    //
 | 
						|
    ZeroMem (&UsbDbg, sizeof (UsbDbg));
 | 
						|
    UsbDbg.Initialized = USB3DBG_UNINITIALIZED;
 | 
						|
 | 
						|
    DiscoverInitializeUsbDebugPort (&UsbDbg);
 | 
						|
 | 
						|
    Instance = &UsbDbg;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // It is first time to run DXE instance, copy Instance from Hob to ACPINvs.
 | 
						|
  //
 | 
						|
  Address = SIZE_4GB;
 | 
						|
  Status = gBS->AllocatePages (
 | 
						|
                  AllocateMaxAddress,
 | 
						|
                  EfiACPIMemoryNVS,
 | 
						|
                  EFI_SIZE_TO_PAGES (sizeof (USB3_DEBUG_PORT_HANDLE)),
 | 
						|
                  &Address
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  CopyMem (
 | 
						|
    (VOID *)(UINTN)Address,
 | 
						|
    Instance,
 | 
						|
    sizeof (USB3_DEBUG_PORT_HANDLE)
 | 
						|
    );
 | 
						|
  mUsb3Instance = (USB3_DEBUG_PORT_HANDLE *)(UINTN)Address;
 | 
						|
 | 
						|
  Status = gBS->InstallConfigurationTable (&gUsb3DbgGuid, mUsb3Instance);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
Done:
 | 
						|
  if (mUsb3Instance->Ready && (mUsb3Instance->PciIoEvent == 0)) {
 | 
						|
    Status = Usb3NamedEventListen (
 | 
						|
               &gEfiPciIoProtocolGuid,
 | 
						|
               TPL_NOTIFY,
 | 
						|
               Usb3PciIoNotify,
 | 
						|
               &Event
 | 
						|
               );
 | 
						|
    if (!EFI_ERROR (Status)) {
 | 
						|
      mUsb3Instance->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
 | 
						|
  )
 | 
						|
{
 | 
						|
  if ((mUsb3Instance != NULL) && (mUsb3Instance->PciIoEvent != 0)) {
 | 
						|
    //
 | 
						|
    // Close the event created.
 | 
						|
    //
 | 
						|
    gBS->CloseEvent ((EFI_EVENT) (UINTN) mUsb3Instance->PciIoEvent);
 | 
						|
    mUsb3Instance->PciIoEvent = 0;
 | 
						|
  }
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 |