]> git.proxmox.com Git - mirror_edk2.git/blobdiff - NetworkPkg/TcpDxe/TcpDriver.c
Fix a bug about the iSCSI DHCP dependency issue.
[mirror_edk2.git] / NetworkPkg / TcpDxe / TcpDriver.c
index 3e01f34892ffe006d5d4ec90367e4e7084ac0048..1f0d3716542c422e4cd62468f24bc0e49b6d5270 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   The driver binding and service binding protocol for the TCP driver.\r
 \r
-  Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2009 - 2013, Intel Corporation. All rights reserved.<BR>\r
 \r
   This program and the accompanying materials\r
   are licensed and made available under the terms and conditions of the BSD License\r
@@ -66,10 +66,19 @@ SOCK_INIT_DATA                mTcpDefaultSockData = {
   NULL,\r
 };\r
 \r
-EFI_DRIVER_BINDING_PROTOCOL   gTcpDriverBinding = {\r
-  TcpDriverBindingSupported,\r
-  TcpDriverBindingStart,\r
-  TcpDriverBindingStop,\r
+EFI_DRIVER_BINDING_PROTOCOL   gTcp4DriverBinding = {\r
+  Tcp4DriverBindingSupported,\r
+  Tcp4DriverBindingStart,\r
+  Tcp4DriverBindingStop,\r
+  0xa,\r
+  NULL,\r
+  NULL\r
+};\r
+\r
+EFI_DRIVER_BINDING_PROTOCOL   gTcp6DriverBinding = {\r
+  Tcp6DriverBindingSupported,\r
+  Tcp6DriverBindingStart,\r
+  Tcp6DriverBindingStop,\r
   0xa,\r
   NULL,\r
   NULL\r
@@ -172,12 +181,37 @@ TcpDriverEntryPoint (
   Status = EfiLibInstallDriverBindingComponentName2 (\r
              ImageHandle,\r
              SystemTable,\r
-             &gTcpDriverBinding,\r
+             &gTcp4DriverBinding,\r
+             ImageHandle,\r
+             &gTcpComponentName,\r
+             &gTcpComponentName2\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Install the TCP Driver Binding Protocol\r
+  //\r
+  Status = EfiLibInstallDriverBindingComponentName2 (\r
              ImageHandle,\r
+             SystemTable,\r
+             &gTcp6DriverBinding,\r
+             NULL,\r
              &gTcpComponentName,\r
              &gTcpComponentName2\r
              );\r
   if (EFI_ERROR (Status)) {\r
+    gBS->UninstallMultipleProtocolInterfaces (\r
+           ImageHandle,\r
+           &gEfiDriverBindingProtocolGuid,\r
+           &gTcp4DriverBinding,\r
+           &gEfiComponentName2ProtocolGuid,\r
+           &gTcpComponentName2,\r
+           &gEfiComponentNameProtocolGuid,\r
+           &gTcpComponentName,\r
+           NULL\r
+           );\r
     return Status;\r
   }\r
 \r
@@ -323,6 +357,7 @@ ON_ERROR:
 \r
   if (TcpServiceData->IpIo != NULL) {\r
     IpIoDestroy (TcpServiceData->IpIo);\r
+    TcpServiceData->IpIo = NULL;\r
   }\r
 \r
   FreePool (TcpServiceData);\r
@@ -330,14 +365,54 @@ ON_ERROR:
   return Status;\r
 }\r
 \r
+/**\r
+  Callback function which provided by user to remove one node in NetDestroyLinkList process.\r
+  \r
+  @param[in]    Entry           The entry to be removed.\r
+  @param[in]    Context         Pointer to the callback context corresponds to the Context in NetDestroyLinkList.\r
+\r
+  @retval EFI_SUCCESS           The entry has been removed successfully.\r
+  @retval Others                Fail to remove the entry.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TcpDestroyChildEntryInHandleBuffer (\r
+  IN LIST_ENTRY         *Entry,\r
+  IN VOID               *Context\r
+  )\r
+{\r
+  SOCKET                        *Sock;\r
+  EFI_SERVICE_BINDING_PROTOCOL  *ServiceBinding;\r
+  UINTN                         NumberOfChildren;\r
+  EFI_HANDLE                    *ChildHandleBuffer;\r
+\r
+  if (Entry == NULL || Context == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Sock = NET_LIST_USER_STRUCT_S (Entry, SOCKET, Link, SOCK_SIGNATURE);\r
+  ServiceBinding    = ((TCP_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ServiceBinding;\r
+  NumberOfChildren  = ((TCP_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->NumberOfChildren;\r
+  ChildHandleBuffer = ((TCP_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ChildHandleBuffer;\r
+\r
+  if (!NetIsInHandleBuffer (Sock->SockHandle, NumberOfChildren, ChildHandleBuffer)) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  return ServiceBinding->DestroyChild (ServiceBinding, Sock->SockHandle);\r
+}\r
+\r
 /**\r
   Destroy a TCP6 or TCP4 service binding instance. It will release all\r
   the resources allocated by the instance.\r
 \r
   @param[in]  Controller         Controller handle of device to bind driver to.\r
   @param[in]  ImageHandle        The TCP driver's image handle.\r
-  @param[in]  NumberOfChildren    Number of Handles in ChildHandleBuffer. If number\r
+  @param[in]  NumberOfChildren   Number of Handles in ChildHandleBuffer. If number\r
                                  of children is zero stop the entire bus driver.\r
+  @param[in]  ChildHandleBuffer  An array of child handles to be freed. May be NULL\r
+                                 if NumberOfChildren is 0.  \r
   @param[in]  IpVersion          IP_VERSION_4 or IP_VERSION_6\r
 \r
   @retval EFI_SUCCESS            The resources used by the instance were cleaned up.\r
@@ -349,6 +424,7 @@ TcpDestroyService (
   IN EFI_HANDLE  Controller,\r
   IN EFI_HANDLE  ImageHandle,\r
   IN UINTN       NumberOfChildren,\r
+  IN EFI_HANDLE  *ChildHandleBuffer, OPTIONAL\r
   IN UINT8       IpVersion\r
   )\r
 {\r
@@ -358,7 +434,8 @@ TcpDestroyService (
   EFI_SERVICE_BINDING_PROTOCOL  *ServiceBinding;\r
   TCP_SERVICE_DATA              *TcpServiceData;\r
   EFI_STATUS                    Status;\r
-  SOCKET                        *Sock;\r
+  LIST_ENTRY                    *List;\r
+  TCP_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT  Context;\r
 \r
   ASSERT ((IpVersion == IP_VERSION_4) || (IpVersion == IP_VERSION_6));\r
 \r
@@ -372,7 +449,7 @@ TcpDestroyService (
 \r
   NicHandle = NetLibGetNicHandle (Controller, IpProtocolGuid);\r
   if (NicHandle == NULL) {\r
-    return EFI_NOT_FOUND;\r
+    return EFI_SUCCESS;\r
   }\r
 \r
   Status = gBS->OpenProtocol (\r
@@ -389,7 +466,18 @@ TcpDestroyService (
 \r
   TcpServiceData = TCP_SERVICE_FROM_THIS (ServiceBinding);\r
 \r
-  if (NumberOfChildren == 0) {\r
+  if (NumberOfChildren != 0) {\r
+    List = &TcpServiceData->SocketList;\r
+    Context.ServiceBinding = ServiceBinding;\r
+    Context.NumberOfChildren = NumberOfChildren;\r
+    Context.ChildHandleBuffer = ChildHandleBuffer;\r
+    Status = NetDestroyLinkList (\r
+               List,\r
+               TcpDestroyChildEntryInHandleBuffer,\r
+               &Context,\r
+               NULL\r
+               );\r
+  } else if (IsListEmpty (&TcpServiceData->SocketList)) {\r
     //\r
     // Uninstall TCP servicebinding protocol\r
     //\r
@@ -404,6 +492,7 @@ TcpDestroyService (
     // Destroy the IpIO consumed by TCP driver\r
     //\r
     IpIoDestroy (TcpServiceData->IpIo);\r
+    TcpServiceData->IpIo = NULL;\r
 \r
     //\r
     // Destroy the heartbeat timer.\r
@@ -419,16 +508,11 @@ TcpDestroyService (
     // Release the TCP service data\r
     //\r
     FreePool (TcpServiceData);\r
-  } else {\r
-\r
-    while (!IsListEmpty (&TcpServiceData->SocketList)) {\r
-      Sock = NET_LIST_HEAD (&TcpServiceData->SocketList, SOCKET, Link);\r
 \r
-      ServiceBinding->DestroyChild (ServiceBinding, Sock->SockHandle);\r
-    }\r
+    Status = EFI_SUCCESS;\r
   }\r
 \r
-  return EFI_SUCCESS;\r
+  return Status;\r
 }\r
 \r
 /**\r
@@ -446,14 +530,13 @@ TcpDestroyService (
 **/\r
 EFI_STATUS\r
 EFIAPI\r
-TcpDriverBindingSupported (\r
+Tcp4DriverBindingSupported (\r
   IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
   IN EFI_HANDLE                   ControllerHandle,\r
   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL\r
   )\r
 {\r
   EFI_STATUS  Status;\r
-  BOOLEAN     IsTcp4Started;\r
 \r
   //\r
   // Test for the Tcp4ServiceBinding Protocol\r
@@ -466,29 +549,114 @@ TcpDriverBindingSupported (
                   ControllerHandle,\r
                   EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
                   );\r
-  if (EFI_ERROR (Status)) {\r
-    //\r
-    // Test for the Ip4ServiceBinding Protocol\r
-    //\r
-    Status = gBS->OpenProtocol (\r
-                    ControllerHandle,\r
-                    &gEfiIp4ServiceBindingProtocolGuid,\r
-                    NULL,\r
-                    This->DriverBindingHandle,\r
-                    ControllerHandle,\r
-                    EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
-                    );\r
-    if (!EFI_ERROR (Status)) {\r
-      return EFI_SUCCESS;\r
-    }\r
+  if (!EFI_ERROR (Status)) {\r
+    return EFI_ALREADY_STARTED;\r
+  }\r
+  \r
+  //\r
+  // Test for the Ip4ServiceBinding Protocol\r
+  //\r
+  Status = gBS->OpenProtocol (\r
+                  ControllerHandle,\r
+                  &gEfiIp4ServiceBindingProtocolGuid,\r
+                  NULL,\r
+                  This->DriverBindingHandle,\r
+                  ControllerHandle,\r
+                  EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
+                  );\r
+  return Status;\r
+}\r
 \r
-    IsTcp4Started = FALSE;\r
-  } else {\r
-    IsTcp4Started = TRUE;\r
+/**\r
+  Start this driver on ControllerHandle.\r
+\r
+  @param[in]  This                   Protocol instance pointer.\r
+  @param[in]  ControllerHandle       Handle of device to bind driver to.\r
+  @param[in]  RemainingDevicePath    Optional parameter use to pick a specific child\r
+                                     device to start.\r
+\r
+  @retval EFI_SUCCESS            The driver is added to ControllerHandle.\r
+  @retval EFI_OUT_OF_RESOURCES   There are not enough resources to start the\r
+                                 driver.\r
+  @retval other                  The driver cannot be added to ControllerHandle.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tcp4DriverBindingStart (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN EFI_HANDLE                   ControllerHandle,\r
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  Status = TcpCreateService (ControllerHandle, This->DriverBindingHandle, IP_VERSION_4);\r
+  if ((Status == EFI_ALREADY_STARTED) || (Status == EFI_UNSUPPORTED)) {\r
+    Status = EFI_SUCCESS;\r
   }\r
 \r
+  return Status;\r
+}\r
+\r
+/**\r
+  Stop this driver on ControllerHandle.\r
+\r
+  @param[in]  This              A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
+  @param[in]  ControllerHandle  A handle to the device being stopped. The handle must\r
+                                support a bus specific I/O protocol for the driver\r
+                                to use to stop the device.\r
+  @param[in]  NumberOfChildren  The number of child device handles in ChildHandleBuffer.\r
+  @param[in]  ChildHandleBuffer An array of child handles to be freed. May be NULL\r
+                                if NumberOfChildren is 0.\r
+\r
+  @retval EFI_SUCCESS           The device was stopped.\r
+  @retval EFI_DEVICE_ERROR      The device could not be stopped due to a device error.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tcp4DriverBindingStop (\r
+  IN  EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN  EFI_HANDLE                   ControllerHandle,\r
+  IN  UINTN                        NumberOfChildren,\r
+  IN  EFI_HANDLE                   *ChildHandleBuffer OPTIONAL\r
+  )\r
+{\r
+  return TcpDestroyService (\r
+           ControllerHandle,\r
+           This->DriverBindingHandle,\r
+           NumberOfChildren,\r
+           ChildHandleBuffer,\r
+           IP_VERSION_4\r
+           );\r
+}\r
+\r
+/**\r
+  Test to see if this driver supports ControllerHandle.\r
+\r
+  @param[in]  This                Protocol instance pointer.\r
+  @param[in]  ControllerHandle    Handle of device to test.\r
+  @param[in]  RemainingDevicePath Optional parameter use to pick a specific\r
+                                  child device to start.\r
+\r
+  @retval EFI_SUCCESS             This driver supports this device.\r
+  @retval EFI_ALREADY_STARTED     This driver is already running on this device.\r
+  @retval other                   This driver does not support this device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Tcp6DriverBindingSupported (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN EFI_HANDLE                   ControllerHandle,\r
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
   //\r
-  // Check the Tcp6ServiceBinding Protocol\r
+  // Test for the Tcp6ServiceBinding Protocol\r
   //\r
   Status = gBS->OpenProtocol (\r
                   ControllerHandle,\r
@@ -498,26 +666,22 @@ TcpDriverBindingSupported (
                   ControllerHandle,\r
                   EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
                   );\r
-  if (EFI_ERROR (Status)) {\r
-    //\r
-    // Test for the Ip6ServiceBinding Protocol\r
-    //\r
-    Status = gBS->OpenProtocol (\r
-                    ControllerHandle,\r
-                    &gEfiIp6ServiceBindingProtocolGuid,\r
-                    NULL,\r
-                    This->DriverBindingHandle,\r
-                    ControllerHandle,\r
-                    EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
-                    );\r
-    if (!EFI_ERROR (Status)) {\r
-      return EFI_SUCCESS;\r
-    }\r
-  } else if (IsTcp4Started) {\r
+  if (!EFI_ERROR (Status)) {\r
     return EFI_ALREADY_STARTED;\r
   }\r
-\r
-  return EFI_UNSUPPORTED;\r
+  \r
+  //\r
+  // Test for the Ip6ServiceBinding Protocol\r
+  //\r
+  Status = gBS->OpenProtocol (\r
+                  ControllerHandle,\r
+                  &gEfiIp6ServiceBindingProtocolGuid,\r
+                  NULL,\r
+                  This->DriverBindingHandle,\r
+                  ControllerHandle,\r
+                  EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
+                  );\r
+  return Status;\r
 }\r
 \r
 /**\r
@@ -536,32 +700,20 @@ TcpDriverBindingSupported (
 **/\r
 EFI_STATUS\r
 EFIAPI\r
-TcpDriverBindingStart (\r
+Tcp6DriverBindingStart (\r
   IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
   IN EFI_HANDLE                   ControllerHandle,\r
   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL\r
   )\r
 {\r
-  EFI_STATUS  Tcp4Status;\r
-  EFI_STATUS  Tcp6Status;\r
-\r
-  Tcp4Status = TcpCreateService (ControllerHandle, This->DriverBindingHandle, IP_VERSION_4);\r
-  if ((Tcp4Status == EFI_ALREADY_STARTED) || (Tcp4Status == EFI_UNSUPPORTED)) {\r
-    Tcp4Status = EFI_SUCCESS;\r
-  }\r
+  EFI_STATUS  Status;\r
 \r
-  Tcp6Status = TcpCreateService (ControllerHandle, This->DriverBindingHandle, IP_VERSION_6);\r
-  if ((Tcp6Status == EFI_ALREADY_STARTED) || (Tcp6Status == EFI_UNSUPPORTED)) {\r
-    Tcp6Status = EFI_SUCCESS;\r
+  Status = TcpCreateService (ControllerHandle, This->DriverBindingHandle, IP_VERSION_6);\r
+  if ((Status == EFI_ALREADY_STARTED) || (Status == EFI_UNSUPPORTED)) {\r
+    Status = EFI_SUCCESS;\r
   }\r
 \r
-  if (!EFI_ERROR (Tcp4Status) || !EFI_ERROR (Tcp6Status)) {\r
-    return EFI_SUCCESS;\r
-  } else if (EFI_ERROR (Tcp4Status)) {\r
-    return Tcp4Status;\r
-  } else {\r
-    return Tcp6Status;\r
-  }\r
+  return Status;\r
 }\r
 \r
 /**\r
@@ -581,35 +733,20 @@ TcpDriverBindingStart (
 **/\r
 EFI_STATUS\r
 EFIAPI\r
-TcpDriverBindingStop (\r
+Tcp6DriverBindingStop (\r
   IN  EFI_DRIVER_BINDING_PROTOCOL  *This,\r
   IN  EFI_HANDLE                   ControllerHandle,\r
   IN  UINTN                        NumberOfChildren,\r
   IN  EFI_HANDLE                   *ChildHandleBuffer OPTIONAL\r
   )\r
 {\r
-  EFI_STATUS  Tcp4Status;\r
-  EFI_STATUS  Tcp6Status;\r
-\r
-  Tcp4Status = TcpDestroyService (\r
-                 ControllerHandle,\r
-                 This->DriverBindingHandle,\r
-                 NumberOfChildren,\r
-                 IP_VERSION_4\r
-                 );\r
-\r
-  Tcp6Status = TcpDestroyService (\r
-                 ControllerHandle,\r
-                 This->DriverBindingHandle,\r
-                 NumberOfChildren,\r
-                 IP_VERSION_6\r
-                 );\r
-\r
-  if (EFI_ERROR (Tcp4Status) && EFI_ERROR (Tcp6Status)) {\r
-    return EFI_DEVICE_ERROR;\r
-  } else {\r
-    return EFI_SUCCESS;\r
-  }\r
+  return TcpDestroyService (\r
+           ControllerHandle,\r
+           This->DriverBindingHandle,\r
+           NumberOfChildren,\r
+           ChildHandleBuffer,\r
+           IP_VERSION_6\r
+           );\r
 }\r
 \r
 /**\r
@@ -665,7 +802,7 @@ TcpCreateSocketCallback (
                   (VOID **) &This->ParentDevicePath,\r
                   TcpServiceData->DriverBindingHandle,\r
                   This->SockHandle,\r
-                  EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
                   );\r
   if (EFI_ERROR (Status)) {\r
     gBS->CloseProtocol (\r
@@ -713,16 +850,6 @@ TcpDestroySocketCallback (
   //\r
   RemoveEntryList (&This->Link);\r
 \r
-  //\r
-  // Close the device path protocol\r
-  //\r
-  gBS->CloseProtocol (\r
-         TcpServiceData->ControllerHandle,\r
-         &gEfiDevicePathProtocolGuid,\r
-         TcpServiceData->DriverBindingHandle,\r
-         This->SockHandle\r
-         );\r
-\r
   //\r
   // Close the IP protocol.\r
   //\r
@@ -823,7 +950,7 @@ TcpServiceBindingCreateChild (
 \r
   @retval EFI_SUCCES            The protocol was removed from ChildHandle.\r
   @retval EFI_UNSUPPORTED       ChildHandle does not support the protocol that is being removed.\r
-  @retval EFI_INVALID_PARAMETER Child handle is not a valid UEFI Handle.\r
+  @retval EFI_INVALID_PARAMETER Child handle is NULL.\r
   @retval EFI_ACCESS_DENIED     The protocol could not be removed from the ChildHandle\r
                                 because its services are being used.\r
   @retval other                 The child handle was not destroyed.\r
@@ -839,14 +966,11 @@ TcpServiceBindingDestroyChild (
   EFI_STATUS  Status;\r
   VOID        *Tcp;\r
   SOCKET      *Sock;\r
-  EFI_TPL     OldTpl;\r
 \r
   if (NULL == This || NULL == ChildHandle) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
-\r
   //\r
   // retrieve the Tcp4 protocol from ChildHandle\r
   //\r
@@ -854,7 +978,7 @@ TcpServiceBindingDestroyChild (
                   ChildHandle,\r
                   &gEfiTcp4ProtocolGuid,\r
                   &Tcp,\r
-                  gTcpDriverBinding.DriverBindingHandle,\r
+                  gTcp4DriverBinding.DriverBindingHandle,\r
                   ChildHandle,\r
                   EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
                   );\r
@@ -866,7 +990,7 @@ TcpServiceBindingDestroyChild (
                     ChildHandle,\r
                     &gEfiTcp6ProtocolGuid,\r
                     &Tcp,\r
-                    gTcpDriverBinding.DriverBindingHandle,\r
+                    gTcp6DriverBinding.DriverBindingHandle,\r
                     ChildHandle,\r
                     EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
                     );\r
@@ -885,7 +1009,5 @@ TcpServiceBindingDestroyChild (
     SockDestroyChild (Sock);\r
   }\r
 \r
-  gBS->RestoreTPL (OldTpl);\r
-\r
   return Status;\r
 }\r