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