handle.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 1,701 行 · 第 1/3 页
C
1,701 行
/*++
Copyright (c) 2004, 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 "hand.h"
#include EFI_PROTOCOL_DEFINITION (DevicePath)
//
// 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 EFI_LIST_ENTRY mProtocolDatabase = INITIALIZE_LIST_HEAD_VARIABLE (mProtocolDatabase);
EFI_LIST_ENTRY gHandleList = INITIALIZE_LIST_HEAD_VARIABLE (gHandleList);
EFI_LOCK gProtocolDatabaseLock = EFI_INITIALIZE_LOCK_VARIABLE (EFI_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.
N.B. The gProtocolDatabaseLock must be owned
Arguments:
Protocol - The ID of the protocol
Create - Create a new entry if not found
Returns:
Protocol entry
--*/
{
EFI_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 (EfiCompareGuid (&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;
ProtEntry->ProtocolID = *Protocol;
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;
EFI_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.
--*/
{
EFI_LIST_ENTRY *Link;
PROTOCOL_ENTRY *ProtEntry;
EFI_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_BOOTSERVICE
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 %x\n", Protocol, Interface));
Status = EFI_OUT_OF_RESOURCES;
Prot = NULL;
Handle = NULL;
ASSERT (NULL != gBS);
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
//
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?