]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Impl.c
MdeModulePkg: Update IP4 driver to check for NULL pointer before using.
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Ip4Dxe / Ip4Impl.c
index cd01685a304e5a6a4dc5940db0872e4d80dae7e2..6a26143e307d3e4effe40bc1f190fb0833afd3d0 100644 (file)
@@ -1,6 +1,6 @@
 /** @file\r
 \r
-Copyright (c) 2005 - 2013, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>\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
@@ -530,305 +530,6 @@ Ip4ServiceConfigMnp (
 }\r
 \r
 \r
-/**\r
-  The event handle for IP4 auto configuration. If IP is asked\r
-  to reconfigure the default address. The original default\r
-  interface and route table are removed as the default. If there\r
-  is active IP children using the default address, the interface\r
-  will remain valid until all the children have freed their\r
-  references. If IP is signalled when auto configuration is done,\r
-  it will configure the default interface and default route table\r
-  with the configuration information retrieved by IP4_CONFIGURE.\r
-\r
-  @param[in]  Context                The IP4 service binding instance.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-Ip4AutoConfigCallBackDpc (\r
-  IN VOID                   *Context\r
-  )\r
-{\r
-  EFI_IP4_CONFIG_PROTOCOL   *Ip4Config;\r
-  EFI_IP4_IPCONFIG_DATA     *Data;\r
-  EFI_IP4_ROUTE_TABLE       *RouteEntry;\r
-  IP4_SERVICE               *IpSb;\r
-  IP4_ROUTE_TABLE           *RouteTable;\r
-  IP4_INTERFACE             *IpIf;\r
-  EFI_STATUS                Status;\r
-  UINTN                     Len;\r
-  UINT32                    Index;\r
-  IP4_ADDR                  StationAddress;\r
-  IP4_ADDR                  SubnetMask;\r
-  IP4_ADDR                  SubnetAddress;\r
-  IP4_ADDR                  GatewayAddress;\r
-  IP4_PROTOCOL              *Ip4Instance;\r
-  EFI_ARP_PROTOCOL          *Arp;\r
-  LIST_ENTRY                *Entry;\r
-\r
-  IpSb      = (IP4_SERVICE *) Context;\r
-  NET_CHECK_SIGNATURE (IpSb, IP4_SERVICE_SIGNATURE);\r
-\r
-  Ip4Config = IpSb->Ip4Config;\r
-\r
-  //\r
-  // IP is asked to do the reconfiguration. If the default interface\r
-  // has been configured, release the default interface and route\r
-  // table, then create a new one. If there are some IP children\r
-  // using it, the interface won't be physically freed until all the\r
-  // children have released their reference to it. Also remember to\r
-  // restart the receive on the default address. IP4 driver only receive\r
-  // frames on the default address, and when the default interface is\r
-  // freed, Ip4AcceptFrame won't be informed.\r
-  //\r
-  if (IpSb->ActiveEvent == IpSb->ReconfigEvent) {\r
-\r
-    if (IpSb->DefaultInterface->Configured) {\r
-      IpIf = Ip4CreateInterface (IpSb->Mnp, IpSb->Controller, IpSb->Image);\r
-\r
-      if (IpIf == NULL) {\r
-        return;\r
-      }\r
-\r
-      RouteTable = Ip4CreateRouteTable ();\r
-\r
-      if (RouteTable == NULL) {\r
-        Ip4FreeInterface (IpIf, NULL);\r
-        return;\r
-      }\r
-\r
-      Ip4CancelReceive (IpSb->DefaultInterface);\r
-      Ip4FreeInterface (IpSb->DefaultInterface, NULL);\r
-      Ip4FreeRouteTable (IpSb->DefaultRouteTable);\r
-\r
-      IpSb->DefaultInterface  = IpIf;\r
-      InsertHeadList (&IpSb->Interfaces, &IpIf->Link);\r
-\r
-      IpSb->DefaultRouteTable = RouteTable;\r
-      Ip4ReceiveFrame (IpIf, NULL, Ip4AccpetFrame, IpSb);\r
-    }\r
-\r
-    Ip4Config->Stop (Ip4Config);\r
-    Ip4Config->Start (Ip4Config, IpSb->DoneEvent, IpSb->ReconfigEvent);\r
-    return ;\r
-  }\r
-\r
-  //\r
-  // Get the configure data in two steps: get the length then the data.\r
-  //\r
-  Len = 0;\r
-\r
-  if (Ip4Config->GetData (Ip4Config, &Len, NULL) != EFI_BUFFER_TOO_SMALL) {\r
-    return ;\r
-  }\r
-\r
-  Data = AllocatePool (Len);\r
-\r
-  if (Data == NULL) {\r
-    return ;\r
-  }\r
-\r
-  Status = Ip4Config->GetData (Ip4Config, &Len, Data);\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  IpIf = IpSb->DefaultInterface;\r
-\r
-  //\r
-  // If the default address has been configured don't change it.\r
-  // This is unlikely to happen if EFI_IP4_CONFIG protocol has\r
-  // informed us to reconfigure each time it wants to change the\r
-  // configuration parameters.\r
-  //\r
-  if (IpIf->Configured) {\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  //\r
-  // Set the default interface's address, then add a directed\r
-  // route for it, that is, the route whose nexthop is zero.\r
-  //\r
-  StationAddress = EFI_NTOHL (Data->StationAddress);\r
-  SubnetMask = EFI_NTOHL (Data->SubnetMask);\r
-  Status = Ip4SetAddress (IpIf, StationAddress, SubnetMask);\r
-  if (EFI_ERROR (Status)) {\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  if (IpIf->Arp != NULL) {\r
-    //   \r
-    // A non-NULL IpIf->Arp here means a new ARP child is created when setting default address, \r
-    // but some IP children may have referenced the default interface before it is configured,\r
-    // these IP instances also consume this ARP protocol so they need to open it BY_CHILD_CONTROLLER.\r
-    //\r
-    Arp = NULL;\r
-    NET_LIST_FOR_EACH (Entry, &IpIf->IpInstances) {\r
-      Ip4Instance = NET_LIST_USER_STRUCT_S (Entry, IP4_PROTOCOL, AddrLink, IP4_PROTOCOL_SIGNATURE);\r
-      Status = gBS->OpenProtocol (\r
-                      IpIf->ArpHandle,\r
-                      &gEfiArpProtocolGuid,\r
-                      (VOID **) &Arp,\r
-                      gIp4DriverBinding.DriverBindingHandle,\r
-                      Ip4Instance->Handle,\r
-                      EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
-                      );\r
-      if (EFI_ERROR (Status)) {\r
-        goto ON_EXIT;\r
-      }\r
-    }\r
-  }\r
-\r
-  Ip4AddRoute (\r
-    IpSb->DefaultRouteTable,\r
-    StationAddress,\r
-    SubnetMask,\r
-    IP4_ALLZERO_ADDRESS\r
-    );\r
-\r
-  //\r
-  // Add routes returned by EFI_IP4_CONFIG protocol.\r
-  //\r
-  for (Index = 0; Index < Data->RouteTableSize; Index++) {\r
-    RouteEntry = &Data->RouteTable[Index];\r
-\r
-    SubnetAddress = EFI_NTOHL (RouteEntry->SubnetAddress);\r
-    SubnetMask = EFI_NTOHL (RouteEntry->SubnetMask);\r
-    GatewayAddress = EFI_NTOHL (RouteEntry->GatewayAddress);\r
-    Ip4AddRoute (IpSb->DefaultRouteTable, SubnetAddress, SubnetMask, GatewayAddress);\r
-  }\r
-\r
-  IpSb->State = IP4_SERVICE_CONFIGED;\r
-\r
-  Ip4SetVariableData (IpSb);\r
-\r
-ON_EXIT:\r
-  FreePool (Data);\r
-}\r
-\r
-/**\r
-  Request Ip4AutoConfigCallBackDpc as a DPC at TPL_CALLBACK.\r
-\r
-  @param Event     The event that is signalled.\r
-  @param Context   The IP4 service binding instance.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-Ip4AutoConfigCallBack (\r
-  IN EFI_EVENT              Event,\r
-  IN VOID                   *Context\r
-  )\r
-{\r
-  IP4_SERVICE  *IpSb;\r
-\r
-  IpSb              = (IP4_SERVICE *) Context;\r
-  IpSb->ActiveEvent = Event;\r
-\r
-  //\r
-  // Request Ip4AutoConfigCallBackDpc as a DPC at TPL_CALLBACK\r
-  //\r
-  QueueDpc (TPL_CALLBACK, Ip4AutoConfigCallBackDpc, Context);\r
-}\r
-\r
-\r
-/**\r
-  Start the auto configuration for this IP service instance.\r
-  It will locates the EFI_IP4_CONFIG_PROTOCOL, then start the\r
-  auto configuration.\r
-\r
-  @param[in]  IpSb               The IP4 service instance to configure\r
-\r
-  @retval EFI_SUCCESS            The auto configuration is successfull started\r
-  @retval Others                 Failed to start auto configuration.\r
-\r
-**/\r
-EFI_STATUS\r
-Ip4StartAutoConfig (\r
-  IN IP4_SERVICE            *IpSb\r
-  )\r
-{\r
-  EFI_IP4_CONFIG_PROTOCOL   *Ip4Config;\r
-  EFI_STATUS                Status;\r
-\r
-  if (IpSb->State > IP4_SERVICE_UNSTARTED) {\r
-    return EFI_SUCCESS;\r
-  }\r
-\r
-  //\r
-  // Create the DoneEvent and ReconfigEvent to call EFI_IP4_CONFIG\r
-  //\r
-  Status = gBS->CreateEvent (\r
-                  EVT_NOTIFY_SIGNAL,\r
-                  TPL_CALLBACK,\r
-                  Ip4AutoConfigCallBack,\r
-                  IpSb,\r
-                  &IpSb->DoneEvent\r
-                  );\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  Status = gBS->CreateEvent (\r
-                  EVT_NOTIFY_SIGNAL,\r
-                  TPL_NOTIFY,\r
-                  Ip4AutoConfigCallBack,\r
-                  IpSb,\r
-                  &IpSb->ReconfigEvent\r
-                  );\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    goto CLOSE_DONE_EVENT;\r
-  }\r
-\r
-  //\r
-  // Open the EFI_IP4_CONFIG protocol then start auto configure\r
-  //\r
-  Status = gBS->OpenProtocol (\r
-                  IpSb->Controller,\r
-                  &gEfiIp4ConfigProtocolGuid,\r
-                  (VOID **) &Ip4Config,\r
-                  IpSb->Image,\r
-                  IpSb->Controller,\r
-                  EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE\r
-                  );\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    Status = EFI_UNSUPPORTED;\r
-    goto CLOSE_RECONFIG_EVENT;\r
-  }\r
-\r
-  Status = Ip4Config->Start (Ip4Config, IpSb->DoneEvent, IpSb->ReconfigEvent);\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    gBS->CloseProtocol (\r
-           IpSb->Controller,\r
-           &gEfiIp4ConfigProtocolGuid,\r
-           IpSb->Image,\r
-           IpSb->Controller\r
-           );\r
-\r
-    goto CLOSE_RECONFIG_EVENT;\r
-  }\r
-\r
-  IpSb->Ip4Config = Ip4Config;\r
-  IpSb->State     = IP4_SERVICE_STARTED;\r
-  return Status;\r
-\r
-CLOSE_RECONFIG_EVENT:\r
-  gBS->CloseEvent (IpSb->ReconfigEvent);\r
-  IpSb->ReconfigEvent = NULL;\r
-\r
-CLOSE_DONE_EVENT:\r
-  gBS->CloseEvent (IpSb->DoneEvent);\r
-  IpSb->DoneEvent = NULL;\r
-\r
-  return Status;\r
-}\r
-\r
-\r
 /**\r
   Intiialize the IP4_PROTOCOL structure to the unconfigured states.\r
 \r
@@ -849,6 +550,7 @@ Ip4InitProtocol (
   IpInstance->Signature = IP4_PROTOCOL_SIGNATURE;\r
   CopyMem (&IpInstance->Ip4Proto, &mEfiIp4ProtocolTemplete, sizeof (IpInstance->Ip4Proto));\r
   IpInstance->State     = IP4_STATE_UNCONFIGED;\r
+  IpInstance->InDestroy   = FALSE;\r
   IpInstance->Service   = IpSb;\r
 \r
   InitializeListHead (&IpInstance->Link);\r
@@ -894,9 +596,13 @@ Ip4ConfigProtocol (
   IP4_ADDR                  Ip;\r
   IP4_ADDR                  Netmask;\r
   EFI_ARP_PROTOCOL          *Arp;\r
+  EFI_IP4_CONFIG2_PROTOCOL  *Ip4Config2;\r
+  EFI_IP4_CONFIG2_POLICY    Policy;\r
 \r
   IpSb = IpInstance->Service;\r
 \r
+  Ip4Config2  = NULL;\r
+\r
   //\r
   // User is changing packet filters. It must be stopped\r
   // before the station address can be changed.\r
@@ -972,14 +678,26 @@ Ip4ConfigProtocol (
 \r
   } else {\r
     //\r
-    // Use the default address. If the default configuration hasn't\r
-    // been started, start it.\r
+    // Use the default address. Check the state.\r
     //\r
     if (IpSb->State == IP4_SERVICE_UNSTARTED) {\r
-      Status = Ip4StartAutoConfig (IpSb);\r
-\r
-      if (EFI_ERROR (Status)) {\r
-        goto ON_ERROR;\r
+      //\r
+      // Trigger the EFI_IP4_CONFIG2_PROTOCOL to retrieve the \r
+      // default IPv4 address if it is not available yet.\r
+      //\r
+      Policy = IpSb->Ip4Config2Instance.Policy;\r
+      if (Policy != Ip4Config2PolicyDhcp) {\r
+        Ip4Config2 = &IpSb->Ip4Config2Instance.Ip4Config2;\r
+        Policy = Ip4Config2PolicyDhcp;\r
+        Status= Ip4Config2->SetData (\r
+                              Ip4Config2,\r
+                              Ip4Config2DataTypePolicy,\r
+                              sizeof (EFI_IP4_CONFIG2_POLICY),\r
+                              &Policy\r
+                              );\r
+        if (EFI_ERROR (Status)) {\r
+          goto ON_ERROR;\r
+        }\r
       }\r
     }\r
 \r
@@ -1009,6 +727,7 @@ Ip4ConfigProtocol (
                     EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
                     );\r
     if (EFI_ERROR (Status)) {\r
+      Ip4FreeInterface (IpIf, IpInstance);\r
       goto ON_ERROR;\r
     }\r
   }\r
@@ -1040,8 +759,8 @@ ON_ERROR:
 \r
   @param[in]  IpInstance         The IP4 child to clean up.\r
 \r
-  @retval EFI_SUCCESS            The IP4 child is cleaned up\r
-  @retval EFI_DEVICE_ERROR       Some resources failed to be released\r
+  @retval EFI_SUCCESS            The IP4 child is cleaned up.\r
+  @retval EFI_DEVICE_ERROR       Some resources failed to be released.\r
 \r
 **/\r
 EFI_STATUS\r
