2 Support functions for UEFI protocol notification infrastructure.
4 Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials are licensed and made available
6 under the terms and conditions of the BSD License which accompanies this
7 distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "PiSmmCore.h"
18 Signal event for every protocol in protocol entry.
20 @param Prot Protocol interface
25 IN PROTOCOL_INTERFACE
*Prot
28 PROTOCOL_ENTRY
*ProtEntry
;
29 PROTOCOL_NOTIFY
*ProtNotify
;
32 ProtEntry
= Prot
->Protocol
;
33 for (Link
=ProtEntry
->Notify
.ForwardLink
; Link
!= &ProtEntry
->Notify
; Link
=Link
->ForwardLink
) {
34 ProtNotify
= CR(Link
, PROTOCOL_NOTIFY
, Link
, PROTOCOL_NOTIFY_SIGNATURE
);
35 ProtNotify
->Function (&ProtEntry
->ProtocolID
, Prot
->Interface
, Prot
->Handle
);
40 Removes Protocol from the protocol list (but not the handle list).
42 @param Handle The handle to remove protocol on.
43 @param Protocol GUID of the protocol to be moved
44 @param Interface The interface of the protocol
46 @return Protocol Entry
50 SmmRemoveInterfaceFromProtocol (
52 IN EFI_GUID
*Protocol
,
56 PROTOCOL_INTERFACE
*Prot
;
57 PROTOCOL_NOTIFY
*ProtNotify
;
58 PROTOCOL_ENTRY
*ProtEntry
;
61 Prot
= SmmFindProtocolInterface (Handle
, Protocol
, Interface
);
64 ProtEntry
= Prot
->Protocol
;
67 // If there's a protocol notify location pointing to this entry, back it up one
69 for(Link
= ProtEntry
->Notify
.ForwardLink
; Link
!= &ProtEntry
->Notify
; Link
=Link
->ForwardLink
) {
70 ProtNotify
= CR(Link
, PROTOCOL_NOTIFY
, Link
, PROTOCOL_NOTIFY_SIGNATURE
);
72 if (ProtNotify
->Position
== &Prot
->ByProtocol
) {
73 ProtNotify
->Position
= Prot
->ByProtocol
.BackLink
;
78 // Remove the protocol interface entry
80 RemoveEntryList (&Prot
->ByProtocol
);
87 Add a new protocol notification record for the request protocol.
89 @param Protocol The requested protocol to add the notify
91 @param Function Points to the notification function
92 @param Registration Returns the registration record
94 @retval EFI_SUCCESS Successfully returned the registration record
95 that has been added or unhooked
96 @retval EFI_INVALID_PARAMETER Protocol is NULL or Registration is NULL
97 @retval EFI_OUT_OF_RESOURCES Not enough memory resource to finish the request
98 @retval EFI_NOT_FOUND If the registration is not found when Function == NULL
103 SmmRegisterProtocolNotify (
104 IN CONST EFI_GUID
*Protocol
,
105 IN EFI_SMM_NOTIFY_FN Function
,
106 OUT VOID
**Registration
109 PROTOCOL_ENTRY
*ProtEntry
;
110 PROTOCOL_NOTIFY
*ProtNotify
;
114 if (Protocol
== NULL
|| Registration
== NULL
) {
115 return EFI_INVALID_PARAMETER
;
118 if (Function
== NULL
) {
120 // Get the protocol entry per Protocol
122 ProtEntry
= SmmFindProtocolEntry ((EFI_GUID
*) Protocol
, FALSE
);
123 if (ProtEntry
!= NULL
) {
124 ProtNotify
= (PROTOCOL_NOTIFY
* )*Registration
;
125 for (Link
= ProtEntry
->Notify
.ForwardLink
;
126 Link
!= &ProtEntry
->Notify
;
127 Link
= Link
->ForwardLink
) {
129 // Compare the notification record
131 if (ProtNotify
== (CR(Link
, PROTOCOL_NOTIFY
, Link
, PROTOCOL_NOTIFY_SIGNATURE
))){
133 // If Registration is an existing registration, then unhook it
135 ProtNotify
->Signature
= 0;
136 RemoveEntryList (&ProtNotify
->Link
);
137 FreePool (ProtNotify
);
143 // If the registration is not found
145 return EFI_NOT_FOUND
;
151 // Get the protocol entry to add the notification too
153 ProtEntry
= SmmFindProtocolEntry ((EFI_GUID
*) Protocol
, TRUE
);
154 if (ProtEntry
!= NULL
) {
156 // Find whether notification already exist
158 for (Link
= ProtEntry
->Notify
.ForwardLink
;
159 Link
!= &ProtEntry
->Notify
;
160 Link
= Link
->ForwardLink
) {
162 ProtNotify
= CR(Link
, PROTOCOL_NOTIFY
, Link
, PROTOCOL_NOTIFY_SIGNATURE
);
163 if (CompareGuid (&ProtNotify
->Protocol
->ProtocolID
, Protocol
) &&
164 (ProtNotify
->Function
== Function
)) {
167 // Notification already exist
169 *Registration
= ProtNotify
;
176 // Allocate a new notification record
178 ProtNotify
= AllocatePool (sizeof(PROTOCOL_NOTIFY
));
179 if (ProtNotify
!= NULL
) {
180 ProtNotify
->Signature
= PROTOCOL_NOTIFY_SIGNATURE
;
181 ProtNotify
->Protocol
= ProtEntry
;
182 ProtNotify
->Function
= Function
;
184 // Start at the ending
186 ProtNotify
->Position
= ProtEntry
->Protocols
.BackLink
;
188 InsertTailList (&ProtEntry
->Notify
, &ProtNotify
->Link
);
193 // Done. If we have a protocol notify entry, then return it.
194 // Otherwise, we must have run out of resources trying to add one
196 Status
= EFI_OUT_OF_RESOURCES
;
197 if (ProtNotify
!= NULL
) {
198 *Registration
= ProtNotify
;
199 Status
= EFI_SUCCESS
;