/** @file
  Miscellaneous routines for iSCSI driver.

Copyright (c) 2004 - 2017, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution.  The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php

THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

**/

#include "IScsiImpl.h"

GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8  IScsiHexString[] = "0123456789ABCDEFabcdef";

/**
  Removes (trims) specified leading and trailing characters from a string.

  @param[in, out] Str   Pointer to the null-terminated string to be trimmed.
                        On return, Str will hold the trimmed string. 

  @param[in]      CharC Character will be trimmed from str.

**/
VOID
IScsiStrTrim (
  IN OUT CHAR16   *Str,
  IN     CHAR16   CharC
  )
{
  CHAR16  *Pointer1;
  CHAR16  *Pointer2;
  
  if (*Str == 0) {
    return ;
  }
  
  //
  // Trim off the leading and trailing characters c
  //
  for (Pointer1 = Str; (*Pointer1 != 0) && (*Pointer1 == CharC); Pointer1++) {
    ;
  }
  
  Pointer2 = Str;
  if (Pointer2 == Pointer1) {
    while (*Pointer1 != 0) {
      Pointer2++;
      Pointer1++;
    }
  } else {
    while (*Pointer1 != 0) {    
    *Pointer2 = *Pointer1;    
    Pointer1++;
    Pointer2++;
    }
    *Pointer2 = 0;
  }
  
  
  for (Pointer1 = Str + StrLen(Str) - 1; Pointer1 >= Str && *Pointer1 == CharC; Pointer1--) {
    ;
  }
  if  (Pointer1 !=  Str + StrLen(Str) - 1) { 
    *(Pointer1 + 1) = 0;
  }
}

/**
  Calculate the prefix length of the IPv4 subnet mask.

  @param[in]  SubnetMask The IPv4 subnet mask.

  @return     The prefix length of the subnet mask.
  @retval 0   Other errors as indicated.

**/
UINT8
IScsiGetSubnetMaskPrefixLength (
  IN EFI_IPv4_ADDRESS  *SubnetMask
  )
{
  UINT8   Len;
  UINT32  ReverseMask;

  //
  // The SubnetMask is in network byte order.
  //
  ReverseMask = (SubnetMask->Addr[0] << 24) | (SubnetMask->Addr[1] << 16) | (SubnetMask->Addr[2] << 8) | (SubnetMask->Addr[3]);

  //
  // Reverse it.
  //
  ReverseMask = ~ReverseMask;

  if ((ReverseMask & (ReverseMask + 1)) != 0) {
    return 0;
  }

  Len = 0;

  while (ReverseMask != 0) {
    ReverseMask = ReverseMask >> 1;
    Len++;
  }

  return (UINT8) (32 - Len);
}


/**
  Convert the hexadecimal encoded LUN string into the 64-bit LUN.

  @param[in]   Str             The hexadecimal encoded LUN string.
  @param[out]  Lun             Storage to return the 64-bit LUN.

  @retval EFI_SUCCESS            The 64-bit LUN is stored in Lun.
  @retval EFI_INVALID_PARAMETER  The string is malformatted.

**/
EFI_STATUS
IScsiAsciiStrToLun (
  IN  CHAR8  *Str,
  OUT UINT8  *Lun
  )
{
  UINTN   Index, IndexValue, IndexNum, SizeStr;
  CHAR8   TemStr[2];
  UINT8   TemValue;
  UINT16  Value[4];
  
  ZeroMem (Lun, 8);
  ZeroMem (TemStr, 2);
  ZeroMem ((UINT8 *) Value, sizeof (Value));
  SizeStr    = AsciiStrLen (Str);  
  IndexValue = 0;
  IndexNum   = 0;

  for (Index = 0; Index < SizeStr; Index ++) {
    TemStr[0] = Str[Index];
    TemValue = (UINT8) AsciiStrHexToUint64 (TemStr);
    if (TemValue == 0 && TemStr[0] != '0') {
      if ((TemStr[0] != '-') || (IndexNum == 0)) {
        //
        // Invalid Lun Char.
        //
        return EFI_INVALID_PARAMETER;
      }
    }
    
    if ((TemValue == 0) && (TemStr[0] == '-')) {
      //
      // Next Lun value.
      //
      if (++IndexValue >= 4) {
        //
        // Max 4 Lun value.
        //
        return EFI_INVALID_PARAMETER;
      }
      //
      // Restart str index for the next lun value.
      //
      IndexNum = 0;
      continue;
    }
    
    if (++IndexNum > 4) {
      //     
      // Each Lun Str can't exceed size 4, because it will be as UINT16 value.
      //
      return EFI_INVALID_PARAMETER;
    }
    
    //
    // Combine UINT16 value.
    //
    Value[IndexValue] = (UINT16) ((Value[IndexValue] << 4) + TemValue);
  }
 
  for (Index = 0; Index <= IndexValue; Index ++) {
    *((UINT16 *) &Lun[Index * 2]) =  HTONS (Value[Index]);
  }
  
  return EFI_SUCCESS;
}

/**
  Convert the 64-bit LUN into the hexadecimal encoded LUN string.

  @param[in]   Lun The 64-bit LUN.
  @param[out]  Str The storage to return the hexadecimal encoded LUN string.

**/
VOID
IScsiLunToUnicodeStr (
  IN UINT8    *Lun,
  OUT CHAR16  *Str
  )
{
  UINTN   Index;
  CHAR16  *TempStr;

  TempStr = Str;

  for (Index = 0; Index < 4; Index++) {

    if ((Lun[2 * Index] | Lun[2 * Index + 1]) == 0) {
      CopyMem (TempStr, L"0-", sizeof (L"0-"));
    } else {
      TempStr[0]  = (CHAR16) IScsiHexString[Lun[2 * Index] >> 4];
      TempStr[1]  = (CHAR16) IScsiHexString[Lun[2 * Index] & 0x0F];
      TempStr[2]  = (CHAR16) IScsiHexString[Lun[2 * Index + 1] >> 4];
      TempStr[3]  = (CHAR16) IScsiHexString[Lun[2 * Index + 1] & 0x0F];
      TempStr[4]  = L'-';
      TempStr[5]  = 0;

      IScsiStrTrim (TempStr, L'0');
    }

    TempStr += StrLen (TempStr);
  }
  //
  // Remove the last '-'
  //
  ASSERT (StrLen(Str) >= 1);
  Str[StrLen (Str) - 1] = 0;

  for (Index = StrLen (Str) - 1; Index > 1; Index = Index - 2) {
    if ((Str[Index] == L'0') && (Str[Index - 1] == L'-')) {
      Str[Index - 1] = 0;
    } else {
      break;
    }
  }
}

/**
  Convert the formatted IP address into the binary IP address.

  @param[in]   Str               The UNICODE string.
  @param[in]   IpMode            Indicates whether the IP address is v4 or v6.
  @param[out]  Ip                The storage to return the ASCII string.

  @retval EFI_SUCCESS            The binary IP address is returned in Ip.
  @retval EFI_INVALID_PARAMETER  The IP string is malformatted or IpMode is
                                 invalid.

**/
EFI_STATUS
IScsiAsciiStrToIp (
  IN  CHAR8             *Str,
  IN  UINT8             IpMode,
  OUT EFI_IP_ADDRESS    *Ip
  )
{
  EFI_STATUS            Status;

  if (IpMode == IP_MODE_IP4 || IpMode == IP_MODE_AUTOCONFIG_IP4) {
    return NetLibAsciiStrToIp4 (Str, &Ip->v4);

  } else if (IpMode == IP_MODE_IP6 || IpMode == IP_MODE_AUTOCONFIG_IP6) {
    return NetLibAsciiStrToIp6 (Str, &Ip->v6);

  } else if (IpMode == IP_MODE_AUTOCONFIG) {
    Status = NetLibAsciiStrToIp4 (Str, &Ip->v4);
    if (!EFI_ERROR (Status)) {
      return Status;
    }
    return NetLibAsciiStrToIp6 (Str, &Ip->v6);

  }

  return EFI_INVALID_PARAMETER;
}

/**
  Convert the mac address into a hexadecimal encoded "-" seperated string.

  @param[in]  Mac     The mac address.
  @param[in]  Len     Length in bytes of the mac address.
  @param[in]  VlanId  VLAN ID of the network device.
  @param[out] Str     The storage to return the mac string.

**/
VOID
IScsiMacAddrToStr (
  IN  EFI_MAC_ADDRESS  *Mac,
  IN  UINT32           Len,
  IN  UINT16           VlanId,
  OUT CHAR16           *Str
  )
{
  UINT32  Index;
  CHAR16  *String;

  for (Index = 0; Index < Len; Index++) {
    Str[3 * Index]      = (CHAR16) IScsiHexString[(Mac->Addr[Index] >> 4) & 0x0F];
    Str[3 * Index + 1]  = (CHAR16) IScsiHexString[Mac->Addr[Index] & 0x0F];
    Str[3 * Index + 2]  = L':';
  }

  String = &Str[3 * Index - 1] ;
  if (VlanId != 0) {
    String += UnicodeSPrint (String, 6 * sizeof (CHAR16), L"\\%04x", (UINTN) VlanId);
  }

  *String = L'\0';
}

