1 /** @file 2 Tcp driver function. 3 4 Copyright (c) 2005 - 2014, 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<BR> 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 "Tcp4Main.h" 16 17 18 UINT16 mTcp4RandomPort; 19 extern EFI_COMPONENT_NAME_PROTOCOL gTcp4ComponentName; 20 extern EFI_COMPONENT_NAME2_PROTOCOL gTcp4ComponentName2; 21 extern EFI_UNICODE_STRING_TABLE *gTcpControllerNameTable; 22 23 TCP4_HEARTBEAT_TIMER mTcp4Timer = { 24 NULL, 25 0 26 }; 27 28 EFI_TCP4_PROTOCOL mTcp4ProtocolTemplate = { 29 Tcp4GetModeData, 30 Tcp4Configure, 31 Tcp4Routes, 32 Tcp4Connect, 33 Tcp4Accept, 34 Tcp4Transmit, 35 Tcp4Receive, 36 Tcp4Close, 37 Tcp4Cancel, 38 Tcp4Poll 39 }; 40 41 SOCK_INIT_DATA mTcp4DefaultSockData = { 42 SockStream, 43 0, 44 NULL, 45 TCP_BACKLOG, 46 TCP_SND_BUF_SIZE, 47 TCP_RCV_BUF_SIZE, 48 &mTcp4ProtocolTemplate, 49 Tcp4CreateSocketCallback, 50 Tcp4DestroySocketCallback, 51 NULL, 52 NULL, 53 0, 54 Tcp4Dispatcher, 55 NULL, 56 }; 57 58 EFI_DRIVER_BINDING_PROTOCOL mTcp4DriverBinding = { 59 Tcp4DriverBindingSupported, 60 Tcp4DriverBindingStart, 61 Tcp4DriverBindingStop, 62 0xa, 63 NULL, 64 NULL 65 }; 66 67 EFI_SERVICE_BINDING_PROTOCOL mTcp4ServiceBinding = { 68 Tcp4ServiceBindingCreateChild, 69 Tcp4ServiceBindingDestroyChild 70 }; 71 72 73 /** 74 Create and start the heartbeat timer for TCP driver. 75 76 @retval EFI_SUCCESS The timer is successfully created and started. 77 @retval other The timer is not created. 78 79 **/ 80 EFI_STATUS 81 Tcp4CreateTimer ( 82 VOID 83 ) 84 { 85 EFI_STATUS Status; 86 87 Status = EFI_SUCCESS; 88 89 if (mTcp4Timer.RefCnt == 0) { 90 91 Status = gBS->CreateEvent ( 92 EVT_TIMER | EVT_NOTIFY_SIGNAL, 93 TPL_NOTIFY, 94 TcpTicking, 95 NULL, 96 &mTcp4Timer.TimerEvent 97 ); 98 if (!EFI_ERROR (Status)) { 99 100 Status = gBS->SetTimer ( 101 mTcp4Timer.TimerEvent, 102 TimerPeriodic, 103 (UINT64) (TICKS_PER_SECOND / TCP_TICK_HZ) 104 ); 105 } 106 } 107 108 if (!EFI_ERROR (Status)) { 109 110 mTcp4Timer.RefCnt++; 111 } 112 113 return Status; 114 } 115 116 117 /** 118 Stop and destroy the heartbeat timer for TCP driver. 119 120 **/ 121 VOID 122 Tcp4DestroyTimer ( 123 VOID 124 ) 125 { 126 ASSERT (mTcp4Timer.RefCnt > 0); 127 128 mTcp4Timer.RefCnt--; 129 130 if (mTcp4Timer.RefCnt > 0) { 131 return; 132 } 133 134 gBS->SetTimer (mTcp4Timer.TimerEvent, TimerCancel, 0); 135 gBS->CloseEvent (mTcp4Timer.TimerEvent); 136 mTcp4Timer.TimerEvent = NULL; 137 } 138 139 /** 140 Callback function which provided by user to remove one node in NetDestroyLinkList process. 141 142 @param[in] Entry The entry to be removed. 143 @param[in] Context Pointer to the callback context corresponds to the Context in NetDestroyLinkList. 144 145 @retval EFI_SUCCESS The entry has been removed successfully. 146 @retval Others Fail to remove the entry. 147 148 **/ 149 EFI_STATUS 150 EFIAPI 151 Tcp4DestroyChildEntryInHandleBuffer ( 152 IN LIST_ENTRY *Entry, 153 IN VOID *Context 154 ) 155 { 156 SOCKET *Sock; 157 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding; 158 UINTN NumberOfChildren; 159 EFI_HANDLE *ChildHandleBuffer; 160 161 if (Entry == NULL || Context == NULL) { 162 return EFI_INVALID_PARAMETER; 163 } 164 165 Sock = NET_LIST_USER_STRUCT_S (Entry, SOCKET, Link, SOCK_SIGNATURE); 166 ServiceBinding = ((TCP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ServiceBinding; 167 NumberOfChildren = ((TCP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->NumberOfChildren; 168 ChildHandleBuffer = ((TCP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ChildHandleBuffer; 169 170 if (!NetIsInHandleBuffer (Sock->SockHandle, NumberOfChildren, ChildHandleBuffer)) { 171 return EFI_SUCCESS; 172 } 173 174 return ServiceBinding->DestroyChild (ServiceBinding, Sock->SockHandle); 175 } 176 177 /** 178 The entry point for Tcp4 driver, used to install Tcp4 driver on the ImageHandle. 179 180 @param ImageHandle The firmware allocated handle for this 181 driver image. 182 @param SystemTable Pointer to the EFI system table. 183 184 @retval EFI_SUCCESS Driver loaded. 185 @retval other Driver not loaded. 186 187 **/ 188 EFI_STATUS 189 EFIAPI 190 Tcp4DriverEntryPoint ( 191 IN EFI_HANDLE ImageHandle, 192 IN EFI_SYSTEM_TABLE *SystemTable 193 ) 194 { 195 EFI_STATUS Status; 196 UINT32 Seed; 197 198 // 199 // Install the TCP4 Driver Binding Protocol 200 // 201 Status = EfiLibInstallDriverBindingComponentName2 ( 202 ImageHandle, 203 SystemTable, 204 &mTcp4DriverBinding, 205 ImageHandle, 206 &gTcp4ComponentName, 207 &gTcp4ComponentName2 208 ); 209 ASSERT_EFI_ERROR (Status); 210 // 211 // Initialize ISS and random port. 212 // 213 Seed = NetRandomInitSeed (); 214 mTcpGlobalIss = NET_RANDOM (Seed) % mTcpGlobalIss; 215 mTcp4RandomPort = (UINT16) (TCP4_PORT_KNOWN + 216 (UINT16) (NET_RANDOM(Seed) % TCP4_PORT_KNOWN)); 217 218 return Status; 219 } 220 221 222 /** 223 Tests to see if this driver supports a given controller. 224 225 If a child device is provided, it further tests to see if this driver supports 226 creating a handle for the specified child device. 227 228 @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. 229 @param ControllerHandle The handle of the controller to test. This handle 230 must support a protocol interface that supplies 231 an I/O abstraction to the driver. 232 @param RemainingDevicePath A pointer to the remaining portion of a device path. 233 This parameter is ignored by device drivers, and is optional for bus drivers. 234 235 236 @retval EFI_SUCCESS The device specified by ControllerHandle and 237 RemainingDevicePath is supported by the driver 238 specified by This. 239 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and 240 RemainingDevicePath is already being managed by 241 the driver specified by This. 242 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and 243 RemainingDevicePath is already being managed by a 244 different driver or an application that requires 245 exclusive access. 246 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and 247 RemainingDevicePath is not supported by the driver 248 specified by This. 249 250 **/ 251 EFI_STATUS 252 EFIAPI 253 Tcp4DriverBindingSupported ( 254 IN EFI_DRIVER_BINDING_PROTOCOL *This, 255 IN EFI_HANDLE ControllerHandle, 256 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL 257 ) 258 { 259 EFI_STATUS Status; 260 261 // 262 // Test for the Tcp4ServiceBinding Protocol 263 // 264 Status = gBS->OpenProtocol ( 265 ControllerHandle, 266 &gEfiTcp4ServiceBindingProtocolGuid, 267 NULL, 268 This->DriverBindingHandle, 269 ControllerHandle, 270 EFI_OPEN_PROTOCOL_TEST_PROTOCOL 271 ); 272 if (!EFI_ERROR (Status)) { 273 return EFI_ALREADY_STARTED; 274 } 275 276 // 277 // Test for the Ip4 Protocol 278 // 279 Status = gBS->OpenProtocol ( 280 ControllerHandle, 281 &gEfiIp4ServiceBindingProtocolGuid, 282 NULL, 283 This->DriverBindingHandle, 284 ControllerHandle, 285 EFI_OPEN_PROTOCOL_TEST_PROTOCOL 286 ); 287 288 return Status; 289 } 290 291 292 /** 293 Start this driver on ControllerHandle. 294 295 The Start() function is designed to be invoked from the EFI boot service 296 ConnectController(). As a result, much of the error checking on the parameters 297 to Start() has been moved into this common boot service. It is legal to call 298 Start() from other locations, but the following calling restrictions must be 299 followed or the system behavior will not be deterministic. 300 1. ControllerHandle must be a valid EFI_HANDLE. 301 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally 302 aligned EFI_DEVICE_PATH_PROTOCOL. 303 3. Prior to calling Start(), the Supported() function for the driver specified 304 by This must have been called with the same calling parameters, and Supported() 305 must have returned EFI_SUCCESS. 306 307 @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. 308 @param ControllerHandle The handle of the controller to start. This handle 309 must support a protocol interface that supplies 310 an I/O abstraction to the driver. 311 @param RemainingDevicePath A pointer to the remaining portion of a device path. 312 This parameter is ignored by device drivers, and is 313 optional for bus drivers. 314 315 @retval EFI_SUCCESS The device was started. 316 @retval EFI_ALREADY_STARTED The device could not be started due to a device error. 317 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack 318 of resources. 319 320 **/ 321 EFI_STATUS 322 EFIAPI 323 Tcp4DriverBindingStart ( 324 IN EFI_DRIVER_BINDING_PROTOCOL *This, 325 IN EFI_HANDLE ControllerHandle, 326 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL 327 ) 328 { 329 EFI_STATUS Status; 330 TCP4_SERVICE_DATA *TcpServiceData; 331 IP_IO_OPEN_DATA OpenData; 332 333 TcpServiceData = AllocateZeroPool (sizeof (TCP4_SERVICE_DATA)); 334 335 if (NULL == TcpServiceData) { 336 DEBUG ((EFI_D_ERROR, "Tcp4DriverBindingStart: Have no enough" 337 " resource to create a Tcp Servcie Data\n")); 338 339 return EFI_OUT_OF_RESOURCES; 340 } 341 342 // 343 // Create a new IP IO to Consume it 344 // 345 TcpServiceData->IpIo = IpIoCreate ( 346 This->DriverBindingHandle, 347 ControllerHandle, 348 IP_VERSION_4 349 ); 350 if (NULL == TcpServiceData->IpIo) { 351 352 DEBUG ((EFI_D_ERROR, "Tcp4DriverBindingStart: Have no enough" 353 " resource to create an Ip Io\n")); 354 355 Status = EFI_OUT_OF_RESOURCES; 356 goto ON_ERROR; 357 } 358 359 // 360 // Configure and start IpIo. 361 // 362 ZeroMem (&OpenData, sizeof (IP_IO_OPEN_DATA)); 363 364 CopyMem ( 365 &OpenData.IpConfigData.Ip4CfgData, 366 &mIp4IoDefaultIpConfigData, 367 sizeof (EFI_IP4_CONFIG_DATA) 368 ); 369 370 OpenData.IpConfigData.Ip4CfgData.DefaultProtocol = EFI_IP_PROTO_TCP; 371 372 OpenData.PktRcvdNotify = Tcp4RxCallback; 373 Status = IpIoOpen (TcpServiceData->IpIo, &OpenData); 374 375 if (EFI_ERROR (Status)) { 376 goto ON_ERROR; 377 } 378 379 // 380 // Create the timer event used by TCP driver 381 // 382 Status = Tcp4CreateTimer (); 383 if (EFI_ERROR (Status)) { 384 385 DEBUG ((EFI_D_ERROR, "Tcp4DriverBindingStart: Create TcpTimer" 386 " Event failed with %r\n", Status)); 387 388 goto ON_ERROR; 389 } 390 391 // 392 // Install the Tcp4ServiceBinding Protocol on the 393 // controller handle 394 // 395 TcpServiceData->Tcp4ServiceBinding = mTcp4ServiceBinding; 396 397 Status = gBS->InstallMultipleProtocolInterfaces ( 398 &ControllerHandle, 399 &gEfiTcp4ServiceBindingProtocolGuid, 400 &TcpServiceData->Tcp4ServiceBinding, 401 NULL 402 ); 403 if (EFI_ERROR (Status)) { 404 405 DEBUG ((EFI_D_ERROR, "Tcp4DriverBindingStart: Install Tcp4 Service Binding" 406 " Protocol failed for %r\n", Status)); 407 408 Tcp4DestroyTimer (); 409 goto ON_ERROR; 410 } 411 412 // 413 // Initialize member in TcpServiceData 414 // 415 TcpServiceData->ControllerHandle = ControllerHandle; 416 TcpServiceData->Signature = TCP4_DRIVER_SIGNATURE; 417 TcpServiceData->DriverBindingHandle = This->DriverBindingHandle; 418 419 InitializeListHead (&TcpServiceData->SocketList); 420 421 return EFI_SUCCESS; 422 423 ON_ERROR: 424 425 if (TcpServiceData->IpIo != NULL) { 426 IpIoDestroy (TcpServiceData->IpIo); 427 TcpServiceData->IpIo = NULL; 428 } 429 430 FreePool (TcpServiceData); 431 432 return Status; 433 } 434 435 436 /** 437 Stop this driver on ControllerHandle. 438 439 The Stop() function is designed to be invoked from the EFI boot service 440 DisconnectController(). As a result, much of the error checking on the parameters 441 to Stop() has been moved into this common boot service. It is legal to call Stop() 442 from other locations, but the following calling restrictions must be followed 443 or the system behavior will not be deterministic. 444 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call 445 to this same driver's Start() function. 446 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid 447 EFI_HANDLE. In addition, all of these handles must have been created in this 448 driver's Start() function, and the Start() function must have called OpenProtocol() 449 on ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER. 450 451 @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. 452 @param ControllerHandle A handle to the device being stopped. The handle must 453 support a bus specific I/O protocol for the driver 454 to use to stop the device. 455 @param NumberOfChildren The number of child device handles in ChildHandleBuffer. 456 @param ChildHandleBuffer An array of child handles to be freed. May be NULL if 457 NumberOfChildren is 0. 458 459 @retval EFI_SUCCESS The device was stopped. 460 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error. 461 462 **/ 463 EFI_STATUS 464 EFIAPI 465 Tcp4DriverBindingStop ( 466 IN EFI_DRIVER_BINDING_PROTOCOL *This, 467 IN EFI_HANDLE ControllerHandle, 468 IN UINTN NumberOfChildren, 469 IN EFI_HANDLE *ChildHandleBuffer 470 ) 471 { 472 EFI_STATUS Status; 473 EFI_HANDLE NicHandle; 474 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding; 475 TCP4_SERVICE_DATA *TcpServiceData; 476 LIST_ENTRY *List; 477 TCP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context; 478 479 // Find the NicHandle where Tcp4 ServiceBinding Protocol is installed. 480 // 481 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiIp4ProtocolGuid); 482 if (NicHandle == NULL) { 483 return EFI_SUCCESS; 484 } 485 486 // 487 // Retrieve the TCP driver Data Structure 488 // 489 Status = gBS->OpenProtocol ( 490 NicHandle, 491 &gEfiTcp4ServiceBindingProtocolGuid, 492 (VOID **) &ServiceBinding, 493 This->DriverBindingHandle, 494 ControllerHandle, 495 EFI_OPEN_PROTOCOL_GET_PROTOCOL 496 ); 497 if (EFI_ERROR (Status)) { 498 499 DEBUG ((EFI_D_ERROR, "Tcp4DriverBindingStop: Locate Tcp4 Service " 500 " Binding Protocol failed with %r\n", Status)); 501 502 return EFI_DEVICE_ERROR; 503 } 504 505 TcpServiceData = TCP4_FROM_THIS (ServiceBinding); 506 507 if (NumberOfChildren != 0) { 508 List = &TcpServiceData->SocketList; 509 Context.ServiceBinding = ServiceBinding; 510 Context.NumberOfChildren = NumberOfChildren; 511 Context.ChildHandleBuffer = ChildHandleBuffer; 512 Status = NetDestroyLinkList ( 513 List, 514 Tcp4DestroyChildEntryInHandleBuffer, 515 &Context, 516 NULL 517 ); 518 } else if (IsListEmpty (&TcpServiceData->SocketList)) { 519 // 520 // Uninstall TCP servicebinding protocol 521 // 522 gBS->UninstallMultipleProtocolInterfaces ( 523 NicHandle, 524 &gEfiTcp4ServiceBindingProtocolGuid, 525 ServiceBinding, 526 NULL 527 ); 528 529 // 530 // Destroy the IpIO consumed by TCP driver 531 // 532 IpIoDestroy (TcpServiceData->IpIo); 533 TcpServiceData->IpIo = NULL; 534 535 // 536 // Destroy the heartbeat timer. 537 // 538 Tcp4DestroyTimer (); 539 540 if (gTcpControllerNameTable != NULL) { 541 FreeUnicodeStringTable (gTcpControllerNameTable); 542 gTcpControllerNameTable = NULL; 543 } 544 545 // 546 // Release the TCP service data 547 // 548 FreePool (TcpServiceData); 549 550 Status = EFI_SUCCESS; 551 } 552 553 return Status; 554 } 555 556 /** 557 Open Ip4 and device path protocols for a created socket, and insert it in 558 socket list. 559 560 @param This Pointer to the socket just created 561 @param Context Context of the socket 562 563 @retval EFI_SUCCESS This protocol is installed successfully. 564 @retval other Some error occured. 565 566 **/ 567 EFI_STATUS 568 Tcp4CreateSocketCallback ( 569 IN SOCKET *This, 570 IN VOID *Context 571 ) 572 { 573 EFI_STATUS Status; 574 TCP4_SERVICE_DATA *TcpServiceData; 575 EFI_IP4_PROTOCOL *Ip4; 576 577 TcpServiceData = ((TCP4_PROTO_DATA *) This->ProtoReserved)->TcpService; 578 579 // 580 // Open the default Ip4 protocol of IP_IO BY_DRIVER. 581 // 582 Status = gBS->OpenProtocol ( 583 TcpServiceData->IpIo->ChildHandle, 584 &gEfiIp4ProtocolGuid, 585 (VOID **) &Ip4, 586 TcpServiceData->DriverBindingHandle, 587 This->SockHandle, 588 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER 589 ); 590 if (EFI_ERROR (Status)) { 591 return Status; 592 } 593 594 // 595 // Open the device path on the handle where service binding resides on. 596 // 597 Status = gBS->OpenProtocol ( 598 TcpServiceData->ControllerHandle, 599 &gEfiDevicePathProtocolGuid, 600 (VOID **) &This->ParentDevicePath, 601 TcpServiceData->DriverBindingHandle, 602 This->SockHandle, 603 EFI_OPEN_PROTOCOL_GET_PROTOCOL 604 ); 605 if (EFI_ERROR (Status)) { 606 gBS->CloseProtocol ( 607 TcpServiceData->IpIo->ChildHandle, 608 &gEfiIp4ProtocolGuid, 609 TcpServiceData->DriverBindingHandle, 610 This->SockHandle 611 ); 612 } else { 613 // 614 // Insert this socket into the SocketList. 615 // 616 InsertTailList (&TcpServiceData->SocketList, &This->Link); 617 } 618 619 return Status; 620 } 621 622 /** 623 Close Ip4 and device path protocols for a socket, and remove it from socket list. 624 625 @param This Pointer to the socket to be removed 626 @param Context Context of the socket 627 628 **/ 629 VOID 630 Tcp4DestroySocketCallback ( 631 IN SOCKET *This, 632 IN VOID *Context 633 ) 634 { 635 TCP4_SERVICE_DATA *TcpServiceData; 636 637 TcpServiceData = ((TCP4_PROTO_DATA *) This->ProtoReserved)->TcpService; 638 639 // 640 // Remove this node from the list. 641 // 642 RemoveEntryList (&This->Link); 643 644 // 645 // Close the Ip4 protocol. 646 // 647 gBS->CloseProtocol ( 648 TcpServiceData->IpIo->ChildHandle, 649 &gEfiIp4ProtocolGuid, 650 TcpServiceData->DriverBindingHandle, 651 This->SockHandle 652 ); 653 } 654 655 /** 656 Creates a child handle and installs a protocol. 657 658 The CreateChild() function installs a protocol on ChildHandle. If ChildHandle 659 is a pointer to NULL, then a new handle is created and returned in ChildHandle. 660 If ChildHandle is not a pointer to NULL, then the protocol installs on the existing 661 ChildHandle. 662 663 @param This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance. 664 @param ChildHandle Pointer to the handle of the child to create. If it is NULL, then 665 a new handle is created. If it is a pointer to an existing UEFI 666 handle, then the protocol is added to the existing UEFI handle. 667 668 @retval EFI_SUCCES The protocol was added to ChildHandle. 669 @retval EFI_INVALID_PARAMETER ChildHandle is NULL. 670 @retval EFI_OUT_OF_RESOURCES There are not enough resources availabe to create 671 the child. 672 @retval other The child handle was not created. 673 674 **/ 675 EFI_STATUS 676 EFIAPI 677 Tcp4ServiceBindingCreateChild ( 678 IN EFI_SERVICE_BINDING_PROTOCOL *This, 679 IN OUT EFI_HANDLE *ChildHandle 680 ) 681 { 682 SOCKET *Sock; 683 TCP4_SERVICE_DATA *TcpServiceData; 684 TCP4_PROTO_DATA TcpProto; 685 EFI_STATUS Status; 686 EFI_TPL OldTpl; 687 688 if (NULL == This || NULL == ChildHandle) { 689 return EFI_INVALID_PARAMETER; 690 } 691 692 OldTpl = gBS->RaiseTPL (TPL_CALLBACK); 693 Status = EFI_SUCCESS; 694 TcpServiceData = TCP4_FROM_THIS (This); 695 TcpProto.TcpService = TcpServiceData; 696 TcpProto.TcpPcb = NULL; 697 698 // 699 // Create a tcp instance with defualt Tcp default 700 // sock init data and TcpProto 701 // 702 mTcp4DefaultSockData.ProtoData = &TcpProto; 703 mTcp4DefaultSockData.DataSize = sizeof (TCP4_PROTO_DATA); 704 mTcp4DefaultSockData.DriverBinding = TcpServiceData->DriverBindingHandle; 705 706 Sock = SockCreateChild (&mTcp4DefaultSockData); 707 if (NULL == Sock) { 708 DEBUG ((EFI_D_ERROR, "Tcp4DriverBindingCreateChild: " 709 "No resource to create a Tcp Child\n")); 710 711 Status = EFI_OUT_OF_RESOURCES; 712 } else { 713 *ChildHandle = Sock->SockHandle; 714 } 715 716 mTcp4DefaultSockData.ProtoData = NULL; 717 718 gBS->RestoreTPL (OldTpl); 719 return Status; 720 } 721 722 723 /** 724 Destroys a child handle with a protocol installed on it. 725 726 The DestroyChild() function does the opposite of CreateChild(). It removes a protocol 727 that was installed by CreateChild() from ChildHandle. If the removed protocol is the 728 last protocol on ChildHandle, then ChildHandle is destroyed. 729 730 @param This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance. 731 @param ChildHandle Handle of the child to destroy 732 733 @retval EFI_SUCCES The protocol was removed from ChildHandle. 734 @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is 735 being removed. 736 @retval EFI_INVALID_PARAMETER Child handle is NULL. 737 @retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle 738 because its services are being used. 739 @retval other The child handle was not destroyed. 740 741 **/ 742 EFI_STATUS 743 EFIAPI 744 Tcp4ServiceBindingDestroyChild ( 745 IN EFI_SERVICE_BINDING_PROTOCOL *This, 746 IN EFI_HANDLE ChildHandle 747 ) 748 { 749 EFI_STATUS Status; 750 EFI_TCP4_PROTOCOL *Tcp4; 751 SOCKET *Sock; 752 753 if (NULL == This || NULL == ChildHandle) { 754 return EFI_INVALID_PARAMETER; 755 } 756 757 // 758 // retrieve the Tcp4 protocol from ChildHandle 759 // 760 Status = gBS->OpenProtocol ( 761 ChildHandle, 762 &gEfiTcp4ProtocolGuid, 763 (VOID **) &Tcp4, 764 mTcp4DriverBinding.DriverBindingHandle, 765 ChildHandle, 766 EFI_OPEN_PROTOCOL_GET_PROTOCOL 767 ); 768 if (EFI_ERROR (Status)) { 769 Status = EFI_UNSUPPORTED; 770 } else { 771 // 772 // destroy this sock and related Tcp protocol control 773 // block 774 // 775 Sock = SOCK_FROM_THIS (Tcp4); 776 777 SockDestroyChild (Sock); 778 } 779 780 return Status; 781 } 782 783