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