summaryrefslogtreecommitdiff
path: root/Core/EM/UsbRecovery/UsbPeimSrc/UsbPeim.c
diff options
context:
space:
mode:
Diffstat (limited to 'Core/EM/UsbRecovery/UsbPeimSrc/UsbPeim.c')
-rw-r--r--Core/EM/UsbRecovery/UsbPeimSrc/UsbPeim.c1006
1 files changed, 1006 insertions, 0 deletions
diff --git a/Core/EM/UsbRecovery/UsbPeimSrc/UsbPeim.c b/Core/EM/UsbRecovery/UsbPeimSrc/UsbPeim.c
new file mode 100644
index 0000000..87afc78
--- /dev/null
+++ b/Core/EM/UsbRecovery/UsbPeimSrc/UsbPeim.c
@@ -0,0 +1,1006 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2008, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+//**********************************************************************
+//
+// $Header: /Alaska/SOURCE/Modules/USBRecovery/UsbPeimSrc/UsbPeim.c 17 11/24/12 5:46a Ryanchou $
+//
+// $Revision: 17 $
+//
+// $Date: 11/24/12 5:46a $
+//
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/USBRecovery/UsbPeimSrc/UsbPeim.c $
+//
+// 17 11/24/12 5:46a Ryanchou
+// [TAG] EIP103990
+// [Category] Improvement
+// [Description] Synchronized with USB PEI module 4.6.3_USB_08.10.24.
+// [Files] EhciPei.c, EhciPei.h, OhciPei.c, OhciPei.h, UhcPeim.c,
+// BotPeim.c, BotPeim.h, PeiAtapi.c, UsbBotPeim.c, UsbBotPeim.h,
+// HubPeim.c, UsbPeim.c, XhciPei.c, XhciPei.h, HubPeim.h, PeiUsbLib.c,
+// PeiUsbLib.h, UsbPeim.h
+//
+// 16 8/23/12 10:01p Wilsonlee
+// [TAG] EIP97069
+// [Category] Improvement
+// [Description] Reset root port algorythm update.
+// [Files] EhciPei.c, EhciPei.h, OhciPei.c, OhciPei.h, UhcPeim.c,
+// UhcPeim.h, UsbPeim.c, usb.h
+//
+// 15 1/18/11 1:06a Ryanchou
+// [TAG] EIP47931
+// [Category] Improvement
+// [Description] Added USB 3.0 hub support.
+// [Files] EhciPei.c, EhciPei.h, HubPeim.c, HubPeim.h, OhciPei.c,
+// OhciPei.h, UhcPeim.c, UhcPeim.h, usb.h, UsbHostController.h,
+// UsbIoPeim.c, UsbPeim.c, UsbPeim.h, XhciPei.c, XhciPei.h
+//
+// 14 10/22/10 2:55a Rameshr
+// [TAG]- EIP 43687
+// [Category]-IMPROVEMENT
+// [Description]- Build warning from UsbRecovery driver -
+// UsbHostController.obj : warning LNK4221: no public symbols found;
+// archive member will be inaccessible.
+// [Files]- uhcpeim.c, usbpeim.c, UsbHostcontroller.h
+//
+// 13 10/12/10 11:20a Olegi
+// XHCI support added.
+//
+// 12 1/06/10 11:23a Olegi
+// Fix for EIP32503: The Interface descriptor of some devices is not
+// directly after the configuration descriptor, and the first Endpoint
+// descriptor is not directly after the Interface either. Changed the
+// descriptior data parser.
+//
+// 11 10/20/09 9:17a Olegi
+// EIP#28255: Set proper TransactionTranslator field for a non-hispeed USB
+// device.
+//
+// 10 3/17/09 5:07p Olegi
+// Added TransactionTranslator for slow/full speed devices behind USB2
+// hub.
+//
+// 9 10/21/08 5:57p Michaela
+// Added EHCI-related fixes for issues
+// that may occur if EHCI is used before
+// USB Recovery is invoked:
+// Added SDL Tokens:
+// PEI_EHCI_PCI_BDFS and
+// PEI_EHCI_MEM_BASE_ADDRESSES.
+//
+// Removed/modified some debugging
+// development code:
+// Removed SDL Tokens:
+// USBR_DEBUG_SUPPORT and
+// USBR_SERIAL_PORT_AVAILABLE
+// Removed Elinks:
+// UsbRecoveryDebug_DIR and
+// $(BUILD_DIR)\UsbRecoveryDebugDxe.ffs
+// Modified SDL Token:
+// FORCE_RECOVERY to default value of 0.
+//
+// (See this module's Help documentation
+// for more information.)
+//
+// 8 7/29/08 5:52p Michaela
+// 1) Updated code to move most porting tasks to SDL
+// 2) Added more debug break points and improved interactive
+// debugging capability for when a serial port is not available.
+// 3) Updated help files
+//
+// 7 7/18/08 5:05p Michaela
+// 1 File-level debugging is now available
+// 2 AMI_USB_DEBUG_INTERFACE.WaitConsoleKey() now returns
+// the keypress so that conditional debugging can
+// be dynamic (alphanumeric keys only)
+// 3 Added more function headers.
+// 4 Removed code that will never be used (I.e., Bala?).
+// 5 Moved typedef, contants and extern declarations
+// into header files.
+// 6 Now all controller blocks are enabled for SB700
+// (EHCI controllers route to companion controller
+// by default)
+// 7 Removed unused constants and typedefs n OhciPei.h
+// (also reorganized the file to make it more
+// readable.)
+// 8 Renamed many functions/variables according to
+// coding standard.
+// 9 Removed code initializing data structures for
+// periodic lists, as this is not needed.
+// 10 Removed the CONTROLLER_TYPE SDL token to
+// allow UHCI and OHCI controllers to supported
+// simultaneously. (modified MAKE files
+// accordingly)
+//
+// 6 7/10/08 6:37p Michaela
+// Updated to support OHCI controllers
+//
+// 5 10/23/07 5:41p Ambikas
+//
+// 4 8/17/07 4:13p Ambikas
+//
+// 3 4/16/07 12:55p Sivagarn
+// - Updated as per coding standard review
+// - In previous check-in, TIANO.H file is removed and AMIMAPPING.H file
+// is included
+//
+// 2 3/28/07 3:36a Meenakshim
+//
+// 1 9/22/06 12:19p Sivagarn
+// - Initial Checkin
+// - Included Recovery code in Source
+//
+//*****************************************************************************
+
+//<AMI_FHDR_START>
+//----------------------------------------------------------------------------
+//
+// Name: UsbPeim.C
+//
+// Description: This file belongs to "Framework".
+// This file is modified by AMI to include copyright message,
+// appropriate header and integration code.
+// This file contains generic routines needed for USB recovery
+// PEIM
+//
+//----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+/*++
+ This file contains 'Framework Code' and is licensed as such
+ under the terms of your license agreement with Intel or your
+ vendor. This file may not be modified, except as allowed by
+ additional terms of your license agreement.
+ --*/
+
+/*++
+
+ Copyright (c) 1999 - 2002 Intel Corporation. All rights reserved
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+
+
+ Module Name:
+
+ UsbPeim.c
+
+ Abstract:
+
+ Usb Bus PPI
+
+ --*/
+
+#include "UsbPeim.h"
+#include "HubPeim.h"
+#include "PeiUsbLib.h"
+
+
+#include EFI_PPI_DEFINITION (Stall)
+#include EFI_PPI_DEFINITION (LoadFile)
+
+EFI_GUID gPeiUsbIoPpiGuid = PEI_USB_IO_PPI_GUID;
+
+extern EFI_GUID gPeiStallPpiGuid;
+
+
+#define PAGESIZE 4096
+
+//static BOOLEAN mImageInMemory = FALSE;
+
+
+//
+// Driver Entry Point
+//
+
+
+EFI_STATUS
+PeimInitializeUsb (
+ IN EFI_FFS_FILE_HEADER *FfsHeader,
+ IN EFI_PEI_SERVICES **PeiServices );
+
+//
+// UsbIo PPI interface function
+//
+STATIC PEI_USB_IO_PPI mUsbIoPpi = {
+ PeiUsbControlTransfer,
+ PeiUsbBulkTransfer,
+ PeiUsbGetInterfaceDescriptor,
+ PeiUsbGetEndpointDescriptor,
+ PeiUsbPortReset
+};
+
+STATIC EFI_PEI_PPI_DESCRIPTOR mUsbIoPpiList = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gPeiUsbIoPpiGuid,
+ NULL
+};
+
+//
+// Helper functions
+//
+STATIC
+EFI_STATUS
+PeiUsbEnumeration (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *UsbHcPpi );
+
+STATIC
+EFI_STATUS
+PeiConfigureUsbDevice (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_DEVICE *PeiUsbDevice,
+ IN UINT8 Port,
+ IN OUT UINT8 *DeviceAddress );
+
+STATIC
+EFI_STATUS
+PeiUsbGetAllConfiguration (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_DEVICE *PeiUsbDevice );
+
+
+VOID
+ResetRootPort (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *UsbHcPpi,
+ UINT8 PortNum );
+
+extern VOID ZeroMem (
+ IN VOID *Buffer,
+ IN UINTN Size );
+
+
+
+//
+// PEIM Entry Point
+//
+// EFI_PEIM_ENTRY_POINT (PeimInitializeUsb);
+
+EFI_STATUS PeimInitializeUsb (
+ IN EFI_FFS_FILE_HEADER *FfsHeader,
+ IN EFI_PEI_SERVICES **PeiServices )
+{
+ EFI_STATUS Status;
+ UINTN i;
+ PEI_USB_HOST_CONTROLLER_PPI *UsbHcPpi;
+
+ // Assign resources and enable UHCI controllers
+ //
+ // when the image is in flash, the global variable
+ // mImageInMemory could not be modified;
+ // when the image is successfully loaded into memory,
+ // mImageInMemory could be modified to TRUE.
+ //
+
+ i = 0;
+ while (TRUE) {
+ //
+ // Get UsbHcPpi at first.
+ //
+ Status = (**PeiServices).LocatePpi( PeiServices,
+ &gPeiUsbHostControllerPpiGuid, i, NULL, &UsbHcPpi );
+
+ if ( EFI_ERROR( Status ) ) {
+ break;
+ }
+
+ PeiUsbEnumeration( PeiServices, UsbHcPpi ); // 0xff06
+ i++;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+STATIC
+EFI_STATUS PeiHubEnumeration (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_DEVICE *PeiUsbDevice,
+ IN UINT8 *CurrentAddress )
+//
+// Since we are not going to support hot-plug, we will do a
+// dedicated polling process to get all ports change event
+// discovered. This can help to avoid introduce interrupt
+// transfer into the system, for each hub, we will wait for
+// 3s and if one port is enabled we will not wait for others
+// We will start parsing each of them in sequence.
+//
+{
+ UINTN Delay;
+ UINT8 Port;
+ EFI_STATUS Status;
+ PEI_USB_IO_PPI *UsbIoPpi;
+ EFI_USB_PORT_STATUS PortStatus;
+ BOOLEAN PortChanged;
+ UINT8 *AllocateAddress;
+ PEI_USB_DEVICE *NewPeiUsbDevice;
+ PEI_STALL_PPI *StallPpi;
+
+
+ PortChanged = FALSE;
+
+ UsbIoPpi = &PeiUsbDevice->UsbIoPpi;
+ Status = (**PeiServices).LocatePpi( PeiServices, &gPeiStallPpiGuid,
+ 0, NULL, &StallPpi );
+
+ Delay = (HUB_TIME_OUT * STALL_1_MILLI_SECOND / 50000) + 1;
+
+ //
+ // Do while will do a 3s scan for the USB HUB for a connected
+ // device. If we have found one, the waiting process will be
+ // breaked since we assue other ports will be discovered at
+ // the same time.
+ //
+ do {
+ for (Port = 1; Port <= PeiUsbDevice->DownStreamPortNo; Port++) {
+
+ Status = PeiHubGetPortStatus( PeiServices, UsbIoPpi,
+ Port, (UINT32 *) &PortStatus );
+
+ if ( EFI_ERROR( Status ) ) {
+ continue;
+ }
+
+ if ( IsPortConnectChange( PortStatus.PortChangeStatus ) ) {
+ PortChanged = TRUE;
+ PeiHubClearPortFeature( PeiServices, UsbIoPpi,
+ Port, EfiUsbPortConnectChange );
+
+ if ( IsPortConnect( PortStatus.PortStatus ) ) {
+
+ if (IsPortEnable(PortStatus.PortStatus) == FALSE) {
+ //
+ // First reset and enable this port
+ //
+ PeiResetHubPort( PeiServices, UsbIoPpi, Port );
+
+ PeiHubGetPortStatus( PeiServices, UsbIoPpi,
+ Port, (UINT32 *) &PortStatus );
+ }
+
+ //
+ // Begin to deal with the new device
+ //
+ Status = (*PeiServices)->AllocatePool( PeiServices,
+ sizeof(PEI_USB_DEVICE), &AllocateAddress );
+ if ( EFI_ERROR( Status ) ) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ NewPeiUsbDevice = (PEI_USB_DEVICE *)AllocateAddress;
+
+ ZeroMem( NewPeiUsbDevice, sizeof(PEI_USB_DEVICE) );
+
+ NewPeiUsbDevice->Signature =
+ PEI_USB_DEVICE_SIGNATURE;
+ NewPeiUsbDevice->DeviceAddress = 0;
+ NewPeiUsbDevice->MaxPacketSize0 = 8;
+ NewPeiUsbDevice->DataToggle = 0;
+ NewPeiUsbDevice->UsbIoPpi = mUsbIoPpi;
+ NewPeiUsbDevice->UsbIoPpiList = mUsbIoPpiList;
+ NewPeiUsbDevice->UsbIoPpiList.Ppi =
+ &NewPeiUsbDevice->UsbIoPpi;
+ NewPeiUsbDevice->UsbHcPpi =
+ PeiUsbDevice->UsbHcPpi;
+ NewPeiUsbDevice->DeviceSpeed =
+ USB_FULL_SPEED_DEVICE;
+ NewPeiUsbDevice->IsHub = 0x0;
+ NewPeiUsbDevice->DownStreamPortNo = 0x0;
+ NewPeiUsbDevice->TransactionTranslator =
+ (UINT16)(Port << 7) + PeiUsbDevice->DeviceAddress;
+ NewPeiUsbDevice->HubDepth = 0x0;
+ //(EIP28255+)>
+ if ( (PeiUsbDevice->DeviceSpeed == USB_SLOW_SPEED_DEVICE) ||
+ (PeiUsbDevice->DeviceSpeed == USB_FULL_SPEED_DEVICE) )
+ {
+ NewPeiUsbDevice->TransactionTranslator = PeiUsbDevice->TransactionTranslator;
+ }
+ //<(EIP28255+)
+ if ( IsPortLowSpeedDeviceAttached( PortStatus.PortStatus ) )
+ {
+ NewPeiUsbDevice->DeviceSpeed = USB_SLOW_SPEED_DEVICE;
+ }
+
+ if ( IsPortHighSpeedDeviceAttached( PortStatus.PortStatus ) )
+ {
+ NewPeiUsbDevice->DeviceSpeed = USB_HIGH_SPEED_DEVICE;
+ }
+
+ if ( IsPortSuperSpeedDeviceAttached( PortStatus.PortStatus ) )
+ {
+ NewPeiUsbDevice->DeviceSpeed = USB_SUPER_SPEED_DEVICE;
+ }
+
+ //
+ // Configure that Usb Device
+ //
+ Status = PeiConfigureUsbDevice( PeiServices,
+ NewPeiUsbDevice, Port, CurrentAddress );
+
+ if ( EFI_ERROR( Status ) ) {
+ PeiHubClearPortFeature( PeiServices, UsbIoPpi,
+ Port, EfiUsbPortEnable );
+ continue;
+ }
+
+ Status = (**PeiServices).InstallPpi( PeiServices,
+ &NewPeiUsbDevice->UsbIoPpiList );
+
+ if (NewPeiUsbDevice->InterfaceDesc->InterfaceClass
+ == BASE_CLASS_HUB)
+ {
+ NewPeiUsbDevice->IsHub = 0x1;
+ NewPeiUsbDevice->HubDepth = PeiUsbDevice->HubDepth + 1;
+
+ Status = PeiDoHubConfig( PeiServices,
+ NewPeiUsbDevice );
+ if ( EFI_ERROR( Status ) ) {
+ return Status;
+ }
+ PeiHubEnumeration( PeiServices, NewPeiUsbDevice,
+ CurrentAddress );
+ }
+ }
+
+ }
+ }
+
+ if (PortChanged) {
+ break;
+ }
+ StallPpi->Stall( PeiServices, StallPpi, 50000 );
+
+ } while (Delay--);
+
+ return EFI_SUCCESS;
+}
+
+
+STATIC
+EFI_STATUS PeiUsbEnumeration (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *UsbHcPpi )
+{
+ UINT8 NumOfRootPort;
+ EFI_STATUS Status;
+ UINT8 Port;
+ EFI_USB_PORT_STATUS PortStatus;
+ PEI_USB_DEVICE *PeiUsbDevice;
+ UINT8 *AllocateAddress;
+ UINT8 CurrentAddress;
+ PEI_STALL_PPI *PeiStall;
+
+ (**PeiServices).LocatePpi(
+ PeiServices,
+ &gPeiStallPpiGuid,
+ 0,
+ NULL,
+ &PeiStall
+ );
+
+ CurrentAddress = 0;
+ UsbHcPpi->GetRootHubPortNumber(
+ PeiServices,
+ UsbHcPpi,
+ (UINT8 *) &NumOfRootPort
+ );
+
+
+ for (Port = 1; Port <= NumOfRootPort; Port++) {
+ //
+ // First get root port status to detect changes happen
+ //
+ UsbHcPpi->GetRootHubPortStatus(
+ PeiServices,
+ UsbHcPpi,
+ Port,
+ &PortStatus
+ );
+
+ if ( IsPortConnectChange( PortStatus.PortChangeStatus ) ) {
+
+ //
+ // Changes happen, first clear this change status
+ //
+ UsbHcPpi->ClearRootHubPortFeature(
+ PeiServices,
+ UsbHcPpi,
+ Port,
+ EfiUsbPortConnectChange
+ );
+
+ if ( IsPortConnect( PortStatus.PortStatus ) ) {
+
+ if (IsPortEnable(PortStatus.PortStatus) == FALSE) {
+ //
+ // First reset and enable this port
+ //
+ ResetRootPort( PeiServices, UsbHcPpi, Port );
+
+ UsbHcPpi->GetRootHubPortStatus(
+ PeiServices,
+ UsbHcPpi,
+ Port,
+ &PortStatus
+ );
+ }
+
+ //
+ // Connect change happen
+ //
+ Status = (*PeiServices)->AllocatePool(
+ PeiServices,
+ sizeof(PEI_USB_DEVICE),
+ &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;
+ PeiUsbDevice->UsbIoPpi = mUsbIoPpi;
+ PeiUsbDevice->UsbIoPpiList = mUsbIoPpiList;
+ PeiUsbDevice->UsbIoPpiList.Ppi = &PeiUsbDevice->UsbIoPpi;
+ PeiUsbDevice->UsbHcPpi = UsbHcPpi;
+ PeiUsbDevice->DeviceSpeed = USB_FULL_SPEED_DEVICE;
+ PeiUsbDevice->IsHub = 0x0;
+ PeiUsbDevice->DownStreamPortNo = 0x0;
+ PeiUsbDevice->TransactionTranslator = 0x0;
+ PeiUsbDevice->HubDepth = 0x0;
+
+ if ( IsPortLowSpeedDeviceAttached( PortStatus.PortStatus ) )
+ {
+ PeiUsbDevice->DeviceSpeed = USB_SLOW_SPEED_DEVICE;
+ }
+
+ if ( IsPortHighSpeedDeviceAttached( PortStatus.PortStatus ) )
+ {
+ PeiUsbDevice->DeviceSpeed = USB_HIGH_SPEED_DEVICE;
+ }
+
+ if ( IsPortSuperSpeedDeviceAttached( PortStatus.PortStatus ) )
+ {
+ PeiUsbDevice->DeviceSpeed = USB_SUPER_SPEED_DEVICE;
+ }
+
+ //
+ // Delay some times to enable usb devices to initiate.
+ //
+ PeiStall->Stall(
+ PeiServices,
+ PeiStall,
+ 5000
+ );
+
+ //
+ // Configure that Usb Device
+ //
+ Status = PeiConfigureUsbDevice(
+ PeiServices,
+ PeiUsbDevice,
+ Port,
+ &CurrentAddress
+ );
+
+ if ( EFI_ERROR( Status ) ) {
+ UsbHcPpi->ClearRootHubPortFeature(
+ PeiServices,
+ UsbHcPpi,
+ Port,
+ EfiUsbPortEnable
+ );
+ continue;
+ }
+
+ Status = (**PeiServices).InstallPpi(
+ PeiServices,
+ &PeiUsbDevice->UsbIoPpiList
+ );
+
+ if (PeiUsbDevice->InterfaceDesc->InterfaceClass
+ == BASE_CLASS_HUB)
+ {
+ PeiUsbDevice->IsHub = 0x1;
+
+ Status = PeiDoHubConfig( PeiServices, PeiUsbDevice );
+ if ( EFI_ERROR( Status ) ) {
+ return Status;
+ }
+
+ PeiHubEnumeration( PeiServices, PeiUsbDevice,
+ &CurrentAddress );
+ }
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+STATIC 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 i;
+ PEI_STALL_PPI *StallPpi = NULL;
+ UINT8 Retry = 2;
+
+ ( **PeiServices ).LocatePpi( PeiServices, &gPeiStallPpiGuid,
+ 0, NULL, &StallPpi );
+
+ if (PeiUsbDevice->UsbHcPpi->PreConfigureDevice != NULL) {
+ Status = PeiUsbDevice->UsbHcPpi->PreConfigureDevice( PeiServices,
+ PeiUsbDevice->UsbHcPpi, Port, PeiUsbDevice->DeviceSpeed,
+ PeiUsbDevice->TransactionTranslator);
+ if ( EFI_ERROR( Status ) ) {
+ return Status;
+ }
+ }
+
+ UsbIoPpi = &PeiUsbDevice->UsbIoPpi;
+
+ //-----------------------------------------------------------------------
+ // Try 5 times to read the first 8 bytes to determine the size
+ for (i = 0; i < 5; i++) {
+ Status = PeiUsbGetDescriptor( PeiServices,
+ UsbIoPpi,
+ SET_DESCRIPTOR_TYPE( USB_DT_DEVICE ), // Value = Type << 8 | Index
+ 0, // Index
+ 8, // DescriptorLength
+ &DeviceDescriptor );
+ if ( !EFI_ERROR( Status ) ) {
+ break;
+ }
+ StallPpi->Stall( PeiServices, StallPpi, 100 * 1000 ); // 100msec delay
+ }
+ if ( EFI_ERROR( Status ) ) {
+ return Status;
+ }
+
+ //-----------------------------------------------------------------------
+ // Set MaxPacketSize0 = 0x40 if packet size is not specified
+ PeiUsbDevice->MaxPacketSize0 = (DeviceDescriptor.MaxPacketSize0)
+ ? DeviceDescriptor.MaxPacketSize0
+ : 0x40;
+
+
+ //-----------------------------------------------------------------------
+ // Get the entire USB device descriptor
+ StallPpi->Stall( PeiServices, StallPpi, 10 * 1000 ); // 10msec delay
+ Status = PeiUsbGetDescriptor(
+ PeiServices,
+ UsbIoPpi,
+ SET_DESCRIPTOR_TYPE( USB_DT_DEVICE ), // Value = Type << 8 | Index
+ 0, // Index
+ sizeof(EFI_USB_DEVICE_DESCRIPTOR), // DescriptorLength
+ &DeviceDescriptor );
+
+ if ( EFI_ERROR( Status ) ) {
+ return Status;
+ }
+
+ //-----------------------------------------------------------------------
+ // Get its default configuration and its first interface
+ StallPpi->Stall( PeiServices, StallPpi, 10 * 1000 ); // 10msec delay
+ Status = PeiUsbGetAllConfiguration(
+ PeiServices,
+ PeiUsbDevice );
+ if ( EFI_ERROR( Status ) ) {
+ return Status;
+ }
+
+ //-----------------------------------------------------------------------
+ // Set the device's address
+ StallPpi->Stall( PeiServices, StallPpi, 10 * 1000 ); // 10msec delay
+ (*DeviceAddress)++;
+ Status = PeiUsbSetDeviceAddress(
+ PeiServices,
+ UsbIoPpi,
+ *DeviceAddress );
+ if ( EFI_ERROR( Status ) ) {
+ return Status;
+ }
+ PeiUsbDevice->DeviceAddress = *DeviceAddress;
+
+
+ StallPpi->Stall( PeiServices, StallPpi, 200 * 1000 ); // 200msec delay
+
+ Status = PeiUsbSetConfiguration(
+ PeiServices,
+ UsbIoPpi );
+
+ if ( EFI_ERROR( Status ) ) {
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+STATIC EFI_STATUS PeiUsbGetAllConfiguration (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_DEVICE *Device )
+{
+ EFI_USB_CONFIG_DESCRIPTOR ConfigDesc = {0};
+ EFI_USB_ENDPOINT_DESCRIPTOR *EndPointDesc = NULL; //(EIP32503+)
+ EFI_STATUS Status;
+ PEI_USB_IO_PPI *UsbIoPpi = &Device->UsbIoPpi;
+ UINTN i;
+ UINT8 *LastAddress = 0;
+
+
+ // Here we are parsing the descriptors for the device
+ // configurations where the hierarchy of descriptors
+ // is as follows:
+ //
+ // +----------------+
+ // | Configuration1 |
+ // +----------------+
+ // | +------------+
+ // +---------| Interface1 |----+------------------+
+ // | +------------+ | |
+ // | +-----------+ +-------------+
+ // | | Endpoint1 | ... | EndpointMax |
+ // | +-----------+ +-------------+
+ // | :
+ // | :
+ // | :
+ // |
+ // | +--------------+
+ // +---------| InterfaceMax |----+------------------+
+ // +--------------+ | |
+ // : +-----------+ +-------------+
+ // : | Endpoint1 | ... | EndpointMax |
+ // +-----------+ +-------------+
+ // +------------------+
+ // | ConfigurationMax |
+ // +------------------+
+ // | +------------+
+ // +---------| Interface1 |----+------------------+
+ // | +------------+ | |
+ // | +-----------+ +-------------+
+ // | | Endpoint1 | ... | EndpointMax |
+ // | +-----------+ +-------------+
+ // | :
+ // | :
+ // | :
+ // | +--------------+
+ // +---------| InterfaceMax |----+------------------+
+ // +--------------+ | |
+ // +-----------+ +-------------+
+ // | Endpoint1 | ... | EndpointMax |
+ // +-----------+ +-------------+
+
+
+ //-------------------------------------------------------------
+ // Fortunately, we are only interested in the first/default
+ // configuration and its first/default interface, so life is
+ // simple!
+ //-------------------------------------------------------------
+
+ //-------------------------------------------------------------
+ // First get the device's 9-byte configuration descriptor to
+ // determine the length of all descriptors
+ Status = PeiUsbGetDescriptor(
+ PeiServices,
+ UsbIoPpi,
+ USB_DT_CONFIG << 8,
+ 0,
+ 9,
+ &ConfigDesc );
+ if ( EFI_ERROR( Status ) ) {
+ return Status;
+ }
+
+ Status = (*PeiServices)->AllocatePool( PeiServices,
+ ConfigDesc.TotalLength, &Device->ConfigurationData );
+ if ( EFI_ERROR( Status ) ) {
+ return Status;
+ }
+ //-------------------------------------------------------------
+ // Get all the descriptors for this configuration using
+ // TotalLength from the first 9 bytes previously read.
+ // Then, save the Configuration descriptor into the
+ // device management structure.
+ Status = PeiUsbGetDescriptor(
+ PeiServices,
+ UsbIoPpi,
+ USB_DT_CONFIG << 8,
+ 0,
+ ConfigDesc.TotalLength,
+ (VOID *) Device->ConfigurationData );
+ if ( EFI_ERROR( Status ) ) {
+ return Status;
+ }
+ Device->ConfigDesc =
+ (EFI_USB_CONFIG_DESCRIPTOR *) Device->ConfigurationData;
+
+ LastAddress = Device->ConfigurationData +
+ Device->ConfigDesc->TotalLength - 1;
+
+ if (Device->UsbHcPpi->EnableEndpoints != NULL) {
+ Status = Device->UsbHcPpi->EnableEndpoints(PeiServices,
+ Device->UsbHcPpi, Device->ConfigurationData);
+
+ if ( EFI_ERROR( Status ) ) {
+ return Status;
+ }
+ }
+
+ //--------------------------------------------------------------
+ // Assume the Interface descriptor is directly after the
+ // configuration descriptor.
+ //--------------------------------------------------------------
+ Device->InterfaceDesc = (EFI_USB_INTERFACE_DESCRIPTOR *)
+ ( (UINT8 *) Device->ConfigDesc +
+ Device->ConfigDesc->Length );
+ //(EIP32503+)>
+ while ((UINT8 *)Device->InterfaceDesc < LastAddress &&
+ Device->InterfaceDesc->DescriptorType != USB_DT_INTERFACE)
+ {
+ Device->InterfaceDesc = (EFI_USB_INTERFACE_DESCRIPTOR *)
+ ( (UINT8 *) Device->InterfaceDesc +
+ Device->InterfaceDesc->Length );
+ }
+ //<(EIP32503+)
+ //--------------------------------------------------------------
+ // Assume the first Endpoint descriptor is directly after the
+ // Interface descriptor.
+ //--------------------------------------------------------------
+ //(EIP32503)>
+ EndPointDesc = (EFI_USB_ENDPOINT_DESCRIPTOR *)
+ ( (UINT8 *) Device->InterfaceDesc +
+ Device->InterfaceDesc->Length );
+
+ for (i = 0; i < Device->InterfaceDesc->NumEndpoints &&
+ (UINT8 *)EndPointDesc < LastAddress; )
+ {
+ if(EndPointDesc->DescriptorType == USB_DT_ENDPOINT)
+ {
+ Device->EndpointDesc[i++] = EndPointDesc;
+ }
+ EndPointDesc = (EFI_USB_ENDPOINT_DESCRIPTOR *)
+ ( (UINT8 *) EndPointDesc +
+ EndPointDesc->Length );
+ }
+ //<(EIP32503)
+ return EFI_SUCCESS;
+}
+
+
+//
+// Send reset signal over the given root hub port
+//
+VOID ResetRootPort (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_USB_HOST_CONTROLLER_PPI *UsbHcPpi,
+ UINT8 PortNum )
+{
+ EFI_PEI_STALL_PPI *PeiStall;
+ EFI_USB_PORT_STATUS PortStatus;
+ UINT8 i;
+
+ ( **PeiServices ).LocatePpi(
+ PeiServices,
+ &gPeiStallPpiGuid,
+ 0,
+ NULL,
+ &PeiStall
+ );
+
+
+ //
+ // reset root port
+ //
+ UsbHcPpi->SetRootHubPortFeature(
+ PeiServices,
+ UsbHcPpi,
+ PortNum,
+ EfiUsbPortReset
+ );
+
+ for (i = 0; i < 100; i++) {
+ UsbHcPpi->GetRootHubPortStatus(
+ PeiServices,
+ UsbHcPpi,
+ PortNum,
+ &PortStatus
+ );
+
+ if ((PortStatus.PortChangeStatus & USB_PORT_STAT_C_RESET) != 0) {
+ break;
+ }
+
+ PeiStall->Stall(
+ PeiServices,
+ PeiStall,
+ 1 * 1000 // NVS - Changed to 10 msec (as per AMI USB Code)
+ );
+ }
+
+ if ((PortStatus.PortChangeStatus & USB_PORT_STAT_C_RESET) == 0) {
+ return;
+ }
+
+ //
+ // clear reset root port
+ //
+ UsbHcPpi->ClearRootHubPortFeature(
+ PeiServices,
+ UsbHcPpi,
+ PortNum,
+ EfiUsbPortResetChange
+ );
+
+
+ UsbHcPpi->GetRootHubPortStatus(
+ PeiServices,
+ UsbHcPpi,
+ PortNum,
+ &PortStatus
+ );
+
+ if ((PortStatus.PortChangeStatus & USB_PORT_STAT_ENABLE) == 0) {
+ //
+ // Set port enable
+ //
+ UsbHcPpi->SetRootHubPortFeature(
+ PeiServices,
+ UsbHcPpi,
+ PortNum,
+ EfiUsbPortEnable
+ );
+ PeiStall->Stall(
+ PeiServices,
+ PeiStall,
+ 100 * 1000 // NVS - Changed to 100msec as per AMI USB code
+ );
+ }
+
+ return;
+}
+
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2008, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//********************************************************************** \ No newline at end of file