]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Impl.c
BaseTools:Change the path of the file that Binary Cache
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Dhcp4Dxe / Dhcp4Impl.c
index 3595e784a0205b9c290d994915991848742e763b..0b35bdf4df95b51339dcf63c0c1b032cb450420d 100644 (file)
 /** @file\r
+  This file implement the EFI_DHCP4_PROTOCOL interface.\r
+\r
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
-Copyright (c) 2006 - 2007, Intel Corporation\r
-All rights reserved. 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
+**/\r
 \r
-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
+#include "Dhcp4Impl.h"\r
 \r
-  Dhcp4Impl.c\r
+/**\r
+  Returns the current operating mode and cached data packet for the EFI DHCPv4 Protocol driver.\r
 \r
-Abstract:\r
+  The GetModeData() function returns the current operating mode and cached data\r
+  packet for the EFI DHCPv4 Protocol driver.\r
 \r
-  This file implement the EFI_DHCP4_PROTOCOL interface.\r
+  @param[in]  This          Pointer to the EFI_DHCP4_PROTOCOL instance.\r
+  @param[out] Dhcp4ModeData Pointer to storage for the EFI_DHCP4_MODE_DATA structure.\r
 \r
+  @retval EFI_SUCCESS           The mode data was returned.\r
+  @retval EFI_INVALID_PARAMETER This is NULL.\r
 \r
 **/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiDhcp4GetModeData (\r
+  IN  EFI_DHCP4_PROTOCOL    *This,\r
+  OUT EFI_DHCP4_MODE_DATA   *Dhcp4ModeData\r
+  );\r
 \r
