2 Helper functions for configuring or getting the parameters relating to iSCSI.
4 Copyright (c) 2004 - 2017, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "IScsiImpl.h"
17 CHAR16 mVendorStorageName
[] = L
"ISCSI_CONFIG_IFR_NVDATA";
18 BOOLEAN mIScsiDeviceListUpdated
= FALSE
;
19 UINTN mNumberOfIScsiDevices
= 0;
20 ISCSI_FORM_CALLBACK_INFO
*mCallbackInfo
= NULL
;
22 HII_VENDOR_DEVICE_PATH mIScsiHiiVendorDevicePath
= {
28 (UINT8
) (sizeof (VENDOR_DEVICE_PATH
)),
29 (UINT8
) ((sizeof (VENDOR_DEVICE_PATH
)) >> 8)
36 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
38 (UINT8
) (END_DEVICE_PATH_LENGTH
),
39 (UINT8
) ((END_DEVICE_PATH_LENGTH
) >> 8)
46 Convert the IP address into a dotted string.
48 @param[in] Ip The IP address.
49 @param[in] Ipv6Flag Indicates whether the IP address is version 4 or version 6.
50 @param[out] Str The formatted IP string.
55 IN EFI_IP_ADDRESS
*Ip
,
60 EFI_IPv4_ADDRESS
*Ip4
;
61 EFI_IPv6_ADDRESS
*Ip6
;
65 CHAR16 FormatString
[8];
72 (UINTN
) 2 * IP4_STR_MAX_SIZE
,
86 for (Index
= 0; Index
< 15; Index
= Index
+ 2) {
89 Ip6
->Addr
[Index
] == 0 &&
90 Ip6
->Addr
[Index
+ 1] == 0
93 // Deal with the case of ::.
104 while ((Index
< 15) && (Ip6
->Addr
[Index
] == 0) && (Ip6
->Addr
[Index
+ 1] == 0)) {
112 // :: is at the end of the address.
121 if (Ip6
->Addr
[Index
] == 0) {
122 Number
= UnicodeSPrint (Str
, 2 * IP_STR_MAX_SIZE
, L
"%x:", (UINTN
) Ip6
->Addr
[Index
+ 1]);
124 if (Ip6
->Addr
[Index
+ 1] < 0x10) {
125 CopyMem (FormatString
, L
"%x0%x:", StrSize (L
"%x0%x:"));
127 CopyMem (FormatString
, L
"%x%x:", StrSize (L
"%x%x:"));
130 Number
= UnicodeSPrint (
133 (CONST CHAR16
*) FormatString
,
134 (UINTN
) Ip6
->Addr
[Index
],
135 (UINTN
) Ip6
->Addr
[Index
+ 1]
141 if (Index
+ 2 == 16) {
143 if (*(Str
- 1) == L
':') {
151 Check whether the input IP address is valid.
153 @param[in] Ip The IP address.
154 @param[in] IpMode Indicates iSCSI running on IP4 or IP6 stack.
156 @retval TRUE The input IP address is valid.
157 @retval FALSE Otherwise
162 IN EFI_IP_ADDRESS
*Ip
,
166 if (IpMode
== IP_MODE_IP4
) {
167 if (IP4_IS_UNSPECIFIED (NTOHL (Ip
->Addr
[0])) || IP4_IS_LOCAL_BROADCAST (NTOHL (Ip
->Addr
[0]))) {
171 } else if (IpMode
== IP_MODE_IP6
) {
172 return NetIp6IsValidUnicast (&Ip
->v6
);
174 DEBUG ((DEBUG_ERROR
, "IpMode %d is invalid when configuring the iSCSI target IP!\n", IpMode
));
180 Parse IsId in string format and convert it to binary.
182 @param[in] String The buffer of the string to be parsed.
183 @param[in, out] IsId The buffer to store IsId.
185 @retval EFI_SUCCESS The operation finished successfully.
186 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
190 IScsiParseIsIdFromString (
191 IN CONST CHAR16
*String
,
199 CHAR16 PortString
[ISCSI_NAME_IFR_MAX_SIZE
];
202 if ((String
== NULL
) || (IsId
== NULL
)) {
203 return EFI_INVALID_PARAMETER
;
206 IsIdStr
= (CHAR16
*) String
;
208 if (StrLen (IsIdStr
) != 6 && StrLen (IsIdStr
) != 12) {
211 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
212 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"
216 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
222 return EFI_INVALID_PARAMETER
;
225 if (StrLen (IsIdStr
) == 12) {
229 for (Index
= 3; Index
< 6; Index
++) {
230 CopyMem (TempStr
, IsIdStr
, sizeof (TempStr
));
234 // Convert the string to IsId. StrHexToUintn stops at the first character
235 // that is not a valid hex character, '\0' here.
237 NodeVal
= StrHexToUintn (TempStr
);
239 IsId
[Index
] = (UINT8
) NodeVal
;
241 IsIdStr
= IsIdStr
+ 2;
248 Convert IsId from binary to string format.
250 @param[out] String The buffer to store the converted string.
251 @param[in] IsId The buffer to store IsId.
253 @retval EFI_SUCCESS The string converted successfully.
254 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
258 IScsiConvertIsIdToString (
266 if ((String
== NULL
) || (IsId
== NULL
)) {
267 return EFI_INVALID_PARAMETER
;
270 for (Index
= 0; Index
< 6; Index
++) {
271 if (IsId
[Index
] <= 0xF) {
272 Number
= UnicodeSPrint (
274 2 * ISID_CONFIGURABLE_STORAGE
,
279 Number
= UnicodeSPrint (
281 2 * ISID_CONFIGURABLE_STORAGE
,
288 String
= String
+ Number
;
297 Get the Offset value specified by the input String.
299 @param[in] Configuration A null-terminated Unicode string in
300 <ConfigString> format.
301 @param[in] String The string is "&OFFSET=".
302 @param[out] Value The Offset value.
304 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary
306 @retval EFI_SUCCESS Value of <Number> is outputted in Number
312 IN CONST EFI_STRING Configuration
,
332 StringPtr
= StrStr (Configuration
, String
);
333 ASSERT(StringPtr
!= NULL
);
334 StringPtr
+= StrLen (String
);
337 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
340 Length
= StringPtr
- TmpPtr
;
343 Str
= AllocateZeroPool (Len
* sizeof (CHAR16
));
345 Status
= EFI_OUT_OF_RESOURCES
;
349 CopyMem (Str
, TmpPtr
, Len
* sizeof (CHAR16
));
350 *(Str
+ Length
) = L
'\0';
353 Buf
= (UINT8
*) AllocateZeroPool (Len
);
355 Status
= EFI_OUT_OF_RESOURCES
;
359 ZeroMem (TmpStr
, sizeof (TmpStr
));
360 for (Index
= 0; Index
< Length
; Index
++) {
361 TmpStr
[0] = Str
[Length
- Index
- 1];
362 DigitUint8
= (UINT8
) StrHexToUint64 (TmpStr
);
363 if ((Index
& 1) == 0) {
364 Buf
[Index
/2] = DigitUint8
;
366 Buf
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Buf
[Index
/2]);
374 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
378 Status
= EFI_SUCCESS
;
389 Get the attempt config data from global structure by the ConfigIndex.
391 @param[in] AttemptConfigIndex The unique index indicates the attempt.
393 @return Pointer to the attempt config data.
394 @retval NULL The attempt configuration data cannot be found.
397 ISCSI_ATTEMPT_CONFIG_NVDATA
*
398 IScsiConfigGetAttemptByConfigIndex (
399 IN UINT8 AttemptConfigIndex
403 ISCSI_ATTEMPT_CONFIG_NVDATA
*Attempt
;
405 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
406 Attempt
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
407 if (Attempt
->AttemptConfigIndex
== AttemptConfigIndex
) {
417 Get the existing attempt config data from global structure by the NicIndex.
419 @param[in] NewAttempt The created new attempt
420 @param[in] IScsiMode The IScsi Mode of the new attempt, Enabled or
423 @return Pointer to the existing attempt config data which
424 has the same NICIndex as the new created attempt.
425 @retval NULL The attempt with NicIndex does not exist.
428 ISCSI_ATTEMPT_CONFIG_NVDATA
*
429 IScsiConfigGetAttemptByNic (
430 IN ISCSI_ATTEMPT_CONFIG_NVDATA
*NewAttempt
,
435 ISCSI_ATTEMPT_CONFIG_NVDATA
*Attempt
;
437 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
438 Attempt
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
439 if (Attempt
!= NewAttempt
&& Attempt
->NicIndex
== NewAttempt
->NicIndex
&&
440 Attempt
->SessionConfigData
.Enabled
== IScsiMode
) {
449 Extract the Index of the attempt list.
451 @param[in] AttemptNameList The Name list of the Attempts.
452 @param[out] AttemptIndexList The Index list of the Attempts.
453 @param[in] IsAddAttempts If TRUE, Indicates add one or more attempts.
454 If FALSE, Indicates delete attempts or change attempt order.
456 @retval EFI_SUCCESS The Attempt list is valid.
457 @retval EFI_INVALID_PARAMETERS The Attempt List is invalid.
461 IScsiGetAttemptIndexList (
462 IN CHAR16
*AttemptNameList
,
463 OUT UINT8
*AttemptIndexList
,
464 IN BOOLEAN IsAddAttempts
467 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
475 if ((AttemptNameList
== NULL
) || (*AttemptNameList
== L
'\0')) {
476 return EFI_INVALID_PARAMETER
;
479 AttemptStr
= AttemptNameList
;
480 Len
= StrLen (L
"attempt:");
482 while (*AttemptStr
!= L
'\0') {
483 AttemptStr
= StrStr (AttemptStr
, L
"attempt:");
484 if (AttemptStr
== NULL
) {
485 return EFI_INVALID_PARAMETER
;
488 AttemptIndex
= (UINT8
)(*AttemptStr
- L
'0');
489 AttemptConfigData
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
491 if ((AttemptConfigData
!= NULL
) || ((AttemptIndex
) > PcdGet8 (PcdMaxIScsiAttemptNumber
))) {
492 return EFI_INVALID_PARAMETER
;
495 if (AttemptConfigData
== NULL
) {
496 return EFI_INVALID_PARAMETER
;
500 AttemptIndexList
[Index
] = AttemptIndex
;
508 Convert the iSCSI configuration data into the IFR data.
510 @param[in] Attempt The iSCSI attempt config data.
511 @param[in, out] IfrNvData The IFR nv data.
515 IScsiConvertAttemptConfigDataToIfrNvData (
516 IN ISCSI_ATTEMPT_CONFIG_NVDATA
*Attempt
,
517 IN OUT ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
520 ISCSI_SESSION_CONFIG_NVDATA
*SessionConfigData
;
521 ISCSI_CHAP_AUTH_CONFIG_NVDATA
*AuthConfigData
;
526 // Normal session configuration parameters.
528 SessionConfigData
= &Attempt
->SessionConfigData
;
529 IfrNvData
->Enabled
= SessionConfigData
->Enabled
;
530 IfrNvData
->IpMode
= SessionConfigData
->IpMode
;
531 DnsMode
= SessionConfigData
->DnsMode
;
533 IfrNvData
->InitiatorInfoFromDhcp
= SessionConfigData
->InitiatorInfoFromDhcp
;
534 IfrNvData
->TargetInfoFromDhcp
= SessionConfigData
->TargetInfoFromDhcp
;
535 IfrNvData
->TargetPort
= SessionConfigData
->TargetPort
;
537 if (IfrNvData
->IpMode
== IP_MODE_IP4
) {
538 CopyMem (&Ip
.v4
, &SessionConfigData
->LocalIp
, sizeof (EFI_IPv4_ADDRESS
));
539 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->LocalIp
);
540 CopyMem (&Ip
.v4
, &SessionConfigData
->SubnetMask
, sizeof (EFI_IPv4_ADDRESS
));
541 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->SubnetMask
);
542 CopyMem (&Ip
.v4
, &SessionConfigData
->Gateway
, sizeof (EFI_IPv4_ADDRESS
));
543 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->Gateway
);
544 if (SessionConfigData
->TargetIp
.v4
.Addr
[0] != '\0') {
545 CopyMem (&Ip
.v4
, &SessionConfigData
->TargetIp
, sizeof (EFI_IPv4_ADDRESS
));
546 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->TargetIp
);
549 } else if (IfrNvData
->IpMode
== IP_MODE_IP6
) {
550 ZeroMem (IfrNvData
->TargetIp
, sizeof (IfrNvData
->TargetIp
));
551 if (SessionConfigData
->TargetIp
.v6
.Addr
[0] != '\0') {
552 IP6_COPY_ADDRESS (&Ip
.v6
, &SessionConfigData
->TargetIp
);
553 IScsiIpToStr (&Ip
, TRUE
, IfrNvData
->TargetIp
);
557 AsciiStrToUnicodeStrS (
558 SessionConfigData
->TargetName
,
559 IfrNvData
->TargetName
,
560 sizeof (IfrNvData
->TargetName
) / sizeof (IfrNvData
->TargetName
[0])
564 AsciiStrToUnicodeStrS (
565 SessionConfigData
->TargetUrl
,
567 sizeof (IfrNvData
->TargetIp
) / sizeof (IfrNvData
->TargetIp
[0])
571 IScsiLunToUnicodeStr (SessionConfigData
->BootLun
, IfrNvData
->BootLun
);
572 IScsiConvertIsIdToString (IfrNvData
->IsId
, SessionConfigData
->IsId
);
574 IfrNvData
->ConnectRetryCount
= SessionConfigData
->ConnectRetryCount
;
575 IfrNvData
->ConnectTimeout
= SessionConfigData
->ConnectTimeout
;
578 // Authentication parameters.
580 IfrNvData
->AuthenticationType
= Attempt
->AuthenticationType
;
582 if (IfrNvData
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
583 AuthConfigData
= &Attempt
->AuthConfigData
.CHAP
;
584 IfrNvData
->CHAPType
= AuthConfigData
->CHAPType
;
585 AsciiStrToUnicodeStrS (
586 AuthConfigData
->CHAPName
,
588 sizeof (IfrNvData
->CHAPName
) / sizeof (IfrNvData
->CHAPName
[0])
590 AsciiStrToUnicodeStrS (
591 AuthConfigData
->CHAPSecret
,
592 IfrNvData
->CHAPSecret
,
593 sizeof (IfrNvData
->CHAPSecret
) / sizeof (IfrNvData
->CHAPSecret
[0])
595 AsciiStrToUnicodeStrS (
596 AuthConfigData
->ReverseCHAPName
,
597 IfrNvData
->ReverseCHAPName
,
598 sizeof (IfrNvData
->ReverseCHAPName
) / sizeof (IfrNvData
->ReverseCHAPName
[0])
600 AsciiStrToUnicodeStrS (
601 AuthConfigData
->ReverseCHAPSecret
,
602 IfrNvData
->ReverseCHAPSecret
,
603 sizeof (IfrNvData
->ReverseCHAPSecret
) / sizeof (IfrNvData
->ReverseCHAPSecret
[0])
610 AsciiStrToUnicodeStrS (
611 Attempt
->AttemptName
,
612 IfrNvData
->AttemptName
,
613 sizeof (IfrNvData
->AttemptName
) / sizeof (IfrNvData
->AttemptName
[0])
618 Convert the iSCSI configuration data into the IFR data Which will be used
619 to extract the iSCSI Keyword configuration in <ConfigAltResp> format.
621 @param[in, out] IfrNvData The IFR nv data.
626 IScsiConvertAttemptConfigDataToIfrNvDataByKeyword (
627 IN OUT ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
631 ISCSI_ATTEMPT_CONFIG_NVDATA
*Attempt
;
632 ISCSI_SESSION_CONFIG_NVDATA
*SessionConfigData
;
633 ISCSI_CHAP_AUTH_CONFIG_NVDATA
*AuthConfigData
;
634 CHAR16 AttemptNameList
[ATTEMPT_NAME_LIST_SIZE
];
635 ISCSI_NIC_INFO
*NicInfo
;
636 CHAR16 MacString
[ISCSI_MAX_MAC_STRING_LEN
];
642 ZeroMem (AttemptNameList
, sizeof (AttemptNameList
));
644 if ((mPrivate
!= NULL
) && (mPrivate
->AttemptCount
!= 0)) {
645 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
646 Attempt
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
648 // Normal session configuration parameters.
650 SessionConfigData
= &Attempt
->SessionConfigData
;
652 ASSERT ((Attempt
->AttemptConfigIndex
> 0) && (Attempt
->AttemptConfigIndex
<= FixedPcdGet8 (PcdMaxIScsiAttemptNumber
)));
653 Index
= Attempt
->AttemptConfigIndex
- 1;
656 // Save the attempt to AttemptNameList as Attempt:1 Attempt:2
658 AsciiStrToUnicodeStrS (
659 Attempt
->AttemptName
,
660 AttemptNameList
+ StrLen (AttemptNameList
),
661 ATTEMPT_NAME_LIST_SIZE
- StrLen (AttemptNameList
)
664 StringLen
= StrLen (AttemptNameList
);
665 ASSERT (StringLen
> 2);
666 *(AttemptNameList
+ StringLen
- 2) = L
':';
667 *(AttemptNameList
+ StringLen
) = L
' ';
669 AsciiStrToUnicodeStrS (
670 Attempt
->AttemptName
,
671 IfrNvData
->ISCSIAttemptName
+ ATTEMPT_NAME_SIZE
* Index
,
672 ATTEMPT_NAME_LIST_SIZE
- ATTEMPT_NAME_SIZE
* Index
675 IfrNvData
->ISCSIBootEnableList
[Index
] = SessionConfigData
->Enabled
;
676 IfrNvData
->ISCSIIpAddressTypeList
[Index
] = SessionConfigData
->IpMode
;
678 IfrNvData
->ISCSIInitiatorInfoViaDHCP
[Index
] = SessionConfigData
->InitiatorInfoFromDhcp
;
679 IfrNvData
->ISCSITargetInfoViaDHCP
[Index
] = SessionConfigData
->TargetInfoFromDhcp
;
680 IfrNvData
->ISCSIConnectRetry
[Index
] = SessionConfigData
->ConnectRetryCount
;
681 IfrNvData
->ISCSIConnectTimeout
[Index
] = SessionConfigData
->ConnectTimeout
;
682 IfrNvData
->ISCSITargetTcpPort
[Index
] = SessionConfigData
->TargetPort
;
684 if (SessionConfigData
->IpMode
== IP_MODE_IP4
) {
685 CopyMem (&Ip
.v4
, &SessionConfigData
->LocalIp
, sizeof (EFI_IPv4_ADDRESS
));
686 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->Keyword
[Index
].ISCSIInitiatorIpAddress
);
687 CopyMem (&Ip
.v4
, &SessionConfigData
->SubnetMask
, sizeof (EFI_IPv4_ADDRESS
));
688 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->Keyword
[Index
].ISCSIInitiatorNetmask
);
689 CopyMem (&Ip
.v4
, &SessionConfigData
->Gateway
, sizeof (EFI_IPv4_ADDRESS
));
690 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->Keyword
[Index
].ISCSIInitiatorGateway
);
691 if (SessionConfigData
->TargetIp
.v4
.Addr
[0] != '\0') {
692 CopyMem (&Ip
.v4
, &SessionConfigData
->TargetIp
, sizeof (EFI_IPv4_ADDRESS
));
693 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->Keyword
[Index
].ISCSITargetIpAddress
);
695 } else if (SessionConfigData
->IpMode
== IP_MODE_IP6
) {
696 ZeroMem (IfrNvData
->Keyword
[Index
].ISCSITargetIpAddress
, sizeof (IfrNvData
->TargetIp
));
697 if (SessionConfigData
->TargetIp
.v6
.Addr
[0] != '\0') {
698 IP6_COPY_ADDRESS (&Ip
.v6
, &SessionConfigData
->TargetIp
);
699 IScsiIpToStr (&Ip
, TRUE
, IfrNvData
->Keyword
[Index
].ISCSITargetIpAddress
);
703 AsciiStrToUnicodeStrS (
704 SessionConfigData
->TargetName
,
705 IfrNvData
->Keyword
[Index
].ISCSITargetName
,
709 if (SessionConfigData
->DnsMode
) {
710 AsciiStrToUnicodeStrS (
711 SessionConfigData
->TargetUrl
,
712 IfrNvData
->Keyword
[Index
].ISCSITargetIpAddress
,
713 sizeof (IfrNvData
->Keyword
[Index
].ISCSITargetIpAddress
) / sizeof (IfrNvData
->Keyword
[Index
].ISCSITargetIpAddress
[0])
717 IScsiLunToUnicodeStr (SessionConfigData
->BootLun
, IfrNvData
->Keyword
[Index
].ISCSILun
);
718 IScsiConvertIsIdToString (IfrNvData
->Keyword
[Index
].ISCSIIsId
, SessionConfigData
->IsId
);
720 IfrNvData
->ISCSIAuthenticationMethod
[Index
] = Attempt
->AuthenticationType
;
722 if (Attempt
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
723 AuthConfigData
= &Attempt
->AuthConfigData
.CHAP
;
724 IfrNvData
->ISCSIChapType
[Index
] = AuthConfigData
->CHAPType
;
725 AsciiStrToUnicodeStrS (
726 AuthConfigData
->CHAPName
,
727 IfrNvData
->Keyword
[Index
].ISCSIChapUsername
,
728 ISCSI_CHAP_NAME_STORAGE
731 AsciiStrToUnicodeStrS (
732 AuthConfigData
->CHAPSecret
,
733 IfrNvData
->Keyword
[Index
].ISCSIChapSecret
,
734 ISCSI_CHAP_SECRET_STORAGE
737 AsciiStrToUnicodeStrS (
738 AuthConfigData
->ReverseCHAPName
,
739 IfrNvData
->Keyword
[Index
].ISCSIReverseChapUsername
,
740 ISCSI_CHAP_NAME_STORAGE
743 AsciiStrToUnicodeStrS (
744 AuthConfigData
->ReverseCHAPSecret
,
745 IfrNvData
->Keyword
[Index
].ISCSIReverseChapSecret
,
746 ISCSI_CHAP_SECRET_STORAGE
750 CopyMem(IfrNvData
->ISCSIDisplayAttemptList
, AttemptNameList
, ATTEMPT_NAME_LIST_SIZE
);
752 ZeroMem (IfrNvData
->ISCSIMacAddr
, sizeof (IfrNvData
->ISCSIMacAddr
));
753 NET_LIST_FOR_EACH (Entry
, &mPrivate
->NicInfoList
) {
754 NicInfo
= NET_LIST_USER_STRUCT (Entry
, ISCSI_NIC_INFO
, Link
);
756 &NicInfo
->PermanentAddress
,
757 NicInfo
->HwAddressSize
,
762 IfrNvData
->ISCSIMacAddr
+ StrLen (IfrNvData
->ISCSIMacAddr
),
764 StrLen (MacString
) * sizeof (CHAR16
)
767 *(IfrNvData
->ISCSIMacAddr
+ StrLen (IfrNvData
->ISCSIMacAddr
)) = L
'/';
769 if (StrLen (IfrNvData
->ISCSIMacAddr
) != 0) {
770 *(IfrNvData
->ISCSIMacAddr
+ StrLen (IfrNvData
->ISCSIMacAddr
) - 1) = L
'\0';
776 Convert the IFR data to iSCSI configuration data.
778 @param[in] IfrNvData Point to ISCSI_CONFIG_IFR_NVDATA.
779 @param[in, out] Attempt The iSCSI attempt config data.
781 @retval EFI_INVALID_PARAMETER Any input or configured parameter is invalid.
782 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
783 @retval EFI_OUT_OF_RESOURCES The operation is failed due to lack of resources.
784 @retval EFI_ABORTED The operation is aborted.
785 @retval EFI_SUCCESS The operation is completed successfully.
789 IScsiConvertIfrNvDataToAttemptConfigData (
790 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
,
791 IN OUT ISCSI_ATTEMPT_CONFIG_NVDATA
*Attempt
794 EFI_IP_ADDRESS HostIp
;
795 EFI_IP_ADDRESS SubnetMask
;
796 EFI_IP_ADDRESS Gateway
;
798 CHAR16
*AttemptName1
;
799 CHAR16
*AttemptName2
;
800 ISCSI_ATTEMPT_CONFIG_NVDATA
*ExistAttempt
;
801 ISCSI_ATTEMPT_CONFIG_NVDATA
*SameNicAttempt
;
802 CHAR16 IScsiMode
[64];
804 ISCSI_NIC_INFO
*NicInfo
;
806 UINT8
*AttemptConfigOrder
;
807 UINTN AttemptConfigOrderSize
;
808 UINT8
*AttemptOrderTmp
;
812 if (IfrNvData
== NULL
|| Attempt
== NULL
) {
813 return EFI_INVALID_PARAMETER
;
817 // Update those fields which don't have INTERACTIVE attribute.
819 Attempt
->SessionConfigData
.ConnectRetryCount
= IfrNvData
->ConnectRetryCount
;
820 Attempt
->SessionConfigData
.ConnectTimeout
= IfrNvData
->ConnectTimeout
;
821 Attempt
->SessionConfigData
.IpMode
= IfrNvData
->IpMode
;
823 if (IfrNvData
->IpMode
< IP_MODE_AUTOCONFIG
) {
824 Attempt
->SessionConfigData
.InitiatorInfoFromDhcp
= IfrNvData
->InitiatorInfoFromDhcp
;
825 Attempt
->SessionConfigData
.TargetPort
= IfrNvData
->TargetPort
;
827 if (Attempt
->SessionConfigData
.TargetPort
== 0) {
828 Attempt
->SessionConfigData
.TargetPort
= ISCSI_WELL_KNOWN_PORT
;
831 Attempt
->SessionConfigData
.TargetInfoFromDhcp
= IfrNvData
->TargetInfoFromDhcp
;
834 Attempt
->AuthenticationType
= IfrNvData
->AuthenticationType
;
836 if (Attempt
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
837 Attempt
->AuthConfigData
.CHAP
.CHAPType
= IfrNvData
->CHAPType
;
841 // Only do full parameter validation if iSCSI is enabled on this device.
843 if (IfrNvData
->Enabled
!= ISCSI_DISABLED
) {
844 if (Attempt
->SessionConfigData
.ConnectTimeout
< CONNECT_MIN_TIMEOUT
) {
846 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
848 L
"Connection Establishing Timeout is less than minimum value 100ms.",
852 return EFI_INVALID_PARAMETER
;
856 // Validate the address configuration of the Initiator if DHCP isn't
859 if (!Attempt
->SessionConfigData
.InitiatorInfoFromDhcp
) {
860 CopyMem (&HostIp
.v4
, &Attempt
->SessionConfigData
.LocalIp
, sizeof (HostIp
.v4
));
861 CopyMem (&SubnetMask
.v4
, &Attempt
->SessionConfigData
.SubnetMask
, sizeof (SubnetMask
.v4
));
862 CopyMem (&Gateway
.v4
, &Attempt
->SessionConfigData
.Gateway
, sizeof (Gateway
.v4
));
864 if ((Gateway
.Addr
[0] != 0)) {
865 if (SubnetMask
.Addr
[0] == 0) {
867 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
869 L
"Gateway address is set but subnet mask is zero.",
873 return EFI_INVALID_PARAMETER
;
874 } else if (!IP4_NET_EQUAL (HostIp
.Addr
[0], Gateway
.Addr
[0], SubnetMask
.Addr
[0])) {
876 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
878 L
"Local IP and Gateway are not in the same subnet.",
882 return EFI_INVALID_PARAMETER
;
887 // Validate target configuration if DHCP isn't deployed.
889 if (!Attempt
->SessionConfigData
.TargetInfoFromDhcp
&& Attempt
->SessionConfigData
.IpMode
< IP_MODE_AUTOCONFIG
) {
890 if (!Attempt
->SessionConfigData
.DnsMode
) {
891 if (!IpIsUnicast (&Attempt
->SessionConfigData
.TargetIp
, IfrNvData
->IpMode
)) {
893 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
895 L
"Target IP is invalid!",
898 return EFI_INVALID_PARAMETER
;
901 if (Attempt
->SessionConfigData
.TargetUrl
[0] == '\0') {
903 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
905 L
"iSCSI target Url should not be NULL!",
908 return EFI_INVALID_PARAMETER
;
913 // Validate iSCSI target name configuration again:
914 // The format of iSCSI target name is already verified in IScsiFormCallback() when
915 // user input the name; here we only check the case user does not input the name.
917 if (Attempt
->SessionConfigData
.TargetName
[0] == '\0') {
919 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
921 L
"iSCSI target name is NULL!",
924 return EFI_INVALID_PARAMETER
;
929 // Validate the authentication info.
931 if (IfrNvData
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
932 if ((IfrNvData
->CHAPName
[0] == '\0') || (IfrNvData
->CHAPSecret
[0] == '\0')) {
934 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
936 L
"CHAP Name or CHAP Secret is invalid!",
940 return EFI_INVALID_PARAMETER
;
943 if ((IfrNvData
->CHAPType
== ISCSI_CHAP_MUTUAL
) &&
944 ((IfrNvData
->ReverseCHAPName
[0] == '\0') || (IfrNvData
->ReverseCHAPSecret
[0] == '\0'))
947 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
949 L
"Reverse CHAP Name or Reverse CHAP Secret is invalid!",
952 return EFI_INVALID_PARAMETER
;
957 // Check whether this attempt uses NIC which is already used by existing attempt.
959 SameNicAttempt
= IScsiConfigGetAttemptByNic (Attempt
, IfrNvData
->Enabled
);
960 if (SameNicAttempt
!= NULL
) {
961 AttemptName1
= (CHAR16
*) AllocateZeroPool (ATTEMPT_NAME_SIZE
* sizeof (CHAR16
));
962 if (AttemptName1
== NULL
) {
963 return EFI_OUT_OF_RESOURCES
;
966 AttemptName2
= (CHAR16
*) AllocateZeroPool (ATTEMPT_NAME_SIZE
* sizeof (CHAR16
));
967 if (AttemptName2
== NULL
) {
968 FreePool (AttemptName1
);
969 return EFI_OUT_OF_RESOURCES
;
972 AsciiStrToUnicodeStrS (Attempt
->AttemptName
, AttemptName1
, ATTEMPT_NAME_SIZE
);
973 AsciiStrToUnicodeStrS (SameNicAttempt
->AttemptName
, AttemptName2
, ATTEMPT_NAME_SIZE
);
976 mPrivate
->PortString
,
977 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
978 L
"Warning! Attempt \"%s\" uses same NIC as Attempt \"%s\".",
984 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
986 mPrivate
->PortString
,
990 FreePool (AttemptName1
);
991 FreePool (AttemptName2
);
996 // Update the iSCSI Mode data and record it in attempt help info.
998 if (IfrNvData
->Enabled
== ISCSI_DISABLED
) {
999 UnicodeSPrint (IScsiMode
, 64, L
"Disabled");
1000 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
) {
1001 UnicodeSPrint (IScsiMode
, 64, L
"Enabled");
1002 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
1003 UnicodeSPrint (IScsiMode
, 64, L
"Enabled for MPIO");
1006 if (IfrNvData
->IpMode
== IP_MODE_IP4
) {
1007 UnicodeSPrint (IpMode
, 64, L
"IP4");
1008 } else if (IfrNvData
->IpMode
== IP_MODE_IP6
) {
1009 UnicodeSPrint (IpMode
, 64, L
"IP6");
1010 } else if (IfrNvData
->IpMode
== IP_MODE_AUTOCONFIG
) {
1011 UnicodeSPrint (IpMode
, 64, L
"Autoconfigure");
1014 NicInfo
= IScsiGetNicInfoByIndex (Attempt
->NicIndex
);
1015 if (NicInfo
== NULL
) {
1016 return EFI_NOT_FOUND
;
1019 MacString
= (CHAR16
*) AllocateZeroPool (ISCSI_MAX_MAC_STRING_LEN
* sizeof (CHAR16
));
1020 if (MacString
== NULL
) {
1021 return EFI_OUT_OF_RESOURCES
;
1024 AsciiStrToUnicodeStrS (Attempt
->MacString
, MacString
, ISCSI_MAX_MAC_STRING_LEN
);
1027 mPrivate
->PortString
,
1028 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
1029 L
"MAC: %s, PFA: Bus %d | Dev %d | Func %d, iSCSI mode: %s, IP version: %s",
1032 NicInfo
->DeviceNumber
,
1033 NicInfo
->FunctionNumber
,
1038 Attempt
->AttemptTitleHelpToken
= HiiSetString (
1039 mCallbackInfo
->RegisteredHandle
,
1040 Attempt
->AttemptTitleHelpToken
,
1041 mPrivate
->PortString
,
1044 if (Attempt
->AttemptTitleHelpToken
== 0) {
1045 FreePool (MacString
);
1046 return EFI_OUT_OF_RESOURCES
;
1050 // Check whether this attempt is an existing one.
1052 ExistAttempt
= IScsiConfigGetAttemptByConfigIndex (Attempt
->AttemptConfigIndex
);
1053 if (ExistAttempt
!= NULL
) {
1054 ASSERT (ExistAttempt
== Attempt
);
1056 if (IfrNvData
->Enabled
== ISCSI_DISABLED
&&
1057 Attempt
->SessionConfigData
.Enabled
!= ISCSI_DISABLED
) {
1060 // User updates the Attempt from "Enabled"/"Enabled for MPIO" to "Disabled".
1062 if (Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
1063 if (mPrivate
->MpioCount
< 1) {
1067 if (--mPrivate
->MpioCount
== 0) {
1068 mPrivate
->EnableMpio
= FALSE
;
1070 } else if (Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED
) {
1071 if (mPrivate
->SinglePathCount
< 1) {
1074 mPrivate
->SinglePathCount
--;
1077 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
&&
1078 Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED
) {
1080 // User updates the Attempt from "Enabled" to "Enabled for MPIO".
1082 if (mPrivate
->SinglePathCount
< 1) {
1086 mPrivate
->EnableMpio
= TRUE
;
1087 mPrivate
->MpioCount
++;
1088 mPrivate
->SinglePathCount
--;
1090 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
&&
1091 Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
1093 // User updates the Attempt from "Enabled for MPIO" to "Enabled".
1095 if (mPrivate
->MpioCount
< 1) {
1099 if (--mPrivate
->MpioCount
== 0) {
1100 mPrivate
->EnableMpio
= FALSE
;
1102 mPrivate
->SinglePathCount
++;
1104 } else if (IfrNvData
->Enabled
!= ISCSI_DISABLED
&&
1105 Attempt
->SessionConfigData
.Enabled
== ISCSI_DISABLED
) {
1107 // User updates the Attempt from "Disabled" to "Enabled"/"Enabled for MPIO".
1109 if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
1110 mPrivate
->EnableMpio
= TRUE
;
1111 mPrivate
->MpioCount
++;
1113 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
) {
1114 mPrivate
->SinglePathCount
++;
1118 } else if (ExistAttempt
== NULL
) {
1120 // When a new attempt is created, pointer of the attempt is saved to
1121 // mCallbackInfo->Current in IScsiConfigProcessDefault. If input Attempt
1122 // does not match any existing attempt, it should be a new created attempt.
1123 // Save it to system now.
1127 // Save current order number for this attempt.
1129 AttemptConfigOrder
= IScsiGetVariableAndSize (
1132 &AttemptConfigOrderSize
1135 TotalNumber
= AttemptConfigOrderSize
/ sizeof (UINT8
);
1139 // Append the new created attempt order to the end.
1141 AttemptOrderTmp
= AllocateZeroPool (TotalNumber
* sizeof (UINT8
));
1142 if (AttemptOrderTmp
== NULL
) {
1143 if (AttemptConfigOrder
!= NULL
) {
1144 FreePool (AttemptConfigOrder
);
1146 return EFI_OUT_OF_RESOURCES
;
1149 if (AttemptConfigOrder
!= NULL
) {
1150 CopyMem (AttemptOrderTmp
, AttemptConfigOrder
, AttemptConfigOrderSize
);
1151 FreePool (AttemptConfigOrder
);
1154 AttemptOrderTmp
[TotalNumber
- 1] = Attempt
->AttemptConfigIndex
;
1155 AttemptConfigOrder
= AttemptOrderTmp
;
1156 AttemptConfigOrderSize
= TotalNumber
* sizeof (UINT8
);
1158 Status
= gRT
->SetVariable (
1161 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
1162 AttemptConfigOrderSize
,
1165 FreePool (AttemptConfigOrder
);
1166 if (EFI_ERROR (Status
)) {
1171 // Insert new created attempt to array.
1173 InsertTailList (&mPrivate
->AttemptConfigs
, &Attempt
->Link
);
1174 mPrivate
->AttemptCount
++;
1176 if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
1178 // This new Attempt is enabled for MPIO; enable the multipath mode.
1180 mPrivate
->EnableMpio
= TRUE
;
1181 mPrivate
->MpioCount
++;
1182 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
) {
1183 mPrivate
->SinglePathCount
++;
1186 IScsiConfigUpdateAttempt ();
1188 Attempt
->SessionConfigData
.Enabled
= IfrNvData
->Enabled
;
1191 // Record the user configuration information in NVR.
1193 UnicodeSPrint (mPrivate
->PortString
, (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
, L
"Attempt %d", Attempt
->AttemptConfigIndex
);
1195 FreePool (MacString
);
1197 return gRT
->SetVariable (
1198 mPrivate
->PortString
,
1199 &gEfiIScsiInitiatorNameProtocolGuid
,
1200 ISCSI_CONFIG_VAR_ATTR
,
1201 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA
),
1207 Convert the IFR data configured by keyword to iSCSI configuration data.
1209 @param[in] IfrNvData Point to ISCSI_CONFIG_IFR_NVDATA.
1210 @param[in] OffSet The offset of the variable to the configuration structure.
1212 @retval EFI_INVALID_PARAMETER Any input or configured parameter is invalid.
1213 @retval EFI_SUCCESS The operation is completed successfully.
1217 IScsiConvertlfrNvDataToAttemptConfigDataByKeyword (
1218 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
,
1222 ISCSI_ATTEMPT_CONFIG_NVDATA
*Attempt
;
1225 UINT8 ChapSecretLen
;
1226 UINT8 ReverseChapSecretLen
;
1227 CHAR16
*AttemptName1
;
1228 CHAR16
*AttemptName2
;
1229 ISCSI_ATTEMPT_CONFIG_NVDATA
*SameNicAttempt
;
1230 CHAR8 LunString
[ISCSI_LUN_STR_MAX_LEN
];
1231 CHAR8 IScsiName
[ISCSI_NAME_MAX_SIZE
];
1232 CHAR8 IpString
[IP_STR_MAX_SIZE
];
1233 EFI_IP_ADDRESS HostIp
;
1234 EFI_IP_ADDRESS SubnetMask
;
1235 EFI_IP_ADDRESS Gateway
;
1241 ZeroMem (IScsiName
, sizeof (IScsiName
));
1243 if (OffSet
< ATTEMPT_BOOTENABLE_VAR_OFFSET
) {
1246 } else if ((OffSet
>= ATTEMPT_BOOTENABLE_VAR_OFFSET
) && (OffSet
< ATTEMPT_ADDRESS_TYPE_VAR_OFFSET
)) {
1247 AttemptIndex
= (UINT8
) ((OffSet
- ATTEMPT_BOOTENABLE_VAR_OFFSET
) + 1);
1248 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1249 if (Attempt
== NULL
) {
1250 return EFI_INVALID_PARAMETER
;
1252 IfrNvData
->Enabled
= IfrNvData
->ISCSIBootEnableList
[AttemptIndex
- 1];
1254 // Validate the configuration of attempt.
1256 if (IfrNvData
->Enabled
!= ISCSI_DISABLED
) {
1258 // Check whether this attempt uses NIC which is already used by existing attempt.
1260 SameNicAttempt
= IScsiConfigGetAttemptByNic (Attempt
, IfrNvData
->Enabled
);
1261 if (SameNicAttempt
!= NULL
) {
1262 AttemptName1
= (CHAR16
*) AllocateZeroPool (ATTEMPT_NAME_SIZE
* sizeof (CHAR16
));
1263 if (AttemptName1
== NULL
) {
1264 return EFI_OUT_OF_RESOURCES
;
1267 AttemptName2
= (CHAR16
*) AllocateZeroPool (ATTEMPT_NAME_SIZE
* sizeof (CHAR16
));
1268 if (AttemptName2
== NULL
) {
1269 FreePool (AttemptName1
);
1270 return EFI_OUT_OF_RESOURCES
;
1273 AsciiStrToUnicodeStrS (Attempt
->AttemptName
, AttemptName1
, ATTEMPT_NAME_SIZE
);
1274 AsciiStrToUnicodeStrS (SameNicAttempt
->AttemptName
, AttemptName2
, ATTEMPT_NAME_SIZE
);
1277 mPrivate
->PortString
,
1278 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
1279 L
"Warning! \"%s\" uses same NIC as Attempt \"%s\".",
1285 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1287 mPrivate
->PortString
,
1291 FreePool (AttemptName1
);
1292 FreePool (AttemptName2
);
1296 if (IfrNvData
->Enabled
== ISCSI_DISABLED
&&
1297 Attempt
->SessionConfigData
.Enabled
!= ISCSI_DISABLED
) {
1300 // User updates the Attempt from "Enabled"/"Enabled for MPIO" to "Disabled".
1302 if (Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
1303 if (mPrivate
->MpioCount
< 1) {
1307 if (--mPrivate
->MpioCount
== 0) {
1308 mPrivate
->EnableMpio
= FALSE
;
1310 } else if (Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED
) {
1311 if (mPrivate
->SinglePathCount
< 1) {
1314 mPrivate
->SinglePathCount
--;
1317 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
&&
1318 Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED
) {
1320 // User updates the Attempt from "Enabled" to "Enabled for MPIO".
1322 if (mPrivate
->SinglePathCount
< 1) {
1326 mPrivate
->EnableMpio
= TRUE
;
1327 mPrivate
->MpioCount
++;
1328 mPrivate
->SinglePathCount
--;
1330 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
&&
1331 Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
1333 // User updates the Attempt from "Enabled for MPIO" to "Enabled".
1335 if (mPrivate
->MpioCount
< 1) {
1339 if (--mPrivate
->MpioCount
== 0) {
1340 mPrivate
->EnableMpio
= FALSE
;
1342 mPrivate
->SinglePathCount
++;
1344 } else if (IfrNvData
->Enabled
!= ISCSI_DISABLED
&&
1345 Attempt
->SessionConfigData
.Enabled
== ISCSI_DISABLED
) {
1347 // User updates the Attempt from "Disabled" to "Enabled"/"Enabled for MPIO".
1349 if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
1350 mPrivate
->EnableMpio
= TRUE
;
1351 mPrivate
->MpioCount
++;
1353 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
) {
1354 mPrivate
->SinglePathCount
++;
1357 Attempt
->SessionConfigData
.Enabled
= IfrNvData
->Enabled
;
1359 } else if ((OffSet
>= ATTEMPT_ADDRESS_TYPE_VAR_OFFSET
) && (OffSet
< ATTEMPT_CONNECT_RETRY_VAR_OFFSET
)) {
1360 AttemptIndex
= (UINT8
) ((OffSet
- ATTEMPT_ADDRESS_TYPE_VAR_OFFSET
) + 1);
1361 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1362 if (Attempt
== NULL
) {
1363 return EFI_INVALID_PARAMETER
;
1365 Attempt
->SessionConfigData
.IpMode
= IfrNvData
->ISCSIIpAddressTypeList
[AttemptIndex
- 1];
1366 if (Attempt
->SessionConfigData
.IpMode
< IP_MODE_AUTOCONFIG
) {
1367 Attempt
->AutoConfigureMode
= 0;
1370 } else if ((OffSet
>= ATTEMPT_CONNECT_RETRY_VAR_OFFSET
) && (OffSet
< ATTEMPT_CONNECT_TIMEOUT_VAR_OFFSET
)) {
1371 AttemptIndex
= (UINT8
) ((OffSet
- ATTEMPT_CONNECT_RETRY_VAR_OFFSET
) + 1);
1372 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1373 if (Attempt
== NULL
) {
1374 return EFI_INVALID_PARAMETER
;
1377 if (IfrNvData
->ISCSIConnectRetry
[AttemptIndex
- 1] > CONNECT_MAX_RETRY
) {
1379 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1381 L
"The minimum value is 0 and the maximum is 16. 0 means no retry.",
1384 return EFI_INVALID_PARAMETER
;
1386 Attempt
->SessionConfigData
.ConnectRetryCount
= IfrNvData
->ISCSIConnectRetry
[AttemptIndex
- 1];
1388 } else if ((OffSet
>= ATTEMPT_CONNECT_TIMEOUT_VAR_OFFSET
) && (OffSet
< ATTEMPT_INITIATOR_VIA_DHCP_VAR_OFFSET
)) {
1389 AttemptIndex
= (UINT8
) ((OffSet
- ATTEMPT_CONNECT_TIMEOUT_VAR_OFFSET
) / 2 + 1);
1390 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1391 if (Attempt
== NULL
) {
1392 return EFI_INVALID_PARAMETER
;
1395 if ((IfrNvData
->ISCSIConnectTimeout
[AttemptIndex
- 1] < CONNECT_MIN_TIMEOUT
) ||
1396 (IfrNvData
->ISCSIConnectTimeout
[AttemptIndex
- 1] > CONNECT_MAX_TIMEOUT
)) {
1398 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1400 L
"The minimum value is 100 milliseconds and the maximum is 20 seconds.",
1403 return EFI_INVALID_PARAMETER
;
1406 Attempt
->SessionConfigData
.ConnectTimeout
= IfrNvData
->ISCSIConnectTimeout
[AttemptIndex
- 1];
1407 if (Attempt
->SessionConfigData
.ConnectTimeout
== 0) {
1408 Attempt
->SessionConfigData
.ConnectTimeout
= CONNECT_DEFAULT_TIMEOUT
;
1411 } else if ((OffSet
>= ATTEMPT_INITIATOR_VIA_DHCP_VAR_OFFSET
) && (OffSet
< ATTEMPT_TARGET_VIA_DHCP_VAR_OFFSET
)) {
1412 AttemptIndex
= (UINT8
) ((OffSet
- ATTEMPT_INITIATOR_VIA_DHCP_VAR_OFFSET
) + 1);
1413 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1414 if (Attempt
== NULL
) {
1415 return EFI_INVALID_PARAMETER
;
1417 Attempt
->SessionConfigData
.InitiatorInfoFromDhcp
= IfrNvData
->ISCSIInitiatorInfoViaDHCP
[AttemptIndex
- 1];
1419 } else if ((OffSet
>= ATTEMPT_TARGET_VIA_DHCP_VAR_OFFSET
) && (OffSet
< ATTEMPT_TARGET_TCP_PORT_VAR_OFFSET
)) {
1420 AttemptIndex
= (UINT8
) ((OffSet
- ATTEMPT_TARGET_VIA_DHCP_VAR_OFFSET
) + 1);
1421 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1422 if (Attempt
== NULL
) {
1423 return EFI_INVALID_PARAMETER
;
1426 if ((Attempt
->SessionConfigData
.IpMode
< IP_MODE_AUTOCONFIG
) && (Attempt
->SessionConfigData
.InitiatorInfoFromDhcp
)) {
1427 Attempt
->SessionConfigData
.TargetInfoFromDhcp
= IfrNvData
->ISCSITargetInfoViaDHCP
[AttemptIndex
- 1];
1430 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1432 L
"Invalid Configuration, Check value of IpMode or Enable DHCP!",
1435 return EFI_INVALID_PARAMETER
;
1438 } else if ((OffSet
>= ATTEMPT_TARGET_TCP_PORT_VAR_OFFSET
) && (OffSet
< ATTEMPT_AUTHENTICATION_METHOD_VAR_OFFSET
)) {
1439 AttemptIndex
= (UINT8
) ((OffSet
- ATTEMPT_TARGET_TCP_PORT_VAR_OFFSET
) / 2 + 1);
1440 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1441 if (Attempt
== NULL
) {
1442 return EFI_INVALID_PARAMETER
;
1444 if ((Attempt
->SessionConfigData
.IpMode
< IP_MODE_AUTOCONFIG
) && (!Attempt
->SessionConfigData
.TargetInfoFromDhcp
)) {
1445 Attempt
->SessionConfigData
.TargetPort
= IfrNvData
->ISCSITargetTcpPort
[AttemptIndex
- 1];
1446 if (Attempt
->SessionConfigData
.TargetPort
== 0) {
1447 Attempt
->SessionConfigData
.TargetPort
= ISCSI_WELL_KNOWN_PORT
;
1451 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1453 L
"Invalid Configuration, Check value of IpMode or Target Via DHCP!",
1456 return EFI_INVALID_PARAMETER
;
1459 } else if ((OffSet
>= ATTEMPT_AUTHENTICATION_METHOD_VAR_OFFSET
) && (OffSet
< ATTEMPT_CHARTYPE_VAR_OFFSET
)) {
1460 AttemptIndex
= (UINT8
) ((OffSet
- ATTEMPT_AUTHENTICATION_METHOD_VAR_OFFSET
) + 1);
1461 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1462 if (Attempt
== NULL
) {
1463 return EFI_INVALID_PARAMETER
;
1466 Attempt
->AuthenticationType
= IfrNvData
->ISCSIAuthenticationMethod
[AttemptIndex
- 1];
1468 } else if ((OffSet
>= ATTEMPT_CHARTYPE_VAR_OFFSET
) && (OffSet
< ATTEMPT_ISID_VAR_OFFSET
)) {
1469 AttemptIndex
= (UINT8
) ((OffSet
- ATTEMPT_CHARTYPE_VAR_OFFSET
) + 1);
1470 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1471 if (Attempt
== NULL
) {
1472 return EFI_INVALID_PARAMETER
;
1474 if (Attempt
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
1475 Attempt
->AuthConfigData
.CHAP
.CHAPType
= IfrNvData
->ISCSIChapType
[AttemptIndex
- 1];
1478 } else if (OffSet
>= ATTEMPT_ISID_VAR_OFFSET
) {
1479 Index
= (UINT8
) ((OffSet
- ATTEMPT_ISID_VAR_OFFSET
) / sizeof (KEYWORD_STR
));
1480 AttemptIndex
= Index
+ 1;
1481 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1482 if (Attempt
== NULL
) {
1483 return EFI_INVALID_PARAMETER
;
1486 OffSet
= OffSet
- Index
* sizeof (KEYWORD_STR
);
1488 if ((OffSet
>= ATTEMPT_ISID_VAR_OFFSET
) && (OffSet
< ATTEMPT_INITIATOR_IP_ADDRESS_VAR_OFFSET
)) {
1489 IScsiParseIsIdFromString (IfrNvData
->Keyword
[Index
].ISCSIIsId
, Attempt
->SessionConfigData
.IsId
);
1491 } else if ((OffSet
>= ATTEMPT_INITIATOR_IP_ADDRESS_VAR_OFFSET
) && (OffSet
< ATTEMPT_INITIATOR_NET_MASK_VAR_OFFSET
)) {
1492 if ((Attempt
->SessionConfigData
.IpMode
== IP_MODE_IP4
) && (!Attempt
->SessionConfigData
.InitiatorInfoFromDhcp
)) {
1496 Status
= NetLibStrToIp4 (IfrNvData
->Keyword
[Index
].ISCSIInitiatorIpAddress
, &HostIp
.v4
);
1497 if (EFI_ERROR (Status
) || ((Attempt
->SessionConfigData
.SubnetMask
.Addr
[0] != 0) &&
1498 !NetIp4IsUnicast (NTOHL (HostIp
.Addr
[0]), NTOHL(*(UINT32
*)Attempt
->SessionConfigData
.SubnetMask
.Addr
)))) {
1500 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1502 L
"Invalid IP address!",
1505 return EFI_INVALID_PARAMETER
;
1507 CopyMem (&Attempt
->SessionConfigData
.LocalIp
, &HostIp
.v4
, sizeof (HostIp
.v4
));
1511 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1513 L
"Invalid Configuration, Check value of IpMode or Enable DHCP!",
1516 return EFI_INVALID_PARAMETER
;
1519 } else if ((OffSet
>= ATTEMPT_INITIATOR_NET_MASK_VAR_OFFSET
) && (OffSet
< ATTEMPT_INITIATOR_GATE_WAY_VAR_OFFSET
)) {
1520 if ((Attempt
->SessionConfigData
.IpMode
== IP_MODE_IP4
) && (!Attempt
->SessionConfigData
.InitiatorInfoFromDhcp
)) {
1521 Status
= NetLibStrToIp4 (IfrNvData
->Keyword
[Index
].ISCSIInitiatorNetmask
, &SubnetMask
.v4
);
1522 if (EFI_ERROR (Status
) || ((SubnetMask
.Addr
[0] != 0) && (IScsiGetSubnetMaskPrefixLength (&SubnetMask
.v4
) == 0))) {
1524 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1526 L
"Invalid Subnet Mask!",
1529 return EFI_INVALID_PARAMETER
;
1531 CopyMem (&Attempt
->SessionConfigData
.SubnetMask
, &SubnetMask
.v4
, sizeof (SubnetMask
.v4
));
1535 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1537 L
"Invalid Configuration, Check value of IpMode or Enable DHCP!",
1540 return EFI_INVALID_PARAMETER
;
1543 } else if ((OffSet
>= ATTEMPT_INITIATOR_GATE_WAY_VAR_OFFSET
) && (OffSet
< ATTEMPT_TARGET_NAME_VAR_OFFSET
)) {
1544 if ((Attempt
->SessionConfigData
.IpMode
== IP_MODE_IP4
) && (!Attempt
->SessionConfigData
.InitiatorInfoFromDhcp
)) {
1545 Status
= NetLibStrToIp4 (IfrNvData
->Keyword
[Index
].ISCSIInitiatorGateway
, &Gateway
.v4
);
1546 if (EFI_ERROR (Status
) ||
1547 ((Gateway
.Addr
[0] != 0) && (Attempt
->SessionConfigData
.SubnetMask
.Addr
[0] != 0) &&
1548 !NetIp4IsUnicast (NTOHL (Gateway
.Addr
[0]), NTOHL(*(UINT32
*)Attempt
->SessionConfigData
.SubnetMask
.Addr
)))) {
1550 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1552 L
"Invalid Gateway!",
1555 return EFI_INVALID_PARAMETER
;
1557 CopyMem (&Attempt
->SessionConfigData
.Gateway
, &Gateway
.v4
, sizeof (Gateway
.v4
));
1561 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1563 L
"Invalid Configuration, Check value of IpMode or Enable DHCP!",
1566 return EFI_INVALID_PARAMETER
;
1569 } else if ((OffSet
>= ATTEMPT_TARGET_NAME_VAR_OFFSET
) && (OffSet
< ATTEMPT_TARGET_IP_ADDRESS_VAR_OFFSET
)) {
1570 if ((Attempt
->SessionConfigData
.IpMode
< IP_MODE_AUTOCONFIG
) && (!Attempt
->SessionConfigData
.TargetInfoFromDhcp
)) {
1571 UnicodeStrToAsciiStrS (IfrNvData
->Keyword
[Index
].ISCSITargetName
, IScsiName
, ISCSI_NAME_MAX_SIZE
);
1572 Status
= IScsiNormalizeName (IScsiName
, AsciiStrLen (IScsiName
));
1573 if (EFI_ERROR (Status
)) {
1575 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1577 L
"Invalid iSCSI Name!",
1581 AsciiStrCpyS (Attempt
->SessionConfigData
.TargetName
, ISCSI_NAME_MAX_SIZE
, IScsiName
);
1583 if (Attempt
->SessionConfigData
.Enabled
!= ISCSI_DISABLED
) {
1584 if (Attempt
->SessionConfigData
.TargetName
[0] == L
'\0') {
1586 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1588 L
"iSCSI target name is NULL!",
1591 return EFI_INVALID_PARAMETER
;
1596 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1598 L
"Invalid Configuration, Check value of IpMode or Target Via DHCP!",
1601 return EFI_INVALID_PARAMETER
;
1604 } else if ((OffSet
>= ATTEMPT_TARGET_IP_ADDRESS_VAR_OFFSET
) && (OffSet
< ATTEMPT_LUN_VAR_OFFSET
)) {
1605 if ((Attempt
->SessionConfigData
.IpMode
< IP_MODE_AUTOCONFIG
) && (!Attempt
->SessionConfigData
.TargetInfoFromDhcp
)) {
1606 UnicodeStrToAsciiStrS (IfrNvData
->Keyword
[Index
].ISCSITargetIpAddress
, IpString
, sizeof (IpString
));
1607 Status
= IScsiAsciiStrToIp (IpString
, Attempt
->SessionConfigData
.IpMode
, &HostIp
);
1608 if (EFI_ERROR (Status
) || !IpIsUnicast (&HostIp
, Attempt
->SessionConfigData
.IpMode
)) {
1609 Attempt
->SessionConfigData
.DnsMode
= TRUE
;
1610 ZeroMem (&Attempt
->SessionConfigData
.TargetIp
, sizeof (Attempt
->SessionConfigData
.TargetIp
));
1611 UnicodeStrToAsciiStrS (IfrNvData
->Keyword
[Index
].ISCSITargetIpAddress
, Attempt
->SessionConfigData
.TargetUrl
, ISCSI_NAME_MAX_SIZE
);
1613 Attempt
->SessionConfigData
.DnsMode
= FALSE
;
1614 CopyMem (&Attempt
->SessionConfigData
.TargetIp
, &HostIp
, sizeof (HostIp
));
1618 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1620 L
"Invalid Configuration, Check value of IpMode or Target Via DHCP!",
1623 return EFI_INVALID_PARAMETER
;
1626 } else if ((OffSet
>= ATTEMPT_LUN_VAR_OFFSET
) && (OffSet
< ATTEMPT_CHAR_USER_NAME_VAR_OFFSET
)) {
1627 if ((Attempt
->SessionConfigData
.IpMode
< IP_MODE_AUTOCONFIG
) && (Attempt
->SessionConfigData
.TargetInfoFromDhcp
== 0)) {
1631 UnicodeStrToAsciiStrS (IfrNvData
->Keyword
[Index
].ISCSILun
, LunString
, ISCSI_LUN_STR_MAX_LEN
);
1632 Status
= IScsiAsciiStrToLun (LunString
, (UINT8
*) &Lun
);
1633 if (EFI_ERROR (Status
)) {
1635 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1637 L
"Invalid LUN string, Examples are: 4752-3A4F-6b7e-2F99, 6734-9-156f-127, 4186-9!",
1641 CopyMem (&Attempt
->SessionConfigData
.BootLun
, &Lun
, sizeof (Lun
));
1645 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1647 L
"Invalid Configuration, Check value of IpMode or Target Via DHCP!",
1650 return EFI_INVALID_PARAMETER
;
1653 } else if ((OffSet
>= ATTEMPT_CHAR_USER_NAME_VAR_OFFSET
) && (OffSet
< ATTEMPT_CHAR_SECRET_VAR_OFFSET
)) {
1654 if (Attempt
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
1655 UnicodeStrToAsciiStrS (
1656 IfrNvData
->Keyword
[Index
].ISCSIChapUsername
,
1657 Attempt
->AuthConfigData
.CHAP
.CHAPName
,
1658 ISCSI_CHAP_NAME_STORAGE
1661 if (Attempt
->SessionConfigData
.Enabled
!= ISCSI_DISABLED
) {
1662 if (IfrNvData
->Keyword
[Index
].ISCSIChapUsername
[0] == L
'\0') {
1664 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1666 L
"CHAP Name is invalid!",
1669 return EFI_INVALID_PARAMETER
;
1674 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1676 L
"Invalid Configuration, Check value of AuthenticationType!",
1679 return EFI_INVALID_PARAMETER
;
1682 } else if ((OffSet
>= ATTEMPT_CHAR_SECRET_VAR_OFFSET
) && (OffSet
< ATTEMPT_CHAR_REVERSE_USER_NAME_VAR_OFFSET
)) {
1683 if (Attempt
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
1684 ChapSecretLen
= (UINT8
)StrLen (IfrNvData
->Keyword
[Index
].ISCSIChapSecret
);
1685 UnicodeStrToAsciiStrS (
1686 IfrNvData
->Keyword
[Index
].ISCSIChapSecret
,
1687 Attempt
->AuthConfigData
.CHAP
.CHAPSecret
,
1688 ISCSI_CHAP_SECRET_STORAGE
1691 if (Attempt
->SessionConfigData
.Enabled
!= ISCSI_DISABLED
) {
1692 if ((ChapSecretLen
< ISCSI_CHAP_SECRET_MIN_LEN
) || (ChapSecretLen
> ISCSI_CHAP_SECRET_MAX_LEN
)) {
1694 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1696 L
"The Chap Secret minimum length is 12 bytes and the maximum length is 16 bytes.",
1699 return EFI_INVALID_PARAMETER
;
1704 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1706 L
"Invalid Configuration, Check value of AuthenticationType!",
1709 return EFI_INVALID_PARAMETER
;
1712 } else if ((OffSet
>= ATTEMPT_CHAR_REVERSE_USER_NAME_VAR_OFFSET
) && (OffSet
< ATTEMPT_CHAR_REVERSE_SECRET_VAR_OFFSET
)) {
1713 if (Attempt
->AuthConfigData
.CHAP
.CHAPType
== ISCSI_CHAP_MUTUAL
) {
1714 UnicodeStrToAsciiStrS (
1715 IfrNvData
->Keyword
[Index
].ISCSIReverseChapUsername
,
1716 Attempt
->AuthConfigData
.CHAP
.ReverseCHAPName
,
1717 ISCSI_CHAP_NAME_STORAGE
1719 if (Attempt
->SessionConfigData
.Enabled
!= ISCSI_DISABLED
) {
1720 if (IfrNvData
->Keyword
[Index
].ISCSIReverseChapUsername
[0] == L
'\0') {
1722 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1724 L
"Reverse CHAP Name is invalid!",
1727 return EFI_INVALID_PARAMETER
;
1732 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1734 L
"Invalid Configuration, Check value of AuthenticationType or Chap Type!",
1737 return EFI_INVALID_PARAMETER
;
1740 } else if (OffSet
>= ATTEMPT_CHAR_REVERSE_SECRET_VAR_OFFSET
) {
1741 if (Attempt
->AuthConfigData
.CHAP
.CHAPType
== ISCSI_CHAP_MUTUAL
) {
1742 ReverseChapSecretLen
= (UINT8
)StrLen (IfrNvData
->Keyword
[Index
].ISCSIReverseChapSecret
);
1743 UnicodeStrToAsciiStrS (
1744 IfrNvData
->Keyword
[Index
].ISCSIReverseChapSecret
,
1745 Attempt
->AuthConfigData
.CHAP
.ReverseCHAPSecret
,
1746 ISCSI_CHAP_SECRET_STORAGE
1749 if (Attempt
->SessionConfigData
.Enabled
!= ISCSI_DISABLED
) {
1750 if ((ReverseChapSecretLen
< ISCSI_CHAP_SECRET_MIN_LEN
) || (ReverseChapSecretLen
> ISCSI_CHAP_SECRET_MAX_LEN
)) {
1752 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1754 L
"The Reverse CHAP Secret minimum length is 12 bytes and the maximum length is 16 bytes.",
1757 return EFI_INVALID_PARAMETER
;
1762 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1764 L
"Invalid Configuration, Check value of AuthenticationType or Chap Type!",
1767 return EFI_INVALID_PARAMETER
;
1775 // Record the user configuration information in NVR.
1777 ASSERT (Attempt
!= NULL
);
1778 UnicodeSPrint (mPrivate
->PortString
, (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
, L
"Attempt %d", Attempt
->AttemptConfigIndex
);
1779 return gRT
->SetVariable (
1780 mPrivate
->PortString
,
1781 &gEfiIScsiInitiatorNameProtocolGuid
,
1782 ISCSI_CONFIG_VAR_ATTR
,
1783 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA
),
1790 Create Hii Extend Label OpCode as the start opcode and end opcode. It is
1793 @param[in] StartLabelNumber The number of start label.
1794 @param[out] StartOpCodeHandle Points to the start opcode handle.
1795 @param[out] StartLabel Points to the created start opcode.
1796 @param[out] EndOpCodeHandle Points to the end opcode handle.
1797 @param[out] EndLabel Points to the created end opcode.
1799 @retval EFI_OUT_OF_RESOURCES Do not have sufficient resource to finish this
1801 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
1802 @retval EFI_SUCCESS The operation is completed successfully.
1807 IN UINT16 StartLabelNumber
,
1808 OUT VOID
**StartOpCodeHandle
,
1809 OUT EFI_IFR_GUID_LABEL
**StartLabel
,
1810 OUT VOID
**EndOpCodeHandle
,
1811 OUT EFI_IFR_GUID_LABEL
**EndLabel
1815 EFI_IFR_GUID_LABEL
*InternalStartLabel
;
1816 EFI_IFR_GUID_LABEL
*InternalEndLabel
;
1818 if (StartOpCodeHandle
== NULL
|| StartLabel
== NULL
|| EndOpCodeHandle
== NULL
|| EndLabel
== NULL
) {
1819 return EFI_INVALID_PARAMETER
;
1822 *StartOpCodeHandle
= NULL
;
1823 *EndOpCodeHandle
= NULL
;
1824 Status
= EFI_OUT_OF_RESOURCES
;
1827 // Initialize the container for dynamic opcodes.
1829 *StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
1830 if (*StartOpCodeHandle
== NULL
) {
1834 *EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
1835 if (*EndOpCodeHandle
== NULL
) {
1840 // Create Hii Extend Label OpCode as the start opcode.
1842 InternalStartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
1846 sizeof (EFI_IFR_GUID_LABEL
)
1848 if (InternalStartLabel
== NULL
) {
1852 InternalStartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
1853 InternalStartLabel
->Number
= StartLabelNumber
;
1856 // Create Hii Extend Label OpCode as the end opcode.
1858 InternalEndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
1862 sizeof (EFI_IFR_GUID_LABEL
)
1864 if (InternalEndLabel
== NULL
) {
1868 InternalEndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
1869 InternalEndLabel
->Number
= LABEL_END
;
1871 *StartLabel
= InternalStartLabel
;
1872 *EndLabel
= InternalEndLabel
;
1878 if (*StartOpCodeHandle
!= NULL
) {
1879 HiiFreeOpCodeHandle (*StartOpCodeHandle
);
1882 if (*EndOpCodeHandle
!= NULL
) {
1883 HiiFreeOpCodeHandle (*EndOpCodeHandle
);
1889 Update the MAIN form to display the configured attempts.
1893 IScsiConfigUpdateAttempt (
1898 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
1899 VOID
*StartOpCodeHandle
;
1900 EFI_IFR_GUID_LABEL
*StartLabel
;
1901 VOID
*EndOpCodeHandle
;
1902 EFI_IFR_GUID_LABEL
*EndLabel
;
1905 Status
= IScsiCreateOpCode (
1906 ATTEMPT_ENTRY_LABEL
,
1912 if (EFI_ERROR (Status
)) {
1916 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
1917 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
1918 if (AttemptConfigData
->Actived
== ISCSI_ACTIVE_ENABLED
) {
1920 // Update Attempt Help Info.
1922 UnicodeSPrint (mPrivate
->PortString
, (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
, L
"Attempt %d", (UINTN
) AttemptConfigData
->AttemptConfigIndex
);
1923 AttemptConfigData
->AttemptTitleToken
= HiiSetString (
1924 mCallbackInfo
->RegisteredHandle
,
1926 mPrivate
->PortString
,
1929 if (AttemptConfigData
->AttemptTitleToken
== 0) {
1933 HiiCreateGotoOpCode (
1934 StartOpCodeHandle
, // Container for dynamic created opcodes
1935 FORMID_ATTEMPT_FORM
, // Form ID
1936 AttemptConfigData
->AttemptTitleToken
, // Prompt text
1937 AttemptConfigData
->AttemptTitleHelpToken
, // Help text
1938 EFI_IFR_FLAG_CALLBACK
, // Question flag
1939 (UINT16
) (KEY_ATTEMPT_ENTRY_BASE
+ AttemptConfigData
->AttemptConfigIndex
) // Question ID
1945 mCallbackInfo
->RegisteredHandle
, // HII handle
1946 &gIScsiConfigGuid
, // Formset GUID
1947 FORMID_MAIN_FORM
, // Form ID
1948 StartOpCodeHandle
, // Label for where to insert opcodes
1949 EndOpCodeHandle
// Replace data
1952 HiiFreeOpCodeHandle (StartOpCodeHandle
);
1953 HiiFreeOpCodeHandle (EndOpCodeHandle
);
1957 Callback function when user presses "Add an Attempt".
1959 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
1961 @retval EFI_SUCCESS The operation is completed successfully.
1965 IScsiConfigAddAttempt (
1970 ISCSI_NIC_INFO
*NicInfo
;
1971 EFI_STRING_ID PortTitleToken
;
1972 EFI_STRING_ID PortTitleHelpToken
;
1973 CHAR16 MacString
[ISCSI_MAX_MAC_STRING_LEN
];
1975 VOID
*StartOpCodeHandle
;
1976 EFI_IFR_GUID_LABEL
*StartLabel
;
1977 VOID
*EndOpCodeHandle
;
1978 EFI_IFR_GUID_LABEL
*EndLabel
;
1980 Status
= IScsiCreateOpCode (
1987 if (EFI_ERROR (Status
)) {
1992 // Ask user to select a MAC for this attempt.
1994 NET_LIST_FOR_EACH (Entry
, &mPrivate
->NicInfoList
) {
1995 NicInfo
= NET_LIST_USER_STRUCT (Entry
, ISCSI_NIC_INFO
, Link
);
1997 &NicInfo
->PermanentAddress
,
1998 NicInfo
->HwAddressSize
,
2003 UnicodeSPrint (mPrivate
->PortString
, (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
, L
"MAC %s", MacString
);
2004 PortTitleToken
= HiiSetString (
2005 mCallbackInfo
->RegisteredHandle
,
2007 mPrivate
->PortString
,
2010 if (PortTitleToken
== 0) {
2011 Status
= EFI_INVALID_PARAMETER
;
2016 mPrivate
->PortString
,
2017 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
2018 L
"PFA: Bus %d | Dev %d | Func %d",
2020 NicInfo
->DeviceNumber
,
2021 NicInfo
->FunctionNumber
2023 PortTitleHelpToken
= HiiSetString (mCallbackInfo
->RegisteredHandle
, 0, mPrivate
->PortString
, NULL
);
2024 if (PortTitleHelpToken
== 0) {
2025 Status
= EFI_INVALID_PARAMETER
;
2029 HiiCreateGotoOpCode (
2030 StartOpCodeHandle
, // Container for dynamic created opcodes
2031 FORMID_ATTEMPT_FORM
,
2034 EFI_IFR_FLAG_CALLBACK
, // Question flag
2035 (UINT16
) (KEY_MAC_ENTRY_BASE
+ NicInfo
->NicIndex
)
2039 Status
= HiiUpdateForm (
2040 mCallbackInfo
->RegisteredHandle
, // HII handle
2041 &gIScsiConfigGuid
, // Formset GUID
2042 FORMID_MAC_FORM
, // Form ID
2043 StartOpCodeHandle
, // Label for where to insert opcodes
2044 EndOpCodeHandle
// Replace data
2048 HiiFreeOpCodeHandle (StartOpCodeHandle
);
2049 HiiFreeOpCodeHandle (EndOpCodeHandle
);
2055 Add the attempts by keyword 'iSCSIAddAttempts', you can use this keyword with
2056 value 'attempt:1 attempt:2' etc to add one or more attempts once. This is different
2057 with IScsiConfigAddAttempt function which is used to add attempt by UI configuration.
2059 @param[in] AttemptList The new attempt List will be added.
2061 @retval EFI_SUCCESS The operation to add attempt list successfully.
2062 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
2063 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
2064 @retval EFI_OUT_OF_RESOURCES Fail to finish the operation due to lack of
2069 IScsiConfigAddAttemptsByKeywords (
2070 IN UINT8
*AttemptList
2077 UINT8
*AttemptConfigOrder
;
2078 UINTN AttemptConfigOrderSize
;
2079 UINT8
*AttemptConfigOrderTmp
;
2080 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
2081 ISCSI_NIC_INFO
*NicInfo
;
2082 CHAR16 MacString
[ISCSI_MAX_MAC_STRING_LEN
];
2083 CHAR16 IScsiMode
[64];
2087 Nic
= mPrivate
->CurrentNic
;
2088 NicInfo
= IScsiGetNicInfoByIndex (Nic
);
2089 if (NicInfo
== NULL
) {
2090 return EFI_NOT_FOUND
;
2094 // The MAC info will be recorded in Config Data.
2097 &NicInfo
->PermanentAddress
,
2098 NicInfo
->HwAddressSize
,
2103 for (Index
= 0; Index
< PcdGet8 (PcdMaxIScsiAttemptNumber
); Index
++) {
2104 if (AttemptList
[Index
] == 0) {
2111 Number
= AttemptList
[Index
];
2114 mPrivate
->PortString
,
2115 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
2121 mPrivate
->PortString
,
2122 &gEfiIScsiInitiatorNameProtocolGuid
,
2123 (VOID
**)&AttemptConfigData
,
2126 if (AttemptConfigData
== NULL
|| AttemptConfigData
->Actived
== ISCSI_ACTIVE_ENABLED
) {
2127 return EFI_INVALID_PARAMETER
;
2130 AttemptConfigData
->Actived
= ISCSI_ACTIVE_ENABLED
;
2131 AttemptConfigData
->NicIndex
= NicInfo
->NicIndex
;
2132 UnicodeStrToAsciiStrS (MacString
, AttemptConfigData
->MacString
, ISCSI_MAX_MAC_STRING_LEN
);
2135 // Generate OUI-format ISID based on MAC address.
2137 CopyMem (AttemptConfigData
->SessionConfigData
.IsId
, &NicInfo
->PermanentAddress
, 6);
2138 AttemptConfigData
->SessionConfigData
.IsId
[0] =
2139 (UINT8
) (AttemptConfigData
->SessionConfigData
.IsId
[0] & 0x3F);
2142 // Configure the iSCSI Mode and IpMode to default.
2143 // Add Attempt Help Info.
2145 UnicodeSPrint (IScsiMode
, 64, L
"Disabled");
2146 UnicodeSPrint (IpMode
, 64, L
"IP4");
2148 mPrivate
->PortString
,
2149 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
2150 L
"MAC: %s, PFA: Bus %d | Dev %d | Func %d, iSCSI mode: %s, IP version: %s",
2153 NicInfo
->DeviceNumber
,
2154 NicInfo
->FunctionNumber
,
2159 AttemptConfigData
->AttemptTitleHelpToken
= HiiSetString (
2160 mCallbackInfo
->RegisteredHandle
,
2162 mPrivate
->PortString
,
2165 if (AttemptConfigData
->AttemptTitleHelpToken
== 0) {
2166 return EFI_OUT_OF_RESOURCES
;
2170 // Get current Attempt order and number.
2172 AttemptConfigOrder
= IScsiGetVariableAndSize (
2175 &AttemptConfigOrderSize
2177 TotalNumber
= AttemptConfigOrderSize
/ sizeof (UINT8
);
2181 // Append the new created attempt order to the end.
2183 AttemptConfigOrderTmp
= AllocateZeroPool (TotalNumber
* sizeof (UINT8
));
2184 if (AttemptConfigOrderTmp
== NULL
) {
2185 if (AttemptConfigOrder
!= NULL
) {
2186 FreePool (AttemptConfigOrder
);
2188 return EFI_OUT_OF_RESOURCES
;
2190 if (AttemptConfigOrder
!= NULL
) {
2191 CopyMem (AttemptConfigOrderTmp
, AttemptConfigOrder
, AttemptConfigOrderSize
);
2192 FreePool (AttemptConfigOrder
);
2195 AttemptConfigOrderTmp
[TotalNumber
- 1] = Number
;
2196 AttemptConfigOrder
= AttemptConfigOrderTmp
;
2197 AttemptConfigOrderSize
= TotalNumber
* sizeof (UINT8
);
2199 Status
= gRT
->SetVariable (
2202 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
2203 AttemptConfigOrderSize
,
2206 FreePool (AttemptConfigOrder
);
2207 if (EFI_ERROR (Status
)) {
2212 // Record the attempt in global link list.
2214 InsertTailList (&mPrivate
->AttemptConfigs
, &AttemptConfigData
->Link
);
2215 mPrivate
->AttemptCount
++;
2216 UnicodeSPrint (mPrivate
->PortString
, (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
, L
"Attempt %d", AttemptConfigData
->AttemptConfigIndex
);
2218 mPrivate
->PortString
,
2219 &gEfiIScsiInitiatorNameProtocolGuid
,
2220 ISCSI_CONFIG_VAR_ATTR
,
2221 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA
),
2231 Callback function when user presses "Commit Changes and Exit" in Delete Attempts or Delete Attempts by Keyword.
2233 @param[in] IfrNvData The IFR NV data.
2235 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
2236 @retval EFI_SUCCESS The operation is completed successfully.
2237 @retval EFI_ABOTRED This operation is aborted cause of error
2239 @retval EFI_OUT_OF_RESOURCES Fail to finish the operation due to lack of
2244 IScsiConfigDeleteAttempts (
2245 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
2251 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
2252 UINT8
*AttemptConfigOrder
;
2253 UINTN AttemptConfigOrderSize
;
2254 UINT8
*AttemptNewOrder
;
2255 UINT8 AttemptConfigIndex
;
2260 LIST_ENTRY
*NextEntry
;
2261 ISCSI_SESSION_CONFIG_NVDATA
*ConfigData
;
2265 AttemptConfigOrder
= IScsiGetVariableAndSize (
2268 &AttemptConfigOrderSize
2270 if ((AttemptConfigOrder
== NULL
) || (AttemptConfigOrderSize
== 0)) {
2271 return EFI_NOT_FOUND
;
2274 AttemptNewOrder
= AllocateZeroPool (AttemptConfigOrderSize
);
2275 if (AttemptNewOrder
== NULL
) {
2276 Status
= EFI_OUT_OF_RESOURCES
;
2280 Total
= AttemptConfigOrderSize
/ sizeof (UINT8
);
2283 NET_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &mPrivate
->AttemptConfigs
) {
2284 if (IfrNvData
->DeleteAttemptList
[Index
] == 0) {
2290 // Delete the attempt.
2293 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
2294 if (AttemptConfigData
== NULL
) {
2295 Status
= EFI_NOT_FOUND
;
2300 // Remove this attempt from UI configured attempt list.
2302 RemoveEntryList (&AttemptConfigData
->Link
);
2303 mPrivate
->AttemptCount
--;
2305 if (AttemptConfigData
->SessionConfigData
.Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
2306 if (mPrivate
->MpioCount
< 1) {
2307 Status
= EFI_ABORTED
;
2312 // No more attempt is enabled for MPIO. Transit the iSCSI mode to single path.
2314 if (--mPrivate
->MpioCount
== 0) {
2315 mPrivate
->EnableMpio
= FALSE
;
2317 } else if (AttemptConfigData
->SessionConfigData
.Enabled
== ISCSI_ENABLED
) {
2318 if (mPrivate
->SinglePathCount
< 1) {
2319 Status
= EFI_ABORTED
;
2323 mPrivate
->SinglePathCount
--;
2326 AttemptConfigIndex
= AttemptConfigData
->AttemptConfigIndex
;
2327 FreePool (AttemptConfigData
);
2330 // Create a new Attempt
2332 AttemptConfigData
= AllocateZeroPool (sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA
));
2333 if (AttemptConfigData
== NULL
) {
2334 return EFI_OUT_OF_RESOURCES
;
2336 ConfigData
= &AttemptConfigData
->SessionConfigData
;
2337 ConfigData
->TargetPort
= ISCSI_WELL_KNOWN_PORT
;
2338 ConfigData
->ConnectTimeout
= CONNECT_DEFAULT_TIMEOUT
;
2339 ConfigData
->ConnectRetryCount
= CONNECT_MIN_RETRY
;
2341 AttemptConfigData
->AuthenticationType
= ISCSI_AUTH_TYPE_CHAP
;
2342 AttemptConfigData
->AuthConfigData
.CHAP
.CHAPType
= ISCSI_CHAP_UNI
;
2344 // Configure the Attempt index and set variable.
2346 AttemptConfigData
->AttemptConfigIndex
= AttemptConfigIndex
;
2349 // Set the attempt name to default.
2352 mPrivate
->PortString
,
2353 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
2355 (UINTN
) AttemptConfigData
->AttemptConfigIndex
2357 UnicodeStrToAsciiStrS (mPrivate
->PortString
, AttemptConfigData
->AttemptName
, ATTEMPT_NAME_SIZE
);
2359 mPrivate
->PortString
,
2360 &gEfiIScsiInitiatorNameProtocolGuid
,
2361 ISCSI_CONFIG_VAR_ATTR
,
2362 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA
),
2367 // Mark the attempt order in NVR to be deleted - 0.
2369 for (NewIndex
= 0; NewIndex
< Total
; NewIndex
++) {
2370 if (AttemptConfigOrder
[NewIndex
] == AttemptConfigData
->AttemptConfigIndex
) {
2371 AttemptConfigOrder
[NewIndex
] = 0;
2377 if (mCallbackInfo
->Current
== AttemptConfigData
) {
2378 mCallbackInfo
->Current
= NULL
;
2380 FreePool (AttemptConfigData
);
2383 // Check next Attempt.
2389 // Construct AttemptNewOrder.
2391 for (Index
= 0, NewIndex
= 0; Index
< Total
; Index
++) {
2392 if (AttemptConfigOrder
[Index
] != 0) {
2393 AttemptNewOrder
[NewIndex
] = AttemptConfigOrder
[Index
];
2398 Attribute
= EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_NON_VOLATILE
;
2401 // Update AttemptOrder in NVR.
2403 Status
= gRT
->SetVariable (
2407 NewTotal
* sizeof (UINT8
),
2412 if (AttemptConfigOrder
!= NULL
) {
2413 FreePool (AttemptConfigOrder
);
2416 if (AttemptNewOrder
!= NULL
) {
2417 FreePool (AttemptNewOrder
);
2425 Callback function when user presses "Delete Attempts".
2427 @param[in] IfrNvData The IFR nv data.
2429 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
2430 @retval EFI_BUFFER_TOO_SMALL The buffer in UpdateData is too small.
2431 @retval EFI_SUCCESS The operation is completed successfully.
2435 IScsiConfigDisplayDeleteAttempts (
2436 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
2440 UINT8
*AttemptConfigOrder
;
2441 UINTN AttemptConfigOrderSize
;
2443 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
2445 VOID
*StartOpCodeHandle
;
2446 EFI_IFR_GUID_LABEL
*StartLabel
;
2447 VOID
*EndOpCodeHandle
;
2448 EFI_IFR_GUID_LABEL
*EndLabel
;
2451 Status
= IScsiCreateOpCode (
2458 if (EFI_ERROR (Status
)) {
2462 AttemptConfigOrder
= IScsiGetVariableAndSize (
2465 &AttemptConfigOrderSize
2467 if (AttemptConfigOrder
!= NULL
) {
2469 // Create the check box opcode to be deleted.
2473 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
2474 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
2475 IfrNvData
->DeleteAttemptList
[Index
] = 0x00;
2477 HiiCreateCheckBoxOpCode(
2479 (EFI_QUESTION_ID
) (ATTEMPT_DEL_QUESTION_ID
+ Index
),
2480 CONFIGURATION_VARSTORE_ID
,
2481 (UINT16
) (ATTEMPT_DEL_VAR_OFFSET
+ Index
),
2482 AttemptConfigData
->AttemptTitleToken
,
2483 AttemptConfigData
->AttemptTitleHelpToken
,
2491 if (Index
== ISCSI_MAX_ATTEMPTS_NUM
) {
2496 FreePool (AttemptConfigOrder
);
2499 Status
= HiiUpdateForm (
2500 mCallbackInfo
->RegisteredHandle
, // HII handle
2501 &gIScsiConfigGuid
, // Formset GUID
2502 FORMID_DELETE_FORM
, // Form ID
2503 StartOpCodeHandle
, // Label for where to insert opcodes
2504 EndOpCodeHandle
// Replace data
2507 HiiFreeOpCodeHandle (StartOpCodeHandle
);
2508 HiiFreeOpCodeHandle (EndOpCodeHandle
);
2515 Callback function when user presses "Change Attempt Order".
2517 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
2518 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
2520 @retval EFI_SUCCESS The operation is completed successfully.
2524 IScsiConfigDisplayOrderAttempts (
2531 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
2532 VOID
*StartOpCodeHandle
;
2533 EFI_IFR_GUID_LABEL
*StartLabel
;
2534 VOID
*EndOpCodeHandle
;
2535 EFI_IFR_GUID_LABEL
*EndLabel
;
2536 VOID
*OptionsOpCodeHandle
;
2538 Status
= IScsiCreateOpCode (
2545 if (EFI_ERROR (Status
)) {
2548 ASSERT (StartOpCodeHandle
!= NULL
);
2550 OptionsOpCodeHandle
= NULL
;
2553 // If no attempt to be ordered, update the original form and exit.
2555 if (mPrivate
->AttemptCount
== 0) {
2560 // Create Option OpCode.
2562 OptionsOpCodeHandle
= HiiAllocateOpCodeHandle ();
2563 if (OptionsOpCodeHandle
== NULL
) {
2564 Status
= EFI_OUT_OF_RESOURCES
;
2570 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
2571 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
2572 HiiCreateOneOfOptionOpCode (
2573 OptionsOpCodeHandle
,
2574 AttemptConfigData
->AttemptTitleToken
,
2576 EFI_IFR_NUMERIC_SIZE_1
,
2577 AttemptConfigData
->AttemptConfigIndex
2582 ASSERT (Index
== mPrivate
->AttemptCount
);
2584 HiiCreateOrderedListOpCode (
2585 StartOpCodeHandle
, // Container for dynamic created opcodes
2586 DYNAMIC_ORDERED_LIST_QUESTION_ID
, // Question ID
2587 CONFIGURATION_VARSTORE_ID
, // VarStore ID
2588 DYNAMIC_ORDERED_LIST_VAR_OFFSET
, // Offset in Buffer Storage
2589 STRING_TOKEN (STR_ORDER_ATTEMPT_ENTRY
), // Question prompt text
2590 STRING_TOKEN (STR_ORDER_ATTEMPT_ENTRY
), // Question help text
2592 EFI_IFR_UNIQUE_SET
, // Ordered list flag, e.g. EFI_IFR_UNIQUE_SET
2593 EFI_IFR_NUMERIC_SIZE_1
, // Data type of Question value
2594 ISCSI_MAX_ATTEMPTS_NUM
, // Maximum container
2595 OptionsOpCodeHandle
, // Option Opcode list
2596 NULL
// Default Opcode is NULL
2600 Status
= HiiUpdateForm (
2601 mCallbackInfo
->RegisteredHandle
, // HII handle
2602 &gIScsiConfigGuid
, // Formset GUID
2603 FORMID_ORDER_FORM
, // Form ID
2604 StartOpCodeHandle
, // Label for where to insert opcodes
2605 EndOpCodeHandle
// Replace data
2609 HiiFreeOpCodeHandle (StartOpCodeHandle
);
2610 HiiFreeOpCodeHandle (EndOpCodeHandle
);
2611 if (OptionsOpCodeHandle
!= NULL
) {
2612 HiiFreeOpCodeHandle (OptionsOpCodeHandle
);
2619 Callback function when user presses "Commit Changes and Exit" in Change Attempt Order or Change Attempt Order by Keyword.
2621 @param[in] IfrNvData The IFR nv data.
2623 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
2625 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
2626 @retval EFI_SUCCESS The operation is completed successfully.
2630 IScsiConfigOrderAttempts (
2631 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
2637 UINT8 AttemptConfigIndex
;
2638 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
2639 UINT8
*AttemptConfigOrder
;
2640 UINT8
*AttemptConfigOrderTmp
;
2641 UINTN AttemptConfigOrderSize
;
2643 AttemptConfigOrder
= IScsiGetVariableAndSize (
2646 &AttemptConfigOrderSize
2648 if (AttemptConfigOrder
== NULL
) {
2649 return EFI_NOT_FOUND
;
2652 AttemptConfigOrderTmp
= AllocateZeroPool (AttemptConfigOrderSize
);
2653 if (AttemptConfigOrderTmp
== NULL
) {
2654 Status
= EFI_OUT_OF_RESOURCES
;
2658 for (Index
= 0; Index
< ISCSI_MAX_ATTEMPTS_NUM
; Index
++) {
2660 // The real content ends with 0.
2662 if (IfrNvData
->DynamicOrderedList
[Index
] == 0) {
2666 AttemptConfigIndex
= IfrNvData
->DynamicOrderedList
[Index
];
2667 AttemptConfigData
= IScsiConfigGetAttemptByConfigIndex (AttemptConfigIndex
);
2668 if (AttemptConfigData
== NULL
) {
2669 Status
= EFI_NOT_FOUND
;
2674 // Reorder the Attempt List.
2676 RemoveEntryList (&AttemptConfigData
->Link
);
2677 InsertTailList (&mPrivate
->AttemptConfigs
, &AttemptConfigData
->Link
);
2679 AttemptConfigOrderTmp
[Index
] = AttemptConfigIndex
;
2682 // Mark it to be deleted - 0.
2684 for (Indexj
= 0; Indexj
< AttemptConfigOrderSize
/ sizeof (UINT8
); Indexj
++) {
2685 if (AttemptConfigOrder
[Indexj
] == AttemptConfigIndex
) {
2686 AttemptConfigOrder
[Indexj
] = 0;
2693 // Adjust the attempt order in NVR.
2695 for (; Index
< AttemptConfigOrderSize
/ sizeof (UINT8
); Index
++) {
2696 for (Indexj
= 0; Indexj
< AttemptConfigOrderSize
/ sizeof (UINT8
); Indexj
++) {
2697 if (AttemptConfigOrder
[Indexj
] != 0) {
2698 AttemptConfigOrderTmp
[Index
] = AttemptConfigOrder
[Indexj
];
2699 AttemptConfigOrder
[Indexj
] = 0;
2705 Status
= gRT
->SetVariable (
2708 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
2709 AttemptConfigOrderSize
,
2710 AttemptConfigOrderTmp
2714 if (AttemptConfigOrderTmp
!= NULL
) {
2715 FreePool (AttemptConfigOrderTmp
);
2718 FreePool (AttemptConfigOrder
);
2724 Callback function when a user presses "Attempt *" or when a user selects a NIC to
2725 create the new attempt.
2727 @param[in] KeyValue A unique value which is sent to the original
2728 exporting driver so that it can identify the type
2730 @param[in] IfrNvData The IFR nv data.
2732 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
2734 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
2735 @retval EFI_UNSUPPORTED Can not create more attempts.
2736 @retval EFI_SUCCESS The operation is completed successfully.
2740 IScsiConfigProcessDefault (
2741 IN EFI_QUESTION_ID KeyValue
,
2742 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
2746 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
2747 UINT8 CurrentAttemptConfigIndex
;
2748 ISCSI_NIC_INFO
*NicInfo
;
2750 CHAR16 MacString
[ISCSI_MAX_MAC_STRING_LEN
];
2751 UINT8
*AttemptConfigOrder
;
2752 UINTN AttemptConfigOrderSize
;
2756 AttemptConfigData
= NULL
;
2758 // Is User creating a new attempt?
2762 if ((KeyValue
>= KEY_MAC_ENTRY_BASE
) &&
2763 (KeyValue
<= (UINT16
) (mPrivate
->MaxNic
+ KEY_MAC_ENTRY_BASE
))) {
2765 // User has pressed "Add an Attempt" and then selects a NIC.
2768 } else if ((KeyValue
>= KEY_ATTEMPT_ENTRY_BASE
) &&
2769 (KeyValue
< (ISCSI_MAX_ATTEMPTS_NUM
+ KEY_ATTEMPT_ENTRY_BASE
))) {
2772 // User has pressed "Attempt *".
2777 // Don't process anything.
2784 // Determine which NIC user has selected for the new created attempt.
2786 NicIndex
= (UINT8
) (KeyValue
- KEY_MAC_ENTRY_BASE
);
2787 NicInfo
= IScsiGetNicInfoByIndex (NicIndex
);
2788 if (NicInfo
== NULL
) {
2789 return EFI_NOT_FOUND
;
2793 // Create an attempt following the initialized attempt order.
2795 AttemptConfigOrder
= IScsiGetVariableAndSize (
2796 L
"InitialAttemptOrder",
2798 &AttemptConfigOrderSize
2801 if (AttemptConfigOrder
== NULL
) {
2802 return EFI_NOT_FOUND
;
2805 for (Index
= 0; Index
< AttemptConfigOrderSize
/ sizeof (UINT8
); Index
++) {
2807 mPrivate
->PortString
,
2808 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
2810 (UINTN
) AttemptConfigOrder
[Index
]
2813 mPrivate
->PortString
,
2814 &gEfiIScsiInitiatorNameProtocolGuid
,
2815 (VOID
**)&AttemptConfigData
,
2818 if (AttemptConfigData
== NULL
|| AttemptConfigData
->Actived
== ISCSI_ACTIVE_ENABLED
) {
2825 if (Index
> PcdGet8 (PcdMaxIScsiAttemptNumber
)) {
2827 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2829 L
"Can not create more attempts, Please configure the PcdMaxIScsiAttemptNumber if needed!",
2832 return EFI_UNSUPPORTED
;
2835 if (AttemptConfigOrder
!= NULL
) {
2836 FreePool (AttemptConfigOrder
);
2840 // Record the MAC info in Config Data.
2843 &NicInfo
->PermanentAddress
,
2844 NicInfo
->HwAddressSize
,
2849 ASSERT (AttemptConfigData
!= NULL
);
2850 UnicodeStrToAsciiStrS (MacString
, AttemptConfigData
->MacString
, sizeof (AttemptConfigData
->MacString
));
2851 AttemptConfigData
->NicIndex
= NicIndex
;
2852 AttemptConfigData
->Actived
= ISCSI_ACTIVE_ENABLED
;
2855 // Generate OUI-format ISID based on MAC address.
2857 CopyMem (AttemptConfigData
->SessionConfigData
.IsId
, &NicInfo
->PermanentAddress
, 6);
2858 AttemptConfigData
->SessionConfigData
.IsId
[0] =
2859 (UINT8
) (AttemptConfigData
->SessionConfigData
.IsId
[0] & 0x3F);
2862 // Add the help info for the new attempt.
2865 mPrivate
->PortString
,
2866 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
2867 L
"MAC: %s, PFA: Bus %d | Dev %d | Func %d",
2870 NicInfo
->DeviceNumber
,
2871 NicInfo
->FunctionNumber
2874 AttemptConfigData
->AttemptTitleHelpToken
= HiiSetString (
2875 mCallbackInfo
->RegisteredHandle
,
2877 mPrivate
->PortString
,
2880 if (AttemptConfigData
->AttemptTitleHelpToken
== 0) {
2881 FreePool (AttemptConfigData
);
2882 return EFI_OUT_OF_RESOURCES
;
2887 // Determine which Attempt user has selected to configure.
2888 // Get the attempt configuration data.
2890 CurrentAttemptConfigIndex
= (UINT8
) (KeyValue
- KEY_ATTEMPT_ENTRY_BASE
);
2892 AttemptConfigData
= IScsiConfigGetAttemptByConfigIndex (CurrentAttemptConfigIndex
);
2893 if (AttemptConfigData
== NULL
) {
2894 DEBUG ((DEBUG_ERROR
, "Corresponding configuration data can not be retrieved!\n"));
2895 return EFI_NOT_FOUND
;
2900 // Clear the old IFR data to avoid sharing it with other attempts.
2902 if (IfrNvData
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
2903 ZeroMem (IfrNvData
->CHAPName
, sizeof (IfrNvData
->CHAPName
));
2904 ZeroMem (IfrNvData
->CHAPSecret
, sizeof (IfrNvData
->CHAPSecret
));
2905 ZeroMem (IfrNvData
->ReverseCHAPName
, sizeof (IfrNvData
->ReverseCHAPName
));
2906 ZeroMem (IfrNvData
->ReverseCHAPSecret
, sizeof (IfrNvData
->ReverseCHAPSecret
));
2909 IScsiConvertAttemptConfigDataToIfrNvData (AttemptConfigData
, IfrNvData
);
2912 // Update current attempt to be a new created attempt or an existing attempt.
2914 mCallbackInfo
->Current
= AttemptConfigData
;
2922 This function allows the caller to request the current
2923 configuration for one or more named elements. The resulting
2924 string is in <ConfigAltResp> format. Also, any and all alternative
2925 configuration strings shall be appended to the end of the
2926 current configuration string. If they are, they must appear
2927 after the current configuration. They must contain the same
2928 routing (GUID, NAME, PATH) as the current configuration string.
2929 They must have an additional description indicating the type of
2930 alternative configuration the string represents,
2931 "ALTCFG=<StringToken>". That <StringToken> (when
2932 converted from Hex UNICODE to binary) is a reference to a
2933 string in the associated string pack.
2935 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
2937 @param[in] Request A null-terminated Unicode string in
2938 <ConfigRequest> format. Note that this
2939 includes the routing information as well as
2940 the configurable name / value pairs. It is
2941 invalid for this string to be in
2942 <MultiConfigRequest> format.
2944 @param[out] Progress On return, points to a character in the
2945 Request string. Points to the string's null
2946 terminator if request was successful. Points
2947 to the most recent "&" before the first
2948 failing name / value pair (or the beginning
2949 of the string if the failure is in the first
2950 name / value pair) if the request was not successful.
2952 @param[out] Results A null-terminated Unicode string in
2953 <ConfigAltResp> format which has all values
2954 filled in for the names in the Request string.
2955 String to be allocated by the called function.
2957 @retval EFI_SUCCESS The Results string is filled with the
2958 values corresponding to all requested
2961 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
2962 parts of the results that must be
2963 stored awaiting possible future
2966 @retval EFI_INVALID_PARAMETER For example, passing in a NULL
2967 for the Request parameter
2968 would result in this type of
2969 error. In this case, the
2970 Progress parameter would be
2973 @retval EFI_NOT_FOUND Routing data doesn't match any
2974 known driver. Progress set to the
2975 first character in the routing header.
2976 Note: There is no requirement that the
2977 driver validate the routing data. It
2978 must skip the <ConfigHdr> in order to
2981 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set
2982 to most recent "&" before the
2983 error or the beginning of the
2986 @retval EFI_INVALID_PARAMETER Unknown name. Progress points
2987 to the & before the name in
2993 IScsiFormExtractConfig (
2994 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
2995 IN CONST EFI_STRING Request
,
2996 OUT EFI_STRING
*Progress
,
2997 OUT EFI_STRING
*Results
3001 CHAR8
*InitiatorName
;
3003 ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
;
3004 ISCSI_FORM_CALLBACK_INFO
*Private
;
3005 EFI_STRING ConfigRequestHdr
;
3006 EFI_STRING ConfigRequest
;
3007 BOOLEAN AllocatedRequest
;
3010 if (This
== NULL
|| Progress
== NULL
|| Results
== NULL
) {
3011 return EFI_INVALID_PARAMETER
;
3014 *Progress
= Request
;
3015 if ((Request
!= NULL
) && !HiiIsConfigHdrMatch (Request
, &gIScsiConfigGuid
, mVendorStorageName
)) {
3016 return EFI_NOT_FOUND
;
3019 ConfigRequestHdr
= NULL
;
3020 ConfigRequest
= NULL
;
3021 AllocatedRequest
= FALSE
;
3024 Private
= ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This
);
3025 IfrNvData
= AllocateZeroPool (sizeof (ISCSI_CONFIG_IFR_NVDATA
));
3026 if (IfrNvData
== NULL
) {
3027 return EFI_OUT_OF_RESOURCES
;
3031 if (Private
->Current
!= NULL
) {
3032 IScsiConvertAttemptConfigDataToIfrNvData (Private
->Current
, IfrNvData
);
3036 // Extract all AttemptConfigData to Keyword stroage of IfrNvData.
3038 IScsiConvertAttemptConfigDataToIfrNvDataByKeyword (IfrNvData
);
3040 BufferSize
= ISCSI_NAME_MAX_SIZE
;
3041 InitiatorName
= (CHAR8
*) AllocateZeroPool (BufferSize
);
3042 if (InitiatorName
== NULL
) {
3043 FreePool (IfrNvData
);
3044 return EFI_OUT_OF_RESOURCES
;
3047 Status
= gIScsiInitiatorName
.Get (&gIScsiInitiatorName
, &BufferSize
, InitiatorName
);
3048 if (EFI_ERROR (Status
)) {
3049 IfrNvData
->InitiatorName
[0] = L
'\0';
3051 AsciiStrToUnicodeStrS (
3053 IfrNvData
->InitiatorName
,
3054 sizeof (IfrNvData
->InitiatorName
) / sizeof (IfrNvData
->InitiatorName
[0])
3059 // Convert buffer data to <ConfigResp> by helper function BlockToConfig().
3061 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
3062 ConfigRequest
= Request
;
3063 if ((Request
== NULL
) || (StrStr (Request
, L
"OFFSET") == NULL
)) {
3065 // Request has no request element, construct full request string.
3066 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
3067 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
3069 ConfigRequestHdr
= HiiConstructConfigHdr (&gIScsiConfigGuid
, mVendorStorageName
, Private
->DriverHandle
);
3070 Size
= (StrLen (ConfigRequestHdr
) + 32 + 1) * sizeof (CHAR16
);
3071 ConfigRequest
= AllocateZeroPool (Size
);
3072 if (ConfigRequest
== NULL
) {
3073 FreePool (IfrNvData
);
3074 FreePool (InitiatorName
);
3075 return EFI_OUT_OF_RESOURCES
;
3077 AllocatedRequest
= TRUE
;
3078 UnicodeSPrint (ConfigRequest
, Size
, L
"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr
, (UINT64
)BufferSize
);
3079 FreePool (ConfigRequestHdr
);
3082 Status
= gHiiConfigRouting
->BlockToConfig (
3085 (UINT8
*) IfrNvData
,
3090 FreePool (IfrNvData
);
3091 FreePool (InitiatorName
);
3094 // Free the allocated config request string.
3096 if (AllocatedRequest
) {
3097 FreePool (ConfigRequest
);
3098 ConfigRequest
= NULL
;
3101 // Set Progress string to the original request string.
3103 if (Request
== NULL
) {
3105 } else if (StrStr (Request
, L
"OFFSET") == NULL
) {
3106 *Progress
= Request
+ StrLen (Request
);
3115 This function applies changes in a driver's configuration.
3116 Input is a Configuration, which has the routing data for this
3117 driver followed by name / value configuration pairs. The driver
3118 must apply those pairs to its configurable storage. If the
3119 driver's configuration is stored in a linear block of data
3120 and the driver's name / value pairs are in <BlockConfig>
3121 format, it may use the ConfigToBlock helper function (above) to
3124 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
3126 @param[in] Configuration A null-terminated Unicode string in
3127 <ConfigString> format.
3129 @param[out] Progress A pointer to a string filled in with the
3130 offset of the most recent '&' before the
3131 first failing name / value pair (or the
3132 beginning of the string if the failure
3133 is in the first name / value pair) or
3134 the terminating NULL if all was
3137 @retval EFI_SUCCESS The results have been distributed or are
3138 awaiting distribution.
3140 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
3141 parts of the results that must be
3142 stored awaiting possible future
3145 @retval EFI_INVALID_PARAMETERS Passing in a NULL for the
3146 Results parameter would result
3147 in this type of error.
3149 @retval EFI_NOT_FOUND Target for the specified routing data
3155 IScsiFormRouteConfig (
3156 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
3157 IN CONST EFI_STRING Configuration
,
3158 OUT EFI_STRING
*Progress
3162 ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
;
3163 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
3165 LIST_ENTRY
*NextEntry
;
3166 ISCSI_NIC_INFO
*NicInfo
;
3168 CHAR16 MacString
[ISCSI_MAX_MAC_STRING_LEN
];
3169 CHAR8
*InitiatorName
;
3180 Status
= EFI_SUCCESS
;
3182 if (This
== NULL
|| Configuration
== NULL
|| Progress
== NULL
) {
3183 return EFI_INVALID_PARAMETER
;
3187 // Check routing data in <ConfigHdr>.
3188 // Note: if only one Storage is used, then this checking could be skipped.
3190 if (!HiiIsConfigHdrMatch (Configuration
, &gIScsiConfigGuid
, mVendorStorageName
)) {
3191 *Progress
= Configuration
;
3192 return EFI_NOT_FOUND
;
3195 IfrNvData
= AllocateZeroPool (sizeof (ISCSI_CONFIG_IFR_NVDATA
));
3196 if (IfrNvData
== NULL
) {
3197 return EFI_OUT_OF_RESOURCES
;
3200 BufferSize
= ISCSI_NAME_MAX_SIZE
;
3201 InitiatorName
= (CHAR8
*) AllocateZeroPool (BufferSize
);
3202 if (InitiatorName
== NULL
) {
3203 Status
= EFI_OUT_OF_RESOURCES
;
3208 // Convert <ConfigResp> to buffer data by helper function ConfigToBlock().
3210 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
3211 Status
= gHiiConfigRouting
->ConfigToBlock (
3214 (UINT8
*) IfrNvData
,
3218 if (EFI_ERROR (Status
)) {
3222 if (IfrNvData
->InitiatorName
[0] != L
'\0') {
3223 UnicodeStrToAsciiStrS (IfrNvData
->InitiatorName
, InitiatorName
, ISCSI_NAME_MAX_SIZE
);
3224 BufferSize
= AsciiStrSize (InitiatorName
);
3226 Status
= gIScsiInitiatorName
.Set (&gIScsiInitiatorName
, &BufferSize
, InitiatorName
);
3227 if (EFI_ERROR (Status
)) {
3229 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3231 L
"Invalid iSCSI Name!",
3237 Status
= IScsiGetValue (Configuration
, L
"&OFFSET=", &OffSet
);
3238 if (EFI_ERROR (Status
)) {
3242 if (OffSet
>= ATTEMPT_MAC_ADDR_VAR_OFFSET
) {
3243 Status
= gIScsiInitiatorName
.Get (&gIScsiInitiatorName
, &BufferSize
, InitiatorName
);
3244 if (EFI_ERROR (Status
)) {
3246 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3248 L
"Error: please configure iSCSI initiator name first!",
3257 if (IfrNvData
->ISCSIAddAttemptList
[0] != L
'\0') {
3258 Status
=IScsiGetAttemptIndexList (IfrNvData
->ISCSIAddAttemptList
, IfrNvData
->AddAttemptList
, TRUE
);
3259 if (EFI_ERROR (Status
)) {
3261 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3263 L
"Error: The add attempt list is invalid",
3269 Status
= IScsiConfigAddAttemptsByKeywords (IfrNvData
->AddAttemptList
);
3270 if (EFI_ERROR (Status
)) {
3274 } else if (IfrNvData
->ISCSIDeleteAttemptList
[0] != L
'\0') {
3275 AttemptList
=(UINT8
*) AllocateZeroPool ((ISCSI_MAX_ATTEMPTS_NUM
+ 1) * sizeof (UINT8
));
3276 if (AttemptList
== NULL
) {
3277 Status
= EFI_OUT_OF_RESOURCES
;
3280 Status
= IScsiGetAttemptIndexList (IfrNvData
->ISCSIDeleteAttemptList
, AttemptList
, FALSE
);
3281 if (EFI_ERROR (Status
)) {
3283 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3285 L
"Error: The delete attempt list is invalid",
3292 // Mark the attempt which will be delete in the global list.
3294 NET_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &mPrivate
->AttemptConfigs
) {
3295 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
3296 while (AttemptList
[Index
] != 0) {
3297 if (AttemptConfigData
->AttemptConfigIndex
== AttemptList
[Index
]) {
3298 IfrNvData
->DeleteAttemptList
[Index2
] = 1;
3307 Status
= IScsiConfigDeleteAttempts (IfrNvData
);
3308 if (EFI_ERROR (Status
)) {
3312 FreePool (AttemptList
);
3314 } else if (IfrNvData
->ISCSIAttemptOrder
[0] != L
'\0') {
3315 Status
= IScsiGetAttemptIndexList (IfrNvData
->ISCSIAttemptOrder
, IfrNvData
->DynamicOrderedList
, FALSE
);
3316 if (EFI_ERROR (Status
)) {
3318 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3320 L
"Error: The new attempt order list is invalid",
3326 Status
= IScsiConfigOrderAttempts (IfrNvData
);
3327 if (EFI_ERROR (Status
)) {
3331 } else if (IfrNvData
->ISCSIMacAddr
[0] != L
'\0') {
3332 NET_LIST_FOR_EACH (Entry
, &mPrivate
->NicInfoList
) {
3333 NicInfo
= NET_LIST_USER_STRUCT (Entry
, ISCSI_NIC_INFO
, Link
);
3335 &NicInfo
->PermanentAddress
,
3336 NicInfo
->HwAddressSize
,
3340 if (!StrCmp(MacString
, IfrNvData
->ISCSIMacAddr
)) {
3341 mPrivate
->CurrentNic
= NicInfo
->NicIndex
;
3346 if ((NicInfo
== NULL
) || (NicInfo
->NicIndex
== 0)) {
3347 Status
= EFI_NOT_FOUND
;
3352 Status
= IScsiConvertlfrNvDataToAttemptConfigDataByKeyword (IfrNvData
, OffSet
);
3353 if (EFI_ERROR (Status
)) {
3359 IScsiConfigUpdateAttempt ();
3362 if (InitiatorName
!= NULL
) {
3363 FreePool (InitiatorName
);
3366 if (IfrNvData
!= NULL
) {
3367 FreePool (IfrNvData
);
3375 This function is called to provide results data to the driver.
3376 This data consists of a unique key that is used to identify
3377 which data is either being passed back or being asked for.
3379 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
3380 @param[in] Action Specifies the type of action taken by the browser.
3381 @param[in] QuestionId A unique value which is sent to the original
3382 exporting driver so that it can identify the type
3383 of data to expect. The format of the data tends to
3384 vary based on the opcode that generated the callback.
3385 @param[in] Type The type of value for the question.
3386 @param[in, out] Value A pointer to the data being sent to the original
3388 @param[out] ActionRequest On return, points to the action requested by the
3391 @retval EFI_SUCCESS The callback successfully handled the action.
3392 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
3393 variable and its data.
3394 @retval EFI_DEVICE_ERROR The variable could not be saved.
3395 @retval EFI_UNSUPPORTED The specified Action is not supported by the
3401 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
3402 IN EFI_BROWSER_ACTION Action
,
3403 IN EFI_QUESTION_ID QuestionId
,
3405 IN OUT EFI_IFR_TYPE_VALUE
*Value
,
3406 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
3409 ISCSI_FORM_CALLBACK_INFO
*Private
;
3412 CHAR8 IpString
[ISCSI_NAME_MAX_SIZE
];
3413 CHAR8 LunString
[ISCSI_LUN_STR_MAX_LEN
];
3415 EFI_IP_ADDRESS HostIp
;
3416 EFI_IP_ADDRESS SubnetMask
;
3417 EFI_IP_ADDRESS Gateway
;
3418 ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
;
3419 ISCSI_CONFIG_IFR_NVDATA OldIfrNvData
;
3423 if ((Action
== EFI_BROWSER_ACTION_FORM_OPEN
) || (Action
== EFI_BROWSER_ACTION_FORM_CLOSE
)) {
3425 // Do nothing for UEFI OPEN/CLOSE Action
3430 if ((Action
!= EFI_BROWSER_ACTION_CHANGING
) && (Action
!= EFI_BROWSER_ACTION_CHANGED
)) {
3432 // All other type return unsupported.
3434 return EFI_UNSUPPORTED
;
3437 if ((Value
== NULL
) || (ActionRequest
== NULL
)) {
3438 return EFI_INVALID_PARAMETER
;
3441 Private
= ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This
);
3444 // Retrieve uncommitted data from Browser
3447 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
3448 IfrNvData
= AllocateZeroPool (BufferSize
);
3449 if (IfrNvData
== NULL
) {
3450 return EFI_OUT_OF_RESOURCES
;
3453 IScsiName
= (CHAR8
*) AllocateZeroPool (ISCSI_NAME_MAX_SIZE
);
3454 if (IScsiName
== NULL
) {
3455 FreePool (IfrNvData
);
3456 return EFI_OUT_OF_RESOURCES
;
3459 Status
= EFI_SUCCESS
;
3461 ZeroMem (&OldIfrNvData
, BufferSize
);
3463 HiiGetBrowserData (NULL
, NULL
, BufferSize
, (UINT8
*) IfrNvData
);
3465 CopyMem (&OldIfrNvData
, IfrNvData
, BufferSize
);
3467 if (Action
== EFI_BROWSER_ACTION_CHANGING
) {
3468 switch (QuestionId
) {
3469 case KEY_ADD_ATTEMPT
:
3471 // Check whether iSCSI initiator name is configured already.
3473 mPrivate
->InitiatorNameLength
= ISCSI_NAME_MAX_SIZE
;
3474 Status
= gIScsiInitiatorName
.Get (
3475 &gIScsiInitiatorName
,
3476 &mPrivate
->InitiatorNameLength
,
3477 mPrivate
->InitiatorName
3479 if (EFI_ERROR (Status
)) {
3481 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3483 L
"Error: please configure iSCSI initiator name first!",
3489 Status
= IScsiConfigAddAttempt ();
3492 case KEY_DELETE_ATTEMPT
:
3494 OldIfrNvData
.DeleteAttemptList
,
3495 IfrNvData
->DeleteAttemptList
,
3496 sizeof (IfrNvData
->DeleteAttemptList
)
3498 Status
= IScsiConfigDisplayDeleteAttempts (IfrNvData
);
3501 case KEY_ORDER_ATTEMPT_CONFIG
:
3503 // Order the attempt according to user input.
3506 OldIfrNvData
.DynamicOrderedList
,
3507 IfrNvData
->DynamicOrderedList
,
3508 sizeof (IfrNvData
->DynamicOrderedList
)
3510 IScsiConfigDisplayOrderAttempts ();
3514 Status
= IScsiConfigProcessDefault (QuestionId
, IfrNvData
);
3517 } else if (Action
== EFI_BROWSER_ACTION_CHANGED
) {
3518 switch (QuestionId
) {
3519 case KEY_INITIATOR_NAME
:
3520 UnicodeStrToAsciiStrS (IfrNvData
->InitiatorName
, IScsiName
, ISCSI_NAME_MAX_SIZE
);
3521 BufferSize
= AsciiStrSize (IScsiName
);
3523 Status
= gIScsiInitiatorName
.Set (&gIScsiInitiatorName
, &BufferSize
, IScsiName
);
3524 if (EFI_ERROR (Status
)) {
3526 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3528 L
"Invalid iSCSI Name!",
3533 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
3536 case KEY_SAVE_ATTEMPT_CONFIG
:
3537 Status
= IScsiConvertIfrNvDataToAttemptConfigData (IfrNvData
, Private
->Current
);
3538 if (EFI_ERROR (Status
)) {
3542 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT
;
3545 case KEY_SAVE_ORDER_CHANGES
:
3547 // Sync the Attempt Order to NVR.
3549 Status
= IScsiConfigOrderAttempts (IfrNvData
);
3550 if (EFI_ERROR (Status
)) {
3554 IScsiConfigUpdateAttempt ();
3555 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT
;
3558 case KEY_IGNORE_ORDER_CHANGES
:
3560 IfrNvData
->DynamicOrderedList
,
3561 OldIfrNvData
.DynamicOrderedList
,
3562 sizeof (IfrNvData
->DynamicOrderedList
)
3564 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT
;
3567 case KEY_SAVE_DELETE_ATTEMPT
:
3569 // Delete the Attempt Order from NVR
3571 Status
= IScsiConfigDeleteAttempts (IfrNvData
);
3572 if (EFI_ERROR (Status
)) {
3576 IScsiConfigUpdateAttempt ();
3577 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT
;
3580 case KEY_IGNORE_DELETE_ATTEMPT
:
3582 IfrNvData
->DeleteAttemptList
,
3583 OldIfrNvData
.DeleteAttemptList
,
3584 sizeof (IfrNvData
->DeleteAttemptList
)
3586 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT
;
3590 switch (Value
->u8
) {
3593 ZeroMem (IfrNvData
->TargetIp
, sizeof (IfrNvData
->TargetIp
));
3594 Private
->Current
->AutoConfigureMode
= 0;
3602 Status
= NetLibStrToIp4 (IfrNvData
->LocalIp
, &HostIp
.v4
);
3603 if (EFI_ERROR (Status
) ||
3604 ((Private
->Current
->SessionConfigData
.SubnetMask
.Addr
[0] != 0) &&
3605 !NetIp4IsUnicast (NTOHL (HostIp
.Addr
[0]), NTOHL(*(UINT32
*)Private
->Current
->SessionConfigData
.SubnetMask
.Addr
)))) {
3607 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3609 L
"Invalid IP address!",
3613 Status
= EFI_INVALID_PARAMETER
;
3615 CopyMem (&Private
->Current
->SessionConfigData
.LocalIp
, &HostIp
.v4
, sizeof (HostIp
.v4
));
3620 case KEY_SUBNET_MASK
:
3621 Status
= NetLibStrToIp4 (IfrNvData
->SubnetMask
, &SubnetMask
.v4
);
3622 if (EFI_ERROR (Status
) || ((SubnetMask
.Addr
[0] != 0) && (IScsiGetSubnetMaskPrefixLength (&SubnetMask
.v4
) == 0))) {
3624 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3626 L
"Invalid Subnet Mask!",
3630 Status
= EFI_INVALID_PARAMETER
;
3632 CopyMem (&Private
->Current
->SessionConfigData
.SubnetMask
, &SubnetMask
.v4
, sizeof (SubnetMask
.v4
));
3638 Status
= NetLibStrToIp4 (IfrNvData
->Gateway
, &Gateway
.v4
);
3639 if (EFI_ERROR (Status
) ||
3640 ((Gateway
.Addr
[0] != 0) &&
3641 (Private
->Current
->SessionConfigData
.SubnetMask
.Addr
[0] != 0) &&
3642 !NetIp4IsUnicast (NTOHL (Gateway
.Addr
[0]), NTOHL(*(UINT32
*)Private
->Current
->SessionConfigData
.SubnetMask
.Addr
)))) {
3644 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3646 L
"Invalid Gateway!",
3649 Status
= EFI_INVALID_PARAMETER
;
3651 CopyMem (&Private
->Current
->SessionConfigData
.Gateway
, &Gateway
.v4
, sizeof (Gateway
.v4
));
3657 UnicodeStrToAsciiStrS (IfrNvData
->TargetIp
, IpString
, sizeof (IpString
));
3658 Status
= IScsiAsciiStrToIp (IpString
, IfrNvData
->IpMode
, &HostIp
);
3659 if (EFI_ERROR (Status
) || !IpIsUnicast (&HostIp
, IfrNvData
->IpMode
)) {
3661 // The target is expressed in URL format or an invalid Ip address, just save.
3663 Private
->Current
->SessionConfigData
.DnsMode
= TRUE
;
3664 ZeroMem (&Private
->Current
->SessionConfigData
.TargetIp
, sizeof (Private
->Current
->SessionConfigData
.TargetIp
));
3665 UnicodeStrToAsciiStrS (IfrNvData
->TargetIp
, Private
->Current
->SessionConfigData
.TargetUrl
, ISCSI_NAME_MAX_SIZE
);
3667 Private
->Current
->SessionConfigData
.DnsMode
= FALSE
;
3668 CopyMem (&Private
->Current
->SessionConfigData
.TargetIp
, &HostIp
, sizeof (HostIp
));
3673 case KEY_TARGET_NAME
:
3674 UnicodeStrToAsciiStrS (IfrNvData
->TargetName
, IScsiName
, ISCSI_NAME_MAX_SIZE
);
3675 Status
= IScsiNormalizeName (IScsiName
, AsciiStrLen (IScsiName
));
3676 if (EFI_ERROR (Status
)) {
3678 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3680 L
"Invalid iSCSI Name!",
3684 AsciiStrCpyS (Private
->Current
->SessionConfigData
.TargetName
, ISCSI_NAME_MAX_SIZE
, IScsiName
);
3689 case KEY_DHCP_ENABLE
:
3690 if (IfrNvData
->InitiatorInfoFromDhcp
== 0) {
3691 IfrNvData
->TargetInfoFromDhcp
= 0;
3697 UnicodeStrToAsciiStrS (IfrNvData
->BootLun
, LunString
, sizeof (LunString
));
3698 Status
= IScsiAsciiStrToLun (LunString
, (UINT8
*) &Lun
);
3699 if (EFI_ERROR (Status
)) {
3701 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3703 L
"Invalid LUN string!",
3707 CopyMem (Private
->Current
->SessionConfigData
.BootLun
, &Lun
, sizeof (Lun
));
3713 switch (Value
->u8
) {
3714 case ISCSI_AUTH_TYPE_CHAP
:
3715 IfrNvData
->CHAPType
= ISCSI_CHAP_UNI
;
3724 UnicodeStrToAsciiStrS (
3725 IfrNvData
->CHAPName
,
3726 Private
->Current
->AuthConfigData
.CHAP
.CHAPName
,
3727 sizeof (Private
->Current
->AuthConfigData
.CHAP
.CHAPName
)
3731 case KEY_CHAP_SECRET
:
3732 UnicodeStrToAsciiStrS (
3733 IfrNvData
->CHAPSecret
,
3734 Private
->Current
->AuthConfigData
.CHAP
.CHAPSecret
,
3735 sizeof (Private
->Current
->AuthConfigData
.CHAP
.CHAPSecret
)
3739 case KEY_REVERSE_CHAP_NAME
:
3740 UnicodeStrToAsciiStrS (
3741 IfrNvData
->ReverseCHAPName
,
3742 Private
->Current
->AuthConfigData
.CHAP
.ReverseCHAPName
,
3743 sizeof (Private
->Current
->AuthConfigData
.CHAP
.ReverseCHAPName
)
3747 case KEY_REVERSE_CHAP_SECRET
:
3748 UnicodeStrToAsciiStrS (
3749 IfrNvData
->ReverseCHAPSecret
,
3750 Private
->Current
->AuthConfigData
.CHAP
.ReverseCHAPSecret
,
3751 sizeof (Private
->Current
->AuthConfigData
.CHAP
.ReverseCHAPSecret
)
3755 case KEY_CONFIG_ISID
:
3756 IScsiParseIsIdFromString (IfrNvData
->IsId
, Private
->Current
->SessionConfigData
.IsId
);
3757 IScsiConvertIsIdToString (IfrNvData
->IsId
, Private
->Current
->SessionConfigData
.IsId
);
3766 if (!EFI_ERROR (Status
)) {
3768 // Pass changed uncommitted data back to Form Browser.
3770 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
3771 HiiSetBrowserData (NULL
, NULL
, BufferSize
, (UINT8
*) IfrNvData
, NULL
);
3774 FreePool (IfrNvData
);
3775 FreePool (IScsiName
);
3782 Initialize the iSCSI configuration form.
3784 @param[in] DriverBindingHandle The iSCSI driverbinding handle.
3786 @retval EFI_SUCCESS The iSCSI configuration form is initialized.
3787 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
3791 IScsiConfigFormInit (
3792 IN EFI_HANDLE DriverBindingHandle
3796 ISCSI_FORM_CALLBACK_INFO
*CallbackInfo
;
3798 CallbackInfo
= (ISCSI_FORM_CALLBACK_INFO
*) AllocateZeroPool (sizeof (ISCSI_FORM_CALLBACK_INFO
));
3799 if (CallbackInfo
== NULL
) {
3800 return EFI_OUT_OF_RESOURCES
;
3803 CallbackInfo
->Signature
= ISCSI_FORM_CALLBACK_INFO_SIGNATURE
;
3804 CallbackInfo
->Current
= NULL
;
3806 CallbackInfo
->ConfigAccess
.ExtractConfig
= IScsiFormExtractConfig
;
3807 CallbackInfo
->ConfigAccess
.RouteConfig
= IScsiFormRouteConfig
;
3808 CallbackInfo
->ConfigAccess
.Callback
= IScsiFormCallback
;
3811 // Install Device Path Protocol and Config Access protocol to driver handle.
3813 Status
= gBS
->InstallMultipleProtocolInterfaces (
3814 &CallbackInfo
->DriverHandle
,
3815 &gEfiDevicePathProtocolGuid
,
3816 &mIScsiHiiVendorDevicePath
,
3817 &gEfiHiiConfigAccessProtocolGuid
,
3818 &CallbackInfo
->ConfigAccess
,
3821 ASSERT_EFI_ERROR (Status
);
3824 // Publish our HII data.
3826 CallbackInfo
->RegisteredHandle
= HiiAddPackages (
3828 CallbackInfo
->DriverHandle
,
3833 if (CallbackInfo
->RegisteredHandle
== NULL
) {
3834 gBS
->UninstallMultipleProtocolInterfaces (
3835 &CallbackInfo
->DriverHandle
,
3836 &gEfiDevicePathProtocolGuid
,
3837 &mIScsiHiiVendorDevicePath
,
3838 &gEfiHiiConfigAccessProtocolGuid
,
3839 &CallbackInfo
->ConfigAccess
,
3842 FreePool(CallbackInfo
);
3843 return EFI_OUT_OF_RESOURCES
;
3846 mCallbackInfo
= CallbackInfo
;
3853 Unload the iSCSI configuration form, this includes: delete all the iSCSI
3854 configuration entries, uninstall the form callback protocol, and
3855 free the resources used.
3857 @param[in] DriverBindingHandle The iSCSI driverbinding handle.
3859 @retval EFI_SUCCESS The iSCSI configuration form is unloaded.
3860 @retval Others Failed to unload the form.
3864 IScsiConfigFormUnload (
3865 IN EFI_HANDLE DriverBindingHandle
3868 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
3869 ISCSI_NIC_INFO
*NicInfo
;
3873 while (!IsListEmpty (&mPrivate
->AttemptConfigs
)) {
3874 Entry
= NetListRemoveHead (&mPrivate
->AttemptConfigs
);
3875 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
3876 FreePool (AttemptConfigData
);
3877 mPrivate
->AttemptCount
--;
3880 ASSERT (mPrivate
->AttemptCount
== 0);
3882 while (!IsListEmpty (&mPrivate
->NicInfoList
)) {
3883 Entry
= NetListRemoveHead (&mPrivate
->NicInfoList
);
3884 NicInfo
= NET_LIST_USER_STRUCT (Entry
, ISCSI_NIC_INFO
, Link
);
3886 mPrivate
->NicCount
--;
3889 ASSERT (mPrivate
->NicCount
== 0);
3891 FreePool (mPrivate
);
3895 // Remove HII package list.
3897 HiiRemovePackages (mCallbackInfo
->RegisteredHandle
);
3900 // Uninstall Device Path Protocol and Config Access protocol.
3902 Status
= gBS
->UninstallMultipleProtocolInterfaces (
3903 mCallbackInfo
->DriverHandle
,
3904 &gEfiDevicePathProtocolGuid
,
3905 &mIScsiHiiVendorDevicePath
,
3906 &gEfiHiiConfigAccessProtocolGuid
,
3907 &mCallbackInfo
->ConfigAccess
,
3911 FreePool (mCallbackInfo
);