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