]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Core/Dxe/Hand/Handle.c
deae9d62513f7fa982154c9292b408107040eec6
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / Hand / Handle.c
1 /** @file
2 UEFI handle & protocol handling.
3
4 Copyright (c) 2006 - 2010, 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 #include "Handle.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 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 = AllocatePool (sizeof(PROTOCOL_ENTRY));
137
138 if (ProtEntry != NULL) {
139 //
140 // Initialize new protocol entry structure
141 //
142 ProtEntry->Signature = PROTOCOL_ENTRY_SIGNATURE;
143 CopyGuid ((VOID *)&ProtEntry->ProtocolID, Protocol);
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 EFI_STATUS
224 CoreUnregisterProtocolNotifyEvent (
225 IN EFI_EVENT Event
226 )
227 {
228 LIST_ENTRY *Link;
229 PROTOCOL_ENTRY *ProtEntry;
230 LIST_ENTRY *NotifyLink;
231 PROTOCOL_NOTIFY *ProtNotify;
232
233 CoreAcquireProtocolLock ();
234
235 for ( Link = mProtocolDatabase.ForwardLink;
236 Link != &mProtocolDatabase;
237 Link = Link->ForwardLink) {
238
239 ProtEntry = CR(Link, PROTOCOL_ENTRY, AllEntries, PROTOCOL_ENTRY_SIGNATURE);
240
241 for ( NotifyLink = ProtEntry->Notify.ForwardLink;
242 NotifyLink != &ProtEntry->Notify;
243 NotifyLink = NotifyLink->ForwardLink) {
244
245 ProtNotify = CR(NotifyLink, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE);
246
247 if (ProtNotify->Event == Event) {
248 RemoveEntryList(&ProtNotify->Link);
249 CoreFreePool(ProtNotify);
250 CoreReleaseProtocolLock ();
251 return EFI_SUCCESS;
252 }
253 }
254 }
255
256 CoreReleaseProtocolLock ();
257 return EFI_NOT_FOUND;
258 }
259
260
261
262 /**
263 Removes all the events in the protocol database that match Event.
264
265 @param Event The event to search for in the protocol
266 database.
267
268 @return EFI_SUCCESS when done searching the entire database.
269
270 **/
271 EFI_STATUS
272 CoreUnregisterProtocolNotify (
273 IN EFI_EVENT Event
274 )
275 {
276 EFI_STATUS Status;
277
278 do {
279 Status = CoreUnregisterProtocolNotifyEvent (Event);
280 } while (!EFI_ERROR (Status));
281
282 return EFI_SUCCESS;
283 }
284
285
286
287
288 /**
289 Wrapper function to CoreInstallProtocolInterfaceNotify. This is the public API which
290 Calls the private one which contains a BOOLEAN parameter for notifications
291
292 @param UserHandle The handle to install the protocol handler on,
293 or NULL if a new handle is to be allocated
294 @param Protocol The protocol to add to the handle
295 @param InterfaceType Indicates whether Interface is supplied in
296 native form.
297 @param Interface The interface for the protocol being added
298
299 @return Status code
300
301 **/
302 EFI_STATUS
303 EFIAPI
304 CoreInstallProtocolInterface (
305 IN OUT EFI_HANDLE *UserHandle,
306 IN EFI_GUID *Protocol,
307 IN EFI_INTERFACE_TYPE InterfaceType,
308 IN VOID *Interface
309 )
310 {
311 return CoreInstallProtocolInterfaceNotify (
312 UserHandle,
313 Protocol,
314 InterfaceType,
315 Interface,
316 TRUE
317 );
318 }
319
320
321 /**
322 Installs a protocol interface into the boot services environment.
323
324 @param UserHandle The handle to install the protocol handler on,
325 or NULL if a new handle is to be allocated
326 @param Protocol The protocol to add to the handle
327 @param InterfaceType Indicates whether Interface is supplied in
328 native form.
329 @param Interface The interface for the protocol being added
330 @param Notify indicates whether notify the notification list
331 for this protocol
332
333 @retval EFI_INVALID_PARAMETER Invalid parameter
334 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
335 @retval EFI_SUCCESS Protocol interface successfully installed
336
337 **/
338 EFI_STATUS
339 CoreInstallProtocolInterfaceNotify (
340 IN OUT EFI_HANDLE *UserHandle,
341 IN EFI_GUID *Protocol,
342 IN EFI_INTERFACE_TYPE InterfaceType,
343 IN VOID *Interface,
344 IN BOOLEAN Notify
345 )
346 {
347 PROTOCOL_INTERFACE *Prot;
348 PROTOCOL_ENTRY *ProtEntry;
349 IHANDLE *Handle;
350 EFI_STATUS Status;
351 VOID *ExistingInterface;
352
353 //
354 // returns EFI_INVALID_PARAMETER if InterfaceType is invalid.
355 // Also added check for invalid UserHandle and Protocol pointers.
356 //
357 if (UserHandle == NULL || Protocol == NULL) {
358 return EFI_INVALID_PARAMETER;
359 }
360
361 if (InterfaceType != EFI_NATIVE_INTERFACE) {
362 return EFI_INVALID_PARAMETER;
363 }
364
365 //
366 // Print debug message
367 //
368 DEBUG((DEBUG_INFO, "InstallProtocolInterface: %g %p\n", Protocol, Interface));
369
370 Status = EFI_OUT_OF_RESOURCES;
371 Prot = NULL;
372 Handle = NULL;
373
374 if (*UserHandle != NULL) {
375 Status = CoreHandleProtocol (*UserHandle, Protocol, (VOID **)&ExistingInterface);
376 if (!EFI_ERROR (Status)) {
377 return EFI_INVALID_PARAMETER;
378 }
379 }
380
381 //
382 // Lock the protocol database
383 //
384 CoreAcquireProtocolLock ();
385
386 //
387 // Lookup the Protocol Entry for the requested protocol
388 //
389 ProtEntry = CoreFindProtocolEntry (Protocol, TRUE);
390 if (ProtEntry == NULL) {
391 goto Done;
392 }
393
394 //
395 // Allocate a new protocol interface structure
396 //
397 Prot = AllocateZeroPool (sizeof(PROTOCOL_INTERFACE));
398 if (Prot == NULL) {
399 Status = EFI_OUT_OF_RESOURCES;
400 goto Done;
401 }
402
403 //
404 // If caller didn't supply a handle, allocate a new one
405 //
406 Handle = (IHANDLE *)*UserHandle;
407 if (Handle == NULL) {
408 Handle = AllocateZeroPool (sizeof(IHANDLE));
409 if (Handle == NULL) {
410 Status = EFI_OUT_OF_RESOURCES;
411 goto Done;
412 }
413
414 //
415 // Initialize new handler structure
416 //
417 Handle->Signature = EFI_HANDLE_SIGNATURE;
418 InitializeListHead (&Handle->Protocols);
419
420 //
421 // Initialize the Key to show that the handle has been created/modified
422 //
423 gHandleDatabaseKey++;
424 Handle->Key = gHandleDatabaseKey;
425
426 //
427 // Add this handle to the list global list of all handles
428 // in the system
429 //
430 InsertTailList (&gHandleList, &Handle->AllHandles);
431 }
432
433 Status = CoreValidateHandle (Handle);
434 if (EFI_ERROR (Status)) {
435 goto Done;
436 }
437
438 //
439 // Each interface that is added must be unique
440 //
441 ASSERT (CoreFindProtocolInterface (Handle, Protocol, Interface) == NULL);
442
443 //
444 // Initialize the protocol interface structure
445 //
446 Prot->Signature = PROTOCOL_INTERFACE_SIGNATURE;
447 Prot->Handle = Handle;
448 Prot->Protocol = ProtEntry;
449 Prot->Interface = Interface;
450
451 //
452 // Initalize OpenProtocol Data base
453 //
454 InitializeListHead (&Prot->OpenList);
455 Prot->OpenListCount = 0;
456
457 //
458 // Add this protocol interface to the head of the supported
459 // protocol list for this handle
460 //
461 InsertHeadList (&Handle->Protocols, &Prot->Link);
462
463 //
464 // Add this protocol interface to the tail of the
465 // protocol entry
466 //
467 InsertTailList (&ProtEntry->Protocols, &Prot->ByProtocol);
468
469 //
470 // Notify the notification list for this protocol
471 //
472 if (Notify) {
473 CoreNotifyProtocolEntry (ProtEntry);
474 }
475 Status = EFI_SUCCESS;
476
477 Done:
478 //
479 // Done, unlock the database and return
480 //
481 CoreReleaseProtocolLock ();
482 if (!EFI_ERROR (Status)) {
483 //
484 // Return the new handle back to the caller
485 //
486 *UserHandle = Handle;
487 } else {
488 //
489 // There was an error, clean up
490 //
491 if (Prot != NULL) {
492 CoreFreePool (Prot);
493 }
494 }
495
496 return Status;
497 }
498
499
500
501
502 /**
503 Installs a list of protocol interface into the boot services environment.
504 This function calls InstallProtocolInterface() in a loop. If any error
505 occures all the protocols added by this function are removed. This is
506 basically a lib function to save space.
507
508 @param Handle The handle to install the protocol handlers on,
509 or NULL if a new handle is to be allocated
510 @param ... EFI_GUID followed by protocol instance. A NULL
511 terminates the list. The pairs are the
512 arguments to InstallProtocolInterface(). All the
513 protocols are added to Handle.
514
515 @retval EFI_INVALID_PARAMETER Handle is NULL.
516 @retval EFI_SUCCESS Protocol interfaces successfully installed.
517
518 **/
519 EFI_STATUS
520 EFIAPI
521 CoreInstallMultipleProtocolInterfaces (
522 IN OUT EFI_HANDLE *Handle,
523 ...
524 )
525 {
526 VA_LIST Args;
527 EFI_STATUS Status;
528 EFI_GUID *Protocol;
529 VOID *Interface;
530 EFI_TPL OldTpl;
531 UINTN Index;
532 EFI_HANDLE OldHandle;
533 EFI_HANDLE DeviceHandle;
534 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
535
536 if (Handle == NULL) {
537 return EFI_INVALID_PARAMETER;
538 }
539
540 //
541 // Syncronize with notifcations.
542 //
543 OldTpl = CoreRaiseTpl (TPL_NOTIFY);
544 OldHandle = *Handle;
545
546 //
547 // Check for duplicate device path and install the protocol interfaces
548 //
549 VA_START (Args, Handle);
550 for (Index = 0, Status = EFI_SUCCESS; !EFI_ERROR (Status); Index++) {
551 //
552 // If protocol is NULL, then it's the end of the list
553 //
554 Protocol = VA_ARG (Args, EFI_GUID *);
555 if (Protocol == NULL) {
556 break;
557 }
558
559 Interface = VA_ARG (Args, VOID *);
560
561 //
562 // Make sure you are installing on top a device path that has already been added.
563 //
564 if (CompareGuid (Protocol, &gEfiDevicePathProtocolGuid)) {
565 DeviceHandle = NULL;
566 DevicePath = Interface;
567 Status = CoreLocateDevicePath (&gEfiDevicePathProtocolGuid, &DevicePath, &DeviceHandle);
568 if (!EFI_ERROR (Status) && (DeviceHandle != NULL) && IsDevicePathEnd(DevicePath)) {
569 Status = EFI_ALREADY_STARTED;
570 continue;
571 }
572 }
573
574 //
575 // Install it
576 //
577 Status = CoreInstallProtocolInterface (Handle, Protocol, EFI_NATIVE_INTERFACE, Interface);
578 }
579 VA_END (Args);
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 VA_END (Args);
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) != 0) {
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)) != 0) {
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 VA_END (Args);
852
853 //
854 // If there was an error, add all the interfaces that were
855 // uninstalled without any errors
856 //
857 if (EFI_ERROR (Status)) {
858 //
859 // Reset the va_arg back to the first argument.
860 //
861 VA_START (Args, Handle);
862 for (; Index > 1; Index--) {
863 Protocol = VA_ARG(Args, EFI_GUID *);
864 Interface = VA_ARG(Args, VOID *);
865 CoreInstallProtocolInterface (&Handle, Protocol, EFI_NATIVE_INTERFACE, Interface);
866 }
867 VA_END (Args);
868 }
869
870 return Status;
871 }
872
873
874 /**
875 Locate a certain GUID protocol interface in a Handle's protocols.
876
877 @param UserHandle The handle to obtain the protocol interface on
878 @param Protocol The GUID of the protocol
879
880 @return The requested protocol interface for the handle
881
882 **/
883 PROTOCOL_INTERFACE *
884 CoreGetProtocolInterface (
885 IN EFI_HANDLE UserHandle,
886 IN EFI_GUID *Protocol
887 )
888 {
889 EFI_STATUS Status;
890 PROTOCOL_ENTRY *ProtEntry;
891 PROTOCOL_INTERFACE *Prot;
892 IHANDLE *Handle;
893 LIST_ENTRY *Link;
894
895 Status = CoreValidateHandle (UserHandle);
896 if (EFI_ERROR (Status)) {
897 return NULL;
898 }
899
900 Handle = (IHANDLE *)UserHandle;
901
902 //
903 // Look at each protocol interface for a match
904 //
905 for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
906 Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
907 ProtEntry = Prot->Protocol;
908 if (CompareGuid (&ProtEntry->ProtocolID, Protocol)) {
909 return Prot;
910 }
911 }
912 return NULL;
913 }
914
915
916
917 /**
918 Queries a handle to determine if it supports a specified protocol.
919
920 @param UserHandle The handle being queried.
921 @param Protocol The published unique identifier of the protocol.
922 @param Interface Supplies the address where a pointer to the
923 corresponding Protocol Interface is returned.
924
925 @retval EFI_SUCCESS The interface information for the specified protocol was returned.
926 @retval EFI_UNSUPPORTED The device does not support the specified protocol.
927 @retval EFI_INVALID_PARAMETER Handle is not a valid EFI_HANDLE..
928 @retval EFI_INVALID_PARAMETER Protocol is NULL.
929 @retval EFI_INVALID_PARAMETER Interface is NULL.
930
931 **/
932 EFI_STATUS
933 EFIAPI
934 CoreHandleProtocol (
935 IN EFI_HANDLE UserHandle,
936 IN EFI_GUID *Protocol,
937 OUT VOID **Interface
938 )
939 {
940 return CoreOpenProtocol (
941 UserHandle,
942 Protocol,
943 Interface,
944 gDxeCoreImageHandle,
945 NULL,
946 EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
947 );
948 }
949
950
951
952 /**
953 Locates the installed protocol handler for the handle, and
954 invokes it to obtain the protocol interface. Usage information
955 is registered in the protocol data base.
956
957 @param UserHandle The handle to obtain the protocol interface on
958 @param Protocol The ID of the protocol
959 @param Interface The location to return the protocol interface
960 @param ImageHandle The handle of the Image that is opening the
961 protocol interface specified by Protocol and
962 Interface.
963 @param ControllerHandle The controller handle that is requiring this
964 interface.
965 @param Attributes The open mode of the protocol interface
966 specified by Handle and Protocol.
967
968 @retval EFI_INVALID_PARAMETER Protocol is NULL.
969 @retval EFI_SUCCESS Get the protocol interface.
970
971 **/
972 EFI_STATUS
973 EFIAPI
974 CoreOpenProtocol (
975 IN EFI_HANDLE UserHandle,
976 IN EFI_GUID *Protocol,
977 OUT VOID **Interface OPTIONAL,
978 IN EFI_HANDLE ImageHandle,
979 IN EFI_HANDLE ControllerHandle,
980 IN UINT32 Attributes
981 )
982 {
983 EFI_STATUS Status;
984 PROTOCOL_INTERFACE *Prot;
985 LIST_ENTRY *Link;
986 OPEN_PROTOCOL_DATA *OpenData;
987 BOOLEAN ByDriver;
988 BOOLEAN Exclusive;
989 BOOLEAN Disconnect;
990 BOOLEAN ExactMatch;
991
992 //
993 // Check for invalid Protocol
994 //
995 if (Protocol == NULL) {
996 return EFI_INVALID_PARAMETER;
997 }
998
999 //
1000 // Check for invalid Interface
1001 //
1002 if (Attributes != EFI_OPEN_PROTOCOL_TEST_PROTOCOL) {
1003 if (Interface == NULL) {
1004 return EFI_INVALID_PARAMETER;
1005 } else {
1006 *Interface = NULL;
1007 }
1008 }
1009
1010 //
1011 // Check for invalid UserHandle
1012 //
1013 Status = CoreValidateHandle (UserHandle);
1014 if (EFI_ERROR (Status)) {
1015 return Status;
1016 }
1017
1018 //
1019 // Check for invalid Attributes
1020 //
1021 switch (Attributes) {
1022 case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER :
1023 Status = CoreValidateHandle (ImageHandle);
1024 if (EFI_ERROR (Status)) {
1025 return Status;
1026 }
1027 Status = CoreValidateHandle (ControllerHandle);
1028 if (EFI_ERROR (Status)) {
1029 return Status;
1030 }
1031 if (UserHandle == ControllerHandle) {
1032 return EFI_INVALID_PARAMETER;
1033 }
1034 break;
1035 case EFI_OPEN_PROTOCOL_BY_DRIVER :
1036 case EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE :
1037 Status = CoreValidateHandle (ImageHandle);
1038 if (EFI_ERROR (Status)) {
1039 return Status;
1040 }
1041 Status = CoreValidateHandle (ControllerHandle);
1042 if (EFI_ERROR (Status)) {
1043 return Status;
1044 }
1045 break;
1046 case EFI_OPEN_PROTOCOL_EXCLUSIVE :
1047 Status = CoreValidateHandle (ImageHandle);
1048 if (EFI_ERROR (Status)) {
1049 return Status;
1050 }
1051 break;
1052 case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL :
1053 case EFI_OPEN_PROTOCOL_GET_PROTOCOL :
1054 case EFI_OPEN_PROTOCOL_TEST_PROTOCOL :
1055 break;
1056 default:
1057 return EFI_INVALID_PARAMETER;
1058 }
1059
1060 //
1061 // Lock the protocol database
1062 //
1063 CoreAcquireProtocolLock ();
1064
1065 //
1066 // Look at each protocol interface for a match
1067 //
1068 Prot = CoreGetProtocolInterface (UserHandle, Protocol);
1069 if (Prot == NULL) {
1070 Status = EFI_UNSUPPORTED;
1071 goto Done;
1072 }
1073
1074 //
1075 // This is the protocol interface entry for this protocol
1076 //
1077 if (Attributes != EFI_OPEN_PROTOCOL_TEST_PROTOCOL) {
1078 *Interface = Prot->Interface;
1079 }
1080 Status = EFI_SUCCESS;
1081
1082 ByDriver = FALSE;
1083 Exclusive = FALSE;
1084 for ( Link = Prot->OpenList.ForwardLink; Link != &Prot->OpenList; Link = Link->ForwardLink) {
1085 OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
1086 ExactMatch = (BOOLEAN)((OpenData->AgentHandle == ImageHandle) &&
1087 (OpenData->Attributes == Attributes) &&
1088 (OpenData->ControllerHandle == ControllerHandle));
1089 if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
1090 ByDriver = TRUE;
1091 if (ExactMatch) {
1092 Status = EFI_ALREADY_STARTED;
1093 goto Done;
1094 }
1095 }
1096 if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_EXCLUSIVE) != 0) {
1097 Exclusive = TRUE;
1098 } else if (ExactMatch) {
1099 OpenData->OpenCount++;
1100 Status = EFI_SUCCESS;
1101 goto Done;
1102 }
1103 }
1104
1105 //
1106 // ByDriver TRUE -> A driver is managing (UserHandle, Protocol)
1107 // ByDriver FALSE -> There are no drivers managing (UserHandle, Protocol)
1108 // Exclusive TRUE -> Something has exclusive access to (UserHandle, Protocol)
1109 // Exclusive FALSE -> Nothing has exclusive access to (UserHandle, Protocol)
1110 //
1111
1112 switch (Attributes) {
1113 case EFI_OPEN_PROTOCOL_BY_DRIVER :
1114 if (Exclusive || ByDriver) {
1115 Status = EFI_ACCESS_DENIED;
1116 goto Done;
1117 }
1118 break;
1119 case EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE :
1120 case EFI_OPEN_PROTOCOL_EXCLUSIVE :
1121 if (Exclusive) {
1122 Status = EFI_ACCESS_DENIED;
1123 goto Done;
1124 }
1125 if (ByDriver) {
1126 do {
1127 Disconnect = FALSE;
1128 for ( Link = Prot->OpenList.ForwardLink; (Link != &Prot->OpenList) && (!Disconnect); Link = Link->ForwardLink) {
1129 OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
1130 if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
1131 Disconnect = TRUE;
1132 CoreReleaseProtocolLock ();
1133 Status = CoreDisconnectController (UserHandle, OpenData->AgentHandle, NULL);
1134 CoreAcquireProtocolLock ();
1135 if (EFI_ERROR (Status)) {
1136 Status = EFI_ACCESS_DENIED;
1137 goto Done;
1138 }
1139 }
1140 }
1141 } while (Disconnect);
1142 }
1143 break;
1144 case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER :
1145 case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL :
1146 case EFI_OPEN_PROTOCOL_GET_PROTOCOL :
1147 case EFI_OPEN_PROTOCOL_TEST_PROTOCOL :
1148 break;
1149 }
1150
1151 if (ImageHandle == NULL) {
1152 Status = EFI_SUCCESS;
1153 goto Done;
1154 }
1155 //
1156 // Create new entry
1157 //
1158 OpenData = AllocatePool (sizeof(OPEN_PROTOCOL_DATA));
1159 if (OpenData == NULL) {
1160 Status = EFI_OUT_OF_RESOURCES;
1161 } else {
1162 OpenData->Signature = OPEN_PROTOCOL_DATA_SIGNATURE;
1163 OpenData->AgentHandle = ImageHandle;
1164 OpenData->ControllerHandle = ControllerHandle;
1165 OpenData->Attributes = Attributes;
1166 OpenData->OpenCount = 1;
1167 InsertTailList (&Prot->OpenList, &OpenData->Link);
1168 Prot->OpenListCount++;
1169 Status = EFI_SUCCESS;
1170 }
1171
1172 Done:
1173 //
1174 // Done. Release the database lock are return
1175 //
1176 CoreReleaseProtocolLock ();
1177 return Status;
1178 }
1179
1180
1181
1182 /**
1183 Closes a protocol on a handle that was opened using OpenProtocol().
1184
1185 @param UserHandle The handle for the protocol interface that was
1186 previously opened with OpenProtocol(), and is
1187 now being closed.
1188 @param Protocol The published unique identifier of the protocol.
1189 It is the caller's responsibility to pass in a
1190 valid GUID.
1191 @param AgentHandle The handle of the agent that is closing the
1192 protocol interface.
1193 @param ControllerHandle If the agent that opened a protocol is a driver
1194 that follows the EFI Driver Model, then this
1195 parameter is the controller handle that required
1196 the protocol interface. If the agent does not
1197 follow the EFI Driver Model, then this parameter
1198 is optional and may be NULL.
1199
1200 @retval EFI_SUCCESS The protocol instance was closed.
1201 @retval EFI_INVALID_PARAMETER Handle, AgentHandle or ControllerHandle is not a
1202 valid EFI_HANDLE.
1203 @retval EFI_NOT_FOUND Can not find the specified protocol or
1204 AgentHandle.
1205
1206 **/
1207 EFI_STATUS
1208 EFIAPI
1209 CoreCloseProtocol (
1210 IN EFI_HANDLE UserHandle,
1211 IN EFI_GUID *Protocol,
1212 IN EFI_HANDLE AgentHandle,
1213 IN EFI_HANDLE ControllerHandle
1214 )
1215 {
1216 EFI_STATUS Status;
1217 PROTOCOL_INTERFACE *ProtocolInterface;
1218 LIST_ENTRY *Link;
1219 OPEN_PROTOCOL_DATA *OpenData;
1220
1221 //
1222 // Check for invalid parameters
1223 //
1224 Status = CoreValidateHandle (UserHandle);
1225 if (EFI_ERROR (Status)) {
1226 return Status;
1227 }
1228 Status = CoreValidateHandle (AgentHandle);
1229 if (EFI_ERROR (Status)) {
1230 return Status;
1231 }
1232 if (ControllerHandle != NULL) {
1233 Status = CoreValidateHandle (ControllerHandle);
1234 if (EFI_ERROR (Status)) {
1235 return Status;
1236 }
1237 }
1238 if (Protocol == NULL) {
1239 return EFI_INVALID_PARAMETER;
1240 }
1241
1242 //
1243 // Lock the protocol database
1244 //
1245 CoreAcquireProtocolLock ();
1246
1247 //
1248 // Look at each protocol interface for a match
1249 //
1250 Status = EFI_NOT_FOUND;
1251 ProtocolInterface = CoreGetProtocolInterface (UserHandle, Protocol);
1252 if (ProtocolInterface == NULL) {
1253 goto Done;
1254 }
1255
1256 //
1257 // Walk the Open data base looking for AgentHandle
1258 //
1259 Link = ProtocolInterface->OpenList.ForwardLink;
1260 while (Link != &ProtocolInterface->OpenList) {
1261 OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
1262 Link = Link->ForwardLink;
1263 if ((OpenData->AgentHandle == AgentHandle) && (OpenData->ControllerHandle == ControllerHandle)) {
1264 RemoveEntryList (&OpenData->Link);
1265 ProtocolInterface->OpenListCount--;
1266 CoreFreePool (OpenData);
1267 Status = EFI_SUCCESS;
1268 }
1269 }
1270
1271 Done:
1272 //
1273 // Done. Release the database lock and return.
1274 //
1275 CoreReleaseProtocolLock ();
1276 return Status;
1277 }
1278
1279
1280
1281
1282 /**
1283 Return information about Opened protocols in the system
1284
1285 @param UserHandle The handle to close the protocol interface on
1286 @param Protocol The ID of the protocol
1287 @param EntryBuffer A pointer to a buffer of open protocol information in the
1288 form of EFI_OPEN_PROTOCOL_INFORMATION_ENTRY structures.
1289 @param EntryCount Number of EntryBuffer entries
1290
1291 @retval EFI_SUCCESS The open protocol information was returned in EntryBuffer,
1292 and the number of entries was returned EntryCount.
1293 @retval EFI_NOT_FOUND Handle does not support the protocol specified by Protocol.
1294 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to allocate EntryBuffer.
1295
1296 **/
1297 EFI_STATUS
1298 EFIAPI
1299 CoreOpenProtocolInformation (
1300 IN EFI_HANDLE UserHandle,
1301 IN EFI_GUID *Protocol,
1302 OUT EFI_OPEN_PROTOCOL_INFORMATION_ENTRY **EntryBuffer,
1303 OUT UINTN *EntryCount
1304 )
1305 {
1306 EFI_STATUS Status;
1307 PROTOCOL_INTERFACE *ProtocolInterface;
1308 LIST_ENTRY *Link;
1309 OPEN_PROTOCOL_DATA *OpenData;
1310 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *Buffer;
1311 UINTN Count;
1312 UINTN Size;
1313
1314 *EntryBuffer = NULL;
1315 *EntryCount = 0;
1316
1317 //
1318 // Lock the protocol database
1319 //
1320 CoreAcquireProtocolLock ();
1321
1322 //
1323 // Look at each protocol interface for a match
1324 //
1325 Status = EFI_NOT_FOUND;
1326 ProtocolInterface = CoreGetProtocolInterface (UserHandle, Protocol);
1327 if (ProtocolInterface == NULL) {
1328 goto Done;
1329 }
1330
1331 //
1332 // Count the number of Open Entries
1333 //
1334 for ( Link = ProtocolInterface->OpenList.ForwardLink, Count = 0;
1335 (Link != &ProtocolInterface->OpenList) ;
1336 Link = Link->ForwardLink ) {
1337 Count++;
1338 }
1339
1340 ASSERT (Count == ProtocolInterface->OpenListCount);
1341
1342 if (Count == 0) {
1343 Size = sizeof(EFI_OPEN_PROTOCOL_INFORMATION_ENTRY);
1344 } else {
1345 Size = Count * sizeof(EFI_OPEN_PROTOCOL_INFORMATION_ENTRY);
1346 }
1347
1348 Buffer = AllocatePool (Size);
1349 if (Buffer == NULL) {
1350 Status = EFI_OUT_OF_RESOURCES;
1351 goto Done;
1352 }
1353
1354 Status = EFI_SUCCESS;
1355 for ( Link = ProtocolInterface->OpenList.ForwardLink, Count = 0;
1356 (Link != &ProtocolInterface->OpenList);
1357 Link = Link->ForwardLink, Count++ ) {
1358 OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
1359
1360 Buffer[Count].AgentHandle = OpenData->AgentHandle;
1361 Buffer[Count].ControllerHandle = OpenData->ControllerHandle;
1362 Buffer[Count].Attributes = OpenData->Attributes;
1363 Buffer[Count].OpenCount = OpenData->OpenCount;
1364 }
1365
1366 *EntryBuffer = Buffer;
1367 *EntryCount = Count;
1368
1369 Done:
1370 //
1371 // Done. Release the database lock.
1372 //
1373 CoreReleaseProtocolLock ();
1374 return Status;
1375 }
1376
1377
1378
1379
1380 /**
1381 Retrieves the list of protocol interface GUIDs that are installed on a handle in a buffer allocated
1382 from pool.
1383
1384 @param UserHandle The handle from which to retrieve the list of
1385 protocol interface GUIDs.
1386 @param ProtocolBuffer A pointer to the list of protocol interface GUID
1387 pointers that are installed on Handle.
1388 @param ProtocolBufferCount A pointer to the number of GUID pointers present
1389 in ProtocolBuffer.
1390
1391 @retval EFI_SUCCESS The list of protocol interface GUIDs installed
1392 on Handle was returned in ProtocolBuffer. The
1393 number of protocol interface GUIDs was returned
1394 in ProtocolBufferCount.
1395 @retval EFI_INVALID_PARAMETER Handle is NULL.
1396 @retval EFI_INVALID_PARAMETER Handle is not a valid EFI_HANDLE.
1397 @retval EFI_INVALID_PARAMETER ProtocolBuffer is NULL.
1398 @retval EFI_INVALID_PARAMETER ProtocolBufferCount is NULL.
1399 @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the
1400 results.
1401
1402 **/
1403 EFI_STATUS
1404 EFIAPI
1405 CoreProtocolsPerHandle (
1406 IN EFI_HANDLE UserHandle,
1407 OUT EFI_GUID ***ProtocolBuffer,
1408 OUT UINTN *ProtocolBufferCount
1409 )
1410 {
1411 EFI_STATUS Status;
1412 IHANDLE *Handle;
1413 PROTOCOL_INTERFACE *Prot;
1414 LIST_ENTRY *Link;
1415 UINTN ProtocolCount;
1416 EFI_GUID **Buffer;
1417
1418 Status = CoreValidateHandle (UserHandle);
1419 if (EFI_ERROR (Status)) {
1420 return Status;
1421 }
1422
1423 Handle = (IHANDLE *)UserHandle;
1424
1425 if (ProtocolBuffer == NULL) {
1426 return EFI_INVALID_PARAMETER;
1427 }
1428
1429 if (ProtocolBufferCount == NULL) {
1430 return EFI_INVALID_PARAMETER;
1431 }
1432
1433 *ProtocolBufferCount = 0;
1434
1435 ProtocolCount = 0;
1436
1437 CoreAcquireProtocolLock ();
1438
1439 for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
1440 ProtocolCount++;
1441 }
1442
1443 //
1444 // If there are no protocol interfaces installed on Handle, then Handle is not a valid EFI_HANDLE
1445 //
1446 if (ProtocolCount == 0) {
1447 Status = EFI_INVALID_PARAMETER;
1448 goto Done;
1449 }
1450
1451 Buffer = AllocatePool (sizeof (EFI_GUID *) * ProtocolCount);
1452 if (Buffer == NULL) {
1453 Status = EFI_OUT_OF_RESOURCES;
1454 goto Done;
1455 }
1456
1457 *ProtocolBuffer = Buffer;
1458 *ProtocolBufferCount = ProtocolCount;
1459
1460 for ( Link = Handle->Protocols.ForwardLink, ProtocolCount = 0;
1461 Link != &Handle->Protocols;
1462 Link = Link->ForwardLink, ProtocolCount++) {
1463 Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
1464 Buffer[ProtocolCount] = &(Prot->Protocol->ProtocolID);
1465 }
1466 Status = EFI_SUCCESS;
1467
1468 Done:
1469 CoreReleaseProtocolLock ();
1470 return Status;
1471 }
1472
1473
1474
1475 /**
1476 return handle database key.
1477
1478
1479 @return Handle database key.
1480
1481 **/
1482 UINT64
1483 CoreGetHandleDatabaseKey (
1484 VOID
1485 )
1486 {
1487 return gHandleDatabaseKey;
1488 }
1489
1490
1491
1492 /**
1493 Go connect any handles that were created or modified while a image executed.
1494
1495 @param Key The Key to show that the handle has been
1496 created/modified
1497
1498 **/
1499 VOID
1500 CoreConnectHandlesByKey (
1501 UINT64 Key
1502 )
1503 {
1504 UINTN Count;
1505 LIST_ENTRY *Link;
1506 EFI_HANDLE *HandleBuffer;
1507 IHANDLE *Handle;
1508 UINTN Index;
1509
1510 //
1511 // Lock the protocol database
1512 //
1513 CoreAcquireProtocolLock ();
1514
1515 for (Link = gHandleList.ForwardLink, Count = 0; Link != &gHandleList; Link = Link->ForwardLink) {
1516 Handle = CR (Link, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE);
1517 if (Handle->Key > Key) {
1518 Count++;
1519 }
1520 }
1521
1522 HandleBuffer = AllocatePool (Count * sizeof (EFI_HANDLE));
1523 if (HandleBuffer == NULL) {
1524 CoreReleaseProtocolLock ();
1525 return;
1526 }
1527
1528 for (Link = gHandleList.ForwardLink, Count = 0; Link != &gHandleList; Link = Link->ForwardLink) {
1529 Handle = CR (Link, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE);
1530 if (Handle->Key > Key) {
1531 HandleBuffer[Count++] = Handle;
1532 }
1533 }
1534
1535 //
1536 // Unlock the protocol database
1537 //
1538 CoreReleaseProtocolLock ();
1539
1540 //
1541 // Connect all handles whose Key value is greater than Key
1542 //
1543 for (Index = 0; Index < Count; Index++) {
1544 CoreConnectController (HandleBuffer[Index], NULL, NULL, TRUE);
1545 }
1546
1547 CoreFreePool(HandleBuffer);
1548 }