DriverSupport.c revision bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bc
123c98c9417908188207408afa3f6901b8aca826aqhuang/** @file
2504214c4870e9183418014634268ce630eb5332algao  Support functions to connect/disconnect UEFI Driver model Protocol
3504214c4870e9183418014634268ce630eb5332algao
4bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgaoCopyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
5cd5ebaa06dca3e6ef3c464081e6defe00d358c69hhtianThis program and the accompanying materials
623c98c9417908188207408afa3f6901b8aca826aqhuangare licensed and made available under the terms and conditions of the BSD License
723c98c9417908188207408afa3f6901b8aca826aqhuangwhich accompanies this distribution.  The full text of the license may be found at
823c98c9417908188207408afa3f6901b8aca826aqhuanghttp://opensource.org/licenses/bsd-license.php
923c98c9417908188207408afa3f6901b8aca826aqhuang
1023c98c9417908188207408afa3f6901b8aca826aqhuangTHE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
1123c98c9417908188207408afa3f6901b8aca826aqhuangWITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
1228a00297189c323096aae8e2975de94e8549613cyshang
13504214c4870e9183418014634268ce630eb5332algao**/
1428a00297189c323096aae8e2975de94e8549613cyshang
159c4ac31cca01b4a503c36616770ea3157bf3bb9eqhuang#include "DxeMain.h"
16ec90508b3d3ff22a698a0446cb09d551d7466045eric_tian#include "Handle.h"
1728a00297189c323096aae8e2975de94e8549613cyshang
1828a00297189c323096aae8e2975de94e8549613cyshang
1928a00297189c323096aae8e2975de94e8549613cyshang//
2028a00297189c323096aae8e2975de94e8549613cyshang// Driver Support Functions
2128a00297189c323096aae8e2975de94e8549613cyshang//
22162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang/**
23162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  Connects one or more drivers to a controller.
24162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
25bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao  @param  ControllerHandle      The handle of the controller to which driver(s) are to be connected.
26bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao  @param  DriverImageHandle     A pointer to an ordered list handles that support the
27bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao                                EFI_DRIVER_BINDING_PROTOCOL.
28bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao  @param  RemainingDevicePath   A pointer to the device path that specifies a child of the
29bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao                                controller specified by ControllerHandle.
30bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao  @param  Recursive             If TRUE, then ConnectController() is called recursively
31bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao                                until the entire tree of controllers below the controller specified
32bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao                                by ControllerHandle have been created. If FALSE, then
33bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao                                the tree of controllers is only expanded one level.
34162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
35bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao  @retval EFI_SUCCESS           1) One or more drivers were connected to ControllerHandle.
36bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao                                2) No drivers were connected to ControllerHandle, but
37bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao                                RemainingDevicePath is not NULL, and it is an End Device
38bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao                                Path Node.
39bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao  @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
40bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao  @retval EFI_NOT_FOUND         1) There are no EFI_DRIVER_BINDING_PROTOCOL instances
41bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao                                present in the system.
42bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao                                2) No drivers were connected to ControllerHandle.
43bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao  @retval EFI_SECURITY_VIOLATION
44bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao                                The user has no permission to start UEFI device drivers on the device path
45bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao                                associated with the ControllerHandle or specified by the RemainingDevicePath.
46162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
47162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang**/
48022c6d45ef78605c173023f53984e4dfaf7b11f4qhuangEFI_STATUS
4928a00297189c323096aae8e2975de94e8549613cyshangEFIAPI
5028a00297189c323096aae8e2975de94e8549613cyshangCoreConnectController (
5128a00297189c323096aae8e2975de94e8549613cyshang  IN  EFI_HANDLE                ControllerHandle,
5228a00297189c323096aae8e2975de94e8549613cyshang  IN  EFI_HANDLE                *DriverImageHandle    OPTIONAL,
5328a00297189c323096aae8e2975de94e8549613cyshang  IN  EFI_DEVICE_PATH_PROTOCOL  *RemainingDevicePath  OPTIONAL,
5428a00297189c323096aae8e2975de94e8549613cyshang  IN  BOOLEAN                   Recursive
5528a00297189c323096aae8e2975de94e8549613cyshang  )
5628a00297189c323096aae8e2975de94e8549613cyshang{
5728a00297189c323096aae8e2975de94e8549613cyshang  EFI_STATUS                           Status;
5828a00297189c323096aae8e2975de94e8549613cyshang  EFI_STATUS                           ReturnStatus;
5928a00297189c323096aae8e2975de94e8549613cyshang  IHANDLE                              *Handle;
6028a00297189c323096aae8e2975de94e8549613cyshang  PROTOCOL_INTERFACE                   *Prot;
6128a00297189c323096aae8e2975de94e8549613cyshang  LIST_ENTRY                           *Link;
6228a00297189c323096aae8e2975de94e8549613cyshang  LIST_ENTRY                           *ProtLink;
6328a00297189c323096aae8e2975de94e8549613cyshang  OPEN_PROTOCOL_DATA                   *OpenData;
6428a00297189c323096aae8e2975de94e8549613cyshang  EFI_DEVICE_PATH_PROTOCOL             *AlignedRemainingDevicePath;
6585658066182d23e210209299770edaef26d09085mdkinney  EFI_HANDLE                           *ChildHandleBuffer;
6685658066182d23e210209299770edaef26d09085mdkinney  UINTN                                ChildHandleCount;
6785658066182d23e210209299770edaef26d09085mdkinney  UINTN                                Index;
68bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao  UINTN                                HandleFilePathSize;
69bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao  UINTN                                RemainingDevicePathSize;
70bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao  EFI_DEVICE_PATH_PROTOCOL             *HandleFilePath;
71bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao  EFI_DEVICE_PATH_PROTOCOL             *FilePath;
72bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao  EFI_DEVICE_PATH_PROTOCOL             *TempFilePath;
73022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang
7428a00297189c323096aae8e2975de94e8549613cyshang  //
7528a00297189c323096aae8e2975de94e8549613cyshang  // Make sure ControllerHandle is valid
7628a00297189c323096aae8e2975de94e8549613cyshang  //
7728a00297189c323096aae8e2975de94e8549613cyshang  Status = CoreValidateHandle (ControllerHandle);
7828a00297189c323096aae8e2975de94e8549613cyshang  if (EFI_ERROR (Status)) {
7928a00297189c323096aae8e2975de94e8549613cyshang    return Status;
8028a00297189c323096aae8e2975de94e8549613cyshang  }
8128a00297189c323096aae8e2975de94e8549613cyshang
82bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao  if (gSecurity2 != NULL) {
83bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao    //
84bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao    // Check whether the user has permission to start UEFI device drivers.
85bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao    //
86bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao    Status = CoreHandleProtocol (ControllerHandle, &gEfiDevicePathProtocolGuid, (VOID **)&HandleFilePath);
87bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao    if (!EFI_ERROR (Status)) {
88bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao      FilePath     = HandleFilePath;
89bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao      TempFilePath = NULL;
90bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao      if (RemainingDevicePath != NULL && !Recursive) {
91bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao        HandleFilePathSize      = GetDevicePathSize (HandleFilePath) - sizeof (EFI_DEVICE_PATH_PROTOCOL);
92bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao        RemainingDevicePathSize = GetDevicePathSize (RemainingDevicePath);
93bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao        TempFilePath = AllocateZeroPool (HandleFilePathSize + RemainingDevicePathSize);
94bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao        ASSERT (TempFilePath != NULL);
95bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao        CopyMem (TempFilePath, HandleFilePath, HandleFilePathSize);
96bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao        CopyMem ((UINT8 *) TempFilePath + HandleFilePathSize, RemainingDevicePath, RemainingDevicePathSize);
97bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao        FilePath = TempFilePath;
98bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao      }
99bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao      Status = gSecurity2->FileAuthentication (
100bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao                            gSecurity2,
101bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao                            FilePath,
102bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao                            NULL,
103bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao                            0,
104bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao                            FALSE
105bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao                            );
106bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao      if (TempFilePath != NULL) {
107bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao        FreePool (TempFilePath);
108bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao      }
109bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao      if (EFI_ERROR (Status)) {
110bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao        return Status;
111bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao      }
112bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao    }
113bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao  }
114bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao
11528a00297189c323096aae8e2975de94e8549613cyshang  Handle = ControllerHandle;
11628a00297189c323096aae8e2975de94e8549613cyshang
11728a00297189c323096aae8e2975de94e8549613cyshang  //
11885658066182d23e210209299770edaef26d09085mdkinney  // Make a copy of RemainingDevicePath to guanatee it is aligned
11928a00297189c323096aae8e2975de94e8549613cyshang  //
12028a00297189c323096aae8e2975de94e8549613cyshang  AlignedRemainingDevicePath = NULL;
12128a00297189c323096aae8e2975de94e8549613cyshang  if (RemainingDevicePath != NULL) {
1229c4ac31cca01b4a503c36616770ea3157bf3bb9eqhuang    AlignedRemainingDevicePath = DuplicateDevicePath (RemainingDevicePath);
1236c857d668cb7d2b219351be1daeec0bcd597e377qwang
1246c857d668cb7d2b219351be1daeec0bcd597e377qwang    if (AlignedRemainingDevicePath == NULL) {
1256c857d668cb7d2b219351be1daeec0bcd597e377qwang      return EFI_OUT_OF_RESOURCES;
1266c857d668cb7d2b219351be1daeec0bcd597e377qwang    }
12728a00297189c323096aae8e2975de94e8549613cyshang  }
12828a00297189c323096aae8e2975de94e8549613cyshang
12928a00297189c323096aae8e2975de94e8549613cyshang  //
13085658066182d23e210209299770edaef26d09085mdkinney  // Connect all drivers to ControllerHandle
13185658066182d23e210209299770edaef26d09085mdkinney  // If CoreConnectSingleController returns EFI_NOT_READY, then the number of
13285658066182d23e210209299770edaef26d09085mdkinney  // Driver Binding Protocols in the handle database has increased during the call
13385658066182d23e210209299770edaef26d09085mdkinney  // so the connect operation must be restarted
13428a00297189c323096aae8e2975de94e8549613cyshang  //
13585658066182d23e210209299770edaef26d09085mdkinney  do {
13685658066182d23e210209299770edaef26d09085mdkinney    ReturnStatus = CoreConnectSingleController (
137e94a9ff7271367e649ee4f9a86da1f1bea6d112eqhuang                     ControllerHandle,
138e94a9ff7271367e649ee4f9a86da1f1bea6d112eqhuang                     DriverImageHandle,
139e94a9ff7271367e649ee4f9a86da1f1bea6d112eqhuang                     AlignedRemainingDevicePath
140e94a9ff7271367e649ee4f9a86da1f1bea6d112eqhuang                     );
14185658066182d23e210209299770edaef26d09085mdkinney  } while (ReturnStatus == EFI_NOT_READY);
14285658066182d23e210209299770edaef26d09085mdkinney
14385658066182d23e210209299770edaef26d09085mdkinney  //
14485658066182d23e210209299770edaef26d09085mdkinney  // Free the aligned copy of RemainingDevicePath
14585658066182d23e210209299770edaef26d09085mdkinney  //
14685658066182d23e210209299770edaef26d09085mdkinney  if (AlignedRemainingDevicePath != NULL) {
14785658066182d23e210209299770edaef26d09085mdkinney    CoreFreePool (AlignedRemainingDevicePath);
14828a00297189c323096aae8e2975de94e8549613cyshang  }
14928a00297189c323096aae8e2975de94e8549613cyshang
15028a00297189c323096aae8e2975de94e8549613cyshang  //
15128a00297189c323096aae8e2975de94e8549613cyshang  // If recursive, then connect all drivers to all of ControllerHandle's children
15228a00297189c323096aae8e2975de94e8549613cyshang  //
15385658066182d23e210209299770edaef26d09085mdkinney  if (Recursive) {
15485658066182d23e210209299770edaef26d09085mdkinney    //
15585658066182d23e210209299770edaef26d09085mdkinney    // Acquire the protocol lock on the handle database so the child handles can be collected
15685658066182d23e210209299770edaef26d09085mdkinney    //
15785658066182d23e210209299770edaef26d09085mdkinney    CoreAcquireProtocolLock ();
15885658066182d23e210209299770edaef26d09085mdkinney
15985658066182d23e210209299770edaef26d09085mdkinney    //
16085658066182d23e210209299770edaef26d09085mdkinney    // Make sure the DriverBindingHandle is valid
16185658066182d23e210209299770edaef26d09085mdkinney    //
16285658066182d23e210209299770edaef26d09085mdkinney    Status = CoreValidateHandle (ControllerHandle);
16385658066182d23e210209299770edaef26d09085mdkinney    if (EFI_ERROR (Status)) {
16485658066182d23e210209299770edaef26d09085mdkinney      //
16585658066182d23e210209299770edaef26d09085mdkinney      // Release the protocol lock on the handle database
16685658066182d23e210209299770edaef26d09085mdkinney      //
16785658066182d23e210209299770edaef26d09085mdkinney      CoreReleaseProtocolLock ();
16885658066182d23e210209299770edaef26d09085mdkinney
16985658066182d23e210209299770edaef26d09085mdkinney      return ReturnStatus;
17085658066182d23e210209299770edaef26d09085mdkinney    }
17185658066182d23e210209299770edaef26d09085mdkinney
17285658066182d23e210209299770edaef26d09085mdkinney
17385658066182d23e210209299770edaef26d09085mdkinney    //
17485658066182d23e210209299770edaef26d09085mdkinney    // Count ControllerHandle's children
17585658066182d23e210209299770edaef26d09085mdkinney    //
17685658066182d23e210209299770edaef26d09085mdkinney    for (Link = Handle->Protocols.ForwardLink, ChildHandleCount = 0; Link != &Handle->Protocols; Link = Link->ForwardLink) {
17785658066182d23e210209299770edaef26d09085mdkinney      Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
178022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang      for (ProtLink = Prot->OpenList.ForwardLink;
179022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang          ProtLink != &Prot->OpenList;
18085658066182d23e210209299770edaef26d09085mdkinney          ProtLink = ProtLink->ForwardLink) {
18185658066182d23e210209299770edaef26d09085mdkinney        OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
18285658066182d23e210209299770edaef26d09085mdkinney        if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
18385658066182d23e210209299770edaef26d09085mdkinney          ChildHandleCount++;
18485658066182d23e210209299770edaef26d09085mdkinney        }
18585658066182d23e210209299770edaef26d09085mdkinney      }
18685658066182d23e210209299770edaef26d09085mdkinney    }
18785658066182d23e210209299770edaef26d09085mdkinney
18885658066182d23e210209299770edaef26d09085mdkinney    //
18985658066182d23e210209299770edaef26d09085mdkinney    // Allocate a handle buffer for ControllerHandle's children
19085658066182d23e210209299770edaef26d09085mdkinney    //
1919c4ac31cca01b4a503c36616770ea3157bf3bb9eqhuang    ChildHandleBuffer = AllocatePool (ChildHandleCount * sizeof(EFI_HANDLE));
1926c857d668cb7d2b219351be1daeec0bcd597e377qwang    if (ChildHandleBuffer == NULL) {
193fa3c419fec30282afb85a788cb71e12fd1a51804qwang      CoreReleaseProtocolLock ();
1946c857d668cb7d2b219351be1daeec0bcd597e377qwang      return EFI_OUT_OF_RESOURCES;
1956c857d668cb7d2b219351be1daeec0bcd597e377qwang    }
19685658066182d23e210209299770edaef26d09085mdkinney
19785658066182d23e210209299770edaef26d09085mdkinney    //
19885658066182d23e210209299770edaef26d09085mdkinney    // Fill in a handle buffer with ControllerHandle's children
19985658066182d23e210209299770edaef26d09085mdkinney    //
20085658066182d23e210209299770edaef26d09085mdkinney    for (Link = Handle->Protocols.ForwardLink, ChildHandleCount = 0; Link != &Handle->Protocols; Link = Link->ForwardLink) {
20185658066182d23e210209299770edaef26d09085mdkinney      Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
202022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang      for (ProtLink = Prot->OpenList.ForwardLink;
203022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang          ProtLink != &Prot->OpenList;
20485658066182d23e210209299770edaef26d09085mdkinney          ProtLink = ProtLink->ForwardLink) {
20528a00297189c323096aae8e2975de94e8549613cyshang        OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
20628a00297189c323096aae8e2975de94e8549613cyshang        if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
20785658066182d23e210209299770edaef26d09085mdkinney          ChildHandleBuffer[ChildHandleCount] = OpenData->ControllerHandle;
20885658066182d23e210209299770edaef26d09085mdkinney          ChildHandleCount++;
20985658066182d23e210209299770edaef26d09085mdkinney        }
21085658066182d23e210209299770edaef26d09085mdkinney      }
21185658066182d23e210209299770edaef26d09085mdkinney    }
21285658066182d23e210209299770edaef26d09085mdkinney
21385658066182d23e210209299770edaef26d09085mdkinney    //
21485658066182d23e210209299770edaef26d09085mdkinney    // Release the protocol lock on the handle database
21585658066182d23e210209299770edaef26d09085mdkinney    //
21685658066182d23e210209299770edaef26d09085mdkinney    CoreReleaseProtocolLock ();
21785658066182d23e210209299770edaef26d09085mdkinney
21885658066182d23e210209299770edaef26d09085mdkinney    //
21985658066182d23e210209299770edaef26d09085mdkinney    // Recursively connect each child handle
22085658066182d23e210209299770edaef26d09085mdkinney    //
22185658066182d23e210209299770edaef26d09085mdkinney    for (Index = 0; Index < ChildHandleCount; Index++) {
22285658066182d23e210209299770edaef26d09085mdkinney      CoreConnectController (
22385658066182d23e210209299770edaef26d09085mdkinney        ChildHandleBuffer[Index],
22485658066182d23e210209299770edaef26d09085mdkinney        NULL,
22585658066182d23e210209299770edaef26d09085mdkinney        NULL,
22685658066182d23e210209299770edaef26d09085mdkinney        TRUE
227022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang        );
22885658066182d23e210209299770edaef26d09085mdkinney    }
22985658066182d23e210209299770edaef26d09085mdkinney
23085658066182d23e210209299770edaef26d09085mdkinney    //
23185658066182d23e210209299770edaef26d09085mdkinney    // Free the handle buffer of ControllerHandle's children
23285658066182d23e210209299770edaef26d09085mdkinney    //
23385658066182d23e210209299770edaef26d09085mdkinney    CoreFreePool (ChildHandleBuffer);
23485658066182d23e210209299770edaef26d09085mdkinney  }
23585658066182d23e210209299770edaef26d09085mdkinney
23628a00297189c323096aae8e2975de94e8549613cyshang  return ReturnStatus;
23728a00297189c323096aae8e2975de94e8549613cyshang}
23828a00297189c323096aae8e2975de94e8549613cyshang
239162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
240162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang/**
241162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  Add Driver Binding Protocols from Context Driver Image Handles to sorted
242162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  Driver Binding Protocol list.
243162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
244022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  DriverBindingHandle                   Handle of the driver binding
245022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                                protocol.
246022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  NumberOfSortedDriverBindingProtocols  Number Of sorted driver binding
247022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                                protocols
248022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  SortedDriverBindingProtocols          The sorted protocol list.
249022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  DriverBindingHandleCount              Driver Binding Handle Count.
250022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  DriverBindingHandleBuffer             The buffer of driver binding
251022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                                protocol to be modified.
252022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  IsImageHandle                         Indicate whether
253022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                                DriverBindingHandle is an image
254022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                                handle
255162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
256162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  @return None.
257162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
258162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang**/
25928a00297189c323096aae8e2975de94e8549613cyshangVOID
26028a00297189c323096aae8e2975de94e8549613cyshangAddSortedDriverBindingProtocol (
26128a00297189c323096aae8e2975de94e8549613cyshang  IN      EFI_HANDLE                   DriverBindingHandle,
262022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  IN OUT  UINTN                        *NumberOfSortedDriverBindingProtocols,
26328a00297189c323096aae8e2975de94e8549613cyshang  IN OUT  EFI_DRIVER_BINDING_PROTOCOL  **SortedDriverBindingProtocols,
26428a00297189c323096aae8e2975de94e8549613cyshang  IN      UINTN                        DriverBindingHandleCount,
265adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney  IN OUT  EFI_HANDLE                   *DriverBindingHandleBuffer,
266adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney  IN      BOOLEAN                      IsImageHandle
26728a00297189c323096aae8e2975de94e8549613cyshang  )
26828a00297189c323096aae8e2975de94e8549613cyshang{
26928a00297189c323096aae8e2975de94e8549613cyshang  EFI_STATUS                   Status;
27028a00297189c323096aae8e2975de94e8549613cyshang  EFI_DRIVER_BINDING_PROTOCOL  *DriverBinding;
27128a00297189c323096aae8e2975de94e8549613cyshang  UINTN                        Index;
27228a00297189c323096aae8e2975de94e8549613cyshang
27328a00297189c323096aae8e2975de94e8549613cyshang  //
27428a00297189c323096aae8e2975de94e8549613cyshang  // Make sure the DriverBindingHandle is valid
27528a00297189c323096aae8e2975de94e8549613cyshang  //
27628a00297189c323096aae8e2975de94e8549613cyshang  Status = CoreValidateHandle (DriverBindingHandle);
27728a00297189c323096aae8e2975de94e8549613cyshang  if (EFI_ERROR (Status)) {
27828a00297189c323096aae8e2975de94e8549613cyshang    return;
27928a00297189c323096aae8e2975de94e8549613cyshang  }
28028a00297189c323096aae8e2975de94e8549613cyshang
28128a00297189c323096aae8e2975de94e8549613cyshang  //
282adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney  // If IsImageHandle is TRUE, then DriverBindingHandle is an image handle
283adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney  // Find all the DriverBindingHandles associated with that image handle and add them to the sorted list
284adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney  //
285adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney  if (IsImageHandle) {
286adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney    //
287adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney    // Loop through all the Driver Binding Handles
288adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney    //
289adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney    for (Index = 0; Index < DriverBindingHandleCount; Index++) {
290adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney      //
291adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney      // Retrieve the Driver Binding Protocol associated with each Driver Binding Handle
292adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney      //
293adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney      Status = CoreHandleProtocol (
294adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney                DriverBindingHandleBuffer[Index],
295adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney                &gEfiDriverBindingProtocolGuid,
296e94a9ff7271367e649ee4f9a86da1f1bea6d112eqhuang                (VOID **) &DriverBinding
297adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney                );
29870279390ba9a0774e020af36120f8b9ba1c217dbmdkinney      if (EFI_ERROR (Status) || DriverBinding == NULL) {
29970279390ba9a0774e020af36120f8b9ba1c217dbmdkinney        continue;
30070279390ba9a0774e020af36120f8b9ba1c217dbmdkinney      }
30170279390ba9a0774e020af36120f8b9ba1c217dbmdkinney
302adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney      //
303adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney      // If the ImageHandle associated with DriverBinding matches DriverBindingHandle,
304adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney      // then add the DriverBindingProtocol[Index] to the sorted list
305adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney      //
306adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney      if (DriverBinding->ImageHandle == DriverBindingHandle) {
307adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney        AddSortedDriverBindingProtocol (
308adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney          DriverBindingHandleBuffer[Index],
309022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang          NumberOfSortedDriverBindingProtocols,
310adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney          SortedDriverBindingProtocols,
311adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney          DriverBindingHandleCount,
312adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney          DriverBindingHandleBuffer,
313adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney          FALSE
314adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney          );
315adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney      }
316adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney    }
317adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney    return;
318adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney  }
319adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney
320adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney  //
32128a00297189c323096aae8e2975de94e8549613cyshang  // Retrieve the Driver Binding Protocol from DriverBindingHandle
32228a00297189c323096aae8e2975de94e8549613cyshang  //
32328a00297189c323096aae8e2975de94e8549613cyshang  Status = CoreHandleProtocol(
32428a00297189c323096aae8e2975de94e8549613cyshang             DriverBindingHandle,
32528a00297189c323096aae8e2975de94e8549613cyshang             &gEfiDriverBindingProtocolGuid,
326e94a9ff7271367e649ee4f9a86da1f1bea6d112eqhuang             (VOID **) &DriverBinding
32728a00297189c323096aae8e2975de94e8549613cyshang             );
32828a00297189c323096aae8e2975de94e8549613cyshang  //
32928a00297189c323096aae8e2975de94e8549613cyshang  // If DriverBindingHandle does not support the Driver Binding Protocol then return
33028a00297189c323096aae8e2975de94e8549613cyshang  //
33128a00297189c323096aae8e2975de94e8549613cyshang  if (EFI_ERROR (Status) || DriverBinding == NULL) {
33228a00297189c323096aae8e2975de94e8549613cyshang    return;
33328a00297189c323096aae8e2975de94e8549613cyshang  }
33428a00297189c323096aae8e2975de94e8549613cyshang
33528a00297189c323096aae8e2975de94e8549613cyshang  //
33628a00297189c323096aae8e2975de94e8549613cyshang  // See if DriverBinding is already in the sorted list
33728a00297189c323096aae8e2975de94e8549613cyshang  //
33885658066182d23e210209299770edaef26d09085mdkinney  for (Index = 0; Index < *NumberOfSortedDriverBindingProtocols && Index < DriverBindingHandleCount; Index++) {
33928a00297189c323096aae8e2975de94e8549613cyshang    if (DriverBinding == SortedDriverBindingProtocols[Index]) {
34028a00297189c323096aae8e2975de94e8549613cyshang      return;
34128a00297189c323096aae8e2975de94e8549613cyshang    }
34228a00297189c323096aae8e2975de94e8549613cyshang  }
34328a00297189c323096aae8e2975de94e8549613cyshang
34428a00297189c323096aae8e2975de94e8549613cyshang  //
34528a00297189c323096aae8e2975de94e8549613cyshang  // Add DriverBinding to the end of the list
34628a00297189c323096aae8e2975de94e8549613cyshang  //
34785658066182d23e210209299770edaef26d09085mdkinney  if (*NumberOfSortedDriverBindingProtocols < DriverBindingHandleCount) {
34885658066182d23e210209299770edaef26d09085mdkinney    SortedDriverBindingProtocols[*NumberOfSortedDriverBindingProtocols] = DriverBinding;
34985658066182d23e210209299770edaef26d09085mdkinney  }
35028a00297189c323096aae8e2975de94e8549613cyshang  *NumberOfSortedDriverBindingProtocols = *NumberOfSortedDriverBindingProtocols + 1;
35128a00297189c323096aae8e2975de94e8549613cyshang
35228a00297189c323096aae8e2975de94e8549613cyshang  //
35328a00297189c323096aae8e2975de94e8549613cyshang  // Mark the cooresponding handle in DriverBindingHandleBuffer as used
35428a00297189c323096aae8e2975de94e8549613cyshang  //
35528a00297189c323096aae8e2975de94e8549613cyshang  for (Index = 0; Index < DriverBindingHandleCount; Index++) {
35628a00297189c323096aae8e2975de94e8549613cyshang    if (DriverBindingHandleBuffer[Index] == DriverBindingHandle) {
35728a00297189c323096aae8e2975de94e8549613cyshang      DriverBindingHandleBuffer[Index] = NULL;
35828a00297189c323096aae8e2975de94e8549613cyshang    }
35928a00297189c323096aae8e2975de94e8549613cyshang  }
36028a00297189c323096aae8e2975de94e8549613cyshang}
361022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang
362162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
363162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang/**
364162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  Connects a controller to a driver.
365162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
366022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  ControllerHandle                      Handle of the controller to be
367022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                                connected.
368022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  ContextDriverImageHandles             DriverImageHandle A pointer to an
369022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                                ordered list of driver image
370022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                                handles.
371022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  RemainingDevicePath                   RemainingDevicePath A pointer to
372022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                                the device path that specifies a
373022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                                child  of the controller
374022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                                specified by ControllerHandle.
375022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang
376022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @retval EFI_SUCCESS                           One or more drivers were
377022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                                connected to ControllerHandle.
378022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @retval EFI_OUT_OF_RESOURCES                  No enough system resources to
379022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                                complete the request.
380022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @retval EFI_NOT_FOUND                         No drivers were connected to
381162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang                                                ControllerHandle.
382162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
383162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang**/
384022c6d45ef78605c173023f53984e4dfaf7b11f4qhuangEFI_STATUS
38528a00297189c323096aae8e2975de94e8549613cyshangCoreConnectSingleController (
38628a00297189c323096aae8e2975de94e8549613cyshang  IN  EFI_HANDLE                ControllerHandle,
38728a00297189c323096aae8e2975de94e8549613cyshang  IN  EFI_HANDLE                *ContextDriverImageHandles OPTIONAL,
388022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  IN  EFI_DEVICE_PATH_PROTOCOL  *RemainingDevicePath       OPTIONAL
38928a00297189c323096aae8e2975de94e8549613cyshang  )
39028a00297189c323096aae8e2975de94e8549613cyshang{
39128a00297189c323096aae8e2975de94e8549613cyshang  EFI_STATUS                                 Status;
39228a00297189c323096aae8e2975de94e8549613cyshang  UINTN                                      Index;
39328a00297189c323096aae8e2975de94e8549613cyshang  EFI_HANDLE                                 DriverImageHandle;
39428a00297189c323096aae8e2975de94e8549613cyshang  EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL      *PlatformDriverOverride;
39528a00297189c323096aae8e2975de94e8549613cyshang  EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL  *BusSpecificDriverOverride;
39628a00297189c323096aae8e2975de94e8549613cyshang  UINTN                                      DriverBindingHandleCount;
39728a00297189c323096aae8e2975de94e8549613cyshang  EFI_HANDLE                                 *DriverBindingHandleBuffer;
39870279390ba9a0774e020af36120f8b9ba1c217dbmdkinney  UINTN                                      NewDriverBindingHandleCount;
39970279390ba9a0774e020af36120f8b9ba1c217dbmdkinney  EFI_HANDLE                                 *NewDriverBindingHandleBuffer;
40028a00297189c323096aae8e2975de94e8549613cyshang  EFI_DRIVER_BINDING_PROTOCOL                *DriverBinding;
401396e9039aec00982e98392a843635c1dcff5364dniruiyu  EFI_DRIVER_FAMILY_OVERRIDE_PROTOCOL        *DriverFamilyOverride;
40228a00297189c323096aae8e2975de94e8549613cyshang  UINTN                                      NumberOfSortedDriverBindingProtocols;
40328a00297189c323096aae8e2975de94e8549613cyshang  EFI_DRIVER_BINDING_PROTOCOL                **SortedDriverBindingProtocols;
404396e9039aec00982e98392a843635c1dcff5364dniruiyu  UINT32                                     DriverFamilyOverrideVersion;
40528a00297189c323096aae8e2975de94e8549613cyshang  UINT32                                     HighestVersion;
40628a00297189c323096aae8e2975de94e8549613cyshang  UINTN                                      HighestIndex;
40728a00297189c323096aae8e2975de94e8549613cyshang  UINTN                                      SortIndex;
40828a00297189c323096aae8e2975de94e8549613cyshang  BOOLEAN                                    OneStarted;
40928a00297189c323096aae8e2975de94e8549613cyshang  BOOLEAN                                    DriverFound;
41028a00297189c323096aae8e2975de94e8549613cyshang
41128a00297189c323096aae8e2975de94e8549613cyshang  //
41228a00297189c323096aae8e2975de94e8549613cyshang  // Initialize local variables
41328a00297189c323096aae8e2975de94e8549613cyshang  //
41428a00297189c323096aae8e2975de94e8549613cyshang  DriverBindingHandleCount              = 0;
41528a00297189c323096aae8e2975de94e8549613cyshang  DriverBindingHandleBuffer             = NULL;
41628a00297189c323096aae8e2975de94e8549613cyshang  NumberOfSortedDriverBindingProtocols  = 0;
41728a00297189c323096aae8e2975de94e8549613cyshang  SortedDriverBindingProtocols          = NULL;
41828a00297189c323096aae8e2975de94e8549613cyshang
41928a00297189c323096aae8e2975de94e8549613cyshang  //
42028a00297189c323096aae8e2975de94e8549613cyshang  // Get list of all Driver Binding Protocol Instances
42128a00297189c323096aae8e2975de94e8549613cyshang  //
42228a00297189c323096aae8e2975de94e8549613cyshang  Status = CoreLocateHandleBuffer (
423022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang             ByProtocol,
424022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang             &gEfiDriverBindingProtocolGuid,
42528a00297189c323096aae8e2975de94e8549613cyshang             NULL,
426022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang             &DriverBindingHandleCount,
42728a00297189c323096aae8e2975de94e8549613cyshang             &DriverBindingHandleBuffer
42828a00297189c323096aae8e2975de94e8549613cyshang             );
42928a00297189c323096aae8e2975de94e8549613cyshang  if (EFI_ERROR (Status) || (DriverBindingHandleCount == 0)) {
43028a00297189c323096aae8e2975de94e8549613cyshang    return EFI_NOT_FOUND;
43128a00297189c323096aae8e2975de94e8549613cyshang  }
43228a00297189c323096aae8e2975de94e8549613cyshang
43328a00297189c323096aae8e2975de94e8549613cyshang  //
43428a00297189c323096aae8e2975de94e8549613cyshang  // Allocate a duplicate array for the sorted Driver Binding Protocol Instances
43528a00297189c323096aae8e2975de94e8549613cyshang  //
4369c4ac31cca01b4a503c36616770ea3157bf3bb9eqhuang  SortedDriverBindingProtocols = AllocatePool (sizeof (VOID *) * DriverBindingHandleCount);
43728a00297189c323096aae8e2975de94e8549613cyshang  if (SortedDriverBindingProtocols == NULL) {
43828a00297189c323096aae8e2975de94e8549613cyshang    CoreFreePool (DriverBindingHandleBuffer);
43928a00297189c323096aae8e2975de94e8549613cyshang    return EFI_OUT_OF_RESOURCES;
44028a00297189c323096aae8e2975de94e8549613cyshang  }
44128a00297189c323096aae8e2975de94e8549613cyshang
44228a00297189c323096aae8e2975de94e8549613cyshang  //
44328a00297189c323096aae8e2975de94e8549613cyshang  // Add Driver Binding Protocols from Context Driver Image Handles first
44428a00297189c323096aae8e2975de94e8549613cyshang  //
44528a00297189c323096aae8e2975de94e8549613cyshang  if (ContextDriverImageHandles != NULL) {
44628a00297189c323096aae8e2975de94e8549613cyshang    for (Index = 0; ContextDriverImageHandles[Index] != NULL; Index++) {
44728a00297189c323096aae8e2975de94e8549613cyshang      AddSortedDriverBindingProtocol (
44828a00297189c323096aae8e2975de94e8549613cyshang        ContextDriverImageHandles[Index],
449022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang        &NumberOfSortedDriverBindingProtocols,
45028a00297189c323096aae8e2975de94e8549613cyshang        SortedDriverBindingProtocols,
45128a00297189c323096aae8e2975de94e8549613cyshang        DriverBindingHandleCount,
452adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney        DriverBindingHandleBuffer,
453adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney        FALSE
45428a00297189c323096aae8e2975de94e8549613cyshang        );
45528a00297189c323096aae8e2975de94e8549613cyshang    }
45628a00297189c323096aae8e2975de94e8549613cyshang  }
45728a00297189c323096aae8e2975de94e8549613cyshang
45828a00297189c323096aae8e2975de94e8549613cyshang  //
45928a00297189c323096aae8e2975de94e8549613cyshang  // Add the Platform Driver Override Protocol drivers for ControllerHandle next
46028a00297189c323096aae8e2975de94e8549613cyshang  //
46128a00297189c323096aae8e2975de94e8549613cyshang  Status = CoreLocateProtocol (
462022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang             &gEfiPlatformDriverOverrideProtocolGuid,
463022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang             NULL,
464e94a9ff7271367e649ee4f9a86da1f1bea6d112eqhuang             (VOID **) &PlatformDriverOverride
46528a00297189c323096aae8e2975de94e8549613cyshang             );
46628a00297189c323096aae8e2975de94e8549613cyshang  if (!EFI_ERROR (Status) && (PlatformDriverOverride != NULL)) {
46728a00297189c323096aae8e2975de94e8549613cyshang    DriverImageHandle = NULL;
46828a00297189c323096aae8e2975de94e8549613cyshang    do {
46928a00297189c323096aae8e2975de94e8549613cyshang      Status = PlatformDriverOverride->GetDriver (
47028a00297189c323096aae8e2975de94e8549613cyshang                                         PlatformDriverOverride,
47128a00297189c323096aae8e2975de94e8549613cyshang                                         ControllerHandle,
47228a00297189c323096aae8e2975de94e8549613cyshang                                         &DriverImageHandle
47328a00297189c323096aae8e2975de94e8549613cyshang                                         );
47428a00297189c323096aae8e2975de94e8549613cyshang      if (!EFI_ERROR (Status)) {
47528a00297189c323096aae8e2975de94e8549613cyshang        AddSortedDriverBindingProtocol (
47628a00297189c323096aae8e2975de94e8549613cyshang          DriverImageHandle,
477022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang          &NumberOfSortedDriverBindingProtocols,
47828a00297189c323096aae8e2975de94e8549613cyshang          SortedDriverBindingProtocols,
47928a00297189c323096aae8e2975de94e8549613cyshang          DriverBindingHandleCount,
480adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney          DriverBindingHandleBuffer,
481adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney          TRUE
48228a00297189c323096aae8e2975de94e8549613cyshang          );
48328a00297189c323096aae8e2975de94e8549613cyshang      }
48428a00297189c323096aae8e2975de94e8549613cyshang    } while (!EFI_ERROR (Status));
48528a00297189c323096aae8e2975de94e8549613cyshang  }
48628a00297189c323096aae8e2975de94e8549613cyshang
48728a00297189c323096aae8e2975de94e8549613cyshang  //
488396e9039aec00982e98392a843635c1dcff5364dniruiyu  // Add the Driver Family Override Protocol drivers for ControllerHandle
489396e9039aec00982e98392a843635c1dcff5364dniruiyu  //
490396e9039aec00982e98392a843635c1dcff5364dniruiyu  while (TRUE) {
491396e9039aec00982e98392a843635c1dcff5364dniruiyu    HighestIndex   = DriverBindingHandleCount;
492396e9039aec00982e98392a843635c1dcff5364dniruiyu    HighestVersion = 0;
493396e9039aec00982e98392a843635c1dcff5364dniruiyu    for (Index = 0; Index < DriverBindingHandleCount; Index++) {
494396e9039aec00982e98392a843635c1dcff5364dniruiyu      Status = CoreHandleProtocol (
495396e9039aec00982e98392a843635c1dcff5364dniruiyu                 DriverBindingHandleBuffer[Index],
496396e9039aec00982e98392a843635c1dcff5364dniruiyu                 &gEfiDriverFamilyOverrideProtocolGuid,
497396e9039aec00982e98392a843635c1dcff5364dniruiyu                 (VOID **) &DriverFamilyOverride
498396e9039aec00982e98392a843635c1dcff5364dniruiyu                 );
499396e9039aec00982e98392a843635c1dcff5364dniruiyu      if (!EFI_ERROR (Status) && (DriverFamilyOverride != NULL)) {
500396e9039aec00982e98392a843635c1dcff5364dniruiyu        DriverFamilyOverrideVersion = DriverFamilyOverride->GetVersion (DriverFamilyOverride);
501396e9039aec00982e98392a843635c1dcff5364dniruiyu        if ((HighestIndex == DriverBindingHandleCount) || (DriverFamilyOverrideVersion > HighestVersion)) {
502396e9039aec00982e98392a843635c1dcff5364dniruiyu          HighestVersion = DriverFamilyOverrideVersion;
503396e9039aec00982e98392a843635c1dcff5364dniruiyu          HighestIndex   = Index;
504396e9039aec00982e98392a843635c1dcff5364dniruiyu        }
505396e9039aec00982e98392a843635c1dcff5364dniruiyu      }
506396e9039aec00982e98392a843635c1dcff5364dniruiyu    }
507396e9039aec00982e98392a843635c1dcff5364dniruiyu
508396e9039aec00982e98392a843635c1dcff5364dniruiyu    if (HighestIndex == DriverBindingHandleCount) {
509396e9039aec00982e98392a843635c1dcff5364dniruiyu      break;
510396e9039aec00982e98392a843635c1dcff5364dniruiyu    }
511396e9039aec00982e98392a843635c1dcff5364dniruiyu
512396e9039aec00982e98392a843635c1dcff5364dniruiyu    AddSortedDriverBindingProtocol (
513396e9039aec00982e98392a843635c1dcff5364dniruiyu      DriverBindingHandleBuffer[HighestIndex],
514396e9039aec00982e98392a843635c1dcff5364dniruiyu      &NumberOfSortedDriverBindingProtocols,
515396e9039aec00982e98392a843635c1dcff5364dniruiyu      SortedDriverBindingProtocols,
516396e9039aec00982e98392a843635c1dcff5364dniruiyu      DriverBindingHandleCount,
517396e9039aec00982e98392a843635c1dcff5364dniruiyu      DriverBindingHandleBuffer,
518396e9039aec00982e98392a843635c1dcff5364dniruiyu      FALSE
519396e9039aec00982e98392a843635c1dcff5364dniruiyu      );
520396e9039aec00982e98392a843635c1dcff5364dniruiyu  }
521396e9039aec00982e98392a843635c1dcff5364dniruiyu
522396e9039aec00982e98392a843635c1dcff5364dniruiyu  //
52328a00297189c323096aae8e2975de94e8549613cyshang  // Get the Bus Specific Driver Override Protocol instance on the Controller Handle
52428a00297189c323096aae8e2975de94e8549613cyshang  //
525adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney  Status = CoreHandleProtocol (
526022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang             ControllerHandle,
527022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang             &gEfiBusSpecificDriverOverrideProtocolGuid,
528e94a9ff7271367e649ee4f9a86da1f1bea6d112eqhuang             (VOID **) &BusSpecificDriverOverride
52928a00297189c323096aae8e2975de94e8549613cyshang             );
53028a00297189c323096aae8e2975de94e8549613cyshang  if (!EFI_ERROR (Status) && (BusSpecificDriverOverride != NULL)) {
53128a00297189c323096aae8e2975de94e8549613cyshang    DriverImageHandle = NULL;
53228a00297189c323096aae8e2975de94e8549613cyshang    do {
53328a00297189c323096aae8e2975de94e8549613cyshang      Status = BusSpecificDriverOverride->GetDriver (
53428a00297189c323096aae8e2975de94e8549613cyshang                                            BusSpecificDriverOverride,
53528a00297189c323096aae8e2975de94e8549613cyshang                                            &DriverImageHandle
53628a00297189c323096aae8e2975de94e8549613cyshang                                            );
53728a00297189c323096aae8e2975de94e8549613cyshang      if (!EFI_ERROR (Status)) {
53828a00297189c323096aae8e2975de94e8549613cyshang        AddSortedDriverBindingProtocol (
53928a00297189c323096aae8e2975de94e8549613cyshang          DriverImageHandle,
540022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang          &NumberOfSortedDriverBindingProtocols,
54128a00297189c323096aae8e2975de94e8549613cyshang          SortedDriverBindingProtocols,
54228a00297189c323096aae8e2975de94e8549613cyshang          DriverBindingHandleCount,
543adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney          DriverBindingHandleBuffer,
544adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney          TRUE
54528a00297189c323096aae8e2975de94e8549613cyshang          );
54628a00297189c323096aae8e2975de94e8549613cyshang      }
54728a00297189c323096aae8e2975de94e8549613cyshang    } while (!EFI_ERROR (Status));
54828a00297189c323096aae8e2975de94e8549613cyshang  }
54928a00297189c323096aae8e2975de94e8549613cyshang
55028a00297189c323096aae8e2975de94e8549613cyshang  //
55128a00297189c323096aae8e2975de94e8549613cyshang  // Then add all the remaining Driver Binding Protocols
55228a00297189c323096aae8e2975de94e8549613cyshang  //
55328a00297189c323096aae8e2975de94e8549613cyshang  SortIndex = NumberOfSortedDriverBindingProtocols;
55428a00297189c323096aae8e2975de94e8549613cyshang  for (Index = 0; Index < DriverBindingHandleCount; Index++) {
55528a00297189c323096aae8e2975de94e8549613cyshang    AddSortedDriverBindingProtocol (
55628a00297189c323096aae8e2975de94e8549613cyshang      DriverBindingHandleBuffer[Index],
557022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang      &NumberOfSortedDriverBindingProtocols,
55828a00297189c323096aae8e2975de94e8549613cyshang      SortedDriverBindingProtocols,
55928a00297189c323096aae8e2975de94e8549613cyshang      DriverBindingHandleCount,
560adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney      DriverBindingHandleBuffer,
561adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney      FALSE
56228a00297189c323096aae8e2975de94e8549613cyshang      );
56328a00297189c323096aae8e2975de94e8549613cyshang  }
56428a00297189c323096aae8e2975de94e8549613cyshang
56528a00297189c323096aae8e2975de94e8549613cyshang  //
56628a00297189c323096aae8e2975de94e8549613cyshang  // Free the Driver Binding Handle Buffer
56728a00297189c323096aae8e2975de94e8549613cyshang  //
56828a00297189c323096aae8e2975de94e8549613cyshang  CoreFreePool (DriverBindingHandleBuffer);
56928a00297189c323096aae8e2975de94e8549613cyshang
57028a00297189c323096aae8e2975de94e8549613cyshang  //
57185658066182d23e210209299770edaef26d09085mdkinney  // If the number of Driver Binding Protocols has increased since this function started, then return
57285658066182d23e210209299770edaef26d09085mdkinney  // EFI_NOT_READY, so it will be restarted
57385658066182d23e210209299770edaef26d09085mdkinney  //
57470279390ba9a0774e020af36120f8b9ba1c217dbmdkinney  Status = CoreLocateHandleBuffer (
575022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang             ByProtocol,
576022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang             &gEfiDriverBindingProtocolGuid,
57770279390ba9a0774e020af36120f8b9ba1c217dbmdkinney             NULL,
578022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang             &NewDriverBindingHandleCount,
57970279390ba9a0774e020af36120f8b9ba1c217dbmdkinney             &NewDriverBindingHandleBuffer
58070279390ba9a0774e020af36120f8b9ba1c217dbmdkinney             );
58170279390ba9a0774e020af36120f8b9ba1c217dbmdkinney  CoreFreePool (NewDriverBindingHandleBuffer);
58270279390ba9a0774e020af36120f8b9ba1c217dbmdkinney  if (NewDriverBindingHandleCount > DriverBindingHandleCount) {
58385658066182d23e210209299770edaef26d09085mdkinney    //
58485658066182d23e210209299770edaef26d09085mdkinney    // Free any buffers that were allocated with AllocatePool()
58585658066182d23e210209299770edaef26d09085mdkinney    //
58685658066182d23e210209299770edaef26d09085mdkinney    CoreFreePool (SortedDriverBindingProtocols);
58785658066182d23e210209299770edaef26d09085mdkinney
58885658066182d23e210209299770edaef26d09085mdkinney    return EFI_NOT_READY;
58985658066182d23e210209299770edaef26d09085mdkinney  }
59085658066182d23e210209299770edaef26d09085mdkinney
59185658066182d23e210209299770edaef26d09085mdkinney  //
59228a00297189c323096aae8e2975de94e8549613cyshang  // Sort the remaining DriverBinding Protocol based on their Version field from
59328a00297189c323096aae8e2975de94e8549613cyshang  // highest to lowest.
59428a00297189c323096aae8e2975de94e8549613cyshang  //
59528a00297189c323096aae8e2975de94e8549613cyshang  for ( ; SortIndex < NumberOfSortedDriverBindingProtocols; SortIndex++) {
59628a00297189c323096aae8e2975de94e8549613cyshang    HighestVersion = SortedDriverBindingProtocols[SortIndex]->Version;
59728a00297189c323096aae8e2975de94e8549613cyshang    HighestIndex   = SortIndex;
59828a00297189c323096aae8e2975de94e8549613cyshang    for (Index = SortIndex + 1; Index < NumberOfSortedDriverBindingProtocols; Index++) {
59928a00297189c323096aae8e2975de94e8549613cyshang      if (SortedDriverBindingProtocols[Index]->Version > HighestVersion) {
60028a00297189c323096aae8e2975de94e8549613cyshang        HighestVersion = SortedDriverBindingProtocols[Index]->Version;
60128a00297189c323096aae8e2975de94e8549613cyshang        HighestIndex   = Index;
60228a00297189c323096aae8e2975de94e8549613cyshang      }
60328a00297189c323096aae8e2975de94e8549613cyshang    }
60428a00297189c323096aae8e2975de94e8549613cyshang    if (SortIndex != HighestIndex) {
60528a00297189c323096aae8e2975de94e8549613cyshang      DriverBinding = SortedDriverBindingProtocols[SortIndex];
60628a00297189c323096aae8e2975de94e8549613cyshang      SortedDriverBindingProtocols[SortIndex] = SortedDriverBindingProtocols[HighestIndex];
60728a00297189c323096aae8e2975de94e8549613cyshang      SortedDriverBindingProtocols[HighestIndex] = DriverBinding;
60828a00297189c323096aae8e2975de94e8549613cyshang    }
60928a00297189c323096aae8e2975de94e8549613cyshang  }
61028a00297189c323096aae8e2975de94e8549613cyshang
61128a00297189c323096aae8e2975de94e8549613cyshang  //
61228a00297189c323096aae8e2975de94e8549613cyshang  // Loop until no more drivers can be started on ControllerHandle
61328a00297189c323096aae8e2975de94e8549613cyshang  //
61428a00297189c323096aae8e2975de94e8549613cyshang  OneStarted = FALSE;
61528a00297189c323096aae8e2975de94e8549613cyshang  do {
61628a00297189c323096aae8e2975de94e8549613cyshang
61728a00297189c323096aae8e2975de94e8549613cyshang    //
61828a00297189c323096aae8e2975de94e8549613cyshang    // Loop through the sorted Driver Binding Protocol Instances in order, and see if
619022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang    // any of the Driver Binding Protocols support the controller specified by
62028a00297189c323096aae8e2975de94e8549613cyshang    // ControllerHandle.
62128a00297189c323096aae8e2975de94e8549613cyshang    //
62228a00297189c323096aae8e2975de94e8549613cyshang    DriverBinding = NULL;
62328a00297189c323096aae8e2975de94e8549613cyshang    DriverFound = FALSE;
62428a00297189c323096aae8e2975de94e8549613cyshang    for (Index = 0; (Index < NumberOfSortedDriverBindingProtocols) && !DriverFound; Index++) {
62528a00297189c323096aae8e2975de94e8549613cyshang      if (SortedDriverBindingProtocols[Index] != NULL) {
62628a00297189c323096aae8e2975de94e8549613cyshang        DriverBinding = SortedDriverBindingProtocols[Index];
627bc6b5892b007447b1024d98004681aa7a3305ddfqhuang        PERF_START (DriverBinding->DriverBindingHandle, "DB:Support:", NULL, 0);
62828a00297189c323096aae8e2975de94e8549613cyshang        Status = DriverBinding->Supported(
629022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                  DriverBinding,
63028a00297189c323096aae8e2975de94e8549613cyshang                                  ControllerHandle,
63128a00297189c323096aae8e2975de94e8549613cyshang                                  RemainingDevicePath
63228a00297189c323096aae8e2975de94e8549613cyshang                                  );
633bc6b5892b007447b1024d98004681aa7a3305ddfqhuang        PERF_END (DriverBinding->DriverBindingHandle, "DB:Support:", NULL, 0);
63428a00297189c323096aae8e2975de94e8549613cyshang        if (!EFI_ERROR (Status)) {
63528a00297189c323096aae8e2975de94e8549613cyshang          SortedDriverBindingProtocols[Index] = NULL;
63628a00297189c323096aae8e2975de94e8549613cyshang          DriverFound = TRUE;
63728a00297189c323096aae8e2975de94e8549613cyshang
63828a00297189c323096aae8e2975de94e8549613cyshang          //
63928a00297189c323096aae8e2975de94e8549613cyshang          // A driver was found that supports ControllerHandle, so attempt to start the driver
64028a00297189c323096aae8e2975de94e8549613cyshang          // on ControllerHandle.
64128a00297189c323096aae8e2975de94e8549613cyshang          //
642bc6b5892b007447b1024d98004681aa7a3305ddfqhuang          PERF_START (DriverBinding->DriverBindingHandle, "DB:Start:", NULL, 0);
64328a00297189c323096aae8e2975de94e8549613cyshang          Status = DriverBinding->Start (
644022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                    DriverBinding,
64528a00297189c323096aae8e2975de94e8549613cyshang                                    ControllerHandle,
64628a00297189c323096aae8e2975de94e8549613cyshang                                    RemainingDevicePath
64728a00297189c323096aae8e2975de94e8549613cyshang                                    );
648bc6b5892b007447b1024d98004681aa7a3305ddfqhuang          PERF_END (DriverBinding->DriverBindingHandle, "DB:Start:", NULL, 0);
64928a00297189c323096aae8e2975de94e8549613cyshang
65028a00297189c323096aae8e2975de94e8549613cyshang          if (!EFI_ERROR (Status)) {
65128a00297189c323096aae8e2975de94e8549613cyshang            //
65228a00297189c323096aae8e2975de94e8549613cyshang            // The driver was successfully started on ControllerHandle, so set a flag
65328a00297189c323096aae8e2975de94e8549613cyshang            //
65428a00297189c323096aae8e2975de94e8549613cyshang            OneStarted = TRUE;
65528a00297189c323096aae8e2975de94e8549613cyshang          }
65628a00297189c323096aae8e2975de94e8549613cyshang        }
65728a00297189c323096aae8e2975de94e8549613cyshang      }
65828a00297189c323096aae8e2975de94e8549613cyshang    }
65928a00297189c323096aae8e2975de94e8549613cyshang  } while (DriverFound);
66028a00297189c323096aae8e2975de94e8549613cyshang
66128a00297189c323096aae8e2975de94e8549613cyshang  //
66228a00297189c323096aae8e2975de94e8549613cyshang  // Free any buffers that were allocated with AllocatePool()
66328a00297189c323096aae8e2975de94e8549613cyshang  //
66428a00297189c323096aae8e2975de94e8549613cyshang  CoreFreePool (SortedDriverBindingProtocols);
66528a00297189c323096aae8e2975de94e8549613cyshang
66628a00297189c323096aae8e2975de94e8549613cyshang  //
66728a00297189c323096aae8e2975de94e8549613cyshang  // If at least one driver was started on ControllerHandle, then return EFI_SUCCESS.
66828a00297189c323096aae8e2975de94e8549613cyshang  //
66928a00297189c323096aae8e2975de94e8549613cyshang  if (OneStarted) {
67028a00297189c323096aae8e2975de94e8549613cyshang    return EFI_SUCCESS;
671022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  }
67228a00297189c323096aae8e2975de94e8549613cyshang
67328a00297189c323096aae8e2975de94e8549613cyshang  //
67428a00297189c323096aae8e2975de94e8549613cyshang  // If no drivers started and RemainingDevicePath is an End Device Path Node, then return EFI_SUCCESS
67528a00297189c323096aae8e2975de94e8549613cyshang  //
67628a00297189c323096aae8e2975de94e8549613cyshang  if (RemainingDevicePath != NULL) {
67728a00297189c323096aae8e2975de94e8549613cyshang    if (IsDevicePathEnd (RemainingDevicePath)) {
67828a00297189c323096aae8e2975de94e8549613cyshang      return EFI_SUCCESS;
67928a00297189c323096aae8e2975de94e8549613cyshang    }
680022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  }
68128a00297189c323096aae8e2975de94e8549613cyshang
68228a00297189c323096aae8e2975de94e8549613cyshang  //
68328a00297189c323096aae8e2975de94e8549613cyshang  // Otherwise, no drivers were started on ControllerHandle, so return EFI_NOT_FOUND
68428a00297189c323096aae8e2975de94e8549613cyshang  //
68528a00297189c323096aae8e2975de94e8549613cyshang  return EFI_NOT_FOUND;
68628a00297189c323096aae8e2975de94e8549613cyshang}
68728a00297189c323096aae8e2975de94e8549613cyshang
68828a00297189c323096aae8e2975de94e8549613cyshang
689162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
690162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang/**
691162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  Disonnects a controller from a driver
692162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
693022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  ControllerHandle                      ControllerHandle The handle of
694022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                                the controller from which
695022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                                driver(s)  are to be
696022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                                disconnected.
697022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  DriverImageHandle                     DriverImageHandle The driver to
698022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                                disconnect from ControllerHandle.
699022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  ChildHandle                           ChildHandle The handle of the
700022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                                child to destroy.
701022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang
702022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @retval EFI_SUCCESS                           One or more drivers were
703022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                                disconnected from the controller.
704022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @retval EFI_SUCCESS                           On entry, no drivers are managing
705022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                                ControllerHandle.
706022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @retval EFI_SUCCESS                           DriverImageHandle is not NULL,
707022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                                and on entry DriverImageHandle is
708022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                                not managing ControllerHandle.
709284ee2e829ab2453293b7dc4539727ad6c047163niruiyu  @retval EFI_INVALID_PARAMETER                 ControllerHandle is NULL.
710022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @retval EFI_INVALID_PARAMETER                 DriverImageHandle is not NULL,
711022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                                and it is not a valid EFI_HANDLE.
712022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @retval EFI_INVALID_PARAMETER                 ChildHandle is not NULL, and it
713022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                                is not a valid EFI_HANDLE.
714022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @retval EFI_OUT_OF_RESOURCES                  There are not enough resources
715022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                                available to disconnect any
716022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                                drivers from ControllerHandle.
717022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @retval EFI_DEVICE_ERROR                      The controller could not be
718022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                                disconnected because of a device
719162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang                                                error.
720162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
721162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang**/
722022c6d45ef78605c173023f53984e4dfaf7b11f4qhuangEFI_STATUS
72328a00297189c323096aae8e2975de94e8549613cyshangEFIAPI
72428a00297189c323096aae8e2975de94e8549613cyshangCoreDisconnectController (
72528a00297189c323096aae8e2975de94e8549613cyshang  IN  EFI_HANDLE  ControllerHandle,
72628a00297189c323096aae8e2975de94e8549613cyshang  IN  EFI_HANDLE  DriverImageHandle  OPTIONAL,
72728a00297189c323096aae8e2975de94e8549613cyshang  IN  EFI_HANDLE  ChildHandle        OPTIONAL
72828a00297189c323096aae8e2975de94e8549613cyshang  )
72928a00297189c323096aae8e2975de94e8549613cyshang{
73028a00297189c323096aae8e2975de94e8549613cyshang  EFI_STATUS                          Status;
73128a00297189c323096aae8e2975de94e8549613cyshang  IHANDLE                             *Handle;
73228a00297189c323096aae8e2975de94e8549613cyshang  EFI_HANDLE                          *DriverImageHandleBuffer;
73328a00297189c323096aae8e2975de94e8549613cyshang  EFI_HANDLE                          *ChildBuffer;
73428a00297189c323096aae8e2975de94e8549613cyshang  UINTN                               Index;
73528a00297189c323096aae8e2975de94e8549613cyshang  UINTN                               HandleIndex;
73628a00297189c323096aae8e2975de94e8549613cyshang  UINTN                               DriverImageHandleCount;
73728a00297189c323096aae8e2975de94e8549613cyshang  UINTN                               ChildrenToStop;
73828a00297189c323096aae8e2975de94e8549613cyshang  UINTN                               ChildBufferCount;
73928a00297189c323096aae8e2975de94e8549613cyshang  UINTN                               StopCount;
74028a00297189c323096aae8e2975de94e8549613cyshang  BOOLEAN                             Duplicate;
74128a00297189c323096aae8e2975de94e8549613cyshang  BOOLEAN                             ChildHandleValid;
74228a00297189c323096aae8e2975de94e8549613cyshang  BOOLEAN                             DriverImageHandleValid;
74328a00297189c323096aae8e2975de94e8549613cyshang  LIST_ENTRY                          *Link;
74428a00297189c323096aae8e2975de94e8549613cyshang  LIST_ENTRY                          *ProtLink;
74528a00297189c323096aae8e2975de94e8549613cyshang  OPEN_PROTOCOL_DATA                  *OpenData;
74628a00297189c323096aae8e2975de94e8549613cyshang  PROTOCOL_INTERFACE                  *Prot;
74728a00297189c323096aae8e2975de94e8549613cyshang  EFI_DRIVER_BINDING_PROTOCOL         *DriverBinding;
74828a00297189c323096aae8e2975de94e8549613cyshang
74928a00297189c323096aae8e2975de94e8549613cyshang  //
75028a00297189c323096aae8e2975de94e8549613cyshang  // Make sure ControllerHandle is valid
75128a00297189c323096aae8e2975de94e8549613cyshang  //
75228a00297189c323096aae8e2975de94e8549613cyshang  Status = CoreValidateHandle (ControllerHandle);
75328a00297189c323096aae8e2975de94e8549613cyshang  if (EFI_ERROR (Status)) {
75428a00297189c323096aae8e2975de94e8549613cyshang    return Status;
75528a00297189c323096aae8e2975de94e8549613cyshang  }
75628a00297189c323096aae8e2975de94e8549613cyshang
75728a00297189c323096aae8e2975de94e8549613cyshang  //
75828a00297189c323096aae8e2975de94e8549613cyshang  // Make sure ChildHandle is valid if it is not NULL
75928a00297189c323096aae8e2975de94e8549613cyshang  //
76028a00297189c323096aae8e2975de94e8549613cyshang  if (ChildHandle != NULL) {
76128a00297189c323096aae8e2975de94e8549613cyshang    Status = CoreValidateHandle (ChildHandle);
76228a00297189c323096aae8e2975de94e8549613cyshang    if (EFI_ERROR (Status)) {
76328a00297189c323096aae8e2975de94e8549613cyshang      return Status;
76428a00297189c323096aae8e2975de94e8549613cyshang    }
76528a00297189c323096aae8e2975de94e8549613cyshang  }
76628a00297189c323096aae8e2975de94e8549613cyshang
76728a00297189c323096aae8e2975de94e8549613cyshang  Handle = ControllerHandle;
76828a00297189c323096aae8e2975de94e8549613cyshang
76928a00297189c323096aae8e2975de94e8549613cyshang  //
77028a00297189c323096aae8e2975de94e8549613cyshang  // Get list of drivers that are currently managing ControllerHandle
77128a00297189c323096aae8e2975de94e8549613cyshang  //
77228a00297189c323096aae8e2975de94e8549613cyshang  DriverImageHandleBuffer = NULL;
773022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  DriverImageHandleCount  = 1;
774022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang
77528a00297189c323096aae8e2975de94e8549613cyshang  if (DriverImageHandle == NULL) {
77628a00297189c323096aae8e2975de94e8549613cyshang    //
77728a00297189c323096aae8e2975de94e8549613cyshang    // Look at each protocol interface for a match
77828a00297189c323096aae8e2975de94e8549613cyshang    //
77928a00297189c323096aae8e2975de94e8549613cyshang    DriverImageHandleCount = 0;
78028a00297189c323096aae8e2975de94e8549613cyshang
78128a00297189c323096aae8e2975de94e8549613cyshang    CoreAcquireProtocolLock ();
78228a00297189c323096aae8e2975de94e8549613cyshang    for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
78328a00297189c323096aae8e2975de94e8549613cyshang      Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
784022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang      for (ProtLink = Prot->OpenList.ForwardLink;
785022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang           ProtLink != &Prot->OpenList;
78628a00297189c323096aae8e2975de94e8549613cyshang           ProtLink = ProtLink->ForwardLink) {
78728a00297189c323096aae8e2975de94e8549613cyshang        OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
78828a00297189c323096aae8e2975de94e8549613cyshang        if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
78928a00297189c323096aae8e2975de94e8549613cyshang          DriverImageHandleCount++;
79028a00297189c323096aae8e2975de94e8549613cyshang        }
79128a00297189c323096aae8e2975de94e8549613cyshang      }
79228a00297189c323096aae8e2975de94e8549613cyshang    }
79328a00297189c323096aae8e2975de94e8549613cyshang    CoreReleaseProtocolLock ();
794022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang
79528a00297189c323096aae8e2975de94e8549613cyshang    //
79628a00297189c323096aae8e2975de94e8549613cyshang    // If there are no drivers managing this controller, then return EFI_SUCCESS
79728a00297189c323096aae8e2975de94e8549613cyshang    //
79828a00297189c323096aae8e2975de94e8549613cyshang    if (DriverImageHandleCount == 0) {
79928a00297189c323096aae8e2975de94e8549613cyshang      Status = EFI_SUCCESS;
80028a00297189c323096aae8e2975de94e8549613cyshang      goto Done;
80128a00297189c323096aae8e2975de94e8549613cyshang    }
80228a00297189c323096aae8e2975de94e8549613cyshang
8039c4ac31cca01b4a503c36616770ea3157bf3bb9eqhuang    DriverImageHandleBuffer = AllocatePool (sizeof (EFI_HANDLE) * DriverImageHandleCount);
80428a00297189c323096aae8e2975de94e8549613cyshang    if (DriverImageHandleBuffer == NULL) {
80528a00297189c323096aae8e2975de94e8549613cyshang      Status = EFI_OUT_OF_RESOURCES;
80628a00297189c323096aae8e2975de94e8549613cyshang      goto Done;
80728a00297189c323096aae8e2975de94e8549613cyshang    }
80828a00297189c323096aae8e2975de94e8549613cyshang
80928a00297189c323096aae8e2975de94e8549613cyshang    DriverImageHandleCount = 0;
81028a00297189c323096aae8e2975de94e8549613cyshang
81128a00297189c323096aae8e2975de94e8549613cyshang    CoreAcquireProtocolLock ();
81228a00297189c323096aae8e2975de94e8549613cyshang    for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
81328a00297189c323096aae8e2975de94e8549613cyshang      Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
814022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang      for (ProtLink = Prot->OpenList.ForwardLink;
815022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang           ProtLink != &Prot->OpenList;
81628a00297189c323096aae8e2975de94e8549613cyshang           ProtLink = ProtLink->ForwardLink) {
81728a00297189c323096aae8e2975de94e8549613cyshang        OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
81828a00297189c323096aae8e2975de94e8549613cyshang        if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
81928a00297189c323096aae8e2975de94e8549613cyshang          Duplicate = FALSE;
82028a00297189c323096aae8e2975de94e8549613cyshang          for (Index = 0; Index< DriverImageHandleCount; Index++) {
82128a00297189c323096aae8e2975de94e8549613cyshang            if (DriverImageHandleBuffer[Index] == OpenData->AgentHandle) {
82228a00297189c323096aae8e2975de94e8549613cyshang              Duplicate = TRUE;
82328a00297189c323096aae8e2975de94e8549613cyshang              break;
82428a00297189c323096aae8e2975de94e8549613cyshang            }
82528a00297189c323096aae8e2975de94e8549613cyshang          }
82628a00297189c323096aae8e2975de94e8549613cyshang          if (!Duplicate) {
82728a00297189c323096aae8e2975de94e8549613cyshang            DriverImageHandleBuffer[DriverImageHandleCount] = OpenData->AgentHandle;
82828a00297189c323096aae8e2975de94e8549613cyshang            DriverImageHandleCount++;
82928a00297189c323096aae8e2975de94e8549613cyshang          }
83028a00297189c323096aae8e2975de94e8549613cyshang        }
83128a00297189c323096aae8e2975de94e8549613cyshang      }
83228a00297189c323096aae8e2975de94e8549613cyshang    }
83328a00297189c323096aae8e2975de94e8549613cyshang    CoreReleaseProtocolLock ();
83428a00297189c323096aae8e2975de94e8549613cyshang  }
83528a00297189c323096aae8e2975de94e8549613cyshang
83628a00297189c323096aae8e2975de94e8549613cyshang  StopCount = 0;
83728a00297189c323096aae8e2975de94e8549613cyshang  for (HandleIndex = 0; HandleIndex < DriverImageHandleCount; HandleIndex++) {
83828a00297189c323096aae8e2975de94e8549613cyshang
83928a00297189c323096aae8e2975de94e8549613cyshang    if (DriverImageHandleBuffer != NULL) {
84028a00297189c323096aae8e2975de94e8549613cyshang      DriverImageHandle = DriverImageHandleBuffer[HandleIndex];
84128a00297189c323096aae8e2975de94e8549613cyshang    }
84228a00297189c323096aae8e2975de94e8549613cyshang
84328a00297189c323096aae8e2975de94e8549613cyshang    //
84428a00297189c323096aae8e2975de94e8549613cyshang    // Get the Driver Binding Protocol of the driver that is managing this controller
84528a00297189c323096aae8e2975de94e8549613cyshang    //
84628a00297189c323096aae8e2975de94e8549613cyshang    Status = CoreHandleProtocol (
847022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang               DriverImageHandle,
848022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang               &gEfiDriverBindingProtocolGuid,
84928a00297189c323096aae8e2975de94e8549613cyshang               (VOID **)&DriverBinding
85028a00297189c323096aae8e2975de94e8549613cyshang               );
851d2fbaaab17945b59ca66bcd2f72e26ba3361e1d0rsun    if (EFI_ERROR (Status) || DriverBinding == NULL) {
85228a00297189c323096aae8e2975de94e8549613cyshang      Status = EFI_INVALID_PARAMETER;
85328a00297189c323096aae8e2975de94e8549613cyshang      goto Done;
85428a00297189c323096aae8e2975de94e8549613cyshang    }
85528a00297189c323096aae8e2975de94e8549613cyshang
85628a00297189c323096aae8e2975de94e8549613cyshang    //
85728a00297189c323096aae8e2975de94e8549613cyshang    // Look at each protocol interface for a match
85828a00297189c323096aae8e2975de94e8549613cyshang    //
85928a00297189c323096aae8e2975de94e8549613cyshang    DriverImageHandleValid = FALSE;
86028a00297189c323096aae8e2975de94e8549613cyshang    ChildBufferCount = 0;
86128a00297189c323096aae8e2975de94e8549613cyshang
86228a00297189c323096aae8e2975de94e8549613cyshang    CoreAcquireProtocolLock ();
86328a00297189c323096aae8e2975de94e8549613cyshang    for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
86428a00297189c323096aae8e2975de94e8549613cyshang      Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
865022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang      for (ProtLink = Prot->OpenList.ForwardLink;
866022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang           ProtLink != &Prot->OpenList;
86728a00297189c323096aae8e2975de94e8549613cyshang           ProtLink = ProtLink->ForwardLink) {
86828a00297189c323096aae8e2975de94e8549613cyshang        OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
86928a00297189c323096aae8e2975de94e8549613cyshang        if (OpenData->AgentHandle == DriverImageHandle) {
87028a00297189c323096aae8e2975de94e8549613cyshang          if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
87128a00297189c323096aae8e2975de94e8549613cyshang            ChildBufferCount++;
872022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang          }
87328a00297189c323096aae8e2975de94e8549613cyshang          if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
87428a00297189c323096aae8e2975de94e8549613cyshang            DriverImageHandleValid = TRUE;
87528a00297189c323096aae8e2975de94e8549613cyshang          }
87628a00297189c323096aae8e2975de94e8549613cyshang        }
87728a00297189c323096aae8e2975de94e8549613cyshang      }
87828a00297189c323096aae8e2975de94e8549613cyshang    }
87928a00297189c323096aae8e2975de94e8549613cyshang    CoreReleaseProtocolLock ();
88028a00297189c323096aae8e2975de94e8549613cyshang
88128a00297189c323096aae8e2975de94e8549613cyshang    if (DriverImageHandleValid) {
88228a00297189c323096aae8e2975de94e8549613cyshang      ChildHandleValid = FALSE;
88328a00297189c323096aae8e2975de94e8549613cyshang      ChildBuffer = NULL;
88428a00297189c323096aae8e2975de94e8549613cyshang      if (ChildBufferCount != 0) {
8859c4ac31cca01b4a503c36616770ea3157bf3bb9eqhuang        ChildBuffer = AllocatePool (sizeof (EFI_HANDLE) * ChildBufferCount);
88628a00297189c323096aae8e2975de94e8549613cyshang        if (ChildBuffer == NULL) {
88728a00297189c323096aae8e2975de94e8549613cyshang          Status = EFI_OUT_OF_RESOURCES;
88828a00297189c323096aae8e2975de94e8549613cyshang          goto Done;
88928a00297189c323096aae8e2975de94e8549613cyshang        }
89028a00297189c323096aae8e2975de94e8549613cyshang
89128a00297189c323096aae8e2975de94e8549613cyshang        ChildBufferCount = 0;
89228a00297189c323096aae8e2975de94e8549613cyshang
89328a00297189c323096aae8e2975de94e8549613cyshang        CoreAcquireProtocolLock ();
89428a00297189c323096aae8e2975de94e8549613cyshang        for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
89528a00297189c323096aae8e2975de94e8549613cyshang          Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
896022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang          for (ProtLink = Prot->OpenList.ForwardLink;
897022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang               ProtLink != &Prot->OpenList;
89828a00297189c323096aae8e2975de94e8549613cyshang               ProtLink = ProtLink->ForwardLink) {
89928a00297189c323096aae8e2975de94e8549613cyshang            OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
90028a00297189c323096aae8e2975de94e8549613cyshang            if ((OpenData->AgentHandle == DriverImageHandle) &&
90128a00297189c323096aae8e2975de94e8549613cyshang                ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0)) {
90228a00297189c323096aae8e2975de94e8549613cyshang              Duplicate = FALSE;
90328a00297189c323096aae8e2975de94e8549613cyshang              for (Index = 0; Index < ChildBufferCount; Index++) {
90428a00297189c323096aae8e2975de94e8549613cyshang                if (ChildBuffer[Index] == OpenData->ControllerHandle) {
90528a00297189c323096aae8e2975de94e8549613cyshang                  Duplicate = TRUE;
90628a00297189c323096aae8e2975de94e8549613cyshang                  break;
90728a00297189c323096aae8e2975de94e8549613cyshang                }
90828a00297189c323096aae8e2975de94e8549613cyshang              }
90928a00297189c323096aae8e2975de94e8549613cyshang              if (!Duplicate) {
91028a00297189c323096aae8e2975de94e8549613cyshang                ChildBuffer[ChildBufferCount] = OpenData->ControllerHandle;
91128a00297189c323096aae8e2975de94e8549613cyshang                if (ChildHandle == ChildBuffer[ChildBufferCount]) {
91228a00297189c323096aae8e2975de94e8549613cyshang                  ChildHandleValid = TRUE;
91328a00297189c323096aae8e2975de94e8549613cyshang                }
91428a00297189c323096aae8e2975de94e8549613cyshang                ChildBufferCount++;
91528a00297189c323096aae8e2975de94e8549613cyshang              }
91628a00297189c323096aae8e2975de94e8549613cyshang            }
91728a00297189c323096aae8e2975de94e8549613cyshang          }
91828a00297189c323096aae8e2975de94e8549613cyshang        }
91928a00297189c323096aae8e2975de94e8549613cyshang        CoreReleaseProtocolLock ();
92028a00297189c323096aae8e2975de94e8549613cyshang      }
92128a00297189c323096aae8e2975de94e8549613cyshang
92228a00297189c323096aae8e2975de94e8549613cyshang      if (ChildHandle == NULL || ChildHandleValid) {
92328a00297189c323096aae8e2975de94e8549613cyshang        ChildrenToStop = 0;
92428a00297189c323096aae8e2975de94e8549613cyshang        Status = EFI_SUCCESS;
92528a00297189c323096aae8e2975de94e8549613cyshang        if (ChildBufferCount > 0) {
92628a00297189c323096aae8e2975de94e8549613cyshang          if (ChildHandle != NULL) {
92728a00297189c323096aae8e2975de94e8549613cyshang            ChildrenToStop = 1;
92828a00297189c323096aae8e2975de94e8549613cyshang            Status = DriverBinding->Stop (DriverBinding, ControllerHandle, ChildrenToStop, &ChildHandle);
92928a00297189c323096aae8e2975de94e8549613cyshang          } else {
93028a00297189c323096aae8e2975de94e8549613cyshang            ChildrenToStop = ChildBufferCount;
93128a00297189c323096aae8e2975de94e8549613cyshang            Status = DriverBinding->Stop (DriverBinding, ControllerHandle, ChildrenToStop, ChildBuffer);
93228a00297189c323096aae8e2975de94e8549613cyshang          }
93328a00297189c323096aae8e2975de94e8549613cyshang        }
93428a00297189c323096aae8e2975de94e8549613cyshang        if (!EFI_ERROR (Status) && ((ChildHandle == NULL) || (ChildBufferCount == ChildrenToStop))) {
93528a00297189c323096aae8e2975de94e8549613cyshang          Status = DriverBinding->Stop (DriverBinding, ControllerHandle, 0, NULL);
93628a00297189c323096aae8e2975de94e8549613cyshang        }
93728a00297189c323096aae8e2975de94e8549613cyshang        if (!EFI_ERROR (Status)) {
93828a00297189c323096aae8e2975de94e8549613cyshang          StopCount++;
93928a00297189c323096aae8e2975de94e8549613cyshang        }
94028a00297189c323096aae8e2975de94e8549613cyshang      }
94128a00297189c323096aae8e2975de94e8549613cyshang
94228a00297189c323096aae8e2975de94e8549613cyshang      if (ChildBuffer != NULL) {
94328a00297189c323096aae8e2975de94e8549613cyshang        CoreFreePool (ChildBuffer);
94428a00297189c323096aae8e2975de94e8549613cyshang      }
94528a00297189c323096aae8e2975de94e8549613cyshang    }
94628a00297189c323096aae8e2975de94e8549613cyshang  }
94728a00297189c323096aae8e2975de94e8549613cyshang
94828a00297189c323096aae8e2975de94e8549613cyshang  if (StopCount > 0) {
94928a00297189c323096aae8e2975de94e8549613cyshang    Status = EFI_SUCCESS;
95028a00297189c323096aae8e2975de94e8549613cyshang  } else {
95128a00297189c323096aae8e2975de94e8549613cyshang    Status = EFI_NOT_FOUND;
95228a00297189c323096aae8e2975de94e8549613cyshang  }
953022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang
954022c6d45ef78605c173023f53984e4dfaf7b11f4qhuangDone:
95528a00297189c323096aae8e2975de94e8549613cyshang
95628a00297189c323096aae8e2975de94e8549613cyshang  if (DriverImageHandleBuffer != NULL) {
95728a00297189c323096aae8e2975de94e8549613cyshang    CoreFreePool (DriverImageHandleBuffer);
95828a00297189c323096aae8e2975de94e8549613cyshang  }
95928a00297189c323096aae8e2975de94e8549613cyshang
96028a00297189c323096aae8e2975de94e8549613cyshang  return Status;
96128a00297189c323096aae8e2975de94e8549613cyshang}
962