]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Core/Dxe/Hand/Notify.c
553413a3509cf231363baa889aeac90043510abb
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / Hand / Notify.c
1 /** @file
2 Support functions for UEFI protocol notification infrastructure.
3
4 Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR>
5 (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 **/
9
10 #include "DxeMain.h"
11 #include "Handle.h"
12 #include "Event.h"
13
14 /**
15 Signal event for every protocol in protocol entry.
16
17 @param ProtEntry Protocol entry
18
19 **/
20 VOID
21 CoreNotifyProtocolEntry (
22 IN PROTOCOL_ENTRY *ProtEntry
23 )
24 {
25 PROTOCOL_NOTIFY *ProtNotify;
26 LIST_ENTRY *Link;
27
28 ASSERT_LOCKED (&gProtocolDatabaseLock);
29
30 for (Link=ProtEntry->Notify.ForwardLink; Link != &ProtEntry->Notify; Link=Link->ForwardLink) {
31 ProtNotify = CR(Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE);
32 CoreSignalEvent (ProtNotify->Event);
33 }
34 }
35
36
37
38 /**
39 Removes Protocol from the protocol list (but not the handle list).
40
41 @param Handle The handle to remove protocol on.
42 @param Protocol GUID of the protocol to be moved
43 @param Interface The interface of the protocol
44
45 @return Protocol Entry
46
47 **/
48 PROTOCOL_INTERFACE *
49 CoreRemoveInterfaceFromProtocol (
50 IN IHANDLE *Handle,
51 IN EFI_GUID *Protocol,
52 IN VOID *Interface
53 )
54 {
55 PROTOCOL_INTERFACE *Prot;
56 PROTOCOL_NOTIFY *ProtNotify;
57 PROTOCOL_ENTRY *ProtEntry;
58 LIST_ENTRY *Link;
59
60 ASSERT_LOCKED (&gProtocolDatabaseLock);
61
62 Prot = CoreFindProtocolInterface (Handle, Protocol, Interface);
63 if (Prot != NULL) {
64
65 ProtEntry = Prot->Protocol;
66
67 //
68 // If there's a protocol notify location pointing to this entry, back it up one
69 //
70 for(Link = ProtEntry->Notify.ForwardLink; Link != &ProtEntry->Notify; Link=Link->ForwardLink) {
71 ProtNotify = CR(Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE);
72
73 if (ProtNotify->Position == &Prot->ByProtocol) {
74 ProtNotify->Position = Prot->ByProtocol.BackLink;
75 }
76 }
77
78 //
79 // Remove the protocol interface entry
80 //
81 RemoveEntryList (&Prot->ByProtocol);
82 }
83
84 return Prot;
85 }
86
87
88 /**
89 Add a new protocol notification record for the request protocol.
90
91 @param Protocol The requested protocol to add the notify
92 registration
93 @param Event The event to signal
94 @param Registration Returns the registration record
95
96 @retval EFI_INVALID_PARAMETER Invalid parameter
97 @retval EFI_SUCCESS Successfully returned the registration record
98 that has been added
99
100 **/
101 EFI_STATUS
102 EFIAPI
103 CoreRegisterProtocolNotify (
104 IN EFI_GUID *Protocol,
105 IN EFI_EVENT Event,
106 OUT VOID **Registration
107 )
108 {
109 PROTOCOL_ENTRY *ProtEntry;
110 PROTOCOL_NOTIFY *ProtNotify;
111 EFI_STATUS Status;
112
113 if ((Protocol == NULL) || (Event == NULL) || (Registration == NULL)) {
114 return EFI_INVALID_PARAMETER;
115 }
116
117 CoreAcquireProtocolLock ();
118
119 ProtNotify = NULL;
120
121 //
122 // Get the protocol entry to add the notification too
123 //
124
125 ProtEntry = CoreFindProtocolEntry (Protocol, TRUE);
126 if (ProtEntry != NULL) {
127
128 //
129 // Allocate a new notification record
130 //
131 ProtNotify = AllocatePool (sizeof(PROTOCOL_NOTIFY));
132 if (ProtNotify != NULL) {
133 ((IEVENT *)Event)->ExFlag |= EVT_EXFLAG_EVENT_PROTOCOL_NOTIFICATION;
134 ProtNotify->Signature = PROTOCOL_NOTIFY_SIGNATURE;
135 ProtNotify->Protocol = ProtEntry;
136 ProtNotify->Event = Event;
137 //
138 // start at the begining
139 //
140 ProtNotify->Position = &ProtEntry->Protocols;
141
142 InsertTailList (&ProtEntry->Notify, &ProtNotify->Link);
143 }
144 }
145
146 CoreReleaseProtocolLock ();
147
148 //
149 // Done. If we have a protocol notify entry, then return it.
150 // Otherwise, we must have run out of resources trying to add one
151 //
152
153 Status = EFI_OUT_OF_RESOURCES;
154 if (ProtNotify != NULL) {
155 *Registration = ProtNotify;
156 Status = EFI_SUCCESS;
157 }
158
159 return Status;
160 }
161
162
163 /**
164 Reinstall a protocol interface on a device handle. The OldInterface for Protocol is replaced by the NewInterface.
165
166 @param UserHandle Handle on which the interface is to be
167 reinstalled
168 @param Protocol The numeric ID of the interface
169 @param OldInterface A pointer to the old interface
170 @param NewInterface A pointer to the new interface
171
172 @retval EFI_SUCCESS The protocol interface was installed
173 @retval EFI_NOT_FOUND The OldInterface on the handle was not found
174 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value
175
176 **/
177 EFI_STATUS
178 EFIAPI
179 CoreReinstallProtocolInterface (
180 IN EFI_HANDLE UserHandle,
181 IN EFI_GUID *Protocol,
182 IN VOID *OldInterface,
183 IN VOID *NewInterface
184 )
185 {
186 EFI_STATUS Status;
187 IHANDLE *Handle;
188 PROTOCOL_INTERFACE *Prot;
189 PROTOCOL_ENTRY *ProtEntry;
190
191 Status = CoreValidateHandle (UserHandle);
192 if (EFI_ERROR (Status)) {
193 return Status;
194 }
195
196 if (Protocol == NULL) {
197 return EFI_INVALID_PARAMETER;
198 }
199
200 Handle = (IHANDLE *) UserHandle;
201
202 //
203 // Lock the protocol database
204 //
205 CoreAcquireProtocolLock ();
206
207 //
208 // Check that Protocol exists on UserHandle, and Interface matches the interface in the database
209 //
210 Prot = CoreFindProtocolInterface (UserHandle, Protocol, OldInterface);
211 if (Prot == NULL) {
212 Status = EFI_NOT_FOUND;
213 goto Done;
214 }
215
216 //
217 // Attempt to disconnect all drivers that are using the protocol interface that is about to be reinstalled
218 //
219 Status = CoreDisconnectControllersUsingProtocolInterface (
220 UserHandle,
221 Prot
222 );
223 if (EFI_ERROR (Status)) {
224 //
225 // One or more drivers refused to release, so return the error
226 //
227 goto Done;
228 }
229
230 //
231 // Remove the protocol interface from the protocol
232 //
233 Prot = CoreRemoveInterfaceFromProtocol (Handle, Protocol, OldInterface);
234
235 if (Prot == NULL) {
236 Status = EFI_NOT_FOUND;
237 goto Done;
238 }
239
240 ProtEntry = Prot->Protocol;
241
242 //
243 // Update the interface on the protocol
244 //
245 Prot->Interface = NewInterface;
246
247 //
248 // Add this protocol interface to the tail of the
249 // protocol entry
250 //
251 InsertTailList (&ProtEntry->Protocols, &Prot->ByProtocol);
252
253 //
254 // Update the Key to show that the handle has been created/modified
255 //
256 gHandleDatabaseKey++;
257 Handle->Key = gHandleDatabaseKey;
258
259 //
260 // Release the lock and connect all drivers to UserHandle
261 //
262 CoreReleaseProtocolLock ();
263 //
264 // Return code is ignored on purpose.
265 //
266 CoreConnectController (
267 UserHandle,
268 NULL,
269 NULL,
270 TRUE
271 );
272 CoreAcquireProtocolLock ();
273
274 //
275 // Notify the notification list for this protocol
276 //
277 CoreNotifyProtocolEntry (ProtEntry);
278
279 Status = EFI_SUCCESS;
280
281 Done:
282 CoreReleaseProtocolLock ();
283
284 return Status;
285 }