From af1a266670d040d2f4083ff309d732d648afba2a Mon Sep 17 00:00:00 2001
From: Angelos Mouzakitis <a.mouzakitis@virtualopensystems.com>
Date: Tue, 10 Oct 2023 14:33:42 +0000
Subject: Add submodule dependency files

Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec
---
 roms/edk2/MdeModulePkg/Bus/Usb/UsbBusPei/HubPeim.c |  586 +++++++++
 roms/edk2/MdeModulePkg/Bus/Usb/UsbBusPei/HubPeim.h |  258 ++++
 .../MdeModulePkg/Bus/Usb/UsbBusPei/PeiUsbLib.c     |  185 +++
 .../MdeModulePkg/Bus/Usb/UsbBusPei/PeiUsbLib.h     |  189 +++
 .../MdeModulePkg/Bus/Usb/UsbBusPei/UsbBusPei.inf   |   60 +
 .../MdeModulePkg/Bus/Usb/UsbBusPei/UsbBusPei.uni   |   16 +
 .../Bus/Usb/UsbBusPei/UsbBusPeiExtra.uni           |   14 +
 .../MdeModulePkg/Bus/Usb/UsbBusPei/UsbIoPeim.c     |  365 ++++++
 roms/edk2/MdeModulePkg/Bus/Usb/UsbBusPei/UsbPeim.c | 1243 ++++++++++++++++++++
 roms/edk2/MdeModulePkg/Bus/Usb/UsbBusPei/UsbPeim.h |  257 ++++
 10 files changed, 3173 insertions(+)
 create mode 100644 roms/edk2/MdeModulePkg/Bus/Usb/UsbBusPei/HubPeim.c
 create mode 100644 roms/edk2/MdeModulePkg/Bus/Usb/UsbBusPei/HubPeim.h
 create mode 100644 roms/edk2/MdeModulePkg/Bus/Usb/UsbBusPei/PeiUsbLib.c
 create mode 100644 roms/edk2/MdeModulePkg/Bus/Usb/UsbBusPei/PeiUsbLib.h
 create mode 100644 roms/edk2/MdeModulePkg/Bus/Usb/UsbBusPei/UsbBusPei.inf
 create mode 100644 roms/edk2/MdeModulePkg/Bus/Usb/UsbBusPei/UsbBusPei.uni
 create mode 100644 roms/edk2/MdeModulePkg/Bus/Usb/UsbBusPei/UsbBusPeiExtra.uni
 create mode 100644 roms/edk2/MdeModulePkg/Bus/Usb/UsbBusPei/UsbIoPeim.c
 create mode 100644 roms/edk2/MdeModulePkg/Bus/Usb/UsbBusPei/UsbPeim.c
 create mode 100644 roms/edk2/MdeModulePkg/Bus/Usb/UsbBusPei/UsbPeim.h

(limited to 'roms/edk2/MdeModulePkg/Bus/Usb/UsbBusPei')

