From 216f79703b8cb8dc65abdd768bedb2bcdbc1a1f8 Mon Sep 17 00:00:00 2001 From: sfu5 Date: Thu, 13 Dec 2012 06:47:06 +0000 Subject: 1. Add EFI_COMPONENT_NAME2_PROTOCOL.GetControllerName() support. 2. Fix the driver binding Stop() hang issue in the network stack. 3. Add Ip4 raw data support. 4. Add iSCSI Dhcp option 60 support. Signed-off-by: Fu Siyuan Reviewed-by: Ye Ting Reviewed-by: Ouyang Qian git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13995 6f19259b-4bc3-4df7-8a09-765794883524 --- NetworkPkg/TcpDxe/ComponentName.c | 226 +++++++++++++++++++++++++++++++++++++- NetworkPkg/TcpDxe/SockInterface.c | 6 +- NetworkPkg/TcpDxe/Socket.h | 2 +- NetworkPkg/TcpDxe/TcpDispatcher.c | 42 +++++++ NetworkPkg/TcpDxe/TcpDriver.c | 80 +++++++++++--- NetworkPkg/TcpDxe/TcpMain.h | 10 +- 6 files changed, 342 insertions(+), 24 deletions(-) (limited to 'NetworkPkg/TcpDxe') diff --git a/NetworkPkg/TcpDxe/ComponentName.c b/NetworkPkg/TcpDxe/ComponentName.c index f1e0e62f73..9b4dada6a0 100644 --- a/NetworkPkg/TcpDxe/ComponentName.c +++ b/NetworkPkg/TcpDxe/ComponentName.c @@ -2,7 +2,7 @@ Implementation of protocols EFI_COMPONENT_NAME_PROTOCOL and EFI_COMPONENT_NAME2_PROTOCOL. - Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.
+ Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License @@ -170,6 +170,8 @@ GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mTcpDriverNameTabl } }; +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE *gTcpControllerNameTable = NULL; + /** Retrieves a Unicode string that is the user-readable name of the driver. @@ -224,6 +226,142 @@ TcpComponentNameGetDriverName ( ); } +/** + Update the component name for the Tcp4 child handle. + + @param Tcp4[in] A pointer to the EFI_TCP4_PROTOCOL. + + + @retval EFI_SUCCESS Update the ControllerNameTable of this instance successfully. + @retval EFI_INVALID_PARAMETER The input parameter is invalid. + +**/ +EFI_STATUS +UpdateTcp4Name ( + IN EFI_TCP4_PROTOCOL *Tcp4 + ) +{ + EFI_STATUS Status; + CHAR16 HandleName[80]; + EFI_TCP4_CONFIG_DATA Tcp4ConfigData; + + if (Tcp4 == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Format the child name into the string buffer as: + // TCPv4 (SrcPort=59, DestPort=60, ActiveFlag=TRUE) + // + Status = Tcp4->GetModeData (Tcp4, NULL, &Tcp4ConfigData, NULL, NULL, NULL); + if (!EFI_ERROR (Status)) { + UnicodeSPrint (HandleName, sizeof (HandleName), + L"TCPv4 (SrcPort=%d, DestPort=&d, ActiveFlag=%s)", + Tcp4ConfigData.AccessPoint.StationPort, + Tcp4ConfigData.AccessPoint.RemotePort, + (Tcp4ConfigData.AccessPoint.ActiveFlag ? L"TRUE" : L"FALSE") + ); + } if (Status == EFI_NOT_STARTED) { + UnicodeSPrint ( + HandleName, + sizeof (HandleName), + L"TCPv4 (Not started)" + ); + } else { + return Status; + } + + if (gTcpControllerNameTable != NULL) { + FreeUnicodeStringTable (gTcpControllerNameTable); + gTcpControllerNameTable = NULL; + } + + Status = AddUnicodeString2 ( + "eng", + gTcpComponentName.SupportedLanguages, + &gTcpControllerNameTable, + HandleName, + TRUE + ); + if (EFI_ERROR (Status)) { + return Status; + } + + return AddUnicodeString2 ( + "en", + gTcpComponentName2.SupportedLanguages, + &gTcpControllerNameTable, + HandleName, + FALSE + ); +} + +/** + Update the component name for the Tcp6 child handle. + + @param Tcp6[in] A pointer to the EFI_TCP6_PROTOCOL. + + + @retval EFI_SUCCESS Update the ControllerNameTable of this instance successfully. + @retval EFI_INVALID_PARAMETER The input parameter is invalid. + +**/ +EFI_STATUS +UpdateTcp6Name ( + IN EFI_TCP6_PROTOCOL *Tcp6 + ) +{ + EFI_STATUS Status; + CHAR16 HandleName[80]; + EFI_TCP6_CONFIG_DATA Tcp6ConfigData; + + if (Tcp6 == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Format the child name into the string buffer. + // + Status = Tcp6->GetModeData (Tcp6, NULL, &Tcp6ConfigData, NULL, NULL, NULL); + if (!EFI_ERROR (Status)) { + UnicodeSPrint (HandleName, sizeof (HandleName), + L"TCPv6(SrcPort=%d, DestPort=%d, ActiveFlag=%d)", + Tcp6ConfigData.AccessPoint.StationPort, + Tcp6ConfigData.AccessPoint.RemotePort, + Tcp6ConfigData.AccessPoint.ActiveFlag + ); + } else if (Status == EFI_NOT_STARTED) { + UnicodeSPrint (HandleName, sizeof (HandleName), L"TCPv6(Not started)"); + } else { + return Status; + } + + + if (gTcpControllerNameTable != NULL) { + FreeUnicodeStringTable (gTcpControllerNameTable); + gTcpControllerNameTable = NULL; + } + + Status = AddUnicodeString2 ( + "eng", + gTcpComponentName.SupportedLanguages, + &gTcpControllerNameTable, + HandleName, + TRUE + ); + if (EFI_ERROR (Status)) { + return Status; + } + + return AddUnicodeString2 ( + "en", + gTcpComponentName2.SupportedLanguages, + &gTcpControllerNameTable, + HandleName, + FALSE + ); +} + /** Retrieves a Unicode string that is the user-readable name of the controller that is being managed by a driver. @@ -300,5 +438,89 @@ TcpComponentNameGetControllerName ( OUT CHAR16 **ControllerName ) { - return EFI_UNSUPPORTED; + EFI_STATUS Status; + EFI_TCP4_PROTOCOL *Tcp4; + EFI_TCP6_PROTOCOL *Tcp6; + + // + // Only provide names for child handles. + // + if (ChildHandle == NULL) { + return EFI_UNSUPPORTED; + } + + // + // Make sure this driver produced ChildHandle + // + Status = EfiTestChildHandle ( + ControllerHandle, + ChildHandle, + &gEfiIp6ProtocolGuid + ); + if (!EFI_ERROR (Status)) { + // + // Retrieve an instance of a produced protocol from ChildHandle + // + Status = gBS->OpenProtocol ( + ChildHandle, + &gEfiTcp6ProtocolGuid, + (VOID **)&Tcp6, + NULL, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Update the component name for this child handle. + // + Status = UpdateTcp6Name (Tcp6); + if (EFI_ERROR (Status)) { + return Status; + } + } + + // + // Make sure this driver is currently managing ControllHandle + // + Status = EfiTestChildHandle ( + ControllerHandle, + ChildHandle, + &gEfiIp4ProtocolGuid + ); + if (!EFI_ERROR (Status)) { + // + // Retrieve an instance of a produced protocol from ChildHandle + // + Status = gBS->OpenProtocol ( + ChildHandle, + &gEfiTcp4ProtocolGuid, + (VOID **)&Tcp4, + NULL, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Update the component name for this child handle. + // + Status = UpdateTcp4Name (Tcp4); + if (EFI_ERROR (Status)) { + return Status; + } + } + + return LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + gTcpControllerNameTable, + ControllerName, + (BOOLEAN)(This == &gTcpComponentName) + ); } + diff --git a/NetworkPkg/TcpDxe/SockInterface.c b/NetworkPkg/TcpDxe/SockInterface.c index 075e9ada6a..4abda74220 100644 --- a/NetworkPkg/TcpDxe/SockInterface.c +++ b/NetworkPkg/TcpDxe/SockInterface.c @@ -146,11 +146,11 @@ SockDestroyChild ( ASSERT ((Sock != NULL) && (Sock->ProtoHandler != NULL)); - if (Sock->IsDestroyed) { + if (Sock->InDestroy) { return EFI_SUCCESS; } - Sock->IsDestroyed = TRUE; + Sock->InDestroy = TRUE; Status = EfiAcquireLockOrFail (&(Sock->Lock)); if (EFI_ERROR (Status)) { @@ -177,7 +177,7 @@ SockDestroyChild ( Status) ); - Sock->IsDestroyed = FALSE; + Sock->InDestroy = FALSE; } else if (SOCK_IS_CONFIGURED (Sock)) { SockConnFlush (Sock); diff --git a/NetworkPkg/TcpDxe/Socket.h b/NetworkPkg/TcpDxe/Socket.h index 9e2d907150..5a63047f90 100644 --- a/NetworkPkg/TcpDxe/Socket.h +++ b/NetworkPkg/TcpDxe/Socket.h @@ -477,7 +477,7 @@ struct _TCP_SOCKET { SOCK_BUFFER SndBuffer; ///< Send buffer of application's data SOCK_BUFFER RcvBuffer; ///< Receive buffer of received data EFI_STATUS SockError; ///< The error returned by low layer protocol - BOOLEAN IsDestroyed; + BOOLEAN InDestroy; // // Fields used to manage the connection request diff --git a/NetworkPkg/TcpDxe/TcpDispatcher.c b/NetworkPkg/TcpDxe/TcpDispatcher.c index 3e6d34c63f..d3d2cb1c3a 100644 --- a/NetworkPkg/TcpDxe/TcpDispatcher.c +++ b/NetworkPkg/TcpDxe/TcpDispatcher.c @@ -354,7 +354,16 @@ TcpAttachPcb ( TCP_CB *Tcb; TCP_PROTO_DATA *ProtoData; IP_IO *IpIo; + EFI_STATUS Status; + VOID *Ip; + EFI_GUID *IpProtocolGuid; + if (Sk->IpVersion == IP_VERSION_4) { + IpProtocolGuid = &gEfiIp4ProtocolGuid; + } else { + IpProtocolGuid = &gEfiIp6ProtocolGuid; + } + Tcb = AllocateZeroPool (sizeof (TCP_CB)); if (Tcb == NULL) { @@ -377,6 +386,22 @@ TcpAttachPcb ( return EFI_OUT_OF_RESOURCES; } + // + // Open the new created IP instance BY_CHILD. + // + Status = gBS->OpenProtocol ( + Tcb->IpInfo->ChildHandle, + IpProtocolGuid, + &Ip, + IpIo->Image, + Sk->SockHandle, + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + if (EFI_ERROR (Status)) { + IpIoRemoveIp (IpIo, Tcb->IpInfo); + return Status; + } + InitializeListHead (&Tcb->List); InitializeListHead (&Tcb->SndQue); InitializeListHead (&Tcb->RcvQue); @@ -401,7 +426,14 @@ TcpDetachPcb ( { TCP_PROTO_DATA *ProtoData; TCP_CB *Tcb; + EFI_GUID *IpProtocolGuid; + if (Sk->IpVersion == IP_VERSION_4) { + IpProtocolGuid = &gEfiIp4ProtocolGuid; + } else { + IpProtocolGuid = &gEfiIp6ProtocolGuid; + } + ProtoData = (TCP_PROTO_DATA *) Sk->ProtoReserved; Tcb = ProtoData->TcpPcb; @@ -409,6 +441,16 @@ TcpDetachPcb ( TcpFlushPcb (Tcb); + // + // Close the IP protocol. + // + gBS->CloseProtocol ( + Tcb->IpInfo->ChildHandle, + IpProtocolGuid, + ProtoData->TcpService->IpIo->Image, + Sk->SockHandle + ); + IpIoRemoveIp (ProtoData->TcpService->IpIo, Tcb->IpInfo); FreePool (Tcb); diff --git a/NetworkPkg/TcpDxe/TcpDriver.c b/NetworkPkg/TcpDxe/TcpDriver.c index c9ac10c758..4e697b1f4e 100644 --- a/NetworkPkg/TcpDxe/TcpDriver.c +++ b/NetworkPkg/TcpDxe/TcpDriver.c @@ -1,7 +1,7 @@ /** @file The driver binding and service binding protocol for the TCP driver. - Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.
+ Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License @@ -323,6 +323,7 @@ ON_ERROR: if (TcpServiceData->IpIo != NULL) { IpIoDestroy (TcpServiceData->IpIo); + TcpServiceData->IpIo = NULL; } FreePool (TcpServiceData); @@ -330,14 +331,53 @@ ON_ERROR: return Status; } +/** + Callback function which provided by user to remove one node in NetDestroyLinkList process. + + @param[in] Entry The entry to be removed. + @param[in] Context Pointer to the callback context corresponds to the Context in NetDestroyLinkList. + + @retval EFI_SUCCESS The entry has been removed successfully. + @retval Others Fail to remove the entry. + +**/ +EFI_STATUS +TcpDestroyChildEntryInHandleBuffer ( + IN LIST_ENTRY *Entry, + IN VOID *Context +) +{ + SOCKET *Sock; + EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding; + UINTN NumberOfChildren; + EFI_HANDLE *ChildHandleBuffer; + + if (Entry == NULL || Context == NULL) { + return EFI_INVALID_PARAMETER; + } + + Sock = NET_LIST_USER_STRUCT_S (Entry, SOCKET, Link, SOCK_SIGNATURE); + ServiceBinding = ((TCP_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ServiceBinding; + NumberOfChildren = ((TCP_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->NumberOfChildren; + ChildHandleBuffer = ((TCP_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ChildHandleBuffer; + + if (!NetIsInHandleBuffer (Sock->SockHandle, NumberOfChildren, ChildHandleBuffer)) { + return EFI_SUCCESS; + } + + return ServiceBinding->DestroyChild (ServiceBinding, Sock->SockHandle); +} + /** Destroy a TCP6 or TCP4 service binding instance. It will release all the resources allocated by the instance. @param[in] Controller Controller handle of device to bind driver to. @param[in] ImageHandle The TCP driver's image handle. - @param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If number + @param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If number of children is zero stop the entire bus driver. + @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL + if NumberOfChildren is 0. @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6 @retval EFI_SUCCESS The resources used by the instance were cleaned up. @@ -349,6 +389,7 @@ TcpDestroyService ( IN EFI_HANDLE Controller, IN EFI_HANDLE ImageHandle, IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer, OPTIONAL IN UINT8 IpVersion ) { @@ -358,7 +399,8 @@ TcpDestroyService ( EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding; TCP_SERVICE_DATA *TcpServiceData; EFI_STATUS Status; - SOCKET *Sock; + LIST_ENTRY *List; + TCP_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context; ASSERT ((IpVersion == IP_VERSION_4) || (IpVersion == IP_VERSION_6)); @@ -372,7 +414,7 @@ TcpDestroyService ( NicHandle = NetLibGetNicHandle (Controller, IpProtocolGuid); if (NicHandle == NULL) { - return EFI_NOT_FOUND; + return EFI_SUCCESS; } Status = gBS->OpenProtocol ( @@ -389,7 +431,18 @@ TcpDestroyService ( TcpServiceData = TCP_SERVICE_FROM_THIS (ServiceBinding); - if (NumberOfChildren == 0) { + if (NumberOfChildren != 0) { + List = &TcpServiceData->SocketList; + Context.ServiceBinding = ServiceBinding; + Context.NumberOfChildren = NumberOfChildren; + Context.ChildHandleBuffer = ChildHandleBuffer; + Status = NetDestroyLinkList ( + List, + TcpDestroyChildEntryInHandleBuffer, + &Context, + NULL + ); + } else if (IsListEmpty (&TcpServiceData->SocketList)) { // // Uninstall TCP servicebinding protocol // @@ -404,6 +457,7 @@ TcpDestroyService ( // Destroy the IpIO consumed by TCP driver // IpIoDestroy (TcpServiceData->IpIo); + TcpServiceData->IpIo = NULL; // // Destroy the heartbeat timer. @@ -419,16 +473,11 @@ TcpDestroyService ( // Release the TCP service data // FreePool (TcpServiceData); - } else { - - while (!IsListEmpty (&TcpServiceData->SocketList)) { - Sock = NET_LIST_HEAD (&TcpServiceData->SocketList, SOCKET, Link); - ServiceBinding->DestroyChild (ServiceBinding, Sock->SockHandle); - } + Status = EFI_SUCCESS; } - return EFI_SUCCESS; + return Status; } /** @@ -595,6 +644,7 @@ TcpDriverBindingStop ( ControllerHandle, This->DriverBindingHandle, NumberOfChildren, + ChildHandleBuffer, IP_VERSION_4 ); @@ -602,6 +652,7 @@ TcpDriverBindingStop ( ControllerHandle, This->DriverBindingHandle, NumberOfChildren, + ChildHandleBuffer, IP_VERSION_6 ); @@ -839,14 +890,11 @@ TcpServiceBindingDestroyChild ( EFI_STATUS Status; VOID *Tcp; SOCKET *Sock; - EFI_TPL OldTpl; if (NULL == This || NULL == ChildHandle) { return EFI_INVALID_PARAMETER; } - OldTpl = gBS->RaiseTPL (TPL_CALLBACK); - // // retrieve the Tcp4 protocol from ChildHandle // @@ -885,7 +933,5 @@ TcpServiceBindingDestroyChild ( SockDestroyChild (Sock); } - gBS->RestoreTPL (OldTpl); - return Status; } diff --git a/NetworkPkg/TcpDxe/TcpMain.h b/NetworkPkg/TcpDxe/TcpMain.h index 69c764cde1..bd4434e26b 100644 --- a/NetworkPkg/TcpDxe/TcpMain.h +++ b/NetworkPkg/TcpDxe/TcpMain.h @@ -2,7 +2,7 @@ Declaration of protocol interfaces in EFI_TCP4_PROTOCOL and EFI_TCP6_PROTOCOL. It is the common head file for all Tcp*.c in TCP driver. - Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.
+ Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License @@ -21,6 +21,7 @@ #include #include #include +#include #include "Socket.h" #include "TcpProto.h" @@ -32,6 +33,7 @@ extern UINT16 mTcp6RandomPort; extern CHAR16 *mTcpStateName[]; extern EFI_COMPONENT_NAME_PROTOCOL gTcpComponentName; extern EFI_COMPONENT_NAME2_PROTOCOL gTcpComponentName2; +extern EFI_UNICODE_STRING_TABLE *gTcpControllerNameTable; extern LIST_ENTRY mTcpRunQue; extern LIST_ENTRY mTcpListenQue; @@ -90,6 +92,12 @@ typedef struct _TCP4_ROUTE_INFO { EFI_IPv4_ADDRESS *GatewayAddress; } TCP4_ROUTE_INFO; +typedef struct { + EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding; + UINTN NumberOfChildren; + EFI_HANDLE *ChildHandleBuffer; +} TCP_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT; + // // EFI_TCP4_PROTOCOL definitions. // -- cgit v1.2.3