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