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