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