]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Core/Dxe/Hand/Handle.c
MdeModulePkg/DxeCore: Fixed Interface returned by CoreOpenProtocol
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / Hand / Handle.c
1 /** @file
2 UEFI handle & protocol handling.
3
4 Copyright (c) 2006 - 2017, 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
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 *
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 *
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
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
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
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
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 } else {
432 Status = CoreValidateHandle (Handle);
433 if (EFI_ERROR (Status)) {
434 DEBUG((DEBUG_ERROR, "InstallProtocolInterface: input handle at 0x%x is invalid\n", Handle));
435 goto Done;
436 }
437 }
438
439 //
440 // Each interface that is added must be unique
441 //
442 ASSERT (CoreFindProtocolInterface (Handle, Protocol, Interface) == NULL);
443
444 //
445 // Initialize the protocol interface structure
446 //
447 Prot->Signature = PROTOCOL_INTERFACE_SIGNATURE;
448 Prot->Handle = Handle;
449 Prot->Protocol = ProtEntry;
450 Prot->Interface = Interface;
451
452 //
453 // Initalize OpenProtocol Data base
454 //
455 InitializeListHead (&Prot->OpenList);
456 Prot->OpenListCount = 0;
457
458 //
459 // Add this protocol interface to the head of the supported
460 // protocol list for this handle
461 //
462 InsertHeadList (&Handle->Protocols, &Prot->Link);
463
464 //
465 // Add this protocol interface to the tail of the
466 // protocol entry
467 //
468 InsertTailList (&ProtEntry->Protocols, &Prot->ByProtocol);
469
470 //
471 // Notify the notification list for this protocol
472 //
473 if (Notify) {
474 CoreNotifyProtocolEntry (ProtEntry);
475 }
476 Status = EFI_SUCCESS;
477
478 Done:
479 //
480 // Done, unlock the database and return
481 //
482 CoreReleaseProtocolLock ();
483 if (!EFI_ERROR (Status)) {
484 //
485 // Return the new handle back to the caller
486 //
487 *UserHandle = Handle;
488 } else {
489 //
490 // There was an error, clean up
491 //
492 if (Prot != NULL) {
493 CoreFreePool (Prot);
494 }
495 DEBUG((DEBUG_ERROR, "InstallProtocolInterface: %g %p failed with %r\n", Protocol, Interface, Status));
496 }
497
498 return Status;
499 }
500
501
502
503
504 /**
505 Installs a list of protocol interface into the boot services environment.
506 This function calls InstallProtocolInterface() in a loop. If any error
507 occures all the protocols added by this function are removed. This is
508 basically a lib function to save space.
509
510 @param Handle The pointer to a handle to install the new
511 protocol interfaces on, or a pointer to NULL
512 if a new handle is to be allocated.
513 @param ... EFI_GUID followed by protocol instance. A NULL
514 terminates the list. The pairs are the
515 arguments to InstallProtocolInterface(). All the
516 protocols are added to Handle.
517
518 @retval EFI_SUCCESS All the protocol interface was installed.
519 @retval EFI_OUT_OF_RESOURCES There was not enough memory in pool to install all the protocols.
520 @retval EFI_ALREADY_STARTED A Device Path Protocol instance was passed in that is already present in
521 the handle database.
522 @retval EFI_INVALID_PARAMETER Handle is NULL.
523 @retval EFI_INVALID_PARAMETER Protocol is already installed on the handle specified by Handle.
524
525 **/
526 EFI_STATUS
527 EFIAPI
528 CoreInstallMultipleProtocolInterfaces (
529 IN OUT EFI_HANDLE *Handle,
530 ...
531 )
532 {
533 VA_LIST Args;
534 EFI_STATUS Status;
535 EFI_GUID *Protocol;
536 VOID *Interface;
537 EFI_TPL OldTpl;
538 UINTN Index;
539 EFI_HANDLE OldHandle;
540 EFI_HANDLE DeviceHandle;
541 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
542
543 if (Handle == NULL) {
544 return EFI_INVALID_PARAMETER;
545 }
546
547 //
548 // Syncronize with notifcations.
549 //
550 OldTpl = CoreRaiseTpl (TPL_NOTIFY);
551 OldHandle = *Handle;
552
553 //
554 // Check for duplicate device path and install the protocol interfaces
555 //
556 VA_START (Args, Handle);
557 for (Index = 0, Status = EFI_SUCCESS; !EFI_ERROR (Status); Index++) {
558 //
559 // If protocol is NULL, then it's the end of the list
560 //
561 Protocol = VA_ARG (Args, EFI_GUID *);
562 if (Protocol == NULL) {
563 break;
564 }
565
566 Interface = VA_ARG (Args, VOID *);
567
568 //
569 // Make sure you are installing on top a device path that has already been added.
570 //
571 if (CompareGuid (Protocol, &gEfiDevicePathProtocolGuid)) {
572 DeviceHandle = NULL;
573 DevicePath = Interface;
574 Status = CoreLocateDevicePath (&gEfiDevicePathProtocolGuid, &DevicePath, &DeviceHandle);
575 if (!EFI_ERROR (Status) && (DeviceHandle != NULL) && IsDevicePathEnd(DevicePath)) {
576 Status = EFI_ALREADY_STARTED;
577 continue;
578 }
579 }
580
581 //
582 // Install it
583 //
584 Status = CoreInstallProtocolInterface (Handle, Protocol, EFI_NATIVE_INTERFACE, Interface);
585 }
586 VA_END (Args);
587
588 //
589 // If there was an error, remove all the interfaces that were installed without any errors
590 //
591 if (EFI_ERROR (Status)) {
592 //
593 // Reset the va_arg back to the first argument.
594 //
595 VA_START (Args, Handle);
596 for (; Index > 1; Index--) {
597 Protocol = VA_ARG (Args, EFI_GUID *);
598 Interface = VA_ARG (Args, VOID *);
599 CoreUninstallProtocolInterface (*Handle, Protocol, Interface);
600 }
601 VA_END (Args);
602
603 *Handle = OldHandle;
604 }
605
606 //
607 // Done
608 //
609 CoreRestoreTpl (OldTpl);
610 return Status;
611 }
612
613
614 /**
615 Attempts to disconnect all drivers that are using the protocol interface being queried.
616 If failed, reconnect all drivers disconnected.
617 Note: This function doesn't do parameters checking, it's caller's responsibility
618 to pass in valid parameters.
619
620 @param UserHandle The handle on which the protocol is installed
621 @param Prot The protocol to disconnect drivers from
622
623 @retval EFI_SUCCESS Drivers using the protocol interface are all
624 disconnected
625 @retval EFI_ACCESS_DENIED Failed to disconnect one or all of the drivers
626
627 **/
628 EFI_STATUS
629 CoreDisconnectControllersUsingProtocolInterface (
630 IN EFI_HANDLE UserHandle,
631 IN PROTOCOL_INTERFACE *Prot
632 )
633 {
634 EFI_STATUS Status;
635 BOOLEAN ItemFound;
636 LIST_ENTRY *Link;
637 OPEN_PROTOCOL_DATA *OpenData;
638
639 Status = EFI_SUCCESS;
640
641 //
642 // Attempt to disconnect all drivers from this protocol interface
643 //
644 do {
645 ItemFound = FALSE;
646 for ( Link = Prot->OpenList.ForwardLink;
647 (Link != &Prot->OpenList) && !ItemFound;
648 Link = Link->ForwardLink ) {
649 OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
650 if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
651 ItemFound = TRUE;
652 CoreReleaseProtocolLock ();
653 Status = CoreDisconnectController (UserHandle, OpenData->AgentHandle, NULL);
654 CoreAcquireProtocolLock ();
655 if (EFI_ERROR (Status)) {
656 ItemFound = FALSE;
657 break;
658 }
659 }
660 }
661 } while (ItemFound);
662
663 if (!EFI_ERROR (Status)) {
664 //
665 // Attempt to remove BY_HANDLE_PROTOOCL and GET_PROTOCOL and TEST_PROTOCOL Open List items
666 //
667 do {
668 ItemFound = FALSE;
669 for ( Link = Prot->OpenList.ForwardLink;
670 (Link != &Prot->OpenList) && !ItemFound;
671 Link = Link->ForwardLink ) {
672 OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
673 if ((OpenData->Attributes &
674 (EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL | EFI_OPEN_PROTOCOL_GET_PROTOCOL | EFI_OPEN_PROTOCOL_TEST_PROTOCOL)) != 0) {
675 ItemFound = TRUE;
676 RemoveEntryList (&OpenData->Link);
677 Prot->OpenListCount--;
678 CoreFreePool (OpenData);
679 }
680 }
681 } while (ItemFound);
682 }
683
684 //
685 // If there are errors or still has open items in the list, then reconnect all the drivers and return an error
686 //
687 if (EFI_ERROR (Status) || (Prot->OpenListCount > 0)) {
688 CoreReleaseProtocolLock ();
689 CoreConnectController (UserHandle, NULL, NULL, TRUE);
690 CoreAcquireProtocolLock ();
691 Status = EFI_ACCESS_DENIED;
692 }
693
694 return Status;
695 }
696
697
698
699 /**
700 Uninstalls all instances of a protocol:interfacer from a handle.
701 If the last protocol interface is remove from the handle, the
702 handle is freed.
703
704 @param UserHandle The handle to remove the protocol handler from
705 @param Protocol The protocol, of protocol:interface, to remove
706 @param Interface The interface, of protocol:interface, to remove
707
708 @retval EFI_INVALID_PARAMETER Protocol is NULL.
709 @retval EFI_SUCCESS Protocol interface successfully uninstalled.
710
711 **/
712 EFI_STATUS
713 EFIAPI
714 CoreUninstallProtocolInterface (
715 IN EFI_HANDLE UserHandle,
716 IN EFI_GUID *Protocol,
717 IN VOID *Interface
718 )
719 {
720 EFI_STATUS Status;
721 IHANDLE *Handle;
722 PROTOCOL_INTERFACE *Prot;
723
724 //
725 // Check that Protocol is valid
726 //
727 if (Protocol == NULL) {
728 return EFI_INVALID_PARAMETER;
729 }
730
731 //
732 // Check that UserHandle is a valid handle
733 //
734 Status = CoreValidateHandle (UserHandle);
735 if (EFI_ERROR (Status)) {
736 return Status;
737 }
738
739 //
740 // Lock the protocol database
741 //
742 CoreAcquireProtocolLock ();
743
744 //
745 // Check that Protocol exists on UserHandle, and Interface matches the interface in the database
746 //
747 Prot = CoreFindProtocolInterface (UserHandle, Protocol, Interface);
748 if (Prot == NULL) {
749 Status = EFI_NOT_FOUND;
750 goto Done;
751 }
752
753 //
754 // Attempt to disconnect all drivers that are using the protocol interface that is about to be removed
755 //
756 Status = CoreDisconnectControllersUsingProtocolInterface (
757 UserHandle,
758 Prot
759 );
760 if (EFI_ERROR (Status)) {
761 //
762 // One or more drivers refused to release, so return the error
763 //
764 goto Done;
765 }
766
767 //
768 // Remove the protocol interface from the protocol
769 //
770 Status = EFI_NOT_FOUND;
771 Handle = (IHANDLE *)UserHandle;
772 Prot = CoreRemoveInterfaceFromProtocol (Handle, Protocol, Interface);
773
774 if (Prot != NULL) {
775 //
776 // Update the Key to show that the handle has been created/modified
777 //
778 gHandleDatabaseKey++;
779 Handle->Key = gHandleDatabaseKey;
780
781 //
782 // Remove the protocol interface from the handle
783 //
784 RemoveEntryList (&Prot->Link);
785
786 //
787 // Free the memory
788 //
789 Prot->Signature = 0;
790 CoreFreePool (Prot);
791 Status = EFI_SUCCESS;
792 }
793
794 //
795 // If there are no more handlers for the handle, free the handle
796 //
797 if (IsListEmpty (&Handle->Protocols)) {
798 Handle->Signature = 0;
799 RemoveEntryList (&Handle->AllHandles);
800 CoreFreePool (Handle);
801 }
802
803 Done:
804 //
805 // Done, unlock the database and return
806 //
807 CoreReleaseProtocolLock ();
808 return Status;
809 }
810
811
812
813
814 /**
815 Uninstalls a list of protocol interface in the boot services environment.
816 This function calls UnisatllProtocolInterface() in a loop. This is
817 basically a lib function to save space.
818
819 @param Handle The handle to uninstall the protocol
820 @param ... EFI_GUID followed by protocol instance. A NULL
821 terminates the list. The pairs are the
822 arguments to UninstallProtocolInterface(). All
823 the protocols are added to Handle.
824
825 @return Status code
826
827 **/
828 EFI_STATUS
829 EFIAPI
830 CoreUninstallMultipleProtocolInterfaces (
831 IN EFI_HANDLE Handle,
832 ...
833 )
834 {
835 EFI_STATUS Status;
836 VA_LIST Args;
837 EFI_GUID *Protocol;
838 VOID *Interface;
839 UINTN Index;
840
841 VA_START (Args, Handle);
842 for (Index = 0, Status = EFI_SUCCESS; !EFI_ERROR (Status); Index++) {
843 //
844 // If protocol is NULL, then it's the end of the list
845 //
846 Protocol = VA_ARG (Args, EFI_GUID *);
847 if (Protocol == NULL) {
848 break;
849 }
850
851 Interface = VA_ARG (Args, VOID *);
852
853 //
854 // Uninstall it
855 //
856 Status = CoreUninstallProtocolInterface (Handle, Protocol, Interface);
857 }
858 VA_END (Args);
859
860 //
861 // If there was an error, add all the interfaces that were
862 // uninstalled without any errors
863 //
864 if (EFI_ERROR (Status)) {
865 //
866 // Reset the va_arg back to the first argument.
867 //
868 VA_START (Args, Handle);
869 for (; Index > 1; Index--) {
870 Protocol = VA_ARG(Args, EFI_GUID *);
871 Interface = VA_ARG(Args, VOID *);
872 CoreInstallProtocolInterface (&Handle, Protocol, EFI_NATIVE_INTERFACE, Interface);
873 }
874 VA_END (Args);
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 *
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
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
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 if (Attributes != EFI_OPEN_PROTOCOL_TEST_PROTOCOL){
1075 //Return NULL Interface if Unsupported Protocol
1076 *Interface = NULL;
1077 }
1078 goto Done;
1079 }
1080
1081 Status = EFI_SUCCESS;
1082
1083 ByDriver = FALSE;
1084 Exclusive = FALSE;
1085 for ( Link = Prot->OpenList.ForwardLink; Link != &Prot->OpenList; Link = Link->ForwardLink) {
1086 OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
1087 ExactMatch = (BOOLEAN)((OpenData->AgentHandle == ImageHandle) &&
1088 (OpenData->Attributes == Attributes) &&
1089 (OpenData->ControllerHandle == ControllerHandle));
1090 if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
1091 ByDriver = TRUE;
1092 if (ExactMatch) {
1093 Status = EFI_ALREADY_STARTED;
1094 goto Done;
1095 }
1096 }
1097 if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_EXCLUSIVE) != 0) {
1098 Exclusive = TRUE;
1099 } else if (ExactMatch) {
1100 OpenData->OpenCount++;
1101 Status = EFI_SUCCESS;
1102 goto Done;
1103 }
1104 }
1105
1106 //
1107 // ByDriver TRUE -> A driver is managing (UserHandle, Protocol)
1108 // ByDriver FALSE -> There are no drivers managing (UserHandle, Protocol)
1109 // Exclusive TRUE -> Something has exclusive access to (UserHandle, Protocol)
1110 // Exclusive FALSE -> Nothing has exclusive access to (UserHandle, Protocol)
1111 //
1112
1113 switch (Attributes) {
1114 case EFI_OPEN_PROTOCOL_BY_DRIVER :
1115 if (Exclusive || ByDriver) {
1116 Status = EFI_ACCESS_DENIED;
1117 goto Done;
1118 }
1119 break;
1120 case EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE :
1121 case EFI_OPEN_PROTOCOL_EXCLUSIVE :
1122 if (Exclusive) {
1123 Status = EFI_ACCESS_DENIED;
1124 goto Done;
1125 }
1126 if (ByDriver) {
1127 do {
1128 Disconnect = FALSE;
1129 for ( Link = Prot->OpenList.ForwardLink; (Link != &Prot->OpenList) && (!Disconnect); Link = Link->ForwardLink) {
1130 OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
1131 if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
1132 Disconnect = TRUE;
1133 CoreReleaseProtocolLock ();
1134 Status = CoreDisconnectController (UserHandle, OpenData->AgentHandle, NULL);
1135 CoreAcquireProtocolLock ();
1136 if (EFI_ERROR (Status)) {
1137 Status = EFI_ACCESS_DENIED;
1138 goto Done;
1139 }
1140 }
1141 }
1142 } while (Disconnect);
1143 }
1144 break;
1145 case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER :
1146 case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL :
1147 case EFI_OPEN_PROTOCOL_GET_PROTOCOL :
1148 case EFI_OPEN_PROTOCOL_TEST_PROTOCOL :
1149 break;
1150 }
1151
1152 if (ImageHandle == NULL) {
1153 Status = EFI_SUCCESS;
1154 goto Done;
1155 }
1156 //
1157 // Create new entry
1158 //
1159 OpenData = AllocatePool (sizeof(OPEN_PROTOCOL_DATA));
1160 if (OpenData == NULL) {
1161 Status = EFI_OUT_OF_RESOURCES;
1162 } else {
1163 OpenData->Signature = OPEN_PROTOCOL_DATA_SIGNATURE;
1164 OpenData->AgentHandle = ImageHandle;
1165 OpenData->ControllerHandle = ControllerHandle;
1166 OpenData->Attributes = Attributes;
1167 OpenData->OpenCount = 1;
1168 InsertTailList (&Prot->OpenList, &OpenData->Link);
1169 Prot->OpenListCount++;
1170 Status = EFI_SUCCESS;
1171 }
1172
1173 Done:
1174
1175 //
1176 // This is the protocol interface entry for this protocol.
1177 // In case of any Error, Interface should not be updated as per spec.
1178 //
1179 if (!EFI_ERROR (Status) && (Attributes != EFI_OPEN_PROTOCOL_TEST_PROTOCOL)) {
1180 *Interface = Prot->Interface;
1181 }
1182 //
1183 // Done. Release the database lock are return
1184 //
1185 CoreReleaseProtocolLock ();
1186 return Status;
1187 }
1188
1189
1190
1191 /**
1192 Closes a protocol on a handle that was opened using OpenProtocol().
1193
1194 @param UserHandle The handle for the protocol interface that was
1195 previously opened with OpenProtocol(), and is
1196 now being closed.
1197 @param Protocol The published unique identifier of the protocol.
1198 It is the caller's responsibility to pass in a
1199 valid GUID.
1200 @param AgentHandle The handle of the agent that is closing the
1201 protocol interface.
1202 @param ControllerHandle If the agent that opened a protocol is a driver
1203 that follows the EFI Driver Model, then this
1204 parameter is the controller handle that required
1205 the protocol interface. If the agent does not
1206 follow the EFI Driver Model, then this parameter
1207 is optional and may be NULL.
1208
1209 @retval EFI_SUCCESS The protocol instance was closed.
1210 @retval EFI_INVALID_PARAMETER Handle, AgentHandle or ControllerHandle is not a
1211 valid EFI_HANDLE.
1212 @retval EFI_NOT_FOUND Can not find the specified protocol or
1213 AgentHandle.
1214
1215 **/
1216 EFI_STATUS
1217 EFIAPI
1218 CoreCloseProtocol (
1219 IN EFI_HANDLE UserHandle,
1220 IN EFI_GUID *Protocol,
1221 IN EFI_HANDLE AgentHandle,
1222 IN EFI_HANDLE ControllerHandle
1223 )
1224 {
1225 EFI_STATUS Status;
1226 PROTOCOL_INTERFACE *ProtocolInterface;
1227 LIST_ENTRY *Link;
1228 OPEN_PROTOCOL_DATA *OpenData;
1229
1230 //
1231 // Check for invalid parameters
1232 //
1233 Status = CoreValidateHandle (UserHandle);
1234 if (EFI_ERROR (Status)) {
1235 return Status;
1236 }
1237 Status = CoreValidateHandle (AgentHandle);
1238 if (EFI_ERROR (Status)) {
1239 return Status;
1240 }
1241 if (ControllerHandle != NULL) {
1242 Status = CoreValidateHandle (ControllerHandle);
1243 if (EFI_ERROR (Status)) {
1244 return Status;
1245 }
1246 }
1247 if (Protocol == NULL) {
1248 return EFI_INVALID_PARAMETER;
1249 }
1250
1251 //
1252 // Lock the protocol database
1253 //
1254 CoreAcquireProtocolLock ();
1255
1256 //
1257 // Look at each protocol interface for a match
1258 //
1259 Status = EFI_NOT_FOUND;
1260 ProtocolInterface = CoreGetProtocolInterface (UserHandle, Protocol);
1261 if (ProtocolInterface == NULL) {
1262 goto Done;
1263 }
1264
1265 //
1266 // Walk the Open data base looking for AgentHandle
1267 //
1268 Link = ProtocolInterface->OpenList.ForwardLink;
1269 while (Link != &ProtocolInterface->OpenList) {
1270 OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
1271 Link = Link->ForwardLink;
1272 if ((OpenData->AgentHandle == AgentHandle) && (OpenData->ControllerHandle == ControllerHandle)) {
1273 RemoveEntryList (&OpenData->Link);
1274 ProtocolInterface->OpenListCount--;
1275 CoreFreePool (OpenData);
1276 Status = EFI_SUCCESS;
1277 }
1278 }
1279
1280 Done:
1281 //
1282 // Done. Release the database lock and return.
1283 //
1284 CoreReleaseProtocolLock ();
1285 return Status;
1286 }
1287
1288
1289
1290
1291 /**
1292 Return information about Opened protocols in the system
1293
1294 @param UserHandle The handle to close the protocol interface on
1295 @param Protocol The ID of the protocol
1296 @param EntryBuffer A pointer to a buffer of open protocol information in the
1297 form of EFI_OPEN_PROTOCOL_INFORMATION_ENTRY structures.
1298 @param EntryCount Number of EntryBuffer entries
1299
1300 @retval EFI_SUCCESS The open protocol information was returned in EntryBuffer,
1301 and the number of entries was returned EntryCount.
1302 @retval EFI_NOT_FOUND Handle does not support the protocol specified by Protocol.
1303 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to allocate EntryBuffer.
1304
1305 **/
1306 EFI_STATUS
1307 EFIAPI
1308 CoreOpenProtocolInformation (
1309 IN EFI_HANDLE UserHandle,
1310 IN EFI_GUID *Protocol,
1311 OUT EFI_OPEN_PROTOCOL_INFORMATION_ENTRY **EntryBuffer,
1312 OUT UINTN *EntryCount
1313 )
1314 {
1315 EFI_STATUS Status;
1316 PROTOCOL_INTERFACE *ProtocolInterface;
1317 LIST_ENTRY *Link;
1318 OPEN_PROTOCOL_DATA *OpenData;
1319 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *Buffer;
1320 UINTN Count;
1321 UINTN Size;
1322
1323 *EntryBuffer = NULL;
1324 *EntryCount = 0;
1325
1326 //
1327 // Lock the protocol database
1328 //
1329 CoreAcquireProtocolLock ();
1330
1331 //
1332 // Look at each protocol interface for a match
1333 //
1334 Status = EFI_NOT_FOUND;
1335 ProtocolInterface = CoreGetProtocolInterface (UserHandle, Protocol);
1336 if (ProtocolInterface == NULL) {
1337 goto Done;
1338 }
1339
1340 //
1341 // Count the number of Open Entries
1342 //
1343 for ( Link = ProtocolInterface->OpenList.ForwardLink, Count = 0;
1344 (Link != &ProtocolInterface->OpenList) ;
1345 Link = Link->ForwardLink ) {
1346 Count++;
1347 }
1348
1349 ASSERT (Count == ProtocolInterface->OpenListCount);
1350
1351 if (Count == 0) {
1352 Size = sizeof(EFI_OPEN_PROTOCOL_INFORMATION_ENTRY);
1353 } else {
1354 Size = Count * sizeof(EFI_OPEN_PROTOCOL_INFORMATION_ENTRY);
1355 }
1356
1357 Buffer = AllocatePool (Size);
1358 if (Buffer == NULL) {
1359 Status = EFI_OUT_OF_RESOURCES;
1360 goto Done;
1361 }
1362
1363 Status = EFI_SUCCESS;
1364 for ( Link = ProtocolInterface->OpenList.ForwardLink, Count = 0;
1365 (Link != &ProtocolInterface->OpenList);
1366 Link = Link->ForwardLink, Count++ ) {
1367 OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
1368
1369 Buffer[Count].AgentHandle = OpenData->AgentHandle;
1370 Buffer[Count].ControllerHandle = OpenData->ControllerHandle;
1371 Buffer[Count].Attributes = OpenData->Attributes;
1372 Buffer[Count].OpenCount = OpenData->OpenCount;
1373 }
1374
1375 *EntryBuffer = Buffer;
1376 *EntryCount = Count;
1377
1378 Done:
1379 //
1380 // Done. Release the database lock.
1381 //
1382 CoreReleaseProtocolLock ();
1383 return Status;
1384 }
1385
1386
1387
1388
1389 /**
1390 Retrieves the list of protocol interface GUIDs that are installed on a handle in a buffer allocated
1391 from pool.
1392
1393 @param UserHandle The handle from which to retrieve the list of
1394 protocol interface GUIDs.
1395 @param ProtocolBuffer A pointer to the list of protocol interface GUID
1396 pointers that are installed on Handle.
1397 @param ProtocolBufferCount A pointer to the number of GUID pointers present
1398 in ProtocolBuffer.
1399
1400 @retval EFI_SUCCESS The list of protocol interface GUIDs installed
1401 on Handle was returned in ProtocolBuffer. The
1402 number of protocol interface GUIDs was returned
1403 in ProtocolBufferCount.
1404 @retval EFI_INVALID_PARAMETER Handle is NULL.
1405 @retval EFI_INVALID_PARAMETER Handle is not a valid EFI_HANDLE.
1406 @retval EFI_INVALID_PARAMETER ProtocolBuffer is NULL.
1407 @retval EFI_INVALID_PARAMETER ProtocolBufferCount is NULL.
1408 @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the
1409 results.
1410
1411 **/
1412 EFI_STATUS
1413 EFIAPI
1414 CoreProtocolsPerHandle (
1415 IN EFI_HANDLE UserHandle,
1416 OUT EFI_GUID ***ProtocolBuffer,
1417 OUT UINTN *ProtocolBufferCount
1418 )
1419 {
1420 EFI_STATUS Status;
1421 IHANDLE *Handle;
1422 PROTOCOL_INTERFACE *Prot;
1423 LIST_ENTRY *Link;
1424 UINTN ProtocolCount;
1425 EFI_GUID **Buffer;
1426
1427 Status = CoreValidateHandle (UserHandle);
1428 if (EFI_ERROR (Status)) {
1429 return Status;
1430 }
1431
1432 Handle = (IHANDLE *)UserHandle;
1433
1434 if (ProtocolBuffer == NULL) {
1435 return EFI_INVALID_PARAMETER;
1436 }
1437
1438 if (ProtocolBufferCount == NULL) {
1439 return EFI_INVALID_PARAMETER;
1440 }
1441
1442 *ProtocolBufferCount = 0;
1443
1444 ProtocolCount = 0;
1445
1446 CoreAcquireProtocolLock ();
1447
1448 for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
1449 ProtocolCount++;
1450 }
1451
1452 //
1453 // If there are no protocol interfaces installed on Handle, then Handle is not a valid EFI_HANDLE
1454 //
1455 if (ProtocolCount == 0) {
1456 Status = EFI_INVALID_PARAMETER;
1457 goto Done;
1458 }
1459
1460 Buffer = AllocatePool (sizeof (EFI_GUID *) * ProtocolCount);
1461 if (Buffer == NULL) {
1462 Status = EFI_OUT_OF_RESOURCES;
1463 goto Done;
1464 }
1465
1466 *ProtocolBuffer = Buffer;
1467 *ProtocolBufferCount = ProtocolCount;
1468
1469 for ( Link = Handle->Protocols.ForwardLink, ProtocolCount = 0;
1470 Link != &Handle->Protocols;
1471 Link = Link->ForwardLink, ProtocolCount++) {
1472 Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
1473 Buffer[ProtocolCount] = &(Prot->Protocol->ProtocolID);
1474 }
1475 Status = EFI_SUCCESS;
1476
1477 Done:
1478 CoreReleaseProtocolLock ();
1479 return Status;
1480 }
1481
1482
1483
1484 /**
1485 return handle database key.
1486
1487
1488 @return Handle database key.
1489
1490 **/
1491 UINT64
1492 CoreGetHandleDatabaseKey (
1493 VOID
1494 )
1495 {
1496 return gHandleDatabaseKey;
1497 }
1498
1499
1500
1501 /**
1502 Go connect any handles that were created or modified while a image executed.
1503
1504 @param Key The Key to show that the handle has been
1505 created/modified
1506
1507 **/
1508 VOID
1509 CoreConnectHandlesByKey (
1510 UINT64 Key
1511 )
1512 {
1513 UINTN Count;
1514 LIST_ENTRY *Link;
1515 EFI_HANDLE *HandleBuffer;
1516 IHANDLE *Handle;
1517 UINTN Index;
1518
1519 //
1520 // Lock the protocol database
1521 //
1522 CoreAcquireProtocolLock ();
1523
1524 for (Link = gHandleList.ForwardLink, Count = 0; Link != &gHandleList; Link = Link->ForwardLink) {
1525 Handle = CR (Link, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE);
1526 if (Handle->Key > Key) {
1527 Count++;
1528 }
1529 }
1530
1531 HandleBuffer = AllocatePool (Count * sizeof (EFI_HANDLE));
1532 if (HandleBuffer == NULL) {
1533 CoreReleaseProtocolLock ();
1534 return;
1535 }
1536
1537 for (Link = gHandleList.ForwardLink, Count = 0; Link != &gHandleList; Link = Link->ForwardLink) {
1538 Handle = CR (Link, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE);
1539 if (Handle->Key > Key) {
1540 HandleBuffer[Count++] = Handle;
1541 }
1542 }
1543
1544 //
1545 // Unlock the protocol database
1546 //
1547 CoreReleaseProtocolLock ();
1548
1549 //
1550 // Connect all handles whose Key value is greater than Key
1551 //
1552 for (Index = 0; Index < Count; Index++) {
1553 CoreConnectController (HandleBuffer[Index], NULL, NULL, TRUE);
1554 }
1555
1556 CoreFreePool(HandleBuffer);
1557 }