[edk2-devel] [Patch 2/3] [edk2-platforms] Platform/Intel/DebugFeaturePkg: Add USB3DebugPort related modules.

Dong, Eric eric.dong at intel.com
Wed May 29 00:47:53 UTC 2019


https://bugzilla.tianocore.org/show_bug.cgi?id=1553

Add USB3DebugPort related modules, include Usb3DebugPortLib and
Usb3DebugPortParameterLib. Usb3DebugPortParameterLib will be consumed
by Usb3DebugPortLib.

Interfaces export by Us3DebugPortLib includes:
Usb3DebugPortParameterLib
Usb3DebugPortWrite
Usb3DebugPortPoll

Interfaces export by Usb3DebugPortParameterLib includes:
GetUsb3DebugPortController
SetUsb3DebugPortController

Signed-off-by: Eric Dong <eric.dong at intel.com>
Cc: Liming Gao <liming.gao at intel.com>
---
 .../Intel/DebugFeaturePkg/DebugFeaturePkg.dec |  36 +-
 .../Intel/DebugFeaturePkg/DebugFeaturePkg.dsc |  62 ++
 .../Include/Library/Usb3DebugPortLib.h        |  76 ++
 .../Library/Usb3DebugPortParameterLib.h       |  56 ++
 .../Library/Usb3DebugPortLib/MiscServices.c   | 385 ++++++++
 .../Usb3DebugPortDataTransfer.c               | 892 ++++++++++++++++++
 .../Usb3DebugPortInitialize.c                 | 726 ++++++++++++++
 .../Usb3DebugPortLib/Usb3DebugPortLibDxe.c    | 454 +++++++++
 .../Usb3DebugPortLib/Usb3DebugPortLibDxe.inf  |  55 ++
 .../Usb3DebugPortLibDxeIoMmu.c                | 828 ++++++++++++++++
 .../Usb3DebugPortLibDxeIoMmu.inf              |  63 ++
 .../Usb3DebugPortLibInternal.h                | 887 +++++++++++++++++
 .../Usb3DebugPortLib/Usb3DebugPortLibNull.c   | 103 ++
 .../Usb3DebugPortLib/Usb3DebugPortLibNull.inf |  28 +
 .../Usb3DebugPortLib/Usb3DebugPortLibPei.c    | 236 +++++
 .../Usb3DebugPortLib/Usb3DebugPortLibPei.inf  |  48 +
 .../Usb3DebugPortLibPeiIoMmu.c                | 440 +++++++++
 .../Usb3DebugPortLibPeiIoMmu.inf              |  51 +
 .../Usb3DebugPortParameterLibPcd.c            |  58 ++
 .../Usb3DebugPortParameterLibPcd.inf          |  31 +
 20 files changed, 5514 insertions(+), 1 deletion(-)
 create mode 100644 Platform/Intel/DebugFeaturePkg/Include/Library/Usb3DebugPortLib.h
 create mode 100644 Platform/Intel/DebugFeaturePkg/Include/Library/Usb3DebugPortParameterLib.h
 create mode 100644 Platform/Intel/DebugFeaturePkg/Library/Usb3DebugPortLib/MiscServices.c
 create mode 100644 Platform/Intel/DebugFeaturePkg/Library/Usb3DebugPortLib/Usb3DebugPortDataTransfer.c
 create mode 100644 Platform/Intel/DebugFeaturePkg/Library/Usb3DebugPortLib/Usb3DebugPortInitialize.c
 create mode 100644 Platform/Intel/DebugFeaturePkg/Library/Usb3DebugPortLib/Usb3DebugPortLibDxe.c
 create mode 100644 Platform/Intel/DebugFeaturePkg/Library/Usb3DebugPortLib/Usb3DebugPortLibDxe.inf
 create mode 100644 Platform/Intel/DebugFeaturePkg/Library/Usb3DebugPortLib/Usb3DebugPortLibDxeIoMmu.c
 create mode 100644 Platform/Intel/DebugFeaturePkg/Library/Usb3DebugPortLib/Usb3DebugPortLibDxeIoMmu.inf
 create mode 100644 Platform/Intel/DebugFeaturePkg/Library/Usb3DebugPortLib/Usb3DebugPortLibInternal.h
 create mode 100644 Platform/Intel/DebugFeaturePkg/Library/Usb3DebugPortLib/Usb3DebugPortLibNull.c
 create mode 100644 Platform/Intel/DebugFeaturePkg/Library/Usb3DebugPortLib/Usb3DebugPortLibNull.inf
 create mode 100644 Platform/Intel/DebugFeaturePkg/Library/Usb3DebugPortLib/Usb3DebugPortLibPei.c
 create mode 100644 Platform/Intel/DebugFeaturePkg/Library/Usb3DebugPortLib/Usb3DebugPortLibPei.inf
 create mode 100644 Platform/Intel/DebugFeaturePkg/Library/Usb3DebugPortLib/Usb3DebugPortLibPeiIoMmu.c
 create mode 100644 Platform/Intel/DebugFeaturePkg/Library/Usb3DebugPortLib/Usb3DebugPortLibPeiIoMmu.inf
 create mode 100644 Platform/Intel/DebugFeaturePkg/Library/Usb3DebugPortParameterLibPcd/Usb3DebugPortParameterLibPcd.c
 create mode 100644 Platform/Intel/DebugFeaturePkg/Library/Usb3DebugPortParameterLibPcd/Usb3DebugPortParameterLibPcd.inf

diff --git a/Platform/Intel/DebugFeaturePkg/DebugFeaturePkg.dec b/Platform/Intel/DebugFeaturePkg/DebugFeaturePkg.dec
index 839684183a..63a6ed03b7 100644
--- a/Platform/Intel/DebugFeaturePkg/DebugFeaturePkg.dec
+++ b/Platform/Intel/DebugFeaturePkg/DebugFeaturePkg.dec
@@ -16,4 +16,38 @@
   DEC_SPECIFICATION              = 0x00010005
   PACKAGE_NAME                   = DebugFeaturePkg
   PACKAGE_GUID                   = 58B6F2BB-A94F-4EB9-89DA-2F06ED59CE39
-  PACKAGE_VERSION                = 0.1
\ No newline at end of file
+  PACKAGE_VERSION                = 0.1
+
+[Includes]
+  Include
+
+[LibraryClasses]
+  ##  @libraryclass    Provide capability to get/set USB3 debug port parameter.
+  Usb3DebugPortParameterLib|Include/Library/Usb3DebugPortParameterLib.h
+
+[Guids]
+  gEfiUsb3DebugPortTokenSpaceGuid = { 0x87e7378b, 0xc59d, 0x4a16, { 0xa4, 0x21, 0x2c, 0xdb, 0x78, 0x26, 0xb1, 0xca } }
+
+[PcdsFeatureFlag]
+  ## This PCD specifies whether StatusCode is reported via USB3 Serial port.
+  gEfiUsb3DebugPortTokenSpaceGuid.PcdStatusCodeUseUsb3Serial|TRUE|BOOLEAN|0x10000003
+
+[PcdsFixedAtBuild]
+  ## These PCD specify XHCI controller Bus/Device/Function, which are used to enable
+  #  XHCI debug device.
+  gEfiUsb3DebugPortTokenSpaceGuid.PcdUsbSerialXhciBus|0x00|UINT8|0x00000016
+  gEfiUsb3DebugPortTokenSpaceGuid.PcdUsbSerialXhciDev|0x14|UINT8|0x00000017
+  gEfiUsb3DebugPortTokenSpaceGuid.PcdUsbSerialXhciFunc|0x00|UINT8|0x00000018
+  gEfiUsb3DebugPortTokenSpaceGuid.PcdXhciDefaultBaseAddress|0xFEA10000|UINT32|0x00000019
+
+  ## This PCD specifies the wait timeout value in microsecond if USB debug cable is detected but host not connected.
+  #  Default timeout value is 2000000 microseconds.
+  #  If user does not want system stall for long time, it can be set to small value.
+  gEfiUsb3DebugPortTokenSpaceGuid.PcdXhciHostWaitTimeout|2000000|UINT64|0x00000020
+
+  ## This PCD sepcifies the start index in CMOS, it will occupy 1 bytes space.
+  gEfiUsb3DebugPortTokenSpaceGuid.PcdUsb3DebugPortBusIndex|0x59|UINT8|0x10000024
+  ## This PCD sepcifies the start index in CMOS, it will occupy 1 bytes space.
+  gEfiUsb3DebugPortTokenSpaceGuid.PcdUsb3DebugPortDeviceIndex|0x5A|UINT8|0x10000025
+  ## This PCD sepcifies the start index in CMOS, it will occupy 1 bytes space.
+  gEfiUsb3DebugPortTokenSpaceGuid.PcdUsb3DebugPortFunctionIndex|0x5B|UINT8|0x10000026
\ No newline at end of file
diff --git a/Platform/Intel/DebugFeaturePkg/DebugFeaturePkg.dsc b/Platform/Intel/DebugFeaturePkg/DebugFeaturePkg.dsc
index 351d6583d5..aeca73a8c8 100644
--- a/Platform/Intel/DebugFeaturePkg/DebugFeaturePkg.dsc
+++ b/Platform/Intel/DebugFeaturePkg/DebugFeaturePkg.dsc
@@ -22,3 +22,65 @@
   BUILD_TARGETS                  = DEBUG|RELEASE|NOOPT
   SKUID_IDENTIFIER               = DEFAULT
 
