]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Core/Dxe/Hand/Notify.c
Check in DxeCore for Nt32 platform. Currently, it does not follow PI/UEFI2.1.
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / Hand / Notify.c
1 /*++
2
3 Copyright (c) 2006, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12 Module Name:
13
14 notify.c
15
16 Abstract:
17
18 EFI notify infrastructure
19
20
21
22 Revision History
23
24 --*/
25
26 #include <DxeMain.h>
27
28 VOID
29 CoreNotifyProtocolEntry (
30 IN PROTOCOL_ENTRY *ProtEntry
31 )
32 /*++
33
34 Routine Description:
35
36 Signal event for every protocol in protocol entry.
37
38 Arguments:
39
40 ProtEntry - Protocol entry
41
42 Returns:
43
44 --*/
45 {
46 PROTOCOL_NOTIFY *ProtNotify;
47 LIST_ENTRY *Link;
48
49 ASSERT_LOCKED (&gProtocolDatabaseLock);
50
51 for (Link=ProtEntry->Notify.ForwardLink; Link != &ProtEntry->Notify; Link=Link->ForwardLink) {
52 ProtNotify = CR(Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE);
53 CoreSignalEvent (ProtNotify->Event);
54 }
55 }
56
57
58 PROTOCOL_INTERFACE *
59 CoreRemoveInterfaceFromProtocol (
60 IN IHANDLE *Handle,
61 IN EFI_GUID *Protocol,
62 IN VOID *Interface
63 )
64 /*++
65
66 Routine Description:
67
68 Removes Protocol from the protocol list (but not the handle list).
69
70 Arguments:
71
72 Handle - The handle to remove protocol on.
73
74 Protocol - GUID of the protocol to be moved
75
76 Interface - The interface of the protocol
77
78 Returns:
79
80 Protocol Entry
81
82 --*/
83 {
84 PROTOCOL_INTERFACE *Prot;
85 PROTOCOL_NOTIFY *ProtNotify;
86 PROTOCOL_ENTRY *ProtEntry;
87 LIST_ENTRY *Link;
88
89 ASSERT_LOCKED (&gProtocolDatabaseLock);
90
91 Prot = CoreFindProtocolInterface (Handle, Protocol, Interface);
92 if (Prot != NULL) {
93
94 ProtEntry = Prot->Protocol;
95
96 //
97 // If there's a protocol notify location pointing to this entry, back it up one
98 //
99
100 for(Link = ProtEntry->Notify.ForwardLink; Link != &ProtEntry->Notify; Link=Link->ForwardLink) {
101 ProtNotify = CR(Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE);
102
103 if (ProtNotify->Position == &Prot->ByProtocol) {
104 ProtNotify->Position = Prot->ByProtocol.BackLink;
105 }
106 }
107
108 //
109 // Remove the protocol interface entry
110 //
111
112 RemoveEntryList (&Prot->ByProtocol);
113 }
114
115 return Prot;
116 }
117
118
119
120 EFI_STATUS
121 EFIAPI
122 CoreRegisterProtocolNotify (
123 IN EFI_GUID *Protocol,
124 IN EFI_EVENT Event,
125 OUT VOID **Registration
126 )
127 /*++
128
129 Routine Description:
130
131 Add a new protocol notification record for the request protocol.
132
133 Arguments:
134
135 Protocol - The requested protocol to add the notify registration
136
137 Event - The event to signal
138
139 Registration - Returns the registration record
140
141
142 Returns:
143
144 EFI_INVALID_PARAMETER - Invalid parameter
145
146 EFI_SUCCESS - Successfully returned the registration record that has been added
147
148 --*/
149 {
150 PROTOCOL_ENTRY *ProtEntry;
151 PROTOCOL_NOTIFY *ProtNotify;
152 EFI_STATUS Status;
153
154 if ((Protocol == NULL) || (Event == NULL) || (Registration == NULL)) {
155 return EFI_INVALID_PARAMETER;
156 }
157
158 CoreAcquireProtocolLock ();
159
160 ProtNotify = NULL;
161
162 //
163 // Get the protocol entry to add the notification too
164 //
165
166 ProtEntry = CoreFindProtocolEntry (Protocol, TRUE);
167 if (ProtEntry != NULL) {
168
169 //
170 // Allocate a new notification record
171 //
172
173 ProtNotify = CoreAllocateBootServicesPool (sizeof(PROTOCOL_NOTIFY));
174
175 if (ProtNotify != NULL) {
176
177 ProtNotify->Signature = PROTOCOL_NOTIFY_SIGNATURE;
178 ProtNotify->Protocol = ProtEntry;
179 ProtNotify->Event = Event;
180 //
181 // start at the begining
182 //
183 ProtNotify->Position = &ProtEntry->Protocols;
184
185 InsertTailList (&ProtEntry->Notify, &ProtNotify->Link);
186 }
187 }
188
189 CoreReleaseProtocolLock ();
190
191 //
192 // Done. If we have a protocol notify entry, then return it.
193 // Otherwise, we must have run out of resources trying to add one
194 //
195
196 Status = EFI_OUT_OF_RESOURCES;
197 if (ProtNotify != NULL) {
198 *Registration = ProtNotify;
199 Status = EFI_SUCCESS;
200 }
201
202 return Status;
203 }
204
205
206
207 EFI_STATUS
208 EFIAPI
209 CoreReinstallProtocolInterface (
210 IN EFI_HANDLE UserHandle,
211 IN EFI_GUID *Protocol,
212 IN VOID *OldInterface,
213 IN VOID *NewInterface
214 )
215 /*++
216
217 Routine Description:
218
219 Reinstall a protocol interface on a device handle. The OldInterface for Protocol is replaced by the NewInterface.
220
221 Arguments:
222
223 UserHandle - Handle on which the interface is to be reinstalled
224 Protocol - The numeric ID of the interface
225 OldInterface - A pointer to the old interface
226 NewInterface - A pointer to the new interface
227
228
229 Returns:
230
231 Status code.
232
233 On EFI_SUCCESS The protocol interface was installed
234 On EFI_NOT_FOUND The OldInterface on the handle was not found
235 On EFI_INVALID_PARAMETER One of the parameters has an invalid value
236
237 --*/
238 {
239 EFI_STATUS Status;
240 IHANDLE *Handle;
241 PROTOCOL_INTERFACE *Prot;
242 PROTOCOL_ENTRY *ProtEntry;
243
244 Status = CoreValidateHandle (UserHandle);
245 if (EFI_ERROR (Status)) {
246 return Status;
247 }
248
249 if (Protocol == NULL) {
250 return EFI_INVALID_PARAMETER;
251 }
252
253 Handle = (IHANDLE *) UserHandle;
254
255 //
256 // Lock the protocol database
257 //
258 CoreAcquireProtocolLock ();
259
260 //
261 // Check that Protocol exists on UserHandle, and Interface matches the interface in the database
262 //
263 Prot = CoreFindProtocolInterface (UserHandle, Protocol, OldInterface);
264 if (Prot == NULL) {
265 CoreReleaseProtocolLock ();
266 return EFI_NOT_FOUND;
267 }
268
269 //
270 // Attempt to disconnect all drivers that are using the protocol interface that is about to be reinstalled
271 //
272 Status = CoreDisconnectControllersUsingProtocolInterface (
273 UserHandle,
274 Prot
275 );
276 if (EFI_ERROR (Status)) {
277 //
278 // One or more drivers refused to release, so return the error
279 //
280 CoreReleaseProtocolLock ();
281 return Status;
282 }
283
284 //
285 // Remove the protocol interface from the protocol
286 //
287 Prot = CoreRemoveInterfaceFromProtocol (Handle, Protocol, OldInterface);
288
289 if (Prot == NULL) {
290 CoreReleaseProtocolLock ();
291 return EFI_NOT_FOUND;
292 }
293
294 ProtEntry = Prot->Protocol;
295
296 //
297 // Update the interface on the protocol
298 //
299 Prot->Interface = NewInterface;
300
301 //
302 // Add this protocol interface to the tail of the
303 // protocol entry
304 //
305 InsertTailList (&ProtEntry->Protocols, &Prot->ByProtocol);
306
307 //
308 // Update the Key to show that the handle has been created/modified
309 //
310 gHandleDatabaseKey++;
311 Handle->Key = gHandleDatabaseKey;
312
313 //
314 // Release the lock and connect all drivers to UserHandle
315 //
316 CoreReleaseProtocolLock ();
317 Status = CoreConnectController (
318 UserHandle,
319 NULL,
320 NULL,
321 TRUE
322 );
323 CoreAcquireProtocolLock ();
324
325 //
326 // Notify the notification list for this protocol
327 //
328 CoreNotifyProtocolEntry (ProtEntry);
329
330 CoreReleaseProtocolLock ();
331
332 return EFI_SUCCESS;
333 }