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