DriverSupport.c revision 85658066182d23e210209299770edaef26d09085
128a00297189c323096aae8e2975de94e8549613cyshang/*++
228a00297189c323096aae8e2975de94e8549613cyshang
328a00297189c323096aae8e2975de94e8549613cyshangCopyright (c) 2006, Intel Corporation
428a00297189c323096aae8e2975de94e8549613cyshangAll rights reserved. This program and the accompanying materials
528a00297189c323096aae8e2975de94e8549613cyshangare licensed and made available under the terms and conditions of the BSD License
628a00297189c323096aae8e2975de94e8549613cyshangwhich accompanies this distribution.  The full text of the license may be found at
728a00297189c323096aae8e2975de94e8549613cyshanghttp://opensource.org/licenses/bsd-license.php
828a00297189c323096aae8e2975de94e8549613cyshang
928a00297189c323096aae8e2975de94e8549613cyshangTHE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
1028a00297189c323096aae8e2975de94e8549613cyshangWITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
1128a00297189c323096aae8e2975de94e8549613cyshang
1228a00297189c323096aae8e2975de94e8549613cyshangModule Name:
1328a00297189c323096aae8e2975de94e8549613cyshang
1428a00297189c323096aae8e2975de94e8549613cyshang    DriverSupport.c
1528a00297189c323096aae8e2975de94e8549613cyshang
1628a00297189c323096aae8e2975de94e8549613cyshangAbstract:
1728a00297189c323096aae8e2975de94e8549613cyshang
1828a00297189c323096aae8e2975de94e8549613cyshang    EFI Driver Support Protocol
1928a00297189c323096aae8e2975de94e8549613cyshang
2028a00297189c323096aae8e2975de94e8549613cyshangRevision History
2128a00297189c323096aae8e2975de94e8549613cyshang
2228a00297189c323096aae8e2975de94e8549613cyshang--*/
2328a00297189c323096aae8e2975de94e8549613cyshang
2428a00297189c323096aae8e2975de94e8549613cyshang#include <DxeMain.h>
2528a00297189c323096aae8e2975de94e8549613cyshang
2685658066182d23e210209299770edaef26d09085mdkinneyBOOLEAN mRepairLoadedImage = FALSE;
2728a00297189c323096aae8e2975de94e8549613cyshang
2885658066182d23e210209299770edaef26d09085mdkinney//
2985658066182d23e210209299770edaef26d09085mdkinney// Driver Support Function Prototypes
3085658066182d23e210209299770edaef26d09085mdkinney//
3128a00297189c323096aae8e2975de94e8549613cyshangEFI_STATUS
3228a00297189c323096aae8e2975de94e8549613cyshangGetHandleFromDriverBinding (
3328a00297189c323096aae8e2975de94e8549613cyshang  IN EFI_DRIVER_BINDING_PROTOCOL           *DriverBindingNeed,
3428a00297189c323096aae8e2975de94e8549613cyshang  OUT  EFI_HANDLE                          *Handle
3528a00297189c323096aae8e2975de94e8549613cyshang  );
3628a00297189c323096aae8e2975de94e8549613cyshang
3728a00297189c323096aae8e2975de94e8549613cyshangEFI_STATUS
3828a00297189c323096aae8e2975de94e8549613cyshangCoreConnectSingleController (
3928a00297189c323096aae8e2975de94e8549613cyshang  IN  EFI_HANDLE                ControllerHandle,
4028a00297189c323096aae8e2975de94e8549613cyshang  IN  EFI_HANDLE                *DriverImageHandle    OPTIONAL,
4128a00297189c323096aae8e2975de94e8549613cyshang  IN  EFI_DEVICE_PATH_PROTOCOL  *RemainingDevicePath  OPTIONAL
4228a00297189c323096aae8e2975de94e8549613cyshang  );
4328a00297189c323096aae8e2975de94e8549613cyshang
4428a00297189c323096aae8e2975de94e8549613cyshang//
4528a00297189c323096aae8e2975de94e8549613cyshang// Driver Support Functions
4628a00297189c323096aae8e2975de94e8549613cyshang//
4728a00297189c323096aae8e2975de94e8549613cyshangEFI_STATUS
4828a00297189c323096aae8e2975de94e8549613cyshangEFIAPI
4928a00297189c323096aae8e2975de94e8549613cyshangCoreConnectController (
5028a00297189c323096aae8e2975de94e8549613cyshang  IN  EFI_HANDLE                ControllerHandle,
5128a00297189c323096aae8e2975de94e8549613cyshang  IN  EFI_HANDLE                *DriverImageHandle    OPTIONAL,
5228a00297189c323096aae8e2975de94e8549613cyshang  IN  EFI_DEVICE_PATH_PROTOCOL  *RemainingDevicePath  OPTIONAL,
5328a00297189c323096aae8e2975de94e8549613cyshang  IN  BOOLEAN                   Recursive
5428a00297189c323096aae8e2975de94e8549613cyshang  )
5528a00297189c323096aae8e2975de94e8549613cyshang/*++
5628a00297189c323096aae8e2975de94e8549613cyshang
5728a00297189c323096aae8e2975de94e8549613cyshangRoutine Description:
5828a00297189c323096aae8e2975de94e8549613cyshang
5928a00297189c323096aae8e2975de94e8549613cyshang  Connects one or more drivers to a controller.
6028a00297189c323096aae8e2975de94e8549613cyshang
6128a00297189c323096aae8e2975de94e8549613cyshangArguments:
6228a00297189c323096aae8e2975de94e8549613cyshang
6328a00297189c323096aae8e2975de94e8549613cyshang  ControllerHandle            - Handle of the controller to be connected.
6428a00297189c323096aae8e2975de94e8549613cyshang
6528a00297189c323096aae8e2975de94e8549613cyshang  DriverImageHandle           - DriverImageHandle A pointer to an ordered list of driver image handles.
6628a00297189c323096aae8e2975de94e8549613cyshang
6728a00297189c323096aae8e2975de94e8549613cyshang  RemainingDevicePath         - RemainingDevicePath A pointer to the device path that specifies a child of the
6828a00297189c323096aae8e2975de94e8549613cyshang                                controller specified by ControllerHandle.
6928a00297189c323096aae8e2975de94e8549613cyshang
7028a00297189c323096aae8e2975de94e8549613cyshang  Recursive                   - Whether the function would be called recursively or not.
7128a00297189c323096aae8e2975de94e8549613cyshang
7228a00297189c323096aae8e2975de94e8549613cyshangReturns:
7328a00297189c323096aae8e2975de94e8549613cyshang
7428a00297189c323096aae8e2975de94e8549613cyshang  Status code.
7528a00297189c323096aae8e2975de94e8549613cyshang
7628a00297189c323096aae8e2975de94e8549613cyshang--*/
7728a00297189c323096aae8e2975de94e8549613cyshang{
7828a00297189c323096aae8e2975de94e8549613cyshang  EFI_STATUS                           Status;
7928a00297189c323096aae8e2975de94e8549613cyshang  EFI_STATUS                           ReturnStatus;
8028a00297189c323096aae8e2975de94e8549613cyshang  IHANDLE                              *Handle;
8128a00297189c323096aae8e2975de94e8549613cyshang  PROTOCOL_INTERFACE                   *Prot;
8228a00297189c323096aae8e2975de94e8549613cyshang  LIST_ENTRY                           *Link;
8328a00297189c323096aae8e2975de94e8549613cyshang  LIST_ENTRY                           *ProtLink;
8428a00297189c323096aae8e2975de94e8549613cyshang  OPEN_PROTOCOL_DATA                   *OpenData;
8528a00297189c323096aae8e2975de94e8549613cyshang  EFI_DEVICE_PATH_PROTOCOL             *AlignedRemainingDevicePath;
8685658066182d23e210209299770edaef26d09085mdkinney  EFI_HANDLE                           *ChildHandleBuffer;
8785658066182d23e210209299770edaef26d09085mdkinney  UINTN                                ChildHandleCount;
8885658066182d23e210209299770edaef26d09085mdkinney  UINTN                                Index;
8985658066182d23e210209299770edaef26d09085mdkinney  EFI_HANDLE                           *LoadedImageHandleBuffer;
9085658066182d23e210209299770edaef26d09085mdkinney  UINTN                                LoadedImageHandleCount;
9185658066182d23e210209299770edaef26d09085mdkinney  LOADED_IMAGE_PRIVATE_DATA            *Image;
9285658066182d23e210209299770edaef26d09085mdkinney  EFI_HANDLE                           DeviceHandle;
9385658066182d23e210209299770edaef26d09085mdkinney  EFI_DEVICE_PATH_PROTOCOL             *DevicePath;
9428a00297189c323096aae8e2975de94e8549613cyshang
9528a00297189c323096aae8e2975de94e8549613cyshang  //
9628a00297189c323096aae8e2975de94e8549613cyshang  // Make sure ControllerHandle is valid
9728a00297189c323096aae8e2975de94e8549613cyshang  //
9828a00297189c323096aae8e2975de94e8549613cyshang  Status = CoreValidateHandle (ControllerHandle);
9928a00297189c323096aae8e2975de94e8549613cyshang  if (EFI_ERROR (Status)) {
10028a00297189c323096aae8e2975de94e8549613cyshang    return Status;
10128a00297189c323096aae8e2975de94e8549613cyshang  }
10228a00297189c323096aae8e2975de94e8549613cyshang
10328a00297189c323096aae8e2975de94e8549613cyshang  Handle = ControllerHandle;
10428a00297189c323096aae8e2975de94e8549613cyshang
10528a00297189c323096aae8e2975de94e8549613cyshang  //
10685658066182d23e210209299770edaef26d09085mdkinney  // Make a copy of RemainingDevicePath to guanatee it is aligned
10728a00297189c323096aae8e2975de94e8549613cyshang  //
10828a00297189c323096aae8e2975de94e8549613cyshang  AlignedRemainingDevicePath = NULL;
10928a00297189c323096aae8e2975de94e8549613cyshang  if (RemainingDevicePath != NULL) {
11028a00297189c323096aae8e2975de94e8549613cyshang    AlignedRemainingDevicePath = CoreDuplicateDevicePath (RemainingDevicePath);
11128a00297189c323096aae8e2975de94e8549613cyshang  }
11228a00297189c323096aae8e2975de94e8549613cyshang
11328a00297189c323096aae8e2975de94e8549613cyshang  //
11485658066182d23e210209299770edaef26d09085mdkinney  // Connect all drivers to ControllerHandle
11585658066182d23e210209299770edaef26d09085mdkinney  // If CoreConnectSingleController returns EFI_NOT_READY, then the number of
11685658066182d23e210209299770edaef26d09085mdkinney  // Driver Binding Protocols in the handle database has increased during the call
11785658066182d23e210209299770edaef26d09085mdkinney  // so the connect operation must be restarted
11828a00297189c323096aae8e2975de94e8549613cyshang  //
11985658066182d23e210209299770edaef26d09085mdkinney  do {
12085658066182d23e210209299770edaef26d09085mdkinney    ReturnStatus = CoreConnectSingleController (
12185658066182d23e210209299770edaef26d09085mdkinney                    ControllerHandle,
12285658066182d23e210209299770edaef26d09085mdkinney                    DriverImageHandle,
12385658066182d23e210209299770edaef26d09085mdkinney                    AlignedRemainingDevicePath
12485658066182d23e210209299770edaef26d09085mdkinney                    );
12585658066182d23e210209299770edaef26d09085mdkinney  } while (ReturnStatus == EFI_NOT_READY);
12685658066182d23e210209299770edaef26d09085mdkinney
12785658066182d23e210209299770edaef26d09085mdkinney  //
12885658066182d23e210209299770edaef26d09085mdkinney  // Free the aligned copy of RemainingDevicePath
12985658066182d23e210209299770edaef26d09085mdkinney  //
13085658066182d23e210209299770edaef26d09085mdkinney  if (AlignedRemainingDevicePath != NULL) {
13185658066182d23e210209299770edaef26d09085mdkinney    CoreFreePool (AlignedRemainingDevicePath);
13228a00297189c323096aae8e2975de94e8549613cyshang  }
13328a00297189c323096aae8e2975de94e8549613cyshang
13428a00297189c323096aae8e2975de94e8549613cyshang  //
13528a00297189c323096aae8e2975de94e8549613cyshang  // If recursive, then connect all drivers to all of ControllerHandle's children
13628a00297189c323096aae8e2975de94e8549613cyshang  //
13785658066182d23e210209299770edaef26d09085mdkinney  if (Recursive) {
13885658066182d23e210209299770edaef26d09085mdkinney    //
13985658066182d23e210209299770edaef26d09085mdkinney    // Acquire the protocol lock on the handle database so the child handles can be collected
14085658066182d23e210209299770edaef26d09085mdkinney    //
14185658066182d23e210209299770edaef26d09085mdkinney    CoreAcquireProtocolLock ();
14285658066182d23e210209299770edaef26d09085mdkinney
14385658066182d23e210209299770edaef26d09085mdkinney    //
14485658066182d23e210209299770edaef26d09085mdkinney    // Make sure the DriverBindingHandle is valid
14585658066182d23e210209299770edaef26d09085mdkinney    //
14685658066182d23e210209299770edaef26d09085mdkinney    Status = CoreValidateHandle (ControllerHandle);
14785658066182d23e210209299770edaef26d09085mdkinney    if (EFI_ERROR (Status)) {
14885658066182d23e210209299770edaef26d09085mdkinney      //
14985658066182d23e210209299770edaef26d09085mdkinney      // Release the protocol lock on the handle database
15085658066182d23e210209299770edaef26d09085mdkinney      //
15185658066182d23e210209299770edaef26d09085mdkinney      CoreReleaseProtocolLock ();
15285658066182d23e210209299770edaef26d09085mdkinney
15385658066182d23e210209299770edaef26d09085mdkinney      return ReturnStatus;
15485658066182d23e210209299770edaef26d09085mdkinney    }
15585658066182d23e210209299770edaef26d09085mdkinney
15685658066182d23e210209299770edaef26d09085mdkinney
15785658066182d23e210209299770edaef26d09085mdkinney    //
15885658066182d23e210209299770edaef26d09085mdkinney    // Count ControllerHandle's children
15985658066182d23e210209299770edaef26d09085mdkinney    //
16085658066182d23e210209299770edaef26d09085mdkinney    for (Link = Handle->Protocols.ForwardLink, ChildHandleCount = 0; Link != &Handle->Protocols; Link = Link->ForwardLink) {
16185658066182d23e210209299770edaef26d09085mdkinney      Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
16285658066182d23e210209299770edaef26d09085mdkinney      for (ProtLink = Prot->OpenList.ForwardLink;
16385658066182d23e210209299770edaef26d09085mdkinney          ProtLink != &Prot->OpenList;
16485658066182d23e210209299770edaef26d09085mdkinney          ProtLink = ProtLink->ForwardLink) {
16585658066182d23e210209299770edaef26d09085mdkinney        OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
16685658066182d23e210209299770edaef26d09085mdkinney        if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
16785658066182d23e210209299770edaef26d09085mdkinney          ChildHandleCount++;
16885658066182d23e210209299770edaef26d09085mdkinney        }
16985658066182d23e210209299770edaef26d09085mdkinney      }
17085658066182d23e210209299770edaef26d09085mdkinney    }
17185658066182d23e210209299770edaef26d09085mdkinney
17285658066182d23e210209299770edaef26d09085mdkinney    //
17385658066182d23e210209299770edaef26d09085mdkinney    // Allocate a handle buffer for ControllerHandle's children
17485658066182d23e210209299770edaef26d09085mdkinney    //
17585658066182d23e210209299770edaef26d09085mdkinney    ChildHandleBuffer = CoreAllocateBootServicesPool (ChildHandleCount * sizeof(EFI_HANDLE));
17685658066182d23e210209299770edaef26d09085mdkinney
17785658066182d23e210209299770edaef26d09085mdkinney    //
17885658066182d23e210209299770edaef26d09085mdkinney    // Fill in a handle buffer with ControllerHandle's children
17985658066182d23e210209299770edaef26d09085mdkinney    //
18085658066182d23e210209299770edaef26d09085mdkinney    for (Link = Handle->Protocols.ForwardLink, ChildHandleCount = 0; Link != &Handle->Protocols; Link = Link->ForwardLink) {
18185658066182d23e210209299770edaef26d09085mdkinney      Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
18285658066182d23e210209299770edaef26d09085mdkinney      for (ProtLink = Prot->OpenList.ForwardLink;
18385658066182d23e210209299770edaef26d09085mdkinney          ProtLink != &Prot->OpenList;
18485658066182d23e210209299770edaef26d09085mdkinney          ProtLink = ProtLink->ForwardLink) {
18528a00297189c323096aae8e2975de94e8549613cyshang        OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
18628a00297189c323096aae8e2975de94e8549613cyshang        if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
18785658066182d23e210209299770edaef26d09085mdkinney          ChildHandleBuffer[ChildHandleCount] = OpenData->ControllerHandle;
18885658066182d23e210209299770edaef26d09085mdkinney          ChildHandleCount++;
18985658066182d23e210209299770edaef26d09085mdkinney        }
19085658066182d23e210209299770edaef26d09085mdkinney      }
19185658066182d23e210209299770edaef26d09085mdkinney    }
19285658066182d23e210209299770edaef26d09085mdkinney
19385658066182d23e210209299770edaef26d09085mdkinney    //
19485658066182d23e210209299770edaef26d09085mdkinney    // Release the protocol lock on the handle database
19585658066182d23e210209299770edaef26d09085mdkinney    //
19685658066182d23e210209299770edaef26d09085mdkinney    CoreReleaseProtocolLock ();
19785658066182d23e210209299770edaef26d09085mdkinney
19885658066182d23e210209299770edaef26d09085mdkinney    //
19985658066182d23e210209299770edaef26d09085mdkinney    // Recursively connect each child handle
20085658066182d23e210209299770edaef26d09085mdkinney    //
20185658066182d23e210209299770edaef26d09085mdkinney    for (Index = 0; Index < ChildHandleCount; Index++) {
20285658066182d23e210209299770edaef26d09085mdkinney      CoreConnectController (
20385658066182d23e210209299770edaef26d09085mdkinney        ChildHandleBuffer[Index],
20485658066182d23e210209299770edaef26d09085mdkinney        NULL,
20585658066182d23e210209299770edaef26d09085mdkinney        NULL,
20685658066182d23e210209299770edaef26d09085mdkinney        TRUE
20785658066182d23e210209299770edaef26d09085mdkinney        );
20885658066182d23e210209299770edaef26d09085mdkinney    }
20985658066182d23e210209299770edaef26d09085mdkinney
21085658066182d23e210209299770edaef26d09085mdkinney    //
21185658066182d23e210209299770edaef26d09085mdkinney    // Free the handle buffer of ControllerHandle's children
21285658066182d23e210209299770edaef26d09085mdkinney    //
21385658066182d23e210209299770edaef26d09085mdkinney    CoreFreePool (ChildHandleBuffer);
21485658066182d23e210209299770edaef26d09085mdkinney  }
21585658066182d23e210209299770edaef26d09085mdkinney
21685658066182d23e210209299770edaef26d09085mdkinney  //
21785658066182d23e210209299770edaef26d09085mdkinney  // If a Stop() function has been called one or more time successfully, then attempt to
21885658066182d23e210209299770edaef26d09085mdkinney  // repair the stale DeviceHandle fields of the Loaded Image Protocols
21985658066182d23e210209299770edaef26d09085mdkinney  //
22085658066182d23e210209299770edaef26d09085mdkinney  if (mRepairLoadedImage) {
22185658066182d23e210209299770edaef26d09085mdkinney    //
22285658066182d23e210209299770edaef26d09085mdkinney    // Assume that all Loaded Image Protocols can be repaired
22385658066182d23e210209299770edaef26d09085mdkinney    //
22485658066182d23e210209299770edaef26d09085mdkinney    mRepairLoadedImage = FALSE;
22585658066182d23e210209299770edaef26d09085mdkinney
22685658066182d23e210209299770edaef26d09085mdkinney    //
22785658066182d23e210209299770edaef26d09085mdkinney    // Get list of all Loaded Image Protocol Instances
22885658066182d23e210209299770edaef26d09085mdkinney    //
22985658066182d23e210209299770edaef26d09085mdkinney    Status = CoreLocateHandleBuffer (
23085658066182d23e210209299770edaef26d09085mdkinney              ByProtocol,
23185658066182d23e210209299770edaef26d09085mdkinney              &gEfiLoadedImageProtocolGuid,
23285658066182d23e210209299770edaef26d09085mdkinney              NULL,
23385658066182d23e210209299770edaef26d09085mdkinney              &LoadedImageHandleCount,
23485658066182d23e210209299770edaef26d09085mdkinney              &LoadedImageHandleBuffer
23585658066182d23e210209299770edaef26d09085mdkinney              );
23685658066182d23e210209299770edaef26d09085mdkinney    if (!EFI_ERROR (Status) && LoadedImageHandleCount != 0) {
23785658066182d23e210209299770edaef26d09085mdkinney      for (Index = 0; Index < LoadedImageHandleCount; Index++) {
23885658066182d23e210209299770edaef26d09085mdkinney        //
23985658066182d23e210209299770edaef26d09085mdkinney        // Retrieve the Loaded Image Protocol
24085658066182d23e210209299770edaef26d09085mdkinney        //
24185658066182d23e210209299770edaef26d09085mdkinney        Image = CoreLoadedImageInfo (LoadedImageHandleBuffer[Index]);
24285658066182d23e210209299770edaef26d09085mdkinney        if (Image != NULL) {
24385658066182d23e210209299770edaef26d09085mdkinney          //
24485658066182d23e210209299770edaef26d09085mdkinney          // Check to see if the DeviceHandle field is a valid handle
24585658066182d23e210209299770edaef26d09085mdkinney          //
24685658066182d23e210209299770edaef26d09085mdkinney          Status = CoreValidateHandle (Image->Info.DeviceHandle);
24785658066182d23e210209299770edaef26d09085mdkinney          if (EFI_ERROR (Status)) {
24885658066182d23e210209299770edaef26d09085mdkinney            //
24985658066182d23e210209299770edaef26d09085mdkinney            // The DeviceHandle field is not valid.
25085658066182d23e210209299770edaef26d09085mdkinney            // Attempt to locate a device handle with a device path that matches the one
25185658066182d23e210209299770edaef26d09085mdkinney            // that was used to originally load the image
25285658066182d23e210209299770edaef26d09085mdkinney            //
25385658066182d23e210209299770edaef26d09085mdkinney            DevicePath = Image->DeviceHandleDevicePath;
25485658066182d23e210209299770edaef26d09085mdkinney            if (DevicePath != NULL) {
25585658066182d23e210209299770edaef26d09085mdkinney              Status = CoreLocateDevicePath (&gEfiDevicePathProtocolGuid, &DevicePath, &DeviceHandle);
25685658066182d23e210209299770edaef26d09085mdkinney              if (!EFI_ERROR (Status) && (DeviceHandle != NULL_HANDLE) && IsDevicePathEnd(DevicePath)) {
25785658066182d23e210209299770edaef26d09085mdkinney                //
25885658066182d23e210209299770edaef26d09085mdkinney                // A device handle with a matching device path was found, so update the Loaded Image Protocol
25985658066182d23e210209299770edaef26d09085mdkinney                // with the device handle discovered
26085658066182d23e210209299770edaef26d09085mdkinney                //
26185658066182d23e210209299770edaef26d09085mdkinney                Image->Info.DeviceHandle = DeviceHandle;
26285658066182d23e210209299770edaef26d09085mdkinney              } else {
26385658066182d23e210209299770edaef26d09085mdkinney                //
26485658066182d23e210209299770edaef26d09085mdkinney                // There is still at least one Loaded Image Protocol that requires repair
26585658066182d23e210209299770edaef26d09085mdkinney                //
26685658066182d23e210209299770edaef26d09085mdkinney                mRepairLoadedImage = TRUE;
26785658066182d23e210209299770edaef26d09085mdkinney              }
26885658066182d23e210209299770edaef26d09085mdkinney            }
26985658066182d23e210209299770edaef26d09085mdkinney          }
27028a00297189c323096aae8e2975de94e8549613cyshang        }
27185658066182d23e210209299770edaef26d09085mdkinney      }
27285658066182d23e210209299770edaef26d09085mdkinney      CoreFreePool (LoadedImageHandleBuffer);
27328a00297189c323096aae8e2975de94e8549613cyshang    }
27428a00297189c323096aae8e2975de94e8549613cyshang  }
27585658066182d23e210209299770edaef26d09085mdkinney
27628a00297189c323096aae8e2975de94e8549613cyshang  return ReturnStatus;
27728a00297189c323096aae8e2975de94e8549613cyshang}
27828a00297189c323096aae8e2975de94e8549613cyshang
27928a00297189c323096aae8e2975de94e8549613cyshangVOID
28028a00297189c323096aae8e2975de94e8549613cyshangAddSortedDriverBindingProtocol (
28128a00297189c323096aae8e2975de94e8549613cyshang  IN      EFI_HANDLE                   DriverBindingHandle,
28228a00297189c323096aae8e2975de94e8549613cyshang  IN OUT  UINTN                        *NumberOfSortedDriverBindingProtocols,
28328a00297189c323096aae8e2975de94e8549613cyshang  IN OUT  EFI_DRIVER_BINDING_PROTOCOL  **SortedDriverBindingProtocols,
28428a00297189c323096aae8e2975de94e8549613cyshang  IN      UINTN                        DriverBindingHandleCount,
28528a00297189c323096aae8e2975de94e8549613cyshang  IN OUT  EFI_HANDLE                   *DriverBindingHandleBuffer
28628a00297189c323096aae8e2975de94e8549613cyshang  )
28728a00297189c323096aae8e2975de94e8549613cyshang/*++
28828a00297189c323096aae8e2975de94e8549613cyshang
28928a00297189c323096aae8e2975de94e8549613cyshangRoutine Description:
29028a00297189c323096aae8e2975de94e8549613cyshang
29128a00297189c323096aae8e2975de94e8549613cyshang  Add Driver Binding Protocols from Context Driver Image Handles to sorted
29228a00297189c323096aae8e2975de94e8549613cyshang   Driver Binding Protocol list.
29328a00297189c323096aae8e2975de94e8549613cyshang
29428a00297189c323096aae8e2975de94e8549613cyshangArguments:
29528a00297189c323096aae8e2975de94e8549613cyshang
29628a00297189c323096aae8e2975de94e8549613cyshang  DriverBindingHandle - Handle of the driver binding protocol.
29728a00297189c323096aae8e2975de94e8549613cyshang
29828a00297189c323096aae8e2975de94e8549613cyshang  NumberOfSortedDriverBindingProtocols - Number Of sorted driver binding protocols
29928a00297189c323096aae8e2975de94e8549613cyshang
30028a00297189c323096aae8e2975de94e8549613cyshang  SortedDriverBindingProtocols - The sorted protocol list.
30128a00297189c323096aae8e2975de94e8549613cyshang
30228a00297189c323096aae8e2975de94e8549613cyshang  DriverBindingHandleCount - Driver Binding Handle Count.
30328a00297189c323096aae8e2975de94e8549613cyshang
30428a00297189c323096aae8e2975de94e8549613cyshang  DriverBindingHandleBuffer - The buffer of driver binding protocol to be modified.
30528a00297189c323096aae8e2975de94e8549613cyshang
30628a00297189c323096aae8e2975de94e8549613cyshangReturns:
30728a00297189c323096aae8e2975de94e8549613cyshang
30828a00297189c323096aae8e2975de94e8549613cyshang  None.
30928a00297189c323096aae8e2975de94e8549613cyshang
31028a00297189c323096aae8e2975de94e8549613cyshang--*/
31128a00297189c323096aae8e2975de94e8549613cyshang{
31228a00297189c323096aae8e2975de94e8549613cyshang  EFI_STATUS                   Status;
31328a00297189c323096aae8e2975de94e8549613cyshang  EFI_DRIVER_BINDING_PROTOCOL  *DriverBinding;
31428a00297189c323096aae8e2975de94e8549613cyshang  UINTN                        Index;
31528a00297189c323096aae8e2975de94e8549613cyshang
31628a00297189c323096aae8e2975de94e8549613cyshang  //
31728a00297189c323096aae8e2975de94e8549613cyshang  // Make sure the DriverBindingHandle is valid
31828a00297189c323096aae8e2975de94e8549613cyshang  //
31928a00297189c323096aae8e2975de94e8549613cyshang  Status = CoreValidateHandle (DriverBindingHandle);
32028a00297189c323096aae8e2975de94e8549613cyshang  if (EFI_ERROR (Status)) {
32128a00297189c323096aae8e2975de94e8549613cyshang    return;
32228a00297189c323096aae8e2975de94e8549613cyshang  }
32328a00297189c323096aae8e2975de94e8549613cyshang
32428a00297189c323096aae8e2975de94e8549613cyshang  //
32528a00297189c323096aae8e2975de94e8549613cyshang  // Retrieve the Driver Binding Protocol from DriverBindingHandle
32628a00297189c323096aae8e2975de94e8549613cyshang  //
32728a00297189c323096aae8e2975de94e8549613cyshang  Status = CoreHandleProtocol(
32828a00297189c323096aae8e2975de94e8549613cyshang             DriverBindingHandle,
32928a00297189c323096aae8e2975de94e8549613cyshang             &gEfiDriverBindingProtocolGuid,
33028a00297189c323096aae8e2975de94e8549613cyshang             (VOID **)&DriverBinding
33128a00297189c323096aae8e2975de94e8549613cyshang             );
33228a00297189c323096aae8e2975de94e8549613cyshang  //
33328a00297189c323096aae8e2975de94e8549613cyshang  // If DriverBindingHandle does not support the Driver Binding Protocol then return
33428a00297189c323096aae8e2975de94e8549613cyshang  //
33528a00297189c323096aae8e2975de94e8549613cyshang  if (EFI_ERROR (Status) || DriverBinding == NULL) {
33628a00297189c323096aae8e2975de94e8549613cyshang    return;
33728a00297189c323096aae8e2975de94e8549613cyshang  }
33828a00297189c323096aae8e2975de94e8549613cyshang
33928a00297189c323096aae8e2975de94e8549613cyshang  //
34028a00297189c323096aae8e2975de94e8549613cyshang  // See if DriverBinding is already in the sorted list
34128a00297189c323096aae8e2975de94e8549613cyshang  //
34285658066182d23e210209299770edaef26d09085mdkinney  for (Index = 0; Index < *NumberOfSortedDriverBindingProtocols && Index < DriverBindingHandleCount; Index++) {
34328a00297189c323096aae8e2975de94e8549613cyshang    if (DriverBinding == SortedDriverBindingProtocols[Index]) {
34428a00297189c323096aae8e2975de94e8549613cyshang      return;
34528a00297189c323096aae8e2975de94e8549613cyshang    }
34628a00297189c323096aae8e2975de94e8549613cyshang  }
34728a00297189c323096aae8e2975de94e8549613cyshang
34828a00297189c323096aae8e2975de94e8549613cyshang  //
34928a00297189c323096aae8e2975de94e8549613cyshang  // Add DriverBinding to the end of the list
35028a00297189c323096aae8e2975de94e8549613cyshang  //
35185658066182d23e210209299770edaef26d09085mdkinney  if (*NumberOfSortedDriverBindingProtocols < DriverBindingHandleCount) {
35285658066182d23e210209299770edaef26d09085mdkinney    SortedDriverBindingProtocols[*NumberOfSortedDriverBindingProtocols] = DriverBinding;
35385658066182d23e210209299770edaef26d09085mdkinney  }
35428a00297189c323096aae8e2975de94e8549613cyshang  *NumberOfSortedDriverBindingProtocols = *NumberOfSortedDriverBindingProtocols + 1;
35528a00297189c323096aae8e2975de94e8549613cyshang
35628a00297189c323096aae8e2975de94e8549613cyshang  //
35728a00297189c323096aae8e2975de94e8549613cyshang  // Mark the cooresponding handle in DriverBindingHandleBuffer as used
35828a00297189c323096aae8e2975de94e8549613cyshang  //
35928a00297189c323096aae8e2975de94e8549613cyshang  for (Index = 0; Index < DriverBindingHandleCount; Index++) {
36028a00297189c323096aae8e2975de94e8549613cyshang    if (DriverBindingHandleBuffer[Index] == DriverBindingHandle) {
36128a00297189c323096aae8e2975de94e8549613cyshang      DriverBindingHandleBuffer[Index] = NULL;
36228a00297189c323096aae8e2975de94e8549613cyshang    }
36328a00297189c323096aae8e2975de94e8549613cyshang  }
36428a00297189c323096aae8e2975de94e8549613cyshang}
36528a00297189c323096aae8e2975de94e8549613cyshang
36628a00297189c323096aae8e2975de94e8549613cyshangEFI_STATUS
36728a00297189c323096aae8e2975de94e8549613cyshangCoreConnectSingleController (
36828a00297189c323096aae8e2975de94e8549613cyshang  IN  EFI_HANDLE                ControllerHandle,
36928a00297189c323096aae8e2975de94e8549613cyshang  IN  EFI_HANDLE                *ContextDriverImageHandles OPTIONAL,
37028a00297189c323096aae8e2975de94e8549613cyshang  IN  EFI_DEVICE_PATH_PROTOCOL  *RemainingDevicePath       OPTIONAL
37128a00297189c323096aae8e2975de94e8549613cyshang  )
37228a00297189c323096aae8e2975de94e8549613cyshang/*++
37328a00297189c323096aae8e2975de94e8549613cyshang
37428a00297189c323096aae8e2975de94e8549613cyshangRoutine Description:
37528a00297189c323096aae8e2975de94e8549613cyshang
37628a00297189c323096aae8e2975de94e8549613cyshang  Connects a controller to a driver.
37728a00297189c323096aae8e2975de94e8549613cyshang
37828a00297189c323096aae8e2975de94e8549613cyshangArguments:
37928a00297189c323096aae8e2975de94e8549613cyshang
38028a00297189c323096aae8e2975de94e8549613cyshang  ControllerHandle            - Handle of the controller to be connected.
38128a00297189c323096aae8e2975de94e8549613cyshang  ContextDriverImageHandles   - DriverImageHandle A pointer to an ordered list of driver image handles.
38228a00297189c323096aae8e2975de94e8549613cyshang  RemainingDevicePath         - RemainingDevicePath A pointer to the device path that specifies a child
38328a00297189c323096aae8e2975de94e8549613cyshang                                of the controller specified by ControllerHandle.
38428a00297189c323096aae8e2975de94e8549613cyshang
38528a00297189c323096aae8e2975de94e8549613cyshangReturns:
38628a00297189c323096aae8e2975de94e8549613cyshang
38728a00297189c323096aae8e2975de94e8549613cyshang  EFI_SUCCESS           - One or more drivers were connected to ControllerHandle.
38828a00297189c323096aae8e2975de94e8549613cyshang  EFI_OUT_OF_RESOURCES  - No enough system resources to complete the request.
38928a00297189c323096aae8e2975de94e8549613cyshang  EFI_NOT_FOUND         - No drivers were connected to ControllerHandle.
39028a00297189c323096aae8e2975de94e8549613cyshang
39128a00297189c323096aae8e2975de94e8549613cyshang--*/
39228a00297189c323096aae8e2975de94e8549613cyshang{
39328a00297189c323096aae8e2975de94e8549613cyshang  EFI_STATUS                                 Status;
39428a00297189c323096aae8e2975de94e8549613cyshang  UINTN                                      Index;
39528a00297189c323096aae8e2975de94e8549613cyshang  EFI_HANDLE                                 DriverImageHandle;
39628a00297189c323096aae8e2975de94e8549613cyshang  EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL      *PlatformDriverOverride;
39728a00297189c323096aae8e2975de94e8549613cyshang  EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL  *BusSpecificDriverOverride;
39828a00297189c323096aae8e2975de94e8549613cyshang  UINTN                                      DriverBindingHandleCount;
39928a00297189c323096aae8e2975de94e8549613cyshang  EFI_HANDLE                                 *DriverBindingHandleBuffer;
40028a00297189c323096aae8e2975de94e8549613cyshang  EFI_DRIVER_BINDING_PROTOCOL                *DriverBinding;
40128a00297189c323096aae8e2975de94e8549613cyshang  UINTN                                      NumberOfSortedDriverBindingProtocols;
40228a00297189c323096aae8e2975de94e8549613cyshang  EFI_DRIVER_BINDING_PROTOCOL                **SortedDriverBindingProtocols;
40328a00297189c323096aae8e2975de94e8549613cyshang  UINT32                                     HighestVersion;
40428a00297189c323096aae8e2975de94e8549613cyshang  UINTN                                      HighestIndex;
40528a00297189c323096aae8e2975de94e8549613cyshang  UINTN                                      SortIndex;
40628a00297189c323096aae8e2975de94e8549613cyshang  BOOLEAN                                    OneStarted;
40728a00297189c323096aae8e2975de94e8549613cyshang  BOOLEAN                                    DriverFound;
40828a00297189c323096aae8e2975de94e8549613cyshang  EFI_HANDLE                                 DriverBindingHandle;
40928a00297189c323096aae8e2975de94e8549613cyshang
41028a00297189c323096aae8e2975de94e8549613cyshang  //
41128a00297189c323096aae8e2975de94e8549613cyshang  // DriverBindingHandle is used for performance measurement, initialize it here just in case.
41228a00297189c323096aae8e2975de94e8549613cyshang  //
41328a00297189c323096aae8e2975de94e8549613cyshang  DriverBindingHandle                   = NULL;
41428a00297189c323096aae8e2975de94e8549613cyshang  //
41528a00297189c323096aae8e2975de94e8549613cyshang  // Initialize local variables
41628a00297189c323096aae8e2975de94e8549613cyshang  //
41728a00297189c323096aae8e2975de94e8549613cyshang  DriverBindingHandleCount              = 0;
41828a00297189c323096aae8e2975de94e8549613cyshang  DriverBindingHandleBuffer             = NULL;
41928a00297189c323096aae8e2975de94e8549613cyshang  NumberOfSortedDriverBindingProtocols  = 0;
42028a00297189c323096aae8e2975de94e8549613cyshang  SortedDriverBindingProtocols          = NULL;
42128a00297189c323096aae8e2975de94e8549613cyshang
42228a00297189c323096aae8e2975de94e8549613cyshang  //
42328a00297189c323096aae8e2975de94e8549613cyshang  // Get list of all Driver Binding Protocol Instances
42428a00297189c323096aae8e2975de94e8549613cyshang  //
42528a00297189c323096aae8e2975de94e8549613cyshang  Status = CoreLocateHandleBuffer (
42628a00297189c323096aae8e2975de94e8549613cyshang             ByProtocol,
42728a00297189c323096aae8e2975de94e8549613cyshang             &gEfiDriverBindingProtocolGuid,
42828a00297189c323096aae8e2975de94e8549613cyshang             NULL,
42928a00297189c323096aae8e2975de94e8549613cyshang             &DriverBindingHandleCount,
43028a00297189c323096aae8e2975de94e8549613cyshang             &DriverBindingHandleBuffer
43128a00297189c323096aae8e2975de94e8549613cyshang             );
43228a00297189c323096aae8e2975de94e8549613cyshang  if (EFI_ERROR (Status) || (DriverBindingHandleCount == 0)) {
43328a00297189c323096aae8e2975de94e8549613cyshang    return EFI_NOT_FOUND;
43428a00297189c323096aae8e2975de94e8549613cyshang  }
43528a00297189c323096aae8e2975de94e8549613cyshang
43628a00297189c323096aae8e2975de94e8549613cyshang  //
43728a00297189c323096aae8e2975de94e8549613cyshang  // Allocate a duplicate array for the sorted Driver Binding Protocol Instances
43828a00297189c323096aae8e2975de94e8549613cyshang  //
43928a00297189c323096aae8e2975de94e8549613cyshang  SortedDriverBindingProtocols = CoreAllocateBootServicesPool (sizeof (VOID *) * DriverBindingHandleCount);
44028a00297189c323096aae8e2975de94e8549613cyshang  if (SortedDriverBindingProtocols == NULL) {
44128a00297189c323096aae8e2975de94e8549613cyshang    CoreFreePool (DriverBindingHandleBuffer);
44228a00297189c323096aae8e2975de94e8549613cyshang    return EFI_OUT_OF_RESOURCES;
44328a00297189c323096aae8e2975de94e8549613cyshang  }
44428a00297189c323096aae8e2975de94e8549613cyshang
44528a00297189c323096aae8e2975de94e8549613cyshang  //
44628a00297189c323096aae8e2975de94e8549613cyshang  // Add Driver Binding Protocols from Context Driver Image Handles first
44728a00297189c323096aae8e2975de94e8549613cyshang  //
44828a00297189c323096aae8e2975de94e8549613cyshang  if (ContextDriverImageHandles != NULL) {
44928a00297189c323096aae8e2975de94e8549613cyshang    for (Index = 0; ContextDriverImageHandles[Index] != NULL; Index++) {
45028a00297189c323096aae8e2975de94e8549613cyshang      AddSortedDriverBindingProtocol (
45128a00297189c323096aae8e2975de94e8549613cyshang        ContextDriverImageHandles[Index],
45228a00297189c323096aae8e2975de94e8549613cyshang        &NumberOfSortedDriverBindingProtocols,
45328a00297189c323096aae8e2975de94e8549613cyshang        SortedDriverBindingProtocols,
45428a00297189c323096aae8e2975de94e8549613cyshang        DriverBindingHandleCount,
45528a00297189c323096aae8e2975de94e8549613cyshang        DriverBindingHandleBuffer
45628a00297189c323096aae8e2975de94e8549613cyshang        );
45728a00297189c323096aae8e2975de94e8549613cyshang    }
45828a00297189c323096aae8e2975de94e8549613cyshang  }
45928a00297189c323096aae8e2975de94e8549613cyshang
46028a00297189c323096aae8e2975de94e8549613cyshang  //
46128a00297189c323096aae8e2975de94e8549613cyshang  // Add the Platform Driver Override Protocol drivers for ControllerHandle next
46228a00297189c323096aae8e2975de94e8549613cyshang  //
46328a00297189c323096aae8e2975de94e8549613cyshang  Status = CoreLocateProtocol (
46428a00297189c323096aae8e2975de94e8549613cyshang             &gEfiPlatformDriverOverrideProtocolGuid,
46528a00297189c323096aae8e2975de94e8549613cyshang             NULL,
46628a00297189c323096aae8e2975de94e8549613cyshang             (VOID **)&PlatformDriverOverride
46728a00297189c323096aae8e2975de94e8549613cyshang             );
46828a00297189c323096aae8e2975de94e8549613cyshang  if (!EFI_ERROR (Status) && (PlatformDriverOverride != NULL)) {
46928a00297189c323096aae8e2975de94e8549613cyshang    DriverImageHandle = NULL;
47028a00297189c323096aae8e2975de94e8549613cyshang    do {
47128a00297189c323096aae8e2975de94e8549613cyshang      Status = PlatformDriverOverride->GetDriver (
47228a00297189c323096aae8e2975de94e8549613cyshang                                         PlatformDriverOverride,
47328a00297189c323096aae8e2975de94e8549613cyshang                                         ControllerHandle,
47428a00297189c323096aae8e2975de94e8549613cyshang                                         &DriverImageHandle
47528a00297189c323096aae8e2975de94e8549613cyshang                                         );
47628a00297189c323096aae8e2975de94e8549613cyshang      if (!EFI_ERROR (Status)) {
47728a00297189c323096aae8e2975de94e8549613cyshang        AddSortedDriverBindingProtocol (
47828a00297189c323096aae8e2975de94e8549613cyshang          DriverImageHandle,
47928a00297189c323096aae8e2975de94e8549613cyshang          &NumberOfSortedDriverBindingProtocols,
48028a00297189c323096aae8e2975de94e8549613cyshang          SortedDriverBindingProtocols,
48128a00297189c323096aae8e2975de94e8549613cyshang          DriverBindingHandleCount,
48228a00297189c323096aae8e2975de94e8549613cyshang          DriverBindingHandleBuffer
48328a00297189c323096aae8e2975de94e8549613cyshang          );
48428a00297189c323096aae8e2975de94e8549613cyshang      }
48528a00297189c323096aae8e2975de94e8549613cyshang    } while (!EFI_ERROR (Status));
48628a00297189c323096aae8e2975de94e8549613cyshang  }
48728a00297189c323096aae8e2975de94e8549613cyshang
48828a00297189c323096aae8e2975de94e8549613cyshang  //
48928a00297189c323096aae8e2975de94e8549613cyshang  // Get the Bus Specific Driver Override Protocol instance on the Controller Handle
49028a00297189c323096aae8e2975de94e8549613cyshang  //
49128a00297189c323096aae8e2975de94e8549613cyshang  Status = CoreHandleProtocol(
49228a00297189c323096aae8e2975de94e8549613cyshang             ControllerHandle,
49328a00297189c323096aae8e2975de94e8549613cyshang             &gEfiBusSpecificDriverOverrideProtocolGuid,
49428a00297189c323096aae8e2975de94e8549613cyshang             (VOID **)&BusSpecificDriverOverride
49528a00297189c323096aae8e2975de94e8549613cyshang             );
49628a00297189c323096aae8e2975de94e8549613cyshang  if (!EFI_ERROR (Status) && (BusSpecificDriverOverride != NULL)) {
49728a00297189c323096aae8e2975de94e8549613cyshang    DriverImageHandle = NULL;
49828a00297189c323096aae8e2975de94e8549613cyshang    do {
49928a00297189c323096aae8e2975de94e8549613cyshang      Status = BusSpecificDriverOverride->GetDriver (
50028a00297189c323096aae8e2975de94e8549613cyshang                                            BusSpecificDriverOverride,
50128a00297189c323096aae8e2975de94e8549613cyshang                                            &DriverImageHandle
50228a00297189c323096aae8e2975de94e8549613cyshang                                            );
50328a00297189c323096aae8e2975de94e8549613cyshang      if (!EFI_ERROR (Status)) {
50428a00297189c323096aae8e2975de94e8549613cyshang        AddSortedDriverBindingProtocol (
50528a00297189c323096aae8e2975de94e8549613cyshang          DriverImageHandle,
50628a00297189c323096aae8e2975de94e8549613cyshang          &NumberOfSortedDriverBindingProtocols,
50728a00297189c323096aae8e2975de94e8549613cyshang          SortedDriverBindingProtocols,
50828a00297189c323096aae8e2975de94e8549613cyshang          DriverBindingHandleCount,
50928a00297189c323096aae8e2975de94e8549613cyshang          DriverBindingHandleBuffer
51028a00297189c323096aae8e2975de94e8549613cyshang          );
51128a00297189c323096aae8e2975de94e8549613cyshang      }
51228a00297189c323096aae8e2975de94e8549613cyshang    } while (!EFI_ERROR (Status));
51328a00297189c323096aae8e2975de94e8549613cyshang  }
51428a00297189c323096aae8e2975de94e8549613cyshang
51528a00297189c323096aae8e2975de94e8549613cyshang  //
51628a00297189c323096aae8e2975de94e8549613cyshang  // Then add all the remaining Driver Binding Protocols
51728a00297189c323096aae8e2975de94e8549613cyshang  //
51828a00297189c323096aae8e2975de94e8549613cyshang  SortIndex = NumberOfSortedDriverBindingProtocols;
51928a00297189c323096aae8e2975de94e8549613cyshang  for (Index = 0; Index < DriverBindingHandleCount; Index++) {
52028a00297189c323096aae8e2975de94e8549613cyshang    AddSortedDriverBindingProtocol (
52128a00297189c323096aae8e2975de94e8549613cyshang      DriverBindingHandleBuffer[Index],
52228a00297189c323096aae8e2975de94e8549613cyshang      &NumberOfSortedDriverBindingProtocols,
52328a00297189c323096aae8e2975de94e8549613cyshang      SortedDriverBindingProtocols,
52428a00297189c323096aae8e2975de94e8549613cyshang      DriverBindingHandleCount,
52528a00297189c323096aae8e2975de94e8549613cyshang      DriverBindingHandleBuffer
52628a00297189c323096aae8e2975de94e8549613cyshang      );
52728a00297189c323096aae8e2975de94e8549613cyshang  }
52828a00297189c323096aae8e2975de94e8549613cyshang
52928a00297189c323096aae8e2975de94e8549613cyshang  //
53028a00297189c323096aae8e2975de94e8549613cyshang  // Free the Driver Binding Handle Buffer
53128a00297189c323096aae8e2975de94e8549613cyshang  //
53228a00297189c323096aae8e2975de94e8549613cyshang  CoreFreePool (DriverBindingHandleBuffer);
53328a00297189c323096aae8e2975de94e8549613cyshang
53428a00297189c323096aae8e2975de94e8549613cyshang  //
53585658066182d23e210209299770edaef26d09085mdkinney  // If the number of Driver Binding Protocols has increased since this function started, then return
53685658066182d23e210209299770edaef26d09085mdkinney  // EFI_NOT_READY, so it will be restarted
53785658066182d23e210209299770edaef26d09085mdkinney  //
53885658066182d23e210209299770edaef26d09085mdkinney  if (NumberOfSortedDriverBindingProtocols > DriverBindingHandleCount) {
53985658066182d23e210209299770edaef26d09085mdkinney    //
54085658066182d23e210209299770edaef26d09085mdkinney    // Free any buffers that were allocated with AllocatePool()
54185658066182d23e210209299770edaef26d09085mdkinney    //
54285658066182d23e210209299770edaef26d09085mdkinney    CoreFreePool (SortedDriverBindingProtocols);
54385658066182d23e210209299770edaef26d09085mdkinney
54485658066182d23e210209299770edaef26d09085mdkinney    return EFI_NOT_READY;
54585658066182d23e210209299770edaef26d09085mdkinney  }
54685658066182d23e210209299770edaef26d09085mdkinney
54785658066182d23e210209299770edaef26d09085mdkinney  //
54828a00297189c323096aae8e2975de94e8549613cyshang  // Sort the remaining DriverBinding Protocol based on their Version field from
54928a00297189c323096aae8e2975de94e8549613cyshang  // highest to lowest.
55028a00297189c323096aae8e2975de94e8549613cyshang  //
55128a00297189c323096aae8e2975de94e8549613cyshang  for ( ; SortIndex < NumberOfSortedDriverBindingProtocols; SortIndex++) {
55228a00297189c323096aae8e2975de94e8549613cyshang    HighestVersion = SortedDriverBindingProtocols[SortIndex]->Version;
55328a00297189c323096aae8e2975de94e8549613cyshang    HighestIndex   = SortIndex;
55428a00297189c323096aae8e2975de94e8549613cyshang    for (Index = SortIndex + 1; Index < NumberOfSortedDriverBindingProtocols; Index++) {
55528a00297189c323096aae8e2975de94e8549613cyshang      if (SortedDriverBindingProtocols[Index]->Version > HighestVersion) {
55628a00297189c323096aae8e2975de94e8549613cyshang        HighestVersion = SortedDriverBindingProtocols[Index]->Version;
55728a00297189c323096aae8e2975de94e8549613cyshang        HighestIndex   = Index;
55828a00297189c323096aae8e2975de94e8549613cyshang      }
55928a00297189c323096aae8e2975de94e8549613cyshang    }
56028a00297189c323096aae8e2975de94e8549613cyshang    if (SortIndex != HighestIndex) {
56128a00297189c323096aae8e2975de94e8549613cyshang      DriverBinding = SortedDriverBindingProtocols[SortIndex];
56228a00297189c323096aae8e2975de94e8549613cyshang      SortedDriverBindingProtocols[SortIndex] = SortedDriverBindingProtocols[HighestIndex];
56328a00297189c323096aae8e2975de94e8549613cyshang      SortedDriverBindingProtocols[HighestIndex] = DriverBinding;
56428a00297189c323096aae8e2975de94e8549613cyshang    }
56528a00297189c323096aae8e2975de94e8549613cyshang  }
56628a00297189c323096aae8e2975de94e8549613cyshang
56728a00297189c323096aae8e2975de94e8549613cyshang  //
56828a00297189c323096aae8e2975de94e8549613cyshang  // Loop until no more drivers can be started on ControllerHandle
56928a00297189c323096aae8e2975de94e8549613cyshang  //
57028a00297189c323096aae8e2975de94e8549613cyshang  OneStarted = FALSE;
57128a00297189c323096aae8e2975de94e8549613cyshang  do {
57228a00297189c323096aae8e2975de94e8549613cyshang
57328a00297189c323096aae8e2975de94e8549613cyshang    //
57428a00297189c323096aae8e2975de94e8549613cyshang    // Loop through the sorted Driver Binding Protocol Instances in order, and see if
57528a00297189c323096aae8e2975de94e8549613cyshang    // any of the Driver Binding Protocols support the controller specified by
57628a00297189c323096aae8e2975de94e8549613cyshang    // ControllerHandle.
57728a00297189c323096aae8e2975de94e8549613cyshang    //
57828a00297189c323096aae8e2975de94e8549613cyshang    DriverBinding = NULL;
57928a00297189c323096aae8e2975de94e8549613cyshang    DriverFound = FALSE;
58028a00297189c323096aae8e2975de94e8549613cyshang    for (Index = 0; (Index < NumberOfSortedDriverBindingProtocols) && !DriverFound; Index++) {
58128a00297189c323096aae8e2975de94e8549613cyshang      if (SortedDriverBindingProtocols[Index] != NULL) {
58228a00297189c323096aae8e2975de94e8549613cyshang        DriverBinding = SortedDriverBindingProtocols[Index];
58328a00297189c323096aae8e2975de94e8549613cyshang        Status = DriverBinding->Supported(
58428a00297189c323096aae8e2975de94e8549613cyshang                                  DriverBinding,
58528a00297189c323096aae8e2975de94e8549613cyshang                                  ControllerHandle,
58628a00297189c323096aae8e2975de94e8549613cyshang                                  RemainingDevicePath
58728a00297189c323096aae8e2975de94e8549613cyshang                                  );
58828a00297189c323096aae8e2975de94e8549613cyshang        if (!EFI_ERROR (Status)) {
58928a00297189c323096aae8e2975de94e8549613cyshang          SortedDriverBindingProtocols[Index] = NULL;
59028a00297189c323096aae8e2975de94e8549613cyshang          DriverFound = TRUE;
59128a00297189c323096aae8e2975de94e8549613cyshang
59228a00297189c323096aae8e2975de94e8549613cyshang          //
59328a00297189c323096aae8e2975de94e8549613cyshang          // A driver was found that supports ControllerHandle, so attempt to start the driver
59428a00297189c323096aae8e2975de94e8549613cyshang          // on ControllerHandle.
59528a00297189c323096aae8e2975de94e8549613cyshang          //
59628a00297189c323096aae8e2975de94e8549613cyshang          PERF_CODE_BEGIN ();
59728a00297189c323096aae8e2975de94e8549613cyshang          GetHandleFromDriverBinding (DriverBinding, &DriverBindingHandle);
59828a00297189c323096aae8e2975de94e8549613cyshang          PERF_CODE_END ();
59928a00297189c323096aae8e2975de94e8549613cyshang
60028a00297189c323096aae8e2975de94e8549613cyshang          PERF_START (DriverBindingHandle, DRIVERBINDING_START_TOK, NULL, 0);
60128a00297189c323096aae8e2975de94e8549613cyshang          Status = DriverBinding->Start (
60228a00297189c323096aae8e2975de94e8549613cyshang                                    DriverBinding,
60328a00297189c323096aae8e2975de94e8549613cyshang                                    ControllerHandle,
60428a00297189c323096aae8e2975de94e8549613cyshang                                    RemainingDevicePath
60528a00297189c323096aae8e2975de94e8549613cyshang                                    );
60628a00297189c323096aae8e2975de94e8549613cyshang          PERF_END (DriverBindingHandle, DRIVERBINDING_START_TOK, NULL, 0);
60728a00297189c323096aae8e2975de94e8549613cyshang
60828a00297189c323096aae8e2975de94e8549613cyshang          if (!EFI_ERROR (Status)) {
60928a00297189c323096aae8e2975de94e8549613cyshang            //
61028a00297189c323096aae8e2975de94e8549613cyshang            // The driver was successfully started on ControllerHandle, so set a flag
61128a00297189c323096aae8e2975de94e8549613cyshang            //
61228a00297189c323096aae8e2975de94e8549613cyshang            OneStarted = TRUE;
61328a00297189c323096aae8e2975de94e8549613cyshang          }
61428a00297189c323096aae8e2975de94e8549613cyshang        }
61528a00297189c323096aae8e2975de94e8549613cyshang      }
61628a00297189c323096aae8e2975de94e8549613cyshang    }
61728a00297189c323096aae8e2975de94e8549613cyshang  } while (DriverFound);
61828a00297189c323096aae8e2975de94e8549613cyshang
61928a00297189c323096aae8e2975de94e8549613cyshang  //
62028a00297189c323096aae8e2975de94e8549613cyshang  // Free any buffers that were allocated with AllocatePool()
62128a00297189c323096aae8e2975de94e8549613cyshang  //
62228a00297189c323096aae8e2975de94e8549613cyshang  CoreFreePool (SortedDriverBindingProtocols);
62328a00297189c323096aae8e2975de94e8549613cyshang
62428a00297189c323096aae8e2975de94e8549613cyshang  //
62528a00297189c323096aae8e2975de94e8549613cyshang  // If at least one driver was started on ControllerHandle, then return EFI_SUCCESS.
62628a00297189c323096aae8e2975de94e8549613cyshang  //
62728a00297189c323096aae8e2975de94e8549613cyshang  if (OneStarted) {
62828a00297189c323096aae8e2975de94e8549613cyshang    return EFI_SUCCESS;
62928a00297189c323096aae8e2975de94e8549613cyshang  }
63028a00297189c323096aae8e2975de94e8549613cyshang
63128a00297189c323096aae8e2975de94e8549613cyshang  //
63228a00297189c323096aae8e2975de94e8549613cyshang  // If no drivers started and RemainingDevicePath is an End Device Path Node, then return EFI_SUCCESS
63328a00297189c323096aae8e2975de94e8549613cyshang  //
63428a00297189c323096aae8e2975de94e8549613cyshang  if (RemainingDevicePath != NULL) {
63528a00297189c323096aae8e2975de94e8549613cyshang    if (IsDevicePathEnd (RemainingDevicePath)) {
63628a00297189c323096aae8e2975de94e8549613cyshang      return EFI_SUCCESS;
63728a00297189c323096aae8e2975de94e8549613cyshang    }
63828a00297189c323096aae8e2975de94e8549613cyshang  }
63928a00297189c323096aae8e2975de94e8549613cyshang
64028a00297189c323096aae8e2975de94e8549613cyshang  //
64128a00297189c323096aae8e2975de94e8549613cyshang  // Otherwise, no drivers were started on ControllerHandle, so return EFI_NOT_FOUND
64228a00297189c323096aae8e2975de94e8549613cyshang  //
64328a00297189c323096aae8e2975de94e8549613cyshang  return EFI_NOT_FOUND;
64428a00297189c323096aae8e2975de94e8549613cyshang}
64528a00297189c323096aae8e2975de94e8549613cyshang
64628a00297189c323096aae8e2975de94e8549613cyshang
64728a00297189c323096aae8e2975de94e8549613cyshangEFI_STATUS
64828a00297189c323096aae8e2975de94e8549613cyshangEFIAPI
64928a00297189c323096aae8e2975de94e8549613cyshangCoreDisconnectController (
65028a00297189c323096aae8e2975de94e8549613cyshang  IN  EFI_HANDLE  ControllerHandle,
65128a00297189c323096aae8e2975de94e8549613cyshang  IN  EFI_HANDLE  DriverImageHandle  OPTIONAL,
65228a00297189c323096aae8e2975de94e8549613cyshang  IN  EFI_HANDLE  ChildHandle        OPTIONAL
65328a00297189c323096aae8e2975de94e8549613cyshang  )
65428a00297189c323096aae8e2975de94e8549613cyshang/*++
65528a00297189c323096aae8e2975de94e8549613cyshang
65628a00297189c323096aae8e2975de94e8549613cyshangRoutine Description:
65728a00297189c323096aae8e2975de94e8549613cyshang
65828a00297189c323096aae8e2975de94e8549613cyshang  Disonnects a controller from a driver
65928a00297189c323096aae8e2975de94e8549613cyshang
66028a00297189c323096aae8e2975de94e8549613cyshangArguments:
66128a00297189c323096aae8e2975de94e8549613cyshang
66228a00297189c323096aae8e2975de94e8549613cyshang  ControllerHandle  - ControllerHandle The handle of the controller from which driver(s)
66328a00297189c323096aae8e2975de94e8549613cyshang                        are to be disconnected.
66428a00297189c323096aae8e2975de94e8549613cyshang  DriverImageHandle - DriverImageHandle The driver to disconnect from ControllerHandle.
66528a00297189c323096aae8e2975de94e8549613cyshang  ChildHandle       - ChildHandle The handle of the child to destroy.
66628a00297189c323096aae8e2975de94e8549613cyshang
66728a00297189c323096aae8e2975de94e8549613cyshangReturns:
66828a00297189c323096aae8e2975de94e8549613cyshang
66928a00297189c323096aae8e2975de94e8549613cyshang  EFI_SUCCESS           -  One or more drivers were disconnected from the controller.
67028a00297189c323096aae8e2975de94e8549613cyshang  EFI_SUCCESS           -  On entry, no drivers are managing ControllerHandle.
67128a00297189c323096aae8e2975de94e8549613cyshang  EFI_SUCCESS           -  DriverImageHandle is not NULL, and on entry DriverImageHandle is not managing ControllerHandle.
67228a00297189c323096aae8e2975de94e8549613cyshang  EFI_INVALID_PARAMETER -  ControllerHandle is not a valid EFI_HANDLE.
67328a00297189c323096aae8e2975de94e8549613cyshang  EFI_INVALID_PARAMETER -  DriverImageHandle is not NULL, and it is not a valid EFI_HANDLE.
67428a00297189c323096aae8e2975de94e8549613cyshang  EFI_INVALID_PARAMETER -  ChildHandle is not NULL, and it is not a valid EFI_HANDLE.
67528a00297189c323096aae8e2975de94e8549613cyshang  EFI_OUT_OF_RESOURCES  -  There are not enough resources available to disconnect any drivers from ControllerHandle.
67628a00297189c323096aae8e2975de94e8549613cyshang  EFI_DEVICE_ERROR      -  The controller could not be disconnected because of a device error.
67728a00297189c323096aae8e2975de94e8549613cyshang
67828a00297189c323096aae8e2975de94e8549613cyshang--*/
67928a00297189c323096aae8e2975de94e8549613cyshang{
68028a00297189c323096aae8e2975de94e8549613cyshang  EFI_STATUS                          Status;
68128a00297189c323096aae8e2975de94e8549613cyshang  IHANDLE                             *Handle;
68228a00297189c323096aae8e2975de94e8549613cyshang  EFI_HANDLE                          *DriverImageHandleBuffer;
68328a00297189c323096aae8e2975de94e8549613cyshang  EFI_HANDLE                          *ChildBuffer;
68428a00297189c323096aae8e2975de94e8549613cyshang  UINTN                               Index;
68528a00297189c323096aae8e2975de94e8549613cyshang  UINTN                               HandleIndex;
68628a00297189c323096aae8e2975de94e8549613cyshang  UINTN                               DriverImageHandleCount;
68728a00297189c323096aae8e2975de94e8549613cyshang  UINTN                               ChildrenToStop;
68828a00297189c323096aae8e2975de94e8549613cyshang  UINTN                               ChildBufferCount;
68928a00297189c323096aae8e2975de94e8549613cyshang  UINTN                               StopCount;
69028a00297189c323096aae8e2975de94e8549613cyshang  BOOLEAN                             Duplicate;
69128a00297189c323096aae8e2975de94e8549613cyshang  BOOLEAN                             ChildHandleValid;
69228a00297189c323096aae8e2975de94e8549613cyshang  BOOLEAN                             DriverImageHandleValid;
69328a00297189c323096aae8e2975de94e8549613cyshang  LIST_ENTRY                          *Link;
69428a00297189c323096aae8e2975de94e8549613cyshang  LIST_ENTRY                          *ProtLink;
69528a00297189c323096aae8e2975de94e8549613cyshang  OPEN_PROTOCOL_DATA                  *OpenData;
69628a00297189c323096aae8e2975de94e8549613cyshang  PROTOCOL_INTERFACE                  *Prot;
69728a00297189c323096aae8e2975de94e8549613cyshang  EFI_DRIVER_BINDING_PROTOCOL         *DriverBinding;
69885658066182d23e210209299770edaef26d09085mdkinney  EFI_HANDLE                          *LoadedImageHandleBuffer;
69985658066182d23e210209299770edaef26d09085mdkinney  UINTN                               LoadedImageHandleCount;
70085658066182d23e210209299770edaef26d09085mdkinney  LOADED_IMAGE_PRIVATE_DATA           *Image;
70128a00297189c323096aae8e2975de94e8549613cyshang
70228a00297189c323096aae8e2975de94e8549613cyshang  //
70328a00297189c323096aae8e2975de94e8549613cyshang  // Make sure ControllerHandle is valid
70428a00297189c323096aae8e2975de94e8549613cyshang  //
70528a00297189c323096aae8e2975de94e8549613cyshang  Status = CoreValidateHandle (ControllerHandle);
70628a00297189c323096aae8e2975de94e8549613cyshang  if (EFI_ERROR (Status)) {
70728a00297189c323096aae8e2975de94e8549613cyshang    return Status;
70828a00297189c323096aae8e2975de94e8549613cyshang  }
70928a00297189c323096aae8e2975de94e8549613cyshang
71028a00297189c323096aae8e2975de94e8549613cyshang  //
71128a00297189c323096aae8e2975de94e8549613cyshang  // Make sure ChildHandle is valid if it is not NULL
71228a00297189c323096aae8e2975de94e8549613cyshang  //
71328a00297189c323096aae8e2975de94e8549613cyshang  if (ChildHandle != NULL) {
71428a00297189c323096aae8e2975de94e8549613cyshang    Status = CoreValidateHandle (ChildHandle);
71528a00297189c323096aae8e2975de94e8549613cyshang    if (EFI_ERROR (Status)) {
71628a00297189c323096aae8e2975de94e8549613cyshang      return Status;
71728a00297189c323096aae8e2975de94e8549613cyshang    }
71828a00297189c323096aae8e2975de94e8549613cyshang  }
71928a00297189c323096aae8e2975de94e8549613cyshang
72028a00297189c323096aae8e2975de94e8549613cyshang  Handle = ControllerHandle;
72128a00297189c323096aae8e2975de94e8549613cyshang
72228a00297189c323096aae8e2975de94e8549613cyshang  //
72328a00297189c323096aae8e2975de94e8549613cyshang  // Get list of drivers that are currently managing ControllerHandle
72428a00297189c323096aae8e2975de94e8549613cyshang  //
72528a00297189c323096aae8e2975de94e8549613cyshang  DriverImageHandleBuffer = NULL;
72628a00297189c323096aae8e2975de94e8549613cyshang  DriverImageHandleCount  = 1;
72728a00297189c323096aae8e2975de94e8549613cyshang
72828a00297189c323096aae8e2975de94e8549613cyshang  if (DriverImageHandle == NULL) {
72928a00297189c323096aae8e2975de94e8549613cyshang    //
73028a00297189c323096aae8e2975de94e8549613cyshang    // Look at each protocol interface for a match
73128a00297189c323096aae8e2975de94e8549613cyshang    //
73228a00297189c323096aae8e2975de94e8549613cyshang    DriverImageHandleCount = 0;
73328a00297189c323096aae8e2975de94e8549613cyshang
73428a00297189c323096aae8e2975de94e8549613cyshang    CoreAcquireProtocolLock ();
73528a00297189c323096aae8e2975de94e8549613cyshang    for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
73628a00297189c323096aae8e2975de94e8549613cyshang      Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
73728a00297189c323096aae8e2975de94e8549613cyshang      for (ProtLink = Prot->OpenList.ForwardLink;
73828a00297189c323096aae8e2975de94e8549613cyshang           ProtLink != &Prot->OpenList;
73928a00297189c323096aae8e2975de94e8549613cyshang           ProtLink = ProtLink->ForwardLink) {
74028a00297189c323096aae8e2975de94e8549613cyshang        OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
74128a00297189c323096aae8e2975de94e8549613cyshang        if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
74228a00297189c323096aae8e2975de94e8549613cyshang          DriverImageHandleCount++;
74328a00297189c323096aae8e2975de94e8549613cyshang        }
74428a00297189c323096aae8e2975de94e8549613cyshang      }
74528a00297189c323096aae8e2975de94e8549613cyshang    }
74628a00297189c323096aae8e2975de94e8549613cyshang    CoreReleaseProtocolLock ();
74728a00297189c323096aae8e2975de94e8549613cyshang
74828a00297189c323096aae8e2975de94e8549613cyshang    //
74928a00297189c323096aae8e2975de94e8549613cyshang    // If there are no drivers managing this controller, then return EFI_SUCCESS
75028a00297189c323096aae8e2975de94e8549613cyshang    //
75128a00297189c323096aae8e2975de94e8549613cyshang    if (DriverImageHandleCount == 0) {
75228a00297189c323096aae8e2975de94e8549613cyshang      Status = EFI_SUCCESS;
75328a00297189c323096aae8e2975de94e8549613cyshang      goto Done;
75428a00297189c323096aae8e2975de94e8549613cyshang    }
75528a00297189c323096aae8e2975de94e8549613cyshang
75628a00297189c323096aae8e2975de94e8549613cyshang    DriverImageHandleBuffer = CoreAllocateBootServicesPool (sizeof (EFI_HANDLE) * DriverImageHandleCount);
75728a00297189c323096aae8e2975de94e8549613cyshang    if (DriverImageHandleBuffer == NULL) {
75828a00297189c323096aae8e2975de94e8549613cyshang      Status = EFI_OUT_OF_RESOURCES;
75928a00297189c323096aae8e2975de94e8549613cyshang      goto Done;
76028a00297189c323096aae8e2975de94e8549613cyshang    }
76128a00297189c323096aae8e2975de94e8549613cyshang
76228a00297189c323096aae8e2975de94e8549613cyshang    DriverImageHandleCount = 0;
76328a00297189c323096aae8e2975de94e8549613cyshang
76428a00297189c323096aae8e2975de94e8549613cyshang    CoreAcquireProtocolLock ();
76528a00297189c323096aae8e2975de94e8549613cyshang    for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
76628a00297189c323096aae8e2975de94e8549613cyshang      Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
76728a00297189c323096aae8e2975de94e8549613cyshang      for (ProtLink = Prot->OpenList.ForwardLink;
76828a00297189c323096aae8e2975de94e8549613cyshang           ProtLink != &Prot->OpenList;
76928a00297189c323096aae8e2975de94e8549613cyshang           ProtLink = ProtLink->ForwardLink) {
77028a00297189c323096aae8e2975de94e8549613cyshang        OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
77128a00297189c323096aae8e2975de94e8549613cyshang        if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
77228a00297189c323096aae8e2975de94e8549613cyshang          Duplicate = FALSE;
77328a00297189c323096aae8e2975de94e8549613cyshang          for (Index = 0; Index< DriverImageHandleCount; Index++) {
77428a00297189c323096aae8e2975de94e8549613cyshang            if (DriverImageHandleBuffer[Index] == OpenData->AgentHandle) {
77528a00297189c323096aae8e2975de94e8549613cyshang              Duplicate = TRUE;
77628a00297189c323096aae8e2975de94e8549613cyshang              break;
77728a00297189c323096aae8e2975de94e8549613cyshang            }
77828a00297189c323096aae8e2975de94e8549613cyshang          }
77928a00297189c323096aae8e2975de94e8549613cyshang          if (!Duplicate) {
78028a00297189c323096aae8e2975de94e8549613cyshang            DriverImageHandleBuffer[DriverImageHandleCount] = OpenData->AgentHandle;
78128a00297189c323096aae8e2975de94e8549613cyshang            DriverImageHandleCount++;
78228a00297189c323096aae8e2975de94e8549613cyshang          }
78328a00297189c323096aae8e2975de94e8549613cyshang        }
78428a00297189c323096aae8e2975de94e8549613cyshang      }
78528a00297189c323096aae8e2975de94e8549613cyshang    }
78628a00297189c323096aae8e2975de94e8549613cyshang    CoreReleaseProtocolLock ();
78728a00297189c323096aae8e2975de94e8549613cyshang  }
78828a00297189c323096aae8e2975de94e8549613cyshang
78928a00297189c323096aae8e2975de94e8549613cyshang  StopCount = 0;
79028a00297189c323096aae8e2975de94e8549613cyshang  for (HandleIndex = 0; HandleIndex < DriverImageHandleCount; HandleIndex++) {
79128a00297189c323096aae8e2975de94e8549613cyshang
79228a00297189c323096aae8e2975de94e8549613cyshang    if (DriverImageHandleBuffer != NULL) {
79328a00297189c323096aae8e2975de94e8549613cyshang      DriverImageHandle = DriverImageHandleBuffer[HandleIndex];
79428a00297189c323096aae8e2975de94e8549613cyshang    }
79528a00297189c323096aae8e2975de94e8549613cyshang
79628a00297189c323096aae8e2975de94e8549613cyshang    //
79728a00297189c323096aae8e2975de94e8549613cyshang    // Get the Driver Binding Protocol of the driver that is managing this controller
79828a00297189c323096aae8e2975de94e8549613cyshang    //
79928a00297189c323096aae8e2975de94e8549613cyshang    Status = CoreHandleProtocol (
80028a00297189c323096aae8e2975de94e8549613cyshang               DriverImageHandle,
80128a00297189c323096aae8e2975de94e8549613cyshang               &gEfiDriverBindingProtocolGuid,
80228a00297189c323096aae8e2975de94e8549613cyshang               (VOID **)&DriverBinding
80328a00297189c323096aae8e2975de94e8549613cyshang               );
80428a00297189c323096aae8e2975de94e8549613cyshang    if (EFI_ERROR (Status)) {
80528a00297189c323096aae8e2975de94e8549613cyshang      Status = EFI_INVALID_PARAMETER;
80628a00297189c323096aae8e2975de94e8549613cyshang      goto Done;
80728a00297189c323096aae8e2975de94e8549613cyshang    }
80828a00297189c323096aae8e2975de94e8549613cyshang
80928a00297189c323096aae8e2975de94e8549613cyshang    //
81028a00297189c323096aae8e2975de94e8549613cyshang    // Look at each protocol interface for a match
81128a00297189c323096aae8e2975de94e8549613cyshang    //
81228a00297189c323096aae8e2975de94e8549613cyshang    DriverImageHandleValid = FALSE;
81328a00297189c323096aae8e2975de94e8549613cyshang    ChildBufferCount = 0;
81428a00297189c323096aae8e2975de94e8549613cyshang
81528a00297189c323096aae8e2975de94e8549613cyshang    CoreAcquireProtocolLock ();
81628a00297189c323096aae8e2975de94e8549613cyshang    for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
81728a00297189c323096aae8e2975de94e8549613cyshang      Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
81828a00297189c323096aae8e2975de94e8549613cyshang      for (ProtLink = Prot->OpenList.ForwardLink;
81928a00297189c323096aae8e2975de94e8549613cyshang           ProtLink != &Prot->OpenList;
82028a00297189c323096aae8e2975de94e8549613cyshang           ProtLink = ProtLink->ForwardLink) {
82128a00297189c323096aae8e2975de94e8549613cyshang        OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
82228a00297189c323096aae8e2975de94e8549613cyshang        if (OpenData->AgentHandle == DriverImageHandle) {
82328a00297189c323096aae8e2975de94e8549613cyshang          if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
82428a00297189c323096aae8e2975de94e8549613cyshang            ChildBufferCount++;
82528a00297189c323096aae8e2975de94e8549613cyshang          }
82628a00297189c323096aae8e2975de94e8549613cyshang          if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
82728a00297189c323096aae8e2975de94e8549613cyshang            DriverImageHandleValid = TRUE;
82828a00297189c323096aae8e2975de94e8549613cyshang          }
82928a00297189c323096aae8e2975de94e8549613cyshang        }
83028a00297189c323096aae8e2975de94e8549613cyshang      }
83128a00297189c323096aae8e2975de94e8549613cyshang    }
83228a00297189c323096aae8e2975de94e8549613cyshang    CoreReleaseProtocolLock ();
83328a00297189c323096aae8e2975de94e8549613cyshang
83428a00297189c323096aae8e2975de94e8549613cyshang    if (DriverImageHandleValid) {
83528a00297189c323096aae8e2975de94e8549613cyshang      ChildHandleValid = FALSE;
83628a00297189c323096aae8e2975de94e8549613cyshang      ChildBuffer = NULL;
83728a00297189c323096aae8e2975de94e8549613cyshang      if (ChildBufferCount != 0) {
83828a00297189c323096aae8e2975de94e8549613cyshang        ChildBuffer = CoreAllocateBootServicesPool (sizeof (EFI_HANDLE) * ChildBufferCount);
83928a00297189c323096aae8e2975de94e8549613cyshang        if (ChildBuffer == NULL) {
84028a00297189c323096aae8e2975de94e8549613cyshang          Status = EFI_OUT_OF_RESOURCES;
84128a00297189c323096aae8e2975de94e8549613cyshang          goto Done;
84228a00297189c323096aae8e2975de94e8549613cyshang        }
84328a00297189c323096aae8e2975de94e8549613cyshang
84428a00297189c323096aae8e2975de94e8549613cyshang        ChildBufferCount = 0;
84528a00297189c323096aae8e2975de94e8549613cyshang
84628a00297189c323096aae8e2975de94e8549613cyshang        CoreAcquireProtocolLock ();
84728a00297189c323096aae8e2975de94e8549613cyshang        for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
84828a00297189c323096aae8e2975de94e8549613cyshang          Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
84928a00297189c323096aae8e2975de94e8549613cyshang          for (ProtLink = Prot->OpenList.ForwardLink;
85028a00297189c323096aae8e2975de94e8549613cyshang               ProtLink != &Prot->OpenList;
85128a00297189c323096aae8e2975de94e8549613cyshang               ProtLink = ProtLink->ForwardLink) {
85228a00297189c323096aae8e2975de94e8549613cyshang            OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
85328a00297189c323096aae8e2975de94e8549613cyshang            if ((OpenData->AgentHandle == DriverImageHandle) &&
85428a00297189c323096aae8e2975de94e8549613cyshang                ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0)) {
85528a00297189c323096aae8e2975de94e8549613cyshang              Duplicate = FALSE;
85628a00297189c323096aae8e2975de94e8549613cyshang              for (Index = 0; Index < ChildBufferCount; Index++) {
85728a00297189c323096aae8e2975de94e8549613cyshang                if (ChildBuffer[Index] == OpenData->ControllerHandle) {
85828a00297189c323096aae8e2975de94e8549613cyshang                  Duplicate = TRUE;
85928a00297189c323096aae8e2975de94e8549613cyshang                  break;
86028a00297189c323096aae8e2975de94e8549613cyshang                }
86128a00297189c323096aae8e2975de94e8549613cyshang              }
86228a00297189c323096aae8e2975de94e8549613cyshang              if (!Duplicate) {
86328a00297189c323096aae8e2975de94e8549613cyshang                ChildBuffer[ChildBufferCount] = OpenData->ControllerHandle;
86428a00297189c323096aae8e2975de94e8549613cyshang                if (ChildHandle == ChildBuffer[ChildBufferCount]) {
86528a00297189c323096aae8e2975de94e8549613cyshang                  ChildHandleValid = TRUE;
86628a00297189c323096aae8e2975de94e8549613cyshang                }
86728a00297189c323096aae8e2975de94e8549613cyshang                ChildBufferCount++;
86828a00297189c323096aae8e2975de94e8549613cyshang              }
86928a00297189c323096aae8e2975de94e8549613cyshang            }
87028a00297189c323096aae8e2975de94e8549613cyshang          }
87128a00297189c323096aae8e2975de94e8549613cyshang        }
87228a00297189c323096aae8e2975de94e8549613cyshang        CoreReleaseProtocolLock ();
87328a00297189c323096aae8e2975de94e8549613cyshang      }
87428a00297189c323096aae8e2975de94e8549613cyshang
87528a00297189c323096aae8e2975de94e8549613cyshang      if (ChildHandle == NULL || ChildHandleValid) {
87628a00297189c323096aae8e2975de94e8549613cyshang        ChildrenToStop = 0;
87728a00297189c323096aae8e2975de94e8549613cyshang        Status = EFI_SUCCESS;
87828a00297189c323096aae8e2975de94e8549613cyshang        if (ChildBufferCount > 0) {
87928a00297189c323096aae8e2975de94e8549613cyshang          if (ChildHandle != NULL) {
88028a00297189c323096aae8e2975de94e8549613cyshang            ChildrenToStop = 1;
88128a00297189c323096aae8e2975de94e8549613cyshang            Status = DriverBinding->Stop (DriverBinding, ControllerHandle, ChildrenToStop, &ChildHandle);
88228a00297189c323096aae8e2975de94e8549613cyshang          } else {
88328a00297189c323096aae8e2975de94e8549613cyshang            ChildrenToStop = ChildBufferCount;
88428a00297189c323096aae8e2975de94e8549613cyshang            Status = DriverBinding->Stop (DriverBinding, ControllerHandle, ChildrenToStop, ChildBuffer);
88528a00297189c323096aae8e2975de94e8549613cyshang          }
88628a00297189c323096aae8e2975de94e8549613cyshang        }
88728a00297189c323096aae8e2975de94e8549613cyshang        if (!EFI_ERROR (Status) && ((ChildHandle == NULL) || (ChildBufferCount == ChildrenToStop))) {
88828a00297189c323096aae8e2975de94e8549613cyshang          Status = DriverBinding->Stop (DriverBinding, ControllerHandle, 0, NULL);
88928a00297189c323096aae8e2975de94e8549613cyshang        }
89028a00297189c323096aae8e2975de94e8549613cyshang        if (!EFI_ERROR (Status)) {
89128a00297189c323096aae8e2975de94e8549613cyshang          StopCount++;
89228a00297189c323096aae8e2975de94e8549613cyshang        }
89328a00297189c323096aae8e2975de94e8549613cyshang      }
89428a00297189c323096aae8e2975de94e8549613cyshang
89528a00297189c323096aae8e2975de94e8549613cyshang      if (ChildBuffer != NULL) {
89628a00297189c323096aae8e2975de94e8549613cyshang        CoreFreePool (ChildBuffer);
89728a00297189c323096aae8e2975de94e8549613cyshang      }
89828a00297189c323096aae8e2975de94e8549613cyshang    }
89928a00297189c323096aae8e2975de94e8549613cyshang  }
90028a00297189c323096aae8e2975de94e8549613cyshang
90128a00297189c323096aae8e2975de94e8549613cyshang  if (StopCount > 0) {
90285658066182d23e210209299770edaef26d09085mdkinney    //
90385658066182d23e210209299770edaef26d09085mdkinney    // If the Loaded Image Protocols do not already need to be repaired, then
90485658066182d23e210209299770edaef26d09085mdkinney    // check the status of the DeviceHandle field of all Loaded Image Protocols
90585658066182d23e210209299770edaef26d09085mdkinney    // to determine if any of them now need repair because a sucessful Stop()
90685658066182d23e210209299770edaef26d09085mdkinney    // may have destroyed the DeviceHandle value in the Loaded Image Protocol
90785658066182d23e210209299770edaef26d09085mdkinney    //
90885658066182d23e210209299770edaef26d09085mdkinney    if (!mRepairLoadedImage) {
90985658066182d23e210209299770edaef26d09085mdkinney      //
91085658066182d23e210209299770edaef26d09085mdkinney      // Get list of all Loaded Image Protocol Instances
91185658066182d23e210209299770edaef26d09085mdkinney      //
91285658066182d23e210209299770edaef26d09085mdkinney      Status = CoreLocateHandleBuffer (
91385658066182d23e210209299770edaef26d09085mdkinney                ByProtocol,
91485658066182d23e210209299770edaef26d09085mdkinney                &gEfiLoadedImageProtocolGuid,
91585658066182d23e210209299770edaef26d09085mdkinney                NULL,
91685658066182d23e210209299770edaef26d09085mdkinney                &LoadedImageHandleCount,
91785658066182d23e210209299770edaef26d09085mdkinney                &LoadedImageHandleBuffer
91885658066182d23e210209299770edaef26d09085mdkinney                );
91985658066182d23e210209299770edaef26d09085mdkinney      if (!EFI_ERROR (Status) && LoadedImageHandleCount != 0) {
92085658066182d23e210209299770edaef26d09085mdkinney        for (Index = 0; Index < LoadedImageHandleCount; Index++) {
92185658066182d23e210209299770edaef26d09085mdkinney          //
92285658066182d23e210209299770edaef26d09085mdkinney          // Retrieve the Loaded Image Protocol
92385658066182d23e210209299770edaef26d09085mdkinney          //
92485658066182d23e210209299770edaef26d09085mdkinney          Image = CoreLoadedImageInfo (LoadedImageHandleBuffer[Index]);
92585658066182d23e210209299770edaef26d09085mdkinney          if (Image != NULL) {
92685658066182d23e210209299770edaef26d09085mdkinney            //
92785658066182d23e210209299770edaef26d09085mdkinney            // Check to see if the DeviceHandle field is a valid handle
92885658066182d23e210209299770edaef26d09085mdkinney            //
92985658066182d23e210209299770edaef26d09085mdkinney            Status = CoreValidateHandle (Image->Info.DeviceHandle);
93085658066182d23e210209299770edaef26d09085mdkinney            if (EFI_ERROR (Status)) {
93185658066182d23e210209299770edaef26d09085mdkinney              //
93285658066182d23e210209299770edaef26d09085mdkinney              // The DeviceHandle field is not longer a valid handle.  This means
93385658066182d23e210209299770edaef26d09085mdkinney              // that future calls to ConnectController() need to attemp to repair
93485658066182d23e210209299770edaef26d09085mdkinney              // the Loaded Image Protocols with invalid DeviceHandle fields.  Set
93585658066182d23e210209299770edaef26d09085mdkinney              // the flag used by ConnectController().
93685658066182d23e210209299770edaef26d09085mdkinney              //
93785658066182d23e210209299770edaef26d09085mdkinney              mRepairLoadedImage = TRUE;
93885658066182d23e210209299770edaef26d09085mdkinney              break;
93985658066182d23e210209299770edaef26d09085mdkinney            }
94085658066182d23e210209299770edaef26d09085mdkinney          }
94185658066182d23e210209299770edaef26d09085mdkinney        }
94285658066182d23e210209299770edaef26d09085mdkinney        CoreFreePool (LoadedImageHandleBuffer);
94385658066182d23e210209299770edaef26d09085mdkinney      }
94485658066182d23e210209299770edaef26d09085mdkinney    }
94528a00297189c323096aae8e2975de94e8549613cyshang    Status = EFI_SUCCESS;
94628a00297189c323096aae8e2975de94e8549613cyshang  } else {
94728a00297189c323096aae8e2975de94e8549613cyshang    Status = EFI_NOT_FOUND;
94828a00297189c323096aae8e2975de94e8549613cyshang  }
94928a00297189c323096aae8e2975de94e8549613cyshang
95028a00297189c323096aae8e2975de94e8549613cyshangDone:
95128a00297189c323096aae8e2975de94e8549613cyshang
95228a00297189c323096aae8e2975de94e8549613cyshang  if (DriverImageHandleBuffer != NULL) {
95328a00297189c323096aae8e2975de94e8549613cyshang    CoreFreePool (DriverImageHandleBuffer);
95428a00297189c323096aae8e2975de94e8549613cyshang  }
95528a00297189c323096aae8e2975de94e8549613cyshang
95628a00297189c323096aae8e2975de94e8549613cyshang  return Status;
95728a00297189c323096aae8e2975de94e8549613cyshang}
95828a00297189c323096aae8e2975de94e8549613cyshang
95928a00297189c323096aae8e2975de94e8549613cyshangEFI_STATUS
96028a00297189c323096aae8e2975de94e8549613cyshangGetHandleFromDriverBinding (
96128a00297189c323096aae8e2975de94e8549613cyshang  IN   EFI_DRIVER_BINDING_PROTOCOL           *DriverBindingNeed,
96228a00297189c323096aae8e2975de94e8549613cyshang  OUT  EFI_HANDLE                            *Handle
96328a00297189c323096aae8e2975de94e8549613cyshang )
96428a00297189c323096aae8e2975de94e8549613cyshang/*++
96528a00297189c323096aae8e2975de94e8549613cyshang
96628a00297189c323096aae8e2975de94e8549613cyshangRoutine Description:
96728a00297189c323096aae8e2975de94e8549613cyshang
96828a00297189c323096aae8e2975de94e8549613cyshang  Locate the driver binding handle which a specified driver binding protocol installed on.
96928a00297189c323096aae8e2975de94e8549613cyshang
97028a00297189c323096aae8e2975de94e8549613cyshangArguments:
97128a00297189c323096aae8e2975de94e8549613cyshang
97228a00297189c323096aae8e2975de94e8549613cyshang  DriverBindingNeed  - The specified driver binding protocol.
97328a00297189c323096aae8e2975de94e8549613cyshang
97428a00297189c323096aae8e2975de94e8549613cyshang  Handle             - The driver binding handle which the protocol installed on.
97528a00297189c323096aae8e2975de94e8549613cyshang
97628a00297189c323096aae8e2975de94e8549613cyshang
97728a00297189c323096aae8e2975de94e8549613cyshangReturns:
97828a00297189c323096aae8e2975de94e8549613cyshang
97928a00297189c323096aae8e2975de94e8549613cyshang  EFI_NOT_FOUND         - Could not find the handle.
98028a00297189c323096aae8e2975de94e8549613cyshang
98128a00297189c323096aae8e2975de94e8549613cyshang  EFI_SUCCESS           - Successfully find the associated driver binding handle.
98228a00297189c323096aae8e2975de94e8549613cyshang
98328a00297189c323096aae8e2975de94e8549613cyshang--*/
98428a00297189c323096aae8e2975de94e8549613cyshang {
98528a00297189c323096aae8e2975de94e8549613cyshang  EFI_STATUS                          Status ;
98628a00297189c323096aae8e2975de94e8549613cyshang  EFI_DRIVER_BINDING_PROTOCOL         *DriverBinding;
98728a00297189c323096aae8e2975de94e8549613cyshang  UINTN                               DriverBindingHandleCount;
98828a00297189c323096aae8e2975de94e8549613cyshang  EFI_HANDLE                          *DriverBindingHandleBuffer;
98928a00297189c323096aae8e2975de94e8549613cyshang  UINTN                               Index;
99028a00297189c323096aae8e2975de94e8549613cyshang
99128a00297189c323096aae8e2975de94e8549613cyshang  DriverBindingHandleCount = 0;
99228a00297189c323096aae8e2975de94e8549613cyshang  DriverBindingHandleBuffer = NULL;
99328a00297189c323096aae8e2975de94e8549613cyshang  *Handle = NULL_HANDLE;
99428a00297189c323096aae8e2975de94e8549613cyshang  Status = CoreLocateHandleBuffer (
99528a00297189c323096aae8e2975de94e8549613cyshang              ByProtocol,
99628a00297189c323096aae8e2975de94e8549613cyshang              &gEfiDriverBindingProtocolGuid,
99728a00297189c323096aae8e2975de94e8549613cyshang              NULL,
99828a00297189c323096aae8e2975de94e8549613cyshang              &DriverBindingHandleCount,
99928a00297189c323096aae8e2975de94e8549613cyshang              &DriverBindingHandleBuffer
100028a00297189c323096aae8e2975de94e8549613cyshang              );
100128a00297189c323096aae8e2975de94e8549613cyshang  if (EFI_ERROR (Status) || DriverBindingHandleCount == 0) {
100228a00297189c323096aae8e2975de94e8549613cyshang    return EFI_NOT_FOUND;
100328a00297189c323096aae8e2975de94e8549613cyshang  }
100428a00297189c323096aae8e2975de94e8549613cyshang
100528a00297189c323096aae8e2975de94e8549613cyshang  for (Index = 0 ; Index < DriverBindingHandleCount; Index++ ) {
100628a00297189c323096aae8e2975de94e8549613cyshang    Status = CoreOpenProtocol(
100728a00297189c323096aae8e2975de94e8549613cyshang                      DriverBindingHandleBuffer[Index],
100828a00297189c323096aae8e2975de94e8549613cyshang                      &gEfiDriverBindingProtocolGuid,
100928a00297189c323096aae8e2975de94e8549613cyshang                      (VOID **)&DriverBinding,
101028a00297189c323096aae8e2975de94e8549613cyshang                      gDxeCoreImageHandle,
101128a00297189c323096aae8e2975de94e8549613cyshang                      NULL,
101228a00297189c323096aae8e2975de94e8549613cyshang                      EFI_OPEN_PROTOCOL_GET_PROTOCOL
101328a00297189c323096aae8e2975de94e8549613cyshang                      );
101428a00297189c323096aae8e2975de94e8549613cyshang
101528a00297189c323096aae8e2975de94e8549613cyshang   if (!EFI_ERROR (Status) && DriverBinding != NULL) {
101628a00297189c323096aae8e2975de94e8549613cyshang
101728a00297189c323096aae8e2975de94e8549613cyshang    if ( DriverBinding == DriverBindingNeed ) {
101828a00297189c323096aae8e2975de94e8549613cyshang      *Handle = DriverBindingHandleBuffer[Index];
101928a00297189c323096aae8e2975de94e8549613cyshang      CoreFreePool (DriverBindingHandleBuffer);
102028a00297189c323096aae8e2975de94e8549613cyshang      return EFI_SUCCESS ;
102128a00297189c323096aae8e2975de94e8549613cyshang    }
102228a00297189c323096aae8e2975de94e8549613cyshang   }
102328a00297189c323096aae8e2975de94e8549613cyshang }
102428a00297189c323096aae8e2975de94e8549613cyshang
102528a00297189c323096aae8e2975de94e8549613cyshang CoreFreePool (DriverBindingHandleBuffer);
102628a00297189c323096aae8e2975de94e8549613cyshang return EFI_NOT_FOUND ;
102728a00297189c323096aae8e2975de94e8549613cyshang}
102828a00297189c323096aae8e2975de94e8549613cyshang
1029