]> git.proxmox.com Git - mirror_edk2.git/blobdiff - NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / NetworkPkg / UefiPxeBcDxe / PxeBcDhcp6.c
index 07f1724365f4dc7078d2c833ec4abefe9808ae93..425e0cf8061de1392178a03ef7de211d7457f913 100644 (file)
@@ -2,15 +2,9 @@
   Functions implementation related with DHCPv6 for UefiPxeBc Driver.\r
 \r
   (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>\r
-  Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>\r
 \r
-  This program and the accompanying materials\r
-  are licensed and made available under the terms and conditions of the BSD License\r
-  which accompanies this distribution.  The full text of the license may be found at\r
-  http://opensource.org/licenses/bsd-license.php.\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
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
@@ -21,7 +15,9 @@
 //\r
 //   ALL_DHCP_Relay_Agents_and_Servers address: FF02::1:2\r
 //\r
-EFI_IPv6_ADDRESS   mAllDhcpRelayAndServersAddress = {{0xFF, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2}};\r
+EFI_IPv6_ADDRESS  mAllDhcpRelayAndServersAddress = {\r
+  { 0xFF, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2 }\r
+};\r
 \r
 /**\r
   Parse out a DHCPv6 option by OptTag, and find the position in buffer.\r
@@ -31,40 +27,37 @@ EFI_IPv6_ADDRESS   mAllDhcpRelayAndServersAddress = {{0xFF, 2, 0, 0, 0, 0, 0, 0,
   @param[in]  OptTag        The required option tag.\r
 \r
   @retval     NULL          Failed to parse the required option.\r
-  @retval     Others        The postion of the required option in buffer.\r
+  @retval     Others        The position of the required option in buffer.\r
 \r
 **/\r
 EFI_DHCP6_PACKET_OPTION *\r
 PxeBcParseDhcp6Options (\r
-  IN UINT8                       *Buffer,\r
-  IN UINT32                      Length,\r
-  IN UINT16                      OptTag\r
+  IN UINT8   *Buffer,\r
+  IN UINT32  Length,\r
+  IN UINT16  OptTag\r
   )\r
 {\r
-  EFI_DHCP6_PACKET_OPTION        *Option;\r
-  UINT32                         Offset;\r
+  EFI_DHCP6_PACKET_OPTION  *Option;\r
+  UINT32                   Offset;\r
 \r
-  Option  = (EFI_DHCP6_PACKET_OPTION *) Buffer;\r
-  Offset  = 0;\r
+  Option = (EFI_DHCP6_PACKET_OPTION *)Buffer;\r
+  Offset = 0;\r
 \r
   //\r
   // OpLen and OpCode here are both stored in network order.\r
   //\r
   while (Offset < Length) {\r
-\r
     if (NTOHS (Option->OpCode) == OptTag) {\r
-\r
       return Option;\r
     }\r
 \r
-    Offset += (NTOHS(Option->OpLen) + 4);\r
-    Option  = (EFI_DHCP6_PACKET_OPTION *) (Buffer + Offset);\r
+    Offset += (NTOHS (Option->OpLen) + 4);\r
+    Option  = (EFI_DHCP6_PACKET_OPTION *)(Buffer + Offset);\r
   }\r
 \r
   return NULL;\r
 }\r
 \r
-\r
 /**\r
   Build the options buffer for the DHCPv6 request packet.\r
 \r
@@ -77,68 +70,70 @@ PxeBcParseDhcp6Options (
 **/\r
 UINT32\r
 PxeBcBuildDhcp6Options (\r
-  IN  PXEBC_PRIVATE_DATA           *Private,\r
-  OUT EFI_DHCP6_PACKET_OPTION      **OptList,\r
-  IN  UINT8                        *Buffer\r
+  IN  PXEBC_PRIVATE_DATA       *Private,\r
+  OUT EFI_DHCP6_PACKET_OPTION  **OptList,\r
+  IN  UINT8                    *Buffer\r
   )\r
 {\r
-  PXEBC_DHCP6_OPTION_ENTRY         OptEnt;\r
-  UINT32                           Index;\r
-  UINT16                           Value;\r
+  PXEBC_DHCP6_OPTION_ENTRY  OptEnt;\r
+  UINT32                    Index;\r
+  UINT16                    Value;\r
 \r
-  Index       = 0;\r
-  OptList[0]  = (EFI_DHCP6_PACKET_OPTION *) Buffer;\r
+  Index      = 0;\r
+  OptList[0] = (EFI_DHCP6_PACKET_OPTION *)Buffer;\r
 \r
   //\r
   // Append client option request option\r
   //\r
-  OptList[Index]->OpCode     = HTONS (PXEBC_DHCP6_OPT_ORO);\r
-  OptList[Index]->OpLen      = HTONS (4);\r
-  OptEnt.Oro                 = (PXEBC_DHCP6_OPTION_ORO *) OptList[Index]->Data;\r
-  OptEnt.Oro->OpCode[0]      = HTONS(PXEBC_DHCP6_OPT_BOOT_FILE_URL);\r
-  OptEnt.Oro->OpCode[1]      = HTONS(PXEBC_DHCP6_OPT_BOOT_FILE_PARAM);\r
+  OptList[Index]->OpCode = HTONS (DHCP6_OPT_ORO);\r
+  OptList[Index]->OpLen  = HTONS (8);\r
+  OptEnt.Oro             = (PXEBC_DHCP6_OPTION_ORO *)OptList[Index]->Data;\r
+  OptEnt.Oro->OpCode[0]  = HTONS (DHCP6_OPT_BOOT_FILE_URL);\r
+  OptEnt.Oro->OpCode[1]  = HTONS (DHCP6_OPT_BOOT_FILE_PARAM);\r
+  OptEnt.Oro->OpCode[2]  = HTONS (DHCP6_OPT_DNS_SERVERS);\r
+  OptEnt.Oro->OpCode[3]  = HTONS (DHCP6_OPT_VENDOR_CLASS);\r
   Index++;\r
-  OptList[Index]             = GET_NEXT_DHCP6_OPTION (OptList[Index - 1]);\r
+  OptList[Index] = GET_NEXT_DHCP6_OPTION (OptList[Index - 1]);\r
 \r
   //\r
   // Append client network device interface option\r
   //\r
-  OptList[Index]->OpCode     = HTONS (PXEBC_DHCP6_OPT_UNDI);\r
-  OptList[Index]->OpLen      = HTONS ((UINT16)3);\r
-  OptEnt.Undi                = (PXEBC_DHCP6_OPTION_UNDI *) OptList[Index]->Data;\r
+  OptList[Index]->OpCode = HTONS (DHCP6_OPT_UNDI);\r
+  OptList[Index]->OpLen  = HTONS ((UINT16)3);\r
+  OptEnt.Undi            = (PXEBC_DHCP6_OPTION_UNDI *)OptList[Index]->Data;\r
 \r
   if (Private->Nii != NULL) {\r
-    OptEnt.Undi->Type        = Private->Nii->Type;\r
-    OptEnt.Undi->MajorVer    = Private->Nii->MajorVer;\r
-    OptEnt.Undi->MinorVer    = Private->Nii->MinorVer;\r
+    OptEnt.Undi->Type     = Private->Nii->Type;\r
+    OptEnt.Undi->MajorVer = Private->Nii->MajorVer;\r
+    OptEnt.Undi->MinorVer = Private->Nii->MinorVer;\r
   } else {\r
-    OptEnt.Undi->Type        = DEFAULT_UNDI_TYPE;\r
-    OptEnt.Undi->MajorVer    = DEFAULT_UNDI_MAJOR;\r
-    OptEnt.Undi->MinorVer    = DEFAULT_UNDI_MINOR;\r
+    OptEnt.Undi->Type     = DEFAULT_UNDI_TYPE;\r
+    OptEnt.Undi->MajorVer = DEFAULT_UNDI_MAJOR;\r
+    OptEnt.Undi->MinorVer = DEFAULT_UNDI_MINOR;\r
   }\r
 \r
   Index++;\r
-  OptList[Index]             = GET_NEXT_DHCP6_OPTION (OptList[Index - 1]);\r
+  OptList[Index] = GET_NEXT_DHCP6_OPTION (OptList[Index - 1]);\r
 \r
   //\r
   // Append client system architecture option\r
   //\r
-  OptList[Index]->OpCode     = HTONS (PXEBC_DHCP6_OPT_ARCH);\r
-  OptList[Index]->OpLen      = HTONS ((UINT16) sizeof (PXEBC_DHCP6_OPTION_ARCH));\r
-  OptEnt.Arch                = (PXEBC_DHCP6_OPTION_ARCH *) OptList[Index]->Data;\r
-  Value                      = HTONS (EFI_PXE_CLIENT_SYSTEM_ARCHITECTURE);\r
+  OptList[Index]->OpCode = HTONS (DHCP6_OPT_ARCH);\r
+  OptList[Index]->OpLen  = HTONS ((UINT16)sizeof (PXEBC_DHCP6_OPTION_ARCH));\r
+  OptEnt.Arch            = (PXEBC_DHCP6_OPTION_ARCH *)OptList[Index]->Data;\r
+  Value                  = HTONS (EFI_PXE_CLIENT_SYSTEM_ARCHITECTURE);\r
   CopyMem (&OptEnt.Arch->Type, &Value, sizeof (UINT16));\r
   Index++;\r
-  OptList[Index]             = GET_NEXT_DHCP6_OPTION (OptList[Index - 1]);\r
+  OptList[Index] = GET_NEXT_DHCP6_OPTION (OptList[Index - 1]);\r
 \r
   //\r
   // Append vendor class option to store the PXE class identifier.\r
   //\r
-  OptList[Index]->OpCode       = HTONS (PXEBC_DHCP6_OPT_VENDOR_CLASS);\r
-  OptList[Index]->OpLen        = HTONS ((UINT16) sizeof (PXEBC_DHCP6_OPTION_VENDOR_CLASS));\r
-  OptEnt.VendorClass           = (PXEBC_DHCP6_OPTION_VENDOR_CLASS *) OptList[Index]->Data;\r
+  OptList[Index]->OpCode       = HTONS (DHCP6_OPT_VENDOR_CLASS);\r
+  OptList[Index]->OpLen        = HTONS ((UINT16)sizeof (PXEBC_DHCP6_OPTION_VENDOR_CLASS));\r
+  OptEnt.VendorClass           = (PXEBC_DHCP6_OPTION_VENDOR_CLASS *)OptList[Index]->Data;\r
   OptEnt.VendorClass->Vendor   = HTONL (PXEBC_DHCP6_ENTERPRISE_NUM);\r
-  OptEnt.VendorClass->ClassLen = HTONS ((UINT16) sizeof (PXEBC_CLASS_ID));\r
+  OptEnt.VendorClass->ClassLen = HTONS ((UINT16)sizeof (PXEBC_CLASS_ID));\r
   CopyMem (\r
     &OptEnt.VendorClass->ClassId,\r
     DEFAULT_CLASS_ID_DATA,\r
@@ -173,53 +168,203 @@ PxeBcBuildDhcp6Options (
   return Index;\r
 }\r
 \r
-\r
 /**\r
   Cache the DHCPv6 packet.\r
 \r
   @param[in]  Dst          The pointer to the cache buffer for DHCPv6 packet.\r
   @param[in]  Src          The pointer to the DHCPv6 packet to be cached.\r
 \r
+  @retval     EFI_SUCCESS                Packet is copied.\r
+  @retval     EFI_BUFFER_TOO_SMALL       Cache buffer is not big enough to hold the packet.\r
+\r
 **/\r
-VOID\r
+EFI_STATUS\r
 PxeBcCacheDhcp6Packet (\r
-  IN EFI_DHCP6_PACKET          *Dst,\r
-  IN EFI_DHCP6_PACKET          *Src\r
+  IN EFI_DHCP6_PACKET  *Dst,\r
+  IN EFI_DHCP6_PACKET  *Src\r
   )\r
 {\r
-  ASSERT (Dst->Size >= Src->Length);\r
+  if (Dst->Size < Src->Length) {\r
+    return EFI_BUFFER_TOO_SMALL;\r
+  }\r
 \r
   CopyMem (&Dst->Dhcp6, &Src->Dhcp6, Src->Length);\r
   Dst->Length = Src->Length;\r
-}\r
 \r
+  return EFI_SUCCESS;\r
+}\r
 \r
 /**\r
-  Free all the nodes in the list for boot file.\r
+  Retrieve the boot server address using the EFI_DNS6_PROTOCOL.\r
 \r
-  @param[in]  Head            The pointer to the head of list.\r
+  @param[in]  Private             Pointer to PxeBc private data.\r
+  @param[in]  HostName            Pointer to buffer containing hostname.\r
+  @param[out] IpAddress           On output, pointer to buffer containing IPv6 address.\r
+\r
+  @retval EFI_SUCCESS             Operation succeeded.\r
+  @retval EFI_OUT_OF_RESOURCES    Failed to allocate needed resources.\r
+  @retval EFI_DEVICE_ERROR        An unexpected network error occurred.\r
+  @retval Others                  Other errors as indicated.\r
 \r
 **/\r
-VOID\r
-PxeBcFreeBootFileOption (\r
-  IN LIST_ENTRY               *Head\r
+EFI_STATUS\r
+PxeBcDns6 (\r
+  IN PXEBC_PRIVATE_DATA  *Private,\r
+  IN     CHAR16          *HostName,\r
+  OUT EFI_IPv6_ADDRESS   *IpAddress\r
   )\r
 {\r
-  LIST_ENTRY                  *Entry;\r
-  LIST_ENTRY                  *NextEntry;\r
-  PXEBC_DHCP6_OPTION_NODE     *Node;\r
+  EFI_STATUS                 Status;\r
+  EFI_DNS6_PROTOCOL          *Dns6;\r
+  EFI_DNS6_CONFIG_DATA       Dns6ConfigData;\r
+  EFI_DNS6_COMPLETION_TOKEN  Token;\r
+  EFI_HANDLE                 Dns6Handle;\r
+  EFI_IPv6_ADDRESS           *DnsServerList;\r
+  BOOLEAN                    IsDone;\r
+\r
+  Dns6          = NULL;\r
+  Dns6Handle    = NULL;\r
+  DnsServerList = Private->DnsServer;\r
+  ZeroMem (&Token, sizeof (EFI_DNS6_COMPLETION_TOKEN));\r
+\r
+  //\r
+  // Create a DNSv6 child instance and get the protocol.\r
+  //\r
+  Status = NetLibCreateServiceChild (\r
+             Private->Controller,\r
+             Private->Image,\r
+             &gEfiDns6ServiceBindingProtocolGuid,\r
+             &Dns6Handle\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    goto Exit;\r
+  }\r
 \r
-  NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, Head) {\r
-    Node = NET_LIST_USER_STRUCT (Entry, PXEBC_DHCP6_OPTION_NODE, Link);\r
-    RemoveEntryList (Entry);\r
-    FreePool (Node);\r
+  Status = gBS->OpenProtocol (\r
+                  Dns6Handle,\r
+                  &gEfiDns6ProtocolGuid,\r
+                  (VOID **)&Dns6,\r
+                  Private->Image,\r
+                  Private->Controller,\r
+                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    goto Exit;\r
   }\r
-}\r
 \r
+  //\r
+  // Configure DNS6 instance for the DNS server address and protocol.\r
+  //\r
+  ZeroMem (&Dns6ConfigData, sizeof (EFI_DNS6_CONFIG_DATA));\r
+  Dns6ConfigData.DnsServerCount = 1;\r
+  Dns6ConfigData.DnsServerList  = DnsServerList;\r
+  Dns6ConfigData.EnableDnsCache = TRUE;\r
+  Dns6ConfigData.Protocol       = EFI_IP_PROTO_UDP;\r
+  IP6_COPY_ADDRESS (&Dns6ConfigData.StationIp, &Private->TmpStationIp.v6);\r
+  Status = Dns6->Configure (\r
+                   Dns6,\r
+                   &Dns6ConfigData\r
+                   );\r
+  if (EFI_ERROR (Status)) {\r
+    goto Exit;\r
+  }\r
+\r
+  Token.Status = EFI_NOT_READY;\r
+  IsDone       = FALSE;\r
+  //\r
+  // Create event to set the  IsDone flag when name resolution is finished.\r
+  //\r
+  Status = gBS->CreateEvent (\r
+                  EVT_NOTIFY_SIGNAL,\r
+                  TPL_NOTIFY,\r
+                  PxeBcCommonNotify,\r
+                  &IsDone,\r
+                  &Token.Event\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    goto Exit;\r
+  }\r
+\r
+  //\r
+  // Start asynchronous name resolution.\r
+  //\r
+  Status = Dns6->HostNameToIp (Dns6, HostName, &Token);\r
+  if (EFI_ERROR (Status)) {\r
+    goto Exit;\r
+  }\r
+\r
+  while (!IsDone) {\r
+    Dns6->Poll (Dns6);\r
+  }\r
+\r
+  //\r
+  // Name resolution is done, check result.\r
+  //\r
+  Status = Token.Status;\r
+  if (!EFI_ERROR (Status)) {\r
+    if (Token.RspData.H2AData == NULL) {\r
+      Status = EFI_DEVICE_ERROR;\r
+      goto Exit;\r
+    }\r
+\r
+    if ((Token.RspData.H2AData->IpCount == 0) || (Token.RspData.H2AData->IpList == NULL)) {\r
+      Status = EFI_DEVICE_ERROR;\r
+      goto Exit;\r
+    }\r
+\r
+    //\r
+    // We just return the first IPv6 address from DNS protocol.\r
+    //\r
+    IP6_COPY_ADDRESS (IpAddress, Token.RspData.H2AData->IpList);\r
+    Status = EFI_SUCCESS;\r
+  }\r
+\r
+Exit:\r
+  FreePool (HostName);\r
+\r
+  if (Token.Event != NULL) {\r
+    gBS->CloseEvent (Token.Event);\r
+  }\r
+\r
+  if (Token.RspData.H2AData != NULL) {\r
+    if (Token.RspData.H2AData->IpList != NULL) {\r
+      FreePool (Token.RspData.H2AData->IpList);\r
+    }\r
+\r
+    FreePool (Token.RspData.H2AData);\r
+  }\r
+\r
+  if (Dns6 != NULL) {\r
+    Dns6->Configure (Dns6, NULL);\r
+\r
+    gBS->CloseProtocol (\r
+           Dns6Handle,\r
+           &gEfiDns6ProtocolGuid,\r
+           Private->Image,\r
+           Private->Controller\r
+           );\r
+  }\r
+\r
+  if (Dns6Handle != NULL) {\r
+    NetLibDestroyServiceChild (\r
+      Private->Controller,\r
+      Private->Image,\r
+      &gEfiDns6ServiceBindingProtocolGuid,\r
+      Dns6Handle\r
+      );\r
+  }\r
+\r
+  if (DnsServerList != NULL) {\r
+    FreePool (DnsServerList);\r
+  }\r
+\r
+  return Status;\r
+}\r
 \r
 /**\r
   Parse the Boot File URL option.\r
 \r
+  @param[in]      Private      Pointer to PxeBc private data.\r
   @param[out]     FileName     The pointer to the boot file name.\r
   @param[in, out] SrvAddr      The pointer to the boot server address.\r
   @param[in]      BootFile     The pointer to the boot file URL option data.\r
@@ -227,28 +372,33 @@ PxeBcFreeBootFileOption (
 \r
   @retval EFI_ABORTED     User cancel operation.\r
   @retval EFI_SUCCESS     Selected the boot menu successfully.\r
-  @retval EFI_NOT_READY   Read the input key from the keybroad has not finish.\r
+  @retval EFI_NOT_READY   Read the input key from the keyboard has not finish.\r
 \r
 **/\r
 EFI_STATUS\r
 PxeBcExtractBootFileUrl (\r
-     OUT UINT8               **FileName,\r
-  IN OUT EFI_IPv6_ADDRESS    *SrvAddr,\r
-  IN     CHAR8               *BootFile,\r
-  IN     UINT16              Length\r
+  IN PXEBC_PRIVATE_DATA    *Private,\r
+  OUT UINT8                **FileName,\r
+  IN OUT EFI_IPv6_ADDRESS  *SrvAddr,\r
+  IN     CHAR8             *BootFile,\r
+  IN     UINT16            Length\r
   )\r
 {\r
-  UINT16                     PrefixLen;\r
-  CHAR8                      *BootFileNamePtr;\r
-  CHAR8                      *BootFileName;\r
-  UINT16                     BootFileNameLen;\r
-  CHAR8                      *TmpStr;\r
-  CHAR8                      TmpChar;\r
-  CHAR8                      *ServerAddressOption;\r
-  CHAR8                      *ServerAddress;\r
-  CHAR8                      *ModeStr;\r
-  EFI_STATUS                 Status;\r
-\r
+  UINT16      PrefixLen;\r
+  CHAR8       *BootFileNamePtr;\r
+  CHAR8       *BootFileName;\r
+  UINT16      BootFileNameLen;\r
+  CHAR8       *TmpStr;\r
+  CHAR8       TmpChar;\r
+  CHAR8       *ServerAddressOption;\r
+  CHAR8       *ServerAddress;\r
+  CHAR8       *ModeStr;\r
+  CHAR16      *HostName;\r
+  BOOLEAN     IpExpressedUrl;\r
+  UINTN       Len;\r
+  EFI_STATUS  Status;\r
+\r
+  IpExpressedUrl = TRUE;\r
   //\r
   // The format of the Boot File URL option is:\r
   //\r
@@ -264,22 +414,23 @@ PxeBcExtractBootFileUrl (
   //\r
 \r
   //\r
-  // Based upon RFC 5970 and UEFI 2.3 Errata D specification, bootfile-url format\r
-  // is tftp://[SERVER_ADDRESS]/BOOTFILE_NAME\r
+  // Based upon RFC 5970 and UEFI 2.6, bootfile-url format can be\r
+  // tftp://[SERVER_ADDRESS]/BOOTFILE_NAME or tftp://domain_name/BOOTFILE_NAME\r
   // As an example where the BOOTFILE_NAME is the EFI loader and\r
   // SERVER_ADDRESS is the ASCII encoding of an IPV6 address.\r
   //\r
-  PrefixLen = (UINT16) AsciiStrLen (PXEBC_DHCP6_BOOT_FILE_URL_PREFIX);\r
+  PrefixLen = (UINT16)AsciiStrLen (PXEBC_DHCP6_BOOT_FILE_URL_PREFIX);\r
 \r
-  if (Length <= PrefixLen ||\r
-      CompareMem (BootFile, PXEBC_DHCP6_BOOT_FILE_URL_PREFIX, PrefixLen) != 0) {\r
+  if ((Length <= PrefixLen) ||\r
+      (CompareMem (BootFile, PXEBC_DHCP6_BOOT_FILE_URL_PREFIX, PrefixLen) != 0))\r
+  {\r
     return EFI_NOT_FOUND;\r
   }\r
 \r
   BootFile = BootFile + PrefixLen;\r
-  Length   = (UINT16) (Length - PrefixLen);\r
+  Length   = (UINT16)(Length - PrefixLen);\r
 \r
-  TmpStr = (CHAR8 *) AllocateZeroPool (Length + 1);\r
+  TmpStr = (CHAR8 *)AllocateZeroPool (Length + 1);\r
   if (TmpStr == NULL) {\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
@@ -291,83 +442,121 @@ PxeBcExtractBootFileUrl (
   // Get the part of SERVER_ADDRESS string.\r
   //\r
   ServerAddressOption = TmpStr;\r
-  if (*ServerAddressOption != PXEBC_ADDR_START_DELIMITER) {\r
-    FreePool (TmpStr);\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
+  if (*ServerAddressOption == PXEBC_ADDR_START_DELIMITER) {\r
+    ServerAddressOption++;\r
+    ServerAddress = ServerAddressOption;\r
+    while (*ServerAddress != '\0' && *ServerAddress != PXEBC_ADDR_END_DELIMITER) {\r
+      ServerAddress++;\r
+    }\r
 \r
-  ServerAddressOption ++;\r
-  ServerAddress = ServerAddressOption;\r
-  while (*ServerAddress != '\0' && *ServerAddress != PXEBC_ADDR_END_DELIMITER) {\r
-    ServerAddress++;\r
-  }\r
+    if (*ServerAddress != PXEBC_ADDR_END_DELIMITER) {\r
+      FreePool (TmpStr);\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
 \r
-  if (*ServerAddress != PXEBC_ADDR_END_DELIMITER) {\r
-    FreePool (TmpStr);\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
+    *ServerAddress = '\0';\r
 \r
-  *ServerAddress = '\0';\r
+    //\r
+    // Convert the string of server address to Ipv6 address format and store it.\r
+    //\r
+    Status = NetLibAsciiStrToIp6 (ServerAddressOption, SrvAddr);\r
+    if (EFI_ERROR (Status)) {\r
+      FreePool (TmpStr);\r
+      return Status;\r
+    }\r
+  } else {\r
+    IpExpressedUrl = FALSE;\r
+    ServerAddress  = ServerAddressOption;\r
+    while (*ServerAddress != '\0' && *ServerAddress != PXEBC_TFTP_URL_SEPARATOR) {\r
+      ServerAddress++;\r
+    }\r
 \r
-  //\r
-  // Convert the string of server address to Ipv6 address format and store it.\r
-  //\r
-  Status = NetLibAsciiStrToIp6 (ServerAddressOption, SrvAddr);\r
-  if (EFI_ERROR (Status)) {\r
-    FreePool (TmpStr);\r
-    return Status;\r
+    if (*ServerAddress != PXEBC_TFTP_URL_SEPARATOR) {\r
+      FreePool (TmpStr);\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+\r
+    *ServerAddress = '\0';\r
+\r
+    Len      = AsciiStrSize (ServerAddressOption);\r
+    HostName = AllocateZeroPool (Len * sizeof (CHAR16));\r
+    if (HostName == NULL) {\r
+      FreePool (TmpStr);\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    AsciiStrToUnicodeStrS (\r
+      ServerAddressOption,\r
+      HostName,\r
+      Len\r
+      );\r
+\r
+    //\r
+    // Perform DNS resolution.\r
+    //\r
+    Status = PxeBcDns6 (Private, HostName, SrvAddr);\r
+    if (EFI_ERROR (Status)) {\r
+      FreePool (TmpStr);\r
+      return Status;\r
+    }\r
   }\r
 \r
   //\r
   // Get the part of BOOTFILE_NAME string.\r
   //\r
-  BootFileNamePtr = (CHAR8*)((UINTN)ServerAddress + 1);\r
-  if (*BootFileNamePtr != PXEBC_TFTP_URL_SEPARATOR) {\r
-    FreePool (TmpStr);\r
-    return EFI_INVALID_PARAMETER;\r
+  BootFileNamePtr = (CHAR8 *)((UINTN)ServerAddress + 1);\r
+  if (IpExpressedUrl) {\r
+    if (*BootFileNamePtr != PXEBC_TFTP_URL_SEPARATOR) {\r
+      FreePool (TmpStr);\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+\r
+    ++BootFileNamePtr;\r
   }\r
 \r
-  ++BootFileNamePtr;\r
-  BootFileNameLen = (UINT16)(Length - (UINT16) ((UINTN)BootFileNamePtr - (UINTN)TmpStr) + 1);\r
-  if (BootFileNameLen != 0 || FileName != NULL) {\r
+  BootFileNameLen = (UINT16)(Length - (UINT16)((UINTN)BootFileNamePtr - (UINTN)TmpStr) + 1);\r
+  if ((BootFileNameLen != 0) || (FileName != NULL)) {\r
     //\r
     // Remove trailing mode=octet if present and ignore.  All other modes are\r
     // invalid for netboot6, so reject them.\r
     //\r
     ModeStr = AsciiStrStr (BootFileNamePtr, ";mode=octet");\r
-    if (ModeStr != NULL && *(ModeStr + AsciiStrLen (";mode=octet")) == '\0') {\r
+    if ((ModeStr != NULL) && (*(ModeStr + AsciiStrLen (";mode=octet")) == '\0')) {\r
       *ModeStr = '\0';\r
     } else if (AsciiStrStr (BootFileNamePtr, ";mode=") != NULL) {\r
+      FreePool (TmpStr);\r
       return EFI_INVALID_PARAMETER;\r
     }\r
 \r
     //\r
     // Extract boot file name from URL.\r
     //\r
-    BootFileName = (CHAR8 *) AllocateZeroPool (BootFileNameLen);\r
+    BootFileName = (CHAR8 *)AllocateZeroPool (BootFileNameLen);\r
     if (BootFileName == NULL) {\r
       FreePool (TmpStr);\r
       return EFI_OUT_OF_RESOURCES;\r
     }\r
-    *FileName = (UINT8*) BootFileName;\r
+\r
+    *FileName = (UINT8 *)BootFileName;\r
 \r
     //\r
     // Decode percent-encoding in boot file name.\r
     //\r
     while (*BootFileNamePtr != '\0') {\r
       if (*BootFileNamePtr == '%') {\r
-        TmpChar = *(BootFileNamePtr+ 3);\r
+        TmpChar               = *(BootFileNamePtr+ 3);\r
         *(BootFileNamePtr+ 3) = '\0';\r
-        *BootFileName = (UINT8) AsciiStrHexToUintn ((CHAR8*)(BootFileNamePtr + 1));\r
+        *BootFileName         = (UINT8)AsciiStrHexToUintn ((CHAR8 *)(BootFileNamePtr + 1));\r
         BootFileName++;\r
         *(BootFileNamePtr+ 3) = TmpChar;\r
-        BootFileNamePtr += 3;\r
+        BootFileNamePtr      += 3;\r
       } else {\r
         *BootFileName = *BootFileNamePtr;\r
         BootFileName++;\r
         BootFileNamePtr++;\r
       }\r
     }\r
+\r
     *BootFileName = '\0';\r
   }\r
 \r
@@ -376,7 +565,6 @@ PxeBcExtractBootFileUrl (
   return EFI_SUCCESS;\r
 }\r
 \r
-\r
 /**\r
   Parse the Boot File Parameter option.\r
 \r
@@ -389,14 +577,14 @@ PxeBcExtractBootFileUrl (
 **/\r
 EFI_STATUS\r
 PxeBcExtractBootFileParam (\r
-  IN  CHAR8                  *BootFilePara,\r
-  OUT UINT16                 *BootFileSize\r
+  IN  CHAR8   *BootFilePara,\r
+  OUT UINT16  *BootFileSize\r
   )\r
 {\r
-  UINT16                     Length;\r
-  UINT8                      Index;\r
-  UINT8                      Digit;\r
-  UINT32                     Size;\r
+  UINT16  Length;\r
+  UINT8   Index;\r
+  UINT8   Digit;\r
+  UINT32  Size;\r
 \r
   CopyMem (&Length, BootFilePara, sizeof (UINT16));\r
   Length = NTOHS (Length);\r
@@ -404,7 +592,7 @@ PxeBcExtractBootFileParam (
   //\r
   // The BootFile Size should be 1~5 byte ASCII strings\r
   //\r
-  if (Length < 1 || Length > 5) {\r
+  if ((Length < 1) || (Length > 5)) {\r
     return EFI_NOT_FOUND;\r
   }\r
 \r
@@ -426,11 +614,10 @@ PxeBcExtractBootFileParam (
     return EFI_NOT_FOUND;\r
   }\r
 \r
-  *BootFileSize = (UINT16) Size;\r
+  *BootFileSize = (UINT16)Size;\r
   return EFI_SUCCESS;\r
 }\r
 \r
-\r
 /**\r
   Parse the cached DHCPv6 packet, including all the options.\r
 \r
@@ -445,15 +632,15 @@ PxeBcParseDhcp6Packet (
   IN PXEBC_DHCP6_PACKET_CACHE  *Cache6\r
   )\r
 {\r
-  EFI_DHCP6_PACKET             *Offer;\r
-  EFI_DHCP6_PACKET_OPTION      **Options;\r
-  EFI_DHCP6_PACKET_OPTION      *Option;\r
-  PXEBC_OFFER_TYPE             OfferType;\r
-  BOOLEAN                      IsProxyOffer;\r
-  BOOLEAN                      IsPxeOffer;\r
-  UINT32                       Offset;\r
-  UINT32                       Length;\r
-  UINT32                       EnterpriseNum;\r
+  EFI_DHCP6_PACKET         *Offer;\r
+  EFI_DHCP6_PACKET_OPTION  **Options;\r
+  EFI_DHCP6_PACKET_OPTION  *Option;\r
+  PXEBC_OFFER_TYPE         OfferType;\r
+  BOOLEAN                  IsProxyOffer;\r
+  BOOLEAN                  IsPxeOffer;\r
+  UINT32                   Offset;\r
+  UINT32                   Length;\r
+  UINT32                   EnterpriseNum;\r
 \r
   IsProxyOffer = TRUE;\r
   IsPxeOffer   = FALSE;\r
@@ -462,44 +649,45 @@ PxeBcParseDhcp6Packet (
 \r
   ZeroMem (Cache6->OptList, sizeof (Cache6->OptList));\r
 \r
-  Option  = (EFI_DHCP6_PACKET_OPTION *) (Offer->Dhcp6.Option);\r
-  Offset  = 0;\r
-  Length  = GET_DHCP6_OPTION_SIZE (Offer);\r
+  Option = (EFI_DHCP6_PACKET_OPTION *)(Offer->Dhcp6.Option);\r
+  Offset = 0;\r
+  Length = GET_DHCP6_OPTION_SIZE (Offer);\r
 \r
   //\r
   // OpLen and OpCode here are both stored in network order, since they are from original packet.\r
   //\r
   while (Offset < Length) {\r
-\r
-    if (NTOHS (Option->OpCode) == PXEBC_DHCP6_OPT_IA_NA) {\r
+    if (NTOHS (Option->OpCode) == DHCP6_OPT_IA_NA) {\r
       Options[PXEBC_DHCP6_IDX_IA_NA] = Option;\r
-    } else if (NTOHS (Option->OpCode) == PXEBC_DHCP6_OPT_BOOT_FILE_URL) {\r
+    } else if (NTOHS (Option->OpCode) == DHCP6_OPT_BOOT_FILE_URL) {\r
       //\r
       // The server sends this option to inform the client about an URL to a boot file.\r
       //\r
       Options[PXEBC_DHCP6_IDX_BOOT_FILE_URL] = Option;\r
-    } else if (NTOHS (Option->OpCode) == PXEBC_DHCP6_OPT_BOOT_FILE_PARAM) {\r
+    } else if (NTOHS (Option->OpCode) == DHCP6_OPT_BOOT_FILE_PARAM) {\r
       Options[PXEBC_DHCP6_IDX_BOOT_FILE_PARAM] = Option;\r
-    } else if (NTOHS (Option->OpCode) == PXEBC_DHCP6_OPT_VENDOR_CLASS) {\r
+    } else if (NTOHS (Option->OpCode) == DHCP6_OPT_VENDOR_CLASS) {\r
       Options[PXEBC_DHCP6_IDX_VENDOR_CLASS] = Option;\r
+    } else if (NTOHS (Option->OpCode) == DHCP6_OPT_DNS_SERVERS) {\r
+      Options[PXEBC_DHCP6_IDX_DNS_SERVER] = Option;\r
     }\r
 \r
     Offset += (NTOHS (Option->OpLen) + 4);\r
-    Option  = (EFI_DHCP6_PACKET_OPTION *) (Offer->Dhcp6.Option + Offset);\r
+    Option  = (EFI_DHCP6_PACKET_OPTION *)(Offer->Dhcp6.Option + Offset);\r
   }\r
 \r
   //\r
   // The offer with assigned client address is NOT a proxy offer.\r
-  // An ia_na option, embeded with valid ia_addr option and a status_code of success.\r
+  // An ia_na option, embedded with valid ia_addr option and a status_code of success.\r
   //\r
   Option = Options[PXEBC_DHCP6_IDX_IA_NA];\r
   if (Option != NULL) {\r
     Option = PxeBcParseDhcp6Options (\r
                Option->Data + 12,\r
                NTOHS (Option->OpLen),\r
-               PXEBC_DHCP6_OPT_STATUS_CODE\r
+               DHCP6_OPT_STATUS_CODE\r
                );\r
-    if ((Option != NULL && Option->Data[0] == 0) || (Option == NULL)) {\r
+    if (((Option != NULL) && (Option->Data[0] == 0)) || (Option == NULL)) {\r
       IsProxyOffer = FALSE;\r
     }\r
   }\r
@@ -508,12 +696,13 @@ PxeBcParseDhcp6Packet (
   // The offer with "PXEClient" is a pxe offer.\r
   //\r
   Option        = Options[PXEBC_DHCP6_IDX_VENDOR_CLASS];\r
-  EnterpriseNum = HTONL(PXEBC_DHCP6_ENTERPRISE_NUM);\r
+  EnterpriseNum = HTONL (PXEBC_DHCP6_ENTERPRISE_NUM);\r
 \r
-  if (Option != NULL &&\r
-      NTOHS(Option->OpLen) >= 13 &&\r
-      CompareMem (Option->Data, &EnterpriseNum, sizeof (UINT32)) == 0 &&\r
-      CompareMem (&Option->Data[6], DEFAULT_CLASS_ID_DATA, 9) == 0) {\r
+  if ((Option != NULL) &&\r
+      (NTOHS (Option->OpLen) >= 13) &&\r
+      (CompareMem (Option->Data, &EnterpriseNum, sizeof (UINT32)) == 0) &&\r
+      (CompareMem (&Option->Data[6], DEFAULT_CLASS_ID_DATA, 9) == 0))\r
+  {\r
     IsPxeOffer = TRUE;\r
   }\r
 \r
@@ -537,7 +726,6 @@ PxeBcParseDhcp6Packet (
   return EFI_SUCCESS;\r
 }\r
 \r
-\r
 /**\r
   Cache the DHCPv6 ack packet, and parse it on demand.\r
 \r
@@ -545,19 +733,26 @@ PxeBcParseDhcp6Packet (
   @param[in]  Ack                 The pointer to the DHCPv6 ack packet.\r
   @param[in]  Verified            If TRUE, parse the ACK packet and store info into mode data.\r
 \r
+  @retval     EFI_SUCCESS                Cache and parse the packet successfully.\r
+  @retval     EFI_BUFFER_TOO_SMALL       Cache buffer is not big enough to hold the packet.\r
+\r
 **/\r
-VOID\r
+EFI_STATUS\r
 PxeBcCopyDhcp6Ack (\r
-  IN PXEBC_PRIVATE_DATA   *Private,\r
-  IN EFI_DHCP6_PACKET     *Ack,\r
-  IN BOOLEAN              Verified\r
+  IN PXEBC_PRIVATE_DATA  *Private,\r
+  IN EFI_DHCP6_PACKET    *Ack,\r
+  IN BOOLEAN             Verified\r
   )\r
 {\r
   EFI_PXE_BASE_CODE_MODE  *Mode;\r
+  EFI_STATUS              Status;\r
 \r
   Mode = Private->PxeBc.Mode;\r
 \r
-  PxeBcCacheDhcp6Packet (&Private->DhcpAck.Dhcp6.Packet.Ack, Ack);\r
+  Status = PxeBcCacheDhcp6Packet (&Private->DhcpAck.Dhcp6.Packet.Ack, Ack);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
 \r
   if (Verified) {\r
     //\r
@@ -567,8 +762,9 @@ PxeBcCopyDhcp6Ack (
     CopyMem (&Mode->DhcpAck.Dhcpv6, &Ack->Dhcp6, Ack->Length);\r
     Mode->DhcpAckReceived = TRUE;\r
   }\r
-}\r
 \r
+  return EFI_SUCCESS;\r
+}\r
 \r
 /**\r
   Cache the DHCPv6 proxy offer packet according to the received order.\r
@@ -576,15 +772,19 @@ PxeBcCopyDhcp6Ack (
   @param[in]  Private               The pointer to PxeBc private data.\r
   @param[in]  OfferIndex            The received order of offer packets.\r
 \r
+  @retval     EFI_SUCCESS                Cache and parse the packet successfully.\r
+  @retval     EFI_BUFFER_TOO_SMALL       Cache buffer is not big enough to hold the packet.\r
+\r
 **/\r
-VOID\r
+EFI_STATUS\r
 PxeBcCopyDhcp6Proxy (\r
-  IN PXEBC_PRIVATE_DATA     *Private,\r
-  IN UINT32                 OfferIndex\r
+  IN PXEBC_PRIVATE_DATA  *Private,\r
+  IN UINT32              OfferIndex\r
   )\r
 {\r
-  EFI_PXE_BASE_CODE_MODE    *Mode;\r
-  EFI_DHCP6_PACKET          *Offer;\r
+  EFI_PXE_BASE_CODE_MODE  *Mode;\r
+  EFI_DHCP6_PACKET        *Offer;\r
+  EFI_STATUS              Status;\r
 \r
   ASSERT (OfferIndex < Private->OfferNum);\r
   ASSERT (OfferIndex < PXEBC_OFFER_MAX_NUM);\r
@@ -595,7 +795,11 @@ PxeBcCopyDhcp6Proxy (
   //\r
   // Cache the proxy offer packet and parse it.\r
   //\r
-  PxeBcCacheDhcp6Packet (&Private->ProxyOffer.Dhcp6.Packet.Offer, Offer);\r
+  Status = PxeBcCacheDhcp6Packet (&Private->ProxyOffer.Dhcp6.Packet.Offer, Offer);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
   PxeBcParseDhcp6Packet (&Private->ProxyOffer.Dhcp6);\r
 \r
   //\r
@@ -603,6 +807,8 @@ PxeBcCopyDhcp6Proxy (
   //\r
   CopyMem (&Mode->ProxyOffer.Dhcpv6, &Offer->Dhcp6, Offer->Length);\r
   Mode->ProxyOfferReceived = TRUE;\r
+\r
+  return EFI_SUCCESS;\r
 }\r
 \r
 /**\r
@@ -618,33 +824,33 @@ PxeBcCopyDhcp6Proxy (
 **/\r
 UINT8 *\r
 PxeBcDhcp6SeekOption (\r
-  IN UINT8           *Buf,\r
-  IN UINT32          SeekLen,\r
-  IN UINT16          OptType\r
+  IN UINT8   *Buf,\r
+  IN UINT32  SeekLen,\r
+  IN UINT16  OptType\r
   )\r
 {\r
-  UINT8              *Cursor;\r
-  UINT8              *Option;\r
-  UINT16             DataLen;\r
-  UINT16             OpCode;\r
+  UINT8   *Cursor;\r
+  UINT8   *Option;\r
+  UINT16  DataLen;\r
+  UINT16  OpCode;\r
 \r
   Option = NULL;\r
   Cursor = Buf;\r
 \r
   while (Cursor < Buf + SeekLen) {\r
-    OpCode = ReadUnaligned16 ((UINT16 *) Cursor);\r
+    OpCode = ReadUnaligned16 ((UINT16 *)Cursor);\r
     if (OpCode == HTONS (OptType)) {\r
       Option = Cursor;\r
       break;\r
     }\r
-    DataLen = NTOHS (ReadUnaligned16 ((UINT16 *) (Cursor + 2)));\r
+\r
+    DataLen = NTOHS (ReadUnaligned16 ((UINT16 *)(Cursor + 2)));\r
     Cursor += (DataLen + 4);\r
   }\r
 \r
   return Option;\r
 }\r
 \r
-\r
 /**\r
   Build and send out the request packet for the bootfile, and parse the reply.\r
 \r
@@ -659,34 +865,34 @@ PxeBcDhcp6SeekOption (
 **/\r
 EFI_STATUS\r
 PxeBcRequestBootService (\r
-  IN  PXEBC_PRIVATE_DATA              *Private,\r
-  IN  UINT32                          Index\r
+  IN  PXEBC_PRIVATE_DATA  *Private,\r
+  IN  UINT32              Index\r
   )\r
 {\r
-  EFI_PXE_BASE_CODE_UDP_PORT          SrcPort;\r
-  EFI_PXE_BASE_CODE_UDP_PORT          DestPort;\r
-  EFI_PXE_BASE_CODE_PROTOCOL          *PxeBc;\r
-  EFI_PXE_BASE_CODE_DHCPV6_PACKET     *Discover;\r
-  UINTN                               DiscoverLen;\r
-  EFI_DHCP6_PACKET                    *Request;\r
-  UINTN                               RequestLen;\r
-  EFI_DHCP6_PACKET                    *Reply;\r
-  UINT8                               *RequestOpt;\r
-  UINT8                               *DiscoverOpt;\r
-  UINTN                               ReadSize;\r
-  UINT16                              OpFlags;\r
-  UINT16                              OpCode;\r
-  UINT16                              OpLen;\r
-  EFI_STATUS                          Status;\r
-  EFI_DHCP6_PACKET                    *ProxyOffer;\r
-  UINT8                               *Option;\r
-\r
-  PxeBc       = &Private->PxeBc;\r
-  Request     = Private->Dhcp6Request;\r
-  ProxyOffer = &Private->OfferBuffer[Index].Dhcp6.Packet.Offer;\r
-  SrcPort     = PXEBC_BS_DISCOVER_PORT;\r
-  DestPort    = PXEBC_BS_DISCOVER_PORT;\r
-  OpFlags     = 0;\r
+  EFI_PXE_BASE_CODE_UDP_PORT       SrcPort;\r
+  EFI_PXE_BASE_CODE_UDP_PORT       DestPort;\r
+  EFI_PXE_BASE_CODE_PROTOCOL       *PxeBc;\r
+  EFI_PXE_BASE_CODE_DHCPV6_PACKET  *Discover;\r
+  UINTN                            DiscoverLen;\r
+  EFI_DHCP6_PACKET                 *Request;\r
+  UINTN                            RequestLen;\r
+  EFI_DHCP6_PACKET                 *Reply;\r
+  UINT8                            *RequestOpt;\r
+  UINT8                            *DiscoverOpt;\r
+  UINTN                            ReadSize;\r
+  UINT16                           OpFlags;\r
+  UINT16                           OpCode;\r
+  UINT16                           OpLen;\r
+  EFI_STATUS                       Status;\r
+  EFI_DHCP6_PACKET                 *IndexOffer;\r
+  UINT8                            *Option;\r
+\r
+  PxeBc      = &Private->PxeBc;\r
+  Request    = Private->Dhcp6Request;\r
+  IndexOffer = &Private->OfferBuffer[Index].Dhcp6.Packet.Offer;\r
+  SrcPort    = PXEBC_BS_DISCOVER_PORT;\r
+  DestPort   = PXEBC_BS_DISCOVER_PORT;\r
+  OpFlags    = 0;\r
 \r
   if (Request == NULL) {\r
     return EFI_DEVICE_ERROR;\r
@@ -700,7 +906,7 @@ PxeBcRequestBootService (
   //\r
   // Build the request packet by the cached request packet before.\r
   //\r
-  Discover->TransactionId = ProxyOffer->Dhcp6.Header.TransactionId;\r
+  Discover->TransactionId = IndexOffer->Dhcp6.Header.TransactionId;\r
   Discover->MessageType   = Request->Dhcp6.Header.MessageType;\r
   RequestOpt              = Request->Dhcp6.Option;\r
   DiscoverOpt             = Discover->DhcpOptions;\r
@@ -710,30 +916,33 @@ PxeBcRequestBootService (
   //\r
   // Find Server ID Option from ProxyOffer.\r
   //\r
-  Option = PxeBcDhcp6SeekOption (\r
-             ProxyOffer->Dhcp6.Option,\r
-             ProxyOffer->Length - 4,\r
-             PXEBC_DHCP6_OPT_SERVER_ID\r
-             );\r
-  if (Option == NULL) {\r
-    return EFI_NOT_FOUND;\r
+  if (Private->OfferBuffer[Index].Dhcp6.OfferType == PxeOfferTypeProxyBinl) {\r
+    Option = PxeBcDhcp6SeekOption (\r
+               IndexOffer->Dhcp6.Option,\r
+               IndexOffer->Length - 4,\r
+               DHCP6_OPT_SERVER_ID\r
+               );\r
+    if (Option == NULL) {\r
+      return EFI_NOT_FOUND;\r
+    }\r
+\r
+    //\r
+    // Add Server ID Option.\r
+    //\r
+    OpLen = NTOHS (((EFI_DHCP6_PACKET_OPTION *)Option)->OpLen);\r
+    CopyMem (DiscoverOpt, Option, OpLen + 4);\r
+    DiscoverOpt += (OpLen + 4);\r
+    DiscoverLen += (OpLen + 4);\r
   }\r
-  \r
-  //\r
-  // Add Server ID Option.\r
-  //\r
-  OpLen = NTOHS (((EFI_DHCP6_PACKET_OPTION *) Option)->OpLen);\r
-  CopyMem (DiscoverOpt, Option, OpLen + 4);\r
-  DiscoverOpt += (OpLen + 4);\r
-  DiscoverLen += (OpLen + 4);\r
 \r
   while (RequestLen < Request->Length) {\r
-    OpCode = NTOHS (((EFI_DHCP6_PACKET_OPTION *) RequestOpt)->OpCode);\r
-    OpLen  = NTOHS (((EFI_DHCP6_PACKET_OPTION *) RequestOpt)->OpLen);\r
-    if (OpCode != EFI_DHCP6_IA_TYPE_NA &&\r
-        OpCode != EFI_DHCP6_IA_TYPE_TA &&\r
-        OpCode != PXEBC_DHCP6_OPT_SERVER_ID\r
-        ) {\r
+    OpCode = NTOHS (((EFI_DHCP6_PACKET_OPTION *)RequestOpt)->OpCode);\r
+    OpLen  = NTOHS (((EFI_DHCP6_PACKET_OPTION *)RequestOpt)->OpLen);\r
+    if ((OpCode != EFI_DHCP6_IA_TYPE_NA) &&\r
+        (OpCode != EFI_DHCP6_IA_TYPE_TA) &&\r
+        (OpCode != DHCP6_OPT_SERVER_ID)\r
+        )\r
+    {\r
       //\r
       // Copy all the options except IA option and Server ID\r
       //\r
@@ -741,22 +950,23 @@ PxeBcRequestBootService (
       DiscoverOpt += (OpLen + 4);\r
       DiscoverLen += (OpLen + 4);\r
     }\r
+\r
     RequestOpt += (OpLen + 4);\r
     RequestLen += (OpLen + 4);\r
   }\r
 \r
   //\r
-  // Update Elapsed option in the package \r
+  // Update Elapsed option in the package\r
   //\r
   Option = PxeBcDhcp6SeekOption (\r
              Discover->DhcpOptions,\r
              (UINT32)(RequestLen - 4),\r
-             PXEBC_DHCP6_OPT_ELAPSED_TIME\r
+             DHCP6_OPT_ELAPSED_TIME\r
              );\r
   if (Option != NULL) {\r
     CalcElapsedTime (Private);\r
-    WriteUnaligned16 ((UINT16*)(Option + 4), HTONS((UINT16) Private->ElapsedTime));\r
-  }  \r
+    WriteUnaligned16 ((UINT16 *)(Option + 4), HTONS ((UINT16)Private->ElapsedTime));\r
+  }\r
 \r
   Status = PxeBc->UdpWrite (\r
                     PxeBc,\r
@@ -769,39 +979,39 @@ PxeBcRequestBootService (
                     NULL,\r
                     NULL,\r
                     &DiscoverLen,\r
-                    (VOID *) Discover\r
+                    (VOID *)Discover\r
                     );\r
 \r
   if (EFI_ERROR (Status)) {\r
-    return Status;\r
+    goto ON_ERROR;\r
   }\r
 \r
   //\r
   // Cache the right PXE reply packet here, set valid flag later.\r
   // Especially for PXE discover packet, store it into mode data here.\r
   //\r
-  Reply = &Private->ProxyOffer.Dhcp6.Packet.Offer;\r
-  ReadSize = (UINTN) Reply->Size;\r
+  Reply    = &Private->ProxyOffer.Dhcp6.Packet.Offer;\r
+  ReadSize = (UINTN)Reply->Size;\r
 \r
   //\r
   // Start Udp6Read instance\r
   //\r
   Status = Private->Udp6Read->Configure (Private->Udp6Read, &Private->Udp6CfgData);\r
   if (EFI_ERROR (Status)) {\r
-    return Status;\r
+    goto ON_ERROR;\r
   }\r
-    \r
+\r
   Status = PxeBc->UdpRead (\r
                     PxeBc,\r
-                    EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP,\r
-                    &Private->StationIp,\r
+                    EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP | EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_IP,\r
+                    NULL,\r
                     &SrcPort,\r
                     &Private->ServerIp,\r
                     &DestPort,\r
                     NULL,\r
                     NULL,\r
                     &ReadSize,\r
-                    (VOID *) &Reply->Dhcp6\r
+                    (VOID *)&Reply->Dhcp6\r
                     );\r
   //\r
   // Stop Udp6Read instance\r
@@ -809,17 +1019,23 @@ PxeBcRequestBootService (
   Private->Udp6Read->Configure (Private->Udp6Read, NULL);\r
 \r
   if (EFI_ERROR (Status)) {\r
-    return Status;\r
+    goto ON_ERROR;\r
   }\r
 \r
   //\r
   // Update length\r
   //\r
-  Reply->Length = (UINT32) ReadSize;\r
+  Reply->Length = (UINT32)ReadSize;\r
 \r
   return EFI_SUCCESS;\r
-}\r
 \r
+ON_ERROR:\r
+  if (Discover != NULL) {\r
+    FreePool (Discover);\r
+  }\r
+\r
+  return Status;\r
+}\r
 \r
 /**\r
   Retry to request bootfile name by the BINL offer.\r
@@ -843,13 +1059,15 @@ PxeBcRetryDhcp6Binl (
   EFI_STATUS                Status;\r
 \r
   ASSERT (Index < PXEBC_OFFER_MAX_NUM);\r
-  ASSERT (Private->OfferBuffer[Index].Dhcp6.OfferType == PxeOfferTypeDhcpBinl ||\r
-          Private->OfferBuffer[Index].Dhcp6.OfferType == PxeOfferTypeProxyBinl);\r
+  ASSERT (\r
+    Private->OfferBuffer[Index].Dhcp6.OfferType == PxeOfferTypeDhcpBinl ||\r
+    Private->OfferBuffer[Index].Dhcp6.OfferType == PxeOfferTypeProxyBinl\r
+    );\r
 \r
   Mode                  = Private->PxeBc.Mode;\r
   Private->IsDoDiscover = FALSE;\r
   Offer                 = &Private->OfferBuffer[Index].Dhcp6;\r
-  if (Offer->OfferType == PxeOfferTypeDhcpBinl) {\r
+  if (Offer->OptList[PXEBC_DHCP6_IDX_BOOT_FILE_URL] == NULL) {\r
     //\r
     // There is no BootFileUrl option in dhcp6 offer, so use servers multi-cast address instead.\r
     //\r
@@ -864,9 +1082,10 @@ PxeBcRetryDhcp6Binl (
     // Parse out the next server address from the last offer, and store it\r
     //\r
     Status = PxeBcExtractBootFileUrl (\r
+               Private,\r
                &Private->BootFileName,\r
                &Private->ServerIp.v6,\r
-               (CHAR8 *) (Offer->OptList[PXEBC_DHCP6_IDX_BOOT_FILE_URL]->Data),\r
+               (CHAR8 *)(Offer->OptList[PXEBC_DHCP6_IDX_BOOT_FILE_URL]->Data),\r
                NTOHS (Offer->OptList[PXEBC_DHCP6_IDX_BOOT_FILE_URL]->OpLen)\r
                );\r
     if (EFI_ERROR (Status)) {\r
@@ -889,9 +1108,10 @@ PxeBcRetryDhcp6Binl (
     return Status;\r
   }\r
 \r
-  if (Cache6->OfferType != PxeOfferTypeProxyPxe10 &&\r
-      Cache6->OfferType != PxeOfferTypeProxyWfm11a &&\r
-      Cache6->OptList[PXEBC_DHCP6_IDX_BOOT_FILE_URL] == NULL) {\r
+  if ((Cache6->OfferType != PxeOfferTypeProxyPxe10) &&\r
+      (Cache6->OfferType != PxeOfferTypeProxyWfm11a) &&\r
+      (Cache6->OptList[PXEBC_DHCP6_IDX_BOOT_FILE_URL] == NULL))\r
+  {\r
     //\r
     // This BINL ack doesn't have discovery option set or multicast option set\r
     // or bootfile name specified.\r
@@ -909,23 +1129,25 @@ PxeBcRetryDhcp6Binl (
   return EFI_SUCCESS;\r
 }\r
 \r
-\r
 /**\r
   Cache all the received DHCPv6 offers, and set OfferIndex and OfferCount.\r
 \r
   @param[in]  Private               The pointer to PXEBC_PRIVATE_DATA.\r
   @param[in]  RcvdOffer             The pointer to the received offer packet.\r
 \r
+  @retval     EFI_SUCCESS      Cache and parse the packet successfully.\r
+  @retval     Others           Operation failed.\r
 **/\r
-VOID\r
+EFI_STATUS\r
 PxeBcCacheDhcp6Offer (\r
-  IN PXEBC_PRIVATE_DATA     *Private,\r
-  IN EFI_DHCP6_PACKET       *RcvdOffer\r
+  IN PXEBC_PRIVATE_DATA  *Private,\r
+  IN EFI_DHCP6_PACKET    *RcvdOffer\r
   )\r
 {\r
   PXEBC_DHCP6_PACKET_CACHE  *Cache6;\r
   EFI_DHCP6_PACKET          *Offer;\r
   PXEBC_OFFER_TYPE          OfferType;\r
+  EFI_STATUS                Status;\r
 \r
   Cache6 = &Private->OfferBuffer[Private->OfferNum].Dhcp6;\r
   Offer  = &Cache6->Packet.Offer;\r
@@ -933,13 +1155,16 @@ PxeBcCacheDhcp6Offer (
   //\r
   // Cache the content of DHCPv6 packet firstly.\r
   //\r
-  PxeBcCacheDhcp6Packet (Offer, RcvdOffer);\r
+  Status = PxeBcCacheDhcp6Packet (Offer, RcvdOffer);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
 \r
   //\r
   // Validate the DHCPv6 packet, and parse the options and offer type.\r
   //\r
   if (EFI_ERROR (PxeBcParseDhcp6Packet (Cache6))) {\r
-    return ;\r
+    return EFI_ABORTED;\r
   }\r
 \r
   //\r
@@ -961,14 +1186,16 @@ PxeBcCacheDhcp6Offer (
       //\r
       Private->OfferIndex[OfferType][Private->OfferCount[OfferType]] = Private->OfferNum;\r
       Private->OfferCount[OfferType]++;\r
-    } else if (Private->OfferCount[OfferType] > 0) {\r
+    } else if (((OfferType == PxeOfferTypeProxyPxe10) || (OfferType == PxeOfferTypeProxyWfm11a)) &&\r
+               (Private->OfferCount[OfferType] < 1))\r
+    {\r
       //\r
       // Only cache the first PXE10/WFM11a offer, and discard the others.\r
       //\r
       Private->OfferIndex[OfferType][0] = Private->OfferNum;\r
       Private->OfferCount[OfferType]    = 1;\r
     } else {\r
-      return;\r
+      return EFI_ABORTED;\r
     }\r
   } else {\r
     //\r
@@ -979,8 +1206,9 @@ PxeBcCacheDhcp6Offer (
   }\r
 \r
   Private->OfferNum++;\r
-}\r
 \r
+  return EFI_SUCCESS;\r
+}\r
 \r
 /**\r
   Select an DHCPv6 offer, and record SelectIndex and SelectProxyType.\r
@@ -990,12 +1218,12 @@ PxeBcCacheDhcp6Offer (
 **/\r
 VOID\r
 PxeBcSelectDhcp6Offer (\r
-  IN PXEBC_PRIVATE_DATA     *Private\r
+  IN PXEBC_PRIVATE_DATA  *Private\r
   )\r
 {\r
-  UINT32                Index;\r
-  UINT32                OfferIndex;\r
-  PXEBC_OFFER_TYPE      OfferType;\r
+  UINT32            Index;\r
+  UINT32            OfferIndex;\r
+  PXEBC_OFFER_TYPE  OfferType;\r
 \r
   Private->SelectIndex = 0;\r
 \r
@@ -1008,43 +1236,40 @@ PxeBcSelectDhcp6Offer (
       // 1. DhcpPxe10 offer\r
       //\r
       Private->SelectIndex = Private->OfferIndex[PxeOfferTypeDhcpPxe10][0] + 1;\r
-\r
     } else if (Private->OfferCount[PxeOfferTypeDhcpWfm11a] > 0) {\r
       //\r
       // 2. DhcpWfm11a offer\r
       //\r
       Private->SelectIndex = Private->OfferIndex[PxeOfferTypeDhcpWfm11a][0] + 1;\r
-\r
-    } else if (Private->OfferCount[PxeOfferTypeDhcpOnly] > 0 &&\r
-               Private->OfferCount[PxeOfferTypeProxyPxe10] > 0) {\r
+    } else if ((Private->OfferCount[PxeOfferTypeDhcpOnly] > 0) &&\r
+               (Private->OfferCount[PxeOfferTypeProxyPxe10] > 0))\r
+    {\r
       //\r
       // 3. DhcpOnly offer and ProxyPxe10 offer.\r
       //\r
       Private->SelectIndex     = Private->OfferIndex[PxeOfferTypeDhcpOnly][0] + 1;\r
       Private->SelectProxyType = PxeOfferTypeProxyPxe10;\r
-\r
-    } else if (Private->OfferCount[PxeOfferTypeDhcpOnly] > 0 &&\r
-               Private->OfferCount[PxeOfferTypeProxyWfm11a] > 0) {\r
+    } else if ((Private->OfferCount[PxeOfferTypeDhcpOnly] > 0) &&\r
+               (Private->OfferCount[PxeOfferTypeProxyWfm11a] > 0))\r
+    {\r
       //\r
       // 4. DhcpOnly offer and ProxyWfm11a offer.\r
       //\r
       Private->SelectIndex     = Private->OfferIndex[PxeOfferTypeDhcpOnly][0] + 1;\r
       Private->SelectProxyType = PxeOfferTypeProxyWfm11a;\r
-\r
     } else if (Private->OfferCount[PxeOfferTypeDhcpBinl] > 0) {\r
       //\r
       // 5. DhcpBinl offer.\r
       //\r
       Private->SelectIndex = Private->OfferIndex[PxeOfferTypeDhcpBinl][0] + 1;\r
-\r
-    } else if (Private->OfferCount[PxeOfferTypeDhcpOnly] > 0 &&\r
-               Private->OfferCount[PxeOfferTypeProxyBinl] > 0) {\r
+    } else if ((Private->OfferCount[PxeOfferTypeDhcpOnly] > 0) &&\r
+               (Private->OfferCount[PxeOfferTypeProxyBinl] > 0))\r
+    {\r
       //\r
       // 6. DhcpOnly offer and ProxyBinl offer.\r
       //\r
       Private->SelectIndex     = Private->OfferIndex[PxeOfferTypeDhcpOnly][0] + 1;\r
       Private->SelectProxyType = PxeOfferTypeProxyBinl;\r
-\r
     } else {\r
       //\r
       // 7. DhcpOnly offer with bootfilename.\r
@@ -1062,7 +1287,6 @@ PxeBcSelectDhcp6Offer (
     // Select offer by received order.\r
     //\r
     for (Index = 0; Index < Private->OfferNum; Index++) {\r
-\r
       OfferType = Private->OfferBuffer[Index].Dhcp6.OfferType;\r
 \r
       if (IS_PROXY_OFFER (OfferType)) {\r
@@ -1073,8 +1297,9 @@ PxeBcSelectDhcp6Offer (
       }\r
 \r
       if (!Private->IsProxyRecved &&\r
-          OfferType == PxeOfferTypeDhcpOnly &&\r
-          Private->OfferBuffer[Index].Dhcp6.OptList[PXEBC_DHCP6_IDX_BOOT_FILE_URL] == NULL) {\r
+          (OfferType == PxeOfferTypeDhcpOnly) &&\r
+          (Private->OfferBuffer[Index].Dhcp6.OptList[PXEBC_DHCP6_IDX_BOOT_FILE_URL] == NULL))\r
+      {\r
         //\r
         // Skip if DhcpOnly offer without any other proxy offers or bootfilename.\r
         //\r
@@ -1087,33 +1312,46 @@ PxeBcSelectDhcp6Offer (
   }\r
 }\r
 \r
-\r
 /**\r
   Handle the DHCPv6 offer packet.\r
 \r
   @param[in]  Private             The pointer to PXEBC_PRIVATE_DATA.\r
 \r
-  @retval     EFI_SUCCESS         Handled the DHCPv6 offer packet successfully.\r
-  @retval     EFI_NO_RESPONSE     No response to the following request packet.\r
+  @retval     EFI_SUCCESS           Handled the DHCPv6 offer packet successfully.\r
+  @retval     EFI_NO_RESPONSE       No response to the following request packet.\r
+  @retval     EFI_OUT_OF_RESOURCES  Failed to allocate resources.\r
+  @retval     EFI_BUFFER_TOO_SMALL  Can't cache the offer pacet.\r
 \r
 **/\r
 EFI_STATUS\r
 PxeBcHandleDhcp6Offer (\r
-  IN PXEBC_PRIVATE_DATA            *Private\r
+  IN PXEBC_PRIVATE_DATA  *Private\r
   )\r
 {\r
-  PXEBC_DHCP6_PACKET_CACHE         *Cache6;\r
-  EFI_STATUS                       Status;\r
-  PXEBC_OFFER_TYPE                 OfferType;\r
-  UINT32                           ProxyIndex;\r
-  UINT32                           SelectIndex;\r
-  UINT32                           Index;\r
+  PXEBC_DHCP6_PACKET_CACHE  *Cache6;\r
+  EFI_STATUS                Status;\r
+  PXEBC_OFFER_TYPE          OfferType;\r
+  UINT32                    ProxyIndex;\r
+  UINT32                    SelectIndex;\r
+  UINT32                    Index;\r
 \r
   ASSERT (Private->SelectIndex > 0);\r
-  SelectIndex = (UINT32) (Private->SelectIndex - 1);\r
+  SelectIndex = (UINT32)(Private->SelectIndex - 1);\r
   ASSERT (SelectIndex < PXEBC_OFFER_MAX_NUM);\r
-  Cache6      = &Private->OfferBuffer[SelectIndex].Dhcp6;\r
-  Status      = EFI_SUCCESS;\r
+  Cache6 = &Private->OfferBuffer[SelectIndex].Dhcp6;\r
+  Status = EFI_SUCCESS;\r
+\r
+  //\r
+  // First try to cache DNS server address if DHCP6 offer provides.\r
+  //\r
+  if (Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER] != NULL) {\r
+    Private->DnsServer = AllocateZeroPool (NTOHS (Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpLen));\r
+    if (Private->DnsServer == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    CopyMem (Private->DnsServer, Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->Data, sizeof (EFI_IPv6_ADDRESS));\r
+  }\r
 \r
   if (Cache6->OfferType == PxeOfferTypeDhcpBinl) {\r
     //\r
@@ -1123,7 +1361,6 @@ PxeBcHandleDhcp6Offer (
       Status = EFI_NO_RESPONSE;\r
     }\r
   } else if (Cache6->OfferType == PxeOfferTypeDhcpOnly) {\r
-\r
     if (Private->IsProxyRecved) {\r
       //\r
       // DhcpOnly offer is selected, so need try to request bootfilename.\r
@@ -1141,12 +1378,12 @@ PxeBcHandleDhcp6Offer (
           // Try all the cached ProxyBinl offer one by one to request bootfilename.\r
           //\r
           for (Index = 0; Index < Private->OfferCount[Private->SelectProxyType]; Index++) {\r
-\r
             ProxyIndex = Private->OfferIndex[Private->SelectProxyType][Index];\r
             if (!EFI_ERROR (PxeBcRetryDhcp6Binl (Private, ProxyIndex))) {\r
               break;\r
             }\r
           }\r
+\r
           if (Index == Private->OfferCount[Private->SelectProxyType]) {\r
             Status = EFI_NO_RESPONSE;\r
           }\r
@@ -1163,7 +1400,6 @@ PxeBcHandleDhcp6Offer (
         Status = EFI_NO_RESPONSE;\r
 \r
         for (Index = 0; Index < Private->OfferNum; Index++) {\r
-\r
           OfferType = Private->OfferBuffer[Index].Dhcp6.OfferType;\r
 \r
           if (!IS_PROXY_OFFER (OfferType)) {\r
@@ -1189,15 +1425,15 @@ PxeBcHandleDhcp6Offer (
         }\r
       }\r
 \r
-      if (!EFI_ERROR (Status) && Private->SelectProxyType != PxeOfferTypeProxyBinl) {\r
+      if (!EFI_ERROR (Status) && (Private->SelectProxyType != PxeOfferTypeProxyBinl)) {\r
         //\r
         // Success to try to request by a ProxyPxe10 or ProxyWfm11a offer, copy and parse it.\r
         //\r
-        PxeBcCopyDhcp6Proxy (Private, ProxyIndex);\r
+        Status = PxeBcCopyDhcp6Proxy (Private, ProxyIndex);\r
       }\r
     } else {\r
       //\r
-      //  Othewise, the bootfilename must be included in DhcpOnly offer.\r
+      //  Otherwise, the bootfilename must be included in DhcpOnly offer.\r
       //\r
       ASSERT (Cache6->OptList[PXEBC_DHCP6_IDX_BOOT_FILE_URL] != NULL);\r
     }\r
@@ -1207,14 +1443,13 @@ PxeBcHandleDhcp6Offer (
     //\r
     // All PXE boot information is ready by now.\r
     //\r
-    PxeBcCopyDhcp6Ack (Private, &Private->DhcpAck.Dhcp6.Packet.Ack, TRUE);\r
+    Status                                 = PxeBcCopyDhcp6Ack (Private, &Private->DhcpAck.Dhcp6.Packet.Ack, TRUE);\r
     Private->PxeBc.Mode->DhcpDiscoverValid = TRUE;\r
   }\r
 \r
   return Status;\r
 }\r
 \r
-\r
 /**\r
   Unregister the address by Ip6Config protocol.\r
 \r
@@ -1223,7 +1458,7 @@ PxeBcHandleDhcp6Offer (
 **/\r
 VOID\r
 PxeBcUnregisterIp6Address (\r
-  IN PXEBC_PRIVATE_DATA           *Private\r
+  IN PXEBC_PRIVATE_DATA  *Private\r
   )\r
 {\r
   if (Private->Ip6Policy != PXEBC_IP6_POLICY_MAX) {\r
@@ -1236,7 +1471,7 @@ PxeBcUnregisterIp6Address (
 \r
 /**\r
   Check whether IP driver could route the message which will be sent to ServerIp address.\r
-  \r
+\r
   This function will check the IP6 route table every 1 seconds until specified timeout is expired, if a valid\r
   route is found in IP6 route table, the address will be filed in GatewayAddr and return.\r
 \r
@@ -1246,23 +1481,23 @@ PxeBcUnregisterIp6Address (
 \r
   @retval     EFI_SUCCESS         Found a valid gateway address successfully.\r
   @retval     EFI_TIMEOUT         The operation is time out.\r
-  @retval     Other               Unexpect error happened.\r
-  \r
+  @retval     Other               Unexpected error happened.\r
+\r
 **/\r
 EFI_STATUS\r
 PxeBcCheckRouteTable (\r
-  IN  PXEBC_PRIVATE_DATA            *Private,\r
-  IN  UINTN                         TimeOutInSecond,\r
-  OUT EFI_IPv6_ADDRESS              *GatewayAddr\r
+  IN  PXEBC_PRIVATE_DATA  *Private,\r
+  IN  UINTN               TimeOutInSecond,\r
+  OUT EFI_IPv6_ADDRESS    *GatewayAddr\r
   )\r
 {\r
-  EFI_STATUS                       Status;\r
-  EFI_IP6_PROTOCOL                 *Ip6;\r
-  EFI_IP6_MODE_DATA                Ip6ModeData;\r
-  UINTN                            Index;\r
-  EFI_EVENT                        TimeOutEvt;\r
-  UINTN                            RetryCount;\r
-  BOOLEAN                          GatewayIsFound;\r
+  EFI_STATUS         Status;\r
+  EFI_IP6_PROTOCOL   *Ip6;\r
+  EFI_IP6_MODE_DATA  Ip6ModeData;\r
+  UINTN              Index;\r
+  EFI_EVENT          TimeOutEvt;\r
+  UINTN              RetryCount;\r
+  BOOLEAN            GatewayIsFound;\r
 \r
   ASSERT (GatewayAddr != NULL);\r
   ASSERT (Private != NULL);\r
@@ -1293,28 +1528,33 @@ PxeBcCheckRouteTable (
     if (Ip6ModeData.AddressList != NULL) {\r
       FreePool (Ip6ModeData.AddressList);\r
     }\r
+\r
     if (Ip6ModeData.GroupTable != NULL) {\r
       FreePool (Ip6ModeData.GroupTable);\r
     }\r
+\r
     if (Ip6ModeData.RouteTable != NULL) {\r
       FreePool (Ip6ModeData.RouteTable);\r
     }\r
+\r
     if (Ip6ModeData.NeighborCache != NULL) {\r
       FreePool (Ip6ModeData.NeighborCache);\r
     }\r
+\r
     if (Ip6ModeData.PrefixTable != NULL) {\r
       FreePool (Ip6ModeData.PrefixTable);\r
     }\r
+\r
     if (Ip6ModeData.IcmpTypeList != NULL) {\r
       FreePool (Ip6ModeData.IcmpTypeList);\r
     }\r
-    \r
-    if (GatewayIsFound || RetryCount == TimeOutInSecond) {\r
+\r
+    if (GatewayIsFound || (RetryCount == TimeOutInSecond)) {\r
       break;\r
     }\r
-    \r
+\r
     RetryCount++;\r
-    \r
+\r
     //\r
     // Delay 1 second then recheck it again.\r
     //\r
@@ -1335,23 +1575,24 @@ PxeBcCheckRouteTable (
     if (EFI_ERROR (Status)) {\r
       goto ON_EXIT;\r
     }\r
+\r
     while (EFI_ERROR (gBS->CheckEvent (TimeOutEvt))) {\r
       Ip6->Poll (Ip6);\r
     }\r
   }\r
-  \r
+\r
 ON_EXIT:\r
   if (TimeOutEvt != NULL) {\r
     gBS->CloseEvent (TimeOutEvt);\r
   }\r
-  \r
+\r
   if (GatewayIsFound) {\r
     Status = EFI_SUCCESS;\r
   } else if (RetryCount == TimeOutInSecond) {\r
     Status = EFI_TIMEOUT;\r
   }\r
 \r
-  return Status; \r
+  return Status;\r
 }\r
 \r
 /**\r
@@ -1360,36 +1601,35 @@ ON_EXIT:
   @param[in]  Private             The pointer to PXEBC_PRIVATE_DATA.\r
   @param[in]  Address             The pointer to the ready address.\r
 \r
-  @retval     EFI_SUCCESS         Registered the address succesfully.\r
+  @retval     EFI_SUCCESS         Registered the address successfully.\r
   @retval     Others              Failed to register the address.\r
 \r
 **/\r
 EFI_STATUS\r
 PxeBcRegisterIp6Address (\r
-  IN PXEBC_PRIVATE_DATA            *Private,\r
-  IN EFI_IPv6_ADDRESS              *Address\r
+  IN PXEBC_PRIVATE_DATA  *Private,\r
+  IN EFI_IPv6_ADDRESS    *Address\r
   )\r
 {\r
-  EFI_IP6_PROTOCOL                 *Ip6;\r
-  EFI_IP6_CONFIG_PROTOCOL          *Ip6Cfg;\r
-  EFI_IP6_CONFIG_POLICY            Policy;\r
-  EFI_IP6_CONFIG_MANUAL_ADDRESS    CfgAddr;\r
-  EFI_IPv6_ADDRESS                 GatewayAddr;\r
-  UINTN                            DataSize;\r
-  EFI_EVENT                        TimeOutEvt;\r
-  EFI_EVENT                        MappedEvt;\r
-  EFI_STATUS                       Status;\r
-  UINT64                           DadTriggerTime;\r
-  EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS    DadXmits;\r
-  BOOLEAN                          NoGateway;\r
-\r
-  Status     = EFI_SUCCESS;\r
-  TimeOutEvt = NULL;\r
-  MappedEvt  = NULL;\r
-  DataSize   = sizeof (EFI_IP6_CONFIG_POLICY);\r
-  Ip6Cfg     = Private->Ip6Cfg;\r
-  Ip6        = Private->Ip6;\r
-  NoGateway  = FALSE;\r
+  EFI_IP6_PROTOCOL               *Ip6;\r
+  EFI_IP6_CONFIG_PROTOCOL        *Ip6Cfg;\r
+  EFI_IP6_CONFIG_POLICY          Policy;\r
+  EFI_IP6_CONFIG_MANUAL_ADDRESS  CfgAddr;\r
+  EFI_IPv6_ADDRESS               GatewayAddr;\r
+  UINTN                          DataSize;\r
+  EFI_EVENT                      MappedEvt;\r
+  EFI_STATUS                     Status;\r
+  BOOLEAN                        NoGateway;\r
+  EFI_IPv6_ADDRESS               *Ip6Addr;\r
+  UINTN                          Index;\r
+\r
+  Status    = EFI_SUCCESS;\r
+  MappedEvt = NULL;\r
+  Ip6Addr   = NULL;\r
+  DataSize  = sizeof (EFI_IP6_CONFIG_POLICY);\r
+  Ip6Cfg    = Private->Ip6Cfg;\r
+  Ip6       = Private->Ip6;\r
+  NoGateway = FALSE;\r
 \r
   ZeroMem (&CfgAddr, sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS));\r
   CopyMem (&CfgAddr.Address, Address, sizeof (EFI_IPv6_ADDRESS));\r
@@ -1406,7 +1646,7 @@ PxeBcRegisterIp6Address (
   if (EFI_ERROR (Status)) {\r
     NoGateway = TRUE;\r
   }\r
-  \r
+\r
   //\r
   // There is no channel between IP6 and PXE driver about address setting,\r
   // so it has to set the new address by Ip6ConfigProtocol manually.\r
@@ -1415,7 +1655,7 @@ PxeBcRegisterIp6Address (
   Status = Ip6Cfg->SetData (\r
                      Ip6Cfg,\r
                      Ip6ConfigDataTypePolicy,\r
-                     sizeof(EFI_IP6_CONFIG_POLICY),\r
+                     sizeof (EFI_IP6_CONFIG_POLICY),\r
                      &Policy\r
                      );\r
   if (EFI_ERROR (Status)) {\r
@@ -1426,34 +1666,6 @@ PxeBcRegisterIp6Address (
     goto ON_EXIT;\r
   }\r
 \r
-  //\r
-  // Get Duplicate Address Detection Transmits count.\r
-  //\r
-  DataSize = sizeof (EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS);\r
-  Status = Ip6Cfg->GetData (\r
-                     Ip6Cfg,\r
-                     Ip6ConfigDataTypeDupAddrDetectTransmits,\r
-                     &DataSize,\r
-                     &DadXmits\r
-                     );\r
-  if (EFI_ERROR (Status)) {\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  //\r
-  // Create a timer as setting address timeout event since DAD in IP6 driver.\r
-  //\r
-  Status = gBS->CreateEvent (\r
-                  EVT_TIMER,\r
-                  TPL_CALLBACK,\r
-                  NULL,\r
-                  NULL,\r
-                  &TimeOutEvt\r
-                  );\r
-  if (EFI_ERROR (Status)) {\r
-    goto ON_EXIT;\r
-  }\r
-\r
   //\r
   // Create a notify event to set address flag when DAD if IP6 driver succeeded.\r
   //\r
@@ -1468,37 +1680,72 @@ PxeBcRegisterIp6Address (
     goto ON_EXIT;\r
   }\r
 \r
-  Status = Ip6Cfg->RegisterDataNotify (\r
-                     Ip6Cfg,\r
-                     Ip6ConfigDataTypeManualAddress,\r
-                     MappedEvt\r
-                     );\r
-  if (EFI_ERROR(Status)) {\r
+  Private->IsAddressOk = FALSE;\r
+  Status               = Ip6Cfg->RegisterDataNotify (\r
+                                   Ip6Cfg,\r
+                                   Ip6ConfigDataTypeManualAddress,\r
+                                   MappedEvt\r
+                                   );\r
+  if (EFI_ERROR (Status)) {\r
     goto ON_EXIT;\r
   }\r
 \r
   Status = Ip6Cfg->SetData (\r
                      Ip6Cfg,\r
                      Ip6ConfigDataTypeManualAddress,\r
-                     sizeof(EFI_IP6_CONFIG_MANUAL_ADDRESS),\r
+                     sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS),\r
                      &CfgAddr\r
                      );\r
-  if (EFI_ERROR(Status) && Status != EFI_NOT_READY) {\r
+  if (EFI_ERROR (Status) && (Status != EFI_NOT_READY)) {\r
     goto ON_EXIT;\r
-  }\r
+  } else if (Status == EFI_NOT_READY) {\r
+    //\r
+    // Poll the network until the asynchronous process is finished.\r
+    //\r
+    while (!Private->IsAddressOk) {\r
+      Ip6->Poll (Ip6);\r
+    }\r
 \r
-  //\r
-  // Start the 5 secondes timer to wait for setting address.\r
-  //\r
-  Status = EFI_NO_MAPPING;\r
-  DadTriggerTime = TICKS_PER_SECOND * DadXmits.DupAddrDetectTransmits + PXEBC_DAD_ADDITIONAL_DELAY;\r
-  gBS->SetTimer (TimeOutEvt, TimerRelative, DadTriggerTime);\r
+    //\r
+    // Check whether the IP6 address setting is successed.\r
+    //\r
+    DataSize = 0;\r
+    Status   = Ip6Cfg->GetData (\r
+                         Ip6Cfg,\r
+                         Ip6ConfigDataTypeManualAddress,\r
+                         &DataSize,\r
+                         NULL\r
+                         );\r
+    if ((Status != EFI_BUFFER_TOO_SMALL) || (DataSize == 0)) {\r
+      Status = EFI_DEVICE_ERROR;\r
+      goto ON_EXIT;\r
+    }\r
 \r
-  while (EFI_ERROR (gBS->CheckEvent (TimeOutEvt))) {\r
-    Ip6->Poll (Ip6);\r
-    if (Private->IsAddressOk) {\r
-      Status = EFI_SUCCESS;\r
-      break;\r
+    Ip6Addr = AllocatePool (DataSize);\r
+    if (Ip6Addr == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    Status = Ip6Cfg->GetData (\r
+                       Ip6Cfg,\r
+                       Ip6ConfigDataTypeManualAddress,\r
+                       &DataSize,\r
+                       (VOID *)Ip6Addr\r
+                       );\r
+    if (EFI_ERROR (Status)) {\r
+      Status = EFI_DEVICE_ERROR;\r
+      goto ON_EXIT;\r
+    }\r
+\r
+    for (Index = 0; Index < DataSize / sizeof (EFI_IPv6_ADDRESS); Index++) {\r
+      if (CompareMem (Ip6Addr + Index, Address, sizeof (EFI_IPv6_ADDRESS)) == 0) {\r
+        break;\r
+      }\r
+    }\r
+\r
+    if (Index == DataSize / sizeof (EFI_IPv6_ADDRESS)) {\r
+      Status = EFI_ABORTED;\r
+      goto ON_EXIT;\r
     }\r
   }\r
 \r
@@ -1526,9 +1773,11 @@ ON_EXIT:
               );\r
     gBS->CloseEvent (MappedEvt);\r
   }\r
-  if (TimeOutEvt != NULL) {\r
-    gBS->CloseEvent (TimeOutEvt);\r
+\r
+  if (Ip6Addr != NULL) {\r
+    FreePool (Ip6Addr);\r
   }\r
+\r
   return Status;\r
 }\r
 \r
@@ -1537,22 +1786,22 @@ ON_EXIT:
 \r
   @param[in]  Private             The pointer to PXEBC_PRIVATE_DATA.\r
 \r
-  @retval     EFI_SUCCESS         Switch the IP policy succesfully.\r
-  @retval     Others              Unexpect error happened.\r
+  @retval     EFI_SUCCESS         Switch the IP policy successfully.\r
+  @retval     Others              Unexpected error happened.\r
 \r
 **/\r
 EFI_STATUS\r
 PxeBcSetIp6Policy (\r
-  IN PXEBC_PRIVATE_DATA            *Private\r
+  IN PXEBC_PRIVATE_DATA  *Private\r
   )\r
 {\r
-  EFI_IP6_CONFIG_POLICY            Policy;\r
-  EFI_STATUS                       Status;\r
-  EFI_IP6_CONFIG_PROTOCOL          *Ip6Cfg;\r
-  UINTN                            DataSize;\r
+  EFI_IP6_CONFIG_POLICY    Policy;\r
+  EFI_STATUS               Status;\r
+  EFI_IP6_CONFIG_PROTOCOL  *Ip6Cfg;\r
+  UINTN                    DataSize;\r
 \r
-  Ip6Cfg      = Private->Ip6Cfg;\r
-  DataSize    = sizeof (EFI_IP6_CONFIG_POLICY);\r
+  Ip6Cfg   = Private->Ip6Cfg;\r
+  DataSize = sizeof (EFI_IP6_CONFIG_POLICY);\r
 \r
   //\r
   // Get and store the current policy of IP6 driver.\r
@@ -1572,7 +1821,7 @@ PxeBcSetIp6Policy (
     Status = Ip6Cfg->SetData (\r
                        Ip6Cfg,\r
                        Ip6ConfigDataTypePolicy,\r
-                       sizeof(EFI_IP6_CONFIG_POLICY),\r
+                       sizeof (EFI_IP6_CONFIG_POLICY),\r
                        &Policy\r
                        );\r
     if (EFI_ERROR (Status)) {\r
@@ -1588,7 +1837,7 @@ PxeBcSetIp6Policy (
 \r
 /**\r
   This function will register the station IP address and flush IP instance to start using the new IP address.\r
-  \r
+\r
   @param[in]  Private             The pointer to PXEBC_PRIVATE_DATA.\r
 \r
   @retval     EFI_SUCCESS         The new IP address has been configured successfully.\r
@@ -1597,12 +1846,12 @@ PxeBcSetIp6Policy (
 **/\r
 EFI_STATUS\r
 PxeBcSetIp6Address (\r
-  IN  PXEBC_PRIVATE_DATA              *Private\r
+  IN  PXEBC_PRIVATE_DATA  *Private\r
   )\r
 {\r
-  EFI_STATUS                  Status;\r
-  EFI_DHCP6_PROTOCOL          *Dhcp6;\r
-    \r
+  EFI_STATUS          Status;\r
+  EFI_DHCP6_PROTOCOL  *Dhcp6;\r
+\r
   Dhcp6 = Private->Dhcp6;\r
 \r
   CopyMem (&Private->StationIp.v6, &Private->TmpStationIp.v6, sizeof (EFI_IPv6_ADDRESS));\r
@@ -1648,47 +1897,48 @@ PxeBcSetIp6Address (
 EFI_STATUS\r
 EFIAPI\r
 PxeBcDhcp6CallBack (\r
-  IN  EFI_DHCP6_PROTOCOL           *This,\r
-  IN  VOID                         *Context,\r
-  IN  EFI_DHCP6_STATE              CurrentState,\r
-  IN  EFI_DHCP6_EVENT              Dhcp6Event,\r
-  IN  EFI_DHCP6_PACKET             *Packet,\r
-  OUT EFI_DHCP6_PACKET             **NewPacket     OPTIONAL\r
+  IN  EFI_DHCP6_PROTOCOL  *This,\r
+  IN  VOID                *Context,\r
+  IN  EFI_DHCP6_STATE     CurrentState,\r
+  IN  EFI_DHCP6_EVENT     Dhcp6Event,\r
+  IN  EFI_DHCP6_PACKET    *Packet,\r
+  OUT EFI_DHCP6_PACKET    **NewPacket     OPTIONAL\r
   )\r
 {\r
-  PXEBC_PRIVATE_DATA                  *Private;\r
-  EFI_PXE_BASE_CODE_MODE              *Mode;\r
-  EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL *Callback;\r
-  EFI_DHCP6_PACKET                    *SelectAd;\r
-  EFI_STATUS                          Status;\r
-  BOOLEAN                             Received;\r
+  PXEBC_PRIVATE_DATA                   *Private;\r
+  EFI_PXE_BASE_CODE_MODE               *Mode;\r
+  EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL  *Callback;\r
+  EFI_DHCP6_PACKET                     *SelectAd;\r
+  EFI_STATUS                           Status;\r
+  BOOLEAN                              Received;\r
 \r
   if ((Dhcp6Event != Dhcp6RcvdAdvertise) &&\r
       (Dhcp6Event != Dhcp6SelectAdvertise) &&\r
       (Dhcp6Event != Dhcp6SendSolicit) &&\r
       (Dhcp6Event != Dhcp6SendRequest) &&\r
-      (Dhcp6Event != Dhcp6RcvdReply)) {\r
+      (Dhcp6Event != Dhcp6RcvdReply))\r
+  {\r
     return EFI_SUCCESS;\r
   }\r
 \r
   ASSERT (Packet != NULL);\r
 \r
-  Private   = (PXEBC_PRIVATE_DATA *) Context;\r
-  Mode      = Private->PxeBc.Mode;\r
-  Callback  = Private->PxeBcCallback;\r
+  Private  = (PXEBC_PRIVATE_DATA *)Context;\r
+  Mode     = Private->PxeBc.Mode;\r
+  Callback = Private->PxeBcCallback;\r
 \r
   //\r
-  // Callback to user when any traffic ocurred if has.\r
+  // Callback to user when any traffic occurred if has.\r
   //\r
-  if (Dhcp6Event != Dhcp6SelectAdvertise && Callback != NULL) {\r
-    Received = (BOOLEAN) (Dhcp6Event == Dhcp6RcvdAdvertise || Dhcp6Event == Dhcp6RcvdReply);\r
-    Status = Callback->Callback (\r
-                         Callback,\r
-                         Private->Function,\r
-                         Received,\r
-                         Packet->Length,\r
-                         (EFI_PXE_BASE_CODE_PACKET *) &Packet->Dhcp6\r
-                         );\r
+  if ((Dhcp6Event != Dhcp6SelectAdvertise) && (Callback != NULL)) {\r
+    Received = (BOOLEAN)(Dhcp6Event == Dhcp6RcvdAdvertise || Dhcp6Event == Dhcp6RcvdReply);\r
+    Status   = Callback->Callback (\r
+                           Callback,\r
+                           Private->Function,\r
+                           Received,\r
+                           Packet->Length,\r
+                           (EFI_PXE_BASE_CODE_PACKET *)&Packet->Dhcp6\r
+                           );\r
     if (Status != EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE) {\r
       return EFI_ABORTED;\r
     }\r
@@ -1697,80 +1947,114 @@ PxeBcDhcp6CallBack (
   Status = EFI_SUCCESS;\r
 \r
   switch (Dhcp6Event) {\r
+    case Dhcp6SendSolicit:\r
+      if (Packet->Length > PXEBC_DHCP6_PACKET_MAX_SIZE) {\r
+        //\r
+        // If the to be sent packet exceeds the maximum length, abort the DHCP process.\r
+        //\r
+        Status = EFI_ABORTED;\r
+        break;\r
+      }\r
 \r
-  case Dhcp6SendSolicit:\r
-    //\r
-    // Record the first Solicate msg time\r
-    //\r
-    if (Private->SolicitTimes == 0) {\r
-      CalcElapsedTime (Private);\r
-      Private->SolicitTimes++;\r
-    }\r
-    //\r
-    // Cache the dhcp discover packet to mode data directly.\r
-    //\r
-    CopyMem (&Mode->DhcpDiscover.Dhcpv4, &Packet->Dhcp6, Packet->Length);\r
-    break;\r
+      //\r
+      // Record the first Solicate msg time\r
+      //\r
+      if (Private->SolicitTimes == 0) {\r
+        CalcElapsedTime (Private);\r
+        Private->SolicitTimes++;\r
+      }\r
 \r
-  case Dhcp6RcvdAdvertise:\r
-    Status = EFI_NOT_READY;\r
-    if (Private->OfferNum < PXEBC_OFFER_MAX_NUM) {\r
       //\r
-      // Cache the dhcp offers to OfferBuffer[] for select later, and record\r
-      // the OfferIndex and OfferCount.\r
+      // Cache the dhcp discover packet to mode data directly.\r
       //\r
-      PxeBcCacheDhcp6Offer (Private, Packet);\r
-    }\r
-    break;\r
+      CopyMem (&Mode->DhcpDiscover.Dhcpv4, &Packet->Dhcp6, Packet->Length);\r
+      break;\r
 \r
-  case Dhcp6SendRequest:\r
-    //\r
-    // Store the request packet as seed packet for discover.\r
-    //\r
-    if (Private->Dhcp6Request != NULL) {\r
-      FreePool (Private->Dhcp6Request);\r
-    }\r
-    Private->Dhcp6Request = AllocateZeroPool (Packet->Size);\r
-    if (Private->Dhcp6Request != NULL) {\r
-      CopyMem (Private->Dhcp6Request, Packet, Packet->Size);\r
-    }\r
-    break;\r
+    case Dhcp6RcvdAdvertise:\r
+      Status = EFI_NOT_READY;\r
+      if (Packet->Length > PXEBC_DHCP6_PACKET_MAX_SIZE) {\r
+        //\r
+        // Ignore the incoming packets which exceed the maximum length.\r
+        //\r
+        break;\r
+      }\r
 \r
-  case Dhcp6SelectAdvertise:\r
-    //\r
-    // Select offer by the default policy or by order, and record the SelectIndex\r
-    // and SelectProxyType.\r
-    //\r
-    PxeBcSelectDhcp6Offer (Private);\r
+      if (Private->OfferNum < PXEBC_OFFER_MAX_NUM) {\r
+        //\r
+        // Cache the dhcp offers to OfferBuffer[] for select later, and record\r
+        // the OfferIndex and OfferCount.\r
+        //\r
+        PxeBcCacheDhcp6Offer (Private, Packet);\r
+      }\r
 \r
-    if (Private->SelectIndex == 0) {\r
-      Status = EFI_ABORTED;\r
-    } else {\r
-      ASSERT (NewPacket != NULL);\r
-      SelectAd   = &Private->OfferBuffer[Private->SelectIndex - 1].Dhcp6.Packet.Offer;\r
-      *NewPacket = AllocateZeroPool (SelectAd->Size);\r
-      ASSERT (*NewPacket != NULL);\r
-      CopyMem (*NewPacket, SelectAd, SelectAd->Size);\r
-    }\r
-    break;\r
+      break;\r
 \r
-  case Dhcp6RcvdReply:\r
-    //\r
-    // Cache the dhcp ack to Private->Dhcp6Ack, but it's not the final ack in mode data\r
-    // without verification.\r
-    //\r
-    ASSERT (Private->SelectIndex != 0);\r
-    PxeBcCopyDhcp6Ack (Private, Packet, FALSE);\r
-    break;\r
+    case Dhcp6SendRequest:\r
+      if (Packet->Length > PXEBC_DHCP6_PACKET_MAX_SIZE) {\r
+        //\r
+        // If the to be sent packet exceeds the maximum length, abort the DHCP process.\r
+        //\r
+        Status = EFI_ABORTED;\r
+        break;\r
+      }\r
 \r
-  default:\r
-    ASSERT (0);\r
+      //\r
+      // Store the request packet as seed packet for discover.\r
+      //\r
+      if (Private->Dhcp6Request != NULL) {\r
+        FreePool (Private->Dhcp6Request);\r
+      }\r
+\r
+      Private->Dhcp6Request = AllocateZeroPool (Packet->Size);\r
+      if (Private->Dhcp6Request != NULL) {\r
+        CopyMem (Private->Dhcp6Request, Packet, Packet->Size);\r
+      }\r
+\r
+      break;\r
+\r
+    case Dhcp6SelectAdvertise:\r
+      //\r
+      // Select offer by the default policy or by order, and record the SelectIndex\r
+      // and SelectProxyType.\r
+      //\r
+      PxeBcSelectDhcp6Offer (Private);\r
+\r
+      if (Private->SelectIndex == 0) {\r
+        Status = EFI_ABORTED;\r
+      } else {\r
+        ASSERT (NewPacket != NULL);\r
+        SelectAd   = &Private->OfferBuffer[Private->SelectIndex - 1].Dhcp6.Packet.Offer;\r
+        *NewPacket = AllocateZeroPool (SelectAd->Size);\r
+        ASSERT (*NewPacket != NULL);\r
+        if (*NewPacket == NULL) {\r
+          return EFI_ABORTED;\r
+        }\r
+\r
+        CopyMem (*NewPacket, SelectAd, SelectAd->Size);\r
+      }\r
+\r
+      break;\r
+\r
+    case Dhcp6RcvdReply:\r
+      //\r
+      // Cache the dhcp ack to Private->Dhcp6Ack, but it's not the final ack in mode data\r
+      // without verification.\r
+      //\r
+      ASSERT (Private->SelectIndex != 0);\r
+      Status = PxeBcCopyDhcp6Ack (Private, Packet, FALSE);\r
+      if (EFI_ERROR (Status)) {\r
+        Status = EFI_ABORTED;\r
+      }\r
+\r
+      break;\r
+\r
+    default:\r
+      ASSERT (0);\r
   }\r
 \r
   return Status;\r
 }\r
 \r
-\r
 /**\r
   Build and send out the request packet for the bootfile, and parse the reply.\r
 \r
@@ -1788,39 +2072,37 @@ PxeBcDhcp6CallBack (
 **/\r
 EFI_STATUS\r
 PxeBcDhcp6Discover (\r
-  IN  PXEBC_PRIVATE_DATA              *Private,\r
-  IN  UINT16                          Type,\r
-  IN  UINT16                          *Layer,\r
-  IN  BOOLEAN                         UseBis,\r
-  IN  EFI_IP_ADDRESS                  *DestIp\r
+  IN  PXEBC_PRIVATE_DATA  *Private,\r
+  IN  UINT16              Type,\r
+  IN  UINT16              *Layer,\r
+  IN  BOOLEAN             UseBis,\r
+  IN  EFI_IP_ADDRESS      *DestIp\r
   )\r
 {\r
-  EFI_PXE_BASE_CODE_UDP_PORT          SrcPort;\r
-  EFI_PXE_BASE_CODE_UDP_PORT          DestPort;\r
-  EFI_PXE_BASE_CODE_MODE              *Mode;\r
-  EFI_PXE_BASE_CODE_PROTOCOL          *PxeBc;\r
-  EFI_PXE_BASE_CODE_DHCPV6_PACKET     *Discover;\r
-  UINTN                               DiscoverLen;\r
-  EFI_DHCP6_PACKET                    *Request;\r
-  UINTN                               RequestLen;\r
-  EFI_DHCP6_PACKET                    *Reply;\r
-  UINT8                               *RequestOpt;\r
-  UINT8                               *DiscoverOpt;\r
-  UINTN                               ReadSize;\r
-  UINT16                              OpFlags;\r
-  UINT16                              OpCode;\r
-  UINT16                              OpLen;\r
-  UINT32                              Xid;\r
-  EFI_STATUS                          Status;\r
-\r
-  PxeBc       = &Private->PxeBc;\r
-  Mode        = PxeBc->Mode;\r
-  Request     = Private->Dhcp6Request;\r
-  SrcPort     = PXEBC_BS_DISCOVER_PORT;\r
-  DestPort    = PXEBC_BS_DISCOVER_PORT;\r
-  OpFlags     = 0;\r
-\r
-  if (!UseBis && Layer != NULL) {\r
+  EFI_PXE_BASE_CODE_UDP_PORT       SrcPort;\r
+  EFI_PXE_BASE_CODE_UDP_PORT       DestPort;\r
+  EFI_PXE_BASE_CODE_MODE           *Mode;\r
+  EFI_PXE_BASE_CODE_PROTOCOL       *PxeBc;\r
+  EFI_PXE_BASE_CODE_DHCPV6_PACKET  *Discover;\r
+  UINTN                            DiscoverLen;\r
+  EFI_DHCP6_PACKET                 *Request;\r
+  UINTN                            RequestLen;\r
+  EFI_DHCP6_PACKET                 *Reply;\r
+  UINT8                            *RequestOpt;\r
+  UINT8                            *DiscoverOpt;\r
+  UINTN                            ReadSize;\r
+  UINT16                           OpCode;\r
+  UINT16                           OpLen;\r
+  UINT32                           Xid;\r
+  EFI_STATUS                       Status;\r
+\r
+  PxeBc    = &Private->PxeBc;\r
+  Mode     = PxeBc->Mode;\r
+  Request  = Private->Dhcp6Request;\r
+  SrcPort  = PXEBC_BS_DISCOVER_PORT;\r
+  DestPort = PXEBC_BS_DISCOVER_PORT;\r
+\r
+  if (!UseBis && (Layer != NULL)) {\r
     *Layer &= EFI_PXE_BASE_CODE_BOOT_LAYER_MASK;\r
   }\r
 \r
@@ -1845,10 +2127,11 @@ PxeBcDhcp6Discover (
   RequestLen              = DiscoverLen;\r
 \r
   while (RequestLen < Request->Length) {\r
-    OpCode = NTOHS (((EFI_DHCP6_PACKET_OPTION *) RequestOpt)->OpCode);\r
-    OpLen  = NTOHS (((EFI_DHCP6_PACKET_OPTION *) RequestOpt)->OpLen);\r
-    if (OpCode != EFI_DHCP6_IA_TYPE_NA &&\r
-        OpCode != EFI_DHCP6_IA_TYPE_TA) {\r
+    OpCode = NTOHS (((EFI_DHCP6_PACKET_OPTION *)RequestOpt)->OpCode);\r
+    OpLen  = NTOHS (((EFI_DHCP6_PACKET_OPTION *)RequestOpt)->OpLen);\r
+    if ((OpCode != EFI_DHCP6_IA_TYPE_NA) &&\r
+        (OpCode != EFI_DHCP6_IA_TYPE_TA))\r
+    {\r
       //\r
       // Copy all the options except IA option.\r
       //\r
@@ -1856,13 +2139,14 @@ PxeBcDhcp6Discover (
       DiscoverOpt += (OpLen + 4);\r
       DiscoverLen += (OpLen + 4);\r
     }\r
+\r
     RequestOpt += (OpLen + 4);\r
     RequestLen += (OpLen + 4);\r
   }\r
 \r
   Status = PxeBc->UdpWrite (\r
                     PxeBc,\r
-                    OpFlags,\r
+                    0,\r
                     &Private->ServerIp,\r
                     &DestPort,\r
                     NULL,\r
@@ -1871,10 +2155,10 @@ PxeBcDhcp6Discover (
                     NULL,\r
                     NULL,\r
                     &DiscoverLen,\r
-                    (VOID *) Discover\r
+                    (VOID *)Discover\r
                     );\r
   if (EFI_ERROR (Status)) {\r
-    return Status;\r
+    goto ON_ERROR;\r
   }\r
 \r
   //\r
@@ -1887,39 +2171,46 @@ PxeBcDhcp6Discover (
   } else {\r
     Reply = &Private->ProxyOffer.Dhcp6.Packet.Offer;\r
   }\r
-  ReadSize = (UINTN) Reply->Size;\r
+\r
+  ReadSize = (UINTN)Reply->Size;\r
 \r
   //\r
   // Start Udp6Read instance\r
   //\r
   Status = Private->Udp6Read->Configure (Private->Udp6Read, &Private->Udp6CfgData);\r
   if (EFI_ERROR (Status)) {\r
-    return Status;\r
+    goto ON_ERROR;\r
   }\r
-  \r
+\r
   Status = PxeBc->UdpRead (\r
                     PxeBc,\r
-                    OpFlags,\r
-                    &Private->StationIp,\r
+                    EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_IP,\r
+                    NULL,\r
                     &SrcPort,\r
                     &Private->ServerIp,\r
                     &DestPort,\r
                     NULL,\r
                     NULL,\r
                     &ReadSize,\r
-                    (VOID *) &Reply->Dhcp6\r
+                    (VOID *)&Reply->Dhcp6\r
                     );\r
   //\r
   // Stop Udp6Read instance\r
   //\r
   Private->Udp6Read->Configure (Private->Udp6Read, NULL);\r
   if (EFI_ERROR (Status)) {\r
-    return Status;\r
+    goto ON_ERROR;\r
   }\r
 \r
   return EFI_SUCCESS;\r
-}\r
 \r
+ON_ERROR:\r
+  if (Discover != NULL) {\r
+    FreePool (Discover);\r
+  }\r
+\r
+  return Status;\r
+}\r
 \r
 /**\r
   Start the DHCPv6 S.A.R.R. process to acquire the IPv6 address and other PXE boot information.\r
@@ -1933,35 +2224,35 @@ PxeBcDhcp6Discover (
 **/\r
 EFI_STATUS\r
 PxeBcDhcp6Sarr (\r
-  IN PXEBC_PRIVATE_DATA            *Private,\r
-  IN EFI_DHCP6_PROTOCOL            *Dhcp6\r
+  IN PXEBC_PRIVATE_DATA  *Private,\r
+  IN EFI_DHCP6_PROTOCOL  *Dhcp6\r
   )\r
 {\r
-  EFI_PXE_BASE_CODE_MODE           *PxeMode;\r
-  EFI_DHCP6_CONFIG_DATA            Config;\r
-  EFI_DHCP6_MODE_DATA              Mode;\r
-  EFI_DHCP6_RETRANSMISSION         *Retransmit;\r
-  EFI_DHCP6_PACKET_OPTION          *OptList[PXEBC_DHCP6_OPTION_MAX_NUM];\r
-  UINT8                            Buffer[PXEBC_DHCP6_OPTION_MAX_SIZE];\r
-  UINT32                           OptCount;\r
-  EFI_STATUS                       Status;\r
-  EFI_IP6_CONFIG_PROTOCOL          *Ip6Cfg;\r
-  EFI_STATUS                       TimerStatus;\r
-  EFI_EVENT                        Timer;\r
-  UINT64                           GetMappingTimeOut;\r
-  UINTN                            DataSize;\r
-  EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS    DadXmits;\r
-\r
-  Status     = EFI_SUCCESS;\r
-  PxeMode    = Private->PxeBc.Mode;\r
-  Ip6Cfg     = Private->Ip6Cfg;\r
-  Timer      = NULL;\r
+  EFI_PXE_BASE_CODE_MODE                    *PxeMode;\r
+  EFI_DHCP6_CONFIG_DATA                     Config;\r
+  EFI_DHCP6_MODE_DATA                       Mode;\r
+  EFI_DHCP6_RETRANSMISSION                  *Retransmit;\r
+  EFI_DHCP6_PACKET_OPTION                   *OptList[PXEBC_DHCP6_OPTION_MAX_NUM];\r
+  UINT8                                     Buffer[PXEBC_DHCP6_OPTION_MAX_SIZE];\r
+  UINT32                                    OptCount;\r
+  EFI_STATUS                                Status;\r
+  EFI_IP6_CONFIG_PROTOCOL                   *Ip6Cfg;\r
+  EFI_STATUS                                TimerStatus;\r
+  EFI_EVENT                                 Timer;\r
+  UINT64                                    GetMappingTimeOut;\r
+  UINTN                                     DataSize;\r
+  EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS  DadXmits;\r
+\r
+  Status  = EFI_SUCCESS;\r
+  PxeMode = Private->PxeBc.Mode;\r
+  Ip6Cfg  = Private->Ip6Cfg;\r
+  Timer   = NULL;\r
 \r
   //\r
   // Build option list for the request packet.\r
   //\r
-  OptCount   = PxeBcBuildDhcp6Options (Private, OptList, Buffer);\r
-  ASSERT (OptCount> 0);\r
+  OptCount = PxeBcBuildDhcp6Options (Private, OptList, Buffer);\r
+  ASSERT (OptCount > 0);\r
 \r
   Retransmit = AllocateZeroPool (sizeof (EFI_DHCP6_RETRANSMISSION));\r
   if (Retransmit == NULL) {\r
@@ -2004,7 +2295,6 @@ PxeBcDhcp6Sarr (
   ZeroMem (Private->OfferCount, sizeof (Private->OfferCount));\r
   ZeroMem (Private->OfferIndex, sizeof (Private->OfferIndex));\r
 \r
-\r
   //\r
   // Start DHCPv6 S.A.R.R. process to acquire IPv6 address.\r
   //\r
@@ -2020,12 +2310,12 @@ PxeBcDhcp6Sarr (
     // Get Duplicate Address Detection Transmits count.\r
     //\r
     DataSize = sizeof (EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS);\r
-    Status = Ip6Cfg->GetData (\r
-                       Ip6Cfg,\r
-                       Ip6ConfigDataTypeDupAddrDetectTransmits,\r
-                       &DataSize,\r
-                       &DadXmits\r
-                       );\r
+    Status   = Ip6Cfg->GetData (\r
+                         Ip6Cfg,\r
+                         Ip6ConfigDataTypeDupAddrDetectTransmits,\r
+                         &DataSize,\r
+                         &DadXmits\r
+                         );\r
     if (EFI_ERROR (Status)) {\r
       Dhcp6->Configure (Dhcp6, NULL);\r
       return Status;\r
@@ -2038,7 +2328,7 @@ PxeBcDhcp6Sarr (
     }\r
 \r
     GetMappingTimeOut = TICKS_PER_SECOND * DadXmits.DupAddrDetectTransmits + PXEBC_DAD_ADDITIONAL_DELAY;\r
-    Status = gBS->SetTimer (Timer, TimerRelative, GetMappingTimeOut);\r
+    Status            = gBS->SetTimer (Timer, TimerRelative, GetMappingTimeOut);\r
     if (EFI_ERROR (Status)) {\r
       gBS->CloseEvent (Timer);\r
       Dhcp6->Configure (Dhcp6, NULL);\r
@@ -2046,19 +2336,20 @@ PxeBcDhcp6Sarr (
     }\r
 \r
     do {\r
-      \r
       TimerStatus = gBS->CheckEvent (Timer);\r
       if (!EFI_ERROR (TimerStatus)) {\r
         Status = Dhcp6->Start (Dhcp6);\r
       }\r
     } while (TimerStatus == EFI_NOT_READY);\r
-    \r
+\r
     gBS->CloseEvent (Timer);\r
   }\r
+\r
   if (EFI_ERROR (Status)) {\r
     if (Status == EFI_ICMP_ERROR) {\r
       PxeMode->IcmpErrorReceived = TRUE;\r
     }\r
+\r
     Dhcp6->Configure (Dhcp6, NULL);\r
     return Status;\r
   }\r
@@ -2072,15 +2363,22 @@ PxeBcDhcp6Sarr (
     return Status;\r
   }\r
 \r
-  ASSERT (Mode.Ia->State == Dhcp6Bound);\r
+  ASSERT ((Mode.Ia != NULL) && (Mode.Ia->State == Dhcp6Bound));\r
   //\r
   // DHCP6 doesn't have an option to specify the router address on the subnet, the only way to get the\r
   // router address in IP6 is the router discovery mechanism (the RS and RA, which only be handled when\r
   // the IP policy is Automatic). So we just hold the station IP address here and leave the IP policy as\r
-  // Automatic, until we get the server IP address. This could let IP6 driver finish the router discovery \r
+  // Automatic, until we get the server IP address. This could let IP6 driver finish the router discovery\r
   // to find a valid router address.\r
   //\r
   CopyMem (&Private->TmpStationIp.v6, &Mode.Ia->IaAddress[0].IpAddress, sizeof (EFI_IPv6_ADDRESS));\r
+  if (Mode.ClientId != NULL) {\r
+    FreePool (Mode.ClientId);\r
+  }\r
+\r
+  if (Mode.Ia != NULL) {\r
+    FreePool (Mode.Ia);\r
+  }\r
 \r
   //\r
   // Check the selected offer whether BINL retry is needed.\r
@@ -2090,6 +2388,6 @@ PxeBcDhcp6Sarr (
     Dhcp6->Stop (Dhcp6);\r
     return Status;\r
   }\r
-  \r
+\r
   return EFI_SUCCESS;\r
 }\r