1 /** @file 2 The driver binding and service binding protocol for the TCP driver. 3 4 Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR> 5 6 This program and the accompanying materials 7 are licensed and made available under the terms and conditions of the BSD License 8 which accompanies this distribution. The full text of the license may be found at 9 http://opensource.org/licenses/bsd-license.php. 10 11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 13 14 **/ 15 16 #include "TcpMain.h" 17 18 UINT16 mTcp4RandomPort; 19 UINT16 mTcp6RandomPort; 20 21 TCP_HEARTBEAT_TIMER mTcpTimer = { 22 NULL, 23 0 24 }; 25 26 EFI_TCP4_PROTOCOL gTcp4ProtocolTemplate = { 27 Tcp4GetModeData, 28 Tcp4Configure, 29 Tcp4Routes, 30 Tcp4Connect, 31 Tcp4Accept, 32 Tcp4Transmit, 33 Tcp4Receive, 34 Tcp4Close, 35 Tcp4Cancel, 36 Tcp4Poll 37 }; 38 39 EFI_TCP6_PROTOCOL gTcp6ProtocolTemplate = { 40 Tcp6GetModeData, 41 Tcp6Configure, 42 Tcp6Connect, 43 Tcp6Accept, 44 Tcp6Transmit, 45 Tcp6Receive, 46 Tcp6Close, 47 Tcp6Cancel, 48 Tcp6Poll 49 }; 50 51 SOCK_INIT_DATA mTcpDefaultSockData = { 52 SockStream, 53 SO_CLOSED, 54 NULL, 55 TCP_BACKLOG, 56 TCP_SND_BUF_SIZE, 57 TCP_RCV_BUF_SIZE, 58 IP_VERSION_4, 59 NULL, 60 TcpCreateSocketCallback, 61 TcpDestroySocketCallback, 62 NULL, 63 NULL, 64 0, 65 TcpDispatcher, 66 NULL, 67 }; 68 69 EFI_DRIVER_BINDING_PROTOCOL gTcp4DriverBinding = { 70 Tcp4DriverBindingSupported, 71 Tcp4DriverBindingStart, 72 Tcp4DriverBindingStop, 73 0xa, 74 NULL, 75 NULL 76 }; 77 78 EFI_DRIVER_BINDING_PROTOCOL gTcp6DriverBinding = { 79 Tcp6DriverBindingSupported, 80 Tcp6DriverBindingStart, 81 Tcp6DriverBindingStop, 82 0xa, 83 NULL, 84 NULL 85 }; 86 87 EFI_SERVICE_BINDING_PROTOCOL gTcpServiceBinding = { 88 TcpServiceBindingCreateChild, 89 TcpServiceBindingDestroyChild 90 }; 91 92 93 /** 94 Create and start the heartbeat timer for the TCP driver. 95 96 @retval EFI_SUCCESS The timer was successfully created and started. 97 @retval other The timer was not created. 98 99 **/ 100 EFI_STATUS 101 TcpCreateTimer ( 102 VOID 103 ) 104 { 105 EFI_STATUS Status; 106 107 Status = EFI_SUCCESS; 108 109 if (mTcpTimer.RefCnt == 0) { 110 111 Status = gBS->CreateEvent ( 112 EVT_TIMER | EVT_NOTIFY_SIGNAL, 113 TPL_NOTIFY, 114 TcpTicking, 115 NULL, 116 &mTcpTimer.TimerEvent 117 ); 118 if (!EFI_ERROR (Status)) { 119 120 Status = gBS->SetTimer ( 121 mTcpTimer.TimerEvent, 122 TimerPeriodic, 123 (UINT64) (TICKS_PER_SECOND / TCP_TICK_HZ) 124 ); 125 } 126 } 127 128 if (!EFI_ERROR (Status)) { 129 130 mTcpTimer.RefCnt++; 131 } 132 133 return Status; 134 } 135 136 /** 137 Stop and destroy the heartbeat timer for TCP driver. 138 139 **/ 140 VOID 141 TcpDestroyTimer ( 142 VOID 143 ) 144 { 145 ASSERT (mTcpTimer.RefCnt > 0); 146 147 mTcpTimer.RefCnt--; 148 149 if (mTcpTimer.RefCnt > 0) { 150 return; 151 } 152 153 gBS->SetTimer (mTcpTimer.TimerEvent, TimerCancel, 0); 154 gBS->CloseEvent (mTcpTimer.TimerEvent); 155 mTcpTimer.TimerEvent = NULL; 156 } 157 158 /** 159 The entry point for Tcp driver, which is used to install Tcp driver on the ImageHandle. 160 161 @param[in] ImageHandle The firmware allocated handle for this driver image. 162 @param[in] SystemTable Pointer to the EFI system table. 163 164 @retval EFI_SUCCESS The driver loaded. 165 @retval other The driver did not load. 166 167 **/ 168 EFI_STATUS 169 EFIAPI 170 TcpDriverEntryPoint ( 171 IN EFI_HANDLE ImageHandle, 172 IN EFI_SYSTEM_TABLE *SystemTable 173 ) 174 { 175 EFI_STATUS Status; 176 UINT32 Seed; 177 178 // 179 // Install the TCP Driver Binding Protocol 180 // 181 Status = EfiLibInstallDriverBindingComponentName2 ( 182 ImageHandle, 183 SystemTable, 184 &gTcp4DriverBinding, 185 ImageHandle, 186 &gTcpComponentName, 187 &gTcpComponentName2 188 ); 189 if (EFI_ERROR (Status)) { 190 return Status; 191 } 192 193 // 194 // Install the TCP Driver Binding Protocol 195 // 196 Status = EfiLibInstallDriverBindingComponentName2 ( 197 ImageHandle, 198 SystemTable, 199 &gTcp6DriverBinding, 200 NULL, 201 &gTcpComponentName, 202 &gTcpComponentName2 203 ); 204 if (EFI_ERROR (Status)) { 205 gBS->UninstallMultipleProtocolInterfaces ( 206 ImageHandle, 207 &gEfiDriverBindingProtocolGuid, 208 &gTcp4DriverBinding, 209 &gEfiComponentName2ProtocolGuid, 210 &gTcpComponentName2, 211 &gEfiComponentNameProtocolGuid, 212 &gTcpComponentName, 213 NULL 214 ); 215 return Status; 216 } 217 218 // 219 // Initialize ISS and random port. 220 // 221 Seed = NetRandomInitSeed (); 222 mTcpGlobalIss = NET_RANDOM (Seed) % mTcpGlobalIss; 223 mTcp4RandomPort = (UINT16) (TCP_PORT_KNOWN + (NET_RANDOM (Seed) % TCP_PORT_KNOWN)); 224 mTcp6RandomPort = mTcp4RandomPort; 225 226 return EFI_SUCCESS; 227 } 228 229 /** 230 Create a new TCP4 or TCP6 driver service binding protocol 231 232 @param[in] Controller Controller handle of device to bind driver to. 233 @param[in] Image The TCP driver's image handle. 234 @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6. 235 236 @retval EFI_OUT_OF_RESOURCES Failed to allocate some resources. 237 @retval EFI_SUCCESS A new IP6 service binding private was created. 238 239 **/ 240 EFI_STATUS 241 TcpCreateService ( 242 IN EFI_HANDLE Controller, 243 IN EFI_HANDLE Image, 244 IN UINT8 IpVersion 245 ) 246 { 247 EFI_STATUS Status; 248 EFI_GUID *IpServiceBindingGuid; 249 EFI_GUID *TcpServiceBindingGuid; 250 TCP_SERVICE_DATA *TcpServiceData; 251 IP_IO_OPEN_DATA OpenData; 252 253 if (IpVersion == IP_VERSION_4) { 254 IpServiceBindingGuid = &gEfiIp4ServiceBindingProtocolGuid; 255 TcpServiceBindingGuid = &gEfiTcp4ServiceBindingProtocolGuid; 256 } else { 257 IpServiceBindingGuid = &gEfiIp6ServiceBindingProtocolGuid; 258 TcpServiceBindingGuid = &gEfiTcp6ServiceBindingProtocolGuid; 259 } 260 261 Status = gBS->OpenProtocol ( 262 Controller, 263 TcpServiceBindingGuid, 264 NULL, 265 Image, 266 Controller, 267 EFI_OPEN_PROTOCOL_TEST_PROTOCOL 268 ); 269 if (!EFI_ERROR (Status)) { 270 return EFI_ALREADY_STARTED; 271 } 272 273 Status = gBS->OpenProtocol ( 274 Controller, 275 IpServiceBindingGuid, 276 NULL, 277 Image, 278 Controller, 279 EFI_OPEN_PROTOCOL_TEST_PROTOCOL 280 ); 281 if (EFI_ERROR (Status)) { 282 return EFI_UNSUPPORTED; 283 } 284 285 // 286 // Create the TCP service data. 287 // 288 TcpServiceData = AllocateZeroPool (sizeof (TCP_SERVICE_DATA)); 289 if (TcpServiceData == NULL) { 290 return EFI_OUT_OF_RESOURCES; 291 } 292 293 TcpServiceData->Signature = TCP_DRIVER_SIGNATURE; 294 TcpServiceData->ControllerHandle = Controller; 295 TcpServiceData->DriverBindingHandle = Image; 296 TcpServiceData->IpVersion = IpVersion; 297 CopyMem ( 298 &TcpServiceData->ServiceBinding, 299 &gTcpServiceBinding, 300 sizeof (EFI_SERVICE_BINDING_PROTOCOL) 301 ); 302 303 TcpServiceData->IpIo = IpIoCreate (Image, Controller, IpVersion); 304 if (TcpServiceData->IpIo == NULL) { 305 Status = EFI_OUT_OF_RESOURCES; 306 goto ON_ERROR; 307 } 308 309 310 InitializeListHead (&TcpServiceData->SocketList); 311 ZeroMem (&OpenData, sizeof (IP_IO_OPEN_DATA)); 312 313 if (IpVersion == IP_VERSION_4) { 314 CopyMem ( 315 &OpenData.IpConfigData.Ip4CfgData, 316 &mIp4IoDefaultIpConfigData, 317 sizeof (EFI_IP4_CONFIG_DATA) 318 ); 319 OpenData.IpConfigData.Ip4CfgData.DefaultProtocol = EFI_IP_PROTO_TCP; 320 } else { 321 CopyMem ( 322 &OpenData.IpConfigData.Ip6CfgData, 323 &mIp6IoDefaultIpConfigData, 324 sizeof (EFI_IP6_CONFIG_DATA) 325 ); 326 OpenData.IpConfigData.Ip6CfgData.DefaultProtocol = EFI_IP_PROTO_TCP; 327 } 328 329 OpenData.PktRcvdNotify = TcpRxCallback; 330 Status = IpIoOpen (TcpServiceData->IpIo, &OpenData); 331 if (EFI_ERROR (Status)) { 332 goto ON_ERROR; 333 } 334 335 Status = TcpCreateTimer (); 336 if (EFI_ERROR (Status)) { 337 goto ON_ERROR; 338 } 339 340 Status = gBS->InstallMultipleProtocolInterfaces ( 341 &Controller, 342 TcpServiceBindingGuid, 343 &TcpServiceData->ServiceBinding, 344 NULL 345 ); 346 if (EFI_ERROR (Status)) { 347 TcpDestroyTimer (); 348 349 goto ON_ERROR; 350 } 351 352 return EFI_SUCCESS; 353 354 ON_ERROR: 355 356 if (TcpServiceData->IpIo != NULL) { 357 IpIoDestroy (TcpServiceData->IpIo); 358 TcpServiceData->IpIo = NULL; 359 } 360 361 FreePool (TcpServiceData); 362 363 return Status; 364 } 365 366 /** 367 Callback function which provided by user to remove one node in NetDestroyLinkList process. 368 369 @param[in] Entry The entry to be removed. 370 @param[in] Context Pointer to the callback context corresponds to the Context in NetDestroyLinkList. 371 372 @retval EFI_SUCCESS The entry has been removed successfully. 373 @retval Others Fail to remove the entry. 374 375 **/ 376 EFI_STATUS 377 EFIAPI 378 TcpDestroyChildEntryInHandleBuffer ( 379 IN LIST_ENTRY *Entry, 380 IN VOID *Context 381 ) 382 { 383 SOCKET *Sock; 384 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding; 385 UINTN NumberOfChildren; 386 EFI_HANDLE *ChildHandleBuffer; 387 388 if (Entry == NULL || Context == NULL) { 389 return EFI_INVALID_PARAMETER; 390 } 391 392 Sock = NET_LIST_USER_STRUCT_S (Entry, SOCKET, Link, SOCK_SIGNATURE); 393 ServiceBinding = ((TCP_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ServiceBinding; 394 NumberOfChildren = ((TCP_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->NumberOfChildren; 395 ChildHandleBuffer = ((TCP_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ChildHandleBuffer; 396 397 if (!NetIsInHandleBuffer (Sock->SockHandle, NumberOfChildren, ChildHandleBuffer)) { 398 return EFI_SUCCESS; 399 } 400 401 return ServiceBinding->DestroyChild (ServiceBinding, Sock->SockHandle); 402 } 403 404 /** 405 Destroy a TCP6 or TCP4 service binding instance. It will release all 406 the resources allocated by the instance. 407 408 @param[in] Controller Controller handle of device to bind driver to. 409 @param[in] ImageHandle The TCP driver's image handle. 410 @param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If number 411 of children is zero stop the entire bus driver. 412 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL 413 if NumberOfChildren is 0. 414 @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6 415 416 @retval EFI_SUCCESS The resources used by the instance were cleaned up. 417 @retval Others Failed to clean up some of the resources. 418 419 **/ 420 EFI_STATUS 421 TcpDestroyService ( 422 IN EFI_HANDLE Controller, 423 IN EFI_HANDLE ImageHandle, 424 IN UINTN NumberOfChildren, 425 IN EFI_HANDLE *ChildHandleBuffer, OPTIONAL 426 IN UINT8 IpVersion 427 ) 428 { 429 EFI_HANDLE NicHandle; 430 EFI_GUID *IpProtocolGuid; 431 EFI_GUID *ServiceBindingGuid; 432 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding; 433 TCP_SERVICE_DATA *TcpServiceData; 434 EFI_STATUS Status; 435 LIST_ENTRY *List; 436 TCP_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context; 437 438 ASSERT ((IpVersion == IP_VERSION_4) || (IpVersion == IP_VERSION_6)); 439 440 if (IpVersion == IP_VERSION_4) { 441 IpProtocolGuid = &gEfiIp4ProtocolGuid; 442 ServiceBindingGuid = &gEfiTcp4ServiceBindingProtocolGuid; 443 } else { 444 IpProtocolGuid = &gEfiIp6ProtocolGuid; 445 ServiceBindingGuid = &gEfiTcp6ServiceBindingProtocolGuid; 446 } 447 448 NicHandle = NetLibGetNicHandle (Controller, IpProtocolGuid); 449 if (NicHandle == NULL) { 450 return EFI_SUCCESS; 451 } 452 453 Status = gBS->OpenProtocol ( 454 NicHandle, 455 ServiceBindingGuid, 456 (VOID **) &ServiceBinding, 457 ImageHandle, 458 Controller, 459 EFI_OPEN_PROTOCOL_GET_PROTOCOL 460 ); 461 if (EFI_ERROR (Status)) { 462 return EFI_DEVICE_ERROR; 463 } 464 465 TcpServiceData = TCP_SERVICE_FROM_THIS (ServiceBinding); 466 467 if (NumberOfChildren != 0) { 468 List = &TcpServiceData->SocketList; 469 Context.ServiceBinding = ServiceBinding; 470 Context.NumberOfChildren = NumberOfChildren; 471 Context.ChildHandleBuffer = ChildHandleBuffer; 472 Status = NetDestroyLinkList ( 473 List, 474 TcpDestroyChildEntryInHandleBuffer, 475 &Context, 476 NULL 477 ); 478 } else if (IsListEmpty (&TcpServiceData->SocketList)) { 479 // 480 // Uninstall TCP servicebinding protocol 481 // 482 gBS->UninstallMultipleProtocolInterfaces ( 483 NicHandle, 484 ServiceBindingGuid, 485 ServiceBinding, 486 NULL 487 ); 488 489 // 490 // Destroy the IpIO consumed by TCP driver 491 // 492 IpIoDestroy (TcpServiceData->IpIo); 493 TcpServiceData->IpIo = NULL; 494 495 // 496 // Destroy the heartbeat timer. 497 // 498 TcpDestroyTimer (); 499 500 // 501 // Release the TCP service data 502 // 503 FreePool (TcpServiceData); 504 505 Status = EFI_SUCCESS; 506 } 507 508 return Status; 509 } 510 511 /** 512 Test to see if this driver supports ControllerHandle. 513 514 @param[in] This Protocol instance pointer. 515 @param[in] ControllerHandle Handle of device to test. 516 @param[in] RemainingDevicePath Optional parameter use to pick a specific 517 child device to start. 518 519 @retval EFI_SUCCESS This driver supports this device. 520 @retval EFI_ALREADY_STARTED This driver is already running on this device. 521 @retval other This driver does not support this device. 522 523 **/ 524 EFI_STATUS 525 EFIAPI 526 Tcp4DriverBindingSupported ( 527 IN EFI_DRIVER_BINDING_PROTOCOL *This, 528 IN EFI_HANDLE ControllerHandle, 529 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL 530 ) 531 { 532 EFI_STATUS Status; 533 534 // 535 // Test for the Tcp4ServiceBinding Protocol 536 // 537 Status = gBS->OpenProtocol ( 538 ControllerHandle, 539 &gEfiTcp4ServiceBindingProtocolGuid, 540 NULL, 541 This->DriverBindingHandle, 542 ControllerHandle, 543 EFI_OPEN_PROTOCOL_TEST_PROTOCOL 544 ); 545 if (!EFI_ERROR (Status)) { 546 return EFI_ALREADY_STARTED; 547 } 548 549 // 550 // Test for the Ip4ServiceBinding Protocol 551 // 552 Status = gBS->OpenProtocol ( 553 ControllerHandle, 554 &gEfiIp4ServiceBindingProtocolGuid, 555 NULL, 556 This->DriverBindingHandle, 557 ControllerHandle, 558 EFI_OPEN_PROTOCOL_TEST_PROTOCOL 559 ); 560 return Status; 561 } 562 563 /** 564 Start this driver on ControllerHandle. 565 566 @param[in] This Protocol instance pointer. 567 @param[in] ControllerHandle Handle of device to bind driver to. 568 @param[in] RemainingDevicePath Optional parameter use to pick a specific child 569 device to start. 570 571 @retval EFI_SUCCESS The driver is added to ControllerHandle. 572 @retval EFI_OUT_OF_RESOURCES There are not enough resources to start the 573 driver. 574 @retval other The driver cannot be added to ControllerHandle. 575 576 **/ 577 EFI_STATUS 578 EFIAPI 579 Tcp4DriverBindingStart ( 580 IN EFI_DRIVER_BINDING_PROTOCOL *This, 581 IN EFI_HANDLE ControllerHandle, 582 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL 583 ) 584 { 585 EFI_STATUS Status; 586 587 Status = TcpCreateService (ControllerHandle, This->DriverBindingHandle, IP_VERSION_4); 588 if ((Status == EFI_ALREADY_STARTED) || (Status == EFI_UNSUPPORTED)) { 589 Status = EFI_SUCCESS; 590 } 591 592 return Status; 593 } 594 595 /** 596 Stop this driver on ControllerHandle. 597 598 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. 599 @param[in] ControllerHandle A handle to the device being stopped. The handle must 600 support a bus specific I/O protocol for the driver 601 to use to stop the device. 602 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer. 603 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL 604 if NumberOfChildren is 0. 605 606 @retval EFI_SUCCESS The device was stopped. 607 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error. 608 609 **/ 610 EFI_STATUS 611 EFIAPI 612 Tcp4DriverBindingStop ( 613 IN EFI_DRIVER_BINDING_PROTOCOL *This, 614 IN EFI_HANDLE ControllerHandle, 615 IN UINTN NumberOfChildren, 616 IN EFI_HANDLE *ChildHandleBuffer OPTIONAL 617 ) 618 { 619 return TcpDestroyService ( 620 ControllerHandle, 621 This->DriverBindingHandle, 622 NumberOfChildren, 623 ChildHandleBuffer, 624 IP_VERSION_4 625 ); 626 } 627 628 /** 629 Test to see if this driver supports ControllerHandle. 630 631 @param[in] This Protocol instance pointer. 632 @param[in] ControllerHandle Handle of device to test. 633 @param[in] RemainingDevicePath Optional parameter use to pick a specific 634 child device to start. 635 636 @retval EFI_SUCCESS This driver supports this device. 637 @retval EFI_ALREADY_STARTED This driver is already running on this device. 638 @retval other This driver does not support this device. 639 640 **/ 641 EFI_STATUS 642 EFIAPI 643 Tcp6DriverBindingSupported ( 644 IN EFI_DRIVER_BINDING_PROTOCOL *This, 645 IN EFI_HANDLE ControllerHandle, 646 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL 647 ) 648 { 649 EFI_STATUS Status; 650 651 // 652 // Test for the Tcp6ServiceBinding Protocol 653 // 654 Status = gBS->OpenProtocol ( 655 ControllerHandle, 656 &gEfiTcp6ServiceBindingProtocolGuid, 657 NULL, 658 This->DriverBindingHandle, 659 ControllerHandle, 660 EFI_OPEN_PROTOCOL_TEST_PROTOCOL 661 ); 662 if (!EFI_ERROR (Status)) { 663 return EFI_ALREADY_STARTED; 664 } 665 666 // 667 // Test for the Ip6ServiceBinding Protocol 668 // 669 Status = gBS->OpenProtocol ( 670 ControllerHandle, 671 &gEfiIp6ServiceBindingProtocolGuid, 672 NULL, 673 This->DriverBindingHandle, 674 ControllerHandle, 675 EFI_OPEN_PROTOCOL_TEST_PROTOCOL 676 ); 677 return Status; 678 } 679 680 /** 681 Start this driver on ControllerHandle. 682 683 @param[in] This Protocol instance pointer. 684 @param[in] ControllerHandle Handle of device to bind driver to. 685 @param[in] RemainingDevicePath Optional parameter use to pick a specific child 686 device to start. 687 688 @retval EFI_SUCCESS The driver is added to ControllerHandle. 689 @retval EFI_OUT_OF_RESOURCES There are not enough resources to start the 690 driver. 691 @retval other The driver cannot be added to ControllerHandle. 692 693 **/ 694 EFI_STATUS 695 EFIAPI 696 Tcp6DriverBindingStart ( 697 IN EFI_DRIVER_BINDING_PROTOCOL *This, 698 IN EFI_HANDLE ControllerHandle, 699 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL 700 ) 701 { 702 EFI_STATUS Status; 703 704 Status = TcpCreateService (ControllerHandle, This->DriverBindingHandle, IP_VERSION_6); 705 if ((Status == EFI_ALREADY_STARTED) || (Status == EFI_UNSUPPORTED)) { 706 Status = EFI_SUCCESS; 707 } 708 709 return Status; 710 } 711 712 /** 713 Stop this driver on ControllerHandle. 714 715 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. 716 @param[in] ControllerHandle A handle to the device being stopped. The handle must 717 support a bus specific I/O protocol for the driver 718 to use to stop the device. 719 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer. 720 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL 721 if NumberOfChildren is 0. 722 723 @retval EFI_SUCCESS The device was stopped. 724 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error. 725 726 **/ 727 EFI_STATUS 728 EFIAPI 729 Tcp6DriverBindingStop ( 730 IN EFI_DRIVER_BINDING_PROTOCOL *This, 731 IN EFI_HANDLE ControllerHandle, 732 IN UINTN NumberOfChildren, 733 IN EFI_HANDLE *ChildHandleBuffer OPTIONAL 734 ) 735 { 736 return TcpDestroyService ( 737 ControllerHandle, 738 This->DriverBindingHandle, 739 NumberOfChildren, 740 ChildHandleBuffer, 741 IP_VERSION_6 742 ); 743 } 744 745 /** 746 The Callback funtion called after the TCP socket was created. 747 748 @param[in] This Pointer to the socket just created 749 @param[in] Context Context of the socket 750 751 @retval EFI_SUCCESS This protocol installed successfully. 752 @retval other An error occured. 753 754 **/ 755 EFI_STATUS 756 TcpCreateSocketCallback ( 757 IN SOCKET *This, 758 IN VOID *Context 759 ) 760 { 761 EFI_STATUS Status; 762 TCP_SERVICE_DATA *TcpServiceData; 763 EFI_GUID *IpProtocolGuid; 764 VOID *Ip; 765 766 if (This->IpVersion == IP_VERSION_4) { 767 IpProtocolGuid = &gEfiIp4ProtocolGuid; 768 } else { 769 IpProtocolGuid = &gEfiIp6ProtocolGuid; 770 } 771 772 TcpServiceData = ((TCP_PROTO_DATA *) This->ProtoReserved)->TcpService; 773 774 // 775 // Open the default IP protocol of IP_IO BY_DRIVER. 776 // 777 Status = gBS->OpenProtocol ( 778 TcpServiceData->IpIo->ChildHandle, 779 IpProtocolGuid, 780 &Ip, 781 TcpServiceData->DriverBindingHandle, 782 This->SockHandle, 783 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER 784 ); 785 if (EFI_ERROR (Status)) { 786 return Status; 787 } 788 789 // 790 // Open the device path on the handle where service binding resides on. 791 // 792 Status = gBS->OpenProtocol ( 793 TcpServiceData->ControllerHandle, 794 &gEfiDevicePathProtocolGuid, 795 (VOID **) &This->ParentDevicePath, 796 TcpServiceData->DriverBindingHandle, 797 This->SockHandle, 798 EFI_OPEN_PROTOCOL_GET_PROTOCOL 799 ); 800 if (EFI_ERROR (Status)) { 801 gBS->CloseProtocol ( 802 TcpServiceData->IpIo->ChildHandle, 803 IpProtocolGuid, 804 TcpServiceData->DriverBindingHandle, 805 This->SockHandle 806 ); 807 } else { 808 // 809 // Insert this socket into the SocketList. 810 // 811 InsertTailList (&TcpServiceData->SocketList, &This->Link); 812 } 813 814 return Status; 815 } 816 817 /** 818 The callback function called before the TCP socket was to be destroyed. 819 820 @param[in] This The TCP socket to be destroyed. 821 @param[in] Context The context of the socket. 822 823 **/ 824 VOID 825 TcpDestroySocketCallback ( 826 IN SOCKET *This, 827 IN VOID *Context 828 ) 829 { 830 TCP_SERVICE_DATA *TcpServiceData; 831 EFI_GUID *IpProtocolGuid; 832 833 if (This->IpVersion == IP_VERSION_4) { 834 IpProtocolGuid = &gEfiIp4ProtocolGuid; 835 } else { 836 IpProtocolGuid = &gEfiIp6ProtocolGuid; 837 } 838 839 TcpServiceData = ((TCP_PROTO_DATA *) This->ProtoReserved)->TcpService; 840 841 // 842 // Remove this node from the list. 843 // 844 RemoveEntryList (&This->Link); 845 846 // 847 // Close the IP protocol. 848 // 849 gBS->CloseProtocol ( 850 TcpServiceData->IpIo->ChildHandle, 851 IpProtocolGuid, 852 TcpServiceData->DriverBindingHandle, 853 This->SockHandle 854 ); 855 } 856 857 /** 858 Creates a child handle with a set of TCP services. 859 860 The CreateChild() function installs a protocol on ChildHandle. 861 If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle. 862 If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle. 863 864 @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance. 865 @param[in, out] ChildHandle Pointer to the handle of the child to create. 866 If it is NULL, then a new handle is created. 867 If it is a pointer to an existing UEFI handle, 868 then the protocol is added to the existing UEFI handle. 869 870 @retval EFI_SUCCES The protocol was added to ChildHandle. 871 @retval EFI_INVALID_PARAMETER ChildHandle is NULL. 872 @retval EFI_OUT_OF_RESOURCES There are not enough resources availabe to create 873 the child. 874 @retval other The child handle was not created. 875 876 **/ 877 EFI_STATUS 878 EFIAPI 879 TcpServiceBindingCreateChild ( 880 IN EFI_SERVICE_BINDING_PROTOCOL *This, 881 IN OUT EFI_HANDLE *ChildHandle 882 ) 883 { 884 SOCKET *Sock; 885 TCP_SERVICE_DATA *TcpServiceData; 886 TCP_PROTO_DATA TcpProto; 887 EFI_STATUS Status; 888 EFI_TPL OldTpl; 889 890 if (NULL == This || NULL == ChildHandle) { 891 return EFI_INVALID_PARAMETER; 892 } 893 894 OldTpl = gBS->RaiseTPL (TPL_CALLBACK); 895 896 Status = EFI_SUCCESS; 897 TcpServiceData = TCP_SERVICE_FROM_THIS (This); 898 TcpProto.TcpService = TcpServiceData; 899 TcpProto.TcpPcb = NULL; 900 901 // 902 // Create a tcp instance with defualt Tcp default 903 // sock init data and TcpProto 904 // 905 mTcpDefaultSockData.ProtoData = &TcpProto; 906 mTcpDefaultSockData.DataSize = sizeof (TCP_PROTO_DATA); 907 mTcpDefaultSockData.DriverBinding = TcpServiceData->DriverBindingHandle; 908 mTcpDefaultSockData.IpVersion = TcpServiceData->IpVersion; 909 910 if (TcpServiceData->IpVersion == IP_VERSION_4) { 911 mTcpDefaultSockData.Protocol = &gTcp4ProtocolTemplate; 912 } else { 913 mTcpDefaultSockData.Protocol = &gTcp6ProtocolTemplate; 914 } 915 916 Sock = SockCreateChild (&mTcpDefaultSockData); 917 if (NULL == Sock) { 918 DEBUG ( 919 (EFI_D_ERROR, 920 "TcpDriverBindingCreateChild: No resource to create a Tcp Child\n") 921 ); 922 923 Status = EFI_OUT_OF_RESOURCES; 924 } else { 925 *ChildHandle = Sock->SockHandle; 926 } 927 928 mTcpDefaultSockData.ProtoData = NULL; 929 930 gBS->RestoreTPL (OldTpl); 931 return Status; 932 } 933 934 /** 935 Destroys a child handle with a set of TCP services. 936 937 The DestroyChild() function does the opposite of CreateChild(). It removes a protocol 938 that was installed by CreateChild() from ChildHandle. If the removed protocol is the 939 last protocol on ChildHandle, then ChildHandle is destroyed. 940 941 @param This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance. 942 @param ChildHandle Handle of the child to be destroyed. 943 944 @retval EFI_SUCCES The protocol was removed from ChildHandle. 945 @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is being removed. 946 @retval EFI_INVALID_PARAMETER Child handle is NULL. 947 @retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle 948 because its services are being used. 949 @retval other The child handle was not destroyed. 950 951 **/ 952 EFI_STATUS 953 EFIAPI 954 TcpServiceBindingDestroyChild ( 955 IN EFI_SERVICE_BINDING_PROTOCOL *This, 956 IN EFI_HANDLE ChildHandle 957 ) 958 { 959 EFI_STATUS Status; 960 VOID *Tcp; 961 SOCKET *Sock; 962 963 if (NULL == This || NULL == ChildHandle) { 964 return EFI_INVALID_PARAMETER; 965 } 966 967 // 968 // retrieve the Tcp4 protocol from ChildHandle 969 // 970 Status = gBS->OpenProtocol ( 971 ChildHandle, 972 &gEfiTcp4ProtocolGuid, 973 &Tcp, 974 gTcp4DriverBinding.DriverBindingHandle, 975 ChildHandle, 976 EFI_OPEN_PROTOCOL_GET_PROTOCOL 977 ); 978 if (EFI_ERROR (Status)) { 979 // 980 // No Tcp4, try the Tcp6 protocol 981 // 982 Status = gBS->OpenProtocol ( 983 ChildHandle, 984 &gEfiTcp6ProtocolGuid, 985 &Tcp, 986 gTcp6DriverBinding.DriverBindingHandle, 987 ChildHandle, 988 EFI_OPEN_PROTOCOL_GET_PROTOCOL 989 ); 990 if (EFI_ERROR (Status)) { 991 Status = EFI_UNSUPPORTED; 992 } 993 } 994 995 if (!EFI_ERROR (Status)) { 996 // 997 // destroy this sock and related Tcp protocol control 998 // block 999 // 1000 Sock = SOCK_FROM_THIS (Tcp); 1001 1002 SockDestroyChild (Sock); 1003 } 1004 1005 return Status; 1006 } 1007