X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=NetworkPkg%2FIScsiDxe%2FIScsiConfig.c;h=a588403017355547b8ce0d61830a456e3a2802af;hb=b28bf4143d00142323d5dd9a9129b9b25d0dff56;hp=a82ce231e8db26335d20ef24fde1d60729a229aa;hpb=b9679cd7458110573dd4614148433312b61a1e26;p=mirror_edk2.git diff --git a/NetworkPkg/IScsiDxe/IScsiConfig.c b/NetworkPkg/IScsiDxe/IScsiConfig.c index a82ce231e8..a588403017 100644 --- a/NetworkPkg/IScsiDxe/IScsiConfig.c +++ b/NetworkPkg/IScsiDxe/IScsiConfig.c @@ -1,7 +1,7 @@ /** @file Helper functions for configuring or getting the parameters relating to iSCSI. -Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.
+Copyright (c) 2004 - 2017, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at @@ -164,7 +164,10 @@ IpIsUnicast ( ) { if (IpMode == IP_MODE_IP4) { - return NetIp4IsUnicast (NTOHL (Ip->Addr[0]), 0); + 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 { @@ -286,6 +289,98 @@ IScsiConvertIsIdToString ( return EFI_SUCCESS; } +/** + Get the Offset value specified by the input String. + + @param[in] Configuration A null-terminated Unicode string in + format. + @param[in] String The string is "&OFFSET=". + @param[out] Value The Offset value. + + @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary + structures. + @retval EFI_SUCCESS Value of 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. @@ -346,6 +441,64 @@ IScsiConfigGetAttemptByNic ( 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. @@ -363,6 +516,7 @@ IScsiConvertAttemptConfigDataToIfrNvData ( ISCSI_SESSION_CONFIG_NVDATA *SessionConfigData; ISCSI_CHAP_AUTH_CONFIG_NVDATA *AuthConfigData; EFI_IP_ADDRESS Ip; + BOOLEAN DnsMode; // // Normal session configuration parameters. @@ -370,6 +524,7 @@ IScsiConvertAttemptConfigDataToIfrNvData ( SessionConfigData = &Attempt->SessionConfigData; IfrNvData->Enabled = SessionConfigData->Enabled; IfrNvData->IpMode = SessionConfigData->IpMode; + DnsMode = SessionConfigData->DnsMode; IfrNvData->InitiatorInfoFromDhcp = SessionConfigData->InitiatorInfoFromDhcp; IfrNvData->TargetInfoFromDhcp = SessionConfigData->TargetInfoFromDhcp; @@ -382,12 +537,17 @@ IScsiConvertAttemptConfigDataToIfrNvData ( IScsiIpToStr (&Ip, FALSE, IfrNvData->SubnetMask); CopyMem (&Ip.v4, &SessionConfigData->Gateway, sizeof (EFI_IPv4_ADDRESS)); IScsiIpToStr (&Ip, FALSE, IfrNvData->Gateway); - CopyMem (&Ip.v4, &SessionConfigData->TargetIp, sizeof (EFI_IPv4_ADDRESS)); - IScsiIpToStr (&Ip, FALSE, 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)); - IP6_COPY_ADDRESS (&Ip.v6, &SessionConfigData->TargetIp); - IScsiIpToStr (&Ip, TRUE, IfrNvData->TargetIp); + if (SessionConfigData->TargetIp.v6.Addr[0] != '\0') { + IP6_COPY_ADDRESS (&Ip.v6, &SessionConfigData->TargetIp); + IScsiIpToStr (&Ip, TRUE, IfrNvData->TargetIp); + } } AsciiStrToUnicodeStrS ( @@ -395,6 +555,15 @@ IScsiConvertAttemptConfigDataToIfrNvData ( 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); @@ -441,6 +610,160 @@ IScsiConvertAttemptConfigDataToIfrNvData ( ); } +/** + Convert the iSCSI configuration data into the IFR data Which will be used + to extract the iSCSI Keyword configuration in 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); + + 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'/'; + } + } +} + /** Convert the IFR data to iSCSI configuration data. @@ -517,7 +840,7 @@ IScsiConvertIfrNvDataToAttemptConfigData ( L"Connection Establishing Timeout is less than minimum value 100ms.", NULL ); - + return EFI_INVALID_PARAMETER; } @@ -538,7 +861,7 @@ IScsiConvertIfrNvDataToAttemptConfigData ( 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 ( @@ -547,7 +870,7 @@ IScsiConvertIfrNvDataToAttemptConfigData ( L"Local IP and Gateway are not in the same subnet.", NULL ); - + return EFI_INVALID_PARAMETER; } } @@ -556,14 +879,26 @@ IScsiConvertIfrNvDataToAttemptConfigData ( // Validate target configuration if DHCP isn't deployed. // if (!Attempt->SessionConfigData.TargetInfoFromDhcp && Attempt->SessionConfigData.IpMode < IP_MODE_AUTOCONFIG) { - if (!IpIsUnicast (&Attempt->SessionConfigData.TargetIp, IfrNvData->IpMode)) { - CreatePopUp ( - EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, - &Key, - L"Target IP is invalid!", - NULL - ); - return EFI_INVALID_PARAMETER; + 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; + } } // @@ -582,7 +917,6 @@ IScsiConvertIfrNvDataToAttemptConfigData ( } } - // // Validate the authentication info. // @@ -616,26 +950,19 @@ IScsiConvertIfrNvDataToAttemptConfigData ( // SameNicAttempt = IScsiConfigGetAttemptByNic (Attempt, IfrNvData->Enabled); if (SameNicAttempt != NULL) { - AttemptName1 = (CHAR16 *) AllocateZeroPool (ATTEMPT_NAME_MAX_SIZE * sizeof (CHAR16)); + AttemptName1 = (CHAR16 *) AllocateZeroPool (ATTEMPT_NAME_SIZE * sizeof (CHAR16)); if (AttemptName1 == NULL) { return EFI_OUT_OF_RESOURCES; } - AttemptName2 = (CHAR16 *) AllocateZeroPool (ATTEMPT_NAME_MAX_SIZE * sizeof (CHAR16)); + AttemptName2 = (CHAR16 *) AllocateZeroPool (ATTEMPT_NAME_SIZE * sizeof (CHAR16)); if (AttemptName2 == NULL) { FreePool (AttemptName1); return EFI_OUT_OF_RESOURCES; } - - AsciiStrToUnicodeStrS (Attempt->AttemptName, AttemptName1, ATTEMPT_NAME_MAX_SIZE); - if (StrLen (AttemptName1) > ATTEMPT_NAME_SIZE) { - CopyMem (&AttemptName1[ATTEMPT_NAME_SIZE], L"...", 4 * sizeof (CHAR16)); - } - AsciiStrToUnicodeStrS (SameNicAttempt->AttemptName, AttemptName2, ATTEMPT_NAME_MAX_SIZE); - if (StrLen (AttemptName2) > ATTEMPT_NAME_SIZE) { - CopyMem (&AttemptName2[ATTEMPT_NAME_SIZE], L"...", 4 * sizeof (CHAR16)); - } + AsciiStrToUnicodeStrS (Attempt->AttemptName, AttemptName1, ATTEMPT_NAME_SIZE); + AsciiStrToUnicodeStrS (SameNicAttempt->AttemptName, AttemptName2, ATTEMPT_NAME_SIZE); UnicodeSPrint ( mPrivate->PortString, @@ -660,7 +987,6 @@ IScsiConvertIfrNvDataToAttemptConfigData ( // // Update the iSCSI Mode data and record it in attempt help info. // - Attempt->SessionConfigData.Enabled = IfrNvData->Enabled; if (IfrNvData->Enabled == ISCSI_DISABLED) { UnicodeSPrint (IScsiMode, 64, L"Disabled"); } else if (IfrNvData->Enabled == ISCSI_ENABLED) { @@ -687,7 +1013,7 @@ IScsiConvertIfrNvDataToAttemptConfigData ( return EFI_OUT_OF_RESOURCES; } - AsciiStrToUnicodeStrS (Attempt->MacString, MacString, sizeof (MacString) / sizeof (MacString[0])); + AsciiStrToUnicodeStrS (Attempt->MacString, MacString, ISCSI_MAX_MAC_STRING_LEN); UnicodeSPrint ( mPrivate->PortString, @@ -784,11 +1110,10 @@ IScsiConvertIfrNvDataToAttemptConfigData ( } else if (ExistAttempt == NULL) { // // When a new attempt is created, pointer of the attempt is saved to - // mPrivate->NewAttempt, and also 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. - // - ASSERT (Attempt == mPrivate->NewAttempt); + // 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. @@ -839,11 +1164,6 @@ IScsiConvertIfrNvDataToAttemptConfigData ( // InsertTailList (&mPrivate->AttemptConfigs, &Attempt->Link); mPrivate->AttemptCount++; - // - // Reset mPrivate->NewAttempt to NULL, which indicates none attempt is created - // but not saved now. - // - mPrivate->NewAttempt = NULL; if (IfrNvData->Enabled == ISCSI_ENABLED_FOR_MPIO) { // @@ -857,17 +1177,12 @@ IScsiConvertIfrNvDataToAttemptConfigData ( IScsiConfigUpdateAttempt (); } + Attempt->SessionConfigData.Enabled = IfrNvData->Enabled; // // Record the user configuration information in NVR. // - UnicodeSPrint ( - mPrivate->PortString, - (UINTN) ISCSI_NAME_IFR_MAX_SIZE, - L"%s%d", - MacString, - (UINTN) Attempt->AttemptConfigIndex - ); + UnicodeSPrint (mPrivate->PortString, (UINTN) ISCSI_NAME_IFR_MAX_SIZE, L"Attempt %d", Attempt->AttemptConfigIndex); FreePool (MacString); @@ -881,86 +1196,669 @@ IScsiConvertIfrNvDataToAttemptConfigData ( } /** - Create Hii Extend Label OpCode as the start opcode and end opcode. It is - a help function. + Convert the IFR data configured by keyword to iSCSI configuration data. - @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. + @param[in] IfrNvData Point to ISCSI_CONFIG_IFR_NVDATA. + @param[in] OffSet The offset of the variable to the configuration structure. - @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_INVALID_PARAMETER Any input or configured 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 +IScsiConvertlfrNvDataToAttemptConfigDataByKeyword ( + IN ISCSI_CONFIG_IFR_NVDATA *IfrNvData, + IN UINTN OffSet ) { - EFI_STATUS Status; - EFI_IFR_GUID_LABEL *InternalStartLabel; - EFI_IFR_GUID_LABEL *InternalEndLabel; + 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; - if (StartOpCodeHandle == NULL || StartLabel == NULL || EndOpCodeHandle == NULL || EndLabel == NULL) { - return EFI_INVALID_PARAMETER; - } + Attempt = NULL; + ZeroMem (IScsiName, sizeof (IScsiName)); - *StartOpCodeHandle = NULL; - *EndOpCodeHandle = NULL; - Status = EFI_OUT_OF_RESOURCES; + if (OffSet < ATTEMPT_BOOTENABLE_VAR_OFFSET) { + return EFI_SUCCESS; - // - // Initialize the container for dynamic opcodes. - // - *StartOpCodeHandle = HiiAllocateOpCodeHandle (); - if (*StartOpCodeHandle == NULL) { - return Status; - } + } 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; + } - *EndOpCodeHandle = HiiAllocateOpCodeHandle (); - if (*EndOpCodeHandle == NULL) { - goto Exit; - } + AttemptName2 = (CHAR16 *) AllocateZeroPool (ATTEMPT_NAME_SIZE * sizeof (CHAR16)); + if (AttemptName2 == NULL) { + FreePool (AttemptName1); + return EFI_OUT_OF_RESOURCES; + } - // - // 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; + AsciiStrToUnicodeStrS (Attempt->AttemptName, AttemptName1, ATTEMPT_NAME_SIZE); + AsciiStrToUnicodeStrS (SameNicAttempt->AttemptName, AttemptName2, ATTEMPT_NAME_SIZE); - // - // 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; - } + UnicodeSPrint ( + mPrivate->PortString, + (UINTN) ISCSI_NAME_IFR_MAX_SIZE, + L"Warning! \"%s\" uses same NIC as Attempt \"%s\".", + AttemptName1, + AttemptName2 + ); - InternalEndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; - InternalEndLabel->Number = LABEL_END; + 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; @@ -976,10 +1874,77 @@ Exit: 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". @@ -1078,76 +2043,184 @@ Exit: return Status; } - /** - Update the MAIN form to display the configured attempts. + 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. **/ -VOID -IScsiConfigUpdateAttempt ( - VOID +EFI_STATUS +IScsiConfigAddAttemptsByKeywords ( + IN UINT8 *AttemptList ) { - CHAR16 AttemptName[ATTEMPT_NAME_MAX_SIZE]; - 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; + 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; - Status = IScsiCreateOpCode ( - ATTEMPT_ENTRY_LABEL, - &StartOpCodeHandle, - &StartLabel, - &EndOpCodeHandle, - &EndLabel - ); - if (EFI_ERROR (Status)) { - return ; + Nic = mPrivate->CurrentNic; + NicInfo = IScsiGetNicInfoByIndex (Nic); + if (NicInfo == NULL) { + return EFI_NOT_FOUND; } - NET_LIST_FOR_EACH (Entry, &mPrivate->AttemptConfigs) { - AttemptConfigData = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link); + // + // The MAC info will be recorded in Config Data. + // + IScsiMacAddrToStr ( + &NicInfo->PermanentAddress, + NicInfo->HwAddressSize, + NicInfo->VlanId, + MacString + ); - AsciiStrToUnicodeStrS (AttemptConfigData->AttemptName, AttemptName, sizeof (AttemptName) / sizeof (AttemptName[0])); - UnicodeSPrint (mPrivate->PortString, (UINTN) 128, L"Attempt %s", AttemptName); - AttemptConfigData->AttemptTitleToken = HiiSetString ( - mCallbackInfo->RegisteredHandle, - 0, - mPrivate->PortString, - NULL - ); - if (AttemptConfigData->AttemptTitleToken == 0) { - return ; + for (Index = 0; Index < PcdGet8 (PcdMaxIScsiAttemptNumber); Index++) { + if (AttemptList[Index] == 0) { + continue; } - 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 + // + // Add the attempt. + // + Number = AttemptList[Index]; + + UnicodeSPrint ( + mPrivate->PortString, + (UINTN) ISCSI_NAME_IFR_MAX_SIZE, + L"Attempt %d", + Number ); - } - HiiUpdateForm ( - mCallbackInfo->RegisteredHandle, // HII handle - &gIScsiConfigGuid, // Formset GUID - FORMID_MAIN_FORM, // Form ID - StartOpCodeHandle, // Label for where to insert opcodes - EndOpCodeHandle // Replace data - ); + GetVariable2 ( + mPrivate->PortString, + &gEfiIScsiInitiatorNameProtocolGuid, + (VOID**)&AttemptConfigData, + NULL + ); + if (AttemptConfigData == NULL || AttemptConfigData->Actived == ISCSI_ACTIVE_ENABLED) { + return EFI_INVALID_PARAMETER; + } - HiiFreeOpCodeHandle (StartOpCodeHandle); - HiiFreeOpCodeHandle (EndOpCodeHandle); + 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. + Callback function when user presses "Commit Changes and Exit" in Delete Attempts or Delete Attempts by Keyword. @param[in] IfrNvData The IFR NV data. @@ -1164,19 +2237,22 @@ 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; - UINT32 Attribute; - UINTN Total; - UINTN NewTotal; - LIST_ENTRY *Entry; - LIST_ENTRY *NextEntry; - CHAR16 MacString[ISCSI_MAX_MAC_STRING_LEN]; + 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", @@ -1195,7 +2271,6 @@ IScsiConfigDeleteAttempts ( Total = AttemptConfigOrderSize / sizeof (UINT8); NewTotal = Total; - Index = 0; NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &mPrivate->AttemptConfigs) { if (IfrNvData->DeleteAttemptList[Index] == 0) { @@ -1240,22 +2315,44 @@ IScsiConfigDeleteAttempts ( mPrivate->SinglePathCount--; } - AsciiStrToUnicodeStrS (AttemptConfigData->MacString, MacString, sizeof (MacString) / sizeof (MacString[0])); + 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) 128, - L"%s%d", - MacString, + (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, - 0, - 0, - NULL + ISCSI_CONFIG_VAR_ATTR, + sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA), + AttemptConfigData ); // @@ -1269,6 +2366,9 @@ IScsiConfigDeleteAttempts ( } NewTotal--; + if (mCallbackInfo->Current == AttemptConfigData) { + mCallbackInfo->Current = NULL; + } FreePool (AttemptConfigData); // @@ -1308,7 +2408,7 @@ Error: if (AttemptNewOrder != NULL) { FreePool (AttemptNewOrder); } - + return Status; } @@ -1507,9 +2607,8 @@ Error: return Status; } - /** - Callback function when user presses "Commit Changes and Exit" in Change Attempt Order. + 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. @@ -1625,6 +2724,7 @@ Exit: @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. **/ @@ -1636,16 +2736,16 @@ IScsiConfigProcessDefault ( { BOOLEAN NewAttempt; ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData; - ISCSI_SESSION_CONFIG_NVDATA *ConfigData; UINT8 CurrentAttemptConfigIndex; ISCSI_NIC_INFO *NicInfo; UINT8 NicIndex; CHAR16 MacString[ISCSI_MAX_MAC_STRING_LEN]; UINT8 *AttemptConfigOrder; UINTN AttemptConfigOrderSize; - UINTN TotalNumber; UINTN Index; + EFI_INPUT_KEY Key; + AttemptConfigData = NULL; // // Is User creating a new attempt? // @@ -1670,14 +2770,6 @@ IScsiConfigProcessDefault ( // return EFI_SUCCESS; } - - // - // Free any attempt that is previously created but not saved to system. - // - if (mPrivate->NewAttempt != NULL) { - FreePool (mPrivate->NewAttempt); - mPrivate->NewAttempt = NULL; - } if (NewAttempt) { // @@ -1688,57 +2780,49 @@ IScsiConfigProcessDefault ( if (NicInfo == NULL) { return EFI_NOT_FOUND; } - - // - // Create new attempt. - // - - AttemptConfigData = AllocateZeroPool (sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA)); - if (AttemptConfigData == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - ConfigData = &AttemptConfigData->SessionConfigData; - ConfigData->TargetPort = ISCSI_WELL_KNOWN_PORT; - ConfigData->ConnectTimeout = CONNECT_DEFAULT_TIMEOUT; - ConfigData->ConnectRetryCount = CONNECT_MIN_RETRY; - - AttemptConfigData->AuthenticationType = ISCSI_AUTH_TYPE_CHAP; - AttemptConfigData->AuthConfigData.CHAP.CHAPType = ISCSI_CHAP_UNI; // - // Get current order number for this attempt. + // Create an attempt following the initialized attempt order. // AttemptConfigOrder = IScsiGetVariableAndSize ( - L"AttemptOrder", + L"InitialAttemptOrder", &gIScsiConfigGuid, &AttemptConfigOrderSize ); - TotalNumber = AttemptConfigOrderSize / sizeof (UINT8); - if (AttemptConfigOrder == NULL) { - CurrentAttemptConfigIndex = 1; - } else { - // - // Get the max attempt config index. - // - CurrentAttemptConfigIndex = AttemptConfigOrder[0]; - for (Index = 1; Index < TotalNumber; Index++) { - if (CurrentAttemptConfigIndex < AttemptConfigOrder[Index]) { - CurrentAttemptConfigIndex = AttemptConfigOrder[Index]; - } - } - - CurrentAttemptConfigIndex++; + return EFI_NOT_FOUND; } - TotalNumber++; - - // - // Record the mapping between attempt order and attempt's configdata. - // - AttemptConfigData->AttemptConfigIndex = CurrentAttemptConfigIndex; + 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); @@ -1754,8 +2838,10 @@ IScsiConfigProcessDefault ( 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. @@ -1785,27 +2871,9 @@ IScsiConfigProcessDefault ( ); if (AttemptConfigData->AttemptTitleHelpToken == 0) { FreePool (AttemptConfigData); - return EFI_INVALID_PARAMETER; + return EFI_OUT_OF_RESOURCES; } - // - // Set the attempt name to default. - // - UnicodeSPrint ( - mPrivate->PortString, - (UINTN) 128, - L"%d", - (UINTN) AttemptConfigData->AttemptConfigIndex - ); - UnicodeStrToAsciiStrS (mPrivate->PortString, AttemptConfigData->AttemptName, sizeof (AttemptConfigData->AttemptName)); - - // - // Save the created Attempt temporarily. If user does not save the attempt - // by press 'KEY_SAVE_ATTEMPT_CONFIG' later, iSCSI driver would know that - // and free resources. - // - mPrivate->NewAttempt = (VOID *) AttemptConfigData; - } else { // // Determine which Attempt user has selected to configure. @@ -1950,11 +3018,17 @@ IScsiFormExtractConfig ( if (IfrNvData == NULL) { return EFI_OUT_OF_RESOURCES; } - - if (Private->Current != NULL) { + + + if (Private->Current!= NULL) { IScsiConvertAttemptConfigDataToIfrNvData (Private->Current, IfrNvData); } + // + // Extract all AttemptConfigData to Keyword stroage of IfrNvData. + // + IScsiConvertAttemptConfigDataToIfrNvDataByKeyword (IfrNvData); + BufferSize = ISCSI_NAME_MAX_SIZE; InitiatorName = (CHAR8 *) AllocateZeroPool (BufferSize); if (InitiatorName == NULL) { @@ -1987,7 +3061,11 @@ IScsiFormExtractConfig ( ConfigRequestHdr = HiiConstructConfigHdr (&gIScsiConfigGuid, mVendorStorageName, Private->DriverHandle); Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16); ConfigRequest = AllocateZeroPool (Size); - ASSERT (ConfigRequest != NULL); + 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); @@ -2072,6 +3150,27 @@ IScsiFormRouteConfig ( 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; } @@ -2085,10 +3184,183 @@ IScsiFormRouteConfig ( return EFI_NOT_FOUND; } - *Progress = Configuration + StrLen (Configuration); - return EFI_SUCCESS; -} + 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 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; +} /** @@ -2129,7 +3401,7 @@ IScsiFormCallback ( ISCSI_FORM_CALLBACK_INFO *Private; UINTN BufferSize; CHAR8 *IScsiName; - CHAR8 IpString[IP_STR_MAX_SIZE]; + CHAR8 IpString[ISCSI_NAME_MAX_SIZE]; CHAR8 LunString[ISCSI_LUN_STR_MAX_LEN]; UINT64 Lun; EFI_IP_ADDRESS HostIp; @@ -2138,7 +3410,6 @@ IScsiFormCallback ( ISCSI_CONFIG_IFR_NVDATA *IfrNvData; ISCSI_CONFIG_IFR_NVDATA OldIfrNvData; EFI_STATUS Status; - CHAR16 AttemptName[ATTEMPT_NAME_SIZE + 4]; EFI_INPUT_KEY Key; if ((Action == EFI_BROWSER_ACTION_FORM_OPEN) || (Action == EFI_BROWSER_ACTION_FORM_CLOSE)) { @@ -2251,24 +3522,6 @@ IScsiFormCallback ( ); } - *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY; - break; - case KEY_ATTEMPT_NAME: - if (StrLen (IfrNvData->AttemptName) > ATTEMPT_NAME_SIZE) { - CopyMem (AttemptName, IfrNvData->AttemptName, ATTEMPT_NAME_SIZE * sizeof (CHAR16)); - CopyMem (&AttemptName[ATTEMPT_NAME_SIZE], L"...", 4 * sizeof (CHAR16)); - } else { - CopyMem ( - AttemptName, - IfrNvData->AttemptName, - (StrLen (IfrNvData->AttemptName) + 1) * sizeof (CHAR16) - ); - } - - UnicodeStrToAsciiStrS (IfrNvData->AttemptName, Private->Current->AttemptName, sizeof (Private->Current->AttemptName)); - - IScsiConfigUpdateAttempt (); - *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY; break; @@ -2278,7 +3531,7 @@ IScsiFormCallback ( break; } - *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY; + *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT; break; case KEY_SAVE_ORDER_CHANGES: @@ -2328,14 +3581,8 @@ IScsiFormCallback ( case KEY_IP_MODE: switch (Value->u8) { case IP_MODE_IP6: - ZeroMem (IfrNvData->TargetIp, sizeof (IfrNvData->TargetIp)); - IScsiIpToStr (&Private->Current->SessionConfigData.TargetIp, TRUE, IfrNvData->TargetIp); - Private->Current->AutoConfigureMode = 0; - break; - case IP_MODE_IP4: ZeroMem (IfrNvData->TargetIp, sizeof (IfrNvData->TargetIp)); - IScsiIpToStr (&Private->Current->SessionConfigData.TargetIp, FALSE, IfrNvData->TargetIp); Private->Current->AutoConfigureMode = 0; break; @@ -2345,7 +3592,9 @@ IScsiFormCallback ( case KEY_LOCAL_IP: Status = NetLibStrToIp4 (IfrNvData->LocalIp, &HostIp.v4); - if (EFI_ERROR (Status) || !NetIp4IsUnicast (NTOHL (HostIp.Addr[0]), 0)) { + 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, @@ -2379,7 +3628,10 @@ IScsiFormCallback ( case KEY_GATE_WAY: Status = NetLibStrToIp4 (IfrNvData->Gateway, &Gateway.v4); - if (EFI_ERROR (Status) || ((Gateway.Addr[0] != 0) && !NetIp4IsUnicast (NTOHL (Gateway.Addr[0]), 0))) { + 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, @@ -2397,14 +3649,14 @@ IScsiFormCallback ( UnicodeStrToAsciiStrS (IfrNvData->TargetIp, IpString, sizeof (IpString)); Status = IScsiAsciiStrToIp (IpString, IfrNvData->IpMode, &HostIp); if (EFI_ERROR (Status) || !IpIsUnicast (&HostIp, IfrNvData->IpMode)) { - CreatePopUp ( - EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, - &Key, - L"Invalid IP address!", - NULL - ); - Status = EFI_INVALID_PARAMETER; + // + // 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)); } @@ -2628,13 +3880,6 @@ IScsiConfigFormUnload ( ASSERT (mPrivate->NicCount == 0); - // - // Free attempt is created but not saved to system. - // - if (mPrivate->NewAttempt != NULL) { - FreePool (mPrivate->NewAttempt); - } - FreePool (mPrivate); mPrivate = NULL;