📄 handle.c
字号:
/*++
Copyright (c) 1999 - 2002 Intel Corporation. All rights reserved
This software and associated documentation (if any) is furnished
under a license and may only be used or copied in accordance
with the terms of the license. Except as permitted by such
license, no part of this software or documentation may be
reproduced, stored in a retrieval system, or transmitted in any
form or by any means without the express written consent of
Intel Corporation.
Module Name:
handle.c
Abstract:
EFI handle & protocol handling
Revision History
--*/
#include "hand.h"
//
// ProtocolDatabase - A list of all protocols in the system. (simple list for now)
// HandleQueue - A list of all the handles in the system
// ProtocolDatabaseLock - Lock to protect the ProtocolDatabase
//
STATIC LIST_ENTRY ProtocolDatabase;
INTERNAL LIST_ENTRY HandleList;
INTERNAL FLOCK ProtocolDatabaseLock;
UINT64 HandleDatabaseKey = 0;
VOID
InitializeHandle(
VOID
)
/*++
Routine Description:
Initialize handle & protocol support
Arguments:
None
Returns:
None
--*/
{
InitializeListHead (&ProtocolDatabase);
InitializeListHead (&HandleList);
InitializeLock (&ProtocolDatabaseLock, TPL_NOTIFY);
}
EFI_STATUS
ValidateHandle (
IN EFI_HANDLE UserHandle
)
{
IHANDLE *Handle;
Handle = UserHandle;
if (Handle == NULL) {
return EFI_INVALID_PARAMETER;
}
if (Handle->Signature != EFI_HANDLE_SIGNATURE) {
return EFI_INVALID_PARAMETER;
}
return EFI_SUCCESS;
}
INTERNAL
PROTOCOL_ENTRY *
FindProtocolEntry(
IN EFI_GUID *Protocol,
IN BOOLEAN Create
)
/*++
Routine Description:
Finds the protocl entry for the requested protocol.
N.B. The ProtocolDatabaseLock 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, *ProtEntry;
ASSERT_LOCKED(&ProtocolDatabaseLock);
//
// Search the database for the matching GUID
//
ProtEntry = NULL;
for (Link=ProtocolDatabase.Flink;
Link != &ProtocolDatabase;
Link=Link->Flink) {
Item = CR(Link, PROTOCOL_ENTRY, AllEntries, PROTOCOL_ENTRY_SIGNATURE);
if (CompareGuid (&Item->ProtocolID, Protocol) == 0) {
//
// 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 && Create) {
ProtEntry = (PROTOCOL_ENTRY *) AllocatePool (sizeof(PROTOCOL_ENTRY));
if (ProtEntry) {
//
// Initialize new protocol entry structure
//
ProtEntry->Signature = PROTOCOL_ENTRY_SIGNATURE;
ProtEntry->ProtocolID = *Protocol;
InitializeListHead (&ProtEntry->Protocols);
InitializeListHead (&ProtEntry->Notify);
//
// Add it to protocol database
//
InsertTailList (&ProtocolDatabase, &ProtEntry->AllEntries);
}
}
return ProtEntry;
}
PROTOCOL_INTERFACE *
FindProtocolInterface (
IN IHANDLE *Handle,
IN EFI_GUID *Protocol,
IN VOID *Interface
)
{
PROTOCOL_INTERFACE *Prot;
PROTOCOL_ENTRY *ProtEntry;
LIST_ENTRY *Link;
ASSERT_LOCKED(&ProtocolDatabaseLock);
Prot = NULL;
//
// Lookup the protocol entry for this protocol ID
//
ProtEntry = FindProtocolEntry (Protocol, FALSE);
if (ProtEntry) {
//
// Look at each protocol interface for any matches
//
for (Link = Handle->Protocols.Flink; Link != &Handle->Protocols; Link=Link->Flink) {
//
// 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
UnregisterProtocolNotifyEvent (
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;
AcquireLock (&ProtocolDatabaseLock);
for (Link = ProtocolDatabase.Flink;
Link != &ProtocolDatabase;
Link = Link->Flink) {
ProtEntry = CR(Link, PROTOCOL_ENTRY, AllEntries, PROTOCOL_ENTRY_SIGNATURE);
for (NotifyLink = ProtEntry->Notify.Flink;
NotifyLink != &ProtEntry->Notify;
NotifyLink = NotifyLink->Flink) {
ProtNotify = CR(NotifyLink, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE);
if (ProtNotify->Event == Event) {
RemoveEntryList(&ProtNotify->Link);
FreePool(ProtNotify);
ReleaseLock (&ProtocolDatabaseLock);
return EFI_SUCCESS;
}
}
}
ReleaseLock (&ProtocolDatabaseLock);
return EFI_NOT_FOUND;
}
EFI_STATUS
UnregisterProtocolNotify (
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 = UnregisterProtocolNotifyEvent(Event);
} while (!EFI_ERROR(Status));
return EFI_SUCCESS;
}
EFI_STATUS
BOOTSERVICE
InstallProtocolInterface (
IN OUT EFI_HANDLE *UserHandle,
IN EFI_GUID *Protocol,
IN EFI_INTERFACE_TYPE InterfaceType,
IN VOID *Interface
)
/*++
Routine Description:
Installs a protocol interface into the boot services environment
Arguments:
Handle - 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
Interface - The interface for the protocol being added
Returns:
Status code
--*/
{
PROTOCOL_INTERFACE *Prot;
PROTOCOL_ENTRY *ProtEntry;
IHANDLE *Handle;
EFI_STATUS Status;
VOID *ExistingInterface;
Status = EFI_OUT_OF_RESOURCES;
Prot = NULL;
Handle = NULL;
//
// Validate parameters
//
if (UserHandle == NULL || Protocol == NULL) {
return EFI_INVALID_PARAMETER;
}
//
// Only native style interfaces are supported
//
if (InterfaceType != EFI_NATIVE_INTERFACE) {
return EFI_INVALID_PARAMETER;
}
if (*UserHandle != NULL) {
Status = BS->HandleProtocol(*UserHandle, Protocol, (VOID **)&ExistingInterface);
if (!EFI_ERROR (Status)) {
return EFI_INVALID_PARAMETER;
}
}
//
// Lock the protocol database
//
AcquireLock (&ProtocolDatabaseLock);
//
// Lookup the Protocol Entry for the requested protocol
//
ProtEntry = FindProtocolEntry (Protocol, TRUE);
if (!ProtEntry) {
goto Done;
}
//
// Allocate a new protocol interface structure
//
Prot = AllocateZeroPool(sizeof(PROTOCOL_INTERFACE));
if (!Prot) {
goto Done;
}
//
// If caller didn't supply a handle, allocate a new one
//
Handle = *UserHandle;
if (!Handle) {
Handle = (IHANDLE *) AllocateZeroPool(sizeof(IHANDLE));
if (!Handle) {
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
//
HandleDatabaseKey++;
Handle->Key = HandleDatabaseKey;
//
// Add this handle to the list global list of all handles
// in the system
//
InsertTailList (&HandleList, &Handle->AllHandles);
}
if (Handle->Signature != EFI_HANDLE_SIGNATURE) {
Status = EFI_INVALID_PARAMETER;
goto Done;
}
//
// Each interface that is added must be unique
//
ASSERT (FindProtocolInterface (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
//
NotifyProtocolEntry (ProtEntry);
Status = EFI_SUCCESS;
Done:
//
// Done, unlock the database and return
//
ReleaseLock (&ProtocolDatabaseLock);
if (!EFI_ERROR(Status)) {
//
// Return the new handle back to the caller
//
*UserHandle = Handle;
} else {
//
// There was an error, clean up
//
if (Prot) {
FreePool (Prot);
}
}
return Status;
}
EFI_STATUS
BOOTSERVICE
InstallMultipleProtocolInterfaces (
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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -