/** 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. @param UserHandle The handle on which the protocol is installed @param Prot The protocol to disconnect drivers from @retval EFI_SUCCESS Drivers using the protocol interface are all disconnected @retval EFI_ACCESS_DENIED Failed to disconnect one or all of the drivers **/ EFI_STATUS CoreDisconnectControllersUsingProtocolInterface ( IN EFI_HANDLE UserHandle, IN PROTOCOL_INTERFACE *Prot ) { 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; Link = Link->ForwardLink) { OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE); if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) { CoreReleaseProtocolLock (); Status = CoreDisconnectController (UserHandle, OpenData->AgentHandle, NULL); CoreAcquireProtocolLock (); if (!EFI_ERROR (Status)) { ItemFound = TRUE; } break; } } } while (ItemFound); if (!EFI_ERROR (Status)) { // // Attempt to remove BY_HANDLE_PROTOOCL and GET_PROTOCOL and TEST_PROTOCOL Open List items // for (Link = Prot->OpenList.ForwardLink; Link != &Prot->OpenList;) { 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)) != 0) { Link = RemoveEntryList (&OpenData->Link); Prot->OpenListCount--; CoreFreePool (OpenData); } else { Link = Link->ForwardLink; } } } // // 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_BOOTSERVICE EFI_STATUS EFIAPI CoreReinstallProtocolInterface ( IN EFI_HANDLE UserHandle, IN EFI_GUID *Protocol, IN VOID *OldInterface, IN VOID *NewInterface ) /*++ Routine Description: Reinstall a protocol interface on a device handle. The OldInterface for Protocol is replaced by the NewInterface. Arguments: UserHandle - Handle on which the interface is to be reinstalled Protocol - The numeric ID of the interface OldInterface - A pointer to the old interface NewInterface - A pointer to the new interface Returns: Status code. On EFI_SUCCESS The protocol interface was installed On EFI_NOT_FOUND The OldInterface on the handle was not found On EFI_INVALID_PARAMETER One of the parameters has an invalid value --*/ { EFI_STATUS Status; IHANDLE *Handle; PROTOCOL_INTERFACE *Prot; PROTOCOL_ENTRY *ProtEntry; Status = CoreValidateHandle (UserHandle); if (EFI_ERROR (Status)) { return Status; } if (Protocol == NULL) { return EFI_INVALID_PARAMETER; } Handle = (IHANDLE *) UserHandle; // // Lock the protocol database // CoreAcquireProtocolLock (); // // Check that Protocol exists on UserHandle, and Interface matches the interface in the database // Prot = CoreFindProtocolInterface (UserHandle, Protocol, OldInterface); if (Prot == NULL) { CoreReleaseProtocolLock (); return EFI_NOT_FOUND; } // // Attempt to disconnect all drivers that are using the protocol interface that is about to be reinstalled // Status = CoreDisconnectControllersUsingProtocolInterface ( UserHandle, Prot ); if (EFI_ERROR (Status)) { // // One or more drivers refused to release, so return the error // CoreReleaseProtocolLock (); return Status; } // // Remove the protocol interface from the protocol // Prot = CoreRemoveInterfaceFromProtocol (Handle, Protocol, OldInterface); if (Prot == NULL) { CoreReleaseProtocolLock (); return EFI_NOT_FOUND; } ProtEntry = Prot->Protocol; // // Update the interface on the protocol // Prot->Interface = NewInterface; // // Add this protocol interface to the tail of the // protocol entry // InsertTailList (&ProtEntry->Protocols, &Prot->ByProtocol); // // Update the Key to show that the handle has been created/modified // gHandleDatabaseKey++; Handle->Key = gHandleDatabaseKey; // // Release the lock and connect all drivers to UserHandle // CoreReleaseProtocolLock (); Status = CoreConnectController ( UserHandle, NULL, NULL, TRUE ); CoreAcquireProtocolLock (); // // Notify the notification list for this protocol // CoreNotifyProtocolEntry (ProtEntry); CoreReleaseProtocolLock (); return EFI_SUCCESS; }
/** Reinstall a protocol interface on a device handle. The OldInterface for Protocol is replaced by the NewInterface. @param UserHandle Handle on which the interface is to be reinstalled @param Protocol The numeric ID of the interface @param OldInterface A pointer to the old interface @param NewInterface A pointer to the new interface @retval EFI_SUCCESS The protocol interface was installed @retval EFI_NOT_FOUND The OldInterface on the handle was not found @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value **/ EFI_STATUS EFIAPI CoreReinstallProtocolInterface ( IN EFI_HANDLE UserHandle, IN EFI_GUID *Protocol, IN VOID *OldInterface, IN VOID *NewInterface ) { EFI_STATUS Status; IHANDLE *Handle; PROTOCOL_INTERFACE *Prot; PROTOCOL_ENTRY *ProtEntry; Status = CoreValidateHandle (UserHandle); if (EFI_ERROR (Status)) { return Status; } if (Protocol == NULL) { return EFI_INVALID_PARAMETER; } Handle = (IHANDLE *) UserHandle; // // Lock the protocol database // CoreAcquireProtocolLock (); // // Check that Protocol exists on UserHandle, and Interface matches the interface in the database // Prot = CoreFindProtocolInterface (UserHandle, Protocol, OldInterface); 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 reinstalled // 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 // Prot = CoreRemoveInterfaceFromProtocol (Handle, Protocol, OldInterface); if (Prot == NULL) { Status = EFI_NOT_FOUND; goto Done; } ProtEntry = Prot->Protocol; // // Update the interface on the protocol // Prot->Interface = NewInterface; // // Add this protocol interface to the tail of the // protocol entry // InsertTailList (&ProtEntry->Protocols, &Prot->ByProtocol); // // Update the Key to show that the handle has been created/modified // gHandleDatabaseKey++; Handle->Key = gHandleDatabaseKey; // // Release the lock and connect all drivers to UserHandle // CoreReleaseProtocolLock (); // // Return code is ignored on purpose. // CoreConnectController ( UserHandle, NULL, NULL, TRUE ); CoreAcquireProtocolLock (); // // Notify the notification list for this protocol // CoreNotifyProtocolEntry (ProtEntry); Status = EFI_SUCCESS; Done: CoreReleaseProtocolLock (); return Status; }