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