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