REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3737 Apply uncrustify changes to .c/.h files in the NetworkPkg package Cc: Andrew Fish <afish@apple.com> Cc: Leif Lindholm <leif@nuviainc.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com> Reviewed-by: Maciej Rabeda <maciej.rabeda@linux.intel.com>
		
			
				
	
	
		
			2608 lines
		
	
	
		
			77 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			2608 lines
		
	
	
		
			77 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  Miscellaneous routines for iSCSI driver.
 | 
						|
 | 
						|
Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
 | 
						|
SPDX-License-Identifier: BSD-2-Clause-Patent
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#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 "-" separated 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_BAD_BUFFER_SIZE  BinLength is too large for hex encoding.
 | 
						|
  @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
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT32  HexLengthMin;
 | 
						|
  UINT32  HexLengthProvided;
 | 
						|
  UINT32  Index;
 | 
						|
 | 
						|
  if ((HexStr == NULL) || (BinBuffer == NULL) || (BinLength == 0)) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Safely calculate: HexLengthMin := BinLength * 2 + 3.
 | 
						|
  //
 | 
						|
  if (RETURN_ERROR (SafeUint32Mult (BinLength, 2, &HexLengthMin)) ||
 | 
						|
      RETURN_ERROR (SafeUint32Add (HexLengthMin, 3, &HexLengthMin)))
 | 
						|
  {
 | 
						|
    return EFI_BAD_BUFFER_SIZE;
 | 
						|
  }
 | 
						|
 | 
						|
  HexLengthProvided = *HexLength;
 | 
						|
  *HexLength        = HexLengthMin;
 | 
						|
  if (HexLengthProvided < HexLengthMin) {
 | 
						|
    return EFI_BUFFER_TOO_SMALL;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // 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_INVALID_PARAMETER Invalid hex encoding found in HexStr.
 | 
						|
  @retval EFI_BAD_BUFFER_SIZE   The length of HexStr is too large for decoding:
 | 
						|
                                the decoded size cannot be expressed in
 | 
						|
                                BinLength on output.
 | 
						|
  @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   BinLengthMin;
 | 
						|
  UINT32  BinLengthProvided;
 | 
						|
  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);
 | 
						|
 | 
						|
  //
 | 
						|
  // Reject an empty hex string; reject a stray nibble.
 | 
						|
  //
 | 
						|
  if ((Length == 0) || (Length % 2 != 0)) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Check if the caller provides enough room for the decoded blob.
 | 
						|
  //
 | 
						|
  BinLengthMin = Length / 2;
 | 
						|
  if (BinLengthMin > MAX_UINT32) {
 | 
						|
    return EFI_BAD_BUFFER_SIZE;
 | 
						|
  }
 | 
						|
 | 
						|
  BinLengthProvided = *BinLength;
 | 
						|
  *BinLength        = (UINT32)BinLengthMin;
 | 
						|
  if (BinLengthProvided < BinLengthMin) {
 | 
						|
    return EFI_BUFFER_TOO_SMALL;
 | 
						|
  }
 | 
						|
 | 
						|
  for (Index = 0; Index < Length; Index++) {
 | 
						|
    TemStr[0] = HexStr[Index];
 | 
						|
    Digit     = (UINT8)AsciiStrHexToUint64 (TemStr);
 | 
						|
    if ((Digit == 0) && (TemStr[0] != '0')) {
 | 
						|
      //
 | 
						|
      // Invalid Hex Char.
 | 
						|
      //
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
 | 
						|
    if ((Index & 1) == 0) {
 | 
						|
      BinBuffer[Index/2] = Digit;
 | 
						|
    } else {
 | 
						|
      BinBuffer[Index/2] = (UINT8)((BinBuffer[Index/2] << 4) + Digit);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  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--;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Check whether UNDI protocol supports IPv6.
 | 
						|
 | 
						|
  @param[in]   ControllerHandle    Controller handle.
 | 
						|
  @param[in]   Image               Handle of the image.
 | 
						|
  @param[out]  Ipv6Support         TRUE if UNDI supports IPv6.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS            Get the result whether UNDI supports IPv6 by NII or AIP protocol successfully.
 | 
						|
  @retval EFI_NOT_FOUND          Don't know whether UNDI supports IPv6 since NII or AIP is not available.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
IScsiCheckIpv6Support (
 | 
						|
  IN  EFI_HANDLE  ControllerHandle,
 | 
						|
  IN  EFI_HANDLE  Image,
 | 
						|
  OUT BOOLEAN     *Ipv6Support
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_HANDLE                        Handle;
 | 
						|
  EFI_ADAPTER_INFORMATION_PROTOCOL  *Aip;
 | 
						|
  EFI_STATUS                        Status;
 | 
						|
  EFI_GUID                          *InfoTypesBuffer;
 | 
						|
  UINTN                             InfoTypeBufferCount;
 | 
						|
  UINTN                             TypeIndex;
 | 
						|
  BOOLEAN                           Supported;
 | 
						|
  VOID                              *InfoBlock;
 | 
						|
  UINTN                             InfoBlockSize;
 | 
						|
 | 
						|
  EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL  *Nii;
 | 
						|
 | 
						|
  ASSERT (Ipv6Support != NULL);
 | 
						|
 | 
						|
  //
 | 
						|
  // Check whether the UNDI supports IPv6 by NII protocol.
 | 
						|
  //
 | 
						|
  Status = gBS->OpenProtocol (
 | 
						|
                  ControllerHandle,
 | 
						|
                  &gEfiNetworkInterfaceIdentifierProtocolGuid_31,
 | 
						|
                  (VOID **)&Nii,
 | 
						|
                  Image,
 | 
						|
                  ControllerHandle,
 | 
						|
                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
 | 
						|
                  );
 | 
						|
  if (Status == EFI_SUCCESS) {
 | 
						|
    *Ipv6Support = Nii->Ipv6Supported;
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Get the NIC handle by SNP protocol.
 | 
						|
  //
 | 
						|
  Handle = NetLibGetSnpHandle (ControllerHandle, NULL);
 | 
						|
  if (Handle == NULL) {
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
 | 
						|
  Aip    = NULL;
 | 
						|
  Status = gBS->HandleProtocol (
 | 
						|
                  Handle,
 | 
						|
                  &gEfiAdapterInformationProtocolGuid,
 | 
						|
                  (VOID *)&Aip
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status) || (Aip == NULL)) {
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
 | 
						|
  InfoTypesBuffer     = NULL;
 | 
						|
  InfoTypeBufferCount = 0;
 | 
						|
  Status              = Aip->GetSupportedTypes (Aip, &InfoTypesBuffer, &InfoTypeBufferCount);
 | 
						|
  if (EFI_ERROR (Status) || (InfoTypesBuffer == NULL)) {
 | 
						|
    FreePool (InfoTypesBuffer);
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
 | 
						|
  Supported = FALSE;
 | 
						|
  for (TypeIndex = 0; TypeIndex < InfoTypeBufferCount; TypeIndex++) {
 | 
						|
    if (CompareGuid (&InfoTypesBuffer[TypeIndex], &gEfiAdapterInfoUndiIpv6SupportGuid)) {
 | 
						|
      Supported = TRUE;
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  FreePool (InfoTypesBuffer);
 | 
						|
  if (!Supported) {
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // We now have adapter information block.
 | 
						|
  //
 | 
						|
  InfoBlock     = NULL;
 | 
						|
  InfoBlockSize = 0;
 | 
						|
  Status        = Aip->GetInformation (Aip, &gEfiAdapterInfoUndiIpv6SupportGuid, &InfoBlock, &InfoBlockSize);
 | 
						|
  if (EFI_ERROR (Status) || (InfoBlock == NULL)) {
 | 
						|
    FreePool (InfoBlock);
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
 | 
						|
  *Ipv6Support = ((EFI_ADAPTER_INFO_UNDI_IPV6_SUPPORT *)InfoBlock)->Ipv6Support;
 | 
						|
  FreePool (InfoBlock);
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Record the NIC info in global structure.
 | 
						|
 | 
						|
  @param[in]  Controller         The handle of the controller.
 | 
						|
  @param[in]  Image              Handle of the image.
 | 
						|
 | 
						|
  @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,
 | 
						|
  IN EFI_HANDLE  Image
 | 
						|
  )
 | 
						|
{
 | 
						|
  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;
 | 
						|
 | 
						|
      //
 | 
						|
      // Set IPv6 available flag.
 | 
						|
      //
 | 
						|
      Status = IScsiCheckIpv6Support (Controller, Image, &NicInfo->Ipv6Available);
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        //
 | 
						|
        // Fail to get the data whether UNDI supports IPv6.
 | 
						|
        // Set default value to TRUE.
 | 
						|
        //
 | 
						|
        NicInfo->Ipv6Available = TRUE;
 | 
						|
      }
 | 
						|
 | 
						|
      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;
 | 
						|
 | 
						|
  //
 | 
						|
  // Set IPv6 available flag.
 | 
						|
  //
 | 
						|
  Status = IScsiCheckIpv6Support (Controller, Image, &NicInfo->Ipv6Available);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    //
 | 
						|
    // Fail to get the data whether UNDI supports IPv6.
 | 
						|
    // Set default value to TRUE.
 | 
						|
    //
 | 
						|
    NicInfo->Ipv6Available = TRUE;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // 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)) {
 | 
						|
      DEBUG ((
 | 
						|
        DEBUG_ERROR,
 | 
						|
        "%a: Failed to set 'InitialAttemptOrder' with Guid (%g): "
 | 
						|
        "%r\n",
 | 
						|
        __FUNCTION__,
 | 
						|
        &gIScsiConfigGuid,
 | 
						|
        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)) {
 | 
						|
      DEBUG ((
 | 
						|
        DEBUG_ERROR,
 | 
						|
        "%a: Failed to set variable (mPrivate->PortString) with Guid (%g): "
 | 
						|
        "%r\n",
 | 
						|
        __FUNCTION__,
 | 
						|
        &gEfiIScsiInitiatorNameProtocolGuid,
 | 
						|
        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,
 | 
						|
      STRING_TOKEN (STR_ISCSI_ISID_HELP),
 | 
						|
      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_STR_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_STR_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_STR_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_STR_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:
 | 
						|
  if (Private->ExitBootServiceEvent != NULL) {
 | 
						|
    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 || AttemptTmp->SessionConfigData.TargetInfoFromDhcp) {
 | 
						|
      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 &&
 | 
						|
                 (AttemptTmp->NicIndex == mPrivate->CurrentNic))
 | 
						|
      {
 | 
						|
        //
 | 
						|
        // If the attempt associates with the current NIC, we can
 | 
						|
        // 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, structure 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);
 | 
						|
  Private->ExitBootServiceEvent = NULL;
 | 
						|
 | 
						|
  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 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;
 | 
						|
}
 |