]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Library/GenericBdsLib/BdsConnect.c
Clean up BDS lib to remove assembly files, remove R8Lib.h & R8Lib.c by applying Mde...
[mirror_edk2.git] / MdeModulePkg / Library / GenericBdsLib / BdsConnect.c
index 6e9068b053c9840465ee0b09154d82fca7c9c504..50675429c36ecc2fa011863f8cf97dd0621ff434 100644 (file)
-/** @file
-
-Copyright (c) 2004 - 2007, Intel Corporation
-All rights reserved. This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution.  The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-Module Name:
-
-  BdsConnect.c
-
-Abstract:
-
-  BDS Lib functions which relate with connect the device
-
-
-**/
-
-#include "InternalBdsLib.h"
-
-
-/**
-  This function will connect all the system driver to controller
-  first, and then special connect the default console, this make
-  sure all the system controller avialbe and the platform default
-  console connected.
-
-  None
-
-  @return None
-
-**/
-VOID
-BdsLibConnectAll (
-  VOID
-  )
-{
-  //
-  // Connect the platform console first
-  //
-  BdsLibConnectAllDefaultConsoles ();
-
-  //
-  // Generic way to connect all the drivers
-  //
-  BdsLibConnectAllDriversToAllControllers ();
-
-  //
-  // Here we have the assumption that we have already had
-  // platform default console
-  //
-  BdsLibConnectAllDefaultConsoles ();
-}
-
-
-/**
-  This function will connect all the system drivers to all controllers
-  first, and then connect all the console devices the system current
-  have. After this we should get all the device work and console avariable
-  if the system have console device.
-
-  None
-
-  @return None
-
-**/
-VOID
-BdsLibGenericConnectAll (
-  VOID
-  )
-{
-  //
-  // Most generic way to connect all the drivers
-  //
-  BdsLibConnectAllDriversToAllControllers ();
-  BdsLibConnectAllConsoles ();
-}
-
-
-/**
-  This function will create all handles associate with every device
-  path node. If the handle associate with one device path node can not
-  be created success, then still give one chance to do the dispatch,
-  which load the missing drivers if possible.
-
-  @param  DevicePathToConnect   The device path which will be connected, it can be
-                                a multi-instance device path
-
-  @retval EFI_SUCCESS           All handles associate with every device path  node
-                                have been created
-  @retval EFI_OUT_OF_RESOURCES  There is no resource to create new handles
-  @retval EFI_NOT_FOUND         Create the handle associate with one device  path
-                                node failed
-
-**/
-EFI_STATUS
-BdsLibConnectDevicePath (
-  IN EFI_DEVICE_PATH_PROTOCOL  *DevicePathToConnect
-  )
-{
-  EFI_STATUS                Status;
-  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
-  EFI_DEVICE_PATH_PROTOCOL  *CopyOfDevicePath;
-  EFI_DEVICE_PATH_PROTOCOL  *Instance;
-  EFI_DEVICE_PATH_PROTOCOL  *RemainingDevicePath;
-  EFI_DEVICE_PATH_PROTOCOL  *Next;
-  EFI_HANDLE                Handle;
-  EFI_HANDLE                PreviousHandle;
-  UINTN                     Size;
-
-  if (DevicePathToConnect == NULL) {
-    return EFI_SUCCESS;
-  }
-
-  DevicePath        = DuplicateDevicePath (DevicePathToConnect);
-  CopyOfDevicePath  = DevicePath;
-  if (DevicePath == NULL) {
-    return EFI_OUT_OF_RESOURCES;
-  }
-
-  do {
-    //
-    // The outer loop handles multi instance device paths.
-    // Only console variables contain multiple instance device paths.
-    //
-    // After this call DevicePath points to the next Instance
-    //
-    Instance  = GetNextDevicePathInstance (&DevicePath, &Size);
-    Next      = Instance;
-    while (!IsDevicePathEndType (Next)) {
-      Next = NextDevicePathNode (Next);
-    }
-
-    SetDevicePathEndNode (Next);
-
-    //
-    // Start the real work of connect with RemainingDevicePath
-    //
-    PreviousHandle = NULL;
-    do {
-      //
-      // Find the handle that best matches the Device Path. If it is only a
-      // partial match the remaining part of the device path is returned in
-      // RemainingDevicePath.
-      //
-      RemainingDevicePath = Instance;
-      Status              = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &RemainingDevicePath, &Handle);
-
-      if (!EFI_ERROR (Status)) {
-        if (Handle == PreviousHandle) {
-          //
-          // If no forward progress is made try invoking the Dispatcher.
-          // A new FV may have been added to the system an new drivers
-          // may now be found.
-          // Status == EFI_SUCCESS means a driver was dispatched
-          // Status == EFI_NOT_FOUND means no new drivers were dispatched
-          //
-          Status = gDS->Dispatch ();
-        }
-
-        if (!EFI_ERROR (Status)) {
-          PreviousHandle = Handle;
-          //
-          // Connect all drivers that apply to Handle and RemainingDevicePath,
-          // the Recursive flag is FALSE so only one level will be expanded.
-          //
-          // Do not check the connect status here, if the connect controller fail,
-          // then still give the chance to do dispatch, because partial
-          // RemainingDevicepath may be in the new FV
-          //
-          // 1. If the connect fail, RemainingDevicepath and handle will not
-          //    change, so next time will do the dispatch, then dispatch's status
-          //    will take effect
-          // 2. If the connect success, the RemainingDevicepath and handle will
-          //    change, then avoid the dispatch, we have chance to continue the
-          //    next connection
-          //
-          gBS->ConnectController (Handle, NULL, RemainingDevicePath, FALSE);
-        }
-      }
-      //
-      // Loop until RemainingDevicePath is an empty device path
-      //
-    } while (!EFI_ERROR (Status) && !IsDevicePathEnd (RemainingDevicePath));
-
-  } while (DevicePath != NULL);
-
-  if (CopyOfDevicePath != NULL) {
-    gBS->FreePool (CopyOfDevicePath);
-  }
-  //
-  // All handle with DevicePath exists in the handle database
-  //
-  return Status;
-}
-
-
-/**
-  This function will connect all current system handles recursively. The
-  connection will finish until every handle's child handle created if it have.
-
-  None
-
-  @retval EFI_SUCCESS           All handles and it's child handle have been
-                                connected
-  @retval EFI_STATUS            Return the status of gBS->LocateHandleBuffer().
-
-**/
-EFI_STATUS
-BdsLibConnectAllEfi (
-  VOID
-  )
-{
-  EFI_STATUS  Status;
-  UINTN       HandleCount;
-  EFI_HANDLE  *HandleBuffer;
-  UINTN       Index;
-
-  Status = gBS->LocateHandleBuffer (
-                  AllHandles,
-                  NULL,
-                  NULL,
-                  &HandleCount,
-                  &HandleBuffer
-                  );
-  if (EFI_ERROR (Status)) {
-    return Status;
-  }
-
-  for (Index = 0; Index < HandleCount; Index++) {
-    Status = gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE);
-  }
-
-  gBS->FreePool (HandleBuffer);
-
-  return EFI_SUCCESS;
-}
-
-
-/**
-  This function will disconnect all current system handles. The disconnection
-  will finish until every handle have been disconnected.
-
-  None
-
-  @retval EFI_SUCCESS           All handles have been disconnected
-  @retval EFI_STATUS            Return the status of gBS->LocateHandleBuffer().
-
-**/
-EFI_STATUS
-BdsLibDisconnectAllEfi (
-  VOID
-  )
-{
-  EFI_STATUS  Status;
-  UINTN       HandleCount;
-  EFI_HANDLE  *HandleBuffer;
-  UINTN       Index;
-
-  //
-  // Disconnect all
-  //
-  Status = gBS->LocateHandleBuffer (
-                  AllHandles,
-                  NULL,
-                  NULL,
-                  &HandleCount,
-                  &HandleBuffer
-                  );
-  if (EFI_ERROR (Status)) {
-    return Status;
-  }
-
-  for (Index = 0; Index < HandleCount; Index++) {
-    Status = gBS->DisconnectController (HandleBuffer[Index], NULL, NULL);
-  }
-
-  gBS->FreePool (HandleBuffer);
-
-  return EFI_SUCCESS;
-}
-
-
-/**
-  Connects all drivers to all controllers.
-  This function make sure all the current system driver will manage
-  the correspoinding controllers if have. And at the same time, make
-  sure all the system controllers have driver to manage it if have.
-
-  None
-
-  @return None
-
-**/
-VOID
-BdsLibConnectAllDriversToAllControllers (
-  VOID
-  )
-{
-  EFI_STATUS  Status;
-
-  do {
-    //
-    // Connect All EFI 1.10 drivers following EFI 1.10 algorithm
-    //
-    BdsLibConnectAllEfi ();
-
-    //
-    // Check to see if it's possible to dispatch an more DXE drivers.
-    // The BdsLibConnectAllEfi () may have made new DXE drivers show up.
-    // If anything is Dispatched Status == EFI_SUCCESS and we will try
-    // the connect again.
-    //
-    Status = gDS->Dispatch ();
-
-  } while (!EFI_ERROR (Status));
-
-}
-
-
-/**
-  Connect the specific Usb device which match the short form device path,
-  and whose bus is determined by Host Controller (Uhci or Ehci)
-
-  @param  HostControllerPI      Uhci (0x00) or Ehci (0x20) or Both uhci and ehci
-                                (0xFF)
-  @param  RemainingDevicePath   a short-form device path that starts with the first
-                                element  being a USB WWID or a USB Class device
-                                path
-
-  @return EFI_INVALID_PARAMETER
-  @return EFI_SUCCESS
-  @return EFI_NOT_FOUND
-
-**/
-EFI_STATUS
-BdsLibConnectUsbDevByShortFormDP(
-  IN CHAR8                      HostControllerPI,
-  IN EFI_DEVICE_PATH_PROTOCOL   *RemainingDevicePath
-  )
-{
-  EFI_STATUS                            Status;
-  EFI_HANDLE                            *HandleArray;
-  UINTN                                 HandleArrayCount;
-  UINTN                                 Index;
-  EFI_PCI_IO_PROTOCOL                   *PciIo;
-  UINT8                                 Class[3];
-  BOOLEAN                               AtLeastOneConnected;
-
-  //
-  // Check the passed in parameters
-  //
-  if (RemainingDevicePath == NULL) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  if ((DevicePathType (RemainingDevicePath) != MESSAGING_DEVICE_PATH) ||
-      ((DevicePathSubType (RemainingDevicePath) != MSG_USB_CLASS_DP)
-#if (EFI_SPECIFICATION_VERSION >= 0x00020000)
-      && (DevicePathSubType (RemainingDevicePath) != MSG_USB_WWID_DP)
-#endif
-      )) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  if (HostControllerPI != 0xFF &&
-      HostControllerPI != 0x00 &&
-      HostControllerPI != 0x20) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  //
-  // Find the usb host controller firstly, then connect with the remaining device path
-  //
-  AtLeastOneConnected = FALSE;
-  Status = gBS->LocateHandleBuffer (
-                  ByProtocol,
-                  &gEfiPciIoProtocolGuid,
-                  NULL,
-                  &HandleArrayCount,
-                  &HandleArray
-                  );
-  if (!EFI_ERROR (Status)) {
-    for (Index = 0; Index < HandleArrayCount; Index++) {
-      Status = gBS->HandleProtocol (
-                      HandleArray[Index],
-                      &gEfiPciIoProtocolGuid,
-                      (VOID **)&PciIo
-                      );
-      if (!EFI_ERROR (Status)) {
-        //
-        // Check whether the Pci device is the wanted usb host controller
-        //
-        Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x09, 3, &Class);
-        if (!EFI_ERROR (Status)) {
-          if ((PCI_CLASS_SERIAL == Class[2]) &&
-              (PCI_CLASS_SERIAL_USB == Class[1])) {
-            if (HostControllerPI == Class[0] || HostControllerPI == 0xFF) {
-              Status = gBS->ConnectController (
-                              HandleArray[Index],
-                              NULL,
-                              RemainingDevicePath,
-                              FALSE
-                              );
-              if (!EFI_ERROR(Status)) {
-                AtLeastOneConnected = TRUE;
-              }
-            }
-          }
-        }
-      }
-    }
-
-    if (AtLeastOneConnected) {
-      return EFI_SUCCESS;
-    }
-  }
-
-  return EFI_NOT_FOUND;
-}
+/** @file\r
+  BDS Lib functions which relate with connect the device\r
+\r
+Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "InternalBdsLib.h"\r
+\r
+\r
+/**\r
+  This function will connect all the system driver to controller\r
+  first, and then special connect the default console, this make\r
+  sure all the system controller avialbe and the platform default\r
+  console connected.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+BdsLibConnectAll (\r
+  VOID\r
+  )\r
+{\r
+  //\r
+  // Connect the platform console first\r
+  //\r
+  BdsLibConnectAllDefaultConsoles ();\r
+\r
+  //\r
+  // Generic way to connect all the drivers\r
+  //\r
+  BdsLibConnectAllDriversToAllControllers ();\r
+\r
+  //\r
+  // Here we have the assumption that we have already had\r
+  // platform default console\r
+  //\r
+  BdsLibConnectAllDefaultConsoles ();\r
+}\r
+\r
+\r
+/**\r
+  This function will connect all the system drivers to all controllers\r
+  first, and then connect all the console devices the system current\r
+  have. After this we should get all the device work and console avariable\r
+  if the system have console device.\r
+\r
+  None\r
+\r
+  @return None\r
+\r
+**/\r
+VOID\r
+BdsLibGenericConnectAll (\r
+  VOID\r
+  )\r
+{\r
+  //\r
+  // Most generic way to connect all the drivers\r
+  //\r
+  BdsLibConnectAllDriversToAllControllers ();\r
+  BdsLibConnectAllConsoles ();\r
+}\r
+\r
+\r
+/**\r
+  This function will create all handles associate with every device\r
+  path node. If the handle associate with one device path node can not\r
+  be created success, then still give one chance to do the dispatch,\r
+  which load the missing drivers if possible.\r
+\r
+  @param  DevicePathToConnect   The device path which will be connected, it can be\r
+                                a multi-instance device path\r
+\r
+  @retval EFI_SUCCESS           All handles associate with every device path  node\r
+                                have been created\r
+  @retval EFI_OUT_OF_RESOURCES  There is no resource to create new handles\r
+  @retval EFI_NOT_FOUND         Create the handle associate with one device  path\r
+                                node failed\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BdsLibConnectDevicePath (\r
+  IN EFI_DEVICE_PATH_PROTOCOL  *DevicePathToConnect\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL  *CopyOfDevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL  *Instance;\r
+  EFI_DEVICE_PATH_PROTOCOL  *RemainingDevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL  *Next;\r
+  EFI_HANDLE                Handle;\r
+  EFI_HANDLE                PreviousHandle;\r
+  UINTN                     Size;\r
+\r
+  if (DevicePathToConnect == NULL) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  DevicePath        = DuplicateDevicePath (DevicePathToConnect);\r
+  CopyOfDevicePath  = DevicePath;\r
+  if (DevicePath == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  do {\r
+    //\r
+    // The outer loop handles multi instance device paths.\r
+    // Only console variables contain multiple instance device paths.\r
+    //\r
+    // After this call DevicePath points to the next Instance\r
+    //\r
+    Instance  = GetNextDevicePathInstance (&DevicePath, &Size);\r
+    Next      = Instance;\r
+    while (!IsDevicePathEndType (Next)) {\r
+      Next = NextDevicePathNode (Next);\r
+    }\r
+\r
+    SetDevicePathEndNode (Next);\r
+\r
+    //\r
+    // Start the real work of connect with RemainingDevicePath\r
+    //\r
+    PreviousHandle = NULL;\r
+    do {\r
+      //\r
+      // Find the handle that best matches the Device Path. If it is only a\r
+      // partial match the remaining part of the device path is returned in\r
+      // RemainingDevicePath.\r
+      //\r
+      RemainingDevicePath = Instance;\r
+      Status              = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &RemainingDevicePath, &Handle);\r
+\r
+      if (!EFI_ERROR (Status)) {\r
+        if (Handle == PreviousHandle) {\r
+          //\r
+          // If no forward progress is made try invoking the Dispatcher.\r
+          // A new FV may have been added to the system an new drivers\r
+          // may now be found.\r
+          // Status == EFI_SUCCESS means a driver was dispatched\r
+          // Status == EFI_NOT_FOUND means no new drivers were dispatched\r
+          //\r
+          Status = gDS->Dispatch ();\r
+        }\r
+\r
+        if (!EFI_ERROR (Status)) {\r
+          PreviousHandle = Handle;\r
+          //\r
+          // Connect all drivers that apply to Handle and RemainingDevicePath,\r
+          // the Recursive flag is FALSE so only one level will be expanded.\r
+          //\r
+          // Do not check the connect status here, if the connect controller fail,\r
+          // then still give the chance to do dispatch, because partial\r
+          // RemainingDevicepath may be in the new FV\r
+          //\r
+          // 1. If the connect fail, RemainingDevicepath and handle will not\r
+          //    change, so next time will do the dispatch, then dispatch's status\r
+          //    will take effect\r
+          // 2. If the connect success, the RemainingDevicepath and handle will\r
+          //    change, then avoid the dispatch, we have chance to continue the\r
+          //    next connection\r
+          //\r
+          gBS->ConnectController (Handle, NULL, RemainingDevicePath, FALSE);\r
+        }\r
+      }\r
+      //\r
+      // Loop until RemainingDevicePath is an empty device path\r
+      //\r
+    } while (!EFI_ERROR (Status) && !IsDevicePathEnd (RemainingDevicePath));\r
+\r
+  } while (DevicePath != NULL);\r
+\r
+  if (CopyOfDevicePath != NULL) {\r
+    gBS->FreePool (CopyOfDevicePath);\r
+  }\r
+  //\r
+  // All handle with DevicePath exists in the handle database\r
+  //\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  This function will connect all current system handles recursively. The\r
+  connection will finish until every handle's child handle created if it have.\r
+\r
+  @retval EFI_SUCCESS           All handles and it's child handle have been\r
+                                connected\r
+  @retval EFI_STATUS            Return the status of gBS->LocateHandleBuffer().\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BdsLibConnectAllEfi (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  UINTN       HandleCount;\r
+  EFI_HANDLE  *HandleBuffer;\r
+  UINTN       Index;\r
+\r
+  Status = gBS->LocateHandleBuffer (\r
+                  AllHandles,\r
+                  NULL,\r
+                  NULL,\r
+                  &HandleCount,\r
+                  &HandleBuffer\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  for (Index = 0; Index < HandleCount; Index++) {\r
+    Status = gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE);\r
+  }\r
+\r
+  gBS->FreePool (HandleBuffer);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  This function will disconnect all current system handles. The disconnection\r
+  will finish until every handle have been disconnected.\r
+\r
+  @retval EFI_SUCCESS           All handles have been disconnected\r
+  @retval EFI_STATUS            Return the status of gBS->LocateHandleBuffer().\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BdsLibDisconnectAllEfi (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  UINTN       HandleCount;\r
+  EFI_HANDLE  *HandleBuffer;\r
+  UINTN       Index;\r
+\r
+  //\r
+  // Disconnect all\r
+  //\r
+  Status = gBS->LocateHandleBuffer (\r
+                  AllHandles,\r
+                  NULL,\r
+                  NULL,\r
+                  &HandleCount,\r
+                  &HandleBuffer\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  for (Index = 0; Index < HandleCount; Index++) {\r
+    Status = gBS->DisconnectController (HandleBuffer[Index], NULL, NULL);\r
+  }\r
+\r
+  gBS->FreePool (HandleBuffer);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Connects all drivers to all controllers.\r
+  This function make sure all the current system driver will manage\r
+  the correspoinding controllers if have. And at the same time, make\r
+  sure all the system controllers have driver to manage it if have.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+BdsLibConnectAllDriversToAllControllers (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  do {\r
+    //\r
+    // Connect All EFI 1.10 drivers following EFI 1.10 algorithm\r
+    //\r
+    BdsLibConnectAllEfi ();\r
+\r
+    //\r
+    // Check to see if it's possible to dispatch an more DXE drivers.\r
+    // The BdsLibConnectAllEfi () may have made new DXE drivers show up.\r
+    // If anything is Dispatched Status == EFI_SUCCESS and we will try\r
+    // the connect again.\r
+    //\r
+    Status = gDS->Dispatch ();\r
+\r
+  } while (!EFI_ERROR (Status));\r
+\r
+}\r
+\r
+\r
+/**\r
+  Connect the specific Usb device which match the short form device path,\r
+  and whose bus is determined by Host Controller (Uhci or Ehci)\r
+\r
+  @param  HostControllerPI      Uhci (0x00) or Ehci (0x20) or Both uhci and ehci\r
+                                (0xFF)\r
+  @param  RemainingDevicePath   a short-form device path that starts with the first\r
+                                element  being a USB WWID or a USB Class device\r
+                                path\r
+\r
+  @return EFI_INVALID_PARAMETER\r
+  @return EFI_SUCCESS\r
+  @return EFI_NOT_FOUND\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BdsLibConnectUsbDevByShortFormDP(\r
+  IN UINT8                      HostControllerPI,\r
+  IN EFI_DEVICE_PATH_PROTOCOL   *RemainingDevicePath\r
+  )\r
+{\r
+  EFI_STATUS                            Status;\r
+  EFI_HANDLE                            *HandleArray;\r
+  UINTN                                 HandleArrayCount;\r
+  UINTN                                 Index;\r
+  EFI_PCI_IO_PROTOCOL                   *PciIo;\r
+  UINT8                                 Class[3];\r
+  BOOLEAN                               AtLeastOneConnected;\r
+\r
+  //\r
+  // Check the passed in parameters\r
+  //\r
+  if (RemainingDevicePath == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if ((DevicePathType (RemainingDevicePath) != MESSAGING_DEVICE_PATH) ||\r
+      ((DevicePathSubType (RemainingDevicePath) != MSG_USB_CLASS_DP)\r
+      && (DevicePathSubType (RemainingDevicePath) != MSG_USB_WWID_DP)\r
+      )) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (HostControllerPI != 0xFF &&\r
+      HostControllerPI != 0x00 &&\r
+      HostControllerPI != 0x20) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // Find the usb host controller firstly, then connect with the remaining device path\r
+  //\r
+  AtLeastOneConnected = FALSE;\r
+  Status = gBS->LocateHandleBuffer (\r
+                  ByProtocol,\r
+                  &gEfiPciIoProtocolGuid,\r
+                  NULL,\r
+                  &HandleArrayCount,\r
+                  &HandleArray\r
+                  );\r
+  if (!EFI_ERROR (Status)) {\r
+    for (Index = 0; Index < HandleArrayCount; Index++) {\r
+      Status = gBS->HandleProtocol (\r
+                      HandleArray[Index],\r
+                      &gEfiPciIoProtocolGuid,\r
+                      (VOID **)&PciIo\r
+                      );\r
+      if (!EFI_ERROR (Status)) {\r
+        //\r
+        // Check whether the Pci device is the wanted usb host controller\r
+        //\r
+        Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x09, 3, &Class);\r
+        if (!EFI_ERROR (Status)) {\r
+          if ((PCI_CLASS_SERIAL == Class[2]) &&\r
+              (PCI_CLASS_SERIAL_USB == Class[1])) {\r
+            if (HostControllerPI == Class[0] || HostControllerPI == 0xFF) {\r
+              Status = gBS->ConnectController (\r
+                              HandleArray[Index],\r
+                              NULL,\r
+                              RemainingDevicePath,\r
+                              FALSE\r
+                              );\r
+              if (!EFI_ERROR(Status)) {\r
+                AtLeastOneConnected = TRUE;\r
+              }\r
+            }\r
+          }\r
+        }\r
+      }\r
+    }\r
+\r
+    if (AtLeastOneConnected) {\r
+      return EFI_SUCCESS;\r
+    }\r
+  }\r
+\r
+  return EFI_NOT_FOUND;\r
+}\r