mirror of https://github.com/acidanthera/audk.git
1700 lines
42 KiB
C
1700 lines
42 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 2006, Intel Corporation
|
|||
|
All rights reserved. This program and the accompanying materials
|
|||
|
are licensed and made available under the terms and conditions of the BSD License
|
|||
|
which accompanies this distribution. The full text of the license may be found at
|
|||
|
http://opensource.org/licenses/bsd-license.php
|
|||
|
|
|||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
|||
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
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 (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.
|
|||
|
|
|||
|
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 %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
|
|||
|
//
|
|||
|
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 (EFI_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;
|
|||
|
}
|
|||
|
|
|||
|
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<EFBFBD><EFBFBD>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);
|
|||
|
}
|