@@ -1109,66 +828,6 @@ Ip4CleanProtocol (
 }\r
 \r
 \r
-/**\r
-  Validate that Ip/Netmask pair is OK to be used as station\r
-  address. Only continuous netmasks are supported. and check\r
-  that StationAddress is a unicast address on the newtwork.\r
-\r
-  @param[in]  Ip                 The IP address to validate\r
-  @param[in]  Netmask            The netmaks of the IP\r
-\r
-  @retval TRUE                   The Ip/Netmask pair is valid\r
-  @retval FALSE                  The Ip/Netmask pair is invalid\r
-\r
-**/\r
-BOOLEAN\r
-Ip4StationAddressValid (\r
-  IN IP4_ADDR               Ip,\r
-  IN IP4_ADDR               Netmask\r
-  )\r
-{\r
-  IP4_ADDR                  NetBrdcastMask;\r
-  INTN                      Len;\r
-  INTN                      Type;\r
-\r
-  //\r
-  // Only support the station address with 0.0.0.0/0 to enable DHCP client.\r
-  //\r
-  if (Netmask == IP4_ALLZERO_ADDRESS) {\r
-    return (BOOLEAN) (Ip == IP4_ALLZERO_ADDRESS);\r
-  }\r
-\r
-  //\r
-  // Only support the continuous net masks\r
-  //\r
-  if ((Len = NetGetMaskLength (Netmask)) == IP4_MASK_NUM) {\r
-    return FALSE;\r
-  }\r
-\r
-  //\r
-  // Station address can't be class D or class E address\r
-  //\r
-  if ((Type = NetGetIpClass (Ip)) > IP4_ADDR_CLASSC) {\r
-    return FALSE;\r
-  }\r
-\r
-  //\r
-  // Station address can't be subnet broadcast/net broadcast address\r
-  //\r
-  if ((Ip == (Ip & Netmask)) || (Ip == (Ip | ~Netmask))) {\r
-    return FALSE;\r
-  }\r
-\r
-  NetBrdcastMask = gIp4AllMasks[MIN (Len, Type << 3)];\r
-\r
-  if (Ip == (Ip | ~NetBrdcastMask)) {\r
-    return FALSE;\r
-  }\r
-\r
-  return TRUE;\r
-}\r
-\r
-\r
 /**\r
   Assigns an IPv4 address and subnet mask to this EFI IPv4 Protocol driver instance.\r
 \r
@@ -1296,8 +955,7 @@ EfiIp4Configure (
     Status = Ip4CleanProtocol (IpInstance);\r
 \r
     //\r
-    // Don't change the state if it is DESTROY, consider the following\r
-    // valid sequence: Mnp is unloaded-->Ip Stopped-->Udp Stopped,\r
+    // Consider the following valid sequence: Mnp is unloaded-->Ip Stopped-->Udp Stopped,\r
     // Configure (ThisIp, NULL). If the state is changed to UNCONFIGED,\r
     // the unload fails miserably.\r
     //\r
@@ -1312,11 +970,6 @@ EfiIp4Configure (
   //\r
   Ip4ServiceConfigMnp (IpInstance->Service, FALSE);\r
 \r
-  //\r
-  // Update the variable data.\r
-  //\r
-  Ip4SetVariableData (IpInstance->Service);\r
-\r
 ON_EXIT:\r
   gBS->RestoreTPL (OldTpl);\r
   return Status;\r
@@ -1329,12 +982,12 @@ ON_EXIT:
   should make sure that the parameters is valid.\r
 \r
   @param[in]  IpInstance             The IP4 child to change the setting.\r
-  @param[in]  JoinFlag               TRUE to join the group, otherwise leave it\r
-  @param[in]  GroupAddress           The target group address\r
+  @param[in]  JoinFlag               TRUE to join the group, otherwise leave it.\r
+  @param[in]  GroupAddress           The target group address.\r
 \r
-  @retval EFI_ALREADY_STARTED    Want to join the group, but already a member of it\r
+  @retval EFI_ALREADY_STARTED    Want to join the group, but already a member of it.\r
   @retval EFI_OUT_OF_RESOURCES   Failed to allocate some resources.\r
-  @retval EFI_DEVICE_ERROR       Failed to set the group configuraton\r
+  @retval EFI_DEVICE_ERROR       Failed to set the group configuraton.\r
   @retval EFI_SUCCESS            Successfully updated the group setting.\r
   @retval EFI_NOT_FOUND          Try to leave the group which it isn't a member.\r
 \r
@@ -1395,8 +1048,8 @@ Ip4Groups (
   // is decreamented each time an address is removed..\r
   //\r
   for (Index = IpInstance->GroupCount; Index > 0 ; Index--) {\r
+    ASSERT (IpInstance->Groups != NULL);\r
     Group = IpInstance->Groups[Index - 1];\r
-\r
     if ((GroupAddress == NULL) || EFI_IP4_EQUAL (&Group, GroupAddress)) {\r
       if (EFI_ERROR (Ip4LeaveGroup (IpInstance, NTOHL (Group)))) {\r
         return EFI_DEVICE_ERROR;\r
@@ -1631,10 +1284,10 @@ ON_EXIT:
 \r
   @param[in]  Map                    The container of either user's transmit or receive\r
                                      token.\r
-  @param[in]  Item                   Current item to check against\r
+  @param[in]  Item                   Current item to check against.\r
   @param[in]  Context                The Token to check againist.\r
 \r
-  @retval EFI_ACCESS_DENIED      The token or event has already been enqueued in IP\r
+  @retval EFI_ACCESS_DENIED      The token or event has already been enqueued in IP.\r
   @retval EFI_SUCCESS            The current item isn't the same token/event as the\r
                                  context.\r
 \r
@@ -1807,7 +1460,7 @@ Ip4TxTokenValid (
   are bound together. Check the comments in Ip4Output for information\r
   about IP fragmentation.\r
 \r
-  @param[in]  Context                The token's wrap\r
+  @param[in]  Context                The token's wrap.\r
 \r
 **/\r
 VOID\r
