4 Copyright (c) 2005 - 2014, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php<BR>
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 UINT16 mTcp4RandomPort
;
19 extern EFI_COMPONENT_NAME_PROTOCOL gTcp4ComponentName
;
20 extern EFI_COMPONENT_NAME2_PROTOCOL gTcp4ComponentName2
;
21 extern EFI_UNICODE_STRING_TABLE
*gTcpControllerNameTable
;
23 TCP4_HEARTBEAT_TIMER mTcp4Timer
= {
28 EFI_TCP4_PROTOCOL mTcp4ProtocolTemplate
= {
41 SOCK_INIT_DATA mTcp4DefaultSockData
= {
48 &mTcp4ProtocolTemplate
,
49 Tcp4CreateSocketCallback
,
50 Tcp4DestroySocketCallback
,
58 EFI_DRIVER_BINDING_PROTOCOL mTcp4DriverBinding
= {
59 Tcp4DriverBindingSupported
,
60 Tcp4DriverBindingStart
,
61 Tcp4DriverBindingStop
,
67 EFI_SERVICE_BINDING_PROTOCOL mTcp4ServiceBinding
= {
68 Tcp4ServiceBindingCreateChild
,
69 Tcp4ServiceBindingDestroyChild
74 Create and start the heartbeat timer for TCP driver.
76 @retval EFI_SUCCESS The timer is successfully created and started.
77 @retval other The timer is not created.
89 if (mTcp4Timer
.RefCnt
== 0) {
91 Status
= gBS
->CreateEvent (
92 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
96 &mTcp4Timer
.TimerEvent
98 if (!EFI_ERROR (Status
)) {
100 Status
= gBS
->SetTimer (
101 mTcp4Timer
.TimerEvent
,
103 (UINT64
) (TICKS_PER_SECOND
/ TCP_TICK_HZ
)
108 if (!EFI_ERROR (Status
)) {
118 Stop and destroy the heartbeat timer for TCP driver.
126 ASSERT (mTcp4Timer
.RefCnt
> 0);
130 if (mTcp4Timer
.RefCnt
> 0) {
134 gBS
->SetTimer (mTcp4Timer
.TimerEvent
, TimerCancel
, 0);
135 gBS
->CloseEvent (mTcp4Timer
.TimerEvent
);
136 mTcp4Timer
.TimerEvent
= NULL
;
140 Callback function which provided by user to remove one node in NetDestroyLinkList process.
142 @param[in] Entry The entry to be removed.
143 @param[in] Context Pointer to the callback context corresponds to the Context in NetDestroyLinkList.
145 @retval EFI_SUCCESS The entry has been removed successfully.
146 @retval Others Fail to remove the entry.
151 Tcp4DestroyChildEntryInHandleBuffer (
152 IN LIST_ENTRY
*Entry
,
157 EFI_SERVICE_BINDING_PROTOCOL
*ServiceBinding
;
158 UINTN NumberOfChildren
;
159 EFI_HANDLE
*ChildHandleBuffer
;
161 if (Entry
== NULL
|| Context
== NULL
) {
162 return EFI_INVALID_PARAMETER
;
165 Sock
= NET_LIST_USER_STRUCT_S (Entry
, SOCKET
, Link
, SOCK_SIGNATURE
);
166 ServiceBinding
= ((TCP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT
*) Context
)->ServiceBinding
;
167 NumberOfChildren
= ((TCP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT
*) Context
)->NumberOfChildren
;
168 ChildHandleBuffer
= ((TCP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT
*) Context
)->ChildHandleBuffer
;
170 if (!NetIsInHandleBuffer (Sock
->SockHandle
, NumberOfChildren
, ChildHandleBuffer
)) {
174 return ServiceBinding
->DestroyChild (ServiceBinding
, Sock
->SockHandle
);
178 The entry point for Tcp4 driver, used to install Tcp4 driver on the ImageHandle.
180 @param ImageHandle The firmware allocated handle for this
182 @param SystemTable Pointer to the EFI system table.
184 @retval EFI_SUCCESS Driver loaded.
185 @retval other Driver not loaded.
190 Tcp4DriverEntryPoint (
191 IN EFI_HANDLE ImageHandle
,
192 IN EFI_SYSTEM_TABLE
*SystemTable
199 // Install the TCP4 Driver Binding Protocol
201 Status
= EfiLibInstallDriverBindingComponentName2 (
209 ASSERT_EFI_ERROR (Status
);
211 // Initialize ISS and random port.
213 Seed
= NetRandomInitSeed ();
214 mTcpGlobalIss
= NET_RANDOM (Seed
) % mTcpGlobalIss
;
215 mTcp4RandomPort
= (UINT16
) (TCP4_PORT_KNOWN
+
216 (UINT16
) (NET_RANDOM(Seed
) % TCP4_PORT_KNOWN
));
223 Tests to see if this driver supports a given controller.
225 If a child device is provided, it further tests to see if this driver supports
226 creating a handle for the specified child device.
228 @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
229 @param ControllerHandle The handle of the controller to test. This handle
230 must support a protocol interface that supplies
231 an I/O abstraction to the driver.
232 @param RemainingDevicePath A pointer to the remaining portion of a device path.
233 This parameter is ignored by device drivers, and is optional for bus drivers.
236 @retval EFI_SUCCESS The device specified by ControllerHandle and
237 RemainingDevicePath is supported by the driver
239 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
240 RemainingDevicePath is already being managed by
241 the driver specified by This.
242 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
243 RemainingDevicePath is already being managed by a
244 different driver or an application that requires
246 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
247 RemainingDevicePath is not supported by the driver
253 Tcp4DriverBindingSupported (
254 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
255 IN EFI_HANDLE ControllerHandle
,
256 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
262 // Test for the Tcp4ServiceBinding Protocol
264 Status
= gBS
->OpenProtocol (
266 &gEfiTcp4ServiceBindingProtocolGuid
,
268 This
->DriverBindingHandle
,
270 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
272 if (!EFI_ERROR (Status
)) {
273 return EFI_ALREADY_STARTED
;
277 // Test for the Ip4 Protocol
279 Status
= gBS
->OpenProtocol (
281 &gEfiIp4ServiceBindingProtocolGuid
,
283 This
->DriverBindingHandle
,
285 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
293 Start this driver on ControllerHandle.
295 The Start() function is designed to be invoked from the EFI boot service
296 ConnectController(). As a result, much of the error checking on the parameters
297 to Start() has been moved into this common boot service. It is legal to call
298 Start() from other locations, but the following calling restrictions must be
299 followed or the system behavior will not be deterministic.
300 1. ControllerHandle must be a valid EFI_HANDLE.
301 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally
302 aligned EFI_DEVICE_PATH_PROTOCOL.
303 3. Prior to calling Start(), the Supported() function for the driver specified
304 by This must have been called with the same calling parameters, and Supported()
305 must have returned EFI_SUCCESS.
307 @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
308 @param ControllerHandle The handle of the controller to start. This handle
309 must support a protocol interface that supplies
310 an I/O abstraction to the driver.
311 @param RemainingDevicePath A pointer to the remaining portion of a device path.
312 This parameter is ignored by device drivers, and is
313 optional for bus drivers.
315 @retval EFI_SUCCESS The device was started.
316 @retval EFI_ALREADY_STARTED The device could not be started due to a device error.
317 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack
323 Tcp4DriverBindingStart (
324 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
325 IN EFI_HANDLE ControllerHandle
,
326 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
330 TCP4_SERVICE_DATA
*TcpServiceData
;
331 IP_IO_OPEN_DATA OpenData
;
333 TcpServiceData
= AllocateZeroPool (sizeof (TCP4_SERVICE_DATA
));
335 if (NULL
== TcpServiceData
) {
336 DEBUG ((EFI_D_ERROR
, "Tcp4DriverBindingStart: Have no enough"
337 " resource to create a Tcp Servcie Data\n"));
339 return EFI_OUT_OF_RESOURCES
;
343 // Create a new IP IO to Consume it
345 TcpServiceData
->IpIo
= IpIoCreate (
346 This
->DriverBindingHandle
,
350 if (NULL
== TcpServiceData
->IpIo
) {
352 DEBUG ((EFI_D_ERROR
, "Tcp4DriverBindingStart: Have no enough"
353 " resource to create an Ip Io\n"));
355 Status
= EFI_OUT_OF_RESOURCES
;
360 // Configure and start IpIo.
362 ZeroMem (&OpenData
, sizeof (IP_IO_OPEN_DATA
));
365 &OpenData
.IpConfigData
.Ip4CfgData
,
366 &mIp4IoDefaultIpConfigData
,
367 sizeof (EFI_IP4_CONFIG_DATA
)
370 OpenData
.IpConfigData
.Ip4CfgData
.DefaultProtocol
= EFI_IP_PROTO_TCP
;
372 OpenData
.PktRcvdNotify
= Tcp4RxCallback
;
373 Status
= IpIoOpen (TcpServiceData
->IpIo
, &OpenData
);
375 if (EFI_ERROR (Status
)) {
380 // Create the timer event used by TCP driver
382 Status
= Tcp4CreateTimer ();
383 if (EFI_ERROR (Status
)) {
385 DEBUG ((EFI_D_ERROR
, "Tcp4DriverBindingStart: Create TcpTimer"
386 " Event failed with %r\n", Status
));
392 // Install the Tcp4ServiceBinding Protocol on the
395 TcpServiceData
->Tcp4ServiceBinding
= mTcp4ServiceBinding
;
397 Status
= gBS
->InstallMultipleProtocolInterfaces (
399 &gEfiTcp4ServiceBindingProtocolGuid
,
400 &TcpServiceData
->Tcp4ServiceBinding
,
403 if (EFI_ERROR (Status
)) {
405 DEBUG ((EFI_D_ERROR
, "Tcp4DriverBindingStart: Install Tcp4 Service Binding"
406 " Protocol failed for %r\n", Status
));
413 // Initialize member in TcpServiceData
415 TcpServiceData
->ControllerHandle
= ControllerHandle
;
416 TcpServiceData
->Signature
= TCP4_DRIVER_SIGNATURE
;
417 TcpServiceData
->DriverBindingHandle
= This
->DriverBindingHandle
;
419 InitializeListHead (&TcpServiceData
->SocketList
);
425 if (TcpServiceData
->IpIo
!= NULL
) {
426 IpIoDestroy (TcpServiceData
->IpIo
);
427 TcpServiceData
->IpIo
= NULL
;
430 FreePool (TcpServiceData
);
437 Stop this driver on ControllerHandle.
439 The Stop() function is designed to be invoked from the EFI boot service
440 DisconnectController(). As a result, much of the error checking on the parameters
441 to Stop() has been moved into this common boot service. It is legal to call Stop()
442 from other locations, but the following calling restrictions must be followed
443 or the system behavior will not be deterministic.
444 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call
445 to this same driver's Start() function.
446 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
447 EFI_HANDLE. In addition, all of these handles must have been created in this
448 driver's Start() function, and the Start() function must have called OpenProtocol()
449 on ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
451 @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
452 @param ControllerHandle A handle to the device being stopped. The handle must
453 support a bus specific I/O protocol for the driver
454 to use to stop the device.
455 @param NumberOfChildren The number of child device handles in ChildHandleBuffer.
456 @param ChildHandleBuffer An array of child handles to be freed. May be NULL if
457 NumberOfChildren is 0.
459 @retval EFI_SUCCESS The device was stopped.
460 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
465 Tcp4DriverBindingStop (
466 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
467 IN EFI_HANDLE ControllerHandle
,
468 IN UINTN NumberOfChildren
,
469 IN EFI_HANDLE
*ChildHandleBuffer
473 EFI_HANDLE NicHandle
;
474 EFI_SERVICE_BINDING_PROTOCOL
*ServiceBinding
;
475 TCP4_SERVICE_DATA
*TcpServiceData
;
477 TCP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context
;
479 // Find the NicHandle where Tcp4 ServiceBinding Protocol is installed.
481 NicHandle
= NetLibGetNicHandle (ControllerHandle
, &gEfiIp4ProtocolGuid
);
482 if (NicHandle
== NULL
) {
487 // Retrieve the TCP driver Data Structure
489 Status
= gBS
->OpenProtocol (
491 &gEfiTcp4ServiceBindingProtocolGuid
,
492 (VOID
**) &ServiceBinding
,
493 This
->DriverBindingHandle
,
495 EFI_OPEN_PROTOCOL_GET_PROTOCOL
497 if (EFI_ERROR (Status
)) {
499 DEBUG ((EFI_D_ERROR
, "Tcp4DriverBindingStop: Locate Tcp4 Service "
500 " Binding Protocol failed with %r\n", Status
));
502 return EFI_DEVICE_ERROR
;
505 TcpServiceData
= TCP4_FROM_THIS (ServiceBinding
);
507 if (NumberOfChildren
!= 0) {
508 List
= &TcpServiceData
->SocketList
;
509 Context
.ServiceBinding
= ServiceBinding
;
510 Context
.NumberOfChildren
= NumberOfChildren
;
511 Context
.ChildHandleBuffer
= ChildHandleBuffer
;
512 Status
= NetDestroyLinkList (
514 Tcp4DestroyChildEntryInHandleBuffer
,
518 } else if (IsListEmpty (&TcpServiceData
->SocketList
)) {
520 // Uninstall TCP servicebinding protocol
522 gBS
->UninstallMultipleProtocolInterfaces (
524 &gEfiTcp4ServiceBindingProtocolGuid
,
530 // Destroy the IpIO consumed by TCP driver
532 IpIoDestroy (TcpServiceData
->IpIo
);
533 TcpServiceData
->IpIo
= NULL
;
536 // Destroy the heartbeat timer.
540 if (gTcpControllerNameTable
!= NULL
) {
541 FreeUnicodeStringTable (gTcpControllerNameTable
);
542 gTcpControllerNameTable
= NULL
;
546 // Release the TCP service data
548 FreePool (TcpServiceData
);
550 Status
= EFI_SUCCESS
;
557 Open Ip4 and device path protocols for a created socket, and insert it in
560 @param This Pointer to the socket just created
561 @param Context Context of the socket
563 @retval EFI_SUCCESS This protocol is installed successfully.
564 @retval other Some error occured.
568 Tcp4CreateSocketCallback (
574 TCP4_SERVICE_DATA
*TcpServiceData
;
575 EFI_IP4_PROTOCOL
*Ip4
;
577 TcpServiceData
= ((TCP4_PROTO_DATA
*) This
->ProtoReserved
)->TcpService
;
580 // Open the default Ip4 protocol of IP_IO BY_DRIVER.
582 Status
= gBS
->OpenProtocol (
583 TcpServiceData
->IpIo
->ChildHandle
,
584 &gEfiIp4ProtocolGuid
,
586 TcpServiceData
->DriverBindingHandle
,
588 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
590 if (EFI_ERROR (Status
)) {
595 // Open the device path on the handle where service binding resides on.
597 Status
= gBS
->OpenProtocol (
598 TcpServiceData
->ControllerHandle
,
599 &gEfiDevicePathProtocolGuid
,
600 (VOID
**) &This
->ParentDevicePath
,
601 TcpServiceData
->DriverBindingHandle
,
603 EFI_OPEN_PROTOCOL_GET_PROTOCOL
605 if (EFI_ERROR (Status
)) {
607 TcpServiceData
->IpIo
->ChildHandle
,
608 &gEfiIp4ProtocolGuid
,
609 TcpServiceData
->DriverBindingHandle
,
614 // Insert this socket into the SocketList.
616 InsertTailList (&TcpServiceData
->SocketList
, &This
->Link
);
623 Close Ip4 and device path protocols for a socket, and remove it from socket list.
625 @param This Pointer to the socket to be removed
626 @param Context Context of the socket
630 Tcp4DestroySocketCallback (
635 TCP4_SERVICE_DATA
*TcpServiceData
;
637 TcpServiceData
= ((TCP4_PROTO_DATA
*) This
->ProtoReserved
)->TcpService
;
640 // Remove this node from the list.
642 RemoveEntryList (&This
->Link
);
645 // Close the Ip4 protocol.
648 TcpServiceData
->IpIo
->ChildHandle
,
649 &gEfiIp4ProtocolGuid
,
650 TcpServiceData
->DriverBindingHandle
,
656 Creates a child handle and installs a protocol.
658 The CreateChild() function installs a protocol on ChildHandle. If ChildHandle
659 is a pointer to NULL, then a new handle is created and returned in ChildHandle.
660 If ChildHandle is not a pointer to NULL, then the protocol installs on the existing
663 @param This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
664 @param ChildHandle Pointer to the handle of the child to create. If it is NULL, then
665 a new handle is created. If it is a pointer to an existing UEFI
666 handle, then the protocol is added to the existing UEFI handle.
668 @retval EFI_SUCCES The protocol was added to ChildHandle.
669 @retval EFI_INVALID_PARAMETER ChildHandle is NULL.
670 @retval EFI_OUT_OF_RESOURCES There are not enough resources availabe to create
672 @retval other The child handle was not created.
677 Tcp4ServiceBindingCreateChild (
678 IN EFI_SERVICE_BINDING_PROTOCOL
*This
,
679 IN OUT EFI_HANDLE
*ChildHandle
683 TCP4_SERVICE_DATA
*TcpServiceData
;
684 TCP4_PROTO_DATA TcpProto
;
688 if (NULL
== This
|| NULL
== ChildHandle
) {
689 return EFI_INVALID_PARAMETER
;
692 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
693 Status
= EFI_SUCCESS
;
694 TcpServiceData
= TCP4_FROM_THIS (This
);
695 TcpProto
.TcpService
= TcpServiceData
;
696 TcpProto
.TcpPcb
= NULL
;
699 // Create a tcp instance with defualt Tcp default
700 // sock init data and TcpProto
702 mTcp4DefaultSockData
.ProtoData
= &TcpProto
;
703 mTcp4DefaultSockData
.DataSize
= sizeof (TCP4_PROTO_DATA
);
704 mTcp4DefaultSockData
.DriverBinding
= TcpServiceData
->DriverBindingHandle
;
706 Sock
= SockCreateChild (&mTcp4DefaultSockData
);
708 DEBUG ((EFI_D_ERROR
, "Tcp4DriverBindingCreateChild: "
709 "No resource to create a Tcp Child\n"));
711 Status
= EFI_OUT_OF_RESOURCES
;
713 *ChildHandle
= Sock
->SockHandle
;
716 mTcp4DefaultSockData
.ProtoData
= NULL
;
718 gBS
->RestoreTPL (OldTpl
);
724 Destroys a child handle with a protocol installed on it.
726 The DestroyChild() function does the opposite of CreateChild(). It removes a protocol
727 that was installed by CreateChild() from ChildHandle. If the removed protocol is the
728 last protocol on ChildHandle, then ChildHandle is destroyed.
730 @param This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
731 @param ChildHandle Handle of the child to destroy
733 @retval EFI_SUCCES The protocol was removed from ChildHandle.
734 @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is
736 @retval EFI_INVALID_PARAMETER Child handle is NULL.
737 @retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle
738 because its services are being used.
739 @retval other The child handle was not destroyed.
744 Tcp4ServiceBindingDestroyChild (
745 IN EFI_SERVICE_BINDING_PROTOCOL
*This
,
746 IN EFI_HANDLE ChildHandle
750 EFI_TCP4_PROTOCOL
*Tcp4
;
753 if (NULL
== This
|| NULL
== ChildHandle
) {
754 return EFI_INVALID_PARAMETER
;
758 // retrieve the Tcp4 protocol from ChildHandle
760 Status
= gBS
->OpenProtocol (
762 &gEfiTcp4ProtocolGuid
,
764 mTcp4DriverBinding
.DriverBindingHandle
,
766 EFI_OPEN_PROTOCOL_GET_PROTOCOL
768 if (EFI_ERROR (Status
)) {
769 Status
= EFI_UNSUPPORTED
;
772 // destroy this sock and related Tcp protocol control
775 Sock
= SOCK_FROM_THIS (Tcp4
);
777 SockDestroyChild (Sock
);