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