summaryrefslogtreecommitdiff
path: root/MdeModulePkg/Core/Dxe/Hand
diff options
context:
space:
mode:
authorkx <kx@radix.pro>2024-06-04 06:43:08 +0300
committerkx <kx@radix.pro>2024-06-04 06:43:08 +0300
commit7e2ccccace24636f29ddc210b94606abd4c7e42b (patch)
tree545d43ea12671048956cafeb12303e84d601e571 /MdeModulePkg/Core/Dxe/Hand
parent27b044605cd5f6b33a3d231576003850b3fe305b (diff)
downloadedk2-trunk.tar.xz
Renormalized end-of-lines from master@27b044605cd5f6b33a3d231576003850b3fe305btrunk
Diffstat (limited to 'MdeModulePkg/Core/Dxe/Hand')
-rw-r--r--MdeModulePkg/Core/Dxe/Hand/DriverSupport.c1988
-rw-r--r--MdeModulePkg/Core/Dxe/Hand/Handle.c3248
-rw-r--r--MdeModulePkg/Core/Dxe/Hand/Handle.h504
-rw-r--r--MdeModulePkg/Core/Dxe/Hand/Locate.c1482
-rw-r--r--MdeModulePkg/Core/Dxe/Hand/Notify.c556
5 files changed, 3889 insertions, 3889 deletions
diff --git a/MdeModulePkg/Core/Dxe/Hand/DriverSupport.c b/MdeModulePkg/Core/Dxe/Hand/DriverSupport.c
index 64d7474f15..5ae6ce9448 100644
--- a/MdeModulePkg/Core/Dxe/Hand/DriverSupport.c
+++ b/MdeModulePkg/Core/Dxe/Hand/DriverSupport.c
@@ -1,994 +1,994 @@
-/** @file
- Support functions to connect/disconnect UEFI Driver model Protocol
-
-Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#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
- //
- CoreAcquireProtocolLock ();
-
- Status = CoreValidateHandle (ControllerHandle);
-
- CoreReleaseProtocolLock ();
-
- 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
- //
- CoreAcquireProtocolLock ();
-
- Status = CoreValidateHandle (DriverBindingHandle);
-
- CoreReleaseProtocolLock ();
-
- 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
- //
- Status = CoreLocateProtocol (
- &gEfiDriverFamilyOverrideProtocolGuid,
- NULL,
- (VOID **)&DriverFamilyOverride
- );
- while (!EFI_ERROR (Status) && (DriverFamilyOverride != NULL)) {
- 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_DRIVER_BINDING_SUPPORT_BEGIN (DriverBinding->DriverBindingHandle, ControllerHandle);
- Status = DriverBinding->Supported (
- DriverBinding,
- ControllerHandle,
- RemainingDevicePath
- );
- PERF_DRIVER_BINDING_SUPPORT_END (DriverBinding->DriverBindingHandle, ControllerHandle);
- 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_DRIVER_BINDING_START_BEGIN (DriverBinding->DriverBindingHandle, ControllerHandle);
- Status = DriverBinding->Start (
- DriverBinding,
- ControllerHandle,
- RemainingDevicePath
- );
- PERF_DRIVER_BINDING_START_END (DriverBinding->DriverBindingHandle, ControllerHandle);
-
- 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
- //
- CoreAcquireProtocolLock ();
-
- Status = CoreValidateHandle (ControllerHandle);
- if (EFI_ERROR (Status)) {
- CoreReleaseProtocolLock ();
- return Status;
- }
-
- //
- // Make sure ChildHandle is valid if it is not NULL
- //
- if (ChildHandle != NULL) {
- Status = CoreValidateHandle (ChildHandle);
- if (EFI_ERROR (Status)) {
- CoreReleaseProtocolLock ();
- return Status;
- }
- }
-
- CoreReleaseProtocolLock ();
-
- 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;
-}
+/** @file
+ Support functions to connect/disconnect UEFI Driver model Protocol
+
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#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
+ //
+ CoreAcquireProtocolLock ();
+
+ Status = CoreValidateHandle (ControllerHandle);
+
+ CoreReleaseProtocolLock ();
+
+ 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
+ //
+ CoreAcquireProtocolLock ();
+
+ Status = CoreValidateHandle (DriverBindingHandle);
+
+ CoreReleaseProtocolLock ();
+
+ 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
+ //
+ Status = CoreLocateProtocol (
+ &gEfiDriverFamilyOverrideProtocolGuid,
+ NULL,
+ (VOID **)&DriverFamilyOverride
+ );
+ while (!EFI_ERROR (Status) && (DriverFamilyOverride != NULL)) {
+ 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_DRIVER_BINDING_SUPPORT_BEGIN (DriverBinding->DriverBindingHandle, ControllerHandle);
+ Status = DriverBinding->Supported (
+ DriverBinding,
+ ControllerHandle,
+ RemainingDevicePath
+ );
+ PERF_DRIVER_BINDING_SUPPORT_END (DriverBinding->DriverBindingHandle, ControllerHandle);
+ 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_DRIVER_BINDING_START_BEGIN (DriverBinding->DriverBindingHandle, ControllerHandle);
+ Status = DriverBinding->Start (
+ DriverBinding,
+ ControllerHandle,
+ RemainingDevicePath
+ );
+ PERF_DRIVER_BINDING_START_END (DriverBinding->DriverBindingHandle, ControllerHandle);
+
+ 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
+ //
+ CoreAcquireProtocolLock ();
+
+ Status = CoreValidateHandle (ControllerHandle);
+ if (EFI_ERROR (Status)) {
+ CoreReleaseProtocolLock ();
+ return Status;
+ }
+
+ //
+ // Make sure ChildHandle is valid if it is not NULL
+ //
+ if (ChildHandle != NULL) {
+ Status = CoreValidateHandle (ChildHandle);
+ if (EFI_ERROR (Status)) {
+ CoreReleaseProtocolLock ();
+ return Status;
+ }
+ }
+
+ CoreReleaseProtocolLock ();
+
+ 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;
+}
diff --git a/MdeModulePkg/Core/Dxe/Hand/Handle.c b/MdeModulePkg/Core/Dxe/Hand/Handle.c
index 24e4fbf5f3..02762f2100 100644
--- a/MdeModulePkg/Core/Dxe/Hand/Handle.c
+++ b/MdeModulePkg/Core/Dxe/Hand/Handle.c
@@ -1,1624 +1,1624 @@
-/** @file
- UEFI handle & protocol handling.
-
-Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include "DxeMain.h"
-#include "Handle.h"
-
-//
-// mProtocolDatabase - A list of all protocols in the system. (simple list for now)
-// gHandleList - A list of all the handles in the system
-// gProtocolDatabaseLock - Lock to protect the mProtocolDatabase
-// gHandleDatabaseKey - The Key to show that the handle has been created/modified
-//
-LIST_ENTRY mProtocolDatabase = INITIALIZE_LIST_HEAD_VARIABLE (mProtocolDatabase);
-LIST_ENTRY gHandleList = INITIALIZE_LIST_HEAD_VARIABLE (gHandleList);
-EFI_LOCK gProtocolDatabaseLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY);
-UINT64 gHandleDatabaseKey = 0;
-
-/**
- Acquire lock on gProtocolDatabaseLock.
-
-**/
-VOID
-CoreAcquireProtocolLock (
- VOID
- )
-{
- CoreAcquireLock (&gProtocolDatabaseLock);
-}
-
-/**
- Release lock on gProtocolDatabaseLock.
-
-**/
-VOID
-CoreReleaseProtocolLock (
- VOID
- )
-{
- CoreReleaseLock (&gProtocolDatabaseLock);
-}
-
-/**
- Check whether a handle is a valid EFI_HANDLE
- The gProtocolDatabaseLock must be owned
-
- @param UserHandle The handle to check
-
- @retval EFI_INVALID_PARAMETER The handle is NULL or not a valid EFI_HANDLE.
- @retval EFI_SUCCESS The handle is valid EFI_HANDLE.
-
-**/
-EFI_STATUS
-CoreValidateHandle (
- IN EFI_HANDLE UserHandle
- )
-{
- IHANDLE *Handle;
- LIST_ENTRY *Link;
-
- if (UserHandle == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- ASSERT_LOCKED (&gProtocolDatabaseLock);
-
- for (Link = gHandleList.BackLink; Link != &gHandleList; Link = Link->BackLink) {
- Handle = CR (Link, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE);
- if (Handle == (IHANDLE *)UserHandle) {
- return EFI_SUCCESS;
- }
- }
-
- return EFI_INVALID_PARAMETER;
-}
-
-/**
- Finds the protocol entry for the requested protocol.
- The gProtocolDatabaseLock must be owned
-
- @param Protocol The ID of the protocol
- @param Create Create a new entry if not found
-
- @return Protocol entry
-
-**/
-PROTOCOL_ENTRY *
-CoreFindProtocolEntry (
- IN EFI_GUID *Protocol,
- IN BOOLEAN Create
- )
-{
- LIST_ENTRY *Link;
- PROTOCOL_ENTRY *Item;
- PROTOCOL_ENTRY *ProtEntry;
-
- ASSERT_LOCKED (&gProtocolDatabaseLock);
-
- //
- // Search the database for the matching GUID
- //
-
- ProtEntry = NULL;
- for (Link = mProtocolDatabase.ForwardLink;
- Link != &mProtocolDatabase;
- Link = Link->ForwardLink)
- {
- Item = CR (Link, PROTOCOL_ENTRY, AllEntries, PROTOCOL_ENTRY_SIGNATURE);
- if (CompareGuid (&Item->ProtocolID, Protocol)) {
- //
- // This is the protocol entry
- //
-
- ProtEntry = Item;
- break;
- }
- }
-
- //
- // If the protocol entry was not found and Create is TRUE, then
- // allocate a new entry
- //
- if ((ProtEntry == NULL) && Create) {
- ProtEntry = AllocatePool (sizeof (PROTOCOL_ENTRY));
-
- if (ProtEntry != NULL) {
- //
- // Initialize new protocol entry structure
- //
- ProtEntry->Signature = PROTOCOL_ENTRY_SIGNATURE;
- CopyGuid ((VOID *)&ProtEntry->ProtocolID, Protocol);
- InitializeListHead (&ProtEntry->Protocols);
- InitializeListHead (&ProtEntry->Notify);
-
- //
- // Add it to protocol database
- //
- InsertTailList (&mProtocolDatabase, &ProtEntry->AllEntries);
- }
- }
-
- return ProtEntry;
-}
-
-/**
- Finds the protocol instance for the requested handle and protocol.
- Note: This function doesn't do parameters checking, it's caller's responsibility
- to pass in valid parameters.
-
- @param Handle The handle to search the protocol on
- @param Protocol GUID of the protocol
- @param Interface The interface for the protocol being searched
-
- @return Protocol instance (NULL: Not found)
-
-**/
-PROTOCOL_INTERFACE *
-CoreFindProtocolInterface (
- IN IHANDLE *Handle,
- IN EFI_GUID *Protocol,
- IN VOID *Interface
- )
-{
- PROTOCOL_INTERFACE *Prot;
- PROTOCOL_ENTRY *ProtEntry;
- LIST_ENTRY *Link;
-
- ASSERT_LOCKED (&gProtocolDatabaseLock);
- Prot = NULL;
-
- //
- // Lookup the protocol entry for this protocol ID
- //
-
- ProtEntry = CoreFindProtocolEntry (Protocol, FALSE);
- if (ProtEntry != NULL) {
- //
- // Look at each protocol interface for any matches
- //
- for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
- //
- // If this protocol interface matches, remove it
- //
- Prot = CR (Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
- if ((Prot->Interface == Interface) && (Prot->Protocol == ProtEntry)) {
- break;
- }
-
- Prot = NULL;
- }
- }
-
- return Prot;
-}
-
-/**
- Check if the given device path is already installed.
-
- @param DevicePath The given device path
-
- @retval TRUE The device path is already installed
- @retval FALSE The device path is not installed
-
-**/
-BOOLEAN
-IsDevicePathInstalled (
- IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
- )
-{
- UINTN SourceSize;
- UINTN Size;
- BOOLEAN Found;
- LIST_ENTRY *Link;
- PROTOCOL_ENTRY *ProtEntry;
- PROTOCOL_INTERFACE *Prot;
-
- if (DevicePath == NULL) {
- return FALSE;
- }
-
- Found = FALSE;
- SourceSize = GetDevicePathSize (DevicePath);
- ASSERT (SourceSize >= END_DEVICE_PATH_LENGTH);
-
- CoreAcquireProtocolLock ();
- //
- // Look up the protocol entry
- //
- ProtEntry = CoreFindProtocolEntry (&gEfiDevicePathProtocolGuid, FALSE);
- if (ProtEntry == NULL) {
- goto Done;
- }
-
- for (Link = ProtEntry->Protocols.ForwardLink; Link != &ProtEntry->Protocols; Link = Link->ForwardLink) {
- //
- // Loop on the DevicePathProtocol interfaces
- //
- Prot = CR (Link, PROTOCOL_INTERFACE, ByProtocol, PROTOCOL_INTERFACE_SIGNATURE);
-
- //
- // Check if DevicePath is same as this interface
- //
- Size = GetDevicePathSize (Prot->Interface);
- ASSERT (Size >= END_DEVICE_PATH_LENGTH);
- if ((Size == SourceSize) && (CompareMem (DevicePath, Prot->Interface, Size - END_DEVICE_PATH_LENGTH) == 0)) {
- Found = TRUE;
- break;
- }
- }
-
-Done:
- CoreReleaseProtocolLock ();
- return Found;
-}
-
-/**
- Removes an event from a register protocol notify list on a protocol.
-
- @param Event The event to search for in the protocol
- database.
-
- @return EFI_SUCCESS if the event was found and removed.
- @return EFI_NOT_FOUND if the event was not found in the protocl database.
-
-**/
-EFI_STATUS
-CoreUnregisterProtocolNotifyEvent (
- IN EFI_EVENT Event
- )
-{
- LIST_ENTRY *Link;
- PROTOCOL_ENTRY *ProtEntry;
- LIST_ENTRY *NotifyLink;
- PROTOCOL_NOTIFY *ProtNotify;
-
- CoreAcquireProtocolLock ();
-
- for ( Link = mProtocolDatabase.ForwardLink;
- Link != &mProtocolDatabase;
- Link = Link->ForwardLink)
- {
- ProtEntry = CR (Link, PROTOCOL_ENTRY, AllEntries, PROTOCOL_ENTRY_SIGNATURE);
-
- for ( NotifyLink = ProtEntry->Notify.ForwardLink;
- NotifyLink != &ProtEntry->Notify;
- NotifyLink = NotifyLink->ForwardLink)
- {
- ProtNotify = CR (NotifyLink, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE);
-
- if (ProtNotify->Event == Event) {
- RemoveEntryList (&ProtNotify->Link);
- CoreFreePool (ProtNotify);
- CoreReleaseProtocolLock ();
- return EFI_SUCCESS;
- }
- }
- }
-
- CoreReleaseProtocolLock ();
- return EFI_NOT_FOUND;
-}
-
-/**
- Removes all the events in the protocol database that match Event.
-
- @param Event The event to search for in the protocol
- database.
-
- @return EFI_SUCCESS when done searching the entire database.
-
-**/
-EFI_STATUS
-CoreUnregisterProtocolNotify (
- IN EFI_EVENT Event
- )
-{
- EFI_STATUS Status;
-
- do {
- Status = CoreUnregisterProtocolNotifyEvent (Event);
- } while (!EFI_ERROR (Status));
-
- return EFI_SUCCESS;
-}
-
-/**
- Wrapper function to CoreInstallProtocolInterfaceNotify. This is the public API which
- Calls the private one which contains a BOOLEAN parameter for notifications
-
- @param UserHandle The handle to install the protocol handler on,
- or NULL if a new handle is to be allocated
- @param Protocol The protocol to add to the handle
- @param InterfaceType Indicates whether Interface is supplied in
- native form.
- @param Interface The interface for the protocol being added
-
- @return Status code
-
-**/
-EFI_STATUS
-EFIAPI
-CoreInstallProtocolInterface (
- IN OUT EFI_HANDLE *UserHandle,
- IN EFI_GUID *Protocol,
- IN EFI_INTERFACE_TYPE InterfaceType,
- IN VOID *Interface
- )
-{
- return CoreInstallProtocolInterfaceNotify (
- UserHandle,
- Protocol,
- InterfaceType,
- Interface,
- TRUE
- );
-}
-
-/**
- Installs a protocol interface into the boot services environment.
-
- @param UserHandle The handle to install the protocol handler on,
- or NULL if a new handle is to be allocated
- @param Protocol The protocol to add to the handle
- @param InterfaceType Indicates whether Interface is supplied in
- native form.
- @param Interface The interface for the protocol being added
- @param Notify indicates whether notify the notification list
- for this protocol
-
- @retval EFI_INVALID_PARAMETER Invalid parameter
- @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
- @retval EFI_SUCCESS Protocol interface successfully installed
-
-**/
-EFI_STATUS
-CoreInstallProtocolInterfaceNotify (
- IN OUT EFI_HANDLE *UserHandle,
- IN EFI_GUID *Protocol,
- IN EFI_INTERFACE_TYPE InterfaceType,
- IN VOID *Interface,
- IN BOOLEAN Notify
- )
-{
- PROTOCOL_INTERFACE *Prot;
- PROTOCOL_ENTRY *ProtEntry;
- IHANDLE *Handle;
- EFI_STATUS Status;
- VOID *ExistingInterface;
-
- //
- // returns EFI_INVALID_PARAMETER if InterfaceType is invalid.
- // Also added check for invalid UserHandle and Protocol pointers.
- //
- if ((UserHandle == NULL) || (Protocol == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- if (InterfaceType != EFI_NATIVE_INTERFACE) {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // Print debug message
- //
- DEBUG ((DEBUG_INFO, "InstallProtocolInterface: %g %p\n", Protocol, Interface));
-
- Status = EFI_OUT_OF_RESOURCES;
- Prot = NULL;
- Handle = NULL;
-
- if (*UserHandle != NULL) {
- Status = CoreHandleProtocol (*UserHandle, Protocol, (VOID **)&ExistingInterface);
- if (!EFI_ERROR (Status)) {
- return EFI_INVALID_PARAMETER;
- }
- }
-
- //
- // Lock the protocol database
- //
- CoreAcquireProtocolLock ();
-
- //
- // Lookup the Protocol Entry for the requested protocol
- //
- ProtEntry = CoreFindProtocolEntry (Protocol, TRUE);
- if (ProtEntry == NULL) {
- goto Done;
- }
-
- //
- // Allocate a new protocol interface structure
- //
- Prot = AllocateZeroPool (sizeof (PROTOCOL_INTERFACE));
- if (Prot == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Done;
- }
-
- //
- // If caller didn't supply a handle, allocate a new one
- //
- Handle = (IHANDLE *)*UserHandle;
- if (Handle == NULL) {
- Handle = AllocateZeroPool (sizeof (IHANDLE));
- if (Handle == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Done;
- }
-
- //
- // Initialize new handler structure
- //
- Handle->Signature = EFI_HANDLE_SIGNATURE;
- InitializeListHead (&Handle->Protocols);
-
- //
- // Initialize the Key to show that the handle has been created/modified
- //
- gHandleDatabaseKey++;
- Handle->Key = gHandleDatabaseKey;
-
- //
- // Add this handle to the list global list of all handles
- // in the system
- //
- InsertTailList (&gHandleList, &Handle->AllHandles);
- } else {
- Status = CoreValidateHandle (Handle);
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "InstallProtocolInterface: input handle at 0x%x is invalid\n", Handle));
- goto Done;
- }
- }
-
- //
- // Each interface that is added must be unique
- //
- ASSERT (CoreFindProtocolInterface (Handle, Protocol, Interface) == NULL);
-
- //
- // Initialize the protocol interface structure
- //
- Prot->Signature = PROTOCOL_INTERFACE_SIGNATURE;
- Prot->Handle = Handle;
- Prot->Protocol = ProtEntry;
- Prot->Interface = Interface;
-
- //
- // Initalize OpenProtocol Data base
- //
- InitializeListHead (&Prot->OpenList);
- Prot->OpenListCount = 0;
-
- //
- // Add this protocol interface to the head of the supported
- // protocol list for this handle
- //
- InsertHeadList (&Handle->Protocols, &Prot->Link);
-
- //
- // Add this protocol interface to the tail of the
- // protocol entry
- //
- InsertTailList (&ProtEntry->Protocols, &Prot->ByProtocol);
-
- //
- // Notify the notification list for this protocol
- //
- if (Notify) {
- CoreNotifyProtocolEntry (ProtEntry);
- }
-
- Status = EFI_SUCCESS;
-
-Done:
- //
- // Done, unlock the database and return
- //
- CoreReleaseProtocolLock ();
- if (!EFI_ERROR (Status)) {
- //
- // Return the new handle back to the caller
- //
- *UserHandle = Handle;
- } else {
- //
- // There was an error, clean up
- //
- if (Prot != NULL) {
- CoreFreePool (Prot);
- }
-
- DEBUG ((DEBUG_ERROR, "InstallProtocolInterface: %g %p failed with %r\n", Protocol, Interface, Status));
- }
-
- return Status;
-}
-
-/**
- Installs a list of protocol interface into the boot services environment.
- This function calls InstallProtocolInterface() in a loop. If any error
- occures all the protocols added by this function are removed. This is
- basically a lib function to save space.
-
- @param Handle The pointer to a handle to install the new
- protocol interfaces on, or a pointer to NULL
- if a new handle is to be allocated.
- @param ... EFI_GUID followed by protocol instance. A NULL
- terminates the list. The pairs are the
- arguments to InstallProtocolInterface(). All the
- protocols are added to Handle.
-
- @retval EFI_SUCCESS All the protocol interface was installed.
- @retval EFI_OUT_OF_RESOURCES There was not enough memory in pool to install all the protocols.
- @retval EFI_ALREADY_STARTED A Device Path Protocol instance was passed in that is already present in
- the handle database.
- @retval EFI_INVALID_PARAMETER Handle is NULL.
- @retval EFI_INVALID_PARAMETER Protocol is already installed on the handle specified by Handle.
-
-**/
-EFI_STATUS
-EFIAPI
-CoreInstallMultipleProtocolInterfaces (
- IN OUT EFI_HANDLE *Handle,
- ...
- )
-{
- VA_LIST Args;
- EFI_STATUS Status;
- EFI_GUID *Protocol;
- VOID *Interface;
- EFI_TPL OldTpl;
- UINTN Index;
- EFI_HANDLE OldHandle;
-
- if (Handle == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // Syncronize with notifcations.
- //
- OldTpl = CoreRaiseTpl (TPL_NOTIFY);
- OldHandle = *Handle;
-
- //
- // Check for duplicate device path and install the protocol interfaces
- //
- VA_START (Args, Handle);
- for (Index = 0, Status = EFI_SUCCESS; !EFI_ERROR (Status); Index++) {
- //
- // If protocol is NULL, then it's the end of the list
- //
- Protocol = VA_ARG (Args, EFI_GUID *);
- if (Protocol == NULL) {
- break;
- }
-
- Interface = VA_ARG (Args, VOID *);
-
- //
- // Make sure you are installing on top a device path that has already been added.
- //
- if (CompareGuid (Protocol, &gEfiDevicePathProtocolGuid) &&
- IsDevicePathInstalled (Interface))
- {
- Status = EFI_ALREADY_STARTED;
- continue;
- }
-
- //
- // Install it
- //
- Status = CoreInstallProtocolInterface (Handle, Protocol, EFI_NATIVE_INTERFACE, Interface);
- }
-
- VA_END (Args);
-
- //
- // If there was an error, remove all the interfaces that were installed without any errors
- //
- if (EFI_ERROR (Status)) {
- //
- // Reset the va_arg back to the first argument.
- //
- VA_START (Args, Handle);
- for ( ; Index > 1; Index--) {
- Protocol = VA_ARG (Args, EFI_GUID *);
- Interface = VA_ARG (Args, VOID *);
- CoreUninstallProtocolInterface (*Handle, Protocol, Interface);
- }
-
- VA_END (Args);
-
- *Handle = OldHandle;
- }
-
- //
- // Done
- //
- CoreRestoreTpl (OldTpl);
- return Status;
-}
-
-/**
- Attempts to disconnect all drivers that are using the protocol interface being queried.
- If failed, reconnect all drivers disconnected.
- Note: This function doesn't do parameters checking, it's caller's responsibility
- to pass in valid parameters.
-
- @param UserHandle The handle on which the protocol is installed
- @param Prot The protocol to disconnect drivers from
-
- @retval EFI_SUCCESS Drivers using the protocol interface are all
- disconnected
- @retval EFI_ACCESS_DENIED Failed to disconnect one or all of the drivers
-
-**/
-EFI_STATUS
-CoreDisconnectControllersUsingProtocolInterface (
- IN EFI_HANDLE UserHandle,
- IN PROTOCOL_INTERFACE *Prot
- )
-{
- EFI_STATUS Status;
- BOOLEAN ItemFound;
- LIST_ENTRY *Link;
- OPEN_PROTOCOL_DATA *OpenData;
-
- Status = EFI_SUCCESS;
-
- //
- // Attempt to disconnect all drivers from this protocol interface
- //
- do {
- ItemFound = FALSE;
- for (Link = Prot->OpenList.ForwardLink; Link != &Prot->OpenList; Link = Link->ForwardLink) {
- OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
- if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
- CoreReleaseProtocolLock ();
- Status = CoreDisconnectController (UserHandle, OpenData->AgentHandle, NULL);
- CoreAcquireProtocolLock ();
- if (!EFI_ERROR (Status)) {
- ItemFound = TRUE;
- }
-
- break;
- }
- }
- } while (ItemFound);
-
- if (!EFI_ERROR (Status)) {
- //
- // Attempt to remove BY_HANDLE_PROTOOCL and GET_PROTOCOL and TEST_PROTOCOL Open List items
- //
- for (Link = Prot->OpenList.ForwardLink; Link != &Prot->OpenList;) {
- OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
- if ((OpenData->Attributes &
- (EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL | EFI_OPEN_PROTOCOL_GET_PROTOCOL | EFI_OPEN_PROTOCOL_TEST_PROTOCOL)) != 0)
- {
- Link = RemoveEntryList (&OpenData->Link);
- Prot->OpenListCount--;
- CoreFreePool (OpenData);
- } else {
- Link = Link->ForwardLink;
- }
- }
- }
-
- //
- // If there are errors or still has open items in the list, then reconnect all the drivers and return an error
- //
- if (EFI_ERROR (Status) || (Prot->OpenListCount > 0)) {
- CoreReleaseProtocolLock ();
- CoreConnectController (UserHandle, NULL, NULL, TRUE);
- CoreAcquireProtocolLock ();
- Status = EFI_ACCESS_DENIED;
- }
-
- return Status;
-}
-
-/**
- Uninstalls all instances of a protocol:interfacer from a handle.
- If the last protocol interface is remove from the handle, the
- handle is freed.
-
- @param UserHandle The handle to remove the protocol handler from
- @param Protocol The protocol, of protocol:interface, to remove
- @param Interface The interface, of protocol:interface, to remove
-
- @retval EFI_INVALID_PARAMETER Protocol is NULL.
- @retval EFI_SUCCESS Protocol interface successfully uninstalled.
-
-**/
-EFI_STATUS
-EFIAPI
-CoreUninstallProtocolInterface (
- IN EFI_HANDLE UserHandle,
- IN EFI_GUID *Protocol,
- IN VOID *Interface
- )
-{
- EFI_STATUS Status;
- IHANDLE *Handle;
- PROTOCOL_INTERFACE *Prot;
-
- //
- // Check that Protocol is valid
- //
- if (Protocol == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // Lock the protocol database
- //
- CoreAcquireProtocolLock ();
-
- //
- // Check that UserHandle is a valid handle
- //
- Status = CoreValidateHandle (UserHandle);
- if (EFI_ERROR (Status)) {
- goto Done;
- }
-
- //
- // Check that Protocol exists on UserHandle, and Interface matches the interface in the database
- //
- Prot = CoreFindProtocolInterface (UserHandle, Protocol, Interface);
- if (Prot == NULL) {
- Status = EFI_NOT_FOUND;
- goto Done;
- }
-
- //
- // Attempt to disconnect all drivers that are using the protocol interface that is about to be removed
- //
- Status = CoreDisconnectControllersUsingProtocolInterface (
- UserHandle,
- Prot
- );
- if (EFI_ERROR (Status)) {
- //
- // One or more drivers refused to release, so return the error
- //
- goto Done;
- }
-
- //
- // Remove the protocol interface from the protocol
- //
- Status = EFI_NOT_FOUND;
- Handle = (IHANDLE *)UserHandle;
- Prot = CoreRemoveInterfaceFromProtocol (Handle, Protocol, Interface);
-
- if (Prot != NULL) {
- //
- // Update the Key to show that the handle has been created/modified
- //
- gHandleDatabaseKey++;
- Handle->Key = gHandleDatabaseKey;
-
- //
- // Remove the protocol interface from the handle
- //
- RemoveEntryList (&Prot->Link);
-
- //
- // Free the memory
- //
- Prot->Signature = 0;
- CoreFreePool (Prot);
- Status = EFI_SUCCESS;
- }
-
- //
- // If there are no more handlers for the handle, free the handle
- //
- if (IsListEmpty (&Handle->Protocols)) {
- Handle->Signature = 0;
- RemoveEntryList (&Handle->AllHandles);
- CoreFreePool (Handle);
- }
-
-Done:
- //
- // Done, unlock the database and return
- //
- CoreReleaseProtocolLock ();
- return Status;
-}
-
-/**
- Uninstalls a list of protocol interface in the boot services environment.
- This function calls UninstallProtocolInterface() in a loop. This is
- basically a lib function to save space.
-
- If any errors are generated while the protocol interfaces are being
- uninstalled, then the protocol interfaces uninstalled prior to the error will
- be reinstalled and EFI_INVALID_PARAMETER will be returned.
-
- @param Handle The handle to uninstall the protocol interfaces
- from.
- @param ... EFI_GUID followed by protocol instance. A NULL
- terminates the list. The pairs are the
- arguments to UninstallProtocolInterface(). All
- the protocols are added to Handle.
-
- @retval EFI_SUCCESS if all protocol interfaces where uninstalled.
- @retval EFI_INVALID_PARAMETER if any protocol interface could not be
- uninstalled and an attempt was made to
- reinstall previously uninstalled protocol
- interfaces.
-**/
-EFI_STATUS
-EFIAPI
-CoreUninstallMultipleProtocolInterfaces (
- IN EFI_HANDLE Handle,
- ...
- )
-{
- EFI_STATUS Status;
- VA_LIST Args;
- EFI_GUID *Protocol;
- VOID *Interface;
- UINTN Index;
-
- VA_START (Args, Handle);
- for (Index = 0, Status = EFI_SUCCESS; !EFI_ERROR (Status); Index++) {
- //
- // If protocol is NULL, then it's the end of the list
- //
- Protocol = VA_ARG (Args, EFI_GUID *);
- if (Protocol == NULL) {
- break;
- }
-
- Interface = VA_ARG (Args, VOID *);
-
- //
- // Uninstall it
- //
- Status = CoreUninstallProtocolInterface (Handle, Protocol, Interface);
- }
-
- VA_END (Args);
-
- //
- // If there was an error, add all the interfaces that were
- // uninstalled without any errors
- //
- if (EFI_ERROR (Status)) {
- //
- // Reset the va_arg back to the first argument.
- //
- VA_START (Args, Handle);
- for ( ; Index > 1; Index--) {
- Protocol = VA_ARG (Args, EFI_GUID *);
- Interface = VA_ARG (Args, VOID *);
- CoreInstallProtocolInterface (&Handle, Protocol, EFI_NATIVE_INTERFACE, Interface);
- }
-
- VA_END (Args);
- Status = EFI_INVALID_PARAMETER;
- }
-
- return Status;
-}
-
-/**
- Locate a certain GUID protocol interface in a Handle's protocols.
-
- @param UserHandle The handle to obtain the protocol interface on
- The caller must pass in a valid UserHandle that
- is checked with CoreValidateHandle().
- @param Protocol The GUID of the protocol
-
- @return The requested protocol interface for the handle
-
-**/
-STATIC
-PROTOCOL_INTERFACE *
-CoreGetProtocolInterface (
- IN EFI_HANDLE UserHandle,
- IN EFI_GUID *Protocol
- )
-{
- PROTOCOL_ENTRY *ProtEntry;
- PROTOCOL_INTERFACE *Prot;
- IHANDLE *Handle;
- LIST_ENTRY *Link;
-
- Handle = (IHANDLE *)UserHandle;
-
- //
- // Look at each protocol interface for a match
- //
- for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
- Prot = CR (Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
- ProtEntry = Prot->Protocol;
- if (CompareGuid (&ProtEntry->ProtocolID, Protocol)) {
- return Prot;
- }
- }
-
- return NULL;
-}
-
-/**
- Queries a handle to determine if it supports a specified protocol.
-
- @param UserHandle The handle being queried.
- @param Protocol The published unique identifier of the protocol.
- @param Interface Supplies the address where a pointer to the
- corresponding Protocol Interface is returned.
-
- @retval EFI_SUCCESS The interface information for the specified protocol was returned.
- @retval EFI_UNSUPPORTED The device does not support the specified protocol.
- @retval EFI_INVALID_PARAMETER Handle is NULL..
- @retval EFI_INVALID_PARAMETER Protocol is NULL.
- @retval EFI_INVALID_PARAMETER Interface is NULL.
-
-**/
-EFI_STATUS
-EFIAPI
-CoreHandleProtocol (
- IN EFI_HANDLE UserHandle,
- IN EFI_GUID *Protocol,
- OUT VOID **Interface
- )
-{
- return CoreOpenProtocol (
- UserHandle,
- Protocol,
- Interface,
- gDxeCoreImageHandle,
- NULL,
- EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
- );
-}
-
-/**
- Locates the installed protocol handler for the handle, and
- invokes it to obtain the protocol interface. Usage information
- is registered in the protocol data base.
-
- @param UserHandle The handle to obtain the protocol interface on
- @param Protocol The ID of the protocol
- @param Interface The location to return the protocol interface
- @param ImageHandle The handle of the Image that is opening the
- protocol interface specified by Protocol and
- Interface.
- @param ControllerHandle The controller handle that is requiring this
- interface.
- @param Attributes The open mode of the protocol interface
- specified by Handle and Protocol.
-
- @retval EFI_INVALID_PARAMETER Protocol is NULL.
- @retval EFI_SUCCESS Get the protocol interface.
-
-**/
-EFI_STATUS
-EFIAPI
-CoreOpenProtocol (
- IN EFI_HANDLE UserHandle,
- IN EFI_GUID *Protocol,
- OUT VOID **Interface OPTIONAL,
- IN EFI_HANDLE ImageHandle,
- IN EFI_HANDLE ControllerHandle,
- IN UINT32 Attributes
- )
-{
- EFI_STATUS Status;
- PROTOCOL_INTERFACE *Prot;
- LIST_ENTRY *Link;
- OPEN_PROTOCOL_DATA *OpenData;
- BOOLEAN ByDriver;
- BOOLEAN Exclusive;
- BOOLEAN Disconnect;
- BOOLEAN ExactMatch;
-
- //
- // Check for invalid Protocol
- //
- if (Protocol == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // Check for invalid Interface
- //
- if ((Attributes != EFI_OPEN_PROTOCOL_TEST_PROTOCOL) && (Interface == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // Lock the protocol database
- //
- CoreAcquireProtocolLock ();
-
- //
- // Check for invalid UserHandle
- //
- Status = CoreValidateHandle (UserHandle);
- if (EFI_ERROR (Status)) {
- goto Done;
- }
-
- //
- // Check for invalid Attributes
- //
- switch (Attributes) {
- case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER:
- Status = CoreValidateHandle (ImageHandle);
- if (EFI_ERROR (Status)) {
- goto Done;
- }
-
- Status = CoreValidateHandle (ControllerHandle);
- if (EFI_ERROR (Status)) {
- goto Done;
- }
-
- if (UserHandle == ControllerHandle) {
- Status = EFI_INVALID_PARAMETER;
- goto Done;
- }
-
- break;
- case EFI_OPEN_PROTOCOL_BY_DRIVER:
- case EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE:
- Status = CoreValidateHandle (ImageHandle);
- if (EFI_ERROR (Status)) {
- goto Done;
- }
-
- Status = CoreValidateHandle (ControllerHandle);
- if (EFI_ERROR (Status)) {
- goto Done;
- }
-
- break;
- case EFI_OPEN_PROTOCOL_EXCLUSIVE:
- Status = CoreValidateHandle (ImageHandle);
- if (EFI_ERROR (Status)) {
- goto Done;
- }
-
- break;
- case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL:
- case EFI_OPEN_PROTOCOL_GET_PROTOCOL:
- case EFI_OPEN_PROTOCOL_TEST_PROTOCOL:
- break;
- default:
- Status = EFI_INVALID_PARAMETER;
- goto Done;
- }
-
- //
- // Look at each protocol interface for a match
- //
- Prot = CoreGetProtocolInterface (UserHandle, Protocol);
- if (Prot == NULL) {
- Status = EFI_UNSUPPORTED;
- goto Done;
- }
-
- Status = EFI_SUCCESS;
-
- ByDriver = FALSE;
- Exclusive = FALSE;
- for ( Link = Prot->OpenList.ForwardLink; Link != &Prot->OpenList; Link = Link->ForwardLink) {
- OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
- ExactMatch = (BOOLEAN)((OpenData->AgentHandle == ImageHandle) &&
- (OpenData->Attributes == Attributes) &&
- (OpenData->ControllerHandle == ControllerHandle));
- if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
- ByDriver = TRUE;
- if (ExactMatch) {
- Status = EFI_ALREADY_STARTED;
- goto Done;
- }
- }
-
- if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_EXCLUSIVE) != 0) {
- Exclusive = TRUE;
- } else if (ExactMatch) {
- OpenData->OpenCount++;
- Status = EFI_SUCCESS;
- goto Done;
- }
- }
-
- //
- // ByDriver TRUE -> A driver is managing (UserHandle, Protocol)
- // ByDriver FALSE -> There are no drivers managing (UserHandle, Protocol)
- // Exclusive TRUE -> Something has exclusive access to (UserHandle, Protocol)
- // Exclusive FALSE -> Nothing has exclusive access to (UserHandle, Protocol)
- //
-
- switch (Attributes) {
- case EFI_OPEN_PROTOCOL_BY_DRIVER:
- if (Exclusive || ByDriver) {
- Status = EFI_ACCESS_DENIED;
- goto Done;
- }
-
- break;
- case EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE:
- case EFI_OPEN_PROTOCOL_EXCLUSIVE:
- if (Exclusive) {
- Status = EFI_ACCESS_DENIED;
- goto Done;
- }
-
- if (ByDriver) {
- do {
- Disconnect = FALSE;
- for (Link = Prot->OpenList.ForwardLink; Link != &Prot->OpenList; Link = Link->ForwardLink) {
- OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
- if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
- Disconnect = TRUE;
- CoreReleaseProtocolLock ();
- Status = CoreDisconnectController (UserHandle, OpenData->AgentHandle, NULL);
- CoreAcquireProtocolLock ();
- if (EFI_ERROR (Status)) {
- Status = EFI_ACCESS_DENIED;
- goto Done;
- } else {
- break;
- }
- }
- }
- } while (Disconnect);
- }
-
- break;
- case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER:
- case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL:
- case EFI_OPEN_PROTOCOL_GET_PROTOCOL:
- case EFI_OPEN_PROTOCOL_TEST_PROTOCOL:
- break;
- }
-
- if (ImageHandle == NULL) {
- Status = EFI_SUCCESS;
- goto Done;
- }
-
- //
- // Create new entry
- //
- OpenData = AllocatePool (sizeof (OPEN_PROTOCOL_DATA));
- if (OpenData == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- } else {
- OpenData->Signature = OPEN_PROTOCOL_DATA_SIGNATURE;
- OpenData->AgentHandle = ImageHandle;
- OpenData->ControllerHandle = ControllerHandle;
- OpenData->Attributes = Attributes;
- OpenData->OpenCount = 1;
- InsertTailList (&Prot->OpenList, &OpenData->Link);
- Prot->OpenListCount++;
- Status = EFI_SUCCESS;
- }
-
-Done:
-
- if (Attributes != EFI_OPEN_PROTOCOL_TEST_PROTOCOL) {
- //
- // Keep Interface unmodified in case of any Error
- // except EFI_ALREADY_STARTED and EFI_UNSUPPORTED.
- //
- if (!EFI_ERROR (Status) || (Status == EFI_ALREADY_STARTED)) {
- //
- // According to above logic, if 'Prot' is NULL, then the 'Status' must be
- // EFI_UNSUPPORTED. Here the 'Status' is not EFI_UNSUPPORTED, so 'Prot'
- // must be not NULL.
- //
- // The ASSERT here is for addressing a false positive NULL pointer
- // dereference issue raised from static analysis.
- //
- ASSERT (Prot != NULL);
- //
- // EFI_ALREADY_STARTED is not an error for bus driver.
- // Return the corresponding protocol interface.
- //
- *Interface = Prot->Interface;
- } else if (Status == EFI_UNSUPPORTED) {
- //
- // Return NULL Interface if Unsupported Protocol.
- //
- *Interface = NULL;
- }
- }
-
- //
- // Done. Release the database lock and return
- //
- CoreReleaseProtocolLock ();
- return Status;
-}
-
-/**
- Closes a protocol on a handle that was opened using OpenProtocol().
-
- @param UserHandle The handle for the protocol interface that was
- previously opened with OpenProtocol(), and is
- now being closed.
- @param Protocol The published unique identifier of the protocol.
- It is the caller's responsibility to pass in a
- valid GUID.
- @param AgentHandle The handle of the agent that is closing the
- protocol interface.
- @param ControllerHandle If the agent that opened a protocol is a driver
- that follows the EFI Driver Model, then this
- parameter is the controller handle that required
- the protocol interface. If the agent does not
- follow the EFI Driver Model, then this parameter
- is optional and may be NULL.
-
- @retval EFI_SUCCESS The protocol instance was closed.
- @retval EFI_INVALID_PARAMETER Handle, AgentHandle or ControllerHandle is not a
- valid EFI_HANDLE.
- @retval EFI_NOT_FOUND Can not find the specified protocol or
- AgentHandle.
-
-**/
-EFI_STATUS
-EFIAPI
-CoreCloseProtocol (
- IN EFI_HANDLE UserHandle,
- IN EFI_GUID *Protocol,
- IN EFI_HANDLE AgentHandle,
- IN EFI_HANDLE ControllerHandle
- )
-{
- EFI_STATUS Status;
- PROTOCOL_INTERFACE *ProtocolInterface;
- LIST_ENTRY *Link;
- OPEN_PROTOCOL_DATA *OpenData;
-
- //
- // Lock the protocol database
- //
- CoreAcquireProtocolLock ();
-
- //
- // Check for invalid parameters
- //
- Status = CoreValidateHandle (UserHandle);
- if (EFI_ERROR (Status)) {
- goto Done;
- }
-
- Status = CoreValidateHandle (AgentHandle);
- if (EFI_ERROR (Status)) {
- goto Done;
- }
-
- if (ControllerHandle != NULL) {
- Status = CoreValidateHandle (ControllerHandle);
- if (EFI_ERROR (Status)) {
- goto Done;
- }
- }
-
- if (Protocol == NULL) {
- Status = EFI_INVALID_PARAMETER;
- goto Done;
- }
-
- //
- // Look at each protocol interface for a match
- //
- Status = EFI_NOT_FOUND;
- ProtocolInterface = CoreGetProtocolInterface (UserHandle, Protocol);
- if (ProtocolInterface == NULL) {
- goto Done;
- }
-
- //
- // Walk the Open data base looking for AgentHandle
- //
- Link = ProtocolInterface->OpenList.ForwardLink;
- while (Link != &ProtocolInterface->OpenList) {
- OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
- Link = Link->ForwardLink;
- if ((OpenData->AgentHandle == AgentHandle) && (OpenData->ControllerHandle == ControllerHandle)) {
- RemoveEntryList (&OpenData->Link);
- ProtocolInterface->OpenListCount--;
- CoreFreePool (OpenData);
- Status = EFI_SUCCESS;
- }
- }
-
-Done:
- //
- // Done. Release the database lock and return.
- //
- CoreReleaseProtocolLock ();
- return Status;
-}
-
-/**
- Return information about Opened protocols in the system
-
- @param UserHandle The handle to close the protocol interface on
- @param Protocol The ID of the protocol
- @param EntryBuffer A pointer to a buffer of open protocol information in the
- form of EFI_OPEN_PROTOCOL_INFORMATION_ENTRY structures.
- @param EntryCount Number of EntryBuffer entries
-
- @retval EFI_SUCCESS The open protocol information was returned in EntryBuffer,
- and the number of entries was returned EntryCount.
- @retval EFI_NOT_FOUND Handle does not support the protocol specified by Protocol.
- @retval EFI_OUT_OF_RESOURCES There are not enough resources available to allocate EntryBuffer.
-
-**/
-EFI_STATUS
-EFIAPI
-CoreOpenProtocolInformation (
- IN EFI_HANDLE UserHandle,
- IN EFI_GUID *Protocol,
- OUT EFI_OPEN_PROTOCOL_INFORMATION_ENTRY **EntryBuffer,
- OUT UINTN *EntryCount
- )
-{
- EFI_STATUS Status;
- PROTOCOL_INTERFACE *ProtocolInterface;
- LIST_ENTRY *Link;
- OPEN_PROTOCOL_DATA *OpenData;
- EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *Buffer;
- UINTN Count;
- UINTN Size;
-
- *EntryBuffer = NULL;
- *EntryCount = 0;
-
- //
- // Lock the protocol database
- //
- CoreAcquireProtocolLock ();
-
- //
- // Check for invalid UserHandle
- //
- Status = CoreValidateHandle (UserHandle);
- if (EFI_ERROR (Status)) {
- Status = EFI_NOT_FOUND;
- goto Done;
- }
-
- //
- // Look at each protocol interface for a match
- //
- Status = EFI_NOT_FOUND;
- ProtocolInterface = CoreGetProtocolInterface (UserHandle, Protocol);
- if (ProtocolInterface == NULL) {
- goto Done;
- }
-
- //
- // Count the number of Open Entries
- //
- for ( Link = ProtocolInterface->OpenList.ForwardLink, Count = 0;
- (Link != &ProtocolInterface->OpenList);
- Link = Link->ForwardLink )
- {
- Count++;
- }
-
- ASSERT (Count == ProtocolInterface->OpenListCount);
-
- if (Count == 0) {
- Size = sizeof (EFI_OPEN_PROTOCOL_INFORMATION_ENTRY);
- } else {
- Size = Count * sizeof (EFI_OPEN_PROTOCOL_INFORMATION_ENTRY);
- }
-
- Buffer = AllocatePool (Size);
- if (Buffer == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Done;
- }
-
- Status = EFI_SUCCESS;
- for ( Link = ProtocolInterface->OpenList.ForwardLink, Count = 0;
- (Link != &ProtocolInterface->OpenList);
- Link = Link->ForwardLink, Count++ )
- {
- OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
-
- Buffer[Count].AgentHandle = OpenData->AgentHandle;
- Buffer[Count].ControllerHandle = OpenData->ControllerHandle;
- Buffer[Count].Attributes = OpenData->Attributes;
- Buffer[Count].OpenCount = OpenData->OpenCount;
- }
-
- *EntryBuffer = Buffer;
- *EntryCount = Count;
-
-Done:
- //
- // Done. Release the database lock.
- //
- CoreReleaseProtocolLock ();
- return Status;
-}
-
-/**
- Retrieves the list of protocol interface GUIDs that are installed on a handle in a buffer allocated
- from pool.
-
- @param UserHandle The handle from which to retrieve the list of
- protocol interface GUIDs.
- @param ProtocolBuffer A pointer to the list of protocol interface GUID
- pointers that are installed on Handle.
- @param ProtocolBufferCount A pointer to the number of GUID pointers present
- in ProtocolBuffer.
-
- @retval EFI_SUCCESS The list of protocol interface GUIDs installed
- on Handle was returned in ProtocolBuffer. The
- number of protocol interface GUIDs was returned
- in ProtocolBufferCount.
- @retval EFI_INVALID_PARAMETER Handle is NULL.
- @retval EFI_INVALID_PARAMETER Handle is not a valid EFI_HANDLE.
- @retval EFI_INVALID_PARAMETER ProtocolBuffer is NULL.
- @retval EFI_INVALID_PARAMETER ProtocolBufferCount is NULL.
- @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the
- results.
-
-**/
-EFI_STATUS
-EFIAPI
-CoreProtocolsPerHandle (
- IN EFI_HANDLE UserHandle,
- OUT EFI_GUID ***ProtocolBuffer,
- OUT UINTN *ProtocolBufferCount
- )
-{
- EFI_STATUS Status;
- IHANDLE *Handle;
- PROTOCOL_INTERFACE *Prot;
- LIST_ENTRY *Link;
- UINTN ProtocolCount;
- EFI_GUID **Buffer;
-
- if (ProtocolBuffer == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- if (ProtocolBufferCount == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- *ProtocolBufferCount = 0;
-
- ProtocolCount = 0;
-
- CoreAcquireProtocolLock ();
-
- Status = CoreValidateHandle (UserHandle);
- if (EFI_ERROR (Status)) {
- goto Done;
- }
-
- Handle = (IHANDLE *)UserHandle;
-
- for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
- ProtocolCount++;
- }
-
- //
- // If there are no protocol interfaces installed on Handle, then Handle is not a valid EFI_HANDLE
- //
- if (ProtocolCount == 0) {
- Status = EFI_INVALID_PARAMETER;
- goto Done;
- }
-
- Buffer = AllocatePool (sizeof (EFI_GUID *) * ProtocolCount);
- if (Buffer == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Done;
- }
-
- *ProtocolBuffer = Buffer;
- *ProtocolBufferCount = ProtocolCount;
-
- for ( Link = Handle->Protocols.ForwardLink, ProtocolCount = 0;
- Link != &Handle->Protocols;
- Link = Link->ForwardLink, ProtocolCount++)
- {
- Prot = CR (Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
- Buffer[ProtocolCount] = &(Prot->Protocol->ProtocolID);
- }
-
- Status = EFI_SUCCESS;
-
-Done:
- CoreReleaseProtocolLock ();
- return Status;
-}
-
-/**
- return handle database key.
-
-
- @return Handle database key.
-
-**/
-UINT64
-CoreGetHandleDatabaseKey (
- VOID
- )
-{
- return gHandleDatabaseKey;
-}
-
-/**
- Go connect any handles that were created or modified while a image executed.
-
- @param Key The Key to show that the handle has been
- created/modified
-
-**/
-VOID
-CoreConnectHandlesByKey (
- UINT64 Key
- )
-{
- UINTN Count;
- LIST_ENTRY *Link;
- EFI_HANDLE *HandleBuffer;
- IHANDLE *Handle;
- UINTN Index;
-
- //
- // Lock the protocol database
- //
- CoreAcquireProtocolLock ();
-
- for (Link = gHandleList.ForwardLink, Count = 0; Link != &gHandleList; Link = Link->ForwardLink) {
- Handle = CR (Link, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE);
- if (Handle->Key > Key) {
- Count++;
- }
- }
-
- HandleBuffer = AllocatePool (Count * sizeof (EFI_HANDLE));
- if (HandleBuffer == NULL) {
- CoreReleaseProtocolLock ();
- return;
- }
-
- for (Link = gHandleList.ForwardLink, Count = 0; Link != &gHandleList; Link = Link->ForwardLink) {
- Handle = CR (Link, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE);
- if (Handle->Key > Key) {
- HandleBuffer[Count++] = Handle;
- }
- }
-
- //
- // Unlock the protocol database
- //
- CoreReleaseProtocolLock ();
-
- //
- // Connect all handles whose Key value is greater than Key
- //
- for (Index = 0; Index < Count; Index++) {
- CoreConnectController (HandleBuffer[Index], NULL, NULL, TRUE);
- }
-
- CoreFreePool (HandleBuffer);
-}
+/** @file
+ UEFI handle & protocol handling.
+
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "DxeMain.h"
+#include "Handle.h"
+
+//
+// mProtocolDatabase - A list of all protocols in the system. (simple list for now)
+// gHandleList - A list of all the handles in the system
+// gProtocolDatabaseLock - Lock to protect the mProtocolDatabase
+// gHandleDatabaseKey - The Key to show that the handle has been created/modified
+//
+LIST_ENTRY mProtocolDatabase = INITIALIZE_LIST_HEAD_VARIABLE (mProtocolDatabase);
+LIST_ENTRY gHandleList = INITIALIZE_LIST_HEAD_VARIABLE (gHandleList);
+EFI_LOCK gProtocolDatabaseLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY);
+UINT64 gHandleDatabaseKey = 0;
+
+/**
+ Acquire lock on gProtocolDatabaseLock.
+
+**/
+VOID
+CoreAcquireProtocolLock (
+ VOID
+ )
+{
+ CoreAcquireLock (&gProtocolDatabaseLock);
+}
+
+/**
+ Release lock on gProtocolDatabaseLock.
+
+**/
+VOID
+CoreReleaseProtocolLock (
+ VOID
+ )
+{
+ CoreReleaseLock (&gProtocolDatabaseLock);
+}
+
+/**
+ Check whether a handle is a valid EFI_HANDLE
+ The gProtocolDatabaseLock must be owned
+
+ @param UserHandle The handle to check
+
+ @retval EFI_INVALID_PARAMETER The handle is NULL or not a valid EFI_HANDLE.
+ @retval EFI_SUCCESS The handle is valid EFI_HANDLE.
+
+**/
+EFI_STATUS
+CoreValidateHandle (
+ IN EFI_HANDLE UserHandle
+ )
+{
+ IHANDLE *Handle;
+ LIST_ENTRY *Link;
+
+ if (UserHandle == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ASSERT_LOCKED (&gProtocolDatabaseLock);
+
+ for (Link = gHandleList.BackLink; Link != &gHandleList; Link = Link->BackLink) {
+ Handle = CR (Link, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE);
+ if (Handle == (IHANDLE *)UserHandle) {
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_INVALID_PARAMETER;
+}
+
+/**
+ Finds the protocol entry for the requested protocol.
+ The gProtocolDatabaseLock must be owned
+
+ @param Protocol The ID of the protocol
+ @param Create Create a new entry if not found
+
+ @return Protocol entry
+
+**/
+PROTOCOL_ENTRY *
+CoreFindProtocolEntry (
+ IN EFI_GUID *Protocol,
+ IN BOOLEAN Create
+ )
+{
+ LIST_ENTRY *Link;
+ PROTOCOL_ENTRY *Item;
+ PROTOCOL_ENTRY *ProtEntry;
+
+ ASSERT_LOCKED (&gProtocolDatabaseLock);
+
+ //
+ // Search the database for the matching GUID
+ //
+
+ ProtEntry = NULL;
+ for (Link = mProtocolDatabase.ForwardLink;
+ Link != &mProtocolDatabase;
+ Link = Link->ForwardLink)
+ {
+ Item = CR (Link, PROTOCOL_ENTRY, AllEntries, PROTOCOL_ENTRY_SIGNATURE);
+ if (CompareGuid (&Item->ProtocolID, Protocol)) {
+ //
+ // This is the protocol entry
+ //
+
+ ProtEntry = Item;
+ break;
+ }
+ }
+
+ //
+ // If the protocol entry was not found and Create is TRUE, then
+ // allocate a new entry
+ //
+ if ((ProtEntry == NULL) && Create) {
+ ProtEntry = AllocatePool (sizeof (PROTOCOL_ENTRY));
+
+ if (ProtEntry != NULL) {
+ //
+ // Initialize new protocol entry structure
+ //
+ ProtEntry->Signature = PROTOCOL_ENTRY_SIGNATURE;
+ CopyGuid ((VOID *)&ProtEntry->ProtocolID, Protocol);
+ InitializeListHead (&ProtEntry->Protocols);
+ InitializeListHead (&ProtEntry->Notify);
+
+ //
+ // Add it to protocol database
+ //
+ InsertTailList (&mProtocolDatabase, &ProtEntry->AllEntries);
+ }
+ }
+
+ return ProtEntry;
+}
+
+/**
+ Finds the protocol instance for the requested handle and protocol.
+ Note: This function doesn't do parameters checking, it's caller's responsibility
+ to pass in valid parameters.
+
+ @param Handle The handle to search the protocol on
+ @param Protocol GUID of the protocol
+ @param Interface The interface for the protocol being searched
+
+ @return Protocol instance (NULL: Not found)
+
+**/
+PROTOCOL_INTERFACE *
+CoreFindProtocolInterface (
+ IN IHANDLE *Handle,
+ IN EFI_GUID *Protocol,
+ IN VOID *Interface
+ )
+{
+ PROTOCOL_INTERFACE *Prot;
+ PROTOCOL_ENTRY *ProtEntry;
+ LIST_ENTRY *Link;
+
+ ASSERT_LOCKED (&gProtocolDatabaseLock);
+ Prot = NULL;
+
+ //
+ // Lookup the protocol entry for this protocol ID
+ //
+
+ ProtEntry = CoreFindProtocolEntry (Protocol, FALSE);
+ if (ProtEntry != NULL) {
+ //
+ // Look at each protocol interface for any matches
+ //
+ for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
+ //
+ // If this protocol interface matches, remove it
+ //
+ Prot = CR (Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
+ if ((Prot->Interface == Interface) && (Prot->Protocol == ProtEntry)) {
+ break;
+ }
+
+ Prot = NULL;
+ }
+ }
+
+ return Prot;
+}
+
+/**
+ Check if the given device path is already installed.
+
+ @param DevicePath The given device path
+
+ @retval TRUE The device path is already installed
+ @retval FALSE The device path is not installed
+
+**/
+BOOLEAN
+IsDevicePathInstalled (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+{
+ UINTN SourceSize;
+ UINTN Size;
+ BOOLEAN Found;
+ LIST_ENTRY *Link;
+ PROTOCOL_ENTRY *ProtEntry;
+ PROTOCOL_INTERFACE *Prot;
+
+ if (DevicePath == NULL) {
+ return FALSE;
+ }
+
+ Found = FALSE;
+ SourceSize = GetDevicePathSize (DevicePath);
+ ASSERT (SourceSize >= END_DEVICE_PATH_LENGTH);
+
+ CoreAcquireProtocolLock ();
+ //
+ // Look up the protocol entry
+ //
+ ProtEntry = CoreFindProtocolEntry (&gEfiDevicePathProtocolGuid, FALSE);
+ if (ProtEntry == NULL) {
+ goto Done;
+ }
+
+ for (Link = ProtEntry->Protocols.ForwardLink; Link != &ProtEntry->Protocols; Link = Link->ForwardLink) {
+ //
+ // Loop on the DevicePathProtocol interfaces
+ //
+ Prot = CR (Link, PROTOCOL_INTERFACE, ByProtocol, PROTOCOL_INTERFACE_SIGNATURE);
+
+ //
+ // Check if DevicePath is same as this interface
+ //
+ Size = GetDevicePathSize (Prot->Interface);
+ ASSERT (Size >= END_DEVICE_PATH_LENGTH);
+ if ((Size == SourceSize) && (CompareMem (DevicePath, Prot->Interface, Size - END_DEVICE_PATH_LENGTH) == 0)) {
+ Found = TRUE;
+ break;
+ }
+ }
+
+Done:
+ CoreReleaseProtocolLock ();
+ return Found;
+}
+
+/**
+ Removes an event from a register protocol notify list on a protocol.
+
+ @param Event The event to search for in the protocol
+ database.
+
+ @return EFI_SUCCESS if the event was found and removed.
+ @return EFI_NOT_FOUND if the event was not found in the protocl database.
+
+**/
+EFI_STATUS
+CoreUnregisterProtocolNotifyEvent (
+ IN EFI_EVENT Event
+ )
+{
+ LIST_ENTRY *Link;
+ PROTOCOL_ENTRY *ProtEntry;
+ LIST_ENTRY *NotifyLink;
+ PROTOCOL_NOTIFY *ProtNotify;
+
+ CoreAcquireProtocolLock ();
+
+ for ( Link = mProtocolDatabase.ForwardLink;
+ Link != &mProtocolDatabase;
+ Link = Link->ForwardLink)
+ {
+ ProtEntry = CR (Link, PROTOCOL_ENTRY, AllEntries, PROTOCOL_ENTRY_SIGNATURE);
+
+ for ( NotifyLink = ProtEntry->Notify.ForwardLink;
+ NotifyLink != &ProtEntry->Notify;
+ NotifyLink = NotifyLink->ForwardLink)
+ {
+ ProtNotify = CR (NotifyLink, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE);
+
+ if (ProtNotify->Event == Event) {
+ RemoveEntryList (&ProtNotify->Link);
+ CoreFreePool (ProtNotify);
+ CoreReleaseProtocolLock ();
+ return EFI_SUCCESS;
+ }
+ }
+ }
+
+ CoreReleaseProtocolLock ();
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Removes all the events in the protocol database that match Event.
+
+ @param Event The event to search for in the protocol
+ database.
+
+ @return EFI_SUCCESS when done searching the entire database.
+
+**/
+EFI_STATUS
+CoreUnregisterProtocolNotify (
+ IN EFI_EVENT Event
+ )
+{
+ EFI_STATUS Status;
+
+ do {
+ Status = CoreUnregisterProtocolNotifyEvent (Event);
+ } while (!EFI_ERROR (Status));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Wrapper function to CoreInstallProtocolInterfaceNotify. This is the public API which
+ Calls the private one which contains a BOOLEAN parameter for notifications
+
+ @param UserHandle The handle to install the protocol handler on,
+ or NULL if a new handle is to be allocated
+ @param Protocol The protocol to add to the handle
+ @param InterfaceType Indicates whether Interface is supplied in
+ native form.
+ @param Interface The interface for the protocol being added
+
+ @return Status code
+
+**/
+EFI_STATUS
+EFIAPI
+CoreInstallProtocolInterface (
+ IN OUT EFI_HANDLE *UserHandle,
+ IN EFI_GUID *Protocol,
+ IN EFI_INTERFACE_TYPE InterfaceType,
+ IN VOID *Interface
+ )
+{
+ return CoreInstallProtocolInterfaceNotify (
+ UserHandle,
+ Protocol,
+ InterfaceType,
+ Interface,
+ TRUE
+ );
+}
+
+/**
+ Installs a protocol interface into the boot services environment.
+
+ @param UserHandle The handle to install the protocol handler on,
+ or NULL if a new handle is to be allocated
+ @param Protocol The protocol to add to the handle
+ @param InterfaceType Indicates whether Interface is supplied in
+ native form.
+ @param Interface The interface for the protocol being added
+ @param Notify indicates whether notify the notification list
+ for this protocol
+
+ @retval EFI_INVALID_PARAMETER Invalid parameter
+ @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
+ @retval EFI_SUCCESS Protocol interface successfully installed
+
+**/
+EFI_STATUS
+CoreInstallProtocolInterfaceNotify (
+ IN OUT EFI_HANDLE *UserHandle,
+ IN EFI_GUID *Protocol,
+ IN EFI_INTERFACE_TYPE InterfaceType,
+ IN VOID *Interface,
+ IN BOOLEAN Notify
+ )
+{
+ PROTOCOL_INTERFACE *Prot;
+ PROTOCOL_ENTRY *ProtEntry;
+ IHANDLE *Handle;
+ EFI_STATUS Status;
+ VOID *ExistingInterface;
+
+ //
+ // returns EFI_INVALID_PARAMETER if InterfaceType is invalid.
+ // Also added check for invalid UserHandle and Protocol pointers.
+ //
+ if ((UserHandle == NULL) || (Protocol == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (InterfaceType != EFI_NATIVE_INTERFACE) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Print debug message
+ //
+ DEBUG ((DEBUG_INFO, "InstallProtocolInterface: %g %p\n", Protocol, Interface));
+
+ Status = EFI_OUT_OF_RESOURCES;
+ Prot = NULL;
+ Handle = NULL;
+
+ if (*UserHandle != NULL) {
+ Status = CoreHandleProtocol (*UserHandle, Protocol, (VOID **)&ExistingInterface);
+ if (!EFI_ERROR (Status)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ //
+ // Lock the protocol database
+ //
+ CoreAcquireProtocolLock ();
+
+ //
+ // Lookup the Protocol Entry for the requested protocol
+ //
+ ProtEntry = CoreFindProtocolEntry (Protocol, TRUE);
+ if (ProtEntry == NULL) {
+ goto Done;
+ }
+
+ //
+ // Allocate a new protocol interface structure
+ //
+ Prot = AllocateZeroPool (sizeof (PROTOCOL_INTERFACE));
+ if (Prot == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ //
+ // If caller didn't supply a handle, allocate a new one
+ //
+ Handle = (IHANDLE *)*UserHandle;
+ if (Handle == NULL) {
+ Handle = AllocateZeroPool (sizeof (IHANDLE));
+ if (Handle == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ //
+ // Initialize new handler structure
+ //
+ Handle->Signature = EFI_HANDLE_SIGNATURE;
+ InitializeListHead (&Handle->Protocols);
+
+ //
+ // Initialize the Key to show that the handle has been created/modified
+ //
+ gHandleDatabaseKey++;
+ Handle->Key = gHandleDatabaseKey;
+
+ //
+ // Add this handle to the list global list of all handles
+ // in the system
+ //
+ InsertTailList (&gHandleList, &Handle->AllHandles);
+ } else {
+ Status = CoreValidateHandle (Handle);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "InstallProtocolInterface: input handle at 0x%x is invalid\n", Handle));
+ goto Done;
+ }
+ }
+
+ //
+ // Each interface that is added must be unique
+ //
+ ASSERT (CoreFindProtocolInterface (Handle, Protocol, Interface) == NULL);
+
+ //
+ // Initialize the protocol interface structure
+ //
+ Prot->Signature = PROTOCOL_INTERFACE_SIGNATURE;
+ Prot->Handle = Handle;
+ Prot->Protocol = ProtEntry;
+ Prot->Interface = Interface;
+
+ //
+ // Initalize OpenProtocol Data base
+ //
+ InitializeListHead (&Prot->OpenList);
+ Prot->OpenListCount = 0;
+
+ //
+ // Add this protocol interface to the head of the supported
+ // protocol list for this handle
+ //
+ InsertHeadList (&Handle->Protocols, &Prot->Link);
+
+ //
+ // Add this protocol interface to the tail of the
+ // protocol entry
+ //
+ InsertTailList (&ProtEntry->Protocols, &Prot->ByProtocol);
+
+ //
+ // Notify the notification list for this protocol
+ //
+ if (Notify) {
+ CoreNotifyProtocolEntry (ProtEntry);
+ }
+
+ Status = EFI_SUCCESS;
+
+Done:
+ //
+ // Done, unlock the database and return
+ //
+ CoreReleaseProtocolLock ();
+ if (!EFI_ERROR (Status)) {
+ //
+ // Return the new handle back to the caller
+ //
+ *UserHandle = Handle;
+ } else {
+ //
+ // There was an error, clean up
+ //
+ if (Prot != NULL) {
+ CoreFreePool (Prot);
+ }
+
+ DEBUG ((DEBUG_ERROR, "InstallProtocolInterface: %g %p failed with %r\n", Protocol, Interface, Status));
+ }
+
+ return Status;
+}
+
+/**
+ Installs a list of protocol interface into the boot services environment.
+ This function calls InstallProtocolInterface() in a loop. If any error
+ occures all the protocols added by this function are removed. This is
+ basically a lib function to save space.
+
+ @param Handle The pointer to a handle to install the new
+ protocol interfaces on, or a pointer to NULL
+ if a new handle is to be allocated.
+ @param ... EFI_GUID followed by protocol instance. A NULL
+ terminates the list. The pairs are the
+ arguments to InstallProtocolInterface(). All the
+ protocols are added to Handle.
+
+ @retval EFI_SUCCESS All the protocol interface was installed.
+ @retval EFI_OUT_OF_RESOURCES There was not enough memory in pool to install all the protocols.
+ @retval EFI_ALREADY_STARTED A Device Path Protocol instance was passed in that is already present in
+ the handle database.
+ @retval EFI_INVALID_PARAMETER Handle is NULL.
+ @retval EFI_INVALID_PARAMETER Protocol is already installed on the handle specified by Handle.
+
+**/
+EFI_STATUS
+EFIAPI
+CoreInstallMultipleProtocolInterfaces (
+ IN OUT EFI_HANDLE *Handle,
+ ...
+ )
+{
+ VA_LIST Args;
+ EFI_STATUS Status;
+ EFI_GUID *Protocol;
+ VOID *Interface;
+ EFI_TPL OldTpl;
+ UINTN Index;
+ EFI_HANDLE OldHandle;
+
+ if (Handle == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Syncronize with notifcations.
+ //
+ OldTpl = CoreRaiseTpl (TPL_NOTIFY);
+ OldHandle = *Handle;
+
+ //
+ // Check for duplicate device path and install the protocol interfaces
+ //
+ VA_START (Args, Handle);
+ for (Index = 0, Status = EFI_SUCCESS; !EFI_ERROR (Status); Index++) {
+ //
+ // If protocol is NULL, then it's the end of the list
+ //
+ Protocol = VA_ARG (Args, EFI_GUID *);
+ if (Protocol == NULL) {
+ break;
+ }
+
+ Interface = VA_ARG (Args, VOID *);
+
+ //
+ // Make sure you are installing on top a device path that has already been added.
+ //
+ if (CompareGuid (Protocol, &gEfiDevicePathProtocolGuid) &&
+ IsDevicePathInstalled (Interface))
+ {
+ Status = EFI_ALREADY_STARTED;
+ continue;
+ }
+
+ //
+ // Install it
+ //
+ Status = CoreInstallProtocolInterface (Handle, Protocol, EFI_NATIVE_INTERFACE, Interface);
+ }
+
+ VA_END (Args);
+
+ //
+ // If there was an error, remove all the interfaces that were installed without any errors
+ //
+ if (EFI_ERROR (Status)) {
+ //
+ // Reset the va_arg back to the first argument.
+ //
+ VA_START (Args, Handle);
+ for ( ; Index > 1; Index--) {
+ Protocol = VA_ARG (Args, EFI_GUID *);
+ Interface = VA_ARG (Args, VOID *);
+ CoreUninstallProtocolInterface (*Handle, Protocol, Interface);
+ }
+
+ VA_END (Args);
+
+ *Handle = OldHandle;
+ }
+
+ //
+ // Done
+ //
+ CoreRestoreTpl (OldTpl);
+ return Status;
+}
+
+/**
+ Attempts to disconnect all drivers that are using the protocol interface being queried.
+ If failed, reconnect all drivers disconnected.
+ Note: This function doesn't do parameters checking, it's caller's responsibility
+ to pass in valid parameters.
+
+ @param UserHandle The handle on which the protocol is installed
+ @param Prot The protocol to disconnect drivers from
+
+ @retval EFI_SUCCESS Drivers using the protocol interface are all
+ disconnected
+ @retval EFI_ACCESS_DENIED Failed to disconnect one or all of the drivers
+
+**/
+EFI_STATUS
+CoreDisconnectControllersUsingProtocolInterface (
+ IN EFI_HANDLE UserHandle,
+ IN PROTOCOL_INTERFACE *Prot
+ )
+{
+ EFI_STATUS Status;
+ BOOLEAN ItemFound;
+ LIST_ENTRY *Link;
+ OPEN_PROTOCOL_DATA *OpenData;
+
+ Status = EFI_SUCCESS;
+
+ //
+ // Attempt to disconnect all drivers from this protocol interface
+ //
+ do {
+ ItemFound = FALSE;
+ for (Link = Prot->OpenList.ForwardLink; Link != &Prot->OpenList; Link = Link->ForwardLink) {
+ OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
+ if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
+ CoreReleaseProtocolLock ();
+ Status = CoreDisconnectController (UserHandle, OpenData->AgentHandle, NULL);
+ CoreAcquireProtocolLock ();
+ if (!EFI_ERROR (Status)) {
+ ItemFound = TRUE;
+ }
+
+ break;
+ }
+ }
+ } while (ItemFound);
+
+ if (!EFI_ERROR (Status)) {
+ //
+ // Attempt to remove BY_HANDLE_PROTOOCL and GET_PROTOCOL and TEST_PROTOCOL Open List items
+ //
+ for (Link = Prot->OpenList.ForwardLink; Link != &Prot->OpenList;) {
+ OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
+ if ((OpenData->Attributes &
+ (EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL | EFI_OPEN_PROTOCOL_GET_PROTOCOL | EFI_OPEN_PROTOCOL_TEST_PROTOCOL)) != 0)
+ {
+ Link = RemoveEntryList (&OpenData->Link);
+ Prot->OpenListCount--;
+ CoreFreePool (OpenData);
+ } else {
+ Link = Link->ForwardLink;
+ }
+ }
+ }
+
+ //
+ // If there are errors or still has open items in the list, then reconnect all the drivers and return an error
+ //
+ if (EFI_ERROR (Status) || (Prot->OpenListCount > 0)) {
+ CoreReleaseProtocolLock ();
+ CoreConnectController (UserHandle, NULL, NULL, TRUE);
+ CoreAcquireProtocolLock ();
+ Status = EFI_ACCESS_DENIED;
+ }
+
+ return Status;
+}
+
+/**
+ Uninstalls all instances of a protocol:interfacer from a handle.
+ If the last protocol interface is remove from the handle, the
+ handle is freed.
+
+ @param UserHandle The handle to remove the protocol handler from
+ @param Protocol The protocol, of protocol:interface, to remove
+ @param Interface The interface, of protocol:interface, to remove
+
+ @retval EFI_INVALID_PARAMETER Protocol is NULL.
+ @retval EFI_SUCCESS Protocol interface successfully uninstalled.
+
+**/
+EFI_STATUS
+EFIAPI
+CoreUninstallProtocolInterface (
+ IN EFI_HANDLE UserHandle,
+ IN EFI_GUID *Protocol,
+ IN VOID *Interface
+ )
+{
+ EFI_STATUS Status;
+ IHANDLE *Handle;
+ PROTOCOL_INTERFACE *Prot;
+
+ //
+ // Check that Protocol is valid
+ //
+ if (Protocol == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Lock the protocol database
+ //
+ CoreAcquireProtocolLock ();
+
+ //
+ // Check that UserHandle is a valid handle
+ //
+ Status = CoreValidateHandle (UserHandle);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ //
+ // Check that Protocol exists on UserHandle, and Interface matches the interface in the database
+ //
+ Prot = CoreFindProtocolInterface (UserHandle, Protocol, Interface);
+ if (Prot == NULL) {
+ Status = EFI_NOT_FOUND;
+ goto Done;
+ }
+
+ //
+ // Attempt to disconnect all drivers that are using the protocol interface that is about to be removed
+ //
+ Status = CoreDisconnectControllersUsingProtocolInterface (
+ UserHandle,
+ Prot
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // One or more drivers refused to release, so return the error
+ //
+ goto Done;
+ }
+
+ //
+ // Remove the protocol interface from the protocol
+ //
+ Status = EFI_NOT_FOUND;
+ Handle = (IHANDLE *)UserHandle;
+ Prot = CoreRemoveInterfaceFromProtocol (Handle, Protocol, Interface);
+
+ if (Prot != NULL) {
+ //
+ // Update the Key to show that the handle has been created/modified
+ //
+ gHandleDatabaseKey++;
+ Handle->Key = gHandleDatabaseKey;
+
+ //
+ // Remove the protocol interface from the handle
+ //
+ RemoveEntryList (&Prot->Link);
+
+ //
+ // Free the memory
+ //
+ Prot->Signature = 0;
+ CoreFreePool (Prot);
+ Status = EFI_SUCCESS;
+ }
+
+ //
+ // If there are no more handlers for the handle, free the handle
+ //
+ if (IsListEmpty (&Handle->Protocols)) {
+ Handle->Signature = 0;
+ RemoveEntryList (&Handle->AllHandles);
+ CoreFreePool (Handle);
+ }
+
+Done:
+ //
+ // Done, unlock the database and return
+ //
+ CoreReleaseProtocolLock ();
+ return Status;
+}
+
+/**
+ Uninstalls a list of protocol interface in the boot services environment.
+ This function calls UninstallProtocolInterface() in a loop. This is
+ basically a lib function to save space.
+
+ If any errors are generated while the protocol interfaces are being
+ uninstalled, then the protocol interfaces uninstalled prior to the error will
+ be reinstalled and EFI_INVALID_PARAMETER will be returned.
+
+ @param Handle The handle to uninstall the protocol interfaces
+ from.
+ @param ... EFI_GUID followed by protocol instance. A NULL
+ terminates the list. The pairs are the
+ arguments to UninstallProtocolInterface(). All
+ the protocols are added to Handle.
+
+ @retval EFI_SUCCESS if all protocol interfaces where uninstalled.
+ @retval EFI_INVALID_PARAMETER if any protocol interface could not be
+ uninstalled and an attempt was made to
+ reinstall previously uninstalled protocol
+ interfaces.
+**/
+EFI_STATUS
+EFIAPI
+CoreUninstallMultipleProtocolInterfaces (
+ IN EFI_HANDLE Handle,
+ ...
+ )
+{
+ EFI_STATUS Status;
+ VA_LIST Args;
+ EFI_GUID *Protocol;
+ VOID *Interface;
+ UINTN Index;
+
+ VA_START (Args, Handle);
+ for (Index = 0, Status = EFI_SUCCESS; !EFI_ERROR (Status); Index++) {
+ //
+ // If protocol is NULL, then it's the end of the list
+ //
+ Protocol = VA_ARG (Args, EFI_GUID *);
+ if (Protocol == NULL) {
+ break;
+ }
+
+ Interface = VA_ARG (Args, VOID *);
+
+ //
+ // Uninstall it
+ //
+ Status = CoreUninstallProtocolInterface (Handle, Protocol, Interface);
+ }
+
+ VA_END (Args);
+
+ //
+ // If there was an error, add all the interfaces that were
+ // uninstalled without any errors
+ //
+ if (EFI_ERROR (Status)) {
+ //
+ // Reset the va_arg back to the first argument.
+ //
+ VA_START (Args, Handle);
+ for ( ; Index > 1; Index--) {
+ Protocol = VA_ARG (Args, EFI_GUID *);
+ Interface = VA_ARG (Args, VOID *);
+ CoreInstallProtocolInterface (&Handle, Protocol, EFI_NATIVE_INTERFACE, Interface);
+ }
+
+ VA_END (Args);
+ Status = EFI_INVALID_PARAMETER;
+ }
+
+ return Status;
+}
+
+/**
+ Locate a certain GUID protocol interface in a Handle's protocols.
+
+ @param UserHandle The handle to obtain the protocol interface on
+ The caller must pass in a valid UserHandle that
+ is checked with CoreValidateHandle().
+ @param Protocol The GUID of the protocol
+
+ @return The requested protocol interface for the handle
+
+**/
+STATIC
+PROTOCOL_INTERFACE *
+CoreGetProtocolInterface (
+ IN EFI_HANDLE UserHandle,
+ IN EFI_GUID *Protocol
+ )
+{
+ PROTOCOL_ENTRY *ProtEntry;
+ PROTOCOL_INTERFACE *Prot;
+ IHANDLE *Handle;
+ LIST_ENTRY *Link;
+
+ Handle = (IHANDLE *)UserHandle;
+
+ //
+ // Look at each protocol interface for a match
+ //
+ for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
+ Prot = CR (Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
+ ProtEntry = Prot->Protocol;
+ if (CompareGuid (&ProtEntry->ProtocolID, Protocol)) {
+ return Prot;
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ Queries a handle to determine if it supports a specified protocol.
+
+ @param UserHandle The handle being queried.
+ @param Protocol The published unique identifier of the protocol.
+ @param Interface Supplies the address where a pointer to the
+ corresponding Protocol Interface is returned.
+
+ @retval EFI_SUCCESS The interface information for the specified protocol was returned.
+ @retval EFI_UNSUPPORTED The device does not support the specified protocol.
+ @retval EFI_INVALID_PARAMETER Handle is NULL..
+ @retval EFI_INVALID_PARAMETER Protocol is NULL.
+ @retval EFI_INVALID_PARAMETER Interface is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+CoreHandleProtocol (
+ IN EFI_HANDLE UserHandle,
+ IN EFI_GUID *Protocol,
+ OUT VOID **Interface
+ )
+{
+ return CoreOpenProtocol (
+ UserHandle,
+ Protocol,
+ Interface,
+ gDxeCoreImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
+ );
+}
+
+/**
+ Locates the installed protocol handler for the handle, and
+ invokes it to obtain the protocol interface. Usage information
+ is registered in the protocol data base.
+
+ @param UserHandle The handle to obtain the protocol interface on
+ @param Protocol The ID of the protocol
+ @param Interface The location to return the protocol interface
+ @param ImageHandle The handle of the Image that is opening the
+ protocol interface specified by Protocol and
+ Interface.
+ @param ControllerHandle The controller handle that is requiring this
+ interface.
+ @param Attributes The open mode of the protocol interface
+ specified by Handle and Protocol.
+
+ @retval EFI_INVALID_PARAMETER Protocol is NULL.
+ @retval EFI_SUCCESS Get the protocol interface.
+
+**/
+EFI_STATUS
+EFIAPI
+CoreOpenProtocol (
+ IN EFI_HANDLE UserHandle,
+ IN EFI_GUID *Protocol,
+ OUT VOID **Interface OPTIONAL,
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_HANDLE ControllerHandle,
+ IN UINT32 Attributes
+ )
+{
+ EFI_STATUS Status;
+ PROTOCOL_INTERFACE *Prot;
+ LIST_ENTRY *Link;
+ OPEN_PROTOCOL_DATA *OpenData;
+ BOOLEAN ByDriver;
+ BOOLEAN Exclusive;
+ BOOLEAN Disconnect;
+ BOOLEAN ExactMatch;
+
+ //
+ // Check for invalid Protocol
+ //
+ if (Protocol == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check for invalid Interface
+ //
+ if ((Attributes != EFI_OPEN_PROTOCOL_TEST_PROTOCOL) && (Interface == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Lock the protocol database
+ //
+ CoreAcquireProtocolLock ();
+
+ //
+ // Check for invalid UserHandle
+ //
+ Status = CoreValidateHandle (UserHandle);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ //
+ // Check for invalid Attributes
+ //
+ switch (Attributes) {
+ case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER:
+ Status = CoreValidateHandle (ImageHandle);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ Status = CoreValidateHandle (ControllerHandle);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ if (UserHandle == ControllerHandle) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ break;
+ case EFI_OPEN_PROTOCOL_BY_DRIVER:
+ case EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE:
+ Status = CoreValidateHandle (ImageHandle);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ Status = CoreValidateHandle (ControllerHandle);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ break;
+ case EFI_OPEN_PROTOCOL_EXCLUSIVE:
+ Status = CoreValidateHandle (ImageHandle);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ break;
+ case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL:
+ case EFI_OPEN_PROTOCOL_GET_PROTOCOL:
+ case EFI_OPEN_PROTOCOL_TEST_PROTOCOL:
+ break;
+ default:
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ //
+ // Look at each protocol interface for a match
+ //
+ Prot = CoreGetProtocolInterface (UserHandle, Protocol);
+ if (Prot == NULL) {
+ Status = EFI_UNSUPPORTED;
+ goto Done;
+ }
+
+ Status = EFI_SUCCESS;
+
+ ByDriver = FALSE;
+ Exclusive = FALSE;
+ for ( Link = Prot->OpenList.ForwardLink; Link != &Prot->OpenList; Link = Link->ForwardLink) {
+ OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
+ ExactMatch = (BOOLEAN)((OpenData->AgentHandle == ImageHandle) &&
+ (OpenData->Attributes == Attributes) &&
+ (OpenData->ControllerHandle == ControllerHandle));
+ if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
+ ByDriver = TRUE;
+ if (ExactMatch) {
+ Status = EFI_ALREADY_STARTED;
+ goto Done;
+ }
+ }
+
+ if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_EXCLUSIVE) != 0) {
+ Exclusive = TRUE;
+ } else if (ExactMatch) {
+ OpenData->OpenCount++;
+ Status = EFI_SUCCESS;
+ goto Done;
+ }
+ }
+
+ //
+ // ByDriver TRUE -> A driver is managing (UserHandle, Protocol)
+ // ByDriver FALSE -> There are no drivers managing (UserHandle, Protocol)
+ // Exclusive TRUE -> Something has exclusive access to (UserHandle, Protocol)
+ // Exclusive FALSE -> Nothing has exclusive access to (UserHandle, Protocol)
+ //
+
+ switch (Attributes) {
+ case EFI_OPEN_PROTOCOL_BY_DRIVER:
+ if (Exclusive || ByDriver) {
+ Status = EFI_ACCESS_DENIED;
+ goto Done;
+ }
+
+ break;
+ case EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE:
+ case EFI_OPEN_PROTOCOL_EXCLUSIVE:
+ if (Exclusive) {
+ Status = EFI_ACCESS_DENIED;
+ goto Done;
+ }
+
+ if (ByDriver) {
+ do {
+ Disconnect = FALSE;
+ for (Link = Prot->OpenList.ForwardLink; Link != &Prot->OpenList; Link = Link->ForwardLink) {
+ OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
+ if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
+ Disconnect = TRUE;
+ CoreReleaseProtocolLock ();
+ Status = CoreDisconnectController (UserHandle, OpenData->AgentHandle, NULL);
+ CoreAcquireProtocolLock ();
+ if (EFI_ERROR (Status)) {
+ Status = EFI_ACCESS_DENIED;
+ goto Done;
+ } else {
+ break;
+ }
+ }
+ }
+ } while (Disconnect);
+ }
+
+ break;
+ case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER:
+ case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL:
+ case EFI_OPEN_PROTOCOL_GET_PROTOCOL:
+ case EFI_OPEN_PROTOCOL_TEST_PROTOCOL:
+ break;
+ }
+
+ if (ImageHandle == NULL) {
+ Status = EFI_SUCCESS;
+ goto Done;
+ }
+
+ //
+ // Create new entry
+ //
+ OpenData = AllocatePool (sizeof (OPEN_PROTOCOL_DATA));
+ if (OpenData == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ } else {
+ OpenData->Signature = OPEN_PROTOCOL_DATA_SIGNATURE;
+ OpenData->AgentHandle = ImageHandle;
+ OpenData->ControllerHandle = ControllerHandle;
+ OpenData->Attributes = Attributes;
+ OpenData->OpenCount = 1;
+ InsertTailList (&Prot->OpenList, &OpenData->Link);
+ Prot->OpenListCount++;
+ Status = EFI_SUCCESS;
+ }
+
+Done:
+
+ if (Attributes != EFI_OPEN_PROTOCOL_TEST_PROTOCOL) {
+ //
+ // Keep Interface unmodified in case of any Error
+ // except EFI_ALREADY_STARTED and EFI_UNSUPPORTED.
+ //
+ if (!EFI_ERROR (Status) || (Status == EFI_ALREADY_STARTED)) {
+ //
+ // According to above logic, if 'Prot' is NULL, then the 'Status' must be
+ // EFI_UNSUPPORTED. Here the 'Status' is not EFI_UNSUPPORTED, so 'Prot'
+ // must be not NULL.
+ //
+ // The ASSERT here is for addressing a false positive NULL pointer
+ // dereference issue raised from static analysis.
+ //
+ ASSERT (Prot != NULL);
+ //
+ // EFI_ALREADY_STARTED is not an error for bus driver.
+ // Return the corresponding protocol interface.
+ //
+ *Interface = Prot->Interface;
+ } else if (Status == EFI_UNSUPPORTED) {
+ //
+ // Return NULL Interface if Unsupported Protocol.
+ //
+ *Interface = NULL;
+ }
+ }
+
+ //
+ // Done. Release the database lock and return
+ //
+ CoreReleaseProtocolLock ();
+ return Status;
+}
+
+/**
+ Closes a protocol on a handle that was opened using OpenProtocol().
+
+ @param UserHandle The handle for the protocol interface that was
+ previously opened with OpenProtocol(), and is
+ now being closed.
+ @param Protocol The published unique identifier of the protocol.
+ It is the caller's responsibility to pass in a
+ valid GUID.
+ @param AgentHandle The handle of the agent that is closing the
+ protocol interface.
+ @param ControllerHandle If the agent that opened a protocol is a driver
+ that follows the EFI Driver Model, then this
+ parameter is the controller handle that required
+ the protocol interface. If the agent does not
+ follow the EFI Driver Model, then this parameter
+ is optional and may be NULL.
+
+ @retval EFI_SUCCESS The protocol instance was closed.
+ @retval EFI_INVALID_PARAMETER Handle, AgentHandle or ControllerHandle is not a
+ valid EFI_HANDLE.
+ @retval EFI_NOT_FOUND Can not find the specified protocol or
+ AgentHandle.
+
+**/
+EFI_STATUS
+EFIAPI
+CoreCloseProtocol (
+ IN EFI_HANDLE UserHandle,
+ IN EFI_GUID *Protocol,
+ IN EFI_HANDLE AgentHandle,
+ IN EFI_HANDLE ControllerHandle
+ )
+{
+ EFI_STATUS Status;
+ PROTOCOL_INTERFACE *ProtocolInterface;
+ LIST_ENTRY *Link;
+ OPEN_PROTOCOL_DATA *OpenData;
+
+ //
+ // Lock the protocol database
+ //
+ CoreAcquireProtocolLock ();
+
+ //
+ // Check for invalid parameters
+ //
+ Status = CoreValidateHandle (UserHandle);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ Status = CoreValidateHandle (AgentHandle);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ if (ControllerHandle != NULL) {
+ Status = CoreValidateHandle (ControllerHandle);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+ }
+
+ if (Protocol == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ //
+ // Look at each protocol interface for a match
+ //
+ Status = EFI_NOT_FOUND;
+ ProtocolInterface = CoreGetProtocolInterface (UserHandle, Protocol);
+ if (ProtocolInterface == NULL) {
+ goto Done;
+ }
+
+ //
+ // Walk the Open data base looking for AgentHandle
+ //
+ Link = ProtocolInterface->OpenList.ForwardLink;
+ while (Link != &ProtocolInterface->OpenList) {
+ OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
+ Link = Link->ForwardLink;
+ if ((OpenData->AgentHandle == AgentHandle) && (OpenData->ControllerHandle == ControllerHandle)) {
+ RemoveEntryList (&OpenData->Link);
+ ProtocolInterface->OpenListCount--;
+ CoreFreePool (OpenData);
+ Status = EFI_SUCCESS;
+ }
+ }
+
+Done:
+ //
+ // Done. Release the database lock and return.
+ //
+ CoreReleaseProtocolLock ();
+ return Status;
+}
+
+/**
+ Return information about Opened protocols in the system
+
+ @param UserHandle The handle to close the protocol interface on
+ @param Protocol The ID of the protocol
+ @param EntryBuffer A pointer to a buffer of open protocol information in the
+ form of EFI_OPEN_PROTOCOL_INFORMATION_ENTRY structures.
+ @param EntryCount Number of EntryBuffer entries
+
+ @retval EFI_SUCCESS The open protocol information was returned in EntryBuffer,
+ and the number of entries was returned EntryCount.
+ @retval EFI_NOT_FOUND Handle does not support the protocol specified by Protocol.
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available to allocate EntryBuffer.
+
+**/
+EFI_STATUS
+EFIAPI
+CoreOpenProtocolInformation (
+ IN EFI_HANDLE UserHandle,
+ IN EFI_GUID *Protocol,
+ OUT EFI_OPEN_PROTOCOL_INFORMATION_ENTRY **EntryBuffer,
+ OUT UINTN *EntryCount
+ )
+{
+ EFI_STATUS Status;
+ PROTOCOL_INTERFACE *ProtocolInterface;
+ LIST_ENTRY *Link;
+ OPEN_PROTOCOL_DATA *OpenData;
+ EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *Buffer;
+ UINTN Count;
+ UINTN Size;
+
+ *EntryBuffer = NULL;
+ *EntryCount = 0;
+
+ //
+ // Lock the protocol database
+ //
+ CoreAcquireProtocolLock ();
+
+ //
+ // Check for invalid UserHandle
+ //
+ Status = CoreValidateHandle (UserHandle);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_NOT_FOUND;
+ goto Done;
+ }
+
+ //
+ // Look at each protocol interface for a match
+ //
+ Status = EFI_NOT_FOUND;
+ ProtocolInterface = CoreGetProtocolInterface (UserHandle, Protocol);
+ if (ProtocolInterface == NULL) {
+ goto Done;
+ }
+
+ //
+ // Count the number of Open Entries
+ //
+ for ( Link = ProtocolInterface->OpenList.ForwardLink, Count = 0;
+ (Link != &ProtocolInterface->OpenList);
+ Link = Link->ForwardLink )
+ {
+ Count++;
+ }
+
+ ASSERT (Count == ProtocolInterface->OpenListCount);
+
+ if (Count == 0) {
+ Size = sizeof (EFI_OPEN_PROTOCOL_INFORMATION_ENTRY);
+ } else {
+ Size = Count * sizeof (EFI_OPEN_PROTOCOL_INFORMATION_ENTRY);
+ }
+
+ Buffer = AllocatePool (Size);
+ if (Buffer == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ Status = EFI_SUCCESS;
+ for ( Link = ProtocolInterface->OpenList.ForwardLink, Count = 0;
+ (Link != &ProtocolInterface->OpenList);
+ Link = Link->ForwardLink, Count++ )
+ {
+ OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
+
+ Buffer[Count].AgentHandle = OpenData->AgentHandle;
+ Buffer[Count].ControllerHandle = OpenData->ControllerHandle;
+ Buffer[Count].Attributes = OpenData->Attributes;
+ Buffer[Count].OpenCount = OpenData->OpenCount;
+ }
+
+ *EntryBuffer = Buffer;
+ *EntryCount = Count;
+
+Done:
+ //
+ // Done. Release the database lock.
+ //
+ CoreReleaseProtocolLock ();
+ return Status;
+}
+
+/**
+ Retrieves the list of protocol interface GUIDs that are installed on a handle in a buffer allocated
+ from pool.
+
+ @param UserHandle The handle from which to retrieve the list of
+ protocol interface GUIDs.
+ @param ProtocolBuffer A pointer to the list of protocol interface GUID
+ pointers that are installed on Handle.
+ @param ProtocolBufferCount A pointer to the number of GUID pointers present
+ in ProtocolBuffer.
+
+ @retval EFI_SUCCESS The list of protocol interface GUIDs installed
+ on Handle was returned in ProtocolBuffer. The
+ number of protocol interface GUIDs was returned
+ in ProtocolBufferCount.
+ @retval EFI_INVALID_PARAMETER Handle is NULL.
+ @retval EFI_INVALID_PARAMETER Handle is not a valid EFI_HANDLE.
+ @retval EFI_INVALID_PARAMETER ProtocolBuffer is NULL.
+ @retval EFI_INVALID_PARAMETER ProtocolBufferCount is NULL.
+ @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the
+ results.
+
+**/
+EFI_STATUS
+EFIAPI
+CoreProtocolsPerHandle (
+ IN EFI_HANDLE UserHandle,
+ OUT EFI_GUID ***ProtocolBuffer,
+ OUT UINTN *ProtocolBufferCount
+ )
+{
+ EFI_STATUS Status;
+ IHANDLE *Handle;
+ PROTOCOL_INTERFACE *Prot;
+ LIST_ENTRY *Link;
+ UINTN ProtocolCount;
+ EFI_GUID **Buffer;
+
+ if (ProtocolBuffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (ProtocolBufferCount == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *ProtocolBufferCount = 0;
+
+ ProtocolCount = 0;
+
+ CoreAcquireProtocolLock ();
+
+ Status = CoreValidateHandle (UserHandle);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ Handle = (IHANDLE *)UserHandle;
+
+ for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
+ ProtocolCount++;
+ }
+
+ //
+ // If there are no protocol interfaces installed on Handle, then Handle is not a valid EFI_HANDLE
+ //
+ if (ProtocolCount == 0) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ Buffer = AllocatePool (sizeof (EFI_GUID *) * ProtocolCount);
+ if (Buffer == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ *ProtocolBuffer = Buffer;
+ *ProtocolBufferCount = ProtocolCount;
+
+ for ( Link = Handle->Protocols.ForwardLink, ProtocolCount = 0;
+ Link != &Handle->Protocols;
+ Link = Link->ForwardLink, ProtocolCount++)
+ {
+ Prot = CR (Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
+ Buffer[ProtocolCount] = &(Prot->Protocol->ProtocolID);
+ }
+
+ Status = EFI_SUCCESS;
+
+Done:
+ CoreReleaseProtocolLock ();
+ return Status;
+}
+
+/**
+ return handle database key.
+
+
+ @return Handle database key.
+
+**/
+UINT64
+CoreGetHandleDatabaseKey (
+ VOID
+ )
+{
+ return gHandleDatabaseKey;
+}
+
+/**
+ Go connect any handles that were created or modified while a image executed.
+
+ @param Key The Key to show that the handle has been
+ created/modified
+
+**/
+VOID
+CoreConnectHandlesByKey (
+ UINT64 Key
+ )
+{
+ UINTN Count;
+ LIST_ENTRY *Link;
+ EFI_HANDLE *HandleBuffer;
+ IHANDLE *Handle;
+ UINTN Index;
+
+ //
+ // Lock the protocol database
+ //
+ CoreAcquireProtocolLock ();
+
+ for (Link = gHandleList.ForwardLink, Count = 0; Link != &gHandleList; Link = Link->ForwardLink) {
+ Handle = CR (Link, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE);
+ if (Handle->Key > Key) {
+ Count++;
+ }
+ }
+
+ HandleBuffer = AllocatePool (Count * sizeof (EFI_HANDLE));
+ if (HandleBuffer == NULL) {
+ CoreReleaseProtocolLock ();
+ return;
+ }
+
+ for (Link = gHandleList.ForwardLink, Count = 0; Link != &gHandleList; Link = Link->ForwardLink) {
+ Handle = CR (Link, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE);
+ if (Handle->Key > Key) {
+ HandleBuffer[Count++] = Handle;
+ }
+ }
+
+ //
+ // Unlock the protocol database
+ //
+ CoreReleaseProtocolLock ();
+
+ //
+ // Connect all handles whose Key value is greater than Key
+ //
+ for (Index = 0; Index < Count; Index++) {
+ CoreConnectController (HandleBuffer[Index], NULL, NULL, TRUE);
+ }
+
+ CoreFreePool (HandleBuffer);
+}
diff --git a/MdeModulePkg/Core/Dxe/Hand/Handle.h b/MdeModulePkg/Core/Dxe/Hand/Handle.h
index 5c66e4da66..df4b934123 100644
--- a/MdeModulePkg/Core/Dxe/Hand/Handle.h
+++ b/MdeModulePkg/Core/Dxe/Hand/Handle.h
@@ -1,252 +1,252 @@
-/** @file
- Support functions for managing protocol.
-
-Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#ifndef _HAND_H_
-#define _HAND_H_
-
-#define EFI_HANDLE_SIGNATURE SIGNATURE_32('h','n','d','l')
-
-///
-/// IHANDLE - contains a list of protocol handles
-///
-typedef struct {
- UINTN Signature;
- /// All handles list of IHANDLE
- LIST_ENTRY AllHandles;
- /// List of PROTOCOL_INTERFACE's for this handle
- LIST_ENTRY Protocols;
- UINTN LocateRequest;
- /// The Handle Database Key value when this handle was last created or modified
- UINT64 Key;
-} IHANDLE;
-
-#define ASSERT_IS_HANDLE(a) ASSERT((a)->Signature == EFI_HANDLE_SIGNATURE)
-
-#define PROTOCOL_ENTRY_SIGNATURE SIGNATURE_32('p','r','t','e')
-
-///
-/// PROTOCOL_ENTRY - each different protocol has 1 entry in the protocol
-/// database. Each handler that supports this protocol is listed, along
-/// with a list of registered notifies.
-///
-typedef struct {
- UINTN Signature;
- /// Link Entry inserted to mProtocolDatabase
- LIST_ENTRY AllEntries;
- /// ID of the protocol
- EFI_GUID ProtocolID;
- /// All protocol interfaces
- LIST_ENTRY Protocols;
- /// Registerd notification handlers
- LIST_ENTRY Notify;
-} PROTOCOL_ENTRY;
-
-#define PROTOCOL_INTERFACE_SIGNATURE SIGNATURE_32('p','i','f','c')
-
-///
-/// PROTOCOL_INTERFACE - each protocol installed on a handle is tracked
-/// with a protocol interface structure
-///
-typedef struct {
- UINTN Signature;
- /// Link on IHANDLE.Protocols
- LIST_ENTRY Link;
- /// Back pointer
- IHANDLE *Handle;
- /// Link on PROTOCOL_ENTRY.Protocols
- LIST_ENTRY ByProtocol;
- /// The protocol ID
- PROTOCOL_ENTRY *Protocol;
- /// The interface value
- VOID *Interface;
- /// OPEN_PROTOCOL_DATA list
- LIST_ENTRY OpenList;
- UINTN OpenListCount;
-} PROTOCOL_INTERFACE;
-
-#define OPEN_PROTOCOL_DATA_SIGNATURE SIGNATURE_32('p','o','d','l')
-
-typedef struct {
- UINTN Signature;
- /// Link on PROTOCOL_INTERFACE.OpenList
- LIST_ENTRY Link;
-
- EFI_HANDLE AgentHandle;
- EFI_HANDLE ControllerHandle;
- UINT32 Attributes;
- UINT32 OpenCount;
-} OPEN_PROTOCOL_DATA;
-
-#define PROTOCOL_NOTIFY_SIGNATURE SIGNATURE_32('p','r','t','n')
-
-///
-/// PROTOCOL_NOTIFY - used for each register notification for a protocol
-///
-typedef struct {
- UINTN Signature;
- PROTOCOL_ENTRY *Protocol;
- /// All notifications for this protocol
- LIST_ENTRY Link;
- /// Event to notify
- EFI_EVENT Event;
- /// Last position notified
- LIST_ENTRY *Position;
-} PROTOCOL_NOTIFY;
-
-/**
- Finds the protocol entry for the requested protocol.
- The gProtocolDatabaseLock must be owned
-
- @param Protocol The ID of the protocol
- @param Create Create a new entry if not found
-
- @return Protocol entry
-
-**/
-PROTOCOL_ENTRY *
-CoreFindProtocolEntry (
- IN EFI_GUID *Protocol,
- IN BOOLEAN Create
- );
-
-/**
- Signal event for every protocol in protocol entry.
-
- @param ProtEntry Protocol entry
-
-**/
-VOID
-CoreNotifyProtocolEntry (
- IN PROTOCOL_ENTRY *ProtEntry
- );
-
-/**
- Finds the protocol instance for the requested handle and protocol.
- Note: This function doesn't do parameters checking, it's caller's responsibility
- to pass in valid parameters.
-
- @param Handle The handle to search the protocol on
- @param Protocol GUID of the protocol
- @param Interface The interface for the protocol being searched
-
- @return Protocol instance (NULL: Not found)
-
-**/
-PROTOCOL_INTERFACE *
-CoreFindProtocolInterface (
- IN IHANDLE *Handle,
- IN EFI_GUID *Protocol,
- IN VOID *Interface
- );
-
-/**
- Removes Protocol from the protocol list (but not the handle list).
-
- @param Handle The handle to remove protocol on.
- @param Protocol GUID of the protocol to be moved
- @param Interface The interface of the protocol
-
- @return Protocol Entry
-
-**/
-PROTOCOL_INTERFACE *
-CoreRemoveInterfaceFromProtocol (
- IN IHANDLE *Handle,
- IN EFI_GUID *Protocol,
- IN VOID *Interface
- );
-
-/**
- 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
- );
-
-/**
- Attempts to disconnect all drivers that are using the protocol interface being queried.
- If failed, reconnect all drivers disconnected.
- Note: This function doesn't do parameters checking, it's caller's responsibility
- to pass in valid parameters.
-
- @param UserHandle The handle on which the protocol is installed
- @param Prot The protocol to disconnect drivers from
-
- @retval EFI_SUCCESS Drivers using the protocol interface are all
- disconnected
- @retval EFI_ACCESS_DENIED Failed to disconnect one or all of the drivers
-
-**/
-EFI_STATUS
-CoreDisconnectControllersUsingProtocolInterface (
- IN EFI_HANDLE UserHandle,
- IN PROTOCOL_INTERFACE *Prot
- );
-
-/**
- Acquire lock on gProtocolDatabaseLock.
-
-**/
-VOID
-CoreAcquireProtocolLock (
- VOID
- );
-
-/**
- Release lock on gProtocolDatabaseLock.
-
-**/
-VOID
-CoreReleaseProtocolLock (
- VOID
- );
-
-/**
- Check whether a handle is a valid EFI_HANDLE
- The gProtocolDatabaseLock must be owned
-
- @param UserHandle The handle to check
-
- @retval EFI_INVALID_PARAMETER The handle is NULL or not a valid EFI_HANDLE.
- @retval EFI_SUCCESS The handle is valid EFI_HANDLE.
-
-**/
-EFI_STATUS
-CoreValidateHandle (
- IN EFI_HANDLE UserHandle
- );
-
-//
-// Externs
-//
-extern EFI_LOCK gProtocolDatabaseLock;
-extern LIST_ENTRY gHandleList;
-extern UINT64 gHandleDatabaseKey;
-
-#endif
+/** @file
+ Support functions for managing protocol.
+
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _HAND_H_
+#define _HAND_H_
+
+#define EFI_HANDLE_SIGNATURE SIGNATURE_32('h','n','d','l')
+
+///
+/// IHANDLE - contains a list of protocol handles
+///
+typedef struct {
+ UINTN Signature;
+ /// All handles list of IHANDLE
+ LIST_ENTRY AllHandles;
+ /// List of PROTOCOL_INTERFACE's for this handle
+ LIST_ENTRY Protocols;
+ UINTN LocateRequest;
+ /// The Handle Database Key value when this handle was last created or modified
+ UINT64 Key;
+} IHANDLE;
+
+#define ASSERT_IS_HANDLE(a) ASSERT((a)->Signature == EFI_HANDLE_SIGNATURE)
+
+#define PROTOCOL_ENTRY_SIGNATURE SIGNATURE_32('p','r','t','e')
+
+///
+/// PROTOCOL_ENTRY - each different protocol has 1 entry in the protocol
+/// database. Each handler that supports this protocol is listed, along
+/// with a list of registered notifies.
+///
+typedef struct {
+ UINTN Signature;
+ /// Link Entry inserted to mProtocolDatabase
+ LIST_ENTRY AllEntries;
+ /// ID of the protocol
+ EFI_GUID ProtocolID;
+ /// All protocol interfaces
+ LIST_ENTRY Protocols;
+ /// Registerd notification handlers
+ LIST_ENTRY Notify;
+} PROTOCOL_ENTRY;
+
+#define PROTOCOL_INTERFACE_SIGNATURE SIGNATURE_32('p','i','f','c')
+
+///
+/// PROTOCOL_INTERFACE - each protocol installed on a handle is tracked
+/// with a protocol interface structure
+///
+typedef struct {
+ UINTN Signature;
+ /// Link on IHANDLE.Protocols
+ LIST_ENTRY Link;
+ /// Back pointer
+ IHANDLE *Handle;
+ /// Link on PROTOCOL_ENTRY.Protocols
+ LIST_ENTRY ByProtocol;
+ /// The protocol ID
+ PROTOCOL_ENTRY *Protocol;
+ /// The interface value
+ VOID *Interface;
+ /// OPEN_PROTOCOL_DATA list
+ LIST_ENTRY OpenList;
+ UINTN OpenListCount;
+} PROTOCOL_INTERFACE;
+
+#define OPEN_PROTOCOL_DATA_SIGNATURE SIGNATURE_32('p','o','d','l')
+
+typedef struct {
+ UINTN Signature;
+ /// Link on PROTOCOL_INTERFACE.OpenList
+ LIST_ENTRY Link;
+
+ EFI_HANDLE AgentHandle;
+ EFI_HANDLE ControllerHandle;
+ UINT32 Attributes;
+ UINT32 OpenCount;
+} OPEN_PROTOCOL_DATA;
+
+#define PROTOCOL_NOTIFY_SIGNATURE SIGNATURE_32('p','r','t','n')
+
+///
+/// PROTOCOL_NOTIFY - used for each register notification for a protocol
+///
+typedef struct {
+ UINTN Signature;
+ PROTOCOL_ENTRY *Protocol;
+ /// All notifications for this protocol
+ LIST_ENTRY Link;
+ /// Event to notify
+ EFI_EVENT Event;
+ /// Last position notified
+ LIST_ENTRY *Position;
+} PROTOCOL_NOTIFY;
+
+/**
+ Finds the protocol entry for the requested protocol.
+ The gProtocolDatabaseLock must be owned
+
+ @param Protocol The ID of the protocol
+ @param Create Create a new entry if not found
+
+ @return Protocol entry
+
+**/
+PROTOCOL_ENTRY *
+CoreFindProtocolEntry (
+ IN EFI_GUID *Protocol,
+ IN BOOLEAN Create
+ );
+
+/**
+ Signal event for every protocol in protocol entry.
+
+ @param ProtEntry Protocol entry
+
+**/
+VOID
+CoreNotifyProtocolEntry (
+ IN PROTOCOL_ENTRY *ProtEntry
+ );
+
+/**
+ Finds the protocol instance for the requested handle and protocol.
+ Note: This function doesn't do parameters checking, it's caller's responsibility
+ to pass in valid parameters.
+
+ @param Handle The handle to search the protocol on
+ @param Protocol GUID of the protocol
+ @param Interface The interface for the protocol being searched
+
+ @return Protocol instance (NULL: Not found)
+
+**/
+PROTOCOL_INTERFACE *
+CoreFindProtocolInterface (
+ IN IHANDLE *Handle,
+ IN EFI_GUID *Protocol,
+ IN VOID *Interface
+ );
+
+/**
+ Removes Protocol from the protocol list (but not the handle list).
+
+ @param Handle The handle to remove protocol on.
+ @param Protocol GUID of the protocol to be moved
+ @param Interface The interface of the protocol
+
+ @return Protocol Entry
+
+**/
+PROTOCOL_INTERFACE *
+CoreRemoveInterfaceFromProtocol (
+ IN IHANDLE *Handle,
+ IN EFI_GUID *Protocol,
+ IN VOID *Interface
+ );
+
+/**
+ 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
+ );
+
+/**
+ Attempts to disconnect all drivers that are using the protocol interface being queried.
+ If failed, reconnect all drivers disconnected.
+ Note: This function doesn't do parameters checking, it's caller's responsibility
+ to pass in valid parameters.
+
+ @param UserHandle The handle on which the protocol is installed
+ @param Prot The protocol to disconnect drivers from
+
+ @retval EFI_SUCCESS Drivers using the protocol interface are all
+ disconnected
+ @retval EFI_ACCESS_DENIED Failed to disconnect one or all of the drivers
+
+**/
+EFI_STATUS
+CoreDisconnectControllersUsingProtocolInterface (
+ IN EFI_HANDLE UserHandle,
+ IN PROTOCOL_INTERFACE *Prot
+ );
+
+/**
+ Acquire lock on gProtocolDatabaseLock.
+
+**/
+VOID
+CoreAcquireProtocolLock (
+ VOID
+ );
+
+/**
+ Release lock on gProtocolDatabaseLock.
+
+**/
+VOID
+CoreReleaseProtocolLock (
+ VOID
+ );
+
+/**
+ Check whether a handle is a valid EFI_HANDLE
+ The gProtocolDatabaseLock must be owned
+
+ @param UserHandle The handle to check
+
+ @retval EFI_INVALID_PARAMETER The handle is NULL or not a valid EFI_HANDLE.
+ @retval EFI_SUCCESS The handle is valid EFI_HANDLE.
+
+**/
+EFI_STATUS
+CoreValidateHandle (
+ IN EFI_HANDLE UserHandle
+ );
+
+//
+// Externs
+//
+extern EFI_LOCK gProtocolDatabaseLock;
+extern LIST_ENTRY gHandleList;
+extern UINT64 gHandleDatabaseKey;
+
+#endif
diff --git a/MdeModulePkg/Core/Dxe/Hand/Locate.c b/MdeModulePkg/Core/Dxe/Hand/Locate.c
index 8f20c6332d..4de2d1ea4d 100644
--- a/MdeModulePkg/Core/Dxe/Hand/Locate.c
+++ b/MdeModulePkg/Core/Dxe/Hand/Locate.c
@@ -1,741 +1,741 @@
-/** @file
- Locate handle functions
-
-Copyright (c) 2006 - 2023, Intel Corporation. All rights reserved.<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include "DxeMain.h"
-#include "Handle.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
- );
-
-/**
- Routine to get the next Handle, when you are searching for all handles.
-
- @param Position Information about which Handle to seach for.
- @param Interface Return the interface structure for the matching
- protocol.
-
- @return An pointer to IHANDLE if the next Position is not the end of the list.
- Otherwise,NULL is returned.
-
-**/
-IHANDLE *
-CoreGetNextLocateAllHandles (
- IN OUT LOCATE_POSITION *Position,
- OUT VOID **Interface
- );
-
-/**
- Routine to get the next Handle, when you are searching for register protocol
- notifies.
-
- @param Position Information about which Handle to seach for.
- @param Interface Return the interface structure for the matching
- protocol.
-
- @return An pointer to IHANDLE if the next Position is not the end of the list.
- Otherwise,NULL is returned.
-
-**/
-IHANDLE *
-CoreGetNextLocateByRegisterNotify (
- IN OUT LOCATE_POSITION *Position,
- OUT VOID **Interface
- );
-
-/**
- Routine to get the next Handle, when you are searching for a given protocol.
-
- @param Position Information about which Handle to seach for.
- @param Interface Return the interface structure for the matching
- protocol.
-
- @return An pointer to IHANDLE if the next Position is not the end of the list.
- Otherwise,NULL is returned.
-
-**/
-IHANDLE *
-CoreGetNextLocateByProtocol (
- IN OUT LOCATE_POSITION *Position,
- OUT VOID **Interface
- );
-
-/**
- Internal function for locating the requested handle(s) and returns them in Buffer.
- The caller should already have acquired the ProtocolLock.
-
- @param SearchType The type of search to perform to locate the
- handles
- @param Protocol The protocol to search for
- @param SearchKey Dependant on SearchType
- @param BufferSize On input the size of Buffer. On output the
- size of data returned.
- @param Buffer The buffer to return the results in
-
- @retval EFI_BUFFER_TOO_SMALL Buffer too small, required buffer size is
- returned in BufferSize.
- @retval EFI_INVALID_PARAMETER Invalid parameter
- @retval EFI_SUCCESS Successfully found the requested handle(s) and
- returns them in Buffer.
-
-**/
-EFI_STATUS
-InternalCoreLocateHandle (
- IN EFI_LOCATE_SEARCH_TYPE SearchType,
- IN EFI_GUID *Protocol OPTIONAL,
- IN VOID *SearchKey OPTIONAL,
- IN OUT UINTN *BufferSize,
- OUT EFI_HANDLE *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) {
- return 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;
-
- //
- // 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)) {
- return Status;
- }
-
- ASSERT (GetNext != NULL);
- //
- // 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
- //
- ASSERT (SearchKey != NULL);
- ProtNotify = SearchKey;
- ProtNotify->Position = ProtNotify->Position->ForwardLink;
- }
- }
-
- return Status;
-}
-
-/**
- Locates the requested handle(s) and returns them in Buffer.
-
- @param SearchType The type of search to perform to locate the
- handles
- @param Protocol The protocol to search for
- @param SearchKey Dependant on SearchType
- @param BufferSize On input the size of Buffer. On output the
- size of data returned.
- @param Buffer The buffer to return the results in
-
- @retval EFI_BUFFER_TOO_SMALL Buffer too small, required buffer size is
- returned in BufferSize.
- @retval EFI_INVALID_PARAMETER Invalid parameter
- @retval EFI_SUCCESS Successfully found the requested handle(s) and
- returns them in Buffer.
-
-**/
-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
- )
-{
- EFI_STATUS Status;
-
- //
- // Lock the protocol database
- //
- CoreAcquireProtocolLock ();
- Status = InternalCoreLocateHandle (SearchType, Protocol, SearchKey, BufferSize, Buffer);
- CoreReleaseProtocolLock ();
- return Status;
-}
-
-/**
- Routine to get the next Handle, when you are searching for all handles.
-
- @param Position Information about which Handle to seach for.
- @param Interface Return the interface structure for the matching
- protocol.
-
- @return An pointer to IHANDLE if the next Position is not the end of the list.
- Otherwise,NULL is returned.
-
-**/
-IHANDLE *
-CoreGetNextLocateAllHandles (
- IN OUT LOCATE_POSITION *Position,
- OUT VOID **Interface
- )
-{
- IHANDLE *Handle;
-
- //
- // Next handle
- //
- Position->Position = Position->Position->ForwardLink;
-
- //
- // If not at the end of the list, get the handle
- //
- Handle = NULL;
- *Interface = NULL;
- if (Position->Position != &gHandleList) {
- Handle = CR (Position->Position, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE);
- }
-
- return Handle;
-}
-
-/**
- Routine to get the next Handle, when you are searching for register protocol
- notifies.
-
- @param Position Information about which Handle to seach for.
- @param Interface Return the interface structure for the matching
- protocol.
-
- @return An pointer to IHANDLE if the next Position is not the end of the list.
- Otherwise,NULL is returned.
-
-**/
-IHANDLE *
-CoreGetNextLocateByRegisterNotify (
- IN OUT LOCATE_POSITION *Position,
- OUT VOID **Interface
- )
-{
- IHANDLE *Handle;
- PROTOCOL_NOTIFY *ProtNotify;
- PROTOCOL_INTERFACE *Prot;
- LIST_ENTRY *Link;
-
- Handle = NULL;
- *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 = Prot->Handle;
- *Interface = Prot->Interface;
- }
- }
-
- return Handle;
-}
-
-/**
- Routine to get the next Handle, when you are searching for a given protocol.
-
- @param Position Information about which Handle to seach for.
- @param Interface Return the interface structure for the matching
- protocol.
-
- @return An pointer to IHANDLE if the next Position is not the end of the list.
- Otherwise,NULL is returned.
-
-**/
-IHANDLE *
-CoreGetNextLocateByProtocol (
- IN OUT LOCATE_POSITION *Position,
- OUT VOID **Interface
- )
-{
- IHANDLE *Handle;
- LIST_ENTRY *Link;
- PROTOCOL_INTERFACE *Prot;
-
- Handle = NULL;
- *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;
- break;
- }
-
- //
- // Get the handle
- //
- Prot = CR (Link, PROTOCOL_INTERFACE, ByProtocol, PROTOCOL_INTERFACE_SIGNATURE);
- Handle = 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;
-}
-
-/**
- Locates the handle to a device on the device path that supports the specified protocol.
-
- @param Protocol Specifies the protocol to search for.
- @param 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 device
- path.
- @param Device A pointer to the returned device handle.
-
- @retval EFI_SUCCESS The resulting handle was returned.
- @retval EFI_NOT_FOUND No handles match the search.
- @retval EFI_INVALID_PARAMETER Protocol is NULL.
- @retval EFI_INVALID_PARAMETER DevicePath is NULL.
- @retval EFI_INVALID_PARAMETER A handle matched the search and Device is NULL.
-
-**/
-EFI_STATUS
-EFIAPI
-CoreLocateDevicePath (
- IN EFI_GUID *Protocol,
- IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath,
- OUT EFI_HANDLE *Device
- )
-{
- INTN SourceSize;
- INTN Size;
- INTN BestMatch;
- UINTN HandleCount;
- UINTN Index;
- EFI_STATUS Status;
- EFI_HANDLE *Handles;
- EFI_HANDLE Handle;
- EFI_HANDLE BestDevice;
- 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;
- }
-
- Handles = NULL;
- BestDevice = NULL;
- SourcePath = *DevicePath;
- TmpDevicePath = SourcePath;
- while (!IsDevicePathEnd (TmpDevicePath)) {
- if (IsDevicePathEndInstance (TmpDevicePath)) {
- //
- // If DevicePath is a multi-instance device path,
- // the function will operate on the first instance
- //
- break;
- }
-
- TmpDevicePath = NextDevicePathNode (TmpDevicePath);
- }
-
- SourceSize = (UINTN)TmpDevicePath - (UINTN)SourcePath;
-
- //
- // 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 = GetDevicePathSize (TmpDevicePath) - sizeof (EFI_DEVICE_PATH_PROTOCOL);
- ASSERT (Size >= 0);
- if ((Size <= SourceSize) && (CompareMem (SourcePath, TmpDevicePath, (UINTN)Size) == 0)) {
- //
- // If the size is equal to the best match, then we
- // have a duplicate 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;
- BestDevice = 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;
- }
-
- if (Device == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- *Device = BestDevice;
-
- //
- // Return the remaining part of the device path
- //
- *DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)(((UINT8 *)SourcePath) + BestMatch);
- return EFI_SUCCESS;
-}
-
-/**
- Return the first Protocol Interface that matches the Protocol GUID. If
- Registration is passed in, return a Protocol Instance that was just add
- to the system. If Registration is NULL return the first Protocol Interface
- you find.
-
- @param Protocol The protocol to search for
- @param Registration Optional Registration Key returned from
- RegisterProtocolNotify()
- @param Interface Return the Protocol interface (instance).
-
- @retval EFI_SUCCESS If a valid Interface is returned
- @retval EFI_INVALID_PARAMETER Invalid parameter
- @retval EFI_NOT_FOUND Protocol interface not found
-
-**/
-EFI_STATUS
-EFIAPI
-CoreLocateProtocol (
- IN EFI_GUID *Protocol,
- IN VOID *Registration OPTIONAL,
- OUT VOID **Interface
- )
-{
- EFI_STATUS Status;
- LOCATE_POSITION Position;
- PROTOCOL_NOTIFY *ProtNotify;
- IHANDLE *Handle;
-
- if ((Interface == NULL) || (Protocol == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- *Interface = NULL;
- Status = EFI_SUCCESS;
-
- //
- // Set initial position
- //
- Position.Protocol = Protocol;
- Position.SearchKey = Registration;
- Position.Position = &gHandleList;
-
- //
- // Lock the protocol database
- //
- Status = CoreAcquireLockOrFail (&gProtocolDatabaseLock);
- if (EFI_ERROR (Status)) {
- return EFI_NOT_FOUND;
- }
-
- mEfiLocateHandleRequest += 1;
-
- if (Registration == NULL) {
- //
- // 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 (Handle == NULL) {
- Status = EFI_NOT_FOUND;
- } else if (Registration != NULL) {
- //
- // 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;
-}
-
-/**
- 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.
-
- @param SearchType Specifies which handle(s) are to be returned.
- @param Protocol Provides the protocol to search by. This
- parameter is only valid for SearchType
- ByProtocol.
- @param SearchKey Supplies the search key depending on the
- SearchType.
- @param NumberHandles The number of handles returned in Buffer.
- @param Buffer A pointer to the buffer to return the requested
- array of handles that support Protocol.
-
- @retval EFI_SUCCESS The result array of handles was returned.
- @retval EFI_NOT_FOUND No handles match the search.
- @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the
- matching results.
- @retval EFI_INVALID_PARAMETER One or more parameters are not valid.
-
-**/
-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
- )
-{
- 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;
-
- //
- // Lock the protocol database
- //
- CoreAcquireProtocolLock ();
- Status = InternalCoreLocateHandle (
- 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;
- }
-
- CoreReleaseProtocolLock ();
- return Status;
- }
-
- *Buffer = AllocatePool (BufferSize);
- if (*Buffer == NULL) {
- CoreReleaseProtocolLock ();
- return EFI_OUT_OF_RESOURCES;
- }
-
- Status = InternalCoreLocateHandle (
- SearchType,
- Protocol,
- SearchKey,
- &BufferSize,
- *Buffer
- );
-
- *NumberHandles = BufferSize / sizeof (EFI_HANDLE);
- if (EFI_ERROR (Status)) {
- *NumberHandles = 0;
- if (*Buffer != NULL) {
- CoreFreePool (*Buffer);
- *Buffer = NULL;
- }
- }
-
- CoreReleaseProtocolLock ();
- return Status;
-}
+/** @file
+ Locate handle functions
+
+Copyright (c) 2006 - 2023, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "DxeMain.h"
+#include "Handle.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
+ );
+
+/**
+ Routine to get the next Handle, when you are searching for all handles.
+
+ @param Position Information about which Handle to seach for.
+ @param Interface Return the interface structure for the matching
+ protocol.
+
+ @return An pointer to IHANDLE if the next Position is not the end of the list.
+ Otherwise,NULL is returned.
+
+**/
+IHANDLE *
+CoreGetNextLocateAllHandles (
+ IN OUT LOCATE_POSITION *Position,
+ OUT VOID **Interface
+ );
+
+/**
+ Routine to get the next Handle, when you are searching for register protocol
+ notifies.
+
+ @param Position Information about which Handle to seach for.
+ @param Interface Return the interface structure for the matching
+ protocol.
+
+ @return An pointer to IHANDLE if the next Position is not the end of the list.
+ Otherwise,NULL is returned.
+
+**/
+IHANDLE *
+CoreGetNextLocateByRegisterNotify (
+ IN OUT LOCATE_POSITION *Position,
+ OUT VOID **Interface
+ );
+
+/**
+ Routine to get the next Handle, when you are searching for a given protocol.
+
+ @param Position Information about which Handle to seach for.
+ @param Interface Return the interface structure for the matching
+ protocol.
+
+ @return An pointer to IHANDLE if the next Position is not the end of the list.
+ Otherwise,NULL is returned.
+
+**/
+IHANDLE *
+CoreGetNextLocateByProtocol (
+ IN OUT LOCATE_POSITION *Position,
+ OUT VOID **Interface
+ );
+
+/**
+ Internal function for locating the requested handle(s) and returns them in Buffer.
+ The caller should already have acquired the ProtocolLock.
+
+ @param SearchType The type of search to perform to locate the
+ handles
+ @param Protocol The protocol to search for
+ @param SearchKey Dependant on SearchType
+ @param BufferSize On input the size of Buffer. On output the
+ size of data returned.
+ @param Buffer The buffer to return the results in
+
+ @retval EFI_BUFFER_TOO_SMALL Buffer too small, required buffer size is
+ returned in BufferSize.
+ @retval EFI_INVALID_PARAMETER Invalid parameter
+ @retval EFI_SUCCESS Successfully found the requested handle(s) and
+ returns them in Buffer.
+
+**/
+EFI_STATUS
+InternalCoreLocateHandle (
+ IN EFI_LOCATE_SEARCH_TYPE SearchType,
+ IN EFI_GUID *Protocol OPTIONAL,
+ IN VOID *SearchKey OPTIONAL,
+ IN OUT UINTN *BufferSize,
+ OUT EFI_HANDLE *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) {
+ return 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;
+
+ //
+ // 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)) {
+ return Status;
+ }
+
+ ASSERT (GetNext != NULL);
+ //
+ // 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
+ //
+ ASSERT (SearchKey != NULL);
+ ProtNotify = SearchKey;
+ ProtNotify->Position = ProtNotify->Position->ForwardLink;
+ }
+ }
+
+ return Status;
+}
+
+/**
+ Locates the requested handle(s) and returns them in Buffer.
+
+ @param SearchType The type of search to perform to locate the
+ handles
+ @param Protocol The protocol to search for
+ @param SearchKey Dependant on SearchType
+ @param BufferSize On input the size of Buffer. On output the
+ size of data returned.
+ @param Buffer The buffer to return the results in
+
+ @retval EFI_BUFFER_TOO_SMALL Buffer too small, required buffer size is
+ returned in BufferSize.
+ @retval EFI_INVALID_PARAMETER Invalid parameter
+ @retval EFI_SUCCESS Successfully found the requested handle(s) and
+ returns them in Buffer.
+
+**/
+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
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Lock the protocol database
+ //
+ CoreAcquireProtocolLock ();
+ Status = InternalCoreLocateHandle (SearchType, Protocol, SearchKey, BufferSize, Buffer);
+ CoreReleaseProtocolLock ();
+ return Status;
+}
+
+/**
+ Routine to get the next Handle, when you are searching for all handles.
+
+ @param Position Information about which Handle to seach for.
+ @param Interface Return the interface structure for the matching
+ protocol.
+
+ @return An pointer to IHANDLE if the next Position is not the end of the list.
+ Otherwise,NULL is returned.
+
+**/
+IHANDLE *
+CoreGetNextLocateAllHandles (
+ IN OUT LOCATE_POSITION *Position,
+ OUT VOID **Interface
+ )
+{
+ IHANDLE *Handle;
+
+ //
+ // Next handle
+ //
+ Position->Position = Position->Position->ForwardLink;
+
+ //
+ // If not at the end of the list, get the handle
+ //
+ Handle = NULL;
+ *Interface = NULL;
+ if (Position->Position != &gHandleList) {
+ Handle = CR (Position->Position, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE);
+ }
+
+ return Handle;
+}
+
+/**
+ Routine to get the next Handle, when you are searching for register protocol
+ notifies.
+
+ @param Position Information about which Handle to seach for.
+ @param Interface Return the interface structure for the matching
+ protocol.
+
+ @return An pointer to IHANDLE if the next Position is not the end of the list.
+ Otherwise,NULL is returned.
+
+**/
+IHANDLE *
+CoreGetNextLocateByRegisterNotify (
+ IN OUT LOCATE_POSITION *Position,
+ OUT VOID **Interface
+ )
+{
+ IHANDLE *Handle;
+ PROTOCOL_NOTIFY *ProtNotify;
+ PROTOCOL_INTERFACE *Prot;
+ LIST_ENTRY *Link;
+
+ Handle = NULL;
+ *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 = Prot->Handle;
+ *Interface = Prot->Interface;
+ }
+ }
+
+ return Handle;
+}
+
+/**
+ Routine to get the next Handle, when you are searching for a given protocol.
+
+ @param Position Information about which Handle to seach for.
+ @param Interface Return the interface structure for the matching
+ protocol.
+
+ @return An pointer to IHANDLE if the next Position is not the end of the list.
+ Otherwise,NULL is returned.
+
+**/
+IHANDLE *
+CoreGetNextLocateByProtocol (
+ IN OUT LOCATE_POSITION *Position,
+ OUT VOID **Interface
+ )
+{
+ IHANDLE *Handle;
+ LIST_ENTRY *Link;
+ PROTOCOL_INTERFACE *Prot;
+
+ Handle = NULL;
+ *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;
+ break;
+ }
+
+ //
+ // Get the handle
+ //
+ Prot = CR (Link, PROTOCOL_INTERFACE, ByProtocol, PROTOCOL_INTERFACE_SIGNATURE);
+ Handle = 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;
+}
+
+/**
+ Locates the handle to a device on the device path that supports the specified protocol.
+
+ @param Protocol Specifies the protocol to search for.
+ @param 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 device
+ path.
+ @param Device A pointer to the returned device handle.
+
+ @retval EFI_SUCCESS The resulting handle was returned.
+ @retval EFI_NOT_FOUND No handles match the search.
+ @retval EFI_INVALID_PARAMETER Protocol is NULL.
+ @retval EFI_INVALID_PARAMETER DevicePath is NULL.
+ @retval EFI_INVALID_PARAMETER A handle matched the search and Device is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+CoreLocateDevicePath (
+ IN EFI_GUID *Protocol,
+ IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath,
+ OUT EFI_HANDLE *Device
+ )
+{
+ INTN SourceSize;
+ INTN Size;
+ INTN BestMatch;
+ UINTN HandleCount;
+ UINTN Index;
+ EFI_STATUS Status;
+ EFI_HANDLE *Handles;
+ EFI_HANDLE Handle;
+ EFI_HANDLE BestDevice;
+ 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;
+ }
+
+ Handles = NULL;
+ BestDevice = NULL;
+ SourcePath = *DevicePath;
+ TmpDevicePath = SourcePath;
+ while (!IsDevicePathEnd (TmpDevicePath)) {
+ if (IsDevicePathEndInstance (TmpDevicePath)) {
+ //
+ // If DevicePath is a multi-instance device path,
+ // the function will operate on the first instance
+ //
+ break;
+ }
+
+ TmpDevicePath = NextDevicePathNode (TmpDevicePath);
+ }
+
+ SourceSize = (UINTN)TmpDevicePath - (UINTN)SourcePath;
+
+ //
+ // 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 = GetDevicePathSize (TmpDevicePath) - sizeof (EFI_DEVICE_PATH_PROTOCOL);
+ ASSERT (Size >= 0);
+ if ((Size <= SourceSize) && (CompareMem (SourcePath, TmpDevicePath, (UINTN)Size) == 0)) {
+ //
+ // If the size is equal to the best match, then we
+ // have a duplicate 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;
+ BestDevice = 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;
+ }
+
+ if (Device == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *Device = BestDevice;
+
+ //
+ // Return the remaining part of the device path
+ //
+ *DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)(((UINT8 *)SourcePath) + BestMatch);
+ return EFI_SUCCESS;
+}
+
+/**
+ Return the first Protocol Interface that matches the Protocol GUID. If
+ Registration is passed in, return a Protocol Instance that was just add
+ to the system. If Registration is NULL return the first Protocol Interface
+ you find.
+
+ @param Protocol The protocol to search for
+ @param Registration Optional Registration Key returned from
+ RegisterProtocolNotify()
+ @param Interface Return the Protocol interface (instance).
+
+ @retval EFI_SUCCESS If a valid Interface is returned
+ @retval EFI_INVALID_PARAMETER Invalid parameter
+ @retval EFI_NOT_FOUND Protocol interface not found
+
+**/
+EFI_STATUS
+EFIAPI
+CoreLocateProtocol (
+ IN EFI_GUID *Protocol,
+ IN VOID *Registration OPTIONAL,
+ OUT VOID **Interface
+ )
+{
+ EFI_STATUS Status;
+ LOCATE_POSITION Position;
+ PROTOCOL_NOTIFY *ProtNotify;
+ IHANDLE *Handle;
+
+ if ((Interface == NULL) || (Protocol == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *Interface = NULL;
+ Status = EFI_SUCCESS;
+
+ //
+ // Set initial position
+ //
+ Position.Protocol = Protocol;
+ Position.SearchKey = Registration;
+ Position.Position = &gHandleList;
+
+ //
+ // Lock the protocol database
+ //
+ Status = CoreAcquireLockOrFail (&gProtocolDatabaseLock);
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
+
+ mEfiLocateHandleRequest += 1;
+
+ if (Registration == NULL) {
+ //
+ // 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 (Handle == NULL) {
+ Status = EFI_NOT_FOUND;
+ } else if (Registration != NULL) {
+ //
+ // 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;
+}
+
+/**
+ 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.
+
+ @param SearchType Specifies which handle(s) are to be returned.
+ @param Protocol Provides the protocol to search by. This
+ parameter is only valid for SearchType
+ ByProtocol.
+ @param SearchKey Supplies the search key depending on the
+ SearchType.
+ @param NumberHandles The number of handles returned in Buffer.
+ @param Buffer A pointer to the buffer to return the requested
+ array of handles that support Protocol.
+
+ @retval EFI_SUCCESS The result array of handles was returned.
+ @retval EFI_NOT_FOUND No handles match the search.
+ @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the
+ matching results.
+ @retval EFI_INVALID_PARAMETER One or more parameters are not valid.
+
+**/
+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
+ )
+{
+ 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;
+
+ //
+ // Lock the protocol database
+ //
+ CoreAcquireProtocolLock ();
+ Status = InternalCoreLocateHandle (
+ 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;
+ }
+
+ CoreReleaseProtocolLock ();
+ return Status;
+ }
+
+ *Buffer = AllocatePool (BufferSize);
+ if (*Buffer == NULL) {
+ CoreReleaseProtocolLock ();
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = InternalCoreLocateHandle (
+ SearchType,
+ Protocol,
+ SearchKey,
+ &BufferSize,
+ *Buffer
+ );
+
+ *NumberHandles = BufferSize / sizeof (EFI_HANDLE);
+ if (EFI_ERROR (Status)) {
+ *NumberHandles = 0;
+ if (*Buffer != NULL) {
+ CoreFreePool (*Buffer);
+ *Buffer = NULL;
+ }
+ }
+
+ CoreReleaseProtocolLock ();
+ return Status;
+}
diff --git a/MdeModulePkg/Core/Dxe/Hand/Notify.c b/MdeModulePkg/Core/Dxe/Hand/Notify.c
index a6e20cad23..8d65a72457 100644
--- a/MdeModulePkg/Core/Dxe/Hand/Notify.c
+++ b/MdeModulePkg/Core/Dxe/Hand/Notify.c
@@ -1,278 +1,278 @@
-/** @file
- Support functions for UEFI protocol notification infrastructure.
-
-Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR>
-(C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include "DxeMain.h"
-#include "Handle.h"
-#include "Event.h"
-
-/**
- Signal event for every protocol in protocol entry.
-
- @param ProtEntry Protocol entry
-
-**/
-VOID
-CoreNotifyProtocolEntry (
- IN PROTOCOL_ENTRY *ProtEntry
- )
-{
- 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);
- }
-}
-
-/**
- Removes Protocol from the protocol list (but not the handle list).
-
- @param Handle The handle to remove protocol on.
- @param Protocol GUID of the protocol to be moved
- @param Interface The interface of the protocol
-
- @return Protocol Entry
-
-**/
-PROTOCOL_INTERFACE *
-CoreRemoveInterfaceFromProtocol (
- IN IHANDLE *Handle,
- IN EFI_GUID *Protocol,
- IN VOID *Interface
- )
-{
- 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;
-}
-
-/**
- Add a new protocol notification record for the request protocol.
-
- @param Protocol The requested protocol to add the notify
- registration
- @param Event The event to signal
- @param Registration Returns the registration record
-
- @retval EFI_INVALID_PARAMETER Invalid parameter
- @retval EFI_SUCCESS Successfully returned the registration record
- that has been added
-
-**/
-EFI_STATUS
-EFIAPI
-CoreRegisterProtocolNotify (
- IN EFI_GUID *Protocol,
- IN EFI_EVENT Event,
- OUT VOID **Registration
- )
-{
- 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 = AllocatePool (sizeof (PROTOCOL_NOTIFY));
- if (ProtNotify != NULL) {
- ((IEVENT *)Event)->ExFlag |= EVT_EXFLAG_EVENT_PROTOCOL_NOTIFICATION;
- 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;
-}
-
-/**
- Reinstall a protocol interface on a device handle. The OldInterface for Protocol is replaced by the NewInterface.
-
- @param UserHandle Handle on which the interface is to be
- reinstalled
- @param Protocol The numeric ID of the interface
- @param OldInterface A pointer to the old interface
- @param NewInterface A pointer to the new interface
-
- @retval EFI_SUCCESS The protocol interface was installed
- @retval EFI_NOT_FOUND The OldInterface on the handle was not found
- @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value
-
-**/
-EFI_STATUS
-EFIAPI
-CoreReinstallProtocolInterface (
- IN EFI_HANDLE UserHandle,
- IN EFI_GUID *Protocol,
- IN VOID *OldInterface,
- IN VOID *NewInterface
- )
-{
- EFI_STATUS Status;
- IHANDLE *Handle;
- PROTOCOL_INTERFACE *Prot;
- PROTOCOL_ENTRY *ProtEntry;
-
- if (Protocol == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // Lock the protocol database
- //
- CoreAcquireProtocolLock ();
-
- Status = CoreValidateHandle (UserHandle);
- if (EFI_ERROR (Status)) {
- goto Done;
- }
-
- Handle = (IHANDLE *)UserHandle;
- //
- // Check that Protocol exists on UserHandle, and Interface matches the interface in the database
- //
- Prot = CoreFindProtocolInterface (UserHandle, Protocol, OldInterface);
- if (Prot == NULL) {
- Status = EFI_NOT_FOUND;
- goto Done;
- }
-
- //
- // 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
- //
- goto Done;
- }
-
- //
- // Remove the protocol interface from the protocol
- //
- Prot = CoreRemoveInterfaceFromProtocol (Handle, Protocol, OldInterface);
-
- if (Prot == NULL) {
- Status = EFI_NOT_FOUND;
- goto Done;
- }
-
- 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 ();
- //
- // Return code is ignored on purpose.
- //
- CoreConnectController (
- UserHandle,
- NULL,
- NULL,
- TRUE
- );
- CoreAcquireProtocolLock ();
-
- //
- // Notify the notification list for this protocol
- //
- CoreNotifyProtocolEntry (ProtEntry);
-
- Status = EFI_SUCCESS;
-
-Done:
- CoreReleaseProtocolLock ();
-
- return Status;
-}
+/** @file
+ Support functions for UEFI protocol notification infrastructure.
+
+Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR>
+(C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "DxeMain.h"
+#include "Handle.h"
+#include "Event.h"
+
+/**
+ Signal event for every protocol in protocol entry.
+
+ @param ProtEntry Protocol entry
+
+**/
+VOID
+CoreNotifyProtocolEntry (
+ IN PROTOCOL_ENTRY *ProtEntry
+ )
+{
+ 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);
+ }
+}
+
+/**
+ Removes Protocol from the protocol list (but not the handle list).
+
+ @param Handle The handle to remove protocol on.
+ @param Protocol GUID of the protocol to be moved
+ @param Interface The interface of the protocol
+
+ @return Protocol Entry
+
+**/
+PROTOCOL_INTERFACE *
+CoreRemoveInterfaceFromProtocol (
+ IN IHANDLE *Handle,
+ IN EFI_GUID *Protocol,
+ IN VOID *Interface
+ )
+{
+ 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;
+}
+
+/**
+ Add a new protocol notification record for the request protocol.
+
+ @param Protocol The requested protocol to add the notify
+ registration
+ @param Event The event to signal
+ @param Registration Returns the registration record
+
+ @retval EFI_INVALID_PARAMETER Invalid parameter
+ @retval EFI_SUCCESS Successfully returned the registration record
+ that has been added
+
+**/
+EFI_STATUS
+EFIAPI
+CoreRegisterProtocolNotify (
+ IN EFI_GUID *Protocol,
+ IN EFI_EVENT Event,
+ OUT VOID **Registration
+ )
+{
+ 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 = AllocatePool (sizeof (PROTOCOL_NOTIFY));
+ if (ProtNotify != NULL) {
+ ((IEVENT *)Event)->ExFlag |= EVT_EXFLAG_EVENT_PROTOCOL_NOTIFICATION;
+ 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;
+}
+
+/**
+ Reinstall a protocol interface on a device handle. The OldInterface for Protocol is replaced by the NewInterface.
+
+ @param UserHandle Handle on which the interface is to be
+ reinstalled
+ @param Protocol The numeric ID of the interface
+ @param OldInterface A pointer to the old interface
+ @param NewInterface A pointer to the new interface
+
+ @retval EFI_SUCCESS The protocol interface was installed
+ @retval EFI_NOT_FOUND The OldInterface on the handle was not found
+ @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value
+
+**/
+EFI_STATUS
+EFIAPI
+CoreReinstallProtocolInterface (
+ IN EFI_HANDLE UserHandle,
+ IN EFI_GUID *Protocol,
+ IN VOID *OldInterface,
+ IN VOID *NewInterface
+ )
+{
+ EFI_STATUS Status;
+ IHANDLE *Handle;
+ PROTOCOL_INTERFACE *Prot;
+ PROTOCOL_ENTRY *ProtEntry;
+
+ if (Protocol == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Lock the protocol database
+ //
+ CoreAcquireProtocolLock ();
+
+ Status = CoreValidateHandle (UserHandle);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ Handle = (IHANDLE *)UserHandle;
+ //
+ // Check that Protocol exists on UserHandle, and Interface matches the interface in the database
+ //
+ Prot = CoreFindProtocolInterface (UserHandle, Protocol, OldInterface);
+ if (Prot == NULL) {
+ Status = EFI_NOT_FOUND;
+ goto Done;
+ }
+
+ //
+ // 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
+ //
+ goto Done;
+ }
+
+ //
+ // Remove the protocol interface from the protocol
+ //
+ Prot = CoreRemoveInterfaceFromProtocol (Handle, Protocol, OldInterface);
+
+ if (Prot == NULL) {
+ Status = EFI_NOT_FOUND;
+ goto Done;
+ }
+
+ 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 ();
+ //
+ // Return code is ignored on purpose.
+ //
+ CoreConnectController (
+ UserHandle,
+ NULL,
+ NULL,
+ TRUE
+ );
+ CoreAcquireProtocolLock ();
+
+ //
+ // Notify the notification list for this protocol
+ //
+ CoreNotifyProtocolEntry (ProtEntry);
+
+ Status = EFI_SUCCESS;
+
+Done:
+ CoreReleaseProtocolLock ();
+
+ return Status;
+}