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
);
58 ProtEntry
= Prot
->Protocol
;
61 // If there's a protocol notify location pointing to this entry, back it up one
63 for(Link
= ProtEntry
->Notify
.ForwardLink
; Link
!= &ProtEntry
->Notify
; Link
=Link
->ForwardLink
) {
64 ProtNotify
= CR(Link
, PROTOCOL_NOTIFY
, Link
, PROTOCOL_NOTIFY_SIGNATURE
);
66 if (ProtNotify
->Position
== &Prot
->ByProtocol
) {
67 ProtNotify
->Position
= Prot
->ByProtocol
.BackLink
;
72 // Remove the protocol interface entry
74 RemoveEntryList (&Prot
->ByProtocol
);
81 Add a new protocol notification record for the request protocol.
83 @param Protocol The requested protocol to add the notify
85 @param Function Points to the notification function
86 @param Registration Returns the registration record
88 @retval EFI_SUCCESS Successfully returned the registration record
89 that has been added or unhooked
90 @retval EFI_INVALID_PARAMETER Protocol is NULL or Registration is NULL
91 @retval EFI_OUT_OF_RESOURCES Not enough memory resource to finish the request
92 @retval EFI_NOT_FOUND If the registration is not found when Function == NULL
97 SmmRegisterProtocolNotify (
98 IN CONST EFI_GUID
*Protocol
,
99 IN EFI_SMM_NOTIFY_FN Function
,
100 OUT VOID
**Registration
103 PROTOCOL_ENTRY
*ProtEntry
;
104 PROTOCOL_NOTIFY
*ProtNotify
;
108 if (Protocol
== NULL
|| Registration
== NULL
) {
109 return EFI_INVALID_PARAMETER
;
112 if (Function
== NULL
) {
114 // Get the protocol entry per Protocol
116 ProtEntry
= SmmFindProtocolEntry ((EFI_GUID
*) Protocol
, FALSE
);
117 if (ProtEntry
!= NULL
) {
118 ProtNotify
= (PROTOCOL_NOTIFY
* )*Registration
;
119 for (Link
= ProtEntry
->Notify
.ForwardLink
;
120 Link
!= &ProtEntry
->Notify
;
121 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
);
137 // If the registration is not found
139 return EFI_NOT_FOUND
;
145 // Get the protocol entry to add the notification too
147 ProtEntry
= SmmFindProtocolEntry ((EFI_GUID
*) Protocol
, TRUE
);
148 if (ProtEntry
!= NULL
) {
150 // Find whether notification already exist
152 for (Link
= ProtEntry
->Notify
.ForwardLink
;
153 Link
!= &ProtEntry
->Notify
;
154 Link
= Link
->ForwardLink
) {
156 ProtNotify
= CR(Link
, PROTOCOL_NOTIFY
, Link
, PROTOCOL_NOTIFY_SIGNATURE
);
157 if (CompareGuid (&ProtNotify
->Protocol
->ProtocolID
, Protocol
) &&
158 (ProtNotify
->Function
== Function
)) {
161 // Notification already exist
163 *Registration
= ProtNotify
;
170 // Allocate a new notification record
172 ProtNotify
= AllocatePool (sizeof(PROTOCOL_NOTIFY
));
173 if (ProtNotify
!= NULL
) {
174 ProtNotify
->Signature
= PROTOCOL_NOTIFY_SIGNATURE
;
175 ProtNotify
->Protocol
= ProtEntry
;
176 ProtNotify
->Function
= Function
;
178 // Start at the ending
180 ProtNotify
->Position
= ProtEntry
->Protocols
.BackLink
;
182 InsertTailList (&ProtEntry
->Notify
, &ProtNotify
->Link
);
187 // Done. If we have a protocol notify entry, then return it.
188 // Otherwise, we must have run out of resources trying to add one
190 Status
= EFI_OUT_OF_RESOURCES
;
191 if (ProtNotify
!= NULL
) {
192 *Registration
= ProtNotify
;
193 Status
= EFI_SUCCESS
;