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