2 Helper functions for configuring or getting the parameters relating to iSCSI.
4 Copyright (c) 2004 - 2019, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
11 CHAR16 mVendorStorageName
[] = L
"ISCSI_CONFIG_IFR_NVDATA";
12 ISCSI_FORM_CALLBACK_INFO
*mCallbackInfo
= NULL
;
14 HII_VENDOR_DEVICE_PATH mIScsiHiiVendorDevicePath
= {
20 (UINT8
)(sizeof (VENDOR_DEVICE_PATH
)),
21 (UINT8
)((sizeof (VENDOR_DEVICE_PATH
)) >> 8)
28 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
30 (UINT8
)(END_DEVICE_PATH_LENGTH
),
31 (UINT8
)((END_DEVICE_PATH_LENGTH
) >> 8)
37 Convert the IP address into a dotted string.
39 @param[in] Ip The IP address.
40 @param[in] Ipv6Flag Indicates whether the IP address is version 4 or version 6.
41 @param[out] Str The formatted IP string.
46 IN EFI_IP_ADDRESS
*Ip
,
51 EFI_IPv4_ADDRESS
*Ip4
;
52 EFI_IPv6_ADDRESS
*Ip6
;
56 CHAR16 FormatString
[8];
63 (UINTN
)2 * IP4_STR_MAX_SIZE
,
77 for (Index
= 0; Index
< 15; Index
= Index
+ 2) {
80 (Ip6
->Addr
[Index
] == 0) &&
81 (Ip6
->Addr
[Index
+ 1] == 0)
85 // Deal with the case of ::.
96 while ((Index
< 15) && (Ip6
->Addr
[Index
] == 0) && (Ip6
->Addr
[Index
+ 1] == 0)) {
104 // :: is at the end of the address.
113 if (Ip6
->Addr
[Index
] == 0) {
114 Number
= UnicodeSPrint (Str
, 2 * IP_STR_MAX_SIZE
, L
"%x:", (UINTN
)Ip6
->Addr
[Index
+ 1]);
116 if (Ip6
->Addr
[Index
+ 1] < 0x10) {
117 CopyMem (FormatString
, L
"%x0%x:", StrSize (L
"%x0%x:"));
119 CopyMem (FormatString
, L
"%x%x:", StrSize (L
"%x%x:"));
122 Number
= UnicodeSPrint (
125 (CONST CHAR16
*)FormatString
,
126 (UINTN
)Ip6
->Addr
[Index
],
127 (UINTN
)Ip6
->Addr
[Index
+ 1]
133 if (Index
+ 2 == 16) {
135 if (*(Str
- 1) == L
':') {
143 Check whether the input IP address is valid.
145 @param[in] Ip The IP address.
146 @param[in] IpMode Indicates iSCSI running on IP4 or IP6 stack.
148 @retval TRUE The input IP address is valid.
149 @retval FALSE Otherwise
154 IN EFI_IP_ADDRESS
*Ip
,
158 if (IpMode
== IP_MODE_IP4
) {
159 if (IP4_IS_UNSPECIFIED (NTOHL (Ip
->Addr
[0])) || IP4_IS_LOCAL_BROADCAST (NTOHL (Ip
->Addr
[0]))) {
164 } else if (IpMode
== IP_MODE_IP6
) {
165 return NetIp6IsValidUnicast (&Ip
->v6
);
167 DEBUG ((DEBUG_ERROR
, "IpMode %d is invalid when configuring the iSCSI target IP!\n", IpMode
));
173 Parse IsId in string format and convert it to binary.
175 @param[in] String The buffer of the string to be parsed.
176 @param[in, out] IsId The buffer to store IsId.
178 @retval EFI_SUCCESS The operation finished successfully.
179 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
183 IScsiParseIsIdFromString (
184 IN CONST CHAR16
*String
,
192 CHAR16 PortString
[ISCSI_NAME_IFR_MAX_SIZE
];
195 if ((String
== NULL
) || (IsId
== NULL
)) {
196 return EFI_INVALID_PARAMETER
;
199 IsIdStr
= (CHAR16
*)String
;
201 if ((StrLen (IsIdStr
) != 6) && (StrLen (IsIdStr
) != 12)) {
204 (UINTN
)ISCSI_NAME_IFR_MAX_SIZE
,
205 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"
209 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
215 return EFI_INVALID_PARAMETER
;
218 if (StrLen (IsIdStr
) == 12) {
222 for (Index
= 3; Index
< 6; Index
++) {
223 CopyMem (TempStr
, IsIdStr
, sizeof (TempStr
));
227 // Convert the string to IsId. StrHexToUintn stops at the first character
228 // that is not a valid hex character, '\0' here.
230 NodeVal
= StrHexToUintn (TempStr
);
232 IsId
[Index
] = (UINT8
)NodeVal
;
234 IsIdStr
= IsIdStr
+ 2;
241 Convert IsId from binary to string format.
243 @param[out] String The buffer to store the converted string.
244 @param[in] IsId The buffer to store IsId.
246 @retval EFI_SUCCESS The string converted successfully.
247 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
251 IScsiConvertIsIdToString (
259 if ((String
== NULL
) || (IsId
== NULL
)) {
260 return EFI_INVALID_PARAMETER
;
263 for (Index
= 0; Index
< 6; Index
++) {
264 if (IsId
[Index
] <= 0xF) {
265 Number
= UnicodeSPrint (
267 2 * ISID_CONFIGURABLE_STORAGE
,
272 Number
= UnicodeSPrint (
274 2 * ISID_CONFIGURABLE_STORAGE
,
280 String
= String
+ Number
;
289 Get the Offset value specified by the input String.
291 @param[in] Configuration A null-terminated Unicode string in
292 <ConfigString> format.
293 @param[in] String The string is "&OFFSET=".
294 @param[out] Value The Offset value.
296 @retval EFI_OUT_OF_RESOURCES Insufficient resources to store necessary
298 @retval EFI_SUCCESS Value of <Number> is outputted in Number
304 IN CONST EFI_STRING Configuration
,
324 StringPtr
= StrStr (Configuration
, String
);
325 ASSERT (StringPtr
!= NULL
);
326 StringPtr
+= StrLen (String
);
329 while (*StringPtr
!= L
'\0' && *StringPtr
!= L
'&') {
333 Length
= StringPtr
- TmpPtr
;
336 Str
= AllocateZeroPool (Len
* sizeof (CHAR16
));
338 Status
= EFI_OUT_OF_RESOURCES
;
342 CopyMem (Str
, TmpPtr
, Len
* sizeof (CHAR16
));
343 *(Str
+ Length
) = L
'\0';
346 Buf
= (UINT8
*)AllocateZeroPool (Len
);
348 Status
= EFI_OUT_OF_RESOURCES
;
352 ZeroMem (TmpStr
, sizeof (TmpStr
));
353 for (Index
= 0; Index
< Length
; Index
++) {
354 TmpStr
[0] = Str
[Length
- Index
- 1];
355 DigitUint8
= (UINT8
)StrHexToUint64 (TmpStr
);
356 if ((Index
& 1) == 0) {
357 Buf
[Index
/2] = DigitUint8
;
359 Buf
[Index
/2] = (UINT8
)((DigitUint8
<< 4) + Buf
[Index
/2]);
367 (((Length
+ 1) / 2) < sizeof (UINTN
)) ? ((Length
+ 1) / 2) : sizeof (UINTN
)
371 Status
= EFI_SUCCESS
;
382 Get the attempt config data from global structure by the ConfigIndex.
384 @param[in] AttemptConfigIndex The unique index indicates the attempt.
386 @return Pointer to the attempt config data.
387 @retval NULL The attempt configuration data cannot be found.
390 ISCSI_ATTEMPT_CONFIG_NVDATA
*
391 IScsiConfigGetAttemptByConfigIndex (
392 IN UINT8 AttemptConfigIndex
396 ISCSI_ATTEMPT_CONFIG_NVDATA
*Attempt
;
398 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
399 Attempt
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
400 if (Attempt
->AttemptConfigIndex
== AttemptConfigIndex
) {
409 Get the existing attempt config data from global structure by the NicIndex.
411 @param[in] NewAttempt The created new attempt
412 @param[in] IScsiMode The IScsi Mode of the new attempt, Enabled or
415 @return Pointer to the existing attempt config data which
416 has the same NICIndex as the new created attempt.
417 @retval NULL The attempt with NicIndex does not exist.
420 ISCSI_ATTEMPT_CONFIG_NVDATA
*
421 IScsiConfigGetAttemptByNic (
422 IN ISCSI_ATTEMPT_CONFIG_NVDATA
*NewAttempt
,
427 ISCSI_ATTEMPT_CONFIG_NVDATA
*Attempt
;
429 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
430 Attempt
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
431 if ((Attempt
!= NewAttempt
) && (Attempt
->NicIndex
== NewAttempt
->NicIndex
) &&
432 (Attempt
->SessionConfigData
.Enabled
== IScsiMode
))
442 Extract the Index of the attempt list.
444 @param[in] AttemptNameList The Name list of the Attempts.
445 @param[out] AttemptIndexList The Index list of the Attempts.
446 @param[in] IsAddAttempts If TRUE, Indicates add one or more attempts.
447 If FALSE, Indicates delete attempts or change attempt order.
449 @retval EFI_SUCCESS The Attempt list is valid.
450 @retval EFI_INVALID_PARAMETERS The Attempt List is invalid.
454 IScsiGetAttemptIndexList (
455 IN CHAR16
*AttemptNameList
,
456 OUT UINT8
*AttemptIndexList
,
457 IN BOOLEAN IsAddAttempts
460 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
468 if ((AttemptNameList
== NULL
) || (*AttemptNameList
== L
'\0')) {
469 return EFI_INVALID_PARAMETER
;
472 AttemptStr
= AttemptNameList
;
473 Len
= StrLen (L
"attempt:");
475 while (*AttemptStr
!= L
'\0') {
476 AttemptStr
= StrStr (AttemptStr
, L
"attempt:");
477 if (AttemptStr
== NULL
) {
478 return EFI_INVALID_PARAMETER
;
482 AttemptIndex
= (UINT8
)(*AttemptStr
- L
'0');
483 AttemptConfigData
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
485 if ((AttemptConfigData
!= NULL
) || ((AttemptIndex
) > PcdGet8 (PcdMaxIScsiAttemptNumber
))) {
486 return EFI_INVALID_PARAMETER
;
489 if (AttemptConfigData
== NULL
) {
490 return EFI_INVALID_PARAMETER
;
494 AttemptIndexList
[Index
] = AttemptIndex
;
503 Convert the iSCSI configuration data into the IFR data.
505 @param[in] Attempt The iSCSI attempt config data.
506 @param[in, out] IfrNvData The IFR nv data.
510 IScsiConvertAttemptConfigDataToIfrNvData (
511 IN ISCSI_ATTEMPT_CONFIG_NVDATA
*Attempt
,
512 IN OUT ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
515 ISCSI_SESSION_CONFIG_NVDATA
*SessionConfigData
;
516 ISCSI_CHAP_AUTH_CONFIG_NVDATA
*AuthConfigData
;
521 // Normal session configuration parameters.
523 SessionConfigData
= &Attempt
->SessionConfigData
;
524 IfrNvData
->Enabled
= SessionConfigData
->Enabled
;
525 IfrNvData
->IpMode
= SessionConfigData
->IpMode
;
526 DnsMode
= SessionConfigData
->DnsMode
;
528 IfrNvData
->InitiatorInfoFromDhcp
= SessionConfigData
->InitiatorInfoFromDhcp
;
529 IfrNvData
->TargetInfoFromDhcp
= SessionConfigData
->TargetInfoFromDhcp
;
530 IfrNvData
->TargetPort
= SessionConfigData
->TargetPort
;
532 if (IfrNvData
->IpMode
== IP_MODE_IP4
) {
533 CopyMem (&Ip
.v4
, &SessionConfigData
->LocalIp
, sizeof (EFI_IPv4_ADDRESS
));
534 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->LocalIp
);
535 CopyMem (&Ip
.v4
, &SessionConfigData
->SubnetMask
, sizeof (EFI_IPv4_ADDRESS
));
536 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->SubnetMask
);
537 CopyMem (&Ip
.v4
, &SessionConfigData
->Gateway
, sizeof (EFI_IPv4_ADDRESS
));
538 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->Gateway
);
539 ZeroMem (IfrNvData
->TargetIp
, sizeof (IfrNvData
->TargetIp
));
540 if (SessionConfigData
->TargetIp
.v4
.Addr
[0] != '\0') {
541 CopyMem (&Ip
.v4
, &SessionConfigData
->TargetIp
, sizeof (EFI_IPv4_ADDRESS
));
542 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->TargetIp
);
544 } else if (IfrNvData
->IpMode
== IP_MODE_IP6
) {
545 ZeroMem (IfrNvData
->TargetIp
, sizeof (IfrNvData
->TargetIp
));
546 if (SessionConfigData
->TargetIp
.v6
.Addr
[0] != '\0') {
547 IP6_COPY_ADDRESS (&Ip
.v6
, &SessionConfigData
->TargetIp
);
548 IScsiIpToStr (&Ip
, TRUE
, IfrNvData
->TargetIp
);
552 AsciiStrToUnicodeStrS (
553 SessionConfigData
->TargetName
,
554 IfrNvData
->TargetName
,
555 sizeof (IfrNvData
->TargetName
) / sizeof (IfrNvData
->TargetName
[0])
559 AsciiStrToUnicodeStrS (
560 SessionConfigData
->TargetUrl
,
562 sizeof (IfrNvData
->TargetIp
) / sizeof (IfrNvData
->TargetIp
[0])
566 IScsiLunToUnicodeStr (SessionConfigData
->BootLun
, IfrNvData
->BootLun
);
567 IScsiConvertIsIdToString (IfrNvData
->IsId
, SessionConfigData
->IsId
);
569 IfrNvData
->ConnectRetryCount
= SessionConfigData
->ConnectRetryCount
;
570 IfrNvData
->ConnectTimeout
= SessionConfigData
->ConnectTimeout
;
573 // Authentication parameters.
575 IfrNvData
->AuthenticationType
= Attempt
->AuthenticationType
;
577 if (IfrNvData
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
578 AuthConfigData
= &Attempt
->AuthConfigData
.CHAP
;
579 IfrNvData
->CHAPType
= AuthConfigData
->CHAPType
;
580 AsciiStrToUnicodeStrS (
581 AuthConfigData
->CHAPName
,
583 sizeof (IfrNvData
->CHAPName
) / sizeof (IfrNvData
->CHAPName
[0])
585 AsciiStrToUnicodeStrS (
586 AuthConfigData
->CHAPSecret
,
587 IfrNvData
->CHAPSecret
,
588 sizeof (IfrNvData
->CHAPSecret
) / sizeof (IfrNvData
->CHAPSecret
[0])
590 AsciiStrToUnicodeStrS (
591 AuthConfigData
->ReverseCHAPName
,
592 IfrNvData
->ReverseCHAPName
,
593 sizeof (IfrNvData
->ReverseCHAPName
) / sizeof (IfrNvData
->ReverseCHAPName
[0])
595 AsciiStrToUnicodeStrS (
596 AuthConfigData
->ReverseCHAPSecret
,
597 IfrNvData
->ReverseCHAPSecret
,
598 sizeof (IfrNvData
->ReverseCHAPSecret
) / sizeof (IfrNvData
->ReverseCHAPSecret
[0])
605 AsciiStrToUnicodeStrS (
606 Attempt
->AttemptName
,
607 IfrNvData
->AttemptName
,
608 sizeof (IfrNvData
->AttemptName
) / sizeof (IfrNvData
->AttemptName
[0])
613 Convert the iSCSI configuration data into the IFR data Which will be used
614 to extract the iSCSI Keyword configuration in <ConfigAltResp> format.
616 @param[in, out] IfrNvData The IFR nv data.
621 IScsiConvertAttemptConfigDataToIfrNvDataByKeyword (
622 IN OUT ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
626 ISCSI_ATTEMPT_CONFIG_NVDATA
*Attempt
;
627 ISCSI_SESSION_CONFIG_NVDATA
*SessionConfigData
;
628 ISCSI_CHAP_AUTH_CONFIG_NVDATA
*AuthConfigData
;
629 CHAR16 AttemptNameList
[ATTEMPT_NAME_LIST_SIZE
];
630 ISCSI_NIC_INFO
*NicInfo
;
631 CHAR16 MacString
[ISCSI_MAX_MAC_STRING_LEN
];
637 ZeroMem (AttemptNameList
, sizeof (AttemptNameList
));
639 if ((mPrivate
!= NULL
) && (mPrivate
->AttemptCount
!= 0)) {
640 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
641 Attempt
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
643 // Normal session configuration parameters.
645 SessionConfigData
= &Attempt
->SessionConfigData
;
647 ASSERT ((Attempt
->AttemptConfigIndex
> 0) && (Attempt
->AttemptConfigIndex
<= FixedPcdGet8 (PcdMaxIScsiAttemptNumber
)));
648 Index
= Attempt
->AttemptConfigIndex
- 1;
651 // Save the attempt to AttemptNameList as Attempt:1 Attempt:2
653 AsciiStrToUnicodeStrS (
654 Attempt
->AttemptName
,
655 AttemptNameList
+ StrLen (AttemptNameList
),
656 ATTEMPT_NAME_LIST_SIZE
- StrLen (AttemptNameList
)
659 StringLen
= StrLen (AttemptNameList
);
660 ASSERT (StringLen
> 2);
661 *(AttemptNameList
+ StringLen
- 2) = L
':';
662 *(AttemptNameList
+ StringLen
) = L
' ';
664 AsciiStrToUnicodeStrS (
665 Attempt
->AttemptName
,
666 IfrNvData
->ISCSIAttemptName
+ ATTEMPT_NAME_SIZE
* Index
,
667 ATTEMPT_NAME_LIST_SIZE
- ATTEMPT_NAME_SIZE
* Index
670 IfrNvData
->ISCSIBootEnableList
[Index
] = SessionConfigData
->Enabled
;
671 IfrNvData
->ISCSIIpAddressTypeList
[Index
] = SessionConfigData
->IpMode
;
673 IfrNvData
->ISCSIInitiatorInfoViaDHCP
[Index
] = SessionConfigData
->InitiatorInfoFromDhcp
;
674 IfrNvData
->ISCSITargetInfoViaDHCP
[Index
] = SessionConfigData
->TargetInfoFromDhcp
;
675 IfrNvData
->ISCSIConnectRetry
[Index
] = SessionConfigData
->ConnectRetryCount
;
676 IfrNvData
->ISCSIConnectTimeout
[Index
] = SessionConfigData
->ConnectTimeout
;
677 IfrNvData
->ISCSITargetTcpPort
[Index
] = SessionConfigData
->TargetPort
;
679 if (SessionConfigData
->IpMode
== IP_MODE_IP4
) {
680 CopyMem (&Ip
.v4
, &SessionConfigData
->LocalIp
, sizeof (EFI_IPv4_ADDRESS
));
681 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->Keyword
[Index
].ISCSIInitiatorIpAddress
);
682 CopyMem (&Ip
.v4
, &SessionConfigData
->SubnetMask
, sizeof (EFI_IPv4_ADDRESS
));
683 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->Keyword
[Index
].ISCSIInitiatorNetmask
);
684 CopyMem (&Ip
.v4
, &SessionConfigData
->Gateway
, sizeof (EFI_IPv4_ADDRESS
));
685 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->Keyword
[Index
].ISCSIInitiatorGateway
);
686 if (SessionConfigData
->TargetIp
.v4
.Addr
[0] != '\0') {
687 CopyMem (&Ip
.v4
, &SessionConfigData
->TargetIp
, sizeof (EFI_IPv4_ADDRESS
));
688 IScsiIpToStr (&Ip
, FALSE
, IfrNvData
->Keyword
[Index
].ISCSITargetIpAddress
);
690 } else if (SessionConfigData
->IpMode
== IP_MODE_IP6
) {
691 ZeroMem (IfrNvData
->Keyword
[Index
].ISCSITargetIpAddress
, sizeof (IfrNvData
->TargetIp
));
692 if (SessionConfigData
->TargetIp
.v6
.Addr
[0] != '\0') {
693 IP6_COPY_ADDRESS (&Ip
.v6
, &SessionConfigData
->TargetIp
);
694 IScsiIpToStr (&Ip
, TRUE
, IfrNvData
->Keyword
[Index
].ISCSITargetIpAddress
);
698 AsciiStrToUnicodeStrS (
699 SessionConfigData
->TargetName
,
700 IfrNvData
->Keyword
[Index
].ISCSITargetName
,
704 if (SessionConfigData
->DnsMode
) {
705 AsciiStrToUnicodeStrS (
706 SessionConfigData
->TargetUrl
,
707 IfrNvData
->Keyword
[Index
].ISCSITargetIpAddress
,
708 sizeof (IfrNvData
->Keyword
[Index
].ISCSITargetIpAddress
) / sizeof (IfrNvData
->Keyword
[Index
].ISCSITargetIpAddress
[0])
712 IScsiLunToUnicodeStr (SessionConfigData
->BootLun
, IfrNvData
->Keyword
[Index
].ISCSILun
);
713 IScsiConvertIsIdToString (IfrNvData
->Keyword
[Index
].ISCSIIsId
, SessionConfigData
->IsId
);
715 IfrNvData
->ISCSIAuthenticationMethod
[Index
] = Attempt
->AuthenticationType
;
717 if (Attempt
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
718 AuthConfigData
= &Attempt
->AuthConfigData
.CHAP
;
719 IfrNvData
->ISCSIChapType
[Index
] = AuthConfigData
->CHAPType
;
720 AsciiStrToUnicodeStrS (
721 AuthConfigData
->CHAPName
,
722 IfrNvData
->Keyword
[Index
].ISCSIChapUsername
,
723 ISCSI_CHAP_NAME_STORAGE
726 AsciiStrToUnicodeStrS (
727 AuthConfigData
->CHAPSecret
,
728 IfrNvData
->Keyword
[Index
].ISCSIChapSecret
,
729 ISCSI_CHAP_SECRET_STORAGE
732 AsciiStrToUnicodeStrS (
733 AuthConfigData
->ReverseCHAPName
,
734 IfrNvData
->Keyword
[Index
].ISCSIReverseChapUsername
,
735 ISCSI_CHAP_NAME_STORAGE
738 AsciiStrToUnicodeStrS (
739 AuthConfigData
->ReverseCHAPSecret
,
740 IfrNvData
->Keyword
[Index
].ISCSIReverseChapSecret
,
741 ISCSI_CHAP_SECRET_STORAGE
745 CopyMem (IfrNvData
->ISCSIDisplayAttemptList
, AttemptNameList
, ATTEMPT_NAME_LIST_SIZE
);
747 ZeroMem (IfrNvData
->ISCSIMacAddr
, sizeof (IfrNvData
->ISCSIMacAddr
));
748 NET_LIST_FOR_EACH (Entry
, &mPrivate
->NicInfoList
) {
749 NicInfo
= NET_LIST_USER_STRUCT (Entry
, ISCSI_NIC_INFO
, Link
);
751 &NicInfo
->PermanentAddress
,
752 NicInfo
->HwAddressSize
,
757 IfrNvData
->ISCSIMacAddr
+ StrLen (IfrNvData
->ISCSIMacAddr
),
759 StrLen (MacString
) * sizeof (CHAR16
)
762 *(IfrNvData
->ISCSIMacAddr
+ StrLen (IfrNvData
->ISCSIMacAddr
)) = L
'/';
765 StringLen
= StrLen (IfrNvData
->ISCSIMacAddr
);
767 *(IfrNvData
->ISCSIMacAddr
+ StringLen
- 1) = L
'\0';
773 Convert the IFR data to iSCSI configuration data.
775 @param[in] IfrNvData Point to ISCSI_CONFIG_IFR_NVDATA.
776 @param[in, out] Attempt The iSCSI attempt config data.
778 @retval EFI_INVALID_PARAMETER Any input or configured parameter is invalid.
779 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
780 @retval EFI_OUT_OF_RESOURCES The operation is failed due to lack of resources.
781 @retval EFI_ABORTED The operation is aborted.
782 @retval EFI_SUCCESS The operation is completed successfully.
786 IScsiConvertIfrNvDataToAttemptConfigData (
787 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
,
788 IN OUT ISCSI_ATTEMPT_CONFIG_NVDATA
*Attempt
791 EFI_IP_ADDRESS HostIp
;
792 EFI_IP_ADDRESS SubnetMask
;
793 EFI_IP_ADDRESS Gateway
;
795 CHAR16
*AttemptName1
;
796 CHAR16
*AttemptName2
;
797 ISCSI_ATTEMPT_CONFIG_NVDATA
*ExistAttempt
;
798 ISCSI_ATTEMPT_CONFIG_NVDATA
*SameNicAttempt
;
799 CHAR16 IScsiMode
[64];
801 ISCSI_NIC_INFO
*NicInfo
;
803 UINT8
*AttemptConfigOrder
;
804 UINTN AttemptConfigOrderSize
;
805 UINT8
*AttemptOrderTmp
;
809 if ((IfrNvData
== NULL
) || (Attempt
== NULL
)) {
810 return EFI_INVALID_PARAMETER
;
814 // Update those fields which don't have INTERACTIVE attribute.
816 Attempt
->SessionConfigData
.ConnectRetryCount
= IfrNvData
->ConnectRetryCount
;
817 Attempt
->SessionConfigData
.ConnectTimeout
= IfrNvData
->ConnectTimeout
;
818 Attempt
->SessionConfigData
.IpMode
= IfrNvData
->IpMode
;
820 if (IfrNvData
->IpMode
< IP_MODE_AUTOCONFIG
) {
821 Attempt
->SessionConfigData
.InitiatorInfoFromDhcp
= IfrNvData
->InitiatorInfoFromDhcp
;
822 Attempt
->SessionConfigData
.TargetPort
= IfrNvData
->TargetPort
;
824 if (Attempt
->SessionConfigData
.TargetPort
== 0) {
825 Attempt
->SessionConfigData
.TargetPort
= ISCSI_WELL_KNOWN_PORT
;
828 Attempt
->SessionConfigData
.TargetInfoFromDhcp
= IfrNvData
->TargetInfoFromDhcp
;
831 Attempt
->AuthenticationType
= IfrNvData
->AuthenticationType
;
833 if (Attempt
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
834 Attempt
->AuthConfigData
.CHAP
.CHAPType
= IfrNvData
->CHAPType
;
838 // Only do full parameter validation if iSCSI is enabled on this device.
840 if (IfrNvData
->Enabled
!= ISCSI_DISABLED
) {
841 if (Attempt
->SessionConfigData
.ConnectTimeout
< CONNECT_MIN_TIMEOUT
) {
843 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
845 L
"Connection Establishing Timeout is less than minimum value 100ms.",
849 return EFI_INVALID_PARAMETER
;
853 // Validate the address configuration of the Initiator if DHCP isn't
856 if (!Attempt
->SessionConfigData
.InitiatorInfoFromDhcp
) {
857 CopyMem (&HostIp
.v4
, &Attempt
->SessionConfigData
.LocalIp
, sizeof (HostIp
.v4
));
858 CopyMem (&SubnetMask
.v4
, &Attempt
->SessionConfigData
.SubnetMask
, sizeof (SubnetMask
.v4
));
859 CopyMem (&Gateway
.v4
, &Attempt
->SessionConfigData
.Gateway
, sizeof (Gateway
.v4
));
861 if ((Gateway
.Addr
[0] != 0)) {
862 if (SubnetMask
.Addr
[0] == 0) {
864 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
866 L
"Gateway address is set but subnet mask is zero.",
870 return EFI_INVALID_PARAMETER
;
871 } else if (!IP4_NET_EQUAL (HostIp
.Addr
[0], Gateway
.Addr
[0], SubnetMask
.Addr
[0])) {
873 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
875 L
"Local IP and Gateway are not in the same subnet.",
879 return EFI_INVALID_PARAMETER
;
885 // Validate target configuration if DHCP isn't deployed.
887 if (!Attempt
->SessionConfigData
.TargetInfoFromDhcp
&& (Attempt
->SessionConfigData
.IpMode
< IP_MODE_AUTOCONFIG
)) {
888 if (!Attempt
->SessionConfigData
.DnsMode
) {
889 if (!IpIsUnicast (&Attempt
->SessionConfigData
.TargetIp
, IfrNvData
->IpMode
)) {
891 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
893 L
"Target IP is invalid!",
896 return EFI_INVALID_PARAMETER
;
899 if (Attempt
->SessionConfigData
.TargetUrl
[0] == '\0') {
901 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
903 L
"iSCSI target Url should not be NULL!",
906 return EFI_INVALID_PARAMETER
;
911 // Validate iSCSI target name configuration again:
912 // The format of iSCSI target name is already verified in IScsiFormCallback() when
913 // user input the name; here we only check the case user does not input the name.
915 if (Attempt
->SessionConfigData
.TargetName
[0] == '\0') {
917 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
919 L
"iSCSI target name is NULL!",
922 return EFI_INVALID_PARAMETER
;
927 // Validate the authentication info.
929 if (IfrNvData
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
930 if ((IfrNvData
->CHAPName
[0] == '\0') || (IfrNvData
->CHAPSecret
[0] == '\0')) {
932 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
934 L
"CHAP Name or CHAP Secret is invalid!",
938 return EFI_INVALID_PARAMETER
;
941 if ((IfrNvData
->CHAPType
== ISCSI_CHAP_MUTUAL
) &&
942 ((IfrNvData
->ReverseCHAPName
[0] == '\0') || (IfrNvData
->ReverseCHAPSecret
[0] == '\0'))
946 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
948 L
"Reverse CHAP Name or Reverse CHAP Secret is invalid!",
951 return EFI_INVALID_PARAMETER
;
956 // Check whether this attempt uses NIC which is already used by existing attempt.
958 SameNicAttempt
= IScsiConfigGetAttemptByNic (Attempt
, IfrNvData
->Enabled
);
959 if (SameNicAttempt
!= NULL
) {
960 AttemptName1
= (CHAR16
*)AllocateZeroPool (ATTEMPT_NAME_SIZE
* sizeof (CHAR16
));
961 if (AttemptName1
== NULL
) {
962 return EFI_OUT_OF_RESOURCES
;
965 AttemptName2
= (CHAR16
*)AllocateZeroPool (ATTEMPT_NAME_SIZE
* sizeof (CHAR16
));
966 if (AttemptName2
== NULL
) {
967 FreePool (AttemptName1
);
968 return EFI_OUT_OF_RESOURCES
;
971 AsciiStrToUnicodeStrS (Attempt
->AttemptName
, AttemptName1
, ATTEMPT_NAME_SIZE
);
972 AsciiStrToUnicodeStrS (SameNicAttempt
->AttemptName
, AttemptName2
, ATTEMPT_NAME_SIZE
);
975 mPrivate
->PortString
,
976 (UINTN
)ISCSI_NAME_IFR_MAX_SIZE
,
977 L
"Warning! Attempt \"%s\" uses same NIC as Attempt \"%s\".",
983 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
985 mPrivate
->PortString
,
989 FreePool (AttemptName1
);
990 FreePool (AttemptName2
);
995 // Update the iSCSI Mode data and record it in attempt help info.
997 if (IfrNvData
->Enabled
== ISCSI_DISABLED
) {
998 UnicodeSPrint (IScsiMode
, 64, L
"Disabled");
999 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
) {
1000 UnicodeSPrint (IScsiMode
, 64, L
"Enabled");
1001 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
1002 UnicodeSPrint (IScsiMode
, 64, L
"Enabled for MPIO");
1005 if (IfrNvData
->IpMode
== IP_MODE_IP4
) {
1006 UnicodeSPrint (IpMode
, 64, L
"IP4");
1007 } else if (IfrNvData
->IpMode
== IP_MODE_IP6
) {
1008 UnicodeSPrint (IpMode
, 64, L
"IP6");
1009 } else if (IfrNvData
->IpMode
== IP_MODE_AUTOCONFIG
) {
1010 UnicodeSPrint (IpMode
, 64, L
"Autoconfigure");
1013 NicInfo
= IScsiGetNicInfoByIndex (Attempt
->NicIndex
);
1014 if (NicInfo
== NULL
) {
1015 return EFI_NOT_FOUND
;
1018 MacString
= (CHAR16
*)AllocateZeroPool (ISCSI_MAX_MAC_STRING_LEN
* sizeof (CHAR16
));
1019 if (MacString
== NULL
) {
1020 return EFI_OUT_OF_RESOURCES
;
1023 AsciiStrToUnicodeStrS (Attempt
->MacString
, MacString
, ISCSI_MAX_MAC_STRING_LEN
);
1026 mPrivate
->PortString
,
1027 (UINTN
)ISCSI_NAME_IFR_MAX_SIZE
,
1028 L
"MAC: %s, PFA: Bus %d | Dev %d | Func %d, iSCSI mode: %s, IP version: %s",
1031 NicInfo
->DeviceNumber
,
1032 NicInfo
->FunctionNumber
,
1037 Attempt
->AttemptTitleHelpToken
= HiiSetString (
1038 mCallbackInfo
->RegisteredHandle
,
1039 Attempt
->AttemptTitleHelpToken
,
1040 mPrivate
->PortString
,
1043 if (Attempt
->AttemptTitleHelpToken
== 0) {
1044 FreePool (MacString
);
1045 return EFI_OUT_OF_RESOURCES
;
1049 // Check whether this attempt is an existing one.
1051 ExistAttempt
= IScsiConfigGetAttemptByConfigIndex (Attempt
->AttemptConfigIndex
);
1052 if (ExistAttempt
!= NULL
) {
1053 ASSERT (ExistAttempt
== Attempt
);
1055 if ((IfrNvData
->Enabled
== ISCSI_DISABLED
) &&
1056 (Attempt
->SessionConfigData
.Enabled
!= ISCSI_DISABLED
))
1059 // User updates the Attempt from "Enabled"/"Enabled for MPIO" to "Disabled".
1061 if (Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
1062 if (mPrivate
->MpioCount
< 1) {
1066 if (--mPrivate
->MpioCount
== 0) {
1067 mPrivate
->EnableMpio
= FALSE
;
1069 } else if (Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED
) {
1070 if (mPrivate
->SinglePathCount
< 1) {
1074 mPrivate
->SinglePathCount
--;
1076 } else if ((IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
) &&
1077 (Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED
))
1080 // User updates the Attempt from "Enabled" to "Enabled for MPIO".
1082 if (mPrivate
->SinglePathCount
< 1) {
1086 mPrivate
->EnableMpio
= TRUE
;
1087 mPrivate
->MpioCount
++;
1088 mPrivate
->SinglePathCount
--;
1089 } else if ((IfrNvData
->Enabled
== ISCSI_ENABLED
) &&
1090 (Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED_FOR_MPIO
))
1093 // User updates the Attempt from "Enabled for MPIO" to "Enabled".
1095 if (mPrivate
->MpioCount
< 1) {
1099 if (--mPrivate
->MpioCount
== 0) {
1100 mPrivate
->EnableMpio
= FALSE
;
1103 mPrivate
->SinglePathCount
++;
1104 } else if ((IfrNvData
->Enabled
!= ISCSI_DISABLED
) &&
1105 (Attempt
->SessionConfigData
.Enabled
== ISCSI_DISABLED
))
1108 // User updates the Attempt from "Disabled" to "Enabled"/"Enabled for MPIO".
1110 if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
1111 mPrivate
->EnableMpio
= TRUE
;
1112 mPrivate
->MpioCount
++;
1113 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
) {
1114 mPrivate
->SinglePathCount
++;
1117 } else if (ExistAttempt
== NULL
) {
1119 // When a new attempt is created, pointer of the attempt is saved to
1120 // mCallbackInfo->Current in IScsiConfigProcessDefault. If input Attempt
1121 // does not match any existing attempt, it should be a new created attempt.
1122 // Save it to system now.
1126 // Save current order number for this attempt.
1128 AttemptConfigOrder
= IScsiGetVariableAndSize (
1131 &AttemptConfigOrderSize
1134 TotalNumber
= AttemptConfigOrderSize
/ sizeof (UINT8
);
1138 // Append the new created attempt order to the end.
1140 AttemptOrderTmp
= AllocateZeroPool (TotalNumber
* sizeof (UINT8
));
1141 if (AttemptOrderTmp
== NULL
) {
1142 if (AttemptConfigOrder
!= NULL
) {
1143 FreePool (AttemptConfigOrder
);
1146 return EFI_OUT_OF_RESOURCES
;
1149 if (AttemptConfigOrder
!= NULL
) {
1150 CopyMem (AttemptOrderTmp
, AttemptConfigOrder
, AttemptConfigOrderSize
);
1151 FreePool (AttemptConfigOrder
);
1154 AttemptOrderTmp
[TotalNumber
- 1] = Attempt
->AttemptConfigIndex
;
1155 AttemptConfigOrder
= AttemptOrderTmp
;
1156 AttemptConfigOrderSize
= TotalNumber
* sizeof (UINT8
);
1158 Status
= gRT
->SetVariable (
1161 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
1162 AttemptConfigOrderSize
,
1165 FreePool (AttemptConfigOrder
);
1166 if (EFI_ERROR (Status
)) {
1171 // Insert new created attempt to array.
1173 InsertTailList (&mPrivate
->AttemptConfigs
, &Attempt
->Link
);
1174 mPrivate
->AttemptCount
++;
1176 if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
1178 // This new Attempt is enabled for MPIO; enable the multipath mode.
1180 mPrivate
->EnableMpio
= TRUE
;
1181 mPrivate
->MpioCount
++;
1182 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
) {
1183 mPrivate
->SinglePathCount
++;
1186 IScsiConfigUpdateAttempt ();
1189 Attempt
->SessionConfigData
.Enabled
= IfrNvData
->Enabled
;
1192 // Record the user configuration information in NVR.
1194 UnicodeSPrint (mPrivate
->PortString
, (UINTN
)ISCSI_NAME_IFR_MAX_SIZE
, L
"Attempt %d", Attempt
->AttemptConfigIndex
);
1196 FreePool (MacString
);
1198 return gRT
->SetVariable (
1199 mPrivate
->PortString
,
1200 &gEfiIScsiInitiatorNameProtocolGuid
,
1201 ISCSI_CONFIG_VAR_ATTR
,
1202 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA
),
1208 Convert the IFR data configured by keyword to iSCSI configuration data.
1210 @param[in] IfrNvData Point to ISCSI_CONFIG_IFR_NVDATA.
1211 @param[in] OffSet The offset of the variable to the configuration structure.
1213 @retval EFI_INVALID_PARAMETER Any input or configured parameter is invalid.
1214 @retval EFI_SUCCESS The operation is completed successfully.
1218 IScsiConvertlfrNvDataToAttemptConfigDataByKeyword (
1219 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
,
1223 ISCSI_ATTEMPT_CONFIG_NVDATA
*Attempt
;
1226 UINT8 ChapSecretLen
;
1227 UINT8 ReverseChapSecretLen
;
1228 CHAR16
*AttemptName1
;
1229 CHAR16
*AttemptName2
;
1230 ISCSI_ATTEMPT_CONFIG_NVDATA
*SameNicAttempt
;
1231 CHAR8 LunString
[ISCSI_LUN_STR_MAX_LEN
];
1232 CHAR8 IScsiName
[ISCSI_NAME_MAX_SIZE
];
1233 CHAR8 IpString
[IP_STR_MAX_SIZE
];
1234 EFI_IP_ADDRESS HostIp
;
1235 EFI_IP_ADDRESS SubnetMask
;
1236 EFI_IP_ADDRESS Gateway
;
1242 ZeroMem (IScsiName
, sizeof (IScsiName
));
1244 if (OffSet
< ATTEMPT_BOOTENABLE_VAR_OFFSET
) {
1246 } else if ((OffSet
>= ATTEMPT_BOOTENABLE_VAR_OFFSET
) && (OffSet
< ATTEMPT_ADDRESS_TYPE_VAR_OFFSET
)) {
1247 AttemptIndex
= (UINT8
)((OffSet
- ATTEMPT_BOOTENABLE_VAR_OFFSET
) + 1);
1248 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1249 if (Attempt
== NULL
) {
1250 return EFI_INVALID_PARAMETER
;
1253 IfrNvData
->Enabled
= IfrNvData
->ISCSIBootEnableList
[AttemptIndex
- 1];
1255 // Validate the configuration of attempt.
1257 if (IfrNvData
->Enabled
!= ISCSI_DISABLED
) {
1259 // Check whether this attempt uses NIC which is already used by existing attempt.
1261 SameNicAttempt
= IScsiConfigGetAttemptByNic (Attempt
, IfrNvData
->Enabled
);
1262 if (SameNicAttempt
!= NULL
) {
1263 AttemptName1
= (CHAR16
*)AllocateZeroPool (ATTEMPT_NAME_SIZE
* sizeof (CHAR16
));
1264 if (AttemptName1
== NULL
) {
1265 return EFI_OUT_OF_RESOURCES
;
1268 AttemptName2
= (CHAR16
*)AllocateZeroPool (ATTEMPT_NAME_SIZE
* sizeof (CHAR16
));
1269 if (AttemptName2
== NULL
) {
1270 FreePool (AttemptName1
);
1271 return EFI_OUT_OF_RESOURCES
;
1274 AsciiStrToUnicodeStrS (Attempt
->AttemptName
, AttemptName1
, ATTEMPT_NAME_SIZE
);
1275 AsciiStrToUnicodeStrS (SameNicAttempt
->AttemptName
, AttemptName2
, ATTEMPT_NAME_SIZE
);
1278 mPrivate
->PortString
,
1279 (UINTN
)ISCSI_NAME_IFR_MAX_SIZE
,
1280 L
"Warning! \"%s\" uses same NIC as Attempt \"%s\".",
1286 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1288 mPrivate
->PortString
,
1292 FreePool (AttemptName1
);
1293 FreePool (AttemptName2
);
1297 if ((IfrNvData
->Enabled
== ISCSI_DISABLED
) &&
1298 (Attempt
->SessionConfigData
.Enabled
!= ISCSI_DISABLED
))
1301 // User updates the Attempt from "Enabled"/"Enabled for MPIO" to "Disabled".
1303 if (Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
1304 if (mPrivate
->MpioCount
< 1) {
1308 if (--mPrivate
->MpioCount
== 0) {
1309 mPrivate
->EnableMpio
= FALSE
;
1311 } else if (Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED
) {
1312 if (mPrivate
->SinglePathCount
< 1) {
1316 mPrivate
->SinglePathCount
--;
1318 } else if ((IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
) &&
1319 (Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED
))
1322 // User updates the Attempt from "Enabled" to "Enabled for MPIO".
1324 if (mPrivate
->SinglePathCount
< 1) {
1328 mPrivate
->EnableMpio
= TRUE
;
1329 mPrivate
->MpioCount
++;
1330 mPrivate
->SinglePathCount
--;
1331 } else if ((IfrNvData
->Enabled
== ISCSI_ENABLED
) &&
1332 (Attempt
->SessionConfigData
.Enabled
== ISCSI_ENABLED_FOR_MPIO
))
1335 // User updates the Attempt from "Enabled for MPIO" to "Enabled".
1337 if (mPrivate
->MpioCount
< 1) {
1341 if (--mPrivate
->MpioCount
== 0) {
1342 mPrivate
->EnableMpio
= FALSE
;
1345 mPrivate
->SinglePathCount
++;
1346 } else if ((IfrNvData
->Enabled
!= ISCSI_DISABLED
) &&
1347 (Attempt
->SessionConfigData
.Enabled
== ISCSI_DISABLED
))
1350 // User updates the Attempt from "Disabled" to "Enabled"/"Enabled for MPIO".
1352 if (IfrNvData
->Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
1353 mPrivate
->EnableMpio
= TRUE
;
1354 mPrivate
->MpioCount
++;
1355 } else if (IfrNvData
->Enabled
== ISCSI_ENABLED
) {
1356 mPrivate
->SinglePathCount
++;
1360 Attempt
->SessionConfigData
.Enabled
= IfrNvData
->Enabled
;
1361 } else if ((OffSet
>= ATTEMPT_ADDRESS_TYPE_VAR_OFFSET
) && (OffSet
< ATTEMPT_CONNECT_RETRY_VAR_OFFSET
)) {
1362 AttemptIndex
= (UINT8
)((OffSet
- ATTEMPT_ADDRESS_TYPE_VAR_OFFSET
) + 1);
1363 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1364 if (Attempt
== NULL
) {
1365 return EFI_INVALID_PARAMETER
;
1368 Attempt
->SessionConfigData
.IpMode
= IfrNvData
->ISCSIIpAddressTypeList
[AttemptIndex
- 1];
1369 if (Attempt
->SessionConfigData
.IpMode
< IP_MODE_AUTOCONFIG
) {
1370 Attempt
->AutoConfigureMode
= 0;
1372 } else if ((OffSet
>= ATTEMPT_CONNECT_RETRY_VAR_OFFSET
) && (OffSet
< ATTEMPT_CONNECT_TIMEOUT_VAR_OFFSET
)) {
1373 AttemptIndex
= (UINT8
)((OffSet
- ATTEMPT_CONNECT_RETRY_VAR_OFFSET
) + 1);
1374 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1375 if (Attempt
== NULL
) {
1376 return EFI_INVALID_PARAMETER
;
1379 if (IfrNvData
->ISCSIConnectRetry
[AttemptIndex
- 1] > CONNECT_MAX_RETRY
) {
1381 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1383 L
"The minimum value is 0 and the maximum is 16. 0 means no retry.",
1386 return EFI_INVALID_PARAMETER
;
1389 Attempt
->SessionConfigData
.ConnectRetryCount
= IfrNvData
->ISCSIConnectRetry
[AttemptIndex
- 1];
1390 } else if ((OffSet
>= ATTEMPT_CONNECT_TIMEOUT_VAR_OFFSET
) && (OffSet
< ATTEMPT_INITIATOR_VIA_DHCP_VAR_OFFSET
)) {
1391 AttemptIndex
= (UINT8
)((OffSet
- ATTEMPT_CONNECT_TIMEOUT_VAR_OFFSET
) / 2 + 1);
1392 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1393 if (Attempt
== NULL
) {
1394 return EFI_INVALID_PARAMETER
;
1397 if ((IfrNvData
->ISCSIConnectTimeout
[AttemptIndex
- 1] < CONNECT_MIN_TIMEOUT
) ||
1398 (IfrNvData
->ISCSIConnectTimeout
[AttemptIndex
- 1] > CONNECT_MAX_TIMEOUT
))
1401 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1403 L
"The minimum value is 100 milliseconds and the maximum is 20 seconds.",
1406 return EFI_INVALID_PARAMETER
;
1409 Attempt
->SessionConfigData
.ConnectTimeout
= IfrNvData
->ISCSIConnectTimeout
[AttemptIndex
- 1];
1410 if (Attempt
->SessionConfigData
.ConnectTimeout
== 0) {
1411 Attempt
->SessionConfigData
.ConnectTimeout
= CONNECT_DEFAULT_TIMEOUT
;
1413 } else if ((OffSet
>= ATTEMPT_INITIATOR_VIA_DHCP_VAR_OFFSET
) && (OffSet
< ATTEMPT_TARGET_VIA_DHCP_VAR_OFFSET
)) {
1414 AttemptIndex
= (UINT8
)((OffSet
- ATTEMPT_INITIATOR_VIA_DHCP_VAR_OFFSET
) + 1);
1415 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1416 if (Attempt
== NULL
) {
1417 return EFI_INVALID_PARAMETER
;
1420 Attempt
->SessionConfigData
.InitiatorInfoFromDhcp
= IfrNvData
->ISCSIInitiatorInfoViaDHCP
[AttemptIndex
- 1];
1421 } else if ((OffSet
>= ATTEMPT_TARGET_VIA_DHCP_VAR_OFFSET
) && (OffSet
< ATTEMPT_TARGET_TCP_PORT_VAR_OFFSET
)) {
1422 AttemptIndex
= (UINT8
)((OffSet
- ATTEMPT_TARGET_VIA_DHCP_VAR_OFFSET
) + 1);
1423 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1424 if (Attempt
== NULL
) {
1425 return EFI_INVALID_PARAMETER
;
1428 if ((Attempt
->SessionConfigData
.IpMode
< IP_MODE_AUTOCONFIG
) && (Attempt
->SessionConfigData
.InitiatorInfoFromDhcp
)) {
1429 Attempt
->SessionConfigData
.TargetInfoFromDhcp
= IfrNvData
->ISCSITargetInfoViaDHCP
[AttemptIndex
- 1];
1432 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1434 L
"Invalid Configuration, Check value of IpMode or Enable DHCP!",
1437 return EFI_INVALID_PARAMETER
;
1439 } else if ((OffSet
>= ATTEMPT_TARGET_TCP_PORT_VAR_OFFSET
) && (OffSet
< ATTEMPT_AUTHENTICATION_METHOD_VAR_OFFSET
)) {
1440 AttemptIndex
= (UINT8
)((OffSet
- ATTEMPT_TARGET_TCP_PORT_VAR_OFFSET
) / 2 + 1);
1441 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1442 if (Attempt
== NULL
) {
1443 return EFI_INVALID_PARAMETER
;
1446 if ((Attempt
->SessionConfigData
.IpMode
< IP_MODE_AUTOCONFIG
) && (!Attempt
->SessionConfigData
.TargetInfoFromDhcp
)) {
1447 Attempt
->SessionConfigData
.TargetPort
= IfrNvData
->ISCSITargetTcpPort
[AttemptIndex
- 1];
1448 if (Attempt
->SessionConfigData
.TargetPort
== 0) {
1449 Attempt
->SessionConfigData
.TargetPort
= ISCSI_WELL_KNOWN_PORT
;
1453 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1455 L
"Invalid Configuration, Check value of IpMode or Target Via DHCP!",
1458 return EFI_INVALID_PARAMETER
;
1460 } else if ((OffSet
>= ATTEMPT_AUTHENTICATION_METHOD_VAR_OFFSET
) && (OffSet
< ATTEMPT_CHARTYPE_VAR_OFFSET
)) {
1461 AttemptIndex
= (UINT8
)((OffSet
- ATTEMPT_AUTHENTICATION_METHOD_VAR_OFFSET
) + 1);
1462 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1463 if (Attempt
== NULL
) {
1464 return EFI_INVALID_PARAMETER
;
1467 Attempt
->AuthenticationType
= IfrNvData
->ISCSIAuthenticationMethod
[AttemptIndex
- 1];
1468 } else if ((OffSet
>= ATTEMPT_CHARTYPE_VAR_OFFSET
) && (OffSet
< ATTEMPT_ISID_VAR_OFFSET
)) {
1469 AttemptIndex
= (UINT8
)((OffSet
- ATTEMPT_CHARTYPE_VAR_OFFSET
) + 1);
1470 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1471 if (Attempt
== NULL
) {
1472 return EFI_INVALID_PARAMETER
;
1475 if (Attempt
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
1476 Attempt
->AuthConfigData
.CHAP
.CHAPType
= IfrNvData
->ISCSIChapType
[AttemptIndex
- 1];
1478 } else if (OffSet
>= ATTEMPT_ISID_VAR_OFFSET
) {
1479 Index
= (UINT8
)((OffSet
- ATTEMPT_ISID_VAR_OFFSET
) / sizeof (KEYWORD_STR
));
1480 AttemptIndex
= Index
+ 1;
1481 Attempt
= IScsiConfigGetAttemptByConfigIndex (AttemptIndex
);
1482 if (Attempt
== NULL
) {
1483 return EFI_INVALID_PARAMETER
;
1486 OffSet
= OffSet
- Index
* sizeof (KEYWORD_STR
);
1488 if ((OffSet
>= ATTEMPT_ISID_VAR_OFFSET
) && (OffSet
< ATTEMPT_INITIATOR_IP_ADDRESS_VAR_OFFSET
)) {
1489 IScsiParseIsIdFromString (IfrNvData
->Keyword
[Index
].ISCSIIsId
, Attempt
->SessionConfigData
.IsId
);
1490 } else if ((OffSet
>= ATTEMPT_INITIATOR_IP_ADDRESS_VAR_OFFSET
) && (OffSet
< ATTEMPT_INITIATOR_NET_MASK_VAR_OFFSET
)) {
1491 if ((Attempt
->SessionConfigData
.IpMode
== IP_MODE_IP4
) && (!Attempt
->SessionConfigData
.InitiatorInfoFromDhcp
)) {
1495 Status
= NetLibStrToIp4 (IfrNvData
->Keyword
[Index
].ISCSIInitiatorIpAddress
, &HostIp
.v4
);
1496 if (EFI_ERROR (Status
) || ((Attempt
->SessionConfigData
.SubnetMask
.Addr
[0] != 0) &&
1497 !NetIp4IsUnicast (NTOHL (HostIp
.Addr
[0]), NTOHL (*(UINT32
*)Attempt
->SessionConfigData
.SubnetMask
.Addr
))))
1500 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1502 L
"Invalid IP address!",
1505 return EFI_INVALID_PARAMETER
;
1507 CopyMem (&Attempt
->SessionConfigData
.LocalIp
, &HostIp
.v4
, sizeof (HostIp
.v4
));
1511 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1513 L
"Invalid Configuration, Check value of IpMode or Enable DHCP!",
1516 return EFI_INVALID_PARAMETER
;
1518 } else if ((OffSet
>= ATTEMPT_INITIATOR_NET_MASK_VAR_OFFSET
) && (OffSet
< ATTEMPT_INITIATOR_GATE_WAY_VAR_OFFSET
)) {
1519 if ((Attempt
->SessionConfigData
.IpMode
== IP_MODE_IP4
) && (!Attempt
->SessionConfigData
.InitiatorInfoFromDhcp
)) {
1520 Status
= NetLibStrToIp4 (IfrNvData
->Keyword
[Index
].ISCSIInitiatorNetmask
, &SubnetMask
.v4
);
1521 if (EFI_ERROR (Status
) || ((SubnetMask
.Addr
[0] != 0) && (IScsiGetSubnetMaskPrefixLength (&SubnetMask
.v4
) == 0))) {
1523 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1525 L
"Invalid Subnet Mask!",
1528 return EFI_INVALID_PARAMETER
;
1530 CopyMem (&Attempt
->SessionConfigData
.SubnetMask
, &SubnetMask
.v4
, sizeof (SubnetMask
.v4
));
1534 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1536 L
"Invalid Configuration, Check value of IpMode or Enable DHCP!",
1539 return EFI_INVALID_PARAMETER
;
1541 } else if ((OffSet
>= ATTEMPT_INITIATOR_GATE_WAY_VAR_OFFSET
) && (OffSet
< ATTEMPT_TARGET_NAME_VAR_OFFSET
)) {
1542 if ((Attempt
->SessionConfigData
.IpMode
== IP_MODE_IP4
) && (!Attempt
->SessionConfigData
.InitiatorInfoFromDhcp
)) {
1543 Status
= NetLibStrToIp4 (IfrNvData
->Keyword
[Index
].ISCSIInitiatorGateway
, &Gateway
.v4
);
1544 if (EFI_ERROR (Status
) ||
1545 ((Gateway
.Addr
[0] != 0) && (Attempt
->SessionConfigData
.SubnetMask
.Addr
[0] != 0) &&
1546 !NetIp4IsUnicast (NTOHL (Gateway
.Addr
[0]), NTOHL (*(UINT32
*)Attempt
->SessionConfigData
.SubnetMask
.Addr
))))
1549 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1551 L
"Invalid Gateway!",
1554 return EFI_INVALID_PARAMETER
;
1556 CopyMem (&Attempt
->SessionConfigData
.Gateway
, &Gateway
.v4
, sizeof (Gateway
.v4
));
1560 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1562 L
"Invalid Configuration, Check value of IpMode or Enable DHCP!",
1565 return EFI_INVALID_PARAMETER
;
1567 } else if ((OffSet
>= ATTEMPT_TARGET_NAME_VAR_OFFSET
) && (OffSet
< ATTEMPT_TARGET_IP_ADDRESS_VAR_OFFSET
)) {
1568 if ((Attempt
->SessionConfigData
.IpMode
< IP_MODE_AUTOCONFIG
) && (!Attempt
->SessionConfigData
.TargetInfoFromDhcp
)) {
1569 UnicodeStrToAsciiStrS (IfrNvData
->Keyword
[Index
].ISCSITargetName
, IScsiName
, ISCSI_NAME_MAX_SIZE
);
1570 Status
= IScsiNormalizeName (IScsiName
, AsciiStrLen (IScsiName
));
1571 if (EFI_ERROR (Status
)) {
1573 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1575 L
"Invalid iSCSI Name!",
1579 AsciiStrCpyS (Attempt
->SessionConfigData
.TargetName
, ISCSI_NAME_MAX_SIZE
, IScsiName
);
1582 if (Attempt
->SessionConfigData
.Enabled
!= ISCSI_DISABLED
) {
1583 if (Attempt
->SessionConfigData
.TargetName
[0] == L
'\0') {
1585 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1587 L
"iSCSI target name is NULL!",
1590 return EFI_INVALID_PARAMETER
;
1595 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1597 L
"Invalid Configuration, Check value of IpMode or Target Via DHCP!",
1600 return EFI_INVALID_PARAMETER
;
1602 } else if ((OffSet
>= ATTEMPT_TARGET_IP_ADDRESS_VAR_OFFSET
) && (OffSet
< ATTEMPT_LUN_VAR_OFFSET
)) {
1603 if ((Attempt
->SessionConfigData
.IpMode
< IP_MODE_AUTOCONFIG
) && (!Attempt
->SessionConfigData
.TargetInfoFromDhcp
)) {
1604 UnicodeStrToAsciiStrS (IfrNvData
->Keyword
[Index
].ISCSITargetIpAddress
, IpString
, sizeof (IpString
));
1605 Status
= IScsiAsciiStrToIp (IpString
, Attempt
->SessionConfigData
.IpMode
, &HostIp
);
1606 if (EFI_ERROR (Status
) || !IpIsUnicast (&HostIp
, Attempt
->SessionConfigData
.IpMode
)) {
1607 Attempt
->SessionConfigData
.DnsMode
= TRUE
;
1608 ZeroMem (&Attempt
->SessionConfigData
.TargetIp
, sizeof (Attempt
->SessionConfigData
.TargetIp
));
1609 UnicodeStrToAsciiStrS (IfrNvData
->Keyword
[Index
].ISCSITargetIpAddress
, Attempt
->SessionConfigData
.TargetUrl
, ISCSI_NAME_MAX_SIZE
);
1611 Attempt
->SessionConfigData
.DnsMode
= FALSE
;
1612 CopyMem (&Attempt
->SessionConfigData
.TargetIp
, &HostIp
, sizeof (HostIp
));
1616 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1618 L
"Invalid Configuration, Check value of IpMode or Target Via DHCP!",
1621 return EFI_INVALID_PARAMETER
;
1623 } else if ((OffSet
>= ATTEMPT_LUN_VAR_OFFSET
) && (OffSet
< ATTEMPT_CHAR_USER_NAME_VAR_OFFSET
)) {
1624 if ((Attempt
->SessionConfigData
.IpMode
< IP_MODE_AUTOCONFIG
) && (Attempt
->SessionConfigData
.TargetInfoFromDhcp
== 0)) {
1628 UnicodeStrToAsciiStrS (IfrNvData
->Keyword
[Index
].ISCSILun
, LunString
, ISCSI_LUN_STR_MAX_LEN
);
1629 Status
= IScsiAsciiStrToLun (LunString
, (UINT8
*)&Lun
);
1630 if (EFI_ERROR (Status
)) {
1632 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1634 L
"Invalid LUN string, Examples are: 4752-3A4F-6b7e-2F99, 6734-9-156f-127, 4186-9!",
1638 CopyMem (&Attempt
->SessionConfigData
.BootLun
, &Lun
, sizeof (Lun
));
1642 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1644 L
"Invalid Configuration, Check value of IpMode or Target Via DHCP!",
1647 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
;
1677 } else if ((OffSet
>= ATTEMPT_CHAR_SECRET_VAR_OFFSET
) && (OffSet
< ATTEMPT_CHAR_REVERSE_USER_NAME_VAR_OFFSET
)) {
1678 if (Attempt
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
1679 ChapSecretLen
= (UINT8
)StrLen (IfrNvData
->Keyword
[Index
].ISCSIChapSecret
);
1680 UnicodeStrToAsciiStrS (
1681 IfrNvData
->Keyword
[Index
].ISCSIChapSecret
,
1682 Attempt
->AuthConfigData
.CHAP
.CHAPSecret
,
1683 ISCSI_CHAP_SECRET_STORAGE
1686 if (Attempt
->SessionConfigData
.Enabled
!= ISCSI_DISABLED
) {
1687 if ((ChapSecretLen
< ISCSI_CHAP_SECRET_MIN_LEN
) || (ChapSecretLen
> ISCSI_CHAP_SECRET_MAX_LEN
)) {
1689 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1691 L
"The Chap Secret minimum length is 12 bytes and the maximum length is 16 bytes.",
1694 return EFI_INVALID_PARAMETER
;
1699 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1701 L
"Invalid Configuration, Check value of AuthenticationType!",
1704 return EFI_INVALID_PARAMETER
;
1706 } else if ((OffSet
>= ATTEMPT_CHAR_REVERSE_USER_NAME_VAR_OFFSET
) && (OffSet
< ATTEMPT_CHAR_REVERSE_SECRET_VAR_OFFSET
)) {
1707 if (Attempt
->AuthConfigData
.CHAP
.CHAPType
== ISCSI_CHAP_MUTUAL
) {
1708 UnicodeStrToAsciiStrS (
1709 IfrNvData
->Keyword
[Index
].ISCSIReverseChapUsername
,
1710 Attempt
->AuthConfigData
.CHAP
.ReverseCHAPName
,
1711 ISCSI_CHAP_NAME_STORAGE
1713 if (Attempt
->SessionConfigData
.Enabled
!= ISCSI_DISABLED
) {
1714 if (IfrNvData
->Keyword
[Index
].ISCSIReverseChapUsername
[0] == L
'\0') {
1716 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1718 L
"Reverse CHAP Name is invalid!",
1721 return EFI_INVALID_PARAMETER
;
1726 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1728 L
"Invalid Configuration, Check value of AuthenticationType or Chap Type!",
1731 return EFI_INVALID_PARAMETER
;
1733 } else if (OffSet
>= ATTEMPT_CHAR_REVERSE_SECRET_VAR_OFFSET
) {
1734 if (Attempt
->AuthConfigData
.CHAP
.CHAPType
== ISCSI_CHAP_MUTUAL
) {
1735 ReverseChapSecretLen
= (UINT8
)StrLen (IfrNvData
->Keyword
[Index
].ISCSIReverseChapSecret
);
1736 UnicodeStrToAsciiStrS (
1737 IfrNvData
->Keyword
[Index
].ISCSIReverseChapSecret
,
1738 Attempt
->AuthConfigData
.CHAP
.ReverseCHAPSecret
,
1739 ISCSI_CHAP_SECRET_STORAGE
1742 if (Attempt
->SessionConfigData
.Enabled
!= ISCSI_DISABLED
) {
1743 if ((ReverseChapSecretLen
< ISCSI_CHAP_SECRET_MIN_LEN
) || (ReverseChapSecretLen
> ISCSI_CHAP_SECRET_MAX_LEN
)) {
1745 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1747 L
"The Reverse CHAP Secret minimum length is 12 bytes and the maximum length is 16 bytes.",
1750 return EFI_INVALID_PARAMETER
;
1755 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1757 L
"Invalid Configuration, Check value of AuthenticationType or Chap Type!",
1760 return EFI_INVALID_PARAMETER
;
1766 // Record the user configuration information in NVR.
1768 ASSERT (Attempt
!= NULL
);
1769 UnicodeSPrint (mPrivate
->PortString
, (UINTN
)ISCSI_NAME_IFR_MAX_SIZE
, L
"Attempt %d", Attempt
->AttemptConfigIndex
);
1770 return gRT
->SetVariable (
1771 mPrivate
->PortString
,
1772 &gEfiIScsiInitiatorNameProtocolGuid
,
1773 ISCSI_CONFIG_VAR_ATTR
,
1774 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA
),
1780 Create Hii Extend Label OpCode as the start opcode and end opcode. It is
1783 @param[in] StartLabelNumber The number of start label.
1784 @param[out] StartOpCodeHandle Points to the start opcode handle.
1785 @param[out] StartLabel Points to the created start opcode.
1786 @param[out] EndOpCodeHandle Points to the end opcode handle.
1787 @param[out] EndLabel Points to the created end opcode.
1789 @retval EFI_OUT_OF_RESOURCES Do not have sufficient resource to finish this
1791 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
1792 @retval EFI_SUCCESS The operation is completed successfully.
1797 IN UINT16 StartLabelNumber
,
1798 OUT VOID
**StartOpCodeHandle
,
1799 OUT EFI_IFR_GUID_LABEL
**StartLabel
,
1800 OUT VOID
**EndOpCodeHandle
,
1801 OUT EFI_IFR_GUID_LABEL
**EndLabel
1805 EFI_IFR_GUID_LABEL
*InternalStartLabel
;
1806 EFI_IFR_GUID_LABEL
*InternalEndLabel
;
1808 if ((StartOpCodeHandle
== NULL
) || (StartLabel
== NULL
) || (EndOpCodeHandle
== NULL
) || (EndLabel
== NULL
)) {
1809 return EFI_INVALID_PARAMETER
;
1812 *StartOpCodeHandle
= NULL
;
1813 *EndOpCodeHandle
= NULL
;
1814 Status
= EFI_OUT_OF_RESOURCES
;
1817 // Initialize the container for dynamic opcodes.
1819 *StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
1820 if (*StartOpCodeHandle
== NULL
) {
1824 *EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
1825 if (*EndOpCodeHandle
== NULL
) {
1830 // Create Hii Extend Label OpCode as the start opcode.
1832 InternalStartLabel
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode (
1836 sizeof (EFI_IFR_GUID_LABEL
)
1838 if (InternalStartLabel
== NULL
) {
1842 InternalStartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
1843 InternalStartLabel
->Number
= StartLabelNumber
;
1846 // Create Hii Extend Label OpCode as the end opcode.
1848 InternalEndLabel
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode (
1852 sizeof (EFI_IFR_GUID_LABEL
)
1854 if (InternalEndLabel
== NULL
) {
1858 InternalEndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
1859 InternalEndLabel
->Number
= LABEL_END
;
1861 *StartLabel
= InternalStartLabel
;
1862 *EndLabel
= InternalEndLabel
;
1868 if (*StartOpCodeHandle
!= NULL
) {
1869 HiiFreeOpCodeHandle (*StartOpCodeHandle
);
1872 if (*EndOpCodeHandle
!= NULL
) {
1873 HiiFreeOpCodeHandle (*EndOpCodeHandle
);
1880 Update the MAIN form to display the configured attempts.
1884 IScsiConfigUpdateAttempt (
1889 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
1890 VOID
*StartOpCodeHandle
;
1891 EFI_IFR_GUID_LABEL
*StartLabel
;
1892 VOID
*EndOpCodeHandle
;
1893 EFI_IFR_GUID_LABEL
*EndLabel
;
1896 Status
= IScsiCreateOpCode (
1897 ATTEMPT_ENTRY_LABEL
,
1903 if (EFI_ERROR (Status
)) {
1907 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
1908 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
1909 if (AttemptConfigData
->Actived
== ISCSI_ACTIVE_ENABLED
) {
1911 // Update Attempt Help Info.
1913 UnicodeSPrint (mPrivate
->PortString
, (UINTN
)ISCSI_NAME_IFR_MAX_SIZE
, L
"Attempt %d", (UINTN
)AttemptConfigData
->AttemptConfigIndex
);
1914 AttemptConfigData
->AttemptTitleToken
= HiiSetString (
1915 mCallbackInfo
->RegisteredHandle
,
1917 mPrivate
->PortString
,
1920 if (AttemptConfigData
->AttemptTitleToken
== 0) {
1924 HiiCreateGotoOpCode (
1925 StartOpCodeHandle
, // Container for dynamic created opcodes
1926 FORMID_ATTEMPT_FORM
, // Form ID
1927 AttemptConfigData
->AttemptTitleToken
, // Prompt text
1928 AttemptConfigData
->AttemptTitleHelpToken
, // Help text
1929 EFI_IFR_FLAG_CALLBACK
, // Question flag
1930 (UINT16
)(KEY_ATTEMPT_ENTRY_BASE
+ AttemptConfigData
->AttemptConfigIndex
) // Question ID
1936 mCallbackInfo
->RegisteredHandle
, // HII handle
1937 &gIScsiConfigGuid
, // Formset GUID
1938 FORMID_MAIN_FORM
, // Form ID
1939 StartOpCodeHandle
, // Label for where to insert opcodes
1940 EndOpCodeHandle
// Replace data
1943 HiiFreeOpCodeHandle (StartOpCodeHandle
);
1944 HiiFreeOpCodeHandle (EndOpCodeHandle
);
1948 Callback function when user presses "Add an Attempt".
1950 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
1952 @retval EFI_SUCCESS The operation is completed successfully.
1956 IScsiConfigAddAttempt (
1961 ISCSI_NIC_INFO
*NicInfo
;
1962 EFI_STRING_ID PortTitleToken
;
1963 EFI_STRING_ID PortTitleHelpToken
;
1964 CHAR16 MacString
[ISCSI_MAX_MAC_STRING_LEN
];
1966 VOID
*StartOpCodeHandle
;
1967 EFI_IFR_GUID_LABEL
*StartLabel
;
1968 VOID
*EndOpCodeHandle
;
1969 EFI_IFR_GUID_LABEL
*EndLabel
;
1971 Status
= IScsiCreateOpCode (
1978 if (EFI_ERROR (Status
)) {
1983 // Ask user to select a MAC for this attempt.
1985 NET_LIST_FOR_EACH (Entry
, &mPrivate
->NicInfoList
) {
1986 NicInfo
= NET_LIST_USER_STRUCT (Entry
, ISCSI_NIC_INFO
, Link
);
1988 &NicInfo
->PermanentAddress
,
1989 NicInfo
->HwAddressSize
,
1994 UnicodeSPrint (mPrivate
->PortString
, (UINTN
)ISCSI_NAME_IFR_MAX_SIZE
, L
"MAC %s", MacString
);
1995 PortTitleToken
= HiiSetString (
1996 mCallbackInfo
->RegisteredHandle
,
1998 mPrivate
->PortString
,
2001 if (PortTitleToken
== 0) {
2002 Status
= EFI_INVALID_PARAMETER
;
2007 mPrivate
->PortString
,
2008 (UINTN
)ISCSI_NAME_IFR_MAX_SIZE
,
2009 L
"PFA: Bus %d | Dev %d | Func %d",
2011 NicInfo
->DeviceNumber
,
2012 NicInfo
->FunctionNumber
2014 PortTitleHelpToken
= HiiSetString (mCallbackInfo
->RegisteredHandle
, 0, mPrivate
->PortString
, NULL
);
2015 if (PortTitleHelpToken
== 0) {
2016 Status
= EFI_INVALID_PARAMETER
;
2020 HiiCreateGotoOpCode (
2021 StartOpCodeHandle
, // Container for dynamic created opcodes
2022 FORMID_ATTEMPT_FORM
,
2025 EFI_IFR_FLAG_CALLBACK
, // Question flag
2026 (UINT16
)(KEY_MAC_ENTRY_BASE
+ NicInfo
->NicIndex
)
2030 Status
= HiiUpdateForm (
2031 mCallbackInfo
->RegisteredHandle
, // HII handle
2032 &gIScsiConfigGuid
, // Formset GUID
2033 FORMID_MAC_FORM
, // Form ID
2034 StartOpCodeHandle
, // Label for where to insert opcodes
2035 EndOpCodeHandle
// Replace data
2039 HiiFreeOpCodeHandle (StartOpCodeHandle
);
2040 HiiFreeOpCodeHandle (EndOpCodeHandle
);
2046 Add the attempts by keyword 'iSCSIAddAttempts', you can use this keyword with
2047 value 'attempt:1 attempt:2' etc to add one or more attempts once. This is different
2048 with IScsiConfigAddAttempt function which is used to add attempt by UI configuration.
2050 @param[in] AttemptList The new attempt List will be added.
2052 @retval EFI_SUCCESS The operation to add attempt list successfully.
2053 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
2054 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
2055 @retval EFI_OUT_OF_RESOURCES Fail to finish the operation due to lack of
2060 IScsiConfigAddAttemptsByKeywords (
2061 IN UINT8
*AttemptList
2068 UINT8
*AttemptConfigOrder
;
2069 UINTN AttemptConfigOrderSize
;
2070 UINT8
*AttemptConfigOrderTmp
;
2071 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
2072 ISCSI_NIC_INFO
*NicInfo
;
2073 CHAR16 MacString
[ISCSI_MAX_MAC_STRING_LEN
];
2074 CHAR16 IScsiMode
[64];
2078 Nic
= mPrivate
->CurrentNic
;
2079 NicInfo
= IScsiGetNicInfoByIndex (Nic
);
2080 if (NicInfo
== NULL
) {
2081 return EFI_NOT_FOUND
;
2085 // The MAC info will be recorded in Config Data.
2088 &NicInfo
->PermanentAddress
,
2089 NicInfo
->HwAddressSize
,
2094 for (Index
= 0; Index
< PcdGet8 (PcdMaxIScsiAttemptNumber
); Index
++) {
2095 if (AttemptList
[Index
] == 0) {
2102 Number
= AttemptList
[Index
];
2105 mPrivate
->PortString
,
2106 (UINTN
)ISCSI_NAME_IFR_MAX_SIZE
,
2112 mPrivate
->PortString
,
2113 &gEfiIScsiInitiatorNameProtocolGuid
,
2114 (VOID
**)&AttemptConfigData
,
2117 if ((AttemptConfigData
== NULL
) || (AttemptConfigData
->Actived
== ISCSI_ACTIVE_ENABLED
)) {
2118 return EFI_INVALID_PARAMETER
;
2121 AttemptConfigData
->Actived
= ISCSI_ACTIVE_ENABLED
;
2122 AttemptConfigData
->NicIndex
= NicInfo
->NicIndex
;
2123 UnicodeStrToAsciiStrS (MacString
, AttemptConfigData
->MacString
, ISCSI_MAX_MAC_STRING_LEN
);
2126 // Generate OUI-format ISID based on MAC address.
2128 CopyMem (AttemptConfigData
->SessionConfigData
.IsId
, &NicInfo
->PermanentAddress
, 6);
2129 AttemptConfigData
->SessionConfigData
.IsId
[0] =
2130 (UINT8
)(AttemptConfigData
->SessionConfigData
.IsId
[0] & 0x3F);
2133 // Configure the iSCSI Mode and IpMode to default.
2134 // Add Attempt Help Info.
2136 UnicodeSPrint (IScsiMode
, 64, L
"Disabled");
2137 UnicodeSPrint (IpMode
, 64, L
"IP4");
2139 mPrivate
->PortString
,
2140 (UINTN
)ISCSI_NAME_IFR_MAX_SIZE
,
2141 L
"MAC: %s, PFA: Bus %d | Dev %d | Func %d, iSCSI mode: %s, IP version: %s",
2144 NicInfo
->DeviceNumber
,
2145 NicInfo
->FunctionNumber
,
2150 AttemptConfigData
->AttemptTitleHelpToken
= HiiSetString (
2151 mCallbackInfo
->RegisteredHandle
,
2153 mPrivate
->PortString
,
2156 if (AttemptConfigData
->AttemptTitleHelpToken
== 0) {
2157 return EFI_OUT_OF_RESOURCES
;
2161 // Get current Attempt order and number.
2163 AttemptConfigOrder
= IScsiGetVariableAndSize (
2166 &AttemptConfigOrderSize
2168 TotalNumber
= AttemptConfigOrderSize
/ sizeof (UINT8
);
2172 // Append the new created attempt order to the end.
2174 AttemptConfigOrderTmp
= AllocateZeroPool (TotalNumber
* sizeof (UINT8
));
2175 if (AttemptConfigOrderTmp
== NULL
) {
2176 if (AttemptConfigOrder
!= NULL
) {
2177 FreePool (AttemptConfigOrder
);
2180 return EFI_OUT_OF_RESOURCES
;
2183 if (AttemptConfigOrder
!= NULL
) {
2184 CopyMem (AttemptConfigOrderTmp
, AttemptConfigOrder
, AttemptConfigOrderSize
);
2185 FreePool (AttemptConfigOrder
);
2188 AttemptConfigOrderTmp
[TotalNumber
- 1] = Number
;
2189 AttemptConfigOrder
= AttemptConfigOrderTmp
;
2190 AttemptConfigOrderSize
= TotalNumber
* sizeof (UINT8
);
2192 Status
= gRT
->SetVariable (
2195 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
2196 AttemptConfigOrderSize
,
2199 FreePool (AttemptConfigOrder
);
2200 if (EFI_ERROR (Status
)) {
2205 // Record the attempt in global link list.
2207 InsertTailList (&mPrivate
->AttemptConfigs
, &AttemptConfigData
->Link
);
2208 mPrivate
->AttemptCount
++;
2209 UnicodeSPrint (mPrivate
->PortString
, (UINTN
)ISCSI_NAME_IFR_MAX_SIZE
, L
"Attempt %d", AttemptConfigData
->AttemptConfigIndex
);
2211 mPrivate
->PortString
,
2212 &gEfiIScsiInitiatorNameProtocolGuid
,
2213 ISCSI_CONFIG_VAR_ATTR
,
2214 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA
),
2223 Callback function when user presses "Commit Changes and Exit" in Delete Attempts or Delete Attempts by Keyword.
2225 @param[in] IfrNvData The IFR NV data.
2227 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
2228 @retval EFI_SUCCESS The operation is completed successfully.
2229 @retval EFI_ABORTED This operation is aborted cause of error
2231 @retval EFI_OUT_OF_RESOURCES Fail to finish the operation due to lack of
2236 IScsiConfigDeleteAttempts (
2237 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
2243 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
2244 UINT8
*AttemptConfigOrder
;
2245 UINTN AttemptConfigOrderSize
;
2246 UINT8
*AttemptNewOrder
;
2247 UINT8 AttemptConfigIndex
;
2252 LIST_ENTRY
*NextEntry
;
2253 ISCSI_SESSION_CONFIG_NVDATA
*ConfigData
;
2257 AttemptConfigOrder
= IScsiGetVariableAndSize (
2260 &AttemptConfigOrderSize
2262 if ((AttemptConfigOrder
== NULL
) || (AttemptConfigOrderSize
== 0)) {
2263 return EFI_NOT_FOUND
;
2266 AttemptNewOrder
= AllocateZeroPool (AttemptConfigOrderSize
);
2267 if (AttemptNewOrder
== NULL
) {
2268 Status
= EFI_OUT_OF_RESOURCES
;
2272 Total
= AttemptConfigOrderSize
/ sizeof (UINT8
);
2275 NET_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &mPrivate
->AttemptConfigs
) {
2276 if (IfrNvData
->DeleteAttemptList
[Index
] == 0) {
2282 // Delete the attempt.
2285 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
2288 // Remove this attempt from UI configured attempt list.
2290 RemoveEntryList (&AttemptConfigData
->Link
);
2291 mPrivate
->AttemptCount
--;
2293 if (AttemptConfigData
->SessionConfigData
.Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
2294 if (mPrivate
->MpioCount
< 1) {
2295 Status
= EFI_ABORTED
;
2300 // No more attempt is enabled for MPIO. Transit the iSCSI mode to single path.
2302 if (--mPrivate
->MpioCount
== 0) {
2303 mPrivate
->EnableMpio
= FALSE
;
2305 } else if (AttemptConfigData
->SessionConfigData
.Enabled
== ISCSI_ENABLED
) {
2306 if (mPrivate
->SinglePathCount
< 1) {
2307 Status
= EFI_ABORTED
;
2311 mPrivate
->SinglePathCount
--;
2314 AttemptConfigIndex
= AttemptConfigData
->AttemptConfigIndex
;
2315 FreePool (AttemptConfigData
);
2318 // Create a new Attempt
2320 AttemptConfigData
= AllocateZeroPool (sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA
));
2321 if (AttemptConfigData
== NULL
) {
2322 return EFI_OUT_OF_RESOURCES
;
2325 ConfigData
= &AttemptConfigData
->SessionConfigData
;
2326 ConfigData
->TargetPort
= ISCSI_WELL_KNOWN_PORT
;
2327 ConfigData
->ConnectTimeout
= CONNECT_DEFAULT_TIMEOUT
;
2328 ConfigData
->ConnectRetryCount
= CONNECT_MIN_RETRY
;
2330 AttemptConfigData
->AuthenticationType
= ISCSI_AUTH_TYPE_CHAP
;
2331 AttemptConfigData
->AuthConfigData
.CHAP
.CHAPType
= ISCSI_CHAP_UNI
;
2333 // Configure the Attempt index and set variable.
2335 AttemptConfigData
->AttemptConfigIndex
= AttemptConfigIndex
;
2338 // Set the attempt name to default.
2341 mPrivate
->PortString
,
2342 (UINTN
)ISCSI_NAME_IFR_MAX_SIZE
,
2344 (UINTN
)AttemptConfigData
->AttemptConfigIndex
2346 UnicodeStrToAsciiStrS (mPrivate
->PortString
, AttemptConfigData
->AttemptName
, ATTEMPT_NAME_SIZE
);
2348 mPrivate
->PortString
,
2349 &gEfiIScsiInitiatorNameProtocolGuid
,
2350 ISCSI_CONFIG_VAR_ATTR
,
2351 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA
),
2356 // Mark the attempt order in NVR to be deleted - 0.
2358 for (NewIndex
= 0; NewIndex
< Total
; NewIndex
++) {
2359 if (AttemptConfigOrder
[NewIndex
] == AttemptConfigData
->AttemptConfigIndex
) {
2360 AttemptConfigOrder
[NewIndex
] = 0;
2366 if (mCallbackInfo
->Current
== AttemptConfigData
) {
2367 mCallbackInfo
->Current
= NULL
;
2370 FreePool (AttemptConfigData
);
2373 // Check next Attempt.
2379 // Construct AttemptNewOrder.
2381 for (Index
= 0, NewIndex
= 0; Index
< Total
; Index
++) {
2382 if (AttemptConfigOrder
[Index
] != 0) {
2383 AttemptNewOrder
[NewIndex
] = AttemptConfigOrder
[Index
];
2388 Attribute
= EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_NON_VOLATILE
;
2391 // Update AttemptOrder in NVR.
2393 Status
= gRT
->SetVariable (
2397 NewTotal
* sizeof (UINT8
),
2402 if (AttemptConfigOrder
!= NULL
) {
2403 FreePool (AttemptConfigOrder
);
2406 if (AttemptNewOrder
!= NULL
) {
2407 FreePool (AttemptNewOrder
);
2414 Callback function when user presses "Delete Attempts".
2416 @param[in] IfrNvData The IFR nv data.
2418 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
2419 @retval EFI_BUFFER_TOO_SMALL The buffer in UpdateData is too small.
2420 @retval EFI_SUCCESS The operation is completed successfully.
2424 IScsiConfigDisplayDeleteAttempts (
2425 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
2428 UINT8
*AttemptConfigOrder
;
2429 UINTN AttemptConfigOrderSize
;
2431 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
2433 VOID
*StartOpCodeHandle
;
2434 EFI_IFR_GUID_LABEL
*StartLabel
;
2435 VOID
*EndOpCodeHandle
;
2436 EFI_IFR_GUID_LABEL
*EndLabel
;
2439 Status
= IScsiCreateOpCode (
2446 if (EFI_ERROR (Status
)) {
2450 AttemptConfigOrder
= IScsiGetVariableAndSize (
2453 &AttemptConfigOrderSize
2455 if (AttemptConfigOrder
!= NULL
) {
2457 // Create the check box opcode to be deleted.
2461 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
2462 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
2463 IfrNvData
->DeleteAttemptList
[Index
] = 0x00;
2465 HiiCreateCheckBoxOpCode (
2467 (EFI_QUESTION_ID
)(ATTEMPT_DEL_QUESTION_ID
+ Index
),
2468 CONFIGURATION_VARSTORE_ID
,
2469 (UINT16
)(ATTEMPT_DEL_VAR_OFFSET
+ Index
),
2470 AttemptConfigData
->AttemptTitleToken
,
2471 AttemptConfigData
->AttemptTitleHelpToken
,
2479 if (Index
== ISCSI_MAX_ATTEMPTS_NUM
) {
2484 FreePool (AttemptConfigOrder
);
2487 Status
= HiiUpdateForm (
2488 mCallbackInfo
->RegisteredHandle
, // HII handle
2489 &gIScsiConfigGuid
, // Formset GUID
2490 FORMID_DELETE_FORM
, // Form ID
2491 StartOpCodeHandle
, // Label for where to insert opcodes
2492 EndOpCodeHandle
// Replace data
2495 HiiFreeOpCodeHandle (StartOpCodeHandle
);
2496 HiiFreeOpCodeHandle (EndOpCodeHandle
);
2502 Callback function when user presses "Change Attempt Order".
2504 @retval EFI_INVALID_PARAMETER Any parameter is invalid.
2505 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
2507 @retval EFI_SUCCESS The operation is completed successfully.
2511 IScsiConfigDisplayOrderAttempts (
2518 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
2519 VOID
*StartOpCodeHandle
;
2520 EFI_IFR_GUID_LABEL
*StartLabel
;
2521 VOID
*EndOpCodeHandle
;
2522 EFI_IFR_GUID_LABEL
*EndLabel
;
2523 VOID
*OptionsOpCodeHandle
;
2525 Status
= IScsiCreateOpCode (
2532 if (EFI_ERROR (Status
)) {
2536 ASSERT (StartOpCodeHandle
!= NULL
);
2538 OptionsOpCodeHandle
= NULL
;
2541 // If no attempt to be ordered, update the original form and exit.
2543 if (mPrivate
->AttemptCount
== 0) {
2548 // Create Option OpCode.
2550 OptionsOpCodeHandle
= HiiAllocateOpCodeHandle ();
2551 if (OptionsOpCodeHandle
== NULL
) {
2552 Status
= EFI_OUT_OF_RESOURCES
;
2558 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
2559 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
2560 HiiCreateOneOfOptionOpCode (
2561 OptionsOpCodeHandle
,
2562 AttemptConfigData
->AttemptTitleToken
,
2564 EFI_IFR_NUMERIC_SIZE_1
,
2565 AttemptConfigData
->AttemptConfigIndex
2570 ASSERT (Index
== mPrivate
->AttemptCount
);
2572 HiiCreateOrderedListOpCode (
2573 StartOpCodeHandle
, // Container for dynamic created opcodes
2574 DYNAMIC_ORDERED_LIST_QUESTION_ID
, // Question ID
2575 CONFIGURATION_VARSTORE_ID
, // VarStore ID
2576 DYNAMIC_ORDERED_LIST_VAR_OFFSET
, // Offset in Buffer Storage
2577 STRING_TOKEN (STR_ORDER_ATTEMPT_ENTRY
), // Question prompt text
2578 STRING_TOKEN (STR_ORDER_ATTEMPT_ENTRY
), // Question help text
2580 EFI_IFR_UNIQUE_SET
, // Ordered list flag, e.g. EFI_IFR_UNIQUE_SET
2581 EFI_IFR_NUMERIC_SIZE_1
, // Data type of Question value
2582 ISCSI_MAX_ATTEMPTS_NUM
, // Maximum container
2583 OptionsOpCodeHandle
, // Option Opcode list
2584 NULL
// Default Opcode is NULL
2588 Status
= HiiUpdateForm (
2589 mCallbackInfo
->RegisteredHandle
, // HII handle
2590 &gIScsiConfigGuid
, // Formset GUID
2591 FORMID_ORDER_FORM
, // Form ID
2592 StartOpCodeHandle
, // Label for where to insert opcodes
2593 EndOpCodeHandle
// Replace data
2597 HiiFreeOpCodeHandle (StartOpCodeHandle
);
2598 HiiFreeOpCodeHandle (EndOpCodeHandle
);
2599 if (OptionsOpCodeHandle
!= NULL
) {
2600 HiiFreeOpCodeHandle (OptionsOpCodeHandle
);
2607 Callback function when user presses "Commit Changes and Exit" in Change Attempt Order or Change Attempt Order by Keyword.
2609 @param[in] IfrNvData The IFR nv data.
2611 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
2613 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
2614 @retval EFI_SUCCESS The operation is completed successfully.
2618 IScsiConfigOrderAttempts (
2619 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
2625 UINT8 AttemptConfigIndex
;
2626 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
2627 UINT8
*AttemptConfigOrder
;
2628 UINT8
*AttemptConfigOrderTmp
;
2629 UINTN AttemptConfigOrderSize
;
2631 AttemptConfigOrder
= IScsiGetVariableAndSize (
2634 &AttemptConfigOrderSize
2636 if (AttemptConfigOrder
== NULL
) {
2637 return EFI_NOT_FOUND
;
2640 AttemptConfigOrderTmp
= AllocateZeroPool (AttemptConfigOrderSize
);
2641 if (AttemptConfigOrderTmp
== NULL
) {
2642 Status
= EFI_OUT_OF_RESOURCES
;
2646 for (Index
= 0; Index
< ISCSI_MAX_ATTEMPTS_NUM
; Index
++) {
2648 // The real content ends with 0.
2650 if (IfrNvData
->DynamicOrderedList
[Index
] == 0) {
2654 AttemptConfigIndex
= IfrNvData
->DynamicOrderedList
[Index
];
2655 AttemptConfigData
= IScsiConfigGetAttemptByConfigIndex (AttemptConfigIndex
);
2656 if (AttemptConfigData
== NULL
) {
2657 Status
= EFI_NOT_FOUND
;
2662 // Reorder the Attempt List.
2664 RemoveEntryList (&AttemptConfigData
->Link
);
2665 InsertTailList (&mPrivate
->AttemptConfigs
, &AttemptConfigData
->Link
);
2667 AttemptConfigOrderTmp
[Index
] = AttemptConfigIndex
;
2670 // Mark it to be deleted - 0.
2672 for (Indexj
= 0; Indexj
< AttemptConfigOrderSize
/ sizeof (UINT8
); Indexj
++) {
2673 if (AttemptConfigOrder
[Indexj
] == AttemptConfigIndex
) {
2674 AttemptConfigOrder
[Indexj
] = 0;
2681 // Adjust the attempt order in NVR.
2683 for ( ; Index
< AttemptConfigOrderSize
/ sizeof (UINT8
); Index
++) {
2684 for (Indexj
= 0; Indexj
< AttemptConfigOrderSize
/ sizeof (UINT8
); Indexj
++) {
2685 if (AttemptConfigOrder
[Indexj
] != 0) {
2686 AttemptConfigOrderTmp
[Index
] = AttemptConfigOrder
[Indexj
];
2687 AttemptConfigOrder
[Indexj
] = 0;
2693 Status
= gRT
->SetVariable (
2696 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
2697 AttemptConfigOrderSize
,
2698 AttemptConfigOrderTmp
2702 if (AttemptConfigOrderTmp
!= NULL
) {
2703 FreePool (AttemptConfigOrderTmp
);
2706 FreePool (AttemptConfigOrder
);
2711 Callback function when a user presses "Attempt *" or when a user selects a NIC to
2712 create the new attempt.
2714 @param[in] KeyValue A unique value which is sent to the original
2715 exporting driver so that it can identify the type
2717 @param[in] IfrNvData The IFR nv data.
2719 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
2721 @retval EFI_NOT_FOUND Cannot find the corresponding variable.
2722 @retval EFI_UNSUPPORTED Can not create more attempts.
2723 @retval EFI_SUCCESS The operation is completed successfully.
2727 IScsiConfigProcessDefault (
2728 IN EFI_QUESTION_ID KeyValue
,
2729 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
2733 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
2734 UINT8 CurrentAttemptConfigIndex
;
2735 ISCSI_NIC_INFO
*NicInfo
;
2737 CHAR16 MacString
[ISCSI_MAX_MAC_STRING_LEN
];
2738 UINT8
*AttemptConfigOrder
;
2739 UINTN AttemptConfigOrderSize
;
2743 AttemptConfigData
= NULL
;
2745 // Is User creating a new attempt?
2749 if ((KeyValue
>= KEY_MAC_ENTRY_BASE
) &&
2750 (KeyValue
<= (UINT16
)(mPrivate
->MaxNic
+ KEY_MAC_ENTRY_BASE
)))
2753 // User has pressed "Add an Attempt" and then selects a NIC.
2756 } else if ((KeyValue
>= KEY_ATTEMPT_ENTRY_BASE
) &&
2757 (KeyValue
< (ISCSI_MAX_ATTEMPTS_NUM
+ KEY_ATTEMPT_ENTRY_BASE
)))
2760 // User has pressed "Attempt *".
2765 // Don't process anything.
2772 // Determine which NIC user has selected for the new created attempt.
2774 NicIndex
= (UINT8
)(KeyValue
- KEY_MAC_ENTRY_BASE
);
2775 NicInfo
= IScsiGetNicInfoByIndex (NicIndex
);
2776 if (NicInfo
== NULL
) {
2777 return EFI_NOT_FOUND
;
2781 // Create an attempt following the initialized attempt order.
2783 AttemptConfigOrder
= IScsiGetVariableAndSize (
2784 L
"InitialAttemptOrder",
2786 &AttemptConfigOrderSize
2789 if (AttemptConfigOrder
== NULL
) {
2790 return EFI_NOT_FOUND
;
2793 for (Index
= 0; Index
< AttemptConfigOrderSize
/ sizeof (UINT8
); Index
++) {
2795 mPrivate
->PortString
,
2796 (UINTN
)ISCSI_NAME_IFR_MAX_SIZE
,
2798 (UINTN
)AttemptConfigOrder
[Index
]
2801 mPrivate
->PortString
,
2802 &gEfiIScsiInitiatorNameProtocolGuid
,
2803 (VOID
**)&AttemptConfigData
,
2806 if ((AttemptConfigData
== NULL
) || (AttemptConfigData
->Actived
== ISCSI_ACTIVE_ENABLED
)) {
2813 if (Index
> PcdGet8 (PcdMaxIScsiAttemptNumber
)) {
2815 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2817 L
"Can not create more attempts, Please configure the PcdMaxIScsiAttemptNumber if needed!",
2820 return EFI_UNSUPPORTED
;
2823 if (AttemptConfigOrder
!= NULL
) {
2824 FreePool (AttemptConfigOrder
);
2828 // Record the MAC info in Config Data.
2831 &NicInfo
->PermanentAddress
,
2832 NicInfo
->HwAddressSize
,
2837 ASSERT (AttemptConfigData
!= NULL
);
2838 UnicodeStrToAsciiStrS (MacString
, AttemptConfigData
->MacString
, sizeof (AttemptConfigData
->MacString
));
2839 AttemptConfigData
->NicIndex
= NicIndex
;
2840 AttemptConfigData
->Actived
= ISCSI_ACTIVE_ENABLED
;
2843 // Generate OUI-format ISID based on MAC address.
2845 CopyMem (AttemptConfigData
->SessionConfigData
.IsId
, &NicInfo
->PermanentAddress
, 6);
2846 AttemptConfigData
->SessionConfigData
.IsId
[0] =
2847 (UINT8
)(AttemptConfigData
->SessionConfigData
.IsId
[0] & 0x3F);
2850 // Add the help info for the new attempt.
2853 mPrivate
->PortString
,
2854 (UINTN
)ISCSI_NAME_IFR_MAX_SIZE
,
2855 L
"MAC: %s, PFA: Bus %d | Dev %d | Func %d",
2858 NicInfo
->DeviceNumber
,
2859 NicInfo
->FunctionNumber
2862 AttemptConfigData
->AttemptTitleHelpToken
= HiiSetString (
2863 mCallbackInfo
->RegisteredHandle
,
2865 mPrivate
->PortString
,
2868 if (AttemptConfigData
->AttemptTitleHelpToken
== 0) {
2869 FreePool (AttemptConfigData
);
2870 return EFI_OUT_OF_RESOURCES
;
2874 // Determine which Attempt user has selected to configure.
2875 // Get the attempt configuration data.
2877 CurrentAttemptConfigIndex
= (UINT8
)(KeyValue
- KEY_ATTEMPT_ENTRY_BASE
);
2879 AttemptConfigData
= IScsiConfigGetAttemptByConfigIndex (CurrentAttemptConfigIndex
);
2880 if (AttemptConfigData
== NULL
) {
2881 DEBUG ((DEBUG_ERROR
, "Corresponding configuration data can not be retrieved!\n"));
2882 return EFI_NOT_FOUND
;
2887 // Clear the old IFR data to avoid sharing it with other attempts.
2889 if (IfrNvData
->AuthenticationType
== ISCSI_AUTH_TYPE_CHAP
) {
2890 ZeroMem (IfrNvData
->CHAPName
, sizeof (IfrNvData
->CHAPName
));
2891 ZeroMem (IfrNvData
->CHAPSecret
, sizeof (IfrNvData
->CHAPSecret
));
2892 ZeroMem (IfrNvData
->ReverseCHAPName
, sizeof (IfrNvData
->ReverseCHAPName
));
2893 ZeroMem (IfrNvData
->ReverseCHAPSecret
, sizeof (IfrNvData
->ReverseCHAPSecret
));
2896 IScsiConvertAttemptConfigDataToIfrNvData (AttemptConfigData
, IfrNvData
);
2899 // Update current attempt to be a new created attempt or an existing attempt.
2901 mCallbackInfo
->Current
= AttemptConfigData
;
2908 This function allows the caller to request the current
2909 configuration for one or more named elements. The resulting
2910 string is in <ConfigAltResp> format. Also, any and all alternative
2911 configuration strings shall be appended to the end of the
2912 current configuration string. If they are, they must appear
2913 after the current configuration. They must contain the same
2914 routing (GUID, NAME, PATH) as the current configuration string.
2915 They must have an additional description indicating the type of
2916 alternative configuration the string represents,
2917 "ALTCFG=<StringToken>". That <StringToken> (when
2918 converted from Hex UNICODE to binary) is a reference to a
2919 string in the associated string pack.
2921 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
2923 @param[in] Request A null-terminated Unicode string in
2924 <ConfigRequest> format. Note that this
2925 includes the routing information as well as
2926 the configurable name / value pairs. It is
2927 invalid for this string to be in
2928 <MultiConfigRequest> format.
2930 @param[out] Progress On return, points to a character in the
2931 Request string. Points to the string's null
2932 terminator if request was successful. Points
2933 to the most recent "&" before the first
2934 failing name / value pair (or the beginning
2935 of the string if the failure is in the first
2936 name / value pair) if the request was not successful.
2938 @param[out] Results A null-terminated Unicode string in
2939 <ConfigAltResp> format which has all values
2940 filled in for the names in the Request string.
2941 String to be allocated by the called function.
2943 @retval EFI_SUCCESS The Results string is filled with the
2944 values corresponding to all requested
2947 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
2948 parts of the results that must be
2949 stored awaiting possible future
2952 @retval EFI_INVALID_PARAMETER For example, passing in a NULL
2953 for the Request parameter
2954 would result in this type of
2955 error. In this case, the
2956 Progress parameter would be
2959 @retval EFI_NOT_FOUND Routing data doesn't match any
2960 known driver. Progress set to the
2961 first character in the routing header.
2962 Note: There is no requirement that the
2963 driver validate the routing data. It
2964 must skip the <ConfigHdr> in order to
2967 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set
2968 to most recent "&" before the
2969 error or the beginning of the
2972 @retval EFI_INVALID_PARAMETER Unknown name. Progress points
2973 to the & before the name in
2979 IScsiFormExtractConfig (
2980 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
2981 IN CONST EFI_STRING Request
,
2982 OUT EFI_STRING
*Progress
,
2983 OUT EFI_STRING
*Results
2987 CHAR8
*InitiatorName
;
2989 ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
;
2990 ISCSI_FORM_CALLBACK_INFO
*Private
;
2991 EFI_STRING ConfigRequestHdr
;
2992 EFI_STRING ConfigRequest
;
2993 BOOLEAN AllocatedRequest
;
2996 if ((This
== NULL
) || (Progress
== NULL
) || (Results
== NULL
)) {
2997 return EFI_INVALID_PARAMETER
;
3000 *Progress
= Request
;
3001 if ((Request
!= NULL
) && !HiiIsConfigHdrMatch (Request
, &gIScsiConfigGuid
, mVendorStorageName
)) {
3002 return EFI_NOT_FOUND
;
3005 ConfigRequestHdr
= NULL
;
3006 ConfigRequest
= NULL
;
3007 AllocatedRequest
= FALSE
;
3010 Private
= ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This
);
3011 IfrNvData
= AllocateZeroPool (sizeof (ISCSI_CONFIG_IFR_NVDATA
));
3012 if (IfrNvData
== NULL
) {
3013 return EFI_OUT_OF_RESOURCES
;
3016 if (Private
->Current
!= NULL
) {
3017 IScsiConvertAttemptConfigDataToIfrNvData (Private
->Current
, IfrNvData
);
3021 // Extract all AttemptConfigData to Keyword storage of IfrNvData.
3023 IScsiConvertAttemptConfigDataToIfrNvDataByKeyword (IfrNvData
);
3025 BufferSize
= ISCSI_NAME_MAX_SIZE
;
3026 InitiatorName
= (CHAR8
*)AllocateZeroPool (BufferSize
);
3027 if (InitiatorName
== NULL
) {
3028 FreePool (IfrNvData
);
3029 return EFI_OUT_OF_RESOURCES
;
3032 Status
= gIScsiInitiatorName
.Get (&gIScsiInitiatorName
, &BufferSize
, InitiatorName
);
3033 if (EFI_ERROR (Status
)) {
3034 IfrNvData
->InitiatorName
[0] = L
'\0';
3036 AsciiStrToUnicodeStrS (
3038 IfrNvData
->InitiatorName
,
3039 sizeof (IfrNvData
->InitiatorName
) / sizeof (IfrNvData
->InitiatorName
[0])
3044 // Convert buffer data to <ConfigResp> by helper function BlockToConfig().
3046 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
3047 ConfigRequest
= Request
;
3048 if ((Request
== NULL
) || (StrStr (Request
, L
"OFFSET") == NULL
)) {
3050 // Request has no request element, construct full request string.
3051 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
3052 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
3054 ConfigRequestHdr
= HiiConstructConfigHdr (&gIScsiConfigGuid
, mVendorStorageName
, Private
->DriverHandle
);
3055 Size
= (StrLen (ConfigRequestHdr
) + 32 + 1) * sizeof (CHAR16
);
3056 ConfigRequest
= AllocateZeroPool (Size
);
3057 if (ConfigRequest
== NULL
) {
3058 FreePool (IfrNvData
);
3059 FreePool (InitiatorName
);
3060 return EFI_OUT_OF_RESOURCES
;
3063 AllocatedRequest
= TRUE
;
3064 UnicodeSPrint (ConfigRequest
, Size
, L
"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr
, (UINT64
)BufferSize
);
3065 FreePool (ConfigRequestHdr
);
3068 Status
= gHiiConfigRouting
->BlockToConfig (
3076 FreePool (IfrNvData
);
3077 FreePool (InitiatorName
);
3080 // Free the allocated config request string.
3082 if (AllocatedRequest
) {
3083 FreePool (ConfigRequest
);
3084 ConfigRequest
= NULL
;
3088 // Set Progress string to the original request string.
3090 if (Request
== NULL
) {
3092 } else if (StrStr (Request
, L
"OFFSET") == NULL
) {
3093 *Progress
= Request
+ StrLen (Request
);
3101 This function applies changes in a driver's configuration.
3102 Input is a Configuration, which has the routing data for this
3103 driver followed by name / value configuration pairs. The driver
3104 must apply those pairs to its configurable storage. If the
3105 driver's configuration is stored in a linear block of data
3106 and the driver's name / value pairs are in <BlockConfig>
3107 format, it may use the ConfigToBlock helper function (above) to
3110 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
3112 @param[in] Configuration A null-terminated Unicode string in
3113 <ConfigString> format.
3115 @param[out] Progress A pointer to a string filled in with the
3116 offset of the most recent '&' before the
3117 first failing name / value pair (or the
3118 beginning of the string if the failure
3119 is in the first name / value pair) or
3120 the terminating NULL if all was
3123 @retval EFI_SUCCESS The results have been distributed or are
3124 awaiting distribution.
3126 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
3127 parts of the results that must be
3128 stored awaiting possible future
3131 @retval EFI_INVALID_PARAMETERS Passing in a NULL for the
3132 Results parameter would result
3133 in this type of error.
3135 @retval EFI_NOT_FOUND Target for the specified routing data
3141 IScsiFormRouteConfig (
3142 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
3143 IN CONST EFI_STRING Configuration
,
3144 OUT EFI_STRING
*Progress
3148 ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
;
3149 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
3151 LIST_ENTRY
*NextEntry
;
3152 ISCSI_NIC_INFO
*NicInfo
;
3154 CHAR16 MacString
[ISCSI_MAX_MAC_STRING_LEN
];
3155 CHAR8
*InitiatorName
;
3166 Status
= EFI_SUCCESS
;
3168 if ((This
== NULL
) || (Configuration
== NULL
) || (Progress
== NULL
)) {
3169 return EFI_INVALID_PARAMETER
;
3173 // Check routing data in <ConfigHdr>.
3174 // Note: if only one Storage is used, then this checking could be skipped.
3176 if (!HiiIsConfigHdrMatch (Configuration
, &gIScsiConfigGuid
, mVendorStorageName
)) {
3177 *Progress
= Configuration
;
3178 return EFI_NOT_FOUND
;
3181 IfrNvData
= AllocateZeroPool (sizeof (ISCSI_CONFIG_IFR_NVDATA
));
3182 if (IfrNvData
== NULL
) {
3183 return EFI_OUT_OF_RESOURCES
;
3186 BufferSize
= ISCSI_NAME_MAX_SIZE
;
3187 InitiatorName
= (CHAR8
*)AllocateZeroPool (BufferSize
);
3188 if (InitiatorName
== NULL
) {
3189 Status
= EFI_OUT_OF_RESOURCES
;
3194 // Convert <ConfigResp> to buffer data by helper function ConfigToBlock().
3196 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
3197 Status
= gHiiConfigRouting
->ConfigToBlock (
3204 if (EFI_ERROR (Status
)) {
3208 if (IfrNvData
->InitiatorName
[0] != L
'\0') {
3209 UnicodeStrToAsciiStrS (IfrNvData
->InitiatorName
, InitiatorName
, ISCSI_NAME_MAX_SIZE
);
3210 BufferSize
= AsciiStrSize (InitiatorName
);
3212 Status
= gIScsiInitiatorName
.Set (&gIScsiInitiatorName
, &BufferSize
, InitiatorName
);
3213 if (EFI_ERROR (Status
)) {
3215 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3217 L
"Invalid iSCSI Name!",
3223 Status
= IScsiGetValue (Configuration
, L
"&OFFSET=", &OffSet
);
3224 if (EFI_ERROR (Status
)) {
3228 if (OffSet
>= ATTEMPT_MAC_ADDR_VAR_OFFSET
) {
3229 Status
= gIScsiInitiatorName
.Get (&gIScsiInitiatorName
, &BufferSize
, InitiatorName
);
3230 if (EFI_ERROR (Status
)) {
3232 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3234 L
"Error: please configure iSCSI initiator name first!",
3243 if (IfrNvData
->ISCSIAddAttemptList
[0] != L
'\0') {
3244 Status
= IScsiGetAttemptIndexList (IfrNvData
->ISCSIAddAttemptList
, IfrNvData
->AddAttemptList
, TRUE
);
3245 if (EFI_ERROR (Status
)) {
3247 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3249 L
"Error: The add attempt list is invalid",
3255 Status
= IScsiConfigAddAttemptsByKeywords (IfrNvData
->AddAttemptList
);
3256 if (EFI_ERROR (Status
)) {
3259 } else if (IfrNvData
->ISCSIDeleteAttemptList
[0] != L
'\0') {
3260 AttemptList
= (UINT8
*)AllocateZeroPool ((ISCSI_MAX_ATTEMPTS_NUM
+ 1) * sizeof (UINT8
));
3261 if (AttemptList
== NULL
) {
3262 Status
= EFI_OUT_OF_RESOURCES
;
3266 Status
= IScsiGetAttemptIndexList (IfrNvData
->ISCSIDeleteAttemptList
, AttemptList
, FALSE
);
3267 if (EFI_ERROR (Status
)) {
3269 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3271 L
"Error: The delete attempt list is invalid",
3278 // Mark the attempt which will be delete in the global list.
3280 NET_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &mPrivate
->AttemptConfigs
) {
3281 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
3282 while (AttemptList
[Index
] != 0) {
3283 if (AttemptConfigData
->AttemptConfigIndex
== AttemptList
[Index
]) {
3284 IfrNvData
->DeleteAttemptList
[Index2
] = 1;
3295 Status
= IScsiConfigDeleteAttempts (IfrNvData
);
3296 if (EFI_ERROR (Status
)) {
3300 FreePool (AttemptList
);
3301 } else if (IfrNvData
->ISCSIAttemptOrder
[0] != L
'\0') {
3302 Status
= IScsiGetAttemptIndexList (IfrNvData
->ISCSIAttemptOrder
, IfrNvData
->DynamicOrderedList
, FALSE
);
3303 if (EFI_ERROR (Status
)) {
3305 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3307 L
"Error: The new attempt order list is invalid",
3313 Status
= IScsiConfigOrderAttempts (IfrNvData
);
3314 if (EFI_ERROR (Status
)) {
3317 } else if (IfrNvData
->ISCSIMacAddr
[0] != L
'\0') {
3318 NET_LIST_FOR_EACH (Entry
, &mPrivate
->NicInfoList
) {
3319 NicInfo
= NET_LIST_USER_STRUCT (Entry
, ISCSI_NIC_INFO
, Link
);
3321 &NicInfo
->PermanentAddress
,
3322 NicInfo
->HwAddressSize
,
3326 if (!StrCmp (MacString
, IfrNvData
->ISCSIMacAddr
)) {
3327 mPrivate
->CurrentNic
= NicInfo
->NicIndex
;
3332 if ((NicInfo
== NULL
) || (NicInfo
->NicIndex
== 0)) {
3333 Status
= EFI_NOT_FOUND
;
3337 Status
= IScsiConvertlfrNvDataToAttemptConfigDataByKeyword (IfrNvData
, OffSet
);
3338 if (EFI_ERROR (Status
)) {
3344 IScsiConfigUpdateAttempt ();
3347 if (InitiatorName
!= NULL
) {
3348 FreePool (InitiatorName
);
3351 if (IfrNvData
!= NULL
) {
3352 FreePool (IfrNvData
);
3360 This function is called to provide results data to the driver.
3361 This data consists of a unique key that is used to identify
3362 which data is either being passed back or being asked for.
3364 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
3365 @param[in] Action Specifies the type of action taken by the browser.
3366 @param[in] QuestionId A unique value which is sent to the original
3367 exporting driver so that it can identify the type
3368 of data to expect. The format of the data tends to
3369 vary based on the opcode that generated the callback.
3370 @param[in] Type The type of value for the question.
3371 @param[in, out] Value A pointer to the data being sent to the original
3373 @param[out] ActionRequest On return, points to the action requested by the
3376 @retval EFI_SUCCESS The callback successfully handled the action.
3377 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
3378 variable and its data.
3379 @retval EFI_DEVICE_ERROR The variable could not be saved.
3380 @retval EFI_UNSUPPORTED The specified Action is not supported by the
3386 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
3387 IN EFI_BROWSER_ACTION Action
,
3388 IN EFI_QUESTION_ID QuestionId
,
3390 IN OUT EFI_IFR_TYPE_VALUE
*Value
,
3391 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
3394 ISCSI_FORM_CALLBACK_INFO
*Private
;
3397 CHAR8 IpString
[ISCSI_NAME_MAX_SIZE
];
3398 CHAR8 LunString
[ISCSI_LUN_STR_MAX_LEN
];
3400 EFI_IP_ADDRESS HostIp
;
3401 EFI_IP_ADDRESS SubnetMask
;
3402 EFI_IP_ADDRESS Gateway
;
3403 ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
;
3404 ISCSI_CONFIG_IFR_NVDATA OldIfrNvData
;
3407 ISCSI_NIC_INFO
*NicInfo
;
3411 if ((Action
== EFI_BROWSER_ACTION_FORM_OPEN
) || (Action
== EFI_BROWSER_ACTION_FORM_CLOSE
)) {
3413 // Do nothing for UEFI OPEN/CLOSE Action
3418 if ((Action
!= EFI_BROWSER_ACTION_CHANGING
) && (Action
!= EFI_BROWSER_ACTION_CHANGED
)) {
3420 // All other type return unsupported.
3422 return EFI_UNSUPPORTED
;
3425 if ((Value
== NULL
) || (ActionRequest
== NULL
)) {
3426 return EFI_INVALID_PARAMETER
;
3429 Private
= ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This
);
3432 // Retrieve uncommitted data from Browser
3435 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
3436 IfrNvData
= AllocateZeroPool (BufferSize
);
3437 if (IfrNvData
== NULL
) {
3438 return EFI_OUT_OF_RESOURCES
;
3441 IScsiName
= (CHAR8
*)AllocateZeroPool (ISCSI_NAME_MAX_SIZE
);
3442 if (IScsiName
== NULL
) {
3443 FreePool (IfrNvData
);
3444 return EFI_OUT_OF_RESOURCES
;
3447 Status
= EFI_SUCCESS
;
3449 ZeroMem (&OldIfrNvData
, BufferSize
);
3451 HiiGetBrowserData (NULL
, NULL
, BufferSize
, (UINT8
*)IfrNvData
);
3453 CopyMem (&OldIfrNvData
, IfrNvData
, BufferSize
);
3455 if (Action
== EFI_BROWSER_ACTION_CHANGING
) {
3456 switch (QuestionId
) {
3457 case KEY_ADD_ATTEMPT
:
3459 // Check whether iSCSI initiator name is configured already.
3461 mPrivate
->InitiatorNameLength
= ISCSI_NAME_MAX_SIZE
;
3462 Status
= gIScsiInitiatorName
.Get (
3463 &gIScsiInitiatorName
,
3464 &mPrivate
->InitiatorNameLength
,
3465 mPrivate
->InitiatorName
3467 if (EFI_ERROR (Status
)) {
3469 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3471 L
"Error: please configure iSCSI initiator name first!",
3477 Status
= IScsiConfigAddAttempt ();
3480 case KEY_DELETE_ATTEMPT
:
3482 OldIfrNvData
.DeleteAttemptList
,
3483 IfrNvData
->DeleteAttemptList
,
3484 sizeof (IfrNvData
->DeleteAttemptList
)
3486 Status
= IScsiConfigDisplayDeleteAttempts (IfrNvData
);
3489 case KEY_ORDER_ATTEMPT_CONFIG
:
3491 // Order the attempt according to user input.
3494 OldIfrNvData
.DynamicOrderedList
,
3495 IfrNvData
->DynamicOrderedList
,
3496 sizeof (IfrNvData
->DynamicOrderedList
)
3498 IScsiConfigDisplayOrderAttempts ();
3502 Status
= IScsiConfigProcessDefault (QuestionId
, IfrNvData
);
3505 } else if (Action
== EFI_BROWSER_ACTION_CHANGED
) {
3506 switch (QuestionId
) {
3507 case KEY_INITIATOR_NAME
:
3508 UnicodeStrToAsciiStrS (IfrNvData
->InitiatorName
, IScsiName
, ISCSI_NAME_MAX_SIZE
);
3509 BufferSize
= AsciiStrSize (IScsiName
);
3511 Status
= gIScsiInitiatorName
.Set (&gIScsiInitiatorName
, &BufferSize
, IScsiName
);
3512 if (EFI_ERROR (Status
)) {
3514 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3516 L
"Invalid iSCSI Name!",
3521 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
3524 case KEY_SAVE_ATTEMPT_CONFIG
:
3525 Status
= IScsiConvertIfrNvDataToAttemptConfigData (IfrNvData
, Private
->Current
);
3526 if (EFI_ERROR (Status
)) {
3530 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT
;
3533 case KEY_SAVE_ORDER_CHANGES
:
3535 // Sync the Attempt Order to NVR.
3537 Status
= IScsiConfigOrderAttempts (IfrNvData
);
3538 if (EFI_ERROR (Status
)) {
3542 IScsiConfigUpdateAttempt ();
3543 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT
;
3546 case KEY_IGNORE_ORDER_CHANGES
:
3548 IfrNvData
->DynamicOrderedList
,
3549 OldIfrNvData
.DynamicOrderedList
,
3550 sizeof (IfrNvData
->DynamicOrderedList
)
3552 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT
;
3555 case KEY_SAVE_DELETE_ATTEMPT
:
3557 // Delete the Attempt Order from NVR
3559 Status
= IScsiConfigDeleteAttempts (IfrNvData
);
3560 if (EFI_ERROR (Status
)) {
3564 IScsiConfigUpdateAttempt ();
3565 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT
;
3568 case KEY_IGNORE_DELETE_ATTEMPT
:
3570 IfrNvData
->DeleteAttemptList
,
3571 OldIfrNvData
.DeleteAttemptList
,
3572 sizeof (IfrNvData
->DeleteAttemptList
)
3574 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT
;
3578 switch (Value
->u8
) {
3580 NicInfo
= IScsiGetNicInfoByIndex (Private
->Current
->NicIndex
);
3581 if (NicInfo
== NULL
) {
3585 if (!NicInfo
->Ipv6Available
) {
3587 // Current NIC doesn't Support IPv6, hence use IPv4.
3589 IfrNvData
->IpMode
= IP_MODE_IP4
;
3592 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3594 L
"Current NIC doesn't Support IPv6!",
3600 ZeroMem (IfrNvData
->LocalIp
, sizeof (IfrNvData
->LocalIp
));
3601 ZeroMem (IfrNvData
->SubnetMask
, sizeof (IfrNvData
->SubnetMask
));
3602 ZeroMem (IfrNvData
->Gateway
, sizeof (IfrNvData
->Gateway
));
3603 ZeroMem (IfrNvData
->TargetIp
, sizeof (IfrNvData
->TargetIp
));
3604 Private
->Current
->AutoConfigureMode
= 0;
3605 ZeroMem (&Private
->Current
->SessionConfigData
.LocalIp
, sizeof (EFI_IP_ADDRESS
));
3606 ZeroMem (&Private
->Current
->SessionConfigData
.SubnetMask
, sizeof (EFI_IPv4_ADDRESS
));
3607 ZeroMem (&Private
->Current
->SessionConfigData
.Gateway
, sizeof (EFI_IP_ADDRESS
));
3608 ZeroMem (&Private
->Current
->SessionConfigData
.TargetIp
, sizeof (EFI_IP_ADDRESS
));
3616 Status
= NetLibStrToIp4 (IfrNvData
->LocalIp
, &HostIp
.v4
);
3617 if (EFI_ERROR (Status
) ||
3618 ((Private
->Current
->SessionConfigData
.SubnetMask
.Addr
[0] != 0) &&
3619 !NetIp4IsUnicast (NTOHL (HostIp
.Addr
[0]), NTOHL (*(UINT32
*)Private
->Current
->SessionConfigData
.SubnetMask
.Addr
))))
3622 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3624 L
"Invalid IP address!",
3628 Status
= EFI_INVALID_PARAMETER
;
3630 CopyMem (&Private
->Current
->SessionConfigData
.LocalIp
, &HostIp
.v4
, sizeof (HostIp
.v4
));
3635 case KEY_SUBNET_MASK
:
3636 Status
= NetLibStrToIp4 (IfrNvData
->SubnetMask
, &SubnetMask
.v4
);
3637 if (EFI_ERROR (Status
) || ((SubnetMask
.Addr
[0] != 0) && (IScsiGetSubnetMaskPrefixLength (&SubnetMask
.v4
) == 0))) {
3639 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3641 L
"Invalid Subnet Mask!",
3645 Status
= EFI_INVALID_PARAMETER
;
3647 CopyMem (&Private
->Current
->SessionConfigData
.SubnetMask
, &SubnetMask
.v4
, sizeof (SubnetMask
.v4
));
3653 Status
= NetLibStrToIp4 (IfrNvData
->Gateway
, &Gateway
.v4
);
3654 if (EFI_ERROR (Status
) ||
3655 ((Gateway
.Addr
[0] != 0) &&
3656 (Private
->Current
->SessionConfigData
.SubnetMask
.Addr
[0] != 0) &&
3657 !NetIp4IsUnicast (NTOHL (Gateway
.Addr
[0]), NTOHL (*(UINT32
*)Private
->Current
->SessionConfigData
.SubnetMask
.Addr
))))
3660 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3662 L
"Invalid Gateway!",
3665 Status
= EFI_INVALID_PARAMETER
;
3667 CopyMem (&Private
->Current
->SessionConfigData
.Gateway
, &Gateway
.v4
, sizeof (Gateway
.v4
));
3673 UnicodeStrToAsciiStrS (IfrNvData
->TargetIp
, IpString
, sizeof (IpString
));
3674 Status
= IScsiAsciiStrToIp (IpString
, IfrNvData
->IpMode
, &HostIp
);
3675 if (EFI_ERROR (Status
) || !IpIsUnicast (&HostIp
, IfrNvData
->IpMode
)) {
3677 // The target is expressed in URL format or an invalid Ip address, just save.
3679 Private
->Current
->SessionConfigData
.DnsMode
= TRUE
;
3680 ZeroMem (&Private
->Current
->SessionConfigData
.TargetIp
, sizeof (Private
->Current
->SessionConfigData
.TargetIp
));
3681 UnicodeStrToAsciiStrS (IfrNvData
->TargetIp
, Private
->Current
->SessionConfigData
.TargetUrl
, ISCSI_NAME_MAX_SIZE
);
3683 Private
->Current
->SessionConfigData
.DnsMode
= FALSE
;
3684 CopyMem (&Private
->Current
->SessionConfigData
.TargetIp
, &HostIp
, sizeof (HostIp
));
3689 case KEY_TARGET_NAME
:
3690 UnicodeStrToAsciiStrS (IfrNvData
->TargetName
, IScsiName
, ISCSI_NAME_MAX_SIZE
);
3691 Status
= IScsiNormalizeName (IScsiName
, AsciiStrLen (IScsiName
));
3692 if (EFI_ERROR (Status
)) {
3694 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3696 L
"Invalid iSCSI Name!",
3700 AsciiStrCpyS (Private
->Current
->SessionConfigData
.TargetName
, ISCSI_NAME_MAX_SIZE
, IScsiName
);
3705 case KEY_DHCP_ENABLE
:
3706 if (IfrNvData
->InitiatorInfoFromDhcp
== 0) {
3707 IfrNvData
->TargetInfoFromDhcp
= 0;
3713 UnicodeStrToAsciiStrS (IfrNvData
->BootLun
, LunString
, sizeof (LunString
));
3714 Status
= IScsiAsciiStrToLun (LunString
, (UINT8
*)&Lun
);
3715 if (EFI_ERROR (Status
)) {
3717 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
3719 L
"Invalid LUN string!",
3723 CopyMem (Private
->Current
->SessionConfigData
.BootLun
, &Lun
, sizeof (Lun
));
3729 switch (Value
->u8
) {
3730 case ISCSI_AUTH_TYPE_CHAP
:
3731 IfrNvData
->CHAPType
= ISCSI_CHAP_UNI
;
3740 UnicodeStrToAsciiStrS (
3741 IfrNvData
->CHAPName
,
3742 Private
->Current
->AuthConfigData
.CHAP
.CHAPName
,
3743 sizeof (Private
->Current
->AuthConfigData
.CHAP
.CHAPName
)
3747 case KEY_CHAP_SECRET
:
3748 UnicodeStrToAsciiStrS (
3749 IfrNvData
->CHAPSecret
,
3750 Private
->Current
->AuthConfigData
.CHAP
.CHAPSecret
,
3751 sizeof (Private
->Current
->AuthConfigData
.CHAP
.CHAPSecret
)
3755 case KEY_REVERSE_CHAP_NAME
:
3756 UnicodeStrToAsciiStrS (
3757 IfrNvData
->ReverseCHAPName
,
3758 Private
->Current
->AuthConfigData
.CHAP
.ReverseCHAPName
,
3759 sizeof (Private
->Current
->AuthConfigData
.CHAP
.ReverseCHAPName
)
3763 case KEY_REVERSE_CHAP_SECRET
:
3764 UnicodeStrToAsciiStrS (
3765 IfrNvData
->ReverseCHAPSecret
,
3766 Private
->Current
->AuthConfigData
.CHAP
.ReverseCHAPSecret
,
3767 sizeof (Private
->Current
->AuthConfigData
.CHAP
.ReverseCHAPSecret
)
3771 case KEY_CONFIG_ISID
:
3772 IScsiParseIsIdFromString (IfrNvData
->IsId
, Private
->Current
->SessionConfigData
.IsId
);
3773 IScsiConvertIsIdToString (IfrNvData
->IsId
, Private
->Current
->SessionConfigData
.IsId
);
3782 if (!EFI_ERROR (Status
)) {
3784 // Pass changed uncommitted data back to Form Browser.
3786 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
3787 HiiSetBrowserData (NULL
, NULL
, BufferSize
, (UINT8
*)IfrNvData
, NULL
);
3790 FreePool (IfrNvData
);
3791 FreePool (IScsiName
);
3797 Initialize the iSCSI configuration form.
3799 @param[in] DriverBindingHandle The iSCSI driverbinding handle.
3801 @retval EFI_SUCCESS The iSCSI configuration form is initialized.
3802 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
3806 IScsiConfigFormInit (
3807 IN EFI_HANDLE DriverBindingHandle
3811 ISCSI_FORM_CALLBACK_INFO
*CallbackInfo
;
3813 CallbackInfo
= (ISCSI_FORM_CALLBACK_INFO
*)AllocateZeroPool (sizeof (ISCSI_FORM_CALLBACK_INFO
));
3814 if (CallbackInfo
== NULL
) {
3815 return EFI_OUT_OF_RESOURCES
;
3818 CallbackInfo
->Signature
= ISCSI_FORM_CALLBACK_INFO_SIGNATURE
;
3819 CallbackInfo
->Current
= NULL
;
3821 CallbackInfo
->ConfigAccess
.ExtractConfig
= IScsiFormExtractConfig
;
3822 CallbackInfo
->ConfigAccess
.RouteConfig
= IScsiFormRouteConfig
;
3823 CallbackInfo
->ConfigAccess
.Callback
= IScsiFormCallback
;
3826 // Install Device Path Protocol and Config Access protocol to driver handle.
3828 Status
= gBS
->InstallMultipleProtocolInterfaces (
3829 &CallbackInfo
->DriverHandle
,
3830 &gEfiDevicePathProtocolGuid
,
3831 &mIScsiHiiVendorDevicePath
,
3832 &gEfiHiiConfigAccessProtocolGuid
,
3833 &CallbackInfo
->ConfigAccess
,
3836 ASSERT_EFI_ERROR (Status
);
3839 // Publish our HII data.
3841 CallbackInfo
->RegisteredHandle
= HiiAddPackages (
3843 CallbackInfo
->DriverHandle
,
3848 if (CallbackInfo
->RegisteredHandle
== NULL
) {
3849 gBS
->UninstallMultipleProtocolInterfaces (
3850 CallbackInfo
->DriverHandle
,
3851 &gEfiDevicePathProtocolGuid
,
3852 &mIScsiHiiVendorDevicePath
,
3853 &gEfiHiiConfigAccessProtocolGuid
,
3854 &CallbackInfo
->ConfigAccess
,
3857 FreePool (CallbackInfo
);
3858 return EFI_OUT_OF_RESOURCES
;
3861 mCallbackInfo
= CallbackInfo
;
3867 Unload the iSCSI configuration form, this includes: delete all the iSCSI
3868 configuration entries, uninstall the form callback protocol, and
3869 free the resources used.
3871 @param[in] DriverBindingHandle The iSCSI driverbinding handle.
3873 @retval EFI_SUCCESS The iSCSI configuration form is unloaded.
3874 @retval Others Failed to unload the form.
3878 IScsiConfigFormUnload (
3879 IN EFI_HANDLE DriverBindingHandle
3882 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
3883 ISCSI_NIC_INFO
*NicInfo
;
3887 while (!IsListEmpty (&mPrivate
->AttemptConfigs
)) {
3888 Entry
= NetListRemoveHead (&mPrivate
->AttemptConfigs
);
3889 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
3890 FreePool (AttemptConfigData
);
3891 mPrivate
->AttemptCount
--;
3894 ASSERT (mPrivate
->AttemptCount
== 0);
3896 while (!IsListEmpty (&mPrivate
->NicInfoList
)) {
3897 Entry
= NetListRemoveHead (&mPrivate
->NicInfoList
);
3898 NicInfo
= NET_LIST_USER_STRUCT (Entry
, ISCSI_NIC_INFO
, Link
);
3900 mPrivate
->NicCount
--;
3903 ASSERT (mPrivate
->NicCount
== 0);
3905 FreePool (mPrivate
);
3909 // Remove HII package list.
3911 HiiRemovePackages (mCallbackInfo
->RegisteredHandle
);
3914 // Uninstall Device Path Protocol and Config Access protocol.
3916 Status
= gBS
->UninstallMultipleProtocolInterfaces (
3917 mCallbackInfo
->DriverHandle
,
3918 &gEfiDevicePathProtocolGuid
,
3919 &mIScsiHiiVendorDevicePath
,
3920 &gEfiHiiConfigAccessProtocolGuid
,
3921 &mCallbackInfo
->ConfigAccess
,
3925 FreePool (mCallbackInfo
);