]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Core/Dxe/Hand/Handle.c
Fix the typo in InstallMultipleProtocolInterfaces comments
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / Hand / Handle.c
1 /** @file
2 UEFI handle & protocol handling.
3
4 Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
5 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 pointer to a handle to install the new
509 protocol interfaces on, or a pointer to NULL
510 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) && 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 VA_END (Args);
581
582 //
583 // If there was an error, remove all the interfaces that were installed without any errors
584 //
585 if (EFI_ERROR (Status)) {
586 //
587 // Reset the va_arg back to the first argument.
588 //
589 VA_START (Args, Handle);
590 for (; Index > 1; Index--) {
591 Protocol = VA_ARG (Args, EFI_GUID *);
592 Interface = VA_ARG (Args, VOID *);
593 CoreUninstallProtocolInterface (*Handle, Protocol, Interface);
594 }
595 VA_END (Args);
596
597 *Handle = OldHandle;
598 }
599
600 //
601 // Done
602 //
603 CoreRestoreTpl (OldTpl);
604 return Status;
605 }
606
607
608 /**
609 Attempts to disconnect all drivers that are using the protocol interface being queried.
610 If failed, reconnect all drivers disconnected.
611 Note: This function doesn't do parameters checking, it's caller's responsibility
612 to pass in valid parameters.
613
614 @param UserHandle The handle on which the protocol is installed
615 @param Prot The protocol to disconnect drivers from
616
617 @retval EFI_SUCCESS Drivers using the protocol interface are all
618 disconnected
619 @retval EFI_ACCESS_DENIED Failed to disconnect one or all of the drivers
620
621 **/
622 EFI_STATUS
623 CoreDisconnectControllersUsingProtocolInterface (
624 IN EFI_HANDLE UserHandle,
625 IN PROTOCOL_INTERFACE *Prot
626 )
627 {
628 EFI_STATUS Status;
629 BOOLEAN ItemFound;
630 LIST_ENTRY *Link;
631 OPEN_PROTOCOL_DATA *OpenData;
632
633 Status = EFI_SUCCESS;
634
635 //
636 // Attempt to disconnect all drivers from this protocol interface
637 //
638 do {
639 ItemFound = FALSE;
640 for ( Link = Prot->OpenList.ForwardLink;
641 (Link != &Prot->OpenList) && !ItemFound;
642 Link = Link->ForwardLink ) {
643 OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
644 if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
645 ItemFound = TRUE;
646 CoreReleaseProtocolLock ();
647 Status = CoreDisconnectController (UserHandle, OpenData->AgentHandle, NULL);
648 CoreAcquireProtocolLock ();
649 if (EFI_ERROR (Status)) {
650 ItemFound = FALSE;
651 break;
652 }
653 }
654 }
655 } while (ItemFound);
656
657 if (!EFI_ERROR (Status)) {
658 //
659 // Attempt to remove BY_HANDLE_PROTOOCL and GET_PROTOCOL and TEST_PROTOCOL Open List items
660 //
661 do {
662 ItemFound = FALSE;
663 for ( Link = Prot->OpenList.ForwardLink;
664 (Link != &Prot->OpenList) && !ItemFound;
665 Link = Link->ForwardLink ) {
666 OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
667 if ((OpenData->Attributes &
668 (EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL | EFI_OPEN_PROTOCOL_GET_PROTOCOL | EFI_OPEN_PROTOCOL_TEST_PROTOCOL)) != 0) {
669 ItemFound = TRUE;
670 RemoveEntryList (&OpenData->Link);
671 Prot->OpenListCount--;
672 CoreFreePool (OpenData);
673 }
674 }
675 } while (ItemFound);
676 }
677
678 //
679 // If there are errors or still has open items in the list, then reconnect all the drivers and return an error
680 //
681 if (EFI_ERROR (Status) || (Prot->OpenListCount > 0)) {
682 CoreReleaseProtocolLock ();
683 CoreConnectController (UserHandle, NULL, NULL, TRUE);
684 CoreAcquireProtocolLock ();
685 Status = EFI_ACCESS_DENIED;
686 }
687
688 return Status;
689 }
690
691
692
693 /**
694 Uninstalls all instances of a protocol:interfacer from a handle.
695 If the last protocol interface is remove from the handle, the
696 handle is freed.
697
698 @param UserHandle The handle to remove the protocol handler from
699 @param Protocol The protocol, of protocol:interface, to remove
700 @param Interface The interface, of protocol:interface, to remove
701
702 @retval EFI_INVALID_PARAMETER Protocol is NULL.
703 @retval EFI_SUCCESS Protocol interface successfully uninstalled.
704
705 **/
706 EFI_STATUS
707 EFIAPI
708 CoreUninstallProtocolInterface (
709 IN EFI_HANDLE UserHandle,
710 IN EFI_GUID *Protocol,
711 IN VOID *Interface
712 )
713 {
714 EFI_STATUS Status;
715 IHANDLE *Handle;
716 PROTOCOL_INTERFACE *Prot;
717
718 //
719 // Check that Protocol is valid
720 //
721 if (Protocol == NULL) {
722 return EFI_INVALID_PARAMETER;
723 }
724
725 //
726 // Check that UserHandle is a valid handle
727 //
728 Status = CoreValidateHandle (UserHandle);
729 if (EFI_ERROR (Status)) {
730 return Status;
731 }
732
733 //
734 // Lock the protocol database
735 //
736 CoreAcquireProtocolLock ();
737
738 //
739 // Check that Protocol exists on UserHandle, and Interface matches the interface in the database
740 //
741 Prot = CoreFindProtocolInterface (UserHandle, Protocol, Interface);
742 if (Prot == NULL) {
743 Status = EFI_NOT_FOUND;
744 goto Done;
745 }
746
747 //
748 // Attempt to disconnect all drivers that are using the protocol interface that is about to be removed
749 //
750 Status = CoreDisconnectControllersUsingProtocolInterface (
751 UserHandle,
752 Prot
753 );
754 if (EFI_ERROR (Status)) {
755 //
756 // One or more drivers refused to release, so return the error
757 //
758 goto Done;
759 }
760
761 //
762 // Remove the protocol interface from the protocol
763 //
764 Status = EFI_NOT_FOUND;
765 Handle = (IHANDLE *)UserHandle;
766 Prot = CoreRemoveInterfaceFromProtocol (Handle, Protocol, Interface);
767
768 if (Prot != NULL) {
769 //
770 // Update the Key to show that the handle has been created/modified
771 //
772 gHandleDatabaseKey++;
773 Handle->Key = gHandleDatabaseKey;
774
775 //
776 // Remove the protocol interface from the handle
777 //
778 RemoveEntryList (&Prot->Link);
779
780 //
781 // Free the memory
782 //
783 Prot->Signature = 0;
784 CoreFreePool (Prot);
785 Status = EFI_SUCCESS;
786 }
787
788 //
789 // If there are no more handlers for the handle, free the handle
790 //
791 if (IsListEmpty (&Handle->Protocols)) {
792 Handle->Signature = 0;
793 RemoveEntryList (&Handle->AllHandles);
794 CoreFreePool (Handle);
795 }
796
797 Done:
798 //
799 // Done, unlock the database and return
800 //
801 CoreReleaseProtocolLock ();
802 return Status;
803 }
804
805
806
807
808 /**
809 Uninstalls a list of protocol interface in the boot services environment.
810 This function calls UnisatllProtocolInterface() in a loop. This is
811 basically a lib function to save space.
812
813 @param Handle The handle to uninstall the protocol
814 @param ... EFI_GUID followed by protocol instance. A NULL
815 terminates the list. The pairs are the
816 arguments to UninstallProtocolInterface(). All
817 the protocols are added to Handle.
818
819 @return Status code
820
821 **/
822 EFI_STATUS
823 EFIAPI
824 CoreUninstallMultipleProtocolInterfaces (
825 IN EFI_HANDLE Handle,
826 ...
827 )
828 {
829 EFI_STATUS Status;
830 VA_LIST Args;
831 EFI_GUID *Protocol;
832 VOID *Interface;
833 UINTN Index;
834
835 VA_START (Args, Handle);
836 for (Index = 0, Status = EFI_SUCCESS; !EFI_ERROR (Status); Index++) {
837 //
838 // If protocol is NULL, then it's the end of the list
839 //
840 Protocol = VA_ARG (Args, EFI_GUID *);
841 if (Protocol == NULL) {
842 break;
843 }
844
845 Interface = VA_ARG (Args, VOID *);
846
847 //
848 // Uninstall it
849 //
850 Status = CoreUninstallProtocolInterface (Handle, Protocol, Interface);
851 }
852 VA_END (Args);
853
854 //
855 // If there was an error, add all the interfaces that were
856 // uninstalled without any errors
857 //
858 if (EFI_ERROR (Status)) {
859 //
860 // Reset the va_arg back to the first argument.
861 //
862 VA_START (Args, Handle);
863 for (; Index > 1; Index--) {
864 Protocol = VA_ARG(Args, EFI_GUID *);
865 Interface = VA_ARG(Args, VOID *);
866 CoreInstallProtocolInterface (&Handle, Protocol, EFI_NATIVE_INTERFACE, Interface);
867 }
868 VA_END (Args);
869 }
870
871 return Status;
872 }
873
874
875 /**
876 Locate a certain GUID protocol interface in a Handle's protocols.
877
878 @param UserHandle The handle to obtain the protocol interface on
879 @param Protocol The GUID of the protocol
880
881 @return The requested protocol interface for the handle
882
883 **/
884 PROTOCOL_INTERFACE *
885 CoreGetProtocolInterface (
886 IN EFI_HANDLE UserHandle,
887 IN EFI_GUID *Protocol
888 )
889 {
890 EFI_STATUS Status;
891 PROTOCOL_ENTRY *ProtEntry;
892 PROTOCOL_INTERFACE *Prot;
893 IHANDLE *Handle;
894 LIST_ENTRY *Link;
895
896 Status = CoreValidateHandle (UserHandle);
897 if (EFI_ERROR (Status)) {
898 return NULL;
899 }
900
901 Handle = (IHANDLE *)UserHandle;
902
903 //
904 // Look at each protocol interface for a match
905 //
906 for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
907 Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
908 ProtEntry = Prot->Protocol;
909 if (CompareGuid (&ProtEntry->ProtocolID, Protocol)) {
910 return Prot;
911 }
912 }
913 return NULL;
914 }
915
916
917
918 /**
919 Queries a handle to determine if it supports a specified protocol.
920
921 @param UserHandle The handle being queried.
922 @param Protocol The published unique identifier of the protocol.
923 @param Interface Supplies the address where a pointer to the
924 corresponding Protocol Interface is returned.
925
926 @retval EFI_SUCCESS The interface information for the specified protocol was returned.
927 @retval EFI_UNSUPPORTED The device does not support the specified protocol.
928 @retval EFI_INVALID_PARAMETER Handle is NULL..
929 @retval EFI_INVALID_PARAMETER Protocol is NULL.
930 @retval EFI_INVALID_PARAMETER Interface is NULL.
931
932 **/
933 EFI_STATUS
934 EFIAPI
935 CoreHandleProtocol (
936 IN EFI_HANDLE UserHandle,
937 IN EFI_GUID *Protocol,
938 OUT VOID **Interface
939 )
940 {
941 return CoreOpenProtocol (
942 UserHandle,
943 Protocol,
944 Interface,
945 gDxeCoreImageHandle,
946 NULL,
947 EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
948 );
949 }
950
951
952
953 /**
954 Locates the installed protocol handler for the handle, and
955 invokes it to obtain the protocol interface. Usage information
956 is registered in the protocol data base.
957
958 @param UserHandle The handle to obtain the protocol interface on
959 @param Protocol The ID of the protocol
960 @param Interface The location to return the protocol interface
961 @param ImageHandle The handle of the Image that is opening the
962 protocol interface specified by Protocol and
963 Interface.
964 @param ControllerHandle The controller handle that is requiring this
965 interface.
966 @param Attributes The open mode of the protocol interface
967 specified by Handle and Protocol.
968
969 @retval EFI_INVALID_PARAMETER Protocol is NULL.
970 @retval EFI_SUCCESS Get the protocol interface.
971
972 **/
973 EFI_STATUS
974 EFIAPI
975 CoreOpenProtocol (
976 IN EFI_HANDLE UserHandle,
977 IN EFI_GUID *Protocol,
978 OUT VOID **Interface OPTIONAL,
979 IN EFI_HANDLE ImageHandle,
980 IN EFI_HANDLE ControllerHandle,
981 IN UINT32 Attributes
982 )
983 {
984 EFI_STATUS Status;
985 PROTOCOL_INTERFACE *Prot;
986 LIST_ENTRY *Link;
987 OPEN_PROTOCOL_DATA *OpenData;
988 BOOLEAN ByDriver;
989 BOOLEAN Exclusive;
990 BOOLEAN Disconnect;
991 BOOLEAN ExactMatch;
992
993 //
994 // Check for invalid Protocol
995 //
996 if (Protocol == NULL) {
997 return EFI_INVALID_PARAMETER;
998 }
999
1000 //
1001 // Check for invalid Interface
1002 //
1003 if (Attributes != EFI_OPEN_PROTOCOL_TEST_PROTOCOL) {
1004 if (Interface == NULL) {
1005 return EFI_INVALID_PARAMETER;
1006 } else {
1007 *Interface = NULL;
1008 }
1009 }
1010
1011 //
1012 // Check for invalid UserHandle
1013 //
1014 Status = CoreValidateHandle (UserHandle);
1015 if (EFI_ERROR (Status)) {
1016 return Status;
1017 }
1018
1019 //
1020 // Check for invalid Attributes
1021 //
1022 switch (Attributes) {
1023 case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER :
1024 Status = CoreValidateHandle (ImageHandle);
1025 if (EFI_ERROR (Status)) {
1026 return Status;
1027 }
1028 Status = CoreValidateHandle (ControllerHandle);
1029 if (EFI_ERROR (Status)) {
1030 return Status;
1031 }
1032 if (UserHandle == ControllerHandle) {
1033 return EFI_INVALID_PARAMETER;
1034 }
1035 break;
1036 case EFI_OPEN_PROTOCOL_BY_DRIVER :
1037 case EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE :
1038 Status = CoreValidateHandle (ImageHandle);
1039 if (EFI_ERROR (Status)) {
1040 return Status;
1041 }
1042 Status = CoreValidateHandle (ControllerHandle);
1043 if (EFI_ERROR (Status)) {
1044 return Status;
1045 }
1046 break;
1047 case EFI_OPEN_PROTOCOL_EXCLUSIVE :
1048 Status = CoreValidateHandle (ImageHandle);
1049 if (EFI_ERROR (Status)) {
1050 return Status;
1051 }
1052 break;
1053 case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL :
1054 case EFI_OPEN_PROTOCOL_GET_PROTOCOL :
1055 case EFI_OPEN_PROTOCOL_TEST_PROTOCOL :
1056 break;
1057 default:
1058 return EFI_INVALID_PARAMETER;
1059 }
1060
1061 //
1062 // Lock the protocol database
1063 //
1064 CoreAcquireProtocolLock ();
1065
1066 //
1067 // Look at each protocol interface for a match
1068 //
1069 Prot = CoreGetProtocolInterface (UserHandle, Protocol);
1070 if (Prot == NULL) {
1071 Status = EFI_UNSUPPORTED;
1072 goto Done;
1073 }
1074
1075 //
1076 // This is the protocol interface entry for this protocol
1077 //
1078 if (Attributes != EFI_OPEN_PROTOCOL_TEST_PROTOCOL) {
1079 *Interface = Prot->Interface;
1080 }
1081 Status = EFI_SUCCESS;
1082
1083 ByDriver = FALSE;
1084 Exclusive = FALSE;
1085 for ( Link = Prot->OpenList.ForwardLink; Link != &Prot->OpenList; Link = Link->ForwardLink) {
1086 OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
1087 ExactMatch = (BOOLEAN)((OpenData->AgentHandle == ImageHandle) &&
1088 (OpenData->Attributes == Attributes) &&
1089 (OpenData->ControllerHandle == ControllerHandle));
1090 if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
1091 ByDriver = TRUE;
1092 if (ExactMatch) {
1093 Status = EFI_ALREADY_STARTED;
1094 goto Done;
1095 }
1096 }
1097 if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_EXCLUSIVE) != 0) {
1098 Exclusive = TRUE;
1099 } else if (ExactMatch) {
1100 OpenData->OpenCount++;
1101 Status = EFI_SUCCESS;
1102 goto Done;
1103 }
1104 }
1105
1106 //
1107 // ByDriver TRUE -> A driver is managing (UserHandle, Protocol)
1108 // ByDriver FALSE -> There are no drivers managing (UserHandle, Protocol)
1109 // Exclusive TRUE -> Something has exclusive access to (UserHandle, Protocol)
1110 // Exclusive FALSE -> Nothing has exclusive access to (UserHandle, Protocol)
1111 //
1112
1113 switch (Attributes) {
1114 case EFI_OPEN_PROTOCOL_BY_DRIVER :
1115 if (Exclusive || ByDriver) {
1116 Status = EFI_ACCESS_DENIED;
1117 goto Done;
1118 }
1119 break;
1120 case EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE :
1121 case EFI_OPEN_PROTOCOL_EXCLUSIVE :
1122 if (Exclusive) {
1123 Status = EFI_ACCESS_DENIED;
1124 goto Done;
1125 }
1126 if (ByDriver) {
1127 do {
1128 Disconnect = FALSE;
1129 for ( Link = Prot->OpenList.ForwardLink; (Link != &Prot->OpenList) && (!Disconnect); Link = Link->ForwardLink) {
1130 OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
1131 if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
1132 Disconnect = TRUE;
1133 CoreReleaseProtocolLock ();
1134 Status = CoreDisconnectController (UserHandle, OpenData->AgentHandle, NULL);
1135 CoreAcquireProtocolLock ();
1136 if (EFI_ERROR (Status)) {
1137 Status = EFI_ACCESS_DENIED;
1138 goto Done;
1139 }
1140 }
1141 }
1142 } while (Disconnect);
1143 }
1144 break;
1145 case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER :
1146 case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL :
1147 case EFI_OPEN_PROTOCOL_GET_PROTOCOL :
1148 case EFI_OPEN_PROTOCOL_TEST_PROTOCOL :
1149 break;
1150 }
1151
1152 if (ImageHandle == NULL) {
1153 Status = EFI_SUCCESS;
1154 goto Done;
1155 }
1156 //
1157 // Create new entry
1158 //
1159 OpenData = AllocatePool (sizeof(OPEN_PROTOCOL_DATA));
1160 if (OpenData == NULL) {
1161 Status = EFI_OUT_OF_RESOURCES;
1162 } else {
1163 OpenData->Signature = OPEN_PROTOCOL_DATA_SIGNATURE;
1164 OpenData->AgentHandle = ImageHandle;
1165 OpenData->ControllerHandle = ControllerHandle;
1166 OpenData->Attributes = Attributes;
1167 OpenData->OpenCount = 1;
1168 InsertTailList (&Prot->OpenList, &OpenData->Link);
1169 Prot->OpenListCount++;
1170 Status = EFI_SUCCESS;
1171 }
1172
1173 Done:
1174 //
1175 // Done. Release the database lock are return
1176 //
1177 CoreReleaseProtocolLock ();
1178 return Status;
1179 }
1180
1181
1182
1183 /**
1184 Closes a protocol on a handle that was opened using OpenProtocol().
1185
1186 @param UserHandle The handle for the protocol interface that was
1187 previously opened with OpenProtocol(), and is
1188 now being closed.
1189 @param Protocol The published unique identifier of the protocol.
1190 It is the caller's responsibility to pass in a
1191 valid GUID.
1192 @param AgentHandle The handle of the agent that is closing the
1193 protocol interface.
1194 @param ControllerHandle If the agent that opened a protocol is a driver
1195 that follows the EFI Driver Model, then this
1196 parameter is the controller handle that required
1197 the protocol interface. If the agent does not
1198 follow the EFI Driver Model, then this parameter
1199 is optional and may be NULL.
1200
1201 @retval EFI_SUCCESS The protocol instance was closed.
1202 @retval EFI_INVALID_PARAMETER Handle, AgentHandle or ControllerHandle is not a
1203 valid EFI_HANDLE.
1204 @retval EFI_NOT_FOUND Can not find the specified protocol or
1205 AgentHandle.
1206
1207 **/
1208 EFI_STATUS
1209 EFIAPI
1210 CoreCloseProtocol (
1211 IN EFI_HANDLE UserHandle,
1212 IN EFI_GUID *Protocol,
1213 IN EFI_HANDLE AgentHandle,
1214 IN EFI_HANDLE ControllerHandle
1215 )
1216 {
1217 EFI_STATUS Status;
1218 PROTOCOL_INTERFACE *ProtocolInterface;
1219 LIST_ENTRY *Link;
1220 OPEN_PROTOCOL_DATA *OpenData;
1221
1222 //
1223 // Check for invalid parameters
1224 //
1225 Status = CoreValidateHandle (UserHandle);
1226 if (EFI_ERROR (Status)) {
1227 return Status;
1228 }
1229 Status = CoreValidateHandle (AgentHandle);
1230 if (EFI_ERROR (Status)) {
1231 return Status;
1232 }
1233 if (ControllerHandle != NULL) {
1234 Status = CoreValidateHandle (ControllerHandle);
1235 if (EFI_ERROR (Status)) {
1236 return Status;
1237 }
1238 }
1239 if (Protocol == NULL) {
1240 return EFI_INVALID_PARAMETER;
1241 }
1242
1243 //
1244 // Lock the protocol database
1245 //
1246 CoreAcquireProtocolLock ();
1247
1248 //
1249 // Look at each protocol interface for a match
1250 //
1251 Status = EFI_NOT_FOUND;
1252 ProtocolInterface = CoreGetProtocolInterface (UserHandle, Protocol);
1253 if (ProtocolInterface == NULL) {
1254 goto Done;
1255 }
1256
1257 //
1258 // Walk the Open data base looking for AgentHandle
1259 //
1260 Link = ProtocolInterface->OpenList.ForwardLink;
1261 while (Link != &ProtocolInterface->OpenList) {
1262 OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
1263 Link = Link->ForwardLink;
1264 if ((OpenData->AgentHandle == AgentHandle) && (OpenData->ControllerHandle == ControllerHandle)) {
1265 RemoveEntryList (&OpenData->Link);
1266 ProtocolInterface->OpenListCount--;
1267 CoreFreePool (OpenData);
1268 Status = EFI_SUCCESS;
1269 }
1270 }
1271
1272 Done:
1273 //
1274 // Done. Release the database lock and return.
1275 //
1276 CoreReleaseProtocolLock ();
1277 return Status;
1278 }
1279
1280
1281
1282
1283 /**
1284 Return information about Opened protocols in the system
1285
1286 @param UserHandle The handle to close the protocol interface on
1287 @param Protocol The ID of the protocol
1288 @param EntryBuffer A pointer to a buffer of open protocol information in the
1289 form of EFI_OPEN_PROTOCOL_INFORMATION_ENTRY structures.
1290 @param EntryCount Number of EntryBuffer entries
1291
1292 @retval EFI_SUCCESS The open protocol information was returned in EntryBuffer,
1293 and the number of entries was returned EntryCount.
1294 @retval EFI_NOT_FOUND Handle does not support the protocol specified by Protocol.
1295 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to allocate EntryBuffer.
1296
1297 **/
1298 EFI_STATUS
1299 EFIAPI
1300 CoreOpenProtocolInformation (
1301 IN EFI_HANDLE UserHandle,
1302 IN EFI_GUID *Protocol,
1303 OUT EFI_OPEN_PROTOCOL_INFORMATION_ENTRY **EntryBuffer,
1304 OUT UINTN *EntryCount
1305 )
1306 {
1307 EFI_STATUS Status;
1308 PROTOCOL_INTERFACE *ProtocolInterface;
1309 LIST_ENTRY *Link;
1310 OPEN_PROTOCOL_DATA *OpenData;
1311 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *Buffer;
1312 UINTN Count;
1313 UINTN Size;
1314
1315 *EntryBuffer = NULL;
1316 *EntryCount = 0;
1317
1318 //
1319 // Lock the protocol database
1320 //
1321 CoreAcquireProtocolLock ();
1322
1323 //
1324 // Look at each protocol interface for a match
1325 //
1326 Status = EFI_NOT_FOUND;
1327 ProtocolInterface = CoreGetProtocolInterface (UserHandle, Protocol);
1328 if (ProtocolInterface == NULL) {
1329 goto Done;
1330 }
1331
1332 //
1333 // Count the number of Open Entries
1334 //
1335 for ( Link = ProtocolInterface->OpenList.ForwardLink, Count = 0;
1336 (Link != &ProtocolInterface->OpenList) ;
1337 Link = Link->ForwardLink ) {
1338 Count++;
1339 }
1340
1341 ASSERT (Count == ProtocolInterface->OpenListCount);
1342
1343 if (Count == 0) {
1344 Size = sizeof(EFI_OPEN_PROTOCOL_INFORMATION_ENTRY);
1345 } else {
1346 Size = Count * sizeof(EFI_OPEN_PROTOCOL_INFORMATION_ENTRY);
1347 }
1348
1349 Buffer = AllocatePool (Size);
1350 if (Buffer == NULL) {
1351 Status = EFI_OUT_OF_RESOURCES;
1352 goto Done;
1353 }
1354
1355 Status = EFI_SUCCESS;
1356 for ( Link = ProtocolInterface->OpenList.ForwardLink, Count = 0;
1357 (Link != &ProtocolInterface->OpenList);
1358 Link = Link->ForwardLink, Count++ ) {
1359 OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
1360
1361 Buffer[Count].AgentHandle = OpenData->AgentHandle;
1362 Buffer[Count].ControllerHandle = OpenData->ControllerHandle;
1363 Buffer[Count].Attributes = OpenData->Attributes;
1364 Buffer[Count].OpenCount = OpenData->OpenCount;
1365 }
1366
1367 *EntryBuffer = Buffer;
1368 *EntryCount = Count;
1369
1370 Done:
1371 //
1372 // Done. Release the database lock.
1373 //
1374 CoreReleaseProtocolLock ();
1375 return Status;
1376 }
1377
1378
1379
1380
1381 /**
1382 Retrieves the list of protocol interface GUIDs that are installed on a handle in a buffer allocated
1383 from pool.
1384
1385 @param UserHandle The handle from which to retrieve the list of
1386 protocol interface GUIDs.
1387 @param ProtocolBuffer A pointer to the list of protocol interface GUID
1388 pointers that are installed on Handle.
1389 @param ProtocolBufferCount A pointer to the number of GUID pointers present
1390 in ProtocolBuffer.
1391
1392 @retval EFI_SUCCESS The list of protocol interface GUIDs installed
1393 on Handle was returned in ProtocolBuffer. The
1394 number of protocol interface GUIDs was returned
1395 in ProtocolBufferCount.
1396 @retval EFI_INVALID_PARAMETER Handle is NULL.
1397 @retval EFI_INVALID_PARAMETER Handle is not a valid EFI_HANDLE.
1398 @retval EFI_INVALID_PARAMETER ProtocolBuffer is NULL.
1399 @retval EFI_INVALID_PARAMETER ProtocolBufferCount is NULL.
1400 @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the
1401 results.
1402
1403 **/
1404 EFI_STATUS
1405 EFIAPI
1406 CoreProtocolsPerHandle (
1407 IN EFI_HANDLE UserHandle,
1408 OUT EFI_GUID ***ProtocolBuffer,
1409 OUT UINTN *ProtocolBufferCount
1410 )
1411 {
1412 EFI_STATUS Status;
1413 IHANDLE *Handle;
1414 PROTOCOL_INTERFACE *Prot;
1415 LIST_ENTRY *Link;
1416 UINTN ProtocolCount;
1417 EFI_GUID **Buffer;
1418
1419 Status = CoreValidateHandle (UserHandle);
1420 if (EFI_ERROR (Status)) {
1421 return Status;
1422 }
1423
1424 Handle = (IHANDLE *)UserHandle;
1425
1426 if (ProtocolBuffer == NULL) {
1427 return EFI_INVALID_PARAMETER;
1428 }
1429
1430 if (ProtocolBufferCount == NULL) {
1431 return EFI_INVALID_PARAMETER;
1432 }
1433
1434 *ProtocolBufferCount = 0;
1435
1436 ProtocolCount = 0;
1437
1438 CoreAcquireProtocolLock ();
1439
1440 for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
1441 ProtocolCount++;
1442 }
1443
1444 //
1445 // If there are no protocol interfaces installed on Handle, then Handle is not a valid EFI_HANDLE
1446 //
1447 if (ProtocolCount == 0) {
1448 Status = EFI_INVALID_PARAMETER;
1449 goto Done;
1450 }
1451
1452 Buffer = AllocatePool (sizeof (EFI_GUID *) * ProtocolCount);
1453 if (Buffer == NULL) {
1454 Status = EFI_OUT_OF_RESOURCES;
1455 goto Done;
1456 }
1457
1458 *ProtocolBuffer = Buffer;
1459 *ProtocolBufferCount = ProtocolCount;
1460
1461 for ( Link = Handle->Protocols.ForwardLink, ProtocolCount = 0;
1462 Link != &Handle->Protocols;
1463 Link = Link->ForwardLink, ProtocolCount++) {
1464 Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
1465 Buffer[ProtocolCount] = &(Prot->Protocol->ProtocolID);
1466 }
1467 Status = EFI_SUCCESS;
1468
1469 Done:
1470 CoreReleaseProtocolLock ();
1471 return Status;
1472 }
1473
1474
1475
1476 /**
1477 return handle database key.
1478
1479
1480 @return Handle database key.
1481
1482 **/
1483 UINT64
1484 CoreGetHandleDatabaseKey (
1485 VOID
1486 )
1487 {
1488 return gHandleDatabaseKey;
1489 }
1490
1491
1492
1493 /**
1494 Go connect any handles that were created or modified while a image executed.
1495
1496 @param Key The Key to show that the handle has been
1497 created/modified
1498
1499 **/
1500 VOID
1501 CoreConnectHandlesByKey (
1502 UINT64 Key
1503 )
1504 {
1505 UINTN Count;
1506 LIST_ENTRY *Link;
1507 EFI_HANDLE *HandleBuffer;
1508 IHANDLE *Handle;
1509 UINTN Index;
1510
1511 //
1512 // Lock the protocol database
1513 //
1514 CoreAcquireProtocolLock ();
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 Count++;
1520 }
1521 }
1522
1523 HandleBuffer = AllocatePool (Count * sizeof (EFI_HANDLE));
1524 if (HandleBuffer == NULL) {
1525 CoreReleaseProtocolLock ();
1526 return;
1527 }
1528
1529 for (Link = gHandleList.ForwardLink, Count = 0; Link != &gHandleList; Link = Link->ForwardLink) {
1530 Handle = CR (Link, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE);
1531 if (Handle->Key > Key) {
1532 HandleBuffer[Count++] = Handle;
1533 }
1534 }
1535
1536 //
1537 // Unlock the protocol database
1538 //
1539 CoreReleaseProtocolLock ();
1540
1541 //
1542 // Connect all handles whose Key value is greater than Key
1543 //
1544 for (Index = 0; Index < Count; Index++) {
1545 CoreConnectController (HandleBuffer[Index], NULL, NULL, TRUE);
1546 }
1547
1548 CoreFreePool(HandleBuffer);
1549 }