]> git.proxmox.com Git - mirror_edk2.git/blame - StandaloneMmPkg/Core/Handle.c
SourceLevelDebugPkg: Apply uncrustify changes
[mirror_edk2.git] / StandaloneMmPkg / Core / Handle.c
CommitLineData
6b46d772
SV
1/** @file\r
2 SMM handle & protocol handling.\r
3\r
4 Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>\r
5 Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.<BR>\r
86094561 6 SPDX-License-Identifier: BSD-2-Clause-Patent\r
6b46d772
SV
7\r
8**/\r
9\r
10#include "StandaloneMmCore.h"\r
11\r
12//\r
13// mProtocolDatabase - A list of all protocols in the system. (simple list for now)\r
14// gHandleList - A list of all the handles in the system\r
15//\r
16LIST_ENTRY mProtocolDatabase = INITIALIZE_LIST_HEAD_VARIABLE (mProtocolDatabase);\r
17LIST_ENTRY gHandleList = INITIALIZE_LIST_HEAD_VARIABLE (gHandleList);\r
18\r
19/**\r
20 Check whether a handle is a valid EFI_HANDLE\r
21\r
22 @param UserHandle The handle to check\r
23\r
24 @retval EFI_INVALID_PARAMETER The handle is NULL or not a valid EFI_HANDLE.\r
25 @retval EFI_SUCCESS The handle is valid EFI_HANDLE.\r
26\r
27**/\r
28EFI_STATUS\r
29MmValidateHandle (\r
30 IN EFI_HANDLE UserHandle\r
31 )\r
32{\r
33 IHANDLE *Handle;\r
34\r
35 Handle = (IHANDLE *)UserHandle;\r
36 if (Handle == NULL) {\r
37 return EFI_INVALID_PARAMETER;\r
38 }\r
39 if (Handle->Signature != EFI_HANDLE_SIGNATURE) {\r
40 return EFI_INVALID_PARAMETER;\r
41 }\r
42 return EFI_SUCCESS;\r
43}\r
44\r
45/**\r
46 Finds the protocol entry for the requested protocol.\r
47\r
48 @param Protocol The ID of the protocol\r
49 @param Create Create a new entry if not found\r
50\r
51 @return Protocol entry\r
52\r
53**/\r
54PROTOCOL_ENTRY *\r
55MmFindProtocolEntry (\r
56 IN EFI_GUID *Protocol,\r
57 IN BOOLEAN Create\r
58 )\r
59{\r
60 LIST_ENTRY *Link;\r
61 PROTOCOL_ENTRY *Item;\r
62 PROTOCOL_ENTRY *ProtEntry;\r
63\r
64 //\r
65 // Search the database for the matching GUID\r
66 //\r
67\r
68 ProtEntry = NULL;\r
69 for (Link = mProtocolDatabase.ForwardLink;\r
70 Link != &mProtocolDatabase;\r
71 Link = Link->ForwardLink) {\r
72\r
73 Item = CR (Link, PROTOCOL_ENTRY, AllEntries, PROTOCOL_ENTRY_SIGNATURE);\r
74 if (CompareGuid (&Item->ProtocolID, Protocol)) {\r
75 //\r
76 // This is the protocol entry\r
77 //\r
78 ProtEntry = Item;\r
79 break;\r
80 }\r
81 }\r
82\r
83 //\r
84 // If the protocol entry was not found and Create is TRUE, then\r
85 // allocate a new entry\r
86 //\r
87 if ((ProtEntry == NULL) && Create) {\r
88 ProtEntry = AllocatePool (sizeof(PROTOCOL_ENTRY));\r
89 if (ProtEntry != NULL) {\r
90 //\r
91 // Initialize new protocol entry structure\r
92 //\r
93 ProtEntry->Signature = PROTOCOL_ENTRY_SIGNATURE;\r
94 CopyGuid ((VOID *)&ProtEntry->ProtocolID, Protocol);\r
95 InitializeListHead (&ProtEntry->Protocols);\r
96 InitializeListHead (&ProtEntry->Notify);\r
97\r
98 //\r
99 // Add it to protocol database\r
100 //\r
101 InsertTailList (&mProtocolDatabase, &ProtEntry->AllEntries);\r
102 }\r
103 }\r
104 return ProtEntry;\r
105}\r
106\r
107/**\r
108 Finds the protocol instance for the requested handle and protocol.\r
109 Note: This function doesn't do parameters checking, it's caller's responsibility\r
110 to pass in valid parameters.\r
111\r
112 @param Handle The handle to search the protocol on\r
113 @param Protocol GUID of the protocol\r
114 @param Interface The interface for the protocol being searched\r
115\r
116 @return Protocol instance (NULL: Not found)\r
117\r
118**/\r
119PROTOCOL_INTERFACE *\r
120MmFindProtocolInterface (\r
121 IN IHANDLE *Handle,\r
122 IN EFI_GUID *Protocol,\r
123 IN VOID *Interface\r
124 )\r
125{\r
126 PROTOCOL_INTERFACE *Prot;\r
127 PROTOCOL_ENTRY *ProtEntry;\r
128 LIST_ENTRY *Link;\r
129\r
130 Prot = NULL;\r
131\r
132 //\r
133 // Lookup the protocol entry for this protocol ID\r
134 //\r
135 ProtEntry = MmFindProtocolEntry (Protocol, FALSE);\r
136 if (ProtEntry != NULL) {\r
137 //\r
138 // Look at each protocol interface for any matches\r
139 //\r
140 for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link=Link->ForwardLink) {\r
141 //\r
142 // If this protocol interface matches, remove it\r
143 //\r
144 Prot = CR (Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);\r
145 if (Prot->Interface == Interface && Prot->Protocol == ProtEntry) {\r
146 break;\r
147 }\r
148 Prot = NULL;\r
149 }\r
150 }\r
151 return Prot;\r
152}\r
153\r
154/**\r
155 Wrapper function to MmInstallProtocolInterfaceNotify. This is the public API which\r
156 Calls the private one which contains a BOOLEAN parameter for notifications\r
157\r
158 @param UserHandle The handle to install the protocol handler on,\r
159 or NULL if a new handle is to be allocated\r
160 @param Protocol The protocol to add to the handle\r
161 @param InterfaceType Indicates whether Interface is supplied in\r
162 native form.\r
163 @param Interface The interface for the protocol being added\r
164\r
165 @return Status code\r
166\r
167**/\r
168EFI_STATUS\r
169EFIAPI\r
170MmInstallProtocolInterface (\r
171 IN OUT EFI_HANDLE *UserHandle,\r
172 IN EFI_GUID *Protocol,\r
173 IN EFI_INTERFACE_TYPE InterfaceType,\r
174 IN VOID *Interface\r
175 )\r
176{\r
177 return MmInstallProtocolInterfaceNotify (\r
178 UserHandle,\r
179 Protocol,\r
180 InterfaceType,\r
181 Interface,\r
182 TRUE\r
183 );\r
184}\r
185\r
186/**\r
187 Installs a protocol interface into the boot services environment.\r
188\r
189 @param UserHandle The handle to install the protocol handler on,\r
190 or NULL if a new handle is to be allocated\r
191 @param Protocol The protocol to add to the handle\r
192 @param InterfaceType Indicates whether Interface is supplied in\r
193 native form.\r
194 @param Interface The interface for the protocol being added\r
195 @param Notify indicates whether notify the notification list\r
196 for this protocol\r
197\r
198 @retval EFI_INVALID_PARAMETER Invalid parameter\r
199 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate\r
200 @retval EFI_SUCCESS Protocol interface successfully installed\r
201\r
202**/\r
203EFI_STATUS\r
204MmInstallProtocolInterfaceNotify (\r
205 IN OUT EFI_HANDLE *UserHandle,\r
206 IN EFI_GUID *Protocol,\r
207 IN EFI_INTERFACE_TYPE InterfaceType,\r
208 IN VOID *Interface,\r
209 IN BOOLEAN Notify\r
210 )\r
211{\r
212 PROTOCOL_INTERFACE *Prot;\r
213 PROTOCOL_ENTRY *ProtEntry;\r
214 IHANDLE *Handle;\r
215 EFI_STATUS Status;\r
216 VOID *ExistingInterface;\r
217\r
218 //\r
219 // returns EFI_INVALID_PARAMETER if InterfaceType is invalid.\r
220 // Also added check for invalid UserHandle and Protocol pointers.\r
221 //\r
222 if (UserHandle == NULL || Protocol == NULL) {\r
223 return EFI_INVALID_PARAMETER;\r
224 }\r
225\r
226 if (InterfaceType != EFI_NATIVE_INTERFACE) {\r
227 return EFI_INVALID_PARAMETER;\r
228 }\r
229\r
230 //\r
231 // Print debug message\r
232 //\r
233 DEBUG ((DEBUG_LOAD | DEBUG_INFO, "MmInstallProtocolInterface: %g %p\n", Protocol, Interface));\r
234\r
235 Status = EFI_OUT_OF_RESOURCES;\r
236 Prot = NULL;\r
237 Handle = NULL;\r
238\r
239 if (*UserHandle != NULL) {\r
240 Status = MmHandleProtocol (*UserHandle, Protocol, (VOID **)&ExistingInterface);\r
241 if (!EFI_ERROR (Status)) {\r
242 return EFI_INVALID_PARAMETER;\r
243 }\r
244 }\r
245\r
246 //\r
247 // Lookup the Protocol Entry for the requested protocol\r
248 //\r
249 ProtEntry = MmFindProtocolEntry (Protocol, TRUE);\r
250 if (ProtEntry == NULL) {\r
251 goto Done;\r
252 }\r
253\r
254 //\r
255 // Allocate a new protocol interface structure\r
256 //\r
257 Prot = AllocateZeroPool (sizeof (PROTOCOL_INTERFACE));\r
258 if (Prot == NULL) {\r
259 Status = EFI_OUT_OF_RESOURCES;\r
260 goto Done;\r
261 }\r
262\r
263 //\r
264 // If caller didn't supply a handle, allocate a new one\r
265 //\r
266 Handle = (IHANDLE *)*UserHandle;\r
267 if (Handle == NULL) {\r
268 Handle = AllocateZeroPool (sizeof (IHANDLE));\r
269 if (Handle == NULL) {\r
270 Status = EFI_OUT_OF_RESOURCES;\r
271 goto Done;\r
272 }\r
273\r
274 //\r
275 // Initialize new handler structure\r
276 //\r
277 Handle->Signature = EFI_HANDLE_SIGNATURE;\r
278 InitializeListHead (&Handle->Protocols);\r
279\r
280 //\r
281 // Add this handle to the list global list of all handles\r
282 // in the system\r
283 //\r
284 InsertTailList (&gHandleList, &Handle->AllHandles);\r
285 }\r
286\r
287 Status = MmValidateHandle (Handle);\r
288 if (EFI_ERROR (Status)) {\r
289 goto Done;\r
290 }\r
291\r
292 //\r
293 // Each interface that is added must be unique\r
294 //\r
295 ASSERT (MmFindProtocolInterface (Handle, Protocol, Interface) == NULL);\r
296\r
297 //\r
298 // Initialize the protocol interface structure\r
299 //\r
300 Prot->Signature = PROTOCOL_INTERFACE_SIGNATURE;\r
301 Prot->Handle = Handle;\r
302 Prot->Protocol = ProtEntry;\r
303 Prot->Interface = Interface;\r
304\r
305 //\r
306 // Add this protocol interface to the head of the supported\r
307 // protocol list for this handle\r
308 //\r
309 InsertHeadList (&Handle->Protocols, &Prot->Link);\r
310\r
311 //\r
312 // Add this protocol interface to the tail of the\r
313 // protocol entry\r
314 //\r
315 InsertTailList (&ProtEntry->Protocols, &Prot->ByProtocol);\r
316\r
317 //\r
318 // Notify the notification list for this protocol\r
319 //\r
320 if (Notify) {\r
321 MmNotifyProtocol (Prot);\r
322 }\r
323 Status = EFI_SUCCESS;\r
324\r
325Done:\r
326 if (!EFI_ERROR (Status)) {\r
327 //\r
328 // Return the new handle back to the caller\r
329 //\r
330 *UserHandle = Handle;\r
331 } else {\r
332 //\r
333 // There was an error, clean up\r
334 //\r
335 if (Prot != NULL) {\r
336 FreePool (Prot);\r
337 }\r
338 }\r
339 return Status;\r
340}\r
341\r
342/**\r
343 Uninstalls all instances of a protocol:interfacer from a handle.\r
344 If the last protocol interface is remove from the handle, the\r
345 handle is freed.\r
346\r
347 @param UserHandle The handle to remove the protocol handler from\r
348 @param Protocol The protocol, of protocol:interface, to remove\r
349 @param Interface The interface, of protocol:interface, to remove\r
350\r
351 @retval EFI_INVALID_PARAMETER Protocol is NULL.\r
352 @retval EFI_SUCCESS Protocol interface successfully uninstalled.\r
353\r
354**/\r
355EFI_STATUS\r
356EFIAPI\r
357MmUninstallProtocolInterface (\r
358 IN EFI_HANDLE UserHandle,\r
359 IN EFI_GUID *Protocol,\r
360 IN VOID *Interface\r
361 )\r
362{\r
363 EFI_STATUS Status;\r
364 IHANDLE *Handle;\r
365 PROTOCOL_INTERFACE *Prot;\r
366\r
367 //\r
368 // Check that Protocol is valid\r
369 //\r
370 if (Protocol == NULL) {\r
371 return EFI_INVALID_PARAMETER;\r
372 }\r
373\r
374 //\r
375 // Check that UserHandle is a valid handle\r
376 //\r
377 Status = MmValidateHandle (UserHandle);\r
378 if (EFI_ERROR (Status)) {\r
379 return Status;\r
380 }\r
381\r
382 //\r
383 // Check that Protocol exists on UserHandle, and Interface matches the interface in the database\r
384 //\r
385 Prot = MmFindProtocolInterface (UserHandle, Protocol, Interface);\r
386 if (Prot == NULL) {\r
387 return EFI_NOT_FOUND;\r
388 }\r
389\r
390 //\r
391 // Remove the protocol interface from the protocol\r
392 //\r
393 Status = EFI_NOT_FOUND;\r
394 Handle = (IHANDLE *)UserHandle;\r
395 Prot = MmRemoveInterfaceFromProtocol (Handle, Protocol, Interface);\r
396\r
397 if (Prot != NULL) {\r
398 //\r
399 // Remove the protocol interface from the handle\r
400 //\r
401 RemoveEntryList (&Prot->Link);\r
402\r
403 //\r
404 // Free the memory\r
405 //\r
406 Prot->Signature = 0;\r
407 FreePool (Prot);\r
408 Status = EFI_SUCCESS;\r
409 }\r
410\r
411 //\r
412 // If there are no more handlers for the handle, free the handle\r
413 //\r
414 if (IsListEmpty (&Handle->Protocols)) {\r
415 Handle->Signature = 0;\r
416 RemoveEntryList (&Handle->AllHandles);\r
417 FreePool (Handle);\r
418 }\r
419 return Status;\r
420}\r
421\r
422/**\r
423 Locate a certain GUID protocol interface in a Handle's protocols.\r
424\r
425 @param UserHandle The handle to obtain the protocol interface on\r
426 @param Protocol The GUID of the protocol\r
427\r
428 @return The requested protocol interface for the handle\r
429\r
430**/\r
431PROTOCOL_INTERFACE *\r
432MmGetProtocolInterface (\r
433 IN EFI_HANDLE UserHandle,\r
434 IN EFI_GUID *Protocol\r
435 )\r
436{\r
437 EFI_STATUS Status;\r
438 PROTOCOL_ENTRY *ProtEntry;\r
439 PROTOCOL_INTERFACE *Prot;\r
440 IHANDLE *Handle;\r
441 LIST_ENTRY *Link;\r
442\r
443 Status = MmValidateHandle (UserHandle);\r
444 if (EFI_ERROR (Status)) {\r
445 return NULL;\r
446 }\r
447\r
448 Handle = (IHANDLE *)UserHandle;\r
449\r
450 //\r
451 // Look at each protocol interface for a match\r
452 //\r
453 for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {\r
454 Prot = CR (Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);\r
455 ProtEntry = Prot->Protocol;\r
456 if (CompareGuid (&ProtEntry->ProtocolID, Protocol)) {\r
457 return Prot;\r
458 }\r
459 }\r
460 return NULL;\r
461}\r
462\r
463/**\r
464 Queries a handle to determine if it supports a specified protocol.\r
465\r
466 @param UserHandle The handle being queried.\r
467 @param Protocol The published unique identifier of the protocol.\r
468 @param Interface Supplies the address where a pointer to the\r
469 corresponding Protocol Interface is returned.\r
470\r
471 @retval EFI_SUCCESS The interface information for the specified protocol was returned.\r
472 @retval EFI_UNSUPPORTED The device does not support the specified protocol.\r
473 @retval EFI_INVALID_PARAMETER Handle is not a valid EFI_HANDLE..\r
474 @retval EFI_INVALID_PARAMETER Protocol is NULL.\r
475 @retval EFI_INVALID_PARAMETER Interface is NULL.\r
476\r
477**/\r
478EFI_STATUS\r
479EFIAPI\r
480MmHandleProtocol (\r
481 IN EFI_HANDLE UserHandle,\r
482 IN EFI_GUID *Protocol,\r
483 OUT VOID **Interface\r
484 )\r
485{\r
486 EFI_STATUS Status;\r
487 PROTOCOL_INTERFACE *Prot;\r
488\r
489 //\r
490 // Check for invalid Protocol\r
491 //\r
492 if (Protocol == NULL) {\r
493 return EFI_INVALID_PARAMETER;\r
494 }\r
495\r
496 //\r
497 // Check for invalid Interface\r
498 //\r
499 if (Interface == NULL) {\r
500 return EFI_INVALID_PARAMETER;\r
501 } else {\r
502 *Interface = NULL;\r
503 }\r
504\r
505 //\r
506 // Check for invalid UserHandle\r
507 //\r
508 Status = MmValidateHandle (UserHandle);\r
509 if (EFI_ERROR (Status)) {\r
510 return Status;\r
511 }\r
512\r
513 //\r
514 // Look at each protocol interface for a match\r
515 //\r
516 Prot = MmGetProtocolInterface (UserHandle, Protocol);\r
517 if (Prot == NULL) {\r
518 return EFI_UNSUPPORTED;\r
519 }\r
520\r
521 //\r
522 // This is the protocol interface entry for this protocol\r
523 //\r
524 *Interface = Prot->Interface;\r
525\r
526 return EFI_SUCCESS;\r
527}\r