mirror of
				https://github.com/acidanthera/audk.git
				synced 2025-11-04 05:25:45 +01:00 
			
		
		
		
	git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@3045 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			1701 lines
		
	
	
		
			42 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1701 lines
		
	
	
		
			42 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*++
 | 
						|
 | 
						|
Copyright (c) 2006 - 2007, Intel Corporation                                                         
 | 
						|
All rights reserved. This program and the accompanying materials                          
 | 
						|
are licensed and made available under the terms and conditions of the BSD License         
 | 
						|
which accompanies this distribution.  The full text of the license may be found at        
 | 
						|
http://opensource.org/licenses/bsd-license.php                                            
 | 
						|
                                                                                          
 | 
						|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     
 | 
						|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             
 | 
						|
 | 
						|
Module Name:
 | 
						|
 | 
						|
  handle.c
 | 
						|
 | 
						|
Abstract:
 | 
						|
 | 
						|
  EFI handle & protocol handling
 | 
						|
 | 
						|
 | 
						|
 | 
						|
Revision History
 | 
						|
 | 
						|
--*/
 | 
						|
 | 
						|
#include <DxeMain.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
 | 
						|
//
 | 
						|
static 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;
 | 
						|
 | 
						|
 | 
						|
VOID
 | 
						|
CoreAcquireProtocolLock (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Acquire lock on gProtocolDatabaseLock.
 | 
						|
  
 | 
						|
Arguments:
 | 
						|
 | 
						|
  None
 | 
						|
  
 | 
						|
Returns:
 | 
						|
 | 
						|
  None
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  CoreAcquireLock (&gProtocolDatabaseLock);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
VOID
 | 
						|
CoreReleaseProtocolLock (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Release lock on gProtocolDatabaseLock.
 | 
						|
  
 | 
						|
Arguments:
 | 
						|
 | 
						|
  None
 | 
						|
  
 | 
						|
Returns:
 | 
						|
 | 
						|
  None
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  CoreReleaseLock (&gProtocolDatabaseLock);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
CoreValidateHandle (
 | 
						|
  IN  EFI_HANDLE                UserHandle
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Check whether a handle is a valid EFI_HANDLE
 | 
						|
  
 | 
						|
Arguments:
 | 
						|
 | 
						|
  UserHandle    - The handle to check
 | 
						|
  
 | 
						|
Returns:
 | 
						|
 | 
						|
  EFI_INVALID_PARAMETER   - The handle is NULL or not a valid EFI_HANDLE.
 | 
						|
 | 
						|
  EFI_SUCCESS             - The handle is valid EFI_HANDLE.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  IHANDLE             *Handle;
 | 
						|
 | 
						|
  Handle = (IHANDLE *)UserHandle;
 | 
						|
  if (Handle == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
  if (Handle->Signature != EFI_HANDLE_SIGNATURE) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
PROTOCOL_ENTRY  *
 | 
						|
CoreFindProtocolEntry (
 | 
						|
  IN EFI_GUID   *Protocol,
 | 
						|
  IN BOOLEAN    Create
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Finds the protocol entry for the requested protocol.
 | 
						|
  
 | 
						|
  The gProtocolDatabaseLock must be owned
 | 
						|
 | 
						|
Arguments:
 | 
						|
  
 | 
						|
  Protocol  - The ID of the protocol 
 | 
						|
 | 
						|
  Create    - Create a new entry if not found
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  Protocol entry
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  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 = CoreAllocateBootServicesPool (sizeof(PROTOCOL_ENTRY));
 | 
						|
    
 | 
						|
    if (ProtEntry != NULL) {
 | 
						|
      //
 | 
						|
      // Initialize new protocol entry structure
 | 
						|
      //
 | 
						|
      ProtEntry->Signature = PROTOCOL_ENTRY_SIGNATURE;
 | 
						|
      CopyMem ((VOID *)&ProtEntry->ProtocolID, Protocol, sizeof (EFI_GUID));
 | 
						|
      InitializeListHead (&ProtEntry->Protocols);
 | 
						|
      InitializeListHead (&ProtEntry->Notify);
 | 
						|
 | 
						|
      //
 | 
						|
      // Add it to protocol database
 | 
						|
      //
 | 
						|
      InsertTailList (&mProtocolDatabase, &ProtEntry->AllEntries);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return ProtEntry;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
PROTOCOL_INTERFACE *
 | 
						|
CoreFindProtocolInterface (
 | 
						|
  IN IHANDLE        *Handle,
 | 
						|
  IN EFI_GUID       *Protocol,
 | 
						|
  IN VOID           *Interface
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  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.
 | 
						|
  
 | 
						|
Arguments:
 | 
						|
  
 | 
						|
  Handle    - The handle to search the protocol on
 | 
						|
  
 | 
						|
  Protocol  - GUID of the protocol
 | 
						|
 | 
						|
  Interface - The interface for the protocol being searched
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  Protocol instance (NULL: Not found)
 | 
						|
 | 
						|
--*/  
 | 
						|
{
 | 
						|
  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;
 | 
						|
}
 | 
						|
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
CoreUnregisterProtocolNotifyEvent (
 | 
						|
  IN EFI_EVENT      Event
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Removes an event from a register protocol notify list on a protocol.
 | 
						|
 | 
						|
Arguments:
 | 
						|
  
 | 
						|
  Event   - The event to search for in the protocol database.
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  EFI_SUCCESS   if the event was found and removed.
 | 
						|
  EFI_NOT_FOUND if the event was not found in the protocl database.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  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;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
CoreUnregisterProtocolNotify (
 | 
						|
  IN EFI_EVENT      Event
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Removes all the events in the protocol database that match Event.
 | 
						|
 | 
						|
Arguments:
 | 
						|
  
 | 
						|
  Event   - The event to search for in the protocol database.
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  EFI_SUCCESS when done searching the entire database.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_STATUS       Status;
 | 
						|
 | 
						|
  do {
 | 
						|
    Status = CoreUnregisterProtocolNotifyEvent (Event);
 | 
						|
  } while (!EFI_ERROR (Status));
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
CoreInstallProtocolInterface (
 | 
						|
  IN OUT EFI_HANDLE     *UserHandle,
 | 
						|
  IN EFI_GUID           *Protocol,
 | 
						|
  IN EFI_INTERFACE_TYPE InterfaceType,
 | 
						|
  IN VOID               *Interface
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Wrapper function to CoreInstallProtocolInterfaceNotify.  This is the public API which
 | 
						|
  Calls the private one which contains a BOOLEAN parameter for notifications
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  UserHandle     - The handle to install the protocol handler on,
 | 
						|
                    or NULL if a new handle is to be allocated
 | 
						|
 | 
						|
  Protocol       - The protocol to add to the handle
 | 
						|
 | 
						|
  InterfaceType  - Indicates whether Interface is supplied in native form.
 | 
						|
 | 
						|
  Interface      - The interface for the protocol being added
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  Status code    
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  return CoreInstallProtocolInterfaceNotify (
 | 
						|
            UserHandle, 
 | 
						|
            Protocol, 
 | 
						|
            InterfaceType, 
 | 
						|
            Interface, 
 | 
						|
            TRUE
 | 
						|
            );
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
CoreInstallProtocolInterfaceNotify (
 | 
						|
  IN OUT EFI_HANDLE     *UserHandle,
 | 
						|
  IN EFI_GUID           *Protocol,
 | 
						|
  IN EFI_INTERFACE_TYPE InterfaceType,
 | 
						|
  IN VOID               *Interface,
 | 
						|
  IN BOOLEAN            Notify
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Installs a protocol interface into the boot services environment.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  UserHandle     - The handle to install the protocol handler on,
 | 
						|
                   or NULL if a new handle is to be allocated
 | 
						|
 | 
						|
  Protocol       - The protocol to add to the handle
 | 
						|
 | 
						|
  InterfaceType  - Indicates whether Interface is supplied in native form.
 | 
						|
 | 
						|
  Interface      - The interface for the protocol being added
 | 
						|
 | 
						|
  Notify         - indicates whether notify the notification list 
 | 
						|
                   for this protocol
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  EFI_INVALID_PARAMETER     - Invalid parameter
 | 
						|
  
 | 
						|
  EFI_OUT_OF_RESOURCES       - No enough buffer to allocate
 | 
						|
  
 | 
						|
  EFI_SUCCESS               - Protocol interface successfully installed
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  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((EFI_D_ERROR | EFI_D_INFO, "InstallProtocolInterface: %g %p\n", Protocol, Interface));
 | 
						|
 | 
						|
  Status = EFI_OUT_OF_RESOURCES;
 | 
						|
  Prot = NULL;
 | 
						|
  Handle = NULL;
 | 
						|
 | 
						|
  ASSERT (NULL != gDxeCoreBS);
 | 
						|
 | 
						|
  if (*UserHandle != NULL_HANDLE) {
 | 
						|
    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 = CoreAllocateZeroBootServicesPool (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 = CoreAllocateZeroBootServicesPool (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);
 | 
						|
  } 
 | 
						|
 | 
						|
  Status = CoreValidateHandle (Handle);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    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);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
CoreInstallMultipleProtocolInterfaces (
 | 
						|
  IN OUT EFI_HANDLE           *Handle,
 | 
						|
  ...
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  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.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  Handle      - The handle to install the protocol handlers on,
 | 
						|
                or NULL if a new handle is to be allocated
 | 
						|
  ...         - 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.
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  EFI_INVALID_PARAMETER       - Handle is NULL.
 | 
						|
  
 | 
						|
  EFI_SUCCESS                 - Protocol interfaces successfully installed.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  VA_LIST                   args;
 | 
						|
  EFI_STATUS                Status;
 | 
						|
  EFI_GUID                  *Protocol;
 | 
						|
  VOID                      *Interface;
 | 
						|
  EFI_TPL                   OldTpl;
 | 
						|
  UINTN                     Index;
 | 
						|
  EFI_HANDLE                OldHandle;
 | 
						|
  EFI_HANDLE                DeviceHandle;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
 | 
						|
  
 | 
						|
  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)) {
 | 
						|
      DeviceHandle = NULL;
 | 
						|
      DevicePath   = Interface;
 | 
						|
      Status = CoreLocateDevicePath (&gEfiDevicePathProtocolGuid, &DevicePath, &DeviceHandle);
 | 
						|
      if (!EFI_ERROR (Status) && (DeviceHandle != NULL_HANDLE) && IsDevicePathEnd(DevicePath)) {
 | 
						|
        Status = EFI_ALREADY_STARTED;
 | 
						|
        continue;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  
 | 
						|
    //
 | 
						|
    // Install it
 | 
						|
    //
 | 
						|
    Status = CoreInstallProtocolInterface (Handle, Protocol, EFI_NATIVE_INTERFACE, Interface);
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  // 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);
 | 
						|
    }        
 | 
						|
    *Handle = OldHandle;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Done
 | 
						|
  //
 | 
						|
  CoreRestoreTpl (OldTpl);
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
CoreDisconnectControllersUsingProtocolInterface (
 | 
						|
  IN EFI_HANDLE           UserHandle,
 | 
						|
  IN PROTOCOL_INTERFACE   *Prot
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  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.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  UserHandle  - The handle on which the protocol is installed 
 | 
						|
  Prot        - The protocol to disconnect drivers from
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  EFI_SUCCESS       - Drivers using the protocol interface are all disconnected
 | 
						|
  EFI_ACCESS_DENIED - Failed to disconnect one or all of the drivers
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  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) && !ItemFound;
 | 
						|
          Link = Link->ForwardLink ) {
 | 
						|
      OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
 | 
						|
      if (OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) {
 | 
						|
        ItemFound = TRUE;
 | 
						|
        CoreReleaseProtocolLock ();
 | 
						|
        Status = CoreDisconnectController (UserHandle, OpenData->AgentHandle, NULL);
 | 
						|
        CoreAcquireProtocolLock ();
 | 
						|
        if (EFI_ERROR (Status)) {
 | 
						|
           ItemFound = FALSE;
 | 
						|
           break;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  } while (ItemFound);
 | 
						|
 | 
						|
  if (!EFI_ERROR (Status)) {
 | 
						|
    //
 | 
						|
    // Attempt to remove BY_HANDLE_PROTOOCL and GET_PROTOCOL and TEST_PROTOCOL Open List items
 | 
						|
    //
 | 
						|
    do {
 | 
						|
      ItemFound = FALSE;
 | 
						|
      for ( Link = Prot->OpenList.ForwardLink;
 | 
						|
            (Link != &Prot->OpenList) && !ItemFound;
 | 
						|
            Link = Link->ForwardLink ) {
 | 
						|
        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)) {
 | 
						|
          ItemFound = TRUE;
 | 
						|
          RemoveEntryList (&OpenData->Link);  
 | 
						|
          Prot->OpenListCount--;
 | 
						|
          CoreFreePool (OpenData);
 | 
						|
        }
 | 
						|
      }
 | 
						|
    } while (ItemFound);
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // 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;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
CoreUninstallProtocolInterface (
 | 
						|
  IN EFI_HANDLE       UserHandle,
 | 
						|
  IN EFI_GUID         *Protocol,
 | 
						|
  IN VOID             *Interface
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Uninstalls all instances of a protocol:interfacer from a handle. 
 | 
						|
  If the last protocol interface is remove from the handle, the 
 | 
						|
  handle is freed.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  UserHandle      - The handle to remove the protocol handler from
 | 
						|
 | 
						|
  Protocol        - The protocol, of protocol:interface, to remove
 | 
						|
 | 
						|
  Interface       - The interface, of protocol:interface, to remove
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  EFI_INVALID_PARAMETER       - Protocol is NULL.
 | 
						|
  
 | 
						|
  EFI_SUCCESS                 - Protocol interface successfully uninstalled.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_STATUS            Status;
 | 
						|
  IHANDLE               *Handle;
 | 
						|
  PROTOCOL_INTERFACE    *Prot;
 | 
						|
 | 
						|
  //
 | 
						|
  // Check that Protocol is valid
 | 
						|
  //
 | 
						|
  if (Protocol == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Check that UserHandle is a valid handle
 | 
						|
  //
 | 
						|
  Status = CoreValidateHandle (UserHandle);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Lock the protocol database
 | 
						|
  //
 | 
						|
  CoreAcquireProtocolLock ();
 | 
						|
 | 
						|
  //
 | 
						|
  // 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;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
CoreUninstallMultipleProtocolInterfaces (
 | 
						|
  IN EFI_HANDLE           Handle,
 | 
						|
  ...
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Uninstalls a list of protocol interface in the boot services environment. 
 | 
						|
  This function calls UnisatllProtocolInterface() in a loop. This is 
 | 
						|
  basically a lib function to save space.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  Handle      - The handle to uninstall the protocol
 | 
						|
 | 
						|
  ...         - 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.
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  Status code    
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  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);
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // 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);
 | 
						|
    }        
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}    
 | 
						|
 | 
						|
STATIC
 | 
						|
PROTOCOL_INTERFACE  *
 | 
						|
CoreGetProtocolInterface (
 | 
						|
  IN  EFI_HANDLE                UserHandle,
 | 
						|
  IN  EFI_GUID                  *Protocol
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Locate a certain GUID protocol interface in a Handle's protocols.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  UserHandle  - The handle to obtain the protocol interface on
 | 
						|
 | 
						|
  Protocol    - The GUID of the protocol 
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  The requested protocol interface for the handle
 | 
						|
  
 | 
						|
--*/  
 | 
						|
{
 | 
						|
  EFI_STATUS          Status;
 | 
						|
  PROTOCOL_ENTRY      *ProtEntry;
 | 
						|
  PROTOCOL_INTERFACE  *Prot;
 | 
						|
  IHANDLE             *Handle;
 | 
						|
  LIST_ENTRY          *Link;
 | 
						|
 | 
						|
  Status = CoreValidateHandle (UserHandle);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
  
 | 
						|
  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;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
CoreHandleProtocol (
 | 
						|
  IN EFI_HANDLE       UserHandle,
 | 
						|
  IN EFI_GUID         *Protocol,
 | 
						|
  OUT VOID            **Interface
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Queries a handle to determine if it supports a specified protocol.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  UserHandle  - The handle being queried.
 | 
						|
 | 
						|
  Protocol    - The published unique identifier of the protocol.
 | 
						|
 | 
						|
  Interface   - Supplies the address where a pointer to the corresponding Protocol
 | 
						|
               Interface is returned.
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  The requested protocol interface for the handle
 | 
						|
  
 | 
						|
--*/  
 | 
						|
{
 | 
						|
  return CoreOpenProtocol (
 | 
						|
          UserHandle,     
 | 
						|
          Protocol, 
 | 
						|
          Interface, 
 | 
						|
          gDxeCoreImageHandle, 
 | 
						|
          NULL,     
 | 
						|
          EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
 | 
						|
          );
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
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
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  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.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  UserHandle     - The handle to obtain the protocol interface on
 | 
						|
 | 
						|
  Protocol       - The ID of the protocol 
 | 
						|
 | 
						|
  Interface      - The location to return the protocol interface
 | 
						|
 | 
						|
  ImageHandle       - The handle of the Image that is opening the protocol interface
 | 
						|
                    specified by Protocol and Interface.
 | 
						|
  
 | 
						|
  ControllerHandle  - The controller handle that is requiring this interface.
 | 
						|
 | 
						|
  Attributes     - The open mode of the protocol interface specified by Handle
 | 
						|
                    and Protocol.
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  EFI_INVALID_PARAMETER       - Protocol is NULL.
 | 
						|
  
 | 
						|
  EFI_SUCCESS                 - Get the protocol interface.
 | 
						|
  
 | 
						|
--*/
 | 
						|
{
 | 
						|
  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) {
 | 
						|
    if (Interface == NULL) {
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    } else {
 | 
						|
      *Interface = NULL;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Check for invalid UserHandle
 | 
						|
  //
 | 
						|
  Status = CoreValidateHandle (UserHandle);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Check for invalid Attributes
 | 
						|
  //
 | 
						|
  switch (Attributes) {
 | 
						|
  case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER :
 | 
						|
    Status = CoreValidateHandle (ImageHandle);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
    Status = CoreValidateHandle (ControllerHandle);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
    if (UserHandle == ControllerHandle) {
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
    break;
 | 
						|
  case EFI_OPEN_PROTOCOL_BY_DRIVER :
 | 
						|
  case EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE :
 | 
						|
    Status = CoreValidateHandle (ImageHandle);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
    Status = CoreValidateHandle (ControllerHandle);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
    break;
 | 
						|
  case EFI_OPEN_PROTOCOL_EXCLUSIVE :
 | 
						|
    Status = CoreValidateHandle (ImageHandle);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
    break;
 | 
						|
  case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL :
 | 
						|
  case EFI_OPEN_PROTOCOL_GET_PROTOCOL :
 | 
						|
  case EFI_OPEN_PROTOCOL_TEST_PROTOCOL :
 | 
						|
    break;
 | 
						|
  default:
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Lock the protocol database
 | 
						|
  //
 | 
						|
  CoreAcquireProtocolLock ();
 | 
						|
 | 
						|
  //
 | 
						|
  // Look at each protocol interface for a match
 | 
						|
  //
 | 
						|
  Prot = CoreGetProtocolInterface (UserHandle, Protocol);
 | 
						|
  if (Prot == NULL) {
 | 
						|
    Status = EFI_UNSUPPORTED;
 | 
						|
    goto Done;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // This is the protocol interface entry for this protocol
 | 
						|
  //    
 | 
						|
  if (Attributes != EFI_OPEN_PROTOCOL_TEST_PROTOCOL) {
 | 
						|
    *Interface = Prot->Interface;
 | 
						|
  }
 | 
						|
  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) {
 | 
						|
      ByDriver = TRUE;
 | 
						|
      if (ExactMatch) {
 | 
						|
        Status = EFI_ALREADY_STARTED;
 | 
						|
        goto Done;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    if (OpenData->Attributes & EFI_OPEN_PROTOCOL_EXCLUSIVE) {
 | 
						|
      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) && (!Disconnect); Link = Link->ForwardLink) {
 | 
						|
          OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
 | 
						|
          if (OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) {
 | 
						|
            Disconnect = TRUE;
 | 
						|
            CoreReleaseProtocolLock ();
 | 
						|
            Status = CoreDisconnectController (UserHandle, OpenData->AgentHandle, NULL);
 | 
						|
            CoreAcquireProtocolLock ();
 | 
						|
            if (EFI_ERROR (Status)) {
 | 
						|
              Status = EFI_ACCESS_DENIED;
 | 
						|
              goto Done;
 | 
						|
            }
 | 
						|
          }
 | 
						|
        }
 | 
						|
      } 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 = CoreAllocateBootServicesPool (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:
 | 
						|
  //
 | 
						|
  // Done. Release the database lock are return
 | 
						|
  //
 | 
						|
  CoreReleaseProtocolLock ();
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
CoreCloseProtocol (
 | 
						|
  IN  EFI_HANDLE                UserHandle,
 | 
						|
  IN  EFI_GUID                  *Protocol,
 | 
						|
  IN  EFI_HANDLE                AgentHandle,
 | 
						|
  IN  EFI_HANDLE                ControllerHandle  
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Closes a protocol on a handle that was opened using OpenProtocol().
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  UserHandle       -  The handle for the protocol interface that was previously opened
 | 
						|
                      with OpenProtocol(), and is now being closed.
 | 
						|
  Protocol         -  The published unique identifier of the protocol. It is the caller's
 | 
						|
                      responsibility to pass in a valid GUID.
 | 
						|
  AgentHandle      -  The handle of the agent that is closing the protocol interface.
 | 
						|
  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.
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  EFI_SUCCESS             - The protocol instance was closed.
 | 
						|
  EFI_INVALID_PARAMETER   - Handle, AgentHandle or ControllerHandle is not a valid EFI_HANDLE. 
 | 
						|
  EFI_NOT_FOUND           - Can not find the specified protocol or AgentHandle.
 | 
						|
  
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_STATUS          Status;
 | 
						|
  PROTOCOL_INTERFACE  *ProtocolInterface;
 | 
						|
  LIST_ENTRY          *Link;
 | 
						|
  OPEN_PROTOCOL_DATA  *OpenData;
 | 
						|
 | 
						|
  //
 | 
						|
  // Check for invalid parameters
 | 
						|
  //
 | 
						|
  Status = CoreValidateHandle (UserHandle);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  Status = CoreValidateHandle (AgentHandle);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  if (ControllerHandle != NULL_HANDLE) {
 | 
						|
    Status = CoreValidateHandle (ControllerHandle);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  if (Protocol == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Lock the protocol database
 | 
						|
  //
 | 
						|
  CoreAcquireProtocolLock ();
 | 
						|
 | 
						|
  //
 | 
						|
  // 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;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
CoreOpenProtocolInformation (
 | 
						|
  IN  EFI_HANDLE                          UserHandle,
 | 
						|
  IN  EFI_GUID                            *Protocol,
 | 
						|
  OUT EFI_OPEN_PROTOCOL_INFORMATION_ENTRY **EntryBuffer,
 | 
						|
  OUT UINTN                               *EntryCount
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Return information about Opened protocols in the system
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  UserHandle  - The handle to close the protocol interface on
 | 
						|
 | 
						|
  Protocol    - The ID of the protocol 
 | 
						|
 | 
						|
  EntryBuffer - A pointer to a buffer of open protocol information in the form of
 | 
						|
                EFI_OPEN_PROTOCOL_INFORMATION_ENTRY structures.
 | 
						|
 | 
						|
  EntryCount  - Number of EntryBuffer entries
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  
 | 
						|
--*/
 | 
						|
{
 | 
						|
  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 ();
 | 
						|
 | 
						|
  //
 | 
						|
  // 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 = CoreAllocateBootServicesPool (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 are return
 | 
						|
  //
 | 
						|
  CoreReleaseProtocolLock ();
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
CoreProtocolsPerHandle (
 | 
						|
  IN EFI_HANDLE       UserHandle,
 | 
						|
  OUT EFI_GUID        ***ProtocolBuffer,
 | 
						|
  OUT UINTN           *ProtocolBufferCount
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Retrieves the list of protocol interface GUIDs that are installed on a handle in a buffer allocated
 | 
						|
 from pool.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  UserHandle           - The handle from which to retrieve the list of protocol interface
 | 
						|
                          GUIDs.
 | 
						|
 | 
						|
  ProtocolBuffer       - A pointer to the list of protocol interface GUID pointers that are
 | 
						|
                          installed on Handle.
 | 
						|
 | 
						|
  ProtocolBufferCount  - A pointer to the number of GUID pointers present in
 | 
						|
                          ProtocolBuffer.
 | 
						|
 | 
						|
Returns:
 | 
						|
  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.
 | 
						|
  EFI_INVALID_PARAMETER   -  Handle is NULL.
 | 
						|
  EFI_INVALID_PARAMETER   -  Handle is not a valid EFI_HANDLE.
 | 
						|
  EFI_INVALID_PARAMETER   -  ProtocolBuffer is NULL.
 | 
						|
  EFI_INVALID_PARAMETER   -  ProtocolBufferCount is NULL.
 | 
						|
  EFI_OUT_OF_RESOURCES    -  There is not enough pool memory to store the results.
 | 
						|
  
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_STATUS                          Status;
 | 
						|
  IHANDLE                             *Handle;
 | 
						|
  PROTOCOL_INTERFACE                  *Prot;
 | 
						|
  LIST_ENTRY                          *Link;
 | 
						|
  UINTN                               ProtocolCount;
 | 
						|
  EFI_GUID                            **Buffer;
 | 
						|
 | 
						|
  Status = CoreValidateHandle (UserHandle);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  Handle = (IHANDLE *)UserHandle;
 | 
						|
 | 
						|
  if (ProtocolBuffer == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  if (ProtocolBufferCount == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  *ProtocolBufferCount = 0;
 | 
						|
 | 
						|
  ProtocolCount = 0;
 | 
						|
 | 
						|
  CoreAcquireProtocolLock ();
 | 
						|
  
 | 
						|
  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 = CoreAllocateBootServicesPool (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;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
UINT64
 | 
						|
CoreGetHandleDatabaseKey (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  return handle database key.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  None
 | 
						|
  
 | 
						|
Returns:
 | 
						|
  
 | 
						|
  Handle database key.
 | 
						|
  
 | 
						|
--*/
 | 
						|
{
 | 
						|
  return gHandleDatabaseKey;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
VOID
 | 
						|
CoreConnectHandlesByKey (
 | 
						|
  UINT64  Key
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Go connect any handles that were created or modified while a image executed.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  Key  -  The Key to show that the handle has been created/modified
 | 
						|
 | 
						|
Returns:
 | 
						|
  
 | 
						|
  None
 | 
						|
--*/
 | 
						|
{
 | 
						|
  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 = CoreAllocateBootServicesPool (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);
 | 
						|
}
 |