]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Driver.c
MdeModulePkg/Ip4Dxe: Fix the incorrect RemoveEntryList
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Ip4Dxe / Ip4Driver.c
index 73b4e246e0dc66b50f4bdb4502d6b786d525b87d..792db5c173f2ad47a5578e31407ce8279074d73e 100644 (file)
@@ -1,7 +1,9 @@
 /** @file\r
   The driver binding and service binding protocol for IP4 driver.\r
 \r
-Copyright (c) 2005 - 2013, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2005 - 2017, Intel Corporation. All rights reserved.<BR>\r
+(C) Copyright 2015 Hewlett-Packard Development Company, L.P.<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
 which accompanies this distribution.  The full text of the license may be found at\r
@@ -23,6 +25,30 @@ EFI_DRIVER_BINDING_PROTOCOL gIp4DriverBinding = {
   NULL\r
 };\r
 \r
+BOOLEAN  mIpSec2Installed = FALSE;\r
+\r
+/**\r
+   Callback function for IpSec2 Protocol install.\r
+\r
+   @param[in] Event           Event whose notification function is being invoked\r
+   @param[in] Context         Pointer to the notification function's context\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+IpSec2InstalledCallback (\r
+  IN EFI_EVENT  Event,\r
+  IN VOID       *Context\r
+  )\r
+{\r
+  //\r
+  // Close the event so it does not get called again.\r
+  //\r
+  gBS->CloseEvent (Event);\r
+\r
+  mIpSec2Installed = TRUE;\r
+}\r
+\r
 /**\r
   This is the declaration of an EFI image entry point. This entry point is\r
   the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including\r
@@ -45,6 +71,16 @@ Ip4DriverEntryPoint (
   IN EFI_SYSTEM_TABLE       *SystemTable\r
   )\r
 {\r
+  VOID            *Registration;\r
+\r
+  EfiCreateProtocolNotifyEvent (\r
+    &gEfiIpSec2ProtocolGuid,\r
+    TPL_CALLBACK,\r
+    IpSec2InstalledCallback,\r
+    NULL,\r
+    &Registration\r
+    );\r
+\r
   return EfiLibInstallDriverBindingComponentName2 (\r
            ImageHandle,\r
            SystemTable,\r
@@ -121,7 +157,7 @@ Ip4DriverBindingSupported (
   destroyed, it is marked as that in case the destroy failed and\r
   being called again later.\r
 \r
-  @param[in]  IpSb               The IP4 serviceing binding instance to clean up\r
+  @param[in]  IpSb               The IP4 service binding instance to clean up\r
 \r
   @retval EFI_SUCCESS            The resource used by the instance are cleaned up\r
   @retval other                  Failed to clean up some of the resources.\r
@@ -166,7 +202,7 @@ Ip4CreateService (
   // empty resources, so if any thing goes wrong when allocating\r
   // resources, Ip4CleanService can be called to clean it up.\r
   //\r
-  IpSb = AllocatePool (sizeof (IP4_SERVICE));\r
+  IpSb = AllocateZeroPool (sizeof (IP4_SERVICE));\r
 \r
   if (IpSb == NULL) {\r
     return EFI_OUT_OF_RESOURCES;\r
@@ -208,15 +244,17 @@ Ip4CreateService (
 \r
   ZeroMem (&IpSb->SnpMode, sizeof (EFI_SIMPLE_NETWORK_MODE));\r
 \r
-  IpSb->Timer                       = NULL;\r
-  IpSb->Ip4Config                   = NULL;\r
-  IpSb->DoneEvent                   = NULL;\r
-  IpSb->ReconfigEvent               = NULL;\r
-  IpSb->ActiveEvent                 = NULL;\r
+  IpSb->Timer = NULL;\r
+\r
+  IpSb->ReconfigEvent = NULL;\r
+\r
+  IpSb->Reconfig = FALSE;\r
+  \r
+  IpSb->MediaPresent = TRUE;\r
 \r
   //\r
   // Create various resources. First create the route table, timer\r
-  // event and MNP child. IGMP, interface's initialization depend\r
+  // event, ReconfigEvent and MNP child. IGMP, interface's initialization depend\r
   // on the MNP child.\r
   //\r
   IpSb->DefaultRouteTable = Ip4CreateRouteTable ();\r
@@ -238,6 +276,17 @@ Ip4CreateService (
     goto ON_ERROR;\r
   }\r
 \r
+  Status = gBS->CreateEvent (\r
+                  EVT_NOTIFY_SIGNAL,\r
+                  TPL_NOTIFY,\r
+                  Ip4AutoReconfigCallBack,\r
+                  IpSb,\r
+                  &IpSb->ReconfigEvent\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_ERROR;\r
+  }\r
+\r
   Status = NetLibCreateServiceChild (\r
              Controller,\r
              ImageHandle,\r
@@ -280,6 +329,13 @@ Ip4CreateService (
     goto ON_ERROR;\r
   }\r
 \r
+  IpSb->MacString = NULL;\r
+  Status = NetLibGetMacString (IpSb->Controller, IpSb->Image, &IpSb->MacString);\r
+  \r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_ERROR;\r
+  }\r
+\r
   IpSb->DefaultInterface = Ip4CreateInterface (IpSb->Mnp, Controller, ImageHandle);\r
 \r
   if (IpSb->DefaultInterface == NULL) {\r
@@ -289,6 +345,14 @@ Ip4CreateService (
 \r
   InsertHeadList (&IpSb->Interfaces, &IpSb->DefaultInterface->Link);\r
 \r
+  ZeroMem (&IpSb->Ip4Config2Instance, sizeof (IP4_CONFIG2_INSTANCE));\r
+  \r
+  Status = Ip4Config2InitInstance (&IpSb->Ip4Config2Instance);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_ERROR;\r
+  }\r
+\r
   IpSb->MaxPacketSize = IpSb->SnpMode.MaxPacketSize - sizeof (IP4_HEAD);\r
   if (NetLibGetVlanId (IpSb->Controller) != 0) {\r
     //\r
@@ -297,9 +361,8 @@ Ip4CreateService (
     IpSb->MaxPacketSize -= NET_VLAN_TAG_LEN;\r
   }\r
   IpSb->OldMaxPacketSize = IpSb->MaxPacketSize;\r
-  IpSb->MacString = NULL;\r
-\r
   *Service = IpSb;\r
+\r
   return EFI_SUCCESS;\r
 \r
 ON_ERROR:\r
@@ -317,7 +380,7 @@ ON_ERROR:
   destroyed, it is marked as that in case the destroy failed and\r
   being called again later.\r
 \r
-  @param[in]  IpSb               The IP4 serviceing binding instance to clean up\r
+  @param[in]  IpSb               The IP4 service binding instance to clean up\r
 \r
   @retval EFI_SUCCESS            The resource used by the instance are cleaned up\r
   @retval other                  Failed to clean up some of the resources.\r
@@ -330,6 +393,15 @@ Ip4CleanService (
 {\r
   EFI_STATUS                Status;\r
 \r
+  IpSb->State     = IP4_SERVICE_DESTROY;\r
+\r
+  if (IpSb->Timer != NULL) {\r
+    gBS->SetTimer (IpSb->Timer, TimerCancel, 0);\r
+    gBS->CloseEvent (IpSb->Timer);\r
+\r
+    IpSb->Timer = NULL;\r
+  }\r
+\r
   if (IpSb->DefaultInterface != NULL) {\r
     Status = Ip4FreeInterface (IpSb->DefaultInterface, NULL);\r
 \r
@@ -369,29 +441,20 @@ Ip4CleanService (
     IpSb->MnpChildHandle = NULL;\r
   }\r
 \r
-  if (IpSb->Timer != NULL) {\r
-    gBS->SetTimer (IpSb->Timer, TimerCancel, 0);\r
-    gBS->CloseEvent (IpSb->Timer);\r
+  if (IpSb->ReconfigEvent != NULL) {\r
+    gBS->CloseEvent (IpSb->ReconfigEvent);\r
 \r
-    IpSb->Timer = NULL;\r
+    IpSb->ReconfigEvent = NULL;\r
   }\r
 \r
-  if (IpSb->Ip4Config != NULL) {\r
-    IpSb->Ip4Config->Stop (IpSb->Ip4Config);\r
-\r
-    gBS->CloseProtocol (\r
-          IpSb->Controller,\r
-          &gEfiIp4ConfigProtocolGuid,\r
-          IpSb->Image,\r
-          IpSb->Controller\r
-          );\r
+  IpSb->Reconfig = FALSE;\r
 \r
-    gBS->CloseEvent (IpSb->DoneEvent);\r
-    gBS->CloseEvent (IpSb->ReconfigEvent);\r
-    IpSb->ActiveEvent = NULL;\r
-    IpSb->Ip4Config = NULL;\r
+  if (IpSb->MacString != NULL) {\r
+    FreePool (IpSb->MacString);\r
   }\r
 \r
+  Ip4Config2CleanInstance (&IpSb->Ip4Config2Instance);\r
+\r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -454,13 +517,20 @@ Ip4DestroyChildEntryInHandleBuffer (
 EFI_STATUS\r
 EFIAPI\r
 Ip4DriverBindingStart (\r
-  IN EFI_DRIVER_BINDING_PROTOCOL  * This,\r
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
   IN EFI_HANDLE                   ControllerHandle,\r
-  IN EFI_DEVICE_PATH_PROTOCOL     * RemainingDevicePath OPTIONAL\r
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL\r
   )\r
-{\r
-  IP4_SERVICE               *IpSb;\r
-  EFI_STATUS                Status;\r
+{ \r
+  EFI_STATUS                    Status;\r
+  IP4_SERVICE                   *IpSb;\r
+  EFI_IP4_CONFIG2_PROTOCOL      *Ip4Cfg2;\r
+  UINTN                         Index;\r
+  IP4_CONFIG2_DATA_ITEM         *DataItem;\r
+\r
+  IpSb     = NULL;\r
+  Ip4Cfg2  = NULL;\r
+  DataItem = NULL;\r
 \r
   //\r
   // Test for the Ip4 service binding protocol\r
@@ -477,14 +547,17 @@ Ip4DriverBindingStart (
   if (Status == EFI_SUCCESS) {\r
     return EFI_ALREADY_STARTED;\r
   }\r
-\r
+  \r
   Status = Ip4CreateService (ControllerHandle, This->DriverBindingHandle, &IpSb);\r
-\r
+  \r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
+  \r
   ASSERT (IpSb != NULL);\r
 \r
+  Ip4Cfg2  = &IpSb->Ip4Config2Instance.Ip4Config2;\r
+\r
   //\r
   // Install the Ip4ServiceBinding Protocol onto ControlerHandle\r
   //\r
@@ -492,6 +565,8 @@ Ip4DriverBindingStart (
                   &ControllerHandle,\r
                   &gEfiIp4ServiceBindingProtocolGuid,\r
                   &IpSb->ServiceBinding,\r
+                  &gEfiIp4Config2ProtocolGuid,\r
+                  Ip4Cfg2,\r
                   NULL\r
                   );\r
 \r
@@ -500,11 +575,44 @@ Ip4DriverBindingStart (
   }\r
 \r
   //\r
-  // ready to go: start the receiving and timer\r
+  // Read the config data from NV variable again. \r
+  // The default data can be changed by other drivers.\r
+  //\r
+  Status = Ip4Config2ReadConfigData (IpSb->MacString, &IpSb->Ip4Config2Instance);\r
+  if (EFI_ERROR (Status)) {\r
+    goto UNINSTALL_PROTOCOL;\r
+  }\r
+  \r
+  //\r
+  // Consume the installed EFI_IP4_CONFIG2_PROTOCOL to set the default data items. \r
+  //\r
+  for (Index = Ip4Config2DataTypePolicy; Index < Ip4Config2DataTypeMaximum; Index++) {\r
+    DataItem = &IpSb->Ip4Config2Instance.DataItem[Index];\r
+    if (DataItem->Data.Ptr != NULL) {\r
+      Status = Ip4Cfg2->SetData (\r
+                          Ip4Cfg2,\r
+                          Index,\r
+                          DataItem->DataSize,\r
+                          DataItem->Data.Ptr\r
+                          );\r
+      if (EFI_ERROR(Status)) {\r
+        goto UNINSTALL_PROTOCOL;\r
+      }\r
+      \r
+      if (Index == Ip4Config2DataTypePolicy && (*(DataItem->Data.Policy) == Ip4Config2PolicyDhcp)) {\r
+        break;\r
+      } \r
+    }\r
+  }\r
\r
+  //\r
+  // Ready to go: start the receiving and timer.\r
+  // Ip4Config2SetPolicy maybe call Ip4ReceiveFrame() to set the default interface's RecvRequest first after\r
+  // Ip4Config2 instance is initialized. So, EFI_ALREADY_STARTED is the allowed return status.\r
   //\r
   Status = Ip4ReceiveFrame (IpSb->DefaultInterface, NULL, Ip4AccpetFrame, IpSb);\r
 \r
-  if (EFI_ERROR (Status)) {\r
+  if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
     goto UNINSTALL_PROTOCOL;\r
   }\r
 \r
@@ -519,8 +627,6 @@ Ip4DriverBindingStart (
   //\r
   mIp4Id = (UINT16)NET_RANDOM (NetRandomInitSeed ());\r
 \r
-  Ip4SetVariableData (IpSb);\r
-\r
   return Status;\r
 \r
 UNINSTALL_PROTOCOL:\r
@@ -533,7 +639,6 @@ UNINSTALL_PROTOCOL:
 FREE_SERVICE:\r
   Ip4CleanService (IpSb);\r
   FreePool (IpSb);\r
-\r
   return Status;\r
 }\r
 \r
@@ -575,90 +680,23 @@ Ip4DriverBindingStop (
   IP4_INTERFACE                            *IpIf;\r
   IP4_ROUTE_TABLE                          *RouteTable;\r
 \r
-  //\r
-  // IP4 driver opens the MNP child, ARP children or the IP4_CONFIG protocol\r
-  // by driver. So the ControllerHandle may be the MNP child handle, ARP child\r
-  // handle, or the NIC (UNDI) handle because IP4_CONFIG protocol is installed\r
-  // in the NIC handle.\r
-  //\r
-  //\r
-  // First, check whether it is the IP4_CONFIG protocol being uninstalled.\r
-  // IP4_CONFIG protocol is installed on the NIC handle. It isn't necessary\r
-  // to clean up the default configuration if IP4_CONFIG is being stopped.\r
-  //\r
-  Status = gBS->OpenProtocol (\r
-                  ControllerHandle,\r
-                  &gEfiIp4ConfigProtocolGuid,\r
-                  NULL,\r
-                  This->DriverBindingHandle,\r
-                  ControllerHandle,\r
-                  EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
-                  );\r
-  if (Status == EFI_SUCCESS) {\r
-    //\r
-    // Retrieve the IP4 service binding protocol. If failed, it is\r
-    // likely that Ip4 ServiceBinding is uninstalled already. In this\r
-    // case, return immediately.\r
-    //\r
-    Status = gBS->OpenProtocol (\r
-                    ControllerHandle,\r
-                    &gEfiIp4ServiceBindingProtocolGuid,\r
-                    (VOID **) &ServiceBinding,\r
-                    This->DriverBindingHandle,\r
-                    ControllerHandle,\r
-                    EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
-                    );\r
-    if (EFI_ERROR (Status)) {\r
-      return EFI_DEVICE_ERROR;\r
-    }\r
-\r
-    IpSb = IP4_SERVICE_FROM_PROTOCOL (ServiceBinding);\r
-    if (IpSb->Ip4Config != NULL && (IpSb->State != IP4_SERVICE_DESTROY)) {\r
-\r
-      IpSb->Ip4Config->Stop (IpSb->Ip4Config);\r
-\r
-      Status = gBS->CloseProtocol (\r
-                      ControllerHandle,\r
-                      &gEfiIp4ConfigProtocolGuid,\r
-                      IpSb->Image,\r
-                      ControllerHandle\r
-                      );\r
-      if (EFI_ERROR (Status)) {\r
-        return Status;\r
-      }\r
-\r
-      //\r
-      // If the auto configure hasn't complete, mark it as not started.\r
-      //\r
-      if (IpSb->State == IP4_SERVICE_STARTED) {\r
-        IpSb->State = IP4_SERVICE_UNSTARTED;\r
-      }\r
-\r
-      IpSb->Ip4Config = NULL;\r
-      gBS->CloseEvent (IpSb->DoneEvent);\r
-      gBS->CloseEvent (IpSb->ReconfigEvent);\r
-    }\r
-\r
-    return EFI_SUCCESS;\r
-  }\r
+  BOOLEAN                                  IsDhcp4;\r
 \r
-  //\r
-  // Either MNP or ARP protocol is being uninstalled. The controller\r
-  // handle is either the MNP child or ARP child. But, the IP4's\r
-  // service binding is installed on the NIC handle. So, need to open\r
-  // the protocol info to find the NIC handle.\r
-  //\r
+  IsDhcp4   = FALSE;\r
+   \r
   NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiManagedNetworkProtocolGuid);\r
   if (NicHandle == NULL) {\r
     NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiArpProtocolGuid);\r
     if (NicHandle == NULL) {\r
-      return EFI_SUCCESS;\r
+      NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiDhcp4ProtocolGuid);\r
+      if (NicHandle != NULL) {\r
+        IsDhcp4 = TRUE;  \r
+      } else {\r
+        return EFI_SUCCESS;\r
+      }\r
     }\r
   }\r
-\r
-  //\r
-  // Retrieve the IP4 service binding protocol\r
-  //\r
+   \r
   Status = gBS->OpenProtocol (\r
                   NicHandle,\r
                   &gEfiIp4ServiceBindingProtocolGuid,\r
@@ -670,9 +708,14 @@ Ip4DriverBindingStop (
   if (EFI_ERROR (Status)) {\r
     return EFI_DEVICE_ERROR;\r
   }\r
+  \r
+  IpSb = IP4_SERVICE_FROM_PROTOCOL (ServiceBinding);\r
 \r
-  IpSb   = IP4_SERVICE_FROM_PROTOCOL (ServiceBinding);\r
-  if (NumberOfChildren != 0) {\r
+  if (IsDhcp4) {\r
+    Status = Ip4Config2DestroyDhcp4 (&IpSb->Ip4Config2Instance);\r
+    gBS->CloseEvent (IpSb->Ip4Config2Instance.Dhcp4Event);\r
+    IpSb->Ip4Config2Instance.Dhcp4Event = NULL;\r
+  } else if (NumberOfChildren != 0) {\r
     List = &IpSb->Children;\r
     Context.ServiceBinding    = ServiceBinding;\r
     Context.NumberOfChildren  = NumberOfChildren;\r
@@ -684,6 +727,7 @@ Ip4DriverBindingStop (
                NULL\r
                );\r
   } else if (IpSb->DefaultInterface->ArpHandle == ControllerHandle) {\r
+  \r
     //\r
     // The ARP protocol for the default interface is being uninstalled and all\r
     // its IP child handles should have been destroyed before. So, release the\r
@@ -708,19 +752,10 @@ Ip4DriverBindingStop (
     IpSb->DefaultRouteTable = RouteTable;\r
     Ip4ReceiveFrame (IpIf, NULL, Ip4AccpetFrame, IpSb);\r
 \r
-    if (IpSb->Ip4Config != NULL && IpSb->State != IP4_SERVICE_DESTROY) {\r
-      IpSb->Ip4Config->Stop (IpSb->Ip4Config);\r
-    }\r
     IpSb->State = IP4_SERVICE_UNSTARTED;\r
+\r
   } else if (IsListEmpty (&IpSb->Children)) {\r
     State           = IpSb->State;\r
-    IpSb->State     = IP4_SERVICE_DESTROY;\r
-\r
-    //\r
-    // Clear the variable data.\r
-    //\r
-    Ip4ClearVariableData (IpSb);\r
-\r
     //\r
     // OK, clean other resources then uninstall the service binding protocol.\r
     //\r
@@ -730,10 +765,13 @@ Ip4DriverBindingStop (
       goto ON_ERROR;\r
     }\r
 \r
-    gBS->UninstallProtocolInterface (\r
+    gBS->UninstallMultipleProtocolInterfaces (\r
            NicHandle,\r
            &gEfiIp4ServiceBindingProtocolGuid,\r
-           ServiceBinding\r
+           ServiceBinding,\r
+           &gEfiIp4Config2ProtocolGuid,\r
+           &IpSb->Ip4Config2Instance.Ip4Config2,\r
+           NULL\r
            );\r
     \r
     if (gIp4ControllerNameTable != NULL) {\r
@@ -762,7 +800,7 @@ ON_ERROR:
 \r
   @retval EFI_SUCCES            The protocol was added to ChildHandle.\r
   @retval EFI_INVALID_PARAMETER ChildHandle is NULL.\r
-  @retval EFI_OUT_OF_RESOURCES  There are not enough resources availabe to create\r
+  @retval EFI_OUT_OF_RESOURCES  There are not enough resources available to create\r
                                 the child\r
   @retval other                 The child handle was not created\r
 \r
@@ -884,7 +922,6 @@ Ip4ServiceBindingDestroyChild (
   IP4_PROTOCOL              *IpInstance;\r
   EFI_IP4_PROTOCOL          *Ip4;\r
   EFI_TPL                   OldTpl;\r
-  INTN                      State;\r
 \r
   if ((This == NULL) || (ChildHandle == NULL)) {\r
     return EFI_INVALID_PARAMETER;\r
@@ -922,13 +959,12 @@ Ip4ServiceBindingDestroyChild (
   // when UDP driver is being stopped, it will destroy all\r
   // the IP child it opens.\r
   //\r
-  if (IpInstance->State == IP4_STATE_DESTROY) {\r
+  if (IpInstance->InDestroy) {\r
     gBS->RestoreTPL (OldTpl);\r
     return EFI_SUCCESS;\r
   }\r
 \r
-  State             = IpInstance->State;\r
-  IpInstance->State = IP4_STATE_DESTROY;\r
+  IpInstance->InDestroy = TRUE;\r
 \r
   //\r
   // Close the Managed Network protocol.\r
@@ -971,13 +1007,11 @@ Ip4ServiceBindingDestroyChild (
                   );\r
   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
   if (EFI_ERROR (Status)) {\r
+    IpInstance->InDestroy = FALSE;\r
     goto ON_ERROR;\r
   }\r
 \r
   Status = Ip4CleanProtocol (IpInstance);\r
-\r
-  Ip4SetVariableData (IpSb);\r
-\r
   if (EFI_ERROR (Status)) {\r
     gBS->InstallMultipleProtocolInterfaces (\r
            &ChildHandle,\r
@@ -998,7 +1032,6 @@ Ip4ServiceBindingDestroyChild (
   return EFI_SUCCESS;\r
 \r
 ON_ERROR:\r
-  IpInstance->State = State;\r
   gBS->RestoreTPL (OldTpl);\r
 \r
   return Status;\r