+/**\r
+  Initializes, changes, or resets the operational settings for the EFI DHCPv4 Protocol driver.\r
+\r
+  The Configure() function is used to initialize, change, or reset the operational\r
+  settings of the EFI DHCPv4 Protocol driver for the communication device on which\r
+  the EFI DHCPv4 Service Binding Protocol is installed. This function can be\r
+  successfully called only if both of the following are true:\r
+  * This instance of the EFI DHCPv4 Protocol driver is in the Dhcp4Stopped, Dhcp4Init,\r
+    Dhcp4InitReboot, or Dhcp4Bound states.\r
+  * No other EFI DHCPv4 Protocol driver instance that is controlled by this EFI\r
+    DHCPv4 Service Binding Protocol driver instance has configured this EFI DHCPv4\r
+    Protocol driver.\r
+  When this driver is in the Dhcp4Stopped state, it can transfer into one of the\r
+  following two possible initial states:\r
+  * Dhcp4Init\r
+  * Dhcp4InitReboot\r
+  The driver can transfer into these states by calling Configure() with a non-NULL\r
+  Dhcp4CfgData. The driver will transfer into the appropriate state based on the\r
+  supplied client network address in the ClientAddress parameter and DHCP options\r
+  in the OptionList parameter as described in RFC 2131.\r
+  When Configure() is called successfully while Dhcp4CfgData is set to NULL, the\r
+  default configuring data will be reset in the EFI DHCPv4 Protocol driver and\r
+  the state of the EFI DHCPv4 Protocol driver will not be changed. If one instance\r
+  wants to make it possible for another instance to configure the EFI DHCPv4 Protocol\r
+  driver, it must call this function with Dhcp4CfgData set to NULL.\r
+\r
+  @param[in]  This                   Pointer to the EFI_DHCP4_PROTOCOL instance.\r
+  @param[in]  Dhcp4CfgData           Pointer to the EFI_DHCP4_CONFIG_DATA.\r
+\r
+  @retval EFI_SUCCESS           The EFI DHCPv4 Protocol driver is now in the Dhcp4Init or\r
+                                Dhcp4InitReboot state, if the original state of this driver\r
+                                was Dhcp4Stopped and the value of Dhcp4CfgData was\r
+                                not NULL. Otherwise, the state was left unchanged.\r
+  @retval EFI_ACCESS_DENIED     This instance of the EFI DHCPv4 Protocol driver was not in the\r
+                                Dhcp4Stopped, Dhcp4Init, Dhcp4InitReboot, or Dhcp4Bound state;\r
+                                Or onother instance of this EFI DHCPv4 Protocol driver is already\r
+                                in a valid configured state.\r
+  @retval EFI_INVALID_PARAMETER Some parameter is NULL.\r
+  @retval EFI_OUT_OF_RESOURCES  Required system resources could not be allocated.\r
+  @retval EFI_DEVICE_ERROR      An unexpected system or network error occurred.\r
 \r
-#include "Dhcp4Impl.h"\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiDhcp4Configure (\r
+  IN EFI_DHCP4_PROTOCOL     *This,\r
+  IN EFI_DHCP4_CONFIG_DATA  *Dhcp4CfgData       OPTIONAL\r
+  );\r
+\r
+/**\r
+  Starts the DHCP configuration process.\r
+\r
+  The Start() function starts the DHCP configuration process. This function can\r
+  be called only when the EFI DHCPv4 Protocol driver is in the Dhcp4Init or\r
+  Dhcp4InitReboot state.\r
+  If the DHCP process completes successfully, the state of the EFI DHCPv4 Protocol\r
+  driver will be transferred through Dhcp4Selecting and Dhcp4Requesting to the\r
+  Dhcp4Bound state. The CompletionEvent will then be signaled if it is not NULL.\r
+  If the process aborts, either by the user or by some unexpected network error,\r
+  the state is restored to the Dhcp4Init state. The Start() function can be called\r
+  again to restart the process.\r
+  Refer to RFC 2131 for precise state transitions during this process. At the\r
+  time when each event occurs in this process, the callback function that was set\r
+  by EFI_DHCP4_PROTOCOL.Configure() will be called and the user can take this\r
+  opportunity to control the process.\r
+\r
+  @param[in]  This            Pointer to the EFI_DHCP4_PROTOCOL instance.\r
+  @param[in]  CompletionEvent If not NULL, indicates the event that will be signaled when the\r
+                              EFI DHCPv4 Protocol driver is transferred into the\r
+                              Dhcp4Bound state or when the DHCP process is aborted.\r
+                              EFI_DHCP4_PROTOCOL.GetModeData() can be called to\r
+                              check the completion status. If NULL,\r
+                              EFI_DHCP4_PROTOCOL.Start() will wait until the driver\r
+                              is transferred into the Dhcp4Bound state or the process fails.\r
+\r
+  @retval EFI_SUCCESS           The DHCP configuration process has started, or it has completed\r
+                                when CompletionEvent is NULL.\r
+  @retval EFI_NOT_STARTED       The EFI DHCPv4 Protocol driver is in the Dhcp4Stopped\r
+                                state. EFI_DHCP4_PROTOCOL. Configure() needs to be called.\r
+  @retval EFI_INVALID_PARAMETER This is NULL.\r
+  @retval EFI_OUT_OF_RESOURCES  Required system resources could not be allocated.\r
+  @retval EFI_TIMEOUT           The DHCP configuration process failed because no response was\r
+                                received from the server within the specified timeout value.\r
+  @retval EFI_ABORTED           The user aborted the DHCP process.\r
+  @retval EFI_ALREADY_STARTED   Some other EFI DHCPv4 Protocol instance already started the\r
+                                DHCP process.\r
+  @retval EFI_DEVICE_ERROR      An unexpected system or network error occurred.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiDhcp4Start (\r
+  IN EFI_DHCP4_PROTOCOL     *This,\r
+  IN EFI_EVENT              CompletionEvent   OPTIONAL\r
+  );\r
+\r
+/**\r
+  Extends the lease time by sending a request packet.\r
+\r
+  The RenewRebind() function is used to manually extend the lease time when the\r
+  EFI DHCPv4 Protocol driver is in the Dhcp4Bound state and the lease time has\r
+  not expired yet. This function will send a request packet to the previously\r
+  found server (or to any server when RebindRequest is TRUE) and transfer the\r
+  state into the Dhcp4Renewing state (or Dhcp4Rebinding when RebindingRequest is\r
+  TRUE). When a response is received, the state is returned to Dhcp4Bound.\r
+  If no response is received before the try count is exceeded (the RequestTryCount\r
+  field that is specified in EFI_DHCP4_CONFIG_DATA) but before the lease time that\r
+  was issued by the previous server expires, the driver will return to the Dhcp4Bound\r
+  state and the previous configuration is restored. The outgoing and incoming packets\r
+  can be captured by the EFI_DHCP4_CALLBACK function.\r
+\r
+  @param[in]  This            Pointer to the EFI_DHCP4_PROTOCOL instance.\r
+  @param[in]  RebindRequest   If TRUE, this function broadcasts the request packets and enters\r
+                              the Dhcp4Rebinding state. Otherwise, it sends a unicast\r
+                              request packet and enters the Dhcp4Renewing state.\r
+  @param[in]  CompletionEvent If not NULL, this event is signaled when the renew/rebind phase\r
+                              completes or some error occurs.\r
+                              EFI_DHCP4_PROTOCOL.GetModeData() can be called to\r
+                              check the completion status. If NULL,\r
+                              EFI_DHCP4_PROTOCOL.RenewRebind() will busy-wait\r
+                              until the DHCP process finishes.\r
+\r
+  @retval EFI_SUCCESS           The EFI DHCPv4 Protocol driver is now in the\r
+                                Dhcp4Renewing state or is back to the Dhcp4Bound state.\r
+  @retval EFI_NOT_STARTED       The EFI DHCPv4 Protocol driver is in the Dhcp4Stopped\r
+                                state. EFI_DHCP4_PROTOCOL.Configure() needs to\r
+                                be called.\r
+  @retval EFI_INVALID_PARAMETER This is NULL.\r
+  @retval EFI_TIMEOUT           There was no response from the server when the try count was\r
+                                exceeded.\r
+  @retval EFI_ACCESS_DENIED     The driver is not in the Dhcp4Bound state.\r
+  @retval EFI_DEVICE_ERROR      An unexpected system or network error occurred.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiDhcp4RenewRebind (\r
+  IN EFI_DHCP4_PROTOCOL     *This,\r
+  IN BOOLEAN                RebindRequest,\r
+  IN EFI_EVENT              CompletionEvent   OPTIONAL\r
+  );\r
+\r
+/**\r
+  Releases the current address configuration.\r
+\r
+  The Release() function releases the current configured IP address by doing either\r
+  of the following:\r
+  * Sending a DHCPRELEASE packet when the EFI DHCPv4 Protocol driver is in the\r
+    Dhcp4Bound state\r
+  * Setting the previously assigned IP address that was provided with the\r
+    EFI_DHCP4_PROTOCOL.Configure() function to 0.0.0.0 when the driver is in\r
+    Dhcp4InitReboot state\r
+  After a successful call to this function, the EFI DHCPv4 Protocol driver returns\r
+  to the Dhcp4Init state and any subsequent incoming packets will be discarded silently.\r
+\r
+  @param[in]  This                  Pointer to the EFI_DHCP4_PROTOCOL instance.\r
+\r
+  @retval EFI_SUCCESS           The EFI DHCPv4 Protocol driver is now in the Dhcp4Init phase.\r
+  @retval EFI_INVALID_PARAMETER This is NULL.\r
+  @retval EFI_ACCESS_DENIED     The EFI DHCPv4 Protocol driver is not Dhcp4InitReboot state.\r
+  @retval EFI_DEVICE_ERROR      An unexpected system or network error occurred.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiDhcp4Release (\r
+  IN EFI_DHCP4_PROTOCOL     *This\r
+  );\r
+\r
+/**\r
+  Stops the current address configuration.\r
+\r
+  The Stop() function is used to stop the DHCP configuration process. After this\r
+  function is called successfully, the EFI DHCPv4 Protocol driver is transferred\r
+  into the Dhcp4Stopped state. EFI_DHCP4_PROTOCOL.Configure() needs to be called\r
+  before DHCP configuration process can be started again. This function can be\r
+  called when the EFI DHCPv4 Protocol driver is in any state.\r
+\r
+  @param[in]  This                  Pointer to the EFI_DHCP4_PROTOCOL instance.\r
+\r
+  @retval EFI_SUCCESS           The EFI DHCPv4 Protocol driver is now in the Dhcp4Stopped phase.\r
+  @retval EFI_INVALID_PARAMETER This is NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiDhcp4Stop (\r
+  IN EFI_DHCP4_PROTOCOL     *This\r
+  );\r
+\r
+/**\r
+  Builds a DHCP packet, given the options to be appended or deleted or replaced.\r
+\r
+  The Build() function is used to assemble a new packet from the original packet\r
+  by replacing or deleting existing options or appending new options. This function\r
+  does not change any state of the EFI DHCPv4 Protocol driver and can be used at\r
+  any time.\r
+\r
+  @param[in]  This        Pointer to the EFI_DHCP4_PROTOCOL instance.\r
+  @param[in]  SeedPacket  Initial packet to be used as a base for building new packet.\r
+  @param[in]  DeleteCount Number of opcodes in the DeleteList.\r
+  @param[in]  DeleteList  List of opcodes to be deleted from the seed packet.\r
+                          Ignored if DeleteCount is zero.\r
+  @param[in]  AppendCount Number of entries in the OptionList.\r
+  @param[in]  AppendList  Pointer to a DHCP option list to be appended to SeedPacket.\r
+                          If SeedPacket also contains options in this list, they are\r
+                          replaced by new options (except pad option). Ignored if\r
+                          AppendCount is zero. Type EFI_DHCP4_PACKET_OPTION\r
+  @param[out] NewPacket   Pointer to storage for the pointer to the new allocated packet.\r
+                          Use the EFI Boot Service FreePool() on the resulting pointer\r
+                          when done with the packet.\r
+\r
+  @retval EFI_SUCCESS           The new packet was built.\r
+  @retval EFI_OUT_OF_RESOURCES  Storage for the new packet could not be allocated.\r
+  @retval EFI_INVALID_PARAMETER Some parameter is NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiDhcp4Build (\r
+  IN EFI_DHCP4_PROTOCOL       *This,\r
+  IN EFI_DHCP4_PACKET         *SeedPacket,\r
+  IN UINT32                   DeleteCount,\r
+  IN UINT8                    *DeleteList OPTIONAL,\r
+  IN UINT32                   AppendCount,\r
+  IN EFI_DHCP4_PACKET_OPTION  *AppendList[] OPTIONAL,\r
+  OUT EFI_DHCP4_PACKET        **NewPacket\r
+  );\r
+\r
+/**\r
+  Transmits a DHCP formatted packet and optionally waits for responses.\r
+\r
+  The TransmitReceive() function is used to transmit a DHCP packet and optionally\r
+  wait for the response from servers. This function does not change the state of\r
+  the EFI DHCPv4 Protocol driver and thus can be used at any time.\r
+\r
+  @param[in]  This    Pointer to the EFI_DHCP4_PROTOCOL instance.\r
+  @param[in]  Token   Pointer to the EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN structure.\r
+\r
+  @retval EFI_SUCCESS           The packet was successfully queued for transmission.\r
+  @retval EFI_INVALID_PARAMETER Some parameter is NULL.\r
+  @retval EFI_NOT_READY         The previous call to this function has not finished yet. Try to call\r
+                                this function after collection process completes.\r
+  @retval EFI_NO_MAPPING        The default station address is not available yet.\r
+  @retval EFI_OUT_OF_RESOURCES  Required system resources could not be allocated.\r
+  @retval Others                Some other unexpected error occurred.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiDhcp4TransmitReceive (\r
+  IN EFI_DHCP4_PROTOCOL                *This,\r
+  IN EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN  *Token\r
+  );\r
+\r
+/**\r
+  Parses the packed DHCP option data.\r
+\r
+  The Parse() function is used to retrieve the option list from a DHCP packet.\r
+  If *OptionCount isn't zero, and there is enough space for all the DHCP options\r
+  in the Packet, each element of PacketOptionList is set to point to somewhere in\r
+  the Packet->Dhcp4.Option where a new DHCP option begins. If RFC3396 is supported,\r
+  the caller should reassemble the parsed DHCP options to get the finial result.\r
+  If *OptionCount is zero or there isn't enough space for all of them, the number\r
+  of DHCP options in the Packet is returned in OptionCount.\r
+\r
+  @param  This             Pointer to the EFI_DHCP4_PROTOCOL instance.\r
+  @param  Packet           Pointer to packet to be parsed.\r
+  @param  OptionCount      On input, the number of entries in the PacketOptionList.\r
+                           On output, the number of entries that were written into the\r
+                           PacketOptionList.\r
+  @param  PacketOptionList List of packet option entries to be filled in. End option or pad\r
+                           options are not included.\r
+\r
+  @retval EFI_SUCCESS           The packet was successfully parsed.\r
+  @retval EFI_INVALID_PARAMETER Some parameter is NULL.\r
+  @retval EFI_BUFFER_TOO_SMALL  One or more of the following conditions is TRUE:\r
+                                1) *OptionCount is smaller than the number of options that\r
+                                were found in the Packet.\r
+                                2) PacketOptionList is NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiDhcp4Parse (\r
+  IN EFI_DHCP4_PROTOCOL       *This,\r
+  IN EFI_DHCP4_PACKET         *Packet,\r
+  IN OUT UINT32               *OptionCount,\r
+  OUT EFI_DHCP4_PACKET_OPTION *PacketOptionList[] OPTIONAL\r
+  );\r
 \r
+EFI_DHCP4_PROTOCOL  mDhcp4ProtocolTemplate = {\r
+  EfiDhcp4GetModeData,\r
+  EfiDhcp4Configure,\r
+  EfiDhcp4Start,\r
+  EfiDhcp4RenewRebind,\r
+  EfiDhcp4Release,\r
+  EfiDhcp4Stop,\r
+  EfiDhcp4Build,\r
+  EfiDhcp4TransmitReceive,\r
+  EfiDhcp4Parse\r
+};\r
 \r
 /**\r
-  Get the current operation parameter and lease for the network interface.\r
+  Returns the current operating mode and cached data packet for the EFI DHCPv4 Protocol driver.\r
 \r
-  @param  This                   The DHCP protocol instance\r
-  @param  Dhcp4ModeData          The variable to save the DHCP mode data.\r
+  The GetModeData() function returns the current operating mode and cached data\r
+  packet for the EFI DHCPv4 Protocol driver.\r
 \r
-  @retval EFI_INVALID_PARAMETER  The parameter is invalid\r
-  @retval EFI_SUCCESS            The Dhcp4ModeData is updated with the current\r
-                                 operation parameter.\r
+  @param[in]  This          Pointer to the EFI_DHCP4_PROTOCOL instance.\r
+  @param[out] Dhcp4ModeData Pointer to storage for the EFI_DHCP4_MODE_DATA structure.\r
+\r
+  @retval EFI_SUCCESS           The mode data was returned.\r
+  @retval EFI_INVALID_PARAMETER This is NULL.\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 EFIAPI\r
 EfiDhcp4GetModeData (\r
@@ -58,44 +367,40 @@ EfiDhcp4GetModeData (
 \r
   Instance = DHCP_INSTANCE_FROM_THIS (This);\r
 \r
-  if (Instance->Signature != DHCP_PROTOCOL_SIGNATURE) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  OldTpl  = NET_RAISE_TPL (NET_TPL_LOCK);\r
+  OldTpl  = gBS->RaiseTPL (TPL_CALLBACK);\r
   DhcpSb  = Instance->Service;\r
 \r
   //\r
   // Caller can use GetModeData to retrieve current DHCP states\r
   // no matter whether it is the active child or not.\r
   //\r
-  Dhcp4ModeData->State                     = (EFI_DHCP4_STATE) DhcpSb->DhcpState;\r
+  Dhcp4ModeData->State = (EFI_DHCP4_STATE) DhcpSb->DhcpState;\r
   CopyMem (&Dhcp4ModeData->ConfigData, &DhcpSb->ActiveConfig, sizeof (Dhcp4ModeData->ConfigData));\r
   CopyMem (&Dhcp4ModeData->ClientMacAddress, &DhcpSb->Mac, sizeof (Dhcp4ModeData->ClientMacAddress));\r
 \r
   Ip = HTONL (DhcpSb->ClientAddr);\r
-  NetCopyMem (&Dhcp4ModeData->ClientAddress, &Ip, sizeof (EFI_IPv4_ADDRESS));\r
+  CopyMem (&Dhcp4ModeData->ClientAddress, &Ip, sizeof (EFI_IPv4_ADDRESS));\r
 \r
   Ip = HTONL (DhcpSb->Netmask);\r
-  NetCopyMem (&Dhcp4ModeData->SubnetMask, &Ip, sizeof (EFI_IPv4_ADDRESS));\r
+  CopyMem (&Dhcp4ModeData->SubnetMask, &Ip, sizeof (EFI_IPv4_ADDRESS));\r
 \r
   Ip = HTONL (DhcpSb->ServerAddr);\r
-  NetCopyMem (&Dhcp4ModeData->ServerAddress, &Ip, sizeof (EFI_IPv4_ADDRESS));\r
+  CopyMem (&Dhcp4ModeData->ServerAddress, &Ip, sizeof (EFI_IPv4_ADDRESS));\r
 \r
   Para = DhcpSb->Para;\r
 \r
   if (Para != NULL) {\r
     Ip = HTONL (Para->Router);\r
-    NetCopyMem (&Dhcp4ModeData->RouterAddress, &Ip, sizeof (EFI_IPv4_ADDRESS));\r
-    Dhcp4ModeData->LeaseTime               = Para->Lease;\r
+    CopyMem (&Dhcp4ModeData->RouterAddress, &Ip, sizeof (EFI_IPv4_ADDRESS));\r
+    Dhcp4ModeData->LeaseTime = Para->Lease;\r
   } else {\r
-    NetZeroMem (&Dhcp4ModeData->RouterAddress, sizeof (EFI_IPv4_ADDRESS));\r
-    Dhcp4ModeData->LeaseTime               = 0xffffffff;\r
+    ZeroMem (&Dhcp4ModeData->RouterAddress, sizeof (EFI_IPv4_ADDRESS));\r
+    Dhcp4ModeData->LeaseTime = 0xffffffff;\r
   }\r
 \r
   Dhcp4ModeData->ReplyPacket = DhcpSb->Selected;\r
 \r
-  NET_RESTORE_TPL (OldTpl);\r
+  gBS->RestoreTPL (OldTpl);\r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -107,35 +412,33 @@ EfiDhcp4GetModeData (
 \r
   @param  Config                 The DHCP configure data\r
 \r
-  @return None\r
-\r
 **/\r
 VOID\r
 DhcpCleanConfigure (\r
-  IN EFI_DHCP4_CONFIG_DATA  *Config\r
+  IN OUT EFI_DHCP4_CONFIG_DATA  *Config\r
   )\r
 {\r
   UINT32                    Index;\r
 \r
   if (Config->DiscoverTimeout != NULL) {\r
-    NetFreePool (Config->DiscoverTimeout);\r
+    FreePool (Config->DiscoverTimeout);\r
   }\r
 \r
   if (Config->RequestTimeout != NULL) {\r
-    NetFreePool (Config->RequestTimeout);\r
+    FreePool (Config->RequestTimeout);\r
   }\r
 \r
   if (Config->OptionList != NULL) {\r
     for (Index = 0; Index < Config->OptionCount; Index++) {\r
       if (Config->OptionList[Index] != NULL) {\r
-        NetFreePool (Config->OptionList[Index]);\r
+        FreePool (Config->OptionList[Index]);\r
       }\r
     }\r
 \r
-    NetFreePool (Config->OptionList);\r
+    FreePool (Config->OptionList);\r
   }\r
 \r
-  NetZeroMem (Config, sizeof (EFI_DHCP4_CONFIG_DATA));\r
+  ZeroMem (Config, sizeof (EFI_DHCP4_CONFIG_DATA));\r
 }\r
 \r
 \r
