2 Helper functions for configuring or getting the parameters relating to iSCSI.
4 Copyright (c) 2004 - 2017, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "IScsiImpl.h"
17 CHAR16 mVendorStorageName
[] = L
"ISCSI_CONFIG_IFR_NVDATA";
18 BOOLEAN mIScsiDeviceListUpdated
= FALSE
;
19 UINTN mNumberOfIScsiDevices
= 0;
20 ISCSI_FORM_CALLBACK_INFO
*mCallbackInfo
= NULL
;
22 HII_VENDOR_DEVICE_PATH mIScsiHiiVendorDevicePath
= {
28 (UINT8
) (sizeof (VENDOR_DEVICE_PATH
)),
29 (UINT8
) ((sizeof (VENDOR_DEVICE_PATH
)) >> 8)
36 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
38 (UINT8
) (END_DEVICE_PATH_LENGTH
),
39 (UINT8
) ((END_DEVICE_PATH_LENGTH
) >> 8)
46 Convert the IP address into a dotted string.
48 @param[in] Ip The IP address.
49 @param[in] Ipv6Flag Indicates whether the IP address is version 4 or version 6.
50 @param[out] Str The formatted IP string.
55 IN EFI_IP_ADDRESS
*Ip
,
60 EFI_IPv4_ADDRESS
*Ip4
;
61 EFI_IPv6_ADDRESS
*Ip6
;
65 CHAR16 FormatString
[8];
72 (UINTN
) 2 * IP4_STR_MAX_SIZE
,
86 for (Index
= 0; Index
< 15; Index
= Index
+ 2) {
89 Ip6
->Addr
[Index
] == 0 &&
90 Ip6
->Addr
[Index
+ 1] == 0
93 // Deal with the case of ::.
104 while ((Index
< 15) && (Ip6
->Addr
[Index
] == 0) && (Ip6
->Addr
[Index
+ 1] == 0)) {
112 // :: is at the end of the address.
121 if (Ip6
->Addr
[Index
] == 0) {
122 Number
= UnicodeSPrint (Str
, 2 * IP_STR_MAX_SIZE
, L
"%x:", (UINTN
) Ip6
->Addr
[Index
+ 1]);
124 if (Ip6
->Addr
[Index
+ 1] < 0x10) {
125 CopyMem (FormatString
, L
"%x0%x:", StrSize (L
"%x0%x:"));
127 CopyMem (FormatString
, L
"%x%x:", StrSize (L
"%x%x:"));
130 Number
= UnicodeSPrint (
133 (CONST CHAR16
*) FormatString
,
134 (UINTN
) Ip6
->Addr
[Index
],
135 (UINTN
) Ip6
->Addr
[Index
+ 1]
141 if (Index
+ 2 == 16) {
143 if (*(Str
- 1) == L
':') {
151 Check whether the input IP address is valid.
153 @param[in] Ip The IP address.
154 @param[in] IpMode Indicates iSCSI running on IP4 or IP6 stack.
156 @retval TRUE The input IP address is valid.
157 @retval FALSE Otherwise
162 IN EFI_IP_ADDRESS
*Ip
,
166 if (IpMode
== IP_MODE_IP4
) {
167 if (IP4_IS_UNSPECIFIED (NTOHL (Ip
->Addr
[0])) || IP4_IS_LOCAL_BROADCAST (NTOHL (Ip
->Addr
[0]))) {
171 } else if (IpMode
== IP_MODE_IP6
) {
172 return NetIp6IsValidUnicast (&Ip
->v6
);
174 DEBUG ((DEBUG_ERROR
, "IpMode %d is invalid when configuring the iSCSI target IP!\n", IpMode
));
180 Parse IsId in string format and convert it to binary.
182 @param[in] String The buffer of the string to be parsed.
183 @param[in, out] IsId The buffer to store IsId.
185 @retval EFI_SUCCESS The operation finished successfully.
186 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
190 IScsiParseIsIdFromString (
191 IN CONST CHAR16
*String
,
199 CHAR16 PortString
[ISCSI_NAME_IFR_MAX_SIZE
];
202 if ((String
== NULL
) || (IsId
== NULL
)) {
203 return EFI_INVALID_PARAMETER
;
206 IsIdStr
= (CHAR16
*) String
;
208 if (StrLen (IsIdStr
) != 6 && StrLen (IsIdStr
) != 12) {
211 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
212 L
"Error! Only last 3 bytes are configurable, please input 6 hex numbers for last 3 bytes only or 12 hex numbers for full SSID!\n"
216 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
222 return EFI_INVALID_PARAMETER
;
225 if (StrLen (IsIdStr
) == 12) {
229 for (Index
= 3; Index
< 6; Index
++) {
230 CopyMem (TempStr
, IsIdStr
, sizeof (TempStr
));
234 // Convert the string to IsId. StrHexToUintn stops at the first character
235 // that is not a valid hex character, '\0' here.
237 NodeVal
= StrHexToUintn (TempStr
);
239 IsId
[Index
] = (UINT8
) NodeVal
;
241 IsIdStr
= IsIdStr
+ 2;
248 Convert IsId from binary to string format.
250 @param[out] String The buffer to store the converted string.
251 @param[in] IsId The buffer to store IsId.
253 @retval EFI_SUCCESS The string converted successfully.
254 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
258 IScsiConvertIsIdToString (
266 if ((String
== NULL
) || (IsId
== NULL
)) {
267 return EFI_INVALID_PARAMETER
;
270 for (Index
= 0; Index
< 6; Index
++) {
271 if (IsId
[Index
] <= 0xF) {
272 Number
= UnicodeSPrint (
274 2 * ISID_CONFIGURABLE_STORAGE
,
279 Number
= UnicodeSPrint (
281 2 * ISID_CONFIGURABLE_STORAGE
,
288 String
= String
+ Number
;
297 Get the Offset value specified by the input String.
299 @param[in] Configuration A null-terminated Unicode string in
300 <ConfigString> format.
301 @param[in] String The string is "&OFFSET=".
302 @param[out] Value The Offset value.
304 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store neccessary
306 @retval EFI_SUCCESS Value of <Number> is outputted in Number
312 IN CONST EFI_STRING Configuration
,
332 StringPtr
= StrStr (Configuration
, String
);
333 ASSERT(StringPtr
!= NULL
);
334 StringPtr
+= StrLen (String
);
337 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
340 Length
= StringPtr
- TmpPtr
;
343 Str
= AllocateZeroPool (Len
* sizeof (CHAR16
));
345 Status
= EFI_OUT_OF_RESOURCES
;
349 CopyMem (Str
, TmpPtr
, Len
* sizeof (CHAR16
));
350 *(Str
+ Length
) = L
'\0';
353 Buf
= (UINT8
*) AllocateZeroPool (Len
);
355 Status
= EFI_OUT_OF_RESOURCES
;
359 ZeroMem (TmpStr
, sizeof (TmpStr
));
360 for (Index
= 0; Index
< Length
; Index
++) {
361 TmpStr
[0] = Str
[Length
- Index
- 1];
362 DigitUint8
= (UINT8
) StrHexToUint64 (TmpStr
);
363 if ((Index
& 1) == 0) {
364 Buf
[Index
/2] = DigitUint8
;
366 Buf
[Index
/2] = (UINT8
) ((DigitUint8
<< 4) + Buf
[Index
/2]);
374 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
378 Status
= EFI_SUCCESS
;
389 Get the attempt config data from global structure by the ConfigIndex.
391 @param[in] AttemptConfigIndex The unique index indicates the attempt.
393 @return Pointer to the attempt config data.
394 @retval NULL The attempt configuration data cannot be found.
397 ISCSI_ATTEMPT_CONFIG_NVDATA
*
398 IScsiConfigGetAttemptByConfigIndex (
399 IN UINT8 AttemptConfigIndex
403 ISCSI_ATTEMPT_CONFIG_NVDATA
*Attempt
;
405 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
406 Attempt
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
407 if (Attempt
->AttemptConfigIndex
== AttemptConfigIndex
) {
417 Get the existing attempt config data from global structure by the NicIndex.
419 @param[in] NewAttempt The created new attempt
420 @param[in] IScsiMode The IScsi Mode of the new attempt, Enabled or
423 @return Pointer to the existing attempt config data which
424 has the same NICIndex as the new created attempt.
425 @retval NULL The attempt with NicIndex does not exist.
428 ISCSI_ATTEMPT_CONFIG_NVDATA
*
429 IScsiConfigGetAttemptByNic (
430 IN ISCSI_ATTEMPT_CONFIG_NVDATA
*NewAttempt
,
435 ISCSI_ATTEMPT_CONFIG_NVDATA
*Attempt
;
437 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
438 Attempt
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
439 if (Attempt
!= NewAttempt
&& Attempt
->NicIndex
== NewAttempt
->NicIndex
&&
440 Attempt
->SessionConfigData
.Enabled
== IScsiMode
) {
449 Extract the Index of the attempt list.
451 @param[in] AttemptNameList The Name list of the Attempts.
452 @param[out] AttemptIndexList The Index list of the Attempts.
453 @param[in] IsAddAttempts If TRUE, Indicates add one or more attempts.
454 If FALSE, Indicates delete attempts or change attempt order.
456 @retval EFI_SUCCESS The Attempt list is valid.
457 @retval EFI_INVALID_PARAMETERS The Attempt List is invalid.
461 IScsiGetAttemptIndexList (
462 IN CHAR16
*AttemptNameList
,
463 OUT UINT8
*AttemptIndexList
,
464 IN BOOLEAN IsAddAttempts
467 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
475 if ((AttemptNameList
== NULL
) || (*AttemptNameList
== L
'\0')) {
476 return EFI_INVALID_PARAMETER
;
479 AttemptStr
= AttemptNameList
;
480 Len
= StrLen (L
"attempt:");
482 while (*AttemptStr
!= L
'\0') {
483 AttemptStr
= StrStr (AttemptStr
, L
"attempt:");
484 if (AttemptStr
== NULL
) {
485 return EFI_INVALID_PARAMETER
;
488 AttemptIndex
= (UINT8
)(*AttemptStr
- L
'0');
489 AttemptConfigData
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
491 if ((AttemptConfigData
!= NULL
) || ((AttemptIndex
) > PcdGet8 (PcdMaxIScsiAttemptNumber
))) {
492 return EFI_INVALID_PARAMETER
;
495 if (AttemptConfigData
== NULL
) {
496 return EFI_INVALID_PARAMETER
;
500 AttemptIndexList
[Index
] = AttemptIndex
;
508 Convert the iSCSI configuration data into the IFR data.
510 @param[in] Attempt The iSCSI attempt config data.
511 @param[in, out] IfrNvData The IFR nv data.
515 IScsiConvertAttemptConfigDataToIfrNvData (
516 IN ISCSI_ATTEMPT_CONFIG_NVDATA
*Attempt
,
517 IN OUT ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
520 ISCSI_SESSION_CONFIG_NVDATA
*SessionConfigData
;
521 ISCSI_CHAP_AUTH_CONFIG_NVDATA
*AuthConfigData
;
526 // Normal session configuration parameters.
528 SessionConfigData
= &Attempt
->SessionConfigData
;
529 IfrNvData
->Enabled
= SessionConfigData
->Enabled
;
530 IfrNvData
->IpMode
= SessionConfigData
->IpMode
;
531 DnsMode
= SessionConfigData
->DnsMode
;
533 IfrNvData
->InitiatorInfoFromDhcp
= SessionConfigData
->InitiatorInfoFromDhcp
;
534 IfrNvData
->TargetInfoFromDhcp
= SessionConfigData
->TargetInfoFromDhcp
;
535 IfrNvData
->TargetPort
= SessionConfigData
->TargetPort
;
537 if (IfrNvData
->IpMode
== IP_MODE_IP4
) {
538 CopyMem (&Ip
.v4
, &SessionConfigData
->LocalIp
, sizeof (EFI_IPv4_ADDRESS
));
539 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->LocalIp
);
540 CopyMem (&Ip
.v4
, &SessionConfigData
->SubnetMask
, sizeof (EFI_IPv4_ADDRESS
));
541 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->SubnetMask
);
542 CopyMem (&Ip
.v4
, &SessionConfigData
->Gateway
, sizeof (EFI_IPv4_ADDRESS
));
543 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->Gateway
);
544 if (SessionConfigData
->TargetIp
.v4
.Addr
[0] != '\0') {
545 CopyMem (&Ip
.v4
, &SessionConfigData
->TargetIp
, sizeof (EFI_IPv4_ADDRESS
));
546 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->TargetIp
);
549 } else if (IfrNvData
->IpMode
== IP_MODE_IP6
) {
550 ZeroMem (IfrNvData
->TargetIp
, sizeof (IfrNvData
->TargetIp
));
551 if (SessionConfigData
->TargetIp
.v6
.Addr
[0] != '\0') {
552 IP6_COPY_ADDRESS (&Ip
.v6
, &SessionConfigData
->TargetIp
);
553 IScsiIpToStr (&Ip
, TRUE
, IfrNvData
->TargetIp
);
557 AsciiStrToUnicodeStrS (
558 SessionConfigData
->TargetName
,
559 IfrNvData
->TargetName
,
560 sizeof (IfrNvData
->TargetName
) / sizeof (IfrNvData
->TargetName
[0])
564 AsciiStrToUnicodeStrS (
565 SessionConfigData
->TargetUrl
,
567 sizeof (IfrNvData
->TargetIp
) / sizeof (IfrNvData
->TargetIp
[0])
571 IScsiLunToUnicodeStr (SessionConfigData
->BootLun
, IfrNvData
->BootLun
);
572 IScsiConvertIsIdToString (IfrNvData
->IsId
, SessionConfigData
->IsId
);
574 IfrNvData
->ConnectRetryCount
= SessionConfigData
->ConnectRetryCount
;
575 IfrNvData
->ConnectTimeout
= SessionConfigData
->ConnectTimeout
;
578 // Authentication parameters.
580 IfrNvData
->AuthenticationType
= Attempt
->AuthenticationType
;
582 if (IfrNvData
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
583 AuthConfigData
= &Attempt
->AuthConfigData
.CHAP
;
584 IfrNvData
->CHAPType
= AuthConfigData
->CHAPType
;
585 AsciiStrToUnicodeStrS (
586 AuthConfigData
->CHAPName
,
588 sizeof (IfrNvData
->CHAPName
) / sizeof (IfrNvData
->CHAPName
[0])
590 AsciiStrToUnicodeStrS (
591 AuthConfigData
->CHAPSecret
,
592 IfrNvData
->CHAPSecret
,
593 sizeof (IfrNvData
->CHAPSecret
) / sizeof (IfrNvData
->CHAPSecret
[0])
595 AsciiStrToUnicodeStrS (
596 AuthConfigData
->ReverseCHAPName
,
597 IfrNvData
->ReverseCHAPName
,
598 sizeof (IfrNvData
->ReverseCHAPName
) / sizeof (IfrNvData
->ReverseCHAPName
[0])
600 AsciiStrToUnicodeStrS (
601 AuthConfigData
->ReverseCHAPSecret
,
602 IfrNvData
->ReverseCHAPSecret
,
603 sizeof (IfrNvData
->ReverseCHAPSecret
) / sizeof (IfrNvData
->ReverseCHAPSecret
[0])
610 AsciiStrToUnicodeStrS (
611 Attempt
->AttemptName
,
612 IfrNvData
->AttemptName
,
613 sizeof (IfrNvData
->AttemptName
) / sizeof (IfrNvData
->AttemptName
[0])
618 Convert the iSCSI configuration data into the IFR data Which will be used
619 to extract the iSCSI Keyword configuration in <ConfigAltResp> format.
621 @param[in, out] IfrNvData The IFR nv data.
626 IScsiConvertAttemptConfigDataToIfrNvDataByKeyword (
627 IN OUT ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
631 ISCSI_ATTEMPT_CONFIG_NVDATA
*Attempt
;
632 ISCSI_SESSION_CONFIG_NVDATA
*SessionConfigData
;
633 ISCSI_CHAP_AUTH_CONFIG_NVDATA
*AuthConfigData
;
634 CHAR16 AttemptNameList
[ATTEMPT_NAME_LIST_SIZE
];
635 ISCSI_NIC_INFO
*NicInfo
;
636 CHAR16 MacString
[ISCSI_MAX_MAC_STRING_LEN
];
642 ZeroMem (AttemptNameList
, sizeof (AttemptNameList
));
644 if ((mPrivate
!= NULL
) && (mPrivate
->AttemptCount
!= 0)) {
645 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
646 Attempt
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
648 // Normal session configuration parameters.
650 SessionConfigData
= &Attempt
->SessionConfigData
;
652 ASSERT ((Attempt
->AttemptConfigIndex
> 0) && (Attempt
->AttemptConfigIndex
<= FixedPcdGet8 (PcdMaxIScsiAttemptNumber
)));
653 Index
= Attempt
->AttemptConfigIndex
- 1;
656 // Save the attempt to AttemptNameList as Attempt:1 Attempt:2
658 AsciiStrToUnicodeStrS (
659 Attempt
->AttemptName
,
660 AttemptNameList
+ StrLen (AttemptNameList
),
661 ATTEMPT_NAME_LIST_SIZE
- StrLen (AttemptNameList
)
664 StringLen
= StrLen (AttemptNameList
);
665 ASSERT (StringLen
> 2);
666 *(AttemptNameList
+ StringLen
- 2) = L
':';
667 *(AttemptNameList
+ StringLen
) = L
' ';
669 AsciiStrToUnicodeStrS (
670 Attempt
->AttemptName
,
671 IfrNvData
->ISCSIAttemptName
+ ATTEMPT_NAME_SIZE
* Index
,
672 ATTEMPT_NAME_LIST_SIZE
- ATTEMPT_NAME_SIZE
* Index
675 IfrNvData
->ISCSIBootEnableList
[Index
] = SessionConfigData
->Enabled
;
676 IfrNvData
->ISCSIIpAddressTypeList
[Index
] = SessionConfigData
->IpMode
;
678 IfrNvData
->ISCSIInitiatorInfoViaDHCP
[Index
] = SessionConfigData
->InitiatorInfoFromDhcp
;
679 IfrNvData
->ISCSITargetInfoViaDHCP
[Index
] = SessionConfigData
->TargetInfoFromDhcp
;
680 IfrNvData
->ISCSIConnectRetry
[Index
] = SessionConfigData
->ConnectRetryCount
;
681 IfrNvData
->ISCSIConnectTimeout
[Index
] = SessionConfigData
->ConnectTimeout
;
682 IfrNvData
->ISCSITargetTcpPort
[Index
] = SessionConfigData
->TargetPort
;
684 if (SessionConfigData
->IpMode
== IP_MODE_IP4
) {
685 CopyMem (&Ip
.v4
, &SessionConfigData
->LocalIp
, sizeof (EFI_IPv4_ADDRESS
));
686 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->Keyword
[Index
].ISCSIInitiatorIpAddress
);
687 CopyMem (&Ip
.v4
, &SessionConfigData
->SubnetMask
, sizeof (EFI_IPv4_ADDRESS
));
688 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->Keyword
[Index
].ISCSIInitiatorNetmask
);
689 CopyMem (&Ip
.v4
, &SessionConfigData
->Gateway
, sizeof (EFI_IPv4_ADDRESS
));
690 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->Keyword
[Index
].ISCSIInitiatorGateway
);
691 if (SessionConfigData
->TargetIp
.v4
.Addr
[0] != '\0') {
692 CopyMem (&Ip
.v4
, &SessionConfigData
->TargetIp
, sizeof (EFI_IPv4_ADDRESS
));
693 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->Keyword
[Index
].ISCSITargetIpAddress
);
695 } else if (SessionConfigData
->IpMode
== IP_MODE_IP6
) {
696 ZeroMem (IfrNvData
->Keyword
[Index
].ISCSITargetIpAddress
, sizeof (IfrNvData
->TargetIp
));
697 if (SessionConfigData
->TargetIp
.v6
.Addr
[0] != '\0') {
698 IP6_COPY_ADDRESS (&Ip
.v6
, &SessionConfigData
->TargetIp
);
699 IScsiIpToStr (&Ip
, TRUE
, IfrNvData
->Keyword
[Index
].ISCSITargetIpAddress
);
703 AsciiStrToUnicodeStrS (
704 SessionConfigData
->TargetName
,
705 IfrNvData
->Keyword
[Index
].ISCSITargetName
,
709 if (SessionConfigData
->DnsMode
) {
710 AsciiStrToUnicodeStrS (
711 SessionConfigData
->TargetUrl
,
712 IfrNvData
->Keyword
[Index
].ISCSITargetIpAddress
,
713 sizeof (IfrNvData
->Keyword
[Index
].ISCSITargetIpAddress
) / sizeof (IfrNvData
->Keyword
[Index
].ISCSITargetIpAddress
[0])
717 IScsiLunToUnicodeStr (SessionConfigData
->BootLun
, IfrNvData
->Keyword
[Index
].ISCSILun
);
718 IScsiConvertIsIdToString (IfrNvData
->Keyword
[Index
].ISCSIIsId
, SessionConfigData
->IsId
);
720 IfrNvData
->ISCSIAuthenticationMethod
[Index
] = Attempt
->AuthenticationType
;
722 if (Attempt
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
723 AuthConfigData
= &Attempt
->AuthConfigData
.CHAP
;
724 IfrNvData
->ISCSIChapType
[Index
] = AuthConfigData
->CHAPType
;
725 AsciiStrToUnicodeStrS (
726 AuthConfigData
->CHAPName
,
727 IfrNvData
->Keyword
[Index
].ISCSIChapUsername
,
728 ISCSI_CHAP_NAME_STORAGE
731 AsciiStrToUnicodeStrS (
732 AuthConfigData
->CHAPSecret
,
733 IfrNvData
->Keyword
[Index
].ISCSIChapSecret
,
734 ISCSI_CHAP_SECRET_STORAGE
737 AsciiStrToUnicodeStrS (
738 AuthConfigData
->ReverseCHAPName
,
739 IfrNvData
->Keyword
[Index
].ISCSIReverseChapUsername
,
740 ISCSI_CHAP_NAME_STORAGE
743 AsciiStrToUnicodeStrS (
744 AuthConfigData
->ReverseCHAPSecret
,
745 IfrNvData
->Keyword
[Index
].ISCSIReverseChapSecret
,
746 ISCSI_CHAP_SECRET_STORAGE
750 CopyMem(IfrNvData
->ISCSIDisplayAttemptList
, AttemptNameList
, ATTEMPT_NAME_LIST_SIZE
);
752 ZeroMem (IfrNvData
->ISCSIMacAddr
, sizeof (IfrNvData
->ISCSIMacAddr
));
753 NET_LIST_FOR_EACH (Entry
, &mPrivate
->NicInfoList
) {
754 NicInfo
= NET_LIST_USER_STRUCT (Entry
, ISCSI_NIC_INFO
, Link
);
756 &NicInfo
->PermanentAddress
,
757 NicInfo
->HwAddressSize
,
762 IfrNvData
->ISCSIMacAddr
+ StrLen (IfrNvData
->ISCSIMacAddr
),
764 StrLen (MacString
) * sizeof (CHAR16
)
767 *(IfrNvData
->ISCSIMacAddr
+ StrLen (IfrNvData
->ISCSIMacAddr
)) = L
'/';
770 StringLen
= StrLen (IfrNvData
->ISCSIMacAddr
);
772 *(IfrNvData
->ISCSIMacAddr
+ StringLen
- 1) = L
'\0';
778 Convert the IFR data to iSCSI configuration data.
780 @param[in] IfrNvData Point to ISCSI_CONFIG_IFR_NVDATA.
781 @param[in, out] Attempt The iSCSI attempt config data.
783 @retval EFI_INVALID_PARAMETER Any input or configured parameter is invalid.
784 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
785 @retval EFI_OUT_OF_RESOURCES The operation is failed due to lack of resources.
786 @retval EFI_ABORTED The operation is aborted.
787 @retval EFI_SUCCESS The operation is completed successfully.
791 IScsiConvertIfrNvDataToAttemptConfigData (
792 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
,
793 IN OUT ISCSI_ATTEMPT_CONFIG_NVDATA
*Attempt
796 EFI_IP_ADDRESS HostIp
;
797 EFI_IP_ADDRESS SubnetMask
;
798 EFI_IP_ADDRESS Gateway
;
800 CHAR16
*AttemptName1
;
801 CHAR16
*AttemptName2
;
802 ISCSI_ATTEMPT_CONFIG_NVDATA
*ExistAttempt
;
803 ISCSI_ATTEMPT_CONFIG_NVDATA
*SameNicAttempt
;
804 CHAR16 IScsiMode
[64];
806 ISCSI_NIC_INFO
*NicInfo
;
808 UINT8
*AttemptConfigOrder
;
809 UINTN AttemptConfigOrderSize
;
810 UINT8
*AttemptOrderTmp
;
814 if (IfrNvData
== NULL
|| Attempt
== NULL
) {
815 return EFI_INVALID_PARAMETER
;
819 // Update those fields which don't have INTERACTIVE attribute.
821 Attempt
->SessionConfigData
.ConnectRetryCount
= IfrNvData
->ConnectRetryCount
;
822 Attempt
->SessionConfigData
.ConnectTimeout
= IfrNvData
->ConnectTimeout
;
823 Attempt
->SessionConfigData
.IpMode
= IfrNvData
->IpMode
;
825 if (IfrNvData
->IpMode
< IP_MODE_AUTOCONFIG
) {
826 Attempt
->SessionConfigData
.InitiatorInfoFromDhcp
= IfrNvData
->InitiatorInfoFromDhcp
;
827 Attempt
->SessionConfigData
.TargetPort
= IfrNvData
->TargetPort
;
829 if (Attempt
->SessionConfigData
.TargetPort
== 0) {
830 Attempt
->SessionConfigData
.TargetPort
= ISCSI_WELL_KNOWN_PORT
;
833 Attempt
->SessionConfigData
.TargetInfoFromDhcp
= IfrNvData
->TargetInfoFromDhcp
;
836 Attempt
->AuthenticationType
= IfrNvData
->AuthenticationType
;
838 if (Attempt
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
839 Attempt
->AuthConfigData
.CHAP
.CHAPType
= IfrNvData
->CHAPType
;
843 // Only do full parameter validation if iSCSI is enabled on this device.
845 if (IfrNvData
->Enabled
!= ISCSI_DISABLED
) {
846 if (Attempt
->SessionConfigData
.ConnectTimeout
< CONNECT_MIN_TIMEOUT
) {
848 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
850 L
"Connection Establishing Timeout is less than minimum value 100ms.",
854 return EFI_INVALID_PARAMETER
;
858 // Validate the address configuration of the Initiator if DHCP isn't
861 if (!Attempt
->SessionConfigData
.InitiatorInfoFromDhcp
) {
862 CopyMem (&HostIp
.v4
, &Attempt
->SessionConfigData
.LocalIp
, sizeof (HostIp
.v4
));
863 CopyMem (&SubnetMask
.v4
, &Attempt
->SessionConfigData
.SubnetMask
, sizeof (SubnetMask
.v4
));
864 CopyMem (&Gateway
.v4
, &Attempt
->SessionConfigData
.Gateway
, sizeof (Gateway
.v4
));
866 if ((Gateway
.Addr
[0] != 0)) {
867 if (SubnetMask
.Addr
[0] == 0) {
869 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
871 L
"Gateway address is set but subnet mask is zero.",
875 return EFI_INVALID_PARAMETER
;
876 } else if (!IP4_NET_EQUAL (HostIp
.Addr
[0], Gateway
.Addr
[0], SubnetMask
.Addr
[0])) {
878 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
880 L
"Local IP and Gateway are not in the same subnet.",
884 return EFI_INVALID_PARAMETER
;
889 // Validate target configuration if DHCP isn't deployed.
891 if (!Attempt
->SessionConfigData
.TargetInfoFromDhcp
&& Attempt
->SessionConfigData
.IpMode
< IP_MODE_AUTOCONFIG
) {
892 if (!Attempt
->SessionConfigData
.DnsMode
) {
893 if (!IpIsUnicast (&Attempt
->SessionConfigData
.TargetIp
, IfrNvData
->IpMode
)) {
895 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
897 L
"Target IP is invalid!",
900 return EFI_INVALID_PARAMETER
;
903 if (Attempt
->SessionConfigData
.TargetUrl
[0] == '\0') {
905 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
907 L
"iSCSI target Url should not be NULL!",
910 return EFI_INVALID_PARAMETER
;
915 // Validate iSCSI target name configuration again:
916 // The format of iSCSI target name is already verified in IScsiFormCallback() when
917 // user input the name; here we only check the case user does not input the name.
919 if (Attempt
->SessionConfigData
.TargetName
[0] == '\0') {
921 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
923 L
"iSCSI target name is NULL!",
926 return EFI_INVALID_PARAMETER
;
931 // Validate the authentication info.
933 if (IfrNvData
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
934 if ((IfrNvData
->CHAPName
[0] == '\0') || (IfrNvData
->CHAPSecret
[0] == '\0')) {
936 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
938 L
"CHAP Name or CHAP Secret is invalid!",
942 return EFI_INVALID_PARAMETER
;
945 if ((IfrNvData
->CHAPType
== ISCSI_CHAP_MUTUAL
) &&
946 ((IfrNvData
->ReverseCHAPName
[0] == '\0') || (IfrNvData
->ReverseCHAPSecret
[0] == '\0'))
949 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
951 L
"Reverse CHAP Name or Reverse CHAP Secret is invalid!",
954 return EFI_INVALID_PARAMETER
;
959 // Check whether this attempt uses NIC which is already used by existing attempt.
961 SameNicAttempt
= IScsiConfigGetAttemptByNic (Attempt
, IfrNvData
->Enabled
);
962 if (SameNicAttempt
!= NULL
) {
963 AttemptName1
= (CHAR16
*) AllocateZeroPool (ATTEMPT_NAME_SIZE
* sizeof (CHAR16
));
964 if (AttemptName1
== NULL
) {
965 return EFI_OUT_OF_RESOURCES
;
968 AttemptName2
= (CHAR16
*) AllocateZeroPool (ATTEMPT_NAME_SIZE
* sizeof (CHAR16
));
969 if (AttemptName2
== NULL
) {
970 FreePool (AttemptName1
);
971 return EFI_OUT_OF_RESOURCES
;
974 AsciiStrToUnicodeStrS (Attempt
->AttemptName
, AttemptName1
, ATTEMPT_NAME_SIZE
);
975 AsciiStrToUnicodeStrS (SameNicAttempt
->AttemptName
, AttemptName2
, ATTEMPT_NAME_SIZE
);
978 mPrivate
->PortString
,
979 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
980 L
"Warning! Attempt \"%s\" uses same NIC as Attempt \"%s\".",
986 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
988 mPrivate
->PortString
,
992 FreePool (AttemptName1
);
993 FreePool (AttemptName2
);
998 // Update the iSCSI Mode data and record it in attempt help info.
1000 if (IfrNvData
->Enabled
== ISCSI_DISABLED
) {
1001 UnicodeSPrint (IScsiMode
, 64, L
"Disabled");
1002 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
) {
1003 UnicodeSPrint (IScsiMode
, 64, L
"Enabled");
1004 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
1005 UnicodeSPrint (IScsiMode
, 64, L
"Enabled for MPIO");
1008 if (IfrNvData
->IpMode
== IP_MODE_IP4
) {
1009 UnicodeSPrint (IpMode
, 64, L
"IP4");
1010 } else if (IfrNvData
->IpMode
== IP_MODE_IP6
) {
1011 UnicodeSPrint (IpMode
, 64, L
"IP6");
1012 } else if (IfrNvData
->IpMode
== IP_MODE_AUTOCONFIG
) {
1013 UnicodeSPrint (IpMode
, 64, L
"Autoconfigure");
1016 NicInfo
= IScsiGetNicInfoByIndex (Attempt
->NicIndex
);
1017 if (NicInfo
== NULL
) {
1018 return EFI_NOT_FOUND
;
1021 MacString
= (CHAR16
*) AllocateZeroPool (ISCSI_MAX_MAC_STRING_LEN
* sizeof (CHAR16
));
1022 if (MacString
== NULL
) {
1023 return EFI_OUT_OF_RESOURCES
;
1026 AsciiStrToUnicodeStrS (Attempt
->MacString
, MacString
, ISCSI_MAX_MAC_STRING_LEN
);
1029 mPrivate
->PortString
,
1030 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
1031 L
"MAC: %s, PFA: Bus %d | Dev %d | Func %d, iSCSI mode: %s, IP version: %s",
1034 NicInfo
->DeviceNumber
,
1035 NicInfo
->FunctionNumber
,
1040 Attempt
->AttemptTitleHelpToken
= HiiSetString (
1041 mCallbackInfo
->RegisteredHandle
,
1042 Attempt
->AttemptTitleHelpToken
,
1043 mPrivate
->PortString
,
1046 if (Attempt
->AttemptTitleHelpToken
== 0) {
1047 FreePool (MacString
);
1048 return EFI_OUT_OF_RESOURCES
;
1052 // Check whether this attempt is an existing one.
1054 ExistAttempt
= IScsiConfigGetAttemptByConfigIndex (Attempt
->AttemptConfigIndex
);
1055 if (ExistAttempt
!= NULL
) {
1056 ASSERT (ExistAttempt
== Attempt
);
1058 if (IfrNvData
->Enabled
== ISCSI_DISABLED
&&
1059 Attempt
->SessionConfigData
.Enabled
!= ISCSI_DISABLED
) {
1062 // User updates the Attempt from "Enabled"/"Enabled for MPIO" to "Disabled".
1064 if (Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
1065 if (mPrivate
->MpioCount
< 1) {
1069 if (--mPrivate
->MpioCount
== 0) {
1070 mPrivate
->EnableMpio
= FALSE
;
1072 } else if (Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED
) {
1073 if (mPrivate
->SinglePathCount
< 1) {
1076 mPrivate
->SinglePathCount
--;
1079 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
&&
1080 Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED
) {
1082 // User updates the Attempt from "Enabled" to "Enabled for MPIO".
1084 if (mPrivate
->SinglePathCount
< 1) {
1088 mPrivate
->EnableMpio
= TRUE
;
1089 mPrivate
->MpioCount
++;
1090 mPrivate
->SinglePathCount
--;
1092 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
&&
1093 Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
1095 // User updates the Attempt from "Enabled for MPIO" to "Enabled".
1097 if (mPrivate
->MpioCount
< 1) {
1101 if (--mPrivate
->MpioCount
== 0) {
1102 mPrivate
->EnableMpio
= FALSE
;
1104 mPrivate
->SinglePathCount
++;
1106 } else if (IfrNvData
->Enabled
!= ISCSI_DISABLED
&&
1107 Attempt
->SessionConfigData
.Enabled
== ISCSI_DISABLED
) {
1109 // User updates the Attempt from "Disabled" to "Enabled"/"Enabled for MPIO".
1111 if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
1112 mPrivate
->EnableMpio
= TRUE
;
1113 mPrivate
->MpioCount
++;
1115 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
) {
1116 mPrivate
->SinglePathCount
++;
1120 } else if (ExistAttempt
== NULL
) {
1122 // When a new attempt is created, pointer of the attempt is saved to
1123 // mCallbackInfo->Current in IScsiConfigProcessDefault. If input Attempt
1124 // does not match any existing attempt, it should be a new created attempt.
1125 // Save it to system now.
1129 // Save current order number for this attempt.
1131 AttemptConfigOrder
= IScsiGetVariableAndSize (
1134 &AttemptConfigOrderSize
1137 TotalNumber
= AttemptConfigOrderSize
/ sizeof (UINT8
);
1141 // Append the new created attempt order to the end.
1143 AttemptOrderTmp
= AllocateZeroPool (TotalNumber
* sizeof (UINT8
));
1144 if (AttemptOrderTmp
== NULL
) {
1145 if (AttemptConfigOrder
!= NULL
) {
1146 FreePool (AttemptConfigOrder
);
1148 return EFI_OUT_OF_RESOURCES
;
1151 if (AttemptConfigOrder
!= NULL
) {
1152 CopyMem (AttemptOrderTmp
, AttemptConfigOrder
, AttemptConfigOrderSize
);
1153 FreePool (AttemptConfigOrder
);
1156 AttemptOrderTmp
[TotalNumber
- 1] = Attempt
->AttemptConfigIndex
;
1157 AttemptConfigOrder
= AttemptOrderTmp
;
1158 AttemptConfigOrderSize
= TotalNumber
* sizeof (UINT8
);
1160 Status
= gRT
->SetVariable (
1163 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
1164 AttemptConfigOrderSize
,
1167 FreePool (AttemptConfigOrder
);
1168 if (EFI_ERROR (Status
)) {
1173 // Insert new created attempt to array.
1175 InsertTailList (&mPrivate
->AttemptConfigs
, &Attempt
->Link
);
1176 mPrivate
->AttemptCount
++;
1178 if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
1180 // This new Attempt is enabled for MPIO; enable the multipath mode.
1182 mPrivate
->EnableMpio
= TRUE
;
1183 mPrivate
->MpioCount
++;
1184 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
) {
1185 mPrivate
->SinglePathCount
++;
1188 IScsiConfigUpdateAttempt ();
1190 Attempt
->SessionConfigData
.Enabled
= IfrNvData
->Enabled
;
1193 // Record the user configuration information in NVR.
1195 UnicodeSPrint (mPrivate
->PortString
, (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
, L
"Attempt %d", Attempt
->AttemptConfigIndex
);
1197 FreePool (MacString
);
1199 return gRT
->SetVariable (
1200 mPrivate
->PortString
,
1201 &gEfiIScsiInitiatorNameProtocolGuid
,
1202 ISCSI_CONFIG_VAR_ATTR
,
1203 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA
),
1209 Convert the IFR data configured by keyword to iSCSI configuration data.
1211 @param[in] IfrNvData Point to ISCSI_CONFIG_IFR_NVDATA.
1212 @param[in] OffSet The offset of the variable to the configuration structure.
1214 @retval EFI_INVALID_PARAMETER Any input or configured parameter is invalid.
1215 @retval EFI_SUCCESS The operation is completed successfully.
1219 IScsiConvertlfrNvDataToAttemptConfigDataByKeyword (
1220 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
,
1224 ISCSI_ATTEMPT_CONFIG_NVDATA
*Attempt
;
1227 UINT8 ChapSecretLen
;
1228 UINT8 ReverseChapSecretLen
;
1229 CHAR16
*AttemptName1
;
1230 CHAR16
*AttemptName2
;
1231 ISCSI_ATTEMPT_CONFIG_NVDATA
*SameNicAttempt
;
1232 CHAR8 LunString
[ISCSI_LUN_STR_MAX_LEN
];
1233 CHAR8 IScsiName
[ISCSI_NAME_MAX_SIZE
];
1234 CHAR8 IpString
[IP_STR_MAX_SIZE
];
1235 EFI_IP_ADDRESS HostIp
;
1236 EFI_IP_ADDRESS SubnetMask
;
1237 EFI_IP_ADDRESS Gateway
;
1243 ZeroMem (IScsiName
, sizeof (IScsiName
));
1245 if (OffSet
< ATTEMPT_BOOTENABLE_VAR_OFFSET
) {
1248 } else if ((OffSet
>= ATTEMPT_BOOTENABLE_VAR_OFFSET
) && (OffSet
< ATTEMPT_ADDRESS_TYPE_VAR_OFFSET
)) {
1249 AttemptIndex
= (UINT8
) ((OffSet
- ATTEMPT_BOOTENABLE_VAR_OFFSET
) + 1);
1250 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1251 if (Attempt
== NULL
) {
1252 return EFI_INVALID_PARAMETER
;
1254 IfrNvData
->Enabled
= IfrNvData
->ISCSIBootEnableList
[AttemptIndex
- 1];
1256 // Validate the configuration of attempt.
1258 if (IfrNvData
->Enabled
!= ISCSI_DISABLED
) {
1260 // Check whether this attempt uses NIC which is already used by existing attempt.
1262 SameNicAttempt
= IScsiConfigGetAttemptByNic (Attempt
, IfrNvData
->Enabled
);
1263 if (SameNicAttempt
!= NULL
) {
1264 AttemptName1
= (CHAR16
*) AllocateZeroPool (ATTEMPT_NAME_SIZE
* sizeof (CHAR16
));
1265 if (AttemptName1
== NULL
) {
1266 return EFI_OUT_OF_RESOURCES
;
1269 AttemptName2
= (CHAR16
*) AllocateZeroPool (ATTEMPT_NAME_SIZE
* sizeof (CHAR16
));
1270 if (AttemptName2
== NULL
) {
1271 FreePool (AttemptName1
);
1272 return EFI_OUT_OF_RESOURCES
;
1275 AsciiStrToUnicodeStrS (Attempt
->AttemptName
, AttemptName1
, ATTEMPT_NAME_SIZE
);
1276 AsciiStrToUnicodeStrS (SameNicAttempt
->AttemptName
, AttemptName2
, ATTEMPT_NAME_SIZE
);
1279 mPrivate
->PortString
,
1280 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
1281 L
"Warning! \"%s\" uses same NIC as Attempt \"%s\".",
1287 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1289 mPrivate
->PortString
,
1293 FreePool (AttemptName1
);
1294 FreePool (AttemptName2
);
1298 if (IfrNvData
->Enabled
== ISCSI_DISABLED
&&
1299 Attempt
->SessionConfigData
.Enabled
!= ISCSI_DISABLED
) {
1302 // User updates the Attempt from "Enabled"/"Enabled for MPIO" to "Disabled".
1304 if (Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
1305 if (mPrivate
->MpioCount
< 1) {
1309 if (--mPrivate
->MpioCount
== 0) {
1310 mPrivate
->EnableMpio
= FALSE
;
1312 } else if (Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED
) {
1313 if (mPrivate
->SinglePathCount
< 1) {
1316 mPrivate
->SinglePathCount
--;
1319 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
&&
1320 Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED
) {
1322 // User updates the Attempt from "Enabled" to "Enabled for MPIO".
1324 if (mPrivate
->SinglePathCount
< 1) {
1328 mPrivate
->EnableMpio
= TRUE
;
1329 mPrivate
->MpioCount
++;
1330 mPrivate
->SinglePathCount
--;
1332 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
&&
1333 Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
1335 // User updates the Attempt from "Enabled for MPIO" to "Enabled".
1337 if (mPrivate
->MpioCount
< 1) {
1341 if (--mPrivate
->MpioCount
== 0) {
1342 mPrivate
->EnableMpio
= FALSE
;
1344 mPrivate
->SinglePathCount
++;
1346 } else if (IfrNvData
->Enabled
!= ISCSI_DISABLED
&&
1347 Attempt
->SessionConfigData
.Enabled
== ISCSI_DISABLED
) {
1349 // User updates the Attempt from "Disabled" to "Enabled"/"Enabled for MPIO".
1351 if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
1352 mPrivate
->EnableMpio
= TRUE
;
1353 mPrivate
->MpioCount
++;
1355 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
) {
1356 mPrivate
->SinglePathCount
++;
1359 Attempt
->SessionConfigData
.Enabled
= IfrNvData
->Enabled
;
1361 } else if ((OffSet
>= ATTEMPT_ADDRESS_TYPE_VAR_OFFSET
) && (OffSet
< ATTEMPT_CONNECT_RETRY_VAR_OFFSET
)) {
1362 AttemptIndex
= (UINT8
) ((OffSet
- ATTEMPT_ADDRESS_TYPE_VAR_OFFSET
) + 1);
1363 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1364 if (Attempt
== NULL
) {
1365 return EFI_INVALID_PARAMETER
;
1367 Attempt
->SessionConfigData
.IpMode
= IfrNvData
->ISCSIIpAddressTypeList
[AttemptIndex
- 1];
1368 if (Attempt
->SessionConfigData
.IpMode
< IP_MODE_AUTOCONFIG
) {
1369 Attempt
->AutoConfigureMode
= 0;
1372 } else if ((OffSet
>= ATTEMPT_CONNECT_RETRY_VAR_OFFSET
) && (OffSet
< ATTEMPT_CONNECT_TIMEOUT_VAR_OFFSET
)) {
1373 AttemptIndex
= (UINT8
) ((OffSet
- ATTEMPT_CONNECT_RETRY_VAR_OFFSET
) + 1);
1374 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1375 if (Attempt
== NULL
) {
1376 return EFI_INVALID_PARAMETER
;
1379 if (IfrNvData
->ISCSIConnectRetry
[AttemptIndex
- 1] > CONNECT_MAX_RETRY
) {
1381 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1383 L
"The minimum value is 0 and the maximum is 16. 0 means no retry.",
1386 return EFI_INVALID_PARAMETER
;
1388 Attempt
->SessionConfigData
.ConnectRetryCount
= IfrNvData
->ISCSIConnectRetry
[AttemptIndex
- 1];
1390 } else if ((OffSet
>= ATTEMPT_CONNECT_TIMEOUT_VAR_OFFSET
) && (OffSet
< ATTEMPT_INITIATOR_VIA_DHCP_VAR_OFFSET
)) {
1391 AttemptIndex
= (UINT8
) ((OffSet
- ATTEMPT_CONNECT_TIMEOUT_VAR_OFFSET
) / 2 + 1);
1392 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1393 if (Attempt
== NULL
) {
1394 return EFI_INVALID_PARAMETER
;
1397 if ((IfrNvData
->ISCSIConnectTimeout
[AttemptIndex
- 1] < CONNECT_MIN_TIMEOUT
) ||
1398 (IfrNvData
->ISCSIConnectTimeout
[AttemptIndex
- 1] > CONNECT_MAX_TIMEOUT
)) {
1400 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1402 L
"The minimum value is 100 milliseconds and the maximum is 20 seconds.",
1405 return EFI_INVALID_PARAMETER
;
1408 Attempt
->SessionConfigData
.ConnectTimeout
= IfrNvData
->ISCSIConnectTimeout
[AttemptIndex
- 1];
1409 if (Attempt
->SessionConfigData
.ConnectTimeout
== 0) {
1410 Attempt
->SessionConfigData
.ConnectTimeout
= CONNECT_DEFAULT_TIMEOUT
;
1413 } else if ((OffSet
>= ATTEMPT_INITIATOR_VIA_DHCP_VAR_OFFSET
) && (OffSet
< ATTEMPT_TARGET_VIA_DHCP_VAR_OFFSET
)) {
1414 AttemptIndex
= (UINT8
) ((OffSet
- ATTEMPT_INITIATOR_VIA_DHCP_VAR_OFFSET
) + 1);
1415 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1416 if (Attempt
== NULL
) {
1417 return EFI_INVALID_PARAMETER
;
1419 Attempt
->SessionConfigData
.InitiatorInfoFromDhcp
= IfrNvData
->ISCSIInitiatorInfoViaDHCP
[AttemptIndex
- 1];
1421 } else if ((OffSet
>= ATTEMPT_TARGET_VIA_DHCP_VAR_OFFSET
) && (OffSet
< ATTEMPT_TARGET_TCP_PORT_VAR_OFFSET
)) {
1422 AttemptIndex
= (UINT8
) ((OffSet
- ATTEMPT_TARGET_VIA_DHCP_VAR_OFFSET
) + 1);
1423 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1424 if (Attempt
== NULL
) {
1425 return EFI_INVALID_PARAMETER
;
1428 if ((Attempt
->SessionConfigData
.IpMode
< IP_MODE_AUTOCONFIG
) && (Attempt
->SessionConfigData
.InitiatorInfoFromDhcp
)) {
1429 Attempt
->SessionConfigData
.TargetInfoFromDhcp
= IfrNvData
->ISCSITargetInfoViaDHCP
[AttemptIndex
- 1];
1432 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1434 L
"Invalid Configuration, Check value of IpMode or Enable DHCP!",
1437 return EFI_INVALID_PARAMETER
;
1440 } else if ((OffSet
>= ATTEMPT_TARGET_TCP_PORT_VAR_OFFSET
) && (OffSet
< ATTEMPT_AUTHENTICATION_METHOD_VAR_OFFSET
)) {
1441 AttemptIndex
= (UINT8
) ((OffSet
- ATTEMPT_TARGET_TCP_PORT_VAR_OFFSET
) / 2 + 1);
1442 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1443 if (Attempt
== NULL
) {
1444 return EFI_INVALID_PARAMETER
;
1446 if ((Attempt
->SessionConfigData
.IpMode
< IP_MODE_AUTOCONFIG
) && (!Attempt
->SessionConfigData
.TargetInfoFromDhcp
)) {
1447 Attempt
->SessionConfigData
.TargetPort
= IfrNvData
->ISCSITargetTcpPort
[AttemptIndex
- 1];
1448 if (Attempt
->SessionConfigData
.TargetPort
== 0) {
1449 Attempt
->SessionConfigData
.TargetPort
= ISCSI_WELL_KNOWN_PORT
;
1453 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1455 L
"Invalid Configuration, Check value of IpMode or Target Via DHCP!",
1458 return EFI_INVALID_PARAMETER
;
1461 } else if ((OffSet
>= ATTEMPT_AUTHENTICATION_METHOD_VAR_OFFSET
) && (OffSet
< ATTEMPT_CHARTYPE_VAR_OFFSET
)) {
1462 AttemptIndex
= (UINT8
) ((OffSet
- ATTEMPT_AUTHENTICATION_METHOD_VAR_OFFSET
) + 1);
1463 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1464 if (Attempt
== NULL
) {
1465 return EFI_INVALID_PARAMETER
;
1468 Attempt
->AuthenticationType
= IfrNvData
->ISCSIAuthenticationMethod
[AttemptIndex
- 1];
1470 } else if ((OffSet
>= ATTEMPT_CHARTYPE_VAR_OFFSET
) && (OffSet
< ATTEMPT_ISID_VAR_OFFSET
)) {
1471 AttemptIndex
= (UINT8
) ((OffSet
- ATTEMPT_CHARTYPE_VAR_OFFSET
) + 1);
1472 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1473 if (Attempt
== NULL
) {
1474 return EFI_INVALID_PARAMETER
;
1476 if (Attempt
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
1477 Attempt
->AuthConfigData
.CHAP
.CHAPType
= IfrNvData
->ISCSIChapType
[AttemptIndex
- 1];
1480 } else if (OffSet
>= ATTEMPT_ISID_VAR_OFFSET
) {
1481 Index
= (UINT8
) ((OffSet
- ATTEMPT_ISID_VAR_OFFSET
) / sizeof (KEYWORD_STR
));
1482 AttemptIndex
= Index
+ 1;
1483 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1484 if (Attempt
== NULL
) {
1485 return EFI_INVALID_PARAMETER
;
1488 OffSet
= OffSet
- Index
* sizeof (KEYWORD_STR
);
1490 if ((OffSet
>= ATTEMPT_ISID_VAR_OFFSET
) && (OffSet
< ATTEMPT_INITIATOR_IP_ADDRESS_VAR_OFFSET
)) {
1491 IScsiParseIsIdFromString (IfrNvData
->Keyword
[Index
].ISCSIIsId
, Attempt
->SessionConfigData
.IsId
);
1493 } else if ((OffSet
>= ATTEMPT_INITIATOR_IP_ADDRESS_VAR_OFFSET
) && (OffSet
< ATTEMPT_INITIATOR_NET_MASK_VAR_OFFSET
)) {
1494 if ((Attempt
->SessionConfigData
.IpMode
== IP_MODE_IP4
) && (!Attempt
->SessionConfigData
.InitiatorInfoFromDhcp
)) {
1498 Status
= NetLibStrToIp4 (IfrNvData
->Keyword
[Index
].ISCSIInitiatorIpAddress
, &HostIp
.v4
);
1499 if (EFI_ERROR (Status
) || ((Attempt
->SessionConfigData
.SubnetMask
.Addr
[0] != 0) &&
1500 !NetIp4IsUnicast (NTOHL (HostIp
.Addr
[0]), NTOHL(*(UINT32
*)Attempt
->SessionConfigData
.SubnetMask
.Addr
)))) {
1502 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1504 L
"Invalid IP address!",
1507 return EFI_INVALID_PARAMETER
;
1509 CopyMem (&Attempt
->SessionConfigData
.LocalIp
, &HostIp
.v4
, sizeof (HostIp
.v4
));
1513 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1515 L
"Invalid Configuration, Check value of IpMode or Enable DHCP!",
1518 return EFI_INVALID_PARAMETER
;
1521 } else if ((OffSet
>= ATTEMPT_INITIATOR_NET_MASK_VAR_OFFSET
) && (OffSet
< ATTEMPT_INITIATOR_GATE_WAY_VAR_OFFSET
)) {
1522 if ((Attempt
->SessionConfigData
.IpMode
== IP_MODE_IP4
) && (!Attempt
->SessionConfigData
.InitiatorInfoFromDhcp
)) {
1523 Status
= NetLibStrToIp4 (IfrNvData
->Keyword
[Index
].ISCSIInitiatorNetmask
, &SubnetMask
.v4
);
1524 if (EFI_ERROR (Status
) || ((SubnetMask
.Addr
[0] != 0) && (IScsiGetSubnetMaskPrefixLength (&SubnetMask
.v4
) == 0))) {
1526 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1528 L
"Invalid Subnet Mask!",
1531 return EFI_INVALID_PARAMETER
;
1533 CopyMem (&Attempt
->SessionConfigData
.SubnetMask
, &SubnetMask
.v4
, sizeof (SubnetMask
.v4
));
1537 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1539 L
"Invalid Configuration, Check value of IpMode or Enable DHCP!",
1542 return EFI_INVALID_PARAMETER
;
1545 } else if ((OffSet
>= ATTEMPT_INITIATOR_GATE_WAY_VAR_OFFSET
) && (OffSet
< ATTEMPT_TARGET_NAME_VAR_OFFSET
)) {
1546 if ((Attempt
->SessionConfigData
.IpMode
== IP_MODE_IP4
) && (!Attempt
->SessionConfigData
.InitiatorInfoFromDhcp
)) {
1547 Status
= NetLibStrToIp4 (IfrNvData
->Keyword
[Index
].ISCSIInitiatorGateway
, &Gateway
.v4
);
1548 if (EFI_ERROR (Status
) ||
1549 ((Gateway
.Addr
[0] != 0) && (Attempt
->SessionConfigData
.SubnetMask
.Addr
[0] != 0) &&
1550 !NetIp4IsUnicast (NTOHL (Gateway
.Addr
[0]), NTOHL(*(UINT32
*)Attempt
->SessionConfigData
.SubnetMask
.Addr
)))) {
1552 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1554 L
"Invalid Gateway!",
1557 return EFI_INVALID_PARAMETER
;
1559 CopyMem (&Attempt
->SessionConfigData
.Gateway
, &Gateway
.v4
, sizeof (Gateway
.v4
));
1563 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1565 L
"Invalid Configuration, Check value of IpMode or Enable DHCP!",
1568 return EFI_INVALID_PARAMETER
;
1571 } else if ((OffSet
>= ATTEMPT_TARGET_NAME_VAR_OFFSET
) && (OffSet
< ATTEMPT_TARGET_IP_ADDRESS_VAR_OFFSET
)) {
1572 if ((Attempt
->SessionConfigData
.IpMode
< IP_MODE_AUTOCONFIG
) && (!Attempt
->SessionConfigData
.TargetInfoFromDhcp
)) {
1573 UnicodeStrToAsciiStrS (IfrNvData
->Keyword
[Index
].ISCSITargetName
, IScsiName
, ISCSI_NAME_MAX_SIZE
);
1574 Status
= IScsiNormalizeName (IScsiName
, AsciiStrLen (IScsiName
));
1575 if (EFI_ERROR (Status
)) {
1577 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1579 L
"Invalid iSCSI Name!",
1583 AsciiStrCpyS (Attempt
->SessionConfigData
.TargetName
, ISCSI_NAME_MAX_SIZE
, IScsiName
);
1585 if (Attempt
->SessionConfigData
.Enabled
!= ISCSI_DISABLED
) {
1586 if (Attempt
->SessionConfigData
.TargetName
[0] == L
'\0') {
1588 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1590 L
"iSCSI target name is NULL!",
1593 return EFI_INVALID_PARAMETER
;
1598 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1600 L
"Invalid Configuration, Check value of IpMode or Target Via DHCP!",
1603 return EFI_INVALID_PARAMETER
;
1606 } else if ((OffSet
>= ATTEMPT_TARGET_IP_ADDRESS_VAR_OFFSET
) && (OffSet
< ATTEMPT_LUN_VAR_OFFSET
)) {
1607 if ((Attempt
->SessionConfigData
.IpMode
< IP_MODE_AUTOCONFIG
) && (!Attempt
->SessionConfigData
.TargetInfoFromDhcp
)) {
1608 UnicodeStrToAsciiStrS (IfrNvData
->Keyword
[Index
].ISCSITargetIpAddress
, IpString
, sizeof (IpString
));
1609 Status
= IScsiAsciiStrToIp (IpString
, Attempt
->SessionConfigData
.IpMode
, &HostIp
);
1610 if (EFI_ERROR (Status
) || !IpIsUnicast (&HostIp
, Attempt
->SessionConfigData
.IpMode
)) {
1611 Attempt
->SessionConfigData
.DnsMode
= TRUE
;
1612 ZeroMem (&Attempt
->SessionConfigData
.TargetIp
, sizeof (Attempt
->SessionConfigData
.TargetIp
));
1613 UnicodeStrToAsciiStrS (IfrNvData
->Keyword
[Index
].ISCSITargetIpAddress
, Attempt
->SessionConfigData
.TargetUrl
, ISCSI_NAME_MAX_SIZE
);
1615 Attempt
->SessionConfigData
.DnsMode
= FALSE
;
1616 CopyMem (&Attempt
->SessionConfigData
.TargetIp
, &HostIp
, sizeof (HostIp
));
1620 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1622 L
"Invalid Configuration, Check value of IpMode or Target Via DHCP!",
1625 return EFI_INVALID_PARAMETER
;
1628 } else if ((OffSet
>= ATTEMPT_LUN_VAR_OFFSET
) && (OffSet
< ATTEMPT_CHAR_USER_NAME_VAR_OFFSET
)) {
1629 if ((Attempt
->SessionConfigData
.IpMode
< IP_MODE_AUTOCONFIG
) && (Attempt
->SessionConfigData
.TargetInfoFromDhcp
== 0)) {
1633 UnicodeStrToAsciiStrS (IfrNvData
->Keyword
[Index
].ISCSILun
, LunString
, ISCSI_LUN_STR_MAX_LEN
);
1634 Status
= IScsiAsciiStrToLun (LunString
, (UINT8
*) &Lun
);
1635 if (EFI_ERROR (Status
)) {
1637 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1639 L
"Invalid LUN string, Examples are: 4752-3A4F-6b7e-2F99, 6734-9-156f-127, 4186-9!",
1643 CopyMem (&Attempt
->SessionConfigData
.BootLun
, &Lun
, sizeof (Lun
));
1647 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1649 L
"Invalid Configuration, Check value of IpMode or Target Via DHCP!",
1652 return EFI_INVALID_PARAMETER
;
1655 } else if ((OffSet
>= ATTEMPT_CHAR_USER_NAME_VAR_OFFSET
) && (OffSet
< ATTEMPT_CHAR_SECRET_VAR_OFFSET
)) {
1656 if (Attempt
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
1657 UnicodeStrToAsciiStrS (
1658 IfrNvData
->Keyword
[Index
].ISCSIChapUsername
,
1659 Attempt
->AuthConfigData
.CHAP
.CHAPName
,
1660 ISCSI_CHAP_NAME_STORAGE
1663 if (Attempt
->SessionConfigData
.Enabled
!= ISCSI_DISABLED
) {
1664 if (IfrNvData
->Keyword
[Index
].ISCSIChapUsername
[0] == L
'\0') {
1666 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1668 L
"CHAP Name is invalid!",
1671 return EFI_INVALID_PARAMETER
;
1676 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1678 L
"Invalid Configuration, Check value of AuthenticationType!",
1681 return EFI_INVALID_PARAMETER
;
1684 } else if ((OffSet
>= ATTEMPT_CHAR_SECRET_VAR_OFFSET
) && (OffSet
< ATTEMPT_CHAR_REVERSE_USER_NAME_VAR_OFFSET
)) {
1685 if (Attempt
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
1686 ChapSecretLen
= (UINT8
)StrLen (IfrNvData
->Keyword
[Index
].ISCSIChapSecret
);
1687 UnicodeStrToAsciiStrS (
1688 IfrNvData
->Keyword
[Index
].ISCSIChapSecret
,
1689 Attempt
->AuthConfigData
.CHAP
.CHAPSecret
,
1690 ISCSI_CHAP_SECRET_STORAGE
1693 if (Attempt
->SessionConfigData
.Enabled
!= ISCSI_DISABLED
) {
1694 if ((ChapSecretLen
< ISCSI_CHAP_SECRET_MIN_LEN
) || (ChapSecretLen
> ISCSI_CHAP_SECRET_MAX_LEN
)) {
1696 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1698 L
"The Chap Secret minimum length is 12 bytes and the maximum length is 16 bytes.",
1701 return EFI_INVALID_PARAMETER
;
1706 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1708 L
"Invalid Configuration, Check value of AuthenticationType!",
1711 return EFI_INVALID_PARAMETER
;
1714 } else if ((OffSet
>= ATTEMPT_CHAR_REVERSE_USER_NAME_VAR_OFFSET
) && (OffSet
< ATTEMPT_CHAR_REVERSE_SECRET_VAR_OFFSET
)) {
1715 if (Attempt
->AuthConfigData
.CHAP
.CHAPType
== ISCSI_CHAP_MUTUAL
) {
1716 UnicodeStrToAsciiStrS (
1717 IfrNvData
->Keyword
[Index
].ISCSIReverseChapUsername
,
1718 Attempt
->AuthConfigData
.CHAP
.ReverseCHAPName
,
1719 ISCSI_CHAP_NAME_STORAGE
1721 if (Attempt
->SessionConfigData
.Enabled
!= ISCSI_DISABLED
) {
1722 if (IfrNvData
->Keyword
[Index
].ISCSIReverseChapUsername
[0] == L
'\0') {
1724 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1726 L
"Reverse CHAP Name is invalid!",
1729 return EFI_INVALID_PARAMETER
;
1734 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1736 L
"Invalid Configuration, Check value of AuthenticationType or Chap Type!",
1739 return EFI_INVALID_PARAMETER
;
1742 } else if (OffSet
>= ATTEMPT_CHAR_REVERSE_SECRET_VAR_OFFSET
) {
1743 if (Attempt
->AuthConfigData
.CHAP
.CHAPType
== ISCSI_CHAP_MUTUAL
) {
1744 ReverseChapSecretLen
= (UINT8
)StrLen (IfrNvData
->Keyword
[Index
].ISCSIReverseChapSecret
);
1745 UnicodeStrToAsciiStrS (
1746 IfrNvData
->Keyword
[Index
].ISCSIReverseChapSecret
,
1747 Attempt
->AuthConfigData
.CHAP
.ReverseCHAPSecret
,
1748 ISCSI_CHAP_SECRET_STORAGE
1751 if (Attempt
->SessionConfigData
.Enabled
!= ISCSI_DISABLED
) {
1752 if ((ReverseChapSecretLen
< ISCSI_CHAP_SECRET_MIN_LEN
) || (ReverseChapSecretLen
> ISCSI_CHAP_SECRET_MAX_LEN
)) {
1754 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1756 L
"The Reverse CHAP Secret minimum length is 12 bytes and the maximum length is 16 bytes.",
1759 return EFI_INVALID_PARAMETER
;
1764 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1766 L
"Invalid Configuration, Check value of AuthenticationType or Chap Type!",
1769 return EFI_INVALID_PARAMETER
;
1777 // Record the user configuration information in NVR.
1779 ASSERT (Attempt
!= NULL
);
1780 UnicodeSPrint (mPrivate
->PortString
, (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
, L
"Attempt %d", Attempt
->AttemptConfigIndex
);
1781 return gRT
->SetVariable (
1782 mPrivate
->PortString
,
1783 &gEfiIScsiInitiatorNameProtocolGuid
,
1784 ISCSI_CONFIG_VAR_ATTR
,
1785 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA
),
1792 Create Hii Extend Label OpCode as the start opcode and end opcode. It is
1795 @param[in] StartLabelNumber The number of start label.
1796 @param[out] StartOpCodeHandle Points to the start opcode handle.
1797 @param[out] StartLabel Points to the created start opcode.
1798 @param[out] EndOpCodeHandle Points to the end opcode handle.
1799 @param[out] EndLabel Points to the created end opcode.
1801 @retval EFI_OUT_OF_RESOURCES Do not have sufficient resource to finish this
1803 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
1804 @retval EFI_SUCCESS The operation is completed successfully.
1809 IN UINT16 StartLabelNumber
,
1810 OUT VOID
**StartOpCodeHandle
,
1811 OUT EFI_IFR_GUID_LABEL
**StartLabel
,
1812 OUT VOID
**EndOpCodeHandle
,
1813 OUT EFI_IFR_GUID_LABEL
**EndLabel
1817 EFI_IFR_GUID_LABEL
*InternalStartLabel
;
1818 EFI_IFR_GUID_LABEL
*InternalEndLabel
;
1820 if (StartOpCodeHandle
== NULL
|| StartLabel
== NULL
|| EndOpCodeHandle
== NULL
|| EndLabel
== NULL
) {
1821 return EFI_INVALID_PARAMETER
;
1824 *StartOpCodeHandle
= NULL
;
1825 *EndOpCodeHandle
= NULL
;
1826 Status
= EFI_OUT_OF_RESOURCES
;
1829 // Initialize the container for dynamic opcodes.
1831 *StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
1832 if (*StartOpCodeHandle
== NULL
) {
1836 *EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
1837 if (*EndOpCodeHandle
== NULL
) {
1842 // Create Hii Extend Label OpCode as the start opcode.
1844 InternalStartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
1848 sizeof (EFI_IFR_GUID_LABEL
)
1850 if (InternalStartLabel
== NULL
) {
1854 InternalStartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
1855 InternalStartLabel
->Number
= StartLabelNumber
;
1858 // Create Hii Extend Label OpCode as the end opcode.
1860 InternalEndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
1864 sizeof (EFI_IFR_GUID_LABEL
)
1866 if (InternalEndLabel
== NULL
) {
1870 InternalEndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
1871 InternalEndLabel
->Number
= LABEL_END
;
1873 *StartLabel
= InternalStartLabel
;
1874 *EndLabel
= InternalEndLabel
;
1880 if (*StartOpCodeHandle
!= NULL
) {
1881 HiiFreeOpCodeHandle (*StartOpCodeHandle
);
1884 if (*EndOpCodeHandle
!= NULL
) {
1885 HiiFreeOpCodeHandle (*EndOpCodeHandle
);
1891 Update the MAIN form to display the configured attempts.
1895 IScsiConfigUpdateAttempt (
1900 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
1901 VOID
*StartOpCodeHandle
;
1902 EFI_IFR_GUID_LABEL
*StartLabel
;
1903 VOID
*EndOpCodeHandle
;
1904 EFI_IFR_GUID_LABEL
*EndLabel
;
1907 Status
= IScsiCreateOpCode (
1908 ATTEMPT_ENTRY_LABEL
,
1914 if (EFI_ERROR (Status
)) {
1918 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
1919 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
1920 if (AttemptConfigData
->Actived
== ISCSI_ACTIVE_ENABLED
) {
1922 // Update Attempt Help Info.
1924 UnicodeSPrint (mPrivate
->PortString
, (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
, L
"Attempt %d", (UINTN
) AttemptConfigData
->AttemptConfigIndex
);
1925 AttemptConfigData
->AttemptTitleToken
= HiiSetString (
1926 mCallbackInfo
->RegisteredHandle
,
1928 mPrivate
->PortString
,
1931 if (AttemptConfigData
->AttemptTitleToken
== 0) {
1935 HiiCreateGotoOpCode (
1936 StartOpCodeHandle
, // Container for dynamic created opcodes
1937 FORMID_ATTEMPT_FORM
, // Form ID
1938 AttemptConfigData
->AttemptTitleToken
, // Prompt text
1939 AttemptConfigData
->AttemptTitleHelpToken
, // Help text
1940 EFI_IFR_FLAG_CALLBACK
, // Question flag
1941 (UINT16
) (KEY_ATTEMPT_ENTRY_BASE
+ AttemptConfigData
->AttemptConfigIndex
) // Question ID
1947 mCallbackInfo
->RegisteredHandle
, // HII handle
1948 &gIScsiConfigGuid
, // Formset GUID
1949 FORMID_MAIN_FORM
, // Form ID
1950 StartOpCodeHandle
, // Label for where to insert opcodes
1951 EndOpCodeHandle
// Replace data
1954 HiiFreeOpCodeHandle (StartOpCodeHandle
);
1955 HiiFreeOpCodeHandle (EndOpCodeHandle
);
1959 Callback function when user presses "Add an Attempt".
1961 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
1963 @retval EFI_SUCCESS The operation is completed successfully.
1967 IScsiConfigAddAttempt (
1972 ISCSI_NIC_INFO
*NicInfo
;
1973 EFI_STRING_ID PortTitleToken
;
1974 EFI_STRING_ID PortTitleHelpToken
;
1975 CHAR16 MacString
[ISCSI_MAX_MAC_STRING_LEN
];
1977 VOID
*StartOpCodeHandle
;
1978 EFI_IFR_GUID_LABEL
*StartLabel
;
1979 VOID
*EndOpCodeHandle
;
1980 EFI_IFR_GUID_LABEL
*EndLabel
;
1982 Status
= IScsiCreateOpCode (
1989 if (EFI_ERROR (Status
)) {
1994 // Ask user to select a MAC for this attempt.
1996 NET_LIST_FOR_EACH (Entry
, &mPrivate
->NicInfoList
) {
1997 NicInfo
= NET_LIST_USER_STRUCT (Entry
, ISCSI_NIC_INFO
, Link
);
1999 &NicInfo
->PermanentAddress
,
2000 NicInfo
->HwAddressSize
,
2005 UnicodeSPrint (mPrivate
->PortString
, (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
, L
"MAC %s", MacString
);
2006 PortTitleToken
= HiiSetString (
2007 mCallbackInfo
->RegisteredHandle
,
2009 mPrivate
->PortString
,
2012 if (PortTitleToken
== 0) {
2013 Status
= EFI_INVALID_PARAMETER
;
2018 mPrivate
->PortString
,
2019 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
2020 L
"PFA: Bus %d | Dev %d | Func %d",
2022 NicInfo
->DeviceNumber
,
2023 NicInfo
->FunctionNumber
2025 PortTitleHelpToken
= HiiSetString (mCallbackInfo
->RegisteredHandle
, 0, mPrivate
->PortString
, NULL
);
2026 if (PortTitleHelpToken
== 0) {
2027 Status
= EFI_INVALID_PARAMETER
;
2031 HiiCreateGotoOpCode (
2032 StartOpCodeHandle
, // Container for dynamic created opcodes
2033 FORMID_ATTEMPT_FORM
,
2036 EFI_IFR_FLAG_CALLBACK
, // Question flag
2037 (UINT16
) (KEY_MAC_ENTRY_BASE
+ NicInfo
->NicIndex
)
2041 Status
= HiiUpdateForm (
2042 mCallbackInfo
->RegisteredHandle
, // HII handle
2043 &gIScsiConfigGuid
, // Formset GUID
2044 FORMID_MAC_FORM
, // Form ID
2045 StartOpCodeHandle
, // Label for where to insert opcodes
2046 EndOpCodeHandle
// Replace data
2050 HiiFreeOpCodeHandle (StartOpCodeHandle
);
2051 HiiFreeOpCodeHandle (EndOpCodeHandle
);
2057 Add the attempts by keyword 'iSCSIAddAttempts', you can use this keyword with
2058 value 'attempt:1 attempt:2' etc to add one or more attempts once. This is different
2059 with IScsiConfigAddAttempt function which is used to add attempt by UI configuration.
2061 @param[in] AttemptList The new attempt List will be added.
2063 @retval EFI_SUCCESS The operation to add attempt list successfully.
2064 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
2065 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
2066 @retval EFI_OUT_OF_RESOURCES Fail to finish the operation due to lack of
2071 IScsiConfigAddAttemptsByKeywords (
2072 IN UINT8
*AttemptList
2079 UINT8
*AttemptConfigOrder
;
2080 UINTN AttemptConfigOrderSize
;
2081 UINT8
*AttemptConfigOrderTmp
;
2082 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
2083 ISCSI_NIC_INFO
*NicInfo
;
2084 CHAR16 MacString
[ISCSI_MAX_MAC_STRING_LEN
];
2085 CHAR16 IScsiMode
[64];
2089 Nic
= mPrivate
->CurrentNic
;
2090 NicInfo
= IScsiGetNicInfoByIndex (Nic
);
2091 if (NicInfo
== NULL
) {
2092 return EFI_NOT_FOUND
;
2096 // The MAC info will be recorded in Config Data.
2099 &NicInfo
->PermanentAddress
,
2100 NicInfo
->HwAddressSize
,
2105 for (Index
= 0; Index
< PcdGet8 (PcdMaxIScsiAttemptNumber
); Index
++) {
2106 if (AttemptList
[Index
] == 0) {
2113 Number
= AttemptList
[Index
];
2116 mPrivate
->PortString
,
2117 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
2123 mPrivate
->PortString
,
2124 &gEfiIScsiInitiatorNameProtocolGuid
,
2125 (VOID
**)&AttemptConfigData
,
2128 if (AttemptConfigData
== NULL
|| AttemptConfigData
->Actived
== ISCSI_ACTIVE_ENABLED
) {
2129 return EFI_INVALID_PARAMETER
;
2132 AttemptConfigData
->Actived
= ISCSI_ACTIVE_ENABLED
;
2133 AttemptConfigData
->NicIndex
= NicInfo
->NicIndex
;
2134 UnicodeStrToAsciiStrS (MacString
, AttemptConfigData
->MacString
, ISCSI_MAX_MAC_STRING_LEN
);
2137 // Generate OUI-format ISID based on MAC address.
2139 CopyMem (AttemptConfigData
->SessionConfigData
.IsId
, &NicInfo
->PermanentAddress
, 6);
2140 AttemptConfigData
->SessionConfigData
.IsId
[0] =
2141 (UINT8
) (AttemptConfigData
->SessionConfigData
.IsId
[0] & 0x3F);
2144 // Configure the iSCSI Mode and IpMode to default.
2145 // Add Attempt Help Info.
2147 UnicodeSPrint (IScsiMode
, 64, L
"Disabled");
2148 UnicodeSPrint (IpMode
, 64, L
"IP4");
2150 mPrivate
->PortString
,
2151 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
2152 L
"MAC: %s, PFA: Bus %d | Dev %d | Func %d, iSCSI mode: %s, IP version: %s",
2155 NicInfo
->DeviceNumber
,
2156 NicInfo
->FunctionNumber
,
2161 AttemptConfigData
->AttemptTitleHelpToken
= HiiSetString (
2162 mCallbackInfo
->RegisteredHandle
,
2164 mPrivate
->PortString
,
2167 if (AttemptConfigData
->AttemptTitleHelpToken
== 0) {
2168 return EFI_OUT_OF_RESOURCES
;
2172 // Get current Attempt order and number.
2174 AttemptConfigOrder
= IScsiGetVariableAndSize (
2177 &AttemptConfigOrderSize
2179 TotalNumber
= AttemptConfigOrderSize
/ sizeof (UINT8
);
2183 // Append the new created attempt order to the end.
2185 AttemptConfigOrderTmp
= AllocateZeroPool (TotalNumber
* sizeof (UINT8
));
2186 if (AttemptConfigOrderTmp
== NULL
) {
2187 if (AttemptConfigOrder
!= NULL
) {
2188 FreePool (AttemptConfigOrder
);
2190 return EFI_OUT_OF_RESOURCES
;
2192 if (AttemptConfigOrder
!= NULL
) {
2193 CopyMem (AttemptConfigOrderTmp
, AttemptConfigOrder
, AttemptConfigOrderSize
);
2194 FreePool (AttemptConfigOrder
);
2197 AttemptConfigOrderTmp
[TotalNumber
- 1] = Number
;
2198 AttemptConfigOrder
= AttemptConfigOrderTmp
;
2199 AttemptConfigOrderSize
= TotalNumber
* sizeof (UINT8
);
2201 Status
= gRT
->SetVariable (
2204 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
2205 AttemptConfigOrderSize
,
2208 FreePool (AttemptConfigOrder
);
2209 if (EFI_ERROR (Status
)) {
2214 // Record the attempt in global link list.
2216 InsertTailList (&mPrivate
->AttemptConfigs
, &AttemptConfigData
->Link
);
2217 mPrivate
->AttemptCount
++;
2218 UnicodeSPrint (mPrivate
->PortString
, (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
, L
"Attempt %d", AttemptConfigData
->AttemptConfigIndex
);
2220 mPrivate
->PortString
,
2221 &gEfiIScsiInitiatorNameProtocolGuid
,
2222 ISCSI_CONFIG_VAR_ATTR
,
2223 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA
),
2233 Callback function when user presses "Commit Changes and Exit" in Delete Attempts or Delete Attempts by Keyword.
2235 @param[in] IfrNvData The IFR NV data.
2237 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
2238 @retval EFI_SUCCESS The operation is completed successfully.
2239 @retval EFI_ABOTRED This operation is aborted cause of error
2241 @retval EFI_OUT_OF_RESOURCES Fail to finish the operation due to lack of
2246 IScsiConfigDeleteAttempts (
2247 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
2253 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
2254 UINT8
*AttemptConfigOrder
;
2255 UINTN AttemptConfigOrderSize
;
2256 UINT8
*AttemptNewOrder
;
2257 UINT8 AttemptConfigIndex
;
2262 LIST_ENTRY
*NextEntry
;
2263 ISCSI_SESSION_CONFIG_NVDATA
*ConfigData
;
2267 AttemptConfigOrder
= IScsiGetVariableAndSize (
2270 &AttemptConfigOrderSize
2272 if ((AttemptConfigOrder
== NULL
) || (AttemptConfigOrderSize
== 0)) {
2273 return EFI_NOT_FOUND
;
2276 AttemptNewOrder
= AllocateZeroPool (AttemptConfigOrderSize
);
2277 if (AttemptNewOrder
== NULL
) {
2278 Status
= EFI_OUT_OF_RESOURCES
;
2282 Total
= AttemptConfigOrderSize
/ sizeof (UINT8
);
2285 NET_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &mPrivate
->AttemptConfigs
) {
2286 if (IfrNvData
->DeleteAttemptList
[Index
] == 0) {
2292 // Delete the attempt.
2295 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
2296 if (AttemptConfigData
== NULL
) {
2297 Status
= EFI_NOT_FOUND
;
2302 // Remove this attempt from UI configured attempt list.
2304 RemoveEntryList (&AttemptConfigData
->Link
);
2305 mPrivate
->AttemptCount
--;
2307 if (AttemptConfigData
->SessionConfigData
.Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
2308 if (mPrivate
->MpioCount
< 1) {
2309 Status
= EFI_ABORTED
;
2314 // No more attempt is enabled for MPIO. Transit the iSCSI mode to single path.
2316 if (--mPrivate
->MpioCount
== 0) {
2317 mPrivate
->EnableMpio
= FALSE
;
2319 } else if (AttemptConfigData
->SessionConfigData
.Enabled
== ISCSI_ENABLED
) {
2320 if (mPrivate
->SinglePathCount
< 1) {
2321 Status
= EFI_ABORTED
;
2325 mPrivate
->SinglePathCount
--;
2328 AttemptConfigIndex
= AttemptConfigData
->AttemptConfigIndex
;
2329 FreePool (AttemptConfigData
);
2332 // Create a new Attempt
2334 AttemptConfigData
= AllocateZeroPool (sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA
));
2335 if (AttemptConfigData
== NULL
) {
2336 return EFI_OUT_OF_RESOURCES
;
2338 ConfigData
= &AttemptConfigData
->SessionConfigData
;
2339 ConfigData
->TargetPort
= ISCSI_WELL_KNOWN_PORT
;
2340 ConfigData
->ConnectTimeout
= CONNECT_DEFAULT_TIMEOUT
;
2341 ConfigData
->ConnectRetryCount
= CONNECT_MIN_RETRY
;
2343 AttemptConfigData
->AuthenticationType
= ISCSI_AUTH_TYPE_CHAP
;
2344 AttemptConfigData
->AuthConfigData
.CHAP
.CHAPType
= ISCSI_CHAP_UNI
;
2346 // Configure the Attempt index and set variable.
2348 AttemptConfigData
->AttemptConfigIndex
= AttemptConfigIndex
;
2351 // Set the attempt name to default.
2354 mPrivate
->PortString
,
2355 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
2357 (UINTN
) AttemptConfigData
->AttemptConfigIndex
2359 UnicodeStrToAsciiStrS (mPrivate
->PortString
, AttemptConfigData
->AttemptName
, ATTEMPT_NAME_SIZE
);
2361 mPrivate
->PortString
,
2362 &gEfiIScsiInitiatorNameProtocolGuid
,
2363 ISCSI_CONFIG_VAR_ATTR
,
2364 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA
),
2369 // Mark the attempt order in NVR to be deleted - 0.
2371 for (NewIndex
= 0; NewIndex
< Total
; NewIndex
++) {
2372 if (AttemptConfigOrder
[NewIndex
] == AttemptConfigData
->AttemptConfigIndex
) {
2373 AttemptConfigOrder
[NewIndex
] = 0;
2379 if (mCallbackInfo
->Current
== AttemptConfigData
) {
2380 mCallbackInfo
->Current
= NULL
;
2382 FreePool (AttemptConfigData
);
2385 // Check next Attempt.
2391 // Construct AttemptNewOrder.
2393 for (Index
= 0, NewIndex
= 0; Index
< Total
; Index
++) {
2394 if (AttemptConfigOrder
[Index
] != 0) {
2395 AttemptNewOrder
[NewIndex
] = AttemptConfigOrder
[Index
];
2400 Attribute
= EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_NON_VOLATILE
;
2403 // Update AttemptOrder in NVR.
2405 Status
= gRT
->SetVariable (
2409 NewTotal
* sizeof (UINT8
),
2414 if (AttemptConfigOrder
!= NULL
) {
2415 FreePool (AttemptConfigOrder
);
2418 if (AttemptNewOrder
!= NULL
) {
2419 FreePool (AttemptNewOrder
);
2427 Callback function when user presses "Delete Attempts".
2429 @param[in] IfrNvData The IFR nv data.
2431 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
2432 @retval EFI_BUFFER_TOO_SMALL The buffer in UpdateData is too small.
2433 @retval EFI_SUCCESS The operation is completed successfully.
2437 IScsiConfigDisplayDeleteAttempts (
2438 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
2442 UINT8
*AttemptConfigOrder
;
2443 UINTN AttemptConfigOrderSize
;
2445 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
2447 VOID
*StartOpCodeHandle
;
2448 EFI_IFR_GUID_LABEL
*StartLabel
;
2449 VOID
*EndOpCodeHandle
;
2450 EFI_IFR_GUID_LABEL
*EndLabel
;
2453 Status
= IScsiCreateOpCode (
2460 if (EFI_ERROR (Status
)) {
2464 AttemptConfigOrder
= IScsiGetVariableAndSize (
2467 &AttemptConfigOrderSize
2469 if (AttemptConfigOrder
!= NULL
) {
2471 // Create the check box opcode to be deleted.
2475 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
2476 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
2477 IfrNvData
->DeleteAttemptList
[Index
] = 0x00;
2479 HiiCreateCheckBoxOpCode(
2481 (EFI_QUESTION_ID
) (ATTEMPT_DEL_QUESTION_ID
+ Index
),
2482 CONFIGURATION_VARSTORE_ID
,
2483 (UINT16
) (ATTEMPT_DEL_VAR_OFFSET
+ Index
),
2484 AttemptConfigData
->AttemptTitleToken
,
2485 AttemptConfigData
->AttemptTitleHelpToken
,
2493 if (Index
== ISCSI_MAX_ATTEMPTS_NUM
) {
2498 FreePool (AttemptConfigOrder
);
2501 Status
= HiiUpdateForm (
2502 mCallbackInfo
->RegisteredHandle
, // HII handle
2503 &gIScsiConfigGuid
, // Formset GUID
2504 FORMID_DELETE_FORM
, // Form ID
2505 StartOpCodeHandle
, // Label for where to insert opcodes
2506 EndOpCodeHandle
// Replace data
2509 HiiFreeOpCodeHandle (StartOpCodeHandle
);
2510 HiiFreeOpCodeHandle (EndOpCodeHandle
);
2517 Callback function when user presses "Change Attempt Order".
2519 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
2520 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
2522 @retval EFI_SUCCESS The operation is completed successfully.
2526 IScsiConfigDisplayOrderAttempts (
2533 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
2534 VOID
*StartOpCodeHandle
;
2535 EFI_IFR_GUID_LABEL
*StartLabel
;
2536 VOID
*EndOpCodeHandle
;
2537 EFI_IFR_GUID_LABEL
*EndLabel
;
2538 VOID
*OptionsOpCodeHandle
;
2540 Status
= IScsiCreateOpCode (
2547 if (EFI_ERROR (Status
)) {
2550 ASSERT (StartOpCodeHandle
!= NULL
);
2552 OptionsOpCodeHandle
= NULL
;
2555 // If no attempt to be ordered, update the original form and exit.
2557 if (mPrivate
->AttemptCount
== 0) {
2562 // Create Option OpCode.
2564 OptionsOpCodeHandle
= HiiAllocateOpCodeHandle ();
2565 if (OptionsOpCodeHandle
== NULL
) {
2566 Status
= EFI_OUT_OF_RESOURCES
;
2572 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
2573 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
2574 HiiCreateOneOfOptionOpCode (
2575 OptionsOpCodeHandle
,
2576 AttemptConfigData
->AttemptTitleToken
,
2578 EFI_IFR_NUMERIC_SIZE_1
,
2579 AttemptConfigData
->AttemptConfigIndex
2584 ASSERT (Index
== mPrivate
->AttemptCount
);
2586 HiiCreateOrderedListOpCode (
2587 StartOpCodeHandle
, // Container for dynamic created opcodes
2588 DYNAMIC_ORDERED_LIST_QUESTION_ID
, // Question ID
2589 CONFIGURATION_VARSTORE_ID
, // VarStore ID
2590 DYNAMIC_ORDERED_LIST_VAR_OFFSET
, // Offset in Buffer Storage
2591 STRING_TOKEN (STR_ORDER_ATTEMPT_ENTRY
), // Question prompt text
2592 STRING_TOKEN (STR_ORDER_ATTEMPT_ENTRY
), // Question help text
2594 EFI_IFR_UNIQUE_SET
, // Ordered list flag, e.g. EFI_IFR_UNIQUE_SET
2595 EFI_IFR_NUMERIC_SIZE_1
, // Data type of Question value
2596 ISCSI_MAX_ATTEMPTS_NUM
, // Maximum container
2597 OptionsOpCodeHandle
, // Option Opcode list
2598 NULL
// Default Opcode is NULL
2602 Status
= HiiUpdateForm (
2603 mCallbackInfo
->RegisteredHandle
, // HII handle
2604 &gIScsiConfigGuid
, // Formset GUID
2605 FORMID_ORDER_FORM
, // Form ID
2606 StartOpCodeHandle
, // Label for where to insert opcodes
2607 EndOpCodeHandle
// Replace data
2611 HiiFreeOpCodeHandle (StartOpCodeHandle
);
2612 HiiFreeOpCodeHandle (EndOpCodeHandle
);
2613 if (OptionsOpCodeHandle
!= NULL
) {
2614 HiiFreeOpCodeHandle (OptionsOpCodeHandle
);
2621 Callback function when user presses "Commit Changes and Exit" in Change Attempt Order or Change Attempt Order by Keyword.
2623 @param[in] IfrNvData The IFR nv data.
2625 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
2627 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
2628 @retval EFI_SUCCESS The operation is completed successfully.
2632 IScsiConfigOrderAttempts (
2633 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
2639 UINT8 AttemptConfigIndex
;
2640 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
2641 UINT8
*AttemptConfigOrder
;
2642 UINT8
*AttemptConfigOrderTmp
;
2643 UINTN AttemptConfigOrderSize
;
2645 AttemptConfigOrder
= IScsiGetVariableAndSize (
2648 &AttemptConfigOrderSize
2650 if (AttemptConfigOrder
== NULL
) {
2651 return EFI_NOT_FOUND
;
2654 AttemptConfigOrderTmp
= AllocateZeroPool (AttemptConfigOrderSize
);
2655 if (AttemptConfigOrderTmp
== NULL
) {
2656 Status
= EFI_OUT_OF_RESOURCES
;
2660 for (Index
= 0; Index
< ISCSI_MAX_ATTEMPTS_NUM
; Index
++) {
2662 // The real content ends with 0.
2664 if (IfrNvData
->DynamicOrderedList
[Index
] == 0) {
2668 AttemptConfigIndex
= IfrNvData
->DynamicOrderedList
[Index
];
2669 AttemptConfigData
= IScsiConfigGetAttemptByConfigIndex (AttemptConfigIndex
);
2670 if (AttemptConfigData
== NULL
) {
2671 Status
= EFI_NOT_FOUND
;
2676 // Reorder the Attempt List.
2678 RemoveEntryList (&AttemptConfigData
->Link
);
2679 InsertTailList (&mPrivate
->AttemptConfigs
, &AttemptConfigData
->Link
);
2681 AttemptConfigOrderTmp
[Index
] = AttemptConfigIndex
;
2684 // Mark it to be deleted - 0.
2686 for (Indexj
= 0; Indexj
< AttemptConfigOrderSize
/ sizeof (UINT8
); Indexj
++) {
2687 if (AttemptConfigOrder
[Indexj
] == AttemptConfigIndex
) {
2688 AttemptConfigOrder
[Indexj
] = 0;
2695 // Adjust the attempt order in NVR.
2697 for (; Index
< AttemptConfigOrderSize
/ sizeof (UINT8
); Index
++) {
2698 for (Indexj
= 0; Indexj
< AttemptConfigOrderSize
/ sizeof (UINT8
); Indexj
++) {
2699 if (AttemptConfigOrder
[Indexj
] != 0) {
2700 AttemptConfigOrderTmp
[Index
] = AttemptConfigOrder
[Indexj
];
2701 AttemptConfigOrder
[Indexj
] = 0;
2707 Status
= gRT
->SetVariable (
2710 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
2711 AttemptConfigOrderSize
,
2712 AttemptConfigOrderTmp
2716 if (AttemptConfigOrderTmp
!= NULL
) {
2717 FreePool (AttemptConfigOrderTmp
);
2720 FreePool (AttemptConfigOrder
);
2726 Callback function when a user presses "Attempt *" or when a user selects a NIC to
2727 create the new attempt.
2729 @param[in] KeyValue A unique value which is sent to the original
2730 exporting driver so that it can identify the type
2732 @param[in] IfrNvData The IFR nv data.
2734 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
2736 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
2737 @retval EFI_UNSUPPORTED Can not create more attempts.
2738 @retval EFI_SUCCESS The operation is completed successfully.
2742 IScsiConfigProcessDefault (
2743 IN EFI_QUESTION_ID KeyValue
,
2744 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
2748 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
2749 UINT8 CurrentAttemptConfigIndex
;
2750 ISCSI_NIC_INFO
*NicInfo
;
2752 CHAR16 MacString
[ISCSI_MAX_MAC_STRING_LEN
];
2753 UINT8
*AttemptConfigOrder
;
2754 UINTN AttemptConfigOrderSize
;
2758 AttemptConfigData
= NULL
;
2760 // Is User creating a new attempt?
2764 if ((KeyValue
>= KEY_MAC_ENTRY_BASE
) &&
2765 (KeyValue
<= (UINT16
) (mPrivate
->MaxNic
+ KEY_MAC_ENTRY_BASE
))) {
2767 // User has pressed "Add an Attempt" and then selects a NIC.
2770 } else if ((KeyValue
>= KEY_ATTEMPT_ENTRY_BASE
) &&
2771 (KeyValue
< (ISCSI_MAX_ATTEMPTS_NUM
+ KEY_ATTEMPT_ENTRY_BASE
))) {
2774 // User has pressed "Attempt *".
2779 // Don't process anything.
2786 // Determine which NIC user has selected for the new created attempt.
2788 NicIndex
= (UINT8
) (KeyValue
- KEY_MAC_ENTRY_BASE
);
2789 NicInfo
= IScsiGetNicInfoByIndex (NicIndex
);
2790 if (NicInfo
== NULL
) {
2791 return EFI_NOT_FOUND
;
2795 // Create an attempt following the initialized attempt order.
2797 AttemptConfigOrder
= IScsiGetVariableAndSize (
2798 L
"InitialAttemptOrder",
2800 &AttemptConfigOrderSize
2803 if (AttemptConfigOrder
== NULL
) {
2804 return EFI_NOT_FOUND
;
2807 for (Index
= 0; Index
< AttemptConfigOrderSize
/ sizeof (UINT8
); Index
++) {
2809 mPrivate
->PortString
,
2810 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
2812 (UINTN
) AttemptConfigOrder
[Index
]
2815 mPrivate
->PortString
,
2816 &gEfiIScsiInitiatorNameProtocolGuid
,
2817 (VOID
**)&AttemptConfigData
,
2820 if (AttemptConfigData
== NULL
|| AttemptConfigData
->Actived
== ISCSI_ACTIVE_ENABLED
) {
2827 if (Index
> PcdGet8 (PcdMaxIScsiAttemptNumber
)) {
2829 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2831 L
"Can not create more attempts, Please configure the PcdMaxIScsiAttemptNumber if needed!",
2834 return EFI_UNSUPPORTED
;
2837 if (AttemptConfigOrder
!= NULL
) {
2838 FreePool (AttemptConfigOrder
);
2842 // Record the MAC info in Config Data.
2845 &NicInfo
->PermanentAddress
,
2846 NicInfo
->HwAddressSize
,
2851 ASSERT (AttemptConfigData
!= NULL
);
2852 UnicodeStrToAsciiStrS (MacString
, AttemptConfigData
->MacString
, sizeof (AttemptConfigData
->MacString
));
2853 AttemptConfigData
->NicIndex
= NicIndex
;
2854 AttemptConfigData
->Actived
= ISCSI_ACTIVE_ENABLED
;
2857 // Generate OUI-format ISID based on MAC address.
2859 CopyMem (AttemptConfigData
->SessionConfigData
.IsId
, &NicInfo
->PermanentAddress
, 6);
2860 AttemptConfigData
->SessionConfigData
.IsId
[0] =
2861 (UINT8
) (AttemptConfigData
->SessionConfigData
.IsId
[0] & 0x3F);
2864 // Add the help info for the new attempt.
2867 mPrivate
->PortString
,
2868 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
2869 L
"MAC: %s, PFA: Bus %d | Dev %d | Func %d",
2872 NicInfo
->DeviceNumber
,
2873 NicInfo
->FunctionNumber
2876 AttemptConfigData
->AttemptTitleHelpToken
= HiiSetString (
2877 mCallbackInfo
->RegisteredHandle
,
2879 mPrivate
->PortString
,
2882 if (AttemptConfigData
->AttemptTitleHelpToken
== 0) {
2883 FreePool (AttemptConfigData
);
2884 return EFI_OUT_OF_RESOURCES
;
2889 // Determine which Attempt user has selected to configure.
2890 // Get the attempt configuration data.
2892 CurrentAttemptConfigIndex
= (UINT8
) (KeyValue
- KEY_ATTEMPT_ENTRY_BASE
);
2894 AttemptConfigData
= IScsiConfigGetAttemptByConfigIndex (CurrentAttemptConfigIndex
);
2895 if (AttemptConfigData
== NULL
) {
2896 DEBUG ((DEBUG_ERROR
, "Corresponding configuration data can not be retrieved!\n"));
2897 return EFI_NOT_FOUND
;
2902 // Clear the old IFR data to avoid sharing it with other attempts.
2904 if (IfrNvData
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
2905 ZeroMem (IfrNvData
->CHAPName
, sizeof (IfrNvData
->CHAPName
));
2906 ZeroMem (IfrNvData
->CHAPSecret
, sizeof (IfrNvData
->CHAPSecret
));
2907 ZeroMem (IfrNvData
->ReverseCHAPName
, sizeof (IfrNvData
->ReverseCHAPName
));
2908 ZeroMem (IfrNvData
->ReverseCHAPSecret
, sizeof (IfrNvData
->ReverseCHAPSecret
));
2911 IScsiConvertAttemptConfigDataToIfrNvData (AttemptConfigData
, IfrNvData
);
2914 // Update current attempt to be a new created attempt or an existing attempt.
2916 mCallbackInfo
->Current
= AttemptConfigData
;
2924 This function allows the caller to request the current
2925 configuration for one or more named elements. The resulting
2926 string is in <ConfigAltResp> format. Also, any and all alternative
2927 configuration strings shall be appended to the end of the
2928 current configuration string. If they are, they must appear
2929 after the current configuration. They must contain the same
2930 routing (GUID, NAME, PATH) as the current configuration string.
2931 They must have an additional description indicating the type of
2932 alternative configuration the string represents,
2933 "ALTCFG=<StringToken>". That <StringToken> (when
2934 converted from Hex UNICODE to binary) is a reference to a
2935 string in the associated string pack.
2937 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
2939 @param[in] Request A null-terminated Unicode string in
2940 <ConfigRequest> format. Note that this
2941 includes the routing information as well as
2942 the configurable name / value pairs. It is
2943 invalid for this string to be in
2944 <MultiConfigRequest> format.
2946 @param[out] Progress On return, points to a character in the
2947 Request string. Points to the string's null
2948 terminator if request was successful. Points
2949 to the most recent "&" before the first
2950 failing name / value pair (or the beginning
2951 of the string if the failure is in the first
2952 name / value pair) if the request was not successful.
2954 @param[out] Results A null-terminated Unicode string in
2955 <ConfigAltResp> format which has all values
2956 filled in for the names in the Request string.
2957 String to be allocated by the called function.
2959 @retval EFI_SUCCESS The Results string is filled with the
2960 values corresponding to all requested
2963 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
2964 parts of the results that must be
2965 stored awaiting possible future
2968 @retval EFI_INVALID_PARAMETER For example, passing in a NULL
2969 for the Request parameter
2970 would result in this type of
2971 error. In this case, the
2972 Progress parameter would be
2975 @retval EFI_NOT_FOUND Routing data doesn't match any
2976 known driver. Progress set to the
2977 first character in the routing header.
2978 Note: There is no requirement that the
2979 driver validate the routing data. It
2980 must skip the <ConfigHdr> in order to
2983 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set
2984 to most recent "&" before the
2985 error or the beginning of the
2988 @retval EFI_INVALID_PARAMETER Unknown name. Progress points
2989 to the & before the name in
2995 IScsiFormExtractConfig (
2996 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
2997 IN CONST EFI_STRING Request
,
2998 OUT EFI_STRING
*Progress
,
2999 OUT EFI_STRING
*Results
3003 CHAR8
*InitiatorName
;
3005 ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
;
3006 ISCSI_FORM_CALLBACK_INFO
*Private
;
3007 EFI_STRING ConfigRequestHdr
;
3008 EFI_STRING ConfigRequest
;
3009 BOOLEAN AllocatedRequest
;
3012 if (This
== NULL
|| Progress
== NULL
|| Results
== NULL
) {
3013 return EFI_INVALID_PARAMETER
;
3016 *Progress
= Request
;
3017 if ((Request
!= NULL
) && !HiiIsConfigHdrMatch (Request
, &gIScsiConfigGuid
, mVendorStorageName
)) {
3018 return EFI_NOT_FOUND
;
3021 ConfigRequestHdr
= NULL
;
3022 ConfigRequest
= NULL
;
3023 AllocatedRequest
= FALSE
;
3026 Private
= ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This
);
3027 IfrNvData
= AllocateZeroPool (sizeof (ISCSI_CONFIG_IFR_NVDATA
));
3028 if (IfrNvData
== NULL
) {
3029 return EFI_OUT_OF_RESOURCES
;
3033 if (Private
->Current
!= NULL
) {
3034 IScsiConvertAttemptConfigDataToIfrNvData (Private
->Current
, IfrNvData
);
3038 // Extract all AttemptConfigData to Keyword stroage of IfrNvData.
3040 IScsiConvertAttemptConfigDataToIfrNvDataByKeyword (IfrNvData
);
3042 BufferSize
= ISCSI_NAME_MAX_SIZE
;
3043 InitiatorName
= (CHAR8
*) AllocateZeroPool (BufferSize
);
3044 if (InitiatorName
== NULL
) {
3045 FreePool (IfrNvData
);
3046 return EFI_OUT_OF_RESOURCES
;
3049 Status
= gIScsiInitiatorName
.Get (&gIScsiInitiatorName
, &BufferSize
, InitiatorName
);
3050 if (EFI_ERROR (Status
)) {
3051 IfrNvData
->InitiatorName
[0] = L
'\0';
3053 AsciiStrToUnicodeStrS (
3055 IfrNvData
->InitiatorName
,
3056 sizeof (IfrNvData
->InitiatorName
) / sizeof (IfrNvData
->InitiatorName
[0])
3061 // Convert buffer data to <ConfigResp> by helper function BlockToConfig().
3063 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
3064 ConfigRequest
= Request
;
3065 if ((Request
== NULL
) || (StrStr (Request
, L
"OFFSET") == NULL
)) {
3067 // Request has no request element, construct full request string.
3068 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
3069 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
3071 ConfigRequestHdr
= HiiConstructConfigHdr (&gIScsiConfigGuid
, mVendorStorageName
, Private
->DriverHandle
);
3072 Size
= (StrLen (ConfigRequestHdr
) + 32 + 1) * sizeof (CHAR16
);
3073 ConfigRequest
= AllocateZeroPool (Size
);
3074 if (ConfigRequest
== NULL
) {
3075 FreePool (IfrNvData
);
3076 FreePool (InitiatorName
);
3077 return EFI_OUT_OF_RESOURCES
;
3079 AllocatedRequest
= TRUE
;
3080 UnicodeSPrint (ConfigRequest
, Size
, L
"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr
, (UINT64
)BufferSize
);
3081 FreePool (ConfigRequestHdr
);
3084 Status
= gHiiConfigRouting
->BlockToConfig (
3087 (UINT8
*) IfrNvData
,
3092 FreePool (IfrNvData
);
3093 FreePool (InitiatorName
);
3096 // Free the allocated config request string.
3098 if (AllocatedRequest
) {
3099 FreePool (ConfigRequest
);
3100 ConfigRequest
= NULL
;
3103 // Set Progress string to the original request string.
3105 if (Request
== NULL
) {
3107 } else if (StrStr (Request
, L
"OFFSET") == NULL
) {
3108 *Progress
= Request
+ StrLen (Request
);
3117 This function applies changes in a driver's configuration.
3118 Input is a Configuration, which has the routing data for this
3119 driver followed by name / value configuration pairs. The driver
3120 must apply those pairs to its configurable storage. If the
3121 driver's configuration is stored in a linear block of data
3122 and the driver's name / value pairs are in <BlockConfig>
3123 format, it may use the ConfigToBlock helper function (above) to
3126 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
3128 @param[in] Configuration A null-terminated Unicode string in
3129 <ConfigString> format.
3131 @param[out] Progress A pointer to a string filled in with the
3132 offset of the most recent '&' before the
3133 first failing name / value pair (or the
3134 beginning of the string if the failure
3135 is in the first name / value pair) or
3136 the terminating NULL if all was
3139 @retval EFI_SUCCESS The results have been distributed or are
3140 awaiting distribution.
3142 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
3143 parts of the results that must be
3144 stored awaiting possible future
3147 @retval EFI_INVALID_PARAMETERS Passing in a NULL for the
3148 Results parameter would result
3149 in this type of error.
3151 @retval EFI_NOT_FOUND Target for the specified routing data
3157 IScsiFormRouteConfig (
3158 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
3159 IN CONST EFI_STRING Configuration
,
3160 OUT EFI_STRING
*Progress
3164 ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
;
3165 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
3167 LIST_ENTRY
*NextEntry
;
3168 ISCSI_NIC_INFO
*NicInfo
;
3170 CHAR16 MacString
[ISCSI_MAX_MAC_STRING_LEN
];
3171 CHAR8
*InitiatorName
;
3182 Status
= EFI_SUCCESS
;
3184 if (This
== NULL
|| Configuration
== NULL
|| Progress
== NULL
) {
3185 return EFI_INVALID_PARAMETER
;
3189 // Check routing data in <ConfigHdr>.
3190 // Note: if only one Storage is used, then this checking could be skipped.
3192 if (!HiiIsConfigHdrMatch (Configuration
, &gIScsiConfigGuid
, mVendorStorageName
)) {
3193 *Progress
= Configuration
;
3194 return EFI_NOT_FOUND
;
3197 IfrNvData
= AllocateZeroPool (sizeof (ISCSI_CONFIG_IFR_NVDATA
));
3198 if (IfrNvData
== NULL
) {
3199 return EFI_OUT_OF_RESOURCES
;
3202 BufferSize
= ISCSI_NAME_MAX_SIZE
;
3203 InitiatorName
= (CHAR8
*) AllocateZeroPool (BufferSize
);
3204 if (InitiatorName
== NULL
) {
3205 Status
= EFI_OUT_OF_RESOURCES
;
3210 // Convert <ConfigResp> to buffer data by helper function ConfigToBlock().
3212 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
3213 Status
= gHiiConfigRouting
->ConfigToBlock (
3216 (UINT8
*) IfrNvData
,
3220 if (EFI_ERROR (Status
)) {
3224 if (IfrNvData
->InitiatorName
[0] != L
'\0') {
3225 UnicodeStrToAsciiStrS (IfrNvData
->InitiatorName
, InitiatorName
, ISCSI_NAME_MAX_SIZE
);
3226 BufferSize
= AsciiStrSize (InitiatorName
);
3228 Status
= gIScsiInitiatorName
.Set (&gIScsiInitiatorName
, &BufferSize
, InitiatorName
);
3229 if (EFI_ERROR (Status
)) {
3231 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3233 L
"Invalid iSCSI Name!",
3239 Status
= IScsiGetValue (Configuration
, L
"&OFFSET=", &OffSet
);
3240 if (EFI_ERROR (Status
)) {
3244 if (OffSet
>= ATTEMPT_MAC_ADDR_VAR_OFFSET
) {
3245 Status
= gIScsiInitiatorName
.Get (&gIScsiInitiatorName
, &BufferSize
, InitiatorName
);
3246 if (EFI_ERROR (Status
)) {
3248 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3250 L
"Error: please configure iSCSI initiator name first!",
3259 if (IfrNvData
->ISCSIAddAttemptList
[0] != L
'\0') {
3260 Status
=IScsiGetAttemptIndexList (IfrNvData
->ISCSIAddAttemptList
, IfrNvData
->AddAttemptList
, TRUE
);
3261 if (EFI_ERROR (Status
)) {
3263 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3265 L
"Error: The add attempt list is invalid",
3271 Status
= IScsiConfigAddAttemptsByKeywords (IfrNvData
->AddAttemptList
);
3272 if (EFI_ERROR (Status
)) {
3276 } else if (IfrNvData
->ISCSIDeleteAttemptList
[0] != L
'\0') {
3277 AttemptList
=(UINT8
*) AllocateZeroPool ((ISCSI_MAX_ATTEMPTS_NUM
+ 1) * sizeof (UINT8
));
3278 if (AttemptList
== NULL
) {
3279 Status
= EFI_OUT_OF_RESOURCES
;
3282 Status
= IScsiGetAttemptIndexList (IfrNvData
->ISCSIDeleteAttemptList
, AttemptList
, FALSE
);
3283 if (EFI_ERROR (Status
)) {
3285 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3287 L
"Error: The delete attempt list is invalid",
3294 // Mark the attempt which will be delete in the global list.
3296 NET_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &mPrivate
->AttemptConfigs
) {
3297 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
3298 while (AttemptList
[Index
] != 0) {
3299 if (AttemptConfigData
->AttemptConfigIndex
== AttemptList
[Index
]) {
3300 IfrNvData
->DeleteAttemptList
[Index2
] = 1;
3309 Status
= IScsiConfigDeleteAttempts (IfrNvData
);
3310 if (EFI_ERROR (Status
)) {
3314 FreePool (AttemptList
);
3316 } else if (IfrNvData
->ISCSIAttemptOrder
[0] != L
'\0') {
3317 Status
= IScsiGetAttemptIndexList (IfrNvData
->ISCSIAttemptOrder
, IfrNvData
->DynamicOrderedList
, FALSE
);
3318 if (EFI_ERROR (Status
)) {
3320 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3322 L
"Error: The new attempt order list is invalid",
3328 Status
= IScsiConfigOrderAttempts (IfrNvData
);
3329 if (EFI_ERROR (Status
)) {
3333 } else if (IfrNvData
->ISCSIMacAddr
[0] != L
'\0') {
3334 NET_LIST_FOR_EACH (Entry
, &mPrivate
->NicInfoList
) {
3335 NicInfo
= NET_LIST_USER_STRUCT (Entry
, ISCSI_NIC_INFO
, Link
);
3337 &NicInfo
->PermanentAddress
,
3338 NicInfo
->HwAddressSize
,
3342 if (!StrCmp(MacString
, IfrNvData
->ISCSIMacAddr
)) {
3343 mPrivate
->CurrentNic
= NicInfo
->NicIndex
;
3348 if ((NicInfo
== NULL
) || (NicInfo
->NicIndex
== 0)) {
3349 Status
= EFI_NOT_FOUND
;
3354 Status
= IScsiConvertlfrNvDataToAttemptConfigDataByKeyword (IfrNvData
, OffSet
);
3355 if (EFI_ERROR (Status
)) {
3361 IScsiConfigUpdateAttempt ();
3364 if (InitiatorName
!= NULL
) {
3365 FreePool (InitiatorName
);
3368 if (IfrNvData
!= NULL
) {
3369 FreePool (IfrNvData
);
3377 This function is called to provide results data to the driver.
3378 This data consists of a unique key that is used to identify
3379 which data is either being passed back or being asked for.
3381 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
3382 @param[in] Action Specifies the type of action taken by the browser.
3383 @param[in] QuestionId A unique value which is sent to the original
3384 exporting driver so that it can identify the type
3385 of data to expect. The format of the data tends to
3386 vary based on the opcode that generated the callback.
3387 @param[in] Type The type of value for the question.
3388 @param[in, out] Value A pointer to the data being sent to the original
3390 @param[out] ActionRequest On return, points to the action requested by the
3393 @retval EFI_SUCCESS The callback successfully handled the action.
3394 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
3395 variable and its data.
3396 @retval EFI_DEVICE_ERROR The variable could not be saved.
3397 @retval EFI_UNSUPPORTED The specified Action is not supported by the
3403 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
3404 IN EFI_BROWSER_ACTION Action
,
3405 IN EFI_QUESTION_ID QuestionId
,
3407 IN OUT EFI_IFR_TYPE_VALUE
*Value
,
3408 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
3411 ISCSI_FORM_CALLBACK_INFO
*Private
;
3414 CHAR8 IpString
[ISCSI_NAME_MAX_SIZE
];
3415 CHAR8 LunString
[ISCSI_LUN_STR_MAX_LEN
];
3417 EFI_IP_ADDRESS HostIp
;
3418 EFI_IP_ADDRESS SubnetMask
;
3419 EFI_IP_ADDRESS Gateway
;
3420 ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
;
3421 ISCSI_CONFIG_IFR_NVDATA OldIfrNvData
;
3425 if ((Action
== EFI_BROWSER_ACTION_FORM_OPEN
) || (Action
== EFI_BROWSER_ACTION_FORM_CLOSE
)) {
3427 // Do nothing for UEFI OPEN/CLOSE Action
3432 if ((Action
!= EFI_BROWSER_ACTION_CHANGING
) && (Action
!= EFI_BROWSER_ACTION_CHANGED
)) {
3434 // All other type return unsupported.
3436 return EFI_UNSUPPORTED
;
3439 if ((Value
== NULL
) || (ActionRequest
== NULL
)) {
3440 return EFI_INVALID_PARAMETER
;
3443 Private
= ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This
);
3446 // Retrieve uncommitted data from Browser
3449 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
3450 IfrNvData
= AllocateZeroPool (BufferSize
);
3451 if (IfrNvData
== NULL
) {
3452 return EFI_OUT_OF_RESOURCES
;
3455 IScsiName
= (CHAR8
*) AllocateZeroPool (ISCSI_NAME_MAX_SIZE
);
3456 if (IScsiName
== NULL
) {
3457 FreePool (IfrNvData
);
3458 return EFI_OUT_OF_RESOURCES
;
3461 Status
= EFI_SUCCESS
;
3463 ZeroMem (&OldIfrNvData
, BufferSize
);
3465 HiiGetBrowserData (NULL
, NULL
, BufferSize
, (UINT8
*) IfrNvData
);
3467 CopyMem (&OldIfrNvData
, IfrNvData
, BufferSize
);
3469 if (Action
== EFI_BROWSER_ACTION_CHANGING
) {
3470 switch (QuestionId
) {
3471 case KEY_ADD_ATTEMPT
:
3473 // Check whether iSCSI initiator name is configured already.
3475 mPrivate
->InitiatorNameLength
= ISCSI_NAME_MAX_SIZE
;
3476 Status
= gIScsiInitiatorName
.Get (
3477 &gIScsiInitiatorName
,
3478 &mPrivate
->InitiatorNameLength
,
3479 mPrivate
->InitiatorName
3481 if (EFI_ERROR (Status
)) {
3483 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3485 L
"Error: please configure iSCSI initiator name first!",
3491 Status
= IScsiConfigAddAttempt ();
3494 case KEY_DELETE_ATTEMPT
:
3496 OldIfrNvData
.DeleteAttemptList
,
3497 IfrNvData
->DeleteAttemptList
,
3498 sizeof (IfrNvData
->DeleteAttemptList
)
3500 Status
= IScsiConfigDisplayDeleteAttempts (IfrNvData
);
3503 case KEY_ORDER_ATTEMPT_CONFIG
:
3505 // Order the attempt according to user input.
3508 OldIfrNvData
.DynamicOrderedList
,
3509 IfrNvData
->DynamicOrderedList
,
3510 sizeof (IfrNvData
->DynamicOrderedList
)
3512 IScsiConfigDisplayOrderAttempts ();
3516 Status
= IScsiConfigProcessDefault (QuestionId
, IfrNvData
);
3519 } else if (Action
== EFI_BROWSER_ACTION_CHANGED
) {
3520 switch (QuestionId
) {
3521 case KEY_INITIATOR_NAME
:
3522 UnicodeStrToAsciiStrS (IfrNvData
->InitiatorName
, IScsiName
, ISCSI_NAME_MAX_SIZE
);
3523 BufferSize
= AsciiStrSize (IScsiName
);
3525 Status
= gIScsiInitiatorName
.Set (&gIScsiInitiatorName
, &BufferSize
, IScsiName
);
3526 if (EFI_ERROR (Status
)) {
3528 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3530 L
"Invalid iSCSI Name!",
3535 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
3538 case KEY_SAVE_ATTEMPT_CONFIG
:
3539 Status
= IScsiConvertIfrNvDataToAttemptConfigData (IfrNvData
, Private
->Current
);
3540 if (EFI_ERROR (Status
)) {
3544 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT
;
3547 case KEY_SAVE_ORDER_CHANGES
:
3549 // Sync the Attempt Order to NVR.
3551 Status
= IScsiConfigOrderAttempts (IfrNvData
);
3552 if (EFI_ERROR (Status
)) {
3556 IScsiConfigUpdateAttempt ();
3557 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT
;
3560 case KEY_IGNORE_ORDER_CHANGES
:
3562 IfrNvData
->DynamicOrderedList
,
3563 OldIfrNvData
.DynamicOrderedList
,
3564 sizeof (IfrNvData
->DynamicOrderedList
)
3566 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT
;
3569 case KEY_SAVE_DELETE_ATTEMPT
:
3571 // Delete the Attempt Order from NVR
3573 Status
= IScsiConfigDeleteAttempts (IfrNvData
);
3574 if (EFI_ERROR (Status
)) {
3578 IScsiConfigUpdateAttempt ();
3579 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT
;
3582 case KEY_IGNORE_DELETE_ATTEMPT
:
3584 IfrNvData
->DeleteAttemptList
,
3585 OldIfrNvData
.DeleteAttemptList
,
3586 sizeof (IfrNvData
->DeleteAttemptList
)
3588 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT
;
3592 switch (Value
->u8
) {
3595 ZeroMem (IfrNvData
->LocalIp
, sizeof (IfrNvData
->LocalIp
));
3596 ZeroMem (IfrNvData
->SubnetMask
, sizeof (IfrNvData
->SubnetMask
));
3597 ZeroMem (IfrNvData
->Gateway
, sizeof (IfrNvData
->Gateway
));
3598 ZeroMem (IfrNvData
->TargetIp
, sizeof (IfrNvData
->TargetIp
));
3599 Private
->Current
->AutoConfigureMode
= 0;
3600 ZeroMem (&Private
->Current
->SessionConfigData
.LocalIp
, sizeof (EFI_IP_ADDRESS
));
3601 ZeroMem (&Private
->Current
->SessionConfigData
.SubnetMask
, sizeof (EFI_IPv4_ADDRESS
));
3602 ZeroMem (&Private
->Current
->SessionConfigData
.Gateway
, sizeof (EFI_IP_ADDRESS
));
3603 ZeroMem (&Private
->Current
->SessionConfigData
.TargetIp
, sizeof (EFI_IP_ADDRESS
));
3611 Status
= NetLibStrToIp4 (IfrNvData
->LocalIp
, &HostIp
.v4
);
3612 if (EFI_ERROR (Status
) ||
3613 ((Private
->Current
->SessionConfigData
.SubnetMask
.Addr
[0] != 0) &&
3614 !NetIp4IsUnicast (NTOHL (HostIp
.Addr
[0]), NTOHL(*(UINT32
*)Private
->Current
->SessionConfigData
.SubnetMask
.Addr
)))) {
3616 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3618 L
"Invalid IP address!",
3622 Status
= EFI_INVALID_PARAMETER
;
3624 CopyMem (&Private
->Current
->SessionConfigData
.LocalIp
, &HostIp
.v4
, sizeof (HostIp
.v4
));
3629 case KEY_SUBNET_MASK
:
3630 Status
= NetLibStrToIp4 (IfrNvData
->SubnetMask
, &SubnetMask
.v4
);
3631 if (EFI_ERROR (Status
) || ((SubnetMask
.Addr
[0] != 0) && (IScsiGetSubnetMaskPrefixLength (&SubnetMask
.v4
) == 0))) {
3633 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3635 L
"Invalid Subnet Mask!",
3639 Status
= EFI_INVALID_PARAMETER
;
3641 CopyMem (&Private
->Current
->SessionConfigData
.SubnetMask
, &SubnetMask
.v4
, sizeof (SubnetMask
.v4
));
3647 Status
= NetLibStrToIp4 (IfrNvData
->Gateway
, &Gateway
.v4
);
3648 if (EFI_ERROR (Status
) ||
3649 ((Gateway
.Addr
[0] != 0) &&
3650 (Private
->Current
->SessionConfigData
.SubnetMask
.Addr
[0] != 0) &&
3651 !NetIp4IsUnicast (NTOHL (Gateway
.Addr
[0]), NTOHL(*(UINT32
*)Private
->Current
->SessionConfigData
.SubnetMask
.Addr
)))) {
3653 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3655 L
"Invalid Gateway!",
3658 Status
= EFI_INVALID_PARAMETER
;
3660 CopyMem (&Private
->Current
->SessionConfigData
.Gateway
, &Gateway
.v4
, sizeof (Gateway
.v4
));
3666 UnicodeStrToAsciiStrS (IfrNvData
->TargetIp
, IpString
, sizeof (IpString
));
3667 Status
= IScsiAsciiStrToIp (IpString
, IfrNvData
->IpMode
, &HostIp
);
3668 if (EFI_ERROR (Status
) || !IpIsUnicast (&HostIp
, IfrNvData
->IpMode
)) {
3670 // The target is expressed in URL format or an invalid Ip address, just save.
3672 Private
->Current
->SessionConfigData
.DnsMode
= TRUE
;
3673 ZeroMem (&Private
->Current
->SessionConfigData
.TargetIp
, sizeof (Private
->Current
->SessionConfigData
.TargetIp
));
3674 UnicodeStrToAsciiStrS (IfrNvData
->TargetIp
, Private
->Current
->SessionConfigData
.TargetUrl
, ISCSI_NAME_MAX_SIZE
);
3676 Private
->Current
->SessionConfigData
.DnsMode
= FALSE
;
3677 CopyMem (&Private
->Current
->SessionConfigData
.TargetIp
, &HostIp
, sizeof (HostIp
));
3682 case KEY_TARGET_NAME
:
3683 UnicodeStrToAsciiStrS (IfrNvData
->TargetName
, IScsiName
, ISCSI_NAME_MAX_SIZE
);
3684 Status
= IScsiNormalizeName (IScsiName
, AsciiStrLen (IScsiName
));
3685 if (EFI_ERROR (Status
)) {
3687 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3689 L
"Invalid iSCSI Name!",
3693 AsciiStrCpyS (Private
->Current
->SessionConfigData
.TargetName
, ISCSI_NAME_MAX_SIZE
, IScsiName
);
3698 case KEY_DHCP_ENABLE
:
3699 if (IfrNvData
->InitiatorInfoFromDhcp
== 0) {
3700 IfrNvData
->TargetInfoFromDhcp
= 0;
3706 UnicodeStrToAsciiStrS (IfrNvData
->BootLun
, LunString
, sizeof (LunString
));
3707 Status
= IScsiAsciiStrToLun (LunString
, (UINT8
*) &Lun
);
3708 if (EFI_ERROR (Status
)) {
3710 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3712 L
"Invalid LUN string!",
3716 CopyMem (Private
->Current
->SessionConfigData
.BootLun
, &Lun
, sizeof (Lun
));
3722 switch (Value
->u8
) {
3723 case ISCSI_AUTH_TYPE_CHAP
:
3724 IfrNvData
->CHAPType
= ISCSI_CHAP_UNI
;
3733 UnicodeStrToAsciiStrS (
3734 IfrNvData
->CHAPName
,
3735 Private
->Current
->AuthConfigData
.CHAP
.CHAPName
,
3736 sizeof (Private
->Current
->AuthConfigData
.CHAP
.CHAPName
)
3740 case KEY_CHAP_SECRET
:
3741 UnicodeStrToAsciiStrS (
3742 IfrNvData
->CHAPSecret
,
3743 Private
->Current
->AuthConfigData
.CHAP
.CHAPSecret
,
3744 sizeof (Private
->Current
->AuthConfigData
.CHAP
.CHAPSecret
)
3748 case KEY_REVERSE_CHAP_NAME
:
3749 UnicodeStrToAsciiStrS (
3750 IfrNvData
->ReverseCHAPName
,
3751 Private
->Current
->AuthConfigData
.CHAP
.ReverseCHAPName
,
3752 sizeof (Private
->Current
->AuthConfigData
.CHAP
.ReverseCHAPName
)
3756 case KEY_REVERSE_CHAP_SECRET
:
3757 UnicodeStrToAsciiStrS (
3758 IfrNvData
->ReverseCHAPSecret
,
3759 Private
->Current
->AuthConfigData
.CHAP
.ReverseCHAPSecret
,
3760 sizeof (Private
->Current
->AuthConfigData
.CHAP
.ReverseCHAPSecret
)
3764 case KEY_CONFIG_ISID
:
3765 IScsiParseIsIdFromString (IfrNvData
->IsId
, Private
->Current
->SessionConfigData
.IsId
);
3766 IScsiConvertIsIdToString (IfrNvData
->IsId
, Private
->Current
->SessionConfigData
.IsId
);
3775 if (!EFI_ERROR (Status
)) {
3777 // Pass changed uncommitted data back to Form Browser.
3779 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
3780 HiiSetBrowserData (NULL
, NULL
, BufferSize
, (UINT8
*) IfrNvData
, NULL
);
3783 FreePool (IfrNvData
);
3784 FreePool (IScsiName
);
3791 Initialize the iSCSI configuration form.
3793 @param[in] DriverBindingHandle The iSCSI driverbinding handle.
3795 @retval EFI_SUCCESS The iSCSI configuration form is initialized.
3796 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
3800 IScsiConfigFormInit (
3801 IN EFI_HANDLE DriverBindingHandle
3805 ISCSI_FORM_CALLBACK_INFO
*CallbackInfo
;
3807 CallbackInfo
= (ISCSI_FORM_CALLBACK_INFO
*) AllocateZeroPool (sizeof (ISCSI_FORM_CALLBACK_INFO
));
3808 if (CallbackInfo
== NULL
) {
3809 return EFI_OUT_OF_RESOURCES
;
3812 CallbackInfo
->Signature
= ISCSI_FORM_CALLBACK_INFO_SIGNATURE
;
3813 CallbackInfo
->Current
= NULL
;
3815 CallbackInfo
->ConfigAccess
.ExtractConfig
= IScsiFormExtractConfig
;
3816 CallbackInfo
->ConfigAccess
.RouteConfig
= IScsiFormRouteConfig
;
3817 CallbackInfo
->ConfigAccess
.Callback
= IScsiFormCallback
;
3820 // Install Device Path Protocol and Config Access protocol to driver handle.
3822 Status
= gBS
->InstallMultipleProtocolInterfaces (
3823 &CallbackInfo
->DriverHandle
,
3824 &gEfiDevicePathProtocolGuid
,
3825 &mIScsiHiiVendorDevicePath
,
3826 &gEfiHiiConfigAccessProtocolGuid
,
3827 &CallbackInfo
->ConfigAccess
,
3830 ASSERT_EFI_ERROR (Status
);
3833 // Publish our HII data.
3835 CallbackInfo
->RegisteredHandle
= HiiAddPackages (
3837 CallbackInfo
->DriverHandle
,
3842 if (CallbackInfo
->RegisteredHandle
== NULL
) {
3843 gBS
->UninstallMultipleProtocolInterfaces (
3844 &CallbackInfo
->DriverHandle
,
3845 &gEfiDevicePathProtocolGuid
,
3846 &mIScsiHiiVendorDevicePath
,
3847 &gEfiHiiConfigAccessProtocolGuid
,
3848 &CallbackInfo
->ConfigAccess
,
3851 FreePool(CallbackInfo
);
3852 return EFI_OUT_OF_RESOURCES
;
3855 mCallbackInfo
= CallbackInfo
;
3862 Unload the iSCSI configuration form, this includes: delete all the iSCSI
3863 configuration entries, uninstall the form callback protocol, and
3864 free the resources used.
3866 @param[in] DriverBindingHandle The iSCSI driverbinding handle.
3868 @retval EFI_SUCCESS The iSCSI configuration form is unloaded.
3869 @retval Others Failed to unload the form.
3873 IScsiConfigFormUnload (
3874 IN EFI_HANDLE DriverBindingHandle
3877 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
3878 ISCSI_NIC_INFO
*NicInfo
;
3882 while (!IsListEmpty (&mPrivate
->AttemptConfigs
)) {
3883 Entry
= NetListRemoveHead (&mPrivate
->AttemptConfigs
);
3884 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
3885 FreePool (AttemptConfigData
);
3886 mPrivate
->AttemptCount
--;
3889 ASSERT (mPrivate
->AttemptCount
== 0);
3891 while (!IsListEmpty (&mPrivate
->NicInfoList
)) {
3892 Entry
= NetListRemoveHead (&mPrivate
->NicInfoList
);
3893 NicInfo
= NET_LIST_USER_STRUCT (Entry
, ISCSI_NIC_INFO
, Link
);
3895 mPrivate
->NicCount
--;
3898 ASSERT (mPrivate
->NicCount
== 0);
3900 FreePool (mPrivate
);
3904 // Remove HII package list.
3906 HiiRemovePackages (mCallbackInfo
->RegisteredHandle
);
3909 // Uninstall Device Path Protocol and Config Access protocol.
3911 Status
= gBS
->UninstallMultipleProtocolInterfaces (
3912 mCallbackInfo
->DriverHandle
,
3913 &gEfiDevicePathProtocolGuid
,
3914 &mIScsiHiiVendorDevicePath
,
3915 &gEfiHiiConfigAccessProtocolGuid
,
3916 &mCallbackInfo
->ConfigAccess
,
3920 FreePool (mCallbackInfo
);