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