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