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