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