mirror of
				https://github.com/acidanthera/audk.git
				synced 2025-11-04 05:25:45 +01:00 
			
		
		
		
	git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@597 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			849 lines
		
	
	
		
			28 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			849 lines
		
	
	
		
			28 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*++
 | 
						|
 | 
						|
Copyright (c) 2006, Intel Corporation                                                         
 | 
						|
All rights reserved. This program and the accompanying materials                          
 | 
						|
are licensed and made available under the terms and conditions of the BSD License         
 | 
						|
which accompanies this distribution.  The full text of the license may be found at        
 | 
						|
http://opensource.org/licenses/bsd-license.php                                            
 | 
						|
                                                                                          
 | 
						|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     
 | 
						|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             
 | 
						|
 | 
						|
Module Name:
 | 
						|
 | 
						|
    DriverSupport.c
 | 
						|
    
 | 
						|
Abstract:
 | 
						|
 | 
						|
    EFI Driver Support Protocol
 | 
						|
 | 
						|
Revision History
 | 
						|
 | 
						|
--*/
 | 
						|
 | 
						|
#include <DxeMain.h>
 | 
						|
 | 
						|
 | 
						|
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
GetHandleFromDriverBinding (
 | 
						|
  IN EFI_DRIVER_BINDING_PROTOCOL           *DriverBindingNeed,
 | 
						|
  OUT  EFI_HANDLE                          *Handle 
 | 
						|
  );
 | 
						|
 | 
						|
 | 
						|
//
 | 
						|
// Driver Support Function Prototypes
 | 
						|
//
 | 
						|
STATIC
 | 
						|
EFI_STATUS 
 | 
						|
CoreConnectSingleController (
 | 
						|
  IN  EFI_HANDLE                ControllerHandle,
 | 
						|
  IN  EFI_HANDLE                *DriverImageHandle    OPTIONAL,
 | 
						|
  IN  EFI_DEVICE_PATH_PROTOCOL  *RemainingDevicePath  OPTIONAL
 | 
						|
  );
 | 
						|
 | 
						|
//
 | 
						|
// Driver Support Functions
 | 
						|
//
 | 
						|
 | 
						|
 | 
						|
EFI_STATUS 
 | 
						|
EFIAPI
 | 
						|
