Check in DxeCore for Nt32 platform. Currently, it does not follow PI/UEFI2.1.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@3045 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
845
MdeModulePkg/Core/Dxe/Hand/DriverSupport.c
Normal file
845
MdeModulePkg/Core/Dxe/Hand/DriverSupport.c
Normal file
@@ -0,0 +1,845 @@
|
||||
/*++
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
STATIC
|
||||
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;
|
||||
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;
|
||||
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 ;
|
||||
}
|
||||
|
333
MdeModulePkg/Core/Dxe/Hand/Notify.c
Normal file
333
MdeModulePkg/Core/Dxe/Hand/Notify.c
Normal file
@@ -0,0 +1,333 @@
|
||||
/*++
|
||||
|
||||
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:
|
||||
|
||||
notify.c
|
||||
|
||||
Abstract:
|
||||
|
||||
EFI notify infrastructure
|
||||
|
||||
|
||||
|
||||
Revision History
|
||||
|
||||
--*/
|
||||
|
||||
#include <DxeMain.h>
|
||||
|
||||
VOID
|
||||
CoreNotifyProtocolEntry (
|
||||
IN PROTOCOL_ENTRY *ProtEntry
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Signal event for every protocol in protocol entry.
|
||||
|
||||
Arguments:
|
||||
|
||||
ProtEntry - Protocol entry
|
||||
|
||||
Returns:
|
||||
|
||||
--*/
|
||||
{
|
||||
PROTOCOL_NOTIFY *ProtNotify;
|
||||
LIST_ENTRY *Link;
|
||||
|
||||
ASSERT_LOCKED (&gProtocolDatabaseLock);
|
||||
|
||||
for (Link=ProtEntry->Notify.ForwardLink; Link != &ProtEntry->Notify; Link=Link->ForwardLink) {
|
||||
ProtNotify = CR(Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE);
|
||||
CoreSignalEvent (ProtNotify->Event);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PROTOCOL_INTERFACE *
|
||||
CoreRemoveInterfaceFromProtocol (
|
||||
IN IHANDLE *Handle,
|
||||
IN EFI_GUID *Protocol,
|
||||
IN VOID *Interface
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Removes Protocol from the protocol list (but not the handle list).
|
||||
|
||||
Arguments:
|
||||
|
||||
Handle - The handle to remove protocol on.
|
||||
|
||||
Protocol - GUID of the protocol to be moved
|
||||
|
||||
Interface - The interface of the protocol
|
||||
|
||||
Returns:
|
||||
|
||||
Protocol Entry
|
||||
|
||||
--*/
|
||||
{
|
||||
PROTOCOL_INTERFACE *Prot;
|
||||
PROTOCOL_NOTIFY *ProtNotify;
|
||||
PROTOCOL_ENTRY *ProtEntry;
|
||||
LIST_ENTRY *Link;
|
||||
|
||||
ASSERT_LOCKED (&gProtocolDatabaseLock);
|
||||
|
||||
Prot = CoreFindProtocolInterface (Handle, Protocol, Interface);
|
||||
if (Prot != NULL) {
|
||||
|
||||
ProtEntry = Prot->Protocol;
|
||||
|
||||
//
|
||||
// If there's a protocol notify location pointing to this entry, back it up one
|
||||
//
|
||||
|
||||
for(Link = ProtEntry->Notify.ForwardLink; Link != &ProtEntry->Notify; Link=Link->ForwardLink) {
|
||||
ProtNotify = CR(Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE);
|
||||
|
||||
if (ProtNotify->Position == &Prot->ByProtocol) {
|
||||
ProtNotify->Position = Prot->ByProtocol.BackLink;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Remove the protocol interface entry
|
||||
//
|
||||
|
||||
RemoveEntryList (&Prot->ByProtocol);
|
||||
}
|
||||
|
||||
return Prot;
|
||||
}
|
||||
|
||||
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
CoreRegisterProtocolNotify (
|
||||
IN EFI_GUID *Protocol,
|
||||
IN EFI_EVENT Event,
|
||||
OUT VOID **Registration
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Add a new protocol notification record for the request protocol.
|
||||
|
||||
Arguments:
|
||||
|
||||
Protocol - The requested protocol to add the notify registration
|
||||
|
||||
Event - The event to signal
|
||||
|
||||
Registration - Returns the registration record
|
||||
|
||||
|
||||
Returns:
|
||||
|
||||
EFI_INVALID_PARAMETER - Invalid parameter
|
||||
|
||||
EFI_SUCCESS - Successfully returned the registration record that has been added
|
||||
|
||||
--*/
|
||||
{
|
||||
PROTOCOL_ENTRY *ProtEntry;
|
||||
PROTOCOL_NOTIFY *ProtNotify;
|
||||
EFI_STATUS Status;
|
||||
|
||||
if ((Protocol == NULL) || (Event == NULL) || (Registration == NULL)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
CoreAcquireProtocolLock ();
|
||||
|
||||
ProtNotify = NULL;
|
||||
|
||||
//
|
||||
// Get the protocol entry to add the notification too
|
||||
//
|
||||
|
||||
ProtEntry = CoreFindProtocolEntry (Protocol, TRUE);
|
||||
if (ProtEntry != NULL) {
|
||||
|
||||
//
|
||||
// Allocate a new notification record
|
||||
//
|
||||
|
||||
ProtNotify = CoreAllocateBootServicesPool (sizeof(PROTOCOL_NOTIFY));
|
||||
|
||||
if (ProtNotify != NULL) {
|
||||
|
||||
ProtNotify->Signature = PROTOCOL_NOTIFY_SIGNATURE;
|
||||
ProtNotify->Protocol = ProtEntry;
|
||||
ProtNotify->Event = Event;
|
||||
//
|
||||
// start at the begining
|
||||
//
|
||||
ProtNotify->Position = &ProtEntry->Protocols;
|
||||
|
||||
InsertTailList (&ProtEntry->Notify, &ProtNotify->Link);
|
||||
}
|
||||
}
|
||||
|
||||
CoreReleaseProtocolLock ();
|
||||
|
||||
//
|
||||
// Done. If we have a protocol notify entry, then return it.
|
||||
// Otherwise, we must have run out of resources trying to add one
|
||||
//
|
||||
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
if (ProtNotify != NULL) {
|
||||
*Registration = ProtNotify;
|
||||
Status = EFI_SUCCESS;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
CoreReinstallProtocolInterface (
|
||||
IN EFI_HANDLE UserHandle,
|
||||
IN EFI_GUID *Protocol,
|
||||
IN VOID *OldInterface,
|
||||
IN VOID *NewInterface
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Reinstall a protocol interface on a device handle. The OldInterface for Protocol is replaced by the NewInterface.
|
||||
|
||||
Arguments:
|
||||
|
||||
UserHandle - Handle on which the interface is to be reinstalled
|
||||
Protocol - The numeric ID of the interface
|
||||
OldInterface - A pointer to the old interface
|
||||
NewInterface - A pointer to the new interface
|
||||
|
||||
|
||||
Returns:
|
||||
|
||||
Status code.
|
||||
|
||||
On EFI_SUCCESS The protocol interface was installed
|
||||
On EFI_NOT_FOUND The OldInterface on the handle was not found
|
||||
On EFI_INVALID_PARAMETER One of the parameters has an invalid value
|
||||
|
||||
--*/
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
IHANDLE *Handle;
|
||||
PROTOCOL_INTERFACE *Prot;
|
||||
PROTOCOL_ENTRY *ProtEntry;
|
||||
|
||||
Status = CoreValidateHandle (UserHandle);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
if (Protocol == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Handle = (IHANDLE *) UserHandle;
|
||||
|
||||
//
|
||||
// Lock the protocol database
|
||||
//
|
||||
CoreAcquireProtocolLock ();
|
||||
|
||||
//
|
||||
// Check that Protocol exists on UserHandle, and Interface matches the interface in the database
|
||||
//
|
||||
Prot = CoreFindProtocolInterface (UserHandle, Protocol, OldInterface);
|
||||
if (Prot == NULL) {
|
||||
CoreReleaseProtocolLock ();
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
//
|
||||
// Attempt to disconnect all drivers that are using the protocol interface that is about to be reinstalled
|
||||
//
|
||||
Status = CoreDisconnectControllersUsingProtocolInterface (
|
||||
UserHandle,
|
||||
Prot
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
//
|
||||
// One or more drivers refused to release, so return the error
|
||||
//
|
||||
CoreReleaseProtocolLock ();
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Remove the protocol interface from the protocol
|
||||
//
|
||||
Prot = CoreRemoveInterfaceFromProtocol (Handle, Protocol, OldInterface);
|
||||
|
||||
if (Prot == NULL) {
|
||||
CoreReleaseProtocolLock ();
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
ProtEntry = Prot->Protocol;
|
||||
|
||||
//
|
||||
// Update the interface on the protocol
|
||||
//
|
||||
Prot->Interface = NewInterface;
|
||||
|
||||
//
|
||||
// Add this protocol interface to the tail of the
|
||||
// protocol entry
|
||||
//
|
||||
InsertTailList (&ProtEntry->Protocols, &Prot->ByProtocol);
|
||||
|
||||
//
|
||||
// Update the Key to show that the handle has been created/modified
|
||||
//
|
||||
gHandleDatabaseKey++;
|
||||
Handle->Key = gHandleDatabaseKey;
|
||||
|
||||
//
|
||||
// Release the lock and connect all drivers to UserHandle
|
||||
//
|
||||
CoreReleaseProtocolLock ();
|
||||
Status = CoreConnectController (
|
||||
UserHandle,
|
||||
NULL,
|
||||
NULL,
|
||||
TRUE
|
||||
);
|
||||
CoreAcquireProtocolLock ();
|
||||
|
||||
//
|
||||
// Notify the notification list for this protocol
|
||||
//
|
||||
CoreNotifyProtocolEntry (ProtEntry);
|
||||
|
||||
CoreReleaseProtocolLock ();
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
1700
MdeModulePkg/Core/Dxe/Hand/handle.c
Normal file
1700
MdeModulePkg/Core/Dxe/Hand/handle.c
Normal file
File diff suppressed because it is too large
Load Diff
733
MdeModulePkg/Core/Dxe/Hand/locate.c
Normal file
733
MdeModulePkg/Core/Dxe/Hand/locate.c
Normal file
@@ -0,0 +1,733 @@
|
||||
/*++
|
||||
|
||||
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:
|
||||
|
||||
locate.c
|
||||
|
||||
Abstract:
|
||||
|
||||
Locate handle functions
|
||||
|
||||
Revision History
|
||||
|
||||
--*/
|
||||
|
||||
#include <DxeMain.h>
|
||||
|
||||
//
|
||||
// ProtocolRequest - Last LocateHandle request ID
|
||||
//
|
||||
UINTN mEfiLocateHandleRequest = 0;
|
||||
|
||||
//
|
||||
// Internal prototypes
|
||||
//
|
||||
|
||||
typedef struct {
|
||||
EFI_GUID *Protocol;
|
||||
VOID *SearchKey;
|
||||
LIST_ENTRY *Position;
|
||||
PROTOCOL_ENTRY *ProtEntry;
|
||||
} LOCATE_POSITION;
|
||||
|
||||
typedef
|
||||
IHANDLE *
|
||||
(* CORE_GET_NEXT) (
|
||||
IN OUT LOCATE_POSITION *Position,
|
||||
OUT VOID **Interface
|
||||
);
|
||||
|
||||
STATIC
|
||||
IHANDLE *
|
||||
CoreGetNextLocateAllHandles (
|
||||
IN OUT LOCATE_POSITION *Position,
|
||||
OUT VOID **Interface
|
||||
);
|
||||
|
||||
STATIC
|
||||
IHANDLE *
|
||||
CoreGetNextLocateByRegisterNotify (
|
||||
IN OUT LOCATE_POSITION *Position,
|
||||
OUT VOID **Interface
|
||||
);
|
||||
|
||||
STATIC
|
||||
IHANDLE *
|
||||
CoreGetNextLocateByProtocol (
|
||||
IN OUT LOCATE_POSITION *Position,
|
||||
OUT VOID **Interface
|
||||
);
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
|
||||
|
||||
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
CoreLocateHandle (
|
||||
IN EFI_LOCATE_SEARCH_TYPE SearchType,
|
||||
IN EFI_GUID *Protocol OPTIONAL,
|
||||
IN VOID *SearchKey OPTIONAL,
|
||||
IN OUT UINTN *BufferSize,
|
||||
OUT EFI_HANDLE *Buffer
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Locates the requested handle(s) and returns them in Buffer.
|
||||
|
||||
Arguments:
|
||||
|
||||
SearchType - The type of search to perform to locate the handles
|
||||
|
||||
Protocol - The protocol to search for
|
||||
|
||||
SearchKey - Dependant on SearchType
|
||||
|
||||
BufferSize - On input the size of Buffer. On output the
|
||||
size of data returned.
|
||||
|
||||
Buffer - The buffer to return the results in
|
||||
|
||||
|
||||
Returns:
|
||||
|
||||
EFI_BUFFER_TOO_SMALL - Buffer too small, required buffer size is returned in BufferSize.
|
||||
|
||||
EFI_INVALID_PARAMETER - Invalid parameter
|
||||
|
||||
EFI_SUCCESS - Successfully found the requested handle(s) and returns them in Buffer.
|
||||
|
||||
--*/
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
LOCATE_POSITION Position;
|
||||
PROTOCOL_NOTIFY *ProtNotify;
|
||||
CORE_GET_NEXT GetNext;
|
||||
UINTN ResultSize;
|
||||
IHANDLE *Handle;
|
||||
IHANDLE **ResultBuffer;
|
||||
VOID *Interface;
|
||||
|
||||
if (BufferSize == NULL) {
|
||||
Status = EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if ((*BufferSize > 0) && (Buffer == NULL)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
GetNext = NULL;
|
||||
//
|
||||
// Set initial position
|
||||
//
|
||||
|
||||
Position.Protocol = Protocol;
|
||||
Position.SearchKey = SearchKey;
|
||||
Position.Position = &gHandleList;
|
||||
|
||||
ResultSize = 0;
|
||||
ResultBuffer = (IHANDLE **) Buffer;
|
||||
Status = EFI_SUCCESS;
|
||||
|
||||
//
|
||||
// Lock the protocol database
|
||||
//
|
||||
|
||||
CoreAcquireProtocolLock ();
|
||||
|
||||
//
|
||||
// Get the search function based on type
|
||||
//
|
||||
switch (SearchType) {
|
||||
case AllHandles:
|
||||
GetNext = CoreGetNextLocateAllHandles;
|
||||
break;
|
||||
|
||||
case ByRegisterNotify:
|
||||
//
|
||||
// Must have SearchKey for locate ByRegisterNotify
|
||||
//
|
||||
if (SearchKey == NULL) {
|
||||
Status = EFI_INVALID_PARAMETER;
|
||||
break;
|
||||
}
|
||||
GetNext = CoreGetNextLocateByRegisterNotify;
|
||||
break;
|
||||
|
||||
case ByProtocol:
|
||||
GetNext = CoreGetNextLocateByProtocol;
|
||||
if (Protocol == NULL) {
|
||||
Status = EFI_INVALID_PARAMETER;
|
||||
break;
|
||||
}
|
||||
//
|
||||
// Look up the protocol entry and set the head pointer
|
||||
//
|
||||
Position.ProtEntry = CoreFindProtocolEntry (Protocol, FALSE);
|
||||
if (Position.ProtEntry == NULL) {
|
||||
Status = EFI_NOT_FOUND;
|
||||
break;
|
||||
}
|
||||
Position.Position = &Position.ProtEntry->Protocols;
|
||||
break;
|
||||
|
||||
default:
|
||||
Status = EFI_INVALID_PARAMETER;
|
||||
break;
|
||||
}
|
||||
|
||||
if (EFI_ERROR(Status)) {
|
||||
CoreReleaseProtocolLock ();
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Enumerate out the matching handles
|
||||
//
|
||||
mEfiLocateHandleRequest += 1;
|
||||
for (; ;) {
|
||||
//
|
||||
// Get the next handle. If no more handles, stop
|
||||
//
|
||||
Handle = GetNext (&Position, &Interface);
|
||||
if (NULL == Handle) {
|
||||
break;
|
||||
}
|
||||
|
||||
//
|
||||
// Increase the resulting buffer size, and if this handle
|
||||
// fits return it
|
||||
//
|
||||
ResultSize += sizeof(Handle);
|
||||
if (ResultSize <= *BufferSize) {
|
||||
*ResultBuffer = Handle;
|
||||
ResultBuffer += 1;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// If the result is a zero length buffer, then there were no
|
||||
// matching handles
|
||||
//
|
||||
if (ResultSize == 0) {
|
||||
Status = EFI_NOT_FOUND;
|
||||
} else {
|
||||
//
|
||||
// Return the resulting buffer size. If it's larger than what
|
||||
// was passed, then set the error code
|
||||
//
|
||||
if (ResultSize > *BufferSize) {
|
||||
Status = EFI_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
*BufferSize = ResultSize;
|
||||
|
||||
if (SearchType == ByRegisterNotify && !EFI_ERROR(Status)) {
|
||||
//
|
||||
// If this is a search by register notify and a handle was
|
||||
// returned, update the register notification position
|
||||
//
|
||||
ProtNotify = SearchKey;
|
||||
ProtNotify->Position = ProtNotify->Position->ForwardLink;
|
||||
}
|
||||
}
|
||||
|
||||
CoreReleaseProtocolLock ();
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
STATIC
|
||||
IHANDLE *
|
||||
CoreGetNextLocateAllHandles (
|
||||
IN OUT LOCATE_POSITION *Position,
|
||||
OUT VOID **Interface
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Routine to get the next Handle, when you are searching for all handles.
|
||||
|
||||
Arguments:
|
||||
|
||||
Position - Information about which Handle to seach for.
|
||||
|
||||
Interface - Return the interface structure for the matching protocol.
|
||||
|
||||
Returns:
|
||||
IHANDLE - An IHANDLE is returned if the next Position is not the end of the
|
||||
list. A NULL_HANDLE is returned if it's the end of the list.
|
||||
|
||||
--*/
|
||||
{
|
||||
IHANDLE *Handle;
|
||||
|
||||
//
|
||||
// Next handle
|
||||
//
|
||||
Position->Position = Position->Position->ForwardLink;
|
||||
|
||||
//
|
||||
// If not at the end of the list, get the handle
|
||||
//
|
||||
Handle = NULL_HANDLE;
|
||||
*Interface = NULL;
|
||||
if (Position->Position != &gHandleList) {
|
||||
Handle = CR (Position->Position, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE);
|
||||
}
|
||||
|
||||
return Handle;
|
||||
}
|
||||
|
||||
|
||||
STATIC
|
||||
IHANDLE *
|
||||
CoreGetNextLocateByRegisterNotify (
|
||||
IN OUT LOCATE_POSITION *Position,
|
||||
OUT VOID **Interface
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Routine to get the next Handle, when you are searching for register protocol
|
||||
notifies.
|
||||
|
||||
Arguments:
|
||||
|
||||
Position - Information about which Handle to seach for.
|
||||
|
||||
Interface - Return the interface structure for the matching protocol.
|
||||
|
||||
Returns:
|
||||
IHANDLE - An IHANDLE is returned if the next Position is not the end of the
|
||||
list. A NULL_HANDLE is returned if it's the end of the list.
|
||||
|
||||
--*/
|
||||
{
|
||||
IHANDLE *Handle;
|
||||
PROTOCOL_NOTIFY *ProtNotify;
|
||||
PROTOCOL_INTERFACE *Prot;
|
||||
LIST_ENTRY *Link;
|
||||
|
||||
Handle = NULL_HANDLE;
|
||||
*Interface = NULL;
|
||||
ProtNotify = Position->SearchKey;
|
||||
|
||||
//
|
||||
// If this is the first request, get the next handle
|
||||
//
|
||||
if (ProtNotify != NULL) {
|
||||
ASSERT(ProtNotify->Signature == PROTOCOL_NOTIFY_SIGNATURE);
|
||||
Position->SearchKey = NULL;
|
||||
|
||||
//
|
||||
// If not at the end of the list, get the next handle
|
||||
//
|
||||
Link = ProtNotify->Position->ForwardLink;
|
||||
if (Link != &ProtNotify->Protocol->Protocols) {
|
||||
Prot = CR (Link, PROTOCOL_INTERFACE, ByProtocol, PROTOCOL_INTERFACE_SIGNATURE);
|
||||
Handle = (IHANDLE *) Prot->Handle;
|
||||
*Interface = Prot->Interface;
|
||||
}
|
||||
}
|
||||
|
||||
return Handle;
|
||||
}
|
||||
|
||||
|
||||
STATIC
|
||||
IHANDLE *
|
||||
CoreGetNextLocateByProtocol (
|
||||
IN OUT LOCATE_POSITION *Position,
|
||||
OUT VOID **Interface
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Routine to get the next Handle, when you are searching for a given protocol.
|
||||
|
||||
Arguments:
|
||||
|
||||
Position - Information about which Handle to seach for.
|
||||
|
||||
Interface - Return the interface structure for the matching protocol.
|
||||
|
||||
Returns:
|
||||
IHANDLE - An IHANDLE is returned if the next Position is not the end of the
|
||||
list. A NULL_HANDLE is returned if it's the end of the list.
|
||||
|
||||
--*/
|
||||
{
|
||||
IHANDLE *Handle;
|
||||
LIST_ENTRY *Link;
|
||||
PROTOCOL_INTERFACE *Prot;
|
||||
|
||||
Handle = NULL_HANDLE;
|
||||
*Interface = NULL;
|
||||
for (; ;) {
|
||||
//
|
||||
// Next entry
|
||||
//
|
||||
Link = Position->Position->ForwardLink;
|
||||
Position->Position = Link;
|
||||
|
||||
//
|
||||
// If not at the end, return the handle
|
||||
//
|
||||
if (Link == &Position->ProtEntry->Protocols) {
|
||||
Handle = NULL_HANDLE;
|
||||
break;
|
||||
}
|
||||
|
||||
//
|
||||
// Get the handle
|
||||
//
|
||||
Prot = CR(Link, PROTOCOL_INTERFACE, ByProtocol, PROTOCOL_INTERFACE_SIGNATURE);
|
||||
Handle = (IHANDLE *) Prot->Handle;
|
||||
*Interface = Prot->Interface;
|
||||
|
||||
//
|
||||
// If this handle has not been returned this request, then
|
||||
// return it now
|
||||
//
|
||||
if (Handle->LocateRequest != mEfiLocateHandleRequest) {
|
||||
Handle->LocateRequest = mEfiLocateHandleRequest;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return Handle;
|
||||
}
|
||||
|
||||
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
CoreLocateDevicePath (
|
||||
IN EFI_GUID *Protocol,
|
||||
IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath,
|
||||
OUT EFI_HANDLE *Device
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Locates the handle to a device on the device path that best matches the specified protocol.
|
||||
|
||||
Arguments:
|
||||
|
||||
Protocol - The protocol to search for.
|
||||
DevicePath - On input, a pointer to a pointer to the device path. On output, the device
|
||||
path pointer is modified to point to the remaining part of the devicepath.
|
||||
Device - A pointer to the returned device handle.
|
||||
|
||||
Returns:
|
||||
|
||||
EFI_SUCCESS - The resulting handle was returned.
|
||||
EFI_NOT_FOUND - No handles matched the search.
|
||||
EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
|
||||
|
||||
--*/
|
||||
{
|
||||
INTN SourceSize;
|
||||
INTN Size;
|
||||
INTN BestMatch;
|
||||
UINTN HandleCount;
|
||||
UINTN Index;
|
||||
EFI_STATUS Status;
|
||||
EFI_HANDLE *Handles;
|
||||
EFI_HANDLE Handle;
|
||||
EFI_DEVICE_PATH_PROTOCOL *SourcePath;
|
||||
EFI_DEVICE_PATH_PROTOCOL *TmpDevicePath;
|
||||
|
||||
if (Protocol == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if ((DevicePath == NULL) || (*DevicePath == NULL)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (Device == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
*Device = NULL_HANDLE;
|
||||
SourcePath = *DevicePath;
|
||||
SourceSize = CoreDevicePathSize (SourcePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL);
|
||||
|
||||
//
|
||||
// The source path can only have 1 instance
|
||||
//
|
||||
if (CoreIsDevicePathMultiInstance (SourcePath)) {
|
||||
DEBUG((EFI_D_ERROR, "LocateDevicePath: Device path has too many instances\n"));
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// Get a list of all handles that support the requested protocol
|
||||
//
|
||||
Status = CoreLocateHandleBuffer (ByProtocol, Protocol, NULL, &HandleCount, &Handles);
|
||||
if (EFI_ERROR (Status) || HandleCount == 0) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
BestMatch = -1;
|
||||
for(Index = 0; Index < HandleCount; Index += 1) {
|
||||
Handle = Handles[Index];
|
||||
Status = CoreHandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID **)&TmpDevicePath);
|
||||
if (EFI_ERROR (Status)) {
|
||||
//
|
||||
// If this handle doesn't support device path, then skip it
|
||||
//
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// Check if DevicePath is first part of SourcePath
|
||||
//
|
||||
Size = CoreDevicePathSize (TmpDevicePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL);
|
||||
if ((Size <= SourceSize) && CompareMem (SourcePath, TmpDevicePath, Size) == 0) {
|
||||
//
|
||||
// If the size is equal to the best match, then we
|
||||
// have a duplice device path for 2 different device
|
||||
// handles
|
||||
//
|
||||
ASSERT (Size != BestMatch);
|
||||
|
||||
//
|
||||
// We've got a match, see if it's the best match so far
|
||||
//
|
||||
if (Size > BestMatch) {
|
||||
BestMatch = Size;
|
||||
*Device = Handle;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CoreFreePool (Handles);
|
||||
|
||||
//
|
||||
// If there wasn't any match, then no parts of the device path was found.
|
||||
// Which is strange since there is likely a "root level" device path in the system.
|
||||
//
|
||||
if (BestMatch == -1) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
//
|
||||
// Return the remaining part of the device path
|
||||
//
|
||||
*DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) (((UINT8 *) SourcePath) + BestMatch);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
CoreLocateProtocol (
|
||||
IN EFI_GUID *Protocol,
|
||||
IN VOID *Registration OPTIONAL,
|
||||
OUT VOID **Interface
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Return the first Protocol Interface that matches the Protocol GUID. If
|
||||
Registration is pasased in return a Protocol Instance that was just add
|
||||
to the system. If Retistration is NULL return the first Protocol Interface
|
||||
you find.
|
||||
|
||||
Arguments:
|
||||
|
||||
Protocol - The protocol to search for
|
||||
|
||||
Registration - Optional Registration Key returned from RegisterProtocolNotify()
|
||||
|
||||
Interface - Return the Protocol interface (instance).
|
||||
|
||||
Returns:
|
||||
|
||||
EFI_SUCCESS - If a valid Interface is returned
|
||||
|
||||
EFI_INVALID_PARAMETER - Invalid parameter
|
||||
|
||||
EFI_NOT_FOUND - Protocol interface not found
|
||||
|
||||
--*/
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
LOCATE_POSITION Position;
|
||||
PROTOCOL_NOTIFY *ProtNotify;
|
||||
IHANDLE *Handle;
|
||||
|
||||
if (Interface == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (Protocol == NULL) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
*Interface = NULL;
|
||||
Status = EFI_SUCCESS;
|
||||
|
||||
//
|
||||
// Set initial position
|
||||
//
|
||||
Position.Protocol = Protocol;
|
||||
Position.SearchKey = Registration;
|
||||
Position.Position = &gHandleList;
|
||||
|
||||
//
|
||||
// Lock the protocol database
|
||||
//
|
||||
CoreAcquireProtocolLock ();
|
||||
|
||||
mEfiLocateHandleRequest += 1;
|
||||
|
||||
if (NULL == Registration) {
|
||||
//
|
||||
// Look up the protocol entry and set the head pointer
|
||||
//
|
||||
Position.ProtEntry = CoreFindProtocolEntry (Protocol, FALSE);
|
||||
if (Position.ProtEntry == NULL) {
|
||||
Status = EFI_NOT_FOUND;
|
||||
goto Done;
|
||||
}
|
||||
Position.Position = &Position.ProtEntry->Protocols;
|
||||
|
||||
Handle = CoreGetNextLocateByProtocol (&Position, Interface);
|
||||
} else {
|
||||
Handle = CoreGetNextLocateByRegisterNotify (&Position, Interface);
|
||||
}
|
||||
|
||||
if (NULL == Handle) {
|
||||
Status = EFI_NOT_FOUND;
|
||||
} else if (NULL != Registration) {
|
||||
//
|
||||
// If this is a search by register notify and a handle was
|
||||
// returned, update the register notification position
|
||||
//
|
||||
ProtNotify = Registration;
|
||||
ProtNotify->Position = ProtNotify->Position->ForwardLink;
|
||||
}
|
||||
|
||||
Done:
|
||||
CoreReleaseProtocolLock ();
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
CoreLocateHandleBuffer (
|
||||
IN EFI_LOCATE_SEARCH_TYPE SearchType,
|
||||
IN EFI_GUID *Protocol OPTIONAL,
|
||||
IN VOID *SearchKey OPTIONAL,
|
||||
IN OUT UINTN *NumberHandles,
|
||||
OUT EFI_HANDLE **Buffer
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Function returns an array of handles that support the requested protocol
|
||||
in a buffer allocated from pool. This is a version of CoreLocateHandle()
|
||||
that allocates a buffer for the caller.
|
||||
|
||||
Arguments:
|
||||
|
||||
SearchType - Specifies which handle(s) are to be returned.
|
||||
Protocol - Provides the protocol to search by.
|
||||
This parameter is only valid for SearchType ByProtocol.
|
||||
SearchKey - Supplies the search key depending on the SearchType.
|
||||
NumberHandles - The number of handles returned in Buffer.
|
||||
Buffer - A pointer to the buffer to return the requested array of
|
||||
handles that support Protocol.
|
||||
|
||||
Returns:
|
||||
|
||||
EFI_SUCCESS - The result array of handles was returned.
|
||||
EFI_NOT_FOUND - No handles match the search.
|
||||
EFI_OUT_OF_RESOURCES - There is not enough pool memory to store the matching results.
|
||||
EFI_INVALID_PARAMETER - Invalid parameter
|
||||
|
||||
--*/
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINTN BufferSize;
|
||||
|
||||
if (NumberHandles == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (Buffer == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
BufferSize = 0;
|
||||
*NumberHandles = 0;
|
||||
*Buffer = NULL;
|
||||
Status = CoreLocateHandle (
|
||||
SearchType,
|
||||
Protocol,
|
||||
SearchKey,
|
||||
&BufferSize,
|
||||
*Buffer
|
||||
);
|
||||
//
|
||||
// LocateHandleBuffer() returns incorrect status code if SearchType is
|
||||
// invalid.
|
||||
//
|
||||
// Add code to correctly handle expected errors from CoreLocateHandle().
|
||||
//
|
||||
if (EFI_ERROR(Status) && Status != EFI_BUFFER_TOO_SMALL) {
|
||||
if (Status != EFI_INVALID_PARAMETER) {
|
||||
Status = EFI_NOT_FOUND;
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
||||
*Buffer = CoreAllocateBootServicesPool (BufferSize);
|
||||
if (*Buffer == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
Status = CoreLocateHandle (
|
||||
SearchType,
|
||||
Protocol,
|
||||
SearchKey,
|
||||
&BufferSize,
|
||||
*Buffer
|
||||
);
|
||||
|
||||
*NumberHandles = BufferSize/sizeof(EFI_HANDLE);
|
||||
if (EFI_ERROR(Status)) {
|
||||
*NumberHandles = 0;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user