mirror of
				https://github.com/acidanthera/audk.git
				synced 2025-10-31 11:13:53 +01:00 
			
		
		
		
	Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Eric Dong <eric.dong@intel.com> Reviewed-by: Liming Gao <liming.gao@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@15695 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			965 lines
		
	
	
		
			35 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			965 lines
		
	
	
		
			35 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   Support functions to connect/disconnect UEFI Driver model Protocol
 | |
| 
 | |
| Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
 | |
| 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.
 | |
| 
 | |
| **/
 | |
| 
 | |
| #include "DxeMain.h"
 | |
| #include "Handle.h"
 | |
| 
 | |
| 
 | |
| //
 | |
| // Driver Support Functions
 | |
| //
 | |
| /**
 | |
|   Connects one or more drivers to a controller.
 | |
| 
 | |
|   @param  ControllerHandle      The handle of the controller to which driver(s) are to be connected.
 | |
|   @param  DriverImageHandle     A pointer to an ordered list handles that support the
 | |
|                                 EFI_DRIVER_BINDING_PROTOCOL.
 | |
|   @param  RemainingDevicePath   A pointer to the device path that specifies a child of the
 | |
|                                 controller specified by ControllerHandle.
 | |
|   @param  Recursive             If TRUE, then ConnectController() is called recursively
 | |
|                                 until the entire tree of controllers below the controller specified
 | |
|                                 by ControllerHandle have been created. If FALSE, then
 | |
|                                 the tree of controllers is only expanded one level.
 | |
| 
 | |
|   @retval EFI_SUCCESS           1) One or more drivers were connected to ControllerHandle.
 | |
|                                 2) No drivers were connected to ControllerHandle, but
 | |
|                                 RemainingDevicePath is not NULL, and it is an End Device
 | |
|                                 Path Node.
 | |
|   @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
 | |
|   @retval EFI_NOT_FOUND         1) There are no EFI_DRIVER_BINDING_PROTOCOL instances
 | |
|                                 present in the system.
 | |
|                                 2) No drivers were connected to ControllerHandle.
 | |
|   @retval EFI_SECURITY_VIOLATION 
 | |
|                                 The user has no permission to start UEFI device drivers on the device path 
 | |
|                                 associated with the ControllerHandle or specified by the RemainingDevicePath.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| CoreConnectController (
 | |
|   IN  EFI_HANDLE                ControllerHandle,
 | |
|   IN  EFI_HANDLE                *DriverImageHandle    OPTIONAL,
 | |
|   IN  EFI_DEVICE_PATH_PROTOCOL  *RemainingDevicePath  OPTIONAL,
 | |
|   IN  BOOLEAN                   Recursive
 | |
|   )
 | |
| {
 | |
|   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;
 | |
|   EFI_HANDLE                           *ChildHandleBuffer;
 | |
|   UINTN                                ChildHandleCount;
 | |
|   UINTN                                Index;
 | |
|   UINTN                                HandleFilePathSize;
 | |
|   UINTN                                RemainingDevicePathSize;
 | |
|   EFI_DEVICE_PATH_PROTOCOL             *HandleFilePath;
 | |
|   EFI_DEVICE_PATH_PROTOCOL             *FilePath;
 | |
|   EFI_DEVICE_PATH_PROTOCOL             *TempFilePath;
 | |
| 
 | |
|   //
 | |
|   // Make sure ControllerHandle is valid
 | |
|   //
 | |
|   Status = CoreValidateHandle (ControllerHandle);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   if (gSecurity2 != NULL) {
 | |
|     //
 | |
|     // Check whether the user has permission to start UEFI device drivers.
 | |
|     //
 | |
|     Status = CoreHandleProtocol (ControllerHandle, &gEfiDevicePathProtocolGuid, (VOID **)&HandleFilePath);
 | |
|     if (!EFI_ERROR (Status)) {
 | |
|       ASSERT (HandleFilePath != NULL);
 | |
|       FilePath     = HandleFilePath;
 | |
|       TempFilePath = NULL;
 | |
|       if (RemainingDevicePath != NULL && !Recursive) {
 | |
|         HandleFilePathSize      = GetDevicePathSize (HandleFilePath) - sizeof (EFI_DEVICE_PATH_PROTOCOL);
 | |
|         RemainingDevicePathSize = GetDevicePathSize (RemainingDevicePath);
 | |
|         TempFilePath = AllocateZeroPool (HandleFilePathSize + RemainingDevicePathSize);
 | |
|         ASSERT (TempFilePath != NULL);
 | |
|         CopyMem (TempFilePath, HandleFilePath, HandleFilePathSize);
 | |
|         CopyMem ((UINT8 *) TempFilePath + HandleFilePathSize, RemainingDevicePath, RemainingDevicePathSize);
 | |
|         FilePath = TempFilePath;
 | |
|       }
 | |
|       Status = gSecurity2->FileAuthentication (
 | |
|                             gSecurity2,
 | |
|                             FilePath,
 | |
|                             NULL,
 | |
|                             0,
 | |
|                             FALSE
 | |
|                             );
 | |
|       if (TempFilePath != NULL) {
 | |
|         FreePool (TempFilePath);
 | |
|       }
 | |
|       if (EFI_ERROR (Status)) {
 | |
|         return Status;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   
 | |
|   Handle = ControllerHandle;
 | |
| 
 | |
|   //
 | |
|   // Make a copy of RemainingDevicePath to guanatee it is aligned
 | |
|   //
 | |
|   AlignedRemainingDevicePath = NULL;
 | |
|   if (RemainingDevicePath != NULL) {
 | |
|     AlignedRemainingDevicePath = DuplicateDevicePath (RemainingDevicePath);
 | |
| 
 | |
|     if (AlignedRemainingDevicePath == NULL) {
 | |
|       return EFI_OUT_OF_RESOURCES;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Connect all drivers to ControllerHandle
 | |
|   // If CoreConnectSingleController returns EFI_NOT_READY, then the number of
 | |
|   // Driver Binding Protocols in the handle database has increased during the call
 | |
|   // so the connect operation must be restarted
 | |
|   //
 | |
|   do {
 | |
|     ReturnStatus = CoreConnectSingleController (
 | |
|                      ControllerHandle,
 | |
|                      DriverImageHandle,
 | |
|                      AlignedRemainingDevicePath
 | |
|                      );
 | |
|   } while (ReturnStatus == EFI_NOT_READY);
 | |
| 
 | |
|   //
 | |
|   // Free the aligned copy of RemainingDevicePath
 | |
|   //
 | |
|   if (AlignedRemainingDevicePath != NULL) {
 | |
|     CoreFreePool (AlignedRemainingDevicePath);
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // If recursive, then connect all drivers to all of ControllerHandle's children
 | |
|   //
 | |
|   if (Recursive) {
 | |
|     //
 | |
|     // Acquire the protocol lock on the handle database so the child handles can be collected
 | |
|     //
 | |
|     CoreAcquireProtocolLock ();
 | |
| 
 | |
|     //
 | |
|     // Make sure the DriverBindingHandle is valid
 | |
|     //
 | |
|     Status = CoreValidateHandle (ControllerHandle);
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       //
 | |
|       // Release the protocol lock on the handle database
 | |
|       //
 | |
|       CoreReleaseProtocolLock ();
 | |
| 
 | |
|       return ReturnStatus;
 | |
|     }
 | |
| 
 | |
| 
 | |
|     //
 | |
|     // Count ControllerHandle's children
 | |
|     //
 | |
|     for (Link = Handle->Protocols.ForwardLink, ChildHandleCount = 0; 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) {
 | |
|           ChildHandleCount++;
 | |
|         }
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Allocate a handle buffer for ControllerHandle's children
 | |
|     //
 | |
|     ChildHandleBuffer = AllocatePool (ChildHandleCount * sizeof(EFI_HANDLE));
 | |
|     if (ChildHandleBuffer == NULL) {
 | |
|       CoreReleaseProtocolLock ();
 | |
|       return EFI_OUT_OF_RESOURCES;
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Fill in a handle buffer with ControllerHandle's children
 | |
|     //
 | |
|     for (Link = Handle->Protocols.ForwardLink, ChildHandleCount = 0; 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) {
 | |
|           ChildHandleBuffer[ChildHandleCount] = OpenData->ControllerHandle;
 | |
|           ChildHandleCount++;
 | |
|         }
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Release the protocol lock on the handle database
 | |
|     //
 | |
|     CoreReleaseProtocolLock ();
 | |
| 
 | |
|     //
 | |
|     // Recursively connect each child handle
 | |
|     //
 | |
|     for (Index = 0; Index < ChildHandleCount; Index++) {
 | |
|       CoreConnectController (
 | |
|         ChildHandleBuffer[Index],
 | |
|         NULL,
 | |
|         NULL,
 | |
|         TRUE
 | |
|         );
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Free the handle buffer of ControllerHandle's children
 | |
|     //
 | |
|     CoreFreePool (ChildHandleBuffer);
 | |
|   }
 | |
| 
 | |
|   return ReturnStatus;
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Add Driver Binding Protocols from Context Driver Image Handles to sorted
 | |
|   Driver Binding Protocol list.
 | |
| 
 | |
|   @param  DriverBindingHandle                   Handle of the driver binding
 | |
|                                                 protocol.
 | |
|   @param  NumberOfSortedDriverBindingProtocols  Number Of sorted driver binding
 | |
|                                                 protocols
 | |
|   @param  SortedDriverBindingProtocols          The sorted protocol list.
 | |
|   @param  DriverBindingHandleCount              Driver Binding Handle Count.
 | |
|   @param  DriverBindingHandleBuffer             The buffer of driver binding
 | |
|                                                 protocol to be modified.
 | |
|   @param  IsImageHandle                         Indicate whether
 | |
|                                                 DriverBindingHandle is an image
 | |
|                                                 handle
 | |
| 
 | |
|   @return None.
 | |
| 
 | |
| **/
 | |
