]> git.proxmox.com Git - mirror_edk2.git/blob - NetworkPkg/TcpDxe/TcpDriver.c
Add NetworkPkg (P.UDK2010.UP3.Network.P1)
[mirror_edk2.git] / NetworkPkg / TcpDxe / TcpDriver.c
1 /** @file
2 The driver binding and service binding protocol for the TCP driver.
3
4 Copyright (c) 2009 - 2010, 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 gTcpDriverBinding = {
70 TcpDriverBindingSupported,
71 TcpDriverBindingStart,
72 TcpDriverBindingStop,
73 0xa,
74 NULL,
75 NULL
76 };
77
78 EFI_SERVICE_BINDING_PROTOCOL gTcpServiceBinding = {
79 TcpServiceBindingCreateChild,
80 TcpServiceBindingDestroyChild
81 };
82
83
84 /**
85 Create and start the heartbeat timer for the TCP driver.
86
87 @retval EFI_SUCCESS The timer was successfully created and started.
88 @retval other The timer was not created.
89
90 **/
91 EFI_STATUS
92 TcpCreateTimer (
93 VOID
94 )
95 {
96 EFI_STATUS Status;
97
98 Status = EFI_SUCCESS;
99
100 if (mTcpTimer.RefCnt == 0) {
101
102 Status = gBS->CreateEvent (
103 EVT_TIMER | EVT_NOTIFY_SIGNAL,
104 TPL_NOTIFY,
105 TcpTicking,
106 NULL,
107 &mTcpTimer.TimerEvent
108 );
109 if (!EFI_ERROR (Status)) {
110
111 Status = gBS->SetTimer (
112 mTcpTimer.TimerEvent,
113 TimerPeriodic,
114 (UINT64) (TICKS_PER_SECOND / TCP_TICK_HZ)
115 );
116 }
117 }
118
119 if (!EFI_ERROR (Status)) {
120
121 mTcpTimer.RefCnt++;
122 }
123
124 return Status;
125 }
126
127 /**
128 Stop and destroy the heartbeat timer for TCP driver.
129
130 **/
131 VOID
132 TcpDestroyTimer (
133 VOID
134 )
135 {
136 ASSERT (mTcpTimer.RefCnt > 0);
137
138 mTcpTimer.RefCnt--;
139
140 if (mTcpTimer.RefCnt > 0) {
141 return;
142 }
143
144 gBS->SetTimer (mTcpTimer.TimerEvent, TimerCancel, 0);
145 gBS->CloseEvent (mTcpTimer.TimerEvent);
146 mTcpTimer.TimerEvent = NULL;
147 }
148
149 /**
150 The entry point for Tcp driver, which is used to install Tcp driver on the ImageHandle.
151
152 @param[in] ImageHandle The firmware allocated handle for this driver image.
153 @param[in] SystemTable Pointer to the EFI system table.
154
155 @retval EFI_SUCCESS The driver loaded.
156 @retval other The driver did not load.
157
158 **/
159 EFI_STATUS
160 EFIAPI
161 TcpDriverEntryPoint (
162 IN EFI_HANDLE ImageHandle,
163 IN EFI_SYSTEM_TABLE *SystemTable
164 )
165 {
166 EFI_STATUS Status;
167 UINT32 Seed;
168
169 //
170 // Install the TCP Driver Binding Protocol
171 //
172 Status = EfiLibInstallDriverBindingComponentName2 (
173 ImageHandle,
174 SystemTable,
175 &gTcpDriverBinding,
176 ImageHandle,
177 &gTcpComponentName,
178 &gTcpComponentName2
179 );
180 if (EFI_ERROR (Status)) {
181 return Status;
182 }
183
184 //
185 // Initialize ISS and random port.
186 //
187 Seed = NetRandomInitSeed ();
188 mTcpGlobalIss = NET_RANDOM (Seed) % mTcpGlobalIss;
189 mTcp4RandomPort = (UINT16) (TCP_PORT_KNOWN + (NET_RANDOM (Seed) % TCP_PORT_KNOWN));
190 mTcp6RandomPort = mTcp4RandomPort;
191
192 return EFI_SUCCESS;
193 }
194
195 /**
196 Create a new TCP4 or TCP6 driver service binding protocol
197
198 @param[in] Controller Controller handle of device to bind driver to.
199 @param[in] ImageHandle The TCP driver's image handle.
200 @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.
201
202 @retval EFI_OUT_OF_RESOURCES Failed to allocate some resources.
203 @retval EFI_SUCCESS A new IP6 service binding private was created.
204
205 **/
206 EFI_STATUS
207 TcpCreateService (
208 IN EFI_HANDLE Controller,
209 IN EFI_HANDLE Image,
210 IN UINT8 IpVersion
211 )
212 {
213 EFI_STATUS Status;
214 EFI_GUID *IpServiceBindingGuid;
215 EFI_GUID *TcpServiceBindingGuid;
216 TCP_SERVICE_DATA *TcpServiceData;
217 IP_IO_OPEN_DATA OpenData;
218
219 if (IpVersion == IP_VERSION_4) {
220 IpServiceBindingGuid = &gEfiIp4ServiceBindingProtocolGuid;
221 TcpServiceBindingGuid = &gEfiTcp4ServiceBindingProtocolGuid;
222 } else {
223 IpServiceBindingGuid = &gEfiIp6ServiceBindingProtocolGuid;
224 TcpServiceBindingGuid = &gEfiTcp6ServiceBindingProtocolGuid;
225 }
226
227 Status = gBS->OpenProtocol (
228 Controller,
229 TcpServiceBindingGuid,
230 NULL,
231 Image,
232 Controller,
233 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
234 );
235 if (!EFI_ERROR (Status)) {
236 return EFI_ALREADY_STARTED;
237 }
238
239 Status = gBS->OpenProtocol (
240 Controller,
241 IpServiceBindingGuid,
242 NULL,
243 Image,
244 Controller,
245 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
246 );
247 if (EFI_ERROR (Status)) {
248 return EFI_UNSUPPORTED;
249 }
250
251 //
252 // Create the TCP service data.
253 //
254 TcpServiceData = AllocateZeroPool (sizeof (TCP_SERVICE_DATA));
255 if (TcpServiceData == NULL) {
256 return EFI_OUT_OF_RESOURCES;
257 }
258
259 TcpServiceData->Signature = TCP_DRIVER_SIGNATURE;
260 TcpServiceData->ControllerHandle = Controller;
261 TcpServiceData->DriverBindingHandle = Image;
262 TcpServiceData->IpVersion = IpVersion;
263 CopyMem (
264 &TcpServiceData->ServiceBinding,
265 &gTcpServiceBinding,
266 sizeof (EFI_SERVICE_BINDING_PROTOCOL)
267 );
268
269 TcpServiceData->IpIo = IpIoCreate (Image, Controller, IpVersion);
270 if (TcpServiceData->IpIo == NULL) {
271 Status = EFI_OUT_OF_RESOURCES;
272 goto ON_ERROR;
273 }
274
275
276 InitializeListHead (&TcpServiceData->SocketList);
277 ZeroMem (&OpenData, sizeof (IP_IO_OPEN_DATA));
278
279 if (IpVersion == IP_VERSION_4) {
280 CopyMem (
281 &OpenData.IpConfigData.Ip4CfgData,
282 &mIp4IoDefaultIpConfigData,
283 sizeof (EFI_IP4_CONFIG_DATA)
284 );
285 OpenData.IpConfigData.Ip4CfgData.DefaultProtocol = EFI_IP_PROTO_TCP;
286 } else {
287 CopyMem (
288 &OpenData.IpConfigData.Ip6CfgData,
289 &mIp6IoDefaultIpConfigData,
290 sizeof (EFI_IP6_CONFIG_DATA)
291 );
292 OpenData.IpConfigData.Ip6CfgData.DefaultProtocol = EFI_IP_PROTO_TCP;
293 }
294
295 OpenData.PktRcvdNotify = TcpRxCallback;
296 Status = IpIoOpen (TcpServiceData->IpIo, &OpenData);
297 if (EFI_ERROR (Status)) {
298 goto ON_ERROR;
299 }
300
301 Status = TcpCreateTimer ();
302 if (EFI_ERROR (Status)) {
303 goto ON_ERROR;
304 }
305
306 Status = gBS->InstallMultipleProtocolInterfaces (
307 &Controller,
308 TcpServiceBindingGuid,
309 &TcpServiceData->ServiceBinding,
310 NULL
311 );
312 if (EFI_ERROR (Status)) {
313 TcpDestroyTimer ();
314
315 goto ON_ERROR;
316 }
317
318 TcpSetVariableData (TcpServiceData);
319
320 return EFI_SUCCESS;
321
322 ON_ERROR:
323
324 if (TcpServiceData->IpIo != NULL) {
325 IpIoDestroy (TcpServiceData->IpIo);
326 }
327
328 FreePool (TcpServiceData);
329
330 return Status;
331 }
332
333 /**
334 Destroy a TCP6 or TCP4 service binding instance. It will release all
335 the resources allocated by the instance.
336
337 @param[in] Controller Controller handle of device to bind driver to.
338 @param[in] ImageHandle The TCP driver's image handle.
339 @param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If number
340 of children is zero stop the entire bus driver.
341 @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6
342
343 @retval EFI_SUCCESS The resources used by the instance were cleaned up.
344 @retval Others Failed to clean up some of the resources.
345
346 **/
347 EFI_STATUS
348 TcpDestroyService (
349 IN EFI_HANDLE Controller,
350 IN EFI_HANDLE ImageHandle,
351 IN UINTN NumberOfChildren,
352 IN UINT8 IpVersion
353 )
354 {
355 EFI_HANDLE NicHandle;
356 EFI_GUID *IpProtocolGuid;
357 EFI_GUID *ServiceBindingGuid;
358 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
359 TCP_SERVICE_DATA *TcpServiceData;
360 EFI_STATUS Status;
361 SOCKET *Sock;
362
363 ASSERT ((IpVersion == IP_VERSION_4) || (IpVersion == IP_VERSION_6));
364
365 if (IpVersion == IP_VERSION_4) {
366 IpProtocolGuid = &gEfiIp4ProtocolGuid;
367 ServiceBindingGuid = &gEfiTcp4ServiceBindingProtocolGuid;
368 } else {
369 IpProtocolGuid = &gEfiIp6ProtocolGuid;
370 ServiceBindingGuid = &gEfiTcp6ServiceBindingProtocolGuid;
371 }
372
373 NicHandle = NetLibGetNicHandle (Controller, IpProtocolGuid);
374 if (NicHandle == NULL) {
375 return EFI_NOT_FOUND;
376 }
377
378 Status = gBS->OpenProtocol (
379 NicHandle,
380 ServiceBindingGuid,
381 (VOID **) &ServiceBinding,
382 ImageHandle,
383 Controller,
384 EFI_OPEN_PROTOCOL_GET_PROTOCOL
385 );
386 if (EFI_ERROR (Status)) {
387 return EFI_DEVICE_ERROR;
388 }
389
390 TcpServiceData = TCP_SERVICE_FROM_THIS (ServiceBinding);
391
392 if (NumberOfChildren == 0) {
393 //
394 // Uninstall TCP servicebinding protocol
395 //
396 gBS->UninstallMultipleProtocolInterfaces (
397 NicHandle,
398 ServiceBindingGuid,
399 ServiceBinding,
400 NULL
401 );
402
403 //
404 // Destroy the IpIO consumed by TCP driver
405 //
406 IpIoDestroy (TcpServiceData->IpIo);
407
408 //
409 // Destroy the heartbeat timer.
410 //
411 TcpDestroyTimer ();
412
413 //
414 // Clear the variable.
415 //
416 TcpClearVariableData (TcpServiceData);
417
418 //
419 // Release the TCP service data
420 //
421 FreePool (TcpServiceData);
422 } else {
423
424 while (!IsListEmpty (&TcpServiceData->SocketList)) {
425 Sock = NET_LIST_HEAD (&TcpServiceData->SocketList, SOCKET, Link);
426
427 ServiceBinding->DestroyChild (ServiceBinding, Sock->SockHandle);
428 }
429 }
430
431 return EFI_SUCCESS;
432 }
433
434 /**
435 Test to see if this driver supports ControllerHandle.
436
437 @param[in] This Protocol instance pointer.
438 @param[in] ControllerHandle Handle of device to test.
439 @param[in] RemainingDevicePath Optional parameter use to pick a specific
440 child device to start.
441
442 @retval EFI_SUCCESS This driver supports this device.
443 @retval EFI_ALREADY_STARTED This driver is already running on this device.
444 @retval other This driver does not support this device.
445
446 **/
447 EFI_STATUS
448 EFIAPI
449 TcpDriverBindingSupported (
450 IN EFI_DRIVER_BINDING_PROTOCOL *This,
451 IN EFI_HANDLE ControllerHandle,
452 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
453 )
454 {
455 EFI_STATUS Status;
456 BOOLEAN IsTcp4Started;
457
458 //
459 // Test for the Tcp4ServiceBinding Protocol
460 //
461 Status = gBS->OpenProtocol (
462 ControllerHandle,
463 &gEfiTcp4ServiceBindingProtocolGuid,
464 NULL,
465 This->DriverBindingHandle,
466 ControllerHandle,
467 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
468 );
469 if (EFI_ERROR (Status)) {
470 //
471 // Test for the Ip4ServiceBinding Protocol
472 //
473 Status = gBS->OpenProtocol (
474 ControllerHandle,
475 &gEfiIp4ServiceBindingProtocolGuid,
476 NULL,
477 This->DriverBindingHandle,
478 ControllerHandle,
479 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
480 );
481 if (!EFI_ERROR (Status)) {
482 return EFI_SUCCESS;
483 }
484
485 IsTcp4Started = FALSE;
486 } else {
487 IsTcp4Started = TRUE;
488 }
489
490 //
491 // Check the Tcp6ServiceBinding Protocol
492 //
493 Status = gBS->OpenProtocol (
494 ControllerHandle,
495 &gEfiTcp6ServiceBindingProtocolGuid,
496 NULL,
497 This->DriverBindingHandle,
498 ControllerHandle,
499 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
500 );
501 if (EFI_ERROR (Status)) {
502 //
503 // Test for the Ip6ServiceBinding Protocol
504 //
505 Status = gBS->OpenProtocol (
506 ControllerHandle,
507 &gEfiIp6ServiceBindingProtocolGuid,
508 NULL,
509 This->DriverBindingHandle,
510 ControllerHandle,
511 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
512 );
513 if (!EFI_ERROR (Status)) {
514 return EFI_SUCCESS;
515 }
516 } else if (IsTcp4Started) {
517 return EFI_ALREADY_STARTED;
518 }
519
520 return EFI_UNSUPPORTED;
521 }
522
523 /**
524 Start this driver on ControllerHandle.
525
526 @param[in] This Protocol instance pointer.
527 @param[in] ControllerHandle Handle of device to bind driver to.
528 @param[in] RemainingDevicePath Optional parameter use to pick a specific child
529 device to start.
530
531 @retval EFI_SUCCESS The driver is added to ControllerHandle.
532 @retval EFI_OUT_OF_RESOURCES There are not enough resources to start the
533 driver.
534 @retval other The driver cannot be added to ControllerHandle.
535
536 **/
537 EFI_STATUS
538 EFIAPI
539 TcpDriverBindingStart (
540 IN EFI_DRIVER_BINDING_PROTOCOL *This,
541 IN EFI_HANDLE ControllerHandle,
542 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
543 )
544 {
545 EFI_STATUS Tcp4Status;
546 EFI_STATUS Tcp6Status;
547
548 Tcp4Status = TcpCreateService (ControllerHandle, This->DriverBindingHandle, IP_VERSION_4);
549 if ((Tcp4Status == EFI_ALREADY_STARTED) || (Tcp4Status == EFI_UNSUPPORTED)) {
550 Tcp4Status = EFI_SUCCESS;
551 }
552
553 Tcp6Status = TcpCreateService (ControllerHandle, This->DriverBindingHandle, IP_VERSION_6);
554 if ((Tcp6Status == EFI_ALREADY_STARTED) || (Tcp6Status == EFI_UNSUPPORTED)) {
555 Tcp6Status = EFI_SUCCESS;
556 }
557
558 if (!EFI_ERROR (Tcp4Status) || !EFI_ERROR (Tcp6Status)) {
559 return EFI_SUCCESS;
560 } else if (EFI_ERROR (Tcp4Status)) {
561 return Tcp4Status;
562 } else {
563 return Tcp6Status;
564 }
565 }
566
567 /**
568 Stop this driver on ControllerHandle.
569
570 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
571 @param[in] ControllerHandle A handle to the device being stopped. The handle must
572 support a bus specific I/O protocol for the driver
573 to use to stop the device.
574 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
575 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
576 if NumberOfChildren is 0.
577
578 @retval EFI_SUCCESS The device was stopped.
579 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
580
581 **/
582 EFI_STATUS
583 EFIAPI
584 TcpDriverBindingStop (
585 IN EFI_DRIVER_BINDING_PROTOCOL *This,
586 IN EFI_HANDLE ControllerHandle,
587 IN UINTN NumberOfChildren,
588 IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
589 )
590 {
591 EFI_STATUS Tcp4Status;
592 EFI_STATUS Tcp6Status;
593
594 Tcp4Status = TcpDestroyService (
595 ControllerHandle,
596 This->DriverBindingHandle,
597 NumberOfChildren,
598 IP_VERSION_4
599 );
600
601 Tcp6Status = TcpDestroyService (
602 ControllerHandle,
603 This->DriverBindingHandle,
604 NumberOfChildren,
605 IP_VERSION_6
606 );
607
608 if (EFI_ERROR (Tcp4Status) && EFI_ERROR (Tcp6Status)) {
609 return EFI_DEVICE_ERROR;
610 } else {
611 return EFI_SUCCESS;
612 }
613 }
614
615 /**
616 The Callback funtion called after the TCP socket was created.
617
618 @param[in] This Pointer to the socket just created
619 @param[in] Context Context of the socket
620
621 @retval EFI_SUCCESS This protocol installed successfully.
622 @retval other An error occured.
623
624 **/
625 EFI_STATUS
626 TcpCreateSocketCallback (
627 IN SOCKET *This,
628 IN VOID *Context
629 )
630 {
631 EFI_STATUS Status;
632 TCP_SERVICE_DATA *TcpServiceData;
633 EFI_GUID *IpProtocolGuid;
634 VOID *Ip;
635
636 if (This->IpVersion == IP_VERSION_4) {
637 IpProtocolGuid = &gEfiIp4ProtocolGuid;
638 } else {
639 IpProtocolGuid = &gEfiIp6ProtocolGuid;
640 }
641
642 TcpServiceData = ((TCP_PROTO_DATA *) This->ProtoReserved)->TcpService;
643
644 //
645 // Open the default IP protocol of IP_IO BY_DRIVER.
646 //
647 Status = gBS->OpenProtocol (
648 TcpServiceData->IpIo->ChildHandle,
649 IpProtocolGuid,
650 &Ip,
651 TcpServiceData->DriverBindingHandle,
652 This->SockHandle,
653 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
654 );
655 if (EFI_ERROR (Status)) {
656 return Status;
657 }
658
659 //
660 // Open the device path on the handle where service binding resides on.
661 //
662 Status = gBS->OpenProtocol (
663 TcpServiceData->ControllerHandle,
664 &gEfiDevicePathProtocolGuid,
665 (VOID **) &This->ParentDevicePath,
666 TcpServiceData->DriverBindingHandle,
667 This->SockHandle,
668 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
669 );
670 if (EFI_ERROR (Status)) {
671 gBS->CloseProtocol (
672 TcpServiceData->IpIo->ChildHandle,
673 IpProtocolGuid,
674 TcpServiceData->DriverBindingHandle,
675 This->SockHandle
676 );
677 } else {
678 //
679 // Insert this socket into the SocketList.
680 //
681 InsertTailList (&TcpServiceData->SocketList, &This->Link);
682 }
683
684 return Status;
685 }
686
687 /**
688 The callback function called before the TCP socket was to be destroyed.
689
690 @param[in] This The TCP socket to be destroyed.
691 @param[in] Context The context of the socket.
692
693 **/
694 VOID
695 TcpDestroySocketCallback (
696 IN SOCKET *This,
697 IN VOID *Context
698 )
699 {
700 TCP_SERVICE_DATA *TcpServiceData;
701 EFI_GUID *IpProtocolGuid;
702
703 if (This->IpVersion == IP_VERSION_4) {
704 IpProtocolGuid = &gEfiIp4ProtocolGuid;
705 } else {
706 IpProtocolGuid = &gEfiIp6ProtocolGuid;
707 }
708
709 TcpServiceData = ((TCP_PROTO_DATA *) This->ProtoReserved)->TcpService;
710
711 //
712 // Remove this node from the list.
713 //
714 RemoveEntryList (&This->Link);
715
716 //
717 // Close the device path protocol
718 //
719 gBS->CloseProtocol (
720 TcpServiceData->ControllerHandle,
721 &gEfiDevicePathProtocolGuid,
722 TcpServiceData->DriverBindingHandle,
723 This->SockHandle
724 );
725
726 //
727 // Close the IP protocol.
728 //
729 gBS->CloseProtocol (
730 TcpServiceData->IpIo->ChildHandle,
731 IpProtocolGuid,
732 TcpServiceData->DriverBindingHandle,
733 This->SockHandle
734 );
735 }
736
737 /**
738 Creates a child handle with a set of TCP services.
739
740 The CreateChild() function installs a protocol on ChildHandle.
741 If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle.
742 If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle.
743
744 @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
745 @param[in, out] ChildHandle Pointer to the handle of the child to create.
746 If it is NULL, then a new handle is created.
747 If it is a pointer to an existing UEFI handle,
748 then the protocol is added to the existing UEFI handle.
749
750 @retval EFI_SUCCES The protocol was added to ChildHandle.
751 @retval EFI_INVALID_PARAMETER ChildHandle is NULL.
752 @retval EFI_OUT_OF_RESOURCES There are not enough resources availabe to create
753 the child.
754 @retval other The child handle was not created.
755
756 **/
757 EFI_STATUS
758 EFIAPI
759 TcpServiceBindingCreateChild (
760 IN EFI_SERVICE_BINDING_PROTOCOL *This,
761 IN OUT EFI_HANDLE *ChildHandle
762 )
763 {
764 SOCKET *Sock;
765 TCP_SERVICE_DATA *TcpServiceData;
766 TCP_PROTO_DATA TcpProto;
767 EFI_STATUS Status;
768 EFI_TPL OldTpl;
769
770 if (NULL == This || NULL == ChildHandle) {
771 return EFI_INVALID_PARAMETER;
772 }
773
774 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
775
776 Status = EFI_SUCCESS;
777 TcpServiceData = TCP_SERVICE_FROM_THIS (This);
778 TcpProto.TcpService = TcpServiceData;
779 TcpProto.TcpPcb = NULL;
780
781 //
782 // Create a tcp instance with defualt Tcp default
783 // sock init data and TcpProto
784 //
785 mTcpDefaultSockData.ProtoData = &TcpProto;
786 mTcpDefaultSockData.DataSize = sizeof (TCP_PROTO_DATA);
787 mTcpDefaultSockData.DriverBinding = TcpServiceData->DriverBindingHandle;
788 mTcpDefaultSockData.IpVersion = TcpServiceData->IpVersion;
789
790 if (TcpServiceData->IpVersion == IP_VERSION_4) {
791 mTcpDefaultSockData.Protocol = &gTcp4ProtocolTemplate;
792 } else {
793 mTcpDefaultSockData.Protocol = &gTcp6ProtocolTemplate;
794 }
795
796 Sock = SockCreateChild (&mTcpDefaultSockData);
797 if (NULL == Sock) {
798 DEBUG (
799 (EFI_D_ERROR,
800 "TcpDriverBindingCreateChild: No resource to create a Tcp Child\n")
801 );
802
803 Status = EFI_OUT_OF_RESOURCES;
804 } else {
805 *ChildHandle = Sock->SockHandle;
806 }
807
808 mTcpDefaultSockData.ProtoData = NULL;
809
810 gBS->RestoreTPL (OldTpl);
811 return Status;
812 }
813
814 /**
815 Destroys a child handle with a set of TCP services.
816
817 The DestroyChild() function does the opposite of CreateChild(). It removes a protocol
818 that was installed by CreateChild() from ChildHandle. If the removed protocol is the
819 last protocol on ChildHandle, then ChildHandle is destroyed.
820
821 @param This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
822 @param ChildHandle Handle of the child to be destroyed.
823
824 @retval EFI_SUCCES The protocol was removed from ChildHandle.
825 @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is being removed.
826 @retval EFI_INVALID_PARAMETER Child handle is not a valid UEFI Handle.
827 @retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle
828 because its services are being used.
829 @retval other The child handle was not destroyed.
830
831 **/
832 EFI_STATUS
833 EFIAPI
834 TcpServiceBindingDestroyChild (
835 IN EFI_SERVICE_BINDING_PROTOCOL *This,
836 IN EFI_HANDLE ChildHandle
837 )
838 {
839 EFI_STATUS Status;
840 VOID *Tcp;
841 SOCKET *Sock;
842 EFI_TPL OldTpl;
843
844 if (NULL == This || NULL == ChildHandle) {
845 return EFI_INVALID_PARAMETER;
846 }
847
848 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
849
850 //
851 // retrieve the Tcp4 protocol from ChildHandle
852 //
853 Status = gBS->OpenProtocol (
854 ChildHandle,
855 &gEfiTcp4ProtocolGuid,
856 &Tcp,
857 gTcpDriverBinding.DriverBindingHandle,
858 ChildHandle,
859 EFI_OPEN_PROTOCOL_GET_PROTOCOL
860 );
861 if (EFI_ERROR (Status)) {
862 //
863 // No Tcp4, try the Tcp6 protocol
864 //
865 Status = gBS->OpenProtocol (
866 ChildHandle,
867 &gEfiTcp6ProtocolGuid,
868 &Tcp,
869 gTcpDriverBinding.DriverBindingHandle,
870 ChildHandle,
871 EFI_OPEN_PROTOCOL_GET_PROTOCOL
872 );
873 if (EFI_ERROR (Status)) {
874 Status = EFI_UNSUPPORTED;
875 }
876 }
877
878 if (!EFI_ERROR (Status)) {
879 //
880 // destroy this sock and related Tcp protocol control
881 // block
882 //
883 Sock = SOCK_FROM_THIS (Tcp);
884
885 SockDestroyChild (Sock);
886 }
887
888 gBS->RestoreTPL (OldTpl);
889
890 return Status;
891 }