]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Driver.c
29a0cf76c21b8195dfcf3571bd8246186f7d1df5
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Tcp4Dxe / Tcp4Driver.c
1 /** @file
2 Tcp driver function.
3
4 Copyright (c) 2005 - 2013, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php<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 TcpSetVariableData (TcpServiceData);
422
423 return EFI_SUCCESS;
424
425 ON_ERROR:
426
427 if (TcpServiceData->IpIo != NULL) {
428 IpIoDestroy (TcpServiceData->IpIo);
429 TcpServiceData->IpIo = NULL;
430 }
431
432 FreePool (TcpServiceData);
433
434 return Status;
435 }
436
437
438 /**
439 Stop this driver on ControllerHandle.
440
441 The Stop() function is designed to be invoked from the EFI boot service
442 DisconnectController(). As a result, much of the error checking on the parameters
443 to Stop() has been moved into this common boot service. It is legal to call Stop()
444 from other locations, but the following calling restrictions must be followed
445 or the system behavior will not be deterministic.
446 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call
447 to this same driver's Start() function.
448 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
449 EFI_HANDLE. In addition, all of these handles must have been created in this
450 driver's Start() function, and the Start() function must have called OpenProtocol()
451 on ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
452
453 @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
454 @param ControllerHandle A handle to the device being stopped. The handle must
455 support a bus specific I/O protocol for the driver
456 to use to stop the device.
457 @param NumberOfChildren The number of child device handles in ChildHandleBuffer.
458 @param ChildHandleBuffer An array of child handles to be freed. May be NULL if
459 NumberOfChildren is 0.
460
461 @retval EFI_SUCCESS The device was stopped.
462 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
463
464 **/
465 EFI_STATUS
466 EFIAPI
467 Tcp4DriverBindingStop (
468 IN EFI_DRIVER_BINDING_PROTOCOL *This,
469 IN EFI_HANDLE ControllerHandle,
470 IN UINTN NumberOfChildren,
471 IN EFI_HANDLE *ChildHandleBuffer
472 )
473 {
474 EFI_STATUS Status;
475 EFI_HANDLE NicHandle;
476 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
477 TCP4_SERVICE_DATA *TcpServiceData;
478 LIST_ENTRY *List;
479 TCP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context;
480
481 // Find the NicHandle where Tcp4 ServiceBinding Protocol is installed.
482 //
483 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiIp4ProtocolGuid);
484 if (NicHandle == NULL) {
485 return EFI_SUCCESS;
486 }
487
488 //
489 // Retrieve the TCP driver Data Structure
490 //
491 Status = gBS->OpenProtocol (
492 NicHandle,
493 &gEfiTcp4ServiceBindingProtocolGuid,
494 (VOID **) &ServiceBinding,
495 This->DriverBindingHandle,
496 ControllerHandle,
497 EFI_OPEN_PROTOCOL_GET_PROTOCOL
498 );
499 if (EFI_ERROR (Status)) {
500
501 DEBUG ((EFI_D_ERROR, "Tcp4DriverBindingStop: Locate Tcp4 Service "
502 " Binding Protocol failed with %r\n", Status));
503
504 return EFI_DEVICE_ERROR;
505 }
506
507 TcpServiceData = TCP4_FROM_THIS (ServiceBinding);
508
509 if (NumberOfChildren != 0) {
510 List = &TcpServiceData->SocketList;
511 Context.ServiceBinding = ServiceBinding;
512 Context.NumberOfChildren = NumberOfChildren;
513 Context.ChildHandleBuffer = ChildHandleBuffer;
514 Status = NetDestroyLinkList (
515 List,
516 Tcp4DestroyChildEntryInHandleBuffer,
517 &Context,
518 NULL
519 );
520 } else if (IsListEmpty (&TcpServiceData->SocketList)) {
521 //
522 // Uninstall TCP servicebinding protocol
523 //
524 gBS->UninstallMultipleProtocolInterfaces (
525 NicHandle,
526 &gEfiTcp4ServiceBindingProtocolGuid,
527 ServiceBinding,
528 NULL
529 );
530
531 //
532 // Destroy the IpIO consumed by TCP driver
533 //
534 IpIoDestroy (TcpServiceData->IpIo);
535 TcpServiceData->IpIo = NULL;
536
537 //
538 // Destroy the heartbeat timer.
539 //
540 Tcp4DestroyTimer ();
541
542 //
543 // Clear the variable.
544 //
545 TcpClearVariableData (TcpServiceData);
546
547 if (gTcpControllerNameTable != NULL) {
548 FreeUnicodeStringTable (gTcpControllerNameTable);
549 gTcpControllerNameTable = NULL;
550 }
551
552 //
553 // Release the TCP service data
554 //
555 FreePool (TcpServiceData);
556
557 Status = EFI_SUCCESS;
558 }
559
560 return Status;
561 }
562
563 /**
564 Open Ip4 and device path protocols for a created socket, and insert it in
565 socket list.
566
567 @param This Pointer to the socket just created
568 @param Context Context of the socket
569
570 @retval EFI_SUCCESS This protocol is installed successfully.
571 @retval other Some error occured.
572
573 **/
574 EFI_STATUS
575 Tcp4CreateSocketCallback (
576 IN SOCKET *This,
577 IN VOID *Context
578 )
579 {
580 EFI_STATUS Status;
581 TCP4_SERVICE_DATA *TcpServiceData;
582 EFI_IP4_PROTOCOL *Ip4;
583
584 TcpServiceData = ((TCP4_PROTO_DATA *) This->ProtoReserved)->TcpService;
585
586 //
587 // Open the default Ip4 protocol of IP_IO BY_DRIVER.
588 //
589 Status = gBS->OpenProtocol (
590 TcpServiceData->IpIo->ChildHandle,
591 &gEfiIp4ProtocolGuid,
592 (VOID **) &Ip4,
593 TcpServiceData->DriverBindingHandle,
594 This->SockHandle,
595 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
596 );
597 if (EFI_ERROR (Status)) {
598 return Status;
599 }
600
601 //
602 // Open the device path on the handle where service binding resides on.
603 //
604 Status = gBS->OpenProtocol (
605 TcpServiceData->ControllerHandle,
606 &gEfiDevicePathProtocolGuid,
607 (VOID **) &This->ParentDevicePath,
608 TcpServiceData->DriverBindingHandle,
609 This->SockHandle,
610 EFI_OPEN_PROTOCOL_GET_PROTOCOL
611 );
612 if (EFI_ERROR (Status)) {
613 gBS->CloseProtocol (
614 TcpServiceData->IpIo->ChildHandle,
615 &gEfiIp4ProtocolGuid,
616 TcpServiceData->DriverBindingHandle,
617 This->SockHandle
618 );
619 } else {
620 //
621 // Insert this socket into the SocketList.
622 //
623 InsertTailList (&TcpServiceData->SocketList, &This->Link);
624 }
625
626 return Status;
627 }
628
629 /**
630 Close Ip4 and device path protocols for a socket, and remove it from socket list.
631
632 @param This Pointer to the socket to be removed
633 @param Context Context of the socket
634
635 **/
636 VOID
637 Tcp4DestroySocketCallback (
638 IN SOCKET *This,
639 IN VOID *Context
640 )
641 {
642 TCP4_SERVICE_DATA *TcpServiceData;
643
644 TcpServiceData = ((TCP4_PROTO_DATA *) This->ProtoReserved)->TcpService;
645
646 //
647 // Remove this node from the list.
648 //
649 RemoveEntryList (&This->Link);
650
651 //
652 // Close the Ip4 protocol.
653 //
654 gBS->CloseProtocol (
655 TcpServiceData->IpIo->ChildHandle,
656 &gEfiIp4ProtocolGuid,
657 TcpServiceData->DriverBindingHandle,
658 This->SockHandle
659 );
660 }
661
662 /**
663 Creates a child handle and installs a protocol.
664
665 The CreateChild() function installs a protocol on ChildHandle. If ChildHandle
666 is a pointer to NULL, then a new handle is created and returned in ChildHandle.
667 If ChildHandle is not a pointer to NULL, then the protocol installs on the existing
668 ChildHandle.
669
670 @param This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
671 @param ChildHandle Pointer to the handle of the child to create. If it is NULL, then
672 a new handle is created. If it is a pointer to an existing UEFI
673 handle, then the protocol is added to the existing UEFI handle.
674
675 @retval EFI_SUCCES The protocol was added to ChildHandle.
676 @retval EFI_INVALID_PARAMETER ChildHandle is NULL.
677 @retval EFI_OUT_OF_RESOURCES There are not enough resources availabe to create
678 the child.
679 @retval other The child handle was not created.
680
681 **/
682 EFI_STATUS
683 EFIAPI
684 Tcp4ServiceBindingCreateChild (
685 IN EFI_SERVICE_BINDING_PROTOCOL *This,
686 IN OUT EFI_HANDLE *ChildHandle
687 )
688 {
689 SOCKET *Sock;
690 TCP4_SERVICE_DATA *TcpServiceData;
691 TCP4_PROTO_DATA TcpProto;
692 EFI_STATUS Status;
693 EFI_TPL OldTpl;
694
695 if (NULL == This || NULL == ChildHandle) {
696 return EFI_INVALID_PARAMETER;
697 }
698
699 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
700 Status = EFI_SUCCESS;
701 TcpServiceData = TCP4_FROM_THIS (This);
702 TcpProto.TcpService = TcpServiceData;
703 TcpProto.TcpPcb = NULL;
704
705 //
706 // Create a tcp instance with defualt Tcp default
707 // sock init data and TcpProto
708 //
709 mTcp4DefaultSockData.ProtoData = &TcpProto;
710 mTcp4DefaultSockData.DataSize = sizeof (TCP4_PROTO_DATA);
711 mTcp4DefaultSockData.DriverBinding = TcpServiceData->DriverBindingHandle;
712
713 Sock = SockCreateChild (&mTcp4DefaultSockData);
714 if (NULL == Sock) {
715 DEBUG ((EFI_D_ERROR, "Tcp4DriverBindingCreateChild: "
716 "No resource to create a Tcp Child\n"));
717
718 Status = EFI_OUT_OF_RESOURCES;
719 } else {
720 *ChildHandle = Sock->SockHandle;
721 }
722
723 mTcp4DefaultSockData.ProtoData = NULL;
724
725 gBS->RestoreTPL (OldTpl);
726 return Status;
727 }
728
729
730 /**
731 Destroys a child handle with a protocol installed on it.
732
733 The DestroyChild() function does the opposite of CreateChild(). It removes a protocol
734 that was installed by CreateChild() from ChildHandle. If the removed protocol is the
735 last protocol on ChildHandle, then ChildHandle is destroyed.
736
737 @param This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
738 @param ChildHandle Handle of the child to destroy
739
740 @retval EFI_SUCCES The protocol was removed from ChildHandle.
741 @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is
742 being removed.
743 @retval EFI_INVALID_PARAMETER Child handle is NULL.
744 @retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle
745 because its services are being used.
746 @retval other The child handle was not destroyed.
747
748 **/
749 EFI_STATUS
750 EFIAPI
751 Tcp4ServiceBindingDestroyChild (
752 IN EFI_SERVICE_BINDING_PROTOCOL *This,
753 IN EFI_HANDLE ChildHandle
754 )
755 {
756 EFI_STATUS Status;
757 EFI_TCP4_PROTOCOL *Tcp4;
758 SOCKET *Sock;
759
760 if (NULL == This || NULL == ChildHandle) {
761 return EFI_INVALID_PARAMETER;
762 }
763
764 //
765 // retrieve the Tcp4 protocol from ChildHandle
766 //
767 Status = gBS->OpenProtocol (
768 ChildHandle,
769 &gEfiTcp4ProtocolGuid,
770 (VOID **) &Tcp4,
771 mTcp4DriverBinding.DriverBindingHandle,
772 ChildHandle,
773 EFI_OPEN_PROTOCOL_GET_PROTOCOL
774 );
775 if (EFI_ERROR (Status)) {
776 Status = EFI_UNSUPPORTED;
777 } else {
778 //
779 // destroy this sock and related Tcp protocol control
780 // block
781 //
782 Sock = SOCK_FROM_THIS (Tcp4);
783
784 SockDestroyChild (Sock);
785 }
786
787 return Status;
788 }
789