2 The driver binding and service binding protocol for the TCP driver.
4 Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
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.
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.
18 UINT16 mTcp4RandomPort
;
19 UINT16 mTcp6RandomPort
;
21 TCP_HEARTBEAT_TIMER mTcpTimer
= {
26 EFI_TCP4_PROTOCOL gTcp4ProtocolTemplate
= {
39 EFI_TCP6_PROTOCOL gTcp6ProtocolTemplate
= {
51 SOCK_INIT_DATA mTcpDefaultSockData
= {
60 TcpCreateSocketCallback
,
61 TcpDestroySocketCallback
,
69 EFI_DRIVER_BINDING_PROTOCOL gTcpDriverBinding
= {
70 TcpDriverBindingSupported
,
71 TcpDriverBindingStart
,
78 EFI_SERVICE_BINDING_PROTOCOL gTcpServiceBinding
= {
79 TcpServiceBindingCreateChild
,
80 TcpServiceBindingDestroyChild
85 Create and start the heartbeat timer for the TCP driver.
87 @retval EFI_SUCCESS The timer was successfully created and started.
88 @retval other The timer was not created.
100 if (mTcpTimer
.RefCnt
== 0) {
102 Status
= gBS
->CreateEvent (
103 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
107 &mTcpTimer
.TimerEvent
109 if (!EFI_ERROR (Status
)) {
111 Status
= gBS
->SetTimer (
112 mTcpTimer
.TimerEvent
,
114 (UINT64
) (TICKS_PER_SECOND
/ TCP_TICK_HZ
)
119 if (!EFI_ERROR (Status
)) {
128 Stop and destroy the heartbeat timer for TCP driver.
136 ASSERT (mTcpTimer
.RefCnt
> 0);
140 if (mTcpTimer
.RefCnt
> 0) {
144 gBS
->SetTimer (mTcpTimer
.TimerEvent
, TimerCancel
, 0);
145 gBS
->CloseEvent (mTcpTimer
.TimerEvent
);
146 mTcpTimer
.TimerEvent
= NULL
;
150 The entry point for Tcp driver, which is used to install Tcp driver on the ImageHandle.
152 @param[in] ImageHandle The firmware allocated handle for this driver image.
153 @param[in] SystemTable Pointer to the EFI system table.
155 @retval EFI_SUCCESS The driver loaded.
156 @retval other The driver did not load.
161 TcpDriverEntryPoint (
162 IN EFI_HANDLE ImageHandle
,
163 IN EFI_SYSTEM_TABLE
*SystemTable
170 // Install the TCP Driver Binding Protocol
172 Status
= EfiLibInstallDriverBindingComponentName2 (
180 if (EFI_ERROR (Status
)) {
185 // Initialize ISS and random port.
187 Seed
= NetRandomInitSeed ();
188 mTcpGlobalIss
= NET_RANDOM (Seed
) % mTcpGlobalIss
;
189 mTcp4RandomPort
= (UINT16
) (TCP_PORT_KNOWN
+ (NET_RANDOM (Seed
) % TCP_PORT_KNOWN
));
190 mTcp6RandomPort
= mTcp4RandomPort
;
196 Create a new TCP4 or TCP6 driver service binding protocol
198 @param[in] Controller Controller handle of device to bind driver to.
199 @param[in] ImageHandle The TCP driver's image handle.
200 @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.
202 @retval EFI_OUT_OF_RESOURCES Failed to allocate some resources.
203 @retval EFI_SUCCESS A new IP6 service binding private was created.
208 IN EFI_HANDLE Controller
,
214 EFI_GUID
*IpServiceBindingGuid
;
215 EFI_GUID
*TcpServiceBindingGuid
;
216 TCP_SERVICE_DATA
*TcpServiceData
;
217 IP_IO_OPEN_DATA OpenData
;
219 if (IpVersion
== IP_VERSION_4
) {
220 IpServiceBindingGuid
= &gEfiIp4ServiceBindingProtocolGuid
;
221 TcpServiceBindingGuid
= &gEfiTcp4ServiceBindingProtocolGuid
;
223 IpServiceBindingGuid
= &gEfiIp6ServiceBindingProtocolGuid
;
224 TcpServiceBindingGuid
= &gEfiTcp6ServiceBindingProtocolGuid
;
227 Status
= gBS
->OpenProtocol (
229 TcpServiceBindingGuid
,
233 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
235 if (!EFI_ERROR (Status
)) {
236 return EFI_ALREADY_STARTED
;
239 Status
= gBS
->OpenProtocol (
241 IpServiceBindingGuid
,
245 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
247 if (EFI_ERROR (Status
)) {
248 return EFI_UNSUPPORTED
;
252 // Create the TCP service data.
254 TcpServiceData
= AllocateZeroPool (sizeof (TCP_SERVICE_DATA
));
255 if (TcpServiceData
== NULL
) {
256 return EFI_OUT_OF_RESOURCES
;
259 TcpServiceData
->Signature
= TCP_DRIVER_SIGNATURE
;
260 TcpServiceData
->ControllerHandle
= Controller
;
261 TcpServiceData
->DriverBindingHandle
= Image
;
262 TcpServiceData
->IpVersion
= IpVersion
;
264 &TcpServiceData
->ServiceBinding
,
266 sizeof (EFI_SERVICE_BINDING_PROTOCOL
)
269 TcpServiceData
->IpIo
= IpIoCreate (Image
, Controller
, IpVersion
);
270 if (TcpServiceData
->IpIo
== NULL
) {
271 Status
= EFI_OUT_OF_RESOURCES
;
276 InitializeListHead (&TcpServiceData
->SocketList
);
277 ZeroMem (&OpenData
, sizeof (IP_IO_OPEN_DATA
));
279 if (IpVersion
== IP_VERSION_4
) {
281 &OpenData
.IpConfigData
.Ip4CfgData
,
282 &mIp4IoDefaultIpConfigData
,
283 sizeof (EFI_IP4_CONFIG_DATA
)
285 OpenData
.IpConfigData
.Ip4CfgData
.DefaultProtocol
= EFI_IP_PROTO_TCP
;
288 &OpenData
.IpConfigData
.Ip6CfgData
,
289 &mIp6IoDefaultIpConfigData
,
290 sizeof (EFI_IP6_CONFIG_DATA
)
292 OpenData
.IpConfigData
.Ip6CfgData
.DefaultProtocol
= EFI_IP_PROTO_TCP
;
295 OpenData
.PktRcvdNotify
= TcpRxCallback
;
296 Status
= IpIoOpen (TcpServiceData
->IpIo
, &OpenData
);
297 if (EFI_ERROR (Status
)) {
301 Status
= TcpCreateTimer ();
302 if (EFI_ERROR (Status
)) {
306 Status
= gBS
->InstallMultipleProtocolInterfaces (
308 TcpServiceBindingGuid
,
309 &TcpServiceData
->ServiceBinding
,
312 if (EFI_ERROR (Status
)) {
318 TcpSetVariableData (TcpServiceData
);
324 if (TcpServiceData
->IpIo
!= NULL
) {
325 IpIoDestroy (TcpServiceData
->IpIo
);
328 FreePool (TcpServiceData
);
334 Destroy a TCP6 or TCP4 service binding instance. It will release all
335 the resources allocated by the instance.
337 @param[in] Controller Controller handle of device to bind driver to.
338 @param[in] ImageHandle The TCP driver's image handle.
339 @param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If number
340 of children is zero stop the entire bus driver.
341 @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6
343 @retval EFI_SUCCESS The resources used by the instance were cleaned up.
344 @retval Others Failed to clean up some of the resources.
349 IN EFI_HANDLE Controller
,
350 IN EFI_HANDLE ImageHandle
,
351 IN UINTN NumberOfChildren
,
355 EFI_HANDLE NicHandle
;
356 EFI_GUID
*IpProtocolGuid
;
357 EFI_GUID
*ServiceBindingGuid
;
358 EFI_SERVICE_BINDING_PROTOCOL
*ServiceBinding
;
359 TCP_SERVICE_DATA
*TcpServiceData
;
363 ASSERT ((IpVersion
== IP_VERSION_4
) || (IpVersion
== IP_VERSION_6
));
365 if (IpVersion
== IP_VERSION_4
) {
366 IpProtocolGuid
= &gEfiIp4ProtocolGuid
;
367 ServiceBindingGuid
= &gEfiTcp4ServiceBindingProtocolGuid
;
369 IpProtocolGuid
= &gEfiIp6ProtocolGuid
;
370 ServiceBindingGuid
= &gEfiTcp6ServiceBindingProtocolGuid
;
373 NicHandle
= NetLibGetNicHandle (Controller
, IpProtocolGuid
);
374 if (NicHandle
== NULL
) {
375 return EFI_NOT_FOUND
;
378 Status
= gBS
->OpenProtocol (
381 (VOID
**) &ServiceBinding
,
384 EFI_OPEN_PROTOCOL_GET_PROTOCOL
386 if (EFI_ERROR (Status
)) {
387 return EFI_DEVICE_ERROR
;
390 TcpServiceData
= TCP_SERVICE_FROM_THIS (ServiceBinding
);
392 if (NumberOfChildren
== 0) {
394 // Uninstall TCP servicebinding protocol
396 gBS
->UninstallMultipleProtocolInterfaces (
404 // Destroy the IpIO consumed by TCP driver
406 IpIoDestroy (TcpServiceData
->IpIo
);
409 // Destroy the heartbeat timer.
414 // Clear the variable.
416 TcpClearVariableData (TcpServiceData
);
419 // Release the TCP service data
421 FreePool (TcpServiceData
);
424 while (!IsListEmpty (&TcpServiceData
->SocketList
)) {
425 Sock
= NET_LIST_HEAD (&TcpServiceData
->SocketList
, SOCKET
, Link
);
427 ServiceBinding
->DestroyChild (ServiceBinding
, Sock
->SockHandle
);
435 Test to see if this driver supports ControllerHandle.
437 @param[in] This Protocol instance pointer.
438 @param[in] ControllerHandle Handle of device to test.
439 @param[in] RemainingDevicePath Optional parameter use to pick a specific
440 child device to start.
442 @retval EFI_SUCCESS This driver supports this device.
443 @retval EFI_ALREADY_STARTED This driver is already running on this device.
444 @retval other This driver does not support this device.
449 TcpDriverBindingSupported (
450 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
451 IN EFI_HANDLE ControllerHandle
,
452 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
456 BOOLEAN IsTcp4Started
;
459 // Test for the Tcp4ServiceBinding Protocol
461 Status
= gBS
->OpenProtocol (
463 &gEfiTcp4ServiceBindingProtocolGuid
,
465 This
->DriverBindingHandle
,
467 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
469 if (EFI_ERROR (Status
)) {
471 // Test for the Ip4ServiceBinding Protocol
473 Status
= gBS
->OpenProtocol (
475 &gEfiIp4ServiceBindingProtocolGuid
,
477 This
->DriverBindingHandle
,
479 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
481 if (!EFI_ERROR (Status
)) {
485 IsTcp4Started
= FALSE
;
487 IsTcp4Started
= TRUE
;
491 // Check the Tcp6ServiceBinding Protocol
493 Status
= gBS
->OpenProtocol (
495 &gEfiTcp6ServiceBindingProtocolGuid
,
497 This
->DriverBindingHandle
,
499 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
501 if (EFI_ERROR (Status
)) {
503 // Test for the Ip6ServiceBinding Protocol
505 Status
= gBS
->OpenProtocol (
507 &gEfiIp6ServiceBindingProtocolGuid
,
509 This
->DriverBindingHandle
,
511 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
513 if (!EFI_ERROR (Status
)) {
516 } else if (IsTcp4Started
) {
517 return EFI_ALREADY_STARTED
;
520 return EFI_UNSUPPORTED
;
524 Start this driver on ControllerHandle.
526 @param[in] This Protocol instance pointer.
527 @param[in] ControllerHandle Handle of device to bind driver to.
528 @param[in] RemainingDevicePath Optional parameter use to pick a specific child
531 @retval EFI_SUCCESS The driver is added to ControllerHandle.
532 @retval EFI_OUT_OF_RESOURCES There are not enough resources to start the
534 @retval other The driver cannot be added to ControllerHandle.
539 TcpDriverBindingStart (
540 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
541 IN EFI_HANDLE ControllerHandle
,
542 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
545 EFI_STATUS Tcp4Status
;
546 EFI_STATUS Tcp6Status
;
548 Tcp4Status
= TcpCreateService (ControllerHandle
, This
->DriverBindingHandle
, IP_VERSION_4
);
549 if ((Tcp4Status
== EFI_ALREADY_STARTED
) || (Tcp4Status
== EFI_UNSUPPORTED
)) {
550 Tcp4Status
= EFI_SUCCESS
;
553 Tcp6Status
= TcpCreateService (ControllerHandle
, This
->DriverBindingHandle
, IP_VERSION_6
);
554 if ((Tcp6Status
== EFI_ALREADY_STARTED
) || (Tcp6Status
== EFI_UNSUPPORTED
)) {
555 Tcp6Status
= EFI_SUCCESS
;
558 if (!EFI_ERROR (Tcp4Status
) || !EFI_ERROR (Tcp6Status
)) {
560 } else if (EFI_ERROR (Tcp4Status
)) {
568 Stop this driver on ControllerHandle.
570 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
571 @param[in] ControllerHandle A handle to the device being stopped. The handle must
572 support a bus specific I/O protocol for the driver
573 to use to stop the device.
574 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
575 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
576 if NumberOfChildren is 0.
578 @retval EFI_SUCCESS The device was stopped.
579 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
584 TcpDriverBindingStop (
585 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
586 IN EFI_HANDLE ControllerHandle
,
587 IN UINTN NumberOfChildren
,
588 IN EFI_HANDLE
*ChildHandleBuffer OPTIONAL
591 EFI_STATUS Tcp4Status
;
592 EFI_STATUS Tcp6Status
;
594 Tcp4Status
= TcpDestroyService (
596 This
->DriverBindingHandle
,
601 Tcp6Status
= TcpDestroyService (
603 This
->DriverBindingHandle
,
608 if (EFI_ERROR (Tcp4Status
) && EFI_ERROR (Tcp6Status
)) {
609 return EFI_DEVICE_ERROR
;
616 The Callback funtion called after the TCP socket was created.
618 @param[in] This Pointer to the socket just created
619 @param[in] Context Context of the socket
621 @retval EFI_SUCCESS This protocol installed successfully.
622 @retval other An error occured.
626 TcpCreateSocketCallback (
632 TCP_SERVICE_DATA
*TcpServiceData
;
633 EFI_GUID
*IpProtocolGuid
;
636 if (This
->IpVersion
== IP_VERSION_4
) {
637 IpProtocolGuid
= &gEfiIp4ProtocolGuid
;
639 IpProtocolGuid
= &gEfiIp6ProtocolGuid
;
642 TcpServiceData
= ((TCP_PROTO_DATA
*) This
->ProtoReserved
)->TcpService
;
645 // Open the default IP protocol of IP_IO BY_DRIVER.
647 Status
= gBS
->OpenProtocol (
648 TcpServiceData
->IpIo
->ChildHandle
,
651 TcpServiceData
->DriverBindingHandle
,
653 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
655 if (EFI_ERROR (Status
)) {
660 // Open the device path on the handle where service binding resides on.
662 Status
= gBS
->OpenProtocol (
663 TcpServiceData
->ControllerHandle
,
664 &gEfiDevicePathProtocolGuid
,
665 (VOID
**) &This
->ParentDevicePath
,
666 TcpServiceData
->DriverBindingHandle
,
668 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
670 if (EFI_ERROR (Status
)) {
672 TcpServiceData
->IpIo
->ChildHandle
,
674 TcpServiceData
->DriverBindingHandle
,
679 // Insert this socket into the SocketList.
681 InsertTailList (&TcpServiceData
->SocketList
, &This
->Link
);
688 The callback function called before the TCP socket was to be destroyed.
690 @param[in] This The TCP socket to be destroyed.
691 @param[in] Context The context of the socket.
695 TcpDestroySocketCallback (
700 TCP_SERVICE_DATA
*TcpServiceData
;
701 EFI_GUID
*IpProtocolGuid
;
703 if (This
->IpVersion
== IP_VERSION_4
) {
704 IpProtocolGuid
= &gEfiIp4ProtocolGuid
;
706 IpProtocolGuid
= &gEfiIp6ProtocolGuid
;
709 TcpServiceData
= ((TCP_PROTO_DATA
*) This
->ProtoReserved
)->TcpService
;
712 // Remove this node from the list.
714 RemoveEntryList (&This
->Link
);
717 // Close the device path protocol
720 TcpServiceData
->ControllerHandle
,
721 &gEfiDevicePathProtocolGuid
,
722 TcpServiceData
->DriverBindingHandle
,
727 // Close the IP protocol.
730 TcpServiceData
->IpIo
->ChildHandle
,
732 TcpServiceData
->DriverBindingHandle
,
738 Creates a child handle with a set of TCP services.
740 The CreateChild() function installs a protocol on ChildHandle.
741 If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle.
742 If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle.
744 @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
745 @param[in, out] ChildHandle Pointer to the handle of the child to create.
746 If it is NULL, then a new handle is created.
747 If it is a pointer to an existing UEFI handle,
748 then the protocol is added to the existing UEFI handle.
750 @retval EFI_SUCCES The protocol was added to ChildHandle.
751 @retval EFI_INVALID_PARAMETER ChildHandle is NULL.
752 @retval EFI_OUT_OF_RESOURCES There are not enough resources availabe to create
754 @retval other The child handle was not created.
759 TcpServiceBindingCreateChild (
760 IN EFI_SERVICE_BINDING_PROTOCOL
*This
,
761 IN OUT EFI_HANDLE
*ChildHandle
765 TCP_SERVICE_DATA
*TcpServiceData
;
766 TCP_PROTO_DATA TcpProto
;
770 if (NULL
== This
|| NULL
== ChildHandle
) {
771 return EFI_INVALID_PARAMETER
;
774 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
776 Status
= EFI_SUCCESS
;
777 TcpServiceData
= TCP_SERVICE_FROM_THIS (This
);
778 TcpProto
.TcpService
= TcpServiceData
;
779 TcpProto
.TcpPcb
= NULL
;
782 // Create a tcp instance with defualt Tcp default
783 // sock init data and TcpProto
785 mTcpDefaultSockData
.ProtoData
= &TcpProto
;
786 mTcpDefaultSockData
.DataSize
= sizeof (TCP_PROTO_DATA
);
787 mTcpDefaultSockData
.DriverBinding
= TcpServiceData
->DriverBindingHandle
;
788 mTcpDefaultSockData
.IpVersion
= TcpServiceData
->IpVersion
;
790 if (TcpServiceData
->IpVersion
== IP_VERSION_4
) {
791 mTcpDefaultSockData
.Protocol
= &gTcp4ProtocolTemplate
;
793 mTcpDefaultSockData
.Protocol
= &gTcp6ProtocolTemplate
;
796 Sock
= SockCreateChild (&mTcpDefaultSockData
);
800 "TcpDriverBindingCreateChild: No resource to create a Tcp Child\n")
803 Status
= EFI_OUT_OF_RESOURCES
;
805 *ChildHandle
= Sock
->SockHandle
;
808 mTcpDefaultSockData
.ProtoData
= NULL
;
810 gBS
->RestoreTPL (OldTpl
);
815 Destroys a child handle with a set of TCP services.
817 The DestroyChild() function does the opposite of CreateChild(). It removes a protocol
818 that was installed by CreateChild() from ChildHandle. If the removed protocol is the
819 last protocol on ChildHandle, then ChildHandle is destroyed.
821 @param This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
822 @param ChildHandle Handle of the child to be destroyed.
824 @retval EFI_SUCCES The protocol was removed from ChildHandle.
825 @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is being removed.
826 @retval EFI_INVALID_PARAMETER Child handle is not a valid UEFI Handle.
827 @retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle
828 because its services are being used.
829 @retval other The child handle was not destroyed.
834 TcpServiceBindingDestroyChild (
835 IN EFI_SERVICE_BINDING_PROTOCOL
*This
,
836 IN EFI_HANDLE ChildHandle
844 if (NULL
== This
|| NULL
== ChildHandle
) {
845 return EFI_INVALID_PARAMETER
;
848 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
851 // retrieve the Tcp4 protocol from ChildHandle
853 Status
= gBS
->OpenProtocol (
855 &gEfiTcp4ProtocolGuid
,
857 gTcpDriverBinding
.DriverBindingHandle
,
859 EFI_OPEN_PROTOCOL_GET_PROTOCOL
861 if (EFI_ERROR (Status
)) {
863 // No Tcp4, try the Tcp6 protocol
865 Status
= gBS
->OpenProtocol (
867 &gEfiTcp6ProtocolGuid
,
869 gTcpDriverBinding
.DriverBindingHandle
,
871 EFI_OPEN_PROTOCOL_GET_PROTOCOL
873 if (EFI_ERROR (Status
)) {
874 Status
= EFI_UNSUPPORTED
;
878 if (!EFI_ERROR (Status
)) {
880 // destroy this sock and related Tcp protocol control
883 Sock
= SOCK_FROM_THIS (Tcp
);
885 SockDestroyChild (Sock
);
888 gBS
->RestoreTPL (OldTpl
);