@@ -1855,9 +1508,9 @@ Ip4FreeTxToken (
   The callback function to Ip4Output to update the transmit status.\r
 \r
   @param  Ip4Instance            The Ip4Instance that request the transmit.\r
-  @param  Packet                 The user's transmit request\r
-  @param  IoStatus               The result of the transmission\r
-  @param  Flag                   Not used during transmission\r
+  @param  Packet                 The user's transmit request.\r
+  @param  IoStatus               The result of the transmission.\r
+  @param  Flag                   Not used during transmission.\r
   @param  Context                The token's wrap.\r
 \r
 **/\r
@@ -1918,7 +1571,7 @@ Ip4OnPacketSent (
   @retval  EFI_BAD_BUFFER_SIZE   The length of the IPv4 header + option length + total data length is\r
                                  greater than MTU (or greater than the maximum packet size if\r
                                  Token.Packet.TxData.OverrideData.\r
-                                 DoNotFragment is TRUE.)\r
+                                 DoNotFragment is TRUE).\r
 \r
 **/\r
 EFI_STATUS\r
@@ -2269,9 +1922,9 @@ ON_EXIT:
   Because Ip4CancelPacket and other functions are all called in\r
   line, so, after Ip4CancelPacket returns, the Item has been freed.\r
 \r
-  @param[in]  Map                    The IP4 child's transmit queue\r
-  @param[in]  Item                   The current transmitted packet to test.\r
-  @param[in]  Context                The user's token to cancel.\r
+  @param[in]  Map                The IP4 child's transmit queue.\r
+  @param[in]  Item               The current transmitted packet to test.\r
+  @param[in]  Context            The user's token to cancel.\r
 \r
   @retval EFI_SUCCESS            Continue to check the next Item.\r
   @retval EFI_ABORTED            The user's Token (Token != NULL) is cancelled.\r
@@ -2323,9 +1976,9 @@ Ip4CancelTxTokens (
   Cancel the receive request. This is quiet simple, because\r
   it is only enqueued in our local receive map.\r
 \r
-  @param[in]  Map                    The IP4 child's receive queue\r
-  @param[in]  Item                   Current receive request to cancel.\r
-  @param[in]  Context                The user's token to cancel\r
+  @param[in]  Map                The IP4 child's receive queue.\r
+  @param[in]  Item               Current receive request to cancel.\r
+  @param[in]  Context            The user's token to cancel.\r
 \r
   @retval EFI_SUCCESS            Continue to check the next receive request on the\r
                                  queue.\r
@@ -2368,13 +2021,13 @@ Ip4CancelRxTokens (
 /**\r
   Cancel the user's receive/transmit request.\r
 \r
-  @param[in]  IpInstance         The IP4 child\r
+  @param[in]  IpInstance         The IP4 child.\r
   @param[in]  Token              The token to cancel. If NULL, all token will be\r
                                  cancelled.\r
 \r
-  @retval EFI_SUCCESS            The token is cancelled\r
+  @retval EFI_SUCCESS            The token is cancelled.\r
   @retval EFI_NOT_FOUND          The token isn't found on either the\r
-                                 transmit/receive queue\r
+                                 transmit/receive queue.\r
   @retval EFI_DEVICE_ERROR       Not all token is cancelled when Token is NULL.\r
 \r
 **/\r
@@ -2570,10 +2223,10 @@ EfiIp4Poll (
   packets.\r
 \r
   @param[in]  Map                    The IP4 child's transmit map.\r
-  @param[in]  Item                   Current transmitted packet\r
+  @param[in]  Item                   Current transmitted packet.\r
   @param[in]  Context                Not used.\r
 \r
-  @retval EFI_SUCCESS            Always returns EFI_SUCCESS\r
+  @retval EFI_SUCCESS            Always returns EFI_SUCCESS.\r
 \r
 **/\r
 EFI_STATUS\r
@@ -2596,12 +2249,10 @@ Ip4SentPacketTicking (
   return EFI_SUCCESS;\r
 }\r
 \r
-\r
 /**\r
-  The heart beat timer of IP4 service instance. It times out\r
-  all of its IP4 children's received-but-not-delivered and\r
-  transmitted-but-not-recycle packets, and provides time input\r
-  for its IGMP protocol.\r
+  This heart beat timer of IP4 service instance times out all of its IP4 children's \r
+  received-but-not-delivered and transmitted-but-not-recycle packets, and provides \r
+  time input for its IGMP protocol.\r
 \r
   @param[in]  Event                  The IP4 service instance's heart beat timer.\r
   @param[in]  Context                The IP4 service instance.\r
@@ -2618,7 +2269,64 @@ Ip4TimerTicking (
 \r
   IpSb = (IP4_SERVICE *) Context;\r
   NET_CHECK_SIGNATURE (IpSb, IP4_SERVICE_SIGNATURE);\r
-\r
+  \r
   Ip4PacketTimerTicking (IpSb);\r
   Ip4IgmpTicking (IpSb);\r
 }\r
+\r
+/**\r
+  This dedicated timer is used to poll underlying network media status. In case \r
+  of cable swap or wireless network switch, a new round auto configuration will \r
+  be initiated. The timer will signal the IP4 to run DHCP configuration again. \r
+  IP4 driver will free old IP address related resource, such as route table and \r
+  Interface, then initiate a DHCP process to acquire new IP, eventually create \r
+  route table for new IP address.\r
+\r
+  @param[in]  Event                  The IP4 service instance's heart beat timer.\r
+  @param[in]  Context                The IP4 service instance.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+Ip4TimerReconfigChecking (\r
+  IN EFI_EVENT              Event,\r
+  IN VOID                   *Context\r
+  )\r
+{\r
+  IP4_SERVICE               *IpSb;\r
+  BOOLEAN                   OldMediaPresent;\r
+  EFI_STATUS                Status;\r
+  EFI_SIMPLE_NETWORK_MODE   SnpModeData;\r
+\r
+  IpSb = (IP4_SERVICE *) Context;\r
+  NET_CHECK_SIGNATURE (IpSb, IP4_SERVICE_SIGNATURE);\r
+  \r
+  OldMediaPresent = IpSb->MediaPresent;\r
+\r
+  //\r
+  // Get fresh mode data from MNP, since underlying media status may change. \r
+  // Here, it needs to mention that the MediaPresent can also be checked even if \r
+  // EFI_NOT_STARTED returned while this MNP child driver instance isn't configured.\r
+  //\r
+  Status = IpSb->Mnp->GetModeData (IpSb->Mnp, NULL, &SnpModeData);\r
+  if (EFI_ERROR (Status) && (Status != EFI_NOT_STARTED)) {\r
+    return;\r
+  }\r
+\r
+  IpSb->MediaPresent = SnpModeData.MediaPresent;\r
+  //\r
+  // Media transimit Unpresent to Present means new link movement is detected.\r
+  //\r
+  if (!OldMediaPresent && IpSb->MediaPresent && (IpSb->Ip4Config2Instance.Policy == Ip4Config2PolicyDhcp)) {\r
+    //\r
+    // Signal the IP4 to run the dhcp configuration again. IP4 driver will free\r
+    // old IP address related resource, such as route table and Interface, then \r
+    // initiate a DHCP round to acquire new IP, eventually \r
+    // create route table for new IP address.\r
+    //\r
+    if (IpSb->ReconfigEvent != NULL) {\r
+      Status = gBS->SignalEvent (IpSb->ReconfigEvent);\r
+      DispatchDpc ();\r
+    }\r
+  }\r
+}\r