diff options
Diffstat (limited to 'roms/edk2/MdeModulePkg/Bus/Usb/UsbBusPei')
-rw-r--r-- | roms/edk2/MdeModulePkg/Bus/Usb/UsbBusPei/HubPeim.c | 586 | ||||
-rw-r--r-- | roms/edk2/MdeModulePkg/Bus/Usb/UsbBusPei/HubPeim.h | 258 | ||||
-rw-r--r-- | roms/edk2/MdeModulePkg/Bus/Usb/UsbBusPei/PeiUsbLib.c | 185 | ||||
-rw-r--r-- | roms/edk2/MdeModulePkg/Bus/Usb/UsbBusPei/PeiUsbLib.h | 189 | ||||
-rw-r--r-- | roms/edk2/MdeModulePkg/Bus/Usb/UsbBusPei/UsbBusPei.inf | 60 | ||||
-rw-r--r-- | roms/edk2/MdeModulePkg/Bus/Usb/UsbBusPei/UsbBusPei.uni | 16 | ||||
-rw-r--r-- | roms/edk2/MdeModulePkg/Bus/Usb/UsbBusPei/UsbBusPeiExtra.uni | 14 | ||||
-rw-r--r-- | roms/edk2/MdeModulePkg/Bus/Usb/UsbBusPei/UsbIoPeim.c | 365 | ||||
-rw-r--r-- | roms/edk2/MdeModulePkg/Bus/Usb/UsbBusPei/UsbPeim.c | 1243 | ||||
-rw-r--r-- | roms/edk2/MdeModulePkg/Bus/Usb/UsbBusPei/UsbPeim.h | 257 |
10 files changed, 3173 insertions, 0 deletions
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
|