/**
  Convert the binary encoded buffer into a hexadecimal encoded string.

  @param[in]       BinBuffer   The buffer containing the binary data.
  @param[in]       BinLength   Length of the binary buffer.
  @param[in, out]  HexStr      Pointer to the string.
  @param[in, out]  HexLength   The length of the string.

  @retval EFI_SUCCESS          The binary data is converted to the hexadecimal string 
                               and the length of the string is updated.
  @retval EFI_BUFFER_TOO_SMALL The string is too small.
  @retval EFI_INVALID_PARAMETER The IP string is malformatted.

**/
EFI_STATUS
IScsiBinToHex (
  IN     UINT8  *BinBuffer,
  IN     UINT32 BinLength,
  IN OUT CHAR8  *HexStr,
  IN OUT UINT32 *HexLength
  )
{
  UINTN Index;

  if ((HexStr == NULL) || (BinBuffer == NULL) || (BinLength == 0)) {
    return EFI_INVALID_PARAMETER;
  }

  if (((*HexLength) - 3) < BinLength * 2) {
    *HexLength = BinLength * 2 + 3;
    return EFI_BUFFER_TOO_SMALL;
  }

  *HexLength = BinLength * 2 + 3;
  //
  // Prefix for Hex String.
  //
  HexStr[0] = '0';
  HexStr[1] = 'x';

  for (Index = 0; Index < BinLength; Index++) {
    HexStr[Index * 2 + 2] = IScsiHexString[BinBuffer[Index] >> 4];
    HexStr[Index * 2 + 3] = IScsiHexString[BinBuffer[Index] & 0xf];
  }

  HexStr[Index * 2 + 2] = '\0';

  return EFI_SUCCESS;
}


/**
  Convert the hexadecimal string into a binary encoded buffer.

  @param[in, out]  BinBuffer   The binary buffer.
  @param[in, out]  BinLength   Length of the binary buffer.
  @param[in]       HexStr      The hexadecimal string.

  @retval EFI_SUCCESS          The hexadecimal string is converted into a binary
                               encoded buffer.
  @retval EFI_BUFFER_TOO_SMALL The binary buffer is too small to hold the converted data.

**/
EFI_STATUS
IScsiHexToBin (
  IN OUT UINT8  *BinBuffer,
  IN OUT UINT32 *BinLength,
  IN     CHAR8  *HexStr
  )
{
  UINTN   Index;
  UINTN   Length;
  UINT8   Digit;
  CHAR8   TemStr[2];
  
  ZeroMem (TemStr, sizeof (TemStr));

  //
  // Find out how many hex characters the string has.
  //
  if ((HexStr[0] == '0') && ((HexStr[1] == 'x') || (HexStr[1] == 'X'))) {
    HexStr += 2;
  }
  
  Length = AsciiStrLen (HexStr);

  for (Index = 0; Index < Length; Index ++) {
    TemStr[0] = HexStr[Index];
    Digit = (UINT8) AsciiStrHexToUint64 (TemStr);
    if (Digit == 0 && TemStr[0] != '0') {
      //
      // Invalid Lun Char.
      //
      break;
    }
    if ((Index & 1) == 0) {
      BinBuffer [Index/2] = Digit;
    } else {
      BinBuffer [Index/2] = (UINT8) ((BinBuffer [Index/2] << 4) + Digit);
    }
  }
  
  *BinLength = (UINT32) ((Index + 1)/2);

  return EFI_SUCCESS;
}


/**
  Convert the decimal-constant string or hex-constant string into a numerical value.

  @param[in] Str                    String in decimal or hex.

  @return The numerical value.

**/
UINTN
IScsiNetNtoi (
  IN     CHAR8  *Str
  )
{
  if ((Str[0] == '0') && ((Str[1] == 'x') || (Str[1] == 'X'))) {
    Str += 2;

    return AsciiStrHexToUintn (Str);
  }

  return AsciiStrDecimalToUintn (Str);
}


/**
  Generate random numbers.

  @param[in, out]  Rand       The buffer to contain random numbers.
  @param[in]       RandLength The length of the Rand buffer.

**/
VOID
IScsiGenRandom (
  IN OUT UINT8  *Rand,
  IN     UINTN  RandLength
  )
{
  UINT32  Random;

  while (RandLength > 0) {
    Random  = NET_RANDOM (NetRandomInitSeed ());
    *Rand++ = (UINT8) (Random);
    RandLength--;
  }
}


/**
  Record the NIC info in global structure.

  @param[in]  Controller         The handle of the controller.

  @retval EFI_SUCCESS            The operation is completed.
  @retval EFI_OUT_OF_RESOURCES   Do not have sufficient resources to finish this
                                 operation.

**/
EFI_STATUS
IScsiAddNic (
  IN EFI_HANDLE  Controller
  )
{
  EFI_STATUS                  Status;
  ISCSI_NIC_INFO              *NicInfo;
  LIST_ENTRY                  *Entry;
  EFI_MAC_ADDRESS             MacAddr;
  UINTN                       HwAddressSize;
  UINT16                      VlanId;

  //
  // Get MAC address of this network device.
  //
  Status = NetLibGetMacAddress (Controller, &MacAddr, &HwAddressSize);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  //
  // Get VLAN ID of this network device.
  //
  VlanId = NetLibGetVlanId (Controller);

  //
  // Check whether the NIC info already exists. Return directly if so.
  //
  NET_LIST_FOR_EACH (Entry, &mPrivate->NicInfoList) {
    NicInfo = NET_LIST_USER_STRUCT (Entry, ISCSI_NIC_INFO, Link);
    if (NicInfo->HwAddressSize == HwAddressSize &&
        CompareMem (&NicInfo->PermanentAddress, MacAddr.Addr, HwAddressSize) == 0 &&
        NicInfo->VlanId == VlanId) {
      mPrivate->CurrentNic = NicInfo->NicIndex;
      return EFI_SUCCESS;
    }

    if (mPrivate->MaxNic < NicInfo->NicIndex) {
      mPrivate->MaxNic = NicInfo->NicIndex;
    }
  }

  //
  // Record the NIC info in private structure.
  //
  NicInfo = AllocateZeroPool (sizeof (ISCSI_NIC_INFO));
  if (NicInfo == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }

  CopyMem (&NicInfo->PermanentAddress, MacAddr.Addr, HwAddressSize);
  NicInfo->HwAddressSize  = (UINT32) HwAddressSize;
  NicInfo->VlanId         = VlanId;
  NicInfo->NicIndex       = (UINT8) (mPrivate->MaxNic + 1);
  mPrivate->MaxNic        = NicInfo->NicIndex;

  //
  // Get the PCI location.
  //
  IScsiGetNICPciLocation (
    Controller,
    &NicInfo->BusNumber,
    &NicInfo->DeviceNumber,
    &NicInfo->FunctionNumber
    );

  InsertTailList (&mPrivate->NicInfoList, &NicInfo->Link);
  mPrivate->NicCount++;

  mPrivate->CurrentNic = NicInfo->NicIndex;
  return EFI_SUCCESS;
}


/**
  Delete the recorded NIC info from global structure. Also delete corresponding
  attempts.

  @param[in]  Controller         The handle of the controller.

  @retval EFI_SUCCESS            The operation is completed.
  @retval EFI_NOT_FOUND          The NIC info to be deleted is not recorded.

**/
EFI_STATUS
IScsiRemoveNic (
  IN EFI_HANDLE  Controller
  )
{
  EFI_STATUS                  Status;
  ISCSI_NIC_INFO              *NicInfo;
  LIST_ENTRY                  *Entry;
  LIST_ENTRY                  *NextEntry;
  ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;
  ISCSI_NIC_INFO              *ThisNic;
  EFI_MAC_ADDRESS             MacAddr;
  UINTN                       HwAddressSize;
  UINT16                      VlanId;

  //
  // Get MAC address of this network device.
  //
  Status = NetLibGetMacAddress (Controller, &MacAddr, &HwAddressSize);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  //
  // Get VLAN ID of this network device.
  //
  VlanId = NetLibGetVlanId (Controller);

  //
  // Check whether the NIC information exists.
  //
  ThisNic = NULL;

  NET_LIST_FOR_EACH (Entry, &mPrivate->NicInfoList) {
    NicInfo = NET_LIST_USER_STRUCT (Entry, ISCSI_NIC_INFO, Link);
    if (NicInfo->HwAddressSize == HwAddressSize &&
        CompareMem (&NicInfo->PermanentAddress, MacAddr.Addr, HwAddressSize) == 0 &&
        NicInfo->VlanId == VlanId) {

      ThisNic = NicInfo;
      break;
    }
  }

  if (ThisNic == NULL) {
    return EFI_NOT_FOUND;
  }

  mPrivate->CurrentNic = ThisNic->NicIndex;

  RemoveEntryList (&ThisNic->Link);
  FreePool (ThisNic);
  mPrivate->NicCount--;

  //
  // Remove all attempts related to this NIC.
  //
  NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &mPrivate->AttemptConfigs) {
    AttemptConfigData = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);
    if (AttemptConfigData->NicIndex == mPrivate->CurrentNic) {
      RemoveEntryList (&AttemptConfigData->Link);
      mPrivate->AttemptCount--;

      if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED_FOR_MPIO && mPrivate->MpioCount > 0) {
        if (--mPrivate->MpioCount == 0) {
          mPrivate->EnableMpio = FALSE;
        }

        if (AttemptConfigData->AuthenticationType == ISCSI_AUTH_TYPE_KRB && mPrivate->Krb5MpioCount > 0) {
          mPrivate->Krb5MpioCount--;
        }

      } else if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED && mPrivate->SinglePathCount > 0) {
        mPrivate->SinglePathCount--;

        if (mPrivate->ValidSinglePathCount > 0) {
          mPrivate->ValidSinglePathCount--;
        }
      }

      FreePool (AttemptConfigData);
    }
  }

  return EFI_SUCCESS;
}

