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
CoreAcquireProtocolLock(VOID)31 CoreAcquireProtocolLock (
32 VOID
33 )
34 {
35 CoreAcquireLock (&gProtocolDatabaseLock);
36 }
37
38
39
40 /**
41 Release lock on gProtocolDatabaseLock.
42
43 **/
44 VOID
CoreReleaseProtocolLock(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
CoreValidateHandle(IN EFI_HANDLE UserHandle)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 *
CoreFindProtocolEntry(IN EFI_GUID * Protocol,IN BOOLEAN Create)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 *
CoreFindProtocolInterface(IN IHANDLE * Handle,IN EFI_GUID * Protocol,IN VOID * 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
CoreUnregisterProtocolNotifyEvent(IN EFI_EVENT Event)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
CoreUnregisterProtocolNotify(IN EFI_EVENT Event)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
CoreInstallProtocolInterface(IN OUT EFI_HANDLE * UserHandle,IN EFI_GUID * Protocol,IN EFI_INTERFACE_TYPE InterfaceType,IN VOID * Interface)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
CoreInstallProtocolInterfaceNotify(IN OUT EFI_HANDLE * UserHandle,IN EFI_GUID * Protocol,IN EFI_INTERFACE_TYPE InterfaceType,IN VOID * Interface,IN BOOLEAN Notify)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
CoreInstallMultipleProtocolInterfaces(IN OUT EFI_HANDLE * Handle,...)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
CoreDisconnectControllersUsingProtocolInterface(IN EFI_HANDLE UserHandle,IN PROTOCOL_INTERFACE * Prot)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
CoreUninstallProtocolInterface(IN EFI_HANDLE UserHandle,IN EFI_GUID * Protocol,IN VOID * Interface)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 Uninstalls a list of protocol interface in the boot services environment.
807 This function calls UninstallProtocolInterface() in a loop. This is
808 basically a lib function to save space.
809
810 If any errors are generated while the protocol interfaces are being
811 uninstalled, then the protocol interfaces uninstalled prior to the error will
812 be reinstalled and EFI_INVALID_PARAMETER will be returned.
813
814 @param Handle The handle to uninstall the protocol interfaces
815 from.
816 @param ... EFI_GUID followed by protocol instance. A NULL
817 terminates the list. The pairs are the
818 arguments to UninstallProtocolInterface(). All
819 the protocols are added to Handle.
820
821 @retval EFI_SUCCESS if all protocol interfaces where uninstalled.
822 @retval EFI_INVALID_PARAMETER if any protocol interface could not be
823 uninstalled and an attempt was made to
824 reinstall previously uninstalled protocol
825 interfaces.
826 **/
827 EFI_STATUS
828 EFIAPI
CoreUninstallMultipleProtocolInterfaces(IN EFI_HANDLE Handle,...)829 CoreUninstallMultipleProtocolInterfaces (
830 IN EFI_HANDLE Handle,
831 ...
832 )
833 {
834 EFI_STATUS Status;
835 VA_LIST Args;
836 EFI_GUID *Protocol;
837 VOID *Interface;
838 UINTN Index;
839
840 VA_START (Args, Handle);
841 for (Index = 0, Status = EFI_SUCCESS; !EFI_ERROR (Status); Index++) {
842 //
843 // If protocol is NULL, then it's the end of the list
844 //
845 Protocol = VA_ARG (Args, EFI_GUID *);
846 if (Protocol == NULL) {
847 break;
848 }
849
850 Interface = VA_ARG (Args, VOID *);
851
852 //
853 // Uninstall it
854 //
855 Status = CoreUninstallProtocolInterface (Handle, Protocol, Interface);
856 }
857 VA_END (Args);
858
859 //
860 // If there was an error, add all the interfaces that were
861 // uninstalled without any errors
862 //
863 if (EFI_ERROR (Status)) {
864 //
865 // Reset the va_arg back to the first argument.
866 //
867 VA_START (Args, Handle);
868 for (; Index > 1; Index--) {
869 Protocol = VA_ARG(Args, EFI_GUID *);
870 Interface = VA_ARG(Args, VOID *);
871 CoreInstallProtocolInterface (&Handle, Protocol, EFI_NATIVE_INTERFACE, Interface);
872 }
873 VA_END (Args);
874 Status = EFI_INVALID_PARAMETER;
875 }
876
877 return Status;
878 }
879
880
881 /**
882 Locate a certain GUID protocol interface in a Handle's protocols.
883
884 @param UserHandle The handle to obtain the protocol interface on
885 @param Protocol The GUID of the protocol
886
887 @return The requested protocol interface for the handle
888
889 **/
890 PROTOCOL_INTERFACE *
CoreGetProtocolInterface(IN EFI_HANDLE UserHandle,IN EFI_GUID * Protocol)891 CoreGetProtocolInterface (
892 IN EFI_HANDLE UserHandle,
893 IN EFI_GUID *Protocol
894 )
895 {
896 EFI_STATUS Status;
897 PROTOCOL_ENTRY *ProtEntry;
898 PROTOCOL_INTERFACE *Prot;
899 IHANDLE *Handle;
900 LIST_ENTRY *Link;
901
902 Status = CoreValidateHandle (UserHandle);
903 if (EFI_ERROR (Status)) {
904 return NULL;
905 }
906
907 Handle = (IHANDLE *)UserHandle;
908
909 //
910 // Look at each protocol interface for a match
911 //
912 for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
913 Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
914 ProtEntry = Prot->Protocol;
915 if (CompareGuid (&ProtEntry->ProtocolID, Protocol)) {
916 return Prot;
917 }
918 }
919 return NULL;
920 }
921
922
923
924 /**
925 Queries a handle to determine if it supports a specified protocol.
926
927 @param UserHandle The handle being queried.
928 @param Protocol The published unique identifier of the protocol.
929 @param Interface Supplies the address where a pointer to the
930 corresponding Protocol Interface is returned.
931
932 @retval EFI_SUCCESS The interface information for the specified protocol was returned.
933 @retval EFI_UNSUPPORTED The device does not support the specified protocol.
934 @retval EFI_INVALID_PARAMETER Handle is NULL..
935 @retval EFI_INVALID_PARAMETER Protocol is NULL.
936 @retval EFI_INVALID_PARAMETER Interface is NULL.
937
938 **/
939 EFI_STATUS
940 EFIAPI
CoreHandleProtocol(IN EFI_HANDLE UserHandle,IN EFI_GUID * Protocol,OUT VOID ** Interface)941 CoreHandleProtocol (
942 IN EFI_HANDLE UserHandle,
943 IN EFI_GUID *Protocol,
944 OUT VOID **Interface
945 )
946 {
947 return CoreOpenProtocol (
948 UserHandle,
949 Protocol,
950 Interface,
951 gDxeCoreImageHandle,
952 NULL,
953 EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
954 );
955 }
956
957
958
959 /**
960 Locates the installed protocol handler for the handle, and
961 invokes it to obtain the protocol interface. Usage information
962 is registered in the protocol data base.
963
964 @param UserHandle The handle to obtain the protocol interface on
965 @param Protocol The ID of the protocol
966 @param Interface The location to return the protocol interface
967 @param ImageHandle The handle of the Image that is opening the
968 protocol interface specified by Protocol and
969 Interface.
970 @param ControllerHandle The controller handle that is requiring this
971 interface.
972 @param Attributes The open mode of the protocol interface
973 specified by Handle and Protocol.
974
975 @retval EFI_INVALID_PARAMETER Protocol is NULL.
976 @retval EFI_SUCCESS Get the protocol interface.
977
978 **/
979 EFI_STATUS
980 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)981 CoreOpenProtocol (
982 IN EFI_HANDLE UserHandle,
983 IN EFI_GUID *Protocol,
984 OUT VOID **Interface OPTIONAL,
985 IN EFI_HANDLE ImageHandle,
986 IN EFI_HANDLE ControllerHandle,
987 IN UINT32 Attributes
988 )
989 {
990 EFI_STATUS Status;
991 PROTOCOL_INTERFACE *Prot;
992 LIST_ENTRY *Link;
993 OPEN_PROTOCOL_DATA *OpenData;
994 BOOLEAN ByDriver;
995 BOOLEAN Exclusive;
996 BOOLEAN Disconnect;
997 BOOLEAN ExactMatch;
998
999 //
1000 // Check for invalid Protocol
1001 //
1002 if (Protocol == NULL) {
1003 return EFI_INVALID_PARAMETER;
1004 }
1005
1006 //
1007 // Check for invalid Interface
1008 //
1009 if ((Attributes != EFI_OPEN_PROTOCOL_TEST_PROTOCOL) && (Interface == NULL)) {
1010 return EFI_INVALID_PARAMETER;
1011 }
1012
1013 //
1014 // Check for invalid UserHandle
1015 //
1016 Status = CoreValidateHandle (UserHandle);
1017 if (EFI_ERROR (Status)) {
1018 return Status;
1019 }
1020
1021 //
1022 // Check for invalid Attributes
1023 //
1024 switch (Attributes) {
1025 case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER :
1026 Status = CoreValidateHandle (ImageHandle);
1027 if (EFI_ERROR (Status)) {
1028 return Status;
1029 }
1030 Status = CoreValidateHandle (ControllerHandle);
1031 if (EFI_ERROR (Status)) {
1032 return Status;
1033 }
1034 if (UserHandle == ControllerHandle) {
1035 return EFI_INVALID_PARAMETER;
1036 }
1037 break;
1038 case EFI_OPEN_PROTOCOL_BY_DRIVER :
1039 case EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE :
1040 Status = CoreValidateHandle (ImageHandle);
1041 if (EFI_ERROR (Status)) {
1042 return Status;
1043 }
1044 Status = CoreValidateHandle (ControllerHandle);
1045 if (EFI_ERROR (Status)) {
1046 return Status;
1047 }
1048 break;
1049 case EFI_OPEN_PROTOCOL_EXCLUSIVE :
1050 Status = CoreValidateHandle (ImageHandle);
1051 if (EFI_ERROR (Status)) {
1052 return Status;
1053 }
1054 break;
1055 case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL :
1056 case EFI_OPEN_PROTOCOL_GET_PROTOCOL :
1057 case EFI_OPEN_PROTOCOL_TEST_PROTOCOL :
1058 break;
1059 default:
1060 return EFI_INVALID_PARAMETER;
1061 }
1062
1063 //
1064 // Lock the protocol database
1065 //
1066 CoreAcquireProtocolLock ();
1067
1068 //
1069 // Look at each protocol interface for a match
1070 //
1071 Prot = CoreGetProtocolInterface (UserHandle, Protocol);
1072 if (Prot == NULL) {
1073 Status = EFI_UNSUPPORTED;
1074 goto Done;
1075 }
1076
1077 Status = EFI_SUCCESS;
1078
1079 ByDriver = FALSE;
1080 Exclusive = FALSE;
1081 for ( Link = Prot->OpenList.ForwardLink; Link != &Prot->OpenList; Link = Link->ForwardLink) {
1082 OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
1083 ExactMatch = (BOOLEAN)((OpenData->AgentHandle == ImageHandle) &&
1084 (OpenData->Attributes == Attributes) &&
1085 (OpenData->ControllerHandle == ControllerHandle));
1086 if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
1087 ByDriver = TRUE;
1088 if (ExactMatch) {
1089 Status = EFI_ALREADY_STARTED;
1090 goto Done;
1091 }
1092 }
1093 if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_EXCLUSIVE) != 0) {
1094 Exclusive = TRUE;
1095 } else if (ExactMatch) {
1096 OpenData->OpenCount++;
1097 Status = EFI_SUCCESS;
1098 goto Done;
1099 }
1100 }
1101
1102 //
1103 // ByDriver TRUE -> A driver is managing (UserHandle, Protocol)
1104 // ByDriver FALSE -> There are no drivers managing (UserHandle, Protocol)
1105 // Exclusive TRUE -> Something has exclusive access to (UserHandle, Protocol)
1106 // Exclusive FALSE -> Nothing has exclusive access to (UserHandle, Protocol)
1107 //
1108
1109 switch (Attributes) {
1110 case EFI_OPEN_PROTOCOL_BY_DRIVER :
1111 if (Exclusive || ByDriver) {
1112 Status = EFI_ACCESS_DENIED;
1113 goto Done;
1114 }
1115 break;
1116 case EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE :
1117 case EFI_OPEN_PROTOCOL_EXCLUSIVE :
1118 if (Exclusive) {
1119 Status = EFI_ACCESS_DENIED;
1120 goto Done;
1121 }
1122 if (ByDriver) {
1123 do {
1124 Disconnect = FALSE;
1125 for (Link = Prot->OpenList.ForwardLink; Link != &Prot->OpenList; Link = Link->ForwardLink) {
1126 OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
1127 if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
1128 Disconnect = TRUE;
1129 CoreReleaseProtocolLock ();
1130 Status = CoreDisconnectController (UserHandle, OpenData->AgentHandle, NULL);
1131 CoreAcquireProtocolLock ();
1132 if (EFI_ERROR (Status)) {
1133 Status = EFI_ACCESS_DENIED;
1134 goto Done;
1135 } else {
1136 break;
1137 }
1138 }
1139 }
1140 } while (Disconnect);
1141 }
1142 break;
1143 case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER :
1144 case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL :
1145 case EFI_OPEN_PROTOCOL_GET_PROTOCOL :
1146 case EFI_OPEN_PROTOCOL_TEST_PROTOCOL :
1147 break;
1148 }
1149
1150 if (ImageHandle == NULL) {
1151 Status = EFI_SUCCESS;
1152 goto Done;
1153 }
1154 //
1155 // Create new entry
1156 //
1157 OpenData = AllocatePool (sizeof(OPEN_PROTOCOL_DATA));
1158 if (OpenData == NULL) {
1159 Status = EFI_OUT_OF_RESOURCES;
1160 } else {
1161 OpenData->Signature = OPEN_PROTOCOL_DATA_SIGNATURE;
1162 OpenData->AgentHandle = ImageHandle;
1163 OpenData->ControllerHandle = ControllerHandle;
1164 OpenData->Attributes = Attributes;
1165 OpenData->OpenCount = 1;
1166 InsertTailList (&Prot->OpenList, &OpenData->Link);
1167 Prot->OpenListCount++;
1168 Status = EFI_SUCCESS;
1169 }
1170
1171 Done:
1172
1173 if (Attributes != EFI_OPEN_PROTOCOL_TEST_PROTOCOL) {
1174 //
1175 // Keep Interface unmodified in case of any Error
1176 // except EFI_ALREADY_STARTED and EFI_UNSUPPORTED.
1177 //
1178 if (!EFI_ERROR (Status) || Status == EFI_ALREADY_STARTED) {
1179 //
1180 // According to above logic, if 'Prot' is NULL, then the 'Status' must be
1181 // EFI_UNSUPPORTED. Here the 'Status' is not EFI_UNSUPPORTED, so 'Prot'
1182 // must be not NULL.
1183 //
1184 // The ASSERT here is for addressing a false positive NULL pointer
1185 // dereference issue raised from static analysis.
1186 //
1187 ASSERT (Prot != NULL);
1188 //
1189 // EFI_ALREADY_STARTED is not an error for bus driver.
1190 // Return the corresponding protocol interface.
1191 //
1192 *Interface = Prot->Interface;
1193 } else if (Status == EFI_UNSUPPORTED) {
1194 //
1195 // Return NULL Interface if Unsupported Protocol.
1196 //
1197 *Interface = NULL;
1198 }
1199 }
1200
1201 //
1202 // Done. Release the database lock and return
1203 //
1204 CoreReleaseProtocolLock ();
1205 return Status;
1206 }
1207
1208
1209
1210 /**
1211 Closes a protocol on a handle that was opened using OpenProtocol().
1212
1213 @param UserHandle The handle for the protocol interface that was
1214 previously opened with OpenProtocol(), and is
1215 now being closed.
1216 @param Protocol The published unique identifier of the protocol.
1217 It is the caller's responsibility to pass in a
1218 valid GUID.
1219 @param AgentHandle The handle of the agent that is closing the
1220 protocol interface.
1221 @param ControllerHandle If the agent that opened a protocol is a driver
1222 that follows the EFI Driver Model, then this
1223 parameter is the controller handle that required
1224 the protocol interface. If the agent does not
1225 follow the EFI Driver Model, then this parameter
1226 is optional and may be NULL.
1227
1228 @retval EFI_SUCCESS The protocol instance was closed.
1229 @retval EFI_INVALID_PARAMETER Handle, AgentHandle or ControllerHandle is not a
1230 valid EFI_HANDLE.
1231 @retval EFI_NOT_FOUND Can not find the specified protocol or
1232 AgentHandle.
1233
1234 **/
1235 EFI_STATUS
1236 EFIAPI
CoreCloseProtocol(IN EFI_HANDLE UserHandle,IN EFI_GUID * Protocol,IN EFI_HANDLE AgentHandle,IN EFI_HANDLE ControllerHandle)1237 CoreCloseProtocol (
1238 IN EFI_HANDLE UserHandle,
1239 IN EFI_GUID *Protocol,
1240 IN EFI_HANDLE AgentHandle,
1241 IN EFI_HANDLE ControllerHandle
1242 )
1243 {
1244 EFI_STATUS Status;
1245 PROTOCOL_INTERFACE *ProtocolInterface;
1246 LIST_ENTRY *Link;
1247 OPEN_PROTOCOL_DATA *OpenData;
1248
1249 //
1250 // Check for invalid parameters
1251 //
1252 Status = CoreValidateHandle (UserHandle);
1253 if (EFI_ERROR (Status)) {
1254 return Status;
1255 }
1256 Status = CoreValidateHandle (AgentHandle);
1257 if (EFI_ERROR (Status)) {
1258 return Status;
1259 }
1260 if (ControllerHandle != NULL) {
1261 Status = CoreValidateHandle (ControllerHandle);
1262 if (EFI_ERROR (Status)) {
1263 return Status;
1264 }
1265 }
1266 if (Protocol == NULL) {
1267 return EFI_INVALID_PARAMETER;
1268 }
1269
1270 //
1271 // Lock the protocol database
1272 //
1273 CoreAcquireProtocolLock ();
1274
1275 //
1276 // Look at each protocol interface for a match
1277 //
1278 Status = EFI_NOT_FOUND;
1279 ProtocolInterface = CoreGetProtocolInterface (UserHandle, Protocol);
1280 if (ProtocolInterface == NULL) {
1281 goto Done;
1282 }
1283
1284 //
1285 // Walk the Open data base looking for AgentHandle
1286 //
1287 Link = ProtocolInterface->OpenList.ForwardLink;
1288 while (Link != &ProtocolInterface->OpenList) {
1289 OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
1290 Link = Link->ForwardLink;
1291 if ((OpenData->AgentHandle == AgentHandle) && (OpenData->ControllerHandle == ControllerHandle)) {
1292 RemoveEntryList (&OpenData->Link);
1293 ProtocolInterface->OpenListCount--;
1294 CoreFreePool (OpenData);
1295 Status = EFI_SUCCESS;
1296 }
1297 }
1298
1299 Done:
1300 //
1301 // Done. Release the database lock and return.
1302 //
1303 CoreReleaseProtocolLock ();
1304 return Status;
1305 }
1306
1307
1308
1309
1310 /**
1311 Return information about Opened protocols in the system
1312
1313 @param UserHandle The handle to close the protocol interface on
1314 @param Protocol The ID of the protocol
1315 @param EntryBuffer A pointer to a buffer of open protocol information in the
1316 form of EFI_OPEN_PROTOCOL_INFORMATION_ENTRY structures.
1317 @param EntryCount Number of EntryBuffer entries
1318
1319 @retval EFI_SUCCESS The open protocol information was returned in EntryBuffer,
1320 and the number of entries was returned EntryCount.
1321 @retval EFI_NOT_FOUND Handle does not support the protocol specified by Protocol.
1322 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to allocate EntryBuffer.
1323
1324 **/
1325 EFI_STATUS
1326 EFIAPI
CoreOpenProtocolInformation(IN EFI_HANDLE UserHandle,IN EFI_GUID * Protocol,OUT EFI_OPEN_PROTOCOL_INFORMATION_ENTRY ** EntryBuffer,OUT UINTN * EntryCount)1327 CoreOpenProtocolInformation (
1328 IN EFI_HANDLE UserHandle,
1329 IN EFI_GUID *Protocol,
1330 OUT EFI_OPEN_PROTOCOL_INFORMATION_ENTRY **EntryBuffer,
1331 OUT UINTN *EntryCount
1332 )
1333 {
1334 EFI_STATUS Status;
1335 PROTOCOL_INTERFACE *ProtocolInterface;
1336 LIST_ENTRY *Link;
1337 OPEN_PROTOCOL_DATA *OpenData;
1338 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *Buffer;
1339 UINTN Count;
1340 UINTN Size;
1341
1342 *EntryBuffer = NULL;
1343 *EntryCount = 0;
1344
1345 //
1346 // Lock the protocol database
1347 //
1348 CoreAcquireProtocolLock ();
1349
1350 //
1351 // Look at each protocol interface for a match
1352 //
1353 Status = EFI_NOT_FOUND;
1354 ProtocolInterface = CoreGetProtocolInterface (UserHandle, Protocol);
1355 if (ProtocolInterface == NULL) {
1356 goto Done;
1357 }
1358
1359 //
1360 // Count the number of Open Entries
1361 //
1362 for ( Link = ProtocolInterface->OpenList.ForwardLink, Count = 0;
1363 (Link != &ProtocolInterface->OpenList) ;
1364 Link = Link->ForwardLink ) {
1365 Count++;
1366 }
1367
1368 ASSERT (Count == ProtocolInterface->OpenListCount);
1369
1370 if (Count == 0) {
1371 Size = sizeof(EFI_OPEN_PROTOCOL_INFORMATION_ENTRY);
1372 } else {
1373 Size = Count * sizeof(EFI_OPEN_PROTOCOL_INFORMATION_ENTRY);
1374 }
1375
1376 Buffer = AllocatePool (Size);
1377 if (Buffer == NULL) {
1378 Status = EFI_OUT_OF_RESOURCES;
1379 goto Done;
1380 }
1381
1382 Status = EFI_SUCCESS;
1383 for ( Link = ProtocolInterface->OpenList.ForwardLink, Count = 0;
1384 (Link != &ProtocolInterface->OpenList);
1385 Link = Link->ForwardLink, Count++ ) {
1386 OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
1387
1388 Buffer[Count].AgentHandle = OpenData->AgentHandle;
1389 Buffer[Count].ControllerHandle = OpenData->ControllerHandle;
1390 Buffer[Count].Attributes = OpenData->Attributes;
1391 Buffer[Count].OpenCount = OpenData->OpenCount;
1392 }
1393
1394 *EntryBuffer = Buffer;
1395 *EntryCount = Count;
1396
1397 Done:
1398 //
1399 // Done. Release the database lock.
1400 //
1401 CoreReleaseProtocolLock ();
1402 return Status;
1403 }
1404
1405
1406
1407
1408 /**
1409 Retrieves the list of protocol interface GUIDs that are installed on a handle in a buffer allocated
1410 from pool.
1411
1412 @param UserHandle The handle from which to retrieve the list of
1413 protocol interface GUIDs.
1414 @param ProtocolBuffer A pointer to the list of protocol interface GUID
1415 pointers that are installed on Handle.
1416 @param ProtocolBufferCount A pointer to the number of GUID pointers present
1417 in ProtocolBuffer.
1418
1419 @retval EFI_SUCCESS The list of protocol interface GUIDs installed
1420 on Handle was returned in ProtocolBuffer. The
1421 number of protocol interface GUIDs was returned
1422 in ProtocolBufferCount.
1423 @retval EFI_INVALID_PARAMETER Handle is NULL.
1424 @retval EFI_INVALID_PARAMETER Handle is not a valid EFI_HANDLE.
1425 @retval EFI_INVALID_PARAMETER ProtocolBuffer is NULL.
1426 @retval EFI_INVALID_PARAMETER ProtocolBufferCount is NULL.
1427 @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the
1428 results.
1429
1430 **/
1431 EFI_STATUS
1432 EFIAPI
CoreProtocolsPerHandle(IN EFI_HANDLE UserHandle,OUT EFI_GUID *** ProtocolBuffer,OUT UINTN * ProtocolBufferCount)1433 CoreProtocolsPerHandle (
1434 IN EFI_HANDLE UserHandle,
1435 OUT EFI_GUID ***ProtocolBuffer,
1436 OUT UINTN *ProtocolBufferCount
1437 )
1438 {
1439 EFI_STATUS Status;
1440 IHANDLE *Handle;
1441 PROTOCOL_INTERFACE *Prot;
1442 LIST_ENTRY *Link;
1443 UINTN ProtocolCount;
1444 EFI_GUID **Buffer;
1445
1446 Status = CoreValidateHandle (UserHandle);
1447 if (EFI_ERROR (Status)) {
1448 return Status;
1449 }
1450
1451 Handle = (IHANDLE *)UserHandle;
1452
1453 if (ProtocolBuffer == NULL) {
1454 return EFI_INVALID_PARAMETER;
1455 }
1456
1457 if (ProtocolBufferCount == NULL) {
1458 return EFI_INVALID_PARAMETER;
1459 }
1460
1461 *ProtocolBufferCount = 0;
1462
1463 ProtocolCount = 0;
1464
1465 CoreAcquireProtocolLock ();
1466
1467 for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
1468 ProtocolCount++;
1469 }
1470
1471 //
1472 // If there are no protocol interfaces installed on Handle, then Handle is not a valid EFI_HANDLE
1473 //
1474 if (ProtocolCount == 0) {
1475 Status = EFI_INVALID_PARAMETER;
1476 goto Done;
1477 }
1478
1479 Buffer = AllocatePool (sizeof (EFI_GUID *) * ProtocolCount);
1480 if (Buffer == NULL) {
1481 Status = EFI_OUT_OF_RESOURCES;
1482 goto Done;
1483 }
1484
1485 *ProtocolBuffer = Buffer;
1486 *ProtocolBufferCount = ProtocolCount;
1487
1488 for ( Link = Handle->Protocols.ForwardLink, ProtocolCount = 0;
1489 Link != &Handle->Protocols;
1490 Link = Link->ForwardLink, ProtocolCount++) {
1491 Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
1492 Buffer[ProtocolCount] = &(Prot->Protocol->ProtocolID);
1493 }
1494 Status = EFI_SUCCESS;
1495
1496 Done:
1497 CoreReleaseProtocolLock ();
1498 return Status;
1499 }
1500
1501
1502
1503 /**
1504 return handle database key.
1505
1506
1507 @return Handle database key.
1508
1509 **/
1510 UINT64
CoreGetHandleDatabaseKey(VOID)1511 CoreGetHandleDatabaseKey (
1512 VOID
1513 )
1514 {
1515 return gHandleDatabaseKey;
1516 }
1517
1518
1519
1520 /**
1521 Go connect any handles that were created or modified while a image executed.
1522
1523 @param Key The Key to show that the handle has been
1524 created/modified
1525
1526 **/
1527 VOID
CoreConnectHandlesByKey(UINT64 Key)1528 CoreConnectHandlesByKey (
1529 UINT64 Key
1530 )
1531 {
1532 UINTN Count;
1533 LIST_ENTRY *Link;
1534 EFI_HANDLE *HandleBuffer;
1535 IHANDLE *Handle;
1536 UINTN Index;
1537
1538 //
1539 // Lock the protocol database
1540 //
1541 CoreAcquireProtocolLock ();
1542
1543 for (Link = gHandleList.ForwardLink, Count = 0; Link != &gHandleList; Link = Link->ForwardLink) {
1544 Handle = CR (Link, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE);
1545 if (Handle->Key > Key) {
1546 Count++;
1547 }
1548 }
1549
1550 HandleBuffer = AllocatePool (Count * sizeof (EFI_HANDLE));
1551 if (HandleBuffer == NULL) {
1552 CoreReleaseProtocolLock ();
1553 return;
1554 }
1555
1556 for (Link = gHandleList.ForwardLink, Count = 0; Link != &gHandleList; Link = Link->ForwardLink) {
1557 Handle = CR (Link, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE);
1558 if (Handle->Key > Key) {
1559 HandleBuffer[Count++] = Handle;
1560 }
1561 }
1562
1563 //
1564 // Unlock the protocol database
1565 //
1566 CoreReleaseProtocolLock ();
1567
1568 //
1569 // Connect all handles whose Key value is greater than Key
1570 //
1571 for (Index = 0; Index < Count; Index++) {
1572 CoreConnectController (HandleBuffer[Index], NULL, NULL, TRUE);
1573 }
1574
1575 CoreFreePool(HandleBuffer);
1576 }
1577