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