/**
  Create and initialize the Attempts.

  @param[in]  AttemptNum          The number of Attempts will be created.

  @retval EFI_SUCCESS             The Attempts have been created successfully.
  @retval Others                  Failed to create the Attempt.

**/
EFI_STATUS
IScsiCreateAttempts (
  IN UINTN            AttemptNum
)
{
  ISCSI_ATTEMPT_CONFIG_NVDATA   *AttemptConfigData;
  ISCSI_SESSION_CONFIG_NVDATA   *ConfigData;
  UINT8                         *AttemptConfigOrder;
  UINTN                         AttemptConfigOrderSize;
  UINT8                         *AttemptOrderTmp;
  UINTN                         TotalNumber;
  UINT8                         Index;
  EFI_STATUS                    Status;

  for (Index = 1; Index <= AttemptNum; Index ++) {
    //
    // Get the initialized attempt order. This is used to essure creating attempts by order.
    //
    AttemptConfigOrder = IScsiGetVariableAndSize (
                           L"InitialAttemptOrder",
                           &gIScsiConfigGuid,
                           &AttemptConfigOrderSize
                           );
    TotalNumber = AttemptConfigOrderSize / sizeof (UINT8);
    if (TotalNumber == AttemptNum) {
      Status = EFI_SUCCESS;
      break;
    }
    TotalNumber++;

    //
    // Append the new created attempt to the end.
    //
    AttemptOrderTmp = AllocateZeroPool (TotalNumber * sizeof (UINT8));
    if (AttemptOrderTmp == NULL) {
      if (AttemptConfigOrder != NULL) {
        FreePool (AttemptConfigOrder);
      }
      return EFI_OUT_OF_RESOURCES;
    }

    if (AttemptConfigOrder != NULL) {
      CopyMem (AttemptOrderTmp, AttemptConfigOrder, AttemptConfigOrderSize);
      FreePool (AttemptConfigOrder);
    }

    AttemptOrderTmp[TotalNumber - 1] = Index;
    AttemptConfigOrder               = AttemptOrderTmp;
    AttemptConfigOrderSize           = TotalNumber * sizeof (UINT8);

    Status = gRT->SetVariable (
                    L"InitialAttemptOrder",
                    &gIScsiConfigGuid,
                    EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
                    AttemptConfigOrderSize,
                    AttemptConfigOrder
                    );
    FreePool (AttemptConfigOrder);
    if (EFI_ERROR (Status)) {
      return Status;
    }

    //
    // Create new Attempt
    //
    AttemptConfigData = AllocateZeroPool (sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA));
    if (AttemptConfigData == NULL) {
      return EFI_OUT_OF_RESOURCES;
    }
    ConfigData                    = &AttemptConfigData->SessionConfigData;
    ConfigData->TargetPort        = ISCSI_WELL_KNOWN_PORT;
    ConfigData->ConnectTimeout    = CONNECT_DEFAULT_TIMEOUT;
    ConfigData->ConnectRetryCount = CONNECT_MIN_RETRY;

    AttemptConfigData->AuthenticationType           = ISCSI_AUTH_TYPE_CHAP;
    AttemptConfigData->AuthConfigData.CHAP.CHAPType = ISCSI_CHAP_UNI;
    //
    // Configure the Attempt index and set variable.
    //
    AttemptConfigData->AttemptConfigIndex = Index;

    //
    // Set the attempt name according to the order.
    //
    UnicodeSPrint (
      mPrivate->PortString,
      (UINTN) ISCSI_NAME_IFR_MAX_SIZE,
      L"Attempt %d",
      (UINTN) AttemptConfigData->AttemptConfigIndex
      );
    UnicodeStrToAsciiStrS (mPrivate->PortString, AttemptConfigData->AttemptName, ATTEMPT_NAME_SIZE);

    Status = gRT->SetVariable (
                    mPrivate->PortString,
                    &gEfiIScsiInitiatorNameProtocolGuid,
                    ISCSI_CONFIG_VAR_ATTR,
                    sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA),
                    AttemptConfigData
                    );
    FreePool (AttemptConfigData);
    if (EFI_ERROR (Status)) {
      return Status;
    }
  }

  return EFI_SUCCESS;
}

