Fix various typos in comments and documentation. Cc: Jiaxin Wu <jiaxin.wu@intel.com> Cc: Siyuan Fu <siyuan.fu@intel.com> Cc: Maciej Rabeda <maciej.rabeda@intel.com> Signed-off-by: Antoine Coeur <coeur@gmx.fr> Reviewed-by: Philippe Mathieu-Daude <philmd@redhat.com> Reviewed-by: Maciej Rabeda <maciej.rabeda@linux.intel.com> Signed-off-by: Philippe Mathieu-Daude <philmd@redhat.com> Message-Id: <20200207010831.9046-42-philmd@redhat.com>
		
			
				
	
	
		
			3935 lines
		
	
	
		
			130 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			3935 lines
		
	
	
		
			130 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   Helper functions for configuring or getting the parameters relating to iSCSI.
 | |
| 
 | |
| Copyright (c) 2004 - 2019, Intel Corporation. All rights reserved.<BR>
 | |
| SPDX-License-Identifier: BSD-2-Clause-Patent
 | |
| 
 | |
| **/
 | |
| 
 | |
| #include "IScsiImpl.h"
 | |
| 
 | |
| CHAR16          mVendorStorageName[]     = L"ISCSI_CONFIG_IFR_NVDATA";
 | |
| ISCSI_FORM_CALLBACK_INFO  *mCallbackInfo = NULL;
 | |
| 
 | |
