]> git.proxmox.com Git - mirror_edk2.git/blob - NetworkPkg/TcpDxe/TcpDriver.c
1f0d3716542c422e4cd62468f24bc0e49b6d5270
[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 - 2013, 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 TcpSetVariableData (TcpServiceData);
353
354 return EFI_SUCCESS;
355
356 ON_ERROR:
357
358 if (TcpServiceData->IpIo != NULL) {
359 IpIoDestroy (TcpServiceData->IpIo);
360 TcpServiceData->IpIo = NULL;
361 }
362
363 FreePool (TcpServiceData);
364
365 return Status;
366 }
367
368 /**
369 Callback function which provided by user to remove one node in NetDestroyLinkList process.
370
371 @param[in] Entry The entry to be removed.
372 @param[in] Context Pointer to the callback context corresponds to the Context in NetDestroyLinkList.
373
374 @retval EFI_SUCCESS The entry has been removed successfully.
375 @retval Others Fail to remove the entry.
376
377 **/
378 EFI_STATUS
379 EFIAPI
380 TcpDestroyChildEntryInHandleBuffer (
381 IN LIST_ENTRY *Entry,
382 IN VOID *Context
383 )
384 {
385 SOCKET *Sock;
386 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
387 UINTN NumberOfChildren;
388 EFI_HANDLE *ChildHandleBuffer;
389
390 if (Entry == NULL || Context == NULL) {
391 return EFI_INVALID_PARAMETER;
392 }
393
394 Sock = NET_LIST_USER_STRUCT_S (Entry, SOCKET, Link, SOCK_SIGNATURE);
395 ServiceBinding = ((TCP_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ServiceBinding;
396 NumberOfChildren = ((TCP_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->NumberOfChildren;
397 ChildHandleBuffer = ((TCP_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ChildHandleBuffer;
398
399 if (!NetIsInHandleBuffer (Sock->SockHandle, NumberOfChildren, ChildHandleBuffer)) {
400 return EFI_SUCCESS;
401 }
402
403 return ServiceBinding->DestroyChild (ServiceBinding, Sock->SockHandle);
404 }
405
406 /**
407 Destroy a TCP6 or TCP4 service binding instance. It will release all
408 the resources allocated by the instance.
409
410 @param[in] Controller Controller handle of device to bind driver to.
411 @param[in] ImageHandle The TCP driver's image handle.
412 @param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If number
413 of children is zero stop the entire bus driver.
414 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
415 if NumberOfChildren is 0.
416 @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6
417
418 @retval EFI_SUCCESS The resources used by the instance were cleaned up.
419 @retval Others Failed to clean up some of the resources.
420
421 **/
422 EFI_STATUS
423 TcpDestroyService (
424 IN EFI_HANDLE Controller,
425 IN EFI_HANDLE ImageHandle,
426 IN UINTN NumberOfChildren,
427 IN EFI_HANDLE *ChildHandleBuffer, OPTIONAL
428 IN UINT8 IpVersion
429 )
430 {
431 EFI_HANDLE NicHandle;
432 EFI_GUID *IpProtocolGuid;
433 EFI_GUID *ServiceBindingGuid;
434 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
435 TCP_SERVICE_DATA *TcpServiceData;
436 EFI_STATUS Status;
437 LIST_ENTRY *List;
438 TCP_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context;
439
440 ASSERT ((IpVersion == IP_VERSION_4) || (IpVersion == IP_VERSION_6));
441
442 if (IpVersion == IP_VERSION_4) {
443 IpProtocolGuid = &gEfiIp4ProtocolGuid;
444 ServiceBindingGuid = &gEfiTcp4ServiceBindingProtocolGuid;
445 } else {
446 IpProtocolGuid = &gEfiIp6ProtocolGuid;
447 ServiceBindingGuid = &gEfiTcp6ServiceBindingProtocolGuid;
448 }
449
450 NicHandle = NetLibGetNicHandle (Controller, IpProtocolGuid);
451 if (NicHandle == NULL) {
452 return EFI_SUCCESS;
453 }
454
455 Status = gBS->OpenProtocol (
456 NicHandle,
457 ServiceBindingGuid,
458 (VOID **) &ServiceBinding,
459 ImageHandle,
460 Controller,
461 EFI_OPEN_PROTOCOL_GET_PROTOCOL
462 );
463 if (EFI_ERROR (Status)) {
464 return EFI_DEVICE_ERROR;
465 }
466
467 TcpServiceData = TCP_SERVICE_FROM_THIS (ServiceBinding);
468
469 if (NumberOfChildren != 0) {
470 List = &TcpServiceData->SocketList;
471 Context.ServiceBinding = ServiceBinding;
472 Context.NumberOfChildren = NumberOfChildren;
473 Context.ChildHandleBuffer = ChildHandleBuffer;
474 Status = NetDestroyLinkList (
475 List,
476 TcpDestroyChildEntryInHandleBuffer,
477 &Context,
478 NULL
479 );
480 } else if (IsListEmpty (&TcpServiceData->SocketList)) {
481 //
482 // Uninstall TCP servicebinding protocol
483 //
484 gBS->UninstallMultipleProtocolInterfaces (
485 NicHandle,
486 ServiceBindingGuid,
487 ServiceBinding,
488 NULL
489 );
490
491 //
492 // Destroy the IpIO consumed by TCP driver
493 //
494 IpIoDestroy (TcpServiceData->IpIo);
495 TcpServiceData->IpIo = NULL;
496
497 //
498 // Destroy the heartbeat timer.
499 //
500 TcpDestroyTimer ();
501
502 //
503 // Clear the variable.
504 //
505 TcpClearVariableData (TcpServiceData);
506
507 //
508 // Release the TCP service data
509 //
510 FreePool (TcpServiceData);
511
512 Status = EFI_SUCCESS;
513 }
514
515 return Status;
516 }
517
518 /**
519 Test to see if this driver supports ControllerHandle.
520
521 @param[in] This Protocol instance pointer.
522 @param[in] ControllerHandle Handle of device to test.
523 @param[in] RemainingDevicePath Optional parameter use to pick a specific
524 child device to start.
525
526 @retval EFI_SUCCESS This driver supports this device.
527 @retval EFI_ALREADY_STARTED This driver is already running on this device.
528 @retval other This driver does not support this device.
529
530 **/
531 EFI_STATUS
532 EFIAPI
533 Tcp4DriverBindingSupported (
534 IN EFI_DRIVER_BINDING_PROTOCOL *This,
535 IN EFI_HANDLE ControllerHandle,
536 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
537 )
538 {
539 EFI_STATUS Status;
540
541 //
542 // Test for the Tcp4ServiceBinding Protocol
543 //
544 Status = gBS->OpenProtocol (
545 ControllerHandle,
546 &gEfiTcp4ServiceBindingProtocolGuid,
547 NULL,
548 This->DriverBindingHandle,
549 ControllerHandle,
550 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
551 );
552 if (!EFI_ERROR (Status)) {
553 return EFI_ALREADY_STARTED;
554 }
555
556 //
557 // Test for the Ip4ServiceBinding Protocol
558 //
559 Status = gBS->OpenProtocol (
560 ControllerHandle,
561 &gEfiIp4ServiceBindingProtocolGuid,
562 NULL,
563 This->DriverBindingHandle,
564 ControllerHandle,
565 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
566 );
567 return Status;
568 }
569
570 /**
571 Start this driver on ControllerHandle.
572
573 @param[in] This Protocol instance pointer.
574 @param[in] ControllerHandle Handle of device to bind driver to.
575 @param[in] RemainingDevicePath Optional parameter use to pick a specific child
576 device to start.
577
578 @retval EFI_SUCCESS The driver is added to ControllerHandle.
579 @retval EFI_OUT_OF_RESOURCES There are not enough resources to start the
580 driver.
581 @retval other The driver cannot be added to ControllerHandle.
582
583 **/
584 EFI_STATUS
585 EFIAPI
586 Tcp4DriverBindingStart (
587 IN EFI_DRIVER_BINDING_PROTOCOL *This,
588 IN EFI_HANDLE ControllerHandle,
589 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
590 )
591 {
592 EFI_STATUS Status;
593
594 Status = TcpCreateService (ControllerHandle, This->DriverBindingHandle, IP_VERSION_4);
595 if ((Status == EFI_ALREADY_STARTED) || (Status == EFI_UNSUPPORTED)) {
596 Status = EFI_SUCCESS;
597 }
598
599 return Status;
600 }
601
602 /**
603 Stop this driver on ControllerHandle.
604
605 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
606 @param[in] ControllerHandle A handle to the device being stopped. The handle must
607 support a bus specific I/O protocol for the driver
608 to use to stop the device.
609 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
610 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
611 if NumberOfChildren is 0.
612
613 @retval EFI_SUCCESS The device was stopped.
614 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
615
616 **/
617 EFI_STATUS
618 EFIAPI
619 Tcp4DriverBindingStop (
620 IN EFI_DRIVER_BINDING_PROTOCOL *This,
621 IN EFI_HANDLE ControllerHandle,
622 IN UINTN NumberOfChildren,
623 IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
624 )
625 {
626 return TcpDestroyService (
627 ControllerHandle,
628 This->DriverBindingHandle,
629 NumberOfChildren,
630 ChildHandleBuffer,
631 IP_VERSION_4
632 );
633 }
634
635 /**
636 Test to see if this driver supports ControllerHandle.
637
638 @param[in] This Protocol instance pointer.
639 @param[in] ControllerHandle Handle of device to test.
640 @param[in] RemainingDevicePath Optional parameter use to pick a specific
641 child device to start.
642
643 @retval EFI_SUCCESS This driver supports this device.
644 @retval EFI_ALREADY_STARTED This driver is already running on this device.
645 @retval other This driver does not support this device.
646
647 **/
648 EFI_STATUS
649 EFIAPI
650 Tcp6DriverBindingSupported (
651 IN EFI_DRIVER_BINDING_PROTOCOL *This,
652 IN EFI_HANDLE ControllerHandle,
653 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
654 )
655 {
656 EFI_STATUS Status;
657
658 //
659 // Test for the Tcp6ServiceBinding Protocol
660 //
661 Status = gBS->OpenProtocol (
662 ControllerHandle,
663 &gEfiTcp6ServiceBindingProtocolGuid,
664 NULL,
665 This->DriverBindingHandle,
666 ControllerHandle,
667 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
668 );
669 if (!EFI_ERROR (Status)) {
670 return EFI_ALREADY_STARTED;
671 }
672
673 //
674 // Test for the Ip6ServiceBinding Protocol
675 //
676 Status = gBS->OpenProtocol (
677 ControllerHandle,
678 &gEfiIp6ServiceBindingProtocolGuid,
679 NULL,
680 This->DriverBindingHandle,
681 ControllerHandle,
682 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
683 );
684 return Status;
685 }
686
687 /**
688 Start this driver on ControllerHandle.
689
690 @param[in] This Protocol instance pointer.
691 @param[in] ControllerHandle Handle of device to bind driver to.
692 @param[in] RemainingDevicePath Optional parameter use to pick a specific child
693 device to start.
694
695 @retval EFI_SUCCESS The driver is added to ControllerHandle.
696 @retval EFI_OUT_OF_RESOURCES There are not enough resources to start the
697 driver.
698 @retval other The driver cannot be added to ControllerHandle.
699
700 **/
701 EFI_STATUS
702 EFIAPI
703 Tcp6DriverBindingStart (
704 IN EFI_DRIVER_BINDING_PROTOCOL *This,
705 IN EFI_HANDLE ControllerHandle,
706 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
707 )
708 {
709 EFI_STATUS Status;
710
711 Status = TcpCreateService (ControllerHandle, This->DriverBindingHandle, IP_VERSION_6);
712 if ((Status == EFI_ALREADY_STARTED) || (Status == EFI_UNSUPPORTED)) {
713 Status = EFI_SUCCESS;
714 }
715
716 return Status;
717 }
718
719 /**
720 Stop this driver on ControllerHandle.
721
722 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
723 @param[in] ControllerHandle A handle to the device being stopped. The handle must
724 support a bus specific I/O protocol for the driver
725 to use to stop the device.
726 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
727 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
728 if NumberOfChildren is 0.
729
730 @retval EFI_SUCCESS The device was stopped.
731 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
732
733 **/
734 EFI_STATUS
735 EFIAPI
736 Tcp6DriverBindingStop (
737 IN EFI_DRIVER_BINDING_PROTOCOL *This,
738 IN EFI_HANDLE ControllerHandle,
739 IN UINTN NumberOfChildren,
740 IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
741 )
742 {
743 return TcpDestroyService (
744 ControllerHandle,
745 This->DriverBindingHandle,
746 NumberOfChildren,
747 ChildHandleBuffer,
748 IP_VERSION_6
749 );
750 }
751
752 /**
753 The Callback funtion called after the TCP socket was created.
754
755 @param[in] This Pointer to the socket just created
756 @param[in] Context Context of the socket
757
758 @retval EFI_SUCCESS This protocol installed successfully.
759 @retval other An error occured.
760
761 **/
762 EFI_STATUS
763 TcpCreateSocketCallback (
764 IN SOCKET *This,
765 IN VOID *Context
766 )
767 {
768 EFI_STATUS Status;
769 TCP_SERVICE_DATA *TcpServiceData;
770 EFI_GUID *IpProtocolGuid;
771 VOID *Ip;
772
773 if (This->IpVersion == IP_VERSION_4) {
774 IpProtocolGuid = &gEfiIp4ProtocolGuid;
775 } else {
776 IpProtocolGuid = &gEfiIp6ProtocolGuid;
777 }
778
779 TcpServiceData = ((TCP_PROTO_DATA *) This->ProtoReserved)->TcpService;
780
781 //
782 // Open the default IP protocol of IP_IO BY_DRIVER.
783 //
784 Status = gBS->OpenProtocol (
785 TcpServiceData->IpIo->ChildHandle,
786 IpProtocolGuid,
787 &Ip,
788 TcpServiceData->DriverBindingHandle,
789 This->SockHandle,
790 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
791 );
792 if (EFI_ERROR (Status)) {
793 return Status;
794 }
795
796 //
797 // Open the device path on the handle where service binding resides on.
798 //
799 Status = gBS->OpenProtocol (
800 TcpServiceData->ControllerHandle,
801 &gEfiDevicePathProtocolGuid,
802 (VOID **) &This->ParentDevicePath,
803 TcpServiceData->DriverBindingHandle,
804 This->SockHandle,
805 EFI_OPEN_PROTOCOL_GET_PROTOCOL
806 );
807 if (EFI_ERROR (Status)) {
808 gBS->CloseProtocol (
809 TcpServiceData->IpIo->ChildHandle,
810 IpProtocolGuid,
811 TcpServiceData->DriverBindingHandle,
812 This->SockHandle
813 );
814 } else {
815 //
816 // Insert this socket into the SocketList.
817 //
818 InsertTailList (&TcpServiceData->SocketList, &This->Link);
819 }
820
821 return Status;
822 }
823
824 /**
825 The callback function called before the TCP socket was to be destroyed.
826
827 @param[in] This The TCP socket to be destroyed.
828 @param[in] Context The context of the socket.
829
830 **/
831 VOID
832 TcpDestroySocketCallback (
833 IN SOCKET *This,
834 IN VOID *Context
835 )
836 {
837 TCP_SERVICE_DATA *TcpServiceData;
838 EFI_GUID *IpProtocolGuid;
839
840 if (This->IpVersion == IP_VERSION_4) {
841 IpProtocolGuid = &gEfiIp4ProtocolGuid;
842 } else {
843 IpProtocolGuid = &gEfiIp6ProtocolGuid;
844 }
845
846 TcpServiceData = ((TCP_PROTO_DATA *) This->ProtoReserved)->TcpService;
847
848 //
849 // Remove this node from the list.
850 //
851 RemoveEntryList (&This->Link);
852
853 //
854 // Close the IP protocol.
855 //
856 gBS->CloseProtocol (
857 TcpServiceData->IpIo->ChildHandle,
858 IpProtocolGuid,
859 TcpServiceData->DriverBindingHandle,
860 This->SockHandle
861 );
862 }
863
864 /**
865 Creates a child handle with a set of TCP services.
866
867 The CreateChild() function installs a protocol on ChildHandle.
868 If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle.
869 If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle.
870
871 @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
872 @param[in, out] ChildHandle Pointer to the handle of the child to create.
873 If it is NULL, then a new handle is created.
874 If it is a pointer to an existing UEFI handle,
875 then the protocol is added to the existing UEFI handle.
876
877 @retval EFI_SUCCES The protocol was added to ChildHandle.
878 @retval EFI_INVALID_PARAMETER ChildHandle is NULL.
879 @retval EFI_OUT_OF_RESOURCES There are not enough resources availabe to create
880 the child.
881 @retval other The child handle was not created.
882
883 **/
884 EFI_STATUS
885 EFIAPI
886 TcpServiceBindingCreateChild (
887 IN EFI_SERVICE_BINDING_PROTOCOL *This,
888 IN OUT EFI_HANDLE *ChildHandle
889 )
890 {
891 SOCKET *Sock;
892 TCP_SERVICE_DATA *TcpServiceData;
893 TCP_PROTO_DATA TcpProto;
894 EFI_STATUS Status;
895 EFI_TPL OldTpl;
896
897 if (NULL == This || NULL == ChildHandle) {
898 return EFI_INVALID_PARAMETER;
899 }
900
901 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
902
903 Status = EFI_SUCCESS;
904 TcpServiceData = TCP_SERVICE_FROM_THIS (This);
905 TcpProto.TcpService = TcpServiceData;
906 TcpProto.TcpPcb = NULL;
907
908 //
909 // Create a tcp instance with defualt Tcp default
910 // sock init data and TcpProto
911 //
912 mTcpDefaultSockData.ProtoData = &TcpProto;
913 mTcpDefaultSockData.DataSize = sizeof (TCP_PROTO_DATA);
914 mTcpDefaultSockData.DriverBinding = TcpServiceData->DriverBindingHandle;
915 mTcpDefaultSockData.IpVersion = TcpServiceData->IpVersion;
916
917 if (TcpServiceData->IpVersion == IP_VERSION_4) {
918 mTcpDefaultSockData.Protocol = &gTcp4ProtocolTemplate;
919 } else {
920 mTcpDefaultSockData.Protocol = &gTcp6ProtocolTemplate;
921 }
922
923 Sock = SockCreateChild (&mTcpDefaultSockData);
924 if (NULL == Sock) {
925 DEBUG (
926 (EFI_D_ERROR,
927 "TcpDriverBindingCreateChild: No resource to create a Tcp Child\n")
928 );
929
930 Status = EFI_OUT_OF_RESOURCES;
931 } else {
932 *ChildHandle = Sock->SockHandle;
933 }
934
935 mTcpDefaultSockData.ProtoData = NULL;
936
937 gBS->RestoreTPL (OldTpl);
938 return Status;
939 }
940
941 /**
942 Destroys a child handle with a set of TCP services.
943
944 The DestroyChild() function does the opposite of CreateChild(). It removes a protocol
945 that was installed by CreateChild() from ChildHandle. If the removed protocol is the
946 last protocol on ChildHandle, then ChildHandle is destroyed.
947
948 @param This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
949 @param ChildHandle Handle of the child to be destroyed.
950
951 @retval EFI_SUCCES The protocol was removed from ChildHandle.
952 @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is being removed.
953 @retval EFI_INVALID_PARAMETER Child handle is NULL.
954 @retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle
955 because its services are being used.
956 @retval other The child handle was not destroyed.
957
958 **/
959 EFI_STATUS
960 EFIAPI
961 TcpServiceBindingDestroyChild (
962 IN EFI_SERVICE_BINDING_PROTOCOL *This,
963 IN EFI_HANDLE ChildHandle
964 )
965 {
966 EFI_STATUS Status;
967 VOID *Tcp;
968 SOCKET *Sock;
969
970 if (NULL == This || NULL == ChildHandle) {
971 return EFI_INVALID_PARAMETER;
972 }
973
974 //
975 // retrieve the Tcp4 protocol from ChildHandle
976 //
977 Status = gBS->OpenProtocol (
978 ChildHandle,
979 &gEfiTcp4ProtocolGuid,
980 &Tcp,
981 gTcp4DriverBinding.DriverBindingHandle,
982 ChildHandle,
983 EFI_OPEN_PROTOCOL_GET_PROTOCOL
984 );
985 if (EFI_ERROR (Status)) {
986 //
987 // No Tcp4, try the Tcp6 protocol
988 //
989 Status = gBS->OpenProtocol (
990 ChildHandle,
991 &gEfiTcp6ProtocolGuid,
992 &Tcp,
993 gTcp6DriverBinding.DriverBindingHandle,
994 ChildHandle,
995 EFI_OPEN_PROTOCOL_GET_PROTOCOL
996 );
997 if (EFI_ERROR (Status)) {
998 Status = EFI_UNSUPPORTED;
999 }
1000 }
1001
1002 if (!EFI_ERROR (Status)) {
1003 //
1004 // destroy this sock and related Tcp protocol control
1005 // block
1006 //
1007 Sock = SOCK_FROM_THIS (Tcp);
1008
1009 SockDestroyChild (Sock);
1010 }
1011
1012 return Status;
1013 }