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