mirror of https://github.com/acidanthera/audk.git
3917 lines
129 KiB
C
3917 lines
129 KiB
C
/** @file
|
|
Helper functions for configuring or getting the parameters relating to iSCSI.
|
|
|
|
Copyright (c) 2004 - 2017, Intel Corporation. All rights reserved.<BR>
|
|
This program and the accompanying materials
|
|
are licensed and made available under the terms and conditions of the BSD License
|
|
which accompanies this distribution. The full text of the license may be found at
|
|
http://opensource.org/licenses/bsd-license.php
|
|
|
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|
|
|
**/
|
|
|
|
#include "IScsiImpl.h"
|
|
|
|
CHAR16 mVendorStorageName[] = L"ISCSI_CONFIG_IFR_NVDATA";
|
|
BOOLEAN mIScsiDeviceListUpdated = FALSE;
|
|
UINTN mNumberOfIScsiDevices = 0;
|
|
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 neccessary
|
|
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);
|
|
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_ABOTRED 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);
|
|
if (AttemptConfigData == NULL) {
|
|
Status = EFI_NOT_FOUND;
|
|
goto Error;
|
|
}
|
|
|
|
//
|
|
// 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 stroage 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;
|
|
|
|
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:
|
|
case IP_MODE_IP4:
|
|
ZeroMem (IfrNvData->TargetIp, sizeof (IfrNvData->TargetIp));
|
|
Private->Current->AutoConfigureMode = 0;
|
|
|
|
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;
|
|
}
|