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