@@ -143,8 +446,8 @@ DhcpCleanConfigure (
   Allocate memory for configure parameter such as timeout value for Dst,\r
   then copy the configure parameter from Src to Dst.\r
 \r
-  @param  Dst                    The destination DHCP configure data.\r
-  @param  Src                    The source DHCP configure data.\r
+  @param[out]  Dst                    The destination DHCP configure data.\r
+  @param[in]   Src                    The source DHCP configure data.\r
 \r
   @retval EFI_OUT_OF_RESOURCES   Failed to allocate memory.\r
   @retval EFI_SUCCESS            The configure is copied.\r
@@ -152,16 +455,16 @@ DhcpCleanConfigure (
 **/\r
 EFI_STATUS\r
 DhcpCopyConfigure (\r
-  IN EFI_DHCP4_CONFIG_DATA  *Dst,\r
-  IN EFI_DHCP4_CONFIG_DATA  *Src\r
+  OUT EFI_DHCP4_CONFIG_DATA  *Dst,\r
+  IN  EFI_DHCP4_CONFIG_DATA  *Src\r
   )\r
 {\r
   EFI_DHCP4_PACKET_OPTION   **DstOptions;\r
   EFI_DHCP4_PACKET_OPTION   **SrcOptions;\r
-  INTN                      Len;\r
+  UINTN                     Len;\r
   UINT32                    Index;\r
 \r
-  CopyMem (Dst, Src, sizeof (Dst));\r
+  CopyMem (Dst, Src, sizeof (*Dst));\r
   Dst->DiscoverTimeout  = NULL;\r
   Dst->RequestTimeout   = NULL;\r
   Dst->OptionList       = NULL;\r
@@ -171,14 +474,14 @@ DhcpCopyConfigure (
   //\r
   if (Src->DiscoverTimeout != NULL) {\r
     Len                   = Src->DiscoverTryCount * sizeof (UINT32);\r
-    Dst->DiscoverTimeout  = NetAllocatePool (Len);\r
+    Dst->DiscoverTimeout  = AllocatePool (Len);\r
 \r
     if (Dst->DiscoverTimeout == NULL) {\r
       return EFI_OUT_OF_RESOURCES;\r
     }\r
 \r
     for (Index = 0; Index < Src->DiscoverTryCount; Index++) {\r
-      Dst->DiscoverTimeout[Index] = NET_MAX (Src->DiscoverTimeout[Index], 1);\r
+      Dst->DiscoverTimeout[Index] = MAX (Src->DiscoverTimeout[Index], 1);\r
     }\r
   }\r
 \r
@@ -187,14 +490,14 @@ DhcpCopyConfigure (
   //\r
   if (Src->RequestTimeout != NULL) {\r
     Len                 = Src->RequestTryCount * sizeof (UINT32);\r
-    Dst->RequestTimeout = NetAllocatePool (Len);\r
+    Dst->RequestTimeout = AllocatePool (Len);\r
 \r
     if (Dst->RequestTimeout == NULL) {\r
       goto ON_ERROR;\r
     }\r
 \r
     for (Index = 0; Index < Src->RequestTryCount; Index++) {\r
-      Dst->RequestTimeout[Index] = NET_MAX (Src->RequestTimeout[Index], 1);\r
+      Dst->RequestTimeout[Index] = MAX (Src->RequestTimeout[Index], 1);\r
     }\r
   }\r
 \r
@@ -204,7 +507,7 @@ DhcpCopyConfigure (
   //\r
   if (Src->OptionList != NULL) {\r
     Len             = Src->OptionCount * sizeof (EFI_DHCP4_PACKET_OPTION *);\r
-    Dst->OptionList = NetAllocateZeroPool (Len);\r
+    Dst->OptionList = AllocateZeroPool (Len);\r
 \r
     if (Dst->OptionList == NULL) {\r
       goto ON_ERROR;\r
@@ -214,15 +517,15 @@ DhcpCopyConfigure (
     SrcOptions  = Src->OptionList;\r
 \r
     for (Index = 0; Index < Src->OptionCount; Index++) {\r
-      Len = sizeof (EFI_DHCP4_PACKET_OPTION) + NET_MAX (SrcOptions[Index]->Length - 1, 0);\r
+      Len = sizeof (EFI_DHCP4_PACKET_OPTION) + MAX (SrcOptions[Index]->Length - 1, 0);\r
 \r
-      DstOptions[Index] = NetAllocatePool (Len);\r
+      DstOptions[Index] = AllocatePool (Len);\r
 \r
       if (DstOptions[Index] == NULL) {\r
         goto ON_ERROR;\r
       }\r
 \r
-      NetCopyMem (DstOptions[Index], SrcOptions[Index], Len);\r
+      CopyMem (DstOptions[Index], SrcOptions[Index], Len);\r
     }\r
   }\r
 \r
@@ -241,8 +544,6 @@ ON_ERROR:
 \r
   @param  DhcpSb                 The DHCP service instance.\r
 \r
-  @return None\r
-\r
 **/\r
 VOID\r
 DhcpYieldControl (\r
@@ -257,14 +558,14 @@ DhcpYieldControl (
   DhcpSb->ActiveChild   = NULL;\r
 \r
   if (Config->DiscoverTimeout != NULL) {\r
-    NetFreePool (Config->DiscoverTimeout);\r
+    FreePool (Config->DiscoverTimeout);\r
 \r
     Config->DiscoverTryCount  = 0;\r
     Config->DiscoverTimeout   = NULL;\r
   }\r
 \r
   if (Config->RequestTimeout != NULL) {\r
-    NetFreePool (Config->RequestTimeout);\r
+    FreePool (Config->RequestTimeout);\r
 \r
     Config->RequestTryCount = 0;\r
     Config->RequestTimeout  = NULL;\r
@@ -276,21 +577,47 @@ DhcpYieldControl (
 \r
 \r
 /**\r
-  Configure the DHCP protocol instance and its underlying DHCP service\r
-  for operation. If Dhcp4CfgData is NULL and the child is currently\r
-  controlling the DHCP service, release the control.\r
-\r
-  @param  This                   The DHCP protocol instance\r
-  @param  Dhcp4CfgData           The DHCP configure data.\r
-\r
-  @retval EFI_INVALID_PARAMETER  The parameters are invalid.\r
-  @retval EFI_ACCESS_DENIED      The service isn't in one of configurable states,\r
-                                 or there is already an active child.\r
-  @retval EFI_OUT_OF_RESOURCE    Failed to allocate some resources.\r
-  @retval EFI_SUCCESS            The child is configured.\r
+  Initializes, changes, or resets the operational settings for the EFI DHCPv4 Protocol driver.\r
+\r
+  The Configure() function is used to initialize, change, or reset the operational\r
+  settings of the EFI DHCPv4 Protocol driver for the communication device on which\r
+  the EFI DHCPv4 Service Binding Protocol is installed. This function can be\r
+  successfully called only if both of the following are true:\r
+  * This instance of the EFI DHCPv4 Protocol driver is in the Dhcp4Stopped, Dhcp4Init,\r
+    Dhcp4InitReboot, or Dhcp4Bound states.\r
+  * No other EFI DHCPv4 Protocol driver instance that is controlled by this EFI\r
+    DHCPv4 Service Binding Protocol driver instance has configured this EFI DHCPv4\r
+    Protocol driver.\r
+  When this driver is in the Dhcp4Stopped state, it can transfer into one of the\r
+  following two possible initial states:\r
+  * Dhcp4Init\r
+  * Dhcp4InitReboot\r
+  The driver can transfer into these states by calling Configure() with a non-NULL\r
+  Dhcp4CfgData. The driver will transfer into the appropriate state based on the\r
+  supplied client network address in the ClientAddress parameter and DHCP options\r
+  in the OptionList parameter as described in RFC 2131.\r
+  When Configure() is called successfully while Dhcp4CfgData is set to NULL, the\r
+  default configuring data will be reset in the EFI DHCPv4 Protocol driver and\r
+  the state of the EFI DHCPv4 Protocol driver will not be changed. If one instance\r
+  wants to make it possible for another instance to configure the EFI DHCPv4 Protocol\r
+  driver, it must call this function with Dhcp4CfgData set to NULL.\r
+\r
+  @param[in]  This                   Pointer to the EFI_DHCP4_PROTOCOL instance.\r
+  @param[in]  Dhcp4CfgData           Pointer to the EFI_DHCP4_CONFIG_DATA.\r
+\r
+  @retval EFI_SUCCESS           The EFI DHCPv4 Protocol driver is now in the Dhcp4Init or\r
+                                Dhcp4InitReboot state, if the original state of this driver\r
+                                was Dhcp4Stopped and the value of Dhcp4CfgData was\r
+                                not NULL. Otherwise, the state was left unchanged.\r
+  @retval EFI_ACCESS_DENIED     This instance of the EFI DHCPv4 Protocol driver was not in the\r
+                                Dhcp4Stopped, Dhcp4Init, Dhcp4InitReboot, or Dhcp4Bound state;\r
+                                Or onother instance of this EFI DHCPv4 Protocol driver is already\r
+                                in a valid configured state.\r
+  @retval EFI_INVALID_PARAMETER Some parameter is NULL.\r
+  @retval EFI_OUT_OF_RESOURCES  Required system resources could not be allocated.\r
+  @retval EFI_DEVICE_ERROR      An unexpected system or network error occurred.\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 EFIAPI\r
 EfiDhcp4Configure (\r
@@ -314,22 +641,20 @@ EfiDhcp4Configure (
   }\r
 \r
   if (Dhcp4CfgData != NULL) {\r
-    if (Dhcp4CfgData->DiscoverTryCount && (Dhcp4CfgData->DiscoverTimeout == NULL)) {\r
+    if ((Dhcp4CfgData->DiscoverTryCount != 0) && (Dhcp4CfgData->DiscoverTimeout == NULL)) {\r
       return EFI_INVALID_PARAMETER;\r
     }\r
 \r
-    if (Dhcp4CfgData->RequestTryCount && (Dhcp4CfgData->RequestTimeout == NULL)) {\r
+    if ((Dhcp4CfgData->RequestTryCount != 0) && (Dhcp4CfgData->RequestTimeout == NULL)) {\r
       return EFI_INVALID_PARAMETER;\r
     }\r
 \r
-    if (Dhcp4CfgData->OptionCount && (Dhcp4CfgData->OptionList == NULL)) {\r
+    if ((Dhcp4CfgData->OptionCount != 0) && (Dhcp4CfgData->OptionList == NULL)) {\r
       return EFI_INVALID_PARAMETER;\r
     }\r
 \r
-    NetCopyMem (&Ip, &Dhcp4CfgData->ClientAddress, sizeof (IP4_ADDR));\r
-\r
-    if ((Ip != 0) && !Ip4IsUnicast (NTOHL (Ip), 0)) {\r
-\r
+    CopyMem (&Ip, &Dhcp4CfgData->ClientAddress, sizeof (IP4_ADDR));\r
+    if (IP4_IS_LOCAL_BROADCAST(NTOHL (Ip))) {\r
       return EFI_INVALID_PARAMETER;\r
     }\r
   }\r
@@ -340,7 +665,7 @@ EfiDhcp4Configure (
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  OldTpl  = NET_RAISE_TPL (NET_TPL_LOCK);\r
+  OldTpl  = gBS->RaiseTPL (TPL_CALLBACK);\r
 \r
   DhcpSb  = Instance->Service;\r
   Config  = &DhcpSb->ActiveConfig;\r
@@ -394,24 +719,52 @@ EfiDhcp4Configure (
   }\r
 \r
 ON_EXIT:\r
-  NET_RESTORE_TPL (OldTpl);\r
+  gBS->RestoreTPL (OldTpl);\r
   return Status;\r
 }\r
 \r
 \r
 /**\r
-  Start the DHCP process.\r
-\r
-  @param  This                   The DHCP protocol instance\r
-  @param  CompletionEvent        The event to signal is address is acquired.\r
-\r
-  @retval EFI_INVALID_PARAMETER  The parameters are invalid.\r
-  @retval EFI_NOT_STARTED        The protocol hasn't been configured.\r
-  @retval EFI_ALREADY_STARTED    The DHCP process has already been started.\r
-  @retval EFI_SUCCESS            The DHCP process is started.\r
+  Starts the DHCP configuration process.\r
+\r
+  The Start() function starts the DHCP configuration process. This function can\r
+  be called only when the EFI DHCPv4 Protocol driver is in the Dhcp4Init or\r
+  Dhcp4InitReboot state.\r
+  If the DHCP process completes successfully, the state of the EFI DHCPv4 Protocol\r
+  driver will be transferred through Dhcp4Selecting and Dhcp4Requesting to the\r
+  Dhcp4Bound state. The CompletionEvent will then be signaled if it is not NULL.\r
+  If the process aborts, either by the user or by some unexpected network error,\r
+  the state is restored to the Dhcp4Init state. The Start() function can be called\r
+  again to restart the process.\r
+  Refer to RFC 2131 for precise state transitions during this process. At the\r
+  time when each event occurs in this process, the callback function that was set\r
+  by EFI_DHCP4_PROTOCOL.Configure() will be called and the user can take this\r
+  opportunity to control the process.\r
+\r
+  @param[in]  This            Pointer to the EFI_DHCP4_PROTOCOL instance.\r
+  @param[in]  CompletionEvent If not NULL, indicates the event that will be signaled when the\r
+                              EFI DHCPv4 Protocol driver is transferred into the\r
+                              Dhcp4Bound state or when the DHCP process is aborted.\r
+                              EFI_DHCP4_PROTOCOL.GetModeData() can be called to\r
+                              check the completion status. If NULL,\r
+                              EFI_DHCP4_PROTOCOL.Start() will wait until the driver\r
+                              is transferred into the Dhcp4Bound state or the process fails.\r
+\r
+  @retval EFI_SUCCESS           The DHCP configuration process has started, or it has completed\r
+                                when CompletionEvent is NULL.\r
+  @retval EFI_NOT_STARTED       The EFI DHCPv4 Protocol driver is in the Dhcp4Stopped\r
+                                state. EFI_DHCP4_PROTOCOL. Configure() needs to be called.\r
+  @retval EFI_INVALID_PARAMETER This is NULL.\r
+  @retval EFI_OUT_OF_RESOURCES  Required system resources could not be allocated.\r
+  @retval EFI_TIMEOUT           The DHCP configuration process failed because no response was\r
+                                received from the server within the specified timeout value.\r
+  @retval EFI_ABORTED           The user aborted the DHCP process.\r
+  @retval EFI_ALREADY_STARTED   Some other EFI DHCPv4 Protocol instance already started the\r
+                                DHCP process.\r
+  @retval EFI_DEVICE_ERROR      An unexpected system or network error occurred.\r
+  @retval EFI_NO_MEDIA          There was a media error.\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 EFIAPI\r
 EfiDhcp4Start (\r
@@ -423,6 +776,7 @@ EfiDhcp4Start (
   DHCP_SERVICE              *DhcpSb;\r
   EFI_STATUS                Status;\r
   EFI_TPL                   OldTpl;\r
+  EFI_STATUS                MediaStatus;\r
 \r
   //\r
   // First validate the parameters\r
@@ -437,7 +791,7 @@ EfiDhcp4Start (
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  OldTpl  = NET_RAISE_TPL (NET_TPL_LOCK);\r
+  OldTpl  = gBS->RaiseTPL (TPL_CALLBACK);\r
   DhcpSb  = Instance->Service;\r
 \r
   if (DhcpSb->DhcpState == Dhcp4Stopped) {\r
@@ -450,31 +804,33 @@ EfiDhcp4Start (
     goto ON_ERROR;\r
   }\r
 \r
-  DhcpSb->IoStatus = EFI_ALREADY_STARTED;\r
-\r
-  if (EFI_ERROR (Status = DhcpInitRequest (DhcpSb))) {\r
+  //\r
+  // Check Media Satus.\r
+  //\r
+  MediaStatus = EFI_SUCCESS;\r
+  NetLibDetectMediaWaitTimeout (DhcpSb->Controller, DHCP_CHECK_MEDIA_WAITING_TIME, &MediaStatus);\r
+  if (MediaStatus != EFI_SUCCESS) {\r
+    Status = EFI_NO_MEDIA;\r
     goto ON_ERROR;\r
   }\r
 \r
-  //\r
-  // Start/Restart the receiving.\r
-  //\r
-  Status = UdpIoRecvDatagram (DhcpSb->UdpIo, DhcpInput, DhcpSb, 0);\r
+  DhcpSb->IoStatus = EFI_ALREADY_STARTED;\r
 \r
-  if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {\r
+  if (EFI_ERROR (Status = DhcpInitRequest (DhcpSb))) {\r
     goto ON_ERROR;\r
   }\r
 \r
+\r
   Instance->CompletionEvent = CompletionEvent;\r
 \r
   //\r
-  // Restore the TPL now, don't call poll function at NET_TPL_LOCK.\r
+  // Restore the TPL now, don't call poll function at TPL_CALLBACK.\r
   //\r
-  NET_RESTORE_TPL (OldTpl);\r
+  gBS->RestoreTPL (OldTpl);\r
 \r
   if (CompletionEvent == NULL) {\r
     while (DhcpSb->IoStatus == EFI_ALREADY_STARTED) {\r
-      DhcpSb->UdpIo->Udp->Poll (DhcpSb->UdpIo->Udp);\r
+      DhcpSb->UdpIo->Protocol.Udp4->Poll (DhcpSb->UdpIo->Protocol.Udp4);\r
     }\r
 \r
     return DhcpSb->IoStatus;\r
@@ -483,25 +839,49 @@ EfiDhcp4Start (
   return EFI_SUCCESS;\r
 \r
 ON_ERROR:\r
-  NET_RESTORE_TPL (OldTpl);\r
+  gBS->RestoreTPL (OldTpl);\r
   return Status;\r
 }\r
 \r
 \r
 /**\r
-  Request an extra manual renew/rebind.\r
-\r
-  @param  This                   The DHCP protocol instance\r
-  @param  RebindRequest          TRUE if request a rebind, otherwise renew it\r
-  @param  CompletionEvent        Event to signal when complete\r
-\r
-  @retval EFI_INVALID_PARAMETER  The parameters are invalid\r
-  @retval EFI_NOT_STARTED        The DHCP protocol hasn't been started.\r
-  @retval EFI_ACCESS_DENIED      The DHCP protocol isn't in Bound state.\r
-  @retval EFI_SUCCESS            The DHCP is renewed/rebound.\r
+  Extends the lease time by sending a request packet.\r
+\r
+  The RenewRebind() function is used to manually extend the lease time when the\r
+  EFI DHCPv4 Protocol driver is in the Dhcp4Bound state and the lease time has\r
+  not expired yet. This function will send a request packet to the previously\r
+  found server (or to any server when RebindRequest is TRUE) and transfer the\r
+  state into the Dhcp4Renewing state (or Dhcp4Rebinding when RebindingRequest is\r
+  TRUE). When a response is received, the state is returned to Dhcp4Bound.\r
+  If no response is received before the try count is exceeded (the RequestTryCount\r
+  field that is specified in EFI_DHCP4_CONFIG_DATA) but before the lease time that\r
+  was issued by the previous server expires, the driver will return to the Dhcp4Bound\r
+  state and the previous configuration is restored. The outgoing and incoming packets\r
+  can be captured by the EFI_DHCP4_CALLBACK function.\r
+\r
+  @param[in]  This            Pointer to the EFI_DHCP4_PROTOCOL instance.\r
+  @param[in]  RebindRequest   If TRUE, this function broadcasts the request packets and enters\r
+                              the Dhcp4Rebinding state. Otherwise, it sends a unicast\r
+                              request packet and enters the Dhcp4Renewing state.\r
+  @param[in]  CompletionEvent If not NULL, this event is signaled when the renew/rebind phase\r
+                              completes or some error occurs.\r
+                              EFI_DHCP4_PROTOCOL.GetModeData() can be called to\r
+                              check the completion status. If NULL,\r
+                              EFI_DHCP4_PROTOCOL.RenewRebind() will busy-wait\r
+                              until the DHCP process finishes.\r
+\r
+  @retval EFI_SUCCESS           The EFI DHCPv4 Protocol driver is now in the\r
+                                Dhcp4Renewing state or is back to the Dhcp4Bound state.\r
+  @retval EFI_NOT_STARTED       The EFI DHCPv4 Protocol driver is in the Dhcp4Stopped\r
+                                state. EFI_DHCP4_PROTOCOL.Configure() needs to\r
+                                be called.\r
+  @retval EFI_INVALID_PARAMETER This is NULL.\r
+  @retval EFI_TIMEOUT           There was no response from the server when the try count was\r
+                                exceeded.\r
+  @retval EFI_ACCESS_DENIED     The driver is not in the Dhcp4Bound state.\r
+  @retval EFI_DEVICE_ERROR      An unexpected system or network error occurred.\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 EFIAPI\r
 EfiDhcp4RenewRebind (\r
@@ -528,21 +908,22 @@ EfiDhcp4RenewRebind (
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  OldTpl  = NET_RAISE_TPL (NET_TPL_LOCK);\r
+  OldTpl  = gBS->RaiseTPL (TPL_CALLBACK);\r
   DhcpSb  = Instance->Service;\r
 \r
   if (DhcpSb->DhcpState == Dhcp4Stopped) {\r
     Status = EFI_NOT_STARTED;\r
-    goto ON_ERROR;\r
+    goto ON_EXIT;\r
   }\r
 \r
   if (DhcpSb->DhcpState != Dhcp4Bound) {\r
     Status = EFI_ACCESS_DENIED;\r
-    goto ON_ERROR;\r
+    goto ON_EXIT;\r
   }\r
 \r
   if (DHCP_IS_BOOTP (DhcpSb->Para)) {\r
-    return EFI_SUCCESS;\r
+    Status = EFI_SUCCESS;\r
+    goto ON_EXIT;\r
   }\r
 \r
   //\r
@@ -554,28 +935,35 @@ EfiDhcp4RenewRebind (
     DhcpSetState (DhcpSb, Dhcp4Rebinding, FALSE);\r
   }\r
 \r
+  //\r
+  // Clear initial time to make sure that elapsed-time\r
+  // is set to 0 for first REQUEST in renewal process.\r
+  //\r
+  Instance->ElaspedTime = 0;\r
+\r
   Status = DhcpSendMessage (\r
              DhcpSb,\r
              DhcpSb->Selected,\r
              DhcpSb->Para,\r
              DHCP_MSG_REQUEST,\r
-             "Extra renew/rebind by the application"\r
+             (UINT8 *) "Extra renew/rebind by the application"\r
              );\r
 \r
   if (EFI_ERROR (Status)) {\r
     DhcpSetState (DhcpSb, Dhcp4Bound, FALSE);\r
-    goto ON_ERROR;\r
+    goto ON_EXIT;\r
   }\r
 \r
   DhcpSb->ExtraRefresh        = TRUE;\r
   DhcpSb->IoStatus            = EFI_ALREADY_STARTED;\r
   Instance->RenewRebindEvent  = CompletionEvent;\r
 \r
-  NET_RESTORE_TPL (OldTpl);\r
+  gBS->RestoreTPL (OldTpl);\r
 \r
   if (CompletionEvent == NULL) {\r
     while (DhcpSb->IoStatus == EFI_ALREADY_STARTED) {\r
-      DhcpSb->UdpIo->Udp->Poll (DhcpSb->UdpIo->Udp);\r
+      DhcpSb->UdpIo->Protocol.Udp4->Poll (DhcpSb->UdpIo->Protocol.Udp4);\r
+\r
     }\r
 \r
     return DhcpSb->IoStatus;\r
@@ -583,25 +971,33 @@ EfiDhcp4RenewRebind (
 \r
   return EFI_SUCCESS;\r
 \r
-ON_ERROR:\r
-  NET_RESTORE_TPL (OldTpl);\r
+ON_EXIT:\r
+  gBS->RestoreTPL (OldTpl);\r
   return Status;\r
 }\r
 \r
 \r
 /**\r
-  Release the current acquired lease.\r
+  Releases the current address configuration.\r
 \r
-  @param  This                   The DHCP protocol instance\r
+  The Release() function releases the current configured IP address by doing either\r
+  of the following:\r
+  * Sending a DHCPRELEASE packet when the EFI DHCPv4 Protocol driver is in the\r
+    Dhcp4Bound state\r
+  * Setting the previously assigned IP address that was provided with the\r
+    EFI_DHCP4_PROTOCOL.Configure() function to 0.0.0.0 when the driver is in\r
+    Dhcp4InitReboot state\r
+  After a successful call to this function, the EFI DHCPv4 Protocol driver returns\r
+  to the Dhcp4Init state and any subsequent incoming packets will be discarded silently.\r
 \r
-  @retval EFI_INVALID_PARAMETER  The parameter is invalid\r
-  @retval EFI_DEVICE_ERROR       Failed to transmit the DHCP release packet\r
-  @retval EFI_ACCESS_DENIED      The DHCP service isn't in one of the connected\r
-                                 state.\r
-  @retval EFI_SUCCESS            The lease is released.\r
+  @param[in]  This                  Pointer to the EFI_DHCP4_PROTOCOL instance.\r
+\r
+  @retval EFI_SUCCESS           The EFI DHCPv4 Protocol driver is now in the Dhcp4Init phase.\r
+  @retval EFI_INVALID_PARAMETER This is NULL.\r
+  @retval EFI_ACCESS_DENIED     The EFI DHCPv4 Protocol driver is not Dhcp4InitReboot state.\r
+  @retval EFI_DEVICE_ERROR      An unexpected system or network error occurred.\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 EFIAPI\r
 EfiDhcp4Release (\r
@@ -627,7 +1023,7 @@ EfiDhcp4Release (
   }\r
 \r
   Status  = EFI_SUCCESS;\r
-  OldTpl  = NET_RAISE_TPL (NET_TPL_LOCK);\r
+  OldTpl  = gBS->RaiseTPL (TPL_CALLBACK);\r
   DhcpSb  = Instance->Service;\r
 \r
   if ((DhcpSb->DhcpState != Dhcp4InitReboot) && (DhcpSb->DhcpState != Dhcp4Bound)) {\r
@@ -653,22 +1049,26 @@ EfiDhcp4Release (
   DhcpCleanLease (DhcpSb);\r
 \r
 ON_EXIT:\r
-  NET_RESTORE_TPL (OldTpl);\r
+  gBS->RestoreTPL (OldTpl);\r
   return Status;\r
 }\r
 \r
 \r
 /**\r
-  Stop the current DHCP process. After this, other DHCP child\r
-  can gain control of the service, configure and use it.\r
+  Stops the current address configuration.\r
+\r
+  The Stop() function is used to stop the DHCP configuration process. After this\r
+  function is called successfully, the EFI DHCPv4 Protocol driver is transferred\r
+  into the Dhcp4Stopped state. EFI_DHCP4_PROTOCOL.Configure() needs to be called\r
+  before DHCP configuration process can be started again. This function can be\r
+  called when the EFI DHCPv4 Protocol driver is in any state.\r
 \r
-  @param  This                   The DHCP protocol instance\r
+  @param[in]  This                  Pointer to the EFI_DHCP4_PROTOCOL instance.\r
 \r
-  @retval EFI_INVALID_PARAMETER  The parameter is invalid.\r
-  @retval EFI_SUCCESS            The DHCP process is stopped.\r
+  @retval EFI_SUCCESS           The EFI DHCPv4 Protocol driver is now in the Dhcp4Stopped phase.\r
+  @retval EFI_INVALID_PARAMETER This is NULL.\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 EFIAPI\r
 EfiDhcp4Stop (\r
@@ -692,7 +1092,7 @@ EfiDhcp4Stop (
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  OldTpl  = NET_RAISE_TPL (NET_TPL_LOCK);\r
+  OldTpl  = gBS->RaiseTPL (TPL_CALLBACK);\r
   DhcpSb  = Instance->Service;\r
 \r
   DhcpCleanLease (DhcpSb);\r
@@ -700,30 +1100,38 @@ EfiDhcp4Stop (
   DhcpSb->DhcpState     = Dhcp4Stopped;\r
   DhcpSb->ServiceState  = DHCP_UNCONFIGED;\r
 \r
-  NET_RESTORE_TPL (OldTpl);\r
+  gBS->RestoreTPL (OldTpl);\r
   return EFI_SUCCESS;\r
 }\r
 \r
 \r
 /**\r
-  Build a new DHCP packet from the seed packet. Options may be deleted or\r
-  appended. The caller should free the NewPacket when finished using it.\r
-\r
-  @param  This                   The DHCP protocol instance.\r
-  @param  SeedPacket             The seed packet to start with\r
-  @param  DeleteCount            The number of options to delete\r
-  @param  DeleteList             The options to delete from the packet\r
-  @param  AppendCount            The number of options to append\r
-  @param  AppendList             The options to append to the packet\r
-  @param  NewPacket              The new packet, allocated and built by this\r
-                                 function.\r
-\r
-  @retval EFI_INVALID_PARAMETER  The parameters are invalid.\r
-  @retval EFI_OUT_OF_RESOURCES   Failed to allocate memory\r
-  @retval EFI_SUCCESS            The packet is build.\r
+  Builds a DHCP packet, given the options to be appended or deleted or replaced.\r
+\r
+  The Build() function is used to assemble a new packet from the original packet\r
+  by replacing or deleting existing options or appending new options. This function\r
+  does not change any state of the EFI DHCPv4 Protocol driver and can be used at\r
+  any time.\r
+\r
+  @param[in]  This        Pointer to the EFI_DHCP4_PROTOCOL instance.\r
+  @param[in]  SeedPacket  Initial packet to be used as a base for building new packet.\r
+  @param[in]  DeleteCount Number of opcodes in the DeleteList.\r
+  @param[in]  DeleteList  List of opcodes to be deleted from the seed packet.\r
+                          Ignored if DeleteCount is zero.\r
+  @param[in]  AppendCount Number of entries in the OptionList.\r
+  @param[in]  AppendList  Pointer to a DHCP option list to be appended to SeedPacket.\r
+                          If SeedPacket also contains options in this list, they are\r
+                          replaced by new options (except pad option). Ignored if\r
+                          AppendCount is zero. Type EFI_DHCP4_PACKET_OPTION\r
+  @param[out] NewPacket   Pointer to storage for the pointer to the new allocated packet.\r
+                          Use the EFI Boot Service FreePool() on the resulting pointer\r
+                          when done with the packet.\r
+\r
+  @retval EFI_SUCCESS           The new packet was built.\r
+  @retval EFI_OUT_OF_RESOURCES  Storage for the new packet could not be allocated.\r
+  @retval EFI_INVALID_PARAMETER Some parameter is NULL.\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 EFIAPI\r
 EfiDhcp4Build (\r
@@ -766,18 +1174,326 @@ EfiDhcp4Build (
            );\r
 }\r
 \r
+/**\r
+  Callback by UdpIoCreatePort() when creating UdpIo for this Dhcp4 instance.\r
+\r
+  @param[in] UdpIo      The UdpIo being created.\r
+  @param[in] Context    Dhcp4 instance.\r
+\r
+  @retval EFI_SUCCESS              UdpIo is configured successfully.\r
+  @retval EFI_INVALID_PARAMETER    Class E IP address is not supported or other parameters\r
+                                   are not valid.\r
+  @retval other                    Other error occurs.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Dhcp4InstanceConfigUdpIo (\r
+  IN UDP_IO       *UdpIo,\r
+  IN VOID         *Context\r
+  )\r
+{\r
+  DHCP_PROTOCOL                     *Instance;\r
+  DHCP_SERVICE                      *DhcpSb;\r
+  EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN  *Token;\r
+  EFI_UDP4_CONFIG_DATA              UdpConfigData;\r
+  IP4_ADDR                          ClientAddr;\r
+  IP4_ADDR                          Ip;\r
+  INTN                              Class;\r
+  IP4_ADDR                          SubnetMask;\r
+\r
+  Instance = (DHCP_PROTOCOL *) Context;\r
+  DhcpSb   = Instance->Service;\r
+  Token    = Instance->Token;\r
+\r
+  ZeroMem (&UdpConfigData, sizeof (EFI_UDP4_CONFIG_DATA));\r
+\r
+  UdpConfigData.AcceptBroadcast    = TRUE;\r
+  UdpConfigData.AllowDuplicatePort = TRUE;\r
+  UdpConfigData.TimeToLive         = 64;\r
+  UdpConfigData.DoNotFragment      = TRUE;\r
+\r
+  ClientAddr = EFI_NTOHL (Token->Packet->Dhcp4.Header.ClientAddr);\r
+  Ip = HTONL (ClientAddr);\r
+  CopyMem (&UdpConfigData.StationAddress, &Ip, sizeof (EFI_IPv4_ADDRESS));\r
+\r
+  if (DhcpSb->Netmask == 0) {\r
+    //\r
+    // The Dhcp4.TransmitReceive() API should be able to used at any time according to\r
+    // UEFI spec, while in classless addressing network, the netmask must be explicitly\r
+    // provided together with the station address.\r
+    // If the DHCP instance haven't be configured with a valid netmask, we could only\r
+    // compute it according to the classful addressing rule.\r
+    //\r
+    Class = NetGetIpClass (ClientAddr);\r
+    //\r
+    //  Class E IP address is not supported here!\r
+    //\r
+    ASSERT (Class < IP4_ADDR_CLASSE);\r
+    if (Class >= IP4_ADDR_CLASSE) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+\r
+    SubnetMask = gIp4AllMasks[Class << 3];\r
+  } else {\r
+    SubnetMask = DhcpSb->Netmask;\r
+  }\r
+\r
+  Ip = HTONL (SubnetMask);\r
+  CopyMem (&UdpConfigData.SubnetMask, &Ip, sizeof (EFI_IPv4_ADDRESS));\r
+\r
+  if ((Token->ListenPointCount == 0) || (Token->ListenPoints[0].ListenPort == 0)) {\r
+    UdpConfigData.StationPort = DHCP_CLIENT_PORT;\r
+  } else {\r
+    UdpConfigData.StationPort = Token->ListenPoints[0].ListenPort;\r
+  }\r
+\r
+  return UdpIo->Protocol.Udp4->Configure (UdpIo->Protocol.Udp4, &UdpConfigData);\r
+}\r
+\r
+/**\r
+  Create UdpIo for this Dhcp4 instance.\r
+\r
+  @param Instance   The Dhcp4 instance.\r
+\r
+  @retval EFI_SUCCESS                UdpIo is created successfully.\r
+  @retval EFI_OUT_OF_RESOURCES       Fails to create UdpIo because of limited\r
+                                     resources or configuration failure.\r
+**/\r
+EFI_STATUS\r
+Dhcp4InstanceCreateUdpIo (\r
+  IN OUT DHCP_PROTOCOL  *Instance\r
+  )\r
+{\r
+  DHCP_SERVICE  *DhcpSb;\r
+  EFI_STATUS    Status;\r
+  VOID          *Udp4;\r
+\r
+  ASSERT (Instance->Token != NULL);\r
+\r
+  DhcpSb          = Instance->Service;\r
+  Instance->UdpIo = UdpIoCreateIo (\r
+                      DhcpSb->Controller,\r
+                      DhcpSb->Image,\r
+                      Dhcp4InstanceConfigUdpIo,\r
+                      UDP_IO_UDP4_VERSION,\r
+                      Instance\r
+                      );\r
+  if (Instance->UdpIo == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  } else {\r
+    Status = gBS->OpenProtocol (\r
+                    Instance->UdpIo->UdpHandle,\r
+                    &gEfiUdp4ProtocolGuid,\r
+                    (VOID **) &Udp4,\r
+                    Instance->Service->Image,\r
+                    Instance->Handle,\r
+                    EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      UdpIoFreeIo (Instance->UdpIo);\r
+      Instance->UdpIo = NULL;\r
+    }\r
+    return Status;\r
+  }\r
+}\r
+\r
+/**\r
+  Callback of Dhcp packet. Does nothing.\r
+\r
+  @param Arg           The context.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+DhcpDummyExtFree (\r
+  IN VOID                   *Arg\r
+  )\r
+{\r
+}\r
+\r
+/**\r
+  Callback of UdpIoRecvDatagram() that handles a Dhcp4 packet.\r
+\r
+  Only BOOTP responses will be handled that correspond to the Xid of the request\r
+  sent out. The packet will be queued to the response queue.\r
+\r
+  @param UdpPacket        The Dhcp4 packet.\r
+  @param EndPoint         Udp4 address pair.\r
+  @param IoStatus         Status of the input.\r
+  @param Context          Extra info for the input.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+PxeDhcpInput (\r
+  NET_BUF                   *UdpPacket,\r
+  UDP_END_POINT             *EndPoint,\r
+  EFI_STATUS                IoStatus,\r
+  VOID                      *Context\r
+  )\r
+{\r
+  DHCP_PROTOCOL                     *Instance;\r
+  EFI_DHCP4_HEADER                  *Head;\r
+  NET_BUF                           *Wrap;\r
+  EFI_DHCP4_PACKET                  *Packet;\r
+  EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN  *Token;\r
+  UINT32                            Len;\r
+  EFI_STATUS                        Status;\r
+\r
+  Wrap     = NULL;\r
+  Instance = (DHCP_PROTOCOL *) Context;\r
+  Token    = Instance->Token;\r
+\r
+  //\r
+  // Don't restart receive if error occurs or DHCP is destroyed.\r
+  //\r
+  if (EFI_ERROR (IoStatus)) {\r
+    return ;\r
+  }\r
+\r
+  ASSERT (UdpPacket != NULL);\r
+\r
+  //\r
+  // Validate the packet received\r
+  //\r
+  if (UdpPacket->TotalSize < sizeof (EFI_DHCP4_HEADER)) {\r
+    goto RESTART;\r
+  }\r
+\r
+  //\r
+  // Copy the DHCP message to a continuous memory block, make the buffer size\r
+  // of the EFI_DHCP4_PACKET a multiple of 4-byte.\r
+  //\r
+  Len  = NET_ROUNDUP (sizeof (EFI_DHCP4_PACKET) + UdpPacket->TotalSize - sizeof (EFI_DHCP4_HEADER), 4);\r
+  Wrap = NetbufAlloc (Len);\r
+  if (Wrap == NULL) {\r
+    goto RESTART;\r
+  }\r
+\r
+  Packet         = (EFI_DHCP4_PACKET *) NetbufAllocSpace (Wrap, Len, NET_BUF_TAIL);\r
+  ASSERT (Packet != NULL);\r
+\r
+  Packet->Size   = Len;\r
+  Head           = &Packet->Dhcp4.Header;\r
+  Packet->Length = NetbufCopy (UdpPacket, 0, UdpPacket->TotalSize, (UINT8 *) Head);\r
+\r
+  if (Packet->Length != UdpPacket->TotalSize) {\r
+    goto RESTART;\r
+  }\r
+\r
+  //\r
+  // Is this packet the answer to our packet?\r
+  //\r
+  if ((Head->OpCode != BOOTP_REPLY) ||\r
+      (Head->Xid != Token->Packet->Dhcp4.Header.Xid) ||\r
+      (CompareMem (&Token->Packet->Dhcp4.Header.ClientHwAddr[0], Head->ClientHwAddr, Head->HwAddrLen) != 0)) {\r
+    goto RESTART;\r
+  }\r
+\r
+  //\r
+  // Validate the options and retrieve the interested options\r
+  //\r
+  if ((Packet->Length > sizeof (EFI_DHCP4_HEADER) + sizeof (UINT32)) &&\r
+      (Packet->Dhcp4.Magik == DHCP_OPTION_MAGIC) &&\r
+      EFI_ERROR (DhcpValidateOptions (Packet, NULL))) {\r
+\r
+    goto RESTART;\r
+  }\r
+\r
+  //\r
+  // Keep this packet in the ResponseQueue.\r
+  //\r
+  NET_GET_REF (Wrap);\r
+  NetbufQueAppend (&Instance->ResponseQueue, Wrap);\r
+\r
+RESTART:\r
+\r
+  NetbufFree (UdpPacket);\r
+\r
+  if (Wrap != NULL) {\r
+    NetbufFree (Wrap);\r
+  }\r
+\r
+  Status = UdpIoRecvDatagram (Instance->UdpIo, PxeDhcpInput, Instance, 0);\r
+  if (EFI_ERROR (Status)) {\r
+    PxeDhcpDone (Instance);\r
+  }\r
+}\r
+\r
+/**\r
+  Complete a Dhcp4 transaction and signal the upper layer.\r
+\r
+  @param Instance      Dhcp4 instance.\r
+\r
+**/\r
+VOID\r
+PxeDhcpDone (\r
+  IN DHCP_PROTOCOL  *Instance\r
+  )\r
+{\r
+  EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN  *Token;\r
+\r
+  Token = Instance->Token;\r
+\r
+  Token->ResponseCount = Instance->ResponseQueue.BufNum;\r
+  if (Token->ResponseCount != 0) {\r
+    Token->ResponseList = (EFI_DHCP4_PACKET *) AllocatePool (Instance->ResponseQueue.BufSize);\r
+    if (Token->ResponseList == NULL) {\r
+      Token->Status = EFI_OUT_OF_RESOURCES;\r
+      goto SIGNAL_USER;\r
+    }\r
+\r
+    //\r
+    // Copy the received DHCP responses.\r
+    //\r
+    NetbufQueCopy (&Instance->ResponseQueue, 0, Instance->ResponseQueue.BufSize, (UINT8 *) Token->ResponseList);\r
+    Token->Status = EFI_SUCCESS;\r
+  } else {\r
+    Token->ResponseList = NULL;\r
+    Token->Status       = EFI_TIMEOUT;\r
+  }\r
+\r
+SIGNAL_USER:\r
+  //\r
+  // Clean up the resources dedicated for this transmit receive transaction.\r
+  //\r
+  NetbufQueFlush (&Instance->ResponseQueue);\r
+  UdpIoCleanIo (Instance->UdpIo);\r
+  gBS->CloseProtocol (\r
+         Instance->UdpIo->UdpHandle,\r
+         &gEfiUdp4ProtocolGuid,\r
+         Instance->Service->Image,\r
+         Instance->Handle\r
+         );\r
+  UdpIoFreeIo (Instance->UdpIo);\r
+  Instance->UdpIo = NULL;\r
+  Instance->Token = NULL;\r
+\r
+  if (Token->CompletionEvent != NULL) {\r
+    gBS->SignalEvent (Token->CompletionEvent);\r
+  }\r
+}\r
+\r
 \r
 /**\r
-  Transmit and receive a packet through this DHCP service.\r
-  This is unsupported.\r
+  Transmits a DHCP formatted packet and optionally waits for responses.\r
+\r
+  The TransmitReceive() function is used to transmit a DHCP packet and optionally\r
+  wait for the response from servers. This function does not change the state of\r
+  the EFI DHCPv4 Protocol driver and thus can be used at any time.\r
 \r
-  @param  This                   The DHCP protocol instance\r
-  @param  Token                  The transmit and receive instance\r
+  @param[in]  This    Pointer to the EFI_DHCP4_PROTOCOL instance.\r
+  @param[in]  Token   Pointer to the EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN structure.\r
 \r
-  @retval EFI_UNSUPPORTED        It always returns unsupported.\r
+  @retval EFI_SUCCESS           The packet was successfully queued for transmission.\r
+  @retval EFI_INVALID_PARAMETER Some parameter is NULL.\r
+  @retval EFI_NOT_READY         The previous call to this function has not finished yet. Try to call\r
+                                this function after collection process completes.\r
+  @retval EFI_NO_MAPPING        The default station address is not available yet.\r
+  @retval EFI_OUT_OF_RESOURCES  Required system resources could not be allocated.\r
+  @retval Others                Some other unexpected error occurred.\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 EFIAPI\r
 EfiDhcp4TransmitReceive (\r
@@ -785,10 +1501,170 @@ EfiDhcp4TransmitReceive (
   IN EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN  *Token\r
   )\r
 {\r
+  DHCP_PROTOCOL  *Instance;\r
+  EFI_TPL        OldTpl;\r
+  EFI_STATUS     Status;\r
+  NET_FRAGMENT   Frag;\r
+  NET_BUF        *Wrap;\r
+  UDP_END_POINT  EndPoint;\r
+  IP4_ADDR       Ip;\r
+  DHCP_SERVICE   *DhcpSb;\r
+  EFI_IP_ADDRESS Gateway;\r
+  IP4_ADDR       ClientAddr;\r
+\r
+  if ((This == NULL) || (Token == NULL) || (Token->Packet == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Instance = DHCP_INSTANCE_FROM_THIS (This);\r
+  DhcpSb   = Instance->Service;\r
+\r
+  if (Instance->Token != NULL) {\r
+    //\r
+    // The previous call to TransmitReceive is not finished.\r
+    //\r
+    return EFI_NOT_READY;\r
+  }\r
+\r
+  if ((Token->Packet->Dhcp4.Magik != DHCP_OPTION_MAGIC)                   ||\r
+      (NTOHL (Token->Packet->Dhcp4.Header.Xid) == Instance->Service->Xid) ||\r
+      (Token->TimeoutValue == 0)                                          ||\r
+      ((Token->ListenPointCount != 0) && (Token->ListenPoints == NULL))   ||\r
+      EFI_ERROR (DhcpValidateOptions (Token->Packet, NULL))               ||\r
+      EFI_IP4_EQUAL (&Token->RemoteAddress, &mZeroIp4Addr)\r
+      ) {\r
+    //\r
+    // The DHCP packet isn't well-formed, the Transaction ID is already used,\r
+    // the timeout value is zero, the ListenPoint is invalid, or the\r
+    // RemoteAddress is zero.\r
+    //\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  ClientAddr = EFI_NTOHL (Token->Packet->Dhcp4.Header.ClientAddr);\r
+\r
+  if (ClientAddr == 0) {\r
+    return EFI_NO_MAPPING;\r
+  }\r
+\r
+  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
+\r
+  //\r
+  // Save the token and the timeout value.\r
+  //\r
+  Instance->Token   = Token;\r
+  Instance->Timeout = Token->TimeoutValue;\r
+\r
+  //\r
+  // Create a UDP IO for this transmit receive transaction.\r
+  //\r
+  Status = Dhcp4InstanceCreateUdpIo (Instance);\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_ERROR;\r
+  }\r
+\r
+  //\r
+  // Save the Client Address is sent out\r
+  //\r
+  CopyMem (\r
+    &DhcpSb->ClientAddressSendOut[0],\r
+    &Token->Packet->Dhcp4.Header.ClientHwAddr[0],\r
+    Token->Packet->Dhcp4.Header.HwAddrLen\r
+    );\r
+\r
+  //\r
+  // Wrap the DHCP packet into a net buffer.\r
+  //\r
+  Frag.Bulk = (UINT8 *) &Token->Packet->Dhcp4;\r
+  Frag.Len  = Token->Packet->Length;\r
+  Wrap      = NetbufFromExt (&Frag, 1, 0, 0, DhcpDummyExtFree, NULL);\r
+  if (Wrap == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto ON_ERROR;\r
+  }\r
+\r
+  //\r
+  // Set the local address and local port to ZERO.\r
+  //\r
+  ZeroMem (&EndPoint, sizeof (UDP_END_POINT));\r
+\r
+  //\r
+  // Set the destination address and destination port.\r
+  //\r
+  CopyMem (&Ip, &Token->RemoteAddress, sizeof (EFI_IPv4_ADDRESS));\r
+  EndPoint.RemoteAddr.Addr[0] = NTOHL (Ip);\r
+\r
+  if (Token->RemotePort == 0) {\r
+    EndPoint.RemotePort = DHCP_SERVER_PORT;\r
+  } else {\r
+    EndPoint.RemotePort = Token->RemotePort;\r
+  }\r
+\r
+  //\r
+  // Get the gateway.\r
+  //\r
+  ZeroMem (&Gateway, sizeof (Gateway));\r
+  if (!IP4_NET_EQUAL (ClientAddr, EndPoint.RemoteAddr.Addr[0], DhcpSb->Netmask)) {\r
+    CopyMem (&Gateway.v4, &Token->GatewayAddress, sizeof (EFI_IPv4_ADDRESS));\r
+    Gateway.Addr[0] = NTOHL (Gateway.Addr[0]);\r
+  }\r
+\r
+  //\r
+  // Transmit the DHCP packet.\r
+  //\r
+  Status = UdpIoSendDatagram (Instance->UdpIo, Wrap, &EndPoint, &Gateway, DhcpOnPacketSent, NULL);\r
+  if (EFI_ERROR (Status)) {\r
+    NetbufFree (Wrap);\r
+    goto ON_ERROR;\r
+  }\r
+\r
   //\r
-  // This function is for PXE, leave it for now\r
+  // Start to receive the DHCP response.\r
   //\r
-  return EFI_UNSUPPORTED;\r
+  Status = UdpIoRecvDatagram (Instance->UdpIo, PxeDhcpInput, Instance, 0);\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_ERROR;\r
+  }\r
+\r
+ON_ERROR:\r
+\r
+  if (EFI_ERROR (Status) && (Instance->UdpIo != NULL)) {\r
+    UdpIoCleanIo (Instance->UdpIo);\r
+    gBS->CloseProtocol (\r
+           Instance->UdpIo->UdpHandle,\r
+           &gEfiUdp4ProtocolGuid,\r
+           Instance->Service->Image,\r
+           Instance->Handle\r
+           );\r
+    UdpIoFreeIo (Instance->UdpIo);\r
+    Instance->UdpIo = NULL;\r
+    Instance->Token = NULL;\r
+  }\r
+\r
+  gBS->RestoreTPL (OldTpl);\r
+\r
+  if (!EFI_ERROR (Status) && (Token->CompletionEvent == NULL)) {\r
+    //\r
+    // Keep polling until timeout if no error happens and the CompletionEvent\r
+    // is NULL.\r
+    //\r
+    while (TRUE) {\r
+      OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
+      //\r
+      // Raise TPL to protect the UDPIO in instance, in case that DhcpOnTimerTick\r
+      // free it when timeout.\r
+      //\r
+      if (Instance->Timeout > 0) {\r
+        Instance->UdpIo->Protocol.Udp4->Poll (Instance->UdpIo->Protocol.Udp4);\r
+        gBS->RestoreTPL (OldTpl);\r
+      } else {\r
+        gBS->RestoreTPL (OldTpl);\r
+        break;\r
+      }\r
+    }\r
+  }\r
+\r
+  return Status;\r
 }\r
 \r
 \r
@@ -797,15 +1673,14 @@ EfiDhcp4TransmitReceive (
   EFI_DHCP4_PACKET_OPTION array in the DHCP_PARSE_CONTEXT to point\r
   the individual DHCP option in the packet.\r
 \r
-  @param  Tag                    The DHCP option type\r
-  @param  Len                    length of the DHCP option data\r
-  @param  Data                   The DHCP option data\r
-  @param  Context                The context, to pass several parameters in.\r
+  @param[in]  Tag                    The DHCP option type\r
+  @param[in]  Len                    Length of the DHCP option data\r
+  @param[in]  Data                   The DHCP option data\r
+  @param[in]  Context                The context, to pass several parameters in.\r
 \r
   @retval EFI_SUCCESS            It always returns EFI_SUCCESS\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 Dhcp4ParseCheckOption (\r
   IN UINT8                  Tag,\r
@@ -819,13 +1694,13 @@ Dhcp4ParseCheckOption (
   Parse = (DHCP_PARSE_CONTEXT *) Context;\r
   Parse->Index++;\r
 \r
-  if (Parse->Index < Parse->OptionCount) {\r
+  if (Parse->Index <= Parse->OptionCount) {\r
     //\r
-    // Use _CR to get the memory position of EFI_DHCP4_PACKET_OPTION for\r
+    // Use BASE_CR to get the memory position of EFI_DHCP4_PACKET_OPTION for\r
     // the EFI_DHCP4_PACKET_OPTION->Data because DhcpIterateOptions only\r
     // pass in the point to option data.\r
     //\r
-    Parse->Option[Parse->Index - 1] = _CR (Data, EFI_DHCP4_PACKET_OPTION, Data);\r
+    Parse->Option[Parse->Index - 1] = BASE_CR (Data, EFI_DHCP4_PACKET_OPTION, Data);\r
   }\r
 \r
   return EFI_SUCCESS;\r
@@ -833,21 +1708,32 @@ Dhcp4ParseCheckOption (
 \r
 \r
 /**\r
-  Parse the DHCP options in the Packet into the PacketOptionList.\r
-  User should allocate this array of EFI_DHCP4_PACKET_OPTION points.\r
-\r
-  @param  This                   The DHCP protocol instance\r
-  @param  Packet                 The DHCP packet to parse\r
-  @param  OptionCount            On input, the size of the PacketOptionList; On\r
-                                 output,  the actual number of options processed.\r
-  @param  PacketOptionList       The array of EFI_DHCP4_PACKET_OPTION points\r
-\r
-  @retval EFI_INVALID_PARAMETER  The parameters are invalid.\r
-  @retval EFI_BUFFER_TOO_SMALL   A bigger array of points is needed.\r
-  @retval EFI_SUCCESS            The options are parsed.\r
+  Parses the packed DHCP option data.\r
+\r
+  The Parse() function is used to retrieve the option list from a DHCP packet.\r
+  If *OptionCount isn't zero, and there is enough space for all the DHCP options\r
+  in the Packet, each element of PacketOptionList is set to point to somewhere in\r
+  the Packet->Dhcp4.Option where a new DHCP option begins. If RFC3396 is supported,\r
+  the caller should reassemble the parsed DHCP options to get the finial result.\r
+  If *OptionCount is zero or there isn't enough space for all of them, the number\r
+  of DHCP options in the Packet is returned in OptionCount.\r
+\r
+  @param  This             Pointer to the EFI_DHCP4_PROTOCOL instance.\r
+  @param  Packet           Pointer to packet to be parsed.\r
+  @param  OptionCount      On input, the number of entries in the PacketOptionList.\r
+                           On output, the number of entries that were written into the\r
+                           PacketOptionList.\r
+  @param  PacketOptionList List of packet option entries to be filled in. End option or pad\r
+                           options are not included.\r
+\r
+  @retval EFI_SUCCESS           The packet was successfully parsed.\r
+  @retval EFI_INVALID_PARAMETER Some parameter is NULL.\r
+  @retval EFI_BUFFER_TOO_SMALL  One or more of the following conditions is TRUE:\r
+                                1) *OptionCount is smaller than the number of options that\r
+                                were found in the Packet.\r
+                                2) PacketOptionList is NULL.\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 EFIAPI\r
 EfiDhcp4Parse (\r
@@ -878,7 +1764,7 @@ EfiDhcp4Parse (
     return EFI_BUFFER_TOO_SMALL;\r
   }\r
 \r
-  NetZeroMem (PacketOptionList, *OptionCount * sizeof (EFI_DHCP4_PACKET_OPTION *));\r
+  ZeroMem (PacketOptionList, *OptionCount * sizeof (EFI_DHCP4_PACKET_OPTION *));\r
 \r
   Context.Option      = PacketOptionList;\r
   Context.OptionCount = *OptionCount;\r
@@ -899,14 +1785,18 @@ EfiDhcp4Parse (
   return EFI_SUCCESS;\r
 }\r
 \r
-EFI_DHCP4_PROTOCOL  mDhcp4ProtocolTemplate = {\r
-  EfiDhcp4GetModeData,\r
-  EfiDhcp4Configure,\r
-  EfiDhcp4Start,\r
-  EfiDhcp4RenewRebind,\r
-  EfiDhcp4Release,\r
-  EfiDhcp4Stop,\r
-  EfiDhcp4Build,\r
-  EfiDhcp4TransmitReceive,\r
-  EfiDhcp4Parse\r
-};\r
+/**\r
+  Set the elapsed time based on the given instance and the pointer to the\r
+  elapsed time option.\r
+\r
+  @param[in]      Elapsed       The pointer to the position to append.\r
+  @param[in]      Instance      The pointer to the Dhcp4 instance.\r
+**/\r
+VOID\r
+SetElapsedTime (\r
+  IN     UINT16                 *Elapsed,\r
+  IN     DHCP_PROTOCOL          *Instance\r
+  )\r
+{\r
+  WriteUnaligned16 (Elapsed, HTONS(Instance->ElaspedTime));\r
+}\r