Initial import.
[mirror_edk2.git] / EdkModulePkg / Core / Dxe / Hand / handle.c
Content-type: text/html git.proxmox.com Git - mirror_edk2.git/blame - EdkModulePkg/Core/Dxe/Hand/handle.c


500 - Internal Server Error

Malformed UTF-8 character (fatal) at (eval 8) line 1, <$fd> line 2667.
CommitLineData
878ddf1f 1/*++\r
2\r
3Copyright (c) 2006, Intel Corporation \r
4All rights reserved. This program and the accompanying materials \r
5are licensed and made available under the terms and conditions of the BSD License \r
6which accompanies this distribution. The full text of the license may be found at \r
7http://opensource.org/licenses/bsd-license.php \r
8 \r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
11\r
12Module Name:\r
13\r
14 handle.c\r
15\r
16Abstract:\r
17\r
18 EFI handle & protocol handling\r
19\r
20\r
21\r
22Revision 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
35static LIST_ENTRY mProtocolDatabase = INITIALIZE_LIST_HEAD_VARIABLE (mProtocolDatabase);\r
36LIST_ENTRY gHandleList = INITIALIZE_LIST_HEAD_VARIABLE (gHandleList);\r
37EFI_LOCK gProtocolDatabaseLock = EFI_INITIALIZE_LOCK_VARIABLE (EFI_TPL_NOTIFY);\r
38UINT64 gHandleDatabaseKey = 0;\r
39\r
40\r
41VOID\r
42CoreAcquireProtocolLock (\r
43 VOID\r
44 )\r
45/*++\r
46\r
47Routine Description:\r
48\r
49 Acquire lock on gProtocolDatabaseLock.\r
50 \r
51Arguments:\r
52\r
53 None\r
54 \r
55Returns:\r
56\r
57 None\r
58\r
59--*/\r
60{\r
61 CoreAcquireLock (&gProtocolDatabaseLock);\r
62}\r
63\r
64\r
65VOID\r
66CoreReleaseProtocolLock (\r
67 VOID\r
68 )\r
69/*++\r
70\r
71Routine Description:\r
72\r
73 Release lock on gProtocolDatabaseLock.\r
74 \r
75Arguments:\r
76\r
77 None\r
78 \r
79Returns:\r
80\r
81 None\r
82\r
83--*/\r
84{\r
85 CoreReleaseLock (&gProtocolDatabaseLock);\r
86}\r
87\r
88\r
89EFI_STATUS\r
90CoreValidateHandle (\r
91 IN EFI_HANDLE UserHandle\r
92 )\r
93/*++\r
94\r
95Routine Description:\r
96\r
97 Check whether a handle is a valid EFI_HANDLE\r
98 \r
99Arguments:\r
100\r
101 UserHandle - The handle to check\r
102 \r
103Returns:\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
124PROTOCOL_ENTRY *\r
125CoreFindProtocolEntry (\r
126 IN EFI_GUID *Protocol,\r
127 IN BOOLEAN Create\r
128 )\r
129/*++\r
130\r
131Routine 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
137Arguments:\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
143Returns:\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
203PROTOCOL_INTERFACE *\r
204CoreFindProtocolInterface (\r
205 IN IHANDLE *Handle,\r
206 IN EFI_GUID *Protocol,\r
207 IN VOID *Interface\r
208 )\r
209/*++\r
210\r
211Routine 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
218Arguments:\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
226Returns:\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
266STATIC\r
267EFI_STATUS\r
268CoreUnregisterProtocolNotifyEvent (\r
269 IN EFI_EVENT Event\r
270 )\r
271/*++\r
272\r
273Routine Description:\r
274\r
275 Removes an event from a register protocol notify list on a protocol.\r
276\r
277Arguments:\r
278 \r
279 Event - The event to search for in the protocol database.\r
280\r
281Returns:\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
321EFI_STATUS\r
322CoreUnregisterProtocolNotify (\r
323 IN EFI_EVENT Event\r
324 )\r
325/*++\r
326\r
327Routine Description:\r
328\r
329 Removes all the events in the protocol database that match Event.\r
330\r
331Arguments:\r
332 \r
333 Event - The event to search for in the protocol database.\r
334\r
335Returns:\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
352EFI_STATUS\r
353EFIAPI\r
354CoreInstallProtocolInterface (\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
362Routine 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
367Arguments:\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
378Returns:\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
393EFI_STATUS\r
394CoreInstallProtocolInterfaceNotify (\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
403Routine Description:\r
404\r
405 Installs a protocol interface into the boot services environment.\r
406\r
407Arguments:\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
421Returns:\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 %x\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 != gBS);\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
563Done:\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
587EFI_STATUS\r
588EFIAPI\r
589CoreInstallMultipleProtocolInterfaces (\r
590 IN OUT EFI_HANDLE *Handle,\r
591 ...\r
592 )\r
593/*++\r
594\r
595Routine 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
602Arguments:\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
610Returns:\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 (EFI_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
695EFI_STATUS\r
696CoreDisconnectControllersUsingProtocolInterface (\r
697 IN EFI_HANDLE UserHandle,\r
698 IN PROTOCOL_INTERFACE *Prot\r
699 )\r
700/*++\r
701\r
702Routine 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
710Arguments:\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
715Returns:\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
786EFI_STATUS\r
787EFIAPI\r
788CoreUninstallProtocolInterface (\r
789 IN EFI_HANDLE UserHandle,\r
790 IN EFI_GUID *Protocol,\r
791 IN VOID *Interface\r
792 )\r
793/*++\r
794\r
795Routine 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
801Arguments:\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
809Returns:\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
900Done: \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
910EFI_STATUS\r
911EFIAPI\r
912CoreUninstallMultipleProtocolInterfaces (\r
913 IN EFI_HANDLE Handle,\r
914 ...\r
915 )\r
916/*++\r
917\r
918Routine 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
924Arguments:\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
932Returns:\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
981PROTOCOL_INTERFACE *\r
982CoreGetProtocolInterface (\r
983 IN EFI_HANDLE UserHandle,\r
984 IN EFI_GUID *Protocol\r
985 )\r
986/*++\r
987\r
988Routine Description:\r
989\r
990 Locate a certain GUID protocol interface in a Handle's protocols.\r
991\r
992Arguments:\r
993\r
994 UserHandle - The handle to obtain the protocol interface on\r
995\r
996 Protocol - The GUID of the protocol \r
997\r
998Returns:\r
999\r
1000 The requested protocol interface for the handle\r
1001 \r
1002--*/ \r
1003{\r
1004 EFI_STATUS Status;\r
1005 PROTOCOL_ENTRY *ProtEntry;\r
1006 PROTOCOL_INTERFACE *Prot;\r
1007 IHANDLE *Handle;\r
1008 LIST_ENTRY *Link;\r
1009\r
1010 Status = CoreValidateHandle (UserHandle);\r
1011 if (EFI_ERROR (Status)) {\r
1012 return NULL;\r
1013 }\r
1014 \r
1015 Handle = (IHANDLE *)UserHandle;\r
1016\r
1017 //\r
1018 // Look at each protocol interface for a match\r
1019 //\r
1020 for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {\r
1021 Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);\r
1022 ProtEntry = Prot->Protocol;\r
1023 if (CompareGuid (&ProtEntry->ProtocolID, Protocol)) {\r
1024 return Prot;\r
1025 }\r
1026 }\r
1027 return NULL;\r
1028}\r
1029\r
1030\r
1031EFI_STATUS\r
1032EFIAPI\r
1033CoreHandleProtocol (\r
1034 IN EFI_HANDLE UserHandle,\r
1035 IN EFI_GUID *Protocol,\r
1036 OUT VOID **Interface\r
1037 )\r
1038/*++\r
1039\r
1040Routine Description:\r
1041\r
1042 Queries a handle to determine if it supports a specified protocol.\r
1043\r
1044Arguments:\r
1045\r
1046 UserHandle - The handle being queried.\r
1047\r
1048 Protocol - The published unique identifier of the protocol.\r
1049\r
1050 Interface - Supplies the address where a pointer to the corresponding Protocol\r
1051 Interface is returned.\r
1052\r
1053Returns:\r
1054\r
1055 The requested protocol interface for the handle\r
1056 \r
1057--*/ \r
1058{\r
1059 return CoreOpenProtocol (\r
1060 UserHandle, \r
1061 Protocol, \r
1062 Interface, \r
1063 gDxeCoreImageHandle, \r
1064 NULL, \r
1065 EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL\r
1066 );\r
1067}\r
1068\r
1069\r
1070EFI_STATUS\r
1071EFIAPI\r
1072CoreOpenProtocol (\r
1073 IN EFI_HANDLE UserHandle,\r
1074 IN EFI_GUID *Protocol,\r
1075 OUT VOID **Interface OPTIONAL,\r
1076 IN EFI_HANDLE ImageHandle,\r
1077 IN EFI_HANDLE ControllerHandle,\r
1078 IN UINT32 Attributes\r
1079 )\r
1080/*++\r
1081\r
1082Routine Description:\r
1083\r
1084 Locates the installed protocol handler for the handle, and\r
1085 invokes it to obtain the protocol interface. Usage information\r
1086 is registered in the protocol data base.\r
1087\r
1088Arguments:\r
1089\r
1090 UserHandle - The handle to obtain the protocol interface on\r
1091\r
1092 Protocol - The ID of the protocol \r
1093\r
1094 Interface - The location to return the protocol interface\r
1095\r
1096 ImageHandle - The handle of the Image that is opening the protocol interface\r
1097 specified by Protocol and Interface.\r
1098 \r
1099 ControllerHandle - The controller handle that is requiring this interface.\r
1100\r
1101 Attributes - The open mode of the protocol interface specified by Handle\r
1102 and Protocol.\r
1103\r
1104Returns:\r
1105\r
1106 EFI_INVALID_PARAMETER - Protocol is NULL.\r
1107 \r
1108 EFI_SUCCESS - Get the protocol interface.\r
1109 \r
1110--*/\r
1111{\r
1112 EFI_STATUS Status;\r
1113 PROTOCOL_INTERFACE *Prot;\r
1114 LIST_ENTRY *Link;\r
1115 OPEN_PROTOCOL_DATA *OpenData;\r
1116 BOOLEAN ByDriver;\r
1117 BOOLEAN Exclusive;\r
1118 BOOLEAN Disconnect;\r
1119 BOOLEAN ExactMatch;\r
1120\r
1121 //\r
1122 // Check for invalid Protocol\r
1123 //\r
1124 if (Protocol == NULL) {\r
1125 return EFI_INVALID_PARAMETER;\r
1126 }\r
1127\r
1128 //\r
1129 // Check for invalid Interface\r
1130 //\r
1131 if (Attributes != EFI_OPEN_PROTOCOL_TEST_PROTOCOL) {\r
1132 if (Interface == NULL) {\r
1133 return EFI_INVALID_PARAMETER;\r
1134 } else {\r
1135 *Interface = NULL;\r
1136 }\r
1137 }\r
1138 \r
1139 //\r
1140 // Check for invalid UserHandle\r
1141 //\r
1142 Status = CoreValidateHandle (UserHandle);\r
1143 if (EFI_ERROR (Status)) {\r
1144 return Status;\r
1145 }\r
1146\r
1147 //\r
1148 // Check for invalid Attributes\r
1149 //\r
1150 switch (Attributes) {\r
1151 case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER :\r
1152 Status = CoreValidateHandle (ImageHandle);\r
1153 if (EFI_ERROR (Status)) {\r
1154 return Status;\r
1155 }\r
1156 Status = CoreValidateHandle (ControllerHandle);\r
1157 if (EFI_ERROR (Status)) {\r
1158 return Status;\r
1159 }\r
1160 if (UserHandle == ControllerHandle) {\r
1161 return EFI_INVALID_PARAMETER;\r
1162 }\r
1163 break;\r
1164 case EFI_OPEN_PROTOCOL_BY_DRIVER :\r
1165 case EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE :\r
1166 Status = CoreValidateHandle (ImageHandle);\r
1167 if (EFI_ERROR (Status)) {\r
1168 return Status;\r
1169 }\r
1170 Status = CoreValidateHandle (ControllerHandle);\r
1171 if (EFI_ERROR (Status)) {\r
1172 return Status;\r
1173 }\r
1174 break;\r
1175 case EFI_OPEN_PROTOCOL_EXCLUSIVE :\r
1176 Status = CoreValidateHandle (ImageHandle);\r
1177 if (EFI_ERROR (Status)) {\r
1178 return Status;\r
1179 }\r
1180 break;\r
1181 case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL :\r
1182 case EFI_OPEN_PROTOCOL_GET_PROTOCOL :\r
1183 case EFI_OPEN_PROTOCOL_TEST_PROTOCOL :\r
1184 break;\r
1185 default:\r
1186 return EFI_INVALID_PARAMETER;\r
1187 }\r
1188\r
1189 //\r
1190 // Lock the protocol database\r
1191 //\r
1192 CoreAcquireProtocolLock ();\r
1193\r
1194 //\r
1195 // Look at each protocol interface for a match\r
1196 //\r
1197 Prot = CoreGetProtocolInterface (UserHandle, Protocol);\r
1198 if (Prot == NULL) {\r
1199 Status = EFI_UNSUPPORTED;\r
1200 goto Done;\r
1201 }\r
1202\r
1203 //\r
1204 // This is the protocol interface entry for this protocol\r
1205 // \r
1206 if (Attributes != EFI_OPEN_PROTOCOL_TEST_PROTOCOL) {\r
1207 *Interface = Prot->Interface;\r
1208 }\r
1209 Status = EFI_SUCCESS;\r
1210\r
1211 ByDriver = FALSE;\r
1212 Exclusive = FALSE;\r
1213 for ( Link = Prot->OpenList.ForwardLink; Link != &Prot->OpenList; Link = Link->ForwardLink) {\r
1214 OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);\r
1215 ExactMatch = (BOOLEAN)((OpenData->AgentHandle == ImageHandle) && \r
1216 (OpenData->Attributes == Attributes) &&\r
1217 (OpenData->ControllerHandle == ControllerHandle));\r
1218 if (OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) {\r
1219 ByDriver = TRUE;\r
1220 if (ExactMatch) {\r
1221 Status = EFI_ALREADY_STARTED;\r
1222 goto Done;\r
1223 }\r
1224 }\r
1225 if (OpenData->Attributes & EFI_OPEN_PROTOCOL_EXCLUSIVE) {\r
1226 Exclusive = TRUE;\r
1227 } else if (ExactMatch) {\r
1228 OpenData->OpenCount++;\r
1229 Status = EFI_SUCCESS;\r
1230 goto Done;\r
1231 }\r
1232 }\r
1233\r
1234 //\r
1235 // ByDriver TRUE -> A driver is managing (UserHandle, Protocol)\r
1236 // ByDriver FALSE -> There are no drivers managing (UserHandle, Protocol)\r
1237 // Exclusive TRUE -> Something has exclusive access to (UserHandle, Protocol)\r
1238 // Exclusive FALSE -> Nothing has exclusive access to (UserHandle, Protocol)\r
1239 //\r
1240\r
1241 switch (Attributes) {\r
1242 case EFI_OPEN_PROTOCOL_BY_DRIVER :\r
1243 if (Exclusive || ByDriver) {\r
1244 Status = EFI_ACCESS_DENIED;\r
1245 goto Done;\r
1246 }\r
1247 break;\r
1248 case EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE :\r
1249 case EFI_OPEN_PROTOCOL_EXCLUSIVE :\r
1250 if (Exclusive) {\r
1251 Status = EFI_ACCESS_DENIED;\r
1252 goto Done;\r
1253 }\r
1254 if (ByDriver) {\r
1255 do {\r
1256 Disconnect = FALSE;\r
1257 for ( Link = Prot->OpenList.ForwardLink; (Link != &Prot->OpenList) && (!Disconnect); Link = Link->ForwardLink) {\r
1258 OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);\r
1259 if (OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) {\r
1260 Disconnect = TRUE;\r
1261 CoreReleaseProtocolLock ();\r
1262 Status = CoreDisconnectController (UserHandle, OpenData->AgentHandle, NULL);\r
1263 CoreAcquireProtocolLock ();\r
1264 if (EFI_ERROR (Status)) {\r
1265 Status = EFI_ACCESS_DENIED;\r
1266 goto Done;\r
1267 }\r
1268 }\r
1269 }\r
1270 } while (Disconnect);\r
1271 } \r
1272 break;\r
1273 case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER :\r
1274 case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL :\r
1275 case EFI_OPEN_PROTOCOL_GET_PROTOCOL :\r
1276 case EFI_OPEN_PROTOCOL_TEST_PROTOCOL :\r
1277 break;\r
1278 }\r
1279\r
1280 if (ImageHandle == NULL) {\r
1281 Status = EFI_SUCCESS;\r
1282 goto Done;\r
1283 }\r
1284 //\r
1285 // Create new entry\r
1286 //\r
1287 OpenData = CoreAllocateBootServicesPool (sizeof(OPEN_PROTOCOL_DATA));\r
1288 if (OpenData == NULL) {\r
1289 Status = EFI_OUT_OF_RESOURCES;\r
1290 } else {\r
1291 OpenData->Signature = OPEN_PROTOCOL_DATA_SIGNATURE;\r
1292 OpenData->AgentHandle = ImageHandle;\r
1293 OpenData->ControllerHandle = ControllerHandle;\r
1294 OpenData->Attributes = Attributes;\r
1295 OpenData->OpenCount = 1;\r
1296 InsertTailList (&Prot->OpenList, &OpenData->Link);\r
1297 Prot->OpenListCount++;\r
1298 Status = EFI_SUCCESS;\r
1299 }\r
1300\r
1301Done:\r
1302 //\r
1303 // Done. Release the database lock are return\r
1304 //\r
1305 CoreReleaseProtocolLock ();\r
1306 return Status;\r
1307}\r
1308\r
1309\r
1310EFI_STATUS\r
1311EFIAPI\r
1312CoreCloseProtocol (\r
1313 IN EFI_HANDLE UserHandle,\r
1314 IN EFI_GUID *Protocol,\r
1315 IN EFI_HANDLE AgentHandle,\r
1316 IN EFI_HANDLE ControllerHandle \r
1317 )\r
1318/*++\r
1319\r
1320Routine Description:\r
1321\r
1322 Closes a protocol on a handle that was opened using OpenProtocol().\r
1323\r
1324Arguments:\r
1325\r
1326 UserHandle - The handle for the protocol interface that was previously opened\r
1327 with OpenProtocol(), and is now being closed.\r
1328