| 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,
 | |
|   IN      BOOLEAN                      IsImageHandle
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                   Status;
 | |
|   EFI_DRIVER_BINDING_PROTOCOL  *DriverBinding;
 | |
|   UINTN                        Index;
 | |
| 
 | |
|   //
 | |
|   // Make sure the DriverBindingHandle is valid
 | |
|   //
 | |
|   Status = CoreValidateHandle (DriverBindingHandle);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // If IsImageHandle is TRUE, then DriverBindingHandle is an image handle
 | |
|   // Find all the DriverBindingHandles associated with that image handle and add them to the sorted list
 | |
|   //
 | |
|   if (IsImageHandle) {
 | |
|     //
 | |
|     // Loop through all the Driver Binding Handles
 | |
|     //
 | |
|     for (Index = 0; Index < DriverBindingHandleCount; Index++) {
 | |
|       //
 | |
|       // Retrieve the Driver Binding Protocol associated with each Driver Binding Handle
 | |
|       //
 | |
|       Status = CoreHandleProtocol (
 | |
|                 DriverBindingHandleBuffer[Index],
 | |
|                 &gEfiDriverBindingProtocolGuid,
 | |
|                 (VOID **) &DriverBinding
 | |
|                 );
 | |
|       if (EFI_ERROR (Status) || DriverBinding == NULL) {
 | |
|         continue;
 | |
|       }
 | |
| 
 | |
|       //
 | |
|       // If the ImageHandle associated with DriverBinding matches DriverBindingHandle,
 | |
|       // then add the DriverBindingProtocol[Index] to the sorted list
 | |
|       //
 | |
|       if (DriverBinding->ImageHandle == DriverBindingHandle) {
 | |
|         AddSortedDriverBindingProtocol (
 | |
|           DriverBindingHandleBuffer[Index],
 | |
|           NumberOfSortedDriverBindingProtocols,
 | |
|           SortedDriverBindingProtocols,
 | |
|           DriverBindingHandleCount,
 | |
|           DriverBindingHandleBuffer,
 | |
|           FALSE
 | |
|           );
 | |
|       }
 | |
|     }
 | |
|     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 < DriverBindingHandleCount; Index++) {
 | |
|     if (DriverBinding == SortedDriverBindingProtocols[Index]) {
 | |
|       return;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Add DriverBinding to the end of the list
 | |
|   //
 | |
|   if (*NumberOfSortedDriverBindingProtocols < DriverBindingHandleCount) {
 | |
|     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;
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Connects a controller to a driver.
 | |
| 
 | |
|   @param  ControllerHandle                      Handle of the controller to be
 | |
|                                                 connected.
 | |
|   @param  ContextDriverImageHandles             DriverImageHandle A pointer to an
 | |
|                                                 ordered list of driver image
 | |
|                                                 handles.
 | |
|   @param  RemainingDevicePath                   RemainingDevicePath A pointer to
 | |
|                                                 the device path that specifies a
 | |
|                                                 child  of the controller
 | |
|                                                 specified by ControllerHandle.
 | |
| 
 | |
|   @retval EFI_SUCCESS                           One or more drivers were
 | |
|                                                 connected to ControllerHandle.
 | |
|   @retval EFI_OUT_OF_RESOURCES                  No enough system resources to
 | |
|                                                 complete the request.
 | |
|   @retval EFI_NOT_FOUND                         No drivers were connected to
 | |
|                                                 ControllerHandle.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| CoreConnectSingleController (
 | |
|   IN  EFI_HANDLE                ControllerHandle,
 | |
|   IN  EFI_HANDLE                *ContextDriverImageHandles OPTIONAL,
 | |
|   IN  EFI_DEVICE_PATH_PROTOCOL  *RemainingDevicePath       OPTIONAL
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                                 Status;
 | |
|   UINTN                                      Index;
 | |
|   EFI_HANDLE                                 DriverImageHandle;
 | |
|   EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL      *PlatformDriverOverride;
 | |
|   EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL  *BusSpecificDriverOverride;
 | |
|   UINTN                                      DriverBindingHandleCount;
 | |
|   EFI_HANDLE                                 *DriverBindingHandleBuffer;
 | |
|   UINTN                                      NewDriverBindingHandleCount;
 | |
|   EFI_HANDLE                                 *NewDriverBindingHandleBuffer;
 | |
|   EFI_DRIVER_BINDING_PROTOCOL                *DriverBinding;
 | |
|   EFI_DRIVER_FAMILY_OVERRIDE_PROTOCOL        *DriverFamilyOverride;
 | |
|   UINTN                                      NumberOfSortedDriverBindingProtocols;
 | |
|   EFI_DRIVER_BINDING_PROTOCOL                **SortedDriverBindingProtocols;
 | |
|   UINT32                                     DriverFamilyOverrideVersion;
 | |
|   UINT32                                     HighestVersion;
 | |
|   UINTN                                      HighestIndex;
 | |
|   UINTN                                      SortIndex;
 | |
|   BOOLEAN                                    OneStarted;
 | |
|   BOOLEAN                                    DriverFound;
 | |
| 
 | |
|   //
 | |
|   // Initialize local variables
 | |
|   //
 | |
|   DriverBindingHandleCount              = 0;
 | |
|   DriverBindingHandleBuffer             = NULL;
 | |
|   NumberOfSortedDriverBindingProtocols  = 0;
 | |
|   SortedDriverBindingProtocols          = NULL;
 | |
|   PlatformDriverOverride                = NULL;
 | |
|   NewDriverBindingHandleBuffer          = 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 = AllocatePool (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,
 | |
|         FALSE
 | |
|         );
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // 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,
 | |
|           TRUE
 | |
|           );
 | |
|       }
 | |
|     } while (!EFI_ERROR (Status));
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Add the Driver Family Override Protocol drivers for ControllerHandle
 | |
|   //
 | |
|   while (TRUE) {
 | |
|     HighestIndex   = DriverBindingHandleCount;
 | |
|     HighestVersion = 0;
 | |
|     for (Index = 0; Index < DriverBindingHandleCount; Index++) {
 | |
|       Status = CoreHandleProtocol (
 | |
|                  DriverBindingHandleBuffer[Index],
 | |
|                  &gEfiDriverFamilyOverrideProtocolGuid,
 | |
|                  (VOID **) &DriverFamilyOverride
 | |
|                  );
 | |
|       if (!EFI_ERROR (Status) && (DriverFamilyOverride != NULL)) {
 | |
|         DriverFamilyOverrideVersion = DriverFamilyOverride->GetVersion (DriverFamilyOverride);
 | |
|         if ((HighestIndex == DriverBindingHandleCount) || (DriverFamilyOverrideVersion > HighestVersion)) {
 | |
|           HighestVersion = DriverFamilyOverrideVersion;
 | |
|           HighestIndex   = Index;
 | |
|         }
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     if (HighestIndex == DriverBindingHandleCount) {
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|     AddSortedDriverBindingProtocol (
 | |
|       DriverBindingHandleBuffer[HighestIndex],
 | |
|       &NumberOfSortedDriverBindingProtocols,
 | |
|       SortedDriverBindingProtocols,
 | |
|       DriverBindingHandleCount,
 | |
|       DriverBindingHandleBuffer,
 | |
|       FALSE
 | |
|       );
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // 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,
 | |
|           TRUE
 | |
|           );
 | |
|       }
 | |
|     } 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,
 | |
|       FALSE
 | |
|       );
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Free the Driver Binding Handle Buffer
 | |
|   //
 | |
|   CoreFreePool (DriverBindingHandleBuffer);
 | |
| 
 | |
|   //
 | |
|   // If the number of Driver Binding Protocols has increased since this function started, then return
 | |
|   // EFI_NOT_READY, so it will be restarted
 | |
|   //
 | |
|   Status = CoreLocateHandleBuffer (
 | |
|              ByProtocol,
 | |
|              &gEfiDriverBindingProtocolGuid,
 | |
|              NULL,
 | |
|              &NewDriverBindingHandleCount,
 | |
|              &NewDriverBindingHandleBuffer
 | |
|              );
 | |
|   CoreFreePool (NewDriverBindingHandleBuffer);
 | |
|   if (NewDriverBindingHandleCount > DriverBindingHandleCount) {
 | |
|     //
 | |
|     // Free any buffers that were allocated with AllocatePool()
 | |
|     //
 | |
|     CoreFreePool (SortedDriverBindingProtocols);
 | |
| 
 | |
|     return EFI_NOT_READY;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // 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];
 | |
|         PERF_START (DriverBinding->DriverBindingHandle, "DB:Support:", NULL, 0);
 | |
|         Status = DriverBinding->Supported(
 | |
|                                   DriverBinding,
 | |
|                                   ControllerHandle,
 | |
|                                   RemainingDevicePath
 | |
|                                   );
 | |
|         PERF_END (DriverBinding->DriverBindingHandle, "DB:Support:", NULL, 0);
 | |
|         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_START (DriverBinding->DriverBindingHandle, "DB:Start:", NULL, 0);
 | |
|           Status = DriverBinding->Start (
 | |
|                                     DriverBinding,
 | |
|                                     ControllerHandle,
 | |
|                                     RemainingDevicePath
 | |
|                                     );
 | |
|           PERF_END (DriverBinding->DriverBindingHandle, "DB:Start:", 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;
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Disonnects a controller from a driver
 | |
| 
 | |
|   @param  ControllerHandle                      ControllerHandle The handle of
 | |
|                                                 the controller from which
 | |
|                                                 driver(s)  are to be
 | |
|                                                 disconnected.
 | |
|   @param  DriverImageHandle                     DriverImageHandle The driver to
 | |
|                                                 disconnect from ControllerHandle.
 | |
|   @param  ChildHandle                           ChildHandle The handle of the
 | |
|                                                 child to destroy.
 | |
| 
 | |
|   @retval EFI_SUCCESS                           One or more drivers were
 | |
|                                                 disconnected from the controller.
 | |
|   @retval EFI_SUCCESS                           On entry, no drivers are managing
 | |
|                                                 ControllerHandle.
 | |
|   @retval EFI_SUCCESS                           DriverImageHandle is not NULL,
 | |
|                                                 and on entry DriverImageHandle is
 | |
|                                                 not managing ControllerHandle.
 | |
|   @retval EFI_INVALID_PARAMETER                 ControllerHandle is NULL.
 | |
|   @retval EFI_INVALID_PARAMETER                 DriverImageHandle is not NULL,
 | |
|                                                 and it is not a valid EFI_HANDLE.
 | |
|   @retval EFI_INVALID_PARAMETER                 ChildHandle is not NULL, and it
 | |
|                                                 is not a valid EFI_HANDLE.
 | |
|   @retval EFI_OUT_OF_RESOURCES                  There are not enough resources
 | |
|                                                 available to disconnect any
 | |
|                                                 drivers from ControllerHandle.
 | |
|   @retval EFI_DEVICE_ERROR                      The controller could not be
 | |
|                                                 disconnected because of a device
 | |
|                                                 error.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| CoreDisconnectController (
 | |
|   IN  EFI_HANDLE  ControllerHandle,
 | |
|   IN  EFI_HANDLE  DriverImageHandle  OPTIONAL,
 | |
|   IN  EFI_HANDLE  ChildHandle        OPTIONAL
 | |
|   )
 | |
| {
 | |
|   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 = AllocatePool (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) || DriverBinding == NULL) {
 | |
|       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 = AllocatePool (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;
 | |
| }
 |