]> git.proxmox.com Git - mirror_edk2.git/blobdiff - NetworkPkg/IScsiDxe/IScsiMisc.c
NetworkPkg: Apply uncrustify changes
[mirror_edk2.git] / NetworkPkg / IScsiDxe / IScsiMisc.c
index 731081f1df85fa86ce2e49a99ae886a46e39a812..b3ea90158f51848776568cbfe2ca849f5efc2d4f 100644 (file)
@@ -1,14 +1,8 @@
 /** @file\r
   Miscellaneous routines for iSCSI driver.\r
 \r
-Copyright (c) 2004 - 2011, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution.  The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\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
+Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
@@ -20,31 +14,30 @@ GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8  IScsiHexString[] = "0123456789ABCDEFa
   Removes (trims) specified leading and trailing characters from a string.\r
 \r
   @param[in, out] Str   Pointer to the null-terminated string to be trimmed.\r
-                        On return, Str will hold the trimmed string. \r
+                        On return, Str will hold the trimmed string.\r
 \r
   @param[in]      CharC Character will be trimmed from str.\r
 \r
 **/\r
 VOID\r
 IScsiStrTrim (\r
-  IN OUT CHAR16   *Str,\r
-  IN     CHAR16   CharC\r
+  IN OUT CHAR16  *Str,\r
+  IN     CHAR16  CharC\r
   )\r
 {\r
   CHAR16  *Pointer1;\r
   CHAR16  *Pointer2;\r
-  \r
+\r
   if (*Str == 0) {\r
-    return ;\r
+    return;\r
   }\r
-  \r
+\r
   //\r
   // Trim off the leading and trailing characters c\r
   //\r
   for (Pointer1 = Str; (*Pointer1 != 0) && (*Pointer1 == CharC); Pointer1++) {\r
-    ;\r
   }\r
-  \r
+\r
   Pointer2 = Str;\r
   if (Pointer2 == Pointer1) {\r
     while (*Pointer1 != 0) {\r
@@ -52,19 +45,19 @@ IScsiStrTrim (
       Pointer1++;\r
     }\r
   } else {\r
-    while (*Pointer1 != 0) {    \r
-    *Pointer2 = *Pointer1;    \r
-    Pointer1++;\r
-    Pointer2++;\r
+    while (*Pointer1 != 0) {\r
+      *Pointer2 = *Pointer1;\r
+      Pointer1++;\r
+      Pointer2++;\r
     }\r
+\r
     *Pointer2 = 0;\r
   }\r
-  \r
-  \r
-  for (Pointer1 = Str + StrLen(Str) - 1; Pointer1 >= Str && *Pointer1 == CharC; Pointer1--) {\r
-    ;\r
+\r
+  for (Pointer1 = Str + StrLen (Str) - 1; Pointer1 >= Str && *Pointer1 == CharC; Pointer1--) {\r
   }\r
-  if  (Pointer1 !=  Str + StrLen(Str) - 1) { \r
+\r
+  if (Pointer1 !=  Str + StrLen (Str) - 1) {\r
     *(Pointer1 + 1) = 0;\r
   }\r
 }\r
@@ -107,10 +100,9 @@ IScsiGetSubnetMaskPrefixLength (
     Len++;\r
   }\r
 \r
-  return (UINT8) (32 - Len);\r
+  return (UINT8)(32 - Len);\r
 }\r
 \r
-\r
 /**\r
   Convert the hexadecimal encoded LUN string into the 64-bit LUN.\r
 \r
@@ -131,18 +123,18 @@ IScsiAsciiStrToLun (
   CHAR8   TemStr[2];\r
   UINT8   TemValue;\r
   UINT16  Value[4];\r
-  \r
+\r
   ZeroMem (Lun, 8);\r
   ZeroMem (TemStr, 2);\r
-  ZeroMem ((UINT8 *) Value, sizeof (Value));\r
-  SizeStr    = AsciiStrLen (Str);  \r
+  ZeroMem ((UINT8 *)Value, sizeof (Value));\r
+  SizeStr    = AsciiStrLen (Str);\r
   IndexValue = 0;\r
   IndexNum   = 0;\r
 \r
-  for (Index = 0; Index < SizeStr; Index ++) {\r
+  for (Index = 0; Index < SizeStr; Index++) {\r
     TemStr[0] = Str[Index];\r
-    TemValue = (UINT8) AsciiStrHexToUint64 (TemStr);\r
-    if (TemValue == 0 && TemStr[0] != '0') {\r
+    TemValue  = (UINT8)AsciiStrHexToUint64 (TemStr);\r
+    if ((TemValue == 0) && (TemStr[0] != '0')) {\r
       if ((TemStr[0] != '-') || (IndexNum == 0)) {\r
         //\r
         // Invalid Lun Char.\r
@@ -150,7 +142,7 @@ IScsiAsciiStrToLun (
         return EFI_INVALID_PARAMETER;\r
       }\r
     }\r
-    \r
+\r
     if ((TemValue == 0) && (TemStr[0] == '-')) {\r
       //\r
       // Next Lun value.\r
@@ -161,30 +153,31 @@ IScsiAsciiStrToLun (
         //\r
         return EFI_INVALID_PARAMETER;\r
       }\r
+\r
       //\r
       // Restart str index for the next lun value.\r
       //\r
       IndexNum = 0;\r
       continue;\r
     }\r
-    \r
+\r
     if (++IndexNum > 4) {\r
-      //     \r
+      //\r
       // Each Lun Str can't exceed size 4, because it will be as UINT16 value.\r
       //\r
       return EFI_INVALID_PARAMETER;\r
     }\r
-    \r
+\r
     //\r
     // Combine UINT16 value.\r
     //\r
-    Value[IndexValue] = (UINT16) ((Value[IndexValue] << 4) + TemValue);\r
+    Value[IndexValue] = (UINT16)((Value[IndexValue] << 4) + TemValue);\r
   }\r
\r
-  for (Index = 0; Index <= IndexValue; Index ++) {\r
-    *((UINT16 *) &Lun[Index * 2]) =  HTONS (Value[Index]);\r
+\r
+  for (Index = 0; Index <= IndexValue; Index++) {\r
+    *((UINT16 *)&Lun[Index * 2]) =  HTONS (Value[Index]);\r
   }\r
-  \r
+\r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -207,16 +200,15 @@ IScsiLunToUnicodeStr (
   TempStr = Str;\r
 \r
   for (Index = 0; Index < 4; Index++) {\r
-\r
     if ((Lun[2 * Index] | Lun[2 * Index + 1]) == 0) {\r
-      StrCpy (TempStr, L"0-");\r
+      CopyMem (TempStr, L"0-", sizeof (L"0-"));\r
     } else {\r
-      TempStr[0]  = (CHAR16) IScsiHexString[Lun[2 * Index] >> 4];\r
-      TempStr[1]  = (CHAR16) IScsiHexString[Lun[2 * Index] & 0x0F];\r
-      TempStr[2]  = (CHAR16) IScsiHexString[Lun[2 * Index + 1] >> 4];\r
-      TempStr[3]  = (CHAR16) IScsiHexString[Lun[2 * Index + 1] & 0x0F];\r
-      TempStr[4]  = L'-';\r
-      TempStr[5]  = 0;\r
+      TempStr[0] = (CHAR16)IScsiHexString[Lun[2 * Index] >> 4];\r
+      TempStr[1] = (CHAR16)IScsiHexString[Lun[2 * Index] & 0x0F];\r
+      TempStr[2] = (CHAR16)IScsiHexString[Lun[2 * Index + 1] >> 4];\r
+      TempStr[3] = (CHAR16)IScsiHexString[Lun[2 * Index + 1] & 0x0F];\r
+      TempStr[4] = L'-';\r
+      TempStr[5] = 0;\r
 \r
       IScsiStrTrim (TempStr, L'0');\r
     }\r
@@ -224,6 +216,10 @@ IScsiLunToUnicodeStr (
     TempStr += StrLen (TempStr);\r
   }\r
 \r
+  //\r
+  // Remove the last '-'\r
+  //\r
+  ASSERT (StrLen (Str) >= 1);\r
   Str[StrLen (Str) - 1] = 0;\r
 \r
   for (Index = StrLen (Str) - 1; Index > 1; Index = Index - 2) {\r
@@ -249,33 +245,31 @@ IScsiLunToUnicodeStr (
 **/\r
 EFI_STATUS\r
 IScsiAsciiStrToIp (\r
-  IN  CHAR8             *Str,\r
-  IN  UINT8             IpMode,\r
-  OUT EFI_IP_ADDRESS    *Ip\r
+  IN  CHAR8           *Str,\r
+  IN  UINT8           IpMode,\r
+  OUT EFI_IP_ADDRESS  *Ip\r
   )\r
 {\r
-  EFI_STATUS            Status;\r
+  EFI_STATUS  Status;\r
 \r
-  if (IpMode == IP_MODE_IP4 || IpMode == IP_MODE_AUTOCONFIG_IP4) {\r
+  if ((IpMode == IP_MODE_IP4) || (IpMode == IP_MODE_AUTOCONFIG_IP4)) {\r
     return NetLibAsciiStrToIp4 (Str, &Ip->v4);\r
-\r
-  } else if (IpMode == IP_MODE_IP6 || IpMode == IP_MODE_AUTOCONFIG_IP6) {\r
+  } else if ((IpMode == IP_MODE_IP6) || (IpMode == IP_MODE_AUTOCONFIG_IP6)) {\r
     return NetLibAsciiStrToIp6 (Str, &Ip->v6);\r
-\r
   } else if (IpMode == IP_MODE_AUTOCONFIG) {\r
     Status = NetLibAsciiStrToIp4 (Str, &Ip->v4);\r
     if (!EFI_ERROR (Status)) {\r
       return Status;\r
     }\r
-    return NetLibAsciiStrToIp6 (Str, &Ip->v6);\r
 \r
+    return NetLibAsciiStrToIp6 (Str, &Ip->v6);\r
   }\r
 \r
   return EFI_INVALID_PARAMETER;\r
 }\r
 \r
 /**\r
-  Convert the mac address into a hexadecimal encoded "-" seperated string.\r
+  Convert the mac address into a hexadecimal encoded "-" separated string.\r
 \r
   @param[in]  Mac     The mac address.\r
   @param[in]  Len     Length in bytes of the mac address.\r
@@ -295,14 +289,14 @@ IScsiMacAddrToStr (
   CHAR16  *String;\r
 \r
   for (Index = 0; Index < Len; Index++) {\r
-    Str[3 * Index]      = (CHAR16) IScsiHexString[(Mac->Addr[Index] >> 4) & 0x0F];\r
-    Str[3 * Index + 1]  = (CHAR16) IScsiHexString[Mac->Addr[Index] & 0x0F];\r
-    Str[3 * Index + 2]  = L':';\r
+    Str[3 * Index]     = (CHAR16)IScsiHexString[(Mac->Addr[Index] >> 4) & 0x0F];\r
+    Str[3 * Index + 1] = (CHAR16)IScsiHexString[Mac->Addr[Index] & 0x0F];\r
+    Str[3 * Index + 2] = L':';\r
   }\r
 \r
-  String = &Str[3 * Index - 1] ;\r
+  String = &Str[3 * Index - 1];\r
   if (VlanId != 0) {\r
-    String += UnicodeSPrint (String, 6 * sizeof (CHAR16), L"\\%04x", (UINTN) VlanId);\r
+    String += UnicodeSPrint (String, 6 * sizeof (CHAR16), L"\\%04x", (UINTN)VlanId);\r
   }\r
 \r
   *String = L'\0';\r
@@ -316,32 +310,44 @@ IScsiMacAddrToStr (
   @param[in, out]  HexStr      Pointer to the string.\r
   @param[in, out]  HexLength   The length of the string.\r
 \r
-  @retval EFI_SUCCESS          The binary data is converted to the hexadecimal string \r
+  @retval EFI_SUCCESS          The binary data is converted to the hexadecimal string\r
                                and the length of the string is updated.\r
   @retval EFI_BUFFER_TOO_SMALL The string is too small.\r
+  @retval EFI_BAD_BUFFER_SIZE  BinLength is too large for hex encoding.\r
   @retval EFI_INVALID_PARAMETER The IP string is malformatted.\r
 \r
 **/\r
 EFI_STATUS\r
 IScsiBinToHex (\r
-  IN     UINT8  *BinBuffer,\r
-  IN     UINT32 BinLength,\r
-  IN OUT CHAR8  *HexStr,\r
-  IN OUT UINT32 *HexLength\r
+  IN     UINT8   *BinBuffer,\r
+  IN     UINT32  BinLength,\r
+  IN OUT CHAR8   *HexStr,\r
+  IN OUT UINT32  *HexLength\r
   )\r
 {\r
-  UINTN Index;\r
+  UINT32  HexLengthMin;\r
+  UINT32  HexLengthProvided;\r
+  UINT32  Index;\r
 \r
   if ((HexStr == NULL) || (BinBuffer == NULL) || (BinLength == 0)) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  if (((*HexLength) - 3) < BinLength * 2) {\r
-    *HexLength = BinLength * 2 + 3;\r
+  //\r
+  // Safely calculate: HexLengthMin := BinLength * 2 + 3.\r
+  //\r
+  if (RETURN_ERROR (SafeUint32Mult (BinLength, 2, &HexLengthMin)) ||\r
+      RETURN_ERROR (SafeUint32Add (HexLengthMin, 3, &HexLengthMin)))\r
+  {\r
+    return EFI_BAD_BUFFER_SIZE;\r
+  }\r
+\r
+  HexLengthProvided = *HexLength;\r
+  *HexLength        = HexLengthMin;\r
+  if (HexLengthProvided < HexLengthMin) {\r
     return EFI_BUFFER_TOO_SMALL;\r
   }\r
 \r
-  *HexLength = BinLength * 2 + 3;\r
   //\r
   // Prefix for Hex String.\r
   //\r
@@ -358,31 +364,36 @@ IScsiBinToHex (
   return EFI_SUCCESS;\r
 }\r
 \r
-\r
 /**\r
   Convert the hexadecimal string into a binary encoded buffer.\r
 \r
-  @param[in, out]  BinBuffer   The binary buffer.\r
-  @param[in, out]  BinLength   Length of the binary buffer.\r
-  @param[in]       HexStr      The hexadecimal string.\r
-\r
-  @retval EFI_SUCCESS          The hexadecimal string is converted into a binary\r
-                               encoded buffer.\r
-  @retval EFI_BUFFER_TOO_SMALL The binary buffer is too small to hold the converted data.\r
-\r
+  @param[in, out]  BinBuffer    The binary buffer.\r
+  @param[in, out]  BinLength    Length of the binary buffer.\r
+  @param[in]       HexStr       The hexadecimal string.\r
+\r
+  @retval EFI_SUCCESS           The hexadecimal string is converted into a\r
+                                binary encoded buffer.\r
+  @retval EFI_INVALID_PARAMETER Invalid hex encoding found in HexStr.\r
+  @retval EFI_BAD_BUFFER_SIZE   The length of HexStr is too large for decoding:\r
+                                the decoded size cannot be expressed in\r
+                                BinLength on output.\r
+  @retval EFI_BUFFER_TOO_SMALL  The binary buffer is too small to hold the\r
+                                converted data.\r
 **/\r
 EFI_STATUS\r
 IScsiHexToBin (\r
-  IN OUT UINT8  *BinBuffer,\r
-  IN OUT UINT32 *BinLength,\r
-  IN     CHAR8  *HexStr\r
+  IN OUT UINT8   *BinBuffer,\r
+  IN OUT UINT32  *BinLength,\r
+  IN     CHAR8   *HexStr\r
   )\r
 {\r
+  UINTN   BinLengthMin;\r
+  UINT32  BinLengthProvided;\r
   UINTN   Index;\r
   UINTN   Length;\r
   UINT8   Digit;\r
   CHAR8   TemStr[2];\r
-  \r
+\r
   ZeroMem (TemStr, sizeof (TemStr));\r
 \r
   //\r
@@ -391,31 +402,50 @@ IScsiHexToBin (
   if ((HexStr[0] == '0') && ((HexStr[1] == 'x') || (HexStr[1] == 'X'))) {\r
     HexStr += 2;\r
   }\r
-  \r
+\r
   Length = AsciiStrLen (HexStr);\r
 \r
-  for (Index = 0; Index < Length; Index ++) {\r
+  //\r
+  // Reject an empty hex string; reject a stray nibble.\r
+  //\r
+  if ((Length == 0) || (Length % 2 != 0)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // Check if the caller provides enough room for the decoded blob.\r
+  //\r
+  BinLengthMin = Length / 2;\r
+  if (BinLengthMin > MAX_UINT32) {\r
+    return EFI_BAD_BUFFER_SIZE;\r
+  }\r
+\r
+  BinLengthProvided = *BinLength;\r
+  *BinLength        = (UINT32)BinLengthMin;\r
+  if (BinLengthProvided < BinLengthMin) {\r
+    return EFI_BUFFER_TOO_SMALL;\r
+  }\r
+\r
+  for (Index = 0; Index < Length; Index++) {\r
     TemStr[0] = HexStr[Index];\r
-    Digit = (UINT8) AsciiStrHexToUint64 (TemStr);\r
-    if (Digit == 0 && TemStr[0] != '0') {\r
+    Digit     = (UINT8)AsciiStrHexToUint64 (TemStr);\r
+    if ((Digit == 0) && (TemStr[0] != '0')) {\r
       //\r
-      // Invalid Lun Char.\r
+      // Invalid Hex Char.\r
       //\r
-      break;\r
+      return EFI_INVALID_PARAMETER;\r
     }\r
+\r
     if ((Index & 1) == 0) {\r
-      BinBuffer [Index/2] = Digit;\r
+      BinBuffer[Index/2] = Digit;\r
     } else {\r
-      BinBuffer [Index/2] = (UINT8) ((BinBuffer [Index/2] << 4) + Digit);\r
+      BinBuffer[Index/2] = (UINT8)((BinBuffer[Index/2] << 4) + Digit);\r
     }\r
   }\r
-  \r
-  *BinLength = (UINT32) ((Index + 1)/2);\r
 \r
   return EFI_SUCCESS;\r
 }\r
 \r
-\r
 /**\r
   Convert the decimal-constant string or hex-constant string into a numerical value.\r
 \r
@@ -438,7 +468,6 @@ IScsiNetNtoi (
   return AsciiStrDecimalToUintn (Str);\r
 }\r
 \r
-\r
 /**\r
   Generate random numbers.\r
 \r
@@ -456,16 +485,120 @@ IScsiGenRandom (
 \r
   while (RandLength > 0) {\r
     Random  = NET_RANDOM (NetRandomInitSeed ());\r
-    *Rand++ = (UINT8) (Random);\r
+    *Rand++ = (UINT8)(Random);\r
     RandLength--;\r
   }\r
 }\r
 \r
+/**\r
+  Check whether UNDI protocol supports IPv6.\r
+\r
+  @param[in]   ControllerHandle    Controller handle.\r
+  @param[in]   Image               Handle of the image.\r
+  @param[out]  Ipv6Support         TRUE if UNDI supports IPv6.\r
+\r
+  @retval EFI_SUCCESS            Get the result whether UNDI supports IPv6 by NII or AIP protocol successfully.\r
+  @retval EFI_NOT_FOUND          Don't know whether UNDI supports IPv6 since NII or AIP is not available.\r
+\r
+**/\r
+EFI_STATUS\r
+IScsiCheckIpv6Support (\r
+  IN  EFI_HANDLE  ControllerHandle,\r
+  IN  EFI_HANDLE  Image,\r
+  OUT BOOLEAN     *Ipv6Support\r
+  )\r
+{\r
+  EFI_HANDLE                        Handle;\r
+  EFI_ADAPTER_INFORMATION_PROTOCOL  *Aip;\r
+  EFI_STATUS                        Status;\r
+  EFI_GUID                          *InfoTypesBuffer;\r
+  UINTN                             InfoTypeBufferCount;\r
+  UINTN                             TypeIndex;\r
+  BOOLEAN                           Supported;\r
+  VOID                              *InfoBlock;\r
+  UINTN                             InfoBlockSize;\r
+\r
+  EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL  *Nii;\r
+\r
+  ASSERT (Ipv6Support != NULL);\r
+\r
+  //\r
+  // Check whether the UNDI supports IPv6 by NII protocol.\r
+  //\r
+  Status = gBS->OpenProtocol (\r
+                  ControllerHandle,\r
+                  &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
+                  (VOID **)&Nii,\r
+                  Image,\r
+                  ControllerHandle,\r
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                  );\r
+  if (Status == EFI_SUCCESS) {\r
+    *Ipv6Support = Nii->Ipv6Supported;\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // Get the NIC handle by SNP protocol.\r
+  //\r
+  Handle = NetLibGetSnpHandle (ControllerHandle, NULL);\r
+  if (Handle == NULL) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  Aip    = NULL;\r
+  Status = gBS->HandleProtocol (\r
+                  Handle,\r
+                  &gEfiAdapterInformationProtocolGuid,\r
+                  (VOID *)&Aip\r
+                  );\r
+  if (EFI_ERROR (Status) || (Aip == NULL)) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  InfoTypesBuffer     = NULL;\r
+  InfoTypeBufferCount = 0;\r
+  Status              = Aip->GetSupportedTypes (Aip, &InfoTypesBuffer, &InfoTypeBufferCount);\r
+  if (EFI_ERROR (Status) || (InfoTypesBuffer == NULL)) {\r
+    FreePool (InfoTypesBuffer);\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  Supported = FALSE;\r
+  for (TypeIndex = 0; TypeIndex < InfoTypeBufferCount; TypeIndex++) {\r
+    if (CompareGuid (&InfoTypesBuffer[TypeIndex], &gEfiAdapterInfoUndiIpv6SupportGuid)) {\r
+      Supported = TRUE;\r
+      break;\r
+    }\r
+  }\r
+\r
+  FreePool (InfoTypesBuffer);\r
+  if (!Supported) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  //\r
+  // We now have adapter information block.\r
+  //\r
+  InfoBlock     = NULL;\r
+  InfoBlockSize = 0;\r
+  Status        = Aip->GetInformation (Aip, &gEfiAdapterInfoUndiIpv6SupportGuid, &InfoBlock, &InfoBlockSize);\r
+  if (EFI_ERROR (Status) || (InfoBlock == NULL)) {\r
+    FreePool (InfoBlock);\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  *Ipv6Support = ((EFI_ADAPTER_INFO_UNDI_IPV6_SUPPORT *)InfoBlock)->Ipv6Support;\r
+  FreePool (InfoBlock);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
 \r
 /**\r
   Record the NIC info in global structure.\r
 \r
   @param[in]  Controller         The handle of the controller.\r
+  @param[in]  Image              Handle of the image.\r
 \r
   @retval EFI_SUCCESS            The operation is completed.\r
   @retval EFI_OUT_OF_RESOURCES   Do not have sufficient resources to finish this\r
@@ -474,15 +607,16 @@ IScsiGenRandom (
 **/\r
 EFI_STATUS\r
 IScsiAddNic (\r
-  IN EFI_HANDLE  Controller\r
+  IN EFI_HANDLE  Controller,\r
+  IN EFI_HANDLE  Image\r
   )\r
 {\r
-  EFI_STATUS                  Status;\r
-  ISCSI_NIC_INFO              *NicInfo;\r
-  LIST_ENTRY                  *Entry;\r
-  EFI_MAC_ADDRESS             MacAddr;\r
-  UINTN                       HwAddressSize;\r
-  UINT16                      VlanId;\r
+  EFI_STATUS       Status;\r
+  ISCSI_NIC_INFO   *NicInfo;\r
+  LIST_ENTRY       *Entry;\r
+  EFI_MAC_ADDRESS  MacAddr;\r
+  UINTN            HwAddressSize;\r
+  UINT16           VlanId;\r
 \r
   //\r
   // Get MAC address of this network device.\r
@@ -502,10 +636,24 @@ IScsiAddNic (
   //\r
   NET_LIST_FOR_EACH (Entry, &mPrivate->NicInfoList) {\r
     NicInfo = NET_LIST_USER_STRUCT (Entry, ISCSI_NIC_INFO, Link);\r
-    if (NicInfo->HwAddressSize == HwAddressSize &&\r
-        CompareMem (&NicInfo->PermanentAddress, MacAddr.Addr, HwAddressSize) == 0 &&\r
-        NicInfo->VlanId == VlanId) {\r
+    if ((NicInfo->HwAddressSize == HwAddressSize) &&\r
+        (CompareMem (&NicInfo->PermanentAddress, MacAddr.Addr, HwAddressSize) == 0) &&\r
+        (NicInfo->VlanId == VlanId))\r
+    {\r
       mPrivate->CurrentNic = NicInfo->NicIndex;\r
+\r
+      //\r
+      // Set IPv6 available flag.\r
+      //\r
+      Status = IScsiCheckIpv6Support (Controller, Image, &NicInfo->Ipv6Available);\r
+      if (EFI_ERROR (Status)) {\r
+        //\r
+        // Fail to get the data whether UNDI supports IPv6.\r
+        // Set default value to TRUE.\r
+        //\r
+        NicInfo->Ipv6Available = TRUE;\r
+      }\r
+\r
       return EFI_SUCCESS;\r
     }\r
 \r
@@ -523,10 +671,22 @@ IScsiAddNic (
   }\r
 \r
   CopyMem (&NicInfo->PermanentAddress, MacAddr.Addr, HwAddressSize);\r
-  NicInfo->HwAddressSize  = (UINT32) HwAddressSize;\r
-  NicInfo->VlanId         = VlanId;\r
-  NicInfo->NicIndex       = (UINT8) (mPrivate->MaxNic + 1);\r
-  mPrivate->MaxNic        = NicInfo->NicIndex;\r
+  NicInfo->HwAddressSize = (UINT32)HwAddressSize;\r
+  NicInfo->VlanId        = VlanId;\r
+  NicInfo->NicIndex      = (UINT8)(mPrivate->MaxNic + 1);\r
+  mPrivate->MaxNic       = NicInfo->NicIndex;\r
+\r
+  //\r
+  // Set IPv6 available flag.\r
+  //\r
+  Status = IScsiCheckIpv6Support (Controller, Image, &NicInfo->Ipv6Available);\r
+  if (EFI_ERROR (Status)) {\r
+    //\r
+    // Fail to get the data whether UNDI supports IPv6.\r
+    // Set default value to TRUE.\r
+    //\r
+    NicInfo->Ipv6Available = TRUE;\r
+  }\r
 \r
   //\r
   // Get the PCI location.\r
@@ -545,7 +705,6 @@ IScsiAddNic (
   return EFI_SUCCESS;\r
 }\r
 \r
-\r
 /**\r
   Delete the recorded NIC info from global structure. Also delete corresponding\r
   attempts.\r
@@ -561,15 +720,15 @@ IScsiRemoveNic (
   IN EFI_HANDLE  Controller\r
   )\r
 {\r
-  EFI_STATUS                  Status;\r
-  ISCSI_NIC_INFO              *NicInfo;\r
-  LIST_ENTRY                  *Entry;\r
-  LIST_ENTRY                  *NextEntry;\r
-  ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;\r
-  ISCSI_NIC_INFO              *ThisNic;\r
-  EFI_MAC_ADDRESS             MacAddr;\r
-  UINTN                       HwAddressSize;\r
-  UINT16                      VlanId;\r
+  EFI_STATUS                   Status;\r
+  ISCSI_NIC_INFO               *NicInfo;\r
+  LIST_ENTRY                   *Entry;\r
+  LIST_ENTRY                   *NextEntry;\r
+  ISCSI_ATTEMPT_CONFIG_NVDATA  *AttemptConfigData;\r
+  ISCSI_NIC_INFO               *ThisNic;\r
+  EFI_MAC_ADDRESS              MacAddr;\r
+  UINTN                        HwAddressSize;\r
+  UINT16                       VlanId;\r
 \r
   //\r
   // Get MAC address of this network device.\r
@@ -591,10 +750,10 @@ IScsiRemoveNic (
 \r
   NET_LIST_FOR_EACH (Entry, &mPrivate->NicInfoList) {\r
     NicInfo = NET_LIST_USER_STRUCT (Entry, ISCSI_NIC_INFO, Link);\r
-    if (NicInfo->HwAddressSize == HwAddressSize &&\r
-        CompareMem (&NicInfo->PermanentAddress, MacAddr.Addr, HwAddressSize) == 0 &&\r
-        NicInfo->VlanId == VlanId) {\r
-\r
+    if ((NicInfo->HwAddressSize == HwAddressSize) &&\r
+        (CompareMem (&NicInfo->PermanentAddress, MacAddr.Addr, HwAddressSize) == 0) &&\r
+        (NicInfo->VlanId == VlanId))\r
+    {\r
       ThisNic = NicInfo;\r
       break;\r
     }\r
@@ -619,16 +778,15 @@ IScsiRemoveNic (
       RemoveEntryList (&AttemptConfigData->Link);\r
       mPrivate->AttemptCount--;\r
 \r
-      if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED_FOR_MPIO && mPrivate->MpioCount > 0) {\r
+      if ((AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED_FOR_MPIO) && (mPrivate->MpioCount > 0)) {\r
         if (--mPrivate->MpioCount == 0) {\r
           mPrivate->EnableMpio = FALSE;\r
         }\r
 \r
-        if (AttemptConfigData->AuthenticationType == ISCSI_AUTH_TYPE_KRB && mPrivate->Krb5MpioCount > 0) {\r
+        if ((AttemptConfigData->AuthenticationType == ISCSI_AUTH_TYPE_KRB) && (mPrivate->Krb5MpioCount > 0)) {\r
           mPrivate->Krb5MpioCount--;\r
         }\r
-\r
-      } else if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED && mPrivate->SinglePathCount > 0) {\r
+      } else if ((AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED) && (mPrivate->SinglePathCount > 0)) {\r
         mPrivate->SinglePathCount--;\r
 \r
         if (mPrivate->ValidSinglePathCount > 0) {\r
@@ -640,17 +798,807 @@ IScsiRemoveNic (
     }\r
   }\r
 \r
-  //\r
-  // Free attempt is created but not saved to system.\r
-  //\r
-  if (mPrivate->NewAttempt != NULL) {\r
-    FreePool (mPrivate->NewAttempt);\r
-    mPrivate->NewAttempt = NULL;\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Create and initialize the Attempts.\r
+\r
+  @param[in]  AttemptNum          The number of Attempts will be created.\r
+\r
+  @retval EFI_SUCCESS             The Attempts have been created successfully.\r
+  @retval Others                  Failed to create the Attempt.\r
+\r
+**/\r
+EFI_STATUS\r
+IScsiCreateAttempts (\r
+  IN UINTN  AttemptNum\r
+  )\r
+{\r
+  ISCSI_ATTEMPT_CONFIG_NVDATA  *AttemptConfigData;\r
+  ISCSI_SESSION_CONFIG_NVDATA  *ConfigData;\r
+  UINT8                        *AttemptConfigOrder;\r
+  UINTN                        AttemptConfigOrderSize;\r
+  UINT8                        *AttemptOrderTmp;\r
+  UINTN                        TotalNumber;\r
+  UINT8                        Index;\r
+  EFI_STATUS                   Status;\r
+\r
+  for (Index = 1; Index <= AttemptNum; Index++) {\r
+    //\r
+    // Get the initialized attempt order. This is used to essure creating attempts by order.\r
+    //\r
+    AttemptConfigOrder = IScsiGetVariableAndSize (\r
+                           L"InitialAttemptOrder",\r
+                           &gIScsiConfigGuid,\r
+                           &AttemptConfigOrderSize\r
+                           );\r
+    TotalNumber = AttemptConfigOrderSize / sizeof (UINT8);\r
+    if (TotalNumber == AttemptNum) {\r
+      Status = EFI_SUCCESS;\r
+      break;\r
+    }\r
+\r
+    TotalNumber++;\r
+\r
+    //\r
+    // Append the new created attempt to the end.\r
+    //\r
+    AttemptOrderTmp = AllocateZeroPool (TotalNumber * sizeof (UINT8));\r
+    if (AttemptOrderTmp == NULL) {\r
+      if (AttemptConfigOrder != NULL) {\r
+        FreePool (AttemptConfigOrder);\r
+      }\r
+\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    if (AttemptConfigOrder != NULL) {\r
+      CopyMem (AttemptOrderTmp, AttemptConfigOrder, AttemptConfigOrderSize);\r
+      FreePool (AttemptConfigOrder);\r
+    }\r
+\r
+    AttemptOrderTmp[TotalNumber - 1] = Index;\r
+    AttemptConfigOrder               = AttemptOrderTmp;\r
+    AttemptConfigOrderSize           = TotalNumber * sizeof (UINT8);\r
+\r
+    Status = gRT->SetVariable (\r
+                    L"InitialAttemptOrder",\r
+                    &gIScsiConfigGuid,\r
+                    EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+                    AttemptConfigOrderSize,\r
+                    AttemptConfigOrder\r
+                    );\r
+    FreePool (AttemptConfigOrder);\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((\r
+        DEBUG_ERROR,\r
+        "%a: Failed to set 'InitialAttemptOrder' with Guid (%g): "\r
+        "%r\n",\r
+        __FUNCTION__,\r
+        &gIScsiConfigGuid,\r
+        Status\r
+        ));\r
+      return Status;\r
+    }\r
+\r
+    //\r
+    // Create new Attempt\r
+    //\r
+    AttemptConfigData = AllocateZeroPool (sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA));\r
+    if (AttemptConfigData == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    ConfigData                    = &AttemptConfigData->SessionConfigData;\r
+    ConfigData->TargetPort        = ISCSI_WELL_KNOWN_PORT;\r
+    ConfigData->ConnectTimeout    = CONNECT_DEFAULT_TIMEOUT;\r
+    ConfigData->ConnectRetryCount = CONNECT_MIN_RETRY;\r
+\r
+    AttemptConfigData->AuthenticationType           = ISCSI_AUTH_TYPE_CHAP;\r
+    AttemptConfigData->AuthConfigData.CHAP.CHAPType = ISCSI_CHAP_UNI;\r
+    //\r
+    // Configure the Attempt index and set variable.\r
+    //\r
+    AttemptConfigData->AttemptConfigIndex = Index;\r
+\r
+    //\r
+    // Set the attempt name according to the order.\r
+    //\r
+    UnicodeSPrint (\r
+      mPrivate->PortString,\r
+      (UINTN)ISCSI_NAME_IFR_MAX_SIZE,\r
+      L"Attempt %d",\r
+      (UINTN)AttemptConfigData->AttemptConfigIndex\r
+      );\r
+    UnicodeStrToAsciiStrS (mPrivate->PortString, AttemptConfigData->AttemptName, ATTEMPT_NAME_SIZE);\r
+\r
+    Status = gRT->SetVariable (\r
+                    mPrivate->PortString,\r
+                    &gEfiIScsiInitiatorNameProtocolGuid,\r
+                    ISCSI_CONFIG_VAR_ATTR,\r
+                    sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA),\r
+                    AttemptConfigData\r
+                    );\r
+    FreePool (AttemptConfigData);\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((\r
+        DEBUG_ERROR,\r
+        "%a: Failed to set variable (mPrivate->PortString) with Guid (%g): "\r
+        "%r\n",\r
+        __FUNCTION__,\r
+        &gEfiIScsiInitiatorNameProtocolGuid,\r
+        Status\r
+        ));\r
+      return Status;\r
+    }\r
   }\r
 \r
   return EFI_SUCCESS;\r
 }\r
 \r
+/**\r
+  Create the iSCSI configuration Keywords for each attempt. You can find the keywords\r
+  defined in the "x-UEFI-ns" namespace (http://www.uefi.org/confignamespace).\r
+\r
+  @param[in]  KeywordNum          The number Sets of Keywords will be created.\r
+\r
+  @retval EFI_SUCCESS             The operation is completed.\r
+  @retval Others                  Failed to create the Keywords.\r
+\r
+**/\r
+EFI_STATUS\r
+IScsiCreateKeywords (\r
+  IN UINTN  KeywordNum\r
+  )\r
+{\r
+  VOID                *StartOpCodeHandle;\r
+  EFI_IFR_GUID_LABEL  *StartLabel;\r
+  VOID                *EndOpCodeHandle;\r
+  EFI_IFR_GUID_LABEL  *EndLabel;\r
+  UINTN               Index;\r
+  EFI_STRING_ID       StringToken;\r
+  CHAR16              StringId[64];\r
+  CHAR16              KeywordId[32];\r
+  EFI_STATUS          Status;\r
+\r
+  Status = IScsiCreateOpCode (\r
+             KEYWORD_ENTRY_LABEL,\r
+             &StartOpCodeHandle,\r
+             &StartLabel,\r
+             &EndOpCodeHandle,\r
+             &EndLabel\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  for (Index = 1; Index <= KeywordNum; Index++) {\r
+    //\r
+    // Create iSCSIAttemptName Keyword.\r
+    //\r
+    UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_ATTEMPTT_NAME_PROMPT%d", Index);\r
+    StringToken =  HiiSetString (\r
+                     mCallbackInfo->RegisteredHandle,\r
+                     0,\r
+                     StringId,\r
+                     NULL\r
+                     );\r
+    UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIAttemptName:%d", Index);\r
+    HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");\r
+    HiiCreateStringOpCode (\r
+      StartOpCodeHandle,\r
+      (EFI_QUESTION_ID)(ATTEMPT_ATTEMPT_NAME_QUESTION_ID + (Index - 1)),\r
+      CONFIGURATION_VARSTORE_ID,\r
+      (UINT16)(ATTEMPT_ATTEMPT_NAME_VAR_OFFSET + ATTEMPT_NAME_SIZE * (Index - 1) * sizeof (CHAR16)),\r
+      StringToken,\r
+      StringToken,\r
+      EFI_IFR_FLAG_READ_ONLY,\r
+      0,\r
+      0,\r
+      ATTEMPT_NAME_SIZE,\r
+      NULL\r
+      );\r
+\r
+    //\r
+    // Create iSCSIBootEnable Keyword.\r
+    //\r
+    UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_MODE_PROMPT%d", Index);\r
+    StringToken =  HiiSetString (\r
+                     mCallbackInfo->RegisteredHandle,\r
+                     0,\r
+                     StringId,\r
+                     NULL\r
+                     );\r
+    UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIBootEnable:%d", Index);\r
+    HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");\r
+    HiiCreateNumericOpCode (\r
+      StartOpCodeHandle,\r
+      (EFI_QUESTION_ID)(ATTEMPT_BOOTENABLE_QUESTION_ID + (Index - 1)),\r
+      CONFIGURATION_VARSTORE_ID,\r
+      (UINT16)(ATTEMPT_BOOTENABLE_VAR_OFFSET + (Index - 1)),\r
+      StringToken,\r
+      StringToken,\r
+      0,\r
+      EFI_IFR_NUMERIC_SIZE_1,\r
+      0,\r
+      2,\r
+      0,\r
+      NULL\r
+      );\r
+\r
+    //\r
+    // Create iSCSIIpAddressType Keyword.\r
+    //\r
+    UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_IP_MODE_PROMPT%d", Index);\r
+    StringToken =  HiiSetString (\r
+                     mCallbackInfo->RegisteredHandle,\r
+                     0,\r
+                     StringId,\r
+                     NULL\r
+                     );\r
+    UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIIpAddressType:%d", Index);\r
+    HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");\r
+    HiiCreateNumericOpCode (\r
+      StartOpCodeHandle,\r
+      (EFI_QUESTION_ID)(ATTEMPT_ADDRESS_TYPE_QUESTION_ID + (Index - 1)),\r
+      CONFIGURATION_VARSTORE_ID,\r
+      (UINT16)(ATTEMPT_ADDRESS_TYPE_VAR_OFFSET + (Index - 1)),\r
+      StringToken,\r
+      StringToken,\r
+      0,\r
+      EFI_IFR_NUMERIC_SIZE_1,\r
+      0,\r
+      2,\r
+      0,\r
+      NULL\r
+      );\r
+\r
+    //\r
+    // Create iSCSIConnectRetry Keyword.\r
+    //\r
+    UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_CONNECT_RETRY_PROMPT%d", Index);\r
+    StringToken =  HiiSetString (\r
+                     mCallbackInfo->RegisteredHandle,\r
+                     0,\r
+                     StringId,\r
+                     NULL\r
+                     );\r
+    UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIConnectRetry:%d", Index);\r
+    HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");\r
+    HiiCreateNumericOpCode (\r
+      StartOpCodeHandle,\r
+      (EFI_QUESTION_ID)(ATTEMPT_CONNECT_RETRY_QUESTION_ID + (Index - 1)),\r
+      CONFIGURATION_VARSTORE_ID,\r
+      (UINT16)(ATTEMPT_CONNECT_RETRY_VAR_OFFSET + (Index - 1)),\r
+      StringToken,\r
+      StringToken,\r
+      0,\r
+      EFI_IFR_NUMERIC_SIZE_1,\r
+      0,\r
+      16,\r
+      0,\r
+      NULL\r
+      );\r
+\r
+    //\r
+    // Create iSCSIConnectTimeout Keyword.\r
+    //\r
+    UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_CONNECT_TIMEOUT_PROMPT%d", Index);\r
+    StringToken =  HiiSetString (\r
+                     mCallbackInfo->RegisteredHandle,\r
+                     0,\r
+                     StringId,\r
+                     NULL\r
+                     );\r
+    UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIConnectTimeout:%d", Index);\r
+    HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");\r
+    HiiCreateNumericOpCode (\r
+      StartOpCodeHandle,\r
+      (EFI_QUESTION_ID)(ATTEMPT_CONNECT_TIMEOUT_QUESTION_ID + (Index - 1)),\r
+      CONFIGURATION_VARSTORE_ID,\r
+      (UINT16)(ATTEMPT_CONNECT_TIMEOUT_VAR_OFFSET + 2 * (Index - 1)),\r
+      StringToken,\r
+      StringToken,\r
+      0,\r
+      EFI_IFR_NUMERIC_SIZE_2,\r
+      CONNECT_MIN_TIMEOUT,\r
+      CONNECT_MAX_TIMEOUT,\r
+      0,\r
+      NULL\r
+      );\r
+\r
+    //\r
+    // Create ISID Keyword.\r
+    //\r
+    UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_ISID_PROMPT%d", Index);\r
+    StringToken =  HiiSetString (\r
+                     mCallbackInfo->RegisteredHandle,\r
+                     0,\r
+                     StringId,\r
+                     NULL\r
+                     );\r
+    UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIISID:%d", Index);\r
+    HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");\r
+    HiiCreateStringOpCode (\r
+      StartOpCodeHandle,\r
+      (EFI_QUESTION_ID)(ATTEMPT_ISID_QUESTION_ID + (Index - 1)),\r
+      CONFIGURATION_VARSTORE_ID,\r
+      (UINT16)(ATTEMPT_ISID_VAR_OFFSET + sizeof (KEYWORD_STR) * (Index - 1)),\r
+      StringToken,\r
+      STRING_TOKEN (STR_ISCSI_ISID_HELP),\r
+      0,\r
+      0,\r
+      ISID_CONFIGURABLE_MIN_LEN,\r
+      ISID_CONFIGURABLE_STORAGE,\r
+      NULL\r
+      );\r
+\r
+    //\r
+    // Create iSCSIInitiatorInfoViaDHCP Keyword.\r
+    //\r
+    UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_INITIATOR_VIA_DHCP_PROMPT%d", Index);\r
+    StringToken =  HiiSetString (\r
+                     mCallbackInfo->RegisteredHandle,\r
+                     0,\r
+                     StringId,\r
+                     NULL\r
+                     );\r
+    UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIInitiatorInfoViaDHCP:%d", Index);\r
+    HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");\r
+    HiiCreateNumericOpCode (\r
+      StartOpCodeHandle,\r
+      (EFI_QUESTION_ID)(ATTEMPT_INITIATOR_VIA_DHCP_QUESTION_ID + (Index - 1)),\r
+      CONFIGURATION_VARSTORE_ID,\r
+      (UINT16)(ATTEMPT_INITIATOR_VIA_DHCP_VAR_OFFSET + (Index - 1)),\r
+      StringToken,\r
+      StringToken,\r
+      0,\r
+      0,\r
+      0,\r
+      1,\r
+      0,\r
+      NULL\r
+      );\r
+\r
+    //\r
+    // Create iSCSIInitiatorIpAddress Keyword.\r
+    //\r
+    UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_INITIATOR_IP_ADDRESS_PROMPT%d", Index);\r
+    StringToken =  HiiSetString (\r
+                     mCallbackInfo->RegisteredHandle,\r
+                     0,\r
+                     StringId,\r
+                     NULL\r
+                     );\r
+    UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIInitiatorIpAddress:%d", Index);\r
+    HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");\r
+    HiiCreateStringOpCode (\r
+      StartOpCodeHandle,\r
+      (EFI_QUESTION_ID)(ATTEMPT_INITIATOR_IP_ADDRESS_QUESTION_ID + (Index - 1)),\r
+      CONFIGURATION_VARSTORE_ID,\r
+      (UINT16)(ATTEMPT_INITIATOR_IP_ADDRESS_VAR_OFFSET + sizeof (KEYWORD_STR) * (Index - 1)),\r
+      StringToken,\r
+      StringToken,\r
+      0,\r
+      0,\r
+      IP4_MIN_SIZE,\r
+      IP4_STR_MAX_SIZE,\r
+      NULL\r
+      );\r
+\r
+    //\r
+    // Create iSCSIInitiatorNetmask Keyword.\r
+    //\r
+    UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_INITIATOR_NET_MASK_PROMPT%d", Index);\r
+    StringToken =  HiiSetString (\r
+                     mCallbackInfo->RegisteredHandle,\r
+                     0,\r
+                     StringId,\r
+                     NULL\r
+                     );\r
+    UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIInitiatorNetmask:%d", Index);\r
+    HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");\r
+    HiiCreateStringOpCode (\r
+      StartOpCodeHandle,\r
+      (EFI_QUESTION_ID)(ATTEMPT_INITIATOR_NET_MASK_QUESTION_ID + (Index - 1)),\r
+      CONFIGURATION_VARSTORE_ID,\r
+      (UINT16)(ATTEMPT_INITIATOR_NET_MASK_VAR_OFFSET + sizeof (KEYWORD_STR) * (Index - 1)),\r
+      StringToken,\r
+      StringToken,\r
+      0,\r
+      0,\r
+      IP4_MIN_SIZE,\r
+      IP4_STR_MAX_SIZE,\r
+      NULL\r
+      );\r
+\r
+    //\r
+    // Create iSCSIInitiatorGateway Keyword.\r
+    //\r
+    UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_INITIATOR_GATE_PROMPT%d", Index);\r
+    StringToken =  HiiSetString (\r
+                     mCallbackInfo->RegisteredHandle,\r
+                     0,\r
+                     StringId,\r
+                     NULL\r
+                     );\r
+    UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIInitiatorGateway:%d", Index);\r
+    HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");\r
+    HiiCreateStringOpCode (\r
+      StartOpCodeHandle,\r
+      (EFI_QUESTION_ID)(ATTEMPT_INITIATOR_GATE_WAY_QUESTION_ID + (Index - 1)),\r
+      CONFIGURATION_VARSTORE_ID,\r
+      (UINT16)(ATTEMPT_INITIATOR_GATE_WAY_VAR_OFFSET + sizeof (KEYWORD_STR) * (Index - 1)),\r
+      StringToken,\r
+      StringToken,\r
+      0,\r
+      0,\r
+      IP4_MIN_SIZE,\r
+      IP4_STR_MAX_SIZE,\r
+      NULL\r
+      );\r
+\r
+    //\r
+    // Create iSCSITargetInfoViaDHCP Keyword.\r
+    //\r
+    UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_TARGET_VIA_DHCP_PROMPT%d", Index);\r
+    StringToken =  HiiSetString (\r
+                     mCallbackInfo->RegisteredHandle,\r
+                     0,\r
+                     StringId,\r
+                     NULL\r
+                     );\r
+    UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSITargetInfoViaDHCP:%d", Index);\r
+    HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");\r
+    HiiCreateNumericOpCode (\r
+      StartOpCodeHandle,\r
+      (EFI_QUESTION_ID)(ATTEMPT_TARGET_VIA_DHCP_QUESTION_ID + (Index - 1)),\r
+      CONFIGURATION_VARSTORE_ID,\r
+      (UINT16)(ATTEMPT_TARGET_VIA_DHCP_VAR_OFFSET + (Index - 1)),\r
+      StringToken,\r
+      StringToken,\r
+      0,\r
+      0,\r
+      0,\r
+      1,\r
+      0,\r
+      NULL\r
+      );\r
+\r
+    //\r
+    // Create iSCSITargetTcpPort Keyword.\r
+    //\r
+    UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_TARGET_TCP_PORT_PROMPT%d", Index);\r
+    StringToken =  HiiSetString (\r
+                     mCallbackInfo->RegisteredHandle,\r
+                     0,\r
+                     StringId,\r
+                     NULL\r
+                     );\r
+    UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSITargetTcpPort:%d", Index);\r
+    HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");\r
+    HiiCreateNumericOpCode (\r
+      StartOpCodeHandle,\r
+      (EFI_QUESTION_ID)(ATTEMPT_TARGET_TCP_PORT_QUESTION_ID + (Index - 1)),\r
+      CONFIGURATION_VARSTORE_ID,\r
+      (UINT16)(ATTEMPT_TARGET_TCP_PORT_VAR_OFFSET + 2 * (Index - 1)),\r
+      StringToken,\r
+      StringToken,\r
+      0,\r
+      EFI_IFR_NUMERIC_SIZE_2,\r
+      TARGET_PORT_MIN_NUM,\r
+      TARGET_PORT_MAX_NUM,\r
+      0,\r
+      NULL\r
+      );\r
+\r
+    //\r
+    // Create iSCSITargetName Keyword.\r
+    //\r
+    UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_TARGET_NAME_PROMPT%d", Index);\r
+    StringToken =  HiiSetString (\r
+                     mCallbackInfo->RegisteredHandle,\r
+                     0,\r
+                     StringId,\r
+                     NULL\r
+                     );\r
+    UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSITargetName:%d", Index);\r
+    HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");\r
+    HiiCreateStringOpCode (\r
+      StartOpCodeHandle,\r
+      (EFI_QUESTION_ID)(ATTEMPT_TARGET_NAME_QUESTION_ID + (Index - 1)),\r
+      CONFIGURATION_VARSTORE_ID,\r
+      (UINT16)(ATTEMPT_TARGET_NAME_VAR_OFFSET + sizeof (KEYWORD_STR) * (Index - 1)),\r
+      StringToken,\r
+      StringToken,\r
+      0,\r
+      0,\r
+      ISCSI_NAME_IFR_MIN_SIZE,\r
+      ISCSI_NAME_IFR_MAX_SIZE,\r
+      NULL\r
+      );\r
+\r
+    //\r
+    // Create iSCSITargetIpAddress Keyword.\r
+    //\r
+    UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_TARGET_IP_ADDRESS_PROMPT%d", Index);\r
+    StringToken =  HiiSetString (\r
+                     mCallbackInfo->RegisteredHandle,\r
+                     0,\r
+                     StringId,\r
+                     NULL\r
+                     );\r
+    UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSITargetIpAddress:%d", Index);\r
+    HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");\r
+    HiiCreateStringOpCode (\r
+      StartOpCodeHandle,\r
+      (EFI_QUESTION_ID)(ATTEMPT_TARGET_IP_ADDRESS_QUESTION_ID + (Index - 1)),\r
+      CONFIGURATION_VARSTORE_ID,\r
+      (UINT16)(ATTEMPT_TARGET_IP_ADDRESS_VAR_OFFSET + sizeof (KEYWORD_STR) * (Index - 1)),\r
+      StringToken,\r
+      StringToken,\r
+      0,\r
+      0,\r
+      IP_MIN_SIZE,\r
+      IP_STR_MAX_SIZE,\r
+      NULL\r
+      );\r
+\r
+    //\r
+    // Create iSCSILUN Keyword.\r
+    //\r
+    UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_LUN_PROMPT%d", Index);\r
+    StringToken =  HiiSetString (\r
+                     mCallbackInfo->RegisteredHandle,\r
+                     0,\r
+                     StringId,\r
+                     NULL\r
+                     );\r
+    UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSILUN:%d", Index);\r
+    HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");\r
+    HiiCreateStringOpCode (\r
+      StartOpCodeHandle,\r
+      (EFI_QUESTION_ID)(ATTEMPT_LUN_QUESTION_ID + (Index - 1)),\r
+      CONFIGURATION_VARSTORE_ID,\r
+      (UINT16)(ATTEMPT_LUN_VAR_OFFSET + sizeof (KEYWORD_STR) * (Index - 1)),\r
+      StringToken,\r
+      StringToken,\r
+      0,\r
+      0,\r
+      LUN_MIN_SIZE,\r
+      LUN_MAX_SIZE,\r
+      NULL\r
+      );\r
+\r
+    //\r
+    // Create iSCSIAuthenticationMethod Keyword.\r
+    //\r
+    UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_AUTHENTICATION_METHOD_PROMPT%d", Index);\r
+    StringToken =  HiiSetString (\r
+                     mCallbackInfo->RegisteredHandle,\r
+                     0,\r
+                     StringId,\r
+                     NULL\r
+                     );\r
+    UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIAuthenticationMethod:%d", Index);\r
+    HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");\r
+    HiiCreateNumericOpCode (\r
+      StartOpCodeHandle,\r
+      (EFI_QUESTION_ID)(ATTEMPT_AUTHENTICATION_METHOD_QUESTION_ID + (Index - 1)),\r
+      CONFIGURATION_VARSTORE_ID,\r
+      (UINT16)(ATTEMPT_AUTHENTICATION_METHOD_VAR_OFFSET + (Index - 1)),\r
+      StringToken,\r
+      StringToken,\r
+      0,\r
+      0,\r
+      0,\r
+      1,\r
+      0,\r
+      NULL\r
+      );\r
+\r
+    //\r
+    // Create iSCSIChapType Keyword.\r
+    //\r
+    UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_CHARTYPE_PROMPT%d", Index);\r
+    StringToken =  HiiSetString (\r
+                     mCallbackInfo->RegisteredHandle,\r
+                     0,\r
+                     StringId,\r
+                     NULL\r
+                     );\r
+    UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIChapType:%d", Index);\r
+    HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");\r
+    HiiCreateNumericOpCode (\r
+      StartOpCodeHandle,\r
+      (EFI_QUESTION_ID)(ATTEMPT_CHARTYPE_QUESTION_ID + (Index - 1)),\r
+      CONFIGURATION_VARSTORE_ID,\r
+      (UINT16)(ATTEMPT_CHARTYPE_VAR_OFFSET + (Index - 1)),\r
+      StringToken,\r
+      StringToken,\r
+      0,\r
+      0,\r
+      0,\r
+      1,\r
+      0,\r
+      NULL\r
+      );\r
+\r
+    //\r
+    // Create iSCSIChapUsername Keyword.\r
+    //\r
+    UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_CHAR_USER_NAME_PROMPT%d", Index);\r
+    StringToken =  HiiSetString (\r
+                     mCallbackInfo->RegisteredHandle,\r
+                     0,\r
+                     StringId,\r
+                     NULL\r
+                     );\r
+    UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIChapUsername:%d", Index);\r
+    HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");\r
+    HiiCreateStringOpCode (\r
+      StartOpCodeHandle,\r
+      (EFI_QUESTION_ID)(ATTEMPT_CHAR_USER_NAME_QUESTION_ID + (Index - 1)),\r
+      CONFIGURATION_VARSTORE_ID,\r
+      (UINT16)(ATTEMPT_CHAR_USER_NAME_VAR_OFFSET + sizeof (KEYWORD_STR) * (Index - 1)),\r
+      StringToken,\r
+      StringToken,\r
+      0,\r
+      0,\r
+      0,\r
+      ISCSI_CHAP_NAME_MAX_LEN,\r
+      NULL\r
+      );\r
+\r
+    //\r
+    // Create iSCSIChapSecret Keyword.\r
+    //\r
+    UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_CHAR_SECRET_PROMPT%d", Index);\r
+    StringToken =  HiiSetString (\r
+                     mCallbackInfo->RegisteredHandle,\r
+                     0,\r
+                     StringId,\r
+                     NULL\r
+                     );\r
+    UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIChapSecret:%d", Index);\r
+    HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");\r
+    HiiCreateStringOpCode (\r
+      StartOpCodeHandle,\r
+      (EFI_QUESTION_ID)(ATTEMPT_CHAR_SECRET_QUESTION_ID + (Index - 1)),\r
+      CONFIGURATION_VARSTORE_ID,\r
+      (UINT16)(ATTEMPT_CHAR_SECRET_VAR_OFFSET + sizeof (KEYWORD_STR) * (Index - 1)),\r
+      StringToken,\r
+      StringToken,\r
+      0,\r
+      0,\r
+      ISCSI_CHAP_SECRET_MIN_LEN,\r
+      ISCSI_CHAP_SECRET_MAX_LEN,\r
+      NULL\r
+      );\r
+\r
+    //\r
+    // Create iSCSIReverseChapUsername Keyword.\r
+    //\r
+    UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_CHAR_REVERSE_USER_NAME_PROMPT%d", Index);\r
+    StringToken =  HiiSetString (\r
+                     mCallbackInfo->RegisteredHandle,\r
+                     0,\r
+                     StringId,\r
+                     NULL\r
+                     );\r
+    UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIReverseChapUsername:%d", Index);\r
+    HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");\r
+    HiiCreateStringOpCode (\r
+      StartOpCodeHandle,\r
+      (EFI_QUESTION_ID)(ATTEMPT_CHAR_REVERSE_USER_NAME_QUESTION_ID + (Index - 1)),\r
+      CONFIGURATION_VARSTORE_ID,\r
+      (UINT16)(ATTEMPT_CHAR_REVERSE_USER_NAME_VAR_OFFSET + sizeof (KEYWORD_STR) * (Index - 1)),\r
+      StringToken,\r
+      StringToken,\r
+      0,\r
+      0,\r
+      0,\r
+      ISCSI_CHAP_NAME_MAX_LEN,\r
+      NULL\r
+      );\r
+\r
+    //\r
+    // Create iSCSIReverseChapSecret Keyword.\r
+    //\r
+    UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_CHAR_REVERSE_SECRET_PROMPT%d", Index);\r
+    StringToken =  HiiSetString (\r
+                     mCallbackInfo->RegisteredHandle,\r
+                     0,\r
+                     StringId,\r
+                     NULL\r
+                     );\r
+    UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIReverseChapSecret:%d", Index);\r
+    HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");\r
+    HiiCreateStringOpCode (\r
+      StartOpCodeHandle,\r
+      (EFI_QUESTION_ID)(ATTEMPT_CHAR_REVERSE_SECRET_QUESTION_ID + (Index - 1)),\r
+      CONFIGURATION_VARSTORE_ID,\r
+      (UINT16)(ATTEMPT_CHAR_REVERSE_SECRET_VAR_OFFSET + sizeof (KEYWORD_STR) * (Index - 1)),\r
+      StringToken,\r
+      StringToken,\r
+      0,\r
+      0,\r
+      ISCSI_CHAP_SECRET_MIN_LEN,\r
+      ISCSI_CHAP_SECRET_MAX_LEN,\r
+      NULL\r
+      );\r
+  }\r
+\r
+  Status = HiiUpdateForm (\r
+             mCallbackInfo->RegisteredHandle, // HII handle\r
+             &gIScsiConfigGuid,               // Formset GUID\r
+             FORMID_ATTEMPT_FORM,             // Form ID\r
+             StartOpCodeHandle,               // Label for where to insert opcodes\r
+             EndOpCodeHandle                  // Replace data\r
+             );\r
+\r
+  HiiFreeOpCodeHandle (StartOpCodeHandle);\r
+  HiiFreeOpCodeHandle (EndOpCodeHandle);\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+\r
+  Free the attempt configure data variable.\r
+\r
+**/\r
+VOID\r
+IScsiCleanAttemptVariable (\r
+  IN   VOID\r
+  )\r
+{\r
+  ISCSI_ATTEMPT_CONFIG_NVDATA  *AttemptConfigData;\r
+  UINT8                        *AttemptConfigOrder;\r
+  UINTN                        AttemptConfigOrderSize;\r
+  UINTN                        Index;\r
+\r
+  //\r
+  // Get the initialized attempt order.\r
+  //\r
+  AttemptConfigOrder = IScsiGetVariableAndSize (\r
+                         L"InitialAttemptOrder",\r
+                         &gIScsiConfigGuid,\r
+                         &AttemptConfigOrderSize\r
+                         );\r
+  if ((AttemptConfigOrder == NULL) || (AttemptConfigOrderSize == 0)) {\r
+    return;\r
+  }\r
+\r
+  for (Index = 1; Index < AttemptConfigOrderSize / sizeof (UINT8); Index++) {\r
+    UnicodeSPrint (\r
+      mPrivate->PortString,\r
+      (UINTN)ISCSI_NAME_IFR_MAX_SIZE,\r
+      L"Attempt %d",\r
+      Index\r
+      );\r
+\r
+    GetVariable2 (\r
+      mPrivate->PortString,\r
+      &gEfiIScsiInitiatorNameProtocolGuid,\r
+      (VOID **)&AttemptConfigData,\r
+      NULL\r
+      );\r
+\r
+    if (AttemptConfigData != NULL) {\r
+      gRT->SetVariable (\r
+             mPrivate->PortString,\r
+             &gEfiIScsiInitiatorNameProtocolGuid,\r
+             0,\r
+             0,\r
+             NULL\r
+             );\r
+    }\r
+  }\r
+\r
+  return;\r
+}\r
 \r
 /**\r
   Get the recorded NIC info from global structure by the Index.\r
@@ -662,11 +1610,11 @@ IScsiRemoveNic (
 **/\r
 ISCSI_NIC_INFO *\r
 IScsiGetNicInfoByIndex (\r
-  IN UINT8      NicIndex\r
+  IN UINT8  NicIndex\r
   )\r
 {\r
-  LIST_ENTRY        *Entry;\r
-  ISCSI_NIC_INFO    *NicInfo;\r
+  LIST_ENTRY      *Entry;\r
+  ISCSI_NIC_INFO  *NicInfo;\r
 \r
   NET_LIST_FOR_EACH (Entry, &mPrivate->NicInfoList) {\r
     NicInfo = NET_LIST_USER_STRUCT (Entry, ISCSI_NIC_INFO, Link);\r
@@ -678,9 +1626,8 @@ IScsiGetNicInfoByIndex (
   return NULL;\r
 }\r
 \r
-\r
 /**\r
-  Get the NIC's PCI location and return it accroding to the composited\r
+  Get the NIC's PCI location and return it according to the composited\r
   format defined in iSCSI Boot Firmware Table.\r
 \r
   @param[in]   Controller        The handle of the controller.\r
@@ -708,7 +1655,7 @@ IScsiGetNICPciLocation (
   Status = gBS->HandleProtocol (\r
                   Controller,\r
                   &gEfiDevicePathProtocolGuid,\r
-                  (VOID **) &DevicePath\r
+                  (VOID **)&DevicePath\r
                   );\r
   if (EFI_ERROR (Status)) {\r
     return 0;\r
@@ -723,7 +1670,7 @@ IScsiGetNICPciLocation (
     return 0;\r
   }\r
 \r
-  Status = gBS->HandleProtocol (PciIoHandle, &gEfiPciIoProtocolGuid, (VOID **) &PciIo);\r
+  Status = gBS->HandleProtocol (PciIoHandle, &gEfiPciIoProtocolGuid, (VOID **)&PciIo);\r
   if (EFI_ERROR (Status)) {\r
     return 0;\r
   }\r
@@ -733,10 +1680,9 @@ IScsiGetNICPciLocation (
     return 0;\r
   }\r
 \r
-  return (UINT16) ((*Bus << 8) | (*Device << 3) | *Function);\r
+  return (UINT16)((*Bus << 8) | (*Device << 3) | *Function);\r
 }\r
 \r
-\r
 /**\r
   Read the EFI variable (VendorGuid/Name) and return a dynamically allocated\r
   buffer, and the size of the buffer. If failure, return NULL.\r
@@ -752,9 +1698,9 @@ IScsiGetNICPciLocation (
 **/\r
 VOID *\r
 IScsiGetVariableAndSize (\r
-  IN  CHAR16              *Name,\r
-  IN  EFI_GUID            *VendorGuid,\r
-  OUT UINTN               *VariableSize\r
+  IN  CHAR16    *Name,\r
+  IN  EFI_GUID  *VendorGuid,\r
+  OUT UINTN     *VariableSize\r
   )\r
 {\r
   EFI_STATUS  Status;\r
@@ -766,8 +1712,8 @@ IScsiGetVariableAndSize (
   //\r
   // Pass in a zero size buffer to find the required buffer size.\r
   //\r
-  BufferSize  = 0;\r
-  Status      = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer);\r
+  BufferSize = 0;\r
+  Status     = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer);\r
   if (Status == EFI_BUFFER_TOO_SMALL) {\r
     //\r
     // Allocate the buffer to return\r
@@ -776,6 +1722,7 @@ IScsiGetVariableAndSize (
     if (Buffer == NULL) {\r
       return NULL;\r
     }\r
+\r
     //\r
     // Read variable into the allocated buffer.\r
     //\r
@@ -789,7 +1736,6 @@ IScsiGetVariableAndSize (
   return Buffer;\r
 }\r
 \r
-\r
 /**\r
   Create the iSCSI driver data.\r
 \r
@@ -806,8 +1752,8 @@ IScsiCreateDriverData (
   IN EFI_HANDLE  Controller\r
   )\r
 {\r
-  ISCSI_DRIVER_DATA *Private;\r
-  EFI_STATUS        Status;\r
+  ISCSI_DRIVER_DATA  *Private;\r
+  EFI_STATUS         Status;\r
 \r
   Private = AllocateZeroPool (sizeof (ISCSI_DRIVER_DATA));\r
   if (Private == NULL) {\r
@@ -837,7 +1783,7 @@ IScsiCreateDriverData (
   }\r
 \r
   Private->ExtScsiPassThruHandle = NULL;\r
-  CopyMem(&Private->IScsiExtScsiPassThru, &gIScsiExtScsiPassThruProtocolTemplate, sizeof(EFI_EXT_SCSI_PASS_THRU_PROTOCOL));\r
+  CopyMem (&Private->IScsiExtScsiPassThru, &gIScsiExtScsiPassThruProtocolTemplate, sizeof (EFI_EXT_SCSI_PASS_THRU_PROTOCOL));\r
 \r
   //\r
   // 0 is designated to the TargetId, so use another value for the AdapterId.\r
@@ -850,26 +1796,33 @@ IScsiCreateDriverData (
   return Private;\r
 }\r
 \r
-\r
 /**\r
   Clean the iSCSI driver data.\r
 \r
-  @param[in]  Private The iSCSI driver data.\r
+  @param[in]              Private The iSCSI driver data.\r
+\r
+  @retval EFI_SUCCESS     The clean operation is successful.\r
+  @retval Others          Other errors as indicated.\r
 \r
 **/\r
-VOID\r
+EFI_STATUS\r
 IScsiCleanDriverData (\r
   IN ISCSI_DRIVER_DATA  *Private\r
   )\r
 {\r
-  EFI_STATUS            Status;\r
+  EFI_STATUS  Status;\r
+\r
+  Status = EFI_SUCCESS;\r
 \r
   if (Private->DevicePath != NULL) {\r
-    gBS->UninstallProtocolInterface (\r
-           Private->ExtScsiPassThruHandle,\r
-           &gEfiDevicePathProtocolGuid,\r
-           Private->DevicePath\r
-           );\r
+    Status = gBS->UninstallProtocolInterface (\r
+                    Private->ExtScsiPassThruHandle,\r
+                    &gEfiDevicePathProtocolGuid,\r
+                    Private->DevicePath\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      goto EXIT;\r
+    }\r
 \r
     FreePool (Private->DevicePath);\r
   }\r
@@ -885,11 +1838,210 @@ IScsiCleanDriverData (
     }\r
   }\r
 \r
-  gBS->CloseEvent (Private->ExitBootServiceEvent);\r
+EXIT:\r
+  if (Private->ExitBootServiceEvent != NULL) {\r
+    gBS->CloseEvent (Private->ExitBootServiceEvent);\r
+  }\r
+\r
+  mCallbackInfo->Current = NULL;\r
 \r
   FreePool (Private);\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Check wheather the Controller handle is configured to use DHCP protocol.\r
+\r
+  @param[in]  Controller           The handle of the controller.\r
+  @param[in]  IpVersion            IP_VERSION_4 or IP_VERSION_6.\r
+\r
+  @retval TRUE                     The handle of the controller need the Dhcp protocol.\r
+  @retval FALSE                    The handle of the controller does not need the Dhcp protocol.\r
+\r
+**/\r
+BOOLEAN\r
+IScsiDhcpIsConfigured (\r
+  IN EFI_HANDLE  Controller,\r
+  IN UINT8       IpVersion\r
+  )\r
+{\r
+  ISCSI_ATTEMPT_CONFIG_NVDATA  *AttemptTmp;\r
+  UINT8                        *AttemptConfigOrder;\r
+  UINTN                        AttemptConfigOrderSize;\r
+  UINTN                        Index;\r
+  EFI_STATUS                   Status;\r
+  EFI_MAC_ADDRESS              MacAddr;\r
+  UINTN                        HwAddressSize;\r
+  UINT16                       VlanId;\r
+  CHAR16                       MacString[ISCSI_MAX_MAC_STRING_LEN];\r
+  CHAR16                       AttemptMacString[ISCSI_MAX_MAC_STRING_LEN];\r
+  CHAR16                       AttemptName[ISCSI_NAME_IFR_MAX_SIZE];\r
+\r
+  AttemptConfigOrder = IScsiGetVariableAndSize (\r
+                         L"AttemptOrder",\r
+                         &gIScsiConfigGuid,\r
+                         &AttemptConfigOrderSize\r
+                         );\r
+  if ((AttemptConfigOrder == NULL) || (AttemptConfigOrderSize == 0)) {\r
+    return FALSE;\r
+  }\r
+\r
+  //\r
+  // Get MAC address of this network device.\r
+  //\r
+  Status = NetLibGetMacAddress (Controller, &MacAddr, &HwAddressSize);\r
+  if (EFI_ERROR (Status)) {\r
+    return FALSE;\r
+  }\r
+\r
+  //\r
+  // Get VLAN ID of this network device.\r
+  //\r
+  VlanId = NetLibGetVlanId (Controller);\r
+  IScsiMacAddrToStr (&MacAddr, (UINT32)HwAddressSize, VlanId, MacString);\r
+\r
+  for (Index = 0; Index < AttemptConfigOrderSize / sizeof (UINT8); Index++) {\r
+    UnicodeSPrint (\r
+      AttemptName,\r
+      (UINTN)128,\r
+      L"Attempt %d",\r
+      (UINTN)AttemptConfigOrder[Index]\r
+      );\r
+    Status = GetVariable2 (\r
+               AttemptName,\r
+               &gEfiIScsiInitiatorNameProtocolGuid,\r
+               (VOID **)&AttemptTmp,\r
+               NULL\r
+               );\r
+    if ((AttemptTmp == NULL) || EFI_ERROR (Status)) {\r
+      continue;\r
+    }\r
+\r
+    ASSERT (AttemptConfigOrder[Index] == AttemptTmp->AttemptConfigIndex);\r
+\r
+    if (AttemptTmp->SessionConfigData.Enabled == ISCSI_DISABLED) {\r
+      FreePool (AttemptTmp);\r
+      continue;\r
+    }\r
+\r
+    if ((AttemptTmp->SessionConfigData.IpMode != IP_MODE_AUTOCONFIG) &&\r
+        (AttemptTmp->SessionConfigData.IpMode != ((IpVersion == IP_VERSION_4) ? IP_MODE_IP4 : IP_MODE_IP6)))\r
+    {\r
+      FreePool (AttemptTmp);\r
+      continue;\r
+    }\r
+\r
+    AsciiStrToUnicodeStrS (AttemptTmp->MacString, AttemptMacString, sizeof (AttemptMacString) / sizeof (AttemptMacString[0]));\r
+\r
+    if ((AttemptTmp->Actived == ISCSI_ACTIVE_DISABLED) || StrCmp (MacString, AttemptMacString)) {\r
+      continue;\r
+    }\r
+\r
+    if ((AttemptTmp->SessionConfigData.IpMode == IP_MODE_AUTOCONFIG) ||\r
+        (AttemptTmp->SessionConfigData.InitiatorInfoFromDhcp == TRUE) ||\r
+        (AttemptTmp->SessionConfigData.TargetInfoFromDhcp == TRUE))\r
+    {\r
+      FreePool (AttemptTmp);\r
+      FreePool (AttemptConfigOrder);\r
+      return TRUE;\r
+    }\r
+\r
+    FreePool (AttemptTmp);\r
+  }\r
+\r
+  FreePool (AttemptConfigOrder);\r
+  return FALSE;\r
 }\r
 \r
+/**\r
+  Check whether the Controller handle is configured to use DNS protocol.\r
+\r
+  @param[in]  Controller           The handle of the controller.\r
+\r
+  @retval TRUE                     The handle of the controller need the Dns protocol.\r
+  @retval FALSE                    The handle of the controller does not need the Dns protocol.\r
+\r
+**/\r
+BOOLEAN\r
+IScsiDnsIsConfigured (\r
+  IN EFI_HANDLE  Controller\r
+  )\r
+{\r
+  ISCSI_ATTEMPT_CONFIG_NVDATA  *AttemptTmp;\r
+  UINT8                        *AttemptConfigOrder;\r
+  UINTN                        AttemptConfigOrderSize;\r
+  UINTN                        Index;\r
+  EFI_STATUS                   Status;\r
+  EFI_MAC_ADDRESS              MacAddr;\r
+  UINTN                        HwAddressSize;\r
+  UINT16                       VlanId;\r
+  CHAR16                       AttemptMacString[ISCSI_MAX_MAC_STRING_LEN];\r
+  CHAR16                       MacString[ISCSI_MAX_MAC_STRING_LEN];\r
+  CHAR16                       AttemptName[ISCSI_NAME_IFR_MAX_SIZE];\r
+\r
+  AttemptConfigOrder = IScsiGetVariableAndSize (\r
+                         L"AttemptOrder",\r
+                         &gIScsiConfigGuid,\r
+                         &AttemptConfigOrderSize\r
+                         );\r
+  if ((AttemptConfigOrder == NULL) || (AttemptConfigOrderSize == 0)) {\r
+    return FALSE;\r
+  }\r
+\r
+  //\r
+  // Get MAC address of this network device.\r
+  //\r
+  Status = NetLibGetMacAddress (Controller, &MacAddr, &HwAddressSize);\r
+  if (EFI_ERROR (Status)) {\r
+    return FALSE;\r
+  }\r
+\r
+  //\r
+  // Get VLAN ID of this network device.\r
+  //\r
+  VlanId = NetLibGetVlanId (Controller);\r
+  IScsiMacAddrToStr (&MacAddr, (UINT32)HwAddressSize, VlanId, MacString);\r
+\r
+  for (Index = 0; Index < AttemptConfigOrderSize / sizeof (UINT8); Index++) {\r
+    UnicodeSPrint (\r
+      AttemptName,\r
+      (UINTN)128,\r
+      L"Attempt %d",\r
+      (UINTN)AttemptConfigOrder[Index]\r
+      );\r
+\r
+    Status = GetVariable2 (\r
+               AttemptName,\r
+               &gEfiIScsiInitiatorNameProtocolGuid,\r
+               (VOID **)&AttemptTmp,\r
+               NULL\r
+               );\r
+    if ((AttemptTmp == NULL) || EFI_ERROR (Status)) {\r
+      continue;\r
+    }\r
+\r
+    ASSERT (AttemptConfigOrder[Index] == AttemptTmp->AttemptConfigIndex);\r
+\r
+    AsciiStrToUnicodeStrS (AttemptTmp->MacString, AttemptMacString, sizeof (AttemptMacString) / sizeof (AttemptMacString[0]));\r
+\r
+    if ((AttemptTmp->SessionConfigData.Enabled == ISCSI_DISABLED) || StrCmp (MacString, AttemptMacString)) {\r
+      FreePool (AttemptTmp);\r
+      continue;\r
+    }\r
+\r
+    if (AttemptTmp->SessionConfigData.DnsMode || AttemptTmp->SessionConfigData.TargetInfoFromDhcp) {\r
+      FreePool (AttemptTmp);\r
+      FreePool (AttemptConfigOrder);\r
+      return TRUE;\r
+    } else {\r
+      FreePool (AttemptTmp);\r
+      continue;\r
+    }\r
+  }\r
+\r
+  FreePool (AttemptConfigOrder);\r
+  return FALSE;\r
+}\r
 \r
 /**\r
   Get the various configuration data.\r
@@ -898,6 +2050,7 @@ IScsiCleanDriverData (
 \r
   @retval EFI_SUCCESS            The configuration data is retrieved.\r
   @retval EFI_NOT_FOUND          This iSCSI driver is not configured yet.\r
+  @retval EFI_OUT_OF_RESOURCES   Failed to allocate memory.\r
 \r
 **/\r
 EFI_STATUS\r
@@ -905,16 +2058,17 @@ IScsiGetConfigData (
   IN ISCSI_DRIVER_DATA  *Private\r
   )\r
 {\r
-  EFI_STATUS                  Status;\r
-  CHAR16                      MacString[ISCSI_MAX_MAC_STRING_LEN];\r
-  UINTN                       Index;\r
-  ISCSI_NIC_INFO              *NicInfo;\r
-  ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;\r
-  ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptTmp;\r
-  UINT8                       *AttemptConfigOrder;\r
-  UINTN                       AttemptConfigOrderSize;\r
-  CHAR16                      IScsiMode[64];\r
-  CHAR16                      IpMode[64];\r
+  EFI_STATUS                   Status;\r
+  CHAR16                       MacString[ISCSI_MAX_MAC_STRING_LEN];\r
+  CHAR16                       AttemptMacString[ISCSI_MAX_MAC_STRING_LEN];\r
+  UINTN                        Index;\r
+  ISCSI_NIC_INFO               *NicInfo;\r
+  ISCSI_ATTEMPT_CONFIG_NVDATA  *AttemptConfigData;\r
+  ISCSI_ATTEMPT_CONFIG_NVDATA  *AttemptTmp;\r
+  UINT8                        *AttemptConfigOrder;\r
+  UINTN                        AttemptConfigOrderSize;\r
+  CHAR16                       IScsiMode[64];\r
+  CHAR16                       IpMode[64];\r
 \r
   //\r
   // There should be at least one attempt configured.\r
@@ -924,19 +2078,19 @@ IScsiGetConfigData (
                          &gIScsiConfigGuid,\r
                          &AttemptConfigOrderSize\r
                          );\r
-  if (AttemptConfigOrder == NULL || AttemptConfigOrderSize == 0) {\r
+  if ((AttemptConfigOrder == NULL) || (AttemptConfigOrderSize == 0)) {\r
     return EFI_NOT_FOUND;\r
   }\r
 \r
   //\r
   // Get the iSCSI Initiator Name.\r
   //\r
-  mPrivate->InitiatorNameLength  = ISCSI_NAME_MAX_SIZE;\r
-  Status = gIScsiInitiatorName.Get (\r
-                                 &gIScsiInitiatorName,\r
-                                 &mPrivate->InitiatorNameLength,\r
-                                 mPrivate->InitiatorName\r
-                                 );\r
+  mPrivate->InitiatorNameLength = ISCSI_NAME_MAX_SIZE;\r
+  Status                        = gIScsiInitiatorName.Get (\r
+                                                        &gIScsiInitiatorName,\r
+                                                        &mPrivate->InitiatorNameLength,\r
+                                                        mPrivate->InitiatorName\r
+                                                        );\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
@@ -945,27 +2099,29 @@ IScsiGetConfigData (
   // Get the normal configuration.\r
   //\r
   for (Index = 0; Index < AttemptConfigOrderSize / sizeof (UINT8); Index++) {\r
-\r
     //\r
     // Check whether the attempt exists in AttemptConfig.\r
     //\r
-    AttemptTmp = IScsiConfigGetAttemptByConfigIndex (AttemptConfigOrder[Index]);    \r
-    if (AttemptTmp != NULL && AttemptTmp->SessionConfigData.Enabled == ISCSI_DISABLED) {\r
+    AttemptTmp = IScsiConfigGetAttemptByConfigIndex (AttemptConfigOrder[Index]);\r
+    if ((AttemptTmp != NULL) && (AttemptTmp->SessionConfigData.Enabled == ISCSI_DISABLED)) {\r
       continue;\r
-    } else if (AttemptTmp != NULL && AttemptTmp->SessionConfigData.Enabled != ISCSI_DISABLED) {\r
+    } else if ((AttemptTmp != NULL) && (AttemptTmp->SessionConfigData.Enabled != ISCSI_DISABLED)) {\r
       //\r
       // Check the autoconfig path to see whether it should be retried.\r
       //\r
-      if (AttemptTmp->SessionConfigData.IpMode == IP_MODE_AUTOCONFIG &&\r
-          AttemptTmp->AutoConfigureMode != IP_MODE_AUTOCONFIG_SUCCESS) {\r
+      if ((AttemptTmp->SessionConfigData.IpMode == IP_MODE_AUTOCONFIG) &&\r
+          !AttemptTmp->AutoConfigureSuccess)\r
+      {\r
         if (mPrivate->Ipv6Flag &&\r
-            AttemptTmp->AutoConfigureMode == IP_MODE_AUTOCONFIG_IP6) {\r
+            (AttemptTmp->AutoConfigureMode == IP_MODE_AUTOCONFIG_IP6))\r
+        {\r
           //\r
           // Autoconfigure for IP6 already attempted but failed. Do not try again.\r
           //\r
           continue;\r
         } else if (!mPrivate->Ipv6Flag &&\r
-                   AttemptTmp->AutoConfigureMode == IP_MODE_AUTOCONFIG_IP4) {\r
+                   (AttemptTmp->AutoConfigureMode == IP_MODE_AUTOCONFIG_IP4))\r
+        {\r
           //\r
           // Autoconfigure for IP4  already attempted but failed. Do not try again.\r
           //\r
@@ -975,7 +2131,7 @@ IScsiGetConfigData (
           // Try another approach for this autoconfigure path.\r
           //\r
           AttemptTmp->AutoConfigureMode =\r
-            (UINT8) (mPrivate->Ipv6Flag ? IP_MODE_AUTOCONFIG_IP6 : IP_MODE_AUTOCONFIG_IP4);\r
+            (UINT8)(mPrivate->Ipv6Flag ? IP_MODE_AUTOCONFIG_IP6 : IP_MODE_AUTOCONFIG_IP4);\r
           AttemptTmp->SessionConfigData.InitiatorInfoFromDhcp = TRUE;\r
           AttemptTmp->SessionConfigData.TargetInfoFromDhcp    = TRUE;\r
           AttemptTmp->DhcpSuccess                             = FALSE;\r
@@ -998,13 +2154,11 @@ IScsiGetConfigData (
           //\r
           // Refresh the state of this attempt to NVR.\r
           //\r
-          AsciiStrToUnicodeStr (AttemptTmp->MacString, MacString);\r
           UnicodeSPrint (\r
             mPrivate->PortString,\r
-            (UINTN) ISCSI_NAME_IFR_MAX_SIZE,\r
-            L"%s%d",\r
-            MacString,\r
-            (UINTN) AttemptTmp->AttemptConfigIndex\r
+            (UINTN)ISCSI_NAME_IFR_MAX_SIZE,\r
+            L"Attempt %d",\r
+            (UINTN)AttemptTmp->AttemptConfigIndex\r
             );\r
 \r
           gRT->SetVariable (\r
@@ -1017,9 +2171,13 @@ IScsiGetConfigData (
 \r
           continue;\r
         }\r
-      } else if (AttemptTmp->SessionConfigData.InitiatorInfoFromDhcp && !AttemptTmp->ValidPath) {\r
+      } else if (AttemptTmp->SessionConfigData.InitiatorInfoFromDhcp &&\r
+                 !AttemptTmp->ValidPath &&\r
+                 (AttemptTmp->NicIndex == mPrivate->CurrentNic))\r
+      {\r
         //\r
-        // Get DHCP information for already added, but failed, attempt.\r
+        // If the attempt associates with the current NIC, we can\r
+        // get DHCP information for already added, but failed, attempt.\r
         //\r
         AttemptTmp->DhcpSuccess = FALSE;\r
         if (!mPrivate->Ipv6Flag && (AttemptTmp->SessionConfigData.IpMode == IP_MODE_IP4)) {\r
@@ -1037,13 +2195,11 @@ IScsiGetConfigData (
         //\r
         // Refresh the state of this attempt to NVR.\r
         //\r
-        AsciiStrToUnicodeStr (AttemptTmp->MacString, MacString);\r
         UnicodeSPrint (\r
           mPrivate->PortString,\r
-          (UINTN) ISCSI_NAME_IFR_MAX_SIZE,\r
-          L"%s%d",\r
-          MacString,\r
-          (UINTN) AttemptTmp->AttemptConfigIndex\r
+          (UINTN)ISCSI_NAME_IFR_MAX_SIZE,\r
+          L"Attempt %d",\r
+          (UINTN)AttemptTmp->AttemptConfigIndex\r
           );\r
 \r
         gRT->SetVariable (\r
@@ -1055,7 +2211,6 @@ IScsiGetConfigData (
                );\r
 \r
         continue;\r
-\r
       } else {\r
         continue;\r
       }\r
@@ -1070,18 +2225,22 @@ IScsiGetConfigData (
     IScsiMacAddrToStr (&NicInfo->PermanentAddress, NicInfo->HwAddressSize, NicInfo->VlanId, MacString);\r
     UnicodeSPrint (\r
       mPrivate->PortString,\r
-      (UINTN) 128,\r
-      L"%s%d",\r
-      MacString,\r
-      (UINTN) AttemptConfigOrder[Index]\r
+      (UINTN)ISCSI_NAME_IFR_MAX_SIZE,\r
+      L"Attempt %d",\r
+      (UINTN)AttemptConfigOrder[Index]\r
       );\r
 \r
-    AttemptConfigData = (ISCSI_ATTEMPT_CONFIG_NVDATA *) GetVariable (\r
-                                                          mPrivate->PortString,\r
-                                                          &gEfiIScsiInitiatorNameProtocolGuid\r
-                                                          );\r
+    GetVariable2 (\r
+      mPrivate->PortString,\r
+      &gEfiIScsiInitiatorNameProtocolGuid,\r
+      (VOID **)&AttemptConfigData,\r
+      NULL\r
+      );\r
+    AsciiStrToUnicodeStrS (AttemptConfigData->MacString, AttemptMacString, sizeof (AttemptMacString) / sizeof (AttemptMacString[0]));\r
 \r
-    if (AttemptConfigData == NULL) {\r
+    if ((AttemptConfigData == NULL) || (AttemptConfigData->Actived == ISCSI_ACTIVE_DISABLED) ||\r
+        StrCmp (MacString, AttemptMacString))\r
+    {\r
       continue;\r
     }\r
 \r
@@ -1089,7 +2248,7 @@ IScsiGetConfigData (
 \r
     AttemptConfigData->NicIndex      = NicInfo->NicIndex;\r
     AttemptConfigData->DhcpSuccess   = FALSE;\r
-    AttemptConfigData->ValidiBFTPath = (BOOLEAN) (mPrivate->EnableMpio ? TRUE : FALSE);\r
+    AttemptConfigData->ValidiBFTPath = (BOOLEAN)(mPrivate->EnableMpio ? TRUE : FALSE);\r
     AttemptConfigData->ValidPath     = FALSE;\r
 \r
     if (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_AUTOCONFIG) {\r
@@ -1097,25 +2256,28 @@ IScsiGetConfigData (
       AttemptConfigData->SessionConfigData.TargetInfoFromDhcp    = TRUE;\r
 \r
       AttemptConfigData->AutoConfigureMode =\r
-        (UINT8) (mPrivate->Ipv6Flag ? IP_MODE_AUTOCONFIG_IP6 : IP_MODE_AUTOCONFIG_IP4);\r
+        (UINT8)(mPrivate->Ipv6Flag ? IP_MODE_AUTOCONFIG_IP6 : IP_MODE_AUTOCONFIG_IP4);\r
+      AttemptConfigData->AutoConfigureSuccess = FALSE;\r
     }\r
-    \r
+\r
     //\r
     // Get some information from dhcp server.\r
     //\r
-    if (AttemptConfigData->SessionConfigData.Enabled != ISCSI_DISABLED &&\r
-        AttemptConfigData->SessionConfigData.InitiatorInfoFromDhcp) {\r
-\r
+    if ((AttemptConfigData->SessionConfigData.Enabled != ISCSI_DISABLED) &&\r
+        AttemptConfigData->SessionConfigData.InitiatorInfoFromDhcp)\r
+    {\r
       if (!mPrivate->Ipv6Flag &&\r
-          (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_IP4 ||\r
-           AttemptConfigData->AutoConfigureMode == IP_MODE_AUTOCONFIG_IP4)) {\r
+          ((AttemptConfigData->SessionConfigData.IpMode == IP_MODE_IP4) ||\r
+           (AttemptConfigData->AutoConfigureMode == IP_MODE_AUTOCONFIG_IP4)))\r
+      {\r
         Status = IScsiDoDhcp (Private->Image, Private->Controller, AttemptConfigData);\r
         if (!EFI_ERROR (Status)) {\r
           AttemptConfigData->DhcpSuccess = TRUE;\r
         }\r
       } else if (mPrivate->Ipv6Flag &&\r
-                (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_IP6 ||\r
-                 AttemptConfigData->AutoConfigureMode == IP_MODE_AUTOCONFIG_IP6)) {\r
+                 ((AttemptConfigData->SessionConfigData.IpMode == IP_MODE_IP6) ||\r
+                  (AttemptConfigData->AutoConfigureMode == IP_MODE_AUTOCONFIG_IP6)))\r
+      {\r
         Status = IScsiDoDhcp6 (Private->Image, Private->Controller, AttemptConfigData);\r
         if (!EFI_ERROR (Status)) {\r
           AttemptConfigData->DhcpSuccess = TRUE;\r
@@ -1125,13 +2287,11 @@ IScsiGetConfigData (
       //\r
       // Refresh the state of this attempt to NVR.\r
       //\r
-      AsciiStrToUnicodeStr (AttemptConfigData->MacString, MacString);\r
       UnicodeSPrint (\r
         mPrivate->PortString,\r
-        (UINTN) ISCSI_NAME_IFR_MAX_SIZE,\r
-        L"%s%d",\r
-        MacString,\r
-        (UINTN) AttemptConfigData->AttemptConfigIndex\r
+        (UINTN)ISCSI_NAME_IFR_MAX_SIZE,\r
+        L"Attempt %d",\r
+        (UINTN)AttemptConfigData->AttemptConfigIndex\r
         );\r
 \r
       gRT->SetVariable (\r
@@ -1165,7 +2325,7 @@ IScsiGetConfigData (
 \r
     UnicodeSPrint (\r
       mPrivate->PortString,\r
-      (UINTN) ISCSI_NAME_IFR_MAX_SIZE,\r
+      (UINTN)ISCSI_NAME_IFR_MAX_SIZE,\r
       L"MAC: %s, PFA: Bus %d | Dev %d | Func %d, iSCSI mode: %s, IP version: %s",\r
       MacString,\r
       NicInfo->BusNumber,\r
@@ -1181,7 +2341,9 @@ IScsiGetConfigData (
                                                  mPrivate->PortString,\r
                                                  NULL\r
                                                  );\r
-    ASSERT (AttemptConfigData->AttemptTitleHelpToken != 0);\r
+    if (AttemptConfigData->AttemptTitleHelpToken == 0) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
 \r
     //\r
     // Record the attempt in global link list.\r
@@ -1228,13 +2390,13 @@ IScsiGetConfigData (
     if (mPrivate->SinglePathCount == 0) {\r
       return EFI_NOT_FOUND;\r
     }\r
+\r
     mPrivate->ValidSinglePathCount = mPrivate->SinglePathCount;\r
   }\r
 \r
   return EFI_SUCCESS;\r
 }\r
 \r
-\r
 /**\r
   Get the device path of the iSCSI tcp connection and update it.\r
 \r
@@ -1246,13 +2408,14 @@ IScsiGetConfigData (
 **/\r
 EFI_DEVICE_PATH_PROTOCOL *\r
 IScsiGetTcpConnDevicePath (\r
-  IN ISCSI_SESSION      *Session\r
+  IN ISCSI_SESSION  *Session\r
   )\r
 {\r
   ISCSI_CONNECTION          *Conn;\r
   EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
   EFI_STATUS                Status;\r
   EFI_DEV_PATH              *DPathNode;\r
+  UINTN                     PathLen;\r
 \r
   if (Session->State != SESSION_STATE_LOGGED_IN) {\r
     return NULL;\r
@@ -1268,41 +2431,88 @@ IScsiGetTcpConnDevicePath (
   Status = gBS->HandleProtocol (\r
                   Conn->TcpIo.Handle,\r
                   &gEfiDevicePathProtocolGuid,\r
-                  (VOID **) &DevicePath\r
-                  );  \r
+                  (VOID **)&DevicePath\r
+                  );\r
   if (EFI_ERROR (Status)) {\r
     return NULL;\r
   }\r
+\r
   //\r
   // Duplicate it.\r
   //\r
-  DevicePath  = DuplicateDevicePath (DevicePath);\r
+  DevicePath = DuplicateDevicePath (DevicePath);\r
   if (DevicePath == NULL) {\r
     return NULL;\r
   }\r
 \r
-  DPathNode   = (EFI_DEV_PATH *) DevicePath;\r
+  DPathNode = (EFI_DEV_PATH *)DevicePath;\r
 \r
   while (!IsDevicePathEnd (&DPathNode->DevPath)) {\r
     if (DevicePathType (&DPathNode->DevPath) == MESSAGING_DEVICE_PATH) {\r
-      if (!Conn->Ipv6Flag && DevicePathSubType (&DPathNode->DevPath) == MSG_IPv4_DP) {\r
-        DPathNode->Ipv4.LocalPort       = 0;\r
-        DPathNode->Ipv4.StaticIpAddress = (BOOLEAN) !Session->ConfigData->SessionConfigData.InitiatorInfoFromDhcp;\r
+      if (!Conn->Ipv6Flag && (DevicePathSubType (&DPathNode->DevPath) == MSG_IPv4_DP)) {\r
+        DPathNode->Ipv4.LocalPort = 0;\r
+\r
+        DPathNode->Ipv4.StaticIpAddress =\r
+          (BOOLEAN)(!Session->ConfigData->SessionConfigData.InitiatorInfoFromDhcp);\r
+\r
+        //\r
+        //  Add a judgement here to support previous versions of IPv4_DEVICE_PATH.\r
+        //  In previous versions of IPv4_DEVICE_PATH, GatewayIpAddress and SubnetMask\r
+        //  do not exist.\r
+        //  In new version of IPv4_DEVICE_PATH, structure length is 27.\r
+        //\r
+\r
+        PathLen = DevicePathNodeLength (&DPathNode->Ipv4);\r
+\r
+        if (PathLen == IP4_NODE_LEN_NEW_VERSIONS) {\r
+          IP4_COPY_ADDRESS (\r
+            &DPathNode->Ipv4.GatewayIpAddress,\r
+            &Session->ConfigData->SessionConfigData.Gateway\r
+            );\r
+\r
+          IP4_COPY_ADDRESS (\r
+            &DPathNode->Ipv4.SubnetMask,\r
+            &Session->ConfigData->SessionConfigData.SubnetMask\r
+            );\r
+        }\r
+\r
         break;\r
-      } else if (Conn->Ipv6Flag && DevicePathSubType (&DPathNode->DevPath) == MSG_IPv6_DP) {\r
-        DPathNode->Ipv6.LocalPort       = 0;\r
-        DPathNode->Ipv6.StaticIpAddress = (BOOLEAN) !Session->ConfigData->SessionConfigData.InitiatorInfoFromDhcp;\r
+      } else if (Conn->Ipv6Flag && (DevicePathSubType (&DPathNode->DevPath) == MSG_IPv6_DP)) {\r
+        DPathNode->Ipv6.LocalPort = 0;\r
+\r
+        //\r
+        //  Add a judgement here to support previous versions of IPv6_DEVICE_PATH.\r
+        //  In previous versions of IPv6_DEVICE_PATH, IpAddressOrigin, PrefixLength\r
+        //  and GatewayIpAddress do not exist.\r
+        //  In new version of IPv6_DEVICE_PATH, structure length is 60, while in\r
+        //  old versions, the length is 43.\r
+        //\r
+\r
+        PathLen = DevicePathNodeLength (&DPathNode->Ipv6);\r
+\r
+        if (PathLen == IP6_NODE_LEN_NEW_VERSIONS ) {\r
+          DPathNode->Ipv6.IpAddressOrigin = 0;\r
+          DPathNode->Ipv6.PrefixLength    = IP6_PREFIX_LENGTH;\r
+          ZeroMem (&DPathNode->Ipv6.GatewayIpAddress, sizeof (EFI_IPv6_ADDRESS));\r
+        } else if (PathLen == IP6_NODE_LEN_OLD_VERSIONS) {\r
+          //\r
+          //  StaticIPAddress is a field in old versions of IPv6_DEVICE_PATH, while ignored in new\r
+          //  version. Set StaticIPAddress through its' offset in old IPv6_DEVICE_PATH.\r
+          //\r
+          *((UINT8 *)(&DPathNode->Ipv6) + IP6_OLD_IPADDRESS_OFFSET) =\r
+            (BOOLEAN)(!Session->ConfigData->SessionConfigData.InitiatorInfoFromDhcp);\r
+        }\r
+\r
         break;\r
       }\r
     }\r
 \r
-    DPathNode = (EFI_DEV_PATH *) NextDevicePathNode (&DPathNode->DevPath);\r
+    DPathNode = (EFI_DEV_PATH *)NextDevicePathNode (&DPathNode->DevPath);\r
   }\r
 \r
   return DevicePath;\r
 }\r
 \r
-\r
 /**\r
   Abort the session when the transition from BS to RT is initiated.\r
 \r
@@ -1317,12 +2527,81 @@ IScsiOnExitBootService (
   IN VOID       *Context\r
   )\r
 {\r
-  ISCSI_DRIVER_DATA *Private;\r
+  ISCSI_DRIVER_DATA  *Private;\r
+\r
+  Private = (ISCSI_DRIVER_DATA *)Context;\r
 \r
-  Private = (ISCSI_DRIVER_DATA *) Context;\r
   gBS->CloseEvent (Private->ExitBootServiceEvent);\r
+  Private->ExitBootServiceEvent = NULL;\r
 \r
   if (Private->Session != NULL) {\r
     IScsiSessionAbort (Private->Session);\r
   }\r
 }\r
+\r
+/**\r
+  Tests whether a controller handle is being managed by IScsi driver.\r
+\r
+  This function tests whether the driver specified by DriverBindingHandle is\r
+  currently managing the controller specified by ControllerHandle.  This test\r
+  is performed by evaluating if the protocol specified by ProtocolGuid is\r
+  present on ControllerHandle and is was opened by DriverBindingHandle and Nic\r
+  Device handle with an attribute of EFI_OPEN_PROTOCOL_BY_DRIVER.\r
+  If ProtocolGuid is NULL, then ASSERT().\r
+\r
+  @param  ControllerHandle     A handle for a controller to test.\r
+  @param  DriverBindingHandle  Specifies the driver binding handle for the\r
+                               driver.\r
+  @param  ProtocolGuid         Specifies the protocol that the driver specified\r
+                               by DriverBindingHandle opens in its Start()\r
+                               function.\r
+\r
+  @retval EFI_SUCCESS          ControllerHandle is managed by the driver\r
+                               specified by DriverBindingHandle.\r
+  @retval EFI_UNSUPPORTED      ControllerHandle is not managed by the driver\r
+                               specified by DriverBindingHandle.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+IScsiTestManagedDevice (\r
+  IN  EFI_HANDLE  ControllerHandle,\r
+  IN  EFI_HANDLE  DriverBindingHandle,\r
+  IN  EFI_GUID    *ProtocolGuid\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  VOID        *ManagedInterface;\r
+  EFI_HANDLE  NicControllerHandle;\r
+\r
+  ASSERT (ProtocolGuid != NULL);\r
+\r
+  NicControllerHandle = NetLibGetNicHandle (ControllerHandle, ProtocolGuid);\r
+  if (NicControllerHandle == NULL) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  Status = gBS->OpenProtocol (\r
+                  ControllerHandle,\r
+                  (EFI_GUID *)ProtocolGuid,\r
+                  &ManagedInterface,\r
+                  DriverBindingHandle,\r
+                  NicControllerHandle,\r
+                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                  );\r
+  if (!EFI_ERROR (Status)) {\r
+    gBS->CloseProtocol (\r
+           ControllerHandle,\r
+           (EFI_GUID *)ProtocolGuid,\r
+           DriverBindingHandle,\r
+           NicControllerHandle\r
+           );\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  if (Status != EFI_ALREADY_STARTED) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r