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