/**
  Create the iSCSI configuration Keywords for each attempt. You can find the keywords
  defined in the "x-UEFI-ns" namespace (http://www.uefi.org/confignamespace).

  @param[in]  KeywordNum          The number Sets of Keywords will be created.

  @retval EFI_SUCCESS             The operation is completed.
  @retval Others                  Failed to create the Keywords.

**/
EFI_STATUS
IScsiCreateKeywords (
  IN UINTN            KeywordNum
)
{
  VOID                          *StartOpCodeHandle;
  EFI_IFR_GUID_LABEL            *StartLabel;
  VOID                          *EndOpCodeHandle;
  EFI_IFR_GUID_LABEL            *EndLabel;
  UINTN                         Index;
  EFI_STRING_ID                 StringToken;
  CHAR16                        StringId[64];
  CHAR16                        KeywordId[32];
  EFI_STATUS                    Status;

  Status = IScsiCreateOpCode (
             KEYWORD_ENTRY_LABEL,
             &StartOpCodeHandle,
             &StartLabel,
             &EndOpCodeHandle,
             &EndLabel
             );
  if (EFI_ERROR (Status)) {
    return EFI_OUT_OF_RESOURCES;
  }

  for (Index = 1; Index <= KeywordNum; Index ++) {
    //
    // Create iSCSIAttemptName Keyword.
    //
    UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_ATTEMPTT_NAME_PROMPT%d", Index);
    StringToken =  HiiSetString (
                     mCallbackInfo->RegisteredHandle,
                     0,
                     StringId,
                     NULL
                     );
    UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIAttemptName:%d", Index);
    HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
    HiiCreateStringOpCode (
      StartOpCodeHandle,
      (EFI_QUESTION_ID) (ATTEMPT_ATTEMPT_NAME_QUESTION_ID + (Index - 1)),
      CONFIGURATION_VARSTORE_ID,
      (UINT16) (ATTEMPT_ATTEMPT_NAME_VAR_OFFSET + ATTEMPT_NAME_SIZE * (Index - 1) * sizeof (CHAR16)),
      StringToken,
      StringToken,
      EFI_IFR_FLAG_READ_ONLY,
      0,
      0,
      ATTEMPT_NAME_SIZE,
      NULL
      );

    //
    // Create iSCSIBootEnable Keyword.
    //
    UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_MODE_PROMPT%d", Index);
    StringToken =  HiiSetString (
                     mCallbackInfo->RegisteredHandle,
                     0,
                     StringId,
                     NULL
                     );
    UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIBootEnable:%d", Index);
    HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
    HiiCreateNumericOpCode (
      StartOpCodeHandle,
      (EFI_QUESTION_ID) (ATTEMPT_BOOTENABLE_QUESTION_ID + (Index - 1)),
      CONFIGURATION_VARSTORE_ID,
      (UINT16) (ATTEMPT_BOOTENABLE_VAR_OFFSET + (Index - 1)),
      StringToken,
      StringToken,
      0,
      EFI_IFR_NUMERIC_SIZE_1,
      0,
      2,
      0,
      NULL
      );

    //
    // Create iSCSIIpAddressType Keyword.
    //
    UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_IP_MODE_PROMPT%d", Index);
    StringToken =  HiiSetString (
                     mCallbackInfo->RegisteredHandle,
                     0,
                     StringId,
                     NULL
                     );
    UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIIpAddressType:%d", Index);
    HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
    HiiCreateNumericOpCode (
      StartOpCodeHandle,
      (EFI_QUESTION_ID) (ATTEMPT_ADDRESS_TYPE_QUESTION_ID + (Index - 1)),
      CONFIGURATION_VARSTORE_ID,
      (UINT16) (ATTEMPT_ADDRESS_TYPE_VAR_OFFSET + (Index - 1)),
      StringToken,
      StringToken,
      0,
      EFI_IFR_NUMERIC_SIZE_1,
      0,
      2,
      0,
      NULL
      );

    //
    // Create iSCSIConnectRetry Keyword.
    //
    UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_CONNECT_RETRY_PROMPT%d", Index);
    StringToken =  HiiSetString (
                     mCallbackInfo->RegisteredHandle,
                     0,
                     StringId,
                     NULL
                     );
    UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIConnectRetry:%d", Index);
    HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
    HiiCreateNumericOpCode (
      StartOpCodeHandle,
      (EFI_QUESTION_ID) (ATTEMPT_CONNECT_RETRY_QUESTION_ID + (Index - 1)),
      CONFIGURATION_VARSTORE_ID,
      (UINT16) (ATTEMPT_CONNECT_RETRY_VAR_OFFSET + (Index - 1)),
      StringToken,
      StringToken,
      0,
      EFI_IFR_NUMERIC_SIZE_1,
      0,
      16,
      0,
      NULL
      );

    //
    // Create iSCSIConnectTimeout Keyword.
    //
    UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_CONNECT_TIMEOUT_PROMPT%d", Index);
    StringToken =  HiiSetString (
                     mCallbackInfo->RegisteredHandle,
                     0,
                     StringId,
                     NULL
                     );
    UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIConnectTimeout:%d", Index);
    HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
    HiiCreateNumericOpCode (
      StartOpCodeHandle,
      (EFI_QUESTION_ID) (ATTEMPT_CONNECT_TIMEOUT_QUESTION_ID + (Index - 1)),
      CONFIGURATION_VARSTORE_ID,
      (UINT16) (ATTEMPT_CONNECT_TIMEOUT_VAR_OFFSET + 2 * (Index - 1)),
      StringToken,
      StringToken,
      0,
      EFI_IFR_NUMERIC_SIZE_2,
      CONNECT_MIN_TIMEOUT,
      CONNECT_MAX_TIMEOUT,
      0,
      NULL
      );

    //
    // Create ISID Keyword.
    //
    UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_ISID_PROMPT%d", Index);
    StringToken =  HiiSetString (
                     mCallbackInfo->RegisteredHandle,
                     0,
                     StringId,
                     NULL
                     );
    UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIISID:%d", Index);
    HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
    HiiCreateStringOpCode (
      StartOpCodeHandle,
      (EFI_QUESTION_ID) (ATTEMPT_ISID_QUESTION_ID + (Index - 1)),
      CONFIGURATION_VARSTORE_ID,
      (UINT16) (ATTEMPT_ISID_VAR_OFFSET + sizeof (KEYWORD_STR) * (Index - 1)),
      StringToken,
      StringToken,
      0,
      0,
      ISID_CONFIGURABLE_MIN_LEN,
      ISID_CONFIGURABLE_STORAGE,
      NULL
      );

    //
    // Create iSCSIInitiatorInfoViaDHCP Keyword.
    //
    UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_INITIATOR_VIA_DHCP_PROMPT%d", Index);
    StringToken =  HiiSetString (
                     mCallbackInfo->RegisteredHandle,
                     0,
                     StringId,
                     NULL
                     );
    UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIInitiatorInfoViaDHCP:%d", Index);
    HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
    HiiCreateNumericOpCode (
    StartOpCodeHandle,
    (EFI_QUESTION_ID) (ATTEMPT_INITIATOR_VIA_DHCP_QUESTION_ID + (Index - 1)),
    CONFIGURATION_VARSTORE_ID,
    (UINT16) (ATTEMPT_INITIATOR_VIA_DHCP_VAR_OFFSET + (Index - 1)),
    StringToken,
    StringToken,
    0,
    0,
    0,
    1,
    0,
    NULL
    );

    //
    // Create iSCSIInitiatorIpAddress Keyword.
    //
    UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_INITIATOR_IP_ADDRESS_PROMPT%d", Index);
    StringToken =  HiiSetString (
                     mCallbackInfo->RegisteredHandle,
                     0,
                     StringId,
                     NULL
                     );
    UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIInitiatorIpAddress:%d", Index);
    HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
    HiiCreateStringOpCode (
      StartOpCodeHandle,
      (EFI_QUESTION_ID) (ATTEMPT_INITIATOR_IP_ADDRESS_QUESTION_ID + (Index - 1)),
      CONFIGURATION_VARSTORE_ID,
      (UINT16) (ATTEMPT_INITIATOR_IP_ADDRESS_VAR_OFFSET + sizeof (KEYWORD_STR) * (Index - 1)),
      StringToken,
      StringToken,
      0,
      0,
      IP4_MIN_SIZE,
      IP4_MAX_SIZE,
      NULL
      );

    //
    // Create iSCSIInitiatorNetmask Keyword.
    //
    UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_INITIATOR_NET_MASK_PROMPT%d", Index);
    StringToken =  HiiSetString (
                     mCallbackInfo->RegisteredHandle,
                     0,
                     StringId,
                     NULL
                     );
    UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIInitiatorNetmask:%d", Index);
    HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
    HiiCreateStringOpCode (
      StartOpCodeHandle,
      (EFI_QUESTION_ID) (ATTEMPT_INITIATOR_NET_MASK_QUESTION_ID + (Index - 1)),
      CONFIGURATION_VARSTORE_ID,
      (UINT16) (ATTEMPT_INITIATOR_NET_MASK_VAR_OFFSET + sizeof (KEYWORD_STR) * (Index - 1)),
      StringToken,
      StringToken,
      0,
      0,
      IP4_MIN_SIZE,
      IP4_MAX_SIZE,
      NULL
      );

    //
    // Create iSCSIInitiatorGateway Keyword.
    //
    UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_INITIATOR_GATE_PROMPT%d", Index);
    StringToken =  HiiSetString (
                     mCallbackInfo->RegisteredHandle,
                     0,
                     StringId,
                     NULL
                     );
    UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIInitiatorGateway:%d", Index);
    HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
    HiiCreateStringOpCode (
      StartOpCodeHandle,
      (EFI_QUESTION_ID) (ATTEMPT_INITIATOR_GATE_WAY_QUESTION_ID + (Index - 1)),
      CONFIGURATION_VARSTORE_ID,
      (UINT16) (ATTEMPT_INITIATOR_GATE_WAY_VAR_OFFSET + sizeof (KEYWORD_STR) * (Index - 1)),
      StringToken,
      StringToken,
      0,
      0,
      IP4_MIN_SIZE,
      IP4_MAX_SIZE,
      NULL
      );

    //
    // Create iSCSITargetInfoViaDHCP Keyword.
    //
    UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_TARGET_VIA_DHCP_PROMPT%d", Index);
    StringToken =  HiiSetString (
                     mCallbackInfo->RegisteredHandle,
                     0,
                     StringId,
                     NULL
                     );
    UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSITargetInfoViaDHCP:%d", Index);
    HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
    HiiCreateNumericOpCode (
    StartOpCodeHandle,
    (EFI_QUESTION_ID) (ATTEMPT_TARGET_VIA_DHCP_QUESTION_ID + (Index - 1)),
    CONFIGURATION_VARSTORE_ID,
    (UINT16) (ATTEMPT_TARGET_VIA_DHCP_VAR_OFFSET + (Index - 1)),
    StringToken,
    StringToken,
    0,
    0,
    0,
    1,
    0,
    NULL
    );

    //
    // Create iSCSITargetTcpPort Keyword.
    //
    UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_TARGET_TCP_PORT_PROMPT%d", Index);
    StringToken =  HiiSetString (
                     mCallbackInfo->RegisteredHandle,
                     0,
                     StringId,
                     NULL
                     );
    UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSITargetTcpPort:%d", Index);
    HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
    HiiCreateNumericOpCode (
      StartOpCodeHandle,
      (EFI_QUESTION_ID) (ATTEMPT_TARGET_TCP_PORT_QUESTION_ID + (Index - 1)),
      CONFIGURATION_VARSTORE_ID,
      (UINT16) (ATTEMPT_TARGET_TCP_PORT_VAR_OFFSET + 2 * (Index - 1)),
      StringToken,
      StringToken,
      0,
      EFI_IFR_NUMERIC_SIZE_2,
      TARGET_PORT_MIN_NUM,
      TARGET_PORT_MAX_NUM,
      0,
      NULL
      );

    //
    // Create iSCSITargetName Keyword.
    //
    UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_TARGET_NAME_PROMPT%d", Index);
    StringToken =  HiiSetString (
                     mCallbackInfo->RegisteredHandle,
                     0,
                     StringId,
                     NULL
                     );
    UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSITargetName:%d", Index);
    HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
    HiiCreateStringOpCode (
      StartOpCodeHandle,
      (EFI_QUESTION_ID) (ATTEMPT_TARGET_NAME_QUESTION_ID + (Index - 1)),
      CONFIGURATION_VARSTORE_ID,
      (UINT16) (ATTEMPT_TARGET_NAME_VAR_OFFSET + sizeof (KEYWORD_STR) * (Index - 1)),
      StringToken,
      StringToken,
      0,
      0,
      ISCSI_NAME_IFR_MIN_SIZE,
      ISCSI_NAME_IFR_MAX_SIZE,
      NULL
      );

    //
    // Create iSCSITargetIpAddress Keyword.
    //
    UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_TARGET_IP_ADDRESS_PROMPT%d", Index);
    StringToken =  HiiSetString (
                     mCallbackInfo->RegisteredHandle,
                     0,
                     StringId,
                     NULL
                     );
    UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSITargetIpAddress:%d", Index);
    HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
    HiiCreateStringOpCode (
      StartOpCodeHandle,
      (EFI_QUESTION_ID) (ATTEMPT_TARGET_IP_ADDRESS_QUESTION_ID + (Index - 1)),
      CONFIGURATION_VARSTORE_ID,
      (UINT16) (ATTEMPT_TARGET_IP_ADDRESS_VAR_OFFSET + sizeof (KEYWORD_STR) * (Index - 1)),
      StringToken,
      StringToken,
      0,
      0,
      IP_MIN_SIZE,
      IP_MAX_SIZE,
      NULL
      );

    //
    // Create iSCSILUN Keyword.
    //
    UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_LUN_PROMPT%d", Index);
    StringToken =  HiiSetString (
                     mCallbackInfo->RegisteredHandle,
                     0,
                     StringId,
                     NULL
                     );
    UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSILUN:%d", Index);
    HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
    HiiCreateStringOpCode (
      StartOpCodeHandle,
      (EFI_QUESTION_ID) (ATTEMPT_LUN_QUESTION_ID + (Index - 1)),
      CONFIGURATION_VARSTORE_ID,
      (UINT16) (ATTEMPT_LUN_VAR_OFFSET + sizeof (KEYWORD_STR) * (Index - 1)),
      StringToken,
      StringToken,
      0,
      0,
      LUN_MIN_SIZE,
      LUN_MAX_SIZE,
      NULL
      );

    //
    // Create iSCSIAuthenticationMethod Keyword.
    //
    UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_AUTHENTICATION_METHOD_PROMPT%d", Index);
    StringToken =  HiiSetString (
                     mCallbackInfo->RegisteredHandle,
                     0,
                     StringId,
                     NULL
                     );
    UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIAuthenticationMethod:%d", Index);
    HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
    HiiCreateNumericOpCode (
    StartOpCodeHandle,
    (EFI_QUESTION_ID) (ATTEMPT_AUTHENTICATION_METHOD_QUESTION_ID + (Index - 1)),
    CONFIGURATION_VARSTORE_ID,
    (UINT16) (ATTEMPT_AUTHENTICATION_METHOD_VAR_OFFSET + (Index - 1)),
    StringToken,
    StringToken,
    0,
    0,
    0,
    1,
    0,
    NULL
    );

    //
    // Create iSCSIChapType Keyword.
    //
    UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_CHARTYPE_PROMPT%d", Index);
    StringToken =  HiiSetString (
                     mCallbackInfo->RegisteredHandle,
                     0,
                     StringId,
                     NULL
                     );
    UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIChapType:%d", Index);
    HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
    HiiCreateNumericOpCode (
    StartOpCodeHandle,
    (EFI_QUESTION_ID) (ATTEMPT_CHARTYPE_QUESTION_ID + (Index - 1)),
    CONFIGURATION_VARSTORE_ID,
    (UINT16) (ATTEMPT_CHARTYPE_VAR_OFFSET + (Index - 1)),
    StringToken,
    StringToken,
    0,
    0,
    0,
    1,
    0,
    NULL
    );

    //
    // Create iSCSIChapUsername Keyword.
    //
    UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_CHAR_USER_NAME_PROMPT%d", Index);
    StringToken =  HiiSetString (
                     mCallbackInfo->RegisteredHandle,
                     0,
                     StringId,
                     NULL
                     );
    UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIChapUsername:%d", Index);
    HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
    HiiCreateStringOpCode (
      StartOpCodeHandle,
      (EFI_QUESTION_ID) (ATTEMPT_CHAR_USER_NAME_QUESTION_ID + (Index - 1)),
      CONFIGURATION_VARSTORE_ID,
      (UINT16) (ATTEMPT_CHAR_USER_NAME_VAR_OFFSET + sizeof (KEYWORD_STR) * (Index - 1)),
      StringToken,
      StringToken,
      0,
      0,
      0,
      ISCSI_CHAP_NAME_MAX_LEN,
      NULL
      );

    //
    // Create iSCSIChapSecret Keyword.
    //
    UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_CHAR_SECRET_PROMPT%d", Index);
    StringToken =  HiiSetString (
                     mCallbackInfo->RegisteredHandle,
                     0,
                     StringId,
                     NULL
                     );
    UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIChapSecret:%d", Index);
    HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
    HiiCreateStringOpCode (
      StartOpCodeHandle,
      (EFI_QUESTION_ID) (ATTEMPT_CHAR_SECRET_QUESTION_ID + (Index - 1)),
      CONFIGURATION_VARSTORE_ID,
      (UINT16) (ATTEMPT_CHAR_SECRET_VAR_OFFSET + sizeof (KEYWORD_STR) * (Index - 1)),
      StringToken,
      StringToken,
      0,
      0,
      ISCSI_CHAP_SECRET_MIN_LEN,
      ISCSI_CHAP_SECRET_MAX_LEN,
      NULL
      );

    //
    // Create iSCSIReverseChapUsername Keyword.
    //
    UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_CHAR_REVERSE_USER_NAME_PROMPT%d", Index);
    StringToken =  HiiSetString (
                     mCallbackInfo->RegisteredHandle,
                     0,
                     StringId,
                     NULL
                     );
    UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIReverseChapUsername:%d", Index);
    HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
    HiiCreateStringOpCode (
      StartOpCodeHandle,
      (EFI_QUESTION_ID) (ATTEMPT_CHAR_REVERSE_USER_NAME_QUESTION_ID + (Index - 1)),
      CONFIGURATION_VARSTORE_ID,
      (UINT16) (ATTEMPT_CHAR_REVERSE_USER_NAME_VAR_OFFSET + sizeof (KEYWORD_STR) * (Index - 1)),
      StringToken,
      StringToken,
      0,
      0,
      0,
      ISCSI_CHAP_NAME_MAX_LEN,
      NULL
      );

    //
    // Create iSCSIReverseChapSecret Keyword.
    //
    UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_CHAR_REVERSE_SECRET_PROMPT%d", Index);
    StringToken =  HiiSetString (
                     mCallbackInfo->RegisteredHandle,
                     0,
                     StringId,
                     NULL
                     );
    UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIReverseChapSecret:%d", Index);
    HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
    HiiCreateStringOpCode (
      StartOpCodeHandle,
      (EFI_QUESTION_ID) (ATTEMPT_CHAR_REVERSE_SECRET_QUESTION_ID + (Index - 1)),
      CONFIGURATION_VARSTORE_ID,
      (UINT16) (ATTEMPT_CHAR_REVERSE_SECRET_VAR_OFFSET + sizeof (KEYWORD_STR) * (Index - 1)),
      StringToken,
      StringToken,
      0,
      0,
      ISCSI_CHAP_SECRET_MIN_LEN,
      ISCSI_CHAP_SECRET_MAX_LEN,
      NULL
      );
  }

  Status = HiiUpdateForm (
             mCallbackInfo->RegisteredHandle, // HII handle
             &gIScsiConfigGuid,               // Formset GUID
             FORMID_ATTEMPT_FORM,             // Form ID
             StartOpCodeHandle,               // Label for where to insert opcodes
             EndOpCodeHandle                  // Replace data
             );

  HiiFreeOpCodeHandle (StartOpCodeHandle);
  HiiFreeOpCodeHandle (EndOpCodeHandle);

  return Status;
}

