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