CoreConnectController (
 | 
						|
  IN  EFI_HANDLE                ControllerHandle,
 | 
						|
  IN  EFI_HANDLE                *DriverImageHandle    OPTIONAL,
 | 
						|
  IN  EFI_DEVICE_PATH_PROTOCOL  *RemainingDevicePath  OPTIONAL,
 | 
						|
  IN  BOOLEAN                   Recursive
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Connects one or more drivers to a controller.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  ControllerHandle            - Handle of the controller to be connected.
 | 
						|
 | 
						|
  DriverImageHandle           - DriverImageHandle A pointer to an ordered list of driver image handles.
 | 
						|
 | 
						|
  RemainingDevicePath         - RemainingDevicePath A pointer to the device path that specifies a child of the
 | 
						|
                                controller specified by ControllerHandle.
 | 
						|
    
 | 
						|
  Recursive                   - Whether the function would be called recursively or not.
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  Status code.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_STATUS                           Status;
 | 
						|
  EFI_STATUS                           ReturnStatus;
 | 
						|
  IHANDLE                              *Handle;
 | 
						|
  PROTOCOL_INTERFACE                   *Prot;
 | 
						|
  LIST_ENTRY                           *Link;
 | 
						|
  LIST_ENTRY                           *ProtLink;
 | 
						|
  OPEN_PROTOCOL_DATA                   *OpenData;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL             *AlignedRemainingDevicePath;
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Make sure ControllerHandle is valid
 | 
						|
  //
 | 
						|
  Status = CoreValidateHandle (ControllerHandle);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  Handle = ControllerHandle;
 | 
						|
 | 
						|
  //
 | 
						|
  // Connect all drivers to ControllerHandle 
 | 
						|
  //
 | 
						|
  AlignedRemainingDevicePath = NULL;
 | 
						|
  if (RemainingDevicePath != NULL) {
 | 
						|
    AlignedRemainingDevicePath = CoreDuplicateDevicePath (RemainingDevicePath);
 | 
						|
  }
 | 
						|
  ReturnStatus = CoreConnectSingleController (
 | 
						|
                   ControllerHandle,
 | 
						|
                   DriverImageHandle,
 | 
						|
                   AlignedRemainingDevicePath
 | 
						|
                   );
 | 
						|
  if (AlignedRemainingDevicePath != NULL) {
 | 
						|
    CoreFreePool (AlignedRemainingDevicePath);
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // If not recursive, then just return after connecting drivers to ControllerHandle
 | 
						|
  //
 | 
						|
  if (!Recursive) {
 | 
						|
    return ReturnStatus;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // If recursive, then connect all drivers to all of ControllerHandle's children
 | 
						|
  //
 | 
						|
  CoreAcquireProtocolLock ();
 | 
						|
  for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
 | 
						|
    Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
 | 
						|
    for (ProtLink = Prot->OpenList.ForwardLink; 
 | 
						|
           ProtLink != &Prot->OpenList; 
 | 
						|
           ProtLink = ProtLink->ForwardLink) {
 | 
						|
        OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
 | 
						|
        if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
 | 
						|
          CoreReleaseProtocolLock ();
 | 
						|
          Status = CoreConnectController (
 | 
						|
                          OpenData->ControllerHandle,
 | 
						|
                          NULL,
 | 
						|
                          NULL,
 | 
						|
                          TRUE
 | 
						|
                          ); 
 | 
						|
          CoreAcquireProtocolLock ();
 | 
						|
        }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  CoreReleaseProtocolLock ();
 | 
						|
  
 | 
						|
  return ReturnStatus;
 | 
						|
}
 | 
						|
 | 
						|
VOID
 | 
						|
AddSortedDriverBindingProtocol (
 | 
						|
  IN      EFI_HANDLE                   DriverBindingHandle,
 | 
						|
  IN OUT  UINTN                        *NumberOfSortedDriverBindingProtocols, 
 | 
						|
  IN OUT  EFI_DRIVER_BINDING_PROTOCOL  **SortedDriverBindingProtocols,
 | 
						|
  IN      UINTN                        DriverBindingHandleCount,
 | 
						|
  IN OUT  EFI_HANDLE                   *DriverBindingHandleBuffer
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Add Driver Binding Protocols from Context Driver Image Handles to sorted 
 | 
						|
   Driver Binding Protocol list.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  DriverBindingHandle - Handle of the driver binding protocol.
 | 
						|
 | 
						|
  NumberOfSortedDriverBindingProtocols - Number Of sorted driver binding protocols
 | 
						|
 | 
						|
  SortedDriverBindingProtocols - The sorted protocol list.                        
 | 
						|
    
 | 
						|
  DriverBindingHandleCount - Driver Binding Handle Count.
 | 
						|
 | 
						|
  DriverBindingHandleBuffer - The buffer of driver binding protocol to be modified.
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  None.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_STATUS                   Status;
 | 
						|
  EFI_DRIVER_BINDING_PROTOCOL  *DriverBinding;
 | 
						|
  UINTN                        Index;
 | 
						|
 | 
						|
  //
 | 
						|
  // Make sure the DriverBindingHandle is valid
 | 
						|
  //
 | 
						|
  Status = CoreValidateHandle (DriverBindingHandle);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Retrieve the Driver Binding Protocol from DriverBindingHandle
 | 
						|
  //
 | 
						|
  Status = CoreHandleProtocol(
 | 
						|
             DriverBindingHandle,
 | 
						|
             &gEfiDriverBindingProtocolGuid,
 | 
						|
             (VOID **)&DriverBinding
 | 
						|
             );
 | 
						|
  //
 | 
						|
  // If DriverBindingHandle does not support the Driver Binding Protocol then return
 | 
						|
  //
 | 
						|
  if (EFI_ERROR (Status) || DriverBinding == NULL) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // See if DriverBinding is already in the sorted list
 | 
						|
  //
 | 
						|
  for (Index = 0; Index < *NumberOfSortedDriverBindingProtocols; Index++) {
 | 
						|
    if (DriverBinding == SortedDriverBindingProtocols[Index]) {
 | 
						|
      return;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Add DriverBinding to the end of the list
 | 
						|
  //
 | 
						|
  SortedDriverBindingProtocols[*NumberOfSortedDriverBindingProtocols] = DriverBinding;
 | 
						|
  *NumberOfSortedDriverBindingProtocols = *NumberOfSortedDriverBindingProtocols + 1;
 | 
						|
 | 
						|
  //
 | 
						|
  // Mark the cooresponding handle in DriverBindingHandleBuffer as used
 | 
						|
  //
 | 
						|
  for (Index = 0; Index < DriverBindingHandleCount; Index++) {
 | 
						|
    if (DriverBindingHandleBuffer[Index] == DriverBindingHandle) {
 | 
						|
      DriverBindingHandleBuffer[Index] = NULL;
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 
 | 
						|
STATIC
 | 
						|
EFI_STATUS 
 | 
						|
CoreConnectSingleController (
 | 
						|
  IN  EFI_HANDLE                ControllerHandle,
 | 
						|
  IN  EFI_HANDLE                *ContextDriverImageHandles OPTIONAL,
 | 
						|
  IN  EFI_DEVICE_PATH_PROTOCOL  *RemainingDevicePath       OPTIONAL     
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Connects a controller to a driver.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  ControllerHandle            - Handle of the controller to be connected.
 | 
						|
  ContextDriverImageHandles   - DriverImageHandle A pointer to an ordered list of driver image handles.
 | 
						|
  RemainingDevicePath         - RemainingDevicePath A pointer to the device path that specifies a child 
 | 
						|
                                of the controller specified by ControllerHandle.
 | 
						|
    
 | 
						|
Returns:
 | 
						|
 | 
						|
  EFI_SUCCESS           - One or more drivers were connected to ControllerHandle.
 | 
						|
  EFI_OUT_OF_RESOURCES  - No enough system resources to complete the request.
 | 
						|
  EFI_NOT_FOUND         - No drivers were connected to ControllerHandle.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_STATUS                                 Status;
 | 
						|
  UINTN                                      Index;
 | 
						|
  EFI_HANDLE                                 DriverImageHandle;
 | 
						|
  UINTN                                      PlatformDriverOverrideHandleCount;
 | 
						|
  EFI_HANDLE                                 *PlatformDriverOverrideHandleBuffer;
 | 
						|
  EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL      *PlatformDriverOverride;
 | 
						|
  EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL  *BusSpecificDriverOverride;
 | 
						|
  UINTN                                      DriverBindingHandleCount;
 | 
						|
  EFI_HANDLE                                 *DriverBindingHandleBuffer;
 | 
						|
  EFI_DRIVER_BINDING_PROTOCOL                *DriverBinding;
 | 
						|
  UINTN                                      NumberOfSortedDriverBindingProtocols;
 | 
						|
  EFI_DRIVER_BINDING_PROTOCOL                **SortedDriverBindingProtocols;
 | 
						|
  UINT32                                     HighestVersion;
 | 
						|
  UINTN                                      HighestIndex;
 | 
						|
  UINTN                                      SortIndex;
 | 
						|
  BOOLEAN                                    OneStarted;
 | 
						|
  BOOLEAN                                    DriverFound;
 | 
						|
  EFI_HANDLE                                 DriverBindingHandle;
 | 
						|
 | 
						|
  //
 | 
						|
  // DriverBindingHandle is used for performance measurement, initialize it here just in case.
 | 
						|
  //
 | 
						|
  DriverBindingHandle                   = NULL;
 | 
						|
  //
 | 
						|
  // Initialize local variables
 | 
						|
  //
 | 
						|
  DriverBindingHandleCount              = 0;
 | 
						|
  DriverBindingHandleBuffer             = NULL;
 | 
						|
  PlatformDriverOverrideHandleCount     = 0;
 | 
						|
  PlatformDriverOverrideHandleBuffer    = NULL;
 | 
						|
  NumberOfSortedDriverBindingProtocols  = 0;
 | 
						|
  SortedDriverBindingProtocols          = NULL;
 | 
						|
 | 
						|
  //
 | 
						|
  // Get list of all Driver Binding Protocol Instances
 | 
						|
  //
 | 
						|
  Status = CoreLocateHandleBuffer (
 | 
						|
             ByProtocol,   
 | 
						|
             &gEfiDriverBindingProtocolGuid,  
 | 
						|
             NULL,
 | 
						|
             &DriverBindingHandleCount, 
 | 
						|
             &DriverBindingHandleBuffer
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status) || (DriverBindingHandleCount == 0)) {
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Allocate a duplicate array for the sorted Driver Binding Protocol Instances
 | 
						|
  //
 | 
						|
  SortedDriverBindingProtocols = CoreAllocateBootServicesPool (sizeof (VOID *) * DriverBindingHandleCount);
 | 
						|
  if (SortedDriverBindingProtocols == NULL) {
 | 
						|
    CoreFreePool (DriverBindingHandleBuffer);
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Add Driver Binding Protocols from Context Driver Image Handles first
 | 
						|
  //
 | 
						|
  if (ContextDriverImageHandles != NULL) {
 | 
						|
    for (Index = 0; ContextDriverImageHandles[Index] != NULL; Index++) {
 | 
						|
      AddSortedDriverBindingProtocol (
 | 
						|
        ContextDriverImageHandles[Index],
 | 
						|
        &NumberOfSortedDriverBindingProtocols, 
 | 
						|
        SortedDriverBindingProtocols,
 | 
						|
        DriverBindingHandleCount,
 | 
						|
        DriverBindingHandleBuffer
 | 
						|
        );
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Add the Platform Driver Override Protocol drivers for ControllerHandle next
 | 
						|
  //
 | 
						|
  Status = CoreLocateProtocol (
 | 
						|
             &gEfiPlatformDriverOverrideProtocolGuid, 
 | 
						|
             NULL, 
 | 
						|
             (VOID **)&PlatformDriverOverride
 | 
						|
             );
 | 
						|
  if (!EFI_ERROR (Status) && (PlatformDriverOverride != NULL)) {
 | 
						|
    DriverImageHandle = NULL;
 | 
						|
    do {
 | 
						|
      Status = PlatformDriverOverride->GetDriver (
 | 
						|
                                         PlatformDriverOverride,
 | 
						|
                                         ControllerHandle,
 | 
						|
                                         &DriverImageHandle
 | 
						|
                                         );
 | 
						|
      if (!EFI_ERROR (Status)) {
 | 
						|
        AddSortedDriverBindingProtocol (
 | 
						|
          DriverImageHandle,
 | 
						|
          &NumberOfSortedDriverBindingProtocols, 
 | 
						|
          SortedDriverBindingProtocols,
 | 
						|
          DriverBindingHandleCount,
 | 
						|
          DriverBindingHandleBuffer
 | 
						|
          );
 | 
						|
      }
 | 
						|
    } while (!EFI_ERROR (Status));
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Get the Bus Specific Driver Override Protocol instance on the Controller Handle
 | 
						|
  //
 | 
						|
  Status = CoreHandleProtocol(
 | 
						|
             ControllerHandle,  
 | 
						|
             &gEfiBusSpecificDriverOverrideProtocolGuid, 
 | 
						|
             (VOID **)&BusSpecificDriverOverride
 | 
						|
             );
 | 
						|
  if (!EFI_ERROR (Status) && (BusSpecificDriverOverride != NULL)) {
 | 
						|
    DriverImageHandle = NULL;
 | 
						|
    do {
 | 
						|
      Status = BusSpecificDriverOverride->GetDriver (
 | 
						|
                                            BusSpecificDriverOverride,
 | 
						|
                                            &DriverImageHandle
 | 
						|
                                            );
 | 
						|
      if (!EFI_ERROR (Status)) {
 | 
						|
        AddSortedDriverBindingProtocol (
 | 
						|
          DriverImageHandle,
 | 
						|
          &NumberOfSortedDriverBindingProtocols, 
 | 
						|
          SortedDriverBindingProtocols,
 | 
						|
          DriverBindingHandleCount,
 | 
						|
          DriverBindingHandleBuffer
 | 
						|
          );
 | 
						|
      }
 | 
						|
    } while (!EFI_ERROR (Status));
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Then add all the remaining Driver Binding Protocols
 | 
						|
  //
 | 
						|
  SortIndex = NumberOfSortedDriverBindingProtocols;
 | 
						|
  for (Index = 0; Index < DriverBindingHandleCount; Index++) {
 | 
						|
    AddSortedDriverBindingProtocol (
 | 
						|
      DriverBindingHandleBuffer[Index],
 | 
						|
      &NumberOfSortedDriverBindingProtocols, 
 | 
						|
      SortedDriverBindingProtocols,
 | 
						|
      DriverBindingHandleCount,
 | 
						|
      DriverBindingHandleBuffer
 | 
						|
      );
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Free the Driver Binding Handle Buffer
 | 
						|
  //
 | 
						|
  CoreFreePool (DriverBindingHandleBuffer);
 | 
						|
 | 
						|
  //
 | 
						|
  // Sort the remaining DriverBinding Protocol based on their Version field from
 | 
						|
  // highest to lowest.
 | 
						|
  //
 | 
						|
  for ( ; SortIndex < NumberOfSortedDriverBindingProtocols; SortIndex++) {
 | 
						|
    HighestVersion = SortedDriverBindingProtocols[SortIndex]->Version;
 | 
						|
    HighestIndex   = SortIndex;
 | 
						|
    for (Index = SortIndex + 1; Index < NumberOfSortedDriverBindingProtocols; Index++) {
 | 
						|
      if (SortedDriverBindingProtocols[Index]->Version > HighestVersion) {
 | 
						|
        HighestVersion = SortedDriverBindingProtocols[Index]->Version;
 | 
						|
        HighestIndex   = Index;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    if (SortIndex != HighestIndex) {
 | 
						|
      DriverBinding = SortedDriverBindingProtocols[SortIndex];
 | 
						|
      SortedDriverBindingProtocols[SortIndex] = SortedDriverBindingProtocols[HighestIndex];
 | 
						|
      SortedDriverBindingProtocols[HighestIndex] = DriverBinding;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Loop until no more drivers can be started on ControllerHandle
 | 
						|
  //
 | 
						|
  OneStarted = FALSE;
 | 
						|
  do {
 | 
						|
 | 
						|
    //
 | 
						|
    // Loop through the sorted Driver Binding Protocol Instances in order, and see if
 | 
						|
    // any of the Driver Binding Protocols support the controller specified by 
 | 
						|
    // ControllerHandle.
 | 
						|
    //
 | 
						|
    DriverBinding = NULL;
 | 
						|
    DriverFound = FALSE;
 | 
						|
    for (Index = 0; (Index < NumberOfSortedDriverBindingProtocols) && !DriverFound; Index++) {
 | 
						|
      if (SortedDriverBindingProtocols[Index] != NULL) {
 | 
						|
        DriverBinding = SortedDriverBindingProtocols[Index];
 | 
						|
        Status = DriverBinding->Supported(
 | 
						|
                                  DriverBinding, 
 | 
						|
                                  ControllerHandle,
 | 
						|
                                  RemainingDevicePath
 | 
						|
                                  );
 | 
						|
        if (!EFI_ERROR (Status)) {
 | 
						|
          SortedDriverBindingProtocols[Index] = NULL;
 | 
						|
          DriverFound = TRUE;
 | 
						|
 | 
						|
          //
 | 
						|
          // A driver was found that supports ControllerHandle, so attempt to start the driver
 | 
						|
          // on ControllerHandle.
 | 
						|
          //
 | 
						|
          PERF_CODE_BEGIN ();
 | 
						|
          GetHandleFromDriverBinding (DriverBinding, &DriverBindingHandle);
 | 
						|
          PERF_CODE_END ();
 | 
						|
 | 
						|
          PERF_START (DriverBindingHandle, DRIVERBINDING_START_TOK, NULL, 0);
 | 
						|
          Status = DriverBinding->Start (
 | 
						|
                                    DriverBinding, 
 | 
						|
                                    ControllerHandle,
 | 
						|
                                    RemainingDevicePath
 | 
						|
                                    );
 | 
						|
          PERF_END (DriverBindingHandle, DRIVERBINDING_START_TOK, NULL, 0);
 | 
						|
 | 
						|
          if (!EFI_ERROR (Status)) {
 | 
						|
            //
 | 
						|
            // The driver was successfully started on ControllerHandle, so set a flag
 | 
						|
            //
 | 
						|
            OneStarted = TRUE;
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  } while (DriverFound);
 | 
						|
 | 
						|
  //
 | 
						|
  // Free any buffers that were allocated with AllocatePool()
 | 
						|
  //
 | 
						|
  CoreFreePool (SortedDriverBindingProtocols);
 | 
						|
 | 
						|
  //
 | 
						|
  // If at least one driver was started on ControllerHandle, then return EFI_SUCCESS.
 | 
						|
  //
 | 
						|
  if (OneStarted) {
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  } 
 | 
						|
 | 
						|
  //
 | 
						|
  // If no drivers started and RemainingDevicePath is an End Device Path Node, then return EFI_SUCCESS
 | 
						|
  //
 | 
						|
  if (RemainingDevicePath != NULL) {
 | 
						|
    if (IsDevicePathEnd (RemainingDevicePath)) {
 | 
						|
      return EFI_SUCCESS;
 | 
						|
    }
 | 
						|
  } 
 | 
						|
 | 
						|
  //
 | 
						|
  // Otherwise, no drivers were started on ControllerHandle, so return EFI_NOT_FOUND
 | 
						|
  //
 | 
						|
  return EFI_NOT_FOUND;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
EFI_STATUS 
 | 
						|
EFIAPI
 | 
						|
CoreDisconnectController (
 | 
						|
  IN  EFI_HANDLE  ControllerHandle,
 | 
						|
  IN  EFI_HANDLE  DriverImageHandle  OPTIONAL,
 | 
						|
  IN  EFI_HANDLE  ChildHandle        OPTIONAL
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Disonnects a controller from a driver
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  ControllerHandle  - ControllerHandle The handle of the controller from which driver(s) 
 | 
						|
                        are to be disconnected.
 | 
						|
  DriverImageHandle - DriverImageHandle The driver to disconnect from ControllerHandle.
 | 
						|
  ChildHandle       - ChildHandle The handle of the child to destroy.
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  EFI_SUCCESS           -  One or more drivers were disconnected from the controller.
 | 
						|
  EFI_SUCCESS           -  On entry, no drivers are managing ControllerHandle.
 | 
						|
  EFI_SUCCESS           -  DriverImageHandle is not NULL, and on entry DriverImageHandle is not managing ControllerHandle.
 | 
						|
  EFI_INVALID_PARAMETER -  ControllerHandle is not a valid EFI_HANDLE.
 | 
						|
  EFI_INVALID_PARAMETER -  DriverImageHandle is not NULL, and it is not a valid EFI_HANDLE.
 | 
						|
  EFI_INVALID_PARAMETER -  ChildHandle is not NULL, and it is not a valid EFI_HANDLE.
 | 
						|
  EFI_OUT_OF_RESOURCES  -  There are not enough resources available to disconnect any drivers from ControllerHandle.
 | 
						|
  EFI_DEVICE_ERROR      -  The controller could not be disconnected because of a device error.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_STATUS                          Status;
 | 
						|
  IHANDLE                             *Handle;
 | 
						|
  EFI_HANDLE                          *DriverImageHandleBuffer;
 | 
						|
  EFI_HANDLE                          *ChildBuffer;
 | 
						|
  UINTN                               Index;
 | 
						|
  UINTN                               HandleIndex;
 | 
						|
  UINTN                               DriverImageHandleCount;
 | 
						|
  UINTN                               ChildrenToStop;
 | 
						|
  UINTN                               ChildBufferCount;
 | 
						|
  UINTN                               StopCount;
 | 
						|
  BOOLEAN                             Duplicate;
 | 
						|
  BOOLEAN                             ChildHandleValid;
 | 
						|
  BOOLEAN                             DriverImageHandleValid;
 | 
						|
  LIST_ENTRY                          *Link;
 | 
						|
  LIST_ENTRY                          *ProtLink;
 | 
						|
  OPEN_PROTOCOL_DATA                  *OpenData;
 | 
						|
  PROTOCOL_INTERFACE                  *Prot;
 | 
						|
  EFI_DRIVER_BINDING_PROTOCOL         *DriverBinding;
 | 
						|
 | 
						|
  //
 | 
						|
  // Make sure ControllerHandle is valid
 | 
						|
  //
 | 
						|
  Status = CoreValidateHandle (ControllerHandle);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Make sure ChildHandle is valid if it is not NULL
 | 
						|
  //
 | 
						|
  if (ChildHandle != NULL) {
 | 
						|
    Status = CoreValidateHandle (ChildHandle);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  Handle = ControllerHandle;
 | 
						|
 | 
						|
  //
 | 
						|
  // Get list of drivers that are currently managing ControllerHandle
 | 
						|
  //
 | 
						|
  DriverImageHandleBuffer = NULL;
 | 
						|
  DriverImageHandleCount  = 1;  
 | 
						|
  
 | 
						|
  if (DriverImageHandle == NULL) {
 | 
						|
    //
 | 
						|
    // Look at each protocol interface for a match
 | 
						|
    //
 | 
						|
    DriverImageHandleCount = 0;
 | 
						|
 | 
						|
    CoreAcquireProtocolLock ();
 | 
						|
    for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
 | 
						|
      Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
 | 
						|
      for (ProtLink = Prot->OpenList.ForwardLink; 
 | 
						|
           ProtLink != &Prot->OpenList; 
 | 
						|
           ProtLink = ProtLink->ForwardLink) {
 | 
						|
        OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
 | 
						|
        if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
 | 
						|
          DriverImageHandleCount++;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
    CoreReleaseProtocolLock ();
 | 
						|
    
 | 
						|
    //
 | 
						|
    // If there are no drivers managing this controller, then return EFI_SUCCESS
 | 
						|
    //
 | 
						|
    if (DriverImageHandleCount == 0) {
 | 
						|
      Status = EFI_SUCCESS;
 | 
						|
      goto Done;
 | 
						|
    }
 | 
						|
 | 
						|
    DriverImageHandleBuffer = CoreAllocateBootServicesPool (sizeof (EFI_HANDLE) * DriverImageHandleCount);
 | 
						|
    if (DriverImageHandleBuffer == NULL) {
 | 
						|
      Status = EFI_OUT_OF_RESOURCES;
 | 
						|
      goto Done;
 | 
						|
    }
 | 
						|
 | 
						|
    DriverImageHandleCount = 0;
 | 
						|
 | 
						|
    CoreAcquireProtocolLock ();
 | 
						|
    for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
 | 
						|
      Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
 | 
						|
      for (ProtLink = Prot->OpenList.ForwardLink; 
 | 
						|
           ProtLink != &Prot->OpenList; 
 | 
						|
           ProtLink = ProtLink->ForwardLink) {
 | 
						|
        OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
 | 
						|
        if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
 | 
						|
          Duplicate = FALSE;
 | 
						|
          for (Index = 0; Index< DriverImageHandleCount; Index++) {
 | 
						|
            if (DriverImageHandleBuffer[Index] == OpenData->AgentHandle) {
 | 
						|
              Duplicate = TRUE;
 | 
						|
              break;
 | 
						|
            }
 | 
						|
          }
 | 
						|
          if (!Duplicate) {
 | 
						|
            DriverImageHandleBuffer[DriverImageHandleCount] = OpenData->AgentHandle;
 | 
						|
            DriverImageHandleCount++;
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
    CoreReleaseProtocolLock ();
 | 
						|
  }
 | 
						|
 | 
						|
  StopCount = 0;
 | 
						|
  for (HandleIndex = 0; HandleIndex < DriverImageHandleCount; HandleIndex++) {
 | 
						|
 | 
						|
    if (DriverImageHandleBuffer != NULL) {
 | 
						|
      DriverImageHandle = DriverImageHandleBuffer[HandleIndex];
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Get the Driver Binding Protocol of the driver that is managing this controller
 | 
						|
    //
 | 
						|
    Status = CoreHandleProtocol (
 | 
						|
               DriverImageHandle,  
 | 
						|
               &gEfiDriverBindingProtocolGuid,   
 | 
						|
               (VOID **)&DriverBinding
 | 
						|
               );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      Status = EFI_INVALID_PARAMETER;
 | 
						|
      goto Done;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Look at each protocol interface for a match
 | 
						|
    //
 | 
						|
    DriverImageHandleValid = FALSE;
 | 
						|
    ChildBufferCount = 0;
 | 
						|
 | 
						|
    CoreAcquireProtocolLock ();
 | 
						|
    for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
 | 
						|
      Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
 | 
						|
      for (ProtLink = Prot->OpenList.ForwardLink; 
 | 
						|
           ProtLink != &Prot->OpenList; 
 | 
						|
           ProtLink = ProtLink->ForwardLink) {
 | 
						|
        OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
 | 
						|
        if (OpenData->AgentHandle == DriverImageHandle) {
 | 
						|
          if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
 | 
						|
            ChildBufferCount++;
 | 
						|
          } 
 | 
						|
          if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
 | 
						|
            DriverImageHandleValid = TRUE;
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
    CoreReleaseProtocolLock ();
 | 
						|
 | 
						|
    if (DriverImageHandleValid) {
 | 
						|
      ChildHandleValid = FALSE;
 | 
						|
      ChildBuffer = NULL;
 | 
						|
      if (ChildBufferCount != 0) {
 | 
						|
        ChildBuffer = CoreAllocateBootServicesPool (sizeof (EFI_HANDLE) * ChildBufferCount);
 | 
						|
        if (ChildBuffer == NULL) {
 | 
						|
          Status = EFI_OUT_OF_RESOURCES;
 | 
						|
          goto Done;
 | 
						|
        }
 | 
						|
 | 
						|
        ChildBufferCount = 0;
 | 
						|
 | 
						|
        CoreAcquireProtocolLock ();
 | 
						|
        for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
 | 
						|
          Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
 | 
						|
          for (ProtLink = Prot->OpenList.ForwardLink; 
 | 
						|
               ProtLink != &Prot->OpenList; 
 | 
						|
               ProtLink = ProtLink->ForwardLink) {
 | 
						|
            OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
 | 
						|
            if ((OpenData->AgentHandle == DriverImageHandle) &&
 | 
						|
                ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0)) {
 | 
						|
              Duplicate = FALSE;
 | 
						|
              for (Index = 0; Index < ChildBufferCount; Index++) {
 | 
						|
                if (ChildBuffer[Index] == OpenData->ControllerHandle) {
 | 
						|
                  Duplicate = TRUE;
 | 
						|
                  break;
 | 
						|
                }
 | 
						|
              }
 | 
						|
              if (!Duplicate) {
 | 
						|
                ChildBuffer[ChildBufferCount] = OpenData->ControllerHandle;
 | 
						|
                if (ChildHandle == ChildBuffer[ChildBufferCount]) {
 | 
						|
                  ChildHandleValid = TRUE;
 | 
						|
                }
 | 
						|
                ChildBufferCount++;
 | 
						|
              }
 | 
						|
            }
 | 
						|
          }
 | 
						|
        }
 | 
						|
        CoreReleaseProtocolLock ();
 | 
						|
      }
 | 
						|
 | 
						|
      if (ChildHandle == NULL || ChildHandleValid) {
 | 
						|
        ChildrenToStop = 0;
 | 
						|
        Status = EFI_SUCCESS;
 | 
						|
        if (ChildBufferCount > 0) {
 | 
						|
          if (ChildHandle != NULL) {
 | 
						|
            ChildrenToStop = 1;
 | 
						|
            Status = DriverBinding->Stop (DriverBinding, ControllerHandle, ChildrenToStop, &ChildHandle);
 | 
						|
          } else {
 | 
						|
            ChildrenToStop = ChildBufferCount;
 | 
						|
            Status = DriverBinding->Stop (DriverBinding, ControllerHandle, ChildrenToStop, ChildBuffer);
 | 
						|
          }
 | 
						|
        }
 | 
						|
        if (!EFI_ERROR (Status) && ((ChildHandle == NULL) || (ChildBufferCount == ChildrenToStop))) {
 | 
						|
          Status = DriverBinding->Stop (DriverBinding, ControllerHandle, 0, NULL);
 | 
						|
        }
 | 
						|
        if (!EFI_ERROR (Status)) {
 | 
						|
          StopCount++;
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      if (ChildBuffer != NULL) {
 | 
						|
        CoreFreePool (ChildBuffer);
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (StopCount > 0) {
 | 
						|
    Status = EFI_SUCCESS;
 | 
						|
  } else {
 | 
						|
    Status = EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
  
 | 
						|
Done:  
 | 
						|
 | 
						|
  if (DriverImageHandleBuffer != NULL) {
 | 
						|
    CoreFreePool (DriverImageHandleBuffer);
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
GetHandleFromDriverBinding (
 | 
						|
  IN   EFI_DRIVER_BINDING_PROTOCOL           *DriverBindingNeed,
 | 
						|
  OUT  EFI_HANDLE                            *Handle 
 | 
						|
 )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Locate the driver binding handle which a specified driver binding protocol installed on.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  DriverBindingNeed  - The specified driver binding protocol.
 | 
						|
  
 | 
						|
  Handle             - The driver binding handle which the protocol installed on.
 | 
						|
  
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  EFI_NOT_FOUND         - Could not find the handle.
 | 
						|
  
 | 
						|
  EFI_SUCCESS           - Successfully find the associated driver binding handle.
 | 
						|
  
 | 
						|
--*/ 
 | 
						|
 {
 | 
						|
  EFI_STATUS                          Status ;
 | 
						|
  EFI_DRIVER_BINDING_PROTOCOL         *DriverBinding;
 | 
						|
  UINTN                               DriverBindingHandleCount;
 | 
						|
  EFI_HANDLE                          *DriverBindingHandleBuffer;
 | 
						|
  UINTN                               Index;
 | 
						|
  
 | 
						|
  DriverBindingHandleCount = 0;
 | 
						|
  DriverBindingHandleBuffer = NULL;
 | 
						|
  *Handle = NULL_HANDLE;
 | 
						|
  Status = CoreLocateHandleBuffer (
 | 
						|
              ByProtocol,   
 | 
						|
              &gEfiDriverBindingProtocolGuid,  
 | 
						|
              NULL,
 | 
						|
              &DriverBindingHandleCount, 
 | 
						|
              &DriverBindingHandleBuffer
 | 
						|
              );
 | 
						|
  if (EFI_ERROR (Status) || DriverBindingHandleCount == 0) {
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
  
 | 
						|
  for (Index = 0 ; Index < DriverBindingHandleCount; Index++ ) {
 | 
						|
    Status = CoreOpenProtocol(
 | 
						|
                      DriverBindingHandleBuffer[Index],
 | 
						|
                      &gEfiDriverBindingProtocolGuid,
 | 
						|
                      (VOID **)&DriverBinding,
 | 
						|
                      gDxeCoreImageHandle,
 | 
						|
                      NULL,
 | 
						|
                      EFI_OPEN_PROTOCOL_GET_PROTOCOL
 | 
						|
                      );
 | 
						|
                      
 | 
						|
   if (!EFI_ERROR (Status) && DriverBinding != NULL) {
 | 
						|
    
 | 
						|
    if ( DriverBinding == DriverBindingNeed ) {
 | 
						|
      *Handle = DriverBindingHandleBuffer[Index];
 | 
						|
      CoreFreePool (DriverBindingHandleBuffer);         
 | 
						|
      return EFI_SUCCESS ;
 | 
						|
    }
 | 
						|
   }
 | 
						|
 }
 | 
						|
 
 | 
						|
 CoreFreePool (DriverBindingHandleBuffer);
 | 
						|
 return EFI_NOT_FOUND ;
 | 
						|
}
 | 
						|
 |