/**

  Free the attempt configure data variable.

**/
VOID
IScsiCleanAttemptVariable (
  IN   VOID
)
{
  ISCSI_ATTEMPT_CONFIG_NVDATA   *AttemptConfigData;
  UINT8                         *AttemptConfigOrder;
  UINTN                         AttemptConfigOrderSize;
  UINTN                         Index;

  //
  // Get the initialized attempt order.
  //
  AttemptConfigOrder = IScsiGetVariableAndSize (
                         L"InitialAttemptOrder",
                         &gIScsiConfigGuid,
                         &AttemptConfigOrderSize
                         );
  if (AttemptConfigOrder == NULL || AttemptConfigOrderSize == 0) {
    return;
  }

  for (Index = 1; Index < AttemptConfigOrderSize / sizeof (UINT8); Index++) {
    UnicodeSPrint (
      mPrivate->PortString,
      (UINTN) ISCSI_NAME_IFR_MAX_SIZE,
      L"Attempt %d",
      Index
      );

    GetVariable2 (
      mPrivate->PortString,
      &gEfiIScsiInitiatorNameProtocolGuid,
      (VOID**)&AttemptConfigData,
      NULL
      );

    if (AttemptConfigData != NULL) {
      gRT->SetVariable (
             mPrivate->PortString,
             &gEfiIScsiInitiatorNameProtocolGuid,
             0,
             0,
             NULL
             );
    }
  }
  return;
}

/**
  Get the recorded NIC info from global structure by the Index.

  @param[in]  NicIndex          The index indicates the position of NIC info.

  @return Pointer to the NIC info, or NULL if not found.

**/
ISCSI_NIC_INFO *
IScsiGetNicInfoByIndex (
  IN UINT8      NicIndex
  )
{
  LIST_ENTRY        *Entry;
  ISCSI_NIC_INFO    *NicInfo;

  NET_LIST_FOR_EACH (Entry, &mPrivate->NicInfoList) {
    NicInfo = NET_LIST_USER_STRUCT (Entry, ISCSI_NIC_INFO, Link);
    if (NicInfo->NicIndex == NicIndex) {
      return NicInfo;
    }
  }

  return NULL;
}


/**
  Get the NIC's PCI location and return it according to the composited
  format defined in iSCSI Boot Firmware Table.

  @param[in]   Controller        The handle of the controller.
  @param[out]  Bus               The bus number.
  @param[out]  Device            The device number.
  @param[out]  Function          The function number.

  @return      The composited representation of the NIC PCI location.

**/
UINT16
IScsiGetNICPciLocation (
  IN EFI_HANDLE  Controller,
  OUT UINTN      *Bus,
  OUT UINTN      *Device,
  OUT UINTN      *Function
  )
{
  EFI_STATUS                Status;
  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
  EFI_HANDLE                PciIoHandle;
  EFI_PCI_IO_PROTOCOL       *PciIo;
  UINTN                     Segment;

  Status = gBS->HandleProtocol (
                  Controller,
                  &gEfiDevicePathProtocolGuid,
                  (VOID **) &DevicePath
                  );
  if (EFI_ERROR (Status)) {
    return 0;
  }

  Status = gBS->LocateDevicePath (
                  &gEfiPciIoProtocolGuid,
                  &DevicePath,
                  &PciIoHandle
                  );
  if (EFI_ERROR (Status)) {
    return 0;
  }

  Status = gBS->HandleProtocol (PciIoHandle, &gEfiPciIoProtocolGuid, (VOID **) &PciIo);
  if (EFI_ERROR (Status)) {
    return 0;
  }

  Status = PciIo->GetLocation (PciIo, &Segment, Bus, Device, Function);
  if (EFI_ERROR (Status)) {
    return 0;
  }

  return (UINT16) ((*Bus << 8) | (*Device << 3) | *Function);
}


/**
  Read the EFI variable (VendorGuid/Name) and return a dynamically allocated
  buffer, and the size of the buffer. If failure, return NULL.

  @param[in]   Name                   String part of EFI variable name.
  @param[in]   VendorGuid             GUID part of EFI variable name.
  @param[out]  VariableSize           Returns the size of the EFI variable that was read.

  @return Dynamically allocated memory that contains a copy of the EFI variable.
  @return Caller is responsible freeing the buffer.
  @retval NULL                   Variable was not read.

**/
VOID *
IScsiGetVariableAndSize (
  IN  CHAR16              *Name,
  IN  EFI_GUID            *VendorGuid,
  OUT UINTN               *VariableSize
  )
{
  EFI_STATUS  Status;
  UINTN       BufferSize;
  VOID        *Buffer;

  Buffer = NULL;

  //
  // Pass in a zero size buffer to find the required buffer size.
  //
  BufferSize  = 0;
  Status      = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer);
  if (Status == EFI_BUFFER_TOO_SMALL) {
    //
    // Allocate the buffer to return
    //
    Buffer = AllocateZeroPool (BufferSize);
    if (Buffer == NULL) {
      return NULL;
    }
    //
    // Read variable into the allocated buffer.
    //
    Status = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer);
    if (EFI_ERROR (Status)) {
      BufferSize = 0;
    }
  }

  *VariableSize = BufferSize;
  return Buffer;
}


