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