13cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei/** @file
23cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  BDS Lib functions which relate with connect the device
33cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
43cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiCopyright (c) 2004 - 2013, Intel Corporation. All rights reserved.<BR>
53cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiThis program and the accompanying materials
63cbfba02fef9dae07a041fdbf2e89611d72d6f90David Weiare licensed and made available under the terms and conditions of the BSD License
73cbfba02fef9dae07a041fdbf2e89611d72d6f90David Weiwhich accompanies this distribution.  The full text of the license may be found at
83cbfba02fef9dae07a041fdbf2e89611d72d6f90David Weihttp://opensource.org/licenses/bsd-license.php
93cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
103cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiTHE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
113cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiWITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
123cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
133cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei**/
143cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
153cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei#include "InternalBdsLib.h"
163cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
173cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
183cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei/**
193cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  This function will connect all the system driver to controller
203cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  first, and then special connect the default console, this make
213cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  sure all the system controller available and the platform default
223cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  console connected.
233cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
243cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei**/
253cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiVOID
263cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiEFIAPI
273cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiBdsLibConnectAll (
283cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  VOID
293cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  )
303cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei{
313cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
323cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  // Connect the platform console first
333cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
343cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  BdsLibConnectAllDefaultConsoles ();
353cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
363cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
373cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  // Generic way to connect all the drivers
383cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
393cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  BdsLibConnectAllDriversToAllControllers ();
403cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
413cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
423cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  // Here we have the assumption that we have already had
433cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  // platform default console
443cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
453cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  BdsLibConnectAllDefaultConsoles ();
463cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei}
473cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
483cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
493cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei/**
503cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  This function will connect all the system drivers to all controllers
513cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  first, and then connect all the console devices the system current
523cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  have. After this we should get all the device work and console available
533cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  if the system have console device.
543cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
553cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei**/
563cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiVOID
573cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiBdsLibGenericConnectAll (
583cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  VOID
593cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  )
603cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei{
613cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
623cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  // Most generic way to connect all the drivers
633cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
643cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  BdsLibConnectAllDriversToAllControllers ();
653cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  BdsLibConnectAllConsoles ();
663cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei}
673cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
683cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei/**
693cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  This function will create all handles associate with every device
703cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  path node. If the handle associate with one device path node can not
713cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  be created successfully, then still give chance to do the dispatch,
723cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  which load the missing drivers if possible.
733cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
743cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param  DevicePathToConnect   The device path which will be connected, it can be
753cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                                a multi-instance device path
763cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
773cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval EFI_SUCCESS           All handles associate with every device path  node
783cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                                have been created
793cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval EFI_OUT_OF_RESOURCES  There is no resource to create new handles
803cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval EFI_NOT_FOUND         Create the handle associate with one device  path
813cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                                node failed
823cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
833cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei**/
843cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiEFI_STATUS
853cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiEFIAPI
863cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiBdsLibConnectDevicePath (
873cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN EFI_DEVICE_PATH_PROTOCOL  *DevicePathToConnect
883cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  )
893cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei{
903cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_STATUS                Status;
913cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
923cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_DEVICE_PATH_PROTOCOL  *CopyOfDevicePath;
933cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_DEVICE_PATH_PROTOCOL  *Instance;
943cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_DEVICE_PATH_PROTOCOL  *RemainingDevicePath;
953cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_DEVICE_PATH_PROTOCOL  *Next;
963cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_HANDLE                Handle;
973cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_HANDLE                PreviousHandle;
983cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  UINTN                     Size;
993cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_TPL                   CurrentTpl;
1003cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
1013cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  if (DevicePathToConnect == NULL) {
1023cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    return EFI_SUCCESS;
1033cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
1043cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
1053cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  CurrentTpl  = EfiGetCurrentTpl ();
1063cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
1073cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  DevicePath        = DuplicateDevicePath (DevicePathToConnect);
1083cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  if (DevicePath == NULL) {
1093cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    return EFI_OUT_OF_RESOURCES;
1103cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
1113cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  CopyOfDevicePath  = DevicePath;
1123cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
1133cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  do {
1143cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    //
1153cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    // The outer loop handles multi instance device paths.
1163cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    // Only console variables contain multiple instance device paths.
1173cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    //
1183cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    // After this call DevicePath points to the next Instance
1193cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    //
1203cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    Instance  = GetNextDevicePathInstance (&DevicePath, &Size);
1213cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    if (Instance == NULL) {
1223cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      FreePool (CopyOfDevicePath);
1233cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      return EFI_OUT_OF_RESOURCES;
1243cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    }
1253cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
1263cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    Next      = Instance;
1273cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    while (!IsDevicePathEndType (Next)) {
1283cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      Next = NextDevicePathNode (Next);
1293cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    }
1303cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
1313cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    SetDevicePathEndNode (Next);
1323cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
1333cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    //
1343cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    // Start the real work of connect with RemainingDevicePath
1353cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    //
1363cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    PreviousHandle = NULL;
1373cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    do {
1383cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      //
1393cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      // Find the handle that best matches the Device Path. If it is only a
1403cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      // partial match the remaining part of the device path is returned in
1413cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      // RemainingDevicePath.
1423cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      //
1433cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      RemainingDevicePath = Instance;
1443cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      Status              = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &RemainingDevicePath, &Handle);
1453cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
1463cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      if (!EFI_ERROR (Status)) {
1473cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei        if (Handle == PreviousHandle) {
1483cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei          //
1493cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei          // If no forward progress is made try invoking the Dispatcher.
1503cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei          // A new FV may have been added to the system an new drivers
1513cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei          // may now be found.
1523cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei          // Status == EFI_SUCCESS means a driver was dispatched
1533cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei          // Status == EFI_NOT_FOUND means no new drivers were dispatched
1543cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei          //
1553cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei          if (CurrentTpl == TPL_APPLICATION) {
1563cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei            //
1573cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei            // Dispatch calls LoadImage/StartImage which cannot run at TPL > TPL_APPLICATION
1583cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei            //
1593cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei            Status = gDS->Dispatch ();
1603cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei          } else {
1613cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei            //
1623cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei            // Always return EFI_NOT_FOUND here
1633cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei            // to prevent dead loop when control handle is found but connection failded case
1643cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei            //
1653cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei            Status = EFI_NOT_FOUND;
1663cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei          }
1673cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei        }
1683cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
1693cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei        if (!EFI_ERROR (Status)) {
1703cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei          PreviousHandle = Handle;
1713cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei          //
1723cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei          // Connect all drivers that apply to Handle and RemainingDevicePath,
1733cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei          // the Recursive flag is FALSE so only one level will be expanded.
1743cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei          //
1753cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei          // Do not check the connect status here, if the connect controller fail,
1763cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei          // then still give the chance to do dispatch, because partial
1773cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei          // RemainingDevicepath may be in the new FV
1783cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei          //
1793cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei          // 1. If the connect fail, RemainingDevicepath and handle will not
1803cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei          //    change, so next time will do the dispatch, then dispatch's status
1813cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei          //    will take effect
1823cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei          // 2. If the connect success, the RemainingDevicepath and handle will
1833cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei          //    change, then avoid the dispatch, we have chance to continue the
1843cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei          //    next connection
1853cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei          //
1863cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei          gBS->ConnectController (Handle, NULL, RemainingDevicePath, FALSE);
1873cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei        }
1883cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      }
1893cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      //
1903cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      // Loop until RemainingDevicePath is an empty device path
1913cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      //
1923cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    } while (!EFI_ERROR (Status) && !IsDevicePathEnd (RemainingDevicePath));
1933cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
1943cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  } while (DevicePath != NULL);
1953cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
1963cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  if (CopyOfDevicePath != NULL) {
1973cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    FreePool (CopyOfDevicePath);
1983cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
1993cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
2003cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  // All handle with DevicePath exists in the handle database
2013cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
2023cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  return Status;
2033cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei}
2043cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
2053cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei/**
2063cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  This function will connect all current system handles recursively.
2073cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
2083cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  gBS->ConnectController() service is invoked for each handle exist in system handler buffer.
2093cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  If the handle is bus type handler, all childrens also will be connected recursively
2103cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  by gBS->ConnectController().
2113cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
2123cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval EFI_SUCCESS           All handles and it's child handle have been connected
2133cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval EFI_STATUS            Error status returned by of gBS->LocateHandleBuffer().
2143cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
2153cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei**/
2163cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiEFI_STATUS
2173cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiEFIAPI
2183cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiBdsLibConnectAllEfi (
2193cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  VOID
2203cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  )
2213cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei{
2223cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_STATUS  Status;
2233cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  UINTN       HandleCount;
2243cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_HANDLE  *HandleBuffer;
2253cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  UINTN       Index;
2263cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
2273cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Status = gBS->LocateHandleBuffer (
2283cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                  AllHandles,
2293cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                  NULL,
2303cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                  NULL,
2313cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                  &HandleCount,
2323cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                  &HandleBuffer
2333cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                  );
2343cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  if (EFI_ERROR (Status)) {
2353cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    return Status;
2363cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
2373cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
2383cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  for (Index = 0; Index < HandleCount; Index++) {
2393cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    Status = gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE);
2403cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
2413cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
2423cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  if (HandleBuffer != NULL) {
2433cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    FreePool (HandleBuffer);
2443cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
2453cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
2463cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  return EFI_SUCCESS;
2473cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei}
2483cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
2493cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei/**
2503cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  This function will disconnect all current system handles.
2513cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
2523cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  gBS->DisconnectController() is invoked for each handle exists in system handle buffer.
2533cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  If handle is a bus type handle, all childrens also are disconnected recursively by
2543cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  gBS->DisconnectController().
2553cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
2563cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval EFI_SUCCESS           All handles have been disconnected
2573cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @retval EFI_STATUS            Error status returned by of gBS->LocateHandleBuffer().
2583cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
2593cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei**/
2603cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiEFI_STATUS
2613cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiEFIAPI
2623cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiBdsLibDisconnectAllEfi (
2633cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  VOID
2643cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  )
2653cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei{
2663cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_STATUS  Status;
2673cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  UINTN       HandleCount;
2683cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_HANDLE  *HandleBuffer;
2693cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  UINTN       Index;
2703cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
2713cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
2723cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  // Disconnect all
2733cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
2743cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Status = gBS->LocateHandleBuffer (
2753cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                  AllHandles,
2763cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                  NULL,
2773cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                  NULL,
2783cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                  &HandleCount,
2793cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                  &HandleBuffer
2803cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                  );
2813cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  if (EFI_ERROR (Status)) {
2823cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    return Status;
2833cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
2843cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
2853cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  for (Index = 0; Index < HandleCount; Index++) {
2863cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    Status = gBS->DisconnectController (HandleBuffer[Index], NULL, NULL);
2873cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
2883cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
2893cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  if (HandleBuffer != NULL) {
2903cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    FreePool (HandleBuffer);
2913cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
2923cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
2933cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  return EFI_SUCCESS;
2943cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei}
2953cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
2963cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
2973cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei/**
2983cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Connects all drivers to all controllers.
2993cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  This function make sure all the current system driver will manage
3003cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  the correspoinding controllers if have. And at the same time, make
3013cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  sure all the system controllers have driver to manage it if have.
3023cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
3033cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei**/
3043cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiVOID
3053cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiEFIAPI
3063cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiBdsLibConnectAllDriversToAllControllers (
3073cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  VOID
3083cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  )
3093cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei{
3103cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_STATUS  Status;
3113cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
3123cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  do {
3133cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    //
3143cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    // Connect All EFI 1.10 drivers following EFI 1.10 algorithm
3153cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    //
3163cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    BdsLibConnectAllEfi ();
3173cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
3183cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    //
3193cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    // Check to see if it's possible to dispatch an more DXE drivers.
3203cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    // The BdsLibConnectAllEfi () may have made new DXE drivers show up.
3213cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    // If anything is Dispatched Status == EFI_SUCCESS and we will try
3223cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    // the connect again.
3233cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    //
3243cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    Status = gDS->Dispatch ();
3253cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
3263cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  } while (!EFI_ERROR (Status));
3273cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
3283cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei}
3293cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
3303cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
3313cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei/**
3323cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Connect the specific Usb device which match the short form device path,
3333cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  and whose bus is determined by Host Controller (Uhci or Ehci).
3343cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
3353cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param  HostControllerPI      Uhci (0x00) or Ehci (0x20) or Both uhci and ehci
3363cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                                (0xFF)
3373cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @param  RemainingDevicePath   a short-form device path that starts with the first
3383cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                                element  being a USB WWID or a USB Class device
3393cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                                path
3403cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
3413cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @return EFI_INVALID_PARAMETER  RemainingDevicePath is NULL pointer.
3423cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                                 RemainingDevicePath is not a USB device path.
3433cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                                 Invalid HostControllerPI type.
3443cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @return EFI_SUCCESS            Success to connect USB device
3453cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  @return EFI_NOT_FOUND          Fail to find handle for USB controller to connect.
3463cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
3473cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei**/
3483cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiEFI_STATUS
3493cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiEFIAPI
3503cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiBdsLibConnectUsbDevByShortFormDP(
3513cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN UINT8                      HostControllerPI,
3523cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN EFI_DEVICE_PATH_PROTOCOL   *RemainingDevicePath
3533cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  )
3543cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei{
3553cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_STATUS                            Status;
3563cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_HANDLE                            *HandleArray;
3573cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  UINTN                                 HandleArrayCount;
3583cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  UINTN                                 Index;
3593cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_PCI_IO_PROTOCOL                   *PciIo;
3603cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  UINT8                                 Class[3];
3613cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  BOOLEAN                               AtLeastOneConnected;
3623cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
3633cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
3643cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  // Check the passed in parameters
3653cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
3663cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  if (RemainingDevicePath == NULL) {
3673cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    return EFI_INVALID_PARAMETER;
3683cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
3693cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
3703cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  if ((DevicePathType (RemainingDevicePath) != MESSAGING_DEVICE_PATH) ||
3713cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      ((DevicePathSubType (RemainingDevicePath) != MSG_USB_CLASS_DP)
3723cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      && (DevicePathSubType (RemainingDevicePath) != MSG_USB_WWID_DP)
3733cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      )) {
3743cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    return EFI_INVALID_PARAMETER;
3753cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
3763cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
3773cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  if (HostControllerPI != 0xFF &&
3783cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      HostControllerPI != 0x00 &&
3793cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      HostControllerPI != 0x20) {
3803cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    return EFI_INVALID_PARAMETER;
3813cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
3823cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
3833cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
3843cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  // Find the usb host controller firstly, then connect with the remaining device path
3853cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
3863cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  AtLeastOneConnected = FALSE;
3873cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Status = gBS->LocateHandleBuffer (
3883cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                  ByProtocol,
3893cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                  &gEfiPciIoProtocolGuid,
3903cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                  NULL,
3913cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                  &HandleArrayCount,
3923cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                  &HandleArray
3933cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                  );
3943cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  if (!EFI_ERROR (Status)) {
3953cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    for (Index = 0; Index < HandleArrayCount; Index++) {
3963cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      Status = gBS->HandleProtocol (
3973cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                      HandleArray[Index],
3983cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                      &gEfiPciIoProtocolGuid,
3993cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                      (VOID **)&PciIo
4003cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                      );
4013cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      if (!EFI_ERROR (Status)) {
4023cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei        //
4033cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei        // Check whether the Pci device is the wanted usb host controller
4043cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei        //
4053cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei        Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x09, 3, &Class);
4063cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei        if (!EFI_ERROR (Status)) {
4073cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei          if ((PCI_CLASS_SERIAL == Class[2]) &&
4083cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei              (PCI_CLASS_SERIAL_USB == Class[1])) {
4093cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei            if (HostControllerPI == Class[0] || HostControllerPI == 0xFF) {
4103cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei              Status = gBS->ConnectController (
4113cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                              HandleArray[Index],
4123cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                              NULL,
4133cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                              RemainingDevicePath,
4143cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                              FALSE
4153cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                              );
4163cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei              if (!EFI_ERROR(Status)) {
4173cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                AtLeastOneConnected = TRUE;
4183cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei              }
4193cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei            }
4203cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei          }
4213cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei        }
4223cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      }
4233cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    }
4243cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
4253cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    if (HandleArray != NULL) {
4263cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      FreePool (HandleArray);
4273cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    }
4283cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
4293cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    if (AtLeastOneConnected) {
4303cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      return EFI_SUCCESS;
4313cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    }
4323cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
4333cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
4343cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  return EFI_NOT_FOUND;
4353cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei}
436