/** 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. @param Handle The handle to search the protocol on @param Protocol GUID of the protocol @param Interface The interface for the protocol being searched @return Protocol instance (NULL: Not found) **/ PROTOCOL_INTERFACE * SmmFindProtocolInterface ( IN IHANDLE *Handle, IN EFI_GUID *Protocol, IN VOID *Interface ) { PROTOCOL_INTERFACE *Prot; PROTOCOL_ENTRY *ProtEntry; LIST_ENTRY *Link; Prot = NULL; // // Lookup the protocol entry for this protocol ID // ProtEntry = SmmFindProtocolEntry (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; }
/** Add a new protocol notification record for the request protocol. @param Protocol The requested protocol to add the notify registration @param Function Points to the notification function @param Registration Returns the registration record @retval EFI_SUCCESS Successfully returned the registration record that has been added or unhooked @retval EFI_INVALID_PARAMETER Protocol is NULL or Registration is NULL @retval EFI_OUT_OF_RESOURCES Not enough memory resource to finish the request @retval EFI_NOT_FOUND If the registration is not found when Function == NULL **/ EFI_STATUS EFIAPI SmmRegisterProtocolNotify ( IN CONST EFI_GUID *Protocol, IN EFI_SMM_NOTIFY_FN Function, OUT VOID **Registration ) { PROTOCOL_ENTRY *ProtEntry; PROTOCOL_NOTIFY *ProtNotify; LIST_ENTRY *Link; EFI_STATUS Status; if (Protocol == NULL || Registration == NULL) { return EFI_INVALID_PARAMETER; } if (Function == NULL) { // // Get the protocol entry per Protocol // ProtEntry = SmmFindProtocolEntry ((EFI_GUID *) Protocol, FALSE); if (ProtEntry != NULL) { ProtNotify = (PROTOCOL_NOTIFY * )*Registration; for (Link = ProtEntry->Notify.ForwardLink; Link != &ProtEntry->Notify; Link = Link->ForwardLink) { // // Compare the notification record // if (ProtNotify == (CR(Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE))) { // // If Registration is an existing registration, then unhook it // ProtNotify->Signature = 0; RemoveEntryList (&ProtNotify->Link); FreePool (ProtNotify); return EFI_SUCCESS; } } } // // If the registration is not found // return EFI_NOT_FOUND; } ProtNotify = NULL; // // Get the protocol entry to add the notification too // ProtEntry = SmmFindProtocolEntry ((EFI_GUID *) Protocol, TRUE); if (ProtEntry != NULL) { // // Find whether notification already exist // for (Link = ProtEntry->Notify.ForwardLink; Link != &ProtEntry->Notify; Link = Link->ForwardLink) { ProtNotify = CR(Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE); if (CompareGuid (&ProtNotify->Protocol->ProtocolID, Protocol) && (ProtNotify->Function == Function)) { // // Notification already exist // *Registration = ProtNotify; return EFI_SUCCESS; } } // // Allocate a new notification record // ProtNotify = AllocatePool (sizeof(PROTOCOL_NOTIFY)); if (ProtNotify != NULL) { ProtNotify->Signature = PROTOCOL_NOTIFY_SIGNATURE; ProtNotify->Protocol = ProtEntry; ProtNotify->Function = Function; // // Start at the ending // ProtNotify->Position = ProtEntry->Protocols.BackLink; InsertTailList (&ProtEntry->Notify, &ProtNotify->Link); } } // // 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; }
/** 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 SmmInstallProtocolInterfaceNotify ( 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_LOAD | DEBUG_INFO, "SmmInstallProtocolInterface: %g %p\n", Protocol, Interface)); Status = EFI_OUT_OF_RESOURCES; Prot = NULL; Handle = NULL; if (*UserHandle != NULL) { Status = SmmHandleProtocol (*UserHandle, Protocol, (VOID **)&ExistingInterface); if (!EFI_ERROR (Status)) { return EFI_INVALID_PARAMETER; } } // // Lookup the Protocol Entry for the requested protocol // ProtEntry = SmmFindProtocolEntry (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); // // Add this handle to the list global list of all handles // in the system // InsertTailList (&gHandleList, &Handle->AllHandles); } else { Status = SmmValidateHandle (Handle); if (EFI_ERROR (Status)) { DEBUG((DEBUG_ERROR, "SmmInstallProtocolInterface: input handle at 0x%x is invalid\n", Handle)); goto Done; } } // // Each interface that is added must be unique // ASSERT (SmmFindProtocolInterface (Handle, Protocol, Interface) == NULL); // // Initialize the protocol interface structure // Prot->Signature = PROTOCOL_INTERFACE_SIGNATURE; Prot->Handle = Handle; Prot->Protocol = ProtEntry; Prot->Interface = Interface; // // 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) { SmmNotifyProtocol (Prot); } Status = EFI_SUCCESS; Done: if (!EFI_ERROR (Status)) { // // Return the new handle back to the caller // *UserHandle = Handle; } else { // // There was an error, clean up // if (Prot != NULL) { FreePool (Prot); } DEBUG((DEBUG_ERROR, "SmmInstallProtocolInterface: %g %p failed with %r\n", Protocol, Interface, Status)); } return Status; }