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 ;
 | |
| }
 | |
| 
 |