📄 handle.c
字号:
list. The pairs are the arguments to InstallProtocolInterface().
All the protocols are added to Handle.
Returns:
Status code
--*/
{
va_list args;
EFI_STATUS Status;
EFI_GUID *Protocol;
VOID *Interface;
EFI_TPL OldTpl;
UINTN Index;
EFI_HANDLE OldHandle;
EFI_DEVICE_PATH *DevicePath;
EFI_HANDLE DeviceHandle;
//
// Syncronize with notifcations.
//
OldTpl = BS->RaiseTPL (TPL_NOTIFY);
OldHandle = *Handle;
//
// Check for duplicate device path
//
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 *);
//
// Install it
//
if (CompareGuid (Protocol, &DevicePathProtocol) == 0) {
//
// Make sure you are installing on top a device path that has already
// been added.
//
DeviceHandle = NULL;
DevicePath = Interface;
Status = LocateDevicePath (&DevicePathProtocol, &DevicePath, &DeviceHandle);
if (!EFI_ERROR(Status) && DeviceHandle != NULL && IsDevicePathEnd(DevicePath)) {
BS->RestoreTPL(OldTpl);
return EFI_ALREADY_STARTED;
}
}
}
//
// 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 *);
//
// Install it
//
DEBUG((D_INFO, "InstallProtocolInterface: %d %x\n", Protocol, Interface));
Status = InstallProtocolInterface (Handle, Protocol, EFI_NATIVE_INTERFACE, Interface);
if (EFI_ERROR(Status)) {
break;
}
}
//
// 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);
while (Index) {
Protocol = va_arg(args, EFI_GUID *);
Interface = va_arg(args, VOID *);
UninstallProtocolInterface (*Handle, Protocol, Interface);
Index -= 1;
}
*Handle = OldHandle;
}
//
// Done
//
BS->RestoreTPL(OldTpl);
return Status;
}
EFI_STATUS
DisconnectControllersUsingProtocolInterface (
IN EFI_HANDLE UserHandle,
PROTOCOL_INTERFACE *Prot
)
/*++
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:
Handle - The handle to remove the protocol handler from
ProtocolHandle - The protocol, of protocol:interface, to remove
Interface - The interface, of protocol:interface, to remove
Returns:
Status code
--*/
{
EFI_STATUS Status;
BOOLEAN ItemFound;
LIST_ENTRY *Link;
OPEN_PROTOCOL_DATA *OpenData;
//
// Attempt to disconnect all drivers from this protocol interface
//
do {
ItemFound = FALSE;
for ( Link = Prot->OpenList.Flink;
(Link != &Prot->OpenList) & !ItemFound;
Link = Link->Flink
) {
OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
if (OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) {
ItemFound = TRUE;
ReleaseLock (&ProtocolDatabaseLock);
// Status = BS->DisconnectController (OpenData->ControllerHandle, OpenData->AgentHandle, NULL);
Status = BS->DisconnectController (UserHandle, OpenData->AgentHandle, NULL);
AcquireLock (&ProtocolDatabaseLock);
if (EFI_ERROR (Status)) {
return EFI_ACCESS_DENIED;
}
}
}
} while (ItemFound == TRUE);
//
// Attempt to remove BY_HANDLE_PROTOOCL and GET_PROTOCOL and TEST_PROTOCOL Open List items
//
do {
ItemFound = FALSE;
for ( Link = Prot->OpenList.Flink;
(Link != &Prot->OpenList) & !ItemFound;
Link = Link->Flink
) {
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--;
BS->FreePool (OpenData);
}
}
} while (ItemFound == TRUE);
//
// If there are still Open Items in the list, then reconnect all the drivers and return an error
//
if (Prot->OpenListCount > 0) {
ReleaseLock (&ProtocolDatabaseLock);
Status = BS->ConnectController (UserHandle, NULL, NULL, TRUE);
AcquireLock (&ProtocolDatabaseLock);
return EFI_ACCESS_DENIED;
}
return EFI_SUCCESS;
}
EFI_STATUS
BOOTSERVICE
UninstallProtocolInterface (
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:
Handle - The handle to remove the protocol handler from
ProtocolHandle - The protocol, of protocol:interface, to remove
Interface - The interface, of protocol:interface, to remove
Returns:
Status code
--*/
{
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 = ValidateHandle (UserHandle);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Lock the protocol database
//
AcquireLock (&ProtocolDatabaseLock);
//
// Check that Protocol exists on UserHandle, and Interface matches the interface in the database
//
Prot = FindProtocolInterface (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 = DisconnectControllersUsingProtocolInterface (
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 = UserHandle;
Prot = RemoveInterfaceFromProtocol (Handle, Protocol, Interface);
//
// Update the Key to show that the handle has been created/modified
//
HandleDatabaseKey++;
Handle->Key = HandleDatabaseKey;
if (Prot != NULL) {
//
// Remove the protocol interface from the handle
//
RemoveEntryList (&Prot->Link);
//
// Free the memory
//
Prot->Signature = 0;
BS->FreePool (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);
BS->FreePool (Handle);
}
Done:
//
// Done, unlock the database and return
//
ReleaseLock (&ProtocolDatabaseLock);
return Status;
}
EFI_STATUS
BOOTSERVICE
UninstallMultipleProtocolInterfaces (
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;
//
// Uninstall 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 *);
//
// Uninstall it
//
DEBUG((D_INFO, "UninstallProtocolInterface: %d %x\n", Protocol, Interface));
Status = UninstallProtocolInterface (Handle, Protocol, Interface);
if (EFI_ERROR(Status)) {
break;
}
}
//
// 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);
while (Index) {
Protocol = va_arg(args, EFI_GUID *);
Interface = va_arg(args, VOID *);
InstallProtocolInterface (&Handle, Protocol, EFI_NATIVE_INTERFACE, Interface);
Index -= 1;
}
}
return Status;
}
PROTOCOL_INTERFACE *
GetProtocolEntry (
IN EFI_HANDLE UserHandle,
IN EFI_GUID *Protocol
)
{
PROTOCOL_ENTRY *ProtEntry;
PROTOCOL_INTERFACE *Prot;
IHANDLE *Handle;
LIST_ENTRY *Link;
Handle = UserHandle;
if (Handle == NULL) {
return NULL;
}
if (Handle->Signature != EFI_HANDLE_SIGNATURE) {
return NULL;
}
//
// Look at each protocol interface for a match
//
for (Link = Handle->Protocols.Flink; Link != &Handle->Protocols; Link = Link->Flink) {
Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
ProtEntry = Prot->Protocol;
if (CompareGuid (&ProtEntry->ProtocolID, Protocol) == 0) {
return Prot;
}
}
return NULL;
}
EFI_STATUS
BOOTSERVICE
HandleProtocol (
IN EFI_HANDLE UserHandle,
IN EFI_GUID *Protocol,
OUT VOID **Interface
)
{
return OpenProtocol (
UserHandle,
Protocol,
Interface,
NULL, //gMyImageHandle,
NULL,
EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
);
}
EFI_STATUS
BOOTSERVICE
OpenProtocol (
IN EFI_HANDLE UserHandle,
IN EFI_GUID *Protocol,
OUT VOID **Interface,
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 -
NotifyFunction -
Attributes -
Returns:
The requested protocol interface for the handle
--*/
{
EFI_STATUS Status;
PROTOCOL_INTERFACE *Prot;
LIST_ENTRY *Link;
OPEN_PROTOCOL_DATA *OpenData;
BOOLEAN ByDriver;
BOOLEAN Exclusive;
BOOLEAN Disconnect;
BOOLEAN ExactMatch;
//
// Check for invalid Protocol
//
if (Protocol == NULL) {
return EFI_INVALID_PARAMETER;
}
//
// Check for invalid Interface
//
if (Attributes != EFI_OPEN_PROTOCOL_TEST_PROTOCOL && Interface == NULL) {
return EFI_INVALID_PARAMETER;
}
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -