]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Io.c
1. Fix a bug in PXE driver that the PXE boot do not restart if a new boot option...
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Dhcp4Dxe / Dhcp4Io.c
index 19b897ae0d20b4b9448b50948d6f18017978cd20..19ad101d5404d812998568727fdbb7175f43e72c 100644 (file)
@@ -1,7 +1,8 @@
 /** @file\r
-\r
-Copyright (c) 2006 - 2007, Intel Corporation\r
-All rights reserved. This program and the accompanying materials\r
+  EFI DHCP protocol implementation.\r
+  \r
+Copyright (c) 2006 - 2012, 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
 http://opensource.org/licenses/bsd-license.php\r
@@ -9,15 +10,6 @@ http://opensource.org/licenses/bsd-license.php
 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
 \r
-Module Name:\r
-\r
-  Dhcp4Io.c\r
-\r
-Abstract:\r
-\r
-  EFI DHCP protocol implementation\r
-\r
-\r
 **/\r
 \r
 \r
@@ -30,9 +22,10 @@ UINT32  mDhcp4DefaultTimeout[4] = { 4, 8, 16, 32 };
   Send an initial DISCOVER or REQUEST message according to the\r
   DHCP service's current state.\r
 \r
-  @param  DhcpSb                The DHCP service instance\r
+  @param[in]  DhcpSb                The DHCP service instance\r
 \r
   @retval EFI_SUCCESS           The request has been sent\r
+  @retval other                 Some error occurs when sending the request.\r
 \r
 **/\r
 EFI_STATUS\r
@@ -44,6 +37,11 @@ DhcpInitRequest (
 \r
   ASSERT ((DhcpSb->DhcpState == Dhcp4Init) || (DhcpSb->DhcpState == Dhcp4InitReboot));\r
 \r
+  //\r
+  // Clear initial time to make sure that elapsed-time is set to 0 for first Discover or REQUEST message.\r
+  //\r
+  DhcpSb->ActiveChild->ElaspedTime= 0;\r
+  \r
   if (DhcpSb->DhcpState == Dhcp4Init) {\r
     DhcpSetState (DhcpSb, Dhcp4Selecting, FALSE);\r
     Status = DhcpSendMessage (DhcpSb, NULL, NULL, DHCP_MSG_DISCOVER, NULL);\r
@@ -72,17 +70,16 @@ DhcpInitRequest (
   proper return value is selected to let the caller continue the\r
   normal process.\r
 \r
-  @param  DhcpSb                The DHCP service instance\r
-  @param  Event                 The event as defined in the spec\r
-  @param  Packet                The current packet trigger the event\r
-  @param  NewPacket             The user's return new packet\r
+  @param[in]  DhcpSb                The DHCP service instance\r
+  @param[in]  Event                 The event as defined in the spec\r
+  @param[in]  Packet                The current packet trigger the event\r
+  @param[out] NewPacket             The user's return new packet\r
 \r
   @retval EFI_NOT_READY         Direct the caller to continue collecting the offer.\r
   @retval EFI_SUCCESS           The user function returns success.\r
   @retval EFI_ABORTED           The user function ask it to abort.\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 DhcpCallUser (\r
   IN  DHCP_SERVICE          *DhcpSb,\r
@@ -141,9 +138,7 @@ DhcpCallUser (
   Notify the user about the operation result.\r
 \r
   @param  DhcpSb                DHCP service instance\r
-  @param  Which                 which notify function to signal\r
-\r
-  @return None\r
+  @param  Which                 Which notify function to signal\r
 \r
 **/\r
 VOID\r
@@ -159,14 +154,16 @@ DhcpNotifyUser (
   }\r
 \r
   if ((Child->CompletionEvent != NULL) &&\r
-     ((Which == DHCP_NOTIFY_COMPLETION) || (Which == DHCP_NOTIFY_ALL))) {\r
+      ((Which == DHCP_NOTIFY_COMPLETION) || (Which == DHCP_NOTIFY_ALL))\r
+      ) {\r
 \r
     gBS->SignalEvent (Child->CompletionEvent);\r
     Child->CompletionEvent = NULL;\r
   }\r
 \r
   if ((Child->RenewRebindEvent != NULL) &&\r
-     ((Which == DHCP_NOTIFY_RENEWREBIND) || (Which == DHCP_NOTIFY_ALL))) {\r
+      ((Which == DHCP_NOTIFY_RENEWREBIND) || (Which == DHCP_NOTIFY_ALL))\r
+      ) {\r
 \r
     gBS->SignalEvent (Child->RenewRebindEvent);\r
     Child->RenewRebindEvent = NULL;\r
@@ -192,9 +189,9 @@ DhcpNotifyUser (
 **/\r
 EFI_STATUS\r
 DhcpSetState (\r
-  IN DHCP_SERVICE           *DhcpSb,\r
-  IN INTN                   State,\r
-  IN BOOLEAN                CallUser\r
+  IN OUT DHCP_SERVICE           *DhcpSb,\r
+  IN     INTN                   State,\r
+  IN     BOOLEAN                CallUser\r
   )\r
 {\r
   EFI_STATUS                Status;\r
@@ -235,7 +232,7 @@ DhcpSetState (
 \r
   DhcpSb->CurRetry      = 0;\r
   DhcpSb->PacketToLive  = 0;\r
-\r
+  DhcpSb->LastTimeout   = 0;\r
   DhcpSb->DhcpState     = State;\r
   return EFI_SUCCESS;\r
 }\r
@@ -247,13 +244,10 @@ DhcpSetState (
 \r
   @param  DhcpSb                The DHCP service instance.\r
 \r
-  @return None\r
-\r
 **/\r
-STATIC\r
 VOID\r
 DhcpSetTransmitTimer (\r
-  IN DHCP_SERVICE           *DhcpSb\r
+  IN OUT DHCP_SERVICE           *DhcpSb\r
   )\r
 {\r
   UINT32                    *Times;\r
@@ -271,10 +265,9 @@ DhcpSetTransmitTimer (
   }\r
 \r
   DhcpSb->PacketToLive = Times[DhcpSb->CurRetry];\r
+  DhcpSb->LastTimeout  = DhcpSb->PacketToLive;\r
 \r
-  if (DhcpSb->DhcpState == Dhcp4Selecting) {\r
-    DhcpSb->WaitOffer = DhcpSb->PacketToLive;\r
-  }\r
+  return;\r
 }\r
 \r
 /**\r
@@ -285,15 +278,11 @@ DhcpSetTransmitTimer (
   @param  DhcpSb                The DHCP service instance\r
   @param  Para                  The DHCP parameter extracted from the server's\r
                                 response.\r
-\r
-  @return None\r
-\r
 **/\r
-STATIC\r
 VOID\r
 DhcpComputeLease (\r
-  IN DHCP_SERVICE           *DhcpSb,\r
-  IN DHCP_PARAMETER         *Para\r
+  IN OUT DHCP_SERVICE           *DhcpSb,\r
+  IN     DHCP_PARAMETER         *Para\r
   )\r
 {\r
   ASSERT (Para != NULL);\r
@@ -321,16 +310,17 @@ DhcpComputeLease (
   DHCP driver needs this port to unicast packet to the server\r
   such as DHCP release.\r
 \r
-  @param  UdpIo                 The UDP IO port to configure\r
-  @param  Context               The opaque parameter to the function.\r
+  @param[in]  UdpIo                 The UDP IO to configure\r
+  @param[in]  Context               Dhcp service instance.\r
 \r
   @retval EFI_SUCCESS           The UDP IO port is successfully configured.\r
   @retval Others                It failed to configure the port.\r
 \r
 **/\r
 EFI_STATUS\r
+EFIAPI\r
 DhcpConfigLeaseIoPort (\r
-  IN UDP_IO_PORT            *UdpIo,\r
+  IN UDP_IO                 *UdpIo,\r
   IN VOID                   *Context\r
   )\r
 {\r
@@ -365,7 +355,7 @@ DhcpConfigLeaseIoPort (
 \r
   ZeroMem (&UdpConfigData.RemoteAddress, sizeof (EFI_IPv4_ADDRESS));\r
 \r
-  Status = UdpIo->Udp->Configure (UdpIo->Udp, &UdpConfigData);\r
+  Status = UdpIo->Protocol.Udp4->Configure (UdpIo->Protocol.Udp4, &UdpConfigData);\r
 \r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
@@ -380,7 +370,7 @@ DhcpConfigLeaseIoPort (
     Ip = HTONL (DhcpSb->Para->Router);\r
     CopyMem (&Gateway, &Ip, sizeof (EFI_IPv4_ADDRESS));\r
 \r
-    UdpIo->Udp->Routes (UdpIo->Udp, FALSE, &Subnet, &Subnet, &Gateway);\r
+    UdpIo->Protocol.Udp4->Routes (UdpIo->Protocol.Udp4, FALSE, &Subnet, &Subnet, &Gateway);\r
   }\r
 \r
   return EFI_SUCCESS;\r
@@ -398,10 +388,9 @@ DhcpConfigLeaseIoPort (
   @retval EFI_SUCCESS           The lease is recorded.\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 DhcpLeaseAcquired (\r
-  IN DHCP_SERVICE           *DhcpSb\r
+  IN OUT DHCP_SERVICE           *DhcpSb\r
   )\r
 {\r
   INTN                      Class;\r
@@ -415,11 +404,11 @@ DhcpLeaseAcquired (
 \r
   if (DhcpSb->Netmask == 0) {\r
     Class           = NetGetIpClass (DhcpSb->ClientAddr);\r
-    DhcpSb->Netmask = mIp4AllMasks[Class << 3];\r
+    DhcpSb->Netmask = gIp4AllMasks[Class << 3];\r
   }\r
 \r
   if (DhcpSb->LeaseIoPort != NULL) {\r
-    UdpIoFreePort (DhcpSb->LeaseIoPort);\r
+    UdpIoFreeIo (DhcpSb->LeaseIoPort);\r
   }\r
 \r
   //\r
@@ -427,10 +416,11 @@ DhcpLeaseAcquired (
   // and transmit unicast packet with it as source address. Don't\r
   // start receive on this port, the queued packet will be timeout.\r
   //\r
-  DhcpSb->LeaseIoPort = UdpIoCreatePort (\r
+  DhcpSb->LeaseIoPort = UdpIoCreateIo (\r
                           DhcpSb->Controller,\r
                           DhcpSb->Image,\r
                           DhcpConfigLeaseIoPort,\r
+                          UDP_IO_UDP4_VERSION,\r
                           DhcpSb\r
                           );\r
 \r
@@ -451,8 +441,6 @@ DhcpLeaseAcquired (
 \r
   @param  DhcpSb                The DHCP instance service.\r
 \r
-  @return None\r
-\r
 **/\r
 VOID\r
 DhcpCleanLease (\r
@@ -462,20 +450,21 @@ DhcpCleanLease (
   DhcpSb->DhcpState   = Dhcp4Init;\r
   DhcpSb->Xid         = DhcpSb->Xid + 1;\r
   DhcpSb->ClientAddr  = 0;\r
+  DhcpSb->Netmask     = 0;\r
   DhcpSb->ServerAddr  = 0;\r
 \r
   if (DhcpSb->LastOffer != NULL) {\r
-    gBS->FreePool (DhcpSb->LastOffer);\r
+    FreePool (DhcpSb->LastOffer);\r
     DhcpSb->LastOffer = NULL;\r
   }\r
 \r
   if (DhcpSb->Selected != NULL) {\r
-    gBS->FreePool (DhcpSb->Selected);\r
+    FreePool (DhcpSb->Selected);\r
     DhcpSb->Selected = NULL;\r
   }\r
 \r
   if (DhcpSb->Para != NULL) {\r
-    gBS->FreePool (DhcpSb->Para);\r
+    FreePool (DhcpSb->Para);\r
     DhcpSb->Para = NULL;\r
   }\r
 \r
@@ -485,20 +474,25 @@ DhcpCleanLease (
   DhcpSb->ExtraRefresh  = FALSE;\r
 \r
   if (DhcpSb->LeaseIoPort != NULL) {\r
-    UdpIoFreePort (DhcpSb->LeaseIoPort);\r
+    UdpIoFreeIo (DhcpSb->LeaseIoPort);\r
     DhcpSb->LeaseIoPort = NULL;\r
   }\r
 \r
   if (DhcpSb->LastPacket != NULL) {\r
-    NetbufFree (DhcpSb->LastPacket);\r
+    FreePool (DhcpSb->LastPacket);\r
     DhcpSb->LastPacket = NULL;\r
   }\r
 \r
   DhcpSb->PacketToLive  = 0;\r
+  DhcpSb->LastTimeout   = 0;\r
   DhcpSb->CurRetry      = 0;\r
   DhcpSb->MaxRetries    = 0;\r
-  DhcpSb->WaitOffer     = 0;\r
   DhcpSb->LeaseLife     = 0;\r
+\r
+  //\r
+  // Clean active config data.\r
+  //\r
+  DhcpCleanConfigure (&DhcpSb->ActiveConfig);\r
 }\r
 \r
 \r
@@ -507,12 +501,11 @@ DhcpCleanLease (
   of BOOTP, the lease is recorded and user notified. If the offer is of\r
   DHCP, it will request the offer from the server.\r
 \r
-  @param  DhcpSb                The DHCP service instance.\r
+  @param[in]  DhcpSb                The DHCP service instance.\r
 \r
   @retval EFI_SUCCESS           One of the offer is selected.\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 DhcpChooseOffer (\r
   IN DHCP_SERVICE           *DhcpSb\r
@@ -525,11 +518,6 @@ DhcpChooseOffer (
 \r
   ASSERT (DhcpSb->LastOffer != NULL);\r
 \r
-  //\r
-  // Stop waiting more offers\r
-  //\r
-  DhcpSb->WaitOffer = 0;\r
-\r
   //\r
   // User will cache previous offers if he wants to select\r
   // from multiple offers. If user provides an invalid packet,\r
@@ -548,7 +536,7 @@ DhcpChooseOffer (
     TempPacket = (EFI_DHCP4_PACKET *) AllocatePool (NewPacket->Size);\r
     if (TempPacket != NULL) {\r
       CopyMem (TempPacket, NewPacket, NewPacket->Size);\r
-      gBS->FreePool (Selected);\r
+      FreePool (Selected);\r
       Selected = TempPacket;\r
     }\r
   }\r
@@ -593,13 +581,10 @@ DhcpChooseOffer (
   to this is: only call DhcpEndSession at the highest level, such as\r
   DhcpInput, DhcpOnTimerTick...At the other level, just return error.\r
 \r
-  @param  DhcpSb                The DHCP service instance\r
-  @param  Status                The result of the DHCP process.\r
-\r
-  @return None\r
+  @param[in]  DhcpSb                The DHCP service instance\r
+  @param[in]  Status                The result of the DHCP process.\r
 \r
 **/\r
-STATIC\r
 VOID\r
 DhcpEndSession (\r
   IN DHCP_SERVICE           *DhcpSb,\r
@@ -622,16 +607,15 @@ DhcpEndSession (
 /**\r
   Handle packets in DHCP select state.\r
 \r
-  @param  DhcpSb                The DHCP service instance\r
-  @param  Packet                The DHCP packet received\r
-  @param  Para                  The DHCP parameter extracted from the packet. That\r
-                                is, all the option value that we care.\r
+  @param[in]  DhcpSb                The DHCP service instance\r
+  @param[in]  Packet                The DHCP packet received\r
+  @param[in]  Para                  The DHCP parameter extracted from the packet. That\r
+                                    is, all the option value that we care.\r
 \r
   @retval EFI_SUCCESS           The packet is successfully processed.\r
   @retval Others                Some error occured.\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 DhcpHandleSelect (\r
   IN DHCP_SERVICE           *DhcpSb,\r
@@ -650,7 +634,8 @@ DhcpHandleSelect (
   // Don't return a error for these two case otherwise the session is ended.\r
   //\r
   if (!DHCP_IS_BOOTP (Para) &&\r
-     ((Para->DhcpType != DHCP_MSG_OFFER) || (Para->ServerId == 0))) {\r
+      ((Para->DhcpType != DHCP_MSG_OFFER) || (Para->ServerId == 0))\r
+      ) {\r
     goto ON_EXIT;\r
   }\r
 \r
@@ -664,7 +649,7 @@ DhcpHandleSelect (
 \r
   if (Status == EFI_SUCCESS) {\r
     if (DhcpSb->LastOffer != NULL) {\r
-      gBS->FreePool (DhcpSb->LastOffer);\r
+      FreePool (DhcpSb->LastOffer);\r
     }\r
 \r
     DhcpSb->LastOffer = Packet;\r
@@ -673,7 +658,7 @@ DhcpHandleSelect (
 \r
   } else if (Status == EFI_NOT_READY) {\r
     if (DhcpSb->LastOffer != NULL) {\r
-      gBS->FreePool (DhcpSb->LastOffer);\r
+      FreePool (DhcpSb->LastOffer);\r
     }\r
 \r
     DhcpSb->LastOffer = Packet;\r
@@ -689,7 +674,7 @@ DhcpHandleSelect (
   return EFI_SUCCESS;\r
 \r
 ON_EXIT:\r
-  gBS->FreePool (Packet);\r
+  FreePool (Packet);\r
   return Status;\r
 }\r
 \r
@@ -697,16 +682,15 @@ ON_EXIT:
 /**\r
   Handle packets in DHCP request state.\r
 \r
-  @param  DhcpSb                The DHCP service instance\r
-  @param  Packet                The DHCP packet received\r
-  @param  Para                  The DHCP parameter extracted from the packet. That\r
-                                is, all the option value that we care.\r
+  @param[in]  DhcpSb                The DHCP service instance\r
+  @param[in]  Packet                The DHCP packet received\r
+  @param[in]  Para                  The DHCP parameter extracted from the packet. That\r
+                                    is, all the option value that we care.\r
 \r
   @retval EFI_SUCCESS           The packet is successfully processed.\r
   @retval Others                Some error occured.\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 DhcpHandleRequest (\r
   IN DHCP_SERVICE           *DhcpSb,\r
@@ -728,8 +712,9 @@ DhcpHandleRequest (
   // Ignore the BOOTP message and DHCP messages other than DHCP ACK/NACK.\r
   //\r
   if (DHCP_IS_BOOTP (Para) ||\r
-     (Para->ServerId != DhcpSb->Para->ServerId) ||\r
-     ((Para->DhcpType != DHCP_MSG_ACK) && (Para->DhcpType != DHCP_MSG_NAK))) {\r
+      (Para->ServerId != DhcpSb->Para->ServerId) ||\r
+      ((Para->DhcpType != DHCP_MSG_ACK) && (Para->DhcpType != DHCP_MSG_NAK))\r
+      ) {\r
 \r
     Status = EFI_SUCCESS;\r
     goto ON_EXIT;\r
@@ -775,14 +760,14 @@ DhcpHandleRequest (
   DhcpSb->IoStatus = EFI_SUCCESS;\r
   DhcpNotifyUser (DhcpSb, DHCP_NOTIFY_COMPLETION);\r
 \r
-  gBS->FreePool (Packet);\r
+  FreePool (Packet);\r
   return EFI_SUCCESS;\r
 \r
 REJECT:\r
   DhcpSendMessage (DhcpSb, DhcpSb->Selected, DhcpSb->Para, DHCP_MSG_DECLINE, Message);\r
 \r
 ON_EXIT:\r
-  gBS->FreePool (Packet);\r
+  FreePool (Packet);\r
   return Status;\r
 }\r
 \r
@@ -790,16 +775,15 @@ ON_EXIT:
 /**\r
   Handle packets in DHCP renew/rebound state.\r
 \r
-  @param  DhcpSb                The DHCP service instance\r
-  @param  Packet                The DHCP packet received\r
-  @param  Para                  The DHCP parameter extracted from the packet. That\r
-                                is, all the option value that we care.\r
+  @param[in]  DhcpSb                The DHCP service instance\r
+  @param[in]  Packet                The DHCP packet received\r
+  @param[in]  Para                  The DHCP parameter extracted from the packet. That\r
+                                    is, all the option value that we care.\r
 \r
   @retval EFI_SUCCESS           The packet is successfully processed.\r
   @retval Others                Some error occured.\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 DhcpHandleRenewRebind (\r
   IN DHCP_SERVICE           *DhcpSb,\r
@@ -820,8 +804,9 @@ DhcpHandleRenewRebind (
   // Ignore the BOOTP message and DHCP messages other than DHCP ACK/NACK\r
   //\r
   if (DHCP_IS_BOOTP (Para) ||\r
-     (Para->ServerId != DhcpSb->Para->ServerId) ||\r
-     ((Para->DhcpType != DHCP_MSG_ACK) && (Para->DhcpType != DHCP_MSG_NAK))) {\r
+      (Para->ServerId != DhcpSb->Para->ServerId) ||\r
+      ((Para->DhcpType != DHCP_MSG_ACK) && (Para->DhcpType != DHCP_MSG_NAK))\r
+      ) {\r
 \r
     Status = EFI_SUCCESS;\r
     goto ON_EXIT;\r
@@ -858,7 +843,7 @@ DhcpHandleRenewRebind (
   DhcpSb->LeaseLife = 0;\r
   DhcpSetState (DhcpSb, Dhcp4Bound, TRUE);\r
 \r
-  if (DhcpSb->ExtraRefresh) {\r
+  if (DhcpSb->ExtraRefresh != 0) {\r
     DhcpSb->ExtraRefresh  = FALSE;\r
 \r
     DhcpSb->IoStatus      = EFI_SUCCESS;\r
@@ -866,7 +851,7 @@ DhcpHandleRenewRebind (
   }\r
 \r
 ON_EXIT:\r
-  gBS->FreePool (Packet);\r
+  FreePool (Packet);\r
   return Status;\r
 }\r
 \r
@@ -874,16 +859,15 @@ ON_EXIT:
 /**\r
   Handle packets in DHCP reboot state.\r
 \r
-  @param  DhcpSb                The DHCP service instance\r
-  @param  Packet                The DHCP packet received\r
-  @param  Para                  The DHCP parameter extracted from the packet. That\r
-                                is, all the option value that we care.\r
+  @param[in]  DhcpSb                The DHCP service instance\r
+  @param[in]  Packet                The DHCP packet received\r
+  @param[in]  Para                  The DHCP parameter extracted from the packet. That\r
+                                    is, all the option value that we care.\r
 \r
   @retval EFI_SUCCESS           The packet is successfully processed.\r
   @retval Others                Some error occured.\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 DhcpHandleReboot (\r
   IN DHCP_SERVICE           *DhcpSb,\r
@@ -900,7 +884,8 @@ DhcpHandleReboot (
   // Ignore the BOOTP message and DHCP messages other than DHCP ACK/NACK\r
   //\r
   if (DHCP_IS_BOOTP (Para) ||\r
-     ((Para->DhcpType != DHCP_MSG_ACK) && (Para->DhcpType != DHCP_MSG_NAK))) {\r
+      ((Para->DhcpType != DHCP_MSG_ACK) && (Para->DhcpType != DHCP_MSG_NAK))\r
+      ) {\r
 \r
     Status = EFI_SUCCESS;\r
     goto ON_EXIT;\r
@@ -935,18 +920,14 @@ DhcpHandleReboot (
   //\r
   // OK, get the parameter from server, record the lease\r
   //\r
-  DhcpSb->Para = AllocatePool (sizeof (DHCP_PARAMETER));\r
-\r
+  DhcpSb->Para = AllocateCopyPool (sizeof (DHCP_PARAMETER), Para);\r
   if (DhcpSb->Para == NULL) {\r
     Status = EFI_OUT_OF_RESOURCES;\r
     goto ON_EXIT;\r
   }\r
 \r
   DhcpSb->Selected  = Packet;\r
-  CopyMem (DhcpSb->Para, Para, sizeof (*DhcpSb->Para));\r
-\r
   Status            = DhcpLeaseAcquired (DhcpSb);\r
-\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
@@ -956,27 +937,26 @@ DhcpHandleReboot (
   return EFI_SUCCESS;\r
 \r
 ON_EXIT:\r
-  gBS->FreePool (Packet);\r
+  FreePool (Packet);\r
   return Status;\r
 }\r
 \r
 \r
 /**\r
-  Handle the received DHCP packets. This function drivers the DHCP\r
+  Handle the received DHCP packets. This function drives the DHCP\r
   state machine.\r
 \r
   @param  UdpPacket             The UDP packets received.\r
-  @param  Points                The local/remote UDP access points\r
+  @param  EndPoint              The local/remote UDP access point\r
   @param  IoStatus              The status of the UDP receive\r
   @param  Context               The opaque parameter to the function.\r
 \r
-  @return None\r
-\r
 **/\r
 VOID\r
+EFIAPI\r
 DhcpInput (\r
   NET_BUF                   *UdpPacket,\r
-  UDP_POINTS                *Points,\r
+  UDP_END_POINT             *EndPoint,\r
   EFI_STATUS                IoStatus,\r
   VOID                      *Context\r
   )\r
@@ -992,11 +972,11 @@ DhcpInput (
   DhcpSb  = (DHCP_SERVICE *) Context;\r
 \r
   //\r
-  // Don't restart receive if error occurs or DHCP is destoried.\r
+  // Don't restart receive if error occurs or DHCP is destroyed.\r
   //\r
   if (EFI_ERROR (IoStatus)) {\r
     return ;\r
-  } else if (DhcpSb->ServiceState == DHCP_DESTORY) {\r
+  } else if (DhcpSb->ServiceState == DHCP_DESTROY) {\r
     NetbufFree (UdpPacket);\r
     return ;\r
   }\r
@@ -1037,7 +1017,7 @@ DhcpInput (
   //\r
   if ((Head->OpCode != BOOTP_REPLY) ||\r
       (NTOHL (Head->Xid) != DhcpSb->Xid) ||\r
-      !NET_MAC_EQUAL (&DhcpSb->Mac, Head->ClientHwAddr, DhcpSb->HwLen)) {\r
+      (CompareMem (DhcpSb->ClientAddressSendOut, Head->ClientHwAddr, Head->HwAddrLen) != 0)) {\r
     goto RESTART;\r
   }\r
 \r
@@ -1078,7 +1058,7 @@ DhcpInput (
     //\r
     // Ignore the packet in INITREBOOT, INIT and BOUND states\r
     //\r
-    gBS->FreePool (Packet);\r
+    FreePool (Packet);\r
     Status = EFI_SUCCESS;\r
     break;\r
 \r
@@ -1093,13 +1073,14 @@ DhcpInput (
   }\r
 \r
   if (Para != NULL) {\r
-    gBS->FreePool (Para);\r
+    FreePool (Para);\r
   }\r
 \r
   Packet = NULL;\r
 \r
   if (EFI_ERROR (Status)) {\r
     NetbufFree (UdpPacket);\r
+    UdpIoRecvDatagram (DhcpSb->UdpIo, DhcpInput, DhcpSb, 0);\r
     DhcpEndSession (DhcpSb, Status);\r
     return ;\r
   }\r
@@ -1108,7 +1089,7 @@ RESTART:
   NetbufFree (UdpPacket);\r
 \r
   if (Packet != NULL) {\r
-    gBS->FreePool (Packet);\r
+    FreePool (Packet);\r
   }\r
 \r
   Status = UdpIoRecvDatagram (DhcpSb->UdpIo, DhcpInput, DhcpSb, 0);\r
@@ -1122,17 +1103,16 @@ RESTART:
 /**\r
   Release the packet.\r
 \r
-  @param  Arg                   The packet to release\r
-\r
-  @return None\r
+  @param[in]  Arg                   The packet to release\r
 \r
 **/\r
 VOID\r
+EFIAPI\r
 DhcpReleasePacket (\r
   IN VOID                   *Arg\r
   )\r
 {\r
-  gBS->FreePool (Arg);\r
+  FreePool (Arg);\r
 }\r
 \r
 \r
@@ -1140,17 +1120,16 @@ DhcpReleasePacket (
   Release the net buffer when packet is sent.\r
 \r
   @param  UdpPacket             The UDP packets received.\r
-  @param  Points                The local/remote UDP access points\r
+  @param  EndPoint              The local/remote UDP access point\r
   @param  IoStatus              The status of the UDP receive\r
   @param  Context               The opaque parameter to the function.\r
 \r
-  @return None\r
-\r
 **/\r
 VOID\r
+EFIAPI\r
 DhcpOnPacketSent (\r
   NET_BUF                   *Packet,\r
-  UDP_POINTS                *Points,\r
+  UDP_END_POINT             *EndPoint,\r
   EFI_STATUS                IoStatus,\r
   VOID                      *Context\r
   )\r
@@ -1166,16 +1145,17 @@ DhcpOnPacketSent (
   the state (as defined in Figure 5. of the same RFC) before sending\r
   a DHCP message. The table is adjusted accordingly.\r
 \r
-  @param  DhcpSb                The DHCP service instance\r
-  @param  Seed                  The seed packet which the new packet is based on\r
-  @param  Para                  The DHCP parameter of the Seed packet\r
-  @param  Type                  The message type to send\r
-  @param  Msg                   The human readable message to include in the packet\r
-                                sent.\r
+  @param[in]  DhcpSb                The DHCP service instance\r
+  @param[in]  Seed                  The seed packet which the new packet is based on\r
+  @param[in]  Para                  The DHCP parameter of the Seed packet\r
+  @param[in]  Type                  The message type to send\r
+  @param[in]  Msg                   The human readable message to include in the packet\r
+                                    sent.\r
 \r
   @retval EFI_OUT_OF_RESOURCES  Failed to allocate resources for the packet\r
   @retval EFI_ACCESS_DENIED     Failed to transmit the packet through UDP\r
   @retval EFI_SUCCESS           The message is sent\r
+  @retval other                 Other error occurs\r
 \r
 **/\r
 EFI_STATUS\r
@@ -1192,8 +1172,8 @@ DhcpSendMessage (
   EFI_DHCP4_PACKET          *NewPacket;\r
   EFI_DHCP4_HEADER          *Head;\r
   EFI_DHCP4_HEADER          *SeedHead;\r
-  UDP_IO_PORT               *UdpIo;\r
-  UDP_POINTS                EndPoint;\r
+  UDP_IO                    *UdpIo;\r
+  UDP_END_POINT             EndPoint;\r
   NET_BUF                   *Wrap;\r
   NET_FRAGMENT              Frag;\r
   EFI_STATUS                Status;\r
@@ -1243,6 +1223,17 @@ DhcpSendMessage (
   EFI_IP4 (Head->ClientAddr) = HTONL (DhcpSb->ClientAddr);\r
   CopyMem (Head->ClientHwAddr, DhcpSb->Mac.Addr, DhcpSb->HwLen);\r
 \r
+  if ((Type == DHCP_MSG_DECLINE) || (Type == DHCP_MSG_RELEASE)) {\r
+    Head->Seconds = 0;\r
+  } else if ((Type == DHCP_MSG_REQUEST) && (DhcpSb->DhcpState == Dhcp4Requesting)) {\r
+    //\r
+    // Use the same value as the original DHCPDISCOVER message.\r
+    //\r
+    Head->Seconds = DhcpSb->LastPacket->Dhcp4.Header.Seconds;\r
+  } else {\r
+    SetElapsedTime(&Head->Seconds, DhcpSb->ActiveChild);\r
+  }\r
+\r
   //\r
   // Append the DHCP message type\r
   //\r
@@ -1257,7 +1248,8 @@ DhcpSendMessage (
   //   3. DHCP request to confirm one lease.\r
   //\r
   if ((Type == DHCP_MSG_DECLINE) || (Type == DHCP_MSG_RELEASE) ||\r
-      ((Type == DHCP_MSG_REQUEST) && (DhcpSb->DhcpState == Dhcp4Requesting))) {\r
+      ((Type == DHCP_MSG_REQUEST) && (DhcpSb->DhcpState == Dhcp4Requesting))\r
+      ) {\r
 \r
     ASSERT ((Para != NULL) && (Para->ServerId != 0));\r
 \r
@@ -1352,15 +1344,25 @@ DhcpSendMessage (
   }\r
 \r
   if (EFI_ERROR (Status)) {\r
-    gBS->FreePool (Packet);\r
+    FreePool (Packet);\r
     return Status;\r
   }\r
 \r
   if (NewPacket != NULL) {\r
-    gBS->FreePool (Packet);\r
+    FreePool (Packet);\r
     Packet = NewPacket;\r
   }\r
 \r
+  //\r
+  // Save the Client Address will be sent out\r
+  //\r
+  CopyMem (\r
+    &DhcpSb->ClientAddressSendOut[0],\r
+    &Packet->Dhcp4.Header.ClientHwAddr[0],\r
+    Packet->Dhcp4.Header.HwAddrLen\r
+    );\r
+\r
+\r
   //\r
   // Wrap it into a netbuf then send it.\r
   //\r
@@ -1369,7 +1371,7 @@ DhcpSendMessage (
   Wrap      = NetbufFromExt (&Frag, 1, 0, 0, DhcpReleasePacket, Packet);\r
 \r
   if (Wrap == NULL) {\r
-    gBS->FreePool (Packet);\r
+    FreePool (Packet);\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
@@ -1377,34 +1379,42 @@ DhcpSendMessage (
   // Save it as the last sent packet for retransmission\r
   //\r
   if (DhcpSb->LastPacket != NULL) {\r
-    NetbufFree (DhcpSb->LastPacket);\r
+    FreePool (DhcpSb->LastPacket);\r
   }\r
 \r
-  NET_GET_REF (Wrap);\r
-  DhcpSb->LastPacket = Wrap;\r
+  DhcpSb->LastPacket = Packet;\r
   DhcpSetTransmitTimer (DhcpSb);\r
 \r
   //\r
   // Broadcast the message, unless we know the server address.\r
   // Use the lease UdpIo port to send the unicast packet.\r
   //\r
-  EndPoint.RemoteAddr = 0xffffffff;\r
-  EndPoint.LocalAddr  = 0;\r
-  EndPoint.RemotePort = DHCP_SERVER_PORT;\r
-  EndPoint.LocalPort  = DHCP_CLIENT_PORT;\r
-  UdpIo               = DhcpSb->UdpIo;\r
+  EndPoint.RemoteAddr.Addr[0] = 0xffffffff;\r
+  EndPoint.LocalAddr.Addr[0]  = 0;\r
+  EndPoint.RemotePort         = DHCP_SERVER_PORT;\r
+  EndPoint.LocalPort          = DHCP_CLIENT_PORT;\r
+  UdpIo                       = DhcpSb->UdpIo;\r
 \r
   if ((DhcpSb->DhcpState == Dhcp4Renewing) || (Type == DHCP_MSG_RELEASE)) {\r
-    EndPoint.RemoteAddr = DhcpSb->ServerAddr;\r
-    EndPoint.LocalAddr  = DhcpSb->ClientAddr;\r
-    UdpIo               = DhcpSb->LeaseIoPort;\r
+    EndPoint.RemoteAddr.Addr[0] = DhcpSb->ServerAddr;\r
+    EndPoint.LocalAddr.Addr[0]  = DhcpSb->ClientAddr;\r
+    UdpIo                       = DhcpSb->LeaseIoPort;\r
   }\r
 \r
   ASSERT (UdpIo != NULL);\r
-  Status = UdpIoSendDatagram (UdpIo, Wrap, &EndPoint, 0, DhcpOnPacketSent, DhcpSb);\r
+  NET_GET_REF (Wrap);\r
+  \r
+  Status = UdpIoSendDatagram (\r
+             UdpIo, \r
+             Wrap, \r
+             &EndPoint, \r
+             NULL, \r
+             DhcpOnPacketSent, \r
+             DhcpSb\r
+             );\r
 \r
   if (EFI_ERROR (Status)) {\r
-    NetbufFree (Wrap);\r
+    NET_PUT_REF (Wrap);\r
     return EFI_ACCESS_DENIED;\r
   }\r
 \r
@@ -1416,7 +1426,7 @@ DhcpSendMessage (
   Retransmit a saved packet. Only DISCOVER and REQUEST messages\r
   will be retransmitted.\r
 \r
-  @param  DhcpSb                The DHCP service instance\r
+  @param[in]  DhcpSb                The DHCP service instance\r
 \r
   @retval EFI_ACCESS_DENIED     Failed to transmit packet through UDP port\r
   @retval EFI_SUCCESS           The packet is retransmitted.\r
@@ -1427,41 +1437,61 @@ DhcpRetransmit (
   IN DHCP_SERVICE           *DhcpSb\r
   )\r
 {\r
-  UDP_IO_PORT               *UdpIo;\r
-  UDP_POINTS                EndPoint;\r
+  UDP_IO                    *UdpIo;\r
+  UDP_END_POINT             EndPoint;\r
+  NET_BUF                   *Wrap;\r
+  NET_FRAGMENT              Frag;\r
   EFI_STATUS                Status;\r
 \r
   ASSERT (DhcpSb->LastPacket != NULL);\r
 \r
+  //\r
+  // For REQUEST message in Dhcp4Requesting state, do not change the secs fields.\r
+  //\r
+  if (DhcpSb->DhcpState != Dhcp4Requesting) {\r
+    SetElapsedTime(&DhcpSb->LastPacket->Dhcp4.Header.Seconds, DhcpSb->ActiveChild);\r
+  }\r
+\r
+  //\r
+  // Wrap it into a netbuf then send it.\r
+  //\r
+  Frag.Bulk = (UINT8 *) &DhcpSb->LastPacket->Dhcp4.Header;\r
+  Frag.Len  = DhcpSb->LastPacket->Length;\r
+  Wrap      = NetbufFromExt (&Frag, 1, 0, 0, DhcpReleasePacket, DhcpSb->LastPacket);\r
+\r
+  if (Wrap == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  \r
   //\r
   // Broadcast the message, unless we know the server address.\r
   //\r
-  EndPoint.RemotePort = DHCP_SERVER_PORT;\r
-  EndPoint.LocalPort  = DHCP_CLIENT_PORT;\r
-  EndPoint.RemoteAddr = 0xffffffff;\r
-  EndPoint.LocalAddr  = 0;\r
-  UdpIo               = DhcpSb->UdpIo;\r
+  EndPoint.RemotePort         = DHCP_SERVER_PORT;\r
+  EndPoint.LocalPort          = DHCP_CLIENT_PORT;\r
+  EndPoint.RemoteAddr.Addr[0] = 0xffffffff;\r
+  EndPoint.LocalAddr.Addr[0]  = 0;\r
+  UdpIo                       = DhcpSb->UdpIo;\r
 \r
   if (DhcpSb->DhcpState == Dhcp4Renewing) {\r
-    EndPoint.RemoteAddr = DhcpSb->ServerAddr;\r
-    EndPoint.LocalAddr  = DhcpSb->ClientAddr;\r
-    UdpIo               = DhcpSb->LeaseIoPort;\r
+    EndPoint.RemoteAddr.Addr[0] = DhcpSb->ServerAddr;\r
+    EndPoint.LocalAddr.Addr[0]  = DhcpSb->ClientAddr;\r
+    UdpIo                       = DhcpSb->LeaseIoPort;\r
   }\r
 \r
   ASSERT (UdpIo != NULL);\r
 \r
-  NET_GET_REF (DhcpSb->LastPacket);\r
+  NET_GET_REF (Wrap);\r
   Status = UdpIoSendDatagram (\r
              UdpIo,\r
-             DhcpSb->LastPacket,\r
+             Wrap,\r
              &EndPoint,\r
-             0,\r
+             NULL,\r
              DhcpOnPacketSent,\r
              DhcpSb\r
              );\r
 \r
   if (EFI_ERROR (Status)) {\r
-    NET_PUT_REF (DhcpSb->LastPacket);\r
+    NET_PUT_REF (Wrap);\r
     return EFI_ACCESS_DENIED;\r
   }\r
 \r
@@ -1476,10 +1506,8 @@ DhcpRetransmit (
   and lease to determine the time to renew and rebind the lease.\r
   DhcpOnTimerTick will be called once every second.\r
 \r
-  @param  Event                 The timer event\r
-  @param  Context               The context, which is the DHCP service instance.\r
-\r
-  @return None\r
+  @param[in]  Event                 The timer event\r
+  @param[in]  Context               The context, which is the DHCP service instance.\r
 \r
 **/\r
 VOID\r
@@ -1492,26 +1520,15 @@ DhcpOnTimerTick (
   DHCP_SERVICE              *DhcpSb;\r
   DHCP_PROTOCOL             *Instance;\r
   EFI_STATUS                Status;\r
-  \r
+\r
   DhcpSb   = (DHCP_SERVICE *) Context;\r
   Instance = DhcpSb->ActiveChild;\r
 \r
   //\r
-  // Check the time to wait offer\r
+  // 0xffff is the maximum supported value for elapsed time according to RFC.\r
   //\r
-  if ((DhcpSb->WaitOffer > 0) && (--DhcpSb->WaitOffer == 0)) {\r
-    //\r
-    // OK, offer collection finished, select a offer\r
-    //\r
-    ASSERT (DhcpSb->DhcpState == Dhcp4Selecting);\r
-\r
-    if (DhcpSb->LastOffer == NULL) {\r
-      goto END_SESSION;\r
-    }\r
-\r
-    if (EFI_ERROR (DhcpChooseOffer (DhcpSb))) {\r
-      goto END_SESSION;\r
-    }\r
+  if (Instance != NULL && Instance->ElaspedTime < 0xffff) {\r
+    Instance->ElaspedTime++;\r
   }\r
   \r
   //\r
@@ -1519,6 +1536,23 @@ DhcpOnTimerTick (
   //\r
   if ((DhcpSb->PacketToLive > 0) && (--DhcpSb->PacketToLive == 0)) {\r
 \r
+    //\r
+    // Select offer at each timeout if any offer received.\r
+    //\r
+    if (DhcpSb->DhcpState == Dhcp4Selecting && DhcpSb->LastOffer != NULL) {\r
+\r
+      Status = DhcpChooseOffer (DhcpSb);\r
+\r
+      if (EFI_ERROR(Status)) {\r
+        if (DhcpSb->LastOffer != NULL) {\r
+          FreePool (DhcpSb->LastOffer);\r
+          DhcpSb->LastOffer = NULL;\r
+        }\r
+      } else {\r
+        goto ON_EXIT;\r
+      }\r
+    }\r
+    \r
     if (++DhcpSb->CurRetry < DhcpSb->MaxRetries) {\r
       //\r
       // Still has another try\r
@@ -1526,17 +1560,14 @@ DhcpOnTimerTick (
       DhcpRetransmit (DhcpSb);\r
       DhcpSetTransmitTimer (DhcpSb);\r
 \r
-    } else {\r
-      if (!DHCP_CONNECTED (DhcpSb->DhcpState)) {\r
-        goto END_SESSION;\r
-      }\r
+    } else if (DHCP_CONNECTED (DhcpSb->DhcpState)) {\r
 \r
       //\r
       // Retransmission failed, if the DHCP request is initiated by\r
       // user, adjust the current state according to the lease life.\r
       // Otherwise do nothing to wait the lease to timeout\r
       //\r
-      if (DhcpSb->ExtraRefresh) {\r
+      if (DhcpSb->ExtraRefresh != 0) {\r
         Status = EFI_SUCCESS;\r
 \r
         if (DhcpSb->LeaseLife < DhcpSb->T1) {\r
@@ -1556,6 +1587,8 @@ DhcpOnTimerTick (
         DhcpSb->IoStatus = EFI_TIMEOUT;\r
         DhcpNotifyUser (DhcpSb, DHCP_NOTIFY_RENEWREBIND);\r
       }\r
+    } else {\r
+      goto END_SESSION;\r
     }\r
   }\r
   \r
@@ -1570,7 +1603,7 @@ DhcpOnTimerTick (
     // Don't timeout the lease, only count the life if user is\r
     // requesting extra renew/rebind. Adjust the state after that.\r
     //\r
-    if (DhcpSb->ExtraRefresh) {\r
+    if (DhcpSb->ExtraRefresh != 0) {\r
       return ;\r
     }\r
 \r
@@ -1588,6 +1621,10 @@ DhcpOnTimerTick (
         goto END_SESSION;\r
       }\r
 \r
+      if (Instance != NULL) {\r
+        Instance->ElaspedTime= 0;\r
+      }      \r
+      \r
       Status = DhcpSendMessage (\r
                  DhcpSb,\r
                  DhcpSb->Selected,\r
@@ -1608,6 +1645,10 @@ DhcpOnTimerTick (
         goto END_SESSION;\r
       }\r
 \r
+      if (Instance != NULL) {\r
+        Instance->ElaspedTime= 0;\r
+      }    \r
+\r
       Status = DhcpSendMessage (\r
                  DhcpSb,\r
                  DhcpSb->Selected,\r
@@ -1622,9 +1663,7 @@ DhcpOnTimerTick (
     }\r
   }\r
 \r
-  //\r
-  //\r
-  //\r
+ON_EXIT:\r
   if ((Instance != NULL) && (Instance->Token != NULL)) {\r
     Instance->Timeout--;\r
     if (Instance->Timeout == 0) {\r