]> git.proxmox.com Git - mirror_edk2.git/blobdiff - NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c
IntelFsp2Pkg: Removing FSP Data Table
[mirror_edk2.git] / NetworkPkg / UefiPxeBcDxe / PxeBcDhcp6.c
index 35bdc57479caf54e17ca591861a28d41a6cd082c..45377e3626463410a968f3ec51ac1198ef6a9358 100644 (file)
@@ -2,7 +2,7 @@
   Functions implementation related with DHCPv6 for UefiPxeBc Driver.\r
 \r
   (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>\r
-  Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2009 - 2016, 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
@@ -92,18 +92,19 @@ PxeBcBuildDhcp6Options (
   //\r
   // Append client option request option\r
   //\r
-  OptList[Index]->OpCode     = HTONS (PXEBC_DHCP6_OPT_ORO);\r
-  OptList[Index]->OpLen      = HTONS (4);\r
+  OptList[Index]->OpCode     = HTONS (DHCP6_OPT_ORO);\r
+  OptList[Index]->OpLen      = HTONS (6);\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
+  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
   Index++;\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]->OpCode     = HTONS (DHCP6_OPT_UNDI);\r
   OptList[Index]->OpLen      = HTONS ((UINT16)3);\r
   OptEnt.Undi                = (PXEBC_DHCP6_OPTION_UNDI *) OptList[Index]->Data;\r
 \r
@@ -123,7 +124,7 @@ PxeBcBuildDhcp6Options (
   //\r
   // Append client system architecture option\r
   //\r
-  OptList[Index]->OpCode     = HTONS (PXEBC_DHCP6_OPT_ARCH);\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
@@ -134,7 +135,7 @@ PxeBcBuildDhcp6Options (
   //\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]->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
@@ -216,10 +217,173 @@ PxeBcFreeBootFileOption (
   }\r
 }\r
 \r
+/**\r
+  Retrieve the boot server address using the EFI_DNS6_PROTOCOL.\r
+\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
+EFI_STATUS\r
+PxeBcDns6 (\r
+  IN PXEBC_PRIVATE_DATA           *Private,\r
+  IN     CHAR16                   *HostName,\r
+     OUT EFI_IPv6_ADDRESS         *IpAddress                \r
+  )\r
+{\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
+  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
+  // 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
+    if (Token.RspData.H2AData->IpCount == 0 || Token.RspData.H2AData->IpList == NULL) {\r
+      Status = EFI_DEVICE_ERROR;\r
+      goto Exit;\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
+  if (Token.RspData.H2AData != NULL) {\r
+    if (Token.RspData.H2AData->IpList != NULL) {\r
+      FreePool (Token.RspData.H2AData->IpList);\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
@@ -232,6 +396,7 @@ PxeBcFreeBootFileOption (
 **/\r
 EFI_STATUS\r
 PxeBcExtractBootFileUrl (\r
+  IN PXEBC_PRIVATE_DATA      *Private,\r
      OUT UINT8               **FileName,\r
   IN OUT EFI_IPv6_ADDRESS    *SrvAddr,\r
   IN     CHAR8               *BootFile,\r
@@ -247,8 +412,12 @@ PxeBcExtractBootFileUrl (
   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,8 +433,8 @@ 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
@@ -291,43 +460,76 @@ 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
+    if (*ServerAddress != PXEBC_ADDR_END_DELIMITER) {\r
+      FreePool (TmpStr);\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+    \r
+    *ServerAddress = '\0';\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
+    }\r
 \r
-  ServerAddressOption ++;\r
-  ServerAddress = ServerAddressOption;\r
-  while (*ServerAddress != '\0' && *ServerAddress != PXEBC_ADDR_END_DELIMITER) {\r
-    ServerAddress++;\r
-  }\r
+  } else {\r
+    IpExpressedUrl = FALSE;\r
+    ServerAddress = ServerAddressOption;\r
+    while (*ServerAddress != '\0' && *ServerAddress != PXEBC_TFTP_URL_SEPARATOR) {\r
+      ServerAddress++;\r
+    }\r
 \r
-  if (*ServerAddress != PXEBC_ADDR_END_DELIMITER) {\r
-    FreePool (TmpStr);\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
+    if (*ServerAddress != PXEBC_TFTP_URL_SEPARATOR) {\r
+      FreePool (TmpStr);\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+    *ServerAddress = '\0';\r
 \r
-  *ServerAddress = '\0';\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
+    AsciiStrToUnicodeStrS (\r
+      ServerAddressOption,\r
+      HostName,\r
+      Len\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
+    //\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
+  if (IpExpressedUrl) {\r
+    if (*BootFileNamePtr != PXEBC_TFTP_URL_SEPARATOR) {\r
+      FreePool (TmpStr);\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+    ++BootFileNamePtr;\r
   }\r
 \r
-  ++BootFileNamePtr;\r
   BootFileNameLen = (UINT16)(Length - (UINT16) ((UINTN)BootFileNamePtr - (UINTN)TmpStr) + 1);\r
   if (BootFileNameLen != 0 || FileName != NULL) {\r
     //\r
@@ -471,17 +673,19 @@ PxeBcParseDhcp6Packet (
   //\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
@@ -497,7 +701,7 @@ PxeBcParseDhcp6Packet (
     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
       IsProxyOffer = FALSE;\r
@@ -713,7 +917,7 @@ PxeBcRequestBootService (
   Option = PxeBcDhcp6SeekOption (\r
              ProxyOffer->Dhcp6.Option,\r
              ProxyOffer->Length - 4,\r
-             PXEBC_DHCP6_OPT_SERVER_ID\r
+             DHCP6_OPT_SERVER_ID\r
              );\r
   if (Option == NULL) {\r
     return EFI_NOT_FOUND;\r
@@ -732,7 +936,7 @@ PxeBcRequestBootService (
     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
+        OpCode != DHCP6_OPT_SERVER_ID\r
         ) {\r
       //\r
       // Copy all the options except IA option and Server ID\r
@@ -751,7 +955,7 @@ PxeBcRequestBootService (
   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
@@ -864,6 +1068,7 @@ 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
@@ -1115,6 +1320,14 @@ PxeBcHandleDhcp6Offer (
   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
+    CopyMem (Private->DnsServer, Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->Data, sizeof (EFI_IPv6_ADDRESS));\r
+  }\r
+\r
   if (Cache6->OfferType == PxeOfferTypeDhcpBinl) {\r
     //\r
     // DhcpBinl offer is selected, so need try to request bootfilename by this offer.\r
@@ -1376,16 +1589,15 @@ PxeBcRegisterIp6Address (
   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
+  EFI_IPv6_ADDRESS                 *Ip6Addr;\r
+  UINTN                            Index;\r
 \r
   Status     = EFI_SUCCESS;\r
-  TimeOutEvt = NULL;\r
   MappedEvt  = NULL;\r
+  Ip6Addr    = NULL;\r
   DataSize   = sizeof (EFI_IP6_CONFIG_POLICY);\r
   Ip6Cfg     = Private->Ip6Cfg;\r
   Ip6        = Private->Ip6;\r
@@ -1426,34 +1638,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,6 +1652,7 @@ PxeBcRegisterIp6Address (
     goto ON_EXIT;\r
   }\r
 \r
+  Private->IsAddressOk = FALSE;\r
   Status = Ip6Cfg->RegisterDataNotify (\r
                      Ip6Cfg,\r
                      Ip6ConfigDataTypeManualAddress,\r
@@ -1485,23 +1670,54 @@ PxeBcRegisterIp6Address (
                      );\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
+    // 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
-  //\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
+    Ip6Addr = AllocatePool (DataSize);\r
+    if (Ip6Addr == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\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
-  while (EFI_ERROR (gBS->CheckEvent (TimeOutEvt))) {\r
-    Ip6->Poll (Ip6);\r
-    if (Private->IsAddressOk) {\r
-      Status = EFI_SUCCESS;\r
-      break;\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
+    if (Index == DataSize / sizeof (EFI_IPv6_ADDRESS)) {\r
+      Status = EFI_ABORTED;\r
+      goto ON_EXIT;\r
     }\r
   }\r
-\r
+  \r
   //\r
   // Set the default gateway address back if needed.\r
   //\r
@@ -1526,8 +1742,8 @@ ON_EXIT:
               );\r
     gBS->CloseEvent (MappedEvt);\r
   }\r
-  if (TimeOutEvt != NULL) {\r
-    gBS->CloseEvent (TimeOutEvt);\r
+  if (Ip6Addr != NULL) {\r
+    FreePool (Ip6Addr);\r
   }\r
   return Status;\r
 }\r
@@ -2070,7 +2286,7 @@ 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
@@ -2079,7 +2295,12 @@ PxeBcDhcp6Sarr (
   // to find a valid router address.\r
   //\r
   CopyMem (&Private->TmpStationIp.v6, &Mode.Ia->IaAddress[0].IpAddress, sizeof (EFI_IPv6_ADDRESS));\r
-\r
+  if (Mode.ClientId != NULL) {\r
+    FreePool (Mode.ClientId);\r
+  }\r
+  if (Mode.Ia != NULL) {\r
+    FreePool (Mode.Ia);\r
+  }\r
   //\r
   // Check the selected offer whether BINL retry is needed.\r
   //\r