2 Support functions for UEFI protocol notification infrastructure.
4 Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
12 Signal event for every protocol in protocol entry.
14 @param Prot Protocol interface
19 IN PROTOCOL_INTERFACE
*Prot
22 PROTOCOL_ENTRY
*ProtEntry
;
23 PROTOCOL_NOTIFY
*ProtNotify
;
26 ProtEntry
= Prot
->Protocol
;
27 for (Link
= ProtEntry
->Notify
.ForwardLink
; Link
!= &ProtEntry
->Notify
; Link
= Link
->ForwardLink
) {
28 ProtNotify
= CR (Link
, PROTOCOL_NOTIFY
, Link
, PROTOCOL_NOTIFY_SIGNATURE
);
29 ProtNotify
->Function (&ProtEntry
->ProtocolID
, Prot
->Interface
, Prot
->Handle
);
34 Removes Protocol from the protocol list (but not the handle list).
36 @param Handle The handle to remove protocol on.
37 @param Protocol GUID of the protocol to be moved
38 @param Interface The interface of the protocol
40 @return Protocol Entry
44 SmmRemoveInterfaceFromProtocol (
46 IN EFI_GUID
*Protocol
,
50 PROTOCOL_INTERFACE
*Prot
;
51 PROTOCOL_NOTIFY
*ProtNotify
;
52 PROTOCOL_ENTRY
*ProtEntry
;
55 Prot
= SmmFindProtocolInterface (Handle
, Protocol
, Interface
);
57 ProtEntry
= Prot
->Protocol
;
60 // If there's a protocol notify location pointing to this entry, back it up one
62 for (Link
= ProtEntry
->Notify
.ForwardLink
; Link
!= &ProtEntry
->Notify
; Link
= Link
->ForwardLink
) {
63 ProtNotify
= CR (Link
, PROTOCOL_NOTIFY
, Link
, PROTOCOL_NOTIFY_SIGNATURE
);
65 if (ProtNotify
->Position
== &Prot
->ByProtocol
) {
66 ProtNotify
->Position
= Prot
->ByProtocol
.BackLink
;
71 // Remove the protocol interface entry
73 RemoveEntryList (&Prot
->ByProtocol
);
80 Add a new protocol notification record for the request protocol.
82 @param Protocol The requested protocol to add the notify
84 @param Function Points to the notification function
85 @param Registration Returns the registration record
87 @retval EFI_SUCCESS Successfully returned the registration record
88 that has been added or unhooked
89 @retval EFI_INVALID_PARAMETER Protocol is NULL or Registration is NULL
90 @retval EFI_OUT_OF_RESOURCES Not enough memory resource to finish the request
91 @retval EFI_NOT_FOUND If the registration is not found when Function == NULL
96 SmmRegisterProtocolNotify (
97 IN CONST EFI_GUID
*Protocol
,
98 IN EFI_SMM_NOTIFY_FN Function
,
99 OUT VOID
**Registration
102 PROTOCOL_ENTRY
*ProtEntry
;
103 PROTOCOL_NOTIFY
*ProtNotify
;
107 if ((Protocol
== NULL
) || (Registration
== NULL
)) {
108 return EFI_INVALID_PARAMETER
;
111 if (Function
== NULL
) {
113 // Get the protocol entry per Protocol
115 ProtEntry
= SmmFindProtocolEntry ((EFI_GUID
*)Protocol
, FALSE
);
116 if (ProtEntry
!= NULL
) {
117 ProtNotify
= (PROTOCOL_NOTIFY
*)*Registration
;
118 for (Link
= ProtEntry
->Notify
.ForwardLink
;
119 Link
!= &ProtEntry
->Notify
;
120 Link
= Link
->ForwardLink
)
123 // Compare the notification record
125 if (ProtNotify
== (CR (Link
, PROTOCOL_NOTIFY
, Link
, PROTOCOL_NOTIFY_SIGNATURE
))) {
127 // If Registration is an existing registration, then unhook it
129 ProtNotify
->Signature
= 0;
130 RemoveEntryList (&ProtNotify
->Link
);
131 FreePool (ProtNotify
);
138 // If the registration is not found
140 return EFI_NOT_FOUND
;
146 // Get the protocol entry to add the notification too
148 ProtEntry
= SmmFindProtocolEntry ((EFI_GUID
*)Protocol
, TRUE
);
149 if (ProtEntry
!= NULL
) {
151 // Find whether notification already exist
153 for (Link
= ProtEntry
->Notify
.ForwardLink
;
154 Link
!= &ProtEntry
->Notify
;
155 Link
= Link
->ForwardLink
)
157 ProtNotify
= CR (Link
, PROTOCOL_NOTIFY
, Link
, PROTOCOL_NOTIFY_SIGNATURE
);
158 if (CompareGuid (&ProtNotify
->Protocol
->ProtocolID
, Protocol
) &&
159 (ProtNotify
->Function
== Function
))
162 // Notification already exist
164 *Registration
= ProtNotify
;
171 // Allocate a new notification record
173 ProtNotify
= AllocatePool (sizeof (PROTOCOL_NOTIFY
));
174 if (ProtNotify
!= NULL
) {
175 ProtNotify
->Signature
= PROTOCOL_NOTIFY_SIGNATURE
;
176 ProtNotify
->Protocol
= ProtEntry
;
177 ProtNotify
->Function
= Function
;
179 // Start at the ending
181 ProtNotify
->Position
= ProtEntry
->Protocols
.BackLink
;
183 InsertTailList (&ProtEntry
->Notify
, &ProtNotify
->Link
);
188 // Done. If we have a protocol notify entry, then return it.
189 // Otherwise, we must have run out of resources trying to add one
191 Status
= EFI_OUT_OF_RESOURCES
;
192 if (ProtNotify
!= NULL
) {
193 *Registration
= ProtNotify
;
194 Status
= EFI_SUCCESS
;