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