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