1 /** @file
2 UEFI handle & protocol handling.
3
4 Copyright (c) 2006 - 2013, 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
CoreAcquireProtocolLock(VOID)37 CoreAcquireProtocolLock (
38 VOID
39 )
40 {
41 CoreAcquireLock (&gProtocolDatabaseLock);
42 }
43
44
45
46 /**
47 Release lock on gProtocolDatabaseLock.
48
49 **/
50 VOID
CoreReleaseProtocolLock(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
CoreValidateHandle(IN EFI_HANDLE UserHandle)70 CoreValidateHandle (
71 IN EFI_HANDLE UserHandle
72 )
73 {
74 IHANDLE *Handle;
75
76 Handle = (IHANDLE *)UserHandle;
77 if (Handle == NULL) {
78 return EFI_INVALID_PARAMETER;
79 }
80 if (Handle->Signature != EFI_HANDLE_SIGNATURE) {
81 return EFI_INVALID_PARAMETER;
82 }
83 return EFI_SUCCESS;
84 }
85
86
87
88 /**
89 Finds the protocol entry for the requested protocol.
90 The gProtocolDatabaseLock must be owned
91
92 @param Protocol The ID of the protocol
93 @param Create Create a new entry if not found
94
95 @return Protocol entry
96
97 **/
98 PROTOCOL_ENTRY *
CoreFindProtocolEntry(IN EFI_GUID * Protocol,IN BOOLEAN Create)99 CoreFindProtocolEntry (
100 IN EFI_GUID *Protocol,
101 IN BOOLEAN Create
102 )
103 {
104 LIST_ENTRY *Link;
105 PROTOCOL_ENTRY *Item;
106 PROTOCOL_ENTRY *ProtEntry;
107
108 ASSERT_LOCKED(&gProtocolDatabaseLock);
109
110 //
111 // Search the database for the matching GUID
112 //
113
114 ProtEntry = NULL;
115 for (Link = mProtocolDatabase.ForwardLink;
116 Link != &mProtocolDatabase;
117 Link = Link->ForwardLink) {
118
119 Item = CR(Link, PROTOCOL_ENTRY, AllEntries, PROTOCOL_ENTRY_SIGNATURE);
120 if (CompareGuid (&Item->ProtocolID, Protocol)) {
121
122 //
123 // This is the protocol entry
124 //
125
126 ProtEntry = Item;
127 break;
128 }
129 }
130
131 //
132 // If the protocol entry was not found and Create is TRUE, then
133 // allocate a new entry
134 //
135 if ((ProtEntry == NULL) && Create) {
136 ProtEntry = AllocatePool (sizeof(PROTOCOL_ENTRY));
137
138 if (ProtEntry != NULL) {
139 //
140 // Initialize new protocol entry structure
141 //
142 ProtEntry->Signature = PROTOCOL_ENTRY_SIGNATURE;
143 CopyGuid ((VOID *)&ProtEntry->ProtocolID, Protocol);
144 InitializeListHead (&ProtEntry->Protocols);
145 InitializeListHead (&ProtEntry->Notify);
146
147 //
148 // Add it to protocol database
149 //
150 InsertTailList (&mProtocolDatabase, &ProtEntry->AllEntries);
151 }
152 }
153
154 return ProtEntry;
155 }
156
157
158
159 /**
160 Finds the protocol instance for the requested handle and protocol.
161 Note: This function doesn't do parameters checking, it's caller's responsibility
162 to pass in valid parameters.
163
164 @param Handle The handle to search the protocol on
165 @param Protocol GUID of the protocol
166 @param Interface The interface for the protocol being searched
167
168 @return Protocol instance (NULL: Not found)
169
170 **/
171 PROTOCOL_INTERFACE *
CoreFindProtocolInterface(IN IHANDLE * Handle,IN EFI_GUID * Protocol,IN VOID * Interface)172 CoreFindProtocolInterface (
173 IN IHANDLE *Handle,
174 IN EFI_GUID *Protocol,
175 IN VOID *Interface
176 )
177 {
178 PROTOCOL_INTERFACE *Prot;
179 PROTOCOL_ENTRY *ProtEntry;
180 LIST_ENTRY *Link;
181
182 ASSERT_LOCKED(&gProtocolDatabaseLock);
183 Prot = NULL;
184
185 //
186 // Lookup the protocol entry for this protocol ID
187 //
188
189 ProtEntry = CoreFindProtocolEntry (Protocol, FALSE);
190 if (ProtEntry != NULL) {
191
192 //
193 // Look at each protocol interface for any matches
194 //
195 for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link=Link->ForwardLink) {
196
197 //
198 // If this protocol interface matches, remove it
199 //
200 Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
201 if (Prot->Interface == Interface && Prot->Protocol == ProtEntry) {
202 break;
203 }
204
205 Prot = NULL;
206 }
207 }
208
209 return Prot;
210 }
211
212
213 /**
214 Removes an event from a register protocol notify list on a protocol.
215
216 @param Event The event to search for in the protocol
217 database.
218
219 @return EFI_SUCCESS if the event was found and removed.
220 @return EFI_NOT_FOUND if the event was not found in the protocl database.
221
222 **/
223 EFI_STATUS
CoreUnregisterProtocolNotifyEvent(IN EFI_EVENT Event)224 CoreUnregisterProtocolNotifyEvent (
225 IN EFI_EVENT Event
226 )
227 {
228 LIST_ENTRY *Link;
229 PROTOCOL_ENTRY *ProtEntry;
230 LIST_ENTRY *NotifyLink;
231 PROTOCOL_NOTIFY *ProtNotify;
232
233 CoreAcquireProtocolLock ();
234
235 for ( Link = mProtocolDatabase.ForwardLink;
236 Link != &mProtocolDatabase;
237 Link = Link->ForwardLink) {
238
239 ProtEntry = CR(Link, PROTOCOL_ENTRY, AllEntries, PROTOCOL_ENTRY_SIGNATURE);
240
241 for ( NotifyLink = ProtEntry->Notify.ForwardLink;
242 NotifyLink != &ProtEntry->Notify;
243 NotifyLink = NotifyLink->ForwardLink) {
244
245 ProtNotify = CR(NotifyLink, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE);
246
247 if (ProtNotify->Event == Event) {
248 RemoveEntryList(&ProtNotify->Link);
249 CoreFreePool(ProtNotify);
250 CoreReleaseProtocolLock ();
251 return EFI_SUCCESS;
252 }
253 }
254 }
255
256 CoreReleaseProtocolLock ();
257 return EFI_NOT_FOUND;
258 }
259
260
261
262 /**
263 Removes all the events in the protocol database that match Event.
264
265 @param Event The event to search for in the protocol
266 database.
267
268 @return EFI_SUCCESS when done searching the entire database.
269
270 **/
271 EFI_STATUS
CoreUnregisterProtocolNotify(IN EFI_EVENT Event)272 CoreUnregisterProtocolNotify (
273 IN EFI_EVENT Event
274 )
275 {
276 EFI_STATUS Status;
277
278 do {
279 Status = CoreUnregisterProtocolNotifyEvent (Event);
280 } while (!EFI_ERROR (Status));
281
282 return EFI_SUCCESS;
283 }
284
285
286
287
288 /**
289 Wrapper function to CoreInstallProtocolInterfaceNotify. This is the public API which
290 Calls the private one which contains a BOOLEAN parameter for notifications
291
292 @param UserHandle The handle to install the protocol handler on,
293 or NULL if a new handle is to be allocated
294 @param Protocol The protocol to add to the handle
295 @param InterfaceType Indicates whether Interface is supplied in
296 native form.
297 @param Interface The interface for the protocol being added
298
299 @return Status code
300
301 **/
302 EFI_STATUS
303 EFIAPI
CoreInstallProtocolInterface(IN OUT EFI_HANDLE * UserHandle,IN EFI_GUID * Protocol,IN EFI_INTERFACE_TYPE InterfaceType,IN VOID * Interface)304 CoreInstallProtocolInterface (
305 IN OUT EFI_HANDLE *UserHandle,
306 IN EFI_GUID *Protocol,
307 IN EFI_INTERFACE_TYPE InterfaceType,
308 IN VOID *Interface
309 )
310 {
311 return CoreInstallProtocolInterfaceNotify (
312 UserHandle,
313 Protocol,
314 InterfaceType,
315 Interface,
316 TRUE
317 );
318 }
319
320
321 /**
322 Installs a protocol interface into the boot services environment.
323
324 @param UserHandle The handle to install the protocol handler on,
325 or NULL if a new handle is to be allocated
326 @param Protocol The protocol to add to the handle
327 @param InterfaceType Indicates whether Interface is supplied in
328 native form.
329 @param Interface The interface for the protocol being added
330 @param Notify indicates whether notify the notification list
331 for this protocol
332
333 @retval EFI_INVALID_PARAMETER Invalid parameter
334 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
335 @retval EFI_SUCCESS Protocol interface successfully installed
336
337 **/
338 EFI_STATUS
CoreInstallProtocolInterfaceNotify(IN OUT EFI_HANDLE * UserHandle,IN EFI_GUID * Protocol,IN EFI_INTERFACE_TYPE InterfaceType,IN VOID * Interface,IN BOOLEAN Notify)339 CoreInstallProtocolInterfaceNotify (
340 IN OUT EFI_HANDLE *UserHandle,
341 IN EFI_GUID *Protocol,
342 IN EFI_INTERFACE_TYPE InterfaceType,
343 IN VOID *Interface,
344 IN BOOLEAN Notify
345 )
346 {
347 PROTOCOL_INTERFACE *Prot;
348 PROTOCOL_ENTRY *ProtEntry;
349 IHANDLE *Handle;
350 EFI_STATUS Status;
351 VOID *ExistingInterface;
352
353 //
354 // returns EFI_INVALID_PARAMETER if InterfaceType is invalid.
355 // Also added check for invalid UserHandle and Protocol pointers.
356 //
357 if (UserHandle == NULL || Protocol == NULL) {
358 return EFI_INVALID_PARAMETER;
359 }
360
361 if (InterfaceType != EFI_NATIVE_INTERFACE) {
362 return EFI_INVALID_PARAMETER;
363 }
364
365 //
366 // Print debug message
367 //
368 DEBUG((DEBUG_INFO, "InstallProtocolInterface: %g %p\n", Protocol, Interface));
369
370 Status = EFI_OUT_OF_RESOURCES;
371 Prot = NULL;
372 Handle = NULL;
373
374 if (*UserHandle != NULL) {
375 Status = CoreHandleProtocol (*UserHandle, Protocol, (VOID **)&ExistingInterface);
376 if (!EFI_ERROR (Status)) {
377 return EFI_INVALID_PARAMETER;
378 }
379 }
380
381 //
382 // Lock the protocol database
383 //
384 CoreAcquireProtocolLock ();
385
386 //
387 // Lookup the Protocol Entry for the requested protocol
388 //
389 ProtEntry = CoreFindProtocolEntry (Protocol, TRUE);
390 if (ProtEntry == NULL) {
391 goto Done;
392 }
393
394 //
395 // Allocate a new protocol interface structure
396 //
397 Prot = AllocateZeroPool (sizeof(PROTOCOL_INTERFACE));
398 if (Prot == NULL) {
399 Status = EFI_OUT_OF_RESOURCES;
400 goto Done;
401 }
402
403 //
404 // If caller didn't supply a handle, allocate a new one
405 //
406 Handle = (IHANDLE *)*UserHandle;
407 if (Handle == NULL) {
408 Handle = AllocateZeroPool (sizeof(IHANDLE));
409 if (Handle == NULL) {
410 Status = EFI_OUT_OF_RESOURCES;
411 goto Done;
412 }
413
414 //
415 // Initialize new handler structure
416 //
417 Handle->Signature = EFI_HANDLE_SIGNATURE;
418 InitializeListHead (&Handle->Protocols);
419
420 //
421 // Initialize the Key to show that the handle has been created/modified
422 //
423 gHandleDatabaseKey++;
424 Handle->Key = gHandleDatabaseKey;
425
426 //
427 // Add this handle to the list global list of all handles
428 // in the system
429 //
430 InsertTailList (&gHandleList, &Handle->AllHandles);
431 }
432
433 Status = CoreValidateHandle (Handle);
434 if (EFI_ERROR (Status)) {
435 goto Done;
436 }
437
438 //
439 // Each interface that is added must be unique
440 //
441 ASSERT (CoreFindProtocolInterface (Handle, Protocol, Interface) == NULL);
442
443 //
444 // Initialize the protocol interface structure
445 //
446 Prot->Signature = PROTOCOL_INTERFACE_SIGNATURE;
447 Prot->Handle = Handle;
448 Prot->Protocol = ProtEntry;
449 Prot->Interface = Interface;
450
451 //
452 // Initalize OpenProtocol Data base
453 //
454 InitializeListHead (&Prot->OpenList);
455 Prot->OpenListCount = 0;
456
457 //
458 // Add this protocol interface to the head of the supported
459 // protocol list for this handle
460 //
461 InsertHeadList (&Handle->Protocols, &Prot->Link);
462
463 //
464 // Add this protocol interface to the tail of the
465 // protocol entry
466 //
467 InsertTailList (&ProtEntry->Protocols, &Prot->ByProtocol);
468
469 //
470 // Notify the notification list for this protocol
471 //
472 if (Notify) {
473 CoreNotifyProtocolEntry (ProtEntry);
474 }
475 Status = EFI_SUCCESS;
476
477 Done:
478 //
479 // Done, unlock the database and return
480 //
481 CoreReleaseProtocolLock ();
482 if (!EFI_ERROR (Status)) {
483 //
484 // Return the new handle back to the caller
485 //
486 *UserHandle = Handle;
487 } else {
488 //
489 // There was an error, clean up
490 //
491 if (Prot != NULL) {
492 CoreFreePool (Prot);
493 }
494 }
495
496 return Status;
497 }
498
499
500
501
502 /**
503 Installs a list of protocol interface into the boot services environment.
504 This function calls InstallProtocolInterface() in a loop. If any error
505 occures all the protocols added by this function are removed. This is
506 basically a lib function to save space.
507
508 @param Handle The pointer to a handle to install the new
509 protocol interfaces on, or a pointer to NULL
510 if a new handle is to be allocated.
511 @param ... EFI_GUID followed by protocol instance. A NULL
512 terminates the list. The pairs are the
513 arguments to InstallProtocolInterface(). All the
514 protocols are added to Handle.
515
516 @retval EFI_SUCCESS All the protocol interface was installed.
517 @retval EFI_OUT_OF_RESOURCES There was not enough memory in pool to install all the protocols.
518 @retval EFI_ALREADY_STARTED A Device Path Protocol instance was passed in that is already present in
519 the handle database.
520 @retval EFI_INVALID_PARAMETER Handle is NULL.
521 @retval EFI_INVALID_PARAMETER Protocol is already installed on the handle specified by Handle.
522
523 **/
524 EFI_STATUS
525 EFIAPI
CoreInstallMultipleProtocolInterfaces(IN OUT EFI_HANDLE * Handle,...)526 CoreInstallMultipleProtocolInterfaces (
527 IN OUT EFI_HANDLE *Handle,
528 ...
529 )
530 {
531 VA_LIST Args;
532 EFI_STATUS Status;
533 EFI_GUID *Protocol;
534 VOID *Interface;
535 EFI_TPL OldTpl;
536 UINTN Index;
537 EFI_HANDLE OldHandle;
538 EFI_HANDLE DeviceHandle;
539 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
540
541 if (Handle == NULL) {
542 return EFI_INVALID_PARAMETER;
543 }
544
545 //
546 // Syncronize with notifcations.
547 //
548 OldTpl = CoreRaiseTpl (TPL_NOTIFY);
549 OldHandle = *Handle;
550
551 //
552 // Check for duplicate device path and install the protocol interfaces
553 //
554 VA_START (Args, Handle);
555 for (Index = 0, Status = EFI_SUCCESS; !EFI_ERROR (Status); Index++) {
556 //
557 // If protocol is NULL, then it's the end of the list
558 //
559 Protocol = VA_ARG (Args, EFI_GUID *);
560 if (Protocol == NULL) {
561 break;
562 }
563
564 Interface = VA_ARG (Args, VOID *);
565
566 //
567 // Make sure you are installing on top a device path that has already been added.
568 //
569 if (CompareGuid (Protocol, &gEfiDevicePathProtocolGuid)) {
570 DeviceHandle = NULL;
571 DevicePath = Interface;
572 Status = CoreLocateDevicePath (&gEfiDevicePathProtocolGuid, &DevicePath, &DeviceHandle);
573 if (!EFI_ERROR (Status) && (DeviceHandle != NULL) && IsDevicePathEnd(DevicePath)) {
574 Status = EFI_ALREADY_STARTED;
575 continue;
576 }
577 }
578
579 //
580 // Install it
581 //
582 Status = CoreInstallProtocolInterface (Handle, Protocol, EFI_NATIVE_INTERFACE, Interface);
583 }
584 VA_END (Args);
585
586 //
587 // If there was an error, remove all the interfaces that were installed without any errors
588 //
589 if (EFI_ERROR (Status)) {
590 //
591 // Reset the va_arg back to the first argument.
592 //
593 VA_START (Args, Handle);
594 for (; Index > 1; Index--) {
595 Protocol = VA_ARG (Args, EFI_GUID *);
596 Interface = VA_ARG (Args, VOID *);
597 CoreUninstallProtocolInterface (*Handle, Protocol, Interface);
598 }
599 VA_END (Args);
600
601 *Handle = OldHandle;
602 }
603
604 //
605 // Done
606 //
607 CoreRestoreTpl (OldTpl);
608 return Status;
609 }
610
611
612 /**
613 Attempts to disconnect all drivers that are using the protocol interface being queried.
614 If failed, reconnect all drivers disconnected.
615 Note: This function doesn't do parameters checking, it's caller's responsibility
616 to pass in valid parameters.
617
618 @param UserHandle The handle on which the protocol is installed
619 @param Prot The protocol to disconnect drivers from
620
621 @retval EFI_SUCCESS Drivers using the protocol interface are all
622 disconnected
623 @retval EFI_ACCESS_DENIED Failed to disconnect one or all of the drivers
624
625 **/
626 EFI_STATUS
CoreDisconnectControllersUsingProtocolInterface(IN EFI_HANDLE UserHandle,IN PROTOCOL_INTERFACE * Prot)627 CoreDisconnectControllersUsingProtocolInterface (
628 IN EFI_HANDLE UserHandle,
629 IN PROTOCOL_INTERFACE *Prot
630 )
631 {
632 EFI_STATUS Status;
633 BOOLEAN ItemFound;
634 LIST_ENTRY *Link;
635 OPEN_PROTOCOL_DATA *OpenData;
636
637 Status = EFI_SUCCESS;
638
639 //
640 // Attempt to disconnect all drivers from this protocol interface
641 //
642 do {
643 ItemFound = FALSE;
644 for ( Link = Prot->OpenList.ForwardLink;
645 (Link != &Prot->OpenList) && !ItemFound;
646 Link = Link->ForwardLink ) {
647 OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
648 if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
649 ItemFound = TRUE;
650 CoreReleaseProtocolLock ();
651 Status = CoreDisconnectController (UserHandle, OpenData->AgentHandle, NULL);
652 CoreAcquireProtocolLock ();
653 if (EFI_ERROR (Status)) {
654 ItemFound = FALSE;
655 break;
656 }
657 }
658 }
659 } while (ItemFound);
660
661 if (!EFI_ERROR (Status)) {
662 //
663 // Attempt to remove BY_HANDLE_PROTOOCL and GET_PROTOCOL and TEST_PROTOCOL Open List items
664 //
665 do {
666 ItemFound = FALSE;
667 for ( Link = Prot->OpenList.ForwardLink;
668 (Link != &Prot->OpenList) && !ItemFound;
669 Link = Link->ForwardLink ) {
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 ItemFound = TRUE;
674 RemoveEntryList (&OpenData->Link);
675 Prot->OpenListCount--;
676 CoreFreePool (OpenData);
677 }
678 }
679 } while (ItemFound);
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
CoreUninstallProtocolInterface(IN EFI_HANDLE UserHandle,IN EFI_GUID * Protocol,IN VOID * Interface)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
CoreUninstallMultipleProtocolInterfaces(IN EFI_HANDLE Handle,...)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 *
CoreGetProtocolInterface(IN EFI_HANDLE UserHandle,IN EFI_GUID * Protocol)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
CoreHandleProtocol(IN EFI_HANDLE UserHandle,IN EFI_GUID * Protocol,OUT VOID ** Interface)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
CoreOpenProtocol(IN EFI_HANDLE UserHandle,IN EFI_GUID * Protocol,OUT VOID ** Interface OPTIONAL,IN EFI_HANDLE ImageHandle,IN EFI_HANDLE ControllerHandle,IN UINT32 Attributes)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) {
1008 if (Interface == NULL) {
1009 return EFI_INVALID_PARAMETER;
1010 } else {
1011 *Interface = NULL;
1012 }
1013 }
1014
1015 //
1016 // Check for invalid UserHandle
1017 //
1018 Status = CoreValidateHandle (UserHandle);
1019 if (EFI_ERROR (Status)) {
1020 return Status;
1021 }
1022
1023 //
1024 // Check for invalid Attributes
1025 //
1026 switch (Attributes) {
1027 case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER :
1028 Status = CoreValidateHandle (ImageHandle);
1029 if (EFI_ERROR (Status)) {
1030 return Status;
1031 }
1032 Status = CoreValidateHandle (ControllerHandle);
1033 if (EFI_ERROR (Status)) {
1034 return Status;
1035 }
1036 if (UserHandle == ControllerHandle) {
1037 return EFI_INVALID_PARAMETER;
1038 }
1039 break;
1040 case EFI_OPEN_PROTOCOL_BY_DRIVER :
1041 case EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE :
1042 Status = CoreValidateHandle (ImageHandle);
1043 if (EFI_ERROR (Status)) {
1044 return Status;
1045 }
1046 Status = CoreValidateHandle (ControllerHandle);
1047 if (EFI_ERROR (Status)) {
1048 return Status;
1049 }
1050 break;
1051 case EFI_OPEN_PROTOCOL_EXCLUSIVE :
1052 Status = CoreValidateHandle (ImageHandle);
1053 if (EFI_ERROR (Status)) {
1054 return Status;
1055 }
1056 break;
1057 case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL :
1058 case EFI_OPEN_PROTOCOL_GET_PROTOCOL :
1059 case EFI_OPEN_PROTOCOL_TEST_PROTOCOL :
1060 break;
1061 default:
1062 return EFI_INVALID_PARAMETER;
1063 }
1064
1065 //
1066 // Lock the protocol database
1067 //
1068 CoreAcquireProtocolLock ();
1069
1070 //
1071 // Look at each protocol interface for a match
1072 //
1073 Prot = CoreGetProtocolInterface (UserHandle, Protocol);
1074 if (Prot == NULL) {
1075 Status = EFI_UNSUPPORTED;
1076 goto Done;
1077 }
1078
1079 //
1080 // This is the protocol interface entry for this protocol
1081 //
1082 if (Attributes != EFI_OPEN_PROTOCOL_TEST_PROTOCOL) {
1083 *Interface = Prot->Interface;
1084 }
1085 Status = EFI_SUCCESS;
1086
1087 ByDriver = FALSE;
1088 Exclusive = FALSE;
1089 for ( Link = Prot->OpenList.ForwardLink; Link != &Prot->OpenList; Link = Link->ForwardLink) {
1090 OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
1091 ExactMatch = (BOOLEAN)((OpenData->AgentHandle == ImageHandle) &&
1092 (OpenData->Attributes == Attributes) &&
1093 (OpenData->ControllerHandle == ControllerHandle));
1094 if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
1095 ByDriver = TRUE;
1096 if (ExactMatch) {
1097 Status = EFI_ALREADY_STARTED;
1098 goto Done;
1099 }
1100 }
1101 if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_EXCLUSIVE) != 0) {
1102 Exclusive = TRUE;
1103 } else if (ExactMatch) {
1104 OpenData->OpenCount++;
1105 Status = EFI_SUCCESS;
1106 goto Done;
1107 }
1108 }
1109
1110 //
1111 // ByDriver TRUE -> A driver is managing (UserHandle, Protocol)
1112 // ByDriver FALSE -> There are no drivers managing (UserHandle, Protocol)
1113 // Exclusive TRUE -> Something has exclusive access to (UserHandle, Protocol)
1114 // Exclusive FALSE -> Nothing has exclusive access to (UserHandle, Protocol)
1115 //
1116
1117 switch (Attributes) {
1118 case EFI_OPEN_PROTOCOL_BY_DRIVER :
1119 if (Exclusive || ByDriver) {
1120 Status = EFI_ACCESS_DENIED;
1121 goto Done;
1122 }
1123 break;
1124 case EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE :
1125 case EFI_OPEN_PROTOCOL_EXCLUSIVE :
1126 if (Exclusive) {
1127 Status = EFI_ACCESS_DENIED;
1128 goto Done;
1129 }
1130 if (ByDriver) {
1131 do {
1132 Disconnect = FALSE;
1133 for ( Link = Prot->OpenList.ForwardLink; (Link != &Prot->OpenList) && (!Disconnect); Link = Link->ForwardLink) {
1134 OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
1135 if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
1136 Disconnect = TRUE;
1137 CoreReleaseProtocolLock ();
1138 Status = CoreDisconnectController (UserHandle, OpenData->AgentHandle, NULL);
1139 CoreAcquireProtocolLock ();
1140 if (EFI_ERROR (Status)) {
1141 Status = EFI_ACCESS_DENIED;
1142 goto Done;
1143 }
1144 }
1145 }
1146 } while (Disconnect);
1147 }
1148 break;
1149 case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER :
1150 case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL :
1151 case EFI_OPEN_PROTOCOL_GET_PROTOCOL :
1152 case EFI_OPEN_PROTOCOL_TEST_PROTOCOL :
1153 break;
1154 }
1155
1156 if (ImageHandle == NULL) {
1157 Status = EFI_SUCCESS;
1158 goto Done;
1159 }
1160 //
1161 // Create new entry
1162 //
1163 OpenData = AllocatePool (sizeof(OPEN_PROTOCOL_DATA));
1164 if (OpenData == NULL) {
1165 Status = EFI_OUT_OF_RESOURCES;
1166 } else {
1167 OpenData->Signature = OPEN_PROTOCOL_DATA_SIGNATURE;
1168 OpenData->AgentHandle = ImageHandle;
1169 OpenData->ControllerHandle = ControllerHandle;
1170 OpenData->Attributes = Attributes;
1171 OpenData->OpenCount = 1;
1172 InsertTailList (&Prot->OpenList, &OpenData->Link);
1173 Prot->OpenListCount++;
1174 Status = EFI_SUCCESS;
1175 }
1176
1177 Done:
1178 //
1179 // Done. Release the database lock are return
1180 //
1181 CoreReleaseProtocolLock ();
1182 return Status;
1183 }
1184
1185
1186
1187 /**
1188 Closes a protocol on a handle that was opened using OpenProtocol().
1189
1190 @param UserHandle The handle for the protocol interface that was
1191 previously opened with OpenProtocol(), and is
1192 now being closed.
1193 @param Protocol The published unique identifier of the protocol.
1194 It is the caller's responsibility to pass in a
1195 valid GUID.
1196 @param AgentHandle The handle of the agent that is closing the
1197 protocol interface.
1198 @param ControllerHandle If the agent that opened a protocol is a driver
1199 that follows the EFI Driver Model, then this
1200 parameter is the controller handle that required
1201 the protocol interface. If the agent does not
1202 follow the EFI Driver Model, then this parameter
1203 is optional and may be NULL.
1204
1205 @retval EFI_SUCCESS The protocol instance was closed.
1206 @retval EFI_INVALID_PARAMETER Handle, AgentHandle or ControllerHandle is not a
1207 valid EFI_HANDLE.
1208 @retval EFI_NOT_FOUND Can not find the specified protocol or
1209 AgentHandle.
1210
1211 **/
1212 EFI_STATUS
1213 EFIAPI
CoreCloseProtocol(IN EFI_HANDLE UserHandle,IN EFI_GUID * Protocol,IN EFI_HANDLE AgentHandle,IN EFI_HANDLE ControllerHandle)1214 CoreCloseProtocol (
1215 IN EFI_HANDLE UserHandle,
1216 IN EFI_GUID *Protocol,
1217 IN EFI_HANDLE AgentHandle,
1218 IN EFI_HANDLE ControllerHandle
1219 )
1220 {
1221 EFI_STATUS Status;
1222 PROTOCOL_INTERFACE *ProtocolInterface;
1223 LIST_ENTRY *Link;
1224 OPEN_PROTOCOL_DATA *OpenData;
1225
1226 //
1227 // Check for invalid parameters
1228 //
1229 Status = CoreValidateHandle (UserHandle);
1230 if (EFI_ERROR (Status)) {
1231 return Status;
1232 }
1233 Status = CoreValidateHandle (AgentHandle);
1234 if (EFI_ERROR (Status)) {
1235 return Status;
1236 }
1237 if (ControllerHandle != NULL) {
1238 Status = CoreValidateHandle (ControllerHandle);
1239 if (EFI_ERROR (Status)) {
1240 return Status;
1241 }
1242 }
1243 if (Protocol == NULL) {
1244 return EFI_INVALID_PARAMETER;
1245 }
1246
1247 //
1248 // Lock the protocol database
1249 //
1250 CoreAcquireProtocolLock ();
1251
1252 //
1253 // Look at each protocol interface for a match
1254 //
1255 Status = EFI_NOT_FOUND;
1256 ProtocolInterface = CoreGetProtocolInterface (UserHandle, Protocol);
1257 if (ProtocolInterface == NULL) {
1258 goto Done;
1259 }
1260
1261 //
1262 // Walk the Open data base looking for AgentHandle
1263 //
1264 Link = ProtocolInterface->OpenList.ForwardLink;
1265 while (Link != &ProtocolInterface->OpenList) {
1266 OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
1267 Link = Link->ForwardLink;
1268 if ((OpenData->AgentHandle == AgentHandle) && (OpenData->ControllerHandle == ControllerHandle)) {
1269 RemoveEntryList (&OpenData->Link);
1270 ProtocolInterface->OpenListCount--;
1271 CoreFreePool (OpenData);
1272 Status = EFI_SUCCESS;
1273 }
1274 }
1275
1276 Done:
1277 //
1278 // Done. Release the database lock and return.
1279 //
1280 CoreReleaseProtocolLock ();
1281 return Status;
1282 }
1283
1284
1285
1286
1287 /**
1288 Return information about Opened protocols in the system
1289
1290 @param UserHandle The handle to close the protocol interface on
1291 @param Protocol The ID of the protocol
1292 @param EntryBuffer A pointer to a buffer of open protocol information in the
1293 form of EFI_OPEN_PROTOCOL_INFORMATION_ENTRY structures.
1294 @param EntryCount Number of EntryBuffer entries
1295
1296 @retval EFI_SUCCESS The open protocol information was returned in EntryBuffer,
1297 and the number of entries was returned EntryCount.
1298 @retval EFI_NOT_FOUND Handle does not support the protocol specified by Protocol.
1299 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to allocate EntryBuffer.
1300
1301 **/
1302 EFI_STATUS
1303 EFIAPI
CoreOpenProtocolInformation(IN EFI_HANDLE UserHandle,IN EFI_GUID * Protocol,OUT EFI_OPEN_PROTOCOL_INFORMATION_ENTRY ** EntryBuffer,OUT UINTN * EntryCount)1304 CoreOpenProtocolInformation (
1305 IN EFI_HANDLE UserHandle,
1306 IN EFI_GUID *Protocol,
1307 OUT EFI_OPEN_PROTOCOL_INFORMATION_ENTRY **EntryBuffer,
1308 OUT UINTN *EntryCount
1309 )
1310 {
1311 EFI_STATUS Status;
1312 PROTOCOL_INTERFACE *ProtocolInterface;
1313 LIST_ENTRY *Link;
1314 OPEN_PROTOCOL_DATA *OpenData;
1315 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *Buffer;
1316 UINTN Count;
1317 UINTN Size;
1318
1319 *EntryBuffer = NULL;
1320 *EntryCount = 0;
1321
1322 //
1323 // Lock the protocol database
1324 //
1325 CoreAcquireProtocolLock ();
1326
1327 //
1328 // Look at each protocol interface for a match
1329 //
1330 Status = EFI_NOT_FOUND;
1331 ProtocolInterface = CoreGetProtocolInterface (UserHandle, Protocol);
1332 if (ProtocolInterface == NULL) {
1333 goto Done;
1334 }
1335
1336 //
1337 // Count the number of Open Entries
1338 //
1339 for ( Link = ProtocolInterface->OpenList.ForwardLink, Count = 0;
1340 (Link != &ProtocolInterface->OpenList) ;
1341 Link = Link->ForwardLink ) {
1342 Count++;
1343 }
1344
1345 ASSERT (Count == ProtocolInterface->OpenListCount);
1346
1347 if (Count == 0) {
1348 Size = sizeof(EFI_OPEN_PROTOCOL_INFORMATION_ENTRY);
1349 } else {
1350 Size = Count * sizeof(EFI_OPEN_PROTOCOL_INFORMATION_ENTRY);
1351 }
1352
1353 Buffer = AllocatePool (Size);
1354 if (Buffer == NULL) {
1355 Status = EFI_OUT_OF_RESOURCES;
1356 goto Done;
1357 }
1358
1359 Status = EFI_SUCCESS;
1360 for ( Link = ProtocolInterface->OpenList.ForwardLink, Count = 0;
1361 (Link != &ProtocolInterface->OpenList);
1362 Link = Link->ForwardLink, Count++ ) {
1363 OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
1364
1365 Buffer[Count].AgentHandle = OpenData->AgentHandle;
1366 Buffer[Count].ControllerHandle = OpenData->ControllerHandle;
1367 Buffer[Count].Attributes = OpenData->Attributes;
1368 Buffer[Count].OpenCount = OpenData->OpenCount;
1369 }
1370
1371 *EntryBuffer = Buffer;
1372 *EntryCount = Count;
1373
1374 Done:
1375 //
1376 // Done. Release the database lock.
1377 //
1378 CoreReleaseProtocolLock ();
1379 return Status;
1380 }
1381
1382
1383
1384
1385 /**
1386 Retrieves the list of protocol interface GUIDs that are installed on a handle in a buffer allocated
1387 from pool.
1388
1389 @param UserHandle The handle from which to retrieve the list of
1390 protocol interface GUIDs.
1391 @param ProtocolBuffer A pointer to the list of protocol interface GUID
1392 pointers that are installed on Handle.
1393 @param ProtocolBufferCount A pointer to the number of GUID pointers present
1394 in ProtocolBuffer.
1395
1396 @retval EFI_SUCCESS The list of protocol interface GUIDs installed
1397 on Handle was returned in ProtocolBuffer. The
1398 number of protocol interface GUIDs was returned
1399 in ProtocolBufferCount.
1400 @retval EFI_INVALID_PARAMETER Handle is NULL.
1401 @retval EFI_INVALID_PARAMETER Handle is not a valid EFI_HANDLE.
1402 @retval EFI_INVALID_PARAMETER ProtocolBuffer is NULL.
1403 @retval EFI_INVALID_PARAMETER ProtocolBufferCount is NULL.
1404 @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the
1405 results.
1406
1407 **/
1408 EFI_STATUS
1409 EFIAPI
CoreProtocolsPerHandle(IN EFI_HANDLE UserHandle,OUT EFI_GUID *** ProtocolBuffer,OUT UINTN * ProtocolBufferCount)1410 CoreProtocolsPerHandle (
1411 IN EFI_HANDLE UserHandle,
1412 OUT EFI_GUID ***ProtocolBuffer,
1413 OUT UINTN *ProtocolBufferCount
1414 )
1415 {
1416 EFI_STATUS Status;
1417 IHANDLE *Handle;
1418 PROTOCOL_INTERFACE *Prot;
1419 LIST_ENTRY *Link;
1420 UINTN ProtocolCount;
1421 EFI_GUID **Buffer;
1422
1423 Status = CoreValidateHandle (UserHandle);
1424 if (EFI_ERROR (Status)) {
1425 return Status;
1426 }
1427
1428 Handle = (IHANDLE *)UserHandle;
1429
1430 if (ProtocolBuffer == NULL) {
1431 return EFI_INVALID_PARAMETER;
1432 }
1433
1434 if (ProtocolBufferCount == NULL) {
1435 return EFI_INVALID_PARAMETER;
1436 }
1437
1438 *ProtocolBufferCount = 0;
1439
1440 ProtocolCount = 0;
1441
1442 CoreAcquireProtocolLock ();
1443
1444 for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
1445 ProtocolCount++;
1446 }
1447
1448 //
1449 // If there are no protocol interfaces installed on Handle, then Handle is not a valid EFI_HANDLE
1450 //
1451 if (ProtocolCount == 0) {
1452 Status = EFI_INVALID_PARAMETER;
1453 goto Done;
1454 }
1455
1456 Buffer = AllocatePool (sizeof (EFI_GUID *) * ProtocolCount);
1457 if (Buffer == NULL) {
1458 Status = EFI_OUT_OF_RESOURCES;
1459 goto Done;
1460 }
1461
1462 *ProtocolBuffer = Buffer;
1463 *ProtocolBufferCount = ProtocolCount;
1464
1465 for ( Link = Handle->Protocols.ForwardLink, ProtocolCount = 0;
1466 Link != &Handle->Protocols;
1467 Link = Link->ForwardLink, ProtocolCount++) {
1468 Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
1469 Buffer[ProtocolCount] = &(Prot->Protocol->ProtocolID);
1470 }
1471 Status = EFI_SUCCESS;
1472
1473 Done:
1474 CoreReleaseProtocolLock ();
1475 return Status;
1476 }
1477
1478
1479
1480 /**
1481 return handle database key.
1482
1483
1484 @return Handle database key.
1485
1486 **/
1487 UINT64
CoreGetHandleDatabaseKey(VOID)1488 CoreGetHandleDatabaseKey (
1489 VOID
1490 )
1491 {
1492 return gHandleDatabaseKey;
1493 }
1494
1495
1496
1497 /**
1498 Go connect any handles that were created or modified while a image executed.
1499
1500 @param Key The Key to show that the handle has been
1501 created/modified
1502
1503 **/
1504 VOID
CoreConnectHandlesByKey(UINT64 Key)1505 CoreConnectHandlesByKey (
1506 UINT64 Key
1507 )
1508 {
1509 UINTN Count;
1510 LIST_ENTRY *Link;
1511 EFI_HANDLE *HandleBuffer;
1512 IHANDLE *Handle;
1513 UINTN Index;
1514
1515 //
1516 // Lock the protocol database
1517 //
1518 CoreAcquireProtocolLock ();
1519
1520 for (Link = gHandleList.ForwardLink, Count = 0; Link != &gHandleList; Link = Link->ForwardLink) {
1521 Handle = CR (Link, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE);
1522 if (Handle->Key > Key) {
1523 Count++;
1524 }
1525 }
1526
1527 HandleBuffer = AllocatePool (Count * sizeof (EFI_HANDLE));
1528 if (HandleBuffer == NULL) {
1529 CoreReleaseProtocolLock ();
1530 return;
1531 }
1532
1533 for (Link = gHandleList.ForwardLink, Count = 0; Link != &gHandleList; Link = Link->ForwardLink) {
1534 Handle = CR (Link, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE);
1535 if (Handle->Key > Key) {
1536 HandleBuffer[Count++] = Handle;
1537 }
1538 }
1539
1540 //
1541 // Unlock the protocol database
1542 //
1543 CoreReleaseProtocolLock ();
1544
1545 //
1546 // Connect all handles whose Key value is greater than Key
1547 //
1548 for (Index = 0; Index < Count; Index++) {
1549 CoreConnectController (HandleBuffer[Index], NULL, NULL, TRUE);
1550 }
1551
1552 CoreFreePool(HandleBuffer);
1553 }
1554