]> git.proxmox.com Git - mirror_edk2.git/commitdiff
NetworkPkg:Add scriptable configuration to iSCSI driver by leveraging x-UEFI.
authorZhang Lubo <lubo.zhang@intel.com>
Fri, 17 Feb 2017 06:43:41 +0000 (14:43 +0800)
committerJiaxin Wu <jiaxin.wu@intel.com>
Thu, 23 Feb 2017 08:50:54 +0000 (16:50 +0800)
v2:
Add error handling if can not create Attempts in driver entry point.
Since we support to define a macro be a PCD value, we enhance our code
by modifying the structure in IFR_NVDATA. This effect code logic mainly
in Creating Keywords,Convert IFR NvData To AttemptConfigData ByKeyword and
reverse function.
Fix typo errors and sync based on the latest code.

Enable iSCSI keywords configuration based on x-UEFI
name space. we introduce new PCD to control the attempt
numbers which will be created in non activated state, besides
the Attempt name is changed to READ_ONLY attribute in UI.
We can invoke KEYWORD HANDLER Protocol to configure
the related keywords.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Zhang Lubo <lubo.zhang@intel.com>
Cc: Ye Ting <ting.ye@intel.com>
Cc: Fu Siyuan <siyuan.fu@intel.com>
Cc: Wu Jiaxin <jiaxin.wu@intel.com>
Reviewed-by: Ye Ting <ting.ye@intel.com>
Reviewed-by: Fu Siyuan <siyuan.fu@intel.com>
Reviewed-by: Wu Jiaxin jiaxin.wu@intel.com
NetworkPkg/IScsiDxe/IScsiConfig.c
NetworkPkg/IScsiDxe/IScsiConfig.h
NetworkPkg/IScsiDxe/IScsiConfigNVDataStruc.h
NetworkPkg/IScsiDxe/IScsiConfigStrings.uni
NetworkPkg/IScsiDxe/IScsiConfigVfr.vfr
NetworkPkg/IScsiDxe/IScsiDriver.c
NetworkPkg/IScsiDxe/IScsiDriver.h
NetworkPkg/IScsiDxe/IScsiDxe.inf
NetworkPkg/IScsiDxe/IScsiMisc.c
NetworkPkg/IScsiDxe/IScsiMisc.h
NetworkPkg/NetworkPkg.dec

index 40ea75ae3a2941af06f43f29795a580c9718e956..b1696205c4dbff9c29ffe191f68ee238d5502817 100644 (file)
@@ -289,6 +289,98 @@ IScsiConvertIsIdToString (
   return EFI_SUCCESS;\r
 }\r
 \r
+/**\r
+  Get the Offset value specified by the input String.\r
+\r
+  @param[in]  Configuration      A null-terminated Unicode string in\r
+                                 <ConfigString> format.\r
+  @param[in]  String             The string is "&OFFSET=".\r
+  @param[out] Value              The Offset value.\r
+\r
+  @retval EFI_OUT_OF_RESOURCES   Insufficient resources to store neccessary\r
+                                 structures.\r
+  @retval EFI_SUCCESS            Value of <Number> is outputted in Number\r
+                                 successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+IScsiGetValue (\r
+  IN  CONST EFI_STRING             Configuration,\r
+  IN  CHAR16                       *String,\r
+  OUT UINTN                        *Value\r
+  )\r
+{\r
+  CHAR16                           *StringPtr;\r
+  CHAR16                           *TmpPtr;\r
+  CHAR16                           *Str;\r
+  CHAR16                           TmpStr[2];\r
+  UINTN                            Length;\r
+  UINTN                            Len;\r
+  UINTN                            Index;\r
+  UINT8                            *Buf;\r
+  UINT8                            DigitUint8;\r
+  EFI_STATUS                       Status;\r
+\r
+  //\r
+  // Get Value.\r
+  //\r
+  Buf = NULL;\r
+  StringPtr = StrStr (Configuration, String);\r
+  ASSERT(StringPtr != NULL);\r
+  StringPtr += StrLen (String);\r
+  TmpPtr = StringPtr;\r
+\r
+  while (*StringPtr != L'\0' && *StringPtr != L'&') {\r
+    StringPtr ++;\r
+  }\r
+  Length = StringPtr - TmpPtr;\r
+  Len = Length + 1;\r
+\r
+  Str = AllocateZeroPool (Len * sizeof (CHAR16));\r
+  if (Str == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Exit;\r
+  }\r
+\r
+  CopyMem (Str, TmpPtr, Len * sizeof (CHAR16));\r
+  *(Str + Length) = L'\0';\r
+\r
+  Len = (Len + 1) / 2;\r
+  Buf = (UINT8 *) AllocateZeroPool (Len);\r
+  if (Buf == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Exit;\r
+  }\r
+\r
+  ZeroMem (TmpStr, sizeof (TmpStr));\r
+  for (Index = 0; Index < Length; Index ++) {\r
+    TmpStr[0] = Str[Length - Index - 1];\r
+    DigitUint8 = (UINT8) StrHexToUint64 (TmpStr);\r
+    if ((Index & 1) == 0) {\r
+      Buf [Index/2] = DigitUint8;\r
+    } else {\r
+      Buf [Index/2] = (UINT8) ((DigitUint8 << 4) + Buf [Index/2]);\r
+    }\r
+  }\r
+\r
+  *Value = 0;\r
+  CopyMem (\r
+    Value,\r
+    Buf,\r
+    (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)\r
+    );\r
+\r
+  FreePool (Buf);\r
+  Status = EFI_SUCCESS;\r
+\r
+Exit:\r
+  if (Str != NULL) {\r
+    FreePool (Str);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
 /**\r
   Get the attempt config data from global structure by the ConfigIndex.\r
 \r
@@ -349,6 +441,64 @@ IScsiConfigGetAttemptByNic (
   return NULL;\r
 }\r
 \r
+/**\r
+  Extract the Index of the attempt list.\r
+\r
+  @param[in]   AttemptNameList     The Name list of the Attempts.\r
+  @param[out]  AttemptIndexList    The Index list of the Attempts.\r
+  @param[in]   IsAddAttempts       If TRUE, Indicates add one or more attempts.\r
+                                   If FALSE, Indicates delete attempts or change attempt order.\r
+\r
+  @retval EFI_SUCCESS              The Attempt list is valid.\r
+  @retval EFI_INVALID_PARAMETERS   The Attempt List is invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+IScsiGetAttemptIndexList (\r
+  IN      CHAR16                    *AttemptNameList,\r
+     OUT  UINT8                     *AttemptIndexList,\r
+  IN      BOOLEAN                   IsAddAttempts\r
+)\r
+{\r
+  ISCSI_ATTEMPT_CONFIG_NVDATA   *AttemptConfigData;\r
+  CHAR16                        *AttemptStr;\r
+  UINT8                         AttemptIndex;\r
+  UINTN                         Len;\r
+  UINTN                         Index;\r
+\r
+  Index = 0;\r
+\r
+  if ((AttemptNameList == NULL) || (*AttemptNameList == L'\0')) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  AttemptStr = AttemptNameList;\r
+  Len = StrLen (L"attempt:");\r
+\r
+  while (*AttemptStr != L'\0') {\r
+    AttemptStr = StrStr (AttemptStr, L"attempt:");\r
+    if (AttemptStr == NULL) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+    AttemptStr += Len;\r
+    AttemptIndex = (UINT8)(*AttemptStr - L'0');\r
+    AttemptConfigData  = IScsiConfigGetAttemptByConfigIndex (AttemptIndex);\r
+    if (IsAddAttempts) {\r
+      if ((AttemptConfigData != NULL) || ((AttemptIndex) > PcdGet8 (PcdMaxIScsiAttemptNumber))) {\r
+        return EFI_INVALID_PARAMETER;\r
+      }\r
+    } else {\r
+      if (AttemptConfigData == NULL) {\r
+        return EFI_INVALID_PARAMETER;\r
+      }\r
+    }\r
+\r
+    AttemptIndexList[Index] = AttemptIndex;\r
+    Index ++;\r
+    AttemptStr += 2;\r
+  }\r
+  return EFI_SUCCESS;\r
+}\r
 \r
 /**\r
   Convert the iSCSI configuration data into the IFR data.\r
@@ -460,6 +610,134 @@ IScsiConvertAttemptConfigDataToIfrNvData (
     );\r
 }\r
 \r
+/**\r
+  Convert the iSCSI configuration data into the IFR data Which will be used\r
+  to extract the iSCSI Keyword configuration in <ConfigAltResp> format.\r
+\r
+  @param[in, out]  IfrNvData              The IFR nv data.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+IScsiConvertAttemptConfigDataToIfrNvDataByKeyword (\r
+  IN OUT ISCSI_CONFIG_IFR_NVDATA  *IfrNvData\r
+  )\r
+{\r
+  LIST_ENTRY                    *Entry;\r
+  ISCSI_ATTEMPT_CONFIG_NVDATA   *Attempt;\r
+  ISCSI_SESSION_CONFIG_NVDATA   *SessionConfigData;\r
+  ISCSI_CHAP_AUTH_CONFIG_NVDATA *AuthConfigData;\r
+  CHAR16                        AttemptNameList[ATTEMPT_NAME_LIST_SIZE];\r
+  EFI_IP_ADDRESS                Ip;\r
+  UINTN                         Index;\r
+\r
+  ZeroMem (AttemptNameList, sizeof (AttemptNameList));\r
+\r
+  NET_LIST_FOR_EACH (Entry, &mPrivate->AttemptConfigs) {\r
+    Attempt = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);\r
+    //\r
+    // Normal session configuration parameters.\r
+    //\r
+    SessionConfigData                 = &Attempt->SessionConfigData;\r
+\r
+    Index   = Attempt->AttemptConfigIndex - 1;\r
+\r
+    //\r
+    // Save the attempt to AttemptNameList as Attempt:1 Attempt:2\r
+    //\r
+    AsciiStrToUnicodeStrS (\r
+      Attempt->AttemptName,\r
+      AttemptNameList + StrLen (AttemptNameList),\r
+      ATTEMPT_NAME_LIST_SIZE\r
+    );\r
+    *(AttemptNameList + StrLen (AttemptNameList) - 2) = L':';\r
+    *(AttemptNameList + StrLen (AttemptNameList))     = L' ';\r
+\r
+    AsciiStrToUnicodeStrS (\r
+      Attempt->AttemptName,\r
+      IfrNvData->ISCSIAttemptName  + ATTEMPT_NAME_SIZE * Index,\r
+      ATTEMPT_NAME_SIZE\r
+    );\r
+\r
+    IfrNvData->ISCSIBootEnableList[Index]          = SessionConfigData->Enabled;\r
+    IfrNvData->ISCSIIpAddressTypeList[Index]       = SessionConfigData->IpMode;\r
+\r
+    IfrNvData->ISCSIInitiatorInfoViaDHCP[Index]    = SessionConfigData->InitiatorInfoFromDhcp;\r
+    IfrNvData->ISCSITargetInfoViaDHCP[Index]       = SessionConfigData->TargetInfoFromDhcp;\r
+    IfrNvData->ISCSIConnectRetry[Index]            = SessionConfigData->ConnectRetryCount;\r
+    IfrNvData->ISCSIConnectTimeout[Index]          = SessionConfigData->ConnectTimeout;\r
+    IfrNvData->ISCSITargetTcpPort[Index]           = SessionConfigData->TargetPort;\r
+\r
+    if (SessionConfigData->IpMode == IP_MODE_IP4) {\r
+      CopyMem (&Ip.v4, &SessionConfigData->LocalIp, sizeof (EFI_IPv4_ADDRESS));\r
+      IScsiIpToStr (&Ip, FALSE, IfrNvData->Keyword[Index].ISCSIInitiatorIpAddress);\r
+      CopyMem (&Ip.v4, &SessionConfigData->SubnetMask, sizeof (EFI_IPv4_ADDRESS));\r
+      IScsiIpToStr (&Ip, FALSE, IfrNvData->Keyword[Index].ISCSIInitiatorNetmask);\r
+      CopyMem (&Ip.v4, &SessionConfigData->Gateway, sizeof (EFI_IPv4_ADDRESS));\r
+      IScsiIpToStr (&Ip, FALSE, IfrNvData->Keyword[Index].ISCSIInitiatorGateway);\r
+      if (SessionConfigData->TargetIp.v4.Addr[0] != '\0') {\r
+        CopyMem (&Ip.v4, &SessionConfigData->TargetIp, sizeof (EFI_IPv4_ADDRESS));\r
+        IScsiIpToStr (&Ip, FALSE, IfrNvData->Keyword[Index].ISCSITargetIpAddress);\r
+      }\r
+    } else if (SessionConfigData->IpMode == IP_MODE_IP6) {\r
+      ZeroMem (IfrNvData->Keyword[Index].ISCSITargetIpAddress, sizeof (IfrNvData->TargetIp));\r
+      if (SessionConfigData->TargetIp.v6.Addr[0] != '\0') {\r
+        IP6_COPY_ADDRESS (&Ip.v6, &SessionConfigData->TargetIp);\r
+        IScsiIpToStr (&Ip, TRUE, IfrNvData->Keyword[Index].ISCSITargetIpAddress);\r
+      }\r
+    }\r
+\r
+    AsciiStrToUnicodeStrS (\r
+      SessionConfigData->TargetName,\r
+      IfrNvData->Keyword[Index].ISCSITargetName,\r
+      ISCSI_NAME_MAX_SIZE\r
+      );\r
+\r
+    if (SessionConfigData->DnsMode) {\r
+      AsciiStrToUnicodeStrS (\r
+        SessionConfigData->TargetUrl,\r
+        IfrNvData->TargetIp,\r
+        sizeof (IfrNvData->TargetIp) / sizeof (IfrNvData->TargetIp[0])\r
+        );\r
+    }\r
+\r
+    IScsiLunToUnicodeStr (SessionConfigData->BootLun, IfrNvData->Keyword[Index].ISCSILun);\r
+    IScsiConvertIsIdToString (IfrNvData->Keyword[Index].ISCSIIsId, SessionConfigData->IsId);\r
+\r
+    IfrNvData->ISCSIAuthenticationMethod[Index]    = Attempt->AuthenticationType;\r
+\r
+    if (Attempt->AuthenticationType == ISCSI_AUTH_TYPE_CHAP) {\r
+      AuthConfigData      = &Attempt->AuthConfigData.CHAP;\r
+      IfrNvData->ISCSIChapType[Index] = AuthConfigData->CHAPType;\r
+      AsciiStrToUnicodeStrS (\r
+        AuthConfigData->CHAPName,\r
+        IfrNvData->Keyword[Index].ISCSIChapUsername,\r
+        ISCSI_CHAP_NAME_STORAGE\r
+        );\r
+\r
+      AsciiStrToUnicodeStrS (\r
+        AuthConfigData->CHAPSecret,\r
+        IfrNvData->Keyword[Index].ISCSIChapSecret,\r
+        ISCSI_CHAP_SECRET_STORAGE\r
+        );\r
+\r
+      AsciiStrToUnicodeStrS (\r
+        AuthConfigData->ReverseCHAPName,\r
+        IfrNvData->Keyword[Index].ISCSIReverseChapUsername,\r
+        ISCSI_CHAP_NAME_STORAGE\r
+        );\r
+\r
+      AsciiStrToUnicodeStrS (\r
+        AuthConfigData->ReverseCHAPSecret,\r
+        IfrNvData->Keyword[Index].ISCSIReverseChapSecret,\r
+        ISCSI_CHAP_SECRET_STORAGE\r
+        );\r
+    }\r
+  }\r
+\r
+  CopyMem(IfrNvData->ISCSIDisplayAttemptList, AttemptNameList, ATTEMPT_NAME_LIST_SIZE);\r
+}\r
+\r
 /**\r
   Convert the IFR data to iSCSI configuration data.\r
 \r
@@ -536,7 +814,7 @@ IScsiConvertIfrNvDataToAttemptConfigData (
         L"Connection Establishing Timeout is less than minimum value 100ms.",\r
         NULL\r
         );\r
-      \r
+\r
       return EFI_INVALID_PARAMETER;\r
     }\r
 \r
@@ -557,7 +835,7 @@ IScsiConvertIfrNvDataToAttemptConfigData (
             L"Gateway address is set but subnet mask is zero.",\r
             NULL\r
             );\r
-          \r
+\r
           return EFI_INVALID_PARAMETER;\r
         } else if (!IP4_NET_EQUAL (HostIp.Addr[0], Gateway.Addr[0], SubnetMask.Addr[0])) {\r
           CreatePopUp (\r
@@ -566,7 +844,7 @@ IScsiConvertIfrNvDataToAttemptConfigData (
             L"Local IP and Gateway are not in the same subnet.",\r
             NULL\r
             );\r
-          \r
+\r
           return EFI_INVALID_PARAMETER;\r
         }\r
       }\r
@@ -613,7 +891,6 @@ IScsiConvertIfrNvDataToAttemptConfigData (
       }\r
     }\r
 \r
-\r
     //\r
     // Validate the authentication info.\r
     //\r
@@ -647,26 +924,19 @@ IScsiConvertIfrNvDataToAttemptConfigData (
     //\r
     SameNicAttempt = IScsiConfigGetAttemptByNic (Attempt, IfrNvData->Enabled);\r
     if (SameNicAttempt != NULL) {\r
-      AttemptName1 = (CHAR16 *) AllocateZeroPool (ATTEMPT_NAME_MAX_SIZE * sizeof (CHAR16));\r
+      AttemptName1 = (CHAR16 *) AllocateZeroPool (ATTEMPT_NAME_SIZE * sizeof (CHAR16));\r
       if (AttemptName1 == NULL) {\r
         return EFI_OUT_OF_RESOURCES;\r
       }\r
 \r
-      AttemptName2 = (CHAR16 *) AllocateZeroPool (ATTEMPT_NAME_MAX_SIZE * sizeof (CHAR16));\r
+      AttemptName2 = (CHAR16 *) AllocateZeroPool (ATTEMPT_NAME_SIZE * sizeof (CHAR16));\r
       if (AttemptName2 == NULL) {\r
         FreePool (AttemptName1);\r
         return EFI_OUT_OF_RESOURCES;\r
       }      \r
-      \r
-      AsciiStrToUnicodeStrS (Attempt->AttemptName, AttemptName1, ATTEMPT_NAME_MAX_SIZE);\r
-      if (StrLen (AttemptName1) > ATTEMPT_NAME_SIZE) {\r
-        CopyMem (&AttemptName1[ATTEMPT_NAME_SIZE], L"...", 4 * sizeof (CHAR16));\r
-      }\r
 \r
-      AsciiStrToUnicodeStrS (SameNicAttempt->AttemptName, AttemptName2, ATTEMPT_NAME_MAX_SIZE);\r
-      if (StrLen (AttemptName2) > ATTEMPT_NAME_SIZE) {\r
-        CopyMem (&AttemptName2[ATTEMPT_NAME_SIZE], L"...", 4 * sizeof (CHAR16));\r
-      }\r
+      AsciiStrToUnicodeStrS (Attempt->AttemptName, AttemptName1, ATTEMPT_NAME_SIZE);\r
+      AsciiStrToUnicodeStrS (SameNicAttempt->AttemptName, AttemptName2, ATTEMPT_NAME_SIZE);\r
 \r
       UnicodeSPrint (\r
         mPrivate->PortString,\r
@@ -691,7 +961,6 @@ IScsiConvertIfrNvDataToAttemptConfigData (
   //\r
   // Update the iSCSI Mode data and record it in attempt help info.\r
   //\r
-  Attempt->SessionConfigData.Enabled = IfrNvData->Enabled;\r
   if (IfrNvData->Enabled == ISCSI_DISABLED) {\r
     UnicodeSPrint (IScsiMode, 64, L"Disabled");\r
   } else if (IfrNvData->Enabled == ISCSI_ENABLED) {\r
@@ -815,11 +1084,10 @@ IScsiConvertIfrNvDataToAttemptConfigData (
   } else if (ExistAttempt == NULL) {\r
     //\r
     // When a new attempt is created, pointer of the attempt is saved to\r
-    // mPrivate->NewAttempt, and also saved to mCallbackInfo->Current in\r
-    // IScsiConfigProcessDefault. If input Attempt does not match any existing\r
-    // attempt, it should be a new created attempt. Save it to system now.\r
-    //    \r
-    ASSERT (Attempt == mPrivate->NewAttempt);\r
+    // mCallbackInfo->Current in IScsiConfigProcessDefault. If input Attempt\r
+    // does not match any existing attempt, it should be a new created attempt.\r
+    // Save it to system now.\r
+    //\r
 \r
     //\r
     // Save current order number for this attempt.\r
@@ -870,11 +1138,6 @@ IScsiConvertIfrNvDataToAttemptConfigData (
     //\r
     InsertTailList (&mPrivate->AttemptConfigs, &Attempt->Link);\r
     mPrivate->AttemptCount++;\r
-    //\r
-    // Reset mPrivate->NewAttempt to NULL, which indicates none attempt is created\r
-    // but not saved now.\r
-    //\r
-    mPrivate->NewAttempt = NULL;\r
 \r
     if (IfrNvData->Enabled == ISCSI_ENABLED_FOR_MPIO) {\r
       //\r
@@ -888,17 +1151,12 @@ IScsiConvertIfrNvDataToAttemptConfigData (
 \r
     IScsiConfigUpdateAttempt ();\r
   }\r
+  Attempt->SessionConfigData.Enabled = IfrNvData->Enabled;\r
 \r
   //\r
   // Record the user configuration information in NVR.\r
   //\r
-  UnicodeSPrint (\r
-    mPrivate->PortString,\r
-    (UINTN) ISCSI_NAME_IFR_MAX_SIZE,\r
-    L"%s%d",\r
-    MacString,\r
-    (UINTN) Attempt->AttemptConfigIndex\r
-    );\r
+  UnicodeSPrint (mPrivate->PortString, (UINTN) ISCSI_NAME_IFR_MAX_SIZE, L"Attempt %d", Attempt->AttemptConfigIndex);\r
 \r
   FreePool (MacString);\r
 \r
@@ -912,107 +1170,745 @@ IScsiConvertIfrNvDataToAttemptConfigData (
 }\r
 \r
 /**\r
-  Create Hii Extend Label OpCode as the start opcode and end opcode. It is \r
-  a help function.\r
+  Convert the IFR data configured by keyword to iSCSI configuration data.\r
 \r
-  @param[in]  StartLabelNumber   The number of start label.\r
-  @param[out] StartOpCodeHandle  Points to the start opcode handle.\r
-  @param[out] StartLabel         Points to the created start opcode.\r
-  @param[out] EndOpCodeHandle    Points to the end opcode handle.\r
-  @param[out] EndLabel           Points to the created end opcode.\r
+  @param[in]  IfrNvData      Point to ISCSI_CONFIG_IFR_NVDATA.\r
+  @param[in]  OffSet         The offset of the variable to the configuration structure.\r
 \r
-  @retval EFI_OUT_OF_RESOURCES   Do not have sufficient resource to finish this\r
-                                 operation.\r
-  @retval EFI_INVALID_PARAMETER  Any input parameter is invalid.                                 \r
+  @retval EFI_INVALID_PARAMETER  Any input or configured parameter is invalid.\r
   @retval EFI_SUCCESS            The operation is completed successfully.\r
 \r
 **/\r
 EFI_STATUS\r