/**
  Create the iSCSI driver data.

  @param[in] Image      The handle of the driver image.
  @param[in] Controller The handle of the controller.

  @return The iSCSI driver data created.
  @retval NULL Other errors as indicated.

**/
ISCSI_DRIVER_DATA *
IScsiCreateDriverData (
  IN EFI_HANDLE  Image,
  IN EFI_HANDLE  Controller
  )
{
  ISCSI_DRIVER_DATA *Private;
  EFI_STATUS        Status;

  Private = AllocateZeroPool (sizeof (ISCSI_DRIVER_DATA));
  if (Private == NULL) {
    return NULL;
  }

  Private->Signature  = ISCSI_DRIVER_DATA_SIGNATURE;
  Private->Image      = Image;
  Private->Controller = Controller;
  Private->Session    = NULL;

  //
  // Create an event to be signaled when the BS to RT transition is triggerd so
  // as to abort the iSCSI session.
  //
  Status = gBS->CreateEventEx (
                  EVT_NOTIFY_SIGNAL,
                  TPL_CALLBACK,
                  IScsiOnExitBootService,
                  Private,
                  &gEfiEventExitBootServicesGuid,
                  &Private->ExitBootServiceEvent
                  );
  if (EFI_ERROR (Status)) {
    FreePool (Private);
    return NULL;
  }

  Private->ExtScsiPassThruHandle = NULL;
  CopyMem(&Private->IScsiExtScsiPassThru, &gIScsiExtScsiPassThruProtocolTemplate, sizeof(EFI_EXT_SCSI_PASS_THRU_PROTOCOL));

  //
  // 0 is designated to the TargetId, so use another value for the AdapterId.
  //
  Private->ExtScsiPassThruMode.AdapterId  = 2;
  Private->ExtScsiPassThruMode.Attributes = EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_PHYSICAL | EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_LOGICAL;
  Private->ExtScsiPassThruMode.IoAlign    = 4;
  Private->IScsiExtScsiPassThru.Mode      = &Private->ExtScsiPassThruMode;

  return Private;
}


/**
  Clean the iSCSI driver data.

  @param[in]              Private The iSCSI driver data.

  @retval EFI_SUCCESS     The clean operation is successful.
  @retval Others          Other errors as indicated.

**/
EFI_STATUS
IScsiCleanDriverData (
  IN ISCSI_DRIVER_DATA  *Private
  )
{
  EFI_STATUS            Status;

  Status = EFI_SUCCESS;

  if (Private->DevicePath != NULL) {
    Status = gBS->UninstallProtocolInterface (
                    Private->ExtScsiPassThruHandle,
                    &gEfiDevicePathProtocolGuid,
                    Private->DevicePath
                    );
    if (EFI_ERROR (Status)) {
      goto EXIT;
    }

    FreePool (Private->DevicePath);
  }

  if (Private->ExtScsiPassThruHandle != NULL) {
    Status = gBS->UninstallProtocolInterface (
                    Private->ExtScsiPassThruHandle,
                    &gEfiExtScsiPassThruProtocolGuid,
                    &Private->IScsiExtScsiPassThru
                    );
    if (!EFI_ERROR (Status)) {
      mPrivate->OneSessionEstablished = FALSE;
    }
  }

EXIT:

  gBS->CloseEvent (Private->ExitBootServiceEvent);

  mCallbackInfo->Current = NULL;

  FreePool (Private);
  return Status;
}

/**
  Check wheather the Controller handle is configured to use DHCP protocol.

  @param[in]  Controller           The handle of the controller.
  @param[in]  IpVersion            IP_VERSION_4 or IP_VERSION_6.
  
  @retval TRUE                     The handle of the controller need the Dhcp protocol.
  @retval FALSE                    The handle of the controller does not need the Dhcp protocol.
  
**/
BOOLEAN
IScsiDhcpIsConfigured (
  IN EFI_HANDLE  Controller,
  IN UINT8       IpVersion
  )
{
  ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptTmp;
  UINT8                       *AttemptConfigOrder;
  UINTN                       AttemptConfigOrderSize;
  UINTN                       Index;
  EFI_STATUS                  Status;
  EFI_MAC_ADDRESS             MacAddr;
  UINTN                       HwAddressSize;
  UINT16                      VlanId;
  CHAR16                      MacString[ISCSI_MAX_MAC_STRING_LEN];
  CHAR16                      AttemptMacString[ISCSI_MAX_MAC_STRING_LEN];
  CHAR16                      AttemptName[ISCSI_NAME_IFR_MAX_SIZE];
  
  AttemptConfigOrder = IScsiGetVariableAndSize (
                         L"AttemptOrder",
                         &gIScsiConfigGuid,
                         &AttemptConfigOrderSize
                         );
  if (AttemptConfigOrder == NULL || AttemptConfigOrderSize == 0) {
    return FALSE;
  }
  
  //
  // Get MAC address of this network device.
  //
  Status = NetLibGetMacAddress (Controller, &MacAddr, &HwAddressSize);
  if(EFI_ERROR (Status)) {
    return FALSE;
  }
  //
  // Get VLAN ID of this network device.
  //
  VlanId = NetLibGetVlanId (Controller);
  IScsiMacAddrToStr (&MacAddr, (UINT32) HwAddressSize, VlanId, MacString);
  
  for (Index = 0; Index < AttemptConfigOrderSize / sizeof (UINT8); Index++) {
    UnicodeSPrint (
      AttemptName,
      (UINTN) 128,
      L"Attempt %d",
      (UINTN) AttemptConfigOrder[Index]
      );
    Status = GetVariable2 (
               AttemptName,
               &gEfiIScsiInitiatorNameProtocolGuid,
               (VOID**)&AttemptTmp,
               NULL
               );
    if(AttemptTmp == NULL || EFI_ERROR (Status)) {
      continue;
    }
    
    ASSERT (AttemptConfigOrder[Index] == AttemptTmp->AttemptConfigIndex);

    if (AttemptTmp->SessionConfigData.Enabled == ISCSI_DISABLED) {
      FreePool (AttemptTmp);
      continue;
    }

    if (AttemptTmp->SessionConfigData.IpMode != IP_MODE_AUTOCONFIG && 
        AttemptTmp->SessionConfigData.IpMode != ((IpVersion == IP_VERSION_4) ? IP_MODE_IP4 : IP_MODE_IP6)) {
      FreePool (AttemptTmp);
      continue;
    }

    AsciiStrToUnicodeStrS (AttemptTmp->MacString, AttemptMacString, sizeof (AttemptMacString) / sizeof (AttemptMacString[0]));

    if (AttemptTmp->Actived == ISCSI_ACTIVE_DISABLED || StrCmp (MacString, AttemptMacString)) {
      continue;
    }

    if(AttemptTmp->SessionConfigData.IpMode == IP_MODE_AUTOCONFIG ||
       AttemptTmp->SessionConfigData.InitiatorInfoFromDhcp == TRUE ||
       AttemptTmp->SessionConfigData.TargetInfoFromDhcp == TRUE) { 
      FreePool (AttemptTmp);
      FreePool (AttemptConfigOrder);
      return TRUE;
    }

    FreePool (AttemptTmp);
  }
  
  FreePool (AttemptConfigOrder);
  return FALSE;
}

/**
  Check whether the Controller handle is configured to use DNS protocol.

  @param[in]  Controller           The handle of the controller.
  
  @retval TRUE                     The handle of the controller need the Dns protocol.
  @retval FALSE                    The handle of the controller does not need the Dns protocol.
  
**/
BOOLEAN
IScsiDnsIsConfigured (
  IN EFI_HANDLE  Controller
  )
{
  ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptTmp;
  UINT8                       *AttemptConfigOrder;
  UINTN                       AttemptConfigOrderSize;
  UINTN                       Index;
  EFI_STATUS                  Status;
  EFI_MAC_ADDRESS             MacAddr;
  UINTN                       HwAddressSize;
  UINT16                      VlanId;
  CHAR16                      AttemptMacString[ISCSI_MAX_MAC_STRING_LEN];
  CHAR16                      MacString[ISCSI_MAX_MAC_STRING_LEN];
  CHAR16                      AttemptName[ISCSI_NAME_IFR_MAX_SIZE];
  
  AttemptConfigOrder = IScsiGetVariableAndSize (
                         L"AttemptOrder",
                         &gIScsiConfigGuid,
                         &AttemptConfigOrderSize
                         );
  if (AttemptConfigOrder == NULL || AttemptConfigOrderSize == 0) {
    return FALSE;
  }
  
  //
  // Get MAC address of this network device.
  //
  Status = NetLibGetMacAddress (Controller, &MacAddr, &HwAddressSize);
  if(EFI_ERROR (Status)) {
    return FALSE;
  }
  //
  // Get VLAN ID of this network device.
  //
  VlanId = NetLibGetVlanId (Controller);
  IScsiMacAddrToStr (&MacAddr, (UINT32) HwAddressSize, VlanId, MacString);
  
  for (Index = 0; Index < AttemptConfigOrderSize / sizeof (UINT8); Index++) {
    UnicodeSPrint (
      AttemptName,
      (UINTN) 128,
      L"Attempt %d",
      (UINTN) AttemptConfigOrder[Index]
      );

    Status = GetVariable2 (
               AttemptName,
               &gEfiIScsiInitiatorNameProtocolGuid,
               (VOID**)&AttemptTmp,
               NULL
               );
    if(AttemptTmp == NULL || EFI_ERROR (Status)) {
      continue;
    }
    
    ASSERT (AttemptConfigOrder[Index] == AttemptTmp->AttemptConfigIndex);

    AsciiStrToUnicodeStrS (AttemptTmp->MacString, AttemptMacString, sizeof (AttemptMacString) / sizeof (AttemptMacString[0]));

    if (AttemptTmp->SessionConfigData.Enabled == ISCSI_DISABLED || StrCmp (MacString, AttemptMacString)) {
      FreePool (AttemptTmp);
      continue;
    }
    
    if (AttemptTmp->SessionConfigData.DnsMode) {
      FreePool (AttemptTmp);
      FreePool (AttemptConfigOrder);
      return TRUE;
    } else {
      FreePool (AttemptTmp);
      continue;
    }

  }

  FreePool (AttemptConfigOrder);
  return FALSE;

}

