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