1 /** @file 2 The driver binding and service binding protocol for DnsDxe driver. 3 4 Copyright (c) 2015 - 2016, 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 "DnsImpl.h" 16 17 EFI_DRIVER_BINDING_PROTOCOL gDns4DriverBinding = { 18 Dns4DriverBindingSupported, 19 Dns4DriverBindingStart, 20 Dns4DriverBindingStop, 21 DNS_VERSION, 22 NULL, 23 NULL 24 }; 25 26 EFI_DRIVER_BINDING_PROTOCOL gDns6DriverBinding = { 27 Dns6DriverBindingSupported, 28 Dns6DriverBindingStart, 29 Dns6DriverBindingStop, 30 DNS_VERSION, 31 NULL, 32 NULL 33 }; 34 35 EFI_SERVICE_BINDING_PROTOCOL mDns4ServiceBinding = { 36 Dns4ServiceBindingCreateChild, 37 Dns4ServiceBindingDestroyChild 38 }; 39 40 EFI_SERVICE_BINDING_PROTOCOL mDns6ServiceBinding = { 41 Dns6ServiceBindingCreateChild, 42 Dns6ServiceBindingDestroyChild 43 }; 44 45 DNS_DRIVER_DATA *mDriverData = NULL; 46 47 /** 48 Destroy the DNS instance and recycle the resources. 49 50 @param[in] Instance The pointer to the DNS instance. 51 52 **/ 53 VOID 54 DnsDestroyInstance ( 55 IN DNS_INSTANCE *Instance 56 ) 57 { 58 ZeroMem (&Instance->Dns4CfgData, sizeof (EFI_DNS4_CONFIG_DATA)); 59 60 ZeroMem (&Instance->Dns6CfgData, sizeof (EFI_DNS6_CONFIG_DATA)); 61 62 if (!NetMapIsEmpty (&Instance->Dns4TxTokens)) { 63 Dns4InstanceCancelToken (Instance, NULL); 64 } 65 66 if (!NetMapIsEmpty (&Instance->Dns6TxTokens)) { 67 Dns6InstanceCancelToken (Instance, NULL); 68 } 69 70 if (Instance->UdpIo!= NULL) { 71 UdpIoFreeIo (Instance->UdpIo); 72 } 73 74 FreePool (Instance); 75 } 76 77 /** 78 Create the DNS instance and initialize it. 79 80 @param[in] Service The pointer to the DNS service. 81 @param[out] Instance The pointer to the DNS instance. 82 83 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources. 84 @retval EFI_SUCCESS The DNS instance is created. 85 86 **/ 87 EFI_STATUS 88 DnsCreateInstance ( 89 IN DNS_SERVICE *Service, 90 OUT DNS_INSTANCE **Instance 91 ) 92 { 93 DNS_INSTANCE *DnsIns; 94 95 *Instance = NULL; 96 97 DnsIns = AllocateZeroPool (sizeof (DNS_INSTANCE)); 98 if (DnsIns == NULL) { 99 return EFI_OUT_OF_RESOURCES; 100 } 101 102 DnsIns->Signature = DNS_INSTANCE_SIGNATURE; 103 InitializeListHead (&DnsIns->Link); 104 DnsIns->State = DNS_STATE_UNCONFIGED; 105 DnsIns->InDestroy = FALSE; 106 DnsIns->Service = Service; 107 108 if (Service->IpVersion == IP_VERSION_4) { 109 CopyMem (&DnsIns->Dns4, &mDns4Protocol, sizeof (DnsIns->Dns4)); 110 NetMapInit (&DnsIns->Dns4TxTokens); 111 } else { 112 CopyMem (&DnsIns->Dns6, &mDns6Protocol, sizeof (DnsIns->Dns6)); 113 NetMapInit (&DnsIns->Dns6TxTokens); 114 } 115 116 DnsIns->UdpIo = UdpIoCreateIo ( 117 Service->ControllerHandle, /// NicHandle 118 Service->ImageHandle, 119 DnsConfigNullUdp, 120 Service->IpVersion, 121 DnsIns 122 ); 123 if (DnsIns->UdpIo == NULL) { 124 FreePool (DnsIns); 125 return EFI_OUT_OF_RESOURCES; 126 } 127 128 *Instance = DnsIns; 129 130 return EFI_SUCCESS; 131 } 132 133 /** 134 Callback function which provided by user to remove one node in NetDestroyLinkList process. 135 136 @param[in] Entry The entry to be removed. 137 @param[in] Context Pointer to the callback context corresponds to the Context in NetDestroyLinkList. 138 139 @retval EFI_SUCCESS The entry has been removed successfully. 140 @retval Others Fail to remove the entry. 141 142 **/ 143 EFI_STATUS 144 EFIAPI 145 DnsDestroyChildEntryInHandleBuffer ( 146 IN LIST_ENTRY *Entry, 147 IN VOID *Context 148 ) 149 { 150 DNS_INSTANCE *Instance; 151 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding; 152 UINTN NumberOfChildren; 153 EFI_HANDLE *ChildHandleBuffer; 154 155 if (Entry == NULL || Context == NULL) { 156 return EFI_INVALID_PARAMETER; 157 } 158 159 Instance = NET_LIST_USER_STRUCT_S (Entry, DNS_INSTANCE, Link, DNS_INSTANCE_SIGNATURE); 160 ServiceBinding = ((DNS_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ServiceBinding; 161 NumberOfChildren = ((DNS_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->NumberOfChildren; 162 ChildHandleBuffer = ((DNS_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ChildHandleBuffer; 163 164 if (!NetIsInHandleBuffer (Instance->ChildHandle, NumberOfChildren, ChildHandleBuffer)) { 165 return EFI_SUCCESS; 166 } 167 168 return ServiceBinding->DestroyChild (ServiceBinding, Instance->ChildHandle); 169 } 170 171 /** 172 Config a NULL UDP that is used to keep the connection between UDP and DNS. 173 174 Just leave the Udp child unconfigured. When UDP is unloaded, 175 DNS will be informed with DriverBinding Stop. 176 177 @param UdpIo The UDP_IO to configure 178 @param Context The opaque parameter to the callback 179 180 @retval EFI_SUCCESS It always return EFI_SUCCESS directly. 181 182 **/ 183 EFI_STATUS 184 EFIAPI 185 DnsConfigNullUdp ( 186 IN UDP_IO *UdpIo, 187 IN VOID *Context 188 ) 189 { 190 return EFI_SUCCESS; 191 } 192 193 /** 194 Release all the resource used the DNS service binding instance. 195 196 @param DnsSb The Dns service binding instance. 197 198 **/ 199 VOID 200 DnsDestroyService ( 201 IN DNS_SERVICE *DnsSb 202 ) 203 { 204 UdpIoFreeIo (DnsSb->ConnectUdp); 205 206 if (DnsSb->TimerToGetMap != NULL){ 207 gBS->CloseEvent (DnsSb->TimerToGetMap); 208 } 209 210 if (DnsSb->Timer != NULL){ 211 gBS->CloseEvent (DnsSb->Timer); 212 } 213 214 FreePool (DnsSb); 215 } 216 217 /** 218 Create then initialize a Dns service binding instance. 219 220 @param Controller The controller to install the DNS service 221 binding on 222 @param Image The driver binding image of the DNS driver 223 @param IpVersion IpVersion for this service 224 @param Service The variable to receive the created service 225 binding instance. 226 227 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to create the instance. 228 @retval EFI_DEVICE_ERROR Failed to create a NULL UDP port to keep 229 connection with UDP. 230 @retval EFI_SUCCESS The service instance is created for the 231 controller. 232 233 **/ 234 EFI_STATUS 235 DnsCreateService ( 236 IN EFI_HANDLE Controller, 237 IN EFI_HANDLE Image, 238 IN UINT8 IpVersion, 239 OUT DNS_SERVICE **Service 240 ) 241 { 242 EFI_STATUS Status; 243 DNS_SERVICE *DnsSb; 244 245 Status = EFI_SUCCESS; 246 DnsSb = NULL; 247 248 *Service = NULL; 249 250 DnsSb = AllocateZeroPool (sizeof (DNS_SERVICE)); 251 if (DnsSb == NULL) { 252 return EFI_OUT_OF_RESOURCES; 253 } 254 255 DnsSb->Signature = DNS_SERVICE_SIGNATURE; 256 257 if (IpVersion == IP_VERSION_4) { 258 DnsSb->ServiceBinding = mDns4ServiceBinding; 259 } else { 260 DnsSb->ServiceBinding = mDns6ServiceBinding; 261 } 262 263 DnsSb->Dns4ChildrenNum = 0; 264 InitializeListHead (&DnsSb->Dns4ChildrenList); 265 266 DnsSb->Dns6ChildrenNum = 0; 267 InitializeListHead (&DnsSb->Dns6ChildrenList); 268 269 DnsSb->ControllerHandle = Controller; 270 DnsSb->ImageHandle = Image; 271 272 DnsSb->TimerToGetMap = NULL; 273 274 DnsSb->Timer = NULL; 275 276 DnsSb->IpVersion = IpVersion; 277 278 // 279 // Create the timer used to time out the procedure which is used to 280 // get the default IP address. 281 // 282 if (DnsSb->IpVersion == IP_VERSION_4) { 283 Status = gBS->CreateEvent ( 284 EVT_TIMER, 285 TPL_CALLBACK, 286 NULL, 287 NULL, 288 &DnsSb->TimerToGetMap 289 ); 290 if (EFI_ERROR (Status)) { 291 FreePool (DnsSb); 292 return Status; 293 } 294 } 295 296 // 297 // Create the timer to retransmit packets. 298 // 299 Status = gBS->CreateEvent ( 300 EVT_NOTIFY_SIGNAL | EVT_TIMER, 301 TPL_CALLBACK, 302 DnsOnTimerRetransmit, 303 DnsSb, 304 &DnsSb->Timer 305 ); 306 if (EFI_ERROR (Status)) { 307 if (DnsSb->TimerToGetMap != NULL) { 308 gBS->CloseEvent (DnsSb->TimerToGetMap); 309 } 310 FreePool (DnsSb); 311 return Status; 312 } 313 314 DnsSb->ConnectUdp = NULL; 315 DnsSb->ConnectUdp = UdpIoCreateIo ( 316 Controller, 317 Image, 318 DnsConfigNullUdp, 319 DnsSb->IpVersion, 320 NULL 321 ); 322 if (DnsSb->ConnectUdp == NULL) { 323 if (DnsSb->TimerToGetMap != NULL) { 324 gBS->CloseEvent (DnsSb->TimerToGetMap); 325 } 326 gBS->CloseEvent (DnsSb->Timer); 327 FreePool (DnsSb); 328 return EFI_DEVICE_ERROR; 329 } 330 331 *Service = DnsSb; 332 return Status; 333 } 334 335 /** 336 Unloads an image. 337 338 @param ImageHandle Handle that identifies the image to be unloaded. 339 340 @retval EFI_SUCCESS The image has been unloaded. 341 @retval EFI_INVALID_PARAMETER ImageHandle is not a valid image handle. 342 343 **/ 344 EFI_STATUS 345 EFIAPI 346 DnsUnload ( 347 IN EFI_HANDLE ImageHandle 348 ) 349 { 350 EFI_STATUS Status; 351 352 LIST_ENTRY *Entry; 353 DNS4_CACHE *ItemCache4; 354 DNS4_SERVER_IP *ItemServerIp4; 355 DNS6_CACHE *ItemCache6; 356 DNS6_SERVER_IP *ItemServerIp6; 357 358 ItemCache4 = NULL; 359 ItemServerIp4 = NULL; 360 ItemCache6 = NULL; 361 ItemServerIp6 = NULL; 362 363 // 364 // Disconnect the driver specified by ImageHandle 365 // 366 Status = NetLibDefaultUnload(ImageHandle); 367 if (EFI_ERROR (Status)) { 368 return Status; 369 } 370 371 // 372 // Free mDriverData. 373 // 374 if (mDriverData != NULL) { 375 if (mDriverData->Timer != NULL) { 376 gBS->CloseEvent (mDriverData->Timer); 377 } 378 379 while (!IsListEmpty (&mDriverData->Dns4CacheList)) { 380 Entry = NetListRemoveHead (&mDriverData->Dns4CacheList); 381 ItemCache4 = NET_LIST_USER_STRUCT (Entry, DNS4_CACHE, AllCacheLink); 382 if (ItemCache4->DnsCache.HostName != NULL) { 383 FreePool (ItemCache4->DnsCache.HostName); 384 } 385 if (ItemCache4->DnsCache.IpAddress != NULL) { 386 FreePool (ItemCache4->DnsCache.IpAddress); 387 } 388 FreePool (ItemCache4); 389 } 390 391 while (!IsListEmpty (&mDriverData->Dns4ServerList)) { 392 Entry = NetListRemoveHead (&mDriverData->Dns4ServerList); 393 ItemServerIp4 = NET_LIST_USER_STRUCT (Entry, DNS4_SERVER_IP, AllServerLink); 394 FreePool (ItemServerIp4); 395 } 396 397 while (!IsListEmpty (&mDriverData->Dns6CacheList)) { 398 Entry = NetListRemoveHead (&mDriverData->Dns6CacheList); 399 ItemCache6 = NET_LIST_USER_STRUCT (Entry, DNS6_CACHE, AllCacheLink); 400 if (ItemCache6->DnsCache.HostName != NULL) { 401 FreePool (ItemCache6->DnsCache.HostName); 402 } 403 if (ItemCache6->DnsCache.IpAddress != NULL) { 404 FreePool (ItemCache6->DnsCache.IpAddress); 405 } 406 FreePool (ItemCache6); 407 } 408 409 while (!IsListEmpty (&mDriverData->Dns6ServerList)) { 410 Entry = NetListRemoveHead (&mDriverData->Dns6ServerList); 411 ItemServerIp6 = NET_LIST_USER_STRUCT (Entry, DNS6_SERVER_IP, AllServerLink); 412 FreePool (ItemServerIp6); 413 } 414 415 FreePool (mDriverData); 416 } 417 418 return Status; 419 } 420 421 /** 422 This is the declaration of an EFI image entry point. This entry point is 423 the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including 424 both device drivers and bus drivers. 425 426 @param ImageHandle The firmware allocated handle for the UEFI image. 427 @param SystemTable A pointer to the EFI System Table. 428 429 @retval EFI_SUCCESS The operation completed successfully. 430 @retval Others An unexpected error occurred. 431 **/ 432 EFI_STATUS 433 EFIAPI 434 DnsDriverEntryPoint ( 435 IN EFI_HANDLE ImageHandle, 436 IN EFI_SYSTEM_TABLE *SystemTable 437 ) 438 { 439 EFI_STATUS Status; 440 441 Status = EFI_SUCCESS; 442 443 // 444 // Install the Dns4 Driver Binding Protocol. 445 // 446 Status = EfiLibInstallDriverBindingComponentName2 ( 447 ImageHandle, 448 SystemTable, 449 &gDns4DriverBinding, 450 ImageHandle, 451 &gDnsComponentName, 452 &gDnsComponentName2 453 ); 454 if (EFI_ERROR (Status)) { 455 return Status; 456 } 457 458 // 459 // Install the Dns6 Driver Binding Protocol. 460 // 461 Status = EfiLibInstallDriverBindingComponentName2 ( 462 ImageHandle, 463 SystemTable, 464 &gDns6DriverBinding, 465 NULL, 466 &gDnsComponentName, 467 &gDnsComponentName2 468 ); 469 if (EFI_ERROR (Status)) { 470 goto Error1; 471 } 472 473 // 474 // Create the driver data structures. 475 // 476 mDriverData = AllocateZeroPool (sizeof (DNS_DRIVER_DATA)); 477 if (mDriverData == NULL) { 478 Status = EFI_OUT_OF_RESOURCES; 479 goto Error2; 480 } 481 482 // 483 // Create the timer event to update DNS cache list. 484 // 485 Status = gBS->CreateEvent ( 486 EVT_NOTIFY_SIGNAL | EVT_TIMER, 487 TPL_CALLBACK, 488 DnsOnTimerUpdate, 489 NULL, 490 &mDriverData->Timer 491 ); 492 if (EFI_ERROR (Status)) { 493 goto Error3; 494 } 495 496 Status = gBS->SetTimer (mDriverData->Timer, TimerPeriodic, TICKS_PER_SECOND); 497 if (EFI_ERROR (Status)) { 498 goto Error4; 499 } 500 501 InitializeListHead (&mDriverData->Dns4CacheList); 502 InitializeListHead (&mDriverData->Dns4ServerList); 503 InitializeListHead (&mDriverData->Dns6CacheList); 504 InitializeListHead (&mDriverData->Dns6ServerList); 505 506 return Status; 507 508 Error4: 509 gBS->CloseEvent (mDriverData->Timer); 510 511 Error3: 512 FreePool (mDriverData); 513 514 Error2: 515 gBS->UninstallMultipleProtocolInterfaces ( 516 gDns6DriverBinding.DriverBindingHandle, 517 &gEfiDriverBindingProtocolGuid, 518 &gDns6DriverBinding, 519 &gEfiComponentName2ProtocolGuid, 520 &gDnsComponentName2, 521 &gEfiComponentNameProtocolGuid, 522 &gDnsComponentName, 523 NULL 524 ); 525 526 Error1: 527 gBS->UninstallMultipleProtocolInterfaces ( 528 ImageHandle, 529 &gEfiDriverBindingProtocolGuid, 530 &gDns4DriverBinding, 531 &gEfiComponentName2ProtocolGuid, 532 &gDnsComponentName2, 533 &gEfiComponentNameProtocolGuid, 534 &gDnsComponentName, 535 NULL 536 ); 537 538 return Status; 539 } 540 541 /** 542 Tests to see if this driver supports a given controller. If a child device is provided, 543 it further tests to see if this driver supports creating a handle for the specified child device. 544 545 This function checks to see if the driver specified by This supports the device specified by 546 ControllerHandle. Drivers will typically use the device path attached to 547 ControllerHandle and/or the services from the bus I/O abstraction attached to 548 ControllerHandle to determine if the driver supports ControllerHandle. This function 549 may be called many times during platform initialization. In order to reduce boot times, the tests 550 performed by this function must be very small, and take as little time as possible to execute. This 551 function must not change the state of any hardware devices, and this function must be aware that the 552 device specified by ControllerHandle may already be managed by the same driver or a 553 different driver. This function must match its calls to AllocatePages() with FreePages(), 554 AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol(). 555 Because ControllerHandle may have been previously started by the same driver, if a protocol is 556 already in the opened state, then it must not be closed with CloseProtocol(). This is required 557 to guarantee the state of ControllerHandle is not modified by this function. 558 559 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. 560 @param[in] ControllerHandle The handle of the controller to test. This handle 561 must support a protocol interface that supplies 562 an I/O abstraction to the driver. 563 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This 564 parameter is ignored by device drivers, and is optional for bus 565 drivers. For bus drivers, if this parameter is not NULL, then 566 the bus driver must determine if the bus controller specified 567 by ControllerHandle and the child controller specified 568 by RemainingDevicePath are both supported by this 569 bus driver. 570 571 @retval EFI_SUCCESS The device specified by ControllerHandle and 572 RemainingDevicePath is supported by the driver specified by This. 573 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and 574 RemainingDevicePath is already being managed by the driver 575 specified by This. 576 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and 577 RemainingDevicePath is already being managed by a different 578 driver or an application that requires exclusive access. 579 Currently not implemented. 580 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and 581 RemainingDevicePath is not supported by the driver specified by This. 582 **/ 583 EFI_STATUS 584 EFIAPI 585 Dns4DriverBindingSupported ( 586 IN EFI_DRIVER_BINDING_PROTOCOL *This, 587 IN EFI_HANDLE ControllerHandle, 588 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL 589 ) 590 { 591 EFI_STATUS Status; 592 593 // 594 // Test for the Dns4ServiceBinding Protocol. 595 // 596 Status = gBS->OpenProtocol ( 597 ControllerHandle, 598 &gEfiDns4ServiceBindingProtocolGuid, 599 NULL, 600 This->DriverBindingHandle, 601 ControllerHandle, 602 EFI_OPEN_PROTOCOL_TEST_PROTOCOL 603 ); 604 if (!EFI_ERROR (Status)) { 605 return EFI_ALREADY_STARTED; 606 } 607 608 // 609 // Test for the Udp4ServiceBinding Protocol. 610 // 611 Status = gBS->OpenProtocol ( 612 ControllerHandle, 613 &gEfiUdp4ServiceBindingProtocolGuid, 614 NULL, 615 This->DriverBindingHandle, 616 ControllerHandle, 617 EFI_OPEN_PROTOCOL_TEST_PROTOCOL 618 ); 619 620 return Status; 621 } 622 623 /** 624 Starts a device controller or a bus controller. 625 626 The Start() function is designed to be invoked from the EFI boot service ConnectController(). 627 As a result, much of the error checking on the parameters to Start() has been moved into this 628 common boot service. It is legal to call Start() from other locations, 629 but the following calling restrictions must be followed, or the system behavior will not be deterministic. 630 1. ControllerHandle must be a valid EFI_HANDLE. 631 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned 632 EFI_DEVICE_PATH_PROTOCOL. 633 3. Prior to calling Start(), the Supported() function for the driver specified by This must 634 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS. 635 636 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. 637 @param[in] ControllerHandle The handle of the controller to start. This handle 638 must support a protocol interface that supplies 639 an I/O abstraction to the driver. 640 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This 641 parameter is ignored by device drivers, and is optional for bus 642 drivers. For a bus driver, if this parameter is NULL, then handles 643 for all the children of Controller are created by this driver. 644 If this parameter is not NULL and the first Device Path Node is 645 not the End of Device Path Node, then only the handle for the 646 child device specified by the first Device Path Node of 647 RemainingDevicePath is created by this driver. 648 If the first Device Path Node of RemainingDevicePath is 649 the End of Device Path Node, no child handle is created by this 650 driver. 651 652 @retval EFI_SUCCESS The device was started. 653 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented. 654 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. 655 @retval Others The driver failded to start the device. 656 657 **/ 658 EFI_STATUS 659 EFIAPI 660 Dns4DriverBindingStart ( 661 IN EFI_DRIVER_BINDING_PROTOCOL *This, 662 IN EFI_HANDLE ControllerHandle, 663 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL 664 ) 665 { 666 DNS_SERVICE *DnsSb; 667 EFI_STATUS Status; 668 669 Status = DnsCreateService (ControllerHandle, This->DriverBindingHandle, IP_VERSION_4, &DnsSb); 670 if (EFI_ERROR (Status)) { 671 return Status; 672 } 673 674 ASSERT (DnsSb != NULL); 675 676 Status = gBS->SetTimer (DnsSb->Timer, TimerPeriodic, TICKS_PER_SECOND); 677 if (EFI_ERROR (Status)) { 678 goto ON_ERROR; 679 } 680 681 // 682 // Install the Dns4ServiceBinding Protocol onto ControllerHandle. 683 // 684 Status = gBS->InstallMultipleProtocolInterfaces ( 685 &ControllerHandle, 686 &gEfiDns4ServiceBindingProtocolGuid, 687 &DnsSb->ServiceBinding, 688 NULL 689 ); 690 if (EFI_ERROR (Status)) { 691 goto ON_ERROR; 692 } 693 694 return EFI_SUCCESS; 695 696 ON_ERROR: 697 DnsDestroyService (DnsSb); 698 699 return Status; 700 } 701 702 /** 703 Stops a device controller or a bus controller. 704 705 The Stop() function is designed to be invoked from the EFI boot service DisconnectController(). 706 As a result, much of the error checking on the parameters to Stop() has been moved 707 into this common boot service. It is legal to call Stop() from other locations, 708 but the following calling restrictions must be followed, or the system behavior will not be deterministic. 709 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this 710 same driver's Start() function. 711 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid 712 EFI_HANDLE. In addition, all of these handles must have been created in this driver's 713 Start() function, and the Start() function must have called OpenProtocol() on 714 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER. 715 716 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. 717 @param[in] ControllerHandle A handle to the device being stopped. The handle must 718 support a bus specific I/O protocol for the driver 719 to use to stop the device. 720 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer. 721 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL 722 if NumberOfChildren is 0. 723 724 @retval EFI_SUCCESS The device was stopped. 725 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error. 726 727 **/ 728 EFI_STATUS 729 EFIAPI 730 Dns4DriverBindingStop ( 731 IN EFI_DRIVER_BINDING_PROTOCOL *This, 732 IN EFI_HANDLE ControllerHandle, 733 IN UINTN NumberOfChildren, 734 IN EFI_HANDLE *ChildHandleBuffer OPTIONAL 735 ) 736 { 737 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding; 738 DNS_SERVICE *DnsSb; 739 EFI_HANDLE NicHandle; 740 EFI_STATUS Status; 741 LIST_ENTRY *List; 742 DNS_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context; 743 744 // 745 // DNS driver opens UDP child, So, Controller is a UDP 746 // child handle. Locate the Nic handle first. Then get the 747 // DNS private data back. 748 // 749 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiUdp4ProtocolGuid); 750 751 if (NicHandle == NULL) { 752 return EFI_SUCCESS; 753 } 754 755 Status = gBS->OpenProtocol ( 756 NicHandle, 757 &gEfiDns4ServiceBindingProtocolGuid, 758 (VOID **) &ServiceBinding, 759 This->DriverBindingHandle, 760 NicHandle, 761 EFI_OPEN_PROTOCOL_GET_PROTOCOL 762 ); 763 if (EFI_ERROR (Status)) { 764 return EFI_DEVICE_ERROR; 765 } 766 767 DnsSb = DNS_SERVICE_FROM_THIS (ServiceBinding); 768 769 if (!IsListEmpty (&DnsSb->Dns4ChildrenList)) { 770 // 771 // Destroy the Dns child instance in ChildHandleBuffer. 772 // 773 List = &DnsSb->Dns4ChildrenList; 774 Context.ServiceBinding = ServiceBinding; 775 Context.NumberOfChildren = NumberOfChildren; 776 Context.ChildHandleBuffer = ChildHandleBuffer; 777 Status = NetDestroyLinkList ( 778 List, 779 DnsDestroyChildEntryInHandleBuffer, 780 &Context, 781 NULL 782 ); 783 } 784 785 if (NumberOfChildren == 0 && IsListEmpty (&DnsSb->Dns4ChildrenList)) { 786 gBS->UninstallProtocolInterface ( 787 NicHandle, 788 &gEfiDns4ServiceBindingProtocolGuid, 789 ServiceBinding 790 ); 791 792 DnsDestroyService (DnsSb); 793 794 if (gDnsControllerNameTable != NULL) { 795 FreeUnicodeStringTable (gDnsControllerNameTable); 796 gDnsControllerNameTable = NULL; 797 } 798 799 Status = EFI_SUCCESS; 800 } 801 802 return Status; 803 } 804 805 /** 806 Tests to see if this driver supports a given controller. If a child device is provided, 807 it further tests to see if this driver supports creating a handle for the specified child device. 808 809 This function checks to see if the driver specified by This supports the device specified by 810 ControllerHandle. Drivers will typically use the device path attached to 811 ControllerHandle and/or the services from the bus I/O abstraction attached to 812 ControllerHandle to determine if the driver supports ControllerHandle. This function 813 may be called many times during platform initialization. In order to reduce boot times, the tests 814 performed by this function must be very small, and take as little time as possible to execute. This 815 function must not change the state of any hardware devices, and this function must be aware that the 816 device specified by ControllerHandle may already be managed by the same driver or a 817 different driver. This function must match its calls to AllocatePages() with FreePages(), 818 AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol(). 819 Because ControllerHandle may have been previously started by the same driver, if a protocol is 820 already in the opened state, then it must not be closed with CloseProtocol(). This is required 821 to guarantee the state of ControllerHandle is not modified by this function. 822 823 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. 824 @param[in] ControllerHandle The handle of the controller to test. This handle 825 must support a protocol interface that supplies 826 an I/O abstraction to the driver. 827 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This 828 parameter is ignored by device drivers, and is optional for bus 829 drivers. For bus drivers, if this parameter is not NULL, then 830 the bus driver must determine if the bus controller specified 831 by ControllerHandle and the child controller specified 832 by RemainingDevicePath are both supported by this 833 bus driver. 834 835 @retval EFI_SUCCESS The device specified by ControllerHandle and 836 RemainingDevicePath is supported by the driver specified by This. 837 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and 838 RemainingDevicePath is already being managed by the driver 839 specified by This. 840 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and 841 RemainingDevicePath is already being managed by a different 842 driver or an application that requires exclusive access. 843 Currently not implemented. 844 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and 845 RemainingDevicePath is not supported by the driver specified by This. 846 **/ 847 EFI_STATUS 848 EFIAPI 849 Dns6DriverBindingSupported ( 850 IN EFI_DRIVER_BINDING_PROTOCOL *This, 851 IN EFI_HANDLE ControllerHandle, 852 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL 853 ) 854 { 855 EFI_STATUS Status; 856 857 // 858 // Test for the Dns6ServiceBinding Protocol 859 // 860 Status = gBS->OpenProtocol ( 861 ControllerHandle, 862 &gEfiDns6ServiceBindingProtocolGuid, 863 NULL, 864 This->DriverBindingHandle, 865 ControllerHandle, 866 EFI_OPEN_PROTOCOL_TEST_PROTOCOL 867 ); 868 if (!EFI_ERROR (Status)) { 869 return EFI_ALREADY_STARTED; 870 } 871 872 // 873 // Test for the Udp6ServiceBinding Protocol 874 // 875 Status = gBS->OpenProtocol ( 876 ControllerHandle, 877 &gEfiUdp6ServiceBindingProtocolGuid, 878 NULL, 879 This->DriverBindingHandle, 880 ControllerHandle, 881 EFI_OPEN_PROTOCOL_TEST_PROTOCOL 882 ); 883 884 return Status; 885 } 886 887 /** 888 Starts a device controller or a bus controller. 889 890 The Start() function is designed to be invoked from the EFI boot service ConnectController(). 891 As a result, much of the error checking on the parameters to Start() has been moved into this 892 common boot service. It is legal to call Start() from other locations, 893 but the following calling restrictions must be followed, or the system behavior will not be deterministic. 894 1. ControllerHandle must be a valid EFI_HANDLE. 895 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned 896 EFI_DEVICE_PATH_PROTOCOL. 897 3. Prior to calling Start(), the Supported() function for the driver specified by This must 898 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS. 899 900 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. 901 @param[in] ControllerHandle The handle of the controller to start. This handle 902 must support a protocol interface that supplies 903 an I/O abstraction to the driver. 904 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This 905 parameter is ignored by device drivers, and is optional for bus 906 drivers. For a bus driver, if this parameter is NULL, then handles 907 for all the children of Controller are created by this driver. 908 If this parameter is not NULL and the first Device Path Node is 909 not the End of Device Path Node, then only the handle for the 910 child device specified by the first Device Path Node of 911 RemainingDevicePath is created by this driver. 912 If the first Device Path Node of RemainingDevicePath is 913 the End of Device Path Node, no child handle is created by this 914 driver. 915 916 @retval EFI_SUCCESS The device was started. 917 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented. 918 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. 919 @retval Others The driver failded to start the device. 920 921 **/ 922 EFI_STATUS 923 EFIAPI 924 Dns6DriverBindingStart ( 925 IN EFI_DRIVER_BINDING_PROTOCOL *This, 926 IN EFI_HANDLE ControllerHandle, 927 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL 928 ) 929 { 930 DNS_SERVICE *DnsSb; 931 EFI_STATUS Status; 932 933 Status = DnsCreateService (ControllerHandle, This->DriverBindingHandle, IP_VERSION_6, &DnsSb); 934 if (EFI_ERROR (Status)) { 935 return Status; 936 } 937 938 ASSERT (DnsSb != NULL); 939 940 Status = gBS->SetTimer (DnsSb->Timer, TimerPeriodic, TICKS_PER_SECOND); 941 if (EFI_ERROR (Status)) { 942 goto ON_ERROR; 943 } 944 945 // 946 // Install the Dns6ServiceBinding Protocol onto ControllerHandle 947 // 948 Status = gBS->InstallMultipleProtocolInterfaces ( 949 &ControllerHandle, 950 &gEfiDns6ServiceBindingProtocolGuid, 951 &DnsSb->ServiceBinding, 952 NULL 953 ); 954 955 if (EFI_ERROR (Status)) { 956 goto ON_ERROR; 957 } 958 959 return EFI_SUCCESS; 960 961 ON_ERROR: 962 DnsDestroyService (DnsSb); 963 964 return Status; 965 } 966 967 /** 968 Stops a device controller or a bus controller. 969 970 The Stop() function is designed to be invoked from the EFI boot service DisconnectController(). 971 As a result, much of the error checking on the parameters to Stop() has been moved 972 into this common boot service. It is legal to call Stop() from other locations, 973 but the following calling restrictions must be followed, or the system behavior will not be deterministic. 974 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this 975 same driver's Start() function. 976 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid 977 EFI_HANDLE. In addition, all of these handles must have been created in this driver's 978 Start() function, and the Start() function must have called OpenProtocol() on 979 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER. 980 981 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. 982 @param[in] ControllerHandle A handle to the device being stopped. The handle must 983 support a bus specific I/O protocol for the driver 984 to use to stop the device. 985 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer. 986 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL 987 if NumberOfChildren is 0. 988 989 @retval EFI_SUCCESS The device was stopped. 990 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error. 991 992 **/ 993 EFI_STATUS 994 EFIAPI 995 Dns6DriverBindingStop ( 996 IN EFI_DRIVER_BINDING_PROTOCOL *This, 997 IN EFI_HANDLE ControllerHandle, 998 IN UINTN NumberOfChildren, 999 IN EFI_HANDLE *ChildHandleBuffer OPTIONAL 1000 ) 1001 { 1002 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding; 1003 DNS_SERVICE *DnsSb; 1004 EFI_HANDLE NicHandle; 1005 EFI_STATUS Status; 1006 LIST_ENTRY *List; 1007 DNS_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context; 1008 1009 // 1010 // DNS driver opens UDP child, So, Controller is a UDP 1011 // child handle. Locate the Nic handle first. Then get the 1012 // DNS private data back. 1013 // 1014 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiUdp6ProtocolGuid); 1015 1016 if (NicHandle == NULL) { 1017 return EFI_SUCCESS; 1018 } 1019 1020 Status = gBS->OpenProtocol ( 1021 NicHandle, 1022 &gEfiDns6ServiceBindingProtocolGuid, 1023 (VOID **) &ServiceBinding, 1024 This->DriverBindingHandle, 1025 NicHandle, 1026 EFI_OPEN_PROTOCOL_GET_PROTOCOL 1027 ); 1028 if (EFI_ERROR (Status)) { 1029 return EFI_DEVICE_ERROR; 1030 } 1031 1032 DnsSb = DNS_SERVICE_FROM_THIS (ServiceBinding); 1033 1034 if (!IsListEmpty (&DnsSb->Dns6ChildrenList)) { 1035 // 1036 // Destroy the Dns child instance in ChildHandleBuffer. 1037 // 1038 List = &DnsSb->Dns6ChildrenList; 1039 Context.ServiceBinding = ServiceBinding; 1040 Context.NumberOfChildren = NumberOfChildren; 1041 Context.ChildHandleBuffer = ChildHandleBuffer; 1042 Status = NetDestroyLinkList ( 1043 List, 1044 DnsDestroyChildEntryInHandleBuffer, 1045 &Context, 1046 NULL 1047 ); 1048 } 1049 1050 if (NumberOfChildren == 0 && IsListEmpty (&DnsSb->Dns6ChildrenList)) { 1051 gBS->UninstallProtocolInterface ( 1052 NicHandle, 1053 &gEfiDns6ServiceBindingProtocolGuid, 1054 ServiceBinding 1055 ); 1056 1057 DnsDestroyService (DnsSb); 1058 1059 if (gDnsControllerNameTable != NULL) { 1060 FreeUnicodeStringTable (gDnsControllerNameTable); 1061 gDnsControllerNameTable = NULL; 1062 } 1063 1064 Status = EFI_SUCCESS; 1065 } 1066 1067 return Status; 1068 } 1069 1070 /** 1071 Creates a child handle and installs a protocol. 1072 1073 The CreateChild() function installs a protocol on ChildHandle. 1074 If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle. 1075 If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle. 1076 1077 @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance. 1078 @param[in] ChildHandle Pointer to the handle of the child to create. If it is NULL, 1079 then a new handle is created. If it is a pointer to an existing UEFI handle, 1080 then the protocol is added to the existing UEFI handle. 1081 1082 @retval EFI_SUCCES The protocol was added to ChildHandle. 1083 @retval EFI_INVALID_PARAMETER ChildHandle is NULL. 1084 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to create 1085 the child 1086 @retval other The child handle was not created 1087 1088 **/ 1089 EFI_STATUS 1090 EFIAPI 1091 Dns4ServiceBindingCreateChild ( 1092 IN EFI_SERVICE_BINDING_PROTOCOL *This, 1093 IN EFI_HANDLE *ChildHandle 1094 ) 1095 { 1096 DNS_SERVICE *DnsSb; 1097 DNS_INSTANCE *Instance; 1098 EFI_STATUS Status; 1099 EFI_TPL OldTpl; 1100 VOID *Udp4; 1101 1102 if ((This == NULL) || (ChildHandle == NULL)) { 1103 return EFI_INVALID_PARAMETER; 1104 } 1105 1106 DnsSb = DNS_SERVICE_FROM_THIS (This); 1107 1108 Status = DnsCreateInstance (DnsSb, &Instance); 1109 if (EFI_ERROR (Status)) { 1110 return Status; 1111 } 1112 ASSERT (Instance != NULL); 1113 1114 // 1115 // Install the DNS protocol onto ChildHandle 1116 // 1117 Status = gBS->InstallMultipleProtocolInterfaces ( 1118 ChildHandle, 1119 &gEfiDns4ProtocolGuid, 1120 &Instance->Dns4, 1121 NULL 1122 ); 1123 if (EFI_ERROR (Status)) { 1124 goto ON_ERROR; 1125 } 1126 1127 Instance->ChildHandle = *ChildHandle; 1128 1129 // 1130 // Open the Udp4 protocol BY_CHILD. 1131 // 1132 Status = gBS->OpenProtocol ( 1133 DnsSb->ConnectUdp->UdpHandle, 1134 &gEfiUdp4ProtocolGuid, 1135 (VOID **) &Udp4, 1136 gDns4DriverBinding.DriverBindingHandle, 1137 Instance->ChildHandle, 1138 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER 1139 ); 1140 if (EFI_ERROR (Status)) { 1141 gBS->UninstallMultipleProtocolInterfaces ( 1142 Instance->ChildHandle, 1143 &gEfiDns4ProtocolGuid, 1144 &Instance->Dns4, 1145 NULL 1146 ); 1147 1148 goto ON_ERROR; 1149 } 1150 1151 // 1152 // Open the Udp4 protocol by child. 1153 // 1154 Status = gBS->OpenProtocol ( 1155 Instance->UdpIo->UdpHandle, 1156 &gEfiUdp4ProtocolGuid, 1157 (VOID **) &Udp4, 1158 gDns4DriverBinding.DriverBindingHandle, 1159 Instance->ChildHandle, 1160 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER 1161 ); 1162 if (EFI_ERROR (Status)) { 1163 // 1164 // Close the Udp4 protocol. 1165 // 1166 gBS->CloseProtocol ( 1167 DnsSb->ConnectUdp->UdpHandle, 1168 &gEfiUdp4ProtocolGuid, 1169 gDns4DriverBinding.DriverBindingHandle, 1170 ChildHandle 1171 ); 1172 1173 gBS->UninstallMultipleProtocolInterfaces ( 1174 Instance->ChildHandle, 1175 &gEfiDns4ProtocolGuid, 1176 &Instance->Dns4, 1177 NULL 1178 ); 1179 1180 goto ON_ERROR; 1181 } 1182 1183 // 1184 // Add it to the parent's child list. 1185 // 1186 OldTpl = gBS->RaiseTPL (TPL_CALLBACK); 1187 1188 InsertTailList (&DnsSb->Dns4ChildrenList, &Instance->Link); 1189 DnsSb->Dns4ChildrenNum++; 1190 1191 gBS->RestoreTPL (OldTpl); 1192 1193 return EFI_SUCCESS; 1194 1195 ON_ERROR: 1196 1197 DnsDestroyInstance (Instance); 1198 return Status; 1199 } 1200 1201 /** 1202 Destroys a child handle with a protocol installed on it. 1203 1204 The DestroyChild() function does the opposite of CreateChild(). It removes a protocol 1205 that was installed by CreateChild() from ChildHandle. If the removed protocol is the 1206 last protocol on ChildHandle, then ChildHandle is destroyed. 1207 1208 @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance. 1209 @param[in] ChildHandle Handle of the child to destroy 1210 1211 @retval EFI_SUCCES The protocol was removed from ChildHandle. 1212 @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is being removed. 1213 @retval EFI_INVALID_PARAMETER Child handle is NULL. 1214 @retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle 1215 because its services are being used. 1216 @retval other The child handle was not destroyed 1217 1218 **/ 1219 EFI_STATUS 1220 EFIAPI 1221 Dns4ServiceBindingDestroyChild ( 1222 IN EFI_SERVICE_BINDING_PROTOCOL *This, 1223 IN EFI_HANDLE ChildHandle 1224 ) 1225 { 1226 DNS_SERVICE *DnsSb; 1227 DNS_INSTANCE *Instance; 1228 1229 EFI_DNS4_PROTOCOL *Dns4; 1230 EFI_STATUS Status; 1231 EFI_TPL OldTpl; 1232 1233 if ((This == NULL) || (ChildHandle == NULL)) { 1234 return EFI_INVALID_PARAMETER; 1235 } 1236 1237 // 1238 // Retrieve the private context data structures 1239 // 1240 Status = gBS->OpenProtocol ( 1241 ChildHandle, 1242 &gEfiDns4ProtocolGuid, 1243 (VOID **) &Dns4, 1244 gDns4DriverBinding.DriverBindingHandle, 1245 ChildHandle, 1246 EFI_OPEN_PROTOCOL_GET_PROTOCOL 1247 ); 1248 1249 if (EFI_ERROR (Status)) { 1250 return EFI_UNSUPPORTED; 1251 } 1252 1253 Instance = DNS_INSTANCE_FROM_THIS_PROTOCOL4 (Dns4); 1254 DnsSb = DNS_SERVICE_FROM_THIS (This); 1255 1256 if (Instance->Service != DnsSb) { 1257 return EFI_INVALID_PARAMETER; 1258 } 1259 1260 if (Instance->InDestroy) { 1261 return EFI_SUCCESS; 1262 } 1263 1264 OldTpl = gBS->RaiseTPL (TPL_CALLBACK); 1265 1266 Instance->InDestroy = TRUE; 1267 1268 // 1269 // Close the Udp4 protocol. 1270 // 1271 gBS->CloseProtocol ( 1272 DnsSb->ConnectUdp->UdpHandle, 1273 &gEfiUdp4ProtocolGuid, 1274 gDns4DriverBinding.DriverBindingHandle, 1275 ChildHandle 1276 ); 1277 1278 gBS->CloseProtocol ( 1279 Instance->UdpIo->UdpHandle, 1280 &gEfiUdp4ProtocolGuid, 1281 gDns4DriverBinding.DriverBindingHandle, 1282 ChildHandle 1283 ); 1284 1285 gBS->RestoreTPL (OldTpl); 1286 1287 // 1288 // Uninstall the DNS protocol first to enable a top down destruction. 1289 // 1290 Status = gBS->UninstallProtocolInterface ( 1291 ChildHandle, 1292 &gEfiDns4ProtocolGuid, 1293 Dns4 1294 ); 1295 1296 OldTpl = gBS->RaiseTPL (TPL_CALLBACK); 1297 1298 if (EFI_ERROR (Status)) { 1299 Instance->InDestroy = FALSE; 1300 gBS->RestoreTPL (OldTpl); 1301 return Status; 1302 } 1303 1304 RemoveEntryList (&Instance->Link); 1305 DnsSb->Dns4ChildrenNum--; 1306 1307 gBS->RestoreTPL (OldTpl); 1308 1309 DnsDestroyInstance (Instance); 1310 return EFI_SUCCESS; 1311 } 1312 1313 /** 1314 Creates a child handle and installs a protocol. 1315 1316 The CreateChild() function installs a protocol on ChildHandle. 1317 If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle. 1318 If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle. 1319 1320 @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance. 1321 @param[in] ChildHandle Pointer to the handle of the child to create. If it is NULL, 1322 then a new handle is created. If it is a pointer to an existing UEFI handle, 1323 then the protocol is added to the existing UEFI handle. 1324 1325 @retval EFI_SUCCES The protocol was added to ChildHandle. 1326 @retval EFI_INVALID_PARAMETER ChildHandle is NULL. 1327 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to create 1328 the child 1329 @retval other The child handle was not created 1330 1331 **/ 1332 EFI_STATUS 1333 EFIAPI 1334 Dns6ServiceBindingCreateChild ( 1335 IN EFI_SERVICE_BINDING_PROTOCOL *This, 1336 IN EFI_HANDLE *ChildHandle 1337 ) 1338 { 1339 DNS_SERVICE *DnsSb; 1340 DNS_INSTANCE *Instance; 1341 EFI_STATUS Status; 1342 EFI_TPL OldTpl; 1343 VOID *Udp6; 1344 1345 if ((This == NULL) || (ChildHandle == NULL)) { 1346 return EFI_INVALID_PARAMETER; 1347 } 1348 1349 DnsSb = DNS_SERVICE_FROM_THIS (This); 1350 1351 Status = DnsCreateInstance (DnsSb, &Instance); 1352 if (EFI_ERROR (Status)) { 1353 return Status; 1354 } 1355 ASSERT (Instance != NULL); 1356 1357 // 1358 // Install the DNS protocol onto ChildHandle 1359 // 1360 Status = gBS->InstallMultipleProtocolInterfaces ( 1361 ChildHandle, 1362 &gEfiDns6ProtocolGuid, 1363 &Instance->Dns6, 1364 NULL 1365 ); 1366 if (EFI_ERROR (Status)) { 1367 goto ON_ERROR; 1368 } 1369 1370 Instance->ChildHandle = *ChildHandle; 1371 1372 // 1373 // Open the Udp6 protocol BY_CHILD. 1374 // 1375 Status = gBS->OpenProtocol ( 1376 DnsSb->ConnectUdp->UdpHandle, 1377 &gEfiUdp6ProtocolGuid, 1378 (VOID **) &Udp6, 1379 gDns6DriverBinding.DriverBindingHandle, 1380 Instance->ChildHandle, 1381 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER 1382 ); 1383 if (EFI_ERROR (Status)) { 1384 gBS->UninstallMultipleProtocolInterfaces ( 1385 Instance->ChildHandle, 1386 &gEfiDns6ProtocolGuid, 1387 &Instance->Dns6, 1388 NULL 1389 ); 1390 1391 goto ON_ERROR; 1392 } 1393 1394 // 1395 // Open the Udp6 protocol by child. 1396 // 1397 Status = gBS->OpenProtocol ( 1398 Instance->UdpIo->UdpHandle, 1399 &gEfiUdp6ProtocolGuid, 1400 (VOID **) &Udp6, 1401 gDns6DriverBinding.DriverBindingHandle, 1402 Instance->ChildHandle, 1403 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER 1404 ); 1405 if (EFI_ERROR (Status)) { 1406 // 1407 // Close the Udp6 protocol. 1408 // 1409 gBS->CloseProtocol ( 1410 DnsSb->ConnectUdp->UdpHandle, 1411 &gEfiUdp6ProtocolGuid, 1412 gDns6DriverBinding.DriverBindingHandle, 1413 ChildHandle 1414 ); 1415 1416 gBS->UninstallMultipleProtocolInterfaces ( 1417 Instance->ChildHandle, 1418 &gEfiDns6ProtocolGuid, 1419 &Instance->Dns6, 1420 NULL 1421 ); 1422 1423 goto ON_ERROR; 1424 } 1425 1426 // 1427 // Add it to the parent's child list. 1428 // 1429 OldTpl = gBS->RaiseTPL (TPL_CALLBACK); 1430 1431 InsertTailList (&DnsSb->Dns6ChildrenList, &Instance->Link); 1432 DnsSb->Dns6ChildrenNum++; 1433 1434 gBS->RestoreTPL (OldTpl); 1435 1436 return EFI_SUCCESS; 1437 1438 ON_ERROR: 1439 1440 DnsDestroyInstance (Instance); 1441 return Status; 1442 } 1443 1444 /** 1445 Destroys a child handle with a protocol installed on it. 1446 1447 The DestroyChild() function does the opposite of CreateChild(). It removes a protocol 1448 that was installed by CreateChild() from ChildHandle. If the removed protocol is the 1449 last protocol on ChildHandle, then ChildHandle is destroyed. 1450 1451 @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance. 1452 @param[in] ChildHandle Handle of the child to destroy 1453 1454 @retval EFI_SUCCES The protocol was removed from ChildHandle. 1455 @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is being removed. 1456 @retval EFI_INVALID_PARAMETER Child handle is NULL. 1457 @retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle 1458 because its services are being used. 1459 @retval other The child handle was not destroyed 1460 1461 **/ 1462 EFI_STATUS 1463 EFIAPI 1464 Dns6ServiceBindingDestroyChild ( 1465 IN EFI_SERVICE_BINDING_PROTOCOL *This, 1466 IN EFI_HANDLE ChildHandle 1467 ) 1468 { 1469 DNS_SERVICE *DnsSb; 1470 DNS_INSTANCE *Instance; 1471 1472 EFI_DNS6_PROTOCOL *Dns6; 1473 EFI_STATUS Status; 1474 EFI_TPL OldTpl; 1475 1476 if ((This == NULL) || (ChildHandle == NULL)) { 1477 return EFI_INVALID_PARAMETER; 1478 } 1479 1480 // 1481 // Retrieve the private context data structures 1482 // 1483 Status = gBS->OpenProtocol ( 1484 ChildHandle, 1485 &gEfiDns6ProtocolGuid, 1486 (VOID **) &Dns6, 1487 gDns6DriverBinding.DriverBindingHandle, 1488 ChildHandle, 1489 EFI_OPEN_PROTOCOL_GET_PROTOCOL 1490 ); 1491 1492 if (EFI_ERROR (Status)) { 1493 return EFI_UNSUPPORTED; 1494 } 1495 1496 Instance = DNS_INSTANCE_FROM_THIS_PROTOCOL6 (Dns6); 1497 DnsSb = DNS_SERVICE_FROM_THIS (This); 1498 1499 if (Instance->Service != DnsSb) { 1500 return EFI_INVALID_PARAMETER; 1501 } 1502 1503 if (Instance->InDestroy) { 1504 return EFI_SUCCESS; 1505 } 1506 1507 OldTpl = gBS->RaiseTPL (TPL_CALLBACK); 1508 1509 Instance->InDestroy = TRUE; 1510 1511 // 1512 // Close the Udp6 protocol. 1513 // 1514 gBS->CloseProtocol ( 1515 DnsSb->ConnectUdp->UdpHandle, 1516 &gEfiUdp6ProtocolGuid, 1517 gDns6DriverBinding.DriverBindingHandle, 1518 ChildHandle 1519 ); 1520 1521 gBS->CloseProtocol ( 1522 Instance->UdpIo->UdpHandle, 1523 &gEfiUdp6ProtocolGuid, 1524 gDns6DriverBinding.DriverBindingHandle, 1525 ChildHandle 1526 ); 1527 1528 gBS->RestoreTPL (OldTpl); 1529 1530 // 1531 // Uninstall the DNS protocol first to enable a top down destruction. 1532 // 1533 Status = gBS->UninstallProtocolInterface ( 1534 ChildHandle, 1535 &gEfiDns6ProtocolGuid, 1536 Dns6 1537 ); 1538 1539 OldTpl = gBS->RaiseTPL (TPL_CALLBACK); 1540 1541 if (EFI_ERROR (Status)) { 1542 Instance->InDestroy = FALSE; 1543 gBS->RestoreTPL (OldTpl); 1544 return Status; 1545 } 1546 1547 RemoveEntryList (&Instance->Link); 1548 DnsSb->Dns6ChildrenNum--; 1549 1550 gBS->RestoreTPL (OldTpl); 1551 1552 DnsDestroyInstance (Instance); 1553 return EFI_SUCCESS; 1554 } 1555