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