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