| HII_VENDOR_DEVICE_PATH  mIScsiHiiVendorDevicePath = {
 | |
|   {
 | |
|     {
 | |
|       HARDWARE_DEVICE_PATH,
 | |
|       HW_VENDOR_DP,
 | |
|       {
 | |
|         (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
 | |
|         (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
 | |
|       }
 | |
|     },
 | |
|     ISCSI_CONFIG_GUID
 | |
|   },
 | |
|   {
 | |
|     END_DEVICE_PATH_TYPE,
 | |
|     END_ENTIRE_DEVICE_PATH_SUBTYPE,
 | |
|     {
 | |
|       (UINT8) (END_DEVICE_PATH_LENGTH),
 | |
|       (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)
 | |
|     }
 | |
|   }
 | |
| };
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Convert the IP address into a dotted string.
 | |
| 
 | |
|   @param[in]  Ip        The IP address.
 | |
|   @param[in]  Ipv6Flag  Indicates whether the IP address is version 4 or version 6.
 | |
|   @param[out] Str       The formatted IP string.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| IScsiIpToStr (
 | |
|   IN  EFI_IP_ADDRESS    *Ip,
 | |
|   IN  BOOLEAN           Ipv6Flag,
 | |
|   OUT CHAR16            *Str
 | |
|   )
 | |
| {
 | |
|   EFI_IPv4_ADDRESS      *Ip4;
 | |
|   EFI_IPv6_ADDRESS      *Ip6;
 | |
|   UINTN                 Index;
 | |
|   BOOLEAN               Short;
 | |
|   UINTN                 Number;
 | |
|   CHAR16                FormatString[8];
 | |
| 
 | |
|   if (!Ipv6Flag) {
 | |
|     Ip4 = &Ip->v4;
 | |
| 
 | |
|     UnicodeSPrint (
 | |
|       Str,
 | |
|       (UINTN) 2 * IP4_STR_MAX_SIZE,
 | |
|       L"%d.%d.%d.%d",
 | |
|       (UINTN) Ip4->Addr[0],
 | |
|       (UINTN) Ip4->Addr[1],
 | |
|       (UINTN) Ip4->Addr[2],
 | |
|       (UINTN) Ip4->Addr[3]
 | |
|       );
 | |
| 
 | |
|     return ;
 | |
|   }
 | |
| 
 | |
|   Ip6   = &Ip->v6;
 | |
|   Short = FALSE;
 | |
| 
 | |
|   for (Index = 0; Index < 15; Index = Index + 2) {
 | |
|     if (!Short &&
 | |
|         Index % 2 == 0 &&
 | |
|         Ip6->Addr[Index] == 0 &&
 | |
|         Ip6->Addr[Index + 1] == 0
 | |
|         ) {
 | |
|       //
 | |
|       // Deal with the case of ::.
 | |
|       //
 | |
|       if (Index == 0) {
 | |
|         *Str       = L':';
 | |
|         *(Str + 1) = L':';
 | |
|         Str        = Str + 2;
 | |
|       } else {
 | |
|         *Str       = L':';
 | |
|         Str        = Str + 1;
 | |
|       }
 | |
| 
 | |
|       while ((Index < 15) && (Ip6->Addr[Index] == 0) && (Ip6->Addr[Index + 1] == 0)) {
 | |
|         Index = Index + 2;
 | |
|       }
 | |
| 
 | |
|       Short = TRUE;
 | |
| 
 | |
|       if (Index == 16) {
 | |
|         //
 | |
|         // :: is at the end of the address.
 | |
|         //
 | |
|         *Str = L'\0';
 | |
|         break;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     ASSERT (Index < 15);
 | |
| 
 | |
|     if (Ip6->Addr[Index] == 0) {
 | |
|       Number = UnicodeSPrint (Str, 2 * IP_STR_MAX_SIZE, L"%x:", (UINTN) Ip6->Addr[Index + 1]);
 | |
|     } else {
 | |
|       if (Ip6->Addr[Index + 1] < 0x10) {
 | |
|         CopyMem (FormatString, L"%x0%x:", StrSize (L"%x0%x:"));
 | |
|       } else {
 | |
|         CopyMem (FormatString, L"%x%x:", StrSize (L"%x%x:"));
 | |
|       }
 | |
| 
 | |
|       Number = UnicodeSPrint (
 | |
|                  Str,
 | |
|                  2 * IP_STR_MAX_SIZE,
 | |
|                  (CONST CHAR16 *) FormatString,
 | |
|                  (UINTN) Ip6->Addr[Index],
 | |
|                  (UINTN) Ip6->Addr[Index + 1]
 | |
|                  );
 | |
|     }
 | |
| 
 | |
|     Str = Str + Number;
 | |
| 
 | |
|     if (Index + 2 == 16) {
 | |
|       *Str = L'\0';
 | |
|       if (*(Str - 1) == L':') {
 | |
|         *(Str - 1) = L'\0';
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Check whether the input IP address is valid.
 | |
| 
 | |
|   @param[in]  Ip        The IP address.
 | |
|   @param[in]  IpMode    Indicates iSCSI running on IP4 or IP6 stack.
 | |
| 
 | |
|   @retval     TRUE      The input IP address is valid.
 | |
|   @retval     FALSE     Otherwise
 | |
| 
 | |
| **/
 | |
| BOOLEAN
 | |
| IpIsUnicast (
 | |
|   IN EFI_IP_ADDRESS *Ip,
 | |
|   IN  UINT8          IpMode
 | |
|   )
 | |
| {
 | |
|   if (IpMode == IP_MODE_IP4) {
 | |
|     if (IP4_IS_UNSPECIFIED (NTOHL (Ip->Addr[0])) || IP4_IS_LOCAL_BROADCAST (NTOHL (Ip->Addr[0])))   {
 | |
|       return FALSE;
 | |
|     }
 | |
|     return TRUE;
 | |
|   } else if (IpMode == IP_MODE_IP6) {
 | |
|     return NetIp6IsValidUnicast (&Ip->v6);
 | |
|   } else {
 | |
|     DEBUG ((DEBUG_ERROR, "IpMode %d is invalid when configuring the iSCSI target IP!\n", IpMode));
 | |
|     return FALSE;
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Parse IsId in string format and convert it to binary.
 | |
| 
 | |
|   @param[in]        String  The buffer of the string to be parsed.
 | |
|   @param[in, out]   IsId    The buffer to store IsId.
 | |
| 
 | |
|   @retval EFI_SUCCESS              The operation finished successfully.
 | |
|   @retval EFI_INVALID_PARAMETER    Any input parameter is invalid.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| IScsiParseIsIdFromString (
 | |
|   IN CONST CHAR16                    *String,
 | |
|   IN OUT   UINT8                     *IsId
 | |
|   )
 | |
| {
 | |
|   UINT8                          Index;
 | |
|   CHAR16                         *IsIdStr;
 | |
|   CHAR16                         TempStr[3];
 | |
|   UINTN                          NodeVal;
 | |
|   CHAR16                         PortString[ISCSI_NAME_IFR_MAX_SIZE];
 | |
|   EFI_INPUT_KEY                  Key;
 | |
| 
 | |
|   if ((String == NULL) || (IsId == NULL)) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   IsIdStr = (CHAR16 *) String;
 | |
| 
 | |
|   if (StrLen (IsIdStr) != 6 && StrLen (IsIdStr) != 12) {
 | |
|     UnicodeSPrint (
 | |
|       PortString,
 | |
|       (UINTN) ISCSI_NAME_IFR_MAX_SIZE,
 | |
|       L"Error! Only last 3 bytes are configurable, please input 6 hex numbers for last 3 bytes only or 12 hex numbers for full SSID!\n"
 | |
|       );
 | |
| 
 | |
|     CreatePopUp (
 | |
|       EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
 | |
|       &Key,
 | |
|       PortString,
 | |
|       NULL
 | |
|       );
 | |
| 
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   if (StrLen (IsIdStr) == 12) {
 | |
|     IsIdStr += 6;
 | |
|   }
 | |
| 
 | |
|   for (Index = 3; Index < 6; Index++) {
 | |
|     CopyMem (TempStr, IsIdStr, sizeof (TempStr));
 | |
|     TempStr[2] = L'\0';
 | |
| 
 | |
|     //
 | |
|     // Convert the string to IsId. StrHexToUintn stops at the first character
 | |
|     // that is not a valid hex character, '\0' here.
 | |
|     //
 | |
|     NodeVal = StrHexToUintn (TempStr);
 | |
| 
 | |
|     IsId[Index] = (UINT8) NodeVal;
 | |
| 
 | |
|     IsIdStr = IsIdStr + 2;
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Convert IsId from binary to string format.
 | |
| 
 | |
|   @param[out]      String  The buffer to store the converted string.
 | |
|   @param[in]       IsId    The buffer to store IsId.
 | |
| 
 | |
|   @retval EFI_SUCCESS              The string converted successfully.
 | |
|   @retval EFI_INVALID_PARAMETER    Any input parameter is invalid.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| IScsiConvertIsIdToString (
 | |
|   OUT CHAR16                         *String,
 | |
|   IN  UINT8                          *IsId
 | |
|   )
 | |
| {
 | |
|   UINT8                          Index;
 | |
|   UINTN                          Number;
 | |
| 
 | |
|   if ((String == NULL) || (IsId == NULL)) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   for (Index = 0; Index < 6; Index++) {
 | |
|     if (IsId[Index] <= 0xF) {
 | |
|       Number = UnicodeSPrint (
 | |
|                  String,
 | |
|                  2 * ISID_CONFIGURABLE_STORAGE,
 | |
|                  L"0%X",
 | |
|                  (UINTN) IsId[Index]
 | |
|                  );
 | |
|     } else {
 | |
|       Number = UnicodeSPrint (
 | |
|                  String,
 | |
|                  2 * ISID_CONFIGURABLE_STORAGE,
 | |
|                  L"%X",
 | |
|                  (UINTN) IsId[Index]
 | |
|                  );
 | |
| 
 | |
|     }
 | |
| 
 | |
|     String = String + Number;
 | |
|   }
 | |
| 
 | |
|   *String = L'\0';
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Get the Offset value specified by the input String.
 | |
| 
 | |
|   @param[in]  Configuration      A null-terminated Unicode string in
 | |
|                                  <ConfigString> format.
 | |
|   @param[in]  String             The string is "&OFFSET=".
 | |
|   @param[out] Value              The Offset value.
 | |
| 
 | |
|   @retval EFI_OUT_OF_RESOURCES   Insufficient resources to store necessary
 | |
|                                  structures.
 | |
|   @retval EFI_SUCCESS            Value of <Number> is outputted in Number
 | |
|                                  successfully.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| IScsiGetValue (
 | |
|   IN  CONST EFI_STRING             Configuration,
 | |
|   IN  CHAR16                       *String,
 | |
|   OUT UINTN                        *Value
 | |
|   )
 | |
| {
 | |
|   CHAR16                           *StringPtr;
 | |
|   CHAR16                           *TmpPtr;
 | |
|   CHAR16                           *Str;
 | |
|   CHAR16                           TmpStr[2];
 | |
|   UINTN                            Length;
 | |
|   UINTN                            Len;
 | |
|   UINTN                            Index;
 | |
|   UINT8                            *Buf;
 | |
|   UINT8                            DigitUint8;
 | |
|   EFI_STATUS                       Status;
 | |
| 
 | |
|   //
 | |
|   // Get Value.
 | |
|   //
 | |
|   Buf = NULL;
 | |
|   StringPtr = StrStr (Configuration, String);
 | |
|   ASSERT(StringPtr != NULL);
 | |
|   StringPtr += StrLen (String);
 | |
|   TmpPtr = StringPtr;
 | |
| 
 | |
|   while (*StringPtr != L'\0' && *StringPtr != L'&') {
 | |
|     StringPtr ++;
 | |
|   }
 | |
|   Length = StringPtr - TmpPtr;
 | |
|   Len = Length + 1;
 | |
| 
 | |
|   Str = AllocateZeroPool (Len * sizeof (CHAR16));
 | |
|   if (Str == NULL) {
 | |
|     Status = EFI_OUT_OF_RESOURCES;
 | |
|     goto Exit;
 | |
|   }
 | |
| 
 | |
|   CopyMem (Str, TmpPtr, Len * sizeof (CHAR16));
 | |
|   *(Str + Length) = L'\0';
 | |
| 
 | |
|   Len = (Len + 1) / 2;
 | |
|   Buf = (UINT8 *) AllocateZeroPool (Len);
 | |
|   if (Buf == NULL) {
 | |
|     Status = EFI_OUT_OF_RESOURCES;
 | |
|     goto Exit;
 | |
|   }
 | |
| 
 | |
|   ZeroMem (TmpStr, sizeof (TmpStr));
 | |
|   for (Index = 0; Index < Length; Index ++) {
 | |
|     TmpStr[0] = Str[Length - Index - 1];
 | |
|     DigitUint8 = (UINT8) StrHexToUint64 (TmpStr);
 | |
|     if ((Index & 1) == 0) {
 | |
|       Buf [Index/2] = DigitUint8;
 | |
|     } else {
 | |
|       Buf [Index/2] = (UINT8) ((DigitUint8 << 4) + Buf [Index/2]);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   *Value = 0;
 | |
|   CopyMem (
 | |
|     Value,
 | |
|     Buf,
 | |
|     (((Length + 1) / 2) < sizeof (UINTN)) ? ((Length + 1) / 2) : sizeof (UINTN)
 | |
|     );
 | |
| 
 | |
|   FreePool (Buf);
 | |
|   Status = EFI_SUCCESS;
 | |
| 
 | |
| Exit:
 | |
|   if (Str != NULL) {
 | |
|     FreePool (Str);
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Get the attempt config data from global structure by the ConfigIndex.
 | |
| 
 | |
|   @param[in]  AttemptConfigIndex     The unique index indicates the attempt.
 | |
| 
 | |
|   @return       Pointer to the attempt config data.
 | |
|   @retval NULL  The attempt configuration data cannot be found.
 | |
| 
 | |
| **/
 | |
| ISCSI_ATTEMPT_CONFIG_NVDATA *
 | |
| IScsiConfigGetAttemptByConfigIndex (
 | |
|   IN UINT8                     AttemptConfigIndex
 | |
|   )
 | |
| {
 | |
|   LIST_ENTRY                   *Entry;
 | |
|   ISCSI_ATTEMPT_CONFIG_NVDATA  *Attempt;
 | |
| 
 | |
|   NET_LIST_FOR_EACH (Entry, &mPrivate->AttemptConfigs) {
 | |
|     Attempt = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);
 | |
|     if (Attempt->AttemptConfigIndex == AttemptConfigIndex) {
 | |
|       return Attempt;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return NULL;
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Get the existing attempt config data from global structure by the NicIndex.
 | |
| 
 | |
|   @param[in]  NewAttempt         The created new attempt
 | |
|   @param[in]  IScsiMode          The IScsi Mode of the new attempt, Enabled or
 | |
|                                  Enabled for MPIO.
 | |
| 
 | |
|   @return                        Pointer to the existing attempt config data which
 | |
|                                  has the same NICIndex as the new created attempt.
 | |
|   @retval     NULL               The attempt with NicIndex does not exist.
 | |
| 
 | |
| **/
 | |
| ISCSI_ATTEMPT_CONFIG_NVDATA *
 | |
| IScsiConfigGetAttemptByNic (
 | |
|   IN ISCSI_ATTEMPT_CONFIG_NVDATA *NewAttempt,
 | |
|   IN UINT8                       IScsiMode
 | |
|   )
 | |
| {
 | |
|   LIST_ENTRY                   *Entry;
 | |
|   ISCSI_ATTEMPT_CONFIG_NVDATA  *Attempt;
 | |
| 
 | |
|   NET_LIST_FOR_EACH (Entry, &mPrivate->AttemptConfigs) {
 | |
|     Attempt = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);
 | |
|     if (Attempt != NewAttempt && Attempt->NicIndex == NewAttempt->NicIndex &&
 | |
|         Attempt->SessionConfigData.Enabled == IScsiMode) {
 | |
|       return Attempt;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return NULL;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Extract the Index of the attempt list.
 | |
| 
 | |
|   @param[in]   AttemptNameList     The Name list of the Attempts.
 | |
|   @param[out]  AttemptIndexList    The Index list of the Attempts.
 | |
|   @param[in]   IsAddAttempts       If TRUE, Indicates add one or more attempts.
 | |
|                                    If FALSE, Indicates delete attempts or change attempt order.
 | |
| 
 | |
|   @retval EFI_SUCCESS              The Attempt list is valid.
 | |
|   @retval EFI_INVALID_PARAMETERS   The Attempt List is invalid.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| IScsiGetAttemptIndexList (
 | |
|   IN      CHAR16                    *AttemptNameList,
 | |
|      OUT  UINT8                     *AttemptIndexList,
 | |
|   IN      BOOLEAN                   IsAddAttempts
 | |
| )
 | |
| {
 | |
|   ISCSI_ATTEMPT_CONFIG_NVDATA   *AttemptConfigData;
 | |
|   CHAR16                        *AttemptStr;
 | |
|   UINT8                         AttemptIndex;
 | |
|   UINTN                         Len;
 | |
|   UINTN                         Index;
 | |
| 
 | |
|   Index = 0;
 | |
| 
 | |
|   if ((AttemptNameList == NULL) || (*AttemptNameList == L'\0')) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   AttemptStr = AttemptNameList;
 | |
|   Len = StrLen (L"attempt:");
 | |
| 
 | |
|   while (*AttemptStr != L'\0') {
 | |
|     AttemptStr = StrStr (AttemptStr, L"attempt:");
 | |
|     if (AttemptStr == NULL) {
 | |
|       return EFI_INVALID_PARAMETER;
 | |
|     }
 | |
|     AttemptStr += Len;
 | |
|     AttemptIndex = (UINT8)(*AttemptStr - L'0');
 | |
|     AttemptConfigData  = IScsiConfigGetAttemptByConfigIndex (AttemptIndex);
 | |
|     if (IsAddAttempts) {
 | |
|       if ((AttemptConfigData != NULL) || ((AttemptIndex) > PcdGet8 (PcdMaxIScsiAttemptNumber))) {
 | |
|         return EFI_INVALID_PARAMETER;
 | |
|       }
 | |
|     } else {
 | |
|       if (AttemptConfigData == NULL) {
 | |
|         return EFI_INVALID_PARAMETER;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     AttemptIndexList[Index] = AttemptIndex;
 | |
|     Index ++;
 | |
|     AttemptStr += 2;
 | |
|   }
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Convert the iSCSI configuration data into the IFR data.
 | |
| 
 | |
|   @param[in]       Attempt                The iSCSI attempt config data.
 | |
|   @param[in, out]  IfrNvData              The IFR nv data.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| IScsiConvertAttemptConfigDataToIfrNvData (
 | |
|   IN ISCSI_ATTEMPT_CONFIG_NVDATA  *Attempt,
 | |
|   IN OUT ISCSI_CONFIG_IFR_NVDATA  *IfrNvData
 | |
|   )
 | |
| {
 | |
|   ISCSI_SESSION_CONFIG_NVDATA   *SessionConfigData;
 | |
|   ISCSI_CHAP_AUTH_CONFIG_NVDATA *AuthConfigData;
 | |
|   EFI_IP_ADDRESS                Ip;
 | |
|   BOOLEAN                       DnsMode;
 | |
| 
 | |
|   //
 | |
|   // Normal session configuration parameters.
 | |
|   //
 | |
|   SessionConfigData                 = &Attempt->SessionConfigData;
 | |
|   IfrNvData->Enabled                = SessionConfigData->Enabled;
 | |
|   IfrNvData->IpMode                 = SessionConfigData->IpMode;
 | |
|   DnsMode                           = SessionConfigData->DnsMode;
 | |
| 
 | |
|   IfrNvData->InitiatorInfoFromDhcp  = SessionConfigData->InitiatorInfoFromDhcp;
 | |
|   IfrNvData->TargetInfoFromDhcp     = SessionConfigData->TargetInfoFromDhcp;
 | |
|   IfrNvData->TargetPort             = SessionConfigData->TargetPort;
 | |
| 
 | |
|   if (IfrNvData->IpMode == IP_MODE_IP4) {
 | |
|     CopyMem (&Ip.v4, &SessionConfigData->LocalIp, sizeof (EFI_IPv4_ADDRESS));
 | |
|     IScsiIpToStr (&Ip, FALSE, IfrNvData->LocalIp);
 | |
|     CopyMem (&Ip.v4, &SessionConfigData->SubnetMask, sizeof (EFI_IPv4_ADDRESS));
 | |
|     IScsiIpToStr (&Ip, FALSE, IfrNvData->SubnetMask);
 | |
|     CopyMem (&Ip.v4, &SessionConfigData->Gateway, sizeof (EFI_IPv4_ADDRESS));
 | |
|     IScsiIpToStr (&Ip, FALSE, IfrNvData->Gateway);
 | |
|     ZeroMem (IfrNvData->TargetIp, sizeof (IfrNvData->TargetIp));
 | |
|     if (SessionConfigData->TargetIp.v4.Addr[0] != '\0') {
 | |
|       CopyMem (&Ip.v4, &SessionConfigData->TargetIp, sizeof (EFI_IPv4_ADDRESS));
 | |
|       IScsiIpToStr (&Ip, FALSE, IfrNvData->TargetIp);
 | |
|     }
 | |
| 
 | |
|   } else if (IfrNvData->IpMode == IP_MODE_IP6) {
 | |
|     ZeroMem (IfrNvData->TargetIp, sizeof (IfrNvData->TargetIp));
 | |
|     if (SessionConfigData->TargetIp.v6.Addr[0] != '\0') {
 | |
|       IP6_COPY_ADDRESS (&Ip.v6, &SessionConfigData->TargetIp);
 | |
|       IScsiIpToStr (&Ip, TRUE, IfrNvData->TargetIp);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   AsciiStrToUnicodeStrS (
 | |
|     SessionConfigData->TargetName,
 | |
|     IfrNvData->TargetName,
 | |
|     sizeof (IfrNvData->TargetName) / sizeof (IfrNvData->TargetName[0])
 | |
|     );
 | |
| 
 | |
|   if (DnsMode) {
 | |
|     AsciiStrToUnicodeStrS (
 | |
|       SessionConfigData->TargetUrl,
 | |
|       IfrNvData->TargetIp,
 | |
|       sizeof (IfrNvData->TargetIp) / sizeof (IfrNvData->TargetIp[0])
 | |
|       );
 | |
|   }
 | |
| 
 | |
|   IScsiLunToUnicodeStr (SessionConfigData->BootLun, IfrNvData->BootLun);
 | |
|   IScsiConvertIsIdToString (IfrNvData->IsId, SessionConfigData->IsId);
 | |
| 
 | |
|   IfrNvData->ConnectRetryCount = SessionConfigData->ConnectRetryCount;
 | |
|   IfrNvData->ConnectTimeout    = SessionConfigData->ConnectTimeout;
 | |
| 
 | |
|   //
 | |
|   // Authentication parameters.
 | |
|   //
 | |
|   IfrNvData->AuthenticationType = Attempt->AuthenticationType;
 | |
| 
 | |
|   if (IfrNvData->AuthenticationType == ISCSI_AUTH_TYPE_CHAP) {
 | |
|     AuthConfigData      = &Attempt->AuthConfigData.CHAP;
 | |
|     IfrNvData->CHAPType = AuthConfigData->CHAPType;
 | |
|     AsciiStrToUnicodeStrS (
 | |
|       AuthConfigData->CHAPName,
 | |
|       IfrNvData->CHAPName,
 | |
|       sizeof (IfrNvData->CHAPName) / sizeof (IfrNvData->CHAPName[0])
 | |
|       );
 | |
|     AsciiStrToUnicodeStrS (
 | |
|       AuthConfigData->CHAPSecret,
 | |
|       IfrNvData->CHAPSecret,
 | |
|       sizeof (IfrNvData->CHAPSecret) / sizeof (IfrNvData->CHAPSecret[0])
 | |
|       );
 | |
|     AsciiStrToUnicodeStrS (
 | |
|       AuthConfigData->ReverseCHAPName,
 | |
|       IfrNvData->ReverseCHAPName,
 | |
|       sizeof (IfrNvData->ReverseCHAPName) / sizeof (IfrNvData->ReverseCHAPName[0])
 | |
|       );
 | |
|     AsciiStrToUnicodeStrS (
 | |
|       AuthConfigData->ReverseCHAPSecret,
 | |
|       IfrNvData->ReverseCHAPSecret,
 | |
|       sizeof (IfrNvData->ReverseCHAPSecret) / sizeof (IfrNvData->ReverseCHAPSecret[0])
 | |
|       );
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Other parameters.
 | |
|   //
 | |
|   AsciiStrToUnicodeStrS (
 | |
|     Attempt->AttemptName,
 | |
|     IfrNvData->AttemptName,
 | |
|     sizeof (IfrNvData->AttemptName) / sizeof (IfrNvData->AttemptName[0])
 | |
|     );
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Convert the iSCSI configuration data into the IFR data Which will be used
 | |
|   to extract the iSCSI Keyword configuration in <ConfigAltResp> format.
 | |
| 
 | |
|   @param[in, out]  IfrNvData              The IFR nv data.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| IScsiConvertAttemptConfigDataToIfrNvDataByKeyword (
 | |
|   IN OUT ISCSI_CONFIG_IFR_NVDATA  *IfrNvData
 | |
|   )
 | |
| {
 | |
|   LIST_ENTRY                    *Entry;
 | |
|   ISCSI_ATTEMPT_CONFIG_NVDATA   *Attempt;
 | |
|   ISCSI_SESSION_CONFIG_NVDATA   *SessionConfigData;
 | |
|   ISCSI_CHAP_AUTH_CONFIG_NVDATA *AuthConfigData;
 | |
|   CHAR16                        AttemptNameList[ATTEMPT_NAME_LIST_SIZE];
 | |
|   ISCSI_NIC_INFO                *NicInfo;
 | |
|   CHAR16                        MacString[ISCSI_MAX_MAC_STRING_LEN];
 | |
|   EFI_IP_ADDRESS                Ip;
 | |
|   UINTN                         Index;
 | |
|   UINTN                         StringLen;
 | |
| 
 | |
|   NicInfo = NULL;
 | |
|   ZeroMem (AttemptNameList, sizeof (AttemptNameList));
 | |
| 
 | |
|   if ((mPrivate != NULL) && (mPrivate->AttemptCount != 0)) {
 | |
|     NET_LIST_FOR_EACH (Entry, &mPrivate->AttemptConfigs) {
 | |
|       Attempt = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);
 | |
|       //
 | |
|       // Normal session configuration parameters.
 | |
|       //
 | |
|       SessionConfigData                 = &Attempt->SessionConfigData;
 | |
| 
 | |
|       ASSERT ((Attempt->AttemptConfigIndex > 0) && (Attempt->AttemptConfigIndex <= FixedPcdGet8 (PcdMaxIScsiAttemptNumber)));
 | |
|       Index   = Attempt->AttemptConfigIndex - 1;
 | |
| 
 | |
|       //
 | |
|       // Save the attempt to AttemptNameList as Attempt:1 Attempt:2
 | |
|       //
 | |
|       AsciiStrToUnicodeStrS (
 | |
|         Attempt->AttemptName,
 | |
|         AttemptNameList + StrLen (AttemptNameList),
 | |
|         ATTEMPT_NAME_LIST_SIZE - StrLen (AttemptNameList)
 | |
|       );
 | |
| 
 | |
|       StringLen = StrLen (AttemptNameList);
 | |
|       ASSERT (StringLen > 2);
 | |
|       *(AttemptNameList + StringLen - 2) = L':';
 | |
|       *(AttemptNameList + StringLen)     = L' ';
 | |
| 
 | |
|       AsciiStrToUnicodeStrS (
 | |
|         Attempt->AttemptName,
 | |
|         IfrNvData->ISCSIAttemptName  + ATTEMPT_NAME_SIZE * Index,
 | |
|         ATTEMPT_NAME_LIST_SIZE - ATTEMPT_NAME_SIZE * Index
 | |
|       );
 | |
| 
 | |
|       IfrNvData->ISCSIBootEnableList[Index]          = SessionConfigData->Enabled;
 | |
|       IfrNvData->ISCSIIpAddressTypeList[Index]       = SessionConfigData->IpMode;
 | |
| 
 | |
|       IfrNvData->ISCSIInitiatorInfoViaDHCP[Index]    = SessionConfigData->InitiatorInfoFromDhcp;
 | |
|       IfrNvData->ISCSITargetInfoViaDHCP[Index]       = SessionConfigData->TargetInfoFromDhcp;
 | |
|       IfrNvData->ISCSIConnectRetry[Index]            = SessionConfigData->ConnectRetryCount;
 | |
|       IfrNvData->ISCSIConnectTimeout[Index]          = SessionConfigData->ConnectTimeout;
 | |
|       IfrNvData->ISCSITargetTcpPort[Index]           = SessionConfigData->TargetPort;
 | |
| 
 | |
|       if (SessionConfigData->IpMode == IP_MODE_IP4) {
 | |
|         CopyMem (&Ip.v4, &SessionConfigData->LocalIp, sizeof (EFI_IPv4_ADDRESS));
 | |
|         IScsiIpToStr (&Ip, FALSE, IfrNvData->Keyword[Index].ISCSIInitiatorIpAddress);
 | |
|         CopyMem (&Ip.v4, &SessionConfigData->SubnetMask, sizeof (EFI_IPv4_ADDRESS));
 | |
|         IScsiIpToStr (&Ip, FALSE, IfrNvData->Keyword[Index].ISCSIInitiatorNetmask);
 | |
|         CopyMem (&Ip.v4, &SessionConfigData->Gateway, sizeof (EFI_IPv4_ADDRESS));
 | |
|         IScsiIpToStr (&Ip, FALSE, IfrNvData->Keyword[Index].ISCSIInitiatorGateway);
 | |
|         if (SessionConfigData->TargetIp.v4.Addr[0] != '\0') {
 | |
|           CopyMem (&Ip.v4, &SessionConfigData->TargetIp, sizeof (EFI_IPv4_ADDRESS));
 | |
|           IScsiIpToStr (&Ip, FALSE, IfrNvData->Keyword[Index].ISCSITargetIpAddress);
 | |
|         }
 | |
|       } else if (SessionConfigData->IpMode == IP_MODE_IP6) {
 | |
|         ZeroMem (IfrNvData->Keyword[Index].ISCSITargetIpAddress, sizeof (IfrNvData->TargetIp));
 | |
|         if (SessionConfigData->TargetIp.v6.Addr[0] != '\0') {
 | |
|           IP6_COPY_ADDRESS (&Ip.v6, &SessionConfigData->TargetIp);
 | |
|           IScsiIpToStr (&Ip, TRUE, IfrNvData->Keyword[Index].ISCSITargetIpAddress);
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       AsciiStrToUnicodeStrS (
 | |
|         SessionConfigData->TargetName,
 | |
|         IfrNvData->Keyword[Index].ISCSITargetName,
 | |
|         ISCSI_NAME_MAX_SIZE
 | |
|         );
 | |
| 
 | |
|       if (SessionConfigData->DnsMode) {
 | |
|         AsciiStrToUnicodeStrS (
 | |
|           SessionConfigData->TargetUrl,
 | |
|           IfrNvData->Keyword[Index].ISCSITargetIpAddress,
 | |
|           sizeof (IfrNvData->Keyword[Index].ISCSITargetIpAddress) / sizeof (IfrNvData->Keyword[Index].ISCSITargetIpAddress[0])
 | |
|           );
 | |
|       }
 | |
| 
 | |
|       IScsiLunToUnicodeStr (SessionConfigData->BootLun, IfrNvData->Keyword[Index].ISCSILun);
 | |
|       IScsiConvertIsIdToString (IfrNvData->Keyword[Index].ISCSIIsId, SessionConfigData->IsId);
 | |
| 
 | |
|       IfrNvData->ISCSIAuthenticationMethod[Index]    = Attempt->AuthenticationType;
 | |
| 
 | |
|       if (Attempt->AuthenticationType == ISCSI_AUTH_TYPE_CHAP) {
 | |
|         AuthConfigData      = &Attempt->AuthConfigData.CHAP;
 | |
|         IfrNvData->ISCSIChapType[Index] = AuthConfigData->CHAPType;
 | |
|         AsciiStrToUnicodeStrS (
 | |
|           AuthConfigData->CHAPName,
 | |
|           IfrNvData->Keyword[Index].ISCSIChapUsername,
 | |
|           ISCSI_CHAP_NAME_STORAGE
 | |
|           );
 | |
| 
 | |
|         AsciiStrToUnicodeStrS (
 | |
|           AuthConfigData->CHAPSecret,
 | |
|           IfrNvData->Keyword[Index].ISCSIChapSecret,
 | |
|           ISCSI_CHAP_SECRET_STORAGE
 | |
|           );
 | |
| 
 | |
|         AsciiStrToUnicodeStrS (
 | |
|           AuthConfigData->ReverseCHAPName,
 | |
|           IfrNvData->Keyword[Index].ISCSIReverseChapUsername,
 | |
|           ISCSI_CHAP_NAME_STORAGE
 | |
|           );
 | |
| 
 | |
|         AsciiStrToUnicodeStrS (
 | |
|           AuthConfigData->ReverseCHAPSecret,
 | |
|           IfrNvData->Keyword[Index].ISCSIReverseChapSecret,
 | |
|           ISCSI_CHAP_SECRET_STORAGE
 | |
|           );
 | |
|       }
 | |
|     }
 | |
|     CopyMem(IfrNvData->ISCSIDisplayAttemptList, AttemptNameList, ATTEMPT_NAME_LIST_SIZE);
 | |
| 
 | |
|     ZeroMem (IfrNvData->ISCSIMacAddr, sizeof (IfrNvData->ISCSIMacAddr));
 | |
|     NET_LIST_FOR_EACH (Entry, &mPrivate->NicInfoList) {
 | |
|       NicInfo = NET_LIST_USER_STRUCT (Entry, ISCSI_NIC_INFO, Link);
 | |
|       IScsiMacAddrToStr (
 | |
|         &NicInfo->PermanentAddress,
 | |
|         NicInfo->HwAddressSize,
 | |
|         NicInfo->VlanId,
 | |
|         MacString
 | |
|         );
 | |
|       CopyMem (
 | |
|         IfrNvData->ISCSIMacAddr + StrLen (IfrNvData->ISCSIMacAddr),
 | |
|         MacString,
 | |
|         StrLen (MacString) * sizeof (CHAR16)
 | |
|         );
 | |
| 
 | |
|       *(IfrNvData->ISCSIMacAddr + StrLen (IfrNvData->ISCSIMacAddr)) = L'/';
 | |
|     }
 | |
| 
 | |
|     StringLen = StrLen (IfrNvData->ISCSIMacAddr);
 | |
|     if (StringLen > 0) {
 | |
|       *(IfrNvData->ISCSIMacAddr + StringLen - 1) = L'\0';
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Convert the IFR data to iSCSI configuration data.
 | |
| 
 | |
|   @param[in]       IfrNvData              Point to ISCSI_CONFIG_IFR_NVDATA.
 | |
|   @param[in, out]  Attempt                The iSCSI attempt config data.
 | |
| 
 | |
|   @retval EFI_INVALID_PARAMETER  Any input or configured parameter is invalid.
 | |
|   @retval EFI_NOT_FOUND          Cannot find the corresponding variable.
 | |
|   @retval EFI_OUT_OF_RESOURCES   The operation is failed due to lack of resources.
 | |
|   @retval EFI_ABORTED            The operation is aborted.
 | |
|   @retval EFI_SUCCESS            The operation is completed successfully.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| IScsiConvertIfrNvDataToAttemptConfigData (
 | |
|   IN ISCSI_CONFIG_IFR_NVDATA          *IfrNvData,
 | |
|   IN OUT ISCSI_ATTEMPT_CONFIG_NVDATA  *Attempt
 | |
|   )
 | |
| {
 | |
|   EFI_IP_ADDRESS              HostIp;
 | |
|   EFI_IP_ADDRESS              SubnetMask;
 | |
|   EFI_IP_ADDRESS              Gateway;
 | |
|   CHAR16                      *MacString;
 | |
|   CHAR16                      *AttemptName1;
 | |
|   CHAR16                      *AttemptName2;
 | |
|   ISCSI_ATTEMPT_CONFIG_NVDATA *ExistAttempt;
 | |
|   ISCSI_ATTEMPT_CONFIG_NVDATA *SameNicAttempt;
 | |
|   CHAR16                      IScsiMode[64];
 | |
|   CHAR16                      IpMode[64];
 | |
|   ISCSI_NIC_INFO              *NicInfo;
 | |
|   EFI_INPUT_KEY               Key;
 | |
|   UINT8                       *AttemptConfigOrder;
 | |
|   UINTN                       AttemptConfigOrderSize;
 | |
|   UINT8                       *AttemptOrderTmp;
 | |
|   UINTN                       TotalNumber;
 | |
|   EFI_STATUS                  Status;
 | |
| 
 | |
|   if (IfrNvData == NULL || Attempt == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Update those fields which don't have INTERACTIVE attribute.
 | |
|   //
 | |
|   Attempt->SessionConfigData.ConnectRetryCount     = IfrNvData->ConnectRetryCount;
 | |
|   Attempt->SessionConfigData.ConnectTimeout        = IfrNvData->ConnectTimeout;
 | |
|   Attempt->SessionConfigData.IpMode                = IfrNvData->IpMode;
 | |
| 
 | |
|   if (IfrNvData->IpMode < IP_MODE_AUTOCONFIG) {
 | |
|     Attempt->SessionConfigData.InitiatorInfoFromDhcp = IfrNvData->InitiatorInfoFromDhcp;
 | |
|     Attempt->SessionConfigData.TargetPort            = IfrNvData->TargetPort;
 | |
| 
 | |
|     if (Attempt->SessionConfigData.TargetPort == 0) {
 | |
|       Attempt->SessionConfigData.TargetPort = ISCSI_WELL_KNOWN_PORT;
 | |
|     }
 | |
| 
 | |
|     Attempt->SessionConfigData.TargetInfoFromDhcp = IfrNvData->TargetInfoFromDhcp;
 | |
|   }
 | |
| 
 | |
|   Attempt->AuthenticationType = IfrNvData->AuthenticationType;
 | |
| 
 | |
|   if (Attempt->AuthenticationType == ISCSI_AUTH_TYPE_CHAP) {
 | |
|     Attempt->AuthConfigData.CHAP.CHAPType = IfrNvData->CHAPType;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Only do full parameter validation if iSCSI is enabled on this device.
 | |
|   //
 | |
|   if (IfrNvData->Enabled != ISCSI_DISABLED) {
 | |
|     if (Attempt->SessionConfigData.ConnectTimeout < CONNECT_MIN_TIMEOUT) {
 | |
|       CreatePopUp (
 | |
|         EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
 | |
|         &Key,
 | |
|         L"Connection Establishing Timeout is less than minimum value 100ms.",
 | |
|         NULL
 | |
|         );
 | |
| 
 | |
|       return EFI_INVALID_PARAMETER;
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Validate the address configuration of the Initiator if DHCP isn't
 | |
|     // deployed.
 | |
|     //
 | |
|     if (!Attempt->SessionConfigData.InitiatorInfoFromDhcp) {
 | |
|       CopyMem (&HostIp.v4, &Attempt->SessionConfigData.LocalIp, sizeof (HostIp.v4));
 | |
|       CopyMem (&SubnetMask.v4, &Attempt->SessionConfigData.SubnetMask, sizeof (SubnetMask.v4));
 | |
|       CopyMem (&Gateway.v4, &Attempt->SessionConfigData.Gateway, sizeof (Gateway.v4));
 | |
| 
 | |
|       if ((Gateway.Addr[0] != 0)) {
 | |
|         if (SubnetMask.Addr[0] == 0) {
 | |
|           CreatePopUp (
 | |
|             EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
 | |
|             &Key,
 | |
|             L"Gateway address is set but subnet mask is zero.",
 | |
|             NULL
 | |
|             );
 | |
| 
 | |
|           return EFI_INVALID_PARAMETER;
 | |
|         } else if (!IP4_NET_EQUAL (HostIp.Addr[0], Gateway.Addr[0], SubnetMask.Addr[0])) {
 | |
|           CreatePopUp (
 | |
|             EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
 | |
|             &Key,
 | |
|             L"Local IP and Gateway are not in the same subnet.",
 | |
|             NULL
 | |
|             );
 | |
| 
 | |
|           return EFI_INVALID_PARAMETER;
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|     //
 | |
|     // Validate target configuration if DHCP isn't deployed.
 | |
|     //
 | |
|     if (!Attempt->SessionConfigData.TargetInfoFromDhcp && Attempt->SessionConfigData.IpMode < IP_MODE_AUTOCONFIG) {
 | |
|       if (!Attempt->SessionConfigData.DnsMode) {
 | |
|         if (!IpIsUnicast (&Attempt->SessionConfigData.TargetIp, IfrNvData->IpMode)) {
 | |
|           CreatePopUp (
 | |
|             EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
 | |
|             &Key,
 | |
|             L"Target IP is invalid!",
 | |
|             NULL
 | |
|             );
 | |
|           return EFI_INVALID_PARAMETER;
 | |
|         }
 | |
|       } else {
 | |
|         if (Attempt->SessionConfigData.TargetUrl[0] == '\0') {
 | |
|           CreatePopUp (
 | |
|             EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
 | |
|             &Key,
 | |
|             L"iSCSI target Url should not be NULL!",
 | |
|             NULL
 | |
|             );
 | |
|           return EFI_INVALID_PARAMETER;
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       //
 | |
|       // Validate iSCSI target name configuration again:
 | |
|       // The format of iSCSI target name is already verified in IScsiFormCallback() when
 | |
|       // user input the name; here we only check the case user does not input the name.
 | |
|       //
 | |
|       if (Attempt->SessionConfigData.TargetName[0] == '\0') {
 | |
|         CreatePopUp (
 | |
|           EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
 | |
|           &Key,
 | |
|           L"iSCSI target name is NULL!",
 | |
|           NULL
 | |
|           );
 | |
|         return EFI_INVALID_PARAMETER;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Validate the authentication info.
 | |
|     //
 | |
|     if (IfrNvData->AuthenticationType == ISCSI_AUTH_TYPE_CHAP) {
 | |
|       if ((IfrNvData->CHAPName[0] == '\0') || (IfrNvData->CHAPSecret[0] == '\0')) {
 | |
|         CreatePopUp (
 | |
|           EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
 | |
|           &Key,
 | |
|           L"CHAP Name or CHAP Secret is invalid!",
 | |
|           NULL
 | |
|           );
 | |
| 
 | |
|         return EFI_INVALID_PARAMETER;
 | |
|       }
 | |
| 
 | |
|       if ((IfrNvData->CHAPType == ISCSI_CHAP_MUTUAL) &&
 | |
|           ((IfrNvData->ReverseCHAPName[0] == '\0') || (IfrNvData->ReverseCHAPSecret[0] == '\0'))
 | |
|           ) {
 | |
|         CreatePopUp (
 | |
|           EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
 | |
|           &Key,
 | |
|           L"Reverse CHAP Name or Reverse CHAP Secret is invalid!",
 | |
|           NULL
 | |
|           );
 | |
|         return EFI_INVALID_PARAMETER;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Check whether this attempt uses NIC which is already used by existing attempt.
 | |
|     //
 | |
|     SameNicAttempt = IScsiConfigGetAttemptByNic (Attempt, IfrNvData->Enabled);
 | |
|     if (SameNicAttempt != NULL) {
 | |
|       AttemptName1 = (CHAR16 *) AllocateZeroPool (ATTEMPT_NAME_SIZE * sizeof (CHAR16));
 | |
|       if (AttemptName1 == NULL) {
 | |
|         return EFI_OUT_OF_RESOURCES;
 | |
|       }
 | |
| 
 | |
|       AttemptName2 = (CHAR16 *) AllocateZeroPool (ATTEMPT_NAME_SIZE * sizeof (CHAR16));
 | |
|       if (AttemptName2 == NULL) {
 | |
|         FreePool (AttemptName1);
 | |
|         return EFI_OUT_OF_RESOURCES;
 | |
|       }
 | |
| 
 | |
|       AsciiStrToUnicodeStrS (Attempt->AttemptName, AttemptName1, ATTEMPT_NAME_SIZE);
 | |
|       AsciiStrToUnicodeStrS (SameNicAttempt->AttemptName, AttemptName2, ATTEMPT_NAME_SIZE);
 | |
| 
 | |
|       UnicodeSPrint (
 | |
|         mPrivate->PortString,
 | |
|         (UINTN) ISCSI_NAME_IFR_MAX_SIZE,
 | |
|         L"Warning! Attempt \"%s\" uses same NIC as Attempt \"%s\".",
 | |
|         AttemptName1,
 | |
|         AttemptName2
 | |
|         );
 | |
| 
 | |
|       CreatePopUp (
 | |
|         EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
 | |
|         &Key,
 | |
|         mPrivate->PortString,
 | |
|         NULL
 | |
|         );
 | |
| 
 | |
|       FreePool (AttemptName1);
 | |
|       FreePool (AttemptName2);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Update the iSCSI Mode data and record it in attempt help info.
 | |
|   //
 | |
|   if (IfrNvData->Enabled == ISCSI_DISABLED) {
 | |
|     UnicodeSPrint (IScsiMode, 64, L"Disabled");
 | |
|   } else if (IfrNvData->Enabled == ISCSI_ENABLED) {
 | |
|     UnicodeSPrint (IScsiMode, 64, L"Enabled");
 | |
|   } else if (IfrNvData->Enabled == ISCSI_ENABLED_FOR_MPIO) {
 | |
|     UnicodeSPrint (IScsiMode, 64, L"Enabled for MPIO");
 | |
|   }
 | |
| 
 | |
|   if (IfrNvData->IpMode == IP_MODE_IP4) {
 | |
|     UnicodeSPrint (IpMode, 64, L"IP4");
 | |
|   } else if (IfrNvData->IpMode == IP_MODE_IP6) {
 | |
|     UnicodeSPrint (IpMode, 64, L"IP6");
 | |
|   } else if (IfrNvData->IpMode == IP_MODE_AUTOCONFIG) {
 | |
|     UnicodeSPrint (IpMode, 64, L"Autoconfigure");
 | |
|   }
 | |
| 
 | |
|   NicInfo = IScsiGetNicInfoByIndex (Attempt->NicIndex);
 | |
|   if (NicInfo == NULL) {
 | |
|     return EFI_NOT_FOUND;
 | |
|   }
 | |
| 
 | |
|   MacString = (CHAR16 *) AllocateZeroPool (ISCSI_MAX_MAC_STRING_LEN * sizeof (CHAR16));
 | |
|   if (MacString == NULL) {
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   AsciiStrToUnicodeStrS (Attempt->MacString, MacString, ISCSI_MAX_MAC_STRING_LEN);
 | |
| 
 | |
|   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
 | |
|     );
 | |
| 
 | |
|   Attempt->AttemptTitleHelpToken = HiiSetString (
 | |
|                                      mCallbackInfo->RegisteredHandle,
 | |
|                                      Attempt->AttemptTitleHelpToken,
 | |
|                                      mPrivate->PortString,
 | |
|                                      NULL
 | |
|                                      );
 | |
|   if (Attempt->AttemptTitleHelpToken == 0) {
 | |
|     FreePool (MacString);
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Check whether this attempt is an existing one.
 | |
|   //
 | |
|   ExistAttempt = IScsiConfigGetAttemptByConfigIndex (Attempt->AttemptConfigIndex);
 | |
|   if (ExistAttempt != NULL) {
 | |
|     ASSERT (ExistAttempt == Attempt);
 | |
| 
 | |
|     if (IfrNvData->Enabled == ISCSI_DISABLED &&
 | |
|         Attempt->SessionConfigData.Enabled != ISCSI_DISABLED) {
 | |
| 
 | |
|       //
 | |
|       // User updates the Attempt from "Enabled"/"Enabled for MPIO" to "Disabled".
 | |
|       //
 | |
|       if (Attempt->SessionConfigData.Enabled == ISCSI_ENABLED_FOR_MPIO) {
 | |
|         if (mPrivate->MpioCount < 1) {
 | |
|           return EFI_ABORTED;
 | |
|         }
 | |
| 
 | |
|         if (--mPrivate->MpioCount == 0) {
 | |
|           mPrivate->EnableMpio = FALSE;
 | |
|         }
 | |
|       } else if (Attempt->SessionConfigData.Enabled == ISCSI_ENABLED) {
 | |
|         if (mPrivate->SinglePathCount < 1) {
 | |
|           return EFI_ABORTED;
 | |
|         }
 | |
|         mPrivate->SinglePathCount--;
 | |
|       }
 | |
| 
 | |
|     } else if (IfrNvData->Enabled == ISCSI_ENABLED_FOR_MPIO &&
 | |
|                Attempt->SessionConfigData.Enabled == ISCSI_ENABLED) {
 | |
|       //
 | |
|       // User updates the Attempt from "Enabled" to "Enabled for MPIO".
 | |
|       //
 | |
|       if (mPrivate->SinglePathCount < 1) {
 | |
|         return EFI_ABORTED;
 | |
|       }
 | |
| 
 | |
|       mPrivate->EnableMpio = TRUE;
 | |
|       mPrivate->MpioCount++;
 | |
|       mPrivate->SinglePathCount--;
 | |
| 
 | |
|     } else if (IfrNvData->Enabled == ISCSI_ENABLED &&
 | |
|                Attempt->SessionConfigData.Enabled == ISCSI_ENABLED_FOR_MPIO) {
 | |
|       //
 | |
|       // User updates the Attempt from "Enabled for MPIO" to "Enabled".
 | |
|       //
 | |
|       if (mPrivate->MpioCount < 1) {
 | |
|         return EFI_ABORTED;
 | |
|       }
 | |
| 
 | |
|       if (--mPrivate->MpioCount == 0) {
 | |
|         mPrivate->EnableMpio = FALSE;
 | |
|       }
 | |
|       mPrivate->SinglePathCount++;
 | |
| 
 | |
|     } else if (IfrNvData->Enabled != ISCSI_DISABLED &&
 | |
|                Attempt->SessionConfigData.Enabled == ISCSI_DISABLED) {
 | |
|       //
 | |
|       // User updates the Attempt from "Disabled" to "Enabled"/"Enabled for MPIO".
 | |
|       //
 | |
|       if (IfrNvData->Enabled == ISCSI_ENABLED_FOR_MPIO) {
 | |
|         mPrivate->EnableMpio = TRUE;
 | |
|         mPrivate->MpioCount++;
 | |
| 
 | |
|       } else if (IfrNvData->Enabled == ISCSI_ENABLED) {
 | |
|         mPrivate->SinglePathCount++;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|   } else if (ExistAttempt == NULL) {
 | |
|     //
 | |
|     // When a new attempt is created, pointer of the attempt is saved to
 | |
|     // mCallbackInfo->Current in IScsiConfigProcessDefault. If input Attempt
 | |
|     // does not match any existing attempt, it should be a new created attempt.
 | |
|     // Save it to system now.
 | |
|     //
 | |
| 
 | |
|     //
 | |
|     // Save current order number for this attempt.
 | |
|     //
 | |
|     AttemptConfigOrder = IScsiGetVariableAndSize (
 | |
|                            L"AttemptOrder",
 | |
|                            &gIScsiConfigGuid,
 | |
|                            &AttemptConfigOrderSize
 | |
|                            );
 | |
| 
 | |
|     TotalNumber = AttemptConfigOrderSize / sizeof (UINT8);
 | |
|     TotalNumber++;
 | |
| 
 | |
|     //
 | |
|     // Append the new created attempt order 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] = Attempt->AttemptConfigIndex;
 | |
|     AttemptConfigOrder               = AttemptOrderTmp;
 | |
|     AttemptConfigOrderSize           = TotalNumber * sizeof (UINT8);
 | |
| 
 | |
|     Status = gRT->SetVariable (
 | |
|                     L"AttemptOrder",
 | |
|                     &gIScsiConfigGuid,
 | |
|                     EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
 | |
|                     AttemptConfigOrderSize,
 | |
|                     AttemptConfigOrder
 | |
|                     );
 | |
|     FreePool (AttemptConfigOrder);
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       return Status;
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Insert new created attempt to array.
 | |
|     //
 | |
|     InsertTailList (&mPrivate->AttemptConfigs, &Attempt->Link);
 | |
|     mPrivate->AttemptCount++;
 | |
| 
 | |
|     if (IfrNvData->Enabled == ISCSI_ENABLED_FOR_MPIO) {
 | |
|       //
 | |
|       // This new Attempt is enabled for MPIO; enable the multipath mode.
 | |
|       //
 | |
|       mPrivate->EnableMpio = TRUE;
 | |
|       mPrivate->MpioCount++;
 | |
|     } else if (IfrNvData->Enabled == ISCSI_ENABLED) {
 | |
|       mPrivate->SinglePathCount++;
 | |
|     }
 | |
| 
 | |
|     IScsiConfigUpdateAttempt ();
 | |
|   }
 | |
|   Attempt->SessionConfigData.Enabled = IfrNvData->Enabled;
 | |
| 
 | |
|   //
 | |
|   // Record the user configuration information in NVR.
 | |
|   //
 | |
|   UnicodeSPrint (mPrivate->PortString, (UINTN) ISCSI_NAME_IFR_MAX_SIZE, L"Attempt %d", Attempt->AttemptConfigIndex);
 | |
| 
 | |
|   FreePool (MacString);
 | |
| 
 | |
|   return gRT->SetVariable (
 | |
|                 mPrivate->PortString,
 | |
|                 &gEfiIScsiInitiatorNameProtocolGuid,
 | |
|                 ISCSI_CONFIG_VAR_ATTR,
 | |
|                 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA),
 | |
|                 Attempt
 | |
|                 );
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Convert the IFR data configured by keyword to iSCSI configuration data.
 | |
| 
 | |
|   @param[in]  IfrNvData      Point to ISCSI_CONFIG_IFR_NVDATA.
 | |
|   @param[in]  OffSet         The offset of the variable to the configuration structure.
 | |
| 
 | |
|   @retval EFI_INVALID_PARAMETER  Any input or configured parameter is invalid.
 | |
|   @retval EFI_SUCCESS            The operation is completed successfully.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| IScsiConvertlfrNvDataToAttemptConfigDataByKeyword (
 | |
|   IN ISCSI_CONFIG_IFR_NVDATA          *IfrNvData,
 | |
|   IN UINTN                             OffSet
 | |
|   )
 | |
| {
 | |
|   ISCSI_ATTEMPT_CONFIG_NVDATA      *Attempt;
 | |
|   UINT8                            AttemptIndex;
 | |
|   UINT8                            Index;
 | |
|   UINT8                            ChapSecretLen;
 | |
|   UINT8                            ReverseChapSecretLen;
 | |
|   CHAR16                           *AttemptName1;
 | |
|   CHAR16                           *AttemptName2;
 | |
|   ISCSI_ATTEMPT_CONFIG_NVDATA      *SameNicAttempt;
 | |
|   CHAR8                            LunString[ISCSI_LUN_STR_MAX_LEN];
 | |
|   CHAR8                            IScsiName[ISCSI_NAME_MAX_SIZE];
 | |
|   CHAR8                            IpString[IP_STR_MAX_SIZE];
 | |
|   EFI_IP_ADDRESS                   HostIp;
 | |
|   EFI_IP_ADDRESS                   SubnetMask;
 | |
|   EFI_IP_ADDRESS                   Gateway;
 | |
|   EFI_INPUT_KEY                    Key;
 | |
|   UINT64                           Lun;
 | |
|   EFI_STATUS                       Status;
 | |
| 
 | |
|   Attempt = NULL;
 | |
|   ZeroMem (IScsiName, sizeof (IScsiName));
 | |
| 
 | |
|   if (OffSet < ATTEMPT_BOOTENABLE_VAR_OFFSET) {
 | |
|     return EFI_SUCCESS;
 | |
| 
 | |
|   } else if ((OffSet >= ATTEMPT_BOOTENABLE_VAR_OFFSET) && (OffSet < ATTEMPT_ADDRESS_TYPE_VAR_OFFSET)) {
 | |
|     AttemptIndex = (UINT8) ((OffSet - ATTEMPT_BOOTENABLE_VAR_OFFSET) + 1);
 | |
|     Attempt = IScsiConfigGetAttemptByConfigIndex (AttemptIndex);
 | |
|     if (Attempt == NULL) {
 | |
|       return EFI_INVALID_PARAMETER;
 | |
|     }
 | |
|     IfrNvData->Enabled = IfrNvData->ISCSIBootEnableList[AttemptIndex - 1];
 | |
|     //
 | |
|     // Validate the configuration of attempt.
 | |
|     //
 | |
|     if (IfrNvData->Enabled != ISCSI_DISABLED) {
 | |
|       //
 | |
|       // Check whether this attempt uses NIC which is already used by existing attempt.
 | |
|       //
 | |
|       SameNicAttempt = IScsiConfigGetAttemptByNic (Attempt, IfrNvData->Enabled);
 | |
|       if (SameNicAttempt != NULL) {
 | |
|         AttemptName1 = (CHAR16 *) AllocateZeroPool (ATTEMPT_NAME_SIZE * sizeof (CHAR16));
 | |
|         if (AttemptName1 == NULL) {
 | |
|           return EFI_OUT_OF_RESOURCES;
 | |
|         }
 | |
| 
 | |
|         AttemptName2 = (CHAR16 *) AllocateZeroPool (ATTEMPT_NAME_SIZE * sizeof (CHAR16));
 | |
|         if (AttemptName2 == NULL) {
 | |
|           FreePool (AttemptName1);
 | |
|           return EFI_OUT_OF_RESOURCES;
 | |
|         }
 | |
| 
 | |
|         AsciiStrToUnicodeStrS (Attempt->AttemptName, AttemptName1, ATTEMPT_NAME_SIZE);
 | |
|         AsciiStrToUnicodeStrS (SameNicAttempt->AttemptName, AttemptName2, ATTEMPT_NAME_SIZE);
 | |
| 
 | |
|         UnicodeSPrint (
 | |
|           mPrivate->PortString,
 | |
|           (UINTN) ISCSI_NAME_IFR_MAX_SIZE,
 | |
|           L"Warning! \"%s\" uses same NIC as Attempt \"%s\".",
 | |
|           AttemptName1,
 | |
|           AttemptName2
 | |
|           );
 | |
| 
 | |
|         CreatePopUp (
 | |
|           EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
 | |
|           &Key,
 | |
|           mPrivate->PortString,
 | |
|           NULL
 | |
|           );
 | |
| 
 | |
|         FreePool (AttemptName1);
 | |
|         FreePool (AttemptName2);
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     if (IfrNvData->Enabled == ISCSI_DISABLED &&
 | |
|         Attempt->SessionConfigData.Enabled != ISCSI_DISABLED) {
 | |
| 
 | |
|       //
 | |
|       // User updates the Attempt from "Enabled"/"Enabled for MPIO" to "Disabled".
 | |
|       //
 | |
|       if (Attempt->SessionConfigData.Enabled == ISCSI_ENABLED_FOR_MPIO) {
 | |
|         if (mPrivate->MpioCount < 1) {
 | |
|           return EFI_ABORTED;
 | |
|         }
 | |
| 
 | |
|         if (--mPrivate->MpioCount == 0) {
 | |
|           mPrivate->EnableMpio = FALSE;
 | |
|         }
 | |
|       } else if (Attempt->SessionConfigData.Enabled == ISCSI_ENABLED) {
 | |
|         if (mPrivate->SinglePathCount < 1) {
 | |
|           return EFI_ABORTED;
 | |
|         }
 | |
|         mPrivate->SinglePathCount--;
 | |
|       }
 | |
| 
 | |
|     } else if (IfrNvData->Enabled == ISCSI_ENABLED_FOR_MPIO &&
 | |
|                Attempt->SessionConfigData.Enabled == ISCSI_ENABLED) {
 | |
|       //
 | |
|       // User updates the Attempt from "Enabled" to "Enabled for MPIO".
 | |
|       //
 | |
|       if (mPrivate->SinglePathCount < 1) {
 | |
|         return EFI_ABORTED;
 | |
|       }
 | |
| 
 | |
|       mPrivate->EnableMpio = TRUE;
 | |
|       mPrivate->MpioCount++;
 | |
|       mPrivate->SinglePathCount--;
 | |
| 
 | |
|     } else if (IfrNvData->Enabled == ISCSI_ENABLED &&
 | |
|                Attempt->SessionConfigData.Enabled == ISCSI_ENABLED_FOR_MPIO) {
 | |
|       //
 | |
|       // User updates the Attempt from "Enabled for MPIO" to "Enabled".
 | |
|       //
 | |
|       if (mPrivate->MpioCount < 1) {
 | |
|         return EFI_ABORTED;
 | |
|       }
 | |
| 
 | |
|       if (--mPrivate->MpioCount == 0) {
 | |
|         mPrivate->EnableMpio = FALSE;
 | |
|       }
 | |
|       mPrivate->SinglePathCount++;
 | |
| 
 | |
|     } else if (IfrNvData->Enabled != ISCSI_DISABLED &&
 | |
|                Attempt->SessionConfigData.Enabled == ISCSI_DISABLED) {
 | |
|       //
 | |
|       // User updates the Attempt from "Disabled" to "Enabled"/"Enabled for MPIO".
 | |
|       //
 | |
|       if (IfrNvData->Enabled == ISCSI_ENABLED_FOR_MPIO) {
 | |
|         mPrivate->EnableMpio = TRUE;
 | |
|         mPrivate->MpioCount++;
 | |
| 
 | |
|       } else if (IfrNvData->Enabled == ISCSI_ENABLED) {
 | |
|         mPrivate->SinglePathCount++;
 | |
|       }
 | |
|     }
 | |
|     Attempt->SessionConfigData.Enabled = IfrNvData->Enabled;
 | |
| 
 | |
|   } else if ((OffSet >= ATTEMPT_ADDRESS_TYPE_VAR_OFFSET) && (OffSet < ATTEMPT_CONNECT_RETRY_VAR_OFFSET)) {
 | |
|     AttemptIndex = (UINT8) ((OffSet - ATTEMPT_ADDRESS_TYPE_VAR_OFFSET) + 1);
 | |
|     Attempt = IScsiConfigGetAttemptByConfigIndex (AttemptIndex);
 | |
|     if (Attempt == NULL) {
 | |
|       return EFI_INVALID_PARAMETER;
 | |
|     }
 | |
|     Attempt->SessionConfigData.IpMode = IfrNvData->ISCSIIpAddressTypeList[AttemptIndex - 1];
 | |
|     if (Attempt->SessionConfigData.IpMode < IP_MODE_AUTOCONFIG) {
 | |
|       Attempt->AutoConfigureMode = 0;
 | |
|     }
 | |
| 
 | |
|   } else if ((OffSet >= ATTEMPT_CONNECT_RETRY_VAR_OFFSET) && (OffSet < ATTEMPT_CONNECT_TIMEOUT_VAR_OFFSET)) {
 | |
|     AttemptIndex = (UINT8) ((OffSet - ATTEMPT_CONNECT_RETRY_VAR_OFFSET) + 1);
 | |
|     Attempt = IScsiConfigGetAttemptByConfigIndex (AttemptIndex);
 | |
|     if (Attempt == NULL) {
 | |
|       return EFI_INVALID_PARAMETER;
 | |
|     }
 | |
| 
 | |
|     if (IfrNvData->ISCSIConnectRetry[AttemptIndex - 1] > CONNECT_MAX_RETRY) {
 | |
|       CreatePopUp (
 | |
|           EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
 | |
|           &Key,
 | |
|           L"The minimum value is 0 and the maximum is 16. 0 means no retry.",
 | |
|           NULL
 | |
|           );
 | |
|       return EFI_INVALID_PARAMETER;
 | |
|     }
 | |
|     Attempt->SessionConfigData.ConnectRetryCount = IfrNvData->ISCSIConnectRetry[AttemptIndex - 1];
 | |
| 
 | |
|   } else if ((OffSet >= ATTEMPT_CONNECT_TIMEOUT_VAR_OFFSET) && (OffSet < ATTEMPT_INITIATOR_VIA_DHCP_VAR_OFFSET)) {
 | |
|     AttemptIndex = (UINT8) ((OffSet - ATTEMPT_CONNECT_TIMEOUT_VAR_OFFSET) / 2 + 1);
 | |
|     Attempt = IScsiConfigGetAttemptByConfigIndex (AttemptIndex);
 | |
|     if (Attempt == NULL) {
 | |
|       return EFI_INVALID_PARAMETER;
 | |
|     }
 | |
| 
 | |
|     if ((IfrNvData->ISCSIConnectTimeout[AttemptIndex - 1] < CONNECT_MIN_TIMEOUT) ||
 | |
|         (IfrNvData->ISCSIConnectTimeout[AttemptIndex - 1] > CONNECT_MAX_TIMEOUT)) {
 | |
|       CreatePopUp (
 | |
|         EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
 | |
|         &Key,
 | |
|         L"The minimum value is 100 milliseconds and the maximum is 20 seconds.",
 | |
|         NULL
 | |
|         );
 | |
|       return EFI_INVALID_PARAMETER;
 | |
|     }
 | |
| 
 | |
|     Attempt->SessionConfigData.ConnectTimeout = IfrNvData->ISCSIConnectTimeout[AttemptIndex - 1];
 | |
|     if (Attempt->SessionConfigData.ConnectTimeout == 0) {
 | |
|       Attempt->SessionConfigData.ConnectTimeout = CONNECT_DEFAULT_TIMEOUT;
 | |
|     }
 | |
| 
 | |
|   } else if ((OffSet >= ATTEMPT_INITIATOR_VIA_DHCP_VAR_OFFSET) && (OffSet < ATTEMPT_TARGET_VIA_DHCP_VAR_OFFSET)) {
 | |
|     AttemptIndex = (UINT8) ((OffSet - ATTEMPT_INITIATOR_VIA_DHCP_VAR_OFFSET) + 1);
 | |
|     Attempt = IScsiConfigGetAttemptByConfigIndex (AttemptIndex);
 | |
|     if (Attempt == NULL) {
 | |
|       return EFI_INVALID_PARAMETER;
 | |
|     }
 | |
|     Attempt->SessionConfigData.InitiatorInfoFromDhcp = IfrNvData->ISCSIInitiatorInfoViaDHCP[AttemptIndex - 1];
 | |
| 
 | |
|   } else if ((OffSet >= ATTEMPT_TARGET_VIA_DHCP_VAR_OFFSET) && (OffSet < ATTEMPT_TARGET_TCP_PORT_VAR_OFFSET)) {
 | |
|     AttemptIndex = (UINT8) ((OffSet - ATTEMPT_TARGET_VIA_DHCP_VAR_OFFSET) + 1);
 | |
|     Attempt = IScsiConfigGetAttemptByConfigIndex (AttemptIndex);
 | |
|     if (Attempt == NULL) {
 | |
|       return EFI_INVALID_PARAMETER;
 | |
|     }
 | |
| 
 | |
|     if ((Attempt->SessionConfigData.IpMode < IP_MODE_AUTOCONFIG) && (Attempt->SessionConfigData.InitiatorInfoFromDhcp)) {
 | |
|       Attempt->SessionConfigData.TargetInfoFromDhcp = IfrNvData->ISCSITargetInfoViaDHCP[AttemptIndex - 1];
 | |
|     } else {
 | |
|       CreatePopUp (
 | |
|         EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
 | |
|         &Key,
 | |
|         L"Invalid Configuration, Check value of IpMode or Enable DHCP!",
 | |
|         NULL
 | |
|         );
 | |
|       return EFI_INVALID_PARAMETER;
 | |
|     }
 | |
| 
 | |
|   } else if ((OffSet >= ATTEMPT_TARGET_TCP_PORT_VAR_OFFSET) && (OffSet < ATTEMPT_AUTHENTICATION_METHOD_VAR_OFFSET)) {
 | |
|     AttemptIndex = (UINT8) ((OffSet - ATTEMPT_TARGET_TCP_PORT_VAR_OFFSET) / 2 + 1);
 | |
|     Attempt = IScsiConfigGetAttemptByConfigIndex (AttemptIndex);
 | |
|     if (Attempt == NULL) {
 | |
|       return EFI_INVALID_PARAMETER;
 | |
|     }
 | |
|     if ((Attempt->SessionConfigData.IpMode < IP_MODE_AUTOCONFIG) && (!Attempt->SessionConfigData.TargetInfoFromDhcp)) {
 | |
|       Attempt->SessionConfigData.TargetPort = IfrNvData->ISCSITargetTcpPort[AttemptIndex - 1];
 | |
|       if (Attempt->SessionConfigData.TargetPort == 0) {
 | |
|         Attempt->SessionConfigData.TargetPort = ISCSI_WELL_KNOWN_PORT;
 | |
|       }
 | |
|     } else {
 | |
|       CreatePopUp (
 | |
|         EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
 | |
|         &Key,
 | |
|         L"Invalid Configuration, Check value of IpMode or Target Via DHCP!",
 | |
|         NULL
 | |
|         );
 | |
|       return EFI_INVALID_PARAMETER;
 | |
|     }
 | |
| 
 | |
|   } else if ((OffSet >= ATTEMPT_AUTHENTICATION_METHOD_VAR_OFFSET) && (OffSet < ATTEMPT_CHARTYPE_VAR_OFFSET)) {
 | |
|     AttemptIndex = (UINT8) ((OffSet - ATTEMPT_AUTHENTICATION_METHOD_VAR_OFFSET) + 1);
 | |
|     Attempt = IScsiConfigGetAttemptByConfigIndex (AttemptIndex);
 | |
|     if (Attempt == NULL) {
 | |
|       return EFI_INVALID_PARAMETER;
 | |
|     }
 | |
| 
 | |
|     Attempt->AuthenticationType = IfrNvData->ISCSIAuthenticationMethod[AttemptIndex - 1];
 | |
| 
 | |
|   } else if ((OffSet >= ATTEMPT_CHARTYPE_VAR_OFFSET) && (OffSet < ATTEMPT_ISID_VAR_OFFSET)) {
 | |
|     AttemptIndex = (UINT8) ((OffSet - ATTEMPT_CHARTYPE_VAR_OFFSET) + 1);
 | |
|     Attempt = IScsiConfigGetAttemptByConfigIndex (AttemptIndex);
 | |
|     if (Attempt == NULL) {
 | |
|       return EFI_INVALID_PARAMETER;
 | |
|     }
 | |
|     if (Attempt->AuthenticationType == ISCSI_AUTH_TYPE_CHAP) {
 | |
|       Attempt->AuthConfigData.CHAP.CHAPType = IfrNvData->ISCSIChapType[AttemptIndex - 1];
 | |
|     }
 | |
| 
 | |
|   } else if (OffSet >= ATTEMPT_ISID_VAR_OFFSET) {
 | |
|     Index = (UINT8) ((OffSet - ATTEMPT_ISID_VAR_OFFSET) / sizeof (KEYWORD_STR));
 | |
|     AttemptIndex = Index + 1;
 | |
|     Attempt = IScsiConfigGetAttemptByConfigIndex (AttemptIndex);
 | |
|     if (Attempt == NULL) {
 | |
|       return EFI_INVALID_PARAMETER;
 | |
|     }
 | |
| 
 | |
|     OffSet = OffSet - Index * sizeof (KEYWORD_STR);
 | |
| 
 | |
|     if ((OffSet >= ATTEMPT_ISID_VAR_OFFSET) && (OffSet < ATTEMPT_INITIATOR_IP_ADDRESS_VAR_OFFSET)) {
 | |
|       IScsiParseIsIdFromString (IfrNvData->Keyword[Index].ISCSIIsId, Attempt->SessionConfigData.IsId);
 | |
| 
 | |
|     }  else if ((OffSet >= ATTEMPT_INITIATOR_IP_ADDRESS_VAR_OFFSET) && (OffSet < ATTEMPT_INITIATOR_NET_MASK_VAR_OFFSET)) {
 | |
|       if ((Attempt->SessionConfigData.IpMode == IP_MODE_IP4) && (!Attempt->SessionConfigData.InitiatorInfoFromDhcp)) {
 | |
|         //
 | |
|         // Config Local ip
 | |
|         //
 | |
|         Status = NetLibStrToIp4 (IfrNvData->Keyword[Index].ISCSIInitiatorIpAddress, &HostIp.v4);
 | |
|         if (EFI_ERROR (Status) || ((Attempt->SessionConfigData.SubnetMask.Addr[0] != 0) &&
 | |
|              !NetIp4IsUnicast (NTOHL (HostIp.Addr[0]), NTOHL(*(UINT32*)Attempt->SessionConfigData.SubnetMask.Addr)))) {
 | |
|           CreatePopUp (
 | |
|             EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
 | |
|             &Key,
 | |
|             L"Invalid IP address!",
 | |
|             NULL
 | |
|             );
 | |
|           return EFI_INVALID_PARAMETER;
 | |
|         } else {
 | |
|           CopyMem (&Attempt->SessionConfigData.LocalIp, &HostIp.v4, sizeof (HostIp.v4));
 | |
|         }
 | |
|       } else {
 | |
|         CreatePopUp (
 | |
|           EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
 | |
|           &Key,
 | |
|           L"Invalid Configuration, Check value of IpMode or Enable DHCP!",
 | |
|           NULL
 | |
|           );
 | |
|         return EFI_INVALID_PARAMETER;
 | |
|       }
 | |
| 
 | |
|     } else if ((OffSet >= ATTEMPT_INITIATOR_NET_MASK_VAR_OFFSET) && (OffSet < ATTEMPT_INITIATOR_GATE_WAY_VAR_OFFSET)) {
 | |
|       if ((Attempt->SessionConfigData.IpMode == IP_MODE_IP4) && (!Attempt->SessionConfigData.InitiatorInfoFromDhcp)) {
 | |
|         Status = NetLibStrToIp4 (IfrNvData->Keyword[Index].ISCSIInitiatorNetmask, &SubnetMask.v4);
 | |
|         if (EFI_ERROR (Status) || ((SubnetMask.Addr[0] != 0) && (IScsiGetSubnetMaskPrefixLength (&SubnetMask.v4) == 0))) {
 | |
|           CreatePopUp (
 | |
|             EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
 | |
|             &Key,
 | |
|             L"Invalid Subnet Mask!",
 | |
|             NULL
 | |
|             );
 | |
|           return EFI_INVALID_PARAMETER;
 | |
|         } else {
 | |
|           CopyMem (&Attempt->SessionConfigData.SubnetMask, &SubnetMask.v4, sizeof (SubnetMask.v4));
 | |
|         }
 | |
|       } else {
 | |
|         CreatePopUp (
 | |
|           EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
 | |
|           &Key,
 | |
|           L"Invalid Configuration, Check value of IpMode or Enable DHCP!",
 | |
|           NULL
 | |
|           );
 | |
|         return EFI_INVALID_PARAMETER;
 | |
|       }
 | |
| 
 | |
|     } else if ((OffSet >= ATTEMPT_INITIATOR_GATE_WAY_VAR_OFFSET) && (OffSet < ATTEMPT_TARGET_NAME_VAR_OFFSET)) {
 | |
|       if ((Attempt->SessionConfigData.IpMode == IP_MODE_IP4) && (!Attempt->SessionConfigData.InitiatorInfoFromDhcp)) {
 | |
|         Status = NetLibStrToIp4 (IfrNvData->Keyword[Index].ISCSIInitiatorGateway, &Gateway.v4);
 | |
|         if (EFI_ERROR (Status) ||
 | |
|           ((Gateway.Addr[0] != 0) && (Attempt->SessionConfigData.SubnetMask.Addr[0] != 0) &&
 | |
|              !NetIp4IsUnicast (NTOHL (Gateway.Addr[0]), NTOHL(*(UINT32*)Attempt->SessionConfigData.SubnetMask.Addr)))) {
 | |
|           CreatePopUp (
 | |
|             EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
 | |
|             &Key,
 | |
|             L"Invalid Gateway!",
 | |
|             NULL
 | |
|             );
 | |
|           return EFI_INVALID_PARAMETER;
 | |
|         } else {
 | |
|           CopyMem (&Attempt->SessionConfigData.Gateway, &Gateway.v4, sizeof (Gateway.v4));
 | |
|         }
 | |
|       } else {
 | |
|         CreatePopUp (
 | |
|           EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
 | |
|           &Key,
 | |
|           L"Invalid Configuration, Check value of IpMode or Enable DHCP!",
 | |
|           NULL
 | |
|           );
 | |
|         return EFI_INVALID_PARAMETER;
 | |
|       }
 | |
| 
 | |
|     } else if ((OffSet >= ATTEMPT_TARGET_NAME_VAR_OFFSET) && (OffSet < ATTEMPT_TARGET_IP_ADDRESS_VAR_OFFSET)) {
 | |
|       if ((Attempt->SessionConfigData.IpMode < IP_MODE_AUTOCONFIG) && (!Attempt->SessionConfigData.TargetInfoFromDhcp)) {
 | |
|         UnicodeStrToAsciiStrS (IfrNvData->Keyword[Index].ISCSITargetName, IScsiName, ISCSI_NAME_MAX_SIZE);
 | |
|         Status = IScsiNormalizeName (IScsiName, AsciiStrLen (IScsiName));
 | |
|         if (EFI_ERROR (Status)) {
 | |
|           CreatePopUp (
 | |
|             EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
 | |
|             &Key,
 | |
|             L"Invalid iSCSI Name!",
 | |
|             NULL
 | |
|             );
 | |
|         } else {
 | |
|           AsciiStrCpyS (Attempt->SessionConfigData.TargetName, ISCSI_NAME_MAX_SIZE, IScsiName);
 | |
|         }
 | |
|         if (Attempt->SessionConfigData.Enabled != ISCSI_DISABLED) {
 | |
|           if (Attempt->SessionConfigData.TargetName[0] == L'\0') {
 | |
|             CreatePopUp (
 | |
|               EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
 | |
|               &Key,
 | |
|               L"iSCSI target name is NULL!",
 | |
|               NULL
 | |
|               );
 | |
|             return EFI_INVALID_PARAMETER;
 | |
|           }
 | |
|         }
 | |
|       } else {
 | |
|         CreatePopUp (
 | |
|           EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
 | |
|           &Key,
 | |
|           L"Invalid Configuration, Check value of IpMode or Target Via DHCP!",
 | |
|           NULL
 | |
|           );
 | |
|         return EFI_INVALID_PARAMETER;
 | |
|       }
 | |
| 
 | |
|     } else if ((OffSet >= ATTEMPT_TARGET_IP_ADDRESS_VAR_OFFSET) && (OffSet < ATTEMPT_LUN_VAR_OFFSET)) {
 | |
|       if ((Attempt->SessionConfigData.IpMode < IP_MODE_AUTOCONFIG) && (!Attempt->SessionConfigData.TargetInfoFromDhcp)) {
 | |
|         UnicodeStrToAsciiStrS (IfrNvData->Keyword[Index].ISCSITargetIpAddress, IpString, sizeof (IpString));
 | |
|         Status = IScsiAsciiStrToIp (IpString, Attempt->SessionConfigData.IpMode, &HostIp);
 | |
|         if (EFI_ERROR (Status) || !IpIsUnicast (&HostIp, Attempt->SessionConfigData.IpMode)) {
 | |
|           Attempt->SessionConfigData.DnsMode = TRUE;
 | |
|           ZeroMem (&Attempt->SessionConfigData.TargetIp, sizeof (Attempt->SessionConfigData.TargetIp));
 | |
|           UnicodeStrToAsciiStrS (IfrNvData->Keyword[Index].ISCSITargetIpAddress, Attempt->SessionConfigData.TargetUrl, ISCSI_NAME_MAX_SIZE);
 | |
|         } else {
 | |
|           Attempt->SessionConfigData.DnsMode = FALSE;
 | |
|           CopyMem (&Attempt->SessionConfigData.TargetIp, &HostIp, sizeof (HostIp));
 | |
|         }
 | |
|       } else {
 | |
|         CreatePopUp (
 | |
|           EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
 | |
|           &Key,
 | |
|           L"Invalid Configuration, Check value of IpMode or Target Via DHCP!",
 | |
|           NULL
 | |
|           );
 | |
|         return EFI_INVALID_PARAMETER;
 | |
|       }
 | |
| 
 | |
|     } else if ((OffSet >= ATTEMPT_LUN_VAR_OFFSET) && (OffSet < ATTEMPT_CHAR_USER_NAME_VAR_OFFSET)) {
 | |
|       if ((Attempt->SessionConfigData.IpMode < IP_MODE_AUTOCONFIG) && (Attempt->SessionConfigData.TargetInfoFromDhcp == 0)) {
 | |
|         //
 | |
|         // Config LUN.
 | |
|         //
 | |
|         UnicodeStrToAsciiStrS (IfrNvData->Keyword[Index].ISCSILun, LunString, ISCSI_LUN_STR_MAX_LEN);
 | |
|         Status = IScsiAsciiStrToLun (LunString, (UINT8 *) &Lun);
 | |
|         if (EFI_ERROR (Status)) {
 | |
|           CreatePopUp (
 | |
|             EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
 | |
|             &Key,
 | |
|             L"Invalid LUN string, Examples are: 4752-3A4F-6b7e-2F99, 6734-9-156f-127, 4186-9!",
 | |
|             NULL
 | |
|             );
 | |
|         } else {
 | |
|           CopyMem (&Attempt->SessionConfigData.BootLun, &Lun, sizeof (Lun));
 | |
|         }
 | |
|       } else {
 | |
|         CreatePopUp (
 | |
|           EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
 | |
|           &Key,
 | |
|           L"Invalid Configuration, Check value of IpMode or Target Via DHCP!",
 | |
|           NULL
 | |
|           );
 | |
|         return EFI_INVALID_PARAMETER;
 | |
|       }
 | |
| 
 | |
|     } else if ((OffSet >= ATTEMPT_CHAR_USER_NAME_VAR_OFFSET) && (OffSet < ATTEMPT_CHAR_SECRET_VAR_OFFSET)) {
 | |
|       if (Attempt->AuthenticationType == ISCSI_AUTH_TYPE_CHAP) {
 | |
|         UnicodeStrToAsciiStrS (
 | |
|           IfrNvData->Keyword[Index].ISCSIChapUsername,
 | |
|           Attempt->AuthConfigData.CHAP.CHAPName,
 | |
|           ISCSI_CHAP_NAME_STORAGE
 | |
|           );
 | |
| 
 | |
|         if (Attempt->SessionConfigData.Enabled != ISCSI_DISABLED) {
 | |
|           if (IfrNvData->Keyword[Index].ISCSIChapUsername[0] == L'\0') {
 | |
|             CreatePopUp (
 | |
|               EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
 | |
|               &Key,
 | |
|               L"CHAP Name is invalid!",
 | |
|               NULL
 | |
|               );
 | |
|             return EFI_INVALID_PARAMETER;
 | |
|           }
 | |
|         }
 | |
|       } else {
 | |
|         CreatePopUp (
 | |
|           EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
 | |
|           &Key,
 | |
|           L"Invalid Configuration, Check value of AuthenticationType!",
 | |
|           NULL
 | |
|           );
 | |
|         return EFI_INVALID_PARAMETER;
 | |
|       }
 | |
| 
 | |
|     } else if ((OffSet >= ATTEMPT_CHAR_SECRET_VAR_OFFSET) && (OffSet < ATTEMPT_CHAR_REVERSE_USER_NAME_VAR_OFFSET)) {
 | |
|       if (Attempt->AuthenticationType == ISCSI_AUTH_TYPE_CHAP) {
 | |
|         ChapSecretLen = (UINT8)StrLen (IfrNvData->Keyword[Index].ISCSIChapSecret);
 | |
|         UnicodeStrToAsciiStrS (
 | |
|           IfrNvData->Keyword[Index].ISCSIChapSecret,
 | |
|           Attempt->AuthConfigData.CHAP.CHAPSecret,
 | |
|           ISCSI_CHAP_SECRET_STORAGE
 | |
|           );
 | |
| 
 | |
|         if (Attempt->SessionConfigData.Enabled != ISCSI_DISABLED) {
 | |
|           if ((ChapSecretLen < ISCSI_CHAP_SECRET_MIN_LEN) || (ChapSecretLen > ISCSI_CHAP_SECRET_MAX_LEN)) {
 | |
|             CreatePopUp (
 | |
|               EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
 | |
|               &Key,
 | |
|               L"The Chap Secret minimum length is 12 bytes and the maximum length is 16 bytes.",
 | |
|               NULL
 | |
|               );
 | |
|             return EFI_INVALID_PARAMETER;
 | |
|           }
 | |
|         }
 | |
|       } else {
 | |
|         CreatePopUp (
 | |
|           EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
 | |
|           &Key,
 | |
|           L"Invalid Configuration, Check value of AuthenticationType!",
 | |
|           NULL
 | |
|           );
 | |
|         return EFI_INVALID_PARAMETER;
 | |
|       }
 | |
| 
 | |
|     } else if ((OffSet >= ATTEMPT_CHAR_REVERSE_USER_NAME_VAR_OFFSET) && (OffSet < ATTEMPT_CHAR_REVERSE_SECRET_VAR_OFFSET)) {
 | |
|       if (Attempt->AuthConfigData.CHAP.CHAPType == ISCSI_CHAP_MUTUAL) {
 | |
|         UnicodeStrToAsciiStrS (
 | |
|           IfrNvData->Keyword[Index].ISCSIReverseChapUsername,
 | |
|           Attempt->AuthConfigData.CHAP.ReverseCHAPName,
 | |
|           ISCSI_CHAP_NAME_STORAGE
 | |
|           );
 | |
|         if (Attempt->SessionConfigData.Enabled != ISCSI_DISABLED) {
 | |
|           if (IfrNvData->Keyword[Index].ISCSIReverseChapUsername[0] == L'\0') {
 | |
|             CreatePopUp (
 | |
|               EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
 | |
|               &Key,
 | |
|               L"Reverse CHAP Name is invalid!",
 | |
|               NULL
 | |
|               );
 | |
|             return EFI_INVALID_PARAMETER;
 | |
|           }
 | |
|         }
 | |
|       } else {
 | |
|         CreatePopUp (
 | |
|           EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
 | |
|           &Key,
 | |
|           L"Invalid Configuration, Check value of AuthenticationType or Chap Type!",
 | |
|           NULL
 | |
|           );
 | |
|         return EFI_INVALID_PARAMETER;
 | |
|       }
 | |
| 
 | |
|     } else if (OffSet >= ATTEMPT_CHAR_REVERSE_SECRET_VAR_OFFSET) {
 | |
|       if (Attempt->AuthConfigData.CHAP.CHAPType == ISCSI_CHAP_MUTUAL) {
 | |
|         ReverseChapSecretLen = (UINT8)StrLen (IfrNvData->Keyword[Index].ISCSIReverseChapSecret);
 | |
|         UnicodeStrToAsciiStrS (
 | |
|           IfrNvData->Keyword[Index].ISCSIReverseChapSecret,
 | |
|           Attempt->AuthConfigData.CHAP.ReverseCHAPSecret,
 | |
|           ISCSI_CHAP_SECRET_STORAGE
 | |
|           );
 | |
| 
 | |
|         if (Attempt->SessionConfigData.Enabled != ISCSI_DISABLED) {
 | |
|           if ((ReverseChapSecretLen < ISCSI_CHAP_SECRET_MIN_LEN) || (ReverseChapSecretLen > ISCSI_CHAP_SECRET_MAX_LEN)) {
 | |
|             CreatePopUp (
 | |
|               EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
 | |
|               &Key,
 | |
|               L"The Reverse CHAP Secret minimum length is 12 bytes and the maximum length is 16 bytes.",
 | |
|               NULL
 | |
|               );
 | |
|             return EFI_INVALID_PARAMETER;
 | |
|           }
 | |
|         }
 | |
|       } else {
 | |
|         CreatePopUp (
 | |
|           EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
 | |
|           &Key,
 | |
|           L"Invalid Configuration, Check value of AuthenticationType or Chap Type!",
 | |
|           NULL
 | |
|           );
 | |
|         return EFI_INVALID_PARAMETER;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
| 
 | |
| 
 | |
|   //
 | |
|   // Record the user configuration information in NVR.
 | |
|   //
 | |
|   ASSERT (Attempt != NULL);
 | |
|   UnicodeSPrint (mPrivate->PortString, (UINTN) ISCSI_NAME_IFR_MAX_SIZE, L"Attempt %d", Attempt->AttemptConfigIndex);
 | |
|   return gRT->SetVariable (
 | |
|                 mPrivate->PortString,
 | |
|                 &gEfiIScsiInitiatorNameProtocolGuid,
 | |
|                 ISCSI_CONFIG_VAR_ATTR,
 | |
|                 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA),
 | |
|                 Attempt
 | |
|                 );
 | |
| 
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Create Hii Extend Label OpCode as the start opcode and end opcode. It is
 | |
|   a help function.
 | |
| 
 | |
|   @param[in]  StartLabelNumber   The number of start label.
 | |
|   @param[out] StartOpCodeHandle  Points to the start opcode handle.
 | |
|   @param[out] StartLabel         Points to the created start opcode.
 | |
|   @param[out] EndOpCodeHandle    Points to the end opcode handle.
 | |
|   @param[out] EndLabel           Points to the created end opcode.
 | |
| 
 | |
|   @retval EFI_OUT_OF_RESOURCES   Do not have sufficient resource to finish this
 | |
|                                  operation.
 | |
|   @retval EFI_INVALID_PARAMETER  Any input parameter is invalid.
 | |
|   @retval EFI_SUCCESS            The operation is completed successfully.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| IScsiCreateOpCode (
 | |
|   IN  UINT16                        StartLabelNumber,
 | |
|   OUT VOID                          **StartOpCodeHandle,
 | |
|   OUT EFI_IFR_GUID_LABEL            **StartLabel,
 | |
|   OUT VOID                          **EndOpCodeHandle,
 | |
|   OUT EFI_IFR_GUID_LABEL            **EndLabel
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                        Status;
 | |
|   EFI_IFR_GUID_LABEL                *InternalStartLabel;
 | |
|   EFI_IFR_GUID_LABEL                *InternalEndLabel;
 | |
| 
 | |
|   if (StartOpCodeHandle == NULL || StartLabel == NULL || EndOpCodeHandle == NULL || EndLabel == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   *StartOpCodeHandle = NULL;
 | |
|   *EndOpCodeHandle   = NULL;
 | |
|   Status             = EFI_OUT_OF_RESOURCES;
 | |
| 
 | |
|   //
 | |
|   // Initialize the container for dynamic opcodes.
 | |
|   //
 | |
|   *StartOpCodeHandle = HiiAllocateOpCodeHandle ();
 | |
|   if (*StartOpCodeHandle == NULL) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   *EndOpCodeHandle = HiiAllocateOpCodeHandle ();
 | |
|   if (*EndOpCodeHandle == NULL) {
 | |
|     goto Exit;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Create Hii Extend Label OpCode as the start opcode.
 | |
|   //
 | |
|   InternalStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
 | |
|                                                 *StartOpCodeHandle,
 | |
|                                                 &gEfiIfrTianoGuid,
 | |
|                                                 NULL,
 | |
|                                                 sizeof (EFI_IFR_GUID_LABEL)
 | |
|                                                 );
 | |
|   if (InternalStartLabel == NULL) {
 | |
|     goto Exit;
 | |
|   }
 | |
| 
 | |
|   InternalStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
 | |
|   InternalStartLabel->Number       = StartLabelNumber;
 | |
| 
 | |
|   //
 | |
|   // Create Hii Extend Label OpCode as the end opcode.
 | |
|   //
 | |
|   InternalEndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
 | |
|                                               *EndOpCodeHandle,
 | |
|                                               &gEfiIfrTianoGuid,
 | |
|                                               NULL,
 | |
|                                               sizeof (EFI_IFR_GUID_LABEL)
 | |
|                                               );
 | |
|   if (InternalEndLabel == NULL) {
 | |
|     goto Exit;
 | |
|   }
 | |
| 
 | |
|   InternalEndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
 | |
|   InternalEndLabel->Number       = LABEL_END;
 | |
| 
 | |
|   *StartLabel = InternalStartLabel;
 | |
|   *EndLabel   = InternalEndLabel;
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| 
 | |
| Exit:
 | |
| 
 | |
|   if (*StartOpCodeHandle != NULL) {
 | |
|     HiiFreeOpCodeHandle (*StartOpCodeHandle);
 | |
|   }
 | |
| 
 | |
|   if (*EndOpCodeHandle != NULL) {
 | |
|     HiiFreeOpCodeHandle (*EndOpCodeHandle);
 | |
|   }
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Update the MAIN form to display the configured attempts.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| IScsiConfigUpdateAttempt (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   LIST_ENTRY                    *Entry;
 | |
|   ISCSI_ATTEMPT_CONFIG_NVDATA   *AttemptConfigData;
 | |
|   VOID                          *StartOpCodeHandle;
 | |
|   EFI_IFR_GUID_LABEL            *StartLabel;
 | |
|   VOID                          *EndOpCodeHandle;
 | |
|   EFI_IFR_GUID_LABEL            *EndLabel;
 | |
|   EFI_STATUS                    Status;
 | |
| 
 | |
|   Status = IScsiCreateOpCode (
 | |
|              ATTEMPT_ENTRY_LABEL,
 | |
|              &StartOpCodeHandle,
 | |
|              &StartLabel,
 | |
|              &EndOpCodeHandle,
 | |
|              &EndLabel
 | |
|              );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return ;
 | |
|   }
 | |
| 
 | |
|   NET_LIST_FOR_EACH (Entry, &mPrivate->AttemptConfigs) {
 | |
|     AttemptConfigData = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);
 | |
|     if (AttemptConfigData->Actived == ISCSI_ACTIVE_ENABLED) {
 | |
|       //
 | |
|       // Update Attempt Help Info.
 | |
|       //
 | |
|       UnicodeSPrint (mPrivate->PortString, (UINTN) ISCSI_NAME_IFR_MAX_SIZE, L"Attempt %d", (UINTN) AttemptConfigData->AttemptConfigIndex);
 | |
|       AttemptConfigData->AttemptTitleToken = HiiSetString (
 | |
|                                                mCallbackInfo->RegisteredHandle,
 | |
|                                                0,
 | |
|                                                mPrivate->PortString,
 | |
|                                                NULL
 | |
|                                                );
 | |
|       if (AttemptConfigData->AttemptTitleToken == 0) {
 | |
|         return ;
 | |
|       }
 | |
| 
 | |
|       HiiCreateGotoOpCode (
 | |
|         StartOpCodeHandle,                         // Container for dynamic created opcodes
 | |
|         FORMID_ATTEMPT_FORM,                       // Form ID
 | |
|         AttemptConfigData->AttemptTitleToken,      // Prompt text
 | |
|         AttemptConfigData->AttemptTitleHelpToken,  // Help text
 | |
|         EFI_IFR_FLAG_CALLBACK,                     // Question flag
 | |
|         (UINT16) (KEY_ATTEMPT_ENTRY_BASE + AttemptConfigData->AttemptConfigIndex)   // Question ID
 | |
|         );
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   HiiUpdateForm (
 | |
|     mCallbackInfo->RegisteredHandle, // HII handle
 | |
|     &gIScsiConfigGuid,               // Formset GUID
 | |
|     FORMID_MAIN_FORM,                // Form ID
 | |
|     StartOpCodeHandle,               // Label for where to insert opcodes
 | |
|     EndOpCodeHandle                  // Replace data
 | |
|   );
 | |
| 
 | |
|   HiiFreeOpCodeHandle (StartOpCodeHandle);
 | |
|   HiiFreeOpCodeHandle (EndOpCodeHandle);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Callback function when user presses "Add an Attempt".
 | |
| 
 | |
|   @retval EFI_OUT_OF_RESOURCES   Does not have sufficient resources to finish this
 | |
|                                  operation.
 | |
|   @retval EFI_SUCCESS            The operation is completed successfully.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| IScsiConfigAddAttempt (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   LIST_ENTRY                    *Entry;
 | |
|   ISCSI_NIC_INFO                *NicInfo;
 | |
|   EFI_STRING_ID                 PortTitleToken;
 | |
|   EFI_STRING_ID                 PortTitleHelpToken;
 | |
|   CHAR16                        MacString[ISCSI_MAX_MAC_STRING_LEN];
 | |
|   EFI_STATUS                    Status;
 | |
|   VOID                          *StartOpCodeHandle;
 | |
|   EFI_IFR_GUID_LABEL            *StartLabel;
 | |
|   VOID                          *EndOpCodeHandle;
 | |
|   EFI_IFR_GUID_LABEL            *EndLabel;
 | |
| 
 | |
|   Status = IScsiCreateOpCode (
 | |
|              MAC_ENTRY_LABEL,
 | |
|              &StartOpCodeHandle,
 | |
|              &StartLabel,
 | |
|              &EndOpCodeHandle,
 | |
|              &EndLabel
 | |
|              );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Ask user to select a MAC for this attempt.
 | |
|   //
 | |
|   NET_LIST_FOR_EACH (Entry, &mPrivate->NicInfoList) {
 | |
|     NicInfo = NET_LIST_USER_STRUCT (Entry, ISCSI_NIC_INFO, Link);
 | |
|     IScsiMacAddrToStr (
 | |
|       &NicInfo->PermanentAddress,
 | |
|       NicInfo->HwAddressSize,
 | |
|       NicInfo->VlanId,
 | |
|       MacString
 | |
|       );
 | |
| 
 | |
|     UnicodeSPrint (mPrivate->PortString, (UINTN) ISCSI_NAME_IFR_MAX_SIZE, L"MAC %s", MacString);
 | |
|     PortTitleToken = HiiSetString (
 | |
|                        mCallbackInfo->RegisteredHandle,
 | |
|                        0,
 | |
|                        mPrivate->PortString,
 | |
|                        NULL
 | |
|                        );
 | |
|     if (PortTitleToken == 0) {
 | |
|       Status = EFI_INVALID_PARAMETER;
 | |
|       goto Exit;
 | |
|     }
 | |
| 
 | |
|     UnicodeSPrint (
 | |
|       mPrivate->PortString,
 | |
|       (UINTN) ISCSI_NAME_IFR_MAX_SIZE,
 | |
|       L"PFA: Bus %d | Dev %d | Func %d",
 | |
|       NicInfo->BusNumber,
 | |
|       NicInfo->DeviceNumber,
 | |
|       NicInfo->FunctionNumber
 | |
|       );
 | |
|     PortTitleHelpToken = HiiSetString (mCallbackInfo->RegisteredHandle, 0, mPrivate->PortString, NULL);
 | |
|     if (PortTitleHelpToken == 0) {
 | |
|       Status = EFI_INVALID_PARAMETER;
 | |
|       goto Exit;
 | |
|     }
 | |
| 
 | |
|     HiiCreateGotoOpCode (
 | |
|       StartOpCodeHandle,                      // Container for dynamic created opcodes
 | |
|       FORMID_ATTEMPT_FORM,
 | |
|       PortTitleToken,
 | |
|       PortTitleHelpToken,
 | |
|       EFI_IFR_FLAG_CALLBACK,                  // Question flag
 | |
|       (UINT16) (KEY_MAC_ENTRY_BASE + NicInfo->NicIndex)
 | |
|       );
 | |
|   }
 | |
| 
 | |
|   Status = HiiUpdateForm (
 | |
|              mCallbackInfo->RegisteredHandle, // HII handle
 | |
|              &gIScsiConfigGuid,               // Formset GUID
 | |
|              FORMID_MAC_FORM,                 // Form ID
 | |
|              StartOpCodeHandle,               // Label for where to insert opcodes
 | |
|              EndOpCodeHandle                  // Replace data
 | |
|              );
 | |
| 
 | |
| Exit:
 | |
|   HiiFreeOpCodeHandle (StartOpCodeHandle);
 | |
|   HiiFreeOpCodeHandle (EndOpCodeHandle);
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Add the attempts by keyword 'iSCSIAddAttempts', you can use this keyword with
 | |
|   value 'attempt:1 attempt:2' etc to add one or more attempts once. This is different
 | |
|   with IScsiConfigAddAttempt function which is used to add attempt by UI configuration.
 | |
| 
 | |
|   @param[in]  AttemptList        The new attempt List will be added.
 | |
| 
 | |
|   @retval EFI_SUCCESS            The operation to add attempt list successfully.
 | |
|   @retval EFI_INVALID_PARAMETER  Any parameter is invalid.
 | |
|   @retval EFI_NOT_FOUND          Cannot find the corresponding variable.
 | |
|   @retval EFI_OUT_OF_RESOURCES   Fail to finish the operation due to lack of
 | |
|                                  resources.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| IScsiConfigAddAttemptsByKeywords (
 | |
|   IN UINT8                   *AttemptList
 | |
|   )
 | |
| {
 | |
|   UINT8                       Index;
 | |
|   UINT8                       Number;
 | |
|   UINTN                       TotalNumber;
 | |
|   UINT8                       Nic;
 | |
|   UINT8                       *AttemptConfigOrder;
 | |
|   UINTN                       AttemptConfigOrderSize;
 | |
|   UINT8                       *AttemptConfigOrderTmp;
 | |
|   ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;
 | |
|   ISCSI_NIC_INFO              *NicInfo;
 | |
|   CHAR16                      MacString[ISCSI_MAX_MAC_STRING_LEN];
 | |
|   CHAR16                      IScsiMode[64];
 | |
|   CHAR16                      IpMode[64];
 | |
|   EFI_STATUS                  Status;
 | |
| 
 | |
|   Nic = mPrivate->CurrentNic;
 | |
|   NicInfo = IScsiGetNicInfoByIndex (Nic);
 | |
|   if (NicInfo == NULL) {
 | |
|     return EFI_NOT_FOUND;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // The MAC info will be recorded in Config Data.
 | |
|   //
 | |
|   IScsiMacAddrToStr (
 | |
|     &NicInfo->PermanentAddress,
 | |
|     NicInfo->HwAddressSize,
 | |
|     NicInfo->VlanId,
 | |
|     MacString
 | |
|     );
 | |
| 
 | |
|   for (Index = 0; Index < PcdGet8 (PcdMaxIScsiAttemptNumber); Index++) {
 | |
|     if (AttemptList[Index] == 0) {
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Add the attempt.
 | |
|     //
 | |
|     Number = AttemptList[Index];
 | |
| 
 | |
|     UnicodeSPrint (
 | |
|       mPrivate->PortString,
 | |
|       (UINTN) ISCSI_NAME_IFR_MAX_SIZE,
 | |
|       L"Attempt %d",
 | |
|       Number
 | |
|       );
 | |
| 
 | |
|     GetVariable2 (
 | |
|            mPrivate->PortString,
 | |
|            &gEfiIScsiInitiatorNameProtocolGuid,
 | |
|            (VOID**)&AttemptConfigData,
 | |
|            NULL
 | |
|            );
 | |
|     if (AttemptConfigData == NULL || AttemptConfigData->Actived == ISCSI_ACTIVE_ENABLED) {
 | |
|       return EFI_INVALID_PARAMETER;
 | |
|     }
 | |
| 
 | |
|     AttemptConfigData->Actived = ISCSI_ACTIVE_ENABLED;
 | |
|     AttemptConfigData->NicIndex = NicInfo->NicIndex;
 | |
|     UnicodeStrToAsciiStrS (MacString, AttemptConfigData->MacString, ISCSI_MAX_MAC_STRING_LEN);
 | |
| 
 | |
|     //
 | |
|     // Generate OUI-format ISID based on MAC address.
 | |
|     //
 | |
|     CopyMem (AttemptConfigData->SessionConfigData.IsId, &NicInfo->PermanentAddress, 6);
 | |
|     AttemptConfigData->SessionConfigData.IsId[0] =
 | |
|       (UINT8) (AttemptConfigData->SessionConfigData.IsId[0] & 0x3F);
 | |
| 
 | |
|     //
 | |
|     // Configure the iSCSI Mode and IpMode to default.
 | |
|     // Add Attempt Help Info.
 | |
|     //
 | |
|     UnicodeSPrint (IScsiMode, 64, L"Disabled");
 | |
|     UnicodeSPrint (IpMode, 64, L"IP4");
 | |
|     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;
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Get current Attempt order and number.
 | |
|     //
 | |
|     AttemptConfigOrder = IScsiGetVariableAndSize (
 | |
|                            L"AttemptOrder",
 | |
|                            &gIScsiConfigGuid,
 | |
|                            &AttemptConfigOrderSize
 | |
|                            );
 | |
|     TotalNumber = AttemptConfigOrderSize / sizeof (UINT8);
 | |
|     TotalNumber++;
 | |
| 
 | |
|     //
 | |
|     // Append the new created attempt order to the end.
 | |
|     //
 | |
|     AttemptConfigOrderTmp = AllocateZeroPool (TotalNumber * sizeof (UINT8));
 | |
|     if (AttemptConfigOrderTmp == NULL) {
 | |
|       if (AttemptConfigOrder != NULL) {
 | |
|         FreePool (AttemptConfigOrder);
 | |
|       }
 | |
|       return EFI_OUT_OF_RESOURCES;
 | |
|     }
 | |
|     if (AttemptConfigOrder != NULL) {
 | |
|       CopyMem (AttemptConfigOrderTmp, AttemptConfigOrder, AttemptConfigOrderSize);
 | |
|       FreePool (AttemptConfigOrder);
 | |
|     }
 | |
| 
 | |
|     AttemptConfigOrderTmp[TotalNumber - 1] = Number;
 | |
|     AttemptConfigOrder               = AttemptConfigOrderTmp;
 | |
|     AttemptConfigOrderSize           = TotalNumber * sizeof (UINT8);
 | |
| 
 | |
|     Status = gRT->SetVariable (
 | |
|                     L"AttemptOrder",
 | |
|                     &gIScsiConfigGuid,
 | |
|                     EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
 | |
|                     AttemptConfigOrderSize,
 | |
|                     AttemptConfigOrder
 | |
|                     );
 | |
|     FreePool (AttemptConfigOrder);
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       return Status;
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Record the attempt in global link list.
 | |
|     //
 | |
|     InsertTailList (&mPrivate->AttemptConfigs, &AttemptConfigData->Link);
 | |
|     mPrivate->AttemptCount++;
 | |
|     UnicodeSPrint (mPrivate->PortString, (UINTN) ISCSI_NAME_IFR_MAX_SIZE, L"Attempt %d", AttemptConfigData->AttemptConfigIndex);
 | |
|     gRT->SetVariable (
 | |
|            mPrivate->PortString,
 | |
|            &gEfiIScsiInitiatorNameProtocolGuid,
 | |
|            ISCSI_CONFIG_VAR_ATTR,
 | |
|            sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA),
 | |
|            AttemptConfigData
 | |
|            );
 | |
| 
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Callback function when user presses "Commit Changes and Exit" in Delete Attempts or Delete Attempts by Keyword.
 | |
| 
 | |
|   @param[in]  IfrNvData          The IFR NV data.
 | |
| 
 | |
|   @retval EFI_NOT_FOUND          Cannot find the corresponding variable.
 | |
|   @retval EFI_SUCCESS            The operation is completed successfully.
 | |
|   @retval EFI_ABORTED            This operation is aborted cause of error
 | |
|                                  configuration.
 | |
|   @retval EFI_OUT_OF_RESOURCES   Fail to finish the operation due to lack of
 | |
|                                  resources.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| IScsiConfigDeleteAttempts (
 | |
|   IN ISCSI_CONFIG_IFR_NVDATA  *IfrNvData
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                    Status;
 | |
|   UINTN                         Index;
 | |
|   UINTN                         NewIndex;
 | |
|   ISCSI_ATTEMPT_CONFIG_NVDATA   *AttemptConfigData;
 | |
|   UINT8                         *AttemptConfigOrder;
 | |
|   UINTN                         AttemptConfigOrderSize;
 | |
|   UINT8                         *AttemptNewOrder;
 | |
|   UINT8                         AttemptConfigIndex;
 | |
|   UINT32                        Attribute;
 | |
|   UINTN                         Total;
 | |
|   UINTN                         NewTotal;
 | |
|   LIST_ENTRY                    *Entry;
 | |
|   LIST_ENTRY                    *NextEntry;
 | |
|   ISCSI_SESSION_CONFIG_NVDATA   *ConfigData;
 | |
| 
 | |
|   Index     = 0;
 | |
| 
 | |
|   AttemptConfigOrder = IScsiGetVariableAndSize (
 | |
|                          L"AttemptOrder",
 | |
|                          &gIScsiConfigGuid,
 | |
|                          &AttemptConfigOrderSize
 | |
|                          );
 | |
|   if ((AttemptConfigOrder == NULL) || (AttemptConfigOrderSize == 0)) {
 | |
|     return EFI_NOT_FOUND;
 | |
|   }
 | |
| 
 | |
|   AttemptNewOrder = AllocateZeroPool (AttemptConfigOrderSize);
 | |
|   if (AttemptNewOrder == NULL) {
 | |
|     Status = EFI_OUT_OF_RESOURCES;
 | |
|     goto Error;
 | |
|   }
 | |
| 
 | |
|   Total    = AttemptConfigOrderSize / sizeof (UINT8);
 | |
|   NewTotal = Total;
 | |
| 
 | |
|   NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &mPrivate->AttemptConfigs) {
 | |
|     if (IfrNvData->DeleteAttemptList[Index] == 0) {
 | |
|       Index++;
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Delete the attempt.
 | |
|     //
 | |
| 
 | |
|     AttemptConfigData = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);
 | |
| 
 | |
|     //
 | |
|     // Remove this attempt from UI configured attempt list.
 | |
|     //
 | |
|     RemoveEntryList (&AttemptConfigData->Link);
 | |
|     mPrivate->AttemptCount--;
 | |
| 
 | |
|     if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED_FOR_MPIO) {
 | |
|       if (mPrivate->MpioCount < 1) {
 | |
|         Status = EFI_ABORTED;
 | |
|         goto Error;
 | |
|       }
 | |
| 
 | |
|       //
 | |
|       // No more attempt is enabled for MPIO. Transit the iSCSI mode to single path.
 | |
|       //
 | |
|       if (--mPrivate->MpioCount == 0) {
 | |
|         mPrivate->EnableMpio = FALSE;
 | |
|       }
 | |
|     } else if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED) {
 | |
|       if (mPrivate->SinglePathCount < 1) {
 | |
|         Status = EFI_ABORTED;
 | |
|         goto Error;
 | |
|       }
 | |
| 
 | |
|       mPrivate->SinglePathCount--;
 | |
|     }
 | |
| 
 | |
|     AttemptConfigIndex = AttemptConfigData->AttemptConfigIndex;
 | |
|     FreePool (AttemptConfigData);
 | |
| 
 | |
|     //
 | |
|     // Create a 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 = AttemptConfigIndex;
 | |
| 
 | |
|     //
 | |
|     // Set the attempt name to default.
 | |
|     //
 | |
|     UnicodeSPrint (
 | |
|       mPrivate->PortString,
 | |
|       (UINTN) ISCSI_NAME_IFR_MAX_SIZE,
 | |
|       L"Attempt %d",
 | |
|       (UINTN) AttemptConfigData->AttemptConfigIndex
 | |
|       );
 | |
|     UnicodeStrToAsciiStrS (mPrivate->PortString, AttemptConfigData->AttemptName, ATTEMPT_NAME_SIZE);
 | |
|     gRT->SetVariable (
 | |
|            mPrivate->PortString,
 | |
|            &gEfiIScsiInitiatorNameProtocolGuid,
 | |
|            ISCSI_CONFIG_VAR_ATTR,
 | |
|            sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA),
 | |
|            AttemptConfigData
 | |
|            );
 | |
| 
 | |
|     //
 | |
|     // Mark the attempt order in NVR to be deleted - 0.
 | |
|     //
 | |
|     for (NewIndex = 0; NewIndex < Total; NewIndex++) {
 | |
|       if (AttemptConfigOrder[NewIndex] == AttemptConfigData->AttemptConfigIndex) {
 | |
|         AttemptConfigOrder[NewIndex] = 0;
 | |
|         break;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     NewTotal--;
 | |
|     if (mCallbackInfo->Current == AttemptConfigData) {
 | |
|       mCallbackInfo->Current = NULL;
 | |
|     }
 | |
|     FreePool (AttemptConfigData);
 | |
| 
 | |
|     //
 | |
|     // Check next Attempt.
 | |
|     //
 | |
|     Index++;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Construct AttemptNewOrder.
 | |
|   //
 | |
|   for (Index = 0, NewIndex = 0; Index < Total; Index++) {
 | |
|     if (AttemptConfigOrder[Index] != 0) {
 | |
|       AttemptNewOrder[NewIndex] = AttemptConfigOrder[Index];
 | |
|       NewIndex++;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   Attribute = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE;
 | |
| 
 | |
|   //
 | |
|   // Update AttemptOrder in NVR.
 | |
|   //
 | |
|   Status = gRT->SetVariable (
 | |
|                   L"AttemptOrder",
 | |
|                   &gIScsiConfigGuid,
 | |
|                   Attribute,
 | |
|                   NewTotal * sizeof (UINT8),
 | |
|                   AttemptNewOrder
 | |
|                   );
 | |
| 
 | |
| Error:
 | |
|   if (AttemptConfigOrder != NULL) {
 | |
|     FreePool (AttemptConfigOrder);
 | |
|   }
 | |
| 
 | |
|   if (AttemptNewOrder != NULL) {
 | |
|     FreePool (AttemptNewOrder);
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Callback function when user presses "Delete Attempts".
 | |
| 
 | |
|   @param[in]  IfrNvData          The IFR nv data.
 | |
| 
 | |
|   @retval EFI_INVALID_PARAMETER  Any parameter is invalid.
 | |
|   @retval EFI_BUFFER_TOO_SMALL   The buffer in UpdateData is too small.
 | |
|   @retval EFI_SUCCESS            The operation is completed successfully.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| IScsiConfigDisplayDeleteAttempts (
 | |
|   IN ISCSI_CONFIG_IFR_NVDATA  *IfrNvData
 | |
|   )
 | |
| {
 | |
| 
 | |
|   UINT8                       *AttemptConfigOrder;
 | |
|   UINTN                       AttemptConfigOrderSize;
 | |
|   LIST_ENTRY                  *Entry;
 | |
|   ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;
 | |
|   UINT8                       Index;
 | |
|   VOID                        *StartOpCodeHandle;
 | |
|   EFI_IFR_GUID_LABEL          *StartLabel;
 | |
|   VOID                        *EndOpCodeHandle;
 | |
|   EFI_IFR_GUID_LABEL          *EndLabel;
 | |
|   EFI_STATUS                  Status;
 | |
| 
 | |
|   Status = IScsiCreateOpCode (
 | |
|              DELETE_ENTRY_LABEL,
 | |
|              &StartOpCodeHandle,
 | |
|              &StartLabel,
 | |
|              &EndOpCodeHandle,
 | |
|              &EndLabel
 | |
|              );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   AttemptConfigOrder = IScsiGetVariableAndSize (
 | |
|                          L"AttemptOrder",
 | |
|                          &gIScsiConfigGuid,
 | |
|                          &AttemptConfigOrderSize
 | |
|                          );
 | |
|   if (AttemptConfigOrder != NULL) {
 | |
|     //
 | |
|     // Create the check box opcode to be deleted.
 | |
|     //
 | |
|     Index = 0;
 | |
| 
 | |
|     NET_LIST_FOR_EACH (Entry, &mPrivate->AttemptConfigs) {
 | |
|       AttemptConfigData = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);
 | |
|       IfrNvData->DeleteAttemptList[Index] = 0x00;
 | |
| 
 | |
|       HiiCreateCheckBoxOpCode(
 | |
|         StartOpCodeHandle,
 | |
|         (EFI_QUESTION_ID) (ATTEMPT_DEL_QUESTION_ID + Index),
 | |
|         CONFIGURATION_VARSTORE_ID,
 | |
|         (UINT16) (ATTEMPT_DEL_VAR_OFFSET + Index),
 | |
|         AttemptConfigData->AttemptTitleToken,
 | |
|         AttemptConfigData->AttemptTitleHelpToken,
 | |
|         0,
 | |
|         0,
 | |
|         NULL
 | |
|         );
 | |
| 
 | |
|       Index++;
 | |
| 
 | |
|       if (Index == ISCSI_MAX_ATTEMPTS_NUM) {
 | |
|         break;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     FreePool (AttemptConfigOrder);
 | |
|   }
 | |
| 
 | |
|   Status = HiiUpdateForm (
 | |
|              mCallbackInfo->RegisteredHandle, // HII handle
 | |
|              &gIScsiConfigGuid,               // Formset GUID
 | |
|              FORMID_DELETE_FORM,              // Form ID
 | |
|              StartOpCodeHandle,               // Label for where to insert opcodes
 | |
|              EndOpCodeHandle                  // Replace data
 | |
|              );
 | |
| 
 | |
|   HiiFreeOpCodeHandle (StartOpCodeHandle);
 | |
|   HiiFreeOpCodeHandle (EndOpCodeHandle);
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Callback function when user presses "Change Attempt Order".
 | |
| 
 | |
|   @retval EFI_INVALID_PARAMETER  Any parameter is invalid.
 | |
|   @retval EFI_OUT_OF_RESOURCES   Does not have sufficient resources to finish this
 | |
|                                  operation.
 | |
|   @retval EFI_SUCCESS            The operation is completed successfully.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| IScsiConfigDisplayOrderAttempts (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                  Status;
 | |
|   UINT8                       Index;
 | |
|   LIST_ENTRY                  *Entry;
 | |
|   ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;
 | |
|   VOID                        *StartOpCodeHandle;
 | |
|   EFI_IFR_GUID_LABEL          *StartLabel;
 | |
|   VOID                        *EndOpCodeHandle;
 | |
|   EFI_IFR_GUID_LABEL          *EndLabel;
 | |
|   VOID                        *OptionsOpCodeHandle;
 | |
| 
 | |
|   Status = IScsiCreateOpCode (
 | |
|              ORDER_ENTRY_LABEL,
 | |
|              &StartOpCodeHandle,
 | |
|              &StartLabel,
 | |
|              &EndOpCodeHandle,
 | |
|              &EndLabel
 | |
|              );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
|   ASSERT (StartOpCodeHandle != NULL);
 | |
| 
 | |
|   OptionsOpCodeHandle = NULL;
 | |
| 
 | |
|   //
 | |
|   // If no attempt to be ordered, update the original form and exit.
 | |
|   //
 | |
|   if (mPrivate->AttemptCount == 0) {
 | |
|     goto Exit;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Create Option OpCode.
 | |
|   //
 | |
|   OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();
 | |
|   if (OptionsOpCodeHandle == NULL) {
 | |
|     Status = EFI_OUT_OF_RESOURCES;
 | |
|     goto Error;
 | |
|   }
 | |
| 
 | |
|   Index = 0;
 | |
| 
 | |
|   NET_LIST_FOR_EACH (Entry, &mPrivate->AttemptConfigs) {
 | |
|     AttemptConfigData = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);
 | |
|     HiiCreateOneOfOptionOpCode (
 | |
|       OptionsOpCodeHandle,
 | |
|       AttemptConfigData->AttemptTitleToken,
 | |
|       0,
 | |
|       EFI_IFR_NUMERIC_SIZE_1,
 | |
|       AttemptConfigData->AttemptConfigIndex
 | |
|       );
 | |
|     Index++;
 | |
|   }
 | |
| 
 | |
|   ASSERT (Index == mPrivate->AttemptCount);
 | |
| 
 | |
|   HiiCreateOrderedListOpCode (
 | |
|     StartOpCodeHandle,                          // Container for dynamic created opcodes
 | |
|     DYNAMIC_ORDERED_LIST_QUESTION_ID,           // Question ID
 | |
|     CONFIGURATION_VARSTORE_ID,                  // VarStore ID
 | |
|     DYNAMIC_ORDERED_LIST_VAR_OFFSET,            // Offset in Buffer Storage
 | |
|     STRING_TOKEN (STR_ORDER_ATTEMPT_ENTRY),     // Question prompt text
 | |
|     STRING_TOKEN (STR_ORDER_ATTEMPT_ENTRY),     // Question help text
 | |
|     0,                                          // Question flag
 | |
|     EFI_IFR_UNIQUE_SET,                         // Ordered list flag, e.g. EFI_IFR_UNIQUE_SET
 | |
|     EFI_IFR_NUMERIC_SIZE_1,                     // Data type of Question value
 | |
|     ISCSI_MAX_ATTEMPTS_NUM,                     // Maximum container
 | |
|     OptionsOpCodeHandle,                        // Option Opcode list
 | |
|     NULL                                        // Default Opcode is NULL
 | |
|     );
 | |
| 
 | |
| Exit:
 | |
|   Status = HiiUpdateForm (
 | |
|              mCallbackInfo->RegisteredHandle, // HII handle
 | |
|              &gIScsiConfigGuid,               // Formset GUID
 | |
|              FORMID_ORDER_FORM,               // Form ID
 | |
|              StartOpCodeHandle,               // Label for where to insert opcodes
 | |
|              EndOpCodeHandle                  // Replace data
 | |
|              );
 | |
| 
 | |
| Error:
 | |
|   HiiFreeOpCodeHandle (StartOpCodeHandle);
 | |
|   HiiFreeOpCodeHandle (EndOpCodeHandle);
 | |
|   if (OptionsOpCodeHandle != NULL) {
 | |
|     HiiFreeOpCodeHandle (OptionsOpCodeHandle);
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Callback function when user presses "Commit Changes and Exit" in Change Attempt Order or Change Attempt Order by Keyword.
 | |
| 
 | |
|   @param[in]  IfrNvData          The IFR nv data.
 | |
| 
 | |
|   @retval EFI_OUT_OF_RESOURCES   Does not have sufficient resources to finish this
 | |
|                                  operation.
 | |
|   @retval EFI_NOT_FOUND          Cannot find the corresponding variable.
 | |
|   @retval EFI_SUCCESS            The operation is completed successfully.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| IScsiConfigOrderAttempts (
 | |
|   IN ISCSI_CONFIG_IFR_NVDATA  *IfrNvData
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                  Status;
 | |
|   UINTN                       Index;
 | |
|   UINTN                       Indexj;
 | |
|   UINT8                       AttemptConfigIndex;
 | |
|   ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;
 | |
|   UINT8                       *AttemptConfigOrder;
 | |
|   UINT8                       *AttemptConfigOrderTmp;
 | |
|   UINTN                       AttemptConfigOrderSize;
 | |
| 
 | |
|   AttemptConfigOrder = IScsiGetVariableAndSize (
 | |
|                          L"AttemptOrder",
 | |
|                          &gIScsiConfigGuid,
 | |
|                          &AttemptConfigOrderSize
 | |
|                          );
 | |
|   if (AttemptConfigOrder == NULL) {
 | |
|     return EFI_NOT_FOUND;
 | |
|   }
 | |
| 
 | |
|   AttemptConfigOrderTmp = AllocateZeroPool (AttemptConfigOrderSize);
 | |
|   if (AttemptConfigOrderTmp == NULL) {
 | |
|     Status = EFI_OUT_OF_RESOURCES;
 | |
|     goto Exit;
 | |
|   }
 | |
| 
 | |
|   for (Index = 0; Index < ISCSI_MAX_ATTEMPTS_NUM; Index++) {
 | |
|     //
 | |
|     // The real content ends with 0.
 | |
|     //
 | |
|     if (IfrNvData->DynamicOrderedList[Index] == 0) {
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|     AttemptConfigIndex = IfrNvData->DynamicOrderedList[Index];
 | |
|     AttemptConfigData  = IScsiConfigGetAttemptByConfigIndex (AttemptConfigIndex);
 | |
|     if (AttemptConfigData == NULL) {
 | |
|       Status = EFI_NOT_FOUND;
 | |
|       goto Exit;
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Reorder the Attempt List.
 | |
|     //
 | |
|     RemoveEntryList (&AttemptConfigData->Link);
 | |
|     InsertTailList (&mPrivate->AttemptConfigs, &AttemptConfigData->Link);
 | |
| 
 | |
|     AttemptConfigOrderTmp[Index] = AttemptConfigIndex;
 | |
| 
 | |
|     //
 | |
|     // Mark it to be deleted - 0.
 | |
|     //
 | |
|     for (Indexj = 0; Indexj < AttemptConfigOrderSize / sizeof (UINT8); Indexj++) {
 | |
|       if (AttemptConfigOrder[Indexj] == AttemptConfigIndex) {
 | |
|         AttemptConfigOrder[Indexj] = 0;
 | |
|         break;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Adjust the attempt order in NVR.
 | |
|   //
 | |
|   for (; Index < AttemptConfigOrderSize / sizeof (UINT8); Index++) {
 | |
|     for (Indexj = 0; Indexj < AttemptConfigOrderSize / sizeof (UINT8); Indexj++) {
 | |
|       if (AttemptConfigOrder[Indexj] != 0) {
 | |
|         AttemptConfigOrderTmp[Index] = AttemptConfigOrder[Indexj];
 | |
|         AttemptConfigOrder[Indexj]   = 0;
 | |
|         continue;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   Status = gRT->SetVariable (
 | |
|                   L"AttemptOrder",
 | |
|                   &gIScsiConfigGuid,
 | |
|                   EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
 | |
|                   AttemptConfigOrderSize,
 | |
|                   AttemptConfigOrderTmp
 | |
|                   );
 | |
| 
 | |
| Exit:
 | |
|   if (AttemptConfigOrderTmp != NULL) {
 | |
|     FreePool (AttemptConfigOrderTmp);
 | |
|   }
 | |
| 
 | |
|   FreePool (AttemptConfigOrder);
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Callback function when a user presses "Attempt *" or when a user selects a NIC to
 | |
|   create the new attempt.
 | |
| 
 | |
|   @param[in]  KeyValue           A unique value which is sent to the original
 | |
|                                  exporting driver so that it can identify the type
 | |
|                                  of data to expect.
 | |
|   @param[in]  IfrNvData          The IFR nv data.
 | |
| 
 | |
|   @retval EFI_OUT_OF_RESOURCES   Does not have sufficient resources to finish this
 | |
|                                  operation.
 | |
|   @retval EFI_NOT_FOUND          Cannot find the corresponding variable.
 | |
|   @retval EFI_UNSUPPORTED        Can not create more attempts.
 | |
|   @retval EFI_SUCCESS            The operation is completed successfully.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| IScsiConfigProcessDefault (
 | |
|   IN  EFI_QUESTION_ID              KeyValue,
 | |
|   IN  ISCSI_CONFIG_IFR_NVDATA      *IfrNvData
 | |
|   )
 | |
| {
 | |
|   BOOLEAN                     NewAttempt;
 | |
|   ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;
 | |
|   UINT8                       CurrentAttemptConfigIndex;
 | |
|   ISCSI_NIC_INFO              *NicInfo;
 | |
|   UINT8                       NicIndex;
 | |
|   CHAR16                      MacString[ISCSI_MAX_MAC_STRING_LEN];
 | |
|   UINT8                       *AttemptConfigOrder;
 | |
|   UINTN                       AttemptConfigOrderSize;
 | |
|   UINTN                       Index;
 | |
|   EFI_INPUT_KEY               Key;
 | |
| 
 | |
|   AttemptConfigData = NULL;
 | |
|   //
 | |
|   // Is User creating a new attempt?
 | |
|   //
 | |
|   NewAttempt = FALSE;
 | |
| 
 | |
|   if ((KeyValue >= KEY_MAC_ENTRY_BASE) &&
 | |
|       (KeyValue <= (UINT16) (mPrivate->MaxNic + KEY_MAC_ENTRY_BASE))) {
 | |
|     //
 | |
|     // User has pressed "Add an Attempt" and then selects a NIC.
 | |
|     //
 | |
|     NewAttempt = TRUE;
 | |
|   } else if ((KeyValue >= KEY_ATTEMPT_ENTRY_BASE) &&
 | |
|              (KeyValue < (ISCSI_MAX_ATTEMPTS_NUM + KEY_ATTEMPT_ENTRY_BASE))) {
 | |
| 
 | |
|     //
 | |
|     // User has pressed "Attempt *".
 | |
|     //
 | |
|     NewAttempt = FALSE;
 | |
|   } else {
 | |
|     //
 | |
|     // Don't process anything.
 | |
|     //
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   if (NewAttempt) {
 | |
|     //
 | |
|     // Determine which NIC user has selected for the new created attempt.
 | |
|     //
 | |
|     NicIndex = (UINT8) (KeyValue - KEY_MAC_ENTRY_BASE);
 | |
|     NicInfo = IScsiGetNicInfoByIndex (NicIndex);
 | |
|     if (NicInfo == NULL) {
 | |
|       return EFI_NOT_FOUND;
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Create an attempt following the initialized attempt order.
 | |
|     //
 | |
|     AttemptConfigOrder = IScsiGetVariableAndSize (
 | |
|                            L"InitialAttemptOrder",
 | |
|                            &gIScsiConfigGuid,
 | |
|                            &AttemptConfigOrderSize
 | |
|                            );
 | |
| 
 | |
|     if (AttemptConfigOrder == NULL) {
 | |
|       return EFI_NOT_FOUND;
 | |
|     }
 | |
| 
 | |
|     for (Index = 0; Index < AttemptConfigOrderSize / sizeof (UINT8); Index++) {
 | |
|       UnicodeSPrint (
 | |
|         mPrivate->PortString,
 | |
|         (UINTN) ISCSI_NAME_IFR_MAX_SIZE,
 | |
|         L"Attempt %d",
 | |
|         (UINTN) AttemptConfigOrder[Index]
 | |
|         );
 | |
|       GetVariable2 (
 | |
|                    mPrivate->PortString,
 | |
|                    &gEfiIScsiInitiatorNameProtocolGuid,
 | |
|                    (VOID**)&AttemptConfigData,
 | |
|                    NULL
 | |
|                    );
 | |
|       if (AttemptConfigData == NULL || AttemptConfigData->Actived == ISCSI_ACTIVE_ENABLED) {
 | |
|         continue;
 | |
|       }
 | |
| 
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|     if (Index > PcdGet8 (PcdMaxIScsiAttemptNumber)) {
 | |
|       CreatePopUp (
 | |
|         EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
 | |
|         &Key,
 | |
|         L"Can not create more attempts, Please configure the PcdMaxIScsiAttemptNumber if needed!",
 | |
|         NULL
 | |
|         );
 | |
|       return EFI_UNSUPPORTED;
 | |
|     }
 | |
| 
 | |
|     if (AttemptConfigOrder != NULL) {
 | |
|       FreePool (AttemptConfigOrder);
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Record the MAC info in Config Data.
 | |
|     //
 | |
|     IScsiMacAddrToStr (
 | |
|       &NicInfo->PermanentAddress,
 | |
|       NicInfo->HwAddressSize,
 | |
|       NicInfo->VlanId,
 | |
|       MacString
 | |
|       );
 | |
| 
 | |
|     ASSERT (AttemptConfigData != NULL);
 | |
|     UnicodeStrToAsciiStrS (MacString, AttemptConfigData->MacString, sizeof (AttemptConfigData->MacString));
 | |
|     AttemptConfigData->NicIndex = NicIndex;
 | |
|     AttemptConfigData->Actived = ISCSI_ACTIVE_ENABLED;
 | |
| 
 | |
|     //
 | |
|     // Generate OUI-format ISID based on MAC address.
 | |
|     //
 | |
|     CopyMem (AttemptConfigData->SessionConfigData.IsId, &NicInfo->PermanentAddress, 6);
 | |
|     AttemptConfigData->SessionConfigData.IsId[0] =
 | |
|       (UINT8) (AttemptConfigData->SessionConfigData.IsId[0] & 0x3F);
 | |
| 
 | |
|     //
 | |
|     // Add the help info for the new attempt.
 | |
|     //
 | |
|     UnicodeSPrint (
 | |
|       mPrivate->PortString,
 | |
|       (UINTN) ISCSI_NAME_IFR_MAX_SIZE,
 | |
|       L"MAC: %s, PFA: Bus %d | Dev %d | Func %d",
 | |
|       MacString,
 | |
|       NicInfo->BusNumber,
 | |
|       NicInfo->DeviceNumber,
 | |
|       NicInfo->FunctionNumber
 | |
|       );
 | |
| 
 | |
|     AttemptConfigData->AttemptTitleHelpToken  = HiiSetString (
 | |
|                                                   mCallbackInfo->RegisteredHandle,
 | |
|                                                   0,
 | |
|                                                   mPrivate->PortString,
 | |
|                                                   NULL
 | |
|                                                   );
 | |
|     if (AttemptConfigData->AttemptTitleHelpToken == 0) {
 | |
|       FreePool (AttemptConfigData);
 | |
|       return EFI_OUT_OF_RESOURCES;
 | |
|     }
 | |
| 
 | |
|   } else {
 | |
|     //
 | |
|     // Determine which Attempt user has selected to configure.
 | |
|     // Get the attempt configuration data.
 | |
|     //
 | |
|     CurrentAttemptConfigIndex = (UINT8) (KeyValue - KEY_ATTEMPT_ENTRY_BASE);
 | |
| 
 | |
|     AttemptConfigData = IScsiConfigGetAttemptByConfigIndex (CurrentAttemptConfigIndex);
 | |
|     if (AttemptConfigData == NULL) {
 | |
|       DEBUG ((DEBUG_ERROR, "Corresponding configuration data can not be retrieved!\n"));
 | |
|       return EFI_NOT_FOUND;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Clear the old IFR data to avoid sharing it with other attempts.
 | |
|   //
 | |
|   if (IfrNvData->AuthenticationType == ISCSI_AUTH_TYPE_CHAP) {
 | |
|     ZeroMem (IfrNvData->CHAPName, sizeof (IfrNvData->CHAPName));
 | |
|     ZeroMem (IfrNvData->CHAPSecret, sizeof (IfrNvData->CHAPSecret));
 | |
|     ZeroMem (IfrNvData->ReverseCHAPName, sizeof (IfrNvData->ReverseCHAPName));
 | |
|     ZeroMem (IfrNvData->ReverseCHAPSecret, sizeof (IfrNvData->ReverseCHAPSecret));
 | |
|   }
 | |
| 
 | |
|   IScsiConvertAttemptConfigDataToIfrNvData (AttemptConfigData, IfrNvData);
 | |
| 
 | |
|   //
 | |
|   // Update current attempt to be a new created attempt or an existing attempt.
 | |
|   //
 | |
|   mCallbackInfo->Current = AttemptConfigData;
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
| 
 | |
|   This function allows the caller to request the current
 | |
|   configuration for one or more named elements. The resulting
 | |
|   string is in <ConfigAltResp> format. Also, any and all alternative
 | |
|   configuration strings shall be appended to the end of the
 | |
|   current configuration string. If they are, they must appear
 | |
|   after the current configuration. They must contain the same
 | |
|   routing (GUID, NAME, PATH) as the current configuration string.
 | |
|   They must have an additional description indicating the type of
 | |
|   alternative configuration the string represents,
 | |
|   "ALTCFG=<StringToken>". That <StringToken> (when
 | |
|   converted from Hex UNICODE to binary) is a reference to a
 | |
|   string in the associated string pack.
 | |
| 
 | |
|   @param[in]  This       Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
 | |
| 
 | |
|   @param[in]  Request    A null-terminated Unicode string in
 | |
|                          <ConfigRequest> format. Note that this
 | |
|                          includes the routing information as well as
 | |
|                          the configurable name / value pairs. It is
 | |
|                          invalid for this string to be in
 | |
|                          <MultiConfigRequest> format.
 | |
| 
 | |
|   @param[out] Progress   On return, points to a character in the
 | |
|                          Request string. Points to the string's null
 | |
|                          terminator if request was successful. Points
 | |
|                          to the most recent "&" before the first
 | |
|                          failing name / value pair (or the beginning
 | |
|                          of the string if the failure is in the first
 | |
|                          name / value pair) if the request was not successful.
 | |
| 
 | |
|   @param[out] Results    A null-terminated Unicode string in
 | |
|                          <ConfigAltResp> format which has all values
 | |
|                          filled in for the names in the Request string.
 | |
|                          String to be allocated by the called function.
 | |
| 
 | |
|   @retval EFI_SUCCESS             The Results string is filled with the
 | |
|                                   values corresponding to all requested
 | |
|                                   names.
 | |
| 
 | |
|   @retval EFI_OUT_OF_RESOURCES    Not enough memory to store the
 | |
|                                   parts of the results that must be
 | |
|                                   stored awaiting possible future
 | |
|                                   protocols.
 | |
| 
 | |
|   @retval EFI_INVALID_PARAMETER   For example, passing in a NULL
 | |
|                                   for the Request parameter
 | |
|                                   would result in this type of
 | |
|                                   error. In this case, the
 | |
|                                   Progress parameter would be
 | |
|                                   set to NULL.
 | |
| 
 | |
|   @retval EFI_NOT_FOUND           Routing data doesn't match any
 | |
|                                   known driver. Progress set to the
 | |
|                                   first character in the routing header.
 | |
|                                   Note: There is no requirement that the
 | |
|                                   driver validate the routing data. It
 | |
|                                   must skip the <ConfigHdr> in order to
 | |
|                                   process the names.
 | |
| 
 | |
|   @retval EFI_INVALID_PARAMETER   Illegal syntax. Progress set
 | |
|                                   to most recent "&" before the
 | |
|                                   error or the beginning of the
 | |
|                                   string.
 | |
| 
 | |
|   @retval EFI_INVALID_PARAMETER   Unknown name. Progress points
 | |
|                                   to the & before the name in
 | |
|                                   question.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| IScsiFormExtractConfig (
 | |
|   IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
 | |
|   IN  CONST EFI_STRING                       Request,
 | |
|   OUT EFI_STRING                             *Progress,
 | |
|   OUT EFI_STRING                             *Results
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                       Status;
 | |
|   CHAR8                            *InitiatorName;
 | |
|   UINTN                            BufferSize;
 | |
|   ISCSI_CONFIG_IFR_NVDATA          *IfrNvData;
 | |
|   ISCSI_FORM_CALLBACK_INFO         *Private;
 | |
|   EFI_STRING                       ConfigRequestHdr;
 | |
|   EFI_STRING                       ConfigRequest;
 | |
|   BOOLEAN                          AllocatedRequest;
 | |
|   UINTN                            Size;
 | |
| 
 | |
|   if (This == NULL || Progress == NULL || Results == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   *Progress = Request;
 | |
|   if ((Request != NULL) && !HiiIsConfigHdrMatch (Request, &gIScsiConfigGuid, mVendorStorageName)) {
 | |
|     return EFI_NOT_FOUND;
 | |
|   }
 | |
| 
 | |
|   ConfigRequestHdr = NULL;
 | |
|   ConfigRequest    = NULL;
 | |
|   AllocatedRequest = FALSE;
 | |
|   Size             = 0;
 | |
| 
 | |
|   Private = ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This);
 | |
|   IfrNvData = AllocateZeroPool (sizeof (ISCSI_CONFIG_IFR_NVDATA));
 | |
|   if (IfrNvData == NULL) {
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
| 
 | |
|   if (Private->Current!= NULL) {
 | |
|     IScsiConvertAttemptConfigDataToIfrNvData (Private->Current, IfrNvData);
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Extract all AttemptConfigData to Keyword storage of IfrNvData.
 | |
|   //
 | |
|   IScsiConvertAttemptConfigDataToIfrNvDataByKeyword (IfrNvData);
 | |
| 
 | |
|   BufferSize    = ISCSI_NAME_MAX_SIZE;
 | |
|   InitiatorName = (CHAR8 *) AllocateZeroPool (BufferSize);
 | |
|   if (InitiatorName == NULL) {
 | |
|     FreePool (IfrNvData);
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   Status = gIScsiInitiatorName.Get (&gIScsiInitiatorName, &BufferSize, InitiatorName);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     IfrNvData->InitiatorName[0] = L'\0';
 | |
|   } else {
 | |
|     AsciiStrToUnicodeStrS (
 | |
|       InitiatorName,
 | |
|       IfrNvData->InitiatorName,
 | |
|       sizeof (IfrNvData->InitiatorName) / sizeof (IfrNvData->InitiatorName[0])
 | |
|       );
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Convert buffer data to <ConfigResp> by helper function BlockToConfig().
 | |
|   //
 | |
|   BufferSize = sizeof (ISCSI_CONFIG_IFR_NVDATA);
 | |
|   ConfigRequest = Request;
 | |
|   if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {
 | |
|     //
 | |
|     // Request has no request element, construct full request string.
 | |
|     // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
 | |
|     // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
 | |
|     //
 | |
|     ConfigRequestHdr = HiiConstructConfigHdr (&gIScsiConfigGuid, mVendorStorageName, Private->DriverHandle);
 | |
|     Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);
 | |
|     ConfigRequest = AllocateZeroPool (Size);
 | |
|     if (ConfigRequest == NULL) {
 | |
|       FreePool (IfrNvData);
 | |
|       FreePool (InitiatorName);
 | |
|       return EFI_OUT_OF_RESOURCES;
 | |
|     }
 | |
|     AllocatedRequest = TRUE;
 | |
|     UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);
 | |
|     FreePool (ConfigRequestHdr);
 | |
|   }
 | |
| 
 | |
|   Status = gHiiConfigRouting->BlockToConfig (
 | |
|                                 gHiiConfigRouting,
 | |
|                                 ConfigRequest,
 | |
|                                 (UINT8 *) IfrNvData,
 | |
|                                 BufferSize,
 | |
|                                 Results,
 | |
|                                 Progress
 | |
|                                 );
 | |
|   FreePool (IfrNvData);
 | |
|   FreePool (InitiatorName);
 | |
| 
 | |
|   //
 | |
|   // Free the allocated config request string.
 | |
|   //
 | |
|   if (AllocatedRequest) {
 | |
|     FreePool (ConfigRequest);
 | |
|     ConfigRequest = NULL;
 | |
|   }
 | |
|   //
 | |
|   // Set Progress string to the original request string.
 | |
|   //
 | |
|   if (Request == NULL) {
 | |
|     *Progress = NULL;
 | |
|   } else if (StrStr (Request, L"OFFSET") == NULL) {
 | |
|     *Progress = Request + StrLen (Request);
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
| 
 | |
|   This function applies changes in a driver's configuration.
 | |
|   Input is a Configuration, which has the routing data for this
 | |
|   driver followed by name / value configuration pairs. The driver
 | |
|   must apply those pairs to its configurable storage. If the
 | |
|   driver's configuration is stored in a linear block of data
 | |
|   and the driver's name / value pairs are in <BlockConfig>
 | |
|   format, it may use the ConfigToBlock helper function (above) to
 | |
|   simplify the job.
 | |
| 
 | |
|   @param[in]  This           Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
 | |
| 
 | |
|   @param[in]  Configuration  A null-terminated Unicode string in
 | |
|                              <ConfigString> format.
 | |
| 
 | |
|   @param[out] Progress       A pointer to a string filled in with the
 | |
|                              offset of the most recent '&' before the
 | |
|                              first failing name / value pair (or the
 | |
|                              beginning of the string if the failure
 | |
|                              is in the first name / value pair) or
 | |
|                              the terminating NULL if all was
 | |
|                              successful.
 | |
| 
 | |
|   @retval EFI_SUCCESS             The results have been distributed or are
 | |
|                                   awaiting distribution.
 | |
| 
 | |
|   @retval EFI_OUT_OF_RESOURCES    Not enough memory to store the
 | |
|                                   parts of the results that must be
 | |
|                                   stored awaiting possible future
 | |
|                                   protocols.
 | |
| 
 | |
|   @retval EFI_INVALID_PARAMETERS  Passing in a NULL for the
 | |
|                                   Results parameter would result
 | |
|                                   in this type of error.
 | |
| 
 | |
|   @retval EFI_NOT_FOUND           Target for the specified routing data
 | |
|                                   was not found.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| IScsiFormRouteConfig (
 | |
|   IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
 | |
|   IN  CONST EFI_STRING                       Configuration,
 | |
|   OUT EFI_STRING                             *Progress
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                       Status;
 | |
|   ISCSI_CONFIG_IFR_NVDATA          *IfrNvData;
 | |
|   ISCSI_ATTEMPT_CONFIG_NVDATA      *AttemptConfigData;
 | |
|   LIST_ENTRY                       *Entry;
 | |
|   LIST_ENTRY                       *NextEntry;
 | |
|   ISCSI_NIC_INFO                   *NicInfo;
 | |
|   EFI_INPUT_KEY                    Key;
 | |
|   CHAR16                           MacString[ISCSI_MAX_MAC_STRING_LEN];
 | |
|   CHAR8                            *InitiatorName;
 | |
|   UINT8                            *AttemptList;
 | |
|   UINTN                            BufferSize;
 | |
|   UINTN                            OffSet;
 | |
|   UINTN                            Index;
 | |
|   UINTN                            Index2;
 | |
| 
 | |
|   Index   = 0;
 | |
|   Index2  = 0;
 | |
|   NicInfo = NULL;
 | |
|   AttemptList = NULL;
 | |
|   Status = EFI_SUCCESS;
 | |
| 
 | |
|   if (This == NULL || Configuration == NULL || Progress == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Check routing data in <ConfigHdr>.
 | |
|   // Note: if only one Storage is used, then this checking could be skipped.
 | |
|   //
 | |
|   if (!HiiIsConfigHdrMatch (Configuration, &gIScsiConfigGuid, mVendorStorageName)) {
 | |
|     *Progress = Configuration;
 | |
|     return EFI_NOT_FOUND;
 | |
|   }
 | |
| 
 | |
|   IfrNvData = AllocateZeroPool (sizeof (ISCSI_CONFIG_IFR_NVDATA));
 | |
|   if (IfrNvData == NULL) {
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   BufferSize    = ISCSI_NAME_MAX_SIZE;
 | |
|   InitiatorName = (CHAR8 *) AllocateZeroPool (BufferSize);
 | |
|   if (InitiatorName == NULL) {
 | |
|     Status = EFI_OUT_OF_RESOURCES;
 | |
|     goto Exit;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Convert <ConfigResp> to buffer data by helper function ConfigToBlock().
 | |
|   //
 | |
|   BufferSize = sizeof (ISCSI_CONFIG_IFR_NVDATA);
 | |
|   Status = gHiiConfigRouting->ConfigToBlock (
 | |
|                              gHiiConfigRouting,
 | |
|                              Configuration,
 | |
|                              (UINT8 *) IfrNvData,
 | |
|                              &BufferSize,
 | |
|                              Progress
 | |
|                              );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     goto Exit;
 | |
|   }
 | |
| 
 | |
|   if (IfrNvData->InitiatorName[0] != L'\0') {
 | |
|     UnicodeStrToAsciiStrS (IfrNvData->InitiatorName, InitiatorName, ISCSI_NAME_MAX_SIZE);
 | |
|     BufferSize  = AsciiStrSize (InitiatorName);
 | |
| 
 | |
|     Status      = gIScsiInitiatorName.Set (&gIScsiInitiatorName, &BufferSize, InitiatorName);
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       CreatePopUp (
 | |
|         EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
 | |
|         &Key,
 | |
|         L"Invalid iSCSI Name!",
 | |
|         NULL
 | |
|         );
 | |
|       goto Exit;
 | |
|     }
 | |
|   } else {
 | |
|     Status = IScsiGetValue (Configuration, L"&OFFSET=", &OffSet);
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       goto Exit;
 | |
|     }
 | |
| 
 | |
|     if (OffSet >= ATTEMPT_MAC_ADDR_VAR_OFFSET) {
 | |
|       Status = gIScsiInitiatorName.Get (&gIScsiInitiatorName, &BufferSize, InitiatorName);
 | |
|       if (EFI_ERROR (Status)) {
 | |
|         CreatePopUp (
 | |
|           EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
 | |
|           &Key,
 | |
|           L"Error: please configure iSCSI initiator name first!",
 | |
|           NULL
 | |
|           );
 | |
|         goto Exit;
 | |
|       }
 | |
|     } else {
 | |
|       goto Exit;
 | |
|     }
 | |
| 
 | |
|     if (IfrNvData->ISCSIAddAttemptList[0] != L'\0') {
 | |
|       Status =IScsiGetAttemptIndexList (IfrNvData->ISCSIAddAttemptList, IfrNvData->AddAttemptList, TRUE);
 | |
|       if (EFI_ERROR (Status)) {
 | |
|           CreatePopUp (
 | |
|             EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
 | |
|             &Key,
 | |
|             L"Error: The add attempt list is invalid",
 | |
|             NULL
 | |
|             );
 | |
|         goto Exit;
 | |
|       }
 | |
| 
 | |
|       Status = IScsiConfigAddAttemptsByKeywords (IfrNvData->AddAttemptList);
 | |
|       if (EFI_ERROR (Status)) {
 | |
|         goto Exit;
 | |
|       }
 | |
| 
 | |
|     } else if (IfrNvData->ISCSIDeleteAttemptList[0] != L'\0') {
 | |
|       AttemptList =(UINT8 *) AllocateZeroPool ((ISCSI_MAX_ATTEMPTS_NUM + 1) * sizeof (UINT8));
 | |
|       if (AttemptList == NULL) {
 | |
|         Status = EFI_OUT_OF_RESOURCES;
 | |
|         goto Exit;
 | |
|       }
 | |
|       Status = IScsiGetAttemptIndexList (IfrNvData->ISCSIDeleteAttemptList, AttemptList, FALSE);
 | |
|       if (EFI_ERROR (Status)) {
 | |
|           CreatePopUp (
 | |
|             EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
 | |
|             &Key,
 | |
|             L"Error: The delete attempt list is invalid",
 | |
|             NULL
 | |
|             );
 | |
|         goto Exit;
 | |
|       }
 | |
| 
 | |
|       //
 | |
|       // Mark the attempt which will be delete in the global list.
 | |
|       //
 | |
|       NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &mPrivate->AttemptConfigs) {
 | |
|         AttemptConfigData = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);
 | |
|         while (AttemptList[Index] != 0) {
 | |
|           if (AttemptConfigData->AttemptConfigIndex == AttemptList[Index]) {
 | |
|             IfrNvData->DeleteAttemptList[Index2] = 1;
 | |
|             break;
 | |
|           }
 | |
|           Index ++;
 | |
|         }
 | |
|         Index2 ++;
 | |
|         Index = 0;
 | |
|       }
 | |
| 
 | |
|       Status = IScsiConfigDeleteAttempts (IfrNvData);
 | |
|       if (EFI_ERROR (Status)) {
 | |
|         goto Exit;
 | |
|       }
 | |
| 
 | |
|       FreePool (AttemptList);
 | |
| 
 | |
|     } else if (IfrNvData->ISCSIAttemptOrder[0] != L'\0') {
 | |
|       Status = IScsiGetAttemptIndexList (IfrNvData->ISCSIAttemptOrder, IfrNvData->DynamicOrderedList, FALSE);
 | |
|       if (EFI_ERROR (Status)) {
 | |
|           CreatePopUp (
 | |
|             EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
 | |
|             &Key,
 | |
|             L"Error: The new attempt order list is invalid",
 | |
|             NULL
 | |
|             );
 | |
|         goto Exit;
 | |
|       }
 | |
| 
 | |
|       Status = IScsiConfigOrderAttempts (IfrNvData);
 | |
|       if (EFI_ERROR (Status)) {
 | |
|         goto Exit;
 | |
|       }
 | |
| 
 | |
|     } else if (IfrNvData->ISCSIMacAddr[0] != L'\0') {
 | |
|       NET_LIST_FOR_EACH (Entry, &mPrivate->NicInfoList) {
 | |
|         NicInfo = NET_LIST_USER_STRUCT (Entry, ISCSI_NIC_INFO, Link);
 | |
|         IScsiMacAddrToStr (
 | |
|         &NicInfo->PermanentAddress,
 | |
|         NicInfo->HwAddressSize,
 | |
|         NicInfo->VlanId,
 | |
|         MacString
 | |
|         );
 | |
|         if (!StrCmp(MacString, IfrNvData->ISCSIMacAddr)) {
 | |
|           mPrivate->CurrentNic = NicInfo->NicIndex;
 | |
|           break;
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       if ((NicInfo == NULL) || (NicInfo->NicIndex == 0)) {
 | |
|         Status = EFI_NOT_FOUND;
 | |
|         goto Exit;
 | |
|       }
 | |
| 
 | |
|     } else {
 | |
|       Status = IScsiConvertlfrNvDataToAttemptConfigDataByKeyword (IfrNvData, OffSet);
 | |
|       if (EFI_ERROR (Status)) {
 | |
|         goto Exit;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   IScsiConfigUpdateAttempt ();
 | |
| 
 | |
| Exit:
 | |
|   if (InitiatorName != NULL) {
 | |
|     FreePool (InitiatorName);
 | |
|   }
 | |
| 
 | |
|   if (IfrNvData != NULL) {
 | |
|     FreePool (IfrNvData);
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
| 
 | |
|   This function is called to provide results data to the driver.
 | |
|   This data consists of a unique key that is used to identify
 | |
|   which data is either being passed back or being asked for.
 | |
| 
 | |
|   @param[in]       This          Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
 | |
|   @param[in]       Action        Specifies the type of action taken by the browser.
 | |
|   @param[in]       QuestionId    A unique value which is sent to the original
 | |
|                                  exporting driver so that it can identify the type
 | |
|                                  of data to expect. The format of the data tends to
 | |
|                                  vary based on the opcode that generated the callback.
 | |
|   @param[in]       Type          The type of value for the question.
 | |
|   @param[in, out]  Value         A pointer to the data being sent to the original
 | |
|                                  exporting driver.
 | |
|   @param[out]      ActionRequest On return, points to the action requested by the
 | |
|                                  callback function.
 | |
| 
 | |
|   @retval EFI_SUCCESS            The callback successfully handled the action.
 | |
|   @retval EFI_OUT_OF_RESOURCES   Not enough storage is available to hold the
 | |
|                                  variable and its data.
 | |
|   @retval EFI_DEVICE_ERROR       The variable could not be saved.
 | |
|   @retval EFI_UNSUPPORTED        The specified Action is not supported by the
 | |
|                                  callback.
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| IScsiFormCallback (
 | |
|   IN CONST  EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
 | |
|   IN        EFI_BROWSER_ACTION               Action,
 | |
|   IN        EFI_QUESTION_ID                  QuestionId,
 | |
|   IN        UINT8                            Type,
 | |
|   IN OUT    EFI_IFR_TYPE_VALUE               *Value,
 | |
|   OUT       EFI_BROWSER_ACTION_REQUEST       *ActionRequest
 | |
|   )
 | |
| {
 | |
|   ISCSI_FORM_CALLBACK_INFO    *Private;
 | |
|   UINTN                       BufferSize;
 | |
|   CHAR8                       *IScsiName;
 | |
|   CHAR8                       IpString[ISCSI_NAME_MAX_SIZE];
 | |
|   CHAR8                       LunString[ISCSI_LUN_STR_MAX_LEN];
 | |
|   UINT64                      Lun;
 | |
|   EFI_IP_ADDRESS              HostIp;
 | |
|   EFI_IP_ADDRESS              SubnetMask;
 | |
|   EFI_IP_ADDRESS              Gateway;
 | |
|   ISCSI_CONFIG_IFR_NVDATA     *IfrNvData;
 | |
|   ISCSI_CONFIG_IFR_NVDATA     OldIfrNvData;
 | |
|   EFI_STATUS                  Status;
 | |
|   EFI_INPUT_KEY               Key;
 | |
|   ISCSI_NIC_INFO              *NicInfo;
 | |
| 
 | |
|   NicInfo = NULL;
 | |
| 
 | |
|   if ((Action == EFI_BROWSER_ACTION_FORM_OPEN) || (Action == EFI_BROWSER_ACTION_FORM_CLOSE)) {
 | |
|     //
 | |
|     // Do nothing for UEFI OPEN/CLOSE Action
 | |
|     //
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   if ((Action != EFI_BROWSER_ACTION_CHANGING) && (Action != EFI_BROWSER_ACTION_CHANGED)) {
 | |
|     //
 | |
|     // All other type return unsupported.
 | |
|     //
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   if ((Value == NULL) || (ActionRequest == NULL)) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   Private = ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This);
 | |
| 
 | |
|   //
 | |
|   // Retrieve uncommitted data from Browser
 | |
|   //
 | |
| 
 | |
|   BufferSize = sizeof (ISCSI_CONFIG_IFR_NVDATA);
 | |
|   IfrNvData = AllocateZeroPool (BufferSize);
 | |
|   if (IfrNvData == NULL) {
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   IScsiName = (CHAR8 *) AllocateZeroPool (ISCSI_NAME_MAX_SIZE);
 | |
|   if (IScsiName == NULL) {
 | |
|     FreePool (IfrNvData);
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   Status = EFI_SUCCESS;
 | |
| 
 | |
|   ZeroMem (&OldIfrNvData, BufferSize);
 | |
| 
 | |
|   HiiGetBrowserData (NULL, NULL, BufferSize, (UINT8 *) IfrNvData);
 | |
| 
 | |
|   CopyMem (&OldIfrNvData, IfrNvData, BufferSize);
 | |
| 
 | |
|   if (Action == EFI_BROWSER_ACTION_CHANGING) {
 | |
|     switch (QuestionId) {
 | |
|     case KEY_ADD_ATTEMPT:
 | |
|       //
 | |
|       // Check whether iSCSI initiator name is configured already.
 | |
|       //
 | |
|       mPrivate->InitiatorNameLength = ISCSI_NAME_MAX_SIZE;
 | |
|       Status = gIScsiInitiatorName.Get (
 | |
|                                      &gIScsiInitiatorName,
 | |
|                                      &mPrivate->InitiatorNameLength,
 | |
|                                      mPrivate->InitiatorName
 | |
|                                      );
 | |
|       if (EFI_ERROR (Status)) {
 | |
|         CreatePopUp (
 | |
|           EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
 | |
|           &Key,
 | |
|           L"Error: please configure iSCSI initiator name first!",
 | |
|           NULL
 | |
|           );
 | |
|         break;
 | |
|       }
 | |
| 
 | |
|       Status = IScsiConfigAddAttempt ();
 | |
|       break;
 | |
| 
 | |
|     case KEY_DELETE_ATTEMPT:
 | |
|       CopyMem (
 | |
|         OldIfrNvData.DeleteAttemptList,
 | |
|         IfrNvData->DeleteAttemptList,
 | |
|         sizeof (IfrNvData->DeleteAttemptList)
 | |
|         );
 | |
|       Status = IScsiConfigDisplayDeleteAttempts (IfrNvData);
 | |
|       break;
 | |
| 
 | |
|     case KEY_ORDER_ATTEMPT_CONFIG:
 | |
|       //
 | |
|       // Order the attempt according to user input.
 | |
|       //
 | |
|       CopyMem (
 | |
|         OldIfrNvData.DynamicOrderedList,
 | |
|         IfrNvData->DynamicOrderedList,
 | |
|         sizeof (IfrNvData->DynamicOrderedList)
 | |
|         );
 | |
|       IScsiConfigDisplayOrderAttempts ();
 | |
|       break;
 | |
| 
 | |
|     default:
 | |
|       Status = IScsiConfigProcessDefault (QuestionId, IfrNvData);
 | |
|       break;
 | |
|     }
 | |
|   } else if (Action == EFI_BROWSER_ACTION_CHANGED) {
 | |
|     switch (QuestionId) {
 | |
|     case KEY_INITIATOR_NAME:
 | |
|       UnicodeStrToAsciiStrS (IfrNvData->InitiatorName, IScsiName, ISCSI_NAME_MAX_SIZE);
 | |
|       BufferSize  = AsciiStrSize (IScsiName);
 | |
| 
 | |
|       Status      = gIScsiInitiatorName.Set (&gIScsiInitiatorName, &BufferSize, IScsiName);
 | |
|       if (EFI_ERROR (Status)) {
 | |
|         CreatePopUp (
 | |
|           EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
 | |
|           &Key,
 | |
|           L"Invalid iSCSI Name!",
 | |
|           NULL
 | |
|           );
 | |
|       }
 | |
| 
 | |
|       *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
 | |
|       break;
 | |
| 
 | |
|     case KEY_SAVE_ATTEMPT_CONFIG:
 | |
|       Status = IScsiConvertIfrNvDataToAttemptConfigData (IfrNvData, Private->Current);
 | |
|       if (EFI_ERROR (Status)) {
 | |
|         break;
 | |
|       }
 | |
| 
 | |
|       *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT;
 | |
|       break;
 | |
| 
 | |
|     case KEY_SAVE_ORDER_CHANGES:
 | |
|       //
 | |
|       // Sync the Attempt Order to NVR.
 | |
|       //
 | |
|       Status = IScsiConfigOrderAttempts (IfrNvData);
 | |
|       if (EFI_ERROR (Status)) {
 | |
|         break;
 | |
|       }
 | |
| 
 | |
|       IScsiConfigUpdateAttempt ();
 | |
|       *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT;
 | |
|       break;
 | |
| 
 | |
|     case KEY_IGNORE_ORDER_CHANGES:
 | |
|       CopyMem (
 | |
|         IfrNvData->DynamicOrderedList,
 | |
|         OldIfrNvData.DynamicOrderedList,
 | |
|         sizeof (IfrNvData->DynamicOrderedList)
 | |
|         );
 | |
|       *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT;
 | |
|       break;
 | |
| 
 | |
|     case KEY_SAVE_DELETE_ATTEMPT:
 | |
|       //
 | |
|       // Delete the Attempt Order from NVR
 | |
|       //
 | |
|       Status = IScsiConfigDeleteAttempts (IfrNvData);
 | |
|       if (EFI_ERROR (Status)) {
 | |
|         break;
 | |
|       }
 | |
| 
 | |
|       IScsiConfigUpdateAttempt ();
 | |
|       *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT;
 | |
|       break;
 | |
| 
 | |
|     case KEY_IGNORE_DELETE_ATTEMPT:
 | |
|       CopyMem (
 | |
|         IfrNvData->DeleteAttemptList,
 | |
|         OldIfrNvData.DeleteAttemptList,
 | |
|         sizeof (IfrNvData->DeleteAttemptList)
 | |
|         );
 | |
|       *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT;
 | |
|       break;
 | |
| 
 | |
|     case KEY_IP_MODE:
 | |
|       switch (Value->u8) {
 | |
|       case IP_MODE_IP6:
 | |
|         NicInfo = IScsiGetNicInfoByIndex (Private->Current->NicIndex);
 | |
|         if(NicInfo == NULL) {
 | |
|           break;
 | |
|         }
 | |
| 
 | |
|         if(!NicInfo->Ipv6Available) {
 | |
|           //
 | |
|           // Current NIC doesn't Support IPv6, hence use IPv4.
 | |
|           //
 | |
|           IfrNvData->IpMode = IP_MODE_IP4;
 | |
| 
 | |
|           CreatePopUp (
 | |
|             EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
 | |
|             &Key,
 | |
|             L"Current NIC doesn't Support IPv6!",
 | |
|             NULL
 | |
|             );
 | |
|         }
 | |
| 
 | |
|       case IP_MODE_IP4:
 | |
|         ZeroMem (IfrNvData->LocalIp, sizeof (IfrNvData->LocalIp));
 | |
|         ZeroMem (IfrNvData->SubnetMask, sizeof (IfrNvData->SubnetMask));
 | |
|         ZeroMem (IfrNvData->Gateway, sizeof (IfrNvData->Gateway));
 | |
|         ZeroMem (IfrNvData->TargetIp, sizeof (IfrNvData->TargetIp));
 | |
|         Private->Current->AutoConfigureMode = 0;
 | |
|         ZeroMem (&Private->Current->SessionConfigData.LocalIp, sizeof (EFI_IP_ADDRESS));
 | |
|         ZeroMem (&Private->Current->SessionConfigData.SubnetMask, sizeof (EFI_IPv4_ADDRESS));
 | |
|         ZeroMem (&Private->Current->SessionConfigData.Gateway, sizeof (EFI_IP_ADDRESS));
 | |
|         ZeroMem (&Private->Current->SessionConfigData.TargetIp, sizeof (EFI_IP_ADDRESS));
 | |
| 
 | |
|         break;
 | |
|       }
 | |
| 
 | |
|       break;
 | |
| 
 | |
|     case KEY_LOCAL_IP:
 | |
|       Status = NetLibStrToIp4 (IfrNvData->LocalIp, &HostIp.v4);
 | |
|       if (EFI_ERROR (Status) ||
 | |
|           ((Private->Current->SessionConfigData.SubnetMask.Addr[0] != 0) &&
 | |
|            !NetIp4IsUnicast (NTOHL (HostIp.Addr[0]), NTOHL(*(UINT32*)Private->Current->SessionConfigData.SubnetMask.Addr)))) {
 | |
|         CreatePopUp (
 | |
|           EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
 | |
|           &Key,
 | |
|           L"Invalid IP address!",
 | |
|           NULL
 | |
|           );
 | |
| 
 | |
|         Status = EFI_INVALID_PARAMETER;
 | |
|       } else {
 | |
|         CopyMem (&Private->Current->SessionConfigData.LocalIp, &HostIp.v4, sizeof (HostIp.v4));
 | |
|       }
 | |
| 
 | |
|       break;
 | |
| 
 | |
|     case KEY_SUBNET_MASK:
 | |
|       Status = NetLibStrToIp4 (IfrNvData->SubnetMask, &SubnetMask.v4);
 | |
|       if (EFI_ERROR (Status) || ((SubnetMask.Addr[0] != 0) && (IScsiGetSubnetMaskPrefixLength (&SubnetMask.v4) == 0))) {
 | |
|         CreatePopUp (
 | |
|           EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
 | |
|           &Key,
 | |
|           L"Invalid Subnet Mask!",
 | |
|           NULL
 | |
|           );
 | |
| 
 | |
|         Status = EFI_INVALID_PARAMETER;
 | |
|       } else {
 | |
|         CopyMem (&Private->Current->SessionConfigData.SubnetMask, &SubnetMask.v4, sizeof (SubnetMask.v4));
 | |
|       }
 | |
| 
 | |
|       break;
 | |
| 
 | |
|     case KEY_GATE_WAY:
 | |
|       Status = NetLibStrToIp4 (IfrNvData->Gateway, &Gateway.v4);
 | |
|       if (EFI_ERROR (Status) ||
 | |
|           ((Gateway.Addr[0] != 0) &&
 | |
|            (Private->Current->SessionConfigData.SubnetMask.Addr[0] != 0) &&
 | |
|            !NetIp4IsUnicast (NTOHL (Gateway.Addr[0]), NTOHL(*(UINT32*)Private->Current->SessionConfigData.SubnetMask.Addr)))) {
 | |
|         CreatePopUp (
 | |
|           EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
 | |
|           &Key,
 | |
|           L"Invalid Gateway!",
 | |
|           NULL
 | |
|           );
 | |
|         Status = EFI_INVALID_PARAMETER;
 | |
|       } else {
 | |
|         CopyMem (&Private->Current->SessionConfigData.Gateway, &Gateway.v4, sizeof (Gateway.v4));
 | |
|       }
 | |
| 
 | |
|       break;
 | |
| 
 | |
|     case KEY_TARGET_IP:
 | |
|       UnicodeStrToAsciiStrS (IfrNvData->TargetIp, IpString, sizeof (IpString));
 | |
|       Status = IScsiAsciiStrToIp (IpString, IfrNvData->IpMode, &HostIp);
 | |
|       if (EFI_ERROR (Status) || !IpIsUnicast (&HostIp, IfrNvData->IpMode)) {
 | |
|       //
 | |
|       // The target is expressed in URL format or an invalid Ip address, just save.
 | |
|       //
 | |
|       Private->Current->SessionConfigData.DnsMode = TRUE;
 | |
|       ZeroMem (&Private->Current->SessionConfigData.TargetIp, sizeof (Private->Current->SessionConfigData.TargetIp));
 | |
|       UnicodeStrToAsciiStrS (IfrNvData->TargetIp, Private->Current->SessionConfigData.TargetUrl, ISCSI_NAME_MAX_SIZE);
 | |
|       } else {
 | |
|         Private->Current->SessionConfigData.DnsMode = FALSE;
 | |
|         CopyMem (&Private->Current->SessionConfigData.TargetIp, &HostIp, sizeof (HostIp));
 | |
|       }
 | |
| 
 | |
|       break;
 | |
| 
 | |
|     case KEY_TARGET_NAME:
 | |
|       UnicodeStrToAsciiStrS (IfrNvData->TargetName, IScsiName, ISCSI_NAME_MAX_SIZE);
 | |
|       Status = IScsiNormalizeName (IScsiName, AsciiStrLen (IScsiName));
 | |
|       if (EFI_ERROR (Status)) {
 | |
|         CreatePopUp (
 | |
|           EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
 | |
|           &Key,
 | |
|           L"Invalid iSCSI Name!",
 | |
|           NULL
 | |
|           );
 | |
|       } else {
 | |
|         AsciiStrCpyS (Private->Current->SessionConfigData.TargetName, ISCSI_NAME_MAX_SIZE, IScsiName);
 | |
|       }
 | |
| 
 | |
|       break;
 | |
| 
 | |
|     case KEY_DHCP_ENABLE:
 | |
|       if (IfrNvData->InitiatorInfoFromDhcp == 0) {
 | |
|         IfrNvData->TargetInfoFromDhcp = 0;
 | |
|       }
 | |
| 
 | |
|       break;
 | |
| 
 | |
|     case KEY_BOOT_LUN:
 | |
|       UnicodeStrToAsciiStrS (IfrNvData->BootLun, LunString, sizeof (LunString));
 | |
|       Status = IScsiAsciiStrToLun (LunString, (UINT8 *) &Lun);
 | |
|       if (EFI_ERROR (Status)) {
 | |
|         CreatePopUp (
 | |
|           EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
 | |
|           &Key,
 | |
|           L"Invalid LUN string!",
 | |
|           NULL
 | |
|           );
 | |
|       } else {
 | |
|         CopyMem (Private->Current->SessionConfigData.BootLun, &Lun, sizeof (Lun));
 | |
|       }
 | |
| 
 | |
|       break;
 | |
| 
 | |
|     case KEY_AUTH_TYPE:
 | |
|       switch (Value->u8) {
 | |
|       case ISCSI_AUTH_TYPE_CHAP:
 | |
|         IfrNvData->CHAPType = ISCSI_CHAP_UNI;
 | |
|         break;
 | |
|       default:
 | |
|         break;
 | |
|       }
 | |
| 
 | |
|       break;
 | |
| 
 | |
|     case KEY_CHAP_NAME:
 | |
|       UnicodeStrToAsciiStrS (
 | |
|         IfrNvData->CHAPName,
 | |
|         Private->Current->AuthConfigData.CHAP.CHAPName,
 | |
|         sizeof (Private->Current->AuthConfigData.CHAP.CHAPName)
 | |
|         );
 | |
|       break;
 | |
| 
 | |
|     case KEY_CHAP_SECRET:
 | |
|       UnicodeStrToAsciiStrS (
 | |
|         IfrNvData->CHAPSecret,
 | |
|         Private->Current->AuthConfigData.CHAP.CHAPSecret,
 | |
|         sizeof (Private->Current->AuthConfigData.CHAP.CHAPSecret)
 | |
|         );
 | |
|       break;
 | |
| 
 | |
|     case KEY_REVERSE_CHAP_NAME:
 | |
|       UnicodeStrToAsciiStrS (
 | |
|         IfrNvData->ReverseCHAPName,
 | |
|         Private->Current->AuthConfigData.CHAP.ReverseCHAPName,
 | |
|         sizeof (Private->Current->AuthConfigData.CHAP.ReverseCHAPName)
 | |
|         );
 | |
|       break;
 | |
| 
 | |
|     case KEY_REVERSE_CHAP_SECRET:
 | |
|       UnicodeStrToAsciiStrS (
 | |
|         IfrNvData->ReverseCHAPSecret,
 | |
|         Private->Current->AuthConfigData.CHAP.ReverseCHAPSecret,
 | |
|         sizeof (Private->Current->AuthConfigData.CHAP.ReverseCHAPSecret)
 | |
|         );
 | |
|       break;
 | |
| 
 | |
|     case KEY_CONFIG_ISID:
 | |
|       IScsiParseIsIdFromString (IfrNvData->IsId, Private->Current->SessionConfigData.IsId);
 | |
|       IScsiConvertIsIdToString (IfrNvData->IsId, Private->Current->SessionConfigData.IsId);
 | |
| 
 | |
|       break;
 | |
| 
 | |
|     default:
 | |
|       break;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (!EFI_ERROR (Status)) {
 | |
|     //
 | |
|     // Pass changed uncommitted data back to Form Browser.
 | |
|     //
 | |
|     BufferSize = sizeof (ISCSI_CONFIG_IFR_NVDATA);
 | |
|     HiiSetBrowserData (NULL, NULL, BufferSize, (UINT8 *) IfrNvData, NULL);
 | |
|   }
 | |
| 
 | |
|   FreePool (IfrNvData);
 | |
|   FreePool (IScsiName);
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Initialize the iSCSI configuration form.
 | |
| 
 | |
|   @param[in]  DriverBindingHandle The iSCSI driverbinding handle.
 | |
| 
 | |
|   @retval EFI_SUCCESS             The iSCSI configuration form is initialized.
 | |
|   @retval EFI_OUT_OF_RESOURCES    Failed to allocate memory.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| IScsiConfigFormInit (
 | |
|   IN EFI_HANDLE  DriverBindingHandle
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                  Status;
 | |
|   ISCSI_FORM_CALLBACK_INFO    *CallbackInfo;
 | |
| 
 | |
|   CallbackInfo = (ISCSI_FORM_CALLBACK_INFO *) AllocateZeroPool (sizeof (ISCSI_FORM_CALLBACK_INFO));
 | |
|   if (CallbackInfo == NULL) {
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   CallbackInfo->Signature   = ISCSI_FORM_CALLBACK_INFO_SIGNATURE;
 | |
|   CallbackInfo->Current     = NULL;
 | |
| 
 | |
|   CallbackInfo->ConfigAccess.ExtractConfig = IScsiFormExtractConfig;
 | |
|   CallbackInfo->ConfigAccess.RouteConfig   = IScsiFormRouteConfig;
 | |
|   CallbackInfo->ConfigAccess.Callback      = IScsiFormCallback;
 | |
| 
 | |
|   //
 | |
|   // Install Device Path Protocol and Config Access protocol to driver handle.
 | |
|   //
 | |
|   Status = gBS->InstallMultipleProtocolInterfaces (
 | |
|                   &CallbackInfo->DriverHandle,
 | |
|                   &gEfiDevicePathProtocolGuid,
 | |
|                   &mIScsiHiiVendorDevicePath,
 | |
|                   &gEfiHiiConfigAccessProtocolGuid,
 | |
|                   &CallbackInfo->ConfigAccess,
 | |
|                   NULL
 | |
|                   );
 | |
|   ASSERT_EFI_ERROR (Status);
 | |
| 
 | |
|   //
 | |
|   // Publish our HII data.
 | |
|   //
 | |
|   CallbackInfo->RegisteredHandle = HiiAddPackages (
 | |
|                                      &gIScsiConfigGuid,
 | |
|                                      CallbackInfo->DriverHandle,
 | |
|                                      IScsiDxeStrings,
 | |
|                                      IScsiConfigVfrBin,
 | |
|                                      NULL
 | |
|                                      );
 | |
|   if (CallbackInfo->RegisteredHandle == NULL) {
 | |
|     gBS->UninstallMultipleProtocolInterfaces (
 | |
|            CallbackInfo->DriverHandle,
 | |
|            &gEfiDevicePathProtocolGuid,
 | |
|            &mIScsiHiiVendorDevicePath,
 | |
|            &gEfiHiiConfigAccessProtocolGuid,
 | |
|            &CallbackInfo->ConfigAccess,
 | |
|            NULL
 | |
|            );
 | |
|     FreePool(CallbackInfo);
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   mCallbackInfo = CallbackInfo;
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Unload the iSCSI configuration form, this includes: delete all the iSCSI
 | |
|   configuration entries, uninstall the form callback protocol, and
 | |
|   free the resources used.
 | |
| 
 | |
|   @param[in]  DriverBindingHandle The iSCSI driverbinding handle.
 | |
| 
 | |
|   @retval EFI_SUCCESS             The iSCSI configuration form is unloaded.
 | |
|   @retval Others                  Failed to unload the form.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| IScsiConfigFormUnload (
 | |
|   IN EFI_HANDLE  DriverBindingHandle
 | |
|   )
 | |
| {
 | |
|   ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;
 | |
|   ISCSI_NIC_INFO              *NicInfo;
 | |
|   LIST_ENTRY                  *Entry;
 | |
|   EFI_STATUS                  Status;
 | |
| 
 | |
|   while (!IsListEmpty (&mPrivate->AttemptConfigs)) {
 | |
|     Entry = NetListRemoveHead (&mPrivate->AttemptConfigs);
 | |
|     AttemptConfigData = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);
 | |
|     FreePool (AttemptConfigData);
 | |
|     mPrivate->AttemptCount--;
 | |
|   }
 | |
| 
 | |
|   ASSERT (mPrivate->AttemptCount == 0);
 | |
| 
 | |
|   while (!IsListEmpty (&mPrivate->NicInfoList)) {
 | |
|     Entry = NetListRemoveHead (&mPrivate->NicInfoList);
 | |
|     NicInfo = NET_LIST_USER_STRUCT (Entry, ISCSI_NIC_INFO, Link);
 | |
|     FreePool (NicInfo);
 | |
|     mPrivate->NicCount--;
 | |
|   }
 | |
| 
 | |
|   ASSERT (mPrivate->NicCount == 0);
 | |
| 
 | |
|   FreePool (mPrivate);
 | |
|   mPrivate = NULL;
 | |
| 
 | |
|   //
 | |
|   // Remove HII package list.
 | |
|   //
 | |
|   HiiRemovePackages (mCallbackInfo->RegisteredHandle);
 | |
| 
 | |
|   //
 | |
|   // Uninstall Device Path Protocol and Config Access protocol.
 | |
|   //
 | |
|   Status = gBS->UninstallMultipleProtocolInterfaces (
 | |
|                   mCallbackInfo->DriverHandle,
 | |
|                   &gEfiDevicePathProtocolGuid,
 | |
|                   &mIScsiHiiVendorDevicePath,
 | |
|                   &gEfiHiiConfigAccessProtocolGuid,
 | |
|                   &mCallbackInfo->ConfigAccess,
 | |
|                   NULL
 | |
|                   );
 | |
| 
 | |
|   FreePool (mCallbackInfo);
 | |
| 
 | |
|   return Status;
 | |
| }
 |