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