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