/*++ | |
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 ; | |
} | |