diff --git a/roms/edk2/MdeModulePkg/Bus/Usb/UsbBusPei/HubPeim.c b/roms/edk2/MdeModulePkg/Bus/Usb/UsbBusPei/HubPeim.c
new file mode 100644
index 000000000..c44c40389
--- /dev/null
+++ b/roms/edk2/MdeModulePkg/Bus/Usb/UsbBusPei/HubPeim.c
@@ -0,0 +1,586 @@
+/** @file
+Usb Hub Request Support In PEI Phase
+
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "UsbPeim.h"
+#include "HubPeim.h"
+#include "PeiUsbLib.h"
+
+/**
+  Get a given hub port status.
+
+  @param  PeiServices   General-purpose services that are available to every PEIM.
+  @param  UsbIoPpi      Indicates the PEI_USB_IO_PPI instance.
+  @param  Port          Usb hub port number (starting from 1).
+  @param  PortStatus    Current Hub port status and change status.
+
+  @retval EFI_SUCCESS       Port status is obtained successfully.
+  @retval EFI_DEVICE_ERROR  Cannot get the port status due to a hardware error.
+  @retval Others            Other failure occurs.
+
+**/
+EFI_STATUS
+PeiHubGetPortStatus (
+  IN  EFI_PEI_SERVICES    **PeiServices,
+  IN  PEI_USB_IO_PPI      *UsbIoPpi,
+  IN  UINT8               Port,
+  OUT UINT32              *PortStatus
+  )
+{
+  EFI_USB_DEVICE_REQUEST  DeviceRequest;
+
+  ZeroMem (&DeviceRequest, sizeof (EFI_USB_DEVICE_REQUEST));
+
+  //
+  // Fill Device request packet
+  //
+  DeviceRequest.RequestType = USB_HUB_GET_PORT_STATUS_REQ_TYPE;
+  DeviceRequest.Request     = USB_HUB_GET_PORT_STATUS;
+  DeviceRequest.Index       = Port;
+  DeviceRequest.Length      = (UINT16) sizeof (UINT32);
+
+
+  return UsbIoPpi->UsbControlTransfer (
+                     PeiServices,
+                     UsbIoPpi,
+                     &DeviceRequest,
+                     EfiUsbDataIn,
+                     PcdGet32 (PcdUsbTransferTimeoutValue),
+                     PortStatus,
+                     sizeof (UINT32)
+                     );
+
+}
+
+/**
+  Set specified feature to a given hub port.
+
+  @param  PeiServices   General-purpose services that are available to every PEIM.
+  @param  UsbIoPpi      Indicates the PEI_USB_IO_PPI instance.
+  @param  Port          Usb hub port number (starting from 1).
+  @param  Value         New feature value.
+
+  @retval EFI_SUCCESS       Port feature is set successfully.
+  @retval EFI_DEVICE_ERROR  Cannot set the port feature due to a hardware error.
+  @retval Others            Other failure occurs.
+
+**/
+EFI_STATUS
+PeiHubSetPortFeature (
+  IN EFI_PEI_SERVICES    **PeiServices,
+  IN PEI_USB_IO_PPI      *UsbIoPpi,
+  IN UINT8               Port,
+  IN UINT8               Value
+  )
+{
+  EFI_USB_DEVICE_REQUEST      DeviceRequest;
+
+  ZeroMem (&DeviceRequest, sizeof (EFI_USB_DEVICE_REQUEST));
+
+  //
+  // Fill Device request packet
+  //
+  DeviceRequest.RequestType = USB_HUB_SET_PORT_FEATURE_REQ_TYPE;
+  DeviceRequest.Request     = USB_HUB_SET_PORT_FEATURE;
+  DeviceRequest.Value       = Value;
+  DeviceRequest.Index       = Port;
+
+  return UsbIoPpi->UsbControlTransfer (
+                     PeiServices,
+                     UsbIoPpi,
+                     &DeviceRequest,
+                     EfiUsbNoData,
+                     PcdGet32 (PcdUsbTransferTimeoutValue),
+                     NULL,
+                     0
+                     );
+}
+
+/**
+  Clear specified feature on a given hub port.
+
+  @param  PeiServices   General-purpose services that are available to every PEIM.
+  @param  UsbIoPpi      Indicates the PEI_USB_IO_PPI instance.
+  @param  Port          Usb hub port number (starting from 1).
+  @param  Value         Feature value that will be cleared from the hub port.
+
+  @retval EFI_SUCCESS       Port feature is cleared successfully.
+  @retval EFI_DEVICE_ERROR  Cannot clear the port feature due to a hardware error.
+  @retval Others            Other failure occurs.
+
+**/
+EFI_STATUS
+PeiHubClearPortFeature (
+  IN EFI_PEI_SERVICES    **PeiServices,
+  IN PEI_USB_IO_PPI      *UsbIoPpi,
+  IN UINT8               Port,
+  IN UINT8               Value
+  )
+{
+  EFI_USB_DEVICE_REQUEST      DeviceRequest;
+
+  ZeroMem (&DeviceRequest, sizeof (EFI_USB_DEVICE_REQUEST));
+
+  //
+  // Fill Device request packet
+  //
+  DeviceRequest.RequestType = USB_HUB_CLEAR_FEATURE_PORT_REQ_TYPE;
+  DeviceRequest.Request     = USB_HUB_CLEAR_FEATURE_PORT;
+  DeviceRequest.Value       = Value;
+  DeviceRequest.Index       = Port;
+
+  return UsbIoPpi->UsbControlTransfer (
+                     PeiServices,
+                     UsbIoPpi,
+                     &DeviceRequest,
+                     EfiUsbNoData,
+                     PcdGet32 (PcdUsbTransferTimeoutValue),
+                     NULL,
+                     0
+                     );
+}
+
+/**
+  Get a given hub status.
+
+  @param  PeiServices   General-purpose services that are available to every PEIM.
+  @param  UsbIoPpi      Indicates the PEI_USB_IO_PPI instance.
+  @param  HubStatus     Current Hub status and change status.
+
+  @retval EFI_SUCCESS       Hub status is obtained successfully.
+  @retval EFI_DEVICE_ERROR  Cannot get the hub status due to a hardware error.
+  @retval Others            Other failure occurs.
+
+**/
+EFI_STATUS
+PeiHubGetHubStatus (
+  IN  EFI_PEI_SERVICES    **PeiServices,
+  IN  PEI_USB_IO_PPI      *UsbIoPpi,
+  OUT UINT32              *HubStatus
+  )
+{
+  EFI_USB_DEVICE_REQUEST  DeviceRequest;
+
+  ZeroMem (&DeviceRequest, sizeof (EFI_USB_DEVICE_REQUEST));
+
+  //
+  // Fill Device request packet
+  //
+  DeviceRequest.RequestType = USB_HUB_GET_HUB_STATUS_REQ_TYPE;
+  DeviceRequest.Request     = USB_HUB_GET_HUB_STATUS;
+  DeviceRequest.Length      = (UINT16) sizeof (UINT32);
+
+  return UsbIoPpi->UsbControlTransfer (
+                     PeiServices,
+                     UsbIoPpi,
+                     &DeviceRequest,
+                     EfiUsbDataIn,
+                     PcdGet32 (PcdUsbTransferTimeoutValue),
+                     HubStatus,
+                     sizeof (UINT32)
+                     );
+}
+
+
+
+/**
+  Clear specified feature on a given hub.
+
+  @param  PeiServices   General-purpose services that are available to every PEIM.
+  @param  UsbIoPpi      Indicates the PEI_USB_IO_PPI instance.
+  @param  Value         Feature value that will be cleared from the hub port.
+
+  @retval EFI_SUCCESS       Hub feature is cleared successfully.
+  @retval EFI_DEVICE_ERROR  Cannot clear the hub feature due to a hardware error.
+  @retval Others            Other failure occurs.
+
+**/
+EFI_STATUS
+PeiHubClearHubFeature (
+  IN EFI_PEI_SERVICES    **PeiServices,
+  IN PEI_USB_IO_PPI      *UsbIoPpi,
+  IN UINT8               Value
+  )
+{
+  EFI_USB_DEVICE_REQUEST      DeviceRequest;
+
+  ZeroMem (&DeviceRequest, sizeof (EFI_USB_DEVICE_REQUEST));
+
+  //
+  // Fill Device request packet
+  //
+  DeviceRequest.RequestType = USB_HUB_CLEAR_FEATURE_REQ_TYPE;
+  DeviceRequest.Request     = USB_HUB_CLEAR_FEATURE;
+  DeviceRequest.Value       = Value;
+
+  return  UsbIoPpi->UsbControlTransfer (
+                      PeiServices,
+                      UsbIoPpi,
+                      &DeviceRequest,
+                      EfiUsbNoData,
+                      PcdGet32 (PcdUsbTransferTimeoutValue),
+                      NULL,
+                      0
+                      );
+}
+
+/**
+  Get a given (SuperSpeed) hub descriptor.
+
+  @param  PeiServices    General-purpose services that are available to every PEIM.
+  @param  PeiUsbDevice   Indicates the hub controller device.
+  @param  UsbIoPpi       Indicates the PEI_USB_IO_PPI instance.
+  @param  DescriptorSize The length of Hub Descriptor buffer.
+  @param  HubDescriptor  Caller allocated buffer to store the hub descriptor if
+                         successfully returned.
+
+  @retval EFI_SUCCESS       Hub descriptor is obtained successfully.
+  @retval EFI_DEVICE_ERROR  Cannot get the hub descriptor due to a hardware error.
+  @retval Others            Other failure occurs.
+
+**/
+EFI_STATUS
+PeiGetHubDescriptor (
+  IN  EFI_PEI_SERVICES          **PeiServices,
+  IN  PEI_USB_DEVICE            *PeiUsbDevice,
+  IN  PEI_USB_IO_PPI            *UsbIoPpi,
+  IN  UINTN                     DescriptorSize,
+  OUT EFI_USB_HUB_DESCRIPTOR    *HubDescriptor
+  )
+{
+  EFI_USB_DEVICE_REQUEST      DevReq;
+  UINT8                       DescType;
+
+  ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));
+
+  DescType = (PeiUsbDevice->DeviceSpeed == EFI_USB_SPEED_SUPER) ?
+             USB_DT_SUPERSPEED_HUB :
+             USB_DT_HUB;
+
+  //
+  // Fill Device request packet
+  //
+  DevReq.RequestType = USB_RT_HUB | 0x80;
+  DevReq.Request     = USB_HUB_GET_DESCRIPTOR;
+  DevReq.Value       = (UINT16) (DescType << 8);
+  DevReq.Length      = (UINT16) DescriptorSize;
+
+  return  UsbIoPpi->UsbControlTransfer (
+                      PeiServices,
+                      UsbIoPpi,
+                      &DevReq,
+                      EfiUsbDataIn,
+                      PcdGet32 (PcdUsbTransferTimeoutValue),
+                      HubDescriptor,
+                      (UINT16)DescriptorSize
+                      );
+}
+
+/**
+  Read the whole usb hub descriptor. It is necessary
+  to do it in two steps because hub descriptor is of
+  variable length.
+
+  @param  PeiServices       General-purpose services that are available to every PEIM.
+  @param  PeiUsbDevice      Indicates the hub controller device.
+  @param  UsbIoPpi          Indicates the PEI_USB_IO_PPI instance.
+  @param  HubDescriptor     Caller allocated buffer to store the hub descriptor if
+                            successfully returned.
+
+  @retval EFI_SUCCESS       Hub descriptor is obtained successfully.
+  @retval EFI_DEVICE_ERROR  Cannot get the hub descriptor due to a hardware error.
+  @retval Others            Other failure occurs.
+
+**/
+EFI_STATUS
+PeiUsbHubReadDesc (
+  IN EFI_PEI_SERVICES           **PeiServices,
+  IN PEI_USB_DEVICE             *PeiUsbDevice,
+  IN PEI_USB_IO_PPI             *UsbIoPpi,
+  OUT EFI_USB_HUB_DESCRIPTOR    *HubDescriptor
+  )
+{
+  EFI_STATUS Status;
+
+  //
+  // First get the hub descriptor length
+  //
+  Status = PeiGetHubDescriptor (PeiServices, PeiUsbDevice, UsbIoPpi, 2, HubDescriptor);
+
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Get the whole hub descriptor
+  //
+  return PeiGetHubDescriptor (PeiServices, PeiUsbDevice, UsbIoPpi, HubDescriptor->Length, HubDescriptor);
+}
+
+/**
+  USB hub control transfer to set the hub depth.
+
+  @param  PeiServices       General-purpose services that are available to every PEIM.
+  @param  PeiUsbDevice      Indicates the hub controller device.
+  @param  UsbIoPpi          Indicates the PEI_USB_IO_PPI instance.
+
+  @retval EFI_SUCCESS       Depth of the hub is set.
+  @retval Others            Failed to set the depth.
+
+**/
+EFI_STATUS
+PeiUsbHubCtrlSetHubDepth (
+  IN EFI_PEI_SERVICES           **PeiServices,
+  IN PEI_USB_DEVICE             *PeiUsbDevice,
+  IN PEI_USB_IO_PPI             *UsbIoPpi
+  )
+{
+  EFI_USB_DEVICE_REQUEST        DevReq;
+  ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));
+
+  //
+  // Fill Device request packet
+  //
+  DevReq.RequestType = USB_RT_HUB;
+  DevReq.Request     = USB_HUB_REQ_SET_DEPTH;
+  DevReq.Value       = PeiUsbDevice->Tier;
+  DevReq.Length      = 0;
+
+  return  UsbIoPpi->UsbControlTransfer (
+                      PeiServices,
+                      UsbIoPpi,
+                      &DevReq,
+                      EfiUsbNoData,
+                      PcdGet32 (PcdUsbTransferTimeoutValue),
+                      NULL,
+                      0
+                      );
+}
+
+/**
+  Configure a given hub.
+
+  @param  PeiServices    General-purpose services that are available to every PEIM.
+  @param  PeiUsbDevice   Indicating the hub controller device that will be configured
+
+  @retval EFI_SUCCESS       Hub configuration is done successfully.
+  @retval EFI_DEVICE_ERROR  Cannot configure the hub due to a hardware error.
+
+**/
+EFI_STATUS
+PeiDoHubConfig (
+  IN EFI_PEI_SERVICES    **PeiServices,
+  IN PEI_USB_DEVICE      *PeiUsbDevice
+  )
+{
+  UINT8                   HubDescBuffer[256];
+  EFI_USB_HUB_DESCRIPTOR  *HubDescriptor;
+  EFI_STATUS              Status;
+  EFI_USB_HUB_STATUS      HubStatus;
+  UINTN                   Index;
+  PEI_USB_IO_PPI          *UsbIoPpi;
+
+  UsbIoPpi = &PeiUsbDevice->UsbIoPpi;
+
+  //
+  // The length field of descriptor is UINT8 type, so the buffer
+  // with 256 bytes is enough to hold the descriptor data.
+  //
+  HubDescriptor = (EFI_USB_HUB_DESCRIPTOR *) HubDescBuffer;
+
+  //
+  // Get the hub descriptor
+  //
+  Status = PeiUsbHubReadDesc (
+            PeiServices,
+            PeiUsbDevice,
+            UsbIoPpi,
+            HubDescriptor
+            );
+  if (EFI_ERROR (Status)) {
+    return EFI_DEVICE_ERROR;
+  }
+
+  PeiUsbDevice->DownStreamPortNo = HubDescriptor->NbrPorts;
+
+  if (PeiUsbDevice->DeviceSpeed == EFI_USB_SPEED_SUPER) {
+    DEBUG ((EFI_D_INFO, "PeiDoHubConfig: Set Hub Depth as 0x%x\n", PeiUsbDevice->Tier));
+    PeiUsbHubCtrlSetHubDepth (
+      PeiServices,
+      PeiUsbDevice,
+      UsbIoPpi
+      );
+  } else {
+    //
+    //  Power all the hub ports
+    //
+    for (Index = 0; Index < PeiUsbDevice->DownStreamPortNo; Index++) {
+      Status = PeiHubSetPortFeature (
+                PeiServices,
+                UsbIoPpi,
+                (UINT8) (Index + 1),
+                EfiUsbPortPower
+                );
+      if (EFI_ERROR (Status)) {
+        DEBUG (( EFI_D_ERROR, "PeiDoHubConfig: PeiHubSetPortFeature EfiUsbPortPower failed %x\n", Index));
+        continue;
+      }
+    }
+
+    DEBUG (( EFI_D_INFO, "PeiDoHubConfig: HubDescriptor.PwrOn2PwrGood: 0x%x\n", HubDescriptor->PwrOn2PwrGood));
+    if (HubDescriptor->PwrOn2PwrGood > 0) {
+      MicroSecondDelay (HubDescriptor->PwrOn2PwrGood * USB_SET_PORT_POWER_STALL);
+    }
+
+    //
+    // Clear Hub Status Change
+    //
+    Status = PeiHubGetHubStatus (
+              PeiServices,
+              UsbIoPpi,
+              (UINT32 *) &HubStatus
+              );
+    if (EFI_ERROR (Status)) {
+      return EFI_DEVICE_ERROR;
+    } else {
+      //
+      // Hub power supply change happens
+      //
+      if ((HubStatus.HubChangeStatus & HUB_CHANGE_LOCAL_POWER) != 0) {
+        PeiHubClearHubFeature (
+          PeiServices,
+          UsbIoPpi,
+          C_HUB_LOCAL_POWER
+          );
+      }
+      //
+      // Hub change overcurrent happens
+      //
+      if ((HubStatus.HubChangeStatus & HUB_CHANGE_OVERCURRENT) != 0) {
+        PeiHubClearHubFeature (
+          PeiServices,
+          UsbIoPpi,
+          C_HUB_OVER_CURRENT
+          );
+      }
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Send reset signal over the given root hub port.
+
+  @param  PeiServices    General-purpose services that are available to every PEIM.
+  @param  UsbIoPpi       Indicates the PEI_USB_IO_PPI instance.
+  @param  PortNum        Usb hub port number (starting from 1).
+
+**/
+VOID
+PeiResetHubPort (
+  IN EFI_PEI_SERVICES    **PeiServices,
+  IN PEI_USB_IO_PPI      *UsbIoPpi,
+  IN UINT8               PortNum
+  )
+{
+  EFI_STATUS          Status;
+  UINTN               Index;
+  EFI_USB_PORT_STATUS HubPortStatus;
+
+  MicroSecondDelay (100 * 1000);
+
+  //
+  // reset root port
+  //
+  PeiHubSetPortFeature (
+    PeiServices,
+    UsbIoPpi,
+    PortNum,
+    EfiUsbPortReset
+    );
+
+  //
+  // Drive the reset signal for worst 20ms. Check USB 2.0 Spec
+  // section 7.1.7.5 for timing requirements.
+  //
+  MicroSecondDelay (USB_SET_PORT_RESET_STALL);
+
+  //
+  // Check USB_PORT_STAT_C_RESET bit to see if the resetting state is done.
+  //
+  ZeroMem (&HubPortStatus, sizeof (EFI_USB_PORT_STATUS));
+
+  for (Index = 0; Index < USB_WAIT_PORT_STS_CHANGE_LOOP; Index++) {
+    Status = PeiHubGetPortStatus (
+               PeiServices,
+               UsbIoPpi,
+               PortNum,
+               (UINT32 *) &HubPortStatus
+               );
+
+    if (EFI_ERROR (Status)) {
+      return;
+    }
+
+    if (USB_BIT_IS_SET (HubPortStatus.PortChangeStatus, USB_PORT_STAT_C_RESET)) {
+      break;
+    }
+
+    MicroSecondDelay (USB_WAIT_PORT_STS_CHANGE_STALL);
+  }
+
+  if (Index == USB_WAIT_PORT_STS_CHANGE_LOOP) {
+    DEBUG ((EFI_D_ERROR, "PeiResetHubPort: reset not finished in time on port %d\n", PortNum));
+    return;
+  }
+
+  //
+  // clear reset change root port
+  //
+  PeiHubClearPortFeature (
+    PeiServices,
+    UsbIoPpi,
+    PortNum,
+    EfiUsbPortResetChange
+    );
+
+  MicroSecondDelay (1 * 1000);
+
+  PeiHubClearPortFeature (
+    PeiServices,
+    UsbIoPpi,
+    PortNum,
+    EfiUsbPortConnectChange
+    );
+
+  //
+  // Set port enable
+  //
+  PeiHubSetPortFeature (
+    PeiServices,
+    UsbIoPpi,
+    PortNum,
+    EfiUsbPortEnable
+    );
+
+  //
+  // Clear any change status
+  //
+
+  PeiHubClearPortFeature (
+    PeiServices,
+    UsbIoPpi,
+    PortNum,
+    EfiUsbPortEnableChange
+    );
+
+  MicroSecondDelay (10 * 1000);
+
+  return;
+}
diff --git a/roms/edk2/MdeModulePkg/Bus/Usb/UsbBusPei/HubPeim.h b/roms/edk2/MdeModulePkg/Bus/Usb/UsbBusPei/HubPeim.h
new file mode 100644
index 000000000..2a6d911a0
--- /dev/null
+++ b/roms/edk2/MdeModulePkg/Bus/Usb/UsbBusPei/HubPeim.h
@@ -0,0 +1,258 @@
+/** @file
+Constants definitions for Usb Hub Peim
+
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _PEI_HUB_PEIM_H_
+#define _PEI_HUB_PEIM_H_
+
+
+//
+// Hub feature numbers
+//
+#define C_HUB_LOCAL_POWER   0
+#define C_HUB_OVER_CURRENT  1
+
+//
+// Hub class code & sub class code
+//
+#define CLASS_CODE_HUB      0x09
+#define SUB_CLASS_CODE_HUB  0
+
+//
+// Hub Status & Hub Change bit masks
+//
+#define HUB_STATUS_LOCAL_POWER  0x0001
+#define HUB_STATUS_OVERCURRENT  0x0002
+
+#define HUB_CHANGE_LOCAL_POWER  0x0001
+#define HUB_CHANGE_OVERCURRENT  0x0002
+
+//
+// Hub Characteristics
+//
+#define HUB_CHAR_LPSM     0x0003
+#define HUB_CHAR_COMPOUND 0x0004
+#define HUB_CHAR_OCPM     0x0018
+
+//
+// Standard hub request and request type
+// By [Spec-USB20/Chapter-11.24]
+//
+#define USB_HUB_CLEAR_FEATURE               0x01
+#define USB_HUB_CLEAR_FEATURE_REQ_TYPE      0x20
+
+#define USB_HUB_CLEAR_FEATURE_PORT          0x01
+#define USB_HUB_CLEAR_FEATURE_PORT_REQ_TYPE 0x23
+
+#define USB_HUB_GET_BUS_STATE               0x02
+#define USB_HUB_GET_BUS_STATE_REQ_TYPE      0xA3
+
+#define USB_HUB_GET_DESCRIPTOR              0x06
+#define USB_HUB_GET_DESCRIPTOR_REQ_TYPE     0xA0
+
+#define USB_HUB_GET_HUB_STATUS              0x00
+#define USB_HUB_GET_HUB_STATUS_REQ_TYPE     0xA0
+
+#define USB_HUB_GET_PORT_STATUS             0x00
+#define USB_HUB_GET_PORT_STATUS_REQ_TYPE    0xA3
+
+#define USB_HUB_SET_DESCRIPTOR              0x07
+#define USB_HUB_SET_DESCRIPTOR_REQ_TYPE     0x20
+
+#define USB_HUB_SET_HUB_FEATURE             0x03
+#define USB_HUB_SET_HUB_FEATURE_REQ_TYPE    0x20
+
+#define USB_HUB_SET_PORT_FEATURE            0x03
+#define USB_HUB_SET_PORT_FEATURE_REQ_TYPE   0x23
+
+#define USB_RT_HUB        (USB_TYPE_CLASS | USB_RECIP_DEVICE)
+#define USB_RT_PORT       (USB_TYPE_CLASS | USB_RECIP_OTHER)
+
+#define USB_HUB_REQ_SET_DEPTH               12
+
+#define MAXBYTES  8
+#pragma pack(1)
+//
+// Hub descriptor, the last two fields are of variable length.
+//
+typedef struct {
+  UINT8 Length;
+  UINT8 DescriptorType;
+  UINT8 NbrPorts;
+  UINT8 HubCharacteristics[2];
+  UINT8 PwrOn2PwrGood;
+  UINT8 HubContrCurrent;
+  UINT8 Filler[MAXBYTES];
+} EFI_USB_HUB_DESCRIPTOR;
+
+typedef struct {
+  UINT16  HubStatus;
+  UINT16  HubChangeStatus;
+} EFI_USB_HUB_STATUS;
+
+#pragma pack()
+/**
+  Get a given hub port status.
+
+  @param  PeiServices   General-purpose services that are available to every PEIM.
+  @param  UsbIoPpi      Indicates the PEI_USB_IO_PPI instance.
+  @param  Port          Usb hub port number (starting from 1).
+  @param  PortStatus    Current Hub port status and change status.
+
+  @retval EFI_SUCCESS       Port status is obtained successfully.
+  @retval EFI_DEVICE_ERROR  Cannot get the port status due to a hardware error.
+  @retval Others            Other failure occurs.
+
+**/
+EFI_STATUS
+PeiHubGetPortStatus (
+  IN EFI_PEI_SERVICES       **PeiServices,
+  IN PEI_USB_IO_PPI         *UsbIoPpi,
+  IN  UINT8                 Port,
+  OUT UINT32                *PortStatus
+  );
+
+/**
+  Set specified feature to a given hub port.
+
+  @param  PeiServices   General-purpose services that are available to every PEIM.
+  @param  UsbIoPpi      Indicates the PEI_USB_IO_PPI instance.
+  @param  Port          Usb hub port number (starting from 1).
+  @param  Value         New feature value.
+
+  @retval EFI_SUCCESS       Port feature is set successfully.
+  @retval EFI_DEVICE_ERROR  Cannot set the port feature due to a hardware error.
+  @retval Others            Other failure occurs.
+
+**/
+EFI_STATUS
+PeiHubSetPortFeature (
+  IN EFI_PEI_SERVICES       **PeiServices,
+  IN PEI_USB_IO_PPI         *UsbIoPpi,
+  IN  UINT8                 Port,
+  IN  UINT8                 Value
+  );
+
+
+/**
+  Get a given hub status.
+
+  @param  PeiServices   General-purpose services that are available to every PEIM.
+  @param  UsbIoPpi      Indicates the PEI_USB_IO_PPI instance.
+  @param  HubStatus     Current Hub status and change status.
+
+  @retval EFI_SUCCESS       Hub status is obtained successfully.
+  @retval EFI_DEVICE_ERROR  Cannot get the hub status due to a hardware error.
+  @retval Others            Other failure occurs.
+
+**/
+EFI_STATUS
+PeiHubGetHubStatus (
+  IN EFI_PEI_SERVICES       **PeiServices,
+  IN PEI_USB_IO_PPI         *UsbIoPpi,
+  OUT UINT32                *HubStatus
+  );
+
+/**
+  Clear specified feature on a given hub port.
+
+  @param  PeiServices   General-purpose services that are available to every PEIM.
+  @param  UsbIoPpi      Indicates the PEI_USB_IO_PPI instance.
+  @param  Port          Usb hub port number (starting from 1).
+  @param  Value         Feature value that will be cleared from the hub port.
+
+  @retval EFI_SUCCESS       Port feature is cleared successfully.
+  @retval EFI_DEVICE_ERROR  Cannot clear the port feature due to a hardware error.
+  @retval Others            Other failure occurs.
+
+**/
+EFI_STATUS
+PeiHubClearPortFeature (
+  IN EFI_PEI_SERVICES       **PeiServices,
+  IN PEI_USB_IO_PPI         *UsbIoPpi,
+  IN  UINT8                 Port,
+  IN  UINT8                 Value
+  );
+
+/**
+  Clear specified feature on a given hub.
+
+  @param  PeiServices   General-purpose services that are available to every PEIM.
+  @param  UsbIoPpi      Indicates the PEI_USB_IO_PPI instance.
+  @param  Value         Feature value that will be cleared from the hub port.
+
+  @retval EFI_SUCCESS       Hub feature is cleared successfully.
+  @retval EFI_DEVICE_ERROR  Cannot clear the hub feature due to a hardware error.
+  @retval Others            Other failure occurs.
+
+**/
+EFI_STATUS
+PeiHubClearHubFeature (
+  IN EFI_PEI_SERVICES       **PeiServices,
+  IN PEI_USB_IO_PPI         *UsbIoPpi,
+  IN  UINT8                 Value
+  );
+
+/**
+  Get a given hub descriptor.
+
+  @param  PeiServices    General-purpose services that are available to every PEIM.
+  @param  PeiUsbDevice   Indicates the hub controller device.
+  @param  UsbIoPpi       Indicates the PEI_USB_IO_PPI instance.
+  @param  DescriptorSize The length of Hub Descriptor buffer.
+  @param  HubDescriptor  Caller allocated buffer to store the hub descriptor if
+                         successfully returned.
+
+  @retval EFI_SUCCESS       Hub descriptor is obtained successfully.
+  @retval EFI_DEVICE_ERROR  Cannot get the hub descriptor due to a hardware error.
+  @retval Others            Other failure occurs.
+
+**/
+EFI_STATUS
+PeiGetHubDescriptor (
+  IN EFI_PEI_SERVICES         **PeiServices,
+  IN PEI_USB_DEVICE           *PeiUsbDevice,
+  IN PEI_USB_IO_PPI           *UsbIoPpi,
+  IN UINTN                    DescriptorSize,
+  OUT EFI_USB_HUB_DESCRIPTOR  *HubDescriptor
+  );
+
+/**
+  Configure a given hub.
+
+  @param  PeiServices    General-purpose services that are available to every PEIM.
+  @param  PeiUsbDevice   Indicating the hub controller device that will be configured
+
+  @retval EFI_SUCCESS       Hub configuration is done successfully.
+  @retval EFI_DEVICE_ERROR  Cannot configure the hub due to a hardware error.
+
+**/
+EFI_STATUS
+PeiDoHubConfig (
+  IN EFI_PEI_SERVICES         **PeiServices,
+  IN PEI_USB_DEVICE           *PeiUsbDevice
+  );
+
+/**
+  Send reset signal over the given root hub port.
+
+  @param  PeiServices    General-purpose services that are available to every PEIM.
+  @param  UsbIoPpi       Indicates the PEI_USB_IO_PPI instance.
+  @param  PortNum        Usb hub port number (starting from 1).
+
+**/
+VOID
+PeiResetHubPort (
+  IN EFI_PEI_SERVICES    **PeiServices,
+  IN PEI_USB_IO_PPI      *UsbIoPpi,
+  IN UINT8               PortNum
+  );
+
+#endif
+
+
diff --git a/roms/edk2/MdeModulePkg/Bus/Usb/UsbBusPei/PeiUsbLib.c b/roms/edk2/MdeModulePkg/Bus/Usb/UsbBusPei/PeiUsbLib.c
new file mode 100644
index 000000000..1385b0ab5
--- /dev/null
+++ b/roms/edk2/MdeModulePkg/Bus/Usb/UsbBusPei/PeiUsbLib.c
@@ -0,0 +1,185 @@
+/** @file
+Common Library for PEI USB
+
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved. <BR>
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "UsbPeim.h"
+#include "PeiUsbLib.h"
+
+/**
+  Get a given usb descriptor.
+
+  @param  PeiServices        General-purpose services that are available to every PEIM.
+  @param  UsbIoPpi           Indicates the PEI_USB_IO_PPI instance.
+  @param  Value              Request Value.
+  @param  Index              Request Index.
+  @param  DescriptorLength   Request descriptor Length.
+  @param  Descriptor         Request descriptor.
+
+
+  @retval EFI_SUCCESS       Usb descriptor is obtained successfully.
+  @retval EFI_DEVICE_ERROR  Cannot get the usb descriptor due to a hardware error.
+  @retval Others            Other failure occurs.
+
+**/
+EFI_STATUS
+PeiUsbGetDescriptor (
+  IN  EFI_PEI_SERVICES         **PeiServices,
+  IN  PEI_USB_IO_PPI           *UsbIoPpi,
+  IN  UINT16                   Value,
+  IN  UINT16                   Index,
+  IN  UINT16                   DescriptorLength,
+  OUT VOID                     *Descriptor
+  )
+{
+  EFI_USB_DEVICE_REQUEST  DevReq;
+
+  ASSERT (UsbIoPpi != NULL);
+
+  DevReq.RequestType  = USB_DEV_GET_DESCRIPTOR_REQ_TYPE;
+  DevReq.Request      = USB_DEV_GET_DESCRIPTOR;
+  DevReq.Value        = Value;
+  DevReq.Index        = Index;
+  DevReq.Length       = DescriptorLength;
+
+  return UsbIoPpi->UsbControlTransfer (
+                     PeiServices,
+                     UsbIoPpi,
+                     &DevReq,
+                     EfiUsbDataIn,
+                     PcdGet32 (PcdUsbTransferTimeoutValue),
+                     Descriptor,
+                     DescriptorLength
+                     );
+}
+
+/**
+  Set a usb device with a specified address.
+
+  @param  PeiServices        General-purpose services that are available to every PEIM.
+  @param  UsbIoPpi           Indicates the PEI_USB_IO_PPI instance.
+  @param  AddressValue       The address to assign.
+
+  @retval EFI_SUCCESS       Usb device address is set successfully.
+  @retval EFI_DEVICE_ERROR  Cannot set the usb address due to a hardware error.
+  @retval Others            Other failure occurs.
+
+**/
+EFI_STATUS
+PeiUsbSetDeviceAddress (
+  IN EFI_PEI_SERVICES         **PeiServices,
+  IN PEI_USB_IO_PPI           *UsbIoPpi,
+  IN UINT16                   AddressValue
+  )
+{
+  EFI_USB_DEVICE_REQUEST  DevReq;
+
+  ASSERT (UsbIoPpi != NULL);
+
+  DevReq.RequestType  = USB_DEV_SET_ADDRESS_REQ_TYPE;
+  DevReq.Request      = USB_DEV_SET_ADDRESS;
+  DevReq.Value        = AddressValue;
+  DevReq.Index        = 0;
+  DevReq.Length       = 0;
+
+  return UsbIoPpi->UsbControlTransfer (
+                     PeiServices,
+                     UsbIoPpi,
+                     &DevReq,
+                     EfiUsbNoData,
+                     PcdGet32 (PcdUsbTransferTimeoutValue),
+                     NULL,
+                     0
+                     );
+}
+
+
+
+/**
+  Configure a usb device to Configuration 1.
+
+  @param  PeiServices        General-purpose services that are available to every PEIM.
+  @param  UsbIoPpi           Indicates the PEI_USB_IO_PPI instance.
+
+  @retval EFI_SUCCESS       Usb device is set to use Configuration 1 successfully.
+  @retval EFI_DEVICE_ERROR  Cannot set the usb device due to a hardware error.
+  @retval Others            Other failure occurs.
+
+**/
+EFI_STATUS
+PeiUsbSetConfiguration (
+  IN EFI_PEI_SERVICES         **PeiServices,
+  IN PEI_USB_IO_PPI           *UsbIoPpi
+  )
+{
+  EFI_USB_DEVICE_REQUEST  DevReq;
+  ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));
+
+  DevReq.RequestType  = USB_DEV_SET_CONFIGURATION_REQ_TYPE;
+  DevReq.Request      = USB_DEV_SET_CONFIGURATION;
+  DevReq.Value        = 1;
+
+  return UsbIoPpi->UsbControlTransfer (
+                     PeiServices,
+                     UsbIoPpi,
+                     &DevReq,
+                     EfiUsbNoData,
+                     PcdGet32 (PcdUsbTransferTimeoutValue),
+                     NULL,
+                     0
+                     );
+}
+
+/**
+  Judge if the port is connected with a usb device or not.
+
+  @param  PortStatus  The usb port status gotten.
+
+  @retval TRUE        A usb device is connected with the port.
+  @retval FALSE       No usb device is connected with the port.
+
+**/
+BOOLEAN
+IsPortConnect (
+  IN UINT16  PortStatus
+  )
+{
+  //
+  // return the bit 0 value of PortStatus
+  //
+  if ((PortStatus & USB_PORT_STAT_CONNECTION) != 0) {
+    return TRUE;
+  } else {
+    return FALSE;
+  }
+}
+
+/**
+  Get device speed according to port status.
+
+  @param    PortStatus  The usb port status gotten.
+
+  @return   Device speed value.
+
+**/
+UINTN
+PeiUsbGetDeviceSpeed (
+  IN UINT16 PortStatus
+  )
+{
+  if ((PortStatus & USB_PORT_STAT_LOW_SPEED) != 0) {
+    return EFI_USB_SPEED_LOW;
+  } else if ((PortStatus & USB_PORT_STAT_HIGH_SPEED) != 0){
+    return EFI_USB_SPEED_HIGH;
+  } else if ((PortStatus & USB_PORT_STAT_SUPER_SPEED) != 0) {
+    return EFI_USB_SPEED_SUPER;
+  } else {
+    return EFI_USB_SPEED_FULL;
+  }
+}
+
+
diff --git a/roms/edk2/MdeModulePkg/Bus/Usb/UsbBusPei/PeiUsbLib.h b/roms/edk2/MdeModulePkg/Bus/Usb/UsbBusPei/PeiUsbLib.h
new file mode 100644
index 000000000..48b8e594b
--- /dev/null
+++ b/roms/edk2/MdeModulePkg/Bus/Usb/UsbBusPei/PeiUsbLib.h
@@ -0,0 +1,189 @@
+/** @file
+Common Library for PEI USB
+
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved. <BR>
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _PEI_USB_LIB_H_
+#define _PEI_USB_LIB_H_
+
+
+//
+// Standard device request and request type
+// By [Spec-USB20/Chapter-9.4]
+//
+#define USB_DEV_GET_STATUS                  0x00
+#define USB_DEV_GET_STATUS_REQ_TYPE_D       0x80 // Receiver : Device
+#define USB_DEV_GET_STATUS_REQ_TYPE_I       0x81 // Receiver : Interface
+#define USB_DEV_GET_STATUS_REQ_TYPE_E       0x82 // Receiver : Endpoint
+
+#define USB_DEV_CLEAR_FEATURE               0x01
+#define USB_DEV_CLEAR_FEATURE_REQ_TYPE_D    0x00 // Receiver : Device
+#define USB_DEV_CLEAR_FEATURE_REQ_TYPE_I    0x01 // Receiver : Interface
+#define USB_DEV_CLEAR_FEATURE_REQ_TYPE_E    0x02 // Receiver : Endpoint
+
+#define USB_DEV_SET_FEATURE                 0x03
+#define USB_DEV_SET_FEATURE_REQ_TYPE_D      0x00 // Receiver : Device
+#define USB_DEV_SET_FEATURE_REQ_TYPE_I      0x01 // Receiver : Interface
+#define USB_DEV_SET_FEATURE_REQ_TYPE_E      0x02 // Receiver : Endpoint
+
+#define USB_DEV_SET_ADDRESS                 0x05
+#define USB_DEV_SET_ADDRESS_REQ_TYPE        0x00
+
+#define USB_DEV_GET_DESCRIPTOR              0x06
+#define USB_DEV_GET_DESCRIPTOR_REQ_TYPE     0x80
+
+#define USB_DEV_SET_DESCRIPTOR              0x07
+#define USB_DEV_SET_DESCRIPTOR_REQ_TYPE     0x00
+
+#define USB_DEV_GET_CONFIGURATION           0x08
+#define USB_DEV_GET_CONFIGURATION_REQ_TYPE  0x80
+
+#define USB_DEV_SET_CONFIGURATION           0x09
+#define USB_DEV_SET_CONFIGURATION_REQ_TYPE  0x00
+
+#define USB_DEV_GET_INTERFACE               0x0A
+#define USB_DEV_GET_INTERFACE_REQ_TYPE      0x81
+
+#define USB_DEV_SET_INTERFACE               0x0B
+#define USB_DEV_SET_INTERFACE_REQ_TYPE      0x01
+
+#define USB_DEV_SYNCH_FRAME                 0x0C
+#define USB_DEV_SYNCH_FRAME_REQ_TYPE        0x82
+
+//
+// USB Descriptor types
+//
+#define USB_DT_DEVICE     0x01
+#define USB_DT_CONFIG     0x02
+#define USB_DT_STRING     0x03
+#define USB_DT_INTERFACE  0x04
+#define USB_DT_ENDPOINT   0x05
+#define USB_DT_HUB        0x29
+#define USB_DT_SUPERSPEED_HUB 0x2A
+#define USB_DT_HID        0x21
+
+//
+// USB request type
+//
+#define USB_TYPE_STANDARD (0x00 << 5)
+#define USB_TYPE_CLASS    (0x01 << 5)
+#define USB_TYPE_VENDOR   (0x02 << 5)
+#define USB_TYPE_RESERVED (0x03 << 5)
+
+//
+// USB request targer device
+//
+#define USB_RECIP_DEVICE    0x00
+#define USB_RECIP_INTERFACE 0x01
+#define USB_RECIP_ENDPOINT  0x02
+#define USB_RECIP_OTHER     0x03
+
+typedef enum {
+  EfiUsbEndpointHalt,
+  EfiUsbDeviceRemoteWakeup
+} EFI_USB_STANDARD_FEATURE_SELECTOR;
+
+//
+// Usb Data recipient type
+//
+typedef enum {
+  EfiUsbDevice,
+  EfiUsbInterface,
+  EfiUsbEndpoint
+} EFI_USB_RECIPIENT;
+
+/**
+  Get a given usb descriptor.
+
+  @param  PeiServices        General-purpose services that are available to every PEIM.
+  @param  UsbIoPpi           Indicates the PEI_USB_IO_PPI instance.
+  @param  Value              Request Value.
+  @param  Index              Request Index.
+  @param  DescriptorLength   Request descriptor Length.
+  @param  Descriptor         Request descriptor.
+
+
+  @retval EFI_SUCCESS       Usb descriptor is obtained successfully.
+  @retval EFI_DEVICE_ERROR  Cannot get the usb descriptor due to a hardware error.
+  @retval Others            Other failure occurs.
+
+**/
+EFI_STATUS
+PeiUsbGetDescriptor (
+  IN  EFI_PEI_SERVICES         **PeiServices,
+  IN  PEI_USB_IO_PPI           *UsbIoPpi,
+  IN  UINT16                   Value,
+  IN  UINT16                   Index,
+  IN  UINT16                   DescriptorLength,
+  OUT VOID                     *Descriptor
+  );
+
+/**
+  Set a usb device with a specified address.
+
+  @param  PeiServices        General-purpose services that are available to every PEIM.
+  @param  UsbIoPpi           Indicates the PEI_USB_IO_PPI instance.
+  @param  AddressValue       The address to assign.
+
+  @retval EFI_SUCCESS        Usb device address is set successfully.
+  @retval EFI_DEVICE_ERROR   Cannot set the usb address due to a hardware error.
+  @retval Others             Other failure occurs.
+
+**/
+EFI_STATUS
+PeiUsbSetDeviceAddress (
+  IN EFI_PEI_SERVICES         **PeiServices,
+  IN PEI_USB_IO_PPI           *UsbIoPpi,
+  IN UINT16                   AddressValue
+  );
+
+
+/**
+  Configure a usb device to Configuration 1.
+
+  @param  PeiServices        General-purpose services that are available to every PEIM.
+  @param  UsbIoPpi           Indicates the PEI_USB_IO_PPI instance.
+
+  @retval EFI_SUCCESS        Usb device is set to use Configuration 1 successfully.
+  @retval EFI_DEVICE_ERROR   Cannot set the usb device due to a hardware error.
+  @retval Others             Other failure occurs.
+
+**/
+EFI_STATUS
+PeiUsbSetConfiguration (
+  IN EFI_PEI_SERVICES         **PeiServices,
+  IN PEI_USB_IO_PPI           *UsbIoPpi
+  );
+
+/**
+  Judge if the port is connected with a usb device or not.
+
+  @param  PortStatus  The usb port status gotten.
+
+  @retval TRUE        A usb device is connected with the port.
+  @retval FALSE       No usb device is connected with the port.
+
+**/
+BOOLEAN
+IsPortConnect (
+  IN UINT16  PortStatus
+  );
+
+/**
+  Get device speed according to port status.
+
+  @param    PortStatus  The usb port status gotten.
+
+  @return   Device speed value.
+
+**/
+UINTN
+PeiUsbGetDeviceSpeed (
+  IN UINT16 PortStatus
+  );
+
+#endif
diff --git a/roms/edk2/MdeModulePkg/Bus/Usb/UsbBusPei/UsbBusPei.inf b/roms/edk2/MdeModulePkg/Bus/Usb/UsbBusPei/UsbBusPei.inf
new file mode 100644
index 000000000..31d7c2e2f
--- /dev/null
+++ b/roms/edk2/MdeModulePkg/Bus/Usb/UsbBusPei/UsbBusPei.inf
@@ -0,0 +1,60 @@
+## @file
+# The Usb Bus Peim driver is used to support recovery from usb device.
+#
+# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = UsbBusPei
+  MODULE_UNI_FILE                = UsbBusPei.uni
+  FILE_GUID                      = 8401A045-6F70-4505-8471-7015B40355E3
+  MODULE_TYPE                    = PEIM
+  VERSION_STRING                 = 1.0
+
+  ENTRY_POINT                    = PeimInitializeUsb
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 EBC
+#
+
+[Sources]
+  PeiUsbLib.c
+  HubPeim.c
+  UsbIoPeim.c
+  UsbPeim.c
+  UsbPeim.h
+  PeiUsbLib.h
+  HubPeim.h
+
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+  TimerLib
+  BaseMemoryLib
+  PeiServicesLib
+  PeimEntryPoint
+  DebugLib
+  PcdLib
+
+[Pcd]
+  gEfiMdePkgTokenSpaceGuid.PcdUsbTransferTimeoutValue  ## CONSUMES
+
+[Ppis]
+  gPeiUsbIoPpiGuid                              ## PRODUCES
+  gPeiUsbHostControllerPpiGuid                  ## SOMETIMES_CONSUMES
+  gPeiUsb2HostControllerPpiGuid                 ## SOMETIMES_CONSUMES
+
+[Depex]
+  gEfiPeiMemoryDiscoveredPpiGuid AND gPeiUsb2HostControllerPpiGuid OR gPeiUsbHostControllerPpiGuid
+
+[UserExtensions.TianoCore."ExtraFiles"]
+  UsbBusPeiExtra.uni
diff --git a/roms/edk2/MdeModulePkg/Bus/Usb/UsbBusPei/UsbBusPei.uni b/roms/edk2/MdeModulePkg/Bus/Usb/UsbBusPei/UsbBusPei.uni
new file mode 100644
index 000000000..92f8af732
--- /dev/null
+++ b/roms/edk2/MdeModulePkg/Bus/Usb/UsbBusPei/UsbBusPei.uni
@@ -0,0 +1,16 @@
+// /** @file
+// The Usb Bus Peim driver is used to support recovery from usb device.
+//
+// The USB Bus PEIM driver is used to support recovery from USB devices.
+//
+// Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT             #language en-US "Support recovery from USB devices"
+
+#string STR_MODULE_DESCRIPTION          #language en-US "The USB Bus PEIM driver is used to support recovery from USB devices."
+
diff --git a/roms/edk2/MdeModulePkg/Bus/Usb/UsbBusPei/UsbBusPeiExtra.uni b/roms/edk2/MdeModulePkg/Bus/Usb/UsbBusPei/UsbBusPeiExtra.uni
new file mode 100644
index 000000000..8bd6c65e7
--- /dev/null
+++ b/roms/edk2/MdeModulePkg/Bus/Usb/UsbBusPei/UsbBusPeiExtra.uni
@@ -0,0 +1,14 @@
+// /** @file
+// UsbBusPei Localized Strings and Content
+//
+// Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+#string STR_PROPERTIES_MODULE_NAME
+#language en-US
+"USB Bus PEI Module for Recovery"
+
+
diff --git a/roms/edk2/MdeModulePkg/Bus/Usb/UsbBusPei/UsbIoPeim.c b/roms/edk2/MdeModulePkg/Bus/Usb/UsbBusPei/UsbIoPeim.c
new file mode 100644
index 000000000..fc04f834a
--- /dev/null
+++ b/roms/edk2/MdeModulePkg/Bus/Usb/UsbBusPei/UsbIoPeim.c
@@ -0,0 +1,365 @@
+/** @file
+The module is used to implement Usb Io PPI interfaces.
+
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved. <BR>
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "UsbPeim.h"
+#include "PeiUsbLib.h"
+
+/**
+  Submits control transfer to a target USB device.
+
+  @param  PeiServices            The pointer of EFI_PEI_SERVICES.
+  @param  This                   The pointer of PEI_USB_IO_PPI.
+  @param  Request                USB device request to send.
+  @param  Direction              Specifies the data direction for the data stage.
+  @param  Timeout                Indicates the maximum timeout, in millisecond. If Timeout
+                                 is 0, then the caller must wait for the function to be
+                                 completed until EFI_SUCCESS or EFI_DEVICE_ERROR is returned.
+  @param  Data                   Data buffer to be transmitted or received from USB device.
+  @param  DataLength             The size (in bytes) of the data buffer.
+
+  @retval EFI_SUCCESS            Transfer was completed successfully.
+  @retval EFI_OUT_OF_RESOURCES   The transfer failed due to lack of resources.
+  @retval EFI_INVALID_PARAMETER  Some parameters are invalid.
+  @retval EFI_TIMEOUT            Transfer failed due to timeout.
+  @retval EFI_DEVICE_ERROR       Transfer failed due to host controller or device error.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiUsbControlTransfer (
+  IN     EFI_PEI_SERVICES          **PeiServices,
+  IN     PEI_USB_IO_PPI            *This,
+  IN     EFI_USB_DEVICE_REQUEST    *Request,
+  IN     EFI_USB_DATA_DIRECTION    Direction,
+  IN     UINT32                    Timeout,
+  IN OUT VOID                      *Data,      OPTIONAL
+  IN     UINTN                     DataLength  OPTIONAL
+  )
+{
+  EFI_STATUS                  Status;
+  PEI_USB_DEVICE              *PeiUsbDev;
+  UINT32                      TransferResult;
+  EFI_USB_ENDPOINT_DESCRIPTOR *EndpointDescriptor;
+  UINT8                       EndpointIndex;
+
+  PeiUsbDev = PEI_USB_DEVICE_FROM_THIS (This);
+
+  EndpointDescriptor = NULL;
+  EndpointIndex = 0;
+
+  if ((Request->Request     == USB_REQ_CLEAR_FEATURE) &&
+      (Request->RequestType == USB_DEV_CLEAR_FEATURE_REQ_TYPE_E) &&
+      (Request->Value       == USB_FEATURE_ENDPOINT_HALT)) {
+    //
+    // Request->Index is the Endpoint Address, use it to get the Endpoint Index.
+    //
+    while (EndpointIndex < MAX_ENDPOINT) {
+      Status = PeiUsbGetEndpointDescriptor (PeiServices, This, EndpointIndex, &EndpointDescriptor);
+      if (EFI_ERROR (Status)) {
+        return EFI_INVALID_PARAMETER;
+      }
+
+      if (EndpointDescriptor->EndpointAddress == Request->Index) {
+        break;
+      }
+
+      EndpointIndex++;
+    }
+
+    if (EndpointIndex == MAX_ENDPOINT) {
+      return EFI_INVALID_PARAMETER;
+    }
+  }
+
+  if (PeiUsbDev->Usb2HcPpi != NULL) {
+    Status = PeiUsbDev->Usb2HcPpi->ControlTransfer (
+                        PeiServices,
+                        PeiUsbDev->Usb2HcPpi,
+                        PeiUsbDev->DeviceAddress,
+                        PeiUsbDev->DeviceSpeed,
+                        PeiUsbDev->MaxPacketSize0,
+                        Request,
+                        Direction,
+                        Data,
+                        &DataLength,
+                        Timeout,
+                        &(PeiUsbDev->Translator),
+                        &TransferResult
+                        );
+  } else {
+    Status = PeiUsbDev->UsbHcPpi->ControlTransfer (
+                        PeiServices,
+                        PeiUsbDev->UsbHcPpi,
+                        PeiUsbDev->DeviceAddress,
+                        PeiUsbDev->DeviceSpeed,
+                        (UINT8) PeiUsbDev->MaxPacketSize0,
+                        Request,
+                        Direction,
+                        Data,
+                        &DataLength,
+                        Timeout,
+                        &TransferResult
+                        );
+  }
+
+  //
+  // Reset the endpoint toggle when endpoint stall is cleared
+  //
+  if ((Request->Request     == USB_REQ_CLEAR_FEATURE) &&
+      (Request->RequestType == USB_DEV_CLEAR_FEATURE_REQ_TYPE_E) &&
+      (Request->Value       == USB_FEATURE_ENDPOINT_HALT)) {
+    if ((PeiUsbDev->DataToggle & (1 << EndpointIndex)) != 0) {
+      PeiUsbDev->DataToggle = (UINT16) (PeiUsbDev->DataToggle ^ (1 << EndpointIndex));
+    }
+  }
+
+  DEBUG ((EFI_D_INFO, "PeiUsbControlTransfer: %r\n", Status));
+  return Status;
+}
+
+/**
+  Submits bulk transfer to a bulk endpoint of a USB device.
+
+  @param  PeiServices           The pointer of EFI_PEI_SERVICES.
+  @param  This                  The pointer of PEI_USB_IO_PPI.
+  @param  DeviceEndpoint        Endpoint number and its direction in bit 7.
+  @param  Data                  A pointer to the buffer of data to transmit
+                                from or receive into.
+  @param  DataLength            The length of the data buffer.
+  @param  Timeout               Indicates the maximum time, in millisecond, which the
+                                transfer is allowed to complete. If Timeout is 0, then
+                                the caller must wait for the function to be completed
+                                until EFI_SUCCESS or EFI_DEVICE_ERROR is returned.
+
+  @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 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
+PeiUsbBulkTransfer (
+  IN     EFI_PEI_SERVICES    **PeiServices,
+  IN     PEI_USB_IO_PPI      *This,
+  IN     UINT8               DeviceEndpoint,
+  IN OUT VOID                *Data,
+  IN OUT UINTN               *DataLength,
+  IN     UINTN               Timeout
+  )
+{
+  EFI_STATUS                  Status;
+  PEI_USB_DEVICE              *PeiUsbDev;
+  UINT32                      TransferResult;
+  UINTN                       MaxPacketLength;
+  UINT8                       DataToggle;
+  UINT8                       OldToggle;
+  EFI_USB_ENDPOINT_DESCRIPTOR *EndpointDescriptor;
+  UINT8                       EndpointIndex;
+  VOID                        *Data2[EFI_USB_MAX_BULK_BUFFER_NUM];
+
+  PeiUsbDev     = PEI_USB_DEVICE_FROM_THIS (This);
+
+  EndpointDescriptor = NULL;
+  EndpointIndex = 0;
+  Data2[0] = Data;
+  Data2[1] = NULL;
+
+  while (EndpointIndex < MAX_ENDPOINT) {
+    Status = PeiUsbGetEndpointDescriptor (PeiServices, This, EndpointIndex, &EndpointDescriptor);
+    if (EFI_ERROR (Status)) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    if (EndpointDescriptor->EndpointAddress == DeviceEndpoint) {
+      break;
+    }
+
+    EndpointIndex++;
+  }
+
+  if (EndpointIndex == MAX_ENDPOINT) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  MaxPacketLength = PeiUsbDev->EndpointDesc[EndpointIndex]->MaxPacketSize;
+  if ((PeiUsbDev->DataToggle & (1 << EndpointIndex)) != 0) {
+    DataToggle = 1;
+  } else {
+    DataToggle = 0;
+  }
+
+  OldToggle = DataToggle;
+
+  if (PeiUsbDev->Usb2HcPpi != NULL) {
+    Status = PeiUsbDev->Usb2HcPpi->BulkTransfer (
+                        PeiServices,
+                        PeiUsbDev->Usb2HcPpi,
+                        PeiUsbDev->DeviceAddress,
+                        DeviceEndpoint,
+                        PeiUsbDev->DeviceSpeed,
+                        MaxPacketLength,
+                        Data2,
+                        DataLength,
+                        &DataToggle,
+                        Timeout,
+                        &(PeiUsbDev->Translator),
+                        &TransferResult
+                        );
+  } else {
+    Status = PeiUsbDev->UsbHcPpi->BulkTransfer (
+                        PeiServices,
+                        PeiUsbDev->UsbHcPpi,
+                        PeiUsbDev->DeviceAddress,
+                        DeviceEndpoint,
+                        (UINT8) MaxPacketLength,
+                        Data,
+                        DataLength,
+                        &DataToggle,
+                        Timeout,
+                        &TransferResult
+                        );
+  }
+
+  if (OldToggle != DataToggle) {
+    PeiUsbDev->DataToggle = (UINT16) (PeiUsbDev->DataToggle ^ (1 << EndpointIndex));
+  }
+
+  DEBUG ((EFI_D_INFO, "PeiUsbBulkTransfer: %r\n", Status));
+  return Status;
+}
+
+/**
+  Get the usb interface descriptor.
+
+  @param  PeiServices          General-purpose services that are available to every PEIM.
+  @param  This                 Indicates the PEI_USB_IO_PPI instance.
+  @param  InterfaceDescriptor  Request interface descriptor.
+
+
+  @retval EFI_SUCCESS          Usb interface descriptor is obtained successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiUsbGetInterfaceDescriptor (
+  IN  EFI_PEI_SERVICES               **PeiServices,
+  IN  PEI_USB_IO_PPI                 *This,
+  OUT EFI_USB_INTERFACE_DESCRIPTOR   **InterfaceDescriptor
+  )
+{
+  PEI_USB_DEVICE  *PeiUsbDev;
+  PeiUsbDev             = PEI_USB_DEVICE_FROM_THIS (This);
+  *InterfaceDescriptor  = PeiUsbDev->InterfaceDesc;
+  return EFI_SUCCESS;
+}
+
+/**
+  Get the usb endpoint descriptor.
+
+  @param  PeiServices          General-purpose services that are available to every PEIM.
+  @param  This                 Indicates the PEI_USB_IO_PPI instance.
+  @param  EndpointIndex        The valid index of the specified endpoint.
+  @param  EndpointDescriptor   Request endpoint descriptor.
+
+  @retval EFI_SUCCESS       Usb endpoint descriptor is obtained successfully.
+  @retval EFI_NOT_FOUND     Usb endpoint descriptor is NOT found.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiUsbGetEndpointDescriptor (
+  IN  EFI_PEI_SERVICES               **PeiServices,
+  IN  PEI_USB_IO_PPI                 *This,
+  IN  UINT8                          EndpointIndex,
+  OUT EFI_USB_ENDPOINT_DESCRIPTOR    **EndpointDescriptor
+  )
+{
+  PEI_USB_DEVICE  *PeiUsbDev;
+
+  PeiUsbDev = PEI_USB_DEVICE_FROM_THIS (This);
+
+  ASSERT (EndpointDescriptor != NULL);
+
+  //
+  // The valid range of EndpointIndex is 0..15
+  // If EndpointIndex is lesser than 15 but larger than the number of interfaces,
+  // a EFI_NOT_FOUND should be returned
+  //
+  ASSERT (EndpointIndex <= 15);
+
+  if (EndpointIndex >= PeiUsbDev->InterfaceDesc->NumEndpoints) {
+    return EFI_NOT_FOUND;
+  }
+
+  *EndpointDescriptor = PeiUsbDev->EndpointDesc[EndpointIndex];
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Reset the port and re-configure the usb device.
+
+  @param  PeiServices    General-purpose services that are available to every PEIM.
+  @param  This           Indicates the PEI_USB_IO_PPI instance.
+
+  @retval EFI_SUCCESS    Usb device is reset and configured successfully.
+  @retval Others         Other failure occurs.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiUsbPortReset (
+  IN EFI_PEI_SERVICES               **PeiServices,
+  IN PEI_USB_IO_PPI                 *This
+  )
+{
+  PEI_USB_DEVICE  *PeiUsbDev;
+  EFI_STATUS      Status;
+  UINT8           Address;
+
+  PeiUsbDev = PEI_USB_DEVICE_FROM_THIS (This);
+
+  ResetRootPort (
+    PeiServices,
+    PeiUsbDev->UsbHcPpi,
+    PeiUsbDev->Usb2HcPpi,
+    PeiUsbDev->DeviceAddress,
+    0
+    );
+
+  //
+  // Set address
+  //
+  Address                   = PeiUsbDev->DeviceAddress;
+  PeiUsbDev->DeviceAddress  = 0;
+
+  Status = PeiUsbSetDeviceAddress (
+            PeiServices,
+            This,
+            Address
+            );
+
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  PeiUsbDev->DeviceAddress = Address;
+
+  //
+  // Set default configuration
+  //
+  Status = PeiUsbSetConfiguration (
+            PeiServices,
+            This
+            );
+
+  return Status;
+}
diff --git a/roms/edk2/MdeModulePkg/Bus/Usb/UsbBusPei/UsbPeim.c b/roms/edk2/MdeModulePkg/Bus/Usb/UsbBusPei/UsbPeim.c
new file mode 100644
index 000000000..45e48f472
--- /dev/null
+++ b/roms/edk2/MdeModulePkg/Bus/Usb/UsbBusPei/UsbPeim.c
@@ -0,0 +1,1243 @@
+/** @file
+The module to produce Usb Bus PPI.
+
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "UsbPeim.h"
+#include "HubPeim.h"
+#include "PeiUsbLib.h"
+
+//
+// UsbIo PPI interface function
+//
+PEI_USB_IO_PPI         mUsbIoPpi = {
+  PeiUsbControlTransfer,
+  PeiUsbBulkTransfer,
+  PeiUsbGetInterfaceDescriptor,
+  PeiUsbGetEndpointDescriptor,
+  PeiUsbPortReset
+};
+
+EFI_PEI_PPI_DESCRIPTOR mUsbIoPpiList = {
+  (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+  &gPeiUsbIoPpiGuid,
+  NULL
+};
+
+/**
+  The enumeration routine to detect device change.
+
+  @param  PeiServices            Describes the list of possible PEI Services.
+  @param  UsbHcPpi               The pointer of PEI_USB_HOST_CONTROLLER_PPI instance.
+  @param  Usb2HcPpi              The pointer of PEI_USB2_HOST_CONTROLLER_PPI instance.
+
+  @retval EFI_SUCCESS            The usb is enumerated successfully.
+  @retval EFI_OUT_OF_RESOURCES   Can't allocate memory resource.
+  @retval Others                 Other failure occurs.
+
+**/
+EFI_STATUS
+PeiUsbEnumeration (
+  IN EFI_PEI_SERVICES               **PeiServices,
+  IN PEI_USB_HOST_CONTROLLER_PPI    *UsbHcPpi,
+  IN PEI_USB2_HOST_CONTROLLER_PPI    *Usb2HcPpi
+  );
+
+/**
+  Configure new detected usb device.
+
+  @param  PeiServices            Describes the list of possible PEI Services.
+  @param  PeiUsbDevice           The pointer of PEI_USB_DEVICE instance.
+  @param  Port                   The port to be configured.
+  @param  DeviceAddress          The device address to be configured.
+
+  @retval EFI_SUCCESS            The new detected usb device is configured successfully.
+  @retval EFI_OUT_OF_RESOURCES   Can't allocate memory resource.
+  @retval Others                 Other failure occurs.
+
+**/
+EFI_STATUS
+PeiConfigureUsbDevice (
+  IN     EFI_PEI_SERVICES    **PeiServices,
+  IN     PEI_USB_DEVICE      *PeiUsbDevice,
+  IN     UINT8               Port,
+  IN OUT UINT8               *DeviceAddress
+  );
+
+/**
+  Get all configurations from a detected usb device.
+
+  @param  PeiServices            Describes the list of possible PEI Services.
+  @param  PeiUsbDevice           The pointer of PEI_USB_DEVICE instance.
+
+  @retval EFI_SUCCESS            The new detected usb device is configured successfully.
+  @retval EFI_OUT_OF_RESOURCES   Can't allocate memory resource.
+  @retval Others                 Other failure occurs.
+
+**/
+EFI_STATUS
+PeiUsbGetAllConfiguration (
+  IN EFI_PEI_SERVICES   **PeiServices,
+  IN PEI_USB_DEVICE     *PeiUsbDevice
+  );
+
+/**
+  Get the start position of next wanted descriptor.
+
+  @param  Buffer            Buffer containing data to parse.
+  @param  Length            Buffer length.
+  @param  DescType          Descriptor type.
+  @param  DescLength        Descriptor length.
+  @param  ParsedBytes       Bytes has been parsed.
+
+  @retval EFI_SUCCESS       Get wanted descriptor successfully.
+  @retval EFI_DEVICE_ERROR  Error occurred.
+
+**/
+EFI_STATUS
+GetExpectedDescriptor (
+  IN  UINT8       *Buffer,
+  IN  UINTN       Length,
+  IN  UINT8       DescType,
+  IN  UINT8       DescLength,
+  OUT UINTN       *ParsedBytes
+  );
+
+/**
+  The entrypoint of the module, it will enumerate all HCs.
+
+  @param  FileHandle             Handle of the file being invoked.
+  @param  PeiServices            Describes the list of possible PEI Services.
+
+  @retval EFI_SUCCESS            Usb initialization is done successfully.
+  @retval EFI_OUT_OF_RESOURCES   Can't allocate memory resource.
+  @retval EFI_UNSUPPORTED        Can't find required PPI.
+
+**/
+EFI_STATUS
+EFIAPI
+PeimInitializeUsb (
+  IN EFI_PEI_FILE_HANDLE        FileHandle,
+  IN CONST EFI_PEI_SERVICES     **PeiServices
+  )
+{
+  EFI_STATUS                   Status;
+  UINTN                        Index;
+  PEI_USB_HOST_CONTROLLER_PPI  *UsbHcPpi;
+  PEI_USB2_HOST_CONTROLLER_PPI *Usb2HcPpi;
+
+  if (!EFI_ERROR (PeiServicesRegisterForShadow (FileHandle))) {
+    return EFI_SUCCESS;
+  }
+
+  //
+  // gPeiUsbHostControllerPpiGuid and gPeiUsb2HostControllerPpiGuid should not
+  // be produced at the same time
+  //
+  Index = 0;
+  while (TRUE) {
+    //
+    // Get UsbHcPpi at first.
+    //
+    Status = PeiServicesLocatePpi (
+               &gPeiUsbHostControllerPpiGuid,
+               Index,
+               NULL,
+               (VOID **) &UsbHcPpi
+               );
+    if (EFI_ERROR (Status)) {
+      //
+      // No more host controller, break out
+      //
+      break;
+    }
+    PeiUsbEnumeration ((EFI_PEI_SERVICES **) PeiServices, UsbHcPpi, NULL);
+    Index++;
+  }
+
+  if (Index == 0) {
+    //
+    // Then try to get Usb2HcPpi.
+    //
+    while (TRUE) {
+      Status = PeiServicesLocatePpi (
+                 &gPeiUsb2HostControllerPpiGuid,
+                 Index,
+                 NULL,
+                 (VOID **) &Usb2HcPpi
+                 );
+      if (EFI_ERROR (Status)) {
+        //
+        // No more host controller, break out
+        //
+        break;
+      }
+      PeiUsbEnumeration ((EFI_PEI_SERVICES **) PeiServices, NULL, Usb2HcPpi);
+      Index++;
+    }
+  }
+
+  if (Index == 0) {
+    return EFI_UNSUPPORTED;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  The Hub Enumeration just scans the hub ports one time. It also
+  doesn't support hot-plug.
+
+  @param  PeiServices            Describes the list of possible PEI Services.
+  @param  PeiUsbDevice           The pointer of PEI_USB_DEVICE instance.
+  @param  CurrentAddress         The DeviceAddress of usb device.
+
+  @retval EFI_SUCCESS            The usb hub is enumerated successfully.
+  @retval EFI_OUT_OF_RESOURCES   Can't allocate memory resource.
+  @retval Others                 Other failure occurs.
+
+**/
+EFI_STATUS
+PeiHubEnumeration (
+  IN EFI_PEI_SERVICES               **PeiServices,
+  IN PEI_USB_DEVICE                 *PeiUsbDevice,
+  IN UINT8                          *CurrentAddress
+  )
+{
+  UINTN                 Index;
+  EFI_STATUS            Status;
+  PEI_USB_IO_PPI        *UsbIoPpi;
+  EFI_USB_PORT_STATUS   PortStatus;
+  UINTN                 MemPages;
+  EFI_PHYSICAL_ADDRESS  AllocateAddress;
+  PEI_USB_DEVICE        *NewPeiUsbDevice;
+  UINTN                 InterfaceIndex;
+  UINTN                 EndpointIndex;
+
+
+  UsbIoPpi    = &PeiUsbDevice->UsbIoPpi;
+
+  DEBUG ((EFI_D_INFO, "PeiHubEnumeration: DownStreamPortNo: %x\n", PeiUsbDevice->DownStreamPortNo));
+
+  for (Index = 0; Index < PeiUsbDevice->DownStreamPortNo; Index++) {
+
+    Status = PeiHubGetPortStatus (
+              PeiServices,
+              UsbIoPpi,
+              (UINT8) (Index + 1),
+              (UINT32 *) &PortStatus
+              );
+
+    if (EFI_ERROR (Status)) {
+      continue;
+    }
+
+    DEBUG ((EFI_D_INFO, "USB Status --- Port: %x ConnectChange[%04x] Status[%04x]\n", Index, PortStatus.PortChangeStatus, PortStatus.PortStatus));
+    //
+    // Only handle connection/enable/overcurrent/reset change.
+    //
+    if ((PortStatus.PortChangeStatus & (USB_PORT_STAT_C_CONNECTION | USB_PORT_STAT_C_ENABLE | USB_PORT_STAT_C_OVERCURRENT | USB_PORT_STAT_C_RESET)) == 0) {
+      continue;
+    } else {
+      if (IsPortConnect (PortStatus.PortStatus)) {
+        //
+        // Begin to deal with the new device
+        //
+        MemPages = sizeof (PEI_USB_DEVICE) / EFI_PAGE_SIZE + 1;
+        Status = PeiServicesAllocatePages (
+                   EfiBootServicesCode,
+                   MemPages,
+                   &AllocateAddress
+                   );
+        if (EFI_ERROR (Status)) {
+          return EFI_OUT_OF_RESOURCES;
+        }
+
+        NewPeiUsbDevice = (PEI_USB_DEVICE *) ((UINTN) AllocateAddress);
+        ZeroMem (NewPeiUsbDevice, sizeof (PEI_USB_DEVICE));
+
+        NewPeiUsbDevice->Signature        = PEI_USB_DEVICE_SIGNATURE;
+        NewPeiUsbDevice->DeviceAddress    = 0;
+        NewPeiUsbDevice->MaxPacketSize0   = 8;
+        NewPeiUsbDevice->DataToggle       = 0;
+        CopyMem (
+          &(NewPeiUsbDevice->UsbIoPpi),
+          &mUsbIoPpi,
+          sizeof (PEI_USB_IO_PPI)
+          );
+        CopyMem (
+          &(NewPeiUsbDevice->UsbIoPpiList),
+          &mUsbIoPpiList,
+          sizeof (EFI_PEI_PPI_DESCRIPTOR)
+          );
+        NewPeiUsbDevice->UsbIoPpiList.Ppi = &NewPeiUsbDevice->UsbIoPpi;
+        NewPeiUsbDevice->AllocateAddress  = (UINTN) AllocateAddress;
+        NewPeiUsbDevice->UsbHcPpi         = PeiUsbDevice->UsbHcPpi;
+        NewPeiUsbDevice->Usb2HcPpi        = PeiUsbDevice->Usb2HcPpi;
+        NewPeiUsbDevice->Tier             = (UINT8) (PeiUsbDevice->Tier + 1);
+        NewPeiUsbDevice->IsHub            = 0x0;
+        NewPeiUsbDevice->DownStreamPortNo = 0x0;
+
+        if (((PortStatus.PortChangeStatus & USB_PORT_STAT_C_RESET) == 0) ||
+             ((PortStatus.PortStatus & (USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE)) == 0)) {
+          //
+          // If the port already has reset change flag and is connected and enabled, skip the port reset logic.
+          //
+          PeiResetHubPort (PeiServices, UsbIoPpi, (UINT8)(Index + 1));
+
+          PeiHubGetPortStatus (
+             PeiServices,
+             UsbIoPpi,
+             (UINT8) (Index + 1),
+             (UINT32 *) &PortStatus
+             );
+        } else {
+          PeiHubClearPortFeature (
+            PeiServices,
+            UsbIoPpi,
+            (UINT8) (Index + 1),
+            EfiUsbPortResetChange
+            );
+        }
+
+        NewPeiUsbDevice->DeviceSpeed = (UINT8) PeiUsbGetDeviceSpeed (PortStatus.PortStatus);
+        DEBUG ((EFI_D_INFO, "Device Speed =%d\n", PeiUsbDevice->DeviceSpeed));
+
+        if (USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_SUPER_SPEED)){
+          NewPeiUsbDevice->MaxPacketSize0 = 512;
+        } else if (USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_HIGH_SPEED)) {
+          NewPeiUsbDevice->MaxPacketSize0 = 64;
+        } else if (USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_LOW_SPEED)) {
+          NewPeiUsbDevice->MaxPacketSize0 = 8;
+        } else {
+          NewPeiUsbDevice->MaxPacketSize0 = 8;
+        }
+
+        if(NewPeiUsbDevice->DeviceSpeed != EFI_USB_SPEED_HIGH) {
+          if (PeiUsbDevice->DeviceSpeed == EFI_USB_SPEED_HIGH) {
+            NewPeiUsbDevice->Translator.TranslatorPortNumber = (UINT8)Index;
+            NewPeiUsbDevice->Translator.TranslatorHubAddress = *CurrentAddress;
+          } else {
+            CopyMem(&(NewPeiUsbDevice->Translator), &(PeiUsbDevice->Translator), sizeof(EFI_USB2_HC_TRANSACTION_TRANSLATOR));
+          }
+        }
+
+        //
+        // Configure that Usb Device
+        //
+        Status = PeiConfigureUsbDevice (
+                  PeiServices,
+                  NewPeiUsbDevice,
+                  (UINT8) (Index + 1),
+                  CurrentAddress
+                  );
+
+        if (EFI_ERROR (Status)) {
+          continue;
+        }
+        DEBUG ((EFI_D_INFO, "PeiHubEnumeration: PeiConfigureUsbDevice Success\n"));
+
+        Status = PeiServicesInstallPpi (&NewPeiUsbDevice->UsbIoPpiList);
+
+        if (NewPeiUsbDevice->InterfaceDesc->InterfaceClass == 0x09) {
+          NewPeiUsbDevice->IsHub  = 0x1;
+
+          Status = PeiDoHubConfig (PeiServices, NewPeiUsbDevice);
+          if (EFI_ERROR (Status)) {
+            return Status;
+          }
+
+          PeiHubEnumeration (PeiServices, NewPeiUsbDevice, CurrentAddress);
+        }
+
+        for (InterfaceIndex = 1; InterfaceIndex < NewPeiUsbDevice->ConfigDesc->NumInterfaces; InterfaceIndex++) {
+          //
+          // Begin to deal with the new device
+          //
+          MemPages = sizeof (PEI_USB_DEVICE) / EFI_PAGE_SIZE + 1;
+          Status = PeiServicesAllocatePages (
+                     EfiBootServicesCode,
+                     MemPages,
+                     &AllocateAddress
+                     );
+          if (EFI_ERROR (Status)) {
+            return EFI_OUT_OF_RESOURCES;
+          }
+          CopyMem ((VOID *)(UINTN)AllocateAddress, NewPeiUsbDevice, sizeof (PEI_USB_DEVICE));
+          NewPeiUsbDevice = (PEI_USB_DEVICE *) ((UINTN) AllocateAddress);
+          NewPeiUsbDevice->AllocateAddress  = (UINTN) AllocateAddress;
+          NewPeiUsbDevice->UsbIoPpiList.Ppi = &NewPeiUsbDevice->UsbIoPpi;
+          NewPeiUsbDevice->InterfaceDesc = NewPeiUsbDevice->InterfaceDescList[InterfaceIndex];
+          for (EndpointIndex = 0; EndpointIndex < NewPeiUsbDevice->InterfaceDesc->NumEndpoints; EndpointIndex++) {
+            NewPeiUsbDevice->EndpointDesc[EndpointIndex] = NewPeiUsbDevice->EndpointDescList[InterfaceIndex][EndpointIndex];
+          }
+
+          Status = PeiServicesInstallPpi (&NewPeiUsbDevice->UsbIoPpiList);
+
+          if (NewPeiUsbDevice->InterfaceDesc->InterfaceClass == 0x09) {
+            NewPeiUsbDevice->IsHub  = 0x1;
+
+            Status = PeiDoHubConfig (PeiServices, NewPeiUsbDevice);
+            if (EFI_ERROR (Status)) {
+              return Status;
+            }
+
+            PeiHubEnumeration (PeiServices, NewPeiUsbDevice, CurrentAddress);
+          }
+        }
+      }
+    }
+  }
+
+
+  return EFI_SUCCESS;
+}
+
+/**
+  The enumeration routine to detect device change.
+
+  @param  PeiServices            Describes the list of possible PEI Services.
+  @param  UsbHcPpi               The pointer of PEI_USB_HOST_CONTROLLER_PPI instance.
+  @param  Usb2HcPpi              The pointer of PEI_USB2_HOST_CONTROLLER_PPI instance.
+
+  @retval EFI_SUCCESS            The usb is enumerated successfully.
+  @retval EFI_OUT_OF_RESOURCES   Can't allocate memory resource.
+  @retval Others                 Other failure occurs.
+
+**/
+EFI_STATUS
+PeiUsbEnumeration (
+  IN EFI_PEI_SERVICES               **PeiServices,
+  IN PEI_USB_HOST_CONTROLLER_PPI    *UsbHcPpi,
+  IN PEI_USB2_HOST_CONTROLLER_PPI   *Usb2HcPpi
+  )
+{
+  UINT8                 NumOfRootPort;
+  EFI_STATUS            Status;
+  UINT8                 Index;
+  EFI_USB_PORT_STATUS   PortStatus;
+  PEI_USB_DEVICE        *PeiUsbDevice;
+  UINTN                 MemPages;
+  EFI_PHYSICAL_ADDRESS  AllocateAddress;
+  UINT8                 CurrentAddress;
+  UINTN                 InterfaceIndex;
+  UINTN                 EndpointIndex;
+
+  CurrentAddress = 0;
+  if (Usb2HcPpi != NULL) {
+    Usb2HcPpi->GetRootHubPortNumber (
+                PeiServices,
+                Usb2HcPpi,
+                (UINT8 *) &NumOfRootPort
+                );
+  } else if (UsbHcPpi != NULL) {
+    UsbHcPpi->GetRootHubPortNumber (
+                PeiServices,
+                UsbHcPpi,
+                (UINT8 *) &NumOfRootPort
+                );
+  } else {
+    ASSERT (FALSE);
+    return EFI_INVALID_PARAMETER;
+  }
+
+  DEBUG ((EFI_D_INFO, "PeiUsbEnumeration: NumOfRootPort: %x\n", NumOfRootPort));
+
+  for (Index = 0; Index < NumOfRootPort; Index++) {
+    //
+    // First get root port status to detect changes happen
+    //
+    if (Usb2HcPpi != NULL) {
+      Usb2HcPpi->GetRootHubPortStatus (
+                  PeiServices,
+                  Usb2HcPpi,
+                  (UINT8) Index,
+                  &PortStatus
+                  );
+    } else {
+      UsbHcPpi->GetRootHubPortStatus (
+                  PeiServices,
+                  UsbHcPpi,
+                  (UINT8) Index,
+                  &PortStatus
+                  );
+    }
+    DEBUG ((EFI_D_INFO, "USB Status --- Port: %x ConnectChange[%04x] Status[%04x]\n", Index, PortStatus.PortChangeStatus, PortStatus.PortStatus));
+    //
+    // Only handle connection/enable/overcurrent/reset change.
+    //
+    if ((PortStatus.PortChangeStatus & (USB_PORT_STAT_C_CONNECTION | USB_PORT_STAT_C_ENABLE | USB_PORT_STAT_C_OVERCURRENT | USB_PORT_STAT_C_RESET)) == 0) {
+      continue;
+    } else {
+      if (IsPortConnect (PortStatus.PortStatus)) {
+        MemPages = sizeof (PEI_USB_DEVICE) / EFI_PAGE_SIZE + 1;
+        Status = PeiServicesAllocatePages (
+                   EfiBootServicesCode,
+                   MemPages,
+                   &AllocateAddress
+                   );
+        if (EFI_ERROR (Status)) {
+          return EFI_OUT_OF_RESOURCES;
+        }
+
+        PeiUsbDevice = (PEI_USB_DEVICE *) ((UINTN) AllocateAddress);
+        ZeroMem (PeiUsbDevice, sizeof (PEI_USB_DEVICE));
+
+        PeiUsbDevice->Signature         = PEI_USB_DEVICE_SIGNATURE;
+        PeiUsbDevice->DeviceAddress     = 0;
+        PeiUsbDevice->MaxPacketSize0    = 8;
+        PeiUsbDevice->DataToggle        = 0;
+        CopyMem (
+          &(PeiUsbDevice->UsbIoPpi),
+          &mUsbIoPpi,
+          sizeof (PEI_USB_IO_PPI)
+          );
+        CopyMem (
+          &(PeiUsbDevice->UsbIoPpiList),
+          &mUsbIoPpiList,
+          sizeof (EFI_PEI_PPI_DESCRIPTOR)
+          );
+        PeiUsbDevice->UsbIoPpiList.Ppi  = &PeiUsbDevice->UsbIoPpi;
+        PeiUsbDevice->AllocateAddress   = (UINTN) AllocateAddress;
+        PeiUsbDevice->UsbHcPpi          = UsbHcPpi;
+        PeiUsbDevice->Usb2HcPpi         = Usb2HcPpi;
+        PeiUsbDevice->IsHub             = 0x0;
+        PeiUsbDevice->DownStreamPortNo  = 0x0;
+
+        if (((PortStatus.PortChangeStatus & USB_PORT_STAT_C_RESET) == 0) ||
+             ((PortStatus.PortStatus & (USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE)) == 0)) {
+          //
+          // If the port already has reset change flag and is connected and enabled, skip the port reset logic.
+          //
+          ResetRootPort (
+            PeiServices,
+            PeiUsbDevice->UsbHcPpi,
+            PeiUsbDevice->Usb2HcPpi,
+            Index,
+            0
+            );
+
+          if (Usb2HcPpi != NULL) {
+            Usb2HcPpi->GetRootHubPortStatus (
+                         PeiServices,
+                         Usb2HcPpi,
+                         (UINT8) Index,
+                         &PortStatus
+                         );
+          } else {
+            UsbHcPpi->GetRootHubPortStatus (
+                        PeiServices,
+                        UsbHcPpi,
+                        (UINT8) Index,
+                        &PortStatus
+                        );
+          }
+        } else {
+          if (Usb2HcPpi != NULL) {
+            Usb2HcPpi->ClearRootHubPortFeature (
+                        PeiServices,
+                        Usb2HcPpi,
+                        (UINT8) Index,
+                        EfiUsbPortResetChange
+                        );
+          } else {
+            UsbHcPpi->ClearRootHubPortFeature (
+                        PeiServices,
+                        UsbHcPpi,
+                        (UINT8) Index,
+                        EfiUsbPortResetChange
+                        );
+          }
+        }
+
+        PeiUsbDevice->DeviceSpeed = (UINT8) PeiUsbGetDeviceSpeed (PortStatus.PortStatus);
+        DEBUG ((EFI_D_INFO, "Device Speed =%d\n", PeiUsbDevice->DeviceSpeed));
+
+        if (USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_SUPER_SPEED)){
+          PeiUsbDevice->MaxPacketSize0 = 512;
+        } else if (USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_HIGH_SPEED)) {
+          PeiUsbDevice->MaxPacketSize0 = 64;
+        } else if (USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_LOW_SPEED)) {
+          PeiUsbDevice->MaxPacketSize0 = 8;
+        } else {
+          PeiUsbDevice->MaxPacketSize0 = 8;
+        }
+
+        //
+        // Configure that Usb Device
+        //
+        Status = PeiConfigureUsbDevice (
+                  PeiServices,
+                  PeiUsbDevice,
+                  Index,
+                  &CurrentAddress
+                  );
+
+        if (EFI_ERROR (Status)) {
+          continue;
+        }
+        DEBUG ((EFI_D_INFO, "PeiUsbEnumeration: PeiConfigureUsbDevice Success\n"));
+
+        Status = PeiServicesInstallPpi (&PeiUsbDevice->UsbIoPpiList);
+
+        if (PeiUsbDevice->InterfaceDesc->InterfaceClass == 0x09) {
+          PeiUsbDevice->IsHub = 0x1;
+
+          Status = PeiDoHubConfig (PeiServices, PeiUsbDevice);
+          if (EFI_ERROR (Status)) {
+            return Status;
+          }
+
+          PeiHubEnumeration (PeiServices, PeiUsbDevice, &CurrentAddress);
+        }
+
+        for (InterfaceIndex = 1; InterfaceIndex < PeiUsbDevice->ConfigDesc->NumInterfaces; InterfaceIndex++) {
+          //
+          // Begin to deal with the new device
+          //
+          MemPages = sizeof (PEI_USB_DEVICE) / EFI_PAGE_SIZE + 1;
+          Status = PeiServicesAllocatePages (
+                     EfiBootServicesCode,
+                     MemPages,
+                     &AllocateAddress
+                     );
+          if (EFI_ERROR (Status)) {
+            return EFI_OUT_OF_RESOURCES;
+          }
+          CopyMem ((VOID *)(UINTN)AllocateAddress, PeiUsbDevice, sizeof (PEI_USB_DEVICE));
+          PeiUsbDevice = (PEI_USB_DEVICE *) ((UINTN) AllocateAddress);
+          PeiUsbDevice->AllocateAddress  = (UINTN) AllocateAddress;
+          PeiUsbDevice->UsbIoPpiList.Ppi = &PeiUsbDevice->UsbIoPpi;
+          PeiUsbDevice->InterfaceDesc = PeiUsbDevice->InterfaceDescList[InterfaceIndex];
+          for (EndpointIndex = 0; EndpointIndex < PeiUsbDevice->InterfaceDesc->NumEndpoints; EndpointIndex++) {
+            PeiUsbDevice->EndpointDesc[EndpointIndex] = PeiUsbDevice->EndpointDescList[InterfaceIndex][EndpointIndex];
+          }
+
+          Status = PeiServicesInstallPpi (&PeiUsbDevice->UsbIoPpiList);
+
+          if (PeiUsbDevice->InterfaceDesc->InterfaceClass == 0x09) {
+            PeiUsbDevice->IsHub = 0x1;
+
+            Status = PeiDoHubConfig (PeiServices, PeiUsbDevice);
+            if (EFI_ERROR (Status)) {
+              return Status;
+            }
+
+            PeiHubEnumeration (PeiServices, PeiUsbDevice, &CurrentAddress);
+          }
+        }
+      } else {
+        //
+        // Disconnect change happen, currently we don't support
+        //
+      }
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Configure new detected usb device.
+
+  @param  PeiServices            Describes the list of possible PEI Services.
+  @param  PeiUsbDevice           The pointer of PEI_USB_DEVICE instance.
+  @param  Port                   The port to be configured.
+  @param  DeviceAddress          The device address to be configured.
+
+  @retval EFI_SUCCESS            The new detected usb device is configured successfully.
+  @retval EFI_OUT_OF_RESOURCES   Can't allocate memory resource.
+  @retval Others                 Other failure occurs.
+
+**/
+EFI_STATUS
+PeiConfigureUsbDevice (
+  IN EFI_PEI_SERVICES   **PeiServices,
+  IN PEI_USB_DEVICE     *PeiUsbDevice,
+  IN UINT8              Port,
+  IN OUT UINT8          *DeviceAddress
+  )
+{
+  EFI_USB_DEVICE_DESCRIPTOR   DeviceDescriptor;
+  EFI_STATUS                  Status;
+  PEI_USB_IO_PPI              *UsbIoPpi;
+  UINT8                       Retry;
+
+  UsbIoPpi = &PeiUsbDevice->UsbIoPpi;
+  Status   = EFI_SUCCESS;
+  ZeroMem (&DeviceDescriptor, sizeof (EFI_USB_DEVICE_DESCRIPTOR));
+  //
+  // Get USB device descriptor
+  //
+
+  for (Retry = 0; Retry < 3; Retry ++) {
+    Status = PeiUsbGetDescriptor (
+               PeiServices,
+               UsbIoPpi,
+               (USB_DT_DEVICE << 8),
+               0,
+               8,
+               &DeviceDescriptor
+               );
+
+    if (!EFI_ERROR (Status)) {
+      DEBUG ((EFI_D_INFO, "PeiUsbGet Device Descriptor the %d time Success\n", Retry));
+      break;
+    }
+  }
+
+  if (Retry == 3) {
+    DEBUG ((EFI_D_ERROR, "PeiUsbGet Device Descriptor fail: %x %r\n", Retry, Status));
+    return Status;
+  }
+
+  if ((DeviceDescriptor.BcdUSB >= 0x0300) && (DeviceDescriptor.MaxPacketSize0 == 9)) {
+    PeiUsbDevice->MaxPacketSize0 = 1 << 9;
+  } else {
+    PeiUsbDevice->MaxPacketSize0 = DeviceDescriptor.MaxPacketSize0;
+  }
+
+  (*DeviceAddress) ++;
+
+  Status = PeiUsbSetDeviceAddress (
+            PeiServices,
+            UsbIoPpi,
+            *DeviceAddress
+            );
+
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "PeiUsbSetDeviceAddress Failed: %r\n", Status));
+    return Status;
+  }
+  MicroSecondDelay (USB_SET_DEVICE_ADDRESS_STALL);
+
+  PeiUsbDevice->DeviceAddress = *DeviceAddress;
+
+  //
+  // Get whole USB device descriptor
+  //
+  Status = PeiUsbGetDescriptor (
+            PeiServices,
+            UsbIoPpi,
+            (USB_DT_DEVICE << 8),
+            0,
+            (UINT16) sizeof (EFI_USB_DEVICE_DESCRIPTOR),
+            &DeviceDescriptor
+            );
+
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "PeiUsbGetDescriptor First Failed\n"));
+    return Status;
+  }
+
+  //
+  // Get its default configuration and its first interface
+  //
+  Status = PeiUsbGetAllConfiguration (
+            PeiServices,
+            PeiUsbDevice
+            );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+  MicroSecondDelay (USB_GET_CONFIG_DESCRIPTOR_STALL);
+
+  Status = PeiUsbSetConfiguration (
+            PeiServices,
+            UsbIoPpi
+            );
+
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Get all configurations from a detected usb device.
+
+  @param  PeiServices            Describes the list of possible PEI Services.
+  @param  PeiUsbDevice           The pointer of PEI_USB_DEVICE instance.
+
+  @retval EFI_SUCCESS            The new detected usb device is configured successfully.
+  @retval EFI_OUT_OF_RESOURCES   Can't allocate memory resource.
+  @retval Others                 Other failure occurs.
+
+**/
+EFI_STATUS
+PeiUsbGetAllConfiguration (
+  IN EFI_PEI_SERVICES   **PeiServices,
+  IN PEI_USB_DEVICE     *PeiUsbDevice
+  )
+{
+  EFI_STATUS                Status;
+  EFI_USB_CONFIG_DESCRIPTOR *ConfigDesc;
+  PEI_USB_IO_PPI            *UsbIoPpi;
+  UINT16                    ConfigDescLength;
+  UINT8                     *Ptr;
+  UINTN                     SkipBytes;
+  UINTN                     LengthLeft;
+  UINTN                     InterfaceIndex;
+  UINTN                     Index;
+  UINTN                     NumOfEndpoint;
+
+  UsbIoPpi = &PeiUsbDevice->UsbIoPpi;
+
+  //
+  // First get its 4-byte configuration descriptor
+  //
+  Status = PeiUsbGetDescriptor (
+            PeiServices,
+            UsbIoPpi,
+            (USB_DT_CONFIG << 8), // Value
+            0,      // Index
+            4,      // Length
+            PeiUsbDevice->ConfigurationData
+            );
+
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "PeiUsbGet Config Descriptor First Failed\n"));
+    return Status;
+  }
+  MicroSecondDelay (USB_GET_CONFIG_DESCRIPTOR_STALL);
+
+  ConfigDesc        = (EFI_USB_CONFIG_DESCRIPTOR *) PeiUsbDevice->ConfigurationData;
+  ConfigDescLength  = ConfigDesc->TotalLength;
+
+  //
+  // Reject if TotalLength even cannot cover itself.
+  //
+  if (ConfigDescLength < OFFSET_OF (EFI_USB_CONFIG_DESCRIPTOR, TotalLength) + sizeof (ConfigDesc->TotalLength)) {
+    return EFI_DEVICE_ERROR;
+  }
+
+  //
+  // Reject if TotalLength exceeds the PeiUsbDevice->ConfigurationData.
+  //
+  if (ConfigDescLength > sizeof (PeiUsbDevice->ConfigurationData)) {
+    return EFI_DEVICE_ERROR;
+  }
+
+  //
+  // Then we get the total descriptors for this configuration
+  //
+  Status = PeiUsbGetDescriptor (
+            PeiServices,
+            UsbIoPpi,
+            (USB_DT_CONFIG << 8),
+            0,
+            ConfigDescLength,
+            PeiUsbDevice->ConfigurationData
+            );
+
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "PeiUsbGet Config Descriptor all Failed\n"));
+    return Status;
+  }
+  //
+  // Parse this configuration descriptor
+  // First get the current config descriptor;
+  //
+  Status = GetExpectedDescriptor (
+            PeiUsbDevice->ConfigurationData,
+            ConfigDescLength,
+            USB_DT_CONFIG,
+            (UINT8) sizeof (EFI_USB_CONFIG_DESCRIPTOR),
+            &SkipBytes
+            );
+
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Ptr                       = PeiUsbDevice->ConfigurationData + SkipBytes;
+  PeiUsbDevice->ConfigDesc  = (EFI_USB_CONFIG_DESCRIPTOR *) Ptr;
+
+  Ptr += sizeof (EFI_USB_CONFIG_DESCRIPTOR);
+  LengthLeft = ConfigDescLength - SkipBytes - sizeof (EFI_USB_CONFIG_DESCRIPTOR);
+
+  for (InterfaceIndex = 0; InterfaceIndex < PeiUsbDevice->ConfigDesc->NumInterfaces; InterfaceIndex++) {
+
+    //
+    // Get the interface descriptor
+    //
+    Status = GetExpectedDescriptor (
+              Ptr,
+              LengthLeft,
+              USB_DT_INTERFACE,
+              (UINT8) sizeof (EFI_USB_INTERFACE_DESCRIPTOR),
+              &SkipBytes
+              );
+
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+
+    Ptr += SkipBytes;
+    if (InterfaceIndex == 0) {
+      PeiUsbDevice->InterfaceDesc = (EFI_USB_INTERFACE_DESCRIPTOR *) Ptr;
+    }
+    PeiUsbDevice->InterfaceDescList[InterfaceIndex] = (EFI_USB_INTERFACE_DESCRIPTOR *) Ptr;
+
+    Ptr += sizeof (EFI_USB_INTERFACE_DESCRIPTOR);
+    LengthLeft -= SkipBytes;
+    LengthLeft -= sizeof (EFI_USB_INTERFACE_DESCRIPTOR);
+
+    //
+    // Parse all the endpoint descriptor within this interface
+    //
+    NumOfEndpoint = PeiUsbDevice->InterfaceDescList[InterfaceIndex]->NumEndpoints;
+    ASSERT (NumOfEndpoint <= MAX_ENDPOINT);
+
+    for (Index = 0; Index < NumOfEndpoint; Index++) {
+      //
+      // Get the endpoint descriptor
+      //
+      Status = GetExpectedDescriptor (
+                Ptr,
+                LengthLeft,
+                USB_DT_ENDPOINT,
+                (UINT8) sizeof (EFI_USB_ENDPOINT_DESCRIPTOR),
+                &SkipBytes
+                );
+
+      if (EFI_ERROR (Status)) {
+        return Status;
+      }
+
+      Ptr += SkipBytes;
+      if (InterfaceIndex == 0) {
+        PeiUsbDevice->EndpointDesc[Index] = (EFI_USB_ENDPOINT_DESCRIPTOR *) Ptr;
+      }
+      PeiUsbDevice->EndpointDescList[InterfaceIndex][Index] = (EFI_USB_ENDPOINT_DESCRIPTOR *) Ptr;
+
+      Ptr += sizeof (EFI_USB_ENDPOINT_DESCRIPTOR);
+      LengthLeft -= SkipBytes;
+      LengthLeft -= sizeof (EFI_USB_ENDPOINT_DESCRIPTOR);
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Get the start position of next wanted descriptor.
+
+  @param  Buffer            Buffer containing data to parse.
+  @param  Length            Buffer length.
+  @param  DescType          Descriptor type.
+  @param  DescLength        Descriptor length.
+  @param  ParsedBytes       Bytes has been parsed.
+
+  @retval EFI_SUCCESS       Get wanted descriptor successfully.
+  @retval EFI_DEVICE_ERROR  Error occurred.
+
+**/
+EFI_STATUS
+GetExpectedDescriptor (
+  IN  UINT8       *Buffer,
+  IN  UINTN       Length,
+  IN  UINT8       DescType,
+  IN  UINT8       DescLength,
+  OUT UINTN       *ParsedBytes
+  )
+{
+  USB_DESC_HEAD   *Head;
+  UINTN           Offset;
+
+  //
+  // Total length is too small that cannot hold the single descriptor header plus data.
+  //
+  if (Length <= sizeof (USB_DESC_HEAD)) {
+    DEBUG ((DEBUG_ERROR, "GetExpectedDescriptor: met mal-format descriptor, total length = %d!\n", Length));
+    return EFI_DEVICE_ERROR;
+  }
+
+  //
+  // All the descriptor has a common LTV (Length, Type, Value)
+  // format. Skip the descriptor that isn't of this Type
+  //
+  Offset = 0;
+  Head   = (USB_DESC_HEAD *)Buffer;
+  while (Offset < Length - sizeof (USB_DESC_HEAD)) {
+    //
+    // Above condition make sure Head->Len and Head->Type are safe to access
+    //
+    Head = (USB_DESC_HEAD *)&Buffer[Offset];
+
+    if (Head->Len == 0) {
+      DEBUG ((DEBUG_ERROR, "GetExpectedDescriptor: met mal-format descriptor, Head->Len = 0!\n"));
+      return EFI_DEVICE_ERROR;
+    }
+
+    //
+    // Make sure no overflow when adding Head->Len to Offset.
+    //
+    if (Head->Len > MAX_UINTN - Offset) {
+      DEBUG ((DEBUG_ERROR, "GetExpectedDescriptor: met mal-format descriptor, Head->Len = %d!\n", Head->Len));
+      return EFI_DEVICE_ERROR;
+    }
+
+    if (Head->Type == DescType) {
+      break;
+    }
+
+    Offset += Head->Len;
+  }
+
+  //
+  // Head->Len is invalid resulting data beyond boundary, or
+  // Descriptor cannot be found: No such type.
+  //
+  if (Length < Offset) {
+    DEBUG ((DEBUG_ERROR, "GetExpectedDescriptor: met mal-format descriptor, Offset/Len = %d/%d!\n", Offset, Length));
+    return EFI_DEVICE_ERROR;
+  }
+
+  if ((Head->Type != DescType) || (Head->Len < DescLength)) {
+    DEBUG ((DEBUG_ERROR, "GetExpectedDescriptor: descriptor cannot be found, Header(T/L) = %d/%d!\n", Head->Type, Head->Len));
+    return EFI_DEVICE_ERROR;
+  }
+
+  *ParsedBytes = Offset;
+  return EFI_SUCCESS;
+}
+
+/**
+  Send reset signal over the given root hub port.
+
+  @param  PeiServices       Describes the list of possible PEI Services.
+  @param  UsbHcPpi          The pointer of PEI_USB_HOST_CONTROLLER_PPI instance.
+  @param  Usb2HcPpi         The pointer of PEI_USB2_HOST_CONTROLLER_PPI instance.
+  @param  PortNum           The port to be reset.
+  @param  RetryIndex        The retry times.
+
+**/
+VOID
+ResetRootPort (
+  IN EFI_PEI_SERVICES               **PeiServices,
+  IN PEI_USB_HOST_CONTROLLER_PPI    *UsbHcPpi,
+  IN PEI_USB2_HOST_CONTROLLER_PPI   *Usb2HcPpi,
+  IN UINT8                          PortNum,
+  IN UINT8                          RetryIndex
+  )
+{
+  EFI_STATUS             Status;
+  UINTN                  Index;
+  EFI_USB_PORT_STATUS    PortStatus;
+
+
+  if (Usb2HcPpi != NULL) {
+    MicroSecondDelay (200 * 1000);
+
+    //
+    // reset root port
+    //
+    Status = Usb2HcPpi->SetRootHubPortFeature (
+                         PeiServices,
+                         Usb2HcPpi,
+                         PortNum,
+                         EfiUsbPortReset
+                         );
+
+    if (EFI_ERROR (Status)) {
+      DEBUG ((EFI_D_ERROR, "SetRootHubPortFeature EfiUsbPortReset Failed\n"));
+      return;
+    }
+
+    //
+    // Drive the reset signal for at least 50ms. Check USB 2.0 Spec
+    // section 7.1.7.5 for timing requirements.
+    //
+    MicroSecondDelay (USB_SET_ROOT_PORT_RESET_STALL);
+
+    //
+    // clear reset root port
+    //
+    Status = Usb2HcPpi->ClearRootHubPortFeature (
+                         PeiServices,
+                         Usb2HcPpi,
+                         PortNum,
+                         EfiUsbPortReset
+                         );
+
+    if (EFI_ERROR (Status)) {
+      DEBUG ((EFI_D_ERROR, "ClearRootHubPortFeature EfiUsbPortReset Failed\n"));
+      return;
+    }
+
+    MicroSecondDelay (USB_CLR_ROOT_PORT_RESET_STALL);
+
+    //
+    // USB host controller won't clear the RESET bit until
+    // reset is actually finished.
+    //
+    ZeroMem (&PortStatus, sizeof (EFI_USB_PORT_STATUS));
+
+    for (Index = 0; Index < USB_WAIT_PORT_STS_CHANGE_LOOP; Index++) {
+      Status = Usb2HcPpi->GetRootHubPortStatus (
+                            PeiServices,
+                            Usb2HcPpi,
+                            PortNum,
+                            &PortStatus
+                            );
+      if (EFI_ERROR (Status)) {
+        return;
+      }
+
+      if (!USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_RESET)) {
+        break;
+      }
+
+      MicroSecondDelay (USB_WAIT_PORT_STS_CHANGE_STALL);
+    }
+
+    if (Index == USB_WAIT_PORT_STS_CHANGE_LOOP) {
+      DEBUG ((EFI_D_ERROR, "ResetRootPort: reset not finished in time on port %d\n", PortNum));
+      return;
+    }
+
+    Usb2HcPpi->ClearRootHubPortFeature (
+                PeiServices,
+                Usb2HcPpi,
+                PortNum,
+                EfiUsbPortResetChange
+                );
+
+    Usb2HcPpi->ClearRootHubPortFeature (
+                PeiServices,
+                Usb2HcPpi,
+                PortNum,
+                EfiUsbPortConnectChange
+                );
+
+    //
+    // Set port enable
+    //
+    Usb2HcPpi->SetRootHubPortFeature(
+                PeiServices,
+                Usb2HcPpi,
+                PortNum,
+                EfiUsbPortEnable
+                );
+
+    Usb2HcPpi->ClearRootHubPortFeature (
+                PeiServices,
+                Usb2HcPpi,
+                PortNum,
+                EfiUsbPortEnableChange
+                );
+
+    MicroSecondDelay ((RetryIndex + 1) * 50 * 1000);
+  } else {
+    MicroSecondDelay (200 * 1000);
+
+    //
+    // reset root port
+    //
+    Status = UsbHcPpi->SetRootHubPortFeature (
+                         PeiServices,
+                         UsbHcPpi,
+                         PortNum,
+                         EfiUsbPortReset
+                         );
+
+    if (EFI_ERROR (Status)) {
+      DEBUG ((EFI_D_ERROR, "SetRootHubPortFeature EfiUsbPortReset Failed\n"));
+      return;
+    }
+
+    //
+    // Drive the reset signal for at least 50ms. Check USB 2.0 Spec
+    // section 7.1.7.5 for timing requirements.
+    //
+    MicroSecondDelay (USB_SET_ROOT_PORT_RESET_STALL);
+
+    //
+    // clear reset root port
+    //
+    Status = UsbHcPpi->ClearRootHubPortFeature (
+                         PeiServices,
+                         UsbHcPpi,
+                         PortNum,
+                         EfiUsbPortReset
+                         );
+
+    if (EFI_ERROR (Status)) {
+      DEBUG ((EFI_D_ERROR, "ClearRootHubPortFeature EfiUsbPortReset Failed\n"));
+      return;
+    }
+
+    MicroSecondDelay (USB_CLR_ROOT_PORT_RESET_STALL);
+
+    //
+    // USB host controller won't clear the RESET bit until
+    // reset is actually finished.
+    //
+    ZeroMem (&PortStatus, sizeof (EFI_USB_PORT_STATUS));
+
+    for (Index = 0; Index < USB_WAIT_PORT_STS_CHANGE_LOOP; Index++) {
+      Status = UsbHcPpi->GetRootHubPortStatus (
+                           PeiServices,
+                           UsbHcPpi,
+                           PortNum,
+                           &PortStatus
+                           );
+      if (EFI_ERROR (Status)) {
+        return;
+      }
+
+      if (!USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_RESET)) {
+        break;
+      }
+
+      MicroSecondDelay (USB_WAIT_PORT_STS_CHANGE_STALL);
+    }
+
+    if (Index == USB_WAIT_PORT_STS_CHANGE_LOOP) {
+      DEBUG ((EFI_D_ERROR, "ResetRootPort: reset not finished in time on port %d\n", PortNum));
+      return;
+    }
+
+    UsbHcPpi->ClearRootHubPortFeature (
+                PeiServices,
+                UsbHcPpi,
+                PortNum,
+                EfiUsbPortResetChange
+                );
+
+    UsbHcPpi->ClearRootHubPortFeature (
+                PeiServices,
+                UsbHcPpi,
+                PortNum,
+                EfiUsbPortConnectChange
+                );
+
+    //
+    // Set port enable
+    //
+    UsbHcPpi->SetRootHubPortFeature(
+                PeiServices,
+                UsbHcPpi,
+                PortNum,
+                EfiUsbPortEnable
+                );
+
+    UsbHcPpi->ClearRootHubPortFeature (
+                PeiServices,
+                UsbHcPpi,
+                PortNum,
+                EfiUsbPortEnableChange
+                );
+
+    MicroSecondDelay ((RetryIndex + 1) * 50 * 1000);
+  }
+  return;
+}
+
+
diff --git a/roms/edk2/MdeModulePkg/Bus/Usb/UsbBusPei/UsbPeim.h b/roms/edk2/MdeModulePkg/Bus/Usb/UsbBusPei/UsbPeim.h
new file mode 100644
index 000000000..b55b97d87
--- /dev/null
+++ b/roms/edk2/MdeModulePkg/Bus/Usb/UsbBusPei/UsbPeim.h
@@ -0,0 +1,257 @@
+/** @file
+Usb Peim definition.
+
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved. <BR>
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _PEI_USB_PEIM_H_
+#define _PEI_USB_PEIM_H_
+
+
+#include <PiPei.h>
+
+#include <Ppi/UsbHostController.h>
+#include <Ppi/Usb2HostController.h>
+#include <Ppi/UsbIo.h>
+
+#include <Library/DebugLib.h>
+#include <Library/PeimEntryPoint.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/TimerLib.h>
+#include <Library/PcdLib.h>
+
+#include <IndustryStandard/Usb.h>
+
+//
+// A common header for usb standard descriptor.
+// Each stand descriptor has a length and type.
+//
+#pragma pack(1)
+typedef struct {
+  UINT8                   Len;
+  UINT8                   Type;
+} USB_DESC_HEAD;
+#pragma pack()
+
+#define MAX_INTERFACE             8
+#define MAX_ENDPOINT              16
+
+#define PEI_USB_DEVICE_SIGNATURE  SIGNATURE_32 ('U', 's', 'b', 'D')
+typedef struct {
+  UINTN                         Signature;
+  PEI_USB_IO_PPI                UsbIoPpi;
+  EFI_PEI_PPI_DESCRIPTOR        UsbIoPpiList;
+  UINT16                        MaxPacketSize0;
+  UINT16                        DataToggle;
+  UINT8                         DeviceAddress;
+  UINT8                         DeviceSpeed;
+  UINT8                         IsHub;
+  UINT8                         DownStreamPortNo;
+  UINTN                         AllocateAddress;
+  PEI_USB_HOST_CONTROLLER_PPI   *UsbHcPpi;
+  PEI_USB2_HOST_CONTROLLER_PPI  *Usb2HcPpi;
+  UINT8                         ConfigurationData[1024];
+  EFI_USB_CONFIG_DESCRIPTOR     *ConfigDesc;
+  EFI_USB_INTERFACE_DESCRIPTOR  *InterfaceDesc;
+  EFI_USB_INTERFACE_DESCRIPTOR  *InterfaceDescList[MAX_INTERFACE];
+  EFI_USB_ENDPOINT_DESCRIPTOR   *EndpointDesc[MAX_ENDPOINT];
+  EFI_USB_ENDPOINT_DESCRIPTOR   *EndpointDescList[MAX_INTERFACE][MAX_ENDPOINT];
+  EFI_USB2_HC_TRANSACTION_TRANSLATOR Translator;
+  UINT8                          Tier;
+} PEI_USB_DEVICE;
+
+#define PEI_USB_DEVICE_FROM_THIS(a) CR (a, PEI_USB_DEVICE, UsbIoPpi, PEI_USB_DEVICE_SIGNATURE)
+
+#define USB_BIT_IS_SET(Data, Bit)   ((BOOLEAN)(((Data) & (Bit)) == (Bit)))
+
+#define USB_BUS_1_MILLISECOND       1000
+
+//
+// Wait for port reset, refers to specification
+// [USB20-7.1.7.5, it says 10ms for hub and 50ms for
+// root hub]
+//
+// According to USB2.0, Chapter 11.5.1.5 Resetting,
+// the worst case for TDRST is 20ms
+//
+#define USB_SET_PORT_RESET_STALL        (20 * USB_BUS_1_MILLISECOND)
+#define USB_SET_ROOT_PORT_RESET_STALL   (50 * USB_BUS_1_MILLISECOND)
+
+//
+// Wait for clear roothub port reset, set by experience
+//
+#define USB_CLR_ROOT_PORT_RESET_STALL   (20 * USB_BUS_1_MILLISECOND)
+
+//
+// Wait for port statue reg change, set by experience
+//
+#define USB_WAIT_PORT_STS_CHANGE_STALL  (100)
+
+//
+// Host software return timeout if port status doesn't change
+// after 500ms(LOOP * STALL = 5000 * 0.1ms), set by experience
+//
+#define USB_WAIT_PORT_STS_CHANGE_LOOP   5000
+
+//
+// Wait for hub port power-on, refers to specification
+// [USB20-11.23.2]
+//
+#define USB_SET_PORT_POWER_STALL        (2 * USB_BUS_1_MILLISECOND)
+
+//
+// Wait for set device address, refers to specification
+// [USB20-9.2.6.3, it says 2ms]
+//
+#define USB_SET_DEVICE_ADDRESS_STALL    (2 * USB_BUS_1_MILLISECOND)
+
+//
+// Wait for get configuration descriptor, set by experience
+//
+#define USB_GET_CONFIG_DESCRIPTOR_STALL (1 * USB_BUS_1_MILLISECOND)
+
+/**
+  Submits control transfer to a target USB device.
+
+  @param  PeiServices            The pointer of EFI_PEI_SERVICES.
+  @param  This                   The pointer of PEI_USB_IO_PPI.
+  @param  Request                USB device request to send.
+  @param  Direction              Specifies the data direction for the data stage.
+  @param  Timeout                Indicates the maximum timeout, in millisecond. If Timeout
+                                 is 0, then the caller must wait for the function to be
+                                 completed until EFI_SUCCESS or EFI_DEVICE_ERROR is returned.
+  @param  Data                   Data buffer to be transmitted or received from USB device.
+  @param  DataLength             The size (in bytes) of the data buffer.
+
+  @retval EFI_SUCCESS            Transfer was completed successfully.
+  @retval EFI_OUT_OF_RESOURCES   The transfer failed due to lack of resources.
+  @retval EFI_INVALID_PARAMETER  Some parameters are invalid.
+  @retval EFI_TIMEOUT            Transfer failed due to timeout.
+  @retval EFI_DEVICE_ERROR       Transfer failed due to host controller or device error.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiUsbControlTransfer (
+  IN     EFI_PEI_SERVICES          **PeiServices,
+  IN     PEI_USB_IO_PPI            *This,
+  IN     EFI_USB_DEVICE_REQUEST    *Request,
+  IN     EFI_USB_DATA_DIRECTION    Direction,
+  IN     UINT32                    Timeout,
+  IN OUT VOID                      *Data,      OPTIONAL
+  IN     UINTN                     DataLength  OPTIONAL
+  );
+
+/**
+  Submits bulk transfer to a bulk endpoint of a USB device.
+
+  @param  PeiServices           The pointer of EFI_PEI_SERVICES.
+  @param  This                  The pointer of PEI_USB_IO_PPI.
+  @param  DeviceEndpoint        Endpoint number and its direction in bit 7.
+  @param  Data                  A pointer to the buffer of data to transmit
+                                from or receive into.
+  @param  DataLength            The length of the data buffer.
+  @param  Timeout               Indicates the maximum time, in millisecond, which the
+                                transfer is allowed to complete. If Timeout is 0, then
+                                the caller must wait for the function to be completed
+                                until EFI_SUCCESS or EFI_DEVICE_ERROR is returned.
+
+  @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 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
+PeiUsbBulkTransfer (
+  IN     EFI_PEI_SERVICES    **PeiServices,
+  IN     PEI_USB_IO_PPI      *This,
+  IN     UINT8               DeviceEndpoint,
+  IN OUT VOID                *Data,
+  IN OUT UINTN               *DataLength,
+  IN     UINTN               Timeout
+  );
+
+/**
+  Get the usb interface descriptor.
+
+  @param  PeiServices          General-purpose services that are available to every PEIM.
+  @param  This                 Indicates the PEI_USB_IO_PPI instance.
+  @param  InterfaceDescriptor  Request interface descriptor.
+
+
+  @retval EFI_SUCCESS          Usb interface descriptor is obtained successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiUsbGetInterfaceDescriptor (
+  IN  EFI_PEI_SERVICES                **PeiServices,
+  IN  PEI_USB_IO_PPI                  *This,
+  OUT EFI_USB_INTERFACE_DESCRIPTOR    **InterfaceDescriptor
+  );
+
+/**
+  Get the usb endpoint descriptor.
+
+  @param  PeiServices          General-purpose services that are available to every PEIM.
+  @param  This                 Indicates the PEI_USB_IO_PPI instance.
+  @param  EndpointIndex        The valid index of the specified endpoint.
+  @param  EndpointDescriptor   Request endpoint descriptor.
+
+  @retval EFI_SUCCESS       Usb endpoint descriptor is obtained successfully.
+  @retval EFI_NOT_FOUND     Usb endpoint descriptor is NOT found.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiUsbGetEndpointDescriptor (
+  IN  EFI_PEI_SERVICES               **PeiServices,
+  IN  PEI_USB_IO_PPI                 *This,
+  IN  UINT8                          EndpointIndex,
+  OUT EFI_USB_ENDPOINT_DESCRIPTOR    **EndpointDescriptor
+  );
+
+/**
+  Reset the port and re-configure the usb device.
+
+  @param  PeiServices    General-purpose services that are available to every PEIM.
+  @param  This           Indicates the PEI_USB_IO_PPI instance.
+
+  @retval EFI_SUCCESS    Usb device is reset and configured successfully.
+  @retval Others         Other failure occurs.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiUsbPortReset (
+  IN EFI_PEI_SERVICES    **PeiServices,
+  IN PEI_USB_IO_PPI      *This
+  );
+
+/**
+  Send reset signal over the given root hub port.
+
+  @param  PeiServices       Describes the list of possible PEI Services.
+  @param  UsbHcPpi          The pointer of PEI_USB_HOST_CONTROLLER_PPI instance.
+  @param  Usb2HcPpi         The pointer of PEI_USB2_HOST_CONTROLLER_PPI instance.
+  @param  PortNum           The port to be reset.
+  @param  RetryIndex        The retry times.
+
+**/
+VOID
+ResetRootPort (
+  IN EFI_PEI_SERVICES               **PeiServices,
+  IN PEI_USB_HOST_CONTROLLER_PPI    *UsbHcPpi,
+  IN PEI_USB2_HOST_CONTROLLER_PPI   *Usb2HcPpi,
+  IN UINT8                          PortNum,
+  IN UINT8                          RetryIndex
+  );
+
+#endif
-- 
cgit