-IScsiCreateOpCode (\r
-  IN  UINT16                        StartLabelNumber,\r
-  OUT VOID                          **StartOpCodeHandle,\r
-  OUT EFI_IFR_GUID_LABEL            **StartLabel,\r
-  OUT VOID                          **EndOpCodeHandle,\r
-  OUT EFI_IFR_GUID_LABEL            **EndLabel\r
+IScsiConvertlfrNvDataToAttemptConfigDataByKeyword (\r
+  IN ISCSI_CONFIG_IFR_NVDATA          *IfrNvData,\r
+  IN UINTN                             OffSet\r
   )\r
 {\r
-  EFI_STATUS                        Status;\r
-  EFI_IFR_GUID_LABEL                *InternalStartLabel;\r
-  EFI_IFR_GUID_LABEL                *InternalEndLabel;\r
-\r
-  if (StartOpCodeHandle == NULL || StartLabel == NULL || EndOpCodeHandle == NULL || EndLabel == NULL) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  *StartOpCodeHandle = NULL;\r
-  *EndOpCodeHandle   = NULL;\r
-  Status             = EFI_OUT_OF_RESOURCES;\r
+  ISCSI_ATTEMPT_CONFIG_NVDATA      *Attempt;\r
+  UINT8                            AttemptIndex;\r
+  UINT8                            Index;\r
+  CHAR16                           *AttemptName1;\r
+  CHAR16                           *AttemptName2;\r
+  ISCSI_ATTEMPT_CONFIG_NVDATA      *SameNicAttempt;\r
+  CHAR8                            LunString[ISCSI_LUN_STR_MAX_LEN];\r
+  CHAR8                            IScsiName[ISCSI_NAME_MAX_SIZE];\r
+  CHAR8                            IpString[IP_STR_MAX_SIZE];\r
+  EFI_IP_ADDRESS                   HostIp;\r
+  EFI_IP_ADDRESS                   SubnetMask;\r
+  EFI_IP_ADDRESS                   Gateway;\r
+  EFI_INPUT_KEY                    Key;\r
+  UINT64                           Lun;\r
+  EFI_STATUS                       Status;\r
 \r
-  //\r
-  // Initialize the container for dynamic opcodes.\r
-  //\r
-  *StartOpCodeHandle = HiiAllocateOpCodeHandle ();\r
-  if (*StartOpCodeHandle == NULL) {\r
-    return Status;\r
-  }\r
+  ZeroMem (IScsiName, sizeof (IScsiName));\r
 \r
-  *EndOpCodeHandle = HiiAllocateOpCodeHandle ();\r
-  if (*EndOpCodeHandle == NULL) {\r
-    goto Exit;\r
-  }\r
+  if (OffSet < ATTEMPT_BOOTENABLE_VAR_OFFSET) {\r
+    return EFI_SUCCESS;\r
 \r
-  //\r
-  // Create Hii Extend Label OpCode as the start opcode.\r
-  //\r
-  InternalStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (\r
-                                                *StartOpCodeHandle,\r
-                                                &gEfiIfrTianoGuid,\r
-                                                NULL,\r
-                                                sizeof (EFI_IFR_GUID_LABEL)\r
-                                                );\r
-  if (InternalStartLabel == NULL) {\r
-    goto Exit;\r
-  }\r
-  \r
-  InternalStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
-  InternalStartLabel->Number       = StartLabelNumber;\r
+  } else if ((OffSet >= ATTEMPT_BOOTENABLE_VAR_OFFSET) && (OffSet < ATTEMPT_ADDRESS_TYPE_VAR_OFFSET)) {\r
+    AttemptIndex = (UINT8) ((OffSet - ATTEMPT_BOOTENABLE_VAR_OFFSET) + 1);\r
+    Attempt = IScsiConfigGetAttemptByConfigIndex (AttemptIndex);\r
+    if (Attempt == NULL) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+    IfrNvData->Enabled = IfrNvData->ISCSIBootEnableList[AttemptIndex - 1];\r
+    //\r
+    // Validate the configuration of attempt.\r
+    //\r
+    if (IfrNvData->Enabled != ISCSI_DISABLED) {\r
+      //\r
+      // Check whether this attempt uses NIC which is already used by existing attempt.\r
+      //\r
+      SameNicAttempt = IScsiConfigGetAttemptByNic (Attempt, IfrNvData->Enabled);\r
+      if (SameNicAttempt != NULL) {\r
+        AttemptName1 = (CHAR16 *) AllocateZeroPool (ATTEMPT_NAME_SIZE * sizeof (CHAR16));\r
+        if (AttemptName1 == NULL) {\r
+          return EFI_OUT_OF_RESOURCES;\r
+        }\r
 \r
-  //\r
-  // Create Hii Extend Label OpCode as the end opcode.\r
-  //\r
-  InternalEndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (\r
-                                              *EndOpCodeHandle,\r
-                                              &gEfiIfrTianoGuid,\r
-                                              NULL,\r
-                                              sizeof (EFI_IFR_GUID_LABEL)\r
-                                              );\r
-  if (InternalEndLabel == NULL) {\r
-    goto Exit;\r
-  }\r
+        AttemptName2 = (CHAR16 *) AllocateZeroPool (ATTEMPT_NAME_SIZE * sizeof (CHAR16));\r
+        if (AttemptName2 == NULL) {\r
+          FreePool (AttemptName1);\r
+          return EFI_OUT_OF_RESOURCES;\r
+        }\r
 \r
-  InternalEndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
-  InternalEndLabel->Number       = LABEL_END;\r
+        AsciiStrToUnicodeStrS (Attempt->AttemptName, AttemptName1, ATTEMPT_NAME_SIZE);\r
+        AsciiStrToUnicodeStrS (SameNicAttempt->AttemptName, AttemptName2, ATTEMPT_NAME_SIZE);\r
 \r
-  *StartLabel = InternalStartLabel;\r
-  *EndLabel   = InternalEndLabel;\r
+        UnicodeSPrint (\r
+          mPrivate->PortString,\r
+          (UINTN) ISCSI_NAME_IFR_MAX_SIZE,\r
+          L"Warning! \"%s\" uses same NIC as Attempt \"%s\".",\r
+          AttemptName1,\r
+          AttemptName2\r
+          );\r
 \r
-  return EFI_SUCCESS;\r
+        CreatePopUp (\r
+          EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+          &Key,\r
+          mPrivate->PortString,\r
+          NULL\r
+          );\r
 \r
-Exit:\r
+        FreePool (AttemptName1);\r
+        FreePool (AttemptName2);\r
+      }\r
+    }\r
 \r
-  if (*StartOpCodeHandle != NULL) {\r
-    HiiFreeOpCodeHandle (*StartOpCodeHandle);\r
-  }\r
+    if (IfrNvData->Enabled == ISCSI_DISABLED &&\r
+        Attempt->SessionConfigData.Enabled != ISCSI_DISABLED) {\r
 \r
-  if (*EndOpCodeHandle != NULL) {\r
-    HiiFreeOpCodeHandle (*EndOpCodeHandle);\r
-  }\r
-  \r
-  return Status;\r
-}\r
+      //\r
+      // User updates the Attempt from "Enabled"/"Enabled for MPIO" to "Disabled".\r
+      //\r
+      if (Attempt->SessionConfigData.Enabled == ISCSI_ENABLED_FOR_MPIO) {\r
+        if (mPrivate->MpioCount < 1) {\r
+          return EFI_ABORTED;\r
+        }\r
 \r
-/**\r
-  Callback function when user presses "Add an Attempt".\r
+        if (--mPrivate->MpioCount == 0) {\r
+          mPrivate->EnableMpio = FALSE;\r
+        }\r
+      } else if (Attempt->SessionConfigData.Enabled == ISCSI_ENABLED) {\r
+        if (mPrivate->SinglePathCount < 1) {\r
+          return EFI_ABORTED;\r
+        }\r
+        mPrivate->SinglePathCount--;\r
+      }\r
+\r
+    } else if (IfrNvData->Enabled == ISCSI_ENABLED_FOR_MPIO &&\r
+               Attempt->SessionConfigData.Enabled == ISCSI_ENABLED) {\r
+      //\r
+      // User updates the Attempt from "Enabled" to "Enabled for MPIO".\r
+      //\r
+      if (mPrivate->SinglePathCount < 1) {\r
+        return EFI_ABORTED;\r
+      }\r
+\r
+      mPrivate->EnableMpio = TRUE;\r
+      mPrivate->MpioCount++;\r
+      mPrivate->SinglePathCount--;\r
+\r
+    } else if (IfrNvData->Enabled == ISCSI_ENABLED &&\r
+               Attempt->SessionConfigData.Enabled == ISCSI_ENABLED_FOR_MPIO) {\r
+      //\r
+      // User updates the Attempt from "Enabled for MPIO" to "Enabled".\r
+      //\r
+      if (mPrivate->MpioCount < 1) {\r
+        return EFI_ABORTED;\r
+      }\r
+\r
+      if (--mPrivate->MpioCount == 0) {\r
+        mPrivate->EnableMpio = FALSE;\r
+      }\r
+      mPrivate->SinglePathCount++;\r
+\r
+    } else if (IfrNvData->Enabled != ISCSI_DISABLED &&\r
+               Attempt->SessionConfigData.Enabled == ISCSI_DISABLED) {\r
+      //\r
+      // User updates the Attempt from "Disabled" to "Enabled"/"Enabled for MPIO".\r
+      //\r
+      if (IfrNvData->Enabled == ISCSI_ENABLED_FOR_MPIO) {\r
+        mPrivate->EnableMpio = TRUE;\r
+        mPrivate->MpioCount++;\r
+\r
+      } else if (IfrNvData->Enabled == ISCSI_ENABLED) {\r
+        mPrivate->SinglePathCount++;\r
+      }\r
+    }\r
+    Attempt->SessionConfigData.Enabled = IfrNvData->Enabled;\r
+\r
+  } else if ((OffSet >= ATTEMPT_ADDRESS_TYPE_VAR_OFFSET) && (OffSet < ATTEMPT_CONNECT_RETRY_VAR_OFFSET)) {\r
+    AttemptIndex = (UINT8) ((OffSet - ATTEMPT_ADDRESS_TYPE_VAR_OFFSET) + 1);\r
+    Attempt = IScsiConfigGetAttemptByConfigIndex (AttemptIndex);\r
+    if (Attempt == NULL) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+    Attempt->SessionConfigData.IpMode = IfrNvData->ISCSIIpAddressTypeList[AttemptIndex - 1];\r
+    if (Attempt->SessionConfigData.IpMode < IP_MODE_AUTOCONFIG) {\r
+      Attempt->AutoConfigureMode = 0;\r
+    }\r
+\r
+  } else if ((OffSet >= ATTEMPT_CONNECT_RETRY_VAR_OFFSET) && (OffSet < ATTEMPT_CONNECT_TIMEOUT_VAR_OFFSET)) {\r
+    AttemptIndex = (UINT8) ((OffSet - ATTEMPT_CONNECT_RETRY_VAR_OFFSET) + 1);\r
+    Attempt = IScsiConfigGetAttemptByConfigIndex (AttemptIndex);\r
+    if (Attempt == NULL) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+    Attempt->SessionConfigData.ConnectRetryCount = IfrNvData->ISCSIConnectRetry[AttemptIndex - 1];\r
+    if (Attempt->SessionConfigData.ConnectRetryCount == 0) {\r
+      Attempt->SessionConfigData.ConnectRetryCount = CONNECT_MIN_RETRY;\r
+    }\r
+\r
+  } else if ((OffSet >= ATTEMPT_CONNECT_TIMEOUT_VAR_OFFSET) && (OffSet < ATTEMPT_INITIATOR_VIA_DHCP_VAR_OFFSET)) {\r
+    AttemptIndex = (UINT8) ((OffSet - ATTEMPT_CONNECT_TIMEOUT_VAR_OFFSET) / 2 + 1);\r
+    Attempt = IScsiConfigGetAttemptByConfigIndex (AttemptIndex);\r
+    if (Attempt == NULL) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+    Attempt->SessionConfigData.ConnectTimeout = IfrNvData->ISCSIConnectTimeout[AttemptIndex - 1];\r
+    if (Attempt->SessionConfigData.ConnectTimeout == 0) {\r
+      Attempt->SessionConfigData.ConnectTimeout = CONNECT_DEFAULT_TIMEOUT;\r
+    }\r
+\r
+    if (Attempt->SessionConfigData.Enabled != ISCSI_DISABLED) {\r
+      if (Attempt->SessionConfigData.ConnectTimeout < CONNECT_MIN_TIMEOUT) {\r
+        CreatePopUp (\r
+          EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+          &Key,\r
+          L"Connection Establishing Timeout is less than minimum value 100ms.",\r
+          NULL\r
+          );\r
+        return EFI_INVALID_PARAMETER;\r
+      }\r
+    }\r
+\r
+  } else if ((OffSet >= ATTEMPT_INITIATOR_VIA_DHCP_VAR_OFFSET) && (OffSet < ATTEMPT_TARGET_VIA_DHCP_VAR_OFFSET)) {\r
+    AttemptIndex = (UINT8) ((OffSet - ATTEMPT_INITIATOR_VIA_DHCP_VAR_OFFSET) + 1);\r
+    Attempt = IScsiConfigGetAttemptByConfigIndex (AttemptIndex);\r
+    if (Attempt == NULL) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+    Attempt->SessionConfigData.InitiatorInfoFromDhcp = IfrNvData->ISCSIInitiatorInfoViaDHCP[AttemptIndex - 1];\r
+\r
+  } else if ((OffSet >= ATTEMPT_TARGET_VIA_DHCP_VAR_OFFSET) && (OffSet < ATTEMPT_TARGET_TCP_PORT_VAR_OFFSET)) {\r
+    AttemptIndex = (UINT8) ((OffSet - ATTEMPT_TARGET_VIA_DHCP_VAR_OFFSET) + 1);\r
+    Attempt = IScsiConfigGetAttemptByConfigIndex (AttemptIndex);\r
+    if (Attempt == NULL) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+\r
+    if ((Attempt->SessionConfigData.IpMode < IP_MODE_AUTOCONFIG) && (Attempt->SessionConfigData.InitiatorInfoFromDhcp)) {\r
+      Attempt->SessionConfigData.TargetInfoFromDhcp = IfrNvData->ISCSITargetInfoViaDHCP[AttemptIndex - 1];\r
+    } else {\r
+      CreatePopUp (\r
+        EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+        &Key,\r
+        L"Invalid Configuration, Check value of IpMode or Enable DHCP!",\r
+        NULL\r
+        );\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+\r
+  } else if ((OffSet >= ATTEMPT_TARGET_TCP_PORT_VAR_OFFSET) && (OffSet < ATTEMPT_AUTHENTICATION_METHOD_VAR_OFFSET)) {\r
+    AttemptIndex = (UINT8) ((OffSet - ATTEMPT_TARGET_TCP_PORT_VAR_OFFSET) / 2 + 1);\r
+    Attempt = IScsiConfigGetAttemptByConfigIndex (AttemptIndex);\r
+    if (Attempt == NULL) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+    if ((Attempt->SessionConfigData.IpMode < IP_MODE_AUTOCONFIG) && (!Attempt->SessionConfigData.TargetInfoFromDhcp)) {\r
+      Attempt->SessionConfigData.TargetPort = IfrNvData->ISCSITargetTcpPort[AttemptIndex - 1];\r
+      if (Attempt->SessionConfigData.TargetPort == 0) {\r
+        Attempt->SessionConfigData.TargetPort = ISCSI_WELL_KNOWN_PORT;\r
+      }\r
+    } else {\r
+      CreatePopUp (\r
+        EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+        &Key,\r
+        L"Invalid Configuration, Check value of IpMode or Target Via DHCP!",\r
+        NULL\r
+        );\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+\r
+  } else if ((OffSet >= ATTEMPT_AUTHENTICATION_METHOD_VAR_OFFSET) && (OffSet < ATTEMPT_CHARTYPE_VAR_OFFSET)) {\r
+    AttemptIndex = (UINT8) ((OffSet - ATTEMPT_AUTHENTICATION_METHOD_VAR_OFFSET) + 1);\r
+    Attempt = IScsiConfigGetAttemptByConfigIndex (AttemptIndex);\r
+    if (Attempt == NULL) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+\r
+    Attempt->AuthenticationType = IfrNvData->ISCSIAuthenticationMethod[AttemptIndex - 1];\r
+\r
+  } else if ((OffSet >= ATTEMPT_CHARTYPE_VAR_OFFSET) && (OffSet < ATTEMPT_ISID_VAR_OFFSET)) {\r
+    AttemptIndex = (UINT8) ((OffSet - ATTEMPT_CHARTYPE_VAR_OFFSET) + 1);\r
+    Attempt = IScsiConfigGetAttemptByConfigIndex (AttemptIndex);\r
+    if (Attempt == NULL) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+    if (Attempt->AuthenticationType == ISCSI_AUTH_TYPE_CHAP) {\r
+      Attempt->AuthConfigData.CHAP.CHAPType = IfrNvData->ISCSIChapType[AttemptIndex - 1];\r
+    }\r
+\r
+  } else if (OffSet >= ATTEMPT_ISID_VAR_OFFSET) {\r
+    Index = (UINT8) ((OffSet - ATTEMPT_ISID_VAR_OFFSET) / sizeof (KEYWORD_STR));\r
+    AttemptIndex = Index + 1;\r
+    Attempt = IScsiConfigGetAttemptByConfigIndex (AttemptIndex);\r
+    if (Attempt == NULL) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+\r
+    OffSet = OffSet - Index * sizeof (KEYWORD_STR);\r
+\r
+    if ((OffSet >= ATTEMPT_ISID_VAR_OFFSET) && (OffSet < ATTEMPT_INITIATOR_IP_ADDRESS_VAR_OFFSET)) {\r
+      IScsiParseIsIdFromString (IfrNvData->Keyword[Index].ISCSIIsId, Attempt->SessionConfigData.IsId);\r
+\r
+    }  else if ((OffSet >= ATTEMPT_INITIATOR_IP_ADDRESS_VAR_OFFSET) && (OffSet < ATTEMPT_INITIATOR_NET_MASK_VAR_OFFSET)) {\r
+      if ((Attempt->SessionConfigData.IpMode == IP_MODE_IP4) && (!Attempt->SessionConfigData.InitiatorInfoFromDhcp)) {\r
+        //\r
+        // Config Local ip\r
+        //\r
+        Status = NetLibStrToIp4 (IfrNvData->Keyword[Index].ISCSIInitiatorIpAddress, &HostIp.v4);\r
+        if (EFI_ERROR (Status) || ((Attempt->SessionConfigData.SubnetMask.Addr[0] != 0) &&\r
+             !NetIp4IsUnicast (NTOHL (HostIp.Addr[0]), NTOHL(*(UINT32*)Attempt->SessionConfigData.SubnetMask.Addr)))) {\r
+          CreatePopUp (\r
+            EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+            &Key,\r
+            L"Invalid IP address!",\r
+            NULL\r
+            );\r
+          return EFI_INVALID_PARAMETER;\r
+        } else {\r
+          CopyMem (&Attempt->SessionConfigData.LocalIp, &HostIp.v4, sizeof (HostIp.v4));\r
+        }\r
+      } else {\r
+        CreatePopUp (\r
+          EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+          &Key,\r
+          L"Invalid Configuration, Check value of IpMode or Enable DHCP!",\r
+          NULL\r
+          );\r
+        return EFI_INVALID_PARAMETER;\r
+      }\r
+\r
+    } else if ((OffSet >= ATTEMPT_INITIATOR_NET_MASK_VAR_OFFSET) && (OffSet < ATTEMPT_INITIATOR_GATE_WAY_VAR_OFFSET)) {\r
+      if ((Attempt->SessionConfigData.IpMode == IP_MODE_IP4) && (!Attempt->SessionConfigData.InitiatorInfoFromDhcp)) {\r
+        Status = NetLibStrToIp4 (IfrNvData->Keyword[Index].ISCSIInitiatorNetmask, &SubnetMask.v4);\r
+        if (EFI_ERROR (Status) || ((SubnetMask.Addr[0] != 0) && (IScsiGetSubnetMaskPrefixLength (&SubnetMask.v4) == 0))) {\r
+          CreatePopUp (\r
+            EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+            &Key,\r
+            L"Invalid Subnet Mask!",\r
+            NULL\r
+            );\r
+          return EFI_INVALID_PARAMETER;\r
+        } else {\r
+          CopyMem (&Attempt->SessionConfigData.SubnetMask, &SubnetMask.v4, sizeof (SubnetMask.v4));\r
+        }\r
+      } else {\r
+        CreatePopUp (\r
+          EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+          &Key,\r
+          L"Invalid Configuration, Check value of IpMode or Enable DHCP!",\r
+          NULL\r
+          );\r
+        return EFI_INVALID_PARAMETER;\r
+      }\r
+\r
+    } else if ((OffSet >= ATTEMPT_INITIATOR_GATE_WAY_VAR_OFFSET) && (OffSet < ATTEMPT_TARGET_NAME_VAR_OFFSET)) {\r
+      if ((Attempt->SessionConfigData.IpMode == IP_MODE_IP4) && (!Attempt->SessionConfigData.InitiatorInfoFromDhcp)) {\r
+        Status = NetLibStrToIp4 (IfrNvData->Keyword[Index].ISCSIInitiatorGateway, &Gateway.v4);\r
+        if (EFI_ERROR (Status) ||\r
+          ((Gateway.Addr[0] != 0) && (Attempt->SessionConfigData.SubnetMask.Addr[0] != 0) &&\r
+             !NetIp4IsUnicast (NTOHL (Gateway.Addr[0]), NTOHL(*(UINT32*)Attempt->SessionConfigData.SubnetMask.Addr)))) {\r
+          CreatePopUp (\r
+            EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+            &Key,\r
+            L"Invalid Gateway!",\r
+            NULL\r
+            );\r
+          return EFI_INVALID_PARAMETER;\r
+        } else {\r
+          CopyMem (&Attempt->SessionConfigData.Gateway, &Gateway.v4, sizeof (Gateway.v4));\r
+        }\r
+      } else {\r
+        CreatePopUp (\r
+          EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+          &Key,\r
+          L"Invalid Configuration, Check value of IpMode or Enable DHCP!",\r
+          NULL\r
+          );\r
+        return EFI_INVALID_PARAMETER;\r
+      }\r
+\r
+    } else if ((OffSet >= ATTEMPT_TARGET_NAME_VAR_OFFSET) && (OffSet < ATTEMPT_TARGET_IP_ADDRESS_VAR_OFFSET)) {\r
+      if ((Attempt->SessionConfigData.IpMode < IP_MODE_AUTOCONFIG) && (!Attempt->SessionConfigData.TargetInfoFromDhcp)) {\r
+        UnicodeStrToAsciiStrS (IfrNvData->Keyword[Index].ISCSITargetName, IScsiName, ISCSI_NAME_MAX_SIZE);\r
+        Status = IScsiNormalizeName (IScsiName, AsciiStrLen (IScsiName));\r
+        if (EFI_ERROR (Status)) {\r
+          CreatePopUp (\r
+            EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+            &Key,\r
+            L"Invalid iSCSI Name!",\r
+            NULL\r
+            );\r
+        } else {\r
+          AsciiStrCpyS (Attempt->SessionConfigData.TargetName, ISCSI_NAME_MAX_SIZE, IScsiName);\r
+        }\r
+        if (Attempt->SessionConfigData.Enabled != ISCSI_DISABLED) {\r
+          if (Attempt->SessionConfigData.TargetName[0] == L'\0') {\r
+            CreatePopUp (\r
+              EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+              &Key,\r
+              L"iSCSI target name is NULL!",\r
+              NULL\r
+              );\r
+            return EFI_INVALID_PARAMETER;\r
+          }\r
+        }\r
+      } else {\r
+        CreatePopUp (\r
+          EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+          &Key,\r
+          L"Invalid Configuration, Check value of IpMode or Target Via DHCP!",\r
+          NULL\r
+          );\r
+        return EFI_INVALID_PARAMETER;\r
+      }\r
+\r
+    } else if ((OffSet >= ATTEMPT_TARGET_IP_ADDRESS_VAR_OFFSET) && (OffSet < ATTEMPT_LUN_VAR_OFFSET)) {\r
+      if ((Attempt->SessionConfigData.IpMode < IP_MODE_AUTOCONFIG) && (!Attempt->SessionConfigData.TargetInfoFromDhcp)) {\r
+        UnicodeStrToAsciiStrS (IfrNvData->Keyword[Index].ISCSITargetIpAddress, IpString, sizeof (IpString));\r
+        Status = IScsiAsciiStrToIp (IpString, Attempt->SessionConfigData.IpMode, &HostIp);\r
+        if (EFI_ERROR (Status) || !IpIsUnicast (&HostIp, Attempt->SessionConfigData.IpMode)) {\r
+          Attempt->SessionConfigData.DnsMode = TRUE;\r
+          ZeroMem (&Attempt->SessionConfigData.TargetIp, sizeof (Attempt->SessionConfigData.TargetIp));\r
+          UnicodeStrToAsciiStrS (IfrNvData->Keyword[Index].ISCSITargetIpAddress, Attempt->SessionConfigData.TargetUrl, ISCSI_NAME_MAX_SIZE);\r
+        } else {\r
+          Attempt->SessionConfigData.DnsMode = FALSE;\r
+          CopyMem (&Attempt->SessionConfigData.TargetIp, &HostIp, sizeof (HostIp));\r
+        }\r
+      } else {\r
+        CreatePopUp (\r
+          EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+          &Key,\r
+          L"Invalid Configuration, Check value of IpMode or Target Via DHCP!",\r
+          NULL\r
+          );\r
+        return EFI_INVALID_PARAMETER;\r
+      }\r
+\r
+    } else if ((OffSet >= ATTEMPT_LUN_VAR_OFFSET) && (OffSet < ATTEMPT_CHAR_USER_NAME_VAR_OFFSET)) {\r
+      if ((Attempt->SessionConfigData.IpMode < IP_MODE_AUTOCONFIG) && (Attempt->SessionConfigData.TargetInfoFromDhcp == 0)) {\r
+        //\r
+        // Config LUN.\r
+        //\r
+        UnicodeStrToAsciiStrS (IfrNvData->Keyword[Index].ISCSILun, LunString, ISCSI_LUN_STR_MAX_LEN);\r
+        Status = IScsiAsciiStrToLun (LunString, (UINT8 *) &Lun);\r
+        if (EFI_ERROR (Status)) {\r
+          CreatePopUp (\r
+            EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+            &Key,\r
+            L"Invalid LUN string, Examples are: 4752-3A4F-6b7e-2F99, 6734-9-156f-127, 4186-9!",\r
+            NULL\r
+            );\r
+        } else {\r
+          CopyMem (&Attempt->SessionConfigData.BootLun, &Lun, sizeof (Lun));\r
+        }\r
+      } else {\r
+        CreatePopUp (\r
+          EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+          &Key,\r
+          L"Invalid Configuration, Check value of IpMode or Target Via DHCP!",\r
+          NULL\r
+          );\r
+        return EFI_INVALID_PARAMETER;\r
+      }\r
+\r
+    } else if ((OffSet >= ATTEMPT_CHAR_USER_NAME_VAR_OFFSET) && (OffSet < ATTEMPT_CHAR_SECRET_VAR_OFFSET)) {\r
+      if (Attempt->AuthenticationType == ISCSI_AUTH_TYPE_CHAP) {\r
+        UnicodeStrToAsciiStrS (\r
+          IfrNvData->Keyword[Index].ISCSIChapUsername,\r
+          Attempt->AuthConfigData.CHAP.CHAPName,\r
+          ISCSI_CHAP_NAME_STORAGE\r
+          );\r
+\r
+        if (Attempt->SessionConfigData.Enabled != ISCSI_DISABLED) {\r
+          if (IfrNvData->CHAPName[0] == L'\0') {\r
+            CreatePopUp (\r
+              EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+              &Key,\r
+              L"CHAP Name is invalid!",\r
+              NULL\r
+              );\r
+            return EFI_INVALID_PARAMETER;\r
+          }\r
+        }\r
+      } else {\r
+        CreatePopUp (\r
+          EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+          &Key,\r
+          L"Invalid Configuration, Check value of AuthenticationType!",\r
+          NULL\r
+          );\r
+        return EFI_INVALID_PARAMETER;\r
+      }\r
+\r
+    } else if ((OffSet >= ATTEMPT_CHAR_SECRET_VAR_OFFSET) && (OffSet < ATTEMPT_CHAR_REVERSE_USER_NAME_VAR_OFFSET)) {\r
+      if (Attempt->AuthenticationType == ISCSI_AUTH_TYPE_CHAP) {\r
+        UnicodeStrToAsciiStrS (\r
+          IfrNvData->Keyword[Index].ISCSIChapSecret,\r
+          Attempt->AuthConfigData.CHAP.CHAPSecret,\r
+          ISCSI_CHAP_SECRET_STORAGE\r
+          );\r
+\r
+        if (Attempt->SessionConfigData.Enabled != ISCSI_DISABLED) {\r
+          if (IfrNvData->CHAPSecret[0] == L'\0') {\r
+            CreatePopUp (\r
+              EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+              &Key,\r
+              L"CHAP Secret is invalid!",\r
+              NULL\r
+              );\r
+            return EFI_INVALID_PARAMETER;\r
+          }\r
+        }\r
+      } else {\r
+        CreatePopUp (\r
+          EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+          &Key,\r
+          L"Invalid Configuration, Check value of AuthenticationType!",\r
+          NULL\r
+          );\r
+        return EFI_INVALID_PARAMETER;\r
+      }\r
+\r
+    } else if ((OffSet >= ATTEMPT_CHAR_REVERSE_USER_NAME_VAR_OFFSET) && (OffSet < ATTEMPT_CHAR_REVERSE_SECRET_VAR_OFFSET)) {\r
+      if (Attempt->AuthConfigData.CHAP.CHAPType == ISCSI_CHAP_MUTUAL) {\r
+        UnicodeStrToAsciiStrS (\r
+          IfrNvData->Keyword[Index].ISCSIReverseChapUsername,\r
+          Attempt->AuthConfigData.CHAP.ReverseCHAPName,\r
+          ISCSI_CHAP_NAME_STORAGE\r
+          );\r
+        if (Attempt->SessionConfigData.Enabled != ISCSI_DISABLED) {\r
+          if (IfrNvData->ReverseCHAPName[0] == L'\0') {\r
+            CreatePopUp (\r
+              EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+              &Key,\r
+              L"Reverse CHAP Name is invalid!",\r
+              NULL\r
+              );\r
+            return EFI_INVALID_PARAMETER;\r
+          }\r
+        }\r
+      } else {\r
+        CreatePopUp (\r
+          EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+          &Key,\r
+          L"Invalid Configuration, Check value of AuthenticationType or Chap Type!",\r
+          NULL\r
+          );\r
+        return EFI_INVALID_PARAMETER;\r
+      }\r
+\r
+    } else if (OffSet >= ATTEMPT_CHAR_REVERSE_SECRET_VAR_OFFSET) {\r
+      if (Attempt->AuthConfigData.CHAP.CHAPType == ISCSI_CHAP_MUTUAL) {\r
+        UnicodeStrToAsciiStrS (\r
+          IfrNvData->Keyword[Index].ISCSIReverseChapSecret,\r
+          Attempt->AuthConfigData.CHAP.ReverseCHAPSecret,\r
+          ISCSI_CHAP_SECRET_STORAGE\r
+          );\r
+\r
+        if (Attempt->SessionConfigData.Enabled != ISCSI_DISABLED) {\r
+          if (IfrNvData->ReverseCHAPSecret[0] == L'\0') {\r
+            CreatePopUp (\r
+              EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+              &Key,\r
+              L"Reverse CHAP Secret is invalid!",\r
+              NULL\r
+              );\r
+            return EFI_INVALID_PARAMETER;\r
+          }\r
+        }\r
+      } else {\r
+        CreatePopUp (\r
+          EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+          &Key,\r
+          L"Invalid Configuration, Check value of AuthenticationType or Chap Type!",\r
+          NULL\r
+          );\r
+        return EFI_INVALID_PARAMETER;\r
+      }\r
+    }\r
+  }\r
+\r
+\r
+\r
+  //\r
+  // Record the user configuration information in NVR.\r
+  //\r
+\r
+  UnicodeSPrint (mPrivate->PortString, (UINTN) ISCSI_NAME_IFR_MAX_SIZE, L"Attempt %d", Attempt->AttemptConfigIndex);\r
+  return gRT->SetVariable (\r
+                mPrivate->PortString,\r
+                &gEfiIScsiInitiatorNameProtocolGuid,\r
+                ISCSI_CONFIG_VAR_ATTR,\r
+                sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA),\r
+                Attempt\r
+                );\r
+\r
+}\r
+\r
+/**\r
+  Create Hii Extend Label OpCode as the start opcode and end opcode. It is\r
+  a help function.\r
+\r
+  @param[in]  StartLabelNumber   The number of start label.\r
+  @param[out] StartOpCodeHandle  Points to the start opcode handle.\r
+  @param[out] StartLabel         Points to the created start opcode.\r
+  @param[out] EndOpCodeHandle    Points to the end opcode handle.\r
+  @param[out] EndLabel           Points to the created end opcode.\r
+\r
+  @retval EFI_OUT_OF_RESOURCES   Do not have sufficient resource to finish this\r
+                                 operation.\r
+  @retval EFI_INVALID_PARAMETER  Any input parameter is invalid.\r
+  @retval EFI_SUCCESS            The operation is completed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+IScsiCreateOpCode (\r
+  IN  UINT16                        StartLabelNumber,\r
+  OUT VOID                          **StartOpCodeHandle,\r
+  OUT EFI_IFR_GUID_LABEL            **StartLabel,\r
+  OUT VOID                          **EndOpCodeHandle,\r
+  OUT EFI_IFR_GUID_LABEL            **EndLabel\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  EFI_IFR_GUID_LABEL                *InternalStartLabel;\r
+  EFI_IFR_GUID_LABEL                *InternalEndLabel;\r
+\r
+  if (StartOpCodeHandle == NULL || StartLabel == NULL || EndOpCodeHandle == NULL || EndLabel == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  *StartOpCodeHandle = NULL;\r
+  *EndOpCodeHandle   = NULL;\r
+  Status             = EFI_OUT_OF_RESOURCES;\r
+\r
+  //\r
+  // Initialize the container for dynamic opcodes.\r
+  //\r
+  *StartOpCodeHandle = HiiAllocateOpCodeHandle ();\r
+  if (*StartOpCodeHandle == NULL) {\r
+    return Status;\r
+  }\r
+\r
+  *EndOpCodeHandle = HiiAllocateOpCodeHandle ();\r
+  if (*EndOpCodeHandle == NULL) {\r
+    goto Exit;\r
+  }\r
+\r
+  //\r
+  // Create Hii Extend Label OpCode as the start opcode.\r
+  //\r
+  InternalStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (\r
+                                                *StartOpCodeHandle,\r
+                                                &gEfiIfrTianoGuid,\r
+                                                NULL,\r
+                                                sizeof (EFI_IFR_GUID_LABEL)\r
+                                                );\r
+  if (InternalStartLabel == NULL) {\r
+    goto Exit;\r
+  }\r
+\r
+  InternalStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
+  InternalStartLabel->Number       = StartLabelNumber;\r
+\r
+  //\r
+  // Create Hii Extend Label OpCode as the end opcode.\r
+  //\r
+  InternalEndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (\r
+                                              *EndOpCodeHandle,\r
+                                              &gEfiIfrTianoGuid,\r
+                                              NULL,\r
+                                              sizeof (EFI_IFR_GUID_LABEL)\r
+                                              );\r
+  if (InternalEndLabel == NULL) {\r
+    goto Exit;\r
+  }\r
+\r
+  InternalEndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
+  InternalEndLabel->Number       = LABEL_END;\r
+\r
+  *StartLabel = InternalStartLabel;\r
+  *EndLabel   = InternalEndLabel;\r
+\r
+  return EFI_SUCCESS;\r
+\r
+Exit:\r
+\r
+  if (*StartOpCodeHandle != NULL) {\r
+    HiiFreeOpCodeHandle (*StartOpCodeHandle);\r
+  }\r
+\r
+  if (*EndOpCodeHandle != NULL) {\r
+    HiiFreeOpCodeHandle (*EndOpCodeHandle);\r
+  }\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Update the MAIN form to display the configured attempts.\r
+\r
+**/\r
+VOID\r
+IScsiConfigUpdateAttempt (\r
+  VOID\r
+  )\r
+{\r
+  LIST_ENTRY                    *Entry;\r
+  ISCSI_ATTEMPT_CONFIG_NVDATA   *AttemptConfigData;\r
+  VOID                          *StartOpCodeHandle;\r
+  EFI_IFR_GUID_LABEL            *StartLabel;\r
+  VOID                          *EndOpCodeHandle;\r
+  EFI_IFR_GUID_LABEL            *EndLabel;\r
+  EFI_STATUS                    Status;\r
+\r
+  Status = IScsiCreateOpCode (\r
+             ATTEMPT_ENTRY_LABEL,\r
+             &StartOpCodeHandle,\r
+             &StartLabel,\r
+             &EndOpCodeHandle,\r
+             &EndLabel\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    return ;\r
+  }\r
+\r
+  NET_LIST_FOR_EACH (Entry, &mPrivate->AttemptConfigs) {\r
+    AttemptConfigData = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);\r
+    if (AttemptConfigData->Actived == ISCSI_ACTIVE_ENABLED) {\r
+      //\r
+      // Update Attempt Help Info.\r
+      //\r
+      UnicodeSPrint (mPrivate->PortString, (UINTN) ISCSI_NAME_IFR_MAX_SIZE, L"Attempt %d", (UINTN) AttemptConfigData->AttemptConfigIndex);\r
+      AttemptConfigData->AttemptTitleToken = HiiSetString (\r
+                                               mCallbackInfo->RegisteredHandle,\r
+                                               0,\r
+                                               mPrivate->PortString,\r
+                                               NULL\r
+                                               );\r
+      if (AttemptConfigData->AttemptTitleToken == 0) {\r
+        return ;\r
+      }\r
+\r
+      HiiCreateGotoOpCode (\r
+        StartOpCodeHandle,                         // Container for dynamic created opcodes\r
+        FORMID_ATTEMPT_FORM,                       // Form ID\r
+        AttemptConfigData->AttemptTitleToken,      // Prompt text\r
+        AttemptConfigData->AttemptTitleHelpToken,  // Help text\r
+        EFI_IFR_FLAG_CALLBACK,                     // Question flag\r
+        (UINT16) (KEY_ATTEMPT_ENTRY_BASE + AttemptConfigData->AttemptConfigIndex)   // Question ID\r
+        );\r
+    }\r
+  }\r
+\r
+  HiiUpdateForm (\r
+    mCallbackInfo->RegisteredHandle, // HII handle\r
+    &gIScsiConfigGuid,               // Formset GUID\r
+    FORMID_MAIN_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
+\r
+/**\r
+  Callback function when user presses "Add an Attempt".\r
 \r
   @retval EFI_OUT_OF_RESOURCES   Does not have sufficient resources to finish this\r
                                  operation.\r
@@ -1109,76 +2005,184 @@ Exit:
   return Status;\r
 }\r
 \r
-\r
 /**\r
-  Update the MAIN form to display the configured attempts.\r
+  Add the attempts by keyword 'iSCSIAddAttempts', you can use this keyword with\r
+  value 'attempt:1 attempt:2' etc to add one or more attempts once. This is different\r
+  with IScsiConfigAddAttempt function which is used to add attempt by UI configuration. \r
+\r
+  @param[in]  AttemptList        The new attempt List will be added.\r
+\r
+  @retval EFI_SUCCESS            The operation to add attempt list successfully.\r
+  @retval EFI_INVALID_PARAMETER  Any parameter is invalid.\r
+  @retval EFI_NOT_FOUND          Cannot find the corresponding variable.\r
+  @retval EFI_OUT_OF_RESOURCES   Fail to finish the operation due to lack of\r
+                                 resources.\r
 \r
 **/\r
-VOID\r
-IScsiConfigUpdateAttempt (\r
-  VOID\r
+EFI_STATUS\r
+IScsiConfigAddAttemptsByKeywords (\r
+  IN UINT8                   *AttemptList\r
   )\r
 {\r
-  CHAR16                        AttemptName[ATTEMPT_NAME_MAX_SIZE];\r
-  LIST_ENTRY                    *Entry;\r
-  ISCSI_ATTEMPT_CONFIG_NVDATA   *AttemptConfigData;\r
-  VOID                          *StartOpCodeHandle;\r
-  EFI_IFR_GUID_LABEL            *StartLabel;\r
-  VOID                          *EndOpCodeHandle;\r
-  EFI_IFR_GUID_LABEL            *EndLabel;\r
-  EFI_STATUS                    Status;\r
+  UINT8                       Index;\r
+  UINT8                       Number;\r
+  UINTN                       TotalNumber;\r
+  UINT8                       Nic;\r
+  UINT8                       *AttemptConfigOrder;\r
+  UINTN                       AttemptConfigOrderSize;\r
+  UINT8                       *AttemptConfigOrderTmp;\r
+  ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;\r
+  ISCSI_NIC_INFO              *NicInfo;\r
+  CHAR16                      MacString[ISCSI_MAX_MAC_STRING_LEN];\r
+  CHAR16                      IScsiMode[64];\r
+  CHAR16                      IpMode[64];\r
+  EFI_STATUS                  Status;\r
 \r
-  Status = IScsiCreateOpCode (\r
-             ATTEMPT_ENTRY_LABEL,\r
-             &StartOpCodeHandle,\r
-             &StartLabel,\r
-             &EndOpCodeHandle,\r
-             &EndLabel\r
-             );\r
-  if (EFI_ERROR (Status)) {\r
-    return ;\r
+  Nic = mPrivate->CurrentNic;\r
+  NicInfo = IScsiGetNicInfoByIndex (Nic);\r
+  if (NicInfo == NULL) {\r
+    return EFI_NOT_FOUND;\r
   }\r
 \r
-  NET_LIST_FOR_EACH (Entry, &mPrivate->AttemptConfigs) {\r
-    AttemptConfigData = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);\r
+  //\r
+  // The MAC info will be recorded in Config Data.\r
+  //\r
+  IScsiMacAddrToStr (\r
+    &NicInfo->PermanentAddress,\r
+    NicInfo->HwAddressSize,\r
+    NicInfo->VlanId,\r
+    MacString\r
+    );\r
+\r
+  for (Index = 0; Index < PcdGet8 (PcdMaxIScsiAttemptNumber); Index++) {\r
+    if (AttemptList[Index] == 0) {\r
+      continue;\r
+    }\r
+\r
+    //\r
+    // Add the attempt.\r
+    //\r
+    Number = AttemptList[Index];\r
+\r
+    UnicodeSPrint (\r
+      mPrivate->PortString,\r
+      (UINTN) ISCSI_NAME_IFR_MAX_SIZE,\r
+      L"Attempt %d",\r
+      Number\r
+      );\r
+\r
+    GetVariable2 (\r
+           mPrivate->PortString,\r
+           &gEfiIScsiInitiatorNameProtocolGuid,\r
+           (VOID**)&AttemptConfigData,\r
+           NULL\r
+           );\r
+    if (AttemptConfigData == NULL || AttemptConfigData->Actived == ISCSI_ACTIVE_ENABLED) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+\r
+    AttemptConfigData->Actived = ISCSI_ACTIVE_ENABLED;\r
+    AttemptConfigData->NicIndex = NicInfo->NicIndex;\r
+    UnicodeStrToAsciiStrS (MacString, AttemptConfigData->MacString, ISCSI_MAX_MAC_STRING_LEN);\r
+\r
+    //\r
+    // Generate OUI-format ISID based on MAC address.\r
+    //\r
+    CopyMem (AttemptConfigData->SessionConfigData.IsId, &NicInfo->PermanentAddress, 6);\r
+    AttemptConfigData->SessionConfigData.IsId[0] =\r
+      (UINT8) (AttemptConfigData->SessionConfigData.IsId[0] & 0x3F);\r
+\r
+    //\r
+    // Configure the iSCSI Mode and IpMode to default.\r
+    // Add Attempt Help Info.\r
+    //\r
+    UnicodeSPrint (IScsiMode, 64, L"Disabled");\r
+    UnicodeSPrint (IpMode, 64, L"IP4");\r
+    UnicodeSPrint (\r
+      mPrivate->PortString,\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
+      NicInfo->DeviceNumber,\r
+      NicInfo->FunctionNumber,\r
+      IScsiMode,\r
+      IpMode\r
+      );\r
+\r
+    AttemptConfigData->AttemptTitleHelpToken = HiiSetString (\r
+                                                 mCallbackInfo->RegisteredHandle,\r
+                                                 0,\r
+                                                 mPrivate->PortString,\r
+                                                 NULL\r
+                                                 );\r
+    if (AttemptConfigData->AttemptTitleHelpToken == 0) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    //\r
+    // Get current Attempt order and number.\r
+    //\r
+    AttemptConfigOrder = IScsiGetVariableAndSize (\r
+                           L"AttemptOrder",\r
+                           &gIScsiConfigGuid,\r
+                           &AttemptConfigOrderSize\r
+                           );\r
+    TotalNumber = AttemptConfigOrderSize / sizeof (UINT8);\r
+    TotalNumber++;\r
+\r
+    //\r
+    // Append the new created attempt order to the end.\r
+    //\r
+    AttemptConfigOrderTmp = AllocateZeroPool (TotalNumber * sizeof (UINT8));\r
+    if (AttemptConfigOrderTmp == NULL) {\r
+      if (AttemptConfigOrder != NULL) {\r
+        FreePool (AttemptConfigOrder);\r
+      }\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+    if (AttemptConfigOrder != NULL) {\r
+      CopyMem (AttemptConfigOrderTmp, AttemptConfigOrder, AttemptConfigOrderSize);\r
+      FreePool (AttemptConfigOrder);\r
+    }\r
+\r
+    AttemptConfigOrderTmp[TotalNumber - 1] = Number;\r
+    AttemptConfigOrder               = AttemptConfigOrderTmp;\r
+    AttemptConfigOrderSize           = TotalNumber * sizeof (UINT8);\r
 \r
-    AsciiStrToUnicodeStrS (AttemptConfigData->AttemptName, AttemptName, ARRAY_SIZE (AttemptName));\r
-    UnicodeSPrint (mPrivate->PortString, (UINTN) 128, L"Attempt %s", AttemptName);\r
-    AttemptConfigData->AttemptTitleToken = HiiSetString (\r
-                                             mCallbackInfo->RegisteredHandle,\r
-                                             0,\r
-                                             mPrivate->PortString,\r
-                                             NULL\r
-                                             );\r
-    if (AttemptConfigData->AttemptTitleToken == 0) {\r
-      return ;\r
+    Status = gRT->SetVariable (\r
+                    L"AttemptOrder",\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
+      return Status;\r
     }\r
 \r
-    HiiCreateGotoOpCode (\r
-      StartOpCodeHandle,                         // Container for dynamic created opcodes\r
-      FORMID_ATTEMPT_FORM,                       // Form ID\r
-      AttemptConfigData->AttemptTitleToken,      // Prompt text\r
-      AttemptConfigData->AttemptTitleHelpToken,  // Help text\r
-      EFI_IFR_FLAG_CALLBACK,                     // Question flag\r
-      (UINT16) (KEY_ATTEMPT_ENTRY_BASE + AttemptConfigData->AttemptConfigIndex)   // Question ID\r
-      );\r
-  }\r
+    //\r
+    // Record the attempt in global link list.\r
+    //\r
+    InsertTailList (&mPrivate->AttemptConfigs, &AttemptConfigData->Link);\r
+    mPrivate->AttemptCount++;\r
+    UnicodeSPrint (mPrivate->PortString, (UINTN) ISCSI_NAME_IFR_MAX_SIZE, L"Attempt %d", AttemptConfigData->AttemptConfigIndex);\r
+    gRT->SetVariable (\r
+           mPrivate->PortString,\r
+           &gEfiIScsiInitiatorNameProtocolGuid,\r
+           ISCSI_CONFIG_VAR_ATTR,\r
+           sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA),\r
+           AttemptConfigData\r
+           );\r
 \r
-  HiiUpdateForm (\r
-    mCallbackInfo->RegisteredHandle, // HII handle\r
-    &gIScsiConfigGuid,               // Formset GUID\r
-    FORMID_MAIN_FORM,                // Form ID\r
-    StartOpCodeHandle,               // Label for where to insert opcodes\r
-    EndOpCodeHandle                  // Replace data\r
-  );    \r
+  }\r
 \r
-  HiiFreeOpCodeHandle (StartOpCodeHandle);\r
-  HiiFreeOpCodeHandle (EndOpCodeHandle);\r
+  return EFI_SUCCESS;\r
 }\r
 \r
-\r
 /**\r
-  Callback function when user presses "Commit Changes and Exit" in Delete Attempts.\r
+  Callback function when user presses "Commit Changes and Exit" in Delete Attempts or Delete Attempts by Keyword.\r
 \r
   @param[in]  IfrNvData          The IFR NV data.\r
 \r
@@ -1195,19 +2199,22 @@ IScsiConfigDeleteAttempts (
   IN ISCSI_CONFIG_IFR_NVDATA  *IfrNvData\r
   )\r
 {\r
-  EFI_STATUS                  Status;\r
-  UINTN                       Index;\r
-  UINTN                       NewIndex;\r
-  ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;\r
-  UINT8                       *AttemptConfigOrder;\r
-  UINTN                       AttemptConfigOrderSize;\r
-  UINT8                       *AttemptNewOrder;\r
-  UINT32                      Attribute;\r
-  UINTN                       Total;\r
-  UINTN                       NewTotal;\r
-  LIST_ENTRY                  *Entry;\r
-  LIST_ENTRY                  *NextEntry;\r
-  CHAR16                      MacString[ISCSI_MAX_MAC_STRING_LEN];\r
+  EFI_STATUS                    Status;\r
+  UINTN                         Index;\r
+  UINTN                         NewIndex;\r
+  ISCSI_ATTEMPT_CONFIG_NVDATA   *AttemptConfigData;\r
+  UINT8                         *AttemptConfigOrder;\r
+  UINTN                         AttemptConfigOrderSize;\r
+  UINT8                         *AttemptNewOrder;\r
+  UINT8                         AttemptConfigIndex;\r
+  UINT32                        Attribute;\r
+  UINTN                         Total;\r
+  UINTN                         NewTotal;\r
+  LIST_ENTRY                    *Entry;\r
+  LIST_ENTRY                    *NextEntry;\r
+  ISCSI_SESSION_CONFIG_NVDATA   *ConfigData;\r
+\r
+  Index     = 0;\r
 \r
   AttemptConfigOrder = IScsiGetVariableAndSize (\r
                          L"AttemptOrder",\r
@@ -1226,7 +2233,6 @@ IScsiConfigDeleteAttempts (
 \r
   Total    = AttemptConfigOrderSize / sizeof (UINT8);\r
   NewTotal = Total;\r
-  Index    = 0;\r
 \r
   NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &mPrivate->AttemptConfigs) {\r
     if (IfrNvData->DeleteAttemptList[Index] == 0) {\r
@@ -1271,22 +2277,44 @@ IScsiConfigDeleteAttempts (
       mPrivate->SinglePathCount--;\r
     }\r
 \r
-    AsciiStrToUnicodeStrS (AttemptConfigData->MacString, MacString, ARRAY_SIZE (MacString));\r
+    AttemptConfigIndex = AttemptConfigData->AttemptConfigIndex;\r
+    FreePool (AttemptConfigData);\r
+\r
+    //\r
+    // Create a new Attempt\r
+    //\r
+    AttemptConfigData = AllocateZeroPool (sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA));\r
+    if (AttemptConfigData == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\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 = AttemptConfigIndex;\r
 \r
+    //\r
+    // Set the attempt name to default.\r
+    //\r
     UnicodeSPrint (\r
       mPrivate->PortString,\r
-      (UINTN) 128,\r
-      L"%s%d",\r
-      MacString,\r
+      (UINTN) ISCSI_NAME_IFR_MAX_SIZE,\r
+      L"Attempt %d",\r
       (UINTN) AttemptConfigData->AttemptConfigIndex\r
       );\r
-\r
+    UnicodeStrToAsciiStrS (mPrivate->PortString, AttemptConfigData->AttemptName, ATTEMPT_NAME_SIZE);\r
     gRT->SetVariable (\r
            mPrivate->PortString,\r
            &gEfiIScsiInitiatorNameProtocolGuid,\r
-           0,\r
-           0,\r
-           NULL\r
+           ISCSI_CONFIG_VAR_ATTR,\r
+           sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA),\r
+           AttemptConfigData\r
            );\r
 \r
     //\r
@@ -1300,6 +2328,9 @@ IScsiConfigDeleteAttempts (
     }\r
 \r
     NewTotal--;\r
+    if (mCallbackInfo->Current == AttemptConfigData) {\r
+      mCallbackInfo->Current = NULL;\r
+    }\r
     FreePool (AttemptConfigData);\r
 \r
     //\r
@@ -1339,7 +2370,7 @@ Error:
   if (AttemptNewOrder != NULL) {\r
     FreePool (AttemptNewOrder);\r
   }\r
-  \r
+\r
   return Status;\r
 }\r
 \r
@@ -1538,9 +2569,8 @@ Error:
   return Status;\r
 }\r
 \r
-\r
 /**\r
-  Callback function when user presses "Commit Changes and Exit" in Change Attempt Order.\r
+  Callback function when user presses "Commit Changes and Exit" in Change Attempt Order or Change Attempt Order by Keyword.\r
 \r
   @param[in]  IfrNvData          The IFR nv data.\r
 \r
@@ -1656,6 +2686,7 @@ Exit:
   @retval EFI_OUT_OF_RESOURCES   Does not have sufficient resources to finish this\r
                                  operation.\r
   @retval EFI_NOT_FOUND          Cannot find the corresponding variable.\r
+  @retval EFI_UNSUPPORTED        Can not create more attempts.\r
   @retval EFI_SUCCESS            The operation is completed successfully.\r
 \r
 **/\r
@@ -1667,15 +2698,14 @@ IScsiConfigProcessDefault (
 {\r
   BOOLEAN                     NewAttempt;\r
   ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;\r
-  ISCSI_SESSION_CONFIG_NVDATA *ConfigData;\r
   UINT8                       CurrentAttemptConfigIndex;\r
   ISCSI_NIC_INFO              *NicInfo;\r
   UINT8                       NicIndex;\r
   CHAR16                      MacString[ISCSI_MAX_MAC_STRING_LEN];\r
   UINT8                       *AttemptConfigOrder;\r
   UINTN                       AttemptConfigOrderSize;\r
-  UINTN                       TotalNumber;\r
   UINTN                       Index;\r
+  EFI_INPUT_KEY               Key;\r
 \r
   //\r
   // Is User creating a new attempt?\r
@@ -1701,14 +2731,6 @@ IScsiConfigProcessDefault (
     //\r
     return EFI_SUCCESS;\r
   }\r
-  \r
-  //\r
-  // Free any attempt that is previously created but not saved to system.\r
-  //\r
-  if (mPrivate->NewAttempt != NULL) {\r
-    FreePool (mPrivate->NewAttempt);\r
-    mPrivate->NewAttempt = NULL;\r
-  }\r
 \r
   if (NewAttempt) {\r
     //\r
@@ -1719,58 +2741,49 @@ IScsiConfigProcessDefault (
     if (NicInfo == NULL) {\r
       return EFI_NOT_FOUND;\r
     }\r
-    \r
-    //\r
-    // Create new attempt.\r
-    //\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
     //\r
-    // Get current order number for this attempt.\r
+    // Create an attempt following the initialized attempt order.\r
     //\r
     AttemptConfigOrder = IScsiGetVariableAndSize (\r
-                           L"AttemptOrder",\r
+                           L"InitialAttemptOrder",\r
                            &gIScsiConfigGuid,\r
                            &AttemptConfigOrderSize\r
                            );\r
 \r
-    TotalNumber = AttemptConfigOrderSize / sizeof (UINT8);\r
+    if (AttemptConfigOrder != NULL) {\r
 \r
-    if (AttemptConfigOrder == NULL) {\r
-      CurrentAttemptConfigIndex = 1;\r
-    } else {\r
-      //\r
-      // Get the max attempt config index.\r
-      //\r
-      CurrentAttemptConfigIndex = AttemptConfigOrder[0];\r
-      for (Index = 1; Index < TotalNumber; Index++) {\r
-        if (CurrentAttemptConfigIndex < AttemptConfigOrder[Index]) {\r
-          CurrentAttemptConfigIndex = AttemptConfigOrder[Index];\r
+      for (Index = 0; Index < AttemptConfigOrderSize / sizeof (UINT8); Index++) {\r
+        UnicodeSPrint (\r
+          mPrivate->PortString,\r
+          (UINTN) ISCSI_NAME_IFR_MAX_SIZE,\r
+          L"Attempt %d",\r
+          (UINTN) AttemptConfigOrder[Index]\r
+          );\r
+        GetVariable2 (\r
+                     mPrivate->PortString,\r
+                     &gEfiIScsiInitiatorNameProtocolGuid,\r
+                     (VOID**)&AttemptConfigData,\r
+                     NULL\r
+                     );\r
+        if (AttemptConfigData == NULL || AttemptConfigData->Actived == ISCSI_ACTIVE_ENABLED) {\r
+          continue;\r
         }\r
+\r
+        break;\r
       }\r
 \r
-      CurrentAttemptConfigIndex++;\r
+      if (Index > PcdGet8 (PcdMaxIScsiAttemptNumber)) {\r
+        CreatePopUp (\r
+          EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+          &Key,\r
+          L"Can not create more attempts, Please configure the PcdMaxIScsiAttemptNumber if needed!",\r
+          NULL\r
+          );\r
+        return EFI_UNSUPPORTED;\r
+      }\r
     }\r
 \r
-    TotalNumber++;\r
-\r
-    //\r
-    // Record the mapping between attempt order and attempt's configdata.\r
-    //\r
-    AttemptConfigData->AttemptConfigIndex  = CurrentAttemptConfigIndex;\r
-\r
     if (AttemptConfigOrder != NULL) {\r
       FreePool (AttemptConfigOrder);\r
     }\r
@@ -1787,6 +2800,7 @@ IScsiConfigProcessDefault (
 \r
     UnicodeStrToAsciiStrS (MacString, AttemptConfigData->MacString, sizeof (AttemptConfigData->MacString));\r
     AttemptConfigData->NicIndex = NicIndex;\r
+    AttemptConfigData->Actived = ISCSI_ACTIVE_ENABLED;\r
 \r
     //\r
     // Generate OUI-format ISID based on MAC address.\r
@@ -1816,27 +2830,9 @@ IScsiConfigProcessDefault (
                                                   );\r
     if (AttemptConfigData->AttemptTitleHelpToken == 0) {\r
       FreePool (AttemptConfigData);\r
-      return EFI_INVALID_PARAMETER;\r
+      return EFI_OUT_OF_RESOURCES;\r
     }\r
 \r
-    //\r
-    // Set the attempt name to default.\r
-    //\r
-    UnicodeSPrint (\r
-      mPrivate->PortString,\r
-      (UINTN) 128,\r
-      L"%d",\r
-      (UINTN) AttemptConfigData->AttemptConfigIndex\r
-      );\r
-    UnicodeStrToAsciiStrS (mPrivate->PortString, AttemptConfigData->AttemptName, sizeof (AttemptConfigData->AttemptName));\r
-\r
-    //\r
-    // Save the created Attempt temporarily. If user does not save the attempt\r
-    // by press 'KEY_SAVE_ATTEMPT_CONFIG' later, iSCSI driver would know that\r
-    // and free resources.\r
-    //\r
-    mPrivate->NewAttempt = (VOID *) AttemptConfigData;\r
-\r
   } else {\r
     //\r
     // Determine which Attempt user has selected to configure.\r
@@ -1981,11 +2977,17 @@ IScsiFormExtractConfig (
   if (IfrNvData == NULL) {\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
-  \r
-  if (Private->Current != NULL) {\r
+\r
+\r
+  if (Private->Current!= NULL) {\r
     IScsiConvertAttemptConfigDataToIfrNvData (Private->Current, IfrNvData);\r
   }\r
 \r
+  //\r
+  // Extract all AttemptConfigData to Keyword stroage of IfrNvData.\r
+  //\r
+  IScsiConvertAttemptConfigDataToIfrNvDataByKeyword (IfrNvData);\r
+\r
   BufferSize    = ISCSI_NAME_MAX_SIZE;\r
   InitiatorName = (CHAR8 *) AllocateZeroPool (BufferSize);\r
   if (InitiatorName == NULL) {\r
@@ -2107,6 +3109,26 @@ IScsiFormRouteConfig (
   OUT EFI_STRING                             *Progress\r
   )\r
 {\r
+  EFI_STATUS                       Status;\r
+  ISCSI_CONFIG_IFR_NVDATA          *IfrNvData;\r
+  ISCSI_ATTEMPT_CONFIG_NVDATA      *AttemptConfigData;\r
+  LIST_ENTRY                       *Entry;\r
+  LIST_ENTRY                       *NextEntry;\r
+  ISCSI_NIC_INFO                   *NicInfo;\r
+  EFI_INPUT_KEY                    Key;\r
+  CHAR16                           MacString[ISCSI_MAX_MAC_STRING_LEN];\r
+  CHAR8                            *InitiatorName;\r
+  UINT8                            *AttemptList;\r
+  UINTN                            BufferSize;\r
+  UINTN                            OffSet;\r
+  UINTN                            Index;\r
+  UINTN                            Index2;\r
+\r
+  Index   = 0;\r
+  Index2  = 0;\r
+  NicInfo = NULL;\r
+  AttemptList = NULL;\r
+\r
   if (This == NULL || Configuration == NULL || Progress == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
@@ -2120,10 +3142,180 @@ IScsiFormRouteConfig (
     return EFI_NOT_FOUND;\r
   }\r
 \r
-  *Progress = Configuration + StrLen (Configuration);\r
-  return EFI_SUCCESS;\r
-}\r
+  IfrNvData = AllocateZeroPool (sizeof (ISCSI_CONFIG_IFR_NVDATA));\r
+  if (IfrNvData == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  BufferSize    = ISCSI_NAME_MAX_SIZE;\r
+  InitiatorName = (CHAR8 *) AllocateZeroPool (BufferSize);\r
+  if (InitiatorName == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Exit;\r
+  }\r
+\r
+  //\r
+  // Convert <ConfigResp> to buffer data by helper function ConfigToBlock().\r
+  //\r
+  BufferSize = sizeof (ISCSI_CONFIG_IFR_NVDATA);\r
+  Status = gHiiConfigRouting->ConfigToBlock (\r
+                             gHiiConfigRouting,\r
+                             Configuration,\r
+                             (UINT8 *) IfrNvData,\r
+                             &BufferSize,\r
+                             Progress\r
+                             );\r
+  if (EFI_ERROR (Status)) {\r
+    goto Exit;\r
+  }\r
+\r
+  if (IfrNvData->InitiatorName[0] != L'\0') {\r
+    UnicodeStrToAsciiStrS (IfrNvData->InitiatorName, InitiatorName, ISCSI_NAME_MAX_SIZE);\r
+    BufferSize  = AsciiStrSize (InitiatorName);\r
+\r
+    Status      = gIScsiInitiatorName.Set (&gIScsiInitiatorName, &BufferSize, InitiatorName);\r
+    if (EFI_ERROR (Status)) {\r
+      CreatePopUp (\r
+        EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+        &Key,\r
+        L"Invalid iSCSI Name!",\r
+        NULL\r
+        );\r
+      goto Exit;\r
+    }\r
+  } else {\r
+    Status = gIScsiInitiatorName.Get (&gIScsiInitiatorName, &BufferSize, InitiatorName);\r
+    if (EFI_ERROR (Status)) {\r
+      CreatePopUp (\r
+        EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+        &Key,\r
+        L"Error: please configure iSCSI initiator name first!",\r
+        NULL\r
+        );\r
+      goto Exit;\r
+    }\r
+\r
+    if (IfrNvData->ISCSIAddAttemptList[0] != L'\0') {\r
+      Status =IScsiGetAttemptIndexList (IfrNvData->ISCSIAddAttemptList, IfrNvData->AddAttemptList, TRUE);\r
+      if (EFI_ERROR (Status)) {\r
+          CreatePopUp (\r
+            EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+            &Key,\r
+            L"Error: The add attempt list is invalid",\r
+            NULL\r
+            );\r
+        goto Exit;\r
+      }\r
+\r
+      Status = IScsiConfigAddAttemptsByKeywords (IfrNvData->AddAttemptList);\r
+      if (EFI_ERROR (Status)) {\r
+        goto Exit;\r
+      }\r
+\r
+    } else if (IfrNvData->ISCSIDeleteAttemptList[0] != L'\0') {\r
+      AttemptList =(UINT8 *) AllocateZeroPool ((ISCSI_MAX_ATTEMPTS_NUM + 1) * sizeof (UINT8));\r
+      if (AttemptList == NULL) {\r
+        Status = EFI_OUT_OF_RESOURCES;\r
+        goto Exit;\r
+      }\r
+      Status = IScsiGetAttemptIndexList (IfrNvData->ISCSIDeleteAttemptList, AttemptList, FALSE);\r
+      if (EFI_ERROR (Status)) {\r
+          CreatePopUp (\r
+            EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+            &Key,\r
+            L"Error: The delete attempt list is invalid",\r
+            NULL\r
+            );\r
+        goto Exit;\r
+      }\r
+\r
+      //\r
+      // Mark the attempt which will be delete in the global list.\r
+      //\r
+      NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &mPrivate->AttemptConfigs) {\r
+        AttemptConfigData = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);\r
+        while (AttemptList[Index] != 0) {\r
+          if (AttemptConfigData->AttemptConfigIndex == AttemptList[Index]) {\r
+            IfrNvData->DeleteAttemptList[Index2] = 1;\r
+            break;\r
+          }\r
+          Index ++;\r
+        }\r
+        Index2 ++;\r
+        Index = 0;\r
+      }\r
+\r
+      Status = IScsiConfigDeleteAttempts (IfrNvData);\r
+      if (EFI_ERROR (Status)) {\r
+        goto Exit;\r
+      }\r
+\r
+      FreePool (AttemptList);\r
+\r
+    } else if (IfrNvData->ISCSIAttemptOrder[0] != L'\0') {\r
+      Status = IScsiGetAttemptIndexList (IfrNvData->ISCSIAttemptOrder, IfrNvData->DynamicOrderedList, FALSE);\r
+      if (EFI_ERROR (Status)) {\r
+          CreatePopUp (\r
+            EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+            &Key,\r
+            L"Error: The new attempt order list is invalid",\r
+            NULL\r
+            );\r
+        goto Exit;\r
+      }\r
+\r
+      Status = IScsiConfigOrderAttempts (IfrNvData);\r
+      if (EFI_ERROR (Status)) {\r
+        goto Exit;\r
+      }\r
+\r
+    } else if (IfrNvData->ISCSIMacAddr[0] != L'\0') {\r
+      NET_LIST_FOR_EACH (Entry, &mPrivate->NicInfoList) {\r
+        NicInfo = NET_LIST_USER_STRUCT (Entry, ISCSI_NIC_INFO, Link);\r
+        IScsiMacAddrToStr (\r
+        &NicInfo->PermanentAddress,\r
+        NicInfo->HwAddressSize,\r
+        NicInfo->VlanId,\r
+        MacString\r
+        );\r
+        if (!StrCmp(MacString, IfrNvData->ISCSIMacAddr)) {\r
+          mPrivate->CurrentNic = NicInfo->NicIndex;\r
+          break;\r
+        }\r
+      }\r
+\r
+      if ((NicInfo == NULL) || (NicInfo->NicIndex == 0)) {\r
+        Status = EFI_NOT_FOUND;\r
+        goto Exit;\r
+      }\r
+\r
+    } else {\r
+      Status = IScsiGetValue (Configuration, L"&OFFSET=", &OffSet);\r
+      if (EFI_ERROR (Status)) {\r
+        goto Exit;\r
+      }\r
+      Status = IScsiConvertlfrNvDataToAttemptConfigDataByKeyword (IfrNvData, OffSet);\r
+      if (EFI_ERROR (Status)) {\r
+        goto Exit;\r
+      }\r
+    }\r
+  }\r
+\r
+  IScsiConfigUpdateAttempt ();\r
+\r
+  Status = EFI_SUCCESS;\r
+\r
+Exit:\r
+  if (InitiatorName != NULL) {\r
+    FreePool (InitiatorName);\r
+  }\r
 \r
+  if (IfrNvData != NULL) {\r
+    FreePool (IfrNvData);\r
+  }\r
+\r
+  return Status;\r
+}\r
 \r
 /**\r
    \r
@@ -2173,7 +3365,6 @@ IScsiFormCallback (
   ISCSI_CONFIG_IFR_NVDATA     *IfrNvData;\r
   ISCSI_CONFIG_IFR_NVDATA     OldIfrNvData;\r
   EFI_STATUS                  Status;\r
-  CHAR16                      AttemptName[ATTEMPT_NAME_SIZE + 4];\r
   EFI_INPUT_KEY               Key;\r
 \r
   if ((Action == EFI_BROWSER_ACTION_FORM_OPEN) || (Action == EFI_BROWSER_ACTION_FORM_CLOSE)) {\r
@@ -2286,24 +3477,6 @@ IScsiFormCallback (
           );      \r
       }\r
 \r
-      *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;\r
-      break;\r
-    case KEY_ATTEMPT_NAME:\r
-      if (StrLen (IfrNvData->AttemptName) > ATTEMPT_NAME_SIZE) {\r
-        CopyMem (AttemptName, IfrNvData->AttemptName, ATTEMPT_NAME_SIZE * sizeof (CHAR16));\r
-        CopyMem (&AttemptName[ATTEMPT_NAME_SIZE], L"...", 4 * sizeof (CHAR16));\r
-      } else {\r
-        CopyMem (\r
-          AttemptName,\r
-          IfrNvData->AttemptName,\r
-          (StrLen (IfrNvData->AttemptName) + 1) * sizeof (CHAR16)\r
-          );\r
-      }\r
-\r
-      UnicodeStrToAsciiStrS (IfrNvData->AttemptName, Private->Current->AttemptName, sizeof (Private->Current->AttemptName));\r
-\r
-      IScsiConfigUpdateAttempt ();\r
-\r
       *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;\r
       break;\r
       \r
@@ -2313,7 +3486,7 @@ IScsiFormCallback (
         break;\r
       }\r
 \r
-      *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;\r
+      *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT;\r
       break;\r
 \r
     case KEY_SAVE_ORDER_CHANGES:\r
@@ -2662,13 +3835,6 @@ IScsiConfigFormUnload (
 \r
   ASSERT (mPrivate->NicCount == 0);\r
 \r
-  //\r
-  // Free attempt is created but not saved to system.\r
-  //\r
-  if (mPrivate->NewAttempt != NULL) {\r
-    FreePool (mPrivate->NewAttempt);\r
-  }\r
-\r
   FreePool (mPrivate);\r
   mPrivate = NULL;\r
 \r
index daa0d343828a07cbc1ed55509c27410c4e7c8167..21db3c329a422cd68068406a8d52a9c40ee0fe48 100644 (file)
@@ -2,7 +2,7 @@
   The header file of functions for configuring or getting the parameters\r
   relating to iSCSI.\r
 \r
-Copyright (c) 2004 - 2015, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2004 - 2017, 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
@@ -37,11 +37,55 @@ extern ISCSI_FORM_CALLBACK_INFO    *mCallbackInfo;
 #define DYNAMIC_ORDERED_LIST_VAR_OFFSET     VAR_OFFSET  (DynamicOrderedList)\r
 #define ATTEMPT_DEL_QUESTION_ID             QUESTION_ID (DeleteAttemptList)\r
 #define ATTEMPT_DEL_VAR_OFFSET              VAR_OFFSET  (DeleteAttemptList)\r
+#define ATTEMPT_ADD_QUESTION_ID             QUESTION_ID (AddAttemptList)\r
+#define ATTEMPT_ADD_VAR_OFFSET              VAR_OFFSET  (AddAttemptList)\r
 \r
 //\r
-// sizeof (EFI_MAC_ADDRESS) * 3\r
+// Define QuestionId and OffSet for Keywords.\r
 //\r
-#define ISCSI_MAX_MAC_STRING_LEN            96\r
+#define ATTEMPT_ATTEMPT_NAME_QUESTION_ID             QUESTION_ID (ISCSIAttemptName)\r
+#define ATTEMPT_ATTEMPT_NAME_VAR_OFFSET              VAR_OFFSET  (ISCSIAttemptName)\r
+#define ATTEMPT_BOOTENABLE_QUESTION_ID               QUESTION_ID (ISCSIBootEnableList)\r
+#define ATTEMPT_BOOTENABLE_VAR_OFFSET                VAR_OFFSET  (ISCSIBootEnableList)\r
+#define ATTEMPT_ADDRESS_TYPE_QUESTION_ID             QUESTION_ID (ISCSIIpAddressTypeList)\r
+#define ATTEMPT_ADDRESS_TYPE_VAR_OFFSET              VAR_OFFSET  (ISCSIIpAddressTypeList)\r
+#define ATTEMPT_CONNECT_RETRY_QUESTION_ID            QUESTION_ID (ISCSIConnectRetry)\r
+#define ATTEMPT_CONNECT_RETRY_VAR_OFFSET             VAR_OFFSET  (ISCSIConnectRetry)\r
+#define ATTEMPT_CONNECT_TIMEOUT_QUESTION_ID          QUESTION_ID (ISCSIConnectTimeout)\r
+#define ATTEMPT_CONNECT_TIMEOUT_VAR_OFFSET           VAR_OFFSET  (ISCSIConnectTimeout)\r
+#define ATTEMPT_ISID_QUESTION_ID                     QUESTION_ID (Keyword->ISCSIIsId)\r
+#define ATTEMPT_ISID_VAR_OFFSET                      VAR_OFFSET  (Keyword->ISCSIIsId)\r
+#define ATTEMPT_INITIATOR_VIA_DHCP_QUESTION_ID       QUESTION_ID (ISCSIInitiatorInfoViaDHCP)\r
+#define ATTEMPT_INITIATOR_VIA_DHCP_VAR_OFFSET        VAR_OFFSET  (ISCSIInitiatorInfoViaDHCP)\r
+#define ATTEMPT_INITIATOR_IP_ADDRESS_QUESTION_ID     QUESTION_ID (Keyword->ISCSIInitiatorIpAddress)\r
+#define ATTEMPT_INITIATOR_IP_ADDRESS_VAR_OFFSET      VAR_OFFSET  (Keyword->ISCSIInitiatorIpAddress)\r
+#define ATTEMPT_INITIATOR_NET_MASK_QUESTION_ID       QUESTION_ID (Keyword->ISCSIInitiatorNetmask)\r
+#define ATTEMPT_INITIATOR_NET_MASK_VAR_OFFSET        VAR_OFFSET  (Keyword->ISCSIInitiatorNetmask)\r
+#define ATTEMPT_INITIATOR_GATE_WAY_QUESTION_ID       QUESTION_ID (Keyword->ISCSIInitiatorGateway)\r
+#define ATTEMPT_INITIATOR_GATE_WAY_VAR_OFFSET        VAR_OFFSET  (Keyword->ISCSIInitiatorGateway)\r
+#define ATTEMPT_TARGET_VIA_DHCP_QUESTION_ID          QUESTION_ID (ISCSITargetInfoViaDHCP)\r
+#define ATTEMPT_TARGET_VIA_DHCP_VAR_OFFSET           VAR_OFFSET  (ISCSITargetInfoViaDHCP)\r
+#define ATTEMPT_TARGET_NAME_QUESTION_ID              QUESTION_ID (Keyword->ISCSITargetName)\r
+#define ATTEMPT_TARGET_NAME_VAR_OFFSET               VAR_OFFSET  (Keyword->ISCSITargetName)\r
+#define ATTEMPT_TARGET_IP_ADDRESS_QUESTION_ID        QUESTION_ID (Keyword->ISCSITargetIpAddress)\r
+#define ATTEMPT_TARGET_IP_ADDRESS_VAR_OFFSET         VAR_OFFSET  (Keyword->ISCSITargetIpAddress)\r
+#define ATTEMPT_TARGET_TCP_PORT_QUESTION_ID          QUESTION_ID (ISCSITargetTcpPort)\r
+#define ATTEMPT_TARGET_TCP_PORT_VAR_OFFSET           VAR_OFFSET  (ISCSITargetTcpPort)\r
+#define ATTEMPT_LUN_QUESTION_ID                      QUESTION_ID (Keyword->ISCSILun)\r
+#define ATTEMPT_LUN_VAR_OFFSET                       VAR_OFFSET  (Keyword->ISCSILun)\r
+#define ATTEMPT_AUTHENTICATION_METHOD_QUESTION_ID    QUESTION_ID (ISCSIAuthenticationMethod)\r
+#define ATTEMPT_AUTHENTICATION_METHOD_VAR_OFFSET     VAR_OFFSET  (ISCSIAuthenticationMethod)\r
+#define ATTEMPT_CHARTYPE_QUESTION_ID                 QUESTION_ID (ISCSIChapType)\r
+#define ATTEMPT_CHARTYPE_VAR_OFFSET                  VAR_OFFSET  (ISCSIChapType)\r
+#define ATTEMPT_CHAR_USER_NAME_QUESTION_ID           QUESTION_ID (Keyword->ISCSIChapUsername)\r
+#define ATTEMPT_CHAR_USER_NAME_VAR_OFFSET            VAR_OFFSET  (Keyword->ISCSIChapUsername)\r
+#define ATTEMPT_CHAR_SECRET_QUESTION_ID              QUESTION_ID (Keyword->ISCSIChapSecret)\r
+#define ATTEMPT_CHAR_SECRET_VAR_OFFSET               VAR_OFFSET  (Keyword->ISCSIChapSecret)\r
+#define ATTEMPT_CHAR_REVERSE_USER_NAME_QUESTION_ID   QUESTION_ID (Keyword->ISCSIReverseChapUsername)\r
+#define ATTEMPT_CHAR_REVERSE_USER_NAME_VAR_OFFSET    VAR_OFFSET  (Keyword->ISCSIReverseChapUsername)\r
+#define ATTEMPT_CHAR_REVERSE_SECRET_QUESTION_ID      QUESTION_ID (Keyword->ISCSIReverseChapSecret)\r
+#define ATTEMPT_CHAR_REVERSE_SECRET_VAR_OFFSET       VAR_OFFSET  (Keyword->ISCSIReverseChapSecret)\r
+\r
 \r
 #define ISCSI_INITATOR_NAME_VAR_NAME        L"I_NAME"\r
 \r
@@ -68,7 +112,7 @@ struct _ISCSI_ATTEMPT_CONFIG_NVDATA {
   UINT8                            AutoConfigureMode;\r
   EFI_STRING_ID                    AttemptTitleToken;\r
   EFI_STRING_ID                    AttemptTitleHelpToken;\r
-  CHAR8                            AttemptName[ATTEMPT_NAME_MAX_SIZE];\r
+  CHAR8                            AttemptName[ATTEMPT_NAME_SIZE];\r
   CHAR8                            MacString[ISCSI_MAX_MAC_STRING_LEN];\r
   EFI_IP_ADDRESS                   PrimaryDns;\r
   EFI_IP_ADDRESS                   SecondaryDns;\r
@@ -79,6 +123,7 @@ struct _ISCSI_ATTEMPT_CONFIG_NVDATA {
     ISCSI_CHAP_AUTH_CONFIG_NVDATA  CHAP;\r
   } AuthConfigData;\r
   BOOLEAN                          AutoConfigureSuccess;\r
+  UINT8                            Actived;\r
 };\r
 \r
 ///\r
@@ -101,6 +146,31 @@ struct _ISCSI_FORM_CALLBACK_INFO {
   ISCSI_ATTEMPT_CONFIG_NVDATA      *Current;\r
 };\r
 \r
+/**\r
+  Create Hii Extend Label OpCode as the start opcode and end opcode. It is\r
+  a help function.\r
+\r
+  @param[in]  StartLabelNumber   The number of start label.\r
+  @param[out] StartOpCodeHandle  Points to the start opcode handle.\r
+  @param[out] StartLabel         Points to the created start opcode.\r
+  @param[out] EndOpCodeHandle    Points to the end opcode handle.\r
+  @param[out] EndLabel           Points to the created end opcode.\r
+\r
+  @retval EFI_OUT_OF_RESOURCES   Do not have sufficient resource to finish this\r
+                                 operation.\r
+  @retval EFI_INVALID_PARAMETER  Any input parameter is invalid.\r
+  @retval EFI_SUCCESS            The operation is completed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+IScsiCreateOpCode (\r
+  IN  UINT16                        StartLabelNumber,\r
+  OUT VOID                          **StartOpCodeHandle,\r
+  OUT EFI_IFR_GUID_LABEL            **StartLabel,\r
+  OUT VOID                          **EndOpCodeHandle,\r
+  OUT EFI_IFR_GUID_LABEL            **EndLabel\r
+  );\r
+\r
 /**\r
   Initialize the iSCSI configuration form.\r
 \r
index 5f22767644edf8276d78f9ccaf3d2cbb5451a62e..f89f3208547dbf4b8586f5bcec6593b6aae59108 100644 (file)
@@ -26,12 +26,14 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #define FORMID_ORDER_FORM         4\r
 #define FORMID_DELETE_FORM        5\r
 \r
+#define ISCSI_MAX_ATTEMPTS_NUM    FixedPcdGet8 (PcdMaxIScsiAttemptNumber)\r
+\r
 #define ISCSI_NAME_IFR_MIN_SIZE   4\r
 #define ISCSI_NAME_IFR_MAX_SIZE   223\r
 #define ISCSI_NAME_MAX_SIZE       224\r
 \r
-#define ATTEMPT_NAME_MAX_SIZE     96\r
-#define ATTEMPT_NAME_SIZE         10\r
+#define ATTEMPT_NAME_LIST_SIZE    96\r
+#define ATTEMPT_NAME_SIZE         12\r
 \r
 #define CONNECT_MIN_RETRY         0\r
 #define CONNECT_MAX_RETRY         16\r
@@ -40,7 +42,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #define CONNECT_MAX_TIMEOUT       20000\r
 #define CONNECT_DEFAULT_TIMEOUT   1000\r
 \r
-#define ISCSI_MAX_ATTEMPTS_NUM    255\r
+#define ISCSI_ACTIVE_DISABLED     0\r
+#define ISCSI_ACTIVE_ENABLED      1\r
 \r
 #define ISCSI_DISABLED            0\r
 #define ISCSI_ENABLED             1\r
@@ -67,6 +70,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 \r
 #define LUN_MIN_SIZE              1\r
 #define LUN_MAX_SIZE              20\r
+#define ISCSI_LUN_STR_MAX_LEN     21\r
 \r
 #define ISCSI_CHAP_UNI            0\r
 #define ISCSI_CHAP_MUTUAL         1\r
@@ -112,17 +116,18 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #define MAC_ENTRY_LABEL           0x3000\r
 #define ORDER_ENTRY_LABEL         0x4000\r
 #define DELETE_ENTRY_LABEL        0x5000\r
+#define KEYWORD_ENTRY_LABEL       0x6000\r
 #define CONFIG_OPTION_OFFSET      0x9000\r
 \r
-#define ISCSI_LUN_STR_MAX_LEN     21\r
 #define ISCSI_CHAP_SECRET_MIN_LEN 12\r
 #define ISCSI_CHAP_SECRET_MAX_LEN 16\r
 //\r
 // ISCSI_CHAP_SECRET_STORAGE = ISCSI_CHAP_SECRET_MAX_LEN + sizeof (NULL-Terminator)\r
 //\r
-#define ISCSI_CHAP_SECRET_STORAGE 17\r
-#define ISCSI_CHAP_NAME_MAX_LEN   126\r
-#define ISCSI_CHAP_NAME_STORAGE   127\r
+#define ISCSI_CHAP_SECRET_STORAGE  17\r
+\r
+#define ISCSI_CHAP_NAME_MAX_LEN    126\r
+#define ISCSI_CHAP_NAME_STORAGE    127\r
 \r
 #define KERBEROS_SECRET_MIN_LEN   12\r
 #define KERBEROS_SECRET_MAX_LEN   16\r
@@ -135,6 +140,11 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #define ISID_CONFIGURABLE_MAX_LEN 12\r
 #define ISID_CONFIGURABLE_STORAGE 13\r
 \r
+//\r
+// sizeof (EFI_MAC_ADDRESS) * 3\r
+//\r
+#define ISCSI_MAX_MAC_STRING_LEN            96\r
+\r
 ///\r
 /// Macro used for target Url.\r
 ///\r
@@ -142,10 +152,27 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #define ISCSI_TARGET_URI_MAX_SIZE     255\r
 \r
 #pragma pack(1)\r
+\r
+//\r
+// Used by keyword.\r
+//\r
+typedef struct {\r
+  CHAR16  ISCSIIsId[ISID_CONFIGURABLE_STORAGE];\r
+  CHAR16  ISCSIInitiatorIpAddress[IP4_STR_MAX_SIZE];\r
+  CHAR16  ISCSIInitiatorNetmask[IP4_STR_MAX_SIZE];\r
+  CHAR16  ISCSIInitiatorGateway[IP4_STR_MAX_SIZE];\r
+  CHAR16  ISCSITargetName[ISCSI_NAME_MAX_SIZE];\r
+  CHAR16  ISCSITargetIpAddress[IP_STR_MAX_SIZE];\r
+  CHAR16  ISCSILun[ISCSI_LUN_STR_MAX_LEN];\r
+  CHAR16  ISCSIChapUsername[ISCSI_CHAP_NAME_STORAGE];\r
+  CHAR16  ISCSIChapSecret[ISCSI_CHAP_SECRET_STORAGE];\r
+  CHAR16  ISCSIReverseChapUsername[ISCSI_CHAP_NAME_STORAGE];\r
+  CHAR16  ISCSIReverseChapSecret[ISCSI_CHAP_SECRET_STORAGE];\r
+} KEYWORD_STR;\r
+\r
 typedef struct _ISCSI_CONFIG_IFR_NVDATA {\r
   CHAR16  InitiatorName[ISCSI_NAME_MAX_SIZE];\r
-  CHAR16  AttemptName[ATTEMPT_NAME_MAX_SIZE];\r
-\r
+  CHAR16  AttemptName[ATTEMPT_NAME_SIZE];\r
   UINT8   Enabled;\r
   UINT8   IpMode;\r
 \r
@@ -183,8 +210,28 @@ typedef struct _ISCSI_CONFIG_IFR_NVDATA {
 \r
   UINT8   DynamicOrderedList[ISCSI_MAX_ATTEMPTS_NUM];\r
   UINT8   DeleteAttemptList[ISCSI_MAX_ATTEMPTS_NUM];\r
-\r
+  UINT8   AddAttemptList[ISCSI_MAX_ATTEMPTS_NUM];\r
   CHAR16  IsId[ISID_CONFIGURABLE_STORAGE];\r
+\r
+  //\r
+  // This will be used by keywords.\r
+  //\r
+  CHAR16  ISCSIMacAddr[ISCSI_MAX_MAC_STRING_LEN];\r
+  CHAR16  ISCSIAttemptOrder[ATTEMPT_NAME_LIST_SIZE];\r
+  CHAR16  ISCSIAddAttemptList[ATTEMPT_NAME_LIST_SIZE];\r
+  CHAR16  ISCSIDeleteAttemptList[ATTEMPT_NAME_LIST_SIZE];\r
+  CHAR16  ISCSIDisplayAttemptList[ATTEMPT_NAME_LIST_SIZE];\r
+  CHAR16  ISCSIAttemptName[ATTEMPT_NAME_LIST_SIZE];\r
+  UINT8   ISCSIBootEnableList[ISCSI_MAX_ATTEMPTS_NUM];\r
+  UINT8   ISCSIIpAddressTypeList[ISCSI_MAX_ATTEMPTS_NUM];\r
+  UINT8   ISCSIConnectRetry[ISCSI_MAX_ATTEMPTS_NUM];\r
+  UINT16  ISCSIConnectTimeout[ISCSI_MAX_ATTEMPTS_NUM];\r
+  UINT8   ISCSIInitiatorInfoViaDHCP[ISCSI_MAX_ATTEMPTS_NUM];\r
+  UINT8   ISCSITargetInfoViaDHCP[ISCSI_MAX_ATTEMPTS_NUM];\r
+  UINT16  ISCSITargetTcpPort[ISCSI_MAX_ATTEMPTS_NUM];\r
+  UINT8   ISCSIAuthenticationMethod[ISCSI_MAX_ATTEMPTS_NUM];\r
+  UINT8   ISCSIChapType[ISCSI_MAX_ATTEMPTS_NUM];\r
+  KEYWORD_STR Keyword[ISCSI_MAX_ATTEMPTS_NUM];\r
 } ISCSI_CONFIG_IFR_NVDATA;\r
 #pragma pack()\r
 \r
index 11e8b09f99d68c3f5b1e94209a5e12a7611cd711..79522583de3687f8343f09c1250e15af960ca958 100644 (file)
 // Module Name:\r
 //\r
 //   IScsiConfigStrings.uni\r
-// \r
+//\r
 // Abstract:\r
-// \r
+//\r
 //   String definitions for iSCSI configuration.\r
-// \r
+//\r
 // Revision History:\r
-// \r
+//\r
 // --*/\r
 \r
 /=#\r
 \r
 #langdef en-US "English"\r
+#langdef x-UEFI-ns "UefiNameSpace"\r
 \r
 #string STR_ISCSI_CONFIG_FORM_TITLE     #language en-US "iSCSI Configuration"  \r
 #string STR_ISCSI_CONFIG_FORM_HELP      #language en-US "Configure the iSCSI parameters."   \r
 #string STR_ISCSI_MAIN_FORM_TITLE       #language en-US "iSCSI Configuration"\r
 #string STR_ISCSI_MAC_FORM_TITLE        #language en-US "MAC Selection"\r
 #string STR_ISCSI_CONFIG_INIT_NAME      #language en-US "iSCSI Initiator Name"\r
+                                        #language x-UEFI-ns "iSCSIInitiatorName"\r
 #string STR_ISCSI_CONFIG_INIT_NAME_HELP #language en-US "The worldwide unique name of iSCSI Initiator. Only IQN format is accepted."\r
 #string STR_ISCSI_ATTEMPT_NAME          #language en-US "iSCSI Attempt Name"\r
 #string STR_ISCSI_ATTEMPT_NAME_HELP     #language en-US "The human name defined for this attempt."\r
@@ -68,7 +70,7 @@
 #string STR_ISCSI_TARGET_PORT           #language en-US "  Target Port"\r
 #string STR_ISCSI_BOOT_LUN              #language en-US "  Boot LUN"\r
 #string STR_ISCSI_BOOT_LUN_HELP         #language en-US "Hexadecimal representation of the LU number. Examples are: 4752-3A4F-6b7e-2F99, 6734-9-156f-127, 4186-9"\r
-#string STR_ISCSI_ENABLE_DHCP           #language en-US "Enable DHCP"         \r
+#string STR_ISCSI_ENABLE_DHCP           #language en-US "Enable DHCP"\r
 #string STR_ISCSI_ENABLE_DHCP_ON_TARGET #language en-US "Get target info via DHCP"\r
 #string STR_CHAP_TYPE_PROMPT            #language en-US "  CHAP Type"\r
 #string STR_CHAP_TYPE_HELP              #language en-US "None, One way CHAP or mutual CHAP"\r
 #string STR_SAVE_CHANGES                #language en-US "Save Changes"\r
 #string STR_SAVE_CHANGES_HELP           #language en-US "Must reboot system manually for changes to take place."\r
 #string STR_NULL                        #language en-US ""\r
-#string STR_SAVE_AND_EXIT               #language en-US "Commit Changes and Exit"                                      \r
-#string STR_NO_SAVE_AND_EXIT            #language en-US "Discard Changes and Exit"                                       \r
+#string STR_SAVE_AND_EXIT               #language en-US "Commit Changes and Exit"\r
+#string STR_NO_SAVE_AND_EXIT            #language en-US "Discard Changes and Exit"\r
 #string STR_ISCSI_CONFIG_ISID           #language en-US "ISID"\r
 #string STR_ISCSI_CONFIG_ISID_HELP      #language en-US "OUI-format ISID in 6 bytes, default value are derived from MAC address. Only last 3 bytes are configurable. Example: update 0ABBCCDDEEFF to 0ABBCCF07901 by input F07901."\r
-\r
-  
\ No newline at end of file
+#string STR_ISCSI_MAC_PROMPT            #language en-US "Configure the mac address for the attempt"\r
+                                        #language x-UEFI-ns "iSCSIMacAddr"\r
+#string STR_ISCSI_ADD_ATTEMPTS          #language en-US "Add Attempts"\r
+                                        #language x-UEFI-ns "iSCSIAddAttempts"\r
+#string STR_ISCSI_DELETE_ATTEMPTS       #language en-US "Delete Attempts"\r
+                                        #language x-UEFI-ns "iSCSIDeleteAttempts"\r
+#string STR_ISCSI_DISPLAY_ATTEMPTS      #language en-US "Display Attempts"\r
+                                        #language x-UEFI-ns "iSCSIDisplayAttemptList"\r
+#string STR_ISCSI_ATTEMPT_ORDER         #language en-US "New Attempt Order"\r
+                                        #language x-UEFI-ns "iSCSIAttemptOrder"\r
index c469a78cdabfa606dca32f8962d20ae18e68d863..d401419a03d9a56c7f7c7ad6eb93d1bc29ca3c74 100644 (file)
@@ -121,10 +121,10 @@ formset
     string  varid   = ISCSI_CONFIG_IFR_NVDATA.AttemptName,\r
             prompt  = STRING_TOKEN(STR_ISCSI_ATTEMPT_NAME),\r
             help    = STRING_TOKEN(STR_ISCSI_ATTEMPT_NAME_HELP),\r
-            flags   = INTERACTIVE,\r
+            flags   = READ_ONLY,\r
             key     = KEY_ATTEMPT_NAME,\r
             minsize = 0,\r
-            maxsize = ATTEMPT_NAME_MAX_SIZE,\r
+            maxsize = ATTEMPT_NAME_SIZE,\r
     endstring;\r
 \r
     subtitle text = STRING_TOKEN(STR_NULL);\r
@@ -342,6 +342,48 @@ formset
 \r
     endif;\r
 \r
+    suppressif TRUE;\r
+\r
+    string  varid   = ISCSI_CONFIG_IFR_NVDATA.ISCSIMacAddr,\r
+            prompt  = STRING_TOKEN(STR_ISCSI_MAC_PROMPT),\r
+            help    = STRING_TOKEN(STR_ISCSI_MAC_PROMPT),\r
+            minsize = 0,\r
+            maxsize = ISCSI_MAX_MAC_STRING_LEN,\r
+    endstring;\r
+\r
+    string  varid   = ISCSI_CONFIG_IFR_NVDATA.ISCSIAttemptOrder,\r
+            prompt  = STRING_TOKEN(STR_ISCSI_ATTEMPT_ORDER),\r
+            help    = STRING_TOKEN(STR_ISCSI_ATTEMPT_ORDER),\r
+            minsize = 0,\r
+            maxsize = ATTEMPT_NAME_LIST_SIZE,\r
+    endstring;\r
+\r
+    string  varid   = ISCSI_CONFIG_IFR_NVDATA.ISCSIAddAttemptList,\r
+            prompt  = STRING_TOKEN(STR_ISCSI_ADD_ATTEMPTS),\r
+            help    = STRING_TOKEN(STR_ISCSI_ADD_ATTEMPTS),\r
+            minsize = 0,\r
+            maxsize = ATTEMPT_NAME_LIST_SIZE,\r
+    endstring;\r
+\r
+    string  varid   = ISCSI_CONFIG_IFR_NVDATA.ISCSIDeleteAttemptList,\r
+            prompt  = STRING_TOKEN(STR_ISCSI_DELETE_ATTEMPTS),\r
+            help    = STRING_TOKEN(STR_ISCSI_DELETE_ATTEMPTS),\r
+            minsize = 0,\r
+            maxsize = ATTEMPT_NAME_LIST_SIZE,\r
+    endstring;\r
+\r
+    string  varid   = ISCSI_CONFIG_IFR_NVDATA.ISCSIDisplayAttemptList,\r
+            prompt  = STRING_TOKEN(STR_ISCSI_DISPLAY_ATTEMPTS),\r
+            help    = STRING_TOKEN(STR_ISCSI_DISPLAY_ATTEMPTS),\r
+            flags   = READ_ONLY,\r
+            minsize = 0,\r
+            maxsize = ATTEMPT_NAME_LIST_SIZE,\r
+    endstring;\r
+\r
+    label KEYWORD_ENTRY_LABEL;\r
+    label LABEL_END;\r
+    endif;\r
+\r
     subtitle text = STRING_TOKEN(STR_NULL);\r
 \r
     text\r
index 59f387f3c00c04a49dbde1840f09105f2ede5f5b..269c1aec5c9fcfdb9b6f014633ddbc3340625efd 100644 (file)
@@ -373,7 +373,6 @@ IScsiStart (
   EFI_DEVICE_PATH_PROTOCOL        *DevicePath;\r
   EFI_GUID                        *IScsiPrivateGuid;\r
   EFI_GUID                        *TcpServiceBindingGuid;\r
-  CHAR16                          MacString[ISCSI_MAX_MAC_STRING_LEN];\r
   BOOLEAN                         NeedUpdate;\r
   VOID                            *Interface;\r
   EFI_GUID                        *ProtocolGuid;\r
@@ -697,12 +696,10 @@ IScsiStart (
     Session->ConfigData = AttemptConfigData;\r
     Session->AuthType   = AttemptConfigData->AuthenticationType;\r
 \r
-    AsciiStrToUnicodeStrS (AttemptConfigData->MacString, MacString, ARRAY_SIZE (MacString));\r
     UnicodeSPrint (\r
       mPrivate->PortString,\r
       (UINTN) ISCSI_NAME_IFR_MAX_SIZE,\r
-      L"%s%d",\r
-      MacString,\r
+      L"Attempt %d",\r
       (UINTN) AttemptConfigData->AttemptConfigIndex\r
       );\r
 \r
@@ -1803,6 +1800,22 @@ IScsiDriverEntryPoint (
     goto Error4;\r
   }\r
 \r
+  //\r
+  // Create the Maximum Attempts.\r
+  //\r
+  Status = IScsiCreateAttempts (PcdGet8 (PcdMaxIScsiAttemptNumber));\r
+  if (EFI_ERROR (Status)) {\r
+    goto Error5;\r
+  }\r
+\r
+  //\r
+  // Create Keywords for all the Attempts.\r
+  //\r
+  Status = IScsiCreateKeywords (PcdGet8 (PcdMaxIScsiAttemptNumber));\r
+  if (EFI_ERROR (Status)) {\r
+    goto Error5;\r
+  }\r
+\r
   //\r
   // There should be only one EFI_AUTHENTICATION_INFO_PROTOCOL. If already exists,\r
   // do not produce the protocol instance.\r
@@ -1820,15 +1833,18 @@ IScsiDriverEntryPoint (
                     &gIScsiAuthenticationInfo\r
                     );\r
     if (EFI_ERROR (Status)) {\r
-      goto Error5;\r
+      goto Error6;\r
     }    \r
   }\r
 \r
   return EFI_SUCCESS;\r
 \r
-Error5:\r
+Error6:\r
   IScsiConfigFormUnload (gIScsiIp4DriverBinding.DriverBindingHandle);\r
 \r
+Error5:\r
+  IScsiCleanAttemptVariable ();\r
+\r
 Error4:\r
   FreePool (mPrivate);\r
 \r
index 7bfa07fe6b4a0eb029094cede2dc59d05b820091..6c6e11b0d22831af246ae8f4f90d2b8047f75976 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   The header file of IScsiDriver.c.\r
 \r
-Copyright (c) 2004 - 2015, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2004 - 2017, Intel Corporation. All rights reserved.<BR>\r
 (C) Copyright 2017 Hewlett Packard Enterprise Development LP<BR>\r
 \r
 This program and the accompanying materials\r
@@ -68,7 +68,6 @@ typedef struct {
   LIST_ENTRY      AttemptConfigs;       // User configured Attempt list.\r
   CHAR8           InitiatorName[ISCSI_NAME_MAX_SIZE];\r
   UINTN           InitiatorNameLength;\r
-  VOID            *NewAttempt;          // Attempt is created but not saved.\r
 } ISCSI_PRIVATE_DATA;\r
 \r
 extern ISCSI_PRIVATE_DATA                 *mPrivate;\r
index 699ffd1103238ab63d3df5d3cefb3214c797b1df..c9b724bd30337f08f6d95dea1fff373f3a4ecd03 100644 (file)
   \r
   ## SOMETIMES_PRODUCES ## Variable:L"AttemptOrder"\r
   ## SOMETIMES_CONSUMES ## Variable:L"AttemptOrder"\r
+  ## SOMETIMES_PRODUCES ## Variable:L"InitialAttemptOrder"\r
+  ## SOMETIMES_CONSUMES ## Variable:L"InitialAttemptOrder"\r
   ## SOMETIMES_CONSUMES ## UNDEFINED # HiiIsConfigHdrMatch   mVendorStorageName\r
   ## SOMETIMES_PRODUCES ## UNDEFINED # HiiConstructConfigHdr mVendorStorageName\r
   ## SOMETIMES_PRODUCES ## UNDEFINED # HiiGetBrowserData     mVendorStorageName\r
 \r
 [Pcd]\r
   gEfiNetworkPkgTokenSpaceGuid.PcdIScsiAIPNetworkBootPolicy ## CONSUMES\r
-  \r
+  gEfiNetworkPkgTokenSpaceGuid.PcdMaxIScsiAttemptNumber     ## CONSUMES\r
+\r
 [UserExtensions.TianoCore."ExtraFiles"]\r
   IScsiDxeExtra.uni\r
index e8e8f9c9efa1e0a77dfaac3498154f49aa077d57..7b4044fe5ade00d6443c7e68161cb1192e936393 100644 (file)
@@ -643,17 +643,787 @@ 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
+    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
+      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
+      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
+    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
+      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
+      StringToken,\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_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_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_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_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
+  return;\r
+}\r
 \r
 /**\r
   Get the recorded NIC info from global structure by the Index.\r
@@ -931,6 +1701,7 @@ IScsiDhcpIsConfigured (
   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
@@ -959,8 +1730,7 @@ IScsiDhcpIsConfigured (
     UnicodeSPrint (\r
       AttemptName,\r
       (UINTN) 128,\r
-      L"%s%d",\r
-      MacString,\r
+      L"Attempt %d",\r
       (UINTN) AttemptConfigOrder[Index]\r
       );\r
     Status = GetVariable2 (\r
@@ -985,7 +1755,13 @@ IScsiDhcpIsConfigured (
       FreePool (AttemptTmp);\r
       continue;\r
     }\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
@@ -1106,6 +1882,7 @@ IScsiGetConfigData (
 {\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
@@ -1197,12 +1974,10 @@ IScsiGetConfigData (
           //\r
           // Refresh the state of this attempt to NVR.\r
           //\r
-          AsciiStrToUnicodeStrS (AttemptTmp->MacString, MacString, ARRAY_SIZE (MacString));\r
           UnicodeSPrint (\r
             mPrivate->PortString,\r
             (UINTN) ISCSI_NAME_IFR_MAX_SIZE,\r
-            L"%s%d",\r
-            MacString,\r
+            L"Attempt %d",\r
             (UINTN) AttemptTmp->AttemptConfigIndex\r
             );\r
 \r
@@ -1236,12 +2011,10 @@ IScsiGetConfigData (
         //\r
         // Refresh the state of this attempt to NVR.\r
         //\r
-        AsciiStrToUnicodeStrS (AttemptTmp->MacString, MacString, ARRAY_SIZE (MacString));\r
         UnicodeSPrint (\r
           mPrivate->PortString,\r
           (UINTN) ISCSI_NAME_IFR_MAX_SIZE,\r
-          L"%s%d",\r
-          MacString,\r
+          L"Attempt %d",\r
           (UINTN) AttemptTmp->AttemptConfigIndex\r
           );\r
 \r
@@ -1269,9 +2042,8 @@ 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) ISCSI_NAME_IFR_MAX_SIZE,\r
+      L"Attempt %d",\r
       (UINTN) AttemptConfigOrder[Index]\r
       );\r
 \r
@@ -1281,8 +2053,10 @@ IScsiGetConfigData (
       (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
       continue;\r
     }\r
 \r
@@ -1327,12 +2101,10 @@ IScsiGetConfigData (
       //\r
       // Refresh the state of this attempt to NVR.\r
       //\r
-      AsciiStrToUnicodeStrS (AttemptConfigData->MacString, MacString, ARRAY_SIZE (MacString));\r
       UnicodeSPrint (\r
         mPrivate->PortString,\r
         (UINTN) ISCSI_NAME_IFR_MAX_SIZE,\r
-        L"%s%d",\r
-        MacString,\r
+        L"Attempt %d",\r
         (UINTN) AttemptConfigData->AttemptConfigIndex\r
         );\r
 \r
index 2c0fe07fdb60a54da82d8c3199f6a5db492da1e9..caa2f94bb1b90d9d758b547b88d74ca896dca5aa 100644 (file)
@@ -243,6 +243,44 @@ IScsiRemoveNic (
   IN EFI_HANDLE  Controller\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
+/**\r
+  Create the iSCSI configuration Keywords for each attempt.\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
+/**\r
+\r
+  Free the attempt configure data variable.\r
+\r
+**/\r
+VOID\r
+IScsiCleanAttemptVariable (\r
+  IN   VOID\r
+  );\r
+\r
 /**\r
   Get the recorded NIC information from a global structure by the Index.\r
 \r
index 2aa88942fc6f2bb9e7c0b55b112660b6f72833d6..28558d3c25e956e6a19186a0369357bdafb229ef 100644 (file)
   \r
   # Include/Guid/TlsAuthentication.h\r
   gEfiTlsCaCertificateGuid      = { 0xfd2340D0, 0x3dab, 0x4349, { 0xa6, 0xc7, 0x3b, 0x4f, 0x12, 0xb4, 0x8e, 0xae }}\r
-  \r
+\r
+[PcdsFixedAtBuild]\r
+  ## The max attempt number will be created by iSCSI driver.\r
+  # @Prompt Max attempt number.\r
+  gEfiNetworkPkgTokenSpaceGuid.PcdMaxIScsiAttemptNumber|0x08|UINT8|0x0000000D\r
 \r
 [PcdsFeatureFlag]\r
   ## Indicates if the IPsec IKEv2 Certificate Authentication feature is enabled or not.<BR><BR>\r