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