]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - MdeModulePkg/Core/Dxe/Hand/Handle.c
MdeModulePkg: Make retval in UninstallMultipleProtocol follow Spec
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / Hand / Handle.c
... / ...
CommitLineData
1/** @file\r
2 UEFI handle & protocol handling.\r
3\r
4Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
5SPDX-License-Identifier: BSD-2-Clause-Patent\r
6\r
7**/\r
8\r
9#include "DxeMain.h"\r
10#include "Handle.h"\r
11\r
12\r
13//\r
14// mProtocolDatabase - A list of all protocols in the system. (simple list for now)\r
15// gHandleList - A list of all the handles in the system\r
16// gProtocolDatabaseLock - Lock to protect the mProtocolDatabase\r
17// gHandleDatabaseKey - The Key to show that the handle has been created/modified\r
18//\r
19LIST_ENTRY mProtocolDatabase = INITIALIZE_LIST_HEAD_VARIABLE (mProtocolDatabase);\r
20LIST_ENTRY gHandleList = INITIALIZE_LIST_HEAD_VARIABLE (gHandleList);\r
21EFI_LOCK gProtocolDatabaseLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY);\r
22UINT64 gHandleDatabaseKey = 0;\r
23\r
24\r
25\r
26/**\r
27 Acquire lock on gProtocolDatabaseLock.\r
28\r
29**/\r
30VOID\r
31CoreAcquireProtocolLock (\r
32 VOID\r
33 )\r
34{\r
35 CoreAcquireLock (&gProtocolDatabaseLock);\r
36}\r
37\r
38\r
39\r
40/**\r
41 Release lock on gProtocolDatabaseLock.\r
42\r
43**/\r
44VOID\r
45CoreReleaseProtocolLock (\r
46 VOID\r
47 )\r
48{\r
49 CoreReleaseLock (&gProtocolDatabaseLock);\r
50}\r
51\r
52\r
53\r
54/**\r
55 Check whether a handle is a valid EFI_HANDLE\r
56\r
57 @param UserHandle The handle to check\r
58\r
59 @retval EFI_INVALID_PARAMETER The handle is NULL or not a valid EFI_HANDLE.\r
60 @retval EFI_SUCCESS The handle is valid EFI_HANDLE.\r
61\r
62**/\r
63EFI_STATUS\r
64CoreValidateHandle (\r
65 IN EFI_HANDLE UserHandle\r
66 )\r
67{\r
68 IHANDLE *Handle;\r
69 LIST_ENTRY *Link;\r
70\r
71 if (UserHandle == NULL) {\r
72 return EFI_INVALID_PARAMETER;\r
73 }\r
74\r
75 for (Link = gHandleList.BackLink; Link != &gHandleList; Link = Link->BackLink) {\r
76 Handle = CR (Link, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE);\r
77 if (Handle == (IHANDLE *) UserHandle) {\r
78 return EFI_SUCCESS;\r
79 }\r
80 }\r
81\r
82 return EFI_INVALID_PARAMETER;\r
83}\r
84\r
85\r
86\r
87/**\r
88 Finds the protocol entry for the requested protocol.\r
89 The gProtocolDatabaseLock must be owned\r
90\r
91 @param Protocol The ID of the protocol\r
92 @param Create Create a new entry if not found\r
93\r
94 @return Protocol entry\r
95\r
96**/\r
97PROTOCOL_ENTRY *\r
98CoreFindProtocolEntry (\r
99 IN EFI_GUID *Protocol,\r
100 IN BOOLEAN Create\r
101 )\r
102{\r
103 LIST_ENTRY *Link;\r
104 PROTOCOL_ENTRY *Item;\r
105 PROTOCOL_ENTRY *ProtEntry;\r
106\r
107 ASSERT_LOCKED(&gProtocolDatabaseLock);\r
108\r
109 //\r
110 // Search the database for the matching GUID\r
111 //\r
112\r
113 ProtEntry = NULL;\r
114 for (Link = mProtocolDatabase.ForwardLink;\r
115 Link != &mProtocolDatabase;\r
116 Link = Link->ForwardLink) {\r
117\r
118 Item = CR(Link, PROTOCOL_ENTRY, AllEntries, PROTOCOL_ENTRY_SIGNATURE);\r
119 if (CompareGuid (&Item->ProtocolID, Protocol)) {\r
120\r
121 //\r
122 // This is the protocol entry\r
123 //\r
124\r
125 ProtEntry = Item;\r
126 break;\r
127 }\r
128 }\r
129\r
130 //\r
131 // If the protocol entry was not found and Create is TRUE, then\r
132 // allocate a new entry\r
133 //\r
134 if ((ProtEntry == NULL) && Create) {\r
135 ProtEntry = AllocatePool (sizeof(PROTOCOL_ENTRY));\r
136\r
137 if (ProtEntry != NULL) {\r
138 //\r
139 // Initialize new protocol entry structure\r
140 //\r
141 ProtEntry->Signature = PROTOCOL_ENTRY_SIGNATURE;\r
142 CopyGuid ((VOID *)&ProtEntry->ProtocolID, Protocol);\r
143 InitializeListHead (&ProtEntry->Protocols);\r
144 InitializeListHead (&ProtEntry->Notify);\r
145\r
146 //\r
147 // Add it to protocol database\r
148 //\r
149 InsertTailList (&mProtocolDatabase, &ProtEntry->AllEntries);\r
150 }\r
151 }\r
152\r
153 return ProtEntry;\r
154}\r
155\r
156\r
157\r
158/**\r
159 Finds the protocol instance for the requested handle and protocol.\r
160 Note: This function doesn't do parameters checking, it's caller's responsibility\r
161 to pass in valid parameters.\r
162\r
163 @param Handle The handle to search the protocol on\r
164 @param Protocol GUID of the protocol\r
165 @param Interface The interface for the protocol being searched\r
166\r
167 @return Protocol instance (NULL: Not found)\r
168\r
169**/\r
170PROTOCOL_INTERFACE *\r
171CoreFindProtocolInterface (\r
172 IN IHANDLE *Handle,\r
173 IN EFI_GUID *Protocol,\r
174 IN VOID *Interface\r
175 )\r
176{\r
177 PROTOCOL_INTERFACE *Prot;\r
178 PROTOCOL_ENTRY *ProtEntry;\r
179 LIST_ENTRY *Link;\r
180\r
181 ASSERT_LOCKED(&gProtocolDatabaseLock);\r
182 Prot = NULL;\r
183\r
184 //\r
185 // Lookup the protocol entry for this protocol ID\r
186 //\r
187\r
188 ProtEntry = CoreFindProtocolEntry (Protocol, FALSE);\r
189 if (ProtEntry != NULL) {\r
190\r
191 //\r
192 // Look at each protocol interface for any matches\r
193 //\r
194 for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link=Link->ForwardLink) {\r
195\r
196 //\r
197 // If this protocol interface matches, remove it\r
198 //\r
199 Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);\r
200 if (Prot->Interface == Interface && Prot->Protocol == ProtEntry) {\r
201 break;\r
202 }\r
203\r
204 Prot = NULL;\r
205 }\r
206 }\r
207\r
208 return Prot;\r
209}\r
210\r
211\r
212/**\r
213 Removes an event from a register protocol notify list on a protocol.\r
214\r
215 @param Event The event to search for in the protocol\r
216 database.\r
217\r
218 @return EFI_SUCCESS if the event was found and removed.\r
219 @return EFI_NOT_FOUND if the event was not found in the protocl database.\r
220\r
221**/\r
222EFI_STATUS\r
223CoreUnregisterProtocolNotifyEvent (\r
224 IN EFI_EVENT Event\r
225 )\r
226{\r
227 LIST_ENTRY *Link;\r
228 PROTOCOL_ENTRY *ProtEntry;\r
229 LIST_ENTRY *NotifyLink;\r
230 PROTOCOL_NOTIFY *ProtNotify;\r
231\r
232 CoreAcquireProtocolLock ();\r
233\r
234 for ( Link = mProtocolDatabase.ForwardLink;\r
235 Link != &mProtocolDatabase;\r
236 Link = Link->ForwardLink) {\r
237\r
238 ProtEntry = CR(Link, PROTOCOL_ENTRY, AllEntries, PROTOCOL_ENTRY_SIGNATURE);\r
239\r
240 for ( NotifyLink = ProtEntry->Notify.ForwardLink;\r
241 NotifyLink != &ProtEntry->Notify;\r
242 NotifyLink = NotifyLink->ForwardLink) {\r
243\r
244 ProtNotify = CR(NotifyLink, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE);\r
245\r
246 if (ProtNotify->Event == Event) {\r
247 RemoveEntryList(&ProtNotify->Link);\r
248 CoreFreePool(ProtNotify);\r
249 CoreReleaseProtocolLock ();\r
250 return EFI_SUCCESS;\r
251 }\r
252 }\r
253 }\r
254\r
255 CoreReleaseProtocolLock ();\r
256 return EFI_NOT_FOUND;\r
257}\r
258\r
259\r
260\r
261/**\r
262 Removes all the events in the protocol database that match Event.\r
263\r
264 @param Event The event to search for in the protocol\r
265 database.\r
266\r
267 @return EFI_SUCCESS when done searching the entire database.\r
268\r
269**/\r
270EFI_STATUS\r
271CoreUnregisterProtocolNotify (\r
272 IN EFI_EVENT Event\r
273 )\r
274{\r
275 EFI_STATUS Status;\r
276\r
277 do {\r
278 Status = CoreUnregisterProtocolNotifyEvent (Event);\r
279 } while (!EFI_ERROR (Status));\r
280\r
281 return EFI_SUCCESS;\r
282}\r
283\r
284\r
285\r
286\r
287/**\r
288 Wrapper function to CoreInstallProtocolInterfaceNotify. This is the public API which\r
289 Calls the private one which contains a BOOLEAN parameter for notifications\r
290\r
291 @param UserHandle The handle to install the protocol handler on,\r
292 or NULL if a new handle is to be allocated\r
293 @param Protocol The protocol to add to the handle\r
294 @param InterfaceType Indicates whether Interface is supplied in\r
295 native form.\r
296 @param Interface The interface for the protocol being added\r
297\r
298 @return Status code\r
299\r
300**/\r
301EFI_STATUS\r
302EFIAPI\r
303CoreInstallProtocolInterface (\r
304 IN OUT EFI_HANDLE *UserHandle,\r
305 IN EFI_GUID *Protocol,\r
306 IN EFI_INTERFACE_TYPE InterfaceType,\r
307 IN VOID *Interface\r
308 )\r
309{\r
310 return CoreInstallProtocolInterfaceNotify (\r
311 UserHandle,\r
312 Protocol,\r
313 InterfaceType,\r
314 Interface,\r
315 TRUE\r
316 );\r
317}\r
318\r
319\r
320/**\r
321 Installs a protocol interface into the boot services environment.\r
322\r
323 @param UserHandle The handle to install the protocol handler on,\r
324 or NULL if a new handle is to be allocated\r
325 @param Protocol The protocol to add to the handle\r
326 @param InterfaceType Indicates whether Interface is supplied in\r
327 native form.\r
328 @param Interface The interface for the protocol being added\r
329 @param Notify indicates whether notify the notification list\r
330 for this protocol\r
331\r
332 @retval EFI_INVALID_PARAMETER Invalid parameter\r
333 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate\r
334 @retval EFI_SUCCESS Protocol interface successfully installed\r
335\r
336**/\r
337EFI_STATUS\r
338CoreInstallProtocolInterfaceNotify (\r
339 IN OUT EFI_HANDLE *UserHandle,\r
340 IN EFI_GUID *Protocol,\r
341 IN EFI_INTERFACE_TYPE InterfaceType,\r
342 IN VOID *Interface,\r
343 IN BOOLEAN Notify\r
344 )\r
345{\r
346 PROTOCOL_INTERFACE *Prot;\r
347 PROTOCOL_ENTRY *ProtEntry;\r
348 IHANDLE *Handle;\r
349 EFI_STATUS Status;\r
350 VOID *ExistingInterface;\r
351\r
352 //\r
353 // returns EFI_INVALID_PARAMETER if InterfaceType is invalid.\r
354 // Also added check for invalid UserHandle and Protocol pointers.\r
355 //\r
356 if (UserHandle == NULL || Protocol == NULL) {\r
357 return EFI_INVALID_PARAMETER;\r
358 }\r
359\r
360 if (InterfaceType != EFI_NATIVE_INTERFACE) {\r
361 return EFI_INVALID_PARAMETER;\r
362 }\r
363\r
364 //\r
365 // Print debug message\r
366 //\r
367 DEBUG((DEBUG_INFO, "InstallProtocolInterface: %g %p\n", Protocol, Interface));\r
368\r
369 Status = EFI_OUT_OF_RESOURCES;\r
370 Prot = NULL;\r
371 Handle = NULL;\r
372\r
373 if (*UserHandle != NULL) {\r
374 Status = CoreHandleProtocol (*UserHandle, Protocol, (VOID **)&ExistingInterface);\r
375 if (!EFI_ERROR (Status)) {\r
376 return EFI_INVALID_PARAMETER;\r
377 }\r
378 }\r
379\r
380 //\r
381 // Lock the protocol database\r
382 //\r
383 CoreAcquireProtocolLock ();\r
384\r
385 //\r
386 // Lookup the Protocol Entry for the requested protocol\r
387 //\r
388 ProtEntry = CoreFindProtocolEntry (Protocol, TRUE);\r
389 if (ProtEntry == NULL) {\r
390 goto Done;\r
391 }\r
392\r
393 //\r
394 // Allocate a new protocol interface structure\r
395 //\r
396 Prot = AllocateZeroPool (sizeof(PROTOCOL_INTERFACE));\r
397 if (Prot == NULL) {\r
398 Status = EFI_OUT_OF_RESOURCES;\r
399 goto Done;\r
400 }\r
401\r
402 //\r
403 // If caller didn't supply a handle, allocate a new one\r
404 //\r
405 Handle = (IHANDLE *)*UserHandle;\r
406 if (Handle == NULL) {\r
407 Handle = AllocateZeroPool (sizeof(IHANDLE));\r
408 if (Handle == NULL) {\r
409 Status = EFI_OUT_OF_RESOURCES;\r
410 goto Done;\r
411 }\r
412\r
413 //\r
414 // Initialize new handler structure\r
415 //\r
416 Handle->Signature = EFI_HANDLE_SIGNATURE;\r
417 InitializeListHead (&Handle->Protocols);\r
418\r
419 //\r
420 // Initialize the Key to show that the handle has been created/modified\r
421 //\r
422 gHandleDatabaseKey++;\r
423 Handle->Key = gHandleDatabaseKey;\r
424\r
425 //\r
426 // Add this handle to the list global list of all handles\r
427 // in the system\r
428 //\r
429 InsertTailList (&gHandleList, &Handle->AllHandles);\r
430 } else {\r
431 Status = CoreValidateHandle (Handle);\r
432 if (EFI_ERROR (Status)) {\r
433 DEBUG((DEBUG_ERROR, "InstallProtocolInterface: input handle at 0x%x is invalid\n", Handle));\r
434 goto Done;\r
435 }\r
436 }\r
437\r
438 //\r
439 // Each interface that is added must be unique\r
440 //\r
441 ASSERT (CoreFindProtocolInterface (Handle, Protocol, Interface) == NULL);\r
442\r
443 //\r
444 // Initialize the protocol interface structure\r
445 //\r
446 Prot->Signature = PROTOCOL_INTERFACE_SIGNATURE;\r
447 Prot->Handle = Handle;\r
448 Prot->Protocol = ProtEntry;\r
449 Prot->Interface = Interface;\r
450\r
451 //\r
452 // Initalize OpenProtocol Data base\r
453 //\r
454 InitializeListHead (&Prot->OpenList);\r
455 Prot->OpenListCount = 0;\r
456\r
457 //\r
458 // Add this protocol interface to the head of the supported\r
459 // protocol list for this handle\r
460 //\r
461 InsertHeadList (&Handle->Protocols, &Prot->Link);\r
462\r
463 //\r
464 // Add this protocol interface to the tail of the\r
465 // protocol entry\r
466 //\r
467 InsertTailList (&ProtEntry->Protocols, &Prot->ByProtocol);\r
468\r
469 //\r
470 // Notify the notification list for this protocol\r
471 //\r
472 if (Notify) {\r
473 CoreNotifyProtocolEntry (ProtEntry);\r
474 }\r
475 Status = EFI_SUCCESS;\r
476\r
477Done:\r
478 //\r
479 // Done, unlock the database and return\r
480 //\r
481 CoreReleaseProtocolLock ();\r
482 if (!EFI_ERROR (Status)) {\r
483 //\r
484 // Return the new handle back to the caller\r
485 //\r
486 *UserHandle = Handle;\r
487 } else {\r
488 //\r
489 // There was an error, clean up\r
490 //\r
491 if (Prot != NULL) {\r
492 CoreFreePool (Prot);\r
493 }\r
494 DEBUG((DEBUG_ERROR, "InstallProtocolInterface: %g %p failed with %r\n", Protocol, Interface, Status));\r
495 }\r
496\r
497 return Status;\r
498}\r
499\r
500\r
501\r
502\r
503/**\r
504 Installs a list of protocol interface into the boot services environment.\r
505 This function calls InstallProtocolInterface() in a loop. If any error\r
506 occures all the protocols added by this function are removed. This is\r
507 basically a lib function to save space.\r
508\r
509 @param Handle The pointer to a handle to install the new\r
510 protocol interfaces on, or a pointer to NULL\r
511 if a new handle is to be allocated.\r
512 @param ... EFI_GUID followed by protocol instance. A NULL\r
513 terminates the list. The pairs are the\r
514 arguments to InstallProtocolInterface(). All the\r
515 protocols are added to Handle.\r
516\r
517 @retval EFI_SUCCESS All the protocol interface was installed.\r
518 @retval EFI_OUT_OF_RESOURCES There was not enough memory in pool to install all the protocols.\r
519 @retval EFI_ALREADY_STARTED A Device Path Protocol instance was passed in that is already present in\r
520 the handle database.\r
521 @retval EFI_INVALID_PARAMETER Handle is NULL.\r
522 @retval EFI_INVALID_PARAMETER Protocol is already installed on the handle specified by Handle.\r
523\r
524**/\r
525EFI_STATUS\r
526EFIAPI\r
527CoreInstallMultipleProtocolInterfaces (\r
528 IN OUT EFI_HANDLE *Handle,\r
529 ...\r
530 )\r
531{\r
532 VA_LIST Args;\r
533 EFI_STATUS Status;\r
534 EFI_GUID *Protocol;\r
535 VOID *Interface;\r
536 EFI_TPL OldTpl;\r
537 UINTN Index;\r
538 EFI_HANDLE OldHandle;\r
539 EFI_HANDLE DeviceHandle;\r
540 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
541\r
542 if (Handle == NULL) {\r
543 return EFI_INVALID_PARAMETER;\r
544 }\r
545\r
546 //\r
547 // Syncronize with notifcations.\r
548 //\r
549 OldTpl = CoreRaiseTpl (TPL_NOTIFY);\r
550 OldHandle = *Handle;\r
551\r
552 //\r
553 // Check for duplicate device path and install the protocol interfaces\r
554 //\r
555 VA_START (Args, Handle);\r
556 for (Index = 0, Status = EFI_SUCCESS; !EFI_ERROR (Status); Index++) {\r
557 //\r
558 // If protocol is NULL, then it's the end of the list\r
559 //\r
560 Protocol = VA_ARG (Args, EFI_GUID *);\r
561 if (Protocol == NULL) {\r
562 break;\r
563 }\r
564\r
565 Interface = VA_ARG (Args, VOID *);\r
566\r
567 //\r
568 // Make sure you are installing on top a device path that has already been added.\r
569 //\r
570 if (CompareGuid (Protocol, &gEfiDevicePathProtocolGuid)) {\r
571 DeviceHandle = NULL;\r
572 DevicePath = Interface;\r
573 Status = CoreLocateDevicePath (&gEfiDevicePathProtocolGuid, &DevicePath, &DeviceHandle);\r
574 if (!EFI_ERROR (Status) && (DeviceHandle != NULL) && IsDevicePathEnd(DevicePath)) {\r
575 Status = EFI_ALREADY_STARTED;\r
576 continue;\r
577 }\r
578 }\r
579\r
580 //\r
581 // Install it\r
582 //\r
583 Status = CoreInstallProtocolInterface (Handle, Protocol, EFI_NATIVE_INTERFACE, Interface);\r
584 }\r
585 VA_END (Args);\r
586\r
587 //\r
588 // If there was an error, remove all the interfaces that were installed without any errors\r
589 //\r
590 if (EFI_ERROR (Status)) {\r
591 //\r
592 // Reset the va_arg back to the first argument.\r
593 //\r
594 VA_START (Args, Handle);\r
595 for (; Index > 1; Index--) {\r
596 Protocol = VA_ARG (Args, EFI_GUID *);\r
597 Interface = VA_ARG (Args, VOID *);\r
598 CoreUninstallProtocolInterface (*Handle, Protocol, Interface);\r
599 }\r
600 VA_END (Args);\r
601\r
602 *Handle = OldHandle;\r
603 }\r
604\r
605 //\r
606 // Done\r
607 //\r
608 CoreRestoreTpl (OldTpl);\r
609 return Status;\r
610}\r
611\r
612\r
613/**\r
614 Attempts to disconnect all drivers that are using the protocol interface being queried.\r
615 If failed, reconnect all drivers disconnected.\r
616 Note: This function doesn't do parameters checking, it's caller's responsibility\r
617 to pass in valid parameters.\r
618\r
619 @param UserHandle The handle on which the protocol is installed\r
620 @param Prot The protocol to disconnect drivers from\r
621\r
622 @retval EFI_SUCCESS Drivers using the protocol interface are all\r
623 disconnected\r
624 @retval EFI_ACCESS_DENIED Failed to disconnect one or all of the drivers\r
625\r
626**/\r
627EFI_STATUS\r
628CoreDisconnectControllersUsingProtocolInterface (\r
629 IN EFI_HANDLE UserHandle,\r
630 IN PROTOCOL_INTERFACE *Prot\r
631 )\r
632{\r
633 EFI_STATUS Status;\r
634 BOOLEAN ItemFound;\r
635 LIST_ENTRY *Link;\r
636 OPEN_PROTOCOL_DATA *OpenData;\r
637\r
638 Status = EFI_SUCCESS;\r
639\r
640 //\r
641 // Attempt to disconnect all drivers from this protocol interface\r
642 //\r
643 do {\r
644 ItemFound = FALSE;\r
645 for (Link = Prot->OpenList.ForwardLink; Link != &Prot->OpenList; Link = Link->ForwardLink) {\r
646 OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);\r
647 if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {\r
648 CoreReleaseProtocolLock ();\r
649 Status = CoreDisconnectController (UserHandle, OpenData->AgentHandle, NULL);\r
650 CoreAcquireProtocolLock ();\r
651 if (!EFI_ERROR (Status)) {\r
652 ItemFound = TRUE;\r
653 }\r
654 break;\r
655 }\r
656 }\r
657 } while (ItemFound);\r
658\r
659 if (!EFI_ERROR (Status)) {\r
660 //\r
661 // Attempt to remove BY_HANDLE_PROTOOCL and GET_PROTOCOL and TEST_PROTOCOL Open List items\r
662 //\r
663 for (Link = Prot->OpenList.ForwardLink; Link != &Prot->OpenList;) {\r
664 OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);\r
665 if ((OpenData->Attributes &\r
666 (EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL | EFI_OPEN_PROTOCOL_GET_PROTOCOL | EFI_OPEN_PROTOCOL_TEST_PROTOCOL)) != 0) {\r
667 Link = RemoveEntryList (&OpenData->Link);\r
668 Prot->OpenListCount--;\r
669 CoreFreePool (OpenData);\r
670 } else {\r
671 Link = Link->ForwardLink;\r
672 }\r
673 }\r
674 }\r
675\r
676 //\r
677 // If there are errors or still has open items in the list, then reconnect all the drivers and return an error\r
678 //\r
679 if (EFI_ERROR (Status) || (Prot->OpenListCount > 0)) {\r
680 CoreReleaseProtocolLock ();\r
681 CoreConnectController (UserHandle, NULL, NULL, TRUE);\r
682 CoreAcquireProtocolLock ();\r
683 Status = EFI_ACCESS_DENIED;\r
684 }\r
685\r
686 return Status;\r
687}\r
688\r
689\r
690\r
691/**\r
692 Uninstalls all instances of a protocol:interfacer from a handle.\r
693 If the last protocol interface is remove from the handle, the\r
694 handle is freed.\r
695\r
696 @param UserHandle The handle to remove the protocol handler from\r
697 @param Protocol The protocol, of protocol:interface, to remove\r
698 @param Interface The interface, of protocol:interface, to remove\r
699\r
700 @retval EFI_INVALID_PARAMETER Protocol is NULL.\r
701 @retval EFI_SUCCESS Protocol interface successfully uninstalled.\r
702\r
703**/\r
704EFI_STATUS\r
705EFIAPI\r
706CoreUninstallProtocolInterface (\r
707 IN EFI_HANDLE UserHandle,\r
708 IN EFI_GUID *Protocol,\r
709 IN VOID *Interface\r
710 )\r
711{\r
712 EFI_STATUS Status;\r
713 IHANDLE *Handle;\r
714 PROTOCOL_INTERFACE *Prot;\r
715\r
716 //\r
717 // Check that Protocol is valid\r
718 //\r
719 if (Protocol == NULL) {\r
720 return EFI_INVALID_PARAMETER;\r
721 }\r
722\r
723 //\r
724 // Check that UserHandle is a valid handle\r
725 //\r
726 Status = CoreValidateHandle (UserHandle);\r
727 if (EFI_ERROR (Status)) {\r
728 return Status;\r
729 }\r
730\r
731 //\r
732 // Lock the protocol database\r
733 //\r
734 CoreAcquireProtocolLock ();\r
735\r
736 //\r
737 // Check that Protocol exists on UserHandle, and Interface matches the interface in the database\r
738 //\r
739 Prot = CoreFindProtocolInterface (UserHandle, Protocol, Interface);\r
740 if (Prot == NULL) {\r
741 Status = EFI_NOT_FOUND;\r
742 goto Done;\r
743 }\r
744\r
745 //\r
746 // Attempt to disconnect all drivers that are using the protocol interface that is about to be removed\r
747 //\r
748 Status = CoreDisconnectControllersUsingProtocolInterface (\r
749 UserHandle,\r
750 Prot\r
751 );\r
752 if (EFI_ERROR (Status)) {\r
753 //\r
754 // One or more drivers refused to release, so return the error\r
755 //\r
756 goto Done;\r
757 }\r
758\r
759 //\r
760 // Remove the protocol interface from the protocol\r
761 //\r
762 Status = EFI_NOT_FOUND;\r
763 Handle = (IHANDLE *)UserHandle;\r
764 Prot = CoreRemoveInterfaceFromProtocol (Handle, Protocol, Interface);\r
765\r
766 if (Prot != NULL) {\r
767 //\r
768 // Update the Key to show that the handle has been created/modified\r
769 //\r
770 gHandleDatabaseKey++;\r
771 Handle->Key = gHandleDatabaseKey;\r
772\r
773 //\r
774 // Remove the protocol interface from the handle\r
775 //\r
776 RemoveEntryList (&Prot->Link);\r
777\r
778 //\r
779 // Free the memory\r
780 //\r
781 Prot->Signature = 0;\r
782 CoreFreePool (Prot);\r
783 Status = EFI_SUCCESS;\r
784 }\r
785\r
786 //\r
787 // If there are no more handlers for the handle, free the handle\r
788 //\r
789 if (IsListEmpty (&Handle->Protocols)) {\r
790 Handle->Signature = 0;\r
791 RemoveEntryList (&Handle->AllHandles);\r
792 CoreFreePool (Handle);\r
793 }\r
794\r
795Done:\r
796 //\r
797 // Done, unlock the database and return\r
798 //\r
799 CoreReleaseProtocolLock ();\r
800 return Status;\r
801}\r
802\r
803\r
804\r
805/**\r
806 Uninstalls a list of protocol interface in the boot services environment.\r
807 This function calls UninstallProtocolInterface() in a loop. This is\r
808 basically a lib function to save space.\r
809\r
810 If any errors are generated while the protocol interfaces are being\r
811 uninstalled, then the protocol interfaces uninstalled prior to the error will\r
812 be reinstalled and EFI_INVALID_PARAMETER will be returned.\r
813\r
814 @param Handle The handle to uninstall the protocol interfaces\r
815 from.\r
816 @param ... EFI_GUID followed by protocol instance. A NULL\r
817 terminates the list. The pairs are the\r
818 arguments to UninstallProtocolInterface(). All\r
819 the protocols are added to Handle.\r
820\r
821 @retval EFI_SUCCESS if all protocol interfaces where uninstalled.\r
822 @retval EFI_INVALID_PARAMETER if any protocol interface could not be\r
823 uninstalled and an attempt was made to\r
824 reinstall previously uninstalled protocol\r
825 interfaces.\r
826**/\r
827EFI_STATUS\r
828EFIAPI\r
829CoreUninstallMultipleProtocolInterfaces (\r
830 IN EFI_HANDLE Handle,\r
831 ...\r
832 )\r
833{\r
834 EFI_STATUS Status;\r
835 VA_LIST Args;\r
836 EFI_GUID *Protocol;\r
837 VOID *Interface;\r
838 UINTN Index;\r
839\r
840 VA_START (Args, Handle);\r
841 for (Index = 0, Status = EFI_SUCCESS; !EFI_ERROR (Status); Index++) {\r
842 //\r
843 // If protocol is NULL, then it's the end of the list\r
844 //\r
845 Protocol = VA_ARG (Args, EFI_GUID *);\r
846 if (Protocol == NULL) {\r
847 break;\r
848 }\r
849\r
850 Interface = VA_ARG (Args, VOID *);\r
851\r
852 //\r
853 // Uninstall it\r
854 //\r
855 Status = CoreUninstallProtocolInterface (Handle, Protocol, Interface);\r
856 }\r
857 VA_END (Args);\r
858\r
859 //\r
860 // If there was an error, add all the interfaces that were\r
861 // uninstalled without any errors\r
862 //\r
863 if (EFI_ERROR (Status)) {\r
864 //\r
865 // Reset the va_arg back to the first argument.\r
866 //\r
867 VA_START (Args, Handle);\r
868 for (; Index > 1; Index--) {\r
869 Protocol = VA_ARG(Args, EFI_GUID *);\r
870 Interface = VA_ARG(Args, VOID *);\r
871 CoreInstallProtocolInterface (&Handle, Protocol, EFI_NATIVE_INTERFACE, Interface);\r
872 }\r
873 VA_END (Args);\r
874 Status = EFI_INVALID_PARAMETER;\r
875 }\r
876\r
877 return Status;\r
878}\r
879\r
880\r
881/**\r
882 Locate a certain GUID protocol interface in a Handle's protocols.\r
883\r
884 @param UserHandle The handle to obtain the protocol interface on\r
885 @param Protocol The GUID of the protocol\r
886\r
887 @return The requested protocol interface for the handle\r
888\r
889**/\r
890PROTOCOL_INTERFACE *\r
891CoreGetProtocolInterface (\r
892 IN EFI_HANDLE UserHandle,\r
893 IN EFI_GUID *Protocol\r
894 )\r
895{\r
896 EFI_STATUS Status;\r
897 PROTOCOL_ENTRY *ProtEntry;\r
898 PROTOCOL_INTERFACE *Prot;\r
899 IHANDLE *Handle;\r
900 LIST_ENTRY *Link;\r
901\r
902 Status = CoreValidateHandle (UserHandle);\r
903 if (EFI_ERROR (Status)) {\r
904 return NULL;\r
905 }\r
906\r
907 Handle = (IHANDLE *)UserHandle;\r
908\r
909 //\r
910 // Look at each protocol interface for a match\r
911 //\r
912 for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {\r
913 Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);\r
914 ProtEntry = Prot->Protocol;\r
915 if (CompareGuid (&ProtEntry->ProtocolID, Protocol)) {\r
916 return Prot;\r
917 }\r
918 }\r
919 return NULL;\r
920}\r
921\r
922\r
923\r
924/**\r
925 Queries a handle to determine if it supports a specified protocol.\r
926\r
927 @param UserHandle The handle being queried.\r
928 @param Protocol The published unique identifier of the protocol.\r
929 @param Interface Supplies the address where a pointer to the\r
930 corresponding Protocol Interface is returned.\r
931\r
932 @retval EFI_SUCCESS The interface information for the specified protocol was returned.\r
933 @retval EFI_UNSUPPORTED The device does not support the specified protocol.\r
934 @retval EFI_INVALID_PARAMETER Handle is NULL..\r
935 @retval EFI_INVALID_PARAMETER Protocol is NULL.\r
936 @retval EFI_INVALID_PARAMETER Interface is NULL.\r
937\r
938**/\r
939EFI_STATUS\r
940EFIAPI\r
941CoreHandleProtocol (\r
942 IN EFI_HANDLE UserHandle,\r
943 IN EFI_GUID *Protocol,\r
944 OUT VOID **Interface\r
945 )\r
946{\r
947 return CoreOpenProtocol (\r
948 UserHandle,\r
949 Protocol,\r
950 Interface,\r
951 gDxeCoreImageHandle,\r
952 NULL,\r
953 EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL\r
954 );\r
955}\r
956\r
957\r
958\r
959/**\r
960 Locates the installed protocol handler for the handle, and\r
961 invokes it to obtain the protocol interface. Usage information\r
962 is registered in the protocol data base.\r
963\r
964 @param UserHandle The handle to obtain the protocol interface on\r
965 @param Protocol The ID of the protocol\r
966 @param Interface The location to return the protocol interface\r
967 @param ImageHandle The handle of the Image that is opening the\r
968 protocol interface specified by Protocol and\r
969 Interface.\r
970 @param ControllerHandle The controller handle that is requiring this\r
971 interface.\r
972 @param Attributes The open mode of the protocol interface\r
973 specified by Handle and Protocol.\r
974\r
975 @retval EFI_INVALID_PARAMETER Protocol is NULL.\r
976 @retval EFI_SUCCESS Get the protocol interface.\r
977\r
978**/\r
979EFI_STATUS\r
980EFIAPI\r
981CoreOpenProtocol (\r
982 IN EFI_HANDLE UserHandle,\r
983 IN EFI_GUID *Protocol,\r
984 OUT VOID **Interface OPTIONAL,\r
985 IN EFI_HANDLE ImageHandle,\r
986 IN EFI_HANDLE ControllerHandle,\r
987 IN UINT32 Attributes\r
988 )\r
989{\r
990 EFI_STATUS Status;\r
991 PROTOCOL_INTERFACE *Prot;\r
992 LIST_ENTRY *Link;\r
993 OPEN_PROTOCOL_DATA *OpenData;\r
994 BOOLEAN ByDriver;\r
995 BOOLEAN Exclusive;\r
996 BOOLEAN Disconnect;\r
997 BOOLEAN ExactMatch;\r
998\r
999 //\r
1000 // Check for invalid Protocol\r
1001 //\r
1002 if (Protocol == NULL) {\r
1003 return EFI_INVALID_PARAMETER;\r
1004 }\r
1005\r
1006 //\r
1007 // Check for invalid Interface\r
1008 //\r
1009 if ((Attributes != EFI_OPEN_PROTOCOL_TEST_PROTOCOL) && (Interface == NULL)) {\r
1010 return EFI_INVALID_PARAMETER;\r
1011 }\r
1012\r
1013 //\r
1014 // Check for invalid UserHandle\r
1015 //\r
1016 Status = CoreValidateHandle (UserHandle);\r
1017 if (EFI_ERROR (Status)) {\r
1018 return Status;\r
1019 }\r
1020\r
1021 //\r
1022 // Check for invalid Attributes\r
1023 //\r
1024 switch (Attributes) {\r
1025 case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER :\r
1026 Status = CoreValidateHandle (ImageHandle);\r
1027 if (EFI_ERROR (Status)) {\r
1028 return Status;\r
1029 }\r
1030 Status = CoreValidateHandle (ControllerHandle);\r
1031 if (EFI_ERROR (Status)) {\r
1032 return Status;\r
1033 }\r
1034 if (UserHandle == ControllerHandle) {\r
1035 return EFI_INVALID_PARAMETER;\r
1036 }\r
1037 break;\r
1038 case EFI_OPEN_PROTOCOL_BY_DRIVER :\r
1039 case EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE :\r
1040 Status = CoreValidateHandle (ImageHandle);\r
1041 if (EFI_ERROR (Status)) {\r
1042 return Status;\r
1043 }\r
1044 Status = CoreValidateHandle (ControllerHandle);\r
1045 if (EFI_ERROR (Status)) {\r
1046 return Status;\r
1047 }\r
1048 break;\r
1049 case EFI_OPEN_PROTOCOL_EXCLUSIVE :\r
1050 Status = CoreValidateHandle (ImageHandle);\r
1051 if (EFI_ERROR (Status)) {\r
1052 return Status;\r
1053 }\r
1054 break;\r
1055 case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL :\r
1056 case EFI_OPEN_PROTOCOL_GET_PROTOCOL :\r
1057 case EFI_OPEN_PROTOCOL_TEST_PROTOCOL :\r
1058 break;\r
1059 default:\r
1060 return EFI_INVALID_PARAMETER;\r
1061 }\r
1062\r
1063 //\r
1064 // Lock the protocol database\r
1065 //\r
1066 CoreAcquireProtocolLock ();\r
1067\r
1068 //\r
1069 // Look at each protocol interface for a match\r
1070 //\r
1071 Prot = CoreGetProtocolInterface (UserHandle, Protocol);\r
1072 if (Prot == NULL) {\r
1073 Status = EFI_UNSUPPORTED;\r
1074 goto Done;\r
1075 }\r
1076\r
1077 Status = EFI_SUCCESS;\r
1078\r
1079 ByDriver = FALSE;\r
1080 Exclusive = FALSE;\r
1081 for ( Link = Prot->OpenList.ForwardLink; Link != &Prot->OpenList; Link = Link->ForwardLink) {\r
1082 OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);\r
1083 ExactMatch = (BOOLEAN)((OpenData->AgentHandle == ImageHandle) &&\r
1084 (OpenData->Attributes == Attributes) &&\r
1085 (OpenData->ControllerHandle == ControllerHandle));\r
1086 if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {\r
1087 ByDriver = TRUE;\r
1088 if (ExactMatch) {\r
1089 Status = EFI_ALREADY_STARTED;\r
1090 goto Done;\r
1091 }\r
1092 }\r
1093 if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_EXCLUSIVE) != 0) {\r
1094 Exclusive = TRUE;\r
1095 } else if (ExactMatch) {\r
1096 OpenData->OpenCount++;\r
1097 Status = EFI_SUCCESS;\r
1098 goto Done;\r
1099 }\r
1100 }\r
1101\r
1102 //\r
1103 // ByDriver TRUE -> A driver is managing (UserHandle, Protocol)\r
1104 // ByDriver FALSE -> There are no drivers managing (UserHandle, Protocol)\r
1105 // Exclusive TRUE -> Something has exclusive access to (UserHandle, Protocol)\r
1106 // Exclusive FALSE -> Nothing has exclusive access to (UserHandle, Protocol)\r
1107 //\r
1108\r
1109 switch (Attributes) {\r
1110 case EFI_OPEN_PROTOCOL_BY_DRIVER :\r
1111 if (Exclusive || ByDriver) {\r
1112 Status = EFI_ACCESS_DENIED;\r
1113 goto Done;\r
1114 }\r
1115 break;\r
1116 case EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE :\r
1117 case EFI_OPEN_PROTOCOL_EXCLUSIVE :\r
1118 if (Exclusive) {\r
1119 Status = EFI_ACCESS_DENIED;\r
1120 goto Done;\r
1121 }\r
1122 if (ByDriver) {\r
1123 do {\r
1124 Disconnect = FALSE;\r
1125 for (Link = Prot->OpenList.ForwardLink; Link != &Prot->OpenList; Link = Link->ForwardLink) {\r
1126 OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);\r
1127 if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {\r
1128 Disconnect = TRUE;\r
1129 CoreReleaseProtocolLock ();\r
1130 Status = CoreDisconnectController (UserHandle, OpenData->AgentHandle, NULL);\r
1131 CoreAcquireProtocolLock ();\r
1132 if (EFI_ERROR (Status)) {\r
1133 Status = EFI_ACCESS_DENIED;\r
1134 goto Done;\r
1135 } else {\r
1136 break;\r
1137 }\r
1138 }\r
1139 }\r
1140 } while (Disconnect);\r
1141 }\r
1142 break;\r
1143 case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER :\r
1144 case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL :\r
1145 case EFI_OPEN_PROTOCOL_GET_PROTOCOL :\r
1146 case EFI_OPEN_PROTOCOL_TEST_PROTOCOL :\r
1147 break;\r
1148 }\r
1149\r
1150 if (ImageHandle == NULL) {\r
1151 Status = EFI_SUCCESS;\r
1152 goto Done;\r
1153 }\r
1154 //\r
1155 // Create new entry\r
1156 //\r
1157 OpenData = AllocatePool (sizeof(OPEN_PROTOCOL_DATA));\r
1158 if (OpenData == NULL) {\r
1159 Status = EFI_OUT_OF_RESOURCES;\r
1160 } else {\r
1161 OpenData->Signature = OPEN_PROTOCOL_DATA_SIGNATURE;\r
1162 OpenData->AgentHandle = ImageHandle;\r
1163 OpenData->ControllerHandle = ControllerHandle;\r
1164 OpenData->Attributes = Attributes;\r
1165 OpenData->OpenCount = 1;\r
1166 InsertTailList (&Prot->OpenList, &OpenData->Link);\r
1167 Prot->OpenListCount++;\r
1168 Status = EFI_SUCCESS;\r
1169 }\r
1170\r
1171Done:\r
1172\r
1173 if (Attributes != EFI_OPEN_PROTOCOL_TEST_PROTOCOL) {\r
1174 //\r
1175 // Keep Interface unmodified in case of any Error\r
1176 // except EFI_ALREADY_STARTED and EFI_UNSUPPORTED.\r
1177 //\r
1178 if (!EFI_ERROR (Status) || Status == EFI_ALREADY_STARTED) {\r
1179 //\r
1180 // According to above logic, if 'Prot' is NULL, then the 'Status' must be\r
1181 // EFI_UNSUPPORTED. Here the 'Status' is not EFI_UNSUPPORTED, so 'Prot'\r
1182 // must be not NULL.\r
1183 //\r
1184 // The ASSERT here is for addressing a false positive NULL pointer\r
1185 // dereference issue raised from static analysis.\r
1186 //\r
1187 ASSERT (Prot != NULL);\r
1188 //\r
1189 // EFI_ALREADY_STARTED is not an error for bus driver.\r
1190 // Return the corresponding protocol interface.\r
1191 //\r
1192 *Interface = Prot->Interface;\r
1193 } else if (Status == EFI_UNSUPPORTED) {\r
1194 //\r
1195 // Return NULL Interface if Unsupported Protocol.\r
1196 //\r
1197 *Interface = NULL;\r
1198 }\r
1199 }\r
1200\r
1201 //\r
1202 // Done. Release the database lock and return\r
1203 //\r
1204 CoreReleaseProtocolLock ();\r
1205 return Status;\r
1206}\r
1207\r
1208\r
1209\r
1210/**\r
1211 Closes a protocol on a handle that was opened using OpenProtocol().\r
1212\r
1213 @param UserHandle The handle for the protocol interface that was\r
1214 previously opened with OpenProtocol(), and is\r
1215 now being closed.\r
1216 @param Protocol The published unique identifier of the protocol.\r
1217 It is the caller's responsibility to pass in a\r
1218 valid GUID.\r
1219 @param AgentHandle The handle of the agent that is closing the\r
1220 protocol interface.\r
1221 @param ControllerHandle If the agent that opened a protocol is a driver\r
1222 that follows the EFI Driver Model, then this\r
1223 parameter is the controller handle that required\r
1224 the protocol interface. If the agent does not\r
1225 follow the EFI Driver Model, then this parameter\r
1226 is optional and may be NULL.\r
1227\r
1228 @retval EFI_SUCCESS The protocol instance was closed.\r
1229 @retval EFI_INVALID_PARAMETER Handle, AgentHandle or ControllerHandle is not a\r
1230 valid EFI_HANDLE.\r
1231 @retval EFI_NOT_FOUND Can not find the specified protocol or\r
1232 AgentHandle.\r
1233\r
1234**/\r
1235EFI_STATUS\r
1236EFIAPI\r
1237CoreCloseProtocol (\r
1238 IN EFI_HANDLE UserHandle,\r
1239 IN EFI_GUID *Protocol,\r
1240 IN EFI_HANDLE AgentHandle,\r
1241 IN EFI_HANDLE ControllerHandle\r
1242 )\r
1243{\r
1244 EFI_STATUS Status;\r
1245 PROTOCOL_INTERFACE *ProtocolInterface;\r
1246 LIST_ENTRY *Link;\r
1247 OPEN_PROTOCOL_DATA *OpenData;\r
1248\r
1249 //\r
1250 // Check for invalid parameters\r
1251 //\r
1252 Status = CoreValidateHandle (UserHandle);\r
1253 if (EFI_ERROR (Status)) {\r
1254 return Status;\r
1255 }\r
1256 Status = CoreValidateHandle (AgentHandle);\r
1257 if (EFI_ERROR (Status)) {\r
1258 return Status;\r
1259 }\r
1260 if (ControllerHandle != NULL) {\r
1261 Status = CoreValidateHandle (ControllerHandle);\r
1262 if (EFI_ERROR (Status)) {\r
1263 return Status;\r
1264 }\r
1265 }\r
1266 if (Protocol == NULL) {\r
1267 return EFI_INVALID_PARAMETER;\r
1268 }\r
1269\r
1270 //\r
1271 // Lock the protocol database\r
1272 //\r
1273 CoreAcquireProtocolLock ();\r
1274\r
1275 //\r
1276 // Look at each protocol interface for a match\r
1277 //\r
1278 Status = EFI_NOT_FOUND;\r
1279 ProtocolInterface = CoreGetProtocolInterface (UserHandle, Protocol);\r
1280 if (ProtocolInterface == NULL) {\r
1281 goto Done;\r
1282 }\r
1283\r
1284 //\r
1285 // Walk the Open data base looking for AgentHandle\r
1286 //\r
1287 Link = ProtocolInterface->OpenList.ForwardLink;\r
1288 while (Link != &ProtocolInterface->OpenList) {\r
1289 OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);\r
1290 Link = Link->ForwardLink;\r
1291 if ((OpenData->AgentHandle == AgentHandle) && (OpenData->ControllerHandle == ControllerHandle)) {\r
1292 RemoveEntryList (&OpenData->Link);\r
1293 ProtocolInterface->OpenListCount--;\r
1294 CoreFreePool (OpenData);\r
1295 Status = EFI_SUCCESS;\r
1296 }\r
1297 }\r
1298\r
1299Done:\r
1300 //\r
1301 // Done. Release the database lock and return.\r
1302 //\r
1303 CoreReleaseProtocolLock ();\r
1304 return Status;\r
1305}\r
1306\r
1307\r
1308\r
1309\r
1310/**\r
1311 Return information about Opened protocols in the system\r
1312\r
1313 @param UserHandle The handle to close the protocol interface on\r
1314 @param Protocol The ID of the protocol\r
1315 @param EntryBuffer A pointer to a buffer of open protocol information in the\r
1316 form of EFI_OPEN_PROTOCOL_INFORMATION_ENTRY structures.\r
1317 @param EntryCount Number of EntryBuffer entries\r
1318\r
1319 @retval EFI_SUCCESS The open protocol information was returned in EntryBuffer,\r
1320 and the number of entries was returned EntryCount.\r
1321 @retval EFI_NOT_FOUND Handle does not support the protocol specified by Protocol.\r
1322 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to allocate EntryBuffer.\r
1323\r
1324**/\r
1325EFI_STATUS\r
1326EFIAPI\r
1327CoreOpenProtocolInformation (\r
1328 IN EFI_HANDLE UserHandle,\r
1329 IN EFI_GUID *Protocol,\r
1330 OUT EFI_OPEN_PROTOCOL_INFORMATION_ENTRY **EntryBuffer,\r
1331 OUT UINTN *EntryCount\r
1332 )\r
1333{\r
1334 EFI_STATUS Status;\r
1335 PROTOCOL_INTERFACE *ProtocolInterface;\r
1336 LIST_ENTRY *Link;\r
1337 OPEN_PROTOCOL_DATA *OpenData;\r
1338 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *Buffer;\r
1339 UINTN Count;\r
1340 UINTN Size;\r
1341\r
1342 *EntryBuffer = NULL;\r
1343 *EntryCount = 0;\r
1344\r
1345 //\r
1346 // Lock the protocol database\r
1347 //\r
1348 CoreAcquireProtocolLock ();\r
1349\r
1350 //\r
1351 // Look at each protocol interface for a match\r
1352 //\r
1353 Status = EFI_NOT_FOUND;\r
1354 ProtocolInterface = CoreGetProtocolInterface (UserHandle, Protocol);\r
1355 if (ProtocolInterface == NULL) {\r
1356 goto Done;\r
1357 }\r
1358\r
1359 //\r
1360 // Count the number of Open Entries\r
1361 //\r
1362 for ( Link = ProtocolInterface->OpenList.ForwardLink, Count = 0;\r
1363 (Link != &ProtocolInterface->OpenList) ;\r
1364 Link = Link->ForwardLink ) {\r
1365 Count++;\r
1366 }\r
1367\r
1368 ASSERT (Count == ProtocolInterface->OpenListCount);\r
1369\r
1370 if (Count == 0) {\r
1371 Size = sizeof(EFI_OPEN_PROTOCOL_INFORMATION_ENTRY);\r
1372 } else {\r
1373 Size = Count * sizeof(EFI_OPEN_PROTOCOL_INFORMATION_ENTRY);\r
1374 }\r
1375\r
1376 Buffer = AllocatePool (Size);\r
1377 if (Buffer == NULL) {\r
1378 Status = EFI_OUT_OF_RESOURCES;\r
1379 goto Done;\r
1380 }\r
1381\r
1382 Status = EFI_SUCCESS;\r
1383 for ( Link = ProtocolInterface->OpenList.ForwardLink, Count = 0;\r
1384 (Link != &ProtocolInterface->OpenList);\r
1385 Link = Link->ForwardLink, Count++ ) {\r
1386 OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);\r
1387\r
1388 Buffer[Count].AgentHandle = OpenData->AgentHandle;\r
1389 Buffer[Count].ControllerHandle = OpenData->ControllerHandle;\r
1390 Buffer[Count].Attributes = OpenData->Attributes;\r
1391 Buffer[Count].OpenCount = OpenData->OpenCount;\r
1392 }\r
1393\r
1394 *EntryBuffer = Buffer;\r
1395 *EntryCount = Count;\r
1396\r
1397Done:\r
1398 //\r
1399 // Done. Release the database lock.\r
1400 //\r
1401 CoreReleaseProtocolLock ();\r
1402 return Status;\r
1403}\r
1404\r
1405\r
1406\r
1407\r
1408/**\r
1409 Retrieves the list of protocol interface GUIDs that are installed on a handle in a buffer allocated\r
1410 from pool.\r
1411\r
1412 @param UserHandle The handle from which to retrieve the list of\r
1413 protocol interface GUIDs.\r
1414 @param ProtocolBuffer A pointer to the list of protocol interface GUID\r
1415 pointers that are installed on Handle.\r
1416 @param ProtocolBufferCount A pointer to the number of GUID pointers present\r
1417 in ProtocolBuffer.\r
1418\r
1419 @retval EFI_SUCCESS The list of protocol interface GUIDs installed\r
1420 on Handle was returned in ProtocolBuffer. The\r
1421 number of protocol interface GUIDs was returned\r
1422 in ProtocolBufferCount.\r
1423 @retval EFI_INVALID_PARAMETER Handle is NULL.\r
1424 @retval EFI_INVALID_PARAMETER Handle is not a valid EFI_HANDLE.\r
1425 @retval EFI_INVALID_PARAMETER ProtocolBuffer is NULL.\r
1426 @retval EFI_INVALID_PARAMETER ProtocolBufferCount is NULL.\r
1427 @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the\r
1428 results.\r
1429\r
1430**/\r
1431EFI_STATUS\r
1432EFIAPI\r
1433CoreProtocolsPerHandle (\r
1434 IN EFI_HANDLE UserHandle,\r
1435 OUT EFI_GUID ***ProtocolBuffer,\r
1436 OUT UINTN *ProtocolBufferCount\r
1437 )\r
1438{\r
1439 EFI_STATUS Status;\r
1440 IHANDLE *Handle;\r
1441 PROTOCOL_INTERFACE *Prot;\r
1442 LIST_ENTRY *Link;\r
1443 UINTN ProtocolCount;\r
1444 EFI_GUID **Buffer;\r
1445\r
1446 Status = CoreValidateHandle (UserHandle);\r
1447 if (EFI_ERROR (Status)) {\r
1448 return Status;\r
1449 }\r
1450\r
1451 Handle = (IHANDLE *)UserHandle;\r
1452\r
1453 if (ProtocolBuffer == NULL) {\r
1454 return EFI_INVALID_PARAMETER;\r
1455 }\r
1456\r
1457 if (ProtocolBufferCount == NULL) {\r
1458 return EFI_INVALID_PARAMETER;\r
1459 }\r
1460\r
1461 *ProtocolBufferCount = 0;\r
1462\r
1463 ProtocolCount = 0;\r
1464\r
1465 CoreAcquireProtocolLock ();\r
1466\r
1467 for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {\r
1468 ProtocolCount++;\r
1469 }\r
1470\r
1471 //\r
1472 // If there are no protocol interfaces installed on Handle, then Handle is not a valid EFI_HANDLE\r
1473 //\r
1474 if (ProtocolCount == 0) {\r
1475 Status = EFI_INVALID_PARAMETER;\r
1476 goto Done;\r
1477 }\r
1478\r
1479 Buffer = AllocatePool (sizeof (EFI_GUID *) * ProtocolCount);\r
1480 if (Buffer == NULL) {\r
1481 Status = EFI_OUT_OF_RESOURCES;\r
1482 goto Done;\r
1483 }\r
1484\r
1485 *ProtocolBuffer = Buffer;\r
1486 *ProtocolBufferCount = ProtocolCount;\r
1487\r
1488 for ( Link = Handle->Protocols.ForwardLink, ProtocolCount = 0;\r
1489 Link != &Handle->Protocols;\r
1490 Link = Link->ForwardLink, ProtocolCount++) {\r
1491 Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);\r
1492 Buffer[ProtocolCount] = &(Prot->Protocol->ProtocolID);\r
1493 }\r
1494 Status = EFI_SUCCESS;\r
1495\r
1496Done:\r
1497 CoreReleaseProtocolLock ();\r
1498 return Status;\r
1499}\r
1500\r
1501\r
1502\r
1503/**\r
1504 return handle database key.\r
1505\r
1506\r
1507 @return Handle database key.\r
1508\r
1509**/\r
1510UINT64\r
1511CoreGetHandleDatabaseKey (\r
1512 VOID\r
1513 )\r
1514{\r
1515 return gHandleDatabaseKey;\r
1516}\r
1517\r
1518\r
1519\r
1520/**\r
1521 Go connect any handles that were created or modified while a image executed.\r
1522\r
1523 @param Key The Key to show that the handle has been\r
1524 created/modified\r
1525\r
1526**/\r
1527VOID\r
1528CoreConnectHandlesByKey (\r
1529 UINT64 Key\r
1530 )\r
1531{\r
1532 UINTN Count;\r
1533 LIST_ENTRY *Link;\r
1534 EFI_HANDLE *HandleBuffer;\r
1535 IHANDLE *Handle;\r
1536 UINTN Index;\r
1537\r
1538 //\r
1539 // Lock the protocol database\r
1540 //\r
1541 CoreAcquireProtocolLock ();\r
1542\r
1543 for (Link = gHandleList.ForwardLink, Count = 0; Link != &gHandleList; Link = Link->ForwardLink) {\r
1544 Handle = CR (Link, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE);\r
1545 if (Handle->Key > Key) {\r
1546 Count++;\r
1547 }\r
1548 }\r
1549\r
1550 HandleBuffer = AllocatePool (Count * sizeof (EFI_HANDLE));\r
1551 if (HandleBuffer == NULL) {\r
1552 CoreReleaseProtocolLock ();\r
1553 return;\r
1554 }\r
1555\r
1556 for (Link = gHandleList.ForwardLink, Count = 0; Link != &gHandleList; Link = Link->ForwardLink) {\r
1557 Handle = CR (Link, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE);\r
1558 if (Handle->Key > Key) {\r
1559 HandleBuffer[Count++] = Handle;\r
1560 }\r
1561 }\r
1562\r
1563 //\r
1564 // Unlock the protocol database\r
1565 //\r
1566 CoreReleaseProtocolLock ();\r
1567\r
1568 //\r
1569 // Connect all handles whose Key value is greater than Key\r
1570 //\r
1571 for (Index = 0; Index < Count; Index++) {\r
1572 CoreConnectController (HandleBuffer[Index], NULL, NULL, TRUE);\r
1573 }\r
1574\r
1575 CoreFreePool(HandleBuffer);\r
1576}\r