]> 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
5fc3889b 75 LIST_ENTRY *Link;\r
28a00297 76\r
5fc3889b 77 if (UserHandle == NULL) {\r
28a00297 78 return EFI_INVALID_PARAMETER;\r
79 }\r
5fc3889b
RN
80\r
81 for (Link = gHandleList.BackLink; Link != &gHandleList; Link = Link->BackLink) {\r
82 Handle = CR (Link, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE);\r
83 if (Handle == (IHANDLE *) UserHandle) {\r
84 return EFI_SUCCESS;\r
85 }\r
28a00297 86 }\r
5fc3889b
RN
87\r
88 return EFI_INVALID_PARAMETER;\r
28a00297 89}\r
90\r
91\r
28a00297 92\r
162ed594 93/**\r
28a00297 94 Finds the protocol entry for the requested protocol.\r
28a00297 95 The gProtocolDatabaseLock must be owned\r
96\r
022c6d45 97 @param Protocol The ID of the protocol\r
98 @param Create Create a new entry if not found\r
28a00297 99\r
162ed594 100 @return Protocol entry\r
28a00297 101\r
162ed594 102**/\r
103PROTOCOL_ENTRY *\r
104CoreFindProtocolEntry (\r
105 IN EFI_GUID *Protocol,\r
106 IN BOOLEAN Create\r
107 )\r
28a00297 108{\r
109 LIST_ENTRY *Link;\r
110 PROTOCOL_ENTRY *Item;\r
111 PROTOCOL_ENTRY *ProtEntry;\r
112\r
113 ASSERT_LOCKED(&gProtocolDatabaseLock);\r
114\r
115 //\r
116 // Search the database for the matching GUID\r
117 //\r
118\r
119 ProtEntry = NULL;\r
022c6d45 120 for (Link = mProtocolDatabase.ForwardLink;\r
121 Link != &mProtocolDatabase;\r
28a00297 122 Link = Link->ForwardLink) {\r
123\r
124 Item = CR(Link, PROTOCOL_ENTRY, AllEntries, PROTOCOL_ENTRY_SIGNATURE);\r
125 if (CompareGuid (&Item->ProtocolID, Protocol)) {\r
126\r
127 //\r
128 // This is the protocol entry\r
129 //\r
130\r
131 ProtEntry = Item;\r
132 break;\r
133 }\r
134 }\r
135\r
136 //\r
022c6d45 137 // If the protocol entry was not found and Create is TRUE, then\r
28a00297 138 // allocate a new entry\r
022c6d45 139 //\r
28a00297 140 if ((ProtEntry == NULL) && Create) {\r
9c4ac31c 141 ProtEntry = AllocatePool (sizeof(PROTOCOL_ENTRY));\r
022c6d45 142\r
28a00297 143 if (ProtEntry != NULL) {\r
144 //\r
145 // Initialize new protocol entry structure\r
146 //\r
147 ProtEntry->Signature = PROTOCOL_ENTRY_SIGNATURE;\r
e94a9ff7 148 CopyGuid ((VOID *)&ProtEntry->ProtocolID, Protocol);\r
28a00297 149 InitializeListHead (&ProtEntry->Protocols);\r
150 InitializeListHead (&ProtEntry->Notify);\r
151\r
152 //\r
153 // Add it to protocol database\r
154 //\r
155 InsertTailList (&mProtocolDatabase, &ProtEntry->AllEntries);\r
156 }\r
157 }\r
158\r
159 return ProtEntry;\r
160}\r
161\r
162\r
162ed594 163\r
164/**\r
165 Finds the protocol instance for the requested handle and protocol.\r
166 Note: This function doesn't do parameters checking, it's caller's responsibility\r
167 to pass in valid parameters.\r
168\r
022c6d45 169 @param Handle The handle to search the protocol on\r
170 @param Protocol GUID of the protocol\r
171 @param Interface The interface for the protocol being searched\r
162ed594 172\r
173 @return Protocol instance (NULL: Not found)\r
174\r
175**/\r
28a00297 176PROTOCOL_INTERFACE *\r
177CoreFindProtocolInterface (\r
178 IN IHANDLE *Handle,\r
179 IN EFI_GUID *Protocol,\r
180 IN VOID *Interface\r
181 )\r
28a00297 182{\r
183 PROTOCOL_INTERFACE *Prot;\r
184 PROTOCOL_ENTRY *ProtEntry;\r
185 LIST_ENTRY *Link;\r
186\r
187 ASSERT_LOCKED(&gProtocolDatabaseLock);\r
188 Prot = NULL;\r
189\r
190 //\r
191 // Lookup the protocol entry for this protocol ID\r
192 //\r
193\r
194 ProtEntry = CoreFindProtocolEntry (Protocol, FALSE);\r
195 if (ProtEntry != NULL) {\r
196\r
197 //\r
198 // Look at each protocol interface for any matches\r
199 //\r
200 for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link=Link->ForwardLink) {\r
201\r
202 //\r
203 // If this protocol interface matches, remove it\r
204 //\r
205 Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);\r
206 if (Prot->Interface == Interface && Prot->Protocol == ProtEntry) {\r
207 break;\r
208 }\r
209\r
210 Prot = NULL;\r
211 }\r
212 }\r
213\r
214 return Prot;\r
215}\r
216\r
28a00297 217\r
162ed594 218/**\r
28a00297 219 Removes an event from a register protocol notify list on a protocol.\r
220\r
022c6d45 221 @param Event The event to search for in the protocol\r
222 database.\r
28a00297 223\r
162ed594 224 @return EFI_SUCCESS if the event was found and removed.\r
225 @return EFI_NOT_FOUND if the event was not found in the protocl database.\r
28a00297 226\r
162ed594 227**/\r
162ed594 228EFI_STATUS\r
229CoreUnregisterProtocolNotifyEvent (\r
230 IN EFI_EVENT Event\r
231 )\r
28a00297 232{\r
233 LIST_ENTRY *Link;\r
234 PROTOCOL_ENTRY *ProtEntry;\r
235 LIST_ENTRY *NotifyLink;\r
236 PROTOCOL_NOTIFY *ProtNotify;\r
237\r
238 CoreAcquireProtocolLock ();\r
239\r
022c6d45 240 for ( Link = mProtocolDatabase.ForwardLink;\r
241 Link != &mProtocolDatabase;\r
28a00297 242 Link = Link->ForwardLink) {\r
243\r
244 ProtEntry = CR(Link, PROTOCOL_ENTRY, AllEntries, PROTOCOL_ENTRY_SIGNATURE);\r
245\r
022c6d45 246 for ( NotifyLink = ProtEntry->Notify.ForwardLink;\r
247 NotifyLink != &ProtEntry->Notify;\r
28a00297 248 NotifyLink = NotifyLink->ForwardLink) {\r
249\r
250 ProtNotify = CR(NotifyLink, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE);\r
251\r
252 if (ProtNotify->Event == Event) {\r
253 RemoveEntryList(&ProtNotify->Link);\r
254 CoreFreePool(ProtNotify);\r
255 CoreReleaseProtocolLock ();\r
256 return EFI_SUCCESS;\r
257 }\r
258 }\r
259 }\r
260\r
261 CoreReleaseProtocolLock ();\r
262 return EFI_NOT_FOUND;\r
263}\r
264\r
265\r
28a00297 266\r
162ed594 267/**\r
28a00297 268 Removes all the events in the protocol database that match Event.\r
269\r
022c6d45 270 @param Event The event to search for in the protocol\r
271 database.\r
28a00297 272\r
162ed594 273 @return EFI_SUCCESS when done searching the entire database.\r
28a00297 274\r
162ed594 275**/\r
276EFI_STATUS\r
277CoreUnregisterProtocolNotify (\r
278 IN EFI_EVENT Event\r
279 )\r
28a00297 280{\r
281 EFI_STATUS Status;\r
282\r
283 do {\r
284 Status = CoreUnregisterProtocolNotifyEvent (Event);\r
285 } while (!EFI_ERROR (Status));\r
286\r
287 return EFI_SUCCESS;\r
288}\r
289\r
290\r
291\r
162ed594 292\r
293/**\r
294 Wrapper function to CoreInstallProtocolInterfaceNotify. This is the public API which\r
295 Calls the private one which contains a BOOLEAN parameter for notifications\r
296\r
022c6d45 297 @param UserHandle The handle to install the protocol handler on,\r
298 or NULL if a new handle is to be allocated\r
299 @param Protocol The protocol to add to the handle\r
300 @param InterfaceType Indicates whether Interface is supplied in\r
301 native form.\r
302 @param Interface The interface for the protocol being added\r
162ed594 303\r
304 @return Status code\r
305\r
306**/\r
28a00297 307EFI_STATUS\r
308EFIAPI\r
309CoreInstallProtocolInterface (\r
310 IN OUT EFI_HANDLE *UserHandle,\r
311 IN EFI_GUID *Protocol,\r
312 IN EFI_INTERFACE_TYPE InterfaceType,\r
313 IN VOID *Interface\r
314 )\r
28a00297 315{\r
316 return CoreInstallProtocolInterfaceNotify (\r
022c6d45 317 UserHandle,\r
318 Protocol,\r
319 InterfaceType,\r
320 Interface,\r
28a00297 321 TRUE\r
322 );\r
323}\r
324\r
162ed594 325\r
326/**\r
327 Installs a protocol interface into the boot services environment.\r
328\r
022c6d45 329 @param UserHandle The handle to install the protocol handler on,\r
330 or NULL if a new handle is to be allocated\r
331 @param Protocol The protocol to add to the handle\r
332 @param InterfaceType Indicates whether Interface is supplied in\r
333 native form.\r
334 @param Interface The interface for the protocol being added\r
335 @param Notify indicates whether notify the notification list\r
336 for this protocol\r
337\r
338 @retval EFI_INVALID_PARAMETER Invalid parameter\r
339 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate\r
162ed594 340 @retval EFI_SUCCESS Protocol interface successfully installed\r
341\r
342**/\r
28a00297 343EFI_STATUS\r
344CoreInstallProtocolInterfaceNotify (\r
345 IN OUT EFI_HANDLE *UserHandle,\r
346 IN EFI_GUID *Protocol,\r
347 IN EFI_INTERFACE_TYPE InterfaceType,\r
348 IN VOID *Interface,\r
349 IN BOOLEAN Notify\r
350 )\r
28a00297 351{\r
352 PROTOCOL_INTERFACE *Prot;\r
353 PROTOCOL_ENTRY *ProtEntry;\r
354 IHANDLE *Handle;\r
355 EFI_STATUS Status;\r
356 VOID *ExistingInterface;\r
357\r
358 //\r
359 // returns EFI_INVALID_PARAMETER if InterfaceType is invalid.\r
360 // Also added check for invalid UserHandle and Protocol pointers.\r
361 //\r
362 if (UserHandle == NULL || Protocol == NULL) {\r
363 return EFI_INVALID_PARAMETER;\r
364 }\r
365\r
366 if (InterfaceType != EFI_NATIVE_INTERFACE) {\r
367 return EFI_INVALID_PARAMETER;\r
368 }\r
369\r
370 //\r
371 // Print debug message\r
372 //\r
58125fb3 373 DEBUG((DEBUG_INFO, "InstallProtocolInterface: %g %p\n", Protocol, Interface));\r
28a00297 374\r
375 Status = EFI_OUT_OF_RESOURCES;\r
376 Prot = NULL;\r
377 Handle = NULL;\r
378\r
4008328a 379 if (*UserHandle != NULL) {\r
28a00297 380 Status = CoreHandleProtocol (*UserHandle, Protocol, (VOID **)&ExistingInterface);\r
381 if (!EFI_ERROR (Status)) {\r
382 return EFI_INVALID_PARAMETER;\r
383 }\r
384 }\r
385\r
386 //\r
022c6d45 387 // Lock the protocol database\r
28a00297 388 //\r
389 CoreAcquireProtocolLock ();\r
390\r
391 //\r
392 // Lookup the Protocol Entry for the requested protocol\r
393 //\r
394 ProtEntry = CoreFindProtocolEntry (Protocol, TRUE);\r
395 if (ProtEntry == NULL) {\r
396 goto Done;\r
397 }\r
398\r
399 //\r
400 // Allocate a new protocol interface structure\r
401 //\r
9c4ac31c 402 Prot = AllocateZeroPool (sizeof(PROTOCOL_INTERFACE));\r
28a00297 403 if (Prot == NULL) {\r
404 Status = EFI_OUT_OF_RESOURCES;\r
405 goto Done;\r
406 }\r
407\r
408 //\r
409 // If caller didn't supply a handle, allocate a new one\r
410 //\r
411 Handle = (IHANDLE *)*UserHandle;\r
412 if (Handle == NULL) {\r
9c4ac31c 413 Handle = AllocateZeroPool (sizeof(IHANDLE));\r
28a00297 414 if (Handle == NULL) {\r
415 Status = EFI_OUT_OF_RESOURCES;\r
416 goto Done;\r
417 }\r
418\r
419 //\r
420 // Initialize new handler structure\r
421 //\r
422 Handle->Signature = EFI_HANDLE_SIGNATURE;\r
423 InitializeListHead (&Handle->Protocols);\r
424\r
425 //\r
426 // Initialize the Key to show that the handle has been created/modified\r
427 //\r
428 gHandleDatabaseKey++;\r
429 Handle->Key = gHandleDatabaseKey;\r
430\r
431 //\r
432 // Add this handle to the list global list of all handles\r
433 // in the system\r
434 //\r
435 InsertTailList (&gHandleList, &Handle->AllHandles);\r
c01f13d5
SZ
436 } else {\r
437 Status = CoreValidateHandle (Handle);\r
438 if (EFI_ERROR (Status)) {\r
439 DEBUG((DEBUG_ERROR, "InstallProtocolInterface: input handle at 0x%x is invalid\n", Handle));\r
440 goto Done;\r
441 }\r
28a00297 442 }\r
443\r
444 //\r
445 // Each interface that is added must be unique\r
446 //\r
447 ASSERT (CoreFindProtocolInterface (Handle, Protocol, Interface) == NULL);\r
448\r
449 //\r
450 // Initialize the protocol interface structure\r
451 //\r
452 Prot->Signature = PROTOCOL_INTERFACE_SIGNATURE;\r
453 Prot->Handle = Handle;\r
454 Prot->Protocol = ProtEntry;\r
455 Prot->Interface = Interface;\r
456\r
457 //\r
458 // Initalize OpenProtocol Data base\r
459 //\r
460 InitializeListHead (&Prot->OpenList);\r
461 Prot->OpenListCount = 0;\r
462\r
463 //\r
022c6d45 464 // Add this protocol interface to the head of the supported\r
28a00297 465 // protocol list for this handle\r
466 //\r
467 InsertHeadList (&Handle->Protocols, &Prot->Link);\r
468\r
469 //\r
022c6d45 470 // Add this protocol interface to the tail of the\r
28a00297 471 // protocol entry\r
022c6d45 472 //\r
28a00297 473 InsertTailList (&ProtEntry->Protocols, &Prot->ByProtocol);\r
474\r
475 //\r
022c6d45 476 // Notify the notification list for this protocol\r
28a00297 477 //\r
478 if (Notify) {\r
479 CoreNotifyProtocolEntry (ProtEntry);\r
480 }\r
481 Status = EFI_SUCCESS;\r
482\r
483Done:\r
484 //\r
485 // Done, unlock the database and return\r
486 //\r
487 CoreReleaseProtocolLock ();\r
488 if (!EFI_ERROR (Status)) {\r
489 //\r
490 // Return the new handle back to the caller\r
491 //\r
492 *UserHandle = Handle;\r
493 } else {\r
494 //\r
495 // There was an error, clean up\r
496 //\r
497 if (Prot != NULL) {\r
498 CoreFreePool (Prot);\r
499 }\r
c01f13d5 500 DEBUG((DEBUG_ERROR, "InstallProtocolInterface: %g %p failed with %r\n", Protocol, Interface, Status));\r
28a00297 501 }\r
502\r
503 return Status;\r
504}\r
505\r
506\r
507\r
28a00297 508\r
162ed594 509/**\r
28a00297 510 Installs a list of protocol interface into the boot services environment.\r
511 This function calls InstallProtocolInterface() in a loop. If any error\r
162ed594 512 occures all the protocols added by this function are removed. This is\r
28a00297 513 basically a lib function to save space.\r
514\r
4a23eaa9
RN
515 @param Handle The pointer to a handle to install the new\r
516 protocol interfaces on, or a pointer to NULL\r
517 if a new handle is to be allocated.\r
022c6d45 518 @param ... EFI_GUID followed by protocol instance. A NULL\r
519 terminates the list. The pairs are the\r
520 arguments to InstallProtocolInterface(). All the\r
521 protocols are added to Handle.\r
28a00297 522\r
5a7b9bbe
SQ
523 @retval EFI_SUCCESS All the protocol interface was installed.\r
524 @retval EFI_OUT_OF_RESOURCES There was not enough memory in pool to install all the protocols.\r
525 @retval EFI_ALREADY_STARTED A Device Path Protocol instance was passed in that is already present in\r
526 the handle database.\r
022c6d45 527 @retval EFI_INVALID_PARAMETER Handle is NULL.\r
5a7b9bbe 528 @retval EFI_INVALID_PARAMETER Protocol is already installed on the handle specified by Handle.\r
28a00297 529\r
162ed594 530**/\r
531EFI_STATUS\r
532EFIAPI\r
533CoreInstallMultipleProtocolInterfaces (\r
534 IN OUT EFI_HANDLE *Handle,\r
535 ...\r
536 )\r
28a00297 537{\r
162ed594 538 VA_LIST Args;\r
28a00297 539 EFI_STATUS Status;\r
540 EFI_GUID *Protocol;\r
541 VOID *Interface;\r
542 EFI_TPL OldTpl;\r
543 UINTN Index;\r
544 EFI_HANDLE OldHandle;\r
545 EFI_HANDLE DeviceHandle;\r
546 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
022c6d45 547\r
28a00297 548 if (Handle == NULL) {\r
549 return EFI_INVALID_PARAMETER;\r
550 }\r
022c6d45 551\r
552 //\r
553 // Syncronize with notifcations.\r
28a00297 554 //\r
28a00297 555 OldTpl = CoreRaiseTpl (TPL_NOTIFY);\r
556 OldHandle = *Handle;\r
557\r
558 //\r
559 // Check for duplicate device path and install the protocol interfaces\r
560 //\r
162ed594 561 VA_START (Args, Handle);\r
28a00297 562 for (Index = 0, Status = EFI_SUCCESS; !EFI_ERROR (Status); Index++) {\r
563 //\r
564 // If protocol is NULL, then it's the end of the list\r
565 //\r
162ed594 566 Protocol = VA_ARG (Args, EFI_GUID *);\r
28a00297 567 if (Protocol == NULL) {\r
568 break;\r
569 }\r
570\r
162ed594 571 Interface = VA_ARG (Args, VOID *);\r
28a00297 572\r
573 //\r
574 // Make sure you are installing on top a device path that has already been added.\r
575 //\r
576 if (CompareGuid (Protocol, &gEfiDevicePathProtocolGuid)) {\r
577 DeviceHandle = NULL;\r
578 DevicePath = Interface;\r
579 Status = CoreLocateDevicePath (&gEfiDevicePathProtocolGuid, &DevicePath, &DeviceHandle);\r
4008328a 580 if (!EFI_ERROR (Status) && (DeviceHandle != NULL) && IsDevicePathEnd(DevicePath)) {\r
28a00297 581 Status = EFI_ALREADY_STARTED;\r
582 continue;\r
583 }\r
584 }\r
022c6d45 585\r
28a00297 586 //\r
587 // Install it\r
588 //\r
589 Status = CoreInstallProtocolInterface (Handle, Protocol, EFI_NATIVE_INTERFACE, Interface);\r
590 }\r
a70c0fd8 591 VA_END (Args);\r
022c6d45 592\r
28a00297 593 //\r
594 // If there was an error, remove all the interfaces that were installed without any errors\r
595 //\r
596 if (EFI_ERROR (Status)) {\r
597 //\r
598 // Reset the va_arg back to the first argument.\r
599 //\r
162ed594 600 VA_START (Args, Handle);\r
28a00297 601 for (; Index > 1; Index--) {\r
162ed594 602 Protocol = VA_ARG (Args, EFI_GUID *);\r
603 Interface = VA_ARG (Args, VOID *);\r
28a00297 604 CoreUninstallProtocolInterface (*Handle, Protocol, Interface);\r
022c6d45 605 }\r
a70c0fd8 606 VA_END (Args);\r
607 \r
28a00297 608 *Handle = OldHandle;\r
609 }\r
610\r
611 //\r
612 // Done\r
613 //\r
614 CoreRestoreTpl (OldTpl);\r
615 return Status;\r
616}\r
617\r
28a00297 618\r
162ed594 619/**\r
28a00297 620 Attempts to disconnect all drivers that are using the protocol interface being queried.\r
621 If failed, reconnect all drivers disconnected.\r
162ed594 622 Note: This function doesn't do parameters checking, it's caller's responsibility\r
623 to pass in valid parameters.\r
28a00297 624\r
022c6d45 625 @param UserHandle The handle on which the protocol is installed\r
626 @param Prot The protocol to disconnect drivers from\r
28a00297 627\r
022c6d45 628 @retval EFI_SUCCESS Drivers using the protocol interface are all\r
629 disconnected\r
162ed594 630 @retval EFI_ACCESS_DENIED Failed to disconnect one or all of the drivers\r
28a00297 631\r
162ed594 632**/\r
633EFI_STATUS\r
634CoreDisconnectControllersUsingProtocolInterface (\r
635 IN EFI_HANDLE UserHandle,\r
636 IN PROTOCOL_INTERFACE *Prot\r
637 )\r
28a00297 638{\r
639 EFI_STATUS Status;\r
640 BOOLEAN ItemFound;\r
641 LIST_ENTRY *Link;\r
642 OPEN_PROTOCOL_DATA *OpenData;\r
643\r
644 Status = EFI_SUCCESS;\r
022c6d45 645\r
28a00297 646 //\r
647 // Attempt to disconnect all drivers from this protocol interface\r
648 //\r
649 do {\r
650 ItemFound = FALSE;\r
5fc3889b 651 for (Link = Prot->OpenList.ForwardLink; Link != &Prot->OpenList; Link = Link->ForwardLink) {\r
28a00297 652 OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);\r
6e536468 653 if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {\r
28a00297 654 CoreReleaseProtocolLock ();\r
655 Status = CoreDisconnectController (UserHandle, OpenData->AgentHandle, NULL);\r
656 CoreAcquireProtocolLock ();\r
5fc3889b
RN
657 if (!EFI_ERROR (Status)) {\r
658 ItemFound = TRUE;\r
28a00297 659 }\r
5fc3889b 660 break;\r
28a00297 661 }\r
662 }\r
663 } while (ItemFound);\r
664\r
665 if (!EFI_ERROR (Status)) {\r
666 //\r
667 // Attempt to remove BY_HANDLE_PROTOOCL and GET_PROTOCOL and TEST_PROTOCOL Open List items\r
668 //\r
5fc3889b
RN
669 for (Link = Prot->OpenList.ForwardLink; Link != &Prot->OpenList;) {\r
670 OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);\r
671 if ((OpenData->Attributes &\r
672 (EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL | EFI_OPEN_PROTOCOL_GET_PROTOCOL | EFI_OPEN_PROTOCOL_TEST_PROTOCOL)) != 0) {\r
673 Link = RemoveEntryList (&OpenData->Link);\r
674 Prot->OpenListCount--;\r
675 CoreFreePool (OpenData);\r
676 } else {\r
677 Link = Link->ForwardLink;\r
28a00297 678 }\r
5fc3889b 679 }\r
28a00297 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
89f7f2cd
AK
1007 if ((Attributes != EFI_OPEN_PROTOCOL_TEST_PROTOCOL) && (Interface == NULL)) {\r
1008 return EFI_INVALID_PARAMETER;\r
28a00297 1009 }\r
022c6d45 1010\r
28a00297 1011 //\r
1012 // Check for invalid UserHandle\r
1013 //\r
1014 Status = CoreValidateHandle (UserHandle);\r
1015 if (EFI_ERROR (Status)) {\r
1016 return Status;\r
1017 }\r
1018\r
1019 //\r
1020 // Check for invalid Attributes\r
1021 //\r
1022 switch (Attributes) {\r
1023 case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER :\r
1024 Status = CoreValidateHandle (ImageHandle);\r
1025 if (EFI_ERROR (Status)) {\r
1026 return Status;\r
1027 }\r
1028 Status = CoreValidateHandle (ControllerHandle);\r
1029 if (EFI_ERROR (Status)) {\r
1030 return Status;\r
1031 }\r
1032 if (UserHandle == ControllerHandle) {\r
1033 return EFI_INVALID_PARAMETER;\r
1034 }\r
1035 break;\r
1036 case EFI_OPEN_PROTOCOL_BY_DRIVER :\r
1037 case EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE :\r
1038 Status = CoreValidateHandle (ImageHandle);\r
1039 if (EFI_ERROR (Status)) {\r
1040 return Status;\r
1041 }\r
1042 Status = CoreValidateHandle (ControllerHandle);\r
1043 if (EFI_ERROR (Status)) {\r
1044 return Status;\r
1045 }\r
1046 break;\r
1047 case EFI_OPEN_PROTOCOL_EXCLUSIVE :\r
1048 Status = CoreValidateHandle (ImageHandle);\r
1049 if (EFI_ERROR (Status)) {\r
1050 return Status;\r
1051 }\r
1052 break;\r
1053 case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL :\r
1054 case EFI_OPEN_PROTOCOL_GET_PROTOCOL :\r
1055 case EFI_OPEN_PROTOCOL_TEST_PROTOCOL :\r
1056 break;\r
1057 default:\r
1058 return EFI_INVALID_PARAMETER;\r
1059 }\r
1060\r
1061 //\r
1062 // Lock the protocol database\r
1063 //\r
1064 CoreAcquireProtocolLock ();\r
1065\r
1066 //\r
1067 // Look at each protocol interface for a match\r
1068 //\r
1069 Prot = CoreGetProtocolInterface (UserHandle, Protocol);\r
1070 if (Prot == NULL) {\r
1071 Status = EFI_UNSUPPORTED;\r
1072 goto Done;\r
1073 }\r
1074\r
28a00297 1075 Status = EFI_SUCCESS;\r
1076\r
1077 ByDriver = FALSE;\r
1078 Exclusive = FALSE;\r
1079 for ( Link = Prot->OpenList.ForwardLink; Link != &Prot->OpenList; Link = Link->ForwardLink) {\r
1080 OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);\r
022c6d45 1081 ExactMatch = (BOOLEAN)((OpenData->AgentHandle == ImageHandle) &&\r
28a00297 1082 (OpenData->Attributes == Attributes) &&\r
1083 (OpenData->ControllerHandle == ControllerHandle));\r
6e536468 1084 if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {\r
28a00297 1085 ByDriver = TRUE;\r
1086 if (ExactMatch) {\r
1087 Status = EFI_ALREADY_STARTED;\r
1088 goto Done;\r
1089 }\r
1090 }\r
6e536468 1091 if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_EXCLUSIVE) != 0) {\r
28a00297 1092 Exclusive = TRUE;\r
1093 } else if (ExactMatch) {\r
1094 OpenData->OpenCount++;\r
1095 Status = EFI_SUCCESS;\r
1096 goto Done;\r
1097 }\r
1098 }\r
1099\r
1100 //\r
1101 // ByDriver TRUE -> A driver is managing (UserHandle, Protocol)\r
1102 // ByDriver FALSE -> There are no drivers managing (UserHandle, Protocol)\r
1103 // Exclusive TRUE -> Something has exclusive access to (UserHandle, Protocol)\r
1104 // Exclusive FALSE -> Nothing has exclusive access to (UserHandle, Protocol)\r
1105 //\r
1106\r
1107 switch (Attributes) {\r
1108 case EFI_OPEN_PROTOCOL_BY_DRIVER :\r
1109 if (Exclusive || ByDriver) {\r
1110 Status = EFI_ACCESS_DENIED;\r
1111 goto Done;\r
1112 }\r
1113 break;\r
1114 case EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE :\r
1115 case EFI_OPEN_PROTOCOL_EXCLUSIVE :\r
1116 if (Exclusive) {\r
1117 Status = EFI_ACCESS_DENIED;\r
1118 goto Done;\r
1119 }\r
1120 if (ByDriver) {\r
1121 do {\r
1122 Disconnect = FALSE;\r
5fc3889b 1123 for (Link = Prot->OpenList.ForwardLink; Link != &Prot->OpenList; Link = Link->ForwardLink) {\r
28a00297 1124 OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);\r
6e536468 1125 if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {\r
28a00297 1126 Disconnect = TRUE;\r
1127 CoreReleaseProtocolLock ();\r
1128 Status = CoreDisconnectController (UserHandle, OpenData->AgentHandle, NULL);\r
1129 CoreAcquireProtocolLock ();\r
1130 if (EFI_ERROR (Status)) {\r
1131 Status = EFI_ACCESS_DENIED;\r
1132 goto Done;\r
5fc3889b
RN
1133 } else {\r
1134 break;\r
28a00297 1135 }\r
1136 }\r
1137 }\r
1138 } while (Disconnect);\r
022c6d45 1139 }\r
28a00297 1140 break;\r
1141 case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER :\r
1142 case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL :\r
1143 case EFI_OPEN_PROTOCOL_GET_PROTOCOL :\r
1144 case EFI_OPEN_PROTOCOL_TEST_PROTOCOL :\r
1145 break;\r
1146 }\r
1147\r
1148 if (ImageHandle == NULL) {\r
1149 Status = EFI_SUCCESS;\r
1150 goto Done;\r
1151 }\r
1152 //\r
1153 // Create new entry\r
1154 //\r
9c4ac31c 1155 OpenData = AllocatePool (sizeof(OPEN_PROTOCOL_DATA));\r
28a00297 1156 if (OpenData == NULL) {\r
1157 Status = EFI_OUT_OF_RESOURCES;\r
1158 } else {\r
1159 OpenData->Signature = OPEN_PROTOCOL_DATA_SIGNATURE;\r
1160 OpenData->AgentHandle = ImageHandle;\r
1161 OpenData->ControllerHandle = ControllerHandle;\r
1162 OpenData->Attributes = Attributes;\r
1163 OpenData->OpenCount = 1;\r
1164 InsertTailList (&Prot->OpenList, &OpenData->Link);\r
1165 Prot->OpenListCount++;\r
1166 Status = EFI_SUCCESS;\r
1167 }\r
1168\r
1169Done:\r
89f7f2cd
AK
1170\r
1171 if (Attributes != EFI_OPEN_PROTOCOL_TEST_PROTOCOL) {\r
1172 //\r
1173 // Keep Interface unmodified in case of any Error\r
1174 // except EFI_ALREADY_STARTED and EFI_UNSUPPORTED.\r
1175 //\r
1176 if (!EFI_ERROR (Status) || Status == EFI_ALREADY_STARTED) {\r
1177 //\r
1178 // EFI_ALREADY_STARTED is not an error for bus driver.\r
1179 // Return the corresponding protocol interface.\r
1180 //\r
1181 *Interface = Prot->Interface;\r
1182 } else if (Status == EFI_UNSUPPORTED) {\r
1183 //\r
1184 // Return NULL Interface if Unsupported Protocol.\r
1185 //\r
1186 *Interface = NULL;\r
1187 }\r
1188 }\r
1189\r
28a00297 1190 //\r
89f7f2cd 1191 // Done. Release the database lock and return\r
28a00297 1192 //\r
1193 CoreReleaseProtocolLock ();\r
1194 return Status;\r
1195}\r
1196\r
1197\r
162ed594 1198\r
1199/**\r
1200 Closes a protocol on a handle that was opened using OpenProtocol().\r
1201\r
022c6d45 1202 @param UserHandle The handle for the protocol interface that was\r
1203 previously opened with OpenProtocol(), and is\r
1204 now being closed.\r
1205 @param Protocol The published unique identifier of the protocol.\r
1206 It is the caller's responsibility to pass in a\r
1207 valid GUID.\r
1208 @param AgentHandle The handle of the agent that is closing the\r
1209 protocol interface.\r
1210 @param ControllerHandle If the agent that opened a protocol is a driver\r
1211 that follows the EFI Driver Model, then this\r
1212 parameter is the controller handle that required\r
1213 the protocol interface. If the agent does not\r
1214 follow the EFI Driver Model, then this parameter\r
1215 is optional and may be NULL.\r
1216\r
1217 @retval EFI_SUCCESS The protocol instance was closed.\r
1218 @retval EFI_INVALID_PARAMETER Handle, AgentHandle or ControllerHandle is not a\r
1219 valid EFI_HANDLE.\r
1220 @retval EFI_NOT_FOUND Can not find the specified protocol or\r
162ed594 1221 AgentHandle.\r
1222\r
1223**/\r
28a00297 1224EFI_STATUS\r
1225EFIAPI\r
1226CoreCloseProtocol (\r
1227 IN EFI_HANDLE UserHandle,\r
1228 IN EFI_GUID *Protocol,\r
1229 IN EFI_HANDLE AgentHandle,\r
022c6d45 1230 IN EFI_HANDLE ControllerHandle\r
28a00297 1231 )\r
28a00297 1232{\r
1233 EFI_STATUS Status;\r
1234 PROTOCOL_INTERFACE *ProtocolInterface;\r
1235 LIST_ENTRY *Link;\r
1236 OPEN_PROTOCOL_DATA *OpenData;\r
1237\r
1238 //\r
1239 // Check for invalid parameters\r
1240 //\r
1241 Status = CoreValidateHandle (UserHandle);\r
1242 if (EFI_ERROR (Status)) {\r
1243 return Status;\r
1244 }\r
1245 Status = CoreValidateHandle (AgentHandle);\r
1246 if (EFI_ERROR (Status)) {\r
1247 return Status;\r
1248 }\r
4008328a 1249 if (ControllerHandle != NULL) {\r
28a00297 1250 Status = CoreValidateHandle (ControllerHandle);\r
1251 if (EFI_ERROR (Status)) {\r
1252 return Status;\r
1253 }\r
1254 }\r
1255 if (Protocol == NULL) {\r
1256 return EFI_INVALID_PARAMETER;\r
1257 }\r
1258\r
1259 //\r
1260 // Lock the protocol database\r
1261 //\r
1262 CoreAcquireProtocolLock ();\r
1263\r
1264 //\r
1265 // Look at each protocol interface for a match\r
1266 //\r
1267 Status = EFI_NOT_FOUND;\r
1268 ProtocolInterface = CoreGetProtocolInterface (UserHandle, Protocol);\r
1269 if (ProtocolInterface == NULL) {\r
1270 goto Done;\r
1271 }\r
1272\r
1273 //\r
1274 // Walk the Open data base looking for AgentHandle\r
1275 //\r
1276 Link = ProtocolInterface->OpenList.ForwardLink;\r
1277 while (Link != &ProtocolInterface->OpenList) {\r
1278 OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);\r
1279 Link = Link->ForwardLink;\r
1280 if ((OpenData->AgentHandle == AgentHandle) && (OpenData->ControllerHandle == ControllerHandle)) {\r
022c6d45 1281 RemoveEntryList (&OpenData->Link);\r
28a00297 1282 ProtocolInterface->OpenListCount--;\r
1283 CoreFreePool (OpenData);\r
1284 Status = EFI_SUCCESS;\r
1285 }\r
1286 }\r
1287\r
1288Done:\r
1289 //\r
1290 // Done. Release the database lock and return.\r
1291 //\r
1292 CoreReleaseProtocolLock ();\r
1293 return Status;\r
1294}\r
1295\r
1296\r
1297\r
162ed594 1298\r
1299/**\r
1300 Return information about Opened protocols in the system\r
1301\r
022c6d45 1302 @param UserHandle The handle to close the protocol interface on\r
1303 @param Protocol The ID of the protocol\r
11074aab 1304 @param EntryBuffer A pointer to a buffer of open protocol information in the\r
1305 form of EFI_OPEN_PROTOCOL_INFORMATION_ENTRY structures.\r
162ed594 1306 @param EntryCount Number of EntryBuffer entries\r
1307\r
11074aab 1308 @retval EFI_SUCCESS The open protocol information was returned in EntryBuffer, \r
1309 and the number of entries was returned EntryCount.\r
1310 @retval EFI_NOT_FOUND Handle does not support the protocol specified by Protocol.\r
1311 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to allocate EntryBuffer.\r
1312\r
162ed594 1313**/\r
28a00297 1314EFI_STATUS\r
1315EFIAPI\r
1316CoreOpenProtocolInformation (\r
1317 IN EFI_HANDLE UserHandle,\r
1318 IN EFI_GUID *Protocol,\r
1319 OUT EFI_OPEN_PROTOCOL_INFORMATION_ENTRY **EntryBuffer,\r
1320 OUT UINTN *EntryCount\r
1321 )\r
28a00297 1322{\r
1323 EFI_STATUS Status;\r
1324 PROTOCOL_INTERFACE *ProtocolInterface;\r
1325 LIST_ENTRY *Link;\r
1326 OPEN_PROTOCOL_DATA *OpenData;\r
1327 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *Buffer;\r
1328 UINTN Count;\r
1329 UINTN Size;\r
1330\r
1331 *EntryBuffer = NULL;\r
1332 *EntryCount = 0;\r
1333\r
1334 //\r
1335 // Lock the protocol database\r
1336 //\r
1337 CoreAcquireProtocolLock ();\r
1338\r
1339 //\r
1340 // Look at each protocol interface for a match\r
1341 //\r
1342 Status = EFI_NOT_FOUND;\r
1343 ProtocolInterface = CoreGetProtocolInterface (UserHandle, Protocol);\r
1344 if (ProtocolInterface == NULL) {\r
1345 goto Done;\r
1346 }\r
1347\r
1348 //\r
1349 // Count the number of Open Entries\r
1350 //\r
022c6d45 1351 for ( Link = ProtocolInterface->OpenList.ForwardLink, Count = 0;\r
28a00297 1352 (Link != &ProtocolInterface->OpenList) ;\r
1353 Link = Link->ForwardLink ) {\r
1354 Count++;\r
022c6d45 1355 }\r
28a00297 1356\r
1357 ASSERT (Count == ProtocolInterface->OpenListCount);\r
1358\r
1359 if (Count == 0) {\r
1360 Size = sizeof(EFI_OPEN_PROTOCOL_INFORMATION_ENTRY);\r
1361 } else {\r
1362 Size = Count * sizeof(EFI_OPEN_PROTOCOL_INFORMATION_ENTRY);\r
1363 }\r
1364\r
9c4ac31c 1365 Buffer = AllocatePool (Size);\r
28a00297 1366 if (Buffer == NULL) {\r
1367 Status = EFI_OUT_OF_RESOURCES;\r
1368 goto Done;\r
1369 }\r
1370\r
1371 Status = EFI_SUCCESS;\r
022c6d45 1372 for ( Link = ProtocolInterface->OpenList.ForwardLink, Count = 0;\r
28a00297 1373 (Link != &ProtocolInterface->OpenList);\r
1374 Link = Link->ForwardLink, Count++ ) {\r
1375 OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);\r
1376\r
1377 Buffer[Count].AgentHandle = OpenData->AgentHandle;\r
1378 Buffer[Count].ControllerHandle = OpenData->ControllerHandle;\r
1379 Buffer[Count].Attributes = OpenData->Attributes;\r
1380 Buffer[Count].OpenCount = OpenData->OpenCount;\r
022c6d45 1381 }\r
28a00297 1382\r
1383 *EntryBuffer = Buffer;\r
1384 *EntryCount = Count;\r
022c6d45 1385\r
28a00297 1386Done:\r
1387 //\r
1439777e 1388 // Done. Release the database lock.\r
28a00297 1389 //\r
1390 CoreReleaseProtocolLock ();\r
1391 return Status;\r
1392}\r
1393\r
1394\r
1395\r
162ed594 1396\r
1397/**\r
1398 Retrieves the list of protocol interface GUIDs that are installed on a handle in a buffer allocated\r
1399 from pool.\r
1400\r
022c6d45 1401 @param UserHandle The handle from which to retrieve the list of\r
1402 protocol interface GUIDs.\r
1403 @param ProtocolBuffer A pointer to the list of protocol interface GUID\r
1404 pointers that are installed on Handle.\r
1405 @param ProtocolBufferCount A pointer to the number of GUID pointers present\r
1406 in ProtocolBuffer.\r
1407\r
1408 @retval EFI_SUCCESS The list of protocol interface GUIDs installed\r
1409 on Handle was returned in ProtocolBuffer. The\r
1410 number of protocol interface GUIDs was returned\r
1411 in ProtocolBufferCount.\r
1412 @retval EFI_INVALID_PARAMETER Handle is NULL.\r
1413 @retval EFI_INVALID_PARAMETER Handle is not a valid EFI_HANDLE.\r
1414 @retval EFI_INVALID_PARAMETER ProtocolBuffer is NULL.\r
1415 @retval EFI_INVALID_PARAMETER ProtocolBufferCount is NULL.\r
1416 @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the\r
162ed594 1417 results.\r
1418\r
1419**/\r
28a00297 1420EFI_STATUS\r
1421EFIAPI\r
1422CoreProtocolsPerHandle (\r
1423 IN EFI_HANDLE UserHandle,\r
1424 OUT EFI_GUID ***ProtocolBuffer,\r
1425 OUT UINTN *ProtocolBufferCount\r
1426 )\r
28a00297 1427{\r
1428 EFI_STATUS Status;\r
1429 IHANDLE *Handle;\r
1430 PROTOCOL_INTERFACE *Prot;\r
1431 LIST_ENTRY *Link;\r
1432 UINTN ProtocolCount;\r
1433 EFI_GUID **Buffer;\r
1434\r
1435 Status = CoreValidateHandle (UserHandle);\r
1436 if (EFI_ERROR (Status)) {\r
1437 return Status;\r
1438 }\r
1439\r
1440 Handle = (IHANDLE *)UserHandle;\r
1441\r
1442 if (ProtocolBuffer == NULL) {\r
1443 return EFI_INVALID_PARAMETER;\r
1444 }\r
1445\r
1446 if (ProtocolBufferCount == NULL) {\r
1447 return EFI_INVALID_PARAMETER;\r
1448 }\r
1449\r
1450 *ProtocolBufferCount = 0;\r
1451\r
1452 ProtocolCount = 0;\r
1453\r
1454 CoreAcquireProtocolLock ();\r
022c6d45 1455\r
28a00297 1456 for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {\r
1457 ProtocolCount++;\r
1458 }\r
1459\r
1460 //\r
1461 // If there are no protocol interfaces installed on Handle, then Handle is not a valid EFI_HANDLE\r
1462 //\r
1463 if (ProtocolCount == 0) {\r
1464 Status = EFI_INVALID_PARAMETER;\r
1465 goto Done;\r
1466 }\r
1467\r
9c4ac31c 1468 Buffer = AllocatePool (sizeof (EFI_GUID *) * ProtocolCount);\r
28a00297 1469 if (Buffer == NULL) {\r
1470 Status = EFI_OUT_OF_RESOURCES;\r
1471 goto Done;\r
1472 }\r
1473\r
1474 *ProtocolBuffer = Buffer;\r
1475 *ProtocolBufferCount = ProtocolCount;\r
1476\r
1477 for ( Link = Handle->Protocols.ForwardLink, ProtocolCount = 0;\r
022c6d45 1478 Link != &Handle->Protocols;\r
28a00297 1479 Link = Link->ForwardLink, ProtocolCount++) {\r
1480 Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);\r
1481 Buffer[ProtocolCount] = &(Prot->Protocol->ProtocolID);\r
1482 }\r
1483 Status = EFI_SUCCESS;\r
1484\r
1485Done:\r
1486 CoreReleaseProtocolLock ();\r
1487 return Status;\r
1488}\r
1489\r
1490\r
28a00297 1491\r
162ed594 1492/**\r
28a00297 1493 return handle database key.\r
1494\r
28a00297 1495\r
162ed594 1496 @return Handle database key.\r
1497\r
1498**/\r
1499UINT64\r
1500CoreGetHandleDatabaseKey (\r
1501 VOID\r
1502 )\r
28a00297 1503{\r
1504 return gHandleDatabaseKey;\r
1505}\r
1506\r
1507\r
28a00297 1508\r
162ed594 1509/**\r
28a00297 1510 Go connect any handles that were created or modified while a image executed.\r
1511\r
022c6d45 1512 @param Key The Key to show that the handle has been\r
162ed594 1513 created/modified\r
28a00297 1514\r
162ed594 1515**/\r
1516VOID\r
1517CoreConnectHandlesByKey (\r
1518 UINT64 Key\r
1519 )\r
28a00297 1520{\r
1521 UINTN Count;\r
1522 LIST_ENTRY *Link;\r
1523 EFI_HANDLE *HandleBuffer;\r
1524 IHANDLE *Handle;\r
1525 UINTN Index;\r
1526\r
1527 //\r
1528 // Lock the protocol database\r
1529 //\r
1530 CoreAcquireProtocolLock ();\r
1531\r
1532 for (Link = gHandleList.ForwardLink, Count = 0; Link != &gHandleList; Link = Link->ForwardLink) {\r
1533 Handle = CR (Link, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE);\r
1534 if (Handle->Key > Key) {\r
1535 Count++;\r
1536 }\r
1537 }\r
1538\r
9c4ac31c 1539 HandleBuffer = AllocatePool (Count * sizeof (EFI_HANDLE));\r
28a00297 1540 if (HandleBuffer == NULL) {\r
1541 CoreReleaseProtocolLock ();\r
1542 return;\r
1543 }\r
022c6d45 1544\r
28a00297 1545 for (Link = gHandleList.ForwardLink, Count = 0; Link != &gHandleList; Link = Link->ForwardLink) {\r
1546 Handle = CR (Link, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE);\r
1547 if (Handle->Key > Key) {\r
1548 HandleBuffer[Count++] = Handle;\r
1549 }\r
1550 }\r
1551\r
1552 //\r
1553 // Unlock the protocol database\r
1554 //\r
1555 CoreReleaseProtocolLock ();\r
1556\r
1557 //\r
1558 // Connect all handles whose Key value is greater than Key\r
1559 //\r
1560 for (Index = 0; Index < Count; Index++) {\r
1561 CoreConnectController (HandleBuffer[Index], NULL, NULL, TRUE);\r
1562 }\r
022c6d45 1563\r
28a00297 1564 CoreFreePool(HandleBuffer);\r
1565}\r