/**
  Get the various configuration data.

  @param[in]  Private   The iSCSI driver data.

  @retval EFI_SUCCESS            The configuration data is retrieved.
  @retval EFI_NOT_FOUND          This iSCSI driver is not configured yet.
  @retval EFI_OUT_OF_RESOURCES   Failed to allocate memory.

**/
EFI_STATUS
IScsiGetConfigData (
  IN ISCSI_DRIVER_DATA  *Private
  )
{
  EFI_STATUS                  Status;
  CHAR16                      MacString[ISCSI_MAX_MAC_STRING_LEN];
  CHAR16                      AttemptMacString[ISCSI_MAX_MAC_STRING_LEN];
  UINTN                       Index;
  ISCSI_NIC_INFO              *NicInfo;
  ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;
  ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptTmp;
  UINT8                       *AttemptConfigOrder;
  UINTN                       AttemptConfigOrderSize;
  CHAR16                      IScsiMode[64];
  CHAR16                      IpMode[64];

  //
  // There should be at least one attempt configured.
  //
  AttemptConfigOrder = IScsiGetVariableAndSize (
                         L"AttemptOrder",
                         &gIScsiConfigGuid,
                         &AttemptConfigOrderSize
                         );
  if (AttemptConfigOrder == NULL || AttemptConfigOrderSize == 0) {
    return EFI_NOT_FOUND;
  }

  //
  // Get the iSCSI Initiator Name.
  //
  mPrivate->InitiatorNameLength  = ISCSI_NAME_MAX_SIZE;
  Status = gIScsiInitiatorName.Get (
                                 &gIScsiInitiatorName,
                                 &mPrivate->InitiatorNameLength,
                                 mPrivate->InitiatorName
                                 );
  if (EFI_ERROR (Status)) {
    return Status;
  }

  //
  // Get the normal configuration.
  //
  for (Index = 0; Index < AttemptConfigOrderSize / sizeof (UINT8); Index++) {

    //
    // Check whether the attempt exists in AttemptConfig.
    //
    AttemptTmp = IScsiConfigGetAttemptByConfigIndex (AttemptConfigOrder[Index]);    
    if (AttemptTmp != NULL && AttemptTmp->SessionConfigData.Enabled == ISCSI_DISABLED) {
      continue;
    } else if (AttemptTmp != NULL && AttemptTmp->SessionConfigData.Enabled != ISCSI_DISABLED) {
      //
      // Check the autoconfig path to see whether it should be retried.
      //
      if (AttemptTmp->SessionConfigData.IpMode == IP_MODE_AUTOCONFIG &&
          !AttemptTmp->AutoConfigureSuccess) {
        if (mPrivate->Ipv6Flag &&
            AttemptTmp->AutoConfigureMode == IP_MODE_AUTOCONFIG_IP6) {
          //
          // Autoconfigure for IP6 already attempted but failed. Do not try again.
          //
          continue;
        } else if (!mPrivate->Ipv6Flag &&
                   AttemptTmp->AutoConfigureMode == IP_MODE_AUTOCONFIG_IP4) {
          //
          // Autoconfigure for IP4  already attempted but failed. Do not try again.
          //
          continue;
        } else {
          //
          // Try another approach for this autoconfigure path.
          //
          AttemptTmp->AutoConfigureMode =
            (UINT8) (mPrivate->Ipv6Flag ? IP_MODE_AUTOCONFIG_IP6 : IP_MODE_AUTOCONFIG_IP4);
          AttemptTmp->SessionConfigData.InitiatorInfoFromDhcp = TRUE;
          AttemptTmp->SessionConfigData.TargetInfoFromDhcp    = TRUE;
          AttemptTmp->DhcpSuccess                             = FALSE;

          //
          // Get some information from the dhcp server.
          //
          if (!mPrivate->Ipv6Flag) {
            Status = IScsiDoDhcp (Private->Image, Private->Controller, AttemptTmp);
            if (!EFI_ERROR (Status)) {
              AttemptTmp->DhcpSuccess = TRUE;
            }
          } else {
            Status = IScsiDoDhcp6 (Private->Image, Private->Controller, AttemptTmp);
            if (!EFI_ERROR (Status)) {
              AttemptTmp->DhcpSuccess = TRUE;
            }
          }

          //
          // Refresh the state of this attempt to NVR.
          //
          UnicodeSPrint (
            mPrivate->PortString,
            (UINTN) ISCSI_NAME_IFR_MAX_SIZE,
            L"Attempt %d",
            (UINTN) AttemptTmp->AttemptConfigIndex
            );

          gRT->SetVariable (
                 mPrivate->PortString,
                 &gEfiIScsiInitiatorNameProtocolGuid,
                 ISCSI_CONFIG_VAR_ATTR,
                 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA),
                 AttemptTmp
                 );

          continue;
        }
      } else if (AttemptTmp->SessionConfigData.InitiatorInfoFromDhcp && !AttemptTmp->ValidPath) {
        //
        // Get DHCP information for already added, but failed, attempt.
        //
        AttemptTmp->DhcpSuccess = FALSE;
        if (!mPrivate->Ipv6Flag && (AttemptTmp->SessionConfigData.IpMode == IP_MODE_IP4)) {
          Status = IScsiDoDhcp (Private->Image, Private->Controller, AttemptTmp);
          if (!EFI_ERROR (Status)) {
            AttemptTmp->DhcpSuccess = TRUE;
          }
        } else if (mPrivate->Ipv6Flag && (AttemptTmp->SessionConfigData.IpMode == IP_MODE_IP6)) {
          Status = IScsiDoDhcp6 (Private->Image, Private->Controller, AttemptTmp);
          if (!EFI_ERROR (Status)) {
            AttemptTmp->DhcpSuccess = TRUE;
          }
        }

        //
        // Refresh the state of this attempt to NVR.
        //
        UnicodeSPrint (
          mPrivate->PortString,
          (UINTN) ISCSI_NAME_IFR_MAX_SIZE,
          L"Attempt %d",
          (UINTN) AttemptTmp->AttemptConfigIndex
          );

        gRT->SetVariable (
               mPrivate->PortString,
               &gEfiIScsiInitiatorNameProtocolGuid,
               ISCSI_CONFIG_VAR_ATTR,
               sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA),
               AttemptTmp
               );

        continue;

      } else {
        continue;
      }
    }

    //
    // This attempt does not exist in AttemptConfig. Try to add a new one.
    //

    NicInfo = IScsiGetNicInfoByIndex (mPrivate->CurrentNic);
    ASSERT (NicInfo != NULL);
    IScsiMacAddrToStr (&NicInfo->PermanentAddress, NicInfo->HwAddressSize, NicInfo->VlanId, MacString);
    UnicodeSPrint (
      mPrivate->PortString,
      (UINTN) ISCSI_NAME_IFR_MAX_SIZE,
      L"Attempt %d",
      (UINTN) AttemptConfigOrder[Index]
      );

    GetVariable2 (
      mPrivate->PortString,
      &gEfiIScsiInitiatorNameProtocolGuid,
      (VOID**)&AttemptConfigData,
      NULL
      );
    AsciiStrToUnicodeStrS (AttemptConfigData->MacString, AttemptMacString, sizeof (AttemptMacString) / sizeof (AttemptMacString[0]));

    if (AttemptConfigData == NULL || AttemptConfigData->Actived == ISCSI_ACTIVE_DISABLED ||
        StrCmp (MacString, AttemptMacString)) {
      continue;
    }

    ASSERT (AttemptConfigOrder[Index] == AttemptConfigData->AttemptConfigIndex);

    AttemptConfigData->NicIndex      = NicInfo->NicIndex;
    AttemptConfigData->DhcpSuccess   = FALSE;
    AttemptConfigData->ValidiBFTPath = (BOOLEAN) (mPrivate->EnableMpio ? TRUE : FALSE);
    AttemptConfigData->ValidPath     = FALSE;

    if (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_AUTOCONFIG) {
      AttemptConfigData->SessionConfigData.InitiatorInfoFromDhcp = TRUE;
      AttemptConfigData->SessionConfigData.TargetInfoFromDhcp    = TRUE;

      AttemptConfigData->AutoConfigureMode =
        (UINT8) (mPrivate->Ipv6Flag ? IP_MODE_AUTOCONFIG_IP6 : IP_MODE_AUTOCONFIG_IP4);
      AttemptConfigData->AutoConfigureSuccess = FALSE;
    }
    
    //
    // Get some information from dhcp server.
    //
    if (AttemptConfigData->SessionConfigData.Enabled != ISCSI_DISABLED &&
        AttemptConfigData->SessionConfigData.InitiatorInfoFromDhcp) {

      if (!mPrivate->Ipv6Flag &&
          (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_IP4 ||
           AttemptConfigData->AutoConfigureMode == IP_MODE_AUTOCONFIG_IP4)) {
        Status = IScsiDoDhcp (Private->Image, Private->Controller, AttemptConfigData);
        if (!EFI_ERROR (Status)) {
          AttemptConfigData->DhcpSuccess = TRUE;
        }
      } else if (mPrivate->Ipv6Flag &&
                (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_IP6 ||
                 AttemptConfigData->AutoConfigureMode == IP_MODE_AUTOCONFIG_IP6)) {
        Status = IScsiDoDhcp6 (Private->Image, Private->Controller, AttemptConfigData);
        if (!EFI_ERROR (Status)) {
          AttemptConfigData->DhcpSuccess = TRUE;
        }
      }

      //
      // Refresh the state of this attempt to NVR.
      //
      UnicodeSPrint (
        mPrivate->PortString,
        (UINTN) ISCSI_NAME_IFR_MAX_SIZE,
        L"Attempt %d",
        (UINTN) AttemptConfigData->AttemptConfigIndex
        );

      gRT->SetVariable (
             mPrivate->PortString,
             &gEfiIScsiInitiatorNameProtocolGuid,
             ISCSI_CONFIG_VAR_ATTR,
             sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA),
             AttemptConfigData
             );
    }

    //
    // Update Attempt Help Info.
    //

    if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_DISABLED) {
      UnicodeSPrint (IScsiMode, 64, L"Disabled");
    } else if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED) {
      UnicodeSPrint (IScsiMode, 64, L"Enabled");
    } else if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED_FOR_MPIO) {
      UnicodeSPrint (IScsiMode, 64, L"Enabled for MPIO");
    }

    if (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_IP4) {
      UnicodeSPrint (IpMode, 64, L"IP4");
    } else if (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_IP6) {
      UnicodeSPrint (IpMode, 64, L"IP6");
    } else if (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_AUTOCONFIG) {
      UnicodeSPrint (IpMode, 64, L"Autoconfigure");
    }

    UnicodeSPrint (
      mPrivate->PortString,
      (UINTN) ISCSI_NAME_IFR_MAX_SIZE,
      L"MAC: %s, PFA: Bus %d | Dev %d | Func %d, iSCSI mode: %s, IP version: %s",
      MacString,
      NicInfo->BusNumber,
      NicInfo->DeviceNumber,
      NicInfo->FunctionNumber,
      IScsiMode,
      IpMode
      );

    AttemptConfigData->AttemptTitleHelpToken = HiiSetString (
                                                 mCallbackInfo->RegisteredHandle,
                                                 0,
                                                 mPrivate->PortString,
                                                 NULL
                                                 );
    if (AttemptConfigData->AttemptTitleHelpToken == 0) {
      return EFI_OUT_OF_RESOURCES;
    }

    //
    // Record the attempt in global link list.
    //
    InsertTailList (&mPrivate->AttemptConfigs, &AttemptConfigData->Link);
    mPrivate->AttemptCount++;

    if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED_FOR_MPIO) {
      mPrivate->MpioCount++;
      mPrivate->EnableMpio = TRUE;

      if (AttemptConfigData->AuthenticationType == ISCSI_AUTH_TYPE_KRB) {
        mPrivate->Krb5MpioCount++;
      }
    } else if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED) {
      mPrivate->SinglePathCount++;
    }
  }

  //
  // Reorder the AttemptConfig by the configured order.
  //
  for (Index = 0; Index < AttemptConfigOrderSize / sizeof (UINT8); Index++) {
    AttemptConfigData = IScsiConfigGetAttemptByConfigIndex (AttemptConfigOrder[Index]);
    if (AttemptConfigData == NULL) {
      continue;
    }

    RemoveEntryList (&AttemptConfigData->Link);
    InsertTailList (&mPrivate->AttemptConfigs, &AttemptConfigData->Link);
  }

  //
  // Update the Main Form.
  //
  IScsiConfigUpdateAttempt ();

  FreePool (AttemptConfigOrder);

  //
  //  There should be at least one attempt configuration.
  //
  if (!mPrivate->EnableMpio) {
    if (mPrivate->SinglePathCount == 0) {
      return EFI_NOT_FOUND;
    }
    mPrivate->ValidSinglePathCount = mPrivate->SinglePathCount;
  }

  return EFI_SUCCESS;
}


