123c98c9417908188207408afa3f6901b8aca826aqhuang/** @file
2504214c4870e9183418014634268ce630eb5332algao  Support functions to connect/disconnect UEFI Driver model Protocol
3504214c4870e9183418014634268ce630eb5332algao
45fef1a3492fd2bced485ff6845914d5681067f52Eric DongCopyright (c) 2006 - 2014, 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)) {
885fef1a3492fd2bced485ff6845914d5681067f52Eric Dong      ASSERT (HandleFilePath != NULL);
89bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao      FilePath     = HandleFilePath;
90bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao      TempFilePath = NULL;
91bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao      if (RemainingDevicePath != NULL && !Recursive) {
92bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao        HandleFilePathSize      = GetDevicePathSize (HandleFilePath) - sizeof (EFI_DEVICE_PATH_PROTOCOL);
93bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao        RemainingDevicePathSize = GetDevicePathSize (RemainingDevicePath);
94bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao        TempFilePath = AllocateZeroPool (HandleFilePathSize + RemainingDevicePathSize);
95bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao        ASSERT (TempFilePath != NULL);
96bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao        CopyMem (TempFilePath, HandleFilePath, HandleFilePathSize);
97bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao        CopyMem ((UINT8 *) TempFilePath + HandleFilePathSize, RemainingDevicePath, RemainingDevicePathSize);
98bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao        FilePath = TempFilePath;
99bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao      }
100bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao      Status = gSecurity2->FileAuthentication (
101bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao                            gSecurity2,
102bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao                            FilePath,
103bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao                            NULL,
104bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao                            0,
105bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao                            FALSE
106bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao                            );
107bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao      if (TempFilePath != NULL) {
108bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao        FreePool (TempFilePath);
109bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao      }
110bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao      if (EFI_ERROR (Status)) {
111bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao        return Status;
112bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao      }
113bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao    }
114bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao  }
115bc2dfdbcfc11dc785f0cc0ad2f519a63b98f88bclgao
11628a00297189c323096aae8e2975de94e8549613cyshang  Handle = ControllerHandle;
11728a00297189c323096aae8e2975de94e8549613cyshang
11828a00297189c323096aae8e2975de94e8549613cyshang  //
11985658066182d23e210209299770edaef26d09085mdkinney  // Make a copy of RemainingDevicePath to guanatee it is aligned
12028a00297189c323096aae8e2975de94e8549613cyshang  //
12128a00297189c323096aae8e2975de94e8549613cyshang  AlignedRemainingDevicePath = NULL;
12228a00297189c323096aae8e2975de94e8549613cyshang  if (RemainingDevicePath != NULL) {
1239c4ac31cca01b4a503c36616770ea3157bf3bb9eqhuang    AlignedRemainingDevicePath = DuplicateDevicePath (RemainingDevicePath);
1246c857d668cb7d2b219351be1daeec0bcd597e377qwang
1256c857d668cb7d2b219351be1daeec0bcd597e377qwang    if (AlignedRemainingDevicePath == NULL) {
1266c857d668cb7d2b219351be1daeec0bcd597e377qwang      return EFI_OUT_OF_RESOURCES;
1276c857d668cb7d2b219351be1daeec0bcd597e377qwang    }
12828a00297189c323096aae8e2975de94e8549613cyshang  }
12928a00297189c323096aae8e2975de94e8549613cyshang
13028a00297189c323096aae8e2975de94e8549613cyshang  //
13185658066182d23e210209299770edaef26d09085mdkinney  // Connect all drivers to ControllerHandle
13285658066182d23e210209299770edaef26d09085mdkinney  // If CoreConnectSingleController returns EFI_NOT_READY, then the number of
13385658066182d23e210209299770edaef26d09085mdkinney  // Driver Binding Protocols in the handle database has increased during the call
13485658066182d23e210209299770edaef26d09085mdkinney  // so the connect operation must be restarted
13528a00297189c323096aae8e2975de94e8549613cyshang  //
13685658066182d23e210209299770edaef26d09085mdkinney  do {
13785658066182d23e210209299770edaef26d09085mdkinney    ReturnStatus = CoreConnectSingleController (
138e94a9ff7271367e649ee4f9a86da1f1bea6d112eqhuang                     ControllerHandle,
139e94a9ff7271367e649ee4f9a86da1f1bea6d112eqhuang                     DriverImageHandle,
140e94a9ff7271367e649ee4f9a86da1f1bea6d112eqhuang                     AlignedRemainingDevicePath
141e94a9ff7271367e649ee4f9a86da1f1bea6d112eqhuang                     );
14285658066182d23e210209299770edaef26d09085mdkinney  } while (ReturnStatus == EFI_NOT_READY);
14385658066182d23e210209299770edaef26d09085mdkinney
14485658066182d23e210209299770edaef26d09085mdkinney  //
14585658066182d23e210209299770edaef26d09085mdkinney  // Free the aligned copy of RemainingDevicePath
14685658066182d23e210209299770edaef26d09085mdkinney  //
14785658066182d23e210209299770edaef26d09085mdkinney  if (AlignedRemainingDevicePath != NULL) {
14885658066182d23e210209299770edaef26d09085mdkinney    CoreFreePool (AlignedRemainingDevicePath);
14928a00297189c323096aae8e2975de94e8549613cyshang  }
15028a00297189c323096aae8e2975de94e8549613cyshang
15128a00297189c323096aae8e2975de94e8549613cyshang  //
15228a00297189c323096aae8e2975de94e8549613cyshang  // If recursive, then connect all drivers to all of ControllerHandle's children
15328a00297189c323096aae8e2975de94e8549613cyshang  //
15485658066182d23e210209299770edaef26d09085mdkinney  if (Recursive) {
15585658066182d23e210209299770edaef26d09085mdkinney    //
15685658066182d23e210209299770edaef26d09085mdkinney    // Acquire the protocol lock on the handle database so the child handles can be collected
15785658066182d23e210209299770edaef26d09085mdkinney    //
15885658066182d23e210209299770edaef26d09085mdkinney    CoreAcquireProtocolLock ();
15985658066182d23e210209299770edaef26d09085mdkinney
16085658066182d23e210209299770edaef26d09085mdkinney    //
16185658066182d23e210209299770edaef26d09085mdkinney    // Make sure the DriverBindingHandle is valid
16285658066182d23e210209299770edaef26d09085mdkinney    //
16385658066182d23e210209299770edaef26d09085mdkinney    Status = CoreValidateHandle (ControllerHandle);
16485658066182d23e210209299770edaef26d09085mdkinney    if (EFI_ERROR (Status)) {
16585658066182d23e210209299770edaef26d09085mdkinney      //
16685658066182d23e210209299770edaef26d09085mdkinney      // Release the protocol lock on the handle database
16785658066182d23e210209299770edaef26d09085mdkinney      //
16885658066182d23e210209299770edaef26d09085mdkinney      CoreReleaseProtocolLock ();
16985658066182d23e210209299770edaef26d09085mdkinney
17085658066182d23e210209299770edaef26d09085mdkinney      return ReturnStatus;
17185658066182d23e210209299770edaef26d09085mdkinney    }
17285658066182d23e210209299770edaef26d09085mdkinney
17385658066182d23e210209299770edaef26d09085mdkinney
17485658066182d23e210209299770edaef26d09085mdkinney    //
17585658066182d23e210209299770edaef26d09085mdkinney    // Count ControllerHandle's children
17685658066182d23e210209299770edaef26d09085mdkinney    //
17785658066182d23e210209299770edaef26d09085mdkinney    for (Link = Handle->Protocols.ForwardLink, ChildHandleCount = 0; Link != &Handle->Protocols; Link = Link->ForwardLink) {
17885658066182d23e210209299770edaef26d09085mdkinney      Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
179022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang      for (ProtLink = Prot->OpenList.ForwardLink;
180022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang          ProtLink != &Prot->OpenList;
18185658066182d23e210209299770edaef26d09085mdkinney          ProtLink = ProtLink->ForwardLink) {
18285658066182d23e210209299770edaef26d09085mdkinney        OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
18385658066182d23e210209299770edaef26d09085mdkinney        if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
18485658066182d23e210209299770edaef26d09085mdkinney          ChildHandleCount++;
18585658066182d23e210209299770edaef26d09085mdkinney        }
18685658066182d23e210209299770edaef26d09085mdkinney      }
18785658066182d23e210209299770edaef26d09085mdkinney    }
18885658066182d23e210209299770edaef26d09085mdkinney
18985658066182d23e210209299770edaef26d09085mdkinney    //
19085658066182d23e210209299770edaef26d09085mdkinney    // Allocate a handle buffer for ControllerHandle's children
19185658066182d23e210209299770edaef26d09085mdkinney    //
1929c4ac31cca01b4a503c36616770ea3157bf3bb9eqhuang    ChildHandleBuffer = AllocatePool (ChildHandleCount * sizeof(EFI_HANDLE));
1936c857d668cb7d2b219351be1daeec0bcd597e377qwang    if (ChildHandleBuffer == NULL) {
194fa3c419fec30282afb85a788cb71e12fd1a51804qwang      CoreReleaseProtocolLock ();
1956c857d668cb7d2b219351be1daeec0bcd597e377qwang      return EFI_OUT_OF_RESOURCES;
1966c857d668cb7d2b219351be1daeec0bcd597e377qwang    }
19785658066182d23e210209299770edaef26d09085mdkinney
19885658066182d23e210209299770edaef26d09085mdkinney    //
19985658066182d23e210209299770edaef26d09085mdkinney    // Fill in a handle buffer with ControllerHandle's children
20085658066182d23e210209299770edaef26d09085mdkinney    //
20185658066182d23e210209299770edaef26d09085mdkinney    for (Link = Handle->Protocols.ForwardLink, ChildHandleCount = 0; Link != &Handle->Protocols; Link = Link->ForwardLink) {
20285658066182d23e210209299770edaef26d09085mdkinney      Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
203022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang      for (ProtLink = Prot->OpenList.ForwardLink;
204022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang          ProtLink != &Prot->OpenList;
20585658066182d23e210209299770edaef26d09085mdkinney          ProtLink = ProtLink->ForwardLink) {
20628a00297189c323096aae8e2975de94e8549613cyshang        OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
20728a00297189c323096aae8e2975de94e8549613cyshang        if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
20885658066182d23e210209299770edaef26d09085mdkinney          ChildHandleBuffer[ChildHandleCount] = OpenData->ControllerHandle;
20985658066182d23e210209299770edaef26d09085mdkinney          ChildHandleCount++;
21085658066182d23e210209299770edaef26d09085mdkinney        }
21185658066182d23e210209299770edaef26d09085mdkinney      }
21285658066182d23e210209299770edaef26d09085mdkinney    }
21385658066182d23e210209299770edaef26d09085mdkinney
21485658066182d23e210209299770edaef26d09085mdkinney    //
21585658066182d23e210209299770edaef26d09085mdkinney    // Release the protocol lock on the handle database
21685658066182d23e210209299770edaef26d09085mdkinney    //
21785658066182d23e210209299770edaef26d09085mdkinney    CoreReleaseProtocolLock ();
21885658066182d23e210209299770edaef26d09085mdkinney
21985658066182d23e210209299770edaef26d09085mdkinney    //
22085658066182d23e210209299770edaef26d09085mdkinney    // Recursively connect each child handle
22185658066182d23e210209299770edaef26d09085mdkinney    //
22285658066182d23e210209299770edaef26d09085mdkinney    for (Index = 0; Index < ChildHandleCount; Index++) {
22385658066182d23e210209299770edaef26d09085mdkinney      CoreConnectController (
22485658066182d23e210209299770edaef26d09085mdkinney        ChildHandleBuffer[Index],
22585658066182d23e210209299770edaef26d09085mdkinney        NULL,
22685658066182d23e210209299770edaef26d09085mdkinney        NULL,
22785658066182d23e210209299770edaef26d09085mdkinney        TRUE
228022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang        );
22985658066182d23e210209299770edaef26d09085mdkinney    }
23085658066182d23e210209299770edaef26d09085mdkinney
23185658066182d23e210209299770edaef26d09085mdkinney    //
23285658066182d23e210209299770edaef26d09085mdkinney    // Free the handle buffer of ControllerHandle's children
23385658066182d23e210209299770edaef26d09085mdkinney    //
23485658066182d23e210209299770edaef26d09085mdkinney    CoreFreePool (ChildHandleBuffer);
23585658066182d23e210209299770edaef26d09085mdkinney  }
23685658066182d23e210209299770edaef26d09085mdkinney
23728a00297189c323096aae8e2975de94e8549613cyshang  return ReturnStatus;
23828a00297189c323096aae8e2975de94e8549613cyshang}
23928a00297189c323096aae8e2975de94e8549613cyshang
240162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
241162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang/**
242162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  Add Driver Binding Protocols from Context Driver Image Handles to sorted
243162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  Driver Binding Protocol list.
244162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
245022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  DriverBindingHandle                   Handle of the driver binding
246022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                                protocol.
247022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  NumberOfSortedDriverBindingProtocols  Number Of sorted driver binding
248022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                                protocols
249022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  SortedDriverBindingProtocols          The sorted protocol list.
250022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  DriverBindingHandleCount              Driver Binding Handle Count.
251022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  DriverBindingHandleBuffer             The buffer of driver binding
252022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                                protocol to be modified.
253022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  IsImageHandle                         Indicate whether
254022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                                DriverBindingHandle is an image
255022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                                handle
256162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
257162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  @return None.
258162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
259162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang**/
26028a00297189c323096aae8e2975de94e8549613cyshangVOID
26128a00297189c323096aae8e2975de94e8549613cyshangAddSortedDriverBindingProtocol (
26228a00297189c323096aae8e2975de94e8549613cyshang  IN      EFI_HANDLE                   DriverBindingHandle,
263022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  IN OUT  UINTN                        *NumberOfSortedDriverBindingProtocols,
26428a00297189c323096aae8e2975de94e8549613cyshang  IN OUT  EFI_DRIVER_BINDING_PROTOCOL  **SortedDriverBindingProtocols,
26528a00297189c323096aae8e2975de94e8549613cyshang  IN      UINTN                        DriverBindingHandleCount,
266adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney  IN OUT  EFI_HANDLE                   *DriverBindingHandleBuffer,
267adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney  IN      BOOLEAN                      IsImageHandle
26828a00297189c323096aae8e2975de94e8549613cyshang  )
26928a00297189c323096aae8e2975de94e8549613cyshang{
27028a00297189c323096aae8e2975de94e8549613cyshang  EFI_STATUS                   Status;
27128a00297189c323096aae8e2975de94e8549613cyshang  EFI_DRIVER_BINDING_PROTOCOL  *DriverBinding;
27228a00297189c323096aae8e2975de94e8549613cyshang  UINTN                        Index;
27328a00297189c323096aae8e2975de94e8549613cyshang
27428a00297189c323096aae8e2975de94e8549613cyshang  //
27528a00297189c323096aae8e2975de94e8549613cyshang  // Make sure the DriverBindingHandle is valid
27628a00297189c323096aae8e2975de94e8549613cyshang  //
27728a00297189c323096aae8e2975de94e8549613cyshang  Status = CoreValidateHandle (DriverBindingHandle);
27828a00297189c323096aae8e2975de94e8549613cyshang  if (EFI_ERROR (Status)) {
27928a00297189c323096aae8e2975de94e8549613cyshang    return;
28028a00297189c323096aae8e2975de94e8549613cyshang  }
28128a00297189c323096aae8e2975de94e8549613cyshang
28228a00297189c323096aae8e2975de94e8549613cyshang  //
283adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney  // If IsImageHandle is TRUE, then DriverBindingHandle is an image handle
284adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney  // Find all the DriverBindingHandles associated with that image handle and add them to the sorted list
285adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney  //
286adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney  if (IsImageHandle) {
287adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney    //
288adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney    // Loop through all the Driver Binding Handles
289adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney    //
290adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney    for (Index = 0; Index < DriverBindingHandleCount; Index++) {
291adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney      //
292adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney      // Retrieve the Driver Binding Protocol associated with each Driver Binding Handle
293adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney      //
294adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney      Status = CoreHandleProtocol (
295adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney                DriverBindingHandleBuffer[Index],
296adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney                &gEfiDriverBindingProtocolGuid,
297e94a9ff7271367e649ee4f9a86da1f1bea6d112eqhuang                (VOID **) &DriverBinding
298adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney                );
29970279390ba9a0774e020af36120f8b9ba1c217dbmdkinney      if (EFI_ERROR (Status) || DriverBinding == NULL) {
30070279390ba9a0774e020af36120f8b9ba1c217dbmdkinney        continue;
30170279390ba9a0774e020af36120f8b9ba1c217dbmdkinney      }
30270279390ba9a0774e020af36120f8b9ba1c217dbmdkinney
303adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney      //
304adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney      // If the ImageHandle associated with DriverBinding matches DriverBindingHandle,
305adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney      // then add the DriverBindingProtocol[Index] to the sorted list
306adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney      //
307adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney      if (DriverBinding->ImageHandle == DriverBindingHandle) {
308adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney        AddSortedDriverBindingProtocol (
309adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney          DriverBindingHandleBuffer[Index],
310022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang          NumberOfSortedDriverBindingProtocols,
311adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney          SortedDriverBindingProtocols,
312adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney          DriverBindingHandleCount,
313adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney          DriverBindingHandleBuffer,
314adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney          FALSE
315adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney          );
316adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney      }
317adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney    }
318adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney    return;
319adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney  }
320adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney
321adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney  //
32228a00297189c323096aae8e2975de94e8549613cyshang  // Retrieve the Driver Binding Protocol from DriverBindingHandle
32328a00297189c323096aae8e2975de94e8549613cyshang  //
32428a00297189c323096aae8e2975de94e8549613cyshang  Status = CoreHandleProtocol(
32528a00297189c323096aae8e2975de94e8549613cyshang             DriverBindingHandle,
32628a00297189c323096aae8e2975de94e8549613cyshang             &gEfiDriverBindingProtocolGuid,
327e94a9ff7271367e649ee4f9a86da1f1bea6d112eqhuang             (VOID **) &DriverBinding
32828a00297189c323096aae8e2975de94e8549613cyshang             );
32928a00297189c323096aae8e2975de94e8549613cyshang  //
33028a00297189c323096aae8e2975de94e8549613cyshang  // If DriverBindingHandle does not support the Driver Binding Protocol then return
33128a00297189c323096aae8e2975de94e8549613cyshang  //
33228a00297189c323096aae8e2975de94e8549613cyshang  if (EFI_ERROR (Status) || DriverBinding == NULL) {
33328a00297189c323096aae8e2975de94e8549613cyshang    return;
33428a00297189c323096aae8e2975de94e8549613cyshang  }
33528a00297189c323096aae8e2975de94e8549613cyshang
33628a00297189c323096aae8e2975de94e8549613cyshang  //
33728a00297189c323096aae8e2975de94e8549613cyshang  // See if DriverBinding is already in the sorted list
33828a00297189c323096aae8e2975de94e8549613cyshang  //
33985658066182d23e210209299770edaef26d09085mdkinney  for (Index = 0; Index < *NumberOfSortedDriverBindingProtocols && Index < DriverBindingHandleCount; Index++) {
34028a00297189c323096aae8e2975de94e8549613cyshang    if (DriverBinding == SortedDriverBindingProtocols[Index]) {
34128a00297189c323096aae8e2975de94e8549613cyshang      return;
34228a00297189c323096aae8e2975de94e8549613cyshang    }
34328a00297189c323096aae8e2975de94e8549613cyshang  }
34428a00297189c323096aae8e2975de94e8549613cyshang
34528a00297189c323096aae8e2975de94e8549613cyshang  //
34628a00297189c323096aae8e2975de94e8549613cyshang  // Add DriverBinding to the end of the list
34728a00297189c323096aae8e2975de94e8549613cyshang  //
34885658066182d23e210209299770edaef26d09085mdkinney  if (*NumberOfSortedDriverBindingProtocols < DriverBindingHandleCount) {
34985658066182d23e210209299770edaef26d09085mdkinney    SortedDriverBindingProtocols[*NumberOfSortedDriverBindingProtocols] = DriverBinding;
35085658066182d23e210209299770edaef26d09085mdkinney  }
35128a00297189c323096aae8e2975de94e8549613cyshang  *NumberOfSortedDriverBindingProtocols = *NumberOfSortedDriverBindingProtocols + 1;
35228a00297189c323096aae8e2975de94e8549613cyshang
35328a00297189c323096aae8e2975de94e8549613cyshang  //
35428a00297189c323096aae8e2975de94e8549613cyshang  // Mark the cooresponding handle in DriverBindingHandleBuffer as used
35528a00297189c323096aae8e2975de94e8549613cyshang  //
35628a00297189c323096aae8e2975de94e8549613cyshang  for (Index = 0; Index < DriverBindingHandleCount; Index++) {
35728a00297189c323096aae8e2975de94e8549613cyshang    if (DriverBindingHandleBuffer[Index] == DriverBindingHandle) {
35828a00297189c323096aae8e2975de94e8549613cyshang      DriverBindingHandleBuffer[Index] = NULL;
35928a00297189c323096aae8e2975de94e8549613cyshang    }
36028a00297189c323096aae8e2975de94e8549613cyshang  }
36128a00297189c323096aae8e2975de94e8549613cyshang}
362022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang
363162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
364162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang/**
365162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  Connects a controller to a driver.
366162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
367022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  ControllerHandle                      Handle of the controller to be
368022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                                connected.
369022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  ContextDriverImageHandles             DriverImageHandle A pointer to an
370022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                                ordered list of driver image
371022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                                handles.
372022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  RemainingDevicePath                   RemainingDevicePath A pointer to
373022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                                the device path that specifies a
374022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                                child  of the controller
375022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                                specified by ControllerHandle.
376022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang
377022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @retval EFI_SUCCESS                           One or more drivers were
378022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                                connected to ControllerHandle.
379022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @retval EFI_OUT_OF_RESOURCES                  No enough system resources to
380022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                                complete the request.
381022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @retval EFI_NOT_FOUND                         No drivers were connected to
382162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang                                                ControllerHandle.
383162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
384162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang**/
385022c6d45ef78605c173023f53984e4dfaf7b11f4qhuangEFI_STATUS
38628a00297189c323096aae8e2975de94e8549613cyshangCoreConnectSingleController (
38728a00297189c323096aae8e2975de94e8549613cyshang  IN  EFI_HANDLE                ControllerHandle,
38828a00297189c323096aae8e2975de94e8549613cyshang  IN  EFI_HANDLE                *ContextDriverImageHandles OPTIONAL,
389022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  IN  EFI_DEVICE_PATH_PROTOCOL  *RemainingDevicePath       OPTIONAL
39028a00297189c323096aae8e2975de94e8549613cyshang  )
39128a00297189c323096aae8e2975de94e8549613cyshang{
39228a00297189c323096aae8e2975de94e8549613cyshang  EFI_STATUS                                 Status;
39328a00297189c323096aae8e2975de94e8549613cyshang  UINTN                                      Index;
39428a00297189c323096aae8e2975de94e8549613cyshang  EFI_HANDLE                                 DriverImageHandle;
39528a00297189c323096aae8e2975de94e8549613cyshang  EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL      *PlatformDriverOverride;
39628a00297189c323096aae8e2975de94e8549613cyshang  EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL  *BusSpecificDriverOverride;
39728a00297189c323096aae8e2975de94e8549613cyshang  UINTN                                      DriverBindingHandleCount;
39828a00297189c323096aae8e2975de94e8549613cyshang  EFI_HANDLE                                 *DriverBindingHandleBuffer;
39970279390ba9a0774e020af36120f8b9ba1c217dbmdkinney  UINTN                                      NewDriverBindingHandleCount;
40070279390ba9a0774e020af36120f8b9ba1c217dbmdkinney  EFI_HANDLE                                 *NewDriverBindingHandleBuffer;
40128a00297189c323096aae8e2975de94e8549613cyshang  EFI_DRIVER_BINDING_PROTOCOL                *DriverBinding;
402396e9039aec00982e98392a843635c1dcff5364dniruiyu  EFI_DRIVER_FAMILY_OVERRIDE_PROTOCOL        *DriverFamilyOverride;
40328a00297189c323096aae8e2975de94e8549613cyshang  UINTN                                      NumberOfSortedDriverBindingProtocols;
40428a00297189c323096aae8e2975de94e8549613cyshang  EFI_DRIVER_BINDING_PROTOCOL                **SortedDriverBindingProtocols;
405396e9039aec00982e98392a843635c1dcff5364dniruiyu  UINT32                                     DriverFamilyOverrideVersion;
40628a00297189c323096aae8e2975de94e8549613cyshang  UINT32                                     HighestVersion;
40728a00297189c323096aae8e2975de94e8549613cyshang  UINTN                                      HighestIndex;
40828a00297189c323096aae8e2975de94e8549613cyshang  UINTN                                      SortIndex;
40928a00297189c323096aae8e2975de94e8549613cyshang  BOOLEAN                                    OneStarted;
41028a00297189c323096aae8e2975de94e8549613cyshang  BOOLEAN                                    DriverFound;
41128a00297189c323096aae8e2975de94e8549613cyshang
41228a00297189c323096aae8e2975de94e8549613cyshang  //
41328a00297189c323096aae8e2975de94e8549613cyshang  // Initialize local variables
41428a00297189c323096aae8e2975de94e8549613cyshang  //
41528a00297189c323096aae8e2975de94e8549613cyshang  DriverBindingHandleCount              = 0;
41628a00297189c323096aae8e2975de94e8549613cyshang  DriverBindingHandleBuffer             = NULL;
41728a00297189c323096aae8e2975de94e8549613cyshang  NumberOfSortedDriverBindingProtocols  = 0;
41828a00297189c323096aae8e2975de94e8549613cyshang  SortedDriverBindingProtocols          = NULL;
4194e1005eca7186cbe61aaae09108f6fdf29959f22Eric Dong  PlatformDriverOverride                = NULL;
4204e1005eca7186cbe61aaae09108f6fdf29959f22Eric Dong  NewDriverBindingHandleBuffer          = NULL;
42128a00297189c323096aae8e2975de94e8549613cyshang
42228a00297189c323096aae8e2975de94e8549613cyshang  //
42328a00297189c323096aae8e2975de94e8549613cyshang  // Get list of all Driver Binding Protocol Instances
42428a00297189c323096aae8e2975de94e8549613cyshang  //
42528a00297189c323096aae8e2975de94e8549613cyshang  Status = CoreLocateHandleBuffer (
426022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang             ByProtocol,
427022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang             &gEfiDriverBindingProtocolGuid,
42828a00297189c323096aae8e2975de94e8549613cyshang             NULL,
429022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang             &DriverBindingHandleCount,
43028a00297189c323096aae8e2975de94e8549613cyshang             &DriverBindingHandleBuffer
43128a00297189c323096aae8e2975de94e8549613cyshang             );
43228a00297189c323096aae8e2975de94e8549613cyshang  if (EFI_ERROR (Status) || (DriverBindingHandleCount == 0)) {
43328a00297189c323096aae8e2975de94e8549613cyshang    return EFI_NOT_FOUND;
43428a00297189c323096aae8e2975de94e8549613cyshang  }
43528a00297189c323096aae8e2975de94e8549613cyshang
43628a00297189c323096aae8e2975de94e8549613cyshang  //
43728a00297189c323096aae8e2975de94e8549613cyshang  // Allocate a duplicate array for the sorted Driver Binding Protocol Instances
43828a00297189c323096aae8e2975de94e8549613cyshang  //
4399c4ac31cca01b4a503c36616770ea3157bf3bb9eqhuang  SortedDriverBindingProtocols = AllocatePool (sizeof (VOID *) * DriverBindingHandleCount);
44028a00297189c323096aae8e2975de94e8549613cyshang  if (SortedDriverBindingProtocols == NULL) {
44128a00297189c323096aae8e2975de94e8549613cyshang    CoreFreePool (DriverBindingHandleBuffer);
44228a00297189c323096aae8e2975de94e8549613cyshang    return EFI_OUT_OF_RESOURCES;
44328a00297189c323096aae8e2975de94e8549613cyshang  }
44428a00297189c323096aae8e2975de94e8549613cyshang
44528a00297189c323096aae8e2975de94e8549613cyshang  //
44628a00297189c323096aae8e2975de94e8549613cyshang  // Add Driver Binding Protocols from Context Driver Image Handles first
44728a00297189c323096aae8e2975de94e8549613cyshang  //
44828a00297189c323096aae8e2975de94e8549613cyshang  if (ContextDriverImageHandles != NULL) {
44928a00297189c323096aae8e2975de94e8549613cyshang    for (Index = 0; ContextDriverImageHandles[Index] != NULL; Index++) {
45028a00297189c323096aae8e2975de94e8549613cyshang      AddSortedDriverBindingProtocol (
45128a00297189c323096aae8e2975de94e8549613cyshang        ContextDriverImageHandles[Index],
452022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang        &NumberOfSortedDriverBindingProtocols,
45328a00297189c323096aae8e2975de94e8549613cyshang        SortedDriverBindingProtocols,
45428a00297189c323096aae8e2975de94e8549613cyshang        DriverBindingHandleCount,
455adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney        DriverBindingHandleBuffer,
456adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney        FALSE
45728a00297189c323096aae8e2975de94e8549613cyshang        );
45828a00297189c323096aae8e2975de94e8549613cyshang    }
45928a00297189c323096aae8e2975de94e8549613cyshang  }
46028a00297189c323096aae8e2975de94e8549613cyshang
46128a00297189c323096aae8e2975de94e8549613cyshang  //
46228a00297189c323096aae8e2975de94e8549613cyshang  // Add the Platform Driver Override Protocol drivers for ControllerHandle next
46328a00297189c323096aae8e2975de94e8549613cyshang  //
46428a00297189c323096aae8e2975de94e8549613cyshang  Status = CoreLocateProtocol (
465022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang             &gEfiPlatformDriverOverrideProtocolGuid,
466022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang             NULL,
467e94a9ff7271367e649ee4f9a86da1f1bea6d112eqhuang             (VOID **) &PlatformDriverOverride
46828a00297189c323096aae8e2975de94e8549613cyshang             );
46928a00297189c323096aae8e2975de94e8549613cyshang  if (!EFI_ERROR (Status) && (PlatformDriverOverride != NULL)) {
47028a00297189c323096aae8e2975de94e8549613cyshang    DriverImageHandle = NULL;
47128a00297189c323096aae8e2975de94e8549613cyshang    do {
47228a00297189c323096aae8e2975de94e8549613cyshang      Status = PlatformDriverOverride->GetDriver (
47328a00297189c323096aae8e2975de94e8549613cyshang                                         PlatformDriverOverride,
47428a00297189c323096aae8e2975de94e8549613cyshang                                         ControllerHandle,
47528a00297189c323096aae8e2975de94e8549613cyshang                                         &DriverImageHandle
47628a00297189c323096aae8e2975de94e8549613cyshang                                         );
47728a00297189c323096aae8e2975de94e8549613cyshang      if (!EFI_ERROR (Status)) {
47828a00297189c323096aae8e2975de94e8549613cyshang        AddSortedDriverBindingProtocol (
47928a00297189c323096aae8e2975de94e8549613cyshang          DriverImageHandle,
480022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang          &NumberOfSortedDriverBindingProtocols,
48128a00297189c323096aae8e2975de94e8549613cyshang          SortedDriverBindingProtocols,
48228a00297189c323096aae8e2975de94e8549613cyshang          DriverBindingHandleCount,
483adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney          DriverBindingHandleBuffer,
484adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney          TRUE
48528a00297189c323096aae8e2975de94e8549613cyshang          );
48628a00297189c323096aae8e2975de94e8549613cyshang      }
48728a00297189c323096aae8e2975de94e8549613cyshang    } while (!EFI_ERROR (Status));
48828a00297189c323096aae8e2975de94e8549613cyshang  }
48928a00297189c323096aae8e2975de94e8549613cyshang
49028a00297189c323096aae8e2975de94e8549613cyshang  //
491396e9039aec00982e98392a843635c1dcff5364dniruiyu  // Add the Driver Family Override Protocol drivers for ControllerHandle
492396e9039aec00982e98392a843635c1dcff5364dniruiyu  //
493396e9039aec00982e98392a843635c1dcff5364dniruiyu  while (TRUE) {
494396e9039aec00982e98392a843635c1dcff5364dniruiyu    HighestIndex   = DriverBindingHandleCount;
495396e9039aec00982e98392a843635c1dcff5364dniruiyu    HighestVersion = 0;
496396e9039aec00982e98392a843635c1dcff5364dniruiyu    for (Index = 0; Index < DriverBindingHandleCount; Index++) {
497396e9039aec00982e98392a843635c1dcff5364dniruiyu      Status = CoreHandleProtocol (
498396e9039aec00982e98392a843635c1dcff5364dniruiyu                 DriverBindingHandleBuffer[Index],
499396e9039aec00982e98392a843635c1dcff5364dniruiyu                 &gEfiDriverFamilyOverrideProtocolGuid,
500396e9039aec00982e98392a843635c1dcff5364dniruiyu                 (VOID **) &DriverFamilyOverride
501396e9039aec00982e98392a843635c1dcff5364dniruiyu                 );
502396e9039aec00982e98392a843635c1dcff5364dniruiyu      if (!EFI_ERROR (Status) && (DriverFamilyOverride != NULL)) {
503396e9039aec00982e98392a843635c1dcff5364dniruiyu        DriverFamilyOverrideVersion = DriverFamilyOverride->GetVersion (DriverFamilyOverride);
504396e9039aec00982e98392a843635c1dcff5364dniruiyu        if ((HighestIndex == DriverBindingHandleCount) || (DriverFamilyOverrideVersion > HighestVersion)) {
505396e9039aec00982e98392a843635c1dcff5364dniruiyu          HighestVersion = DriverFamilyOverrideVersion;
506396e9039aec00982e98392a843635c1dcff5364dniruiyu          HighestIndex   = Index;
507396e9039aec00982e98392a843635c1dcff5364dniruiyu        }
508396e9039aec00982e98392a843635c1dcff5364dniruiyu      }
509396e9039aec00982e98392a843635c1dcff5364dniruiyu    }
510396e9039aec00982e98392a843635c1dcff5364dniruiyu
511396e9039aec00982e98392a843635c1dcff5364dniruiyu    if (HighestIndex == DriverBindingHandleCount) {
512396e9039aec00982e98392a843635c1dcff5364dniruiyu      break;
513396e9039aec00982e98392a843635c1dcff5364dniruiyu    }
514396e9039aec00982e98392a843635c1dcff5364dniruiyu
515396e9039aec00982e98392a843635c1dcff5364dniruiyu    AddSortedDriverBindingProtocol (
516396e9039aec00982e98392a843635c1dcff5364dniruiyu      DriverBindingHandleBuffer[HighestIndex],
517396e9039aec00982e98392a843635c1dcff5364dniruiyu      &NumberOfSortedDriverBindingProtocols,
518396e9039aec00982e98392a843635c1dcff5364dniruiyu      SortedDriverBindingProtocols,
519396e9039aec00982e98392a843635c1dcff5364dniruiyu      DriverBindingHandleCount,
520396e9039aec00982e98392a843635c1dcff5364dniruiyu      DriverBindingHandleBuffer,
521396e9039aec00982e98392a843635c1dcff5364dniruiyu      FALSE
522396e9039aec00982e98392a843635c1dcff5364dniruiyu      );
523396e9039aec00982e98392a843635c1dcff5364dniruiyu  }
524396e9039aec00982e98392a843635c1dcff5364dniruiyu
525396e9039aec00982e98392a843635c1dcff5364dniruiyu  //
52628a00297189c323096aae8e2975de94e8549613cyshang  // Get the Bus Specific Driver Override Protocol instance on the Controller Handle
52728a00297189c323096aae8e2975de94e8549613cyshang  //
528adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney  Status = CoreHandleProtocol (
529022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang             ControllerHandle,
530022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang             &gEfiBusSpecificDriverOverrideProtocolGuid,
531e94a9ff7271367e649ee4f9a86da1f1bea6d112eqhuang             (VOID **) &BusSpecificDriverOverride
53228a00297189c323096aae8e2975de94e8549613cyshang             );
53328a00297189c323096aae8e2975de94e8549613cyshang  if (!EFI_ERROR (Status) && (BusSpecificDriverOverride != NULL)) {
53428a00297189c323096aae8e2975de94e8549613cyshang    DriverImageHandle = NULL;
53528a00297189c323096aae8e2975de94e8549613cyshang    do {
53628a00297189c323096aae8e2975de94e8549613cyshang      Status = BusSpecificDriverOverride->GetDriver (
53728a00297189c323096aae8e2975de94e8549613cyshang                                            BusSpecificDriverOverride,
53828a00297189c323096aae8e2975de94e8549613cyshang                                            &DriverImageHandle
53928a00297189c323096aae8e2975de94e8549613cyshang                                            );
54028a00297189c323096aae8e2975de94e8549613cyshang      if (!EFI_ERROR (Status)) {
54128a00297189c323096aae8e2975de94e8549613cyshang        AddSortedDriverBindingProtocol (
54228a00297189c323096aae8e2975de94e8549613cyshang          DriverImageHandle,
543022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang          &NumberOfSortedDriverBindingProtocols,
54428a00297189c323096aae8e2975de94e8549613cyshang          SortedDriverBindingProtocols,
54528a00297189c323096aae8e2975de94e8549613cyshang          DriverBindingHandleCount,
546adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney          DriverBindingHandleBuffer,
547adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney          TRUE
54828a00297189c323096aae8e2975de94e8549613cyshang          );
54928a00297189c323096aae8e2975de94e8549613cyshang      }
55028a00297189c323096aae8e2975de94e8549613cyshang    } while (!EFI_ERROR (Status));
55128a00297189c323096aae8e2975de94e8549613cyshang  }
55228a00297189c323096aae8e2975de94e8549613cyshang
55328a00297189c323096aae8e2975de94e8549613cyshang  //
55428a00297189c323096aae8e2975de94e8549613cyshang  // Then add all the remaining Driver Binding Protocols
55528a00297189c323096aae8e2975de94e8549613cyshang  //
55628a00297189c323096aae8e2975de94e8549613cyshang  SortIndex = NumberOfSortedDriverBindingProtocols;
55728a00297189c323096aae8e2975de94e8549613cyshang  for (Index = 0; Index < DriverBindingHandleCount; Index++) {
55828a00297189c323096aae8e2975de94e8549613cyshang    AddSortedDriverBindingProtocol (
55928a00297189c323096aae8e2975de94e8549613cyshang      DriverBindingHandleBuffer[Index],
560022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang      &NumberOfSortedDriverBindingProtocols,
56128a00297189c323096aae8e2975de94e8549613cyshang      SortedDriverBindingProtocols,
56228a00297189c323096aae8e2975de94e8549613cyshang      DriverBindingHandleCount,
563adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney      DriverBindingHandleBuffer,
564adc8840a2517db5d93fbdba93f5f51d94ee0fb39mdkinney      FALSE
56528a00297189c323096aae8e2975de94e8549613cyshang      );
56628a00297189c323096aae8e2975de94e8549613cyshang  }
56728a00297189c323096aae8e2975de94e8549613cyshang
56828a00297189c323096aae8e2975de94e8549613cyshang  //
56928a00297189c323096aae8e2975de94e8549613cyshang  // Free the Driver Binding Handle Buffer
57028a00297189c323096aae8e2975de94e8549613cyshang  //
57128a00297189c323096aae8e2975de94e8549613cyshang  CoreFreePool (DriverBindingHandleBuffer);
57228a00297189c323096aae8e2975de94e8549613cyshang
57328a00297189c323096aae8e2975de94e8549613cyshang  //
57485658066182d23e210209299770edaef26d09085mdkinney  // If the number of Driver Binding Protocols has increased since this function started, then return
57585658066182d23e210209299770edaef26d09085mdkinney  // EFI_NOT_READY, so it will be restarted
57685658066182d23e210209299770edaef26d09085mdkinney  //
57770279390ba9a0774e020af36120f8b9ba1c217dbmdkinney  Status = CoreLocateHandleBuffer (
578022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang             ByProtocol,
579022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang             &gEfiDriverBindingProtocolGuid,
58070279390ba9a0774e020af36120f8b9ba1c217dbmdkinney             NULL,
581022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang             &NewDriverBindingHandleCount,
58270279390ba9a0774e020af36120f8b9ba1c217dbmdkinney             &NewDriverBindingHandleBuffer
58370279390ba9a0774e020af36120f8b9ba1c217dbmdkinney             );
58470279390ba9a0774e020af36120f8b9ba1c217dbmdkinney  CoreFreePool (NewDriverBindingHandleBuffer);
58570279390ba9a0774e020af36120f8b9ba1c217dbmdkinney  if (NewDriverBindingHandleCount > DriverBindingHandleCount) {
58685658066182d23e210209299770edaef26d09085mdkinney    //
58785658066182d23e210209299770edaef26d09085mdkinney    // Free any buffers that were allocated with AllocatePool()
58885658066182d23e210209299770edaef26d09085mdkinney    //
58985658066182d23e210209299770edaef26d09085mdkinney    CoreFreePool (SortedDriverBindingProtocols);
59085658066182d23e210209299770edaef26d09085mdkinney
59185658066182d23e210209299770edaef26d09085mdkinney    return EFI_NOT_READY;
59285658066182d23e210209299770edaef26d09085mdkinney  }
59385658066182d23e210209299770edaef26d09085mdkinney
59485658066182d23e210209299770edaef26d09085mdkinney  //
59528a00297189c323096aae8e2975de94e8549613cyshang  // Sort the remaining DriverBinding Protocol based on their Version field from
59628a00297189c323096aae8e2975de94e8549613cyshang  // highest to lowest.
59728a00297189c323096aae8e2975de94e8549613cyshang  //
59828a00297189c323096aae8e2975de94e8549613cyshang  for ( ; SortIndex < NumberOfSortedDriverBindingProtocols; SortIndex++) {
59928a00297189c323096aae8e2975de94e8549613cyshang    HighestVersion = SortedDriverBindingProtocols[SortIndex]->Version;
60028a00297189c323096aae8e2975de94e8549613cyshang    HighestIndex   = SortIndex;
60128a00297189c323096aae8e2975de94e8549613cyshang    for (Index = SortIndex + 1; Index < NumberOfSortedDriverBindingProtocols; Index++) {
60228a00297189c323096aae8e2975de94e8549613cyshang      if (SortedDriverBindingProtocols[Index]->Version > HighestVersion) {
60328a00297189c323096aae8e2975de94e8549613cyshang        HighestVersion = SortedDriverBindingProtocols[Index]->Version;
60428a00297189c323096aae8e2975de94e8549613cyshang        HighestIndex   = Index;
60528a00297189c323096aae8e2975de94e8549613cyshang      }
60628a00297189c323096aae8e2975de94e8549613cyshang    }
60728a00297189c323096aae8e2975de94e8549613cyshang    if (SortIndex != HighestIndex) {
60828a00297189c323096aae8e2975de94e8549613cyshang      DriverBinding = SortedDriverBindingProtocols[SortIndex];
60928a00297189c323096aae8e2975de94e8549613cyshang      SortedDriverBindingProtocols[SortIndex] = SortedDriverBindingProtocols[HighestIndex];
61028a00297189c323096aae8e2975de94e8549613cyshang      SortedDriverBindingProtocols[HighestIndex] = DriverBinding;
61128a00297189c323096aae8e2975de94e8549613cyshang    }
61228a00297189c323096aae8e2975de94e8549613cyshang  }
61328a00297189c323096aae8e2975de94e8549613cyshang
61428a00297189c323096aae8e2975de94e8549613cyshang  //
61528a00297189c323096aae8e2975de94e8549613cyshang  // Loop until no more drivers can be started on ControllerHandle
61628a00297189c323096aae8e2975de94e8549613cyshang  //
61728a00297189c323096aae8e2975de94e8549613cyshang  OneStarted = FALSE;
61828a00297189c323096aae8e2975de94e8549613cyshang  do {
61928a00297189c323096aae8e2975de94e8549613cyshang
62028a00297189c323096aae8e2975de94e8549613cyshang    //
62128a00297189c323096aae8e2975de94e8549613cyshang    // Loop through the sorted Driver Binding Protocol Instances in order, and see if
622022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang    // any of the Driver Binding Protocols support the controller specified by
62328a00297189c323096aae8e2975de94e8549613cyshang    // ControllerHandle.
62428a00297189c323096aae8e2975de94e8549613cyshang    //
62528a00297189c323096aae8e2975de94e8549613cyshang    DriverBinding = NULL;
62628a00297189c323096aae8e2975de94e8549613cyshang    DriverFound = FALSE;
62728a00297189c323096aae8e2975de94e8549613cyshang    for (Index = 0; (Index < NumberOfSortedDriverBindingProtocols) && !DriverFound; Index++) {
62828a00297189c323096aae8e2975de94e8549613cyshang      if (SortedDriverBindingProtocols[Index] != NULL) {
62928a00297189c323096aae8e2975de94e8549613cyshang        DriverBinding = SortedDriverBindingProtocols[Index];
630bc6b5892b007447b1024d98004681aa7a3305ddfqhuang        PERF_START (DriverBinding->DriverBindingHandle, "DB:Support:", NULL, 0);
63128a00297189c323096aae8e2975de94e8549613cyshang        Status = DriverBinding->Supported(
632022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                  DriverBinding,
63328a00297189c323096aae8e2975de94e8549613cyshang                                  ControllerHandle,
63428a00297189c323096aae8e2975de94e8549613cyshang                                  RemainingDevicePath
63528a00297189c323096aae8e2975de94e8549613cyshang                                  );
636bc6b5892b007447b1024d98004681aa7a3305ddfqhuang        PERF_END (DriverBinding->DriverBindingHandle, "DB:Support:", NULL, 0);
63728a00297189c323096aae8e2975de94e8549613cyshang        if (!EFI_ERROR (Status)) {
63828a00297189c323096aae8e2975de94e8549613cyshang          SortedDriverBindingProtocols[Index] = NULL;
63928a00297189c323096aae8e2975de94e8549613cyshang          DriverFound = TRUE;
64028a00297189c323096aae8e2975de94e8549613cyshang
64128a00297189c323096aae8e2975de94e8549613cyshang          //
64228a00297189c323096aae8e2975de94e8549613cyshang          // A driver was found that supports ControllerHandle, so attempt to start the driver
64328a00297189c323096aae8e2975de94e8549613cyshang          // on ControllerHandle.
64428a00297189c323096aae8e2975de94e8549613cyshang          //
645bc6b5892b007447b1024d98004681aa7a3305ddfqhuang          PERF_START (DriverBinding->DriverBindingHandle, "DB:Start:", NULL, 0);
64628a00297189c323096aae8e2975de94e8549613cyshang          Status = DriverBinding->Start (
647022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                    DriverBinding,
64828a00297189c323096aae8e2975de94e8549613cyshang                                    ControllerHandle,
64928a00297189c323096aae8e2975de94e8549613cyshang                                    RemainingDevicePath
65028a00297189c323096aae8e2975de94e8549613cyshang                                    );
651bc6b5892b007447b1024d98004681aa7a3305ddfqhuang          PERF_END (DriverBinding->DriverBindingHandle, "DB:Start:", NULL, 0);
65228a00297189c323096aae8e2975de94e8549613cyshang
65328a00297189c323096aae8e2975de94e8549613cyshang          if (!EFI_ERROR (Status)) {
65428a00297189c323096aae8e2975de94e8549613cyshang            //
65528a00297189c323096aae8e2975de94e8549613cyshang            // The driver was successfully started on ControllerHandle, so set a flag
65628a00297189c323096aae8e2975de94e8549613cyshang            //
65728a00297189c323096aae8e2975de94e8549613cyshang            OneStarted = TRUE;
65828a00297189c323096aae8e2975de94e8549613cyshang          }
65928a00297189c323096aae8e2975de94e8549613cyshang        }
66028a00297189c323096aae8e2975de94e8549613cyshang      }
66128a00297189c323096aae8e2975de94e8549613cyshang    }
66228a00297189c323096aae8e2975de94e8549613cyshang  } while (DriverFound);
66328a00297189c323096aae8e2975de94e8549613cyshang
66428a00297189c323096aae8e2975de94e8549613cyshang  //
66528a00297189c323096aae8e2975de94e8549613cyshang  // Free any buffers that were allocated with AllocatePool()
66628a00297189c323096aae8e2975de94e8549613cyshang  //
66728a00297189c323096aae8e2975de94e8549613cyshang  CoreFreePool (SortedDriverBindingProtocols);
66828a00297189c323096aae8e2975de94e8549613cyshang
66928a00297189c323096aae8e2975de94e8549613cyshang  //
67028a00297189c323096aae8e2975de94e8549613cyshang  // If at least one driver was started on ControllerHandle, then return EFI_SUCCESS.
67128a00297189c323096aae8e2975de94e8549613cyshang  //
67228a00297189c323096aae8e2975de94e8549613cyshang  if (OneStarted) {
67328a00297189c323096aae8e2975de94e8549613cyshang    return EFI_SUCCESS;
674022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  }
67528a00297189c323096aae8e2975de94e8549613cyshang
67628a00297189c323096aae8e2975de94e8549613cyshang  //
67728a00297189c323096aae8e2975de94e8549613cyshang  // If no drivers started and RemainingDevicePath is an End Device Path Node, then return EFI_SUCCESS
67828a00297189c323096aae8e2975de94e8549613cyshang  //
67928a00297189c323096aae8e2975de94e8549613cyshang  if (RemainingDevicePath != NULL) {
68028a00297189c323096aae8e2975de94e8549613cyshang    if (IsDevicePathEnd (RemainingDevicePath)) {
68128a00297189c323096aae8e2975de94e8549613cyshang      return EFI_SUCCESS;
68228a00297189c323096aae8e2975de94e8549613cyshang    }
683022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  }
68428a00297189c323096aae8e2975de94e8549613cyshang
68528a00297189c323096aae8e2975de94e8549613cyshang  //
68628a00297189c323096aae8e2975de94e8549613cyshang  // Otherwise, no drivers were started on ControllerHandle, so return EFI_NOT_FOUND
68728a00297189c323096aae8e2975de94e8549613cyshang  //
68828a00297189c323096aae8e2975de94e8549613cyshang  return EFI_NOT_FOUND;
68928a00297189c323096aae8e2975de94e8549613cyshang}
69028a00297189c323096aae8e2975de94e8549613cyshang
69128a00297189c323096aae8e2975de94e8549613cyshang
692162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
693162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang/**
694162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  Disonnects a controller from a driver
695162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
696022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  ControllerHandle                      ControllerHandle The handle of
697022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                                the controller from which
698022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                                driver(s)  are to be
699022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                                disconnected.
700022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  DriverImageHandle                     DriverImageHandle The driver to
701022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                                disconnect from ControllerHandle.
702022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  ChildHandle                           ChildHandle The handle of the
703022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                                child to destroy.
704022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang
705022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @retval EFI_SUCCESS                           One or more drivers were
706022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                                disconnected from the controller.
707022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @retval EFI_SUCCESS                           On entry, no drivers are managing
708022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                                ControllerHandle.
709022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @retval EFI_SUCCESS                           DriverImageHandle is not NULL,
710022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                                and on entry DriverImageHandle is
711022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                                not managing ControllerHandle.
712284ee2e829ab2453293b7dc4539727ad6c047163niruiyu  @retval EFI_INVALID_PARAMETER                 ControllerHandle is NULL.
713022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @retval EFI_INVALID_PARAMETER                 DriverImageHandle is not NULL,
714022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                                and it is not a valid EFI_HANDLE.
715022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @retval EFI_INVALID_PARAMETER                 ChildHandle is not NULL, and it
716022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                                is not a valid EFI_HANDLE.
717022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @retval EFI_OUT_OF_RESOURCES                  There are not enough resources
718022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                                available to disconnect any
719022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                                drivers from ControllerHandle.
720022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @retval EFI_DEVICE_ERROR                      The controller could not be
721022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                                disconnected because of a device
722162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang                                                error.
723162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
724162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang**/
725022c6d45ef78605c173023f53984e4dfaf7b11f4qhuangEFI_STATUS
72628a00297189c323096aae8e2975de94e8549613cyshangEFIAPI
72728a00297189c323096aae8e2975de94e8549613cyshangCoreDisconnectController (
72828a00297189c323096aae8e2975de94e8549613cyshang  IN  EFI_HANDLE  ControllerHandle,
72928a00297189c323096aae8e2975de94e8549613cyshang  IN  EFI_HANDLE  DriverImageHandle  OPTIONAL,
73028a00297189c323096aae8e2975de94e8549613cyshang  IN  EFI_HANDLE  ChildHandle        OPTIONAL
73128a00297189c323096aae8e2975de94e8549613cyshang  )
73228a00297189c323096aae8e2975de94e8549613cyshang{
73328a00297189c323096aae8e2975de94e8549613cyshang  EFI_STATUS                          Status;
73428a00297189c323096aae8e2975de94e8549613cyshang  IHANDLE                             *Handle;
73528a00297189c323096aae8e2975de94e8549613cyshang  EFI_HANDLE                          *DriverImageHandleBuffer;
73628a00297189c323096aae8e2975de94e8549613cyshang  EFI_HANDLE                          *ChildBuffer;
73728a00297189c323096aae8e2975de94e8549613cyshang  UINTN                               Index;
73828a00297189c323096aae8e2975de94e8549613cyshang  UINTN                               HandleIndex;
73928a00297189c323096aae8e2975de94e8549613cyshang  UINTN                               DriverImageHandleCount;
74028a00297189c323096aae8e2975de94e8549613cyshang  UINTN                               ChildrenToStop;
74128a00297189c323096aae8e2975de94e8549613cyshang  UINTN                               ChildBufferCount;
74228a00297189c323096aae8e2975de94e8549613cyshang  UINTN                               StopCount;
74328a00297189c323096aae8e2975de94e8549613cyshang  BOOLEAN                             Duplicate;
74428a00297189c323096aae8e2975de94e8549613cyshang  BOOLEAN                             ChildHandleValid;
74528a00297189c323096aae8e2975de94e8549613cyshang  BOOLEAN                             DriverImageHandleValid;
74628a00297189c323096aae8e2975de94e8549613cyshang  LIST_ENTRY                          *Link;
74728a00297189c323096aae8e2975de94e8549613cyshang  LIST_ENTRY                          *ProtLink;
74828a00297189c323096aae8e2975de94e8549613cyshang  OPEN_PROTOCOL_DATA                  *OpenData;
74928a00297189c323096aae8e2975de94e8549613cyshang  PROTOCOL_INTERFACE                  *Prot;
75028a00297189c323096aae8e2975de94e8549613cyshang  EFI_DRIVER_BINDING_PROTOCOL         *DriverBinding;
75128a00297189c323096aae8e2975de94e8549613cyshang
75228a00297189c323096aae8e2975de94e8549613cyshang  //
75328a00297189c323096aae8e2975de94e8549613cyshang  // Make sure ControllerHandle is valid
75428a00297189c323096aae8e2975de94e8549613cyshang  //
75528a00297189c323096aae8e2975de94e8549613cyshang  Status = CoreValidateHandle (ControllerHandle);
75628a00297189c323096aae8e2975de94e8549613cyshang  if (EFI_ERROR (Status)) {
75728a00297189c323096aae8e2975de94e8549613cyshang    return Status;
75828a00297189c323096aae8e2975de94e8549613cyshang  }
75928a00297189c323096aae8e2975de94e8549613cyshang
76028a00297189c323096aae8e2975de94e8549613cyshang  //
76128a00297189c323096aae8e2975de94e8549613cyshang  // Make sure ChildHandle is valid if it is not NULL
76228a00297189c323096aae8e2975de94e8549613cyshang  //
76328a00297189c323096aae8e2975de94e8549613cyshang  if (ChildHandle != NULL) {
76428a00297189c323096aae8e2975de94e8549613cyshang    Status = CoreValidateHandle (ChildHandle);
76528a00297189c323096aae8e2975de94e8549613cyshang    if (EFI_ERROR (Status)) {
76628a00297189c323096aae8e2975de94e8549613cyshang      return Status;
76728a00297189c323096aae8e2975de94e8549613cyshang    }
76828a00297189c323096aae8e2975de94e8549613cyshang  }
76928a00297189c323096aae8e2975de94e8549613cyshang
77028a00297189c323096aae8e2975de94e8549613cyshang  Handle = ControllerHandle;
77128a00297189c323096aae8e2975de94e8549613cyshang
77228a00297189c323096aae8e2975de94e8549613cyshang  //
77328a00297189c323096aae8e2975de94e8549613cyshang  // Get list of drivers that are currently managing ControllerHandle
77428a00297189c323096aae8e2975de94e8549613cyshang  //
77528a00297189c323096aae8e2975de94e8549613cyshang  DriverImageHandleBuffer = NULL;
776022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  DriverImageHandleCount  = 1;
777022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang
77828a00297189c323096aae8e2975de94e8549613cyshang  if (DriverImageHandle == NULL) {
77928a00297189c323096aae8e2975de94e8549613cyshang    //
78028a00297189c323096aae8e2975de94e8549613cyshang    // Look at each protocol interface for a match
78128a00297189c323096aae8e2975de94e8549613cyshang    //
78228a00297189c323096aae8e2975de94e8549613cyshang    DriverImageHandleCount = 0;
78328a00297189c323096aae8e2975de94e8549613cyshang
78428a00297189c323096aae8e2975de94e8549613cyshang    CoreAcquireProtocolLock ();
78528a00297189c323096aae8e2975de94e8549613cyshang    for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
78628a00297189c323096aae8e2975de94e8549613cyshang      Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
787022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang      for (ProtLink = Prot->OpenList.ForwardLink;
788022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang           ProtLink != &Prot->OpenList;
78928a00297189c323096aae8e2975de94e8549613cyshang           ProtLink = ProtLink->ForwardLink) {
79028a00297189c323096aae8e2975de94e8549613cyshang        OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
79128a00297189c323096aae8e2975de94e8549613cyshang        if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
79228a00297189c323096aae8e2975de94e8549613cyshang          DriverImageHandleCount++;
79328a00297189c323096aae8e2975de94e8549613cyshang        }
79428a00297189c323096aae8e2975de94e8549613cyshang      }
79528a00297189c323096aae8e2975de94e8549613cyshang    }
79628a00297189c323096aae8e2975de94e8549613cyshang    CoreReleaseProtocolLock ();
797022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang
79828a00297189c323096aae8e2975de94e8549613cyshang    //
79928a00297189c323096aae8e2975de94e8549613cyshang    // If there are no drivers managing this controller, then return EFI_SUCCESS
80028a00297189c323096aae8e2975de94e8549613cyshang    //
80128a00297189c323096aae8e2975de94e8549613cyshang    if (DriverImageHandleCount == 0) {
80228a00297189c323096aae8e2975de94e8549613cyshang      Status = EFI_SUCCESS;
80328a00297189c323096aae8e2975de94e8549613cyshang      goto Done;
80428a00297189c323096aae8e2975de94e8549613cyshang    }
80528a00297189c323096aae8e2975de94e8549613cyshang
8069c4ac31cca01b4a503c36616770ea3157bf3bb9eqhuang    DriverImageHandleBuffer = AllocatePool (sizeof (EFI_HANDLE) * DriverImageHandleCount);
80728a00297189c323096aae8e2975de94e8549613cyshang    if (DriverImageHandleBuffer == NULL) {
80828a00297189c323096aae8e2975de94e8549613cyshang      Status = EFI_OUT_OF_RESOURCES;
80928a00297189c323096aae8e2975de94e8549613cyshang      goto Done;
81028a00297189c323096aae8e2975de94e8549613cyshang    }
81128a00297189c323096aae8e2975de94e8549613cyshang
81228a00297189c323096aae8e2975de94e8549613cyshang    DriverImageHandleCount = 0;
81328a00297189c323096aae8e2975de94e8549613cyshang
81428a00297189c323096aae8e2975de94e8549613cyshang    CoreAcquireProtocolLock ();
81528a00297189c323096aae8e2975de94e8549613cyshang    for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
81628a00297189c323096aae8e2975de94e8549613cyshang      Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
817022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang      for (ProtLink = Prot->OpenList.ForwardLink;
818022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang           ProtLink != &Prot->OpenList;
81928a00297189c323096aae8e2975de94e8549613cyshang           ProtLink = ProtLink->ForwardLink) {
82028a00297189c323096aae8e2975de94e8549613cyshang        OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
82128a00297189c323096aae8e2975de94e8549613cyshang        if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
82228a00297189c323096aae8e2975de94e8549613cyshang          Duplicate = FALSE;
82328a00297189c323096aae8e2975de94e8549613cyshang          for (Index = 0; Index< DriverImageHandleCount; Index++) {
82428a00297189c323096aae8e2975de94e8549613cyshang            if (DriverImageHandleBuffer[Index] == OpenData->AgentHandle) {
82528a00297189c323096aae8e2975de94e8549613cyshang              Duplicate = TRUE;
82628a00297189c323096aae8e2975de94e8549613cyshang              break;
82728a00297189c323096aae8e2975de94e8549613cyshang            }
82828a00297189c323096aae8e2975de94e8549613cyshang          }
82928a00297189c323096aae8e2975de94e8549613cyshang          if (!Duplicate) {
83028a00297189c323096aae8e2975de94e8549613cyshang            DriverImageHandleBuffer[DriverImageHandleCount] = OpenData->AgentHandle;
83128a00297189c323096aae8e2975de94e8549613cyshang            DriverImageHandleCount++;
83228a00297189c323096aae8e2975de94e8549613cyshang          }
83328a00297189c323096aae8e2975de94e8549613cyshang        }
83428a00297189c323096aae8e2975de94e8549613cyshang      }
83528a00297189c323096aae8e2975de94e8549613cyshang    }
83628a00297189c323096aae8e2975de94e8549613cyshang    CoreReleaseProtocolLock ();
83728a00297189c323096aae8e2975de94e8549613cyshang  }
83828a00297189c323096aae8e2975de94e8549613cyshang
83928a00297189c323096aae8e2975de94e8549613cyshang  StopCount = 0;
84028a00297189c323096aae8e2975de94e8549613cyshang  for (HandleIndex = 0; HandleIndex < DriverImageHandleCount; HandleIndex++) {
84128a00297189c323096aae8e2975de94e8549613cyshang
84228a00297189c323096aae8e2975de94e8549613cyshang    if (DriverImageHandleBuffer != NULL) {
84328a00297189c323096aae8e2975de94e8549613cyshang      DriverImageHandle = DriverImageHandleBuffer[HandleIndex];
84428a00297189c323096aae8e2975de94e8549613cyshang    }
84528a00297189c323096aae8e2975de94e8549613cyshang
84628a00297189c323096aae8e2975de94e8549613cyshang    //
84728a00297189c323096aae8e2975de94e8549613cyshang    // Get the Driver Binding Protocol of the driver that is managing this controller
84828a00297189c323096aae8e2975de94e8549613cyshang    //
84928a00297189c323096aae8e2975de94e8549613cyshang    Status = CoreHandleProtocol (
850022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang               DriverImageHandle,
851022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang               &gEfiDriverBindingProtocolGuid,
85228a00297189c323096aae8e2975de94e8549613cyshang               (VOID **)&DriverBinding
85328a00297189c323096aae8e2975de94e8549613cyshang               );
854d2fbaaab17945b59ca66bcd2f72e26ba3361e1d0rsun    if (EFI_ERROR (Status) || DriverBinding == NULL) {
85528a00297189c323096aae8e2975de94e8549613cyshang      Status = EFI_INVALID_PARAMETER;
85628a00297189c323096aae8e2975de94e8549613cyshang      goto Done;
85728a00297189c323096aae8e2975de94e8549613cyshang    }
85828a00297189c323096aae8e2975de94e8549613cyshang
85928a00297189c323096aae8e2975de94e8549613cyshang    //
86028a00297189c323096aae8e2975de94e8549613cyshang    // Look at each protocol interface for a match
86128a00297189c323096aae8e2975de94e8549613cyshang    //
86228a00297189c323096aae8e2975de94e8549613cyshang    DriverImageHandleValid = FALSE;
86328a00297189c323096aae8e2975de94e8549613cyshang    ChildBufferCount = 0;
86428a00297189c323096aae8e2975de94e8549613cyshang
86528a00297189c323096aae8e2975de94e8549613cyshang    CoreAcquireProtocolLock ();
86628a00297189c323096aae8e2975de94e8549613cyshang    for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
86728a00297189c323096aae8e2975de94e8549613cyshang      Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
868022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang      for (ProtLink = Prot->OpenList.ForwardLink;
869022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang           ProtLink != &Prot->OpenList;
87028a00297189c323096aae8e2975de94e8549613cyshang           ProtLink = ProtLink->ForwardLink) {
87128a00297189c323096aae8e2975de94e8549613cyshang        OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
87228a00297189c323096aae8e2975de94e8549613cyshang        if (OpenData->AgentHandle == DriverImageHandle) {
87328a00297189c323096aae8e2975de94e8549613cyshang          if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
87428a00297189c323096aae8e2975de94e8549613cyshang            ChildBufferCount++;
875022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang          }
87628a00297189c323096aae8e2975de94e8549613cyshang          if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
87728a00297189c323096aae8e2975de94e8549613cyshang            DriverImageHandleValid = TRUE;
87828a00297189c323096aae8e2975de94e8549613cyshang          }
87928a00297189c323096aae8e2975de94e8549613cyshang        }
88028a00297189c323096aae8e2975de94e8549613cyshang      }
88128a00297189c323096aae8e2975de94e8549613cyshang    }
88228a00297189c323096aae8e2975de94e8549613cyshang    CoreReleaseProtocolLock ();
88328a00297189c323096aae8e2975de94e8549613cyshang
88428a00297189c323096aae8e2975de94e8549613cyshang    if (DriverImageHandleValid) {
88528a00297189c323096aae8e2975de94e8549613cyshang      ChildHandleValid = FALSE;
88628a00297189c323096aae8e2975de94e8549613cyshang      ChildBuffer = NULL;
88728a00297189c323096aae8e2975de94e8549613cyshang      if (ChildBufferCount != 0) {
8889c4ac31cca01b4a503c36616770ea3157bf3bb9eqhuang        ChildBuffer = AllocatePool (sizeof (EFI_HANDLE) * ChildBufferCount);
88928a00297189c323096aae8e2975de94e8549613cyshang        if (ChildBuffer == NULL) {
89028a00297189c323096aae8e2975de94e8549613cyshang          Status = EFI_OUT_OF_RESOURCES;
89128a00297189c323096aae8e2975de94e8549613cyshang          goto Done;
89228a00297189c323096aae8e2975de94e8549613cyshang        }
89328a00297189c323096aae8e2975de94e8549613cyshang
89428a00297189c323096aae8e2975de94e8549613cyshang        ChildBufferCount = 0;
89528a00297189c323096aae8e2975de94e8549613cyshang
89628a00297189c323096aae8e2975de94e8549613cyshang        CoreAcquireProtocolLock ();
89728a00297189c323096aae8e2975de94e8549613cyshang        for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
89828a00297189c323096aae8e2975de94e8549613cyshang          Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
899022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang          for (ProtLink = Prot->OpenList.ForwardLink;
900022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang               ProtLink != &Prot->OpenList;
90128a00297189c323096aae8e2975de94e8549613cyshang               ProtLink = ProtLink->ForwardLink) {
90228a00297189c323096aae8e2975de94e8549613cyshang            OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
90328a00297189c323096aae8e2975de94e8549613cyshang            if ((OpenData->AgentHandle == DriverImageHandle) &&
90428a00297189c323096aae8e2975de94e8549613cyshang                ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0)) {
90528a00297189c323096aae8e2975de94e8549613cyshang              Duplicate = FALSE;
90628a00297189c323096aae8e2975de94e8549613cyshang              for (Index = 0; Index < ChildBufferCount; Index++) {
90728a00297189c323096aae8e2975de94e8549613cyshang                if (ChildBuffer[Index] == OpenData->ControllerHandle) {
90828a00297189c323096aae8e2975de94e8549613cyshang                  Duplicate = TRUE;
90928a00297189c323096aae8e2975de94e8549613cyshang                  break;
91028a00297189c323096aae8e2975de94e8549613cyshang                }
91128a00297189c323096aae8e2975de94e8549613cyshang              }
91228a00297189c323096aae8e2975de94e8549613cyshang              if (!Duplicate) {
91328a00297189c323096aae8e2975de94e8549613cyshang                ChildBuffer[ChildBufferCount] = OpenData->ControllerHandle;
91428a00297189c323096aae8e2975de94e8549613cyshang                if (ChildHandle == ChildBuffer[ChildBufferCount]) {
91528a00297189c323096aae8e2975de94e8549613cyshang                  ChildHandleValid = TRUE;
91628a00297189c323096aae8e2975de94e8549613cyshang                }
91728a00297189c323096aae8e2975de94e8549613cyshang                ChildBufferCount++;
91828a00297189c323096aae8e2975de94e8549613cyshang              }
91928a00297189c323096aae8e2975de94e8549613cyshang            }
92028a00297189c323096aae8e2975de94e8549613cyshang          }
92128a00297189c323096aae8e2975de94e8549613cyshang        }
92228a00297189c323096aae8e2975de94e8549613cyshang        CoreReleaseProtocolLock ();
92328a00297189c323096aae8e2975de94e8549613cyshang      }
92428a00297189c323096aae8e2975de94e8549613cyshang
92528a00297189c323096aae8e2975de94e8549613cyshang      if (ChildHandle == NULL || ChildHandleValid) {
92628a00297189c323096aae8e2975de94e8549613cyshang        ChildrenToStop = 0;
92728a00297189c323096aae8e2975de94e8549613cyshang        Status = EFI_SUCCESS;
92828a00297189c323096aae8e2975de94e8549613cyshang        if (ChildBufferCount > 0) {
92928a00297189c323096aae8e2975de94e8549613cyshang          if (ChildHandle != NULL) {
93028a00297189c323096aae8e2975de94e8549613cyshang            ChildrenToStop = 1;
93128a00297189c323096aae8e2975de94e8549613cyshang            Status = DriverBinding->Stop (DriverBinding, ControllerHandle, ChildrenToStop, &ChildHandle);
93228a00297189c323096aae8e2975de94e8549613cyshang          } else {
93328a00297189c323096aae8e2975de94e8549613cyshang            ChildrenToStop = ChildBufferCount;
93428a00297189c323096aae8e2975de94e8549613cyshang            Status = DriverBinding->Stop (DriverBinding, ControllerHandle, ChildrenToStop, ChildBuffer);
93528a00297189c323096aae8e2975de94e8549613cyshang          }
93628a00297189c323096aae8e2975de94e8549613cyshang        }
93728a00297189c323096aae8e2975de94e8549613cyshang        if (!EFI_ERROR (Status) && ((ChildHandle == NULL) || (ChildBufferCount == ChildrenToStop))) {
93828a00297189c323096aae8e2975de94e8549613cyshang          Status = DriverBinding->Stop (DriverBinding, ControllerHandle, 0, NULL);
93928a00297189c323096aae8e2975de94e8549613cyshang        }
94028a00297189c323096aae8e2975de94e8549613cyshang        if (!EFI_ERROR (Status)) {
94128a00297189c323096aae8e2975de94e8549613cyshang          StopCount++;
94228a00297189c323096aae8e2975de94e8549613cyshang        }
94328a00297189c323096aae8e2975de94e8549613cyshang      }
94428a00297189c323096aae8e2975de94e8549613cyshang
94528a00297189c323096aae8e2975de94e8549613cyshang      if (ChildBuffer != NULL) {
94628a00297189c323096aae8e2975de94e8549613cyshang        CoreFreePool (ChildBuffer);
94728a00297189c323096aae8e2975de94e8549613cyshang      }
94828a00297189c323096aae8e2975de94e8549613cyshang    }
94928a00297189c323096aae8e2975de94e8549613cyshang  }
95028a00297189c323096aae8e2975de94e8549613cyshang
95128a00297189c323096aae8e2975de94e8549613cyshang  if (StopCount > 0) {
95228a00297189c323096aae8e2975de94e8549613cyshang    Status = EFI_SUCCESS;
95328a00297189c323096aae8e2975de94e8549613cyshang  } else {
95428a00297189c323096aae8e2975de94e8549613cyshang    Status = EFI_NOT_FOUND;
95528a00297189c323096aae8e2975de94e8549613cyshang  }
956022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang
957022c6d45ef78605c173023f53984e4dfaf7b11f4qhuangDone:
95828a00297189c323096aae8e2975de94e8549613cyshang
95928a00297189c323096aae8e2975de94e8549613cyshang  if (DriverImageHandleBuffer != NULL) {
96028a00297189c323096aae8e2975de94e8549613cyshang    CoreFreePool (DriverImageHandleBuffer);
96128a00297189c323096aae8e2975de94e8549613cyshang  }
96228a00297189c323096aae8e2975de94e8549613cyshang
96328a00297189c323096aae8e2975de94e8549613cyshang  return Status;
96428a00297189c323096aae8e2975de94e8549613cyshang}
965