2 Helper functions for configuring or getting the parameters relating to iSCSI.
4 Copyright (c) 2004 - 2018, 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 ZeroMem (IfrNvData
->TargetIp
, sizeof (IfrNvData
->TargetIp
));
545 if (SessionConfigData
->TargetIp
.v4
.Addr
[0] != '\0') {
546 CopyMem (&Ip
.v4
, &SessionConfigData
->TargetIp
, sizeof (EFI_IPv4_ADDRESS
));
547 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->TargetIp
);
550 } else if (IfrNvData
->IpMode
== IP_MODE_IP6
) {
551 ZeroMem (IfrNvData
->TargetIp
, sizeof (IfrNvData
->TargetIp
));
552 if (SessionConfigData
->TargetIp
.v6
.Addr
[0] != '\0') {
553 IP6_COPY_ADDRESS (&Ip
.v6
, &SessionConfigData
->TargetIp
);
554 IScsiIpToStr (&Ip
, TRUE
, IfrNvData
->TargetIp
);
558 AsciiStrToUnicodeStrS (
559 SessionConfigData
->TargetName
,
560 IfrNvData
->TargetName
,
561 sizeof (IfrNvData
->TargetName
) / sizeof (IfrNvData
->TargetName
[0])
565 AsciiStrToUnicodeStrS (
566 SessionConfigData
->TargetUrl
,
568 sizeof (IfrNvData
->TargetIp
) / sizeof (IfrNvData
->TargetIp
[0])
572 IScsiLunToUnicodeStr (SessionConfigData
->BootLun
, IfrNvData
->BootLun
);
573 IScsiConvertIsIdToString (IfrNvData
->IsId
, SessionConfigData
->IsId
);
575 IfrNvData
->ConnectRetryCount
= SessionConfigData
->ConnectRetryCount
;
576 IfrNvData
->ConnectTimeout
= SessionConfigData
->ConnectTimeout
;
579 // Authentication parameters.
581 IfrNvData
->AuthenticationType
= Attempt
->AuthenticationType
;
583 if (IfrNvData
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
584 AuthConfigData
= &Attempt
->AuthConfigData
.CHAP
;
585 IfrNvData
->CHAPType
= AuthConfigData
->CHAPType
;
586 AsciiStrToUnicodeStrS (
587 AuthConfigData
->CHAPName
,
589 sizeof (IfrNvData
->CHAPName
) / sizeof (IfrNvData
->CHAPName
[0])
591 AsciiStrToUnicodeStrS (
592 AuthConfigData
->CHAPSecret
,
593 IfrNvData
->CHAPSecret
,
594 sizeof (IfrNvData
->CHAPSecret
) / sizeof (IfrNvData
->CHAPSecret
[0])
596 AsciiStrToUnicodeStrS (
597 AuthConfigData
->ReverseCHAPName
,
598 IfrNvData
->ReverseCHAPName
,
599 sizeof (IfrNvData
->ReverseCHAPName
) / sizeof (IfrNvData
->ReverseCHAPName
[0])
601 AsciiStrToUnicodeStrS (
602 AuthConfigData
->ReverseCHAPSecret
,
603 IfrNvData
->ReverseCHAPSecret
,
604 sizeof (IfrNvData
->ReverseCHAPSecret
) / sizeof (IfrNvData
->ReverseCHAPSecret
[0])
611 AsciiStrToUnicodeStrS (
612 Attempt
->AttemptName
,
613 IfrNvData
->AttemptName
,
614 sizeof (IfrNvData
->AttemptName
) / sizeof (IfrNvData
->AttemptName
[0])
619 Convert the iSCSI configuration data into the IFR data Which will be used
620 to extract the iSCSI Keyword configuration in <ConfigAltResp> format.
622 @param[in, out] IfrNvData The IFR nv data.
627 IScsiConvertAttemptConfigDataToIfrNvDataByKeyword (
628 IN OUT ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
632 ISCSI_ATTEMPT_CONFIG_NVDATA
*Attempt
;
633 ISCSI_SESSION_CONFIG_NVDATA
*SessionConfigData
;
634 ISCSI_CHAP_AUTH_CONFIG_NVDATA
*AuthConfigData
;
635 CHAR16 AttemptNameList
[ATTEMPT_NAME_LIST_SIZE
];
636 ISCSI_NIC_INFO
*NicInfo
;
637 CHAR16 MacString
[ISCSI_MAX_MAC_STRING_LEN
];
643 ZeroMem (AttemptNameList
, sizeof (AttemptNameList
));
645 if ((mPrivate
!= NULL
) && (mPrivate
->AttemptCount
!= 0)) {
646 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
647 Attempt
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
649 // Normal session configuration parameters.
651 SessionConfigData
= &Attempt
->SessionConfigData
;
653 ASSERT ((Attempt
->AttemptConfigIndex
> 0) && (Attempt
->AttemptConfigIndex
<= FixedPcdGet8 (PcdMaxIScsiAttemptNumber
)));
654 Index
= Attempt
->AttemptConfigIndex
- 1;
657 // Save the attempt to AttemptNameList as Attempt:1 Attempt:2
659 AsciiStrToUnicodeStrS (
660 Attempt
->AttemptName
,
661 AttemptNameList
+ StrLen (AttemptNameList
),
662 ATTEMPT_NAME_LIST_SIZE
- StrLen (AttemptNameList
)
665 StringLen
= StrLen (AttemptNameList
);
666 ASSERT (StringLen
> 2);
667 *(AttemptNameList
+ StringLen
- 2) = L
':';
668 *(AttemptNameList
+ StringLen
) = L
' ';
670 AsciiStrToUnicodeStrS (
671 Attempt
->AttemptName
,
672 IfrNvData
->ISCSIAttemptName
+ ATTEMPT_NAME_SIZE
* Index
,
673 ATTEMPT_NAME_LIST_SIZE
- ATTEMPT_NAME_SIZE
* Index
676 IfrNvData
->ISCSIBootEnableList
[Index
] = SessionConfigData
->Enabled
;
677 IfrNvData
->ISCSIIpAddressTypeList
[Index
] = SessionConfigData
->IpMode
;
679 IfrNvData
->ISCSIInitiatorInfoViaDHCP
[Index
] = SessionConfigData
->InitiatorInfoFromDhcp
;
680 IfrNvData
->ISCSITargetInfoViaDHCP
[Index
] = SessionConfigData
->TargetInfoFromDhcp
;
681 IfrNvData
->ISCSIConnectRetry
[Index
] = SessionConfigData
->ConnectRetryCount
;
682 IfrNvData
->ISCSIConnectTimeout
[Index
] = SessionConfigData
->ConnectTimeout
;
683 IfrNvData
->ISCSITargetTcpPort
[Index
] = SessionConfigData
->TargetPort
;
685 if (SessionConfigData
->IpMode
== IP_MODE_IP4
) {
686 CopyMem (&Ip
.v4
, &SessionConfigData
->LocalIp
, sizeof (EFI_IPv4_ADDRESS
));
687 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->Keyword
[Index
].ISCSIInitiatorIpAddress
);
688 CopyMem (&Ip
.v4
, &SessionConfigData
->SubnetMask
, sizeof (EFI_IPv4_ADDRESS
));
689 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->Keyword
[Index
].ISCSIInitiatorNetmask
);
690 CopyMem (&Ip
.v4
, &SessionConfigData
->Gateway
, sizeof (EFI_IPv4_ADDRESS
));
691 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->Keyword
[Index
].ISCSIInitiatorGateway
);
692 if (SessionConfigData
->TargetIp
.v4
.Addr
[0] != '\0') {
693 CopyMem (&Ip
.v4
, &SessionConfigData
->TargetIp
, sizeof (EFI_IPv4_ADDRESS
));
694 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->Keyword
[Index
].ISCSITargetIpAddress
);
696 } else if (SessionConfigData
->IpMode
== IP_MODE_IP6
) {
697 ZeroMem (IfrNvData
->Keyword
[Index
].ISCSITargetIpAddress
, sizeof (IfrNvData
->TargetIp
));
698 if (SessionConfigData
->TargetIp
.v6
.Addr
[0] != '\0') {
699 IP6_COPY_ADDRESS (&Ip
.v6
, &SessionConfigData
->TargetIp
);
700 IScsiIpToStr (&Ip
, TRUE
, IfrNvData
->Keyword
[Index
].ISCSITargetIpAddress
);
704 AsciiStrToUnicodeStrS (
705 SessionConfigData
->TargetName
,
706 IfrNvData
->Keyword
[Index
].ISCSITargetName
,
710 if (SessionConfigData
->DnsMode
) {
711 AsciiStrToUnicodeStrS (
712 SessionConfigData
->TargetUrl
,
713 IfrNvData
->Keyword
[Index
].ISCSITargetIpAddress
,
714 sizeof (IfrNvData
->Keyword
[Index
].ISCSITargetIpAddress
) / sizeof (IfrNvData
->Keyword
[Index
].ISCSITargetIpAddress
[0])
718 IScsiLunToUnicodeStr (SessionConfigData
->BootLun
, IfrNvData
->Keyword
[Index
].ISCSILun
);
719 IScsiConvertIsIdToString (IfrNvData
->Keyword
[Index
].ISCSIIsId
, SessionConfigData
->IsId
);
721 IfrNvData
->ISCSIAuthenticationMethod
[Index
] = Attempt
->AuthenticationType
;
723 if (Attempt
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
724 AuthConfigData
= &Attempt
->AuthConfigData
.CHAP
;
725 IfrNvData
->ISCSIChapType
[Index
] = AuthConfigData
->CHAPType
;
726 AsciiStrToUnicodeStrS (
727 AuthConfigData
->CHAPName
,
728 IfrNvData
->Keyword
[Index
].ISCSIChapUsername
,
729 ISCSI_CHAP_NAME_STORAGE
732 AsciiStrToUnicodeStrS (
733 AuthConfigData
->CHAPSecret
,
734 IfrNvData
->Keyword
[Index
].ISCSIChapSecret
,
735 ISCSI_CHAP_SECRET_STORAGE
738 AsciiStrToUnicodeStrS (
739 AuthConfigData
->ReverseCHAPName
,
740 IfrNvData
->Keyword
[Index
].ISCSIReverseChapUsername
,
741 ISCSI_CHAP_NAME_STORAGE
744 AsciiStrToUnicodeStrS (
745 AuthConfigData
->ReverseCHAPSecret
,
746 IfrNvData
->Keyword
[Index
].ISCSIReverseChapSecret
,
747 ISCSI_CHAP_SECRET_STORAGE
751 CopyMem(IfrNvData
->ISCSIDisplayAttemptList
, AttemptNameList
, ATTEMPT_NAME_LIST_SIZE
);
753 ZeroMem (IfrNvData
->ISCSIMacAddr
, sizeof (IfrNvData
->ISCSIMacAddr
));
754 NET_LIST_FOR_EACH (Entry
, &mPrivate
->NicInfoList
) {
755 NicInfo
= NET_LIST_USER_STRUCT (Entry
, ISCSI_NIC_INFO
, Link
);
757 &NicInfo
->PermanentAddress
,
758 NicInfo
->HwAddressSize
,
763 IfrNvData
->ISCSIMacAddr
+ StrLen (IfrNvData
->ISCSIMacAddr
),
765 StrLen (MacString
) * sizeof (CHAR16
)
768 *(IfrNvData
->ISCSIMacAddr
+ StrLen (IfrNvData
->ISCSIMacAddr
)) = L
'/';
771 StringLen
= StrLen (IfrNvData
->ISCSIMacAddr
);
773 *(IfrNvData
->ISCSIMacAddr
+ StringLen
- 1) = L
'\0';
779 Convert the IFR data to iSCSI configuration data.
781 @param[in] IfrNvData Point to ISCSI_CONFIG_IFR_NVDATA.
782 @param[in, out] Attempt The iSCSI attempt config data.
784 @retval EFI_INVALID_PARAMETER Any input or configured parameter is invalid.
785 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
786 @retval EFI_OUT_OF_RESOURCES The operation is failed due to lack of resources.
787 @retval EFI_ABORTED The operation is aborted.
788 @retval EFI_SUCCESS The operation is completed successfully.
792 IScsiConvertIfrNvDataToAttemptConfigData (
793 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
,
794 IN OUT ISCSI_ATTEMPT_CONFIG_NVDATA
*Attempt
797 EFI_IP_ADDRESS HostIp
;
798 EFI_IP_ADDRESS SubnetMask
;
799 EFI_IP_ADDRESS Gateway
;
801 CHAR16
*AttemptName1
;
802 CHAR16
*AttemptName2
;
803 ISCSI_ATTEMPT_CONFIG_NVDATA
*ExistAttempt
;
804 ISCSI_ATTEMPT_CONFIG_NVDATA
*SameNicAttempt
;
805 CHAR16 IScsiMode
[64];
807 ISCSI_NIC_INFO
*NicInfo
;
809 UINT8
*AttemptConfigOrder
;
810 UINTN AttemptConfigOrderSize
;
811 UINT8
*AttemptOrderTmp
;
815 if (IfrNvData
== NULL
|| Attempt
== NULL
) {
816 return EFI_INVALID_PARAMETER
;
820 // Update those fields which don't have INTERACTIVE attribute.
822 Attempt
->SessionConfigData
.ConnectRetryCount
= IfrNvData
->ConnectRetryCount
;
823 Attempt
->SessionConfigData
.ConnectTimeout
= IfrNvData
->ConnectTimeout
;
824 Attempt
->SessionConfigData
.IpMode
= IfrNvData
->IpMode
;
826 if (IfrNvData
->IpMode
< IP_MODE_AUTOCONFIG
) {
827 Attempt
->SessionConfigData
.InitiatorInfoFromDhcp
= IfrNvData
->InitiatorInfoFromDhcp
;
828 Attempt
->SessionConfigData
.TargetPort
= IfrNvData
->TargetPort
;
830 if (Attempt
->SessionConfigData
.TargetPort
== 0) {
831 Attempt
->SessionConfigData
.TargetPort
= ISCSI_WELL_KNOWN_PORT
;
834 Attempt
->SessionConfigData
.TargetInfoFromDhcp
= IfrNvData
->TargetInfoFromDhcp
;
837 Attempt
->AuthenticationType
= IfrNvData
->AuthenticationType
;
839 if (Attempt
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
840 Attempt
->AuthConfigData
.CHAP
.CHAPType
= IfrNvData
->CHAPType
;
844 // Only do full parameter validation if iSCSI is enabled on this device.
846 if (IfrNvData
->Enabled
!= ISCSI_DISABLED
) {
847 if (Attempt
->SessionConfigData
.ConnectTimeout
< CONNECT_MIN_TIMEOUT
) {
849 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
851 L
"Connection Establishing Timeout is less than minimum value 100ms.",
855 return EFI_INVALID_PARAMETER
;
859 // Validate the address configuration of the Initiator if DHCP isn't
862 if (!Attempt
->SessionConfigData
.InitiatorInfoFromDhcp
) {
863 CopyMem (&HostIp
.v4
, &Attempt
->SessionConfigData
.LocalIp
, sizeof (HostIp
.v4
));
864 CopyMem (&SubnetMask
.v4
, &Attempt
->SessionConfigData
.SubnetMask
, sizeof (SubnetMask
.v4
));
865 CopyMem (&Gateway
.v4
, &Attempt
->SessionConfigData
.Gateway
, sizeof (Gateway
.v4
));
867 if ((Gateway
.Addr
[0] != 0)) {
868 if (SubnetMask
.Addr
[0] == 0) {
870 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
872 L
"Gateway address is set but subnet mask is zero.",
876 return EFI_INVALID_PARAMETER
;
877 } else if (!IP4_NET_EQUAL (HostIp
.Addr
[0], Gateway
.Addr
[0], SubnetMask
.Addr
[0])) {
879 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
881 L
"Local IP and Gateway are not in the same subnet.",
885 return EFI_INVALID_PARAMETER
;
890 // Validate target configuration if DHCP isn't deployed.
892 if (!Attempt
->SessionConfigData
.TargetInfoFromDhcp
&& Attempt
->SessionConfigData
.IpMode
< IP_MODE_AUTOCONFIG
) {
893 if (!Attempt
->SessionConfigData
.DnsMode
) {
894 if (!IpIsUnicast (&Attempt
->SessionConfigData
.TargetIp
, IfrNvData
->IpMode
)) {
896 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
898 L
"Target IP is invalid!",
901 return EFI_INVALID_PARAMETER
;
904 if (Attempt
->SessionConfigData
.TargetUrl
[0] == '\0') {
906 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
908 L
"iSCSI target Url should not be NULL!",
911 return EFI_INVALID_PARAMETER
;
916 // Validate iSCSI target name configuration again:
917 // The format of iSCSI target name is already verified in IScsiFormCallback() when
918 // user input the name; here we only check the case user does not input the name.
920 if (Attempt
->SessionConfigData
.TargetName
[0] == '\0') {
922 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
924 L
"iSCSI target name is NULL!",
927 return EFI_INVALID_PARAMETER
;
932 // Validate the authentication info.
934 if (IfrNvData
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
935 if ((IfrNvData
->CHAPName
[0] == '\0') || (IfrNvData
->CHAPSecret
[0] == '\0')) {
937 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
939 L
"CHAP Name or CHAP Secret is invalid!",
943 return EFI_INVALID_PARAMETER
;
946 if ((IfrNvData
->CHAPType
== ISCSI_CHAP_MUTUAL
) &&
947 ((IfrNvData
->ReverseCHAPName
[0] == '\0') || (IfrNvData
->ReverseCHAPSecret
[0] == '\0'))
950 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
952 L
"Reverse CHAP Name or Reverse CHAP Secret is invalid!",
955 return EFI_INVALID_PARAMETER
;
960 // Check whether this attempt uses NIC which is already used by existing attempt.
962 SameNicAttempt
= IScsiConfigGetAttemptByNic (Attempt
, IfrNvData
->Enabled
);
963 if (SameNicAttempt
!= NULL
) {
964 AttemptName1
= (CHAR16
*) AllocateZeroPool (ATTEMPT_NAME_SIZE
* sizeof (CHAR16
));
965 if (AttemptName1
== NULL
) {
966 return EFI_OUT_OF_RESOURCES
;
969 AttemptName2
= (CHAR16
*) AllocateZeroPool (ATTEMPT_NAME_SIZE
* sizeof (CHAR16
));
970 if (AttemptName2
== NULL
) {
971 FreePool (AttemptName1
);
972 return EFI_OUT_OF_RESOURCES
;
975 AsciiStrToUnicodeStrS (Attempt
->AttemptName
, AttemptName1
, ATTEMPT_NAME_SIZE
);
976 AsciiStrToUnicodeStrS (SameNicAttempt
->AttemptName
, AttemptName2
, ATTEMPT_NAME_SIZE
);
979 mPrivate
->PortString
,
980 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
981 L
"Warning! Attempt \"%s\" uses same NIC as Attempt \"%s\".",
987 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
989 mPrivate
->PortString
,
993 FreePool (AttemptName1
);
994 FreePool (AttemptName2
);
999 // Update the iSCSI Mode data and record it in attempt help info.
1001 if (IfrNvData
->Enabled
== ISCSI_DISABLED
) {
1002 UnicodeSPrint (IScsiMode
, 64, L
"Disabled");
1003 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
) {
1004 UnicodeSPrint (IScsiMode
, 64, L
"Enabled");
1005 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
1006 UnicodeSPrint (IScsiMode
, 64, L
"Enabled for MPIO");
1009 if (IfrNvData
->IpMode
== IP_MODE_IP4
) {
1010 UnicodeSPrint (IpMode
, 64, L
"IP4");
1011 } else if (IfrNvData
->IpMode
== IP_MODE_IP6
) {
1012 UnicodeSPrint (IpMode
, 64, L
"IP6");
1013 } else if (IfrNvData
->IpMode
== IP_MODE_AUTOCONFIG
) {
1014 UnicodeSPrint (IpMode
, 64, L
"Autoconfigure");
1017 NicInfo
= IScsiGetNicInfoByIndex (Attempt
->NicIndex
);
1018 if (NicInfo
== NULL
) {
1019 return EFI_NOT_FOUND
;
1022 MacString
= (CHAR16
*) AllocateZeroPool (ISCSI_MAX_MAC_STRING_LEN
* sizeof (CHAR16
));
1023 if (MacString
== NULL
) {
1024 return EFI_OUT_OF_RESOURCES
;
1027 AsciiStrToUnicodeStrS (Attempt
->MacString
, MacString
, ISCSI_MAX_MAC_STRING_LEN
);
1030 mPrivate
->PortString
,
1031 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
1032 L
"MAC: %s, PFA: Bus %d | Dev %d | Func %d, iSCSI mode: %s, IP version: %s",
1035 NicInfo
->DeviceNumber
,
1036 NicInfo
->FunctionNumber
,
1041 Attempt
->AttemptTitleHelpToken
= HiiSetString (
1042 mCallbackInfo
->RegisteredHandle
,
1043 Attempt
->AttemptTitleHelpToken
,
1044 mPrivate
->PortString
,
1047 if (Attempt
->AttemptTitleHelpToken
== 0) {
1048 FreePool (MacString
);
1049 return EFI_OUT_OF_RESOURCES
;
1053 // Check whether this attempt is an existing one.
1055 ExistAttempt
= IScsiConfigGetAttemptByConfigIndex (Attempt
->AttemptConfigIndex
);
1056 if (ExistAttempt
!= NULL
) {
1057 ASSERT (ExistAttempt
== Attempt
);
1059 if (IfrNvData
->Enabled
== ISCSI_DISABLED
&&
1060 Attempt
->SessionConfigData
.Enabled
!= ISCSI_DISABLED
) {
1063 // User updates the Attempt from "Enabled"/"Enabled for MPIO" to "Disabled".
1065 if (Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
1066 if (mPrivate
->MpioCount
< 1) {
1070 if (--mPrivate
->MpioCount
== 0) {
1071 mPrivate
->EnableMpio
= FALSE
;
1073 } else if (Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED
) {
1074 if (mPrivate
->SinglePathCount
< 1) {
1077 mPrivate
->SinglePathCount
--;
1080 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
&&
1081 Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED
) {
1083 // User updates the Attempt from "Enabled" to "Enabled for MPIO".
1085 if (mPrivate
->SinglePathCount
< 1) {
1089 mPrivate
->EnableMpio
= TRUE
;
1090 mPrivate
->MpioCount
++;
1091 mPrivate
->SinglePathCount
--;
1093 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
&&
1094 Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
1096 // User updates the Attempt from "Enabled for MPIO" to "Enabled".
1098 if (mPrivate
->MpioCount
< 1) {
1102 if (--mPrivate
->MpioCount
== 0) {
1103 mPrivate
->EnableMpio
= FALSE
;
1105 mPrivate
->SinglePathCount
++;
1107 } else if (IfrNvData
->Enabled
!= ISCSI_DISABLED
&&
1108 Attempt
->SessionConfigData
.Enabled
== ISCSI_DISABLED
) {
1110 // User updates the Attempt from "Disabled" to "Enabled"/"Enabled for MPIO".
1112 if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
1113 mPrivate
->EnableMpio
= TRUE
;
1114 mPrivate
->MpioCount
++;
1116 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
) {
1117 mPrivate
->SinglePathCount
++;
1121 } else if (ExistAttempt
== NULL
) {
1123 // When a new attempt is created, pointer of the attempt is saved to
1124 // mCallbackInfo->Current in IScsiConfigProcessDefault. If input Attempt
1125 // does not match any existing attempt, it should be a new created attempt.
1126 // Save it to system now.
1130 // Save current order number for this attempt.
1132 AttemptConfigOrder
= IScsiGetVariableAndSize (
1135 &AttemptConfigOrderSize
1138 TotalNumber
= AttemptConfigOrderSize
/ sizeof (UINT8
);
1142 // Append the new created attempt order to the end.
1144 AttemptOrderTmp
= AllocateZeroPool (TotalNumber
* sizeof (UINT8
));
1145 if (AttemptOrderTmp
== NULL
) {
1146 if (AttemptConfigOrder
!= NULL
) {
1147 FreePool (AttemptConfigOrder
);
1149 return EFI_OUT_OF_RESOURCES
;
1152 if (AttemptConfigOrder
!= NULL
) {
1153 CopyMem (AttemptOrderTmp
, AttemptConfigOrder
, AttemptConfigOrderSize
);
1154 FreePool (AttemptConfigOrder
);
1157 AttemptOrderTmp
[TotalNumber
- 1] = Attempt
->AttemptConfigIndex
;
1158 AttemptConfigOrder
= AttemptOrderTmp
;
1159 AttemptConfigOrderSize
= TotalNumber
* sizeof (UINT8
);
1161 Status
= gRT
->SetVariable (
1164 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
1165 AttemptConfigOrderSize
,
1168 FreePool (AttemptConfigOrder
);
1169 if (EFI_ERROR (Status
)) {
1174 // Insert new created attempt to array.
1176 InsertTailList (&mPrivate
->AttemptConfigs
, &Attempt
->Link
);
1177 mPrivate
->AttemptCount
++;
1179 if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
1181 // This new Attempt is enabled for MPIO; enable the multipath mode.
1183 mPrivate
->EnableMpio
= TRUE
;
1184 mPrivate
->MpioCount
++;
1185 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
) {
1186 mPrivate
->SinglePathCount
++;
1189 IScsiConfigUpdateAttempt ();
1191 Attempt
->SessionConfigData
.Enabled
= IfrNvData
->Enabled
;
1194 // Record the user configuration information in NVR.
1196 UnicodeSPrint (mPrivate
->PortString
, (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
, L
"Attempt %d", Attempt
->AttemptConfigIndex
);
1198 FreePool (MacString
);
1200 return gRT
->SetVariable (
1201 mPrivate
->PortString
,
1202 &gEfiIScsiInitiatorNameProtocolGuid
,
1203 ISCSI_CONFIG_VAR_ATTR
,
1204 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA
),
1210 Convert the IFR data configured by keyword to iSCSI configuration data.
1212 @param[in] IfrNvData Point to ISCSI_CONFIG_IFR_NVDATA.
1213 @param[in] OffSet The offset of the variable to the configuration structure.
1215 @retval EFI_INVALID_PARAMETER Any input or configured parameter is invalid.
1216 @retval EFI_SUCCESS The operation is completed successfully.
1220 IScsiConvertlfrNvDataToAttemptConfigDataByKeyword (
1221 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
,
1225 ISCSI_ATTEMPT_CONFIG_NVDATA
*Attempt
;
1228 UINT8 ChapSecretLen
;
1229 UINT8 ReverseChapSecretLen
;
1230 CHAR16
*AttemptName1
;
1231 CHAR16
*AttemptName2
;
1232 ISCSI_ATTEMPT_CONFIG_NVDATA
*SameNicAttempt
;
1233 CHAR8 LunString
[ISCSI_LUN_STR_MAX_LEN
];
1234 CHAR8 IScsiName
[ISCSI_NAME_MAX_SIZE
];
1235 CHAR8 IpString
[IP_STR_MAX_SIZE
];
1236 EFI_IP_ADDRESS HostIp
;
1237 EFI_IP_ADDRESS SubnetMask
;
1238 EFI_IP_ADDRESS Gateway
;
1244 ZeroMem (IScsiName
, sizeof (IScsiName
));
1246 if (OffSet
< ATTEMPT_BOOTENABLE_VAR_OFFSET
) {
1249 } else if ((OffSet
>= ATTEMPT_BOOTENABLE_VAR_OFFSET
) && (OffSet
< ATTEMPT_ADDRESS_TYPE_VAR_OFFSET
)) {
1250 AttemptIndex
= (UINT8
) ((OffSet
- ATTEMPT_BOOTENABLE_VAR_OFFSET
) + 1);
1251 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1252 if (Attempt
== NULL
) {
1253 return EFI_INVALID_PARAMETER
;
1255 IfrNvData
->Enabled
= IfrNvData
->ISCSIBootEnableList
[AttemptIndex
- 1];
1257 // Validate the configuration of attempt.
1259 if (IfrNvData
->Enabled
!= ISCSI_DISABLED
) {
1261 // Check whether this attempt uses NIC which is already used by existing attempt.
1263 SameNicAttempt
= IScsiConfigGetAttemptByNic (Attempt
, IfrNvData
->Enabled
);
1264 if (SameNicAttempt
!= NULL
) {
1265 AttemptName1
= (CHAR16
*) AllocateZeroPool (ATTEMPT_NAME_SIZE
* sizeof (CHAR16
));
1266 if (AttemptName1
== NULL
) {
1267 return EFI_OUT_OF_RESOURCES
;
1270 AttemptName2
= (CHAR16
*) AllocateZeroPool (ATTEMPT_NAME_SIZE
* sizeof (CHAR16
));
1271 if (AttemptName2
== NULL
) {
1272 FreePool (AttemptName1
);
1273 return EFI_OUT_OF_RESOURCES
;
1276 AsciiStrToUnicodeStrS (Attempt
->AttemptName
, AttemptName1
, ATTEMPT_NAME_SIZE
);
1277 AsciiStrToUnicodeStrS (SameNicAttempt
->AttemptName
, AttemptName2
, ATTEMPT_NAME_SIZE
);
1280 mPrivate
->PortString
,
1281 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
1282 L
"Warning! \"%s\" uses same NIC as Attempt \"%s\".",
1288 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1290 mPrivate
->PortString
,
1294 FreePool (AttemptName1
);
1295 FreePool (AttemptName2
);
1299 if (IfrNvData
->Enabled
== ISCSI_DISABLED
&&
1300 Attempt
->SessionConfigData
.Enabled
!= ISCSI_DISABLED
) {
1303 // User updates the Attempt from "Enabled"/"Enabled for MPIO" to "Disabled".
1305 if (Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
1306 if (mPrivate
->MpioCount
< 1) {
1310 if (--mPrivate
->MpioCount
== 0) {
1311 mPrivate
->EnableMpio
= FALSE
;
1313 } else if (Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED
) {
1314 if (mPrivate
->SinglePathCount
< 1) {
1317 mPrivate
->SinglePathCount
--;
1320 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
&&
1321 Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED
) {
1323 // User updates the Attempt from "Enabled" to "Enabled for MPIO".
1325 if (mPrivate
->SinglePathCount
< 1) {
1329 mPrivate
->EnableMpio
= TRUE
;
1330 mPrivate
->MpioCount
++;
1331 mPrivate
->SinglePathCount
--;
1333 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
&&
1334 Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
1336 // User updates the Attempt from "Enabled for MPIO" to "Enabled".
1338 if (mPrivate
->MpioCount
< 1) {
1342 if (--mPrivate
->MpioCount
== 0) {
1343 mPrivate
->EnableMpio
= FALSE
;
1345 mPrivate
->SinglePathCount
++;
1347 } else if (IfrNvData
->Enabled
!= ISCSI_DISABLED
&&
1348 Attempt
->SessionConfigData
.Enabled
== ISCSI_DISABLED
) {
1350 // User updates the Attempt from "Disabled" to "Enabled"/"Enabled for MPIO".
1352 if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
1353 mPrivate
->EnableMpio
= TRUE
;
1354 mPrivate
->MpioCount
++;
1356 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
) {
1357 mPrivate
->SinglePathCount
++;
1360 Attempt
->SessionConfigData
.Enabled
= IfrNvData
->Enabled
;
1362 } else if ((OffSet
>= ATTEMPT_ADDRESS_TYPE_VAR_OFFSET
) && (OffSet
< ATTEMPT_CONNECT_RETRY_VAR_OFFSET
)) {
1363 AttemptIndex
= (UINT8
) ((OffSet
- ATTEMPT_ADDRESS_TYPE_VAR_OFFSET
) + 1);
1364 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1365 if (Attempt
== NULL
) {
1366 return EFI_INVALID_PARAMETER
;
1368 Attempt
->SessionConfigData
.IpMode
= IfrNvData
->ISCSIIpAddressTypeList
[AttemptIndex
- 1];
1369 if (Attempt
->SessionConfigData
.IpMode
< IP_MODE_AUTOCONFIG
) {
1370 Attempt
->AutoConfigureMode
= 0;
1373 } else if ((OffSet
>= ATTEMPT_CONNECT_RETRY_VAR_OFFSET
) && (OffSet
< ATTEMPT_CONNECT_TIMEOUT_VAR_OFFSET
)) {
1374 AttemptIndex
= (UINT8
) ((OffSet
- ATTEMPT_CONNECT_RETRY_VAR_OFFSET
) + 1);
1375 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1376 if (Attempt
== NULL
) {
1377 return EFI_INVALID_PARAMETER
;
1380 if (IfrNvData
->ISCSIConnectRetry
[AttemptIndex
- 1] > CONNECT_MAX_RETRY
) {
1382 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1384 L
"The minimum value is 0 and the maximum is 16. 0 means no retry.",
1387 return EFI_INVALID_PARAMETER
;
1389 Attempt
->SessionConfigData
.ConnectRetryCount
= IfrNvData
->ISCSIConnectRetry
[AttemptIndex
- 1];
1391 } else if ((OffSet
>= ATTEMPT_CONNECT_TIMEOUT_VAR_OFFSET
) && (OffSet
< ATTEMPT_INITIATOR_VIA_DHCP_VAR_OFFSET
)) {
1392 AttemptIndex
= (UINT8
) ((OffSet
- ATTEMPT_CONNECT_TIMEOUT_VAR_OFFSET
) / 2 + 1);
1393 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1394 if (Attempt
== NULL
) {
1395 return EFI_INVALID_PARAMETER
;
1398 if ((IfrNvData
->ISCSIConnectTimeout
[AttemptIndex
- 1] < CONNECT_MIN_TIMEOUT
) ||
1399 (IfrNvData
->ISCSIConnectTimeout
[AttemptIndex
- 1] > CONNECT_MAX_TIMEOUT
)) {
1401 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1403 L
"The minimum value is 100 milliseconds and the maximum is 20 seconds.",
1406 return EFI_INVALID_PARAMETER
;
1409 Attempt
->SessionConfigData
.ConnectTimeout
= IfrNvData
->ISCSIConnectTimeout
[AttemptIndex
- 1];
1410 if (Attempt
->SessionConfigData
.ConnectTimeout
== 0) {
1411 Attempt
->SessionConfigData
.ConnectTimeout
= CONNECT_DEFAULT_TIMEOUT
;
1414 } else if ((OffSet
>= ATTEMPT_INITIATOR_VIA_DHCP_VAR_OFFSET
) && (OffSet
< ATTEMPT_TARGET_VIA_DHCP_VAR_OFFSET
)) {
1415 AttemptIndex
= (UINT8
) ((OffSet
- ATTEMPT_INITIATOR_VIA_DHCP_VAR_OFFSET
) + 1);
1416 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1417 if (Attempt
== NULL
) {
1418 return EFI_INVALID_PARAMETER
;
1420 Attempt
->SessionConfigData
.InitiatorInfoFromDhcp
= IfrNvData
->ISCSIInitiatorInfoViaDHCP
[AttemptIndex
- 1];
1422 } else if ((OffSet
>= ATTEMPT_TARGET_VIA_DHCP_VAR_OFFSET
) && (OffSet
< ATTEMPT_TARGET_TCP_PORT_VAR_OFFSET
)) {
1423 AttemptIndex
= (UINT8
) ((OffSet
- ATTEMPT_TARGET_VIA_DHCP_VAR_OFFSET
) + 1);
1424 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1425 if (Attempt
== NULL
) {
1426 return EFI_INVALID_PARAMETER
;
1429 if ((Attempt
->SessionConfigData
.IpMode
< IP_MODE_AUTOCONFIG
) && (Attempt
->SessionConfigData
.InitiatorInfoFromDhcp
)) {
1430 Attempt
->SessionConfigData
.TargetInfoFromDhcp
= IfrNvData
->ISCSITargetInfoViaDHCP
[AttemptIndex
- 1];
1433 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1435 L
"Invalid Configuration, Check value of IpMode or Enable DHCP!",
1438 return EFI_INVALID_PARAMETER
;
1441 } else if ((OffSet
>= ATTEMPT_TARGET_TCP_PORT_VAR_OFFSET
) && (OffSet
< ATTEMPT_AUTHENTICATION_METHOD_VAR_OFFSET
)) {
1442 AttemptIndex
= (UINT8
) ((OffSet
- ATTEMPT_TARGET_TCP_PORT_VAR_OFFSET
) / 2 + 1);
1443 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1444 if (Attempt
== NULL
) {
1445 return EFI_INVALID_PARAMETER
;
1447 if ((Attempt
->SessionConfigData
.IpMode
< IP_MODE_AUTOCONFIG
) && (!Attempt
->SessionConfigData
.TargetInfoFromDhcp
)) {
1448 Attempt
->SessionConfigData
.TargetPort
= IfrNvData
->ISCSITargetTcpPort
[AttemptIndex
- 1];
1449 if (Attempt
->SessionConfigData
.TargetPort
== 0) {
1450 Attempt
->SessionConfigData
.TargetPort
= ISCSI_WELL_KNOWN_PORT
;
1454 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1456 L
"Invalid Configuration, Check value of IpMode or Target Via DHCP!",
1459 return EFI_INVALID_PARAMETER
;
1462 } else if ((OffSet
>= ATTEMPT_AUTHENTICATION_METHOD_VAR_OFFSET
) && (OffSet
< ATTEMPT_CHARTYPE_VAR_OFFSET
)) {
1463 AttemptIndex
= (UINT8
) ((OffSet
- ATTEMPT_AUTHENTICATION_METHOD_VAR_OFFSET
) + 1);
1464 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1465 if (Attempt
== NULL
) {
1466 return EFI_INVALID_PARAMETER
;
1469 Attempt
->AuthenticationType
= IfrNvData
->ISCSIAuthenticationMethod
[AttemptIndex
- 1];
1471 } else if ((OffSet
>= ATTEMPT_CHARTYPE_VAR_OFFSET
) && (OffSet
< ATTEMPT_ISID_VAR_OFFSET
)) {
1472 AttemptIndex
= (UINT8
) ((OffSet
- ATTEMPT_CHARTYPE_VAR_OFFSET
) + 1);
1473 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1474 if (Attempt
== NULL
) {
1475 return EFI_INVALID_PARAMETER
;
1477 if (Attempt
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
1478 Attempt
->AuthConfigData
.CHAP
.CHAPType
= IfrNvData
->ISCSIChapType
[AttemptIndex
- 1];
1481 } else if (OffSet
>= ATTEMPT_ISID_VAR_OFFSET
) {
1482 Index
= (UINT8
) ((OffSet
- ATTEMPT_ISID_VAR_OFFSET
) / sizeof (KEYWORD_STR
));
1483 AttemptIndex
= Index
+ 1;
1484 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1485 if (Attempt
== NULL
) {
1486 return EFI_INVALID_PARAMETER
;
1489 OffSet
= OffSet
- Index
* sizeof (KEYWORD_STR
);
1491 if ((OffSet
>= ATTEMPT_ISID_VAR_OFFSET
) && (OffSet
< ATTEMPT_INITIATOR_IP_ADDRESS_VAR_OFFSET
)) {
1492 IScsiParseIsIdFromString (IfrNvData
->Keyword
[Index
].ISCSIIsId
, Attempt
->SessionConfigData
.IsId
);
1494 } else if ((OffSet
>= ATTEMPT_INITIATOR_IP_ADDRESS_VAR_OFFSET
) && (OffSet
< ATTEMPT_INITIATOR_NET_MASK_VAR_OFFSET
)) {
1495 if ((Attempt
->SessionConfigData
.IpMode
== IP_MODE_IP4
) && (!Attempt
->SessionConfigData
.InitiatorInfoFromDhcp
)) {
1499 Status
= NetLibStrToIp4 (IfrNvData
->Keyword
[Index
].ISCSIInitiatorIpAddress
, &HostIp
.v4
);
1500 if (EFI_ERROR (Status
) || ((Attempt
->SessionConfigData
.SubnetMask
.Addr
[0] != 0) &&
1501 !NetIp4IsUnicast (NTOHL (HostIp
.Addr
[0]), NTOHL(*(UINT32
*)Attempt
->SessionConfigData
.SubnetMask
.Addr
)))) {
1503 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1505 L
"Invalid IP address!",
1508 return EFI_INVALID_PARAMETER
;
1510 CopyMem (&Attempt
->SessionConfigData
.LocalIp
, &HostIp
.v4
, sizeof (HostIp
.v4
));
1514 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1516 L
"Invalid Configuration, Check value of IpMode or Enable DHCP!",
1519 return EFI_INVALID_PARAMETER
;
1522 } else if ((OffSet
>= ATTEMPT_INITIATOR_NET_MASK_VAR_OFFSET
) && (OffSet
< ATTEMPT_INITIATOR_GATE_WAY_VAR_OFFSET
)) {
1523 if ((Attempt
->SessionConfigData
.IpMode
== IP_MODE_IP4
) && (!Attempt
->SessionConfigData
.InitiatorInfoFromDhcp
)) {
1524 Status
= NetLibStrToIp4 (IfrNvData
->Keyword
[Index
].ISCSIInitiatorNetmask
, &SubnetMask
.v4
);
1525 if (EFI_ERROR (Status
) || ((SubnetMask
.Addr
[0] != 0) && (IScsiGetSubnetMaskPrefixLength (&SubnetMask
.v4
) == 0))) {
1527 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1529 L
"Invalid Subnet Mask!",
1532 return EFI_INVALID_PARAMETER
;
1534 CopyMem (&Attempt
->SessionConfigData
.SubnetMask
, &SubnetMask
.v4
, sizeof (SubnetMask
.v4
));
1538 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1540 L
"Invalid Configuration, Check value of IpMode or Enable DHCP!",
1543 return EFI_INVALID_PARAMETER
;
1546 } else if ((OffSet
>= ATTEMPT_INITIATOR_GATE_WAY_VAR_OFFSET
) && (OffSet
< ATTEMPT_TARGET_NAME_VAR_OFFSET
)) {
1547 if ((Attempt
->SessionConfigData
.IpMode
== IP_MODE_IP4
) && (!Attempt
->SessionConfigData
.InitiatorInfoFromDhcp
)) {
1548 Status
= NetLibStrToIp4 (IfrNvData
->Keyword
[Index
].ISCSIInitiatorGateway
, &Gateway
.v4
);
1549 if (EFI_ERROR (Status
) ||
1550 ((Gateway
.Addr
[0] != 0) && (Attempt
->SessionConfigData
.SubnetMask
.Addr
[0] != 0) &&
1551 !NetIp4IsUnicast (NTOHL (Gateway
.Addr
[0]), NTOHL(*(UINT32
*)Attempt
->SessionConfigData
.SubnetMask
.Addr
)))) {
1553 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1555 L
"Invalid Gateway!",
1558 return EFI_INVALID_PARAMETER
;
1560 CopyMem (&Attempt
->SessionConfigData
.Gateway
, &Gateway
.v4
, sizeof (Gateway
.v4
));
1564 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1566 L
"Invalid Configuration, Check value of IpMode or Enable DHCP!",
1569 return EFI_INVALID_PARAMETER
;
1572 } else if ((OffSet
>= ATTEMPT_TARGET_NAME_VAR_OFFSET
) && (OffSet
< ATTEMPT_TARGET_IP_ADDRESS_VAR_OFFSET
)) {
1573 if ((Attempt
->SessionConfigData
.IpMode
< IP_MODE_AUTOCONFIG
) && (!Attempt
->SessionConfigData
.TargetInfoFromDhcp
)) {
1574 UnicodeStrToAsciiStrS (IfrNvData
->Keyword
[Index
].ISCSITargetName
, IScsiName
, ISCSI_NAME_MAX_SIZE
);
1575 Status
= IScsiNormalizeName (IScsiName
, AsciiStrLen (IScsiName
));
1576 if (EFI_ERROR (Status
)) {
1578 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1580 L
"Invalid iSCSI Name!",
1584 AsciiStrCpyS (Attempt
->SessionConfigData
.TargetName
, ISCSI_NAME_MAX_SIZE
, IScsiName
);
1586 if (Attempt
->SessionConfigData
.Enabled
!= ISCSI_DISABLED
) {
1587 if (Attempt
->SessionConfigData
.TargetName
[0] == L
'\0') {
1589 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1591 L
"iSCSI target name is NULL!",
1594 return EFI_INVALID_PARAMETER
;
1599 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1601 L
"Invalid Configuration, Check value of IpMode or Target Via DHCP!",
1604 return EFI_INVALID_PARAMETER
;
1607 } else if ((OffSet
>= ATTEMPT_TARGET_IP_ADDRESS_VAR_OFFSET
) && (OffSet
< ATTEMPT_LUN_VAR_OFFSET
)) {
1608 if ((Attempt
->SessionConfigData
.IpMode
< IP_MODE_AUTOCONFIG
) && (!Attempt
->SessionConfigData
.TargetInfoFromDhcp
)) {
1609 UnicodeStrToAsciiStrS (IfrNvData
->Keyword
[Index
].ISCSITargetIpAddress
, IpString
, sizeof (IpString
));
1610 Status
= IScsiAsciiStrToIp (IpString
, Attempt
->SessionConfigData
.IpMode
, &HostIp
);
1611 if (EFI_ERROR (Status
) || !IpIsUnicast (&HostIp
, Attempt
->SessionConfigData
.IpMode
)) {
1612 Attempt
->SessionConfigData
.DnsMode
= TRUE
;
1613 ZeroMem (&Attempt
->SessionConfigData
.TargetIp
, sizeof (Attempt
->SessionConfigData
.TargetIp
));
1614 UnicodeStrToAsciiStrS (IfrNvData
->Keyword
[Index
].ISCSITargetIpAddress
, Attempt
->SessionConfigData
.TargetUrl
, ISCSI_NAME_MAX_SIZE
);
1616 Attempt
->SessionConfigData
.DnsMode
= FALSE
;
1617 CopyMem (&Attempt
->SessionConfigData
.TargetIp
, &HostIp
, sizeof (HostIp
));
1621 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1623 L
"Invalid Configuration, Check value of IpMode or Target Via DHCP!",
1626 return EFI_INVALID_PARAMETER
;
1629 } else if ((OffSet
>= ATTEMPT_LUN_VAR_OFFSET
) && (OffSet
< ATTEMPT_CHAR_USER_NAME_VAR_OFFSET
)) {
1630 if ((Attempt
->SessionConfigData
.IpMode
< IP_MODE_AUTOCONFIG
) && (Attempt
->SessionConfigData
.TargetInfoFromDhcp
== 0)) {
1634 UnicodeStrToAsciiStrS (IfrNvData
->Keyword
[Index
].ISCSILun
, LunString
, ISCSI_LUN_STR_MAX_LEN
);
1635 Status
= IScsiAsciiStrToLun (LunString
, (UINT8
*) &Lun
);
1636 if (EFI_ERROR (Status
)) {
1638 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1640 L
"Invalid LUN string, Examples are: 4752-3A4F-6b7e-2F99, 6734-9-156f-127, 4186-9!",
1644 CopyMem (&Attempt
->SessionConfigData
.BootLun
, &Lun
, sizeof (Lun
));
1648 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1650 L
"Invalid Configuration, Check value of IpMode or Target Via DHCP!",
1653 return EFI_INVALID_PARAMETER
;
1656 } else if ((OffSet
>= ATTEMPT_CHAR_USER_NAME_VAR_OFFSET
) && (OffSet
< ATTEMPT_CHAR_SECRET_VAR_OFFSET
)) {
1657 if (Attempt
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
1658 UnicodeStrToAsciiStrS (
1659 IfrNvData
->Keyword
[Index
].ISCSIChapUsername
,
1660 Attempt
->AuthConfigData
.CHAP
.CHAPName
,
1661 ISCSI_CHAP_NAME_STORAGE
1664 if (Attempt
->SessionConfigData
.Enabled
!= ISCSI_DISABLED
) {
1665 if (IfrNvData
->Keyword
[Index
].ISCSIChapUsername
[0] == L
'\0') {
1667 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1669 L
"CHAP Name is invalid!",
1672 return EFI_INVALID_PARAMETER
;
1677 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1679 L
"Invalid Configuration, Check value of AuthenticationType!",
1682 return EFI_INVALID_PARAMETER
;
1685 } else if ((OffSet
>= ATTEMPT_CHAR_SECRET_VAR_OFFSET
) && (OffSet
< ATTEMPT_CHAR_REVERSE_USER_NAME_VAR_OFFSET
)) {
1686 if (Attempt
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
1687 ChapSecretLen
= (UINT8
)StrLen (IfrNvData
->Keyword
[Index
].ISCSIChapSecret
);
1688 UnicodeStrToAsciiStrS (
1689 IfrNvData
->Keyword
[Index
].ISCSIChapSecret
,
1690 Attempt
->AuthConfigData
.CHAP
.CHAPSecret
,
1691 ISCSI_CHAP_SECRET_STORAGE
1694 if (Attempt
->SessionConfigData
.Enabled
!= ISCSI_DISABLED
) {
1695 if ((ChapSecretLen
< ISCSI_CHAP_SECRET_MIN_LEN
) || (ChapSecretLen
> ISCSI_CHAP_SECRET_MAX_LEN
)) {
1697 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1699 L
"The Chap Secret minimum length is 12 bytes and the maximum length is 16 bytes.",
1702 return EFI_INVALID_PARAMETER
;
1707 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1709 L
"Invalid Configuration, Check value of AuthenticationType!",
1712 return EFI_INVALID_PARAMETER
;
1715 } else if ((OffSet
>= ATTEMPT_CHAR_REVERSE_USER_NAME_VAR_OFFSET
) && (OffSet
< ATTEMPT_CHAR_REVERSE_SECRET_VAR_OFFSET
)) {
1716 if (Attempt
->AuthConfigData
.CHAP
.CHAPType
== ISCSI_CHAP_MUTUAL
) {
1717 UnicodeStrToAsciiStrS (
1718 IfrNvData
->Keyword
[Index
].ISCSIReverseChapUsername
,
1719 Attempt
->AuthConfigData
.CHAP
.ReverseCHAPName
,
1720 ISCSI_CHAP_NAME_STORAGE
1722 if (Attempt
->SessionConfigData
.Enabled
!= ISCSI_DISABLED
) {
1723 if (IfrNvData
->Keyword
[Index
].ISCSIReverseChapUsername
[0] == L
'\0') {
1725 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1727 L
"Reverse CHAP Name is invalid!",
1730 return EFI_INVALID_PARAMETER
;
1735 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1737 L
"Invalid Configuration, Check value of AuthenticationType or Chap Type!",
1740 return EFI_INVALID_PARAMETER
;
1743 } else if (OffSet
>= ATTEMPT_CHAR_REVERSE_SECRET_VAR_OFFSET
) {
1744 if (Attempt
->AuthConfigData
.CHAP
.CHAPType
== ISCSI_CHAP_MUTUAL
) {
1745 ReverseChapSecretLen
= (UINT8
)StrLen (IfrNvData
->Keyword
[Index
].ISCSIReverseChapSecret
);
1746 UnicodeStrToAsciiStrS (
1747 IfrNvData
->Keyword
[Index
].ISCSIReverseChapSecret
,
1748 Attempt
->AuthConfigData
.CHAP
.ReverseCHAPSecret
,
1749 ISCSI_CHAP_SECRET_STORAGE
1752 if (Attempt
->SessionConfigData
.Enabled
!= ISCSI_DISABLED
) {
1753 if ((ReverseChapSecretLen
< ISCSI_CHAP_SECRET_MIN_LEN
) || (ReverseChapSecretLen
> ISCSI_CHAP_SECRET_MAX_LEN
)) {
1755 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1757 L
"The Reverse CHAP Secret minimum length is 12 bytes and the maximum length is 16 bytes.",
1760 return EFI_INVALID_PARAMETER
;
1765 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1767 L
"Invalid Configuration, Check value of AuthenticationType or Chap Type!",
1770 return EFI_INVALID_PARAMETER
;
1778 // Record the user configuration information in NVR.
1780 ASSERT (Attempt
!= NULL
);
1781 UnicodeSPrint (mPrivate
->PortString
, (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
, L
"Attempt %d", Attempt
->AttemptConfigIndex
);
1782 return gRT
->SetVariable (
1783 mPrivate
->PortString
,
1784 &gEfiIScsiInitiatorNameProtocolGuid
,
1785 ISCSI_CONFIG_VAR_ATTR
,
1786 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA
),
1793 Create Hii Extend Label OpCode as the start opcode and end opcode. It is
1796 @param[in] StartLabelNumber The number of start label.
1797 @param[out] StartOpCodeHandle Points to the start opcode handle.
1798 @param[out] StartLabel Points to the created start opcode.
1799 @param[out] EndOpCodeHandle Points to the end opcode handle.
1800 @param[out] EndLabel Points to the created end opcode.
1802 @retval EFI_OUT_OF_RESOURCES Do not have sufficient resource to finish this
1804 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
1805 @retval EFI_SUCCESS The operation is completed successfully.
1810 IN UINT16 StartLabelNumber
,
1811 OUT VOID
**StartOpCodeHandle
,
1812 OUT EFI_IFR_GUID_LABEL
**StartLabel
,
1813 OUT VOID
**EndOpCodeHandle
,
1814 OUT EFI_IFR_GUID_LABEL
**EndLabel
1818 EFI_IFR_GUID_LABEL
*InternalStartLabel
;
1819 EFI_IFR_GUID_LABEL
*InternalEndLabel
;
1821 if (StartOpCodeHandle
== NULL
|| StartLabel
== NULL
|| EndOpCodeHandle
== NULL
|| EndLabel
== NULL
) {
1822 return EFI_INVALID_PARAMETER
;
1825 *StartOpCodeHandle
= NULL
;
1826 *EndOpCodeHandle
= NULL
;
1827 Status
= EFI_OUT_OF_RESOURCES
;
1830 // Initialize the container for dynamic opcodes.
1832 *StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
1833 if (*StartOpCodeHandle
== NULL
) {
1837 *EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
1838 if (*EndOpCodeHandle
== NULL
) {
1843 // Create Hii Extend Label OpCode as the start opcode.
1845 InternalStartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
1849 sizeof (EFI_IFR_GUID_LABEL
)
1851 if (InternalStartLabel
== NULL
) {
1855 InternalStartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
1856 InternalStartLabel
->Number
= StartLabelNumber
;
1859 // Create Hii Extend Label OpCode as the end opcode.
1861 InternalEndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
1865 sizeof (EFI_IFR_GUID_LABEL
)
1867 if (InternalEndLabel
== NULL
) {
1871 InternalEndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
1872 InternalEndLabel
->Number
= LABEL_END
;
1874 *StartLabel
= InternalStartLabel
;
1875 *EndLabel
= InternalEndLabel
;
1881 if (*StartOpCodeHandle
!= NULL
) {
1882 HiiFreeOpCodeHandle (*StartOpCodeHandle
);
1885 if (*EndOpCodeHandle
!= NULL
) {
1886 HiiFreeOpCodeHandle (*EndOpCodeHandle
);
1892 Update the MAIN form to display the configured attempts.
1896 IScsiConfigUpdateAttempt (
1901 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
1902 VOID
*StartOpCodeHandle
;
1903 EFI_IFR_GUID_LABEL
*StartLabel
;
1904 VOID
*EndOpCodeHandle
;
1905 EFI_IFR_GUID_LABEL
*EndLabel
;
1908 Status
= IScsiCreateOpCode (
1909 ATTEMPT_ENTRY_LABEL
,
1915 if (EFI_ERROR (Status
)) {
1919 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
1920 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
1921 if (AttemptConfigData
->Actived
== ISCSI_ACTIVE_ENABLED
) {
1923 // Update Attempt Help Info.
1925 UnicodeSPrint (mPrivate
->PortString
, (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
, L
"Attempt %d", (UINTN
) AttemptConfigData
->AttemptConfigIndex
);
1926 AttemptConfigData
->AttemptTitleToken
= HiiSetString (
1927 mCallbackInfo
->RegisteredHandle
,
1929 mPrivate
->PortString
,
1932 if (AttemptConfigData
->AttemptTitleToken
== 0) {
1936 HiiCreateGotoOpCode (
1937 StartOpCodeHandle
, // Container for dynamic created opcodes
1938 FORMID_ATTEMPT_FORM
, // Form ID
1939 AttemptConfigData
->AttemptTitleToken
, // Prompt text
1940 AttemptConfigData
->AttemptTitleHelpToken
, // Help text
1941 EFI_IFR_FLAG_CALLBACK
, // Question flag
1942 (UINT16
) (KEY_ATTEMPT_ENTRY_BASE
+ AttemptConfigData
->AttemptConfigIndex
) // Question ID
1948 mCallbackInfo
->RegisteredHandle
, // HII handle
1949 &gIScsiConfigGuid
, // Formset GUID
1950 FORMID_MAIN_FORM
, // Form ID
1951 StartOpCodeHandle
, // Label for where to insert opcodes
1952 EndOpCodeHandle
// Replace data
1955 HiiFreeOpCodeHandle (StartOpCodeHandle
);
1956 HiiFreeOpCodeHandle (EndOpCodeHandle
);
1960 Callback function when user presses "Add an Attempt".
1962 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
1964 @retval EFI_SUCCESS The operation is completed successfully.
1968 IScsiConfigAddAttempt (
1973 ISCSI_NIC_INFO
*NicInfo
;
1974 EFI_STRING_ID PortTitleToken
;
1975 EFI_STRING_ID PortTitleHelpToken
;
1976 CHAR16 MacString
[ISCSI_MAX_MAC_STRING_LEN
];
1978 VOID
*StartOpCodeHandle
;
1979 EFI_IFR_GUID_LABEL
*StartLabel
;
1980 VOID
*EndOpCodeHandle
;
1981 EFI_IFR_GUID_LABEL
*EndLabel
;
1983 Status
= IScsiCreateOpCode (
1990 if (EFI_ERROR (Status
)) {
1995 // Ask user to select a MAC for this attempt.
1997 NET_LIST_FOR_EACH (Entry
, &mPrivate
->NicInfoList
) {
1998 NicInfo
= NET_LIST_USER_STRUCT (Entry
, ISCSI_NIC_INFO
, Link
);
2000 &NicInfo
->PermanentAddress
,
2001 NicInfo
->HwAddressSize
,
2006 UnicodeSPrint (mPrivate
->PortString
, (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
, L
"MAC %s", MacString
);
2007 PortTitleToken
= HiiSetString (
2008 mCallbackInfo
->RegisteredHandle
,
2010 mPrivate
->PortString
,
2013 if (PortTitleToken
== 0) {
2014 Status
= EFI_INVALID_PARAMETER
;
2019 mPrivate
->PortString
,
2020 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
2021 L
"PFA: Bus %d | Dev %d | Func %d",
2023 NicInfo
->DeviceNumber
,
2024 NicInfo
->FunctionNumber
2026 PortTitleHelpToken
= HiiSetString (mCallbackInfo
->RegisteredHandle
, 0, mPrivate
->PortString
, NULL
);
2027 if (PortTitleHelpToken
== 0) {
2028 Status
= EFI_INVALID_PARAMETER
;
2032 HiiCreateGotoOpCode (
2033 StartOpCodeHandle
, // Container for dynamic created opcodes
2034 FORMID_ATTEMPT_FORM
,
2037 EFI_IFR_FLAG_CALLBACK
, // Question flag
2038 (UINT16
) (KEY_MAC_ENTRY_BASE
+ NicInfo
->NicIndex
)
2042 Status
= HiiUpdateForm (
2043 mCallbackInfo
->RegisteredHandle
, // HII handle
2044 &gIScsiConfigGuid
, // Formset GUID
2045 FORMID_MAC_FORM
, // Form ID
2046 StartOpCodeHandle
, // Label for where to insert opcodes
2047 EndOpCodeHandle
// Replace data
2051 HiiFreeOpCodeHandle (StartOpCodeHandle
);
2052 HiiFreeOpCodeHandle (EndOpCodeHandle
);
2058 Add the attempts by keyword 'iSCSIAddAttempts', you can use this keyword with
2059 value 'attempt:1 attempt:2' etc to add one or more attempts once. This is different
2060 with IScsiConfigAddAttempt function which is used to add attempt by UI configuration.
2062 @param[in] AttemptList The new attempt List will be added.
2064 @retval EFI_SUCCESS The operation to add attempt list successfully.
2065 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
2066 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
2067 @retval EFI_OUT_OF_RESOURCES Fail to finish the operation due to lack of
2072 IScsiConfigAddAttemptsByKeywords (
2073 IN UINT8
*AttemptList
2080 UINT8
*AttemptConfigOrder
;
2081 UINTN AttemptConfigOrderSize
;
2082 UINT8
*AttemptConfigOrderTmp
;
2083 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
2084 ISCSI_NIC_INFO
*NicInfo
;
2085 CHAR16 MacString
[ISCSI_MAX_MAC_STRING_LEN
];
2086 CHAR16 IScsiMode
[64];
2090 Nic
= mPrivate
->CurrentNic
;
2091 NicInfo
= IScsiGetNicInfoByIndex (Nic
);
2092 if (NicInfo
== NULL
) {
2093 return EFI_NOT_FOUND
;
2097 // The MAC info will be recorded in Config Data.
2100 &NicInfo
->PermanentAddress
,
2101 NicInfo
->HwAddressSize
,
2106 for (Index
= 0; Index
< PcdGet8 (PcdMaxIScsiAttemptNumber
); Index
++) {
2107 if (AttemptList
[Index
] == 0) {
2114 Number
= AttemptList
[Index
];
2117 mPrivate
->PortString
,
2118 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
2124 mPrivate
->PortString
,
2125 &gEfiIScsiInitiatorNameProtocolGuid
,
2126 (VOID
**)&AttemptConfigData
,
2129 if (AttemptConfigData
== NULL
|| AttemptConfigData
->Actived
== ISCSI_ACTIVE_ENABLED
) {
2130 return EFI_INVALID_PARAMETER
;
2133 AttemptConfigData
->Actived
= ISCSI_ACTIVE_ENABLED
;
2134 AttemptConfigData
->NicIndex
= NicInfo
->NicIndex
;
2135 UnicodeStrToAsciiStrS (MacString
, AttemptConfigData
->MacString
, ISCSI_MAX_MAC_STRING_LEN
);
2138 // Generate OUI-format ISID based on MAC address.
2140 CopyMem (AttemptConfigData
->SessionConfigData
.IsId
, &NicInfo
->PermanentAddress
, 6);
2141 AttemptConfigData
->SessionConfigData
.IsId
[0] =
2142 (UINT8
) (AttemptConfigData
->SessionConfigData
.IsId
[0] & 0x3F);
2145 // Configure the iSCSI Mode and IpMode to default.
2146 // Add Attempt Help Info.
2148 UnicodeSPrint (IScsiMode
, 64, L
"Disabled");
2149 UnicodeSPrint (IpMode
, 64, L
"IP4");
2151 mPrivate
->PortString
,
2152 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
2153 L
"MAC: %s, PFA: Bus %d | Dev %d | Func %d, iSCSI mode: %s, IP version: %s",
2156 NicInfo
->DeviceNumber
,
2157 NicInfo
->FunctionNumber
,
2162 AttemptConfigData
->AttemptTitleHelpToken
= HiiSetString (
2163 mCallbackInfo
->RegisteredHandle
,
2165 mPrivate
->PortString
,
2168 if (AttemptConfigData
->AttemptTitleHelpToken
== 0) {
2169 return EFI_OUT_OF_RESOURCES
;
2173 // Get current Attempt order and number.
2175 AttemptConfigOrder
= IScsiGetVariableAndSize (
2178 &AttemptConfigOrderSize
2180 TotalNumber
= AttemptConfigOrderSize
/ sizeof (UINT8
);
2184 // Append the new created attempt order to the end.
2186 AttemptConfigOrderTmp
= AllocateZeroPool (TotalNumber
* sizeof (UINT8
));
2187 if (AttemptConfigOrderTmp
== NULL
) {
2188 if (AttemptConfigOrder
!= NULL
) {
2189 FreePool (AttemptConfigOrder
);
2191 return EFI_OUT_OF_RESOURCES
;
2193 if (AttemptConfigOrder
!= NULL
) {
2194 CopyMem (AttemptConfigOrderTmp
, AttemptConfigOrder
, AttemptConfigOrderSize
);
2195 FreePool (AttemptConfigOrder
);
2198 AttemptConfigOrderTmp
[TotalNumber
- 1] = Number
;
2199 AttemptConfigOrder
= AttemptConfigOrderTmp
;
2200 AttemptConfigOrderSize
= TotalNumber
* sizeof (UINT8
);
2202 Status
= gRT
->SetVariable (
2205 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
2206 AttemptConfigOrderSize
,
2209 FreePool (AttemptConfigOrder
);
2210 if (EFI_ERROR (Status
)) {
2215 // Record the attempt in global link list.
2217 InsertTailList (&mPrivate
->AttemptConfigs
, &AttemptConfigData
->Link
);
2218 mPrivate
->AttemptCount
++;
2219 UnicodeSPrint (mPrivate
->PortString
, (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
, L
"Attempt %d", AttemptConfigData
->AttemptConfigIndex
);
2221 mPrivate
->PortString
,
2222 &gEfiIScsiInitiatorNameProtocolGuid
,
2223 ISCSI_CONFIG_VAR_ATTR
,
2224 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA
),
2234 Callback function when user presses "Commit Changes and Exit" in Delete Attempts or Delete Attempts by Keyword.
2236 @param[in] IfrNvData The IFR NV data.
2238 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
2239 @retval EFI_SUCCESS The operation is completed successfully.
2240 @retval EFI_ABOTRED This operation is aborted cause of error
2242 @retval EFI_OUT_OF_RESOURCES Fail to finish the operation due to lack of
2247 IScsiConfigDeleteAttempts (
2248 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
2254 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
2255 UINT8
*AttemptConfigOrder
;
2256 UINTN AttemptConfigOrderSize
;
2257 UINT8
*AttemptNewOrder
;
2258 UINT8 AttemptConfigIndex
;
2263 LIST_ENTRY
*NextEntry
;
2264 ISCSI_SESSION_CONFIG_NVDATA
*ConfigData
;
2268 AttemptConfigOrder
= IScsiGetVariableAndSize (
2271 &AttemptConfigOrderSize
2273 if ((AttemptConfigOrder
== NULL
) || (AttemptConfigOrderSize
== 0)) {
2274 return EFI_NOT_FOUND
;
2277 AttemptNewOrder
= AllocateZeroPool (AttemptConfigOrderSize
);
2278 if (AttemptNewOrder
== NULL
) {
2279 Status
= EFI_OUT_OF_RESOURCES
;
2283 Total
= AttemptConfigOrderSize
/ sizeof (UINT8
);
2286 NET_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &mPrivate
->AttemptConfigs
) {
2287 if (IfrNvData
->DeleteAttemptList
[Index
] == 0) {
2293 // Delete the attempt.
2296 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
2297 if (AttemptConfigData
== NULL
) {
2298 Status
= EFI_NOT_FOUND
;
2303 // Remove this attempt from UI configured attempt list.
2305 RemoveEntryList (&AttemptConfigData
->Link
);
2306 mPrivate
->AttemptCount
--;
2308 if (AttemptConfigData
->SessionConfigData
.Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
2309 if (mPrivate
->MpioCount
< 1) {
2310 Status
= EFI_ABORTED
;
2315 // No more attempt is enabled for MPIO. Transit the iSCSI mode to single path.
2317 if (--mPrivate
->MpioCount
== 0) {
2318 mPrivate
->EnableMpio
= FALSE
;
2320 } else if (AttemptConfigData
->SessionConfigData
.Enabled
== ISCSI_ENABLED
) {
2321 if (mPrivate
->SinglePathCount
< 1) {
2322 Status
= EFI_ABORTED
;
2326 mPrivate
->SinglePathCount
--;
2329 AttemptConfigIndex
= AttemptConfigData
->AttemptConfigIndex
;
2330 FreePool (AttemptConfigData
);
2333 // Create a new Attempt
2335 AttemptConfigData
= AllocateZeroPool (sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA
));
2336 if (AttemptConfigData
== NULL
) {
2337 return EFI_OUT_OF_RESOURCES
;
2339 ConfigData
= &AttemptConfigData
->SessionConfigData
;
2340 ConfigData
->TargetPort
= ISCSI_WELL_KNOWN_PORT
;
2341 ConfigData
->ConnectTimeout
= CONNECT_DEFAULT_TIMEOUT
;
2342 ConfigData
->ConnectRetryCount
= CONNECT_MIN_RETRY
;
2344 AttemptConfigData
->AuthenticationType
= ISCSI_AUTH_TYPE_CHAP
;
2345 AttemptConfigData
->AuthConfigData
.CHAP
.CHAPType
= ISCSI_CHAP_UNI
;
2347 // Configure the Attempt index and set variable.
2349 AttemptConfigData
->AttemptConfigIndex
= AttemptConfigIndex
;
2352 // Set the attempt name to default.
2355 mPrivate
->PortString
,
2356 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
2358 (UINTN
) AttemptConfigData
->AttemptConfigIndex
2360 UnicodeStrToAsciiStrS (mPrivate
->PortString
, AttemptConfigData
->AttemptName
, ATTEMPT_NAME_SIZE
);
2362 mPrivate
->PortString
,
2363 &gEfiIScsiInitiatorNameProtocolGuid
,
2364 ISCSI_CONFIG_VAR_ATTR
,
2365 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA
),
2370 // Mark the attempt order in NVR to be deleted - 0.
2372 for (NewIndex
= 0; NewIndex
< Total
; NewIndex
++) {
2373 if (AttemptConfigOrder
[NewIndex
] == AttemptConfigData
->AttemptConfigIndex
) {
2374 AttemptConfigOrder
[NewIndex
] = 0;
2380 if (mCallbackInfo
->Current
== AttemptConfigData
) {
2381 mCallbackInfo
->Current
= NULL
;
2383 FreePool (AttemptConfigData
);
2386 // Check next Attempt.
2392 // Construct AttemptNewOrder.
2394 for (Index
= 0, NewIndex
= 0; Index
< Total
; Index
++) {
2395 if (AttemptConfigOrder
[Index
] != 0) {
2396 AttemptNewOrder
[NewIndex
] = AttemptConfigOrder
[Index
];
2401 Attribute
= EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_NON_VOLATILE
;
2404 // Update AttemptOrder in NVR.
2406 Status
= gRT
->SetVariable (
2410 NewTotal
* sizeof (UINT8
),
2415 if (AttemptConfigOrder
!= NULL
) {
2416 FreePool (AttemptConfigOrder
);
2419 if (AttemptNewOrder
!= NULL
) {
2420 FreePool (AttemptNewOrder
);
2428 Callback function when user presses "Delete Attempts".
2430 @param[in] IfrNvData The IFR nv data.
2432 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
2433 @retval EFI_BUFFER_TOO_SMALL The buffer in UpdateData is too small.
2434 @retval EFI_SUCCESS The operation is completed successfully.
2438 IScsiConfigDisplayDeleteAttempts (
2439 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
2443 UINT8
*AttemptConfigOrder
;
2444 UINTN AttemptConfigOrderSize
;
2446 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
2448 VOID
*StartOpCodeHandle
;
2449 EFI_IFR_GUID_LABEL
*StartLabel
;
2450 VOID
*EndOpCodeHandle
;
2451 EFI_IFR_GUID_LABEL
*EndLabel
;
2454 Status
= IScsiCreateOpCode (
2461 if (EFI_ERROR (Status
)) {
2465 AttemptConfigOrder
= IScsiGetVariableAndSize (
2468 &AttemptConfigOrderSize
2470 if (AttemptConfigOrder
!= NULL
) {
2472 // Create the check box opcode to be deleted.
2476 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
2477 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
2478 IfrNvData
->DeleteAttemptList
[Index
] = 0x00;
2480 HiiCreateCheckBoxOpCode(
2482 (EFI_QUESTION_ID
) (ATTEMPT_DEL_QUESTION_ID
+ Index
),
2483 CONFIGURATION_VARSTORE_ID
,
2484 (UINT16
) (ATTEMPT_DEL_VAR_OFFSET
+ Index
),
2485 AttemptConfigData
->AttemptTitleToken
,
2486 AttemptConfigData
->AttemptTitleHelpToken
,
2494 if (Index
== ISCSI_MAX_ATTEMPTS_NUM
) {
2499 FreePool (AttemptConfigOrder
);
2502 Status
= HiiUpdateForm (
2503 mCallbackInfo
->RegisteredHandle
, // HII handle
2504 &gIScsiConfigGuid
, // Formset GUID
2505 FORMID_DELETE_FORM
, // Form ID
2506 StartOpCodeHandle
, // Label for where to insert opcodes
2507 EndOpCodeHandle
// Replace data
2510 HiiFreeOpCodeHandle (StartOpCodeHandle
);
2511 HiiFreeOpCodeHandle (EndOpCodeHandle
);
2518 Callback function when user presses "Change Attempt Order".
2520 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
2521 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
2523 @retval EFI_SUCCESS The operation is completed successfully.
2527 IScsiConfigDisplayOrderAttempts (
2534 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
2535 VOID
*StartOpCodeHandle
;
2536 EFI_IFR_GUID_LABEL
*StartLabel
;
2537 VOID
*EndOpCodeHandle
;
2538 EFI_IFR_GUID_LABEL
*EndLabel
;
2539 VOID
*OptionsOpCodeHandle
;
2541 Status
= IScsiCreateOpCode (
2548 if (EFI_ERROR (Status
)) {
2551 ASSERT (StartOpCodeHandle
!= NULL
);
2553 OptionsOpCodeHandle
= NULL
;
2556 // If no attempt to be ordered, update the original form and exit.
2558 if (mPrivate
->AttemptCount
== 0) {
2563 // Create Option OpCode.
2565 OptionsOpCodeHandle
= HiiAllocateOpCodeHandle ();
2566 if (OptionsOpCodeHandle
== NULL
) {
2567 Status
= EFI_OUT_OF_RESOURCES
;
2573 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
2574 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
2575 HiiCreateOneOfOptionOpCode (
2576 OptionsOpCodeHandle
,
2577 AttemptConfigData
->AttemptTitleToken
,
2579 EFI_IFR_NUMERIC_SIZE_1
,
2580 AttemptConfigData
->AttemptConfigIndex
2585 ASSERT (Index
== mPrivate
->AttemptCount
);
2587 HiiCreateOrderedListOpCode (
2588 StartOpCodeHandle
, // Container for dynamic created opcodes
2589 DYNAMIC_ORDERED_LIST_QUESTION_ID
, // Question ID
2590 CONFIGURATION_VARSTORE_ID
, // VarStore ID
2591 DYNAMIC_ORDERED_LIST_VAR_OFFSET
, // Offset in Buffer Storage
2592 STRING_TOKEN (STR_ORDER_ATTEMPT_ENTRY
), // Question prompt text
2593 STRING_TOKEN (STR_ORDER_ATTEMPT_ENTRY
), // Question help text
2595 EFI_IFR_UNIQUE_SET
, // Ordered list flag, e.g. EFI_IFR_UNIQUE_SET
2596 EFI_IFR_NUMERIC_SIZE_1
, // Data type of Question value
2597 ISCSI_MAX_ATTEMPTS_NUM
, // Maximum container
2598 OptionsOpCodeHandle
, // Option Opcode list
2599 NULL
// Default Opcode is NULL
2603 Status
= HiiUpdateForm (
2604 mCallbackInfo
->RegisteredHandle
, // HII handle
2605 &gIScsiConfigGuid
, // Formset GUID
2606 FORMID_ORDER_FORM
, // Form ID
2607 StartOpCodeHandle
, // Label for where to insert opcodes
2608 EndOpCodeHandle
// Replace data
2612 HiiFreeOpCodeHandle (StartOpCodeHandle
);
2613 HiiFreeOpCodeHandle (EndOpCodeHandle
);
2614 if (OptionsOpCodeHandle
!= NULL
) {
2615 HiiFreeOpCodeHandle (OptionsOpCodeHandle
);
2622 Callback function when user presses "Commit Changes and Exit" in Change Attempt Order or Change Attempt Order by Keyword.
2624 @param[in] IfrNvData The IFR nv data.
2626 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
2628 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
2629 @retval EFI_SUCCESS The operation is completed successfully.
2633 IScsiConfigOrderAttempts (
2634 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
2640 UINT8 AttemptConfigIndex
;
2641 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
2642 UINT8
*AttemptConfigOrder
;
2643 UINT8
*AttemptConfigOrderTmp
;
2644 UINTN AttemptConfigOrderSize
;
2646 AttemptConfigOrder
= IScsiGetVariableAndSize (
2649 &AttemptConfigOrderSize
2651 if (AttemptConfigOrder
== NULL
) {
2652 return EFI_NOT_FOUND
;
2655 AttemptConfigOrderTmp
= AllocateZeroPool (AttemptConfigOrderSize
);
2656 if (AttemptConfigOrderTmp
== NULL
) {
2657 Status
= EFI_OUT_OF_RESOURCES
;
2661 for (Index
= 0; Index
< ISCSI_MAX_ATTEMPTS_NUM
; Index
++) {
2663 // The real content ends with 0.
2665 if (IfrNvData
->DynamicOrderedList
[Index
] == 0) {
2669 AttemptConfigIndex
= IfrNvData
->DynamicOrderedList
[Index
];
2670 AttemptConfigData
= IScsiConfigGetAttemptByConfigIndex (AttemptConfigIndex
);
2671 if (AttemptConfigData
== NULL
) {
2672 Status
= EFI_NOT_FOUND
;
2677 // Reorder the Attempt List.
2679 RemoveEntryList (&AttemptConfigData
->Link
);
2680 InsertTailList (&mPrivate
->AttemptConfigs
, &AttemptConfigData
->Link
);
2682 AttemptConfigOrderTmp
[Index
] = AttemptConfigIndex
;
2685 // Mark it to be deleted - 0.
2687 for (Indexj
= 0; Indexj
< AttemptConfigOrderSize
/ sizeof (UINT8
); Indexj
++) {
2688 if (AttemptConfigOrder
[Indexj
] == AttemptConfigIndex
) {
2689 AttemptConfigOrder
[Indexj
] = 0;
2696 // Adjust the attempt order in NVR.
2698 for (; Index
< AttemptConfigOrderSize
/ sizeof (UINT8
); Index
++) {
2699 for (Indexj
= 0; Indexj
< AttemptConfigOrderSize
/ sizeof (UINT8
); Indexj
++) {
2700 if (AttemptConfigOrder
[Indexj
] != 0) {
2701 AttemptConfigOrderTmp
[Index
] = AttemptConfigOrder
[Indexj
];
2702 AttemptConfigOrder
[Indexj
] = 0;
2708 Status
= gRT
->SetVariable (
2711 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
2712 AttemptConfigOrderSize
,
2713 AttemptConfigOrderTmp
2717 if (AttemptConfigOrderTmp
!= NULL
) {
2718 FreePool (AttemptConfigOrderTmp
);
2721 FreePool (AttemptConfigOrder
);
2727 Callback function when a user presses "Attempt *" or when a user selects a NIC to
2728 create the new attempt.
2730 @param[in] KeyValue A unique value which is sent to the original
2731 exporting driver so that it can identify the type
2733 @param[in] IfrNvData The IFR nv data.
2735 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
2737 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
2738 @retval EFI_UNSUPPORTED Can not create more attempts.
2739 @retval EFI_SUCCESS The operation is completed successfully.
2743 IScsiConfigProcessDefault (
2744 IN EFI_QUESTION_ID KeyValue
,
2745 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
2749 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
2750 UINT8 CurrentAttemptConfigIndex
;
2751 ISCSI_NIC_INFO
*NicInfo
;
2753 CHAR16 MacString
[ISCSI_MAX_MAC_STRING_LEN
];
2754 UINT8
*AttemptConfigOrder
;
2755 UINTN AttemptConfigOrderSize
;
2759 AttemptConfigData
= NULL
;
2761 // Is User creating a new attempt?
2765 if ((KeyValue
>= KEY_MAC_ENTRY_BASE
) &&
2766 (KeyValue
<= (UINT16
) (mPrivate
->MaxNic
+ KEY_MAC_ENTRY_BASE
))) {
2768 // User has pressed "Add an Attempt" and then selects a NIC.
2771 } else if ((KeyValue
>= KEY_ATTEMPT_ENTRY_BASE
) &&
2772 (KeyValue
< (ISCSI_MAX_ATTEMPTS_NUM
+ KEY_ATTEMPT_ENTRY_BASE
))) {
2775 // User has pressed "Attempt *".
2780 // Don't process anything.
2787 // Determine which NIC user has selected for the new created attempt.
2789 NicIndex
= (UINT8
) (KeyValue
- KEY_MAC_ENTRY_BASE
);
2790 NicInfo
= IScsiGetNicInfoByIndex (NicIndex
);
2791 if (NicInfo
== NULL
) {
2792 return EFI_NOT_FOUND
;
2796 // Create an attempt following the initialized attempt order.
2798 AttemptConfigOrder
= IScsiGetVariableAndSize (
2799 L
"InitialAttemptOrder",
2801 &AttemptConfigOrderSize
2804 if (AttemptConfigOrder
== NULL
) {
2805 return EFI_NOT_FOUND
;
2808 for (Index
= 0; Index
< AttemptConfigOrderSize
/ sizeof (UINT8
); Index
++) {
2810 mPrivate
->PortString
,
2811 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
2813 (UINTN
) AttemptConfigOrder
[Index
]
2816 mPrivate
->PortString
,
2817 &gEfiIScsiInitiatorNameProtocolGuid
,
2818 (VOID
**)&AttemptConfigData
,
2821 if (AttemptConfigData
== NULL
|| AttemptConfigData
->Actived
== ISCSI_ACTIVE_ENABLED
) {
2828 if (Index
> PcdGet8 (PcdMaxIScsiAttemptNumber
)) {
2830 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2832 L
"Can not create more attempts, Please configure the PcdMaxIScsiAttemptNumber if needed!",
2835 return EFI_UNSUPPORTED
;
2838 if (AttemptConfigOrder
!= NULL
) {
2839 FreePool (AttemptConfigOrder
);
2843 // Record the MAC info in Config Data.
2846 &NicInfo
->PermanentAddress
,
2847 NicInfo
->HwAddressSize
,
2852 ASSERT (AttemptConfigData
!= NULL
);
2853 UnicodeStrToAsciiStrS (MacString
, AttemptConfigData
->MacString
, sizeof (AttemptConfigData
->MacString
));
2854 AttemptConfigData
->NicIndex
= NicIndex
;
2855 AttemptConfigData
->Actived
= ISCSI_ACTIVE_ENABLED
;
2858 // Generate OUI-format ISID based on MAC address.
2860 CopyMem (AttemptConfigData
->SessionConfigData
.IsId
, &NicInfo
->PermanentAddress
, 6);
2861 AttemptConfigData
->SessionConfigData
.IsId
[0] =
2862 (UINT8
) (AttemptConfigData
->SessionConfigData
.IsId
[0] & 0x3F);
2865 // Add the help info for the new attempt.
2868 mPrivate
->PortString
,
2869 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
2870 L
"MAC: %s, PFA: Bus %d | Dev %d | Func %d",
2873 NicInfo
->DeviceNumber
,
2874 NicInfo
->FunctionNumber
2877 AttemptConfigData
->AttemptTitleHelpToken
= HiiSetString (
2878 mCallbackInfo
->RegisteredHandle
,
2880 mPrivate
->PortString
,
2883 if (AttemptConfigData
->AttemptTitleHelpToken
== 0) {
2884 FreePool (AttemptConfigData
);
2885 return EFI_OUT_OF_RESOURCES
;
2890 // Determine which Attempt user has selected to configure.
2891 // Get the attempt configuration data.
2893 CurrentAttemptConfigIndex
= (UINT8
) (KeyValue
- KEY_ATTEMPT_ENTRY_BASE
);
2895 AttemptConfigData
= IScsiConfigGetAttemptByConfigIndex (CurrentAttemptConfigIndex
);
2896 if (AttemptConfigData
== NULL
) {
2897 DEBUG ((DEBUG_ERROR
, "Corresponding configuration data can not be retrieved!\n"));
2898 return EFI_NOT_FOUND
;
2903 // Clear the old IFR data to avoid sharing it with other attempts.
2905 if (IfrNvData
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
2906 ZeroMem (IfrNvData
->CHAPName
, sizeof (IfrNvData
->CHAPName
));
2907 ZeroMem (IfrNvData
->CHAPSecret
, sizeof (IfrNvData
->CHAPSecret
));
2908 ZeroMem (IfrNvData
->ReverseCHAPName
, sizeof (IfrNvData
->ReverseCHAPName
));
2909 ZeroMem (IfrNvData
->ReverseCHAPSecret
, sizeof (IfrNvData
->ReverseCHAPSecret
));
2912 IScsiConvertAttemptConfigDataToIfrNvData (AttemptConfigData
, IfrNvData
);
2915 // Update current attempt to be a new created attempt or an existing attempt.
2917 mCallbackInfo
->Current
= AttemptConfigData
;
2925 This function allows the caller to request the current
2926 configuration for one or more named elements. The resulting
2927 string is in <ConfigAltResp> format. Also, any and all alternative
2928 configuration strings shall be appended to the end of the
2929 current configuration string. If they are, they must appear
2930 after the current configuration. They must contain the same
2931 routing (GUID, NAME, PATH) as the current configuration string.
2932 They must have an additional description indicating the type of
2933 alternative configuration the string represents,
2934 "ALTCFG=<StringToken>". That <StringToken> (when
2935 converted from Hex UNICODE to binary) is a reference to a
2936 string in the associated string pack.
2938 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
2940 @param[in] Request A null-terminated Unicode string in
2941 <ConfigRequest> format. Note that this
2942 includes the routing information as well as
2943 the configurable name / value pairs. It is
2944 invalid for this string to be in
2945 <MultiConfigRequest> format.
2947 @param[out] Progress On return, points to a character in the
2948 Request string. Points to the string's null
2949 terminator if request was successful. Points
2950 to the most recent "&" before the first
2951 failing name / value pair (or the beginning
2952 of the string if the failure is in the first
2953 name / value pair) if the request was not successful.
2955 @param[out] Results A null-terminated Unicode string in
2956 <ConfigAltResp> format which has all values
2957 filled in for the names in the Request string.
2958 String to be allocated by the called function.
2960 @retval EFI_SUCCESS The Results string is filled with the
2961 values corresponding to all requested
2964 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
2965 parts of the results that must be
2966 stored awaiting possible future
2969 @retval EFI_INVALID_PARAMETER For example, passing in a NULL
2970 for the Request parameter
2971 would result in this type of
2972 error. In this case, the
2973 Progress parameter would be
2976 @retval EFI_NOT_FOUND Routing data doesn't match any
2977 known driver. Progress set to the
2978 first character in the routing header.
2979 Note: There is no requirement that the
2980 driver validate the routing data. It
2981 must skip the <ConfigHdr> in order to
2984 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set
2985 to most recent "&" before the
2986 error or the beginning of the
2989 @retval EFI_INVALID_PARAMETER Unknown name. Progress points
2990 to the & before the name in
2996 IScsiFormExtractConfig (
2997 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
2998 IN CONST EFI_STRING Request
,
2999 OUT EFI_STRING
*Progress
,
3000 OUT EFI_STRING
*Results
3004 CHAR8
*InitiatorName
;
3006 ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
;
3007 ISCSI_FORM_CALLBACK_INFO
*Private
;
3008 EFI_STRING ConfigRequestHdr
;
3009 EFI_STRING ConfigRequest
;
3010 BOOLEAN AllocatedRequest
;
3013 if (This
== NULL
|| Progress
== NULL
|| Results
== NULL
) {
3014 return EFI_INVALID_PARAMETER
;
3017 *Progress
= Request
;
3018 if ((Request
!= NULL
) && !HiiIsConfigHdrMatch (Request
, &gIScsiConfigGuid
, mVendorStorageName
)) {
3019 return EFI_NOT_FOUND
;
3022 ConfigRequestHdr
= NULL
;
3023 ConfigRequest
= NULL
;
3024 AllocatedRequest
= FALSE
;
3027 Private
= ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This
);
3028 IfrNvData
= AllocateZeroPool (sizeof (ISCSI_CONFIG_IFR_NVDATA
));
3029 if (IfrNvData
== NULL
) {
3030 return EFI_OUT_OF_RESOURCES
;
3034 if (Private
->Current
!= NULL
) {
3035 IScsiConvertAttemptConfigDataToIfrNvData (Private
->Current
, IfrNvData
);
3039 // Extract all AttemptConfigData to Keyword stroage of IfrNvData.
3041 IScsiConvertAttemptConfigDataToIfrNvDataByKeyword (IfrNvData
);
3043 BufferSize
= ISCSI_NAME_MAX_SIZE
;
3044 InitiatorName
= (CHAR8
*) AllocateZeroPool (BufferSize
);
3045 if (InitiatorName
== NULL
) {
3046 FreePool (IfrNvData
);
3047 return EFI_OUT_OF_RESOURCES
;
3050 Status
= gIScsiInitiatorName
.Get (&gIScsiInitiatorName
, &BufferSize
, InitiatorName
);
3051 if (EFI_ERROR (Status
)) {
3052 IfrNvData
->InitiatorName
[0] = L
'\0';
3054 AsciiStrToUnicodeStrS (
3056 IfrNvData
->InitiatorName
,
3057 sizeof (IfrNvData
->InitiatorName
) / sizeof (IfrNvData
->InitiatorName
[0])
3062 // Convert buffer data to <ConfigResp> by helper function BlockToConfig().
3064 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
3065 ConfigRequest
= Request
;
3066 if ((Request
== NULL
) || (StrStr (Request
, L
"OFFSET") == NULL
)) {
3068 // Request has no request element, construct full request string.
3069 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
3070 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
3072 ConfigRequestHdr
= HiiConstructConfigHdr (&gIScsiConfigGuid
, mVendorStorageName
, Private
->DriverHandle
);
3073 Size
= (StrLen (ConfigRequestHdr
) + 32 + 1) * sizeof (CHAR16
);
3074 ConfigRequest
= AllocateZeroPool (Size
);
3075 if (ConfigRequest
== NULL
) {
3076 FreePool (IfrNvData
);
3077 FreePool (InitiatorName
);
3078 return EFI_OUT_OF_RESOURCES
;
3080 AllocatedRequest
= TRUE
;
3081 UnicodeSPrint (ConfigRequest
, Size
, L
"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr
, (UINT64
)BufferSize
);
3082 FreePool (ConfigRequestHdr
);
3085 Status
= gHiiConfigRouting
->BlockToConfig (
3088 (UINT8
*) IfrNvData
,
3093 FreePool (IfrNvData
);
3094 FreePool (InitiatorName
);
3097 // Free the allocated config request string.
3099 if (AllocatedRequest
) {
3100 FreePool (ConfigRequest
);
3101 ConfigRequest
= NULL
;
3104 // Set Progress string to the original request string.
3106 if (Request
== NULL
) {
3108 } else if (StrStr (Request
, L
"OFFSET") == NULL
) {
3109 *Progress
= Request
+ StrLen (Request
);
3118 This function applies changes in a driver's configuration.
3119 Input is a Configuration, which has the routing data for this
3120 driver followed by name / value configuration pairs. The driver
3121 must apply those pairs to its configurable storage. If the
3122 driver's configuration is stored in a linear block of data
3123 and the driver's name / value pairs are in <BlockConfig>
3124 format, it may use the ConfigToBlock helper function (above) to
3127 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
3129 @param[in] Configuration A null-terminated Unicode string in
3130 <ConfigString> format.
3132 @param[out] Progress A pointer to a string filled in with the
3133 offset of the most recent '&' before the
3134 first failing name / value pair (or the
3135 beginning of the string if the failure
3136 is in the first name / value pair) or
3137 the terminating NULL if all was
3140 @retval EFI_SUCCESS The results have been distributed or are
3141 awaiting distribution.
3143 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
3144 parts of the results that must be
3145 stored awaiting possible future
3148 @retval EFI_INVALID_PARAMETERS Passing in a NULL for the
3149 Results parameter would result
3150 in this type of error.
3152 @retval EFI_NOT_FOUND Target for the specified routing data
3158 IScsiFormRouteConfig (
3159 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
3160 IN CONST EFI_STRING Configuration
,
3161 OUT EFI_STRING
*Progress
3165 ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
;
3166 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
3168 LIST_ENTRY
*NextEntry
;
3169 ISCSI_NIC_INFO
*NicInfo
;
3171 CHAR16 MacString
[ISCSI_MAX_MAC_STRING_LEN
];
3172 CHAR8
*InitiatorName
;
3183 Status
= EFI_SUCCESS
;
3185 if (This
== NULL
|| Configuration
== NULL
|| Progress
== NULL
) {
3186 return EFI_INVALID_PARAMETER
;
3190 // Check routing data in <ConfigHdr>.
3191 // Note: if only one Storage is used, then this checking could be skipped.
3193 if (!HiiIsConfigHdrMatch (Configuration
, &gIScsiConfigGuid
, mVendorStorageName
)) {
3194 *Progress
= Configuration
;
3195 return EFI_NOT_FOUND
;
3198 IfrNvData
= AllocateZeroPool (sizeof (ISCSI_CONFIG_IFR_NVDATA
));
3199 if (IfrNvData
== NULL
) {
3200 return EFI_OUT_OF_RESOURCES
;
3203 BufferSize
= ISCSI_NAME_MAX_SIZE
;
3204 InitiatorName
= (CHAR8
*) AllocateZeroPool (BufferSize
);
3205 if (InitiatorName
== NULL
) {
3206 Status
= EFI_OUT_OF_RESOURCES
;
3211 // Convert <ConfigResp> to buffer data by helper function ConfigToBlock().
3213 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
3214 Status
= gHiiConfigRouting
->ConfigToBlock (
3217 (UINT8
*) IfrNvData
,
3221 if (EFI_ERROR (Status
)) {
3225 if (IfrNvData
->InitiatorName
[0] != L
'\0') {
3226 UnicodeStrToAsciiStrS (IfrNvData
->InitiatorName
, InitiatorName
, ISCSI_NAME_MAX_SIZE
);
3227 BufferSize
= AsciiStrSize (InitiatorName
);
3229 Status
= gIScsiInitiatorName
.Set (&gIScsiInitiatorName
, &BufferSize
, InitiatorName
);
3230 if (EFI_ERROR (Status
)) {
3232 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3234 L
"Invalid iSCSI Name!",
3240 Status
= IScsiGetValue (Configuration
, L
"&OFFSET=", &OffSet
);
3241 if (EFI_ERROR (Status
)) {
3245 if (OffSet
>= ATTEMPT_MAC_ADDR_VAR_OFFSET
) {
3246 Status
= gIScsiInitiatorName
.Get (&gIScsiInitiatorName
, &BufferSize
, InitiatorName
);
3247 if (EFI_ERROR (Status
)) {
3249 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3251 L
"Error: please configure iSCSI initiator name first!",
3260 if (IfrNvData
->ISCSIAddAttemptList
[0] != L
'\0') {
3261 Status
=IScsiGetAttemptIndexList (IfrNvData
->ISCSIAddAttemptList
, IfrNvData
->AddAttemptList
, TRUE
);
3262 if (EFI_ERROR (Status
)) {
3264 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3266 L
"Error: The add attempt list is invalid",
3272 Status
= IScsiConfigAddAttemptsByKeywords (IfrNvData
->AddAttemptList
);
3273 if (EFI_ERROR (Status
)) {
3277 } else if (IfrNvData
->ISCSIDeleteAttemptList
[0] != L
'\0') {
3278 AttemptList
=(UINT8
*) AllocateZeroPool ((ISCSI_MAX_ATTEMPTS_NUM
+ 1) * sizeof (UINT8
));
3279 if (AttemptList
== NULL
) {
3280 Status
= EFI_OUT_OF_RESOURCES
;
3283 Status
= IScsiGetAttemptIndexList (IfrNvData
->ISCSIDeleteAttemptList
, AttemptList
, FALSE
);
3284 if (EFI_ERROR (Status
)) {
3286 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3288 L
"Error: The delete attempt list is invalid",
3295 // Mark the attempt which will be delete in the global list.
3297 NET_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &mPrivate
->AttemptConfigs
) {
3298 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
3299 while (AttemptList
[Index
] != 0) {
3300 if (AttemptConfigData
->AttemptConfigIndex
== AttemptList
[Index
]) {
3301 IfrNvData
->DeleteAttemptList
[Index2
] = 1;
3310 Status
= IScsiConfigDeleteAttempts (IfrNvData
);
3311 if (EFI_ERROR (Status
)) {
3315 FreePool (AttemptList
);
3317 } else if (IfrNvData
->ISCSIAttemptOrder
[0] != L
'\0') {
3318 Status
= IScsiGetAttemptIndexList (IfrNvData
->ISCSIAttemptOrder
, IfrNvData
->DynamicOrderedList
, FALSE
);
3319 if (EFI_ERROR (Status
)) {
3321 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3323 L
"Error: The new attempt order list is invalid",
3329 Status
= IScsiConfigOrderAttempts (IfrNvData
);
3330 if (EFI_ERROR (Status
)) {
3334 } else if (IfrNvData
->ISCSIMacAddr
[0] != L
'\0') {
3335 NET_LIST_FOR_EACH (Entry
, &mPrivate
->NicInfoList
) {
3336 NicInfo
= NET_LIST_USER_STRUCT (Entry
, ISCSI_NIC_INFO
, Link
);
3338 &NicInfo
->PermanentAddress
,
3339 NicInfo
->HwAddressSize
,
3343 if (!StrCmp(MacString
, IfrNvData
->ISCSIMacAddr
)) {
3344 mPrivate
->CurrentNic
= NicInfo
->NicIndex
;
3349 if ((NicInfo
== NULL
) || (NicInfo
->NicIndex
== 0)) {
3350 Status
= EFI_NOT_FOUND
;
3355 Status
= IScsiConvertlfrNvDataToAttemptConfigDataByKeyword (IfrNvData
, OffSet
);
3356 if (EFI_ERROR (Status
)) {
3362 IScsiConfigUpdateAttempt ();
3365 if (InitiatorName
!= NULL
) {
3366 FreePool (InitiatorName
);
3369 if (IfrNvData
!= NULL
) {
3370 FreePool (IfrNvData
);
3378 This function is called to provide results data to the driver.
3379 This data consists of a unique key that is used to identify
3380 which data is either being passed back or being asked for.
3382 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
3383 @param[in] Action Specifies the type of action taken by the browser.
3384 @param[in] QuestionId A unique value which is sent to the original
3385 exporting driver so that it can identify the type
3386 of data to expect. The format of the data tends to
3387 vary based on the opcode that generated the callback.
3388 @param[in] Type The type of value for the question.
3389 @param[in, out] Value A pointer to the data being sent to the original
3391 @param[out] ActionRequest On return, points to the action requested by the
3394 @retval EFI_SUCCESS The callback successfully handled the action.
3395 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
3396 variable and its data.
3397 @retval EFI_DEVICE_ERROR The variable could not be saved.
3398 @retval EFI_UNSUPPORTED The specified Action is not supported by the
3404 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
3405 IN EFI_BROWSER_ACTION Action
,
3406 IN EFI_QUESTION_ID QuestionId
,
3408 IN OUT EFI_IFR_TYPE_VALUE
*Value
,
3409 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
3412 ISCSI_FORM_CALLBACK_INFO
*Private
;
3415 CHAR8 IpString
[ISCSI_NAME_MAX_SIZE
];
3416 CHAR8 LunString
[ISCSI_LUN_STR_MAX_LEN
];
3418 EFI_IP_ADDRESS HostIp
;
3419 EFI_IP_ADDRESS SubnetMask
;
3420 EFI_IP_ADDRESS Gateway
;
3421 ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
;
3422 ISCSI_CONFIG_IFR_NVDATA OldIfrNvData
;
3425 ISCSI_NIC_INFO
*NicInfo
;
3429 if ((Action
== EFI_BROWSER_ACTION_FORM_OPEN
) || (Action
== EFI_BROWSER_ACTION_FORM_CLOSE
)) {
3431 // Do nothing for UEFI OPEN/CLOSE Action
3436 if ((Action
!= EFI_BROWSER_ACTION_CHANGING
) && (Action
!= EFI_BROWSER_ACTION_CHANGED
)) {
3438 // All other type return unsupported.
3440 return EFI_UNSUPPORTED
;
3443 if ((Value
== NULL
) || (ActionRequest
== NULL
)) {
3444 return EFI_INVALID_PARAMETER
;
3447 Private
= ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This
);
3450 // Retrieve uncommitted data from Browser
3453 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
3454 IfrNvData
= AllocateZeroPool (BufferSize
);
3455 if (IfrNvData
== NULL
) {
3456 return EFI_OUT_OF_RESOURCES
;
3459 IScsiName
= (CHAR8
*) AllocateZeroPool (ISCSI_NAME_MAX_SIZE
);
3460 if (IScsiName
== NULL
) {
3461 FreePool (IfrNvData
);
3462 return EFI_OUT_OF_RESOURCES
;
3465 Status
= EFI_SUCCESS
;
3467 ZeroMem (&OldIfrNvData
, BufferSize
);
3469 HiiGetBrowserData (NULL
, NULL
, BufferSize
, (UINT8
*) IfrNvData
);
3471 CopyMem (&OldIfrNvData
, IfrNvData
, BufferSize
);
3473 if (Action
== EFI_BROWSER_ACTION_CHANGING
) {
3474 switch (QuestionId
) {
3475 case KEY_ADD_ATTEMPT
:
3477 // Check whether iSCSI initiator name is configured already.
3479 mPrivate
->InitiatorNameLength
= ISCSI_NAME_MAX_SIZE
;
3480 Status
= gIScsiInitiatorName
.Get (
3481 &gIScsiInitiatorName
,
3482 &mPrivate
->InitiatorNameLength
,
3483 mPrivate
->InitiatorName
3485 if (EFI_ERROR (Status
)) {
3487 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3489 L
"Error: please configure iSCSI initiator name first!",
3495 Status
= IScsiConfigAddAttempt ();
3498 case KEY_DELETE_ATTEMPT
:
3500 OldIfrNvData
.DeleteAttemptList
,
3501 IfrNvData
->DeleteAttemptList
,
3502 sizeof (IfrNvData
->DeleteAttemptList
)
3504 Status
= IScsiConfigDisplayDeleteAttempts (IfrNvData
);
3507 case KEY_ORDER_ATTEMPT_CONFIG
:
3509 // Order the attempt according to user input.
3512 OldIfrNvData
.DynamicOrderedList
,
3513 IfrNvData
->DynamicOrderedList
,
3514 sizeof (IfrNvData
->DynamicOrderedList
)
3516 IScsiConfigDisplayOrderAttempts ();
3520 Status
= IScsiConfigProcessDefault (QuestionId
, IfrNvData
);
3523 } else if (Action
== EFI_BROWSER_ACTION_CHANGED
) {
3524 switch (QuestionId
) {
3525 case KEY_INITIATOR_NAME
:
3526 UnicodeStrToAsciiStrS (IfrNvData
->InitiatorName
, IScsiName
, ISCSI_NAME_MAX_SIZE
);
3527 BufferSize
= AsciiStrSize (IScsiName
);
3529 Status
= gIScsiInitiatorName
.Set (&gIScsiInitiatorName
, &BufferSize
, IScsiName
);
3530 if (EFI_ERROR (Status
)) {
3532 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3534 L
"Invalid iSCSI Name!",
3539 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
3542 case KEY_SAVE_ATTEMPT_CONFIG
:
3543 Status
= IScsiConvertIfrNvDataToAttemptConfigData (IfrNvData
, Private
->Current
);
3544 if (EFI_ERROR (Status
)) {
3548 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT
;
3551 case KEY_SAVE_ORDER_CHANGES
:
3553 // Sync the Attempt Order to NVR.
3555 Status
= IScsiConfigOrderAttempts (IfrNvData
);
3556 if (EFI_ERROR (Status
)) {
3560 IScsiConfigUpdateAttempt ();
3561 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT
;
3564 case KEY_IGNORE_ORDER_CHANGES
:
3566 IfrNvData
->DynamicOrderedList
,
3567 OldIfrNvData
.DynamicOrderedList
,
3568 sizeof (IfrNvData
->DynamicOrderedList
)
3570 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT
;
3573 case KEY_SAVE_DELETE_ATTEMPT
:
3575 // Delete the Attempt Order from NVR
3577 Status
= IScsiConfigDeleteAttempts (IfrNvData
);
3578 if (EFI_ERROR (Status
)) {
3582 IScsiConfigUpdateAttempt ();
3583 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT
;
3586 case KEY_IGNORE_DELETE_ATTEMPT
:
3588 IfrNvData
->DeleteAttemptList
,
3589 OldIfrNvData
.DeleteAttemptList
,
3590 sizeof (IfrNvData
->DeleteAttemptList
)
3592 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT
;
3596 switch (Value
->u8
) {
3598 NicInfo
= IScsiGetNicInfoByIndex (Private
->Current
->NicIndex
);
3599 if(NicInfo
== NULL
) {
3603 if(!NicInfo
->Ipv6Available
) {
3605 // Current NIC doesn't Support IPv6, hence use IPv4.
3607 IfrNvData
->IpMode
= IP_MODE_IP4
;
3610 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3612 L
"Current NIC doesn't Support IPv6!",
3618 ZeroMem (IfrNvData
->LocalIp
, sizeof (IfrNvData
->LocalIp
));
3619 ZeroMem (IfrNvData
->SubnetMask
, sizeof (IfrNvData
->SubnetMask
));
3620 ZeroMem (IfrNvData
->Gateway
, sizeof (IfrNvData
->Gateway
));
3621 ZeroMem (IfrNvData
->TargetIp
, sizeof (IfrNvData
->TargetIp
));
3622 Private
->Current
->AutoConfigureMode
= 0;
3623 ZeroMem (&Private
->Current
->SessionConfigData
.LocalIp
, sizeof (EFI_IP_ADDRESS
));
3624 ZeroMem (&Private
->Current
->SessionConfigData
.SubnetMask
, sizeof (EFI_IPv4_ADDRESS
));
3625 ZeroMem (&Private
->Current
->SessionConfigData
.Gateway
, sizeof (EFI_IP_ADDRESS
));
3626 ZeroMem (&Private
->Current
->SessionConfigData
.TargetIp
, sizeof (EFI_IP_ADDRESS
));
3634 Status
= NetLibStrToIp4 (IfrNvData
->LocalIp
, &HostIp
.v4
);
3635 if (EFI_ERROR (Status
) ||
3636 ((Private
->Current
->SessionConfigData
.SubnetMask
.Addr
[0] != 0) &&
3637 !NetIp4IsUnicast (NTOHL (HostIp
.Addr
[0]), NTOHL(*(UINT32
*)Private
->Current
->SessionConfigData
.SubnetMask
.Addr
)))) {
3639 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3641 L
"Invalid IP address!",
3645 Status
= EFI_INVALID_PARAMETER
;
3647 CopyMem (&Private
->Current
->SessionConfigData
.LocalIp
, &HostIp
.v4
, sizeof (HostIp
.v4
));
3652 case KEY_SUBNET_MASK
:
3653 Status
= NetLibStrToIp4 (IfrNvData
->SubnetMask
, &SubnetMask
.v4
);
3654 if (EFI_ERROR (Status
) || ((SubnetMask
.Addr
[0] != 0) && (IScsiGetSubnetMaskPrefixLength (&SubnetMask
.v4
) == 0))) {
3656 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3658 L
"Invalid Subnet Mask!",
3662 Status
= EFI_INVALID_PARAMETER
;
3664 CopyMem (&Private
->Current
->SessionConfigData
.SubnetMask
, &SubnetMask
.v4
, sizeof (SubnetMask
.v4
));
3670 Status
= NetLibStrToIp4 (IfrNvData
->Gateway
, &Gateway
.v4
);
3671 if (EFI_ERROR (Status
) ||
3672 ((Gateway
.Addr
[0] != 0) &&
3673 (Private
->Current
->SessionConfigData
.SubnetMask
.Addr
[0] != 0) &&
3674 !NetIp4IsUnicast (NTOHL (Gateway
.Addr
[0]), NTOHL(*(UINT32
*)Private
->Current
->SessionConfigData
.SubnetMask
.Addr
)))) {
3676 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3678 L
"Invalid Gateway!",
3681 Status
= EFI_INVALID_PARAMETER
;
3683 CopyMem (&Private
->Current
->SessionConfigData
.Gateway
, &Gateway
.v4
, sizeof (Gateway
.v4
));
3689 UnicodeStrToAsciiStrS (IfrNvData
->TargetIp
, IpString
, sizeof (IpString
));
3690 Status
= IScsiAsciiStrToIp (IpString
, IfrNvData
->IpMode
, &HostIp
);
3691 if (EFI_ERROR (Status
) || !IpIsUnicast (&HostIp
, IfrNvData
->IpMode
)) {
3693 // The target is expressed in URL format or an invalid Ip address, just save.
3695 Private
->Current
->SessionConfigData
.DnsMode
= TRUE
;
3696 ZeroMem (&Private
->Current
->SessionConfigData
.TargetIp
, sizeof (Private
->Current
->SessionConfigData
.TargetIp
));
3697 UnicodeStrToAsciiStrS (IfrNvData
->TargetIp
, Private
->Current
->SessionConfigData
.TargetUrl
, ISCSI_NAME_MAX_SIZE
);
3699 Private
->Current
->SessionConfigData
.DnsMode
= FALSE
;
3700 CopyMem (&Private
->Current
->SessionConfigData
.TargetIp
, &HostIp
, sizeof (HostIp
));
3705 case KEY_TARGET_NAME
:
3706 UnicodeStrToAsciiStrS (IfrNvData
->TargetName
, IScsiName
, ISCSI_NAME_MAX_SIZE
);
3707 Status
= IScsiNormalizeName (IScsiName
, AsciiStrLen (IScsiName
));
3708 if (EFI_ERROR (Status
)) {
3710 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3712 L
"Invalid iSCSI Name!",
3716 AsciiStrCpyS (Private
->Current
->SessionConfigData
.TargetName
, ISCSI_NAME_MAX_SIZE
, IScsiName
);
3721 case KEY_DHCP_ENABLE
:
3722 if (IfrNvData
->InitiatorInfoFromDhcp
== 0) {
3723 IfrNvData
->TargetInfoFromDhcp
= 0;
3729 UnicodeStrToAsciiStrS (IfrNvData
->BootLun
, LunString
, sizeof (LunString
));
3730 Status
= IScsiAsciiStrToLun (LunString
, (UINT8
*) &Lun
);
3731 if (EFI_ERROR (Status
)) {
3733 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3735 L
"Invalid LUN string!",
3739 CopyMem (Private
->Current
->SessionConfigData
.BootLun
, &Lun
, sizeof (Lun
));
3745 switch (Value
->u8
) {
3746 case ISCSI_AUTH_TYPE_CHAP
:
3747 IfrNvData
->CHAPType
= ISCSI_CHAP_UNI
;
3756 UnicodeStrToAsciiStrS (
3757 IfrNvData
->CHAPName
,
3758 Private
->Current
->AuthConfigData
.CHAP
.CHAPName
,
3759 sizeof (Private
->Current
->AuthConfigData
.CHAP
.CHAPName
)
3763 case KEY_CHAP_SECRET
:
3764 UnicodeStrToAsciiStrS (
3765 IfrNvData
->CHAPSecret
,
3766 Private
->Current
->AuthConfigData
.CHAP
.CHAPSecret
,
3767 sizeof (Private
->Current
->AuthConfigData
.CHAP
.CHAPSecret
)
3771 case KEY_REVERSE_CHAP_NAME
:
3772 UnicodeStrToAsciiStrS (
3773 IfrNvData
->ReverseCHAPName
,
3774 Private
->Current
->AuthConfigData
.CHAP
.ReverseCHAPName
,
3775 sizeof (Private
->Current
->AuthConfigData
.CHAP
.ReverseCHAPName
)
3779 case KEY_REVERSE_CHAP_SECRET
:
3780 UnicodeStrToAsciiStrS (
3781 IfrNvData
->ReverseCHAPSecret
,
3782 Private
->Current
->AuthConfigData
.CHAP
.ReverseCHAPSecret
,
3783 sizeof (Private
->Current
->AuthConfigData
.CHAP
.ReverseCHAPSecret
)
3787 case KEY_CONFIG_ISID
:
3788 IScsiParseIsIdFromString (IfrNvData
->IsId
, Private
->Current
->SessionConfigData
.IsId
);
3789 IScsiConvertIsIdToString (IfrNvData
->IsId
, Private
->Current
->SessionConfigData
.IsId
);
3798 if (!EFI_ERROR (Status
)) {
3800 // Pass changed uncommitted data back to Form Browser.
3802 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
3803 HiiSetBrowserData (NULL
, NULL
, BufferSize
, (UINT8
*) IfrNvData
, NULL
);
3806 FreePool (IfrNvData
);
3807 FreePool (IScsiName
);
3814 Initialize the iSCSI configuration form.
3816 @param[in] DriverBindingHandle The iSCSI driverbinding handle.
3818 @retval EFI_SUCCESS The iSCSI configuration form is initialized.
3819 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
3823 IScsiConfigFormInit (
3824 IN EFI_HANDLE DriverBindingHandle
3828 ISCSI_FORM_CALLBACK_INFO
*CallbackInfo
;
3830 CallbackInfo
= (ISCSI_FORM_CALLBACK_INFO
*) AllocateZeroPool (sizeof (ISCSI_FORM_CALLBACK_INFO
));
3831 if (CallbackInfo
== NULL
) {
3832 return EFI_OUT_OF_RESOURCES
;
3835 CallbackInfo
->Signature
= ISCSI_FORM_CALLBACK_INFO_SIGNATURE
;
3836 CallbackInfo
->Current
= NULL
;
3838 CallbackInfo
->ConfigAccess
.ExtractConfig
= IScsiFormExtractConfig
;
3839 CallbackInfo
->ConfigAccess
.RouteConfig
= IScsiFormRouteConfig
;
3840 CallbackInfo
->ConfigAccess
.Callback
= IScsiFormCallback
;
3843 // Install Device Path Protocol and Config Access protocol to driver handle.
3845 Status
= gBS
->InstallMultipleProtocolInterfaces (
3846 &CallbackInfo
->DriverHandle
,
3847 &gEfiDevicePathProtocolGuid
,
3848 &mIScsiHiiVendorDevicePath
,
3849 &gEfiHiiConfigAccessProtocolGuid
,
3850 &CallbackInfo
->ConfigAccess
,
3853 ASSERT_EFI_ERROR (Status
);
3856 // Publish our HII data.
3858 CallbackInfo
->RegisteredHandle
= HiiAddPackages (
3860 CallbackInfo
->DriverHandle
,
3865 if (CallbackInfo
->RegisteredHandle
== NULL
) {
3866 gBS
->UninstallMultipleProtocolInterfaces (
3867 &CallbackInfo
->DriverHandle
,
3868 &gEfiDevicePathProtocolGuid
,
3869 &mIScsiHiiVendorDevicePath
,
3870 &gEfiHiiConfigAccessProtocolGuid
,
3871 &CallbackInfo
->ConfigAccess
,
3874 FreePool(CallbackInfo
);
3875 return EFI_OUT_OF_RESOURCES
;
3878 mCallbackInfo
= CallbackInfo
;
3885 Unload the iSCSI configuration form, this includes: delete all the iSCSI
3886 configuration entries, uninstall the form callback protocol, and
3887 free the resources used.
3889 @param[in] DriverBindingHandle The iSCSI driverbinding handle.
3891 @retval EFI_SUCCESS The iSCSI configuration form is unloaded.
3892 @retval Others Failed to unload the form.
3896 IScsiConfigFormUnload (
3897 IN EFI_HANDLE DriverBindingHandle
3900 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
3901 ISCSI_NIC_INFO
*NicInfo
;
3905 while (!IsListEmpty (&mPrivate
->AttemptConfigs
)) {
3906 Entry
= NetListRemoveHead (&mPrivate
->AttemptConfigs
);
3907 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
3908 FreePool (AttemptConfigData
);
3909 mPrivate
->AttemptCount
--;
3912 ASSERT (mPrivate
->AttemptCount
== 0);
3914 while (!IsListEmpty (&mPrivate
->NicInfoList
)) {
3915 Entry
= NetListRemoveHead (&mPrivate
->NicInfoList
);
3916 NicInfo
= NET_LIST_USER_STRUCT (Entry
, ISCSI_NIC_INFO
, Link
);
3918 mPrivate
->NicCount
--;
3921 ASSERT (mPrivate
->NicCount
== 0);
3923 FreePool (mPrivate
);
3927 // Remove HII package list.
3929 HiiRemovePackages (mCallbackInfo
->RegisteredHandle
);
3932 // Uninstall Device Path Protocol and Config Access protocol.
3934 Status
= gBS
->UninstallMultipleProtocolInterfaces (
3935 mCallbackInfo
->DriverHandle
,
3936 &gEfiDevicePathProtocolGuid
,
3937 &mIScsiHiiVendorDevicePath
,
3938 &gEfiHiiConfigAccessProtocolGuid
,
3939 &mCallbackInfo
->ConfigAccess
,
3943 FreePool (mCallbackInfo
);