4 Copyright (c) 2005 - 2012, 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.
150 Tcp4DestroyChildEntryInHandleBuffer (
151 IN LIST_ENTRY
*Entry
,
156 EFI_SERVICE_BINDING_PROTOCOL
*ServiceBinding
;
157 UINTN NumberOfChildren
;
158 EFI_HANDLE
*ChildHandleBuffer
;
160 if (Entry
== NULL
|| Context
== NULL
) {
161 return EFI_INVALID_PARAMETER
;
164 Sock
= NET_LIST_USER_STRUCT_S (Entry
, SOCKET
, Link
, SOCK_SIGNATURE
);
165 ServiceBinding
= ((TCP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT
*) Context
)->ServiceBinding
;
166 NumberOfChildren
= ((TCP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT
*) Context
)->NumberOfChildren
;
167 ChildHandleBuffer
= ((TCP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT
*) Context
)->ChildHandleBuffer
;
169 if (!NetIsInHandleBuffer (Sock
->SockHandle
, NumberOfChildren
, ChildHandleBuffer
)) {
173 return ServiceBinding
->DestroyChild (ServiceBinding
, Sock
->SockHandle
);
177 The entry point for Tcp4 driver, used to install Tcp4 driver on the ImageHandle.
179 @param ImageHandle The firmware allocated handle for this
181 @param SystemTable Pointer to the EFI system table.
183 @retval EFI_SUCCESS Driver loaded.
184 @retval other Driver not loaded.
189 Tcp4DriverEntryPoint (
190 IN EFI_HANDLE ImageHandle
,
191 IN EFI_SYSTEM_TABLE
*SystemTable
198 // Install the TCP4 Driver Binding Protocol
200 Status
= EfiLibInstallDriverBindingComponentName2 (
208 ASSERT_EFI_ERROR (Status
);
210 // Initialize ISS and random port.
212 Seed
= NetRandomInitSeed ();
213 mTcpGlobalIss
= NET_RANDOM (Seed
) % mTcpGlobalIss
;
214 mTcp4RandomPort
= (UINT16
) (TCP4_PORT_KNOWN
+
215 (UINT16
) (NET_RANDOM(Seed
) % TCP4_PORT_KNOWN
));
222 Tests to see if this driver supports a given controller.
224 If a child device is provided, it further tests to see if this driver supports
225 creating a handle for the specified child device.
227 @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
228 @param ControllerHandle The handle of the controller to test. This handle
229 must support a protocol interface that supplies
230 an I/O abstraction to the driver.
231 @param RemainingDevicePath A pointer to the remaining portion of a device path.
232 This parameter is ignored by device drivers, and is optional for bus drivers.
235 @retval EFI_SUCCESS The device specified by ControllerHandle and
236 RemainingDevicePath is supported by the driver
238 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
239 RemainingDevicePath is already being managed by
240 the driver specified by This.
241 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
242 RemainingDevicePath is already being managed by a
243 different driver or an application that requires
245 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
246 RemainingDevicePath is not supported by the driver
252 Tcp4DriverBindingSupported (
253 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
254 IN EFI_HANDLE ControllerHandle
,
255 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
261 // Test for the Tcp4ServiceBinding Protocol
263 Status
= gBS
->OpenProtocol (
265 &gEfiTcp4ServiceBindingProtocolGuid
,
267 This
->DriverBindingHandle
,
269 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
271 if (!EFI_ERROR (Status
)) {
272 return EFI_ALREADY_STARTED
;
276 // Test for the Ip4 Protocol
278 Status
= gBS
->OpenProtocol (
280 &gEfiIp4ServiceBindingProtocolGuid
,
282 This
->DriverBindingHandle
,
284 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
292 Start this driver on ControllerHandle.
294 The Start() function is designed to be invoked from the EFI boot service
295 ConnectController(). As a result, much of the error checking on the parameters
296 to Start() has been moved into this common boot service. It is legal to call
297 Start() from other locations, but the following calling restrictions must be
298 followed or the system behavior will not be deterministic.
299 1. ControllerHandle must be a valid EFI_HANDLE.
300 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally
301 aligned EFI_DEVICE_PATH_PROTOCOL.
302 3. Prior to calling Start(), the Supported() function for the driver specified
303 by This must have been called with the same calling parameters, and Supported()
304 must have returned EFI_SUCCESS.
306 @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
307 @param ControllerHandle The handle of the controller to start. This handle
308 must support a protocol interface that supplies
309 an I/O abstraction to the driver.
310 @param RemainingDevicePath A pointer to the remaining portion of a device path.
311 This parameter is ignored by device drivers, and is
312 optional for bus drivers.
314 @retval EFI_SUCCESS The device was started.
315 @retval EFI_ALREADY_STARTED The device could not be started due to a device error.
316 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack
322 Tcp4DriverBindingStart (
323 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
324 IN EFI_HANDLE ControllerHandle
,
325 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
329 TCP4_SERVICE_DATA
*TcpServiceData
;
330 IP_IO_OPEN_DATA OpenData
;
332 TcpServiceData
= AllocateZeroPool (sizeof (TCP4_SERVICE_DATA
));
334 if (NULL
== TcpServiceData
) {
335 DEBUG ((EFI_D_ERROR
, "Tcp4DriverBindingStart: Have no enough"
336 " resource to create a Tcp Servcie Data\n"));
338 return EFI_OUT_OF_RESOURCES
;
342 // Create a new IP IO to Consume it
344 TcpServiceData
->IpIo
= IpIoCreate (
345 This
->DriverBindingHandle
,
349 if (NULL
== TcpServiceData
->IpIo
) {
351 DEBUG ((EFI_D_ERROR
, "Tcp4DriverBindingStart: Have no enough"
352 " resource to create an Ip Io\n"));
354 Status
= EFI_OUT_OF_RESOURCES
;
359 // Configure and start IpIo.
361 ZeroMem (&OpenData
, sizeof (IP_IO_OPEN_DATA
));
364 &OpenData
.IpConfigData
.Ip4CfgData
,
365 &mIp4IoDefaultIpConfigData
,
366 sizeof (EFI_IP4_CONFIG_DATA
)
369 OpenData
.IpConfigData
.Ip4CfgData
.DefaultProtocol
= EFI_IP_PROTO_TCP
;
371 OpenData
.PktRcvdNotify
= Tcp4RxCallback
;
372 Status
= IpIoOpen (TcpServiceData
->IpIo
, &OpenData
);
374 if (EFI_ERROR (Status
)) {
379 // Create the timer event used by TCP driver
381 Status
= Tcp4CreateTimer ();
382 if (EFI_ERROR (Status
)) {
384 DEBUG ((EFI_D_ERROR
, "Tcp4DriverBindingStart: Create TcpTimer"
385 " Event failed with %r\n", Status
));
391 // Install the Tcp4ServiceBinding Protocol on the
394 TcpServiceData
->Tcp4ServiceBinding
= mTcp4ServiceBinding
;
396 Status
= gBS
->InstallMultipleProtocolInterfaces (
398 &gEfiTcp4ServiceBindingProtocolGuid
,
399 &TcpServiceData
->Tcp4ServiceBinding
,
402 if (EFI_ERROR (Status
)) {
404 DEBUG ((EFI_D_ERROR
, "Tcp4DriverBindingStart: Install Tcp4 Service Binding"
405 " Protocol failed for %r\n", Status
));
412 // Initialize member in TcpServiceData
414 TcpServiceData
->ControllerHandle
= ControllerHandle
;
415 TcpServiceData
->Signature
= TCP4_DRIVER_SIGNATURE
;
416 TcpServiceData
->DriverBindingHandle
= This
->DriverBindingHandle
;
418 InitializeListHead (&TcpServiceData
->SocketList
);
420 TcpSetVariableData (TcpServiceData
);
426 if (TcpServiceData
->IpIo
!= NULL
) {
427 IpIoDestroy (TcpServiceData
->IpIo
);
428 TcpServiceData
->IpIo
= NULL
;
431 FreePool (TcpServiceData
);
438 Stop this driver on ControllerHandle.
440 The Stop() function is designed to be invoked from the EFI boot service
441 DisconnectController(). As a result, much of the error checking on the parameters
442 to Stop() has been moved into this common boot service. It is legal to call Stop()
443 from other locations, but the following calling restrictions must be followed
444 or the system behavior will not be deterministic.
445 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call
446 to this same driver's Start() function.
447 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
448 EFI_HANDLE. In addition, all of these handles must have been created in this
449 driver's Start() function, and the Start() function must have called OpenProtocol()
450 on ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
452 @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
453 @param ControllerHandle A handle to the device being stopped. The handle must
454 support a bus specific I/O protocol for the driver
455 to use to stop the device.
456 @param NumberOfChildren The number of child device handles in ChildHandleBuffer.
457 @param ChildHandleBuffer An array of child handles to be freed. May be NULL if
458 NumberOfChildren is 0.
460 @retval EFI_SUCCESS The device was stopped.
461 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
466 Tcp4DriverBindingStop (
467 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
468 IN EFI_HANDLE ControllerHandle
,
469 IN UINTN NumberOfChildren
,
470 IN EFI_HANDLE
*ChildHandleBuffer
474 EFI_HANDLE NicHandle
;
475 EFI_SERVICE_BINDING_PROTOCOL
*ServiceBinding
;
476 TCP4_SERVICE_DATA
*TcpServiceData
;
478 TCP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context
;
480 // Find the NicHandle where Tcp4 ServiceBinding Protocol is installed.
482 NicHandle
= NetLibGetNicHandle (ControllerHandle
, &gEfiIp4ProtocolGuid
);
483 if (NicHandle
== NULL
) {
488 // Retrieve the TCP driver Data Structure
490 Status
= gBS
->OpenProtocol (
492 &gEfiTcp4ServiceBindingProtocolGuid
,
493 (VOID
**) &ServiceBinding
,
494 This
->DriverBindingHandle
,
496 EFI_OPEN_PROTOCOL_GET_PROTOCOL
498 if (EFI_ERROR (Status
)) {
500 DEBUG ((EFI_D_ERROR
, "Tcp4DriverBindingStop: Locate Tcp4 Service "
501 " Binding Protocol failed with %r\n", Status
));
503 return EFI_DEVICE_ERROR
;
506 TcpServiceData
= TCP4_FROM_THIS (ServiceBinding
);
508 if (NumberOfChildren
!= 0) {
509 List
= &TcpServiceData
->SocketList
;
510 Context
.ServiceBinding
= ServiceBinding
;
511 Context
.NumberOfChildren
= NumberOfChildren
;
512 Context
.ChildHandleBuffer
= ChildHandleBuffer
;
513 Status
= NetDestroyLinkList (
515 Tcp4DestroyChildEntryInHandleBuffer
,
519 } else if (IsListEmpty (&TcpServiceData
->SocketList
)) {
521 // Uninstall TCP servicebinding protocol
523 gBS
->UninstallMultipleProtocolInterfaces (
525 &gEfiTcp4ServiceBindingProtocolGuid
,
531 // Destroy the IpIO consumed by TCP driver
533 IpIoDestroy (TcpServiceData
->IpIo
);
534 TcpServiceData
->IpIo
= NULL
;
537 // Destroy the heartbeat timer.
542 // Clear the variable.
544 TcpClearVariableData (TcpServiceData
);
546 if (gTcpControllerNameTable
!= NULL
) {
547 FreeUnicodeStringTable (gTcpControllerNameTable
);
548 gTcpControllerNameTable
= NULL
;
552 // Release the TCP service data
554 FreePool (TcpServiceData
);
556 Status
= EFI_SUCCESS
;
563 Open Ip4 and device path protocols for a created socket, and insert it in
566 @param This Pointer to the socket just created
567 @param Context Context of the socket
569 @retval EFI_SUCCESS This protocol is installed successfully.
570 @retval other Some error occured.
574 Tcp4CreateSocketCallback (
580 TCP4_SERVICE_DATA
*TcpServiceData
;
581 EFI_IP4_PROTOCOL
*Ip4
;
583 TcpServiceData
= ((TCP4_PROTO_DATA
*) This
->ProtoReserved
)->TcpService
;
586 // Open the default Ip4 protocol of IP_IO BY_DRIVER.
588 Status
= gBS
->OpenProtocol (
589 TcpServiceData
->IpIo
->ChildHandle
,
590 &gEfiIp4ProtocolGuid
,
592 TcpServiceData
->DriverBindingHandle
,
594 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
596 if (EFI_ERROR (Status
)) {
601 // Open the device path on the handle where service binding resides on.
603 Status
= gBS
->OpenProtocol (
604 TcpServiceData
->ControllerHandle
,
605 &gEfiDevicePathProtocolGuid
,
606 (VOID
**) &This
->ParentDevicePath
,
607 TcpServiceData
->DriverBindingHandle
,
609 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
611 if (EFI_ERROR (Status
)) {
613 TcpServiceData
->IpIo
->ChildHandle
,
614 &gEfiIp4ProtocolGuid
,
615 TcpServiceData
->DriverBindingHandle
,
620 // Insert this socket into the SocketList.
622 InsertTailList (&TcpServiceData
->SocketList
, &This
->Link
);
629 Close Ip4 and device path protocols for a socket, and remove it from socket list.
631 @param This Pointer to the socket to be removed
632 @param Context Context of the socket
636 Tcp4DestroySocketCallback (
641 TCP4_SERVICE_DATA
*TcpServiceData
;
643 TcpServiceData
= ((TCP4_PROTO_DATA
*) This
->ProtoReserved
)->TcpService
;
646 // Remove this node from the list.
648 RemoveEntryList (&This
->Link
);
651 // Close the device path protocol
654 TcpServiceData
->ControllerHandle
,
655 &gEfiDevicePathProtocolGuid
,
656 TcpServiceData
->DriverBindingHandle
,
661 // Close the Ip4 protocol.
664 TcpServiceData
->IpIo
->ChildHandle
,
665 &gEfiIp4ProtocolGuid
,
666 TcpServiceData
->DriverBindingHandle
,
672 Creates a child handle and installs a protocol.
674 The CreateChild() function installs a protocol on ChildHandle. If ChildHandle
675 is a pointer to NULL, then a new handle is created and returned in ChildHandle.
676 If ChildHandle is not a pointer to NULL, then the protocol installs on the existing
679 @param This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
680 @param ChildHandle Pointer to the handle of the child to create. If it is NULL, then
681 a new handle is created. If it is a pointer to an existing UEFI
682 handle, then the protocol is added to the existing UEFI handle.
684 @retval EFI_SUCCES The protocol was added to ChildHandle.
685 @retval EFI_INVALID_PARAMETER ChildHandle is NULL.
686 @retval EFI_OUT_OF_RESOURCES There are not enough resources availabe to create
688 @retval other The child handle was not created.
693 Tcp4ServiceBindingCreateChild (
694 IN EFI_SERVICE_BINDING_PROTOCOL
*This
,
695 IN OUT EFI_HANDLE
*ChildHandle
699 TCP4_SERVICE_DATA
*TcpServiceData
;
700 TCP4_PROTO_DATA TcpProto
;
704 if (NULL
== This
|| NULL
== ChildHandle
) {
705 return EFI_INVALID_PARAMETER
;
708 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
709 Status
= EFI_SUCCESS
;
710 TcpServiceData
= TCP4_FROM_THIS (This
);
711 TcpProto
.TcpService
= TcpServiceData
;
712 TcpProto
.TcpPcb
= NULL
;
715 // Create a tcp instance with defualt Tcp default
716 // sock init data and TcpProto
718 mTcp4DefaultSockData
.ProtoData
= &TcpProto
;
719 mTcp4DefaultSockData
.DataSize
= sizeof (TCP4_PROTO_DATA
);
720 mTcp4DefaultSockData
.DriverBinding
= TcpServiceData
->DriverBindingHandle
;
722 Sock
= SockCreateChild (&mTcp4DefaultSockData
);
724 DEBUG ((EFI_D_ERROR
, "Tcp4DriverBindingCreateChild: "
725 "No resource to create a Tcp Child\n"));
727 Status
= EFI_OUT_OF_RESOURCES
;
729 *ChildHandle
= Sock
->SockHandle
;
732 mTcp4DefaultSockData
.ProtoData
= NULL
;
734 gBS
->RestoreTPL (OldTpl
);
740 Destroys a child handle with a protocol installed on it.
742 The DestroyChild() function does the opposite of CreateChild(). It removes a protocol
743 that was installed by CreateChild() from ChildHandle. If the removed protocol is the
744 last protocol on ChildHandle, then ChildHandle is destroyed.
746 @param This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
747 @param ChildHandle Handle of the child to destroy
749 @retval EFI_SUCCES The protocol was removed from ChildHandle.
750 @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is
752 @retval EFI_INVALID_PARAMETER Child handle is NULL.
753 @retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle
754 because its services are being used.
755 @retval other The child handle was not destroyed.
760 Tcp4ServiceBindingDestroyChild (
761 IN EFI_SERVICE_BINDING_PROTOCOL
*This
,
762 IN EFI_HANDLE ChildHandle
766 EFI_TCP4_PROTOCOL
*Tcp4
;
769 if (NULL
== This
|| NULL
== ChildHandle
) {
770 return EFI_INVALID_PARAMETER
;
774 // retrieve the Tcp4 protocol from ChildHandle
776 Status
= gBS
->OpenProtocol (
778 &gEfiTcp4ProtocolGuid
,
780 mTcp4DriverBinding
.DriverBindingHandle
,
782 EFI_OPEN_PROTOCOL_GET_PROTOCOL
784 if (EFI_ERROR (Status
)) {
785 Status
= EFI_UNSUPPORTED
;
788 // destroy this sock and related Tcp protocol control
791 Sock
= SOCK_FROM_THIS (Tcp4
);
793 SockDestroyChild (Sock
);