DriverSupport.c revision adc8840a2517db5d93fbdba93f5f51d94ee0fb39
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
3228a00297189c323096aae8e2975de94e8549613cyshangCoreConnectSingleController (
3328a00297189c323096aae8e2975de94e8549613cyshang  IN  EFI_HANDLE                ControllerHandle,
3428a00297189c323096aae8e2975de94e8549613cyshang  IN  EFI_HANDLE                *DriverImageHandle    OPTIONAL,
3528a00297189c323096aae8e2975de94e8549613cyshang  IN  EFI_DEVICE_PATH_PROTOCOL  *RemainingDevicePath  OPTIONAL
3628a00297189c323096aae8e2975de94e8549613cyshang  );
3728a00297189c323096aae8e2975de94e8549613cyshang
3828a00297189c323096aae8e2975de94e8549613cyshang//
3928a00297189c323096aae8e2975de94e8549613cyshang// Driver Support Functions
4028a00297189c323096aae8e2975de94e8549613cyshang//
4128a00297189c323096aae8e2975de94e8549613cyshangEFI_STATUS
4228a00297189c323096aae8e2975de94e8549613cyshangEFIAPI
4328a00297189c323096aae8e2975de94e8549613cyshangCoreConnectController (
4428a00297189c323096aae8e2975de94e8549613cyshang  IN  EFI_HANDLE                ControllerHandle,
4528a00297189c323096aae8e2975de94e8549613cyshang  IN  EFI_HANDLE                *DriverImageHandle    OPTIONAL,
4628a00297189c323096aae8e2975de94e8549613cyshang  IN  EFI_DEVICE_PATH_PROTOCOL  *RemainingDevicePath  OPTIONAL,
4728a00297189c323096aae8e2975de94e8549613cyshang  IN  BOOLEAN                   Recursive
4828a00297189c323096aae8e2975de94e8549613cyshang  )
4928a00297189c323096aae8e2975de94e8549613cyshang/*++
5028a00297189c323096aae8e2975de94e8549613cyshang
5128a00297189c323096aae8e2975de94e8549613cyshangRoutine Description:
5228a00297189c323096aae8e2975de94e8549613cyshang
5328a00297189c323096aae8e2975de94e8549613cyshang  Connects one or more drivers to a controller.
5428a00297189c323096aae8e2975de94e8549613cyshang
5528a00297189c323096aae8e2975de94e8549613cyshangArguments:
5628a00297189c323096aae8e2975de94e8549613cyshang
5728a00297189c323096aae8e2975de94e8549613cyshang  ControllerHandle            - Handle of the controller to be connected.
5828a00297189c323096aae8e2975de94e8549613cyshang
5928a00297189c323096aae8e2975de94e8549613cyshang  DriverImageHandle           - DriverImageHandle A pointer to an ordered list of driver image handles.
6028a00297189c323096aae8e2975de94e8549613cyshang
6128a00297189c323096aae8e2975de94e8549613cyshang  RemainingDevicePath         - RemainingDevicePath A pointer to the device path that specifies a child of the
6228a00297189c323096aae8e2975de94e8549613cyshang                                controller specified by ControllerHandle.
6328a00297189c323096aae8e2975de94e8549613cyshang
6428a00297189c323096aae8e2975de94e8549613cyshang  Recursive                   - Whether the function would be called recursively or not.
6528a00297189c323096aae8e2975de94e8549613cyshang
6628a00297189c323096aae8e2975de94e8549613cyshangReturns:
6728a00297189c323096aae8e2975de94e8549613cyshang
6828a00297189c323096aae8e2975de94e8549613cyshang  Status code.
6928a00297189c323096aae8e2975de94e8549613cyshang
7028a00297189c323096aae8e2975de94e8549613cyshang--*/
7128a00297189c323096aae8e2975de94e8549613cyshang{
7228a00297189c323096aae8e2975de94e8549613cyshang  EFI_STATUS                           Status;
7328a00297189c323096aae8e2975de94e8549613cyshang  EFI_STATUS                           ReturnStatus;
7428a00297189c323096aae8e2975de94e8549613cyshang  IHANDLE                              *Handle;
7528a00297189c323096aae8e2975de94e8549613cyshang  PROTOCOL_INTERFACE                   *Prot;
7628a00297189c323096aae8e2975de94e8549613cyshang  LIST_ENTRY                           *Link;
7728a00297189c323096aae8e2975de94e8549613cyshang  LIST_ENTRY                           *ProtLink;
7828a00297189c323096aae8e2975de94e8549613cyshang  OPEN_PROTOCOL_DATA                   *OpenData;
7928a00297189c323096aae8e2975de94e8549613cyshang  EFI_DEVICE_PATH_PROTOCOL             *AlignedRemainingDevicePath;
8085658066182d23e210209299770edaef26d09085mdkinney  EFI_HANDLE                           *ChildHandleBuffer;
8185658066182d23e210209299770edaef26d09085mdkinney  UINTN                                ChildHandleCount;
8285658066182d23e210209299770edaef26d09085mdkinney  UINTN                                Index;
8385658066182d23e210209299770edaef26d09085mdkinney  EFI_HANDLE                           *LoadedImageHandleBuffer;
8485658066182d23e210209299770edaef26d09085mdkinney  UINTN                                LoadedImageHandleCount;
8585658066182d23e210209299770edaef26d09085mdkinney  LOADED_IMAGE_PRIVATE_DATA            *Image;
8685658066182d23e210209299770edaef26d09085mdkinney  EFI_HANDLE                           DeviceHandle;
8785658066182d23e210209299770edaef26d09085mdkinney  EFI_DEVICE_PATH_PROTOCOL             *DevicePath;
8828a00297189c323096aae8e2975de94e8549613cyshang
8928a00297189c323096aae8e2975de94e8549613cyshang  //
9028a00297189c323096aae8e2975de94e8549613cyshang  // Make sure ControllerHandle is valid
9128a00297189c323096aae8e2975de94e8549613cyshang  //
9228a00297189c323096aae8e2975de94e8549613cyshang  Status = CoreValidateHandle (ControllerHandle);
9328a00297189c323096aae8e2975de94e8549613cyshang  if (EFI_ERROR (Status)) {
9428a00297189c323096aae8e2975de94e8549613cyshang    return Status;
9528a00297189c323096aae8e2975de94e8549613cyshang  }
9628a00297189c323096aae8e2975de94e8549613cyshang
9728a00297189c323096aae8e2975de94e8549613cyshang  Handle = ControllerHandle;
9828a00297189c323096aae8e2975de94e8549613cyshang
9928a00297189c323096aae8e2975de94e8549613cyshang  //
10085658066182d23e210209299770edaef26d09085mdkinney  // Make a copy of RemainingDevicePath to guanatee it is aligned
10128a00297189c323096aae8e2975de94e8549613cyshang  //
10228a00297189c323096aae8e2975de94e8549613cyshang  AlignedRemainingDevicePath = NULL;
10328a00297189c323096aae8e2975de94e8549613cyshang  if (RemainingDevicePath != NULL) {
10428a00297189c323096aae8e2975de94e8549613cyshang    AlignedRemainingDevicePath = CoreDuplicateDevicePath (RemainingDevicePath);
10528a00297189c323096aae8e2975de94e8549613cyshang  }
10628a00297189c323096aae8e2975de94e8549613cyshang
10728a00297189c323096aae8e2975de94e8549613cyshang  //
10885658066182d23e210209299770edaef26d09085mdkinney  // Connect all drivers to ControllerHandle
10985658066182d23e210209299770edaef26d09085mdkinney  // If CoreConnectSingleController returns EFI_NOT_READY, then the number of
11085658066182d23e210209299770edaef26d09085mdkinney  // Driver Binding Protocols in the handle database has increased during the call
11185658066182d23e210209299770edaef26d09085mdkinney  // so the connect operation must be restarted
11228a00297189c323096aae8e2975de94e8549613cyshang  //
11385658066182d23e210209299770edaef26d09085mdkinney  do {
11485658066182d23e210209299770edaef26d09085mdkinney    ReturnStatus = CoreConnectSingleController (
11585658066182d23e210209299770edaef26d09085mdkinney                    ControllerHandle,
11685658066182d23e210209299770edaef26d09085mdkinney                    DriverImageHandle,
11785658066182d23e210209299770edaef26d09085mdkinney                    AlignedRemainingDevicePath
11885658066182d23e210209299770edaef26d09085mdkinney                    );
11985658066182d23e210209299770edaef26d09085mdkinney  } while (ReturnStatus == EFI_NOT_READY);
12085658066182d23e210209299770edaef26d09085mdkinney
12185658066182d23e210209299770edaef26d09085mdkinney  //
12285658066182d23e210209299770edaef26d09085mdkinney  // Free the aligned copy of RemainingDevicePath
12385658066182d23e210209299770edaef26d09085mdkinney  //
12485658066182d23e210209299770edaef26d09085mdkinney  if (AlignedRemainingDevicePath != NULL) {
12585658066182d23e210209299770edaef26d09085mdkinney    CoreFreePool (AlignedRemainingDevicePath);
12628a00297189c323096aae8e2975de94e8549613cyshang  }
12728a00297189c323096aae8e2975de94e8549613cyshang
12828a00297189c323096aae8e2975de94e8549613cyshang  //
12928a00297189c323096aae8e2975de94e8549613cyshang  // If recursive, then connect all drivers to all of ControllerHandle's children
13028a00297189c323096aae8e2975de94e8549613cyshang  //
13185658066182d23e210209299770edaef26d09085mdkinney  if (Recursive) {
13285658066182d23e210209299770edaef26d09085mdkinney    //
13385658066182d23e210209299770edaef26d09085mdkinney    // Acquire the protocol lock on the handle database so the child handles can be collected
13485658066182d23e210209299770edaef26d09085mdkinney    //
13585658066182d23e210209299770edaef26d09085mdkinney    CoreAcquireProtocolLock ();
13685658066182d23e210209299770edaef26d09085mdkinney
13785658066182d23e210209299770edaef26d09085mdkinney    //
13885658066182d23e210209299770edaef26d09085mdkinney    // Make sure the DriverBindingHandle is valid
13985658066182d23e210209299770edaef26d09085mdkinney    //
14085658066182d23e210209299770edaef26d09085mdkinney    Status = CoreValidateHandle (ControllerHandle);
14185658066182d23e210209299770edaef26d09085mdkinney    if (EFI_ERROR (Status)) {
14285658066182d23e210209299770edaef26d09085mdkinney      //
14385658066182d23e210209299770edaef26d09085mdkinney      // Release the protocol lock on the handle database
14485658066182d23e210209299770edaef26d09085mdkinney      //
14585658066182d23e210209299770edaef26d09085mdkinney      CoreReleaseProtocolLock ();
14685658066182d23e210209299770edaef26d09085mdkinney
14785658066182d23e210209299770edaef26d09085mdkinney      return ReturnStatus;
14885658066182d23e210209299770edaef26d09085mdkinney    }
14985658066182d23e210209299770edaef26d09085mdkinney
15085658066182d23e210209299770edaef26d09085mdkinney
15185658066182d23e210209299770edaef26d09085mdkinney    //
15285658066182d23e210209299770edaef26d09085mdkinney    // Count ControllerHandle's children
15385658066182d23e210209299770edaef26d09085mdkinney    //
15485658066182d23e210209299770edaef26d09085mdkinney    for (Link = Handle->Protocols.ForwardLink, ChildHandleCount = 0; Link != &Handle->Protocols; Link = Link->ForwardLink) {
15585658066182d23e210209299770edaef26d09085mdkinney      Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
15685658066182d23e210209299770edaef26d09085mdkinney      for (ProtLink = Prot->OpenList.ForwardLink;
15785658066182d23e210209299770edaef26d09085mdkinney          ProtLink != &Prot->OpenList;
15885658066182d23e210209299770edaef26d09085mdkinney          ProtLink = ProtLink->ForwardLink) {
15985658066182d23e210209299770edaef26d09085mdkinney        OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
16085658066182d23e210209299770edaef26d09085mdkinney        if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
16185658066182d23e210209299770edaef26d09085mdkinney          ChildHandleCount++;
16285658066182d23e210209299770edaef26d09085mdkinney        }
16385658066182d23e210209299770edaef26d09085mdkinney      }
16485658066182d23e210209299770edaef26d09085mdkinney    }
16585658066182d23e210209299770edaef26d09085mdkinney
16685658066182d23e210209299770edaef26d09085mdkinney    //
16785658066182d23e210209299770edaef26d09085mdkinney    // Allocate a handle buffer for ControllerHandle's children
16885658066182d23e210209299770edaef26d09085mdkinney    //
16985658066182d23e210209299770edaef26d09085mdkinney    ChildHandleBuffer = CoreAllocateBootServicesPool (ChildHandleCount * sizeof(EFI_HANDLE));
17085658066182d23e210209299770edaef26d09085mdkinney
17185658066182d23e210209299770edaef26d09085mdkinney    //
17285658066182d23e210209299770edaef26d09085mdkinney    // Fill in a handle buffer with ControllerHandle's children
17385658066182d23e210209299770edaef26d09085mdkinney    //
17485658066182d23e210209299770edaef26d09085mdkinney    for (Link = Handle->Protocols.ForwardLink, ChildHandleCount = 0; Link != &Handle->Protocols; Link = Link->ForwardLink) {
17585658066182d23e210209299770edaef26d09085mdkinney      Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
17685658066182d23e210209299770edaef26d09085mdkinney      for (ProtLink = Prot->OpenList.ForwardLink;
17785658066182d23e210209299770edaef26d09085mdkinney          ProtLink != &Prot->OpenList;
17885658066182d23e210209299770edaef26d09085mdkinney          ProtLink = ProtLink->ForwardLink) {
17928a00297189c323096aae8e2975de94e8549613cyshang        OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
18028a00297189c323096aae8e2975de94e8549613cyshang        if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
18185658066182d23e210209299770edaef26d09085mdkinney          ChildHandleBuffer[ChildHandleCount] = OpenData->ControllerHandle;
18285658066182d23e210209299770edaef26d09085mdkinney          ChildHandleCount++;
18385658066182d23e210209299770edaef26d09085mdkinney        }
18485658066182d23e210209299770edaef26d09085mdkinney      }
18585658066182d23e210209299770edaef26d09085mdkinney    }
18685658066182d23e210209299770edaef26d09085mdkinney
18785658066182d23e210209299770edaef26d09085mdkinney    //
18885658066182d23e210209299770edaef26d09085mdkinney    // Release the protocol lock on the handle database
18985658066182d23e210209299770edaef26d09085mdkinney    //
19085658066182d23e210209299770edaef26d09085mdkinney    CoreReleaseProtocolLock ();
19185658066182d23e210209299770edaef26d09085mdkinney
19285658066182d23e210209299770edaef26d09085mdkinney    //
19385658066182d23e210209299770edaef26d09085mdkinney    // Recursively connect each child handle
19485658066182d23e210209299770edaef26d09085mdkinney    //
19585658066182d23e210209299770edaef26d09085mdkinney    for (Index = 0; Index < ChildHandleCount; Index++) {
19685658066182d23e210209299770edaef26d09085mdkinney      CoreConnectController (
19785658066182d23e210209299770edaef26d09085mdkinney        ChildHandleBuffer[Index],
19885658066182d23e210209299770edaef26d09085mdkinney        NULL,
19985658066182d23e210209299770edaef26d09085mdkinney        NULL,
20085658066182d23e210209299770edaef26d09085mdkinney        TRUE
20185658066182d23e210209299770edaef26d09085mdkinney        );
20285658066182d23e210209299770edaef26d09085mdkinney    }
20385658066182d23e210209299770edaef26d09085mdkinney
20485658066182d23e210209299770edaef26d09085mdkinney    //
20585658066182d23e210209299770edaef26d09085mdkinney    // Free the handle buffer of ControllerHandle's children
20685658066182d23e210209299770edaef26d09085mdkinney    //
20785658066182d23e210209299770edaef26d09085mdkinney    CoreFreePool (ChildHandleBuffer);
20885658066182d23e210209299770edaef26d09085mdkinney  }
20985658066182d23e210209299770edaef26d09085mdkinney
21085658066182d23e210209299770edaef26d09085mdkinney  //
21185658066182d23e210209299770edaef26d09085mdkinney  // If a Stop() function has been called one or more time successfully, then attempt to
21285658066182d23e210209299770edaef26d09085mdkinney  // repair the stale DeviceHandle fields of the Loaded Image Protocols
21385658066182d23e210209299770edaef26d09085mdkinney  //
21485658066182d23e210209299770edaef26d09085mdkinney  if (mRepairLoadedImage) {
21585658066182d23e210209299770edaef26d09085mdkinney    //
21685658066182d23e210209299770edaef26d09085mdkinney    // Assume that all Loaded Image Protocols can be repaired
21785658066182d23e210209299770edaef26d09085mdkinney    //
21885658066182d23e210209299770edaef26d09085mdkinney    mRepairLoadedImage = FALSE;
21985658066182d23e210209299770edaef26d09085mdkinney
22085658066182d23e210209299770edaef26d09085mdkinney    //
22185658066182d23e210209299770edaef26d09085mdkinney    // Get list of all Loaded Image Protocol Instances
22285658066182d23e210209299770edaef26d09085mdkinney    //
22385658066182d23e210209299770edaef26d09085mdkinney    Status = CoreLocateHandleBuffer (
22485658066182d23e210209299770edaef26d09085mdkinney              ByProtocol,
22585658066182d23e210209299770edaef26d09085mdkinney              &gEfiLoadedImageProtocolGuid,
22685658066182d23e210209299770edaef26d09085mdkinney              NULL,
22785658066182d23e210209299770edaef26d09085mdkinney              &LoadedImageHandleCount,
22885658066182d23e210209299770edaef26d09085mdkinney              &LoadedImageHandleBuffer
22985658066182d23e210209299770edaef26d09085mdkinney              );
23085658066182d23e210209299770edaef26d09085mdkinney    if (!EFI_ERROR (Status) && LoadedImageHandleCount != 0) {
23185658066182d23e210209299770edaef26d09085mdkinney      for (Index = 0; Index < LoadedImageHandleCount; Index++) {
23285658066182d23e210209299770edaef26d09085mdkinney        //
23385658066182d23e210209299770edaef26d09085mdkinney        // Retrieve the Loaded Image Protocol
23485658066182d23e210209299770edaef26d09085mdkinney        //
23585658066182d23e210209299770edaef26d09085mdkinney        Image = CoreLoadedImageInfo (LoadedImageHandleBuffer[Index]);
23685658066182d23e210209299770edaef26d09085mdkinney        if (Image != NULL) {
23785658066182d23e210209299770edaef26d09085mdkinney          //
23885658066182d23e210209299770edaef26d09085mdkinney          // Check to see if the DeviceHandle field is a valid handle
23985658066182d23e210209299770edaef26d09085mdkinney          //
24085658066182d23e210209299770edaef26d09085mdkinney          Status = CoreValidateHandle (Image->Info.DeviceHandle);
24185658066182d23e210209299770edaef26d09085mdkinney          if (EFI_ERROR (Status)) {
24285658066182d23e210209299770edaef26d09085mdkinney            //
24385658066182d23e210209299770edaef26d09085mdkinney            // The DeviceHandle field is not valid.
24485658066182d23e210209299770edaef26d09085mdkinney            // Attempt to locate a device handle with a device path that matches the one
24585658066182d23e210209299770edaef26d09085mdkinney            // that was used to originally load the image
24685658066182d23e210209299770edaef26d09085mdkinney            //
24785658066182d23e210209299770edaef26d09085mdkinney            DevicePath = Image->DeviceHandleDevicePath;
24885658066182d23e210209299770edaef26d09085mdkinney            if (DevicePath != NULL) {
24985658066182d23e210209299770edaef26d09085mdkinney              Status = CoreLocateDevicePath (&gEfiDevicePathProtocolGuid, &DevicePath, &DeviceHandle);
25085658066182d23e210209299770edaef26d09085mdkinney              if (!EFI_ERROR (Status) && (DeviceHandle != NULL_HANDLE) && IsDevicePathEnd(DevicePath)) {
25185658066182d23e210209299770edaef26d09085mdkinney                //
25285658066182d23e210209299770edaef26d09085mdkinney                // A device handle with a matching device path was found, so update the Loaded Image Protocol
25385658066182d23e210209299770edaef26d09085mdkinney                // with the device handle discovered
25485658066182d23e210209299770edaef26d09085mdkinney                //
25585658066182d23e210209299770edaef26d09085mdkinney                Image->Info.DeviceHandle = DeviceHandle;
25685658066182d23e210209299770edaef26d09085mdkinney              } else {
25785658066182d23e210209299770edaef26d09085mdkinney                //
25885658066182d23e210209299770edaef26d09085mdkinney                // There is still at least one Loaded Image Protocol that requires repair
25985658066182d23e210209299770edaef26d09085mdkinney                //
26085658066182d23e210209299770edaef26d09085mdkinney                mRepairLoadedImage = TRUE;
26185658066182d23e210209299770edaef26d09085mdkinney              }
26285658066182d23e210209299770edaef26d09085mdkinney            }
26385658066182d23e210209299770edaef26d09085mdkinney          }
26428a00297189c323096aae8e2975de94e8549613cyshang        }
26585658066182d23e210209299770edaef26d09085mdkinney      }
26685658066182d23e210209299770edaef26d09085mdkinney      CoreFreePool (LoadedImageHandleBuffer);
26728a00297189c323096aae8e2975de94e8549613cyshang    }
26828a00297189c323096aae8e2975de94e8549613cyshang  }
26985658066182d23e210209299770edaef26d09085mdkinney
27028a00297189c323096aae8e2975de94e8549613cyshang  return ReturnStatus;
27128a00297189c323096aae8e2975de94e8549613cyshang}
27228a00297189c323096aae8e2975de94e8549613cyshang
27328a00297189c323096aae8e2975de94e8549613cyshangVOID
27428a00297189c323096aae8e2975de94e8549613cyshangAddSortedDriverBindingProtocol (
27528a00297189c323096aae8e2975de94e8549613cyshang  IN      EFI_HANDLE                   DriverBindingHandle,
27628a00297189c323096aae8e2975de94e8549613cyshang  IN OUT  UINTN                        *NumberOfSortedDriverBindingProtocols,
27728a00297189c323096aae8e2975de94e8549613cyshang  IN OUT  EFI_DRIVER_BINDING_PROTOCOL  **SortedDriverBindingProtocols,
27828a00297189c323096aae8e2975de94e8549613cyshang  IN      UINTN                        DriverBindingHandleCount,
279adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney  IN OUT  EFI_HANDLE                   *DriverBindingHandleBuffer,
280adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney  IN      BOOLEAN                      IsImageHandle
28128a00297189c323096aae8e2975de94e8549613cyshang  )
28228a00297189c323096aae8e2975de94e8549613cyshang/*++
28328a00297189c323096aae8e2975de94e8549613cyshang
28428a00297189c323096aae8e2975de94e8549613cyshangRoutine Description:
28528a00297189c323096aae8e2975de94e8549613cyshang
28628a00297189c323096aae8e2975de94e8549613cyshang  Add Driver Binding Protocols from Context Driver Image Handles to sorted
28728a00297189c323096aae8e2975de94e8549613cyshang   Driver Binding Protocol list.
28828a00297189c323096aae8e2975de94e8549613cyshang
28928a00297189c323096aae8e2975de94e8549613cyshangArguments:
29028a00297189c323096aae8e2975de94e8549613cyshang
29128a00297189c323096aae8e2975de94e8549613cyshang  DriverBindingHandle - Handle of the driver binding protocol.
29228a00297189c323096aae8e2975de94e8549613cyshang
29328a00297189c323096aae8e2975de94e8549613cyshang  NumberOfSortedDriverBindingProtocols - Number Of sorted driver binding protocols
29428a00297189c323096aae8e2975de94e8549613cyshang
29528a00297189c323096aae8e2975de94e8549613cyshang  SortedDriverBindingProtocols - The sorted protocol list.
29628a00297189c323096aae8e2975de94e8549613cyshang
29728a00297189c323096aae8e2975de94e8549613cyshang  DriverBindingHandleCount - Driver Binding Handle Count.
29828a00297189c323096aae8e2975de94e8549613cyshang
29928a00297189c323096aae8e2975de94e8549613cyshang  DriverBindingHandleBuffer - The buffer of driver binding protocol to be modified.
30028a00297189c323096aae8e2975de94e8549613cyshang
30128a00297189c323096aae8e2975de94e8549613cyshangReturns:
30228a00297189c323096aae8e2975de94e8549613cyshang
30328a00297189c323096aae8e2975de94e8549613cyshang  None.
30428a00297189c323096aae8e2975de94e8549613cyshang
30528a00297189c323096aae8e2975de94e8549613cyshang--*/
30628a00297189c323096aae8e2975de94e8549613cyshang{
30728a00297189c323096aae8e2975de94e8549613cyshang  EFI_STATUS                   Status;
30828a00297189c323096aae8e2975de94e8549613cyshang  EFI_DRIVER_BINDING_PROTOCOL  *DriverBinding;
30928a00297189c323096aae8e2975de94e8549613cyshang  UINTN                        Index;
31028a00297189c323096aae8e2975de94e8549613cyshang
31128a00297189c323096aae8e2975de94e8549613cyshang  //
31228a00297189c323096aae8e2975de94e8549613cyshang  // Make sure the DriverBindingHandle is valid
31328a00297189c323096aae8e2975de94e8549613cyshang  //
31428a00297189c323096aae8e2975de94e8549613cyshang  Status = CoreValidateHandle (DriverBindingHandle);
31528a00297189c323096aae8e2975de94e8549613cyshang  if (EFI_ERROR (Status)) {
31628a00297189c323096aae8e2975de94e8549613cyshang    return;
31728a00297189c323096aae8e2975de94e8549613cyshang  }
31828a00297189c323096aae8e2975de94e8549613cyshang
31928a00297189c323096aae8e2975de94e8549613cyshang  //
320adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney  // If IsImageHandle is TRUE, then DriverBindingHandle is an image handle
321adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney  // Find all the DriverBindingHandles associated with that image handle and add them to the sorted list
322adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney  //
323adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney  if (IsImageHandle) {
324adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney    //
325adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney    // Loop through all the Driver Binding Handles
326adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney    //
327adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney    for (Index = 0; Index < DriverBindingHandleCount; Index++) {
328adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney      //
329adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney      // Retrieve the Driver Binding Protocol associated with each Driver Binding Handle
330adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney      //
331adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney      Status = CoreHandleProtocol (
332adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney                DriverBindingHandleBuffer[Index],
333adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney                &gEfiDriverBindingProtocolGuid,
334adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney                (VOID **)&DriverBinding
335adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney                );
336adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney      //
337adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney      // If the ImageHandle associated with DriverBinding matches DriverBindingHandle,
338adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney      // then add the DriverBindingProtocol[Index] to the sorted list
339adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney      //
340adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney      if (DriverBinding->ImageHandle == DriverBindingHandle) {
341adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney        AddSortedDriverBindingProtocol (
342adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney          DriverBindingHandleBuffer[Index],
343adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney          NumberOfSortedDriverBindingProtocols,
344adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney          SortedDriverBindingProtocols,
345adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney          DriverBindingHandleCount,
346adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney          DriverBindingHandleBuffer,
347adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney          FALSE
348adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney          );
349adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney      }
350adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney    }
351adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney    return;
352adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney  }
353adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney
354adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney  //
35528a00297189c323096aae8e2975de94e8549613cyshang  // Retrieve the Driver Binding Protocol from DriverBindingHandle
35628a00297189c323096aae8e2975de94e8549613cyshang  //
35728a00297189c323096aae8e2975de94e8549613cyshang  Status = CoreHandleProtocol(
35828a00297189c323096aae8e2975de94e8549613cyshang             DriverBindingHandle,
35928a00297189c323096aae8e2975de94e8549613cyshang             &gEfiDriverBindingProtocolGuid,
36028a00297189c323096aae8e2975de94e8549613cyshang             (VOID **)&DriverBinding
36128a00297189c323096aae8e2975de94e8549613cyshang             );
36228a00297189c323096aae8e2975de94e8549613cyshang  //
36328a00297189c323096aae8e2975de94e8549613cyshang  // If DriverBindingHandle does not support the Driver Binding Protocol then return
36428a00297189c323096aae8e2975de94e8549613cyshang  //
36528a00297189c323096aae8e2975de94e8549613cyshang  if (EFI_ERROR (Status) || DriverBinding == NULL) {
36628a00297189c323096aae8e2975de94e8549613cyshang    return;
36728a00297189c323096aae8e2975de94e8549613cyshang  }
36828a00297189c323096aae8e2975de94e8549613cyshang
36928a00297189c323096aae8e2975de94e8549613cyshang  //
37028a00297189c323096aae8e2975de94e8549613cyshang  // See if DriverBinding is already in the sorted list
37128a00297189c323096aae8e2975de94e8549613cyshang  //
37285658066182d23e210209299770edaef26d09085mdkinney  for (Index = 0; Index < *NumberOfSortedDriverBindingProtocols && Index < DriverBindingHandleCount; Index++) {
37328a00297189c323096aae8e2975de94e8549613cyshang    if (DriverBinding == SortedDriverBindingProtocols[Index]) {
37428a00297189c323096aae8e2975de94e8549613cyshang      return;
37528a00297189c323096aae8e2975de94e8549613cyshang    }
37628a00297189c323096aae8e2975de94e8549613cyshang  }
37728a00297189c323096aae8e2975de94e8549613cyshang
37828a00297189c323096aae8e2975de94e8549613cyshang  //
37928a00297189c323096aae8e2975de94e8549613cyshang  // Add DriverBinding to the end of the list
38028a00297189c323096aae8e2975de94e8549613cyshang  //
38185658066182d23e210209299770edaef26d09085mdkinney  if (*NumberOfSortedDriverBindingProtocols < DriverBindingHandleCount) {
38285658066182d23e210209299770edaef26d09085mdkinney    SortedDriverBindingProtocols[*NumberOfSortedDriverBindingProtocols] = DriverBinding;
38385658066182d23e210209299770edaef26d09085mdkinney  }
38428a00297189c323096aae8e2975de94e8549613cyshang  *NumberOfSortedDriverBindingProtocols = *NumberOfSortedDriverBindingProtocols + 1;
38528a00297189c323096aae8e2975de94e8549613cyshang
38628a00297189c323096aae8e2975de94e8549613cyshang  //
38728a00297189c323096aae8e2975de94e8549613cyshang  // Mark the cooresponding handle in DriverBindingHandleBuffer as used
38828a00297189c323096aae8e2975de94e8549613cyshang  //
38928a00297189c323096aae8e2975de94e8549613cyshang  for (Index = 0; Index < DriverBindingHandleCount; Index++) {
39028a00297189c323096aae8e2975de94e8549613cyshang    if (DriverBindingHandleBuffer[Index] == DriverBindingHandle) {
39128a00297189c323096aae8e2975de94e8549613cyshang      DriverBindingHandleBuffer[Index] = NULL;
39228a00297189c323096aae8e2975de94e8549613cyshang    }
39328a00297189c323096aae8e2975de94e8549613cyshang  }
39428a00297189c323096aae8e2975de94e8549613cyshang}
39528a00297189c323096aae8e2975de94e8549613cyshang
39628a00297189c323096aae8e2975de94e8549613cyshangEFI_STATUS
39728a00297189c323096aae8e2975de94e8549613cyshangCoreConnectSingleController (
39828a00297189c323096aae8e2975de94e8549613cyshang  IN  EFI_HANDLE                ControllerHandle,
39928a00297189c323096aae8e2975de94e8549613cyshang  IN  EFI_HANDLE                *ContextDriverImageHandles OPTIONAL,
40028a00297189c323096aae8e2975de94e8549613cyshang  IN  EFI_DEVICE_PATH_PROTOCOL  *RemainingDevicePath       OPTIONAL
40128a00297189c323096aae8e2975de94e8549613cyshang  )
40228a00297189c323096aae8e2975de94e8549613cyshang/*++
40328a00297189c323096aae8e2975de94e8549613cyshang
40428a00297189c323096aae8e2975de94e8549613cyshangRoutine Description:
40528a00297189c323096aae8e2975de94e8549613cyshang
40628a00297189c323096aae8e2975de94e8549613cyshang  Connects a controller to a driver.
40728a00297189c323096aae8e2975de94e8549613cyshang
40828a00297189c323096aae8e2975de94e8549613cyshangArguments:
40928a00297189c323096aae8e2975de94e8549613cyshang
41028a00297189c323096aae8e2975de94e8549613cyshang  ControllerHandle            - Handle of the controller to be connected.
41128a00297189c323096aae8e2975de94e8549613cyshang  ContextDriverImageHandles   - DriverImageHandle A pointer to an ordered list of driver image handles.
41228a00297189c323096aae8e2975de94e8549613cyshang  RemainingDevicePath         - RemainingDevicePath A pointer to the device path that specifies a child
41328a00297189c323096aae8e2975de94e8549613cyshang                                of the controller specified by ControllerHandle.
41428a00297189c323096aae8e2975de94e8549613cyshang
41528a00297189c323096aae8e2975de94e8549613cyshangReturns:
41628a00297189c323096aae8e2975de94e8549613cyshang
41728a00297189c323096aae8e2975de94e8549613cyshang  EFI_SUCCESS           - One or more drivers were connected to ControllerHandle.
41828a00297189c323096aae8e2975de94e8549613cyshang  EFI_OUT_OF_RESOURCES  - No enough system resources to complete the request.
41928a00297189c323096aae8e2975de94e8549613cyshang  EFI_NOT_FOUND         - No drivers were connected to ControllerHandle.
42028a00297189c323096aae8e2975de94e8549613cyshang
42128a00297189c323096aae8e2975de94e8549613cyshang--*/
42228a00297189c323096aae8e2975de94e8549613cyshang{
42328a00297189c323096aae8e2975de94e8549613cyshang  EFI_STATUS                                 Status;
42428a00297189c323096aae8e2975de94e8549613cyshang  UINTN                                      Index;
42528a00297189c323096aae8e2975de94e8549613cyshang  EFI_HANDLE                                 DriverImageHandle;
42628a00297189c323096aae8e2975de94e8549613cyshang  EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL      *PlatformDriverOverride;
42728a00297189c323096aae8e2975de94e8549613cyshang  EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL  *BusSpecificDriverOverride;
42828a00297189c323096aae8e2975de94e8549613cyshang  UINTN                                      DriverBindingHandleCount;
42928a00297189c323096aae8e2975de94e8549613cyshang  EFI_HANDLE                                 *DriverBindingHandleBuffer;
43028a00297189c323096aae8e2975de94e8549613cyshang  EFI_DRIVER_BINDING_PROTOCOL                *DriverBinding;
43128a00297189c323096aae8e2975de94e8549613cyshang  UINTN                                      NumberOfSortedDriverBindingProtocols;
43228a00297189c323096aae8e2975de94e8549613cyshang  EFI_DRIVER_BINDING_PROTOCOL                **SortedDriverBindingProtocols;
43328a00297189c323096aae8e2975de94e8549613cyshang  UINT32                                     HighestVersion;
43428a00297189c323096aae8e2975de94e8549613cyshang  UINTN                                      HighestIndex;
43528a00297189c323096aae8e2975de94e8549613cyshang  UINTN                                      SortIndex;
43628a00297189c323096aae8e2975de94e8549613cyshang  BOOLEAN                                    OneStarted;
43728a00297189c323096aae8e2975de94e8549613cyshang  BOOLEAN                                    DriverFound;
43828a00297189c323096aae8e2975de94e8549613cyshang
43928a00297189c323096aae8e2975de94e8549613cyshang  //
44028a00297189c323096aae8e2975de94e8549613cyshang  // Initialize local variables
44128a00297189c323096aae8e2975de94e8549613cyshang  //
44228a00297189c323096aae8e2975de94e8549613cyshang  DriverBindingHandleCount              = 0;
44328a00297189c323096aae8e2975de94e8549613cyshang  DriverBindingHandleBuffer             = NULL;
44428a00297189c323096aae8e2975de94e8549613cyshang  NumberOfSortedDriverBindingProtocols  = 0;
44528a00297189c323096aae8e2975de94e8549613cyshang  SortedDriverBindingProtocols          = NULL;
44628a00297189c323096aae8e2975de94e8549613cyshang
44728a00297189c323096aae8e2975de94e8549613cyshang  //
44828a00297189c323096aae8e2975de94e8549613cyshang  // Get list of all Driver Binding Protocol Instances
44928a00297189c323096aae8e2975de94e8549613cyshang  //
45028a00297189c323096aae8e2975de94e8549613cyshang  Status = CoreLocateHandleBuffer (
45128a00297189c323096aae8e2975de94e8549613cyshang             ByProtocol,
45228a00297189c323096aae8e2975de94e8549613cyshang             &gEfiDriverBindingProtocolGuid,
45328a00297189c323096aae8e2975de94e8549613cyshang             NULL,
45428a00297189c323096aae8e2975de94e8549613cyshang             &DriverBindingHandleCount,
45528a00297189c323096aae8e2975de94e8549613cyshang             &DriverBindingHandleBuffer
45628a00297189c323096aae8e2975de94e8549613cyshang             );
45728a00297189c323096aae8e2975de94e8549613cyshang  if (EFI_ERROR (Status) || (DriverBindingHandleCount == 0)) {
45828a00297189c323096aae8e2975de94e8549613cyshang    return EFI_NOT_FOUND;
45928a00297189c323096aae8e2975de94e8549613cyshang  }
46028a00297189c323096aae8e2975de94e8549613cyshang
46128a00297189c323096aae8e2975de94e8549613cyshang  //
46228a00297189c323096aae8e2975de94e8549613cyshang  // Allocate a duplicate array for the sorted Driver Binding Protocol Instances
46328a00297189c323096aae8e2975de94e8549613cyshang  //
46428a00297189c323096aae8e2975de94e8549613cyshang  SortedDriverBindingProtocols = CoreAllocateBootServicesPool (sizeof (VOID *) * DriverBindingHandleCount);
46528a00297189c323096aae8e2975de94e8549613cyshang  if (SortedDriverBindingProtocols == NULL) {
46628a00297189c323096aae8e2975de94e8549613cyshang    CoreFreePool (DriverBindingHandleBuffer);
46728a00297189c323096aae8e2975de94e8549613cyshang    return EFI_OUT_OF_RESOURCES;
46828a00297189c323096aae8e2975de94e8549613cyshang  }
46928a00297189c323096aae8e2975de94e8549613cyshang
47028a00297189c323096aae8e2975de94e8549613cyshang  //
47128a00297189c323096aae8e2975de94e8549613cyshang  // Add Driver Binding Protocols from Context Driver Image Handles first
47228a00297189c323096aae8e2975de94e8549613cyshang  //
47328a00297189c323096aae8e2975de94e8549613cyshang  if (ContextDriverImageHandles != NULL) {
47428a00297189c323096aae8e2975de94e8549613cyshang    for (Index = 0; ContextDriverImageHandles[Index] != NULL; Index++) {
47528a00297189c323096aae8e2975de94e8549613cyshang      AddSortedDriverBindingProtocol (
47628a00297189c323096aae8e2975de94e8549613cyshang        ContextDriverImageHandles[Index],
47728a00297189c323096aae8e2975de94e8549613cyshang        &NumberOfSortedDriverBindingProtocols,
47828a00297189c323096aae8e2975de94e8549613cyshang        SortedDriverBindingProtocols,
47928a00297189c323096aae8e2975de94e8549613cyshang        DriverBindingHandleCount,
480adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney        DriverBindingHandleBuffer,
481adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney        FALSE
48228a00297189c323096aae8e2975de94e8549613cyshang        );
48328a00297189c323096aae8e2975de94e8549613cyshang    }
48428a00297189c323096aae8e2975de94e8549613cyshang  }
48528a00297189c323096aae8e2975de94e8549613cyshang
48628a00297189c323096aae8e2975de94e8549613cyshang  //
48728a00297189c323096aae8e2975de94e8549613cyshang  // Add the Platform Driver Override Protocol drivers for ControllerHandle next
48828a00297189c323096aae8e2975de94e8549613cyshang  //
48928a00297189c323096aae8e2975de94e8549613cyshang  Status = CoreLocateProtocol (
49028a00297189c323096aae8e2975de94e8549613cyshang             &gEfiPlatformDriverOverrideProtocolGuid,
49128a00297189c323096aae8e2975de94e8549613cyshang             NULL,
49228a00297189c323096aae8e2975de94e8549613cyshang             (VOID **)&PlatformDriverOverride
49328a00297189c323096aae8e2975de94e8549613cyshang             );
49428a00297189c323096aae8e2975de94e8549613cyshang  if (!EFI_ERROR (Status) && (PlatformDriverOverride != NULL)) {
49528a00297189c323096aae8e2975de94e8549613cyshang    DriverImageHandle = NULL;
49628a00297189c323096aae8e2975de94e8549613cyshang    do {
49728a00297189c323096aae8e2975de94e8549613cyshang      Status = PlatformDriverOverride->GetDriver (
49828a00297189c323096aae8e2975de94e8549613cyshang                                         PlatformDriverOverride,
49928a00297189c323096aae8e2975de94e8549613cyshang                                         ControllerHandle,
50028a00297189c323096aae8e2975de94e8549613cyshang                                         &DriverImageHandle
50128a00297189c323096aae8e2975de94e8549613cyshang                                         );
50228a00297189c323096aae8e2975de94e8549613cyshang      if (!EFI_ERROR (Status)) {
50328a00297189c323096aae8e2975de94e8549613cyshang        AddSortedDriverBindingProtocol (
50428a00297189c323096aae8e2975de94e8549613cyshang          DriverImageHandle,
50528a00297189c323096aae8e2975de94e8549613cyshang          &NumberOfSortedDriverBindingProtocols,
50628a00297189c323096aae8e2975de94e8549613cyshang          SortedDriverBindingProtocols,
50728a00297189c323096aae8e2975de94e8549613cyshang          DriverBindingHandleCount,
508adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney          DriverBindingHandleBuffer,
509adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney          TRUE
51028a00297189c323096aae8e2975de94e8549613cyshang          );
51128a00297189c323096aae8e2975de94e8549613cyshang      }
51228a00297189c323096aae8e2975de94e8549613cyshang    } while (!EFI_ERROR (Status));
51328a00297189c323096aae8e2975de94e8549613cyshang  }
51428a00297189c323096aae8e2975de94e8549613cyshang
51528a00297189c323096aae8e2975de94e8549613cyshang  //
51628a00297189c323096aae8e2975de94e8549613cyshang  // Get the Bus Specific Driver Override Protocol instance on the Controller Handle
51728a00297189c323096aae8e2975de94e8549613cyshang  //
518adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney  Status = CoreHandleProtocol (
51928a00297189c323096aae8e2975de94e8549613cyshang             ControllerHandle,
52028a00297189c323096aae8e2975de94e8549613cyshang             &gEfiBusSpecificDriverOverrideProtocolGuid,
52128a00297189c323096aae8e2975de94e8549613cyshang             (VOID **)&BusSpecificDriverOverride
52228a00297189c323096aae8e2975de94e8549613cyshang             );
52328a00297189c323096aae8e2975de94e8549613cyshang  if (!EFI_ERROR (Status) && (BusSpecificDriverOverride != NULL)) {
52428a00297189c323096aae8e2975de94e8549613cyshang    DriverImageHandle = NULL;
52528a00297189c323096aae8e2975de94e8549613cyshang    do {
52628a00297189c323096aae8e2975de94e8549613cyshang      Status = BusSpecificDriverOverride->GetDriver (
52728a00297189c323096aae8e2975de94e8549613cyshang                                            BusSpecificDriverOverride,
52828a00297189c323096aae8e2975de94e8549613cyshang                                            &DriverImageHandle
52928a00297189c323096aae8e2975de94e8549613cyshang                                            );
53028a00297189c323096aae8e2975de94e8549613cyshang      if (!EFI_ERROR (Status)) {
53128a00297189c323096aae8e2975de94e8549613cyshang        AddSortedDriverBindingProtocol (
53228a00297189c323096aae8e2975de94e8549613cyshang          DriverImageHandle,
53328a00297189c323096aae8e2975de94e8549613cyshang          &NumberOfSortedDriverBindingProtocols,
53428a00297189c323096aae8e2975de94e8549613cyshang          SortedDriverBindingProtocols,
53528a00297189c323096aae8e2975de94e8549613cyshang          DriverBindingHandleCount,
536adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney          DriverBindingHandleBuffer,
537adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney          TRUE
53828a00297189c323096aae8e2975de94e8549613cyshang          );
53928a00297189c323096aae8e2975de94e8549613cyshang      }
54028a00297189c323096aae8e2975de94e8549613cyshang    } while (!EFI_ERROR (Status));
54128a00297189c323096aae8e2975de94e8549613cyshang  }
54228a00297189c323096aae8e2975de94e8549613cyshang
54328a00297189c323096aae8e2975de94e8549613cyshang  //
54428a00297189c323096aae8e2975de94e8549613cyshang  // Then add all the remaining Driver Binding Protocols
54528a00297189c323096aae8e2975de94e8549613cyshang  //
54628a00297189c323096aae8e2975de94e8549613cyshang  SortIndex = NumberOfSortedDriverBindingProtocols;
54728a00297189c323096aae8e2975de94e8549613cyshang  for (Index = 0; Index < DriverBindingHandleCount; Index++) {
54828a00297189c323096aae8e2975de94e8549613cyshang    AddSortedDriverBindingProtocol (
54928a00297189c323096aae8e2975de94e8549613cyshang      DriverBindingHandleBuffer[Index],
55028a00297189c323096aae8e2975de94e8549613cyshang      &NumberOfSortedDriverBindingProtocols,
55128a00297189c323096aae8e2975de94e8549613cyshang      SortedDriverBindingProtocols,
55228a00297189c323096aae8e2975de94e8549613cyshang      DriverBindingHandleCount,
553adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney      DriverBindingHandleBuffer,
554adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney      FALSE
55528a00297189c323096aae8e2975de94e8549613cyshang      );
55628a00297189c323096aae8e2975de94e8549613cyshang  }
55728a00297189c323096aae8e2975de94e8549613cyshang
55828a00297189c323096aae8e2975de94e8549613cyshang  //
55928a00297189c323096aae8e2975de94e8549613cyshang  // Free the Driver Binding Handle Buffer
56028a00297189c323096aae8e2975de94e8549613cyshang  //
56128a00297189c323096aae8e2975de94e8549613cyshang  CoreFreePool (DriverBindingHandleBuffer);
56228a00297189c323096aae8e2975de94e8549613cyshang
56328a00297189c323096aae8e2975de94e8549613cyshang  //
56485658066182d23e210209299770edaef26d09085mdkinney  // If the number of Driver Binding Protocols has increased since this function started, then return
56585658066182d23e210209299770edaef26d09085mdkinney  // EFI_NOT_READY, so it will be restarted
56685658066182d23e210209299770edaef26d09085mdkinney  //
56785658066182d23e210209299770edaef26d09085mdkinney  if (NumberOfSortedDriverBindingProtocols > DriverBindingHandleCount) {
56885658066182d23e210209299770edaef26d09085mdkinney    //
56985658066182d23e210209299770edaef26d09085mdkinney    // Free any buffers that were allocated with AllocatePool()
57085658066182d23e210209299770edaef26d09085mdkinney    //
57185658066182d23e210209299770edaef26d09085mdkinney    CoreFreePool (SortedDriverBindingProtocols);
57285658066182d23e210209299770edaef26d09085mdkinney
57385658066182d23e210209299770edaef26d09085mdkinney    return EFI_NOT_READY;
57485658066182d23e210209299770edaef26d09085mdkinney  }
57585658066182d23e210209299770edaef26d09085mdkinney
57685658066182d23e210209299770edaef26d09085mdkinney  //
57728a00297189c323096aae8e2975de94e8549613cyshang  // Sort the remaining DriverBinding Protocol based on their Version field from
57828a00297189c323096aae8e2975de94e8549613cyshang  // highest to lowest.
57928a00297189c323096aae8e2975de94e8549613cyshang  //
58028a00297189c323096aae8e2975de94e8549613cyshang  for ( ; SortIndex < NumberOfSortedDriverBindingProtocols; SortIndex++) {
58128a00297189c323096aae8e2975de94e8549613cyshang    HighestVersion = SortedDriverBindingProtocols[SortIndex]->Version;
58228a00297189c323096aae8e2975de94e8549613cyshang    HighestIndex   = SortIndex;
58328a00297189c323096aae8e2975de94e8549613cyshang    for (Index = SortIndex + 1; Index < NumberOfSortedDriverBindingProtocols; Index++) {
58428a00297189c323096aae8e2975de94e8549613cyshang      if (SortedDriverBindingProtocols[Index]->Version > HighestVersion) {
58528a00297189c323096aae8e2975de94e8549613cyshang        HighestVersion = SortedDriverBindingProtocols[Index]->Version;
58628a00297189c323096aae8e2975de94e8549613cyshang        HighestIndex   = Index;
58728a00297189c323096aae8e2975de94e8549613cyshang      }
58828a00297189c323096aae8e2975de94e8549613cyshang    }
58928a00297189c323096aae8e2975de94e8549613cyshang    if (SortIndex != HighestIndex) {
59028a00297189c323096aae8e2975de94e8549613cyshang      DriverBinding = SortedDriverBindingProtocols[SortIndex];
59128a00297189c323096aae8e2975de94e8549613cyshang      SortedDriverBindingProtocols[SortIndex] = SortedDriverBindingProtocols[HighestIndex];
59228a00297189c323096aae8e2975de94e8549613cyshang      SortedDriverBindingProtocols[HighestIndex] = DriverBinding;
59328a00297189c323096aae8e2975de94e8549613cyshang    }
59428a00297189c323096aae8e2975de94e8549613cyshang  }
59528a00297189c323096aae8e2975de94e8549613cyshang
59628a00297189c323096aae8e2975de94e8549613cyshang  //
59728a00297189c323096aae8e2975de94e8549613cyshang  // Loop until no more drivers can be started on ControllerHandle
59828a00297189c323096aae8e2975de94e8549613cyshang  //
59928a00297189c323096aae8e2975de94e8549613cyshang  OneStarted = FALSE;
60028a00297189c323096aae8e2975de94e8549613cyshang  do {
60128a00297189c323096aae8e2975de94e8549613cyshang
60228a00297189c323096aae8e2975de94e8549613cyshang    //
60328a00297189c323096aae8e2975de94e8549613cyshang    // Loop through the sorted Driver Binding Protocol Instances in order, and see if
60428a00297189c323096aae8e2975de94e8549613cyshang    // any of the Driver Binding Protocols support the controller specified by
60528a00297189c323096aae8e2975de94e8549613cyshang    // ControllerHandle.
60628a00297189c323096aae8e2975de94e8549613cyshang    //
60728a00297189c323096aae8e2975de94e8549613cyshang    DriverBinding = NULL;
60828a00297189c323096aae8e2975de94e8549613cyshang    DriverFound = FALSE;
60928a00297189c323096aae8e2975de94e8549613cyshang    for (Index = 0; (Index < NumberOfSortedDriverBindingProtocols) && !DriverFound; Index++) {
61028a00297189c323096aae8e2975de94e8549613cyshang      if (SortedDriverBindingProtocols[Index] != NULL) {
61128a00297189c323096aae8e2975de94e8549613cyshang        DriverBinding = SortedDriverBindingProtocols[Index];
61228a00297189c323096aae8e2975de94e8549613cyshang        Status = DriverBinding->Supported(
61328a00297189c323096aae8e2975de94e8549613cyshang                                  DriverBinding,
61428a00297189c323096aae8e2975de94e8549613cyshang                                  ControllerHandle,
61528a00297189c323096aae8e2975de94e8549613cyshang                                  RemainingDevicePath
61628a00297189c323096aae8e2975de94e8549613cyshang                                  );
61728a00297189c323096aae8e2975de94e8549613cyshang        if (!EFI_ERROR (Status)) {
61828a00297189c323096aae8e2975de94e8549613cyshang          SortedDriverBindingProtocols[Index] = NULL;
61928a00297189c323096aae8e2975de94e8549613cyshang          DriverFound = TRUE;
62028a00297189c323096aae8e2975de94e8549613cyshang
62128a00297189c323096aae8e2975de94e8549613cyshang          //
62228a00297189c323096aae8e2975de94e8549613cyshang          // A driver was found that supports ControllerHandle, so attempt to start the driver
62328a00297189c323096aae8e2975de94e8549613cyshang          // on ControllerHandle.
62428a00297189c323096aae8e2975de94e8549613cyshang          //
625adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney          PERF_START (DriverBinding->DriverBindingHandle, DRIVERBINDING_START_TOK, NULL, 0);
62628a00297189c323096aae8e2975de94e8549613cyshang          Status = DriverBinding->Start (
62728a00297189c323096aae8e2975de94e8549613cyshang                                    DriverBinding,
62828a00297189c323096aae8e2975de94e8549613cyshang                                    ControllerHandle,
62928a00297189c323096aae8e2975de94e8549613cyshang                                    RemainingDevicePath
63028a00297189c323096aae8e2975de94e8549613cyshang                                    );
631adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney          PERF_END (DriverBinding->DriverBindingHandle, DRIVERBINDING_START_TOK, NULL, 0);
63228a00297189c323096aae8e2975de94e8549613cyshang
63328a00297189c323096aae8e2975de94e8549613cyshang          if (!EFI_ERROR (Status)) {
63428a00297189c323096aae8e2975de94e8549613cyshang            //
63528a00297189c323096aae8e2975de94e8549613cyshang            // The driver was successfully started on ControllerHandle, so set a flag
63628a00297189c323096aae8e2975de94e8549613cyshang            //
63728a00297189c323096aae8e2975de94e8549613cyshang            OneStarted = TRUE;
63828a00297189c323096aae8e2975de94e8549613cyshang          }
63928a00297189c323096aae8e2975de94e8549613cyshang        }
64028a00297189c323096aae8e2975de94e8549613cyshang      }
64128a00297189c323096aae8e2975de94e8549613cyshang    }
64228a00297189c323096aae8e2975de94e8549613cyshang  } while (DriverFound);
64328a00297189c323096aae8e2975de94e8549613cyshang
64428a00297189c323096aae8e2975de94e8549613cyshang  //
64528a00297189c323096aae8e2975de94e8549613cyshang  // Free any buffers that were allocated with AllocatePool()
64628a00297189c323096aae8e2975de94e8549613cyshang  //
64728a00297189c323096aae8e2975de94e8549613cyshang  CoreFreePool (SortedDriverBindingProtocols);
64828a00297189c323096aae8e2975de94e8549613cyshang
64928a00297189c323096aae8e2975de94e8549613cyshang  //
65028a00297189c323096aae8e2975de94e8549613cyshang  // If at least one driver was started on ControllerHandle, then return EFI_SUCCESS.
65128a00297189c323096aae8e2975de94e8549613cyshang  //
65228a00297189c323096aae8e2975de94e8549613cyshang  if (OneStarted) {
65328a00297189c323096aae8e2975de94e8549613cyshang    return EFI_SUCCESS;
65428a00297189c323096aae8e2975de94e8549613cyshang  }
65528a00297189c323096aae8e2975de94e8549613cyshang
65628a00297189c323096aae8e2975de94e8549613cyshang  //
65728a00297189c323096aae8e2975de94e8549613cyshang  // If no drivers started and RemainingDevicePath is an End Device Path Node, then return EFI_SUCCESS
65828a00297189c323096aae8e2975de94e8549613cyshang  //
65928a00297189c323096aae8e2975de94e8549613cyshang  if (RemainingDevicePath != NULL) {
66028a00297189c323096aae8e2975de94e8549613cyshang    if (IsDevicePathEnd (RemainingDevicePath)) {
66128a00297189c323096aae8e2975de94e8549613cyshang      return EFI_SUCCESS;
66228a00297189c323096aae8e2975de94e8549613cyshang    }
66328a00297189c323096aae8e2975de94e8549613cyshang  }
66428a00297189c323096aae8e2975de94e8549613cyshang
66528a00297189c323096aae8e2975de94e8549613cyshang  //
66628a00297189c323096aae8e2975de94e8549613cyshang  // Otherwise, no drivers were started on ControllerHandle, so return EFI_NOT_FOUND
66728a00297189c323096aae8e2975de94e8549613cyshang  //
66828a00297189c323096aae8e2975de94e8549613cyshang  return EFI_NOT_FOUND;
66928a00297189c323096aae8e2975de94e8549613cyshang}
67028a00297189c323096aae8e2975de94e8549613cyshang
67128a00297189c323096aae8e2975de94e8549613cyshang
67228a00297189c323096aae8e2975de94e8549613cyshangEFI_STATUS
67328a00297189c323096aae8e2975de94e8549613cyshangEFIAPI
67428a00297189c323096aae8e2975de94e8549613cyshangCoreDisconnectController (
67528a00297189c323096aae8e2975de94e8549613cyshang  IN  EFI_HANDLE  ControllerHandle,
67628a00297189c323096aae8e2975de94e8549613cyshang  IN  EFI_HANDLE  DriverImageHandle  OPTIONAL,
67728a00297189c323096aae8e2975de94e8549613cyshang  IN  EFI_HANDLE  ChildHandle        OPTIONAL
67828a00297189c323096aae8e2975de94e8549613cyshang  )
67928a00297189c323096aae8e2975de94e8549613cyshang/*++
68028a00297189c323096aae8e2975de94e8549613cyshang
68128a00297189c323096aae8e2975de94e8549613cyshangRoutine Description:
68228a00297189c323096aae8e2975de94e8549613cyshang
68328a00297189c323096aae8e2975de94e8549613cyshang  Disonnects a controller from a driver
68428a00297189c323096aae8e2975de94e8549613cyshang
68528a00297189c323096aae8e2975de94e8549613cyshangArguments:
68628a00297189c323096aae8e2975de94e8549613cyshang
68728a00297189c323096aae8e2975de94e8549613cyshang  ControllerHandle  - ControllerHandle The handle of the controller from which driver(s)
68828a00297189c323096aae8e2975de94e8549613cyshang                        are to be disconnected.
68928a00297189c323096aae8e2975de94e8549613cyshang  DriverImageHandle - DriverImageHandle The driver to disconnect from ControllerHandle.
69028a00297189c323096aae8e2975de94e8549613cyshang  ChildHandle       - ChildHandle The handle of the child to destroy.
69128a00297189c323096aae8e2975de94e8549613cyshang
69228a00297189c323096aae8e2975de94e8549613cyshangReturns:
69328a00297189c323096aae8e2975de94e8549613cyshang
69428a00297189c323096aae8e2975de94e8549613cyshang  EFI_SUCCESS           -  One or more drivers were disconnected from the controller.
69528a00297189c323096aae8e2975de94e8549613cyshang  EFI_SUCCESS           -  On entry, no drivers are managing ControllerHandle.
69628a00297189c323096aae8e2975de94e8549613cyshang  EFI_SUCCESS           -  DriverImageHandle is not NULL, and on entry DriverImageHandle is not managing ControllerHandle.
69728a00297189c323096aae8e2975de94e8549613cyshang  EFI_INVALID_PARAMETER -  ControllerHandle is not a valid EFI_HANDLE.
69828a00297189c323096aae8e2975de94e8549613cyshang  EFI_INVALID_PARAMETER -  DriverImageHandle is not NULL, and it is not a valid EFI_HANDLE.
69928a00297189c323096aae8e2975de94e8549613cyshang  EFI_INVALID_PARAMETER -  ChildHandle is not NULL, and it is not a valid EFI_HANDLE.
70028a00297189c323096aae8e2975de94e8549613cyshang  EFI_OUT_OF_RESOURCES  -  There are not enough resources available to disconnect any drivers from ControllerHandle.
70128a00297189c323096aae8e2975de94e8549613cyshang  EFI_DEVICE_ERROR      -  The controller could not be disconnected because of a device error.
70228a00297189c323096aae8e2975de94e8549613cyshang
70328a00297189c323096aae8e2975de94e8549613cyshang--*/
70428a00297189c323096aae8e2975de94e8549613cyshang{
70528a00297189c323096aae8e2975de94e8549613cyshang  EFI_STATUS                          Status;
70628a00297189c323096aae8e2975de94e8549613cyshang  IHANDLE                             *Handle;
70728a00297189c323096aae8e2975de94e8549613cyshang  EFI_HANDLE                          *DriverImageHandleBuffer;
70828a00297189c323096aae8e2975de94e8549613cyshang  EFI_HANDLE                          *ChildBuffer;
70928a00297189c323096aae8e2975de94e8549613cyshang  UINTN                               Index;
71028a00297189c323096aae8e2975de94e8549613cyshang  UINTN                               HandleIndex;
71128a00297189c323096aae8e2975de94e8549613cyshang  UINTN                               DriverImageHandleCount;
71228a00297189c323096aae8e2975de94e8549613cyshang  UINTN                               ChildrenToStop;
71328a00297189c323096aae8e2975de94e8549613cyshang  UINTN                               ChildBufferCount;
71428a00297189c323096aae8e2975de94e8549613cyshang  UINTN                               StopCount;
71528a00297189c323096aae8e2975de94e8549613cyshang  BOOLEAN                             Duplicate;
71628a00297189c323096aae8e2975de94e8549613cyshang  BOOLEAN                             ChildHandleValid;
71728a00297189c323096aae8e2975de94e8549613cyshang  BOOLEAN                             DriverImageHandleValid;
71828a00297189c323096aae8e2975de94e8549613cyshang  LIST_ENTRY                          *Link;
71928a00297189c323096aae8e2975de94e8549613cyshang  LIST_ENTRY                          *ProtLink;
72028a00297189c323096aae8e2975de94e8549613cyshang  OPEN_PROTOCOL_DATA                  *OpenData;
72128a00297189c323096aae8e2975de94e8549613cyshang  PROTOCOL_INTERFACE                  *Prot;
72228a00297189c323096aae8e2975de94e8549613cyshang  EFI_DRIVER_BINDING_PROTOCOL         *DriverBinding;
72385658066182d23e210209299770edaef26d09085mdkinney  EFI_HANDLE                          *LoadedImageHandleBuffer;
72485658066182d23e210209299770edaef26d09085mdkinney  UINTN                               LoadedImageHandleCount;
72585658066182d23e210209299770edaef26d09085mdkinney  LOADED_IMAGE_PRIVATE_DATA           *Image;
72628a00297189c323096aae8e2975de94e8549613cyshang
72728a00297189c323096aae8e2975de94e8549613cyshang  //
72828a00297189c323096aae8e2975de94e8549613cyshang  // Make sure ControllerHandle is valid
72928a00297189c323096aae8e2975de94e8549613cyshang  //
73028a00297189c323096aae8e2975de94e8549613cyshang  Status = CoreValidateHandle (ControllerHandle);
73128a00297189c323096aae8e2975de94e8549613cyshang  if (EFI_ERROR (Status)) {
73228a00297189c323096aae8e2975de94e8549613cyshang    return Status;
73328a00297189c323096aae8e2975de94e8549613cyshang  }
73428a00297189c323096aae8e2975de94e8549613cyshang
73528a00297189c323096aae8e2975de94e8549613cyshang  //
73628a00297189c323096aae8e2975de94e8549613cyshang  // Make sure ChildHandle is valid if it is not NULL
73728a00297189c323096aae8e2975de94e8549613cyshang  //
73828a00297189c323096aae8e2975de94e8549613cyshang  if (ChildHandle != NULL) {
73928a00297189c323096aae8e2975de94e8549613cyshang    Status = CoreValidateHandle (ChildHandle);
74028a00297189c323096aae8e2975de94e8549613cyshang    if (EFI_ERROR (Status)) {
74128a00297189c323096aae8e2975de94e8549613cyshang      return Status;
74228a00297189c323096aae8e2975de94e8549613cyshang    }
74328a00297189c323096aae8e2975de94e8549613cyshang  }
74428a00297189c323096aae8e2975de94e8549613cyshang
74528a00297189c323096aae8e2975de94e8549613cyshang  Handle = ControllerHandle;
74628a00297189c323096aae8e2975de94e8549613cyshang
74728a00297189c323096aae8e2975de94e8549613cyshang  //
74828a00297189c323096aae8e2975de94e8549613cyshang  // Get list of drivers that are currently managing ControllerHandle
74928a00297189c323096aae8e2975de94e8549613cyshang  //
75028a00297189c323096aae8e2975de94e8549613cyshang  DriverImageHandleBuffer = NULL;
75128a00297189c323096aae8e2975de94e8549613cyshang  DriverImageHandleCount  = 1;
75228a00297189c323096aae8e2975de94e8549613cyshang
75328a00297189c323096aae8e2975de94e8549613cyshang  if (DriverImageHandle == NULL) {
75428a00297189c323096aae8e2975de94e8549613cyshang    //
75528a00297189c323096aae8e2975de94e8549613cyshang    // Look at each protocol interface for a match
75628a00297189c323096aae8e2975de94e8549613cyshang    //
75728a00297189c323096aae8e2975de94e8549613cyshang    DriverImageHandleCount = 0;
75828a00297189c323096aae8e2975de94e8549613cyshang
75928a00297189c323096aae8e2975de94e8549613cyshang    CoreAcquireProtocolLock ();
76028a00297189c323096aae8e2975de94e8549613cyshang    for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
76128a00297189c323096aae8e2975de94e8549613cyshang      Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
76228a00297189c323096aae8e2975de94e8549613cyshang      for (ProtLink = Prot->OpenList.ForwardLink;
76328a00297189c323096aae8e2975de94e8549613cyshang           ProtLink != &Prot->OpenList;
76428a00297189c323096aae8e2975de94e8549613cyshang           ProtLink = ProtLink->ForwardLink) {
76528a00297189c323096aae8e2975de94e8549613cyshang        OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
76628a00297189c323096aae8e2975de94e8549613cyshang        if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
76728a00297189c323096aae8e2975de94e8549613cyshang          DriverImageHandleCount++;
76828a00297189c323096aae8e2975de94e8549613cyshang        }
76928a00297189c323096aae8e2975de94e8549613cyshang      }
77028a00297189c323096aae8e2975de94e8549613cyshang    }
77128a00297189c323096aae8e2975de94e8549613cyshang    CoreReleaseProtocolLock ();
77228a00297189c323096aae8e2975de94e8549613cyshang
77328a00297189c323096aae8e2975de94e8549613cyshang    //
77428a00297189c323096aae8e2975de94e8549613cyshang    // If there are no drivers managing this controller, then return EFI_SUCCESS
77528a00297189c323096aae8e2975de94e8549613cyshang    //
77628a00297189c323096aae8e2975de94e8549613cyshang    if (DriverImageHandleCount == 0) {
77728a00297189c323096aae8e2975de94e8549613cyshang      Status = EFI_SUCCESS;
77828a00297189c323096aae8e2975de94e8549613cyshang      goto Done;
77928a00297189c323096aae8e2975de94e8549613cyshang    }
78028a00297189c323096aae8e2975de94e8549613cyshang
78128a00297189c323096aae8e2975de94e8549613cyshang    DriverImageHandleBuffer = CoreAllocateBootServicesPool (sizeof (EFI_HANDLE) * DriverImageHandleCount);
78228a00297189c323096aae8e2975de94e8549613cyshang    if (DriverImageHandleBuffer == NULL) {
78328a00297189c323096aae8e2975de94e8549613cyshang      Status = EFI_OUT_OF_RESOURCES;
78428a00297189c323096aae8e2975de94e8549613cyshang      goto Done;
78528a00297189c323096aae8e2975de94e8549613cyshang    }
78628a00297189c323096aae8e2975de94e8549613cyshang
78728a00297189c323096aae8e2975de94e8549613cyshang    DriverImageHandleCount = 0;
78828a00297189c323096aae8e2975de94e8549613cyshang
78928a00297189c323096aae8e2975de94e8549613cyshang    CoreAcquireProtocolLock ();
79028a00297189c323096aae8e2975de94e8549613cyshang    for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
79128a00297189c323096aae8e2975de94e8549613cyshang      Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
79228a00297189c323096aae8e2975de94e8549613cyshang      for (ProtLink = Prot->OpenList.ForwardLink;
79328a00297189c323096aae8e2975de94e8549613cyshang           ProtLink != &Prot->OpenList;
79428a00297189c323096aae8e2975de94e8549613cyshang           ProtLink = ProtLink->ForwardLink) {
79528a00297189c323096aae8e2975de94e8549613cyshang        OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
79628a00297189c323096aae8e2975de94e8549613cyshang        if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
79728a00297189c323096aae8e2975de94e8549613cyshang          Duplicate = FALSE;
79828a00297189c323096aae8e2975de94e8549613cyshang          for (Index = 0; Index< DriverImageHandleCount; Index++) {
79928a00297189c323096aae8e2975de94e8549613cyshang            if (DriverImageHandleBuffer[Index] == OpenData->AgentHandle) {
80028a00297189c323096aae8e2975de94e8549613cyshang              Duplicate = TRUE;
80128a00297189c323096aae8e2975de94e8549613cyshang              break;
80228a00297189c323096aae8e2975de94e8549613cyshang            }
80328a00297189c323096aae8e2975de94e8549613cyshang          }
80428a00297189c323096aae8e2975de94e8549613cyshang          if (!Duplicate) {
80528a00297189c323096aae8e2975de94e8549613cyshang            DriverImageHandleBuffer[DriverImageHandleCount] = OpenData->AgentHandle;
80628a00297189c323096aae8e2975de94e8549613cyshang            DriverImageHandleCount++;
80728a00297189c323096aae8e2975de94e8549613cyshang          }
80828a00297189c323096aae8e2975de94e8549613cyshang        }
80928a00297189c323096aae8e2975de94e8549613cyshang      }
81028a00297189c323096aae8e2975de94e8549613cyshang    }
81128a00297189c323096aae8e2975de94e8549613cyshang    CoreReleaseProtocolLock ();
81228a00297189c323096aae8e2975de94e8549613cyshang  }
81328a00297189c323096aae8e2975de94e8549613cyshang
81428a00297189c323096aae8e2975de94e8549613cyshang  StopCount = 0;
81528a00297189c323096aae8e2975de94e8549613cyshang  for (HandleIndex = 0; HandleIndex < DriverImageHandleCount; HandleIndex++) {
81628a00297189c323096aae8e2975de94e8549613cyshang
81728a00297189c323096aae8e2975de94e8549613cyshang    if (DriverImageHandleBuffer != NULL) {
81828a00297189c323096aae8e2975de94e8549613cyshang      DriverImageHandle = DriverImageHandleBuffer[HandleIndex];
81928a00297189c323096aae8e2975de94e8549613cyshang    }
82028a00297189c323096aae8e2975de94e8549613cyshang
82128a00297189c323096aae8e2975de94e8549613cyshang    //
82228a00297189c323096aae8e2975de94e8549613cyshang    // Get the Driver Binding Protocol of the driver that is managing this controller
82328a00297189c323096aae8e2975de94e8549613cyshang    //
82428a00297189c323096aae8e2975de94e8549613cyshang    Status = CoreHandleProtocol (
82528a00297189c323096aae8e2975de94e8549613cyshang               DriverImageHandle,
82628a00297189c323096aae8e2975de94e8549613cyshang               &gEfiDriverBindingProtocolGuid,
82728a00297189c323096aae8e2975de94e8549613cyshang               (VOID **)&DriverBinding
82828a00297189c323096aae8e2975de94e8549613cyshang               );
82928a00297189c323096aae8e2975de94e8549613cyshang    if (EFI_ERROR (Status)) {
83028a00297189c323096aae8e2975de94e8549613cyshang      Status = EFI_INVALID_PARAMETER;
83128a00297189c323096aae8e2975de94e8549613cyshang      goto Done;
83228a00297189c323096aae8e2975de94e8549613cyshang    }
83328a00297189c323096aae8e2975de94e8549613cyshang
83428a00297189c323096aae8e2975de94e8549613cyshang    //
83528a00297189c323096aae8e2975de94e8549613cyshang    // Look at each protocol interface for a match
83628a00297189c323096aae8e2975de94e8549613cyshang    //
83728a00297189c323096aae8e2975de94e8549613cyshang    DriverImageHandleValid = FALSE;
83828a00297189c323096aae8e2975de94e8549613cyshang    ChildBufferCount = 0;
83928a00297189c323096aae8e2975de94e8549613cyshang
84028a00297189c323096aae8e2975de94e8549613cyshang    CoreAcquireProtocolLock ();
84128a00297189c323096aae8e2975de94e8549613cyshang    for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
84228a00297189c323096aae8e2975de94e8549613cyshang      Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
84328a00297189c323096aae8e2975de94e8549613cyshang      for (ProtLink = Prot->OpenList.ForwardLink;
84428a00297189c323096aae8e2975de94e8549613cyshang           ProtLink != &Prot->OpenList;
84528a00297189c323096aae8e2975de94e8549613cyshang           ProtLink = ProtLink->ForwardLink) {
84628a00297189c323096aae8e2975de94e8549613cyshang        OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
84728a00297189c323096aae8e2975de94e8549613cyshang        if (OpenData->AgentHandle == DriverImageHandle) {
84828a00297189c323096aae8e2975de94e8549613cyshang          if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
84928a00297189c323096aae8e2975de94e8549613cyshang            ChildBufferCount++;
85028a00297189c323096aae8e2975de94e8549613cyshang          }
85128a00297189c323096aae8e2975de94e8549613cyshang          if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
85228a00297189c323096aae8e2975de94e8549613cyshang            DriverImageHandleValid = TRUE;
85328a00297189c323096aae8e2975de94e8549613cyshang          }
85428a00297189c323096aae8e2975de94e8549613cyshang        }
85528a00297189c323096aae8e2975de94e8549613cyshang      }
85628a00297189c323096aae8e2975de94e8549613cyshang    }
85728a00297189c323096aae8e2975de94e8549613cyshang    CoreReleaseProtocolLock ();
85828a00297189c323096aae8e2975de94e8549613cyshang
85928a00297189c323096aae8e2975de94e8549613cyshang    if (DriverImageHandleValid) {
86028a00297189c323096aae8e2975de94e8549613cyshang      ChildHandleValid = FALSE;
86128a00297189c323096aae8e2975de94e8549613cyshang      ChildBuffer = NULL;
86228a00297189c323096aae8e2975de94e8549613cyshang      if (ChildBufferCount != 0) {
86328a00297189c323096aae8e2975de94e8549613cyshang        ChildBuffer = CoreAllocateBootServicesPool (sizeof (EFI_HANDLE) * ChildBufferCount);
86428a00297189c323096aae8e2975de94e8549613cyshang        if (ChildBuffer == NULL) {
86528a00297189c323096aae8e2975de94e8549613cyshang          Status = EFI_OUT_OF_RESOURCES;
86628a00297189c323096aae8e2975de94e8549613cyshang          goto Done;
86728a00297189c323096aae8e2975de94e8549613cyshang        }
86828a00297189c323096aae8e2975de94e8549613cyshang
86928a00297189c323096aae8e2975de94e8549613cyshang        ChildBufferCount = 0;
87028a00297189c323096aae8e2975de94e8549613cyshang
87128a00297189c323096aae8e2975de94e8549613cyshang        CoreAcquireProtocolLock ();
87228a00297189c323096aae8e2975de94e8549613cyshang        for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
87328a00297189c323096aae8e2975de94e8549613cyshang          Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
87428a00297189c323096aae8e2975de94e8549613cyshang          for (ProtLink = Prot->OpenList.ForwardLink;
87528a00297189c323096aae8e2975de94e8549613cyshang               ProtLink != &Prot->OpenList;
87628a00297189c323096aae8e2975de94e8549613cyshang               ProtLink = ProtLink->ForwardLink) {
87728a00297189c323096aae8e2975de94e8549613cyshang            OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
87828a00297189c323096aae8e2975de94e8549613cyshang            if ((OpenData->AgentHandle == DriverImageHandle) &&
87928a00297189c323096aae8e2975de94e8549613cyshang                ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0)) {
88028a00297189c323096aae8e2975de94e8549613cyshang              Duplicate = FALSE;
88128a00297189c323096aae8e2975de94e8549613cyshang              for (Index = 0; Index < ChildBufferCount; Index++) {
88228a00297189c323096aae8e2975de94e8549613cyshang                if (ChildBuffer[Index] == OpenData->ControllerHandle) {
88328a00297189c323096aae8e2975de94e8549613cyshang                  Duplicate = TRUE;
88428a00297189c323096aae8e2975de94e8549613cyshang                  break;
88528a00297189c323096aae8e2975de94e8549613cyshang                }
88628a00297189c323096aae8e2975de94e8549613cyshang              }
88728a00297189c323096aae8e2975de94e8549613cyshang              if (!Duplicate) {
88828a00297189c323096aae8e2975de94e8549613cyshang                ChildBuffer[ChildBufferCount] = OpenData->ControllerHandle;
88928a00297189c323096aae8e2975de94e8549613cyshang                if (ChildHandle == ChildBuffer[ChildBufferCount]) {
89028a00297189c323096aae8e2975de94e8549613cyshang                  ChildHandleValid = TRUE;
89128a00297189c323096aae8e2975de94e8549613cyshang                }
89228a00297189c323096aae8e2975de94e8549613cyshang                ChildBufferCount++;
89328a00297189c323096aae8e2975de94e8549613cyshang              }
89428a00297189c323096aae8e2975de94e8549613cyshang            }
89528a00297189c323096aae8e2975de94e8549613cyshang          }
89628a00297189c323096aae8e2975de94e8549613cyshang        }
89728a00297189c323096aae8e2975de94e8549613cyshang        CoreReleaseProtocolLock ();
89828a00297189c323096aae8e2975de94e8549613cyshang      }
89928a00297189c323096aae8e2975de94e8549613cyshang
90028a00297189c323096aae8e2975de94e8549613cyshang      if (ChildHandle == NULL || ChildHandleValid) {
90128a00297189c323096aae8e2975de94e8549613cyshang        ChildrenToStop = 0;
90228a00297189c323096aae8e2975de94e8549613cyshang        Status = EFI_SUCCESS;
90328a00297189c323096aae8e2975de94e8549613cyshang        if (ChildBufferCount > 0) {
90428a00297189c323096aae8e2975de94e8549613cyshang          if (ChildHandle != NULL) {
90528a00297189c323096aae8e2975de94e8549613cyshang            ChildrenToStop = 1;
90628a00297189c323096aae8e2975de94e8549613cyshang            Status = DriverBinding->Stop (DriverBinding, ControllerHandle, ChildrenToStop, &ChildHandle);
90728a00297189c323096aae8e2975de94e8549613cyshang          } else {
90828a00297189c323096aae8e2975de94e8549613cyshang            ChildrenToStop = ChildBufferCount;
90928a00297189c323096aae8e2975de94e8549613cyshang            Status = DriverBinding->Stop (DriverBinding, ControllerHandle, ChildrenToStop, ChildBuffer);
91028a00297189c323096aae8e2975de94e8549613cyshang          }
91128a00297189c323096aae8e2975de94e8549613cyshang        }
91228a00297189c323096aae8e2975de94e8549613cyshang        if (!EFI_ERROR (Status) && ((ChildHandle == NULL) || (ChildBufferCount == ChildrenToStop))) {
91328a00297189c323096aae8e2975de94e8549613cyshang          Status = DriverBinding->Stop (DriverBinding, ControllerHandle, 0, NULL);
91428a00297189c323096aae8e2975de94e8549613cyshang        }
91528a00297189c323096aae8e2975de94e8549613cyshang        if (!EFI_ERROR (Status)) {
91628a00297189c323096aae8e2975de94e8549613cyshang          StopCount++;
91728a00297189c323096aae8e2975de94e8549613cyshang        }
91828a00297189c323096aae8e2975de94e8549613cyshang      }
91928a00297189c323096aae8e2975de94e8549613cyshang
92028a00297189c323096aae8e2975de94e8549613cyshang      if (ChildBuffer != NULL) {
92128a00297189c323096aae8e2975de94e8549613cyshang        CoreFreePool (ChildBuffer);
92228a00297189c323096aae8e2975de94e8549613cyshang      }
92328a00297189c323096aae8e2975de94e8549613cyshang    }
92428a00297189c323096aae8e2975de94e8549613cyshang  }
92528a00297189c323096aae8e2975de94e8549613cyshang
92628a00297189c323096aae8e2975de94e8549613cyshang  if (StopCount > 0) {
92785658066182d23e210209299770edaef26d09085mdkinney    //
92885658066182d23e210209299770edaef26d09085mdkinney    // If the Loaded Image Protocols do not already need to be repaired, then
92985658066182d23e210209299770edaef26d09085mdkinney    // check the status of the DeviceHandle field of all Loaded Image Protocols
93085658066182d23e210209299770edaef26d09085mdkinney    // to determine if any of them now need repair because a sucessful Stop()
93185658066182d23e210209299770edaef26d09085mdkinney    // may have destroyed the DeviceHandle value in the Loaded Image Protocol
93285658066182d23e210209299770edaef26d09085mdkinney    //
93385658066182d23e210209299770edaef26d09085mdkinney    if (!mRepairLoadedImage) {
93485658066182d23e210209299770edaef26d09085mdkinney      //
93585658066182d23e210209299770edaef26d09085mdkinney      // Get list of all Loaded Image Protocol Instances
93685658066182d23e210209299770edaef26d09085mdkinney      //
93785658066182d23e210209299770edaef26d09085mdkinney      Status = CoreLocateHandleBuffer (
93885658066182d23e210209299770edaef26d09085mdkinney                ByProtocol,
93985658066182d23e210209299770edaef26d09085mdkinney                &gEfiLoadedImageProtocolGuid,
94085658066182d23e210209299770edaef26d09085mdkinney                NULL,
94185658066182d23e210209299770edaef26d09085mdkinney                &LoadedImageHandleCount,
94285658066182d23e210209299770edaef26d09085mdkinney                &LoadedImageHandleBuffer
94385658066182d23e210209299770edaef26d09085mdkinney                );
94485658066182d23e210209299770edaef26d09085mdkinney      if (!EFI_ERROR (Status) && LoadedImageHandleCount != 0) {
94585658066182d23e210209299770edaef26d09085mdkinney        for (Index = 0; Index < LoadedImageHandleCount; Index++) {
94685658066182d23e210209299770edaef26d09085mdkinney          //
94785658066182d23e210209299770edaef26d09085mdkinney          // Retrieve the Loaded Image Protocol
94885658066182d23e210209299770edaef26d09085mdkinney          //
94985658066182d23e210209299770edaef26d09085mdkinney          Image = CoreLoadedImageInfo (LoadedImageHandleBuffer[Index]);
95085658066182d23e210209299770edaef26d09085mdkinney          if (Image != NULL) {
95185658066182d23e210209299770edaef26d09085mdkinney            //
95285658066182d23e210209299770edaef26d09085mdkinney            // Check to see if the DeviceHandle field is a valid handle
95385658066182d23e210209299770edaef26d09085mdkinney            //
95485658066182d23e210209299770edaef26d09085mdkinney            Status = CoreValidateHandle (Image->Info.DeviceHandle);
95585658066182d23e210209299770edaef26d09085mdkinney            if (EFI_ERROR (Status)) {
95685658066182d23e210209299770edaef26d09085mdkinney              //
95785658066182d23e210209299770edaef26d09085mdkinney              // The DeviceHandle field is not longer a valid handle.  This means
95885658066182d23e210209299770edaef26d09085mdkinney              // that future calls to ConnectController() need to attemp to repair
95985658066182d23e210209299770edaef26d09085mdkinney              // the Loaded Image Protocols with invalid DeviceHandle fields.  Set
96085658066182d23e210209299770edaef26d09085mdkinney              // the flag used by ConnectController().
96185658066182d23e210209299770edaef26d09085mdkinney              //
96285658066182d23e210209299770edaef26d09085mdkinney              mRepairLoadedImage = TRUE;
96385658066182d23e210209299770edaef26d09085mdkinney              break;
96485658066182d23e210209299770edaef26d09085mdkinney            }
96585658066182d23e210209299770edaef26d09085mdkinney          }
96685658066182d23e210209299770edaef26d09085mdkinney        }
96785658066182d23e210209299770edaef26d09085mdkinney        CoreFreePool (LoadedImageHandleBuffer);
96885658066182d23e210209299770edaef26d09085mdkinney      }
96985658066182d23e210209299770edaef26d09085mdkinney    }
97028a00297189c323096aae8e2975de94e8549613cyshang    Status = EFI_SUCCESS;
97128a00297189c323096aae8e2975de94e8549613cyshang  } else {
97228a00297189c323096aae8e2975de94e8549613cyshang    Status = EFI_NOT_FOUND;
97328a00297189c323096aae8e2975de94e8549613cyshang  }
97428a00297189c323096aae8e2975de94e8549613cyshang
97528a00297189c323096aae8e2975de94e8549613cyshangDone:
97628a00297189c323096aae8e2975de94e8549613cyshang
97728a00297189c323096aae8e2975de94e8549613cyshang  if (DriverImageHandleBuffer != NULL) {
97828a00297189c323096aae8e2975de94e8549613cyshang    CoreFreePool (DriverImageHandleBuffer);
97928a00297189c323096aae8e2975de94e8549613cyshang  }
98028a00297189c323096aae8e2975de94e8549613cyshang
98128a00297189c323096aae8e2975de94e8549613cyshang  return Status;
98228a00297189c323096aae8e2975de94e8549613cyshang}
983