+[LibraryClasses]
+  BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
+  BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
+  PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
+  IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
+  PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf
+  UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf
+  TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf
+  PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+  DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
+
+[LibraryClasses.common.PEIM]
+  HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
+  MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
+  #Usb3DebugPortLib|DebugFeaturePkg/Library/Usb3DebugPortLib/Usb3DebugPortLibPeiIoMmu.inf
+
+[LibraryClasses.IA32.PEIM, LibraryClasses.X64.PEIM]
+  PeiServicesTablePointerLib|MdePkg/Library/PeiServicesTablePointerLibIdt/PeiServicesTablePointerLibIdt.inf
+
+[LibraryClasses.common.DXE_DRIVER]
+  HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
+  MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
+
+[LibraryClasses.common.UEFI_DRIVER]
+  HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
+  MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
+
+[LibraryClasses.common.DXE_RUNTIME_DRIVER]
+  HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
+  MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
+  UefiRuntimeLib|MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf
+
+[LibraryClasses.common.DXE_SMM_DRIVER]
+  HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
+  MemoryAllocationLib|MdePkg/Library/SmmMemoryAllocationLib/SmmMemoryAllocationLib.inf
+
+###################################################################################################
+#
+# Components Section - list of the modules and components that will be processed by compilation
+#                      tools and the EDK II tools to generate PE32/PE32+/Coff image files.
+#
+# Note: The EDK II DSC file is not used to specify how compiled binary images get placed
+#       into firmware volume images. This section is just a list of modules to compile from
+#       source into UEFI-compliant binaries.
+#       It is the FDF file that contains information on combining binary files into firmware
+#       volume images, whose concept is beyond UEFI and is described in PI specification.
+#       Binary modules do not need to be listed in this section, as they should be
+#       specified in the FDF file. For example: Shell binary (Shell_Full.efi), FAT binary (Fat.efi),
+#       Logo (Logo.bmp), and etc.
+#       There may also be modules listed in this section that are not required in the FDF file,
+#       When a module listed here is excluded from FDF file, then UEFI-compliant binary will be
+#       generated for it, but the binary will not be put into any firmware volume.
+#
+###################################################################################################
+
+[Components]
+  DebugFeaturePkg/Library/Usb3DebugPortParameterLibPcd/Usb3DebugPortParameterLibPcd.inf
+  DebugFeaturePkg/Library/Usb3DebugPortLib/Usb3DebugPortLibNull.inf
+  DebugFeaturePkg/Library/Usb3DebugPortLib/Usb3DebugPortLibPeiIoMmu.inf
+  DebugFeaturePkg/Library/Usb3DebugPortLib/Usb3DebugPortLibDxeIoMmu.inf
+  DebugFeaturePkg/Library/Usb3DebugPortLib/Usb3DebugPortLibPei.inf
+  DebugFeaturePkg/Library/Usb3DebugPortLib/Usb3DebugPortLibDxe.inf
diff --git a/Platform/Intel/DebugFeaturePkg/Include/Library/Usb3DebugPortLib.h b/Platform/Intel/DebugFeaturePkg/Include/Library/Usb3DebugPortLib.h
new file mode 100644
index 0000000000..61adf654d2
--- /dev/null
+++ b/Platform/Intel/DebugFeaturePkg/Include/Library/Usb3DebugPortLib.h
@@ -0,0 +1,76 @@
+/** @file
+  This library class provides common USB3 debug port functions.
+
+  Copyright (c) 2013 - 2019, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __USB3_DEBUG_PORT_LIB__
+#define __USB3_DEBUG_PORT_LIB__
+
+/**
+  Initialize the USB3 debug port hardware.
+
+  If no initialization is required, then return RETURN_SUCCESS.
+  If the serial device was successfully initialized, then return RETURN_SUCCESS.
+  If the serial device could not be initialized, then return RETURN_DEVICE_ERROR.
+
+  @retval RETURN_SUCCESS        The serial device was initialized.
+  @retval RETURN_DEVICE_ERROR   The serial device could not be initialized.
+
+**/
+RETURN_STATUS
+EFIAPI
+Usb3DebugPortInitialize (
+  VOID
+  );
+
+/**
+  Write data from buffer to USB3 debug port.
+
+  Writes NumberOfBytes data bytes from Buffer to the serial device.
+  The number of bytes actually written to the serial device is returned.
+  If the return value is less than NumberOfBytes, then the write operation failed.
+  If Buffer is NULL, then ASSERT().
+  If NumberOfBytes is zero, then return 0.
+
+  @param  Buffer           Pointer to the data buffer to be written.
+  @param  NumberOfBytes    Number of bytes to written to the serial device.
+
+  @retval 0                NumberOfBytes is 0.
+  @retval >0               The number of bytes written to the serial device.
+                           If this value is less than NumberOfBytes, then the read operation failed.
+
+**/
+UINTN
+EFIAPI
+Usb3DebugPortWrite (
+  IN UINT8     *Buffer,
+  IN UINTN     NumberOfBytes
+  );
+
+
+/**
+  Read data from USB3 debug port and save the datas in buffer.
+
+  Reads NumberOfBytes data bytes from a serial device into the buffer
+  specified by Buffer. The number of bytes actua
+/**
+  Polls a USB3 debug port to see if there is any data waiting to be read.
+
+  Polls a serial device to see if there is any data waiting to be read.
+  If there is data waiting to be read from the serial device, then TRUE is returned.
+  If there is no data waiting to be read from the serial device, then FALSE is returned.
+
+  @retval TRUE             Data is waiting to be read from the serial device.
+  @retval FALSE            There is no data waiting to be read from the serial device.
+
+**/
+BOOLEAN
+EFIAPI
+Usb3DebugPortPoll (
+  VOID
+  );
+
+#endif
diff --git a/Platform/Intel/DebugFeaturePkg/Include/Library/Usb3DebugPortParameterLib.h b/Platform/Intel/DebugFeaturePkg/Include/Library/Usb3DebugPortParameterLib.h
new file mode 100644
index 0000000000..167c607e9f
--- /dev/null
+++ b/Platform/Intel/DebugFeaturePkg/Include/Library/Usb3DebugPortParameterLib.h
@@ -0,0 +1,56 @@
+/** @file
+  This library class provides capability to get/set usb3 debug port parameter.
+
+  Copyright (c) 2013 - 2019, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __USB3_DEBUG_PORT_PARAMETER_LIB__
+#define __USB3_DEBUG_PORT_PARAMETER_LIB__
+
+typedef struct {
+  UINT8  Function;
+  UINT8  Device;
+  UINT8  Bus;
+} PCI_ADDRESS;
+
+typedef union {
+  UINT32       Controller;
+  PCI_ADDRESS  PciAddress;
+} USB3_DEBUG_PORT_CONTROLLER;
+
+/**
+  Returns the USB debug port controller.
+  bit:  0~ 7: Function
+  bit:  8~15: Device
+  bit: 16~24: Bus
+
+  @return  Controller information of USB debug port.
+
+**/
+UINT32
+EFIAPI
+GetUsb3DebugPortController (
+  VOID
+  );
+
+/**
+  Sets the USB debug port controller.
+  bit:  0~ 7: Function
+  bit:  8~15: Device
+  bit: 16~24: Bus
+
+  @param[in]    Controller information of USB debug port value to be set.
+
+  @retval  TRUE           The controller of USB debug port was sucessfully set.
+  @retval  FALSE          The controller of USB debug port could not be set.
+
+**/
+BOOLEAN
+EFIAPI
+SetUsb3DebugPortController (
+  UINT32        Controller
+  );
+
+#endif
diff --git a/Platform/Intel/DebugFeaturePkg/Library/Usb3DebugPortLib/MiscServices.c b/Platform/Intel/DebugFeaturePkg/Library/Usb3DebugPortLib/MiscServices.c
new file mode 100644
index 0000000000..cb29a880e6
--- /dev/null
+++ b/Platform/Intel/DebugFeaturePkg/Library/Usb3DebugPortLib/MiscServices.c
@@ -0,0 +1,385 @@
+/** @file
+  Miscellaneous services internal to USB debug port implementation.
+
+  Copyright (c) 2011 - 2019, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "Usb3DebugPortLibInternal.h"
+
+/**
+  Verifies if the bit positions specified by a mask are set in a register.
+
+  @param[in, out] Register    UNITN register
+  @param[in]      BitMask     32-bit mask
+
+  @return  BOOLEAN  - TRUE  if all bits specified by the mask are enabled.
+                    - FALSE even if one of the bits specified by the mask
+                            is not enabled.
+**/
+BOOLEAN
+XhcIsBitSet(
+  IN OUT  UINTN  Register,
+  IN      UINT32 BitMask
+  )
+{
+  if ((MmioRead32 (Register) & (BitMask)) != 0) {
+    return TRUE;
+  }
+  return FALSE;
+}
+
+/**
+  Sets bits as per the enabled bit positions in the mask.
+
+  @param[in, out] Register    UINTN register
+  @param[in]      BitMask     32-bit mask
+**/
+VOID
+XhcSetR32Bit(
+  IN OUT  UINTN  Register,
+  IN      UINT32 BitMask
+  )
+{
+  UINT32    RegisterValue;
+
+  RegisterValue = MmioRead32 (Register);
+  RegisterValue |= (UINT32)(BitMask);
+  MmioWrite32 (Register, RegisterValue);
+}
+
+/**
+  Clears bits as per the enabled bit positions in the mask.
+
+  @param[in, out] Register    UINTN register
+  @param[in]      BitMask     32-bit mask
+**/
+VOID
+XhcClrR32Bit(
+  IN OUT  UINTN  Register,
+  IN      UINT32 BitMask
+  )
+{
+  UINT32    RegisterValue;
+
+  RegisterValue = MmioRead32 (Register);
+  RegisterValue &= (UINT32)(~(BitMask));
+  MmioWrite32 (Register, RegisterValue);
+}
+
+/**
+  Initialize the USB debug port hardware.
+
+  If no initialization is required, then return RETURN_SUCCESS.
+  If the serial device was successfully initialized, then return RETURN_SUCCESS.
+  If the serial device could not be initialized, then return RETURN_DEVICE_ERROR.
+
+  @retval RETURN_SUCCESS        The serial device was initialized.
+  @retval RETURN_DEVICE_ERROR   The serial device could not be initialized.
+**/
+RETURN_STATUS
+EFIAPI
+Usb3DebugPortInitialize (
+  VOID
+  )
+{
+  USB3Initialize ();
+  return RETURN_SUCCESS;
+}
+
+/**
+  Write data from buffer to USB debug port.
+
+  Writes NumberOfBytes data bytes from Buffer to the serial device.
+  The number of bytes actually written to the serial device is returned.
+  If the return value is less than NumberOfBytes, then the write operation failed.
+  If Buffer is NULL, then ASSERT().
+  If NumberOfBytes is zero, then return 0.
+
+  @param  Buffer           Pointer to the data buffer to be written.
+  @param  NumberOfBytes    Number of bytes to written to the serial device.
+
+  @retval 0                NumberOfBytes is 0.
+  @retval >0               The number of bytes written to the serial device.
+                           If this value is less than NumberOfBytes, then the read operation failed.
+**/
+UINTN
+EFIAPI
+Usb3DebugPortWrite (
+  IN UINT8     *Buffer,
+  IN UINTN     NumberOfBytes
+  )
+{
+  Usb3DbgOut (Buffer, &NumberOfBytes);
+  return NumberOfBytes;
+}
+
+/**
+  Read data from USB debug port and save the datas in buffer.
+
+  Reads NumberOfBytes data bytes from a serial device into the buffer
+  specified by Buffer. The number of bytes actually read is returned.
+  If the return value is less than NumberOfBytes, then the rest operation failed.
+  If Buffer is NULL, then ASSERT().
+  If NumberOfBytes is zero, then return 0.
+
+  @param  Buffer           Pointer to the data buffer to store the data read from the serial device.
+  @param  NumberOfBytes    Number of bytes which will be read.
+
+  @retval 0                Read data failed, no data is to be read.
+  @retval >0               Actual number of bytes read from serial device.
+**/
+UINTN
+EFIAPI
+Usb3DebugPortRead (
+  OUT UINT8   *Buffer,
+  IN  UINTN   NumberOfBytes
+  )
+{
+  Usb3DbgIn (Buffer, &NumberOfBytes);
+  return NumberOfBytes;
+}
+
+/**
+  Polls a USB debug port to see if there is any data waiting to be read.
+
+  Polls a serial device to see if there is any data waiting to be read.
+  If there is data waiting to be read from the serial device, then TRUE is returned.
+  If there is no data waiting to be read from the serial device, then FALSE is returned.
+
+  @retval TRUE             Data is waiting to be read from the serial device.
+  @retval FALSE            There is no data waiting to be read from the serial device.
+**/
+BOOLEAN
+EFIAPI
+Usb3DebugPortPoll (
+  VOID
+  )
+{
+  return FALSE;
+}
+
+/**
+  Write the data to the XHCI debug register.
+
+  @param  Xhc          The XHCI Instance.
+  @param  Offset       The offset of the runtime register.
+  @param  Data         The data to write.
+
+**/
+VOID
+XhcWriteDebugReg (
+  IN USB3_DEBUG_PORT_INSTANCE *Xhc,
+  IN UINT32                   Offset,
+  IN UINT32                   Data
+  )
+{
+  EFI_PHYSICAL_ADDRESS  DebugCapabilityBase;
+
+  DebugCapabilityBase = Xhc->DebugCapabilityBase;
+
+  MmioWrite32 ((UINTN)(DebugCapabilityBase + Offset), Data);
+
+  return;
+}
+
+/**
+  Read XHCI debug register.
+
+  @param  Xhc          The XHCI Instance.
+  @param  Offset       The offset of the debug register.
+
+  @return The register content read
+
+**/
+UINT32
+XhcReadDebugReg (
+  IN  USB3_DEBUG_PORT_INSTANCE *Xhc,
+  IN  UINT32                   Offset
+  )
+{
+  UINT32                  Data;
+  EFI_PHYSICAL_ADDRESS    DebugCapabilityBase;
+
+  DebugCapabilityBase = Xhc->DebugCapabilityBase;
+
+  Data = MmioRead32 ((UINTN)(DebugCapabilityBase + Offset));
+
+  return Data;
+}
+
+/**
+  Set one bit of the debug register while keeping other bits.
+
+  @param  Xhc          The XHCI Instance.
+  @param  Offset       The offset of the debug register.
+  @param  Bit          The bit mask of the register to set.
+
+**/
+VOID
+XhcSetDebugRegBit (
+  IN USB3_DEBUG_PORT_INSTANCE *Xhc,
+  IN UINT32                   Offset,
+  IN UINT32                   Bit
+  )
+{
+  UINT32                  Data;
+
+  Data  = XhcReadDebugReg (Xhc, Offset);
+  Data |= Bit;
+  XhcWriteDebugReg (Xhc, Offset, Data);
+}
+
+/**
+  Clear one bit of the debug register while keeping other bits.
+
+  @param  Xhc          The XHCI Instance.
+  @param  Offset       The offset of the debug register.
+  @param  Bit          The bit mask of the register to set.
+
+**/
+VOID
+XhcClearDebugRegBit (
+  IN USB3_DEBUG_PORT_INSTANCE *Xhc,
+  IN UINT32                   Offset,
+  IN UINT32                   Bit
+  )
+{
+  UINT32                  Data;
+
+  Data  = XhcReadDebugReg (Xhc, Offset);
+  Data  &= ~Bit;
+  XhcWriteDebugReg (Xhc, Offset, Data);
+}
+
+/**
+  Write the data to the XHCI MMIO register.
+
+  @param  Xhc          The XHCI Instance.
+  @param  Offset       The offset of the runtime register.
+  @param  Data         The data to write.
+
+**/
+VOID
+XhcWriteMmioReg (
+  IN USB3_DEBUG_PORT_INSTANCE *Xhc,
+  IN UINT32                   Offset,
+  IN UINT32                   Data
+  )
+{
+  EFI_PHYSICAL_ADDRESS    MmioBase;
+
+  MmioBase = Xhc->XhcMmioBase;
+  MmioWrite32 ((UINTN)(MmioBase + Offset), Data);
+
+  return;
+}
+
+/**
+  Read XHCI MMIO register.
+
+  @param  Xhc          The XHCI Instance.
+  @param  Offset       The offset of the runtime register.
+
+  @return The register content read
+
+**/
+UINT32
+XhcReadMmioReg (
+  IN  USB3_DEBUG_PORT_INSTANCE *Xhc,
+  IN  UINT32                   Offset
+  )
+{
+  UINT32                  Data;
+  EFI_PHYSICAL_ADDRESS    MmioBase;
+
+  MmioBase = Xhc->XhcMmioBase;
+
+  Data = MmioRead32 ((UINTN)(MmioBase + Offset));
+
+  return Data;
+}
+
+/**
+  Set one bit of the operational register while keeping other bits.
+
+  @param  Xhc          The XHCI Instance.
+  @param  Offset       The offset of the runtime register.
+  @param  Bit          The bit mask of the register to set.
+
+**/
+VOID
+XhcSetMmioRegBit (
+  IN USB3_DEBUG_PORT_INSTANCE   *Xhc,
+  IN UINT32                     Offset,
+  IN UINT32                     Bit
+  )
+{
+  UINT32                  Data;
+
+  Data  = XhcReadMmioReg (Xhc, Offset);
+  Data |= Bit;
+  XhcWriteMmioReg (Xhc, Offset, Data);
+}
+
+/**
+  Clear one bit of the operational register while keeping other bits.
+
+  @param  Xhc          The XHCI Instance.
+  @param  Offset       The offset of the runtime register.
+  @param  Bit          The bit mask of the register to set.
+
+**/
+VOID
+XhcClearMmioRegBit (
+  IN USB3_DEBUG_PORT_INSTANCE   *Xhc,
+  IN UINT32                     Offset,
+  IN UINT32                     Bit
+  )
+{
+  UINT32                  Data;
+
+  Data  = XhcReadMmioReg (Xhc, Offset);
+  Data  &= ~Bit;
+  XhcWriteMmioReg (Xhc, Offset, Data);
+}
+
+/**
+  Wait the operation register's bit as specified by Bit
+  to be set (or clear).
+
+  @param  Xhc          The XHCI Instance.
+  @param  Offset       The offset of the operational register.
+  @param  Bit          The bit of the register to wait for.
+  @param  WaitToSet    Wait the bit to set or clear.
+  @param  Timeout      The time to wait before abort (in millisecond, ms).
+
+  @retval EFI_SUCCESS  The bit successfully changed by host controller.
+  @retval EFI_TIMEOUT  The time out occurred.
+
+**/
+EFI_STATUS
+XhcWaitMmioRegBit (
+  IN USB3_DEBUG_PORT_INSTANCE *Xhc,
+  IN UINT32                   Offset,
+  IN UINT32                   Bit,
+  IN BOOLEAN                  WaitToSet,
+  IN UINT32                   Timeout
+  )
+{
+  UINT32                  Index;
+  UINTN                   Loop;
+
+  Loop   = (Timeout * XHC_1_MILLISECOND / XHC_POLL_DELAY) + 1;
+
+  for (Index = 0; Index < Loop; Index++) {
+    if (XHC_REG_BIT_IS_SET (Xhc, Offset, Bit) == WaitToSet) {
+      return EFI_SUCCESS;
+    }
+
+    MicroSecondDelay (XHC_POLL_DELAY);
+  }
+
+  return EFI_TIMEOUT;
+}
diff --git a/Platform/Intel/DebugFeaturePkg/Library/Usb3DebugPortLib/Usb3DebugPortDataTransfer.c b/Platform/Intel/DebugFeaturePkg/Library/Usb3DebugPortLib/Usb3DebugPortDataTransfer.c
new file mode 100644
index 0000000000..53478a49b8
--- /dev/null
+++ b/Platform/Intel/DebugFeaturePkg/Library/Usb3DebugPortLib/Usb3DebugPortDataTransfer.c
@@ -0,0 +1,892 @@
+/** @file
+  Usb3 Debug Port library instance
+
+  Copyright (c) 2013 - 2019, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Base.h>
+
+#include <PiPei.h>
+#include <Library/SerialPortLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PciLib.h>
+#include <Library/PcdLib.h>
+#include <Library/TimerLib.h>
+#include <Library/Usb3DebugPortParameterLib.h>
+#include "Usb3DebugPortLibInternal.h"
+
+EFI_SMRAM_DESCRIPTOR        mSmramCheckRanges[MAX_SMRAM_RANGE];
+UINTN                       mSmramCheckRangeCount = 0;
+BOOLEAN                     mUsb3InSmm            = FALSE;
+UINT64                      mUsb3MmioSize         = 0;
+
+/**
+  Synchronize the specified transfer ring to update the enqueue and dequeue pointer.
+
+  @param  Xhc         The XHCI Instance.
+  @param  TrsRing     The transfer ring to sync.
+
+  @retval EFI_SUCCESS The transfer ring is synchronized successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+XhcSyncTrsRing (
+  IN USB3_DEBUG_PORT_INSTANCE  *Xhc,
+  IN TRANSFER_RING             *TrsRing
+  )
+{
+  UINTN               Index;
+  TRB_TEMPLATE        *TrsTrb;
+
+  ASSERT (TrsRing != NULL);
+
+  //
+  // Calculate the latest RingEnqueue and RingPCS
+  //
+  TrsTrb = (TRB_TEMPLATE *)(UINTN) TrsRing->RingEnqueue;
+
+  ASSERT (TrsTrb != NULL);
+
+  for (Index = 0; Index < TrsRing->TrbNumber; Index++) {
+    if (TrsTrb->CycleBit != (TrsRing->RingPCS & BIT0)) {
+      break;
+    }
+    TrsTrb++;
+    if ((UINT8) TrsTrb->Type == TRB_TYPE_LINK) {
+      ASSERT (((LINK_TRB*)TrsTrb)->TC != 0);
+      //
+      // set cycle bit in Link TRB as normal
+      //
+      ((LINK_TRB*)TrsTrb)->CycleBit = TrsRing->RingPCS & BIT0;
+      //
+      // Toggle PCS maintained by software
+      //
+      TrsRing->RingPCS = (TrsRing->RingPCS & BIT0) ? 0 : 1;
+      TrsTrb           = (TRB_TEMPLATE *)(UINTN)((TrsTrb->Parameter1 | LShiftU64 ((UINT64)TrsTrb->Parameter2, 32)) & ~0x0F);
+    }
+  }
+  ASSERT (Index != TrsRing->TrbNumber);
+
+  if ((EFI_PHYSICAL_ADDRESS)(UINTN) TrsTrb != TrsRing->RingEnqueue) {
+    TrsRing->RingEnqueue = (EFI_PHYSICAL_ADDRESS)(UINTN) TrsTrb;
+  }
+
+  //
+  // Clear the Trb context for enqueue, but reserve the PCS bit
+  //
+  TrsTrb->Parameter1 = 0;
+  TrsTrb->Parameter2 = 0;
+  TrsTrb->Status     = 0;
+  TrsTrb->RsvdZ1     = 0;
+  TrsTrb->Type       = 0;
+  TrsTrb->Control    = 0;
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Synchronize the specified event ring to update the enqueue and dequeue pointer.
+
+  @param  Xhc         The XHCI Instance.
+  @param  EvtRing     The event ring to sync.
+
+  @retval EFI_SUCCESS The event ring is synchronized successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+XhcSyncEventRing (
+  IN USB3_DEBUG_PORT_INSTANCE  *Xhc,
+  IN EVENT_RING                *EvtRing
+  )
+{
+  UINTN               Index;
+  TRB_TEMPLATE        *EvtTrb1;
+
+  ASSERT (EvtRing != NULL);
+
+  //
+  // Calculate the EventRingEnqueue and EventRingCCS.
+  // Note: only support single Segment
+  //
+  EvtTrb1 = (TRB_TEMPLATE *)(UINTN) EvtRing->EventRingDequeue;
+
+  for (Index = 0; Index < EvtRing->TrbNumber; Index++) {
+    if (EvtTrb1->CycleBit != EvtRing->EventRingCCS) {
+      break;
+    }
+
+    EvtTrb1++;
+
+    if ((UINTN)EvtTrb1 >= ((UINTN) EvtRing->EventRingSeg0 + sizeof (TRB_TEMPLATE) * EvtRing->TrbNumber)) {
+      EvtTrb1 = (TRB_TEMPLATE *)(UINTN) EvtRing->EventRingSeg0;
+      EvtRing->EventRingCCS = (EvtRing->EventRingCCS) ? 0 : 1;
+    }
+  }
+
+  if (Index < EvtRing->TrbNumber) {
+    EvtRing->EventRingEnqueue = (EFI_PHYSICAL_ADDRESS)(UINTN)EvtTrb1;
+  } else {
+    ASSERT (FALSE);
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Check if there is a new generated event.
+
+  @param  Xhc           The XHCI Instance.
+  @param  EvtRing       The event ring to check.
+  @param  NewEvtTrb     The new event TRB found.
+
+  @retval EFI_SUCCESS   Found a new event TRB at the event ring.
+  @retval EFI_NOT_READY The event ring has no new event.
+
+**/
+EFI_STATUS
+EFIAPI
+XhcCheckNewEvent (
+  IN  USB3_DEBUG_PORT_INSTANCE *Xhc,
+  IN  EVENT_RING               *EvtRing,
+  OUT TRB_TEMPLATE             **NewEvtTrb
+  )
+{
+  EFI_STATUS          Status;
+
+  ASSERT (EvtRing != NULL);
+
+  *NewEvtTrb = (TRB_TEMPLATE *)(UINTN) EvtRing->EventRingDequeue;
+
+  if (EvtRing->EventRingDequeue == EvtRing->EventRingEnqueue) {
+    return EFI_NOT_READY;
+  }
+
+  Status = EFI_SUCCESS;
+
+  EvtRing->EventRingDequeue += sizeof (TRB_TEMPLATE);
+  //
+  // If the dequeue pointer is beyond the ring, then roll-back it to the begining of the ring.
+  //
+  if ((UINTN)EvtRing->EventRingDequeue >= ((UINTN) EvtRing->EventRingSeg0 + sizeof (TRB_TEMPLATE) * EvtRing->TrbNumber)) {
+    EvtRing->EventRingDequeue = EvtRing->EventRingSeg0;
+  }
+
+  return Status;
+}
+
+/**
+  Check if the Trb is a transaction of the URB.
+
+  @param Trb    The TRB to be checked
+  @param Urb    The transfer ring to be checked.
+
+  @retval TRUE  It is a transaction of the URB.
+  @retval FALSE It is not any transaction of the URB.
+
+**/
+BOOLEAN
+IsTransferRingTrb (
+  IN  TRB_TEMPLATE        *Trb,
+  IN  URB                 *Urb
+  )
+{
+  TRB_TEMPLATE  *CheckedTrb;
+  TRANSFER_RING *Ring;
+  UINTN         Index;
+
+  Ring = (TRANSFER_RING *)(UINTN) Urb->Ring;
+  CheckedTrb = (TRB_TEMPLATE *)(UINTN) Ring->RingSeg0;
+
+  ASSERT (Ring->TrbNumber == CMD_RING_TRB_NUMBER || Ring->TrbNumber == TR_RING_TRB_NUMBER);
+
+  for (Index = 0; Index < Ring->TrbNumber; Index++) {
+    if (Trb == CheckedTrb) {
+      return TRUE;
+    }
+    CheckedTrb++;
+  }
+
+  return FALSE;
+}
+
+/**
+  Check the URB's execution result and update the URB's
+  result accordingly.
+
+  @param  Xhc             The XHCI Instance.
+  @param  Urb             The URB to check result.
+
+  @return Whether the result of URB transfer is finialized.
+
+**/
+EFI_STATUS
+XhcCheckUrbResult (
+  IN  USB3_DEBUG_PORT_INSTANCE *Xhc,
+  IN  URB                      *Urb
+  )
+{
+  EVT_TRB_TRANSFER        *EvtTrb;
+  TRB_TEMPLATE            *TRBPtr;
+  UINTN                   Index;
+  UINT8                   TRBType;
+  EFI_STATUS              Status;
+  URB                     *CheckedUrb;
+  UINT64                  XhcDequeue;
+  UINT32                  High;
+  UINT32                  Low;
+
+  ASSERT ((Xhc != NULL) && (Urb != NULL));
+
+  Status   = EFI_SUCCESS;
+
+  if (Urb->Finished) {
+    goto EXIT;
+  }
+
+  EvtTrb = NULL;
+
+  //
+  // Traverse the event ring to find out all new events from the previous check.
+  //
+  XhcSyncEventRing (Xhc, &Xhc->EventRing);
+
+  for (Index = 0; Index < Xhc->EventRing.TrbNumber; Index++) {
+    Status = XhcCheckNewEvent (Xhc, &Xhc->EventRing, ((TRB_TEMPLATE **)&EvtTrb));
+    if (Status == EFI_NOT_READY) {
+      //
+      // All new events are handled, return directly.
+      //
+      goto EXIT;
+    }
+    //
+    // Only handle COMMAND_COMPLETETION_EVENT and TRANSFER_EVENT.
+    //
+    if ((EvtTrb->Type != TRB_TYPE_COMMAND_COMPLT_EVENT) && (EvtTrb->Type != TRB_TYPE_TRANS_EVENT)) {
+      continue;
+    }
+
+    TRBPtr = (TRB_TEMPLATE *)(UINTN)(EvtTrb->TRBPtrLo | LShiftU64 ((UINT64) EvtTrb->TRBPtrHi, 32));
+
+    //
+    // Update the status of Urb according to the finished event regardless of whether
+    // the urb is current checked one or in the XHCI's async transfer list.
+    // This way is used to avoid that those completed async transfer events don't get
+    // handled in time and are flushed by newer coming events.
+    //
+    if (IsTransferRingTrb (TRBPtr, Urb)) {
+      CheckedUrb = Urb;
+    } else {
+      continue;
+    }
+    switch (EvtTrb->Completecode) {
+      case TRB_COMPLETION_STALL_ERROR:
+        CheckedUrb->Result  |= EFI_USB_ERR_STALL;
+        CheckedUrb->Finished = TRUE;
+        break;
+
+      case TRB_COMPLETION_BABBLE_ERROR:
+        CheckedUrb->Result  |= EFI_USB_ERR_BABBLE;
+        CheckedUrb->Finished = TRUE;
+        break;
+
+      case TRB_COMPLETION_DATA_BUFFER_ERROR:
+        CheckedUrb->Result  |= EFI_USB_ERR_BUFFER;
+        CheckedUrb->Finished = TRUE;
+        break;
+
+      case TRB_COMPLETION_USB_TRANSACTION_ERROR:
+        CheckedUrb->Result  |= EFI_USB_ERR_TIMEOUT;
+        CheckedUrb->Finished = TRUE;
+        break;
+
+      case TRB_COMPLETION_SHORT_PACKET:
+      case TRB_COMPLETION_SUCCESS:
+        if (EvtTrb->Completecode == TRB_COMPLETION_SHORT_PACKET) {
+        }
+
+        TRBType = (UINT8) (TRBPtr->Type);
+        if ((TRBType == TRB_TYPE_DATA_STAGE) ||
+            (TRBType == TRB_TYPE_NORMAL) ||
+            (TRBType == TRB_TYPE_ISOCH)) {
+          CheckedUrb->Completed += (CheckedUrb->DataLen - EvtTrb->Length);
+        }
+
+        break;
+
+      default:
+        CheckedUrb->Result  |= EFI_USB_ERR_TIMEOUT;
+        CheckedUrb->Finished = TRUE;
+        break;
+    }
+
+    //
+    // Only check first and end Trb event address
+    //
+
+    if ((EFI_PHYSICAL_ADDRESS)(UINTN) TRBPtr == CheckedUrb->TrbStart) {
+      CheckedUrb->StartDone = TRUE;
+    }
+
+    if ((EFI_PHYSICAL_ADDRESS)(UINTN) TRBPtr == CheckedUrb->TrbEnd) {
+      CheckedUrb->EndDone = TRUE;
+    }
+
+    if (CheckedUrb->StartDone && CheckedUrb->EndDone) {
+      CheckedUrb->Finished = TRUE;
+    }
+
+  }
+
+EXIT:
+  //
+  // Advance event ring to last available entry
+  //
+  // Some 3rd party XHCI external cards don't support single 64-bytes width register access,
+  // So divide it to two 32-bytes width register access.
+  //
+  Low  = XhcReadDebugReg (Xhc, XHC_DC_DCERDP);
+  High = XhcReadDebugReg (Xhc, XHC_DC_DCERDP + 4);
+  XhcDequeue = (UINT64)(LShiftU64((UINT64)High, 32) | Low);
+
+  if ((XhcDequeue & (~0x0F)) != ((UINT64)(UINTN)Xhc->EventRing.EventRingDequeue & (~0x0F))) {
+    //
+    // Some 3rd party XHCI external cards don't support single 64-bytes width register access,
+    // So divide it to two 32-bytes width register access.
+    //
+    XhcWriteDebugReg (Xhc, XHC_DC_DCERDP, XHC_LOW_32BIT (Xhc->EventRing.EventRingDequeue));
+    XhcWriteDebugReg (Xhc, XHC_DC_DCERDP + 4, XHC_HIGH_32BIT (Xhc->EventRing.EventRingDequeue));
+  }
+
+  return Status;
+}
+
+/**
+  Ring the door bell to notify XHCI there is a transaction to be executed.
+
+  @param  Xhc           The XHCI Instance.
+  @param  Urb           The pointer to URB.
+
+  @retval EFI_SUCCESS   Successfully ring the door bell.
+
+**/
+EFI_STATUS
+EFIAPI
+XhcRingDoorBell (
+  IN USB3_DEBUG_PORT_INSTANCE  *Xhc,
+  IN URB                       *Urb
+  )
+{
+  UINT32      Dcdb;
+
+  //
+  // 7.6.8.2 DCDB Register
+  //
+  if (Urb->Direction == EfiUsbDataIn) {
+    Dcdb = 0x100;
+  } else {
+    Dcdb = 0x0;
+  }
+
+  XhcWriteDebugReg (
+    Xhc,
+    XHC_DC_DCDB,
+    Dcdb
+    );
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Execute the transfer by polling the URB. This is a synchronous operation.
+
+  @param  Xhc               The XHCI Instance.
+  @param  Urb               The URB to execute.
+  @param  Timeout           The time to wait before abort, in millisecond.
+
+  @return EFI_DEVICE_ERROR  The transfer failed due to transfer error.
+  @return EFI_TIMEOUT       The transfer failed due to time out.
+  @return EFI_SUCCESS       The transfer finished OK.
+
+**/
+EFI_STATUS
+XhcExecTransfer (
+  IN  USB3_DEBUG_PORT_INSTANCE *Xhc,
+  IN  URB                      *Urb,
+  IN  UINTN                    Timeout
+  )
+{
+  EFI_STATUS              Status;
+  UINTN                   Index;
+  UINTN                   Loop;
+  TRB_TEMPLATE            *Trb;
+  TRANSFER_RING           *Ring;
+  TRB_TEMPLATE            *TrbStart;
+  TRB_TEMPLATE            *TrbEnd;
+
+  Status = EFI_SUCCESS;
+
+  Loop   = (Timeout * XHC_1_MILLISECOND / XHC_POLL_DELAY) + 1;
+  if (Timeout == 0) {
+    Loop = 0xFFFFFFFF;
+  }
+  XhcRingDoorBell (Xhc, Urb);
+  //
+  // DSCT BIT0: Event Ring Not Empty bit can only be set to 1 by XHC after ringing door bell with some delay.
+  //
+
+  for (Index = 0; Index < Loop; Index++) {
+    Status = XhcCheckUrbResult (Xhc, Urb);
+    if (Urb->Finished) {
+      break;
+    }
+    MicroSecondDelay (XHC_POLL_DELAY);
+  }
+  if (Index == Loop) {
+    Urb->Result = EFI_USB_ERR_TIMEOUT;
+  }
+
+  //
+  // If URB transfer is error, restore transfer ring to original value before URB transfer
+  // This will make the current transfer TRB is always at the latest unused one in transfer ring.
+  // Without this code, when there is read TRB from target, but host does not write anything, this TRB (A)
+  // will be still here, next read TRB (B) will be put next to TRB (A), when host write then, the TRB (A)
+  // will be used to contain data, not TRB(B), this will cause Finished flag will not be set and return error in this function.
+  //
+  Ring = (TRANSFER_RING *)(UINTN) Urb->Ring;
+  if (Urb->Result != EFI_USB_NOERROR) {
+    Ring->RingEnqueue = Urb->TrbStart;
+    //
+    // Clear CCS flag for next use
+    //
+    TrbStart = (TRB_TEMPLATE *)(UINTN) Urb->TrbStart;
+    TrbEnd   = (TRB_TEMPLATE *)(UINTN) Urb->TrbEnd;
+    for (Trb = TrbStart; Trb <= TrbEnd; Trb++) {
+      Trb->CycleBit = ((~Ring->RingPCS) & BIT0);
+    }
+  }
+  return Status;
+}
+
+/**
+  Create a transfer TRB.
+
+  @param  Xhc     The XHCI Instance
+  @param  Urb     The urb used to construct the transfer TRB.
+
+  @return Created TRB or NULL
+
+**/
+EFI_STATUS
+XhcCreateTransferTrb (
+  IN USB3_DEBUG_PORT_INSTANCE   *Xhc,
+  IN URB                        *Urb
+  )
+{
+  TRANSFER_RING                 *EPRing;
+  TRB                           *TrbStart;
+  UINT32                        TotalLen;
+  UINT32                        Len;
+  UINT32                        TrbNum;
+
+  Urb->Finished  = FALSE;
+  Urb->StartDone = FALSE;
+  Urb->EndDone   = FALSE;
+  Urb->Completed = 0;
+  Urb->Result    = EFI_USB_NOERROR;
+
+  if (Urb->Direction == EfiUsbDataIn) {
+    EPRing    = &Xhc->TransferRingIn;
+  } else {
+    EPRing    = &Xhc->TransferRingOut;
+  }
+
+  Urb->Ring = (EFI_PHYSICAL_ADDRESS)(UINTN) EPRing;
+  //
+  // Construct the TRB for ED_BULK_OUT and ED_BULK_IN
+  //
+  XhcSyncTrsRing (Xhc, EPRing);
+
+  Urb->TrbStart = EPRing->RingEnqueue;
+
+  TotalLen = 0;
+  Len      = 0;
+  TrbNum   = 0;
+  TrbStart = (TRB *)(UINTN)EPRing->RingEnqueue;
+
+  while (TotalLen < Urb->DataLen) {
+    if ((TotalLen + 0x10000) >= Urb->DataLen) {
+      Len = Urb->DataLen - TotalLen;
+    } else {
+      Len = 0x10000;
+    }
+    TrbStart = (TRB *)(UINTN)EPRing->RingEnqueue;
+    TrbStart->TrbNormal.TRBPtrLo  = XHC_LOW_32BIT(Urb->Data + TotalLen);
+    TrbStart->TrbNormal.TRBPtrHi  = XHC_HIGH_32BIT(Urb->Data + TotalLen);
+    TrbStart->TrbNormal.Length    = Len;
+    TrbStart->TrbNormal.TDSize    = 0;
+    TrbStart->TrbNormal.IntTarget = 0;
+    TrbStart->TrbNormal.ISP       = 1;
+    TrbStart->TrbNormal.IOC       = 1;
+    TrbStart->TrbNormal.Type      = TRB_TYPE_NORMAL;
+
+    //
+    // Update the cycle bit
+    //
+    TrbStart->TrbNormal.CycleBit = EPRing->RingPCS & BIT0;
+
+    XhcSyncTrsRing (Xhc, EPRing);
+    TrbNum++;
+    TotalLen += Len;
+  }
+
+  Urb->TrbNum = TrbNum;
+
+  //
+  // Update to the last TRB
+  //
+  Urb->TrbEnd = (EFI_PHYSICAL_ADDRESS)(UINTN) TrbStart;
+  return EFI_SUCCESS;
+}
+
+/**
+  Create a new URB for a new transaction.
+
+  @param  Xhc        The XHCI Instance
+  @param  Direction  The direction of data flow.
+  @param  Data       The user data to transfer
+  @param  DataLen    The length of data buffer
+
+  @return Created URB or NULL
+
+**/
+URB*
+XhcCreateUrb (
+  IN USB3_DEBUG_PORT_INSTANCE           *Xhc,
+  IN EFI_USB_DATA_DIRECTION             Direction,
+  IN VOID                               *Data,
+  IN UINTN                              DataLen
+  )
+{
+  EFI_STATUS                    Status;
+  URB                           *Urb;
+  EFI_PHYSICAL_ADDRESS          DataAddress;
+
+  Urb = &Xhc->Urb;
+  ASSERT (Urb->Data != 0);
+  DataAddress = Urb->Data;
+  ZeroMem (Urb, sizeof (URB));
+
+  Urb->Signature = USB3_DEBUG_PORT_INSTANCE_SIGNATURE;
+  Urb->Direction = Direction;
+  Urb->Data = DataAddress;
+
+  ZeroMem ((VOID*)(UINTN) Urb->Data, DataLen);
+  CopyMem ((VOID*)(UINTN) Urb->Data, Data, DataLen);
+
+  Urb->DataLen  = (UINT32) DataLen;
+  Status = XhcCreateTransferTrb (Xhc, Urb);
+  ASSERT_EFI_ERROR (Status);
+
+  return Urb;
+}
+
+/**
+  Submits bulk transfer to a bulk endpoint of a USB device.
+
+  @param  Xhc                   The instance of debug device.
+  @param  Direction             The direction of data transfer.
+  @param  Data                  Array of pointers to the buffers of data to transmit
+                                from or receive into.
+  @param  DataLength            The lenght of the data buffer.
+  @param  Timeout               Indicates the maximum time, in millisecond, which
+                                the transfer is allowed to complete.
+  @param  TransferResult        Transfer result.
+
+  @retval EFI_SUCCESS           The transfer was completed successfully.
+  @retval EFI_OUT_OF_RESOURCES  The transfer failed due to lack of resource.
+  @retval EFI_INVALID_PARAMETER Some parameters are invalid.
+  @retval EFI_TIMEOUT           The transfer failed due to timeout.
+  @retval EFI_DEVICE_ERROR      The transfer failed due to host controller error.
+
+**/
+EFI_STATUS
+EFIAPI
+XhcDataTransfer (
+  IN     USB3_DEBUG_PORT_INSTANCE            *Xhc,
+  IN     EFI_USB_DATA_DIRECTION              Direction,
+  IN OUT VOID                                *Data,
+  IN OUT UINTN                               *DataLength,
+  IN     UINTN                               Timeout,
+  OUT    UINT32                              *TransferResult
+  )
+{
+  URB                     *Urb;
+  EFI_STATUS              Status;
+
+  //
+  // Validate the parameters
+  //
+  if ((DataLength == NULL) || (*DataLength == 0) ||
+      (Data == NULL) || (TransferResult == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  *TransferResult = EFI_USB_ERR_SYSTEM;
+  Status          = EFI_DEVICE_ERROR;
+
+  //
+  // Create a new URB, insert it into the asynchronous
+  // schedule list, then poll the execution status.
+  //
+  Urb = XhcCreateUrb (Xhc, Direction, Data, *DataLength);
+
+  if (Urb == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto ON_EXIT;
+  }
+
+  Status = XhcExecTransfer (Xhc, Urb, Timeout);
+
+  *TransferResult = Urb->Result;
+  *DataLength     = Urb->Completed;
+
+  if (*TransferResult == EFI_USB_NOERROR) {
+    Status = EFI_SUCCESS;
+  }
+
+ON_EXIT:
+
+  return Status;
+}
+
+/**
+  Check whether the MMIO Bar is within any of the SMRAM ranges.
+
+  @param[in]  XhcMmioBase  The address of the MMIO to be checked.
+
+  @retval     TURE         The XHCI MMIO is in SMRAM ranges.
+  @retval     FALSE        The XHCI MMIO is out of SMRAM ranges.
+**/
+BOOLEAN
+EFIAPI
+Usb3DebugIsAddressInSmram (
+  IN EFI_PHYSICAL_ADDRESS   XhcMmioBase
+  )
+{
+  UINTN                       Index;
+
+  if (mSmramCheckRangeCount == 0) {
+    //
+    // When we invoke this function, we are already in SMM mode,
+    // but SmmAccess->GetCapabilities failed which kept mSmramCheckRanges as 0.
+    //
+    return TRUE;
+  }
+
+  for (Index = 0; Index < mSmramCheckRangeCount; Index ++) {
+    if (((XhcMmioBase >= mSmramCheckRanges[Index].CpuStart) && (XhcMmioBase < mSmramCheckRanges[Index].CpuStart + mSmramCheckRanges[Index].PhysicalSize)) ||
+        ((mSmramCheckRanges[Index].CpuStart >= XhcMmioBase) && (mSmramCheckRanges[Index].CpuStart < XhcMmioBase + mUsb3MmioSize))) {
+      return TRUE;
+    }
+  }
+
+  return FALSE;
+}
+
+/**
+  Transfer data via XHC controller.
+
+  @param  Data         Data buffer.
+  @param  Length       Data length.
+  @param  Direction    Transfer direction.
+
+**/
+VOID
+Usb3DebugPortDataTransfer (
+  UINT8                   *Data,
+  UINTN                   *Length,
+  EFI_USB_DATA_DIRECTION  Direction
+  )
+{
+  USB3_DEBUG_PORT_INSTANCE        *Instance;
+  EFI_PHYSICAL_ADDRESS            XhcMmioBase;
+  UINT16                          Command;
+  UINT8                           Bus;
+  UINT8                           Device;
+  UINT8                           Function;
+  UINT32                          TransferResult;
+  UINT32                          Dcctrl;
+  EFI_PHYSICAL_ADDRESS            UsbBase;
+  UINTN                           BytesToSend;
+  USB3_DEBUG_PORT_CONTROLLER      UsbDebugPort;
+  EFI_STATUS                      Status;
+  USB3_DEBUG_PORT_INSTANCE        UsbDbgInstance;
+
+  UsbDebugPort.Controller = GetUsb3DebugPortController();
+  Bus      = UsbDebugPort.PciAddress.Bus;
+  Device   = UsbDebugPort.PciAddress.Device;
+  Function = UsbDebugPort.PciAddress.Function;
+
+  //
+  // MMIO base address is possible to clear, set it if it is cleared. (XhciMemorySpaceClose in PchUsbCommon.c)
+  //
+  XhcMmioBase = GetXhciBaseAddress ();
+  Command     = GetXhciPciCommand ();
+
+  if ((XhcMmioBase == 0) || (XhcMmioBase == XHCI_BASE_ADDRESS_64_BIT_MASK)) {
+    //
+    // XHCI device MMIO base is cleared by someone, set it again
+    //
+    UsbBase  = PcdGet32 (PcdXhciDefaultBaseAddress);
+    PciWrite32 (PCI_LIB_ADDRESS(Bus, Device, Function, PCI_BASE_ADDRESSREG_OFFSET), (UINT32)UsbBase);
+    PciWrite32 (PCI_LIB_ADDRESS(Bus, Device, Function, PCI_BASE_ADDRESSREG_OFFSET + 4), 0x0);
+    UsbBase = PciRead32 (PCI_LIB_ADDRESS(Bus, Device, Function, PCI_BASE_ADDRESSREG_OFFSET)) & XHCI_BASE_ADDRESS_32_BIT_MASK;
+    if (UsbBase == 0 || UsbBase == XHCI_BASE_ADDRESS_32_BIT_MASK) {
+      return;
+    }
+  }
+
+  //
+  // Check if XHC debug MMIO range is in SMRAM
+  //
+  if ((mUsb3InSmm) && (Usb3DebugIsAddressInSmram (XhcMmioBase))) {
+    return;
+  }
+
+  //
+  // Save and set Command Register
+  //
+  if (((Command & EFI_PCI_COMMAND_MEMORY_SPACE) == 0) || ((Command & EFI_PCI_COMMAND_BUS_MASTER) == 0)) {
+    PciWrite16(PCI_LIB_ADDRESS(Bus, Device, Function, PCI_COMMAND_OFFSET), Command | EFI_PCI_COMMAND_MEMORY_SPACE | EFI_PCI_COMMAND_BUS_MASTER);
+    PciRead16(PCI_LIB_ADDRESS(Bus, Device, Function, PCI_COMMAND_OFFSET));
+  }
+
+  Instance = GetUsb3DebugPortInstance ();
+
+  if (Instance != NULL) {
+    if (!Instance->DebugSupport) {
+      //
+      // Debug device is not supported by XHCI, return
+      //
+      goto Done;
+    }
+  }
+
+  if ((Instance != NULL) && (Instance->Ready)) {
+    //
+    // Debug device is broken suddently (e.g. Windows OS), return
+    //
+    Dcctrl = XhcReadDebugReg (Instance, XHC_DC_DCCTRL);
+    if ((Dcctrl & BIT0) == 0) {
+      goto Done;
+    }
+  }
+
+  if ((Instance != NULL) && (!Instance->Ready)) {
+    //
+    // Debug host does not connect with target
+    //
+    goto Done;
+  }
+
+  if (Instance == NULL) {
+    ZeroMem (&UsbDbgInstance, sizeof (USB3_DEBUG_PORT_INSTANCE));
+    DiscoverUsb3DebugPort (&UsbDbgInstance);
+    if (UsbDbgInstance.DebugSupport) {
+      if (!IsAllocatePagesReady ()) {
+        //
+        // AllocatePages can not work, return
+        //
+        goto Done;
+      }
+    }
+    Status = USB3InitializeReal ();
+    if (EFI_ERROR (Status)) {
+      //
+      // Debug device is failed to initialize
+      //
+      goto Done;
+    }
+
+    //
+    // Update instance
+    //
+    Instance = GetUsb3DebugPortInstance ();
+
+    if (Instance == NULL) {
+      //
+      // Debug device instance is failed to create
+      //
+      goto Done;
+    }
+
+    if ((!Instance->Ready) || (!Instance->DebugSupport)) {
+      //
+      // Debug host does not connect at first or is not supported
+      //
+      goto Done;
+    }
+  }
+
+  BytesToSend = 0;
+  while (*Length > 0) {
+    BytesToSend = ((*Length) > XHC_DEBUG_PORT_DATA_LENGTH) ? XHC_DEBUG_PORT_DATA_LENGTH : *Length;
+    XhcDataTransfer (
+      Instance,
+      Direction,
+      Data,
+      &BytesToSend,
+      DATA_TRANSFER_TIME_OUT,
+      &TransferResult
+      );
+    if (TransferResult != EFI_USB_NOERROR) {
+      break;
+    }
+    *Length -= BytesToSend;
+    Data += BytesToSend;
+  }
+
+Done:
+  //
+  // Restore Command Register
+  //
+  PciWrite16(PCI_LIB_ADDRESS (Bus, Device, Function, PCI_COMMAND_OFFSET), Command);
+
+}
+
+/**
+  Receive data over the USB3 debug cable.
+
+  @param[out]     Data      Pointer to data
+  @param[in, out] Length    Pointer to data length
+
+**/
+RETURN_STATUS
+Usb3DbgIn (
+      OUT UINT8                           *Data,
+  IN  OUT UINTN                           *Length
+  )
+{
+  Usb3DebugPortDataTransfer (Data, Length, EfiUsbDataIn);
+  return EFI_SUCCESS;
+}
+
+/**
+  Send data over the USB3 debug cable.
+
+  @param[out]      Data    Pointer to data
+  @param[in, out]  Length  Pointer to data length
+
+**/
+VOID
+Usb3DbgOut (
+  OUT      UINT8                           *Data,
+  IN OUT   UINTN                           *Length
+  )
+{
+  Usb3DebugPortDataTransfer (Data, Length, EfiUsbDataOut);
+}
diff --git a/Platform/Intel/DebugFeaturePkg/Library/Usb3DebugPortLib/Usb3DebugPortInitialize.c b/Platform/Intel/DebugFeaturePkg/Library/Usb3DebugPortLib/Usb3DebugPortInitialize.c
new file mode 100644
index 0000000000..dbdae59253
--- /dev/null
+++ b/Platform/Intel/DebugFeaturePkg/Library/Usb3DebugPortLib/Usb3DebugPortInitialize.c
@@ -0,0 +1,726 @@
+/** @file
+  Usb3 Debug Port initialization
+
+  Copyright (c) 2013 - 2019, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Base.h>
+
+#include <PiPei.h>
+#include <Library/SerialPortLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PciLib.h>
+#include <Library/PcdLib.h>
+#include <Library/TimerLib.h>
+#include <Library/HobLib.h>
+#include <Library/Usb3DebugPortParameterLib.h>
+#include "Usb3DebugPortLibInternal.h"
+
+UINT16   mString0Desc[] = {
+  //  String Descriptor Type + Length
+  ( USB_DESC_TYPE_STRING << 8 ) + STRING0_DESC_LEN,
+  0x0409
+};
+
+UINT16   mManufacturerStrDesc[] = {
+  //  String Descriptor Type + Length
+  ( USB_DESC_TYPE_STRING << 8 ) + MANU_DESC_LEN,
+  'I', 'n', 't', 'e', 'l'
+};
+
+//USB 3.0 Debug Cable
+UINT16   mProductStrDesc[] = {
+  //  String Descriptor Type + Length
+  ( USB_DESC_TYPE_STRING << 8 ) +  PRODUCT_DESC_LEN,
+  'U', 'S', 'B', ' ', '3', '.', '0', ' ', 'D', 'e', 'b', 'u', 'g', ' ', 'C', 'a', 'b', 'l', 'e'
+};
+
+UINT16   mSerialNumberStrDesc[] = {
+  //  String Descriptor Type + Length
+  ( USB_DESC_TYPE_STRING << 8 ) +  SERIAL_DESC_LEN,
+  '1'
+};
+
+XHC_DC_CONTEXT   DebugCapabilityContextTemplate = {
+  {
+    0,
+    0,
+    0,
+    0,
+    STRING0_DESC_LEN,
+    MANU_DESC_LEN,
+    PRODUCT_DESC_LEN,
+    SERIAL_DESC_LEN,
+    0,
+    0,
+    0,
+    0
+  },
+  {
+    0,  // EPState
+    0,  // RsvdZ1
+    0,  // Mult
+    0,  // MaxPStreams
+    0,  // LSA
+    0,  // Interval
+    0,  // RsvdZ2
+    0,  // RsvdZ3
+    3,  // CERR
+    ED_BULK_OUT,  // EPType
+    0,  // RsvdZ4
+    0,  // HID
+    0,  // MaxBurstSize
+    1024, // MaxPacketSize
+    0,    // PtrLo
+    0,    // PtrHi
+    0x1000, // AverageTRBLength
+    0,     // MaxESITPayload
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0
+  },
+  {
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    3,    //CERR
+    ED_BULK_IN,
+    0,
+    0,
+    0,
+    1024, //MaxPacketSize
+    0,
+    0,
+    0x1000,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0
+  }
+};
+
+/**
+  Return command register value in XHCI controller.
+
+**/
+UINT16
+GetXhciPciCommand (
+  VOID
+  )
+{
+  UINT8                                  Bus;
+  UINT8                                  Device;
+  UINT8                                  Function;
+  UINT16                                 Command;
+  USB3_DEBUG_PORT_CONTROLLER             UsbDebugPort;
+
+  UsbDebugPort.Controller = GetUsb3DebugPortController();
+
+  Bus = UsbDebugPort.PciAddress.Bus;
+  Device = UsbDebugPort.PciAddress.Device;
+  Function = UsbDebugPort.PciAddress.Function;
+  Command = PciRead16(PCI_LIB_ADDRESS(Bus, Device, Function, PCI_COMMAND_OFFSET));
+  return Command;
+}
+
+/**
+  Discover the USB3 debug device.
+
+  @param[in] Instance           Pointer to USB3 debug port object instance.
+
+  @retval RETURN_SUCCESS        The USB3 debug device was found.
+  @retval RETURN_DEVICE_ERROR   The USB3 debug device was not found.
+
+**/
+RETURN_STATUS
+DiscoverUsb3DebugPort(
+  IN USB3_DEBUG_PORT_INSTANCE   *Instance
+  )
+{
+  UINT8                           Bus;
+  UINT8                           Device;
+  UINT8                           Function;
+  UINT16                          Command;
+  EFI_PHYSICAL_ADDRESS            UsbBase;
+  USB3_DEBUG_PORT_CONTROLLER      UsbDebugPort;
+  EFI_PHYSICAL_ADDRESS            CapabilityPointer;
+  UINT32                          Capability;
+  BOOLEAN                         Flag;
+  UINT8                           CapLength;
+
+  UsbDebugPort.Controller = GetUsb3DebugPortController();
+  Bus = UsbDebugPort.PciAddress.Bus;
+  Device = UsbDebugPort.PciAddress.Device;
+  Function = UsbDebugPort.PciAddress.Function;
+  if ((PciRead8(PCI_LIB_ADDRESS(Bus, Device, Function, PCI_CLASSCODE_OFFSET + 2)) != PCI_CLASS_SERIAL) ||
+      (PciRead8(PCI_LIB_ADDRESS(Bus, Device, Function, PCI_CLASSCODE_OFFSET + 1)) != PCI_CLASS_SERIAL_USB) ||
+      (PciRead8(PCI_LIB_ADDRESS(Bus, Device, Function, PCI_CLASSCODE_OFFSET)) != 0x30)) {
+    //
+    // The device is not XHCI controller
+    //
+    return RETURN_NOT_FOUND;
+  }
+
+  //
+  // USBBASE is at 10-13h, i.e. the first BAR, clear the low bits which is not part of base address
+  //
+  UsbBase = GetXhciBaseAddress ();
+
+  //
+  // Set XHCI MMIO base address if necessary
+  //
+  if ((UsbBase == 0) || (UsbBase == XHCI_BASE_ADDRESS_64_BIT_MASK)) {
+    UsbBase  = PcdGet32 (PcdXhciDefaultBaseAddress);
+    PciWrite32 (PCI_LIB_ADDRESS(Bus, Device, Function, PCI_BASE_ADDRESSREG_OFFSET), (UINT32)UsbBase);
+    PciWrite32 (PCI_LIB_ADDRESS(Bus, Device, Function, PCI_BASE_ADDRESSREG_OFFSET + 4), 0x0);
+    UsbBase = PciRead32 (PCI_LIB_ADDRESS(Bus, Device, Function, PCI_BASE_ADDRESSREG_OFFSET)) & XHCI_BASE_ADDRESS_32_BIT_MASK;
+    if (UsbBase == 0 || UsbBase == XHCI_BASE_ADDRESS_32_BIT_MASK) {
+      return RETURN_DEVICE_ERROR;
+    }
+  }
+
+  //
+  //  Set MSE and BME bit - enable the address space
+  //
+  Command = PciRead16 (PCI_LIB_ADDRESS(Bus, Device, Function, PCI_COMMAND_OFFSET));
+  if ((Command & EFI_PCI_COMMAND_MEMORY_SPACE) == 0) {
+    PciWrite16(PCI_LIB_ADDRESS(Bus, Device, Function, PCI_COMMAND_OFFSET), Command | EFI_PCI_COMMAND_MEMORY_SPACE);
+    PciRead16(PCI_LIB_ADDRESS(Bus, Device, Function, PCI_COMMAND_OFFSET));
+  }
+
+  CapLength = MmioRead8 ((UINTN) UsbBase);
+
+  //
+  // Get capability pointer from HCCPARAMS at offset 0x10
+  //
+  CapabilityPointer = UsbBase + (MmioRead32 ((UINTN)(UsbBase + XHC_HCCPARAMS_OFFSET)) >> 16) * 4;
+
+  //
+  // Search XHCI debug capability
+  //
+  Flag = FALSE;
+  Capability = MmioRead32 ((UINTN)CapabilityPointer);
+  while (TRUE) {
+    if ((Capability & XHC_CAPABILITY_ID_MASK) == PCI_CAPABILITY_ID_DEBUG_PORT) {
+      Flag = TRUE;
+      break;
+    }
+    if ((((Capability & XHC_NEXT_CAPABILITY_MASK) >> 8) & XHC_CAPABILITY_ID_MASK) == 0) {
+      //
+      // Reach the end of capability list, quit
+      //
+      break;
+    }
+    CapabilityPointer += ((Capability & XHC_NEXT_CAPABILITY_MASK) >> 8) * 4;
+    Capability = MmioRead32 ((UINTN)CapabilityPointer);
+  }
+
+  Instance->Signature             = USB3_DEBUG_PORT_INSTANCE_SIGNATURE;
+
+  if (Flag) {
+    Instance->DebugSupport          = TRUE;
+    Instance->DebugCapabilityBase   = CapabilityPointer;
+    Instance->DebugCapabilityOffset = CapabilityPointer - UsbBase;
+
+    Instance->XhciOpRegister        = UsbBase + CapLength;
+    Instance->XhcMmioBase           = UsbBase;
+
+    Instance->PciBusNumber          = Bus;
+    Instance->PciDeviceNumber       = Device;
+    Instance->PciFunctionNumber     = Function;
+  }
+
+  //
+  // Restore Command Register
+  //
+  PciWrite16(PCI_LIB_ADDRESS (Bus, Device, Function, PCI_COMMAND_OFFSET), Command);
+
+  return RETURN_SUCCESS;
+}
+
+/**
+  Create XHCI event ring.
+
+  @param  Xhc                 The XHCI Instance.
+  @param  EventRing           The created event ring.
+
+**/
+EFI_STATUS
+CreateEventRing (
+  IN  USB3_DEBUG_PORT_INSTANCE   *Xhc,
+  OUT EVENT_RING                 *EventRing
+  )
+{
+  VOID                        *Buf;
+  EVENT_RING_SEG_TABLE_ENTRY  *ERSTBase;
+
+  ASSERT (EventRing != NULL);
+
+  //
+  // Allocate Event Ring
+  //
+  Buf = AllocateAlignBuffer (sizeof (TRB_TEMPLATE) * EVENT_RING_TRB_NUMBER);
+  ASSERT (Buf != NULL);
+  ASSERT (((UINTN) Buf & 0x3F) == 0);
+  ZeroMem (Buf, sizeof (TRB_TEMPLATE) * EVENT_RING_TRB_NUMBER);
+
+  EventRing->EventRingSeg0    = (EFI_PHYSICAL_ADDRESS)(UINTN) Buf;
+  EventRing->TrbNumber        = EVENT_RING_TRB_NUMBER;
+  EventRing->EventRingDequeue = (EFI_PHYSICAL_ADDRESS)(UINTN) EventRing->EventRingSeg0;
+  EventRing->EventRingEnqueue = (EFI_PHYSICAL_ADDRESS)(UINTN) EventRing->EventRingSeg0;
+
+  //
+  // Software maintains an Event Ring Consumer Cycle State (CCS) bit, initializing it to '1'
+  // and toggling it every time the Event Ring Dequeue Pointer wraps back to the beginning of the Event Ring.
+  //
+  EventRing->EventRingCCS = 1;
+
+  //
+  // Allocate Event Ring Segment Table Entry 0 in Event Ring Segment Table
+  //
+  Buf = AllocateAlignBuffer (sizeof (EVENT_RING_SEG_TABLE_ENTRY) * ERST_NUMBER);
+  ASSERT (Buf != NULL);
+  ASSERT (((UINTN) Buf & 0x3F) == 0);
+  ZeroMem (Buf, sizeof (EVENT_RING_SEG_TABLE_ENTRY) * ERST_NUMBER);
+
+  ERSTBase              = (EVENT_RING_SEG_TABLE_ENTRY *) Buf;
+  EventRing->ERSTBase   = (EFI_PHYSICAL_ADDRESS)(UINTN) ERSTBase;
+
+  //
+  // Fill Event Segment address
+  //
+  ERSTBase->PtrLo       = XHC_LOW_32BIT (EventRing->EventRingSeg0);
+  ERSTBase->PtrHi       = XHC_HIGH_32BIT (EventRing->EventRingSeg0);
+  ERSTBase->RingTrbSize = EVENT_RING_TRB_NUMBER;
+
+  //
+  // Program the Interrupter Event Ring Dequeue Pointer (DCERDP) register (7.6.4.1)
+  //
+  XhcWriteDebugReg (
+    Xhc,
+    XHC_DC_DCERDP,
+    XHC_LOW_32BIT((UINT64)(UINTN)EventRing->EventRingDequeue)
+    );
+
+  XhcWriteDebugReg (
+    Xhc,
+    XHC_DC_DCERDP + 4,
+    XHC_HIGH_32BIT((UINT64)(UINTN)EventRing->EventRingDequeue)
+    );
+
+  //
+  // Program the Debug Capability Event Ring Segment Table Base Address (DCERSTBA) register(7.6.4.1)
+  //
+  XhcWriteDebugReg (
+    Xhc,
+    XHC_DC_DCERSTBA,
+    XHC_LOW_32BIT((UINT64)(UINTN)ERSTBase)
+    );
+
+  XhcWriteDebugReg (
+    Xhc,
+    XHC_DC_DCERSTBA + 4,
+    XHC_HIGH_32BIT((UINT64)(UINTN)ERSTBase)
+    );
+
+  //
+  // Program the Debug Capability Event Ring Segment Table Size (DCERSTSZ) register(7.6.4.1)
+  //
+  XhcWriteDebugReg (
+    Xhc,
+    XHC_DC_DCERSTSZ,
+    ERST_NUMBER
+    );
+  return EFI_SUCCESS;
+}
+
+/**
+  Create XHCI transfer ring.
+
+  @param  Xhc               The XHCI Instance.
+  @param  TrbNum            The number of TRB in the ring.
+  @param  TransferRing      The created transfer ring.
+
+**/
+VOID
+CreateTransferRing (
+  IN  USB3_DEBUG_PORT_INSTANCE    *Xhc,
+  IN  UINT32                      TrbNum,
+  OUT TRANSFER_RING               *TransferRing
+  )
+{
+  VOID                  *Buf;
+  LINK_TRB              *EndTrb;
+
+  Buf = AllocateAlignBuffer (sizeof (TRB_TEMPLATE) * TrbNum);
+  ASSERT (Buf != NULL);
+  ASSERT (((UINTN) Buf & 0xF) == 0);
+  ZeroMem (Buf, sizeof (TRB_TEMPLATE) * TrbNum);
+
+  TransferRing->RingSeg0     = (EFI_PHYSICAL_ADDRESS)(UINTN) Buf;
+  TransferRing->TrbNumber    = TrbNum;
+  TransferRing->RingEnqueue  = TransferRing->RingSeg0;
+  TransferRing->RingDequeue  = TransferRing->RingSeg0;
+  TransferRing->RingPCS      = 1;
+  //
+  // 4.9.2 Transfer Ring Management
+  // To form a ring (or circular queue) a Link TRB may be inserted at the end of a ring to
+  // point to the first TRB in the ring.
+  //
+  EndTrb        = (LINK_TRB *) ((UINTN)Buf + sizeof (TRB_TEMPLATE) * (TrbNum - 1));
+  EndTrb->Type  = TRB_TYPE_LINK;
+  EndTrb->PtrLo = XHC_LOW_32BIT (Buf);
+  EndTrb->PtrHi = XHC_HIGH_32BIT (Buf);
+  //
+  // Toggle Cycle (TC). When set to '1', the xHC shall toggle its interpretation of the Cycle bit.
+  //
+  EndTrb->TC    = 1;
+  //
+  // Set Cycle bit as other TRB PCS init value
+  //
+  EndTrb->CycleBit = 0;
+}
+
+/**
+  Create debug capability context for XHC debug device.
+
+  @param  Xhc          The XHCI Instance.
+
+  @retval EFI_SUCCESS  The bit successfully changed by host controller.
+  @retval EFI_TIMEOUT  The time out occurred.
+
+**/
+EFI_STATUS
+CreateDebugCapabilityContext (
+  IN  USB3_DEBUG_PORT_INSTANCE   *Xhc
+  )
+{
+  VOID                        *Buf;
+  XHC_DC_CONTEXT              *DebugCapabilityContext;
+  UINT8                       *String0Desc;
+  UINT8                       *ManufacturerStrDesc;
+  UINT8                       *ProductStrDesc;
+  UINT8                       *SerialNumberStrDesc;
+
+  //
+  // Allocate debug device context
+  //
+  Buf = AllocateAlignBuffer (sizeof (XHC_DC_CONTEXT));
+  ASSERT (Buf != NULL);
+  ASSERT (((UINTN) Buf & 0xF) == 0);
+  ZeroMem (Buf, sizeof (XHC_DC_CONTEXT));
+
+  DebugCapabilityContext = (XHC_DC_CONTEXT *)(UINTN) Buf;
+  Xhc->DebugCapabilityContext = (EFI_PHYSICAL_ADDRESS)(UINTN) DebugCapabilityContext;
+
+  CopyMem (DebugCapabilityContext, &DebugCapabilityContextTemplate, sizeof (XHC_DC_CONTEXT));
+
+  //
+  // Update string descriptor address
+  //
+  String0Desc = (UINT8 *) AllocateAlignBuffer (STRING0_DESC_LEN + MANU_DESC_LEN + PRODUCT_DESC_LEN + SERIAL_DESC_LEN);
+  ASSERT (String0Desc != NULL);
+  ZeroMem (String0Desc, STRING0_DESC_LEN + MANU_DESC_LEN + PRODUCT_DESC_LEN + SERIAL_DESC_LEN);
+  CopyMem (String0Desc, mString0Desc, STRING0_DESC_LEN);
+  DebugCapabilityContext->DbcInfoContext.String0DescAddress = (UINT64)(UINTN)String0Desc;
+
+  ManufacturerStrDesc = String0Desc + STRING0_DESC_LEN;
+  CopyMem (ManufacturerStrDesc, mManufacturerStrDesc, MANU_DESC_LEN);
+  DebugCapabilityContext->DbcInfoContext.ManufacturerStrDescAddress = (UINT64)(UINTN)ManufacturerStrDesc;
+
+  ProductStrDesc = ManufacturerStrDesc + MANU_DESC_LEN;
+  CopyMem (ProductStrDesc, mProductStrDesc, PRODUCT_DESC_LEN);
+  DebugCapabilityContext->DbcInfoContext.ProductStrDescAddress = (UINT64)(UINTN)ProductStrDesc;
+
+  SerialNumberStrDesc = ProductStrDesc + PRODUCT_DESC_LEN;
+  CopyMem (SerialNumberStrDesc, mSerialNumberStrDesc, SERIAL_DESC_LEN);
+  DebugCapabilityContext->DbcInfoContext.SerialNumberStrDescAddress = (UINT64)(UINTN)SerialNumberStrDesc;
+
+  //
+  // Allocate and initialize the Transfer Ring for the Input Endpoint Context.
+  //
+  ZeroMem (&Xhc->TransferRingIn, sizeof (TRANSFER_RING));
+  CreateTransferRing (Xhc, TR_RING_TRB_NUMBER, &Xhc->TransferRingIn);
+
+  //
+  // Can not set BIT0, otherwise there is no transfer ring detected.
+  //
+  DebugCapabilityContext->EpInContext.PtrLo = XHC_LOW_32BIT (Xhc->TransferRingIn.RingSeg0) | BIT0;
+  DebugCapabilityContext->EpInContext.PtrHi = XHC_HIGH_32BIT (Xhc->TransferRingIn.RingSeg0);
+
+  //
+  // Allocate and initialize the Transfer Ring for the Output Endpoint Context.
+  //
+  ZeroMem (&Xhc->TransferRingOut, sizeof (TRANSFER_RING));
+  CreateTransferRing (Xhc, TR_RING_TRB_NUMBER, &Xhc->TransferRingOut);
+
+  //
+  // Can not set BIT0, otherwise there is no transfer ring detected.
+  //
+  DebugCapabilityContext->EpOutContext.PtrLo = XHC_LOW_32BIT (Xhc->TransferRingOut.RingSeg0) | BIT0;
+  DebugCapabilityContext->EpOutContext.PtrHi = XHC_HIGH_32BIT (Xhc->TransferRingOut.RingSeg0);
+
+  //
+  // Program the Debug Capability Context Pointer (DCCP) register(7.6.8.7)
+  //
+  XhcWriteDebugReg (
+    Xhc,
+    XHC_DC_DCCP,
+    XHC_LOW_32BIT((UINT64)(UINTN)DebugCapabilityContext)
+    );
+  XhcWriteDebugReg (
+    Xhc,
+    XHC_DC_DCCP + 4,
+    XHC_HIGH_32BIT((UINT64)(UINTN)DebugCapabilityContext)
+    );
+  return EFI_SUCCESS;
+}
+
+/**
+  Initialize the USB3 debug Device hardware.
+
+  @param[in] Instance       Pointer to USB3 debug port object instance.
+
+  @retval RETURN_SUCCESS    The USB3 debug device was initialized successfully.
+  @retval !RETURN_SUCCESS   Error.
+
+**/
+RETURN_STATUS
+InitializeUsb3DebugPort (
+  IN USB3_DEBUG_PORT_INSTANCE   *Instance
+  )
+{
+  RETURN_STATUS                   Status;
+  UINT64                          XhciOpRegister;
+  volatile UINT32                 Dcctrl;
+  UINT8                           Bus;
+  UINT8                           Device;
+  UINT8                           Function;
+  UINT16                          Command;
+  EFI_BOOT_MODE                   BootMode;
+  UINT64                          TimeOut;
+  CHAR8                           *TestString;
+  UINTN                           Length;
+  UINT32                          TransferResult;
+
+  Bus      = Instance->PciBusNumber;
+  Device   = Instance->PciDeviceNumber;
+  Function = Instance->PciFunctionNumber;
+
+  Command = GetXhciPciCommand ();
+
+  //
+  // Save and set Command Register
+  //
+  if (((Command & EFI_PCI_COMMAND_MEMORY_SPACE) == 0) || ((Command & EFI_PCI_COMMAND_BUS_MASTER) == 0)) {
+    PciWrite16(PCI_LIB_ADDRESS(Bus, Device, Function, PCI_COMMAND_OFFSET), Command | EFI_PCI_COMMAND_MEMORY_SPACE | EFI_PCI_COMMAND_BUS_MASTER);
+    PciRead16(PCI_LIB_ADDRESS(Bus, Device, Function, PCI_COMMAND_OFFSET));
+  }
+
+  //
+  // Clear DCE bit and LSE bit in DCCTRL
+  //
+  if ((XhcReadDebugReg (Instance, XHC_DC_DCCTRL) & (BIT1|BIT31)) == (BIT1|BIT31)) {
+    XhcClearDebugRegBit (Instance, XHC_DC_DCCTRL, BIT1|BIT31);
+  }
+
+  XhciOpRegister = Instance->XhciOpRegister;
+
+  //
+  // Get current Boot Mode
+  //
+  BootMode = GetBootModeHob ();
+
+  if (BootMode != BOOT_ON_S3_RESUME) {
+    if (!XhcIsBitSet((UINTN)(XhciOpRegister + XHC_USBSTS_OFFSET), XHC_USBSTS_HALT)) {
+      XhcClrR32Bit((UINTN) XhciOpRegister + XHC_USBCMD_OFFSET, XHC_USBCMD_RUN);
+      while (!XhcIsBitSet((UINTN)(XhciOpRegister + XHC_USBSTS_OFFSET), XHC_USBSTS_HALT)) {
+        MicroSecondDelay (10);
+      }
+    }
+
+    //
+    // Reset host controller
+    //
+    XhcSetR32Bit((UINTN)XhciOpRegister + XHC_USBCMD_OFFSET, XHC_USBCMD_RESET);
+
+    //
+    // Ensure that the host controller is reset (RESET bit must be cleared after reset)
+    //
+    while (XhcIsBitSet((UINTN)XhciOpRegister + XHC_USBCMD_OFFSET, XHC_USBCMD_RESET)) {
+      MicroSecondDelay (10);
+    }
+  }
+
+  //
+  // Initialize event ring
+  //
+  ZeroMem (&Instance->EventRing, sizeof (EVENT_RING));
+  Status = CreateEventRing (Instance, &Instance->EventRing);
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Init IN and OUT endpoint context
+  //
+  Status = CreateDebugCapabilityContext (Instance);
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Init data buffer used to transfer
+  //
+  Instance->Urb.Data = (EFI_PHYSICAL_ADDRESS) (UINTN) AllocateAlignBuffer (XHC_DEBUG_PORT_DATA_LENGTH);
+
+  //
+  // Init DCDDI1 and DCDDI2
+  //
+  XhcWriteDebugReg (
+   Instance,
+   XHC_DC_DCDDI1,
+   (UINT32)((XHCI_DEBUG_DEVICE_VENDOR_ID << 16) | XHCI_DEBUG_DEVICE_PROTOCOL)
+   );
+
+  XhcWriteDebugReg (
+   Instance,
+   XHC_DC_DCDDI2,
+   (UINT32)((XHCI_DEBUG_DEVICE_REVISION << 16) | XHCI_DEBUG_DEVICE_PRODUCT_ID)
+   );
+
+  //
+  // Set DCE bit and LSE bit to "1" in DCCTRL
+  //
+  XhcSetDebugRegBit (Instance, XHC_DC_DCCTRL, BIT1|BIT31);
+
+  TimeOut = DivU64x32 (PcdGet64 (PcdXhciHostWaitTimeout), XHC_POLL_DELAY) + 1;
+  while (TimeOut != 0) {
+    //
+    // Check if debug device is in configured state
+    //
+    Dcctrl = XhcReadDebugReg (Instance, XHC_DC_DCCTRL);
+    if ((Dcctrl & BIT0) != 0) {
+      //
+      // Set the flag to indicate debug device is ready
+      //
+      Instance->Ready = TRUE;
+      break;
+    }
+    MicroSecondDelay (XHC_POLL_DELAY);
+    TimeOut--;
+  }
+
+  if (!Instance->Ready) {
+    XhcClearDebugRegBit (Instance, XHC_DC_DCCTRL, BIT1|BIT31);
+  } else {
+    TestString = "Usb 3.0 Debug Message Start\n";
+    Length = AsciiStrLen (TestString);
+    XhcDataTransfer (
+      Instance,
+      EfiUsbDataOut,
+      TestString,
+      &Length,
+      0,
+      &TransferResult
+      );
+  }
+
+  //
+  // Restore Command Register
+  //
+  PciWrite16 (PCI_LIB_ADDRESS (Bus, Device, Function, PCI_COMMAND_OFFSET), Command);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Update XHC hardware address when MMIO base is changed.
+
+  @param  Instance          The XHCI Instance.
+  @param  XhcMmioBase       XHCI MMIO base address.
+
+**/
+VOID
+FixUsb3InstanceResource (
+  IN OUT USB3_DEBUG_PORT_INSTANCE           *Instance,
+  IN EFI_PHYSICAL_ADDRESS                   XhcMmioBase
+  )
+{
+  if ((Instance == NULL) || (Instance->XhcMmioBase == XhcMmioBase)) {
+    return;
+  }
+
+  //
+  // Need fix Instance data according to PCI resource
+  //
+  Instance->XhcMmioBase         = XhcMmioBase;
+  Instance->DebugCapabilityBase = XhcMmioBase + Instance->DebugCapabilityOffset;
+  Instance->XhciOpRegister      = XhcMmioBase + MmioRead8 ((UINTN)XhcMmioBase);
+}
+
+/**
+  Save USB3 instance address.
+
+  @param[in] Instance   The XHCI Instance.
+
+**/
+VOID
+SaveUsb3InstanceAddress (
+  IN USB3_DEBUG_PORT_INSTANCE   *Instance
+  )
+{
+  UINT16                        Command;
+  USB3_DEBUG_PORT_CONTROLLER    UsbDebugPort;
+  UINT8                         Bus;
+  UINT8                         Device;
+  UINT8                         Function;
+
+  Command = GetXhciPciCommand ();
+  UsbDebugPort.Controller = GetUsb3DebugPortController();
+  Bus      = UsbDebugPort.PciAddress.Bus;
+  Device   = UsbDebugPort.PciAddress.Device;
+  Function = UsbDebugPort.PciAddress.Function;
+
+  //
+  // Set Command Register
+  //
+  if ((Command & EFI_PCI_COMMAND_MEMORY_SPACE) == 0) {
+    PciWrite16(PCI_LIB_ADDRESS(Bus, Device, Function, PCI_COMMAND_OFFSET), Command | EFI_PCI_COMMAND_MEMORY_SPACE);
+    PciRead16(PCI_LIB_ADDRESS(Bus, Device, Function, PCI_COMMAND_OFFSET));
+  }
+
+  //
+  // After debug device is finished to enumerate, use DCDDI2 register to store instance address
+  //
+  XhcWriteDebugReg (
+   Instance,
+   XHC_DC_DCDDI2,
+   (UINT32)(UINTN)Instance
+   );
+
+  //
+  // Restore Command Register
+  //
+  PciWrite16 (PCI_LIB_ADDRESS (Bus, Device, Function, PCI_COMMAND_OFFSET), Command);
+}
+
diff --git a/Platform/Intel/DebugFeaturePkg/Library/Usb3DebugPortLib/Usb3DebugPortLibDxe.c b/Platform/Intel/DebugFeaturePkg/Library/Usb3DebugPortLib/Usb3DebugPortLibDxe.c
new file mode 100644
index 0000000000..8c3dd999db
--- /dev/null
+++ b/Platform/Intel/DebugFeaturePkg/Library/Usb3DebugPortLib/Usb3DebugPortLibDxe.c
@@ -0,0 +1,454 @@
+/** @file
+  Usb3 Debug Port library instance
+
+  Copyright (c) 2013 - 2019, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Base.h>
+
+#include <PiDxe.h>
+#include <Library/SerialPortLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/PciLib.h>
+#include <Library/PcdLib.h>
+#include <Library/TimerLib.h>
+#include <Library/Usb3DebugPortParameterLib.h>
+#include <Protocol/SmmBase2.h>
+#include <Protocol/SmmAccess2.h>
+#include "Usb3DebugPortLibInternal.h"
+
+extern EFI_SMRAM_DESCRIPTOR mSmramCheckRanges[MAX_SMRAM_RANGE];
+extern UINTN                mSmramCheckRangeCount;
+extern BOOLEAN              mUsb3InSmm;
+extern UINT64               mUsb3MmioSize;
+extern BOOLEAN              mUsb3GetCapSuccess;
+
+GUID                        gUsb3DbgGuid =  USB3_DBG_GUID;
+
+USB3_DEBUG_PORT_CONTROLLER  mUsb3DebugPort;
+USB3_DEBUG_PORT_INSTANCE    *mUsb3Instance = NULL;
+
+/**
+  Return XHCI MMIO base address.
+
+**/
+EFI_PHYSICAL_ADDRESS
+GetXhciBaseAddress (
+  VOID
+  )
+{
+  UINT8                       Bus;
+  UINT8                       Device;
+  UINT8                       Function;
+  EFI_PHYSICAL_ADDRESS        Address;
+  UINT32                      Low;
+  UINT32                      High;
+
+  if (mUsb3DebugPort.Controller == 0) {
+    mUsb3DebugPort.Controller = GetUsb3DebugPortController();
+  }
+
+  Bus = mUsb3DebugPort.PciAddress.Bus;
+  Device = mUsb3DebugPort.PciAddress.Device;
+  Function = mUsb3DebugPort.PciAddress.Function;
+
+  Low = PciRead32 (PCI_LIB_ADDRESS(Bus, Device, Function, PCI_BASE_ADDRESSREG_OFFSET));
+  High = PciRead32 (PCI_LIB_ADDRESS(Bus, Device, Function, PCI_BASE_ADDRESSREG_OFFSET + 4));
+  Address = (EFI_PHYSICAL_ADDRESS) (LShiftU64 ((UINT64) High, 32) | Low);
+  //
+  // Mask other parts which are not part of base address
+  //
+  Address &= XHCI_BASE_ADDRESS_64_BIT_MASK;
+  return Address;
+}
+
+/**
+  Return XHCI debug instance address.
+
+**/
+USB3_DEBUG_PORT_INSTANCE *
+GetUsb3DebugPortInstance (
+  VOID
+  )
+{
+  USB3_DEBUG_PORT_INSTANCE               *Instance;
+  EFI_PHYSICAL_ADDRESS                   XhcMmioBase;
+  UINT64                                 CapabilityPointer;
+  UINT32                                 Capability;
+  BOOLEAN                                Flag;
+  UINT8                                  Bus;
+  UINT8                                  Device;
+  UINT8                                  Function;
+  UINT16                                 Command;
+  USB3_DEBUG_PORT_CONTROLLER             UsbDebugPort;
+
+  Instance = NULL;
+
+  XhcMmioBase = GetXhciBaseAddress ();
+
+  if ((XhcMmioBase == 0) || (XhcMmioBase == XHCI_BASE_ADDRESS_64_BIT_MASK)) {
+    return NULL;
+  }
+
+  if (mUsb3Instance != NULL) {
+    FixUsb3InstanceResource (mUsb3Instance, XhcMmioBase);
+    return mUsb3Instance;
+  }
+
+  Command = GetXhciPciCommand ();
+
+  UsbDebugPort.Controller = GetUsb3DebugPortController();
+  Bus      = UsbDebugPort.PciAddress.Bus;
+  Device   = UsbDebugPort.PciAddress.Device;
+  Function = UsbDebugPort.PciAddress.Function;
+
+  //
+  // Set Command Register
+  //
+  if ((Command & EFI_PCI_COMMAND_MEMORY_SPACE) == 0) {
+    PciWrite16(PCI_LIB_ADDRESS(Bus, Device, Function, PCI_COMMAND_OFFSET), Command | EFI_PCI_COMMAND_MEMORY_SPACE);
+    PciRead16(PCI_LIB_ADDRESS(Bus, Device, Function, PCI_COMMAND_OFFSET));
+  }
+
+  //
+  // Calculate capability offset from HCCPARAMS [16:31], in 32-bit words
+  //
+  CapabilityPointer = XhcMmioBase + (MmioRead32 ((UINTN)(XhcMmioBase + XHC_HCCPARAMS_OFFSET)) >> 16) * 4;
+
+  //
+  // Search XHCI debug capability
+  //
+  Flag = FALSE;
+  Capability = MmioRead32 ((UINTN)CapabilityPointer);
+  while (TRUE) {
+    if ((Capability & XHC_CAPABILITY_ID_MASK) == PCI_CAPABILITY_ID_DEBUG_PORT) {
+      Flag = TRUE;
+      break;
+    }
+    if ((((Capability & XHC_NEXT_CAPABILITY_MASK) >> 8) & XHC_CAPABILITY_ID_MASK) == 0) {
+      //
+      // Reach the end of list, quit
+      //
+      break;
+    }
+    CapabilityPointer += ((Capability & XHC_NEXT_CAPABILITY_MASK) >> 8) * 4;
+    Capability = MmioRead32 ((UINTN)CapabilityPointer);
+  }
+
+  if (Flag) {
+    Instance = (USB3_DEBUG_PORT_INSTANCE *)(UINTN) MmioRead32 ((UINTN) (CapabilityPointer + XHC_DC_DCDDI2));
+
+    if (Instance != NULL) {
+      FixUsb3InstanceResource (Instance, XhcMmioBase);
+    }
+  }
+
+  //
+  // Restore Command Register
+  //
+  PciWrite16(PCI_LIB_ADDRESS (Bus, Device, Function, PCI_COMMAND_OFFSET), Command);
+
+  return Instance;
+}
+
+
+/**
+  Initialize USB3 debug port.
+
+  This method invokes various internal functions to facilitate
+  detection and initialization of USB3 debug port.
+
+  @retval RETURN_SUCCESS        The USB3 debug port was initialized.
+**/
+RETURN_STATUS
+EFIAPI
+USB3Initialize (
+  VOID
+  )
+{
+  //
+  // Leave it empty, we assume PEI phase already do initialization
+  //
+  return RETURN_SUCCESS;
+}
+
+/**
+  Initialize USB3 debug port.
+
+  This method invokes various internal functions to facilitate
+  detection and initialization of USB3 debug port.
+
+  @retval RETURN_SUCCESS        The serial device was initialized.
+**/
+RETURN_STATUS
+EFIAPI
+USB3InitializeReal (
+  VOID
+  )
+{
+  USB3_DEBUG_PORT_INSTANCE    UsbDbg;
+  USB3_DEBUG_PORT_INSTANCE    *Instance;
+  EFI_PHYSICAL_ADDRESS        Address;
+  EFI_STATUS                  Status;
+
+  if ((gST == NULL) || (gBS == NULL)) {
+    //
+    // gST and gBS have not been initialized yet
+    //
+    return EFI_DEVICE_ERROR;
+  }
+
+  Status = EfiGetSystemConfigurationTable (&gUsb3DbgGuid, (VOID **) &mUsb3Instance);
+  if (!EFI_ERROR (Status)) {
+    return RETURN_SUCCESS;
+  }
+
+  //
+  // It is first time to run DXE instance, copy Instance from Hob to ACPINvs
+  // NOTE: Hob is not ready at this time, so copy it from XHCI register.
+  //
+  Instance = GetUsb3DebugPortInstance ();
+  if (Instance == NULL) {
+    //
+    // Initialize USB debug
+    //
+    SetMem (&UsbDbg, sizeof(UsbDbg), 0);
+    DiscoverUsb3DebugPort (&UsbDbg);
+    if (UsbDbg.DebugSupport) {
+      InitializeUsb3DebugPort (&UsbDbg);
+    }
+    Instance = &UsbDbg;
+  }
+  Address = SIZE_4GB;
+  Status = gBS->AllocatePages (
+                  AllocateMaxAddress,
+                  EfiACPIMemoryNVS,
+                  EFI_SIZE_TO_PAGES (sizeof (USB3_DEBUG_PORT_INSTANCE)),
+                  &Address
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  CopyMem (
+    (VOID *)(UINTN)Address,
+    Instance,
+    sizeof (USB3_DEBUG_PORT_INSTANCE)
+    );
+  mUsb3Instance = (USB3_DEBUG_PORT_INSTANCE *)(UINTN)Address;
+
+  Status = gBS->InstallConfigurationTable (&gUsb3DbgGuid, mUsb3Instance);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  if (mUsb3Instance->DebugSupport) {
+    SaveUsb3InstanceAddress (mUsb3Instance);
+  }
+
+  return RETURN_SUCCESS;
+}
+
+/**
+  Calculate the size of XHCI MMIO space.
+
+  @retval     TURE         The XHCI MMIO is in SMRAM ranges.
+  @retval     FALSE        The XHCI MMIO is out of SMRAM ranges.
+**/
+UINT64
+CalculateMmioSize (
+  VOID
+  )
+{
+  UINT8                       Bus;
+  UINT8                       Device;
+  UINT8                       Function;
+  UINT32                      Value;
+  UINT32                      Mask;
+  UINT64                      MmioSize;
+  UINT16                      Command;
+  USB3_DEBUG_PORT_CONTROLLER  UsbDebugPort;
+  EFI_PHYSICAL_ADDRESS        XhcMmioBase;
+
+  UsbDebugPort.Controller = GetUsb3DebugPortController();
+  Bus      = UsbDebugPort.PciAddress.Bus;
+  Device   = UsbDebugPort.PciAddress.Device;
+  Function = UsbDebugPort.PciAddress.Function;
+
+  Mask     = 0xFFFFFFF0;
+  MmioSize = 0;
+
+  XhcMmioBase = GetXhciBaseAddress ();
+
+  //
+  // Disable MSE
+  //
+  Command = PciRead16 (PCI_LIB_ADDRESS(Bus, Device, Function, PCI_COMMAND_OFFSET));
+  PciWrite16 (PCI_LIB_ADDRESS (Bus, Device, Function, PCI_COMMAND_OFFSET), Command & ~(EFI_PCI_COMMAND_MEMORY_SPACE));
+
+  //
+  // Get Mmio Size
+  //
+  PciWrite32 (PCI_LIB_ADDRESS(Bus, Device, Function, PCI_BASE_ADDRESSREG_OFFSET), 0xFFFFFFFF);
+  Value    = PciRead32 (PCI_LIB_ADDRESS(Bus, Device, Function, PCI_BASE_ADDRESSREG_OFFSET));
+
+  switch (Value & 0x07) {
+    case 0x0:
+      //
+      // Memory space: anywhere in 32 bit address space
+      //
+      MmioSize = (~(Value & Mask)) + 1;
+      break;
+    case 0x4:
+      //
+      // Memory space: anywhere in 64 bit address space
+      //
+      MmioSize = Value & Mask;
+      PciWrite32 (PCI_LIB_ADDRESS(Bus, Device, Function, PCI_BASE_ADDRESSREG_OFFSET + 4), 0xFFFFFFFF);
+      Value    = PciRead32 (PCI_LIB_ADDRESS(Bus, Device, Function, PCI_BASE_ADDRESSREG_OFFSET + 4));
+      //
+      // Fix the length to support some spefic 64 bit BAR
+      //
+      Value |= ((UINT32)(-1) << HighBitSet32 (Value));
+      //
+      // Calculate the size of 64bit bar
+      //
+      MmioSize  |= LShiftU64 ((UINT64) Value, 32);
+      MmioSize  = (~(MmioSize)) + 1;
+      break;
+    default:
+      //
+      // Unknown BAR type
+      //
+      MmioSize = (~(Value & Mask)) + 1;
+      break;
+  };
+
+
+  //
+  // Restore MMIO address
+  //
+  PciWrite32 (PCI_LIB_ADDRESS(Bus, Device, Function, PCI_BASE_ADDRESSREG_OFFSET), (UINT32)XhcMmioBase);
+  PciWrite32 (PCI_LIB_ADDRESS(Bus, Device, Function, PCI_BASE_ADDRESSREG_OFFSET + 4), (UINT32) (XhcMmioBase >> 32));
+
+  PciWrite16 (PCI_LIB_ADDRESS (Bus, Device, Function, PCI_COMMAND_OFFSET), Command | EFI_PCI_COMMAND_MEMORY_SPACE);
+
+  return MmioSize;
+}
+
+/**
+  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
+Usb3DebugPortLibDxeConstructor (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_SMM_BASE2_PROTOCOL        *SmmBase;
+  EFI_SMM_ACCESS2_PROTOCOL      *SmmAccess;
+  UINTN                         Size;
+  EFI_STATUS                    Status;
+
+  //
+  // Do real initialization here, because we need copy data from Hob to ACPINvs.
+  // We must do it in constructor because it depends on UefiBootServicesTableLib.
+  //
+  if (FeaturePcdGet (PcdStatusCodeUseUsb3Serial)) {
+    USB3InitializeReal ();
+  }
+
+  mUsb3MmioSize = CalculateMmioSize ();
+
+  if (gBS != NULL) {
+    SmmBase = NULL;
+    Status = gBS->LocateProtocol (&gEfiSmmBase2ProtocolGuid, NULL, (VOID **)&SmmBase);
+    if (!EFI_ERROR (Status)) {
+      SmmBase->InSmm(SmmBase, &mUsb3InSmm);
+    }
+
+    if (mUsb3InSmm) {
+      //
+      // Get SMRAM information
+      //
+      SmmAccess = NULL;
+      Status = gBS->LocateProtocol (&gEfiSmmAccess2ProtocolGuid, NULL, (VOID **)&SmmAccess);
+      if (!EFI_ERROR (Status)) {
+        Size = sizeof (mSmramCheckRanges);
+
+        Status = SmmAccess->GetCapabilities (SmmAccess, &Size, mSmramCheckRanges);
+        if (!EFI_ERROR (Status)) {
+          mSmramCheckRangeCount = Size / sizeof (EFI_SMRAM_DESCRIPTOR);
+        }
+      }
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  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
+  )
+{
+  VOID                    *Buf;
+  EFI_PHYSICAL_ADDRESS    Address;
+  EFI_STATUS              Status;
+
+  Buf = NULL;
+
+  if (gBS != NULL) {
+    Address = 0xFFFFFFFF;
+    Status = gBS->AllocatePages (
+                    AllocateMaxAddress,
+                    EfiACPIMemoryNVS,
+                    EFI_SIZE_TO_PAGES (BufferSize),
+                    &Address
+                    );
+    if (!EFI_ERROR (Status)) {
+      Buf = (VOID *)(UINTN)Address;
+    }
+  }
+
+  return Buf;
+}
+
+/**
+  Check whether AllocatePages in permanent memory is ready.
+
+  @retval TRUE  AllocatePages in permanent memory is ready.
+  @retval FALSE AllocatePages in permanent memory is not ready.
+
+**/
+BOOLEAN
+IsAllocatePagesReady (
+  VOID
+  )
+{
+  if (gBS != NULL) {
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
diff --git a/Platform/Intel/DebugFeaturePkg/Library/Usb3DebugPortLib/Usb3DebugPortLibDxe.inf b/Platform/Intel/DebugFeaturePkg/Library/Usb3DebugPortLib/Usb3DebugPortLibDxe.inf
new file mode 100644
index 0000000000..1d4b05779c
--- /dev/null
+++ b/Platform/Intel/DebugFeaturePkg/Library/Usb3DebugPortLib/Usb3DebugPortLibDxe.inf
@@ -0,0 +1,55 @@
+## @file
+#  Usb3 debug port library.
+#
+# Copyright (c) 2013 - 2019, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = Usb3DebugPortLibDxe
+  FILE_GUID                      = 08A575C4-D962-4ca5-8855-D3B4AE93A141
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = Usb3DebugPortLib|DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SAL_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER SMM_CORE
+  CONSTRUCTOR                    = Usb3DebugPortLibDxeConstructor
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 IPF
+#
+
+[Sources]
+  Usb3DebugPortLibDxe.c
+  Usb3DebugPortDataTransfer.c
+  Usb3DebugPortInitialize.c
+  MiscServices.c
+  Usb3DebugPortLibInternal.h
+
+[Packages]
+  MdePkg/MdePkg.dec
+  DebugFeaturePkg/DebugFeaturePkg.dec
+
+[LibraryClasses]
+  BaseLib
+  PcdLib
+  IoLib
+  PciLib
+  TimerLib
+  UefiBootServicesTableLib
+  UefiLib
+  HobLib
+  Usb3DebugPortParameterLib
+
+[Protocols]
+  gEfiSmmAccess2ProtocolGuid                       ## CONSUMES
+  gEfiSmmBase2ProtocolGuid                         ## CONSUMES
+
+[Pcd]
+  gEfiUsb3DebugPortTokenSpaceGuid.PcdXhciDefaultBaseAddress     ## SOMETIMES_CONSUMES
+  gEfiUsb3DebugPortTokenSpaceGuid.PcdXhciHostWaitTimeout        ## CONSUMES
+
+[FeaturePcd]
+  gEfiUsb3DebugPortTokenSpaceGuid.PcdStatusCodeUseUsb3Serial    ## CONSUMES
diff --git a/Platform/Intel/DebugFeaturePkg/Library/Usb3DebugPortLib/Usb3DebugPortLibDxeIoMmu.c b/Platform/Intel/DebugFeaturePkg/Library/Usb3DebugPortLib/Usb3DebugPortLibDxeIoMmu.c
new file mode 100644
index 0000000000..97c3f88113
--- /dev/null
+++ b/Platform/Intel/DebugFeaturePkg/Library/Usb3DebugPortLib/Usb3DebugPortLibDxeIoMmu.c
@@ -0,0 +1,828 @@
+/** @file
+  Usb3 Debug Port library instance
+
+  Copyright (c) 2013 - 2019, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Base.h>
+
+#include <PiDxe.h>
+#include <Library/SerialPortLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/PciLib.h>
+#include <Library/PcdLib.h>
+#include <Library/TimerLib.h>
+#include <Library/Usb3DebugPortParameterLib.h>
+#include <Protocol/SmmBase2.h>
+#include <Protocol/SmmAccess2.h>
+#include <Protocol/IoMmu.h>
+#include <Protocol/PciIo.h>
+#include <Protocol/DxeSmmReadyToLock.h>
+#include "Usb3DebugPortLibInternal.h"
+
+extern EFI_SMRAM_DESCRIPTOR mSmramCheckRanges[MAX_SMRAM_RANGE];
+extern UINTN                mSmramCheckRangeCount;
+extern BOOLEAN              mUsb3InSmm;
+extern UINT64               mUsb3MmioSize;
+extern BOOLEAN              mUsb3GetCapSuccess;
+
+GUID                        gUsb3DbgGuid =  USB3_DBG_GUID;
+
+USB3_DEBUG_PORT_CONTROLLER  mUsb3DebugPort;
+USB3_DEBUG_PORT_INSTANCE    *mUsb3Instance = NULL;
+EFI_PCI_IO_PROTOCOL         *mUsb3PciIo = 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 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_INSTANCE   *Instance,
+  IN EFI_PCI_IO_PROTOCOL        *PciIo
+  )
+{
+  Usb3MapOneDmaBuffer (
+    PciIo,
+    Instance->Urb.Data,
+    XHC_DEBUG_PORT_DATA_LENGTH
+    );
+
+  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
+  )
+{
+  ASSERT (mUsb3Instance != NULL);
+
+  //
+  // 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.
+  //
+  InitializeUsb3DebugPort (mUsb3Instance);
+
+  SaveUsb3InstanceAddress (mUsb3Instance);
+
+  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;
+  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);
+      if ((PciBusNumber == mUsb3DebugPort.PciAddress.Bus) &&
+          (PciDeviceNumber == mUsb3DebugPort.PciAddress.Device) &&
+          (PciFunctionNumber == mUsb3DebugPort.PciAddress.Function)) {
+        //
+        // Found the PciIo for USB3 debug port.
+        //
+        ASSERT (mUsb3Instance != NULL);
+        if (Usb3GetIoMmu () != NULL) {
+          Usb3MapDmaBuffers (mUsb3Instance, PciIo);
+
+          if (mUsb3Instance->FromHob) {
+            mUsb3PciIo = PciIo;
+            Usb3NamedEventListen (
+              &gEfiDxeSmmReadyToLockProtocolGuid,
+              TPL_NOTIFY,
+              Usb3DxeSmmReadyToLockNotify,
+              &SmmReadyToLockEvent
+              );
+          }
+        }
+        gBS->CloseEvent (Event);
+        break;
+      }
+    }
+
+    gBS->FreePool (PciIoHandleBuffer);
+  }
+}
+
+/**
+  Return XHCI MMIO base address.
+
+**/
+EFI_PHYSICAL_ADDRESS
+GetXhciBaseAddress (
+  VOID
+  )
+{
+  UINT8                       Bus;
+  UINT8                       Device;
+  UINT8                       Function;
+  EFI_PHYSICAL_ADDRESS        Address;
+  UINT32                      Low;
+  UINT32                      High;
+
+  if (mUsb3DebugPort.Controller == 0) {
+    mUsb3DebugPort.Controller = GetUsb3DebugPortController();
+  }
+
+  Bus = mUsb3DebugPort.PciAddress.Bus;
+  Device = mUsb3DebugPort.PciAddress.Device;
+  Function = mUsb3DebugPort.PciAddress.Function;
+
+  Low = PciRead32 (PCI_LIB_ADDRESS(Bus, Device, Function, PCI_BASE_ADDRESSREG_OFFSET));
+  High = PciRead32 (PCI_LIB_ADDRESS(Bus, Device, Function, PCI_BASE_ADDRESSREG_OFFSET + 4));
+  Address = (EFI_PHYSICAL_ADDRESS) (LShiftU64 ((UINT64) High, 32) | Low);
+  //
+  // Mask other parts which are not part of base address
+  //
+  Address &= XHCI_BASE_ADDRESS_64_BIT_MASK;
+  return Address;
+}
+
+/**
+  Return XHCI debug instance address.
+
+**/
+USB3_DEBUG_PORT_INSTANCE *
+GetUsb3DebugPortInstance (
+  VOID
+  )
+{
+  USB3_DEBUG_PORT_INSTANCE               *Instance;
+  EFI_PHYSICAL_ADDRESS                   XhcMmioBase;
+  UINT64                                 CapabilityPointer;
+  UINT32                                 Capability;
+  BOOLEAN                                Flag;
+  UINT8                                  Bus;
+  UINT8                                  Device;
+  UINT8                                  Function;
+  UINT16                                 Command;
+  USB3_DEBUG_PORT_CONTROLLER             UsbDebugPort;
+
+  Instance = NULL;
+
+  XhcMmioBase = GetXhciBaseAddress ();
+
+  if ((XhcMmioBase == 0) || (XhcMmioBase == XHCI_BASE_ADDRESS_64_BIT_MASK)) {
+    return NULL;
+  }
+
+  if (mUsb3Instance != NULL) {
+    FixUsb3InstanceResource (mUsb3Instance, XhcMmioBase);
+    return mUsb3Instance;
+  }
+
+  Command = GetXhciPciCommand ();
+
+  UsbDebugPort.Controller = GetUsb3DebugPortController();
+  Bus      = UsbDebugPort.PciAddress.Bus;
+  Device   = UsbDebugPort.PciAddress.Device;
+  Function = UsbDebugPort.PciAddress.Function;
+
+  //
+  // Set Command Register
+  //
+  if ((Command & EFI_PCI_COMMAND_MEMORY_SPACE) == 0) {
+    PciWrite16(PCI_LIB_ADDRESS(Bus, Device, Function, PCI_COMMAND_OFFSET), Command | EFI_PCI_COMMAND_MEMORY_SPACE);
+    PciRead16(PCI_LIB_ADDRESS(Bus, Device, Function, PCI_COMMAND_OFFSET));
+  }
+
+  //
+  // Calculate capability offset from HCCPARAMS [16:31], in 32-bit words
+  //
+  CapabilityPointer = XhcMmioBase + (MmioRead32 ((UINTN)(XhcMmioBase + XHC_HCCPARAMS_OFFSET)) >> 16) * 4;
+
+  //
+  // Search XHCI debug capability
+  //
+  Flag = FALSE;
+  Capability = MmioRead32 ((UINTN)CapabilityPointer);
+  while (TRUE) {
+    if ((Capability & XHC_CAPABILITY_ID_MASK) == PCI_CAPABILITY_ID_DEBUG_PORT) {
+      Flag = TRUE;
+      break;
+    }
+    if ((((Capability & XHC_NEXT_CAPABILITY_MASK) >> 8) & XHC_CAPABILITY_ID_MASK) == 0) {
+      //
+      // Reach the end of list, quit
+      //
+      break;
+    }
+    CapabilityPointer += ((Capability & XHC_NEXT_CAPABILITY_MASK) >> 8) * 4;
+    Capability = MmioRead32 ((UINTN)CapabilityPointer);
+  }
+
+  if (Flag) {
+    Instance = (USB3_DEBUG_PORT_INSTANCE *)(UINTN) MmioRead32 ((UINTN) (CapabilityPointer + XHC_DC_DCDDI2));
+
+    if (Instance != NULL) {
+      FixUsb3InstanceResource (Instance, XhcMmioBase);
+    }
+  }
+
+  //
+  // Restore Command Register
+  //
+  PciWrite16(PCI_LIB_ADDRESS (Bus, Device, Function, PCI_COMMAND_OFFSET), Command);
+
+  return Instance;
+}
+
+
+/**
+  Initialize USB3 debug port.
+
+  This method invokes various internal functions to facilitate
+  detection and initialization of USB3 debug port.
+
+  @retval RETURN_SUCCESS        The USB3 debug port was initialized.
+**/
+RETURN_STATUS
+EFIAPI
+USB3Initialize (
+  VOID
+  )
+{
+  //
+  // Leave it empty, we assume PEI phase already do initialization
+  //
+  return RETURN_SUCCESS;
+}
+
+/**
+  Initialize USB3 debug port.
+
+  This method invokes various internal functions to facilitate
+  detection and initialization of USB3 debug port.
+
+  @retval RETURN_SUCCESS        The serial device was initialized.
+**/
+RETURN_STATUS
+EFIAPI
+USB3InitializeReal (
+  VOID
+  )
+{
+  USB3_DEBUG_PORT_INSTANCE    UsbDbg;
+  USB3_DEBUG_PORT_INSTANCE    *Instance;
+  EFI_PHYSICAL_ADDRESS        Address;
+  EFI_STATUS                  Status;
+  EFI_EVENT                   Event;
+
+  if ((gST == NULL) || (gBS == NULL)) {
+    //
+    // gST and gBS have not been initialized yet
+    //
+    return EFI_DEVICE_ERROR;
+  }
+
+  Status = EfiGetSystemConfigurationTable (&gUsb3DbgGuid, (VOID **) &mUsb3Instance);
+  if (!EFI_ERROR (Status)) {
+    goto Done;
+  }
+
+  //
+  // It is first time to run DXE instance, copy Instance from Hob to ACPINvs
+  // NOTE: Hob is not ready at this time, so copy it from XHCI register.
+  //
+  Instance = GetUsb3DebugPortInstance ();
+  if (Instance == NULL) {
+    //
+    // Initialize USB debug
+    //
+    SetMem (&UsbDbg, sizeof(UsbDbg), 0);
+    DiscoverUsb3DebugPort (&UsbDbg);
+    if (UsbDbg.DebugSupport) {
+      InitializeUsb3DebugPort (&UsbDbg);
+    }
+    Instance = &UsbDbg;
+  }
+  Address = SIZE_4GB;
+  Status = gBS->AllocatePages (
+                  AllocateMaxAddress,
+                  EfiACPIMemoryNVS,
+                  EFI_SIZE_TO_PAGES (sizeof (USB3_DEBUG_PORT_INSTANCE)),
+                  &Address
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  CopyMem (
+    (VOID *)(UINTN)Address,
+    Instance,
+    sizeof (USB3_DEBUG_PORT_INSTANCE)
+    );
+  mUsb3Instance = (USB3_DEBUG_PORT_INSTANCE *)(UINTN)Address;
+
+  Status = gBS->InstallConfigurationTable (&gUsb3DbgGuid, mUsb3Instance);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  if (mUsb3Instance->DebugSupport) {
+    SaveUsb3InstanceAddress (mUsb3Instance);
+  }
+
+Done:
+  if ((mUsb3Instance != NULL) && mUsb3Instance->Ready && (mUsb3Instance->PciIoEvent == 0)) {
+    Status = Usb3NamedEventListen (
+               &gEfiPciIoProtocolGuid,
+               TPL_NOTIFY,
+               Usb3PciIoNotify,
+               &Event
+               );
+    if (!EFI_ERROR (Status)) {
+      mUsb3Instance->PciIoEvent = (EFI_PHYSICAL_ADDRESS) (UINTN) Event;
+    }
+  }
+
+  return RETURN_SUCCESS;
+}
+
+/**
+  Calculate the size of XHCI MMIO space.
+
+  @retval     TURE         The XHCI MMIO is in SMRAM ranges.
+  @retval     FALSE        The XHCI MMIO is out of SMRAM ranges.
+**/
+UINT64
+CalculateMmioSize (
+  VOID
+  )
+{
+  UINT8                       Bus;
+  UINT8                       Device;
+  UINT8                       Function;
+  UINT32                      Value;
+  UINT32                      Mask;
+  UINT64                      MmioSize;
+  UINT16                      Command;
+  USB3_DEBUG_PORT_CONTROLLER  UsbDebugPort;
+  EFI_PHYSICAL_ADDRESS        XhcMmioBase;
+
+  UsbDebugPort.Controller = GetUsb3DebugPortController();
+  Bus      = UsbDebugPort.PciAddress.Bus;
+  Device   = UsbDebugPort.PciAddress.Device;
+  Function = UsbDebugPort.PciAddress.Function;
+
+  Mask     = 0xFFFFFFF0;
+  MmioSize = 0;
+
+  XhcMmioBase = GetXhciBaseAddress ();
+
+  //
+  // Disable MSE
+  //
+  Command = PciRead16 (PCI_LIB_ADDRESS(Bus, Device, Function, PCI_COMMAND_OFFSET));
+  PciWrite16 (PCI_LIB_ADDRESS (Bus, Device, Function, PCI_COMMAND_OFFSET), Command & ~(EFI_PCI_COMMAND_MEMORY_SPACE));
+
+  //
+  // Get Mmio Size
+  //
+  PciWrite32 (PCI_LIB_ADDRESS(Bus, Device, Function, PCI_BASE_ADDRESSREG_OFFSET), 0xFFFFFFFF);
+  Value    = PciRead32 (PCI_LIB_ADDRESS(Bus, Device, Function, PCI_BASE_ADDRESSREG_OFFSET));
+
+  switch (Value & 0x07) {
+    case 0x0:
+      //
+      // Memory space: anywhere in 32 bit address space
+      //
+      MmioSize = (~(Value & Mask)) + 1;
+      break;
+    case 0x4:
+      //
+      // Memory space: anywhere in 64 bit address space
+      //
+      MmioSize = Value & Mask;
+      PciWrite32 (PCI_LIB_ADDRESS(Bus, Device, Function, PCI_BASE_ADDRESSREG_OFFSET + 4), 0xFFFFFFFF);
+      Value    = PciRead32 (PCI_LIB_ADDRESS(Bus, Device, Function, PCI_BASE_ADDRESSREG_OFFSET + 4));
+      //
+      // Fix the length to support some spefic 64 bit BAR
+      //
+      Value |= ((UINT32)(-1) << HighBitSet32 (Value));
+      //
+      // Calculate the size of 64bit bar
+      //
+      MmioSize  |= LShiftU64 ((UINT64) Value, 32);
+      MmioSize  = (~(MmioSize)) + 1;
+      break;
+    default:
+      //
+      // Unknown BAR type
+      //
+      MmioSize = (~(Value & Mask)) + 1;
+      break;
+  };
+
+
+  //
+  // Restore MMIO address
+  //
+  PciWrite32 (PCI_LIB_ADDRESS(Bus, Device, Function, PCI_BASE_ADDRESSREG_OFFSET), (UINT32)XhcMmioBase);
+  PciWrite32 (PCI_LIB_ADDRESS(Bus, Device, Function, PCI_BASE_ADDRESSREG_OFFSET + 4), (UINT32) (XhcMmioBase >> 32));
+
+  PciWrite16 (PCI_LIB_ADDRESS (Bus, Device, Function, PCI_COMMAND_OFFSET), Command | EFI_PCI_COMMAND_MEMORY_SPACE);
+
+  return MmioSize;
+}
+
+/**
+  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
+Usb3DebugPortLibDxeConstructor (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_SMM_BASE2_PROTOCOL        *SmmBase;
+  EFI_SMM_ACCESS2_PROTOCOL      *SmmAccess;
+  UINTN                         Size;
+  EFI_STATUS                    Status;
+
+  //
+  // Do real initialization here, because we need copy data from Hob to ACPINvs.
+  // We must do it in constructor because it depends on UefiBootServicesTableLib.
+  //
+  if (FeaturePcdGet (PcdStatusCodeUseUsb3Serial)) {
+    USB3InitializeReal ();
+  }
+
+  mUsb3MmioSize = CalculateMmioSize ();
+
+  if (gBS != NULL) {
+    SmmBase = NULL;
+    Status = gBS->LocateProtocol (&gEfiSmmBase2ProtocolGuid, NULL, (VOID **)&SmmBase);
+    if (!EFI_ERROR (Status)) {
+      SmmBase->InSmm(SmmBase, &mUsb3InSmm);
+    }
+
+    if (mUsb3InSmm) {
+      //
+      // Get SMRAM information
+      //
+      SmmAccess = NULL;
+      Status = gBS->LocateProtocol (&gEfiSmmAccess2ProtocolGuid, NULL, (VOID **)&SmmAccess);
+      if (!EFI_ERROR (Status)) {
+        Size = sizeof (mSmramCheckRanges);
+
+        Status = SmmAccess->GetCapabilities (SmmAccess, &Size, mSmramCheckRanges);
+        if (!EFI_ERROR (Status)) {
+          mSmramCheckRangeCount = Size / sizeof (EFI_SMRAM_DESCRIPTOR);
+        }
+      }
+    }
+  }
+
+  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
+Usb3DebugPortLibDxeDestructor (
+  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;
+}
+
+/**
+  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
+  )
+{
+  VOID                    *Buf;
+  EFI_PHYSICAL_ADDRESS    Address;
+  EFI_STATUS              Status;
+
+  Buf = NULL;
+
+  if (gBS != NULL) {
+    if (mUsb3PciIo != NULL) {
+      Usb3AllocateDmaBuffer (
+        mUsb3PciIo,
+        EFI_SIZE_TO_PAGES (BufferSize),
+        &Buf
+        );
+    } else {
+      Address = 0xFFFFFFFF;
+      Status = gBS->AllocatePages (
+                      AllocateMaxAddress,
+                      EfiACPIMemoryNVS,
+                      EFI_SIZE_TO_PAGES (BufferSize),
+                      &Address
+                      );
+      if (!EFI_ERROR (Status)) {
+        Buf = (VOID *)(UINTN)Address;
+      }
+    }
+  }
+
+  return Buf;
+}
+
+/**
+  Check whether AllocatePages in permanent memory is ready.
+
+  @retval TRUE  AllocatePages in permanent memory is ready.
+  @retval FALSE AllocatePages in permanent memory is not ready.
+
+**/
+BOOLEAN
+IsAllocatePagesReady (
+  VOID
+  )
+{
+  if (gBS != NULL) {
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
diff --git a/Platform/Intel/DebugFeaturePkg/Library/Usb3DebugPortLib/Usb3DebugPortLibDxeIoMmu.inf b/Platform/Intel/DebugFeaturePkg/Library/Usb3DebugPortLib/Usb3DebugPortLibDxeIoMmu.inf
new file mode 100644
index 0000000000..7e84d26864
--- /dev/null
+++ b/Platform/Intel/DebugFeaturePkg/Library/Usb3DebugPortLib/Usb3DebugPortLibDxeIoMmu.inf
@@ -0,0 +1,63 @@
+## @file
+#  Usb3 debug port library.
+#
+# Copyright (c) 2013 - 2019, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = Usb3DebugPortLibDxeIoMmu
+  FILE_GUID                      = BC48A65D-5E5E-4512-8ACC-90E79E2D80C2
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = Usb3DebugPortLib|DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SAL_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER SMM_CORE
+  CONSTRUCTOR                    = Usb3DebugPortLibDxeConstructor
+  DESTRUCTOR                     = Usb3DebugPortLibDxeDestructor
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 IPF
+#
+
+[Sources]
+  Usb3DebugPortLibDxeIoMmu.c
+  Usb3DebugPortDataTransfer.c
+  Usb3DebugPortInitialize.c
+  MiscServices.c
+  Usb3DebugPortLibInternal.h
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  DebugFeaturePkg/DebugFeaturePkg.dec
+
+[LibraryClasses]
+  BaseLib
+  PcdLib
+  IoLib
+  PciLib
+  TimerLib
+  UefiBootServicesTableLib
+  UefiLib
+  HobLib
+  Usb3DebugPortParameterLib
+
+[Protocols]
+  gEfiSmmAccess2ProtocolGuid                       ## CONSUMES
+  gEfiSmmBase2ProtocolGuid                         ## CONSUMES
+   ## NOTIFY
+   ## SOMETIMES_CONSUMES
+  gEfiPciIoProtocolGuid
+  gEdkiiIoMmuProtocolGuid                          ## SOMETIMES_CONSUMES
+   ## NOTIFY
+  gEfiDxeSmmReadyToLockProtocolGuid
+
+[Pcd]
+  gEfiUsb3DebugPortTokenSpaceGuid.PcdXhciDefaultBaseAddress     ## SOMETIMES_CONSUMES
+  gEfiUsb3DebugPortTokenSpaceGuid.PcdXhciHostWaitTimeout        ## CONSUMES
+
+[FeaturePcd]
+  gEfiUsb3DebugPortTokenSpaceGuid.PcdStatusCodeUseUsb3Serial    ## CONSUMES
diff --git a/Platform/Intel/DebugFeaturePkg/Library/Usb3DebugPortLib/Usb3DebugPortLibInternal.h b/Platform/Intel/DebugFeaturePkg/Library/Usb3DebugPortLib/Usb3DebugPortLibInternal.h
new file mode 100644
index 0000000000..3641cc1d52
--- /dev/null
+++ b/Platform/Intel/DebugFeaturePkg/Library/Usb3DebugPortLib/Usb3DebugPortLibInternal.h
@@ -0,0 +1,887 @@
+/** @file
+  This library class provides common Usb debug port functions.
+
+  Copyright (c) 2013 - 2019, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __USB3_DEBUG_PORT_LIB_INTERNAL__
+#define __USB3_DEBUG_PORT_LIB_INTERNAL__
+
+#include <Uefi.h>
+#include <IndustryStandard/Usb.h>
+#include <Library/IoLib.h>
+#include <IndustryStandard/Pci.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/BaseLib.h>
+#include <Library/TimerLib.h>
+
+//
+// USB Debug GUID value
+//
+#define USB3_DBG_GUID \
+    { \
+      0xb2a56f4d, 0x9177, 0x4fc8, { 0xa6, 0x77, 0xdd, 0x96, 0x3e, 0xb4, 0xcb, 0x1b } \
+    }
+
+//
+// Define the maximum of SMRAM ranges
+//
+#define MAX_SMRAM_RANGE     8
+
+#define XHCI_DEBUG_DEVICE_VENDOR_ID   0x8086
+#define XHCI_DEBUG_DEVICE_PRODUCT_ID  0x1234
+#define XHCI_DEBUG_DEVICE_PROTOCOL    0xFF
+#define XHCI_DEBUG_DEVICE_REVISION    0x00
+
+#define XHCI_BASE_ADDRESS_64_BIT_MASK 0xFFFFFFFFFFFF0000ULL
+#define XHCI_BASE_ADDRESS_32_BIT_MASK 0xFFFF0000
+
+#define PCI_CAPABILITY_ID_DEBUG_PORT  0x0A
+#define XHC_HCCPARAMS_OFFSET          0x10
+#define XHC_CAPABILITY_ID_MASK        0xFF
+#define XHC_NEXT_CAPABILITY_MASK      0xFF00
+
+#define XHC_USBCMD_OFFSET             0x0 // USB Command Register Offset
+#define XHC_USBSTS_OFFSET             0x4 // USB Status Register Offset
+
+#define XHC_USBCMD_RUN                BIT0  // Run/Stop
+#define XHC_USBCMD_RESET              BIT1  // Host Controller Reset
+
+#define XHC_USBSTS_HALT               BIT0
+
+//
+// Transfer the data of 8 bytes each time
+//
+#define XHC_DEBUG_PORT_DATA_LENGTH   8
+
+//
+// Indicate the timeout when data is transferred. 0 means infinite timeout.
+//
+#define DATA_TRANSFER_TIME_OUT       0
+
+//
+// USB debug device string descritpor (header size + unicode string length)
+//
+#define STRING0_DESC_LEN      4
+#define MANU_DESC_LEN         12
+#define PRODUCT_DESC_LEN      40
+#define SERIAL_DESC_LEN       4
+
+//
+// Debug Capability Register Offset
+//
+#define XHC_DC_DCID                  0x0
+#define XHC_DC_DCDB                  0x4
+#define XHC_DC_DCERSTSZ              0x8
+#define XHC_DC_DCERSTBA              0x10
+#define XHC_DC_DCERDP                0x18
+#define XHC_DC_DCCTRL                0x20
+#define XHC_DC_DCST                  0x24
+#define XHC_DC_DCPORTSC              0x28
+#define XHC_DC_DCCP                  0x30
+#define XHC_DC_DCDDI1                0x38
+#define XHC_DC_DCDDI2                0x3C
+
+#define TRB_TYPE_LINK                6
+
+#define ERST_NUMBER                  0x01
+#define TR_RING_TRB_NUMBER           0x100
+#define EVENT_RING_TRB_NUMBER        0x200
+#define CMD_RING_TRB_NUMBER          0x100
+
+#define ED_BULK_OUT                  2
+#define ED_BULK_IN                   6
+
+#define XHC_LOW_32BIT(Addr64)          ((UINT32)(((UINTN)(Addr64)) & 0xFFFFFFFF))
+#define XHC_HIGH_32BIT(Addr64)         ((UINT32)(RShiftU64((UINT64)(UINTN)(Addr64), 32) & 0xFFFFFFFF))
+#define XHC_BIT_IS_SET(Data, Bit)      ((BOOLEAN)(((Data) & (Bit)) == (Bit)))
+
+#define XHC_REG_BIT_IS_SET(Xhc, Offset, Bit) \
+          (XHC_BIT_IS_SET(XhcReadMmioReg ((Xhc), (Offset)), (Bit)))
+
+//
+// Endpoint Type (EP Type).
+//
+#define ED_NOT_VALID                          0
+#define ED_ISOCH_OUT                          1
+#define ED_BULK_OUT                           2
+#define ED_INTERRUPT_OUT                      3
+#define ED_CONTROL_BIDIR                      4
+#define ED_ISOCH_IN                           5
+#define ED_BULK_IN                            6
+#define ED_INTERRUPT_IN                       7
+
+//
+// 6.4.5 TRB Completion Codes
+//
+#define TRB_COMPLETION_INVALID                0
+#define TRB_COMPLETION_SUCCESS                1
+#define TRB_COMPLETION_DATA_BUFFER_ERROR      2
+#define TRB_COMPLETION_BABBLE_ERROR           3
+#define TRB_COMPLETION_USB_TRANSACTION_ERROR  4
+#define TRB_COMPLETION_TRB_ERROR              5
+#define TRB_COMPLETION_STALL_ERROR            6
+#define TRB_COMPLETION_SHORT_PACKET           13
+
+//
+// 6.4.6 TRB Types
+//
+#define TRB_TYPE_NORMAL                       1
+#define TRB_TYPE_SETUP_STAGE                  2
+#define TRB_TYPE_DATA_STAGE                   3
+#define TRB_TYPE_STATUS_STAGE                 4
+#define TRB_TYPE_ISOCH                        5
+#define TRB_TYPE_LINK                         6
+#define TRB_TYPE_EVENT_DATA                   7
+#define TRB_TYPE_NO_OP                        8
+#define TRB_TYPE_EN_SLOT                      9
+#define TRB_TYPE_DIS_SLOT                     10
+#define TRB_TYPE_ADDRESS_DEV                  11
+#define TRB_TYPE_CON_ENDPOINT                 12
+#define TRB_TYPE_EVALU_CONTXT                 13
+#define TRB_TYPE_RESET_ENDPOINT               14
+#define TRB_TYPE_STOP_ENDPOINT                15
+#define TRB_TYPE_SET_TR_DEQUE                 16
+#define TRB_TYPE_RESET_DEV                    17
+#define TRB_TYPE_GET_PORT_BANW                21
+#define TRB_TYPE_FORCE_HEADER                 22
+#define TRB_TYPE_NO_OP_COMMAND                23
+#define TRB_TYPE_TRANS_EVENT                  32
+#define TRB_TYPE_COMMAND_COMPLT_EVENT         33
+#define TRB_TYPE_PORT_STATUS_CHANGE_EVENT     34
+#define TRB_TYPE_HOST_CONTROLLER_EVENT        37
+#define TRB_TYPE_DEVICE_NOTIFI_EVENT          38
+#define TRB_TYPE_MFINDEX_WRAP_EVENT           39
+
+//
+// Convert millisecond to microsecond.
+//
+#define XHC_1_MILLISECOND                     (1000)
+#define XHC_POLL_DELAY                        (1000)
+#define XHC_GENERIC_TIMEOUT                   (10 * 1000)
+
+#define EFI_USB_SPEED_FULL                    0x0000  ///< 12 Mb/s, USB 1.1 OHCI and UHCI HC.
+#define EFI_USB_SPEED_LOW                     0x0001  ///< 1 Mb/s, USB 1.1 OHCI and UHCI HC.
+#define EFI_USB_SPEED_HIGH                    0x0002  ///< 480 Mb/s, USB 2.0 EHCI HC.
+#define EFI_USB_SPEED_SUPER                   0x0003  ///< 4.8 Gb/s, USB 3.0 XHCI HC.
+
+//
+// Transfer types, used in URB to identify the transfer type
+//
+#define XHC_CTRL_TRANSFER                     0x01
+#define XHC_BULK_TRANSFER                     0x02
+#define XHC_INT_TRANSFER_SYNC                 0x04
+#define XHC_INT_TRANSFER_ASYNC                0x08
+#define XHC_INT_ONLY_TRANSFER_ASYNC           0x10
+
+//
+// USB Transfer Results
+//
+#define EFI_USB_NOERROR             0x00
+#define EFI_USB_ERR_NOTEXECUTE      0x01
+#define EFI_USB_ERR_STALL           0x02
+#define EFI_USB_ERR_BUFFER          0x04
+#define EFI_USB_ERR_BABBLE          0x08
+#define EFI_USB_ERR_NAK             0x10
+#define EFI_USB_ERR_CRC             0x20
+#define EFI_USB_ERR_TIMEOUT         0x40
+#define EFI_USB_ERR_BITSTUFF        0x80
+#define EFI_USB_ERR_SYSTEM          0x100
+
+#define USB3_DEBUG_PORT_INSTANCE_SIGNATURE   SIGNATURE_32('D', 'B', 'G', 'P')
+
+#pragma pack(1)
+
+//
+// 7.6.9 OUT/IN EP Context: 64 bytes
+// 7.6.9.2 When used by the DbC it is always a 64 byte data structure
+//
+typedef struct _ENDPOINT_CONTEXT_64 {
+  UINT32                  EPState:3;
+  UINT32                  RsvdZ1:5;
+  UINT32                  Mult:2;         // set to 0
+  UINT32                  MaxPStreams:5;  // set to 0
+  UINT32                  LSA:1;          // set to 0
+  UINT32                  Interval:8;     // set to 0
+  UINT32                  RsvdZ2:8;
+
+  UINT32                  RsvdZ3:1;
+  UINT32                  CErr:2;
+  UINT32                  EPType:3;
+  UINT32                  RsvdZ4:1;
+  UINT32                  HID:1;          // set to 0
+  UINT32                  MaxBurstSize:8;
+  UINT32                  MaxPacketSize:16;
+
+  UINT32                  PtrLo;
+
+  UINT32                  PtrHi;
+
+  UINT32                  AverageTRBLength:16;
+  UINT32                  MaxESITPayload:16;  // set to 0
+
+  UINT32                  RsvdZ5;             // Reserved
+  UINT32                  RsvdZ6;
+  UINT32                  RsvdZ7;
+
+  UINT32                  RsvdZ8;
+  UINT32                  RsvdZ9;
+  UINT32                  RsvdZ10;
+  UINT32                  RsvdZ11;
+
+  UINT32                  RsvdZ12;
+  UINT32                  RsvdZ13;
+  UINT32                  RsvdZ14;
+  UINT32                  RsvdZ15;
+} ENDPOINT_CONTEXT_64;
+
+//
+// 6.4.1.1 Normal TRB: 16 bytes
+// A Normal TRB is used in several ways; exclusively on Bulk and Interrupt Transfer Rings for normal and
+// Scatter/Gather operations, to define additional data buffers for Scatter/Gather operations on Isoch Transfer
+// Rings, and to define the Data stage information for Control Transfer Rings.
+//
+typedef struct _TRANSFER_TRB_NORMAL {
+  UINT32                  TRBPtrLo;
+
+  UINT32                  TRBPtrHi;
+
+  UINT32                  Length:17;
+  UINT32                  TDSize:5;
+  UINT32                  IntTarget:10;
+
+  UINT32                  CycleBit:1;
+  UINT32                  ENT:1;
+  UINT32                  ISP:1;
+  UINT32                  NS:1;
+  UINT32                  CH:1;
+  UINT32                  IOC:1;
+  UINT32                  IDT:1;
+  UINT32                  RsvdZ1:2;
+  UINT32                  BEI:1;
+  UINT32                  Type:6;
+  UINT32                  RsvdZ2:16;
+} TRANSFER_TRB_NORMAL;
+
+//
+// 6.4.2.1 Transfer Event TRB: 16 bytes
+// A Transfer Event provides the completion status associated with a Transfer TRB. Refer to section 4.11.3.1
+// for more information on the use and operation of Transfer Events.
+//
+typedef struct _EVT_TRB_TRANSFER {
+  UINT32                  TRBPtrLo;
+
+  UINT32                  TRBPtrHi;
+
+  UINT32                  Length:24;
+  UINT32                  Completecode:8;
+
+  UINT32                  CycleBit:1;
+  UINT32                  RsvdZ1:1;
+  UINT32                  ED:1;
+  UINT32                  RsvdZ2:7;
+  UINT32                  Type:6;
+  UINT32                  EndpointId:5;
+  UINT32                  RsvdZ3:3;
+  UINT32                  SlotId:8;
+} EVT_TRB_TRANSFER;
+
+//
+// 6.4.4.1 Link TRB: 16 bytes
+// A Link TRB provides support for non-contiguous TRB Rings.
+//
+typedef struct _LINK_TRB {
+  UINT32                  PtrLo;
+
+  UINT32                  PtrHi;
+
+  UINT32                  RsvdZ1:22;
+  UINT32                  InterTarget:10;
+
+  UINT32                  CycleBit:1;
+  UINT32                  TC:1;
+  UINT32                  RsvdZ2:2;
+  UINT32                  CH:1;
+  UINT32                  IOC:1;
+  UINT32                  RsvdZ3:4;
+  UINT32                  Type:6;
+  UINT32                  RsvdZ4:16;
+} LINK_TRB;
+
+//
+// TRB Template: 16 bytes
+//
+typedef struct _TRB_TEMPLATE {
+  UINT32                    Parameter1;
+
+  UINT32                    Parameter2;
+
+  UINT32                    Status;
+
+  UINT32                    CycleBit:1;
+  UINT32                    RsvdZ1:9;
+  UINT32                    Type:6;
+  UINT32                    Control:16;
+} TRB_TEMPLATE;
+
+//
+// Refer to XHCI 6.5 Event Ring Segment Table: 16 bytes
+//
+typedef struct _EVENT_RING_SEG_TABLE_ENTRY {
+  UINT32                  PtrLo;
+  UINT32                  PtrHi;
+  UINT32                  RingTrbSize:16;
+  UINT32                  RsvdZ1:16;
+  UINT32                  RsvdZ2;
+} EVENT_RING_SEG_TABLE_ENTRY;
+
+//
+// Size: 40 bytes
+//
+typedef struct _EVENT_RING {
+  EFI_PHYSICAL_ADDRESS      ERSTBase;
+  EFI_PHYSICAL_ADDRESS      EventRingSeg0;
+  UINT32                    TrbNumber;
+  EFI_PHYSICAL_ADDRESS      EventRingEnqueue;
+  EFI_PHYSICAL_ADDRESS      EventRingDequeue;
+  UINT32                    EventRingCCS;
+} EVENT_RING;
+
+// Size: 32 bytes
+typedef struct _TRANSFER_RING {
+  EFI_PHYSICAL_ADDRESS      RingSeg0;
+  UINT32                    TrbNumber;
+  EFI_PHYSICAL_ADDRESS      RingEnqueue;
+  EFI_PHYSICAL_ADDRESS      RingDequeue;
+  UINT32                    RingPCS;
+} TRANSFER_RING;
+
+//
+// Size: 64 bytes
+//
+typedef struct _DBC_INFO_CONTEXT {
+  UINT64        String0DescAddress;
+  UINT64        ManufacturerStrDescAddress;
+  UINT64        ProductStrDescAddress;
+  UINT64        SerialNumberStrDescAddress;
+  UINT64        String0Length:8;
+  UINT64        ManufacturerStrLength:8;
+  UINT64        ProductStrLength:8;
+  UINT64        SerialNumberStrLength:8;
+  UINT64        RsvdZ1:32;
+  UINT64        RsvdZ2;
+  UINT64        RsvdZ3;
+  UINT64        RsvdZ4;
+} DBC_INFO_CONTEXT;
+
+//
+// Debug Capability Context Data Structure: 192 bytes
+//
+typedef struct _XHC_DC_CONTEXT {
+  DBC_INFO_CONTEXT      DbcInfoContext;
+  ENDPOINT_CONTEXT_64   EpOutContext;
+  ENDPOINT_CONTEXT_64   EpInContext;
+} XHC_DC_CONTEXT;
+
+//
+// Size: 16 bytes
+//
+typedef union _TRB {
+  TRB_TEMPLATE                TrbTemplate;
+  TRANSFER_TRB_NORMAL         TrbNormal;
+} TRB;
+
+///
+/// USB data transfer direction
+///
+typedef enum {
+  EfiUsbDataIn,
+  EfiUsbDataOut,
+  EfiUsbNoData
+} EFI_USB_DATA_DIRECTION;
+
+//
+// URB (Usb Request Block) contains information for all kinds of
+// usb requests.
+//
+typedef struct _URB {
+  UINT32                          Signature;
+  //
+  // Transfer data
+  //
+  EFI_PHYSICAL_ADDRESS            Data;
+  UINT32                          DataLen;
+  //
+  // Execute result
+  //
+  UINT32                          Result;
+  //
+  // Completed data length
+  //
+  UINT32                          Completed;
+  //
+  // Tranfer Ring info
+  //
+  EFI_PHYSICAL_ADDRESS            Ring;
+  EFI_PHYSICAL_ADDRESS            TrbStart;
+  EFI_PHYSICAL_ADDRESS            TrbEnd;
+  UINT32                          TrbNum;
+  BOOLEAN                         StartDone;
+  BOOLEAN                         EndDone;
+  BOOLEAN                         Finished;
+  EFI_USB_DATA_DIRECTION          Direction;
+} URB;
+
+//
+// Size: 90 bytes
+//
+typedef struct _USB3_DEBUG_PORT_INSTANCE {
+  UINT32                                  Signature;
+
+  UINT8                                   PciBusNumber;
+  UINT8                                   PciDeviceNumber;
+  UINT8                                   PciFunctionNumber;
+
+  //
+  // The flag indicates debug capability is supported
+  //
+  BOOLEAN                                 DebugSupport;
+
+  //
+  // The flag indicates debug device is ready
+  //
+  BOOLEAN                                 Ready;
+
+  //
+  // The flag indicates the instance is from HOB
+  //
+  BOOLEAN                                 FromHob;
+
+  //
+  // PciIo protocol event
+  //
+  EFI_PHYSICAL_ADDRESS                    PciIoEvent;
+
+  //
+  // XHCI MMIO Base address
+  //
+  EFI_PHYSICAL_ADDRESS                    XhcMmioBase;
+
+  //
+  // XHCI OP RegisterBase address
+  //
+  EFI_PHYSICAL_ADDRESS                    XhciOpRegister;
+
+  //
+  // XHCI Debug Register Base Address
+  //
+  EFI_PHYSICAL_ADDRESS                    DebugCapabilityBase;
+
+  //
+  // XHCI Debug Capability offset
+  //
+  UINT64                                  DebugCapabilityOffset;
+
+  //
+  // XHCI Debug Context Address
+  //
+  EFI_PHYSICAL_ADDRESS                    DebugCapabilityContext;
+
+  //
+  // Transfer Ring
+  //
+  TRANSFER_RING                           TransferRingOut;
+  TRANSFER_RING                           TransferRingIn;
+
+  //
+  // EventRing
+  //
+  EVENT_RING                              EventRing;
+
+  //
+  // URB
+  //
+  URB                                     Urb;
+} USB3_DEBUG_PORT_INSTANCE;
+
+#pragma pack()
+
+/**
+  Clear one bit of the debug register while keeping other bits.
+
+  @param  Xhc          The XHCI Instance.
+  @param  Offset       The offset of the debug register.
+  @param  Bit          The bit mask of the register to set.
+
+**/
+VOID
+XhcClearDebugRegBit (
+  IN USB3_DEBUG_PORT_INSTANCE *Xhc,
+  IN UINT32                   Offset,
+  IN UINT32                   Bit
+  );
+
+/**
+  Clear one bit of the MMIO register while keeping other bits.
+
+  @param  Xhc          The XHCI Instance.
+  @param  Offset       The offset of the MMIO register.
+  @param  Bit          The bit mask of the register to set.
+
+**/
+VOID
+XhcClearMmioRegBit (
+  IN USB3_DEBUG_PORT_INSTANCE  *Xhc,
+  IN UINT32                    Offset,
+  IN UINT32                    Bit
+  );
+
+/**
+  Read XHCI debug register.
+
+  @param  Xhc          The XHCI Instance.
+  @param  Offset       The offset of the debug register.
+
+  @return The register content read
+
+**/
+UINT32
+XhcReadDebugReg (
+  IN  USB3_DEBUG_PORT_INSTANCE    *Xhc,
+  IN  UINT32                      Offset
+  );
+
+/**
+  Read XHCI MMIO register.
+
+  @param  Xhc          The XHCI Instance.
+  @param  Offset       The offset of the MMIO register.
+
+  @return The register content read
+
+**/
+UINT32
+XhcReadMmioReg (
+  IN  USB3_DEBUG_PORT_INSTANCE    *Xhc,
+  IN  UINT32                      Offset
+  );
+
+/**
+  Set one bit of the debug register while keeping other bits.
+
+  @param  Xhc          The XHCI Instance.
+  @param  Offset       The offset of the debug register.
+  @param  Bit          The bit mask of the register to set.
+
+**/
+VOID
+XhcSetDebugRegBit (
+  IN USB3_DEBUG_PORT_INSTANCE *Xhc,
+  IN UINT32                   Offset,
+  IN UINT32                   Bit
+  );
+
+/**
+  Set one bit of the MMIO register while keeping other bits.
+
+  @param  Xhc          The XHCI Instance.
+  @param  Offset       The offset of the MMIO register.
+  @param  Bit          The bit mask of the register to set.
+
+**/
+VOID
+XhcSetMmioRegBit (
+  IN USB3_DEBUG_PORT_INSTANCE   *Xhc,
+  IN UINT32                     Offset,
+  IN UINT32                     Bit
+  );
+
+/**
+  Wait the MMIO register's bit as specified by Bit
+  to be set (or clear).
+
+  @param  Xhc          The XHCI Instance.
+  @param  Offset       The offset of the MMIO register.
+  @param  Bit          The bit of the register to wait for.
+  @param  WaitToSet    Wait the bit to set or clear.
+  @param  Timeout      The time to wait before abort (in millisecond, ms).
+
+  @retval EFI_SUCCESS  The bit successfully changed by host controller.
+  @retval EFI_TIMEOUT  The time out occurred.
+
+**/
+EFI_STATUS
+XhcWaitMmioRegBit (
+  IN USB3_DEBUG_PORT_INSTANCE  *Xhc,
+  IN UINT32                    Offset,
+  IN UINT32                    Bit,
+  IN BOOLEAN                   WaitToSet,
+  IN UINT32                    Timeout
+  );
+
+/**
+  Write the data to the debug register.
+
+  @param  Xhc          The XHCI Instance.
+  @param  Offset       The offset of the debug register.
+  @param  Data         The data to write.
+
+**/
+VOID
+XhcWriteDebugReg (
+  IN USB3_DEBUG_PORT_INSTANCE   *Xhc,
+  IN UINT32                     Offset,
+  IN UINT32                     Data
+  );
+
+/**
+  Write the data to the MMIO register.
+
+  @param  Xhc          The XHCI Instance.
+  @param  Offset       The offset of the MMIO register.
+  @param  Data         The data to write.
+
+**/
+VOID
+XhcWriteMmioReg (
+  IN USB3_DEBUG_PORT_INSTANCE   *Xhc,
+  IN UINT32                     Offset,
+  IN UINT32                     Data
+  );
+
+/**
+  Discover the USB3 debug device.
+
+  @param[in] Instance           Pointer to USB3 debug port object instance.
+
+  @retval RETURN_SUCCESS        The USB3 debug device was found.
+  @retval RETURN_DEVICE_ERROR   The USB3 debug device was not found.
+
+**/
+RETURN_STATUS
+DiscoverUsb3DebugPort(
+  IN USB3_DEBUG_PORT_INSTANCE   *Instance
+  );
+
+/**
+  Initialize the USB3 debug Device hardware.
+
+  @param[in] Instance       Pointer to USB3 debug port object instance.
+
+  @retval RETURN_SUCCESS    The USB3 debug device was initialized successfully.
+  @retval !RETURN_SUCCESS   Error.
+
+**/
+RETURN_STATUS
+InitializeUsb3DebugPort (
+  IN USB3_DEBUG_PORT_INSTANCE   *Instance
+  );
+
+/**
+  Return XHCI MMIO base address.
+
+**/
+EFI_PHYSICAL_ADDRESS
+GetXhciBaseAddress (
+  VOID
+  );
+
+/**
+  Return XHCI debug instance address.
+
+**/
+USB3_DEBUG_PORT_INSTANCE *
+GetUsb3DebugPortInstance (
+  VOID
+  );
+
+/**
+  Send data over the USB3 debug cable.
+
+  @param[out]      Data    Pointer to data
+  @param[in, out]  Length  Pointer to data length
+
+**/
+VOID
+Usb3DbgOut (
+  OUT      UINT8                           *Data,
+  IN OUT   UINTN                           *Length
+  );
+
+/**
+  Receive data over the USB3 debug cable.
+
+  @param[out]     Data      Pointer to data
+  @param[in, out] Length    Pointer to data length
+
+**/
+RETURN_STATUS
+Usb3DbgIn (
+      OUT UINT8                           *Data,
+  IN  OUT UINTN                           *Length
+  );
+
+/**
+  Verifies if the bit positions specified by a mask are set in a register.
+
+  @param[in, out] Register    UNITN register
+  @param[in]      BitMask     32-bit mask
+
+  @return  BOOLEAN  - TRUE  if all bits specified by the mask are enabled.
+                    - FALSE even if one of the bits specified by the mask
+                            is not enabled.
+**/
+BOOLEAN
+XhcIsBitSet(
+  UINTN   Register,
+  UINT32  BitMask
+  );
+
+/**
+  Sets bits as per the enabled bit positions in the mask.
+
+  @param[in, out] Register    UINTN register
+  @param[in]      BitMask     32-bit mask
+**/
+VOID
+XhcSetR32Bit(
+  UINTN   Register,
+  UINT32  BitMask
+  );
+
+/**
+  Clears bits as per the enabled bit positions in the mask.
+
+  @param[in, out] Register    UINTN register
+  @param[in]      BitMask     32-bit mask
+**/
+VOID
+XhcClrR32Bit(
+  UINTN   Register,
+  UINT32  BitMask
+  );
+
+/**
+  Initialize USB3 debug port.
+
+  This method invokes various internal functions to facilitate
+  detection and initialization of USB3 debug port.
+
+  @retval RETURN_SUCCESS        The serial device was initialized.
+**/
+RETURN_STATUS
+EFIAPI
+USB3Initialize (
+  VOID
+  );
+
+/**
+  Return command register value in XHCI controller.
+
+**/
+UINT16
+GetXhciPciCommand (
+  VOID
+  );
+
+/**
+  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
+  );
+
+/**
+  Check whether AllocatePages in permanent memory is ready.
+
+  @retval TRUE  AllocatePages in permanent memory is ready.
+  @retval FALSE AllocatePages in permanent memory is not ready.
+
+**/
+BOOLEAN
+IsAllocatePagesReady (
+  VOID
+  );
+
+/**
+  The real function to initialize USB3 debug port.
+
+  This method invokes various internal functions to facilitate
+  detection and initialization of USB3 debug port.
+
+  @retval RETURN_SUCCESS        The serial device was initialized.
+**/
+RETURN_STATUS
+EFIAPI
+USB3InitializeReal (
+  VOID
+  );
+
+/**
+  Update XHC hardware address when MMIO base is changed.
+
+  @param  Instance          The XHCI Instance.
+  @param  XhcMmioBase       XHCI MMIO base address.
+
+**/
+VOID
+FixUsb3InstanceResource (
+  IN OUT USB3_DEBUG_PORT_INSTANCE           *Instance,
+  IN EFI_PHYSICAL_ADDRESS                   XhcMmioBase
+  );
+
+/**
+  Save USB3 instance address.
+
+  @param[in] Instance   The XHCI Instance.
+
+**/
+VOID
+SaveUsb3InstanceAddress (
+  IN USB3_DEBUG_PORT_INSTANCE   *Instance
+  );
+
+/**
+  Submits bulk transfer to a bulk endpoint of a USB device.
+
+  @param  Xhc                   The instance of debug device.
+  @param  Direction             The direction of data transfer.
+  @param  Data                  Array of pointers to the buffers of data to transmit
+                                from or receive into.
+  @param  DataLength            The lenght of the data buffer.
+  @param  Timeout               Indicates the maximum time, in millisecond, which
+                                the transfer is allowed to complete.
+  @param  TransferResult        Transfer result.
+
+  @retval EFI_SUCCESS           The transfer was completed successfully.
+  @retval EFI_OUT_OF_RESOURCES  The transfer failed due to lack of resource.
+  @retval EFI_INVALID_PARAMETER Some parameters are invalid.
+  @retval EFI_TIMEOUT           The transfer failed due to timeout.
+  @retval EFI_DEVICE_ERROR      The transfer failed due to host controller error.
+
+**/
+EFI_STATUS
+EFIAPI
+XhcDataTransfer (
+  IN     USB3_DEBUG_PORT_INSTANCE            *Xhc,
+  IN     EFI_USB_DATA_DIRECTION              Direction,
+  IN OUT VOID                                *Data,
+  IN OUT UINTN                               *DataLength,
+  IN     UINTN                               Timeout,
+  OUT    UINT32                              *TransferResult
+  );
+
+#endif //__SERIAL_PORT_LIB_USB__
diff --git a/Platform/Intel/DebugFeaturePkg/Library/Usb3DebugPortLib/Usb3DebugPortLibNull.c b/Platform/Intel/DebugFeaturePkg/Library/Usb3DebugPortLib/Usb3DebugPortLibNull.c
new file mode 100644
index 0000000000..319cebecbb
--- /dev/null
+++ b/Platform/Intel/DebugFeaturePkg/Library/Usb3DebugPortLib/Usb3DebugPortLibNull.c
@@ -0,0 +1,103 @@
+/** @file
+  Usb Debug Port library NULL instance
+
+  Copyright (c) 2013 - 2019, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Base.h>
+
+/**
+  Initialize the USB3 debug port hardware.
+
+  If no initialization is required, then return RETURN_SUCCESS.
+  If the serial device was successfully initialized, then return RETURN_SUCCESS.
+  If the serial device could not be initialized, then return RETURN_DEVICE_ERROR.
+
+  @retval RETURN_SUCCESS        The serial device was initialized.
+  @retval RETURN_DEVICE_ERROR   The serial device could not be initialized.
+
+**/
+RETURN_STATUS
+EFIAPI
+Usb3DebugPortInitialize (
+  VOID
+  )
+{
+  return RETURN_SUCCESS;
+}
+
+/**
+  Write data from buffer to USB3 debug port.
+
+  Writes NumberOfBytes data bytes from Buffer to the serial device.
+  The number of bytes actually written to the serial device is returned.
+  If the return value is less than NumberOfBytes, then the write operation failed.
+  If Buffer is NULL, then ASSERT().
+  If NumberOfBytes is zero, then return 0.
+
+  @param  Buffer           Pointer to the data buffer to be written.
+  @param  NumberOfBytes    Number of bytes to written to the serial device.
+
+  @retval 0                NumberOfBytes is 0.
+  @retval >0               The number of bytes written to the serial device.
+                           If this value is less than NumberOfBytes, then the read operation failed.
+
+**/
+UINTN
+EFIAPI
+Usb3DebugPortWrite (
+  IN UINT8     *Buffer,
+  IN UINTN     NumberOfBytes
+  )
+{
+  return 0;
+}
+
+
+/**
+  Read data from USB3 debug port and save the datas in buffer.
+
+  Reads NumberOfBytes data bytes from a serial device into the buffer
+  specified by Buffer. The number of bytes actually read is returned.
+  If the return value is less than NumberOfBytes, then the rest operation failed.
+  If Buffer is NULL, then ASSERT().
+  If NumberOfBytes is zero, then return 0.
+
+  @param  Buffer           Pointer to the data buffer to store the data read from the serial device.
+  @param  NumberOfBytes    Number of bytes which will be read.
+
+  @retval 0                Read data failed, no data is to be read.
+  @retval >0               Actual number of bytes read from serial device.
+
+**/
+UINTN
+EFIAPI
+Usb3DebugPortRead (
+  OUT UINT8   *Buffer,
+  IN  UINTN   NumberOfBytes
+  )
+{
+  return 0;
+}
+
+/**
+  Polls a USB3 debug port to see if there is any data waiting to be read.
+
+  Polls a serial device to see if there is any data waiting to be read.
+  If there is data waiting to be read from the serial device, then TRUE is returned.
+  If there is no data waiting to be read from the serial device, then FALSE is returned.
+
+  @retval TRUE             Data is waiting to be read from the serial device.
+  @retval FALSE            There is no data waiting to be read from the serial device.
+
+**/
+BOOLEAN
+EFIAPI
+Usb3DebugPortPoll (
+  VOID
+  )
+{
+  return FALSE;
+}
diff --git a/Platform/Intel/DebugFeaturePkg/Library/Usb3DebugPortLib/Usb3DebugPortLibNull.inf b/Platform/Intel/DebugFeaturePkg/Library/Usb3DebugPortLib/Usb3DebugPortLibNull.inf
new file mode 100644
index 0000000000..f632150c26
--- /dev/null
+++ b/Platform/Intel/DebugFeaturePkg/Library/Usb3DebugPortLib/Usb3DebugPortLibNull.inf
@@ -0,0 +1,28 @@
+## @file
+#  Usb3 debug port library.
+#
+# Copyright (c) 2013 - 2019, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = USB3DebugPortLibNull
+  FILE_GUID                      = 3E895F08-0A69-42a2-AF4A-3E9EFAA40361
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = Usb3DebugPortLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 IPF
+#
+
+[Sources]
+  Usb3DebugPortLibNull.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+
diff --git a/Platform/Intel/DebugFeaturePkg/Library/Usb3DebugPortLib/Usb3DebugPortLibPei.c b/Platform/Intel/DebugFeaturePkg/Library/Usb3DebugPortLib/Usb3DebugPortLibPei.c
new file mode 100644
index 0000000000..a1e0bdbf6d
--- /dev/null
+++ b/Platform/Intel/DebugFeaturePkg/Library/Usb3DebugPortLib/Usb3DebugPortLibPei.c
@@ -0,0 +1,236 @@
+/** @file
+  Usb Debug Port library instance
+
+  Copyright (c) 2013 - 2019, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Base.h>
+
+#include <PiPei.h>
+#include <Library/SerialPortLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PciLib.h>
+#include <Library/HobLib.h>
+#include <Library/PcdLib.h>
+#include <Library/TimerLib.h>
+#include <Library/Usb3DebugPortParameterLib.h>
+#include <Library/PeiServicesTablePointerLib.h>
+#include <Ppi/MemoryDiscovered.h>
+#include "Usb3DebugPortLibInternal.h"
+
+GUID                      gUsb3DbgGuid =  USB3_DBG_GUID;
+
+/**
+  Return XHCI MMIO base address.
+
+**/
+EFI_PHYSICAL_ADDRESS
+GetXhciBaseAddress (
+  VOID
+  )
+{
+  UINT8                       Bus;
+  UINT8                       Device;
+  UINT8                       Function;
+  USB3_DEBUG_PORT_CONTROLLER   UsbDebugPort;
+  EFI_PHYSICAL_ADDRESS        Address;
+  UINT32                      Low;
+  UINT32                      High;
+
+  UsbDebugPort.Controller = GetUsb3DebugPortController();
+  Bus = UsbDebugPort.PciAddress.Bus;
+  Device = UsbDebugPort.PciAddress.Device;
+  Function = UsbDebugPort.PciAddress.Function;
+  Low = PciRead32 (PCI_LIB_ADDRESS(Bus, Device, Function, PCI_BASE_ADDRESSREG_OFFSET));
+  High = PciRead32 (PCI_LIB_ADDRESS(Bus, Device, Function, PCI_BASE_ADDRESSREG_OFFSET + 4));
+  Address = (EFI_PHYSICAL_ADDRESS) (LShiftU64 ((UINT64) High, 32) | Low);
+
+  //
+  // Mask other parts which are not part of base address
+  //
+  Address &= XHCI_BASE_ADDRESS_64_BIT_MASK;
+  return Address;
+}
+
+/**
+  Return XHCI debug instance address.
+
+**/
+USB3_DEBUG_PORT_INSTANCE *
+GetUsb3DebugPortInstance (
+  VOID
+  )
+{
+  USB3_DEBUG_PORT_INSTANCE               *Instance;
+  EFI_PEI_HOB_POINTERS                   Hob;
+  EFI_PHYSICAL_ADDRESS                   XhcMmioBase;
+
+  Hob.Raw = GetFirstGuidHob (&gUsb3DbgGuid);
+  if (Hob.Raw == NULL) {
+    return NULL;
+  }
+  Instance = GET_GUID_HOB_DATA (Hob.Guid);
+
+  //
+  // Update XHCI MMIO base address
+  //
+  XhcMmioBase = GetXhciBaseAddress ();
+
+  FixUsb3InstanceResource (Instance, XhcMmioBase);
+
+  return Instance;
+}
+
+/**
+  Initialize USB3 debug port.
+
+  This method invokes various internal functions to facilitate
+  detection and initialization of USB3 debug port.
+
+  @retval RETURN_SUCCESS        The serial device was initialized.
+**/
+RETURN_STATUS
+EFIAPI
+USB3Initialize (
+  VOID
+  )
+{
+  return EFI_SUCCESS;
+}
+
+/**
+  Initialize USB3 debug port.
+
+  This method invokes various internal functions to facilitate
+  detection and initialization of USB3 debug port.
+
+  @retval RETURN_SUCCESS        The serial device was initialized.
+**/
+RETURN_STATUS
+EFIAPI
+USB3InitializeReal (
+  VOID
+  )
+{
+  USB3_DEBUG_PORT_INSTANCE  UsbDbg;
+  VOID                      *DataPtr;
+  EFI_PEI_HOB_POINTERS      Hob;
+
+  //
+  // USB Initilization has to be done only once. So this function should just return when
+  // it is called more than once.
+  //
+  Hob.Raw = GetFirstGuidHob (&gUsb3DbgGuid);
+  if (Hob.Raw != NULL) {
+    return RETURN_SUCCESS;
+  }
+
+  //
+  // Initialize USB debug for PEI at the first time
+  //
+  SetMem (&UsbDbg, sizeof(UsbDbg), 0);
+  UsbDbg.FromHob = TRUE;
+  DiscoverUsb3DebugPort (&UsbDbg);
+  if (UsbDbg.DebugSupport) {
+    InitializeUsb3DebugPort (&UsbDbg);
+  }
+
+  //
+  // Save Instance into HOB
+  //
+  DataPtr = BuildGuidDataHob (
+              &gUsb3DbgGuid,
+              (VOID*) &UsbDbg,
+              sizeof (UsbDbg)
+              );
+
+  if (UsbDbg.DebugSupport) {
+    SaveUsb3InstanceAddress ((USB3_DEBUG_PORT_INSTANCE *) DataPtr);
+  }
+
+  return RETURN_SUCCESS;
+}
+
+/**
+  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
+  )
+{
+  VOID                     *Buf;
+  EFI_PHYSICAL_ADDRESS     Address;
+  CONST EFI_PEI_SERVICES   **PeiServices;
+  EFI_STATUS               Status;
+  VOID                     *MemoryDiscoveredPpi;
+
+  Buf = NULL;
+  PeiServices = GetPeiServicesTablePointer ();
+
+  //
+  // Make sure the allocated memory is physical memory.
+  //
+  Status = (*PeiServices)->LocatePpi (
+                             PeiServices,
+                             &gEfiPeiMemoryDiscoveredPpiGuid,
+                             0,
+                             NULL,
+                             (VOID **) &MemoryDiscoveredPpi
+                             );
+  if (!EFI_ERROR (Status)) {
+    Status = (*PeiServices)->AllocatePages (
+                               PeiServices,
+                               EfiACPIMemoryNVS,
+                               EFI_SIZE_TO_PAGES (BufferSize),
+                               &Address
+                               );
+    if (!EFI_ERROR (Status)) {
+      Buf = (VOID *)(UINTN) Address;
+    }
+  }
+  return Buf;
+}
+
+/**
+  Check whether AllocatePages in permanent memory is ready.
+
+  @retval TRUE  AllocatePages in permanent memory is ready.
+  @retval FALSE AllocatePages in permanent memory is not ready.
+
+**/
+BOOLEAN
+IsAllocatePagesReady (
+  VOID
+  )
+{
+  CONST EFI_PEI_SERVICES   **PeiServices;
+  EFI_STATUS               Status;
+  VOID                     *MemoryDiscoveredPpi;
+
+  PeiServices = GetPeiServicesTablePointer ();
+
+  //
+  // Make sure the allocated memory is physical memory.
+  //
+  Status = (*PeiServices)->LocatePpi (
+                             PeiServices,
+                             &gEfiPeiMemoryDiscoveredPpiGuid,
+                             0,
+                             NULL,
+                             (VOID **) &MemoryDiscoveredPpi
+                             );
+  if (!EFI_ERROR (Status)) {
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
diff --git a/Platform/Intel/DebugFeaturePkg/Library/Usb3DebugPortLib/Usb3DebugPortLibPei.inf b/Platform/Intel/DebugFeaturePkg/Library/Usb3DebugPortLib/Usb3DebugPortLibPei.inf
new file mode 100644
index 0000000000..bc65c06f72
--- /dev/null
+++ b/Platform/Intel/DebugFeaturePkg/Library/Usb3DebugPortLib/Usb3DebugPortLibPei.inf
@@ -0,0 +1,48 @@
+## @file
+#  Usb3 debug port library.
+#
+# Copyright (c) 2013 - 2019, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = USB3DebugPortLibPei
+  FILE_GUID                      = 62C974F0-D0E0-4963-B93A-22FBCEB69AB4
+  MODULE_TYPE                    = PEIM
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = Usb3DebugPortLib|PEIM PEI_CORE
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 IPF
+#
+
+[Sources]
+  Usb3DebugPortLibPei.c
+  Usb3DebugPortDataTransfer.c
+  Usb3DebugPortInitialize.c
+  MiscServices.c
+  Usb3DebugPortLibInternal.h
+
+[Packages]
+  MdePkg/MdePkg.dec
+  DebugFeaturePkg/DebugFeaturePkg.dec
+
+[LibraryClasses]
+  BaseLib
+  PcdLib
+  IoLib
+  PciLib
+  TimerLib
+  HobLib
+  Usb3DebugPortParameterLib
+  PeiServicesTablePointerLib
+
+[Ppis]
+  gEfiPeiMemoryDiscoveredPpiGuid                ## CONSUMES
+
+[Pcd]
+  gEfiUsb3DebugPortTokenSpaceGuid.PcdXhciDefaultBaseAddress         ## SOMETIMES_CONSUMES
+  gEfiUsb3DebugPortTokenSpaceGuid.PcdXhciHostWaitTimeout            ## CONSUMES
diff --git a/Platform/Intel/DebugFeaturePkg/Library/Usb3DebugPortLib/Usb3DebugPortLibPeiIoMmu.c b/Platform/Intel/DebugFeaturePkg/Library/Usb3DebugPortLib/Usb3DebugPortLibPeiIoMmu.c
new file mode 100644
index 0000000000..68543c8562
--- /dev/null
+++ b/Platform/Intel/DebugFeaturePkg/Library/Usb3DebugPortLib/Usb3DebugPortLibPeiIoMmu.c
@@ -0,0 +1,440 @@
+/** @file
+  Usb Debug Port library instance
+
+  Copyright (c) 2013 - 2019, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Base.h>
+
+#include <PiPei.h>
+#include <Library/SerialPortLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PciLib.h>
+#include <Library/HobLib.h>
+#include <Library/PcdLib.h>
+#include <Library/TimerLib.h>
+#include <Library/Usb3DebugPortParameterLib.h>
+#include <Library/PeiServicesTablePointerLib.h>
+#include <Ppi/MemoryDiscovered.h>
+#include <Ppi/IoMmu.h>
+#include "Usb3DebugPortLibInternal.h"
+
+GUID                      gUsb3DbgGuid =  USB3_DBG_GUID;
+
+/**
+  USB3 IOMMU PPI notify.
+
+  @param[in] PeiServices    Pointer to PEI Services Table.
+  @param[in] NotifyDesc     Pointer to the descriptor for the Notification event that
+                            caused this function to execute.
+  @param[in] Ppi            Pointer to the PPI data associated with this function.
+
+  @retval EFI_STATUS        Always return EFI_SUCCESS
+**/
+EFI_STATUS
+EFIAPI
+Usb3IoMmuPpiNotify (
+  IN EFI_PEI_SERVICES           **PeiServices,
+  IN EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDesc,
+  IN VOID                       *Ppi
+  )
+{
+  USB3_DEBUG_PORT_INSTANCE      *Instance;
+
+  Instance = GetUsb3DebugPortInstance ();
+  ASSERT (Instance != NULL);
+  //
+  // Reinitialize USB3 debug port with granted DMA buffer from IOMMU PPI.
+  //
+  InitializeUsb3DebugPort (Instance);
+
+  SaveUsb3InstanceAddress (Instance);
+
+  return EFI_SUCCESS;
+}
+
+EFI_PEI_NOTIFY_DESCRIPTOR mUsb3IoMmuPpiNotifyDesc = {
+  (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+  &gEdkiiIoMmuPpiGuid,
+  Usb3IoMmuPpiNotify
+};
+
+/**
+  Allocates pages that are suitable for an OperationBusMasterCommonBuffer or
+  OperationBusMasterCommonBuffer64 mapping.
+
+  @param IoMmu                  Pointer to IOMMU PPI.
+  @param Pages                  The number of pages to allocate.
+  @param HostAddress            A pointer to store the base system memory address of the
+                                allocated range.
+  @param DeviceAddress          The resulting map address for the bus master PCI controller to use to
+                                access the hosts HostAddress.
+  @param Mapping                A resulting value to pass to Unmap().
+
+  @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
+IoMmuAllocateBuffer (
+  IN EDKII_IOMMU_PPI        *IoMmu,
+  IN UINTN                  Pages,
+  OUT VOID                  **HostAddress,
+  OUT EFI_PHYSICAL_ADDRESS  *DeviceAddress,
+  OUT VOID                  **Mapping
+  )
+{
+  EFI_STATUS            Status;
+  UINTN                 NumberOfBytes;
+
+  *HostAddress = NULL;
+  *DeviceAddress = 0;
+  *Mapping = NULL;
+
+  Status = IoMmu->AllocateBuffer (
+                    IoMmu,
+                    EfiRuntimeServicesData,
+                    Pages,
+                    HostAddress,
+                    0
+                    );
+  if (EFI_ERROR (Status)) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  NumberOfBytes = EFI_PAGES_TO_SIZE (Pages);
+  Status = IoMmu->Map (
+                    IoMmu,
+                    EdkiiIoMmuOperationBusMasterCommonBuffer,
+                    *HostAddress,
+                    &NumberOfBytes,
+                    DeviceAddress,
+                    Mapping
+                    );
+  if (EFI_ERROR (Status)) {
+    IoMmu->FreeBuffer (IoMmu, Pages, *HostAddress);
+    *HostAddress = NULL;
+    return EFI_OUT_OF_RESOURCES;
+  }
+  Status = IoMmu->SetAttribute (
+                    IoMmu,
+                    *Mapping,
+                    EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE
+                    );
+  if (EFI_ERROR (Status)) {
+    IoMmu->Unmap (IoMmu, *Mapping);
+    IoMmu->FreeBuffer (IoMmu, Pages, *HostAddress);
+    *Mapping = NULL;
+    *HostAddress = NULL;
+    return Status;
+  }
+
+  return Status;
+}
+
+/**
+  USB3 get IOMMU PPI.
+
+  @return Pointer to IOMMU PPI.
+
+**/
+EDKII_IOMMU_PPI *
+Usb3GetIoMmu (
+  VOID
+  )
+{
+  EFI_STATUS                Status;
+  EDKII_IOMMU_PPI           *IoMmu;
+  CONST EFI_PEI_SERVICES    **PeiServices;
+
+  PeiServices = GetPeiServicesTablePointer ();
+
+  IoMmu = NULL;
+  Status = (*PeiServices)->LocatePpi (
+                             PeiServices,
+                             &gEdkiiIoMmuPpiGuid,
+                             0,
+                             NULL,
+                             (VOID **) &IoMmu
+                             );
+  if (!EFI_ERROR (Status) && (IoMmu != NULL)) {
+    return IoMmu;
+  }
+
+  return NULL;
+}
+
+/**
+  Return XHCI MMIO base address.
+
+**/
+EFI_PHYSICAL_ADDRESS
+GetXhciBaseAddress (
+  VOID
+  )
+{
+  UINT8                       Bus;
+  UINT8                       Device;
+  UINT8                       Function;
+  USB3_DEBUG_PORT_CONTROLLER   UsbDebugPort;
+  EFI_PHYSICAL_ADDRESS        Address;
+  UINT32                      Low;
+  UINT32                      High;
+
+  UsbDebugPort.Controller = GetUsb3DebugPortController();
+  Bus = UsbDebugPort.PciAddress.Bus;
+  Device = UsbDebugPort.PciAddress.Device;
+  Function = UsbDebugPort.PciAddress.Function;
+  Low = PciRead32 (PCI_LIB_ADDRESS(Bus, Device, Function, PCI_BASE_ADDRESSREG_OFFSET));
+  High = PciRead32 (PCI_LIB_ADDRESS(Bus, Device, Function, PCI_BASE_ADDRESSREG_OFFSET + 4));
+  Address = (EFI_PHYSICAL_ADDRESS) (LShiftU64 ((UINT64) High, 32) | Low);
+
+  //
+  // Mask other parts which are not part of base address
+  //
+  Address &= XHCI_BASE_ADDRESS_64_BIT_MASK;
+  return Address;
+}
+
+/**
+  Return XHCI debug instance address.
+
+**/
+USB3_DEBUG_PORT_INSTANCE *
+GetUsb3DebugPortInstance (
+  VOID
+  )
+{
+  USB3_DEBUG_PORT_INSTANCE               *Instance;
+  EFI_PEI_HOB_POINTERS                   Hob;
+  EFI_PHYSICAL_ADDRESS                   XhcMmioBase;
+
+  Hob.Raw = GetFirstGuidHob (&gUsb3DbgGuid);
+  if (Hob.Raw == NULL) {
+    return NULL;
+  }
+  Instance = GET_GUID_HOB_DATA (Hob.Guid);
+
+  //
+  // Update XHCI MMIO base address
+  //
+  XhcMmioBase = GetXhciBaseAddress ();
+
+  FixUsb3InstanceResource (Instance, XhcMmioBase);
+
+  return Instance;
+}
+
+/**
+  Initialize USB3 debug port.
+
+  This method invokes various internal functions to facilitate
+  detection and initialization of USB3 debug port.
+
+  @retval RETURN_SUCCESS        The serial device was initialized.
+**/
+RETURN_STATUS
+EFIAPI
+USB3Initialize (
+  VOID
+  )
+{
+  return EFI_SUCCESS;
+}
+
+/**
+  Initialize USB3 debug port.
+
+  This method invokes various internal functions to facilitate
+  detection and initialization of USB3 debug port.
+
+  @retval RETURN_SUCCESS        The serial device was initialized.
+**/
+RETURN_STATUS
+EFIAPI
+USB3InitializeReal (
+  VOID
+  )
+{
+  EFI_STATUS                Status;
+  USB3_DEBUG_PORT_INSTANCE  UsbDbg;
+  VOID                      *DataPtr;
+  EFI_PEI_HOB_POINTERS      Hob;
+  CONST EFI_PEI_SERVICES    **PeiServices;
+
+  PeiServices = GetPeiServicesTablePointer ();
+
+  //
+  // USB Initilization has to be done only once. So this function should just return when
+  // it is called more than once.
+  //
+  Hob.Raw = GetFirstGuidHob (&gUsb3DbgGuid);
+  if (Hob.Raw != NULL) {
+    return RETURN_SUCCESS;
+  }
+
+  //
+  // Initialize USB debug for PEI at the first time
+  //
+  SetMem (&UsbDbg, sizeof(UsbDbg), 0);
+  UsbDbg.FromHob = TRUE;
+  DiscoverUsb3DebugPort (&UsbDbg);
+  if (UsbDbg.DebugSupport) {
+    InitializeUsb3DebugPort (&UsbDbg);
+  }
+
+  if (UsbDbg.Ready && (Usb3GetIoMmu () == NULL)) {
+    Status = (*PeiServices)->NotifyPpi (PeiServices, &mUsb3IoMmuPpiNotifyDesc);
+    ASSERT_EFI_ERROR (Status);
+  }
+
+  //
+  // Save Instance into HOB
+  //
+  DataPtr = BuildGuidDataHob (
+              &gUsb3DbgGuid,
+              (VOID*) &UsbDbg,
+              sizeof (UsbDbg)
+              );
+
+  if (UsbDbg.DebugSupport) {
+    SaveUsb3InstanceAddress ((USB3_DEBUG_PORT_INSTANCE *) DataPtr);
+  }
+
+  return RETURN_SUCCESS;
+}
+
+/**
+  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
+  )
+{
+  VOID                     *Buf;
+  EFI_PHYSICAL_ADDRESS     Address;
+  CONST EFI_PEI_SERVICES   **PeiServices;
+  EFI_STATUS               Status;
+  VOID                     *MemoryDiscoveredPpi;
+  EDKII_IOMMU_PPI          *IoMmu;
+  VOID                     *HostAddress;
+  VOID                     *Mapping;
+
+  Buf = NULL;
+  PeiServices = GetPeiServicesTablePointer ();
+
+  //
+  // Make sure the allocated memory is physical memory.
+  //
+  Status = (*PeiServices)->LocatePpi (
+                             PeiServices,
+                             &gEfiPeiMemoryDiscoveredPpiGuid,
+                             0,
+                             NULL,
+                             (VOID **) &MemoryDiscoveredPpi
+                             );
+  if (!EFI_ERROR (Status)) {
+    IoMmu = Usb3GetIoMmu ();
+    if (IoMmu != NULL) {
+      Status = IoMmuAllocateBuffer (
+                 IoMmu,
+                 EFI_SIZE_TO_PAGES (BufferSize),
+                 &HostAddress,
+                 &Address,
+                 &Mapping
+                 );
+      if (!EFI_ERROR (Status)) {
+        ASSERT (Address == ((EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress));
+        Buf = (VOID *)(UINTN) Address;
+      }
+    } else {
+      Status = (*PeiServices)->AllocatePages (
+                                 PeiServices,
+                                 EfiACPIMemoryNVS,
+                                 EFI_SIZE_TO_PAGES (BufferSize),
+                                 &Address
+                                 );
+      if (!EFI_ERROR (Status)) {
+        Buf = (VOID *)(UINTN) Address;
+      }
+    }
+  }
+  return Buf;
+}
+
+/**
+  Check whether AllocatePages in permanent memory is ready.
+
+  @retval TRUE  AllocatePages in permanent memory is ready.
+  @retval FALSE AllocatePages in permanent memory is not ready.
+
+**/
+BOOLEAN
+IsAllocatePagesReady (
+  VOID
+  )
+{
+  CONST EFI_PEI_SERVICES   **PeiServices;
+  EFI_STATUS               Status;
+  VOID                     *MemoryDiscoveredPpi;
+  EDKII_IOMMU_PPI          *IoMmu;
+  VOID                     *HostAddress;
+
+  PeiServices = GetPeiServicesTablePointer ();
+
+  //
+  // Make sure the allocated memory is physical memory.
+  //
+  Status = (*PeiServices)->LocatePpi (
+                             PeiServices,
+                             &gEfiPeiMemoryDiscoveredPpiGuid,
+                             0,
+                             NULL,
+                             (VOID **) &MemoryDiscoveredPpi
+                             );
+  if (!EFI_ERROR (Status)) {
+    Status = (*PeiServices)->LocatePpi (
+                               PeiServices,
+                               &gEdkiiIoMmuPpiGuid,
+                               0,
+                               NULL,
+                               (VOID **) &IoMmu
+                               );
+    if (!EFI_ERROR (Status)) {
+      Status = IoMmu->AllocateBuffer (
+                        IoMmu,
+                        EfiRuntimeServicesData,
+                        1,
+                        &HostAddress,
+                        0
+                        );
+      if (EFI_ERROR (Status)) {
+        //
+        // DMA protection has been enabled,
+        // but DMA buffer could not be allocated yet.
+        //
+        return FALSE;
+      }
+      IoMmu->FreeBuffer (
+               IoMmu,
+               1,
+               HostAddress
+               );
+    }
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
diff --git a/Platform/Intel/DebugFeaturePkg/Library/Usb3DebugPortLib/Usb3DebugPortLibPeiIoMmu.inf b/Platform/Intel/DebugFeaturePkg/Library/Usb3DebugPortLib/Usb3DebugPortLibPeiIoMmu.inf
new file mode 100644
index 0000000000..c351aa0234
--- /dev/null
+++ b/Platform/Intel/DebugFeaturePkg/Library/Usb3DebugPortLib/Usb3DebugPortLibPeiIoMmu.inf
@@ -0,0 +1,51 @@
+## @file
+#  Usb3 debug port library.
+#
+# Copyright (c) 2013 - 2019, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = USB3DebugPortLibPeiIoMmu
+  FILE_GUID                      = C973C5E8-A0D8-4FEE-A0F0-7DA6C3C72451
+  MODULE_TYPE                    = PEIM
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = Usb3DebugPortLib|PEIM PEI_CORE
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 IPF
+#
+
+[Sources]
+  Usb3DebugPortLibPeiIoMmu.c
+  Usb3DebugPortDataTransfer.c
+  Usb3DebugPortInitialize.c
+  MiscServices.c
+  Usb3DebugPortLibInternal.h
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  DebugFeaturePkg/DebugFeaturePkg.dec
+
+[LibraryClasses]
+  BaseLib
+  PcdLib
+  IoLib
+  PciLib
+  TimerLib
+  HobLib
+  Usb3DebugPortParameterLib
+  PeiServicesTablePointerLib
+
+[Ppis]
+  gEfiPeiMemoryDiscoveredPpiGuid                ## CONSUMES
+  gEdkiiIoMmuPpiGuid                            ## SOMETIMES_CONSUMES
+
+[Pcd]
+  gEfiUsb3DebugPortTokenSpaceGuid.PcdXhciDefaultBaseAddress         ## SOMETIMES_CONSUMES
+  gEfiUsb3DebugPortTokenSpaceGuid.PcdXhciHostWaitTimeout            ## CONSUMES
diff --git a/Platform/Intel/DebugFeaturePkg/Library/Usb3DebugPortParameterLibPcd/Usb3DebugPortParameterLibPcd.c b/Platform/Intel/DebugFeaturePkg/Library/Usb3DebugPortParameterLibPcd/Usb3DebugPortParameterLibPcd.c
new file mode 100644
index 0000000000..747c5dccc9
--- /dev/null
+++ b/Platform/Intel/DebugFeaturePkg/Library/Usb3DebugPortParameterLibPcd/Usb3DebugPortParameterLibPcd.c
@@ -0,0 +1,58 @@
+/** @file
+  USB3 debug Port Parameter library instance based on PCD.
+
+  Copyright (c) 2013 - 2019, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Base.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <Library/Usb3DebugPortParameterLib.h>
+
+/**
+  Returns the USB3 debug port controller.
+  bit:  0~ 7: Function
+  bit:  8~15: Device
+  bit: 16~24: Bus
+
+  @return  Controller information of USB debug port.
+
+**/
+UINT32
+EFIAPI
+GetUsb3DebugPortController (
+  VOID
+  )
+{
+  USB3_DEBUG_PORT_CONTROLLER       UsbDebugPort;
+
+  UsbDebugPort.Controller = 0;
+  UsbDebugPort.PciAddress.Bus = PcdGet8(PcdUsbSerialXhciBus);
+  UsbDebugPort.PciAddress.Device = PcdGet8(PcdUsbSerialXhciDev);
+  UsbDebugPort.PciAddress.Function = PcdGet8(PcdUsbSerialXhciFunc);
+
+  return UsbDebugPort.Controller;
+}
+
+/**
+  Sets the USB debug port controller.
+  bit:  0~ 7: Function
+  bit:  8~15: Device
+  bit: 16~24: Bus
+
+  @param[in]    Controller information of USB debug port value to be set.
+
+  @retval  TRUE           The controller of USB debug port was sucessfully set.
+  @retval  FALSE          The controller of USB debug port could not be set.
+
+**/
+BOOLEAN
+EFIAPI
+SetUsb3DebugPortController (
+  UINT32        Controller
+  )
+{
+  return FALSE;
+}
diff --git a/Platform/Intel/DebugFeaturePkg/Library/Usb3DebugPortParameterLibPcd/Usb3DebugPortParameterLibPcd.inf b/Platform/Intel/DebugFeaturePkg/Library/Usb3DebugPortParameterLibPcd/Usb3DebugPortParameterLibPcd.inf
new file mode 100644
index 0000000000..48fdd4800c
--- /dev/null
+++ b/Platform/Intel/DebugFeaturePkg/Library/Usb3DebugPortParameterLibPcd/Usb3DebugPortParameterLibPcd.inf
@@ -0,0 +1,31 @@
+## @file
+#  USB3 debug Port Parameter library instance based on PCD.
+#
+# Copyright (c) 2013 - 2019, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = Usb3DebugPortParameterLibPcd
+  FILE_GUID                      = 4990A700-4002-4d08-8E00-622720032662
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = Usb3DebugPortParameterLib
+
+[Sources]
+  Usb3DebugPortParameterLibPcd.c
+
+[LibraryClasses]
+  BaseLib
+  DebugLib
+
+[Packages]
+  MdePkg/MdePkg.dec
+  DebugFeaturePkg/DebugFeaturePkg.dec
+
+[Pcd]
+  gEfiUsb3DebugPortTokenSpaceGuid.PcdUsbSerialXhciBus     ## CONSUMES
+  gEfiUsb3DebugPortTokenSpaceGuid.PcdUsbSerialXhciDev     ## CONSUMES
+  gEfiUsb3DebugPortTokenSpaceGuid.PcdUsbSerialXhciFunc    ## CONSUMES
-- 
2.21.0.windows.1


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.

View/Reply Online (#41556): https://edk2.groups.io/g/devel/message/41556
Mute This Topic: https://groups.io/mt/31828871/1813853
Group Owner: devel+owner at edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub  [edk2-devel-archive at redhat.com]
-=-=-=-=-=-=-=-=-=-=-=-




More information about the edk2-devel-archive mailing list