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