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