]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/Dxe/Hand/Handle.c
Remove the unnecessary spin_lock protection around CoreUnloadImage. There is almost...
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / Hand / Handle.c
CommitLineData
23c98c94 1/** @file\r
162ed594 2 UEFI handle & protocol handling.\r
28a00297 3\r
23c98c94 4Copyright (c) 2006 - 2008, Intel Corporation. <BR>\r
5All rights reserved. This 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
28a00297 12\r
504214c4 13**/\r
28a00297 14\r
9c4ac31c 15#include "DxeMain.h"\r
28a00297 16\r
17\r
18//\r
19// mProtocolDatabase - A list of all protocols in the system. (simple list for now)\r
20// gHandleList - A list of all the handles in the system\r
21// gProtocolDatabaseLock - Lock to protect the mProtocolDatabase\r
22// gHandleDatabaseKey - The Key to show that the handle has been created/modified\r
23//\r
e94a9ff7 24LIST_ENTRY mProtocolDatabase = INITIALIZE_LIST_HEAD_VARIABLE (mProtocolDatabase);\r
28a00297 25LIST_ENTRY gHandleList = INITIALIZE_LIST_HEAD_VARIABLE (gHandleList);\r
26EFI_LOCK gProtocolDatabaseLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY);\r
27UINT64 gHandleDatabaseKey = 0;\r
28\r
29\r
162ed594 30\r
31/**\r
32 Acquire lock on gProtocolDatabaseLock.\r
33\r
34**/\r
28a00297 35VOID\r
36CoreAcquireProtocolLock (\r
37 VOID\r
38 )\r
28a00297 39{\r
40 CoreAcquireLock (&gProtocolDatabaseLock);\r
41}\r
42\r
43\r
162ed594 44\r
45/**\r
46 Release lock on gProtocolDatabaseLock.\r
47\r
48**/\r
28a00297 49VOID\r
50CoreReleaseProtocolLock (\r
51 VOID\r
52 )\r
28a00297 53{\r
54 CoreReleaseLock (&gProtocolDatabaseLock);\r
55}\r
56\r
57\r
28a00297 58\r
162ed594 59/**\r
28a00297 60 Check whether a handle is a valid EFI_HANDLE\r
28a00297 61\r
022c6d45 62 @param UserHandle The handle to check\r
28a00297 63\r
022c6d45 64 @retval EFI_INVALID_PARAMETER The handle is NULL or not a valid EFI_HANDLE.\r
162ed594 65 @retval EFI_SUCCESS The handle is valid EFI_HANDLE.\r
28a00297 66\r
162ed594 67**/\r
68EFI_STATUS\r
69CoreValidateHandle (\r
70 IN EFI_HANDLE UserHandle\r
71 )\r
28a00297 72{\r
73 IHANDLE *Handle;\r
74\r
75 Handle = (IHANDLE *)UserHandle;\r
76 if (Handle == NULL) {\r
77 return EFI_INVALID_PARAMETER;\r
78 }\r
79 if (Handle->Signature != EFI_HANDLE_SIGNATURE) {\r
80 return EFI_INVALID_PARAMETER;\r
81 }\r
82 return EFI_SUCCESS;\r
83}\r
84\r
85\r
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
1439777e 367 DEBUG((DEBUG_LOAD | 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
022c6d45 430 }\r
28a00297 431\r
432 Status = CoreValidateHandle (Handle);\r
433 if (EFI_ERROR (Status)) {\r
434 goto Done;\r
435 }\r
436\r
437 //\r
438 // Each interface that is added must be unique\r
439 //\r
440 ASSERT (CoreFindProtocolInterface (Handle, Protocol, Interface) == NULL);\r
441\r
442 //\r
443 // Initialize the protocol interface structure\r
444 //\r
445 Prot->Signature = PROTOCOL_INTERFACE_SIGNATURE;\r
446 Prot->Handle = Handle;\r
447 Prot->Protocol = ProtEntry;\r
448 Prot->Interface = Interface;\r
449\r
450 //\r
451 // Initalize OpenProtocol Data base\r
452 //\r
453 InitializeListHead (&Prot->OpenList);\r
454 Prot->OpenListCount = 0;\r
455\r
456 //\r
022c6d45 457 // Add this protocol interface to the head of the supported\r
28a00297 458 // protocol list for this handle\r
459 //\r
460 InsertHeadList (&Handle->Protocols, &Prot->Link);\r
461\r
462 //\r
022c6d45 463 // Add this protocol interface to the tail of the\r
28a00297 464 // protocol entry\r
022c6d45 465 //\r
28a00297 466 InsertTailList (&ProtEntry->Protocols, &Prot->ByProtocol);\r
467\r
468 //\r
022c6d45 469 // Notify the notification list for this protocol\r
28a00297 470 //\r
471 if (Notify) {\r
472 CoreNotifyProtocolEntry (ProtEntry);\r
473 }\r
474 Status = EFI_SUCCESS;\r
475\r
476Done:\r
477 //\r
478 // Done, unlock the database and return\r
479 //\r
480 CoreReleaseProtocolLock ();\r
481 if (!EFI_ERROR (Status)) {\r
482 //\r
483 // Return the new handle back to the caller\r
484 //\r
485 *UserHandle = Handle;\r
486 } else {\r
487 //\r
488 // There was an error, clean up\r
489 //\r
490 if (Prot != NULL) {\r
491 CoreFreePool (Prot);\r
492 }\r
493 }\r
494\r
495 return Status;\r
496}\r
497\r
498\r
499\r
28a00297 500\r
162ed594 501/**\r
28a00297 502 Installs a list of protocol interface into the boot services environment.\r
503 This function calls InstallProtocolInterface() in a loop. If any error\r
162ed594 504 occures all the protocols added by this function are removed. This is\r
28a00297 505 basically a lib function to save space.\r
506\r
022c6d45 507 @param Handle The handle to install the protocol handlers on,\r
508 or NULL if a new handle is to be allocated\r
509 @param ... EFI_GUID followed by protocol instance. A NULL\r
510 terminates the list. The pairs are the\r
511 arguments to InstallProtocolInterface(). All the\r
512 protocols are added to Handle.\r
28a00297 513\r
022c6d45 514 @retval EFI_INVALID_PARAMETER Handle is NULL.\r
162ed594 515 @retval EFI_SUCCESS Protocol interfaces successfully installed.\r
28a00297 516\r
162ed594 517**/\r
518EFI_STATUS\r
519EFIAPI\r
520CoreInstallMultipleProtocolInterfaces (\r
521 IN OUT EFI_HANDLE *Handle,\r
522 ...\r
523 )\r
28a00297 524{\r
162ed594 525 VA_LIST Args;\r
28a00297 526 EFI_STATUS Status;\r
527 EFI_GUID *Protocol;\r
528 VOID *Interface;\r
529 EFI_TPL OldTpl;\r
530 UINTN Index;\r
531 EFI_HANDLE OldHandle;\r
532 EFI_HANDLE DeviceHandle;\r
533 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
022c6d45 534\r
28a00297 535 if (Handle == NULL) {\r
536 return EFI_INVALID_PARAMETER;\r
537 }\r
022c6d45 538\r
539 //\r
540 // Syncronize with notifcations.\r
28a00297 541 //\r
28a00297 542 OldTpl = CoreRaiseTpl (TPL_NOTIFY);\r
543 OldHandle = *Handle;\r
544\r
545 //\r
546 // Check for duplicate device path and install the protocol interfaces\r
547 //\r
162ed594 548 VA_START (Args, Handle);\r
28a00297 549 for (Index = 0, Status = EFI_SUCCESS; !EFI_ERROR (Status); Index++) {\r
550 //\r
551 // If protocol is NULL, then it's the end of the list\r
552 //\r
162ed594 553 Protocol = VA_ARG (Args, EFI_GUID *);\r
28a00297 554 if (Protocol == NULL) {\r
555 break;\r
556 }\r
557\r
162ed594 558 Interface = VA_ARG (Args, VOID *);\r
28a00297 559\r
560 //\r
561 // Make sure you are installing on top a device path that has already been added.\r
562 //\r
563 if (CompareGuid (Protocol, &gEfiDevicePathProtocolGuid)) {\r
564 DeviceHandle = NULL;\r
565 DevicePath = Interface;\r
566 Status = CoreLocateDevicePath (&gEfiDevicePathProtocolGuid, &DevicePath, &DeviceHandle);\r
4008328a 567 if (!EFI_ERROR (Status) && (DeviceHandle != NULL) && IsDevicePathEnd(DevicePath)) {\r
28a00297 568 Status = EFI_ALREADY_STARTED;\r
569 continue;\r
570 }\r
571 }\r
022c6d45 572\r
28a00297 573 //\r
574 // Install it\r
575 //\r
576 Status = CoreInstallProtocolInterface (Handle, Protocol, EFI_NATIVE_INTERFACE, Interface);\r
577 }\r
022c6d45 578\r
28a00297 579 //\r
580 // If there was an error, remove all the interfaces that were installed without any errors\r
581 //\r
582 if (EFI_ERROR (Status)) {\r
583 //\r
584 // Reset the va_arg back to the first argument.\r
585 //\r
162ed594 586 VA_START (Args, Handle);\r
28a00297 587 for (; Index > 1; Index--) {\r
162ed594 588 Protocol = VA_ARG (Args, EFI_GUID *);\r
589 Interface = VA_ARG (Args, VOID *);\r
28a00297 590 CoreUninstallProtocolInterface (*Handle, Protocol, Interface);\r
022c6d45 591 }\r
28a00297 592 *Handle = OldHandle;\r
593 }\r
594\r
595 //\r
596 // Done\r
597 //\r
598 CoreRestoreTpl (OldTpl);\r
599 return Status;\r
600}\r
601\r
28a00297 602\r
162ed594 603/**\r
28a00297 604 Attempts to disconnect all drivers that are using the protocol interface being queried.\r
605 If failed, reconnect all drivers disconnected.\r
162ed594 606 Note: This function doesn't do parameters checking, it's caller's responsibility\r
607 to pass in valid parameters.\r
28a00297 608\r
022c6d45 609 @param UserHandle The handle on which the protocol is installed\r
610 @param Prot The protocol to disconnect drivers from\r
28a00297 611\r
022c6d45 612 @retval EFI_SUCCESS Drivers using the protocol interface are all\r
613 disconnected\r
162ed594 614 @retval EFI_ACCESS_DENIED Failed to disconnect one or all of the drivers\r
28a00297 615\r
162ed594 616**/\r
617EFI_STATUS\r
618CoreDisconnectControllersUsingProtocolInterface (\r
619 IN EFI_HANDLE UserHandle,\r
620 IN PROTOCOL_INTERFACE *Prot\r
621 )\r
28a00297 622{\r
623 EFI_STATUS Status;\r
624 BOOLEAN ItemFound;\r
625 LIST_ENTRY *Link;\r
626 OPEN_PROTOCOL_DATA *OpenData;\r
627\r
628 Status = EFI_SUCCESS;\r
022c6d45 629\r
28a00297 630 //\r
631 // Attempt to disconnect all drivers from this protocol interface\r
632 //\r
633 do {\r
634 ItemFound = FALSE;\r
635 for ( Link = Prot->OpenList.ForwardLink;\r
636 (Link != &Prot->OpenList) && !ItemFound;\r
637 Link = Link->ForwardLink ) {\r
638 OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);\r
639 if (OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) {\r
640 ItemFound = TRUE;\r
641 CoreReleaseProtocolLock ();\r
642 Status = CoreDisconnectController (UserHandle, OpenData->AgentHandle, NULL);\r
643 CoreAcquireProtocolLock ();\r
644 if (EFI_ERROR (Status)) {\r
645 ItemFound = FALSE;\r
646 break;\r
647 }\r
648 }\r
649 }\r
650 } while (ItemFound);\r
651\r
652 if (!EFI_ERROR (Status)) {\r
653 //\r
654 // Attempt to remove BY_HANDLE_PROTOOCL and GET_PROTOCOL and TEST_PROTOCOL Open List items\r
655 //\r
656 do {\r
657 ItemFound = FALSE;\r
658 for ( Link = Prot->OpenList.ForwardLink;\r
659 (Link != &Prot->OpenList) && !ItemFound;\r
660 Link = Link->ForwardLink ) {\r
661 OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);\r
022c6d45 662 if (OpenData->Attributes &\r
28a00297 663 (EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL | EFI_OPEN_PROTOCOL_GET_PROTOCOL | EFI_OPEN_PROTOCOL_TEST_PROTOCOL)) {\r
664 ItemFound = TRUE;\r
022c6d45 665 RemoveEntryList (&OpenData->Link);\r
28a00297 666 Prot->OpenListCount--;\r
667 CoreFreePool (OpenData);\r
668 }\r
669 }\r
670 } while (ItemFound);\r
671 }\r
672\r
673 //\r
674 // If there are errors or still has open items in the list, then reconnect all the drivers and return an error\r
675 //\r
676 if (EFI_ERROR (Status) || (Prot->OpenListCount > 0)) {\r
677 CoreReleaseProtocolLock ();\r
678 CoreConnectController (UserHandle, NULL, NULL, TRUE);\r
679 CoreAcquireProtocolLock ();\r
680 Status = EFI_ACCESS_DENIED;\r
681 }\r
682\r
683 return Status;\r
684}\r
685\r
686\r
162ed594 687\r
688/**\r
689 Uninstalls all instances of a protocol:interfacer from a handle.\r
690 If the last protocol interface is remove from the handle, the\r
691 handle is freed.\r
692\r
022c6d45 693 @param UserHandle The handle to remove the protocol handler from\r
694 @param Protocol The protocol, of protocol:interface, to remove\r
695 @param Interface The interface, of protocol:interface, to remove\r
162ed594 696\r
022c6d45 697 @retval EFI_INVALID_PARAMETER Protocol is NULL.\r
162ed594 698 @retval EFI_SUCCESS Protocol interface successfully uninstalled.\r
699\r
700**/\r
28a00297 701EFI_STATUS\r
702EFIAPI\r
703CoreUninstallProtocolInterface (\r
704 IN EFI_HANDLE UserHandle,\r
705 IN EFI_GUID *Protocol,\r
706 IN VOID *Interface\r
707 )\r
28a00297 708{\r
709 EFI_STATUS Status;\r
710 IHANDLE *Handle;\r
711 PROTOCOL_INTERFACE *Prot;\r
712\r
713 //\r
714 // Check that Protocol is valid\r
715 //\r
716 if (Protocol == NULL) {\r
717 return EFI_INVALID_PARAMETER;\r
718 }\r
719\r
720 //\r
721 // Check that UserHandle is a valid handle\r
722 //\r
723 Status = CoreValidateHandle (UserHandle);\r
724 if (EFI_ERROR (Status)) {\r
725 return Status;\r
726 }\r
727\r
728 //\r
729 // Lock the protocol database\r
730 //\r
731 CoreAcquireProtocolLock ();\r
732\r
733 //\r
734 // Check that Protocol exists on UserHandle, and Interface matches the interface in the database\r
735 //\r
736 Prot = CoreFindProtocolInterface (UserHandle, Protocol, Interface);\r
737 if (Prot == NULL) {\r
738 Status = EFI_NOT_FOUND;\r
739 goto Done;\r
740 }\r
741\r
742 //\r
743 // Attempt to disconnect all drivers that are using the protocol interface that is about to be removed\r
744 //\r
745 Status = CoreDisconnectControllersUsingProtocolInterface (\r
746 UserHandle,\r
747 Prot\r
748 );\r
749 if (EFI_ERROR (Status)) {\r
750 //\r
751 // One or more drivers refused to release, so return the error\r
752 //\r
753 goto Done;\r
754 }\r
755\r
756 //\r
757 // Remove the protocol interface from the protocol\r
758 //\r
759 Status = EFI_NOT_FOUND;\r
760 Handle = (IHANDLE *)UserHandle;\r
761 Prot = CoreRemoveInterfaceFromProtocol (Handle, Protocol, Interface);\r
762\r
763 if (Prot != NULL) {\r
764 //\r
765 // Update the Key to show that the handle has been created/modified\r
766 //\r
767 gHandleDatabaseKey++;\r
768 Handle->Key = gHandleDatabaseKey;\r
022c6d45 769\r
28a00297 770 //\r
771 // Remove the protocol interface from the handle\r
772 //\r
773 RemoveEntryList (&Prot->Link);\r
774\r
775 //\r
776 // Free the memory\r
777 //\r
778 Prot->Signature = 0;\r
779 CoreFreePool (Prot);\r
780 Status = EFI_SUCCESS;\r
781 }\r
782\r
783 //\r
784 // If there are no more handlers for the handle, free the handle\r
785 //\r
786 if (IsListEmpty (&Handle->Protocols)) {\r
787 Handle->Signature = 0;\r
788 RemoveEntryList (&Handle->AllHandles);\r
789 CoreFreePool (Handle);\r
790 }\r
791\r
022c6d45 792Done:\r
28a00297 793 //\r
794 // Done, unlock the database and return\r
795 //\r
796 CoreReleaseProtocolLock ();\r
797 return Status;\r
798}\r
799\r
800\r
801\r
162ed594 802\r
803/**\r
804 Uninstalls a list of protocol interface in the boot services environment.\r
805 This function calls UnisatllProtocolInterface() in a loop. This is\r
806 basically a lib function to save space.\r
807\r
022c6d45 808 @param Handle The handle to uninstall the protocol\r
809 @param ... EFI_GUID followed by protocol instance. A NULL\r
810 terminates the list. The pairs are the\r
811 arguments to UninstallProtocolInterface(). All\r
812 the protocols are added to Handle.\r
162ed594 813\r
814 @return Status code\r
815\r
816**/\r
28a00297 817EFI_STATUS\r
818EFIAPI\r
819CoreUninstallMultipleProtocolInterfaces (\r
820 IN EFI_HANDLE Handle,\r
821 ...\r
822 )\r
28a00297 823{\r
824 EFI_STATUS Status;\r
162ed594 825 VA_LIST Args;\r
28a00297 826 EFI_GUID *Protocol;\r
827 VOID *Interface;\r
828 UINTN Index;\r
829\r
162ed594 830 VA_START (Args, Handle);\r
28a00297 831 for (Index = 0, Status = EFI_SUCCESS; !EFI_ERROR (Status); Index++) {\r
832 //\r
833 // If protocol is NULL, then it's the end of the list\r
834 //\r
162ed594 835 Protocol = VA_ARG (Args, EFI_GUID *);\r
28a00297 836 if (Protocol == NULL) {\r
837 break;\r
838 }\r
839\r
162ed594 840 Interface = VA_ARG (Args, VOID *);\r
28a00297 841\r
842 //\r
843 // Uninstall it\r
844 //\r
845 Status = CoreUninstallProtocolInterface (Handle, Protocol, Interface);\r
846 }\r
847\r
848 //\r
849 // If there was an error, add all the interfaces that were\r
850 // uninstalled without any errors\r
851 //\r
852 if (EFI_ERROR (Status)) {\r
853 //\r
854 // Reset the va_arg back to the first argument.\r
855 //\r
162ed594 856 VA_START (Args, Handle);\r
28a00297 857 for (; Index > 1; Index--) {\r
162ed594 858 Protocol = VA_ARG(Args, EFI_GUID *);\r
859 Interface = VA_ARG(Args, VOID *);\r
28a00297 860 CoreInstallProtocolInterface (&Handle, Protocol, EFI_NATIVE_INTERFACE, Interface);\r
022c6d45 861 }\r
28a00297 862 }\r
863\r
864 return Status;\r
022c6d45 865}\r
28a00297 866\r
162ed594 867\r
868/**\r
869 Locate a certain GUID protocol interface in a Handle's protocols.\r
870\r
022c6d45 871 @param UserHandle The handle to obtain the protocol interface on\r
872 @param Protocol The GUID of the protocol\r
162ed594 873\r
874 @return The requested protocol interface for the handle\r
875\r
876**/\r
28a00297 877PROTOCOL_INTERFACE *\r
878CoreGetProtocolInterface (\r
879 IN EFI_HANDLE UserHandle,\r
880 IN EFI_GUID *Protocol\r
881 )\r
28a00297 882{\r
883 EFI_STATUS Status;\r
884 PROTOCOL_ENTRY *ProtEntry;\r
885 PROTOCOL_INTERFACE *Prot;\r
886 IHANDLE *Handle;\r
887 LIST_ENTRY *Link;\r
888\r
889 Status = CoreValidateHandle (UserHandle);\r
890 if (EFI_ERROR (Status)) {\r
891 return NULL;\r
892 }\r
022c6d45 893\r
28a00297 894 Handle = (IHANDLE *)UserHandle;\r
895\r
896 //\r
897 // Look at each protocol interface for a match\r
898 //\r
899 for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {\r
900 Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);\r
901 ProtEntry = Prot->Protocol;\r
902 if (CompareGuid (&ProtEntry->ProtocolID, Protocol)) {\r
903 return Prot;\r
904 }\r
905 }\r
906 return NULL;\r
907}\r
908\r
909\r
162ed594 910\r
911/**\r
912 Queries a handle to determine if it supports a specified protocol.\r
913\r
022c6d45 914 @param UserHandle The handle being queried.\r
915 @param Protocol The published unique identifier of the protocol.\r
916 @param Interface Supplies the address where a pointer to the\r
917 corresponding Protocol Interface is returned.\r
162ed594 918\r
11074aab 919 @retval EFI_SUCCESS The interface information for the specified protocol was returned.\r
920 @retval EFI_UNSUPPORTED The device does not support the specified protocol.\r
921 @retval EFI_INVALID_PARAMETER Handle is not a valid EFI_HANDLE..\r
922 @retval EFI_INVALID_PARAMETER Protocol is NULL.\r
923 @retval EFI_INVALID_PARAMETER Interface is NULL.\r
162ed594 924\r
925**/\r
28a00297 926EFI_STATUS\r
927EFIAPI\r
928CoreHandleProtocol (\r
929 IN EFI_HANDLE UserHandle,\r
930 IN EFI_GUID *Protocol,\r
931 OUT VOID **Interface\r
932 )\r
28a00297 933{\r
934 return CoreOpenProtocol (\r
022c6d45 935 UserHandle,\r
936 Protocol,\r
937 Interface,\r
938 gDxeCoreImageHandle,\r
939 NULL,\r
28a00297 940 EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL\r
941 );\r
942}\r
943\r
944\r
162ed594 945\r
946/**\r
947 Locates the installed protocol handler for the handle, and\r
948 invokes it to obtain the protocol interface. Usage information\r
949 is registered in the protocol data base.\r
950\r
022c6d45 951 @param UserHandle The handle to obtain the protocol interface on\r
952 @param Protocol The ID of the protocol\r
953 @param Interface The location to return the protocol interface\r
954 @param ImageHandle The handle of the Image that is opening the\r
955 protocol interface specified by Protocol and\r
956 Interface.\r
957 @param ControllerHandle The controller handle that is requiring this\r
958 interface.\r
959 @param Attributes The open mode of the protocol interface\r
960 specified by Handle and Protocol.\r
961\r
962 @retval EFI_INVALID_PARAMETER Protocol is NULL.\r
162ed594 963 @retval EFI_SUCCESS Get the protocol interface.\r
964\r
965**/\r
28a00297 966EFI_STATUS\r
967EFIAPI\r
968CoreOpenProtocol (\r
969 IN EFI_HANDLE UserHandle,\r
970 IN EFI_GUID *Protocol,\r
971 OUT VOID **Interface OPTIONAL,\r
972 IN EFI_HANDLE ImageHandle,\r
973 IN EFI_HANDLE ControllerHandle,\r
974 IN UINT32 Attributes\r
975 )\r
28a00297 976{\r
977 EFI_STATUS Status;\r
978 PROTOCOL_INTERFACE *Prot;\r
979 LIST_ENTRY *Link;\r
980 OPEN_PROTOCOL_DATA *OpenData;\r
981 BOOLEAN ByDriver;\r
982 BOOLEAN Exclusive;\r
983 BOOLEAN Disconnect;\r
984 BOOLEAN ExactMatch;\r
985\r
986 //\r
987 // Check for invalid Protocol\r
988 //\r
989 if (Protocol == NULL) {\r
990 return EFI_INVALID_PARAMETER;\r
991 }\r
992\r
993 //\r
994 // Check for invalid Interface\r
995 //\r
996 if (Attributes != EFI_OPEN_PROTOCOL_TEST_PROTOCOL) {\r
997 if (Interface == NULL) {\r
998 return EFI_INVALID_PARAMETER;\r
999 } else {\r
1000 *Interface = NULL;\r
1001 }\r
1002 }\r
022c6d45 1003\r
28a00297 1004 //\r
1005 // Check for invalid UserHandle\r
1006 //\r
1007 Status = CoreValidateHandle (UserHandle);\r
1008 if (EFI_ERROR (Status)) {\r
1009 return Status;\r
1010 }\r
1011\r
1012 //\r
1013 // Check for invalid Attributes\r
1014 //\r
1015 switch (Attributes) {\r
1016 case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER :\r
1017 Status = CoreValidateHandle (ImageHandle);\r
1018 if (EFI_ERROR (Status)) {\r
1019 return Status;\r
1020 }\r
1021 Status = CoreValidateHandle (ControllerHandle);\r
1022 if (EFI_ERROR (Status)) {\r
1023 return Status;\r
1024 }\r
1025 if (UserHandle == ControllerHandle) {\r
1026 return EFI_INVALID_PARAMETER;\r
1027 }\r
1028 break;\r
1029 case EFI_OPEN_PROTOCOL_BY_DRIVER :\r
1030 case EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE :\r
1031 Status = CoreValidateHandle (ImageHandle);\r
1032 if (EFI_ERROR (Status)) {\r
1033 return Status;\r
1034 }\r
1035 Status = CoreValidateHandle (ControllerHandle);\r
1036 if (EFI_ERROR (Status)) {\r
1037 return Status;\r
1038 }\r
1039 break;\r
1040 case EFI_OPEN_PROTOCOL_EXCLUSIVE :\r
1041 Status = CoreValidateHandle (ImageHandle);\r
1042 if (EFI_ERROR (Status)) {\r
1043 return Status;\r
1044 }\r
1045 break;\r
1046 case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL :\r
1047 case EFI_OPEN_PROTOCOL_GET_PROTOCOL :\r
1048 case EFI_OPEN_PROTOCOL_TEST_PROTOCOL :\r
1049 break;\r
1050 default:\r
1051 return EFI_INVALID_PARAMETER;\r
1052 }\r
1053\r
1054 //\r
1055 // Lock the protocol database\r
1056 //\r
1057 CoreAcquireProtocolLock ();\r
1058\r
1059 //\r
1060 // Look at each protocol interface for a match\r
1061 //\r
1062 Prot = CoreGetProtocolInterface (UserHandle, Protocol);\r
1063 if (Prot == NULL) {\r
1064 Status = EFI_UNSUPPORTED;\r
1065 goto Done;\r
1066 }\r
1067\r
1068 //\r
1069 // This is the protocol interface entry for this protocol\r
022c6d45 1070 //\r
28a00297 1071 if (Attributes != EFI_OPEN_PROTOCOL_TEST_PROTOCOL) {\r
1072 *Interface = Prot->Interface;\r
1073 }\r
1074 Status = EFI_SUCCESS;\r
1075\r
1076 ByDriver = FALSE;\r
1077 Exclusive = FALSE;\r
1078 for ( Link = Prot->OpenList.ForwardLink; Link != &Prot->OpenList; Link = Link->ForwardLink) {\r
1079 OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);\r
022c6d45 1080 ExactMatch = (BOOLEAN)((OpenData->AgentHandle == ImageHandle) &&\r
28a00297 1081 (OpenData->Attributes == Attributes) &&\r
1082 (OpenData->ControllerHandle == ControllerHandle));\r
1083 if (OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) {\r
1084 ByDriver = TRUE;\r
1085 if (ExactMatch) {\r
1086 Status = EFI_ALREADY_STARTED;\r
1087 goto Done;\r
1088 }\r
1089 }\r
1090 if (OpenData->Attributes & EFI_OPEN_PROTOCOL_EXCLUSIVE) {\r
1091 Exclusive = TRUE;\r
1092 } else if (ExactMatch) {\r
1093 OpenData->OpenCount++;\r
1094 Status = EFI_SUCCESS;\r
1095 goto Done;\r
1096 }\r
1097 }\r
1098\r
1099 //\r
1100 // ByDriver TRUE -> A driver is managing (UserHandle, Protocol)\r
1101 // ByDriver FALSE -> There are no drivers managing (UserHandle, Protocol)\r
1102 // Exclusive TRUE -> Something has exclusive access to (UserHandle, Protocol)\r
1103 // Exclusive FALSE -> Nothing has exclusive access to (UserHandle, Protocol)\r
1104 //\r
1105\r
1106 switch (Attributes) {\r
1107 case EFI_OPEN_PROTOCOL_BY_DRIVER :\r
1108 if (Exclusive || ByDriver) {\r
1109 Status = EFI_ACCESS_DENIED;\r
1110 goto Done;\r
1111 }\r
1112 break;\r
1113 case EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE :\r
1114 case EFI_OPEN_PROTOCOL_EXCLUSIVE :\r
1115 if (Exclusive) {\r
1116 Status = EFI_ACCESS_DENIED;\r
1117 goto Done;\r
1118 }\r
1119 if (ByDriver) {\r
1120 do {\r
1121 Disconnect = FALSE;\r
1122 for ( Link = Prot->OpenList.ForwardLink; (Link != &Prot->OpenList) && (!Disconnect); Link = Link->ForwardLink) {\r
1123 OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);\r
1124 if (OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) {\r
1125 Disconnect = TRUE;\r
1126 CoreReleaseProtocolLock ();\r
1127 Status = CoreDisconnectController (UserHandle, OpenData->AgentHandle, NULL);\r
1128 CoreAcquireProtocolLock ();\r
1129 if (EFI_ERROR (Status)) {\r
1130 Status = EFI_ACCESS_DENIED;\r
1131 goto Done;\r
1132 }\r
1133 }\r
1134 }\r
1135 } while (Disconnect);\r
022c6d45 1136 }\r
28a00297 1137 break;\r
1138 case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER :\r
1139 case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL :\r
1140 case EFI_OPEN_PROTOCOL_GET_PROTOCOL :\r
1141 case EFI_OPEN_PROTOCOL_TEST_PROTOCOL :\r
1142 break;\r
1143 }\r
1144\r
1145 if (ImageHandle == NULL) {\r
1146 Status = EFI_SUCCESS;\r
1147 goto Done;\r
1148 }\r
1149 //\r
1150 // Create new entry\r
1151 //\r
9c4ac31c 1152 OpenData = AllocatePool (sizeof(OPEN_PROTOCOL_DATA));\r
28a00297 1153 if (OpenData == NULL) {\r
1154 Status = EFI_OUT_OF_RESOURCES;\r
1155 } else {\r
1156 OpenData->Signature = OPEN_PROTOCOL_DATA_SIGNATURE;\r
1157 OpenData->AgentHandle = ImageHandle;\r
1158 OpenData->ControllerHandle = ControllerHandle;\r
1159 OpenData->Attributes = Attributes;\r
1160 OpenData->OpenCount = 1;\r
1161 InsertTailList (&Prot->OpenList, &OpenData->Link);\r
1162 Prot->OpenListCount++;\r
1163 Status = EFI_SUCCESS;\r
1164 }\r
1165\r
1166Done:\r
1167 //\r
1168 // Done. Release the database lock are return\r
1169 //\r
1170 CoreReleaseProtocolLock ();\r
1171 return Status;\r
1172}\r
1173\r
1174\r
162ed594 1175\r
1176/**\r
1177 Closes a protocol on a handle that was opened using OpenProtocol().\r
1178\r
022c6d45 1179 @param UserHandle The handle for the protocol interface that was\r
1180 previously opened with OpenProtocol(), and is\r
1181 now being closed.\r
1182 @param Protocol The published unique identifier of the protocol.\r
1183 It is the caller's responsibility to pass in a\r
1184 valid GUID.\r
1185 @param AgentHandle The handle of the agent that is closing the\r
1186 protocol interface.\r
1187 @param ControllerHandle If the agent that opened a protocol is a driver\r
1188 that follows the EFI Driver Model, then this\r
1189 parameter is the controller handle that required\r
1190 the protocol interface. If the agent does not\r
1191 follow the EFI Driver Model, then this parameter\r
1192 is optional and may be NULL.\r
1193\r
1194 @retval EFI_SUCCESS The protocol instance was closed.\r
1195 @retval EFI_INVALID_PARAMETER Handle, AgentHandle or ControllerHandle is not a\r
1196 valid EFI_HANDLE.\r
1197 @retval EFI_NOT_FOUND Can not find the specified protocol or\r
162ed594 1198 AgentHandle.\r
1199\r
1200**/\r
28a00297 1201EFI_STATUS\r
1202EFIAPI\r
1203CoreCloseProtocol (\r
1204 IN EFI_HANDLE UserHandle,\r
1205 IN EFI_GUID *Protocol,\r
1206 IN EFI_HANDLE AgentHandle,\r
022c6d45 1207 IN EFI_HANDLE ControllerHandle\r
28a00297 1208 )\r
28a00297 1209{\r
1210 EFI_STATUS Status;\r
1211 PROTOCOL_INTERFACE *ProtocolInterface;\r
1212 LIST_ENTRY *Link;\r
1213 OPEN_PROTOCOL_DATA *OpenData;\r
1214\r
1215 //\r
1216 // Check for invalid parameters\r
1217 //\r
1218 Status = CoreValidateHandle (UserHandle);\r
1219 if (EFI_ERROR (Status)) {\r
1220 return Status;\r
1221 }\r
1222 Status = CoreValidateHandle (AgentHandle);\r
1223 if (EFI_ERROR (Status)) {\r
1224 return Status;\r
1225 }\r
4008328a 1226 if (ControllerHandle != NULL) {\r
28a00297 1227 Status = CoreValidateHandle (ControllerHandle);\r
1228 if (EFI_ERROR (Status)) {\r
1229 return Status;\r
1230 }\r
1231 }\r
1232 if (Protocol == NULL) {\r
1233 return EFI_INVALID_PARAMETER;\r
1234 }\r
1235\r
1236 //\r
1237 // Lock the protocol database\r
1238 //\r
1239 CoreAcquireProtocolLock ();\r
1240\r
1241 //\r
1242 // Look at each protocol interface for a match\r
1243 //\r
1244 Status = EFI_NOT_FOUND;\r
1245 ProtocolInterface = CoreGetProtocolInterface (UserHandle, Protocol);\r
1246 if (ProtocolInterface == NULL) {\r
1247 goto Done;\r
1248 }\r
1249\r
1250 //\r
1251 // Walk the Open data base looking for AgentHandle\r
1252 //\r
1253 Link = ProtocolInterface->OpenList.ForwardLink;\r
1254 while (Link != &ProtocolInterface->OpenList) {\r
1255 OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);\r
1256 Link = Link->ForwardLink;\r
1257 if ((OpenData->AgentHandle == AgentHandle) && (OpenData->ControllerHandle == ControllerHandle)) {\r
022c6d45 1258 RemoveEntryList (&OpenData->Link);\r
28a00297 1259 ProtocolInterface->OpenListCount--;\r
1260 CoreFreePool (OpenData);\r
1261 Status = EFI_SUCCESS;\r
1262 }\r
1263 }\r
1264\r
1265Done:\r
1266 //\r
1267 // Done. Release the database lock and return.\r
1268 //\r
1269 CoreReleaseProtocolLock ();\r
1270 return Status;\r
1271}\r
1272\r
1273\r
1274\r
162ed594 1275\r
1276/**\r
1277 Return information about Opened protocols in the system\r
1278\r
022c6d45 1279 @param UserHandle The handle to close the protocol interface on\r
1280 @param Protocol The ID of the protocol\r
11074aab 1281 @param EntryBuffer A pointer to a buffer of open protocol information in the\r
1282 form of EFI_OPEN_PROTOCOL_INFORMATION_ENTRY structures.\r
162ed594 1283 @param EntryCount Number of EntryBuffer entries\r
1284\r
11074aab 1285 @retval EFI_SUCCESS The open protocol information was returned in EntryBuffer, \r
1286 and the number of entries was returned EntryCount.\r
1287 @retval EFI_NOT_FOUND Handle does not support the protocol specified by Protocol.\r
1288 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to allocate EntryBuffer.\r
1289\r
162ed594 1290**/\r
28a00297 1291EFI_STATUS\r
1292EFIAPI\r
1293CoreOpenProtocolInformation (\r
1294 IN EFI_HANDLE UserHandle,\r
1295 IN EFI_GUID *Protocol,\r
1296 OUT EFI_OPEN_PROTOCOL_INFORMATION_ENTRY **EntryBuffer,\r
1297 OUT UINTN *EntryCount\r
1298 )\r
28a00297 1299{\r
1300 EFI_STATUS Status;\r
1301 PROTOCOL_INTERFACE *ProtocolInterface;\r
1302 LIST_ENTRY *Link;\r
1303 OPEN_PROTOCOL_DATA *OpenData;\r
1304 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *Buffer;\r
1305 UINTN Count;\r
1306 UINTN Size;\r
1307\r
1308 *EntryBuffer = NULL;\r
1309 *EntryCount = 0;\r
1310\r
1311 //\r
1312 // Lock the protocol database\r
1313 //\r
1314 CoreAcquireProtocolLock ();\r
1315\r
1316 //\r
1317 // Look at each protocol interface for a match\r
1318 //\r
1319 Status = EFI_NOT_FOUND;\r
1320 ProtocolInterface = CoreGetProtocolInterface (UserHandle, Protocol);\r
1321 if (ProtocolInterface == NULL) {\r
1322 goto Done;\r
1323 }\r
1324\r
1325 //\r
1326 // Count the number of Open Entries\r
1327 //\r
022c6d45 1328 for ( Link = ProtocolInterface->OpenList.ForwardLink, Count = 0;\r
28a00297 1329 (Link != &ProtocolInterface->OpenList) ;\r
1330 Link = Link->ForwardLink ) {\r
1331 Count++;\r
022c6d45 1332 }\r
28a00297 1333\r
1334 ASSERT (Count == ProtocolInterface->OpenListCount);\r
1335\r
1336 if (Count == 0) {\r
1337 Size = sizeof(EFI_OPEN_PROTOCOL_INFORMATION_ENTRY);\r
1338 } else {\r
1339 Size = Count * sizeof(EFI_OPEN_PROTOCOL_INFORMATION_ENTRY);\r
1340 }\r
1341\r
9c4ac31c 1342 Buffer = AllocatePool (Size);\r
28a00297 1343 if (Buffer == NULL) {\r
1344 Status = EFI_OUT_OF_RESOURCES;\r
1345 goto Done;\r
1346 }\r
1347\r
1348 Status = EFI_SUCCESS;\r
022c6d45 1349 for ( Link = ProtocolInterface->OpenList.ForwardLink, Count = 0;\r
28a00297 1350 (Link != &ProtocolInterface->OpenList);\r
1351 Link = Link->ForwardLink, Count++ ) {\r
1352 OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);\r
1353\r
1354 Buffer[Count].AgentHandle = OpenData->AgentHandle;\r
1355 Buffer[Count].ControllerHandle = OpenData->ControllerHandle;\r
1356 Buffer[Count].Attributes = OpenData->Attributes;\r
1357 Buffer[Count].OpenCount = OpenData->OpenCount;\r
022c6d45 1358 }\r
28a00297 1359\r
1360 *EntryBuffer = Buffer;\r
1361 *EntryCount = Count;\r
022c6d45 1362\r
28a00297 1363Done:\r
1364 //\r
1439777e 1365 // Done. Release the database lock.\r
28a00297 1366 //\r
1367 CoreReleaseProtocolLock ();\r
1368 return Status;\r
1369}\r
1370\r
1371\r
1372\r
162ed594 1373\r
1374/**\r
1375 Retrieves the list of protocol interface GUIDs that are installed on a handle in a buffer allocated\r
1376 from pool.\r
1377\r
022c6d45 1378 @param UserHandle The handle from which to retrieve the list of\r
1379 protocol interface GUIDs.\r
1380 @param ProtocolBuffer A pointer to the list of protocol interface GUID\r
1381 pointers that are installed on Handle.\r
1382 @param ProtocolBufferCount A pointer to the number of GUID pointers present\r
1383 in ProtocolBuffer.\r
1384\r
1385 @retval EFI_SUCCESS The list of protocol interface GUIDs installed\r
1386 on Handle was returned in ProtocolBuffer. The\r
1387 number of protocol interface GUIDs was returned\r
1388 in ProtocolBufferCount.\r
1389 @retval EFI_INVALID_PARAMETER Handle is NULL.\r
1390 @retval EFI_INVALID_PARAMETER Handle is not a valid EFI_HANDLE.\r
1391 @retval EFI_INVALID_PARAMETER ProtocolBuffer is NULL.\r
1392 @retval EFI_INVALID_PARAMETER ProtocolBufferCount is NULL.\r
1393 @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the\r
162ed594 1394 results.\r
1395\r
1396**/\r
28a00297 1397EFI_STATUS\r
1398EFIAPI\r
1399CoreProtocolsPerHandle (\r
1400 IN EFI_HANDLE UserHandle,\r
1401 OUT EFI_GUID ***ProtocolBuffer,\r
1402 OUT UINTN *ProtocolBufferCount\r
1403 )\r
28a00297 1404{\r
1405 EFI_STATUS Status;\r
1406 IHANDLE *Handle;\r
1407 PROTOCOL_INTERFACE *Prot;\r
1408 LIST_ENTRY *Link;\r
1409 UINTN ProtocolCount;\r
1410 EFI_GUID **Buffer;\r
1411\r
1412 Status = CoreValidateHandle (UserHandle);\r
1413 if (EFI_ERROR (Status)) {\r
1414 return Status;\r
1415 }\r
1416\r
1417 Handle = (IHANDLE *)UserHandle;\r
1418\r
1419 if (ProtocolBuffer == NULL) {\r
1420 return EFI_INVALID_PARAMETER;\r
1421 }\r
1422\r
1423 if (ProtocolBufferCount == NULL) {\r
1424 return EFI_INVALID_PARAMETER;\r
1425 }\r
1426\r
1427 *ProtocolBufferCount = 0;\r
1428\r
1429 ProtocolCount = 0;\r
1430\r
1431 CoreAcquireProtocolLock ();\r
022c6d45 1432\r
28a00297 1433 for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {\r
1434 ProtocolCount++;\r
1435 }\r
1436\r
1437 //\r
1438 // If there are no protocol interfaces installed on Handle, then Handle is not a valid EFI_HANDLE\r
1439 //\r
1440 if (ProtocolCount == 0) {\r
1441 Status = EFI_INVALID_PARAMETER;\r
1442 goto Done;\r
1443 }\r
1444\r
9c4ac31c 1445 Buffer = AllocatePool (sizeof (EFI_GUID *) * ProtocolCount);\r
28a00297 1446 if (Buffer == NULL) {\r
1447 Status = EFI_OUT_OF_RESOURCES;\r
1448 goto Done;\r
1449 }\r
1450\r
1451 *ProtocolBuffer = Buffer;\r
1452 *ProtocolBufferCount = ProtocolCount;\r
1453\r
1454 for ( Link = Handle->Protocols.ForwardLink, ProtocolCount = 0;\r
022c6d45 1455 Link != &Handle->Protocols;\r
28a00297 1456 Link = Link->ForwardLink, ProtocolCount++) {\r
1457 Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);\r
1458 Buffer[ProtocolCount] = &(Prot->Protocol->ProtocolID);\r
1459 }\r
1460 Status = EFI_SUCCESS;\r
1461\r
1462Done:\r
1463 CoreReleaseProtocolLock ();\r
1464 return Status;\r
1465}\r
1466\r
1467\r
28a00297 1468\r
162ed594 1469/**\r
28a00297 1470 return handle database key.\r
1471\r
28a00297 1472\r
162ed594 1473 @return Handle database key.\r
1474\r
1475**/\r
1476UINT64\r
1477CoreGetHandleDatabaseKey (\r
1478 VOID\r
1479 )\r
28a00297 1480{\r
1481 return gHandleDatabaseKey;\r
1482}\r
1483\r
1484\r
28a00297 1485\r
162ed594 1486/**\r
28a00297 1487 Go connect any handles that were created or modified while a image executed.\r
1488\r
022c6d45 1489 @param Key The Key to show that the handle has been\r
162ed594 1490 created/modified\r
28a00297 1491\r
162ed594 1492**/\r
1493VOID\r
1494CoreConnectHandlesByKey (\r
1495 UINT64 Key\r
1496 )\r
28a00297 1497{\r
1498 UINTN Count;\r
1499 LIST_ENTRY *Link;\r
1500 EFI_HANDLE *HandleBuffer;\r
1501 IHANDLE *Handle;\r
1502 UINTN Index;\r
1503\r
1504 //\r
1505 // Lock the protocol database\r
1506 //\r
1507 CoreAcquireProtocolLock ();\r
1508\r
1509 for (Link = gHandleList.ForwardLink, Count = 0; Link != &gHandleList; Link = Link->ForwardLink) {\r
1510 Handle = CR (Link, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE);\r
1511 if (Handle->Key > Key) {\r
1512 Count++;\r
1513 }\r
1514 }\r
1515\r
9c4ac31c 1516 HandleBuffer = AllocatePool (Count * sizeof (EFI_HANDLE));\r
28a00297 1517 if (HandleBuffer == NULL) {\r
1518 CoreReleaseProtocolLock ();\r
1519 return;\r
1520 }\r
022c6d45 1521\r
28a00297 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 HandleBuffer[Count++] = Handle;\r
1526 }\r
1527 }\r
1528\r
1529 //\r
1530 // Unlock the protocol database\r
1531 //\r
1532 CoreReleaseProtocolLock ();\r
1533\r
1534 //\r
1535 // Connect all handles whose Key value is greater than Key\r
1536 //\r
1537 for (Index = 0; Index < Count; Index++) {\r
1538 CoreConnectController (HandleBuffer[Index], NULL, NULL, TRUE);\r
1539 }\r
022c6d45 1540\r
28a00297 1541 CoreFreePool(HandleBuffer);\r
1542}\r