]> git.proxmox.com Git - mirror_edk2.git/blob - StandaloneMmPkg/Core/Notify.c
NetworkPkg: Move Network library header file from MdeModulePkg to NetworkPkg
[mirror_edk2.git] / StandaloneMmPkg / Core / Notify.c
1 /** @file
2 Support functions for UEFI protocol notification infrastructure.
3
4 Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>
5 Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 **/
9
10 #include "StandaloneMmCore.h"
11
12 /**
13 Signal event for every protocol in protocol entry.
14
15 @param Prot Protocol interface
16
17 **/
18 VOID
19 MmNotifyProtocol (
20 IN PROTOCOL_INTERFACE *Prot
21 )
22 {
23 PROTOCOL_ENTRY *ProtEntry;
24 PROTOCOL_NOTIFY *ProtNotify;
25 LIST_ENTRY *Link;
26
27 ProtEntry = Prot->Protocol;
28 for (Link=ProtEntry->Notify.ForwardLink; Link != &ProtEntry->Notify; Link=Link->ForwardLink) {
29 ProtNotify = CR (Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE);
30 ProtNotify->Function (&ProtEntry->ProtocolID, Prot->Interface, Prot->Handle);
31 }
32 }
33
34 /**
35 Removes Protocol from the protocol list (but not the handle list).
36
37 @param Handle The handle to remove protocol on.
38 @param Protocol GUID of the protocol to be moved
39 @param Interface The interface of the protocol
40
41 @return Protocol Entry
42
43 **/
44 PROTOCOL_INTERFACE *
45 MmRemoveInterfaceFromProtocol (
46 IN IHANDLE *Handle,
47 IN EFI_GUID *Protocol,
48 IN VOID *Interface
49 )
50 {
51 PROTOCOL_INTERFACE *Prot;
52 PROTOCOL_NOTIFY *ProtNotify;
53 PROTOCOL_ENTRY *ProtEntry;
54 LIST_ENTRY *Link;
55
56 Prot = MmFindProtocolInterface (Handle, Protocol, Interface);
57 if (Prot != NULL) {
58
59 ProtEntry = Prot->Protocol;
60
61 //
62 // If there's a protocol notify location pointing to this entry, back it up one
63 //
64 for (Link = ProtEntry->Notify.ForwardLink; Link != &ProtEntry->Notify; Link = Link->ForwardLink) {
65 ProtNotify = CR (Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE);
66
67 if (ProtNotify->Position == &Prot->ByProtocol) {
68 ProtNotify->Position = Prot->ByProtocol.BackLink;
69 }
70 }
71
72 //
73 // Remove the protocol interface entry
74 //
75 RemoveEntryList (&Prot->ByProtocol);
76 }
77
78 return Prot;
79 }
80
81 /**
82 Add a new protocol notification record for the request protocol.
83
84 @param Protocol The requested protocol to add the notify
85 registration
86 @param Function Points to the notification function
87 @param Registration Returns the registration record
88
89 @retval EFI_SUCCESS Successfully returned the registration record
90 that has been added or unhooked
91 @retval EFI_INVALID_PARAMETER Protocol is NULL or Registration is NULL
92 @retval EFI_OUT_OF_RESOURCES Not enough memory resource to finish the request
93 @retval EFI_NOT_FOUND If the registration is not found when Function == NULL
94
95 **/
96 EFI_STATUS
97 EFIAPI
98 MmRegisterProtocolNotify (
99 IN CONST EFI_GUID *Protocol,
100 IN EFI_MM_NOTIFY_FN Function,
101 OUT VOID **Registration
102 )
103 {
104 PROTOCOL_ENTRY *ProtEntry;
105 PROTOCOL_NOTIFY *ProtNotify;
106 LIST_ENTRY *Link;
107 EFI_STATUS Status;
108
109 if (Protocol == NULL || Registration == NULL) {
110 return EFI_INVALID_PARAMETER;
111 }
112
113 if (Function == NULL) {
114 //
115 // Get the protocol entry per Protocol
116 //
117 ProtEntry = MmFindProtocolEntry ((EFI_GUID *) Protocol, FALSE);
118 if (ProtEntry != NULL) {
119 ProtNotify = (PROTOCOL_NOTIFY * )*Registration;
120 for (Link = ProtEntry->Notify.ForwardLink;
121 Link != &ProtEntry->Notify;
122 Link = Link->ForwardLink) {
123 //
124 // Compare the notification record
125 //
126 if (ProtNotify == (CR (Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE))) {
127 //
128 // If Registration is an existing registration, then unhook it
129 //
130 ProtNotify->Signature = 0;
131 RemoveEntryList (&ProtNotify->Link);
132 FreePool (ProtNotify);
133 return EFI_SUCCESS;
134 }
135 }
136 }
137 //
138 // If the registration is not found
139 //
140 return EFI_NOT_FOUND;
141 }
142
143 ProtNotify = NULL;
144
145 //
146 // Get the protocol entry to add the notification too
147 //
148 ProtEntry = MmFindProtocolEntry ((EFI_GUID *) Protocol, TRUE);
149 if (ProtEntry != NULL) {
150 //
151 // Find whether notification already exist
152 //
153 for (Link = ProtEntry->Notify.ForwardLink;
154 Link != &ProtEntry->Notify;
155 Link = Link->ForwardLink) {
156
157 ProtNotify = CR (Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE);
158 if (CompareGuid (&ProtNotify->Protocol->ProtocolID, Protocol) &&
159 (ProtNotify->Function == Function)) {
160
161 //
162 // Notification already exist
163 //
164 *Registration = ProtNotify;
165
166 return EFI_SUCCESS;
167 }
168 }
169
170 //
171 // Allocate a new notification record
172 //
173 ProtNotify = AllocatePool (sizeof (PROTOCOL_NOTIFY));
174 if (ProtNotify != NULL) {
175 ProtNotify->Signature = PROTOCOL_NOTIFY_SIGNATURE;
176 ProtNotify->Protocol = ProtEntry;
177 ProtNotify->Function = Function;
178 //
179 // Start at the ending
180 //
181 ProtNotify->Position = ProtEntry->Protocols.BackLink;
182
183 InsertTailList (&ProtEntry->Notify, &ProtNotify->Link);
184 }
185 }
186
187 //
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
190 //
191 Status = EFI_OUT_OF_RESOURCES;
192 if (ProtNotify != NULL) {
193 *Registration = ProtNotify;
194 Status = EFI_SUCCESS;
195 }
196 return Status;
197 }