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 NET_LIST_FOR_EACH (Entry
, &mPrivate
->NicInfoList
) {
753 NicInfo
= NET_LIST_USER_STRUCT (Entry
, ISCSI_NIC_INFO
, Link
);
755 &NicInfo
->PermanentAddress
,
756 NicInfo
->HwAddressSize
,
761 IfrNvData
->ISCSIMacAddr
+ StrLen (IfrNvData
->ISCSIMacAddr
),
763 StrLen (MacString
) * sizeof (CHAR16
)
766 *(IfrNvData
->ISCSIMacAddr
+ StrLen (IfrNvData
->ISCSIMacAddr
)) = L
'/';
772 Convert the IFR data to iSCSI configuration data.
774 @param[in] IfrNvData Point to ISCSI_CONFIG_IFR_NVDATA.
775 @param[in, out] Attempt The iSCSI attempt config data.
777 @retval EFI_INVALID_PARAMETER Any input or configured parameter is invalid.
778 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
779 @retval EFI_OUT_OF_RESOURCES The operation is failed due to lack of resources.
780 @retval EFI_ABORTED The operation is aborted.
781 @retval EFI_SUCCESS The operation is completed successfully.
785 IScsiConvertIfrNvDataToAttemptConfigData (
786 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
,
787 IN OUT ISCSI_ATTEMPT_CONFIG_NVDATA
*Attempt
790 EFI_IP_ADDRESS HostIp
;
791 EFI_IP_ADDRESS SubnetMask
;
792 EFI_IP_ADDRESS Gateway
;
794 CHAR16
*AttemptName1
;
795 CHAR16
*AttemptName2
;
796 ISCSI_ATTEMPT_CONFIG_NVDATA
*ExistAttempt
;
797 ISCSI_ATTEMPT_CONFIG_NVDATA
*SameNicAttempt
;
798 CHAR16 IScsiMode
[64];
800 ISCSI_NIC_INFO
*NicInfo
;
802 UINT8
*AttemptConfigOrder
;
803 UINTN AttemptConfigOrderSize
;
804 UINT8
*AttemptOrderTmp
;
808 if (IfrNvData
== NULL
|| Attempt
== NULL
) {
809 return EFI_INVALID_PARAMETER
;
813 // Update those fields which don't have INTERACTIVE attribute.
815 Attempt
->SessionConfigData
.ConnectRetryCount
= IfrNvData
->ConnectRetryCount
;
816 Attempt
->SessionConfigData
.ConnectTimeout
= IfrNvData
->ConnectTimeout
;
817 Attempt
->SessionConfigData
.IpMode
= IfrNvData
->IpMode
;
819 if (IfrNvData
->IpMode
< IP_MODE_AUTOCONFIG
) {
820 Attempt
->SessionConfigData
.InitiatorInfoFromDhcp
= IfrNvData
->InitiatorInfoFromDhcp
;
821 Attempt
->SessionConfigData
.TargetPort
= IfrNvData
->TargetPort
;
823 if (Attempt
->SessionConfigData
.TargetPort
== 0) {
824 Attempt
->SessionConfigData
.TargetPort
= ISCSI_WELL_KNOWN_PORT
;
827 Attempt
->SessionConfigData
.TargetInfoFromDhcp
= IfrNvData
->TargetInfoFromDhcp
;
830 Attempt
->AuthenticationType
= IfrNvData
->AuthenticationType
;
832 if (Attempt
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
833 Attempt
->AuthConfigData
.CHAP
.CHAPType
= IfrNvData
->CHAPType
;
837 // Only do full parameter validation if iSCSI is enabled on this device.
839 if (IfrNvData
->Enabled
!= ISCSI_DISABLED
) {
840 if (Attempt
->SessionConfigData
.ConnectTimeout
< CONNECT_MIN_TIMEOUT
) {
842 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
844 L
"Connection Establishing Timeout is less than minimum value 100ms.",
848 return EFI_INVALID_PARAMETER
;
852 // Validate the address configuration of the Initiator if DHCP isn't
855 if (!Attempt
->SessionConfigData
.InitiatorInfoFromDhcp
) {
856 CopyMem (&HostIp
.v4
, &Attempt
->SessionConfigData
.LocalIp
, sizeof (HostIp
.v4
));
857 CopyMem (&SubnetMask
.v4
, &Attempt
->SessionConfigData
.SubnetMask
, sizeof (SubnetMask
.v4
));
858 CopyMem (&Gateway
.v4
, &Attempt
->SessionConfigData
.Gateway
, sizeof (Gateway
.v4
));
860 if ((Gateway
.Addr
[0] != 0)) {
861 if (SubnetMask
.Addr
[0] == 0) {
863 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
865 L
"Gateway address is set but subnet mask is zero.",
869 return EFI_INVALID_PARAMETER
;
870 } else if (!IP4_NET_EQUAL (HostIp
.Addr
[0], Gateway
.Addr
[0], SubnetMask
.Addr
[0])) {
872 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
874 L
"Local IP and Gateway are not in the same subnet.",
878 return EFI_INVALID_PARAMETER
;
883 // Validate target configuration if DHCP isn't deployed.
885 if (!Attempt
->SessionConfigData
.TargetInfoFromDhcp
&& Attempt
->SessionConfigData
.IpMode
< IP_MODE_AUTOCONFIG
) {
886 if (!Attempt
->SessionConfigData
.DnsMode
) {
887 if (!IpIsUnicast (&Attempt
->SessionConfigData
.TargetIp
, IfrNvData
->IpMode
)) {
889 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
891 L
"Target IP is invalid!",
894 return EFI_INVALID_PARAMETER
;
897 if (Attempt
->SessionConfigData
.TargetUrl
[0] == '\0') {
899 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
901 L
"iSCSI target Url should not be NULL!",
904 return EFI_INVALID_PARAMETER
;
909 // Validate iSCSI target name configuration again:
910 // The format of iSCSI target name is already verified in IScsiFormCallback() when
911 // user input the name; here we only check the case user does not input the name.
913 if (Attempt
->SessionConfigData
.TargetName
[0] == '\0') {
915 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
917 L
"iSCSI target name is NULL!",
920 return EFI_INVALID_PARAMETER
;
925 // Validate the authentication info.
927 if (IfrNvData
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
928 if ((IfrNvData
->CHAPName
[0] == '\0') || (IfrNvData
->CHAPSecret
[0] == '\0')) {
930 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
932 L
"CHAP Name or CHAP Secret is invalid!",
936 return EFI_INVALID_PARAMETER
;
939 if ((IfrNvData
->CHAPType
== ISCSI_CHAP_MUTUAL
) &&
940 ((IfrNvData
->ReverseCHAPName
[0] == '\0') || (IfrNvData
->ReverseCHAPSecret
[0] == '\0'))
943 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
945 L
"Reverse CHAP Name or Reverse CHAP Secret is invalid!",
948 return EFI_INVALID_PARAMETER
;
953 // Check whether this attempt uses NIC which is already used by existing attempt.
955 SameNicAttempt
= IScsiConfigGetAttemptByNic (Attempt
, IfrNvData
->Enabled
);
956 if (SameNicAttempt
!= NULL
) {
957 AttemptName1
= (CHAR16
*) AllocateZeroPool (ATTEMPT_NAME_SIZE
* sizeof (CHAR16
));
958 if (AttemptName1
== NULL
) {
959 return EFI_OUT_OF_RESOURCES
;
962 AttemptName2
= (CHAR16
*) AllocateZeroPool (ATTEMPT_NAME_SIZE
* sizeof (CHAR16
));
963 if (AttemptName2
== NULL
) {
964 FreePool (AttemptName1
);
965 return EFI_OUT_OF_RESOURCES
;
968 AsciiStrToUnicodeStrS (Attempt
->AttemptName
, AttemptName1
, ATTEMPT_NAME_SIZE
);
969 AsciiStrToUnicodeStrS (SameNicAttempt
->AttemptName
, AttemptName2
, ATTEMPT_NAME_SIZE
);
972 mPrivate
->PortString
,
973 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
974 L
"Warning! Attempt \"%s\" uses same NIC as Attempt \"%s\".",
980 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
982 mPrivate
->PortString
,
986 FreePool (AttemptName1
);
987 FreePool (AttemptName2
);
992 // Update the iSCSI Mode data and record it in attempt help info.
994 if (IfrNvData
->Enabled
== ISCSI_DISABLED
) {
995 UnicodeSPrint (IScsiMode
, 64, L
"Disabled");
996 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
) {
997 UnicodeSPrint (IScsiMode
, 64, L
"Enabled");
998 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
999 UnicodeSPrint (IScsiMode
, 64, L
"Enabled for MPIO");
1002 if (IfrNvData
->IpMode
== IP_MODE_IP4
) {
1003 UnicodeSPrint (IpMode
, 64, L
"IP4");
1004 } else if (IfrNvData
->IpMode
== IP_MODE_IP6
) {
1005 UnicodeSPrint (IpMode
, 64, L
"IP6");
1006 } else if (IfrNvData
->IpMode
== IP_MODE_AUTOCONFIG
) {
1007 UnicodeSPrint (IpMode
, 64, L
"Autoconfigure");
1010 NicInfo
= IScsiGetNicInfoByIndex (Attempt
->NicIndex
);
1011 if (NicInfo
== NULL
) {
1012 return EFI_NOT_FOUND
;
1015 MacString
= (CHAR16
*) AllocateZeroPool (ISCSI_MAX_MAC_STRING_LEN
* sizeof (CHAR16
));
1016 if (MacString
== NULL
) {
1017 return EFI_OUT_OF_RESOURCES
;
1020 AsciiStrToUnicodeStrS (Attempt
->MacString
, MacString
, ISCSI_MAX_MAC_STRING_LEN
);
1023 mPrivate
->PortString
,
1024 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
1025 L
"MAC: %s, PFA: Bus %d | Dev %d | Func %d, iSCSI mode: %s, IP version: %s",
1028 NicInfo
->DeviceNumber
,
1029 NicInfo
->FunctionNumber
,
1034 Attempt
->AttemptTitleHelpToken
= HiiSetString (
1035 mCallbackInfo
->RegisteredHandle
,
1036 Attempt
->AttemptTitleHelpToken
,
1037 mPrivate
->PortString
,
1040 if (Attempt
->AttemptTitleHelpToken
== 0) {
1041 FreePool (MacString
);
1042 return EFI_OUT_OF_RESOURCES
;
1046 // Check whether this attempt is an existing one.
1048 ExistAttempt
= IScsiConfigGetAttemptByConfigIndex (Attempt
->AttemptConfigIndex
);
1049 if (ExistAttempt
!= NULL
) {
1050 ASSERT (ExistAttempt
== Attempt
);
1052 if (IfrNvData
->Enabled
== ISCSI_DISABLED
&&
1053 Attempt
->SessionConfigData
.Enabled
!= ISCSI_DISABLED
) {
1056 // User updates the Attempt from "Enabled"/"Enabled for MPIO" to "Disabled".
1058 if (Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
1059 if (mPrivate
->MpioCount
< 1) {
1063 if (--mPrivate
->MpioCount
== 0) {
1064 mPrivate
->EnableMpio
= FALSE
;
1066 } else if (Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED
) {
1067 if (mPrivate
->SinglePathCount
< 1) {
1070 mPrivate
->SinglePathCount
--;
1073 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
&&
1074 Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED
) {
1076 // User updates the Attempt from "Enabled" to "Enabled for MPIO".
1078 if (mPrivate
->SinglePathCount
< 1) {
1082 mPrivate
->EnableMpio
= TRUE
;
1083 mPrivate
->MpioCount
++;
1084 mPrivate
->SinglePathCount
--;
1086 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
&&
1087 Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
1089 // User updates the Attempt from "Enabled for MPIO" to "Enabled".
1091 if (mPrivate
->MpioCount
< 1) {
1095 if (--mPrivate
->MpioCount
== 0) {
1096 mPrivate
->EnableMpio
= FALSE
;
1098 mPrivate
->SinglePathCount
++;
1100 } else if (IfrNvData
->Enabled
!= ISCSI_DISABLED
&&
1101 Attempt
->SessionConfigData
.Enabled
== ISCSI_DISABLED
) {
1103 // User updates the Attempt from "Disabled" to "Enabled"/"Enabled for MPIO".
1105 if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
1106 mPrivate
->EnableMpio
= TRUE
;
1107 mPrivate
->MpioCount
++;
1109 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
) {
1110 mPrivate
->SinglePathCount
++;
1114 } else if (ExistAttempt
== NULL
) {
1116 // When a new attempt is created, pointer of the attempt is saved to
1117 // mCallbackInfo->Current in IScsiConfigProcessDefault. If input Attempt
1118 // does not match any existing attempt, it should be a new created attempt.
1119 // Save it to system now.
1123 // Save current order number for this attempt.
1125 AttemptConfigOrder
= IScsiGetVariableAndSize (
1128 &AttemptConfigOrderSize
1131 TotalNumber
= AttemptConfigOrderSize
/ sizeof (UINT8
);
1135 // Append the new created attempt order to the end.
1137 AttemptOrderTmp
= AllocateZeroPool (TotalNumber
* sizeof (UINT8
));
1138 if (AttemptOrderTmp
== NULL
) {
1139 if (AttemptConfigOrder
!= NULL
) {
1140 FreePool (AttemptConfigOrder
);
1142 return EFI_OUT_OF_RESOURCES
;
1145 if (AttemptConfigOrder
!= NULL
) {
1146 CopyMem (AttemptOrderTmp
, AttemptConfigOrder
, AttemptConfigOrderSize
);
1147 FreePool (AttemptConfigOrder
);
1150 AttemptOrderTmp
[TotalNumber
- 1] = Attempt
->AttemptConfigIndex
;
1151 AttemptConfigOrder
= AttemptOrderTmp
;
1152 AttemptConfigOrderSize
= TotalNumber
* sizeof (UINT8
);
1154 Status
= gRT
->SetVariable (
1157 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
1158 AttemptConfigOrderSize
,
1161 FreePool (AttemptConfigOrder
);
1162 if (EFI_ERROR (Status
)) {
1167 // Insert new created attempt to array.
1169 InsertTailList (&mPrivate
->AttemptConfigs
, &Attempt
->Link
);
1170 mPrivate
->AttemptCount
++;
1172 if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
1174 // This new Attempt is enabled for MPIO; enable the multipath mode.
1176 mPrivate
->EnableMpio
= TRUE
;
1177 mPrivate
->MpioCount
++;
1178 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
) {
1179 mPrivate
->SinglePathCount
++;
1182 IScsiConfigUpdateAttempt ();
1184 Attempt
->SessionConfigData
.Enabled
= IfrNvData
->Enabled
;
1187 // Record the user configuration information in NVR.
1189 UnicodeSPrint (mPrivate
->PortString
, (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
, L
"Attempt %d", Attempt
->AttemptConfigIndex
);
1191 FreePool (MacString
);
1193 return gRT
->SetVariable (
1194 mPrivate
->PortString
,
1195 &gEfiIScsiInitiatorNameProtocolGuid
,
1196 ISCSI_CONFIG_VAR_ATTR
,
1197 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA
),
1203 Convert the IFR data configured by keyword to iSCSI configuration data.
1205 @param[in] IfrNvData Point to ISCSI_CONFIG_IFR_NVDATA.
1206 @param[in] OffSet The offset of the variable to the configuration structure.
1208 @retval EFI_INVALID_PARAMETER Any input or configured parameter is invalid.
1209 @retval EFI_SUCCESS The operation is completed successfully.
1213 IScsiConvertlfrNvDataToAttemptConfigDataByKeyword (
1214 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
,
1218 ISCSI_ATTEMPT_CONFIG_NVDATA
*Attempt
;
1221 UINT8 ChapSecretLen
;
1222 UINT8 ReverseChapSecretLen
;
1223 CHAR16
*AttemptName1
;
1224 CHAR16
*AttemptName2
;
1225 ISCSI_ATTEMPT_CONFIG_NVDATA
*SameNicAttempt
;
1226 CHAR8 LunString
[ISCSI_LUN_STR_MAX_LEN
];
1227 CHAR8 IScsiName
[ISCSI_NAME_MAX_SIZE
];
1228 CHAR8 IpString
[IP_STR_MAX_SIZE
];
1229 EFI_IP_ADDRESS HostIp
;
1230 EFI_IP_ADDRESS SubnetMask
;
1231 EFI_IP_ADDRESS Gateway
;
1237 ZeroMem (IScsiName
, sizeof (IScsiName
));
1239 if (OffSet
< ATTEMPT_BOOTENABLE_VAR_OFFSET
) {
1242 } else if ((OffSet
>= ATTEMPT_BOOTENABLE_VAR_OFFSET
) && (OffSet
< ATTEMPT_ADDRESS_TYPE_VAR_OFFSET
)) {
1243 AttemptIndex
= (UINT8
) ((OffSet
- ATTEMPT_BOOTENABLE_VAR_OFFSET
) + 1);
1244 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1245 if (Attempt
== NULL
) {
1246 return EFI_INVALID_PARAMETER
;
1248 IfrNvData
->Enabled
= IfrNvData
->ISCSIBootEnableList
[AttemptIndex
- 1];
1250 // Validate the configuration of attempt.
1252 if (IfrNvData
->Enabled
!= ISCSI_DISABLED
) {
1254 // Check whether this attempt uses NIC which is already used by existing attempt.
1256 SameNicAttempt
= IScsiConfigGetAttemptByNic (Attempt
, IfrNvData
->Enabled
);
1257 if (SameNicAttempt
!= NULL
) {
1258 AttemptName1
= (CHAR16
*) AllocateZeroPool (ATTEMPT_NAME_SIZE
* sizeof (CHAR16
));
1259 if (AttemptName1
== NULL
) {
1260 return EFI_OUT_OF_RESOURCES
;
1263 AttemptName2
= (CHAR16
*) AllocateZeroPool (ATTEMPT_NAME_SIZE
* sizeof (CHAR16
));
1264 if (AttemptName2
== NULL
) {
1265 FreePool (AttemptName1
);
1266 return EFI_OUT_OF_RESOURCES
;
1269 AsciiStrToUnicodeStrS (Attempt
->AttemptName
, AttemptName1
, ATTEMPT_NAME_SIZE
);
1270 AsciiStrToUnicodeStrS (SameNicAttempt
->AttemptName
, AttemptName2
, ATTEMPT_NAME_SIZE
);
1273 mPrivate
->PortString
,
1274 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
1275 L
"Warning! \"%s\" uses same NIC as Attempt \"%s\".",
1281 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1283 mPrivate
->PortString
,
1287 FreePool (AttemptName1
);
1288 FreePool (AttemptName2
);
1292 if (IfrNvData
->Enabled
== ISCSI_DISABLED
&&
1293 Attempt
->SessionConfigData
.Enabled
!= ISCSI_DISABLED
) {
1296 // User updates the Attempt from "Enabled"/"Enabled for MPIO" to "Disabled".
1298 if (Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
1299 if (mPrivate
->MpioCount
< 1) {
1303 if (--mPrivate
->MpioCount
== 0) {
1304 mPrivate
->EnableMpio
= FALSE
;
1306 } else if (Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED
) {
1307 if (mPrivate
->SinglePathCount
< 1) {
1310 mPrivate
->SinglePathCount
--;
1313 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
&&
1314 Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED
) {
1316 // User updates the Attempt from "Enabled" to "Enabled for MPIO".
1318 if (mPrivate
->SinglePathCount
< 1) {
1322 mPrivate
->EnableMpio
= TRUE
;
1323 mPrivate
->MpioCount
++;
1324 mPrivate
->SinglePathCount
--;
1326 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
&&
1327 Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
1329 // User updates the Attempt from "Enabled for MPIO" to "Enabled".
1331 if (mPrivate
->MpioCount
< 1) {
1335 if (--mPrivate
->MpioCount
== 0) {
1336 mPrivate
->EnableMpio
= FALSE
;
1338 mPrivate
->SinglePathCount
++;
1340 } else if (IfrNvData
->Enabled
!= ISCSI_DISABLED
&&
1341 Attempt
->SessionConfigData
.Enabled
== ISCSI_DISABLED
) {
1343 // User updates the Attempt from "Disabled" to "Enabled"/"Enabled for MPIO".
1345 if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
1346 mPrivate
->EnableMpio
= TRUE
;
1347 mPrivate
->MpioCount
++;
1349 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
) {
1350 mPrivate
->SinglePathCount
++;
1353 Attempt
->SessionConfigData
.Enabled
= IfrNvData
->Enabled
;
1355 } else if ((OffSet
>= ATTEMPT_ADDRESS_TYPE_VAR_OFFSET
) && (OffSet
< ATTEMPT_CONNECT_RETRY_VAR_OFFSET
)) {
1356 AttemptIndex
= (UINT8
) ((OffSet
- ATTEMPT_ADDRESS_TYPE_VAR_OFFSET
) + 1);
1357 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1358 if (Attempt
== NULL
) {
1359 return EFI_INVALID_PARAMETER
;
1361 Attempt
->SessionConfigData
.IpMode
= IfrNvData
->ISCSIIpAddressTypeList
[AttemptIndex
- 1];
1362 if (Attempt
->SessionConfigData
.IpMode
< IP_MODE_AUTOCONFIG
) {
1363 Attempt
->AutoConfigureMode
= 0;
1366 } else if ((OffSet
>= ATTEMPT_CONNECT_RETRY_VAR_OFFSET
) && (OffSet
< ATTEMPT_CONNECT_TIMEOUT_VAR_OFFSET
)) {
1367 AttemptIndex
= (UINT8
) ((OffSet
- ATTEMPT_CONNECT_RETRY_VAR_OFFSET
) + 1);
1368 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1369 if (Attempt
== NULL
) {
1370 return EFI_INVALID_PARAMETER
;
1373 if (IfrNvData
->ISCSIConnectRetry
[AttemptIndex
- 1] > CONNECT_MAX_RETRY
) {
1375 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1377 L
"The minimum value is 0 and the maximum is 16. 0 means no retry.",
1380 return EFI_INVALID_PARAMETER
;
1382 Attempt
->SessionConfigData
.ConnectRetryCount
= IfrNvData
->ISCSIConnectRetry
[AttemptIndex
- 1];
1384 } else if ((OffSet
>= ATTEMPT_CONNECT_TIMEOUT_VAR_OFFSET
) && (OffSet
< ATTEMPT_INITIATOR_VIA_DHCP_VAR_OFFSET
)) {
1385 AttemptIndex
= (UINT8
) ((OffSet
- ATTEMPT_CONNECT_TIMEOUT_VAR_OFFSET
) / 2 + 1);
1386 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1387 if (Attempt
== NULL
) {
1388 return EFI_INVALID_PARAMETER
;
1391 if ((IfrNvData
->ISCSIConnectTimeout
[AttemptIndex
- 1] < CONNECT_MIN_TIMEOUT
) ||
1392 (IfrNvData
->ISCSIConnectTimeout
[AttemptIndex
- 1] > CONNECT_MAX_TIMEOUT
)) {
1394 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1396 L
"The minimum value is 100 milliseconds and the maximum is 20 seconds.",
1399 return EFI_INVALID_PARAMETER
;
1402 Attempt
->SessionConfigData
.ConnectTimeout
= IfrNvData
->ISCSIConnectTimeout
[AttemptIndex
- 1];
1403 if (Attempt
->SessionConfigData
.ConnectTimeout
== 0) {
1404 Attempt
->SessionConfigData
.ConnectTimeout
= CONNECT_DEFAULT_TIMEOUT
;
1407 } else if ((OffSet
>= ATTEMPT_INITIATOR_VIA_DHCP_VAR_OFFSET
) && (OffSet
< ATTEMPT_TARGET_VIA_DHCP_VAR_OFFSET
)) {
1408 AttemptIndex
= (UINT8
) ((OffSet
- ATTEMPT_INITIATOR_VIA_DHCP_VAR_OFFSET
) + 1);
1409 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1410 if (Attempt
== NULL
) {
1411 return EFI_INVALID_PARAMETER
;
1413 Attempt
->SessionConfigData
.InitiatorInfoFromDhcp
= IfrNvData
->ISCSIInitiatorInfoViaDHCP
[AttemptIndex
- 1];
1415 } else if ((OffSet
>= ATTEMPT_TARGET_VIA_DHCP_VAR_OFFSET
) && (OffSet
< ATTEMPT_TARGET_TCP_PORT_VAR_OFFSET
)) {
1416 AttemptIndex
= (UINT8
) ((OffSet
- ATTEMPT_TARGET_VIA_DHCP_VAR_OFFSET
) + 1);
1417 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1418 if (Attempt
== NULL
) {
1419 return EFI_INVALID_PARAMETER
;
1422 if ((Attempt
->SessionConfigData
.IpMode
< IP_MODE_AUTOCONFIG
) && (Attempt
->SessionConfigData
.InitiatorInfoFromDhcp
)) {
1423 Attempt
->SessionConfigData
.TargetInfoFromDhcp
= IfrNvData
->ISCSITargetInfoViaDHCP
[AttemptIndex
- 1];
1426 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1428 L
"Invalid Configuration, Check value of IpMode or Enable DHCP!",
1431 return EFI_INVALID_PARAMETER
;
1434 } else if ((OffSet
>= ATTEMPT_TARGET_TCP_PORT_VAR_OFFSET
) && (OffSet
< ATTEMPT_AUTHENTICATION_METHOD_VAR_OFFSET
)) {
1435 AttemptIndex
= (UINT8
) ((OffSet
- ATTEMPT_TARGET_TCP_PORT_VAR_OFFSET
) / 2 + 1);
1436 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1437 if (Attempt
== NULL
) {
1438 return EFI_INVALID_PARAMETER
;
1440 if ((Attempt
->SessionConfigData
.IpMode
< IP_MODE_AUTOCONFIG
) && (!Attempt
->SessionConfigData
.TargetInfoFromDhcp
)) {
1441 Attempt
->SessionConfigData
.TargetPort
= IfrNvData
->ISCSITargetTcpPort
[AttemptIndex
- 1];
1442 if (Attempt
->SessionConfigData
.TargetPort
== 0) {
1443 Attempt
->SessionConfigData
.TargetPort
= ISCSI_WELL_KNOWN_PORT
;
1447 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1449 L
"Invalid Configuration, Check value of IpMode or Target Via DHCP!",
1452 return EFI_INVALID_PARAMETER
;
1455 } else if ((OffSet
>= ATTEMPT_AUTHENTICATION_METHOD_VAR_OFFSET
) && (OffSet
< ATTEMPT_CHARTYPE_VAR_OFFSET
)) {
1456 AttemptIndex
= (UINT8
) ((OffSet
- ATTEMPT_AUTHENTICATION_METHOD_VAR_OFFSET
) + 1);
1457 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1458 if (Attempt
== NULL
) {
1459 return EFI_INVALID_PARAMETER
;
1462 Attempt
->AuthenticationType
= IfrNvData
->ISCSIAuthenticationMethod
[AttemptIndex
- 1];
1464 } else if ((OffSet
>= ATTEMPT_CHARTYPE_VAR_OFFSET
) && (OffSet
< ATTEMPT_ISID_VAR_OFFSET
)) {
1465 AttemptIndex
= (UINT8
) ((OffSet
- ATTEMPT_CHARTYPE_VAR_OFFSET
) + 1);
1466 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1467 if (Attempt
== NULL
) {
1468 return EFI_INVALID_PARAMETER
;
1470 if (Attempt
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
1471 Attempt
->AuthConfigData
.CHAP
.CHAPType
= IfrNvData
->ISCSIChapType
[AttemptIndex
- 1];
1474 } else if (OffSet
>= ATTEMPT_ISID_VAR_OFFSET
) {
1475 Index
= (UINT8
) ((OffSet
- ATTEMPT_ISID_VAR_OFFSET
) / sizeof (KEYWORD_STR
));
1476 AttemptIndex
= Index
+ 1;
1477 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1478 if (Attempt
== NULL
) {
1479 return EFI_INVALID_PARAMETER
;
1482 OffSet
= OffSet
- Index
* sizeof (KEYWORD_STR
);
1484 if ((OffSet
>= ATTEMPT_ISID_VAR_OFFSET
) && (OffSet
< ATTEMPT_INITIATOR_IP_ADDRESS_VAR_OFFSET
)) {
1485 IScsiParseIsIdFromString (IfrNvData
->Keyword
[Index
].ISCSIIsId
, Attempt
->SessionConfigData
.IsId
);
1487 } else if ((OffSet
>= ATTEMPT_INITIATOR_IP_ADDRESS_VAR_OFFSET
) && (OffSet
< ATTEMPT_INITIATOR_NET_MASK_VAR_OFFSET
)) {
1488 if ((Attempt
->SessionConfigData
.IpMode
== IP_MODE_IP4
) && (!Attempt
->SessionConfigData
.InitiatorInfoFromDhcp
)) {
1492 Status
= NetLibStrToIp4 (IfrNvData
->Keyword
[Index
].ISCSIInitiatorIpAddress
, &HostIp
.v4
);
1493 if (EFI_ERROR (Status
) || ((Attempt
->SessionConfigData
.SubnetMask
.Addr
[0] != 0) &&
1494 !NetIp4IsUnicast (NTOHL (HostIp
.Addr
[0]), NTOHL(*(UINT32
*)Attempt
->SessionConfigData
.SubnetMask
.Addr
)))) {
1496 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1498 L
"Invalid IP address!",
1501 return EFI_INVALID_PARAMETER
;
1503 CopyMem (&Attempt
->SessionConfigData
.LocalIp
, &HostIp
.v4
, sizeof (HostIp
.v4
));
1507 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1509 L
"Invalid Configuration, Check value of IpMode or Enable DHCP!",
1512 return EFI_INVALID_PARAMETER
;
1515 } else if ((OffSet
>= ATTEMPT_INITIATOR_NET_MASK_VAR_OFFSET
) && (OffSet
< ATTEMPT_INITIATOR_GATE_WAY_VAR_OFFSET
)) {
1516 if ((Attempt
->SessionConfigData
.IpMode
== IP_MODE_IP4
) && (!Attempt
->SessionConfigData
.InitiatorInfoFromDhcp
)) {
1517 Status
= NetLibStrToIp4 (IfrNvData
->Keyword
[Index
].ISCSIInitiatorNetmask
, &SubnetMask
.v4
);
1518 if (EFI_ERROR (Status
) || ((SubnetMask
.Addr
[0] != 0) && (IScsiGetSubnetMaskPrefixLength (&SubnetMask
.v4
) == 0))) {
1520 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1522 L
"Invalid Subnet Mask!",
1525 return EFI_INVALID_PARAMETER
;
1527 CopyMem (&Attempt
->SessionConfigData
.SubnetMask
, &SubnetMask
.v4
, sizeof (SubnetMask
.v4
));
1531 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1533 L
"Invalid Configuration, Check value of IpMode or Enable DHCP!",
1536 return EFI_INVALID_PARAMETER
;
1539 } else if ((OffSet
>= ATTEMPT_INITIATOR_GATE_WAY_VAR_OFFSET
) && (OffSet
< ATTEMPT_TARGET_NAME_VAR_OFFSET
)) {
1540 if ((Attempt
->SessionConfigData
.IpMode
== IP_MODE_IP4
) && (!Attempt
->SessionConfigData
.InitiatorInfoFromDhcp
)) {
1541 Status
= NetLibStrToIp4 (IfrNvData
->Keyword
[Index
].ISCSIInitiatorGateway
, &Gateway
.v4
);
1542 if (EFI_ERROR (Status
) ||
1543 ((Gateway
.Addr
[0] != 0) && (Attempt
->SessionConfigData
.SubnetMask
.Addr
[0] != 0) &&
1544 !NetIp4IsUnicast (NTOHL (Gateway
.Addr
[0]), NTOHL(*(UINT32
*)Attempt
->SessionConfigData
.SubnetMask
.Addr
)))) {
1546 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1548 L
"Invalid Gateway!",
1551 return EFI_INVALID_PARAMETER
;
1553 CopyMem (&Attempt
->SessionConfigData
.Gateway
, &Gateway
.v4
, sizeof (Gateway
.v4
));
1557 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1559 L
"Invalid Configuration, Check value of IpMode or Enable DHCP!",
1562 return EFI_INVALID_PARAMETER
;
1565 } else if ((OffSet
>= ATTEMPT_TARGET_NAME_VAR_OFFSET
) && (OffSet
< ATTEMPT_TARGET_IP_ADDRESS_VAR_OFFSET
)) {
1566 if ((Attempt
->SessionConfigData
.IpMode
< IP_MODE_AUTOCONFIG
) && (!Attempt
->SessionConfigData
.TargetInfoFromDhcp
)) {
1567 UnicodeStrToAsciiStrS (IfrNvData
->Keyword
[Index
].ISCSITargetName
, IScsiName
, ISCSI_NAME_MAX_SIZE
);
1568 Status
= IScsiNormalizeName (IScsiName
, AsciiStrLen (IScsiName
));
1569 if (EFI_ERROR (Status
)) {
1571 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1573 L
"Invalid iSCSI Name!",
1577 AsciiStrCpyS (Attempt
->SessionConfigData
.TargetName
, ISCSI_NAME_MAX_SIZE
, IScsiName
);
1579 if (Attempt
->SessionConfigData
.Enabled
!= ISCSI_DISABLED
) {
1580 if (Attempt
->SessionConfigData
.TargetName
[0] == L
'\0') {
1582 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1584 L
"iSCSI target name is NULL!",
1587 return EFI_INVALID_PARAMETER
;
1592 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1594 L
"Invalid Configuration, Check value of IpMode or Target Via DHCP!",
1597 return EFI_INVALID_PARAMETER
;
1600 } else if ((OffSet
>= ATTEMPT_TARGET_IP_ADDRESS_VAR_OFFSET
) && (OffSet
< ATTEMPT_LUN_VAR_OFFSET
)) {
1601 if ((Attempt
->SessionConfigData
.IpMode
< IP_MODE_AUTOCONFIG
) && (!Attempt
->SessionConfigData
.TargetInfoFromDhcp
)) {
1602 UnicodeStrToAsciiStrS (IfrNvData
->Keyword
[Index
].ISCSITargetIpAddress
, IpString
, sizeof (IpString
));
1603 Status
= IScsiAsciiStrToIp (IpString
, Attempt
->SessionConfigData
.IpMode
, &HostIp
);
1604 if (EFI_ERROR (Status
) || !IpIsUnicast (&HostIp
, Attempt
->SessionConfigData
.IpMode
)) {
1605 Attempt
->SessionConfigData
.DnsMode
= TRUE
;
1606 ZeroMem (&Attempt
->SessionConfigData
.TargetIp
, sizeof (Attempt
->SessionConfigData
.TargetIp
));
1607 UnicodeStrToAsciiStrS (IfrNvData
->Keyword
[Index
].ISCSITargetIpAddress
, Attempt
->SessionConfigData
.TargetUrl
, ISCSI_NAME_MAX_SIZE
);
1609 Attempt
->SessionConfigData
.DnsMode
= FALSE
;
1610 CopyMem (&Attempt
->SessionConfigData
.TargetIp
, &HostIp
, sizeof (HostIp
));
1614 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1616 L
"Invalid Configuration, Check value of IpMode or Target Via DHCP!",
1619 return EFI_INVALID_PARAMETER
;
1622 } else if ((OffSet
>= ATTEMPT_LUN_VAR_OFFSET
) && (OffSet
< ATTEMPT_CHAR_USER_NAME_VAR_OFFSET
)) {
1623 if ((Attempt
->SessionConfigData
.IpMode
< IP_MODE_AUTOCONFIG
) && (Attempt
->SessionConfigData
.TargetInfoFromDhcp
== 0)) {
1627 UnicodeStrToAsciiStrS (IfrNvData
->Keyword
[Index
].ISCSILun
, LunString
, ISCSI_LUN_STR_MAX_LEN
);
1628 Status
= IScsiAsciiStrToLun (LunString
, (UINT8
*) &Lun
);
1629 if (EFI_ERROR (Status
)) {
1631 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1633 L
"Invalid LUN string, Examples are: 4752-3A4F-6b7e-2F99, 6734-9-156f-127, 4186-9!",
1637 CopyMem (&Attempt
->SessionConfigData
.BootLun
, &Lun
, sizeof (Lun
));
1641 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1643 L
"Invalid Configuration, Check value of IpMode or Target Via DHCP!",
1646 return EFI_INVALID_PARAMETER
;
1649 } else if ((OffSet
>= ATTEMPT_CHAR_USER_NAME_VAR_OFFSET
) && (OffSet
< ATTEMPT_CHAR_SECRET_VAR_OFFSET
)) {
1650 if (Attempt
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
1651 UnicodeStrToAsciiStrS (
1652 IfrNvData
->Keyword
[Index
].ISCSIChapUsername
,
1653 Attempt
->AuthConfigData
.CHAP
.CHAPName
,
1654 ISCSI_CHAP_NAME_STORAGE
1657 if (Attempt
->SessionConfigData
.Enabled
!= ISCSI_DISABLED
) {
1658 if (IfrNvData
->Keyword
[Index
].ISCSIChapUsername
[0] == L
'\0') {
1660 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1662 L
"CHAP Name is invalid!",
1665 return EFI_INVALID_PARAMETER
;
1670 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1672 L
"Invalid Configuration, Check value of AuthenticationType!",
1675 return EFI_INVALID_PARAMETER
;
1678 } else if ((OffSet
>= ATTEMPT_CHAR_SECRET_VAR_OFFSET
) && (OffSet
< ATTEMPT_CHAR_REVERSE_USER_NAME_VAR_OFFSET
)) {
1679 if (Attempt
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
1680 ChapSecretLen
= (UINT8
)StrLen (IfrNvData
->Keyword
[Index
].ISCSIChapSecret
);
1681 UnicodeStrToAsciiStrS (
1682 IfrNvData
->Keyword
[Index
].ISCSIChapSecret
,
1683 Attempt
->AuthConfigData
.CHAP
.CHAPSecret
,
1684 ISCSI_CHAP_SECRET_STORAGE
1687 if (Attempt
->SessionConfigData
.Enabled
!= ISCSI_DISABLED
) {
1688 if ((ChapSecretLen
< ISCSI_CHAP_SECRET_MIN_LEN
) || (ChapSecretLen
> ISCSI_CHAP_SECRET_MAX_LEN
)) {
1690 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1692 L
"The Chap Secret minimum length is 12 bytes and the maximum length is 16 bytes.",
1695 return EFI_INVALID_PARAMETER
;
1700 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1702 L
"Invalid Configuration, Check value of AuthenticationType!",
1705 return EFI_INVALID_PARAMETER
;
1708 } else if ((OffSet
>= ATTEMPT_CHAR_REVERSE_USER_NAME_VAR_OFFSET
) && (OffSet
< ATTEMPT_CHAR_REVERSE_SECRET_VAR_OFFSET
)) {
1709 if (Attempt
->AuthConfigData
.CHAP
.CHAPType
== ISCSI_CHAP_MUTUAL
) {
1710 UnicodeStrToAsciiStrS (
1711 IfrNvData
->Keyword
[Index
].ISCSIReverseChapUsername
,
1712 Attempt
->AuthConfigData
.CHAP
.ReverseCHAPName
,
1713 ISCSI_CHAP_NAME_STORAGE
1715 if (Attempt
->SessionConfigData
.Enabled
!= ISCSI_DISABLED
) {
1716 if (IfrNvData
->Keyword
[Index
].ISCSIReverseChapUsername
[0] == L
'\0') {
1718 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1720 L
"Reverse CHAP Name is invalid!",
1723 return EFI_INVALID_PARAMETER
;
1728 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1730 L
"Invalid Configuration, Check value of AuthenticationType or Chap Type!",
1733 return EFI_INVALID_PARAMETER
;
1736 } else if (OffSet
>= ATTEMPT_CHAR_REVERSE_SECRET_VAR_OFFSET
) {
1737 if (Attempt
->AuthConfigData
.CHAP
.CHAPType
== ISCSI_CHAP_MUTUAL
) {
1738 ReverseChapSecretLen
= (UINT8
)StrLen (IfrNvData
->Keyword
[Index
].ISCSIReverseChapSecret
);
1739 UnicodeStrToAsciiStrS (
1740 IfrNvData
->Keyword
[Index
].ISCSIReverseChapSecret
,
1741 Attempt
->AuthConfigData
.CHAP
.ReverseCHAPSecret
,
1742 ISCSI_CHAP_SECRET_STORAGE
1745 if (Attempt
->SessionConfigData
.Enabled
!= ISCSI_DISABLED
) {
1746 if ((ReverseChapSecretLen
< ISCSI_CHAP_SECRET_MIN_LEN
) || (ReverseChapSecretLen
> ISCSI_CHAP_SECRET_MAX_LEN
)) {
1748 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1750 L
"The Reverse CHAP Secret minimum length is 12 bytes and the maximum length is 16 bytes.",
1753 return EFI_INVALID_PARAMETER
;
1758 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1760 L
"Invalid Configuration, Check value of AuthenticationType or Chap Type!",
1763 return EFI_INVALID_PARAMETER
;
1771 // Record the user configuration information in NVR.
1773 ASSERT (Attempt
!= NULL
);
1774 UnicodeSPrint (mPrivate
->PortString
, (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
, L
"Attempt %d", Attempt
->AttemptConfigIndex
);
1775 return gRT
->SetVariable (
1776 mPrivate
->PortString
,
1777 &gEfiIScsiInitiatorNameProtocolGuid
,
1778 ISCSI_CONFIG_VAR_ATTR
,
1779 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA
),
1786 Create Hii Extend Label OpCode as the start opcode and end opcode. It is
1789 @param[in] StartLabelNumber The number of start label.
1790 @param[out] StartOpCodeHandle Points to the start opcode handle.
1791 @param[out] StartLabel Points to the created start opcode.
1792 @param[out] EndOpCodeHandle Points to the end opcode handle.
1793 @param[out] EndLabel Points to the created end opcode.
1795 @retval EFI_OUT_OF_RESOURCES Do not have sufficient resource to finish this
1797 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
1798 @retval EFI_SUCCESS The operation is completed successfully.
1803 IN UINT16 StartLabelNumber
,
1804 OUT VOID
**StartOpCodeHandle
,
1805 OUT EFI_IFR_GUID_LABEL
**StartLabel
,
1806 OUT VOID
**EndOpCodeHandle
,
1807 OUT EFI_IFR_GUID_LABEL
**EndLabel
1811 EFI_IFR_GUID_LABEL
*InternalStartLabel
;
1812 EFI_IFR_GUID_LABEL
*InternalEndLabel
;
1814 if (StartOpCodeHandle
== NULL
|| StartLabel
== NULL
|| EndOpCodeHandle
== NULL
|| EndLabel
== NULL
) {
1815 return EFI_INVALID_PARAMETER
;
1818 *StartOpCodeHandle
= NULL
;
1819 *EndOpCodeHandle
= NULL
;
1820 Status
= EFI_OUT_OF_RESOURCES
;
1823 // Initialize the container for dynamic opcodes.
1825 *StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
1826 if (*StartOpCodeHandle
== NULL
) {
1830 *EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
1831 if (*EndOpCodeHandle
== NULL
) {
1836 // Create Hii Extend Label OpCode as the start opcode.
1838 InternalStartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
1842 sizeof (EFI_IFR_GUID_LABEL
)
1844 if (InternalStartLabel
== NULL
) {
1848 InternalStartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
1849 InternalStartLabel
->Number
= StartLabelNumber
;
1852 // Create Hii Extend Label OpCode as the end opcode.
1854 InternalEndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
1858 sizeof (EFI_IFR_GUID_LABEL
)
1860 if (InternalEndLabel
== NULL
) {
1864 InternalEndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
1865 InternalEndLabel
->Number
= LABEL_END
;
1867 *StartLabel
= InternalStartLabel
;
1868 *EndLabel
= InternalEndLabel
;
1874 if (*StartOpCodeHandle
!= NULL
) {
1875 HiiFreeOpCodeHandle (*StartOpCodeHandle
);
1878 if (*EndOpCodeHandle
!= NULL
) {
1879 HiiFreeOpCodeHandle (*EndOpCodeHandle
);
1885 Update the MAIN form to display the configured attempts.
1889 IScsiConfigUpdateAttempt (
1894 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
1895 VOID
*StartOpCodeHandle
;
1896 EFI_IFR_GUID_LABEL
*StartLabel
;
1897 VOID
*EndOpCodeHandle
;
1898 EFI_IFR_GUID_LABEL
*EndLabel
;
1901 Status
= IScsiCreateOpCode (
1902 ATTEMPT_ENTRY_LABEL
,
1908 if (EFI_ERROR (Status
)) {
1912 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
1913 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
1914 if (AttemptConfigData
->Actived
== ISCSI_ACTIVE_ENABLED
) {
1916 // Update Attempt Help Info.
1918 UnicodeSPrint (mPrivate
->PortString
, (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
, L
"Attempt %d", (UINTN
) AttemptConfigData
->AttemptConfigIndex
);
1919 AttemptConfigData
->AttemptTitleToken
= HiiSetString (
1920 mCallbackInfo
->RegisteredHandle
,
1922 mPrivate
->PortString
,
1925 if (AttemptConfigData
->AttemptTitleToken
== 0) {
1929 HiiCreateGotoOpCode (
1930 StartOpCodeHandle
, // Container for dynamic created opcodes
1931 FORMID_ATTEMPT_FORM
, // Form ID
1932 AttemptConfigData
->AttemptTitleToken
, // Prompt text
1933 AttemptConfigData
->AttemptTitleHelpToken
, // Help text
1934 EFI_IFR_FLAG_CALLBACK
, // Question flag
1935 (UINT16
) (KEY_ATTEMPT_ENTRY_BASE
+ AttemptConfigData
->AttemptConfigIndex
) // Question ID
1941 mCallbackInfo
->RegisteredHandle
, // HII handle
1942 &gIScsiConfigGuid
, // Formset GUID
1943 FORMID_MAIN_FORM
, // Form ID
1944 StartOpCodeHandle
, // Label for where to insert opcodes
1945 EndOpCodeHandle
// Replace data
1948 HiiFreeOpCodeHandle (StartOpCodeHandle
);
1949 HiiFreeOpCodeHandle (EndOpCodeHandle
);
1953 Callback function when user presses "Add an Attempt".
1955 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
1957 @retval EFI_SUCCESS The operation is completed successfully.
1961 IScsiConfigAddAttempt (
1966 ISCSI_NIC_INFO
*NicInfo
;
1967 EFI_STRING_ID PortTitleToken
;
1968 EFI_STRING_ID PortTitleHelpToken
;
1969 CHAR16 MacString
[ISCSI_MAX_MAC_STRING_LEN
];
1971 VOID
*StartOpCodeHandle
;
1972 EFI_IFR_GUID_LABEL
*StartLabel
;
1973 VOID
*EndOpCodeHandle
;
1974 EFI_IFR_GUID_LABEL
*EndLabel
;
1976 Status
= IScsiCreateOpCode (
1983 if (EFI_ERROR (Status
)) {
1988 // Ask user to select a MAC for this attempt.
1990 NET_LIST_FOR_EACH (Entry
, &mPrivate
->NicInfoList
) {
1991 NicInfo
= NET_LIST_USER_STRUCT (Entry
, ISCSI_NIC_INFO
, Link
);
1993 &NicInfo
->PermanentAddress
,
1994 NicInfo
->HwAddressSize
,
1999 UnicodeSPrint (mPrivate
->PortString
, (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
, L
"MAC %s", MacString
);
2000 PortTitleToken
= HiiSetString (
2001 mCallbackInfo
->RegisteredHandle
,
2003 mPrivate
->PortString
,
2006 if (PortTitleToken
== 0) {
2007 Status
= EFI_INVALID_PARAMETER
;
2012 mPrivate
->PortString
,
2013 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
2014 L
"PFA: Bus %d | Dev %d | Func %d",
2016 NicInfo
->DeviceNumber
,
2017 NicInfo
->FunctionNumber
2019 PortTitleHelpToken
= HiiSetString (mCallbackInfo
->RegisteredHandle
, 0, mPrivate
->PortString
, NULL
);
2020 if (PortTitleHelpToken
== 0) {
2021 Status
= EFI_INVALID_PARAMETER
;
2025 HiiCreateGotoOpCode (
2026 StartOpCodeHandle
, // Container for dynamic created opcodes
2027 FORMID_ATTEMPT_FORM
,
2030 EFI_IFR_FLAG_CALLBACK
, // Question flag
2031 (UINT16
) (KEY_MAC_ENTRY_BASE
+ NicInfo
->NicIndex
)
2035 Status
= HiiUpdateForm (
2036 mCallbackInfo
->RegisteredHandle
, // HII handle
2037 &gIScsiConfigGuid
, // Formset GUID
2038 FORMID_MAC_FORM
, // Form ID
2039 StartOpCodeHandle
, // Label for where to insert opcodes
2040 EndOpCodeHandle
// Replace data
2044 HiiFreeOpCodeHandle (StartOpCodeHandle
);
2045 HiiFreeOpCodeHandle (EndOpCodeHandle
);
2051 Add the attempts by keyword 'iSCSIAddAttempts', you can use this keyword with
2052 value 'attempt:1 attempt:2' etc to add one or more attempts once. This is different
2053 with IScsiConfigAddAttempt function which is used to add attempt by UI configuration.
2055 @param[in] AttemptList The new attempt List will be added.
2057 @retval EFI_SUCCESS The operation to add attempt list successfully.
2058 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
2059 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
2060 @retval EFI_OUT_OF_RESOURCES Fail to finish the operation due to lack of
2065 IScsiConfigAddAttemptsByKeywords (
2066 IN UINT8
*AttemptList
2073 UINT8
*AttemptConfigOrder
;
2074 UINTN AttemptConfigOrderSize
;
2075 UINT8
*AttemptConfigOrderTmp
;
2076 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
2077 ISCSI_NIC_INFO
*NicInfo
;
2078 CHAR16 MacString
[ISCSI_MAX_MAC_STRING_LEN
];
2079 CHAR16 IScsiMode
[64];
2083 Nic
= mPrivate
->CurrentNic
;
2084 NicInfo
= IScsiGetNicInfoByIndex (Nic
);
2085 if (NicInfo
== NULL
) {
2086 return EFI_NOT_FOUND
;
2090 // The MAC info will be recorded in Config Data.
2093 &NicInfo
->PermanentAddress
,
2094 NicInfo
->HwAddressSize
,
2099 for (Index
= 0; Index
< PcdGet8 (PcdMaxIScsiAttemptNumber
); Index
++) {
2100 if (AttemptList
[Index
] == 0) {
2107 Number
= AttemptList
[Index
];
2110 mPrivate
->PortString
,
2111 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
2117 mPrivate
->PortString
,
2118 &gEfiIScsiInitiatorNameProtocolGuid
,
2119 (VOID
**)&AttemptConfigData
,
2122 if (AttemptConfigData
== NULL
|| AttemptConfigData
->Actived
== ISCSI_ACTIVE_ENABLED
) {
2123 return EFI_INVALID_PARAMETER
;
2126 AttemptConfigData
->Actived
= ISCSI_ACTIVE_ENABLED
;
2127 AttemptConfigData
->NicIndex
= NicInfo
->NicIndex
;
2128 UnicodeStrToAsciiStrS (MacString
, AttemptConfigData
->MacString
, ISCSI_MAX_MAC_STRING_LEN
);
2131 // Generate OUI-format ISID based on MAC address.
2133 CopyMem (AttemptConfigData
->SessionConfigData
.IsId
, &NicInfo
->PermanentAddress
, 6);
2134 AttemptConfigData
->SessionConfigData
.IsId
[0] =
2135 (UINT8
) (AttemptConfigData
->SessionConfigData
.IsId
[0] & 0x3F);
2138 // Configure the iSCSI Mode and IpMode to default.
2139 // Add Attempt Help Info.
2141 UnicodeSPrint (IScsiMode
, 64, L
"Disabled");
2142 UnicodeSPrint (IpMode
, 64, L
"IP4");
2144 mPrivate
->PortString
,
2145 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
2146 L
"MAC: %s, PFA: Bus %d | Dev %d | Func %d, iSCSI mode: %s, IP version: %s",
2149 NicInfo
->DeviceNumber
,
2150 NicInfo
->FunctionNumber
,
2155 AttemptConfigData
->AttemptTitleHelpToken
= HiiSetString (
2156 mCallbackInfo
->RegisteredHandle
,
2158 mPrivate
->PortString
,
2161 if (AttemptConfigData
->AttemptTitleHelpToken
== 0) {
2162 return EFI_OUT_OF_RESOURCES
;
2166 // Get current Attempt order and number.
2168 AttemptConfigOrder
= IScsiGetVariableAndSize (
2171 &AttemptConfigOrderSize
2173 TotalNumber
= AttemptConfigOrderSize
/ sizeof (UINT8
);
2177 // Append the new created attempt order to the end.
2179 AttemptConfigOrderTmp
= AllocateZeroPool (TotalNumber
* sizeof (UINT8
));
2180 if (AttemptConfigOrderTmp
== NULL
) {
2181 if (AttemptConfigOrder
!= NULL
) {
2182 FreePool (AttemptConfigOrder
);
2184 return EFI_OUT_OF_RESOURCES
;
2186 if (AttemptConfigOrder
!= NULL
) {
2187 CopyMem (AttemptConfigOrderTmp
, AttemptConfigOrder
, AttemptConfigOrderSize
);
2188 FreePool (AttemptConfigOrder
);
2191 AttemptConfigOrderTmp
[TotalNumber
- 1] = Number
;
2192 AttemptConfigOrder
= AttemptConfigOrderTmp
;
2193 AttemptConfigOrderSize
= TotalNumber
* sizeof (UINT8
);
2195 Status
= gRT
->SetVariable (
2198 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
2199 AttemptConfigOrderSize
,
2202 FreePool (AttemptConfigOrder
);
2203 if (EFI_ERROR (Status
)) {
2208 // Record the attempt in global link list.
2210 InsertTailList (&mPrivate
->AttemptConfigs
, &AttemptConfigData
->Link
);
2211 mPrivate
->AttemptCount
++;
2212 UnicodeSPrint (mPrivate
->PortString
, (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
, L
"Attempt %d", AttemptConfigData
->AttemptConfigIndex
);
2214 mPrivate
->PortString
,
2215 &gEfiIScsiInitiatorNameProtocolGuid
,
2216 ISCSI_CONFIG_VAR_ATTR
,
2217 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA
),
2227 Callback function when user presses "Commit Changes and Exit" in Delete Attempts or Delete Attempts by Keyword.
2229 @param[in] IfrNvData The IFR NV data.
2231 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
2232 @retval EFI_SUCCESS The operation is completed successfully.
2233 @retval EFI_ABOTRED This operation is aborted cause of error
2235 @retval EFI_OUT_OF_RESOURCES Fail to finish the operation due to lack of
2240 IScsiConfigDeleteAttempts (
2241 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
2247 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
2248 UINT8
*AttemptConfigOrder
;
2249 UINTN AttemptConfigOrderSize
;
2250 UINT8
*AttemptNewOrder
;
2251 UINT8 AttemptConfigIndex
;
2256 LIST_ENTRY
*NextEntry
;
2257 ISCSI_SESSION_CONFIG_NVDATA
*ConfigData
;
2261 AttemptConfigOrder
= IScsiGetVariableAndSize (
2264 &AttemptConfigOrderSize
2266 if ((AttemptConfigOrder
== NULL
) || (AttemptConfigOrderSize
== 0)) {
2267 return EFI_NOT_FOUND
;
2270 AttemptNewOrder
= AllocateZeroPool (AttemptConfigOrderSize
);
2271 if (AttemptNewOrder
== NULL
) {
2272 Status
= EFI_OUT_OF_RESOURCES
;
2276 Total
= AttemptConfigOrderSize
/ sizeof (UINT8
);
2279 NET_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &mPrivate
->AttemptConfigs
) {
2280 if (IfrNvData
->DeleteAttemptList
[Index
] == 0) {
2286 // Delete the attempt.
2289 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
2290 if (AttemptConfigData
== NULL
) {
2291 Status
= EFI_NOT_FOUND
;
2296 // Remove this attempt from UI configured attempt list.
2298 RemoveEntryList (&AttemptConfigData
->Link
);
2299 mPrivate
->AttemptCount
--;
2301 if (AttemptConfigData
->SessionConfigData
.Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
2302 if (mPrivate
->MpioCount
< 1) {
2303 Status
= EFI_ABORTED
;
2308 // No more attempt is enabled for MPIO. Transit the iSCSI mode to single path.
2310 if (--mPrivate
->MpioCount
== 0) {
2311 mPrivate
->EnableMpio
= FALSE
;
2313 } else if (AttemptConfigData
->SessionConfigData
.Enabled
== ISCSI_ENABLED
) {
2314 if (mPrivate
->SinglePathCount
< 1) {
2315 Status
= EFI_ABORTED
;
2319 mPrivate
->SinglePathCount
--;
2322 AttemptConfigIndex
= AttemptConfigData
->AttemptConfigIndex
;
2323 FreePool (AttemptConfigData
);
2326 // Create a new Attempt
2328 AttemptConfigData
= AllocateZeroPool (sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA
));
2329 if (AttemptConfigData
== NULL
) {
2330 return EFI_OUT_OF_RESOURCES
;
2332 ConfigData
= &AttemptConfigData
->SessionConfigData
;
2333 ConfigData
->TargetPort
= ISCSI_WELL_KNOWN_PORT
;
2334 ConfigData
->ConnectTimeout
= CONNECT_DEFAULT_TIMEOUT
;
2335 ConfigData
->ConnectRetryCount
= CONNECT_MIN_RETRY
;
2337 AttemptConfigData
->AuthenticationType
= ISCSI_AUTH_TYPE_CHAP
;
2338 AttemptConfigData
->AuthConfigData
.CHAP
.CHAPType
= ISCSI_CHAP_UNI
;
2340 // Configure the Attempt index and set variable.
2342 AttemptConfigData
->AttemptConfigIndex
= AttemptConfigIndex
;
2345 // Set the attempt name to default.
2348 mPrivate
->PortString
,
2349 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
2351 (UINTN
) AttemptConfigData
->AttemptConfigIndex
2353 UnicodeStrToAsciiStrS (mPrivate
->PortString
, AttemptConfigData
->AttemptName
, ATTEMPT_NAME_SIZE
);
2355 mPrivate
->PortString
,
2356 &gEfiIScsiInitiatorNameProtocolGuid
,
2357 ISCSI_CONFIG_VAR_ATTR
,
2358 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA
),
2363 // Mark the attempt order in NVR to be deleted - 0.
2365 for (NewIndex
= 0; NewIndex
< Total
; NewIndex
++) {
2366 if (AttemptConfigOrder
[NewIndex
] == AttemptConfigData
->AttemptConfigIndex
) {
2367 AttemptConfigOrder
[NewIndex
] = 0;
2373 if (mCallbackInfo
->Current
== AttemptConfigData
) {
2374 mCallbackInfo
->Current
= NULL
;
2376 FreePool (AttemptConfigData
);
2379 // Check next Attempt.
2385 // Construct AttemptNewOrder.
2387 for (Index
= 0, NewIndex
= 0; Index
< Total
; Index
++) {
2388 if (AttemptConfigOrder
[Index
] != 0) {
2389 AttemptNewOrder
[NewIndex
] = AttemptConfigOrder
[Index
];
2394 Attribute
= EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_NON_VOLATILE
;
2397 // Update AttemptOrder in NVR.
2399 Status
= gRT
->SetVariable (
2403 NewTotal
* sizeof (UINT8
),
2408 if (AttemptConfigOrder
!= NULL
) {
2409 FreePool (AttemptConfigOrder
);
2412 if (AttemptNewOrder
!= NULL
) {
2413 FreePool (AttemptNewOrder
);
2421 Callback function when user presses "Delete Attempts".
2423 @param[in] IfrNvData The IFR nv data.
2425 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
2426 @retval EFI_BUFFER_TOO_SMALL The buffer in UpdateData is too small.
2427 @retval EFI_SUCCESS The operation is completed successfully.
2431 IScsiConfigDisplayDeleteAttempts (
2432 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
2436 UINT8
*AttemptConfigOrder
;
2437 UINTN AttemptConfigOrderSize
;
2439 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
2441 VOID
*StartOpCodeHandle
;
2442 EFI_IFR_GUID_LABEL
*StartLabel
;
2443 VOID
*EndOpCodeHandle
;
2444 EFI_IFR_GUID_LABEL
*EndLabel
;
2447 Status
= IScsiCreateOpCode (
2454 if (EFI_ERROR (Status
)) {
2458 AttemptConfigOrder
= IScsiGetVariableAndSize (
2461 &AttemptConfigOrderSize
2463 if (AttemptConfigOrder
!= NULL
) {
2465 // Create the check box opcode to be deleted.
2469 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
2470 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
2471 IfrNvData
->DeleteAttemptList
[Index
] = 0x00;
2473 HiiCreateCheckBoxOpCode(
2475 (EFI_QUESTION_ID
) (ATTEMPT_DEL_QUESTION_ID
+ Index
),
2476 CONFIGURATION_VARSTORE_ID
,
2477 (UINT16
) (ATTEMPT_DEL_VAR_OFFSET
+ Index
),
2478 AttemptConfigData
->AttemptTitleToken
,
2479 AttemptConfigData
->AttemptTitleHelpToken
,
2487 if (Index
== ISCSI_MAX_ATTEMPTS_NUM
) {
2492 FreePool (AttemptConfigOrder
);
2495 Status
= HiiUpdateForm (
2496 mCallbackInfo
->RegisteredHandle
, // HII handle
2497 &gIScsiConfigGuid
, // Formset GUID
2498 FORMID_DELETE_FORM
, // Form ID
2499 StartOpCodeHandle
, // Label for where to insert opcodes
2500 EndOpCodeHandle
// Replace data
2503 HiiFreeOpCodeHandle (StartOpCodeHandle
);
2504 HiiFreeOpCodeHandle (EndOpCodeHandle
);
2511 Callback function when user presses "Change Attempt Order".
2513 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
2514 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
2516 @retval EFI_SUCCESS The operation is completed successfully.
2520 IScsiConfigDisplayOrderAttempts (
2527 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
2528 VOID
*StartOpCodeHandle
;
2529 EFI_IFR_GUID_LABEL
*StartLabel
;
2530 VOID
*EndOpCodeHandle
;
2531 EFI_IFR_GUID_LABEL
*EndLabel
;
2532 VOID
*OptionsOpCodeHandle
;
2534 Status
= IScsiCreateOpCode (
2541 if (EFI_ERROR (Status
)) {
2544 ASSERT (StartOpCodeHandle
!= NULL
);
2546 OptionsOpCodeHandle
= NULL
;
2549 // If no attempt to be ordered, update the original form and exit.
2551 if (mPrivate
->AttemptCount
== 0) {
2556 // Create Option OpCode.
2558 OptionsOpCodeHandle
= HiiAllocateOpCodeHandle ();
2559 if (OptionsOpCodeHandle
== NULL
) {
2560 Status
= EFI_OUT_OF_RESOURCES
;
2566 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
2567 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
2568 HiiCreateOneOfOptionOpCode (
2569 OptionsOpCodeHandle
,
2570 AttemptConfigData
->AttemptTitleToken
,
2572 EFI_IFR_NUMERIC_SIZE_1
,
2573 AttemptConfigData
->AttemptConfigIndex
2578 ASSERT (Index
== mPrivate
->AttemptCount
);
2580 HiiCreateOrderedListOpCode (
2581 StartOpCodeHandle
, // Container for dynamic created opcodes
2582 DYNAMIC_ORDERED_LIST_QUESTION_ID
, // Question ID
2583 CONFIGURATION_VARSTORE_ID
, // VarStore ID
2584 DYNAMIC_ORDERED_LIST_VAR_OFFSET
, // Offset in Buffer Storage
2585 STRING_TOKEN (STR_ORDER_ATTEMPT_ENTRY
), // Question prompt text
2586 STRING_TOKEN (STR_ORDER_ATTEMPT_ENTRY
), // Question help text
2588 EFI_IFR_UNIQUE_SET
, // Ordered list flag, e.g. EFI_IFR_UNIQUE_SET
2589 EFI_IFR_NUMERIC_SIZE_1
, // Data type of Question value
2590 ISCSI_MAX_ATTEMPTS_NUM
, // Maximum container
2591 OptionsOpCodeHandle
, // Option Opcode list
2592 NULL
// Default Opcode is NULL
2596 Status
= HiiUpdateForm (
2597 mCallbackInfo
->RegisteredHandle
, // HII handle
2598 &gIScsiConfigGuid
, // Formset GUID
2599 FORMID_ORDER_FORM
, // Form ID
2600 StartOpCodeHandle
, // Label for where to insert opcodes
2601 EndOpCodeHandle
// Replace data
2605 HiiFreeOpCodeHandle (StartOpCodeHandle
);
2606 HiiFreeOpCodeHandle (EndOpCodeHandle
);
2607 if (OptionsOpCodeHandle
!= NULL
) {
2608 HiiFreeOpCodeHandle (OptionsOpCodeHandle
);
2615 Callback function when user presses "Commit Changes and Exit" in Change Attempt Order or Change Attempt Order by Keyword.
2617 @param[in] IfrNvData The IFR nv data.
2619 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
2621 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
2622 @retval EFI_SUCCESS The operation is completed successfully.
2626 IScsiConfigOrderAttempts (
2627 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
2633 UINT8 AttemptConfigIndex
;
2634 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
2635 UINT8
*AttemptConfigOrder
;
2636 UINT8
*AttemptConfigOrderTmp
;
2637 UINTN AttemptConfigOrderSize
;
2639 AttemptConfigOrder
= IScsiGetVariableAndSize (
2642 &AttemptConfigOrderSize
2644 if (AttemptConfigOrder
== NULL
) {
2645 return EFI_NOT_FOUND
;
2648 AttemptConfigOrderTmp
= AllocateZeroPool (AttemptConfigOrderSize
);
2649 if (AttemptConfigOrderTmp
== NULL
) {
2650 Status
= EFI_OUT_OF_RESOURCES
;
2654 for (Index
= 0; Index
< ISCSI_MAX_ATTEMPTS_NUM
; Index
++) {
2656 // The real content ends with 0.
2658 if (IfrNvData
->DynamicOrderedList
[Index
] == 0) {
2662 AttemptConfigIndex
= IfrNvData
->DynamicOrderedList
[Index
];
2663 AttemptConfigData
= IScsiConfigGetAttemptByConfigIndex (AttemptConfigIndex
);
2664 if (AttemptConfigData
== NULL
) {
2665 Status
= EFI_NOT_FOUND
;
2670 // Reorder the Attempt List.
2672 RemoveEntryList (&AttemptConfigData
->Link
);
2673 InsertTailList (&mPrivate
->AttemptConfigs
, &AttemptConfigData
->Link
);
2675 AttemptConfigOrderTmp
[Index
] = AttemptConfigIndex
;
2678 // Mark it to be deleted - 0.
2680 for (Indexj
= 0; Indexj
< AttemptConfigOrderSize
/ sizeof (UINT8
); Indexj
++) {
2681 if (AttemptConfigOrder
[Indexj
] == AttemptConfigIndex
) {
2682 AttemptConfigOrder
[Indexj
] = 0;
2689 // Adjust the attempt order in NVR.
2691 for (; Index
< AttemptConfigOrderSize
/ sizeof (UINT8
); Index
++) {
2692 for (Indexj
= 0; Indexj
< AttemptConfigOrderSize
/ sizeof (UINT8
); Indexj
++) {
2693 if (AttemptConfigOrder
[Indexj
] != 0) {
2694 AttemptConfigOrderTmp
[Index
] = AttemptConfigOrder
[Indexj
];
2695 AttemptConfigOrder
[Indexj
] = 0;
2701 Status
= gRT
->SetVariable (
2704 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
2705 AttemptConfigOrderSize
,
2706 AttemptConfigOrderTmp
2710 if (AttemptConfigOrderTmp
!= NULL
) {
2711 FreePool (AttemptConfigOrderTmp
);
2714 FreePool (AttemptConfigOrder
);
2720 Callback function when a user presses "Attempt *" or when a user selects a NIC to
2721 create the new attempt.
2723 @param[in] KeyValue A unique value which is sent to the original
2724 exporting driver so that it can identify the type
2726 @param[in] IfrNvData The IFR nv data.
2728 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
2730 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
2731 @retval EFI_UNSUPPORTED Can not create more attempts.
2732 @retval EFI_SUCCESS The operation is completed successfully.
2736 IScsiConfigProcessDefault (
2737 IN EFI_QUESTION_ID KeyValue
,
2738 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
2742 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
2743 UINT8 CurrentAttemptConfigIndex
;
2744 ISCSI_NIC_INFO
*NicInfo
;
2746 CHAR16 MacString
[ISCSI_MAX_MAC_STRING_LEN
];
2747 UINT8
*AttemptConfigOrder
;
2748 UINTN AttemptConfigOrderSize
;
2752 AttemptConfigData
= NULL
;
2754 // Is User creating a new attempt?
2758 if ((KeyValue
>= KEY_MAC_ENTRY_BASE
) &&
2759 (KeyValue
<= (UINT16
) (mPrivate
->MaxNic
+ KEY_MAC_ENTRY_BASE
))) {
2761 // User has pressed "Add an Attempt" and then selects a NIC.
2764 } else if ((KeyValue
>= KEY_ATTEMPT_ENTRY_BASE
) &&
2765 (KeyValue
< (ISCSI_MAX_ATTEMPTS_NUM
+ KEY_ATTEMPT_ENTRY_BASE
))) {
2768 // User has pressed "Attempt *".
2773 // Don't process anything.
2780 // Determine which NIC user has selected for the new created attempt.
2782 NicIndex
= (UINT8
) (KeyValue
- KEY_MAC_ENTRY_BASE
);
2783 NicInfo
= IScsiGetNicInfoByIndex (NicIndex
);
2784 if (NicInfo
== NULL
) {
2785 return EFI_NOT_FOUND
;
2789 // Create an attempt following the initialized attempt order.
2791 AttemptConfigOrder
= IScsiGetVariableAndSize (
2792 L
"InitialAttemptOrder",
2794 &AttemptConfigOrderSize
2797 if (AttemptConfigOrder
== NULL
) {
2798 return EFI_NOT_FOUND
;
2801 for (Index
= 0; Index
< AttemptConfigOrderSize
/ sizeof (UINT8
); Index
++) {
2803 mPrivate
->PortString
,
2804 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
2806 (UINTN
) AttemptConfigOrder
[Index
]
2809 mPrivate
->PortString
,
2810 &gEfiIScsiInitiatorNameProtocolGuid
,
2811 (VOID
**)&AttemptConfigData
,
2814 if (AttemptConfigData
== NULL
|| AttemptConfigData
->Actived
== ISCSI_ACTIVE_ENABLED
) {
2821 if (Index
> PcdGet8 (PcdMaxIScsiAttemptNumber
)) {
2823 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2825 L
"Can not create more attempts, Please configure the PcdMaxIScsiAttemptNumber if needed!",
2828 return EFI_UNSUPPORTED
;
2831 if (AttemptConfigOrder
!= NULL
) {
2832 FreePool (AttemptConfigOrder
);
2836 // Record the MAC info in Config Data.
2839 &NicInfo
->PermanentAddress
,
2840 NicInfo
->HwAddressSize
,
2845 ASSERT (AttemptConfigData
!= NULL
);
2846 UnicodeStrToAsciiStrS (MacString
, AttemptConfigData
->MacString
, sizeof (AttemptConfigData
->MacString
));
2847 AttemptConfigData
->NicIndex
= NicIndex
;
2848 AttemptConfigData
->Actived
= ISCSI_ACTIVE_ENABLED
;
2851 // Generate OUI-format ISID based on MAC address.
2853 CopyMem (AttemptConfigData
->SessionConfigData
.IsId
, &NicInfo
->PermanentAddress
, 6);
2854 AttemptConfigData
->SessionConfigData
.IsId
[0] =
2855 (UINT8
) (AttemptConfigData
->SessionConfigData
.IsId
[0] & 0x3F);
2858 // Add the help info for the new attempt.
2861 mPrivate
->PortString
,
2862 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
2863 L
"MAC: %s, PFA: Bus %d | Dev %d | Func %d",
2866 NicInfo
->DeviceNumber
,
2867 NicInfo
->FunctionNumber
2870 AttemptConfigData
->AttemptTitleHelpToken
= HiiSetString (
2871 mCallbackInfo
->RegisteredHandle
,
2873 mPrivate
->PortString
,
2876 if (AttemptConfigData
->AttemptTitleHelpToken
== 0) {
2877 FreePool (AttemptConfigData
);
2878 return EFI_OUT_OF_RESOURCES
;
2883 // Determine which Attempt user has selected to configure.
2884 // Get the attempt configuration data.
2886 CurrentAttemptConfigIndex
= (UINT8
) (KeyValue
- KEY_ATTEMPT_ENTRY_BASE
);
2888 AttemptConfigData
= IScsiConfigGetAttemptByConfigIndex (CurrentAttemptConfigIndex
);
2889 if (AttemptConfigData
== NULL
) {
2890 DEBUG ((DEBUG_ERROR
, "Corresponding configuration data can not be retrieved!\n"));
2891 return EFI_NOT_FOUND
;
2896 // Clear the old IFR data to avoid sharing it with other attempts.
2898 if (IfrNvData
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
2899 ZeroMem (IfrNvData
->CHAPName
, sizeof (IfrNvData
->CHAPName
));
2900 ZeroMem (IfrNvData
->CHAPSecret
, sizeof (IfrNvData
->CHAPSecret
));
2901 ZeroMem (IfrNvData
->ReverseCHAPName
, sizeof (IfrNvData
->ReverseCHAPName
));
2902 ZeroMem (IfrNvData
->ReverseCHAPSecret
, sizeof (IfrNvData
->ReverseCHAPSecret
));
2905 IScsiConvertAttemptConfigDataToIfrNvData (AttemptConfigData
, IfrNvData
);
2908 // Update current attempt to be a new created attempt or an existing attempt.
2910 mCallbackInfo
->Current
= AttemptConfigData
;
2918 This function allows the caller to request the current
2919 configuration for one or more named elements. The resulting
2920 string is in <ConfigAltResp> format. Also, any and all alternative
2921 configuration strings shall be appended to the end of the
2922 current configuration string. If they are, they must appear
2923 after the current configuration. They must contain the same
2924 routing (GUID, NAME, PATH) as the current configuration string.
2925 They must have an additional description indicating the type of
2926 alternative configuration the string represents,
2927 "ALTCFG=<StringToken>". That <StringToken> (when
2928 converted from Hex UNICODE to binary) is a reference to a
2929 string in the associated string pack.
2931 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
2933 @param[in] Request A null-terminated Unicode string in
2934 <ConfigRequest> format. Note that this
2935 includes the routing information as well as
2936 the configurable name / value pairs. It is
2937 invalid for this string to be in
2938 <MultiConfigRequest> format.
2940 @param[out] Progress On return, points to a character in the
2941 Request string. Points to the string's null
2942 terminator if request was successful. Points
2943 to the most recent "&" before the first
2944 failing name / value pair (or the beginning
2945 of the string if the failure is in the first
2946 name / value pair) if the request was not successful.
2948 @param[out] Results A null-terminated Unicode string in
2949 <ConfigAltResp> format which has all values
2950 filled in for the names in the Request string.
2951 String to be allocated by the called function.
2953 @retval EFI_SUCCESS The Results string is filled with the
2954 values corresponding to all requested
2957 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
2958 parts of the results that must be
2959 stored awaiting possible future
2962 @retval EFI_INVALID_PARAMETER For example, passing in a NULL
2963 for the Request parameter
2964 would result in this type of
2965 error. In this case, the
2966 Progress parameter would be
2969 @retval EFI_NOT_FOUND Routing data doesn't match any
2970 known driver. Progress set to the
2971 first character in the routing header.
2972 Note: There is no requirement that the
2973 driver validate the routing data. It
2974 must skip the <ConfigHdr> in order to
2977 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set
2978 to most recent "&" before the
2979 error or the beginning of the
2982 @retval EFI_INVALID_PARAMETER Unknown name. Progress points
2983 to the & before the name in
2989 IScsiFormExtractConfig (
2990 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
2991 IN CONST EFI_STRING Request
,
2992 OUT EFI_STRING
*Progress
,
2993 OUT EFI_STRING
*Results
2997 CHAR8
*InitiatorName
;
2999 ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
;
3000 ISCSI_FORM_CALLBACK_INFO
*Private
;
3001 EFI_STRING ConfigRequestHdr
;
3002 EFI_STRING ConfigRequest
;
3003 BOOLEAN AllocatedRequest
;
3006 if (This
== NULL
|| Progress
== NULL
|| Results
== NULL
) {
3007 return EFI_INVALID_PARAMETER
;
3010 *Progress
= Request
;
3011 if ((Request
!= NULL
) && !HiiIsConfigHdrMatch (Request
, &gIScsiConfigGuid
, mVendorStorageName
)) {
3012 return EFI_NOT_FOUND
;
3015 ConfigRequestHdr
= NULL
;
3016 ConfigRequest
= NULL
;
3017 AllocatedRequest
= FALSE
;
3020 Private
= ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This
);
3021 IfrNvData
= AllocateZeroPool (sizeof (ISCSI_CONFIG_IFR_NVDATA
));
3022 if (IfrNvData
== NULL
) {
3023 return EFI_OUT_OF_RESOURCES
;
3027 if (Private
->Current
!= NULL
) {
3028 IScsiConvertAttemptConfigDataToIfrNvData (Private
->Current
, IfrNvData
);
3032 // Extract all AttemptConfigData to Keyword stroage of IfrNvData.
3034 IScsiConvertAttemptConfigDataToIfrNvDataByKeyword (IfrNvData
);
3036 BufferSize
= ISCSI_NAME_MAX_SIZE
;
3037 InitiatorName
= (CHAR8
*) AllocateZeroPool (BufferSize
);
3038 if (InitiatorName
== NULL
) {
3039 FreePool (IfrNvData
);
3040 return EFI_OUT_OF_RESOURCES
;
3043 Status
= gIScsiInitiatorName
.Get (&gIScsiInitiatorName
, &BufferSize
, InitiatorName
);
3044 if (EFI_ERROR (Status
)) {
3045 IfrNvData
->InitiatorName
[0] = L
'\0';
3047 AsciiStrToUnicodeStrS (
3049 IfrNvData
->InitiatorName
,
3050 sizeof (IfrNvData
->InitiatorName
) / sizeof (IfrNvData
->InitiatorName
[0])
3055 // Convert buffer data to <ConfigResp> by helper function BlockToConfig().
3057 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
3058 ConfigRequest
= Request
;
3059 if ((Request
== NULL
) || (StrStr (Request
, L
"OFFSET") == NULL
)) {
3061 // Request has no request element, construct full request string.
3062 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
3063 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
3065 ConfigRequestHdr
= HiiConstructConfigHdr (&gIScsiConfigGuid
, mVendorStorageName
, Private
->DriverHandle
);
3066 Size
= (StrLen (ConfigRequestHdr
) + 32 + 1) * sizeof (CHAR16
);
3067 ConfigRequest
= AllocateZeroPool (Size
);
3068 if (ConfigRequest
== NULL
) {
3069 FreePool (IfrNvData
);
3070 FreePool (InitiatorName
);
3071 return EFI_OUT_OF_RESOURCES
;
3073 AllocatedRequest
= TRUE
;
3074 UnicodeSPrint (ConfigRequest
, Size
, L
"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr
, (UINT64
)BufferSize
);
3075 FreePool (ConfigRequestHdr
);
3078 Status
= gHiiConfigRouting
->BlockToConfig (
3081 (UINT8
*) IfrNvData
,
3086 FreePool (IfrNvData
);
3087 FreePool (InitiatorName
);
3090 // Free the allocated config request string.
3092 if (AllocatedRequest
) {
3093 FreePool (ConfigRequest
);
3094 ConfigRequest
= NULL
;
3097 // Set Progress string to the original request string.
3099 if (Request
== NULL
) {
3101 } else if (StrStr (Request
, L
"OFFSET") == NULL
) {
3102 *Progress
= Request
+ StrLen (Request
);
3111 This function applies changes in a driver's configuration.
3112 Input is a Configuration, which has the routing data for this
3113 driver followed by name / value configuration pairs. The driver
3114 must apply those pairs to its configurable storage. If the
3115 driver's configuration is stored in a linear block of data
3116 and the driver's name / value pairs are in <BlockConfig>
3117 format, it may use the ConfigToBlock helper function (above) to
3120 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
3122 @param[in] Configuration A null-terminated Unicode string in
3123 <ConfigString> format.
3125 @param[out] Progress A pointer to a string filled in with the
3126 offset of the most recent '&' before the
3127 first failing name / value pair (or the
3128 beginning of the string if the failure
3129 is in the first name / value pair) or
3130 the terminating NULL if all was
3133 @retval EFI_SUCCESS The results have been distributed or are
3134 awaiting distribution.
3136 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
3137 parts of the results that must be
3138 stored awaiting possible future
3141 @retval EFI_INVALID_PARAMETERS Passing in a NULL for the
3142 Results parameter would result
3143 in this type of error.
3145 @retval EFI_NOT_FOUND Target for the specified routing data
3151 IScsiFormRouteConfig (
3152 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
3153 IN CONST EFI_STRING Configuration
,
3154 OUT EFI_STRING
*Progress
3158 ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
;
3159 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
3161 LIST_ENTRY
*NextEntry
;
3162 ISCSI_NIC_INFO
*NicInfo
;
3164 CHAR16 MacString
[ISCSI_MAX_MAC_STRING_LEN
];
3165 CHAR8
*InitiatorName
;
3176 Status
= EFI_SUCCESS
;
3178 if (This
== NULL
|| Configuration
== NULL
|| Progress
== NULL
) {
3179 return EFI_INVALID_PARAMETER
;
3183 // Check routing data in <ConfigHdr>.
3184 // Note: if only one Storage is used, then this checking could be skipped.
3186 if (!HiiIsConfigHdrMatch (Configuration
, &gIScsiConfigGuid
, mVendorStorageName
)) {
3187 *Progress
= Configuration
;
3188 return EFI_NOT_FOUND
;
3191 IfrNvData
= AllocateZeroPool (sizeof (ISCSI_CONFIG_IFR_NVDATA
));
3192 if (IfrNvData
== NULL
) {
3193 return EFI_OUT_OF_RESOURCES
;
3196 BufferSize
= ISCSI_NAME_MAX_SIZE
;
3197 InitiatorName
= (CHAR8
*) AllocateZeroPool (BufferSize
);
3198 if (InitiatorName
== NULL
) {
3199 Status
= EFI_OUT_OF_RESOURCES
;
3204 // Convert <ConfigResp> to buffer data by helper function ConfigToBlock().
3206 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
3207 Status
= gHiiConfigRouting
->ConfigToBlock (
3210 (UINT8
*) IfrNvData
,
3214 if (EFI_ERROR (Status
)) {
3218 if (IfrNvData
->InitiatorName
[0] != L
'\0') {
3219 UnicodeStrToAsciiStrS (IfrNvData
->InitiatorName
, InitiatorName
, ISCSI_NAME_MAX_SIZE
);
3220 BufferSize
= AsciiStrSize (InitiatorName
);
3222 Status
= gIScsiInitiatorName
.Set (&gIScsiInitiatorName
, &BufferSize
, InitiatorName
);
3223 if (EFI_ERROR (Status
)) {
3225 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3227 L
"Invalid iSCSI Name!",
3233 Status
= IScsiGetValue (Configuration
, L
"&OFFSET=", &OffSet
);
3234 if (EFI_ERROR (Status
)) {
3238 if (OffSet
>= ATTEMPT_MAC_ADDR_VAR_OFFSET
) {
3239 Status
= gIScsiInitiatorName
.Get (&gIScsiInitiatorName
, &BufferSize
, InitiatorName
);
3240 if (EFI_ERROR (Status
)) {
3242 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3244 L
"Error: please configure iSCSI initiator name first!",
3253 if (IfrNvData
->ISCSIAddAttemptList
[0] != L
'\0') {
3254 Status
=IScsiGetAttemptIndexList (IfrNvData
->ISCSIAddAttemptList
, IfrNvData
->AddAttemptList
, TRUE
);
3255 if (EFI_ERROR (Status
)) {
3257 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3259 L
"Error: The add attempt list is invalid",
3265 Status
= IScsiConfigAddAttemptsByKeywords (IfrNvData
->AddAttemptList
);
3266 if (EFI_ERROR (Status
)) {
3270 } else if (IfrNvData
->ISCSIDeleteAttemptList
[0] != L
'\0') {
3271 AttemptList
=(UINT8
*) AllocateZeroPool ((ISCSI_MAX_ATTEMPTS_NUM
+ 1) * sizeof (UINT8
));
3272 if (AttemptList
== NULL
) {
3273 Status
= EFI_OUT_OF_RESOURCES
;
3276 Status
= IScsiGetAttemptIndexList (IfrNvData
->ISCSIDeleteAttemptList
, AttemptList
, FALSE
);
3277 if (EFI_ERROR (Status
)) {
3279 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3281 L
"Error: The delete attempt list is invalid",
3288 // Mark the attempt which will be delete in the global list.
3290 NET_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &mPrivate
->AttemptConfigs
) {
3291 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
3292 while (AttemptList
[Index
] != 0) {
3293 if (AttemptConfigData
->AttemptConfigIndex
== AttemptList
[Index
]) {
3294 IfrNvData
->DeleteAttemptList
[Index2
] = 1;
3303 Status
= IScsiConfigDeleteAttempts (IfrNvData
);
3304 if (EFI_ERROR (Status
)) {
3308 FreePool (AttemptList
);
3310 } else if (IfrNvData
->ISCSIAttemptOrder
[0] != L
'\0') {
3311 Status
= IScsiGetAttemptIndexList (IfrNvData
->ISCSIAttemptOrder
, IfrNvData
->DynamicOrderedList
, FALSE
);
3312 if (EFI_ERROR (Status
)) {
3314 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3316 L
"Error: The new attempt order list is invalid",
3322 Status
= IScsiConfigOrderAttempts (IfrNvData
);
3323 if (EFI_ERROR (Status
)) {
3327 } else if (IfrNvData
->ISCSIMacAddr
[0] != L
'\0') {
3328 NET_LIST_FOR_EACH (Entry
, &mPrivate
->NicInfoList
) {
3329 NicInfo
= NET_LIST_USER_STRUCT (Entry
, ISCSI_NIC_INFO
, Link
);
3331 &NicInfo
->PermanentAddress
,
3332 NicInfo
->HwAddressSize
,
3336 if (!StrCmp(MacString
, IfrNvData
->ISCSIMacAddr
)) {
3337 mPrivate
->CurrentNic
= NicInfo
->NicIndex
;
3342 if ((NicInfo
== NULL
) || (NicInfo
->NicIndex
== 0)) {
3343 Status
= EFI_NOT_FOUND
;
3348 Status
= IScsiConvertlfrNvDataToAttemptConfigDataByKeyword (IfrNvData
, OffSet
);
3349 if (EFI_ERROR (Status
)) {
3355 IScsiConfigUpdateAttempt ();
3358 if (InitiatorName
!= NULL
) {
3359 FreePool (InitiatorName
);
3362 if (IfrNvData
!= NULL
) {
3363 FreePool (IfrNvData
);
3371 This function is called to provide results data to the driver.
3372 This data consists of a unique key that is used to identify
3373 which data is either being passed back or being asked for.
3375 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
3376 @param[in] Action Specifies the type of action taken by the browser.
3377 @param[in] QuestionId A unique value which is sent to the original
3378 exporting driver so that it can identify the type
3379 of data to expect. The format of the data tends to
3380 vary based on the opcode that generated the callback.
3381 @param[in] Type The type of value for the question.
3382 @param[in, out] Value A pointer to the data being sent to the original
3384 @param[out] ActionRequest On return, points to the action requested by the
3387 @retval EFI_SUCCESS The callback successfully handled the action.
3388 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
3389 variable and its data.
3390 @retval EFI_DEVICE_ERROR The variable could not be saved.
3391 @retval EFI_UNSUPPORTED The specified Action is not supported by the
3397 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
3398 IN EFI_BROWSER_ACTION Action
,
3399 IN EFI_QUESTION_ID QuestionId
,
3401 IN OUT EFI_IFR_TYPE_VALUE
*Value
,
3402 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
3405 ISCSI_FORM_CALLBACK_INFO
*Private
;
3408 CHAR8 IpString
[ISCSI_NAME_MAX_SIZE
];
3409 CHAR8 LunString
[ISCSI_LUN_STR_MAX_LEN
];
3411 EFI_IP_ADDRESS HostIp
;
3412 EFI_IP_ADDRESS SubnetMask
;
3413 EFI_IP_ADDRESS Gateway
;
3414 ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
;
3415 ISCSI_CONFIG_IFR_NVDATA OldIfrNvData
;
3419 if ((Action
== EFI_BROWSER_ACTION_FORM_OPEN
) || (Action
== EFI_BROWSER_ACTION_FORM_CLOSE
)) {
3421 // Do nothing for UEFI OPEN/CLOSE Action
3426 if ((Action
!= EFI_BROWSER_ACTION_CHANGING
) && (Action
!= EFI_BROWSER_ACTION_CHANGED
)) {
3428 // All other type return unsupported.
3430 return EFI_UNSUPPORTED
;
3433 if ((Value
== NULL
) || (ActionRequest
== NULL
)) {
3434 return EFI_INVALID_PARAMETER
;
3437 Private
= ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This
);
3440 // Retrieve uncommitted data from Browser
3443 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
3444 IfrNvData
= AllocateZeroPool (BufferSize
);
3445 if (IfrNvData
== NULL
) {
3446 return EFI_OUT_OF_RESOURCES
;
3449 IScsiName
= (CHAR8
*) AllocateZeroPool (ISCSI_NAME_MAX_SIZE
);
3450 if (IScsiName
== NULL
) {
3451 FreePool (IfrNvData
);
3452 return EFI_OUT_OF_RESOURCES
;
3455 Status
= EFI_SUCCESS
;
3457 ZeroMem (&OldIfrNvData
, BufferSize
);
3459 HiiGetBrowserData (NULL
, NULL
, BufferSize
, (UINT8
*) IfrNvData
);
3461 CopyMem (&OldIfrNvData
, IfrNvData
, BufferSize
);
3463 if (Action
== EFI_BROWSER_ACTION_CHANGING
) {
3464 switch (QuestionId
) {
3465 case KEY_ADD_ATTEMPT
:
3467 // Check whether iSCSI initiator name is configured already.
3469 mPrivate
->InitiatorNameLength
= ISCSI_NAME_MAX_SIZE
;
3470 Status
= gIScsiInitiatorName
.Get (
3471 &gIScsiInitiatorName
,
3472 &mPrivate
->InitiatorNameLength
,
3473 mPrivate
->InitiatorName
3475 if (EFI_ERROR (Status
)) {
3477 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3479 L
"Error: please configure iSCSI initiator name first!",
3485 Status
= IScsiConfigAddAttempt ();
3488 case KEY_DELETE_ATTEMPT
:
3490 OldIfrNvData
.DeleteAttemptList
,
3491 IfrNvData
->DeleteAttemptList
,
3492 sizeof (IfrNvData
->DeleteAttemptList
)
3494 Status
= IScsiConfigDisplayDeleteAttempts (IfrNvData
);
3497 case KEY_ORDER_ATTEMPT_CONFIG
:
3499 // Order the attempt according to user input.
3502 OldIfrNvData
.DynamicOrderedList
,
3503 IfrNvData
->DynamicOrderedList
,
3504 sizeof (IfrNvData
->DynamicOrderedList
)
3506 IScsiConfigDisplayOrderAttempts ();
3510 Status
= IScsiConfigProcessDefault (QuestionId
, IfrNvData
);
3513 } else if (Action
== EFI_BROWSER_ACTION_CHANGED
) {
3514 switch (QuestionId
) {
3515 case KEY_INITIATOR_NAME
:
3516 UnicodeStrToAsciiStrS (IfrNvData
->InitiatorName
, IScsiName
, ISCSI_NAME_MAX_SIZE
);
3517 BufferSize
= AsciiStrSize (IScsiName
);
3519 Status
= gIScsiInitiatorName
.Set (&gIScsiInitiatorName
, &BufferSize
, IScsiName
);
3520 if (EFI_ERROR (Status
)) {
3522 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3524 L
"Invalid iSCSI Name!",
3529 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
3532 case KEY_SAVE_ATTEMPT_CONFIG
:
3533 Status
= IScsiConvertIfrNvDataToAttemptConfigData (IfrNvData
, Private
->Current
);
3534 if (EFI_ERROR (Status
)) {
3538 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT
;
3541 case KEY_SAVE_ORDER_CHANGES
:
3543 // Sync the Attempt Order to NVR.
3545 Status
= IScsiConfigOrderAttempts (IfrNvData
);
3546 if (EFI_ERROR (Status
)) {
3550 IScsiConfigUpdateAttempt ();
3551 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT
;
3554 case KEY_IGNORE_ORDER_CHANGES
:
3556 IfrNvData
->DynamicOrderedList
,
3557 OldIfrNvData
.DynamicOrderedList
,
3558 sizeof (IfrNvData
->DynamicOrderedList
)
3560 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT
;
3563 case KEY_SAVE_DELETE_ATTEMPT
:
3565 // Delete the Attempt Order from NVR
3567 Status
= IScsiConfigDeleteAttempts (IfrNvData
);
3568 if (EFI_ERROR (Status
)) {
3572 IScsiConfigUpdateAttempt ();
3573 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT
;
3576 case KEY_IGNORE_DELETE_ATTEMPT
:
3578 IfrNvData
->DeleteAttemptList
,
3579 OldIfrNvData
.DeleteAttemptList
,
3580 sizeof (IfrNvData
->DeleteAttemptList
)
3582 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT
;
3586 switch (Value
->u8
) {
3589 ZeroMem (IfrNvData
->TargetIp
, sizeof (IfrNvData
->TargetIp
));
3590 Private
->Current
->AutoConfigureMode
= 0;
3598 Status
= NetLibStrToIp4 (IfrNvData
->LocalIp
, &HostIp
.v4
);
3599 if (EFI_ERROR (Status
) ||
3600 ((Private
->Current
->SessionConfigData
.SubnetMask
.Addr
[0] != 0) &&
3601 !NetIp4IsUnicast (NTOHL (HostIp
.Addr
[0]), NTOHL(*(UINT32
*)Private
->Current
->SessionConfigData
.SubnetMask
.Addr
)))) {
3603 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3605 L
"Invalid IP address!",
3609 Status
= EFI_INVALID_PARAMETER
;
3611 CopyMem (&Private
->Current
->SessionConfigData
.LocalIp
, &HostIp
.v4
, sizeof (HostIp
.v4
));
3616 case KEY_SUBNET_MASK
:
3617 Status
= NetLibStrToIp4 (IfrNvData
->SubnetMask
, &SubnetMask
.v4
);
3618 if (EFI_ERROR (Status
) || ((SubnetMask
.Addr
[0] != 0) && (IScsiGetSubnetMaskPrefixLength (&SubnetMask
.v4
) == 0))) {
3620 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3622 L
"Invalid Subnet Mask!",
3626 Status
= EFI_INVALID_PARAMETER
;
3628 CopyMem (&Private
->Current
->SessionConfigData
.SubnetMask
, &SubnetMask
.v4
, sizeof (SubnetMask
.v4
));
3634 Status
= NetLibStrToIp4 (IfrNvData
->Gateway
, &Gateway
.v4
);
3635 if (EFI_ERROR (Status
) ||
3636 ((Gateway
.Addr
[0] != 0) &&
3637 (Private
->Current
->SessionConfigData
.SubnetMask
.Addr
[0] != 0) &&
3638 !NetIp4IsUnicast (NTOHL (Gateway
.Addr
[0]), NTOHL(*(UINT32
*)Private
->Current
->SessionConfigData
.SubnetMask
.Addr
)))) {
3640 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3642 L
"Invalid Gateway!",
3645 Status
= EFI_INVALID_PARAMETER
;
3647 CopyMem (&Private
->Current
->SessionConfigData
.Gateway
, &Gateway
.v4
, sizeof (Gateway
.v4
));
3653 UnicodeStrToAsciiStrS (IfrNvData
->TargetIp
, IpString
, sizeof (IpString
));
3654 Status
= IScsiAsciiStrToIp (IpString
, IfrNvData
->IpMode
, &HostIp
);
3655 if (EFI_ERROR (Status
) || !IpIsUnicast (&HostIp
, IfrNvData
->IpMode
)) {
3657 // The target is expressed in URL format or an invalid Ip address, just save.
3659 Private
->Current
->SessionConfigData
.DnsMode
= TRUE
;
3660 ZeroMem (&Private
->Current
->SessionConfigData
.TargetIp
, sizeof (Private
->Current
->SessionConfigData
.TargetIp
));
3661 UnicodeStrToAsciiStrS (IfrNvData
->TargetIp
, Private
->Current
->SessionConfigData
.TargetUrl
, ISCSI_NAME_MAX_SIZE
);
3663 Private
->Current
->SessionConfigData
.DnsMode
= FALSE
;
3664 CopyMem (&Private
->Current
->SessionConfigData
.TargetIp
, &HostIp
, sizeof (HostIp
));
3669 case KEY_TARGET_NAME
:
3670 UnicodeStrToAsciiStrS (IfrNvData
->TargetName
, IScsiName
, ISCSI_NAME_MAX_SIZE
);
3671 Status
= IScsiNormalizeName (IScsiName
, AsciiStrLen (IScsiName
));
3672 if (EFI_ERROR (Status
)) {
3674 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3676 L
"Invalid iSCSI Name!",
3680 AsciiStrCpyS (Private
->Current
->SessionConfigData
.TargetName
, ISCSI_NAME_MAX_SIZE
, IScsiName
);
3685 case KEY_DHCP_ENABLE
:
3686 if (IfrNvData
->InitiatorInfoFromDhcp
== 0) {
3687 IfrNvData
->TargetInfoFromDhcp
= 0;
3693 UnicodeStrToAsciiStrS (IfrNvData
->BootLun
, LunString
, sizeof (LunString
));
3694 Status
= IScsiAsciiStrToLun (LunString
, (UINT8
*) &Lun
);
3695 if (EFI_ERROR (Status
)) {
3697 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3699 L
"Invalid LUN string!",
3703 CopyMem (Private
->Current
->SessionConfigData
.BootLun
, &Lun
, sizeof (Lun
));
3709 switch (Value
->u8
) {
3710 case ISCSI_AUTH_TYPE_CHAP
:
3711 IfrNvData
->CHAPType
= ISCSI_CHAP_UNI
;
3720 UnicodeStrToAsciiStrS (
3721 IfrNvData
->CHAPName
,
3722 Private
->Current
->AuthConfigData
.CHAP
.CHAPName
,
3723 sizeof (Private
->Current
->AuthConfigData
.CHAP
.CHAPName
)
3727 case KEY_CHAP_SECRET
:
3728 UnicodeStrToAsciiStrS (
3729 IfrNvData
->CHAPSecret
,
3730 Private
->Current
->AuthConfigData
.CHAP
.CHAPSecret
,
3731 sizeof (Private
->Current
->AuthConfigData
.CHAP
.CHAPSecret
)
3735 case KEY_REVERSE_CHAP_NAME
:
3736 UnicodeStrToAsciiStrS (
3737 IfrNvData
->ReverseCHAPName
,
3738 Private
->Current
->AuthConfigData
.CHAP
.ReverseCHAPName
,
3739 sizeof (Private
->Current
->AuthConfigData
.CHAP
.ReverseCHAPName
)
3743 case KEY_REVERSE_CHAP_SECRET
:
3744 UnicodeStrToAsciiStrS (
3745 IfrNvData
->ReverseCHAPSecret
,
3746 Private
->Current
->AuthConfigData
.CHAP
.ReverseCHAPSecret
,
3747 sizeof (Private
->Current
->AuthConfigData
.CHAP
.ReverseCHAPSecret
)
3751 case KEY_CONFIG_ISID
:
3752 IScsiParseIsIdFromString (IfrNvData
->IsId
, Private
->Current
->SessionConfigData
.IsId
);
3753 IScsiConvertIsIdToString (IfrNvData
->IsId
, Private
->Current
->SessionConfigData
.IsId
);
3762 if (!EFI_ERROR (Status
)) {
3764 // Pass changed uncommitted data back to Form Browser.
3766 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
3767 HiiSetBrowserData (NULL
, NULL
, BufferSize
, (UINT8
*) IfrNvData
, NULL
);
3770 FreePool (IfrNvData
);
3771 FreePool (IScsiName
);
3778 Initialize the iSCSI configuration form.
3780 @param[in] DriverBindingHandle The iSCSI driverbinding handle.
3782 @retval EFI_SUCCESS The iSCSI configuration form is initialized.
3783 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
3787 IScsiConfigFormInit (
3788 IN EFI_HANDLE DriverBindingHandle
3792 ISCSI_FORM_CALLBACK_INFO
*CallbackInfo
;
3794 CallbackInfo
= (ISCSI_FORM_CALLBACK_INFO
*) AllocateZeroPool (sizeof (ISCSI_FORM_CALLBACK_INFO
));
3795 if (CallbackInfo
== NULL
) {
3796 return EFI_OUT_OF_RESOURCES
;
3799 CallbackInfo
->Signature
= ISCSI_FORM_CALLBACK_INFO_SIGNATURE
;
3800 CallbackInfo
->Current
= NULL
;
3802 CallbackInfo
->ConfigAccess
.ExtractConfig
= IScsiFormExtractConfig
;
3803 CallbackInfo
->ConfigAccess
.RouteConfig
= IScsiFormRouteConfig
;
3804 CallbackInfo
->ConfigAccess
.Callback
= IScsiFormCallback
;
3807 // Install Device Path Protocol and Config Access protocol to driver handle.
3809 Status
= gBS
->InstallMultipleProtocolInterfaces (
3810 &CallbackInfo
->DriverHandle
,
3811 &gEfiDevicePathProtocolGuid
,
3812 &mIScsiHiiVendorDevicePath
,
3813 &gEfiHiiConfigAccessProtocolGuid
,
3814 &CallbackInfo
->ConfigAccess
,
3817 ASSERT_EFI_ERROR (Status
);
3820 // Publish our HII data.
3822 CallbackInfo
->RegisteredHandle
= HiiAddPackages (
3824 CallbackInfo
->DriverHandle
,
3829 if (CallbackInfo
->RegisteredHandle
== NULL
) {
3830 gBS
->UninstallMultipleProtocolInterfaces (
3831 &CallbackInfo
->DriverHandle
,
3832 &gEfiDevicePathProtocolGuid
,
3833 &mIScsiHiiVendorDevicePath
,
3834 &gEfiHiiConfigAccessProtocolGuid
,
3835 &CallbackInfo
->ConfigAccess
,
3838 FreePool(CallbackInfo
);
3839 return EFI_OUT_OF_RESOURCES
;
3842 mCallbackInfo
= CallbackInfo
;
3849 Unload the iSCSI configuration form, this includes: delete all the iSCSI
3850 configuration entries, uninstall the form callback protocol, and
3851 free the resources used.
3853 @param[in] DriverBindingHandle The iSCSI driverbinding handle.
3855 @retval EFI_SUCCESS The iSCSI configuration form is unloaded.
3856 @retval Others Failed to unload the form.
3860 IScsiConfigFormUnload (
3861 IN EFI_HANDLE DriverBindingHandle
3864 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
3865 ISCSI_NIC_INFO
*NicInfo
;
3869 while (!IsListEmpty (&mPrivate
->AttemptConfigs
)) {
3870 Entry
= NetListRemoveHead (&mPrivate
->AttemptConfigs
);
3871 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
3872 FreePool (AttemptConfigData
);
3873 mPrivate
->AttemptCount
--;
3876 ASSERT (mPrivate
->AttemptCount
== 0);
3878 while (!IsListEmpty (&mPrivate
->NicInfoList
)) {
3879 Entry
= NetListRemoveHead (&mPrivate
->NicInfoList
);
3880 NicInfo
= NET_LIST_USER_STRUCT (Entry
, ISCSI_NIC_INFO
, Link
);
3882 mPrivate
->NicCount
--;
3885 ASSERT (mPrivate
->NicCount
== 0);
3887 FreePool (mPrivate
);
3891 // Remove HII package list.
3893 HiiRemovePackages (mCallbackInfo
->RegisteredHandle
);
3896 // Uninstall Device Path Protocol and Config Access protocol.
3898 Status
= gBS
->UninstallMultipleProtocolInterfaces (
3899 mCallbackInfo
->DriverHandle
,
3900 &gEfiDevicePathProtocolGuid
,
3901 &mIScsiHiiVendorDevicePath
,
3902 &gEfiHiiConfigAccessProtocolGuid
,
3903 &mCallbackInfo
->ConfigAccess
,
3907 FreePool (mCallbackInfo
);