/** Add a new protocol notification record for the request protocol. @param Protocol The requested protocol to add the notify registration @param Event The event to signal @param Registration Returns the registration record @retval EFI_INVALID_PARAMETER Invalid parameter @retval EFI_SUCCESS Successfully returned the registration record that has been added **/ EFI_STATUS EFIAPI CoreRegisterProtocolNotify ( IN EFI_GUID *Protocol, IN EFI_EVENT Event, OUT VOID **Registration ) { PROTOCOL_ENTRY *ProtEntry; PROTOCOL_NOTIFY *ProtNotify; EFI_STATUS Status; if ((Protocol == NULL) || (Event == NULL) || (Registration == NULL)) { return EFI_INVALID_PARAMETER; } CoreAcquireProtocolLock (); ProtNotify = NULL; // // Get the protocol entry to add the notification too // ProtEntry = CoreFindProtocolEntry (Protocol, TRUE); if (ProtEntry != NULL) { // // Allocate a new notification record // ProtNotify = AllocatePool (sizeof(PROTOCOL_NOTIFY)); if (ProtNotify != NULL) { ((IEVENT *)Event)->ExFlag |= EVT_EXFLAG_EVENT_PROTOCOL_NOTIFICATION; ProtNotify->Signature = PROTOCOL_NOTIFY_SIGNATURE; ProtNotify->Protocol = ProtEntry; ProtNotify->Event = Event; // // start at the begining // ProtNotify->Position = &ProtEntry->Protocols; InsertTailList (&ProtEntry->Notify, &ProtNotify->Link); } } CoreReleaseProtocolLock (); // // Done. If we have a protocol notify entry, then return it. // Otherwise, we must have run out of resources trying to add one // Status = EFI_OUT_OF_RESOURCES; if (ProtNotify != NULL) { *Registration = ProtNotify; Status = EFI_SUCCESS; } return Status; }
/** Removes an event from a register protocol notify list on a protocol. @param Event The event to search for in the protocol database. @return EFI_SUCCESS if the event was found and removed. @return EFI_NOT_FOUND if the event was not found in the protocl database. **/ EFI_STATUS CoreUnregisterProtocolNotifyEvent ( IN EFI_EVENT Event ) { 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_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; }
EFI_BOOTSERVICE EFI_STATUS EFIAPI CoreRegisterProtocolNotify ( IN EFI_GUID *Protocol, IN EFI_EVENT Event, OUT VOID **Registration ) /*++ Routine Description: Add a new protocol notification record for the request protocol. Arguments: Protocol - The requested protocol to add the notify registration Event - The event to signal Registration - Returns the registration record Returns: EFI_INVALID_PARAMETER - Invalid parameter EFI_SUCCESS - Successfully returned the registration record that has been added --*/ { PROTOCOL_ENTRY *ProtEntry; PROTOCOL_NOTIFY *ProtNotify; EFI_STATUS Status; if ((Protocol == NULL) || (Event == NULL) || (Registration == NULL)) { return EFI_INVALID_PARAMETER; } CoreAcquireProtocolLock (); ProtNotify = NULL; // // Get the protocol entry to add the notification too // ProtEntry = CoreFindProtocolEntry (Protocol, TRUE); if (ProtEntry != NULL) { // // Allocate a new notification record // ProtNotify = CoreAllocateBootServicesPool (sizeof(PROTOCOL_NOTIFY)); if (ProtNotify != NULL) { ProtNotify->Signature = PROTOCOL_NOTIFY_SIGNATURE; ProtNotify->Protocol = ProtEntry; ProtNotify->Event = Event; // // start at the begining // ProtNotify->Position = &ProtEntry->Protocols; InsertTailList (&ProtEntry->Notify, &ProtNotify->Link); } } CoreReleaseProtocolLock (); // // Done. If we have a protocol notify entry, then return it. // Otherwise, we must have run out of resources trying to add one // Status = EFI_OUT_OF_RESOURCES; if (ProtNotify != NULL) { *Registration = ProtNotify; Status = EFI_SUCCESS; } return Status; }
/** Uninstalls all instances of a protocol:interfacer from a handle. If the last protocol interface is remove from the handle, the handle is freed. @param UserHandle The handle to remove the protocol handler from @param Protocol The protocol, of protocol:interface, to remove @param Interface The interface, of protocol:interface, to remove @retval EFI_INVALID_PARAMETER Protocol is NULL. @retval EFI_SUCCESS Protocol interface successfully uninstalled. **/ EFI_STATUS EFIAPI CoreUninstallProtocolInterface ( IN EFI_HANDLE UserHandle, IN EFI_GUID *Protocol, IN VOID *Interface ) { 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; }
/** 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; }
/** Installs a protocol interface into the boot services environment. @param UserHandle The handle to install the protocol handler on, or NULL if a new handle is to be allocated @param Protocol The protocol to add to the handle @param InterfaceType Indicates whether Interface is supplied in native form. @param Interface The interface for the protocol being added @param Notify indicates whether notify the notification list for this protocol @retval EFI_INVALID_PARAMETER Invalid parameter @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate @retval EFI_SUCCESS Protocol interface successfully installed **/ EFI_STATUS CoreInstallProtocolInterfaceNotify ( IN OUT EFI_HANDLE *UserHandle, IN EFI_GUID *Protocol, IN EFI_INTERFACE_TYPE InterfaceType, IN VOID *Interface, IN BOOLEAN Notify ) { 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((DEBUG_INFO, "InstallProtocolInterface: %g %p\n", Protocol, Interface)); Status = EFI_OUT_OF_RESOURCES; Prot = NULL; Handle = NULL; if (*UserHandle != NULL) { 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 = AllocateZeroPool (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 = AllocateZeroPool (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); } else { Status = CoreValidateHandle (Handle); if (EFI_ERROR (Status)) { DEBUG((DEBUG_ERROR, "InstallProtocolInterface: input handle at 0x%x is invalid\n", Handle)); 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); } DEBUG((DEBUG_ERROR, "InstallProtocolInterface: %g %p failed with %r\n", Protocol, Interface, Status)); } return Status; }
/** 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; }