2 Support functions for UEFI protocol notification infrastructure.
4 Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>
5 Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.<BR>
6 This program and the accompanying materials are licensed and made available
7 under the terms and conditions of the BSD License which accompanies this
8 distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include "StandaloneMmCore.h"
19 Signal event for every protocol in protocol entry.
21 @param Prot Protocol interface
26 IN PROTOCOL_INTERFACE
*Prot
29 PROTOCOL_ENTRY
*ProtEntry
;
30 PROTOCOL_NOTIFY
*ProtNotify
;
33 ProtEntry
= Prot
->Protocol
;
34 for (Link
=ProtEntry
->Notify
.ForwardLink
; Link
!= &ProtEntry
->Notify
; Link
=Link
->ForwardLink
) {
35 ProtNotify
= CR (Link
, PROTOCOL_NOTIFY
, Link
, PROTOCOL_NOTIFY_SIGNATURE
);
36 ProtNotify
->Function (&ProtEntry
->ProtocolID
, Prot
->Interface
, Prot
->Handle
);
41 Removes Protocol from the protocol list (but not the handle list).
43 @param Handle The handle to remove protocol on.
44 @param Protocol GUID of the protocol to be moved
45 @param Interface The interface of the protocol
47 @return Protocol Entry
51 MmRemoveInterfaceFromProtocol (
53 IN EFI_GUID
*Protocol
,
57 PROTOCOL_INTERFACE
*Prot
;
58 PROTOCOL_NOTIFY
*ProtNotify
;
59 PROTOCOL_ENTRY
*ProtEntry
;
62 Prot
= MmFindProtocolInterface (Handle
, Protocol
, Interface
);
65 ProtEntry
= Prot
->Protocol
;
68 // If there's a protocol notify location pointing to this entry, back it up one
70 for (Link
= ProtEntry
->Notify
.ForwardLink
; Link
!= &ProtEntry
->Notify
; Link
= Link
->ForwardLink
) {
71 ProtNotify
= CR (Link
, PROTOCOL_NOTIFY
, Link
, PROTOCOL_NOTIFY_SIGNATURE
);
73 if (ProtNotify
->Position
== &Prot
->ByProtocol
) {
74 ProtNotify
->Position
= Prot
->ByProtocol
.BackLink
;
79 // Remove the protocol interface entry
81 RemoveEntryList (&Prot
->ByProtocol
);
88 Add a new protocol notification record for the request protocol.
90 @param Protocol The requested protocol to add the notify
92 @param Function Points to the notification function
93 @param Registration Returns the registration record
95 @retval EFI_SUCCESS Successfully returned the registration record
96 that has been added or unhooked
97 @retval EFI_INVALID_PARAMETER Protocol is NULL or Registration is NULL
98 @retval EFI_OUT_OF_RESOURCES Not enough memory resource to finish the request
99 @retval EFI_NOT_FOUND If the registration is not found when Function == NULL
104 MmRegisterProtocolNotify (
105 IN CONST EFI_GUID
*Protocol
,
106 IN EFI_MM_NOTIFY_FN Function
,
107 OUT VOID
**Registration
110 PROTOCOL_ENTRY
*ProtEntry
;
111 PROTOCOL_NOTIFY
*ProtNotify
;
115 if (Protocol
== NULL
|| Registration
== NULL
) {
116 return EFI_INVALID_PARAMETER
;
119 if (Function
== NULL
) {
121 // Get the protocol entry per Protocol
123 ProtEntry
= MmFindProtocolEntry ((EFI_GUID
*) Protocol
, FALSE
);
124 if (ProtEntry
!= NULL
) {
125 ProtNotify
= (PROTOCOL_NOTIFY
* )*Registration
;
126 for (Link
= ProtEntry
->Notify
.ForwardLink
;
127 Link
!= &ProtEntry
->Notify
;
128 Link
= Link
->ForwardLink
) {
130 // Compare the notification record
132 if (ProtNotify
== (CR (Link
, PROTOCOL_NOTIFY
, Link
, PROTOCOL_NOTIFY_SIGNATURE
))) {
134 // If Registration is an existing registration, then unhook it
136 ProtNotify
->Signature
= 0;
137 RemoveEntryList (&ProtNotify
->Link
);
138 FreePool (ProtNotify
);
144 // If the registration is not found
146 return EFI_NOT_FOUND
;
152 // Get the protocol entry to add the notification too
154 ProtEntry
= MmFindProtocolEntry ((EFI_GUID
*) Protocol
, TRUE
);
155 if (ProtEntry
!= NULL
) {
157 // Find whether notification already exist
159 for (Link
= ProtEntry
->Notify
.ForwardLink
;
160 Link
!= &ProtEntry
->Notify
;
161 Link
= Link
->ForwardLink
) {
163 ProtNotify
= CR (Link
, PROTOCOL_NOTIFY
, Link
, PROTOCOL_NOTIFY_SIGNATURE
);
164 if (CompareGuid (&ProtNotify
->Protocol
->ProtocolID
, Protocol
) &&
165 (ProtNotify
->Function
== Function
)) {
168 // Notification already exist
170 *Registration
= ProtNotify
;
177 // Allocate a new notification record
179 ProtNotify
= AllocatePool (sizeof (PROTOCOL_NOTIFY
));
180 if (ProtNotify
!= NULL
) {
181 ProtNotify
->Signature
= PROTOCOL_NOTIFY_SIGNATURE
;
182 ProtNotify
->Protocol
= ProtEntry
;
183 ProtNotify
->Function
= Function
;
185 // Start at the ending
187 ProtNotify
->Position
= ProtEntry
->Protocols
.BackLink
;
189 InsertTailList (&ProtEntry
->Notify
, &ProtNotify
->Link
);
194 // Done. If we have a protocol notify entry, then return it.
195 // Otherwise, we must have run out of resources trying to add one
197 Status
= EFI_OUT_OF_RESOURCES
;
198 if (ProtNotify
!= NULL
) {
199 *Registration
= ProtNotify
;
200 Status
= EFI_SUCCESS
;