/**
  Get the device path of the iSCSI tcp connection and update it.

  @param  Session                The iSCSI session.

  @return The updated device path.
  @retval NULL Other errors as indicated.

**/
EFI_DEVICE_PATH_PROTOCOL *
IScsiGetTcpConnDevicePath (
  IN ISCSI_SESSION      *Session
  )
{
  ISCSI_CONNECTION          *Conn;
  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
  EFI_STATUS                Status;
  EFI_DEV_PATH              *DPathNode;
  UINTN                     PathLen;

  if (Session->State != SESSION_STATE_LOGGED_IN) {
    return NULL;
  }

  Conn = NET_LIST_USER_STRUCT_S (
           Session->Conns.ForwardLink,
           ISCSI_CONNECTION,
           Link,
           ISCSI_CONNECTION_SIGNATURE
           );

  Status = gBS->HandleProtocol (
                  Conn->TcpIo.Handle,
                  &gEfiDevicePathProtocolGuid,
                  (VOID **) &DevicePath
                  );  
  if (EFI_ERROR (Status)) {
    return NULL;
  }
  //
  // Duplicate it.
  //
  DevicePath  = DuplicateDevicePath (DevicePath);
  if (DevicePath == NULL) {
    return NULL;
  }

  DPathNode   = (EFI_DEV_PATH *) DevicePath;

  while (!IsDevicePathEnd (&DPathNode->DevPath)) {
    if (DevicePathType (&DPathNode->DevPath) == MESSAGING_DEVICE_PATH) {
      if (!Conn->Ipv6Flag && DevicePathSubType (&DPathNode->DevPath) == MSG_IPv4_DP) {
        DPathNode->Ipv4.LocalPort       = 0;

        DPathNode->Ipv4.StaticIpAddress = 
          (BOOLEAN) (!Session->ConfigData->SessionConfigData.InitiatorInfoFromDhcp);

        //
        //  Add a judgement here to support previous versions of IPv4_DEVICE_PATH.
        //  In previous versions of IPv4_DEVICE_PATH, GatewayIpAddress and SubnetMask
        //  do not exist.
        //  In new version of IPv4_DEVICE_PATH, structcure length is 27.
        //

        PathLen = DevicePathNodeLength (&DPathNode->Ipv4);
        
        if (PathLen == IP4_NODE_LEN_NEW_VERSIONS) {  
            
          IP4_COPY_ADDRESS (
            &DPathNode->Ipv4.GatewayIpAddress,
            &Session->ConfigData->SessionConfigData.Gateway
            );

          IP4_COPY_ADDRESS (
            &DPathNode->Ipv4.SubnetMask,
            &Session->ConfigData->SessionConfigData.SubnetMask
            );
        }
        
        break;
      } else if (Conn->Ipv6Flag && DevicePathSubType (&DPathNode->DevPath) == MSG_IPv6_DP) {
        DPathNode->Ipv6.LocalPort       = 0;

        //
        //  Add a judgement here to support previous versions of IPv6_DEVICE_PATH.
        //  In previous versions of IPv6_DEVICE_PATH, IpAddressOrigin, PrefixLength
        //  and GatewayIpAddress do not exist.
        //  In new version of IPv6_DEVICE_PATH, structure length is 60, while in 
        //  old versions, the length is 43.
        //

        PathLen = DevicePathNodeLength (&DPathNode->Ipv6);
        
        if (PathLen == IP6_NODE_LEN_NEW_VERSIONS ) { 

          DPathNode->Ipv6.IpAddressOrigin = 0;
          DPathNode->Ipv6.PrefixLength    = IP6_PREFIX_LENGTH;
          ZeroMem (&DPathNode->Ipv6.GatewayIpAddress, sizeof (EFI_IPv6_ADDRESS));
        }
        else if (PathLen == IP6_NODE_LEN_OLD_VERSIONS) { 

          //
          //  StaticIPAddress is a field in old versions of IPv6_DEVICE_PATH, while ignored in new 
          //  version. Set StaticIPAddress through its' offset in old IPv6_DEVICE_PATH.
          //
          *((UINT8 *)(&DPathNode->Ipv6) + IP6_OLD_IPADDRESS_OFFSET) = 
            (BOOLEAN) (!Session->ConfigData->SessionConfigData.InitiatorInfoFromDhcp);
        }
        
        break;
      }
    }

    DPathNode = (EFI_DEV_PATH *) NextDevicePathNode (&DPathNode->DevPath);
  }

  return DevicePath;
}


/**
  Abort the session when the transition from BS to RT is initiated.

  @param[in]   Event  The event signaled.
  @param[in]  Context The iSCSI driver data.

**/
VOID
EFIAPI
IScsiOnExitBootService (
  IN EFI_EVENT  Event,
  IN VOID       *Context
  )
{
  ISCSI_DRIVER_DATA *Private;

  Private = (ISCSI_DRIVER_DATA *) Context;
  gBS->CloseEvent (Private->ExitBootServiceEvent);

  if (Private->Session != NULL) {
    IScsiSessionAbort (Private->Session);
  }
}

/**
  Tests whether a controller handle is being managed by IScsi driver.

  This function tests whether the driver specified by DriverBindingHandle is
  currently managing the controller specified by ControllerHandle.  This test
  is performed by evaluating if the the protocol specified by ProtocolGuid is
  present on ControllerHandle and is was opened by DriverBindingHandle and Nic
  Device handle with an attribute of EFI_OPEN_PROTOCOL_BY_DRIVER. 
  If ProtocolGuid is NULL, then ASSERT().

  @param  ControllerHandle     A handle for a controller to test.
  @param  DriverBindingHandle  Specifies the driver binding handle for the
                               driver.
  @param  ProtocolGuid         Specifies the protocol that the driver specified
                               by DriverBindingHandle opens in its Start()
                               function.

  @retval EFI_SUCCESS          ControllerHandle is managed by the driver
                               specified by DriverBindingHandle.
  @retval EFI_UNSUPPORTED      ControllerHandle is not managed by the driver
                               specified by DriverBindingHandle.

**/
EFI_STATUS
EFIAPI
IScsiTestManagedDevice (
  IN  EFI_HANDLE       ControllerHandle,
  IN  EFI_HANDLE       DriverBindingHandle,
  IN  EFI_GUID         *ProtocolGuid
  )
{
  EFI_STATUS     Status;
  VOID           *ManagedInterface;
  EFI_HANDLE     NicControllerHandle;

  ASSERT (ProtocolGuid != NULL);

  NicControllerHandle = NetLibGetNicHandle (ControllerHandle, ProtocolGuid);
  if (NicControllerHandle == NULL) {
    return EFI_UNSUPPORTED;
  }

  Status = gBS->OpenProtocol (
                  ControllerHandle,
                  (EFI_GUID *) ProtocolGuid,
                  &ManagedInterface,
                  DriverBindingHandle,
                  NicControllerHandle,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );
  if (!EFI_ERROR (Status)) {
    gBS->CloseProtocol (
           ControllerHandle,
           (EFI_GUID *) ProtocolGuid,
           DriverBindingHandle,
           NicControllerHandle
           );
    return EFI_UNSUPPORTED;
  }

  if (Status != EFI_ALREADY_STARTED) {
    return EFI_UNSUPPORTED;
  }

  return EFI_SUCCESS;
}
